# # univariate polynomials over Fr # # constantine's implementation is "somewhat lacking", so we have to # implement these ourselves... # import std/sequtils import std/sugar import constantine/math/arithmetic except Fp,Fr import constantine/math/io/io_fields import bn128 import domain import ntt import misc #------------------------------------------------------------------------------- type Poly* = object coeffs* : seq[Fr] #------------------------------------------------------------------------------- func polyDegree*(P: Poly) : int = let xs = P.coeffs ; let n = xs.len var d : int = n-1 while isZeroFr(xs[d]) and (d >= 0): d -= 1 return d func polyIsZero*(P: Poly) : bool = let xs = P.coeffs ; let n = xs.len var b = true for i in 0..= m: for i in 0.. 0: y = cs[0] for i in 1..= m: for i in 0..= m: for i in 0..= i = k - j >= k - min(k , n2-1) # 0 >= j = k - i >= k - min(k , n1-1) let A : int = max( 0 , k - min(k , n2-1) ) let B : int = min( k , n1-1 ) zs[k] = zeroFr for i in A..B: let j = k-i zs[k] += xs[i] * ys[j] return Poly(coeffs: zs) #------------------------------------------------------------------------------- # multiply two polynomials using FFT func polyMulFFT*(P, Q: Poly): Poly = let n1 = P.coeffs.len let n2 = Q.coeffs.len let log2 : int = max( ceilingLog2(n1) , ceilingLog2(n2) ) + 1 let N : int = (1 shl log2) let D : Domain = createDomain( N ) let us : seq[Fr] = extendAndForwardNTT( P.coeffs, D ) let vs : seq[Fr] = extendAndForwardNTT( Q.coeffs, D ) let zs : seq[Fr] = collect( newSeq, (for i in 0..=1 ) var cs : seq[Fr] = newSeq[Fr]( N+1 ) cs[0] = negFr(b) cs[N] = a return Poly(coeffs: cs) # the vanishing polynomial `(x^N - 1)` func vanishingPoly*(N: int): Poly = return generalizedVanishingPoly(N, oneFr, oneFr) func vanishingPoly*(D: Domain): Poly = return vanishingPoly(D.domainSize) #------------------------------------------------------------------------------- type QuotRem*[T] = object quot* : T rem* : T # divide by the vanishing polynomial `(x^N - 1)` # returns the quotient and remainder func polyQuotRemByVanishing*(P: Poly, N: int): QuotRem[Poly] = assert( N>=1 ) let deg : int = polyDegree(P) let src : seq[Fr] = P.coeffs var quot : seq[Fr] = newSeq[Fr]( max(1, deg - N + 1) ) var rem : seq[Fr] = newSeq[Fr]( N ) if deg < N: rem = src else: # compute quotient for j in countdown(deg-N, 0): if j+N <= deg-N: quot[j] = src[j+N] + quot[j+N] else: quot[j] = src[j+N] # compute remainder for j in 0..