From 1f35ef18d2dd4e4556d6ef759903ebd5d91688e0 Mon Sep 17 00:00:00 2001 From: Balazs Komuves Date: Fri, 19 Jun 2026 01:19:51 +0200 Subject: [PATCH] optimize the preprocessing by using the subgroup structure for the second IFFT-s in the convolution --- groth16/dynamic/shared.nim | 61 ++++++++++++++++++++++++ groth16/dynamic/v1/finish.nim | 9 ++-- groth16/dynamic/v1/preprocess.nim | 6 +-- groth16/dynamic/v1/setup.nim | 2 +- groth16/dynamic/v1/types.nim | 2 +- groth16/dynamic/v3/preprocess.nim | 73 +++++++++++++++++++++++------ groth16/math/convolution.nim | 78 ++++++++++++++++++++++++++++++- tests/groth16/testDyna.nim | 22 +++++++-- tests/groth16/testFFT.nim | 6 +++ 9 files changed, 228 insertions(+), 31 deletions(-) diff --git a/groth16/dynamic/shared.nim b/groth16/dynamic/shared.nim index f886d30..ef07a62 100644 --- a/groth16/dynamic/shared.nim +++ b/groth16/dynamic/shared.nim @@ -154,6 +154,67 @@ proc groupConvolveWithWVecBar*( D: Domain, gs: seq[G1] ): seq[G1] = inplaceScalarMulByFFTofWVecBar( gsHat ) return inverseGroupFFT( gsHat , D) +#--------------------------------------- + +# only computes the result on a subgroup +proc fieldConvolveWithWVecBarOnSubgroup*( sg: Subgroup, xs: seq[F] ): seq[F] = + + let N = xs.len + assert( N == sg.bigDomain.domainSize ) + let D = sg.bigDomain + let K = sg.smallDomain.domainSize + let ell = N div K + + let fN = intToFr( N ) + let invN = invFr( fN ) + let fell : F = intToFr(ell) + let invN_per_fell : F = invN / fell + + let xsHat = forwardNTT( xs , D ) + var ysHat : seq[F] = newSeq[F]( K ) + + let c0 = divBy2Fr(oneFr - fN) * invN_per_fell + for k in 0..