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.

104 lines
2.1 KiB

4 years ago
  1. package gocircomprover
  2. import (
  3. "fmt"
  4. "math"
  5. "math/big"
  6. )
  7. type rootsT struct {
  8. roots [][]*big.Int
  9. w []*big.Int
  10. }
  11. func newRootsT() rootsT {
  12. var roots rootsT
  13. rem := new(big.Int).Sub(R, big.NewInt(1))
  14. s := 0
  15. for rem.Bit(0) == 0 { // rem.Bit==0 when even
  16. s++
  17. rem = new(big.Int).Rsh(rem, 1)
  18. }
  19. roots.w = make([]*big.Int, s+1)
  20. roots.w[s] = FExp(big.NewInt(5), rem)
  21. n := s - 1
  22. for n >= 0 {
  23. roots.w[n] = FMul(roots.w[n+1], roots.w[n+1])
  24. n--
  25. }
  26. roots.roots = make([][]*big.Int, 50)
  27. roots.setRoots(15)
  28. return roots
  29. }
  30. func (roots rootsT) setRoots(n int) {
  31. // var roots []bool
  32. for i := n; i >= 0 && nil == roots.roots[i]; i-- { // TODO tmp i<=len(r)
  33. r := big.NewInt(1)
  34. nroots := 1 << i
  35. var rootsi []*big.Int
  36. for j := 0; j < nroots; j++ {
  37. rootsi = append(rootsi, r)
  38. r = FMul(r, roots.w[i])
  39. }
  40. // fmt.Println("rootsi", rootsi)
  41. roots.roots[i] = rootsi
  42. }
  43. }
  44. func fft(roots rootsT, pall []*big.Int, bits, offset, step int) []*big.Int {
  45. n := 1 << bits
  46. if n == 1 {
  47. return []*big.Int{pall[offset]}
  48. } else if n == 2 {
  49. return []*big.Int{
  50. FAdd(pall[offset], pall[offset+step]), // TODO tmp
  51. FSub(pall[offset], pall[offset+step]),
  52. }
  53. }
  54. ndiv2 := n >> 1
  55. p1 := fft(roots, pall, bits-1, offset, step*2)
  56. p2 := fft(roots, pall, bits-1, offset+step, step*2)
  57. // var out []*big.Int
  58. out := make([]*big.Int, n)
  59. for i := 0; i < ndiv2; i++ {
  60. fmt.Println(i, len(roots.roots))
  61. out[i] = FAdd(p1[i], FMul(roots.roots[bits][i], p2[i]))
  62. out[i+ndiv2] = FSub(p1[i], FMul(roots.roots[bits][i], p2[i]))
  63. }
  64. return out
  65. }
  66. func ifft(p []*big.Int) []*big.Int {
  67. if len(p) <= 1 {
  68. return p
  69. }
  70. bits := math.Log2(float64(len(p)-1)) + 1
  71. roots := newRootsT()
  72. roots.setRoots(int(bits))
  73. m := 1 << int(bits)
  74. ep := extend(p, m)
  75. res := fft(roots, ep, int(bits), 0, 1)
  76. twoinvm := FInv(FMul(big.NewInt(1), big.NewInt(int64(m))))
  77. var resn []*big.Int
  78. for i := 0; i < m; i++ {
  79. resn = append(resn, FMul(res[(m-i)%m], twoinvm))
  80. }
  81. return resn
  82. }
  83. func extend(p []*big.Int, e int) []*big.Int {
  84. if e == len(p) {
  85. return p
  86. }
  87. z := arrayOfZeroes(e - len(p))
  88. return append(p, z...)
  89. }