916 lines
18 KiB
C++
916 lines
18 KiB
C++
// Copyright 2008-2016 Conrad Sanderson (http://conradsanderson.id.au)
|
|
// Copyright 2008-2016 National ICT Australia (NICTA)
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
//! \addtogroup op_norm
|
|
//! @{
|
|
|
|
|
|
|
|
template<typename T1>
|
|
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 use_direct_mem = (is_Mat<typename Proxy<T1>::stored_type>::value) || (is_subview_col<typename Proxy<T1>::stored_type>::value) || (arma_config::openmp && Proxy<T1>::use_mp);
|
|
|
|
if(use_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;
|
|
}
|
|
|
|
|
|
|
|
template<typename T1>
|
|
arma_hot
|
|
inline
|
|
typename T1::pod_type
|
|
op_norm::vec_norm_1(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 += std::sqrt( (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 += std::sqrt( (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 += std::sqrt( (a*a) + (b*b) );
|
|
}
|
|
}
|
|
}
|
|
|
|
if( (acc != T(0)) && arma_isfinite(acc) )
|
|
{
|
|
return acc;
|
|
}
|
|
else
|
|
{
|
|
arma_extra_debug_print("op_norm::vec_norm_1(): 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 std::complex<T>& X = R_mem[i];
|
|
|
|
const T a = std::abs(X.real());
|
|
const T b = std::abs(X.imag());
|
|
|
|
if(a > max_val) { max_val = a; }
|
|
if(b > max_val) { max_val = b; }
|
|
}
|
|
|
|
if(max_val == T(0)) { return T(0); }
|
|
|
|
T alt_acc = T(0);
|
|
|
|
for(uword i=0; i<N; ++i)
|
|
{
|
|
const std::complex<T>& X = R_mem[i];
|
|
|
|
const T a = X.real() / max_val;
|
|
const T b = X.imag() / max_val;
|
|
|
|
alt_acc += std::sqrt( (a*a) + (b*b) );
|
|
}
|
|
|
|
return ( alt_acc * max_val );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
template<typename eT>
|
|
arma_hot
|
|
inline
|
|
eT
|
|
op_norm::vec_norm_1_direct_std(const Mat<eT>& X)
|
|
{
|
|
arma_extra_debug_sigprint();
|
|
|
|
const uword N = X.n_elem;
|
|
const eT* A = X.memptr();
|
|
|
|
if(N < uword(32))
|
|
{
|
|
return op_norm::vec_norm_1_direct_mem(N,A);
|
|
}
|
|
else
|
|
{
|
|
#if defined(ARMA_USE_ATLAS)
|
|
{
|
|
return atlas::cblas_asum(N,A);
|
|
}
|
|
#elif defined(ARMA_USE_BLAS)
|
|
{
|
|
return blas::asum(N,A);
|
|
}
|
|
#else
|
|
{
|
|
return op_norm::vec_norm_1_direct_mem(N,A);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
|
|
template<typename eT>
|
|
arma_hot
|
|
inline
|
|
eT
|
|
op_norm::vec_norm_1_direct_mem(const uword N, const eT* A)
|
|
{
|
|
arma_extra_debug_sigprint();
|
|
|
|
#if defined(ARMA_SIMPLE_LOOPS) || (defined(__FINITE_MATH_ONLY__) && (__FINITE_MATH_ONLY__ > 0))
|
|
{
|
|
eT acc1 = eT(0);
|
|
|
|
if(memory::is_aligned(A))
|
|
{
|
|
memory::mark_as_aligned(A);
|
|
|
|
for(uword i=0; i<N; ++i) { acc1 += std::abs(A[i]); }
|
|
}
|
|
else
|
|
{
|
|
for(uword i=0; i<N; ++i) { acc1 += std::abs(A[i]); }
|
|
}
|
|
|
|
return acc1;
|
|
}
|
|
#else
|
|
{
|
|
eT acc1 = eT(0);
|
|
eT acc2 = eT(0);
|
|
|
|
uword j;
|
|
|
|
for(j=1; j<N; j+=2)
|
|
{
|
|
const eT tmp_i = (*A); A++;
|
|
const eT tmp_j = (*A); A++;
|
|
|
|
acc1 += std::abs(tmp_i);
|
|
acc2 += std::abs(tmp_j);
|
|
}
|
|
|
|
if((j-1) < N)
|
|
{
|
|
acc1 += std::abs(*A);
|
|
}
|
|
|
|
return (acc1 + acc2);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
template<typename T1>
|
|
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 use_direct_mem = (is_Mat<typename Proxy<T1>::stored_type>::value) || (is_subview_col<typename Proxy<T1>::stored_type>::value) || (arma_config::openmp && Proxy<T1>::use_mp);
|
|
|
|
if(use_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);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
template<typename T1>
|
|
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 );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
template<typename eT>
|
|
arma_hot
|
|
inline
|
|
eT
|
|
op_norm::vec_norm_2_direct_std(const Mat<eT>& X)
|
|
{
|
|
arma_extra_debug_sigprint();
|
|
|
|
const uword N = X.n_elem;
|
|
const eT* A = X.memptr();
|
|
|
|
eT result;
|
|
|
|
if(N < uword(32))
|
|
{
|
|
result = op_norm::vec_norm_2_direct_mem(N,A);
|
|
}
|
|
else
|
|
{
|
|
#if defined(ARMA_USE_ATLAS)
|
|
{
|
|
result = atlas::cblas_nrm2(N,A);
|
|
}
|
|
#elif defined(ARMA_USE_BLAS)
|
|
{
|
|
result = blas::nrm2(N,A);
|
|
}
|
|
#else
|
|
{
|
|
result = op_norm::vec_norm_2_direct_mem(N,A);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if( (result != eT(0)) && arma_isfinite(result) )
|
|
{
|
|
return result;
|
|
}
|
|
else
|
|
{
|
|
arma_extra_debug_print("op_norm::vec_norm_2_direct_std(): detected possible underflow or overflow");
|
|
|
|
return op_norm::vec_norm_2_direct_robust(X);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
template<typename eT>
|
|
arma_hot
|
|
inline
|
|
eT
|
|
op_norm::vec_norm_2_direct_mem(const uword N, const eT* A)
|
|
{
|
|
arma_extra_debug_sigprint();
|
|
|
|
eT acc;
|
|
|
|
#if defined(ARMA_SIMPLE_LOOPS) || (defined(__FINITE_MATH_ONLY__) && (__FINITE_MATH_ONLY__ > 0))
|
|
{
|
|
eT acc1 = eT(0);
|
|
|
|
if(memory::is_aligned(A))
|
|
{
|
|
memory::mark_as_aligned(A);
|
|
|
|
for(uword i=0; i<N; ++i) { const eT tmp_i = A[i]; acc1 += tmp_i * tmp_i; }
|
|
}
|
|
else
|
|
{
|
|
for(uword i=0; i<N; ++i) { const eT tmp_i = A[i]; acc1 += tmp_i * tmp_i; }
|
|
}
|
|
|
|
acc = acc1;
|
|
}
|
|
#else
|
|
{
|
|
eT acc1 = eT(0);
|
|
eT acc2 = eT(0);
|
|
|
|
uword j;
|
|
|
|
for(j=1; j<N; j+=2)
|
|
{
|
|
const eT tmp_i = (*A); A++;
|
|
const eT tmp_j = (*A); A++;
|
|
|
|
acc1 += tmp_i * tmp_i;
|
|
acc2 += tmp_j * tmp_j;
|
|
}
|
|
|
|
if((j-1) < N)
|
|
{
|
|
const eT tmp_i = (*A);
|
|
|
|
acc1 += tmp_i * tmp_i;
|
|
}
|
|
|
|
acc = acc1 + acc2;
|
|
}
|
|
#endif
|
|
|
|
return std::sqrt(acc);
|
|
}
|
|
|
|
|
|
|
|
template<typename eT>
|
|
arma_hot
|
|
inline
|
|
eT
|
|
op_norm::vec_norm_2_direct_robust(const Mat<eT>& X)
|
|
{
|
|
arma_extra_debug_sigprint();
|
|
|
|
const uword N = X.n_elem;
|
|
const eT* A = X.memptr();
|
|
|
|
eT max_val = priv::most_neg<eT>();
|
|
|
|
uword j;
|
|
|
|
for(j=1; j<N; j+=2)
|
|
{
|
|
eT val_i = (*A); A++;
|
|
eT val_j = (*A); A++;
|
|
|
|
val_i = std::abs(val_i);
|
|
val_j = std::abs(val_j);
|
|
|
|
if(val_i > max_val) { max_val = val_i; }
|
|
if(val_j > max_val) { max_val = val_j; }
|
|
}
|
|
|
|
if((j-1) < N)
|
|
{
|
|
const eT val_i = std::abs(*A);
|
|
|
|
if(val_i > max_val) { max_val = val_i; }
|
|
}
|
|
|
|
if(max_val == eT(0)) { return eT(0); }
|
|
|
|
const eT* B = X.memptr();
|
|
|
|
eT acc1 = eT(0);
|
|
eT acc2 = eT(0);
|
|
|
|
for(j=1; j<N; j+=2)
|
|
{
|
|
eT val_i = (*B); B++;
|
|
eT val_j = (*B); B++;
|
|
|
|
val_i /= max_val;
|
|
val_j /= max_val;
|
|
|
|
acc1 += val_i * val_i;
|
|
acc2 += val_j * val_j;
|
|
}
|
|
|
|
if((j-1) < N)
|
|
{
|
|
const eT val_i = (*B) / max_val;
|
|
|
|
acc1 += val_i * val_i;
|
|
}
|
|
|
|
return ( std::sqrt(acc1 + acc2) * max_val );
|
|
}
|
|
|
|
|
|
|
|
template<typename T1>
|
|
arma_hot
|
|
inline
|
|
typename T1::pod_type
|
|
op_norm::vec_norm_k(const Proxy<T1>& P, const int k)
|
|
{
|
|
arma_extra_debug_sigprint();
|
|
|
|
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)
|
|
{
|
|
acc += std::pow(std::abs(A[i]), k);
|
|
}
|
|
}
|
|
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)
|
|
{
|
|
acc += std::pow(std::abs(P.at(row,col)), k);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(uword col=0; col < n_cols; ++col)
|
|
{
|
|
acc += std::pow(std::abs(P.at(0,col)), k);
|
|
}
|
|
}
|
|
}
|
|
|
|
return std::pow(acc, T(1)/T(k));
|
|
}
|
|
|
|
|
|
|
|
template<typename T1>
|
|
arma_hot
|
|
inline
|
|
typename T1::pod_type
|
|
op_norm::vec_norm_max(const Proxy<T1>& P)
|
|
{
|
|
arma_extra_debug_sigprint();
|
|
|
|
typedef typename T1::pod_type T;
|
|
|
|
const uword N = P.get_n_elem();
|
|
|
|
T max_val = (N != 1) ? priv::most_neg<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(max_val < tmp_i) { max_val = tmp_i; }
|
|
if(max_val < tmp_j) { max_val = tmp_j; }
|
|
}
|
|
|
|
if(i < N)
|
|
{
|
|
const T tmp_i = std::abs(A[i]);
|
|
|
|
if(max_val < tmp_i) { max_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(max_val < tmp) { max_val = tmp; }
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(uword col=0; col < n_cols; ++col)
|
|
{
|
|
const T tmp = std::abs(P.at(0,col));
|
|
|
|
if(max_val < tmp) { max_val = tmp; }
|
|
}
|
|
}
|
|
}
|
|
|
|
return max_val;
|
|
}
|
|
|
|
|
|
|
|
template<typename T1>
|
|
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;
|
|
}
|
|
|
|
|
|
|
|
template<typename eT>
|
|
inline
|
|
typename get_pod_type<eT>::result
|
|
op_norm::mat_norm_1(const Mat<eT>& X)
|
|
{
|
|
arma_extra_debug_sigprint();
|
|
|
|
// TODO: this can be sped up with a dedicated implementation
|
|
return as_scalar( max( sum(abs(X), 0), 1) );
|
|
}
|
|
|
|
|
|
|
|
template<typename eT>
|
|
inline
|
|
typename get_pod_type<eT>::result
|
|
op_norm::mat_norm_2(const Mat<eT>& X)
|
|
{
|
|
arma_extra_debug_sigprint();
|
|
|
|
typedef typename get_pod_type<eT>::result T;
|
|
|
|
if(X.is_finite() == false) { arma_debug_warn_level(1, "norm(): given matrix has non-finite elements"); }
|
|
|
|
Col<T> S;
|
|
svd(S, X);
|
|
|
|
return (S.n_elem > 0) ? S[0] : T(0);
|
|
}
|
|
|
|
|
|
|
|
template<typename eT>
|
|
inline
|
|
typename get_pod_type<eT>::result
|
|
op_norm::mat_norm_inf(const Mat<eT>& X)
|
|
{
|
|
arma_extra_debug_sigprint();
|
|
|
|
// TODO: this can be sped up with a dedicated implementation
|
|
return as_scalar( max( sum(abs(X), 1), 0) );
|
|
}
|
|
|
|
|
|
|
|
//! @}
|