use std::ops::Mul;
use num_traits::{ops::overflowing::OverflowingMul, CheckedMul, SaturatingMul, WrappingMul};
use crate::{
array::PrimitiveArray,
bitmap::Bitmap,
compute::{
arithmetics::{
ArrayCheckedMul, ArrayMul, ArrayOverflowingMul, ArraySaturatingMul, ArrayWrappingMul,
},
arity::{
binary, binary_checked, binary_with_bitmap, unary, unary_checked, unary_with_bitmap,
},
},
};
use super::NativeArithmetics;
pub fn mul<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> PrimitiveArray<T>
where
T: NativeArithmetics + Mul<Output = T>,
{
binary(lhs, rhs, lhs.data_type().clone(), |a, b| a * b)
}
pub fn wrapping_mul<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> PrimitiveArray<T>
where
T: NativeArithmetics + WrappingMul<Output = T>,
{
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>) -> PrimitiveArray<T>
where
T: NativeArithmetics + CheckedMul<Output = T>,
{
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>) -> PrimitiveArray<T>
where
T: NativeArithmetics + SaturatingMul<Output = T>,
{
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>,
) -> (PrimitiveArray<T>, Bitmap)
where
T: NativeArithmetics + OverflowingMul<Output = T>,
{
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: NativeArithmetics + Mul<Output = T>,
{
fn mul(&self, rhs: &PrimitiveArray<T>) -> Self {
mul(self, rhs)
}
}
impl<T> ArrayWrappingMul<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeArithmetics + WrappingMul<Output = T>,
{
fn wrapping_mul(&self, rhs: &PrimitiveArray<T>) -> Self {
wrapping_mul(self, rhs)
}
}
impl<T> ArrayCheckedMul<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeArithmetics + CheckedMul<Output = T>,
{
fn checked_mul(&self, rhs: &PrimitiveArray<T>) -> Self {
checked_mul(self, rhs)
}
}
impl<T> ArraySaturatingMul<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeArithmetics + SaturatingMul<Output = T>,
{
fn saturating_mul(&self, rhs: &PrimitiveArray<T>) -> Self {
saturating_mul(self, rhs)
}
}
impl<T> ArrayOverflowingMul<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeArithmetics + OverflowingMul<Output = T>,
{
fn overflowing_mul(&self, rhs: &PrimitiveArray<T>) -> (Self, Bitmap) {
overflowing_mul(self, rhs)
}
}
pub fn mul_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> PrimitiveArray<T>
where
T: NativeArithmetics + 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: NativeArithmetics + 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: NativeArithmetics + CheckedMul<Output = T>,
{
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: NativeArithmetics + 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: NativeArithmetics + 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: NativeArithmetics + Mul<Output = T>,
{
fn mul(&self, rhs: &T) -> Self {
mul_scalar(self, rhs)
}
}
impl<T> ArrayCheckedMul<T> for PrimitiveArray<T>
where
T: NativeArithmetics + CheckedMul<Output = T>,
{
fn checked_mul(&self, rhs: &T) -> Self {
checked_mul_scalar(self, rhs)
}
}
impl<T> ArraySaturatingMul<T> for PrimitiveArray<T>
where
T: NativeArithmetics + SaturatingMul<Output = T>,
{
fn saturating_mul(&self, rhs: &T) -> Self {
saturating_mul_scalar(self, rhs)
}
}
impl<T> ArrayOverflowingMul<T> for PrimitiveArray<T>
where
T: NativeArithmetics + OverflowingMul<Output = T>,
{
fn overflowing_mul(&self, rhs: &T) -> (Self, Bitmap) {
overflowing_mul_scalar(self, rhs)
}
}