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