use std::ops::Mul;
use num_traits::{ops::overflowing::OverflowingMul, CheckedMul, SaturatingMul, WrappingMul, Zero};
use crate::compute::arithmetics::basic::check_same_type;
use crate::compute::arithmetics::ArrayWrappingMul;
use crate::{
array::{Array, PrimitiveArray},
bitmap::Bitmap,
compute::{
arithmetics::{
ArrayCheckedMul, ArrayMul, ArrayOverflowingMul, ArraySaturatingMul, NotI128,
},
arity::{
binary, binary_checked, binary_with_bitmap, unary, unary_checked, unary_with_bitmap,
},
},
error::Result,
types::NativeType,
};
pub fn mul<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> Result<PrimitiveArray<T>>
where
T: NativeType + Mul<Output = T>,
{
check_same_type(lhs, rhs)?;
binary(lhs, rhs, lhs.data_type().clone(), |a, b| a * b)
}
pub fn wrapping_mul<T>(
lhs: &PrimitiveArray<T>,
rhs: &PrimitiveArray<T>,
) -> Result<PrimitiveArray<T>>
where
T: NativeType + WrappingMul<Output = T>,
{
check_same_type(lhs, rhs)?;
let op = move |a: T, b: T| a.wrapping_mul(&b);
binary(lhs, rhs, lhs.data_type().clone(), op)
}
pub fn checked_mul<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> Result<PrimitiveArray<T>>
where
T: NativeType + CheckedMul<Output = T> + Zero,
{
check_same_type(lhs, rhs)?;
let op = move |a: T, b: T| a.checked_mul(&b);
binary_checked(lhs, rhs, lhs.data_type().clone(), op)
}
pub fn saturating_mul<T>(
lhs: &PrimitiveArray<T>,
rhs: &PrimitiveArray<T>,
) -> Result<PrimitiveArray<T>>
where
T: NativeType + SaturatingMul<Output = T>,
{
check_same_type(lhs, rhs)?;
let op = move |a: T, b: T| a.saturating_mul(&b);
binary(lhs, rhs, lhs.data_type().clone(), op)
}
pub fn overflowing_mul<T>(
lhs: &PrimitiveArray<T>,
rhs: &PrimitiveArray<T>,
) -> Result<(PrimitiveArray<T>, Bitmap)>
where
T: NativeType + OverflowingMul<Output = T>,
{
check_same_type(lhs, rhs)?;
let op = move |a: T, b: T| a.overflowing_mul(&b);
binary_with_bitmap(lhs, rhs, lhs.data_type().clone(), op)
}
impl<T> ArrayMul<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeType + Mul<Output = T> + NotI128,
{
type Output = Self;
fn mul(&self, rhs: &PrimitiveArray<T>) -> Result<Self::Output> {
mul(self, rhs)
}
}
impl<T> ArrayWrappingMul<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeType + WrappingMul<Output = T> + NotI128,
{
type Output = Self;
fn wrapping_mul(&self, rhs: &PrimitiveArray<T>) -> Result<Self::Output> {
wrapping_mul(self, rhs)
}
}
impl<T> ArrayCheckedMul<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeType + CheckedMul<Output = T> + Zero + NotI128,
{
type Output = Self;
fn checked_mul(&self, rhs: &PrimitiveArray<T>) -> Result<Self::Output> {
checked_mul(self, rhs)
}
}
impl<T> ArraySaturatingMul<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeType + SaturatingMul<Output = T> + NotI128,
{
type Output = Self;
fn saturating_mul(&self, rhs: &PrimitiveArray<T>) -> Result<Self::Output> {
saturating_mul(self, rhs)
}
}
impl<T> ArrayOverflowingMul<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeType + OverflowingMul<Output = T> + NotI128,
{
type Output = Self;
fn overflowing_mul(&self, rhs: &PrimitiveArray<T>) -> Result<(Self::Output, Bitmap)> {
overflowing_mul(self, rhs)
}
}
pub fn mul_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> PrimitiveArray<T>
where
T: NativeType + Mul<Output = T>,
{
let rhs = *rhs;
unary(lhs, |a| a * rhs, lhs.data_type().clone())
}
pub fn wrapping_mul_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> PrimitiveArray<T>
where
T: NativeType + WrappingMul<Output = T>,
{
unary(lhs, |a| a.wrapping_mul(rhs), lhs.data_type().clone())
}
pub fn checked_mul_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> PrimitiveArray<T>
where
T: NativeType + CheckedMul<Output = T> + Zero,
{
let rhs = *rhs;
let op = move |a: T| a.checked_mul(&rhs);
unary_checked(lhs, op, lhs.data_type().clone())
}
pub fn saturating_mul_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> PrimitiveArray<T>
where
T: NativeType + SaturatingMul<Output = T>,
{
let rhs = *rhs;
let op = move |a: T| a.saturating_mul(&rhs);
unary(lhs, op, lhs.data_type().clone())
}
pub fn overflowing_mul_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> (PrimitiveArray<T>, Bitmap)
where
T: NativeType + OverflowingMul<Output = T>,
{
let rhs = *rhs;
let op = move |a: T| a.overflowing_mul(&rhs);
unary_with_bitmap(lhs, op, lhs.data_type().clone())
}
impl<T> ArrayMul<T> for PrimitiveArray<T>
where
T: NativeType + Mul<Output = T> + NotI128,
{
type Output = Self;
fn mul(&self, rhs: &T) -> Result<Self::Output> {
Ok(mul_scalar(self, rhs))
}
}
impl<T> ArrayCheckedMul<T> for PrimitiveArray<T>
where
T: NativeType + CheckedMul<Output = T> + Zero + NotI128,
{
type Output = Self;
fn checked_mul(&self, rhs: &T) -> Result<Self::Output> {
Ok(checked_mul_scalar(self, rhs))
}
}
impl<T> ArraySaturatingMul<T> for PrimitiveArray<T>
where
T: NativeType + SaturatingMul<Output = T> + NotI128,
{
type Output = Self;
fn saturating_mul(&self, rhs: &T) -> Result<Self::Output> {
Ok(saturating_mul_scalar(self, rhs))
}
}
impl<T> ArrayOverflowingMul<T> for PrimitiveArray<T>
where
T: NativeType + OverflowingMul<Output = T> + NotI128,
{
type Output = Self;
fn overflowing_mul(&self, rhs: &T) -> Result<(Self::Output, Bitmap)> {
Ok(overflowing_mul_scalar(self, rhs))
}
}