FastLED 3.9.15
Loading...
Searching...
No Matches
fixed_point.h
Go to the documentation of this file.
1#pragma once
2
3// Template system for fixed-point types with sign support.
4//
5// Fixed-point numbers represent fractional values using integer arithmetic,
6// splitting a 32-bit integer into an integer part and a fractional part.
7// For example, s16x16 uses 16 bits for the integer part (range ~-32768 to 32767)
8// and 16 bits for the fractional part (precision ~0.000015).
9//
10// Quick start:
11// using FP = fl::fixed_point<16, 16>; // signed 16.16 (default)
12// FP x(3.14f); // construct from float
13// FP y = FP::from_raw(0x00028000); // construct from raw: 2.5
14// FP z = x + y; // arithmetic: 5.64
15// float f = z.to_float(); // convert back: 5.64
16// int i = z.to_int(); // truncate to int: 5
17//
18// Available types (IntBits.FracBits):
19// Signed: s0x32, s4x12, s8x8, s8x24, s12x4, s16x16, s24x8
20// Unsigned: u0x32, u4x12, u8x8, u8x24, u12x4, u16x16, u24x8
21//
22// Template aliases:
23// fl::sfixed_integer<16, 16> → signed 16.16
24// fl::ufixed_integer<8, 8> → unsigned 8.8
25//
26// Free-function math API (std::cmath style):
27// fl::floor(x), fl::ceil(x), fl::fract(x), fl::abs(x)
28// fl::sqrt(x), fl::rsqrt(x), fl::pow(x, y), fl::exp(x)
29// fl::sin(x), fl::cos(x), fl::sincos(angle, &s, &c)
30// fl::atan(x), fl::atan2(y, x), fl::asin(x), fl::acos(x)
31// fl::lerp(a, b, t), fl::clamp(x, lo, hi), fl::mod(a, b)
32// fl::step(edge, x), fl::smoothstep(e0, e1, x)
33//
34// numeric_limits specializations in fl/stl/limits.h
35
50#include "fl/stl/type_traits.h"
51#include "fl/stl/noexcept.h"
52
53namespace fl {
54
55// Sign selector for fixed-point types.
56// fl::fixed_point<16, 16> // defaults to Sign::SIGNED
57// fl::fixed_point<16, 16, Sign::UNSIGNED> // explicit unsigned
58enum class Sign {
61};
62
63// Maps <IntBits, FracBits, Sign> to the concrete type (e.g. s16x16, u8x8).
64// Only explicitly specialized combinations are valid; others produce a
65// compile error via the undefined primary template.
66//
67// Example: fixed_point_impl<16, 16, Sign::SIGNED>::type → s16x16
68template <int IntBits, int FracBits, Sign S>
70
71// Signed specializations
72template <> struct fixed_point_impl<0, 32, Sign::SIGNED> { using type = s0x32; };
73template <> struct fixed_point_impl<4, 12, Sign::SIGNED> { using type = s4x12; };
74template <> struct fixed_point_impl<8, 8, Sign::SIGNED> { using type = s8x8; };
75template <> struct fixed_point_impl<8, 24, Sign::SIGNED> { using type = s8x24; };
76template <> struct fixed_point_impl<12, 4, Sign::SIGNED> { using type = s12x4; };
77template <> struct fixed_point_impl<16, 16, Sign::SIGNED> { using type = s16x16; };
78template <> struct fixed_point_impl<24, 8, Sign::SIGNED> { using type = s24x8; };
79
80// Unsigned specializations
81template <> struct fixed_point_impl<0, 32, Sign::UNSIGNED> { using type = u0x32; };
82template <> struct fixed_point_impl<4, 12, Sign::UNSIGNED> { using type = u4x12; };
83template <> struct fixed_point_impl<8, 8, Sign::UNSIGNED> { using type = u8x8; };
84template <> struct fixed_point_impl<8, 24, Sign::UNSIGNED> { using type = u8x24; };
85template <> struct fixed_point_impl<12, 4, Sign::UNSIGNED> { using type = u12x4; };
86template <> struct fixed_point_impl<16, 16, Sign::UNSIGNED> { using type = u16x16; };
87template <> struct fixed_point_impl<24, 8, Sign::UNSIGNED> { using type = u24x8; };
88
89// Forward declaration for is_fp_promotable trait
90template <int IntBits, int FracBits, Sign S = Sign::SIGNED>
91class fixed_point;
92
93// Type trait: true when fixed_point type From can be implicitly promoted to To.
94// Promotion requires: both INT_BITS and FRAC_BITS of From <= To, same sign,
95// and at least one dimension differs (no identity promotion).
96//
97// Example:
98// is_fp_promotable<fixed_point<8,8>, fixed_point<16,16>>::value // true
99// is_fp_promotable<fixed_point<16,16>, fixed_point<8,8>>::value // false (demotion)
100// is_fp_promotable<fixed_point<8,8>, fixed_point<8,8>>::value // false (identity)
101template <typename From, typename To>
103 static constexpr bool value = false;
104};
105
106template <int FromInt, int FromFrac, Sign FromSign, int ToInt, int ToFrac, Sign ToSign>
107struct is_fp_promotable<fixed_point<FromInt, FromFrac, FromSign>, fixed_point<ToInt, ToFrac, ToSign>> {
108 static constexpr bool value =
109 (FromInt <= ToInt) &&
110 (FromFrac <= ToFrac) &&
111 (FromSign == ToSign) &&
112 (FromInt != ToInt || FromFrac != ToFrac);
113};
114
115// Generic fixed-point wrapper that adds auto-promotion between types and
116// forwards all operations to the underlying concrete type (e.g. s16x16).
117//
118// Example:
119// using FP = fl::fixed_point<16, 16>; // signed 16.16
120// FP a(2.5f);
121// FP b(1.25f);
122// FP c = a * b; // 3.125
123// float f = c.to_float(); // 3.125f
124//
125// Auto-promotion:
126// fl::fixed_point<8, 8> small(1.5f);
127// fl::fixed_point<16, 16> big = small; // implicit widening, no data loss
128template <int IntBits, int FracBits, Sign S>
129class fixed_point : protected fixed_point_impl<IntBits, FracBits, S>::type {
130 private:
131 using Base = typename fixed_point_impl<IntBits, FracBits, S>::type;
132 using RawType = decltype(Base().raw());
133
134 // Helper: Select intermediate type for promotion (i64 for signed, u64 for unsigned)
136
137 // Helper: Promote fixed-point value to higher precision with fractional bit shift
138 template <int OtherFrac, typename OtherRawType>
139 static constexpr RawType promote_fp(OtherRawType other_raw) FL_NOEXCEPT {
140 return static_cast<RawType>(
141 static_cast<PromotionType>(other_raw) << (FracBits - OtherFrac));
142 }
143
144 public:
145 // ---- Type constants ----
146 // INT_BITS: number of integer bits (e.g. 16 for s16x16)
147 // FRAC_BITS: number of fractional bits (e.g. 16 for s16x16)
148 // static_assert(FP::INT_BITS == 16, "");
149 using Base::INT_BITS;
150 using Base::FRAC_BITS;
151
152 // ---- Constructors ----
153
154 // Default constructor — value is zero.
155 // FP x; // x == 0
157
158 // Construct from a floating-point literal. Conversion is done at compile
159 // time when used in a constexpr context.
160 // FP x(3.14f); // x ≈ 3.14
161 // FP y(-0.5f); // y = -0.5
162 FASTLED_FORCE_INLINE explicit constexpr fixed_point(float f) FL_NOEXCEPT : Base(f) {}
163
164 // Construct from any integer type. Delegates to Base's template integer
165 // constructor which handles int-width portability (AVR 16-bit int vs
166 // 32-bit platforms) and constexpr range checking.
167 // FP x(5); // x == 5.0
168 // FP y(-3); // y == -3.0
169 template <typename IntT, detail::enable_if_integer_t<IntT> = 0>
170 FASTLED_FORCE_INLINE explicit constexpr fixed_point(IntT n) FL_NOEXCEPT : Base(n) {}
171
172 // Construct from a raw integer value (used internally by from_raw).
173 // FP x(0x00028000, FP::Base::RawTag()); // prefer from_raw() instead
174 constexpr explicit fixed_point(RawType raw, typename Base::RawTag tag) FL_NOEXCEPT : Base(raw, tag) {}
175
176 // Implicit widening promotion from a narrower fixed-point type.
177 // Only enabled when both IntBits and FracBits of the source are <=
178 // this type's, with the same sign. No data is lost.
179 // fixed_point<8, 8> narrow(1.5f);
180 // fixed_point<16, 16> wide = narrow; // OK: implicit promotion
181 template <int OtherInt, int OtherFrac, Sign OtherSign>
191
192 // ---- Factory methods ----
193
194 // Construct from the underlying raw integer representation.
195 // For s16x16 the value 0x00018000 represents 1.5 (0x0001 integer, 0x8000 = 0.5).
196 // auto x = FP::from_raw(0x00028000); // 2.5 in 16.16 format
198 return fixed_point(raw, typename Base::RawTag());
199 }
200
201 // ---- Conversion methods ----
202
203 // Returns the underlying raw integer representation.
204 // FP x(2.5f);
205 // i32 r = x.raw(); // 0x00028000 for s16x16
206 FASTLED_FORCE_INLINE constexpr RawType raw() const FL_NOEXCEPT { return Base::raw(); }
207
208 // Truncates toward zero, returning only the integer part.
209 // FP(3.75f).to_int() // 3
210 // FP(-2.25f).to_int() // -2
211 constexpr FASTLED_FORCE_INLINE i32 to_int() const FL_NOEXCEPT { return Base::to_int(); }
212
213 // Converts to a float. Useful for debugging or interop with float APIs.
214 // FP(3.14f).to_float() // ≈ 3.14f
215 constexpr FASTLED_FORCE_INLINE float to_float() const FL_NOEXCEPT { return Base::to_float(); }
216
217 // ---- Arithmetic operators ----
218 // All arithmetic is integer-only in the hot path.
219 // FP a(3.0f), b(1.5f);
220 // FP sum = a + b; // 4.5
221 // FP diff = a - b; // 1.5
222 // FP prod = a * b; // 4.5
223 // FP quot = a / b; // 2.0
224 // FP neg = -a; // -3.0
225
227 return from_raw((Base::operator+(b)).raw());
228 }
229
231 return from_raw((Base::operator-(b)).raw());
232 }
233
235 return from_raw((Base::operator*(b)).raw());
236 }
237
239 return from_raw((Base::operator/(b)).raw());
240 }
241
242 // Unary negation.
243 // FP x(2.0f);
244 // FP y = -x; // -2.0
246 return from_raw((Base::operator-()).raw());
247 }
248
249 // Bit-shift operators — shift the raw representation.
250 // FP x(4.0f);
251 // FP half = x >> 1; // 2.0 (divide by 2)
252 // FP doubled = x << 1; // 8.0 (multiply by 2)
254 return from_raw((Base::operator>>(shift)).raw());
255 }
256
258 return from_raw((Base::operator<<(shift)).raw());
259 }
260
261 // ---- Scalar multiplication ----
262 // Multiply a fixed-point value by a plain integer (both orderings).
263 // FP x(1.5f);
264 // FP a = x * 3; // 4.5
265 // FP b = 3 * x; // 4.5
266
268 return from_raw((Base::operator*(scalar)).raw());
269 }
270
271 friend constexpr fixed_point operator*(i32 scalar, fixed_point fp) FL_NOEXCEPT {
272 return from_raw((scalar * static_cast<Base>(fp)).raw());
273 }
274
275 // ---- Comparison operators ----
276 // All six relational operators. Comparisons are on the raw integer.
277 // FP a(1.0f), b(2.0f);
278 // a < b; // true
279 // a == a; // true
280 // a != b; // true
281
283 return Base::operator<(b);
284 }
285
287 return Base::operator>(b);
288 }
289
291 return Base::operator<=(b);
292 }
293
295 return Base::operator>=(b);
296 }
297
299 return Base::operator==(b);
300 }
301
303 return Base::operator!=(b);
304 }
305
306 // ---- Static math functions ----
307 // These are also available as free functions: fl::floor(x), fl::mod(a,b), etc.
308
309 // Remainder after division: mod(5.5, 2.0) → 1.5
311 return from_raw(Base::mod(a, b).raw());
312 }
313
314 // Round down to the nearest integer: floor(3.7) → 3.0, floor(-1.2) → -2.0
316 return from_raw(Base::floor(x).raw());
317 }
318
319 // Round up to the nearest integer: ceil(3.2) → 4.0, ceil(-1.8) → -1.0
321 return from_raw(Base::ceil(x).raw());
322 }
323
324 // Fractional part: fract(3.75) → 0.75, fract(-1.25) → 0.75
326 return from_raw(Base::fract(x).raw());
327 }
328
329 // Absolute value: abs(-2.5) → 2.5
331 return from_raw(Base::abs(x).raw());
332 }
333
334 // Sign function: returns -1, 0, or +1.
335 // sign(-3.5) → -1.0, sign(0) → 0.0, sign(2.0) → 1.0
337 return from_raw(Base::sign(x).raw());
338 }
339
340 // Linear interpolation: lerp(a, b, t) = a + t*(b - a), where t is in [0, 1].
341 // lerp(0, 10, 0.5) → 5.0
342 // lerp(0, 10, 0.25) → 2.5
344 return from_raw(Base::lerp(a, b, t).raw());
345 }
346
347 // Clamp x to the range [lo, hi]: clamp(5.0, 0.0, 3.0) → 3.0
349 return from_raw(Base::clamp(x, lo, hi).raw());
350 }
351
352 // Step function: returns 0.0 if x < edge, 1.0 otherwise.
353 // step(0.5, 0.3) → 0.0
354 // step(0.5, 0.7) → 1.0
356 return from_raw(Base::step(edge, x).raw());
357 }
358
359 // Smooth Hermite interpolation between 0 and 1 when edge0 < x < edge1.
360 // smoothstep(0.0, 1.0, 0.5) ≈ 0.5
361 // smoothstep(0.0, 1.0, 0.0) → 0.0
362 // smoothstep(0.0, 1.0, 1.0) → 1.0
364 return from_raw(Base::smoothstep(edge0, edge1, x).raw());
365 }
366
367 // Component-wise minimum: min(3.0, 1.5) → 1.5
369 return from_raw(Base::min(a, b).raw());
370 }
371
372 // Component-wise maximum: max(3.0, 1.5) → 3.0
374 return from_raw(Base::max(a, b).raw());
375 }
376
377 // ---- Trigonometry ----
378 // Angles are in radians (not degrees, not 0-65535 "brev" units).
379 // All trig functions use integer-only LUT-based implementations.
380
381 // Sine: sin(π/2) → 1.0
382 // FP angle(1.5708f); // π/2
383 // FP s = FP::sin(angle); // ≈ 1.0
385 return from_raw(Base::sin(angle).raw());
386 }
387
388 // Cosine: cos(0) → 1.0
389 // FP c = FP::cos(FP(0.0f)); // 1.0
391 return from_raw(Base::cos(angle).raw());
392 }
393
394 // Compute sin and cos simultaneously (more efficient than calling each).
395 // FP s, c;
396 // FP::sincos(FP(1.0f), s, c); // s ≈ 0.841, c ≈ 0.540
398 Base base_sin, base_cos;
399 Base::sincos(angle, base_sin, base_cos);
400 out_sin = from_raw(base_sin.raw());
401 out_cos = from_raw(base_cos.raw());
402 }
403
404 // Arctangent: atan(1.0) ≈ π/4 ≈ 0.785
406 return from_raw(Base::atan(x).raw());
407 }
408
409 // Two-argument arctangent: atan2(y, x) returns angle in [-π, π].
410 // FP::atan2(FP(1.0f), FP(1.0f)) // ≈ π/4 ≈ 0.785
412 return from_raw(Base::atan2(y, x).raw());
413 }
414
415 // Arc sine: asin(1.0) ≈ π/2. Input must be in [-1, 1].
417 return from_raw(Base::asin(x).raw());
418 }
419
420 // Arc cosine: acos(0.0) ≈ π/2. Input must be in [-1, 1].
422 return from_raw(Base::acos(x).raw());
423 }
424
425 // ---- Other math functions ----
426
427 // Square root: sqrt(4.0) → 2.0, sqrt(2.0) ≈ 1.414
428 // FP r = FP::sqrt(FP(9.0f)); // 3.0
430 return from_raw(Base::sqrt(x).raw());
431 }
432
433 // Reciprocal square root: rsqrt(4.0) → 0.5, rsqrt(x) ≈ 1/sqrt(x)
434 // FP r = FP::rsqrt(FP(4.0f)); // 0.5
436 return from_raw(Base::rsqrt(x).raw());
437 }
438
439 // Power: pow(2.0, 3.0) → 8.0. Uses exp2/log2 LUTs internally.
440 // FP r = FP::pow(FP(2.0f), FP(10.0f)); // 1024.0
442 return from_raw(Base::pow(base, exp).raw());
443 }
444};
445
446// Convenience aliases that default the sign, so you don't need to spell Sign::SIGNED.
447// fl::sfixed_integer<16, 16> x(3.14f); // signed 16.16
448// fl::ufixed_integer<8, 8> y(1.5f); // unsigned 8.8
449template <int IntBits, int FracBits>
451
452template <int IntBits, int FracBits>
454
455// Backward-compatible aliases (prefer sfixed_integer / ufixed_integer).
456template <int IntBits, int FracBits>
458
459template <int IntBits, int FracBits>
461
462
463//-------------------------------------------------------------------------------
464// is_fixed_point<T> — type trait that is true_type for any fixed_point<I,F,S>.
465// Strips const/volatile/reference qualifiers automatically.
466// (Default false_type lives in fl/stl/type_traits.h)
467//
468// Example:
469// is_fixed_point<fl::sfixed_integer<16,16>>::value // true
470// is_fixed_point<float>::value // false
471// is_fixed_point<const fl::s16x16&>::value // true
472//-------------------------------------------------------------------------------
473template <int I, int F, Sign S>
475
476// Handle cv-qualified and reference types
477template <typename T> struct is_fixed_point<const T> : is_fixed_point<T> {};
478template <typename T> struct is_fixed_point<volatile T> : is_fixed_point<T> {};
479template <typename T> struct is_fixed_point<const volatile T> : is_fixed_point<T> {};
480template <typename T> struct is_fixed_point<T&> : is_fixed_point<T> {};
481
482
483//-------------------------------------------------------------------------------
484// Free-function math API (std::cmath style)
485//
486// These enable ADL so you can write fl::sin(x) instead of x.sin(x).
487// Only enabled for fixed_point types (SFINAE via is_fixed_point).
488//
489// Usage:
490// using FP = fl::fixed_point<16, 16>;
491// FP x(2.25f);
492// FP f = fl::floor(x); // 2.0
493// FP c = fl::ceil(x); // 3.0
494// FP s = fl::sin(FP(1.0f)); // ≈ 0.841
495// FP r = fl::sqrt(FP(9.0f)); // 3.0
496//-------------------------------------------------------------------------------
497
498// ---- Rounding / decomposition ----
499
500// Round down: fl::floor(FP(2.7f)) → 2.0
501template <typename T>
502inline constexpr typename enable_if<is_fixed_point<T>::value, T>::type
503floor(T x) FL_NOEXCEPT { return T::floor(x); }
504
505// Round up: fl::ceil(FP(2.1f)) → 3.0
506template <typename T>
507inline constexpr typename enable_if<is_fixed_point<T>::value, T>::type
508ceil(T x) FL_NOEXCEPT { return T::ceil(x); }
509
510// Fractional part: fl::fract(FP(2.75f)) → 0.75
511template <typename T>
512inline constexpr typename enable_if<is_fixed_point<T>::value, T>::type
513fract(T x) FL_NOEXCEPT { return T::fract(x); }
514
515// Remainder: fl::mod(FP(5.5f), FP(2.0f)) → 1.5
516template <typename T>
517inline constexpr typename enable_if<is_fixed_point<T>::value, T>::type
518mod(T a, T b) FL_NOEXCEPT { return T::mod(a, b); }
519
520// ---- Absolute value / sign ----
521
522// Absolute value: fl::abs(FP(-3.0f)) → 3.0
523template <typename T>
524inline constexpr typename enable_if<is_fixed_point<T>::value, T>::type
525abs(T x) FL_NOEXCEPT { return T::abs(x); }
526
527// Sign: fl::sign(FP(-5.0f)) → -1
528template <typename T>
529inline constexpr typename enable_if<is_fixed_point<T>::value, int>::type
530sign(T x) FL_NOEXCEPT { return T::sign(x); }
531
532// ---- Interpolation / clamping ----
533
534// Linear interpolation: fl::lerp(FP(0.0f), FP(10.0f), FP(0.5f)) → 5.0
535template <typename T>
536inline constexpr typename enable_if<is_fixed_point<T>::value, T>::type
537lerp(T a, T b, T t) FL_NOEXCEPT { return T::lerp(a, b, t); }
538
539// Clamp to range: fl::clamp(FP(5.0f), FP(0.0f), FP(3.0f)) → 3.0
540template <typename T>
541inline constexpr typename enable_if<is_fixed_point<T>::value, T>::type
542clamp(T x, T lo, T hi) FL_NOEXCEPT { return T::clamp(x, lo, hi); }
543
544// Step: fl::step(FP(0.5f), FP(0.7f)) → 1.0
545template <typename T>
546inline constexpr typename enable_if<is_fixed_point<T>::value, T>::type
547step(T edge, T x) FL_NOEXCEPT { return T::step(edge, x); }
548
549// Smooth Hermite interpolation: fl::smoothstep(FP(0.0f), FP(1.0f), FP(0.5f)) ≈ 0.5
550template <typename T>
551inline typename enable_if<is_fixed_point<T>::value, T>::type
552smoothstep(T edge0, T edge1, T x) FL_NOEXCEPT { return T::smoothstep(edge0, edge1, x); }
553
554// ---- Roots / powers ----
555
556// Square root: fl::sqrt(FP(9.0f)) → 3.0
557template <typename T>
558inline constexpr typename enable_if<is_fixed_point<T>::value, T>::type
559sqrt(T x) FL_NOEXCEPT { return T::sqrt(x); }
560
561// Reciprocal square root: fl::rsqrt(FP(4.0f)) → 0.5
562template <typename T>
563inline constexpr typename enable_if<is_fixed_point<T>::value, T>::type
564rsqrt(T x) FL_NOEXCEPT { return T::rsqrt(x); }
565
566// Power: fl::pow(FP(2.0f), FP(3.0f)) → 8.0
567template <typename T>
568inline typename enable_if<is_fixed_point<T>::value, T>::type
569pow(T base, T exp) FL_NOEXCEPT { return T::pow(base, exp); }
570
571// ---- Trigonometry ----
572// All angles are in radians.
573
574// Sine: fl::sin(FP(1.5708f)) ≈ 1.0 (π/2)
575template <typename T>
576inline typename enable_if<is_fixed_point<T>::value, T>::type
577sin(T angle) FL_NOEXCEPT { return T::sin(angle); }
578
579// Cosine: fl::cos(FP(0.0f)) → 1.0
580template <typename T>
581inline typename enable_if<is_fixed_point<T>::value, T>::type
582cos(T angle) FL_NOEXCEPT { return T::cos(angle); }
583
584// Simultaneous sin+cos (faster than calling each separately).
585// FP s, c;
586// fl::sincos(FP(1.0f), s, c);
587template <typename T>
588inline typename enable_if<is_fixed_point<T>::value, void>::type
589sincos(T angle, T& out_sin, T& out_cos) FL_NOEXCEPT { T::sincos(angle, out_sin, out_cos); }
590
591// Arctangent: fl::atan(FP(1.0f)) ≈ π/4 ≈ 0.785
592template <typename T>
593inline typename enable_if<is_fixed_point<T>::value, T>::type
594atan(T x) FL_NOEXCEPT { return T::atan(x); }
595
596// Two-argument arctangent: fl::atan2(FP(1.0f), FP(1.0f)) ≈ π/4
597template <typename T>
598inline typename enable_if<is_fixed_point<T>::value, T>::type
599atan2(T y, T x) FL_NOEXCEPT { return T::atan2(y, x); }
600
601// Arc sine: fl::asin(FP(1.0f)) ≈ π/2. Input in [-1, 1].
602template <typename T>
603inline typename enable_if<is_fixed_point<T>::value, T>::type
604asin(T x) FL_NOEXCEPT { return T::asin(x); }
605
606// Arc cosine: fl::acos(FP(0.0f)) ≈ π/2. Input in [-1, 1].
607template <typename T>
608inline typename enable_if<is_fixed_point<T>::value, T>::type
609acos(T x) FL_NOEXCEPT { return T::acos(x); }
610
611//-------------------------------------------------------------------------------
612// powfp<T>(base, exp) — free-function power for fixed_point types.
613// Identical to fl::pow() but with a distinct name to avoid ambiguity with
614// C stdlib pow when both fl:: and std:: are in scope.
615//
616// fl::powfp(FP(2.0f), FP(10.0f)) // 1024.0
617//-------------------------------------------------------------------------------
618template <typename T>
619inline typename enable_if<is_fixed_point<T>::value, T>::type
621 return T::pow(base, exp);
622}
623
624//-------------------------------------------------------------------------------
625// expfp<T>(x) — fixed-point exponential: computes e^x.
626// Uses powfp(e, x) where e ≈ 2.71828.
627//
628// fl::expfp(FP(1.0f)) // ≈ 2.718 (e^1)
629// fl::expfp(FP(0.0f)) // ≈ 1.0 (e^0)
630//-------------------------------------------------------------------------------
631template <typename T>
632inline typename enable_if<is_fixed_point<T>::value, T>::type
634 static const T e_val(static_cast<float>(FL_E));
635 return powfp(e_val, x);
636}
637
638// exp(x) for fixed-point types — equivalent to expfp(x).
639// fl::exp(FP(1.0f)) // ≈ 2.718
640template <typename T>
641inline typename enable_if<is_fixed_point<T>::value, T>::type
642exp(T x) FL_NOEXCEPT { return fl::expfp(x); }
643
644// ---- Cross-type operator implementations ----
645// Mixed-type multiplication between different fixed-point widths.
646// The result type is the wider type to avoid precision loss.
647
648// s0x32 × s16x16 → s16x16
649// Scales a fractional-only value (s0x32 range: [-1, 1)) by a 16.16 value.
650// s0x32 frac(0.5f);
651// s16x16 val(10.0f);
652// s16x16 result = frac * val; // 5.0
654 return s16x16::from_raw(static_cast<i32>(
655 (static_cast<i64>(mValue) * b.raw()) >> 31));
656}
657
658// s16x16 × s0x32 → s16x16 (commutative)
659// s16x16 result = val * frac; // same as frac * val
661 return b * a;
662}
663
664} // namespace fl
static FASTLED_FORCE_INLINE fixed_point cos(fixed_point angle) FL_NOEXCEPT
static FASTLED_FORCE_INLINE fixed_point asin(fixed_point x) FL_NOEXCEPT
FASTLED_FORCE_INLINE constexpr fixed_point() FL_NOEXCEPT
static constexpr FASTLED_FORCE_INLINE fixed_point floor(fixed_point x) FL_NOEXCEPT
constexpr FASTLED_FORCE_INLINE bool operator>(fixed_point b) const FL_NOEXCEPT
static constexpr FASTLED_FORCE_INLINE fixed_point rsqrt(fixed_point x) FL_NOEXCEPT
static constexpr FASTLED_FORCE_INLINE fixed_point mod(fixed_point a, fixed_point b) FL_NOEXCEPT
constexpr fixed_point(const fixed_point< OtherInt, OtherFrac, OtherSign > &other, typename enable_if< is_fp_promotable< fixed_point< OtherInt, OtherFrac, OtherSign >, fixed_point< IntBits, FracBits, S > >::value, int >::type=0) FL_NOEXCEPT
static FASTLED_FORCE_INLINE fixed_point atan2(fixed_point y, fixed_point x) FL_NOEXCEPT
constexpr fixed_point(RawType raw, typename Base::RawTag tag) FL_NOEXCEPT
constexpr FASTLED_FORCE_INLINE float to_float() const FL_NOEXCEPT
static constexpr FASTLED_FORCE_INLINE fixed_point max(fixed_point a, fixed_point b) FL_NOEXCEPT
static constexpr RawType promote_fp(OtherRawType other_raw) FL_NOEXCEPT
static constexpr FASTLED_FORCE_INLINE fixed_point lerp(fixed_point a, fixed_point b, fixed_point t) FL_NOEXCEPT
static constexpr FASTLED_FORCE_INLINE fixed_point clamp(fixed_point x, fixed_point lo, fixed_point hi) FL_NOEXCEPT
static constexpr FASTLED_FORCE_INLINE fixed_point abs(fixed_point x) FL_NOEXCEPT
static FASTLED_FORCE_INLINE fixed_point atan(fixed_point x) FL_NOEXCEPT
constexpr FASTLED_FORCE_INLINE fixed_point operator*(i32 scalar) const FL_NOEXCEPT
constexpr FASTLED_FORCE_INLINE fixed_point operator-() const FL_NOEXCEPT
static FASTLED_FORCE_INLINE fixed_point sin(fixed_point angle) FL_NOEXCEPT
constexpr FASTLED_FORCE_INLINE fixed_point operator+(fixed_point b) const FL_NOEXCEPT
static constexpr FASTLED_FORCE_INLINE fixed_point from_raw(RawType raw) FL_NOEXCEPT
static constexpr FASTLED_FORCE_INLINE fixed_point min(fixed_point a, fixed_point b) FL_NOEXCEPT
constexpr FASTLED_FORCE_INLINE fixed_point operator>>(int shift) const FL_NOEXCEPT
constexpr FASTLED_FORCE_INLINE fixed_point operator<<(int shift) const FL_NOEXCEPT
constexpr FASTLED_FORCE_INLINE bool operator==(fixed_point b) const FL_NOEXCEPT
FASTLED_FORCE_INLINE constexpr fixed_point(IntT n) FL_NOEXCEPT
FASTLED_FORCE_INLINE constexpr fixed_point(float f) FL_NOEXCEPT
static constexpr FASTLED_FORCE_INLINE fixed_point ceil(fixed_point x) FL_NOEXCEPT
constexpr FASTLED_FORCE_INLINE bool operator>=(fixed_point b) const FL_NOEXCEPT
decltype(Base().raw()) RawType
FASTLED_FORCE_INLINE constexpr RawType raw() const FL_NOEXCEPT
constexpr FASTLED_FORCE_INLINE fixed_point operator/(fixed_point b) const FL_NOEXCEPT
static FASTLED_FORCE_INLINE fixed_point acos(fixed_point x) FL_NOEXCEPT
constexpr FASTLED_FORCE_INLINE bool operator!=(fixed_point b) const FL_NOEXCEPT
static constexpr FASTLED_FORCE_INLINE fixed_point sign(fixed_point x) FL_NOEXCEPT
typename fixed_point_impl< IntBits, FracBits, S >::type Base
static FASTLED_FORCE_INLINE fixed_point smoothstep(fixed_point edge0, fixed_point edge1, fixed_point x) FL_NOEXCEPT
constexpr FASTLED_FORCE_INLINE fixed_point operator*(fixed_point b) const FL_NOEXCEPT
static constexpr FASTLED_FORCE_INLINE fixed_point step(fixed_point edge, fixed_point x) FL_NOEXCEPT
static FASTLED_FORCE_INLINE void sincos(fixed_point angle, fixed_point &out_sin, fixed_point &out_cos) FL_NOEXCEPT
constexpr FASTLED_FORCE_INLINE fixed_point operator-(fixed_point b) const FL_NOEXCEPT
constexpr FASTLED_FORCE_INLINE bool operator<(fixed_point b) const FL_NOEXCEPT
constexpr FASTLED_FORCE_INLINE bool operator<=(fixed_point b) const FL_NOEXCEPT
static constexpr FASTLED_FORCE_INLINE fixed_point fract(fixed_point x) FL_NOEXCEPT
constexpr FASTLED_FORCE_INLINE i32 to_int() const FL_NOEXCEPT
friend constexpr fixed_point operator*(i32 scalar, fixed_point fp) FL_NOEXCEPT
static FASTLED_FORCE_INLINE fixed_point pow(fixed_point base, fixed_point exp) FL_NOEXCEPT
typename conditional<(S==Sign::SIGNED), i64, u64 >::type PromotionType
static constexpr FASTLED_FORCE_INLINE fixed_point sqrt(fixed_point x) FL_NOEXCEPT
constexpr s0x32() FL_NOEXCEPT=default
constexpr FASTLED_FORCE_INLINE s0x32 operator*(s0x32 b) const FL_NOEXCEPT
Definition s0x32.h:99
static constexpr FASTLED_FORCE_INLINE s16x16 from_raw(i32 raw) FL_NOEXCEPT
Definition s16x16.h:54
#define FL_E
Definition math.h:30
constexpr int type_rank< T >::value
enable_if< is_fixed_point< T >::value, T >::type atan2(T y, T x) FL_NOEXCEPT
constexpr enable_if< is_fixed_point< T >::value, T >::type ceil(T x) FL_NOEXCEPT
enable_if< is_fixed_point< T >::value, T >::type smoothstep(T edge0, T edge1, T x) FL_NOEXCEPT
enable_if< is_fixed_point< T >::value, void >::type sincos(T angle, T &out_sin, T &out_cos) FL_NOEXCEPT
constexpr enable_if< is_fixed_point< T >::value, T >::type sqrt(T x) FL_NOEXCEPT
FASTLED_FORCE_INLINE CRGB operator*(const CRGB &p1, u8 d) FL_NOEXCEPT
Multiply each of the channels by a constant, saturating each channel at 0xFF.
Definition crgb.hpp:198
constexpr enable_if< is_fixed_point< T >::value, T >::type floor(T x) FL_NOEXCEPT
constexpr enable_if< is_fixed_point< T >::value, T >::type fract(T x) FL_NOEXCEPT
constexpr enable_if< is_fixed_point< T >::value, int >::type sign(T x) FL_NOEXCEPT
enable_if< is_fixed_point< T >::value, T >::type acos(T x) FL_NOEXCEPT
enable_if< is_fixed_point< T >::value, T >::type powfp(T base, T exp) FL_NOEXCEPT
fl::i64 i64
Definition s16x16x4.h:222
enable_if< is_fixed_point< T >::value, T >::type expfp(T x) FL_NOEXCEPT
enable_if< is_fixed_point< T >::value, T >::type pow(T base, T exp) FL_NOEXCEPT
fixed_point< IntBits, FracBits, Sign::UNSIGNED > ufixed_integer
sfixed_integer< IntBits, FracBits > sfixed_point
enable_if< is_fixed_point< T >::value, T >::type cos(T angle) FL_NOEXCEPT
constexpr enable_if< is_fixed_point< T >::value, T >::type step(T edge, T x) FL_NOEXCEPT
enable_if< is_fixed_point< T >::value, T >::type sin(T angle) FL_NOEXCEPT
constexpr enable_if< is_fixed_point< T >::value, T >::type rsqrt(T x) FL_NOEXCEPT
enable_if< is_fixed_point< T >::value, T >::type asin(T x) FL_NOEXCEPT
fl::u64 u64
Definition s16x16x4.h:221
enable_if< is_fixed_point< T >::value, T >::type exp(T x) FL_NOEXCEPT
integral_constant< bool, true > true_type
Definition type_traits.h:27
constexpr enable_if< is_fixed_point< T >::value, T >::type abs(T x) FL_NOEXCEPT
ufixed_integer< IntBits, FracBits > ufixed_point
fixed_point< IntBits, FracBits, Sign::SIGNED > sfixed_integer
enable_if< is_fixed_point< T >::value, T >::type atan(T x) FL_NOEXCEPT
constexpr enable_if< is_fixed_point< T >::value, T >::type mod(T a, T b) FL_NOEXCEPT
constexpr enable_if< is_fixed_point< T >::value, T >::type clamp(T x, T lo, T hi) FL_NOEXCEPT
FASTLED_FORCE_INLINE float lerp(float t, float a, float b)
Base definition for an LED controller.
Definition crgb.hpp:179
#define FASTLED_FORCE_INLINE
#define FL_NOEXCEPT
static constexpr bool value