use std::ops::{
Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Not, Rem, RemAssign, Sub, SubAssign,
};
use num::{One, Zero};
use crate::expression::{
Complex, Expression, Integer, Matrix, Rational, RationalRepresentation, Type, Vector,
};
impl Neg for Expression {
type Output = Self;
fn neg(self) -> Self {
Expression::Negation(Box::new(self))
}
}
impl Not for Expression {
type Output = Self;
fn not(self) -> Self {
Expression::Not(Box::new(self))
}
}
impl Add for Expression {
type Output = Self;
fn add(self, other: Self) -> Self {
Expression::Sum(Box::new(self), Box::new(other))
}
}
impl AddAssign for Expression {
fn add_assign(&mut self, other: Self) {
*self = self.clone() + other;
}
}
impl Sub for Expression {
type Output = Self;
fn sub(self, other: Self) -> Self {
Expression::Difference(Box::new(self), Box::new(other))
}
}
impl SubAssign for Expression {
fn sub_assign(&mut self, other: Self) {
*self = self.clone() - other;
}
}
impl Mul for Expression {
type Output = Self;
fn mul(self, other: Self) -> Self {
Expression::Product(Box::new(self), Box::new(other))
}
}
impl MulAssign for Expression {
fn mul_assign(&mut self, other: Self) {
*self = self.clone() * other;
}
}
impl Div for Expression {
type Output = Self;
fn div(self, other: Self) -> Self {
Expression::Quotient(Box::new(self), Box::new(other))
}
}
impl DivAssign for Expression {
fn div_assign(&mut self, other: Self) {
*self = self.clone() / other;
}
}
impl Rem for Expression {
type Output = Self;
fn rem(self, other: Self) -> Self {
Expression::Remainder(Box::new(self), Box::new(other))
}
}
impl RemAssign for Expression {
fn rem_assign(&mut self, other: Self) {
*self = self.clone() % other;
}
}
impl From<&Self> for Expression {
fn from(expression: &Self) -> Self {
expression.clone()
}
}
impl From<Integer> for Expression {
fn from(integer: Integer) -> Self {
Expression::Integer(integer)
}
}
impl TryFrom<Expression> for Integer {
type Error = Expression;
fn try_from(expression: Expression) -> Result<Self, Self::Error> {
if let Type::Number(z, _) = expression.typ() {
if z.im.is_zero() && z.re.denom().is_one() {
Ok(z.re.numer().clone())
} else {
Err(expression)
}
} else {
Err(expression)
}
}
}
impl From<Rational> for Expression {
fn from(rational: Rational) -> Self {
Expression::Rational(rational, RationalRepresentation::Fraction)
}
}
impl TryFrom<Expression> for Rational {
type Error = Expression;
fn try_from(expression: Expression) -> Result<Self, Self::Error> {
if let Type::Number(z, _) = expression.typ() {
if z.im.is_zero() {
Ok(z.re)
} else {
Err(expression)
}
} else {
Err(expression)
}
}
}
impl From<Complex> for Expression {
fn from(complex: Complex) -> Self {
Expression::Complex(complex, RationalRepresentation::Fraction)
}
}
impl TryFrom<Expression> for Complex {
type Error = Expression;
fn try_from(expression: Expression) -> Result<Self, Self::Error> {
if let Type::Number(z, _) = expression.typ() {
Ok(z)
} else {
Err(expression)
}
}
}
impl From<Vector> for Expression {
fn from(vector: Vector) -> Self {
Expression::Vector(vector)
}
}
impl TryFrom<Expression> for Vector {
type Error = Expression;
fn try_from(expression: Expression) -> Result<Self, Self::Error> {
if let Type::Matrix(m) = expression.typ() {
if m.ncols() == 1 {
Ok(m.column(0).clone_owned())
} else {
Err(expression)
}
} else {
Err(expression)
}
}
}
impl From<Matrix> for Expression {
fn from(matrix: Matrix) -> Self {
Expression::Matrix(matrix)
}
}
impl TryFrom<Expression> for Matrix {
type Error = Expression;
fn try_from(expression: Expression) -> Result<Self, Self::Error> {
if let Type::Matrix(m) = expression.typ() {
Ok(m)
} else {
Err(expression)
}
}
}
impl From<bool> for Expression {
fn from(boolean: bool) -> Self {
Expression::Boolean(boolean)
}
}
impl TryFrom<Expression> for bool {
type Error = Expression;
fn try_from(expression: Expression) -> Result<Self, Self::Error> {
if let Expression::Boolean(boolean) = expression {
Ok(boolean)
} else {
Err(expression)
}
}
}
pub fn var(identifier: impl Into<String>) -> Expression {
Expression::Variable(identifier.into())
}
pub fn fun(function: impl Into<Expression>, arguments: impl Into<Vec<Expression>>) -> Expression {
Expression::FunctionValue(Box::new(function.into()), arguments.into())
}
pub fn int(integer: impl Into<Integer>) -> Expression {
Expression::Integer(integer.into())
}
pub fn rat(numerator: impl Into<Integer>, denominator: impl Into<Integer>) -> Expression {
Expression::Rational(
Rational::new(numerator.into(), denominator.into()),
RationalRepresentation::Fraction,
)
}
pub fn ratd(numerator: impl Into<Integer>, denominator: impl Into<Integer>) -> Expression {
Expression::Rational(
Rational::new(numerator.into(), denominator.into()),
RationalRepresentation::Decimal,
)
}
pub fn com(
real_numerator: impl Into<Integer>,
real_denominator: impl Into<Integer>,
imaginary_numerator: impl Into<Integer>,
imaginary_denominator: impl Into<Integer>,
) -> Expression {
Expression::Complex(
Complex::new(
Rational::new(real_numerator.into(), real_denominator.into()),
Rational::new(imaginary_numerator.into(), imaginary_denominator.into()),
),
RationalRepresentation::Fraction,
)
}
pub fn comd(
real_numerator: impl Into<Integer>,
real_denominator: impl Into<Integer>,
imaginary_numerator: impl Into<Integer>,
imaginary_denominator: impl Into<Integer>,
) -> Expression {
Expression::Complex(
Complex::new(
Rational::new(real_numerator.into(), real_denominator.into()),
Rational::new(imaginary_numerator.into(), imaginary_denominator.into()),
),
RationalRepresentation::Decimal,
)
}
pub fn pow(base: impl Into<Expression>, exponent: impl Into<Expression>) -> Expression {
Expression::Power(Box::new(base.into()), Box::new(exponent.into()))
}
pub fn eq(left: impl Into<Expression>, right: impl Into<Expression>) -> Expression {
Expression::Equal(Box::new(left.into()), Box::new(right.into()))
}
pub fn ne(left: impl Into<Expression>, right: impl Into<Expression>) -> Expression {
Expression::NotEqual(Box::new(left.into()), Box::new(right.into()))
}
pub fn lt(left: impl Into<Expression>, right: impl Into<Expression>) -> Expression {
Expression::LessThan(Box::new(left.into()), Box::new(right.into()))
}
pub fn le(left: impl Into<Expression>, right: impl Into<Expression>) -> Expression {
Expression::LessThanOrEqual(Box::new(left.into()), Box::new(right.into()))
}
pub fn gt(left: impl Into<Expression>, right: impl Into<Expression>) -> Expression {
Expression::GreaterThan(Box::new(left.into()), Box::new(right.into()))
}
pub fn ge(left: impl Into<Expression>, right: impl Into<Expression>) -> Expression {
Expression::GreaterThanOrEqual(Box::new(left.into()), Box::new(right.into()))
}
pub fn and(a: impl Into<Expression>, b: impl Into<Expression>) -> Expression {
Expression::And(Box::new(a.into()), Box::new(b.into()))
}
pub fn or(a: impl Into<Expression>, b: impl Into<Expression>) -> Expression {
Expression::Or(Box::new(a.into()), Box::new(b.into()))
}