tinyopt
700
Tinyopt, a lightweight, header only optimization library
Toggle main menu visibility
Loading...
Searching...
No Matches
parameter_traits.h
1
// Copyright 2026 Julien Michot.
2
// SPDX-License-Identifier: Apache-2.0
3
4
#pragma once
5
6
#include <cassert>
7
#include <type_traits>
8
#include <utility>
9
10
#include <tinyopt/traits/matrix_traits.h>
11
12
namespace
tinyopt::traits {
13
14
template
<
typename
T,
typename
=
void
>
15
struct
params_trait
{
16
using
Scalar =
typename
T::Scalar;
17
static
constexpr
Index Dims = Dynamic;
18
19
static
Index dims(
const
T &v) {
return
v.dims(); }
20
21
template
<
typename
T2>
22
static
auto
cast(
const
T &v) {
23
if
constexpr
(has_static_cast_v<T>)
24
return
T::template cast<T2>(v);
25
else
if
constexpr
(has_cast_v<T>)
26
return
v.template cast<T2>();
27
else
28
return
T2(v);
29
}
30
31
static
void
PlusEq(T &v,
const
auto
&delta) { v += delta; }
32
};
33
34
template
<
typename
T>
35
struct
params_trait
<T, std::void_t<decltype(T::Dims)>> {
36
using
Scalar =
typename
T::Scalar;
37
static
constexpr
Index Dims = T::Dims;
38
39
static
Index dims(
const
T &v) {
return
Dims == Dynamic ? v.dims() : Dims; }
40
41
template
<
typename
T2>
42
static
auto
cast(
const
T &v) {
43
if
constexpr
(has_static_cast_v<T>)
44
return
T::template cast<T2>(v);
45
else
if
constexpr
(has_cast_v<T>)
46
return
v.template cast<T2>();
47
else
48
return
T2(v);
49
}
50
51
static
void
PlusEq(T &v,
const
auto
&delta) { v += delta; }
52
};
53
54
template
<
typename
T>
55
struct
params_trait
<T, std::enable_if_t<std::is_scalar_v<T>>> {
56
using
Scalar = T;
57
static
constexpr
Index Dims = 1;
58
59
static
constexpr
Index dims(
const
T &) {
return
1; }
60
61
template
<
typename
T2>
62
static
T2 cast(
const
T &v) {
63
return
static_cast<
T2
>
(v);
64
}
65
66
static
void
PlusEq(T &v,
const
auto
&delta) { v += delta[0]; }
67
static
void
PlusEq(T &v,
const
Scalar &delta) { v += delta; }
68
};
69
70
template
<
typename
T>
71
struct
params_trait
<T, std::enable_if_t<is_matrix_or_array_v<T>>> {
72
using
Scalar =
typename
T::Scalar;
73
static
constexpr
int
ColsAtCompileTime = T::ColsAtCompileTime;
74
static
constexpr
Index Dims =
75
(T::RowsAtCompileTime == Dynamic || T::ColsAtCompileTime == Dynamic)
76
? Dynamic
77
: T::RowsAtCompileTime * T::ColsAtCompileTime;
78
79
static
Index dims(
const
T &m) {
return
m.size(); }
80
81
template
<
typename
T2>
82
static
auto
cast(
const
T &v) {
83
return
v.template cast<T2>().eval();
84
}
85
86
static
void
PlusEq(T &v,
const
auto
&delta) {
87
if
constexpr
(Dims == Dynamic) assert(delta.rows() == (
int
)v.size());
88
if
constexpr
(T::ColsAtCompileTime == 1)
89
v += delta;
90
else
91
v += delta.reshaped(v.rows(), v.cols());
92
}
93
};
94
95
template
<
typename
T>
96
struct
params_trait
<T, std::enable_if_t<is_sparse_matrix_v<T>>> {
97
using
Scalar =
typename
T::Scalar;
98
static
constexpr
Index Dims = Dynamic;
99
100
static
Index dims(
const
T &m) {
return
m.size(); }
101
102
template
<
typename
T2>
103
static
auto
cast(
const
T &v) {
104
return
v.template cast<T2>().eval();
105
}
106
107
static
void
PlusEq(T &v,
const
auto
&delta) {
108
if
constexpr
(Dims == Dynamic) assert(delta.rows() == (
int
)v.size());
109
if
constexpr
(T::ColsAtCompileTime == 1)
110
v += delta;
111
else
112
v += delta.reshaped(v.rows(), v.cols());
113
}
114
};
115
116
template
<
typename
_Scalar>
117
struct
params_trait
<std::vector<_Scalar>> {
118
using
T =
typename
std::vector<_Scalar>;
119
using
Scalar = _Scalar;
120
using
ScalarParamsTraits =
params_trait<Scalar>
;
121
static
constexpr
Index Dims = Dynamic;
122
123
static
Index dims(
const
T &v) {
124
constexpr
int
ScalarDims = ScalarParamsTraits::Dims;
125
if
constexpr
(std::is_scalar_v<Scalar> || ScalarDims == 1) {
126
return
static_cast<
int
>
(v.size());
127
}
else
if
constexpr
(ScalarDims == Dynamic) {
128
int
d = 0;
129
for
(std::size_t i = 0; i < v.size(); ++i) d += ScalarParamsTraits::dims(v[i]);
130
return
d;
131
}
else
{
132
return
static_cast<
int
>
(v.size()) * ScalarDims;
133
}
134
}
135
136
template
<
typename
T2>
137
static
auto
cast(
const
T &v) {
138
using
Scalar2 = std::decay_t<decltype(ScalarParamsTraits::template cast<T2>(std::declval<Scalar>()))>;
139
std::vector<Scalar2> o;
140
o.reserve(v.size());
141
for
(
auto
&x : v) o.emplace_back(ScalarParamsTraits::template cast<T2>(x));
142
return
o;
143
}
144
145
static
void
PlusEq(T &v,
const
auto
&delta) {
146
for
(std::size_t i = 0; i < v.size(); ++i) {
147
if
constexpr
(std::is_scalar_v<Scalar> || ScalarParamsTraits::Dims == 1)
148
v[i] += delta[i];
149
else
if
constexpr
(ScalarParamsTraits::Dims != Dynamic) {
150
ScalarParamsTraits::PlusEq(
151
v[i], delta.template segment<ScalarParamsTraits::Dims>(i * ScalarParamsTraits::Dims));
152
}
else
{
153
ScalarParamsTraits::PlusEq(v[i], delta.segment(i, i * ScalarParamsTraits::dims(v[i])));
154
}
155
}
156
}
157
};
158
159
template
<
typename
_Scalar, std::
size_t
N>
160
struct
params_trait
<std::array<_Scalar, N>> {
161
using
T =
typename
std::array<_Scalar, N>;
162
using
Scalar = _Scalar;
163
using
ScalarParamsTraits =
params_trait<Scalar>
;
164
static
constexpr
Index Dims =
165
ScalarParamsTraits::Dims == Dynamic ? Dynamic : N * ScalarParamsTraits::Dims;
166
167
static
Index dims(
const
T &v) {
168
constexpr
int
ScalarDims = ScalarParamsTraits::Dims;
169
if
constexpr
(std::is_scalar_v<Scalar> || ScalarDims == 1) {
170
return
N;
171
}
else
if
constexpr
(ScalarDims == Dynamic) {
172
int
d = 0;
173
for
(std::size_t i = 0; i < N; ++i) d += ScalarParamsTraits::dims(v[i]);
174
return
d;
175
}
else
{
176
return
static_cast<
Index
>
(v.size()) * ScalarDims;
177
}
178
}
179
180
template
<
typename
T2>
181
static
auto
cast(
const
T &v) {
182
using
Scalar2 = std::decay_t<decltype(ScalarParamsTraits::template cast<T2>(std::declval<Scalar>()))>;
183
std::array<Scalar2, N> o;
184
for
(std::size_t i = 0; i < N; ++i) o[i] = ScalarParamsTraits::template cast<T2>(v[i]);
185
return
o;
186
}
187
188
static
void
PlusEq(T &v,
const
auto
&delta) {
189
for
(std::size_t i = 0; i < N; ++i) {
190
if
constexpr
(std::is_scalar_v<Scalar> || ScalarParamsTraits::Dims == 1)
191
v[i] += delta[i];
192
else
if
constexpr
(ScalarParamsTraits::Dims != Dynamic) {
193
ScalarParamsTraits::PlusEq(
194
v[i], delta.template segment<ScalarParamsTraits::Dims>(i * ScalarParamsTraits::Dims));
195
}
else
{
196
ScalarParamsTraits::PlusEq(v[i], delta.segment(i, i * ScalarParamsTraits::dims(v[i])));
197
}
198
}
199
}
200
};
201
202
template
<
typename
T1,
typename
T2>
203
struct
params_trait
<std::pair<T1, T2>> {
204
using
T = std::pair<T1, T2>;
205
using
Scalar =
typename
params_trait<T1>::Scalar;
206
using
Scalar1ParamsTraits =
params_trait<T1>
;
207
using
Scalar2ParamsTraits =
params_trait<T2>
;
208
static
constexpr
Index Dims =
209
(Scalar1ParamsTraits::Dims == Dynamic || Scalar2ParamsTraits::Dims == Dynamic)
210
? Dynamic
211
: Scalar1ParamsTraits::Dims + Scalar2ParamsTraits::Dims;
212
213
static
Index dims(
const
T &v) {
214
return
Scalar1ParamsTraits::dims(v.first) + Scalar2ParamsTraits::dims(v.second);
215
}
216
217
template
<
typename
T3>
218
static
auto
cast(
const
T &v) {
219
using
Scalar1 = std::decay_t<decltype(Scalar1ParamsTraits::template cast<T3>(std::declval<T1>()))>;
220
using
Scalar2 = std::decay_t<decltype(Scalar2ParamsTraits::template cast<T3>(std::declval<T2>()))>;
221
std::pair<Scalar1, Scalar2> o{Scalar1ParamsTraits::template cast<T3>(v.first),
222
Scalar2ParamsTraits::template cast<T3>(v.second)};
223
return
o;
224
}
225
226
static
void
PlusEq(T &v,
const
auto
&delta) {
227
if
constexpr
(Scalar1ParamsTraits::Dims == Dynamic)
228
Scalar1ParamsTraits::PlusEq(v.first, delta.head(Scalar1ParamsTraits::dims(v.first)));
229
else
230
Scalar1ParamsTraits::PlusEq(v.first, delta.template head<Scalar1ParamsTraits::Dims>());
231
if
constexpr
(Scalar2ParamsTraits::Dims == Dynamic)
232
Scalar2ParamsTraits::PlusEq(v.second, delta.tail(Scalar2ParamsTraits::dims(v.second)));
233
else
234
Scalar2ParamsTraits::PlusEq(v.first, delta.template tail<Scalar2ParamsTraits::Dims>());
235
}
236
};
237
238
template
<
typename
T>
239
inline
auto
DynDims(
const
T &x) {
240
using
ptrait =
params_trait<T>
;
241
if
constexpr
(ptrait::Dims == Dynamic)
242
return
ptrait::dims(x);
243
else
244
return
ptrait::Dims;
245
}
246
247
}
// namespace tinyopt::traits
tinyopt::traits::params_trait
Definition
parameter_traits.h:15
include
tinyopt
traits
parameter_traits.h
Generated by
1.18.0