"Fossies" - the Fresh Open Source Software Archive

Member "armadillo-9.800.3/include/armadillo_bits/subview_cube_meat.hpp" (16 Jun 2016, 64070 Bytes) of package /linux/misc/armadillo-9.800.3.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "subview_cube_meat.hpp" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 9.500.2_vs_9.600.4.

    1 // Copyright 2008-2016 Conrad Sanderson (http://conradsanderson.id.au)
    2 // Copyright 2008-2016 National ICT Australia (NICTA)
    3 // 
    4 // Licensed under the Apache License, Version 2.0 (the "License");
    5 // you may not use this file except in compliance with the License.
    6 // You may obtain a copy of the License at
    7 // http://www.apache.org/licenses/LICENSE-2.0
    8 // 
    9 // Unless required by applicable law or agreed to in writing, software
   10 // distributed under the License is distributed on an "AS IS" BASIS,
   11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   12 // See the License for the specific language governing permissions and
   13 // limitations under the License.
   14 // ------------------------------------------------------------------------
   15 
   16 
   17 //! \addtogroup subview_cube
   18 //! @{
   19 
   20 
   21 template<typename eT>
   22 inline
   23 subview_cube<eT>::~subview_cube()
   24   {
   25   arma_extra_debug_sigprint();
   26   }
   27 
   28 
   29 
   30 template<typename eT>
   31 arma_inline
   32 subview_cube<eT>::subview_cube
   33   (
   34   const Cube<eT>& in_m,
   35   const uword     in_row1,
   36   const uword     in_col1,
   37   const uword     in_slice1,
   38   const uword     in_n_rows,
   39   const uword     in_n_cols,
   40   const uword     in_n_slices
   41   )
   42   : m           (in_m)
   43   , aux_row1    (in_row1)
   44   , aux_col1    (in_col1)
   45   , aux_slice1  (in_slice1)
   46   , n_rows      (in_n_rows)
   47   , n_cols      (in_n_cols)
   48   , n_elem_slice(in_n_rows * in_n_cols)
   49   , n_slices    (in_n_slices)
   50   , n_elem      (n_elem_slice * in_n_slices)
   51   {
   52   arma_extra_debug_sigprint();
   53   }
   54 
   55 
   56 
   57 template<typename eT>
   58 inline
   59 void
   60 subview_cube<eT>::operator= (const eT val)
   61   {
   62   arma_extra_debug_sigprint();
   63   
   64   if(n_elem != 1)
   65     {
   66     arma_debug_assert_same_size(n_rows, n_cols, n_slices, 1, 1, 1, "copy into subcube");
   67     }
   68   
   69   Cube<eT>& Q = const_cast< Cube<eT>& >(m);
   70   
   71   Q.at(aux_row1, aux_col1, aux_slice1) = val;
   72   }
   73 
   74 
   75 
   76 template<typename eT>
   77 inline
   78 void
   79 subview_cube<eT>::operator+= (const eT val)
   80   {
   81   arma_extra_debug_sigprint();
   82   
   83   const uword local_n_rows   = n_rows;
   84   const uword local_n_cols   = n_cols;
   85   const uword local_n_slices = n_slices;
   86   
   87   for(uword slice = 0; slice < local_n_slices; ++slice)
   88     {
   89     for(uword col = 0; col < local_n_cols; ++col)
   90       {
   91       arrayops::inplace_plus( slice_colptr(slice,col), val, local_n_rows );
   92       }
   93     }
   94   }
   95 
   96 
   97 
   98 template<typename eT>
   99 inline
  100 void
  101 subview_cube<eT>::operator-= (const eT val)
  102   {
  103   arma_extra_debug_sigprint();
  104   
  105   const uword local_n_rows   = n_rows;
  106   const uword local_n_cols   = n_cols;
  107   const uword local_n_slices = n_slices;
  108   
  109   for(uword slice = 0; slice < local_n_slices; ++slice)
  110     {
  111     for(uword col = 0; col < local_n_cols; ++col)
  112       {
  113       arrayops::inplace_minus( slice_colptr(slice,col), val, local_n_rows );
  114       }
  115     }
  116   }
  117 
  118 
  119 
  120 template<typename eT>
  121 inline
  122 void
  123 subview_cube<eT>::operator*= (const eT val)
  124   {
  125   arma_extra_debug_sigprint();
  126   
  127   const uword local_n_rows   = n_rows;
  128   const uword local_n_cols   = n_cols;
  129   const uword local_n_slices = n_slices;
  130   
  131   for(uword slice = 0; slice < local_n_slices; ++slice)
  132     {
  133     for(uword col = 0; col < local_n_cols; ++col)
  134       {
  135       arrayops::inplace_mul( slice_colptr(slice,col), val, local_n_rows );
  136       }
  137     }
  138   }
  139 
  140 
  141 
  142 template<typename eT>
  143 inline
  144 void
  145 subview_cube<eT>::operator/= (const eT val)
  146   {
  147   arma_extra_debug_sigprint();
  148   
  149   const uword local_n_rows   = n_rows;
  150   const uword local_n_cols   = n_cols;
  151   const uword local_n_slices = n_slices;
  152   
  153   for(uword slice = 0; slice < local_n_slices; ++slice)
  154     {
  155     for(uword col = 0; col < local_n_cols; ++col)
  156       {
  157       arrayops::inplace_div( slice_colptr(slice,col), val, local_n_rows );
  158       }
  159     }
  160   }
  161 
  162 
  163 
  164 template<typename eT>
  165 template<typename T1>
  166 inline
  167 void
  168 subview_cube<eT>::operator= (const BaseCube<eT,T1>& in)
  169   {
  170   arma_extra_debug_sigprint();
  171   
  172   const unwrap_cube<T1> tmp(in.get_ref());
  173   
  174   const Cube<eT>&         x = tmp.M;
  175         subview_cube<eT>& t = *this;
  176   
  177   arma_debug_assert_same_size(t, x, "copy into subcube");
  178   
  179   const uword t_n_rows   = t.n_rows;
  180   const uword t_n_cols   = t.n_cols;
  181   const uword t_n_slices = t.n_slices;
  182   
  183   for(uword slice = 0; slice < t_n_slices; ++slice)
  184     {
  185     for(uword col = 0; col < t_n_cols; ++col)
  186       {
  187       arrayops::copy( t.slice_colptr(slice,col), x.slice_colptr(slice,col), t_n_rows );
  188       }
  189     }
  190   }
  191 
  192 
  193 
  194 template<typename eT>
  195 template<typename T1>
  196 inline
  197 void
  198 subview_cube<eT>::operator+= (const BaseCube<eT,T1>& in)
  199   {
  200   arma_extra_debug_sigprint();
  201   
  202   const unwrap_cube<T1> tmp(in.get_ref());
  203   
  204   const Cube<eT>&         x = tmp.M;
  205         subview_cube<eT>& t = *this;
  206   
  207   arma_debug_assert_same_size(t, x, "addition");
  208   
  209   const uword t_n_rows   = t.n_rows;
  210   const uword t_n_cols   = t.n_cols;
  211   const uword t_n_slices = t.n_slices;
  212   
  213   for(uword slice = 0; slice < t_n_slices; ++slice)
  214     {
  215     for(uword col = 0; col < t_n_cols; ++col)
  216       {
  217       arrayops::inplace_plus( t.slice_colptr(slice,col), x.slice_colptr(slice,col), t_n_rows );
  218       }
  219     }
  220   }
  221 
  222 
  223 
  224 template<typename eT>
  225 template<typename T1>
  226 inline
  227 void
  228 subview_cube<eT>::operator-= (const BaseCube<eT,T1>& in)
  229   {
  230   arma_extra_debug_sigprint();
  231   
  232   const unwrap_cube<T1> tmp(in.get_ref());
  233   
  234   const Cube<eT>&         x = tmp.M;
  235         subview_cube<eT>& t = *this;
  236   
  237   arma_debug_assert_same_size(t, x, "subtraction");
  238   
  239   const uword t_n_rows   = t.n_rows;
  240   const uword t_n_cols   = t.n_cols;
  241   const uword t_n_slices = t.n_slices;
  242   
  243   for(uword slice = 0; slice < t_n_slices; ++slice)
  244     {
  245     for(uword col = 0; col < t_n_cols; ++col)
  246       {
  247       arrayops::inplace_minus( t.slice_colptr(slice,col), x.slice_colptr(slice,col), t_n_rows );
  248       }
  249     }
  250   }
  251 
  252 
  253 
  254 template<typename eT>
  255 template<typename T1>
  256 inline
  257 void
  258 subview_cube<eT>::operator%= (const BaseCube<eT,T1>& in)
  259   {
  260   arma_extra_debug_sigprint();
  261   
  262   const unwrap_cube<T1> tmp(in.get_ref());
  263   
  264   const Cube<eT>&         x = tmp.M;
  265         subview_cube<eT>& t = *this;
  266   
  267   arma_debug_assert_same_size(t, x, "element-wise multiplication");
  268   
  269   const uword t_n_rows   = t.n_rows;
  270   const uword t_n_cols   = t.n_cols;
  271   const uword t_n_slices = t.n_slices;
  272   
  273   for(uword slice = 0; slice < t_n_slices; ++slice)
  274     {
  275     for(uword col = 0; col < t_n_cols; ++col)
  276       {
  277       arrayops::inplace_mul( t.slice_colptr(slice,col), x.slice_colptr(slice,col), t_n_rows );
  278       }
  279     }
  280   }
  281 
  282 
  283 
  284 template<typename eT>
  285 template<typename T1>
  286 inline
  287 void
  288 subview_cube<eT>::operator/= (const BaseCube<eT,T1>& in)
  289   {
  290   arma_extra_debug_sigprint();
  291   
  292   const unwrap_cube<T1> tmp(in.get_ref());
  293   
  294   const Cube<eT>&         x = tmp.M;
  295         subview_cube<eT>& t = *this;
  296   
  297   arma_debug_assert_same_size(t, x, "element-wise division");
  298   
  299   const uword t_n_rows   = t.n_rows;
  300   const uword t_n_cols   = t.n_cols;
  301   const uword t_n_slices = t.n_slices;
  302   
  303   for(uword slice = 0; slice < t_n_slices; ++slice)
  304     {
  305     for(uword col = 0; col < t_n_cols; ++col)
  306       {
  307       arrayops::inplace_div( t.slice_colptr(slice,col), x.slice_colptr(slice,col), t_n_rows );
  308       }
  309     }
  310   }
  311 
  312 
  313 
  314 //! x.subcube(...) = y.subcube(...)
  315 template<typename eT>
  316 inline
  317 void
  318 subview_cube<eT>::operator= (const subview_cube<eT>& x)
  319   {
  320   arma_extra_debug_sigprint();
  321   
  322   if(check_overlap(x))
  323     {
  324     const Cube<eT> tmp(x);
  325     
  326     (*this).operator=(tmp);
  327     
  328     return;
  329     }
  330   
  331   subview_cube<eT>& t = *this;
  332   
  333   arma_debug_assert_same_size(t, x, "copy into subcube");
  334   
  335   const uword t_n_rows   = t.n_rows;
  336   const uword t_n_cols   = t.n_cols;
  337   const uword t_n_slices = t.n_slices;
  338   
  339   for(uword slice = 0; slice < t_n_slices; ++slice)
  340     {
  341     for(uword col = 0; col < t_n_cols; ++col)
  342       {
  343       arrayops::copy( t.slice_colptr(slice,col), x.slice_colptr(slice,col), t_n_rows );
  344       }
  345     }
  346   }
  347 
  348 
  349 
  350 template<typename eT>
  351 inline
  352 void
  353 subview_cube<eT>::operator+= (const subview_cube<eT>& x)
  354   {
  355   arma_extra_debug_sigprint();
  356   
  357   if(check_overlap(x))
  358     {
  359     const Cube<eT> tmp(x);
  360     
  361     (*this).operator+=(tmp);
  362     
  363     return;
  364     }
  365   
  366   subview_cube<eT>& t = *this;
  367   
  368   arma_debug_assert_same_size(t, x, "addition");
  369   
  370   const uword t_n_rows   = t.n_rows;
  371   const uword t_n_cols   = t.n_cols;
  372   const uword t_n_slices = t.n_slices;
  373   
  374   for(uword slice = 0; slice < t_n_slices; ++slice)
  375     {
  376     for(uword col = 0; col < t_n_cols; ++col)
  377       {
  378       arrayops::inplace_plus( t.slice_colptr(slice,col), x.slice_colptr(slice,col), t_n_rows );
  379       }
  380     }
  381   }
  382 
  383 
  384 
  385 template<typename eT>
  386 inline
  387 void
  388 subview_cube<eT>::operator-= (const subview_cube<eT>& x)
  389   {
  390   arma_extra_debug_sigprint();
  391   
  392   if(check_overlap(x))
  393     {
  394     const Cube<eT> tmp(x);
  395     
  396     (*this).operator-=(tmp);
  397     
  398     return;
  399     }
  400   
  401   subview_cube<eT>& t = *this;
  402   
  403   arma_debug_assert_same_size(t, x, "subtraction");
  404   
  405   const uword t_n_rows   = t.n_rows;
  406   const uword t_n_cols   = t.n_cols;
  407   const uword t_n_slices = t.n_slices;
  408   
  409   for(uword slice = 0; slice < t_n_slices; ++slice)
  410     {
  411     for(uword col = 0; col < t_n_cols; ++col)
  412       {
  413       arrayops::inplace_minus( t.slice_colptr(slice,col), x.slice_colptr(slice,col), t_n_rows );
  414       }
  415     }
  416   }
  417 
  418 
  419 
  420 template<typename eT>
  421 inline
  422 void
  423 subview_cube<eT>::operator%= (const subview_cube<eT>& x)
  424   {
  425   arma_extra_debug_sigprint();
  426   
  427   if(check_overlap(x))
  428     {
  429     const Cube<eT> tmp(x);
  430     
  431     (*this).operator%=(tmp);
  432     
  433     return;
  434     }
  435   
  436   subview_cube<eT>& t = *this;
  437   
  438   arma_debug_assert_same_size(t, x, "element-wise multiplication");
  439   
  440   const uword t_n_rows   = t.n_rows;
  441   const uword t_n_cols   = t.n_cols;
  442   const uword t_n_slices = t.n_slices;
  443   
  444   for(uword slice = 0; slice < t_n_slices; ++slice)
  445     {
  446     for(uword col = 0; col < t_n_cols; ++col)
  447       {
  448       arrayops::inplace_mul( t.slice_colptr(slice,col), x.slice_colptr(slice,col), t_n_rows );
  449       }
  450     }
  451   }
  452 
  453 
  454 
  455 template<typename eT>
  456 inline
  457 void
  458 subview_cube<eT>::operator/= (const subview_cube<eT>& x)
  459   {
  460   arma_extra_debug_sigprint();
  461   
  462   if(check_overlap(x))
  463     {
  464     const Cube<eT> tmp(x);
  465     
  466     (*this).operator/=(tmp);
  467     
  468     return;
  469     }
  470   
  471   subview_cube<eT>& t = *this;
  472   
  473   arma_debug_assert_same_size(t, x, "element-wise division");
  474   
  475   const uword t_n_rows   = t.n_rows;
  476   const uword t_n_cols   = t.n_cols;
  477   const uword t_n_slices = t.n_slices;
  478   
  479   for(uword slice = 0; slice < t_n_slices; ++slice)
  480     {
  481     for(uword col = 0; col < t_n_cols; ++col)
  482       {
  483       arrayops::inplace_div( t.slice_colptr(slice,col), x.slice_colptr(slice,col), t_n_rows );
  484       }
  485     }
  486   }
  487 
  488 
  489 
  490 template<typename eT>
  491 template<typename T1>
  492 inline
  493 void
  494 subview_cube<eT>::operator= (const Base<eT,T1>& in)
  495   {
  496   arma_extra_debug_sigprint();
  497   
  498   const unwrap<T1> tmp(in.get_ref());
  499   
  500   const Mat<eT>&          x = tmp.M;
  501         subview_cube<eT>& t = *this;
  502   
  503   const uword t_n_rows   = t.n_rows;
  504   const uword t_n_cols   = t.n_cols;
  505   const uword t_n_slices = t.n_slices;
  506   
  507   const uword x_n_rows   = x.n_rows;
  508   const uword x_n_cols   = x.n_cols;
  509   
  510   if( ((x_n_rows == 1) || (x_n_cols == 1)) && (t_n_rows == 1) && (t_n_cols == 1) && (x.n_elem == t_n_slices) )
  511     {
  512     Cube<eT>& Q = const_cast< Cube<eT>& >(t.m);
  513     
  514     const uword t_aux_row1   = t.aux_row1;
  515     const uword t_aux_col1   = t.aux_col1;
  516     const uword t_aux_slice1 = t.aux_slice1;
  517     
  518     const eT* x_mem = x.memptr();
  519     
  520     uword i,j;
  521     for(i=0, j=1; j < t_n_slices; i+=2, j+=2)
  522       {
  523       const eT tmp_i = x_mem[i];
  524       const eT tmp_j = x_mem[j];
  525       
  526       Q.at(t_aux_row1, t_aux_col1, t_aux_slice1 + i) = tmp_i;
  527       Q.at(t_aux_row1, t_aux_col1, t_aux_slice1 + j) = tmp_j;
  528       }
  529     
  530     if(i < t_n_slices)
  531       {
  532       Q.at(t_aux_row1, t_aux_col1, t_aux_slice1 + i) = x_mem[i];
  533       }
  534     }
  535   else
  536   if( (t_n_rows == x_n_rows) && (t_n_cols == x_n_cols) && (t_n_slices == 1) )
  537     {
  538     // interpret the matrix as a cube with one slice
  539     
  540     for(uword col = 0; col < t_n_cols; ++col)
  541       {
  542       arrayops::copy( t.slice_colptr(0, col), x.colptr(col), t_n_rows );
  543       }
  544     }
  545   else
  546   if( (t_n_rows == x_n_rows) && (t_n_cols == 1) && (t_n_slices == x_n_cols) )
  547     {
  548     for(uword i=0; i < t_n_slices; ++i)
  549       {
  550       arrayops::copy( t.slice_colptr(i, 0), x.colptr(i), t_n_rows );
  551       }
  552     }
  553   else
  554   if( (t_n_rows == 1) && (t_n_cols == x_n_rows) && (t_n_slices == x_n_cols) )
  555     {
  556     Cube<eT>& Q = const_cast< Cube<eT>& >(t.m);
  557     
  558     const uword t_aux_row1   = t.aux_row1;
  559     const uword t_aux_col1   = t.aux_col1;
  560     const uword t_aux_slice1 = t.aux_slice1;
  561     
  562     for(uword slice=0; slice < t_n_slices; ++slice)
  563       {
  564       const uword mod_slice = t_aux_slice1 + slice;
  565       
  566       const eT* x_colptr = x.colptr(slice);
  567       
  568       uword i,j;
  569       for(i=0, j=1; j < t_n_cols; i+=2, j+=2)
  570         {
  571         const eT tmp_i = x_colptr[i];
  572         const eT tmp_j = x_colptr[j];
  573         
  574         Q.at(t_aux_row1, t_aux_col1 + i, mod_slice) = tmp_i;
  575         Q.at(t_aux_row1, t_aux_col1 + j, mod_slice) = tmp_j;
  576         }
  577       
  578       if(i < t_n_cols)
  579         {
  580         Q.at(t_aux_row1, t_aux_col1 + i, mod_slice) = x_colptr[i];
  581         }
  582       }
  583     }
  584   else
  585     {
  586     if(arma_config::debug)
  587       {
  588       arma_stop_logic_error( arma_incompat_size_string(t, x, "copy into subcube") );
  589       }
  590     }
  591   }
  592 
  593 
  594 
  595 template<typename eT>
  596 template<typename T1>
  597 inline
  598 void
  599 subview_cube<eT>::operator+= (const Base<eT,T1>& in)
  600   {
  601   arma_extra_debug_sigprint();
  602   
  603   const unwrap<T1> tmp(in.get_ref());
  604   
  605   const Mat<eT>&          x = tmp.M;
  606         subview_cube<eT>& t = *this;
  607   
  608   const uword t_n_rows   = t.n_rows;
  609   const uword t_n_cols   = t.n_cols;
  610   const uword t_n_slices = t.n_slices;
  611   
  612   const uword x_n_rows   = x.n_rows;
  613   const uword x_n_cols   = x.n_cols;
  614   
  615   if( ((x_n_rows == 1) || (x_n_cols == 1)) && (t_n_rows == 1) && (t_n_cols == 1) && (x.n_elem == t_n_slices) )
  616     {
  617     Cube<eT>& Q = const_cast< Cube<eT>& >(t.m);
  618     
  619     const uword t_aux_row1   = t.aux_row1;
  620     const uword t_aux_col1   = t.aux_col1;
  621     const uword t_aux_slice1 = t.aux_slice1;
  622     
  623     const eT* x_mem = x.memptr();
  624     
  625     uword i,j;
  626     for(i=0, j=1; j < t_n_slices; i+=2, j+=2)
  627       {
  628       const eT tmp_i = x_mem[i];
  629       const eT tmp_j = x_mem[j];
  630       
  631       Q.at(t_aux_row1, t_aux_col1, t_aux_slice1 + i) += tmp_i;
  632       Q.at(t_aux_row1, t_aux_col1, t_aux_slice1 + j) += tmp_j;
  633       }
  634     
  635     if(i < t_n_slices)
  636       {
  637       Q.at(t_aux_row1, t_aux_col1, t_aux_slice1 + i) += x_mem[i];
  638       }
  639     }
  640   else
  641   if( (t_n_rows == x_n_rows) && (t_n_cols == x_n_cols) && (t_n_slices == 1) )
  642     {
  643     for(uword col = 0; col < t_n_cols; ++col)
  644       {
  645       arrayops::inplace_plus( t.slice_colptr(0, col), x.colptr(col), t_n_rows );
  646       }
  647     }
  648   else
  649   if( (t_n_rows == x_n_rows) && (t_n_cols == 1) && (t_n_slices == x_n_cols) )
  650     {
  651     for(uword i=0; i < t_n_slices; ++i)
  652       {
  653       arrayops::inplace_plus( t.slice_colptr(i, 0), x.colptr(i), t_n_rows );
  654       }
  655     }
  656   else
  657   if( (t_n_rows == 1) && (t_n_cols == x_n_rows) && (t_n_slices == x_n_cols) )
  658     {
  659     Cube<eT>& Q = const_cast< Cube<eT>& >(t.m);
  660     
  661     const uword t_aux_row1   = t.aux_row1;
  662     const uword t_aux_col1   = t.aux_col1;
  663     const uword t_aux_slice1 = t.aux_slice1;
  664     
  665     for(uword slice=0; slice < t_n_slices; ++slice)
  666       {
  667       const uword mod_slice = t_aux_slice1 + slice;
  668       
  669       const eT* x_colptr = x.colptr(slice);
  670       
  671       uword i,j;
  672       for(i=0, j=1; j < t_n_cols; i+=2, j+=2)
  673         {
  674         const eT tmp_i = x_colptr[i];
  675         const eT tmp_j = x_colptr[j];
  676         
  677         Q.at(t_aux_row1, t_aux_col1 + i, mod_slice) += tmp_i;
  678         Q.at(t_aux_row1, t_aux_col1 + j, mod_slice) += tmp_j;
  679         }
  680       
  681       if(i < t_n_cols)
  682         {
  683         Q.at(t_aux_row1, t_aux_col1 + i, mod_slice) += x_colptr[i];
  684         }
  685       }
  686     }
  687   else
  688     {
  689     if(arma_config::debug)
  690       {
  691       arma_stop_logic_error( arma_incompat_size_string(t, x, "addition") );
  692       }
  693     }
  694   }
  695 
  696 
  697 
  698 template<typename eT>
  699 template<typename T1>
  700 inline
  701 void
  702 subview_cube<eT>::operator-= (const Base<eT,T1>& in)
  703   {
  704   arma_extra_debug_sigprint();
  705   
  706   const unwrap<T1> tmp(in.get_ref());
  707   
  708   const Mat<eT>&          x = tmp.M;
  709         subview_cube<eT>& t = *this;
  710   
  711   const uword t_n_rows   = t.n_rows;
  712   const uword t_n_cols   = t.n_cols;
  713   const uword t_n_slices = t.n_slices;
  714   
  715   const uword x_n_rows   = x.n_rows;
  716   const uword x_n_cols   = x.n_cols;
  717   
  718   if( ((x_n_rows == 1) || (x_n_cols == 1)) && (t_n_rows == 1) && (t_n_cols == 1) && (x.n_elem == t_n_slices) )
  719     {
  720     Cube<eT>& Q = const_cast< Cube<eT>& >(t.m);
  721     
  722     const uword t_aux_row1   = t.aux_row1;
  723     const uword t_aux_col1   = t.aux_col1;
  724     const uword t_aux_slice1 = t.aux_slice1;
  725     
  726     const eT* x_mem = x.memptr();
  727     
  728     uword i,j;
  729     for(i=0, j=1; j < t_n_slices; i+=2, j+=2)
  730       {
  731       const eT tmp_i = x_mem[i];
  732       const eT tmp_j = x_mem[j];
  733       
  734       Q.at(t_aux_row1, t_aux_col1, t_aux_slice1 + i) -= tmp_i;
  735       Q.at(t_aux_row1, t_aux_col1, t_aux_slice1 + j) -= tmp_j;
  736       }
  737     
  738     if(i < t_n_slices)
  739       {
  740       Q.at(t_aux_row1, t_aux_col1, t_aux_slice1 + i) -= x_mem[i];
  741       }
  742     }
  743   else
  744   if( (t_n_rows == x_n_rows) && (t_n_cols == x_n_cols) && (t_n_slices == 1) )
  745     {
  746     for(uword col = 0; col < t_n_cols; ++col)
  747       {
  748       arrayops::inplace_minus( t.slice_colptr(0, col), x.colptr(col), t_n_rows );
  749       }
  750     }
  751   else
  752   if( (t_n_rows == x_n_rows) && (t_n_cols == 1) && (t_n_slices == x_n_cols) )
  753     {
  754     for(uword i=0; i < t_n_slices; ++i)
  755       {
  756       arrayops::inplace_minus( t.slice_colptr(i, 0), x.colptr(i), t_n_rows );
  757       }
  758     }
  759   else
  760   if( (t_n_rows == 1) && (t_n_cols == x_n_rows) && (t_n_slices == x_n_cols) )
  761     {
  762     Cube<eT>& Q = const_cast< Cube<eT>& >(t.m);
  763     
  764     const uword t_aux_row1   = t.aux_row1;
  765     const uword t_aux_col1   = t.aux_col1;
  766     const uword t_aux_slice1 = t.aux_slice1;
  767     
  768     for(uword slice=0; slice < t_n_slices; ++slice)
  769       {
  770       const uword mod_slice = t_aux_slice1 + slice;
  771       
  772       const eT* x_colptr = x.colptr(slice);
  773       
  774       uword i,j;
  775       for(i=0, j=1; j < t_n_cols; i+=2, j+=2)
  776         {
  777         const eT tmp_i = x_colptr[i];
  778         const eT tmp_j = x_colptr[j];
  779         
  780         Q.at(t_aux_row1, t_aux_col1 + i, mod_slice) -= tmp_i;
  781         Q.at(t_aux_row1, t_aux_col1 + j, mod_slice) -= tmp_j;
  782         }
  783       
  784       if(i < t_n_cols)
  785         {
  786         Q.at(t_aux_row1, t_aux_col1 + i, mod_slice) -= x_colptr[i];
  787         }
  788       }
  789     }
  790   else
  791     {
  792     if(arma_config::debug)
  793       {
  794       arma_stop_logic_error( arma_incompat_size_string(t, x, "subtraction") );
  795       }
  796     }
  797   }
  798 
  799 
  800 
  801 template<typename eT>
  802 template<typename T1>
  803 inline
  804 void
  805 subview_cube<eT>::operator%= (const Base<eT,T1>& in)
  806   {
  807   arma_extra_debug_sigprint();
  808   
  809   const unwrap<T1> tmp(in.get_ref());
  810   
  811   const Mat<eT>&          x = tmp.M;
  812         subview_cube<eT>& t = *this;
  813   
  814   const uword t_n_rows   = t.n_rows;
  815   const uword t_n_cols   = t.n_cols;
  816   const uword t_n_slices = t.n_slices;
  817   
  818   const uword x_n_rows   = x.n_rows;
  819   const uword x_n_cols   = x.n_cols;
  820   
  821   if( ((x_n_rows == 1) || (x_n_cols == 1)) && (t_n_rows == 1) && (t_n_cols == 1) && (x.n_elem == t_n_slices) )
  822     {
  823     Cube<eT>& Q = const_cast< Cube<eT>& >(t.m);
  824     
  825     const uword t_aux_row1   = t.aux_row1;
  826     const uword t_aux_col1   = t.aux_col1;
  827     const uword t_aux_slice1 = t.aux_slice1;
  828     
  829     const eT* x_mem = x.memptr();
  830     
  831     uword i,j;
  832     for(i=0, j=1; j < t_n_slices; i+=2, j+=2)
  833       {
  834       const eT tmp_i = x_mem[i];
  835       const eT tmp_j = x_mem[j];
  836       
  837       Q.at(t_aux_row1, t_aux_col1, t_aux_slice1 + i) *= tmp_i;
  838       Q.at(t_aux_row1, t_aux_col1, t_aux_slice1 + j) *= tmp_j;
  839       }
  840     
  841     if(i < t_n_slices)
  842       {
  843       Q.at(t_aux_row1, t_aux_col1, t_aux_slice1 + i) *= x_mem[i];
  844       }
  845     }
  846   else
  847   if( (t_n_rows == x_n_rows) && (t_n_cols == x_n_cols) && (t_n_slices == 1) )
  848     {
  849     for(uword col = 0; col < t_n_cols; ++col)
  850       {
  851       arrayops::inplace_mul( t.slice_colptr(0, col), x.colptr(col), t_n_rows );
  852       }
  853     }
  854   else
  855   if( (t_n_rows == x_n_rows) && (t_n_cols == 1) && (t_n_slices == x_n_cols) )
  856     {
  857     for(uword i=0; i < t_n_slices; ++i)
  858       {
  859       arrayops::inplace_mul( t.slice_colptr(i, 0), x.colptr(i), t_n_rows );
  860       }
  861     }
  862   else
  863   if( (t_n_rows == 1) && (t_n_cols == x_n_rows) && (t_n_slices == x_n_cols) )
  864     {
  865     Cube<eT>& Q = const_cast< Cube<eT>& >(t.m);
  866     
  867     const uword t_aux_row1   = t.aux_row1;
  868     const uword t_aux_col1   = t.aux_col1;
  869     const uword t_aux_slice1 = t.aux_slice1;
  870     
  871     for(uword slice=0; slice < t_n_slices; ++slice)
  872       {
  873       const uword mod_slice = t_aux_slice1 + slice;
  874       
  875       const eT* x_colptr = x.colptr(slice);
  876       
  877       uword i,j;
  878       for(i=0, j=1; j < t_n_cols; i+=2, j+=2)
  879         {
  880         const eT tmp_i = x_colptr[i];
  881         const eT tmp_j = x_colptr[j];
  882         
  883         Q.at(t_aux_row1, t_aux_col1 + i, mod_slice) *= tmp_i;
  884         Q.at(t_aux_row1, t_aux_col1 + j, mod_slice) *= tmp_j;
  885         }
  886       
  887       if(i < t_n_cols)
  888         {
  889         Q.at(t_aux_row1, t_aux_col1 + i, mod_slice) *= x_colptr[i];
  890         }
  891       }
  892     }
  893   else
  894     {
  895     if(arma_config::debug)
  896       {
  897       arma_stop_logic_error( arma_incompat_size_string(t, x, "element-wise multiplication") );
  898       }
  899     }
  900   }
  901 
  902 
  903 
  904 template<typename eT>
  905 template<typename T1>
  906 inline
  907 void
  908 subview_cube<eT>::operator/= (const Base<eT,T1>& in)
  909   {
  910   arma_extra_debug_sigprint();
  911   
  912   const unwrap<T1> tmp(in.get_ref());
  913   
  914   const Mat<eT>&          x = tmp.M;
  915         subview_cube<eT>& t = *this;
  916   
  917   const uword t_n_rows   = t.n_rows;
  918   const uword t_n_cols   = t.n_cols;
  919   const uword t_n_slices = t.n_slices;
  920   
  921   const uword x_n_rows   = x.n_rows;
  922   const uword x_n_cols   = x.n_cols;
  923   
  924   if( ((x_n_rows == 1) || (x_n_cols == 1)) && (t_n_rows == 1) && (t_n_cols == 1) && (x.n_elem == t_n_slices) )
  925     {
  926     Cube<eT>& Q = const_cast< Cube<eT>& >(t.m);
  927     
  928     const uword t_aux_row1   = t.aux_row1;
  929     const uword t_aux_col1   = t.aux_col1;
  930     const uword t_aux_slice1 = t.aux_slice1;
  931     
  932     const eT* x_mem = x.memptr();
  933     
  934     uword i,j;
  935     for(i=0, j=1; j < t_n_slices; i+=2, j+=2)
  936       {
  937       const eT tmp_i = x_mem[i];
  938       const eT tmp_j = x_mem[j];
  939       
  940       Q.at(t_aux_row1, t_aux_col1, t_aux_slice1 + i) /= tmp_i;
  941       Q.at(t_aux_row1, t_aux_col1, t_aux_slice1 + j) /= tmp_j;
  942       }
  943     
  944     if(i < t_n_slices)
  945       {
  946       Q.at(t_aux_row1, t_aux_col1, t_aux_slice1 + i) /= x_mem[i];
  947       }
  948     }
  949   else
  950   if( (t_n_rows == x_n_rows) && (t_n_cols == x_n_cols) && (t_n_slices == 1) )
  951     {
  952     for(uword col = 0; col < t_n_cols; ++col)
  953       {
  954       arrayops::inplace_div( t.slice_colptr(0, col), x.colptr(col), t_n_rows );
  955       }
  956     }
  957   else
  958   if( (t_n_rows == x_n_rows) && (t_n_cols == 1) && (t_n_slices == x_n_cols) )
  959     {
  960     for(uword i=0; i < t_n_slices; ++i)
  961       {
  962       arrayops::inplace_div( t.slice_colptr(i, 0), x.colptr(i), t_n_rows );
  963       }
  964     }
  965   else
  966   if( (t_n_rows == 1) && (t_n_cols == x_n_rows) && (t_n_slices == x_n_cols) )
  967     {
  968     Cube<eT>& Q = const_cast< Cube<eT>& >(t.m);
  969     
  970     const uword t_aux_row1   = t.aux_row1;
  971     const uword t_aux_col1   = t.aux_col1;
  972     const uword t_aux_slice1 = t.aux_slice1;
  973     
  974     for(uword slice=0; slice < t_n_slices; ++slice)
  975       {
  976       const uword mod_slice = t_aux_slice1 + slice;
  977       
  978       const eT* x_colptr = x.colptr(slice);
  979       
  980       uword i,j;
  981       for(i=0, j=1; j < t_n_cols; i+=2, j+=2)
  982         {
  983         const eT tmp_i = x_colptr[i];
  984         const eT tmp_j = x_colptr[j];
  985         
  986         Q.at(t_aux_row1, t_aux_col1 + i, mod_slice) /= tmp_i;
  987         Q.at(t_aux_row1, t_aux_col1 + j, mod_slice) /= tmp_j;
  988         }
  989       
  990       if(i < t_n_cols)
  991         {
  992         Q.at(t_aux_row1, t_aux_col1 + i, mod_slice) /= x_colptr[i];
  993         }
  994       }
  995     }
  996   else
  997     {
  998     if(arma_config::debug)
  999       {
 1000       arma_stop_logic_error( arma_incompat_size_string(t, x, "element-wise division") );
 1001       }
 1002     }
 1003   }
 1004 
 1005 
 1006 
 1007 template<typename eT>
 1008 template<typename gen_type>
 1009 inline
 1010 void
 1011 subview_cube<eT>::operator= (const GenCube<eT,gen_type>& in)
 1012   {
 1013   arma_extra_debug_sigprint();
 1014   
 1015   arma_debug_assert_same_size(n_rows, n_cols, n_slices, in.n_rows, in.n_cols, in.n_slices, "copy into subcube");
 1016   
 1017   in.apply(*this);
 1018   }
 1019 
 1020 
 1021 
 1022 //! apply a functor to each element
 1023 template<typename eT>
 1024 template<typename functor>
 1025 inline
 1026 void
 1027 subview_cube<eT>::for_each(functor F)
 1028   {
 1029   arma_extra_debug_sigprint();
 1030   
 1031   Cube<eT>& Q = const_cast< Cube<eT>& >(m);
 1032   
 1033   const uword start_col   = aux_col1;
 1034   const uword start_row   = aux_row1;
 1035   const uword start_slice = aux_slice1;
 1036   
 1037   const uword end_col_plus1   = start_col   + n_cols;
 1038   const uword end_row_plus1   = start_row   + n_rows;
 1039   const uword end_slice_plus1 = start_slice + n_slices;
 1040   
 1041   for(uword uslice = start_slice; uslice < end_slice_plus1; ++uslice)
 1042   for(uword ucol   = start_col;     ucol < end_col_plus1;   ++ucol  )
 1043   for(uword urow   = start_row;     urow < end_row_plus1;   ++urow  )
 1044     {
 1045     F( Q.at(urow, ucol, uslice) );
 1046     }
 1047   }
 1048 
 1049 
 1050 
 1051 template<typename eT>
 1052 template<typename functor>
 1053 inline
 1054 void
 1055 subview_cube<eT>::for_each(functor F) const
 1056   {
 1057   arma_extra_debug_sigprint();
 1058   
 1059   const Cube<eT>& Q = m;
 1060   
 1061   const uword start_col   = aux_col1;
 1062   const uword start_row   = aux_row1;
 1063   const uword start_slice = aux_slice1;
 1064   
 1065   const uword end_col_plus1   = start_col   + n_cols;
 1066   const uword end_row_plus1   = start_row   + n_rows;
 1067   const uword end_slice_plus1 = start_slice + n_slices;
 1068   
 1069   for(uword uslice = start_slice; uslice < end_slice_plus1; ++uslice)
 1070   for(uword ucol   = start_col;     ucol < end_col_plus1;   ++ucol  )
 1071   for(uword urow   = start_row;     urow < end_row_plus1;   ++urow  )
 1072     {
 1073     F( Q.at(urow, ucol, uslice) );
 1074     }
 1075   }
 1076 
 1077 
 1078 
 1079 //! transform each element in the subview using a functor
 1080 template<typename eT>
 1081 template<typename functor>
 1082 inline
 1083 void
 1084 subview_cube<eT>::transform(functor F)
 1085   {
 1086   arma_extra_debug_sigprint();
 1087   
 1088   Cube<eT>& Q = const_cast< Cube<eT>& >(m);
 1089   
 1090   const uword start_col   = aux_col1;
 1091   const uword start_row   = aux_row1;
 1092   const uword start_slice = aux_slice1;
 1093   
 1094   const uword end_col_plus1   = start_col   + n_cols;
 1095   const uword end_row_plus1   = start_row   + n_rows;
 1096   const uword end_slice_plus1 = start_slice + n_slices;
 1097   
 1098   for(uword uslice = start_slice; uslice < end_slice_plus1; ++uslice)
 1099   for(uword ucol   = start_col;     ucol < end_col_plus1;   ++ucol  )
 1100   for(uword urow   = start_row;     urow < end_row_plus1;   ++urow  )
 1101     {
 1102     Q.at(urow, ucol, uslice) = eT( F( Q.at(urow, ucol, uslice) ) );
 1103     }
 1104   }
 1105 
 1106 
 1107 
 1108 //! imbue (fill) the subview with values provided by a functor
 1109 template<typename eT>
 1110 template<typename functor>
 1111 inline
 1112 void
 1113 subview_cube<eT>::imbue(functor F)
 1114   {
 1115   arma_extra_debug_sigprint();
 1116   
 1117   Cube<eT>& Q = const_cast< Cube<eT>& >(m);
 1118   
 1119   const uword start_col   = aux_col1;
 1120   const uword start_row   = aux_row1;
 1121   const uword start_slice = aux_slice1;
 1122   
 1123   const uword end_col_plus1   = start_col   + n_cols;
 1124   const uword end_row_plus1   = start_row   + n_rows;
 1125   const uword end_slice_plus1 = start_slice + n_slices;
 1126   
 1127   for(uword uslice = start_slice; uslice < end_slice_plus1; ++uslice)
 1128   for(uword ucol   = start_col;     ucol < end_col_plus1;   ++ucol  )
 1129   for(uword urow   = start_row;     urow < end_row_plus1;   ++urow  )
 1130     {
 1131     Q.at(urow, ucol, uslice) = eT( F() );
 1132     }
 1133   }
 1134 
 1135 
 1136 
 1137 #if defined(ARMA_USE_CXX11)
 1138   
 1139   //! apply a lambda function to each slice, where each slice is interpreted as a matrix
 1140   template<typename eT>
 1141   inline
 1142   void
 1143   subview_cube<eT>::each_slice(const std::function< void(Mat<eT>&) >& F)
 1144     {
 1145     arma_extra_debug_sigprint();
 1146     
 1147     Mat<eT> tmp1(n_rows, n_cols);
 1148     Mat<eT> tmp2('j', tmp1.memptr(), n_rows, n_cols);
 1149     
 1150     for(uword slice_id=0; slice_id < n_slices; ++slice_id)
 1151       {
 1152       for(uword col_id=0; col_id < n_cols; ++col_id)
 1153         {
 1154         arrayops::copy( tmp1.colptr(col_id), slice_colptr(slice_id, col_id), n_rows );
 1155         }
 1156       
 1157       F(tmp2);
 1158       
 1159       for(uword col_id=0; col_id < n_cols; ++col_id)
 1160         {
 1161         arrayops::copy( slice_colptr(slice_id, col_id), tmp1.colptr(col_id), n_rows );
 1162         }
 1163       }
 1164     }
 1165   
 1166   
 1167   
 1168   template<typename eT>
 1169   inline
 1170   void
 1171   subview_cube<eT>::each_slice(const std::function< void(const Mat<eT>&) >& F) const
 1172     {
 1173     arma_extra_debug_sigprint();
 1174     
 1175           Mat<eT> tmp1(n_rows, n_cols);
 1176     const Mat<eT> tmp2('j', tmp1.memptr(), n_rows, n_cols);
 1177     
 1178     for(uword slice_id=0; slice_id < n_slices; ++slice_id)
 1179       {
 1180       for(uword col_id=0; col_id < n_cols; ++col_id)
 1181         {
 1182         arrayops::copy( tmp1.colptr(col_id), slice_colptr(slice_id, col_id), n_rows );
 1183         }
 1184       
 1185       F(tmp2);
 1186       }
 1187     }
 1188   
 1189 #endif
 1190 
 1191 
 1192 
 1193 template<typename eT>
 1194 inline
 1195 void
 1196 subview_cube<eT>::replace(const eT old_val, const eT new_val)
 1197   {
 1198   arma_extra_debug_sigprint();
 1199   
 1200   const uword local_n_rows   = n_rows;
 1201   const uword local_n_cols   = n_cols;
 1202   const uword local_n_slices = n_slices;
 1203   
 1204   for(uword slice = 0; slice < local_n_slices; ++slice)
 1205     {
 1206     for(uword col = 0; col < local_n_cols; ++col)
 1207       {
 1208       arrayops::replace(slice_colptr(slice,col), local_n_rows, old_val, new_val);
 1209       }
 1210     }
 1211   }
 1212 
 1213 
 1214 
 1215 template<typename eT>
 1216 inline
 1217 void
 1218 subview_cube<eT>::clean(const typename get_pod_type<eT>::result threshold)
 1219   {
 1220   arma_extra_debug_sigprint();
 1221 
 1222   const uword local_n_rows   = n_rows;
 1223   const uword local_n_cols   = n_cols;
 1224   const uword local_n_slices = n_slices;
 1225   
 1226   for(uword slice = 0; slice < local_n_slices; ++slice)
 1227     {
 1228     for(uword col = 0; col < local_n_cols; ++col)
 1229       {
 1230       arrayops::clean( slice_colptr(slice,col), local_n_rows, threshold );
 1231       }
 1232     }
 1233   }
 1234 
 1235 
 1236 
 1237 template<typename eT>
 1238 inline
 1239 void
 1240 subview_cube<eT>::fill(const eT val)
 1241   {
 1242   arma_extra_debug_sigprint();
 1243 
 1244   const uword local_n_rows   = n_rows;
 1245   const uword local_n_cols   = n_cols;
 1246   const uword local_n_slices = n_slices;
 1247   
 1248   for(uword slice = 0; slice < local_n_slices; ++slice)
 1249     {
 1250     for(uword col = 0; col < local_n_cols; ++col)
 1251       {
 1252       arrayops::inplace_set( slice_colptr(slice,col), val, local_n_rows );
 1253       }
 1254     }
 1255   }
 1256 
 1257 
 1258 
 1259 template<typename eT>
 1260 inline
 1261 void
 1262 subview_cube<eT>::zeros()
 1263   {
 1264   arma_extra_debug_sigprint();
 1265   
 1266   const uword local_n_rows   = n_rows;
 1267   const uword local_n_cols   = n_cols;
 1268   const uword local_n_slices = n_slices;
 1269   
 1270   for(uword slice = 0; slice < local_n_slices; ++slice)
 1271     {
 1272     for(uword col = 0; col < local_n_cols; ++col)
 1273       {
 1274       arrayops::fill_zeros( slice_colptr(slice,col), local_n_rows );
 1275       }
 1276     }
 1277   }
 1278 
 1279 
 1280 
 1281 template<typename eT>
 1282 inline
 1283 void
 1284 subview_cube<eT>::ones()
 1285   {
 1286   arma_extra_debug_sigprint();
 1287   
 1288   fill(eT(1));
 1289   }
 1290 
 1291 
 1292 
 1293 template<typename eT>
 1294 inline
 1295 void
 1296 subview_cube<eT>::randu()
 1297   {
 1298   arma_extra_debug_sigprint();
 1299   
 1300   const uword local_n_rows   = n_rows;
 1301   const uword local_n_cols   = n_cols;
 1302   const uword local_n_slices = n_slices;
 1303   
 1304   for(uword slice = 0; slice < local_n_slices; ++slice)
 1305     {
 1306     for(uword col = 0; col < local_n_cols; ++col)
 1307       {
 1308       arma_rng::randu<eT>::fill( slice_colptr(slice,col), local_n_rows );
 1309       }
 1310     }
 1311   }
 1312 
 1313 
 1314 
 1315 template<typename eT>
 1316 inline
 1317 void
 1318 subview_cube<eT>::randn()
 1319   {
 1320   arma_extra_debug_sigprint();
 1321   
 1322   const uword local_n_rows   = n_rows;
 1323   const uword local_n_cols   = n_cols;
 1324   const uword local_n_slices = n_slices;
 1325   
 1326   for(uword slice = 0; slice < local_n_slices; ++slice)
 1327     {
 1328     for(uword col = 0; col < local_n_cols; ++col)
 1329       {
 1330       arma_rng::randn<eT>::fill( slice_colptr(slice,col), local_n_rows );
 1331       }
 1332     }
 1333   }
 1334 
 1335 
 1336 
 1337 template<typename eT>
 1338 inline
 1339 arma_warn_unused
 1340 bool
 1341 subview_cube<eT>::is_finite() const
 1342   {
 1343   arma_extra_debug_sigprint();
 1344   
 1345   const uword local_n_rows   = n_rows;
 1346   const uword local_n_cols   = n_cols;
 1347   const uword local_n_slices = n_slices;
 1348   
 1349   for(uword slice = 0; slice < local_n_slices; ++slice)
 1350     {
 1351     for(uword col = 0; col < local_n_cols; ++col)
 1352       {
 1353       if(arrayops::is_finite(slice_colptr(slice,col), local_n_rows) == false)  { return false; }
 1354       }
 1355     }
 1356   
 1357   return true;
 1358   }
 1359 
 1360 
 1361 
 1362 template<typename eT>
 1363 inline
 1364 arma_warn_unused
 1365 bool
 1366 subview_cube<eT>::has_inf() const
 1367   {
 1368   arma_extra_debug_sigprint();
 1369   
 1370   const uword local_n_rows   = n_rows;
 1371   const uword local_n_cols   = n_cols;
 1372   const uword local_n_slices = n_slices;
 1373   
 1374   for(uword slice = 0; slice < local_n_slices; ++slice)
 1375     {
 1376     for(uword col = 0; col < local_n_cols; ++col)
 1377       {
 1378       if(arrayops::has_inf(slice_colptr(slice,col), local_n_rows))  { return true; }
 1379       }
 1380     }
 1381   
 1382   return false;
 1383   }
 1384 
 1385 
 1386 
 1387 template<typename eT>
 1388 inline
 1389 arma_warn_unused
 1390 bool
 1391 subview_cube<eT>::has_nan() const
 1392   {
 1393   arma_extra_debug_sigprint();
 1394   
 1395   const uword local_n_rows   = n_rows;
 1396   const uword local_n_cols   = n_cols;
 1397   const uword local_n_slices = n_slices;
 1398   
 1399   for(uword slice = 0; slice < local_n_slices; ++slice)
 1400     {
 1401     for(uword col = 0; col < local_n_cols; ++col)
 1402       {
 1403       if(arrayops::has_nan(slice_colptr(slice,col), local_n_rows))  { return true; }
 1404       }
 1405     }
 1406   
 1407   return false;
 1408   }
 1409 
 1410 
 1411 
 1412 template<typename eT>
 1413 inline
 1414 eT
 1415 subview_cube<eT>::at_alt(const uword i) const
 1416   {
 1417   return operator[](i);
 1418   }
 1419 
 1420 
 1421 
 1422 template<typename eT>
 1423 inline
 1424 eT&
 1425 subview_cube<eT>::operator[](const uword i)
 1426   {
 1427   const uword in_slice = i / n_elem_slice;
 1428   const uword offset   = in_slice * n_elem_slice;
 1429   const uword j        = i - offset;
 1430   
 1431   const uword in_col   = j / n_rows;
 1432   const uword in_row   = j % n_rows;
 1433 
 1434   const uword index = (in_slice + aux_slice1)*m.n_elem_slice + (in_col + aux_col1)*m.n_rows + aux_row1 + in_row;
 1435   
 1436   return access::rw( (const_cast< Cube<eT>& >(m)).mem[index] );
 1437   }
 1438 
 1439 
 1440 
 1441 template<typename eT>
 1442 inline
 1443 eT
 1444 subview_cube<eT>::operator[](const uword i) const
 1445   {
 1446   const uword in_slice = i / n_elem_slice;
 1447   const uword offset   = in_slice * n_elem_slice;
 1448   const uword j        = i - offset;
 1449   
 1450   const uword in_col   = j / n_rows;
 1451   const uword in_row   = j % n_rows;
 1452 
 1453   const uword index = (in_slice + aux_slice1)*m.n_elem_slice + (in_col + aux_col1)*m.n_rows + aux_row1 + in_row;
 1454   
 1455   return m.mem[index];
 1456   }
 1457 
 1458 
 1459 
 1460 template<typename eT>
 1461 inline
 1462 eT&
 1463 subview_cube<eT>::operator()(const uword i)
 1464   {
 1465   arma_debug_check( (i >= n_elem), "subview_cube::operator(): index out of bounds" );
 1466   
 1467   const uword in_slice = i / n_elem_slice;
 1468   const uword offset   = in_slice * n_elem_slice;
 1469   const uword j        = i - offset;
 1470   
 1471   const uword in_col   = j / n_rows;
 1472   const uword in_row   = j % n_rows;
 1473 
 1474   const uword index = (in_slice + aux_slice1)*m.n_elem_slice + (in_col + aux_col1)*m.n_rows + aux_row1 + in_row;
 1475   
 1476   return access::rw( (const_cast< Cube<eT>& >(m)).mem[index] );
 1477   }
 1478 
 1479 
 1480 
 1481 template<typename eT>
 1482 inline
 1483 eT
 1484 subview_cube<eT>::operator()(const uword i) const
 1485   {
 1486   arma_debug_check( (i >= n_elem), "subview_cube::operator(): index out of bounds" );
 1487   
 1488   const uword in_slice = i / n_elem_slice;
 1489   const uword offset   = in_slice * n_elem_slice;
 1490   const uword j        = i - offset;
 1491   
 1492   const uword in_col   = j / n_rows;
 1493   const uword in_row   = j % n_rows;
 1494 
 1495   const uword index = (in_slice + aux_slice1)*m.n_elem_slice + (in_col + aux_col1)*m.n_rows + aux_row1 + in_row;
 1496   
 1497   return m.mem[index];
 1498   }
 1499 
 1500 
 1501 
 1502 template<typename eT>
 1503 arma_inline
 1504 eT&
 1505 subview_cube<eT>::operator()(const uword in_row, const uword in_col, const uword in_slice)
 1506   {
 1507   arma_debug_check( ( (in_row >= n_rows) || (in_col >= n_cols) || (in_slice >= n_slices) ), "subview_cube::operator(): location out of bounds" );
 1508   
 1509   const uword index = (in_slice + aux_slice1)*m.n_elem_slice + (in_col + aux_col1)*m.n_rows + aux_row1 + in_row;
 1510   
 1511   return access::rw( (const_cast< Cube<eT>& >(m)).mem[index] );
 1512   }
 1513 
 1514 
 1515 
 1516 template<typename eT>
 1517 arma_inline
 1518 eT
 1519 subview_cube<eT>::operator()(const uword in_row, const uword in_col, const uword in_slice) const
 1520   {
 1521   arma_debug_check( ( (in_row >= n_rows) || (in_col >= n_cols) || (in_slice >= n_slices) ), "subview_cube::operator(): location out of bounds" );
 1522   
 1523   const uword index = (in_slice + aux_slice1)*m.n_elem_slice + (in_col + aux_col1)*m.n_rows + aux_row1 + in_row;
 1524   
 1525   return m.mem[index];
 1526   }
 1527 
 1528 
 1529 
 1530 template<typename eT>
 1531 arma_inline
 1532 eT&
 1533 subview_cube<eT>::at(const uword in_row, const uword in_col, const uword in_slice)
 1534   {
 1535   const uword index = (in_slice + aux_slice1)*m.n_elem_slice + (in_col + aux_col1)*m.n_rows + aux_row1 + in_row;
 1536   
 1537   return access::rw( (const_cast< Cube<eT>& >(m)).mem[index] );
 1538   }
 1539 
 1540 
 1541 
 1542 template<typename eT>
 1543 arma_inline
 1544 eT
 1545 subview_cube<eT>::at(const uword in_row, const uword in_col, const uword in_slice) const
 1546   {
 1547   const uword index = (in_slice + aux_slice1)*m.n_elem_slice + (in_col + aux_col1)*m.n_rows + aux_row1 + in_row;
 1548   
 1549   return m.mem[index];
 1550   }
 1551 
 1552 
 1553 
 1554 template<typename eT>
 1555 arma_inline
 1556 eT*
 1557 subview_cube<eT>::slice_colptr(const uword in_slice, const uword in_col)
 1558   {
 1559   return & access::rw((const_cast< Cube<eT>& >(m)).mem[  (in_slice + aux_slice1)*m.n_elem_slice + (in_col + aux_col1)*m.n_rows + aux_row1  ]);
 1560   }
 1561 
 1562 
 1563 
 1564 template<typename eT>
 1565 arma_inline
 1566 const eT*
 1567 subview_cube<eT>::slice_colptr(const uword in_slice, const uword in_col) const
 1568   {
 1569   return & m.mem[ (in_slice + aux_slice1)*m.n_elem_slice + (in_col + aux_col1)*m.n_rows + aux_row1 ];
 1570   }
 1571 
 1572 
 1573 
 1574 template<typename eT>
 1575 inline
 1576 bool
 1577 subview_cube<eT>::check_overlap(const subview_cube<eT>& x) const
 1578   {
 1579   const subview_cube<eT>& t = *this;
 1580   
 1581   if(&t.m != &x.m)
 1582     {
 1583     return false;
 1584     }
 1585   else
 1586     {
 1587     if( (t.n_elem == 0) || (x.n_elem == 0) )
 1588       {
 1589       return false;
 1590       }
 1591     else
 1592       {
 1593       const uword t_row_start  = t.aux_row1;
 1594       const uword t_row_end_p1 = t_row_start + t.n_rows;
 1595       
 1596       const uword t_col_start  = t.aux_col1;
 1597       const uword t_col_end_p1 = t_col_start + t.n_cols;
 1598       
 1599       const uword t_slice_start  = t.aux_slice1;
 1600       const uword t_slice_end_p1 = t_slice_start + t.n_slices;
 1601       
 1602       
 1603       const uword x_row_start  = x.aux_row1;
 1604       const uword x_row_end_p1 = x_row_start + x.n_rows;
 1605       
 1606       const uword x_col_start  = x.aux_col1;
 1607       const uword x_col_end_p1 = x_col_start + x.n_cols;
 1608       
 1609       const uword x_slice_start  = x.aux_slice1;
 1610       const uword x_slice_end_p1 = x_slice_start + x.n_slices;
 1611       
 1612       
 1613       const bool outside_rows   = ( (x_row_start   >= t_row_end_p1  ) || (t_row_start   >= x_row_end_p1  ) );
 1614       const bool outside_cols   = ( (x_col_start   >= t_col_end_p1  ) || (t_col_start   >= x_col_end_p1  ) );
 1615       const bool outside_slices = ( (x_slice_start >= t_slice_end_p1) || (t_slice_start >= x_slice_end_p1) );
 1616       
 1617       return ( (outside_rows == false) && (outside_cols == false) && (outside_slices == false) );
 1618       }
 1619     }
 1620   }
 1621 
 1622 
 1623 
 1624 template<typename eT>
 1625 inline
 1626 bool
 1627 subview_cube<eT>::check_overlap(const Mat<eT>& x) const
 1628   {
 1629   const subview_cube<eT>& t = *this;
 1630   
 1631   const uword t_aux_slice1        = t.aux_slice1;
 1632   const uword t_aux_slice2_plus_1 = t_aux_slice1 + t.n_slices;
 1633   
 1634   for(uword slice = t_aux_slice1; slice < t_aux_slice2_plus_1; ++slice)
 1635     {
 1636     if(t.m.mat_ptrs[slice] != NULL)
 1637       {
 1638       const Mat<eT>& y = *(t.m.mat_ptrs[slice]);
 1639       
 1640       if( x.memptr() == y.memptr() )  { return true; }
 1641       }
 1642     }
 1643   
 1644   return false;
 1645   }
 1646 
 1647 
 1648 
 1649 //! cube X = Y.subcube(...)
 1650 template<typename eT>
 1651 inline
 1652 void
 1653 subview_cube<eT>::extract(Cube<eT>& out, const subview_cube<eT>& in)
 1654   {
 1655   arma_extra_debug_sigprint();
 1656 
 1657   // NOTE: we're assuming that the cube has already been set to the correct size and there is no aliasing;
 1658   // size setting and alias checking is done by either the Cube contructor or operator=()
 1659   
 1660   const uword n_rows   = in.n_rows;
 1661   const uword n_cols   = in.n_cols;
 1662   const uword n_slices = in.n_slices;
 1663   
 1664   arma_extra_debug_print(arma_str::format("out.n_rows = %d   out.n_cols = %d    out.n_slices = %d    in.m.n_rows = %d   in.m.n_cols = %d   in.m.n_slices = %d") % out.n_rows % out.n_cols % out.n_slices % in.m.n_rows % in.m.n_cols % in.m.n_slices);
 1665   
 1666   
 1667   for(uword slice = 0; slice < n_slices; ++slice)
 1668     {
 1669     for(uword col = 0; col < n_cols; ++col)
 1670       {
 1671       arrayops::copy( out.slice_colptr(slice,col), in.slice_colptr(slice,col), n_rows );
 1672       }
 1673     }
 1674   }
 1675 
 1676 
 1677 
 1678 //! cube X += Y.subcube(...)
 1679 template<typename eT>
 1680 inline
 1681 void
 1682 subview_cube<eT>::plus_inplace(Cube<eT>& out, const subview_cube<eT>& in)
 1683   {
 1684   arma_extra_debug_sigprint();
 1685   
 1686   arma_debug_assert_same_size(out, in, "addition");
 1687   
 1688   const uword n_rows   = out.n_rows;
 1689   const uword n_cols   = out.n_cols;
 1690   const uword n_slices = out.n_slices;
 1691   
 1692   for(uword slice = 0; slice<n_slices; ++slice)
 1693     {
 1694     for(uword col = 0; col<n_cols; ++col)
 1695       {
 1696       arrayops::inplace_plus( out.slice_colptr(slice,col), in.slice_colptr(slice,col), n_rows );
 1697       }
 1698     }
 1699   }
 1700 
 1701 
 1702 
 1703 //! cube X -= Y.subcube(...)
 1704 template<typename eT>
 1705 inline
 1706 void
 1707 subview_cube<eT>::minus_inplace(Cube<eT>& out, const subview_cube<eT>& in)
 1708   {
 1709   arma_extra_debug_sigprint();
 1710   
 1711   arma_debug_assert_same_size(out, in, "subtraction");
 1712   
 1713   const uword n_rows   = out.n_rows;
 1714   const uword n_cols   = out.n_cols;
 1715   const uword n_slices = out.n_slices;
 1716   
 1717   for(uword slice = 0; slice<n_slices; ++slice)
 1718     {
 1719     for(uword col = 0; col<n_cols; ++col)
 1720       {
 1721       arrayops::inplace_minus( out.slice_colptr(slice,col), in.slice_colptr(slice,col), n_rows );
 1722       }
 1723     }
 1724   }
 1725 
 1726 
 1727 
 1728 //! cube X %= Y.subcube(...)
 1729 template<typename eT>
 1730 inline
 1731 void
 1732 subview_cube<eT>::schur_inplace(Cube<eT>& out, const subview_cube<eT>& in)
 1733   {
 1734   arma_extra_debug_sigprint();
 1735   
 1736   arma_debug_assert_same_size(out, in, "element-wise multiplication");
 1737   
 1738   const uword n_rows   = out.n_rows;
 1739   const uword n_cols   = out.n_cols;
 1740   const uword n_slices = out.n_slices;
 1741   
 1742   for(uword slice = 0; slice<n_slices; ++slice)
 1743     {
 1744     for(uword col = 0; col<n_cols; ++col)
 1745       {
 1746       arrayops::inplace_mul( out.slice_colptr(slice,col), in.slice_colptr(slice,col), n_rows );
 1747       }
 1748     }
 1749   }
 1750 
 1751 
 1752 
 1753 //! cube X /= Y.subcube(...)
 1754 template<typename eT>
 1755 inline
 1756 void
 1757 subview_cube<eT>::div_inplace(Cube<eT>& out, const subview_cube<eT>& in)
 1758   {
 1759   arma_extra_debug_sigprint();
 1760   
 1761   arma_debug_assert_same_size(out, in, "element-wise division");
 1762   
 1763   const uword n_rows   = out.n_rows;
 1764   const uword n_cols   = out.n_cols;
 1765   const uword n_slices = out.n_slices;
 1766   
 1767   for(uword slice = 0; slice<n_slices; ++slice)
 1768     {
 1769     for(uword col = 0; col<n_cols; ++col)
 1770       {
 1771       arrayops::inplace_div( out.slice_colptr(slice,col), in.slice_colptr(slice,col), n_rows );
 1772       }
 1773     }
 1774   }
 1775 
 1776 
 1777 
 1778 //! mat X = Y.subcube(...)
 1779 template<typename eT>
 1780 inline
 1781 void
 1782 subview_cube<eT>::extract(Mat<eT>& out, const subview_cube<eT>& in)
 1783   {
 1784   arma_extra_debug_sigprint();
 1785   
 1786   arma_debug_assert_cube_as_mat(out, in, "copy into matrix", false);
 1787   
 1788   const uword in_n_rows   = in.n_rows;
 1789   const uword in_n_cols   = in.n_cols;
 1790   const uword in_n_slices = in.n_slices;
 1791   
 1792   const uword out_vec_state = out.vec_state;
 1793   
 1794   if(in_n_slices == 1)
 1795     {
 1796     out.set_size(in_n_rows, in_n_cols);
 1797     
 1798     for(uword col=0; col < in_n_cols; ++col)
 1799       {
 1800       arrayops::copy( out.colptr(col), in.slice_colptr(0, col), in_n_rows );
 1801       }
 1802     }
 1803   else
 1804     {
 1805     if(out_vec_state == 0)
 1806       {
 1807       if(in_n_cols == 1)
 1808         {
 1809         out.set_size(in_n_rows, in_n_slices);
 1810         
 1811         for(uword i=0; i < in_n_slices; ++i)
 1812           {
 1813           arrayops::copy( out.colptr(i), in.slice_colptr(i, 0), in_n_rows );
 1814           }
 1815         }
 1816       else
 1817       if(in_n_rows == 1)
 1818         {
 1819         const Cube<eT>& Q = in.m;
 1820         
 1821         const uword in_aux_row1   = in.aux_row1;
 1822         const uword in_aux_col1   = in.aux_col1;
 1823         const uword in_aux_slice1 = in.aux_slice1;
 1824         
 1825         out.set_size(in_n_cols, in_n_slices);
 1826         
 1827         for(uword slice=0; slice < in_n_slices; ++slice)
 1828           {
 1829           const uword mod_slice = in_aux_slice1 + slice;
 1830           
 1831           eT* out_colptr = out.colptr(slice);
 1832           
 1833           uword i,j;
 1834           for(i=0, j=1; j < in_n_cols; i+=2, j+=2)
 1835             {
 1836             const eT tmp_i = Q.at(in_aux_row1, in_aux_col1 + i, mod_slice);
 1837             const eT tmp_j = Q.at(in_aux_row1, in_aux_col1 + j, mod_slice);
 1838             
 1839             out_colptr[i] = tmp_i;
 1840             out_colptr[j] = tmp_j;
 1841             }
 1842           
 1843           if(i < in_n_cols)
 1844             {
 1845             out_colptr[i] = Q.at(in_aux_row1, in_aux_col1 + i, mod_slice);
 1846             }
 1847           }
 1848         }
 1849       }
 1850     else
 1851       {
 1852       out.set_size(in_n_slices);
 1853       
 1854       eT* out_mem = out.memptr();
 1855       
 1856       const Cube<eT>& Q = in.m;
 1857       
 1858       const uword in_aux_row1   = in.aux_row1;
 1859       const uword in_aux_col1   = in.aux_col1;
 1860       const uword in_aux_slice1 = in.aux_slice1;
 1861       
 1862       for(uword i=0; i<in_n_slices; ++i)
 1863         {
 1864         out_mem[i] = Q.at(in_aux_row1, in_aux_col1, in_aux_slice1 + i);
 1865         }
 1866       }
 1867     }
 1868   }
 1869 
 1870 
 1871 
 1872 //! mat X += Y.subcube(...)
 1873 template<typename eT>
 1874 inline
 1875 void
 1876 subview_cube<eT>::plus_inplace(Mat<eT>& out, const subview_cube<eT>& in)
 1877   {
 1878   arma_extra_debug_sigprint();
 1879   
 1880   arma_debug_assert_cube_as_mat(out, in, "addition", true);
 1881   
 1882   const uword in_n_rows   = in.n_rows;
 1883   const uword in_n_cols   = in.n_cols;
 1884   const uword in_n_slices = in.n_slices;
 1885   
 1886   const uword out_n_rows    = out.n_rows;
 1887   const uword out_n_cols    = out.n_cols;
 1888   const uword out_vec_state = out.vec_state;
 1889   
 1890   if(in_n_slices == 1)
 1891     {
 1892     if( (arma_config::debug) && ((out_n_rows != in_n_rows) || (out_n_cols != in_n_cols)) )
 1893       {
 1894       std::ostringstream tmp;
 1895       
 1896       tmp
 1897         << "in-place addition: "
 1898         << out_n_rows << 'x' << out_n_cols << " output matrix is incompatible with "
 1899         <<  in_n_rows << 'x' <<  in_n_cols << 'x' << in_n_slices << " cube interpreted as "
 1900         <<  in_n_rows << 'x' <<  in_n_cols << " matrix";
 1901       
 1902       arma_stop_logic_error(tmp.str());
 1903       }
 1904     
 1905     for(uword col=0; col < in_n_cols; ++col)
 1906       {
 1907       arrayops::inplace_plus( out.colptr(col), in.slice_colptr(0, col), in_n_rows );
 1908       }
 1909     }
 1910   else
 1911     {
 1912     if(out_vec_state == 0)
 1913       {
 1914       if( (in_n_rows == out_n_rows) && (in_n_cols == 1) && (in_n_slices == out_n_cols) )
 1915         {
 1916         for(uword i=0; i < in_n_slices; ++i)
 1917           {
 1918           arrayops::inplace_plus( out.colptr(i), in.slice_colptr(i, 0), in_n_rows );
 1919           }
 1920         }
 1921       else
 1922       if( (in_n_rows == 1) && (in_n_cols == out_n_rows) && (in_n_slices == out_n_cols) )
 1923         {
 1924         const Cube<eT>& Q = in.m;
 1925         
 1926         const uword in_aux_row1   = in.aux_row1;
 1927         const uword in_aux_col1   = in.aux_col1;
 1928         const uword in_aux_slice1 = in.aux_slice1;
 1929         
 1930         for(uword slice=0; slice < in_n_slices; ++slice)
 1931           {
 1932           const uword mod_slice = in_aux_slice1 + slice;
 1933           
 1934           eT* out_colptr = out.colptr(slice);
 1935           
 1936           uword i,j;
 1937           for(i=0, j=1; j < in_n_cols; i+=2, j+=2)
 1938             {
 1939             const eT tmp_i = Q.at(in_aux_row1, in_aux_col1 + i, mod_slice);
 1940             const eT tmp_j = Q.at(in_aux_row1, in_aux_col1 + j, mod_slice);
 1941             
 1942             out_colptr[i] += tmp_i;
 1943             out_colptr[j] += tmp_j;
 1944             }
 1945           
 1946           if(i < in_n_cols)
 1947             {
 1948             out_colptr[i] += Q.at(in_aux_row1, in_aux_col1 + i, mod_slice);
 1949             }
 1950           }
 1951         }
 1952       }
 1953     else
 1954       {
 1955       eT* out_mem = out.memptr();
 1956       
 1957       const Cube<eT>& Q = in.m;
 1958       
 1959       const uword in_aux_row1   = in.aux_row1;
 1960       const uword in_aux_col1   = in.aux_col1;
 1961       const uword in_aux_slice1 = in.aux_slice1;
 1962       
 1963       for(uword i=0; i<in_n_slices; ++i)
 1964         {
 1965         out_mem[i] += Q.at(in_aux_row1, in_aux_col1, in_aux_slice1 + i);
 1966         }
 1967       }
 1968     }
 1969   }
 1970 
 1971 
 1972 
 1973 //! mat X -= Y.subcube(...)
 1974 template<typename eT>
 1975 inline
 1976 void
 1977 subview_cube<eT>::minus_inplace(Mat<eT>& out, const subview_cube<eT>& in)
 1978   {
 1979   arma_extra_debug_sigprint();
 1980   
 1981   arma_debug_assert_cube_as_mat(out, in, "subtraction", true);
 1982   
 1983   const uword in_n_rows   = in.n_rows;
 1984   const uword in_n_cols   = in.n_cols;
 1985   const uword in_n_slices = in.n_slices;
 1986   
 1987   const uword out_n_rows    = out.n_rows;
 1988   const uword out_n_cols    = out.n_cols;
 1989   const uword out_vec_state = out.vec_state;
 1990   
 1991   if(in_n_slices == 1)
 1992     {
 1993     if( (arma_config::debug) && ((out_n_rows != in_n_rows) || (out_n_cols != in_n_cols)) )
 1994       {
 1995       std::ostringstream tmp;
 1996       
 1997       tmp
 1998         << "in-place subtraction: "
 1999         << out_n_rows << 'x' << out_n_cols << " output matrix is incompatible with "
 2000         <<  in_n_rows << 'x' <<  in_n_cols << 'x' << in_n_slices << " cube interpreted as "
 2001         <<  in_n_rows << 'x' <<  in_n_cols << " matrix";
 2002       
 2003       arma_stop_logic_error(tmp.str());
 2004       }
 2005     
 2006     for(uword col=0; col < in_n_cols; ++col)
 2007       {
 2008       arrayops::inplace_minus( out.colptr(col), in.slice_colptr(0, col), in_n_rows );
 2009       }
 2010     }
 2011   else
 2012     {
 2013     if(out_vec_state == 0)
 2014       {
 2015       if( (in_n_rows == out_n_rows) && (in_n_cols == 1) && (in_n_slices == out_n_cols) )
 2016         {
 2017         for(uword i=0; i < in_n_slices; ++i)
 2018           {
 2019           arrayops::inplace_minus( out.colptr(i), in.slice_colptr(i, 0), in_n_rows );
 2020           }
 2021         }
 2022       else
 2023       if( (in_n_rows == 1) && (in_n_cols == out_n_rows) && (in_n_slices == out_n_cols) )
 2024         {
 2025         const Cube<eT>& Q = in.m;
 2026         
 2027         const uword in_aux_row1   = in.aux_row1;
 2028         const uword in_aux_col1   = in.aux_col1;
 2029         const uword in_aux_slice1 = in.aux_slice1;
 2030         
 2031         for(uword slice=0; slice < in_n_slices; ++slice)
 2032           {
 2033           const uword mod_slice = in_aux_slice1 + slice;
 2034           
 2035           eT* out_colptr = out.colptr(slice);
 2036           
 2037           uword i,j;
 2038           for(i=0, j=1; j < in_n_cols; i+=2, j+=2)
 2039             {
 2040             const eT tmp_i = Q.at(in_aux_row1, in_aux_col1 + i, mod_slice);
 2041             const eT tmp_j = Q.at(in_aux_row1, in_aux_col1 + j, mod_slice);
 2042             
 2043             out_colptr[i] -= tmp_i;
 2044             out_colptr[j] -= tmp_j;
 2045             }
 2046           
 2047           if(i < in_n_cols)
 2048             {
 2049             out_colptr[i] -= Q.at(in_aux_row1, in_aux_col1 + i, mod_slice);
 2050             }
 2051           }
 2052         }
 2053       }
 2054     else
 2055       {
 2056       eT* out_mem = out.memptr();
 2057       
 2058       const Cube<eT>& Q = in.m;
 2059       
 2060       const uword in_aux_row1   = in.aux_row1;
 2061       const uword in_aux_col1   = in.aux_col1;
 2062       const uword in_aux_slice1 = in.aux_slice1;
 2063       
 2064       for(uword i=0; i<in_n_slices; ++i)
 2065         {
 2066         out_mem[i] -= Q.at(in_aux_row1, in_aux_col1, in_aux_slice1 + i);
 2067         }
 2068       }
 2069     }
 2070   }
 2071 
 2072 
 2073 
 2074 //! mat X %= Y.subcube(...)
 2075 template<typename eT>
 2076 inline
 2077 void
 2078 subview_cube<eT>::schur_inplace(Mat<eT>& out, const subview_cube<eT>& in)
 2079   {
 2080   arma_extra_debug_sigprint();
 2081   
 2082   arma_debug_assert_cube_as_mat(out, in, "element-wise multiplication", true);
 2083   
 2084   const uword in_n_rows   = in.n_rows;
 2085   const uword in_n_cols   = in.n_cols;
 2086   const uword in_n_slices = in.n_slices;
 2087   
 2088   const uword out_n_rows    = out.n_rows;
 2089   const uword out_n_cols    = out.n_cols;
 2090   const uword out_vec_state = out.vec_state;
 2091   
 2092   if(in_n_slices == 1)
 2093     {
 2094     if( (arma_config::debug) && ((out_n_rows != in_n_rows) || (out_n_cols != in_n_cols)) )
 2095       {
 2096       std::ostringstream tmp;
 2097       
 2098       tmp
 2099         << "in-place element-wise multiplication: "
 2100         << out_n_rows << 'x' << out_n_cols << " output matrix is incompatible with "
 2101         <<  in_n_rows << 'x' <<  in_n_cols << 'x' << in_n_slices << " cube interpreted as "
 2102         <<  in_n_rows << 'x' <<  in_n_cols << " matrix";
 2103       
 2104       arma_stop_logic_error(tmp.str());
 2105       }
 2106     
 2107     for(uword col=0; col < in_n_cols; ++col)
 2108       {
 2109       arrayops::inplace_mul( out.colptr(col), in.slice_colptr(0, col), in_n_rows );
 2110       }
 2111     }
 2112   else
 2113     {
 2114     if(out_vec_state == 0)
 2115       {
 2116       if( (in_n_rows == out_n_rows) && (in_n_cols == 1) && (in_n_slices == out_n_cols) )
 2117         {
 2118         for(uword i=0; i < in_n_slices; ++i)
 2119           {
 2120           arrayops::inplace_mul( out.colptr(i), in.slice_colptr(i, 0), in_n_rows );
 2121           }
 2122         }
 2123       else
 2124       if( (in_n_rows == 1) && (in_n_cols == out_n_rows) && (in_n_slices == out_n_cols) )
 2125         {
 2126         const Cube<eT>& Q = in.m;
 2127         
 2128         const uword in_aux_row1   = in.aux_row1;
 2129         const uword in_aux_col1   = in.aux_col1;
 2130         const uword in_aux_slice1 = in.aux_slice1;
 2131         
 2132         for(uword slice=0; slice < in_n_slices; ++slice)
 2133           {
 2134           const uword mod_slice = in_aux_slice1 + slice;
 2135           
 2136           eT* out_colptr = out.colptr(slice);
 2137           
 2138           uword i,j;
 2139           for(i=0, j=1; j < in_n_cols; i+=2, j+=2)
 2140             {
 2141             const eT tmp_i = Q.at(in_aux_row1, in_aux_col1 + i, mod_slice);
 2142             const eT tmp_j = Q.at(in_aux_row1, in_aux_col1 + j, mod_slice);
 2143             
 2144             out_colptr[i] *= tmp_i;
 2145             out_colptr[j] *= tmp_j;
 2146             }
 2147           
 2148           if(i < in_n_cols)
 2149             {
 2150             out_colptr[i] *= Q.at(in_aux_row1, in_aux_col1 + i, mod_slice);
 2151             }
 2152           }
 2153         }
 2154       }
 2155     else
 2156       {
 2157       eT* out_mem = out.memptr();
 2158       
 2159       const Cube<eT>& Q = in.m;
 2160       
 2161       const uword in_aux_row1   = in.aux_row1;
 2162       const uword in_aux_col1   = in.aux_col1;
 2163       const uword in_aux_slice1 = in.aux_slice1;
 2164       
 2165       for(uword i=0; i<in_n_slices; ++i)
 2166         {
 2167         out_mem[i] *= Q.at(in_aux_row1, in_aux_col1, in_aux_slice1 + i);
 2168         }
 2169       }
 2170     }
 2171   }
 2172 
 2173 
 2174 
 2175 //! mat X /= Y.subcube(...)
 2176 template<typename eT>
 2177 inline
 2178 void
 2179 subview_cube<eT>::div_inplace(Mat<eT>& out, const subview_cube<eT>& in)
 2180   {
 2181   arma_extra_debug_sigprint();
 2182   
 2183   arma_debug_assert_cube_as_mat(out, in, "element-wise division", true);
 2184   
 2185   const uword in_n_rows   = in.n_rows;
 2186   const uword in_n_cols   = in.n_cols;
 2187   const uword in_n_slices = in.n_slices;
 2188   
 2189   const uword out_n_rows    = out.n_rows;
 2190   const uword out_n_cols    = out.n_cols;
 2191   const uword out_vec_state = out.vec_state;
 2192   
 2193   if(in_n_slices == 1)
 2194     {
 2195     if( (arma_config::debug) && ((out_n_rows != in_n_rows) || (out_n_cols != in_n_cols)) )
 2196       {
 2197       std::ostringstream tmp;
 2198       
 2199       tmp
 2200         << "in-place element-wise division: "
 2201         << out_n_rows << 'x' << out_n_cols << " output matrix is incompatible with "
 2202         <<  in_n_rows << 'x' <<  in_n_cols << 'x' << in_n_slices << " cube interpreted as "
 2203         <<  in_n_rows << 'x' <<  in_n_cols << " matrix";
 2204       
 2205       arma_stop_logic_error(tmp.str());
 2206       }
 2207     
 2208     for(uword col=0; col < in_n_cols; ++col)
 2209       {
 2210       arrayops::inplace_div( out.colptr(col), in.slice_colptr(0, col), in_n_rows );
 2211       }
 2212     }
 2213   else
 2214     {
 2215     if(out_vec_state == 0)
 2216       {
 2217       if( (in_n_rows == out_n_rows) && (in_n_cols == 1) && (in_n_slices == out_n_cols) )
 2218         {
 2219         for(uword i=0; i < in_n_slices; ++i)
 2220           {
 2221           arrayops::inplace_div( out.colptr(i), in.slice_colptr(i, 0), in_n_rows );
 2222           }
 2223         }
 2224       else
 2225       if( (in_n_rows == 1) && (in_n_cols == out_n_rows) && (in_n_slices == out_n_cols) )
 2226         {
 2227         const Cube<eT>& Q = in.m;
 2228         
 2229         const uword in_aux_row1   = in.aux_row1;
 2230         const uword in_aux_col1   = in.aux_col1;
 2231         const uword in_aux_slice1 = in.aux_slice1;
 2232         
 2233         for(uword slice=0; slice < in_n_slices; ++slice)
 2234           {
 2235           const uword mod_slice = in_aux_slice1 + slice;
 2236           
 2237           eT* out_colptr = out.colptr(slice);
 2238           
 2239           uword i,j;
 2240           for(i=0, j=1; j < in_n_cols; i+=2, j+=2)
 2241             {
 2242             const eT tmp_i = Q.at(in_aux_row1, in_aux_col1 + i, mod_slice);
 2243             const eT tmp_j = Q.at(in_aux_row1, in_aux_col1 + j, mod_slice);
 2244             
 2245             out_colptr[i] /= tmp_i;
 2246             out_colptr[j] /= tmp_j;
 2247             }
 2248           
 2249           if(i < in_n_cols)
 2250             {
 2251             out_colptr[i] /= Q.at(in_aux_row1, in_aux_col1 + i, mod_slice);
 2252             }
 2253           }
 2254         }
 2255       }
 2256     else
 2257       {
 2258       eT* out_mem = out.memptr();
 2259       
 2260       const Cube<eT>& Q = in.m;
 2261       
 2262       const uword in_aux_row1   = in.aux_row1;
 2263       const uword in_aux_col1   = in.aux_col1;
 2264       const uword in_aux_slice1 = in.aux_slice1;
 2265       
 2266       for(uword i=0; i<in_n_slices; ++i)
 2267         {
 2268         out_mem[i] /= Q.at(in_aux_row1, in_aux_col1, in_aux_slice1 + i);
 2269         }
 2270       }
 2271     }
 2272   }
 2273 
 2274 
 2275 
 2276 template<typename eT>
 2277 inline
 2278 typename subview_cube<eT>::iterator
 2279 subview_cube<eT>::begin()
 2280   {
 2281   return iterator(*this, aux_row1, aux_col1, aux_slice1);
 2282   }
 2283 
 2284 
 2285 
 2286 template<typename eT>
 2287 inline
 2288 typename subview_cube<eT>::const_iterator
 2289 subview_cube<eT>::begin() const
 2290   {
 2291   return const_iterator(*this, aux_row1, aux_col1, aux_slice1);
 2292   }
 2293 
 2294 
 2295 
 2296 template<typename eT>
 2297 inline
 2298 typename subview_cube<eT>::const_iterator
 2299 subview_cube<eT>::cbegin() const
 2300   {
 2301   return const_iterator(*this, aux_row1, aux_col1, aux_slice1);
 2302   }
 2303 
 2304 
 2305 
 2306 template<typename eT>
 2307 inline
 2308 typename subview_cube<eT>::iterator
 2309 subview_cube<eT>::end()
 2310   {
 2311   return iterator(*this, aux_row1, aux_col1, aux_slice1 + n_slices);
 2312   }
 2313 
 2314 
 2315 
 2316 template<typename eT>
 2317 inline
 2318 typename subview_cube<eT>::const_iterator
 2319 subview_cube<eT>::end() const
 2320   {
 2321   return const_iterator(*this, aux_row1, aux_col1, aux_slice1 + n_slices);
 2322   }
 2323 
 2324 
 2325 
 2326 template<typename eT>
 2327 inline
 2328 typename subview_cube<eT>::const_iterator
 2329 subview_cube<eT>::cend() const
 2330   {
 2331   return const_iterator(*this, aux_row1, aux_col1, aux_slice1 + n_slices);
 2332   }
 2333 
 2334 
 2335 
 2336 //
 2337 //
 2338 //
 2339 
 2340 
 2341 
 2342 template<typename eT>
 2343 inline
 2344 subview_cube<eT>::iterator::iterator()
 2345   : M            (NULL)
 2346   , current_ptr  (NULL)
 2347   , current_row  (0   )
 2348   , current_col  (0   )
 2349   , current_slice(0   )
 2350   , aux_row1     (0   )
 2351   , aux_col1     (0   )
 2352   , aux_row2_p1  (0   )
 2353   , aux_col2_p1  (0   )
 2354   {
 2355   arma_extra_debug_sigprint();
 2356   // Technically this iterator is invalid (it does not point to a valid element)
 2357   }
 2358 
 2359 
 2360 
 2361 template<typename eT>
 2362 inline
 2363 subview_cube<eT>::iterator::iterator(const iterator& X)
 2364   : M            (X.M            )
 2365   , current_ptr  (X.current_ptr  )
 2366   , current_row  (X.current_row  )
 2367   , current_col  (X.current_col  )
 2368   , current_slice(X.current_slice)
 2369   , aux_row1     (X.aux_row1     )
 2370   , aux_col1     (X.aux_col1     )
 2371   , aux_row2_p1  (X.aux_row2_p1  )
 2372   , aux_col2_p1  (X.aux_col2_p1  )
 2373   {
 2374   arma_extra_debug_sigprint();
 2375   }
 2376 
 2377 
 2378 
 2379 template<typename eT>
 2380 inline
 2381 subview_cube<eT>::iterator::iterator(subview_cube<eT>& in_sv, const uword in_row, const uword in_col, const uword in_slice)
 2382   : M            (&(const_cast< Cube<eT>& >(in_sv.m)))
 2383   , current_ptr  (&(M->at(in_row,in_col,in_slice))   )
 2384   , current_row  (in_row                             )
 2385   , current_col  (in_col                             )
 2386   , current_slice(in_slice                           )
 2387   , aux_row1     (in_sv.aux_row1                     )
 2388   , aux_col1     (in_sv.aux_col1                     )
 2389   , aux_row2_p1  (in_sv.aux_row1 + in_sv.n_rows      )
 2390   , aux_col2_p1  (in_sv.aux_col1 + in_sv.n_cols      )
 2391   {
 2392   arma_extra_debug_sigprint();
 2393   }
 2394 
 2395 
 2396 
 2397 template<typename eT>
 2398 inline
 2399 arma_warn_unused
 2400 eT&
 2401 subview_cube<eT>::iterator::operator*()
 2402   {
 2403   return (*current_ptr);
 2404   }
 2405 
 2406 
 2407 
 2408 template<typename eT>
 2409 inline
 2410 typename subview_cube<eT>::iterator&
 2411 subview_cube<eT>::iterator::operator++()
 2412   {
 2413   current_row++;
 2414   
 2415   if(current_row == aux_row2_p1)
 2416     {
 2417     current_row = aux_row1;
 2418     current_col++;
 2419     
 2420     if(current_col == aux_col2_p1)
 2421       {
 2422       current_col = aux_col1;
 2423       current_slice++;
 2424       }
 2425     
 2426     current_ptr = &( (*M).at(current_row,current_col,current_slice) );
 2427     }
 2428   else
 2429     {
 2430     current_ptr++;
 2431     }
 2432   
 2433   return *this;
 2434   }
 2435 
 2436 
 2437 
 2438 template<typename eT>
 2439 inline
 2440 arma_warn_unused
 2441 typename subview_cube<eT>::iterator
 2442 subview_cube<eT>::iterator::operator++(int)
 2443   {
 2444   typename subview_cube<eT>::iterator temp(*this);
 2445   
 2446   ++(*this);
 2447   
 2448   return temp;
 2449   }
 2450 
 2451 
 2452 
 2453 template<typename eT>
 2454 inline
 2455 arma_warn_unused
 2456 bool
 2457 subview_cube<eT>::iterator::operator==(const iterator& rhs) const
 2458   {
 2459   return (current_ptr == rhs.current_ptr);
 2460   }
 2461 
 2462 
 2463 
 2464 template<typename eT>
 2465 inline
 2466 arma_warn_unused
 2467 bool
 2468 subview_cube<eT>::iterator::operator!=(const iterator& rhs) const
 2469   {
 2470   return (current_ptr != rhs.current_ptr);
 2471   }
 2472 
 2473 
 2474 
 2475 template<typename eT>
 2476 inline
 2477 arma_warn_unused
 2478 bool
 2479 subview_cube<eT>::iterator::operator==(const const_iterator& rhs) const
 2480   {
 2481   return (current_ptr == rhs.current_ptr);
 2482   }
 2483 
 2484 
 2485 
 2486 template<typename eT>
 2487 inline
 2488 arma_warn_unused
 2489 bool
 2490 subview_cube<eT>::iterator::operator!=(const const_iterator& rhs) const
 2491   {
 2492   return (current_ptr != rhs.current_ptr);
 2493   }
 2494 
 2495 
 2496 
 2497 //
 2498 //
 2499 //
 2500 
 2501 
 2502 
 2503 template<typename eT>
 2504 inline
 2505 subview_cube<eT>::const_iterator::const_iterator()
 2506   : M            (NULL)
 2507   , current_ptr  (NULL)
 2508   , current_row  (0   )
 2509   , current_col  (0   )
 2510   , current_slice(0   )
 2511   , aux_row1     (0   )
 2512   , aux_col1     (0   )
 2513   , aux_row2_p1  (0   )
 2514   , aux_col2_p1  (0   )
 2515   {
 2516   arma_extra_debug_sigprint();
 2517   // Technically this iterator is invalid (it does not point to a valid element)
 2518   }
 2519 
 2520 
 2521 
 2522 template<typename eT>
 2523 inline
 2524 subview_cube<eT>::const_iterator::const_iterator(const iterator& X)
 2525   : M            (X.M            )
 2526   , current_ptr  (X.current_ptr  )
 2527   , current_row  (X.current_row  )
 2528   , current_col  (X.current_col  )
 2529   , current_slice(X.current_slice)
 2530   , aux_row1     (X.aux_row1     )
 2531   , aux_col1     (X.aux_col1     )
 2532   , aux_row2_p1  (X.aux_row2_p1  )
 2533   , aux_col2_p1  (X.aux_col2_p1  )
 2534   {
 2535   arma_extra_debug_sigprint();
 2536   }
 2537 
 2538 
 2539 
 2540 template<typename eT>
 2541 inline
 2542 subview_cube<eT>::const_iterator::const_iterator(const const_iterator& X)
 2543   : M            (X.M            )
 2544   , current_ptr  (X.current_ptr  )
 2545   , current_row  (X.current_row  )
 2546   , current_col  (X.current_col  )
 2547   , current_slice(X.current_slice)
 2548   , aux_row1     (X.aux_row1     )
 2549   , aux_col1     (X.aux_col1     )
 2550   , aux_row2_p1  (X.aux_row2_p1  )
 2551   , aux_col2_p1  (X.aux_col2_p1  )
 2552   {
 2553   arma_extra_debug_sigprint();
 2554   }
 2555 
 2556 
 2557 
 2558 template<typename eT>
 2559 inline
 2560 subview_cube<eT>::const_iterator::const_iterator(const subview_cube<eT>& in_sv, const uword in_row, const uword in_col, const uword in_slice)
 2561   : M            (&(in_sv.m)                      )
 2562   , current_ptr  (&(M->at(in_row,in_col,in_slice)))
 2563   , current_row  (in_row                          )
 2564   , current_col  (in_col                          )
 2565   , current_slice(in_slice                        )
 2566   , aux_row1     (in_sv.aux_row1                  )
 2567   , aux_col1     (in_sv.aux_col1                  )
 2568   , aux_row2_p1  (in_sv.aux_row1 + in_sv.n_rows   )
 2569   , aux_col2_p1  (in_sv.aux_col1 + in_sv.n_cols   )
 2570   {
 2571   arma_extra_debug_sigprint();
 2572   }
 2573 
 2574 
 2575 
 2576 template<typename eT>
 2577 inline
 2578 arma_warn_unused
 2579 const eT&
 2580 subview_cube<eT>::const_iterator::operator*()
 2581   {
 2582   return (*current_ptr);
 2583   }
 2584 
 2585 
 2586 
 2587 template<typename eT>
 2588 inline
 2589 typename subview_cube<eT>::const_iterator&
 2590 subview_cube<eT>::const_iterator::operator++()
 2591   {
 2592   current_row++;
 2593   
 2594   if(current_row == aux_row2_p1)
 2595     {
 2596     current_row = aux_row1;
 2597     current_col++;
 2598     
 2599     if(current_col == aux_col2_p1)
 2600       {
 2601       current_col = aux_col1;
 2602       current_slice++;
 2603       }
 2604     
 2605     current_ptr = &( (*M).at(current_row,current_col,current_slice) );
 2606     }
 2607   else
 2608     {
 2609     current_ptr++;
 2610     }
 2611   
 2612   return *this;
 2613   }
 2614 
 2615 
 2616 
 2617 template<typename eT>
 2618 inline
 2619 arma_warn_unused
 2620 typename subview_cube<eT>::const_iterator
 2621 subview_cube<eT>::const_iterator::operator++(int)
 2622   {
 2623   typename subview_cube<eT>::const_iterator temp(*this);
 2624   
 2625   ++(*this);
 2626   
 2627   return temp;
 2628   }
 2629 
 2630 
 2631 
 2632 template<typename eT>
 2633 inline
 2634 arma_warn_unused
 2635 bool
 2636 subview_cube<eT>::const_iterator::operator==(const iterator& rhs) const
 2637   {
 2638   return (current_ptr == rhs.current_ptr);
 2639   }
 2640 
 2641 
 2642 
 2643 template<typename eT>
 2644 inline
 2645 arma_warn_unused
 2646 bool
 2647 subview_cube<eT>::const_iterator::operator!=(const iterator& rhs) const
 2648   {
 2649   return (current_ptr != rhs.current_ptr);
 2650   }
 2651 
 2652 
 2653 
 2654 template<typename eT>
 2655 inline
 2656 arma_warn_unused
 2657 bool
 2658 subview_cube<eT>::const_iterator::operator==(const const_iterator& rhs) const
 2659   {
 2660   return (current_ptr == rhs.current_ptr);
 2661   }
 2662 
 2663 
 2664 
 2665 template<typename eT>
 2666 inline
 2667 arma_warn_unused
 2668 bool
 2669 subview_cube<eT>::const_iterator::operator!=(const const_iterator& rhs) const
 2670   {
 2671   return (current_ptr != rhs.current_ptr);
 2672   }
 2673 
 2674 
 2675 
 2676 //! @}