Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
78717c2af5 | ||
|
|
32cdd2fd27 | ||
|
|
e3aebbe0f5 | ||
|
|
80087a3a55 | ||
|
|
d0b07c02a3 | ||
|
|
1716a6b531 | ||
|
|
a86cfc932b | ||
|
|
8ce3f3aa7d | ||
|
|
89158f7777 | ||
|
|
cedbd0eb89 | ||
|
|
fd38c47657 | ||
|
|
bb5c4469b3 | ||
|
|
36b0cd37ec | ||
|
|
59fbefc095 | ||
|
|
b1f3a185bf | ||
|
|
adcbf1380a | ||
|
|
733533f089 | ||
|
|
ae6f216a82 | ||
|
|
417bb37042 | ||
|
|
95cad27904 | ||
|
|
3e66e7b1f0 |
@@ -9655,7 +9655,7 @@ vec b = diff(a);
|
||||
</li>
|
||||
<br>
|
||||
<li>
|
||||
<b>Caveat:</b> <a href="#norm">norm()</a> is preferred for calculating the 2-norm, as it reduces the incidence of numerical underflows and overflows
|
||||
<b>Caveat:</b> to obtain the Euclidean norm, use the more robust <a href="#norm">norm(x)</a> instead of <i>sqrt(dot(x,x))</i>
|
||||
</li>
|
||||
<br>
|
||||
<li>
|
||||
|
||||
@@ -352,7 +352,7 @@ Base<elem_type,derived>::is_symmetric(const typename get_pod_type<elem_type>::re
|
||||
|
||||
if(tol == T(0)) { return (*this).is_symmetric(); }
|
||||
|
||||
arma_conform_check( ((tol >= T(0)) == false), "is_symmetric(): parameter 'tol' must be >= 0" );
|
||||
arma_conform_check( ((tol >= T(0)) == false), "is_symmetric(): parameter 'tol' must be > 0" );
|
||||
|
||||
const quasi_unwrap<derived> U( (*this).get_ref() );
|
||||
|
||||
@@ -365,8 +365,12 @@ Base<elem_type,derived>::is_symmetric(const typename get_pod_type<elem_type>::re
|
||||
|
||||
if(norm_A == T(0)) { return true; }
|
||||
|
||||
if(arma_isnan(norm_A)) { return false; }
|
||||
|
||||
const T norm_A_Ast = as_scalar( arma::max(sum(abs(A - A.st()), 1), 0) );
|
||||
|
||||
if(arma_isnan(norm_A_Ast)) { return false; }
|
||||
|
||||
return ( (norm_A_Ast / norm_A) <= tol );
|
||||
}
|
||||
|
||||
@@ -435,7 +439,7 @@ Base<elem_type,derived>::is_hermitian(const typename get_pod_type<elem_type>::re
|
||||
|
||||
if(tol == T(0)) { return (*this).is_hermitian(); }
|
||||
|
||||
arma_conform_check( ((tol >= T(0)) == false), "is_hermitian(): parameter 'tol' must be >= 0" );
|
||||
arma_conform_check( ((tol >= T(0)) == false), "is_hermitian(): parameter 'tol' must be > 0" );
|
||||
|
||||
const quasi_unwrap<derived> U( (*this).get_ref() );
|
||||
|
||||
@@ -448,8 +452,12 @@ Base<elem_type,derived>::is_hermitian(const typename get_pod_type<elem_type>::re
|
||||
|
||||
if(norm_A == T(0)) { return true; }
|
||||
|
||||
if(arma_isnan(norm_A)) { return false; }
|
||||
|
||||
const T norm_A_At = as_scalar( arma::max(sum(abs(A - A.t()), 1), 0) );
|
||||
|
||||
if(arma_isnan(norm_A_At)) { return false; }
|
||||
|
||||
return ( (norm_A_At / norm_A) <= tol );
|
||||
}
|
||||
|
||||
@@ -927,6 +935,8 @@ Base_extra_yes<elem_type,derived>::is_sympd() const
|
||||
// default value for tol
|
||||
const T tol = T(100) * std::numeric_limits<T>::epsilon() * norm(X, "fro");
|
||||
|
||||
if(arma_isnan(tol)) { return false; }
|
||||
|
||||
if(X.is_hermitian(tol) == false) { return false; }
|
||||
|
||||
if(X.is_empty()) { return false; }
|
||||
|
||||
@@ -2544,7 +2544,7 @@ Mat<eT>::Mat(const subview_elem1<eT,T1>& X, const arma_vec_indicator&, const uhw
|
||||
{
|
||||
arma_debug_sigprint_this(this);
|
||||
|
||||
(*this).operator=(X);
|
||||
subview_elem1<eT,T1>::extract_noalias(*this, X);
|
||||
}
|
||||
|
||||
|
||||
@@ -2563,7 +2563,7 @@ Mat<eT>::Mat(const subview_elem1<eT,T1>& X)
|
||||
{
|
||||
arma_debug_sigprint_this(this);
|
||||
|
||||
(*this).operator=(X);
|
||||
subview_elem1<eT,T1>::extract_noalias(*this, X);
|
||||
}
|
||||
|
||||
|
||||
@@ -2672,7 +2672,7 @@ Mat<eT>::Mat(const subview_elem2<eT,T1,T2>& X, const arma_vec_indicator&, const
|
||||
{
|
||||
arma_debug_sigprint_this(this);
|
||||
|
||||
(*this).operator=(X);
|
||||
subview_elem2<eT,T1,T2>::extract_noalias(*this, X);
|
||||
}
|
||||
|
||||
|
||||
@@ -2691,7 +2691,7 @@ Mat<eT>::Mat(const subview_elem2<eT,T1,T2>& X)
|
||||
{
|
||||
arma_debug_sigprint_this(this);
|
||||
|
||||
(*this).operator=(X);
|
||||
subview_elem2<eT,T1,T2>::extract_noalias(*this, X);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1537,7 +1537,7 @@ struct Proxy_xtrans_default< Op<T1, op_htrans> >
|
||||
arma_inline aligned_ea_type get_aligned_ea() const { return Q; }
|
||||
|
||||
template<typename eT2>
|
||||
arma_inline bool is_alias(const Mat<eT2>& X) const { return void_ptr(&(U.M)) == void_ptr(&X); }
|
||||
arma_inline bool is_alias(const Mat<eT2>& X) const { return U.is_alias(X); }
|
||||
|
||||
template<typename eT2>
|
||||
arma_inline bool has_overlap(const subview<eT2>& X) const { return is_alias(X.m); }
|
||||
@@ -1578,7 +1578,7 @@ struct Proxy_xtrans_default< Op<T1, op_strans> >
|
||||
arma_inline aligned_ea_type get_aligned_ea() const { return Q; }
|
||||
|
||||
template<typename eT2>
|
||||
arma_inline bool is_alias(const Mat<eT2>& X) const { return void_ptr(&(U.M)) == void_ptr(&X); }
|
||||
arma_inline bool is_alias(const Mat<eT2>& X) const { return U.is_alias(X); }
|
||||
|
||||
template<typename eT2>
|
||||
arma_inline bool has_overlap(const subview<eT2>& X) const { return is_alias(X.m); }
|
||||
@@ -2441,7 +2441,7 @@ struct Proxy_vectorise_col_mat< Op<T1, op_vectorise_col> >
|
||||
arma_inline aligned_ea_type get_aligned_ea() const { return Q; }
|
||||
|
||||
template<typename eT2>
|
||||
arma_inline bool is_alias(const Mat<eT2>& X) const { return ( void_ptr(&X) == void_ptr(&(U.M)) ); }
|
||||
arma_inline bool is_alias(const Mat<eT2>& X) const { return U.is_alias(X); }
|
||||
|
||||
template<typename eT2>
|
||||
arma_inline bool has_overlap(const subview<eT2>& X) const { return is_alias(X.m); }
|
||||
|
||||
@@ -52,8 +52,6 @@ struct SpBase
|
||||
{
|
||||
arma_inline const derived& get_ref() const;
|
||||
|
||||
arma_inline bool is_alias(const SpMat<elem_type>& X) const;
|
||||
|
||||
arma_warn_unused inline const SpOp<derived,spop_htrans> t() const; //!< Hermitian transpose
|
||||
arma_warn_unused inline const SpOp<derived,spop_htrans> ht() const; //!< Hermitian transpose
|
||||
arma_warn_unused inline const SpOp<derived,spop_strans> st() const; //!< simple transpose
|
||||
|
||||
@@ -31,16 +31,6 @@ SpBase<elem_type,derived>::get_ref() const
|
||||
|
||||
|
||||
|
||||
template<typename elem_type, typename derived>
|
||||
arma_inline
|
||||
bool
|
||||
SpBase<elem_type,derived>::is_alias(const SpMat<elem_type>& X) const
|
||||
{
|
||||
return (*this).get_ref().is_alias(X);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename elem_type, typename derived>
|
||||
inline
|
||||
const SpOp<derived, spop_htrans>
|
||||
|
||||
@@ -35,7 +35,8 @@ struct SpGlue : public SpBase< typename T1::elem_type, SpGlue<T1, T2, spglue_typ
|
||||
inline SpGlue(const T1& in_A, const T2& in_B, const elem_type in_aux);
|
||||
inline ~SpGlue();
|
||||
|
||||
arma_inline bool is_alias(const SpMat<elem_type>& X) const;
|
||||
template<typename eT2>
|
||||
arma_inline bool is_alias(const SpMat<eT2>& X) const;
|
||||
|
||||
const T1& A; //!< first operand; must be derived from SpBase
|
||||
const T2& B; //!< second operand; must be derived from SpBase
|
||||
|
||||
@@ -54,9 +54,10 @@ SpGlue<T1,T2,spglue_type>::~SpGlue()
|
||||
|
||||
|
||||
template<typename T1, typename T2, typename spglue_type>
|
||||
template<typename eT2>
|
||||
arma_inline
|
||||
bool
|
||||
SpGlue<T1,T2,spglue_type>::is_alias(const SpMat<typename T1::elem_type>& X) const
|
||||
SpGlue<T1,T2,spglue_type>::is_alias(const SpMat<eT2>& X) const
|
||||
{
|
||||
return (A.is_alias(X) || B.is_alias(X));
|
||||
}
|
||||
|
||||
@@ -647,7 +647,8 @@ class SpMat : public SpBase< eT, SpMat<eT> >
|
||||
template<typename eT2, typename T1, typename Functor> inline void init_xform_mt(const SpBase<eT2,T1>& x, const Functor& func);
|
||||
|
||||
//! don't use this unless you're writing internal Armadillo code
|
||||
arma_inline bool is_alias(const SpMat<eT>& X) const;
|
||||
template<typename eT2>
|
||||
arma_inline bool is_alias(const SpMat<eT2>& X) const;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
@@ -3565,7 +3565,7 @@ SpMat<eT>::is_symmetric(const typename get_pod_type<elem_type>::result tol) cons
|
||||
|
||||
if(tol == T(0)) { return (*this).is_symmetric(); }
|
||||
|
||||
arma_conform_check( ((tol >= T(0)) == false), "is_symmetric(): parameter 'tol' must be >= 0" );
|
||||
arma_conform_check( ((tol >= T(0)) == false), "is_symmetric(): parameter 'tol' must be > 0" );
|
||||
|
||||
const SpMat<eT>& A = (*this);
|
||||
|
||||
@@ -3575,8 +3575,12 @@ SpMat<eT>::is_symmetric(const typename get_pod_type<elem_type>::result tol) cons
|
||||
|
||||
if(norm_A == T(0)) { return true; }
|
||||
|
||||
if(arma_isnan(norm_A)) { return false; }
|
||||
|
||||
const T norm_A_Ast = as_scalar( arma::max(sum(abs(A - A.st()), 1), 0) );
|
||||
|
||||
if(arma_isnan(norm_A_Ast)) { return false; }
|
||||
|
||||
return ( (norm_A_Ast / norm_A) <= tol );
|
||||
}
|
||||
|
||||
@@ -3611,7 +3615,7 @@ SpMat<eT>::is_hermitian(const typename get_pod_type<elem_type>::result tol) cons
|
||||
|
||||
if(tol == T(0)) { return (*this).is_hermitian(); }
|
||||
|
||||
arma_conform_check( ((tol >= T(0)) == false), "is_hermitian(): parameter 'tol' must be >= 0" );
|
||||
arma_conform_check( ((tol >= T(0)) == false), "is_hermitian(): parameter 'tol' must be > 0" );
|
||||
|
||||
const SpMat<eT>& A = (*this);
|
||||
|
||||
@@ -3621,8 +3625,12 @@ SpMat<eT>::is_hermitian(const typename get_pod_type<elem_type>::result tol) cons
|
||||
|
||||
if(norm_A == T(0)) { return true; }
|
||||
|
||||
if(arma_isnan(norm_A)) { return false; }
|
||||
|
||||
const T norm_A_At = as_scalar( arma::max(sum(abs(A - A.t()), 1), 0) );
|
||||
|
||||
if(arma_isnan(norm_A_At)) { return false; }
|
||||
|
||||
return ( (norm_A_At / norm_A) <= tol );
|
||||
}
|
||||
|
||||
@@ -6007,11 +6015,14 @@ SpMat<eT>::init_xform_mt(const SpBase<eT2,T1>& A, const Functor& func)
|
||||
|
||||
|
||||
template<typename eT>
|
||||
template<typename eT2>
|
||||
arma_inline
|
||||
bool
|
||||
SpMat<eT>::is_alias(const SpMat<eT>& X) const
|
||||
SpMat<eT>::is_alias(const SpMat<eT2>& X) const
|
||||
{
|
||||
return (&X == this);
|
||||
arma_debug_sigprint();
|
||||
|
||||
return (is_same_type<eT,eT2>::yes) && (void_ptr(this) == void_ptr(&X));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -36,7 +36,8 @@ struct SpOp : public SpBase< typename T1::elem_type, SpOp<T1, op_type> >
|
||||
inline SpOp(const T1& in_m, const uword in_aux_uword_a, const uword in_aux_uword_b);
|
||||
inline ~SpOp();
|
||||
|
||||
arma_inline bool is_alias(const SpMat<elem_type>& X) const;
|
||||
template<typename eT2>
|
||||
arma_inline bool is_alias(const SpMat<eT2>& X) const;
|
||||
|
||||
const T1& m; //!< the operand; must be derived from SpBase
|
||||
elem_type aux; //!< auxiliary data, using the element type as used by T1
|
||||
|
||||
@@ -64,9 +64,10 @@ SpOp<T1, op_type>::~SpOp()
|
||||
|
||||
|
||||
template<typename T1, typename op_type>
|
||||
template<typename eT2>
|
||||
arma_inline
|
||||
bool
|
||||
SpOp<T1, op_type>::is_alias(const SpMat<typename T1::elem_type>& X) const
|
||||
SpOp<T1, op_type>::is_alias(const SpMat<eT2>& X) const
|
||||
{
|
||||
return m.is_alias(X);
|
||||
}
|
||||
|
||||
@@ -321,7 +321,8 @@ class SpSubview : public SpBase< eT, SpSubview<eT> >
|
||||
inline const_row_iterator end_row(const uword row_num) const;
|
||||
|
||||
//! don't use this unless you're writing internal Armadillo code
|
||||
arma_inline bool is_alias(const SpMat<eT>& X) const;
|
||||
template<typename eT2>
|
||||
arma_inline bool is_alias(const SpMat<eT2>& X) const;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
@@ -87,6 +87,8 @@ class SpSubview_col_list : public SpBase< eT, SpSubview_col_list<eT,T1> >
|
||||
inline static void schur_inplace(SpMat<eT>& out, const SpSubview_col_list& in);
|
||||
inline static void div_inplace(SpMat<eT>& out, const SpSubview_col_list& in);
|
||||
|
||||
template<typename eT2>
|
||||
arma_inline bool is_alias(const SpMat<eT2>& X) const;
|
||||
|
||||
friend class SpMat<eT>;
|
||||
};
|
||||
|
||||
@@ -714,4 +714,15 @@ SpSubview_col_list<eT,T1>::div_inplace(SpMat<eT>& out, const SpSubview_col_list&
|
||||
|
||||
|
||||
|
||||
template<typename eT, typename T1>
|
||||
template<typename eT2>
|
||||
arma_inline
|
||||
bool
|
||||
SpSubview_col_list<eT,T1>::is_alias(const SpMat<eT2>& X) const
|
||||
{
|
||||
return m.is_alias(X);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! @}
|
||||
|
||||
@@ -1786,9 +1786,10 @@ SpSubview<eT>::end_row(const uword row_num) const
|
||||
|
||||
|
||||
template<typename eT>
|
||||
template<typename eT2>
|
||||
arma_inline
|
||||
bool
|
||||
SpSubview<eT>::is_alias(const SpMat<eT>& X) const
|
||||
SpSubview<eT>::is_alias(const SpMat<eT2>& X) const
|
||||
{
|
||||
return m.is_alias(X);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
#define ARMA_VERSION_MAJOR 15
|
||||
#define ARMA_VERSION_MINOR 2
|
||||
#define ARMA_VERSION_PATCH 5
|
||||
#define ARMA_VERSION_PATCH 8
|
||||
#define ARMA_VERSION_NAME "Medium Roast Deluxe"
|
||||
|
||||
|
||||
|
||||
@@ -94,7 +94,9 @@ field<oT>::field(const subview_field<oT>& X)
|
||||
{
|
||||
arma_debug_sigprint_this(this);
|
||||
|
||||
(*this).operator=(X);
|
||||
init(X.n_rows, X.n_cols, X.n_slices);
|
||||
|
||||
subview_field<oT>::extract(*this, X);
|
||||
}
|
||||
|
||||
|
||||
@@ -107,7 +109,20 @@ field<oT>::operator=(const subview_field<oT>& X)
|
||||
{
|
||||
arma_debug_sigprint();
|
||||
|
||||
subview_field<oT>::extract(*this, X);
|
||||
const bool alias = (this == &(X.f));
|
||||
|
||||
if(alias == false)
|
||||
{
|
||||
(*this).init(X.n_rows, X.n_cols, X.n_slices);
|
||||
|
||||
subview_field<oT>::extract(*this, X);
|
||||
}
|
||||
else
|
||||
{
|
||||
field<oT> tmp(X);
|
||||
|
||||
(*this).operator=(std::move(tmp));
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ arma_inline
|
||||
bool
|
||||
mtSpOp<out_eT, T1, op_type>::is_alias(const SpMat<eT2>& X) const
|
||||
{
|
||||
return (void_ptr(&X) == void_ptr(&m));
|
||||
return m.is_alias(X);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -50,6 +50,9 @@ struct mtSpReduceOp : public SpBase< out_eT, mtSpReduceOp<out_eT, T1, op_type> >
|
||||
inline mtSpReduceOp(const T1& in_m, const uword in_aux_uword_a, const uword in_aux_uword_b);
|
||||
inline ~mtSpReduceOp();
|
||||
|
||||
template<typename eT2>
|
||||
arma_inline bool is_alias(const SpMat<eT2>& X) const;
|
||||
|
||||
const T1& m; //!< the operand; must be derived from SpBase
|
||||
uword aux_uword_a; //!< auxiliary data, uword format
|
||||
uword aux_uword_b; //!< auxiliary data, uword format
|
||||
|
||||
@@ -52,4 +52,15 @@ mtSpReduceOp<out_eT, T1, op_type>::~mtSpReduceOp()
|
||||
|
||||
|
||||
|
||||
template<typename out_eT, typename T1, typename op_type>
|
||||
template<typename eT2>
|
||||
arma_inline
|
||||
bool
|
||||
mtSpReduceOp<out_eT, T1, op_type>::is_alias(const SpMat<eT2>& X) const
|
||||
{
|
||||
return m.is_alias(X);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! @}
|
||||
|
||||
@@ -87,6 +87,8 @@ op_orth::apply_direct(Mat<typename T1::elem_type>& out, const Base<typename T1::
|
||||
// set tolerance to default if it hasn't been specified
|
||||
if(tol == T(0)) { tol = (std::max)(A.n_rows, A.n_cols) * s_mem[0] * std::numeric_limits<T>::epsilon(); }
|
||||
|
||||
if(arma_isnan(tol)) { return false; }
|
||||
|
||||
uword count = 0;
|
||||
|
||||
for(uword i=0; i < s_n_elem; ++i) { count += (s_mem[i] > tol) ? uword(1) : uword(0); }
|
||||
@@ -174,6 +176,8 @@ op_null::apply_direct(Mat<typename T1::elem_type>& out, const Base<typename T1::
|
||||
// set tolerance to default if it hasn't been specified
|
||||
if(tol == T(0)) { tol = (std::max)(A.n_rows, A.n_cols) * s_mem[0] * std::numeric_limits<T>::epsilon(); }
|
||||
|
||||
if(arma_isnan(tol)) { return false; }
|
||||
|
||||
uword count = 0;
|
||||
|
||||
for(uword i=0; i < s_n_elem; ++i) { count += (s_mem[i] > tol) ? uword(1) : uword(0); }
|
||||
|
||||
@@ -176,6 +176,8 @@ op_pinv::apply_diag(Mat<eT>& out, const Mat<eT>& A, typename get_pod_type<eT>::r
|
||||
|
||||
if(tol == T(0)) { tol = (std::max)(A.n_rows, A.n_cols) * max_abs_Aii * std::numeric_limits<T>::epsilon(); }
|
||||
|
||||
if(arma_isnan(tol)) { return false; }
|
||||
|
||||
for(uword i=0; i<N; ++i)
|
||||
{
|
||||
if(diag_abs_vals[i] >= tol)
|
||||
@@ -236,6 +238,8 @@ op_pinv::apply_sym(Mat<eT>& out, const Mat<eT>& A, typename get_pod_type<eT>::re
|
||||
// set tolerance to default if it hasn't been specified
|
||||
if(tol == T(0)) { tol = (std::max)(A.n_rows, A.n_cols) * abs_eigval[0] * std::numeric_limits<T>::epsilon(); }
|
||||
|
||||
if(arma_isnan(tol)) { return false; }
|
||||
|
||||
uword count = 0;
|
||||
|
||||
for(uword i=0; i < abs_eigval.n_elem; ++i) { count += (abs_eigval[i] >= tol) ? uword(1) : uword(0); }
|
||||
@@ -310,6 +314,8 @@ op_pinv::apply_gen(Mat<eT>& out, Mat<eT>& A, typename get_pod_type<eT>::result t
|
||||
// set tolerance to default if it hasn't been specified
|
||||
if( (tol == T(0)) && (s.n_elem > 0) ) { tol = (std::max)(n_rows, n_cols) * s[0] * std::numeric_limits<T>::epsilon(); }
|
||||
|
||||
if(arma_isnan(tol)) { return false; }
|
||||
|
||||
uword count = 0;
|
||||
|
||||
for(uword i=0; i < s.n_elem; ++i) { count += (s[i] >= tol) ? uword(1) : uword(0); }
|
||||
|
||||
@@ -87,6 +87,8 @@ op_rank::apply_diag(uword& out, Mat<eT>& A, typename get_pod_type<eT>::result to
|
||||
|
||||
typedef typename get_pod_type<eT>::result T;
|
||||
|
||||
out = uword(0);
|
||||
|
||||
const uword N = (std::min)(A.n_rows, A.n_cols);
|
||||
|
||||
podarray<T> diag_abs_vals(N);
|
||||
@@ -98,7 +100,7 @@ op_rank::apply_diag(uword& out, Mat<eT>& A, typename get_pod_type<eT>::result to
|
||||
const eT Aii = A.at(i,i);
|
||||
const T abs_Aii = std::abs(Aii);
|
||||
|
||||
if(arma_isnan(Aii)) { out = uword(0); return false; }
|
||||
if(arma_isnan(Aii)) { return false; }
|
||||
|
||||
diag_abs_vals[i] = abs_Aii;
|
||||
|
||||
@@ -108,6 +110,8 @@ op_rank::apply_diag(uword& out, Mat<eT>& A, typename get_pod_type<eT>::result to
|
||||
// set tolerance to default if it hasn't been specified
|
||||
if(tol == T(0)) { tol = (std::max)(A.n_rows, A.n_cols) * max_abs_Aii * std::numeric_limits<T>::epsilon(); }
|
||||
|
||||
if(arma_isnan(tol)) { return false; }
|
||||
|
||||
uword count = 0;
|
||||
|
||||
for(uword i=0; i<N; ++i) { count += (diag_abs_vals[i] > tol) ? uword(1) : uword(0); }
|
||||
@@ -128,18 +132,20 @@ op_rank::apply_sym(uword& out, Mat<eT>& A, typename get_pod_type<eT>::result tol
|
||||
|
||||
typedef typename get_pod_type<eT>::result T;
|
||||
|
||||
if(A.is_square() == false) { out = uword(0); return false; }
|
||||
out = uword(0);
|
||||
|
||||
if(A.is_square() == false) { return false; }
|
||||
|
||||
Col<T> v;
|
||||
|
||||
const bool status = auxlib::eig_sym(v, A);
|
||||
|
||||
if(status == false) { out = uword(0); return false; }
|
||||
if(status == false) { return false; }
|
||||
|
||||
const uword v_n_elem = v.n_elem;
|
||||
T* v_mem = v.memptr();
|
||||
|
||||
if(v_n_elem == 0) { out = uword(0); return true; }
|
||||
if(v_n_elem == 0) { return true; }
|
||||
|
||||
T max_abs_v = T(0);
|
||||
|
||||
@@ -148,6 +154,8 @@ op_rank::apply_sym(uword& out, Mat<eT>& A, typename get_pod_type<eT>::result tol
|
||||
// set tolerance to default if it hasn't been specified
|
||||
if(tol == T(0)) { tol = (std::max)(A.n_rows, A.n_cols) * max_abs_v * std::numeric_limits<T>::epsilon(); }
|
||||
|
||||
if(arma_isnan(tol)) { return false; }
|
||||
|
||||
uword count = 0;
|
||||
|
||||
for(uword i=0; i < v_n_elem; ++i) { count += (v_mem[i] > tol) ? uword(1) : uword(0); }
|
||||
@@ -168,20 +176,24 @@ op_rank::apply_gen(uword& out, Mat<eT>& A, typename get_pod_type<eT>::result tol
|
||||
|
||||
typedef typename get_pod_type<eT>::result T;
|
||||
|
||||
out = uword(0);
|
||||
|
||||
Col<T> s;
|
||||
|
||||
const bool status = auxlib::svd_dc(s, A);
|
||||
|
||||
if(status == false) { out = uword(0); return false; }
|
||||
if(status == false) { return false; }
|
||||
|
||||
const uword s_n_elem = s.n_elem;
|
||||
const T* s_mem = s.memptr();
|
||||
|
||||
if(s_n_elem == 0) { out = uword(0); return true; }
|
||||
if(s_n_elem == 0) { return true; }
|
||||
|
||||
// set tolerance to default if it hasn't been specified
|
||||
if(tol == T(0)) { tol = (std::max)(A.n_rows, A.n_cols) * s_mem[0] * std::numeric_limits<T>::epsilon(); }
|
||||
|
||||
if(arma_isnan(tol)) { return false; }
|
||||
|
||||
uword count = 0;
|
||||
|
||||
for(uword i=0; i < s_n_elem; ++i) { count += (s_mem[i] > tol) ? uword(1) : uword(0); }
|
||||
|
||||
@@ -214,6 +214,8 @@ sp_auxlib::eigs_sym_newarp(Col<eT>& eigval, Mat<eT>& eigvec, const SpMat<eT>& X,
|
||||
if(ncv < (n_eigvals + 1)) { ncv = (n_eigvals + 1); }
|
||||
if(ncv > n ) { ncv = n; }
|
||||
|
||||
if(arma_isnan(opts.tol)) { return false; }
|
||||
|
||||
eT tol = (std::max)(eT(opts.tol), std::numeric_limits<eT>::epsilon());
|
||||
|
||||
uword maxiter = uword(opts.maxiter);
|
||||
@@ -347,6 +349,8 @@ sp_auxlib::eigs_sym_newarp(Col<eT>& eigval, Mat<eT>& eigvec, const SpMat<eT>& X,
|
||||
if(ncv < (n_eigvals + 1)) { ncv = (n_eigvals + 1); }
|
||||
if(ncv > n ) { ncv = n; }
|
||||
|
||||
if(arma_isnan(opts.tol)) { return false; }
|
||||
|
||||
eT tol = (std::max)(eT(opts.tol), std::numeric_limits<eT>::epsilon());
|
||||
|
||||
uword maxiter = uword(opts.maxiter);
|
||||
@@ -667,6 +671,8 @@ sp_auxlib::eigs_gen_newarp(Col< std::complex<T> >& eigval, Mat< std::complex<T>
|
||||
if(ncv < (n_eigvals + 3)) { ncv = (n_eigvals + 3); }
|
||||
if(ncv > n ) { ncv = n; }
|
||||
|
||||
if(arma_isnan(opts.tol)) { return false; }
|
||||
|
||||
T tol = (std::max)(T(opts.tol), std::numeric_limits<T>::epsilon());
|
||||
|
||||
uword maxiter = uword(opts.maxiter);
|
||||
|
||||
@@ -105,6 +105,9 @@ class spdiagview : public SpBase< eT, spdiagview<eT> >
|
||||
inline static void extract(SpMat<eT>& out, const spdiagview& in);
|
||||
inline static void extract( Mat<eT>& out, const spdiagview& in);
|
||||
|
||||
template<typename eT2>
|
||||
arma_inline bool is_alias(const SpMat<eT2>& X) const;
|
||||
|
||||
|
||||
friend class SpMat<eT>;
|
||||
};
|
||||
|
||||
@@ -1076,4 +1076,15 @@ spdiagview<eT>::randn()
|
||||
|
||||
|
||||
|
||||
template<typename eT>
|
||||
template<typename eT2>
|
||||
arma_inline
|
||||
bool
|
||||
spdiagview<eT>::is_alias(const SpMat<eT2>& X) const
|
||||
{
|
||||
return m.is_alias(X);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! @}
|
||||
|
||||
@@ -90,6 +90,8 @@ class subview_elem1 : public Base< eT, subview_elem1<eT,T1> >
|
||||
template<typename T2> inline void operator%= (const Base<eT,T2>& x);
|
||||
template<typename T2> inline void operator/= (const Base<eT,T2>& x);
|
||||
|
||||
inline static void extract_noalias(Mat<eT>& out, const subview_elem1& in);
|
||||
|
||||
inline static void extract(Mat<eT>& out, const subview_elem1& in);
|
||||
|
||||
template<typename op_type> inline static void mat_inplace_op(Mat<eT>& out, const subview_elem1& in);
|
||||
|
||||
@@ -759,6 +759,55 @@ subview_elem1<eT,T1>::operator/= (const Base<eT,T2>& x)
|
||||
|
||||
|
||||
|
||||
template<typename eT, typename T1>
|
||||
inline
|
||||
void
|
||||
subview_elem1<eT,T1>::extract_noalias(Mat<eT>& out, const subview_elem1<eT,T1>& in)
|
||||
{
|
||||
arma_debug_sigprint();
|
||||
|
||||
const quasi_unwrap<T1> tmp1(in.a.get_ref());
|
||||
const umat& aa = tmp1.M;
|
||||
|
||||
if(resolves_to_vector<T1>::no)
|
||||
{
|
||||
arma_conform_check( ( (aa.is_vec() == false) && (aa.is_empty() == false) ), "Mat::elem(): given object must be a vector" );
|
||||
}
|
||||
|
||||
const uword* aa_mem = aa.memptr();
|
||||
const uword aa_n_elem = aa.n_elem;
|
||||
|
||||
const eT* m_mem = in.m.memptr();
|
||||
const uword m_n_elem = in.m.n_elem;
|
||||
|
||||
out.set_size(aa_n_elem, 1);
|
||||
|
||||
eT* out_mem = out.memptr();
|
||||
|
||||
uword i,j;
|
||||
for(i=0, j=1; j<aa_n_elem; i+=2, j+=2)
|
||||
{
|
||||
const uword ii = aa_mem[i];
|
||||
const uword jj = aa_mem[j];
|
||||
|
||||
arma_conform_check_bounds( ( (ii >= m_n_elem) || (jj >= m_n_elem) ), "Mat::elem(): index out of bounds" );
|
||||
|
||||
out_mem[i] = m_mem[ii];
|
||||
out_mem[j] = m_mem[jj];
|
||||
}
|
||||
|
||||
if(i < aa_n_elem)
|
||||
{
|
||||
const uword ii = aa_mem[i];
|
||||
|
||||
arma_conform_check_bounds( (ii >= m_n_elem) , "Mat::elem(): index out of bounds" );
|
||||
|
||||
out_mem[i] = m_mem[ii];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename eT, typename T1>
|
||||
inline
|
||||
void
|
||||
@@ -777,12 +826,12 @@ subview_elem1<eT,T1>::extract(Mat<eT>& actual_out, const subview_elem1<eT,T1>& i
|
||||
const uword* aa_mem = aa.memptr();
|
||||
const uword aa_n_elem = aa.n_elem;
|
||||
|
||||
const Mat<eT>& m_local = in.m;
|
||||
const Mat<eT>& m = in.m;
|
||||
|
||||
const eT* m_mem = m_local.memptr();
|
||||
const uword m_n_elem = m_local.n_elem;
|
||||
const eT* m_mem = m.memptr();
|
||||
const uword m_n_elem = m.n_elem;
|
||||
|
||||
const bool alias = (&actual_out == &m_local);
|
||||
const bool alias = (&actual_out == &m);
|
||||
|
||||
if(alias) { arma_debug_print("subview_elem1::extract(): aliasing detected"); }
|
||||
|
||||
|
||||
@@ -98,6 +98,8 @@ class subview_elem2 : public Base< eT, subview_elem2<eT,T1,T2> >
|
||||
template<typename expr> inline void operator%= (const SpBase<eT,expr>& x);
|
||||
template<typename expr> inline void operator/= (const SpBase<eT,expr>& x);
|
||||
|
||||
inline static void extract_noalias(Mat<eT>& out, const subview_elem2& in);
|
||||
|
||||
inline static void extract(Mat<eT>& out, const subview_elem2& in);
|
||||
|
||||
inline static void plus_inplace(Mat<eT>& out, const subview_elem2& in);
|
||||
|
||||
@@ -917,6 +917,121 @@ subview_elem2<eT,T1,T2>::operator/= (const SpBase<eT,expr>& x)
|
||||
|
||||
|
||||
|
||||
template<typename eT, typename T1, typename T2>
|
||||
inline
|
||||
void
|
||||
subview_elem2<eT,T1,T2>::extract_noalias(Mat<eT>& out, const subview_elem2<eT,T1,T2>& in)
|
||||
{
|
||||
arma_debug_sigprint();
|
||||
|
||||
const Mat<eT>& m = in.m;
|
||||
|
||||
const uword m_n_rows = m.n_rows;
|
||||
const uword m_n_cols = m.n_cols;
|
||||
|
||||
if( (in.all_rows == false) && (in.all_cols == false) )
|
||||
{
|
||||
const quasi_unwrap<T1> tmp1(in.base_ri.get_ref());
|
||||
const quasi_unwrap<T2> tmp2(in.base_ci.get_ref());
|
||||
|
||||
const umat& ri = tmp1.M;
|
||||
const umat& ci = tmp2.M;
|
||||
|
||||
arma_conform_check
|
||||
(
|
||||
( ((ri.is_vec() == false) && (ri.is_empty() == false)) || ((ci.is_vec() == false) && (ci.is_empty() == false)) ),
|
||||
"Mat::elem(): given object must be a vector"
|
||||
);
|
||||
|
||||
const uword* ri_mem = ri.memptr();
|
||||
const uword ri_n_elem = ri.n_elem;
|
||||
|
||||
const uword* ci_mem = ci.memptr();
|
||||
const uword ci_n_elem = ci.n_elem;
|
||||
|
||||
out.set_size(ri_n_elem, ci_n_elem);
|
||||
|
||||
eT* out_mem = out.memptr();
|
||||
uword out_count = 0;
|
||||
|
||||
for(uword ci_count=0; ci_count < ci_n_elem; ++ci_count)
|
||||
{
|
||||
const uword col = ci_mem[ci_count];
|
||||
|
||||
arma_conform_check_bounds( (col >= m_n_cols), "Mat::elem(): index out of bounds" );
|
||||
|
||||
for(uword ri_count=0; ri_count < ri_n_elem; ++ri_count)
|
||||
{
|
||||
const uword row = ri_mem[ri_count];
|
||||
|
||||
arma_conform_check_bounds( (row >= m_n_rows), "Mat::elem(): index out of bounds" );
|
||||
|
||||
out_mem[out_count] = m.at(row,col);
|
||||
++out_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if( (in.all_rows == true) && (in.all_cols == false) )
|
||||
{
|
||||
const quasi_unwrap<T2> tmp2(in.base_ci.get_ref());
|
||||
|
||||
const umat& ci = tmp2.M;
|
||||
|
||||
arma_conform_check
|
||||
(
|
||||
( (ci.is_vec() == false) && (ci.is_empty() == false) ),
|
||||
"Mat::elem(): given object must be a vector"
|
||||
);
|
||||
|
||||
const uword* ci_mem = ci.memptr();
|
||||
const uword ci_n_elem = ci.n_elem;
|
||||
|
||||
out.set_size(m_n_rows, ci_n_elem);
|
||||
|
||||
for(uword ci_count=0; ci_count < ci_n_elem; ++ci_count)
|
||||
{
|
||||
const uword col = ci_mem[ci_count];
|
||||
|
||||
arma_conform_check_bounds( (col >= m_n_cols), "Mat::elem(): index out of bounds" );
|
||||
|
||||
arrayops::copy( out.colptr(ci_count), m.colptr(col), m_n_rows );
|
||||
}
|
||||
}
|
||||
else
|
||||
if( (in.all_rows == false) && (in.all_cols == true) )
|
||||
{
|
||||
const quasi_unwrap<T1> tmp1(in.base_ri.get_ref());
|
||||
|
||||
const umat& ri = tmp1.M;
|
||||
|
||||
arma_conform_check
|
||||
(
|
||||
( (ri.is_vec() == false) && (ri.is_empty() == false) ),
|
||||
"Mat::elem(): given object must be a vector"
|
||||
);
|
||||
|
||||
const uword* ri_mem = ri.memptr();
|
||||
const uword ri_n_elem = ri.n_elem;
|
||||
|
||||
out.set_size(ri_n_elem, m_n_cols);
|
||||
|
||||
for(uword col=0; col < m_n_cols; ++col)
|
||||
{
|
||||
for(uword ri_count=0; ri_count < ri_n_elem; ++ri_count)
|
||||
{
|
||||
const uword row = ri_mem[ri_count];
|
||||
|
||||
arma_conform_check_bounds( (row >= m_n_rows), "Mat::elem(): index out of bounds" );
|
||||
|
||||
out.at(ri_count,col) = m.at(row,col);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename eT, typename T1, typename T2>
|
||||
inline
|
||||
void
|
||||
@@ -924,12 +1039,12 @@ subview_elem2<eT,T1,T2>::extract(Mat<eT>& actual_out, const subview_elem2<eT,T1,
|
||||
{
|
||||
arma_debug_sigprint();
|
||||
|
||||
Mat<eT>& m_local = const_cast< Mat<eT>& >(in.m);
|
||||
const Mat<eT>& m = in.m;
|
||||
|
||||
const uword m_n_rows = m_local.n_rows;
|
||||
const uword m_n_cols = m_local.n_cols;
|
||||
const uword m_n_rows = m.n_rows;
|
||||
const uword m_n_cols = m.n_cols;
|
||||
|
||||
const bool alias = (&actual_out == &m_local);
|
||||
const bool alias = (&actual_out == &m);
|
||||
|
||||
if(alias) { arma_debug_print("subview_elem2::extract(): aliasing detected"); }
|
||||
|
||||
@@ -973,7 +1088,7 @@ subview_elem2<eT,T1,T2>::extract(Mat<eT>& actual_out, const subview_elem2<eT,T1,
|
||||
|
||||
arma_conform_check_bounds( (row >= m_n_rows), "Mat::elem(): index out of bounds" );
|
||||
|
||||
out_mem[out_count] = m_local.at(row,col);
|
||||
out_mem[out_count] = m.at(row,col);
|
||||
++out_count;
|
||||
}
|
||||
}
|
||||
@@ -981,7 +1096,7 @@ subview_elem2<eT,T1,T2>::extract(Mat<eT>& actual_out, const subview_elem2<eT,T1,
|
||||
else
|
||||
if( (in.all_rows == true) && (in.all_cols == false) )
|
||||
{
|
||||
const unwrap_check_mixed<T2> tmp2(in.base_ci.get_ref(), m_local);
|
||||
const unwrap_check_mixed<T2> tmp2(in.base_ci.get_ref(), m);
|
||||
|
||||
const umat& ci = tmp2.M;
|
||||
|
||||
@@ -1002,13 +1117,13 @@ subview_elem2<eT,T1,T2>::extract(Mat<eT>& actual_out, const subview_elem2<eT,T1,
|
||||
|
||||
arma_conform_check_bounds( (col >= m_n_cols), "Mat::elem(): index out of bounds" );
|
||||
|
||||
arrayops::copy( out.colptr(ci_count), m_local.colptr(col), m_n_rows );
|
||||
arrayops::copy( out.colptr(ci_count), m.colptr(col), m_n_rows );
|
||||
}
|
||||
}
|
||||
else
|
||||
if( (in.all_rows == false) && (in.all_cols == true) )
|
||||
{
|
||||
const unwrap_check_mixed<T1> tmp1(in.base_ri.get_ref(), m_local);
|
||||
const unwrap_check_mixed<T1> tmp1(in.base_ri.get_ref(), m);
|
||||
|
||||
const umat& ri = tmp1.M;
|
||||
|
||||
@@ -1031,7 +1146,7 @@ subview_elem2<eT,T1,T2>::extract(Mat<eT>& actual_out, const subview_elem2<eT,T1,
|
||||
|
||||
arma_conform_check_bounds( (row >= m_n_rows), "Mat::elem(): index out of bounds" );
|
||||
|
||||
out.at(ri_count,col) = m_local.at(row,col);
|
||||
out.at(ri_count,col) = m.at(row,col);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -507,24 +507,17 @@ subview_field<oT>::fill(const oT& x)
|
||||
template<typename oT>
|
||||
inline
|
||||
void
|
||||
subview_field<oT>::extract(field<oT>& actual_out, const subview_field<oT>& in)
|
||||
subview_field<oT>::extract(field<oT>& out, const subview_field<oT>& in)
|
||||
{
|
||||
arma_debug_sigprint();
|
||||
|
||||
//
|
||||
const bool alias = (&actual_out == &in.f);
|
||||
|
||||
field<oT>* tmp = (alias) ? new field<oT> : nullptr;
|
||||
field<oT>& out = (alias) ? (*tmp) : actual_out;
|
||||
|
||||
//
|
||||
// NOTE: we're assuming that the field has already been set to the correct size and there is no aliasing;
|
||||
// size setting and alias checking is done by either the field constructor or operator=()
|
||||
|
||||
const uword n_rows = in.n_rows;
|
||||
const uword n_cols = in.n_cols;
|
||||
const uword n_slices = in.n_slices;
|
||||
|
||||
out.set_size(n_rows, n_cols, n_slices);
|
||||
|
||||
arma_debug_print(arma_str::format("out.n_rows: %u; out.n_cols: %u; out.n_slices: %u; in.f.n_rows: %u; in.f.n_cols: %u; in.f.n_slices: %u") % out.n_rows % out.n_cols % out.n_slices % in.f.n_rows % in.f.n_cols % in.f.n_slices);
|
||||
|
||||
if(n_slices == 1)
|
||||
@@ -544,12 +537,6 @@ subview_field<oT>::extract(field<oT>& actual_out, const subview_field<oT>& in)
|
||||
out.at(row,col,slice) = in.at(row,col,slice);
|
||||
}
|
||||
}
|
||||
|
||||
if(alias)
|
||||
{
|
||||
actual_out = out;
|
||||
delete tmp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4812,7 +4812,6 @@ subview_row<eT>::is_zero(const typename get_pod_type<eT>::result tol) const
|
||||
const T val_real = access::tmp_real(val);
|
||||
const T val_imag = access::tmp_imag(val);
|
||||
|
||||
// convoluted formulation to handle NaNs
|
||||
if( (eop_aux::arma_abs(val_real) <= tol) == false ) { return false; }
|
||||
if( (eop_aux::arma_abs(val_imag) <= tol) == false ) { return false; }
|
||||
}
|
||||
@@ -4835,7 +4834,6 @@ subview_row<eT>::is_zero(const typename get_pod_type<eT>::result tol) const
|
||||
{
|
||||
const eT val = (*mem_ptr); mem_ptr += local_m_n_rows;
|
||||
|
||||
// convoluted formulation to handle NaNs
|
||||
if( (eop_aux::arma_abs(val) <= tol) == false ) { return false; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,9 @@ struct unwrap_default
|
||||
}
|
||||
|
||||
const Mat<eT> M;
|
||||
|
||||
template<typename eT2>
|
||||
constexpr bool is_alias(const Mat<eT2>&) const { return false; }
|
||||
};
|
||||
|
||||
|
||||
@@ -55,6 +58,9 @@ struct unwrap_fixed
|
||||
}
|
||||
|
||||
const T1& M;
|
||||
|
||||
template<typename eT2>
|
||||
arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&M) == void_ptr(&X)); }
|
||||
};
|
||||
|
||||
|
||||
@@ -94,6 +100,9 @@ struct unwrap< Mat<eT> >
|
||||
}
|
||||
|
||||
const Mat<eT>& M;
|
||||
|
||||
template<typename eT2>
|
||||
arma_inline bool is_alias(const Mat<eT2>& X) const { return (is_same_type<eT,eT2>::yes) && (void_ptr(&M) == void_ptr(&X)); }
|
||||
};
|
||||
|
||||
|
||||
@@ -111,6 +120,9 @@ struct unwrap< Row<eT> >
|
||||
}
|
||||
|
||||
const Row<eT>& M;
|
||||
|
||||
template<typename eT2>
|
||||
arma_inline bool is_alias(const Mat<eT2>& X) const { return (is_same_type<eT,eT2>::yes) && (void_ptr(&M) == void_ptr(&X)); }
|
||||
};
|
||||
|
||||
|
||||
@@ -128,6 +140,9 @@ struct unwrap< Col<eT> >
|
||||
}
|
||||
|
||||
const Col<eT>& M;
|
||||
|
||||
template<typename eT2>
|
||||
arma_inline bool is_alias(const Mat<eT2>& X) const { return (is_same_type<eT,eT2>::yes) && (void_ptr(&M) == void_ptr(&X)); }
|
||||
};
|
||||
|
||||
|
||||
@@ -145,6 +160,9 @@ struct unwrap< subview_col<eT> >
|
||||
}
|
||||
|
||||
const Col<eT> M;
|
||||
|
||||
template<typename eT2>
|
||||
constexpr bool is_alias(const Mat<eT2>&) const { return false; }
|
||||
};
|
||||
|
||||
|
||||
@@ -162,6 +180,9 @@ struct unwrap< subview_cols<eT> >
|
||||
}
|
||||
|
||||
const Mat<eT> M;
|
||||
|
||||
template<typename eT2>
|
||||
constexpr bool is_alias(const Mat<eT2>&) const { return false; }
|
||||
};
|
||||
|
||||
|
||||
@@ -179,6 +200,9 @@ struct unwrap< mtGlue<out_eT, T1, T2, glue_type> >
|
||||
}
|
||||
|
||||
const Mat<out_eT> M;
|
||||
|
||||
template<typename eT2>
|
||||
constexpr bool is_alias(const Mat<eT2>&) const { return false; }
|
||||
};
|
||||
|
||||
|
||||
@@ -196,6 +220,9 @@ struct unwrap< mtOp<out_eT, T1, op_type> >
|
||||
}
|
||||
|
||||
const Mat<out_eT> M;
|
||||
|
||||
template<typename eT2>
|
||||
constexpr bool is_alias(const Mat<eT2>&) const { return false; }
|
||||
};
|
||||
|
||||
|
||||
@@ -311,7 +338,6 @@ struct quasi_unwrap< Mat<eT> >
|
||||
template<typename eT>
|
||||
struct quasi_unwrap< Row<eT> >
|
||||
{
|
||||
|
||||
inline
|
||||
quasi_unwrap(const Row<eT>& A)
|
||||
: M(A)
|
||||
|
||||
Reference in New Issue
Block a user