Exemple #1
0
inline
bool
op_all::all_vec_helper(const Base<typename T1::elem_type, T1>& X)
  {
  arma_extra_debug_sigprint();
  
  typedef typename T1::elem_type eT;
  
  const Proxy<T1> P(X.get_ref());
  
  const uword n_elem = P.get_n_elem();
  
  uword count = 0;
  
  if(Proxy<T1>::prefer_at_accessor == false)
    {
    typename Proxy<T1>::ea_type Pea = P.get_ea();
    
    for(uword i=0; i<n_elem; ++i)
      {
      if(Pea[i] != eT(0))  { ++count; }
      }
    }
  else
    {
    const uword n_rows = P.get_n_rows();
    const uword n_cols = P.get_n_cols();
    
    for(uword col=0; col < n_cols; ++col)
    for(uword row=0; row < n_rows; ++row)
      {
      if(P.at(row,col) != eT(0))  { ++count; }
      }
    }
  
  // NOTE: for empty vectors it makes more sense to return false, but we need to return true for compatability with Octave
  return (n_elem == count);
  }
inline
void
glue_min::apply(Mat<eT>& out, const Proxy<T1>& PA, const Proxy<T2>& PB)
  {
  arma_extra_debug_sigprint();
  
  const uword n_rows = PA.get_n_rows();
  const uword n_cols = PA.get_n_cols();
  
  arma_debug_assert_same_size(n_rows, n_cols, PB.get_n_rows(), PB.get_n_cols(), "element-wise minimum");
  
  out.set_size(n_rows, n_cols);
  
  eT* out_mem = out.memptr();
  
  if( (Proxy<T1>::use_at == false) && (Proxy<T2>::use_at == false) )
    {
    typename Proxy<T1>::ea_type A = PA.get_ea();
    typename Proxy<T2>::ea_type B = PB.get_ea();
    
    const uword N = PA.get_n_elem();
    
    for(uword i=0; i<N; ++i)
      {
      out_mem[i] = (std::min)(A[i], B[i]);
      }
    }
  else
    {
    for(uword col=0; col < n_cols; ++col)
    for(uword row=0; row < n_rows; ++row)
      {
      *out_mem = (std::min)( PA.at(row,col), PB.at(row,col) );
      
      ++out_mem;
      }
    }
  }
Exemple #3
0
arma_hot
inline
typename arma_cx_only<typename T1::elem_type>::result
op_dot::apply_proxy(const Proxy<T1>& PA, const Proxy<T2>& PB)
  {
  arma_extra_debug_sigprint();
  
  typedef typename T1::elem_type            eT;
  typedef typename get_pod_type<eT>::result  T;
  
  typedef typename Proxy<T1>::ea_type ea_type1;
  typedef typename Proxy<T2>::ea_type ea_type2;
  
  const uword N = PA.get_n_elem();
  
  ea_type1 A = PA.get_ea();
  ea_type2 B = PB.get_ea();
  
  T val_real = T(0);
  T val_imag = T(0);
  
  for(uword i=0; i<N; ++i)
    {
    const std::complex<T> xx = A[i];
    const std::complex<T> yy = B[i];
    
    const T a = xx.real();
    const T b = xx.imag();
    
    const T c = yy.real();
    const T d = yy.imag();
    
    val_real += (a*c) - (b*d);
    val_imag += (a*d) + (b*c);
    }
  
  return std::complex<T>(val_real, val_imag);
  }
inline
typename arma_cx_only<typename T1::elem_type>::result
op_min::min(const Base<typename T1::elem_type,T1>& X)
  {
  arma_extra_debug_sigprint();
  
  typedef typename T1::elem_type            eT;
  typedef typename get_pod_type<eT>::result T;
  
  const Proxy<T1> P(X.get_ref());
  
  const uword n_elem = P.get_n_elem();
  
  arma_debug_check( (n_elem == 0), "min(): given object has no elements" );
  
  T min_val = priv::most_pos<T>();
  
  if(Proxy<T1>::prefer_at_accessor == false)
    {
    typedef typename Proxy<T1>::ea_type ea_type;
    
    ea_type A = P.get_ea();
    
    uword index = 0;
    
    for(uword i=0; i<n_elem; ++i)
      {
      const T tmp = std::abs(A[i]);
      
      if(tmp < min_val)
        {
        min_val = tmp;
        index   = i;
        }
      }
    
    return( A[index] );
    }
  else
    {
    const uword n_rows = P.get_n_rows();
    const uword n_cols = P.get_n_cols();
    
    uword best_row = 0;
    uword best_col = 0;
    
    if(n_rows == 1)
      {
      for(uword col=0; col < n_cols; ++col)
        {
        const T tmp = std::abs(P.at(0,col));
        
        if(tmp < min_val)
          {
          min_val  = tmp;
          best_col = col;
          }
        }
      }
    else
      {
      for(uword col=0; col < n_cols; ++col)
      for(uword row=0; row < n_rows; ++row)
        {
        const T tmp = std::abs(P.at(row,col));
        
        if(tmp < min_val)
          {
          min_val = tmp;
          
          best_row = row;
          best_col = col;
          }
        }
      }
    
    return P.at(best_row, best_col);
    }
  }
inline
uword
op_find::helper
  (
  Mat<uword>& indices,
  const mtOp<uword, T1, op_type>& X,
  const typename arma_op_rel_only<op_type>::result           junk1,
  const typename arma_not_cx<typename T1::elem_type>::result junk2
  )
  {
  arma_extra_debug_sigprint();
  arma_ignore(junk1);
  arma_ignore(junk2);
  
  typedef typename T1::elem_type eT;
  
  const eT val = X.aux;
  
  const Proxy<T1> A(X.m);
  
  const uword n_elem = A.get_n_elem();
  
  indices.set_size(n_elem, 1);
  
  uword* indices_mem = indices.memptr();
  uword  n_nz        = 0;
  
  if(Proxy<T1>::prefer_at_accessor == false)
    {
    typename Proxy<T1>::ea_type PA = A.get_ea();
    
    uword i,j;
    for(i=0, j=1; j < n_elem; i+=2, j+=2)
      {
      const eT tpi = PA[i];
      const eT tpj = PA[j];
      
      bool not_zero_i;
      bool not_zero_j;
      
           if(is_same_type<op_type, op_rel_lt_pre   >::value == true)  { not_zero_i = (val <  tpi); }
      else if(is_same_type<op_type, op_rel_lt_post  >::value == true)  { not_zero_i = (tpi <  val); }
      else if(is_same_type<op_type, op_rel_gt_pre   >::value == true)  { not_zero_i = (val >  tpi); }
      else if(is_same_type<op_type, op_rel_gt_post  >::value == true)  { not_zero_i = (tpi >  val); }
      else if(is_same_type<op_type, op_rel_lteq_pre >::value == true)  { not_zero_i = (val <= tpi); }
      else if(is_same_type<op_type, op_rel_lteq_post>::value == true)  { not_zero_i = (tpi <= val); }
      else if(is_same_type<op_type, op_rel_gteq_pre >::value == true)  { not_zero_i = (val >= tpi); }
      else if(is_same_type<op_type, op_rel_gteq_post>::value == true)  { not_zero_i = (tpi >= val); }
      else if(is_same_type<op_type, op_rel_eq       >::value == true)  { not_zero_i = (tpi == val); }
      else if(is_same_type<op_type, op_rel_noteq    >::value == true)  { not_zero_i = (tpi != val); }
      else not_zero_i = false;
      
           if(is_same_type<op_type, op_rel_lt_pre   >::value == true)  { not_zero_j = (val <  tpj); }
      else if(is_same_type<op_type, op_rel_lt_post  >::value == true)  { not_zero_j = (tpj <  val); }
      else if(is_same_type<op_type, op_rel_gt_pre   >::value == true)  { not_zero_j = (val >  tpj); }
      else if(is_same_type<op_type, op_rel_gt_post  >::value == true)  { not_zero_j = (tpj >  val); }
      else if(is_same_type<op_type, op_rel_lteq_pre >::value == true)  { not_zero_j = (val <= tpj); }
      else if(is_same_type<op_type, op_rel_lteq_post>::value == true)  { not_zero_j = (tpj <= val); }
      else if(is_same_type<op_type, op_rel_gteq_pre >::value == true)  { not_zero_j = (val >= tpj); }
      else if(is_same_type<op_type, op_rel_gteq_post>::value == true)  { not_zero_j = (tpj >= val); }
      else if(is_same_type<op_type, op_rel_eq       >::value == true)  { not_zero_j = (tpj == val); }
      else if(is_same_type<op_type, op_rel_noteq    >::value == true)  { not_zero_j = (tpj != val); }
      else not_zero_j = false;
      
      if(not_zero_i == true)  { indices_mem[n_nz] = i;  ++n_nz; }
      if(not_zero_j == true)  { indices_mem[n_nz] = j;  ++n_nz; }
      }
    
    if(i < n_elem)
      {
      bool not_zero;
      
      const eT tmp = PA[i];
      
           if(is_same_type<op_type, op_rel_lt_pre   >::value == true)  { not_zero = (val <  tmp); }
      else if(is_same_type<op_type, op_rel_lt_post  >::value == true)  { not_zero = (tmp <  val); }
      else if(is_same_type<op_type, op_rel_gt_pre   >::value == true)  { not_zero = (val >  tmp); }
      else if(is_same_type<op_type, op_rel_gt_post  >::value == true)  { not_zero = (tmp >  val); }
      else if(is_same_type<op_type, op_rel_lteq_pre >::value == true)  { not_zero = (val <= tmp); }
      else if(is_same_type<op_type, op_rel_lteq_post>::value == true)  { not_zero = (tmp <= val); }
      else if(is_same_type<op_type, op_rel_gteq_pre >::value == true)  { not_zero = (val >= tmp); }
      else if(is_same_type<op_type, op_rel_gteq_post>::value == true)  { not_zero = (tmp >= val); }
      else if(is_same_type<op_type, op_rel_eq       >::value == true)  { not_zero = (tmp == val); }
      else if(is_same_type<op_type, op_rel_noteq    >::value == true)  { not_zero = (tmp != val); }
      else not_zero = false;
      
      if(not_zero == true)  { indices_mem[n_nz] = i;  ++n_nz; }
      }
    }
  else
    {
    const uword n_rows = A.get_n_rows();
    const uword n_cols = A.get_n_cols();
    
    uword i = 0;
    
    for(uword col=0; col < n_cols; ++col)
    for(uword row=0; row < n_rows; ++row)
      {
      const eT tmp = A.at(row,col);
      
      bool not_zero;
      
           if(is_same_type<op_type, op_rel_lt_pre   >::value == true)  { not_zero = (val <  tmp); }
      else if(is_same_type<op_type, op_rel_lt_post  >::value == true)  { not_zero = (tmp <  val); }
      else if(is_same_type<op_type, op_rel_gt_pre   >::value == true)  { not_zero = (val >  tmp); }
      else if(is_same_type<op_type, op_rel_gt_post  >::value == true)  { not_zero = (tmp >  val); }
      else if(is_same_type<op_type, op_rel_lteq_pre >::value == true)  { not_zero = (val <= tmp); }
      else if(is_same_type<op_type, op_rel_lteq_post>::value == true)  { not_zero = (tmp <= val); }
      else if(is_same_type<op_type, op_rel_gteq_pre >::value == true)  { not_zero = (val >= tmp); }
      else if(is_same_type<op_type, op_rel_gteq_post>::value == true)  { not_zero = (tmp >= val); }
      else if(is_same_type<op_type, op_rel_eq       >::value == true)  { not_zero = (tmp == val); }
      else if(is_same_type<op_type, op_rel_noteq    >::value == true)  { not_zero = (tmp != val); }
      else not_zero = false;
      
      if(not_zero == true)  { indices_mem[n_nz] = i;  ++n_nz; }
      
      ++i;
      }
    }
  
  return n_nz;
  }
inline
void
op_vectorise_col::apply_proxy(Mat<typename T1::elem_type>& out, const Proxy<T1>& P)
  {
  arma_extra_debug_sigprint();
  
  typedef typename T1::elem_type eT;
  
  if(P.is_alias(out) == false)
    {
    const uword N = P.get_n_elem();
    
    out.set_size(N, 1);
      
    if(is_Mat<typename Proxy<T1>::stored_type>::value == true)
      {
      const unwrap<typename Proxy<T1>::stored_type> tmp(P.Q);
      
      arrayops::copy(out.memptr(), tmp.M.memptr(), N);
      }
    else
      {
      eT* outmem = out.memptr();
      
      if(Proxy<T1>::use_at == false)
        {
        // TODO: add handling of aligned access ?
        
        typename Proxy<T1>::ea_type A = P.get_ea();
        
        uword i,j;
        
        for(i=0, j=1; j < N; i+=2, j+=2)
          {
          const eT tmp_i = A[i];
          const eT tmp_j = A[j];
          
          outmem[i] = tmp_i;
          outmem[j] = tmp_j;
          }
        
        if(i < N)
          {
          outmem[i] = A[i];
          }
        }
      else
        {
        const uword n_rows = P.get_n_rows();
        const uword n_cols = P.get_n_cols();
        
        if(n_rows == 1)
          {
          for(uword i=0; i < n_cols; ++i)
            {
            outmem[i] = P.at(0,i);
            }
          }
        else
          {
          for(uword col=0; col < n_cols; ++col)
          for(uword row=0; row < n_rows; ++row)
            {
            *outmem = P.at(row,col);
            outmem++;
            }
          }
        }
      }
    }
  else  // we have aliasing
    {
    arma_extra_debug_print("op_vectorise_col::apply(): aliasing detected");
    
    if( (is_Mat<typename Proxy<T1>::stored_type>::value == true) && (Proxy<T1>::fake_mat == false) )
      {
      out.set_size(out.n_elem, 1);  // set_size() doesn't destroy data as long as the number of elements in the matrix remains the same
      }
    else
      {
      Mat<eT> tmp;
      
      op_vectorise_col::apply_proxy(tmp, P);
      
      out.steal_mem(tmp);
      }
    }
  }
arma_hot
inline
typename T1::pod_type
op_norm::vec_norm_2(const Proxy<T1>& P, const typename arma_cx_only<typename T1::elem_type>::result* junk)
  {
  arma_extra_debug_sigprint();
  arma_ignore(junk);
  
  typedef typename T1::elem_type eT;
  typedef typename T1::pod_type   T;
  
  T acc = T(0);
  
  if(Proxy<T1>::use_at == false)
    {
    typename Proxy<T1>::ea_type A = P.get_ea();
    
    const uword N = P.get_n_elem();
    
    for(uword i=0; i<N; ++i)
      {
      const std::complex<T>& X = A[i];
      
      const T a = X.real();
      const T b = X.imag();
      
      acc += (a*a) + (b*b);
      }
    }
  else
    {
    const uword n_rows = P.get_n_rows();
    const uword n_cols = P.get_n_cols();
    
    if(n_rows == 1)
      {
      for(uword col=0; col<n_cols; ++col)
        {
        const std::complex<T>& X = P.at(0,col);
        
        const T a = X.real();
        const T b = X.imag();
        
        acc += (a*a) + (b*b);
        }
      }
    else
      {
      for(uword col=0; col<n_cols; ++col)
      for(uword row=0; row<n_rows; ++row)
        {
        const std::complex<T>& X = P.at(row,col);
        
        const T a = X.real();
        const T b = X.imag();
        
        acc += (a*a) + (b*b);
        }
      }
    }
  
  const T sqrt_acc = std::sqrt(acc);
  
  if( (sqrt_acc != T(0)) && arma_isfinite(sqrt_acc) )
    {
    return sqrt_acc;
    }
  else
    {
    arma_extra_debug_print("op_norm::vec_norm_2(): detected possible underflow or overflow");
    
    const quasi_unwrap<typename Proxy<T1>::stored_type> R(P.Q);
    
    const uword N     = R.M.n_elem;
    const eT*   R_mem = R.M.memptr();
    
    T max_val = priv::most_neg<T>();
    
    for(uword i=0; i<N; ++i)
      {
      const T val_i = std::abs(R_mem[i]);
      
      if(val_i > max_val)  { max_val = val_i; }
      }
    
    if(max_val == T(0))  { return T(0); }
    
    T alt_acc = T(0);
    
    for(uword i=0; i<N; ++i)
      {
      const T val_i = std::abs(R_mem[i]) / max_val;
      
      alt_acc += val_i * val_i;
      }
    
    return ( std::sqrt(alt_acc) * max_val ); 
    }
  }
arma_hot
inline
typename T1::pod_type
op_norm::vec_norm_1(const Proxy<T1>& P, const typename arma_not_cx<typename T1::elem_type>::result* junk)
  {
  arma_extra_debug_sigprint();
  arma_ignore(junk);
  
  const bool have_direct_mem = (is_Mat<typename Proxy<T1>::stored_type>::value) || (is_subview_col<typename Proxy<T1>::stored_type>::value);
  
  if(have_direct_mem)
    {
    const quasi_unwrap<typename Proxy<T1>::stored_type> tmp(P.Q);
    
    return op_norm::vec_norm_1_direct_std(tmp.M);
    }
  
  typedef typename T1::pod_type T;
  
  T acc = T(0);
  
  if(Proxy<T1>::use_at == false)
    {
    typename Proxy<T1>::ea_type A = P.get_ea();
    
    const uword N = P.get_n_elem();
    
    T acc1 = T(0);
    T acc2 = T(0);
    
    uword i,j;
    for(i=0, j=1; j<N; i+=2, j+=2)
      {
      acc1 += std::abs(A[i]);
      acc2 += std::abs(A[j]);
      }
    
    if(i < N)
      {
      acc1 += std::abs(A[i]);
      }
    
    acc = acc1 + acc2;
    }
  else
    {
    const uword n_rows = P.get_n_rows();
    const uword n_cols = P.get_n_cols();
    
    if(n_rows == 1)
      {
      for(uword col=0; col<n_cols; ++col)
        {
        acc += std::abs(P.at(0,col));
        }
      }
    else
      {
      T acc1 = T(0);
      T acc2 = T(0);
      
      for(uword col=0; col<n_cols; ++col)
        {
        uword i,j;
        
        for(i=0, j=1; j<n_rows; i+=2, j+=2)
          {
          acc1 += std::abs(P.at(i,col));
          acc2 += std::abs(P.at(j,col));
          }
        
        if(i < n_rows)
          {
          acc1 += std::abs(P.at(i,col));
          }
        }
      
      acc = acc1 + acc2;
      }
    }
  
  return acc;
  }
inline
void
op_fft_real::apply( Mat< std::complex<typename T1::pod_type> >& out, const mtOp<std::complex<typename T1::pod_type>,T1,op_fft_real>& in )
  {
  arma_extra_debug_sigprint();
  
  typedef typename T1::pod_type         in_eT;
  typedef typename std::complex<in_eT> out_eT;
  
  const Proxy<T1> P(in.m);
  
  const uword n_rows = P.get_n_rows();
  const uword n_cols = P.get_n_cols();
  const uword n_elem = P.get_n_elem();
  
  const bool is_vec = ( (n_rows == 1) || (n_cols == 1) );
  
  const uword N_orig = (is_vec)              ? n_elem         : n_rows;
  const uword N_user = (in.aux_uword_b == 0) ? in.aux_uword_a : N_orig;
  
  fft_engine<out_eT,false> worker(N_user);
  
  // no need to worry about aliasing, as we're going from a real object to complex complex, which by definition cannot alias
  
  if(is_vec)
    {
    (n_cols == 1) ? out.set_size(N_user, 1) : out.set_size(1, N_user);
    
    if( (out.n_elem == 0) || (N_orig == 0) )
      {
      out.zeros();
      return;
      }
    
    if( (N_user == 1) && (N_orig >= 1) )
      {
      out[0] = out_eT( P[0] );
      return;
      }
    
    podarray<out_eT> data(N_user);
    
    out_eT* data_mem = data.memptr();
    
    if(N_user > N_orig)  { arrayops::fill_zeros( &data_mem[N_orig], (N_user - N_orig) ); }
    
    const uword N = (std::min)(N_user, N_orig);
    
    if(Proxy<T1>::use_at == false)
      {
      typename Proxy<T1>::ea_type X = P.get_ea();
      
      for(uword i=0; i < N; ++i)  { data_mem[i] = out_eT( X[i], in_eT(0) ); }
      }
    else
      {
      if(n_cols == 1)
        {
        for(uword i=0; i < N; ++i)  { data_mem[i] = out_eT( P.at(i,0), in_eT(0) ); }
        }
      else
        {
        for(uword i=0; i < N; ++i)  { data_mem[i] = out_eT( P.at(0,i), in_eT(0) ); }
        }
      }
    
    worker.run( out.memptr(), data_mem );
    }
  else
    {
    // process each column seperately
    
    out.set_size(N_user, n_cols);
    
    if( (out.n_elem == 0) || (N_orig == 0) )
      {
      out.zeros();
      return;
      }
    
    if( (N_user == 1) && (N_orig >= 1) )
      {
      for(uword col=0; col < n_cols; ++col)  { out.at(0,col) = out_eT( P.at(0,col) ); }
      
      return;
      }
    
    podarray<out_eT> data(N_user);
    
    out_eT* data_mem = data.memptr();
    
    if(N_user > N_orig)  { arrayops::fill_zeros( &data_mem[N_orig], (N_user - N_orig) ); }
    
    const uword N = (std::min)(N_user, N_orig);
    
    for(uword col=0; col < n_cols; ++col)
      {
      for(uword i=0; i < N; ++i)  { data_mem[i] = P.at(i, col); }
      
      worker.run( out.colptr(col), data_mem );
      }
    }
  }
Exemple #10
0
inline
bool
op_any::any_vec_helper
  (
  const mtOp<uword, T1, op_type>& X,
  const typename arma_op_rel_only<op_type>::result           junk1,
  const typename arma_not_cx<typename T1::elem_type>::result junk2
  )
  {
  arma_extra_debug_sigprint();
  arma_ignore(junk1);
  arma_ignore(junk2);
  
  typedef typename T1::elem_type eT;
  
  const eT val = X.aux;
  
  const Proxy<T1> P(X.m);
  
  
  if(Proxy<T1>::prefer_at_accessor == false)
    {
    typename Proxy<T1>::ea_type Pea = P.get_ea();
    
    const uword n_elem = P.get_n_elem();
  
    for(uword i=0; i < n_elem; ++i)
      {
      const eT tmp = Pea[i];
      
           if(is_same_type<op_type, op_rel_lt_pre   >::yes)  { if(val <  tmp) { return true; } }
      else if(is_same_type<op_type, op_rel_lt_post  >::yes)  { if(tmp <  val) { return true; } }
      else if(is_same_type<op_type, op_rel_gt_pre   >::yes)  { if(val >  tmp) { return true; } }
      else if(is_same_type<op_type, op_rel_gt_post  >::yes)  { if(tmp >  val) { return true; } }
      else if(is_same_type<op_type, op_rel_lteq_pre >::yes)  { if(val <= tmp) { return true; } }
      else if(is_same_type<op_type, op_rel_lteq_post>::yes)  { if(tmp <= val) { return true; } }
      else if(is_same_type<op_type, op_rel_gteq_pre >::yes)  { if(val >= tmp) { return true; } }
      else if(is_same_type<op_type, op_rel_gteq_post>::yes)  { if(tmp >= val) { return true; } }
      else if(is_same_type<op_type, op_rel_eq       >::yes)  { if(tmp == val) { return true; } }
      else if(is_same_type<op_type, op_rel_noteq    >::yes)  { if(tmp != val) { return true; } }
      }
    }
  else
    {
    const uword n_rows = P.get_n_rows();
    const uword n_cols = P.get_n_cols();
    
    for(uword col=0; col < n_cols; ++col)
    for(uword row=0; row < n_rows; ++row)
      {
      const eT tmp = P.at(row,col);
      
           if(is_same_type<op_type, op_rel_lt_pre   >::yes)  { if(val <  tmp) { return true; } }
      else if(is_same_type<op_type, op_rel_lt_post  >::yes)  { if(tmp <  val) { return true; } }
      else if(is_same_type<op_type, op_rel_gt_pre   >::yes)  { if(val >  tmp) { return true; } }
      else if(is_same_type<op_type, op_rel_gt_post  >::yes)  { if(tmp >  val) { return true; } }
      else if(is_same_type<op_type, op_rel_lteq_pre >::yes)  { if(val <= tmp) { return true; } }
      else if(is_same_type<op_type, op_rel_lteq_post>::yes)  { if(tmp <= val) { return true; } }
      else if(is_same_type<op_type, op_rel_gteq_pre >::yes)  { if(val >= tmp) { return true; } }
      else if(is_same_type<op_type, op_rel_gteq_post>::yes)  { if(tmp >= val) { return true; } }
      else if(is_same_type<op_type, op_rel_eq       >::yes)  { if(tmp == val) { return true; } }
      else if(is_same_type<op_type, op_rel_noteq    >::yes)  { if(tmp != val) { return true; } }
      }
    }
  
  return false;
  }
inline
void
subview_elem1<eT,T1>::inplace_op(const Base<eT,T2>& x)
  {
  arma_extra_debug_sigprint();
  
  Mat<eT>& m_local = *m_ptr;
  
        eT* m_mem    = m_local.memptr();
  const u32 m_n_elem = m_local.n_elem;
  
  const unwrap_check_mixed<T1> tmp(a.get_ref(), m_local);
  const umat& aa = tmp.M;
  
  arma_debug_check
    (
    ( aa.is_vec() == false ),
    "Mat::elem(): given object is not a vector"
    );
  
  const u32* aa_mem    = aa.memptr();
  const u32  aa_n_elem = aa.n_elem;
  
  const Proxy<T2> P(x.get_ref());
  
  arma_debug_check( (aa_n_elem != P.get_n_elem()), "Mat::elem(): size mismatch" );
  
  if(P.is_alias(m) == false)
    {
    typename Proxy<T2>::ea_type X = P.get_ea();
    
    u32 i,j;
    for(i=0, j=1; j<aa_n_elem; i+=2, j+=2)
      {
      const u32 ii = aa_mem[i];
      const u32 jj = aa_mem[j];
      
      arma_debug_check( ( (ii >= m_n_elem) || (jj >= m_n_elem) ), "Mat::elem(): index out of bounds" );
      
           if(is_same_type<op_type, op_subview_elem_equ          >::value == true) { m_mem[ii] =  X[i]; m_mem[jj]  = X[j]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_plus >::value == true) { m_mem[ii] += X[i]; m_mem[jj] += X[j]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_minus>::value == true) { m_mem[ii] -= X[i]; m_mem[jj] -= X[j]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_schur>::value == true) { m_mem[ii] *= X[i]; m_mem[jj] *= X[j]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_div  >::value == true) { m_mem[ii] /= X[i]; m_mem[jj] /= X[j]; }
      }
    
    if(i < aa_n_elem)
      {
      const u32 ii = aa_mem[i];
      
      arma_debug_check( (ii >= m_n_elem) , "Mat::elem(): index out of bounds" );
      
           if(is_same_type<op_type, op_subview_elem_equ          >::value == true) { m_mem[ii] =  X[i]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_plus >::value == true) { m_mem[ii] += X[i]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_minus>::value == true) { m_mem[ii] -= X[i]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_schur>::value == true) { m_mem[ii] *= X[i]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_div  >::value == true) { m_mem[ii] /= X[i]; }
      }
    }
  else
    {
    arma_extra_debug_print("subview_elem1::inplace_op(): aliasing detected");
    
    const unwrap_check<typename Proxy<T2>::stored_type> tmp(P.Q, m_local);
    const Mat<eT>& M = tmp.M;
    
    const eT* X = M.memptr();
    
    u32 i,j;
    for(i=0, j=1; j<aa_n_elem; i+=2, j+=2)
      {
      const u32 ii = aa_mem[i];
      const u32 jj = aa_mem[j];
      
      arma_debug_check( ( (ii >= m_n_elem) || (jj >= m_n_elem) ), "Mat::elem(): index out of bounds" );
      
           if(is_same_type<op_type, op_subview_elem_equ          >::value == true) { m_mem[ii] =  X[i]; m_mem[jj]  = X[j]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_plus >::value == true) { m_mem[ii] += X[i]; m_mem[jj] += X[j]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_minus>::value == true) { m_mem[ii] -= X[i]; m_mem[jj] -= X[j]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_schur>::value == true) { m_mem[ii] *= X[i]; m_mem[jj] *= X[j]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_div  >::value == true) { m_mem[ii] /= X[i]; m_mem[jj] /= X[j]; }
      }
    
    if(i < aa_n_elem)
      {
      const u32 ii = aa_mem[i];
      
      arma_debug_check( (ii >= m_n_elem) , "Mat::elem(): index out of bounds" );
      
           if(is_same_type<op_type, op_subview_elem_equ          >::value == true) { m_mem[ii] =  X[i]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_plus >::value == true) { m_mem[ii] += X[i]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_minus>::value == true) { m_mem[ii] -= X[i]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_schur>::value == true) { m_mem[ii] *= X[i]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_div  >::value == true) { m_mem[ii] /= X[i]; }
      }
    }
  }
Exemple #12
0
inline
bool
op_any::any_vec_helper
  (
  const mtGlue<uword, T1, T2, glue_type>& X,
  const typename arma_glue_rel_only<glue_type>::result       junk1,
  const typename arma_not_cx<typename T1::elem_type>::result junk2,
  const typename arma_not_cx<typename T2::elem_type>::result junk3
  )
  {
  arma_extra_debug_sigprint();
  arma_ignore(junk1);
  arma_ignore(junk2);
  arma_ignore(junk3);
  
  typedef typename T1::elem_type eT1;
  typedef typename T2::elem_type eT2;
  
  typedef typename Proxy<T1>::ea_type ea_type1;
  typedef typename Proxy<T2>::ea_type ea_type2;
  
  const Proxy<T1> A(X.A);
  const Proxy<T2> B(X.B);
  
  arma_debug_assert_same_size(A, B, "relational operator");
  
  const bool prefer_at_accessor = Proxy<T1>::prefer_at_accessor || Proxy<T2>::prefer_at_accessor;
  
  if(prefer_at_accessor == false)
    {
    ea_type1 PA = A.get_ea();
    ea_type2 PB = B.get_ea();
    
    const uword n_elem = A.get_n_elem();
    
    for(uword i=0; i<n_elem; ++i)
      {
      const eT1 tmp1 = PA[i];
      const eT2 tmp2 = PB[i];
      
           if(is_same_type<glue_type, glue_rel_lt    >::yes)  { if(tmp1 <  tmp2) { return true; } }
      else if(is_same_type<glue_type, glue_rel_gt    >::yes)  { if(tmp1 >  tmp2) { return true; } }
      else if(is_same_type<glue_type, glue_rel_lteq  >::yes)  { if(tmp1 <= tmp2) { return true; } }
      else if(is_same_type<glue_type, glue_rel_gteq  >::yes)  { if(tmp1 >= tmp2) { return true; } }
      else if(is_same_type<glue_type, glue_rel_eq    >::yes)  { if(tmp1 == tmp2) { return true; } }
      else if(is_same_type<glue_type, glue_rel_noteq >::yes)  { if(tmp1 != tmp2) { return true; } }
      else if(is_same_type<glue_type, glue_rel_and   >::yes)  { if(tmp1 && tmp2) { return true; } }
      else if(is_same_type<glue_type, glue_rel_or    >::yes)  { if(tmp1 || tmp2) { return true; } }
      }
    }
  else
    {
    const uword n_rows = A.get_n_rows();
    const uword n_cols = A.get_n_cols();
    
    for(uword col=0; col < n_cols; ++col)
    for(uword row=0; row < n_rows; ++row)
      {
      const eT1 tmp1 = A.at(row,col);
      const eT2 tmp2 = B.at(row,col);
      
           if(is_same_type<glue_type, glue_rel_lt    >::yes)  { if(tmp1 <  tmp2) { return true; } }
      else if(is_same_type<glue_type, glue_rel_gt    >::yes)  { if(tmp1 >  tmp2) { return true; } }
      else if(is_same_type<glue_type, glue_rel_lteq  >::yes)  { if(tmp1 <= tmp2) { return true; } }
      else if(is_same_type<glue_type, glue_rel_gteq  >::yes)  { if(tmp1 >= tmp2) { return true; } }
      else if(is_same_type<glue_type, glue_rel_eq    >::yes)  { if(tmp1 == tmp2) { return true; } }
      else if(is_same_type<glue_type, glue_rel_noteq >::yes)  { if(tmp1 != tmp2) { return true; } }
      else if(is_same_type<glue_type, glue_rel_and   >::yes)  { if(tmp1 && tmp2) { return true; } }
      else if(is_same_type<glue_type, glue_rel_or    >::yes)  { if(tmp1 || tmp2) { return true; } }
      }
    }
  
  return false;
  }
Exemple #13
0
inline
void
op_unique::apply(Mat<typename T1::elem_type>& out, const Op<T1, op_unique>& X)
  {
  arma_extra_debug_sigprint();
  
  typedef typename T1::elem_type eT;
  
  const Proxy<T1> P(X.m);
  
  const uword in_n_rows = P.get_n_rows();
  const uword in_n_cols = P.get_n_cols();
  const uword in_n_elem = P.get_n_elem();
  
  
  if(in_n_elem <= 1)
    {
    if(in_n_elem == 1)
      {
      const eT tmp = P[0];
      
      out.set_size(in_n_rows, in_n_cols);
      
      out[0] = tmp;
      }
    else
      {
      out.set_size(in_n_rows, in_n_cols);
      }
    
    return;
    }
  
  
  std::vector<eT> lvec(in_n_elem);
  
  
  if(Proxy<T1>::prefer_at_accessor == false)
    {
    typename Proxy<T1>::ea_type Pea = P.get_ea();
    
    uword i,j;
    for(i=0, j=1; j < in_n_elem; i+=2, j+=2)
      {
      const eT tmp_i = Pea[i];
      const eT tmp_j = Pea[j];
      
      lvec[i] = tmp_i;
      lvec[j] = tmp_j;
      }
    
    if(i < in_n_elem)
      {
      lvec[i] = Pea[i];
      }
    }
  else
    {
    uword i = 0;
    
    for(uword col=0; col < in_n_cols; ++col)
    for(uword row=0; row < in_n_rows; ++row, ++i)
      {
      lvec[i] = P.at(row,col);
      }
    }
  
  std::sort( lvec.begin(), lvec.end() );
  
  uword N_unique = 1;
  
  for(uword i=1; i < in_n_elem; ++i)
    {
    const eT a = lvec[i-1];
    const eT b = lvec[i  ];
    
    const eT diff = a - b;
    
    if(diff != eT(0)) { ++N_unique; }
    }
  
  uword out_n_rows;
  uword out_n_cols;
  
  if( (in_n_rows == 1) || (in_n_cols == 1) )
    {
    if(in_n_rows == 1)
      {
      out_n_rows = 1;
      out_n_cols = N_unique;
      }
    else
      {
      out_n_rows = N_unique;
      out_n_cols = 1;
      }
    }
  else
    {
    out_n_rows = N_unique;
    out_n_cols = 1;
    }
  
  // we don't need to worry about aliasing at this stage, as all the data is stored in lvec
  out.set_size(out_n_rows, out_n_cols);
  
  eT* out_mem = out.memptr();
  
  if(in_n_elem > 0) { out_mem[0] = lvec[0]; }
  
  N_unique = 1;
  
  for(uword i=1; i < in_n_elem; ++i)
    {
    const eT a = lvec[i-1];
    const eT b = lvec[i  ];
    
    const eT diff = a - b;
    
    if(diff != eT(0))
      {
      out_mem[N_unique] = b;
      ++N_unique;
      }
    }
  
  }
Exemple #14
0
arma_hot
inline
typename T1::pod_type
arma_vec_norm_1(const Proxy<T1>& P)
{
    arma_extra_debug_sigprint();

    typedef typename T1::pod_type T;

    T acc = T(0);

    if(Proxy<T1>::prefer_at_accessor == false)
    {
        typename Proxy<T1>::ea_type A = P.get_ea();

        const uword N = P.get_n_elem();

        T acc1 = T(0);
        T acc2 = T(0);

        uword i,j;
        for(i=0, j=1; j<N; i+=2, j+=2)
        {
            acc1 += std::abs(A[i]);
            acc2 += std::abs(A[j]);
        }

        if(i < N)
        {
            acc1 += std::abs(A[i]);
        }

        acc = acc1 + acc2;
    }
    else
    {
        const uword n_rows = P.get_n_rows();
        const uword n_cols = P.get_n_cols();

        if(n_rows == 1)
        {
            for(uword col=0; col<n_cols; ++col)
            {
                acc += std::abs(P.at(0,col));
            }
        }
        else
        {
            for(uword col=0; col<n_cols; ++col)
            {
                uword i,j;

                for(i=0, j=1; j<n_rows; i+=2, j+=2)
                {
                    acc += std::abs(P.at(i,col));
                    acc += std::abs(P.at(j,col));
                }

                if(i < n_rows)
                {
                    acc += std::abs(P.at(i,col));
                }
            }
        }
    }

    return acc;
}
inline
bool
op_find_unique::apply_helper(Mat<uword>& out, const Proxy<T1>& P, const bool ascending_indices)
{
    arma_extra_debug_sigprint();

    typedef typename T1::elem_type eT;

    const uword n_elem = P.get_n_elem();

    if(n_elem == 0)  {
        out.set_size(0,1);
        return true;
    }
    if(n_elem == 1)  {
        out.set_size(1,1);
        out[0] = 0;
        return true;
    }

    uvec indices(n_elem);

    std::vector< arma_find_unique_packet<eT> > packet_vec(n_elem);

    if(Proxy<T1>::prefer_at_accessor == false)
    {
        typename Proxy<T1>::ea_type Pea = P.get_ea();

        for(uword i=0; i<n_elem; ++i)
        {
            const eT val = Pea[i];

            if(arma_isnan(val))  {
                return false;
            }

            packet_vec[i].val   = val;
            packet_vec[i].index = i;
        }
    }
    else
    {
        const uword n_rows = P.get_n_rows();
        const uword n_cols = P.get_n_cols();

        uword i = 0;

        for(uword col=0; col < n_cols; ++col)
            for(uword row=0; row < n_rows; ++row)
            {
                const eT val = P.at(row,col);

                if(arma_isnan(val))  {
                    return false;
                }

                packet_vec[i].val   = val;
                packet_vec[i].index = i;

                ++i;
            }
    }

    arma_find_unique_comparator<eT> comparator;

    std::sort( packet_vec.begin(), packet_vec.end(), comparator );

    uword* indices_mem = indices.memptr();

    indices_mem[0] = packet_vec[0].index;

    uword count = 1;

    for(uword i=1; i < n_elem; ++i)
    {
        const eT diff = packet_vec[i-1].val - packet_vec[i].val;

        if(diff != eT(0))
        {
            indices_mem[count] = packet_vec[i].index;
            ++count;
        }
    }

    out.steal_mem_col(indices,count);

    if(ascending_indices)  {
        std::sort(out.begin(), out.end());
    }

    return true;
}
inline
bool
arma_sort_index_helper(Mat<uword>& out, const Proxy<T1>& P, const uword sort_type, typename arma_not_cx<typename T1::elem_type>::result* junk = 0)
  {
  arma_extra_debug_sigprint();
  arma_ignore(junk);
  
  typedef typename T1::elem_type eT;
  
  const uword n_elem = P.get_n_elem();
  
  out.set_size(n_elem, 1);
  
  std::vector< arma_sort_index_packet<eT, uword> > packet_vec(n_elem);
  
  if(Proxy<T1>::prefer_at_accessor == false)
    {
    for(uword i=0; i<n_elem; ++i)
      {
      const eT val = P[i];
      
      if(arma_isnan(val))  { out.reset(); return false; }
      
      packet_vec[i].val   = val;
      packet_vec[i].index = i;
      }
    }
  else
    {
    const uword n_rows = P.get_n_rows();
    const uword n_cols = P.get_n_cols();
    
    uword i = 0;
    
    for(uword col=0; col < n_cols; ++col)
    for(uword row=0; row < n_rows; ++row)
      {
      const eT val = P.at(row,col);
      
      if(arma_isnan(val))  { out.reset(); return false; }
      
      packet_vec[i].val   = val;
      packet_vec[i].index = i;
      
      ++i;
      }
    }
  
  
  if(sort_type == 0)
    {
    // ascend
    
    arma_sort_index_helper_ascend comparator;
    
    if(sort_stable == false)
      {
      std::sort( packet_vec.begin(), packet_vec.end(), comparator );
      }
    else
      {
      std::stable_sort( packet_vec.begin(), packet_vec.end(), comparator );
      }
    }
  else
    {
    // descend
    
    arma_sort_index_helper_descend comparator;
    
    if(sort_stable == false)
      {
      std::sort( packet_vec.begin(), packet_vec.end(), comparator );
      }
    else
      {
      std::stable_sort( packet_vec.begin(), packet_vec.end(), comparator );
      }
    }
  
  uword* out_mem = out.memptr();
  
  for(uword i=0; i<n_elem; ++i)
    {
    out_mem[i] = packet_vec[i].index;
    }
  
  return true;
  }
inline
void
op_fft_cx::apply_noalias(Mat<typename T1::elem_type>& out, const Proxy<T1>& P, const uword a, const uword b)
  {
  arma_extra_debug_sigprint();
  
  typedef typename T1::elem_type eT;
  
  const uword n_rows = P.get_n_rows();
  const uword n_cols = P.get_n_cols();
  const uword n_elem = P.get_n_elem();
  
  const bool is_vec = ( (n_rows == 1) || (n_cols == 1) );
  
  const uword N_orig = (is_vec) ? n_elem : n_rows;
  const uword N_user = (b == 0) ? a      : N_orig;
  
  fft_engine<eT,inverse> worker(N_user);
  
  if(is_vec)
    {
    (n_cols == 1) ? out.set_size(N_user, 1) : out.set_size(1, N_user);
    
    if( (out.n_elem == 0) || (N_orig == 0) )
      {
      out.zeros();
      return;
      }
    
    if( (N_user == 1) && (N_orig >= 1) )
      {
      out[0] = P[0];
      return;
      }
    
    if( (N_user > N_orig) || (is_Mat<typename Proxy<T1>::stored_type>::value == false) )
      {
      podarray<eT> data(N_user);
      
      eT* data_mem = data.memptr();
      
      if(N_user > N_orig)  { arrayops::fill_zeros( &data_mem[N_orig], (N_user - N_orig) ); }
      
      op_fft_cx::copy_vec( data_mem, P, (std::min)(N_user, N_orig) );
      
      worker.run( out.memptr(), data_mem );
      }
    else
      {
      const unwrap< typename Proxy<T1>::stored_type > tmp(P.Q);
      
      worker.run( out.memptr(), tmp.M.memptr() );
      }
    }
  else
    {
    // process each column seperately
    
    out.set_size(N_user, n_cols);
    
    if( (out.n_elem == 0) || (N_orig == 0) )
      {
      out.zeros();
      return;
      }
    
    if( (N_user == 1) && (N_orig >= 1) )
      {
      for(uword col=0; col < n_cols; ++col)  { out.at(0,col) = P.at(0,col); }
      
      return;
      }
    
    if( (N_user > N_orig) || (is_Mat<typename Proxy<T1>::stored_type>::value == false) )
      {
      podarray<eT> data(N_user);
      
      eT* data_mem = data.memptr();
      
      if(N_user > N_orig)  { arrayops::fill_zeros( &data_mem[N_orig], (N_user - N_orig) ); }
      
      const uword N = (std::min)(N_user, N_orig);
      
      for(uword col=0; col < n_cols; ++col)
        {
        for(uword i=0; i < N; ++i)  { data_mem[i] = P.at(i, col); }
        
        worker.run( out.colptr(col), data_mem );
        }
      }
    else
      {
      const unwrap< typename Proxy<T1>::stored_type > tmp(P.Q);
      
      for(uword col=0; col < n_cols; ++col)
        {
        worker.run( out.colptr(col), tmp.M.colptr(col) );
        }
      }
    }
    
  
  // correct the scaling for the inverse transform
  if(inverse == true)
    {
    typedef typename get_pod_type<eT>::result T;
    
    const T k = T(1) / T(N_user);
    
    eT* out_mem = out.memptr();
    
    const uword out_n_elem = out.n_elem;
    
    for(uword i=0; i < out_n_elem; ++i)  { out_mem[i] *= k; }
    }
  }
Exemple #18
0
inline
void
diagview<eT>::operator/=(const Base<eT,T1>& o)
  {
  arma_extra_debug_sigprint();
  
  diagview<eT>& d = *this;
  
  Mat<eT>& d_m = const_cast< Mat<eT>& >(d.m);
  
  const uword d_n_elem     = d.n_elem;
  const uword d_row_offset = d.row_offset;
  const uword d_col_offset = d.col_offset;
    
  const Proxy<T1> P( o.get_ref() );
  
  arma_debug_check
    (
    ( (d_n_elem != P.get_n_elem()) || ((P.get_n_rows() != 1) && (P.get_n_cols() != 1)) ),
    "diagview: given object has incompatible size"
    );
  
  const bool is_alias = P.is_alias(d_m);
  
  arma_extra_debug_warn(is_alias, "aliasing detected");
  
  if( (is_Mat<typename Proxy<T1>::stored_type>::value) || (Proxy<T1>::prefer_at_accessor) || (is_alias) )
    {
    const unwrap_check<typename Proxy<T1>::stored_type> tmp(P.Q, is_alias);
    const Mat<eT>& x = tmp.M;
    
    const eT* x_mem = x.memptr();
    
    uword ii,jj;
    for(ii=0, jj=1; jj < d_n_elem; ii+=2, jj+=2)
      {
      const eT tmp_i = x_mem[ii];
      const eT tmp_j = x_mem[jj];
      
      d_m.at( ii + d_row_offset,  ii + d_col_offset) /= tmp_i;
      d_m.at( jj + d_row_offset,  jj + d_col_offset) /= tmp_j;
      }
    
    if(ii < d_n_elem)
      {
      d_m.at( ii + d_row_offset,  ii + d_col_offset) /= x_mem[ii];
      }
    }
  else
    {
    typename Proxy<T1>::ea_type Pea = P.get_ea();
      
    uword ii,jj;
    for(ii=0, jj=1; jj < d_n_elem; ii+=2, jj+=2)
      {
      const eT tmp_i = Pea[ii];
      const eT tmp_j = Pea[jj];
      
      d_m.at( ii + d_row_offset,  ii + d_col_offset) /= tmp_i;
      d_m.at( jj + d_row_offset,  jj + d_col_offset) /= tmp_j;
      }
    
    if(ii < d_n_elem)
      {
      d_m.at( ii + d_row_offset,  ii + d_col_offset) /= Pea[ii];
      }
    }
  }
Exemple #19
0
inline
typename arma_cx_only<typename T1::elem_type>::result
op_min::min_with_index(const Proxy<T1>& P, uword& index_of_min_val)
  {
  arma_extra_debug_sigprint();
  
  typedef typename T1::elem_type            eT;
  typedef typename get_pod_type<eT>::result T;
  
  const uword n_elem = P.get_n_elem();
  
  if(n_elem == 0)
    {
    arma_debug_check(true, "min(): object has no elements");
    
    return Datum<eT>::nan;
    }
  
  T best_val = priv::most_pos<T>();
  
  if(Proxy<T1>::prefer_at_accessor == false)
    {
    typedef typename Proxy<T1>::ea_type ea_type;
    
    ea_type A = P.get_ea();
    
    uword best_index = 0;
    
    for(uword i=0; i<n_elem; ++i)
      {
      const T tmp = std::abs(A[i]);
      
      if(tmp < best_val)  { best_val = tmp;  best_index = i; }
      }
    
    index_of_min_val = best_index;
    
    return( A[best_index] );
    }
  else
    {
    const uword n_rows = P.get_n_rows();
    const uword n_cols = P.get_n_cols();
    
    uword best_row   = 0;
    uword best_col   = 0;
    uword best_index = 0;
    
    if(n_rows == 1)
      {
      for(uword col=0; col < n_cols; ++col)
        {
        const T tmp = std::abs(P.at(0,col));
        
        if(tmp < best_val)  { best_val = tmp;  best_col = col; }
        }
      
      best_index = best_col;
      }
    else
    if(n_cols == 1)
      {
      for(uword row=0; row < n_rows; ++row)
        {
        const T tmp = std::abs(P.at(row,0));
        
        if(tmp < best_val)  { best_val = tmp;  best_row = row; }
        }
      
      best_index = best_row;
      }
    else
      {
      uword count = 0;
      
      for(uword col=0; col < n_cols; ++col)
      for(uword row=0; row < n_rows; ++row)
        {
        const T tmp = std::abs(P.at(row,col));
        
        if(tmp < best_val)
          {
          best_val = tmp;
          
          best_row = row;
          best_col = col;
          
          best_index = count;
          }
        
        ++count;
        }
      }
    
    index_of_min_val = best_index;
    
    return P.at(best_row, best_col);
    }
  }
Exemple #20
0
inline
arma_warn_unused
typename T1::pod_type
norm
  (
  const Base<typename T1::elem_type,T1>& X,
  const uword k,
  const typename arma_float_or_cx_only<typename T1::elem_type>::result* junk = 0
  )
  {
  arma_extra_debug_sigprint();
  arma_ignore(junk);
  
  typedef typename T1::elem_type eT;
  typedef typename T1::pod_type   T;
  
  const Proxy<T1> A(X.get_ref());
  
  if(A.get_n_elem() == 0)
    {
    return T(0);
    }
  
  const bool is_vec = (A.get_n_rows() == 1) || (A.get_n_cols() == 1);
  
  if(is_vec == true)
    {
    switch(k)
      {
      case 1:
        return arma_vec_norm_1(A);
        break;
      
      case 2:
        return arma_vec_norm_2(A);
        break;
      
      default:
        {
        arma_debug_check( (k == 0), "norm(): k must be greater than zero"   );
        return arma_vec_norm_k(A, int(k));
        }
      }
    }
  else
    {
    switch(k)
      {
      case 1:
        return arma_mat_norm_1(A);
        break;
      
      case 2:
        return arma_mat_norm_2(A);
        break;
      
      default:
        arma_stop("norm(): unsupported matrix norm type");
        return T(0);
      }
    }
  }
arma_hot
inline
typename T1::pod_type
op_norm::vec_norm_2(const Proxy<T1>& P, const typename arma_not_cx<typename T1::elem_type>::result* junk)
  {
  arma_extra_debug_sigprint();
  arma_ignore(junk);
  
  const bool have_direct_mem = (is_Mat<typename Proxy<T1>::stored_type>::value) || (is_subview_col<typename Proxy<T1>::stored_type>::value);
  
  if(have_direct_mem)
    {
    const quasi_unwrap<typename Proxy<T1>::stored_type> tmp(P.Q);
    
    return op_norm::vec_norm_2_direct_std(tmp.M);
    }
  
  typedef typename T1::pod_type T;
  
  T acc = T(0);
  
  if(Proxy<T1>::use_at == false)
    {
    typename Proxy<T1>::ea_type A = P.get_ea();
    
    const uword N = P.get_n_elem();
    
    T acc1 = T(0);
    T acc2 = T(0);
    
    uword i,j;
    
    for(i=0, j=1; j<N; i+=2, j+=2)
      {
      const T tmp_i = A[i];
      const T tmp_j = A[j];
      
      acc1 += tmp_i * tmp_i;
      acc2 += tmp_j * tmp_j;
      }
    
    if(i < N)
      {
      const T tmp_i = A[i];
      
      acc1 += tmp_i * tmp_i;
      }
    
    acc = acc1 + acc2;
    }
  else
    {
    const uword n_rows = P.get_n_rows();
    const uword n_cols = P.get_n_cols();
    
    if(n_rows == 1)
      {
      for(uword col=0; col<n_cols; ++col)
        {
        const T tmp = P.at(0,col);
        
        acc += tmp * tmp;
        }
      }
    else
      {
      for(uword col=0; col<n_cols; ++col)
        {
        uword i,j;
        for(i=0, j=1; j<n_rows; i+=2, j+=2)
          {
          const T tmp_i = P.at(i,col);
          const T tmp_j = P.at(j,col);
          
          acc += tmp_i * tmp_i;
          acc += tmp_j * tmp_j;
          }
        
        if(i < n_rows)
          {
          const T tmp_i = P.at(i,col);
          
          acc += tmp_i * tmp_i;
          }
        }
      }
    }
  
  
  const T sqrt_acc = std::sqrt(acc);
  
  if( (sqrt_acc != T(0)) && arma_isfinite(sqrt_acc) )
    {
    return sqrt_acc;
    }
  else
    {
    arma_extra_debug_print("op_norm::vec_norm_2(): detected possible underflow or overflow");
    
    const quasi_unwrap<typename Proxy<T1>::stored_type> tmp(P.Q);
    
    return op_norm::vec_norm_2_direct_robust(tmp.M);
    }
  }
Exemple #22
0
inline
arma_warn_unused
typename T1::pod_type
norm
  (
  const Base<typename T1::elem_type,T1>& X,
  const char* method,
  const typename arma_float_or_cx_only<typename T1::elem_type>::result* junk = 0
  )
  {
  arma_extra_debug_sigprint();
  arma_ignore(junk);
  
  typedef typename T1::elem_type eT;
  typedef typename T1::pod_type   T;
  
  const Proxy<T1> A(X.get_ref());
  
  if(A.get_n_elem() == 0)
    {
    return T(0);
    }
  
  const char sig    = method[0];
  const bool is_vec = (A.get_n_rows() == 1) || (A.get_n_cols() == 1);
  
  if(is_vec == true)
    {
    if( (sig == 'i') || (sig == 'I') || (sig == '+') )   // max norm
      {
      return arma_vec_norm_max(A);
      }
    else
    if(sig == '-')   // min norm
      {
      return arma_vec_norm_min(A);
      }
    else
    if( (sig == 'f') || (sig == 'F') )
      {
      return arma_vec_norm_2(A);
      }
    else
      {
      arma_stop("norm(): unsupported vector norm type");
      return T(0);
      }
    }
  else
    {
    if( (sig == 'i') || (sig == 'I') || (sig == '+') )   // inf norm
      {
      return arma_mat_norm_inf(A);
      }
    else
    if( (sig == 'f') || (sig == 'F') )
      {
      return arma_vec_norm_2(A);
      }
    else
      {
      arma_stop("norm(): unsupported matrix norm type");
      return T(0);
      }
    }
  }
arma_hot
inline
typename T1::pod_type
op_norm::vec_norm_min(const Proxy<T1>& P)
  {
  arma_extra_debug_sigprint();
  
  typedef typename T1::pod_type T;
  
  const uword N = P.get_n_elem();
  
  T min_val = (N != 1) ? priv::most_pos<T>() : std::abs(P[0]);
  
  if(Proxy<T1>::use_at == false)
    {
    typename Proxy<T1>::ea_type A = P.get_ea();
    
    uword i,j;
    for(i=0, j=1; j<N; i+=2, j+=2)
      {
      const T tmp_i = std::abs(A[i]);
      const T tmp_j = std::abs(A[j]);
      
      if(min_val > tmp_i) { min_val = tmp_i; }
      if(min_val > tmp_j) { min_val = tmp_j; }
      }
    
    if(i < N)
      {
      const T tmp_i = std::abs(A[i]);
      
      if(min_val > tmp_i) { min_val = tmp_i; }
      }
    }
  else
    {
    const uword n_rows = P.get_n_rows();
    const uword n_cols = P.get_n_cols();
    
    if(n_rows != 1)
      {
      for(uword col=0; col < n_cols; ++col)
      for(uword row=0; row < n_rows; ++row)
        {
        const T tmp = std::abs(P.at(row,col));
        
        if(min_val > tmp) { min_val = tmp; }
        }
      }
    else
      {
      for(uword col=0; col < n_cols; ++col)
        {
        const T tmp = std::abs(P.at(0,col));
        
        if(min_val > tmp) { min_val = tmp; }
        }
      }
    }
  
  return min_val;
  }
Exemple #24
0
arma_hot
inline
typename T1::pod_type
arma_vec_norm_2(const Proxy<T1>& A, const typename arma_not_cx<typename T1::elem_type>::result* junk = 0)
  {
  arma_extra_debug_sigprint();
  arma_ignore(junk);
  
  typedef typename T1::pod_type T;
  
  T acc = T(0);
  
  if(Proxy<T1>::prefer_at_accessor == false)
    {
    typename Proxy<T1>::ea_type P = A.get_ea();
    
    const uword N = A.get_n_elem();
    
    uword i,j;
    
    for(i=0, j=1; j<N; i+=2, j+=2)
      {
      const T tmp_i = P[i];
      const T tmp_j = P[j];
      
      acc += tmp_i * tmp_i;
      acc += tmp_j * tmp_j;
      }
    
    if(i < N)
      {
      const T tmp_i = P[i];
      
      acc += tmp_i * tmp_i;
      }
    }
  else
    {
    const uword n_rows = A.get_n_rows();
    const uword n_cols = A.get_n_cols();
    
    for(uword col=0; col<n_cols; ++col)
      {
      uword i,j;
      
      for(i=0, j=1; j<n_rows; i+=2, j+=2)
        {
        const T tmp_i = A.at(i,col);
        const T tmp_j = A.at(j,col);
        
        acc += tmp_i * tmp_i;
        acc += tmp_j * tmp_j;
        }
      
      if(i < n_rows)
        {
        const T tmp_i = A.at(i,col);
        
        acc += tmp_i * tmp_i;
        }
      }
    }
  
  return std::sqrt(acc);
  }
inline
void
subview_elem1<eT,T1>::inplace_op(const Base<eT,T2>& x)
  {
  arma_extra_debug_sigprint();
  
  Mat<eT>& m_local = const_cast< Mat<eT>& >(m);
  
        eT*   m_mem    = m_local.memptr();
  const uword m_n_elem = m_local.n_elem;
  
  const unwrap_check_mixed<T1> aa_tmp(a.get_ref(), m_local);
  const umat& aa = aa_tmp.M;
  
  arma_debug_check
    (
    ( (aa.is_vec() == false) && (aa.is_empty() == false) ),
    "Mat::elem(): given object is not a vector"
    );
  
  const uword* aa_mem    = aa.memptr();
  const uword  aa_n_elem = aa.n_elem;
  
  const Proxy<T2> P(x.get_ref());
  
  arma_debug_check( (aa_n_elem != P.get_n_elem()), "Mat::elem(): size mismatch" );
  
  const bool is_alias = P.is_alias(m);
  
  if( (is_alias == false) && (Proxy<T2>::prefer_at_accessor == false) )
    {
    typename Proxy<T2>::ea_type X = P.get_ea();
    
    uword iq,jq;
    for(iq=0, jq=1; jq < aa_n_elem; iq+=2, jq+=2)
      {
      const uword ii = aa_mem[iq];
      const uword jj = aa_mem[jq];
      
      arma_debug_check( ( (ii >= m_n_elem) || (jj >= m_n_elem) ), "Mat::elem(): index out of bounds" );
      
           if(is_same_type<op_type, op_subview_elem_equ          >::yes) { m_mem[ii] =  X[iq]; m_mem[jj]  = X[jq]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_plus >::yes) { m_mem[ii] += X[iq]; m_mem[jj] += X[jq]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_minus>::yes) { m_mem[ii] -= X[iq]; m_mem[jj] -= X[jq]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_schur>::yes) { m_mem[ii] *= X[iq]; m_mem[jj] *= X[jq]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_div  >::yes) { m_mem[ii] /= X[iq]; m_mem[jj] /= X[jq]; }
      }
    
    if(iq < aa_n_elem)
      {
      const uword ii = aa_mem[iq];
      
      arma_debug_check( (ii >= m_n_elem) , "Mat::elem(): index out of bounds" );
      
           if(is_same_type<op_type, op_subview_elem_equ          >::yes) { m_mem[ii] =  X[iq]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_plus >::yes) { m_mem[ii] += X[iq]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_minus>::yes) { m_mem[ii] -= X[iq]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_schur>::yes) { m_mem[ii] *= X[iq]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_div  >::yes) { m_mem[ii] /= X[iq]; }
      }
    }
  else
    {
    arma_extra_debug_print("subview_elem1::inplace_op(): aliasing or prefer_at_accessor detected");
    
    const unwrap_check<typename Proxy<T2>::stored_type> tmp(P.Q, is_alias);
    const Mat<eT>& M = tmp.M;
    
    const eT* X = M.memptr();
    
    uword iq,jq;
    for(iq=0, jq=1; jq < aa_n_elem; iq+=2, jq+=2)
      {
      const uword ii = aa_mem[iq];
      const uword jj = aa_mem[jq];
      
      arma_debug_check( ( (ii >= m_n_elem) || (jj >= m_n_elem) ), "Mat::elem(): index out of bounds" );
      
           if(is_same_type<op_type, op_subview_elem_equ          >::yes) { m_mem[ii] =  X[iq]; m_mem[jj]  = X[jq]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_plus >::yes) { m_mem[ii] += X[iq]; m_mem[jj] += X[jq]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_minus>::yes) { m_mem[ii] -= X[iq]; m_mem[jj] -= X[jq]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_schur>::yes) { m_mem[ii] *= X[iq]; m_mem[jj] *= X[jq]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_div  >::yes) { m_mem[ii] /= X[iq]; m_mem[jj] /= X[jq]; }
      }
    
    if(iq < aa_n_elem)
      {
      const uword ii = aa_mem[iq];
      
      arma_debug_check( (ii >= m_n_elem) , "Mat::elem(): index out of bounds" );
      
           if(is_same_type<op_type, op_subview_elem_equ          >::yes) { m_mem[ii] =  X[iq]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_plus >::yes) { m_mem[ii] += X[iq]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_minus>::yes) { m_mem[ii] -= X[iq]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_schur>::yes) { m_mem[ii] *= X[iq]; }
      else if(is_same_type<op_type, op_subview_elem_inplace_div  >::yes) { m_mem[ii] /= X[iq]; }
      }
    }
  }
inline
void
op_reshape::apply_proxy(Mat<typename T1::elem_type>& out, const Proxy<T1>& P, const uword in_n_rows, const uword in_n_cols)
  {
  arma_extra_debug_sigprint();
  
  typedef typename T1::elem_type eT;
  
  out.set_size(in_n_rows, in_n_cols);
  
  eT* out_mem = out.memptr();
  
  const uword in_n_elem = in_n_rows * in_n_cols;
  
  if(P.get_n_elem() == in_n_elem)
    {
    if(Proxy<T1>::use_at == false)
      {
      typename Proxy<T1>::ea_type Pea = P.get_ea();
      
      for(uword i=0; i<in_n_elem; ++i)
        {
        out_mem[i] = Pea[i];
        }
      }
    else
      {
      const uword P_n_rows = P.get_n_rows();
      const uword P_n_cols = P.get_n_cols();
      
      for(uword col=0; col < P_n_cols; ++col)
        {
        uword i,j;
        
        for(i=0, j=1; j < P_n_rows; i+=2, j+=2)
          {
          const eT tmp_i = P.at(i,col);
          const eT tmp_j = P.at(j,col);
          
          *out_mem = tmp_i;  out_mem++;
          *out_mem = tmp_j;  out_mem++;
          }
        
        if(i < P_n_rows)
          {
          *out_mem = P.at(i,col);  out_mem++;
          }
        }
      }
    }
  else
    {
    const uword n_elem_to_copy = (std::min)(P.get_n_elem(), in_n_elem);
    
    if(Proxy<T1>::use_at == false)
      {
      typename Proxy<T1>::ea_type Pea = P.get_ea();
      
      for(uword i=0; i<n_elem_to_copy; ++i)
        {
        out_mem[i] = Pea[i];
        }
      }
    else
      {
      uword i = 0;
      
      const uword P_n_rows = P.get_n_rows();
      const uword P_n_cols = P.get_n_cols();
      
      for(uword col=0; col < P_n_cols; ++col)
      for(uword row=0; row < P_n_rows; ++row)
        {
        if(i >= n_elem_to_copy)  { goto nested_loop_end; }
        
        out_mem[i] = P.at(row,col);
        
        ++i;
        }
      
      nested_loop_end: ;
      }
    
    for(uword i=n_elem_to_copy; i<in_n_elem; ++i)
      {
      out_mem[i] = eT(0);
      }
    }
  }
inline
typename arma_not_cx<typename T1::elem_type>::result
op_min::min(const Base<typename T1::elem_type,T1>& X)
  {
  arma_extra_debug_sigprint();
  
  typedef typename T1::elem_type eT;
  
  const Proxy<T1> P(X.get_ref());
  
  const uword n_elem = P.get_n_elem();
  
  arma_debug_check( (n_elem == 0), "min(): given object has no elements" );
  
  eT min_val = priv::most_pos<eT>();
  
  if(Proxy<T1>::prefer_at_accessor == false)
    {
    typedef typename Proxy<T1>::ea_type ea_type;
    
    ea_type A = P.get_ea();
    
    uword i,j;
    
    for(i=0, j=1; j<n_elem; i+=2, j+=2)
      {
      const eT tmp_i = A[i];
      const eT tmp_j = A[j];
      
      if(tmp_i < min_val) { min_val = tmp_i; }
      if(tmp_j < min_val) { min_val = tmp_j; }
      }
    
    if(i < n_elem)
      {
      const eT tmp_i = A[i];
      
      if(tmp_i < min_val) { min_val = tmp_i; }
      }
    }
  else
    {
    const uword n_rows = P.get_n_rows();
    const uword n_cols = P.get_n_cols();
    
    if(n_rows == 1)
      {
      uword i,j;
      for(i=0, j=1; j < n_cols; i+=2, j+=2)
        {
        const eT tmp_i = P.at(0,i);
        const eT tmp_j = P.at(0,j);
        
        if(tmp_i < min_val) { min_val = tmp_i; }
        if(tmp_j < min_val) { min_val = tmp_j; }
        }
      
      if(i < n_cols)
        {
        const eT tmp_i = P.at(0,i);
        
        if(tmp_i < min_val) { min_val = tmp_i; }
        }
      }
    else
      {
      for(uword col=0; col < n_cols; ++col)
        {
        uword i,j;
        for(i=0, j=1; j < n_rows; i+=2, j+=2)
          {
          const eT tmp_i = P.at(i,col);
          const eT tmp_j = P.at(j,col);
          
          if(tmp_i < min_val) { min_val = tmp_i; }
          if(tmp_j < min_val) { min_val = tmp_j; }
          }
          
        if(i < n_rows)
          {
          const eT tmp_i = P.at(i,col);
          
          if(tmp_i < min_val) { min_val = tmp_i; }
          }
        }
      }
    }
  
  return min_val;
  }
inline
typename arma_not_cx<typename T1::elem_type>::result
op_max::max_with_index(const Proxy<T1>& P, uword& index_of_max_val)
  {
  arma_extra_debug_sigprint();
  
  typedef typename T1::elem_type eT;
  
  const uword n_elem = P.get_n_elem();
  
  if(n_elem == 0)
    {
    arma_debug_check(true, "max(): object has no elements");
    
    return Datum<eT>::nan;
    }
  
  eT    best_val   = priv::most_neg<eT>();
  uword best_index = 0;
  
  if(Proxy<T1>::prefer_at_accessor == false)
    {
    typedef typename Proxy<T1>::ea_type ea_type;
    
    ea_type A = P.get_ea();
    
    for(uword i=0; i<n_elem; ++i)
      {
      const eT tmp = A[i];
      
      if(tmp > best_val)  { best_val = tmp;  best_index = i; }
      }
    }
  else
    {
    const uword n_rows = P.get_n_rows();
    const uword n_cols = P.get_n_cols();
    
    if(n_rows == 1)
      {
      for(uword i=0; i < n_cols; ++i)
        {
        const eT tmp = P.at(0,i);
        
        if(tmp > best_val)  { best_val = tmp;  best_index = i; }
        }
      }
    else
    if(n_cols == 1)
      {
      for(uword i=0; i < n_rows; ++i)
        {
        const eT tmp = P.at(i,0);
        
        if(tmp > best_val)  { best_val = tmp;  best_index = i; }
        }
      }
    else
      {
      uword count = 0;
      
      for(uword col=0; col < n_cols; ++col)
      for(uword row=0; row < n_rows; ++row)
        {
        const eT tmp = P.at(row,col);
        
        if(tmp > best_val)  { best_val = tmp;  best_index = count; }
        
        ++count;
        }
      }
    }
  
  index_of_max_val = best_index;
  
  return best_val;
  }
Exemple #29
0
inline
typename T1::elem_type
op_prod::prod(const Base<typename T1::elem_type,T1>& X)
  {
  arma_extra_debug_sigprint();
  
  typedef typename T1::elem_type eT;
  
  const Proxy<T1> P(X.get_ref());
  
  eT val = eT(1);
  
  if(Proxy<T1>::prefer_at_accessor == false)
    {
    typedef typename Proxy<T1>::ea_type ea_type;
    
    const ea_type A = P.get_ea();
    
    const uword n_elem = P.get_n_elem();
    
    uword i,j;
    for(i=0, j=1; j < n_elem; i+=2, j+=2)
      {
      val *= A[i];
      val *= A[j];
      }
    
    if(i < n_elem)
      {
      val *= A[i];
      }
    }
  else
    {
    const uword n_rows = P.get_n_rows();
    const uword n_cols = P.get_n_cols();
    
    if(n_rows == 1)
      {
      uword i,j;
      for(i=0, j=1; j < n_cols; i+=2, j+=2)
        {
        val *= P.at(0,i);
        val *= P.at(0,j);
        }
      
      if(i < n_cols)
        {
        val *= P.at(0,i);
        }
      }
    else
      {
      for(uword col=0; col < n_cols; ++col)
        {
        uword i,j;
        for(i=0, j=1; j < n_rows; i+=2, j+=2)
          {
          val *= P.at(i,col);
          val *= P.at(j,col);
          }
        
        if(i < n_rows)
          {
          val *= P.at(i,col);
          }
        }
      }
    }
  
  return val;
  }
inline
bool
op_unique::apply_helper(Mat<typename T1::elem_type>& out, const Proxy<T1>& P)
  {
  arma_extra_debug_sigprint();
  
  typedef typename T1::elem_type eT;
  
  const uword n_rows = P.get_n_rows();
  const uword n_cols = P.get_n_cols();
  const uword n_elem = P.get_n_elem();
  
  if(n_elem == 0)  { out.set_size(n_rows, n_cols); return true; }
  
  if(n_elem == 1)
    {
    const eT tmp = (Proxy<T1>::use_at) ? P.at(0,0) : P[0];
    
    out.set_size(n_rows, n_cols);
    
    out[0] = tmp;
    
    return true;
    }
  
  Mat<eT> X(n_elem,1);
  
  eT* X_mem = X.memptr();
  
  if(Proxy<T1>::use_at == false)
    {
    typename Proxy<T1>::ea_type Pea = P.get_ea();
    
    for(uword i=0; i<n_elem; ++i)
      {
      const eT val = Pea[i];
      
      if(arma_isnan(val))  { out.reset(); return false; }
      
      X_mem[i] = val;
      }
    }
  else
    {
    for(uword col=0; col < n_cols; ++col)
    for(uword row=0; row < n_rows; ++row)
      {
      const eT val = P.at(row,col);
      
      if(arma_isnan(val))  { out.reset(); return false; }
      
      (*X_mem) = val;  X_mem++;
      }
    
    X_mem = X.memptr();
    }
  
  arma_unique_comparator<eT> comparator;
  
  std::sort( X.begin(), X.end(), comparator );
  
  uword N_unique = 1;
  
  for(uword i=1; i < n_elem; ++i)
    {
    const eT a = X_mem[i-1];
    const eT b = X_mem[i  ];
    
    const eT diff = a - b;
    
    if(diff != eT(0)) { ++N_unique; }
    }
  
  uword out_n_rows;
  uword out_n_cols;
  
  if( (n_rows == 1) || (n_cols == 1) )
    {
    if(n_rows == 1)
      {
      out_n_rows = 1;
      out_n_cols = N_unique;
      }
    else
      {
      out_n_rows = N_unique;
      out_n_cols = 1;
      }
    }
  else
    {
    out_n_rows = N_unique;
    out_n_cols = 1;
    }
  
  out.set_size(out_n_rows, out_n_cols);
  
  eT* out_mem = out.memptr();
  
  if(n_elem > 0)  { (*out_mem) = X_mem[0];  out_mem++; }
  
  for(uword i=1; i < n_elem; ++i)
    {
    const eT a = X_mem[i-1];
    const eT b = X_mem[i  ];
    
    const eT diff = a - b;
    
    if(diff != eT(0))  { (*out_mem) = b;  out_mem++; }
    }
  
  return true;
  }