Cube_meat.hpp

Go to the documentation of this file.
00001 // Copyright (C) 2009 NICTA
00002 // 
00003 // Authors:
00004 // - Conrad Sanderson (conradsand at ieee dot org)
00005 // 
00006 // This file is part of the Armadillo C++ library.
00007 // It is provided without any warranty of fitness
00008 // for any purpose. You can redistribute this file
00009 // and/or modify it under the terms of the GNU
00010 // Lesser General Public License (LGPL) as published
00011 // by the Free Software Foundation, either version 3
00012 // of the License or (at your option) any later version.
00013 // (see http://www.opensource.org/licenses for more info)
00014 
00015 
00016 //! \addtogroup Cube
00017 //! @{
00018 
00019 
00020 template<typename eT>
00021 inline
00022 Cube<eT>::~Cube()
00023   {
00024   arma_extra_debug_sigprint_this(this);
00025   
00026   delete_mat();
00027   
00028   if(use_aux_mem == false)
00029     {
00030     if(n_elem > sizeof(mem_local)/sizeof(eT) )
00031       {
00032       delete [] mem;
00033       }
00034     }
00035     
00036   if(arma_config::debug == true)
00037     {
00038     // try to expose buggy user code that accesses deleted objects
00039     access::rw(n_rows)       = 0;
00040     access::rw(n_cols)       = 0;
00041     access::rw(n_elem_slice) = 0;
00042     access::rw(n_slices)     = 0;
00043     access::rw(n_elem)       = 0;
00044     access::rw(mat_ptrs)     = 0;
00045     access::rw(mem)          = 0;
00046     }
00047   
00048   isnt_supported_elem_type<eT>::check();
00049   }
00050 
00051 
00052 
00053 template<typename eT>
00054 inline
00055 Cube<eT>::Cube()
00056   : n_rows(0)
00057   , n_cols(0)
00058   , n_elem_slice(0)
00059   , n_slices(0)
00060   , n_elem(0)
00061   , use_aux_mem(false)
00062   , mat_ptrs(mat_ptrs)
00063   , mem(mem)
00064   {
00065   arma_extra_debug_sigprint_this(this);
00066   }
00067 
00068 
00069 
00070 //! construct the cube to have user specified dimensions
00071 template<typename eT>
00072 inline
00073 Cube<eT>::Cube(const u32 in_n_rows, const u32 in_n_cols, const u32 in_n_slices)
00074   : n_rows(0)
00075   , n_cols(0)
00076   , n_elem_slice(0)
00077   , n_slices(0)
00078   , n_elem(0)
00079   , use_aux_mem(false)
00080   , mat_ptrs(mat_ptrs)
00081   , mem(mem)
00082   {
00083   arma_extra_debug_sigprint_this(this);
00084   
00085   init(in_n_rows, in_n_cols, in_n_slices);
00086   }
00087 
00088 
00089 
00090 //! internal cube construction; if the requested size is small enough, memory from the stack is used.
00091 //! otherwise memory is allocated via 'new'
00092 template<typename eT>
00093 inline
00094 void
00095 Cube<eT>::init(const u32 in_n_rows, const u32 in_n_cols, const u32 in_n_slices)
00096   {
00097   arma_extra_debug_sigprint( arma_boost::format("in_n_rows = %d, in_n_cols = %d, in_n_slices = %d") % in_n_rows % in_n_cols % in_n_slices );
00098   
00099   const u32 new_n_elem = in_n_rows * in_n_cols * in_n_slices;
00100 
00101   if(n_elem == new_n_elem)
00102     {
00103     if( (n_rows != in_n_rows) || (n_cols != in_n_cols) || (n_slices != in_n_slices) )
00104       {
00105       delete_mat();
00106 
00107       access::rw(n_rows)       = in_n_rows;
00108       access::rw(n_cols)       = in_n_cols;
00109       access::rw(n_elem_slice) = in_n_rows*in_n_cols;
00110       access::rw(n_slices)     = in_n_slices;
00111     
00112       create_mat();
00113       }
00114     }
00115   else
00116     {
00117     arma_debug_check
00118       (
00119       (use_aux_mem == true),
00120       "Cube::init(): can't change the amount of memory as auxiliary memory is in use"
00121       );
00122       
00123     delete_mat();
00124 
00125     if(n_elem > sizeof(mem_local)/sizeof(eT) )
00126       {
00127       delete [] mem;
00128       }
00129     
00130     if(new_n_elem <= sizeof(mem_local)/sizeof(eT) )
00131       {
00132       access::rw(mem) = mem_local;
00133       }
00134     else
00135       {
00136       access::rw(mem) = new(std::nothrow) eT[new_n_elem];
00137       arma_check( (mem == 0), "Cube::init(): out of memory" );
00138       }
00139     
00140     access::rw(n_elem) = new_n_elem;
00141 
00142     if(new_n_elem == 0)
00143       {
00144       access::rw(n_rows)       = 0;
00145       access::rw(n_cols)       = 0;
00146       access::rw(n_elem_slice) = 0;
00147       access::rw(n_slices)     = 0;
00148       }
00149     else
00150       {
00151       access::rw(n_rows)       = in_n_rows;
00152       access::rw(n_cols)       = in_n_cols;
00153       access::rw(n_elem_slice) = in_n_rows*in_n_cols;
00154       access::rw(n_slices)     = in_n_slices;
00155       }
00156       
00157     create_mat();
00158     }
00159   }
00160 
00161 
00162 template<typename eT>
00163 inline
00164 void
00165 Cube<eT>::delete_mat()
00166   {
00167   arma_extra_debug_sigprint();
00168   
00169   for(u32 slice = 0; slice < n_slices; ++slice)
00170     {
00171     delete access::rw(mat_ptrs[slice]);
00172     }
00173 
00174   if(n_slices > sizeof(mat_ptrs_local)/sizeof(Mat<eT>*) )
00175     {
00176     delete [] mat_ptrs;
00177     }
00178   }
00179 
00180 
00181 
00182 template<typename eT>
00183 inline
00184 void
00185 Cube<eT>::create_mat()
00186   {
00187   arma_extra_debug_sigprint();
00188 
00189   if( n_slices <= sizeof(mat_ptrs_local)/sizeof(Mat<eT>*) )
00190     {
00191     access::rw(mat_ptrs) = const_cast< const Mat<eT>** >(mat_ptrs_local);
00192     }
00193   else
00194     {
00195     access::rw(mat_ptrs) = new(std::nothrow) const Mat<eT>*[n_slices];
00196     arma_check( (mat_ptrs == 0), "Cube::create_mat(): out of memory" );
00197     }
00198     
00199   for(u32 slice = 0; slice < n_slices; ++slice)
00200     {
00201     mat_ptrs[slice] = new Mat<eT>('j', slice_memptr(slice), n_rows, n_cols);
00202     }
00203   }
00204 
00205 
00206 
00207 //! Set the cube to be equal to the specified scalar.
00208 //! NOTE: the size of the cube will be 1x1x1
00209 template<typename eT>
00210 arma_inline
00211 const Cube<eT>&
00212 Cube<eT>::operator=(const eT val)
00213   {
00214   arma_extra_debug_sigprint();
00215   
00216   init(1,1,1);
00217   access::rw(mem[0]) = val;
00218   return *this;
00219   }
00220 
00221 
00222 
00223 //! In-place addition of a scalar to all elements of the cube
00224 template<typename eT>
00225 arma_inline
00226 const Cube<eT>&
00227 Cube<eT>::operator+=(const eT val)
00228   {
00229   arma_extra_debug_sigprint();
00230   
00231   for(u32 i=0; i<n_elem; ++i)
00232     {
00233     access::rw(mem[i]) += val;
00234     }
00235   
00236   return *this;
00237   }
00238 
00239 
00240 
00241 //! In-place subtraction of a scalar from all elements of the cube
00242 template<typename eT>
00243 arma_inline
00244 const Cube<eT>&
00245 Cube<eT>::operator-=(const eT val)
00246   {
00247   arma_extra_debug_sigprint();
00248   
00249   for(u32 i=0; i<n_elem; ++i)
00250     {
00251     access::rw(mem[i]) -= val;
00252     }
00253       
00254   return *this;
00255   }
00256 
00257 
00258 
00259 //! In-place multiplication of all elements of the cube with a scalar
00260 template<typename eT>
00261 arma_inline
00262 const Cube<eT>&
00263 Cube<eT>::operator*=(const eT val)
00264   {
00265   arma_extra_debug_sigprint();
00266   
00267   for(u32 i=0; i<n_elem; ++i)
00268     {
00269     access::rw(mem[i]) *= val;
00270     }
00271   
00272   return *this;
00273   }
00274 
00275 
00276 
00277 //! In-place division of all elements of the cube with a scalar
00278 template<typename eT>
00279 arma_inline
00280 const Cube<eT>&
00281 Cube<eT>::operator/=(const eT val)
00282   {
00283   arma_extra_debug_sigprint();
00284   
00285   for(u32 i=0; i<n_elem; ++i)
00286     {
00287     access::rw(mem[i]) /= val;
00288     }
00289   
00290   return *this;
00291   }
00292 
00293 
00294 
00295 //! construct a cube from a given cube
00296 template<typename eT>
00297 inline
00298 Cube<eT>::Cube(const Cube<eT>& in_cube)
00299   : n_rows(0)
00300   , n_cols(0)
00301   , n_elem_slice(0)
00302   , n_slices(0)
00303   , n_elem(0)
00304   , use_aux_mem(false)
00305   , mat_ptrs(mat_ptrs)
00306   , mem(mem)
00307   {
00308   arma_extra_debug_sigprint(arma_boost::format("this = %x   in_cube = %x") % this % &in_cube);
00309   
00310   init(in_cube);
00311   }
00312 
00313 
00314 
00315 //! construct a cube from a given cube
00316 template<typename eT>
00317 inline
00318 const Cube<eT>&
00319 Cube<eT>::operator=(const Cube<eT>& x)
00320   {
00321   arma_extra_debug_sigprint();
00322   
00323   init(x);
00324   return *this;
00325   }
00326 
00327 
00328 
00329 //! construct a cube from a given cube
00330 template<typename eT>
00331 inline
00332 void
00333 Cube<eT>::init(const Cube<eT>& x)
00334   {
00335   arma_extra_debug_sigprint();
00336   
00337   if(this != &x)
00338     {
00339     init(x.n_rows, x.n_cols, x.n_slices);
00340     syslib::copy_elem( memptr(), x.mem, n_elem );
00341     }
00342   }
00343 
00344 
00345 
00346 //! construct a cube from a given auxiliary array of eTs.
00347 //! if copy_aux_mem is true, new memory is allocated and the array is copied.
00348 //! if copy_aux_mem is false, the auxiliary array is used directly (without allocating memory and copying).
00349 //! note that in the latter case 
00350 //! the default is to copy the array.
00351 
00352 template<typename eT>
00353 inline
00354 Cube<eT>::Cube(eT* aux_mem, const u32 aux_n_rows, const u32 aux_n_cols, const u32 aux_n_slices, const bool copy_aux_mem)
00355   : n_rows      (copy_aux_mem ? 0     : aux_n_rows                        )
00356   , n_cols      (copy_aux_mem ? 0     : aux_n_cols                        )
00357   , n_elem_slice(copy_aux_mem ? 0     : aux_n_rows*aux_n_cols             )
00358   , n_slices    (copy_aux_mem ? 0     : aux_n_slices                      )
00359   , n_elem      (copy_aux_mem ? 0     : aux_n_rows*aux_n_cols*aux_n_slices)
00360   , use_aux_mem (copy_aux_mem ? false : true                              )
00361   , mem         (copy_aux_mem ? mem   : aux_mem                           )
00362   {
00363   arma_extra_debug_sigprint_this(this);
00364   
00365   if(copy_aux_mem == true)
00366     {
00367     init(aux_n_rows, aux_n_cols, aux_n_slices);
00368     syslib::copy_elem( memptr(), aux_mem, n_elem );
00369     }
00370   }
00371 
00372 
00373 
00374 //! construct a cube from a given auxiliary read-only array of eTs.
00375 //! the array is copied.
00376 template<typename eT>
00377 inline
00378 Cube<eT>::Cube(const eT* aux_mem, const u32 aux_n_rows, const u32 aux_n_cols, const u32 aux_n_slices)
00379   : n_rows(0)
00380   , n_cols(0)
00381   , n_elem_slice(0)
00382   , n_slices(0)
00383   , n_elem(0)
00384   , use_aux_mem(false)
00385   , mat_ptrs(mat_ptrs)
00386   , mem(mem)
00387   {
00388   arma_extra_debug_sigprint_this(this);
00389   
00390   init(aux_n_rows, aux_n_cols, aux_n_slices);
00391   syslib::copy_elem( memptr(), aux_mem, n_elem );
00392   }
00393 
00394 
00395 
00396 //! in-place cube addition
00397 template<typename eT>
00398 inline
00399 const Cube<eT>&
00400 Cube<eT>::operator+=(const Cube<eT>& m)
00401   {
00402   arma_extra_debug_sigprint();
00403   
00404   glue_cube_plus::apply_inplace(*this, m);
00405   return *this;
00406   }
00407 
00408 
00409 
00410 //! in-place cube subtraction
00411 template<typename eT>
00412 inline
00413 const Cube<eT>&
00414 Cube<eT>::operator-=(const Cube<eT>& m)
00415   {
00416   arma_extra_debug_sigprint();
00417   
00418   glue_cube_minus::apply_inplace(*this, m);
00419   return *this;
00420   }
00421 
00422 
00423 
00424 //! in-place element-wise cube multiplication
00425 template<typename eT>
00426 inline
00427 const Cube<eT>&
00428 Cube<eT>::operator%=(const Cube<eT>& m)
00429   {
00430   arma_extra_debug_sigprint();
00431   
00432   glue_cube_schur::apply_inplace(*this, m);
00433   return *this;
00434   }
00435 
00436 
00437 
00438 //! in-place element-wise cube division
00439 template<typename eT>
00440 inline
00441 const Cube<eT>&
00442 Cube<eT>::operator/=(const Cube<eT>& m)
00443   {
00444   arma_extra_debug_sigprint();
00445   
00446   glue_cube_div::apply_inplace(*this, m);
00447   return *this;
00448   }
00449 
00450 
00451 
00452 //! for constructing a complex cube out of two non-complex cubes
00453 template<typename eT>
00454 template<typename T1, typename T2>
00455 inline
00456 Cube<eT>::Cube
00457   (
00458   const BaseCube<typename Cube<eT>::pod_type,T1>& A,
00459   const BaseCube<typename Cube<eT>::pod_type,T2>& B
00460   )
00461   : n_rows(0)
00462   , n_cols(0)
00463   , n_elem_slice(0)
00464   , n_slices(0)
00465   , n_elem(0)
00466   , use_aux_mem(false)
00467   , mat_ptrs(mat_ptrs)
00468   , mem(mem)
00469   {
00470   arma_extra_debug_sigprint_this(this);
00471   
00472   arma_type_check< is_complex<eT>::value == false >::apply();   //!< compile-time abort if eT isn't std::complex
00473   
00474   typedef typename T1::elem_type T;
00475   arma_type_check< is_complex<T>::value == true >::apply();   //!< compile-time abort if T is std::complex
00476   
00477   isnt_same_type<std::complex<T>, eT>::check();   //!< compile-time abort if types are not compatible
00478   
00479   const unwrap_cube<T1> tmp_A(A.get_ref());
00480   const unwrap_cube<T2> tmp_B(B.get_ref());
00481   
00482   const Cube<T>& X = tmp_A.M;
00483   const Cube<T>& Y = tmp_B.M;
00484   
00485   arma_assert_same_size(X, Y, "Cube()");
00486   
00487   init(X.n_rows, X.n_cols, X.n_slices);
00488   
00489   const T* X_mem = X.mem;
00490   const T* Y_mem = Y.mem;
00491   
00492   for(u32 i=0; i<n_elem; ++i)
00493     {
00494     access::rw(mem[i]) = std::complex<T>(X_mem[i], Y_mem[i]);
00495     }
00496   }
00497 
00498 
00499 
00500 //! construct a cube from a subview_cube instance (e.g. construct a cube from a delayed subcube operation)
00501 template<typename eT>
00502 inline
00503 Cube<eT>::Cube(const subview_cube<eT>& X)
00504   : n_rows(0)
00505   , n_cols(0)
00506   , n_elem_slice(0)
00507   , n_slices(0)
00508   , n_elem(0)
00509   , use_aux_mem(false)
00510   , mat_ptrs(mat_ptrs)
00511   , mem(mem)
00512   {
00513   arma_extra_debug_sigprint_this(this);
00514   
00515   this->operator=(X);
00516   }
00517 
00518 
00519 
00520 //! construct a cube from a subview_cube instance (e.g. construct a cube from a delayed subcube operation)
00521 template<typename eT>
00522 inline
00523 const Cube<eT>&
00524 Cube<eT>::operator=(const subview_cube<eT>& X)
00525   {
00526   arma_extra_debug_sigprint();
00527   
00528   subview_cube<eT>::extract(*this, X);
00529   return *this;
00530   }
00531 
00532 
00533 
00534 //! in-place cube addition (using a subcube on the right-hand-side)
00535 template<typename eT>
00536 inline
00537 const Cube<eT>&
00538 Cube<eT>::operator+=(const subview_cube<eT>& X)
00539   {
00540   arma_extra_debug_sigprint();
00541   
00542   subview_cube<eT>::plus_inplace(*this, X);
00543   return *this;
00544   }
00545 
00546 
00547 
00548 //! in-place cube subtraction (using a subcube on the right-hand-side)
00549 template<typename eT>
00550 inline
00551 const Cube<eT>&
00552 Cube<eT>::operator-=(const subview_cube<eT>& X)
00553   {
00554   arma_extra_debug_sigprint();
00555   
00556   subview_cube<eT>::minus_inplace(*this, X);
00557   return *this;
00558   }
00559 
00560 
00561 
00562 //! in-place element-wise cube mutiplication (using a subcube on the right-hand-side)
00563 template<typename eT>
00564 inline
00565 const Cube<eT>&
00566 Cube<eT>::operator%=(const subview_cube<eT>& X)
00567   {
00568   arma_extra_debug_sigprint();
00569   
00570   subview_cube<eT>::schur_inplace(*this, X);
00571   return *this;
00572   }
00573 
00574 
00575 
00576 //! in-place element-wise cube division (using a subcube on the right-hand-side)
00577 template<typename eT>
00578 inline
00579 const Cube<eT>&
00580 Cube<eT>::operator/=(const subview_cube<eT>& X)
00581   {
00582   arma_extra_debug_sigprint();
00583   
00584   subview_cube<eT>::div_inplace(*this, X);
00585   return *this;
00586   }
00587 
00588 
00589 
00590 //! provide the reference to the matrix representing a single slice
00591 template<typename eT>
00592 arma_inline
00593 Mat<eT>&
00594 Cube<eT>::slice(const u32 in_slice)
00595   {
00596   arma_extra_debug_sigprint();
00597   
00598   arma_debug_check
00599     (
00600     (in_slice >= n_slices),
00601     "Cube::slice(): index out of bounds"
00602     );
00603   
00604   return const_cast< Mat<eT>& >( *(mat_ptrs[in_slice]) );
00605   }
00606 
00607 
00608 
00609 //! provide the reference to the matrix representing a single slice
00610 template<typename eT>
00611 arma_inline
00612 const Mat<eT>&
00613 Cube<eT>::slice(const u32 in_slice) const
00614   {
00615   arma_extra_debug_sigprint();
00616   
00617   arma_debug_check
00618     (
00619     (in_slice >= n_slices),
00620     "Cube::slice(): index out of bounds"
00621     );
00622    
00623   return *(mat_ptrs[in_slice]);
00624   }
00625 
00626 
00627 
00628 //! creation of subview_cube (subcube comprised of specified slices)
00629 template<typename eT>
00630 arma_inline
00631 subview_cube<eT>
00632 Cube<eT>::slices(const u32 in_slice1, const u32 in_slice2)
00633   {
00634   arma_extra_debug_sigprint();
00635   
00636   arma_debug_check
00637     (
00638     (in_slice1 > in_slice2) || (in_slice2 >= n_slices),
00639     "Cube::slices(): indices out of bounds or incorrectly used"
00640     );
00641   
00642   return subview_cube<eT>(*this, 0, 0, in_slice1, ( (n_rows>0) ? n_rows-1 : 0 ), ( (n_cols>0) ? n_cols-1 : 0 ), in_slice2);
00643   }
00644 
00645 
00646 
00647 //! creation of subview_cube (subcube comprised of specified slices)
00648 template<typename eT>
00649 arma_inline
00650 const subview_cube<eT>
00651 Cube<eT>::slices(const u32 in_slice1, const u32 in_slice2) const
00652   {
00653   arma_extra_debug_sigprint();
00654   
00655   arma_debug_check
00656     (
00657     (in_slice1 > in_slice2) || (in_slice2 >= n_slices),
00658     "Cube::rows(): indices out of bounds or incorrectly used"
00659     );
00660   
00661   return subview_cube<eT>(*this, 0, 0, in_slice1, ( (n_rows>0) ? n_rows-1 : 0 ), ( (n_cols>0) ? n_cols-1 : 0 ), in_slice2);
00662   }
00663 
00664 
00665 
00666 //! creation of subview_cube (generic subcube)
00667 template<typename eT>
00668 arma_inline
00669 subview_cube<eT>
00670 Cube<eT>::subcube(const u32 in_row1, const u32 in_col1, const u32 in_slice1, const u32 in_row2, const u32 in_col2, const u32 in_slice2)
00671   {
00672   arma_extra_debug_sigprint();
00673   
00674   arma_debug_check
00675     (
00676     (in_row1 >  in_row2) || (in_col1 >  in_col2) || (in_slice1 >  in_slice2) ||
00677     (in_row2 >= n_rows)  || (in_col2 >= n_cols)  || (in_slice2 >= n_slices),
00678     "Cube::subcube(): indices out of bounds or incorrectly used"
00679     );
00680   
00681   return subview_cube<eT>(*this, in_row1, in_col1, in_slice1, in_row2, in_col2, in_slice2);
00682   }
00683 
00684 
00685 
00686 //! creation of subview_cube (generic subcube)
00687 template<typename eT>
00688 arma_inline
00689 const subview_cube<eT>
00690 Cube<eT>::subcube(const u32 in_row1, const u32 in_col1, const u32 in_slice1, const u32 in_row2, const u32 in_col2, const u32 in_slice2) const
00691   {
00692   arma_extra_debug_sigprint();
00693   
00694   arma_debug_check
00695     (
00696     (in_row1 >  in_row2) || (in_col1 >  in_col2) || (in_slice1 >  in_slice2) ||
00697     (in_row2 >= n_rows)  || (in_col2 >= n_cols)  || (in_slice2 >= n_slices),
00698     "Cube::subcube(): indices out of bounds or incorrectly used"
00699     );
00700     
00701   return subview_cube<eT>(*this, in_row1, in_col1, in_slice1, in_row2, in_col2, in_slice2);
00702   }
00703 
00704 
00705 
00706 //! create a cube from OpCube, i.e. run the previously delayed unary operations
00707 template<typename eT>
00708 template<typename T1, typename op_cube_type>
00709 inline
00710 Cube<eT>::Cube(const OpCube<T1, op_cube_type>& X)
00711   : n_rows(0)
00712   , n_cols(0)
00713   , n_elem_slice(0)
00714   , n_slices(0)
00715   , n_elem(0)
00716   , use_aux_mem(false)
00717   , mat_ptrs(mat_ptrs)
00718   , mem(mem)
00719   {
00720   arma_extra_debug_sigprint_this(this);
00721 
00722   isnt_same_type<eT, typename T1::elem_type>::check();
00723   
00724   op_cube_type::apply(*this, X);
00725   }
00726 
00727 
00728 
00729 //! create a cube from OpCube, i.e. run the previously delayed unary operations
00730 template<typename eT>
00731 template<typename T1, typename op_cube_type>
00732 inline
00733 const Cube<eT>&
00734 Cube<eT>::operator=(const OpCube<T1, op_cube_type>& X)
00735   {
00736   arma_extra_debug_sigprint();
00737 
00738   isnt_same_type<eT, typename T1::elem_type>::check();
00739   
00740   op_cube_type::apply(*this, X);
00741   
00742   return *this;
00743   }
00744 
00745 
00746 
00747 //! in-place cube addition, with the right-hand-side operand having delayed operations
00748 template<typename eT>
00749 template<typename T1, typename op_cube_type>
00750 inline
00751 const Cube<eT>&
00752 Cube<eT>::operator+=(const OpCube<T1, op_cube_type>& X)
00753   {
00754   arma_extra_debug_sigprint();
00755   
00756   isnt_same_type<eT, typename T1::elem_type>::check();
00757   
00758   glue_cube_plus::apply_inplace(*this, X);
00759   
00760   return *this;
00761   }
00762 
00763 
00764 
00765 //! in-place cube subtraction, with the right-hand-side operand having delayed operations
00766 template<typename eT>
00767 template<typename T1, typename op_cube_type>
00768 inline
00769 const Cube<eT>&
00770 Cube<eT>::operator-=(const OpCube<T1, op_cube_type>& X)
00771   {
00772   arma_extra_debug_sigprint();
00773   
00774   isnt_same_type<eT, typename T1::elem_type>::check();
00775   
00776   glue_cube_minus::apply_inplace(*this, X);
00777   
00778   return *this;
00779   }
00780 
00781 
00782 
00783 //! in-place cube element-wise multiplication, with the right-hand-side operand having delayed operations
00784 template<typename eT>
00785 template<typename T1, typename op_cube_type>
00786 inline
00787 const Cube<eT>&
00788 Cube<eT>::operator%=(const OpCube<T1, op_cube_type>& X)
00789   {
00790   arma_extra_debug_sigprint();
00791   
00792   isnt_same_type<eT, typename T1::elem_type>::check();
00793   glue_cube_schur::apply_inplace(*this, X);
00794   
00795   return *this;
00796   }
00797 
00798 
00799 
00800 //! in-place cube element-wise division, with the right-hand-side operand having delayed operations
00801 template<typename eT>
00802 template<typename T1, typename op_cube_type>
00803 inline
00804 const Cube<eT>&
00805 Cube<eT>::operator/=(const OpCube<T1, op_cube_type>& X)
00806   {
00807   arma_extra_debug_sigprint();
00808   
00809   isnt_same_type<eT, typename T1::elem_type>::check();
00810   glue_cube_div::apply_inplace(*this, X);
00811   
00812   return *this;
00813   }
00814 
00815 
00816 
00817 //! create a cube from Glue, i.e. run the previously delayed binary operations
00818 template<typename eT>
00819 template<typename T1, typename T2, typename glue_cube_type>
00820 inline
00821 Cube<eT>::Cube(const GlueCube<T1, T2, glue_cube_type>& X)
00822   : n_rows(0)
00823   , n_cols(0)
00824   , n_elem_slice(0)
00825   , n_slices(0)
00826   , n_elem(0)
00827   , use_aux_mem(false)
00828   , mat_ptrs(mat_ptrs)
00829   , mem(mem)
00830   {
00831   arma_extra_debug_sigprint_this(this);
00832   this->operator=(X);
00833   }
00834 
00835 
00836 
00837 //! create a cube from Glue, i.e. run the previously delayed binary operations
00838 template<typename eT>
00839 template<typename T1, typename T2, typename glue_cube_type>
00840 inline
00841 const Cube<eT>&
00842 Cube<eT>::operator=(const GlueCube<T1, T2, glue_cube_type>& X)
00843   {
00844   arma_extra_debug_sigprint();
00845   
00846   isnt_same_type<eT, typename T1::elem_type>::check();
00847   isnt_same_type<eT, typename T2::elem_type>::check();
00848   
00849   glue_cube_type::apply(*this, X);
00850   
00851   return *this;
00852   }
00853 
00854 
00855 //! in-place cube addition, with the right-hand-side operands having delayed operations
00856 template<typename eT>
00857 template<typename T1, typename T2, typename glue_cube_type>
00858 inline
00859 const Cube<eT>&
00860 Cube<eT>::operator+=(const GlueCube<T1, T2, glue_cube_type>& X)
00861   {
00862   arma_extra_debug_sigprint();
00863   
00864   isnt_same_type<eT, typename T1::elem_type>::check();
00865   isnt_same_type<eT, typename T2::elem_type>::check();
00866   
00867   glue_cube_plus::apply_inplace(*this, X);
00868   
00869   return *this;
00870   }
00871 
00872 
00873 
00874 //! in-place cube subtraction, with the right-hand-side operands having delayed operations
00875 template<typename eT>
00876 template<typename T1, typename T2, typename glue_cube_type>
00877 inline
00878 const Cube<eT>&
00879 Cube<eT>::operator-=(const GlueCube<T1, T2, glue_cube_type>& X)
00880   {
00881   arma_extra_debug_sigprint();
00882   
00883   isnt_same_type<eT, typename T1::elem_type>::check();
00884   isnt_same_type<eT, typename T2::elem_type>::check();
00885   
00886   glue_cube_minus::apply_inplace(*this, X);
00887   
00888   return *this;
00889   }
00890 
00891 
00892 
00893 //! in-place cube element-wise multiplication, with the right-hand-side operands having delayed operations
00894 template<typename eT>
00895 template<typename T1, typename T2, typename glue_cube_type>
00896 inline
00897 const Cube<eT>&
00898 Cube<eT>::operator%=(const GlueCube<T1, T2, glue_cube_type>& X)
00899   {
00900   arma_extra_debug_sigprint();
00901   
00902   isnt_same_type<eT, typename T1::elem_type>::check();
00903   isnt_same_type<eT, typename T2::elem_type>::check();
00904   
00905   glue_cube_schur::apply_inplace(*this, X);
00906   return *this;
00907   }
00908 
00909 
00910 
00911 //! in-place cube element-wise division, with the right-hand-side operands having delayed operations
00912 template<typename eT>
00913 template<typename T1, typename T2, typename glue_cube_type>
00914 inline
00915 const Cube<eT>&
00916 Cube<eT>::operator/=(const GlueCube<T1, T2, glue_cube_type>& X)
00917   {
00918   arma_extra_debug_sigprint();
00919   
00920   isnt_same_type<eT, typename T1::elem_type>::check();
00921   isnt_same_type<eT, typename T2::elem_type>::check();
00922   
00923   glue_cube_div::apply_inplace(*this, X);
00924   return *this;
00925   }
00926 
00927 
00928 
00929 //! linear element accessor (treats the cube as a vector); bounds checking not done when ARMA_NO_DEBUG is defined
00930 template<typename eT>
00931 arma_inline
00932 eT&
00933 Cube<eT>::operator() (const u32 i)
00934   {
00935   arma_debug_check( (i >= n_elem), "Cube::operator(): index out of bounds");
00936   return access::rw(mem[i]);
00937   }
00938 
00939 
00940 
00941 //! linear element accessor (treats the cube as a vector); bounds checking not done when ARMA_NO_DEBUG is defined
00942 template<typename eT>
00943 arma_inline
00944 eT
00945 Cube<eT>::operator() (const u32 i) const
00946   {
00947   arma_debug_check( (i >= n_elem), "Cube::operator(): index out of bounds");
00948   return mem[i];
00949   }
00950 
00951 
00952 //! linear element accessor (treats the cube as a vector); no bounds check.  
00953 template<typename eT>
00954 arma_inline
00955 eT&
00956 Cube<eT>::operator[] (const u32 i)
00957   {
00958   return access::rw(mem[i]);
00959   }
00960 
00961 
00962 
00963 //! linear element accessor (treats the cube as a vector); no bounds check
00964 template<typename eT>
00965 arma_inline
00966 eT
00967 Cube<eT>::operator[] (const u32 i) const
00968   {
00969   return mem[i];
00970   }
00971 
00972 
00973 
00974 //! element accessor; bounds checking not done when ARMA_NO_DEBUG is defined
00975 template<typename eT>
00976 arma_inline
00977 eT&
00978 Cube<eT>::operator() (const u32 in_row, const u32 in_col, const u32 in_slice)
00979   {
00980   arma_debug_check
00981     (
00982     (in_row >= n_rows) ||
00983     (in_col >= n_cols) ||
00984     (in_slice >= n_slices)
00985     ,
00986     "Cube::operator(): index out of bounds"
00987     );
00988 
00989   return access::rw(mem[in_slice*n_elem_slice + in_col*n_rows + in_row]);
00990   }
00991 
00992 
00993 
00994 //! element accessor; bounds checking not done when ARMA_NO_DEBUG is defined
00995 template<typename eT>
00996 arma_inline
00997 eT
00998 Cube<eT>::operator() (const u32 in_row, const u32 in_col, const u32 in_slice) const
00999   {
01000   arma_debug_check
01001     (
01002     (in_row >= n_rows) ||
01003     (in_col >= n_cols) ||
01004     (in_slice >= n_slices)
01005     ,
01006     "Cube::operator(): index out of bounds"
01007     );
01008 
01009   return mem[in_slice*n_elem_slice + in_col*n_rows + in_row];
01010   }
01011 
01012 
01013 
01014 //! element accessor; no bounds check
01015 template<typename eT>
01016 arma_inline
01017 eT&
01018 Cube<eT>::at(const u32 in_row, const u32 in_col, const u32 in_slice)
01019   {
01020   return access::rw( mem[in_slice*n_elem_slice + in_col*n_rows + in_row] );
01021   }
01022 
01023 
01024 
01025 //! element accessor; no bounds check
01026 template<typename eT>
01027 arma_inline
01028 eT
01029 Cube<eT>::at(const u32 in_row, const u32 in_col, const u32 in_slice) const
01030   {
01031   return mem[in_slice*n_elem_slice + in_col*n_rows + in_row];
01032   }
01033 
01034 
01035 
01036 //! prefix ++
01037 template<typename eT>
01038 arma_inline
01039 const Cube<eT>&
01040 Cube<eT>::operator++()
01041   {
01042   Cube_aux::prefix_pp(*this);
01043   return *this;
01044   }
01045 
01046 
01047 
01048 //! postfix ++  (must not return the object by reference)
01049 template<typename eT>
01050 arma_inline
01051 void
01052 Cube<eT>::operator++(int)
01053   {
01054   Cube_aux::postfix_pp(*this);
01055   }
01056 
01057 
01058 
01059 //! prefix --
01060 template<typename eT>
01061 arma_inline
01062 const Cube<eT>&
01063 Cube<eT>::operator--()
01064   {
01065   Cube_aux::prefix_mm(*this);
01066   return *this;
01067   }
01068 
01069 
01070 
01071 //! postfix --  (must not return the object by reference)
01072 template<typename eT>
01073 arma_inline
01074 void
01075 Cube<eT>::operator--(int)
01076   {
01077   Cube_aux::postfix_mm(*this);
01078   }
01079 
01080 
01081 
01082 //! returns true if all of the elements are finite
01083 template<typename eT>
01084 arma_inline
01085 bool
01086 Cube<eT>::is_finite() const
01087   {
01088   for(u32 i=0; i<n_elem; ++i)
01089     {
01090     if(arma_isfinite(mem[i]) == false)
01091       {
01092       return false;
01093       }
01094     }
01095 
01096   return true;
01097   }
01098 
01099 
01100 
01101 //! returns a pointer to array of eTs used by the cube
01102 template<typename eT>
01103 arma_inline
01104 eT*
01105 Cube<eT>::memptr()
01106   {
01107   return const_cast<eT*>(mem);
01108   }
01109 
01110 
01111 
01112 //! returns a pointer to array of eTs used by the cube
01113 template<typename eT>
01114 arma_inline
01115 const eT*
01116 Cube<eT>::memptr() const
01117   {
01118   return mem;
01119   }
01120 
01121 
01122 
01123 //! returns a pointer to array of eTs used by the specified slice in the cube
01124 template<typename eT>
01125 arma_inline
01126 eT*
01127 Cube<eT>::slice_memptr(const u32 slice)
01128   {
01129   return const_cast<eT*>( &mem[ slice*n_elem_slice ] );
01130   }
01131 
01132 
01133 
01134 //! returns a pointer to array of eTs used by the specified slice in the cube
01135 template<typename eT>
01136 arma_inline
01137 const eT*
01138 Cube<eT>::slice_memptr(const u32 slice) const
01139   {
01140   return &mem[ slice*n_elem_slice ];
01141   }
01142 
01143 
01144 
01145 //! returns a pointer to array of eTs used by the specified slice in the cube
01146 template<typename eT>
01147 arma_inline
01148 eT*
01149 Cube<eT>::slice_colptr(const u32 slice, const u32 col)
01150   {
01151   return const_cast<eT*>( &mem[ slice*n_elem_slice + col*n_rows] );
01152   }
01153 
01154 
01155 
01156 //! returns a pointer to array of eTs used by the specified slice in the cube
01157 template<typename eT>
01158 arma_inline
01159 const eT*
01160 Cube<eT>::slice_colptr(const u32 slice, const u32 col) const
01161   {
01162   return &mem[ slice*n_elem_slice + col*n_rows ];
01163   }
01164 
01165 
01166 
01167 //! print contents of the cube (to the cout stream),
01168 //! optionally preceding with a user specified line of text.
01169 //! the precision and cell width are modified.
01170 //! on return, the stream's flags are restored to their original values.
01171 template<typename eT>
01172 inline
01173 void
01174 Cube<eT>::print(const std::string extra_text) const
01175   {
01176   arma_extra_debug_sigprint();
01177   
01178   if(extra_text.length() != 0)
01179     {
01180     cout << extra_text << '\n';
01181     }
01182   
01183   arma_ostream::print(cout, *this, true);
01184   }
01185 
01186 
01187 //! print contents of the cube to a user specified stream,
01188 //! optionally preceding with a user specified line of text.
01189 //! the precision and cell width are modified.
01190 //! on return, the stream's flags are restored to their original values.
01191 template<typename eT>
01192 inline
01193 void
01194 Cube<eT>::print(std::ostream& user_stream, const std::string extra_text) const
01195   {
01196   arma_extra_debug_sigprint();
01197   
01198   if(extra_text.length() != 0)
01199     {
01200     user_stream << extra_text << '\n';
01201     }
01202   
01203   arma_ostream::print(user_stream, *this, true);
01204   }
01205 
01206 
01207 
01208 //! print contents of the cube (to the cout stream),
01209 //! optionally preceding with a user specified line of text.
01210 //! the stream's flags are used as is and are not modified
01211 //! (i.e. the precision and cell width are not modified).
01212 template<typename eT>
01213 inline
01214 void
01215 Cube<eT>::raw_print(const std::string extra_text) const
01216   {
01217   arma_extra_debug_sigprint();
01218   
01219   if(extra_text.length() != 0)
01220     {
01221     cout << extra_text << '\n';
01222     }
01223   
01224   arma_ostream::print(cout, *this, false);
01225   }
01226 
01227 
01228 
01229 //! print contents of the cube to a user specified stream,
01230 //! optionally preceding with a user specified line of text.
01231 //! the stream's flags are used as is and are not modified.
01232 //! (i.e. the precision and cell width are not modified).
01233 template<typename eT>
01234 inline
01235 void
01236 Cube<eT>::raw_print(std::ostream& user_stream, const std::string extra_text) const
01237   {
01238   arma_extra_debug_sigprint();
01239   
01240   if(extra_text.length() != 0)
01241     {
01242     user_stream << extra_text << '\n';
01243     }
01244   
01245   arma_ostream::print(user_stream, *this, false);
01246   }
01247 
01248 
01249 
01250 //! change the cube to have user specified dimensions (data is not preserved)
01251 template<typename eT>
01252 inline
01253 void
01254 Cube<eT>::set_size(const u32 in_n_rows, const u32 in_n_cols, const u32 in_n_slices)
01255   {
01256   arma_extra_debug_sigprint();
01257   
01258   init(in_n_rows, in_n_cols, in_n_slices);
01259   }
01260 
01261 
01262 
01263 //! change the cube (without preserving data) to have the same dimensions as the given cube 
01264 template<typename eT>
01265 template<typename eT2>
01266 inline
01267 void
01268 Cube<eT>::copy_size(const Cube<eT2>& m)
01269   {
01270   arma_extra_debug_sigprint();
01271   
01272   init(m.n_rows, m.n_cols, m.n_slices);
01273   }
01274 
01275 
01276 
01277 //! fill the cube with the specified value
01278 template<typename eT>
01279 inline
01280 void
01281 Cube<eT>::fill(const eT val)
01282   {
01283   arma_extra_debug_sigprint();
01284   
01285   for(u32 i=0; i<n_elem; ++i)
01286     {
01287     access::rw(mem[i]) = val;
01288     }
01289   }
01290 
01291 
01292 
01293 template<typename eT>
01294 inline
01295 void
01296 Cube<eT>::zeros()
01297   {
01298   arma_extra_debug_sigprint();
01299   
01300   fill(eT(0));
01301   }
01302 
01303 
01304 
01305 template<typename eT>
01306 inline
01307 void
01308 Cube<eT>::zeros(const u32 in_rows, const u32 in_cols, const u32 in_slices)
01309   {
01310   arma_extra_debug_sigprint( arma_boost::format("in_rows = %d, in_cols = %d, in_slices = %d") % in_rows % in_cols % in_slices );
01311 
01312   set_size(in_rows, in_cols, in_slices);
01313   fill(eT(0));
01314   }
01315 
01316 
01317 
01318 template<typename eT>
01319 inline
01320 void
01321 Cube<eT>::ones()
01322   {
01323   arma_extra_debug_sigprint();
01324   
01325   fill(eT(1));
01326   }
01327 
01328 
01329 
01330 template<typename eT>
01331 inline
01332 void
01333 Cube<eT>::ones(const u32 in_rows, const u32 in_cols, const u32 in_slices)
01334   {
01335   arma_extra_debug_sigprint( arma_boost::format("in_rows = %d, in_cols = %d, in_slices = %d") % in_rows % in_cols % in_slices );
01336 
01337   set_size(in_rows, in_cols, in_slices);
01338   fill(eT(1));
01339   }
01340 
01341 
01342 
01343 template<typename eT>
01344 inline
01345 void
01346 Cube<eT>::reset()
01347   {
01348   arma_extra_debug_sigprint();
01349   
01350   init(0,0,0);
01351   }
01352 
01353 
01354 
01355 //! save the cube to a file
01356 template<typename eT>
01357 inline
01358 void
01359 Cube<eT>::save(const std::string name, const file_type type) const
01360   {
01361   arma_extra_debug_sigprint();
01362   
01363   switch(type)
01364     {
01365     case raw_ascii:
01366       diskio::save_raw_ascii(*this, name);
01367       break;
01368     
01369     case arma_ascii:
01370       diskio::save_arma_ascii(*this, name);
01371       break;
01372     
01373     case arma_binary:
01374       diskio::save_arma_binary(*this, name);
01375       break;
01376       
01377     case ppm_binary:
01378       diskio::save_ppm_binary(*this, name);
01379       break;
01380 
01381     default:
01382       arma_stop("Cube::save(): unsupported file type");
01383     }
01384   
01385   }
01386 
01387 
01388 
01389 //! load a cube from a file
01390 template<typename eT>
01391 inline
01392 void
01393 Cube<eT>::load(const std::string name, const file_type type)
01394   {
01395   arma_extra_debug_sigprint();
01396   
01397   switch(type)
01398     {
01399     case auto_detect:
01400       diskio::load_auto_detect(*this, name);
01401       break;
01402     
01403     case raw_ascii:
01404       diskio::load_raw_ascii(*this, name);
01405       break;
01406     
01407     case arma_ascii:
01408       diskio::load_arma_ascii(*this, name);
01409       break;
01410     
01411     case arma_binary:
01412       diskio::load_arma_binary(*this, name);
01413       break;
01414       
01415     case ppm_binary:
01416       diskio::load_ppm_binary(*this, name);
01417       break;
01418 
01419     default:
01420       arma_stop("Cube::load(): unsupported file type");
01421     }
01422   
01423   }
01424 
01425 
01426 
01427 //! prefix ++
01428 template<typename eT>
01429 arma_inline
01430 void
01431 Cube_aux::prefix_pp(Cube<eT>& x)
01432   {
01433         eT* memptr = x.memptr();
01434   const u32 n_elem = x.n_elem;
01435 
01436   for(u32 i=0; i<n_elem; ++i)
01437     {
01438     ++(memptr[i]);
01439     }
01440   }
01441 
01442 
01443 
01444 //! prefix ++ for complex numbers (work around for limitations of the std::complex class)
01445 template<typename T>
01446 arma_inline
01447 void
01448 Cube_aux::prefix_pp(Cube< std::complex<T> >& x)
01449   {
01450   x += T(1);
01451   }
01452 
01453 
01454 
01455 //! postfix ++
01456 template<typename eT>
01457 arma_inline
01458 void
01459 Cube_aux::postfix_pp(Cube<eT>& x)
01460   {
01461         eT* memptr = x.memptr();
01462   const u32 n_elem = x.n_elem;
01463 
01464   for(u32 i=0; i<n_elem; ++i)
01465     {
01466     (memptr[i])++;
01467     }
01468   }
01469 
01470 
01471 
01472 //! postfix ++ for complex numbers (work around for limitations of the std::complex class)
01473 template<typename T>
01474 arma_inline
01475 void
01476 Cube_aux::postfix_pp(Cube< std::complex<T> >& x)
01477   {
01478   x += T(1);
01479   }
01480 
01481 
01482 
01483 //! prefix --
01484 template<typename eT>
01485 arma_inline
01486 void
01487 Cube_aux::prefix_mm(Cube<eT>& x)
01488   {
01489         eT* memptr = x.memptr();
01490   const u32 n_elem = x.n_elem;
01491 
01492   for(u32 i=0; i<n_elem; ++i)
01493     {
01494     --(memptr[i]);
01495     }
01496   }
01497 
01498 
01499 
01500 //! prefix -- for complex numbers (work around for limitations of the std::complex class)
01501 template<typename T>
01502 arma_inline
01503 void
01504 Cube_aux::prefix_mm(Cube< std::complex<T> >& x)
01505   {
01506   x -= T(1);
01507   }
01508 
01509 
01510 
01511 //! postfix --
01512 template<typename eT>
01513 arma_inline
01514 void
01515 Cube_aux::postfix_mm(Cube<eT>& x)
01516   {
01517         eT* memptr = x.memptr();
01518   const u32 n_elem = x.n_elem;
01519 
01520   for(u32 i=0; i<n_elem; ++i)
01521     {
01522     (memptr[i])--;
01523     }
01524   }
01525 
01526 
01527 
01528 //! postfix ++ for complex numbers (work around for limitations of the std::complex class)
01529 template<typename T>
01530 arma_inline
01531 void
01532 Cube_aux::postfix_mm(Cube< std::complex<T> >& x)
01533   {
01534   x -= T(1);
01535   }
01536 
01537 
01538 
01539 //! @}