# HG changeset patch # User Jaroslav Hajek # Date 1209540634 14400 # Node ID 39930366b7098845df918a1a49facd1dd3ac5a62 # Parent ca9bfe159144bce7a6e9bbe0bd4c5b9ea4d281ac implement builtin log2 diff --git a/liboctave/ChangeLog b/liboctave/ChangeLog --- a/liboctave/ChangeLog +++ b/liboctave/ChangeLog @@ -1,3 +1,10 @@ +2008-04-30 Jaroslav Hajek + + * lo-mappers.cc (xlog2 (double)): Compute log (2), not log2 (2). + (xlog2 (Complex), xlog2 (double, int&), xlog2 (Complex, int&)): + New functions. + * lo-mappers.h: Provide decls. + 2008-04-25 Michael Goffioul * oct-lookup.h (seq_lookup): Do not use output value of fill_n (MSVC diff --git a/liboctave/lo-mappers.cc b/liboctave/lo-mappers.cc --- a/liboctave/lo-mappers.cc +++ b/liboctave/lo-mappers.cc @@ -139,13 +139,25 @@ #if defined (M_LN2) static double ln2 = M_LN2; #else - static double ln2 = log2 (2); + static double ln2 = log (2); #endif return log (x) / ln2; #endif } +Complex +xlog2 (const Complex& x) +{ +#if defined (M_LN2) + static double ln2 = M_LN2; +#else + static double ln2 = log (2); +#endif + + return std::log (x) / ln2; +} + double xexp2 (double x) { @@ -155,13 +167,27 @@ #if defined (M_LN2) static double ln2 = M_LN2; #else - static double ln2 = log2 (2); + static double ln2 = log (2); #endif return exp (x * ln2); #endif } +double +xlog2 (double x, int& exp) +{ + return frexp (x, &exp); +} + +Complex +xlog2 (const Complex& x, int& exp) +{ + double ax = std::abs (x); + double lax = xlog2 (ax, exp); + return (exp == 0) ? x : (x / ax) * lax; +} + // double -> bool mappers. bool diff --git a/liboctave/lo-mappers.h b/liboctave/lo-mappers.h --- a/liboctave/lo-mappers.h +++ b/liboctave/lo-mappers.h @@ -36,6 +36,9 @@ extern OCTAVE_API double signum (double x); extern OCTAVE_API double xtrunc (double x); extern OCTAVE_API double xlog2 (double x); +extern OCTAVE_API Complex xlog2 (const Complex& x); +extern OCTAVE_API double xlog2 (double x, int& exp); +extern OCTAVE_API Complex xlog2 (const Complex& x, int& exp); extern OCTAVE_API double xexp2 (double x); extern OCTAVE_API bool xisnan (double x); diff --git a/scripts/ChangeLog b/scripts/ChangeLog --- a/scripts/ChangeLog +++ b/scripts/ChangeLog @@ -1,3 +1,8 @@ +2008-04-30 Jaroslav Hajek + + * specfun/log2.m: Delete. + * specfun/Makefile.in (SOURCES): Delete it from the list. + 2008-04-29 David Bateman pkg/pkg.m: Also set archprefix with the -local and -global options. diff --git a/scripts/specfun/Makefile.in b/scripts/specfun/Makefile.in --- a/scripts/specfun/Makefile.in +++ b/scripts/specfun/Makefile.in @@ -34,7 +34,7 @@ INSTALL_DATA = @INSTALL_DATA@ SOURCES = bessel.m beta.m betai.m betaln.m erfinv.m factor.m \ - factorial.m gammai.m isprime.m legendre.m log2.m nchoosek.m \ + factorial.m gammai.m isprime.m legendre.m nchoosek.m \ perms.m pow2.m primes.m reallog.m realpow.m realsqrt.m DISTFILES = $(addprefix $(srcdir)/, Makefile.in $(SOURCES)) diff --git a/scripts/specfun/log2.m b/scripts/specfun/log2.m deleted file mode 100644 --- a/scripts/specfun/log2.m +++ /dev/null @@ -1,73 +0,0 @@ -## Copyright (C) 1995, 1996, 1999, 2000, 2002, 2004, 2005, 2006, 2007 -## Kurt Hornik -## -## This file is part of Octave. -## -## Octave is free software; you can redistribute it and/or modify it -## under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 3 of the License, or (at -## your option) any later version. -## -## Octave is distributed in the hope that it will be useful, but -## WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -## General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with Octave; see the file COPYING. If not, see -## . - -## -*- texinfo -*- -## @deftypefn {Mapping Function} {} log2 (@var{x}) -## @deftypefnx {Mapping Function} {[@var{f}, @var{e}] =} log2 (@var{x}) -## Compute the base-2 logarithm of @var{x}. With two outputs, returns -## @var{f} and @var{e} such that -## @iftex -## @tex -## $1/2 <= |f| < 1$ and $x = f \cdot 2^e$. -## @end tex -## @end iftex -## @ifinfo -## 1/2 <= abs(f) < 1 and x = f * 2^e. -## @end ifinfo -## @seealso{log, log10, logspace, exp} -## @end deftypefn - -## Author: AW -## Created: 17 October 1994 -## Adapted-By: jwe - -function [f, e] = log2 (x) - - if (nargin != 1) - print_usage (); - endif - - if (nargout < 2) - f = log (x) / log (2); - elseif (nargout == 2) - ## Only deal with the real parts ... - x = real (x); - ## Since log (0) gives problems, 0 entries are replaced by 1. - ## This is corrected later by multiplication with the sign. - f = abs (x) + (x == 0); - e = (floor (log (f) / log (2)) + 1) .* (x != 0); - f = sign (x) .* f ./ (2 .^ e); - ## Workaround to cases of f == 1 (due to precision issues). - idx = abs (f) >= 1; - if (any (idx)) - f(idx) /= 2; - e(idx)++; - endif - else - error ("log2 takes at most 2 output arguments"); - endif - -endfunction - -%!assert(all (abs (log2 ([1/4, 1/2, 1, 2, 4]) - [-2, -1, 0, 1, 2]) < sqrt (eps))); - -%!error log2 (); - -%!error log2 (1, 2); - diff --git a/src/ChangeLog b/src/ChangeLog --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,17 @@ +2008-04-30 John W. Eaton + + * ov-fcn-handle.cc: Create handle pointing to flops instead of log2. + +2008-04-30 Jaroslav Hajek + + * ov-base.cc, ov-base.h, ov-bool-mat.h, ov-bool-sparse.h, + ov-bool.h, ov-complex.cc, ov-complex.h, ov-cx-mat.cc, ov-cx-mat.h, + ov-cx-sparse.cc, ov-cx-sparse.h, ov-intx.h, ov-range.h, + ov-re-mat.cc, ov-re-mat.h, ov-re-sparse.cc, ov-re-sparse.h, + ov-scalar.cc, ov-scalar.h, ov.h: + Provide log2 mapper function. + * data.cc (Flog2): New function. + 2008-04-25 John W. Eaton * pt-stmt.h (tree_statement_list::function_body): New data member. diff --git a/src/data.cc b/src/data.cc --- a/src/data.cc +++ b/src/data.cc @@ -686,6 +686,82 @@ %! assert (hypot (1:10,1:10), sqrt(2) * [1:10]); */ +template +void +map_2_xlog2 (const Array& x, Array& f, Array& e) +{ + f = Array(x.dims ()); + e = Array(x.dims ()); + for (octave_idx_type i = 0; i < x.numel (); i++) + { + int exp; + f.xelem (i) = xlog2 (x(i), exp); + e.xelem (i) = exp; + } +} + +DEFUN (log2, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Mapping Function} {} log2 (@var{x})\n\ +@deftypefnx {Mapping Function} {[@var{f}, @var{e}] = } log2 (@var{x})\n\ +Compute the base-2 logarithm for each element of @var{x}.\n\ +If called with two output arguments, split @var{x} to\n\ +binary mantissa and exponent so that @code{1/2 <= abs(f) < 1} and\n\ +@var{e} is an integer. If @code{x = 0}, @code{f = e = 0}.\n\ +@seealso{log, log10, log2, exp}\n\ +@end deftypefn") +{ + octave_value_list retval; + + if (args.length () == 1) + { + if (nargout < 2) + retval(0) = args(0).log2 (); + else if (args(0).is_real_type ()) + { + NDArray f; + NDArray x = args(0).array_value (); + // FIXME -- should E be an int value? + Matrix e; + map_2_xlog2 (x, f, e); + retval (1) = e; + retval (0) = f; + } + else if (args(0).is_complex_type ()) + { + ComplexNDArray f; + ComplexNDArray x = args(0).complex_array_value (); + // FIXME -- should E be an int value? + NDArray e; + map_2_xlog2 (x, f, e); + retval (1) = e; + retval (0) = f; + } + else + gripe_wrong_type_arg ("log2", args(0)); + } + else + print_usage (); + + return retval; +} + +/* +%! assert(log2 ([1/4, 1/2, 1, 2, 4]), [-2, -1, 0, 1, 2]); +%! assert(log2(Inf), Inf); +%! assert(isnan(log2(NaN))); +%! assert(log2(4*i), 2 + log2(1*i)); +%! assert(log2(complex(0,Inf)), Inf + log2(i)); +%!test +%! [f, e] = log2 ([0,-1; 2,-4; Inf,-Inf]); +%! assert (f, [0,-0.5; 0.5,-0.5; Inf,-Inf]); +%! assert (e, [0,1;2,3;0,0]) +%!test +%! [f, e] = log2 (complex (zeros (3, 2), [0,-1; 2,-4; Inf,-Inf])); +%! assert (f, complex (zeros (3, 2), [0,-0.5; 0.5,-0.5; Inf,-Inf])); +%! assert (e, [0,1; 2,3; 0,0]); +*/ + DEFUN (fmod, args, , "-*- texinfo -*-\n\ @deftypefn {Mapping Function} {} fmod (@var{x}, @var{y})\n\ diff --git a/src/ov-base.cc b/src/ov-base.cc --- a/src/ov-base.cc +++ b/src/ov-base.cc @@ -960,6 +960,7 @@ UNDEFINED_MAPPER (isnan) UNDEFINED_MAPPER (lgamma) UNDEFINED_MAPPER (log) +UNDEFINED_MAPPER (log2) UNDEFINED_MAPPER (log10) UNDEFINED_MAPPER (log1p) UNDEFINED_MAPPER (real) diff --git a/src/ov-base.h b/src/ov-base.h --- a/src/ov-base.h +++ b/src/ov-base.h @@ -507,6 +507,7 @@ virtual octave_value isnan (void) const; virtual octave_value lgamma (void) const; virtual octave_value log (void) const; + virtual octave_value log2 (void) const; virtual octave_value log10 (void) const; virtual octave_value log1p (void) const; virtual octave_value real (void) const; diff --git a/src/ov-bool-mat.h b/src/ov-bool-mat.h --- a/src/ov-bool-mat.h +++ b/src/ov-bool-mat.h @@ -219,6 +219,7 @@ BOOL_MAT_MAPPER (isnan) BOOL_MAT_MAPPER (lgamma) BOOL_MAT_MAPPER (log) + BOOL_MAT_MAPPER (log2) BOOL_MAT_MAPPER (log10) BOOL_MAT_MAPPER (log1p) BOOL_MAT_MAPPER (real) diff --git a/src/ov-bool-sparse.h b/src/ov-bool-sparse.h --- a/src/ov-bool-sparse.h +++ b/src/ov-bool-sparse.h @@ -175,6 +175,7 @@ BOOL_SPARSE_MAPPER (isnan) BOOL_SPARSE_MAPPER (lgamma) BOOL_SPARSE_MAPPER (log) + BOOL_SPARSE_MAPPER (log2) BOOL_SPARSE_MAPPER (log10) BOOL_SPARSE_MAPPER (log1p) BOOL_SPARSE_MAPPER (real) diff --git a/src/ov-bool.h b/src/ov-bool.h --- a/src/ov-bool.h +++ b/src/ov-bool.h @@ -227,6 +227,7 @@ BOOL_MAPPER (isnan) BOOL_MAPPER (lgamma) BOOL_MAPPER (log) + BOOL_MAPPER (log2) BOOL_MAPPER (log10) BOOL_MAPPER (log1p) BOOL_MAPPER (real) diff --git a/src/ov-complex.cc b/src/ov-complex.cc --- a/src/ov-complex.cc +++ b/src/ov-complex.cc @@ -413,6 +413,7 @@ COMPLEX_MAPPER (floor, ::floor) COMPLEX_MAPPER (imag, ximag) COMPLEX_MAPPER (log, std::log) +COMPLEX_MAPPER (log2, xlog2) COMPLEX_MAPPER (log10, std::log10) COMPLEX_MAPPER (log1p, ::log1p) COMPLEX_MAPPER (real, xreal) diff --git a/src/ov-complex.h b/src/ov-complex.h --- a/src/ov-complex.h +++ b/src/ov-complex.h @@ -173,6 +173,7 @@ octave_value floor (void) const; octave_value imag (void) const; octave_value log (void) const; + octave_value log2 (void) const; octave_value log10 (void) const; octave_value log1p (void) const; octave_value real (void) const; diff --git a/src/ov-cx-mat.cc b/src/ov-cx-mat.cc --- a/src/ov-cx-mat.cc +++ b/src/ov-cx-mat.cc @@ -781,6 +781,7 @@ ARRAY_MAPPER (floor, ComplexNDArray::cmapper, ::floor) ARRAY_MAPPER (imag, ComplexNDArray::dmapper, ximag) ARRAY_MAPPER (log, ComplexNDArray::cmapper, std::log) +ARRAY_MAPPER (log2, ComplexNDArray::cmapper, xlog2) ARRAY_MAPPER (log10, ComplexNDArray::cmapper, std::log10) ARRAY_MAPPER (log1p, ComplexNDArray::cmapper, ::log1p) ARRAY_MAPPER (real, ComplexNDArray::dmapper, xreal) diff --git a/src/ov-cx-mat.h b/src/ov-cx-mat.h --- a/src/ov-cx-mat.h +++ b/src/ov-cx-mat.h @@ -176,6 +176,7 @@ octave_value floor (void) const; octave_value imag (void) const; octave_value log (void) const; + octave_value log2 (void) const; octave_value log10 (void) const; octave_value log1p (void) const; octave_value real (void) const; diff --git a/src/ov-cx-sparse.cc b/src/ov-cx-sparse.cc --- a/src/ov-cx-sparse.cc +++ b/src/ov-cx-sparse.cc @@ -954,6 +954,7 @@ SPARSE_MAPPER (floor, SparseComplexMatrix::cmapper, ::floor) SPARSE_MAPPER (imag, SparseComplexMatrix::dmapper, ximag) SPARSE_MAPPER (log, SparseComplexMatrix::cmapper, std::log) +SPARSE_MAPPER (log2, SparseComplexMatrix::cmapper, xlog2) SPARSE_MAPPER (log10, SparseComplexMatrix::cmapper, std::log10) SPARSE_MAPPER (log1p, SparseComplexMatrix::cmapper, ::log1p) SPARSE_MAPPER (real, SparseComplexMatrix::dmapper, xreal) diff --git a/src/ov-cx-sparse.h b/src/ov-cx-sparse.h --- a/src/ov-cx-sparse.h +++ b/src/ov-cx-sparse.h @@ -175,6 +175,7 @@ octave_value floor (void) const; octave_value imag (void) const; octave_value log (void) const; + octave_value log2 (void) const; octave_value log10 (void) const; octave_value log1p (void) const; octave_value real (void) const; diff --git a/src/ov-fcn-handle.cc b/src/ov-fcn-handle.cc --- a/src/ov-fcn-handle.cc +++ b/src/ov-fcn-handle.cc @@ -381,7 +381,7 @@ %! a = 2; %! f = @(x) a + x; %! g = @(x) 2 * x; -%! h = @log2; +%! h = @flops; %! f2 = f; %! g2 = g; %! h2 = h; @@ -578,7 +578,7 @@ %! a = 2; %! f = @(x) a + x; %! g = @(x) 2 * x; -%! h = @log2; +%! h = @flops; %! f2 = f; %! g2 = g; %! h2 = h; @@ -1119,7 +1119,7 @@ %! a = 2; %! f = @(x) a + x; %! g = @(x) 2 * x; -%! h = @log2; +%! h = @flops; %! f2 = f; %! g2 = g; %! h2 = h; diff --git a/src/ov-range.h b/src/ov-range.h --- a/src/ov-range.h +++ b/src/ov-range.h @@ -299,6 +299,7 @@ RANGE_MAPPER (isnan) RANGE_MAPPER (lgamma) RANGE_MAPPER (log) + RANGE_MAPPER (log2) RANGE_MAPPER (log10) RANGE_MAPPER (log1p) RANGE_MAPPER (real) diff --git a/src/ov-re-mat.cc b/src/ov-re-mat.cc --- a/src/ov-re-mat.cc +++ b/src/ov-re-mat.cc @@ -735,6 +735,7 @@ ARRAY_MAPPER (floor, NDArray::dmapper, ::floor) ARRAY_MAPPER (imag, NDArray::dmapper, ::imag) CD_ARRAY_MAPPER (log, ::log, std::log, 0.0, octave_Inf) +CD_ARRAY_MAPPER (log2, xlog2, xlog2, 0.0, octave_Inf) CD_ARRAY_MAPPER (log10, ::log10, std::log10, 0.0, octave_Inf) CD_ARRAY_MAPPER (log1p, ::log1p, ::log1p, -1.0, octave_Inf) ARRAY_MAPPER (real, NDArray::dmapper, ::real) diff --git a/src/ov-re-mat.h b/src/ov-re-mat.h --- a/src/ov-re-mat.h +++ b/src/ov-re-mat.h @@ -203,6 +203,7 @@ octave_value floor (void) const; octave_value imag (void) const; octave_value log (void) const; + octave_value log2 (void) const; octave_value log10 (void) const; octave_value log1p (void) const; octave_value real (void) const; diff --git a/src/ov-re-sparse.cc b/src/ov-re-sparse.cc --- a/src/ov-re-sparse.cc +++ b/src/ov-re-sparse.cc @@ -925,6 +925,7 @@ SPARSE_MAPPER (floor, SparseMatrix::dmapper, ::floor) SPARSE_MAPPER (imag, SparseMatrix::dmapper, ::imag) CD_SPARSE_MAPPER (log, ::log, std::log, 0.0, octave_Inf) +CD_SPARSE_MAPPER (log2, xlog2, xlog2, 0.0, octave_Inf) CD_SPARSE_MAPPER (log10, ::log10, std::log10, 0.0, octave_Inf) CD_SPARSE_MAPPER (log1p, ::log1p, ::log1p, 0.0, octave_Inf) SPARSE_MAPPER (real, SparseMatrix::dmapper, ::real) diff --git a/src/ov-re-sparse.h b/src/ov-re-sparse.h --- a/src/ov-re-sparse.h +++ b/src/ov-re-sparse.h @@ -176,6 +176,7 @@ octave_value floor (void) const; octave_value imag (void) const; octave_value log (void) const; + octave_value log2 (void) const; octave_value log10 (void) const; octave_value log1p (void) const; octave_value real (void) const; diff --git a/src/ov-scalar.cc b/src/ov-scalar.cc --- a/src/ov-scalar.cc +++ b/src/ov-scalar.cc @@ -330,6 +330,7 @@ SCALAR_MAPPER (floor, ::floor) SCALAR_MAPPER (imag, ::imag) CD_SCALAR_MAPPER (log, ::log, std::log, 0.0, octave_Inf) +CD_SCALAR_MAPPER (log2, xlog2, xlog2, 0.0, octave_Inf) CD_SCALAR_MAPPER (log10, ::log10, std::log10, 0.0, octave_Inf) CD_SCALAR_MAPPER (log1p, ::log1p, ::log1p, -1.0, octave_Inf) SCALAR_MAPPER (real, ::real) diff --git a/src/ov-scalar.h b/src/ov-scalar.h --- a/src/ov-scalar.h +++ b/src/ov-scalar.h @@ -244,6 +244,7 @@ octave_value floor (void) const; octave_value imag (void) const; octave_value log (void) const; + octave_value log2 (void) const; octave_value log10 (void) const; octave_value log1p (void) const; octave_value real (void) const; diff --git a/src/ov.h b/src/ov.h --- a/src/ov.h +++ b/src/ov.h @@ -920,6 +920,7 @@ MAPPER_FORWARD (isnan) MAPPER_FORWARD (lgamma) MAPPER_FORWARD (log) + MAPPER_FORWARD (log2) MAPPER_FORWARD (log10) MAPPER_FORWARD (log1p) MAPPER_FORWARD (real)