M5Utility 0.0.7 git rev:ba71c71
Loading...
Searching...
No Matches
lfsr.hpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD
3 *
4 * SPDX-License-Identifier: MIT
5 */
10#ifndef M5_UTILITY_LFSR_HPP
11#define M5_UTILITY_LFSR_HPP
12
13#include <bitset>
14#include <climits>
15
16namespace m5 {
17namespace utility {
18
26template <uint32_t N, uint32_t... Taps>
28 static_assert(N > 0, "N must be > 0");
29 static_assert(N <= 64, "N must be <= 64");
30 static_assert(sizeof...(Taps) >= 1, "At least one tap required");
31
32 // Tap boundary check: 1..N-1
33 template <uint32_t...>
34 struct all_valid : std::true_type {
35 //
36 };
37 template <uint32_t A, uint32_t... Rest>
38 struct all_valid<A, Rest...> : std::integral_constant<bool, (A >= 1 && A <= N) && all_valid<Rest...>::value> {
39 //
40 };
41 static_assert(all_valid<Taps...>::value, "Taps out of range");
42
43protected:
44 // XOR of taps; bit index is N - Ts (Ts is exponent)
45 template <uint32_t... Ts>
46 static bool taps_xor(const std::bitset<N>& s)
47 {
48 bool r{};
49 using swallow = int[];
50 (void)swallow{0, (r ^= s.test(N - Ts), 0)...}; // Swallow idiom
51 return r;
52 }
53
54public:
55 using state_type_t = std::bitset<N>;
56
59 explicit FibonacciLFSR_Right(const uint64_t seed) noexcept : _state{seed}
60 {
61 }
62 explicit FibonacciLFSR_Right(const state_type_t s) noexcept : _state{s}
63 {
64 }
66
68 inline const state_type_t& state() const noexcept
69 {
70 return _state;
71 }
72
74 template <typename UL = unsigned long,
75 typename std::enable_if<(sizeof(UL) * CHAR_BIT >= 64), std::nullptr_t>::type = nullptr>
76 inline uint64_t value() const
77 {
78 return static_cast<uint64_t>(_state.to_ulong());
79 }
80 template <typename UL = unsigned long,
81 typename std::enable_if<(sizeof(UL) * CHAR_BIT < 64), std::nullptr_t>::type = nullptr>
82 inline uint64_t value() const
83 {
84 return _state.to_ullong();
85 }
86
88 bool step() noexcept
89 {
90 const bool out = _state.test(0); // LSB (output)
91 const bool fb = taps_xor<Taps...>(_state); // feedback
92 _state >>= 1; // Shift to right
93 _state.set(N - 1, fb); // Insert feedback into MSB
94 return out;
95 }
96
98 uint64_t step(const uint32_t nbits) noexcept
99 {
100 uint64_t v{};
101 for (uint32_t i = 0; i < nbits; ++i) {
102 v |= (uint64_t(step()) << i);
103 }
104 return v;
105 }
106
110 inline uint16_t next16() noexcept
111 {
112 return (uint16_t)step(16);
113 }
115 inline uint32_t next32() noexcept
116 {
117 return (uint32_t)step(32);
118 }
120 inline uint64_t next64() noexcept
121 {
122 return step(64);
123 }
125
126protected:
127 static inline bool taps_xor_all(const state_type_t& s)
128 {
129 return taps_xor<Taps...>(s);
130 }
131
132 state_type_t _state;
133};
134
142template <uint32_t N, uint32_t... Taps>
144 static_assert(N > 0, "N must be > 0");
145 static_assert(N <= 64, "N must be <= 64");
146 static_assert(sizeof...(Taps) >= 1, "At least one tap required");
147
148 // Tap boundary check: 1..N-1
149 template <uint32_t...>
150 struct all_valid : std::true_type {
151 //
152 };
153 template <uint32_t A, uint32_t... Rest>
154 struct all_valid<A, Rest...> : std::integral_constant<bool, (A >= 1 && A <= N) && all_valid<Rest...>::value> {
155 //
156 };
157 static_assert(all_valid<Taps...>::value, "Taps out of range");
158
159protected:
160 // XOR of taps; bit index is N - Ts (Ts is exponent)
161 template <uint32_t... Ts>
162 static bool taps_xor(const std::bitset<N>& s)
163 {
164 bool r{};
165 using swallow = int[];
166 //(void)swallow{0, (r ^= s.test(N - Ts), 0)...}; // Swallow idiom
167 (void)swallow{0, (r ^= s.test(Ts - 1), 0)...}; // Swallow idiom
168 //(void)swallow{0, (r ^= s.test((Ts == N) ? (N - 1) : (N - Ts)), 0)...}; return r;
169 return r;
170 }
171
172public:
173 using state_type_t = std::bitset<N>;
174
177 explicit FibonacciLFSR_Left(const uint64_t seed) noexcept : _state{seed}
178 {
179 }
180 explicit FibonacciLFSR_Left(const state_type_t s) noexcept : _state{s}
181 {
182 }
184
186 inline const state_type_t& state() const noexcept
187 {
188 return _state;
189 }
190
192 template <typename UL = unsigned long,
193 typename std::enable_if<(sizeof(UL) * CHAR_BIT >= 64), std::nullptr_t>::type = nullptr>
194 inline uint64_t value() const
195 {
196 return static_cast<uint64_t>(_state.to_ulong());
197 }
198 template <typename UL = unsigned long,
199 typename std::enable_if<(sizeof(UL) * CHAR_BIT < 64), std::nullptr_t>::type = nullptr>
200 inline uint64_t value() const
201 {
202 return _state.to_ullong();
203 }
204
206 bool step() noexcept
207 {
208 const bool out = _state.test(N - 1); // MSB (output)
209 const bool fb = taps_xor<Taps...>(_state); // feedback
210 _state <<= 1; // shift to left
211 _state.set(0, fb); // insert feedback into LSB
212 return out;
213 }
214
216 uint64_t step(const uint32_t nbits) noexcept
217 {
218 uint64_t v{};
219 for (uint32_t i = 0; i < nbits; ++i) {
220 v |= (uint64_t(step()) << i); // i-th output placed at bit i
221 }
222 return v;
223 }
224
227 inline uint16_t next16() noexcept
228 {
229 return (uint16_t)step(16);
230 }
231 inline uint32_t next32() noexcept
232 {
233 return (uint32_t)step(32);
234 }
235 inline uint64_t next64() noexcept
236 {
237 return step(64);
238 }
240
241protected:
242 static inline bool taps_xor_all(const state_type_t& s)
243 {
244 return taps_xor<Taps...>(s);
245 }
246 state_type_t _state;
247};
248
249} // namespace utility
250} // namespace m5
251#endif
Fibonacci LFSR (left-shift version)
Definition lfsr.hpp:143
bool step() noexcept
Shift 1 step (Left). Returns output bit (MSB before shift)
Definition lfsr.hpp:206
uint64_t value() const
Gets the state value.
Definition lfsr.hpp:194
uint64_t step(const uint32_t nbits) noexcept
Shift nbits steps and pack outputs LSB-first.
Definition lfsr.hpp:216
const state_type_t & state() const noexcept
Gets the state.
Definition lfsr.hpp:186
Fibonacci LFSRs (right-shift version)
Definition lfsr.hpp:27
uint16_t next16() noexcept
Shift 16 bits and get.
Definition lfsr.hpp:110
std::bitset< N > state_type_t
State type.
Definition lfsr.hpp:55
uint64_t next64() noexcept
Shift 64 bits and get.
Definition lfsr.hpp:120
uint32_t next32() noexcept
Shift 32 bits and get.
Definition lfsr.hpp:115
uint64_t step(const uint32_t nbits) noexcept
Shift nbit steps and gets.
Definition lfsr.hpp:98
const state_type_t & state() const noexcept
Gets the state.
Definition lfsr.hpp:68
uint64_t value() const
Gets the state value.
Definition lfsr.hpp:76
bool step() noexcept
Shift 1 step (Right). Returns output bit (LSB before shift)
Definition lfsr.hpp:88
Top level namespace of M5.
Definition bit_segment.hpp:17
For utilities.