1use arrow_buffer::{ArrowNativeType, IntervalDayTime, IntervalMonthDayNano, i256};
19use arrow_schema::ArrowError;
20use half::f16;
21use num_complex::ComplexFloat;
22use std::cmp::Ordering;
23
24pub trait ArrowNativeTypeOp: ArrowNativeType {
43 const ZERO: Self;
45
46 const ONE: Self;
48
49 const MIN_TOTAL_ORDER: Self;
53
54 const MAX_TOTAL_ORDER: Self;
58
59 fn add_checked(self, rhs: Self) -> Result<Self, ArrowError>;
61
62 fn add_wrapping(self, rhs: Self) -> Self;
64
65 fn sub_checked(self, rhs: Self) -> Result<Self, ArrowError>;
67
68 fn sub_wrapping(self, rhs: Self) -> Self;
70
71 fn mul_checked(self, rhs: Self) -> Result<Self, ArrowError>;
73
74 fn mul_wrapping(self, rhs: Self) -> Self;
76
77 fn div_checked(self, rhs: Self) -> Result<Self, ArrowError>;
79
80 fn div_wrapping(self, rhs: Self) -> Self;
86
87 fn mod_checked(self, rhs: Self) -> Result<Self, ArrowError>;
89
90 fn mod_wrapping(self, rhs: Self) -> Self;
96
97 #[inline]
110 fn div_rem_checked(self, rhs: Self) -> Result<(Self, Self), ArrowError> {
111 Ok((self.div_checked(rhs)?, self.mod_checked(rhs)?))
112 }
113
114 #[inline]
130 fn div_rem_wrapping(self, rhs: Self) -> (Self, Self) {
131 (self.div_wrapping(rhs), self.mod_wrapping(rhs))
132 }
133
134 fn neg_checked(self) -> Result<Self, ArrowError>;
136
137 fn neg_wrapping(self) -> Self;
139
140 fn pow_checked(self, exp: u32) -> Result<Self, ArrowError>;
142
143 fn pow_wrapping(self, exp: u32) -> Self;
145
146 fn is_zero(self) -> bool;
148
149 fn compare(self, rhs: Self) -> Ordering;
151
152 fn is_eq(self, rhs: Self) -> bool;
154
155 #[inline]
157 fn is_ne(self, rhs: Self) -> bool {
158 !self.is_eq(rhs)
159 }
160
161 #[inline]
163 fn is_lt(self, rhs: Self) -> bool {
164 self.compare(rhs).is_lt()
165 }
166
167 #[inline]
169 fn is_le(self, rhs: Self) -> bool {
170 self.compare(rhs).is_le()
171 }
172
173 #[inline]
175 fn is_gt(self, rhs: Self) -> bool {
176 self.compare(rhs).is_gt()
177 }
178
179 #[inline]
181 fn is_ge(self, rhs: Self) -> bool {
182 self.compare(rhs).is_ge()
183 }
184}
185
186macro_rules! native_type_op {
187 ($t:tt) => {
188 native_type_op!($t, 0, 1);
189 };
190 ($t:tt, $zero:expr, $one: expr) => {
191 native_type_op!($t, $zero, $one, $t::MIN, $t::MAX);
192 };
193 ($t:tt, $zero:expr, $one: expr, $min: expr, $max: expr $(, $extra:item)*) => {
194 impl ArrowNativeTypeOp for $t {
195 $($extra)*
196
197 const ZERO: Self = $zero;
198 const ONE: Self = $one;
199 const MIN_TOTAL_ORDER: Self = $min;
200 const MAX_TOTAL_ORDER: Self = $max;
201
202 #[inline]
203 fn add_checked(self, rhs: Self) -> Result<Self, ArrowError> {
204 self.checked_add(rhs).ok_or_else(|| {
205 ArrowError::ArithmeticOverflow(format!(
206 "Overflow happened on: {:?} + {:?}",
207 self, rhs
208 ))
209 })
210 }
211
212 #[inline]
213 fn add_wrapping(self, rhs: Self) -> Self {
214 self.wrapping_add(rhs)
215 }
216
217 #[inline]
218 fn sub_checked(self, rhs: Self) -> Result<Self, ArrowError> {
219 self.checked_sub(rhs).ok_or_else(|| {
220 ArrowError::ArithmeticOverflow(format!(
221 "Overflow happened on: {:?} - {:?}",
222 self, rhs
223 ))
224 })
225 }
226
227 #[inline]
228 fn sub_wrapping(self, rhs: Self) -> Self {
229 self.wrapping_sub(rhs)
230 }
231
232 #[inline]
233 fn mul_checked(self, rhs: Self) -> Result<Self, ArrowError> {
234 self.checked_mul(rhs).ok_or_else(|| {
235 ArrowError::ArithmeticOverflow(format!(
236 "Overflow happened on: {:?} * {:?}",
237 self, rhs
238 ))
239 })
240 }
241
242 #[inline]
243 fn mul_wrapping(self, rhs: Self) -> Self {
244 self.wrapping_mul(rhs)
245 }
246
247 #[inline]
248 fn div_checked(self, rhs: Self) -> Result<Self, ArrowError> {
249 if rhs.is_zero() {
250 Err(ArrowError::DivideByZero)
251 } else {
252 self.checked_div(rhs).ok_or_else(|| {
253 ArrowError::ArithmeticOverflow(format!(
254 "Overflow happened on: {:?} / {:?}",
255 self, rhs
256 ))
257 })
258 }
259 }
260
261 #[inline]
262 fn div_wrapping(self, rhs: Self) -> Self {
263 self.wrapping_div(rhs)
264 }
265
266 #[inline]
267 fn mod_checked(self, rhs: Self) -> Result<Self, ArrowError> {
268 if rhs.is_zero() {
269 Err(ArrowError::DivideByZero)
270 } else {
271 self.checked_rem(rhs).ok_or_else(|| {
272 ArrowError::ArithmeticOverflow(format!(
273 "Overflow happened on: {:?} % {:?}",
274 self, rhs
275 ))
276 })
277 }
278 }
279
280 #[inline]
281 fn mod_wrapping(self, rhs: Self) -> Self {
282 self.wrapping_rem(rhs)
283 }
284
285 #[inline]
286 fn neg_checked(self) -> Result<Self, ArrowError> {
287 self.checked_neg().ok_or_else(|| {
288 ArrowError::ArithmeticOverflow(format!("Overflow happened on: - {:?}", self))
289 })
290 }
291
292 #[inline]
293 fn pow_checked(self, exp: u32) -> Result<Self, ArrowError> {
294 self.checked_pow(exp).ok_or_else(|| {
295 ArrowError::ArithmeticOverflow(format!(
296 "Overflow happened on: {:?} ^ {exp:?}",
297 self
298 ))
299 })
300 }
301
302 #[inline]
303 fn pow_wrapping(self, exp: u32) -> Self {
304 self.wrapping_pow(exp)
305 }
306
307 #[inline]
308 fn neg_wrapping(self) -> Self {
309 self.wrapping_neg()
310 }
311
312 #[inline]
313 fn is_zero(self) -> bool {
314 self == Self::ZERO
315 }
316
317 #[inline]
318 fn compare(self, rhs: Self) -> Ordering {
319 self.cmp(&rhs)
320 }
321
322 #[inline]
323 fn is_eq(self, rhs: Self) -> bool {
324 self == rhs
325 }
326 }
327 };
328}
329
330native_type_op!(i8);
331native_type_op!(i16);
332native_type_op!(i32);
333native_type_op!(i64);
334native_type_op!(i128);
335native_type_op!(u8);
336native_type_op!(u16);
337native_type_op!(u32);
338native_type_op!(u64);
339native_type_op!(
340 i256,
341 i256::ZERO,
342 i256::ONE,
343 i256::MIN,
344 i256::MAX,
345 #[inline]
346 fn div_rem_checked(self, rhs: Self) -> Result<(Self, Self), ArrowError> {
347 if rhs.is_zero() {
348 return Err(ArrowError::DivideByZero);
349 }
350 self.checked_div_rem(rhs).ok_or_else(|| {
351 ArrowError::ArithmeticOverflow(format!("Overflow happened on: {self:?} / {rhs:?}"))
352 })
353 },
354 #[inline]
355 fn div_rem_wrapping(self, rhs: Self) -> (Self, Self) {
356 self.wrapping_div_rem(rhs)
357 }
358);
359
360native_type_op!(IntervalDayTime, IntervalDayTime::ZERO, IntervalDayTime::ONE);
361native_type_op!(
362 IntervalMonthDayNano,
363 IntervalMonthDayNano::ZERO,
364 IntervalMonthDayNano::ONE
365);
366
367macro_rules! native_type_float_op {
368 ($t:tt, $zero:expr, $one:expr, $min:expr, $max:expr) => {
369 impl ArrowNativeTypeOp for $t {
370 const ZERO: Self = $zero;
371 const ONE: Self = $one;
372 const MIN_TOTAL_ORDER: Self = $min;
373 const MAX_TOTAL_ORDER: Self = $max;
374
375 #[inline]
376 fn add_checked(self, rhs: Self) -> Result<Self, ArrowError> {
377 Ok(self + rhs)
378 }
379
380 #[inline]
381 fn add_wrapping(self, rhs: Self) -> Self {
382 self + rhs
383 }
384
385 #[inline]
386 fn sub_checked(self, rhs: Self) -> Result<Self, ArrowError> {
387 Ok(self - rhs)
388 }
389
390 #[inline]
391 fn sub_wrapping(self, rhs: Self) -> Self {
392 self - rhs
393 }
394
395 #[inline]
396 fn mul_checked(self, rhs: Self) -> Result<Self, ArrowError> {
397 Ok(self * rhs)
398 }
399
400 #[inline]
401 fn mul_wrapping(self, rhs: Self) -> Self {
402 self * rhs
403 }
404
405 #[inline]
406 fn div_checked(self, rhs: Self) -> Result<Self, ArrowError> {
407 if rhs.is_zero() {
408 Err(ArrowError::DivideByZero)
409 } else {
410 Ok(self / rhs)
411 }
412 }
413
414 #[inline]
415 fn div_wrapping(self, rhs: Self) -> Self {
416 self / rhs
417 }
418
419 #[inline]
420 fn mod_checked(self, rhs: Self) -> Result<Self, ArrowError> {
421 if rhs.is_zero() {
422 Err(ArrowError::DivideByZero)
423 } else {
424 Ok(self % rhs)
425 }
426 }
427
428 #[inline]
429 fn mod_wrapping(self, rhs: Self) -> Self {
430 self % rhs
431 }
432
433 #[inline]
434 fn neg_checked(self) -> Result<Self, ArrowError> {
435 Ok(-self)
436 }
437
438 #[inline]
439 fn neg_wrapping(self) -> Self {
440 -self
441 }
442
443 #[inline]
444 fn pow_checked(self, exp: u32) -> Result<Self, ArrowError> {
445 Ok(self.powi(exp as i32))
446 }
447
448 #[inline]
449 fn pow_wrapping(self, exp: u32) -> Self {
450 self.powi(exp as i32)
451 }
452
453 #[inline]
454 fn is_zero(self) -> bool {
455 self == $zero
456 }
457
458 #[inline]
459 fn compare(self, rhs: Self) -> Ordering {
460 <$t>::total_cmp(&self, &rhs)
461 }
462
463 #[inline]
464 fn is_eq(self, rhs: Self) -> bool {
465 self.to_bits() == rhs.to_bits()
469 }
470 }
471 };
472}
473
474native_type_float_op!(
477 f16,
478 f16::ZERO,
479 f16::ONE,
480 f16::from_bits(-1 as _),
481 f16::from_bits(i16::MAX as _)
482);
483native_type_float_op!(
484 f32,
485 0.,
486 1.,
487 f32::from_bits(-1_i32 as _),
488 f32::from_bits(i32::MAX as _)
489);
490native_type_float_op!(
491 f64,
492 0.,
493 1.,
494 f64::from_bits(-1_i64 as _),
495 f64::from_bits(i64::MAX as _)
496);
497
498#[cfg(test)]
499mod tests {
500 use super::*;
501
502 macro_rules! assert_approx_eq {
503 ( $x: expr, $y: expr ) => {{ assert_approx_eq!($x, $y, 1.0e-4) }};
504 ( $x: expr, $y: expr, $tol: expr ) => {{
505 let x_val = $x;
506 let y_val = $y;
507 let diff = f64::from((x_val - y_val).abs());
508 assert!(
509 diff <= $tol,
510 "{} != {} (with tolerance = {})",
511 x_val,
512 y_val,
513 $tol
514 );
515 }};
516 }
517
518 #[test]
519 fn test_native_type_is_zero() {
520 assert!(0_i8.is_zero());
521 assert!(0_i16.is_zero());
522 assert!(0_i32.is_zero());
523 assert!(0_i64.is_zero());
524 assert!(0_i128.is_zero());
525 assert!(i256::ZERO.is_zero());
526 assert!(0_u8.is_zero());
527 assert!(0_u16.is_zero());
528 assert!(0_u32.is_zero());
529 assert!(0_u64.is_zero());
530 assert!(f16::ZERO.is_zero());
531 assert!(0.0_f32.is_zero());
532 assert!(0.0_f64.is_zero());
533 }
534
535 #[test]
536 #[cfg_attr(miri, ignore)] fn test_native_type_comparison() {
538 assert!(8_i8.is_eq(8_i8));
540 assert!(8_i16.is_eq(8_i16));
541 assert!(8_i32.is_eq(8_i32));
542 assert!(8_i64.is_eq(8_i64));
543 assert!(8_i128.is_eq(8_i128));
544 assert!(i256::from_parts(8, 0).is_eq(i256::from_parts(8, 0)));
545 assert!(8_u8.is_eq(8_u8));
546 assert!(8_u16.is_eq(8_u16));
547 assert!(8_u32.is_eq(8_u32));
548 assert!(8_u64.is_eq(8_u64));
549 assert!(f16::from_f32(8.0).is_eq(f16::from_f32(8.0)));
550 assert!(8.0_f32.is_eq(8.0_f32));
551 assert!(8.0_f64.is_eq(8.0_f64));
552
553 assert!(8_i8.is_ne(1_i8));
555 assert!(8_i16.is_ne(1_i16));
556 assert!(8_i32.is_ne(1_i32));
557 assert!(8_i64.is_ne(1_i64));
558 assert!(8_i128.is_ne(1_i128));
559 assert!(i256::from_parts(8, 0).is_ne(i256::from_parts(1, 0)));
560 assert!(8_u8.is_ne(1_u8));
561 assert!(8_u16.is_ne(1_u16));
562 assert!(8_u32.is_ne(1_u32));
563 assert!(8_u64.is_ne(1_u64));
564 assert!(f16::from_f32(8.0).is_ne(f16::from_f32(1.0)));
565 assert!(8.0_f32.is_ne(1.0_f32));
566 assert!(8.0_f64.is_ne(1.0_f64));
567
568 assert!(8_i8.is_lt(10_i8));
570 assert!(8_i16.is_lt(10_i16));
571 assert!(8_i32.is_lt(10_i32));
572 assert!(8_i64.is_lt(10_i64));
573 assert!(8_i128.is_lt(10_i128));
574 assert!(i256::from_parts(8, 0).is_lt(i256::from_parts(10, 0)));
575 assert!(8_u8.is_lt(10_u8));
576 assert!(8_u16.is_lt(10_u16));
577 assert!(8_u32.is_lt(10_u32));
578 assert!(8_u64.is_lt(10_u64));
579 assert!(f16::from_f32(8.0).is_lt(f16::from_f32(10.0)));
580 assert!(8.0_f32.is_lt(10.0_f32));
581 assert!(8.0_f64.is_lt(10.0_f64));
582
583 assert!(8_i8.is_gt(1_i8));
585 assert!(8_i16.is_gt(1_i16));
586 assert!(8_i32.is_gt(1_i32));
587 assert!(8_i64.is_gt(1_i64));
588 assert!(8_i128.is_gt(1_i128));
589 assert!(i256::from_parts(8, 0).is_gt(i256::from_parts(1, 0)));
590 assert!(8_u8.is_gt(1_u8));
591 assert!(8_u16.is_gt(1_u16));
592 assert!(8_u32.is_gt(1_u32));
593 assert!(8_u64.is_gt(1_u64));
594 assert!(f16::from_f32(8.0).is_gt(f16::from_f32(1.0)));
595 assert!(8.0_f32.is_gt(1.0_f32));
596 assert!(8.0_f64.is_gt(1.0_f64));
597 }
598
599 #[test]
600 #[cfg_attr(miri, ignore)] fn test_native_type_add() {
602 assert_eq!(8_i8.add_wrapping(2_i8), 10_i8);
604 assert_eq!(8_i16.add_wrapping(2_i16), 10_i16);
605 assert_eq!(8_i32.add_wrapping(2_i32), 10_i32);
606 assert_eq!(8_i64.add_wrapping(2_i64), 10_i64);
607 assert_eq!(8_i128.add_wrapping(2_i128), 10_i128);
608 assert_eq!(
609 i256::from_parts(8, 0).add_wrapping(i256::from_parts(2, 0)),
610 i256::from_parts(10, 0)
611 );
612 assert_eq!(8_u8.add_wrapping(2_u8), 10_u8);
613 assert_eq!(8_u16.add_wrapping(2_u16), 10_u16);
614 assert_eq!(8_u32.add_wrapping(2_u32), 10_u32);
615 assert_eq!(8_u64.add_wrapping(2_u64), 10_u64);
616 assert_eq!(
617 f16::from_f32(8.0).add_wrapping(f16::from_f32(2.0)),
618 f16::from_f32(10.0)
619 );
620 assert_eq!(8.0_f32.add_wrapping(2.0_f32), 10_f32);
621 assert_eq!(8.0_f64.add_wrapping(2.0_f64), 10_f64);
622
623 assert_eq!(8_i8.add_checked(2_i8).unwrap(), 10_i8);
625 assert_eq!(8_i16.add_checked(2_i16).unwrap(), 10_i16);
626 assert_eq!(8_i32.add_checked(2_i32).unwrap(), 10_i32);
627 assert_eq!(8_i64.add_checked(2_i64).unwrap(), 10_i64);
628 assert_eq!(8_i128.add_checked(2_i128).unwrap(), 10_i128);
629 assert_eq!(
630 i256::from_parts(8, 0)
631 .add_checked(i256::from_parts(2, 0))
632 .unwrap(),
633 i256::from_parts(10, 0)
634 );
635 assert_eq!(8_u8.add_checked(2_u8).unwrap(), 10_u8);
636 assert_eq!(8_u16.add_checked(2_u16).unwrap(), 10_u16);
637 assert_eq!(8_u32.add_checked(2_u32).unwrap(), 10_u32);
638 assert_eq!(8_u64.add_checked(2_u64).unwrap(), 10_u64);
639 assert_eq!(
640 f16::from_f32(8.0).add_checked(f16::from_f32(2.0)).unwrap(),
641 f16::from_f32(10.0)
642 );
643 assert_eq!(8.0_f32.add_checked(2.0_f32).unwrap(), 10_f32);
644 assert_eq!(8.0_f64.add_checked(2.0_f64).unwrap(), 10_f64);
645 }
646
647 #[test]
648 #[cfg_attr(miri, ignore)] fn test_native_type_sub() {
650 assert_eq!(8_i8.sub_wrapping(2_i8), 6_i8);
652 assert_eq!(8_i16.sub_wrapping(2_i16), 6_i16);
653 assert_eq!(8_i32.sub_wrapping(2_i32), 6_i32);
654 assert_eq!(8_i64.sub_wrapping(2_i64), 6_i64);
655 assert_eq!(8_i128.sub_wrapping(2_i128), 6_i128);
656 assert_eq!(
657 i256::from_parts(8, 0).sub_wrapping(i256::from_parts(2, 0)),
658 i256::from_parts(6, 0)
659 );
660 assert_eq!(8_u8.sub_wrapping(2_u8), 6_u8);
661 assert_eq!(8_u16.sub_wrapping(2_u16), 6_u16);
662 assert_eq!(8_u32.sub_wrapping(2_u32), 6_u32);
663 assert_eq!(8_u64.sub_wrapping(2_u64), 6_u64);
664 assert_eq!(
665 f16::from_f32(8.0).sub_wrapping(f16::from_f32(2.0)),
666 f16::from_f32(6.0)
667 );
668 assert_eq!(8.0_f32.sub_wrapping(2.0_f32), 6_f32);
669 assert_eq!(8.0_f64.sub_wrapping(2.0_f64), 6_f64);
670
671 assert_eq!(8_i8.sub_checked(2_i8).unwrap(), 6_i8);
673 assert_eq!(8_i16.sub_checked(2_i16).unwrap(), 6_i16);
674 assert_eq!(8_i32.sub_checked(2_i32).unwrap(), 6_i32);
675 assert_eq!(8_i64.sub_checked(2_i64).unwrap(), 6_i64);
676 assert_eq!(8_i128.sub_checked(2_i128).unwrap(), 6_i128);
677 assert_eq!(
678 i256::from_parts(8, 0)
679 .sub_checked(i256::from_parts(2, 0))
680 .unwrap(),
681 i256::from_parts(6, 0)
682 );
683 assert_eq!(8_u8.sub_checked(2_u8).unwrap(), 6_u8);
684 assert_eq!(8_u16.sub_checked(2_u16).unwrap(), 6_u16);
685 assert_eq!(8_u32.sub_checked(2_u32).unwrap(), 6_u32);
686 assert_eq!(8_u64.sub_checked(2_u64).unwrap(), 6_u64);
687 assert_eq!(
688 f16::from_f32(8.0).sub_checked(f16::from_f32(2.0)).unwrap(),
689 f16::from_f32(6.0)
690 );
691 assert_eq!(8.0_f32.sub_checked(2.0_f32).unwrap(), 6_f32);
692 assert_eq!(8.0_f64.sub_checked(2.0_f64).unwrap(), 6_f64);
693 }
694
695 #[test]
696 #[cfg_attr(miri, ignore)] fn test_native_type_mul() {
698 assert_eq!(8_i8.mul_wrapping(2_i8), 16_i8);
700 assert_eq!(8_i16.mul_wrapping(2_i16), 16_i16);
701 assert_eq!(8_i32.mul_wrapping(2_i32), 16_i32);
702 assert_eq!(8_i64.mul_wrapping(2_i64), 16_i64);
703 assert_eq!(8_i128.mul_wrapping(2_i128), 16_i128);
704 assert_eq!(
705 i256::from_parts(8, 0).mul_wrapping(i256::from_parts(2, 0)),
706 i256::from_parts(16, 0)
707 );
708 assert_eq!(8_u8.mul_wrapping(2_u8), 16_u8);
709 assert_eq!(8_u16.mul_wrapping(2_u16), 16_u16);
710 assert_eq!(8_u32.mul_wrapping(2_u32), 16_u32);
711 assert_eq!(8_u64.mul_wrapping(2_u64), 16_u64);
712 assert_eq!(
713 f16::from_f32(8.0).mul_wrapping(f16::from_f32(2.0)),
714 f16::from_f32(16.0)
715 );
716 assert_eq!(8.0_f32.mul_wrapping(2.0_f32), 16_f32);
717 assert_eq!(8.0_f64.mul_wrapping(2.0_f64), 16_f64);
718
719 assert_eq!(8_i8.mul_checked(2_i8).unwrap(), 16_i8);
721 assert_eq!(8_i16.mul_checked(2_i16).unwrap(), 16_i16);
722 assert_eq!(8_i32.mul_checked(2_i32).unwrap(), 16_i32);
723 assert_eq!(8_i64.mul_checked(2_i64).unwrap(), 16_i64);
724 assert_eq!(8_i128.mul_checked(2_i128).unwrap(), 16_i128);
725 assert_eq!(
726 i256::from_parts(8, 0)
727 .mul_checked(i256::from_parts(2, 0))
728 .unwrap(),
729 i256::from_parts(16, 0)
730 );
731 assert_eq!(8_u8.mul_checked(2_u8).unwrap(), 16_u8);
732 assert_eq!(8_u16.mul_checked(2_u16).unwrap(), 16_u16);
733 assert_eq!(8_u32.mul_checked(2_u32).unwrap(), 16_u32);
734 assert_eq!(8_u64.mul_checked(2_u64).unwrap(), 16_u64);
735 assert_eq!(
736 f16::from_f32(8.0).mul_checked(f16::from_f32(2.0)).unwrap(),
737 f16::from_f32(16.0)
738 );
739 assert_eq!(8.0_f32.mul_checked(2.0_f32).unwrap(), 16_f32);
740 assert_eq!(8.0_f64.mul_checked(2.0_f64).unwrap(), 16_f64);
741 }
742
743 #[test]
744 #[cfg_attr(miri, ignore)] fn test_native_type_div() {
746 assert_eq!(8_i8.div_wrapping(2_i8), 4_i8);
748 assert_eq!(8_i16.div_wrapping(2_i16), 4_i16);
749 assert_eq!(8_i32.div_wrapping(2_i32), 4_i32);
750 assert_eq!(8_i64.div_wrapping(2_i64), 4_i64);
751 assert_eq!(8_i128.div_wrapping(2_i128), 4_i128);
752 assert_eq!(
753 i256::from_parts(8, 0).div_wrapping(i256::from_parts(2, 0)),
754 i256::from_parts(4, 0)
755 );
756 assert_eq!(8_u8.div_wrapping(2_u8), 4_u8);
757 assert_eq!(8_u16.div_wrapping(2_u16), 4_u16);
758 assert_eq!(8_u32.div_wrapping(2_u32), 4_u32);
759 assert_eq!(8_u64.div_wrapping(2_u64), 4_u64);
760 assert_eq!(
761 f16::from_f32(8.0).div_wrapping(f16::from_f32(2.0)),
762 f16::from_f32(4.0)
763 );
764 assert_eq!(8.0_f32.div_wrapping(2.0_f32), 4_f32);
765 assert_eq!(8.0_f64.div_wrapping(2.0_f64), 4_f64);
766
767 assert_eq!(8_i8.div_checked(2_i8).unwrap(), 4_i8);
769 assert_eq!(8_i16.div_checked(2_i16).unwrap(), 4_i16);
770 assert_eq!(8_i32.div_checked(2_i32).unwrap(), 4_i32);
771 assert_eq!(8_i64.div_checked(2_i64).unwrap(), 4_i64);
772 assert_eq!(8_i128.div_checked(2_i128).unwrap(), 4_i128);
773 assert_eq!(
774 i256::from_parts(8, 0)
775 .div_checked(i256::from_parts(2, 0))
776 .unwrap(),
777 i256::from_parts(4, 0)
778 );
779 assert_eq!(8_u8.div_checked(2_u8).unwrap(), 4_u8);
780 assert_eq!(8_u16.div_checked(2_u16).unwrap(), 4_u16);
781 assert_eq!(8_u32.div_checked(2_u32).unwrap(), 4_u32);
782 assert_eq!(8_u64.div_checked(2_u64).unwrap(), 4_u64);
783 assert_eq!(
784 f16::from_f32(8.0).div_checked(f16::from_f32(2.0)).unwrap(),
785 f16::from_f32(4.0)
786 );
787 assert_eq!(8.0_f32.div_checked(2.0_f32).unwrap(), 4_f32);
788 assert_eq!(8.0_f64.div_checked(2.0_f64).unwrap(), 4_f64);
789 }
790
791 #[test]
792 #[cfg_attr(miri, ignore)] fn test_native_type_mod() {
794 assert_eq!(9_i8.mod_wrapping(2_i8), 1_i8);
796 assert_eq!(9_i16.mod_wrapping(2_i16), 1_i16);
797 assert_eq!(9_i32.mod_wrapping(2_i32), 1_i32);
798 assert_eq!(9_i64.mod_wrapping(2_i64), 1_i64);
799 assert_eq!(9_i128.mod_wrapping(2_i128), 1_i128);
800 assert_eq!(
801 i256::from_parts(9, 0).mod_wrapping(i256::from_parts(2, 0)),
802 i256::from_parts(1, 0)
803 );
804 assert_eq!(9_u8.mod_wrapping(2_u8), 1_u8);
805 assert_eq!(9_u16.mod_wrapping(2_u16), 1_u16);
806 assert_eq!(9_u32.mod_wrapping(2_u32), 1_u32);
807 assert_eq!(9_u64.mod_wrapping(2_u64), 1_u64);
808 assert_eq!(
809 f16::from_f32(9.0).mod_wrapping(f16::from_f32(2.0)),
810 f16::from_f32(1.0)
811 );
812 assert_eq!(9.0_f32.mod_wrapping(2.0_f32), 1_f32);
813 assert_eq!(9.0_f64.mod_wrapping(2.0_f64), 1_f64);
814
815 assert_eq!(9_i8.mod_checked(2_i8).unwrap(), 1_i8);
817 assert_eq!(9_i16.mod_checked(2_i16).unwrap(), 1_i16);
818 assert_eq!(9_i32.mod_checked(2_i32).unwrap(), 1_i32);
819 assert_eq!(9_i64.mod_checked(2_i64).unwrap(), 1_i64);
820 assert_eq!(9_i128.mod_checked(2_i128).unwrap(), 1_i128);
821 assert_eq!(
822 i256::from_parts(9, 0)
823 .mod_checked(i256::from_parts(2, 0))
824 .unwrap(),
825 i256::from_parts(1, 0)
826 );
827 assert_eq!(9_u8.mod_checked(2_u8).unwrap(), 1_u8);
828 assert_eq!(9_u16.mod_checked(2_u16).unwrap(), 1_u16);
829 assert_eq!(9_u32.mod_checked(2_u32).unwrap(), 1_u32);
830 assert_eq!(9_u64.mod_checked(2_u64).unwrap(), 1_u64);
831 assert_eq!(
832 f16::from_f32(9.0).mod_checked(f16::from_f32(2.0)).unwrap(),
833 f16::from_f32(1.0)
834 );
835 assert_eq!(9.0_f32.mod_checked(2.0_f32).unwrap(), 1_f32);
836 assert_eq!(9.0_f64.mod_checked(2.0_f64).unwrap(), 1_f64);
837 }
838
839 #[test]
840 fn test_i256_div_rem() {
841 let values = [
842 i256::MIN,
843 i256::MIN + i256::ONE,
844 i256::from_i128(-7),
845 i256::MINUS_ONE,
846 i256::ZERO,
847 i256::ONE,
848 i256::from_i128(2),
849 i256::from_i128(7),
850 i256::from_i128(i128::MAX),
851 i256::MAX,
852 ];
853 for n in values {
854 for d in values {
855 let checked = n
856 .div_checked(d)
857 .and_then(|q| Ok((q, n.mod_checked(d)?)))
858 .map_err(|e| e.to_string());
859 assert_eq!(
860 n.div_rem_checked(d).map_err(|e| e.to_string()),
861 checked,
862 "{n} / {d}"
863 );
864 if !d.is_zero() {
865 assert_eq!(
866 n.div_rem_wrapping(d),
867 (n.div_wrapping(d), n.mod_wrapping(d)),
868 "{n} / {d}"
869 );
870 }
871 }
872 }
873 }
874
875 #[test]
876 #[should_panic(expected = "attempt to divide by zero")]
877 fn test_i256_div_rem_wrapping_zero_panics() {
878 let _ = i256::ONE.div_rem_wrapping(i256::ZERO);
879 }
880
881 #[test]
882 #[cfg_attr(miri, ignore)] fn test_native_type_neg() {
884 assert_eq!(8_i8.neg_wrapping(), -8_i8);
886 assert_eq!(8_i16.neg_wrapping(), -8_i16);
887 assert_eq!(8_i32.neg_wrapping(), -8_i32);
888 assert_eq!(8_i64.neg_wrapping(), -8_i64);
889 assert_eq!(8_i128.neg_wrapping(), -8_i128);
890 assert_eq!(i256::from_parts(8, 0).neg_wrapping(), i256::from_i128(-8));
891 assert_eq!(8_u8.neg_wrapping(), u8::MAX - 7_u8);
892 assert_eq!(8_u16.neg_wrapping(), u16::MAX - 7_u16);
893 assert_eq!(8_u32.neg_wrapping(), u32::MAX - 7_u32);
894 assert_eq!(8_u64.neg_wrapping(), u64::MAX - 7_u64);
895 assert_eq!(f16::from_f32(8.0).neg_wrapping(), f16::from_f32(-8.0));
896 assert_eq!(8.0_f32.neg_wrapping(), -8_f32);
897 assert_eq!(8.0_f64.neg_wrapping(), -8_f64);
898
899 assert_eq!(8_i8.neg_checked().unwrap(), -8_i8);
901 assert_eq!(8_i16.neg_checked().unwrap(), -8_i16);
902 assert_eq!(8_i32.neg_checked().unwrap(), -8_i32);
903 assert_eq!(8_i64.neg_checked().unwrap(), -8_i64);
904 assert_eq!(8_i128.neg_checked().unwrap(), -8_i128);
905 assert_eq!(
906 i256::from_parts(8, 0).neg_checked().unwrap(),
907 i256::from_i128(-8)
908 );
909 assert!(8_u8.neg_checked().is_err());
910 assert!(8_u16.neg_checked().is_err());
911 assert!(8_u32.neg_checked().is_err());
912 assert!(8_u64.neg_checked().is_err());
913 assert_eq!(
914 f16::from_f32(8.0).neg_checked().unwrap(),
915 f16::from_f32(-8.0)
916 );
917 assert_eq!(8.0_f32.neg_checked().unwrap(), -8_f32);
918 assert_eq!(8.0_f64.neg_checked().unwrap(), -8_f64);
919 }
920
921 #[test]
922 #[cfg_attr(miri, ignore)] fn test_native_type_pow() {
924 assert_eq!(8_i8.pow_wrapping(2_u32), 64_i8);
926 assert_eq!(8_i16.pow_wrapping(2_u32), 64_i16);
927 assert_eq!(8_i32.pow_wrapping(2_u32), 64_i32);
928 assert_eq!(8_i64.pow_wrapping(2_u32), 64_i64);
929 assert_eq!(8_i128.pow_wrapping(2_u32), 64_i128);
930 assert_eq!(
931 i256::from_parts(8, 0).pow_wrapping(2_u32),
932 i256::from_parts(64, 0)
933 );
934 assert_eq!(8_u8.pow_wrapping(2_u32), 64_u8);
935 assert_eq!(8_u16.pow_wrapping(2_u32), 64_u16);
936 assert_eq!(8_u32.pow_wrapping(2_u32), 64_u32);
937 assert_eq!(8_u64.pow_wrapping(2_u32), 64_u64);
938 assert_approx_eq!(f16::from_f32(8.0).pow_wrapping(2_u32), f16::from_f32(64.0));
939 assert_approx_eq!(8.0_f32.pow_wrapping(2_u32), 64_f32);
940 assert_approx_eq!(8.0_f64.pow_wrapping(2_u32), 64_f64);
941
942 assert_eq!(8_i8.pow_checked(2_u32).unwrap(), 64_i8);
944 assert_eq!(8_i16.pow_checked(2_u32).unwrap(), 64_i16);
945 assert_eq!(8_i32.pow_checked(2_u32).unwrap(), 64_i32);
946 assert_eq!(8_i64.pow_checked(2_u32).unwrap(), 64_i64);
947 assert_eq!(8_i128.pow_checked(2_u32).unwrap(), 64_i128);
948 assert_eq!(
949 i256::from_parts(8, 0).pow_checked(2_u32).unwrap(),
950 i256::from_parts(64, 0)
951 );
952 assert_eq!(8_u8.pow_checked(2_u32).unwrap(), 64_u8);
953 assert_eq!(8_u16.pow_checked(2_u32).unwrap(), 64_u16);
954 assert_eq!(8_u32.pow_checked(2_u32).unwrap(), 64_u32);
955 assert_eq!(8_u64.pow_checked(2_u32).unwrap(), 64_u64);
956 assert_approx_eq!(
957 f16::from_f32(8.0).pow_checked(2_u32).unwrap(),
958 f16::from_f32(64.0)
959 );
960 assert_approx_eq!(8.0_f32.pow_checked(2_u32).unwrap(), 64_f32);
961 assert_approx_eq!(8.0_f64.pow_checked(2_u32).unwrap(), 64_f64);
962 }
963
964 #[test]
965 fn test_float_total_order_min_max() {
966 assert!(<f64 as ArrowNativeTypeOp>::MIN_TOTAL_ORDER.is_lt(f64::NEG_INFINITY));
967 assert!(<f64 as ArrowNativeTypeOp>::MAX_TOTAL_ORDER.is_gt(f64::INFINITY));
968
969 assert!(<f64 as ArrowNativeTypeOp>::MIN_TOTAL_ORDER.is_nan());
970 assert!(<f64 as ArrowNativeTypeOp>::MIN_TOTAL_ORDER.is_sign_negative());
971 assert!(<f64 as ArrowNativeTypeOp>::MIN_TOTAL_ORDER.is_lt(-f64::NAN));
972
973 assert!(<f64 as ArrowNativeTypeOp>::MAX_TOTAL_ORDER.is_nan());
974 assert!(<f64 as ArrowNativeTypeOp>::MAX_TOTAL_ORDER.is_sign_positive());
975 assert!(<f64 as ArrowNativeTypeOp>::MAX_TOTAL_ORDER.is_gt(f64::NAN));
976
977 assert!(<f32 as ArrowNativeTypeOp>::MIN_TOTAL_ORDER.is_lt(f32::NEG_INFINITY));
978 assert!(<f32 as ArrowNativeTypeOp>::MAX_TOTAL_ORDER.is_gt(f32::INFINITY));
979
980 assert!(<f32 as ArrowNativeTypeOp>::MIN_TOTAL_ORDER.is_nan());
981 assert!(<f32 as ArrowNativeTypeOp>::MIN_TOTAL_ORDER.is_sign_negative());
982 assert!(<f32 as ArrowNativeTypeOp>::MIN_TOTAL_ORDER.is_lt(-f32::NAN));
983
984 assert!(<f32 as ArrowNativeTypeOp>::MAX_TOTAL_ORDER.is_nan());
985 assert!(<f32 as ArrowNativeTypeOp>::MAX_TOTAL_ORDER.is_sign_positive());
986 assert!(<f32 as ArrowNativeTypeOp>::MAX_TOTAL_ORDER.is_gt(f32::NAN));
987
988 assert!(<f16 as ArrowNativeTypeOp>::MIN_TOTAL_ORDER.is_lt(f16::NEG_INFINITY));
989 assert!(<f16 as ArrowNativeTypeOp>::MAX_TOTAL_ORDER.is_gt(f16::INFINITY));
990
991 assert!(<f16 as ArrowNativeTypeOp>::MIN_TOTAL_ORDER.is_nan());
992 assert!(<f16 as ArrowNativeTypeOp>::MIN_TOTAL_ORDER.is_sign_negative());
993 assert!(<f16 as ArrowNativeTypeOp>::MIN_TOTAL_ORDER.is_lt(-f16::NAN));
994
995 assert!(<f16 as ArrowNativeTypeOp>::MAX_TOTAL_ORDER.is_nan());
996 assert!(<f16 as ArrowNativeTypeOp>::MAX_TOTAL_ORDER.is_sign_positive());
997 assert!(<f16 as ArrowNativeTypeOp>::MAX_TOTAL_ORDER.is_gt(f16::NAN));
998 }
999}