@@ -49,18 +49,40 @@ def test_fft(spec):
4949@spec_test
5050@single_phase
5151def test_coset_fft (spec ):
52+
53+ # in this test we sample a random polynomial in coefficient form
54+ # then we apply a Coset FFT to get evaluations over the coset of the roots of unity
55+ # we then apply an inverse Coset FFT to the evaluations to get coefficients
56+
57+ # we check two things:
58+ # 1) the original coefficients and the resulting coefficients match
59+ # 2) the evaluations that we got are the same as if we would have evaluated individually
60+
5261 rng = random .Random (5566 )
5362
5463 roots_of_unity = spec .compute_roots_of_unity (spec .FIELD_ELEMENTS_PER_BLOB )
5564
65+ # this is the shift that generates the coset
66+ coset_shift = spec .PRIMITIVE_ROOT_OF_UNITY
67+
68+ # sample a random polynomial
5669 poly_coeff = [rng .randint (0 , BLS_MODULUS - 1 ) for _ in range (spec .FIELD_ELEMENTS_PER_BLOB )]
5770
71+ # do a coset FFT and then an inverse coset FFT
5872 poly_eval = spec .coset_fft_field (poly_coeff , roots_of_unity )
5973 poly_coeff_inversed = spec .coset_fft_field (poly_eval , roots_of_unity , inv = True )
6074
75+ # first check: inverse coset FFT after coset FFT results in original coefficients
6176 assert len (poly_eval ) == len (poly_coeff ) == len (poly_coeff_inversed )
6277 assert poly_coeff_inversed == poly_coeff
6378
79+ # second check: result of FFT are really the evaluations over the coset
80+ for i , w in enumerate (roots_of_unity ):
81+ # the element of the coset is coset_shift * w
82+ shifted_w = spec .BLSFieldElement ((coset_shift * int (w )) % BLS_MODULUS )
83+ individual_evaluation = spec .evaluate_polynomialcoeff (poly_coeff , shifted_w )
84+ assert individual_evaluation == poly_eval [i ]
85+
6486
6587@with_eip7594_and_later
6688@spec_test
0 commit comments