dNDArray.cc

Go to the documentation of this file.
00001 // N-D Array  manipulations.
00002 /*
00003 
00004 Copyright (C) 1996-2012 John W. Eaton
00005 Copyright (C) 2009 VZLU Prague, a.s.
00006 
00007 This file is part of Octave.
00008 
00009 Octave is free software; you can redistribute it and/or modify it
00010 under the terms of the GNU General Public License as published by the
00011 Free Software Foundation; either version 3 of the License, or (at your
00012 option) any later version.
00013 
00014 Octave is distributed in the hope that it will be useful, but WITHOUT
00015 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00016 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00017 for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with Octave; see the file COPYING.  If not, see
00021 <http://www.gnu.org/licenses/>.
00022 
00023 */
00024 
00025 #ifdef HAVE_CONFIG_H
00026 #include <config.h>
00027 #endif
00028 
00029 #include <cfloat>
00030 
00031 #include <vector>
00032 
00033 #include "Array-util.h"
00034 #include "dNDArray.h"
00035 #include "f77-fcn.h"
00036 #include "functor.h"
00037 #include "lo-error.h"
00038 #include "lo-ieee.h"
00039 #include "lo-mappers.h"
00040 #include "mx-base.h"
00041 #include "mx-op-defs.h"
00042 #include "oct-fftw.h"
00043 #include "oct-locbuf.h"
00044 
00045 #include "bsxfun-defs.cc"
00046 
00047 NDArray::NDArray (const Array<octave_idx_type>& a, bool zero_based,
00048                   bool negative_to_nan)
00049 {
00050   const octave_idx_type *pa = a.fortran_vec ();
00051   resize (a.dims ());
00052   double *ptmp = fortran_vec ();
00053   if (negative_to_nan)
00054     {
00055       double nan_val = lo_ieee_nan_value ();
00056 
00057       if (zero_based)
00058         for (octave_idx_type i = 0; i < a.numel (); i++)
00059           {
00060             double val = static_cast<double>
00061               (pa[i] + static_cast<octave_idx_type> (1));
00062             if (val <= 0)
00063               ptmp[i] = nan_val;
00064             else
00065               ptmp[i] = val;
00066           }
00067       else
00068         for (octave_idx_type i = 0; i < a.numel (); i++)
00069           {
00070             double val = static_cast<double> (pa[i]);
00071             if (val <= 0)
00072               ptmp[i] = nan_val;
00073             else
00074               ptmp[i] = val;
00075           }
00076     }
00077   else
00078     {
00079       if (zero_based)
00080         for (octave_idx_type i = 0; i < a.numel (); i++)
00081           ptmp[i] = static_cast<double>
00082             (pa[i] + static_cast<octave_idx_type> (1));
00083       else
00084         for (octave_idx_type i = 0; i < a.numel (); i++)
00085           ptmp[i] = static_cast<double> (pa[i]);
00086     }
00087 }
00088 
00089 NDArray::NDArray (const charNDArray& a)
00090   : MArray<double> (a.dims ())
00091 {
00092   octave_idx_type n = a.numel ();
00093   for (octave_idx_type i = 0; i < n; i++)
00094     xelem (i) = static_cast<unsigned char> (a(i));
00095 }
00096 
00097 #if defined (HAVE_FFTW)
00098 
00099 ComplexNDArray
00100 NDArray::fourier (int dim) const
00101 {
00102   dim_vector dv = dims ();
00103 
00104   if (dim > dv.length () || dim < 0)
00105     return ComplexNDArray ();
00106 
00107   octave_idx_type stride = 1;
00108   octave_idx_type n = dv(dim);
00109 
00110   for (int i = 0; i < dim; i++)
00111     stride *= dv(i);
00112 
00113   octave_idx_type howmany = numel () / dv (dim);
00114   howmany = (stride == 1 ? howmany : (howmany > stride ? stride : howmany));
00115   octave_idx_type nloop = (stride == 1 ? 1 : numel () / dv (dim) / stride);
00116   octave_idx_type dist = (stride == 1 ? n : 1);
00117 
00118   const double *in (fortran_vec ());
00119   ComplexNDArray retval (dv);
00120   Complex *out (retval.fortran_vec ());
00121 
00122   // Need to be careful here about the distance between fft's
00123   for (octave_idx_type k = 0; k < nloop; k++)
00124     octave_fftw::fft (in + k * stride * n, out + k * stride * n,
00125                       n, howmany, stride, dist);
00126 
00127   return retval;
00128 }
00129 
00130 ComplexNDArray
00131 NDArray::ifourier (int dim) const
00132 {
00133   dim_vector dv = dims ();
00134 
00135   if (dim > dv.length () || dim < 0)
00136     return ComplexNDArray ();
00137 
00138   octave_idx_type stride = 1;
00139   octave_idx_type n = dv(dim);
00140 
00141   for (int i = 0; i < dim; i++)
00142     stride *= dv(i);
00143 
00144   octave_idx_type howmany = numel () / dv (dim);
00145   howmany = (stride == 1 ? howmany : (howmany > stride ? stride : howmany));
00146   octave_idx_type nloop = (stride == 1 ? 1 : numel () / dv (dim) / stride);
00147   octave_idx_type dist = (stride == 1 ? n : 1);
00148 
00149   ComplexNDArray retval (*this);
00150   Complex *out (retval.fortran_vec ());
00151 
00152   // Need to be careful here about the distance between fft's
00153   for (octave_idx_type k = 0; k < nloop; k++)
00154     octave_fftw::ifft (out + k * stride * n, out + k * stride * n,
00155                       n, howmany, stride, dist);
00156 
00157   return retval;
00158 }
00159 
00160 ComplexNDArray
00161 NDArray::fourier2d (void) const
00162 {
00163   dim_vector dv = dims();
00164   if (dv.length () < 2)
00165     return ComplexNDArray ();
00166 
00167   dim_vector dv2(dv(0), dv(1));
00168   const double *in = fortran_vec ();
00169   ComplexNDArray retval (dv);
00170   Complex *out = retval.fortran_vec ();
00171   octave_idx_type howmany = numel() / dv(0) / dv(1);
00172   octave_idx_type dist = dv(0) * dv(1);
00173 
00174   for (octave_idx_type i=0; i < howmany; i++)
00175     octave_fftw::fftNd (in + i*dist, out + i*dist, 2, dv2);
00176 
00177   return retval;
00178 }
00179 
00180 ComplexNDArray
00181 NDArray::ifourier2d (void) const
00182 {
00183   dim_vector dv = dims();
00184   if (dv.length () < 2)
00185     return ComplexNDArray ();
00186 
00187   dim_vector dv2(dv(0), dv(1));
00188   ComplexNDArray retval (*this);
00189   Complex *out = retval.fortran_vec ();
00190   octave_idx_type howmany = numel() / dv(0) / dv(1);
00191   octave_idx_type dist = dv(0) * dv(1);
00192 
00193   for (octave_idx_type i=0; i < howmany; i++)
00194     octave_fftw::ifftNd (out + i*dist, out + i*dist, 2, dv2);
00195 
00196   return retval;
00197 }
00198 
00199 ComplexNDArray
00200 NDArray::fourierNd (void) const
00201 {
00202   dim_vector dv = dims ();
00203   int rank = dv.length ();
00204 
00205   const double *in (fortran_vec ());
00206   ComplexNDArray retval (dv);
00207   Complex *out (retval.fortran_vec ());
00208 
00209   octave_fftw::fftNd (in, out, rank, dv);
00210 
00211   return retval;
00212 }
00213 
00214 ComplexNDArray
00215 NDArray::ifourierNd (void) const
00216 {
00217   dim_vector dv = dims ();
00218   int rank = dv.length ();
00219 
00220   ComplexNDArray tmp (*this);
00221   Complex *in (tmp.fortran_vec ());
00222   ComplexNDArray retval (dv);
00223   Complex *out (retval.fortran_vec ());
00224 
00225   octave_fftw::ifftNd (in, out, rank, dv);
00226 
00227   return retval;
00228 }
00229 
00230 #else
00231 
00232 extern "C"
00233 {
00234   // Note that the original complex fft routines were not written for
00235   // double complex arguments.  They have been modified by adding an
00236   // implicit double precision (a-h,o-z) statement at the beginning of
00237   // each subroutine.
00238 
00239   F77_RET_T
00240   F77_FUNC (zffti, ZFFTI) (const octave_idx_type&, Complex*);
00241 
00242   F77_RET_T
00243   F77_FUNC (zfftf, ZFFTF) (const octave_idx_type&, Complex*, Complex*);
00244 
00245   F77_RET_T
00246   F77_FUNC (zfftb, ZFFTB) (const octave_idx_type&, Complex*, Complex*);
00247 }
00248 
00249 ComplexNDArray
00250 NDArray::fourier (int dim) const
00251 {
00252   dim_vector dv = dims ();
00253 
00254   if (dim > dv.length () || dim < 0)
00255     return ComplexNDArray ();
00256 
00257   ComplexNDArray retval (dv);
00258   octave_idx_type npts = dv(dim);
00259   octave_idx_type nn = 4*npts+15;
00260   Array<Complex> wsave (nn);
00261   Complex *pwsave = wsave.fortran_vec ();
00262 
00263   OCTAVE_LOCAL_BUFFER (Complex, tmp, npts);
00264 
00265   octave_idx_type stride = 1;
00266 
00267   for (int i = 0; i < dim; i++)
00268     stride *= dv(i);
00269 
00270   octave_idx_type howmany = numel () / npts;
00271   howmany = (stride == 1 ? howmany : (howmany > stride ? stride : howmany));
00272   octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
00273   octave_idx_type dist = (stride == 1 ? npts : 1);
00274 
00275   F77_FUNC (zffti, ZFFTI) (npts, pwsave);
00276 
00277   for (octave_idx_type k = 0; k < nloop; k++)
00278     {
00279       for (octave_idx_type j = 0; j < howmany; j++)
00280         {
00281           octave_quit ();
00282 
00283           for (octave_idx_type i = 0; i < npts; i++)
00284             tmp[i] = elem((i + k*npts)*stride + j*dist);
00285 
00286           F77_FUNC (zfftf, ZFFTF) (npts, tmp, pwsave);
00287 
00288           for (octave_idx_type i = 0; i < npts; i++)
00289             retval ((i + k*npts)*stride + j*dist) = tmp[i];
00290         }
00291     }
00292 
00293   return retval;
00294 }
00295 
00296 ComplexNDArray
00297 NDArray::ifourier (int dim) const
00298 {
00299   dim_vector dv = dims ();
00300 
00301   if (dim > dv.length () || dim < 0)
00302     return ComplexNDArray ();
00303 
00304   ComplexNDArray retval (dv);
00305   octave_idx_type npts = dv(dim);
00306   octave_idx_type nn = 4*npts+15;
00307   Array<Complex> wsave (nn);
00308   Complex *pwsave = wsave.fortran_vec ();
00309 
00310   OCTAVE_LOCAL_BUFFER (Complex, tmp, npts);
00311 
00312   octave_idx_type stride = 1;
00313 
00314   for (int i = 0; i < dim; i++)
00315     stride *= dv(i);
00316 
00317   octave_idx_type howmany = numel () / npts;
00318   howmany = (stride == 1 ? howmany : (howmany > stride ? stride : howmany));
00319   octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
00320   octave_idx_type dist = (stride == 1 ? npts : 1);
00321 
00322   F77_FUNC (zffti, ZFFTI) (npts, pwsave);
00323 
00324   for (octave_idx_type k = 0; k < nloop; k++)
00325     {
00326       for (octave_idx_type j = 0; j < howmany; j++)
00327         {
00328           octave_quit ();
00329 
00330           for (octave_idx_type i = 0; i < npts; i++)
00331             tmp[i] = elem((i + k*npts)*stride + j*dist);
00332 
00333           F77_FUNC (zfftb, ZFFTB) (npts, tmp, pwsave);
00334 
00335           for (octave_idx_type i = 0; i < npts; i++)
00336             retval ((i + k*npts)*stride + j*dist) = tmp[i] /
00337               static_cast<double> (npts);
00338         }
00339     }
00340 
00341   return retval;
00342 }
00343 
00344 ComplexNDArray
00345 NDArray::fourier2d (void) const
00346 {
00347   dim_vector dv = dims();
00348   dim_vector dv2 (dv(0), dv(1));
00349   int rank = 2;
00350   ComplexNDArray retval (*this);
00351   octave_idx_type stride = 1;
00352 
00353   for (int i = 0; i < rank; i++)
00354     {
00355       octave_idx_type npts = dv2(i);
00356       octave_idx_type nn = 4*npts+15;
00357       Array<Complex> wsave (nn);
00358       Complex *pwsave = wsave.fortran_vec ();
00359       Array<Complex> row (npts);
00360       Complex *prow = row.fortran_vec ();
00361 
00362       octave_idx_type howmany = numel () / npts;
00363       howmany = (stride == 1 ? howmany :
00364                  (howmany > stride ? stride : howmany));
00365       octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
00366       octave_idx_type dist = (stride == 1 ? npts : 1);
00367 
00368       F77_FUNC (zffti, ZFFTI) (npts, pwsave);
00369 
00370       for (octave_idx_type k = 0; k < nloop; k++)
00371         {
00372           for (octave_idx_type j = 0; j < howmany; j++)
00373             {
00374               octave_quit ();
00375 
00376               for (octave_idx_type l = 0; l < npts; l++)
00377                 prow[l] = retval ((l + k*npts)*stride + j*dist);
00378 
00379               F77_FUNC (zfftf, ZFFTF) (npts, prow, pwsave);
00380 
00381               for (octave_idx_type l = 0; l < npts; l++)
00382                 retval ((l + k*npts)*stride + j*dist) = prow[l];
00383             }
00384         }
00385 
00386       stride *= dv2(i);
00387     }
00388 
00389   return retval;
00390 }
00391 
00392 ComplexNDArray
00393 NDArray::ifourier2d (void) const
00394 {
00395   dim_vector dv = dims();
00396   dim_vector dv2 (dv(0), dv(1));
00397   int rank = 2;
00398   ComplexNDArray retval (*this);
00399   octave_idx_type stride = 1;
00400 
00401   for (int i = 0; i < rank; i++)
00402     {
00403       octave_idx_type npts = dv2(i);
00404       octave_idx_type nn = 4*npts+15;
00405       Array<Complex> wsave (nn);
00406       Complex *pwsave = wsave.fortran_vec ();
00407       Array<Complex> row (npts);
00408       Complex *prow = row.fortran_vec ();
00409 
00410       octave_idx_type howmany = numel () / npts;
00411       howmany = (stride == 1 ? howmany :
00412                  (howmany > stride ? stride : howmany));
00413       octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
00414       octave_idx_type dist = (stride == 1 ? npts : 1);
00415 
00416       F77_FUNC (zffti, ZFFTI) (npts, pwsave);
00417 
00418       for (octave_idx_type k = 0; k < nloop; k++)
00419         {
00420           for (octave_idx_type j = 0; j < howmany; j++)
00421             {
00422               octave_quit ();
00423 
00424               for (octave_idx_type l = 0; l < npts; l++)
00425                 prow[l] = retval ((l + k*npts)*stride + j*dist);
00426 
00427               F77_FUNC (zfftb, ZFFTB) (npts, prow, pwsave);
00428 
00429               for (octave_idx_type l = 0; l < npts; l++)
00430                 retval ((l + k*npts)*stride + j*dist) = prow[l] /
00431                   static_cast<double> (npts);
00432             }
00433         }
00434 
00435       stride *= dv2(i);
00436     }
00437 
00438   return retval;
00439 }
00440 
00441 ComplexNDArray
00442 NDArray::fourierNd (void) const
00443 {
00444   dim_vector dv = dims ();
00445   int rank = dv.length ();
00446   ComplexNDArray retval (*this);
00447   octave_idx_type stride = 1;
00448 
00449   for (int i = 0; i < rank; i++)
00450     {
00451       octave_idx_type npts = dv(i);
00452       octave_idx_type nn = 4*npts+15;
00453       Array<Complex> wsave (nn);
00454       Complex *pwsave = wsave.fortran_vec ();
00455       Array<Complex> row (npts);
00456       Complex *prow = row.fortran_vec ();
00457 
00458       octave_idx_type howmany = numel () / npts;
00459       howmany = (stride == 1 ? howmany :
00460                  (howmany > stride ? stride : howmany));
00461       octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
00462       octave_idx_type dist = (stride == 1 ? npts : 1);
00463 
00464       F77_FUNC (zffti, ZFFTI) (npts, pwsave);
00465 
00466       for (octave_idx_type k = 0; k < nloop; k++)
00467         {
00468           for (octave_idx_type j = 0; j < howmany; j++)
00469             {
00470               octave_quit ();
00471 
00472               for (octave_idx_type l = 0; l < npts; l++)
00473                 prow[l] = retval ((l + k*npts)*stride + j*dist);
00474 
00475               F77_FUNC (zfftf, ZFFTF) (npts, prow, pwsave);
00476 
00477               for (octave_idx_type l = 0; l < npts; l++)
00478                 retval ((l + k*npts)*stride + j*dist) = prow[l];
00479             }
00480         }
00481 
00482       stride *= dv(i);
00483     }
00484 
00485   return retval;
00486 }
00487 
00488 ComplexNDArray
00489 NDArray::ifourierNd (void) const
00490 {
00491   dim_vector dv = dims ();
00492   int rank = dv.length ();
00493   ComplexNDArray retval (*this);
00494   octave_idx_type stride = 1;
00495 
00496   for (int i = 0; i < rank; i++)
00497     {
00498       octave_idx_type npts = dv(i);
00499       octave_idx_type nn = 4*npts+15;
00500       Array<Complex> wsave (nn);
00501       Complex *pwsave = wsave.fortran_vec ();
00502       Array<Complex> row (npts);
00503       Complex *prow = row.fortran_vec ();
00504 
00505       octave_idx_type howmany = numel () / npts;
00506       howmany = (stride == 1 ? howmany :
00507                  (howmany > stride ? stride : howmany));
00508       octave_idx_type nloop = (stride == 1 ? 1 : numel () / npts / stride);
00509       octave_idx_type dist = (stride == 1 ? npts : 1);
00510 
00511       F77_FUNC (zffti, ZFFTI) (npts, pwsave);
00512 
00513       for (octave_idx_type k = 0; k < nloop; k++)
00514         {
00515           for (octave_idx_type j = 0; j < howmany; j++)
00516             {
00517               octave_quit ();
00518 
00519               for (octave_idx_type l = 0; l < npts; l++)
00520                 prow[l] = retval ((l + k*npts)*stride + j*dist);
00521 
00522               F77_FUNC (zfftb, ZFFTB) (npts, prow, pwsave);
00523 
00524               for (octave_idx_type l = 0; l < npts; l++)
00525                 retval ((l + k*npts)*stride + j*dist) = prow[l] /
00526                   static_cast<double> (npts);
00527             }
00528         }
00529 
00530       stride *= dv(i);
00531     }
00532 
00533   return retval;
00534 }
00535 
00536 #endif
00537 
00538 // unary operations
00539 
00540 boolNDArray
00541 NDArray::operator ! (void) const
00542 {
00543   if (any_element_is_nan ())
00544     gripe_nan_to_logical_conversion ();
00545 
00546   return do_mx_unary_op<bool, double> (*this, mx_inline_not);
00547 }
00548 
00549 bool
00550 NDArray::any_element_is_negative (bool neg_zero) const
00551 {
00552   return (neg_zero ? test_all (xnegative_sign)
00553           : do_mx_check<double> (*this, mx_inline_any_negative));
00554 }
00555 
00556 bool
00557 NDArray::any_element_is_positive (bool neg_zero) const
00558 {
00559   return (neg_zero ? test_all (xpositive_sign)
00560           : do_mx_check<double> (*this, mx_inline_any_positive));
00561 }
00562 
00563 bool
00564 NDArray::any_element_is_nan (void) const
00565 {
00566   return do_mx_check<double> (*this, mx_inline_any_nan);
00567 }
00568 
00569 bool
00570 NDArray::any_element_is_inf_or_nan (void) const
00571 {
00572   return ! do_mx_check<double> (*this, mx_inline_all_finite);
00573 }
00574 
00575 bool
00576 NDArray::any_element_not_one_or_zero (void) const
00577 {
00578   return ! test_all (xis_one_or_zero);
00579 }
00580 
00581 bool
00582 NDArray::all_elements_are_zero (void) const
00583 {
00584   return test_all (xis_zero);
00585 }
00586 
00587 bool
00588 NDArray::all_elements_are_int_or_inf_or_nan (void) const
00589 {
00590   return test_all (xis_int_or_inf_or_nan);
00591 }
00592 
00593 // Return nonzero if any element of M is not an integer.  Also extract
00594 // the largest and smallest values and return them in MAX_VAL and MIN_VAL.
00595 
00596 bool
00597 NDArray::all_integers (double& max_val, double& min_val) const
00598 {
00599   octave_idx_type nel = nelem ();
00600 
00601   if (nel > 0)
00602     {
00603       max_val = elem (0);
00604       min_val = elem (0);
00605     }
00606   else
00607     return false;
00608 
00609   for (octave_idx_type i = 0; i < nel; i++)
00610     {
00611       double val = elem (i);
00612 
00613       if (val > max_val)
00614         max_val = val;
00615 
00616       if (val < min_val)
00617         min_val = val;
00618 
00619       if (! xisinteger (val))
00620         return false;
00621     }
00622 
00623   return true;
00624 }
00625 
00626 bool
00627 NDArray::all_integers (void) const
00628 {
00629   return test_all (xisinteger);
00630 }
00631 
00632 bool
00633 NDArray::too_large_for_float (void) const
00634 {
00635   return test_all (xtoo_large_for_float);
00636 }
00637 
00638 // FIXME -- this is not quite the right thing.
00639 
00640 boolNDArray
00641 NDArray::all (int dim) const
00642 {
00643   return do_mx_red_op<bool, double> (*this, dim, mx_inline_all);
00644 }
00645 
00646 boolNDArray
00647 NDArray::any (int dim) const
00648 {
00649   return do_mx_red_op<bool, double> (*this, dim, mx_inline_any);
00650 }
00651 
00652 NDArray
00653 NDArray::cumprod (int dim) const
00654 {
00655   return do_mx_cum_op<double, double> (*this, dim, mx_inline_cumprod);
00656 }
00657 
00658 NDArray
00659 NDArray::cumsum (int dim) const
00660 {
00661   return do_mx_cum_op<double, double> (*this, dim, mx_inline_cumsum);
00662 }
00663 
00664 NDArray
00665 NDArray::prod (int dim) const
00666 {
00667   return do_mx_red_op<double, double> (*this, dim, mx_inline_prod);
00668 }
00669 
00670 NDArray
00671 NDArray::sum (int dim) const
00672 {
00673   return do_mx_red_op<double, double> (*this, dim, mx_inline_sum);
00674 }
00675 
00676 NDArray
00677 NDArray::xsum (int dim) const
00678 {
00679   return do_mx_red_op<double, double> (*this, dim, mx_inline_xsum);
00680 }
00681 
00682 NDArray
00683 NDArray::sumsq (int dim) const
00684 {
00685   return do_mx_red_op<double, double> (*this, dim, mx_inline_sumsq);
00686 }
00687 
00688 NDArray
00689 NDArray::max (int dim) const
00690 {
00691   return do_mx_minmax_op<double> (*this, dim, mx_inline_max);
00692 }
00693 
00694 NDArray
00695 NDArray::max (Array<octave_idx_type>& idx_arg, int dim) const
00696 {
00697   return do_mx_minmax_op<double> (*this, idx_arg, dim, mx_inline_max);
00698 }
00699 
00700 NDArray
00701 NDArray::min (int dim) const
00702 {
00703   return do_mx_minmax_op<double> (*this, dim, mx_inline_min);
00704 }
00705 
00706 NDArray
00707 NDArray::min (Array<octave_idx_type>& idx_arg, int dim) const
00708 {
00709   return do_mx_minmax_op<double> (*this, idx_arg, dim, mx_inline_min);
00710 }
00711 
00712 NDArray
00713 NDArray::cummax (int dim) const
00714 {
00715   return do_mx_cumminmax_op<double> (*this, dim, mx_inline_cummax);
00716 }
00717 
00718 NDArray
00719 NDArray::cummax (Array<octave_idx_type>& idx_arg, int dim) const
00720 {
00721   return do_mx_cumminmax_op<double> (*this, idx_arg, dim, mx_inline_cummax);
00722 }
00723 
00724 NDArray
00725 NDArray::cummin (int dim) const
00726 {
00727   return do_mx_cumminmax_op<double> (*this, dim, mx_inline_cummin);
00728 }
00729 
00730 NDArray
00731 NDArray::cummin (Array<octave_idx_type>& idx_arg, int dim) const
00732 {
00733   return do_mx_cumminmax_op<double> (*this, idx_arg, dim, mx_inline_cummin);
00734 }
00735 
00736 NDArray
00737 NDArray::diff (octave_idx_type order, int dim) const
00738 {
00739   return do_mx_diff_op<double> (*this, dim, order, mx_inline_diff);
00740 }
00741 
00742 NDArray
00743 NDArray::concat (const NDArray& rb, const Array<octave_idx_type>& ra_idx)
00744 {
00745   if (rb.numel () > 0)
00746     insert (rb, ra_idx);
00747   return *this;
00748 }
00749 
00750 ComplexNDArray
00751 NDArray::concat (const ComplexNDArray& rb, const Array<octave_idx_type>& ra_idx)
00752 {
00753   ComplexNDArray retval (*this);
00754   if (rb.numel () > 0)
00755     retval.insert (rb, ra_idx);
00756   return retval;
00757 }
00758 
00759 charNDArray
00760 NDArray::concat (const charNDArray& rb, const Array<octave_idx_type>& ra_idx)
00761 {
00762   charNDArray retval (dims ());
00763   octave_idx_type nel = numel ();
00764 
00765   for (octave_idx_type i = 0; i < nel; i++)
00766     {
00767       double d = elem (i);
00768 
00769       if (xisnan (d))
00770         {
00771           (*current_liboctave_error_handler)
00772             ("invalid conversion from NaN to character");
00773           return retval;
00774         }
00775       else
00776         {
00777           octave_idx_type ival = NINTbig (d);
00778 
00779           if (ival < 0 || ival > UCHAR_MAX)
00780             // FIXME -- is there something
00781             // better we could do? Should we warn the user?
00782             ival = 0;
00783 
00784           retval.elem (i) = static_cast<char>(ival);
00785         }
00786     }
00787 
00788   if (rb.numel () == 0)
00789     return retval;
00790 
00791   retval.insert (rb, ra_idx);
00792   return retval;
00793 }
00794 
00795 NDArray
00796 real (const ComplexNDArray& a)
00797 {
00798   return do_mx_unary_op<double, Complex> (a, mx_inline_real);
00799 }
00800 
00801 NDArray
00802 imag (const ComplexNDArray& a)
00803 {
00804   return do_mx_unary_op<double, Complex> (a, mx_inline_imag);
00805 }
00806 
00807 NDArray&
00808 NDArray::insert (const NDArray& a, octave_idx_type r, octave_idx_type c)
00809 {
00810   Array<double>::insert (a, r, c);
00811   return *this;
00812 }
00813 
00814 NDArray&
00815 NDArray::insert (const NDArray& a, const Array<octave_idx_type>& ra_idx)
00816 {
00817   Array<double>::insert (a, ra_idx);
00818   return *this;
00819 }
00820 
00821 NDArray
00822 NDArray::abs (void) const
00823 {
00824   return do_mx_unary_map<double, double, std::abs> (*this);
00825 }
00826 
00827 boolNDArray
00828 NDArray::isnan (void) const
00829 {
00830   return do_mx_unary_map<bool, double, xisnan> (*this);
00831 }
00832 
00833 boolNDArray
00834 NDArray::isinf (void) const
00835 {
00836   return do_mx_unary_map<bool, double, xisinf> (*this);
00837 }
00838 
00839 boolNDArray
00840 NDArray::isfinite (void) const
00841 {
00842   return do_mx_unary_map<bool, double, xfinite> (*this);
00843 }
00844 
00845 Matrix
00846 NDArray::matrix_value (void) const
00847 {
00848   Matrix retval;
00849 
00850   if (ndims () == 2)
00851       retval = Matrix (Array<double> (*this));
00852   else
00853     (*current_liboctave_error_handler)
00854       ("invalid conversion of NDArray to Matrix");
00855 
00856   return retval;
00857 }
00858 
00859 void
00860 NDArray::increment_index (Array<octave_idx_type>& ra_idx,
00861                           const dim_vector& dimensions,
00862                           int start_dimension)
00863 {
00864   ::increment_index (ra_idx, dimensions, start_dimension);
00865 }
00866 
00867 octave_idx_type
00868 NDArray::compute_index (Array<octave_idx_type>& ra_idx,
00869                         const dim_vector& dimensions)
00870 {
00871   return ::compute_index (ra_idx, dimensions);
00872 }
00873 
00874 NDArray
00875 NDArray::diag (octave_idx_type k) const
00876 {
00877   return MArray<double>::diag (k);
00878 }
00879 
00880 // This contains no information on the array structure !!!
00881 std::ostream&
00882 operator << (std::ostream& os, const NDArray& a)
00883 {
00884   octave_idx_type nel = a.nelem ();
00885 
00886   for (octave_idx_type i = 0; i < nel; i++)
00887     {
00888       os << " ";
00889       octave_write_double (os, a.elem (i));
00890       os << "\n";
00891     }
00892   return os;
00893 }
00894 
00895 std::istream&
00896 operator >> (std::istream& is, NDArray& a)
00897 {
00898   octave_idx_type nel = a.nelem ();
00899 
00900   if (nel > 0)
00901     {
00902       double tmp;
00903       for (octave_idx_type i = 0; i < nel; i++)
00904           {
00905             tmp = octave_read_value<double> (is);
00906             if (is)
00907               a.elem (i) = tmp;
00908             else
00909               goto done;
00910           }
00911     }
00912 
00913  done:
00914 
00915   return is;
00916 }
00917 
00918 MINMAX_FCNS (NDArray, double)
00919 
00920 NDS_CMP_OPS (NDArray, double)
00921 NDS_BOOL_OPS (NDArray, double)
00922 
00923 SND_CMP_OPS (double, NDArray)
00924 SND_BOOL_OPS (double, NDArray)
00925 
00926 NDND_CMP_OPS (NDArray, NDArray)
00927 NDND_BOOL_OPS (NDArray, NDArray)
00928 
00929 BSXFUN_STDOP_DEFS_MXLOOP (NDArray)
00930 BSXFUN_STDREL_DEFS_MXLOOP (NDArray)
00931 
00932 BSXFUN_OP_DEF_MXLOOP (pow, NDArray, mx_inline_pow)
00933 BSXFUN_OP2_DEF_MXLOOP (pow, ComplexNDArray, ComplexNDArray,
00934                        NDArray, mx_inline_pow)
00935 BSXFUN_OP2_DEF_MXLOOP (pow, ComplexNDArray, NDArray,
00936                        ComplexNDArray, mx_inline_pow)
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines