Documentation
¶
Overview ¶
Package flfsr implements a Fibonacci linear feedback shift register over any unsigned word width.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrZeroPoly is returned when a register is built with no taps. Such a // register only shifts zeros in and dies at the all-zero state. ErrZeroPoly = errors.New("flfsr: polynomial must be non-zero") // ErrZeroSeed is returned when a register is seeded with zero. The all-zero // state is a fixed point: every subsequent output would be zero. ErrZeroSeed = errors.New("flfsr: seed must be non-zero") )
Functions ¶
This section is empty.
Types ¶
type FLFSR ¶
FLFSR is a Fibonacci linear feedback shift register over a W-wide state.
The register shifts towards the most significant bit. Each clock emits the outgoing top bit and feeds the parity of the tapped bits back into bit 0.
The zero value is not usable; build one with New.
func New ¶
New builds a Fibonacci LFSR of the width of W.
poly is a tap mask over register bit positions, not a table of polynomial exponents. Because the register shifts up, mask bit i stands for the term x^(n-1-i) of the feedback polynomial, where n is the width of W. The x^n term is implicit, being the feedback itself, while the polynomial's constant term lands on bit n-1; a primitive polynomial always has a constant term, so the top bit of a usable mask is always set. Mask 0xB8 taps register bits 7, 5, 4 and 3, which is the degree-8 polynomial x^8 + x^4 + x^3 + x^2 + 1.
Most published tap tables describe right-shifting registers. Such a mask used here yields the reciprocal of the polynomial the table names. That costs nothing in practice, since the reciprocal of a primitive polynomial is itself primitive and has the same period, but it does mean the sequence is not the one the table describes.
Reaching the maximal period of 2^n - 1 requires poly to be primitive over GF(2); New only rejects the degenerate masks, it does not check primitivity. Any non-zero seed will do, and the seed is itself a state on the cycle.
Example ¶
Build an 8-bit register from the polynomial x^8 + x^4 + x^3 + x^2 + 1, whose taps on register bits 7, 5, 4 and 3 give the mask 0xB8, then read its bit stream.
package main
import (
"fmt"
"log"
"github.com/1995parham/LFSR.go/flfsr"
)
func main() {
f, err := flfsr.New[uint8](0xB8, 0x40)
if err != nil {
log.Fatal(err)
}
for range 8 {
fmt.Print(f.Next())
}
fmt.Println()
}
Output: 01000000
func (*FLFSR[W]) State ¶
func (f *FLFSR[W]) State() W
State reports the current register contents without clocking it.
func (*FLFSR[W]) Uint ¶
func (f *FLFSR[W]) Uint() W
Uint clocks the register once per bit of W and packs the outgoing bits into a word, most significant bit first.
Example ¶
The width of the type argument picks the register width, so the same code drives a 16-bit register built from x^16 + x^5 + x^3 + x^2 + 1.
Note the first word: a register shifts its seed out before it shifts anything else, so the opening Uint of a freshly built register always reproduces the seed. Discard it if the seed is not meant to be observable.
package main
import (
"fmt"
"log"
"github.com/1995parham/LFSR.go/flfsr"
)
func main() {
f, err := flfsr.New[uint16](0xB400, 0xACE1)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%#04x %#04x %#04x\n", f.Uint(), f.Uint(), f.Uint())
}
Output: 0xace1 0xe455 0xdd17