use num_traits::One;
use crate::anon_series_slice::AnonSeriesSlice;
use crate::ops::{Exp, Ln, Pow};
use crate::poly::{NonConstPoly, fmt_term};
use crate::{Coeff, IntoIter, Iter};
use crate::{Polynomial, PolynomialSlice, traits::*};
use crate::{anon_series::AnonSeries, series_slice::*};
use std::convert::From;
use std::fmt::{self, Debug, Display};
use std::ops::{
Add, AddAssign, Div, DivAssign, Index, Mul, MulAssign, Neg, Range,
RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive, Sub,
SubAssign,
};
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(PartialEq, Eq, Debug, Clone, Hash, Ord, PartialOrd)]
pub struct Series<Var, C: Coeff> {
pub(crate) series: AnonSeries<C>,
pub(crate) var: Var,
}
impl<Var, C: Coeff> Series<Var, C> {
pub fn new(var: Var, min_pow: isize, coeffs: Vec<C>) -> Series<Var, C> {
let series = AnonSeries::new(min_pow, coeffs);
Series { series, var }
}
pub fn with_cutoff(
var: Var,
powers: Range<isize>,
coeffs: Vec<C>,
) -> Series<Var, C> {
let series = AnonSeries::with_cutoff(powers, coeffs);
Series { series, var }
}
pub fn var(&self) -> &Var {
&self.var
}
pub fn replace_var<W>(self, new_var: W) -> (Series<W, C>, Var) {
let Self { series, var: old_var } = self;
(Series{ series, var: new_var }, old_var)
}
pub fn min_pow(&self) -> isize {
self.series.min_pow()
}
pub fn cutoff_pow(&self) -> isize {
self.series.cutoff_pow()
}
pub fn shift_pow(&mut self, n: isize) {
self.series.min_pow += n;
}
pub fn truncate_at(&mut self, n: isize) {
self.series.truncate_at(n)
}
pub fn len(&self) -> usize {
self.series.len()
}
pub fn iter(&self) -> Iter<'_, C> {
self.series.iter()
}
pub fn try_coeff(&self, pow: isize) -> Option<&C> {
self.series.try_coeff(pow)
}
pub fn apply_at<F: FnOnce(&mut C)>(&mut self, pow: isize, f: F) {
self.series.apply_at(pow, f)
}
pub fn for_each<F>(&mut self, f: F)
where
F: FnMut(isize, &mut C),
{
self.series.for_each(f)
}
pub fn map<F, D: Coeff>(self, f: F) -> Series<Var, D>
where
F: FnMut(isize, C) -> D,
{
let Self { series, var } = self;
let series = series.map(f);
Series { series, var }
}
}
impl<Var, C: 'static + Coeff + Send + Sync> Series<Var, C> {
pub fn coeff(&self, pow: isize) -> Option<&C> {
self.series.coeff(pow)
}
}
impl<'a, Var, C: Coeff> AsSlice<Range<isize>> for &'a Series<Var, C> {
type Output = SeriesSlice<'a, Var, C>;
fn as_slice(self, r: Range<isize>) -> Self::Output {
self.series.as_slice(r).in_var(self.var())
}
}
impl<'a, Var, C: Coeff> AsSlice<RangeInclusive<isize>> for &'a Series<Var, C> {
type Output = SeriesSlice<'a, Var, C>;
fn as_slice(self, r: RangeInclusive<isize>) -> Self::Output {
self.series.as_slice(r).in_var(self.var())
}
}
impl<'a, Var, C: Coeff> AsSlice<RangeToInclusive<isize>>
for &'a Series<Var, C>
{
type Output = SeriesSlice<'a, Var, C>;
fn as_slice(self, r: RangeToInclusive<isize>) -> Self::Output {
self.series.as_slice(r).in_var(self.var())
}
}
impl<'a, Var, C: Coeff> AsSlice<RangeFrom<isize>> for &'a Series<Var, C> {
type Output = SeriesSlice<'a, Var, C>;
fn as_slice(self, r: RangeFrom<isize>) -> Self::Output {
self.series.as_slice(r).in_var(self.var())
}
}
impl<'a, Var, C: Coeff> AsSlice<RangeTo<isize>> for &'a Series<Var, C> {
type Output = SeriesSlice<'a, Var, C>;
fn as_slice(self, r: RangeTo<isize>) -> Self::Output {
self.series.as_slice(r).in_var(self.var())
}
}
impl<'a, Var, C: Coeff> AsSlice<RangeFull> for &'a Series<Var, C> {
type Output = SeriesSlice<'a, Var, C>;
fn as_slice(self, r: RangeFull) -> Self::Output {
self.series.as_slice(r).in_var(self.var())
}
}
impl<Var, C: Coeff> Index<isize> for Series<Var, C> {
type Output = C;
fn index(&self, index: isize) -> &Self::Output {
&self.series[index]
}
}
impl<Var, C: Coeff> std::iter::IntoIterator for Series<Var, C> {
type Item = (isize, C);
type IntoIter = crate::IntoIter<C>;
fn into_iter(self) -> IntoIter<C> {
self.series.into_iter()
}
}
impl<Var: Clone, C: Coeff + SubAssign> MulInverse for &Series<Var, C>
where
Var: Clone,
C: Coeff + SubAssign,
for<'c> &'c C: Div<Output = C> + Mul<Output = C>,
{
type Output = Series<Var, C>;
fn mul_inverse(self) -> Self::Output {
(&self.series).mul_inverse().in_var(self.var.clone())
}
}
impl<Var: Clone, C: Coeff + SubAssign> MulInverse for Series<Var, C>
where
for<'a> &'a Series<Var, C>: MulInverse<Output = Series<Var, C>>,
{
type Output = Series<Var, C>;
fn mul_inverse(self) -> Self::Output {
(&self).mul_inverse()
}
}
impl<Var, C: Coeff + Neg<Output = C>> Neg for Series<Var, C> {
type Output = Series<Var, C>;
fn neg(self) -> Self::Output {
let Self { series, var } = self;
let series = -series;
Self { series, var }
}
}
impl<'a, Var: Clone, C: Coeff> Neg for &'a Series<Var, C>
where
&'a C: Neg<Output = C>,
{
type Output = Series<Var, C>;
fn neg(self) -> Self::Output {
self.as_slice(..).neg()
}
}
impl<'a, Var: PartialEq + fmt::Debug, C: Coeff + Clone>
AddAssign<&'a Series<Var, C>> for Series<Var, C>
where
for<'c> C: AddAssign<&'c C>,
{
fn add_assign(&mut self, other: &'a Series<Var, C>) {
assert_eq!(self.var(), other.var());
self.series.add_assign(&other.series)
}
}
impl<'a, Var: PartialEq + fmt::Debug, C: Coeff + Clone>
AddAssign<SeriesSlice<'a, Var, C>> for Series<Var, C>
where
for<'c> C: AddAssign<&'c C>,
{
fn add_assign(&mut self, other: SeriesSlice<'a, Var, C>) {
assert_eq!(self.var(), other.var());
self.series.add_assign(other.series)
}
}
impl<Var, C: AddAssign + Coeff> AddAssign for Series<Var, C>
where
Var: PartialEq + fmt::Debug,
{
fn add_assign(&mut self, other: Series<Var, C>) {
assert_eq!(self.var(), other.var());
self.series.add_assign(other.series)
}
}
impl<Var: Clone, C: Coeff + Clone, Rhs> Add<Rhs> for &Series<Var, C>
where
Series<Var, C>: AddAssign<Rhs>,
{
type Output = Series<Var, C>;
fn add(self, other: Rhs) -> Self::Output {
let mut res = self.clone();
res += other;
res
}
}
impl<Var, C: Coeff + Clone, Rhs> Add<Rhs> for Series<Var, C>
where
Series<Var, C>: AddAssign<Rhs>,
{
type Output = Series<Var, C>;
fn add(mut self, other: Rhs) -> Self::Output {
self += other;
self
}
}
impl<'a, Var, C: Coeff> SubAssign<&'a Series<Var, C>> for Series<Var, C>
where
for<'c> &'c Series<Var, C>: Neg<Output = Series<Var, C>>,
Series<Var, C>: AddAssign<Series<Var, C>>,
{
fn sub_assign(&mut self, other: &'a Series<Var, C>) {
*self += -other;
}
}
impl<'a, Var, C: Coeff> SubAssign<SeriesSlice<'a, Var, C>> for Series<Var, C>
where
for<'c> SeriesSlice<'c, Var, C>: Neg<Output = Series<Var, C>>,
Series<Var, C>: AddAssign<Series<Var, C>>,
{
fn sub_assign(&mut self, other: SeriesSlice<'a, Var, C>) {
*self += -other;
}
}
impl<Var, C: Coeff> SubAssign<Series<Var, C>> for Series<Var, C>
where
Series<Var, C>: AddAssign + Neg<Output = Series<Var, C>>,
{
fn sub_assign(&mut self, other: Series<Var, C>) {
*self += -other;
}
}
impl<Var, C: Coeff, T> Sub<T> for &Series<Var, C>
where
Series<Var, C>: Clone + SubAssign<T>,
{
type Output = Series<Var, C>;
fn sub(self, other: T) -> Self::Output {
let mut res = self.clone();
res -= other;
res
}
}
impl<Var, C: Coeff, T> Sub<T> for Series<Var, C>
where
Series<Var, C>: SubAssign<T>,
{
type Output = Series<Var, C>;
fn sub(mut self, other: T) -> Self::Output {
self -= other;
self
}
}
impl<C: Coeff, Var> MulAssign for Series<Var, C>
where
Var: Debug + PartialEq,
AnonSeries<C>: MulAssign,
{
fn mul_assign(&mut self, other: Series<Var, C>) {
assert_eq!(self.var, other.var);
self.series.mul_assign(other.series)
}
}
impl<C: Coeff, Var> MulAssign<&Series<Var, C>> for Series<Var, C>
where
Var: Debug + PartialEq,
for<'c> AnonSeries<C>: MulAssign<&'c AnonSeries<C>>,
{
fn mul_assign(&mut self, other: &Series<Var, C>) {
assert_eq!(self.var, other.var);
self.series.mul_assign(&other.series)
}
}
impl<'a, C: Coeff, Var> MulAssign<SeriesSlice<'a, Var, C>> for Series<Var, C>
where
Var: Debug + PartialEq,
AnonSeries<C>: MulAssign<AnonSeriesSlice<'a, C>>,
{
fn mul_assign(&mut self, other: SeriesSlice<'a, Var, C>) {
assert_eq!(&self.var, other.var);
self.series.mul_assign(other.series)
}
}
impl<Var, C: Coeff> MulAssign<Polynomial<Var, C>> for Series<Var, C>
where
Self: MulAssign<C> + MulAssign<NonConstPoly<Var, C>>,
{
fn mul_assign(&mut self, rhs: Polynomial<Var, C>) {
match rhs {
Polynomial::Const(c) => self.mul_assign(c),
Polynomial::Poly(p) => self.mul_assign(p),
}
}
}
impl<'a, Var, C: Coeff> MulAssign<&'a Polynomial<Var, C>> for Series<Var, C>
where
Self: MulAssign<PolynomialSlice<'a, Var, C>>,
{
fn mul_assign(&mut self, rhs: &'a Polynomial<Var, C>) {
self.mul_assign(rhs.as_slice(..));
}
}
impl<'a, Var, C: Coeff> MulAssign<PolynomialSlice<'a, Var, C>>
for Series<Var, C>
where
Self: MulAssign<&'a C>,
Var: Debug + PartialEq,
C: MulAssign<&'a C> + AddAssign,
for<'c> &'c C: Mul<Output = C>,
{
fn mul_assign(&mut self, rhs: PolynomialSlice<'a, Var, C>) {
match rhs {
PolynomialSlice::Const(c) => self.mul_assign(c),
PolynomialSlice::Poly {
min_pow,
coeffs,
var,
} => {
assert_eq!(self.var(), var);
self.series.min_pow += min_pow;
let Some((b_0, b)) = coeffs.split_first() else {
panic!("Cannot multiply series by 0")
};
self.series.mul_by_slice(b_0, b)
}
}
}
}
impl<Var: Debug + PartialEq, C: Coeff> MulAssign<NonConstPoly<Var, C>>
for Series<Var, C>
where
for<'c> &'c C: Mul<Output = C>,
for<'c> C: MulAssign<&'c C>,
C: AddAssign,
{
fn mul_assign(&mut self, rhs: NonConstPoly<Var, C>) {
self.mul_assign(&rhs);
}
}
impl<'a, Var: Debug + PartialEq, C: Coeff> MulAssign<&'a NonConstPoly<Var, C>>
for Series<Var, C>
where
for<'c> &'c C: Mul<Output = C>,
C: MulAssign<&'a C> + AddAssign,
{
fn mul_assign(&mut self, rhs: &'a NonConstPoly<Var, C>) {
assert_eq!(self.var(), rhs.var());
let (b0, b) = rhs.coeffs().split_first().unwrap();
self.series.min_pow += rhs.min_pow();
self.series.mul_by_slice(b0, b);
}
}
macro_rules! impl_mul_via_mul_assign {
($($t:ty), *) => {
$(
impl<'a, Var, C: Coeff> Mul<$t> for Series<Var, C>
where
Series<Var, C>: MulAssign<$t>,
{
type Output = Series<Var, C>;
fn mul(mut self, other: $t) -> Self::Output {
self.mul_assign(other);
self
}
}
)*
};
}
impl_mul_via_mul_assign!(
Series<Var, C>, &'a Series<Var, C>, SeriesSlice<'a, Var, C>,
Polynomial<Var, C>, &'a Polynomial<Var, C>, PolynomialSlice<'a, Var, C>,
NonConstPoly<Var, C>, &'a NonConstPoly<Var, C>,
C, &'a C
);
impl<'a, Var, C: Coeff, T> Mul<T> for &'a Series<Var, C>
where
SeriesSlice<'a, Var, C>: Mul<T>,
{
type Output = <SeriesSlice<'a, Var, C> as Mul<T>>::Output;
fn mul(self, other: T) -> Self::Output {
self.as_slice(..).mul(other)
}
}
impl<'a, Var: Clone, C: Coeff + SubAssign> DivAssign<&'a Series<Var, C>>
for Series<Var, C>
where
Series<Var, C>: MulAssign,
for<'b> &'b C: Div<Output = C> + Mul<Output = C>,
for<'c> &'c Series<Var, C>: MulInverse<Output = Series<Var, C>>,
{
fn div_assign(&mut self, other: &'a Series<Var, C>) {
self.div_assign(other.as_slice(..));
}
}
impl<Var: Clone, C: Coeff + SubAssign> DivAssign for Series<Var, C>
where
Series<Var, C>: MulAssign + MulInverse<Output = Series<Var, C>>,
for<'a> &'a C: Div<Output = C> + Mul<Output = C>,
{
fn div_assign(&mut self, other: Series<Var, C>) {
*self *= other.mul_inverse();
}
}
impl<'a, Var: Clone, C: Coeff + SubAssign> DivAssign<SeriesSlice<'a, Var, C>>
for Series<Var, C>
where
Series<Var, C>: MulAssign,
for<'b> &'b C: Div<Output = C> + Mul<Output = C>,
for<'c> &'c Series<Var, C>: MulInverse<Output = Series<Var, C>>,
{
fn div_assign(&mut self, other: SeriesSlice<'a, Var, C>) {
*self *= other.mul_inverse();
}
}
impl<Var, C: Coeff> DivAssign<Polynomial<Var, C>> for Series<Var, C>
where
Self: DivAssign + DivAssign<C>,
{
fn div_assign(&mut self, rhs: Polynomial<Var, C>) {
match rhs {
Polynomial::Const(c) => self.div_assign(c),
Polynomial::Poly(p) => {
let cutoff_pow = self.len() as isize + p.min_pow();
self.div_assign(p.cutoff_at(cutoff_pow))
}
}
}
}
impl<'a, Var, C: Coeff> DivAssign<&'a Polynomial<Var, C>> for Series<Var, C>
where
Self: DivAssign<PolynomialSlice<'a, Var, C>>,
{
fn div_assign(&mut self, rhs: &'a Polynomial<Var, C>) {
self.div_assign(rhs.as_slice(..));
}
}
impl<'a, Var, C: Coeff> DivAssign<PolynomialSlice<'a, Var, C>>
for Series<Var, C>
where
Self: DivAssign + DivAssign<&'a C>,
Polynomial<Var, C>: From<PolynomialSlice<'a, Var, C>>,
Var: Clone + Debug + PartialEq,
{
fn div_assign(&mut self, rhs: PolynomialSlice<'a, Var, C>) {
match rhs {
PolynomialSlice::Const(c) => self.div_assign(c),
PolynomialSlice::Poly {
min_pow,
coeffs: _,
var,
} => {
let cutoff_pow = self.len() as isize + min_pow;
let p = Polynomial::from(rhs);
self.div_assign(p.cutoff_at(var, cutoff_pow))
}
}
}
}
macro_rules! impl_div_via_div_assign {
($($t:ty), *) => {
$(
impl<'a, Var, C: Coeff> Div<$t> for Series<Var, C>
where
Series<Var, C>: DivAssign<$t>,
{
type Output = Series<Var, C>;
fn div(mut self, other: $t) -> Self::Output {
self.div_assign(other);
self
}
}
)*
};
}
impl_div_via_div_assign!(
Series<Var, C>, &'a Series<Var, C>, SeriesSlice<'a, Var, C>,
Polynomial<Var, C>, &'a Polynomial<Var, C>, PolynomialSlice<'a, Var, C>,
C, &'a C
);
impl<Var, C: Coeff, T> Div<T> for &Series<Var, C>
where
Series<Var, C>: Clone + DivAssign<T>,
{
type Output = Series<Var, C>;
fn div(self, other: T) -> Self::Output {
let mut res = self.clone();
res /= other;
res
}
}
impl<Var, C: Coeff> Exp for Series<Var, C>
where
for<'a> &'a C: Mul<Output = C>,
for<'a> C: MulAssign<&'a C>,
C: Clone
+ Div<Output = C>
+ Mul<Output = C>
+ AddAssign
+ Exp<Output = C>
+ From<i32>,
{
type Output = Self;
fn exp(self) -> Self::Output {
let coeff = self.exp_coeff();
Series::new(self.var, 0, coeff)
}
}
impl<Var, C: Coeff> Exp for &Series<Var, C>
where
for<'b> &'b C: Mul<Output = C>,
for<'b> C: MulAssign<&'b C>,
Var: Clone,
C: Clone
+ Div<Output = C>
+ Mul<Output = C>
+ AddAssign
+ Exp<Output = C>
+ From<i32>,
{
type Output = Series<Var, C>;
fn exp(self) -> Self::Output {
self.as_slice(..).exp()
}
}
impl<Var, C: Coeff + From<i32>> Ln for Series<Var, C>
where
for<'a> C: DivAssign<&'a C>,
for<'a> &'a C: Mul<Output = C>,
C: Clone
+ SubAssign
+ Add<Output = C>
+ Mul<Output = C>
+ Div<Output = C>
+ Ln<Output = C>
+ From<Var>,
Var: Clone,
{
type Output = Self;
fn ln(mut self) -> Self {
assert!(!self.series.coeffs.is_empty());
let k0 = self.min_pow();
let c_k0 = self.series.coeffs[0].clone();
self.series.coeffs[0] = C::one();
for i in 1..self.series.coeffs.len() {
self.series.coeffs[i] /= &c_k0;
}
let a = self.series.coeffs;
let mut b = Vec::with_capacity(a.len());
let b_0 = if k0 != 0 {
let var = self.var.clone();
c_k0.ln() + C::from(k0 as i32) * C::from(var).ln()
} else {
c_k0.ln()
};
b.push(b_0);
for n in 1..a.len() {
b.push(a[n].clone());
for i in 1..n {
let num_factor = C::from(i as i32) / C::from(n as i32);
let tmp = num_factor * (&a[n - i] * &b[i]);
b[n] -= tmp;
}
}
Series::new(self.var, 0, b)
}
}
impl<Var, C: Coeff> Ln for &Series<Var, C>
where
for<'b> C: Div<&'b C, Output = C>,
for<'b> &'b C: Mul<Output = C> + Ln<Output = C>,
C: Clone
+ SubAssign
+ Add<Output = C>
+ Mul<Output = C>
+ Div<Output = C>
+ From<Var>
+ From<i32>,
Var: Clone,
{
type Output = Series<Var, C>;
fn ln(self) -> Self::Output {
self.as_slice(..).ln()
}
}
impl<Var, C: Coeff, T> Pow<T> for Series<Var, C>
where
Series<Var, C>: Ln,
<Series<Var, C> as Ln>::Output: Mul<T>,
<<Series<Var, C> as Ln>::Output as std::ops::Mul<T>>::Output: Exp,
{
type Output = <<<Series<Var, C> as Ln>::Output as std::ops::Mul<T>>::Output as Exp>::Output;
fn pow(self, exponent: T) -> Self::Output {
(self.ln() * exponent).exp()
}
}
impl<Var, C: Coeff, T> Pow<T> for &Series<Var, C>
where
for<'b> SeriesSlice<'b, Var, C>: Ln<Output = Series<Var, C>>,
Series<Var, C>: Mul<T>,
<Series<Var, C> as Mul<T>>::Output: Exp,
{
type Output = <<Series<Var, C> as Mul<T>>::Output as Exp>::Output;
fn pow(self, exponent: T) -> Self::Output {
self.as_slice(..).pow(exponent)
}
}
macro_rules! impl_add_assign_const {
($($rhs:ty), *) => {
$(
impl<'a, Var, C: Coeff> AddAssign<$rhs> for Series<Var, C>
where
C: AddAssign<$rhs>,
{
fn add_assign(&mut self, rhs: $rhs) {
self.series.add_assign(rhs)
}
}
)*
};
}
impl_add_assign_const!(C, &'a C);
macro_rules! impl_sub_assign_const {
($($rhs:ty), *) => {
$(
impl<'a, Var, C: Coeff> SubAssign<$rhs> for Series<Var, C>
where
C: SubAssign<$rhs>,
{
fn sub_assign(&mut self, rhs: $rhs) {
self.series.sub_assign(rhs)
}
}
)*
};
}
impl_sub_assign_const!(C, &'a C);
impl<'a, Var, C: Coeff> MulAssign<&'a C> for Series<Var, C>
where
C: MulAssign<&'a C>,
{
fn mul_assign(&mut self, rhs: &'a C) {
self.series.mul_assign(rhs)
}
}
impl<Var, C: Coeff> MulAssign<C> for Series<Var, C>
where
for<'a> AnonSeries<C>: MulAssign<C>,
{
fn mul_assign(&mut self, rhs: C) {
self.series.mul_assign(rhs)
}
}
impl<'a, Var, C: Coeff> DivAssign<&'a C> for Series<Var, C>
where
C: DivAssign<&'a C>,
{
fn div_assign(&mut self, rhs: &'a C) {
self.series.div_assign(rhs)
}
}
impl<Var, C: Coeff> DivAssign<C> for Series<Var, C>
where
for<'a> AnonSeries<C>: DivAssign<C>,
{
fn div_assign(&mut self, rhs: C) {
self.series.div_assign(rhs)
}
}
impl<Var, C: Coeff> AddAssign<Polynomial<Var, C>> for Series<Var, C>
where
Self: AddAssign,
Var: Clone + PartialEq + fmt::Debug,
{
fn add_assign(&mut self, other: Polynomial<Var, C>) {
self.add_assign(other.cutoff_at(self.var(), self.cutoff_pow()))
}
}
impl<Var, C: Coeff> AddAssign<&Polynomial<Var, C>> for Series<Var, C>
where
Polynomial<Var, C>: Clone,
Self: AddAssign<Polynomial<Var, C>>,
{
fn add_assign(&mut self, other: &Polynomial<Var, C>) {
self.add_assign(other.to_owned())
}
}
impl<'a, Var, C: Coeff> AddAssign<PolynomialSlice<'a, Var, C>>
for Series<Var, C>
where
Polynomial<Var, C>: From<PolynomialSlice<'a, Var, C>>,
Self: AddAssign<Polynomial<Var, C>>,
{
fn add_assign(&mut self, other: PolynomialSlice<'a, Var, C>) {
self.add_assign(Polynomial::from(other))
}
}
impl<Var, C: Coeff> SubAssign<Polynomial<Var, C>> for Series<Var, C>
where
Self: SubAssign,
Var: Clone + PartialEq + fmt::Debug,
{
fn sub_assign(&mut self, other: Polynomial<Var, C>) {
self.sub_assign(other.cutoff_at(self.var(), self.cutoff_pow()))
}
}
impl<Var, C: Coeff> SubAssign<&Polynomial<Var, C>> for Series<Var, C>
where
Polynomial<Var, C>: Clone,
Self: SubAssign<Polynomial<Var, C>>,
{
fn sub_assign(&mut self, other: &Polynomial<Var, C>) {
self.sub_assign(other.to_owned())
}
}
impl<'a, Var, C: Coeff> SubAssign<PolynomialSlice<'a, Var, C>>
for Series<Var, C>
where
Polynomial<Var, C>: From<PolynomialSlice<'a, Var, C>>,
Self: SubAssign<Polynomial<Var, C>>,
{
fn sub_assign(&mut self, other: PolynomialSlice<'a, Var, C>) {
self.sub_assign(Polynomial::from(other))
}
}
impl<'a, Var: Clone, C: Coeff + Clone> From<SeriesSlice<'a, Var, C>>
for Series<Var, C>
{
fn from(s: SeriesSlice<'a, Var, C>) -> Self {
Series::new(s.var.clone(), s.series.min_pow, s.series.coeffs.to_vec())
}
}
impl<Var, C: Coeff> NeedsCoeffBracket for Series<Var, C> {
fn needs_coeff_bracket(&self) -> bool {
self.len() > 0
}
}
impl<'a, Var: 'a, C: Coeff + 'a> SplitSign<'a> for Series<Var, C>
where
C: SplitSign<'a>,
{
type Signless = SignlessSeries<'a, Var, C>;
fn split_sign(&'a self) -> (Sign, Self::Signless) {
let sign = self
.series
.coeffs
.first()
.map(|c| c.split_sign().0)
.unwrap_or(Sign::Plus);
(sign, SignlessSeries(self))
}
}
#[derive(PartialEq)]
pub struct SignlessSeries<'a, Var, C: Coeff>(pub(crate) &'a Series<Var, C>);
impl<'a, Var, C: Coeff> Mul for SignlessSeries<'a, Var, C> {
type Output = Self;
fn mul(self, _: Self) -> Self::Output {
unimplemented!(
"`Mul` is only implemented to satisfy the trait bounds for `One`."
)
}
}
impl<'a, Var, C: Coeff + SplitSign<'a>> One for SignlessSeries<'a, Var, C> {
fn one() -> Self {
unimplemented!(
"`One` is only implemented to satisfy trait bounds. Only the `is_one` function should be used"
)
}
fn is_one(&self) -> bool {
false
}
}
impl<'a, C: Coeff, Var: Display> Display for SignlessSeries<'a, Var, C>
where
C: SplitSign<'a> + Display + NeedsCoeffBracket,
<C as SplitSign<'a>>::Signless: Display + One + PartialEq,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = self.0;
let var = s.var();
let terms = s.iter().filter(|(_, c)| !c.is_zero());
let mut first = true;
for (pow, c) in terms {
if pow != 0 && c.needs_coeff_bracket() {
if !first {
write!(f, " + ")?;
}
write!(f, "({c})*{var}")?;
if pow != 1 {
write!(f, "^{pow}")?;
}
} else {
let (sign, c) = c.split_sign();
if !first {
write!(f, " {sign} ")?;
}
fmt_term(&c, var, pow, f)?;
}
first = false;
}
if !first {
write!(f, " + ")?;
}
if s.cutoff_pow() == 1 {
write!(f, "O({var})")
} else {
write!(f, "O({var}^{})", s.cutoff_pow())
}
}
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(PartialEq, Eq, Debug, Clone, Hash, Ord, PartialOrd)]
pub struct SeriesParts<Var, C> {
pub var: Var,
pub min_pow: isize,
pub coeffs: Vec<C>,
}
impl<Var, C: Coeff> From<Series<Var, C>> for SeriesParts<Var, C> {
fn from(s: Series<Var, C>) -> Self {
let Series { series, var } = s;
SeriesParts {
var,
min_pow: series.min_pow,
coeffs: series.coeffs,
}
}
}
impl<Var, C: Coeff> From<SeriesParts<Var, C>> for Series<Var, C> {
fn from(parts: SeriesParts<Var, C>) -> Self {
Series::new(parts.var, parts.min_pow, parts.coeffs)
}
}
impl<Var, C: Coeff + From<i32>> LnVarFree for Series<Var, C>
where
for<'a> C: DivAssign<&'a C>,
for<'a> &'a C: Mul<Output = C>,
C: Clone + SubAssign + Ln<Output = C> + Div<Output = C> + Mul<Output = C>,
{
type Output = Self;
fn ln_var_free(self) -> Self {
let Self { series, var } = self;
let series = series.ln_var_free();
Self { series, var }
}
}
impl<Var, C: Coeff + From<i32>> Series<Var, C> {
pub fn powi(self, exp: i32) -> Self
where
for<'a> C: DivAssign<&'a C>,
for<'a> &'a C: Mul<Output = C>,
C: Clone
+ SubAssign
+ Ln<Output = C>
+ Div<Output = C>
+ Mul<Output = C>,
AnonSeries<C>: Mul<C, Output = AnonSeries<C>>
+ Exp<Output = AnonSeries<C>>
+ MulInverse<Output = AnonSeries<C>>,
{
let Self { series, var } = self;
let series = series.powi(exp);
Self { series, var }
}
}
impl<Var, C: Coeff + From<i32>> ExpCoeff for Series<Var, C>
where
for<'a> &'a C: Mul<Output = C>,
for<'a> C: MulAssign<&'a C>,
C: Clone + Div<Output = C> + Mul<Output = C> + AddAssign + Exp<Output = C>,
{
type Output = Vec<C>;
fn exp_coeff(&self) -> Vec<C> {
self.as_slice(..).exp_coeff()
}
}
impl<Var, C: Coeff + From<i32>> ExpCoeff for SeriesSlice<'_, Var, C>
where
for<'c> &'c C: Mul<Output = C>,
for<'c> C: MulAssign<&'c C>,
C: Clone + Div<Output = C> + Mul<Output = C> + AddAssign + Exp<Output = C>,
{
type Output = Vec<C>;
fn exp_coeff(&self) -> Vec<C> {
self.series.exp_coeff()
}
}
impl<Var, C: Coeff> Display for Series<Var, C>
where
for<'c> SeriesSlice<'c, Var, C>: Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.as_slice(..).fmt(f)
}
}
#[macro_export]
macro_rules! O {
($base:ident ^ $exp:expr) => {
Series::new($base, $exp, vec![])
};
($base:literal ^ $exp:expr) => {
Series::new($base, $exp, vec![])
};
}