Thanks to visit codestin.com
Credit goes to docs.rs

arrow2/compute/arithmetics/basic/
div.rs

1//! Definition of basic div operations with primitive arrays
2use std::ops::Div;
3
4use num_traits::{CheckedDiv, NumCast};
5
6use crate::datatypes::PrimitiveType;
7use crate::{
8    array::{Array, PrimitiveArray},
9    compute::{
10        arithmetics::{ArrayCheckedDiv, ArrayDiv},
11        arity::{binary, binary_checked, unary, unary_checked},
12        utils::check_same_len,
13    },
14};
15use strength_reduce::{
16    StrengthReducedU16, StrengthReducedU32, StrengthReducedU64, StrengthReducedU8,
17};
18
19use super::NativeArithmetics;
20
21/// Divides two primitive arrays with the same type.
22/// Panics if the divisor is zero of one pair of values overflows.
23///
24/// # Examples
25/// ```
26/// use arrow2::compute::arithmetics::basic::div;
27/// use arrow2::array::Int32Array;
28///
29/// let a = Int32Array::from(&[Some(10), Some(1), Some(6)]);
30/// let b = Int32Array::from(&[Some(5), None, Some(6)]);
31/// let result = div(&a, &b);
32/// let expected = Int32Array::from(&[Some(2), None, Some(1)]);
33/// assert_eq!(result, expected)
34/// ```
35pub fn div<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> PrimitiveArray<T>
36where
37    T: NativeArithmetics + Div<Output = T>,
38{
39    if rhs.null_count() == 0 {
40        binary(lhs, rhs, lhs.data_type().clone(), |a, b| a / b)
41    } else {
42        check_same_len(lhs, rhs).unwrap();
43        let values = lhs.iter().zip(rhs.iter()).map(|(l, r)| match (l, r) {
44            (Some(l), Some(r)) => Some(*l / *r),
45            _ => None,
46        });
47
48        PrimitiveArray::from_trusted_len_iter(values).to(lhs.data_type().clone())
49    }
50}
51
52/// Checked division of two primitive arrays. If the result from the division
53/// overflows, the result for the operation will change the validity array
54/// making this operation None
55///
56/// # Examples
57/// ```
58/// use arrow2::compute::arithmetics::basic::checked_div;
59/// use arrow2::array::Int8Array;
60///
61/// let a = Int8Array::from(&[Some(-100i8), Some(10i8)]);
62/// let b = Int8Array::from(&[Some(100i8), Some(0i8)]);
63/// let result = checked_div(&a, &b);
64/// let expected = Int8Array::from(&[Some(-1i8), None]);
65/// assert_eq!(result, expected);
66/// ```
67pub fn checked_div<T>(lhs: &PrimitiveArray<T>, rhs: &PrimitiveArray<T>) -> PrimitiveArray<T>
68where
69    T: NativeArithmetics + CheckedDiv<Output = T>,
70{
71    let op = move |a: T, b: T| a.checked_div(&b);
72
73    binary_checked(lhs, rhs, lhs.data_type().clone(), op)
74}
75
76// Implementation of ArrayDiv trait for PrimitiveArrays
77impl<T> ArrayDiv<PrimitiveArray<T>> for PrimitiveArray<T>
78where
79    T: NativeArithmetics + Div<Output = T>,
80{
81    fn div(&self, rhs: &PrimitiveArray<T>) -> Self {
82        div(self, rhs)
83    }
84}
85
86// Implementation of ArrayCheckedDiv trait for PrimitiveArrays
87impl<T> ArrayCheckedDiv<PrimitiveArray<T>> for PrimitiveArray<T>
88where
89    T: NativeArithmetics + CheckedDiv<Output = T>,
90{
91    fn checked_div(&self, rhs: &PrimitiveArray<T>) -> Self {
92        checked_div(self, rhs)
93    }
94}
95
96/// Divide a primitive array of type T by a scalar T.
97/// Panics if the divisor is zero.
98///
99/// # Examples
100/// ```
101/// use arrow2::compute::arithmetics::basic::div_scalar;
102/// use arrow2::array::Int32Array;
103///
104/// let a = Int32Array::from(&[None, Some(6), None, Some(6)]);
105/// let result = div_scalar(&a, &2i32);
106/// let expected = Int32Array::from(&[None, Some(3), None, Some(3)]);
107/// assert_eq!(result, expected)
108/// ```
109pub fn div_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> PrimitiveArray<T>
110where
111    T: NativeArithmetics + Div<Output = T> + NumCast,
112{
113    let rhs = *rhs;
114    match T::PRIMITIVE {
115        PrimitiveType::UInt64 => {
116            let lhs = lhs.as_any().downcast_ref::<PrimitiveArray<u64>>().unwrap();
117            let rhs = rhs.to_u64().unwrap();
118
119            let reduced_div = StrengthReducedU64::new(rhs);
120            let r = unary(lhs, |a| a / reduced_div, lhs.data_type().clone());
121            (&r as &dyn Array)
122                .as_any()
123                .downcast_ref::<PrimitiveArray<T>>()
124                .unwrap()
125                .clone()
126        }
127        PrimitiveType::UInt32 => {
128            let lhs = lhs.as_any().downcast_ref::<PrimitiveArray<u32>>().unwrap();
129            let rhs = rhs.to_u32().unwrap();
130
131            let reduced_div = StrengthReducedU32::new(rhs);
132            let r = unary(lhs, |a| a / reduced_div, lhs.data_type().clone());
133            (&r as &dyn Array)
134                .as_any()
135                .downcast_ref::<PrimitiveArray<T>>()
136                .unwrap()
137                .clone()
138        }
139        PrimitiveType::UInt16 => {
140            let lhs = lhs.as_any().downcast_ref::<PrimitiveArray<u16>>().unwrap();
141            let rhs = rhs.to_u16().unwrap();
142
143            let reduced_div = StrengthReducedU16::new(rhs);
144
145            let r = unary(lhs, |a| a / reduced_div, lhs.data_type().clone());
146            (&r as &dyn Array)
147                .as_any()
148                .downcast_ref::<PrimitiveArray<T>>()
149                .unwrap()
150                .clone()
151        }
152        PrimitiveType::UInt8 => {
153            let lhs = lhs.as_any().downcast_ref::<PrimitiveArray<u8>>().unwrap();
154            let rhs = rhs.to_u8().unwrap();
155
156            let reduced_div = StrengthReducedU8::new(rhs);
157            let r = unary(lhs, |a| a / reduced_div, lhs.data_type().clone());
158            (&r as &dyn Array)
159                .as_any()
160                .downcast_ref::<PrimitiveArray<T>>()
161                .unwrap()
162                .clone()
163        }
164        _ => unary(lhs, |a| a / rhs, lhs.data_type().clone()),
165    }
166}
167
168/// Checked division of a primitive array of type T by a scalar T. If the
169/// divisor is zero then the validity array is changed to None.
170///
171/// # Examples
172/// ```
173/// use arrow2::compute::arithmetics::basic::checked_div_scalar;
174/// use arrow2::array::Int8Array;
175///
176/// let a = Int8Array::from(&[Some(-100i8)]);
177/// let result = checked_div_scalar(&a, &100i8);
178/// let expected = Int8Array::from(&[Some(-1i8)]);
179/// assert_eq!(result, expected);
180/// ```
181pub fn checked_div_scalar<T>(lhs: &PrimitiveArray<T>, rhs: &T) -> PrimitiveArray<T>
182where
183    T: NativeArithmetics + CheckedDiv<Output = T>,
184{
185    let rhs = *rhs;
186    let op = move |a: T| a.checked_div(&rhs);
187
188    unary_checked(lhs, op, lhs.data_type().clone())
189}
190
191// Implementation of ArrayDiv trait for PrimitiveArrays with a scalar
192impl<T> ArrayDiv<T> for PrimitiveArray<T>
193where
194    T: NativeArithmetics + Div<Output = T> + NumCast,
195{
196    fn div(&self, rhs: &T) -> Self {
197        div_scalar(self, rhs)
198    }
199}
200
201// Implementation of ArrayCheckedDiv trait for PrimitiveArrays with a scalar
202impl<T> ArrayCheckedDiv<T> for PrimitiveArray<T>
203where
204    T: NativeArithmetics + CheckedDiv<Output = T>,
205{
206    fn checked_div(&self, rhs: &T) -> Self {
207        checked_div_scalar(self, rhs)
208    }
209}