use std::ops::Sub;
use num_traits::{ops::overflowing::OverflowingSub, CheckedSub, SaturatingSub, WrappingSub};
use crate::{
array::PrimitiveArray,
bitmap::Bitmap,
compute::{
arithmetics::{
ArrayCheckedSub, ArrayOverflowingSub, ArraySaturatingSub, ArraySub, ArrayWrappingSub,
},
arity::{
binary, binary_checked, binary_with_bitmap, unary, unary_checked, unary_with_bitmap,
},
},
};
use super::NativeArithmetics;
pub fn sub<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> PrimitiveArray<T>
where
T: NativeArithmetics + Sub<Output = T>,
{
binary(lhs, rhs, lhs.data_type().clone(), |a, b| a - b)
}
pub fn wrapping_sub<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> PrimitiveArray<T>
where
T: NativeArithmetics + WrappingSub<Output = T>,
{
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>) -> PrimitiveArray<T>
where
T: NativeArithmetics + CheckedSub<Output = T>,
{
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>) -> PrimitiveArray<T>
where
T: NativeArithmetics + SaturatingSub<Output = T>,
{
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>,
) -> (PrimitiveArray<T>, Bitmap)
where
T: NativeArithmetics + OverflowingSub<Output = T>,
{
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: NativeArithmetics + Sub<Output = T>,
{
fn sub(&self, rhs: &PrimitiveArray<T>) -> Self {
sub(self, rhs)
}
}
impl<T> ArrayWrappingSub<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeArithmetics + WrappingSub<Output = T>,
{
fn wrapping_sub(&self, rhs: &PrimitiveArray<T>) -> Self {
wrapping_sub(self, rhs)
}
}
impl<T> ArrayCheckedSub<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeArithmetics + CheckedSub<Output = T>,
{
fn checked_sub(&self, rhs: &PrimitiveArray<T>) -> Self {
checked_sub(self, rhs)
}
}
impl<T> ArraySaturatingSub<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeArithmetics + SaturatingSub<Output = T>,
{
fn saturating_sub(&self, rhs: &PrimitiveArray<T>) -> Self {
saturating_sub(self, rhs)
}
}
impl<T> ArrayOverflowingSub<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeArithmetics + OverflowingSub<Output = T>,
{
fn overflowing_sub(&self, rhs: &PrimitiveArray<T>) -> (Self, Bitmap) {
overflowing_sub(self, rhs)
}
}
pub fn sub_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> PrimitiveArray<T>
where
T: NativeArithmetics + 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: NativeArithmetics + 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: NativeArithmetics + CheckedSub<Output = T>,
{
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: NativeArithmetics + 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: NativeArithmetics + 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: NativeArithmetics + Sub<Output = T>,
{
fn sub(&self, rhs: &T) -> Self {
sub_scalar(self, rhs)
}
}
impl<T> ArrayCheckedSub<T> for PrimitiveArray<T>
where
T: NativeArithmetics + CheckedSub<Output = T>,
{
fn checked_sub(&self, rhs: &T) -> Self {
checked_sub_scalar(self, rhs)
}
}
impl<T> ArraySaturatingSub<T> for PrimitiveArray<T>
where
T: NativeArithmetics + SaturatingSub<Output = T>,
{
fn saturating_sub(&self, rhs: &T) -> Self {
saturating_sub_scalar(self, rhs)
}
}
impl<T> ArrayOverflowingSub<T> for PrimitiveArray<T>
where
T: NativeArithmetics + OverflowingSub<Output = T>,
{
fn overflowing_sub(&self, rhs: &T) -> (Self, Bitmap) {
overflowing_sub_scalar(self, rhs)
}
}