flfsr

package
v0.0.0-...-e61ebc9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 17, 2026 License: GPL-3.0 Imports: 3 Imported by: 0

Documentation

Overview

Package flfsr implements a Fibonacci linear feedback shift register over any unsigned word width.

Index

Examples

Constants

This section is empty.

Variables

View Source
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

type FLFSR[W lfsr.Word] struct {
	// contains filtered or unexported fields
}

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

func New[W lfsr.Word](poly, seed W) (*FLFSR[W], error)

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]) Next

func (f *FLFSR[W]) Next() uint8

Next clocks the register once and reports the bit shifted out of the top.

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

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL