# # univariate polynomials over Fr # # constantine's implementation is "somewhat lacking", so we have to # implement these ourselves... # # TODO: more efficient implementations (right now I just want something working) # 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 #------------------------------------------------------------------------------- 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) func polyMul*(P, Q : Poly): Poly = return polyMulNaive(P, Q) #------------------------------------------------------------------------------- func `==`*(P, Q: Poly): bool = return polyEqual(P, Q) func `+`*(P, Q: Poly): Poly = return polyAdd(P, Q) func `-`*(P, Q: Poly): Poly = return polySub(P, Q) func `*`*(P, Q: Poly): Poly = return polyMul(P, Q) func `*`*(s: Fr , P: Poly): Poly = return polyScale(s, P) func `*`*(P: Poly, s: Fr ): Poly = return polyScale(s, P) #------------------------------------------------------------------------------- # evaluates a polynomial on an FFT domain func polyForwardNTT*(P: Poly, D: Domain): seq[Fr] = let n = P.coeffs.len assert( n <= D.domainSize , "the domain must be as least as big as the polynomial" ) if n == D.domainSize: let src : seq[Fr] = P.coeffs return forwardNTT(src, D) else: var src : seq[Fr] = P.coeffs for i in n..