#[macro_export]
macro_rules! impl_from_f {
($struct:ident, [$($im:ident),*]$(, [$($dim:tt),*]$(, [$($ddim:tt),*])?)?) => {
impl<T: DualNum<F>, F$($(, $dim: Dim)*)?> From<F> for $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
#[inline]
fn from(float: F) -> Self {
Self::from_re(T::from(float))
}
}
};
}
#[macro_export]
macro_rules! impl_zero_one {
($struct:ident$(, [$($dim:tt),*]$(, [$($ddim:tt),*])?)?) => {
impl<T: DualNum<F>, F: Float$($(, $dim: Dim)*)?> Zero for $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
#[inline]
fn zero() -> Self {
Self::from_re(T::zero())
}
#[inline]
fn is_zero(&self) -> bool {
self.re.is_zero()
}
}
impl<T: DualNum<F>, F: Float$($(, $dim: Dim)*)?> One for $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
#[inline]
fn one() -> Self {
Self::from_re(T::one())
}
#[inline]
fn is_one(&self) -> bool {
self.re.is_one()
}
}
};
}
#[macro_export]
macro_rules! impl_add_sub_rem {
($struct:ident, [$($im:ident),*]$(, [$($dim:tt),*]$(, [$($ddim:tt),*])?)?) => {
impl<'a, 'b, T: DualNum<F>, F: Float$($(, $dim: Dim)*)?> Add<&'a $struct<T, F$($(, $dim)*)?>>
for &'b $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
type Output = $struct<T, F$($(, $dim)*)?>;
#[inline]
fn add(self, other: &$struct<T, F$($(, $dim)*)?>) -> $struct<T, F$($(, $dim)*)?> {
Self::Output::new(self.re.clone() + &other.re, $(self.$im.clone() + &other.$im,)*)
}
}
impl<'a, 'b, T: DualNum<F>, F: Float$($(, $dim: Dim)*)?> Sub<&'a $struct<T, F$($(, $dim)*)?>>
for &'b $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
type Output = $struct<T, F$($(, $dim)*)?>;
#[inline]
fn sub(self, other: &$struct<T, F$($(, $dim)*)?>) -> $struct<T, F$($(, $dim)*)?> {
Self::Output::new(self.re.clone() - &other.re, $(self.$im.clone() - &other.$im,)*)
}
}
impl<'a, 'b, T: DualNum<F>, F$($(, $dim: Dim)*)?> Rem<&'a $struct<T, F$($(, $dim)*)?>> for &'b $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
type Output = $struct<T, F$($(, $dim)*)?>;
#[inline]
fn rem(self, _other: &$struct<T, F$($(, $dim)*)?>) -> $struct<T, F$($(, $dim)*)?> {
unimplemented!()
}
}
};
}
#[macro_export]
macro_rules! forward_binop {
($struct:ident, $trt:ident, $operator:tt, $mth:ident$(, [$($dim:tt),*]$(, [$($ddim:tt),*])?)?) => {
impl<T: DualNum<F>, F: Float$($(, $dim: Dim)*)?> $trt<$struct<T, F$($(, $dim)*)?>> for &$struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
type Output = $struct<T, F$($(, $dim)*)?>;
#[inline]
fn $mth(self, rhs: $struct<T, F$($(, $dim)*)?>) -> Self::Output {
self $operator &rhs
}
}
impl<T: DualNum<F>, F: Float$($(, $dim: Dim)*)?> $trt<&$struct<T, F$($(, $dim)*)?>> for $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
type Output = $struct<T, F$($(, $dim)*)?>;
#[inline]
fn $mth(self, rhs: &$struct<T, F$($(, $dim)*)?>) -> Self::Output {
&self $operator rhs
}
}
impl<T: DualNum<F>, F: Float$($(, $dim: Dim)*)?> $trt for $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
type Output = $struct<T, F$($(, $dim)*)?>;
#[inline]
fn $mth(self, rhs: $struct<T, F$($(, $dim)*)?>) -> Self::Output {
&self $operator &rhs
}
}
};
}
#[macro_export]
macro_rules! impl_neg {
($struct:ident, [$($im:ident),*]$(, [$($dim:tt),*]$(, [$($ddim:tt),*])?)?) => {
impl<T: DualNum<F>, F: Float$($(, $dim: Dim)*)?> Neg for $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
type Output = Self;
#[inline]
fn neg(self) -> Self {
-&self
}
}
impl<T: DualNum<F>, F: Float$($(, $dim: Dim)*)?> Neg for &$struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
type Output = $struct<T, F$($(, $dim)*)?>;
#[inline]
fn neg(self) -> Self::Output {
<$struct<T, F$($(, $dim)*)?>>::new(-self.re.clone(), $(-self.$im.clone()),*)
}
}
};
}
#[macro_export]
macro_rules! impl_assign_ops {
($struct:ident, [$($im:ident),*]$(, [$($dim:tt),*]$(, [$($ddim:tt),*])?)?) => {
impl<T: DualNum<F>, F: Float$($(, $dim: Dim)*)?> MulAssign for $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
#[inline]
fn mul_assign(&mut self, other: Self) {
*self = self.clone() * other;
}
}
impl<T: DualNum<F>, F: Float$($(, $dim: Dim)*)?> DivAssign for $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
#[inline]
fn div_assign(&mut self, other: Self) {
*self = self.clone() / other;
}
}
impl<T: DualNum<F>, F$($(, $dim: Dim)*)?> AddAssign for $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
#[inline]
fn add_assign(&mut self, other: Self) {
self.re += other.re;
$(self.$im += other.$im;)*
}
}
impl<T: DualNum<F>, F$($(, $dim: Dim)*)?> SubAssign for $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
#[inline]
fn sub_assign(&mut self, other: Self) {
self.re -= other.re;
$(self.$im -= other.$im;)*
}
}
impl<T: DualNum<F>, F$($(, $dim: Dim)*)?> RemAssign for $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
#[inline]
fn rem_assign(&mut self, _other: Self) {
unimplemented!()
}
}
};
}
#[macro_export]
macro_rules! impl_scalar_op {
($struct:ident, [$($im:ident),*]$(, [$($dim:tt),*]$(, [$($ddim:tt),*])?)?) => {
impl<T: DualNum<F>, F: DualNumFloat$($(, $dim: Dim)*)?> Mul<F> for $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
type Output = Self;
#[inline]
fn mul(mut self, other: F) -> Self {
self *= other;
self
}
}
impl<T: DualNum<F>, F: DualNumFloat$($(, $dim: Dim)*)?> MulAssign<F> for $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
#[inline]
fn mul_assign(&mut self, other: F) {
self.re *= other;
$(self.$im *= T::from(other);)*
}
}
impl<T: DualNum<F>, F: DualNumFloat$($(, $dim: Dim)*)?> Div<F> for $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
type Output = Self;
#[inline]
fn div(mut self, other: F) -> Self {
self /= other;
self
}
}
impl<T: DualNum<F>, F: DualNumFloat$($(, $dim: Dim)*)?> DivAssign<F> for $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
#[inline]
fn div_assign(&mut self, other: F) {
self.re /= other;
$(self.$im /= T::from(other);)*
}
}
impl<T: DualNum<F>, F$($(, $dim: Dim)*)?> Add<F> for $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
type Output = Self;
#[inline]
fn add(mut self, other: F) -> Self {
self.re += other;
self
}
}
impl<T: DualNum<F>, F$($(, $dim: Dim)*)?> AddAssign<F> for $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
#[inline]
fn add_assign(&mut self, other: F) {
self.re += other;
}
}
impl<T: DualNum<F>, F$($(, $dim: Dim)*)?> Sub<F> for $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
type Output = Self;
#[inline]
fn sub(mut self, other: F) -> Self {
self.re -= other;
self
}
}
impl<T: DualNum<F>, F$($(, $dim: Dim)*)?> SubAssign<F> for $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
#[inline]
fn sub_assign(&mut self, other: F) {
self.re -= other;
}
}
impl<T: DualNum<F>, F$($(, $dim: Dim)*)?> Rem<F> for $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
type Output = Self;
#[inline]
fn rem(self, _other: F) -> Self {
unimplemented!()
}
}
impl<T: DualNum<F>, F$($(, $dim: Dim)*)?> RemAssign<F> for $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
#[inline]
fn rem_assign(&mut self, _other: F) {
unimplemented!()
}
}
};
}
#[macro_export]
macro_rules! impl_inv {
($struct:ident$(, [$($dim:tt),*]$(, [$($ddim:tt),*])?)?) => {
impl<T: DualNum<F>, F: DualNumFloat$($(, $dim: Dim)*)?> Inv for $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
type Output = Self;
#[inline]
fn inv(self) -> Self {
self.recip()
}
}
};
}
#[macro_export]
macro_rules! impl_iterator {
($struct:ident$(, [$($dim:tt),*]$(, [$($ddim:tt),*])?)?) => {
impl<T: DualNum<F>, F: Float$($(, $dim: Dim)*)?> Sum for $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
#[inline]
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::zero(), |acc, c| acc + c)
}
}
impl<'a, T: DualNum<F>, F: Float$($(, $dim: Dim)*)?> Sum<&'a $struct<T, F$($(, $dim)*)?>>
for $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
#[inline]
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = &'a $struct<T, F$($(, $dim)*)?>>,
{
iter.fold(Self::zero(), |acc, c| acc + c)
}
}
impl<T: DualNum<F>, F: Float$($(, $dim: Dim)*)?> Product for $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
#[inline]
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::one(), |acc, c| acc * c)
}
}
impl<'a, T: DualNum<F>, F: Float$($(, $dim: Dim)*)?> Product<&'a $struct<T, F$($(, $dim)*)?>>
for $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
#[inline]
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = &'a $struct<T, F$($(, $dim)*)?>>,
{
iter.fold(Self::one(), |acc, c| acc * c)
}
}
};
}
#[macro_export]
macro_rules! impl_from_primitive {
($struct:ident$(, [$($dim:tt),*]$(, [$($ddim:tt),*])?)?) => {
impl<T: DualNum<F>, F: Float + FromPrimitive$($(, $dim: Dim)*)?> FromPrimitive for $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
#[inline]
fn from_isize(n: isize) -> Option<Self> {
F::from_isize(n).map(|f| f.into())
}
#[inline]
fn from_i8(n: i8) -> Option<Self> {
F::from_i8(n).map(|f| f.into())
}
#[inline]
fn from_i16(n: i16) -> Option<Self> {
F::from_i16(n).map(|f| f.into())
}
#[inline]
fn from_i32(n: i32) -> Option<Self> {
F::from_i32(n).map(|f| f.into())
}
#[inline]
fn from_i64(n: i64) -> Option<Self> {
F::from_i64(n).map(|f| f.into())
}
#[inline]
fn from_i128(n: i128) -> Option<Self> {
F::from_i128(n).map(|f| f.into())
}
#[inline]
fn from_usize(n: usize) -> Option<Self> {
F::from_usize(n).map(|f| f.into())
}
#[inline]
fn from_u8(n: u8) -> Option<Self> {
F::from_u8(n).map(|f| f.into())
}
#[inline]
fn from_u16(n: u16) -> Option<Self> {
F::from_u16(n).map(|f| f.into())
}
#[inline]
fn from_u32(n: u32) -> Option<Self> {
F::from_u32(n).map(|f| f.into())
}
#[inline]
fn from_u64(n: u64) -> Option<Self> {
F::from_u64(n).map(|f| f.into())
}
#[inline]
fn from_u128(n: u128) -> Option<Self> {
F::from_u128(n).map(|f| f.into())
}
#[inline]
fn from_f32(n: f32) -> Option<Self> {
F::from_f32(n).map(|f| f.into())
}
#[inline]
fn from_f64(n: f64) -> Option<Self> {
F::from_f64(n).map(|f| f.into())
}
}
};
}
#[macro_export]
macro_rules! impl_signed {
($struct:ident$(, [$($dim:tt),*]$(, [$($ddim:tt),*])?)?) => {
impl<T: DualNum<F>, F: DualNumFloat$($(, $dim: Dim)*)?> Signed for $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
#[inline]
fn abs(&self) -> Self {
if self.is_positive() {
self.clone()
} else {
-self
}
}
#[inline]
fn abs_sub(&self, other: &Self) -> Self {
if self.re() > other.re() {
self - other
} else {
Self::zero()
}
}
#[inline]
fn signum(&self) -> Self {
if self.is_positive() {
Self::one()
} else if self.is_zero() {
Self::zero()
} else {
-Self::one()
}
}
#[inline]
fn is_positive(&self) -> bool {
self.re.is_positive()
}
#[inline]
fn is_negative(&self) -> bool {
self.re.is_negative()
}
}
};
}
#[macro_export]
macro_rules! impl_float_const {
($struct:ident$(, [$($dim:tt),*]$(, [$($ddim:tt),*])?)?) => {
impl<T: DualNum<F>, F: Float + FloatConst$($(, $dim: Dim)*)?> FloatConst for $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
fn E() -> Self {
Self::from(F::E())
}
fn FRAC_1_PI() -> Self {
Self::from(F::FRAC_1_PI())
}
fn FRAC_1_SQRT_2() -> Self {
Self::from(F::FRAC_1_SQRT_2())
}
fn FRAC_2_PI() -> Self {
Self::from(F::FRAC_2_PI())
}
fn FRAC_2_SQRT_PI() -> Self {
Self::from(F::FRAC_2_SQRT_PI())
}
fn FRAC_PI_2() -> Self {
Self::from(F::FRAC_PI_2())
}
fn FRAC_PI_3() -> Self {
Self::from(F::FRAC_PI_3())
}
fn FRAC_PI_4() -> Self {
Self::from(F::FRAC_PI_4())
}
fn FRAC_PI_6() -> Self {
Self::from(F::FRAC_PI_6())
}
fn FRAC_PI_8() -> Self {
Self::from(F::FRAC_PI_8())
}
fn LN_10() -> Self {
Self::from(F::LN_10())
}
fn LN_2() -> Self {
Self::from(F::LN_2())
}
fn LOG10_E() -> Self {
Self::from(F::LOG10_E())
}
fn LOG2_E() -> Self {
Self::from(F::LOG2_E())
}
fn PI() -> Self {
Self::from(F::PI())
}
fn SQRT_2() -> Self {
Self::from(F::SQRT_2())
}
}
};
}
#[macro_export]
macro_rules! impl_num {
($struct:ident$(, [$($dim:tt),*]$(, [$($ddim:tt),*])?)?) => {
impl<T: DualNum<F> + Signed, F: Float$($(, $dim: Dim)*)?> Num for $struct<T, F$($(, $dim)*)?>
where
$($(DefaultAllocator: Allocator<$dim> + Allocator<U1, $dim> + Allocator<$dim, $dim>,)*)?
$($(DefaultAllocator: Allocator<$($ddim,)*>)?)?
{
type FromStrRadixErr = F::FromStrRadixErr;
#[inline]
fn from_str_radix(_str: &str, _radix: u32) -> Result<Self, Self::FromStrRadixErr> {
unimplemented!()
}
}
};
}
#[macro_export]
macro_rules! impl_dual {
($struct:ident, [$($im:ident),*]$(, [$($dim:tt),*]$(, [$($ddim:tt),*])?)?) => {
impl_from_f!($struct, [$($im),*]$(, [$($dim),*]$(, [$($ddim),*])?)?);
impl_zero_one!($struct$(, [$($dim),*]$(, [$($ddim),*])?)?);
impl_add_sub_rem!($struct, [$($im),*]$(, [$($dim),*]$(, [$($ddim),*])?)?);
forward_binop!($struct, Add, +, add$(, [$($dim),*]$(, [$($ddim),*])?)?);
forward_binop!($struct, Sub, -, sub$(, [$($dim),*]$(, [$($ddim),*])?)?);
forward_binop!($struct, Mul, *, mul$(, [$($dim),*]$(, [$($ddim),*])?)?);
forward_binop!($struct, Div, /, div$(, [$($dim),*]$(, [$($ddim),*])?)?);
forward_binop!($struct, Rem, %, rem$(, [$($dim),*]$(, [$($ddim),*])?)?);
impl_neg!($struct, [$($im),*]$(, [$($dim),*]$(, [$($ddim),*])?)?);
impl_assign_ops!($struct, [$($im),*]$(, [$($dim),*]$(, [$($ddim),*])?)?);
impl_scalar_op!($struct, [$($im),*]$(, [$($dim),*]$(, [$($ddim),*])?)?);
impl_inv!($struct$(, [$($dim),*]$(, [$($ddim),*])?)?);
impl_iterator!($struct$(, [$($dim),*]$(, [$($ddim),*])?)?);
impl_from_primitive!($struct$(, [$($dim),*]$(, [$($ddim),*])?)?);
impl_signed!($struct$(, [$($dim),*]$(, [$($ddim),*])?)?);
impl_num!($struct$(, [$($dim),*]$(, [$($ddim),*])?)?);
impl_float_const!($struct$(, [$($dim),*]$(, [$($ddim),*])?)?);
};
}