# HG changeset patch
# User Jaroslav Hajek
# Date 1209130258 -7200
# Node ID 425dd5f48563880bbe974309cf8b79032f1e3397
# Parent bb614b3883a9d4e1ff9439ee468f2569576c72f7
replace log2 with compiled version (using C library if possible)
diff --git a/ChangeLog b/ChangeLog
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2008-04-25 Jaroslav Hajek
+
+ * configure.in: add check for frexp.
+
2008-04-09 Rafael Laboissiere
* example/octave.desktop.in: Drop the Encoding key, which is
diff --git a/configure.in b/configure.in
--- a/configure.in
+++ b/configure.in
@@ -1539,7 +1539,7 @@
### Check for nonstandard but common math functions that we need.
-AC_CHECK_FUNCS(acosh asinh atanh erf erfc exp2 log2)
+AC_CHECK_FUNCS(acosh asinh atanh erf erfc exp2 log2 frexp)
### Checks for OS specific cruft.
diff --git a/liboctave/ChangeLog b/liboctave/ChangeLog
--- a/liboctave/ChangeLog
+++ b/liboctave/ChangeLog
@@ -1,3 +1,11 @@
+2008-04-25 Jaroslav Hajek
+
+ * lo-mappers.h (xlog2 (Complex), xlog2 (double, int&), xlog2 (Complex,
+ int&): declare new functions.
+ * lo-mappers.cc (xlog2 (double)): fix bug.
+ * lo-mappers.cc (xlog2 (Complex), xlog2 (double, int&), xlog2
+ (Complex, int&)): new functions.
+
2008-04-24 Michael Goffioul
* lo-sysdep.cc (octave_popen2): Don't set PIPE_NOWAIT for parentWrite.
diff --git a/liboctave/lo-mappers.cc b/liboctave/lo-mappers.cc
--- a/liboctave/lo-mappers.cc
+++ b/liboctave/lo-mappers.cc
@@ -139,11 +139,23 @@
#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
@@ -155,11 +167,42 @@
#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)
+{
+#if defined (HAVE_FREXP)
+ return frexp (x, &exp);
+#else
+ if (lo_ieee_isfinite (x) && x != 0)
+ {
+ exp = xtrunc (xlog2 (abs (x)));
+ x *= xexp2 (-exp);
+ if (abs(x) >= 1) // `==' should suffice in theory
+ {
+ x /= 2;
+ exp++;
+ }
+ return x;
+ }
+ else
+ {
+ exp = 0;
+ return x;
+ }
+#endif
+}
+
+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.
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-25 Jaroslav Hajek
+
+ * specfun/log2.m: delete.
+ * specfun/Makefile.in: delete reference to log2.
+
2008-04-21 David Bateman
* plot/__go_draw_axes__.m (gnuplot_position_colorbox): New arg, obj.
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} address@hidden, @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,14 @@
+2008-04-25 Jaroslav Hajek
+
+ * DLD-FUNCTIONS/log2.cc: New DLD function.
+ * 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.
+ * Makefile.in: include DLD-FUNCTIONS/log2.cc in the build process.
+
2008-04-24 John W. Eaton
* toplev.h, toplev.cc (octave_call_stack::unwind_pop_script):
diff --git a/src/DLD-FUNCTIONS/log2.cc b/src/DLD-FUNCTIONS/log2.cc
new file mode 100644
--- /dev/null
+++ b/src/DLD-FUNCTIONS/log2.cc
@@ -0,0 +1,105 @@
+/*
+
+Copyright (C) 2008 Jaroslav Hajek
+
+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
+.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include "lo-mappers.h"
+#include "quit.h"
+#include "dMatrix.h"
+#include "CMatrix.h"
+
+#include "defun-dld.h"
+#include "error.h"
+#include "gripes.h"
+#include "oct-obj.h"
+#include "utils.h"
+
+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_DLD (log2, args, nargout,
+ "-*- texinfo -*-\n\
address@hidden {Mapping Function} {} log2 (@var{x})\n\
address@hidden {Builtin Function} {[f, 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\
address@hidden is an integer. If @code{x = 0}, @code{f = e = 0}.\n\
address@hidden, log10, log2, exp}\n\
address@hidden deftypefn")
+{
+ octave_value_list retval;
+ if (args.length () == 1)
+ {
+ if (nargout < 2)
+ retval(0) = args(0).log2 ();
+ else if (args(0).is_complex_matrix ())
+ {
+ ComplexMatrix f, x = args(0).complex_matrix_value ();
+ Matrix e; // NOTE: could also return intNDArray ...
+ map_2_xlog2 (x, f, e);
+ retval (1) = e;
+ retval (0) = f;
+ }
+ else
+ {
+ Matrix f, x = args(0).matrix_value ();
+ Matrix e; // NOTE: could also return intNDArray ...
+ map_2_xlog2 (x, f, e);
+ retval (1) = e;
+ retval (0) = f;
+ }
+ }
+ else
+ print_usage ();
+
+ return retval;
+}
+
+/*
+%! assert(all (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(all((f == [0,-0.5;0.5,-0.5;Inf,-Inf])(:))
+%! assert(all((e == [0,1;2,3;0,0])(:)))
+%!test
+%! [f,e] = log2(complex(zeros(3,2),[0,-1;2,-4;Inf,-Inf]));
+%! assert(all((f == complex(zeros(3,2),[0,-0.5;0.5,-0.5;Inf,-Inf])(:)))
+%! assert(all((e == [0,1;2,3;0,0])(:)))
+*/
diff --git a/src/Makefile.in b/src/Makefile.in
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -67,7 +67,7 @@
dasrt.cc dassl.cc det.cc dispatch.cc dlmread.cc dmperm.cc eig.cc \
expm.cc fft.cc fft2.cc fftn.cc fftw.cc filter.cc find.cc fsolve.cc \
gammainc.cc gcd.cc getgrent.cc getpwent.cc getrusage.cc \
- givens.cc hess.cc hex2num.cc inv.cc kron.cc lookup.cc lsode.cc \
+ givens.cc hess.cc hex2num.cc inv.cc kron.cc log2.cc lookup.cc lsode.cc \
lu.cc luinc.cc matrix_type.cc max.cc md5sum.cc pinv.cc qr.cc \
quad.cc qz.cc rand.cc regexp.cc schur.cc sparse.cc \
spparms.cc sqrtm.cc svd.cc syl.cc symrcm.cc symbfact.cc \
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-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)