# 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)