MArray.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1993-2012 John W. Eaton
00004 Copyright (C) 2009 VZLU Prague
00005 
00006 This file is part of Octave.
00007 
00008 Octave is free software; you can redistribute it and/or modify it
00009 under the terms of the GNU General Public License as published by the
00010 Free Software Foundation; either version 3 of the License, or (at your
00011 option) any later version.
00012 
00013 Octave is distributed in the hope that it will be useful, but WITHOUT
00014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00015 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00016 for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with Octave; see the file COPYING.  If not, see
00020 <http://www.gnu.org/licenses/>.
00021 
00022 */
00023 
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027 
00028 #include "MArray.h"
00029 #include "Array-util.h"
00030 #include "lo-error.h"
00031 
00032 #include "MArray-defs.h"
00033 #include "mx-inlines.cc"
00034 
00035 template <class T>
00036 struct _idxadds_helper
00037 {
00038   T *array;
00039   T val;
00040   _idxadds_helper (T *a, T v) : array (a), val (v) { }
00041   void operator () (octave_idx_type i)
00042     { array[i] += val; }
00043 };
00044 
00045 template <class T>
00046 struct _idxadda_helper
00047 {
00048   T *array;
00049   const T *vals;
00050   _idxadda_helper (T *a, const T *v) : array (a), vals (v) { }
00051   void operator () (octave_idx_type i)
00052     { array[i] += *vals++; }
00053 };
00054 
00055 template <class T>
00056 void
00057 MArray<T>::idx_add (const idx_vector& idx, T val)
00058 {
00059   octave_idx_type n = this->length ();
00060   octave_idx_type ext = idx.extent (n);
00061   if (ext > n)
00062     {
00063       this->resize1 (ext);
00064       n = ext;
00065     }
00066 
00067   octave_quit ();
00068 
00069   octave_idx_type len = idx.length (n);
00070   idx.loop (len, _idxadds_helper<T> (this->fortran_vec (), val));
00071 }
00072 
00073 template <class T>
00074 void
00075 MArray<T>::idx_add (const idx_vector& idx, const MArray<T>& vals)
00076 {
00077   octave_idx_type n = this->length ();
00078   octave_idx_type ext = idx.extent (n);
00079   if (ext > n)
00080     {
00081       this->resize1 (ext);
00082       n = ext;
00083     }
00084 
00085   octave_quit ();
00086 
00087   octave_idx_type len = std::min (idx.length (n), vals.length ());
00088   idx.loop (len, _idxadda_helper<T> (this->fortran_vec (), vals.data ()));
00089 }
00090 
00091 template <class T, T op (typename ref_param<T>::type, typename ref_param<T>::type)>
00092 struct _idxbinop_helper
00093 {
00094   T *array;
00095   const T *vals;
00096   _idxbinop_helper (T *a, const T *v) : array (a), vals (v) { }
00097   void operator () (octave_idx_type i)
00098     { array[i] = op (array[i], *vals++); }
00099 };
00100 
00101 template <class T>
00102 void
00103 MArray<T>::idx_min (const idx_vector& idx, const MArray<T>& vals)
00104 {
00105   octave_idx_type n = this->length ();
00106   octave_idx_type ext = idx.extent (n);
00107   if (ext > n)
00108     {
00109       this->resize1 (ext);
00110       n = ext;
00111     }
00112 
00113   octave_quit ();
00114 
00115   octave_idx_type len = std::min (idx.length (n), vals.length ());
00116   idx.loop (len, _idxbinop_helper<T, xmin> (this->fortran_vec (), vals.data ()));
00117 }
00118 
00119 template <class T>
00120 void
00121 MArray<T>::idx_max (const idx_vector& idx, const MArray<T>& vals)
00122 {
00123   octave_idx_type n = this->length ();
00124   octave_idx_type ext = idx.extent (n);
00125   if (ext > n)
00126     {
00127       this->resize1 (ext);
00128       n = ext;
00129     }
00130 
00131   octave_quit ();
00132 
00133   octave_idx_type len = std::min (idx.length (n), vals.length ());
00134   idx.loop (len, _idxbinop_helper<T, xmax> (this->fortran_vec (), vals.data ()));
00135 }
00136 
00137 #include <iostream>
00138 
00139 template <class T>
00140 void MArray<T>::idx_add_nd (const idx_vector& idx, const MArray<T>& vals, int dim)
00141 {
00142   int nd = std::max (this->ndims (), vals.ndims ());
00143   if (dim < 0)
00144     dim = vals.dims ().first_non_singleton ();
00145   else if (dim > nd)
00146     nd = dim;
00147 
00148   // Check dimensions.
00149   dim_vector ddv = Array<T>::dims ().redim (nd);
00150   dim_vector sdv = vals.dims ().redim (nd);
00151 
00152   octave_idx_type ext = idx.extent (ddv (dim));
00153 
00154   if (ext > ddv(dim))
00155     {
00156       ddv(dim) = ext;
00157       Array<T>::resize (ddv);
00158       ext = ddv(dim);
00159     }
00160 
00161   octave_idx_type l,n,u,ns;
00162   get_extent_triplet (ddv, dim, l, n, u);
00163   ns = sdv(dim);
00164 
00165   sdv(dim) = ddv(dim) = 0;
00166   if (ddv != sdv)
00167     (*current_liboctave_error_handler)
00168       ("accumdim: dimension mismatch");
00169 
00170   T *dst = Array<T>::fortran_vec ();
00171   const T *src = vals.data ();
00172   octave_idx_type len = idx.length (ns);
00173 
00174   if (l == 1)
00175     {
00176       for (octave_idx_type j = 0; j < u; j++)
00177         {
00178           octave_quit ();
00179 
00180           idx.loop (len, _idxadda_helper<T> (dst + j*n, src + j*ns));
00181         }
00182     }
00183   else
00184     {
00185       for (octave_idx_type j = 0; j < u; j++)
00186         {
00187           octave_quit ();
00188           for (octave_idx_type i = 0; i < len; i++)
00189             {
00190               octave_idx_type k = idx(i);
00191 
00192               mx_inline_add2 (l, dst + l*k, src + l*i);
00193             }
00194 
00195           dst += l*n;
00196           src += l*ns;
00197         }
00198     }
00199 }
00200 
00201 // N-dimensional array with math ops.
00202 template <class T>
00203 void
00204 MArray<T>::changesign (void)
00205 {
00206   if (Array<T>::is_shared ())
00207     *this = - *this;
00208   else
00209     do_mx_inplace_op<T> (*this, mx_inline_uminus2);
00210 }
00211 
00212 // Element by element MArray by scalar ops.
00213 
00214 template <class T>
00215 MArray<T>&
00216 operator += (MArray<T>& a, const T& s)
00217 {
00218   if (a.is_shared ())
00219     a = a + s;
00220   else
00221     do_ms_inplace_op<T, T> (a, s, mx_inline_add2);
00222   return a;
00223 }
00224 
00225 template <class T>
00226 MArray<T>&
00227 operator -= (MArray<T>& a, const T& s)
00228 {
00229   if (a.is_shared ())
00230     a = a - s;
00231   else
00232     do_ms_inplace_op<T, T> (a, s, mx_inline_sub2);
00233   return a;
00234 }
00235 
00236 template <class T>
00237 MArray<T>&
00238 operator *= (MArray<T>& a, const T& s)
00239 {
00240   if (a.is_shared ())
00241     a = a * s;
00242   else
00243     do_ms_inplace_op<T, T> (a, s, mx_inline_mul2);
00244   return a;
00245 }
00246 
00247 template <class T>
00248 MArray<T>&
00249 operator /= (MArray<T>& a, const T& s)
00250 {
00251   if (a.is_shared ())
00252     a = a / s;
00253   else
00254     do_ms_inplace_op<T, T> (a, s, mx_inline_div2);
00255   return a;
00256 }
00257 
00258 // Element by element MArray by MArray ops.
00259 
00260 template <class T>
00261 MArray<T>&
00262 operator += (MArray<T>& a, const MArray<T>& b)
00263 {
00264   if (a.is_shared ())
00265     a = a + b;
00266   else
00267     do_mm_inplace_op<T, T> (a, b, mx_inline_add2, mx_inline_add2, "+=");
00268   return a;
00269 }
00270 
00271 template <class T>
00272 MArray<T>&
00273 operator -= (MArray<T>& a, const MArray<T>& b)
00274 {
00275   if (a.is_shared ())
00276     a = a - b;
00277   else
00278     do_mm_inplace_op<T, T> (a, b, mx_inline_sub2, mx_inline_sub2, "-=");
00279   return a;
00280 }
00281 
00282 
00283 template <class T>
00284 MArray<T>&
00285 product_eq (MArray<T>& a, const MArray<T>& b)
00286 {
00287   if (a.is_shared ())
00288     return a = product (a, b);
00289   else
00290     do_mm_inplace_op<T, T> (a, b, mx_inline_mul2, mx_inline_mul2, ".*=");
00291   return a;
00292 }
00293 
00294 template <class T>
00295 MArray<T>&
00296 quotient_eq (MArray<T>& a, const MArray<T>& b)
00297 {
00298   if (a.is_shared ())
00299     return a = quotient (a, b);
00300   else
00301     do_mm_inplace_op<T, T> (a, b, mx_inline_div2, mx_inline_div2, "./=");
00302   return a;
00303 }
00304 
00305 // Element by element MArray by scalar ops.
00306 
00307 #define MARRAY_NDS_OP(OP, FN) \
00308   template <class T> \
00309   MArray<T> \
00310   operator OP (const MArray<T>& a, const T& s) \
00311   { \
00312     return do_ms_binary_op<T, T, T> (a, s, FN); \
00313   }
00314 
00315 MARRAY_NDS_OP (+, mx_inline_add)
00316 MARRAY_NDS_OP (-, mx_inline_sub)
00317 MARRAY_NDS_OP (*, mx_inline_mul)
00318 MARRAY_NDS_OP (/, mx_inline_div)
00319 
00320 // Element by element scalar by MArray ops.
00321 
00322 #define MARRAY_SND_OP(OP, FN) \
00323   template <class T> \
00324   MArray<T> \
00325   operator OP (const T& s, const MArray<T>& a) \
00326   { \
00327     return do_sm_binary_op<T, T, T> (s, a, FN); \
00328   }
00329 
00330 MARRAY_SND_OP (+, mx_inline_add)
00331 MARRAY_SND_OP (-, mx_inline_sub)
00332 MARRAY_SND_OP (*, mx_inline_mul)
00333 MARRAY_SND_OP (/, mx_inline_div)
00334 
00335 // Element by element MArray by MArray ops.
00336 
00337 #define MARRAY_NDND_OP(FCN, OP, FN) \
00338   template <class T> \
00339   MArray<T> \
00340   FCN (const MArray<T>& a, const MArray<T>& b) \
00341   { \
00342     return do_mm_binary_op<T, T, T> (a, b, FN, FN, FN, #FCN); \
00343   }
00344 
00345 MARRAY_NDND_OP (operator +, +, mx_inline_add)
00346 MARRAY_NDND_OP (operator -, -, mx_inline_sub)
00347 MARRAY_NDND_OP (product,    *, mx_inline_mul)
00348 MARRAY_NDND_OP (quotient,   /, mx_inline_div)
00349 
00350 template <class T>
00351 MArray<T>
00352 operator + (const MArray<T>& a)
00353 {
00354   return a;
00355 }
00356 
00357 template <class T>
00358 MArray<T>
00359 operator - (const MArray<T>& a)
00360 {
00361   return do_mx_unary_op<T, T> (a, mx_inline_uminus);
00362 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines