FastLED 3.9.15
Loading...
Searching...
No Matches
u0x32.h
Go to the documentation of this file.
1#pragma once
2
3// Unsigned 0.32 fixed-point arithmetic.
4// Represents normalized values in range [0.0, 1.0).
5
6#include "fl/stl/int.h"
9#include "fl/stl/noexcept.h"
10#include "fl/stl/undef.h" // Undefine abs/min/max macros from Arduino.h
11
13
14namespace fl {
15
16// Forward declaration for cross-type operations
17class s16x16;
18
19// Unsigned 0.32 fixed-point value type (UQ32 format).
20// Represents values in range [0.0, 1.0) using all 32 bits for fractional precision.
21//
22// Bit layout (u32 storage):
23// Bits 31-0: Fractional magnitude (32 bits of precision)
24// Value interpretation: raw_u32 / 2^32
25//
26// Primary use cases:
27// - Normalized alpha/opacity values
28// - Color blending factors
29// - Normalized coordinate systems (unsigned)
30// - Probability values
31class u0x32 {
32 public:
33 static constexpr int INT_BITS = 0; // No integer bits (always in [0, 1))
34 static constexpr int FRAC_BITS = 32; // 32 fractional bits (all bits)
35
36 // ---- Construction ------------------------------------------------------
37
38 constexpr u0x32() FL_NOEXCEPT = default;
39
40 // Construct from float (clamps to [0.0, 1.0) range)
41 // UQ32 format: max value is 0xFFFFFFFF (just under 1.0), min is 0 (exactly 0.0)
42 explicit constexpr u0x32(float f) FL_NOEXCEPT
43 : mValue(f <= 0.0f ? 0U : // Exactly 0.0
44 f >= 1.0f ? 0xFFFFFFFFU : // Max positive (0.9999999997...)
45 static_cast<u32>(f * 4294967296.0f)) {}
46
47 // Auto-promotion from other fixed-point types
48 // u0x32 has INT_BITS=0, so it can only accept types with INT_BITS=0
49 // and FRAC_BITS ≤ 32 (but since u0x32 has the most fractional precision, no other type qualifies)
50 // This constructor allows future expansion if more normalized types are added
51 template <typename OtherFP>
52 constexpr u0x32(const OtherFP& other,
53 typename fl::enable_if<
54 (OtherFP::INT_BITS <= INT_BITS) &&
55 (OtherFP::FRAC_BITS <= FRAC_BITS) &&
56 (OtherFP::INT_BITS != INT_BITS || OtherFP::FRAC_BITS != FRAC_BITS),
57 int>::type = 0)
58 FL_NOEXCEPT : mValue(static_cast<u32>(
59 static_cast<u64>(other.raw()) << (FRAC_BITS - OtherFP::FRAC_BITS))) {}
60
61 // Construct from raw u32 value (UQ32 format)
62 // Raw constructor for C++11 constexpr from_raw
63 struct RawTag {};
64 constexpr explicit u0x32(u32 raw, RawTag) FL_NOEXCEPT : mValue(raw) {}
65
67 return u0x32(raw, RawTag());
68 }
69
70 // ---- Access ------------------------------------------------------------
71
72 constexpr u32 raw() const FL_NOEXCEPT { return mValue; }
73
74 // Convert to integer (always 0 since range is [0.0, 1.0))
75 constexpr u32 to_int() const FL_NOEXCEPT { return 0; }
76
77 constexpr float to_float() const FL_NOEXCEPT {
78 return static_cast<float>(mValue) / 4294967296.0f;
79 }
80
81 // ---- Same-type arithmetic (u0x32 OP u0x32 → u0x32) --------------------
82
84 // Saturating add to prevent overflow
85 u32 result = mValue + b.mValue;
86 if (result < mValue) return from_raw(0xFFFFFFFFU); // Overflow, clamp to max
87 return from_raw(result);
88 }
89
91 // Saturating subtract to prevent underflow
92 if (b.mValue > mValue) return from_raw(0); // Underflow, clamp to 0
93 return from_raw(mValue - b.mValue);
94 }
95
96 // Multiply two normalized values: u0x32 × u0x32 → u0x32
97 // Both inputs < 1.0, so product < 1.0
99 // UQ32 × UQ32 = UQ64 → shift right 32 → UQ32
100 return from_raw(static_cast<u32>(
101 (static_cast<u64>(mValue) * b.mValue) >> 32));
102 }
103
104 // Divide normalized values: u0x32 / u0x32 → u0x32
106 // UQ32 / UQ32: shift dividend left 32 bits then divide
107 // (a / 2^32) / (b / 2^32) = a / b → need (a << 32) / b
108 if (b.mValue == 0) return from_raw(0xFFFFFFFFU); // Division by zero, return max
109 u64 result = (static_cast<u64>(mValue) << 32) / b.mValue;
110 if (result > 0xFFFFFFFFULL) return from_raw(0xFFFFFFFFU); // Overflow, saturate to max
111 return from_raw(static_cast<u32>(result));
112 }
113
115 return from_raw(mValue >> shift);
116 }
117
119 return from_raw(mValue << shift);
120 }
121
122 // ---- Scalar arithmetic (u0x32 × raw integer → u0x32) ------------------
123
124 constexpr FASTLED_FORCE_INLINE u0x32 operator*(u32 scalar) const FL_NOEXCEPT {
125 // UQ32 * scalar with saturation to prevent overflow
126 return (static_cast<u64>(mValue) * scalar > 0xFFFFFFFFULL)
127 ? from_raw(0xFFFFFFFFU)
128 : from_raw(static_cast<u32>(static_cast<u64>(mValue) * scalar));
129 }
130
131 friend constexpr u0x32 operator*(u32 scalar, u0x32 a) FL_NOEXCEPT {
132 return a * scalar; // Commutative
133 }
134
135 constexpr FASTLED_FORCE_INLINE u0x32 operator/(u32 scalar) const FL_NOEXCEPT {
136 return (scalar == 0) ? from_raw(0xFFFFFFFFU) : from_raw(mValue / scalar);
137 }
138
139 // ---- Math functions ----------------------------------------------------
140
142 return from_raw(a.mValue < b.mValue ? a.mValue : b.mValue);
143 }
144
146 return from_raw(a.mValue > b.mValue ? a.mValue : b.mValue);
147 }
148
149 static constexpr FASTLED_FORCE_INLINE u0x32 clamp(u0x32 val, u0x32 low, u0x32 high) FL_NOEXCEPT {
150 return max(low, min(val, high));
151 }
152
153 // ---- Comparisons -------------------------------------------------------
154
155 constexpr bool operator<(u0x32 b) const FL_NOEXCEPT { return mValue < b.mValue; }
156 constexpr bool operator>(u0x32 b) const FL_NOEXCEPT { return mValue > b.mValue; }
157 constexpr bool operator<=(u0x32 b) const FL_NOEXCEPT { return mValue <= b.mValue; }
158 constexpr bool operator>=(u0x32 b) const FL_NOEXCEPT { return mValue >= b.mValue; }
159 constexpr bool operator==(u0x32 b) const FL_NOEXCEPT { return mValue == b.mValue; }
160 constexpr bool operator!=(u0x32 b) const FL_NOEXCEPT { return mValue != b.mValue; }
161
162 private:
163 u32 mValue = 0;
164};
165
166} // namespace fl
167
FASTLED_FORCE_INLINE u0x32 operator/(u0x32 b) const FL_NOEXCEPT
Definition u0x32.h:105
static constexpr int INT_BITS
Definition u0x32.h:33
constexpr bool operator!=(u0x32 b) const FL_NOEXCEPT
Definition u0x32.h:160
constexpr u0x32() FL_NOEXCEPT=default
constexpr u0x32(u32 raw, RawTag) FL_NOEXCEPT
Definition u0x32.h:64
constexpr FASTLED_FORCE_INLINE u0x32 operator/(u32 scalar) const FL_NOEXCEPT
Definition u0x32.h:135
constexpr FASTLED_FORCE_INLINE u0x32 operator*(u0x32 b) const FL_NOEXCEPT
Definition u0x32.h:98
constexpr float to_float() const FL_NOEXCEPT
Definition u0x32.h:77
constexpr u0x32(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_NOEXCEPT
Definition u0x32.h:52
static constexpr FASTLED_FORCE_INLINE u0x32 clamp(u0x32 val, u0x32 low, u0x32 high) FL_NOEXCEPT
Definition u0x32.h:149
constexpr FASTLED_FORCE_INLINE u0x32 operator<<(int shift) const FL_NOEXCEPT
Definition u0x32.h:118
constexpr bool operator==(u0x32 b) const FL_NOEXCEPT
Definition u0x32.h:159
constexpr u32 raw() const FL_NOEXCEPT
Definition u0x32.h:72
static constexpr int FRAC_BITS
Definition u0x32.h:34
FASTLED_FORCE_INLINE u0x32 operator+(u0x32 b) const FL_NOEXCEPT
Definition u0x32.h:83
constexpr bool operator<=(u0x32 b) const FL_NOEXCEPT
Definition u0x32.h:157
constexpr u32 to_int() const FL_NOEXCEPT
Definition u0x32.h:75
constexpr bool operator>=(u0x32 b) const FL_NOEXCEPT
Definition u0x32.h:158
FASTLED_FORCE_INLINE u0x32 operator-(u0x32 b) const FL_NOEXCEPT
Definition u0x32.h:90
friend constexpr u0x32 operator*(u32 scalar, u0x32 a) FL_NOEXCEPT
Definition u0x32.h:131
static constexpr FASTLED_FORCE_INLINE u0x32 from_raw(u32 raw) FL_NOEXCEPT
Definition u0x32.h:66
static constexpr FASTLED_FORCE_INLINE u0x32 min(u0x32 a, u0x32 b) FL_NOEXCEPT
Definition u0x32.h:141
constexpr FASTLED_FORCE_INLINE u0x32 operator*(u32 scalar) const FL_NOEXCEPT
Definition u0x32.h:124
static constexpr FASTLED_FORCE_INLINE u0x32 max(u0x32 a, u0x32 b) FL_NOEXCEPT
Definition u0x32.h:145
constexpr bool operator>(u0x32 b) const FL_NOEXCEPT
Definition u0x32.h:156
constexpr bool operator<(u0x32 b) const FL_NOEXCEPT
Definition u0x32.h:155
constexpr FASTLED_FORCE_INLINE u0x32 operator>>(int shift) const FL_NOEXCEPT
Definition u0x32.h:114
u32 mValue
Definition u0x32.h:163
#define constexpr
Declares that it is possible to evaluate a value at compile time, introduced in C++11.
Definition cpp_compat.h:15
expected< T, E > result
Alias for expected (Rust-style naming)
Definition result.h:31
fl::u64 u64
Definition s16x16x4.h:221
Base definition for an LED controller.
Definition crgb.hpp:179
#define FL_OPTIMIZATION_LEVEL_O3_BEGIN
#define FASTLED_FORCE_INLINE
#define FL_OPTIMIZATION_LEVEL_O3_END
#define FL_NOEXCEPT