1#![deny(missing_docs)]
31#![no_std]
32
33macro_rules! impl_positive {
34 ($(#[$attr:meta])* $ty:ident, $sty:ident, $d:tt $mac:ident, $base:ty, $uns:ty) => {
35
36 #[doc = concat!("Creates a [`", stringify!($ty), "`] checked at compile time.")]
37 #[doc = concat!("This macro takes a single argument that must be a positive [`", stringify!($base), "`].")]
39 #[doc = concat!("use sign_bound::{", stringify!($ty), ", ", stringify!($mac), "};")]
43 #[doc = concat!("let val: ", stringify!($ty), " = ", stringify!($mac), "!(123);")]
45 #[macro_export]
47 macro_rules! $mac {
48 ($e:expr $d(,)?) => {
49 const {
50 match $crate::$ty::new($e) {
51 ::core::option::Option::Some(e) => e,
52 _ => panic!(concat!(stringify!($base), " out of range for ", stringify!($ty))),
53 }
54 }
55 };
56 }
57
58 #[doc = concat!("For example, `Option<", stringify!($ty), ">` is the same size as [`", stringify!($base), "`].")]
62 #[derive(Copy, Clone)]
63 #[repr(C)]
64 $(#[$attr])*
65 pub struct $ty {
66 #[cfg(target_endian = "big")]
67 _hi: PositiveHighByte,
68 _buf: [u8; size_of::<$base>() - 1],
69 #[cfg(target_endian = "little")]
70 _hi: PositiveHighByte,
71 }
72
73 impl $ty {
74 #[doc = concat!("This value is equal to [`", stringify!($base), "::BITS`].")]
77 pub const BITS: u32 = <$base>::BITS;
78 pub const MIN: Self = unsafe { $ty::new_unchecked(0) };
80 #[doc = concat!("The largest value that can be represented by this positive integer type, equal to [`", stringify!($base), "::MAX`].")]
81 pub const MAX: Self = unsafe { $ty::new_unchecked(<$base>::MAX) };
82 #[doc = concat!("Creates a `", stringify!($ty), "` if the given value is positive.")]
83 pub const fn new(value: $base) -> Option<Self> {
84 if value < 0 {
85 return None;
86 }
87 unsafe { Some(core::mem::transmute::<$base, Self>(value)) }
88 }
89 #[doc = concat!("Creates a `", stringify!($ty), "` without checking whether the value is positive.")]
90 #[inline]
96 pub const unsafe fn new_unchecked(value: $base) -> Self {
97 debug_assert!(value >= 0);
98 core::mem::transmute::<$base, Self>(value)
99 }
100 #[inline]
102 pub const fn get(self) -> $base {
103 unsafe {
104 let n = core::mem::transmute::<Self, $base>(self);
105 core::hint::assert_unchecked(n >= 0);
106 n
107 }
108 }
109 #[inline]
111 pub const fn count_zeros(self) -> u32 {
112 self.get().count_zeros()
113 }
114 #[inline]
116 pub const fn count_ones(self) -> u32 {
117 self.get().count_ones()
118 }
119 #[inline]
121 pub const fn leading_zeros(self) -> u32 {
122 self.get().leading_zeros()
123 }
124 #[inline]
126 pub const fn trailing_zeros(self) -> u32 {
127 self.get().trailing_zeros()
128 }
129 #[inline]
131 pub const fn is_power_of_two(self) -> bool {
132 (self.get() as $uns).is_power_of_two()
133 }
134 #[inline]
140 pub const fn ilog2(self) -> u32 {
141 self.get().ilog2()
142 }
143 #[inline]
149 pub const fn ilog10(self) -> u32 {
150 self.get().ilog10()
151 }
152 #[inline]
154 pub const fn checked_neg(self) -> Option<$sty> {
155 $sty::new(-self.get())
156 }
157 #[inline]
161 pub const fn checked_add(self, rhs: Self) -> Option<Self> {
162 match self.get().checked_add(rhs.get()) {
163 Some(n) => unsafe { Some(Self::new_unchecked(n)) },
164 None => None,
165 }
166 }
167 #[inline]
170 pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
171 Self::new(self.get() - rhs.get())
172 }
173 #[inline]
177 pub const fn checked_mul(self, rhs: Self) -> Option<Self> {
178 match self.get().checked_mul(rhs.get()) {
179 Some(n) => unsafe { Some(Self::new_unchecked(n)) },
180 None => None,
181 }
182 }
183 #[inline]
187 pub const fn checked_div(self, rhs: Self) -> Option<Self> {
188 match self.get().checked_div(rhs.get()) {
189 Some(n) => unsafe { Some(Self::new_unchecked(n)) },
190 None => None,
191 }
192 }
193 #[inline]
198 pub const fn checked_rem(self, rhs: Self) -> Option<Self> {
199 match self.get().checked_rem(rhs.get()) {
200 Some(n) => unsafe { Some(Self::new_unchecked(n)) },
201 None => None,
202 }
203 }
204 #[inline]
208 pub const fn checked_div_unsigned(self, rhs: $uns) -> Option<Self> {
209 match (self.get() as $uns).checked_div(rhs) {
210 Some(n) => unsafe { Some(Self::new_unchecked(n as $base)) },
211 None => None,
212 }
213 }
214 #[inline]
218 pub const fn checked_rem_unsigned(self, rhs: $uns) -> Option<Self> {
219 match (self.get() as $uns).checked_rem(rhs) {
220 Some(n) => unsafe { Some(Self::new_unchecked(n as $base)) },
221 None => None,
222 }
223 }
224 #[inline]
229 pub const fn checked_pow(self, rhs: u32) -> Option<Self> {
230 match self.get().checked_pow(rhs) {
231 Some(n) => unsafe { Some(Self::new_unchecked(n)) },
232 None => None,
233 }
234 }
235 #[inline]
240 pub const fn checked_next_power_of_two(self) -> Option<Self> {
241 Self::new((self.get() as $uns).next_power_of_two() as $base)
242 }
243 #[inline]
247 pub const fn checked_ilog2(self) -> Option<u32> {
248 self.get().checked_ilog2()
249 }
250 #[inline]
254 pub const fn checked_ilog10(self) -> Option<u32> {
255 self.get().checked_ilog10()
256 }
257 #[doc = concat!("Returns [`", stringify!($ty), "::MAX`] on overflow.")]
259 #[inline]
260 pub const fn saturating_add(self, rhs: Self) -> Self {
261 let n = self.get().saturating_add(rhs.get());
262 unsafe { Self::new_unchecked(n) }
263 }
264 #[inline]
267 pub const fn saturating_sub(self, rhs: Self) -> Self {
268 match Self::new(self.get() - rhs.get()) {
269 Some(n) => n,
270 None => Self::MIN
271 }
272 }
273 #[doc = concat!("Returns [`", stringify!($ty), "::MAX`] on overflow.")]
276 #[inline]
277 pub const fn saturating_mul(self, rhs: Self) -> Self {
278 let n = self.get().saturating_mul(rhs.get());
279 unsafe { Self::new_unchecked(n) }
280 }
281 #[doc = concat!("Returns [`", stringify!($ty), "::MAX`] on overflow.")]
284 #[inline]
285 pub const fn saturating_pow(self, rhs: u32) -> Self {
286 let n = self.get().saturating_pow(rhs);
287 unsafe { Self::new_unchecked(n) }
288 }
289 }
290
291 impl Default for $ty {
292 #[inline]
293 fn default() -> Self {
294 Self::MIN
295 }
296 }
297
298 impl PartialEq for $ty {
299 #[inline]
300 fn eq(&self, rhs: &Self) -> bool {
301 self.get().eq(&rhs.get())
302 }
303 }
304
305 impl PartialOrd for $ty {
306 fn partial_cmp(&self, rhs: &Self) -> Option<core::cmp::Ordering> {
307 Some(self.cmp(rhs))
308 }
309 }
310
311 impl Ord for $ty {
312 fn cmp(&self, rhs: &Self) -> core::cmp::Ordering {
313 self.get().cmp(&rhs.get())
314 }
315 }
316
317 impl Eq for $ty {}
318
319 impl core::str::FromStr for $ty {
320 type Err = core::num::IntErrorKind;
321 #[inline]
322 fn from_str(s: &str) -> Result<Self, Self::Err> {
323 let n = s.parse::<$uns>().map_err(|e| e.kind().clone())?;
324 Self::new(n as $base).ok_or_else(|| core::num::IntErrorKind::PosOverflow)
325 }
326 }
327
328 impl core::hash::Hash for $ty {
329 #[inline]
330 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
331 self.get().hash(state);
332 }
333 }
334
335 impl core::ops::Div for $ty {
336 type Output = Self;
337 fn div(self, rhs: Self) -> Self::Output {
338 unsafe { Self::new_unchecked(self.get().div(rhs.get())) }
339 }
340 }
341 impl core::ops::DivAssign for $ty {
342 fn div_assign(&mut self, rhs: Self) {
343 *self = core::ops::Div::div(*self, rhs);
344 }
345 }
346
347 impl core::ops::Rem for $ty {
348 type Output = Self;
349 fn rem(self, rhs: Self) -> Self::Output {
350 unsafe { Self::new_unchecked(self.get().rem(rhs.get())) }
351 }
352 }
353 impl core::ops::RemAssign for $ty {
354 fn rem_assign(&mut self, rhs: Self) {
355 *self = core::ops::Rem::rem(*self, rhs);
356 }
357 }
358
359 impl core::ops::Div<$uns> for $ty {
360 type Output = Self;
361 fn div(self, rhs: $uns) -> Self::Output {
362 unsafe { Self::new_unchecked((self.get() as $uns).div(rhs) as $base) }
363 }
364 }
365 impl core::ops::DivAssign<$uns> for $ty {
366 fn div_assign(&mut self, rhs: $uns) {
367 *self = core::ops::Div::div(*self, rhs);
368 }
369 }
370
371 impl core::ops::Rem<$uns> for $ty {
372 type Output = Self;
373 fn rem(self, rhs: $uns) -> Self::Output {
374 unsafe { Self::new_unchecked((self.get() as $uns).rem(rhs) as $base) }
375 }
376 }
377 impl core::ops::RemAssign<$uns> for $ty {
378 fn rem_assign(&mut self, rhs: $uns) {
379 *self = core::ops::Rem::rem(*self, rhs);
380 }
381 }
382
383 impl core::ops::BitAnd<$base> for $ty {
384 type Output = Self;
385 #[inline]
386 fn bitand(self, rhs: $base) -> Self::Output {
387 unsafe { Self::new_unchecked(self.get().bitand(rhs)) }
388 }
389 }
390 impl core::ops::BitAndAssign<$base> for $ty {
391 #[inline]
392 fn bitand_assign(&mut self, rhs: $base) {
393 *self = core::ops::BitAnd::bitand(*self, rhs);
394 }
395 }
396
397 impl core::ops::BitAnd<$ty> for $base {
398 type Output = $ty;
399 #[inline]
400 fn bitand(self, rhs: $ty) -> Self::Output {
401 unsafe { $ty::new_unchecked(self.bitand(rhs.get())) }
402 }
403 }
404
405 impl_bit_op! { BitOr::bitor, BitOrAssign::bitor_assign for $ty }
406 impl_bit_op! { BitAnd::bitand, BitAndAssign::bitand_assign for $ty }
407 impl_bit_op! { BitXor::bitxor, BitXorAssign::bitxor_assign for $ty }
408 impl_fmt! { Display, Debug, Binary, Octal, LowerHex, UpperHex => $ty }
409 };
410}
411
412macro_rules! impl_negative {
413 ($(#[$attr:meta])* $ty:ident, $pty:ident, $d:tt $mac:ident, $base:ty, $uns:ty) => {
414
415 #[doc = concat!("Creates a [`", stringify!($ty), "`] checked at compile time.")]
416 #[doc = concat!("This macro takes a single argument that must be a negative [`", stringify!($base), "`].")]
418 #[doc = concat!("use sign_bound::{", stringify!($ty), ", ", stringify!($mac), "};")]
422 #[doc = concat!("let val: ", stringify!($ty), " = ", stringify!($mac), "!(-123);")]
424 #[macro_export]
426 macro_rules! $mac {
427 ($e:expr $d(,)?) => {
428 const {
429 match $crate::$ty::new($e) {
430 ::core::option::Option::Some(e) => e,
431 _ => panic!(concat!(stringify!($base), " out of range for ", stringify!($ty))),
432 }
433 }
434 };
435 }
436
437 #[doc = concat!("For example, `Option<", stringify!($ty), ">` is the same size as [`", stringify!($base), "`].")]
441 #[derive(Copy, Clone)]
442 $(#[$attr])*
443 #[repr(C)]
444 pub struct $ty {
445 #[cfg(target_endian = "big")]
446 _hi: NegativeHighByte,
447 _buf: [u8; size_of::<$base>() - 1],
448 #[cfg(target_endian = "little")]
449 _hi: NegativeHighByte,
450 }
451
452 impl $ty {
453 #[doc = concat!("This value is equal to [`", stringify!($base), "::BITS`].")]
456 pub const BITS: u32 = <$base>::BITS;
457 #[doc = concat!("The smallest value that can be represented by this negative integer type, equal to [`", stringify!($base), "::MIN`].")]
458 pub const MIN: Self = unsafe { $ty::new_unchecked(<$base>::MIN) };
459 pub const MAX: Self = unsafe { $ty::new_unchecked(-1) };
461 #[doc = concat!("Creates a `", stringify!($ty), "` if the given value is negative.")]
462 pub const fn new(value: $base) -> Option<Self> {
463 if value >= 0 {
464 return None;
465 }
466 unsafe { Some(core::mem::transmute::<$base, Self>(value)) }
467 }
468 #[doc = concat!("Creates a `", stringify!($ty), "` without checking whether the value is negative.")]
469 #[inline]
475 pub const unsafe fn new_unchecked(value: $base) -> Self {
476 debug_assert!(value < 0);
477 core::mem::transmute::<$base, Self>(value)
478 }
479 #[inline]
481 pub const fn get(self) -> $base {
482 unsafe {
483 let n = core::mem::transmute::<Self, $base>(self);
484 core::hint::assert_unchecked(n < 0);
485 n
486 }
487 }
488 #[inline]
490 pub const fn count_zeros(self) -> u32 {
491 self.get().count_zeros()
492 }
493 #[inline]
495 pub const fn count_ones(self) -> u32 {
496 self.get().count_ones()
497 }
498 #[inline]
502 pub const fn leading_zeros(self) -> u32 {
503 0
504 }
505 #[inline]
510 pub const fn trailing_zeros(self) -> u32 {
511 self.get().trailing_zeros()
512 }
513 #[inline]
516 pub const fn checked_abs(self) -> Option<$pty> {
517 match self.get().checked_abs() {
518 Some(n) => unsafe { Some($pty::new_unchecked(n)) },
519 None => None,
520 }
521 }
522 #[inline]
525 pub const fn checked_neg(self) -> Option<$pty> {
526 match self.get().checked_neg() {
527 Some(n) => unsafe { Some($pty::new_unchecked(n)) },
528 None => None,
529 }
530 }
531 #[inline]
535 pub const fn checked_add(self, rhs: Self) -> Option<Self> {
536 match self.get().checked_add(rhs.get()) {
537 Some(n) => unsafe { Some(Self::new_unchecked(n)) },
538 None => None,
539 }
540 }
541 #[inline]
544 pub const fn checked_sub(self, rhs: Self) -> Option<Self> {
545 Self::new(self.get() - rhs.get())
546 }
547 #[inline]
551 pub const fn checked_mul(self, rhs: Self) -> Option<$pty> {
552 match self.get().checked_mul(rhs.get()) {
553 Some(n) => unsafe { Some($pty::new_unchecked(n)) },
554 None => None,
555 }
556 }
557 #[inline]
561 pub const fn checked_mul_positive(self, rhs: $pty) -> Option<Self> {
562 match self.get().checked_mul(rhs.get()) {
563 Some(n) => Self::new(n),
564 None => None,
565 }
566 }
567 #[doc = concat!("as a [`", stringify!($pty), "`].")]
575 #[inline]
576 pub const fn checked_div(self, rhs: Self) -> Option<$pty> {
577 match self.get().checked_div(rhs.get()) {
578 Some(n) => unsafe { Some($pty::new_unchecked(n)) },
579 None => None,
580 }
581 }
582 #[doc = concat!("Calculates the [Euclidean quotient](", stringify!($base), "::div_euclid)")]
584 #[doc = concat!("as a [`", stringify!($pty), "`].")]
591 #[inline]
592 pub const fn checked_div_euclid(self, rhs: Self) -> Option<$pty> {
593 match self.get().checked_div_euclid(rhs.get()) {
594 Some(n) => unsafe { Some($pty::new_unchecked(n)) },
595 None => None,
596 }
597 }
598 #[doc = concat!("Calculates the [Euclidean remainder](", stringify!($base), "::rem_euclid)")]
600 #[doc = concat!("as a [`", stringify!($pty), "`].")]
607 #[inline]
608 pub const fn checked_rem_euclid(self, rhs: $base) -> Option<$pty> {
609 match self.get().checked_rem_euclid(rhs) {
610 Some(n) => unsafe { Some($pty::new_unchecked(n)) },
611 None => None,
612 }
613 }
614 #[doc = concat!("[`", stringify!($pty), "::MAX`]")]
617 #[inline]
619 pub const fn saturating_abs(self) -> $pty {
620 let n = self.get().saturating_abs();
621 unsafe { $pty::new_unchecked(n) }
622 }
623 #[doc = concat!("[`", stringify!($pty), "::MAX`]")]
626 #[inline]
628 pub const fn saturating_neg(self) -> $pty {
629 let n = self.get().saturating_neg();
630 unsafe { $pty::new_unchecked(n) }
631 }
632 #[doc = concat!("Returns [`", stringify!($ty), "::MIN`] on overflow.")]
634 #[inline]
635 pub const fn saturating_add(self, rhs: Self) -> Self {
636 let n = self.get().saturating_add(rhs.get());
637 unsafe { Self::new_unchecked(n) }
638 }
639 #[inline]
642 pub const fn saturating_sub(self, rhs: Self) -> Self {
643 match Self::new(self.get() - rhs.get()) {
644 Some(n) => n,
645 None => Self::MAX
646 }
647 }
648 #[doc = concat!("Returns [`", stringify!($pty), "::MAX`] on overflow.")]
651 #[inline]
652 pub const fn saturating_mul(self, rhs: Self) -> $pty {
653 let n = self.get().saturating_mul(rhs.get());
654 unsafe { $pty::new_unchecked(n) }
655 }
656 #[doc = concat!("Returns [`", stringify!($ty), "::MIN`] on overflow.")]
660 #[inline]
661 pub const fn saturating_mul_positive(self, rhs: $pty) -> Self {
662 match Self::new(self.get().saturating_mul(rhs.get())) {
663 Some(n) => n,
664 None => Self::MAX,
665 }
666 }
667 }
668
669 impl PartialEq for $ty {
670 #[inline]
671 fn eq(&self, rhs: &Self) -> bool {
672 self.get().eq(&rhs.get())
673 }
674 }
675
676 impl PartialOrd for $ty {
677 fn partial_cmp(&self, rhs: &Self) -> Option<core::cmp::Ordering> {
678 Some(self.cmp(rhs))
679 }
680 }
681
682 impl Ord for $ty {
683 fn cmp(&self, rhs: &Self) -> core::cmp::Ordering {
684 self.get().cmp(&rhs.get())
685 }
686 }
687
688 impl Eq for $ty {}
689
690 impl core::str::FromStr for $ty {
691 type Err = core::num::IntErrorKind;
692 #[inline]
693 fn from_str(s: &str) -> Result<Self, Self::Err> {
694 let n = s.parse::<$base>().map_err(|e| e.kind().clone())?;
695 Self::new(n).ok_or_else(|| core::num::IntErrorKind::PosOverflow)
696 }
697 }
698
699 impl core::hash::Hash for $ty {
700 #[inline]
701 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
702 self.get().hash(state);
703 }
704 }
705
706 impl core::ops::BitOr<$base> for $ty {
707 type Output = Self;
708 #[inline]
709 fn bitor(self, rhs: $base) -> Self::Output {
710 unsafe { Self::new_unchecked(self.get().bitor(rhs)) }
711 }
712 }
713 impl core::ops::BitOrAssign<$base> for $ty {
714 #[inline]
715 fn bitor_assign(&mut self, rhs: $base) {
716 *self = core::ops::BitOr::bitor(*self, rhs);
717 }
718 }
719
720 impl core::ops::BitOr<$ty> for $base {
721 type Output = $ty;
722 #[inline]
723 fn bitor(self, rhs: $ty) -> Self::Output {
724 unsafe { $ty::new_unchecked(self.bitor(rhs.get())) }
725 }
726 }
727
728 impl core::ops::BitOr<$ty> for $pty {
729 type Output = $ty;
730 #[inline]
731 fn bitor(self, rhs: $ty) -> Self::Output {
732 unsafe { $ty::new_unchecked(self.get().bitor(rhs.get())) }
733 }
734 }
735 impl core::ops::BitOr<$pty> for $ty {
736 type Output = Self;
737 #[inline]
738 fn bitor(self, rhs: $pty) -> Self::Output {
739 unsafe { $ty::new_unchecked(self.get().bitor(rhs.get())) }
740 }
741 }
742 impl core::ops::BitOrAssign<$pty> for $ty {
743 #[inline]
744 fn bitor_assign(&mut self, rhs: $pty) {
745 *self = core::ops::BitOr::bitor(*self, rhs);
746 }
747 }
748
749 impl core::ops::BitAnd<$pty> for $ty {
750 type Output = $pty;
751 #[inline]
752 fn bitand(self, rhs: $pty) -> Self::Output {
753 unsafe { $pty::new_unchecked(self.get().bitand(rhs.get())) }
754 }
755 }
756 impl core::ops::BitAnd<$ty> for $pty {
757 type Output = Self;
758 #[inline]
759 fn bitand(self, rhs: $ty) -> Self::Output {
760 unsafe { Self::new_unchecked(self.get().bitand(rhs.get())) }
761 }
762 }
763 impl core::ops::BitAndAssign<$ty> for $pty {
764 #[inline]
765 fn bitand_assign(&mut self, rhs: $ty) {
766 *self = core::ops::BitAnd::bitand(*self, rhs);
767 }
768 }
769
770 impl core::ops::BitXor<$pty> for $ty {
771 type Output = Self;
772 #[inline]
773 fn bitxor(self, rhs: $pty) -> Self::Output {
774 unsafe { Self::new_unchecked(self.get().bitxor(rhs.get())) }
775 }
776 }
777 impl core::ops::BitXorAssign<$pty> for $ty {
778 #[inline]
779 fn bitxor_assign(&mut self, rhs: $pty) {
780 *self = core::ops::BitXor::bitxor(*self, rhs);
781 }
782 }
783 impl core::ops::BitXor<$ty> for $pty {
784 type Output = $ty;
785 #[inline]
786 fn bitxor(self, rhs: $ty) -> Self::Output {
787 unsafe { $ty::new_unchecked(self.get().bitxor(rhs.get())) }
788 }
789 }
790 impl core::ops::BitXor for $ty {
791 type Output = $pty;
792 #[inline]
793 fn bitxor(self, rhs: Self) -> Self::Output {
794 unsafe { $pty::new_unchecked(self.get().bitxor(rhs.get())) }
795 }
796 }
797
798 impl core::ops::Not for $ty {
799 type Output = $pty;
800 fn not(self) -> Self::Output {
801 unsafe { $pty::new_unchecked(self.get().not()) }
802 }
803 }
804 impl core::ops::Not for $pty {
805 type Output = $ty;
806 fn not(self) -> Self::Output {
807 unsafe { $ty::new_unchecked(self.get().not()) }
808 }
809 }
810
811 impl_fmt! { Display, Debug, Binary, Octal, LowerHex, UpperHex => $ty }
812 impl_bit_op! { BitOr::bitor, BitOrAssign::bitor_assign for $ty }
813 impl_bit_op! { BitAnd::bitand, BitAndAssign::bitand_assign for $ty }
814 };
815}
816
817macro_rules! impl_fmt {
818 (=> $ty:ty) => {};
819 ($trait:ident $(, $rest:ident)* => $ty:ty) => {
820 impl core::fmt::$trait for $ty {
821 #[inline]
822 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
823 core::fmt::$trait::fmt(&self.get(), f)
824 }
825 }
826 impl_fmt! { $($rest),* => $ty }
827 };
828}
829
830macro_rules! impl_from {
831 (=> $ty:ty) => {};
832 ($from:ty $(, $rest:ty)* => $ty:ty) => {
833 impl From<$from> for $ty {
834 #[inline]
835 fn from(value: $from) -> Self {
836 unsafe { Self::new_unchecked(value as _) }
837 }
838 }
839 impl_from! { $($rest),* => $ty }
840 };
841}
842
843macro_rules! impl_from_get {
844 ($ty:ty =>) => {};
845 ($ty:ty => $from:ty $(, $rest:ty)*) => {
846 impl From<$ty> for $from {
847 #[inline]
848 fn from(value: $ty) -> Self {
849 unsafe { Self::new_unchecked(value.get() as _) }
850 }
851 }
852 impl TryFrom<$from> for $ty {
853 type Error = core::num::TryFromIntError;
854 #[inline]
855 fn try_from(value: $from) -> Result<Self, Self::Error> {
856 let value = <_>::try_from(value.get())?;
857 unsafe { Ok(Self::new_unchecked(value)) }
858 }
859 }
860 impl_from_get! { $ty => $($rest),*}
861 };
862}
863
864macro_rules! impl_primitive_from {
865 ($ty:ty =>) => {};
866 ($ty:ty => $from:ty $(, $rest:ty)*) => {
867 impl From<$ty> for $from {
868 #[inline]
869 fn from(value: $ty) -> Self {
870 value.get() as _
871 }
872 }
873 impl_primitive_from! { $ty => $($rest),* }
874 };
875}
876
877macro_rules! impl_try_from {
878 ($ty:ty =>) => {};
879 ($ty:ty => $from:ty $(, $rest:ty)*) => {
880 impl TryFrom<$from> for $ty {
881 type Error = core::num::TryFromIntError;
882 #[inline]
883 fn try_from(value: $from) -> Result<Self, Self::Error> {
884 let value = <_>::try_from(value.get())?;
885 unsafe { Ok(Self::new_unchecked(value)) }
886 }
887 }
888 impl_try_from! { $ty => $($rest),*}
889 };
890}
891
892macro_rules! impl_primitive_try_from {
893 ($ty:ty =>) => {};
894 ($ty:ty => $from:ty $(, $rest:ty)*) => {
895 impl TryFrom<$ty> for $from {
896 type Error = core::num::TryFromIntError;
897 #[inline]
898 fn try_from(value: $ty) -> Result<Self, Self::Error> {
899 Self::try_from(value.get())
900 }
901 }
902 impl_primitive_try_from! { $ty => $($rest),* }
903 };
904}
905
906macro_rules! impl_positive_try_from {
907 (=> $ty:ty $(, $base:ty)* ) => {};
908 ($from:ty $(, $rest:ty)* => $ty:ty $(, $base:ty)* ) => {
909 impl TryFrom<$from> for $ty {
910 type Error = core::num::TryFromIntError;
911 #[inline]
912 fn try_from(value: $from) -> Result<Self, Self::Error> {
913 $(let value = <$base>::try_from(value)?;)*
914 unsafe { Ok(Self::new_unchecked(value as _)) }
915 }
916 }
917 impl_positive_try_from! { $($rest),* => $ty $(, $base)* }
918 };
919}
920
921macro_rules! impl_negative_try_from {
922 (=> $ty:ty, $uns:ty, $base:ty) => {};
923 ($from:ty $(, $rest:ty)* => $ty:ty, $uns:ty, $base:ty) => {
924 impl TryFrom<$from> for $ty {
925 type Error = core::num::TryFromIntError;
926 #[inline]
927 fn try_from(value: $from) -> Result<Self, Self::Error> {
928 let value = <$base>::try_from(value)?;
929 Self::new(value).ok_or_else(|| <$base>::try_from(<$uns>::MAX).unwrap_err())
930 }
931 }
932 impl_negative_try_from! { $($rest),* => $ty, $uns, $base }
933 };
934}
935macro_rules! impl_bit_op {
936 ($op:ident :: $opm:ident, $aop:ident :: $aopm:ident for $ty:ty) => {
937 impl core::ops::$op for $ty {
938 type Output = Self;
939 #[inline]
940 fn $opm(self, rhs: Self) -> Self::Output {
941 unsafe { Self::new_unchecked(self.get().$opm(rhs.get())) }
942 }
943 }
944
945 impl core::ops::$aop for $ty {
946 #[inline]
947 fn $aopm(&mut self, rhs: Self) {
948 *self = core::ops::$op::$opm(*self, rhs);
949 }
950 }
951 };
952}
953
954impl_positive! { #[repr(align(1))] PositiveI8, NegativeI8, $ positive_i8, i8, u8 }
955impl_from_get! { PositiveI8 => PositiveI16, PositiveI32, PositiveI64, PositiveIsize }
956impl_primitive_from! { PositiveI8 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize }
957impl_positive_try_from! { u8, u16, u32, u64, u128, usize => PositiveI8, i8 }
958impl_positive_try_from! { i16, i32, i64, i128, isize => PositiveI8, u8, i8 }
959impl_positive_try_from! { i8 => PositiveI8, u8 }
960impl_negative! { #[repr(align(1))] NegativeI8, PositiveI8, $ negative_i8, i8, u8 }
961impl_from_get! { NegativeI8 => NegativeI16, NegativeI32, NegativeI64, NegativeIsize }
962impl_primitive_from! { NegativeI8 => i8, i16, i32, i64, i128, isize }
963impl_negative_try_from! { i8, i16, i32, i64, i128, isize => NegativeI8, u8, i8 }
964
965impl_positive! { #[repr(align(2))] PositiveI16, NegativeI16, $ positive_i16, i16, u16 }
966impl_from! { u8 => PositiveI16 }
967impl_from_get! { PositiveI16 => PositiveI32, PositiveI64, PositiveIsize }
968impl_primitive_from! { PositiveI16 => u16, u32, u64, u128, usize, i16, i32, i64, i128, isize }
969impl_primitive_try_from! { PositiveI16 => u8, i8 }
970impl_positive_try_from! { u16, u32, u64, u128, usize => PositiveI16, i16 }
971impl_positive_try_from! { i8, i32, i64, i128, isize => PositiveI16, u16, i16 }
972impl_positive_try_from! { i16 => PositiveI16, u16 }
973impl_negative! { #[repr(align(2))] NegativeI16, PositiveI16, $ negative_i16, i16, u16 }
974impl_from_get! { NegativeI16 => NegativeI32, NegativeI64, NegativeIsize }
975impl_primitive_from! { NegativeI16 => i16, i32, i64, i128, isize }
976impl_primitive_try_from! { NegativeI16 => i8 }
977impl_negative_try_from! { i8, i16, i32, i64, i128, isize => NegativeI16, u16, i16 }
978
979impl_positive! { #[repr(align(4))] PositiveI32, NegativeI32, $ positive_i32, i32, u32 }
980impl_from! { u8, u16 => PositiveI32 }
981impl_from_get! { PositiveI32 => PositiveI64 }
982impl_primitive_from! { PositiveI32 => u32, u64, u128, i32, i64, i128 }
983impl_primitive_try_from! { PositiveI32 => u8, u16, usize, i8, i16, isize }
984impl_positive_try_from! { u32, u64, u128, usize => PositiveI32, i32 }
985impl_positive_try_from! { i8, i16, i64, i128, isize => PositiveI32, u32, i32 }
986impl_positive_try_from! { i32 => PositiveI32, u32 }
987impl_negative! { #[repr(align(4))] NegativeI32, PositiveI32, $ negative_i32, i32, u32 }
988impl_from_get! { NegativeI32 => NegativeI64 }
989impl_primitive_from! { NegativeI32 => i32, i64, i128 }
990impl_primitive_try_from! { NegativeI32 => i8, i16, isize }
991impl_negative_try_from! { i8, i16, i32, i64, i128, isize => NegativeI32, u32, i32 }
992
993impl_positive! { #[repr(align(8))] PositiveI64, NegativeI64, $ positive_i64, i64, u64 }
994impl_from! { u8, u16, u32 => PositiveI64 }
995impl_primitive_from! { PositiveI64 => u64, u128, i64, i128 }
996impl_primitive_try_from! { PositiveI64 => u8, u16, u32, usize, i8, i16, i32, isize }
997impl_positive_try_from! { u64, u128, usize => PositiveI64, i64 }
998impl_positive_try_from! { i8, i16, i32, i128, isize => PositiveI64, u64, i64 }
999impl_positive_try_from! { i64 => PositiveI64, u64 }
1000impl_negative! { #[repr(align(8))] NegativeI64, PositiveI64, $ negative_i64, i64, u64 }
1001impl_primitive_from! { NegativeI64 => i64, i128 }
1002impl_primitive_try_from! { NegativeI64 => i8, i16, i32, isize }
1003impl_negative_try_from! { i8, i16, i32, i64, i128, isize => NegativeI64, u64, i64 }
1004
1005#[cfg(not(any(
1006 target_pointer_width = "16",
1007 target_pointer_width = "32",
1008 target_pointer_width = "64",
1009)))]
1010compile_error!("unsupported pointer width");
1011
1012impl_positive! {
1013 #[cfg_attr(target_pointer_width = "16", repr(align(2)))]
1014 #[cfg_attr(target_pointer_width = "32", repr(align(4)))]
1015 #[cfg_attr(target_pointer_width = "64", repr(align(8)))]
1016 PositiveIsize, NegativeIsize, $ positive_isize, isize, usize
1017}
1018impl_from! { u8 => PositiveIsize }
1019impl_try_from! { PositiveIsize => PositiveI32, PositiveI64 }
1020impl_primitive_from! { PositiveIsize => usize, isize }
1021impl_primitive_try_from! { PositiveIsize => u8, u16, u32, u64, u128, i8, i16, i32, i64, i128 }
1022impl_positive_try_from! { u16, u32, u64, u128, usize => PositiveIsize, isize }
1023impl_positive_try_from! { i8, i16, i32, i64, i128 => PositiveIsize, usize, isize }
1024impl_positive_try_from! { isize => PositiveIsize, usize }
1025impl_negative! {
1026 #[cfg_attr(target_pointer_width = "16", repr(align(2)))]
1027 #[cfg_attr(target_pointer_width = "32", repr(align(4)))]
1028 #[cfg_attr(target_pointer_width = "64", repr(align(8)))]
1029 NegativeIsize, PositiveIsize, $ negative_isize, isize, usize
1030}
1031impl_try_from! { NegativeIsize => NegativeI32, NegativeI64 }
1032impl_primitive_from! { NegativeIsize => isize }
1033impl_primitive_try_from! { NegativeIsize => i8, i16, i32, i64, i128 }
1034impl_negative_try_from! { i8, i16, i32, i64, i128, isize => NegativeIsize, usize, isize }
1035
1036#[derive(Copy, Clone)]
1037#[repr(u8)]
1038enum PositiveHighByte {
1039 _0 = 0,
1040 _1 = 1,
1041 _2 = 2,
1042 _3 = 3,
1043 _4 = 4,
1044 _5 = 5,
1045 _6 = 6,
1046 _7 = 7,
1047 _8 = 8,
1048 _9 = 9,
1049 _10 = 10,
1050 _11 = 11,
1051 _12 = 12,
1052 _13 = 13,
1053 _14 = 14,
1054 _15 = 15,
1055 _16 = 16,
1056 _17 = 17,
1057 _18 = 18,
1058 _19 = 19,
1059 _20 = 20,
1060 _21 = 21,
1061 _22 = 22,
1062 _23 = 23,
1063 _24 = 24,
1064 _25 = 25,
1065 _26 = 26,
1066 _27 = 27,
1067 _28 = 28,
1068 _29 = 29,
1069 _30 = 30,
1070 _31 = 31,
1071 _32 = 32,
1072 _33 = 33,
1073 _34 = 34,
1074 _35 = 35,
1075 _36 = 36,
1076 _37 = 37,
1077 _38 = 38,
1078 _39 = 39,
1079 _40 = 40,
1080 _41 = 41,
1081 _42 = 42,
1082 _43 = 43,
1083 _44 = 44,
1084 _45 = 45,
1085 _46 = 46,
1086 _47 = 47,
1087 _48 = 48,
1088 _49 = 49,
1089 _50 = 50,
1090 _51 = 51,
1091 _52 = 52,
1092 _53 = 53,
1093 _54 = 54,
1094 _55 = 55,
1095 _56 = 56,
1096 _57 = 57,
1097 _58 = 58,
1098 _59 = 59,
1099 _60 = 60,
1100 _61 = 61,
1101 _62 = 62,
1102 _63 = 63,
1103 _64 = 64,
1104 _65 = 65,
1105 _66 = 66,
1106 _67 = 67,
1107 _68 = 68,
1108 _69 = 69,
1109 _70 = 70,
1110 _71 = 71,
1111 _72 = 72,
1112 _73 = 73,
1113 _74 = 74,
1114 _75 = 75,
1115 _76 = 76,
1116 _77 = 77,
1117 _78 = 78,
1118 _79 = 79,
1119 _80 = 80,
1120 _81 = 81,
1121 _82 = 82,
1122 _83 = 83,
1123 _84 = 84,
1124 _85 = 85,
1125 _86 = 86,
1126 _87 = 87,
1127 _88 = 88,
1128 _89 = 89,
1129 _90 = 90,
1130 _91 = 91,
1131 _92 = 92,
1132 _93 = 93,
1133 _94 = 94,
1134 _95 = 95,
1135 _96 = 96,
1136 _97 = 97,
1137 _98 = 98,
1138 _99 = 99,
1139 _100 = 100,
1140 _101 = 101,
1141 _102 = 102,
1142 _103 = 103,
1143 _104 = 104,
1144 _105 = 105,
1145 _106 = 106,
1146 _107 = 107,
1147 _108 = 108,
1148 _109 = 109,
1149 _110 = 110,
1150 _111 = 111,
1151 _112 = 112,
1152 _113 = 113,
1153 _114 = 114,
1154 _115 = 115,
1155 _116 = 116,
1156 _117 = 117,
1157 _118 = 118,
1158 _119 = 119,
1159 _120 = 120,
1160 _121 = 121,
1161 _122 = 122,
1162 _123 = 123,
1163 _124 = 124,
1164 _125 = 125,
1165 _126 = 126,
1166 _127 = 127,
1167}
1168
1169#[derive(Copy, Clone)]
1170#[repr(u8)]
1171enum NegativeHighByte {
1172 _128 = 128,
1173 _129 = 129,
1174 _130 = 130,
1175 _131 = 131,
1176 _132 = 132,
1177 _133 = 133,
1178 _134 = 134,
1179 _135 = 135,
1180 _136 = 136,
1181 _137 = 137,
1182 _138 = 138,
1183 _139 = 139,
1184 _140 = 140,
1185 _141 = 141,
1186 _142 = 142,
1187 _143 = 143,
1188 _144 = 144,
1189 _145 = 145,
1190 _146 = 146,
1191 _147 = 147,
1192 _148 = 148,
1193 _149 = 149,
1194 _150 = 150,
1195 _151 = 151,
1196 _152 = 152,
1197 _153 = 153,
1198 _154 = 154,
1199 _155 = 155,
1200 _156 = 156,
1201 _157 = 157,
1202 _158 = 158,
1203 _159 = 159,
1204 _160 = 160,
1205 _161 = 161,
1206 _162 = 162,
1207 _163 = 163,
1208 _164 = 164,
1209 _165 = 165,
1210 _166 = 166,
1211 _167 = 167,
1212 _168 = 168,
1213 _169 = 169,
1214 _170 = 170,
1215 _171 = 171,
1216 _172 = 172,
1217 _173 = 173,
1218 _174 = 174,
1219 _175 = 175,
1220 _176 = 176,
1221 _177 = 177,
1222 _178 = 178,
1223 _179 = 179,
1224 _180 = 180,
1225 _181 = 181,
1226 _182 = 182,
1227 _183 = 183,
1228 _184 = 184,
1229 _185 = 185,
1230 _186 = 186,
1231 _187 = 187,
1232 _188 = 188,
1233 _189 = 189,
1234 _190 = 190,
1235 _191 = 191,
1236 _192 = 192,
1237 _193 = 193,
1238 _194 = 194,
1239 _195 = 195,
1240 _196 = 196,
1241 _197 = 197,
1242 _198 = 198,
1243 _199 = 199,
1244 _200 = 200,
1245 _201 = 201,
1246 _202 = 202,
1247 _203 = 203,
1248 _204 = 204,
1249 _205 = 205,
1250 _206 = 206,
1251 _207 = 207,
1252 _208 = 208,
1253 _209 = 209,
1254 _210 = 210,
1255 _211 = 211,
1256 _212 = 212,
1257 _213 = 213,
1258 _214 = 214,
1259 _215 = 215,
1260 _216 = 216,
1261 _217 = 217,
1262 _218 = 218,
1263 _219 = 219,
1264 _220 = 220,
1265 _221 = 221,
1266 _222 = 222,
1267 _223 = 223,
1268 _224 = 224,
1269 _225 = 225,
1270 _226 = 226,
1271 _227 = 227,
1272 _228 = 228,
1273 _229 = 229,
1274 _230 = 230,
1275 _231 = 231,
1276 _232 = 232,
1277 _233 = 233,
1278 _234 = 234,
1279 _235 = 235,
1280 _236 = 236,
1281 _237 = 237,
1282 _238 = 238,
1283 _239 = 239,
1284 _240 = 240,
1285 _241 = 241,
1286 _242 = 242,
1287 _243 = 243,
1288 _244 = 244,
1289 _245 = 245,
1290 _246 = 246,
1291 _247 = 247,
1292 _248 = 248,
1293 _249 = 249,
1294 _250 = 250,
1295 _251 = 251,
1296 _252 = 252,
1297 _253 = 253,
1298 _254 = 254,
1299 _255 = 255,
1300}
1301
1302#[cfg(test)]
1303mod tests {
1304 use super::*;
1305 use core::ops::{
1306 BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign, Not, Rem,
1307 RemAssign,
1308 };
1309 use proptest::prelude::*;
1310
1311 macro_rules! test_unary {
1312 ($ty:ident, $base:ident ($range:expr) :: $($method:ident),+ $(,)?) => {
1313 proptest! {
1314 $(#[test] fn $method(n in $range) {
1315 assert_eq!($ty::new(n).map(|n| n.$method()), Some((n as $base).$method()));
1316 })+
1317 }
1318 };
1319 }
1320
1321 macro_rules! test_unary_op {
1322 ($ty:ident, $base:ident ($range:expr) :: $($method:ident),+ $(,)?) => {
1323 proptest! {
1324 $(#[test] fn $method(n in $range) {
1325 assert_eq!($ty::new(n).map(|n| n.$method().get()), Some((n as $base).$method()));
1326 })+
1327 }
1328 };
1329 }
1330
1331 macro_rules! test_unary_checked {
1332 ($ty:ident, $base:ident ($range:expr) :: $($method:ident),+ $(,)?) => {
1333 proptest! {
1334 $(#[test] fn $method(n in $range) {
1335 assert_eq!($ty::new(n).and_then(|n| n.$method()), (n as $base).$method());
1336 })+
1337 }
1338 };
1339 }
1340
1341 macro_rules! test_binary {
1342 ($ty:ident, $base:ident ($range1:expr, $range2:expr) :: $($method:ident),+ $(,)?) => {
1343 proptest! {
1344 $(#[test] fn $method(a in $range1, b in $range2) {
1345 assert_eq!(
1346 $ty::new(a).zip($ty::new(b)).map(|(a, b)| a.$method(b)).map(|a| a.get()),
1347 Some((a as $base).$method(b as $base)),
1348 );
1349 })+
1350 }
1351 };
1352 }
1353
1354 macro_rules! test_binary_checked {
1355 ($ty:ident, $base:ident ($range1:expr, $range2:expr) :: $($method:ident),+ $(,)?) => {
1356 proptest! {
1357 $(#[test] fn $method(a in $range1, b in $range2) {
1358 assert_eq!(
1359 $ty::new(a).zip($ty::new(b)).and_then(|(a, b)| a.$method(b)).map(|a| a.get()),
1360 (a as $base).$method(b as $base),
1361 );
1362 })+
1363 }
1364 };
1365 }
1366
1367 macro_rules! test_assign {
1368 ($ty:ident, $base:ident ($range1:expr, $range2:expr) :: $($method:ident),+ $(,)?) => {
1369 proptest! {
1370 $(#[test] fn $method(a in $range1, b in $range2) {
1371 let mut a1 = $ty::new(a);
1372 let mut a2 = a;
1373 if let Some((a, b)) = a1.as_mut().zip($ty::new(b)) {
1374 a.$method(b);
1375 }
1376 a2.$method(b);
1377 assert_eq!(a1.map(|a| a.get()), Some(a2));
1378 })+
1379 }
1380 };
1381 }
1382
1383 macro_rules! test_type {
1384 ($base:ident, $uns:ident, $pos:ident, $neg:ident) => {
1385 mod $base {
1386 use super::*;
1387 mod positive {
1388 use super::*;
1389 proptest! {
1390 #[test]
1391 fn valid(n in 0..=$base::MAX) {
1392 assert_eq!($pos::new(n).map(|n| n.get()), Some(n));
1393 }
1394 #[test]
1395 fn invalid(n in $base::MIN..-1) {
1396 assert_eq!($pos::new(n).map(|n| n.get()), None);
1397 }
1398 #[test]
1399 fn checked_neg(n in 0..=$base::MAX) {
1400 assert_eq!(
1401 $pos::new(n).and_then(|n| n.checked_neg()),
1402 n.checked_neg().and_then($neg::new),
1403 );
1404 }
1405 #[test]
1406 fn checked_sub(a in 0..=$base::MAX, b in 0..=$base::MAX) {
1407 assert_eq!(
1408 $pos::new(a).zip($pos::new(b)).and_then(|(a, b)| a.checked_sub(b)),
1409 a.checked_sub(b).and_then($pos::new),
1410 );
1411 }
1412 #[test]
1413 fn checked_div_unsigned(a in 0..=$base::MAX, b in 0..=$uns::MAX) {
1414 assert_eq!(
1415 $pos::new(a).and_then(|a| a.checked_div_unsigned(b)),
1416 (a as $uns).checked_div(b).and_then(|n| $pos::try_from(n).ok()),
1417 );
1418 }
1419 #[test]
1420 fn checked_rem_unsigned(a in 0..=$base::MAX, b in 0..=$uns::MAX) {
1421 assert_eq!(
1422 $pos::new(a).and_then(|a| a.checked_rem_unsigned(b)),
1423 (a as $uns).checked_rem(b).and_then(|n| $pos::try_from(n).ok()),
1424 );
1425 }
1426 #[test]
1427 fn checked_pow(a in 0..=$base::MAX, b in 0..u32::MAX) {
1428 assert_eq!(
1429 $pos::new(a).and_then(|a| a.checked_pow(b)).map(|n| n.get()),
1430 a.checked_pow(b),
1431 );
1432 }
1433 #[test]
1434 fn checked_next_power_of_two(n in 0..=$base::MAX) {
1435 assert_eq!(
1436 $pos::new(n).and_then(|n| n.checked_next_power_of_two()),
1437 (n as $uns).checked_next_power_of_two().and_then(|n| $pos::try_from(n).ok()),
1438 );
1439 }
1440 #[test]
1441 fn saturating_sub(a in 0..=$base::MAX, b in 0..=$base::MAX) {
1442 assert_eq!(
1443 $pos::new(a).zip($pos::new(b)).map(|(a, b)| a.saturating_sub(b)).map(|a| a.get()),
1444 Some(a.saturating_sub(b).max(0)),
1445 );
1446 }
1447 #[test]
1448 fn saturating_pow(a in 0..=$base::MAX, b in 0..u32::MAX) {
1449 assert_eq!(
1450 $pos::new(a).map(|a| a.saturating_pow(b)).map(|a| a.get()),
1451 Some((a as $base).saturating_pow(b)),
1452 );
1453 }
1454 }
1455 test_unary_op! { $pos, $base (0..=$base::MAX) :: not }
1456 test_binary! { $pos, $base (0..=$base::MAX, 1..=$base::MAX) :: div, rem }
1457 test_unary! { $pos, $base (0..=$base::MAX)
1458 :: count_zeros, count_ones, leading_zeros, trailing_zeros }
1459 test_unary! { $pos, $uns (0..=$base::MAX) :: is_power_of_two }
1460 test_unary! { $pos, $base (1..=$base::MAX) :: ilog2, ilog10 }
1461 test_unary_checked! { $pos, $base (1..=$base::MAX) :: checked_ilog2, checked_ilog10 }
1462 test_binary_checked! { $pos, $base (0..=$base::MAX, 0..=$base::MAX)
1463 :: checked_add, checked_mul, checked_div, checked_rem }
1464 test_binary! { $pos, $base (0..=$base::MAX, 0..=$base::MAX)
1465 :: saturating_add, saturating_mul, bitor, bitand, bitxor }
1466 test_assign! { $pos, $base (0..=$base::MAX, 1..=$base::MAX) :: div_assign, rem_assign }
1467 test_assign! { $pos, $base (0..=$base::MAX, 0..=$base::MAX)
1468 :: bitor_assign, bitand_assign, bitxor_assign }
1469 }
1470 mod negative {
1471 use super::*;
1472 proptest! {
1473 #[test]
1474 fn valid(n in $base::MIN..0) {
1475 assert_eq!($neg::new(n).map(|n| n.get()), Some(n));
1476 }
1477 #[test]
1478 fn invalid(n in 0..=$base::MAX) {
1479 assert_eq!($neg::new(n).map(|n| n.get()), None);
1480 }
1481 #[test]
1482 fn checked_abs(n in $base::MIN..0) {
1483 assert_eq!(
1484 $neg::new(n).and_then(|n| n.checked_abs()).map(|n| n.get()),
1485 n.checked_abs(),
1486 );
1487 }
1488 #[test]
1489 fn checked_neg(n in $base::MIN..0) {
1490 assert_eq!(
1491 $neg::new(n).and_then(|n| n.checked_neg()).map(|n| n.get()),
1492 n.checked_neg(),
1493 );
1494 }
1495 #[test]
1496 fn checked_sub(a in $base::MIN..0, b in $base::MIN..0) {
1497 assert_eq!(
1498 $neg::new(a).zip($neg::new(b)).and_then(|(a, b)| a.checked_sub(b)),
1499 a.checked_sub(b).and_then($neg::new),
1500 );
1501 }
1502 #[test]
1503 fn checked_mul_positive(a in $base::MIN..0, b in 0..=$base::MAX) {
1504 assert_eq!(
1505 $neg::new(a)
1506 .zip($pos::new(b))
1507 .and_then(|(a, b)| a.checked_mul_positive(b)),
1508 a.checked_mul(b).and_then($neg::new),
1509 );
1510 }
1511 #[test]
1512 fn checked_rem_euclid(a in $base::MIN..0, b in $base::MIN..=$base::MAX) {
1513 assert_eq!(
1514 $neg::new(a).and_then(|a| a.checked_rem_euclid(b)).map(|n| n.get()),
1515 a.checked_rem_euclid(b),
1516 );
1517 }
1518 #[test]
1519 fn saturating_abs(n in $base::MIN..0) {
1520 assert_eq!(
1521 $neg::new(n).map(|n| n.saturating_abs().get()),
1522 Some(n.saturating_abs()),
1523 );
1524 }
1525 #[test]
1526 fn saturating_neg(n in $base::MIN..0) {
1527 assert_eq!(
1528 $neg::new(n).map(|n| n.saturating_neg().get()),
1529 Some(n.saturating_neg()),
1530 );
1531 }
1532 #[test]
1533 fn saturating_sub(a in $base::MIN..0, b in $base::MIN..0) {
1534 assert_eq!(
1535 $neg::new(a)
1536 .zip($neg::new(b))
1537 .map(|(a, b)| a.saturating_sub(b).get()),
1538 Some(a.saturating_sub(b).min(-1)),
1539 );
1540 }
1541 #[test]
1542 fn saturating_mul_positive(a in $base::MIN..0, b in 0..=$base::MAX) {
1543 assert_eq!(
1544 $neg::new(a)
1545 .zip($pos::new(b))
1546 .map(|(a, b)| a.saturating_mul_positive(b).get()),
1547 Some(a.saturating_mul(b).min(-1)),
1548 );
1549 }
1550 #[test]
1551 fn bitxor_assign(a in $base::MIN..0, b in 0..=$base::MAX) {
1552 let mut a1 = $neg::new(a);
1553 let mut a2 = a;
1554 if let Some((a, b)) = a1.as_mut().zip($pos::new(b)) {
1555 a.bitxor_assign(b);
1556 }
1557 a2.bitxor_assign(b);
1558 assert_eq!(a1.map(|a| a.get()), Some(a2));
1559 }
1560 }
1561 test_unary_op! { $neg, $base ($base::MIN..0) :: not }
1562 test_unary! { $neg, $base ($base::MIN..0)
1563 :: count_zeros, count_ones, leading_zeros, trailing_zeros }
1564 test_binary_checked! { $neg, $base ($base::MIN..0, $base::MIN..0)
1565 :: checked_add, checked_mul, checked_div, checked_div_euclid }
1566 test_binary! { $neg, $base ($base::MIN..0, $base::MIN..0)
1567 :: saturating_add, saturating_mul, bitor, bitand, bitxor }
1568 test_assign! { $neg, $base ($base::MIN..0, $base::MIN..0)
1569 :: bitor_assign, bitand_assign }
1570 }
1571 }
1572 };
1573 }
1574 test_type! { i8, u8, PositiveI8, NegativeI8 }
1575 test_type! { i16, u16, PositiveI16, NegativeI16 }
1576 test_type! { i32, u32, PositiveI32, NegativeI32 }
1577 test_type! { i64, u64, PositiveI64, NegativeI64 }
1578 test_type! { isize, usize, PositiveIsize, NegativeIsize }
1579}