FastLED 3.9.15
Loading...
Searching...
No Matches
base.h
Go to the documentation of this file.
1#pragma once
2
3// CRTP base template for signed fixed-point arithmetic and trigonometry.
4// All operations are integer-only in the hot path.
5//
6// Derived classes inherit via protected inheritance and re-expose methods
7// via using declarations for explicit API control.
8
12#include "fl/math/sin32.h"
13#include "fl/stl/stdint.h"
14#include "fl/stl/type_traits.h"
15#include "fl/stl/noexcept.h"
16#include "fl/stl/undef.h" // Undefine abs/min/max macros from Arduino.h
17
19
20namespace fl {
21
22// CRTP base class for fixed-point types.
23// Template parameters:
24// Derived - The concrete type (e.g., s16x16) for CRTP pattern
25// IntBits - Number of integer bits
26// FracBits - Number of fractional bits
27template<typename Derived, int IntBits, int FracBits>
29 public:
31 using raw_type = typename traits::raw_type;
36
37 static constexpr int INT_BITS = IntBits;
38 static constexpr int FRAC_BITS = FracBits;
39
40 protected:
42
43 public:
44
45 // ---- Construction ------------------------------------------------------
46
47 constexpr fixed_point_base() FL_NOEXCEPT = default;
48
49 explicit constexpr fixed_point_base(float f)
50 : mValue(static_cast<raw_type>(f * (static_cast<raw_type>(1) << FRAC_BITS))) {}
51
52 // Raw constructor for constexpr from_raw (matches concrete type RawTag pattern)
53 struct RawTag {};
54 constexpr explicit fixed_point_base(raw_type raw, RawTag) : mValue(raw) {}
55
56 static constexpr FASTLED_FORCE_INLINE Derived from_raw(raw_type raw) {
57 return Derived(raw, typename Derived::RawTag());
58 }
59
60 // ---- Access ------------------------------------------------------------
61
62 constexpr raw_type raw() const { return mValue; }
63 constexpr raw_type to_int() const { return mValue >> FRAC_BITS; }
64 constexpr float to_float() const { return static_cast<float>(mValue) / (static_cast<raw_type>(1) << FRAC_BITS); }
65
66 // ---- Fixed-point arithmetic --------------------------------------------
67
68 constexpr FASTLED_FORCE_INLINE Derived operator*(Derived b) const {
69 return Derived::from_raw(static_cast<raw_type>(
70 (static_cast<intermediate_type>(mValue) * b.mValue) >> FRAC_BITS));
71 }
72
73 constexpr FASTLED_FORCE_INLINE Derived operator/(Derived b) const {
74 return Derived::from_raw(static_cast<raw_type>(
75 (static_cast<intermediate_type>(mValue) * (static_cast<intermediate_type>(1) << FRAC_BITS)) / b.mValue));
76 }
77
78 constexpr FASTLED_FORCE_INLINE Derived operator+(Derived b) const {
79 return Derived::from_raw(static_cast<raw_type>(
80 static_cast<unsigned_raw_type>(mValue) + static_cast<unsigned_raw_type>(b.mValue)));
81 }
82
83 constexpr FASTLED_FORCE_INLINE Derived operator-(Derived b) const {
84 return Derived::from_raw(static_cast<raw_type>(
85 static_cast<unsigned_raw_type>(mValue) - static_cast<unsigned_raw_type>(b.mValue)));
86 }
87
88 constexpr FASTLED_FORCE_INLINE Derived operator-() const {
89 return Derived::from_raw(static_cast<raw_type>(
90 0u - static_cast<unsigned_raw_type>(mValue)));
91 }
92
93 constexpr FASTLED_FORCE_INLINE Derived operator>>(int shift) const {
94 return Derived::from_raw(mValue >> shift);
95 }
96
97 // ---- Scalar multiply (no fixed-point shift) ----------------------------
98
99 constexpr FASTLED_FORCE_INLINE Derived operator*(raw_type scalar) const {
100 return Derived::from_raw(mValue * scalar);
101 }
102
103 friend constexpr Derived operator*(raw_type scalar, Derived fp) {
104 return Derived::from_raw(scalar * fp.mValue);
105 }
106
107 // ---- Comparisons -------------------------------------------------------
108
109 constexpr bool operator<(Derived b) const { return mValue < b.mValue; }
110 constexpr bool operator>(Derived b) const { return mValue > b.mValue; }
111 constexpr bool operator<=(Derived b) const { return mValue <= b.mValue; }
112 constexpr bool operator>=(Derived b) const { return mValue >= b.mValue; }
113 constexpr bool operator==(Derived b) const { return mValue == b.mValue; }
114 constexpr bool operator!=(Derived b) const { return mValue != b.mValue; }
115
116 // ---- Math ---------------------------------------------------------------
117
118 static constexpr FASTLED_FORCE_INLINE Derived mod(Derived a, Derived b) {
119 return Derived::from_raw(a.mValue % b.mValue);
120 }
121
122 static constexpr FASTLED_FORCE_INLINE Derived floor(Derived x) {
123 return Derived::from_raw(x.mValue & ~(raw_type((Derived::SCALE) - 1)));
124 }
125
126 static constexpr FASTLED_FORCE_INLINE Derived ceil(Derived x) {
127 return Derived::from_raw((x.mValue & ~(raw_type((Derived::SCALE) - 1))) +
128 ((x.mValue & raw_type((Derived::SCALE) - 1)) ? (Derived::SCALE) : 0));
129 }
130
131 static constexpr FASTLED_FORCE_INLINE Derived fract(Derived x) {
132 return Derived::from_raw(x.mValue & raw_type((Derived::SCALE) - 1));
133 }
134
135 static constexpr FASTLED_FORCE_INLINE Derived abs(Derived x) {
136 return Derived::from_raw(x.mValue < 0 ? -x.mValue : x.mValue);
137 }
138
139 static constexpr FASTLED_FORCE_INLINE int sign(Derived x) {
140 return x.mValue > 0 ? 1 : (x.mValue < 0 ? -1 : 0);
141 }
142
143 static constexpr FASTLED_FORCE_INLINE Derived lerp(Derived a, Derived b, Derived t) {
144 return a + (b - a) * t;
145 }
146
147 static constexpr FASTLED_FORCE_INLINE Derived clamp(Derived x, Derived lo, Derived hi) {
148 return x < lo ? lo : (x > hi ? hi : x);
149 }
150
151 static constexpr FASTLED_FORCE_INLINE Derived step(Derived edge, Derived x) {
152 return x < edge ? Derived() : Derived(1.0f);
153 }
154
155 static FASTLED_FORCE_INLINE Derived smoothstep(Derived edge0, Derived edge1, Derived x) {
156 constexpr Derived zero(0.0f);
157 constexpr Derived one(1.0f);
158 constexpr Derived two(2.0f);
159 constexpr Derived three(3.0f);
160 Derived t = clamp((x - edge0) / (edge1 - edge0), zero, one);
161 return t * t * (three - two * t);
162 }
163
164 // ---- Inverse Trigonometry (pure fixed-point) ----------------------------
165
166 static FASTLED_FORCE_INLINE Derived atan(Derived x) {
167 constexpr Derived one(1.0f);
168 constexpr Derived pi_over_2(1.5707963f);
169 bool neg = x.mValue < 0;
170 Derived ax = abs(x);
171 Derived result;
172 if (ax <= one) {
173 result = atan_unit(ax);
174 } else {
175 result = pi_over_2 - atan_unit(one / ax);
176 }
177 return neg ? -result : result;
178 }
179
180 static FASTLED_FORCE_INLINE Derived atan2(Derived y, Derived x) {
181 constexpr Derived pi(3.1415926f);
182 constexpr Derived pi_over_2(1.5707963f);
183 if (x.mValue == 0 && y.mValue == 0) return Derived();
184 if (x.mValue == 0) return y.mValue > 0 ? pi_over_2 : -pi_over_2;
185 if (y.mValue == 0) return x.mValue > 0 ? Derived() : pi;
186 Derived ax = abs(x);
187 Derived ay = abs(y);
188 Derived a;
189 if (ax >= ay) {
190 a = atan_unit(ay / ax);
191 } else {
192 a = pi_over_2 - atan_unit(ax / ay);
193 }
194 if (x.mValue < 0) a = pi - a;
195 if (y.mValue < 0) a = -a;
196 return a;
197 }
198
199 static FASTLED_FORCE_INLINE Derived asin(Derived x) {
200 constexpr Derived one(1.0f);
201 return atan2(x, sqrt(one - x * x));
202 }
203
204 static FASTLED_FORCE_INLINE Derived acos(Derived x) {
205 constexpr Derived one(1.0f);
206 return atan2(sqrt(one - x * x), x);
207 }
208
209 static constexpr FASTLED_FORCE_INLINE Derived sqrt(Derived x) {
210 return x.mValue <= 0 ? Derived() : sqrt_impl(x, fl::bool_constant<traits::USE_ISQRT32>());
211 }
212
213 private:
214 // sqrt implementation for i16 types (use isqrt32)
215 static constexpr FASTLED_FORCE_INLINE Derived sqrt_impl(Derived x, fl::true_type) {
216 return Derived::from_raw(static_cast<raw_type>(
217 fl::isqrt32(static_cast<u32>(x.mValue) << FRAC_BITS)));
218 }
219
220 // sqrt implementation for i32 types (use isqrt64)
221 static constexpr FASTLED_FORCE_INLINE Derived sqrt_impl(Derived x, fl::false_type) {
222 return Derived::from_raw(static_cast<raw_type>(
223 fl::isqrt64(static_cast<u64>(x.mValue) << FRAC_BITS)));
224 }
225
226 public:
227
228 static constexpr FASTLED_FORCE_INLINE Derived rsqrt(Derived x) {
229 return sqrt(x).mValue == 0
230 ? Derived()
231 : Derived::from_raw(static_cast<raw_type>(1) << FRAC_BITS) / sqrt(x);
232 }
233
234 static FASTLED_FORCE_INLINE Derived pow(Derived base, Derived exp) {
235 if (base.mValue <= 0) return Derived();
236 constexpr Derived one(1.0f);
237 if (exp.mValue == 0) return one;
238 if (base == one) return one;
239 // Snap base values within ~2 ULPs of 1.0 to exactly 1.0 to dodge the
240 // log2(1+t) minimax polynomial's upper-endpoint residual (off by
241 // 0.000443 at t=1, which amplifies via exp2 to ~50-100 LSB at u16
242 // scale). See #2969.
243 constexpr raw_type kNearOneEpsilon = static_cast<raw_type>(2);
244 constexpr raw_type kOneRaw = static_cast<raw_type>(Derived::SCALE);
245 if (base.mValue >= static_cast<raw_type>(kOneRaw - kNearOneEpsilon) &&
246 base.mValue <= kOneRaw) {
247 return one;
248 }
249 return exp2_fp(exp * log2_fp(base));
250 }
251
252 // ---- Member function versions (operate on *this) -----------------------
253
254 constexpr FASTLED_FORCE_INLINE Derived floor() const {
255 return floor(*static_cast<const Derived*>(this));
256 }
257
258 constexpr FASTLED_FORCE_INLINE Derived ceil() const {
259 return ceil(*static_cast<const Derived*>(this));
260 }
261
262 constexpr FASTLED_FORCE_INLINE Derived fract() const {
263 return fract(*static_cast<const Derived*>(this));
264 }
265
266 constexpr FASTLED_FORCE_INLINE Derived abs() const {
267 return abs(*static_cast<const Derived*>(this));
268 }
269
270 constexpr FASTLED_FORCE_INLINE int sign() const {
271 return sign(*static_cast<const Derived*>(this));
272 }
273
274 FASTLED_FORCE_INLINE Derived sin() const {
275 return sin(*static_cast<const Derived*>(this));
276 }
277
278 FASTLED_FORCE_INLINE Derived cos() const {
279 return cos(*static_cast<const Derived*>(this));
280 }
281
282 FASTLED_FORCE_INLINE Derived atan() const {
283 return atan(*static_cast<const Derived*>(this));
284 }
285
286 FASTLED_FORCE_INLINE Derived asin() const {
287 return asin(*static_cast<const Derived*>(this));
288 }
289
290 FASTLED_FORCE_INLINE Derived acos() const {
291 return acos(*static_cast<const Derived*>(this));
292 }
293
294 constexpr FASTLED_FORCE_INLINE Derived sqrt() const {
295 return sqrt(*static_cast<const Derived*>(this));
296 }
297
298 constexpr FASTLED_FORCE_INLINE Derived rsqrt() const {
299 return rsqrt(*static_cast<const Derived*>(this));
300 }
301
302 // ---- Trigonometry ------------------------------------------------------
303
304 static FASTLED_FORCE_INLINE Derived sin(Derived angle) {
305 return Derived::from_raw(static_cast<raw_type>(
307 }
308
309 static FASTLED_FORCE_INLINE Derived cos(Derived angle) {
310 return Derived::from_raw(static_cast<raw_type>(
312 }
313
314 // Combined sin+cos from radians. Output in [-1, 1].
315 // Uses sincos32 which shares angle decomposition for ~30% fewer ops.
316 static FASTLED_FORCE_INLINE void sincos(Derived angle, Derived &out_sin,
317 Derived &out_cos) {
318 u32 a24 = angle_to_a24(angle);
319 SinCos32 sc = fl::sincos32(a24);
320 out_sin = Derived::from_raw(static_cast<raw_type>(sc.sin_val >> traits::SIN_COS_SHIFT));
321 out_cos = Derived::from_raw(static_cast<raw_type>(sc.cos_val >> traits::SIN_COS_SHIFT));
322 }
323
324 private:
325 // Returns 0-based position of highest set bit, or -1 if v==0.
326 // C++11 constexpr: recursive helper with accumulator.
327 static constexpr FASTLED_FORCE_INLINE int highest_bit(u32 v) {
328 return v == 0 ? -1 : _highest_bit_step(v, 0);
329 }
330
331 static constexpr int _highest_bit_step(u32 v, int r) {
332 return (v & 0xFFFF0000u) ? _highest_bit_step(v >> 16, r + 16)
333 : (v & 0x0000FF00u) ? _highest_bit_step(v >> 8, r + 8)
334 : (v & 0x000000F0u) ? _highest_bit_step(v >> 4, r + 4)
335 : (v & 0x0000000Cu) ? _highest_bit_step(v >> 2, r + 2)
336 : (v & 0x00000002u) ? r + 1
337 : r;
338 }
339
340 // Fixed-point log base 2 for positive values.
341 // Uses 4-term minimax polynomial for log2(1+t), t in [0,1).
342 // Horner evaluation uses intermediate precision (IFRAC) to minimize
343 // rounding error, then converts back to FRAC_BITS.
344 static FASTLED_FORCE_INLINE Derived log2_fp(Derived x) {
345 constexpr int IFRAC = traits::IFRAC;
346
347 unsigned_raw_type val = static_cast<unsigned_raw_type>(x.mValue);
348 int msb = highest_bit(static_cast<u32>(val));
349 raw_type int_part = msb - FRAC_BITS;
350 raw_type t;
351 if (msb >= FRAC_BITS) {
352 t = static_cast<raw_type>(
353 (val >> (msb - FRAC_BITS)) - (static_cast<unsigned_raw_type>(1) << FRAC_BITS));
354 } else {
355 t = static_cast<raw_type>(
356 (val << (FRAC_BITS - msb)) - (static_cast<unsigned_raw_type>(1) << FRAC_BITS));
357 }
358
359 // 4-term minimax coefficients for log2(1+t), t in [0,1).
360 // Coefficients scaled by 2^IFRAC.
361 // Use poly_intermediate_type (i32 or i64 based on IFRAC).
362 using poly_type = poly_intermediate_type;
363 constexpr poly_type c0 = static_cast<poly_type>(1.44179 * (1LL << IFRAC));
364 constexpr poly_type c1 = static_cast<poly_type>(-0.69907 * (1LL << IFRAC));
365 constexpr poly_type c2 = static_cast<poly_type>(0.36348 * (1LL << IFRAC));
366 constexpr poly_type c3 = static_cast<poly_type>(-0.10660 * (1LL << IFRAC));
367
368 // Extend t to IFRAC fractional bits
369 poly_type t_ifrac = static_cast<poly_type>(t) << (IFRAC - FRAC_BITS);
370
371 // Horner: t * (c0 + t * (c1 + t * (c2 + t * c3)))
372 return log2_horner(int_part, t_ifrac, c0, c1, c2, c3, fl::bool_constant<(IFRAC <= 16)>());
373 }
374
375 // log2 Horner evaluation for i32 intermediates (IFRAC <= 16)
376 template<typename PolyType>
377 static FASTLED_FORCE_INLINE Derived log2_horner(raw_type int_part, PolyType t_ifrac,
378 PolyType c0, PolyType c1, PolyType c2, PolyType c3,
380 constexpr int IFRAC = traits::IFRAC;
381 PolyType acc = c3;
382 acc = c2 + static_cast<PolyType>((static_cast<i64>(acc) * t_ifrac) >> IFRAC);
383 acc = c1 + static_cast<PolyType>((static_cast<i64>(acc) * t_ifrac) >> IFRAC);
384 acc = c0 + static_cast<PolyType>((static_cast<i64>(acc) * t_ifrac) >> IFRAC);
385 PolyType frac_part = static_cast<PolyType>((static_cast<i64>(acc) * t_ifrac) >> IFRAC);
386 raw_type frac_result = static_cast<raw_type>(frac_part >> (IFRAC - FRAC_BITS));
387 return Derived::from_raw(static_cast<raw_type>(static_cast<unsigned_raw_type>(int_part) << FRAC_BITS) + frac_result);
388 }
389
390 // log2 Horner evaluation for i64 intermediates (IFRAC > 16)
391 template<typename PolyType>
392 static FASTLED_FORCE_INLINE Derived log2_horner(raw_type int_part, PolyType t_ifrac,
393 PolyType c0, PolyType c1, PolyType c2, PolyType c3,
395 constexpr int IFRAC = traits::IFRAC;
396 PolyType acc = c3;
397 acc = c2 + ((acc * t_ifrac) >> IFRAC);
398 acc = c1 + ((acc * t_ifrac) >> IFRAC);
399 acc = c0 + ((acc * t_ifrac) >> IFRAC);
400 PolyType frac_part = (acc * t_ifrac) >> IFRAC;
401 raw_type frac_result = static_cast<raw_type>(frac_part >> (IFRAC - FRAC_BITS));
402 return Derived::from_raw(static_cast<raw_type>(static_cast<unsigned_raw_type>(int_part) << FRAC_BITS) + frac_result);
403 }
404
405 // Fixed-point 2^x. Uses 4-term minimax polynomial for 2^t, t in [0,1).
406 // Horner evaluation uses intermediate precision (IFRAC) to minimize
407 // rounding error, then converts back to FRAC_BITS.
408 static FASTLED_FORCE_INLINE Derived exp2_fp(Derived x) {
409 constexpr int IFRAC = traits::IFRAC;
410
411 Derived fl_val = floor(x);
412 Derived fr = x - fl_val;
413 raw_type n = fl_val.mValue >> FRAC_BITS;
414 if (n >= INT_BITS - 1) return Derived::from_raw(traits::MAX_OVERFLOW);
415 if (n < -FRAC_BITS) return Derived();
416
417 raw_type int_pow;
418 if (n >= 0) {
419 int_pow = static_cast<raw_type>(static_cast<unsigned_raw_type>(1) << FRAC_BITS) << n;
420 } else {
421 int_pow = static_cast<raw_type>(static_cast<unsigned_raw_type>(1) << FRAC_BITS) >> (-n);
422 }
423
424 // 4-term minimax coefficients for 2^t - 1, t in [0,1).
425 // Coefficients scaled by 2^IFRAC.
426 using poly_type = poly_intermediate_type;
427 constexpr poly_type d0 = static_cast<poly_type>(0.69316 * (1LL << IFRAC));
428 constexpr poly_type d1 = static_cast<poly_type>(0.24071 * (1LL << IFRAC));
429 constexpr poly_type d2 = static_cast<poly_type>(0.05336 * (1LL << IFRAC));
430 constexpr poly_type d3 = static_cast<poly_type>(0.01276 * (1LL << IFRAC));
431
432 // Extend fr to IFRAC fractional bits
433 poly_type fr_ifrac = static_cast<poly_type>(fr.mValue) << (IFRAC - FRAC_BITS);
434
435 // Horner: 1 + fr * (d0 + fr * (d1 + fr * (d2 + fr * d3)))
436 return exp2_horner(int_pow, fr_ifrac, d0, d1, d2, d3, fl::bool_constant<(IFRAC <= 16)>());
437 }
438
439 // exp2 Horner evaluation for i32 intermediates (IFRAC <= 16)
440 template<typename PolyType>
441 static FASTLED_FORCE_INLINE Derived exp2_horner(raw_type int_pow, PolyType fr_ifrac,
442 PolyType d0, PolyType d1, PolyType d2, PolyType d3,
444 constexpr int IFRAC = traits::IFRAC;
445 constexpr PolyType one_ifrac = static_cast<PolyType>(1) << IFRAC;
446 PolyType acc = d3;
447 acc = d2 + static_cast<PolyType>((static_cast<i64>(acc) * fr_ifrac) >> IFRAC);
448 acc = d1 + static_cast<PolyType>((static_cast<i64>(acc) * fr_ifrac) >> IFRAC);
449 acc = d0 + static_cast<PolyType>((static_cast<i64>(acc) * fr_ifrac) >> IFRAC);
450 PolyType frac_pow_ifrac = one_ifrac + static_cast<PolyType>((static_cast<i64>(acc) * fr_ifrac) >> IFRAC);
451 raw_type frac_pow = static_cast<raw_type>(frac_pow_ifrac >> (IFRAC - FRAC_BITS));
452 intermediate_type result = (static_cast<intermediate_type>(int_pow) * frac_pow) >> FRAC_BITS;
453 return Derived::from_raw(static_cast<raw_type>(result));
454 }
455
456 // exp2 Horner evaluation for i64 intermediates (IFRAC > 16)
457 template<typename PolyType>
458 static FASTLED_FORCE_INLINE Derived exp2_horner(raw_type int_pow, PolyType fr_ifrac,
459 PolyType d0, PolyType d1, PolyType d2, PolyType d3,
461 constexpr int IFRAC = traits::IFRAC;
462 constexpr PolyType one_ifrac = static_cast<PolyType>(1) << IFRAC;
463 PolyType acc = d3;
464 acc = d2 + ((acc * fr_ifrac) >> IFRAC);
465 acc = d1 + ((acc * fr_ifrac) >> IFRAC);
466 acc = d0 + ((acc * fr_ifrac) >> IFRAC);
467 PolyType frac_pow_ifrac = one_ifrac + ((acc * fr_ifrac) >> IFRAC);
468 raw_type frac_pow = static_cast<raw_type>(frac_pow_ifrac >> (IFRAC - FRAC_BITS));
469 intermediate_type result = (static_cast<intermediate_type>(int_pow) * frac_pow) >> FRAC_BITS;
470 return Derived::from_raw(static_cast<raw_type>(result));
471 }
472
473 // Converts radians to sin32/cos32 input format.
474 // 256/(2*PI) — converts radians to sin32/cos32 format.
475 static constexpr i32 RAD_TO_24 = 2670177;
476 static constexpr FASTLED_FORCE_INLINE u32 angle_to_a24(Derived angle) {
477 // Always use i64 for multiplication to avoid overflow
478 return static_cast<u32>(
479 (static_cast<i64>(angle.mValue) * RAD_TO_24) >> FRAC_BITS);
480 }
481
482 // Polynomial atan for t in [0, 1]. Returns [0, π/4].
483 // 7th-order minimax: atan(t) ≈ t * (c0 + t² * (c1 + t² * (c2 + t² * c3)))
484 // Coefficients optimized via coordinate descent on s16x16 quantization grid.
485 static FASTLED_FORCE_INLINE Derived atan_unit(Derived t) {
486 constexpr Derived c0(0.9998779297f);
487 constexpr Derived c1(-0.3269348145f);
488 constexpr Derived c2(0.1594085693f);
489 constexpr Derived c3(-0.0472106934f);
490 Derived t2 = t * t;
491 return t * (c0 + t2 * (c1 + t2 * (c2 + t2 * c3)));
492 }
493};
494
495} // namespace fl
496
typename traits::unsigned_raw_type unsigned_raw_type
Definition base.h:32
static constexpr FASTLED_FORCE_INLINE int highest_bit(u32 v)
Definition base.h:327
static constexpr FASTLED_FORCE_INLINE Derived clamp(Derived x, Derived lo, Derived hi)
Definition base.h:147
static FASTLED_FORCE_INLINE Derived log2_horner(raw_type int_part, PolyType t_ifrac, PolyType c0, PolyType c1, PolyType c2, PolyType c3, fl::true_type)
Definition base.h:377
constexpr fixed_point_base() FL_NOEXCEPT=default
constexpr bool operator!=(Derived b) const
Definition base.h:114
static FASTLED_FORCE_INLINE void sincos(Derived angle, Derived &out_sin, Derived &out_cos)
Definition base.h:316
static constexpr FASTLED_FORCE_INLINE Derived rsqrt(Derived x)
Definition base.h:228
FASTLED_FORCE_INLINE Derived atan() const
Definition base.h:282
constexpr FASTLED_FORCE_INLINE Derived operator*(Derived b) const
Definition base.h:68
typename traits::intermediate_type intermediate_type
Definition base.h:33
constexpr FASTLED_FORCE_INLINE Derived sqrt() const
Definition base.h:294
static constexpr FASTLED_FORCE_INLINE Derived sqrt(Derived x)
Definition base.h:209
static FASTLED_FORCE_INLINE Derived smoothstep(Derived edge0, Derived edge1, Derived x)
Definition base.h:155
static constexpr FASTLED_FORCE_INLINE Derived lerp(Derived a, Derived b, Derived t)
Definition base.h:143
constexpr fixed_point_base(raw_type raw, RawTag)
Definition base.h:54
fixed_point_traits< IntBits, FracBits > traits
Definition base.h:30
static constexpr int FRAC_BITS
Definition base.h:38
constexpr float to_float() const
Definition base.h:64
typename traits::raw_type raw_type
Definition base.h:31
static FASTLED_FORCE_INLINE Derived atan2(Derived y, Derived x)
Definition base.h:180
constexpr FASTLED_FORCE_INLINE Derived fract() const
Definition base.h:262
constexpr FASTLED_FORCE_INLINE Derived operator-(Derived b) const
Definition base.h:83
constexpr bool operator<(Derived b) const
Definition base.h:109
constexpr FASTLED_FORCE_INLINE Derived ceil() const
Definition base.h:258
static constexpr FASTLED_FORCE_INLINE Derived sqrt_impl(Derived x, fl::false_type)
Definition base.h:221
static FASTLED_FORCE_INLINE Derived sin(Derived angle)
Definition base.h:304
static constexpr FASTLED_FORCE_INLINE Derived fract(Derived x)
Definition base.h:131
raw_type mValue
Definition base.h:41
FASTLED_FORCE_INLINE Derived asin() const
Definition base.h:286
constexpr FASTLED_FORCE_INLINE Derived operator/(Derived b) const
Definition base.h:73
static constexpr FASTLED_FORCE_INLINE Derived ceil(Derived x)
Definition base.h:126
constexpr FASTLED_FORCE_INLINE Derived operator-() const
Definition base.h:88
static constexpr int _highest_bit_step(u32 v, int r)
Definition base.h:331
constexpr FASTLED_FORCE_INLINE Derived floor() const
Definition base.h:254
constexpr FASTLED_FORCE_INLINE Derived rsqrt() const
Definition base.h:298
static FASTLED_FORCE_INLINE Derived acos(Derived x)
Definition base.h:204
static FASTLED_FORCE_INLINE Derived log2_fp(Derived x)
Definition base.h:344
static constexpr FASTLED_FORCE_INLINE Derived from_raw(raw_type raw)
Definition base.h:56
constexpr bool operator>=(Derived b) const
Definition base.h:112
static constexpr i32 RAD_TO_24
Definition base.h:475
constexpr raw_type raw() const
Definition base.h:62
static FASTLED_FORCE_INLINE Derived atan_unit(Derived t)
Definition base.h:485
static constexpr FASTLED_FORCE_INLINE int sign(Derived x)
Definition base.h:139
typename traits::unsigned_intermediate_type unsigned_intermediate_type
Definition base.h:34
static constexpr FASTLED_FORCE_INLINE u32 angle_to_a24(Derived angle)
Definition base.h:476
typename traits::poly_intermediate_type poly_intermediate_type
Definition base.h:35
static FASTLED_FORCE_INLINE Derived exp2_horner(raw_type int_pow, PolyType fr_ifrac, PolyType d0, PolyType d1, PolyType d2, PolyType d3, fl::false_type)
Definition base.h:458
static FASTLED_FORCE_INLINE Derived exp2_horner(raw_type int_pow, PolyType fr_ifrac, PolyType d0, PolyType d1, PolyType d2, PolyType d3, fl::true_type)
Definition base.h:441
constexpr bool operator>(Derived b) const
Definition base.h:110
constexpr bool operator==(Derived b) const
Definition base.h:113
static constexpr FASTLED_FORCE_INLINE Derived abs(Derived x)
Definition base.h:135
FASTLED_FORCE_INLINE Derived cos() const
Definition base.h:278
constexpr raw_type to_int() const
Definition base.h:63
static constexpr FASTLED_FORCE_INLINE Derived step(Derived edge, Derived x)
Definition base.h:151
constexpr FASTLED_FORCE_INLINE int sign() const
Definition base.h:270
static FASTLED_FORCE_INLINE Derived pow(Derived base, Derived exp)
Definition base.h:234
static FASTLED_FORCE_INLINE Derived log2_horner(raw_type int_part, PolyType t_ifrac, PolyType c0, PolyType c1, PolyType c2, PolyType c3, fl::false_type)
Definition base.h:392
static constexpr FASTLED_FORCE_INLINE Derived sqrt_impl(Derived x, fl::true_type)
Definition base.h:215
constexpr FASTLED_FORCE_INLINE Derived abs() const
Definition base.h:266
constexpr FASTLED_FORCE_INLINE Derived operator>>(int shift) const
Definition base.h:93
static constexpr FASTLED_FORCE_INLINE Derived mod(Derived a, Derived b)
Definition base.h:118
FASTLED_FORCE_INLINE Derived sin() const
Definition base.h:274
constexpr FASTLED_FORCE_INLINE Derived operator+(Derived b) const
Definition base.h:78
static FASTLED_FORCE_INLINE Derived cos(Derived angle)
Definition base.h:309
static FASTLED_FORCE_INLINE Derived exp2_fp(Derived x)
Definition base.h:408
constexpr FASTLED_FORCE_INLINE Derived operator*(raw_type scalar) const
Definition base.h:99
static constexpr FASTLED_FORCE_INLINE Derived floor(Derived x)
Definition base.h:122
FASTLED_FORCE_INLINE Derived acos() const
Definition base.h:290
static constexpr int INT_BITS
Definition base.h:37
static FASTLED_FORCE_INLINE Derived asin(Derived x)
Definition base.h:199
static FASTLED_FORCE_INLINE Derived atan(Derived x)
Definition base.h:166
friend constexpr Derived operator*(raw_type scalar, Derived fp)
Definition base.h:103
constexpr bool operator<=(Derived b) const
Definition base.h:111
#define constexpr
Declares that it is possible to evaluate a value at compile time, introduced in C++11.
Definition cpp_compat.h:15
integral_constant< bool, B > bool_constant
Definition s16x16x4.h:32
integral_constant< bool, true > true_type
Definition s16x16x4.h:27
integral_constant< bool, false > false_type
Definition s16x16x4.h:28
FASTLED_FORCE_INLINE i32 cos32(u32 angle) FL_NOEXCEPT
Definition sin32.h:81
FASTLED_FORCE_INLINE i32 sin32(u32 angle) FL_NOEXCEPT
Definition sin32.h:59
fl::i64 i64
Definition s16x16x4.h:222
expected< T, E > result
Alias for expected (Rust-style naming)
Definition result.h:31
FASTLED_FORCE_INLINE SinCos32 sincos32(u32 angle) FL_NOEXCEPT
Definition sin32.h:88
fl::u64 u64
Definition s16x16x4.h:221
enable_if< is_fixed_point< T >::value, T >::type exp(T x) FL_NOEXCEPT
FL_OPTIMIZE_FUNCTION constexpr u16 isqrt32(u32 x) FL_NOEXCEPT
Definition isqrt.h:53
FL_OPTIMIZE_FUNCTION constexpr u32 isqrt64(u64 x) FL_NOEXCEPT
Definition isqrt.h:58
Base definition for an LED controller.
Definition crgb.hpp:179
i32 sin_val
Definition sin32.h:25
i32 cos_val
Definition sin32.h:26
#define FL_OPTIMIZATION_LEVEL_O3_BEGIN
#define FASTLED_FORCE_INLINE
#define FL_OPTIMIZATION_LEVEL_O3_END
#define FL_NOEXCEPT
fl::conditional_t<(TOTAL_BITS<=16), i16, i32 > raw_type
Definition traits.h:106
static constexpr int SIN_COS_SHIFT
Definition traits.h:136
fl::conditional_t<(IFRAC<=16), i32, i64 > poly_intermediate_type
Definition traits.h:127
static constexpr auto MAX_OVERFLOW
Definition traits.h:130
fl::conditional_t<(TOTAL_BITS<=16), u16, u32 > unsigned_raw_type
Definition traits.h:107
static constexpr int IFRAC
Definition traits.h:120
fl::conditional_t<(TOTAL_BITS<=16), i32, i64 > intermediate_type
Definition traits.h:110
fl::conditional_t<(TOTAL_BITS<=16), u32, u64 > unsigned_intermediate_type
Definition traits.h:111