use core::ops::{Add, Mul, Neg};
use super::basic::{Z0, P1, N1, B0, B1, Integer, NonZero};
use crate::variable::{Var,Numeric};
impl<I: Integer> Mul<I> for Z0 {
type Output = Self;
#[inline(always)]
fn mul(self, _rhs: I) -> Self::Output {
self }
}
impl<I: Integer> Mul<I> for P1 {
type Output = I;
#[inline(always)]
fn mul(self, rhs: I) -> Self::Output {
rhs }
}
impl<I: Integer + Neg> Mul<I> for N1 {
type Output = I::Output;
#[inline(always)]
fn mul(self, rhs: I) -> Self::Output {
-rhs }
}
impl<H: NonZero> Mul<Z0> for B0<H> {
type Output = Z0;
#[inline(always)]
fn mul(self, _rhs: Z0) -> Self::Output {
Z0 }
}
impl<H: NonZero + Mul<I>, I: NonZero> Mul<I> for B0<H> {
type Output = B0<H::Output>;
#[inline(always)]
fn mul(self, _rhs: I) -> Self::Output {
B0::new() }
}
impl<H: NonZero> Mul<Z0> for B1<H> {
type Output = Z0;
#[inline(always)]
fn mul(self, _rhs: Z0) -> Self::Output {
Z0 }
}
impl<H: NonZero + Mul<I>, I: NonZero + Add<B0<<H as Mul<I>>::Output>>> Mul<I> for B1<H> {
type Output = I::Output;
#[inline(always)]
fn mul(self, i: I) -> Self::Output {
i + B0::new() }
}
pub type Prod<A, B> = <A as Mul<B>>::Output;
impl<T:Numeric> Mul<Var<T>> for Z0 {
type Output = Self;
#[inline(always)]
fn mul(self, _rhs: Var<T>) -> Self::Output {
self }
}
impl<T: Numeric> Mul<Var<T>> for P1 {
type Output = Var<T>;
#[inline(always)]
fn mul(self, rhs: Var<T>) -> Self::Output {
rhs }
}
impl<T: Numeric> Mul<Var<T>> for N1
where
Var<T>: Neg,
{
type Output = <Var<T> as Neg>::Output;
#[inline(always)]
fn mul(self, rhs: Var<T>) -> Self::Output {
-rhs }
}
impl<H: NonZero, T:Numeric> Mul<Var<T>> for B0<H>
where
B0<H>: Integer,
Var<T>: Mul<Var<T>>,
{
type Output = Var<T>;
#[inline(always)]
fn mul(self, rhs: Var<T>) -> Self::Output {
Var(rhs.0 * T::from(B0::<H>::to_i32()))
}
}
impl<H: NonZero, T:Numeric> Mul<Var<T>> for B1<H>
where
B1<H>: Integer,
Var<T>: Mul<Var<T>>,
{
type Output = Var<T>;
#[inline(always)]
fn mul(self, rhs: Var<T>) -> Self::Output {
Var(rhs.0 * T::from(B0::<H>::to_i32()))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_basic_multiplication() {
let _: Z0 = Z0 * Z0;
let _: Z0 = Z0 * P1;
let _: Z0 = Z0 * N1;
let _: Z0 = P1 * Z0;
let _: P1 = P1 * P1;
let _: N1 = P1 * N1;
let _: Z0 = N1 * Z0;
let _: N1 = N1 * P1;
let _: P1 = N1 * N1;
}
#[test]
fn test_b0_multiplication() {
let b0_p1: B0<P1> = B0::new();
let _: Z0 = b0_p1 * Z0;
let _: B0<P1> = b0_p1 * P1;
let _: B0<N1> = b0_p1 * N1;
}
#[test]
fn test_b1_multiplication() {
let b1_p1: B1<P1> = B1::new();
let _: Z0 = b1_p1 * Z0;
}
fn _create_values() {
let _z0 = Z0;
let _p1 = P1;
let _n1 = N1;
let _b0_p1: B0<P1> = B0::new();
let _b1_p1: B1<P1> = B1::new();
}
}