AnalysisSystemForRadionucli.../include/armadillo_bits/fn_accu.hpp

448 lines
8.4 KiB
C++
Raw Normal View History

2024-06-04 15:25:02 +08:00
// Copyright (C) 2008-2015 National ICT Australia (NICTA)
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// -------------------------------------------------------------------
//
// Written by Conrad Sanderson - http://conradsanderson.id.au
// Written by Ryan Curtin
//! \addtogroup fn_accu
//! @{
template<typename T1>
arma_hot
inline
typename T1::elem_type
accu_proxy_linear(const Proxy<T1>& P)
{
typedef typename T1::elem_type eT;
const uword n_elem = P.get_n_elem();
#if defined(__FINITE_MATH_ONLY__) && (__FINITE_MATH_ONLY__ > 0)
{
eT val = eT(0);
if(P.is_aligned())
{
typename Proxy<T1>::aligned_ea_type A = P.get_aligned_ea();
for(uword i=0; i<n_elem; ++i) { val += A.at_alt(i); }
}
else
{
typename Proxy<T1>::ea_type A = P.get_ea();
for(uword i=0; i<n_elem; ++i) { val += A[i]; }
}
return val;
}
#else
{
eT val1 = eT(0);
eT val2 = eT(0);
typename Proxy<T1>::ea_type A = P.get_ea();
uword i,j;
for(i=0, j=1; j < n_elem; i+=2, j+=2)
{
val1 += A[i];
val2 += A[j];
}
if(i < n_elem)
{
val1 += A[i]; // equivalent to: val1 += A[n_elem-1];
}
return (val1 + val2);
}
#endif
}
template<typename T1>
arma_hot
inline
typename T1::elem_type
accu_proxy_mat(const Proxy<T1>& P)
{
const quasi_unwrap<typename Proxy<T1>::stored_type> tmp(P.Q);
return arrayops::accumulate(tmp.M.memptr(), tmp.M.n_elem);
}
template<typename T1>
arma_hot
inline
typename T1::elem_type
accu_proxy_at(const Proxy<T1>& P)
{
typedef typename T1::elem_type eT;
const uword n_rows = P.get_n_rows();
const uword n_cols = P.get_n_cols();
eT val = eT(0);
if(n_rows != 1)
{
eT val1 = eT(0);
eT val2 = eT(0);
for(uword col=0; col < n_cols; ++col)
{
uword i,j;
for(i=0, j=1; j < n_rows; i+=2, j+=2)
{
val1 += P.at(i,col);
val2 += P.at(j,col);
}
if(i < n_rows)
{
val1 += P.at(i,col);
}
}
val = val1 + val2;
}
else
{
for(uword col=0; col < n_cols; ++col)
{
val += P.at(0,col);
}
}
return val;
}
//! accumulate the elements of a matrix
template<typename T1>
arma_hot
inline
typename enable_if2< is_arma_type<T1>::value, typename T1::elem_type >::result
accu(const T1& X)
{
arma_extra_debug_sigprint();
const Proxy<T1> P(X);
const bool have_direct_mem = (is_Mat<typename Proxy<T1>::stored_type>::value) || (is_subview_col<typename Proxy<T1>::stored_type>::value);
return (Proxy<T1>::prefer_at_accessor) ? accu_proxy_at(P) : (have_direct_mem ? accu_proxy_mat(P) : accu_proxy_linear(P));
}
//! explicit handling of Hamming norm (also known as zero norm)
template<typename T1>
inline
arma_warn_unused
uword
accu(const mtOp<uword,T1,op_rel_noteq>& X)
{
arma_extra_debug_sigprint();
typedef typename T1::elem_type eT;
const eT val = X.aux;
const Proxy<T1> P(X.m);
uword n_nonzero = 0;
if(Proxy<T1>::prefer_at_accessor == false)
{
typedef typename Proxy<T1>::ea_type ea_type;
ea_type A = P.get_ea();
const uword n_elem = P.get_n_elem();
for(uword i=0; i<n_elem; ++i)
{
n_nonzero += (A[i] != val) ? uword(1) : uword(0);
}
}
else
{
const uword P_n_cols = P.get_n_cols();
const uword P_n_rows = P.get_n_rows();
if(P_n_rows == 1)
{
for(uword col=0; col < P_n_cols; ++col)
{
n_nonzero += (P.at(0,col) != val) ? uword(1) : uword(0);
}
}
else
{
for(uword col=0; col < P_n_cols; ++col)
for(uword row=0; row < P_n_rows; ++row)
{
n_nonzero += (P.at(row,col) != val) ? uword(1) : uword(0);
}
}
}
return n_nonzero;
}
template<typename T1>
inline
arma_warn_unused
uword
accu(const mtOp<uword,T1,op_rel_eq>& X)
{
arma_extra_debug_sigprint();
typedef typename T1::elem_type eT;
const eT val = X.aux;
const Proxy<T1> P(X.m);
uword n_nonzero = 0;
if(Proxy<T1>::prefer_at_accessor == false)
{
typedef typename Proxy<T1>::ea_type ea_type;
ea_type A = P.get_ea();
const uword n_elem = P.get_n_elem();
for(uword i=0; i<n_elem; ++i)
{
n_nonzero += (A[i] == val) ? uword(1) : uword(0);
}
}
else
{
const uword P_n_cols = P.get_n_cols();
const uword P_n_rows = P.get_n_rows();
if(P_n_rows == 1)
{
for(uword col=0; col < P_n_cols; ++col)
{
n_nonzero += (P.at(0,col) == val) ? uword(1) : uword(0);
}
}
else
{
for(uword col=0; col < P_n_cols; ++col)
for(uword row=0; row < P_n_rows; ++row)
{
n_nonzero += (P.at(row,col) == val) ? uword(1) : uword(0);
}
}
}
return n_nonzero;
}
//! accumulate the elements of a subview (submatrix)
template<typename eT>
arma_hot
arma_pure
arma_warn_unused
inline
eT
accu(const subview<eT>& X)
{
arma_extra_debug_sigprint();
const uword X_n_rows = X.n_rows;
const uword X_n_cols = X.n_cols;
eT val = eT(0);
if(X_n_rows == 1)
{
typedef subview_row<eT> sv_type;
const sv_type& sv = reinterpret_cast<const sv_type&>(X); // subview_row<eT> is a child class of subview<eT> and has no extra data
const Proxy<sv_type> P(sv);
val = accu_proxy_linear(P);
}
else
if(X_n_cols == 1)
{
val = arrayops::accumulate( X.colptr(0), X_n_rows );
}
else
{
for(uword col=0; col < X_n_cols; ++col)
{
val += arrayops::accumulate( X.colptr(col), X_n_rows );
}
}
return val;
}
template<typename eT>
arma_hot
arma_pure
arma_warn_unused
inline
eT
accu(const subview_col<eT>& X)
{
arma_extra_debug_sigprint();
return arrayops::accumulate( X.colptr(0), X.n_rows );
}
//! accumulate the elements of a cube
template<typename T1>
arma_hot
arma_warn_unused
inline
typename T1::elem_type
accu(const BaseCube<typename T1::elem_type,T1>& X)
{
arma_extra_debug_sigprint();
typedef typename T1::elem_type eT;
typedef typename ProxyCube<T1>::ea_type ea_type;
const ProxyCube<T1> A(X.get_ref());
if(is_Cube<typename ProxyCube<T1>::stored_type>::value)
{
unwrap_cube<typename ProxyCube<T1>::stored_type> tmp(A.Q);
return arrayops::accumulate(tmp.M.memptr(), tmp.M.n_elem);
}
if(ProxyCube<T1>::prefer_at_accessor == false)
{
ea_type P = A.get_ea();
const uword n_elem = A.get_n_elem();
eT val1 = eT(0);
eT val2 = eT(0);
uword i,j;
for(i=0, j=1; j<n_elem; i+=2, j+=2)
{
val1 += P[i];
val2 += P[j];
}
if(i < n_elem)
{
val1 += P[i];
}
return val1 + val2;
}
else
{
const uword n_rows = A.get_n_rows();
const uword n_cols = A.get_n_cols();
const uword n_slices = A.get_n_slices();
eT val1 = eT(0);
eT val2 = eT(0);
for(uword slice=0; slice<n_slices; ++slice)
for(uword col=0; col<n_cols; ++col)
{
uword i,j;
for(i=0, j=1; j<n_rows; i+=2, j+=2)
{
val1 += A.at(i,col,slice);
val2 += A.at(j,col,slice);
}
if(i < n_rows)
{
val1 += A.at(i,col,slice);
}
}
return val1 + val2;
}
}
template<typename T>
arma_inline
arma_warn_unused
const typename arma_scalar_only<T>::result &
accu(const T& x)
{
return x;
}
//! accumulate values in a sparse object
template<typename T1>
arma_hot
inline
arma_warn_unused
typename enable_if2<is_arma_sparse_type<T1>::value, typename T1::elem_type>::result
accu(const T1& x)
{
arma_extra_debug_sigprint();
typedef typename T1::elem_type eT;
const SpProxy<T1> p(x);
if(SpProxy<T1>::must_use_iterator == false)
{
// direct counting
return arrayops::accumulate(p.get_values(), p.get_n_nonzero());
}
else
{
typename SpProxy<T1>::const_iterator_type it = p.begin();
typename SpProxy<T1>::const_iterator_type it_end = p.end();
eT result = eT(0);
while(it != it_end)
{
result += (*it);
++it;
}
return result;
}
}
//! @}