Exemple #1
0
arma_hot
inline
void
arma_check(const bool state, const T1& x)
  {
  if(state)  { arma_stop_logic_error(arma_str::str_wrapper(x)); }
  }
Exemple #2
0
arma_hot
inline
void
arma_check(const bool state, const T1& x, const T2& y)
  {
  if(state)  { arma_stop_logic_error( std::string(x) + std::string(y) ); }
  }
inline
typename T1::pod_type
op_norm::mat_norm_2(const SpProxy<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;
  
  // we're calling eigs_gen(), which currently requires ARPACK
  #if !defined(ARMA_USE_ARPACK)
    {
    arma_stop_logic_error("norm(): use of ARPACK must be enabled for norm of complex matrices");
    return T(0);
    }
  #endif
  
  const unwrap_spmat<typename SpProxy<T1>::stored_type> tmp(P.Q);
  
  const SpMat<eT>& A = tmp.M;
  const SpMat<eT>  B = trans(A);
  
  const SpMat<eT>  C = (A.n_rows <= A.n_cols) ? (A*B) : (B*A);
  
  Col<eT> eigval;
  eigs_gen(eigval, C, 1);
  
  return (eigval.n_elem > 0) ? std::sqrt(std::real(eigval[0])) : T(0);
  }
 arma_inline static typename get_pod_type<eT>::result get(const eT& val)
   {
   arma_ignore(val);
   arma_stop_logic_error("newarp::SortingTarget: incompatible selection rule");
   
   typedef typename get_pod_type<eT>::result out_T;
   return out_T(0);
   }
Exemple #5
0
arma_hot
inline
void
arma_assert_same_size(const uword A_n_rows, const uword A_n_cols, const uword A_n_slices, const uword B_n_rows, const uword B_n_cols, const uword B_n_slices, const char* x)
  {
  if( (A_n_rows != B_n_rows) || (A_n_cols != B_n_cols) || (A_n_slices != B_n_slices) )
    {
    arma_stop_logic_error( arma_incompat_size_string(A_n_rows, A_n_cols, A_n_slices, B_n_rows, B_n_cols, B_n_slices, x) );
    }
  }
Exemple #6
0
arma_hot
inline
void
arma_assert_mul_size(const subview<eT1>& A, const subview<eT2>& B, const char* x)
  {
  if(A.n_cols != B.n_rows)
    {
    arma_stop_logic_error( arma_incompat_size_string(A.n_rows, A.n_cols, B.n_rows, B.n_cols, x) );
    }
  }
Exemple #7
0
arma_hot
inline
void
arma_assert_same_size(const Mat<eT1>& A, const subview_cube<eT2>& B, const char* x)
  {
  if( (A.n_rows != B.n_rows) || (A.n_cols != B.n_cols) || (1 != B.n_slices) )
    {
    arma_stop_logic_error( arma_incompat_size_string(A.n_rows, A.n_cols, 1, B.n_rows, B.n_cols, B.n_slices, x) );
    }
  }
inline
void
subview_cube_each_common<eT>::check_size(const Mat<eT>& A) const
  {
  if(arma_config::debug)
    {
    if( (A.n_rows != P.n_rows) || (A.n_cols != P.n_cols) )
      {
      arma_stop_logic_error( incompat_size_string(A) );
      }
    }
  }
Exemple #9
0
arma_hot
inline
void
arma_assert_mul_size(const Mat<eT1>& A, const Mat<eT2>& B, const char* x)
  {
  const uword A_n_cols = A.n_cols;
  const uword B_n_rows = B.n_rows;
  
  if(A_n_cols != B_n_rows)
    {
    arma_stop_logic_error( arma_incompat_size_string(A.n_rows, A_n_cols, B_n_rows, B.n_cols, x) );
    }
  }
Exemple #10
0
arma_hot
inline
void
arma_assert_mul_size(const Mat<eT1>& A, const Mat<eT2>& B, const bool do_trans_A, const bool do_trans_B, const char* x)
  {
  const uword final_A_n_cols = (do_trans_A == false) ? A.n_cols : A.n_rows;
  const uword final_B_n_rows = (do_trans_B == false) ? B.n_rows : B.n_cols;
    
  if(final_A_n_cols != final_B_n_rows)
    {
    const uword final_A_n_rows = (do_trans_A == false) ? A.n_rows : A.n_cols;
    const uword final_B_n_cols = (do_trans_B == false) ? B.n_cols : B.n_rows;
    
    arma_stop_logic_error( arma_incompat_size_string(final_A_n_rows, final_A_n_cols, final_B_n_rows, final_B_n_cols, x) );
    }
  }
Exemple #11
0
arma_hot
inline
void
arma_assert_trans_mul_size(const uword A_n_rows, const uword A_n_cols, const uword B_n_rows, const uword B_n_cols, const char* x)
  {
  const uword final_A_n_cols = (do_trans_A == false) ? A_n_cols : A_n_rows;
  const uword final_B_n_rows = (do_trans_B == false) ? B_n_rows : B_n_cols;
    
  if(final_A_n_cols != final_B_n_rows)
    {
    const uword final_A_n_rows = (do_trans_A == false) ? A_n_rows : A_n_cols;
    const uword final_B_n_cols = (do_trans_B == false) ? B_n_cols : B_n_rows;
    
    arma_stop_logic_error( arma_incompat_size_string(final_A_n_rows, final_A_n_cols, final_B_n_rows, final_B_n_cols, x) );
    }
  }
Exemple #12
0
arma_hot
inline
void
arma_assert_same_size(const subview<eT1>& A, const Proxy<eT2>& B, const char* x)
  {
  const uword A_n_rows = A.n_rows;
  const uword A_n_cols = A.n_cols;
  
  const uword B_n_rows = B.get_n_rows();
  const uword B_n_cols = B.get_n_cols();
  
  if( (A_n_rows != B_n_rows) || (A_n_cols != B_n_cols) )
    {
    arma_stop_logic_error( arma_incompat_size_string(A_n_rows, A_n_cols, B_n_rows, B_n_cols, x) );
    }
  }
inline
bool
op_sqrtmat_sympd::apply_direct(Mat<typename T1::elem_type>& out, const Base<typename T1::elem_type,T1>& expr)
  {
  arma_extra_debug_sigprint();
  
  #if defined(ARMA_USE_LAPACK)
    {
    typedef typename T1::pod_type   T;
    typedef typename T1::elem_type eT;
    
    const unwrap<T1>   U(expr.get_ref());
    const Mat<eT>& X = U.M;
    
    arma_debug_check( (X.is_square() == false), "sqrtmat_sympd(): given matrix must be square sized" );
    
    Col< T> eigval;
    Mat<eT> eigvec;
    
    const bool status = auxlib::eig_sym_dc(eigval, eigvec, X);
    
    if(status == false)  { return false; }
    
    const uword N          = eigval.n_elem;
    const T*    eigval_mem = eigval.memptr();
    
    bool all_pos = true;
    
    for(uword i=0; i<N; ++i)  { all_pos = (eigval_mem[i] < T(0)) ? false : all_pos; }
    
    if(all_pos == false)  { return false; }
    
    eigval = sqrt(eigval);
    
    out = eigvec * diagmat(eigval) * eigvec.t();
    
    return true;
    }
  #else
    {
    arma_ignore(out);
    arma_ignore(expr);
    arma_stop_logic_error("sqrtmat_sympd(): use of LAPACK must be enabled");
    return false;
    }
  #endif
  }
 static
 inline
 eT
 eval(const eT x)
   {
   #if defined(ARMA_USE_CXX11)
     {
     return eT( std::arg(x) );
     }
   #else
     {
     arma_ignore(x);
     arma_stop_logic_error("arg(): need C++11 compiler");
     
     return eT(0);
     }
   #endif
   }
arma_inline
std::complex<T>
arma_atanh(const std::complex<T>& x)
  {
  #if defined(ARMA_USE_CXX11)
    {
    return std::atanh(x);
    }
  #elif defined(ARMA_HAVE_TR1)
    {
    return std::tr1::atanh(x);
    }
  #else
    {
    arma_ignore(x);
    arma_stop_logic_error("atanh(): need C++11 compiler");
    
    return std::complex<T>(0);
    }
  #endif
  }
inline
arma_warn_unused
typename enable_if2< is_arma_type<T1>::value, typename T1::pod_type >::result
norm
  (
  const T1&   X,
  const char* method,
  const typename arma_real_or_cx_only<typename T1::elem_type>::result* junk = 0
  )
  {
  arma_extra_debug_sigprint();
  arma_ignore(junk);
  
  typedef typename T1::pod_type T;
  
  const Proxy<T1> P(X);
  
  if(P.get_n_elem() == 0)
    {
    return T(0);
    }
  
  const char sig    = (method != NULL) ? method[0] : char(0);
  const bool is_vec = (T1::is_row) || (T1::is_col) || (P.get_n_rows() == 1) || (P.get_n_cols() == 1);
  
  if(is_vec)
    {
    if( (sig == 'i') || (sig == 'I') || (sig == '+') )   // max norm
      {
      return op_norm::vec_norm_max(P);
      }
    else
    if(sig == '-')   // min norm
      {
      return op_norm::vec_norm_min(P);
      }
    else
    if( (sig == 'f') || (sig == 'F') )
      {
      return op_norm::vec_norm_2(P);
      }
    else
      {
      arma_stop_logic_error("norm(): unsupported vector norm type");
      return T(0);
      }
    }
  else
    {
    if( (sig == 'i') || (sig == 'I') || (sig == '+') )   // inf norm
      {
      return op_norm::mat_norm_inf(P);
      }
    else
    if( (sig == 'f') || (sig == 'F') )
      {
      return op_norm::vec_norm_2(P);
      }
    else
      {
      arma_stop_logic_error("norm(): unsupported matrix norm type");
      return T(0);
      }
    }
  }
inline
arma_warn_unused
typename enable_if2< is_arma_sparse_type<T1>::value, typename T1::pod_type >::result
norm
  (
  const T1&   X,
  const char* method,
  const typename arma_real_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 SpProxy<T1> P(X);
  
  if(P.get_n_nonzero() == 0)
    {
    return T(0);
    }
  
  
  const unwrap_spmat<typename SpProxy<T1>::stored_type> tmp(P.Q);
  const SpMat<eT>& A = tmp.M;
  
  // create a fake dense vector to allow reuse of code for dense vectors
  Col<eT> fake_vector( access::rwp(A.values), A.n_nonzero, false );
  
  const Proxy< Col<eT> > P_fake_vector(fake_vector);
  
  
  const char sig    = (method != NULL) ? method[0] : char(0);
  const bool is_vec = (P.get_n_rows() == 1) || (P.get_n_cols() == 1);  // TODO: (T1::is_row) || (T1::is_col) || ...
  
  if(is_vec == true)
    {
    if( (sig == 'i') || (sig == 'I') || (sig == '+') )   // max norm
      {
      return op_norm::vec_norm_max(P_fake_vector);
      }
    else
    if(sig == '-')   // min norm
      {
      const T val = op_norm::vec_norm_min(P_fake_vector);
      
      if( P.get_n_nonzero() < P.get_n_elem() )
        {
        return (std::min)(T(0), val);
        }
      else
        {
        return val;
        }
      }
    else
    if( (sig == 'f') || (sig == 'F') )
      {
      return op_norm::vec_norm_2(P_fake_vector);
      }
    else
      {
      arma_stop_logic_error("norm(): unsupported vector norm type");
      return T(0);
      }
    }
  else
    {
    if( (sig == 'i') || (sig == 'I') || (sig == '+') )   // inf norm
      {
      return op_norm::mat_norm_inf(P);
      }
    else
    if( (sig == 'f') || (sig == 'F') )
      {
      return op_norm::vec_norm_2(P_fake_vector);
      }
    else
      {
      arma_stop_logic_error("norm(): unsupported matrix norm type");
      return T(0);
      }
    }
  }
inline
arma_warn_unused
typename enable_if2< is_arma_type<T1>::value, typename T1::pod_type >::result
norm
  (
  const T1&   X,
  const uword k = uword(2),
  const typename arma_real_or_cx_only<typename T1::elem_type>::result* junk = 0
  )
  {
  arma_extra_debug_sigprint();
  arma_ignore(junk);
  
  typedef typename T1::pod_type T;
  
  const Proxy<T1> P(X);
  
  if(P.get_n_elem() == 0)
    {
    return T(0);
    }
  
  const bool is_vec = (T1::is_row) || (T1::is_col) || (P.get_n_rows() == 1) || (P.get_n_cols() == 1);
  
  if(is_vec)
    {
    switch(k)
      {
      case 1:
        return op_norm::vec_norm_1(P);
        break;
      
      case 2:
        return op_norm::vec_norm_2(P);
        break;
      
      default:
        {
        arma_debug_check( (k == 0), "norm(): k must be greater than zero" );
        return op_norm::vec_norm_k(P, int(k));
        }
      }
    }
  else
    {
    switch(k)
      {
      case 1:
        return op_norm::mat_norm_1(P);
        break;
      
      case 2:
        return op_norm::mat_norm_2(P);
        break;
      
      default:
        arma_stop_logic_error("norm(): unsupported matrix norm type");
        return T(0);
      }
    }
  
  return T(0);  // prevent erroneous compiler warnings
  }
inline
arma_warn_unused
typename enable_if2< is_arma_sparse_type<T1>::value, typename T1::pod_type >::result
norm
  (
  const T1&   X,
  const uword k = uword(2),
  const typename arma_real_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 SpProxy<T1> P(X);
  
  if(P.get_n_nonzero() == 0)
    {
    return T(0);
    }
  
  const bool is_vec = (P.get_n_rows() == 1) || (P.get_n_cols() == 1);
  
  if(is_vec == true)
    {
    const unwrap_spmat<typename SpProxy<T1>::stored_type> tmp(P.Q);
    const SpMat<eT>& A = tmp.M;
    
    // create a fake dense vector to allow reuse of code for dense vectors
    Col<eT> fake_vector( access::rwp(A.values), A.n_nonzero, false );
    
    const Proxy< Col<eT> > P_fake_vector(fake_vector);
    
    switch(k)
      {
      case 1:
        return op_norm::vec_norm_1(P_fake_vector);
        break;
      
      case 2:
        return op_norm::vec_norm_2(P_fake_vector);
        break;
      
      default:
        {
        arma_debug_check( (k == 0), "norm(): k must be greater than zero"   );
        return op_norm::vec_norm_k(P_fake_vector, int(k));
        }
      }
    }
  else
    {
    switch(k)
      {
      case 1:
        return op_norm::mat_norm_1(P);
        break;
      
      case 2:
        return op_norm::mat_norm_2(P);
        break;
      
      default:
        arma_stop_logic_error("norm(): unsupported or unimplemented norm type for sparse matrices");
        return T(0);
      }
    }
  }
Exemple #20
0
arma_warn_unused
inline
obj_type
randg(const uword n_rows, const uword n_cols, const distr_param& param = distr_param(), const typename arma_Mat_Col_Row_only<obj_type>::result* junk = 0)
  {
  arma_extra_debug_sigprint();
  arma_ignore(junk);
  
  #if defined(ARMA_USE_CXX11)
    {
    if(is_Col<obj_type>::value == true)
      {
      arma_debug_check( (n_cols != 1), "randg(): incompatible size" );
      }
    else
    if(is_Row<obj_type>::value == true)
      {
      arma_debug_check( (n_rows != 1), "randg(): incompatible size" );
      }
    
    obj_type out(n_rows, n_cols);
    
    double a;
    double b;
    
    if(param.state == 0)
      {
      a = double(1);
      b = double(1);
      }
    else
    if(param.state == 1)
      {
      a = double(param.a_int);
      b = double(param.b_int);
      }
    else
      {
      a = param.a_double;
      b = param.b_double;
      }
    
    arma_debug_check( ((a <= double(0)) || (b <= double(0))), "randg(): a and b must be greater than zero" );
    
    #if defined(ARMA_USE_EXTERN_CXX11_RNG)
      {
      arma_rng_cxx11_instance.randg_fill(out.memptr(), out.n_elem, a, b);
      }
    #else
      {
      arma_rng_cxx11 local_arma_rng_cxx11_instance;
      
      typedef typename arma_rng_cxx11::seed_type seed_type;
      
      local_arma_rng_cxx11_instance.set_seed( seed_type(arma_rng::randi<seed_type>()) );
      
      local_arma_rng_cxx11_instance.randg_fill(out.memptr(), out.n_elem, a, b);
      }
    #endif
    
    return out;
    }
  #else
    {
    arma_ignore(n_rows);
    arma_ignore(n_cols);
    arma_ignore(param);
    
    arma_stop_logic_error("randg(): C++11 compiler required");
    
    return obj_type();
    }
  #endif
  }
inline
typename T1::elem_type
op_median::median_vec
  (
  const T1& X,
  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;
  
  const Proxy<T1> P(X);
  
  const uword n_elem = P.get_n_elem();
  
  if(n_elem == 0)
    {
    arma_debug_check(true, "median(): object has no elements");
    
    return Datum<eT>::nan;
    }
  
  std::vector< arma_cx_median_packet<T> > tmp_vec(n_elem);
  
  if(Proxy<T1>::use_at == false)
    {
    typedef typename Proxy<T1>::ea_type ea_type;
    
    ea_type A = P.get_ea();
    
    for(uword i=0; i<n_elem; ++i)
      {
      tmp_vec[i].val   = std::abs( A[i] );
      tmp_vec[i].index = i;
      }
    
    uword index1;
    uword index2;
    op_median::direct_cx_median_index(index1, index2, tmp_vec);
    
    return op_mean::robust_mean( A[index1], A[index2] );
    }
  else
    {
    const uword n_rows = P.get_n_rows();
    const uword n_cols = P.get_n_cols();
    
    if(n_cols == 1)
      {
      for(uword row=0; row < n_rows; ++row)
        {
        tmp_vec[row].val   = std::abs( P.at(row,0) );
        tmp_vec[row].index = row;
        }
      
      uword index1;
      uword index2;
      op_median::direct_cx_median_index(index1, index2, tmp_vec);
      
      return op_mean::robust_mean( P.at(index1,0), P.at(index2,0) );
      }
    else
    if(n_rows == 1)
      {
      for(uword col=0; col < n_cols; ++col)
        {
        tmp_vec[col].val   = std::abs( P.at(0,col) );
        tmp_vec[col].index = col;
        }
      
      uword index1;
      uword index2;
      op_median::direct_cx_median_index(index1, index2, tmp_vec);
      
      return op_mean::robust_mean( P.at(0,index1), P.at(0,index2) );
      }
    else
      {
      arma_stop_logic_error("op_median::median_vec(): expected a vector" );
      
      return eT(0);
      }
    }
  }
inline
typename T1::elem_type
op_median::median_vec
  (
  const T1& X,
  const typename arma_not_cx<typename T1::elem_type>::result* junk
  )
  {
  arma_extra_debug_sigprint();
  arma_ignore(junk);
  
  typedef typename T1::elem_type eT;
  
  typedef typename Proxy<T1>::stored_type P_stored_type;
    
  const Proxy<T1> P(X);
  
  const uword n_elem = P.get_n_elem();
  
  if(n_elem == 0)
    {
    arma_debug_check(true, "median(): object has no elements");
    
    return Datum<eT>::nan;
    }
  
  std::vector<eT> tmp_vec(n_elem);
  
  if(is_Mat<P_stored_type>::value == true)
    {
    const unwrap<P_stored_type> tmp(P.Q);
    
    const typename unwrap<P_stored_type>::stored_type& Y = tmp.M;
    
    arrayops::copy( &(tmp_vec[0]), Y.memptr(), n_elem );
    }
  else
    {
    if(Proxy<T1>::use_at == false)
      {
      typedef typename Proxy<T1>::ea_type ea_type;
      
      ea_type A = P.get_ea();
      
      for(uword i=0; i<n_elem; ++i)  { tmp_vec[i] = A[i]; }
      }
    else
      {
      const uword n_rows = P.get_n_rows();
      const uword n_cols = P.get_n_cols();
      
      if(n_cols == 1)
        {
        for(uword row=0; row < n_rows; ++row)  { tmp_vec[row] = P.at(row,0); }
        }
      else
      if(n_rows == 1)
        {
        for(uword col=0; col < n_cols; ++col)  { tmp_vec[col] = P.at(0,col); }
        }
      else
        {
        arma_stop_logic_error("op_median::median_vec(): expected a vector" );
        }
      }
    }
  
  return op_median::direct_median(tmp_vec);
  }
Exemple #23
0
inline
void
arma_assert_cube_as_mat(const Mat<eT>& M, const T1& Q, const char* x, const bool check_compat_size)
  {
  const uword Q_n_rows   = Q.n_rows;
  const uword Q_n_cols   = Q.n_cols;
  const uword Q_n_slices = Q.n_slices;
  
  const uword M_vec_state = M.vec_state;
  
  if(M_vec_state == 0)
    {
    if( ( (Q_n_rows == 1) || (Q_n_cols == 1) || (Q_n_slices == 1) ) == false )
      {
      std::stringstream tmp;
        
      tmp << x
          << ": can't interpret cube with dimensions "
          << Q_n_rows << 'x' << Q_n_cols << 'x' << Q_n_slices 
          << " as a matrix; one of the dimensions must be 1";
      
      arma_stop_logic_error( tmp.str() );
      }
    }
  else
    {
    if(Q_n_slices == 1)
      {
      if( (M_vec_state == 1) && (Q_n_cols != 1) )
        {
        std::stringstream tmp;
        
        tmp << x
            << ": can't interpret cube with dimensions "
            << Q_n_rows << 'x' << Q_n_cols << 'x' << Q_n_slices
            << " as a column vector";
        
        arma_stop_logic_error( tmp.str() );
        }
      
      if( (M_vec_state == 2) && (Q_n_rows != 1) )
        {
        std::stringstream tmp;
        
        tmp << x
            << ": can't interpret cube with dimensions "
            << Q_n_rows << 'x' << Q_n_cols << 'x' << Q_n_slices
            << " as a row vector";
        
        arma_stop_logic_error( tmp.str() );
        }
      }
    else
      {
      if( (Q_n_cols != 1) && (Q_n_rows != 1) )
        {
        std::stringstream tmp;
        
        tmp << x
            << ": can't interpret cube with dimensions "
            << Q_n_rows << 'x' << Q_n_cols << 'x' << Q_n_slices
            << " as a vector";
        
        arma_stop_logic_error( tmp.str() );
        }
      }
    }
  
  
  if(check_compat_size == true)
    {
    const uword M_n_rows = M.n_rows;
    const uword M_n_cols = M.n_cols;
    
    if(M_vec_state == 0)
      {
      if(
          (
          ( (Q_n_rows == M_n_rows) && (Q_n_cols   == M_n_cols) )
          ||
          ( (Q_n_rows == M_n_rows) && (Q_n_slices == M_n_cols) )
          ||
          ( (Q_n_cols == M_n_rows) && (Q_n_slices == M_n_cols) )
          )
          == false
        )
        {
        std::stringstream tmp;
        
        tmp << x
            << ": can't interpret cube with dimensions "
            << Q_n_rows << 'x' << Q_n_cols << 'x' << Q_n_slices
            << " as a matrix with dimensions "
            << M_n_rows << 'x' << M_n_cols;
        
        arma_stop_logic_error( tmp.str() );
        }
      }
    else
      {
      if(Q_n_slices == 1)
        {
        if( (M_vec_state == 1) && (Q_n_rows != M_n_rows) )
          {
          std::stringstream tmp;
          
          tmp << x
              << ": can't interpret cube with dimensions "
              << Q_n_rows << 'x' << Q_n_cols << 'x' << Q_n_slices
              << " as a column vector with dimensions "
              << M_n_rows << 'x' << M_n_cols;
          
          arma_stop_logic_error( tmp.str() );
          }
        
        if( (M_vec_state == 2) && (Q_n_cols != M_n_cols) )
          {
          std::stringstream tmp;
          
          tmp << x
              << ": can't interpret cube with dimensions "
              << Q_n_rows << 'x' << Q_n_cols << 'x' << Q_n_slices
              << " as a row vector with dimensions "
              << M_n_rows << 'x' << M_n_cols;
          
          arma_stop_logic_error( tmp.str() );
          }
        }
      else
        {
        if( ( (M_n_cols == Q_n_slices) || (M_n_rows == Q_n_slices) ) == false )
          {
          std::stringstream tmp;
          
          tmp << x
              << ": can't interpret cube with dimensions "
              << Q_n_rows << 'x' << Q_n_cols << 'x' << Q_n_slices
              << " as a vector with dimensions "
              << M_n_rows << 'x' << M_n_cols;
          
          arma_stop_logic_error( tmp.str() );
          }
        }
      }
    }
  }