Shortcut polynomial evaluation for x = 0

This commit is contained in:
Ben Edgington 2021-02-05 12:04:48 +00:00
parent abe417019f
commit ddecf22708
9 changed files with 47 additions and 11 deletions

View File

@ -17,6 +17,14 @@
#include "blst_util.h" #include "blst_util.h"
#include "debug_util.h" #include "debug_util.h"
// TODO - find a better way to do this
bool fr_is_zero(const blst_fr *p) {
uint64_t a[4];
blst_uint64_from_fr(a, p);
return a[0] == 0 && a[1] == 0 && a[2] == 0 && a[3] == 0;
}
// TODO - find a better way to do this
bool fr_is_one(const blst_fr *p) { bool fr_is_one(const blst_fr *p) {
uint64_t a[4]; uint64_t a[4];
blst_uint64_from_fr(a, p); blst_uint64_from_fr(a, p);

View File

@ -16,13 +16,16 @@
#include "c_kzg.h" #include "c_kzg.h"
static const blst_fr fr_zero = {0L, 0L, 0L, 0L};
// This is 1 in Blst's `blst_fr` limb representation. Crazy but true. // This is 1 in Blst's `blst_fr` limb representation. Crazy but true.
static const blst_fr one = static const blst_fr fr_one =
{0x00000001fffffffeL, 0x5884b7fa00034802L, 0x998c4fefecbc4ff5L, 0x1824b159acc5056fL}; {0x00000001fffffffeL, 0x5884b7fa00034802L, 0x998c4fefecbc4ff5L, 0x1824b159acc5056fL};
// The G1 identity/infinity in affine representation // The G1 identity/infinity in affine representation
static const blst_p1_affine identity_g1_affine = {{0,0,0,0,0,0},{0,0,0,0,0,0}}; static const blst_p1_affine identity_g1_affine = {{0L,0L,0L,0L,0L,0L},{0L,0L,0L,0L,0L,0L}};
bool fr_is_zero(const blst_fr *p);
bool fr_is_one(const blst_fr *p); bool fr_is_one(const blst_fr *p);
void fr_from_uint64(blst_fr *a, const uint64_t n); void fr_from_uint64(blst_fr *a, const uint64_t n);
bool fr_equal(const blst_fr *aa, const blst_fr *bb); bool fr_equal(const blst_fr *aa, const blst_fr *bb);

View File

@ -23,14 +23,20 @@ uint64_t m1[] = {0xffffffff00000000L, 0x53bda402fffe5bfeL, 0x3339d80809a1d805L,
void title(void) {;} void title(void) {;}
void fr_is_zero_works(void) {
blst_fr zero;
fr_from_uint64(&zero, 0);
TEST_CHECK(fr_is_zero(&zero));
}
void fr_is_one_works(void) { void fr_is_one_works(void) {
TEST_CHECK(true == fr_is_one(&one)); TEST_CHECK(fr_is_one(&fr_one));
} }
void fr_from_uint64_works(void) { void fr_from_uint64_works(void) {
blst_fr a; blst_fr a;
fr_from_uint64(&a, 1); fr_from_uint64(&a, 1);
TEST_CHECK(true == fr_is_one(&a)); TEST_CHECK(fr_is_one(&a));
} }
void fr_equal_works(void) { void fr_equal_works(void) {
@ -156,6 +162,7 @@ void pairings_work(void) {
TEST_LIST = TEST_LIST =
{ {
{"BLST_UTIL_TEST", title}, {"BLST_UTIL_TEST", title},
{"fr_is_zero_works", fr_is_zero_works },
{"fr_is_one_works", fr_is_one_works }, {"fr_is_one_works", fr_is_one_works },
{"fr_from_uint64_works", fr_from_uint64_works}, {"fr_from_uint64_works", fr_from_uint64_works},
{"fr_equal_works", fr_equal_works}, {"fr_equal_works", fr_equal_works},

View File

@ -25,7 +25,7 @@ bool is_power_of_two(const uint64_t n) {
// Create an array of powers of the root of unity // Create an array of powers of the root of unity
// The `out` array must be of size `width + 1` // The `out` array must be of size `width + 1`
C_KZG_RET expand_root_of_unity(blst_fr *roots, const blst_fr *root_of_unity, const uint64_t width) { C_KZG_RET expand_root_of_unity(blst_fr *roots, const blst_fr *root_of_unity, const uint64_t width) {
roots[0] = one; roots[0] = fr_one;
roots[1] = *root_of_unity; roots[1] = *root_of_unity;
for (int i = 2; !fr_is_one(&roots[i - 1]); i++) { for (int i = 2; !fr_is_one(&roots[i - 1]); i++) {

View File

@ -46,9 +46,9 @@ void reverse_works(void) {
blst_fr diff; blst_fr diff;
// Initialise - increasing values // Initialise - increasing values
arr[0] = one; arr[0] = fr_one;
for (int i = 1; i <= n; i++) { for (int i = 1; i <= n; i++) {
blst_fr_add(arr + i, arr + i - 1, &one); blst_fr_add(arr + i, arr + i - 1, &fr_one);
} }
// Reverse // Reverse

View File

@ -32,7 +32,7 @@ C_KZG_RET compute_proof_single(blst_p1 *out, const KZGSettings *ks, poly *p, con
poly_init(&divisor, 2); poly_init(&divisor, 2);
fr_from_uint64(&tmp, x0); fr_from_uint64(&tmp, x0);
fr_negate(&divisor.coeffs[0],&tmp); fr_negate(&divisor.coeffs[0],&tmp);
divisor.coeffs[1] = one; divisor.coeffs[1] = fr_one;
// Calculate q = p / (x - x0) // Calculate q = p / (x - x0)
// Discard the return codes since we already checked above that all should be fine. // Discard the return codes since we already checked above that all should be fine.

View File

@ -21,7 +21,7 @@
void generate_setup(blst_p1 *s1, blst_p2 *s2, const blst_scalar *secret, const uint64_t n) { void generate_setup(blst_p1 *s1, blst_p2 *s2, const blst_scalar *secret, const uint64_t n) {
blst_fr s_pow, s; blst_fr s_pow, s;
blst_fr_from_scalar(&s, secret); blst_fr_from_scalar(&s, secret);
s_pow = one; s_pow = fr_one;
for (uint64_t i = 0; i < n; i++) { for (uint64_t i = 0; i < n; i++) {
p1_mul(&s1[i], blst_p1_generator(), &s_pow); p1_mul(&s1[i], blst_p1_generator(), &s_pow);
p2_mul(&s2[i], blst_p2_generator(), &s_pow); p2_mul(&s2[i], blst_p2_generator(), &s_pow);

View File

@ -36,7 +36,9 @@ void poly_eval(blst_fr *out, const poly *p, const blst_fr *x) {
if (p->length == 0) { if (p->length == 0) {
fr_from_uint64(out, 0); fr_from_uint64(out, 0);
} }
// TODO x = 0 case if (fr_is_zero(x)) {
*out = p->coeffs[0];
}
// Horner's method // Horner's method
*out = p->coeffs[p->length - 1]; *out = p->coeffs[p->length - 1];

View File

@ -121,7 +121,22 @@ void poly_eval_check(void) {
} }
fr_from_uint64(&expected, n * (n + 1) / 2); fr_from_uint64(&expected, n * (n + 1) / 2);
poly_eval(&res, &p, &one); poly_eval(&res, &p, &fr_one);
TEST_CHECK(fr_equal(&expected, &res));
}
void poly_eval_0_check(void) {
uint64_t n = 7, a = 597;
blst_fr res, expected;
poly p;
poly_init(&p, n);
for (uint64_t i = 0; i < n; i++) {
fr_from_uint64(&p.coeffs[i], i + a);
}
fr_from_uint64(&expected, a);
poly_eval(&res, &p, &fr_zero);
TEST_CHECK(fr_equal(&expected, &res)); TEST_CHECK(fr_equal(&expected, &res));
} }
@ -135,5 +150,6 @@ TEST_LIST =
{"poly_div_1", poly_div_1}, {"poly_div_1", poly_div_1},
{"poly_wrong_size", poly_wrong_size}, {"poly_wrong_size", poly_wrong_size},
{"poly_eval_check", poly_eval_check}, {"poly_eval_check", poly_eval_check},
{"poly_eval_0_check", poly_eval_0_check},
{ NULL, NULL } /* zero record marks the end of the list */ { NULL, NULL } /* zero record marks the end of the list */
}; };