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.

101 lines
2.0 KiB

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