changeset 7740:39930366b709

implement builtin log2
author Jaroslav Hajek <highegg@gmail.com>
date Wed, 30 Apr 2008 03:30:34 -0400
parents ca9bfe159144
children 72c0489653ac
files liboctave/ChangeLog liboctave/lo-mappers.cc liboctave/lo-mappers.h scripts/ChangeLog scripts/specfun/Makefile.in scripts/specfun/log2.m src/ChangeLog src/data.cc src/ov-base.cc src/ov-base.h src/ov-bool-mat.h src/ov-bool-sparse.h src/ov-bool.h src/ov-complex.cc src/ov-complex.h src/ov-cx-mat.cc src/ov-cx-mat.h src/ov-cx-sparse.cc src/ov-cx-sparse.h src/ov-fcn-handle.cc src/ov-range.h src/ov-re-mat.cc src/ov-re-mat.h src/ov-re-sparse.cc src/ov-re-sparse.h src/ov-scalar.cc src/ov-scalar.h src/ov.h
diffstat 28 files changed, 156 insertions(+), 79 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/ChangeLog
+++ b/liboctave/ChangeLog
@@ -1,3 +1,10 @@
+2008-04-30  Jaroslav Hajek <highegg@gmail.com>
+
+	* 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 <michael.goffioul@gmail.com>
 
 	* oct-lookup.h (seq_lookup): Do not use output value of fill_n (MSVC
--- 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
--- 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);
--- a/scripts/ChangeLog
+++ b/scripts/ChangeLog
@@ -1,3 +1,8 @@
+2008-04-30  Jaroslav Hajek <highegg@gmail.com>
+
+	* specfun/log2.m: Delete. 
+	* specfun/Makefile.in (SOURCES): Delete it from the list.
+
 2008-04-29  David Bateman  <dbateman@free.fr>
 
 	pkg/pkg.m: Also set archprefix with the -local and -global options.
--- 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))
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
-## <http://www.gnu.org/licenses/>.
-
-## -*- 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 <Andreas.Weingessel@ci.tuwien.ac.at>
-## 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);
-
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,17 @@
+2008-04-30  John W. Eaton  <jwe@octave.org>
+
+	* ov-fcn-handle.cc: Create handle pointing to flops instead of log2.
+
+2008-04-30  Jaroslav Hajek <highegg@gmail.com>
+
+	* 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  <jwe@octave.org>
 
 	* pt-stmt.h (tree_statement_list::function_body): New data member.
--- a/src/data.cc
+++ b/src/data.cc
@@ -686,6 +686,82 @@
 %! assert (hypot (1:10,1:10), sqrt(2) * [1:10]);
 */
 
+template<typename T, typename ET>
+void 
+map_2_xlog2 (const Array<T>& x, Array<T>& f, Array<ET>& e)
+{
+  f = Array<T>(x.dims ());
+  e = Array<ET>(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\
--- 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)
--- 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;
--- 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)
--- 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)
--- 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)
--- 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)
--- 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;
--- 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)
--- 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;
--- 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)
--- 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;
--- 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;
--- 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)
--- 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)
--- 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;
--- 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)
--- 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;
--- 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)
--- 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;
--- 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)