Skip to content

Commit fad17fd

Browse files
authored
perf: Changed parameter type Number to const Number& (#69)
- Changed parameter type `Number` to `const Number&` where applicable. This improves performance for custom types like arbitrary-precision or symbolic numbers, but slightly reduces performance for fundamental types like `float` or `double`. - Reduced the precision of tests for quadratic and cubic splines on "Fast" and "FastParallel" profiles, as the precision was unexpectedly affected by optimizations from the `-Ofast` option, specifically `-ffast-math`. The behavior remains unchanged on other profiles.
1 parent b4a934f commit fad17fd

File tree

15 files changed

+69
-69
lines changed

15 files changed

+69
-69
lines changed

ALFI/ALFI/dist.h

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ namespace alfi::dist {
3434
};
3535

3636
template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
37-
Container<Number> uniform(SizeT n, Number a, Number b) {
37+
Container<Number> uniform(SizeT n, const Number& a, const Number& b) {
3838
if (n == 1)
3939
return {(a+b)/2};
4040
Container<Number> points(n);
@@ -63,7 +63,7 @@ namespace alfi::dist {
6363
@return a container with \p n points distributed on the segment `[a, b]` according to the transform function
6464
*/
6565
template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
66-
Container<Number> quadratic(SizeT n, Number a, Number b) {
66+
Container<Number> quadratic(SizeT n, const Number& a, const Number& b) {
6767
if (n == 1)
6868
return {(a+b)/2};
6969
Container<Number> points(n);
@@ -91,7 +91,7 @@ namespace alfi::dist {
9191
@return a container with \p n points distributed on the segment `[a, b]` according to the transform function
9292
*/
9393
template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
94-
Container<Number> cubic(SizeT n, Number a, Number b) {
94+
Container<Number> cubic(SizeT n, const Number& a, const Number& b) {
9595
if (n == 1)
9696
return {(a+b)/2};
9797
Container<Number> points(n);
@@ -104,7 +104,7 @@ namespace alfi::dist {
104104
}
105105

106106
template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
107-
Container<Number> chebyshev(SizeT n, Number a, Number b) {
107+
Container<Number> chebyshev(SizeT n, const Number& a, const Number& b) {
108108
if (n == 1)
109109
return {(a+b)/2};
110110
Container<Number> points(n);
@@ -116,12 +116,12 @@ namespace alfi::dist {
116116
}
117117

118118
template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
119-
Container<Number> chebyshev_stretched(SizeT n, Number a, Number b) {
119+
Container<Number> chebyshev_stretched(SizeT n, const Number& a, const Number& b) {
120120
return points::stretched<Number,Container>(chebyshev(n, a, b), a, b);
121121
}
122122

123123
template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
124-
Container<Number> chebyshev_augmented(SizeT n, Number a, Number b) {
124+
Container<Number> chebyshev_augmented(SizeT n, const Number& a, const Number& b) {
125125
if (n == 0) {
126126
return {};
127127
}
@@ -137,7 +137,7 @@ namespace alfi::dist {
137137
}
138138

139139
template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
140-
Container<Number> chebyshev_2(SizeT n, Number a, Number b) {
140+
Container<Number> chebyshev_2(SizeT n, const Number& a, const Number& b) {
141141
if (n == 1)
142142
return {(a+b)/2};
143143
Container<Number> points(n);
@@ -149,7 +149,7 @@ namespace alfi::dist {
149149
}
150150

151151
template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
152-
Container<Number> chebyshev_3(SizeT n, Number a, Number b) {
152+
Container<Number> chebyshev_3(SizeT n, const Number& a, const Number& b) {
153153
Container<Number> points(n);
154154
for (SizeT i = 0; i < n; ++i) {
155155
const Number x = 1 - std::cos(M_PI * static_cast<Number>(2*i) / static_cast<Number>(2*n - 1));
@@ -159,12 +159,12 @@ namespace alfi::dist {
159159
}
160160

161161
template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
162-
Container<Number> chebyshev_3_stretched(SizeT n, Number a, Number b) {
162+
Container<Number> chebyshev_3_stretched(SizeT n, const Number& a, const Number& b) {
163163
return points::stretched<Number,Container>(chebyshev_3(n, a, b), a, b);
164164
}
165165

166166
template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
167-
Container<Number> chebyshev_4(SizeT n, Number a, Number b) {
167+
Container<Number> chebyshev_4(SizeT n, const Number& a, const Number& b) {
168168
Container<Number> points(n);
169169
for (SizeT i = 0; i < n; ++i) {
170170
const Number x = 1 - std::cos(M_PI * static_cast<Number>(2*i + 1) / static_cast<Number>(2*n - 1));
@@ -174,12 +174,12 @@ namespace alfi::dist {
174174
}
175175

176176
template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
177-
Container<Number> chebyshev_4_stretched(SizeT n, Number a, Number b) {
177+
Container<Number> chebyshev_4_stretched(SizeT n, const Number& a, const Number& b) {
178178
return points::stretched<Number,Container>(chebyshev_4(n, a, b), a, b);
179179
}
180180

181181
template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
182-
Container<Number> chebyshev_ellipse(SizeT n, Number a, Number b, Number ratio) {
182+
Container<Number> chebyshev_ellipse(SizeT n, const Number& a, const Number& b, const Number& ratio) {
183183
Container<Number> points(n);
184184
for (SizeT i = 0; i < n / 2; ++i) {
185185
const Number theta = M_PI * (2 * static_cast<Number>(i) + 1) / (2 * static_cast<Number>(n));
@@ -193,12 +193,12 @@ namespace alfi::dist {
193193
}
194194

195195
template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
196-
Container<Number> chebyshev_ellipse_stretched(SizeT n, Number a, Number b, Number ratio) {
196+
Container<Number> chebyshev_ellipse_stretched(SizeT n, const Number& a, const Number& b, const Number& ratio) {
197197
return points::stretched<Number,Container>(chebyshev_ellipse(n, a, b, ratio), a, b);
198198
}
199199

200200
template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
201-
Container<Number> chebyshev_ellipse_augmented(SizeT n, Number a, Number b, Number ratio) {
201+
Container<Number> chebyshev_ellipse_augmented(SizeT n, const Number& a, const Number& b, const Number& ratio) {
202202
if (n == 0) {
203203
return {};
204204
}
@@ -214,7 +214,7 @@ namespace alfi::dist {
214214
}
215215

216216
template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
217-
Container<Number> chebyshev_ellipse_2(SizeT n, Number a, Number b, Number ratio) {
217+
Container<Number> chebyshev_ellipse_2(SizeT n, const Number& a, const Number& b, const Number& ratio) {
218218
Container<Number> points(n);
219219
for (SizeT i = 0; i < n / 2; ++i) {
220220
const Number theta = M_PI * static_cast<Number>(i) / (static_cast<Number>(n) - 1);
@@ -228,7 +228,7 @@ namespace alfi::dist {
228228
}
229229

230230
template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
231-
Container<Number> chebyshev_ellipse_3(SizeT n, Number a, Number b, Number ratio) {
231+
Container<Number> chebyshev_ellipse_3(SizeT n, const Number& a, const Number& b, const Number& ratio) {
232232
Container<Number> points(n);
233233
for (SizeT i = 0; i < n; ++i) {
234234
const Number theta = M_PI * static_cast<Number>(2*i) / static_cast<Number>(2*n - 1);
@@ -239,12 +239,12 @@ namespace alfi::dist {
239239
}
240240

241241
template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
242-
Container<Number> chebyshev_ellipse_3_stretched(SizeT n, Number a, Number b, Number ratio) {
242+
Container<Number> chebyshev_ellipse_3_stretched(SizeT n, const Number& a, const Number& b, const Number& ratio) {
243243
return points::stretched<Number,Container>(chebyshev_ellipse_3(n, a, b, ratio), a, b);
244244
}
245245

246246
template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
247-
Container<Number> chebyshev_ellipse_4(SizeT n, Number a, Number b, Number ratio) {
247+
Container<Number> chebyshev_ellipse_4(SizeT n, const Number& a, const Number& b, const Number& ratio) {
248248
Container<Number> points(n);
249249
for (SizeT i = 0; i < n; ++i) {
250250
const Number theta = M_PI * static_cast<Number>(2*i + 1) / static_cast<Number>(2*n - 1);
@@ -255,7 +255,7 @@ namespace alfi::dist {
255255
}
256256

257257
template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
258-
Container<Number> chebyshev_ellipse_4_stretched(SizeT n, Number a, Number b, Number ratio) {
258+
Container<Number> chebyshev_ellipse_4_stretched(SizeT n, const Number& a, const Number& b, const Number& ratio) {
259259
return points::stretched<Number,Container>(chebyshev_ellipse_4(n, a, b, ratio), a, b);
260260
}
261261

@@ -283,7 +283,7 @@ namespace alfi::dist {
283283
@return a container with \p n points distributed on the interval `(a, b)` according to the transform function
284284
*/
285285
template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
286-
Container<Number> logistic(SizeT n, Number a, Number b, Number steepness) {
286+
Container<Number> logistic(SizeT n, const Number& a, const Number& b, const Number& steepness) {
287287
if (n == 1)
288288
return {(a+b)/2};
289289
Container<Number> points(n);
@@ -296,7 +296,7 @@ namespace alfi::dist {
296296
}
297297

298298
template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
299-
Container<Number> logistic_stretched(SizeT n, Number a, Number b, Number steepness) {
299+
Container<Number> logistic_stretched(SizeT n, const Number& a, const Number& b, const Number& steepness) {
300300
if (n == 0)
301301
return {};
302302
if (n == 1)
@@ -338,7 +338,7 @@ namespace alfi::dist {
338338
@return a container with \p n points distributed on the interval `(a, b)` according to the transform function
339339
*/
340340
template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
341-
Container<Number> erf(SizeT n, Number a, Number b, Number steepness) {
341+
Container<Number> erf(SizeT n, const Number& a, const Number& b, const Number& steepness) {
342342
if (n == 0)
343343
return {};
344344
if (n == 1)
@@ -353,12 +353,12 @@ namespace alfi::dist {
353353
}
354354

355355
template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
356-
Container<Number> erf_stretched(SizeT n, Number a, Number b, Number steepness) {
356+
Container<Number> erf_stretched(SizeT n, const Number& a, const Number& b, const Number& steepness) {
357357
return points::stretched<Number,Container>(erf(n, a, b, steepness), a, b);
358358
}
359359

360360
template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
361-
Container<Number> of_type(Type type, SizeT n, Number a, Number b, Number parameter = NAN) {
361+
Container<Number> of_type(Type type, SizeT n, const Number& a, const Number& b, const Number& parameter = NAN) {
362362
switch (type) {
363363
case Type::QUADRATIC:
364364
return quadratic(n, a, b);

ALFI/ALFI/misc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace alfi::misc {
1313
const Container<Number>& Y,
1414
const Container<Number>& xx,
1515
dist::Type dist_type = dist::Type::GENERAL,
16-
Number epsilon = std::numeric_limits<Number>::epsilon()
16+
const Number& epsilon = std::numeric_limits<Number>::epsilon()
1717
) {
1818
if (X.size() != Y.size()) {
1919
std::cerr << "Error in function " << __FUNCTION__

ALFI/ALFI/poly.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
namespace alfi::poly {
1010
template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
1111
std::enable_if_t<!traits::has_size<Number>::value, Number>
12-
val(const Container<Number>& coeffs, Number x) {
12+
val(const Container<Number>& coeffs, const Number& x) {
1313
Number result = 0;
1414
for (const Number& c : coeffs) {
1515
result = result * x + c;
@@ -187,7 +187,7 @@ namespace alfi::poly {
187187
const Container<Number>& X,
188188
const Container<Number>& Y,
189189
const Container<Number>& xx,
190-
Number epsilon = std::numeric_limits<Number>::epsilon()
190+
const Number& epsilon = std::numeric_limits<Number>::epsilon()
191191
) {
192192
const auto nn = xx.size();
193193

ALFI/ALFI/ratf.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ namespace alfi::ratf {
3535
*/
3636
template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
3737
std::enable_if_t<!traits::has_size<Number>::value, Number>
38-
val_mul(const RationalFunction<Number, Container>& rf, Number x) {
38+
val_mul(const RationalFunction<Number, Container>& rf, const Number& x) {
3939
Number n = 0;
4040
for (const auto& c : rf.first) {
4141
n = n * x + c;
@@ -73,7 +73,7 @@ namespace alfi::ratf {
7373
*/
7474
template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
7575
std::enable_if_t<!traits::has_size<Number>::value, Number>
76-
val_div(const RationalFunction<Number, Container>& rf, Number x) {
76+
val_div(const RationalFunction<Number, Container>& rf, const Number& x) {
7777
const auto& numerator = rf.first;
7878
const auto& denominator = rf.second;
7979
Number n = 0;
@@ -116,7 +116,7 @@ namespace alfi::ratf {
116116
*/
117117
template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
118118
std::enable_if_t<!traits::has_size<Number>::value, Number>
119-
val(const RationalFunction<Number, Container>& rf, Number x) {
119+
val(const RationalFunction<Number, Container>& rf, const Number& x) {
120120
if (std::abs(x) <= 1) {
121121
return val_mul(rf, x);
122122
} else {
@@ -167,7 +167,7 @@ namespace alfi::ratf {
167167
@return a pair `{numerator, denominator}` representing the Pade approximant; if an approximant does not exist, an empty pair is returned
168168
*/
169169
template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
170-
RationalFunction<Number,Container> pade(Container<Number> P, SizeT n, SizeT m, Number epsilon = std::numeric_limits<Number>::epsilon()) {
170+
RationalFunction<Number,Container> pade(Container<Number> P, SizeT n, SizeT m, const Number& epsilon = std::numeric_limits<Number>::epsilon()) {
171171
if constexpr (std::is_signed_v<SizeT>) {
172172
if (n < 0 || m < 0) {
173173
return {{}, {}};

ALFI/ALFI/spline/cubic.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -527,25 +527,25 @@ namespace alfi::spline {
527527
_coeffs = std::move(coeffs);
528528
}
529529

530-
Number eval(Number x) const {
530+
Number eval(const Number& x) const {
531531
return eval(x, std::distance(_X.begin(), util::misc::first_leq_or_begin(_X.begin(), _X.end(), x)));
532532
}
533-
Number eval(Number x, SizeT segment) const {
533+
Number eval(const Number& x, SizeT segment) const {
534534
if (_coeffs.empty()) {
535535
return NAN;
536536
} else if (_coeffs.size() == 1) {
537537
return _coeffs[0];
538538
}
539539
segment = std::clamp(segment, static_cast<SizeT>(0), static_cast<SizeT>(_X.size() - 2));
540-
x = x - _X[segment];
541-
return ((_coeffs[4*segment] * x + _coeffs[4*segment+1]) * x + _coeffs[4*segment+2]) * x + _coeffs[4*segment+3];
540+
const Number x_seg = x - _X[segment];
541+
return ((_coeffs[4*segment] * x_seg + _coeffs[4*segment+1]) * x_seg + _coeffs[4*segment+2]) * x_seg + _coeffs[4*segment+3];
542542
}
543543

544544
Container<Number> eval(const Container<Number>& xx, bool sorted = true) const {
545545
Container<Number> result(xx.size());
546546
if (sorted) {
547547
for (SizeT i = 0, i_x = 0; i < xx.size(); ++i) {
548-
const Number x = xx[i];
548+
const Number& x = xx[i];
549549
while (i_x + 1 < _X.size() && x >= _X[i_x+1])
550550
++i_x;
551551
result[i] = eval(x, i_x);
@@ -558,7 +558,7 @@ namespace alfi::spline {
558558
return result;
559559
}
560560

561-
Number operator()(Number x) const {
561+
Number operator()(const Number& x) const {
562562
return eval(x);
563563
}
564564
Container<Number> operator()(const Container<Number>& xx) const {

ALFI/ALFI/spline/linear.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,25 +76,25 @@ namespace alfi::spline {
7676
_coeffs = std::move(coeffs);
7777
}
7878

79-
Number eval(Number x) const {
79+
Number eval(const Number& x) const {
8080
return eval(x, std::distance(_X.begin(), util::misc::first_leq_or_begin(_X.begin(), _X.end(), x)));
8181
}
82-
Number eval(Number x, SizeT segment) const {
82+
Number eval(const Number& x, SizeT segment) const {
8383
if (_coeffs.empty()) {
8484
return NAN;
8585
} else if (_coeffs.size() == 1) {
8686
return _coeffs[0];
8787
}
8888
segment = std::clamp(segment, static_cast<SizeT>(0), static_cast<SizeT>(_X.size() - 2));
89-
x = x - _X[segment];
90-
return _coeffs[2*segment] * x + _coeffs[2*segment+1];
89+
const Number x_seg = x - _X[segment];
90+
return _coeffs[2*segment] * x_seg + _coeffs[2*segment+1];
9191
}
9292

9393
Container<Number> eval(const Container<Number>& xx, bool sorted = true) const {
9494
Container<Number> result(xx.size());
9595
if (sorted) {
9696
for (SizeT i = 0, i_x = 0; i < xx.size(); ++i) {
97-
const Number x = xx[i];
97+
const Number& x = xx[i];
9898
while (i_x + 1 < _X.size() && x >= _X[i_x+1])
9999
++i_x;
100100
result[i] = eval(x, i_x);
@@ -107,7 +107,7 @@ namespace alfi::spline {
107107
return result;
108108
}
109109

110-
Number operator()(Number x) const {
110+
Number operator()(const Number& x) const {
111111
return eval(x);
112112
}
113113
Container<Number> operator()(const Container<Number>& xx) const {

ALFI/ALFI/spline/polyeqv.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,10 @@ namespace alfi::spline {
161161
_coeffs = std::move(coeffs);
162162
}
163163

164-
Number eval(Number x) const {
164+
Number eval(const Number& x) const {
165165
return eval(x, std::distance(_X.begin(), util::misc::first_leq_or_begin(_X.begin(), _X.end(), x)));
166166
}
167-
Number eval(Number x, SizeT segment) const {
167+
Number eval(const Number& x, SizeT segment) const {
168168
if (_coeffs.empty()) {
169169
return NAN;
170170
} else if (_coeffs.size() == 1) {
@@ -173,7 +173,7 @@ namespace alfi::spline {
173173

174174
segment = std::clamp(segment, static_cast<SizeT>(0), static_cast<SizeT>(_X.size() - 2));
175175

176-
x = x - _X[segment];
176+
const Number x_seg = x - _X[segment];
177177

178178
const SizeT n = _X.size();
179179

@@ -191,7 +191,7 @@ namespace alfi::spline {
191191
}
192192

193193
for (SizeT i = 1; i < n; ++i) {
194-
result *= x;
194+
result *= x_seg;
195195
Number current = _coeffs[segment*n+i];
196196
if (std::isnan(current)) {
197197
switch (_evaluation_type) {
@@ -215,7 +215,7 @@ namespace alfi::spline {
215215
Container<Number> result(xx.size());
216216
if (sorted) {
217217
for (SizeT i = 0, i_x = 0; i < xx.size(); ++i) {
218-
const Number x = xx[i];
218+
const Number& x = xx[i];
219219
while (i_x + 1 < _X.size() && x >= _X[i_x+1])
220220
++i_x;
221221
result[i] = eval(x, i_x);
@@ -228,7 +228,7 @@ namespace alfi::spline {
228228
return result;
229229
}
230230

231-
Number operator()(Number x) const {
231+
Number operator()(const Number& x) const {
232232
return eval(x);
233233
}
234234
Container<Number> operator()(const Container<Number>& xx) const {

0 commit comments

Comments
 (0)