Skip to content

Commit 0dfd803

Browse files
committed
Avoid reevaluating arguments.
_round, _constrain and _sign currently reevaluate their arguments, which wastes CPU cycles. In torque/foc_current mode, this fix saves about 300ns/foc loop (about 2% of total CPU usage). In other modes, especially estimated_current, it saves more.
1 parent 7f9c45f commit 0dfd803

1 file changed

Lines changed: 33 additions & 5 deletions

File tree

src/common/foc_utils.h

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,41 @@
22
#define FOCUTILS_LIB_H
33

44
#include "Arduino.h"
5+
#include <type_traits>
6+
7+
template<typename T>
8+
constexpr inline int _sign(T val) {
9+
return __builtin_signbit(val);
10+
}
511

6-
// sign function
7-
#define _sign(a) ( ( (a) < 0 ) ? -1 : ( (a) > 0 ) )
812
#ifndef _round
9-
#define _round(x) ((x)>=0?(long)((x)+0.5f):(long)((x)-0.5f))
13+
// Use enable_if to select the roundf function for single precision floats.
14+
// This improves performance when -ffast-math is not set.
15+
template<typename T>
16+
constexpr inline std::enable_if<std::is_same<T, float>::value, long>::type _round(T x) {
17+
return __builtin_roundf(x);
18+
}
19+
template<typename T>
20+
constexpr inline std::enable_if<std::is_same<T, double>::value, long>::type _round(T x) {
21+
return __builtin_round(x);
22+
}
1023
#endif
11-
#define _constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
24+
25+
// Use enable_if to select the fastest implementation according to the amt type.
26+
// Using __builtin_fXf is measurably faster than using the ternary approach.
27+
template<typename T, typename L, typename H>
28+
constexpr inline std::enable_if<std::is_integral<T>::value, T>::type _constrain(T amt, L low, H high) {
29+
return (amt < low) ? low : (amt > high) ? high : amt;
30+
}
31+
template<typename T, typename L, typename H>
32+
constexpr inline std::enable_if<std::is_same<T, float>::value, T>::type _constrain(T amt, L low, H high) {
33+
return __builtin_fmaxf(low, __builtin_fminf(high, amt));
34+
}
35+
template<typename T, typename L, typename H>
36+
constexpr inline std::enable_if<std::is_same<T, double>::value, T>::type _constrain(T amt, L low, H high) {
37+
return __builtin_fmax(low, __builtin_fmin(high, amt));
38+
}
39+
1240
#define _sqrt(a) (_sqrtApprox(a))
1341
#define _isset(a) ( (a) != (NOT_SET) )
1442
#define _UNUSED(v) (void) (v)
@@ -121,4 +149,4 @@ float _electricalAngle(float shaft_angle, int pole_pairs);
121149
*/
122150
float _sqrtApprox(float value);
123151

124-
#endif
152+
#endif

0 commit comments

Comments
 (0)