Skip to content

Commit

Permalink
Add more operators between Integer and machine integers
Browse files Browse the repository at this point in the history
- Cargo clippy improvements
  • Loading branch information
benruijl committed Jul 16, 2024
1 parent 5ccee19 commit 9e06cdf
Show file tree
Hide file tree
Showing 30 changed files with 818 additions and 407 deletions.
2 changes: 1 addition & 1 deletion Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Symbolica allows you to build and manipulate mathematical expressions, for examp
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://symbolica.io/resources/demo.dark.svg">
<source media="(prefers-color-scheme: light)" srcset="https://symbolica.io/resources/demo.light.svg">
<img width="600" alt="A demo of Symbolica" srcset="https://symbolica.io/resources/demo.dark.svg">
<img width="600" alt="A demo of Symbolica" src="https://symbolica.io/resources/demo.light.svg">
</picture>

You are able to perform these operations from the comfort of a programming language that you (probably) already know, by using Symbolica's bindings to Python and Rust:
Expand Down
6 changes: 2 additions & 4 deletions src/api/python.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1192,7 +1192,7 @@ impl<'a> FromPyObject<'a> for ConvertibleToExpression {
Ok(ConvertibleToExpression(Atom::new_num(num).into()))
} else if let Ok(num) = ob.extract::<&PyLong>() {
let a = format!("{}", num);
let i = Integer::from_large(rug::Integer::parse(&a).unwrap().complete());
let i = Integer::from(rug::Integer::parse(&a).unwrap().complete());
Ok(ConvertibleToExpression(Atom::new_num(i).into()))
} else if let Ok(_) = ob.extract::<&str>() {
// disallow direct string conversion
Expand Down Expand Up @@ -1237,9 +1237,7 @@ impl<'a> FromPyObject<'a> for Integer {
Ok(num.into())
} else if let Ok(num) = ob.extract::<&PyLong>() {
let a = format!("{}", num);
Ok(Integer::from_large(
rug::Integer::parse(&a).unwrap().complete(),
))
Ok(Integer::from(rug::Integer::parse(&a).unwrap().complete()))
} else {
Err(exceptions::PyValueError::new_err("Not a valid integer"))
}
Expand Down
2 changes: 1 addition & 1 deletion src/atom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ impl Atom {
pub fn new_num<T: Into<Coefficient>>(num: T) -> Atom {
let c = num.into();
if c.is_zero() {
return Atom::Zero;
Atom::Zero
} else {
Num::new(c).into()
}
Expand Down
4 changes: 2 additions & 2 deletions src/atom/coefficient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,9 @@ impl<'a> SerializedRationalPolynomial<'a> {
);
source.advance(num_digits as usize);
if x == 5 {
Integer::from_large(-i)
Integer::from(-i)
} else {
Integer::from_large(i)
Integer::from(i)
}
}
_ => unreachable!(),
Expand Down
6 changes: 3 additions & 3 deletions src/atom/representation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,7 @@ impl Mul {
}
_ => {
n_args += 1;
&other.get_data()
other.get_data()
}
};

Expand Down Expand Up @@ -820,11 +820,11 @@ impl Add {
(sub_n_args, _, sd) = sd.get_frac_u64();

n_args += sub_n_args;
self.data.extend_from_slice(&sd);
self.data.extend_from_slice(sd);
}
_ => {
n_args += 1;
self.data.extend_from_slice(&other.get_data());
self.data.extend_from_slice(other.get_data());
}
};

Expand Down
10 changes: 5 additions & 5 deletions src/coefficient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ impl ConvertToRing for IntegerRing {
CoefficientView::Large(r) => {
let r = r.to_rat();
debug_assert!(r.denom() == &1);
Integer::from_large(r.numer().clone())
Integer::from(r.numer().clone())
}
CoefficientView::Float(_) => {
panic!("Cannot convert float to integer")
Expand Down Expand Up @@ -465,7 +465,7 @@ impl CoefficientView<'_> {
match self {
CoefficientView::Natural(num, den) => Coefficient::Rational((*num, *den).into()),
CoefficientView::Large(r) => Coefficient::Rational(r.to_rat().into()),
CoefficientView::Float(f) => Coefficient::Float(f.to_float().into()),
CoefficientView::Float(f) => Coefficient::Float(f.to_float()),
CoefficientView::FiniteField(num, field) => Coefficient::FiniteField(*num, *field),
CoefficientView::RationalPolynomial(p) => {
Coefficient::RationalPolynomial(p.deserialize())
Expand Down Expand Up @@ -685,8 +685,8 @@ impl Add<CoefficientView<'_>> for CoefficientView<'_> {
let r = p.deserialize();
let (n, d) = l.to_rat().into_numer_denom();
let r2 = RationalPolynomial {
numerator: r.numerator.constant(Integer::from_large(n)),
denominator: r.denominator.constant(Integer::from_large(d)),
numerator: r.numerator.constant(Integer::from(n)),
denominator: r.denominator.constant(Integer::from(d)),
};
Coefficient::RationalPolynomial(&r + &r2)
}
Expand Down Expand Up @@ -778,7 +778,7 @@ impl Mul for CoefficientView<'_> {
| (CoefficientView::RationalPolynomial(p), CoefficientView::Large(l)) => {
let mut r = p.deserialize();
let (n, d) = l.to_rat().into_numer_denom();
let (n, d) = (Integer::from_large(n), Integer::from_large(d));
let (n, d) = (Integer::from(n), Integer::from(d));

let gcd1 = Z.gcd(&n, &r.denominator.content());
let gcd2 = Z.gcd(&d, &r.numerator.content());
Expand Down
15 changes: 8 additions & 7 deletions src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,20 +203,20 @@ impl<'a> AtomView<'a> {
) -> (Vec<(Atom, Atom)>, Atom) {
let mut h = HashMap::default();
let mut rest = workspace.new_atom();
let mut rest_add = rest.to_add();
let rest_add = rest.to_add();

let mut expanded = workspace.new_atom();
self.expand_with_ws_into(workspace, Some(x), &mut expanded);

match expanded.as_view() {
AtomView::Add(a) => {
for arg in a {
arg.collect_factor_list(x, workspace, &mut h, &mut rest_add)
arg.collect_factor_list(x, workspace, &mut h, rest_add)
}
}
_ => expanded
.as_view()
.collect_factor_list(x, workspace, &mut h, &mut rest_add),
.collect_factor_list(x, workspace, &mut h, rest_add),
}

let mut rest_norm = Atom::new();
Expand Down Expand Up @@ -331,15 +331,15 @@ impl<'a> AtomView<'a> {
/// Collect terms involving the literal occurrence of `x`.
pub fn coefficient_with_ws(&self, x: AtomView<'_>, workspace: &Workspace) -> Atom {
let mut coeffs = workspace.new_atom();
let mut coeff_add = coeffs.to_add();
let coeff_add = coeffs.to_add();

match self {
AtomView::Add(a) => {
for arg in a {
arg.collect_factor(x, workspace, &mut coeff_add)
arg.collect_factor(x, workspace, coeff_add)
}
}
_ => self.collect_factor(x, workspace, &mut coeff_add),
_ => self.collect_factor(x, workspace, coeff_add),
}

let mut rest_norm = Atom::new();
Expand Down Expand Up @@ -481,7 +481,8 @@ impl<'a> AtomView<'a> {
if let CoefficientView::Natural(n, d) = n.get_coeff_view() {
if n < 0 && d == 1 {
denominators.push(
b.to_polynomial::<_, u16>(&Q, None).pow(n.abs() as usize),
b.to_polynomial::<_, u16>(&Q, None)
.pow(n.unsigned_abs() as usize),
);
den_changed.push((a, false));
continue;
Expand Down
54 changes: 23 additions & 31 deletions src/derivative.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,16 +362,16 @@ impl<'a> AtomView<'a> {
depth.clone()
};

Workspace::get_local().with(|ws| loop {
loop {
let info = Series::new(
&AtomField::new(),
None,
Arc::new(Variable::Symbol(x)),
expansion_point.to_owned(),
&current_depth + &((1.into(), current_depth.denominator())).into(),
&current_depth + &(1.into(), current_depth.denominator()).into(),
);

let mut series = self.series_with_ws(x, expansion_point, ws, &info)?;
let mut series = self.series_impl(x, expansion_point, &info)?;
if !depth_is_absolute && series.relative_order() >= depth {
series.truncate_relative_order(depth);
break Ok(series);
Expand All @@ -383,19 +383,18 @@ impl<'a> AtomView<'a> {
// TODO: find better heuristic
current_depth = &current_depth * &2.into();
}
})
}
}

/// Series expand in `x` around `expansion_point` to depth `depth`.
pub fn series_with_ws(
pub(crate) fn series_impl(
&self,
x: Symbol,
expansion_point: AtomView,
workspace: &Workspace,
info: &Series<AtomField>,
) -> Result<Series<AtomField>, &'static str> {
if !self.contains_symbol(x) {
return Ok(info.constant(self.to_owned().into()));
return Ok(info.constant(self.to_owned()));
}

// TODO: optimize, appending a monomial using addition is slow
Expand All @@ -411,7 +410,7 @@ impl<'a> AtomView<'a> {
AtomView::Fun(f) => {
let mut args_series = Vec::with_capacity(f.get_nargs());
for arg in f {
args_series.push(arg.series_with_ws(x, expansion_point, workspace, info)?);
args_series.push(arg.series_impl(x, expansion_point, info)?);
}

if args_series.is_empty() {
Expand Down Expand Up @@ -488,40 +487,33 @@ impl<'a> AtomView<'a> {
AtomView::Pow(p) => {
let (base, exp) = p.get_base_exp();

let base_series = base.series_with_ws(x, expansion_point, workspace, info)?;
let base_series = base.series_impl(x, expansion_point, info)?;

if let AtomView::Num(n) = exp {
if let CoefficientView::Natural(n, d) = n.get_coeff_view() {
let r = base_series.rpow((n, d).into());
r
base_series.rpow((n, d).into())
} else {
unimplemented!("Cannot series expand with large exponents yet")
}
} else {
let e = exp.series_with_ws(x, expansion_point, workspace, info)?;
let e = exp.series_impl(x, expansion_point, info)?;
base_series.pow(&e)
}
}
AtomView::Mul(args) => {
let mut iter = args.iter();
let mut series =
iter.next()
.unwrap()
.series_with_ws(x, expansion_point, workspace, info)?;
let mut series = iter.next().unwrap().series_impl(x, expansion_point, info)?;
for arg in iter {
series = &series * &arg.series_with_ws(x, expansion_point, workspace, info)?;
series = &series * &arg.series_impl(x, expansion_point, info)?;
}

Ok(series)
}
AtomView::Add(args) => {
let mut iter = args.iter();
let mut series =
iter.next()
.unwrap()
.series_with_ws(x, expansion_point, workspace, info)?;
let mut series = iter.next().unwrap().series_impl(x, expansion_point, info)?;
for arg in iter {
series = &series + &arg.series_with_ws(x, expansion_point, workspace, info)?;
series = &series + &arg.series_impl(x, expansion_point, info)?;
}

Ok(series)
Expand Down Expand Up @@ -569,7 +561,7 @@ impl Mul<&Atom> for &Series<AtomField> {
current_depth = (2, 1).into();
}

Workspace::get_local().with(|ws| loop {
loop {
let info = Series::new(
&AtomField::new(),
None,
Expand All @@ -580,15 +572,15 @@ impl Mul<&Atom> for &Series<AtomField> {

let series = rhs
.as_view()
.series_with_ws(x, expansion_point.as_view(), ws, &info)?
.series_impl(x, expansion_point.as_view(), &info)?
* self;
if series.relative_order() >= self.relative_order() {
return Ok(series);
} else {
// increase the expansion depth
current_depth = &current_depth * &2.into();
}
})
}
}
}

Expand Down Expand Up @@ -631,7 +623,7 @@ impl Add<&Atom> for &Series<AtomField> {
current_depth = (2, 1).into();
}

Workspace::get_local().with(|ws| loop {
loop {
let info = Series::new(
&AtomField::new(),
None,
Expand All @@ -642,15 +634,15 @@ impl Add<&Atom> for &Series<AtomField> {

let series = rhs
.as_view()
.series_with_ws(x, expansion_point.as_view(), ws, &info)?
.series_impl(x, expansion_point.as_view(), &info)?
+ self.clone();
if series.absolute_order() >= self.absolute_order() {
return Ok(series);
} else {
// increase the expansion depth
current_depth = &current_depth * &2.into();
}
})
}
}
}

Expand Down Expand Up @@ -693,7 +685,7 @@ impl Div<&Atom> for &Series<AtomField> {
current_depth = (2, 1).into();
}

Workspace::get_local().with(|ws| loop {
loop {
let info = Series::new(
&AtomField::new(),
None,
Expand All @@ -705,14 +697,14 @@ impl Div<&Atom> for &Series<AtomField> {
let series = self
/ &rhs
.as_view()
.series_with_ws(x, expansion_point.as_view(), ws, &info)?;
.series_impl(x, expansion_point.as_view(), &info)?;
if series.relative_order() >= self.relative_order() {
return Ok(series);
} else {
// increase the expansion depth
current_depth = &current_depth * &2.into();
}
})
}
}
}

Expand Down
16 changes: 8 additions & 8 deletions src/domains/algebraic_number.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ where
fn to_integer(&self, a: &Self::Element) -> Integer {
let mut p = Integer::zero();
for x in a.poly.into_iter() {
p = p + &(self.poly.field.to_integer(x.coefficient)
p += &(self.poly.field.to_integer(x.coefficient)
* &self.characteristic().pow(x.exponents[0] as u64));
}
p
Expand Down Expand Up @@ -186,30 +186,30 @@ where
poly.is_irreducible()
}

let mut coeffs = vec![0; exp as usize + 1];
coeffs[exp as usize] = 1;
let mut coeffs = vec![0; exp + 1];
coeffs[exp] = 1;
let mut poly = MultivariatePolynomial::new(&prime, Some(coeffs.len()), Arc::new(vec![var]));

// find the minimal polynomial
let p = prime.get_prime().to_integer();
if p == 2.into() {
if p == 2 {
coeffs[0] = 1;

// try all odd number of non-zero coefficients
for g in 0..exp / 2 {
let g = 2 * g + 1;

let mut c = CombinationIterator::new(exp as usize - 1, g as usize);
let mut c = CombinationIterator::new(exp - 1, g);
while let Some(comb) = c.next() {
for i in 0..g as usize {
for i in 0..g {
coeffs[comb[i] + 1] = 1;
}

if is_irreducible(&coeffs, &mut poly) {
return AlgebraicExtension::new(poly);
}

for i in 0..g as usize {
for i in 0..g {
coeffs[comb[i] + 1] = 0;
}
}
Expand Down Expand Up @@ -249,7 +249,7 @@ where
for c in coeffs.iter_mut() {
*c = r.gen_range(0..sample_max);
}
coeffs[exp as usize] = 1;
coeffs[exp] = 1;

if is_irreducible(&coeffs, &mut poly) {
return AlgebraicExtension::new(poly);
Expand Down
Loading

0 comments on commit 9e06cdf

Please sign in to comment.