You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

217 lines
4.3 KiB

  1. // go-qrcode
  2. // Copyright 2014 Tom Harwood
  3. package reedsolomon
  4. import (
  5. "fmt"
  6. "log"
  7. bitset "github.com/skip2/go-qrcode/bitset"
  8. )
  9. // gfPoly is a polynomial over GF(2^8).
  10. type gfPoly struct {
  11. // The ith value is the coefficient of the ith degree of x.
  12. // term[0]*(x^0) + term[1]*(x^1) + term[2]*(x^2) ...
  13. term []gfElement
  14. }
  15. // newGFPolyFromData returns |data| as a polynomial over GF(2^8).
  16. //
  17. // Each data byte becomes the coefficient of an x term.
  18. //
  19. // For an n byte input the polynomial is:
  20. // data[n-1]*(x^n-1) + data[n-2]*(x^n-2) ... + data[0]*(x^0).
  21. func newGFPolyFromData(data *bitset.Bitset) gfPoly {
  22. numTotalBytes := data.Len() / 8
  23. if data.Len()%8 != 0 {
  24. numTotalBytes++
  25. }
  26. result := gfPoly{term: make([]gfElement, numTotalBytes)}
  27. i := numTotalBytes - 1
  28. for j := 0; j < data.Len(); j += 8 {
  29. result.term[i] = gfElement(data.ByteAt(j))
  30. i--
  31. }
  32. return result
  33. }
  34. // newGFPolyMonomial returns term*(x^degree).
  35. func newGFPolyMonomial(term gfElement, degree int) gfPoly {
  36. if term == gfZero {
  37. return gfPoly{}
  38. }
  39. result := gfPoly{term: make([]gfElement, degree+1)}
  40. result.term[degree] = term
  41. return result
  42. }
  43. func (e gfPoly) data(numTerms int) []byte {
  44. result := make([]byte, numTerms)
  45. i := numTerms - len(e.term)
  46. for j := len(e.term) - 1; j >= 0; j-- {
  47. result[i] = byte(e.term[j])
  48. i++
  49. }
  50. return result
  51. }
  52. // numTerms returns the number of
  53. func (e gfPoly) numTerms() int {
  54. return len(e.term)
  55. }
  56. // gfPolyMultiply returns a * b.
  57. func gfPolyMultiply(a, b gfPoly) gfPoly {
  58. numATerms := a.numTerms()
  59. numBTerms := b.numTerms()
  60. result := gfPoly{term: make([]gfElement, numATerms+numBTerms)}
  61. for i := 0; i < numATerms; i++ {
  62. for j := 0; j < numBTerms; j++ {
  63. if a.term[i] != 0 && b.term[j] != 0 {
  64. monomial := gfPoly{term: make([]gfElement, i+j+1)}
  65. monomial.term[i+j] = gfMultiply(a.term[i], b.term[j])
  66. result = gfPolyAdd(result, monomial)
  67. }
  68. }
  69. }
  70. return result.normalised()
  71. }
  72. // gfPolyRemainder return the remainder of numerator / denominator.
  73. func gfPolyRemainder(numerator, denominator gfPoly) gfPoly {
  74. if denominator.equals(gfPoly{}) {
  75. log.Panicln("Remainder by zero")
  76. }
  77. remainder := numerator
  78. for remainder.numTerms() >= denominator.numTerms() {
  79. degree := remainder.numTerms() - denominator.numTerms()
  80. coefficient := gfDivide(remainder.term[remainder.numTerms()-1],
  81. denominator.term[denominator.numTerms()-1])
  82. divisor := gfPolyMultiply(denominator,
  83. newGFPolyMonomial(coefficient, degree))
  84. remainder = gfPolyAdd(remainder, divisor)
  85. }
  86. return remainder.normalised()
  87. }
  88. // gfPolyAdd returns a + b.
  89. func gfPolyAdd(a, b gfPoly) gfPoly {
  90. numATerms := a.numTerms()
  91. numBTerms := b.numTerms()
  92. numTerms := numATerms
  93. if numBTerms > numTerms {
  94. numTerms = numBTerms
  95. }
  96. result := gfPoly{term: make([]gfElement, numTerms)}
  97. for i := 0; i < numTerms; i++ {
  98. switch {
  99. case numATerms > i && numBTerms > i:
  100. result.term[i] = gfAdd(a.term[i], b.term[i])
  101. case numATerms > i:
  102. result.term[i] = a.term[i]
  103. default:
  104. result.term[i] = b.term[i]
  105. }
  106. }
  107. return result.normalised()
  108. }
  109. func (e gfPoly) normalised() gfPoly {
  110. numTerms := e.numTerms()
  111. maxNonzeroTerm := numTerms - 1
  112. for i := numTerms - 1; i >= 0; i-- {
  113. if e.term[i] != 0 {
  114. break
  115. }
  116. maxNonzeroTerm = i - 1
  117. }
  118. if maxNonzeroTerm < 0 {
  119. return gfPoly{}
  120. } else if maxNonzeroTerm < numTerms-1 {
  121. e.term = e.term[0 : maxNonzeroTerm+1]
  122. }
  123. return e
  124. }
  125. func (e gfPoly) string(useIndexForm bool) string {
  126. var str string
  127. numTerms := e.numTerms()
  128. for i := numTerms - 1; i >= 0; i-- {
  129. if e.term[i] > 0 {
  130. if len(str) > 0 {
  131. str += " + "
  132. }
  133. if !useIndexForm {
  134. str += fmt.Sprintf("%dx^%d", e.term[i], i)
  135. } else {
  136. str += fmt.Sprintf("a^%dx^%d", gfLogTable[e.term[i]], i)
  137. }
  138. }
  139. }
  140. if len(str) == 0 {
  141. str = "0"
  142. }
  143. return str
  144. }
  145. // equals returns true if e == other.
  146. func (e gfPoly) equals(other gfPoly) bool {
  147. var minecPoly *gfPoly
  148. var maxecPoly *gfPoly
  149. if e.numTerms() > other.numTerms() {
  150. minecPoly = &other
  151. maxecPoly = &e
  152. } else {
  153. minecPoly = &e
  154. maxecPoly = &other
  155. }
  156. numMinTerms := minecPoly.numTerms()
  157. numMaxTerms := maxecPoly.numTerms()
  158. for i := 0; i < numMinTerms; i++ {
  159. if e.term[i] != other.term[i] {
  160. return false
  161. }
  162. }
  163. for i := numMinTerms; i < numMaxTerms; i++ {
  164. if maxecPoly.term[i] != 0 {
  165. return false
  166. }
  167. }
  168. return true
  169. }