Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • Kazan-team/algebraics
1 result
Show changes
Commits on Source (7)
Showing
with 464 additions and 489 deletions
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Changed
* add changes here
## [0.2.0]
### Changed
* Update PyO3 from v0.8.2 to v0.9.0
## [0.1.2]
### Added
* Add Python bindings using PyO3 v0.8.2
## [0.1.1]
### Changed
* Split common functionality out into internal function `remove_zero_from_interval`
### Added
* Added functions for calculating the integer part of the base-2 log of a `RealAlgebraicNumber`
## 0.1.0
### Added
* Initial release
[Unreleased]: https://salsa.debian.org/Kazan-team/algebraics/-/compare/v0.2.0...master
[0.2.0]: https://salsa.debian.org/Kazan-team/algebraics/-/compare/v0.1.2...v0.2.0
[0.1.2]: https://salsa.debian.org/Kazan-team/algebraics/-/compare/v0.1.1...v0.1.2
[0.1.1]: https://salsa.debian.org/Kazan-team/algebraics/-/compare/v0.1.0...v0.1.1
......@@ -2,7 +2,7 @@
# See Notices.txt for copyright information
[package]
name = "algebraics"
version = "0.1.2"
version = "0.2.0"
authors = ["Jacob Lifshay <programmerjake@gmail.com>"]
edition = "2018"
license = "LGPL-2.1-or-later"
......@@ -31,6 +31,6 @@ rand_pcg = "0.1.1"
lazy_static = "1.4"
[dependencies.pyo3]
version = "0.8.2"
version = "0.9.0"
optional = true
features = ["num-bigint"]
......@@ -73,7 +73,7 @@ assert_eq!(
Using algebraics from Python:
```bash
python3 -m pip install algebraics==0.1.2
python3 -m pip install algebraics
```
```python
......@@ -86,8 +86,7 @@ Using algebraics in your own Rust project:
```toml
[dependencies.algebraics]
version = "0.1.2"
features = ["python"]
version = "0.2"
```
Developing algebraics:
......
// SPDX-License-Identifier: LGPL-2.1-or-later
// See Notices.txt for copyright information
use crate::interval_arithmetic::DyadicFractionInterval;
use crate::polynomial::Polynomial;
use crate::traits::AlwaysExactDiv;
use crate::traits::AlwaysExactDivAssign;
use crate::traits::CeilLog2;
use crate::traits::ExactDiv;
use crate::traits::ExactDivAssign;
use crate::traits::FloorLog2;
use crate::util::DebugAsDisplay;
use crate::util::Sign;
use num_bigint::BigInt;
use num_bigint::BigUint;
use crate::{
interval_arithmetic::DyadicFractionInterval,
polynomial::Polynomial,
traits::{AlwaysExactDiv, AlwaysExactDivAssign, CeilLog2, ExactDiv, ExactDivAssign, FloorLog2},
util::{DebugAsDisplay, Sign},
};
use num_bigint::{BigInt, BigUint};
use num_integer::Integer;
use num_rational::Ratio;
use num_traits::Num;
use num_traits::One;
use num_traits::Pow;
use num_traits::Signed;
use num_traits::ToPrimitive;
use num_traits::Zero;
use std::borrow::Cow;
use std::cmp::Ordering;
use std::error::Error;
use std::fmt;
use std::hash;
use std::mem;
use std::ops::Add;
use std::ops::AddAssign;
use std::ops::Deref;
use std::ops::DerefMut;
use std::ops::Div;
use std::ops::DivAssign;
use std::ops::Mul;
use std::ops::MulAssign;
use std::ops::Neg;
use std::ops::Rem;
use std::ops::RemAssign;
use std::ops::Sub;
use std::ops::SubAssign;
use num_traits::{Num, One, Pow, Signed, ToPrimitive, Zero};
use std::{
borrow::Cow,
cmp::Ordering,
error::Error,
fmt, hash, mem,
ops::{
Add, AddAssign, Deref, DerefMut, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub,
SubAssign,
},
};
pub trait IntoRationalExponent {
fn into_rational_exponent(self) -> Ratio<BigInt>;
......@@ -1527,8 +1508,7 @@ impl<E: IntoRationalExponent> Pow<E> for &'_ RealAlgebraicNumber {
#[cfg(test)]
mod tests {
use super::*;
use crate::util::tests::test_checked_op_helper;
use crate::util::tests::test_op_helper;
use crate::util::tests::{test_checked_op_helper, test_op_helper};
use num_integer::Roots;
fn r(n: i128, d: i128) -> Ratio<BigInt> {
......
......@@ -4,22 +4,16 @@
// FIXME: remove when module made public again
#![allow(dead_code)]
use std::borrow::Borrow;
use std::borrow::BorrowMut;
use std::fmt;
use std::iter::FusedIterator;
use std::ops::Bound;
use std::ops::Index;
use std::ops::IndexMut;
use std::ops::Range;
use std::ops::RangeBounds;
use std::ops::RangeFrom;
use std::ops::RangeFull;
use std::ops::RangeInclusive;
use std::ops::RangeTo;
use std::ops::RangeToInclusive;
use std::slice;
use std::vec;
use std::{
borrow::{Borrow, BorrowMut},
fmt,
iter::FusedIterator,
ops::{
Bound, Index, IndexMut, Range, RangeBounds, RangeFrom, RangeFull, RangeInclusive, RangeTo,
RangeToInclusive,
},
slice, vec,
};
mod private {
pub(crate) trait SealedData {}
......
// SPDX-License-Identifier: LGPL-2.1-or-later
// See Notices.txt for copyright information
use crate::traits::AlwaysExactDiv;
use crate::traits::AlwaysExactDivAssign;
use crate::traits::CeilLog2;
use crate::traits::ExactDiv;
use crate::traits::ExactDivAssign;
use crate::traits::FloorLog2;
use crate::traits::IntervalUnion;
use crate::traits::IntervalUnionAssign;
use crate::util::DebugAsDisplay;
use num_bigint::BigInt;
use num_bigint::BigUint;
use crate::{
traits::{
AlwaysExactDiv, AlwaysExactDivAssign, CeilLog2, ExactDiv, ExactDivAssign, FloorLog2,
IntervalUnion, IntervalUnionAssign,
},
util::DebugAsDisplay,
};
use num_bigint::{BigInt, BigUint};
use num_integer::Integer;
use num_rational::Ratio;
use num_traits::FromPrimitive;
use num_traits::One;
use num_traits::Pow;
use num_traits::Signed;
use num_traits::ToPrimitive;
use num_traits::Zero;
use std::borrow::Cow;
use std::fmt;
use std::mem;
use std::ops::Add;
use std::ops::AddAssign;
use std::ops::Div;
use std::ops::DivAssign;
use std::ops::Mul;
use std::ops::MulAssign;
use std::ops::Neg;
use std::ops::Sub;
use std::ops::SubAssign;
use std::sync::Arc;
use std::sync::RwLock;
use num_traits::{FromPrimitive, One, Pow, Signed, ToPrimitive, Zero};
use std::{
borrow::Cow,
fmt, mem,
ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
sync::{Arc, RwLock},
};
fn convert_log2_denom_floor(numer: &mut BigInt, old_log2_denom: usize, new_log2_denom: usize) {
if new_log2_denom >= old_log2_denom {
......@@ -47,7 +31,7 @@ fn convert_log2_denom_ceil(numer: &mut BigInt, old_log2_denom: usize, new_log2_d
if new_log2_denom >= old_log2_denom {
*numer <<= new_log2_denom - old_log2_denom;
} else {
let mut numer_value = mem::replace(numer, Default::default());
let mut numer_value = mem::take(numer);
numer_value = -numer_value;
numer_value >>= old_log2_denom - new_log2_denom;
numer_value = -numer_value;
......@@ -218,7 +202,7 @@ impl DyadicFractionInterval {
pub fn set_negative_one(&mut self) {
self.lower_bound_numer.set_one();
self.lower_bound_numer <<= self.log2_denom;
self.lower_bound_numer = -mem::replace(&mut self.lower_bound_numer, Default::default());
self.lower_bound_numer = -mem::take(&mut self.lower_bound_numer);
self.upper_bound_numer.clone_from(&self.lower_bound_numer);
}
pub fn into_ratio_range(self) -> (Ratio<BigInt>, Ratio<BigInt>) {
......@@ -478,7 +462,7 @@ impl DyadicFractionInterval {
self
}
pub fn square_assign(&mut self) {
*self = mem::replace(self, Default::default()).into_square();
*self = mem::take(self).into_square();
}
pub fn square(&self) -> Self {
self.clone().into_square()
......@@ -509,7 +493,7 @@ impl DyadicFractionInterval {
}
}
pub fn sqrt_assign(&mut self) {
*self = mem::replace(self, Default::default()).into_sqrt();
*self = mem::take(self).into_sqrt();
}
pub fn into_sqrt(self) -> Self {
Self::do_sqrt(Cow::Owned(self))
......@@ -790,10 +774,10 @@ impl DyadicFractionInterval {
pub fn abs_assign(&mut self) {
let contains_zero = self.contains_zero();
if self.lower_bound_numer.is_negative() {
self.lower_bound_numer = -mem::replace(&mut self.lower_bound_numer, Default::default());
self.lower_bound_numer = -mem::take(&mut self.lower_bound_numer);
}
if self.upper_bound_numer.is_negative() {
self.upper_bound_numer = -mem::replace(&mut self.upper_bound_numer, Default::default());
self.upper_bound_numer = -mem::take(&mut self.upper_bound_numer);
}
if self.lower_bound_numer > self.upper_bound_numer {
mem::swap(&mut self.lower_bound_numer, &mut self.upper_bound_numer);
......@@ -823,12 +807,12 @@ impl DyadicFractionInterval {
self.clone().into_floor(new_log2_denom)
}
pub fn ceil_assign(&mut self, new_log2_denom: usize) {
self.lower_bound_numer = -mem::replace(&mut self.lower_bound_numer, Default::default());
self.upper_bound_numer = -mem::replace(&mut self.upper_bound_numer, Default::default());
self.lower_bound_numer = -mem::take(&mut self.lower_bound_numer);
self.upper_bound_numer = -mem::take(&mut self.upper_bound_numer);
self.lower_bound_numer >>= self.log2_denom;
self.upper_bound_numer >>= self.log2_denom;
self.lower_bound_numer = -mem::replace(&mut self.lower_bound_numer, Default::default());
self.upper_bound_numer = -mem::replace(&mut self.upper_bound_numer, Default::default());
self.lower_bound_numer = -mem::take(&mut self.lower_bound_numer);
self.upper_bound_numer = -mem::take(&mut self.upper_bound_numer);
self.log2_denom = 0;
self.convert_log2_denom(new_log2_denom);
}
......@@ -1320,15 +1304,13 @@ impl<E: Integer> Pow<E> for &'_ DyadicFractionInterval {
#[cfg(test)]
mod tests {
use super::*;
use crate::util::tests::test_checked_op_helper;
use crate::util::tests::test_op_helper;
use crate::util::tests::test_unary_op_helper;
use crate::util::tests::{test_checked_op_helper, test_op_helper, test_unary_op_helper};
use num_traits::ToPrimitive;
use std::borrow::Borrow;
use std::borrow::BorrowMut;
use std::convert::TryInto;
use std::ops::Deref;
use std::ops::DerefMut;
use std::{
borrow::{Borrow, BorrowMut},
convert::TryInto,
ops::{Deref, DerefMut},
};
type DFI = DyadicFractionInterval;
......
......@@ -4,19 +4,14 @@
// FIXME: remove when module made public again
#![allow(dead_code)]
use crate::array2d::Array2DOwned;
use crate::array2d::Array2DSlice;
use crate::array2d::{Array2DOwned, Array2DSlice};
use num_integer::Integer;
use num_rational::Ratio;
use num_traits::FromPrimitive;
use num_traits::NumAssign;
use num_traits::NumRef;
use num_traits::Signed;
use num_traits::Zero;
use std::cmp::Ordering;
use std::ops::Add;
use std::ops::Mul;
use std::ops::RangeTo;
use num_traits::{FromPrimitive, NumAssign, NumRef, Signed, Zero};
use std::{
cmp::Ordering,
ops::{Add, Mul, RangeTo},
};
pub(crate) fn inner_product<'a, L, R, T>(a: Array2DSlice<'a, L>, b: Array2DSlice<'a, R>) -> T
where
......@@ -186,8 +181,7 @@ where
mod tests {
use super::*;
use num_bigint::BigInt;
use num_traits::One;
use num_traits::Pow;
use num_traits::{One, Pow};
#[test]
fn test_gram_schmidt() {
......
// SPDX-License-Identifier: LGPL-2.1-or-later
// See Notices.txt for copyright information
use crate::polynomial::DivisorIsOne;
use crate::polynomial::PolynomialCoefficient;
use crate::polynomial::PolynomialReducingFactorSupported;
use crate::traits::AlwaysExactDiv;
use crate::traits::AlwaysExactDivAssign;
use crate::traits::ExactDiv;
use crate::traits::ExactDivAssign;
use crate::traits::ExtendedGCD;
use crate::traits::ExtendedGCDResult;
use crate::traits::GCD;
use crate::util::BaseAndExponent;
use num_bigint::BigInt;
use num_bigint::BigUint;
use crate::{
polynomial::{DivisorIsOne, PolynomialCoefficient, PolynomialReducingFactorSupported},
traits::{
AlwaysExactDiv, AlwaysExactDivAssign, ExactDiv, ExactDivAssign, ExtendedGCD,
ExtendedGCDResult, GCD,
},
util::BaseAndExponent,
};
use num_bigint::{BigInt, BigUint};
use num_integer::Integer;
use num_traits::CheckedAdd;
use num_traits::CheckedDiv;
use num_traits::CheckedMul;
use num_traits::CheckedSub;
use num_traits::FromPrimitive;
use num_traits::One;
use num_traits::ToPrimitive;
use num_traits::Zero;
use std::borrow::Borrow;
use std::borrow::Cow;
use std::convert::identity;
use std::convert::TryInto;
use std::fmt;
use std::hash::Hash;
use std::ops::Add;
use std::ops::AddAssign;
use std::ops::Deref;
use std::ops::Div;
use std::ops::DivAssign;
use std::ops::Mul;
use std::ops::MulAssign;
use std::ops::Neg;
use std::ops::Sub;
use std::ops::SubAssign;
use num_traits::{
CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, FromPrimitive, One, ToPrimitive, Zero,
};
use std::{
borrow::{Borrow, Cow},
convert::{identity, TryInto},
fmt,
hash::Hash,
ops::{Add, AddAssign, Deref, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
};
pub trait ModularReduce: Clone + Eq {
fn modular_reduce_assign<M: Modulus<Self>>(&mut self, modulus: M);
......@@ -1272,8 +1254,7 @@ where
#[cfg(test)]
mod tests {
use super::*;
use crate::util::tests::test_op_helper;
use crate::util::tests::test_unary_op_helper;
use crate::util::tests::{test_op_helper, test_unary_op_helper};
fn test_overflow_for_type<
T: Modulus<T> + ModularReduce + Sub<Output = T> + Copy + Into<BigInt> + fmt::Debug,
......
// SPDX-License-Identifier: LGPL-2.1-or-later
// See Notices.txt for copyright information
use crate::traits::AlwaysExactDivAssign;
use crate::traits::CharacteristicZero;
use crate::traits::ExactDiv;
use crate::traits::ExactDivAssign;
use crate::traits::GCDAndLCM;
use crate::traits::RingCharacteristic;
use crate::traits::GCD;
use crate::traits::{
AlwaysExactDivAssign, CharacteristicZero, ExactDiv, ExactDivAssign, GCDAndLCM,
RingCharacteristic, GCD,
};
use num_bigint::BigInt;
use num_integer::Integer;
use num_rational::Ratio;
use num_traits::FromPrimitive;
use num_traits::NumAssign;
use num_traits::One;
use num_traits::Pow;
use num_traits::Signed;
use num_traits::ToPrimitive;
use num_traits::Zero;
use std::borrow::Cow;
use std::error::Error;
use std::fmt;
use std::hash;
use std::iter::FromIterator;
use std::mem;
use std::ops::Neg;
use std::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
use std::slice;
use std::vec;
use num_traits::{FromPrimitive, NumAssign, One, Pow, Signed, ToPrimitive, Zero};
use std::{
borrow::Cow,
error::Error,
fmt, hash,
iter::FromIterator,
mem,
ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
slice, vec,
};
mod add_sub;
mod distinct_degree_factorization;
......
......@@ -2,21 +2,16 @@
// See Notices.txt for copyright information
// use super::util::{pairwise_op_eq_move, pairwise_op_eq_ref, pairwise_op_ref_ref};
use crate::polynomial::Polynomial;
use crate::polynomial::PolynomialCoefficient;
use crate::traits::ExactDiv;
use crate::traits::GCDAndLCM;
use crate::traits::GCD;
use num_traits::CheckedAdd;
use num_traits::CheckedSub;
use num_traits::One;
use num_traits::Zero;
use std::borrow::Cow;
use std::mem;
use std::ops::Neg;
use std::ops::Sub;
use std::ops::SubAssign;
use std::ops::{Add, AddAssign};
use crate::{
polynomial::{Polynomial, PolynomialCoefficient},
traits::{ExactDiv, GCDAndLCM, GCD},
};
use num_traits::{CheckedAdd, CheckedSub, One, Zero};
use std::{
borrow::Cow,
mem,
ops::{Add, AddAssign, Neg, Sub, SubAssign},
};
fn add_sub_assign<T: PolynomialCoefficient, AddSubAssign: Fn(&mut T::Element, T::Element)>(
lhs: &mut Polynomial<T>,
......
// SPDX-License-Identifier: LGPL-2.1-or-later
// See Notices.txt for copyright information
use crate::mod_int::ModularInteger;
use crate::mod_int::ModularReducePow;
use crate::mod_int::Modulus;
use crate::mod_int::PrimeModulus;
use crate::polynomial::Polynomial;
use crate::traits::ExtendedGCD;
use crate::traits::GCD;
use crate::{
mod_int::{ModularInteger, ModularReducePow, Modulus, PrimeModulus},
polynomial::Polynomial,
traits::{ExtendedGCD, GCD},
};
use num_integer::Integer;
use num_traits::Zero;
use std::fmt;
use std::hash::Hash;
use std::{fmt, hash::Hash};
impl<V, M> Polynomial<ModularInteger<V, M>>
where
......
// SPDX-License-Identifier: LGPL-2.1-or-later
// See Notices.txt for copyright information
use crate::polynomial::Polynomial;
use crate::polynomial::PolynomialCoefficient;
use crate::polynomial::PolynomialCoefficientElement;
use crate::polynomial::PolynomialDivSupported;
use crate::polynomial::PseudoDivRem;
use crate::traits::ExactDiv;
use crate::traits::ExactDivAssign;
use crate::{
polynomial::{
Polynomial, PolynomialCoefficient, PolynomialCoefficientElement, PolynomialDivSupported,
PseudoDivRem,
},
traits::{ExactDiv, ExactDivAssign},
};
use num_integer::Integer;
use num_traits::CheckedDiv;
use num_traits::CheckedRem;
use num_traits::Zero;
use std::borrow::Borrow;
use std::borrow::Cow;
use std::convert::identity;
use std::mem;
use std::ops::{Div, DivAssign, Mul, Rem, RemAssign, SubAssign};
use num_traits::{CheckedDiv, CheckedRem, Zero};
use std::{
borrow::{Borrow, Cow},
convert::identity,
mem,
ops::{Div, DivAssign, Mul, Rem, RemAssign, SubAssign},
};
fn quotient_len(numerator_len: usize, denominator_len: usize) -> Option<usize> {
debug_assert_ne!(denominator_len, 0);
......@@ -511,8 +510,7 @@ impl<T: PolynomialDivSupported> Polynomial<T> {
#[cfg(test)]
mod tests {
use super::*;
use crate::util::tests::test_op_helper;
use crate::util::DebugAsDisplay;
use crate::util::{tests::test_op_helper, DebugAsDisplay};
use num_bigint::BigInt;
use num_integer::Integer;
use num_rational::Ratio;
......
// SPDX-License-Identifier: LGPL-2.1-or-later
// See Notices.txt for copyright information
use crate::mod_int::KnownOddPrime;
use crate::mod_int::ModularInteger;
use crate::mod_int::Modulus;
use crate::polynomial::Polynomial;
use crate::polynomial::PolynomialCoefficient;
use crate::polynomial::PolynomialDivSupported;
use crate::polynomial::PolynomialFactor;
use crate::polynomial::PolynomialFactors;
use crate::polynomial::PolynomialReducingFactorSupported;
use crate::traits::ExactDiv;
use crate::traits::ExtendedGCD;
use crate::traits::ExtendedGCDResult;
use crate::util::for_subsets_of_size;
use crate::util::next_prime_i32;
use crate::util::ContinueBreak;
use crate::util::LeafOrNodePair;
use crate::util::PrintTree;
use crate::util::PrintTreeData;
use crate::{
mod_int::{KnownOddPrime, ModularInteger, Modulus},
polynomial::{
Polynomial, PolynomialCoefficient, PolynomialDivSupported, PolynomialFactor,
PolynomialFactors, PolynomialReducingFactorSupported,
},
traits::{ExactDiv, ExtendedGCD, ExtendedGCDResult},
util::{
for_subsets_of_size, next_prime_i32, ContinueBreak, LeafOrNodePair, PrintTree,
PrintTreeData,
},
};
use num_bigint::BigInt;
use num_integer::Integer;
use num_rational::Ratio;
use num_traits::One;
use num_traits::Signed;
use rand::Rng;
use rand::SeedableRng;
use num_traits::{One, Signed};
use rand::{Rng, SeedableRng};
use rand_pcg::Pcg64Mcg;
use std::cmp::Ordering;
use std::collections::BinaryHeap;
use std::fmt;
use std::mem;
use std::ops::Add;
use std::ops::AddAssign;
use std::{
cmp::Ordering,
collections::BinaryHeap,
fmt, mem,
ops::{Add, AddAssign},
};
struct FactorTreeInteriorNode<T: PolynomialCoefficient> {
left: FactorTreeNode<T>,
......@@ -246,14 +238,10 @@ impl FactorTreeInteriorNode<ModularInteger<BigInt, BigInt>> {
}
let old_left_product = set_modulus(self.left.product(), new_modulus);
let old_right_product = set_modulus(self.right.product(), new_modulus);
let old_left_bezout_coefficient = set_modulus(
mem::replace(&mut self.left_bezout_coefficient, Default::default()),
new_modulus,
);
let old_right_bezout_coefficient = set_modulus(
mem::replace(&mut self.right_bezout_coefficient, Default::default()),
new_modulus,
);
let old_left_bezout_coefficient =
set_modulus(mem::take(&mut self.left_bezout_coefficient), new_modulus);
let old_right_bezout_coefficient =
set_modulus(mem::take(&mut self.right_bezout_coefficient), new_modulus);
let error = &new_product - &old_left_product * &old_right_product;
let (quotient, remainder) =
(&old_left_bezout_coefficient * &error).div_rem(&old_right_product);
......@@ -678,10 +666,8 @@ impl Polynomial<BigInt> {
#[cfg(test)]
mod tests {
use super::*;
use num_traits::One;
use num_traits::Pow;
use std::collections::HashSet;
use std::ops::Mul;
use num_traits::{One, Pow};
use std::{collections::HashSet, ops::Mul};
fn p(coefficients: Vec<i128>) -> Polynomial<BigInt> {
coefficients.into_iter().map(BigInt::from).collect()
......
// SPDX-License-Identifier: LGPL-2.1-or-later
// See Notices.txt for copyright information
use crate::polynomial::Polynomial;
use crate::polynomial::PolynomialCoefficient;
use crate::polynomial::PolynomialDivSupported;
use crate::polynomial::PolynomialReducingFactorSupported;
use crate::polynomial::PseudoDivRem;
use crate::traits::ExactDiv;
use crate::traits::ExactDivAssign;
use crate::traits::ExtendedGCD;
use crate::traits::ExtendedGCDAndLCM;
use crate::traits::ExtendedGCDResult;
use crate::traits::GCDAndLCM;
use crate::traits::GCD;
use crate::{
polynomial::{
Polynomial, PolynomialCoefficient, PolynomialDivSupported,
PolynomialReducingFactorSupported, PseudoDivRem,
},
traits::{
ExactDiv, ExactDivAssign, ExtendedGCD, ExtendedGCDAndLCM, ExtendedGCDResult, GCDAndLCM, GCD,
},
};
use num_integer::Integer;
use num_traits::Zero;
use std::borrow::Cow;
use std::mem;
use std::{borrow::Cow, mem};
/// computes factor * base.pow(exponent_positive_part - exponent_negative_part)
fn exact_mul_by_signed_power<T: PolynomialCoefficient + for<'a> ExactDiv<&'a T, Output = T>>(
......
// SPDX-License-Identifier: LGPL-2.1-or-later
// See Notices.txt for copyright information
use crate::polynomial::Polynomial;
use crate::polynomial::PolynomialCoefficient;
use crate::polynomial::{Polynomial, PolynomialCoefficient};
use num_integer::Integer;
use num_traits::CheckedMul;
use num_traits::Pow;
use num_traits::{One, Zero};
use std::borrow::Cow;
use std::ops::{AddAssign, Mul, MulAssign};
use num_traits::{CheckedMul, One, Pow, Zero};
use std::{
borrow::Cow,
ops::{AddAssign, Mul, MulAssign},
};
impl<'a, T: PolynomialCoefficient> Mul for &'a Polynomial<T> {
type Output = Polynomial<T>;
......
// SPDX-License-Identifier: LGPL-2.1-or-later
// See Notices.txt for copyright information
use crate::mod_int::ModularInteger;
use crate::mod_int::ModularReducePow;
use crate::mod_int::OddPrimeModulus;
use crate::polynomial::Polynomial;
use crate::traits::ExactDivAssign;
use crate::traits::ExtendedGCD;
use crate::traits::GCD;
use crate::{
mod_int::{ModularInteger, ModularReducePow, OddPrimeModulus},
polynomial::Polynomial,
traits::{ExactDivAssign, ExtendedGCD, GCD},
};
use num_bigint::ToBigInt;
use num_integer::Integer;
use num_traits::Pow;
use rand::distributions::uniform::SampleUniform;
use rand::distributions::Distribution;
use rand::distributions::Uniform;
use rand::Rng;
use std::fmt;
use std::hash::Hash;
use std::iter;
use rand::{
distributions::{uniform::SampleUniform, Distribution, Uniform},
Rng,
};
use std::{fmt, hash::Hash, iter};
impl<V, M> Polynomial<ModularInteger<V, M>>
where
......
// SPDX-License-Identifier: LGPL-2.1-or-later
// See Notices.txt for copyright information
pub use crate::algebraic_numbers::RealAlgebraicNumber;
pub use crate::traits::ExactDiv as _;
pub use crate::traits::ExactDivAssign as _;
pub use crate::traits::ExtendedGCD as _;
pub use crate::traits::IntervalUnion as _;
pub use crate::traits::IntervalUnionAssign as _;
pub use crate::traits::GCD as _;
pub use num_traits::CheckedAdd as _;
pub use num_traits::CheckedDiv as _;
pub use num_traits::CheckedMul as _;
pub use num_traits::CheckedRem as _;
pub use num_traits::CheckedSub as _;
pub use num_traits::One as _;
pub use num_traits::Pow as _;
pub use num_traits::Signed as _;
pub use num_traits::Zero as _;
pub use crate::{
algebraic_numbers::RealAlgebraicNumber,
traits::{
ExactDiv as _, ExactDivAssign as _, ExtendedGCD as _, IntervalUnion as _,
IntervalUnionAssign as _, GCD as _,
},
};
pub use num_traits::{
CheckedAdd as _, CheckedDiv as _, CheckedMul as _, CheckedRem as _, CheckedSub as _, One as _,
Pow as _, Signed as _, Zero as _,
};
......@@ -3,51 +3,43 @@
#![cfg(feature = "python")]
use crate::algebraic_numbers::RealAlgebraicNumber;
use crate::traits::ExactDivAssign;
use crate::{algebraic_numbers::RealAlgebraicNumber, traits::ExactDivAssign};
use num_bigint::BigInt;
use num_traits::Signed;
use num_traits::Zero;
use pyo3::basic::CompareOp;
use pyo3::exceptions::TypeError;
use pyo3::exceptions::ValueError;
use pyo3::exceptions::ZeroDivisionError;
use pyo3::prelude::*;
use pyo3::types::PyAny;
use pyo3::PyNativeType;
use pyo3::PyNumberProtocol;
use pyo3::PyObjectProtocol;
use std::sync::Arc;
use num_traits::{Signed, Zero};
use pyo3::{
basic::CompareOp,
exceptions::{TypeError, ValueError, ZeroDivisionError},
prelude::*,
types::PyAny,
PyNativeType, PyNumberProtocol, PyObjectProtocol,
};
use std::{
ops::{Deref, DerefMut},
sync::Arc,
};
impl FromPyObject<'_> for RealAlgebraicNumber {
fn extract(value: &PyAny) -> PyResult<Self> {
Ok((*RealAlgebraicNumberPy::extract(value)?.value).clone())
Ok(RealAlgebraicNumberWrapper::extract(value)?.into())
}
}
impl<'a> FromPyObject<'a> for &'a RealAlgebraicNumber {
fn extract(value: &'a PyAny) -> PyResult<Self> {
let result = RealAlgebraicNumberPy::extract(value)?.value.clone();
let result: &'a _ = value.py().register_any(result);
Ok(&**result)
let wrapper: RealAlgebraicNumberWrapper = value.extract()?;
Ok(&value.py().register_any(wrapper))
}
}
impl IntoPy<PyObject> for RealAlgebraicNumber {
fn into_py(self, py: Python) -> PyObject {
RealAlgebraicNumberPy {
value: Arc::new(self),
}
.into_py(py)
RealAlgebraicNumberWrapper::from(self).into_py(py)
}
}
impl IntoPy<PyObject> for &'_ RealAlgebraicNumber {
fn into_py(self, py: Python) -> PyObject {
RealAlgebraicNumberPy {
value: Arc::new(self.clone()),
}
.into_py(py)
RealAlgebraicNumberWrapper::from(self).into_py(py)
}
}
......@@ -57,48 +49,102 @@ impl ToPyObject for RealAlgebraicNumber {
}
}
#[pyclass(name=RealAlgebraicNumber, module="algebraics")]
#[derive(Clone)]
struct RealAlgebraicNumberPy {
value: Arc<RealAlgebraicNumber>,
struct RealAlgebraicNumberWrapper(Arc<RealAlgebraicNumber>);
impl Deref for RealAlgebraicNumberWrapper {
type Target = Arc<RealAlgebraicNumber>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl FromPyObject<'_> for RealAlgebraicNumberPy {
impl DerefMut for RealAlgebraicNumberWrapper {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl FromPyObject<'_> for RealAlgebraicNumberWrapper {
fn extract(value: &PyAny) -> PyResult<Self> {
if let Ok(value) = value.downcast_ref::<RealAlgebraicNumberPy>() {
return Ok(value.clone());
if let Ok(value) = value.extract::<PyRef<RealAlgebraicNumberPy2>>() {
return Ok(value.value.clone());
}
let value = value.extract::<Option<BigInt>>()?;
let value = match value {
None => RealAlgebraicNumber::zero(),
Some(value) => RealAlgebraicNumber::from(value),
let value = value.extract::<BigInt>()?;
Ok(RealAlgebraicNumber::from(value).into())
}
}
impl From<Arc<RealAlgebraicNumber>> for RealAlgebraicNumberWrapper {
fn from(v: Arc<RealAlgebraicNumber>) -> Self {
RealAlgebraicNumberWrapper(v)
}
}
impl From<RealAlgebraicNumber> for RealAlgebraicNumberWrapper {
fn from(v: RealAlgebraicNumber) -> Self {
RealAlgebraicNumberWrapper(v.into())
}
}
impl From<&'_ RealAlgebraicNumber> for RealAlgebraicNumberWrapper {
fn from(v: &RealAlgebraicNumber) -> Self {
RealAlgebraicNumber::clone(v).into()
}
}
impl Into<Arc<RealAlgebraicNumber>> for RealAlgebraicNumberWrapper {
fn into(self) -> Arc<RealAlgebraicNumber> {
self.0
}
}
impl From<RealAlgebraicNumberWrapper> for RealAlgebraicNumber {
fn from(v: RealAlgebraicNumberWrapper) -> Self {
match Arc::try_unwrap(v.0) {
Ok(v) => v,
Err(v) => (*v).clone(),
}
.into();
Ok(RealAlgebraicNumberPy { value })
}
}
impl IntoPy<PyObject> for RealAlgebraicNumberWrapper {
fn into_py(self, py: Python) -> PyObject {
RealAlgebraicNumberPy2 { value: self }.into_py(py)
}
}
impl IntoPy<PyObject> for &'_ RealAlgebraicNumberWrapper {
fn into_py(self, py: Python) -> PyObject {
RealAlgebraicNumberWrapper::clone(self).into_py(py)
}
}
impl ToPyObject for RealAlgebraicNumberWrapper {
fn to_object(&self, py: Python) -> PyObject {
self.into_py(py)
}
}
#[pyclass(name=RealAlgebraicNumber, module="algebraics")]
struct RealAlgebraicNumberPy2 {
value: RealAlgebraicNumberWrapper,
}
#[pymethods(PyObjectProtocol, PyNumberProtocol)]
impl RealAlgebraicNumberPy {
impl RealAlgebraicNumberPy2 {
#[new]
fn pynew(obj: &PyRawObject, value: Option<RealAlgebraicNumberPy>) {
obj.init(value.unwrap_or_else(|| RealAlgebraicNumberPy {
value: RealAlgebraicNumber::zero().into(),
}));
}
fn __trunc__(&self) -> BigInt {
let gil = Python::acquire_gil();
let py = gil.python();
fn pynew(value: Option<RealAlgebraicNumberWrapper>) -> Self {
let value = value.unwrap_or_else(|| RealAlgebraicNumber::zero().into());
RealAlgebraicNumberPy2 { value }
}
fn __trunc__(&self, py: Python<'_>) -> BigInt {
py.allow_threads(|| self.value.to_integer_trunc())
}
fn __floor__(&self) -> BigInt {
let gil = Python::acquire_gil();
let py = gil.python();
fn __floor__(&self, py: Python<'_>) -> BigInt {
py.allow_threads(|| self.value.to_integer_floor())
}
fn __ceil__(&self) -> BigInt {
let gil = Python::acquire_gil();
let py = gil.python();
fn __ceil__(&self, py: Python<'_>) -> BigInt {
py.allow_threads(|| self.value.to_integer_ceil())
}
fn to_integer(&self) -> Option<BigInt> {
......@@ -121,47 +167,37 @@ impl RealAlgebraicNumberPy {
fn is_integer(&self) -> bool {
self.value.is_integer()
}
fn recip(&self) -> PyResult<RealAlgebraicNumberPy> {
Python::acquire_gil()
.python()
.allow_threads(|| {
Some(RealAlgebraicNumberPy {
value: self.value.checked_recip()?.into(),
})
})
fn recip(&self, py: Python<'_>) -> PyResult<RealAlgebraicNumberWrapper> {
py.allow_threads(|| Some(self.value.checked_recip()?.into()))
.ok_or_else(get_div_by_zero_error)
}
/// returns `floor(log2(self))`
fn floor_log2(&self) -> PyResult<i64> {
Python::acquire_gil()
.python()
.allow_threads(|| self.value.checked_floor_log2())
fn floor_log2(&self, py: Python<'_>) -> PyResult<i64> {
py.allow_threads(|| self.value.checked_floor_log2())
.ok_or_else(get_floor_ceil_log2_error)
}
/// returns `ceil(log2(self))`
fn ceil_log2(&self) -> PyResult<i64> {
Python::acquire_gil()
.python()
.allow_threads(|| self.value.checked_ceil_log2())
fn ceil_log2(&self, py: Python<'_>) -> PyResult<i64> {
py.allow_threads(|| self.value.checked_ceil_log2())
.ok_or_else(get_floor_ceil_log2_error)
}
}
#[pyproto]
impl PyObjectProtocol for RealAlgebraicNumberPy {
impl PyObjectProtocol for RealAlgebraicNumberPy2 {
fn __repr__(&self) -> PyResult<String> {
Ok(format!("<{:?}>", self.value))
Ok(format!("<{:?}>", *self.value))
}
fn __richcmp__(&self, other: &PyAny, op: CompareOp) -> PyResult<bool> {
let py = other.py();
let other = other.extract::<RealAlgebraicNumberPy>()?;
let other = other.extract::<RealAlgebraicNumberWrapper>()?;
Ok(py.allow_threads(|| match op {
CompareOp::Lt => self.value < other.value,
CompareOp::Le => self.value <= other.value,
CompareOp::Eq => self.value == other.value,
CompareOp::Ne => self.value != other.value,
CompareOp::Gt => self.value > other.value,
CompareOp::Ge => self.value >= other.value,
CompareOp::Lt => *self.value < *other,
CompareOp::Le => *self.value <= *other,
CompareOp::Eq => *self.value == *other,
CompareOp::Ne => *self.value != *other,
CompareOp::Gt => *self.value > *other,
CompareOp::Ge => *self.value >= *other,
}))
}
}
......@@ -174,88 +210,116 @@ fn get_floor_ceil_log2_error() -> PyErr {
ValueError::py_err("can't extract base-2 logarithm of zero or negative RealAlgebraicNumber")
}
fn try_arithmetic_helper<
E: Send,
F: Send + FnOnce(&mut RealAlgebraicNumber, &RealAlgebraicNumber) -> Result<(), E>,
MapErr: FnOnce(E) -> PyErr,
>(
lhs: &PyAny,
rhs: RealAlgebraicNumberWrapper,
f: F,
map_err: MapErr,
) -> PyResult<RealAlgebraicNumberWrapper> {
let py = lhs.py();
let mut lhs: RealAlgebraicNumberWrapper = lhs.extract()?;
py.allow_threads(|| {
f(Arc::make_mut(&mut lhs), &**rhs)?;
Ok(lhs)
})
.map_err(map_err)
}
fn arithmetic_helper<F: Send + FnOnce(&mut RealAlgebraicNumber, &RealAlgebraicNumber)>(
lhs: &PyAny,
rhs: RealAlgebraicNumberWrapper,
f: F,
) -> PyResult<RealAlgebraicNumberWrapper> {
enum Uninhabited {}
try_arithmetic_helper(
lhs,
rhs,
|lhs, rhs| {
f(lhs, rhs);
Ok(())
},
|v: Uninhabited| match v {},
)
}
#[pyproto]
impl PyNumberProtocol for RealAlgebraicNumberPy {
fn __add__(lhs: &PyAny, rhs: RealAlgebraicNumberPy) -> PyResult<RealAlgebraicNumberPy> {
let py = lhs.py();
let mut lhs = lhs.extract::<RealAlgebraicNumberPy>()?;
Ok(py.allow_threads(|| {
*Arc::make_mut(&mut lhs.value) += &*rhs.value;
lhs
}))
impl PyNumberProtocol for RealAlgebraicNumberPy2 {
fn __add__(
lhs: &PyAny,
rhs: RealAlgebraicNumberWrapper,
) -> PyResult<RealAlgebraicNumberWrapper> {
arithmetic_helper(lhs, rhs, |lhs, rhs| *lhs += rhs)
}
fn __sub__(lhs: &PyAny, rhs: RealAlgebraicNumberPy) -> PyResult<RealAlgebraicNumberPy> {
let py = lhs.py();
let mut lhs = lhs.extract::<RealAlgebraicNumberPy>()?;
Ok(py.allow_threads(|| {
*Arc::make_mut(&mut lhs.value) -= &*rhs.value;
lhs
}))
fn __sub__(
lhs: &PyAny,
rhs: RealAlgebraicNumberWrapper,
) -> PyResult<RealAlgebraicNumberWrapper> {
arithmetic_helper(lhs, rhs, |lhs, rhs| *lhs -= rhs)
}
fn __mul__(lhs: &PyAny, rhs: RealAlgebraicNumberPy) -> PyResult<RealAlgebraicNumberPy> {
let py = lhs.py();
let mut lhs = lhs.extract::<RealAlgebraicNumberPy>()?;
Ok(py.allow_threads(|| {
*Arc::make_mut(&mut lhs.value) *= &*rhs.value;
lhs
}))
fn __mul__(
lhs: &PyAny,
rhs: RealAlgebraicNumberWrapper,
) -> PyResult<RealAlgebraicNumberWrapper> {
arithmetic_helper(lhs, rhs, |lhs, rhs| *lhs *= rhs)
}
fn __truediv__(lhs: &PyAny, rhs: RealAlgebraicNumberPy) -> PyResult<RealAlgebraicNumberPy> {
let py = lhs.py();
let mut lhs = lhs.extract::<RealAlgebraicNumberPy>()?;
py.allow_threads(|| -> Result<RealAlgebraicNumberPy, ()> {
Arc::make_mut(&mut lhs.value).checked_exact_div_assign(&*rhs.value)?;
Ok(lhs)
})
.map_err(|()| get_div_by_zero_error())
fn __truediv__(
lhs: &PyAny,
rhs: RealAlgebraicNumberWrapper,
) -> PyResult<RealAlgebraicNumberWrapper> {
try_arithmetic_helper(
lhs,
rhs,
|lhs, rhs| lhs.checked_exact_div_assign(rhs),
|()| get_div_by_zero_error(),
)
}
fn __pow__(
lhs: RealAlgebraicNumberPy,
rhs: RealAlgebraicNumberPy,
lhs: &PyAny,
rhs: RealAlgebraicNumberWrapper,
modulus: &PyAny,
) -> PyResult<RealAlgebraicNumberPy> {
let py = modulus.py();
) -> PyResult<RealAlgebraicNumberWrapper> {
if !modulus.is_none() {
return Err(TypeError::py_err(
"3 argument pow() not allowed for RealAlgebraicNumber",
));
}
py.allow_threads(|| -> Result<RealAlgebraicNumberPy, &'static str> {
if let Some(rhs) = rhs.value.to_rational() {
Ok(RealAlgebraicNumberPy {
value: lhs
.value
try_arithmetic_helper(
lhs,
rhs,
|lhs, rhs| {
if let Some(rhs) = rhs.to_rational() {
*lhs = lhs
.checked_pow(rhs)
.ok_or("pow() failed for RealAlgebraicNumber")?
.into(),
})
} else {
Err("exponent must be rational for RealAlgebraicNumber")
}
})
.map_err(ValueError::py_err)
.ok_or("pow() failed for RealAlgebraicNumber")?;
Ok(())
} else {
Err("exponent must be rational for RealAlgebraicNumber")
}
},
ValueError::py_err,
)
}
// Unary arithmetic
fn __neg__(&self) -> PyResult<RealAlgebraicNumberPy> {
fn __neg__(&self) -> PyResult<RealAlgebraicNumberWrapper> {
Ok(Python::acquire_gil()
.python()
.allow_threads(|| RealAlgebraicNumberPy {
value: Arc::from(-&*self.value),
}))
.allow_threads(|| (-&**self.value).into()))
}
fn __abs__(&self) -> PyResult<RealAlgebraicNumberPy> {
fn __abs__(&self) -> PyResult<RealAlgebraicNumberWrapper> {
Ok(Python::acquire_gil()
.python()
.allow_threads(|| RealAlgebraicNumberPy {
value: self.value.abs().into(),
}))
.allow_threads(|| self.value.abs().into()))
}
}
#[pymodule]
fn algebraics(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<RealAlgebraicNumberPy>()?;
m.add_class::<RealAlgebraicNumberPy2>()?;
Ok(())
}
......
......@@ -4,33 +4,22 @@
// FIXME: remove when module made public again
#![allow(dead_code)]
use crate::polynomial::Polynomial;
use crate::polynomial::PolynomialCoefficient;
use crate::traits::GCD;
use num_bigint::BigUint;
use num_bigint::{BigInt, Sign};
use num_rational::BigRational;
use num_rational::Ratio;
use num_traits::cast::ToPrimitive;
use num_traits::CheckedAdd;
use num_traits::CheckedDiv;
use num_traits::CheckedMul;
use num_traits::CheckedRem;
use num_traits::CheckedSub;
use num_traits::Num;
use num_traits::One;
use num_traits::Signed;
use num_traits::Zero;
use std::cmp::Ordering;
use std::error::Error;
use std::fmt;
use std::mem;
use std::ops::Add;
use std::ops::Div;
use std::ops::Mul;
use std::ops::Neg;
use std::ops::Rem;
use std::ops::Sub;
use crate::{
polynomial::{Polynomial, PolynomialCoefficient},
traits::GCD,
};
use num_bigint::{BigInt, BigUint, Sign};
use num_rational::{BigRational, Ratio};
use num_traits::{
cast::ToPrimitive, CheckedAdd, CheckedDiv, CheckedMul, CheckedRem, CheckedSub, Num, One,
Signed, Zero,
};
use std::{
cmp::Ordering,
error::Error,
fmt, mem,
ops::{Add, Div, Mul, Neg, Rem, Sub},
};
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Default)]
pub(crate) struct QuadraticPolynomial<T> {
......
// SPDX-License-Identifier: LGPL-2.1-or-later
// See Notices.txt for copyright information
use crate::polynomial::Polynomial;
use crate::polynomial::PolynomialCoefficient;
use crate::polynomial::{Polynomial, PolynomialCoefficient};
use num_bigint::{BigInt, BigUint};
use num_integer::Integer;
use num_rational::Ratio;
use num_traits::CheckedRem;
use num_traits::NumAssign;
use num_traits::One;
use num_traits::{CheckedDiv, CheckedMul, Signed, ToPrimitive, Zero};
use std::fmt;
use std::ops::Add;
use std::ops::Div;
use std::ops::DivAssign;
use std::ops::Mul;
use num_traits::{CheckedDiv, CheckedMul, CheckedRem, NumAssign, One, Signed, ToPrimitive, Zero};
use std::{
fmt,
ops::{Add, Div, DivAssign, Mul},
};
/// GCD and LCM
///
......