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