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.

102 lines
2.0 KiB

  1. package gocircomprover
  2. import (
  3. "bytes"
  4. "math/big"
  5. )
  6. func arrayOfZeroes(n int) []*big.Int {
  7. var r []*big.Int
  8. for i := 0; i < n; i++ {
  9. r = append(r, new(big.Int).SetInt64(0))
  10. }
  11. return r
  12. }
  13. func fAdd(a, b *big.Int) *big.Int {
  14. ab := new(big.Int).Add(a, b)
  15. return new(big.Int).Mod(ab, R)
  16. }
  17. func fSub(a, b *big.Int) *big.Int {
  18. ab := new(big.Int).Sub(a, b)
  19. return new(big.Int).Mod(ab, R)
  20. }
  21. func fMul(a, b *big.Int) *big.Int {
  22. ab := new(big.Int).Mul(a, b)
  23. return new(big.Int).Mod(ab, R)
  24. }
  25. func fDiv(a, b *big.Int) *big.Int {
  26. ab := new(big.Int).Mul(a, new(big.Int).ModInverse(b, R))
  27. return new(big.Int).Mod(ab, R)
  28. }
  29. func fNeg(a *big.Int) *big.Int {
  30. return new(big.Int).Mod(new(big.Int).Neg(a), R)
  31. }
  32. func fInv(a *big.Int) *big.Int {
  33. return new(big.Int).ModInverse(a, R)
  34. }
  35. func fExp(base *big.Int, e *big.Int) *big.Int {
  36. res := big.NewInt(1)
  37. rem := new(big.Int).Set(e)
  38. exp := base
  39. for !bytes.Equal(rem.Bytes(), big.NewInt(int64(0)).Bytes()) {
  40. // if BigIsOdd(rem) {
  41. if rem.Bit(0) == 1 { // .Bit(0) returns 1 when is odd
  42. res = fMul(res, exp)
  43. }
  44. exp = fMul(exp, exp)
  45. rem = new(big.Int).Rsh(rem, 1)
  46. }
  47. return res
  48. }
  49. func max(a, b int) int {
  50. if a > b {
  51. return a
  52. }
  53. return b
  54. }
  55. func polynomialSub(a, b []*big.Int) []*big.Int {
  56. r := arrayOfZeroes(max(len(a), len(b)))
  57. for i := 0; i < len(a); i++ {
  58. r[i] = fAdd(r[i], a[i])
  59. }
  60. for i := 0; i < len(b); i++ {
  61. r[i] = fSub(r[i], b[i])
  62. }
  63. return r
  64. }
  65. func polynomialMul(a, b []*big.Int) []*big.Int {
  66. r := arrayOfZeroes(len(a) + len(b) - 1)
  67. for i := 0; i < len(a); i++ {
  68. for j := 0; j < len(b); j++ {
  69. r[i+j] = fAdd(r[i+j], fMul(a[i], b[j]))
  70. }
  71. }
  72. return r
  73. }
  74. func polynomialDiv(a, b []*big.Int) ([]*big.Int, []*big.Int) {
  75. // https://en.wikipedia.org/wiki/Division_algorithm
  76. r := arrayOfZeroes(len(a) - len(b) + 1)
  77. rem := a
  78. for len(rem) >= len(b) {
  79. l := fDiv(rem[len(rem)-1], b[len(b)-1])
  80. pos := len(rem) - len(b)
  81. r[pos] = l
  82. aux := arrayOfZeroes(pos)
  83. aux1 := append(aux, l)
  84. aux2 := polynomialSub(rem, polynomialMul(b, aux1))
  85. rem = aux2[:len(aux2)-1]
  86. }
  87. return r, rem
  88. }