// SPDX-License-Identifier: Apache-2.0 // // 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 fn_norm //! @{ template arma_warn_unused inline typename enable_if2< is_arma_type::value, typename T1::pod_type >::result norm ( const T1& X, const uword k = uword(2), const typename arma_real_or_cx_only::result* junk = nullptr ) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename T1::pod_type T; const Proxy P(X); if(P.get_n_elem() == 0) { return T(0); } const bool is_vec = (T1::is_xvec) || (T1::is_row) || (T1::is_col) || (P.get_n_rows() == 1) || (P.get_n_cols() == 1); if(is_vec) { if(k == uword(1)) { return op_norm::vec_norm_1(P); } if(k == uword(2)) { return op_norm::vec_norm_2(P); } arma_debug_check( (k == 0), "norm(): unsupported vector norm type" ); return op_norm::vec_norm_k(P, int(k)); } else { const quasi_unwrap::stored_type> U(P.Q); if(k == uword(1)) { return op_norm::mat_norm_1(U.M); } if(k == uword(2)) { return op_norm::mat_norm_2(U.M); } arma_stop_logic_error("norm(): unsupported matrix norm type"); } return T(0); } template arma_warn_unused inline typename enable_if2< is_arma_type::value, typename T1::pod_type >::result norm ( const T1& X, const char* method, const typename arma_real_or_cx_only::result* junk = nullptr ) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename T1::pod_type T; const Proxy P(X); if(P.get_n_elem() == 0) { return T(0); } const char sig = (method != nullptr) ? method[0] : char(0); const bool is_vec = (T1::is_xvec) || (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 == '+') ) { return op_norm::vec_norm_max(P); } if( (sig == '-') ) { return op_norm::vec_norm_min(P); } if( (sig == 'f') || (sig == 'F') ) { return op_norm::vec_norm_2(P); } arma_stop_logic_error("norm(): unsupported vector norm type"); } else { if( (sig == 'i') || (sig == 'I') || (sig == '+') ) // inf norm { const quasi_unwrap::stored_type> U(P.Q); return op_norm::mat_norm_inf(U.M); } else if( (sig == 'f') || (sig == 'F') ) { return op_norm::vec_norm_2(P); } arma_stop_logic_error("norm(): unsupported matrix norm type"); } return T(0); } template arma_warn_unused inline typename enable_if2< is_arma_type::value, double >::result norm ( const T1& X, const uword k = uword(2), const typename arma_integral_only::result* junk = nullptr ) { arma_extra_debug_sigprint(); arma_ignore(junk); if(resolves_to_colvector::value) { return norm(conv_to< Col >::from(X), k); } if(resolves_to_rowvector::value) { return norm(conv_to< Row >::from(X), k); } return norm(conv_to< Mat >::from(X), k); } template arma_warn_unused inline typename enable_if2< is_arma_type::value, double >::result norm ( const T1& X, const char* method, const typename arma_integral_only::result* junk = nullptr ) { arma_extra_debug_sigprint(); arma_ignore(junk); if(resolves_to_colvector::value) { return norm(conv_to< Col >::from(X), method); } if(resolves_to_rowvector::value) { return norm(conv_to< Row >::from(X), method); } return norm(conv_to< Mat >::from(X), method); } // // norms for sparse matrices template arma_warn_unused inline typename enable_if2< is_arma_sparse_type::value, typename T1::pod_type >::result norm ( const T1& expr, const uword k = uword(2), const typename arma_real_or_cx_only::result* junk = nullptr ) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename T1::elem_type eT; typedef typename T1::pod_type T; if(is_SpSubview_col::value) { const SpSubview_col& sv = reinterpret_cast< const SpSubview_col& >(expr); if(sv.n_rows == sv.m.n_rows) { const SpMat& m = sv.m; const uword col = sv.aux_col1; const eT* mem = &(m.values[ m.col_ptrs[col] ]); return spop_norm::vec_norm_k(mem, sv.n_nonzero, k); } } const unwrap_spmat U(expr); const SpMat& X = U.M; if(X.n_nonzero == 0) { return T(0); } const bool is_vec = (T1::is_xvec) || (T1::is_row) || (T1::is_col) || (X.n_rows == 1) || (X.n_cols == 1); if(is_vec) { return spop_norm::vec_norm_k(X.values, X.n_nonzero, k); } else { if(k == uword(1)) { return spop_norm::mat_norm_1(X); } if(k == uword(2)) { return spop_norm::mat_norm_2(X); } arma_stop_logic_error("norm(): unsupported or unimplemented norm type for sparse matrices"); } return T(0); } template arma_warn_unused inline typename enable_if2< is_arma_sparse_type::value, typename T1::pod_type >::result norm ( const T1& expr, const char* method, const typename arma_real_or_cx_only::result* junk = nullptr ) { arma_extra_debug_sigprint(); arma_ignore(junk); typedef typename T1::elem_type eT; typedef typename T1::pod_type T; const unwrap_spmat U(expr); const SpMat& X = U.M; if(X.n_nonzero == 0) { return T(0); } // create a fake dense vector to allow reuse of code for dense vectors Col fake_vector( access::rwp(X.values), X.n_nonzero, false ); const Proxy< Col > P_fake_vector(fake_vector); const char sig = (method != nullptr) ? method[0] : char(0); const bool is_vec = (T1::is_xvec) || (T1::is_row) || (T1::is_col) || (X.n_rows == 1) || (X.n_cols == 1); if(is_vec) { 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); return (X.n_nonzero < X.n_elem) ? T((std::min)(T(0), val)) : T(val); } else if( (sig == 'f') || (sig == 'F') ) { return op_norm::vec_norm_2(P_fake_vector); } arma_stop_logic_error("norm(): unsupported vector norm type"); } else { if( (sig == 'i') || (sig == 'I') || (sig == '+') ) // inf norm { return spop_norm::mat_norm_inf(X); } else if( (sig == 'f') || (sig == 'F') ) { return op_norm::vec_norm_2(P_fake_vector); } arma_stop_logic_error("norm(): unsupported matrix norm type"); } return T(0); } // // approximate norms template arma_warn_unused inline typename T1::pod_type norm2est ( const Base& X, const typename T1::pod_type tolerance = 0, const uword max_iter = 100, const typename arma_real_or_cx_only::result* junk = nullptr ) { arma_extra_debug_sigprint(); arma_ignore(junk); return op_norm2est::norm2est(X.get_ref(), tolerance, max_iter); } template arma_warn_unused inline typename T1::pod_type norm2est ( const SpBase& X, const typename T1::pod_type tolerance = 0, const uword max_iter = 100, const typename arma_real_or_cx_only::result* junk = nullptr ) { arma_extra_debug_sigprint(); arma_ignore(junk); return op_norm2est::norm2est(X.get_ref(), tolerance, max_iter); } //! @}