expanded pow() to handle subview_each1

This commit is contained in:
conrad
2022-09-15 11:34:34 +10:00
parent c6f29dc15c
commit b05f4ca6bc
5 changed files with 178 additions and 9 deletions
+35 -4
View File
@@ -65,11 +65,42 @@ pow
// TODO: mat = pow(mat.each_col(), mat) (no promotion)
// TODO: mat = pow(mat.each_row(), mat) (no promotion)
template<typename parent, unsigned int mode, typename T2>
arma_warn_unused
inline
Mat<typename parent::elem_type>
pow
(
const subview_each1<parent,mode>& X,
const Base<typename parent::elem_type,T2>& Y
)
{
arma_extra_debug_sigprint();
return glue_powext::apply(X,Y);
}
// TODO: cx_mat = pow(cx_mat.each_col(), mat) (promotion)
// TODO: cx_mat = pow(cx_mat.each_row(), mat) (promotion)
template<typename parent, unsigned int mode, typename T2>
arma_warn_unused
inline
typename
enable_if2
<
( is_cx<typename parent::elem_type>::yes && is_same_type<typename parent::pod_type, typename T2::elem_type>::yes ),
Mat<typename parent::elem_type>
>::result
pow
(
const subview_each1<parent,mode>& X,
const Base<typename T2::elem_type,T2>& Y
)
{
arma_extra_debug_sigprint();
return glue_powext_cx::apply(X,Y);
}
@@ -31,6 +31,9 @@ class glue_powext
template<typename T1, typename T2> inline static void apply(Mat<typename T1::elem_type>& out, const Glue<T1,T2,glue_powext>& X);
template<typename eT> inline static void apply(Mat<eT>& out, const Mat<eT>& A, const Mat<eT>& B);
template<typename parent, unsigned int mode, typename T2> inline static Mat<typename parent::elem_type> apply(const subview_each1<parent,mode>& X, const Base<typename parent::elem_type,T2>& Y);
};
@@ -43,6 +46,8 @@ class glue_powext_cx
template<typename T1, typename T2> inline static void apply(Mat<typename T1::elem_type>& out, const mtGlue<typename T1::elem_type,T1,T2,glue_powext_cx>& X);
template<typename T> inline static void apply(Mat< std::complex<T> >& out, const Mat< std::complex<T> >& A, const Mat<T>& B);
template<typename parent, unsigned int mode, typename T2> inline static Mat<typename parent::elem_type> apply(const subview_each1<parent,mode>& X, const Base<typename T2::elem_type,T2>& Y);
};
+129
View File
@@ -83,6 +83,70 @@ glue_powext::apply(Mat<eT>& out, const Mat<eT>& A, const Mat<eT>& B)
template<typename parent, unsigned int mode, typename T2>
inline
Mat<typename parent::elem_type>
glue_powext::apply
(
const subview_each1<parent,mode>& X,
const Base<typename parent::elem_type,T2>& Y
)
{
arma_extra_debug_sigprint();
typedef typename parent::elem_type eT;
const parent& A = X.P;
const uword A_n_rows = A.n_rows;
const uword A_n_cols = A.n_cols;
Mat<eT> out(A_n_rows, A_n_cols, arma_nozeros_indicator());
const quasi_unwrap<T2> tmp(Y.get_ref());
const Mat<eT>& B = tmp.M;
X.check_size(B);
// TODO: investigate use of openmp
const eT* B_mem = B.memptr();
if(mode == 0) // each column
{
for(uword i=0; i < A_n_cols; ++i)
{
const eT* A_mem = A.colptr(i);
eT* out_mem = out.colptr(i);
for(uword row=0; row < A_n_rows; ++row)
{
out_mem[row] = eop_aux::pow(A_mem[row], B_mem[row]);
}
}
}
if(mode == 1) // each row
{
for(uword i=0; i < A_n_cols; ++i)
{
const eT* A_mem = A.colptr(i);
eT* out_mem = out.colptr(i);
const eT B_val = B_mem[i];
for(uword row=0; row < A_n_rows; ++row)
{
out_mem[row] = eop_aux::pow(A_mem[row], B_val);
}
}
}
return out;
}
//
@@ -148,4 +212,69 @@ glue_powext_cx::apply(Mat< std::complex<T> >& out, const Mat< std::complex<T> >&
template<typename parent, unsigned int mode, typename T2>
inline
Mat<typename parent::elem_type>
glue_powext_cx::apply
(
const subview_each1<parent,mode>& X,
const Base<typename T2::elem_type,T2>& Y
)
{
arma_extra_debug_sigprint();
typedef typename parent::elem_type eT;
typedef typename parent::pod_type T;
const parent& A = X.P;
const uword A_n_rows = A.n_rows;
const uword A_n_cols = A.n_cols;
Mat<eT> out(A_n_rows, A_n_cols, arma_nozeros_indicator());
const quasi_unwrap<T2> tmp(Y.get_ref());
const Mat<T>& B = tmp.M;
X.check_size(B);
// TODO: investigate use of openmp
const T* B_mem = B.memptr();
if(mode == 0) // each column
{
for(uword i=0; i < A_n_cols; ++i)
{
const eT* A_mem = A.colptr(i);
eT* out_mem = out.colptr(i);
for(uword row=0; row < A_n_rows; ++row)
{
out_mem[row] = std::pow(A_mem[row], B_mem[row]);
}
}
}
if(mode == 1) // each row
{
for(uword i=0; i < A_n_cols; ++i)
{
const eT* A_mem = A.colptr(i);
eT* out_mem = out.colptr(i);
const eT B_val = B_mem[i];
for(uword row=0; row < A_n_rows; ++row)
{
out_mem[row] = std::pow(A_mem[row], B_val);
}
}
}
return out;
}
//! @}
@@ -30,7 +30,8 @@ class subview_each_common
const parent& P;
inline void check_size(const Mat<typename parent::elem_type>& A) const;
template<typename eT2>
inline void check_size(const Mat<eT2>& A) const;
protected:
@@ -43,7 +44,8 @@ class subview_each_common
arma_inline const Mat<typename parent::elem_type>& get_mat_ref() const;
arma_cold inline const std::string incompat_size_string(const Mat<typename parent::elem_type>& A) const;
template<typename eT2>
arma_cold inline const std::string incompat_size_string(const Mat<eT2>& A) const;
};
+5 -3
View File
@@ -65,11 +65,12 @@ subview_each_common<parent,mode>::get_mat_ref() const
template<typename parent, unsigned int mode>
template<typename eT2>
inline
void
subview_each_common<parent,mode>::check_size(const Mat<typename parent::elem_type>& A) const
subview_each_common<parent,mode>::check_size(const Mat<eT2>& A) const
{
if(arma_config::debug == true)
if(arma_config::debug)
{
if(mode == 0)
{
@@ -91,10 +92,11 @@ subview_each_common<parent,mode>::check_size(const Mat<typename parent::elem_typ
template<typename parent, unsigned int mode>
template<typename eT2>
arma_cold
inline
const std::string
subview_each_common<parent,mode>::incompat_size_string(const Mat<typename parent::elem_type>& A) const
subview_each_common<parent,mode>::incompat_size_string(const Mat<eT2>& A) const
{
std::ostringstream tmp;