Polynomial API views replaced by evaluation on rou domain (#514)

- removed poly API to access view of evaluations. This is a problematic API since it cannot handle small domains and for large domains requires the polynomial to use more memory than need to.
- added evaluate_on_rou_domain() API instead that supports any domain size (powers of two size).
- the new API can compute to HOST or DEVICE memory
- Rust wrapper for evaluate_on_rou_domain()
- updated documentation: overview and Rust wrappers
- faster division by vanishing poly for common case where numerator is 2N and vanishing poly is of degree N.
- allow division a/b where deg(a)<deg(b) instead of throwing an error.
This commit is contained in:
yshekel
2024-05-15 14:06:23 +03:00
committed by GitHub
parent 972b924bc0
commit 9c1afe8a44
12 changed files with 342 additions and 142 deletions

View File

@@ -27,6 +27,7 @@ where
domain: &D,
evals: &mut E,
);
fn eval_on_rou_domain<E: HostOrDeviceSlice<Self::Field> + ?Sized>(&self, domain_log_size: u64, evals: &mut E);
fn get_nof_coeffs(&self) -> u64;
fn get_coeff(&self, idx: u64) -> Self::Field;
fn copy_coeffs<S: HostOrDeviceSlice<Self::Field> + ?Sized>(&self, start_idx: u64, coeffs: &mut S);
@@ -115,6 +116,9 @@ macro_rules! impl_univariate_polynomial_api {
#[link_name = concat!($field_prefix, "_polynomial_evaluate_on_domain")]
fn eval_on_domain(a: PolynomialHandle, domain: *const $field, domain_size: u64, evals: *mut $field);
#[link_name = concat!($field_prefix, "_polynomial_evaluate_on_rou_domain")]
fn eval_on_rou_domain(a: PolynomialHandle, domain_log_size: u64, evals: *mut $field);
#[link_name = concat!($field_prefix, "_polynomial_degree")]
fn degree(a: PolynomialHandle) -> i64;
@@ -255,6 +259,20 @@ macro_rules! impl_univariate_polynomial_api {
}
}
fn eval_on_rou_domain<E: HostOrDeviceSlice<Self::Field> + ?Sized>(
&self,
domain_log_size: u64,
evals: &mut E,
) {
assert!(
evals.len() >= 1 << domain_log_size,
"eval_on_rou_domain(): eval size must not be smaller than domain"
);
unsafe {
eval_on_rou_domain(self.handle, domain_log_size, evals.as_mut_ptr());
}
}
fn get_nof_coeffs(&self) -> u64 {
unsafe {
// returns total #coeffs. Not copying when null
@@ -732,6 +750,25 @@ macro_rules! impl_polynomial_tests {
assert_eq!(f.eval(&host_evals_from_device[2]), host_evals[2]);
}
#[test]
#[ignore]
fn test_eval_on_rou_domain() {
setup();
let poly_log_size = 10;
let domain_log_size = poly_log_size + 2; // interpolate 4 times
let f = randomize_poly(1 << poly_log_size);
// evaluate f on rou domain of size 4n
let mut device_evals = DeviceVec::<ScalarField>::cuda_malloc(1 << domain_log_size).unwrap();
f.eval_on_rou_domain(domain_log_size, &mut device_evals[..]);
// construct g from f's evals and assert they are equal
let g = Poly::from_rou_evals(&device_evals[..], 1 << domain_log_size);
let diff = &f - &g;
assert_eq!(diff.degree(), -1); // diff is the zero poly
}
#[test]
#[ignore]
fn test_odd_even_slicing() {