diff --git a/min-bindings/C#/ckzg.c b/min-bindings/C#/ckzg.c index 966d846..56ccd84 100644 --- a/min-bindings/C#/ckzg.c +++ b/min-bindings/C#/ckzg.c @@ -15,8 +15,30 @@ BLSFieldElement* compute_powers_wrap(const BLSFieldElement *r, uint64_t n) { return out; } -PolynomialEvalForm* vector_lincomb_wrap(const uint8_t vectors[], const BLSFieldElement scalars[], uint64_t num_vectors, uint64_t vector_len) { - return NULL; // TODO +PolynomialEvalForm* vector_lincomb_wrap(const uint8_t bytes[], const BLSFieldElement scalars[], uint64_t num_vectors, uint64_t vector_len) { + PolynomialEvalForm *p = (PolynomialEvalForm*)malloc(sizeof(PolynomialEvalForm)); + if (p == NULL) return NULL; + + if (alloc_polynomial(p, vector_len) != C_KZG_OK) { + free(p); + return NULL; + } + + BLSFieldElement *vectors = (BLSFieldElement*)calloc(num_vectors * vector_len, sizeof(BLSFieldElement)); + if (vectors == NULL) { + free_polynomial(p); + free(p); + return NULL; + } + + for (uint64_t i = 0; i < num_vectors; i++) + for (uint64_t j = 0; j < vector_len; j++) + bytes_to_bls_field(&vectors[i * vector_len + j], &bytes[(i * vector_len + j) * 32]); + + vector_lincomb(p->values, vectors, scalars, num_vectors, vector_len); + + free(vectors); + return p; } KZGCommitment* g1_lincomb_wrap(const uint8_t bytes[], const BLSFieldElement scalars[], uint64_t num_points) { diff --git a/min-bindings/python/ckzg.c b/min-bindings/python/ckzg.c index 82ff799..0089087 100644 --- a/min-bindings/python/ckzg.c +++ b/min-bindings/python/ckzg.c @@ -283,7 +283,7 @@ static PyObject* vector_lincomb_wrap(PyObject *self, PyObject *args) { return PyErr_NoMemory(); } - vector_lincomb(r, vectors, scalars, n, m); + vector_lincomb_indirect(r, vectors, scalars, n, m); free(scalars); free(vectors); diff --git a/min-src/c_kzg_4844.c b/min-src/c_kzg_4844.c index 13f1cd2..c1557d8 100644 --- a/min-src/c_kzg_4844.c +++ b/min-src/c_kzg_4844.c @@ -838,7 +838,7 @@ void bytes_to_bls_field(BLSFieldElement *out, const uint8_t bytes[32]) { /** * Compute linear combinations of a sequence of vectors with some scalars */ -void vector_lincomb(fr_t out[], const fr_t* vectors[], const fr_t* scalars[], uint64_t n, uint64_t m) { +void vector_lincomb_indirect(fr_t out[], const fr_t* vectors[], const fr_t* scalars[], uint64_t n, uint64_t m) { fr_t tmp; uint64_t i, j; for (j = 0; j < m; j++) @@ -851,6 +851,22 @@ void vector_lincomb(fr_t out[], const fr_t* vectors[], const fr_t* scalars[], ui } } +/** + * Compute linear combinations of a sequence of vectors with some scalars + */ +void vector_lincomb(fr_t out[], const fr_t vectors[], const fr_t scalars[], uint64_t n, uint64_t m) { + fr_t tmp; + uint64_t i, j; + for (j = 0; j < m; j++) + out[j] = fr_zero; + for (i = 0; i < n; i++) { + for (j = 0; j < m; j++) { + fr_mul(&tmp, &scalars[i], &vectors[i * m + j]); + fr_add(&out[j], &out[j], &tmp); + } + } +} + /** * Calculate a linear combination of G1 group elements. * diff --git a/min-src/c_kzg_4844.h b/min-src/c_kzg_4844.h index 9ae5dff..9245524 100644 --- a/min-src/c_kzg_4844.h +++ b/min-src/c_kzg_4844.h @@ -109,7 +109,10 @@ void free_trusted_setup(KZGSettings *s); void bytes_to_bls_field(BLSFieldElement *out, const uint8_t bytes[32]); -void vector_lincomb(BLSFieldElement out[], const BLSFieldElement* vectors[], const BLSFieldElement* scalars[], uint64_t num_vectors, uint64_t vector_len); +// TODO: probably remove this version +void vector_lincomb_indirect(BLSFieldElement out[], const BLSFieldElement* vectors[], const BLSFieldElement* scalars[], uint64_t num_vectors, uint64_t vector_len); + +void vector_lincomb(BLSFieldElement out[], const BLSFieldElement vectors[], const BLSFieldElement scalars[], uint64_t num_vectors, uint64_t vector_len); void g1_lincomb(KZGCommitment *out, const KZGCommitment points[], const BLSFieldElement scalars[], uint64_t num_points);