use std::ops::Add;
use num_traits::{ops::overflowing::OverflowingAdd, CheckedAdd, SaturatingAdd, WrappingAdd};
use crate::{
array::PrimitiveArray,
bitmap::Bitmap,
compute::{
arithmetics::{
ArrayAdd, ArrayCheckedAdd, ArrayOverflowingAdd, ArraySaturatingAdd, ArrayWrappingAdd,
},
arity::{
binary, binary_checked, binary_with_bitmap, unary, unary_checked, unary_with_bitmap,
},
},
};
use super::NativeArithmetics;
pub fn add<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> PrimitiveArray<T>
where
T: NativeArithmetics + Add<Output = T>,
{
binary(lhs, rhs, lhs.data_type().clone(), |a, b| a + b)
}
pub fn wrapping_add<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> PrimitiveArray<T>
where
T: NativeArithmetics + WrappingAdd<Output = T>,
{
let op = move |a: T, b: T| a.wrapping_add(&b);
binary(lhs, rhs, lhs.data_type().clone(), op)
}
pub fn checked_add<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> PrimitiveArray<T>
where
T: NativeArithmetics + CheckedAdd<Output = T>,
{
let op = move |a: T, b: T| a.checked_add(&b);
binary_checked(lhs, rhs, lhs.data_type().clone(), op)
}
pub fn saturating_add<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> PrimitiveArray<T>
where
T: NativeArithmetics + SaturatingAdd<Output = T>,
{
let op = move |a: T, b: T| a.saturating_add(&b);
binary(lhs, rhs, lhs.data_type().clone(), op)
}
pub fn overflowing_add<T>(
lhs: &PrimitiveArray<T>,
rhs: &PrimitiveArray<T>,
) -> (PrimitiveArray<T>, Bitmap)
where
T: NativeArithmetics + OverflowingAdd<Output = T>,
{
let op = move |a: T, b: T| a.overflowing_add(&b);
binary_with_bitmap(lhs, rhs, lhs.data_type().clone(), op)
}
impl<T> ArrayAdd<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeArithmetics + Add<Output = T>,
{
fn add(&self, rhs: &PrimitiveArray<T>) -> Self {
add(self, rhs)
}
}
impl<T> ArrayWrappingAdd<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeArithmetics + WrappingAdd<Output = T>,
{
fn wrapping_add(&self, rhs: &PrimitiveArray<T>) -> Self {
wrapping_add(self, rhs)
}
}
impl<T> ArrayCheckedAdd<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeArithmetics + CheckedAdd<Output = T>,
{
fn checked_add(&self, rhs: &PrimitiveArray<T>) -> Self {
checked_add(self, rhs)
}
}
impl<T> ArraySaturatingAdd<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeArithmetics + SaturatingAdd<Output = T>,
{
fn saturating_add(&self, rhs: &PrimitiveArray<T>) -> Self {
saturating_add(self, rhs)
}
}
impl<T> ArrayOverflowingAdd<PrimitiveArray<T>> for PrimitiveArray<T>
where
T: NativeArithmetics + OverflowingAdd<Output = T>,
{
fn overflowing_add(&self, rhs: &PrimitiveArray<T>) -> (Self, Bitmap) {
overflowing_add(self, rhs)
}
}
pub fn add_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> PrimitiveArray<T>
where
T: NativeArithmetics + Add<Output = T>,
{
let rhs = *rhs;
unary(lhs, |a| a + rhs, lhs.data_type().clone())
}
pub fn wrapping_add_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> PrimitiveArray<T>
where
T: NativeArithmetics + WrappingAdd<Output = T>,
{
unary(lhs, |a| a.wrapping_add(rhs), lhs.data_type().clone())
}
pub fn checked_add_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> PrimitiveArray<T>
where
T: NativeArithmetics + CheckedAdd<Output = T>,
{
let rhs = *rhs;
let op = move |a: T| a.checked_add(&rhs);
unary_checked(lhs, op, lhs.data_type().clone())
}
pub fn saturating_add_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> PrimitiveArray<T>
where
T: NativeArithmetics + SaturatingAdd<Output = T>,
{
let rhs = *rhs;
let op = move |a: T| a.saturating_add(&rhs);
unary(lhs, op, lhs.data_type().clone())
}
pub fn overflowing_add_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> (PrimitiveArray<T>, Bitmap)
where
T: NativeArithmetics + OverflowingAdd<Output = T>,
{
let rhs = *rhs;
let op = move |a: T| a.overflowing_add(&rhs);
unary_with_bitmap(lhs, op, lhs.data_type().clone())
}
impl<T> ArrayAdd<T> for PrimitiveArray<T>
where
T: NativeArithmetics + Add<Output = T>,
{
fn add(&self, rhs: &T) -> Self {
add_scalar(self, rhs)
}
}
impl<T> ArrayCheckedAdd<T> for PrimitiveArray<T>
where
T: NativeArithmetics + CheckedAdd<Output = T>,
{
fn checked_add(&self, rhs: &T) -> Self {
checked_add_scalar(self, rhs)
}
}
impl<T> ArraySaturatingAdd<T> for PrimitiveArray<T>
where
T: NativeArithmetics + SaturatingAdd<Output = T>,
{
fn saturating_add(&self, rhs: &T) -> Self {
saturating_add_scalar(self, rhs)
}
}
impl<T> ArrayOverflowingAdd<T> for PrimitiveArray<T>
where
T: NativeArithmetics + OverflowingAdd<Output = T>,
{
fn overflowing_add(&self, rhs: &T) -> (Self, Bitmap) {
overflowing_add_scalar(self, rhs)
}
}