Use bit-reversal permutation

This commit is contained in:
Ramana Kumar 2022-09-27 13:37:46 +01:00
parent efef81bdf1
commit 48903d567f
No known key found for this signature in database
GPG Key ID: ED471C788B900433
4 changed files with 25 additions and 16 deletions

View File

@ -55,6 +55,7 @@ typedef struct {
fr_t root_of_unity; /**< The root of unity used to generate the lists in the structure. */
fr_t *expanded_roots_of_unity; /**< Ascending powers of the root of unity, size `width + 1`. */
fr_t *reverse_roots_of_unity; /**< Descending powers of the root of unity, size `width + 1`. */
fr_t *bitrevp_roots_of_unity; /**< Powers of the root of unity in bit-reversal permutation, size `width`. */
} FFTSettings;
C_KZG_RET new_fft_settings(FFTSettings *out, unsigned int max_scale);
@ -87,9 +88,9 @@ typedef struct {
} poly;
typedef struct {
fr_t *values; /**< `values[i]` is value of the polynomial at `ω^i`. */
fr_t *values; /**< `values[i]` is value of the polynomial at `ω^brp(i)`. */
uint64_t length; /**< One more than the polynomial's degree */
} poly_l; // Lagrange form
} poly_l; // Lagrange form, under bit-reversal permutation
void eval_poly(fr_t *out, const poly *p, const fr_t *x);
C_KZG_RET eval_poly_l(fr_t *out, const poly_l *p, const fr_t *x, const FFTSettings *fs);
@ -117,7 +118,7 @@ void fr_vector_lincomb(fr_t out[], const fr_t *vectors, const fr_t *scalars, uin
typedef struct {
const FFTSettings *fs; /**< The corresponding settings for performing FFTs */
g1_t *secret_g1; /**< G1 group elements from the trusted setup */
g1_t *secret_g1_l; /**< secret_g1 in Lagrange form */
g1_t *secret_g1_l; /**< secret_g1 in Lagrange form, in bit-reversal permutation */
g2_t *secret_g2; /**< G2 group elements from the trusted setup */
uint64_t length; /**< The number of elements in secret_g1 and secret_g2 */
} KZGSettings;

View File

@ -20,8 +20,10 @@
* Code shared between the FFTs over field elements and FFTs over G1 group elements.
*/
#include <string.h> // memcpy
#include "control.h"
#include "c_kzg_alloc.h"
#include "utility.h" // reverse_bit_order
/**
* The first 32 roots of unity in the finite field F_r.
@ -131,6 +133,7 @@ C_KZG_RET new_fft_settings(FFTSettings *fs, unsigned int max_scale) {
// Allocate space for the roots of unity
TRY(new_fr_array(&fs->expanded_roots_of_unity, fs->max_width + 1));
TRY(new_fr_array(&fs->reverse_roots_of_unity, fs->max_width + 1));
TRY(new_fr_array(&fs->bitrevp_roots_of_unity, fs->max_width));
// Populate the roots of unity
TRY(expand_root_of_unity(fs->expanded_roots_of_unity, &fs->root_of_unity, fs->max_width));
@ -140,6 +143,10 @@ C_KZG_RET new_fft_settings(FFTSettings *fs, unsigned int max_scale) {
fs->reverse_roots_of_unity[i] = fs->expanded_roots_of_unity[fs->max_width - i];
}
// Permute the roots of unity
memcpy(fs->bitrevp_roots_of_unity, fs->expanded_roots_of_unity, sizeof(fr_t) * fs->max_width);
TRY(reverse_bit_order(fs->bitrevp_roots_of_unity, sizeof(fr_t), fs->max_width));
return C_KZG_OK;
}
@ -151,6 +158,7 @@ C_KZG_RET new_fft_settings(FFTSettings *fs, unsigned int max_scale) {
void free_fft_settings(FFTSettings *fs) {
free(fs->expanded_roots_of_unity);
free(fs->reverse_roots_of_unity);
free(fs->bitrevp_roots_of_unity);
fs->max_width = 0;
}
@ -158,7 +166,6 @@ void free_fft_settings(FFTSettings *fs) {
#include "../inc/acutest.h"
#include "test_util.h"
#include "utility.h"
#define NUM_ROOTS 32

View File

@ -142,13 +142,13 @@ C_KZG_RET compute_proof_single_l(g1_t *out, const poly_l *p, const fr_t *x, cons
TRY(new_fr_array(&inverses, p->length));
for (i = 0; i < q.length; i++) {
if (fr_equal(x, &ks->fs->expanded_roots_of_unity[i])) {
if (fr_equal(x, &ks->fs->bitrevp_roots_of_unity[i])) {
m = i + 1;
continue;
}
// (p_i - y) / (ω_i - x)
fr_sub(&q.values[i], &p->values[i], y);
fr_sub(&inverses_in[i], &ks->fs->expanded_roots_of_unity[i], x);
fr_sub(&inverses_in[i], &ks->fs->bitrevp_roots_of_unity[i], x);
}
TRY(fr_batch_inv(inverses, inverses_in, q.length));
@ -161,14 +161,14 @@ C_KZG_RET compute_proof_single_l(g1_t *out, const poly_l *p, const fr_t *x, cons
for (i=0; i < q.length; i++) {
if (i == m) continue;
// (p_i - y) * ω_i / (x * (x - ω_i))
fr_sub(&tmp, x, &ks->fs->expanded_roots_of_unity[i]);
fr_sub(&tmp, x, &ks->fs->bitrevp_roots_of_unity[i]);
fr_mul(&inverses_in[i], &tmp, x);
}
TRY(fr_batch_inv(inverses, inverses_in, q.length));
for (i=0; i < q.length; i++) {
fr_sub(&tmp2, &p->values[i], y);
fr_mul(&tmp, &tmp2, &inverses[i]);
fr_mul(&tmp, &tmp, &ks->fs->expanded_roots_of_unity[i]);
fr_mul(&tmp, &tmp, &ks->fs->bitrevp_roots_of_unity[i]);
fr_add(&q.values[m], &q.values[m], &tmp);
}
}
@ -318,8 +318,9 @@ C_KZG_RET new_kzg_settings(KZGSettings *ks, const g1_t *secret_g1, const g2_t *s
}
ks->fs = fs;
// Add Lagrange form (and return its success)
return fft_g1(ks->secret_g1_l, ks->secret_g1, true, length, fs);
// Add Lagrange form
TRY(fft_g1(ks->secret_g1_l, ks->secret_g1, true, length, fs));
return reverse_bit_order(ks->secret_g1_l, sizeof(g1_t), length);
}
/**

View File

@ -117,19 +117,19 @@ C_KZG_RET eval_poly_l(fr_t *out, const poly_l *p, const fr_t *x, const FFTSettin
TRY(new_fr_array(&inverses_in, p->length));
TRY(new_fr_array(&inverses, p->length));
for (i = 0; i < p->length; i++) {
if (fr_equal(x, &fs->expanded_roots_of_unity[i * stride])) {
if (fr_equal(x, &fs->bitrevp_roots_of_unity[i * stride])) {
*out = p->values[i];
free(inverses_in);
free(inverses);
return C_KZG_OK;
}
fr_sub(&inverses_in[i], x, &fs->expanded_roots_of_unity[i * stride]);
fr_sub(&inverses_in[i], x, &fs->bitrevp_roots_of_unity[i * stride]);
}
TRY(fr_batch_inv(inverses, inverses_in, p->length));
*out = fr_zero;
for (i = 0; i < p->length; i++) {
fr_mul(&tmp, &inverses[i], &fs->expanded_roots_of_unity[i * stride]);
fr_mul(&tmp, &inverses[i], &fs->bitrevp_roots_of_unity[i * stride]);
fr_mul(&tmp, &tmp, &p->values[i]);
fr_add(out, out, &tmp);
}
@ -635,7 +635,7 @@ C_KZG_RET new_poly_with_coeffs(poly *out, const fr_t *coeffs, uint64_t length) {
C_KZG_RET new_poly_l_from_poly(poly_l *out, const poly *in, const KZGSettings *ks) {
TRY(new_poly_l(out, ks->length));
if (out->length <= in->length) {
return fft_fr(out->values, in->coeffs, false, out->length, ks->fs);
fft_fr(out->values, in->coeffs, false, out->length, ks->fs);
}
else {
int i;
@ -649,8 +649,8 @@ C_KZG_RET new_poly_l_from_poly(poly_l *out, const poly *in, const KZGSettings *k
}
TRY(fft_fr(out->values, coeffs, false, out->length, ks->fs));
free(coeffs);
return C_KZG_OK;
}
return reverse_bit_order(out->values, sizeof(fr_t), out->length);
}
/**