use std::ops::Sub;
use num_traits::{ops::overflowing::OverflowingSub, CheckedSub, SaturatingSub, WrappingSub, Zero};
use crate::compute::arithmetics::basic::check_same_type;
use crate::compute::arithmetics::ArrayWrappingSub;
use crate::{
array::{Array, PrimitiveArray},
bitmap::Bitmap,
compute::{
arithmetics::{
ArrayCheckedSub, ArrayOverflowingSub, ArraySaturatingSub, ArraySub, NotI128,
},
arity::{
binary, binary_checked, binary_with_bitmap, unary, unary_checked, unary_with_bitmap,
},
},
error::Result,
types::NativeType,
};
pub fn sub<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> Result<PrimitiveArray<T>>
where
T: NativeType + Sub<Output = T>,
{
check_same_type(lhs, rhs)?;
binary(lhs, rhs, lhs.data_type().clone(), |a, b| a - b)
}
pub fn wrapping_sub<T>(
lhs: &PrimitiveArray<T>,
rhs: &PrimitiveArray<T>,
) -> Result<PrimitiveArray<T>>
where
T: NativeType + WrappingSub<Output = T>,
{
check_same_type(lhs, rhs)?;
let op = move |a: T, b: T| a.wrapping_sub(&b);
binary(lhs, rhs, lhs.data_type().clone(), op)
}
pub fn checked_sub<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> Result<PrimitiveArray<T>>
where
T: NativeType + CheckedSub<Output = T> + Zero,
{
check_same_type(lhs, rhs)?;
let op = move |a: T, b: T| a.checked_sub(&b);
binary_checked(lhs, rhs, lhs.data_type().clone(), op)
}
pub fn saturating_sub<T>(
lhs: &PrimitiveArray<T>,
rhs: &PrimitiveArray<T>,
) -> Result<PrimitiveArray<T>>
where
T: NativeType + SaturatingSub<Output = T>,
{
check_same_type(lhs, rhs)?;
let op = move |a: T, b: T| a.saturating_sub(&b);
binary(lhs, rhs, lhs.data_type().clone(), op)
}
pub fn overflowing_sub<T>(
lhs: &PrimitiveArray<T>,
rhs: &PrimitiveArray<T>,
) -> Result<(PrimitiveArray<T>, Bitmap)>
where
T: NativeType + OverflowingSub<Output = T>,
{
check_same_type(lhs, rhs)?;
let op = move |a: T, b: T| a.overflowing_sub(&b);
binary_with_bitmap(lhs, rhs, lhs.data_type().clone(), op)
}
impl<T> ArraySub<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeType + Sub<Output = T> + NotI128,
{
type Output = Self;
fn sub(&self, rhs: &PrimitiveArray<T>) -> Result<Self::Output> {
sub(self, rhs)
}
}
impl<T> ArrayWrappingSub<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeType + WrappingSub<Output = T> + NotI128,
{
type Output = Self;
fn wrapping_sub(&self, rhs: &PrimitiveArray<T>) -> Result<Self::Output> {
wrapping_sub(self, rhs)
}
}
impl<T> ArrayCheckedSub<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeType + CheckedSub<Output = T> + Zero + NotI128,
{
type Output = Self;
fn checked_sub(&self, rhs: &PrimitiveArray<T>) -> Result<Self::Output> {
checked_sub(self, rhs)
}
}
impl<T> ArraySaturatingSub<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeType + SaturatingSub<Output = T> + NotI128,
{
type Output = Self;
fn saturating_sub(&self, rhs: &PrimitiveArray<T>) -> Result<Self::Output> {
saturating_sub(self, rhs)
}
}
impl<T> ArrayOverflowingSub<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeType + OverflowingSub<Output = T>,
{
type Output = Self;
fn overflowing_sub(&self, rhs: &PrimitiveArray<T>) -> Result<(Self::Output, Bitmap)> {
overflowing_sub(self, rhs)
}
}
pub fn sub_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> PrimitiveArray<T>
where
T: NativeType + Sub<Output = T>,
{
let rhs = *rhs;
unary(lhs, |a| a - rhs, lhs.data_type().clone())
}
pub fn wrapping_sub_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> PrimitiveArray<T>
where
T: NativeType + WrappingSub<Output = T>,
{
unary(lhs, |a| a.wrapping_sub(rhs), lhs.data_type().clone())
}
pub fn checked_sub_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> PrimitiveArray<T>
where
T: NativeType + CheckedSub<Output = T> + Zero,
{
let rhs = *rhs;
let op = move |a: T| a.checked_sub(&rhs);
unary_checked(lhs, op, lhs.data_type().clone())
}
pub fn saturating_sub_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> PrimitiveArray<T>
where
T: NativeType + SaturatingSub<Output = T>,
{
let rhs = *rhs;
let op = move |a: T| a.saturating_sub(&rhs);
unary(lhs, op, lhs.data_type().clone())
}
pub fn overflowing_sub_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> (PrimitiveArray<T>, Bitmap)
where
T: NativeType + OverflowingSub<Output = T>,
{
let rhs = *rhs;
let op = move |a: T| a.overflowing_sub(&rhs);
unary_with_bitmap(lhs, op, lhs.data_type().clone())
}
impl<T> ArraySub<T> for PrimitiveArray<T>
where
T: NativeType + Sub<Output = T> + NotI128,
{
type Output = Self;
fn sub(&self, rhs: &T) -> Result<Self::Output> {
Ok(sub_scalar(self, rhs))
}
}
impl<T> ArrayCheckedSub<T> for PrimitiveArray<T>
where
T: NativeType + CheckedSub<Output = T> + Zero + NotI128,
{
type Output = Self;
fn checked_sub(&self, rhs: &T) -> Result<Self::Output> {
Ok(checked_sub_scalar(self, rhs))
}
}
impl<T> ArraySaturatingSub<T> for PrimitiveArray<T>
where
T: NativeType + SaturatingSub<Output = T> + NotI128,
{
type Output = Self;
fn saturating_sub(&self, rhs: &T) -> Result<Self::Output> {
Ok(saturating_sub_scalar(self, rhs))
}
}
impl<T> ArrayOverflowingSub<T> for PrimitiveArray<T>
where
T: NativeType + OverflowingSub<Output = T> + NotI128,
{
type Output = Self;
fn overflowing_sub(&self, rhs: &T) -> Result<(Self::Output, Bitmap)> {
Ok(overflowing_sub_scalar(self, rhs))
}
}