1use std::cmp::Ordering;
21use std::fmt::Formatter;
22use std::sync::Arc;
23
24use arrow_array::cast::AsArray;
25use arrow_array::temporal_conversions::{NANOSECONDS, SECONDS_IN_DAY};
26use arrow_array::timezone::Tz;
27use arrow_array::types::*;
28use arrow_array::*;
29use arrow_buffer::{ArrowNativeType, IntervalDayTime, IntervalMonthDayNano};
30use arrow_schema::{ArrowError, DataType, IntervalUnit, TimeUnit};
31use num_traits::{CheckedMul, ToPrimitive};
32
33use crate::arity::{binary, try_binary};
34
35pub fn add(lhs: &dyn Datum, rhs: &dyn Datum) -> Result<ArrayRef, ArrowError> {
37 arithmetic_op(Op::Add, lhs, rhs)
38}
39
40pub fn add_wrapping(lhs: &dyn Datum, rhs: &dyn Datum) -> Result<ArrayRef, ArrowError> {
42 arithmetic_op(Op::AddWrapping, lhs, rhs)
43}
44
45pub fn sub(lhs: &dyn Datum, rhs: &dyn Datum) -> Result<ArrayRef, ArrowError> {
47 arithmetic_op(Op::Sub, lhs, rhs)
48}
49
50pub fn sub_wrapping(lhs: &dyn Datum, rhs: &dyn Datum) -> Result<ArrayRef, ArrowError> {
52 arithmetic_op(Op::SubWrapping, lhs, rhs)
53}
54
55pub fn mul(lhs: &dyn Datum, rhs: &dyn Datum) -> Result<ArrayRef, ArrowError> {
57 arithmetic_op(Op::Mul, lhs, rhs)
58}
59
60pub fn mul_wrapping(lhs: &dyn Datum, rhs: &dyn Datum) -> Result<ArrayRef, ArrowError> {
62 arithmetic_op(Op::MulWrapping, lhs, rhs)
63}
64
65pub fn div(lhs: &dyn Datum, rhs: &dyn Datum) -> Result<ArrayRef, ArrowError> {
70 arithmetic_op(Op::Div, lhs, rhs)
71}
72
73pub fn rem(lhs: &dyn Datum, rhs: &dyn Datum) -> Result<ArrayRef, ArrowError> {
80 arithmetic_op(Op::Rem, lhs, rhs)
81}
82
83macro_rules! neg_checked {
84 ($t:ty, $a:ident) => {{
85 let array = $a
86 .as_primitive::<$t>()
87 .try_unary::<_, $t, _>(|x| x.neg_checked())?;
88 Ok(Arc::new(array))
89 }};
90}
91
92macro_rules! neg_wrapping {
93 ($t:ty, $a:ident) => {{
94 let array = $a.as_primitive::<$t>().unary::<_, $t>(|x| x.neg_wrapping());
95 Ok(Arc::new(array))
96 }};
97}
98
99pub fn neg(array: &dyn Array) -> Result<ArrayRef, ArrowError> {
104 use DataType::*;
105 use IntervalUnit::*;
106 use TimeUnit::*;
107
108 match array.data_type() {
109 Int8 => neg_checked!(Int8Type, array),
110 Int16 => neg_checked!(Int16Type, array),
111 Int32 => neg_checked!(Int32Type, array),
112 Int64 => neg_checked!(Int64Type, array),
113 Float16 => neg_wrapping!(Float16Type, array),
114 Float32 => neg_wrapping!(Float32Type, array),
115 Float64 => neg_wrapping!(Float64Type, array),
116 Decimal32(p, s) => {
117 let a = array
118 .as_primitive::<Decimal32Type>()
119 .try_unary::<_, Decimal32Type, _>(|x| x.neg_checked())?;
120
121 Ok(Arc::new(a.with_precision_and_scale(*p, *s)?))
122 }
123 Decimal64(p, s) => {
124 let a = array
125 .as_primitive::<Decimal64Type>()
126 .try_unary::<_, Decimal64Type, _>(|x| x.neg_checked())?;
127
128 Ok(Arc::new(a.with_precision_and_scale(*p, *s)?))
129 }
130 Decimal128(p, s) => {
131 let a = array
132 .as_primitive::<Decimal128Type>()
133 .try_unary::<_, Decimal128Type, _>(|x| x.neg_checked())?;
134
135 Ok(Arc::new(a.with_precision_and_scale(*p, *s)?))
136 }
137 Decimal256(p, s) => {
138 let a = array
139 .as_primitive::<Decimal256Type>()
140 .try_unary::<_, Decimal256Type, _>(|x| x.neg_checked())?;
141
142 Ok(Arc::new(a.with_precision_and_scale(*p, *s)?))
143 }
144 Duration(Second) => neg_checked!(DurationSecondType, array),
145 Duration(Millisecond) => neg_checked!(DurationMillisecondType, array),
146 Duration(Microsecond) => neg_checked!(DurationMicrosecondType, array),
147 Duration(Nanosecond) => neg_checked!(DurationNanosecondType, array),
148 Interval(YearMonth) => neg_checked!(IntervalYearMonthType, array),
149 Interval(DayTime) => {
150 let a = array
151 .as_primitive::<IntervalDayTimeType>()
152 .try_unary::<_, IntervalDayTimeType, ArrowError>(|x| {
153 let (days, ms) = IntervalDayTimeType::to_parts(x);
154 Ok(IntervalDayTimeType::make_value(
155 days.neg_checked()?,
156 ms.neg_checked()?,
157 ))
158 })?;
159 Ok(Arc::new(a))
160 }
161 Interval(MonthDayNano) => {
162 let a = array
163 .as_primitive::<IntervalMonthDayNanoType>()
164 .try_unary::<_, IntervalMonthDayNanoType, ArrowError>(|x| {
165 let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(x);
166 Ok(IntervalMonthDayNanoType::make_value(
167 months.neg_checked()?,
168 days.neg_checked()?,
169 nanos.neg_checked()?,
170 ))
171 })?;
172 Ok(Arc::new(a))
173 }
174 t => Err(ArrowError::InvalidArgumentError(format!(
175 "Invalid arithmetic operation: !{t}"
176 ))),
177 }
178}
179
180pub fn neg_wrapping(array: &dyn Array) -> Result<ArrayRef, ArrowError> {
182 downcast_integer! {
183 array.data_type() => (neg_wrapping, array),
184 _ => neg(array),
185 }
186}
187
188#[derive(Debug, Copy, Clone)]
192enum Op {
193 AddWrapping,
194 Add,
195 SubWrapping,
196 Sub,
197 MulWrapping,
198 Mul,
199 Div,
200 Rem,
201}
202
203impl std::fmt::Display for Op {
204 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
205 match self {
206 Op::AddWrapping | Op::Add => write!(f, "+"),
207 Op::SubWrapping | Op::Sub => write!(f, "-"),
208 Op::MulWrapping | Op::Mul => write!(f, "*"),
209 Op::Div => write!(f, "/"),
210 Op::Rem => write!(f, "%"),
211 }
212 }
213}
214
215impl Op {
216 fn commutative(&self) -> bool {
217 matches!(
218 self,
219 Self::Add | Self::AddWrapping | Self::Mul | Self::MulWrapping
220 )
221 }
222}
223
224fn arithmetic_op(op: Op, lhs: &dyn Datum, rhs: &dyn Datum) -> Result<ArrayRef, ArrowError> {
226 use DataType::*;
227 use IntervalUnit::*;
228 use TimeUnit::*;
229
230 macro_rules! integer_helper {
231 ($t:ty, $op:ident, $l:ident, $l_scalar:ident, $r:ident, $r_scalar:ident) => {
232 integer_op::<$t>($op, $l, $l_scalar, $r, $r_scalar)
233 };
234 }
235
236 let (l, l_scalar) = lhs.get();
237 let (r, r_scalar) = rhs.get();
238 downcast_integer! {
239 l.data_type(), r.data_type() => (integer_helper, op, l, l_scalar, r, r_scalar),
240 (Float16, Float16) => float_op::<Float16Type>(op, l, l_scalar, r, r_scalar),
241 (Float32, Float32) => float_op::<Float32Type>(op, l, l_scalar, r, r_scalar),
242 (Float64, Float64) => float_op::<Float64Type>(op, l, l_scalar, r, r_scalar),
243 (Timestamp(Second, _), _) => timestamp_op::<TimestampSecondType>(op, l, l_scalar, r, r_scalar),
244 (Timestamp(Millisecond, _), _) => timestamp_op::<TimestampMillisecondType>(op, l, l_scalar, r, r_scalar),
245 (Timestamp(Microsecond, _), _) => timestamp_op::<TimestampMicrosecondType>(op, l, l_scalar, r, r_scalar),
246 (Timestamp(Nanosecond, _), _) => timestamp_op::<TimestampNanosecondType>(op, l, l_scalar, r, r_scalar),
247 (Duration(Second), Duration(Second)) => duration_op::<DurationSecondType>(op, l, l_scalar, r, r_scalar),
248 (Duration(Millisecond), Duration(Millisecond)) => duration_op::<DurationMillisecondType>(op, l, l_scalar, r, r_scalar),
249 (Duration(Microsecond), Duration(Microsecond)) => duration_op::<DurationMicrosecondType>(op, l, l_scalar, r, r_scalar),
250 (Duration(Nanosecond), Duration(Nanosecond)) => duration_op::<DurationNanosecondType>(op, l, l_scalar, r, r_scalar),
251 (Interval(YearMonth), Interval(YearMonth) | Int64) => interval_op::<IntervalYearMonthType>(op, l, l_scalar, r, r_scalar),
252 (Interval(DayTime), Interval(DayTime) | Int64) => interval_op::<IntervalDayTimeType>(op, l, l_scalar, r, r_scalar),
253 (Interval(MonthDayNano), Interval(MonthDayNano) | Int64) => interval_op::<IntervalMonthDayNanoType>(op, l, l_scalar, r, r_scalar),
254 (Interval(MonthDayNano), Float64) => interval_f64_op(op, l, l_scalar, r, r_scalar),
255 (Date32, _) => date_op::<Date32Type>(op, l, l_scalar, r, r_scalar),
256 (Date64, _) => date_op::<Date64Type>(op, l, l_scalar, r, r_scalar),
257 (Decimal32(_, _), Decimal32(_, _)) => decimal_op::<Decimal32Type>(op, l, l_scalar, r, r_scalar),
258 (Decimal64(_, _), Decimal64(_, _)) => decimal_op::<Decimal64Type>(op, l, l_scalar, r, r_scalar),
259 (Decimal128(_, _), Decimal128(_, _)) => decimal_op::<Decimal128Type>(op, l, l_scalar, r, r_scalar),
260 (Decimal256(_, _), Decimal256(_, _)) => decimal_op::<Decimal256Type>(op, l, l_scalar, r, r_scalar),
261 (l_t, r_t) => match (l_t, r_t) {
262 (Duration(_) | Interval(_), Date32 | Date64 | Timestamp(_, _)) if op.commutative() => {
263 arithmetic_op(op, rhs, lhs)
264 }
265 (Int64, Interval(_)) | (Float64, Interval(MonthDayNano))
266 if matches!(op, Op::Mul) =>
267 {
268 arithmetic_op(op, rhs, lhs)
269 }
270 _ => Err(ArrowError::InvalidArgumentError(
271 format!("Invalid arithmetic operation: {l_t} {op} {r_t}")
272 ))
273 }
274 }
275}
276
277macro_rules! op {
279 ($l:ident, $l_s:expr, $r:ident, $r_s:expr, $op:expr) => {
280 match ($l_s, $r_s) {
281 (true, true) | (false, false) => binary($l, $r, |$l, $r| $op)?,
282 (true, false) => match ($l.null_count() == 0).then(|| $l.value(0)) {
283 None => PrimitiveArray::new_null($r.len()),
284 Some($l) => $r.unary(|$r| $op),
285 },
286 (false, true) => match ($r.null_count() == 0).then(|| $r.value(0)) {
287 None => PrimitiveArray::new_null($l.len()),
288 Some($r) => $l.unary(|$l| $op),
289 },
290 }
291 };
292}
293
294macro_rules! op_ref {
296 ($t:ty, $l:ident, $l_s:expr, $r:ident, $r_s:expr, $op:expr) => {{
297 let array: PrimitiveArray<$t> = op!($l, $l_s, $r, $r_s, $op);
298 Arc::new(array)
299 }};
300}
301
302macro_rules! try_op {
304 ($l:ident, $l_s:expr, $r:ident, $r_s:expr, $op:expr) => {
305 match ($l_s, $r_s) {
306 (true, true) | (false, false) => try_binary($l, $r, |$l, $r| $op)?,
307 (true, false) => match ($l.null_count() == 0).then(|| $l.value(0)) {
308 None => PrimitiveArray::new_null($r.len()),
309 Some($l) => $r.try_unary(|$r| $op)?,
310 },
311 (false, true) => match ($r.null_count() == 0).then(|| $r.value(0)) {
312 None => PrimitiveArray::new_null($l.len()),
313 Some($r) => $l.try_unary(|$l| $op)?,
314 },
315 }
316 };
317}
318
319macro_rules! try_op_ref {
321 ($t:ty, $l:ident, $l_s:expr, $r:ident, $r_s:expr, $op:expr) => {{
322 let array: PrimitiveArray<$t> = try_op!($l, $l_s, $r, $r_s, $op);
323 Arc::new(array)
324 }};
325}
326
327fn integer_op<T: ArrowPrimitiveType>(
329 op: Op,
330 l: &dyn Array,
331 l_s: bool,
332 r: &dyn Array,
333 r_s: bool,
334) -> Result<ArrayRef, ArrowError> {
335 let l = l.as_primitive::<T>();
336 let r = r.as_primitive::<T>();
337 let array: PrimitiveArray<T> = match op {
338 Op::AddWrapping => op!(l, l_s, r, r_s, l.add_wrapping(r)),
339 Op::Add => try_op!(l, l_s, r, r_s, l.add_checked(r)),
340 Op::SubWrapping => op!(l, l_s, r, r_s, l.sub_wrapping(r)),
341 Op::Sub => try_op!(l, l_s, r, r_s, l.sub_checked(r)),
342 Op::MulWrapping => op!(l, l_s, r, r_s, l.mul_wrapping(r)),
343 Op::Mul => try_op!(l, l_s, r, r_s, l.mul_checked(r)),
344 Op::Div => try_op!(l, l_s, r, r_s, l.div_checked(r)),
345 Op::Rem => try_op!(l, l_s, r, r_s, {
346 if r.is_zero() {
347 Err(ArrowError::DivideByZero)
348 } else {
349 Ok(l.mod_wrapping(r))
350 }
351 }),
352 };
353 Ok(Arc::new(array))
354}
355
356fn float_op<T: ArrowPrimitiveType>(
358 op: Op,
359 l: &dyn Array,
360 l_s: bool,
361 r: &dyn Array,
362 r_s: bool,
363) -> Result<ArrayRef, ArrowError> {
364 let l = l.as_primitive::<T>();
365 let r = r.as_primitive::<T>();
366 let array: PrimitiveArray<T> = match op {
367 Op::AddWrapping | Op::Add => op!(l, l_s, r, r_s, l.add_wrapping(r)),
368 Op::SubWrapping | Op::Sub => op!(l, l_s, r, r_s, l.sub_wrapping(r)),
369 Op::MulWrapping | Op::Mul => op!(l, l_s, r, r_s, l.mul_wrapping(r)),
370 Op::Div => op!(l, l_s, r, r_s, l.div_wrapping(r)),
371 Op::Rem => op!(l, l_s, r, r_s, l.mod_wrapping(r)),
372 };
373 Ok(Arc::new(array))
374}
375
376trait TimestampOp: ArrowTimestampType {
378 type Duration: ArrowPrimitiveType<Native = i64>;
379
380 fn add_year_month(timestamp: i64, delta: i32, tz: Tz) -> Option<i64>;
381 fn add_day_time(timestamp: i64, delta: IntervalDayTime, tz: Tz) -> Option<i64>;
382 fn add_month_day_nano(timestamp: i64, delta: IntervalMonthDayNano, tz: Tz) -> Option<i64>;
383
384 fn sub_year_month(timestamp: i64, delta: i32, tz: Tz) -> Option<i64>;
385 fn sub_day_time(timestamp: i64, delta: IntervalDayTime, tz: Tz) -> Option<i64>;
386 fn sub_month_day_nano(timestamp: i64, delta: IntervalMonthDayNano, tz: Tz) -> Option<i64>;
387}
388
389macro_rules! timestamp {
390 ($t:ty, $d:ty) => {
391 impl TimestampOp for $t {
392 type Duration = $d;
393
394 fn add_year_month(left: i64, right: i32, tz: Tz) -> Option<i64> {
395 Self::add_year_months(left, right, tz)
396 }
397
398 fn add_day_time(left: i64, right: IntervalDayTime, tz: Tz) -> Option<i64> {
399 Self::add_day_time(left, right, tz)
400 }
401
402 fn add_month_day_nano(left: i64, right: IntervalMonthDayNano, tz: Tz) -> Option<i64> {
403 Self::add_month_day_nano(left, right, tz)
404 }
405
406 fn sub_year_month(left: i64, right: i32, tz: Tz) -> Option<i64> {
407 Self::subtract_year_months(left, right, tz)
408 }
409
410 fn sub_day_time(left: i64, right: IntervalDayTime, tz: Tz) -> Option<i64> {
411 Self::subtract_day_time(left, right, tz)
412 }
413
414 fn sub_month_day_nano(left: i64, right: IntervalMonthDayNano, tz: Tz) -> Option<i64> {
415 Self::subtract_month_day_nano(left, right, tz)
416 }
417 }
418 };
419}
420timestamp!(TimestampSecondType, DurationSecondType);
421timestamp!(TimestampMillisecondType, DurationMillisecondType);
422timestamp!(TimestampMicrosecondType, DurationMicrosecondType);
423timestamp!(TimestampNanosecondType, DurationNanosecondType);
424
425fn timestamp_op<T: TimestampOp>(
427 op: Op,
428 l: &dyn Array,
429 l_s: bool,
430 r: &dyn Array,
431 r_s: bool,
432) -> Result<ArrayRef, ArrowError> {
433 use DataType::*;
434 use IntervalUnit::*;
435
436 let l = l.as_primitive::<T>();
437 let l_tz: Tz = l.timezone().unwrap_or("+00:00").parse()?;
438
439 let array: PrimitiveArray<T> = match (op, r.data_type()) {
440 (Op::Sub | Op::SubWrapping, Timestamp(unit, _)) if unit == &T::UNIT => {
441 let r = r.as_primitive::<T>();
442 return Ok(try_op_ref!(T::Duration, l, l_s, r, r_s, l.sub_checked(r)));
443 }
444
445 (Op::Add | Op::AddWrapping, Duration(unit)) if unit == &T::UNIT => {
446 let r = r.as_primitive::<T::Duration>();
447 try_op!(l, l_s, r, r_s, l.add_checked(r))
448 }
449 (Op::Sub | Op::SubWrapping, Duration(unit)) if unit == &T::UNIT => {
450 let r = r.as_primitive::<T::Duration>();
451 try_op!(l, l_s, r, r_s, l.sub_checked(r))
452 }
453
454 (Op::Add | Op::AddWrapping, Interval(YearMonth)) => {
455 let r = r.as_primitive::<IntervalYearMonthType>();
456 try_op!(
457 l,
458 l_s,
459 r,
460 r_s,
461 T::add_year_month(l, r, l_tz).ok_or(ArrowError::ComputeError(
462 "Timestamp out of range".to_string()
463 ))
464 )
465 }
466 (Op::Sub | Op::SubWrapping, Interval(YearMonth)) => {
467 let r = r.as_primitive::<IntervalYearMonthType>();
468 try_op!(
469 l,
470 l_s,
471 r,
472 r_s,
473 T::sub_year_month(l, r, l_tz).ok_or(ArrowError::ComputeError(
474 "Timestamp out of range".to_string()
475 ))
476 )
477 }
478
479 (Op::Add | Op::AddWrapping, Interval(DayTime)) => {
480 let r = r.as_primitive::<IntervalDayTimeType>();
481 try_op!(
482 l,
483 l_s,
484 r,
485 r_s,
486 T::add_day_time(l, r, l_tz).ok_or(ArrowError::ComputeError(
487 "Timestamp out of range".to_string()
488 ))
489 )
490 }
491 (Op::Sub | Op::SubWrapping, Interval(DayTime)) => {
492 let r = r.as_primitive::<IntervalDayTimeType>();
493 try_op!(
494 l,
495 l_s,
496 r,
497 r_s,
498 T::sub_day_time(l, r, l_tz).ok_or(ArrowError::ComputeError(
499 "Timestamp out of range".to_string()
500 ))
501 )
502 }
503
504 (Op::Add | Op::AddWrapping, Interval(MonthDayNano)) => {
505 let r = r.as_primitive::<IntervalMonthDayNanoType>();
506 try_op!(
507 l,
508 l_s,
509 r,
510 r_s,
511 T::add_month_day_nano(l, r, l_tz).ok_or(ArrowError::ComputeError(
512 "Timestamp out of range".to_string()
513 ))
514 )
515 }
516 (Op::Sub | Op::SubWrapping, Interval(MonthDayNano)) => {
517 let r = r.as_primitive::<IntervalMonthDayNanoType>();
518 try_op!(
519 l,
520 l_s,
521 r,
522 r_s,
523 T::sub_month_day_nano(l, r, l_tz).ok_or(ArrowError::ComputeError(
524 "Timestamp out of range".to_string()
525 ))
526 )
527 }
528 _ => {
529 return Err(ArrowError::InvalidArgumentError(format!(
530 "Invalid timestamp arithmetic operation: {} {op} {}",
531 l.data_type(),
532 r.data_type()
533 )));
534 }
535 };
536 Ok(Arc::new(array.with_timezone_opt(l.timezone())))
537}
538
539trait DateOp: ArrowTemporalType {
541 fn add_year_month(timestamp: Self::Native, delta: i32) -> Result<Self::Native, ArrowError>;
542 fn add_day_time(
543 timestamp: Self::Native,
544 delta: IntervalDayTime,
545 ) -> Result<Self::Native, ArrowError>;
546 fn add_month_day_nano(
547 timestamp: Self::Native,
548 delta: IntervalMonthDayNano,
549 ) -> Result<Self::Native, ArrowError>;
550
551 fn sub_year_month(timestamp: Self::Native, delta: i32) -> Result<Self::Native, ArrowError>;
552 fn sub_day_time(
553 timestamp: Self::Native,
554 delta: IntervalDayTime,
555 ) -> Result<Self::Native, ArrowError>;
556 fn sub_month_day_nano(
557 timestamp: Self::Native,
558 delta: IntervalMonthDayNano,
559 ) -> Result<Self::Native, ArrowError>;
560}
561
562macro_rules! date {
563 ($t:ty) => {
564 impl DateOp for $t {
565 fn add_year_month(left: Self::Native, right: i32) -> Result<Self::Native, ArrowError> {
566 Self::add_year_months_opt(left, right).ok_or_else(|| {
567 ArrowError::ComputeError(format!(
568 "Date arithmetic overflow: {left} + {right} months"
569 ))
570 })
571 }
572
573 fn add_day_time(
574 left: Self::Native,
575 right: IntervalDayTime,
576 ) -> Result<Self::Native, ArrowError> {
577 Self::add_day_time_opt(left, right).ok_or_else(|| {
578 ArrowError::ComputeError(format!(
579 "Date arithmetic overflow: {left} + {right:?}"
580 ))
581 })
582 }
583
584 fn add_month_day_nano(
585 left: Self::Native,
586 right: IntervalMonthDayNano,
587 ) -> Result<Self::Native, ArrowError> {
588 Self::add_month_day_nano_opt(left, right).ok_or_else(|| {
589 ArrowError::ComputeError(format!(
590 "Date arithmetic overflow: {left} + {right:?}"
591 ))
592 })
593 }
594
595 fn sub_year_month(left: Self::Native, right: i32) -> Result<Self::Native, ArrowError> {
596 Self::subtract_year_months_opt(left, right).ok_or_else(|| {
597 ArrowError::ComputeError(format!(
598 "Date arithmetic overflow: {left} - {right} months"
599 ))
600 })
601 }
602
603 fn sub_day_time(
604 left: Self::Native,
605 right: IntervalDayTime,
606 ) -> Result<Self::Native, ArrowError> {
607 Self::subtract_day_time_opt(left, right).ok_or_else(|| {
608 ArrowError::ComputeError(format!(
609 "Date arithmetic overflow: {left} - {right:?}"
610 ))
611 })
612 }
613
614 fn sub_month_day_nano(
615 left: Self::Native,
616 right: IntervalMonthDayNano,
617 ) -> Result<Self::Native, ArrowError> {
618 Self::subtract_month_day_nano_opt(left, right).ok_or_else(|| {
619 ArrowError::ComputeError(format!(
620 "Date arithmetic overflow: {left} - {right:?}"
621 ))
622 })
623 }
624 }
625 };
626}
627
628date!(Date32Type);
629date!(Date64Type);
630
631trait IntervalOp: ArrowPrimitiveType {
633 fn add(left: Self::Native, right: Self::Native) -> Result<Self::Native, ArrowError>;
634 fn sub(left: Self::Native, right: Self::Native) -> Result<Self::Native, ArrowError>;
635 fn mul_i64(left: Self::Native, right: i64) -> Result<Self::Native, ArrowError>;
636}
637
638fn mul_i32_i64(left: i32, right: i64) -> Result<i32, ArrowError> {
639 let value = i64::from(left).mul_checked(right)?;
640 i32::try_from(value).map_err(|_| {
641 ArrowError::ArithmeticOverflow(format!("Overflow happened on: {left} * {right}"))
642 })
643}
644
645impl IntervalOp for IntervalYearMonthType {
646 fn add(left: Self::Native, right: Self::Native) -> Result<Self::Native, ArrowError> {
647 left.add_checked(right)
648 }
649
650 fn sub(left: Self::Native, right: Self::Native) -> Result<Self::Native, ArrowError> {
651 left.sub_checked(right)
652 }
653
654 fn mul_i64(left: Self::Native, right: i64) -> Result<Self::Native, ArrowError> {
655 mul_i32_i64(left, right)
656 }
657}
658
659impl IntervalOp for IntervalDayTimeType {
660 fn add(left: Self::Native, right: Self::Native) -> Result<Self::Native, ArrowError> {
661 let (l_days, l_ms) = Self::to_parts(left);
662 let (r_days, r_ms) = Self::to_parts(right);
663 let days = l_days.add_checked(r_days)?;
664 let ms = l_ms.add_checked(r_ms)?;
665 Ok(Self::make_value(days, ms))
666 }
667
668 fn sub(left: Self::Native, right: Self::Native) -> Result<Self::Native, ArrowError> {
669 let (l_days, l_ms) = Self::to_parts(left);
670 let (r_days, r_ms) = Self::to_parts(right);
671 let days = l_days.sub_checked(r_days)?;
672 let ms = l_ms.sub_checked(r_ms)?;
673 Ok(Self::make_value(days, ms))
674 }
675
676 fn mul_i64(left: Self::Native, right: i64) -> Result<Self::Native, ArrowError> {
677 let (days, ms) = Self::to_parts(left);
678 Ok(Self::make_value(
679 mul_i32_i64(days, right)?,
680 mul_i32_i64(ms, right)?,
681 ))
682 }
683}
684
685impl IntervalOp for IntervalMonthDayNanoType {
686 fn add(left: Self::Native, right: Self::Native) -> Result<Self::Native, ArrowError> {
687 let (l_months, l_days, l_nanos) = Self::to_parts(left);
688 let (r_months, r_days, r_nanos) = Self::to_parts(right);
689 let months = l_months.add_checked(r_months)?;
690 let days = l_days.add_checked(r_days)?;
691 let nanos = l_nanos.add_checked(r_nanos)?;
692 Ok(Self::make_value(months, days, nanos))
693 }
694
695 fn sub(left: Self::Native, right: Self::Native) -> Result<Self::Native, ArrowError> {
696 let (l_months, l_days, l_nanos) = Self::to_parts(left);
697 let (r_months, r_days, r_nanos) = Self::to_parts(right);
698 let months = l_months.sub_checked(r_months)?;
699 let days = l_days.sub_checked(r_days)?;
700 let nanos = l_nanos.sub_checked(r_nanos)?;
701 Ok(Self::make_value(months, days, nanos))
702 }
703
704 fn mul_i64(left: Self::Native, right: i64) -> Result<Self::Native, ArrowError> {
705 let (months, days, nanos) = Self::to_parts(left);
706 Ok(Self::make_value(
707 mul_i32_i64(months, right)?,
708 mul_i32_i64(days, right)?,
709 nanos.mul_checked(right)?,
710 ))
711 }
712}
713
714fn interval_mul_op<T: IntervalOp>(
715 interval: &dyn Array,
716 interval_scalar: bool,
717 factor: &dyn Array,
718 factor_scalar: bool,
719) -> Result<ArrayRef, ArrowError> {
720 let interval = interval.as_primitive::<T>();
721 let factor = factor.as_primitive::<Int64Type>();
722 Ok(try_op_ref!(
723 T,
724 interval,
725 interval_scalar,
726 factor,
727 factor_scalar,
728 T::mul_i64(interval, factor)
729 ))
730}
731
732fn interval_mul_f64(
748 interval: IntervalMonthDayNano,
749 factor: f64,
750) -> Result<IntervalMonthDayNano, ArrowError> {
751 const DAYS_PER_MONTH: f64 = 30.;
752 const NANOS_PER_SECOND: f64 = NANOSECONDS as f64;
753 const SECONDS_PER_DAY: f64 = SECONDS_IN_DAY as f64;
754
755 if factor.fract() == 0.
757 && let Some(factor) = ToPrimitive::to_i64(&factor)
758 {
759 return IntervalMonthDayNanoType::mul_i64(interval, factor);
760 }
761
762 let overflow =
767 |component| ArrowError::ArithmeticOverflow(format!("Overflow in interval {component}"));
768 let timestamp_round =
769 |value: f64| (value * NANOS_PER_SECOND).round_ties_even() / NANOS_PER_SECOND;
770
771 let months_product = f64::from(interval.months) * factor;
772 if !months_product.is_finite()
773 || months_product < f64::from(i32::MIN)
774 || months_product > f64::from(i32::MAX)
775 {
776 return Err(overflow("months"));
777 }
778 let months = months_product.to_i32().ok_or_else(|| overflow("months"))?;
779
780 let days_product = f64::from(interval.days) * factor;
781 if !days_product.is_finite()
782 || days_product < f64::from(i32::MIN)
783 || days_product > f64::from(i32::MAX)
784 {
785 return Err(overflow("days"));
786 }
787 let mut days = days_product.to_i32().ok_or_else(|| overflow("days"))?;
788
789 let month_remainder = timestamp_round(months_product.fract() * DAYS_PER_MONTH);
790 let month_remainder_days = month_remainder
791 .to_i32()
792 .ok_or_else(|| overflow("month remainder"))?;
793 let mut seconds_remainder =
794 timestamp_round((days_product.fract() + month_remainder.fract()) * SECONDS_PER_DAY);
795
796 if seconds_remainder.abs() >= SECONDS_PER_DAY {
797 let remainder_days = (seconds_remainder / SECONDS_PER_DAY)
798 .to_i32()
799 .ok_or_else(|| overflow("day remainder"))?;
800 days = days
801 .checked_add(remainder_days)
802 .ok_or_else(|| overflow("days"))?;
803 seconds_remainder -= f64::from(remainder_days) * SECONDS_PER_DAY;
804 }
805 days = days
806 .checked_add(month_remainder_days)
807 .ok_or_else(|| overflow("days"))?;
808
809 let nanoseconds = ((interval.nanoseconds as f64) * factor
810 + seconds_remainder * NANOS_PER_SECOND)
811 .round_ties_even();
812 let nanoseconds = ToPrimitive::to_i64(&nanoseconds).ok_or_else(|| {
813 ArrowError::ArithmeticOverflow(format!("Overflow in interval nanoseconds: {nanoseconds}"))
814 })?;
815
816 Ok(IntervalMonthDayNano::new(months, days, nanoseconds))
817}
818
819fn interval_f64_op(
820 op: Op,
821 interval: &dyn Array,
822 interval_scalar: bool,
823 factor: &dyn Array,
824 factor_scalar: bool,
825) -> Result<ArrayRef, ArrowError> {
826 let interval = interval.as_primitive::<IntervalMonthDayNanoType>();
827 let factor = factor.as_primitive::<Float64Type>();
828 Ok(try_op_ref!(
829 IntervalMonthDayNanoType,
830 interval,
831 interval_scalar,
832 factor,
833 factor_scalar,
834 {
835 match op {
836 Op::Mul => interval_mul_f64(interval, factor),
837 Op::Div if factor == 0. => Err(ArrowError::DivideByZero),
838 Op::Div => interval_mul_f64(interval, 1. / factor),
841 _ => Err(ArrowError::InvalidArgumentError(format!(
842 "Invalid interval arithmetic operation: Interval(MonthDayNano) {op} Float64"
843 ))),
844 }
845 }
846 ))
847}
848
849fn interval_op<T: IntervalOp>(
851 op: Op,
852 l: &dyn Array,
853 l_s: bool,
854 r: &dyn Array,
855 r_s: bool,
856) -> Result<ArrayRef, ArrowError> {
857 match (op, r.data_type()) {
858 (Op::Add | Op::AddWrapping, data_type) if data_type == l.data_type() => {
859 let l = l.as_primitive::<T>();
860 let r = r.as_primitive::<T>();
861 Ok(try_op_ref!(T, l, l_s, r, r_s, T::add(l, r)))
862 }
863 (Op::Sub | Op::SubWrapping, data_type) if data_type == l.data_type() => {
864 let l = l.as_primitive::<T>();
865 let r = r.as_primitive::<T>();
866 Ok(try_op_ref!(T, l, l_s, r, r_s, T::sub(l, r)))
867 }
868 (Op::Mul, DataType::Int64) => interval_mul_op::<T>(l, l_s, r, r_s),
869 _ => Err(ArrowError::InvalidArgumentError(format!(
870 "Invalid interval arithmetic operation: {} {op} {}",
871 l.data_type(),
872 r.data_type()
873 ))),
874 }
875}
876
877fn duration_op<T: ArrowPrimitiveType>(
878 op: Op,
879 l: &dyn Array,
880 l_s: bool,
881 r: &dyn Array,
882 r_s: bool,
883) -> Result<ArrayRef, ArrowError> {
884 let l = l.as_primitive::<T>();
885 let r = r.as_primitive::<T>();
886 match op {
887 Op::Add | Op::AddWrapping => Ok(try_op_ref!(T, l, l_s, r, r_s, l.add_checked(r))),
888 Op::Sub | Op::SubWrapping => Ok(try_op_ref!(T, l, l_s, r, r_s, l.sub_checked(r))),
889 _ => Err(ArrowError::InvalidArgumentError(format!(
890 "Invalid duration arithmetic operation: {} {op} {}",
891 l.data_type(),
892 r.data_type()
893 ))),
894 }
895}
896
897fn date_op<T: DateOp>(
899 op: Op,
900 l: &dyn Array,
901 l_s: bool,
902 r: &dyn Array,
903 r_s: bool,
904) -> Result<ArrayRef, ArrowError> {
905 use DataType::*;
906 use IntervalUnit::*;
907
908 const NUM_SECONDS_IN_DAY: i64 = 60 * 60 * 24;
909
910 let r_t = r.data_type();
911 match (T::DATA_TYPE, op, r_t) {
912 (Date32, Op::Sub | Op::SubWrapping, Date32) => {
913 let l = l.as_primitive::<Date32Type>();
914 let r = r.as_primitive::<Date32Type>();
915 return Ok(op_ref!(
916 DurationSecondType,
917 l,
918 l_s,
919 r,
920 r_s,
921 ((l as i64) - (r as i64)) * NUM_SECONDS_IN_DAY
922 ));
923 }
924 (Date64, Op::Sub | Op::SubWrapping, Date64) => {
925 let l = l.as_primitive::<Date64Type>();
926 let r = r.as_primitive::<Date64Type>();
927 let result = try_op_ref!(DurationMillisecondType, l, l_s, r, r_s, l.sub_checked(r));
928 return Ok(result);
929 }
930 _ => {}
931 }
932
933 let l = l.as_primitive::<T>();
934 match (op, r_t) {
935 (Op::Add | Op::AddWrapping, Interval(YearMonth)) => {
936 let r = r.as_primitive::<IntervalYearMonthType>();
937 Ok(try_op_ref!(T, l, l_s, r, r_s, T::add_year_month(l, r)))
938 }
939 (Op::Sub | Op::SubWrapping, Interval(YearMonth)) => {
940 let r = r.as_primitive::<IntervalYearMonthType>();
941 Ok(try_op_ref!(T, l, l_s, r, r_s, T::sub_year_month(l, r)))
942 }
943
944 (Op::Add | Op::AddWrapping, Interval(DayTime)) => {
945 let r = r.as_primitive::<IntervalDayTimeType>();
946 Ok(try_op_ref!(T, l, l_s, r, r_s, T::add_day_time(l, r)))
947 }
948 (Op::Sub | Op::SubWrapping, Interval(DayTime)) => {
949 let r = r.as_primitive::<IntervalDayTimeType>();
950 Ok(try_op_ref!(T, l, l_s, r, r_s, T::sub_day_time(l, r)))
951 }
952
953 (Op::Add | Op::AddWrapping, Interval(MonthDayNano)) => {
954 let r = r.as_primitive::<IntervalMonthDayNanoType>();
955 Ok(try_op_ref!(T, l, l_s, r, r_s, T::add_month_day_nano(l, r)))
956 }
957 (Op::Sub | Op::SubWrapping, Interval(MonthDayNano)) => {
958 let r = r.as_primitive::<IntervalMonthDayNanoType>();
959 Ok(try_op_ref!(T, l, l_s, r, r_s, T::sub_month_day_nano(l, r)))
960 }
961
962 _ => Err(ArrowError::InvalidArgumentError(format!(
963 "Invalid date arithmetic operation: {} {op} {}",
964 l.data_type(),
965 r.data_type()
966 ))),
967 }
968}
969
970fn scaled_div<T: DecimalType>(
976 l: T::Native,
977 r: T::Native,
978 mul_pow: i8,
979) -> Result<T::Native, ArrowError> {
980 let zero = T::Native::ZERO;
981 let negative = l.is_lt(zero) != r.is_lt(zero);
982 let dividend = abs_checked::<T>(l)?;
983 let divisor = abs_checked::<T>(r)?;
984
985 let (mut quotient, mut remainder) = dividend.div_rem_checked(divisor)?;
986 for _ in 0..mul_pow {
987 let mut carried = zero;
990 let mut digit = zero;
991 for _ in 0..10 {
992 let headroom = divisor.sub_wrapping(remainder);
993 if carried.is_lt(headroom) {
994 carried = carried.add_wrapping(remainder);
995 } else {
996 carried = carried.sub_wrapping(headroom);
997 digit = digit.add_wrapping(T::Native::ONE);
998 }
999 }
1000 quotient = quotient
1001 .mul_checked(T::Native::usize_as(10))?
1002 .add_checked(digit)?;
1003 remainder = carried;
1004 }
1005
1006 if negative {
1007 quotient.neg_checked()
1008 } else {
1009 Ok(quotient)
1010 }
1011}
1012
1013fn abs_checked<T: DecimalType>(value: T::Native) -> Result<T::Native, ArrowError> {
1014 if value.is_lt(T::Native::ZERO) {
1015 value.neg_checked()
1016 } else {
1017 Ok(value)
1018 }
1019}
1020
1021fn decimal_op<T: DecimalType>(
1023 op: Op,
1024 l: &dyn Array,
1025 l_s: bool,
1026 r: &dyn Array,
1027 r_s: bool,
1028) -> Result<ArrayRef, ArrowError>
1029where
1030 T::Native: CheckedMul,
1031{
1032 let l = l.as_primitive::<T>();
1033 let r = r.as_primitive::<T>();
1034
1035 let (p1, s1, p2, s2) = match (l.data_type(), r.data_type()) {
1036 (DataType::Decimal32(p1, s1), DataType::Decimal32(p2, s2)) => (p1, s1, p2, s2),
1037 (DataType::Decimal64(p1, s1), DataType::Decimal64(p2, s2)) => (p1, s1, p2, s2),
1038 (DataType::Decimal128(p1, s1), DataType::Decimal128(p2, s2)) => (p1, s1, p2, s2),
1039 (DataType::Decimal256(p1, s1), DataType::Decimal256(p2, s2)) => (p1, s1, p2, s2),
1040 _ => unreachable!(),
1041 };
1042
1043 let array: PrimitiveArray<T> = match op {
1046 Op::Add | Op::AddWrapping | Op::Sub | Op::SubWrapping => {
1047 let (p1, s1, p2, s2) = (*p1 as i16, *s1 as i16, *p2 as i16, *s2 as i16);
1048 let result_scale = s1.max(s2);
1050
1051 let result_precision =
1053 (result_scale + (p1 - s1).max(p2 - s2) + 1).min(T::MAX_PRECISION as i16) as u8;
1054
1055 let l_mul = T::Native::usize_as(10).pow_checked((result_scale - s1) as _)?;
1056 let r_mul = T::Native::usize_as(10).pow_checked((result_scale - s2) as _)?;
1057
1058 match op {
1059 Op::Add | Op::AddWrapping if s1 == s2 => {
1061 try_op!(l, l_s, r, r_s, l.add_checked(r))
1062 }
1063 Op::Sub | Op::SubWrapping if s1 == s2 => {
1064 try_op!(l, l_s, r, r_s, l.sub_checked(r))
1065 }
1066 Op::Add | Op::AddWrapping => {
1067 try_op!(
1068 l,
1069 l_s,
1070 r,
1071 r_s,
1072 l.mul_checked(l_mul)?.add_checked(r.mul_checked(r_mul)?)
1073 )
1074 }
1075 Op::Sub | Op::SubWrapping => {
1076 try_op!(
1077 l,
1078 l_s,
1079 r,
1080 r_s,
1081 l.mul_checked(l_mul)?.sub_checked(r.mul_checked(r_mul)?)
1082 )
1083 }
1084 _ => unreachable!(),
1085 }
1086 .with_precision_and_scale(result_precision, result_scale as i8)?
1087 }
1088 Op::Mul | Op::MulWrapping => {
1089 let result_precision = p1.saturating_add(p2 + 1).min(T::MAX_PRECISION);
1090 let result_scale = *s1 as i16 + *s2 as i16;
1091 if result_scale > T::MAX_SCALE as i16 {
1092 return Err(ArrowError::InvalidArgumentError(format!(
1095 "Output scale of {} {op} {} would exceed max scale of {}",
1096 l.data_type(),
1097 r.data_type(),
1098 T::MAX_SCALE
1099 )));
1100 }
1101 let result_scale = i8::try_from(result_scale).map_err(|_| {
1102 ArrowError::InvalidArgumentError(format!(
1103 "Output scale of {} {op} {} would be less than min scale of {}",
1104 l.data_type(),
1105 r.data_type(),
1106 i8::MIN
1107 ))
1108 })?;
1109
1110 try_op!(l, l_s, r, r_s, l.mul_checked(r))
1111 .with_precision_and_scale(result_precision, result_scale)?
1112 }
1113
1114 Op::Div => {
1115 let result_scale = s1.saturating_add(4).min(T::MAX_SCALE);
1118 let mul_pow = result_scale - s1 + s2;
1119
1120 let result_precision = (mul_pow as i16 + *p1 as i16)
1123 .clamp(result_scale.max(1) as i16, T::MAX_PRECISION as i16)
1124 as u8;
1125
1126 let (l_mul, r_mul) = match mul_pow.cmp(&0) {
1127 Ordering::Greater => (
1128 T::Native::usize_as(10).pow_checked(mul_pow as _)?,
1129 T::Native::ONE,
1130 ),
1131 Ordering::Equal => (T::Native::ONE, T::Native::ONE),
1132 Ordering::Less => (
1133 T::Native::ONE,
1134 T::Native::usize_as(10).pow_checked(mul_pow.neg_wrapping() as _)?,
1135 ),
1136 };
1137
1138 try_op!(
1139 l,
1140 l_s,
1141 r,
1142 r_s,
1143 match l.checked_mul(&l_mul) {
1144 Some(scaled) => scaled.div_checked(r.mul_checked(r_mul)?),
1145 None => scaled_div::<T>(l, r, mul_pow),
1146 }
1147 )
1148 .with_precision_and_scale(result_precision, result_scale)?
1149 }
1150
1151 Op::Rem => {
1152 let (p1, s1, p2, s2) = (*p1 as i16, *s1 as i16, *p2 as i16, *s2 as i16);
1153 let result_scale = s1.max(s2);
1155 let result_precision =
1157 (result_scale + (p1 - s1).min(p2 - s2)).min(T::MAX_PRECISION as i16) as u8;
1158
1159 let l_mul = T::Native::usize_as(10).pow_checked((result_scale - s1) as _)?;
1160 let r_mul = T::Native::usize_as(10).pow_checked((result_scale - s2) as _)?;
1161
1162 try_op!(
1163 l,
1164 l_s,
1165 r,
1166 r_s,
1167 l.mul_checked(l_mul)?.mod_checked(r.mul_checked(r_mul)?)
1168 )
1169 .with_precision_and_scale(result_precision, result_scale as i8)?
1170 }
1171 };
1172
1173 Ok(Arc::new(array))
1174}
1175
1176#[cfg(test)]
1177mod tests {
1178 use super::*;
1179 use arrow_array::temporal_conversions::{as_date, as_datetime};
1180 use arrow_buffer::{ScalarBuffer, i256};
1181 use chrono::{DateTime, NaiveDate};
1182
1183 const MAX_VALID_DATE: NaiveDate = NaiveDate::from_ymd_opt(262142, 12, 31).unwrap();
1185 const MIN_VALID_DATE: NaiveDate = NaiveDate::from_ymd_opt(-262143, 1, 1).unwrap();
1186 const MAX_VALID_MILLIS: i64 = date_to_millis(MAX_VALID_DATE);
1187 const MIN_VALID_MILLIS: i64 = date_to_millis(MIN_VALID_DATE);
1188 const MAX_VALID_DAYS: i32 = date_to_days(MAX_VALID_DATE);
1189 const MIN_VALID_DAYS: i32 = date_to_days(MIN_VALID_DATE);
1190 const EPOCH: NaiveDate = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
1191 const YEAR_2000: NaiveDate = NaiveDate::from_ymd_opt(2000, 1, 1).unwrap();
1192
1193 const fn date_to_millis(date: NaiveDate) -> i64 {
1194 date.signed_duration_since(EPOCH).num_milliseconds()
1195 }
1196
1197 const fn date_to_days(date: NaiveDate) -> i32 {
1198 date.signed_duration_since(EPOCH).num_days() as i32
1199 }
1200
1201 fn test_neg_primitive<T: ArrowPrimitiveType>(
1202 input: &[T::Native],
1203 out: Result<&[T::Native], &str>,
1204 ) {
1205 let a = PrimitiveArray::<T>::new(ScalarBuffer::from(input.to_vec()), None);
1206 match out {
1207 Ok(expected) => {
1208 let result = neg(&a).unwrap();
1209 assert_eq!(result.as_primitive::<T>().values(), expected);
1210 }
1211 Err(e) => {
1212 let err = neg(&a).unwrap_err().to_string();
1213 assert_eq!(e, err);
1214 }
1215 }
1216 }
1217
1218 #[test]
1219 fn test_neg() {
1220 let input = &[1, -5, 2, 693, 3929];
1221 let output = &[-1, 5, -2, -693, -3929];
1222 test_neg_primitive::<Int32Type>(input, Ok(output));
1223
1224 let input = &[1, -5, 2, 693, 3929];
1225 let output = &[-1, 5, -2, -693, -3929];
1226 test_neg_primitive::<Int64Type>(input, Ok(output));
1227 test_neg_primitive::<DurationSecondType>(input, Ok(output));
1228 test_neg_primitive::<DurationMillisecondType>(input, Ok(output));
1229 test_neg_primitive::<DurationMicrosecondType>(input, Ok(output));
1230 test_neg_primitive::<DurationNanosecondType>(input, Ok(output));
1231
1232 let input = &[f32::MAX, f32::MIN, f32::INFINITY, 1.3, 0.5];
1233 let output = &[f32::MIN, f32::MAX, f32::NEG_INFINITY, -1.3, -0.5];
1234 test_neg_primitive::<Float32Type>(input, Ok(output));
1235
1236 test_neg_primitive::<Int32Type>(
1237 &[i32::MIN],
1238 Err("Arithmetic overflow: Overflow happened on: - -2147483648"),
1239 );
1240 test_neg_primitive::<Int64Type>(
1241 &[i64::MIN],
1242 Err("Arithmetic overflow: Overflow happened on: - -9223372036854775808"),
1243 );
1244 test_neg_primitive::<DurationSecondType>(
1245 &[i64::MIN],
1246 Err("Arithmetic overflow: Overflow happened on: - -9223372036854775808"),
1247 );
1248
1249 let r = neg_wrapping(&Int32Array::from(vec![i32::MIN])).unwrap();
1250 assert_eq!(r.as_primitive::<Int32Type>().value(0), i32::MIN);
1251
1252 let r = neg_wrapping(&Int64Array::from(vec![i64::MIN])).unwrap();
1253 assert_eq!(r.as_primitive::<Int64Type>().value(0), i64::MIN);
1254
1255 let err = neg_wrapping(&DurationSecondArray::from(vec![i64::MIN]))
1256 .unwrap_err()
1257 .to_string();
1258
1259 assert_eq!(
1260 err,
1261 "Arithmetic overflow: Overflow happened on: - -9223372036854775808"
1262 );
1263
1264 let a = Decimal32Array::from(vec![1, 3, -44, 2, 4])
1265 .with_precision_and_scale(9, 6)
1266 .unwrap();
1267
1268 let r = neg(&a).unwrap();
1269 assert_eq!(r.data_type(), a.data_type());
1270 assert_eq!(
1271 r.as_primitive::<Decimal32Type>().values(),
1272 &[-1, -3, 44, -2, -4]
1273 );
1274
1275 let a = Decimal64Array::from(vec![1, 3, -44, 2, 4])
1276 .with_precision_and_scale(9, 6)
1277 .unwrap();
1278
1279 let r = neg(&a).unwrap();
1280 assert_eq!(r.data_type(), a.data_type());
1281 assert_eq!(
1282 r.as_primitive::<Decimal64Type>().values(),
1283 &[-1, -3, 44, -2, -4]
1284 );
1285
1286 let a = Decimal128Array::from(vec![1, 3, -44, 2, 4])
1287 .with_precision_and_scale(9, 6)
1288 .unwrap();
1289
1290 let r = neg(&a).unwrap();
1291 assert_eq!(r.data_type(), a.data_type());
1292 assert_eq!(
1293 r.as_primitive::<Decimal128Type>().values(),
1294 &[-1, -3, 44, -2, -4]
1295 );
1296
1297 let a = Decimal256Array::from(vec![
1298 i256::from_i128(342),
1299 i256::from_i128(-4949),
1300 i256::from_i128(3),
1301 ])
1302 .with_precision_and_scale(9, 6)
1303 .unwrap();
1304
1305 let r = neg(&a).unwrap();
1306 assert_eq!(r.data_type(), a.data_type());
1307 assert_eq!(
1308 r.as_primitive::<Decimal256Type>().values(),
1309 &[
1310 i256::from_i128(-342),
1311 i256::from_i128(4949),
1312 i256::from_i128(-3),
1313 ]
1314 );
1315
1316 let a = IntervalYearMonthArray::from(vec![
1317 IntervalYearMonthType::make_value(2, 4),
1318 IntervalYearMonthType::make_value(2, -4),
1319 IntervalYearMonthType::make_value(-3, -5),
1320 ]);
1321 let r = neg(&a).unwrap();
1322 assert_eq!(
1323 r.as_primitive::<IntervalYearMonthType>().values(),
1324 &[
1325 IntervalYearMonthType::make_value(-2, -4),
1326 IntervalYearMonthType::make_value(-2, 4),
1327 IntervalYearMonthType::make_value(3, 5),
1328 ]
1329 );
1330
1331 let a = IntervalDayTimeArray::from(vec![
1332 IntervalDayTimeType::make_value(2, 4),
1333 IntervalDayTimeType::make_value(2, -4),
1334 IntervalDayTimeType::make_value(-3, -5),
1335 ]);
1336 let r = neg(&a).unwrap();
1337 assert_eq!(
1338 r.as_primitive::<IntervalDayTimeType>().values(),
1339 &[
1340 IntervalDayTimeType::make_value(-2, -4),
1341 IntervalDayTimeType::make_value(-2, 4),
1342 IntervalDayTimeType::make_value(3, 5),
1343 ]
1344 );
1345
1346 let a = IntervalMonthDayNanoArray::from(vec![
1347 IntervalMonthDayNanoType::make_value(2, 4, 5953394),
1348 IntervalMonthDayNanoType::make_value(2, -4, -45839),
1349 IntervalMonthDayNanoType::make_value(-3, -5, 6944),
1350 ]);
1351 let r = neg(&a).unwrap();
1352 assert_eq!(
1353 r.as_primitive::<IntervalMonthDayNanoType>().values(),
1354 &[
1355 IntervalMonthDayNanoType::make_value(-2, -4, -5953394),
1356 IntervalMonthDayNanoType::make_value(-2, 4, 45839),
1357 IntervalMonthDayNanoType::make_value(3, 5, -6944),
1358 ]
1359 );
1360 }
1361
1362 #[test]
1363 fn test_integer() {
1364 let a = Int32Array::from(vec![4, 3, 5, -6, 100]);
1365 let b = Int32Array::from(vec![6, 2, 5, -7, 3]);
1366 let result = add(&a, &b).unwrap();
1367 assert_eq!(
1368 result.as_ref(),
1369 &Int32Array::from(vec![10, 5, 10, -13, 103])
1370 );
1371 let result = sub(&a, &b).unwrap();
1372 assert_eq!(result.as_ref(), &Int32Array::from(vec![-2, 1, 0, 1, 97]));
1373 let result = div(&a, &b).unwrap();
1374 assert_eq!(result.as_ref(), &Int32Array::from(vec![0, 1, 1, 0, 33]));
1375 let result = mul(&a, &b).unwrap();
1376 assert_eq!(result.as_ref(), &Int32Array::from(vec![24, 6, 25, 42, 300]));
1377 let result = rem(&a, &b).unwrap();
1378 assert_eq!(result.as_ref(), &Int32Array::from(vec![4, 1, 0, -6, 1]));
1379
1380 let a = Int8Array::from(vec![Some(2), None, Some(45)]);
1381 let b = Int8Array::from(vec![Some(5), Some(3), None]);
1382 let result = add(&a, &b).unwrap();
1383 assert_eq!(result.as_ref(), &Int8Array::from(vec![Some(7), None, None]));
1384
1385 let a = UInt8Array::from(vec![56, 5, 3]);
1386 let b = UInt8Array::from(vec![200, 2, 5]);
1387 let err = add(&a, &b).unwrap_err().to_string();
1388 assert_eq!(err, "Arithmetic overflow: Overflow happened on: 56 + 200");
1389 let result = add_wrapping(&a, &b).unwrap();
1390 assert_eq!(result.as_ref(), &UInt8Array::from(vec![0, 7, 8]));
1391
1392 let a = UInt8Array::from(vec![34, 5, 3]);
1393 let b = UInt8Array::from(vec![200, 2, 5]);
1394 let err = sub(&a, &b).unwrap_err().to_string();
1395 assert_eq!(err, "Arithmetic overflow: Overflow happened on: 34 - 200");
1396 let result = sub_wrapping(&a, &b).unwrap();
1397 assert_eq!(result.as_ref(), &UInt8Array::from(vec![90, 3, 254]));
1398
1399 let a = UInt8Array::from(vec![34, 5, 3]);
1400 let b = UInt8Array::from(vec![200, 2, 5]);
1401 let err = mul(&a, &b).unwrap_err().to_string();
1402 assert_eq!(err, "Arithmetic overflow: Overflow happened on: 34 * 200");
1403 let result = mul_wrapping(&a, &b).unwrap();
1404 assert_eq!(result.as_ref(), &UInt8Array::from(vec![144, 10, 15]));
1405
1406 let a = Int16Array::from(vec![i16::MIN]);
1407 let b = Int16Array::from(vec![-1]);
1408 let err = div(&a, &b).unwrap_err().to_string();
1409 assert_eq!(
1410 err,
1411 "Arithmetic overflow: Overflow happened on: -32768 / -1"
1412 );
1413
1414 let a = Int16Array::from(vec![i16::MIN]);
1415 let b = Int16Array::from(vec![-1]);
1416 let result = rem(&a, &b).unwrap();
1417 assert_eq!(result.as_ref(), &Int16Array::from(vec![0]));
1418
1419 let a = Int16Array::from(vec![21]);
1420 let b = Int16Array::from(vec![0]);
1421 let err = div(&a, &b).unwrap_err().to_string();
1422 assert_eq!(err, "Divide by zero error");
1423
1424 let a = Int16Array::from(vec![21]);
1425 let b = Int16Array::from(vec![0]);
1426 let err = rem(&a, &b).unwrap_err().to_string();
1427 assert_eq!(err, "Divide by zero error");
1428 }
1429
1430 #[test]
1431 fn test_float() {
1432 let a = Float32Array::from(vec![1., f32::MAX, 6., -4., -1., 0.]);
1433 let b = Float32Array::from(vec![1., f32::MAX, f32::MAX, -3., 45., 0.]);
1434 let result = add(&a, &b).unwrap();
1435 assert_eq!(
1436 result.as_ref(),
1437 &Float32Array::from(vec![2., f32::INFINITY, f32::MAX, -7., 44.0, 0.])
1438 );
1439
1440 let result = sub(&a, &b).unwrap();
1441 assert_eq!(
1442 result.as_ref(),
1443 &Float32Array::from(vec![0., 0., f32::MIN, -1., -46., 0.])
1444 );
1445
1446 let result = mul(&a, &b).unwrap();
1447 assert_eq!(
1448 result.as_ref(),
1449 &Float32Array::from(vec![1., f32::INFINITY, f32::INFINITY, 12., -45., 0.])
1450 );
1451
1452 let result = div(&a, &b).unwrap();
1453 let r = result.as_primitive::<Float32Type>();
1454 assert_eq!(r.value(0), 1.);
1455 assert_eq!(r.value(1), 1.);
1456 assert!(r.value(2) < f32::EPSILON);
1457 assert_eq!(r.value(3), -4. / -3.);
1458 assert!(r.value(5).is_nan());
1459
1460 let result = rem(&a, &b).unwrap();
1461 let r = result.as_primitive::<Float32Type>();
1462 assert_eq!(&r.values()[..5], &[0., 0., 6., -1., -1.]);
1463 assert!(r.value(5).is_nan());
1464 }
1465
1466 #[test]
1467 fn test_decimal() {
1468 let a = Decimal128Array::from(vec![15, 0, -577, 334, -78, 3])
1470 .with_precision_and_scale(12, 3)
1471 .unwrap();
1472
1473 let b = Decimal128Array::from(vec![54, 34, -356, 3, 6, 745])
1475 .with_precision_and_scale(12, 1)
1476 .unwrap();
1477
1478 let result = add(&a, &b).unwrap();
1479 assert_eq!(result.data_type(), &DataType::Decimal128(15, 3));
1480 assert_eq!(
1481 result.as_primitive::<Decimal128Type>().values(),
1482 &[5415, 3400, -36177, 634, 522, 74503]
1483 );
1484
1485 let result = sub(&a, &b).unwrap();
1486 assert_eq!(result.data_type(), &DataType::Decimal128(15, 3));
1487 assert_eq!(
1488 result.as_primitive::<Decimal128Type>().values(),
1489 &[-5385, -3400, 35023, 34, -678, -74497]
1490 );
1491
1492 let result = mul(&a, &b).unwrap();
1493 assert_eq!(result.data_type(), &DataType::Decimal128(25, 4));
1494 assert_eq!(
1495 result.as_primitive::<Decimal128Type>().values(),
1496 &[810, 0, 205412, 1002, -468, 2235]
1497 );
1498
1499 let result = div(&a, &b).unwrap();
1500 assert_eq!(result.data_type(), &DataType::Decimal128(17, 7));
1501 assert_eq!(
1502 result.as_primitive::<Decimal128Type>().values(),
1503 &[27777, 0, 162078, 11133333, -1300000, 402]
1504 );
1505
1506 let result = rem(&a, &b).unwrap();
1507 assert_eq!(result.data_type(), &DataType::Decimal128(12, 3));
1508 assert_eq!(
1509 result.as_primitive::<Decimal128Type>().values(),
1510 &[15, 0, -577, 34, -78, 3]
1511 );
1512
1513 let a = Decimal128Array::from(vec![1])
1514 .with_precision_and_scale(3, 3)
1515 .unwrap();
1516 let b = Decimal128Array::from(vec![1])
1517 .with_precision_and_scale(37, 37)
1518 .unwrap();
1519 let err = mul(&a, &b).unwrap_err().to_string();
1520 assert_eq!(
1521 err,
1522 "Invalid argument error: Output scale of Decimal128(3, 3) * Decimal128(37, 37) would exceed max scale of 38"
1523 );
1524
1525 let a = Decimal128Array::from(vec![1])
1526 .with_precision_and_scale(3, -2)
1527 .unwrap();
1528 let err = add(&a, &b).unwrap_err().to_string();
1529 assert_eq!(err, "Arithmetic overflow: Overflow happened on: 10 ^ 39");
1530
1531 let a = Decimal128Array::from(vec![10])
1532 .with_precision_and_scale(3, -1)
1533 .unwrap();
1534 let err = add(&a, &b).unwrap_err().to_string();
1535 assert_eq!(
1536 err,
1537 "Arithmetic overflow: Overflow happened on: 10 * 100000000000000000000000000000000000000"
1538 );
1539
1540 let b = Decimal128Array::from(vec![0])
1541 .with_precision_and_scale(1, 1)
1542 .unwrap();
1543 let err = div(&a, &b).unwrap_err().to_string();
1544 assert_eq!(err, "Divide by zero error");
1545 let err = rem(&a, &b).unwrap_err().to_string();
1546 assert_eq!(err, "Divide by zero error");
1547 }
1548
1549 #[test]
1550 fn test_decimal256_add_sub_negative_scale_metadata() {
1551 let a = Decimal256Array::from(vec![Some(i256::ONE), Some(i256::MINUS_ONE), None])
1552 .with_precision_and_scale(76, -52)
1553 .unwrap();
1554 let b = Decimal256Array::from(vec![i256::from_i128(2), i256::ONE, i256::ONE])
1555 .with_precision_and_scale(76, -52)
1556 .unwrap();
1557 let expected =
1558 Decimal256Array::from(vec![Some(i256::from_i128(3)), Some(i256::ZERO), None])
1559 .with_precision_and_scale(76, -52)
1560 .unwrap();
1561 assert_eq!(add(&a, &b).unwrap().as_ref(), &expected);
1562
1563 let expected =
1564 Decimal256Array::from(vec![Some(i256::MINUS_ONE), Some(i256::from_i128(-2)), None])
1565 .with_precision_and_scale(76, -52)
1566 .unwrap();
1567 assert_eq!(sub(&a, &b).unwrap().as_ref(), &expected);
1568 }
1569
1570 #[test]
1571 fn test_decimal256_add_sub_minimum_scale() {
1572 let a = Decimal256Array::from(vec![i256::ONE])
1573 .with_precision_and_scale(20, i8::MIN)
1574 .unwrap();
1575 let b = Decimal256Array::from(vec![i256::from_i128(2)])
1576 .with_precision_and_scale(20, i8::MIN)
1577 .unwrap();
1578 let expected = Decimal256Array::from(vec![i256::from_i128(3)])
1579 .with_precision_and_scale(21, i8::MIN)
1580 .unwrap();
1581 assert_eq!(add(&a, &b).unwrap().as_ref(), &expected);
1582
1583 let expected = Decimal256Array::from(vec![i256::MINUS_ONE])
1584 .with_precision_and_scale(21, i8::MIN)
1585 .unwrap();
1586 assert_eq!(sub(&a, &b).unwrap().as_ref(), &expected);
1587 }
1588
1589 #[test]
1590 fn test_decimal256_remainder_negative_scale_metadata() {
1591 let a = Decimal256Array::from(vec![Some(i256::ONE), Some(i256::MINUS_ONE), None])
1592 .with_precision_and_scale(76, -52)
1593 .unwrap();
1594 let b = Decimal256Array::from(vec![i256::from_i128(2), i256::ONE, i256::ONE])
1595 .with_precision_and_scale(76, -52)
1596 .unwrap();
1597 let expected = Decimal256Array::from(vec![Some(i256::ONE), Some(i256::ZERO), None])
1598 .with_precision_and_scale(76, -52)
1599 .unwrap();
1600 assert_eq!(rem(&a, &b).unwrap().as_ref(), &expected);
1601 }
1602
1603 #[test]
1604 fn test_decimal256_adjacent_minimum_scales() {
1605 let a = Decimal256Array::from(vec![i256::ONE])
1606 .with_precision_and_scale(20, i8::MIN)
1607 .unwrap();
1608 let b = Decimal256Array::from(vec![i256::from_i128(2)])
1609 .with_precision_and_scale(20, i8::MIN + 1)
1610 .unwrap();
1611 let expected = Decimal256Array::from(vec![i256::from_i128(12)])
1612 .with_precision_and_scale(22, -127)
1613 .unwrap();
1614 assert_eq!(add(&a, &b).unwrap().as_ref(), &expected);
1615
1616 let expected = Decimal256Array::from(vec![i256::from_i128(8)])
1617 .with_precision_and_scale(22, -127)
1618 .unwrap();
1619 assert_eq!(sub(&a, &b).unwrap().as_ref(), &expected);
1620
1621 let expected = Decimal256Array::from(vec![i256::ZERO])
1622 .with_precision_and_scale(20, -127)
1623 .unwrap();
1624 assert_eq!(rem(&a, &b).unwrap().as_ref(), &expected);
1625 }
1626
1627 #[test]
1628 fn test_decimal256_extreme_scale_difference_overflow() {
1629 let a = Decimal256Array::from(vec![i256::ONE])
1630 .with_precision_and_scale(20, i8::MIN)
1631 .unwrap();
1632 let b = Decimal256Array::from(vec![i256::from_i128(2)])
1633 .with_precision_and_scale(76, 76)
1634 .unwrap();
1635 let expected = "Arithmetic overflow: Overflow happened on: 10 ^ 204";
1636 assert_eq!(add(&a, &b).unwrap_err().to_string(), expected);
1637 assert_eq!(sub(&a, &b).unwrap_err().to_string(), expected);
1638 assert_eq!(rem(&a, &b).unwrap_err().to_string(), expected);
1639 }
1640
1641 #[test]
1642 fn test_decimal256_multiply_minimum_scale() {
1643 let a = Decimal256Array::from(vec![i256::ONE])
1644 .with_precision_and_scale(76, -64)
1645 .unwrap();
1646 let expected = Decimal256Array::from(vec![i256::ONE])
1647 .with_precision_and_scale(76, i8::MIN)
1648 .unwrap();
1649 assert_eq!(mul(&a, &a).unwrap().as_ref(), &expected);
1650
1651 let b = a.clone().with_precision_and_scale(76, -65).unwrap();
1652 assert_eq!(
1653 mul(&a, &b).unwrap_err().to_string(),
1654 "Invalid argument error: Output scale of Decimal256(76, -64) * Decimal256(76, -65) would be less than min scale of -128"
1655 );
1656 }
1657
1658 #[test]
1659 fn test_decimal_div_precision_at_least_scale() {
1660 fn check<T: DecimalType>()
1661 where
1662 T::Native: From<i32>,
1663 {
1664 let a: PrimitiveArray<T> = [Some(1), Some(-1), Some(0), None]
1665 .into_iter()
1666 .map(|v| v.map(T::Native::from))
1667 .collect();
1668 let a = a.with_precision_and_scale(1, 1).unwrap();
1669 for (scale, coefficient) in [(0, 10000), (-1, 1000), (-4, 1), (-5, 0), (-6, 0)] {
1670 let b = PrimitiveArray::<T>::from_iter_values(
1671 [1, 1, 1, 0].into_iter().map(T::Native::from),
1672 )
1673 .with_precision_and_scale(1, scale)
1674 .unwrap();
1675 let expected: PrimitiveArray<T> =
1676 [Some(coefficient), Some(-coefficient), Some(0), None]
1677 .into_iter()
1678 .map(|v| v.map(T::Native::from))
1679 .collect();
1680 let expected = expected.with_precision_and_scale(5, 5).unwrap();
1681 assert_eq!(div(&a, &b).unwrap().as_ref(), &expected);
1682 }
1683 }
1684 check::<Decimal32Type>();
1685 check::<Decimal64Type>();
1686 check::<Decimal128Type>();
1687 check::<Decimal256Type>();
1688 }
1689
1690 #[test]
1691 fn test_decimal_div_precision_at_least_one() {
1692 fn check<T: DecimalType>()
1693 where
1694 T::Native: From<i32>,
1695 {
1696 for scale in [-4, -5] {
1697 let a: PrimitiveArray<T> = [Some(1), Some(-1), Some(0), None]
1698 .into_iter()
1699 .map(|v| v.map(T::Native::from))
1700 .collect();
1701 let a = a.with_precision_and_scale(1, scale).unwrap();
1702 for (divisor_scale, coefficient) in [(-4, 1), (-5, 0), (-6, 0)] {
1703 let b = PrimitiveArray::<T>::from_iter_values(
1704 [1, 1, 1, 0].into_iter().map(T::Native::from),
1705 )
1706 .with_precision_and_scale(1, divisor_scale)
1707 .unwrap();
1708 let expected: PrimitiveArray<T> =
1709 [Some(coefficient), Some(-coefficient), Some(0), None]
1710 .into_iter()
1711 .map(|v| v.map(T::Native::from))
1712 .collect();
1713 let expected = expected.with_precision_and_scale(1, scale + 4).unwrap();
1714 assert_eq!(div(&a, &b).unwrap().as_ref(), &expected);
1715 }
1716 }
1717 }
1718 check::<Decimal32Type>();
1719 check::<Decimal64Type>();
1720 check::<Decimal128Type>();
1721 check::<Decimal256Type>();
1722 }
1723
1724 #[test]
1725 fn test_decimal_div_scaling_overflow_boundary() {
1726 fn check<T: DecimalType>() {
1729 let one = T::Native::ONE;
1730 let pow = T::Native::usize_as(1_000_000);
1731 let max = T::Native::MAX_TOTAL_ORDER.div_wrapping(pow);
1732 let min = T::Native::MIN_TOTAL_ORDER.div_wrapping(pow);
1733 let values = [
1734 max,
1735 max.add_wrapping(one),
1736 min,
1737 min.sub_wrapping(one),
1738 T::Native::MAX_TOTAL_ORDER,
1739 T::Native::MIN_TOTAL_ORDER.add_wrapping(one),
1740 ];
1741 let a = PrimitiveArray::<T>::from_iter_values(values)
1742 .with_precision_and_scale(T::MAX_PRECISION, 2)
1743 .unwrap();
1744 for (divisor, negate) in [(pow, false), (pow.neg_wrapping(), true)] {
1745 let b = PrimitiveArray::<T>::from_iter_values([divisor])
1746 .with_precision_and_scale(T::MAX_PRECISION, 2)
1747 .unwrap();
1748 let result = div(&a, &Scalar::new(b)).unwrap();
1749 let expected = values.map(|v| if negate { v.neg_wrapping() } else { v });
1750 assert_eq!(result.as_primitive::<T>().values().as_ref(), expected);
1751 }
1752 }
1753 check::<Decimal32Type>();
1754 check::<Decimal64Type>();
1755 check::<Decimal128Type>();
1756 check::<Decimal256Type>();
1757 }
1758
1759 #[test]
1760 fn test_decimal256_div_wide_intermediate() {
1761 let a = Decimal256Array::from(vec![i256::from_i128(
1764 60096743305738933273387748827369321010i128,
1765 )])
1766 .with_precision_and_scale(38, 37)
1767 .unwrap();
1768 let b = Decimal256Array::from(vec![i256::from_i128(
1769 60096763826458053191384497987259478584i128,
1770 )])
1771 .with_precision_and_scale(38, 37)
1772 .unwrap();
1773
1774 let result = div(&a, &b).unwrap();
1775 assert_eq!(result.data_type(), &DataType::Decimal256(76, 41));
1776 assert_eq!(
1777 result.as_primitive::<Decimal256Type>().value(0),
1778 i256::from_string("99999965853869970143724273117679321341339").unwrap()
1779 );
1780
1781 let neg_a = neg(&a).unwrap();
1783 let result = div(neg_a.as_primitive::<Decimal256Type>(), &b).unwrap();
1784 assert_eq!(
1785 result.as_primitive::<Decimal256Type>().value(0),
1786 i256::from_string("-99999965853869970143724273117679321341339").unwrap()
1787 );
1788
1789 let neg_b = neg(&b).unwrap();
1790 let result = div(&a, neg_b.as_primitive::<Decimal256Type>()).unwrap();
1791 assert_eq!(
1792 result.as_primitive::<Decimal256Type>().value(0),
1793 i256::from_string("-99999965853869970143724273117679321341339").unwrap()
1794 );
1795
1796 let zero = Decimal256Array::from(vec![i256::ZERO])
1797 .with_precision_and_scale(38, 37)
1798 .unwrap();
1799 let err = div(&a, &zero).unwrap_err().to_string();
1800 assert_eq!(err, "Divide by zero error");
1801 }
1802
1803 #[test]
1804 fn test_decimal256_div_divisor_near_max() {
1805 let a = Decimal256Array::from(vec![
1807 i256::from_string(
1808 "5900000000000000000000000000000000000000000000000000000000000000000000000000",
1809 )
1810 .unwrap(),
1811 ])
1812 .with_precision_and_scale(76, 37)
1813 .unwrap();
1814 let b = Decimal256Array::from(vec![
1815 i256::from_string(
1816 "6000000000000000000000000000000000000000000000000000000000000000000000000000",
1817 )
1818 .unwrap(),
1819 ])
1820 .with_precision_and_scale(76, 37)
1821 .unwrap();
1822
1823 let result = div(&a, &b).unwrap();
1824 assert_eq!(
1825 result.as_primitive::<Decimal256Type>().value(0),
1826 i256::from_string("98333333333333333333333333333333333333333").unwrap()
1827 );
1828 }
1829
1830 #[test]
1831 fn test_decimal128_div_wide_intermediate() {
1832 let a = Decimal128Array::from(vec![30000000000000000000000000000000000000i128])
1834 .with_precision_and_scale(38, 37)
1835 .unwrap();
1836 let b = Decimal128Array::from(vec![60000000000000000000000000000000000000i128])
1837 .with_precision_and_scale(38, 37)
1838 .unwrap();
1839
1840 let result = div(&a, &b).unwrap();
1841 assert_eq!(result.data_type(), &DataType::Decimal128(38, 38));
1842 assert_eq!(
1843 result.as_primitive::<Decimal128Type>().value(0),
1844 50000000000000000000000000000000000000i128
1845 );
1846 }
1847
1848 #[test]
1849 fn test_scaled_div_agrees_with_direct_division() {
1850 for (l, r, mul_pow) in [
1851 (7i128, 3i128, 4i8),
1852 (-7, 3, 4),
1853 (7, -3, 4),
1854 (-7, -3, 4),
1855 (1, 999_999_999, 9),
1856 (i128::MAX / 10, 7, 1),
1857 (i128::MAX / 10, -i128::MAX / 11, 1),
1858 (0, 5, 6),
1859 ] {
1860 let scaled = l * 10i128.pow(mul_pow as u32);
1861 assert_eq!(
1862 scaled_div::<Decimal128Type>(l, r, mul_pow).unwrap(),
1863 scaled / r,
1864 "{l} * 10^{mul_pow} / {r}"
1865 );
1866 }
1867 }
1868
1869 #[test]
1870 fn test_decimal256_same_scale_add_sub() {
1871 let lhs = Decimal256Array::from(vec![
1872 Some(i256::from_parts(u128::MAX, 0)),
1873 Some(i256::MINUS_ONE),
1874 None,
1875 ])
1876 .with_precision_and_scale(70, 2)
1877 .unwrap();
1878 let rhs = Decimal256Array::from(vec![Some(i256::ONE), Some(i256::ONE), Some(i256::MAX)])
1879 .with_precision_and_scale(70, 2)
1880 .unwrap();
1881
1882 let expected =
1883 Decimal256Array::from(vec![Some(i256::from_parts(0, 1)), Some(i256::ZERO), None])
1884 .with_precision_and_scale(71, 2)
1885 .unwrap();
1886 for operation in [add, add_wrapping] {
1887 let result = operation(&lhs, &rhs).unwrap();
1888 assert_eq!(result.as_primitive::<Decimal256Type>(), &expected);
1889 }
1890
1891 let expected = Decimal256Array::from(vec![
1892 Some(i256::from_parts(u128::MAX - 1, 0)),
1893 Some(i256::from_i128(-2)),
1894 None,
1895 ])
1896 .with_precision_and_scale(71, 2)
1897 .unwrap();
1898 for operation in [sub, sub_wrapping] {
1899 let result = operation(&lhs, &rhs).unwrap();
1900 assert_eq!(result.as_primitive::<Decimal256Type>(), &expected);
1901 }
1902
1903 let lhs = Decimal256Array::from(vec![i256::MAX])
1904 .with_precision_and_scale(76, 0)
1905 .unwrap();
1906 let rhs = Decimal256Array::from(vec![i256::ONE])
1907 .with_precision_and_scale(76, 0)
1908 .unwrap();
1909 for operation in [add, add_wrapping] {
1910 assert_eq!(
1911 operation(&lhs, &rhs).unwrap_err().to_string(),
1912 format!(
1913 "Arithmetic overflow: Overflow happened on: {:?} + {:?}",
1914 i256::MAX,
1915 i256::ONE
1916 )
1917 );
1918 }
1919
1920 let lhs = Decimal256Array::from(vec![i256::MIN])
1921 .with_precision_and_scale(76, 0)
1922 .unwrap();
1923 for operation in [sub, sub_wrapping] {
1924 assert_eq!(
1925 operation(&lhs, &rhs).unwrap_err().to_string(),
1926 format!(
1927 "Arithmetic overflow: Overflow happened on: {:?} - {:?}",
1928 i256::MIN,
1929 i256::ONE
1930 )
1931 );
1932 }
1933 }
1934
1935 fn test_timestamp_impl<T: TimestampOp>() {
1936 let a = PrimitiveArray::<T>::new(vec![2000000, 434030324, 53943340].into(), None);
1937 let b = PrimitiveArray::<T>::new(vec![329593, 59349, 694994].into(), None);
1938
1939 let result = sub(&a, &b).unwrap();
1940 assert_eq!(
1941 result.as_primitive::<T::Duration>().values(),
1942 &[1670407, 433970975, 53248346]
1943 );
1944
1945 let r2 = add(&b, &result.as_ref()).unwrap();
1946 assert_eq!(r2.as_ref(), &a);
1947
1948 let r3 = add(&result.as_ref(), &b).unwrap();
1949 assert_eq!(r3.as_ref(), &a);
1950
1951 let format_array = |x: &dyn Array| -> Vec<String> {
1952 x.as_primitive::<T>()
1953 .values()
1954 .into_iter()
1955 .map(|x| as_datetime::<T>(*x).unwrap().to_string())
1956 .collect()
1957 };
1958
1959 let values = vec![
1960 "1970-01-01T00:00:00Z",
1961 "2010-04-01T04:00:20Z",
1962 "1960-01-30T04:23:20Z",
1963 ]
1964 .into_iter()
1965 .map(|x| {
1966 T::from_naive_datetime(DateTime::parse_from_rfc3339(x).unwrap().naive_utc(), None)
1967 .unwrap()
1968 })
1969 .collect();
1970
1971 let a = PrimitiveArray::<T>::new(values, None);
1972 let b = IntervalYearMonthArray::from(vec![
1973 IntervalYearMonthType::make_value(5, 34),
1974 IntervalYearMonthType::make_value(-2, 4),
1975 IntervalYearMonthType::make_value(7, -4),
1976 ]);
1977 let r4 = add(&a, &b).unwrap();
1978 assert_eq!(
1979 &format_array(r4.as_ref()),
1980 &[
1981 "1977-11-01 00:00:00".to_string(),
1982 "2008-08-01 04:00:20".to_string(),
1983 "1966-09-30 04:23:20".to_string()
1984 ]
1985 );
1986
1987 let r5 = sub(&r4, &b).unwrap();
1988 assert_eq!(r5.as_ref(), &a);
1989
1990 let b = IntervalDayTimeArray::from(vec![
1991 IntervalDayTimeType::make_value(5, 454000),
1992 IntervalDayTimeType::make_value(-34, 0),
1993 IntervalDayTimeType::make_value(7, -4000),
1994 ]);
1995 let r6 = add(&a, &b).unwrap();
1996 assert_eq!(
1997 &format_array(r6.as_ref()),
1998 &[
1999 "1970-01-06 00:07:34".to_string(),
2000 "2010-02-26 04:00:20".to_string(),
2001 "1960-02-06 04:23:16".to_string()
2002 ]
2003 );
2004
2005 let r7 = sub(&r6, &b).unwrap();
2006 assert_eq!(r7.as_ref(), &a);
2007
2008 let b = IntervalMonthDayNanoArray::from(vec![
2009 IntervalMonthDayNanoType::make_value(344, 34, -43_000_000_000),
2010 IntervalMonthDayNanoType::make_value(-593, -33, 13_000_000_000),
2011 IntervalMonthDayNanoType::make_value(5, 2, 493_000_000_000),
2012 ]);
2013 let r8 = add(&a, &b).unwrap();
2014 assert_eq!(
2015 &format_array(r8.as_ref()),
2016 &[
2017 "1998-10-04 23:59:17".to_string(),
2018 "1960-09-29 04:00:33".to_string(),
2019 "1960-07-02 04:31:33".to_string()
2020 ]
2021 );
2022
2023 let r9 = sub(&r8, &b).unwrap();
2024 assert_eq!(
2026 &format_array(r9.as_ref()),
2027 &[
2028 "1970-01-02 00:00:00".to_string(),
2029 "2010-04-02 04:00:20".to_string(),
2030 "1960-01-31 04:23:20".to_string()
2031 ]
2032 );
2033 }
2034
2035 #[test]
2036 fn test_timestamp() {
2037 test_timestamp_impl::<TimestampSecondType>();
2038 test_timestamp_impl::<TimestampMillisecondType>();
2039 test_timestamp_impl::<TimestampMicrosecondType>();
2040 test_timestamp_impl::<TimestampNanosecondType>();
2041 }
2042
2043 #[test]
2044 fn test_interval() {
2045 let a = IntervalYearMonthArray::from(vec![
2046 IntervalYearMonthType::make_value(32, 4),
2047 IntervalYearMonthType::make_value(32, 4),
2048 ]);
2049 let b = IntervalYearMonthArray::from(vec![
2050 IntervalYearMonthType::make_value(-4, 6),
2051 IntervalYearMonthType::make_value(-3, 23),
2052 ]);
2053 let result = add(&a, &b).unwrap();
2054 assert_eq!(
2055 result.as_ref(),
2056 &IntervalYearMonthArray::from(vec![
2057 IntervalYearMonthType::make_value(28, 10),
2058 IntervalYearMonthType::make_value(29, 27)
2059 ])
2060 );
2061 let result = sub(&a, &b).unwrap();
2062 assert_eq!(
2063 result.as_ref(),
2064 &IntervalYearMonthArray::from(vec![
2065 IntervalYearMonthType::make_value(36, -2),
2066 IntervalYearMonthType::make_value(35, -19)
2067 ])
2068 );
2069
2070 let a = IntervalDayTimeArray::from(vec![
2071 IntervalDayTimeType::make_value(32, 4),
2072 IntervalDayTimeType::make_value(32, 4),
2073 ]);
2074 let b = IntervalDayTimeArray::from(vec![
2075 IntervalDayTimeType::make_value(-4, 6),
2076 IntervalDayTimeType::make_value(-3, 23),
2077 ]);
2078 let result = add(&a, &b).unwrap();
2079 assert_eq!(
2080 result.as_ref(),
2081 &IntervalDayTimeArray::from(vec![
2082 IntervalDayTimeType::make_value(28, 10),
2083 IntervalDayTimeType::make_value(29, 27)
2084 ])
2085 );
2086 let result = sub(&a, &b).unwrap();
2087 assert_eq!(
2088 result.as_ref(),
2089 &IntervalDayTimeArray::from(vec![
2090 IntervalDayTimeType::make_value(36, -2),
2091 IntervalDayTimeType::make_value(35, -19)
2092 ])
2093 );
2094 let a = IntervalMonthDayNanoArray::from(vec![
2095 IntervalMonthDayNanoType::make_value(32, 4, 4000000000000),
2096 IntervalMonthDayNanoType::make_value(32, 4, 45463000000000000),
2097 ]);
2098 let b = IntervalMonthDayNanoArray::from(vec![
2099 IntervalMonthDayNanoType::make_value(-4, 6, 46000000000000),
2100 IntervalMonthDayNanoType::make_value(-3, 23, 3564000000000000),
2101 ]);
2102 let result = add(&a, &b).unwrap();
2103 assert_eq!(
2104 result.as_ref(),
2105 &IntervalMonthDayNanoArray::from(vec![
2106 IntervalMonthDayNanoType::make_value(28, 10, 50000000000000),
2107 IntervalMonthDayNanoType::make_value(29, 27, 49027000000000000)
2108 ])
2109 );
2110 let result = sub(&a, &b).unwrap();
2111 assert_eq!(
2112 result.as_ref(),
2113 &IntervalMonthDayNanoArray::from(vec![
2114 IntervalMonthDayNanoType::make_value(36, -2, -42000000000000),
2115 IntervalMonthDayNanoType::make_value(35, -19, 41899000000000000)
2116 ])
2117 );
2118 let a = IntervalMonthDayNanoArray::from(vec![IntervalMonthDayNano::MAX]);
2119 let b = IntervalMonthDayNanoArray::from(vec![IntervalMonthDayNano::ONE]);
2120 let err = add(&a, &b).unwrap_err().to_string();
2121 assert_eq!(
2122 err,
2123 "Arithmetic overflow: Overflow happened on: 2147483647 + 1"
2124 );
2125 }
2126
2127 #[test]
2128 fn test_interval_mul_i64() {
2129 let interval = IntervalYearMonthArray::from(vec![16, 5, 0]);
2130 let factor = Int64Array::from(vec![3, -2, i64::MAX]);
2131 let expected = IntervalYearMonthArray::from(vec![48, -10, 0]);
2132 assert_eq!(mul(&interval, &factor).unwrap().as_ref(), &expected);
2133 assert_eq!(mul(&factor, &interval).unwrap().as_ref(), &expected);
2134
2135 let interval = IntervalDayTimeArray::from(vec![
2136 Some(IntervalDayTimeType::make_value(10, 2 * 60 * 60 * 1000)),
2137 None,
2138 ]);
2139 let factor = Int64Array::new_scalar(3);
2140 let expected = IntervalDayTimeArray::from(vec![
2141 Some(IntervalDayTimeType::make_value(30, 6 * 60 * 60 * 1000)),
2142 None,
2143 ]);
2144 assert_eq!(mul(&interval, &factor).unwrap().as_ref(), &expected);
2145 assert_eq!(mul(&factor, &interval).unwrap().as_ref(), &expected);
2146
2147 let null_factor = Scalar::new(Int64Array::new_null(1));
2148 let expected = IntervalDayTimeArray::new_null(interval.len());
2149 assert_eq!(mul(&interval, &null_factor).unwrap().as_ref(), &expected);
2150 assert_eq!(mul(&null_factor, &interval).unwrap().as_ref(), &expected);
2151
2152 let interval = IntervalMonthDayNanoArray::new_scalar(IntervalMonthDayNanoType::make_value(
2153 12,
2154 15,
2155 5_000_000_000,
2156 ));
2157 let factor = Int64Array::from(vec![2, 0, -1]);
2158 let expected = IntervalMonthDayNanoArray::from(vec![
2159 IntervalMonthDayNanoType::make_value(24, 30, 10_000_000_000),
2160 IntervalMonthDayNanoType::make_value(0, 0, 0),
2161 IntervalMonthDayNanoType::make_value(-12, -15, -5_000_000_000),
2162 ]);
2163 assert_eq!(mul(&interval, &factor).unwrap().as_ref(), &expected);
2164 assert_eq!(mul(&factor, &interval).unwrap().as_ref(), &expected);
2165
2166 let float_factor = Float64Array::new_scalar(2.);
2167 assert!(mul_wrapping(&float_factor, &interval).is_err());
2168 assert!(mul_wrapping(&factor, &interval).is_err());
2169 }
2170
2171 #[test]
2172 fn test_interval_mul_div_f64() {
2173 const HOUR_NANOS: i64 = 3_600_000_000_000;
2174 const MINUTE_NANOS: i64 = 60_000_000_000;
2175
2176 let interval = IntervalMonthDayNanoArray::from(vec![
2181 IntervalMonthDayNanoType::make_value(41, 12, 360 * HOUR_NANOS),
2182 IntervalMonthDayNanoType::make_value(-41, -12, 360 * HOUR_NANOS),
2183 IntervalMonthDayNanoType::make_value(1, 1, 0),
2184 IntervalMonthDayNanoType::make_value(0, 0, 1),
2185 IntervalMonthDayNanoType::make_value(0, 0, 3),
2186 IntervalMonthDayNanoType::make_value(0, 0, -1),
2187 IntervalMonthDayNanoType::make_value(0, 0, -3),
2188 ]);
2189 let factor = Float64Array::from(vec![0.3, 0.3, 1.5, 0.5, 0.5, 0.5, 0.5]);
2190 let expected = IntervalMonthDayNanoArray::from(vec![
2191 IntervalMonthDayNanoType::make_value(12, 12, 122 * HOUR_NANOS + 24 * MINUTE_NANOS),
2192 IntervalMonthDayNanoType::make_value(-12, -12, 93 * HOUR_NANOS + 36 * MINUTE_NANOS),
2193 IntervalMonthDayNanoType::make_value(1, 16, 12 * HOUR_NANOS),
2194 IntervalMonthDayNanoType::make_value(0, 0, 0),
2195 IntervalMonthDayNanoType::make_value(0, 0, 2),
2196 IntervalMonthDayNanoType::make_value(0, 0, 0),
2197 IntervalMonthDayNanoType::make_value(0, 0, -2),
2198 ]);
2199 assert_eq!(mul(&interval, &factor).unwrap().as_ref(), &expected);
2200 assert_eq!(mul(&factor, &interval).unwrap().as_ref(), &expected);
2201
2202 let interval = IntervalMonthDayNanoArray::from(vec![IntervalMonthDayNanoType::make_value(
2203 9,
2204 -27,
2205 45_296 * NANOSECONDS,
2206 )]);
2207 let factor = Float64Array::new_scalar(0.3);
2208 let expected = IntervalMonthDayNanoArray::from(vec![IntervalMonthDayNanoType::make_value(
2209 2,
2210 13,
2211 4_948_800_000_000,
2212 )]);
2213 assert_eq!(mul(&interval, &factor).unwrap().as_ref(), &expected);
2214
2215 let interval = IntervalMonthDayNanoArray::from(vec![
2216 IntervalMonthDayNanoType::make_value(0, 1, 0),
2217 IntervalMonthDayNanoType::make_value(4, 0, 0),
2218 IntervalMonthDayNanoType::make_value(1, 1, 0),
2219 IntervalMonthDayNanoType::make_value(0, 0, (1_i64 << 53) - 1),
2220 IntervalMonthDayNanoType::make_value(0, 0, i64::MAX),
2221 IntervalMonthDayNanoType::make_value(1, 1, 1),
2222 IntervalMonthDayNanoType::make_value(1, 1, 1),
2223 IntervalMonthDayNanoType::make_value(1, 0, 0),
2224 ]);
2225 let factor = Float64Array::from(vec![
2226 3.,
2227 5.,
2228 2.,
2229 0.7,
2230 1.,
2231 f64::INFINITY,
2232 f64::NEG_INFINITY,
2233 -2.,
2234 ]);
2235 let expected = IntervalMonthDayNanoArray::from(vec![
2236 IntervalMonthDayNanoType::make_value(0, 0, 8 * HOUR_NANOS),
2237 IntervalMonthDayNanoType::make_value(0, 24, 0),
2238 IntervalMonthDayNanoType::make_value(0, 15, 12 * HOUR_NANOS),
2239 IntervalMonthDayNanoType::make_value(0, 0, 12_867_427_506_772_844),
2240 IntervalMonthDayNanoType::make_value(0, 0, i64::MAX),
2241 IntervalMonthDayNanoType::make_value(0, 0, 0),
2242 IntervalMonthDayNanoType::make_value(0, 0, 0),
2243 IntervalMonthDayNanoType::make_value(0, -15, 0),
2244 ]);
2245 assert_eq!(div(&interval, &factor).unwrap().as_ref(), &expected);
2246
2247 let null_factor = Scalar::new(Float64Array::new_null(1));
2248 assert_eq!(
2249 mul(&interval, &null_factor).unwrap().as_ref(),
2250 &IntervalMonthDayNanoArray::new_null(interval.len())
2251 );
2252 }
2253
2254 #[test]
2255 fn test_interval_mul_div_f64_errors() {
2256 let factor = Float64Array::new_scalar(2.);
2257 let year_month = IntervalYearMonthArray::new_scalar(1);
2258 let day_time = IntervalDayTimeArray::new_scalar(IntervalDayTime::new(1, 1));
2259 for interval in [&year_month as &dyn Datum, &day_time] {
2260 assert!(mul(interval, &factor).is_err());
2261 assert!(mul(&factor, interval).is_err());
2262 assert!(div(interval, &factor).is_err());
2263 }
2264
2265 let interval =
2266 IntervalMonthDayNanoArray::new_scalar(IntervalMonthDayNanoType::make_value(1, 1, 1));
2267
2268 assert!(matches!(
2269 add(&interval, &factor),
2270 Err(ArrowError::InvalidArgumentError(_))
2271 ));
2272
2273 let zero = Float64Array::new_scalar(-0.);
2274 assert!(matches!(
2275 div(&interval, &zero),
2276 Err(ArrowError::DivideByZero)
2277 ));
2278
2279 assert!(div(&factor, &interval).is_err());
2280
2281 for factor in [f64::NAN, f64::INFINITY, f64::NEG_INFINITY] {
2282 let factor = Float64Array::new_scalar(factor);
2283 assert!(matches!(
2284 mul(&interval, &factor),
2285 Err(ArrowError::ArithmeticOverflow(_))
2286 ));
2287 }
2288
2289 let nan = Float64Array::new_scalar(f64::NAN);
2290 assert!(matches!(
2291 div(&interval, &nan),
2292 Err(ArrowError::ArithmeticOverflow(_))
2293 ));
2294
2295 let interval = IntervalMonthDayNanoArray::new_scalar(IntervalMonthDayNanoType::make_value(
2296 i32::MAX,
2297 0,
2298 0,
2299 ));
2300 assert!(matches!(
2301 mul(&interval, &factor),
2302 Err(ArrowError::ArithmeticOverflow(_))
2303 ));
2304
2305 let factor = Float64Array::new_scalar(1.5);
2306 let interval = IntervalMonthDayNanoArray::new_scalar(IntervalMonthDayNanoType::make_value(
2307 0,
2308 0,
2309 i64::MAX,
2310 ));
2311 assert!(matches!(
2312 mul(&interval, &factor),
2313 Err(ArrowError::ArithmeticOverflow(_))
2314 ));
2315
2316 let factor = Float64Array::new_scalar(1.000_000_000_4);
2317 let interval = IntervalMonthDayNanoArray::new_scalar(IntervalMonthDayNanoType::make_value(
2318 i32::MIN,
2319 0,
2320 0,
2321 ));
2322 assert!(matches!(
2323 mul(&interval, &factor),
2324 Err(ArrowError::ArithmeticOverflow(_))
2325 ));
2326
2327 let factor = Float64Array::new_scalar(0.999_999_999);
2328 let interval = IntervalMonthDayNanoArray::new_scalar(IntervalMonthDayNanoType::make_value(
2329 1,
2330 i32::MAX,
2331 0,
2332 ));
2333 assert!(matches!(
2334 mul(&interval, &factor),
2335 Err(ArrowError::ArithmeticOverflow(_))
2336 ));
2337 }
2338
2339 #[test]
2340 fn test_interval_mul_i64_overflow() {
2341 let interval = IntervalYearMonthArray::from(vec![i32::MAX]);
2342 let factor = Int64Array::from(vec![2]);
2343 assert_eq!(
2344 mul(&interval, &factor).unwrap_err().to_string(),
2345 "Arithmetic overflow: Overflow happened on: 2147483647 * 2"
2346 );
2347
2348 let interval = IntervalMonthDayNanoArray::from(vec![IntervalMonthDayNanoType::make_value(
2349 0,
2350 0,
2351 i64::MAX,
2352 )]);
2353 assert_eq!(
2354 mul(&interval, &factor).unwrap_err().to_string(),
2355 "Arithmetic overflow: Overflow happened on: 9223372036854775807 * 2"
2356 );
2357 }
2358
2359 fn test_duration_impl<T: ArrowPrimitiveType<Native = i64>>() {
2360 let a = PrimitiveArray::<T>::new(vec![1000, 4394, -3944].into(), None);
2361 let b = PrimitiveArray::<T>::new(vec![4, -5, -243].into(), None);
2362
2363 let result = add(&a, &b).unwrap();
2364 assert_eq!(result.as_primitive::<T>().values(), &[1004, 4389, -4187]);
2365 let result = sub(&a, &b).unwrap();
2366 assert_eq!(result.as_primitive::<T>().values(), &[996, 4399, -3701]);
2367
2368 let err = mul(&a, &b).unwrap_err().to_string();
2369 assert!(
2370 err.contains("Invalid duration arithmetic operation"),
2371 "{err}"
2372 );
2373
2374 let err = div(&a, &b).unwrap_err().to_string();
2375 assert!(
2376 err.contains("Invalid duration arithmetic operation"),
2377 "{err}"
2378 );
2379
2380 let err = rem(&a, &b).unwrap_err().to_string();
2381 assert!(
2382 err.contains("Invalid duration arithmetic operation"),
2383 "{err}"
2384 );
2385
2386 let a = PrimitiveArray::<T>::new(vec![i64::MAX].into(), None);
2387 let b = PrimitiveArray::<T>::new(vec![1].into(), None);
2388 let err = add(&a, &b).unwrap_err().to_string();
2389 assert_eq!(
2390 err,
2391 "Arithmetic overflow: Overflow happened on: 9223372036854775807 + 1"
2392 );
2393 }
2394
2395 #[test]
2396 fn test_duration() {
2397 test_duration_impl::<DurationSecondType>();
2398 test_duration_impl::<DurationMillisecondType>();
2399 test_duration_impl::<DurationMicrosecondType>();
2400 test_duration_impl::<DurationNanosecondType>();
2401 }
2402
2403 fn test_date_impl<T: ArrowPrimitiveType, F>(f: F)
2404 where
2405 F: Fn(NaiveDate) -> T::Native,
2406 T::Native: TryInto<i64>,
2407 {
2408 let a = PrimitiveArray::<T>::new(
2409 vec![
2410 f(NaiveDate::from_ymd_opt(1979, 1, 30).unwrap()),
2411 f(NaiveDate::from_ymd_opt(2010, 4, 3).unwrap()),
2412 f(NaiveDate::from_ymd_opt(2008, 2, 29).unwrap()),
2413 ]
2414 .into(),
2415 None,
2416 );
2417
2418 let b = IntervalYearMonthArray::from(vec![
2419 IntervalYearMonthType::make_value(34, 2),
2420 IntervalYearMonthType::make_value(3, -3),
2421 IntervalYearMonthType::make_value(-12, 4),
2422 ]);
2423
2424 let format_array = |x: &dyn Array| -> Vec<String> {
2425 x.as_primitive::<T>()
2426 .values()
2427 .into_iter()
2428 .map(|x| {
2429 as_date::<T>((*x).try_into().ok().unwrap())
2430 .unwrap()
2431 .to_string()
2432 })
2433 .collect()
2434 };
2435
2436 let result = add(&a, &b).unwrap();
2437 assert_eq!(
2438 &format_array(result.as_ref()),
2439 &[
2440 "2013-03-30".to_string(),
2441 "2013-01-03".to_string(),
2442 "1996-06-29".to_string(),
2443 ]
2444 );
2445 let result = sub(&result, &b).unwrap();
2446 assert_eq!(result.as_ref(), &a);
2447
2448 let b = IntervalDayTimeArray::from(vec![
2449 IntervalDayTimeType::make_value(34, 2),
2450 IntervalDayTimeType::make_value(3, -3),
2451 IntervalDayTimeType::make_value(-12, 4),
2452 ]);
2453
2454 let result = add(&a, &b).unwrap();
2455 assert_eq!(
2456 &format_array(result.as_ref()),
2457 &[
2458 "1979-03-05".to_string(),
2459 "2010-04-06".to_string(),
2460 "2008-02-17".to_string(),
2461 ]
2462 );
2463 let result = sub(&result, &b).unwrap();
2464 assert_eq!(result.as_ref(), &a);
2465
2466 let b = IntervalMonthDayNanoArray::from(vec![
2467 IntervalMonthDayNanoType::make_value(34, 2, -34353534),
2468 IntervalMonthDayNanoType::make_value(3, -3, 2443),
2469 IntervalMonthDayNanoType::make_value(-12, 4, 2323242423232),
2470 ]);
2471
2472 let result = add(&a, &b).unwrap();
2473 assert_eq!(
2474 &format_array(result.as_ref()),
2475 &[
2476 "1981-12-02".to_string(),
2477 "2010-06-30".to_string(),
2478 "2007-03-04".to_string(),
2479 ]
2480 );
2481 let result = sub(&result, &b).unwrap();
2482 assert_eq!(
2483 &format_array(result.as_ref()),
2484 &[
2485 "1979-01-31".to_string(),
2486 "2010-04-02".to_string(),
2487 "2008-02-29".to_string(),
2488 ]
2489 );
2490 }
2491
2492 #[test]
2493 fn test_date() {
2494 test_date_impl::<Date32Type, _>(Date32Type::from_naive_date);
2495 test_date_impl::<Date64Type, _>(Date64Type::from_naive_date);
2496
2497 let a = Date32Array::from(vec![i32::MIN, i32::MAX, 23, 7684]);
2498 let b = Date32Array::from(vec![i32::MIN, i32::MIN, -2, 45]);
2499 let result = sub(&a, &b).unwrap();
2500 assert_eq!(
2501 result.as_primitive::<DurationSecondType>().values(),
2502 &[0, 371085174288000, 2160000, 660009600]
2503 );
2504
2505 let a = Date64Array::from(vec![4343, 76676, 3434]);
2506 let b = Date64Array::from(vec![3, -5, 5]);
2507 let result = sub(&a, &b).unwrap();
2508 assert_eq!(
2509 result.as_primitive::<DurationMillisecondType>().values(),
2510 &[4340, 76681, 3429]
2511 );
2512
2513 let a = Date64Array::from(vec![i64::MAX]);
2514 let b = Date64Array::from(vec![-1]);
2515 let err = sub(&a, &b).unwrap_err().to_string();
2516 assert_eq!(
2517 err,
2518 "Arithmetic overflow: Overflow happened on: 9223372036854775807 - -1"
2519 );
2520 }
2521
2522 #[test]
2523 fn test_date32_to_naive_date_opt_boundaries() {
2524 assert_eq!(MAX_VALID_DAYS, 95026236);
2525 assert_eq!(MIN_VALID_DAYS, -96465292);
2526
2527 assert!(Date32Type::to_naive_date_opt(MAX_VALID_DAYS).is_some());
2529 assert!(Date32Type::to_naive_date_opt(MIN_VALID_DAYS).is_some());
2530
2531 assert!(Date32Type::to_naive_date_opt(MAX_VALID_DAYS + 1).is_none());
2533 assert!(Date32Type::to_naive_date_opt(MIN_VALID_DAYS - 1).is_none());
2534
2535 assert!(Date32Type::to_naive_date_opt(i32::MAX).is_none());
2537 assert!(Date32Type::to_naive_date_opt(i32::MIN).is_none());
2538
2539 assert!(Date32Type::to_naive_date_opt(0).is_some());
2541 assert!(Date32Type::to_naive_date_opt(date_to_days(YEAR_2000)).is_some());
2542 }
2543
2544 #[test]
2545 fn test_date64_to_naive_date_opt_boundaries() {
2546 const MS_PER_DAY: i64 = 24 * 60 * 60 * 1000;
2547
2548 assert_eq!(MAX_VALID_MILLIS, 8210266790400000i64);
2550 assert_eq!(MIN_VALID_MILLIS, -8334601228800000i64);
2551
2552 assert!(Date64Type::to_naive_date_opt(MAX_VALID_MILLIS).is_some());
2554 assert!(Date64Type::to_naive_date_opt(MIN_VALID_MILLIS).is_some());
2555
2556 assert!(Date64Type::to_naive_date_opt(MAX_VALID_MILLIS + MS_PER_DAY).is_none());
2558 assert!(Date64Type::to_naive_date_opt(MIN_VALID_MILLIS - MS_PER_DAY).is_none());
2559
2560 assert!(Date64Type::to_naive_date_opt(i64::MAX).is_none());
2562 assert!(Date64Type::to_naive_date_opt(i64::MIN).is_none());
2563
2564 assert!(Date64Type::to_naive_date_opt(0).is_some());
2566 assert!(Date64Type::to_naive_date_opt(date_to_millis(YEAR_2000)).is_some());
2567 }
2568
2569 macro_rules! test_year_month_ops {
2570 ($type:ty, $date_fn:expr) => {{
2571 let date = $date_fn(YEAR_2000);
2572
2573 assert!(
2575 <$type>::add_year_months_opt(date, 120).is_some(),
2576 "add_year_months: normal add"
2577 );
2578 assert!(
2579 <$type>::add_year_months_opt(date, 0).is_some(),
2580 "add_year_months: zero interval"
2581 );
2582 assert!(
2583 <$type>::subtract_year_months_opt(date, 120).is_some(),
2584 "subtract_year_months: normal subtract"
2585 );
2586 assert!(
2587 <$type>::subtract_year_months_opt(date, 0).is_some(),
2588 "subtract_year_months: zero interval"
2589 );
2590
2591 let large_year = $date_fn(NaiveDate::from_ymd_opt(5000, 1, 1).unwrap());
2593 let neg_year = $date_fn(NaiveDate::from_ymd_opt(-5000, 12, 31).unwrap());
2594 assert!(
2595 <$type>::add_year_months_opt(large_year, 12).is_some(),
2596 "add_year_months: large year"
2597 );
2598 assert!(
2599 <$type>::add_year_months_opt(neg_year, -12).is_some(),
2600 "add_year_months: negative year"
2601 );
2602 assert!(
2603 <$type>::subtract_year_months_opt(large_year, 12).is_some(),
2604 "subtract_year_months: large year"
2605 );
2606 assert!(
2607 <$type>::subtract_year_months_opt(neg_year, -12).is_some(),
2608 "subtract_year_months: negative year"
2609 );
2610
2611 assert!(
2613 <$type>::subtract_year_months_opt($date_fn(MIN_VALID_DATE), 1).is_none(),
2614 "subtract_year_months: overflow days from min"
2615 );
2616 assert!(
2617 <$type>::subtract_year_months_opt($date_fn(MAX_VALID_DATE), -1).is_none(),
2618 "subtract_year_months: overflow neg days from max"
2619 );
2620 assert!(
2621 <$type>::add_year_months_opt($date_fn(MAX_VALID_DATE), 1).is_none(),
2622 "add_year_months: overflow days"
2623 );
2624 assert!(
2625 <$type>::add_year_months_opt($date_fn(MIN_VALID_DATE), -1).is_none(),
2626 "add_year_months: overflow neg days"
2627 );
2628 }};
2629 }
2630
2631 #[test]
2632 fn test_date_year_month_operations() {
2633 test_year_month_ops!(Date32Type, date_to_days);
2634 test_year_month_ops!(Date64Type, date_to_millis);
2635 }
2636
2637 macro_rules! test_day_time_ops {
2638 ($type:ty, $date_fn:expr) => {{
2639 let date = $date_fn(YEAR_2000);
2640
2641 assert!(
2643 <$type>::add_day_time_opt(date, IntervalDayTime::new(30, 0)).is_some(),
2644 "add_day_time: +30 days"
2645 );
2646 assert!(
2647 <$type>::add_day_time_opt(date, IntervalDayTime::new(-30, 0)).is_some(),
2648 "add_day_time: -30 days"
2649 );
2650 assert!(
2651 <$type>::add_day_time_opt(date, IntervalDayTime::new(1000, 12345)).is_some(),
2652 "add_day_time: normal"
2653 );
2654 assert!(
2655 <$type>::subtract_day_time_opt(date, IntervalDayTime::new(30, 0)).is_some(),
2656 "subtract_day_time: +30 days"
2657 );
2658 assert!(
2659 <$type>::subtract_day_time_opt(date, IntervalDayTime::new(-30, 0)).is_some(),
2660 "subtract_day_time: -30 days"
2661 );
2662 assert!(
2663 <$type>::subtract_day_time_opt(date, IntervalDayTime::new(1000, 12345)).is_some(),
2664 "subtract_day_time: normal"
2665 );
2666
2667 assert!(
2669 <$type>::subtract_day_time_opt(
2670 $date_fn(MIN_VALID_DATE),
2671 IntervalDayTime::new(1, 0)
2672 )
2673 .is_none(),
2674 "subtract_day_time: overflow days from min"
2675 );
2676 assert!(
2677 <$type>::subtract_day_time_opt(
2678 $date_fn(MAX_VALID_DATE),
2679 IntervalDayTime::new(-1, 0)
2680 )
2681 .is_none(),
2682 "subtract_day_time: overflow neg days from max"
2683 );
2684
2685 assert!(
2687 <$type>::add_day_time_opt($date_fn(MAX_VALID_DATE), IntervalDayTime::new(1, 0))
2688 .is_none(),
2689 "add_day_time: overflow days"
2690 );
2691 assert!(
2692 <$type>::add_day_time_opt($date_fn(MIN_VALID_DATE), IntervalDayTime::new(-1, 0))
2693 .is_none(),
2694 "add_day_time: overflow neg days"
2695 );
2696
2697 assert!(
2699 <$type>::add_day_time_opt(
2700 $date_fn(EPOCH),
2701 IntervalDayTime::new(i32::MAX, i32::MAX)
2702 )
2703 .is_none(),
2704 "add_day_time: max interval"
2705 );
2706 assert!(
2707 <$type>::add_day_time_opt(
2708 $date_fn(EPOCH),
2709 IntervalDayTime::new(i32::MIN, i32::MIN)
2710 )
2711 .is_none(),
2712 "add_day_time: min interval"
2713 );
2714 assert!(
2715 <$type>::subtract_day_time_opt(
2716 $date_fn(EPOCH),
2717 IntervalDayTime::new(i32::MAX, i32::MAX)
2718 )
2719 .is_none(),
2720 "subtract_day_time: max interval"
2721 );
2722 assert!(
2723 <$type>::subtract_day_time_opt(
2724 $date_fn(EPOCH),
2725 IntervalDayTime::new(i32::MIN, i32::MIN)
2726 )
2727 .is_none(),
2728 "subtract_day_time: min interval"
2729 );
2730 }};
2731 }
2732
2733 #[test]
2734 fn test_date_day_time_operations() {
2735 test_day_time_ops!(Date32Type, date_to_days);
2736 test_day_time_ops!(Date64Type, date_to_millis);
2737 }
2738
2739 macro_rules! test_month_day_nano_ops {
2740 ($type:ty, $date_fn:expr) => {{
2741 let date = $date_fn(YEAR_2000);
2742 let zero = IntervalMonthDayNano::new(0, 0, 0);
2743
2744 assert!(
2746 <$type>::add_month_day_nano_opt(date, IntervalMonthDayNano::new(1, 30, 0))
2747 .is_some(),
2748 "add_month_day_nano: +1mo +30d"
2749 );
2750 assert!(
2751 <$type>::add_month_day_nano_opt(date, IntervalMonthDayNano::new(-1, -30, 0))
2752 .is_some(),
2753 "add_month_day_nano: -1mo -30d"
2754 );
2755 assert!(
2756 <$type>::add_month_day_nano_opt(date, zero).is_some(),
2757 "add_month_day_nano: zero interval"
2758 );
2759 assert!(
2760 <$type>::add_month_day_nano_opt(
2761 date,
2762 IntervalMonthDayNano::new(2, 10, 123_456_789_000)
2763 )
2764 .is_some(),
2765 "add_month_day_nano: normal"
2766 );
2767 assert!(
2768 <$type>::subtract_month_day_nano_opt(date, IntervalMonthDayNano::new(1, 30, 0))
2769 .is_some(),
2770 "subtract_month_day_nano: +1mo +30d"
2771 );
2772 assert!(
2773 <$type>::subtract_month_day_nano_opt(date, IntervalMonthDayNano::new(-1, -30, 0))
2774 .is_some(),
2775 "subtract_month_day_nano: -1mo -30d"
2776 );
2777 assert!(
2778 <$type>::subtract_month_day_nano_opt(date, zero).is_some(),
2779 "subtract_month_day_nano: zero interval"
2780 );
2781 assert!(
2782 <$type>::subtract_month_day_nano_opt(
2783 date,
2784 IntervalMonthDayNano::new(2, 10, 123_456_789_000)
2785 )
2786 .is_some(),
2787 "subtract_month_day_nano: normal"
2788 );
2789
2790 assert!(
2792 <$type>::subtract_month_day_nano_opt(
2793 $date_fn(MIN_VALID_DATE),
2794 IntervalMonthDayNano::new(0, 1, 0)
2795 )
2796 .is_none(),
2797 "subtract_month_day_nano: overflow days from min"
2798 );
2799 assert!(
2800 <$type>::subtract_month_day_nano_opt(
2801 $date_fn(MAX_VALID_DATE),
2802 IntervalMonthDayNano::new(0, -1, 0)
2803 )
2804 .is_none(),
2805 "subtract_month_day_nano: overflow neg days from max"
2806 );
2807
2808 assert!(
2810 <$type>::add_month_day_nano_opt(
2811 $date_fn(MAX_VALID_DATE),
2812 IntervalMonthDayNano::new(0, 1, 0)
2813 )
2814 .is_none(),
2815 "add_month_day_nano: overflow days"
2816 );
2817 assert!(
2818 <$type>::add_month_day_nano_opt(
2819 $date_fn(MIN_VALID_DATE),
2820 IntervalMonthDayNano::new(0, -1, 0)
2821 )
2822 .is_none(),
2823 "add_month_day_nano: overflow neg days"
2824 );
2825
2826 assert!(
2828 <$type>::add_month_day_nano_opt(date, IntervalMonthDayNano::new(0, 0, 999_999_999))
2829 .is_some(),
2830 "add_month_day_nano: nanos"
2831 );
2832 assert!(
2833 <$type>::subtract_month_day_nano_opt(
2834 date,
2835 IntervalMonthDayNano::new(0, 0, 999_999_999)
2836 )
2837 .is_some(),
2838 "subtract_month_day_nano: nanos"
2839 );
2840 assert!(
2842 <$type>::add_month_day_nano_opt(
2843 date,
2844 IntervalMonthDayNano::new(0, 0, 86_400_000_000_000)
2845 )
2846 .is_some(),
2847 "add_month_day_nano: 1 day nanos"
2848 );
2849 assert!(
2850 <$type>::subtract_month_day_nano_opt(
2851 date,
2852 IntervalMonthDayNano::new(0, 0, 86_400_000_000_000)
2853 )
2854 .is_some(),
2855 "subtract_month_day_nano: 1 day nanos"
2856 );
2857 }};
2858 }
2859
2860 #[test]
2861 fn test_date_month_day_nano_operations() {
2862 test_month_day_nano_ops!(Date32Type, date_to_days);
2863 test_month_day_nano_ops!(Date64Type, date_to_millis);
2864 }
2865
2866 #[test]
2867 fn test_date_sub_interval_min_months() {
2868 let dates: [ArrayRef; 2] = [
2873 Arc::new(Date32Array::from(vec![0])),
2874 Arc::new(Date64Array::from(vec![0])),
2875 ];
2876 let year_month = IntervalYearMonthArray::from(vec![i32::MIN]);
2877 let month_day_nano =
2878 IntervalMonthDayNanoArray::from(vec![IntervalMonthDayNano::new(i32::MIN, 0, 0)]);
2879 for dates in &dates {
2880 assert_eq!(
2881 sub(dates, &year_month).unwrap_err().to_string(),
2882 "Compute error: Date arithmetic overflow: 0 - -2147483648 months"
2883 );
2884 assert_eq!(
2885 sub(dates, &month_day_nano).unwrap_err().to_string(),
2886 "Compute error: Date arithmetic overflow: 0 - IntervalMonthDayNano { months: -2147483648, days: 0, nanoseconds: 0 }"
2887 );
2888 }
2889 }
2890}