-
Notifications
You must be signed in to change notification settings - Fork 219
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
308 additions
and
312 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,170 +1,4 @@ | ||
//! Work with sparse and dense polynomials. | ||
//! Modules for working with univariate or multivariate polynomials. | ||
use crate::{Cow, EvaluationDomain, Evaluations, Vec}; | ||
use algebra_core::{FftField, Field}; | ||
use core::convert::TryInto; | ||
use DenseOrSparseUniPolynomial::*; | ||
|
||
mod multi_sparse; | ||
mod uni_dense; | ||
mod uni_sparse; | ||
|
||
pub use multi_sparse::PolyVars; | ||
pub use multi_sparse::SparseMultiPolynomial; | ||
pub use uni_dense::DenseUniPolynomial; | ||
pub use uni_sparse::SparseUniPolynomial; | ||
|
||
/// Represents either a sparse polynomial or a dense one. | ||
#[derive(Clone)] | ||
pub enum DenseOrSparseUniPolynomial<'a, F: 'a + Field> { | ||
/// Represents the case where `self` is a sparse polynomial | ||
SPolynomial(Cow<'a, SparseUniPolynomial<F>>), | ||
/// Represents the case where `self` is a dense polynomial | ||
DPolynomial(Cow<'a, DenseUniPolynomial<F>>), | ||
} | ||
|
||
impl<'a, F: 'a + Field> From<DenseUniPolynomial<F>> for DenseOrSparseUniPolynomial<'a, F> { | ||
fn from(other: DenseUniPolynomial<F>) -> Self { | ||
DPolynomial(Cow::Owned(other)) | ||
} | ||
} | ||
|
||
impl<'a, F: 'a + Field> From<&'a DenseUniPolynomial<F>> for DenseOrSparseUniPolynomial<'a, F> { | ||
fn from(other: &'a DenseUniPolynomial<F>) -> Self { | ||
DPolynomial(Cow::Borrowed(other)) | ||
} | ||
} | ||
|
||
impl<'a, F: 'a + Field> From<SparseUniPolynomial<F>> for DenseOrSparseUniPolynomial<'a, F> { | ||
fn from(other: SparseUniPolynomial<F>) -> Self { | ||
SPolynomial(Cow::Owned(other)) | ||
} | ||
} | ||
|
||
impl<'a, F: Field> From<&'a SparseUniPolynomial<F>> for DenseOrSparseUniPolynomial<'a, F> { | ||
fn from(other: &'a SparseUniPolynomial<F>) -> Self { | ||
SPolynomial(Cow::Borrowed(other)) | ||
} | ||
} | ||
|
||
impl<'a, F: Field> Into<DenseUniPolynomial<F>> for DenseOrSparseUniPolynomial<'a, F> { | ||
fn into(self) -> DenseUniPolynomial<F> { | ||
match self { | ||
DPolynomial(p) => p.into_owned(), | ||
SPolynomial(p) => p.into_owned().into(), | ||
} | ||
} | ||
} | ||
|
||
impl<'a, F: 'a + Field> TryInto<SparseUniPolynomial<F>> for DenseOrSparseUniPolynomial<'a, F> { | ||
type Error = (); | ||
|
||
fn try_into(self) -> Result<SparseUniPolynomial<F>, ()> { | ||
match self { | ||
SPolynomial(p) => Ok(p.into_owned()), | ||
_ => Err(()), | ||
} | ||
} | ||
} | ||
|
||
impl<'a, F: Field> DenseOrSparseUniPolynomial<'a, F> { | ||
/// Checks if the given polynomial is zero. | ||
pub fn is_zero(&self) -> bool { | ||
match self { | ||
SPolynomial(s) => s.is_zero(), | ||
DPolynomial(d) => d.is_zero(), | ||
} | ||
} | ||
|
||
/// Return the degree of `self. | ||
pub fn degree(&self) -> usize { | ||
match self { | ||
SPolynomial(s) => s.degree(), | ||
DPolynomial(d) => d.degree(), | ||
} | ||
} | ||
|
||
#[inline] | ||
fn leading_coefficient(&self) -> Option<&F> { | ||
match self { | ||
SPolynomial(p) => p.last().map(|(_, c)| c), | ||
DPolynomial(p) => p.last(), | ||
} | ||
} | ||
|
||
#[inline] | ||
fn iter_with_index(&self) -> Vec<(usize, F)> { | ||
match self { | ||
SPolynomial(p) => p.to_vec(), | ||
DPolynomial(p) => p.iter().cloned().enumerate().collect(), | ||
} | ||
} | ||
|
||
/// Divide self by another (sparse or dense) polynomial, and returns the | ||
/// quotient and remainder. | ||
pub fn divide_with_q_and_r( | ||
&self, | ||
divisor: &Self, | ||
) -> Option<(DenseUniPolynomial<F>, DenseUniPolynomial<F>)> { | ||
if self.is_zero() { | ||
Some((DenseUniPolynomial::zero(), DenseUniPolynomial::zero())) | ||
} else if divisor.is_zero() { | ||
panic!("Dividing by zero polynomial") | ||
} else if self.degree() < divisor.degree() { | ||
Some((DenseUniPolynomial::zero(), self.clone().into())) | ||
} else { | ||
// Now we know that self.degree() >= divisor.degree(); | ||
let mut quotient = vec![F::zero(); self.degree() - divisor.degree() + 1]; | ||
let mut remainder: DenseUniPolynomial<F> = self.clone().into(); | ||
// Can unwrap here because we know self is not zero. | ||
let divisor_leading_inv = divisor.leading_coefficient().unwrap().inverse().unwrap(); | ||
while !remainder.is_zero() && remainder.degree() >= divisor.degree() { | ||
let cur_q_coeff = *remainder.coeffs.last().unwrap() * &divisor_leading_inv; | ||
let cur_q_degree = remainder.degree() - divisor.degree(); | ||
quotient[cur_q_degree] = cur_q_coeff; | ||
|
||
for (i, div_coeff) in divisor.iter_with_index() { | ||
remainder[cur_q_degree + i] -= &(cur_q_coeff * &div_coeff); | ||
} | ||
while let Some(true) = remainder.coeffs.last().map(|c| c.is_zero()) { | ||
remainder.coeffs.pop(); | ||
} | ||
} | ||
Some(( | ||
DenseUniPolynomial::from_coefficients_vec(quotient), | ||
remainder, | ||
)) | ||
} | ||
} | ||
} | ||
impl<'a, F: 'a + FftField> DenseOrSparseUniPolynomial<'a, F> { | ||
/// Construct `Evaluations` by evaluating a polynomial over the domain | ||
/// `domain`. | ||
pub fn evaluate_over_domain<D: EvaluationDomain<F>>( | ||
poly: impl Into<Self>, | ||
domain: D, | ||
) -> Evaluations<F, D> { | ||
let poly = poly.into(); | ||
poly.eval_over_domain_helper(domain) | ||
} | ||
|
||
fn eval_over_domain_helper<D: EvaluationDomain<F>>(self, domain: D) -> Evaluations<F, D> { | ||
match self { | ||
SPolynomial(Cow::Borrowed(s)) => { | ||
let evals = domain.elements().map(|elem| s.evaluate(elem)).collect(); | ||
Evaluations::from_vec_and_domain(evals, domain) | ||
} | ||
SPolynomial(Cow::Owned(s)) => { | ||
let evals = domain.elements().map(|elem| s.evaluate(elem)).collect(); | ||
Evaluations::from_vec_and_domain(evals, domain) | ||
} | ||
DPolynomial(Cow::Borrowed(d)) => { | ||
Evaluations::from_vec_and_domain(domain.fft(&d.coeffs), domain) | ||
} | ||
DPolynomial(Cow::Owned(mut d)) => { | ||
domain.fft_in_place(&mut d.coeffs); | ||
Evaluations::from_vec_and_domain(d.coeffs, domain) | ||
} | ||
} | ||
} | ||
} | ||
pub mod multivariate; | ||
pub mod univariate; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
//! Work with multivariate polynomials. | ||
mod sparse; | ||
|
||
pub use sparse::PolyVars; | ||
pub use sparse::SparsePolynomial; |
Oops, something went wrong.