tinyopt 700
Tinyopt, a lightweight, header only optimization library
Loading...
Searching...
No Matches
norms.h
1// Copyright 2026 Julien Michot.
2// SPDX-License-Identifier: Apache-2.0
3
4#pragma once
5
6#include <tinyopt/math.h>
7#include <tinyopt/traits.h>
8#include <type_traits>
9
10namespace tinyopt::losses {
11
16
18template <typename T>
19auto SquaredL2(const T &x) {
20 constexpr bool IsMatrix = traits::is_matrix_or_array_v<T> || traits::is_sparse_matrix_v<T>;
21 if constexpr (traits::is_pair_v<T>) { // pair
22 return SquaredL2(x.first, x.second);
23 } else if constexpr (IsMatrix) { // scalar
24 return x.squaredNorm();
25 } else { // scalar
26 return x * x;
27 }
28}
29
31template <typename T, typename ExportJ>
32auto SquaredL2(const T &x, const ExportJ &Jx_or_bool, bool add_scale = true) {
33 constexpr bool IsMatrix = traits::is_matrix_or_array_v<T> || traits::is_sparse_matrix_v<T>;
34 const auto l = SquaredL2(x);
35 if constexpr (std::is_null_pointer_v<ExportJ>) {
36 return l;
37 } else if constexpr (IsMatrix) {
38 using Scalar = typename traits::params_trait<T>::Scalar;
39 RowVector<Scalar, traits::params_trait<T>::Dims> J = x.transpose();
40 if (add_scale) J *= Scalar(2.0);
41 if constexpr (traits::is_bool_v<ExportJ>)
42 return std::make_pair(l, J);
43 else
44 return std::make_pair(l, (J * Jx_or_bool).eval());
45 } else { // scalar
46 return std::make_pair(l, add_scale ? T(2.0) * x : x);
47 }
48}
49
51template <typename T>
52auto L2(const T &x) {
53 constexpr bool IsMatrix = traits::is_matrix_or_array_v<T> || traits::is_sparse_matrix_v<T>;
54 if constexpr (traits::is_pair_v<T>) { // pair
55 return L2(x.first, x.second);
56 } else if constexpr (IsMatrix) { // scalar
57 return x.norm();
58 } else { // scalar
59 using std::abs;
60 return abs(x); // same as sqrt(x*x);
61 }
62}
63
65template <typename T, typename ExportJ>
66auto L2(const T &x, const ExportJ &Jx_or_bool) {
67 constexpr bool IsMatrix = traits::is_matrix_or_array_v<T> || traits::is_sparse_matrix_v<T>;
68 const auto l = L2(x);
69 if constexpr (std::is_null_pointer_v<ExportJ>) {
70 return l;
71 } else if constexpr (IsMatrix) {
72 const auto J = l > FloatEpsilon() ? (x / l).eval() : x;
73 if constexpr (traits::is_bool_v<ExportJ>)
74 return std::make_pair(l, J.transpose().eval());
75 else
76 return std::make_pair(l, (J.transpose() * Jx_or_bool).eval());
77 } else { // scalar
78 return std::make_pair(l, 1);
79 }
80}
81
83template <typename T>
84auto L1(const T &x) {
85 constexpr bool IsMatrix = traits::is_matrix_or_array_v<T> || traits::is_sparse_matrix_v<T>;
86 if constexpr (traits::is_pair_v<T>) { // pair
87 return L1(x.first, x.second);
88 } else if constexpr (IsMatrix) { // scalar
89 return x.template lpNorm<1>();
90 } else { // scalar
91 using std::abs;
92 return abs(x);
93 }
94}
95
97template <typename T, typename ExportJ>
98auto L1(const T &x, const ExportJ &Jx_or_bool) {
99 constexpr bool IsMatrix = traits::is_matrix_or_array_v<T> || traits::is_sparse_matrix_v<T>;
100 const auto l = L1(x);
101 if constexpr (std::is_null_pointer_v<ExportJ>) {
102 return l;
103 } else if constexpr (IsMatrix) {
104 using Scalar = typename traits::params_trait<T>::Scalar;
105 constexpr int DimsJ = traits::params_trait<T>::Dims;
106 if constexpr (traits::is_bool_v<ExportJ>)
107 return std::make_pair(l, RowVector<Scalar, DimsJ>(x.array().sign()));
108 else
109 return std::make_pair(l, (x.array().sign() * Jx_or_bool).eval());
110 } else { // scalar
111 return std::make_pair(l, 1);
112 }
113}
114
116template <typename T>
117auto Linf(const T &x) {
118 constexpr bool IsMatrix = traits::is_matrix_or_array_v<T> || traits::is_sparse_matrix_v<T>;
119 if constexpr (traits::is_pair_v<T>) { // pair
120 return Linf(x.first, x.second);
121 } else if constexpr (IsMatrix) {
122 return x.template lpNorm<Infinity>();
123 } else { // scalar
124 using std::abs;
125 return abs(x);
126 }
127}
128
130template <typename T, typename ExportJ>
131auto Linf(const T &x, const ExportJ &Jx_or_bool) {
132 constexpr bool IsMatrix = traits::is_matrix_or_array_v<T> || traits::is_sparse_matrix_v<T>;
133 if constexpr (std::is_null_pointer_v<ExportJ>) {
134 return Linf(x);
135 } else if constexpr (IsMatrix) {
136 using Scalar = typename traits::params_trait<T>::Scalar;
137 constexpr int DimsJ = traits::params_trait<T>::Dims;
138 RowVector<Scalar, DimsJ> J(1, x.rows());
139 J.setZero();
140 int max_idx;
141 const auto l = x.cwiseAbs().maxCoeff(&max_idx);
142 J[max_idx] = x[max_idx] >= 0 ? 1 : -1;
143 if constexpr (traits::is_bool_v<ExportJ>)
144 return std::make_pair(l, J);
145 else
146 return std::make_pair(l, (J * Jx_or_bool).eval());
147 } else { // scalar
148 if (x >= 0)
149 return std::make_pair(x, T(1.0));
150 else
151 return std::make_pair(-x, T(-1.0));
152 }
153}
154
156
157} // namespace tinyopt::losses
Definition activations.h:8
auto Linf(const T &x)
Return L infinity norm of a vector or scalar.
Definition norms.h:117
auto SquaredL2(const T &x)
Return the squared L2 norm of a vector or scalar (a.k.a Sum of Squares).
Definition norms.h:19
auto L2(const T &x)
Return L2 norm of a vector or scalar.
Definition norms.h:52
auto L1(const T &x)
Return L1 norm of a vector or scalar.
Definition norms.h:84