// 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. type Field struct { log [256]byte // log[0] is unused exp [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()) } var Field := 1 for := 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] = 255 for := 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 { := 0 for > 0 { if &1 != 0 { ^= } >>= 1 <<= 1 if &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); ++ { if polyDiv(, ) == 0 { return true } } return false } // 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 { return 0 } 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 } return int(.log[]) } // Inv returns the multiplicative inverse of x in the field. // If x == 0, Inv returns 0. func ( *Field) ( byte) byte { if == 0 { return 0 } return .exp[255-.log[]] } // Mul returns the product of x and y in the field. func ( *Field) (, byte) byte { if == 0 || == 0 { return 0 } return .exp[int(.log[])+int(.log[])] } // An RSEncoder implements Reed-Solomon encoding // over a given field using a given number of error correction bytes. type RSEncoder struct { f *Field c int gen []byte lgen []byte p []byte } func ( *Field) ( int) (, []byte) { // p = 1 := make([]byte, +1) [] = 1 for := 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) { if len() < .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() + .c if len(.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 = }