gfpoly.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. package utils
  2. type GFPoly struct {
  3. gf *GaloisField
  4. Coefficients []int
  5. }
  6. func (gp *GFPoly) Degree() int {
  7. return len(gp.Coefficients) - 1
  8. }
  9. func (gp *GFPoly) Zero() bool {
  10. return gp.Coefficients[0] == 0
  11. }
  12. // GetCoefficient returns the coefficient of x ^ degree
  13. func (gp *GFPoly) GetCoefficient(degree int) int {
  14. return gp.Coefficients[gp.Degree()-degree]
  15. }
  16. func (gp *GFPoly) AddOrSubstract(other *GFPoly) *GFPoly {
  17. if gp.Zero() {
  18. return other
  19. } else if other.Zero() {
  20. return gp
  21. }
  22. smallCoeff := gp.Coefficients
  23. largeCoeff := other.Coefficients
  24. if len(smallCoeff) > len(largeCoeff) {
  25. largeCoeff, smallCoeff = smallCoeff, largeCoeff
  26. }
  27. sumDiff := make([]int, len(largeCoeff))
  28. lenDiff := len(largeCoeff) - len(smallCoeff)
  29. copy(sumDiff, largeCoeff[:lenDiff])
  30. for i := lenDiff; i < len(largeCoeff); i++ {
  31. sumDiff[i] = int(gp.gf.AddOrSub(int(smallCoeff[i-lenDiff]), int(largeCoeff[i])))
  32. }
  33. return NewGFPoly(gp.gf, sumDiff)
  34. }
  35. func (gp *GFPoly) MultByMonominal(degree int, coeff int) *GFPoly {
  36. if coeff == 0 {
  37. return gp.gf.Zero()
  38. }
  39. size := len(gp.Coefficients)
  40. result := make([]int, size+degree)
  41. for i := 0; i < size; i++ {
  42. result[i] = int(gp.gf.Multiply(int(gp.Coefficients[i]), int(coeff)))
  43. }
  44. return NewGFPoly(gp.gf, result)
  45. }
  46. func (gp *GFPoly) Multiply(other *GFPoly) *GFPoly {
  47. if gp.Zero() || other.Zero() {
  48. return gp.gf.Zero()
  49. }
  50. aCoeff := gp.Coefficients
  51. aLen := len(aCoeff)
  52. bCoeff := other.Coefficients
  53. bLen := len(bCoeff)
  54. product := make([]int, aLen+bLen-1)
  55. for i := 0; i < aLen; i++ {
  56. ac := int(aCoeff[i])
  57. for j := 0; j < bLen; j++ {
  58. bc := int(bCoeff[j])
  59. product[i+j] = int(gp.gf.AddOrSub(int(product[i+j]), gp.gf.Multiply(ac, bc)))
  60. }
  61. }
  62. return NewGFPoly(gp.gf, product)
  63. }
  64. func (gp *GFPoly) Divide(other *GFPoly) (quotient *GFPoly, remainder *GFPoly) {
  65. quotient = gp.gf.Zero()
  66. remainder = gp
  67. fld := gp.gf
  68. denomLeadTerm := other.GetCoefficient(other.Degree())
  69. inversDenomLeadTerm := fld.Invers(int(denomLeadTerm))
  70. for remainder.Degree() >= other.Degree() && !remainder.Zero() {
  71. degreeDiff := remainder.Degree() - other.Degree()
  72. scale := int(fld.Multiply(int(remainder.GetCoefficient(remainder.Degree())), inversDenomLeadTerm))
  73. term := other.MultByMonominal(degreeDiff, scale)
  74. itQuot := NewMonominalPoly(fld, degreeDiff, scale)
  75. quotient = quotient.AddOrSubstract(itQuot)
  76. remainder = remainder.AddOrSubstract(term)
  77. }
  78. return
  79. }
  80. func NewMonominalPoly(field *GaloisField, degree int, coeff int) *GFPoly {
  81. if coeff == 0 {
  82. return field.Zero()
  83. }
  84. result := make([]int, degree+1)
  85. result[0] = coeff
  86. return NewGFPoly(field, result)
  87. }
  88. func NewGFPoly(field *GaloisField, coefficients []int) *GFPoly {
  89. for len(coefficients) > 1 && coefficients[0] == 0 {
  90. coefficients = coefficients[1:]
  91. }
  92. return &GFPoly{field, coefficients}
  93. }