TRIQS/nda 1.3.0
Multi-dimensional array library for C++
Loading...
Searching...
No Matches
norm.hpp
Go to the documentation of this file.
1// Copyright (c) 2023 Simons Foundation
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0.txt
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// Authors: Nils Wentzell
16
17#pragma once
18
19/**
20 * @file
21 * @brief Provides the p-norm for general arrays/views of rank 1 and with scalar elements.
22 */
23
24#pragma once
25
26#include "../algorithms.hpp"
27#include "../basic_functions.hpp"
28#include "../blas/dot.hpp"
29#include "../concepts.hpp"
30#include "../mapped_functions.hxx"
31#include "../traits.hpp"
32
33#include <cmath>
34#include <complex>
35#include <limits>
36
37namespace nda {
38
39 /**
40 * @ingroup linalg_tools
41 * @brief Calculate the p-norm of an nda::ArrayOfRank<1> object \f$ \mathbf{x} \f$ with scalar values.
42 * The p-norm is defined as
43 * \f[
44 * || \mathbf{x} ||_p = \left( \sum_{i=0}^{N-1} |x_i|^p \right)^{1/p}
45 * \f]
46 * with the special cases (following numpy.linalg.norm convention)
47 *
48 * - \f$ || \mathbf{x} ||_0 = \text{number of non-zero elements} \f$,
49 * - \f$ || \mathbf{x} ||_{\infty} = \max_i |x_i| \f$,
50 * - \f$ || \mathbf{x} ||_{-\infty} = \min_i |x_i| \f$.
51 *
52 * @tparam A nda::ArrayOfRank<1> type.
53 * @param a nda::ArrayOfRank<1> object.
54 * @param p Order of the norm.
55 * @return Norm of the array/view as a double.
56 */
57 template <ArrayOfRank<1> A>
58 double norm(A const &a, double p = 2.0) {
59 static_assert(Scalar<get_value_t<A>>, "Error in nda::norm: Only scalar value types are allowed");
60
61 if (p == 2.0) [[likely]] {
62 if constexpr (MemoryArray<A>)
63 return std::sqrt(std::real(nda::blas::dotc(a, a)));
64 else
65 return norm(make_regular(a));
66 } else if (p == 1.0) {
67 return sum(abs(a));
68 } else if (p == 0.0) {
69 long count = 0;
70 for (long i = 0; i < a.size(); ++i) {
71 if (a(i) != get_value_t<A>{0}) ++count;
72 }
73 return double(count);
74 } else if (p == std::numeric_limits<double>::infinity()) {
75 return max_element(abs(a));
76 } else if (p == -std::numeric_limits<double>::infinity()) {
77 return min_element(abs(a));
78 } else {
79 return std::pow(sum(pow(abs(a), p)), 1.0 / p);
80 }
81 }
82
83} // namespace nda
double norm(A const &a, double p=2.0)
Calculate the p-norm of an nda::ArrayOfRank<1> object with scalar values. The p-norm is defined as.
Definition norm.hpp:58