123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- // go-qrcode
- // Copyright 2014 Tom Harwood
- package reedsolomon
- import (
- "fmt"
- "log"
- bitset "github.com/skip2/go-qrcode/bitset"
- )
- // gfPoly is a polynomial over GF(2^8).
- type gfPoly struct {
- // The ith value is the coefficient of the ith degree of x.
- // term[0]*(x^0) + term[1]*(x^1) + term[2]*(x^2) ...
- term []gfElement
- }
- // newGFPolyFromData returns |data| as a polynomial over GF(2^8).
- //
- // Each data byte becomes the coefficient of an x term.
- //
- // For an n byte input the polynomial is:
- // data[n-1]*(x^n-1) + data[n-2]*(x^n-2) ... + data[0]*(x^0).
- func newGFPolyFromData(data *bitset.Bitset) gfPoly {
- numTotalBytes := data.Len() / 8
- if data.Len()%8 != 0 {
- numTotalBytes++
- }
- result := gfPoly{term: make([]gfElement, numTotalBytes)}
- i := numTotalBytes - 1
- for j := 0; j < data.Len(); j += 8 {
- result.term[i] = gfElement(data.ByteAt(j))
- i--
- }
- return result
- }
- // newGFPolyMonomial returns term*(x^degree).
- func newGFPolyMonomial(term gfElement, degree int) gfPoly {
- if term == gfZero {
- return gfPoly{}
- }
- result := gfPoly{term: make([]gfElement, degree+1)}
- result.term[degree] = term
- return result
- }
- func (e gfPoly) data(numTerms int) []byte {
- result := make([]byte, numTerms)
- i := numTerms - len(e.term)
- for j := len(e.term) - 1; j >= 0; j-- {
- result[i] = byte(e.term[j])
- i++
- }
- return result
- }
- // numTerms returns the number of
- func (e gfPoly) numTerms() int {
- return len(e.term)
- }
- // gfPolyMultiply returns a * b.
- func gfPolyMultiply(a, b gfPoly) gfPoly {
- numATerms := a.numTerms()
- numBTerms := b.numTerms()
- result := gfPoly{term: make([]gfElement, numATerms+numBTerms)}
- for i := 0; i < numATerms; i++ {
- for j := 0; j < numBTerms; j++ {
- if a.term[i] != 0 && b.term[j] != 0 {
- monomial := gfPoly{term: make([]gfElement, i+j+1)}
- monomial.term[i+j] = gfMultiply(a.term[i], b.term[j])
- result = gfPolyAdd(result, monomial)
- }
- }
- }
- return result.normalised()
- }
- // gfPolyRemainder return the remainder of numerator / denominator.
- func gfPolyRemainder(numerator, denominator gfPoly) gfPoly {
- if denominator.equals(gfPoly{}) {
- log.Panicln("Remainder by zero")
- }
- remainder := numerator
- for remainder.numTerms() >= denominator.numTerms() {
- degree := remainder.numTerms() - denominator.numTerms()
- coefficient := gfDivide(remainder.term[remainder.numTerms()-1],
- denominator.term[denominator.numTerms()-1])
- divisor := gfPolyMultiply(denominator,
- newGFPolyMonomial(coefficient, degree))
- remainder = gfPolyAdd(remainder, divisor)
- }
- return remainder.normalised()
- }
- // gfPolyAdd returns a + b.
- func gfPolyAdd(a, b gfPoly) gfPoly {
- numATerms := a.numTerms()
- numBTerms := b.numTerms()
- numTerms := numATerms
- if numBTerms > numTerms {
- numTerms = numBTerms
- }
- result := gfPoly{term: make([]gfElement, numTerms)}
- for i := 0; i < numTerms; i++ {
- switch {
- case numATerms > i && numBTerms > i:
- result.term[i] = gfAdd(a.term[i], b.term[i])
- case numATerms > i:
- result.term[i] = a.term[i]
- default:
- result.term[i] = b.term[i]
- }
- }
- return result.normalised()
- }
- func (e gfPoly) normalised() gfPoly {
- numTerms := e.numTerms()
- maxNonzeroTerm := numTerms - 1
- for i := numTerms - 1; i >= 0; i-- {
- if e.term[i] != 0 {
- break
- }
- maxNonzeroTerm = i - 1
- }
- if maxNonzeroTerm < 0 {
- return gfPoly{}
- } else if maxNonzeroTerm < numTerms-1 {
- e.term = e.term[0 : maxNonzeroTerm+1]
- }
- return e
- }
- func (e gfPoly) string(useIndexForm bool) string {
- var str string
- numTerms := e.numTerms()
- for i := numTerms - 1; i >= 0; i-- {
- if e.term[i] > 0 {
- if len(str) > 0 {
- str += " + "
- }
- if !useIndexForm {
- str += fmt.Sprintf("%dx^%d", e.term[i], i)
- } else {
- str += fmt.Sprintf("a^%dx^%d", gfLogTable[e.term[i]], i)
- }
- }
- }
- if len(str) == 0 {
- str = "0"
- }
- return str
- }
- // equals returns true if e == other.
- func (e gfPoly) equals(other gfPoly) bool {
- var minecPoly *gfPoly
- var maxecPoly *gfPoly
- if e.numTerms() > other.numTerms() {
- minecPoly = &other
- maxecPoly = &e
- } else {
- minecPoly = &e
- maxecPoly = &other
- }
- numMinTerms := minecPoly.numTerms()
- numMaxTerms := maxecPoly.numTerms()
- for i := 0; i < numMinTerms; i++ {
- if e.term[i] != other.term[i] {
- return false
- }
- }
- for i := numMinTerms; i < numMaxTerms; i++ {
- if maxecPoly.term[i] != 0 {
- return false
- }
- }
- return true
- }
|