UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
LFSR.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreTypes.h"
7
8namespace UE
9{
10
11namespace Math
12{
13
14// See https://en.wikipedia.org/wiki/Linear-feedback_shift_register
15// This implements maximal-length feedback polynomials LFSR for N bits in [2, 12].
17{
18public:
19
21
22 // LFSR numbers usually only include N^2-1 numbers for N bit.
23 // We do apply a -1 to get the value 0 out.
24 // So, for N=4, it should return {0, 1, 2} in random order.
26 {
27 return GetNextValueInternal(N, /*IncludeLast*/false);
28 }
29
30 // This function is the same as above.
31 // But it will also return the last value N^2-1.
32 // So, for N=4, it will return {0, 1, 2, 3} in random order.
34 {
35 return GetNextValueInternal(N, /*IncludeLast*/true);
36 }
37
38private:
39
40 const uint32 StartState = 1;
41 uint32 State = StartState;
42
43 uint32 GetNextValueInternal(uint32 N, bool IncludeLast)
44 {
45 // TODO LFRS code could be put in its own h/cpp for encapsulation and reusability
47 {
48 if (IncludeLast && State == 0)
49 {
50 // LFSR loops over 2^m-1 values excluding 0. The returned value has -1 apply to get 0. So we need to generate the last 2^N-1 value.
51 // We use LFSRCache==0 to detect that case and return the last mask value being 0.
52 State = StartState;
53 return Mask;
54 }
55
56 // Update the cach value.
57 uint32 Tap = ((Taps0 & State) == 0 ? 0 : 1) ^ ((Taps1 & State) == 0 ? 0 : 1);
58 if (Taps2 > 0)
59 {
60 Tap ^= ((Taps2 & State) == 0 ? 0 : 1);
61 }
62 if (Taps3 > 0)
63 {
64 Tap ^= ((Taps3 & State) == 0 ? 0 : 1);
65 }
66 State = ((State << 1) | Tap) & Mask;
67
68 uint32 ValueToReturn = State - 1;
69 if (IncludeLast && State == StartState)
70 {
71 State = 0;
72 }
73
74 return ValueToReturn % Mask;
75 };
76
77 check(N >= 2 && N <=12);
78
79 uint32 NewValue = 0;
80 if (N == 2) // 2 bits
81 {
82 NewValue = CalcLFSRValue(1 << 1, 1 << 0, 0, 0, 0x3);
83 }
84 else if (N == 3)
85 {
86 NewValue = CalcLFSRValue(1 << 2, 1 << 1, 0, 0, 0x7);
87 }
88 else if (N == 4)
89 {
90 NewValue = CalcLFSRValue(1 << 3, 1 << 2, 0, 0, 0xF);
91 }
92 else if (N == 5)
93 {
94 NewValue = CalcLFSRValue(1 << 4, 1 << 2, 0, 0, 0x1F);
95 }
96 else if (N == 6)
97 {
98 NewValue = CalcLFSRValue(1 << 5, 1 << 4, 0, 0, 0x3F);
99 }
100 else if (N == 7)
101 {
102 NewValue = CalcLFSRValue(1 << 6, 1 << 5, 0, 0, 0x7F);
103 }
104 else if (N == 8)
105 {
106 NewValue = CalcLFSRValue(1 << 7, 1 << 5, 1 << 4, 1 << 3, 0xFF);
107 }
108 else if (N == 9)
109 {
110 NewValue = CalcLFSRValue(1 << 8, 1 << 4, 0, 0, 0x1FF);
111 }
112 else if (N == 10)
113 {
114 NewValue = CalcLFSRValue(1 << 9, 1 << 6, 0, 0, 0x3FF);
115 }
116 else if (N == 11)
117 {
118 NewValue = CalcLFSRValue(1 << 10, 1 << 10, 0, 0, 0x7FF);
119 }
120 else if (N == 12)
121 {
122 NewValue = CalcLFSRValue(1 << 11, 1 << 10, 1 << 9, 1 << 3, 0xFFF);
123 }
124 return NewValue;
125 }
126};
127
128} // namespace UE::Math
129
130} // namespace UE
#define check(expr)
Definition AssertionMacros.h:314
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
uint32_t uint32
Definition binka_ue_file_header.h:6
FLinearFeedbackShiftRegister()
Definition LFSR.h:20
uint32 GetNextValue(uint32 N)
Definition LFSR.h:25
uint32 GetNextValueWithLast(uint32 N)
Definition LFSR.h:33
State
Definition PacketHandler.h:88
Definition AdvancedWidgetsModule.cpp:13