// Copyright 2010 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.
// Package gf256 implements arithmetic over the Galois Field GF(256).
package gf256 // import "rsc.io/qr/gf256"import// A Field represents an instance of GF(256) defined by a specific polynomial.typeFieldstruct {log [256]byte// log[0] is unusedexp [510]byte}// NewField returns a new field corresponding to the polynomial poly// and generator α. The Reed-Solomon encoding in QR codes uses// polynomial 0x11d with generator 2.//// The choice of generator α only affects the Exp and Log operations.func (, int) *Field {if < 0x100 || >= 0x200 || reducible() {panic("gf256: invalid polynomial: " + strconv.Itoa()) }varField := 1for := 0; < 255; ++ {if == 1 && != 0 {panic("gf256: invalid generator " + strconv.Itoa() +" for polynomial " + strconv.Itoa()) } .exp[] = byte() .exp[+255] = byte() .log[] = byte() = mul(, , ) } .log[0] = 255for := 0; < 255; ++ {if .log[.exp[]] != byte() {panic("bad log") }if .log[.exp[+255]] != byte() {panic("bad log") } }for := 1; < 256; ++ {if .exp[.log[]] != byte() {panic("bad log") } }return &}// nbit returns the number of significant in p.func ( int) uint { := uint(0)for ; > 0; >>= 1 { ++ }return}// polyDiv divides the polynomial p by q and returns the remainder.func (, int) int { := nbit() := nbit()for ; >= ; -- {if &(1<<(-1)) != 0 { ^= << ( - ) } }return}// mul returns the product x*y mod poly, a GF(256) multiplication.func (, , int) int { := 0for > 0 {if &1 != 0 { ^= } >>= 1 <<= 1if &0x100 != 0 { ^= } }return}// reducible reports whether p is reducible.func ( int) bool {// Multiplying n-bit * n-bit produces (2n-1)-bit, // so if p is reducible, one of its factors must be // of np/2+1 bits or fewer. := nbit()for := 2; < 1<<(/2+1); ++ {ifpolyDiv(, ) == 0 {returntrue } }returnfalse}// Add returns the sum of x and y in the field.func ( *Field) (, byte) byte {return ^ }// Exp returns the base-α exponential of e in the field.// If e < 0, Exp returns 0.func ( *Field) ( int) byte {if < 0 {return0 }return .exp[%255]}// Log returns the base-α logarithm of x in the field.// If x == 0, Log returns -1.func ( *Field) ( byte) int {if == 0 {return -1 }returnint(.log[])}// Inv returns the multiplicative inverse of x in the field.// If x == 0, Inv returns 0.func ( *Field) ( byte) byte {if == 0 {return0 }return .exp[255-.log[]]}// Mul returns the product of x and y in the field.func ( *Field) (, byte) byte {if == 0 || == 0 {return0 }return .exp[int(.log[])+int(.log[])]}// An RSEncoder implements Reed-Solomon encoding// over a given field using a given number of error correction bytes.typeRSEncoderstruct {f *Fieldcintgen []bytelgen []bytep []byte}func ( *Field) ( int) (, []byte) {// p = 1 := make([]byte, +1) [] = 1for := 0; < ; ++ {// p *= (x + Exp(i)) // p[j] = p[j]*Exp(i) + p[j+1]. := .Exp()for := 0; < ; ++ { [] = .Mul([], ) ^ [+1] } [] = .Mul([], ) }// lp = log p. := make([]byte, +1)for , := range {if == 0 { [] = 255 } else { [] = byte(.Log()) } }return , }// NewRSEncoder returns a new Reed-Solomon encoder// over the given field and number of error correction bytes.func ( *Field, int) *RSEncoder { , := .gen()return &RSEncoder{f: , c: , gen: , lgen: }}// ECC writes to check the error correcting code bytes// for data using the given Reed-Solomon parameters.func ( *RSEncoder) ( []byte, []byte) {iflen() < .c {panic("gf256: invalid check byte length") }if .c == 0 {return }// The check bytes are the remainder after dividing // data padded with c zeros by the generator polynomial.// p = data padded with c zeros.var []byte := len() + .ciflen(.p) >= { = .p } else { = make([]byte, ) }copy(, )for := len(); < len(); ++ { [] = 0 }// Divide p by gen, leaving the remainder in p[len(data):]. // p[0] is the most significant term in p, and // gen[0] is the most significant term in the generator, // which is always 1. // To avoid repeated work, we store various values as // lv, not v, where lv = log[v]. := .f := .lgen[1:]for := 0; < len(); ++ { := []if == 0 {continue } := [+1:] := .exp[.log[]:]for , := range {if != 255 { // lgen uses 255 for log 0 [] ^= [] } } }copy(, [len():]) .p = }
The pages are generated with Goldsv0.6.7. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds.