Mercurial > hg > octave-terminal
changeset 10435:6a271334750c
implement general binary mapping facility
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Tue, 23 Mar 2010 09:30:46 +0100 |
parents | f387c5b3a369 |
children | 00219bdd2d17 |
files | liboctave/ChangeLog liboctave/Makefile.am liboctave/oct-binmap.h src/ChangeLog src/data.cc |
diffstat | 5 files changed, 507 insertions(+), 833 deletions(-) [+] |
line wrap: on
line diff
--- a/liboctave/ChangeLog +++ b/liboctave/ChangeLog @@ -1,3 +1,8 @@ +2010-03-23 Jaroslav Hajek <highegg@gmail.com> + + * oct-binmap.h: New source. + * Makefile.am: Include it here. + 2010-03-22 John W. Eaton <jwe@octave.org> * config-ops.sh: Accept additional arguments.
--- a/liboctave/Makefile.am +++ b/liboctave/Makefile.am @@ -211,6 +211,7 @@ lo-utils.h \ mach-info.h \ oct-alloc.h \ + oct-binmap.h \ oct-cmplx.h \ oct-convn.h \ oct-env.h \
new file mode 100644 --- /dev/null +++ b/liboctave/oct-binmap.h @@ -0,0 +1,406 @@ +/* + +Copyright (C) 2010 VZLU Prague + +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/>. + +*/ + +#if !defined (octave_binmap_h) +#define octave_binmap_h 1 + +#include "Array.h" +#include "Sparse.h" +#include "Array-util.h" + +// This source implements a general binary maping function for arrays. +// The syntax is binmap<type> (a, b, f, [name]). type denotes the expected +// return type of the operation. a, b, should be one of the 6 combinations: +// Array-Array +// Array-scalar +// scalar-Array +// Sparse-Sparse +// Sparse-scalar +// scalar-Sparse +// +// If both operands are nonscalar, name must be supplied. It is used as the base for error message +// when operands are nonconforming. +// +// The operation needs not be homogeneous, i.e. a, b and the result may be of distinct types. +// f can have any of the four signatures: +// U f (T, R) +// U f (const T&, R) +// U f (T, const R&) +// U f (const T&, const R&) +// +// Additionally, f can be an arbitrary functor object. +// +// octave_quit() is called at appropriate places, hence the operation is breakable. + +// scalar-Array +template <class U, class T, class R, class F> +Array<U> +binmap (const T& x, const Array<R>& ya, F fcn) +{ + octave_idx_type len = ya.numel (); + + const R *y = ya.data (); + + Array<U> result (ya.dims ()); + U *p = result.fortran_vec (); + + octave_idx_type i; + for (i = 0; i < len - 3; i += 4) + { + octave_quit (); + + p[i] = fcn (x, y[i]); + p[i+1] = fcn (x, y[i+1]); + p[i+2] = fcn (x, y[i+2]); + p[i+3] = fcn (x, y[i+3]); + } + + octave_quit (); + + for (; i < len; i++) + p[i] = fcn (x, y[i]); + + return result; +} + +// Array-scalar +template <class U, class T, class R, class F> +Array<U> +binmap (const Array<T>& xa, const R& y, F fcn) +{ + octave_idx_type len = xa.numel (); + + const R *x = xa.data (); + + Array<U> result (xa.dims ()); + U *p = result.fortran_vec (); + + octave_idx_type i; + for (i = 0; i < len - 3; i += 4) + { + octave_quit (); + + p[i] = fcn (x[i], y); + p[i+1] = fcn (x[i+1], y); + p[i+2] = fcn (x[i+2], y); + p[i+3] = fcn (x[i+3], y); + } + + octave_quit (); + + for (; i < len; i++) + p[i] = fcn (x[i], y); + + return result; +} + +// Array-Array (treats singletons as scalars) +template <class U, class T, class R, class F> +Array<U> +binmap (const Array<T>& xa, const Array<R>& ya, F fcn, const char *name) +{ + if (xa.numel () == 1) + return binmap<U, T, R, F> (xa(0), ya, fcn); + else if (ya.numel () == 1) + return binmap<U, T, R, F> (xa, ya(0), fcn); + else if (xa.dims () != ya.dims ()) + gripe_nonconformant (name, xa.dims (), ya.dims ()); + + octave_idx_type len = xa.numel (); + + const T *x = xa.data (); + const T *y = ya.data (); + + Array<U> result (xa.dims ()); + U *p = result.fortran_vec (); + + octave_idx_type i; + for (i = 0; i < len - 3; i += 4) + { + octave_quit (); + + p[i] = fcn (x[i], y[i]); + p[i+1] = fcn (x[i+1], y[i+1]); + p[i+2] = fcn (x[i+2], y[i+2]); + p[i+3] = fcn (x[i+3], y[i+3]); + } + + octave_quit (); + + for (; i < len; i++) + p[i] = fcn (x[i], y[i]); + + return result; +} + +// scalar-Sparse +template <class U, class T, class R, class F> +Sparse<U> +binmap (const T& x, const Sparse<R>& ys, F fcn) +{ + octave_idx_type nz = ys.nnz (); + Sparse<U> retval (ys.rows (), ys.cols (), nz); + for (octave_idx_type i = 0; i < nz; i++) + { + octave_quit (); + retval.xdata(i) = fcn (x, ys.data(i)); + } + + octave_quit (); + retval.maybe_compress (); + return retval; +} + +// Sparse-scalar +template <class U, class T, class R, class F> +Sparse<U> +binmap (const Sparse<T>& xs, const R& y, F fcn) +{ + octave_idx_type nz = xs.nnz (); + Sparse<U> retval (xs.rows (), xs.cols (), nz); + for (octave_idx_type i = 0; i < nz; i++) + { + octave_quit (); + retval.xdata(i) = fcn (xs.data(i), y); + } + + octave_quit (); + retval.maybe_compress (); + return retval; +} + +// Sparse-Sparse (treats singletons as scalars) +template <class U, class T, class R, class F> +Sparse<U> +binmap (const Sparse<T>& xs, const Sparse<R>& ys, F fcn, const char *name) +{ + if (xs.rows () == 1 && xs.cols () == 1) + return binmap<U, T, R, F> (xs(0,0), ys, fcn); + else if (ys.rows () == 1 && ys.cols () == 1) + return binmap<U, T, R, F> (xs, ys(0,0), fcn); + else if (xs.dims () != ys.dims ()) + gripe_nonconformant (name, xs.dims (), ys.dims ()); + + T xzero = T (); + R yzero = R (); + + U fz = fcn (xzero, yzero); + if (fz == U()) + { + // Sparsity-preserving function. Do it efficiently. + octave_idx_type nr = xs.rows (), nc = xs.cols (); + Sparse<T> retval (nr, nc); + + octave_idx_type nz = 0; + // Count nonzeros. + for (octave_idx_type j = 0; j < nc; j++) + { + octave_quit (); + octave_idx_type ix = xs.cidx(j), iy = ys.cidx(j); + octave_idx_type ux = xs.cidx(j+1), uy = ys.cidx(j+1); + while (ix != ux || iy != uy) + { + octave_idx_type rx = xs.ridx(ix), ry = ys.ridx(ix); + ix += rx <= ry; + iy += ry <= rx; + nz++; + } + + retval.xcidx(j+1) = nz; + } + + // Allocate space. + retval.change_capacity (retval.xcidx(nc)); + + // Fill. + nz = 0; + for (octave_idx_type j = 0; j < nc; j++) + { + octave_quit (); + octave_idx_type ix = xs.cidx(j), iy = ys.cidx(j); + octave_idx_type ux = xs.cidx(j+1), uy = ys.cidx(j+1); + while (ix != ux || iy != uy) + { + octave_idx_type rx = xs.ridx(ix), ry = ys.ridx(ix); + if (rx == ry) + { + retval.xridx(nz) = rx; + retval.xdata(nz) = fcn (xs.data(ix), ys.data(iy)); + ix++; + iy++; + } + else if (rx < ry) + { + retval.xridx(nz) = rx; + retval.xdata(nz) = fcn (xs.data(ix), yzero); + ix++; + } + else if (ry < rx) + { + retval.xridx(nz) = ry; + retval.xdata(nz) = fcn (xzero, ys.data(iy)); + iy++; + } + + nz++; + } + } + + retval.maybe_compress (); + return retval; + } + else + return Sparse<U> (binmap<U, T, R, F> (xs.array_value (), ys.array_value (), + fcn, name)); +} + +// Overloads for function references. + +// Signature (T, R) + +template <class U, class T, class R> +inline Array<U> +binmap (const Array<T>& xa, const Array<R>& ya, U (&fcn) (T, R), const char *name) +{ return binmap<U, T, R, U (&) (T, R)> (xa, ya, fcn, name); } + +template <class U, class T, class R> +inline Array<U> +binmap (const T& x, const Array<R>& ya, U (&fcn) (T, R)) +{ return binmap<U, T, R, U (&) (T, R)> (x, ya, fcn); } + +template <class U, class T, class R> +inline Array<U> +binmap (const Array<T>& xa, const R& y, U (&fcn) (T, R)) +{ return binmap<U, T, R, U (&) (T, R)> (xa, y, fcn); } + +template <class U, class T, class R> +inline Sparse<U> +binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (&fcn) (T, R), const char *name) +{ return binmap<U, T, R, U (&) (T, R)> (xa, ya, fcn, name); } + +template <class U, class T, class R> +inline Sparse<U> +binmap (const T& x, const Sparse<R>& ya, U (&fcn) (T, R)) +{ return binmap<U, T, R, U (&) (T, R)> (x, ya, fcn); } + +template <class U, class T, class R> +inline Sparse<U> +binmap (const Sparse<T>& xa, const R& y, U (&fcn) (T, R)) +{ return binmap<U, T, R, U (&) (T, R)> (xa, y, fcn); } + +// Signature (const T&, const R&) + +template <class U, class T, class R> +inline Array<U> +binmap (const Array<T>& xa, const Array<R>& ya, U (&fcn) (const T&, const R&), const char *name) +{ return binmap<U, T, R, U (&) (const T&, const R&)> (xa, ya, fcn, name); } + +template <class U, class T, class R> +inline Array<U> +binmap (const T& x, const Array<R>& ya, U (&fcn) (const T&, const R&)) +{ return binmap<U, T, R, U (&) (const T&, const R&)> (x, ya, fcn); } + +template <class U, class T, class R> +inline Array<U> +binmap (const Array<T>& xa, const R& y, U (&fcn) (const T&, const R&)) +{ return binmap<U, T, R, U (&) (const T&, const R&)> (xa, y, fcn); } + +template <class U, class T, class R> +inline Sparse<U> +binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (&fcn) (const T&, const R&), const char *name) +{ return binmap<U, T, R, U (&) (const T&, const R&)> (xa, ya, fcn, name); } + +template <class U, class T, class R> +inline Sparse<U> +binmap (const T& x, const Sparse<R>& ya, U (&fcn) (const T&, const R&)) +{ return binmap<U, T, R, U (&) (const T&, const R&)> (x, ya, fcn); } + +template <class U, class T, class R> +inline Sparse<U> +binmap (const Sparse<T>& xa, const R& y, U (&fcn) (const T&, const R&)) +{ return binmap<U, T, R, U (&) (const T&, const R&)> (xa, y, fcn); } + +// Signature (const T&, R) + +template <class U, class T, class R> +inline Array<U> +binmap (const Array<T>& xa, const Array<R>& ya, U (&fcn) (const T&, R), const char *name) +{ return binmap<U, T, R, U (&) (const T&, R)> (xa, ya, fcn, name); } + +template <class U, class T, class R> +inline Array<U> +binmap (const T& x, const Array<R>& ya, U (&fcn) (const T&, R)) +{ return binmap<U, T, R, U (&) (const T&, R)> (x, ya, fcn); } + +template <class U, class T, class R> +inline Array<U> +binmap (const Array<T>& xa, const R& y, U (&fcn) (const T&, R)) +{ return binmap<U, T, R, U (&) (const T&, R)> (xa, y, fcn); } + +template <class U, class T, class R> +inline Sparse<U> +binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (&fcn) (const T&, R), const char *name) +{ return binmap<U, T, R, U (&) (const T&, R)> (xa, ya, fcn, name); } + +template <class U, class T, class R> +inline Sparse<U> +binmap (const T& x, const Sparse<R>& ya, U (&fcn) (const T&, R)) +{ return binmap<U, T, R, U (&) (const T&, R)> (x, ya, fcn); } + +template <class U, class T, class R> +inline Sparse<U> +binmap (const Sparse<T>& xa, const R& y, U (&fcn) (const T&, R)) +{ return binmap<U, T, R, U (&) (const T&, R)> (xa, y, fcn); } + +// Signature (T, const R&) + +template <class U, class T, class R> +inline Array<U> +binmap (const Array<T>& xa, const Array<R>& ya, U (&fcn) (T, const R&), const char *name) +{ return binmap<U, T, R, U (&) (T, const R&)> (xa, ya, fcn, name); } + +template <class U, class T, class R> +inline Array<U> +binmap (const T& x, const Array<R>& ya, U (&fcn) (T, const R&)) +{ return binmap<U, T, R, U (&) (T, const R&)> (x, ya, fcn); } + +template <class U, class T, class R> +inline Array<U> +binmap (const Array<T>& xa, const R& y, U (&fcn) (T, const R&)) +{ return binmap<U, T, R, U (&) (T, const R&)> (xa, y, fcn); } + +template <class U, class T, class R> +inline Sparse<U> +binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (&fcn) (T, const R&), const char *name) +{ return binmap<U, T, R, U (&) (T, const R&)> (xa, ya, fcn, name); } + +template <class U, class T, class R> +inline Sparse<U> +binmap (const T& x, const Sparse<R>& ya, U (&fcn) (T, const R&)) +{ return binmap<U, T, R, U (&) (T, const R&)> (x, ya, fcn); } + +template <class U, class T, class R> +inline Sparse<U> +binmap (const Sparse<T>& xa, const R& y, U (&fcn) (T, const R&)) +{ return binmap<U, T, R, U (&) (T, const R&)> (xa, y, fcn); } + +#endif
--- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,9 @@ +2010-03-23 Jaroslav Hajek <highegg@gmail.com> + + * data.cc (map_d_m, map_m_d, map_m_m, map_f_fm, map_fm_f, map_fm_fm, + map_d_s, map_s_d, map_s_s): Remove. + (Fatan2, Fhypot, Ffmod): Rewrite using binmap. + 2010-03-21 Jaroslav Hajek <highegg@gmail.com> * DLD-FUNCTIONS/cellfun.cc (Fcellfun): Fix the parsing of string
--- a/src/data.cc +++ b/src/data.cc @@ -45,6 +45,7 @@ #include "str-vec.h" #include "quit.h" #include "mx-base.h" +#include "oct-binmap.h" #include "Cell.h" #include "defun.h" @@ -194,351 +195,6 @@ // These mapping functions may also be useful in other places, eh? -typedef double (*d_dd_fcn) (double, double); -typedef float (*f_ff_fcn) (float, float); - -static NDArray -map_d_m (d_dd_fcn f, double x, const NDArray& y) -{ - NDArray retval (y.dims ()); - double *r_data = retval.fortran_vec (); - - const double *y_data = y.data (); - - octave_idx_type nel = y.numel (); - - for (octave_idx_type i = 0; i < nel; i++) - { - octave_quit (); - r_data[i] = f (x, y_data[i]); - } - - return retval; -} - -static FloatNDArray -map_f_fm (f_ff_fcn f, float x, const FloatNDArray& y) -{ - FloatNDArray retval (y.dims ()); - float *r_data = retval.fortran_vec (); - - const float *y_data = y.data (); - - octave_idx_type nel = y.numel (); - - for (octave_idx_type i = 0; i < nel; i++) - { - octave_quit (); - r_data[i] = f (x, y_data[i]); - } - - return retval; -} - -static NDArray -map_m_d (d_dd_fcn f, const NDArray& x, double y) -{ - NDArray retval (x.dims ()); - double *r_data = retval.fortran_vec (); - - const double *x_data = x.data (); - - octave_idx_type nel = x.numel (); - - for (octave_idx_type i = 0; i < nel; i++) - { - octave_quit (); - r_data[i] = f (x_data[i], y); - } - - return retval; -} - -static FloatNDArray -map_fm_f (f_ff_fcn f, const FloatNDArray& x, float y) -{ - FloatNDArray retval (x.dims ()); - float *r_data = retval.fortran_vec (); - - const float *x_data = x.data (); - - octave_idx_type nel = x.numel (); - - for (octave_idx_type i = 0; i < nel; i++) - { - octave_quit (); - r_data[i] = f (x_data[i], y); - } - - return retval; -} - -static NDArray -map_m_m (d_dd_fcn f, const NDArray& x, const NDArray& y) -{ - assert (x.dims () == y.dims ()); - - NDArray retval (x.dims ()); - double *r_data = retval.fortran_vec (); - - const double *x_data = x.data (); - const double *y_data = y.data (); - - octave_idx_type nel = x.numel (); - - for (octave_idx_type i = 0; i < nel; i++) - { - octave_quit (); - r_data[i] = f (x_data[i], y_data[i]); - } - - return retval; -} - -static FloatNDArray -map_fm_fm (f_ff_fcn f, const FloatNDArray& x, const FloatNDArray& y) -{ - assert (x.dims () == y.dims ()); - - FloatNDArray retval (x.dims ()); - float *r_data = retval.fortran_vec (); - - const float *x_data = x.data (); - const float *y_data = y.data (); - - octave_idx_type nel = x.numel (); - - for (octave_idx_type i = 0; i < nel; i++) - { - octave_quit (); - r_data[i] = f (x_data[i], y_data[i]); - } - - return retval; -} - -static SparseMatrix -map_d_s (d_dd_fcn f, double x, const SparseMatrix& y) -{ - octave_idx_type nr = y.rows (); - octave_idx_type nc = y.columns (); - SparseMatrix retval; - double f_zero = f (x, 0.); - - if (f_zero != 0) - { - retval = SparseMatrix (nr, nc, f_zero); - - for (octave_idx_type j = 0; j < nc; j++) - for (octave_idx_type i = y.cidx (j); i < y.cidx (j+1); i++) - { - octave_quit (); - retval.data (y.ridx(i) + j * nr) = f (x, y.data (i)); - } - - retval.maybe_compress (true); - } - else - { - octave_idx_type nz = y.nnz (); - retval = SparseMatrix (nr, nc, nz); - octave_idx_type ii = 0; - retval.cidx (ii) = 0; - - for (octave_idx_type j = 0; j < nc; j++) - { - for (octave_idx_type i = y.cidx (j); i < y.cidx (j+1); i++) - { - octave_quit (); - double val = f (x, y.data (i)); - - if (val != 0.0) - { - retval.data (ii) = val; - retval.ridx (ii++) = y.ridx (i); - } - } - retval.cidx (j + 1) = ii; - } - - retval.maybe_compress (false); - } - - return retval; -} - -static SparseMatrix -map_s_d (d_dd_fcn f, const SparseMatrix& x, double y) -{ - octave_idx_type nr = x.rows (); - octave_idx_type nc = x.columns (); - SparseMatrix retval; - double f_zero = f (0., y); - - if (f_zero != 0) - { - retval = SparseMatrix (nr, nc, f_zero); - - for (octave_idx_type j = 0; j < nc; j++) - for (octave_idx_type i = x.cidx (j); i < x.cidx (j+1); i++) - { - octave_quit (); - retval.data (x.ridx(i) + j * nr) = f (x.data (i), y); - } - - retval.maybe_compress (true); - } - else - { - octave_idx_type nz = x.nnz (); - retval = SparseMatrix (nr, nc, nz); - octave_idx_type ii = 0; - retval.cidx (ii) = 0; - - for (octave_idx_type j = 0; j < nc; j++) - { - for (octave_idx_type i = x.cidx (j); i < x.cidx (j+1); i++) - { - octave_quit (); - double val = f (x.data (i), y); - - if (val != 0.0) - { - retval.data (ii) = val; - retval.ridx (ii++) = x.ridx (i); - } - } - retval.cidx (j + 1) = ii; - } - - retval.maybe_compress (false); - } - - return retval; -} - -static SparseMatrix -map_s_s (d_dd_fcn f, const SparseMatrix& x, const SparseMatrix& y) -{ - octave_idx_type nr = x.rows (); - octave_idx_type nc = x.columns (); - - octave_idx_type y_nr = y.rows (); - octave_idx_type y_nc = y.columns (); - - assert (nr == y_nr && nc == y_nc); - - SparseMatrix retval; - double f_zero = f (0., 0.); - - if (f_zero != 0) - { - retval = SparseMatrix (nr, nc, f_zero); - octave_idx_type k1 = 0, k2 = 0; - - for (octave_idx_type j = 0; j < nc; j++) - { - while (k1 < x.cidx(j+1) && k2 < y.cidx(j+1)) - { - octave_quit (); - if (k1 >= x.cidx(j+1)) - { - retval.data (y.ridx(k2) + j * nr) = f (0.0, y.data (k2)); - k2++; - } - else if (k2 >= y.cidx(j+1)) - { - retval.data (x.ridx(k1) + j * nr) = f (x.data (k1), 0.0); - k1++; - } - else - { - octave_idx_type rx = x.ridx(k1); - octave_idx_type ry = y.ridx(k2); - - if (rx < ry) - { - retval.data (rx + j * nr) = f (x.data (k1), 0.0); - k1++; - } - else if (rx > ry) - { - retval.data (ry + j * nr) = f (0.0, y.data (k2)); - k2++; - } - else - { - retval.data (ry + j * nr) = f (x.data (k1), y.data (k2)); - k1++; - k2++; - } - } - } - } - - retval.maybe_compress (true); - } - else - { - octave_idx_type nz = x.nnz () + y.nnz (); - retval = SparseMatrix (nr, nc, nz); - octave_idx_type ii = 0; - retval.cidx (ii) = 0; - octave_idx_type k1 = 0, k2 = 0; - - for (octave_idx_type j = 0; j < nc; j++) - { - while (k1 < x.cidx(j+1) && k2 < y.cidx(j+1)) - { - octave_quit (); - double val; - octave_idx_type r; - if (k1 >= x.cidx(j+1)) - { - r = y.ridx (k2); - val = f (0.0, y.data (k2++)); - } - else if (k2 >= y.cidx(j+1)) - { - r = x.ridx (k1); - val = f (x.data (k1++), 0.0); - } - else - { - octave_idx_type rx = x.ridx(k1); - octave_idx_type ry = y.ridx(k2); - - if (rx < ry) - { - r = x.ridx (k1); - val = f (x.data (k1++), 0.0); - } - else if (rx > ry) - { - r = y.ridx (k2); - val = f (0.0, y.data (k2++)); - } - else - { - r = y.ridx (k2); - val = f (x.data (k1++), y.data (k2++)); - } - } - if (val != 0.0) - { - retval.data (ii) = val; - retval.ridx (ii++) = r; - } - } - retval.cidx (j + 1) = ii; - } - - retval.maybe_compress (false); - } - - return retval; -} - DEFUN (atan2, args, , "-*- texinfo -*-\n\ @deftypefn {Mapping Function} {} atan2 (@var{y}, @var{x})\n\ @@ -551,160 +207,44 @@ int nargin = args.length (); - if (nargin == 2 && args(0).is_defined () && args(1).is_defined ()) + if (nargin == 2) { - if (args(0).is_integer_type () || args(1).is_integer_type ()) - error ("atan2: not defined for integer types"); + if (! args(0).is_numeric_type ()) + gripe_wrong_type_arg ("atan2", args(0)); + else if (! args(1).is_numeric_type ()) + gripe_wrong_type_arg ("atan2", args(1)); + else if (args(0).is_complex_type () || args(1).is_complex_type ()) + error ("atan2: not defined for complex numbers"); + else if (args(0).is_single_type () || args(1).is_single_type ()) + { + if (args(0).is_scalar_type () && args(1).is_scalar_type ()) + retval = atan2f (args(0).float_value (), args(1).float_value ()); + else + { + FloatNDArray a0 = args(0).float_array_value (); + FloatNDArray a1 = args(1).float_array_value (); + retval = binmap<float> (a0, a1, ::atan2f, "atan2"); + } + } else { - octave_value arg_y = args(0); - octave_value arg_x = args(1); - - dim_vector y_dims = arg_y.dims (); - dim_vector x_dims = arg_x.dims (); - - bool y_is_scalar = y_dims.all_ones (); - bool x_is_scalar = x_dims.all_ones (); - - bool is_float = arg_y.is_single_type () || arg_x.is_single_type (); - - if (y_is_scalar && x_is_scalar) - { - if (is_float) - { - float y = arg_y.float_value (); - - if (! error_state) - { - float x = arg_x.float_value (); - - if (! error_state) - retval = atan2f (y, x); - } - } - else - { - double y = arg_y.double_value (); - - if (! error_state) - { - double x = arg_x.double_value (); - - if (! error_state) - retval = atan2 (y, x); - } - } - } - else if (y_is_scalar) - { - if (is_float) - { - float y = arg_y.float_value (); - - if (! error_state) - { - // Even if x is sparse return a full matrix here - FloatNDArray x = arg_x.float_array_value (); - - if (! error_state) - retval = map_f_fm (atan2f, y, x); - } - } - else - { - double y = arg_y.double_value (); - - if (! error_state) - { - // Even if x is sparse return a full matrix here - NDArray x = arg_x.array_value (); - - if (! error_state) - retval = map_d_m (atan2, y, x); - } - } - } - else if (x_is_scalar) + bool a0_scalar = args(0).is_scalar_type (); + bool a1_scalar = args(1).is_scalar_type (); + if (a0_scalar && a1_scalar) + retval = atan2 (args(0).scalar_value (), args(1).scalar_value ()); + else if ((a0_scalar || args(0).is_sparse_type ()) + && (a1_scalar || args(1).is_sparse_type ())) { - if (arg_y.is_sparse_type ()) - { - SparseMatrix y = arg_y.sparse_matrix_value (); - - if (! error_state) - { - double x = arg_x.double_value (); - - if (! error_state) - retval = map_s_d (atan2, y, x); - } - } - else if (is_float) - { - FloatNDArray y = arg_y.float_array_value (); - - if (! error_state) - { - float x = arg_x.float_value (); - - if (! error_state) - retval = map_fm_f (atan2f, y, x); - } - } - else - { - NDArray y = arg_y.array_value (); - - if (! error_state) - { - double x = arg_x.double_value (); - - if (! error_state) - retval = map_m_d (atan2, y, x); - } - } - } - else if (y_dims == x_dims) - { - // Even if y is sparse return a full matrix here - if (arg_x.is_sparse_type ()) - { - SparseMatrix y = arg_y.sparse_matrix_value (); - - if (! error_state) - { - SparseMatrix x = arg_x.sparse_matrix_value (); - - if (! error_state) - retval = map_s_s (atan2, y, x); - } - } - else if (is_float) - { - FloatNDArray y = arg_y.array_value (); - - if (! error_state) - { - FloatNDArray x = arg_x.array_value (); - - if (! error_state) - retval = map_fm_fm (atan2f, y, x); - } - } - else - { - NDArray y = arg_y.array_value (); - - if (! error_state) - { - NDArray x = arg_x.array_value (); - - if (! error_state) - retval = map_m_m (atan2, y, x); - } - } + SparseMatrix m0 = args(0).sparse_matrix_value (); + SparseMatrix m1 = args(1).sparse_matrix_value (); + retval = binmap<double> (m0, m1, ::atan2, "atan2"); } else - error ("atan2: nonconformant matrices"); + { + NDArray a0 = args(0).array_value (); + NDArray a1 = args(1).array_value (); + retval = binmap<double> (a0, a1, ::atan2, "atan2"); + } } } else @@ -756,217 +296,51 @@ int nargin = args.length (); - if (nargin == 2 && args(0).is_defined () && args(1).is_defined ()) + if (nargin == 2) { - if (args(0).is_integer_type () || args(1).is_integer_type ()) - error ("hypot: not defined for integer types"); + octave_value arg0 = args(0), arg1 = args(1); + if (! arg0.is_numeric_type ()) + gripe_wrong_type_arg ("hypot", arg0); + else if (! arg1.is_numeric_type ()) + gripe_wrong_type_arg ("hypot", arg1); else { - octave_value arg_x = args(0); - octave_value arg_y = args(1); - - dim_vector x_dims = arg_x.dims (); - dim_vector y_dims = arg_y.dims (); - - bool x_is_scalar = x_dims.all_ones (); - bool y_is_scalar = y_dims.all_ones (); - - bool is_float = arg_y.is_single_type () || arg_x.is_single_type (); - - if (y_is_scalar && x_is_scalar) + if (arg0.is_complex_type ()) + arg0 = arg0.abs (); + if (arg1.is_complex_type ()) + arg1 = arg1.abs (); + + if (arg0.is_single_type () || arg1.is_single_type ()) { - if (is_float) - { - float x; - if (arg_x.is_complex_type ()) - x = abs (arg_x.float_complex_value ()); - else - x = arg_x.float_value (); - - if (! error_state) - { - float y; - if (arg_y.is_complex_type ()) - y = abs (arg_y.float_complex_value ()); - else - y = arg_y.float_value (); - - if (! error_state) - retval = hypotf (x, y); - } - } + if (arg0.is_scalar_type () && arg1.is_scalar_type ()) + retval = hypotf (arg0.float_value (), arg1.float_value ()); else { - double x; - if (arg_x.is_complex_type ()) - x = abs (arg_x.complex_value ()); - else - x = arg_x.double_value (); - - if (! error_state) - { - double y; - if (arg_y.is_complex_type ()) - y = abs (arg_y.complex_value ()); - else - y = arg_y.double_value (); - - if (! error_state) - retval = hypot (x, y); - } + FloatNDArray a0 = arg0.float_array_value (); + FloatNDArray a1 = arg1.float_array_value (); + retval = binmap<float> (a0, a1, ::hypotf, "hypot"); } } - else if (y_is_scalar) + else { - if (is_float) + bool a0_scalar = arg0.is_scalar_type (); + bool a1_scalar = arg1.is_scalar_type (); + if (a0_scalar && a1_scalar) + retval = hypot (arg0.scalar_value (), arg1.scalar_value ()); + else if ((a0_scalar || arg0.is_sparse_type ()) + && (a1_scalar || arg1.is_sparse_type ())) { - FloatNDArray x; - if (arg_x.is_complex_type ()) - x = arg_x.float_complex_array_value ().abs (); - else - x = arg_x.float_array_value (); - - if (! error_state) - { - float y; - if (arg_y.is_complex_type ()) - y = abs (arg_y.float_complex_value ()); - else - y = arg_y.float_value (); - - if (! error_state) - retval = map_fm_f (hypotf, x, y); - } + SparseMatrix m0 = arg0.sparse_matrix_value (); + SparseMatrix m1 = arg1.sparse_matrix_value (); + retval = binmap<double> (m0, m1, ::hypot, "hypot"); } else { - NDArray x; - if (arg_x.is_complex_type ()) - x = arg_x.complex_array_value ().abs (); - else - x = arg_x.array_value (); - - if (! error_state) - { - double y; - if (arg_y.is_complex_type ()) - y = abs (arg_y.complex_value ()); - else - y = arg_y.double_value (); - - if (! error_state) - retval = map_m_d (hypot, x, y); - } - } - } - else if (x_is_scalar) - { - if (is_float) - { - float x; - if (arg_x.is_complex_type ()) - x = abs (arg_x.float_complex_value ()); - else - x = arg_x.float_value (); - - if (! error_state) - { - FloatNDArray y; - if (arg_y.is_complex_type ()) - y = arg_y.float_complex_array_value ().abs (); - else - y = arg_y.float_array_value (); - - if (! error_state) - retval = map_f_fm (hypotf, x, y); - } - } - else - { - double x; - if (arg_x.is_complex_type ()) - x = abs (arg_x.complex_value ()); - else - x = arg_x.double_value (); - - if (! error_state) - { - NDArray y; - if (arg_y.is_complex_type ()) - y = arg_y.complex_array_value ().abs (); - else - y = arg_y.array_value (); - - if (! error_state) - retval = map_d_m (hypot, x, y); - } + NDArray a0 = arg0.array_value (); + NDArray a1 = arg1.array_value (); + retval = binmap<double> (a0, a1, ::hypot, "hypot"); } } - else if (y_dims == x_dims) - { - if (arg_x.is_sparse_type () && arg_y.is_sparse_type ()) - { - SparseMatrix x; - if (arg_x.is_complex_type ()) - x = arg_x.sparse_complex_matrix_value ().abs (); - else - x = arg_x.sparse_matrix_value (); - - if (! error_state) - { - SparseMatrix y; - if (arg_y.is_complex_type ()) - y = arg_y.sparse_complex_matrix_value ().abs (); - else - y = arg_y.sparse_matrix_value (); - - if (! error_state) - retval = map_s_s (hypot, x, y); - } - } - else if (is_float) - { - FloatNDArray x; - if (arg_x.is_complex_type ()) - x = arg_x.float_complex_array_value ().abs (); - else - x = arg_x.float_array_value (); - - if (! error_state) - { - FloatNDArray y; - if (arg_y.is_complex_type ()) - y = arg_y.float_complex_array_value ().abs (); - else - y = arg_y.float_array_value (); - - if (! error_state) - retval = map_fm_fm (hypotf, x, y); - } - } - else - { - NDArray x; - if (arg_x.is_complex_type ()) - x = arg_x.complex_array_value ().abs (); - else - x = arg_x.array_value (); - - if (! error_state) - { - NDArray y; - if (arg_y.is_complex_type ()) - y = arg_y.complex_array_value ().abs (); - else - y = arg_y.array_value (); - - if (! error_state) - retval = map_m_m (hypot, x, y); - } - } - } - else - error ("hypot: nonconformant matrices"); } } else @@ -1112,163 +486,45 @@ int nargin = args.length (); - if (nargin == 2 && args(0).is_defined () && args(1).is_defined ()) + if (nargin == 2) { - octave_value arg_x = args(0); - octave_value arg_y = args(1); - - dim_vector y_dims = arg_y.dims (); - dim_vector x_dims = arg_x.dims (); - - bool y_is_scalar = y_dims.all_ones (); - bool x_is_scalar = x_dims.all_ones (); - - bool is_float = arg_y.is_single_type () || arg_x.is_single_type (); - - if (y_is_scalar && x_is_scalar) + if (! args(0).is_numeric_type ()) + gripe_wrong_type_arg ("fmod", args(0)); + else if (! args(1).is_numeric_type ()) + gripe_wrong_type_arg ("fmod", args(1)); + else if (args(0).is_complex_type () || args(1).is_complex_type ()) + error ("fmod: not defined for complex numbers"); + else if (args(0).is_single_type () || args(1).is_single_type ()) { - if (is_float) - { - float y = arg_y.float_value (); - - if (! error_state) - { - float x = arg_x.float_value (); - - if (! error_state) - retval = fmod (x, y); - } - } + if (args(0).is_scalar_type () && args(1).is_scalar_type ()) + retval = fmodf (args(0).float_value (), args(1).float_value ()); else { - double y = arg_y.double_value (); - - if (! error_state) - { - double x = arg_x.double_value (); - - if (! error_state) - retval = fmod (x, y); - } + FloatNDArray a0 = args(0).float_array_value (); + FloatNDArray a1 = args(1).float_array_value (); + retval = binmap<float> (a0, a1, ::fmodf, "fmod"); } } - else if (y_is_scalar) + else { - if (is_float) + bool a0_scalar = args(0).is_scalar_type (); + bool a1_scalar = args(1).is_scalar_type (); + if (a0_scalar && a1_scalar) + retval = fmod (args(0).scalar_value (), args(1).scalar_value ()); + else if ((a0_scalar || args(0).is_sparse_type ()) + && (a1_scalar || args(1).is_sparse_type ())) { - float y = arg_y.float_value (); - - if (! error_state) - { - FloatNDArray x = arg_x.float_array_value (); - - if (! error_state) - retval = map_fm_f (fmodf, x, y); - } + SparseMatrix m0 = args(0).sparse_matrix_value (); + SparseMatrix m1 = args(1).sparse_matrix_value (); + retval = binmap<double> (m0, m1, ::fmod, "fmod"); } else { - double y = arg_y.double_value (); - - if (! error_state) - { - if (arg_x.is_sparse_type ()) - { - SparseMatrix x = arg_x.sparse_matrix_value (); - - if (! error_state) - retval = map_s_d (fmod, x, y); - } - else - { - NDArray x = arg_x.array_value (); - - if (! error_state) - retval = map_m_d (fmod, x, y); - } - } + NDArray a0 = args(0).array_value (); + NDArray a1 = args(1).array_value (); + retval = binmap<double> (a0, a1, ::fmod, "fmod"); } } - else if (x_is_scalar) - { - if (arg_y.is_sparse_type ()) - { - SparseMatrix y = arg_y.sparse_matrix_value (); - - if (! error_state) - { - double x = arg_x.double_value (); - - if (! error_state) - retval = map_d_s (fmod, x, y); - } - } - else if (is_float) - { - FloatNDArray y = arg_y.float_array_value (); - - if (! error_state) - { - float x = arg_x.float_value (); - - if (! error_state) - retval = map_f_fm (fmodf, x, y); - } - } - else - { - NDArray y = arg_y.array_value (); - - if (! error_state) - { - double x = arg_x.double_value (); - - if (! error_state) - retval = map_d_m (fmod, x, y); - } - } - } - else if (y_dims == x_dims) - { - if (arg_y.is_sparse_type () || arg_x.is_sparse_type ()) - { - SparseMatrix y = arg_y.sparse_matrix_value (); - - if (! error_state) - { - SparseMatrix x = arg_x.sparse_matrix_value (); - - if (! error_state) - retval = map_s_s (fmod, x, y); - } - } - else if (is_float) - { - FloatNDArray y = arg_y.float_array_value (); - - if (! error_state) - { - FloatNDArray x = arg_x.float_array_value (); - - if (! error_state) - retval = map_fm_fm (fmodf, x, y); - } - } - else - { - NDArray y = arg_y.array_value (); - - if (! error_state) - { - NDArray x = arg_x.array_value (); - - if (! error_state) - retval = map_m_m (fmod, x, y); - } - } - } - else - error ("fmod: nonconformant matrices"); } else print_usage ();