use std::any::Any;
use libnum::Complex;
pub trait ScalarOperand : Any + Clone { }
impl ScalarOperand for bool { }
impl ScalarOperand for i8 { }
impl ScalarOperand for u8 { }
impl ScalarOperand for i16 { }
impl ScalarOperand for u16 { }
impl ScalarOperand for i32 { }
impl ScalarOperand for u32 { }
impl ScalarOperand for i64 { }
impl ScalarOperand for u64 { }
impl ScalarOperand for f32 { }
impl ScalarOperand for f64 { }
impl ScalarOperand for Complex<f32> { }
impl ScalarOperand for Complex<f64> { }
macro_rules! impl_binary_op(
($trt:ident, $mth:ident, $imth:ident, $imth_scalar:ident, $doc:expr) => (
#[doc=$doc]
impl<A, S, S2, D, E> $trt<ArrayBase<S2, E>> for ArrayBase<S, D>
where A: Clone + $trt<A, Output=A>,
S: DataOwned<Elem=A> + DataMut,
S2: Data<Elem=A>,
D: Dimension,
E: Dimension,
{
type Output = ArrayBase<S, D>;
fn $mth(self, rhs: ArrayBase<S2, E>) -> ArrayBase<S, D>
{
self.$mth(&rhs)
}
}
#[doc=$doc]
impl<'a, A, S, S2, D, E> $trt<&'a ArrayBase<S2, E>> for ArrayBase<S, D>
where A: Clone + $trt<A, Output=A>,
S: DataMut<Elem=A>,
S2: Data<Elem=A>,
D: Dimension,
E: Dimension,
{
type Output = ArrayBase<S, D>;
fn $mth(mut self, rhs: &ArrayBase<S2, E>) -> ArrayBase<S, D>
{
self.$imth(rhs);
self
}
}
#[doc=$doc]
impl<'a, 'b, A, S, S2, D, E> $trt<&'a ArrayBase<S2, E>> for &'b ArrayBase<S, D>
where A: Clone + $trt<A, Output=A>,
S: Data<Elem=A>,
S2: Data<Elem=A>,
D: Dimension,
E: Dimension,
{
type Output = OwnedArray<A, D>;
fn $mth(self, rhs: &'a ArrayBase<S2, E>) -> OwnedArray<A, D> {
self.to_owned().$mth(rhs)
}
}
#[doc=$doc]
impl<A, S, D, B> $trt<B> for ArrayBase<S, D>
where A: Clone + $trt<B, Output=A>,
S: DataOwned<Elem=A> + DataMut,
D: Dimension,
B: ScalarOperand,
{
type Output = ArrayBase<S, D>;
fn $mth(mut self, x: B) -> ArrayBase<S, D> {
self.unordered_foreach_mut(move |elt| {
*elt = elt.clone().$mth(x.clone());
});
self
}
}
#[doc=$doc]
impl<'a, A, S, D, B> $trt<B> for &'a ArrayBase<S, D>
where A: Clone + $trt<B, Output=A>,
S: Data<Elem=A>,
D: Dimension,
B: ScalarOperand,
{
type Output = OwnedArray<A, D>;
fn $mth(self, x: B) -> OwnedArray<A, D> {
self.to_owned().$mth(x)
}
}
);
);
macro_rules! if_commutative {
(Commute { $a:expr } or { $b:expr }) => ($a);
(Ordered { $a:expr } or { $b:expr }) => ($b);
}
macro_rules! impl_scalar_lhs_op {
($scalar:ty, $commutative:ident, $trt:ident, $mth:ident, $doc:expr) => (
impl<S, D> $trt<ArrayBase<S, D>> for $scalar
where S: DataMut<Elem=$scalar>,
D: Dimension,
{
type Output = ArrayBase<S, D>;
fn $mth(self, mut rhs: ArrayBase<S, D>) -> ArrayBase<S, D> {
rhs.unordered_foreach_mut(move |elt| {
*elt = self.$mth(*elt);
});
rhs
}
}
impl<'a, S, D> $trt<&'a ArrayBase<S, D>> for $scalar
where S: Data<Elem=$scalar>,
D: Dimension,
{
type Output = OwnedArray<$scalar, D>;
fn $mth(self, rhs: &ArrayBase<S, D>) -> OwnedArray<$scalar, D> {
if_commutative!($commutative {
rhs.$mth(self)
} or {
self.$mth(rhs.to_owned())
})
}
}
);
}
mod arithmetic_ops {
use super::*;
use imp_prelude::*;
use std::ops::*;
use libnum::Complex;
impl_binary_op!(Add, add, iadd, iadd_scalar, "addition");
impl_binary_op!(Sub, sub, isub, isub_scalar, "subtraction");
impl_binary_op!(Mul, mul, imul, imul_scalar, "multiplication");
impl_binary_op!(Div, div, idiv, idiv_scalar, "division");
impl_binary_op!(Rem, rem, irem, irem_scalar, "remainder");
impl_binary_op!(BitAnd, bitand, ibitand, ibitand_scalar, "bit and");
impl_binary_op!(BitOr, bitor, ibitor, ibitor_scalar, "bit or");
impl_binary_op!(BitXor, bitxor, ibitxor, ibitxor_scalar, "bit xor");
impl_binary_op!(Shl, shl, ishl, ishl_scalar, "left shift");
impl_binary_op!(Shr, shr, ishr, ishr_scalar, "right shift");
macro_rules! all_scalar_ops {
($int_scalar:ty) => (
impl_scalar_lhs_op!($int_scalar, Commute, Add, add, "addition");
impl_scalar_lhs_op!($int_scalar, Ordered, Sub, sub, "subtraction");
impl_scalar_lhs_op!($int_scalar, Commute, Mul, mul, "multiplication");
impl_scalar_lhs_op!($int_scalar, Ordered, Div, div, "division");
impl_scalar_lhs_op!($int_scalar, Ordered, Rem, rem, "remainder");
impl_scalar_lhs_op!($int_scalar, Commute, BitAnd, bitand, "bit and");
impl_scalar_lhs_op!($int_scalar, Commute, BitOr, bitor, "bit or");
impl_scalar_lhs_op!($int_scalar, Commute, BitXor, bitxor, "bit xor");
impl_scalar_lhs_op!($int_scalar, Ordered, Shl, shl, "left shift");
impl_scalar_lhs_op!($int_scalar, Ordered, Shr, shr, "right shift");
);
}
all_scalar_ops!(i8);
all_scalar_ops!(u8);
all_scalar_ops!(i16);
all_scalar_ops!(u16);
all_scalar_ops!(i32);
all_scalar_ops!(u32);
all_scalar_ops!(i64);
all_scalar_ops!(u64);
impl_scalar_lhs_op!(bool, Commute, BitAnd, bitand, "bit and");
impl_scalar_lhs_op!(bool, Commute, BitOr, bitor, "bit or");
impl_scalar_lhs_op!(bool, Commute, BitXor, bitxor, "bit xor");
impl_scalar_lhs_op!(f32, Commute, Add, add, "addition");
impl_scalar_lhs_op!(f32, Ordered, Sub, sub, "subtraction");
impl_scalar_lhs_op!(f32, Commute, Mul, mul, "multiplication");
impl_scalar_lhs_op!(f32, Ordered, Div, div, "division");
impl_scalar_lhs_op!(f32, Ordered, Rem, rem, "remainder");
impl_scalar_lhs_op!(f64, Commute, Add, add, "addition");
impl_scalar_lhs_op!(f64, Ordered, Sub, sub, "subtraction");
impl_scalar_lhs_op!(f64, Commute, Mul, mul, "multiplication");
impl_scalar_lhs_op!(f64, Ordered, Div, div, "division");
impl_scalar_lhs_op!(f64, Ordered, Rem, rem, "remainder");
impl_scalar_lhs_op!(Complex<f32>, Commute, Add, add, "addition");
impl_scalar_lhs_op!(Complex<f32>, Ordered, Sub, sub, "subtraction");
impl_scalar_lhs_op!(Complex<f32>, Commute, Mul, mul, "multiplication");
impl_scalar_lhs_op!(Complex<f32>, Ordered, Div, div, "division");
impl_scalar_lhs_op!(Complex<f64>, Commute, Add, add, "addition");
impl_scalar_lhs_op!(Complex<f64>, Ordered, Sub, sub, "subtraction");
impl_scalar_lhs_op!(Complex<f64>, Commute, Mul, mul, "multiplication");
impl_scalar_lhs_op!(Complex<f64>, Ordered, Div, div, "division");
impl<A, S, D> Neg for ArrayBase<S, D>
where A: Clone + Neg<Output=A>,
S: DataMut<Elem=A>,
D: Dimension
{
type Output = Self;
fn neg(mut self) -> Self {
self.ineg();
self
}
}
impl<A, S, D> Not for ArrayBase<S, D>
where A: Clone + Not<Output=A>,
S: DataMut<Elem=A>,
D: Dimension
{
type Output = Self;
fn not(mut self) -> Self {
self.inot();
self
}
}
}
#[cfg(feature = "assign_ops")]
mod assign_ops {
use super::*;
use imp_prelude::*;
macro_rules! impl_assign_op {
($trt:ident, $method:ident, $doc:expr) => {
use std::ops::$trt;
#[doc=$doc]
impl<'a, A, S, S2, D, E> $trt<&'a ArrayBase<S2, E>> for ArrayBase<S, D>
where A: Clone + $trt<A>,
S: DataMut<Elem=A>,
S2: Data<Elem=A>,
D: Dimension,
E: Dimension,
{
fn $method(&mut self, rhs: &ArrayBase<S2, E>) {
self.zip_mut_with(rhs, |x, y| {
x.$method(y.clone());
});
}
}
#[doc=$doc]
impl<A, S, D> $trt<A> for ArrayBase<S, D>
where A: ScalarOperand + $trt<A>,
S: DataMut<Elem=A>,
D: Dimension,
{
fn $method(&mut self, rhs: A) {
self.unordered_foreach_mut(move |elt| {
elt.$method(rhs.clone());
});
}
}
};
}
impl_assign_op!(AddAssign, add_assign,
"Perform `self += rhs` as elementwise addition (in place).\n");
impl_assign_op!(SubAssign, sub_assign,
"Perform `self -= rhs` as elementwise subtraction (in place).\n");
impl_assign_op!(MulAssign, mul_assign,
"Perform `self *= rhs` as elementwise multiplication (in place).\n");
impl_assign_op!(DivAssign, div_assign,
"Perform `self /= rhs` as elementwise division (in place).\n");
impl_assign_op!(RemAssign, rem_assign,
"Perform `self %= rhs` as elementwise remainder (in place).\n");
impl_assign_op!(BitAndAssign, bitand_assign,
"Perform `self &= rhs` as elementwise bit and (in place).\n");
impl_assign_op!(BitOrAssign, bitor_assign,
"Perform `self |= rhs` as elementwise bit or (in place).\n");
impl_assign_op!(BitXorAssign, bitxor_assign,
"Perform `self ^= rhs` as elementwise bit xor (in place).\n");
impl_assign_op!(ShlAssign, shl_assign,
"Perform `self <<= rhs` as elementwise left shift (in place).\n");
impl_assign_op!(ShrAssign, shr_assign,
"Perform `self >>= rhs` as elementwise right shift (in place).\n");
}