FastLED 3.10.8
Loading...
Searching...
No Matches
s16x16.h
Go to the documentation of this file.
1#pragma once
2
3// Signed 16.16 fixed-point arithmetic and trigonometry.
4// All operations are integer-only in the hot path.
5
6#include "fl/stl/stdint.h"
8#include "fl/math/sin32.h"
13#include "fl/stl/noexcept.h"
14#include "fl/stl/undef.h" // Undefine abs/min/max macros from Arduino.h
15
17
18namespace fl {
19
20// Signed 16.16 fixed-point value type.
21class s16x16 {
22 public:
23 static constexpr int INT_BITS = 16;
24 static constexpr int FRAC_BITS = 16;
25 static constexpr i32 SCALE = static_cast<i32>(1) << FRAC_BITS;
26
27 // ---- Construction ------------------------------------------------------
28
29 constexpr s16x16() FL_NO_EXCEPT = default;
30
31 explicit constexpr s16x16(float f) FL_NO_EXCEPT
32 : mValue(static_cast<i32>(f * (SCALE))) {}
33
34 // Integer constructor — any integer width (portable: AVR 16-bit int, ARM/x86 32-bit).
35 // Compile error if constexpr value exceeds INT_BITS range.
36 template <typename IntT, detail::enable_if_integer_t<IntT> = 0>
39
40 // Auto-promotion from other fixed-point types
41 // Enabled only when both INT_BITS and FRAC_BITS can be promoted (no demotion)
42 template <typename OtherFP>
43 constexpr s16x16(const OtherFP& other,
44 typename fl::enable_if<
45 (OtherFP::INT_BITS <= INT_BITS) &&
46 (OtherFP::FRAC_BITS <= FRAC_BITS) &&
47 (OtherFP::INT_BITS != INT_BITS || OtherFP::FRAC_BITS != FRAC_BITS),
48 int>::type = 0)
49 FL_NO_EXCEPT : mValue(static_cast<i32>(
50 static_cast<i64>(other.raw()) << (FRAC_BITS - OtherFP::FRAC_BITS))) {}
51
52 // Raw constructor for C++11 constexpr from_raw
53 struct RawTag {};
54 constexpr explicit s16x16(i32 raw, RawTag) FL_NO_EXCEPT : mValue(raw) {}
55
57 return s16x16(raw, RawTag());
58 }
59
60 // ---- Access ------------------------------------------------------------
61
62 constexpr i32 raw() const FL_NO_EXCEPT { return mValue; }
63 constexpr i32 to_int() const FL_NO_EXCEPT { return mValue >> FRAC_BITS; }
64 constexpr float to_float() const FL_NO_EXCEPT { return static_cast<float>(mValue) / (SCALE); }
65
66 // ---- Fixed-point arithmetic --------------------------------------------
67
68#if defined(__riscv) && (__riscv_xlen == 32)
69 // RV32: Use mul+mulh inline asm to avoid expensive 64-bit widening multiply.
70 // Extracts bits [47:16] of the 64-bit product for Q16.16 fixed-point.
72 i32 lo, hi;
73 asm("mul %0, %2, %3\n\t"
74 "mulh %1, %2, %3"
75 : "=&r"(lo), "=&r"(hi)
76 : "r"(mValue), "r"(b.mValue));
77 return from_raw(static_cast<i32>(
78 (static_cast<u32>(lo) >> 16) | (static_cast<u32>(hi) << 16)));
79 }
80#else
82 return from_raw(static_cast<i32>(
83 (static_cast<i64>(mValue) * b.mValue) >> FRAC_BITS));
84 }
85#endif
86
88#if FL_FIXED_POINT_NARROW_DIVIDE
89 // Same value as the expression below, without the 64-bit divide that
90 // costs a libgcc call on a core whose divider is 32 bits wide.
91 // FastLED#4307 measured that call at 47x the cost of `s8x8`'s single
92 // `SDIV`, and 36x scalar float. Magnitudes go through the unsigned
93 // routine and the sign is reapplied, which also gives the
94 // truncate-toward-zero that C++ integer division specifies.
95 const u32 numerator = mValue < 0
96 ? static_cast<u32>(-static_cast<i64>(mValue))
97 : static_cast<u32>(mValue);
98 const u32 denominator =
99 b.mValue < 0 ? static_cast<u32>(-static_cast<i64>(b.mValue))
100 : static_cast<u32>(b.mValue);
101 const u32 magnitude = divide64By32(numerator >> (32 - FRAC_BITS),
102 numerator << FRAC_BITS, denominator);
103 const bool negative = (mValue < 0) != (b.mValue < 0);
104 // Negated in unsigned space. The quotient of INT32_MIN by one is
105 // INT32_MIN, which is a representable s16.16 value of -32768.0, and
106 // negating it as a signed int is undefined -- it happened to give the
107 // right answer, which is exactly why a value comparison could not
108 // find it and UBSan could.
109 return from_raw(static_cast<i32>(negative ? 0u - magnitude : magnitude));
110#else
111 return from_raw(static_cast<i32>(
112 (static_cast<i64>(mValue) * (static_cast<i64>(SCALE))) / b.mValue));
113#endif
114 }
115
117 return from_raw(static_cast<i32>(
118 static_cast<u32>(mValue) + static_cast<u32>(b.mValue)));
119 }
120
122 return from_raw(static_cast<i32>(
123 static_cast<u32>(mValue) - static_cast<u32>(b.mValue)));
124 }
125
127 return from_raw(static_cast<i32>(0u - static_cast<u32>(mValue)));
128 }
129
131 return from_raw(mValue >> shift);
132 }
133
134 // ---- Scalar multiply (no fixed-point shift) ----------------------------
135
136 constexpr FASTLED_FORCE_INLINE s16x16 operator*(i32 scalar) const FL_NO_EXCEPT {
137 return from_raw(mValue * scalar);
138 }
139
140 friend constexpr s16x16 operator*(i32 scalar, s16x16 fp) FL_NO_EXCEPT {
141 return s16x16::from_raw(scalar * fp.mValue);
142 }
143
144 // ---- Comparisons -------------------------------------------------------
145
146 constexpr bool operator<(s16x16 b) const FL_NO_EXCEPT { return mValue < b.mValue; }
147 constexpr bool operator>(s16x16 b) const FL_NO_EXCEPT { return mValue > b.mValue; }
148 constexpr bool operator<=(s16x16 b) const FL_NO_EXCEPT { return mValue <= b.mValue; }
149 constexpr bool operator>=(s16x16 b) const FL_NO_EXCEPT { return mValue >= b.mValue; }
150 constexpr bool operator==(s16x16 b) const FL_NO_EXCEPT { return mValue == b.mValue; }
151 constexpr bool operator!=(s16x16 b) const FL_NO_EXCEPT { return mValue != b.mValue; }
152
153 // ---- Math ---------------------------------------------------------------
154
156 return from_raw(a.mValue % b.mValue);
157 }
158
160 return from_raw(x.mValue & ~(i32((SCALE) - 1)));
161 }
162
164 return from_raw((x.mValue & ~(i32((SCALE) - 1))) +
165 ((x.mValue & i32((SCALE) - 1)) ? (SCALE) : 0));
166 }
167
169 return from_raw(x.mValue & i32((SCALE) - 1));
170 }
171
173 return from_raw(x.mValue < 0 ? -x.mValue : x.mValue);
174 }
175
177 return x.mValue > 0 ? 1 : (x.mValue < 0 ? -1 : 0);
178 }
179
180#if defined(__riscv) && (__riscv_xlen == 32)
182#else
184#endif
185 return a + (b - a) * t;
186 }
187
189 return x < lo ? lo : (x > hi ? hi : x);
190 }
191
193 return x < edge ? s16x16() : s16x16(1.0f);
194 }
195
197 constexpr s16x16 zero(0.0f);
198 constexpr s16x16 one(1.0f);
199 constexpr s16x16 two(2.0f);
200 constexpr s16x16 three(3.0f);
201 s16x16 t = clamp((x - edge0) / (edge1 - edge0), zero, one);
202 return t * t * (three - two * t);
203 }
204
205 // ---- Inverse Trigonometry (pure fixed-point) ----------------------------
206
208 constexpr s16x16 one(1.0f);
209 constexpr s16x16 pi_over_2(1.5707963f);
210 bool neg = x.mValue < 0;
211 s16x16 ax = abs(x);
213 if (ax <= one) {
214 result = atan_unit(ax);
215 } else {
216 result = pi_over_2 - atan_unit(one / ax);
217 }
218 return neg ? -result : result;
219 }
220
222 constexpr s16x16 pi(3.1415926f);
223 constexpr s16x16 pi_over_2(1.5707963f);
224 if (x.mValue == 0 && y.mValue == 0) return s16x16();
225 if (x.mValue == 0) return y.mValue > 0 ? pi_over_2 : -pi_over_2;
226 if (y.mValue == 0) return x.mValue > 0 ? s16x16() : pi;
227 s16x16 ax = abs(x);
228 s16x16 ay = abs(y);
229 s16x16 a;
230 if (ax >= ay) {
231 a = atan_unit(ay / ax);
232 } else {
233 a = pi_over_2 - atan_unit(ax / ay);
234 }
235 if (x.mValue < 0) a = pi - a;
236 if (y.mValue < 0) a = -a;
237 return a;
238 }
239
241 constexpr s16x16 one(1.0f);
242 return atan2(x, sqrt(one - x * x));
243 }
244
246 constexpr s16x16 one(1.0f);
247 return atan2(sqrt(one - x * x), x);
248 }
249
251 return x.mValue <= 0 ? s16x16() : from_raw(static_cast<i32>(
252 fl::isqrt64(static_cast<u64>(x.mValue) << FRAC_BITS)));
253 }
254
256 return sqrt(x).mValue == 0
257 ? s16x16()
258 : from_raw(SCALE) / sqrt(x);
259 }
260
261 // Signed cube root, exact to within one ULP (it truncates toward zero).
262 //
263 // The identity is the same one `sqrt` uses one power down: for a Q16 raw
264 // value `r` representing r/2^16, the root `y` satisfies
265 // (y/2^16)^3 = r/2^16, i.e. y^3 = r * 2^32 -- so the root is the integer
266 // cube root of the raw value shifted left by 2*FRAC_BITS.
267 //
268 // The shift cannot overflow: the widest input, raw = INT32_MIN, gives
269 // 2^31 << 32 = 2^63, which is representable in u64, and the result
270 // 2^21 = 32.0 is well inside i32.
272 return x.mValue < 0
273 ? from_raw(-static_cast<i32>(fl::icbrt64(
274 static_cast<u64>(-static_cast<i64>(x.mValue)) << (2 * FRAC_BITS))))
275 : from_raw(static_cast<i32>(fl::icbrt64(
276 static_cast<u64>(x.mValue) << (2 * FRAC_BITS))));
277 }
278
280 if (base.mValue <= 0) return s16x16();
281 constexpr s16x16 one(1.0f);
282 if (exp.mValue == 0) return one;
283 if (base == one) return one;
284 // Snap base values within ~2 ULPs of 1.0 to exactly 1.0 to dodge the
285 // log2(1+t) minimax polynomial's upper-endpoint residual (#2969).
286 constexpr i32 kOneRaw = static_cast<i32>(SCALE);
287 if (base.mValue >= (kOneRaw - 2) && base.mValue <= kOneRaw) {
288 return one;
289 }
290 return exp2_fp(exp * log2_fp(base));
291 }
292
293 // ---- Member function versions (operate on *this) -----------------------
294
296 return floor(*this);
297 }
298
300 return ceil(*this);
301 }
302
304 return fract(*this);
305 }
306
308 return abs(*this);
309 }
310
311 constexpr FASTLED_FORCE_INLINE int sign() const FL_NO_EXCEPT {
312 return sign(*this);
313 }
314
316 return sin(*this);
317 }
318
320 return cos(*this);
321 }
322
324 return atan(*this);
325 }
326
328 return asin(*this);
329 }
330
332 return acos(*this);
333 }
334
336 return sqrt(*this);
337 }
338
340 return rsqrt(*this);
341 }
342
343 // ---- Trigonometry ------------------------------------------------------
344
346 return from_raw(fl::sin32(angle_to_a24(angle)) >> 15);
347 }
348
350 return from_raw(fl::cos32(angle_to_a24(angle)) >> 15);
351 }
352
353 // Combined sin+cos from s16x16 radians. Output in s16x16 [-1, 1].
354 // Uses sincos32 which shares angle decomposition for ~30% fewer ops.
355 static FASTLED_FORCE_INLINE void sincos(s16x16 angle, s16x16 &out_sin,
356 s16x16 &out_cos) FL_NO_EXCEPT {
357 u32 a24 = angle_to_a24(angle);
358 fl::SinCos32 sc = fl::sincos32(a24);
359 out_sin = from_raw(sc.sin_val >> 15);
360 out_cos = from_raw(sc.cos_val >> 15);
361 }
362
363 private:
364 i32 mValue = 0;
365
366 // Returns 0-based position of highest set bit, or -1 if v==0.
367 static constexpr FASTLED_FORCE_INLINE int highest_bit(u32 v) FL_NO_EXCEPT {
368 return v == 0 ? -1 : _highest_bit_step(v, 0);
369 }
370
371 static constexpr int _highest_bit_step(u32 v, int r) FL_NO_EXCEPT {
372 return (v & 0xFFFF0000u) ? _highest_bit_step(v >> 16, r + 16)
373 : (v & 0x0000FF00u) ? _highest_bit_step(v >> 8, r + 8)
374 : (v & 0x000000F0u) ? _highest_bit_step(v >> 4, r + 4)
375 : (v & 0x0000000Cu) ? _highest_bit_step(v >> 2, r + 2)
376 : (v & 0x00000002u) ? r + 1
377 : r;
378 }
379
380 // Fixed-point log base 2 for positive values.
381 // Uses 4-term minimax polynomial for log2(1+t), t in [0,1).
382 // Horner evaluation uses i64 intermediates (24 frac bits) to minimize
383 // rounding error, then converts back to 16 frac bits.
385 u32 val = static_cast<u32>(x.mValue);
386 int msb = highest_bit(val);
387 i32 int_part = msb - FRAC_BITS;
388 i32 t;
389 if (msb >= FRAC_BITS) {
390 t = static_cast<i32>(
391 (val >> (msb - FRAC_BITS)) - (SCALE));
392 } else {
393 t = static_cast<i32>(
394 (val << (FRAC_BITS - msb)) - (SCALE));
395 }
396 // 4-term minimax coefficients for log2(1+t), t in [0,1).
397 // Stored as i64 with 24 fractional bits. Max product ~2^49, fits i64.
398 constexpr int IFRAC = 24;
399 constexpr i64 c0 = 24189248LL; // 1.44179 * 2^24
400 constexpr i64 c1 = -11728384LL; // -0.69907 * 2^24
401 constexpr i64 c2 = 6098176LL; // 0.36348 * 2^24
402 constexpr i64 c3 = -1788416LL; // -0.10660 * 2^24
403 // Extend t from 16 to 24 frac bits.
404 i64 t24 = static_cast<i64>(t) << (IFRAC - FRAC_BITS);
405 // Horner: t * (c0 + t * (c1 + t * (c2 + t * c3)))
406 i64 acc = c3;
407 acc = c2 + ((acc * t24) >> IFRAC);
408 acc = c1 + ((acc * t24) >> IFRAC);
409 acc = c0 + ((acc * t24) >> IFRAC);
410 i64 frac_part = (acc * t24) >> IFRAC;
411 // Convert from 24 frac bits back to 16.
412 i32 frac16 = static_cast<i32>(frac_part >> (IFRAC - FRAC_BITS));
413 return from_raw(static_cast<i32>(static_cast<u32>(int_part) << FRAC_BITS) + frac16);
414 }
415
416 // Fixed-point 2^x. Uses 4-term minimax polynomial for 2^t, t in [0,1).
417 // Horner evaluation uses i64 intermediates (24 frac bits) to minimize
418 // rounding error, then converts back to 16 frac bits.
420 s16x16 fl_val = floor(x);
421 s16x16 fr = x - fl_val;
422 i32 n = fl_val.mValue >> FRAC_BITS;
423 if (n >= INT_BITS - 1) return from_raw(0x7FFFFFFF);
424 if (n < -FRAC_BITS) return s16x16();
425 i32 int_pow;
426 if (n >= 0) {
427 int_pow = static_cast<i32>(SCALE) << n;
428 } else {
429 int_pow = static_cast<i32>(SCALE) >> (-n);
430 }
431 // 4-term minimax coefficients for 2^t - 1, t in [0,1).
432 // Stored as i64 with 24 fractional bits. Max product ~2^48, fits i64.
433 constexpr int IFRAC = 24;
434 constexpr i64 d0 = 11629376LL; // 0.69316 * 2^24
435 constexpr i64 d1 = 4038400LL; // 0.24071 * 2^24
436 constexpr i64 d2 = 895232LL; // 0.05336 * 2^24
437 constexpr i64 d3 = 214016LL; // 0.01276 * 2^24
438 // Extend fr from 16 to 24 frac bits.
439 i64 fr24 = static_cast<i64>(fr.mValue) << (IFRAC - FRAC_BITS);
440 // Horner: 1 + fr * (d0 + fr * (d1 + fr * (d2 + fr * d3)))
441 i64 acc = d3;
442 acc = d2 + ((acc * fr24) >> IFRAC);
443 acc = d1 + ((acc * fr24) >> IFRAC);
444 acc = d0 + ((acc * fr24) >> IFRAC);
445 constexpr i64 one24 = 1LL << IFRAC;
446 i64 frac_pow24 = one24 + ((acc * fr24) >> IFRAC);
447 // Convert from 24 frac bits to 16 frac bits, then scale by int_pow.
448 i32 frac_pow16 = static_cast<i32>(frac_pow24 >> (IFRAC - FRAC_BITS));
449 i64 result =
450 (static_cast<i64>(int_pow) * frac_pow16) >> FRAC_BITS;
451 return from_raw(static_cast<i32>(result));
452 }
453
454 // Converts s16x16 radians to sin32/cos32 input format.
455 // 256/(2*PI) — converts radians to sin32/cos32 format.
456 static constexpr i32 RAD_TO_24 = 2670177;
458 return static_cast<u32>(
459 (static_cast<i64>(angle.mValue) * RAD_TO_24) >> FRAC_BITS);
460 }
461
462 // Polynomial atan for t in [0, 1]. Returns [0, π/4].
463 // 7th-order minimax: atan(t) ≈ t * (c0 + t² * (c1 + t² * (c2 + t² * c3)))
464 // Coefficients optimized via coordinate descent on s16x16 quantization grid.
466 constexpr s16x16 c0(0.9998779297f);
467 constexpr s16x16 c1(-0.3269348145f);
468 constexpr s16x16 c2(0.1594085693f);
469 constexpr s16x16 c3(-0.0472106934f);
470 s16x16 t2 = t * t;
471 return t * (c0 + t2 * (c1 + t2 * (c2 + t2 * c3)));
472 }
473};
474
475} // namespace fl
476
FASTLED_FORCE_INLINE s16x16 atan() const FL_NO_EXCEPT
Definition s16x16.h:323
FASTLED_FORCE_INLINE s16x16 asin() const FL_NO_EXCEPT
Definition s16x16.h:327
constexpr float to_float() const FL_NO_EXCEPT
Definition s16x16.h:64
static constexpr i32 SCALE
Definition s16x16.h:25
static constexpr int _highest_bit_step(u32 v, int r) FL_NO_EXCEPT
Definition s16x16.h:371
static FASTLED_FORCE_INLINE s16x16 asin(s16x16 x) FL_NO_EXCEPT
Definition s16x16.h:240
static constexpr FASTLED_FORCE_INLINE s16x16 cbrt(s16x16 x) FL_NO_EXCEPT
Definition s16x16.h:271
constexpr FASTLED_FORCE_INLINE s16x16 fract() const FL_NO_EXCEPT
Definition s16x16.h:303
static FASTLED_FORCE_INLINE s16x16 acos(s16x16 x) FL_NO_EXCEPT
Definition s16x16.h:245
constexpr s16x16(i32 raw, RawTag) FL_NO_EXCEPT
Definition s16x16.h:54
constexpr FASTLED_FORCE_INLINE s16x16 operator+(s16x16 b) const FL_NO_EXCEPT
Definition s16x16.h:116
static constexpr FASTLED_FORCE_INLINE s16x16 lerp(s16x16 a, s16x16 b, s16x16 t) FL_NO_EXCEPT
Definition s16x16.h:183
constexpr bool operator<(s16x16 b) const FL_NO_EXCEPT
Definition s16x16.h:146
static constexpr int INT_BITS
Definition s16x16.h:23
static FASTLED_FORCE_INLINE s16x16 atan_unit(s16x16 t) FL_NO_EXCEPT
Definition s16x16.h:465
static constexpr FASTLED_FORCE_INLINE s16x16 rsqrt(s16x16 x) FL_NO_EXCEPT
Definition s16x16.h:255
static constexpr FASTLED_FORCE_INLINE s16x16 sqrt(s16x16 x) FL_NO_EXCEPT
Definition s16x16.h:250
constexpr FASTLED_FORCE_INLINE s16x16 ceil() const FL_NO_EXCEPT
Definition s16x16.h:299
constexpr bool operator==(s16x16 b) const FL_NO_EXCEPT
Definition s16x16.h:150
constexpr FASTLED_FORCE_INLINE s16x16 floor() const FL_NO_EXCEPT
Definition s16x16.h:295
static constexpr i32 RAD_TO_24
Definition s16x16.h:456
constexpr FASTLED_FORCE_INLINE s16x16 operator/(s16x16 b) const FL_NO_EXCEPT
Definition s16x16.h:87
static constexpr FASTLED_FORCE_INLINE u32 angle_to_a24(s16x16 angle) FL_NO_EXCEPT
Definition s16x16.h:457
static constexpr int FRAC_BITS
Definition s16x16.h:24
constexpr bool operator>=(s16x16 b) const FL_NO_EXCEPT
Definition s16x16.h:149
constexpr i32 raw() const FL_NO_EXCEPT
Definition s16x16.h:62
static constexpr FASTLED_FORCE_INLINE int sign(s16x16 x) FL_NO_EXCEPT
Definition s16x16.h:176
constexpr bool operator>(s16x16 b) const FL_NO_EXCEPT
Definition s16x16.h:147
FASTLED_FORCE_INLINE s16x16 sin() const FL_NO_EXCEPT
Definition s16x16.h:315
friend constexpr s16x16 operator*(i32 scalar, s16x16 fp) FL_NO_EXCEPT
Definition s16x16.h:140
static constexpr FASTLED_FORCE_INLINE s16x16 step(s16x16 edge, s16x16 x) FL_NO_EXCEPT
Definition s16x16.h:192
static constexpr FASTLED_FORCE_INLINE s16x16 fract(s16x16 x) FL_NO_EXCEPT
Definition s16x16.h:168
constexpr FASTLED_FORCE_INLINE s16x16(IntT n) FL_NO_EXCEPT
Definition s16x16.h:37
static FASTLED_FORCE_INLINE s16x16 cos(s16x16 angle) FL_NO_EXCEPT
Definition s16x16.h:349
static constexpr FASTLED_FORCE_INLINE s16x16 clamp(s16x16 x, s16x16 lo, s16x16 hi) FL_NO_EXCEPT
Definition s16x16.h:188
i32 mValue
Definition s16x16.h:364
static FASTLED_FORCE_INLINE s16x16 exp2_fp(s16x16 x) FL_NO_EXCEPT
Definition s16x16.h:419
FASTLED_FORCE_INLINE s16x16 cos() const FL_NO_EXCEPT
Definition s16x16.h:319
static constexpr FASTLED_FORCE_INLINE s16x16 mod(s16x16 a, s16x16 b) FL_NO_EXCEPT
Definition s16x16.h:155
static FASTLED_FORCE_INLINE s16x16 atan(s16x16 x) FL_NO_EXCEPT
Definition s16x16.h:207
constexpr FASTLED_FORCE_INLINE s16x16 rsqrt() const FL_NO_EXCEPT
Definition s16x16.h:339
static constexpr FASTLED_FORCE_INLINE int highest_bit(u32 v) FL_NO_EXCEPT
Definition s16x16.h:367
FASTLED_FORCE_INLINE s16x16 acos() const FL_NO_EXCEPT
Definition s16x16.h:331
constexpr FASTLED_FORCE_INLINE s16x16 operator-() const FL_NO_EXCEPT
Definition s16x16.h:126
constexpr FASTLED_FORCE_INLINE s16x16 operator>>(int shift) const FL_NO_EXCEPT
Definition s16x16.h:130
constexpr FASTLED_FORCE_INLINE s16x16 abs() const FL_NO_EXCEPT
Definition s16x16.h:307
static constexpr FASTLED_FORCE_INLINE s16x16 from_raw(i32 raw) FL_NO_EXCEPT
Definition s16x16.h:56
constexpr bool operator<=(s16x16 b) const FL_NO_EXCEPT
Definition s16x16.h:148
static FASTLED_FORCE_INLINE s16x16 pow(s16x16 base, s16x16 exp) FL_NO_EXCEPT
Definition s16x16.h:279
static constexpr FASTLED_FORCE_INLINE s16x16 ceil(s16x16 x) FL_NO_EXCEPT
Definition s16x16.h:163
static FASTLED_FORCE_INLINE s16x16 log2_fp(s16x16 x) FL_NO_EXCEPT
Definition s16x16.h:384
static FASTLED_FORCE_INLINE s16x16 sin(s16x16 angle) FL_NO_EXCEPT
Definition s16x16.h:345
constexpr FASTLED_FORCE_INLINE s16x16 operator*(s16x16 b) const FL_NO_EXCEPT
Definition s16x16.h:81
constexpr FASTLED_FORCE_INLINE s16x16 sqrt() const FL_NO_EXCEPT
Definition s16x16.h:335
constexpr s16x16() FL_NO_EXCEPT=default
constexpr FASTLED_FORCE_INLINE int sign() const FL_NO_EXCEPT
Definition s16x16.h:311
static FASTLED_FORCE_INLINE s16x16 smoothstep(s16x16 edge0, s16x16 edge1, s16x16 x) FL_NO_EXCEPT
Definition s16x16.h:196
static FASTLED_FORCE_INLINE void sincos(s16x16 angle, s16x16 &out_sin, s16x16 &out_cos) FL_NO_EXCEPT
Definition s16x16.h:355
constexpr i32 to_int() const FL_NO_EXCEPT
Definition s16x16.h:63
constexpr s16x16(const OtherFP &other, typename fl::enable_if<(OtherFP::INT_BITS<=INT_BITS) &&(OtherFP::FRAC_BITS<=FRAC_BITS) &&(OtherFP::INT_BITS !=INT_BITS||OtherFP::FRAC_BITS !=FRAC_BITS), int >::type=0) FL_NO_EXCEPT
Definition s16x16.h:43
constexpr bool operator!=(s16x16 b) const FL_NO_EXCEPT
Definition s16x16.h:151
static constexpr FASTLED_FORCE_INLINE s16x16 floor(s16x16 x) FL_NO_EXCEPT
Definition s16x16.h:159
static constexpr FASTLED_FORCE_INLINE s16x16 abs(s16x16 x) FL_NO_EXCEPT
Definition s16x16.h:172
constexpr FASTLED_FORCE_INLINE s16x16 operator*(i32 scalar) const FL_NO_EXCEPT
Definition s16x16.h:136
static FASTLED_FORCE_INLINE s16x16 atan2(s16x16 y, s16x16 x) FL_NO_EXCEPT
Definition s16x16.h:221
constexpr FASTLED_FORCE_INLINE s16x16 operator-(s16x16 b) const FL_NO_EXCEPT
Definition s16x16.h:121
#define FL_OPTIMIZATION_LEVEL_O3_BEGIN
#define FASTLED_FORCE_INLINE
#define FL_OPTIMIZATION_LEVEL_O3_END
#define constexpr
Declares that it is possible to evaluate a value at compile time, introduced in C++11.
Definition cpp_compat.h:15
FASTLED_FORCE_INLINE i32 sin32(u32 angle) FL_NO_EXCEPT
Definition sin32.h:57
FL_FIXED_POINT_DIVIDE_INLINE u32 divide64By32(u32 hi, u32 lo, u32 divisor) FL_NO_EXCEPT
(hi:lo) / divisor, for a quotient that fits 32 bits.
u8 u8 fract8 blur_amount FL_NO_EXCEPT
Definition blur.h:186
FL_OPTIMIZE_FUNCTION constexpr u32 isqrt64(u64 x) FL_NO_EXCEPT
Definition isqrt.h:58
FL_OPTIMIZE_FUNCTION constexpr u32 icbrt64(u64 x) FL_NO_EXCEPT
Definition icbrt.h:45
FASTLED_FORCE_INLINE SinCos32 sincos32(u32 angle) FL_NO_EXCEPT
Definition sin32.h:86
FASTLED_FORCE_INLINE i32 cos32(u32 angle) FL_NO_EXCEPT
Definition sin32.h:79
expected< T, E > result
Alias for expected (Rust-style naming)
Definition result.h:31
enable_if< is_fixed_point< T >::value, T >::type exp(T x) FL_NO_EXCEPT
Base definition for an LED controller.
Definition crgb.hpp:179
i32 sin_val
Definition sin32.h:23
i32 cos_val
Definition sin32.h:24
fl::u64 u64
Definition stdint.h:220
fl::i64 i64
Definition stdint.h:221
A 64/32 -> 32 division built from 32-bit divides.