123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- // 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 "strconv"
- // 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 NewField(poly, α int) *Field {
- if poly < 0x100 || poly >= 0x200 || reducible(poly) {
- panic("gf256: invalid polynomial: " + strconv.Itoa(poly))
- }
- var f Field
- x := 1
- for i := 0; i < 255; i++ {
- if x == 1 && i != 0 {
- panic("gf256: invalid generator " + strconv.Itoa(α) +
- " for polynomial " + strconv.Itoa(poly))
- }
- f.exp[i] = byte(x)
- f.exp[i+255] = byte(x)
- f.log[x] = byte(i)
- x = mul(x, α, poly)
- }
- f.log[0] = 255
- for i := 0; i < 255; i++ {
- if f.log[f.exp[i]] != byte(i) {
- panic("bad log")
- }
- if f.log[f.exp[i+255]] != byte(i) {
- panic("bad log")
- }
- }
- for i := 1; i < 256; i++ {
- if f.exp[f.log[i]] != byte(i) {
- panic("bad log")
- }
- }
- return &f
- }
- // nbit returns the number of significant in p.
- func nbit(p int) uint {
- n := uint(0)
- for ; p > 0; p >>= 1 {
- n++
- }
- return n
- }
- // polyDiv divides the polynomial p by q and returns the remainder.
- func polyDiv(p, q int) int {
- np := nbit(p)
- nq := nbit(q)
- for ; np >= nq; np-- {
- if p&(1<<(np-1)) != 0 {
- p ^= q << (np - nq)
- }
- }
- return p
- }
- // mul returns the product x*y mod poly, a GF(256) multiplication.
- func mul(x, y, poly int) int {
- z := 0
- for x > 0 {
- if x&1 != 0 {
- z ^= y
- }
- x >>= 1
- y <<= 1
- if y&0x100 != 0 {
- y ^= poly
- }
- }
- return z
- }
- // reducible reports whether p is reducible.
- func reducible(p 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.
- np := nbit(p)
- for q := 2; q < 1<<(np/2+1); q++ {
- if polyDiv(p, q) == 0 {
- return true
- }
- }
- return false
- }
- // Add returns the sum of x and y in the field.
- func (f *Field) Add(x, y byte) byte {
- return x ^ y
- }
- // Exp returns the base-α exponential of e in the field.
- // If e < 0, Exp returns 0.
- func (f *Field) Exp(e int) byte {
- if e < 0 {
- return 0
- }
- return f.exp[e%255]
- }
- // Log returns the base-α logarithm of x in the field.
- // If x == 0, Log returns -1.
- func (f *Field) Log(x byte) int {
- if x == 0 {
- return -1
- }
- return int(f.log[x])
- }
- // Inv returns the multiplicative inverse of x in the field.
- // If x == 0, Inv returns 0.
- func (f *Field) Inv(x byte) byte {
- if x == 0 {
- return 0
- }
- return f.exp[255-f.log[x]]
- }
- // Mul returns the product of x and y in the field.
- func (f *Field) Mul(x, y byte) byte {
- if x == 0 || y == 0 {
- return 0
- }
- return f.exp[int(f.log[x])+int(f.log[y])]
- }
- // 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 (f *Field) gen(e int) (gen, lgen []byte) {
- // p = 1
- p := make([]byte, e+1)
- p[e] = 1
- for i := 0; i < e; i++ {
- // p *= (x + Exp(i))
- // p[j] = p[j]*Exp(i) + p[j+1].
- c := f.Exp(i)
- for j := 0; j < e; j++ {
- p[j] = f.Mul(p[j], c) ^ p[j+1]
- }
- p[e] = f.Mul(p[e], c)
- }
- // lp = log p.
- lp := make([]byte, e+1)
- for i, c := range p {
- if c == 0 {
- lp[i] = 255
- } else {
- lp[i] = byte(f.Log(c))
- }
- }
- return p, lp
- }
- // NewRSEncoder returns a new Reed-Solomon encoder
- // over the given field and number of error correction bytes.
- func NewRSEncoder(f *Field, c int) *RSEncoder {
- gen, lgen := f.gen(c)
- return &RSEncoder{f: f, c: c, gen: gen, lgen: lgen}
- }
- // ECC writes to check the error correcting code bytes
- // for data using the given Reed-Solomon parameters.
- func (rs *RSEncoder) ECC(data []byte, check []byte) {
- if len(check) < rs.c {
- panic("gf256: invalid check byte length")
- }
- if rs.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 p []byte
- n := len(data) + rs.c
- if len(rs.p) >= n {
- p = rs.p
- } else {
- p = make([]byte, n)
- }
- copy(p, data)
- for i := len(data); i < len(p); i++ {
- p[i] = 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 := rs.f
- lgen := rs.lgen[1:]
- for i := 0; i < len(data); i++ {
- c := p[i]
- if c == 0 {
- continue
- }
- q := p[i+1:]
- exp := f.exp[f.log[c]:]
- for j, lg := range lgen {
- if lg != 255 { // lgen uses 255 for log 0
- q[j] ^= exp[lg]
- }
- }
- }
- copy(check, p[len(data):])
- rs.p = p
- }
|