jiff/util/
rangeint.rs

1// We squash dead_code warnings because we define all of our methods for all
2// primitive integer types, even though we don't use each method at least once
3// on each of the integer types. It would really just be too annoying to do
4// anything different. With that said, it is very likely that there is some
5// actual dead code below that we're missing because we squash the warning.
6#![allow(dead_code, non_snake_case, non_camel_case_types)]
7
8use core::{
9    cmp::Ordering,
10    ops::{
11        Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign,
12        Sub, SubAssign,
13    },
14};
15
16use crate::{error::Error, util::t::Constant};
17
18macro_rules! define_ranged {
19    (
20        $name:ident,
21        $repr:ty,
22        smaller { $($smaller_name:ident $smaller_repr:ty),* },
23        bigger { $($bigger_name:ident $bigger_repr:ty),* }
24    ) => {
25        #[derive(Clone, Copy)]
26        pub(crate) struct $name<const MIN: i128, const MAX: i128> {
27            /// The actual value of the integer.
28            ///
29            /// Callers should not access this directly. There are some very
30            /// rare cases where algorithms are too difficult to express on
31            /// ranged integers, and it's useful to be able to reach inside and
32            /// access the raw value directly. (For example, the conversions
33            /// between Unix epoch day and Gregorian date.)
34            pub(crate) val: $repr,
35            /// The minimum possible value computed so far.
36            ///
37            /// This value is only present when `debug_assertions` are enabled.
38            /// In that case, it is used to ensure the minimum possible value
39            /// when the integer is actually observed (or converted) is still
40            /// within the legal range.
41            ///
42            /// Callers should not access this directly. There are some very
43            /// rare cases where algorithms are too difficult to express on
44            /// ranged integers, and it's useful to be able to reach inside and
45            /// access the raw value directly. (For example, the conversions
46            /// between Unix epoch day and Gregorian date.)
47            #[cfg(debug_assertions)]
48            pub(crate) min: $repr,
49            /// The maximum possible value computed so far.
50            ///
51            /// This value is only present when `debug_assertions` are enabled.
52            /// In that case, it is used to ensure the maximum possible value
53            /// when the integer is actually observed (or converted) is still
54            /// within the legal range.
55            ///
56            /// Callers should not access this directly. There are some very
57            /// rare cases where algorithms are too difficult to express on
58            /// ranged integers, and it's useful to be able to reach inside and
59            /// access the raw value directly. (For example, the conversions
60            /// between Unix epoch day and Gregorian date.)
61            #[cfg(debug_assertions)]
62            pub(crate) max: $repr,
63        }
64
65        impl<const MIN: i128, const MAX: i128> $name<MIN, MAX> {
66            /// These are the absolute min/max values for the integer type
67            /// being used.
68            const PRIMITIVE_MIN: i128 = <$repr>::MIN as i128;
69            const PRIMITIVE_MAX: i128 = <$repr>::MAX as i128;
70
71            /// When true, this range integer has bounds precisely equivalent
72            /// to its underlying primitive representation.
73            const IS_PRIMITIVE: bool = Self::MIN_REPR == <$repr>::MIN
74                && Self::MAX_REPR == <$repr>::MAX;
75
76            /// The min/max values as given by our type parameters.
77            pub(crate) const MIN: i128 = MIN;
78            pub(crate) const MAX: i128 = MAX;
79
80            /// The number of distinct elements in this type's range.
81            pub(crate) const LEN: i128 = {
82                assert!(Self::PRIMITIVE_MIN < Self::PRIMITIVE_MAX);
83                MAX - MIN + 1
84            };
85
86            /// The min/max values of this type, represented in their
87            /// primitive form for easy comparisons with incoming values.
88            pub(crate) const MIN_REPR: $repr = {
89                assert!(
90                    Self::PRIMITIVE_MIN <= MIN && MIN <= Self::PRIMITIVE_MAX
91                );
92                MIN as $repr
93            };
94            pub(crate) const MAX_REPR: $repr = {
95                assert!(
96                    Self::PRIMITIVE_MIN <= MAX && MAX <= Self::PRIMITIVE_MAX
97                );
98                MAX as $repr
99            };
100
101            /// The min/max values of this type as a ranged type.
102            pub(crate) const MIN_SELF: Self =
103                Self::new_unchecked(Self::MIN_REPR);
104            pub(crate) const MAX_SELF: Self =
105                Self::new_unchecked(Self::MAX_REPR);
106
107            /// The min/max values of this type as a constant.
108            pub(crate) const MIN_CONST: Constant =
109                Constant(Self::MIN_REPR as i64);
110            pub(crate) const MAX_CONST: Constant =
111                Constant(Self::MAX_REPR as i64);
112
113            #[inline]
114            pub(crate) fn error(
115                what: &'static str,
116                given: $repr,
117            ) -> Error {
118                Error::range(what, given, Self::MIN_REPR, Self::MAX_REPR)
119            }
120
121            #[inline]
122            pub(crate) fn new(val: impl TryInto<$repr>) -> Option<Self> {
123                let val = val.try_into().ok()?;
124                if !Self::contains(val) {
125                    return None;
126                }
127                #[cfg(not(debug_assertions))]
128                {
129                    Some(Self { val })
130                }
131                #[cfg(debug_assertions)]
132                {
133                    Some(Self {
134                        val,
135                        min: Self::MIN_REPR,
136                        max: Self::MAX_REPR,
137                    })
138                }
139            }
140
141            /// Like `new`, but monomorphic and works in a `const` context.
142            #[inline]
143            pub(crate) const fn new_const(val: $repr) -> Option<Self> {
144                if !Self::contains(val) {
145                    return None;
146                }
147                #[cfg(not(debug_assertions))]
148                {
149                    Some(Self { val })
150                }
151                #[cfg(debug_assertions)]
152                {
153                    Some(Self {
154                        val,
155                        min: Self::MIN_REPR,
156                        max: Self::MAX_REPR,
157                    })
158                }
159            }
160
161            #[inline]
162            pub(crate) fn try_new(
163                what: &'static str,
164                val: impl Into<i64>,
165            ) -> Result<Self, Error> {
166                let val = val.into();
167                #[allow(irrefutable_let_patterns)]
168                let Ok(val) = <$repr>::try_from(val) else {
169                    return Err(Error::range(
170                        what,
171                        val,
172                        Self::MIN_REPR,
173                        Self::MAX_REPR,
174                    ));
175                };
176                Self::new(val).ok_or_else(|| Self::error(what, val))
177            }
178
179            #[inline]
180            pub(crate) fn try_new128(
181                what: &'static str,
182                val: impl Into<i128>,
183            ) -> Result<Self, Error> {
184                let val = val.into();
185                #[allow(irrefutable_let_patterns)]
186                let Ok(val) = <$repr>::try_from(val) else {
187                    return Err(Error::range(
188                        what,
189                        val,
190                        Self::MIN_REPR,
191                        Self::MAX_REPR,
192                    ));
193                };
194                Self::new(val).ok_or_else(|| Self::error(what, val))
195            }
196
197            #[inline]
198            pub(crate) fn constrain(val: impl Into<$repr>) -> Self {
199                let val = val.into().clamp(Self::MIN_REPR, Self::MAX_REPR);
200                Self::new_unchecked(val)
201            }
202
203            #[inline]
204            pub(crate) const fn new_unchecked(val: $repr) -> Self {
205                #[cfg(not(debug_assertions))]
206                {
207                    Self { val }
208                }
209                #[cfg(debug_assertions)]
210                {
211                    assert!(Self::contains(val), "val is not in range");
212                    Self { val, min: Self::MIN_REPR, max: Self::MAX_REPR }
213                }
214            }
215
216            #[inline]
217            pub(crate) const fn N<const VAL: $repr>() -> Self {
218                #[cfg(not(debug_assertions))]
219                {
220                    Self { val: VAL }
221                }
222                #[cfg(debug_assertions)]
223                {
224                    Self { val: VAL, min: VAL, max: VAL }
225                }
226            }
227
228            #[inline]
229            pub(crate) const fn N128<const VAL: i128>() -> Self {
230                #[cfg(not(debug_assertions))]
231                {
232                    Self { val: VAL as $repr }
233                }
234                #[cfg(debug_assertions)]
235                {
236                    if !(MIN <= VAL && VAL <= MAX) {
237                        panic!("constant out of range");
238                    }
239                    let val = VAL as $repr;
240                    Self { val, min: val, max: val }
241                }
242            }
243
244            #[inline]
245            pub(crate) const fn V<
246                const VAL: $repr,
247                const START: $repr,
248                const END: $repr,
249            >() -> Self {
250                #[cfg(not(debug_assertions))]
251                {
252                    Self { val: VAL }
253                }
254                #[cfg(debug_assertions)]
255                {
256                    Self { val: VAL, min: START, max: END }
257                }
258            }
259
260            #[inline]
261            pub(crate) const fn contains(val: $repr) -> bool {
262                Self::MIN_REPR <= val && val <= Self::MAX_REPR
263            }
264
265            #[inline]
266            pub(crate) fn vary<
267                const N: usize,
268                const MIN2: i128,
269                const MAX2: i128,
270            >(
271                numbers: [Self; N],
272                with: impl Fn([Self; N]) -> $name<MIN2, MAX2>,
273            ) -> $name<MIN2, MAX2> {
274                let [result] =
275                    Self::vary_many(numbers, |numbers| [with(numbers)]);
276                result
277            }
278
279            #[inline]
280            pub(crate) fn vary_many<
281                const N: usize,
282                const M: usize,
283                const MIN2: i128,
284                const MAX2: i128,
285            >(
286                numbers: [Self; N],
287                with: impl Fn([Self; N]) -> [$name<MIN2, MAX2>; M],
288            ) -> [$name<MIN2, MAX2>; M] {
289                #[cfg(not(debug_assertions))]
290                {
291                    with(numbers)
292                }
293                #[cfg(debug_assertions)]
294                {
295                    let vals = with(numbers);
296                    let mins = with(numbers.map(|n| Self {
297                        val: n.min,
298                        min: n.min,
299                        max: n.max,
300                    }));
301                    let maxs = with(numbers.map(|n| Self {
302                        val: n.max,
303                        min: n.min,
304                        max: n.max,
305                    }));
306                    let mut result = [$name::MIN_SELF; M];
307                    let it = vals.into_iter().zip(mins).zip(maxs).enumerate();
308                    for (i, ((val, min), max)) in it {
309                        result[i] =
310                            $name { val: val.val, min: min.val, max: max.val };
311                    }
312                    result
313                }
314            }
315
316            #[inline]
317            pub(crate) fn get(self) -> $repr {
318                #[cfg(not(debug_assertions))]
319                {
320                    self.val
321                }
322                #[cfg(debug_assertions)]
323                {
324                    assert!(
325                        Self::contains(self.val),
326                        concat!(
327                            stringify!($name),
328                            " val {val:?} is not in range {MIN:?}..={MAX:?}"
329                        ),
330                        val = self.val,
331                        MIN = MIN,
332                        MAX = MAX,
333                    );
334                    assert!(
335                        Self::contains(self.min),
336                        concat!(
337                            stringify!($name),
338                            " min {min:?} is not in range {MIN:?}..={MAX:?}"
339                        ),
340                        min = self.min,
341                        MIN = MIN,
342                        MAX = MAX,
343                    );
344                    assert!(
345                        Self::contains(self.max),
346                        concat!(
347                            stringify!($name),
348                            " max {max:?} is not in range {MIN:?}..={MAX:?}"
349                        ),
350                        max = self.max,
351                        MIN = MIN,
352                        MAX = MAX,
353                    );
354                    self.val
355                }
356            }
357
358            /// Returns the underlying value without checking whether it's
359            /// in bounds or not.
360            ///
361            /// This should generally be avoided as it circumvents the
362            /// protections of this type. It is sometimes useful in cases
363            /// where the bounds are known not to matter. For example, in
364            /// producing an error message for checked arithmetic. It's also
365            /// good to use this in `Debug` impls for higher level types,
366            /// otherwise printing the debug representation of a type will fail
367            /// if a ranged integer is out of bounds. (And this is annoying.)
368            #[inline]
369            pub(crate) const fn get_unchecked(self) -> $repr {
370                self.val
371            }
372
373            /// Turns this integer into an error.
374            ///
375            /// This is useful because it will use the integer's value even if
376            /// it falls outside of the bounds of this type.
377            ///
378            /// Callers can also use this routine to set custom context
379            /// dependent bounds. For example, when the day of the month is out
380            /// of bounds. The maximum value can vary based on the month (and
381            /// year).
382            #[inline]
383            pub(crate) fn to_error_with_bounds(
384                self,
385                what: &'static str,
386                min: impl Into<i128>,
387                max: impl Into<i128>,
388            ) -> Error {
389                Error::range(
390                    what,
391                    self.get_unchecked(),
392                    min.into(),
393                    max.into(),
394                )
395            }
396
397            #[inline]
398            pub(crate) fn abs(self) -> Self {
399                #[cfg(not(debug_assertions))]
400                {
401                    $name { val: self.val.abs() }
402                }
403                #[cfg(debug_assertions)]
404                {
405                    let val = self.val.checked_abs().expect(concat!(
406                        "absolute value of ",
407                        stringify!($name),
408                        " value overflowed",
409                    ));
410                    let min = self.min.checked_abs().expect(concat!(
411                        "absolute value of ",
412                        stringify!($name),
413                        " minimum overflowed",
414                    ));
415                    let max = self.max.checked_abs().expect(concat!(
416                        "absolute value of ",
417                        stringify!($name),
418                        " maximum overflowed",
419                    ));
420                    $name { val, min, max }
421                }
422            }
423
424            #[inline]
425            pub(crate) fn signum(self) -> $name<-1, 1> {
426                #[cfg(not(debug_assertions))]
427                {
428                    $name { val: self.val.signum() }
429                }
430                #[cfg(debug_assertions)]
431                {
432                    let val = self.val.signum();
433                    let min = self.min.signum();
434                    let max = self.max.signum();
435                    $name { val, min, max }
436                }
437            }
438
439            #[inline]
440            pub(crate) fn min(self, other: impl RInto<Self>) -> Self {
441                let other = other.rinto();
442                #[cfg(not(debug_assertions))]
443                {
444                    Self { val: self.val.min(other.val) }
445                }
446                #[cfg(debug_assertions)]
447                {
448                    let val = self.val.min(other.val);
449                    let min = self.val.min(other.min);
450                    let max = self.max.min(other.max);
451                    Self { val, min, max }
452                }
453            }
454
455            #[inline]
456            pub(crate) fn max(self, other: impl RInto<Self>) -> Self {
457                let other = other.rinto();
458                #[cfg(not(debug_assertions))]
459                {
460                    Self { val: self.val.max(other.val) }
461                }
462                #[cfg(debug_assertions)]
463                {
464                    let val = self.val.max(other.val);
465                    let min = self.val.max(other.min);
466                    let max = self.max.max(other.max);
467                    Self { val, min, max }
468                }
469            }
470
471            #[inline]
472            pub(crate) fn clamp(
473                self,
474                min: impl RInto<Self>,
475                max: impl RInto<Self>,
476            ) -> Self {
477                self.min(max).max(min)
478            }
479
480            #[inline]
481            pub(crate) fn div_ceil(self, rhs: impl RInto<Self>) -> Self {
482                let rhs = rhs.rinto();
483                #[cfg(not(debug_assertions))]
484                {
485                    let val = self.val.wrapping_div(rhs.val);
486                    Self { val }
487                }
488                #[cfg(debug_assertions)]
489                {
490                    let val = self.val.checked_div(rhs.val).expect(concat!(
491                        "dividing(ceil) ",
492                        stringify!($name),
493                        " values overflowed"
494                    ));
495                    let min = self.min.checked_div(rhs.min).expect(concat!(
496                        "dividing(ceil) ",
497                        stringify!($name),
498                        " minimums overflowed"
499                    ));
500                    let max = self.max.checked_div(rhs.max).expect(concat!(
501                        "dividing(ceil) ",
502                        stringify!($name),
503                        " maximums overflowed"
504                    ));
505                    Self { val, min, max }
506                }
507            }
508
509            #[inline]
510            pub(crate) fn div_floor(self, rhs: impl RInto<Self>) -> Self {
511                let rhs = rhs.rinto();
512                #[cfg(not(debug_assertions))]
513                {
514                    let val = self.val.wrapping_div_euclid(rhs.val);
515                    Self { val }
516                }
517                #[cfg(debug_assertions)]
518                {
519                    let val =
520                        self.val.checked_div_euclid(rhs.val).expect(concat!(
521                            "dividing(ceil) ",
522                            stringify!($name),
523                            " values overflowed"
524                        ));
525                    let min =
526                        self.min.checked_div_euclid(rhs.min).expect(concat!(
527                            "dividing(ceil) ",
528                            stringify!($name),
529                            " minimums overflowed"
530                        ));
531                    let max =
532                        self.max.checked_div_euclid(rhs.max).expect(concat!(
533                            "dividing(ceil) ",
534                            stringify!($name),
535                            " maximums overflowed"
536                        ));
537                    Self { val, min, max }
538                }
539            }
540
541            #[inline]
542            pub(crate) fn rem_ceil(self, rhs: impl RInto<Self>) -> Self {
543                let rhs = rhs.rinto();
544                #[cfg(not(debug_assertions))]
545                {
546                    let val = self.val.wrapping_rem(rhs.val);
547                    Self { val }
548                }
549                #[cfg(debug_assertions)]
550                {
551                    let val = self.val.checked_rem(rhs.val).expect(concat!(
552                        "modulo(ceil) ",
553                        stringify!($name),
554                        " values overflowed"
555                    ));
556                    let min = self.min.checked_rem(rhs.min).expect(concat!(
557                        "modulo(ceil) ",
558                        stringify!($name),
559                        " minimums overflowed"
560                    ));
561                    let max = self.max.checked_rem(rhs.max).expect(concat!(
562                        "modulo(ceil) ",
563                        stringify!($name),
564                        " maximums overflowed"
565                    ));
566                    Self { val, min, max }
567                }
568            }
569
570            #[inline]
571            pub(crate) fn rem_floor(self, rhs: impl RInto<Self>) -> Self {
572                let rhs = rhs.rinto();
573                #[cfg(not(debug_assertions))]
574                {
575                    let val = self.val.wrapping_rem_euclid(rhs.val);
576                    Self { val }
577                }
578                #[cfg(debug_assertions)]
579                {
580                    let val =
581                        self.val.checked_rem_euclid(rhs.val).expect(concat!(
582                            "modulo(ceil) ",
583                            stringify!($name),
584                            " values overflowed"
585                        ));
586                    let min =
587                        self.min.checked_rem_euclid(rhs.min).expect(concat!(
588                            "modulo(ceil) ",
589                            stringify!($name),
590                            " minimums overflowed"
591                        ));
592                    let max =
593                        self.max.checked_rem_euclid(rhs.max).expect(concat!(
594                            "modulo(ceil) ",
595                            stringify!($name),
596                            " maximums overflowed"
597                        ));
598                    Self { val, min, max }
599                }
600            }
601
602            #[inline]
603            pub(crate) fn try_checked_add(
604                self,
605                what: &'static str,
606                rhs: impl RInto<Self>,
607            ) -> Result<Self, Error> {
608                let rhs = rhs.rinto();
609                self.checked_add(rhs)
610                    .ok_or_else(|| Self::error(what, rhs.get_unchecked()))
611            }
612
613            #[inline]
614            pub(crate) fn try_checked_sub(
615                self,
616                what: &'static str,
617                rhs: impl RInto<Self>,
618            ) -> Result<Self, Error> {
619                let rhs = rhs.rinto();
620                self.checked_sub(rhs)
621                    .ok_or_else(|| Self::error(what, rhs.get_unchecked()))
622            }
623
624            #[inline]
625            pub(crate) fn try_checked_mul(
626                self,
627                what: &'static str,
628                rhs: impl RInto<Self>,
629            ) -> Result<Self, Error> {
630                let rhs = rhs.rinto();
631                self.checked_mul(rhs)
632                    .ok_or_else(|| Self::error(what, rhs.get_unchecked()))
633            }
634
635            #[inline]
636            pub(crate) fn checked_add(
637                self,
638                rhs: impl RInto<Self>,
639            ) -> Option<Self> {
640                let rhs = rhs.rinto();
641                #[cfg(not(debug_assertions))]
642                {
643                    let val = self.val.checked_add(rhs.val)?;
644                    Self::new(val)
645                }
646                #[cfg(debug_assertions)]
647                {
648                    let val = self.val.checked_add(rhs.val)?;
649                    if !Self::contains(val) {
650                        return None;
651                    }
652                    // We specifically clamp min/max at the boundaries because
653                    // the checked arithmetic above implies we will catch
654                    // overflow. If we didn't do this, min/max arithmetic
655                    // could overflow even when the checked arithmetic above
656                    // did not. That is, under normal and expected operation,
657                    // we expect the min/max to eventually overflow even when
658                    // val does not.
659                    let min = self
660                        .min
661                        .saturating_add(rhs.min)
662                        .clamp(Self::MIN_REPR, Self::MAX_REPR);
663                    let max = self
664                        .max
665                        .saturating_add(rhs.max)
666                        .clamp(Self::MIN_REPR, Self::MAX_REPR);
667                    Some(Self { val, min, max })
668                }
669            }
670
671            #[inline]
672            pub(crate) fn checked_sub(
673                self,
674                rhs: impl RInto<Self>,
675            ) -> Option<Self> {
676                let rhs = rhs.rinto();
677                #[cfg(not(debug_assertions))]
678                {
679                    let val = self.val.checked_sub(rhs.val)?;
680                    Self::new(val)
681                }
682                #[cfg(debug_assertions)]
683                {
684                    let val = self.val.checked_sub(rhs.val)?;
685                    if !Self::contains(val) {
686                        return None;
687                    }
688                    // See comment in `checked_add`.
689                    let min = self
690                        .min
691                        .saturating_sub(rhs.min)
692                        .clamp(Self::MIN_REPR, Self::MAX_REPR);
693                    let max = self
694                        .max
695                        .saturating_sub(rhs.max)
696                        .clamp(Self::MIN_REPR, Self::MAX_REPR);
697                    Some(Self { val, min, max })
698                }
699            }
700
701            #[inline]
702            pub(crate) fn checked_mul(
703                self,
704                rhs: impl RInto<Self>,
705            ) -> Option<Self> {
706                let rhs = rhs.rinto();
707                #[cfg(not(debug_assertions))]
708                {
709                    let val = self.val.checked_mul(rhs.val)?;
710                    Self::new(val)
711                }
712                #[cfg(debug_assertions)]
713                {
714                    let val = self.val.checked_mul(rhs.val)?;
715                    if !Self::contains(val) {
716                        return None;
717                    }
718                    // See comment in `checked_add`.
719                    let min = self
720                        .min
721                        .saturating_mul(rhs.min)
722                        .clamp(Self::MIN_REPR, Self::MAX_REPR);
723                    let max = self
724                        .max
725                        .saturating_mul(rhs.max)
726                        .clamp(Self::MIN_REPR, Self::MAX_REPR);
727                    Some(Self { val, min, max })
728                }
729            }
730
731            #[inline]
732            pub(crate) fn wrapping_add(self, rhs: impl RInto<Self>) -> Self {
733                let rhs = rhs.rinto();
734                #[cfg(not(debug_assertions))]
735                {
736                    // When the min/max bounds match our primitive type, then
737                    // standard wrapping arithmetic will work fine. This is
738                    // likely a benefit for perf, but it's also required
739                    // for correctness since we don't support anything else
740                    // at the moment.
741                    if Self::IS_PRIMITIVE {
742                        Self { val: self.val.wrapping_add(rhs.val) }
743                    } else {
744                        unimplemented!(
745                            "wrapping arithmetic for non-primitive \
746                             ranged integers is not implemented yet",
747                        );
748                    }
749                }
750                #[cfg(debug_assertions)]
751                {
752                    if Self::IS_PRIMITIVE {
753                        let val = self.val.wrapping_add(rhs.val);
754                        let min = self.min.wrapping_add(rhs.min);
755                        let max = self.max.wrapping_add(rhs.max);
756                        Self { val, min, max }
757                    } else {
758                        unimplemented!(
759                            "wrapping arithmetic for non-primitive \
760                             ranged integers is not implemented yet",
761                        );
762                    }
763                }
764            }
765
766            #[inline]
767            pub(crate) fn wrapping_sub(self, rhs: impl RInto<Self>) -> Self {
768                let rhs = rhs.rinto();
769                #[cfg(not(debug_assertions))]
770                {
771                    // When the min/max bounds match our primitive type, then
772                    // standard wrapping arithmetic will work fine. This is
773                    // likely a benefit for perf, but it's also required
774                    // for correctness since we don't support anything else
775                    // at the moment.
776                    if Self::IS_PRIMITIVE {
777                        Self { val: self.val.wrapping_sub(rhs.val) }
778                    } else {
779                        unimplemented!(
780                            "wrapping arithmetic for non-primitive \
781                             ranged integers is not implemented yet",
782                        );
783                    }
784                }
785                #[cfg(debug_assertions)]
786                {
787                    if Self::IS_PRIMITIVE {
788                        let val = self.val.wrapping_sub(rhs.val);
789                        let min = self.min.wrapping_sub(rhs.min);
790                        let max = self.max.wrapping_sub(rhs.max);
791                        Self { val, min, max }
792                    } else {
793                        unimplemented!(
794                            "wrapping arithmetic for non-primitive \
795                             ranged integers is not implemented yet",
796                        );
797                    }
798                }
799            }
800
801            #[inline]
802            pub(crate) fn wrapping_mul(self, rhs: impl RInto<Self>) -> Self {
803                let rhs = rhs.rinto();
804                #[cfg(not(debug_assertions))]
805                {
806                    // When the min/max bounds match our primitive type, then
807                    // standard wrapping arithmetic will work fine. This is
808                    // likely a benefit for perf, but it's also required
809                    // for correctness since we don't support anything else
810                    // at the moment.
811                    if Self::IS_PRIMITIVE {
812                        Self { val: self.val.wrapping_mul(rhs.val) }
813                    } else {
814                        unimplemented!(
815                            "wrapping arithmetic for non-primitive \
816                             ranged integers is not implemented yet",
817                        );
818                    }
819                }
820                #[cfg(debug_assertions)]
821                {
822                    if Self::IS_PRIMITIVE {
823                        let val = self.val.wrapping_mul(rhs.val);
824                        let min = self.min.wrapping_mul(rhs.min);
825                        let max = self.max.wrapping_mul(rhs.max);
826                        Self { val, min, max }
827                    } else {
828                        unimplemented!(
829                            "wrapping arithmetic for non-primitive \
830                             ranged integers is not implemented yet",
831                        );
832                    }
833                }
834            }
835
836            #[inline]
837            pub(crate) fn saturating_add(self, rhs: impl RInto<Self>) -> Self {
838                let rhs = rhs.rinto();
839                #[cfg(not(debug_assertions))]
840                {
841                    let val = self
842                        .val
843                        .saturating_add(rhs.val)
844                        .clamp(Self::MIN_REPR, Self::MAX_REPR);
845                    Self { val }
846                }
847                #[cfg(debug_assertions)]
848                {
849                    let val = self
850                        .val
851                        .saturating_add(rhs.val)
852                        .clamp(Self::MIN_REPR, Self::MAX_REPR);
853                    let min = self
854                        .min
855                        .saturating_add(rhs.val)
856                        .clamp(Self::MIN_REPR, Self::MAX_REPR);
857                    let max = self
858                        .max
859                        .saturating_add(rhs.val)
860                        .clamp(Self::MIN_REPR, Self::MAX_REPR);
861                    Self { val, min, max }
862                }
863            }
864
865            #[inline]
866            pub(crate) fn saturating_sub(self, rhs: impl RInto<Self>) -> Self {
867                let rhs = rhs.rinto();
868                #[cfg(not(debug_assertions))]
869                {
870                    let val = self
871                        .val
872                        .saturating_sub(rhs.val)
873                        .clamp(Self::MIN_REPR, Self::MAX_REPR);
874                    Self { val }
875                }
876                #[cfg(debug_assertions)]
877                {
878                    let val = self
879                        .val
880                        .saturating_sub(rhs.val)
881                        .clamp(Self::MIN_REPR, Self::MAX_REPR);
882                    let min = self
883                        .min
884                        .saturating_sub(rhs.val)
885                        .clamp(Self::MIN_REPR, Self::MAX_REPR);
886                    let max = self
887                        .max
888                        .saturating_sub(rhs.val)
889                        .clamp(Self::MIN_REPR, Self::MAX_REPR);
890                    Self { val, min, max }
891                }
892            }
893
894            #[inline]
895            pub(crate) fn saturating_mul(self, rhs: impl RInto<Self>) -> Self {
896                let rhs = rhs.rinto();
897                #[cfg(not(debug_assertions))]
898                {
899                    let val = self
900                        .val
901                        .saturating_mul(rhs.val)
902                        .clamp(Self::MIN_REPR, Self::MAX_REPR);
903                    Self { val }
904                }
905                #[cfg(debug_assertions)]
906                {
907                    let val = self
908                        .val
909                        .saturating_mul(rhs.val)
910                        .clamp(Self::MIN_REPR, Self::MAX_REPR);
911                    let min = self
912                        .min
913                        .saturating_mul(rhs.val)
914                        .clamp(Self::MIN_REPR, Self::MAX_REPR);
915                    let max = self
916                        .max
917                        .saturating_mul(rhs.val)
918                        .clamp(Self::MIN_REPR, Self::MAX_REPR);
919                    Self { val, min, max }
920                }
921            }
922
923            pub(crate) fn debug(self) -> RangedDebug<MIN, MAX> {
924                RangedDebug { rint: self.rinto() }
925            }
926        }
927
928        // We hand-write the `Hash` impl to avoid the min/max values
929        // influencing the hash. Only the actual value should be hashed.
930        //
931        // See: https://github.com/BurntSushi/jiff/issues/330
932        impl<const MIN: i128, const MAX: i128> core::hash::Hash for $name<MIN, MAX> {
933            fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
934                self.val.hash(state);
935            }
936        }
937
938        impl<
939            const MIN1: i128,
940            const MAX1: i128,
941            const MIN2: i128,
942            const MAX2: i128,
943        > RFrom<$name<MIN1, MAX1>> for $name<MIN2, MAX2>
944        {
945            #[inline]
946            fn rfrom(r: $name<MIN1, MAX1>) -> Self {
947                #[cfg(not(debug_assertions))]
948                {
949                    $name { val: r.val }
950                }
951                #[cfg(debug_assertions)]
952                {
953                    $name { val: r.val, min: r.min, max: r.max }
954                }
955            }
956        }
957
958        impl<const MIN: i128, const MAX: i128> RFrom<$name<MIN, MAX>>
959            for $repr
960        {
961            #[inline]
962            fn rfrom(r: $name<MIN, MAX>) -> $repr {
963                r.get()
964            }
965        }
966
967        impl<const MIN: i128, const MAX: i128> From<$name<MIN, MAX>>
968            for $repr
969        {
970            #[inline]
971            fn from(r: $name<MIN, MAX>) -> $repr {
972                r.get()
973            }
974        }
975
976        impl<const MIN: i128, const MAX: i128> RFrom<Constant>
977            for $name<MIN, MAX>
978        {
979            #[inline]
980            fn rfrom(c: Constant) -> Self {
981                #[cfg(not(debug_assertions))]
982                {
983                    Self { val: c.value() as $repr }
984                }
985                #[cfg(debug_assertions)]
986                {
987                    // We specifically allow constants that don't fit in the
988                    // bounds of the integer type, but we don't allow constans
989                    // that can't fit in the actual integer representation.
990                    // This makes doing things like `number % one-plus-max`
991                    // much more convenient.
992                    #[allow(irrefutable_let_patterns)]
993                    let Ok(val) = <$repr>::try_from(c.value()) else {
994                        panic!(
995                            "{c:?} does not fit in {name:?}",
996                            name = stringify!($name),
997                        )
998                    };
999                    Self { val, min: val, max: val }
1000                }
1001            }
1002        }
1003
1004        impl<
1005            const MIN1: i128,
1006            const MAX1: i128,
1007            const MIN2: i128,
1008            const MAX2: i128,
1009        > TryRFrom<$name<MIN1, MAX1>> for $name<MIN2, MAX2>
1010        {
1011            #[inline]
1012            fn try_rfrom(
1013                what: &'static str, r: $name<MIN1, MAX1>,
1014            ) -> Result<Self, Error> {
1015                #[cfg(not(debug_assertions))]
1016                {
1017                    if !Self::contains(r.val) {
1018                        return Err(Self::error(what, r.val));
1019                    }
1020                    Ok($name { val: r.val })
1021                }
1022                #[cfg(debug_assertions)]
1023                {
1024                    if !Self::contains(r.val) {
1025                        return Err(Self::error(what, r.val));
1026                    }
1027                    Ok($name {
1028                        val: r.val,
1029                        min: r.min.clamp(Self::MIN_REPR, Self::MAX_REPR),
1030                        max: r.max.clamp(Self::MIN_REPR, Self::MAX_REPR),
1031                    })
1032                }
1033            }
1034        }
1035
1036        $(
1037            impl<
1038                const MIN1: i128,
1039                const MAX1: i128,
1040                const MIN2: i128,
1041                const MAX2: i128,
1042            > RFrom<$smaller_name<MIN1, MAX1>> for $name<MIN2, MAX2>
1043            {
1044                #[inline]
1045                fn rfrom(r: $smaller_name<MIN1, MAX1>) -> Self {
1046                    #[cfg(not(debug_assertions))]
1047                    {
1048                        Self { val: <$repr>::from(r.val) }
1049                    }
1050                    #[cfg(debug_assertions)]
1051                    {
1052                        Self {
1053                            val: <$repr>::from(r.val),
1054                            min: <$repr>::from(r.min),
1055                            max: <$repr>::from(r.max),
1056                        }
1057                    }
1058                }
1059            }
1060
1061            impl<
1062                const MIN: i128,
1063                const MAX: i128,
1064            > RFrom<$name<MIN, MAX>> for $smaller_repr
1065            {
1066                #[inline]
1067                fn rfrom(r: $name<MIN, MAX>) -> $smaller_repr {
1068                    #[cfg(not(debug_assertions))]
1069                    {
1070                        r.val as $smaller_repr
1071                    }
1072                    #[cfg(debug_assertions)]
1073                    {
1074                        let Ok(val) = <$smaller_repr>::try_from(r.val) else {
1075                            panic!(
1076                                "{from} value {val} does not fit in {to}",
1077                                from = stringify!($name),
1078                                val = r.val,
1079                                to = stringify!($smaller_name),
1080                            );
1081                        };
1082                        if <$smaller_repr>::try_from(r.min).is_err() {
1083                            panic!(
1084                                "{from} min value {val} does not fit in {to}",
1085                                from = stringify!($name),
1086                                val = r.min,
1087                                to = stringify!($smaller_name),
1088                            );
1089                        }
1090                        if <$smaller_repr>::try_from(r.max).is_err() {
1091                            panic!(
1092                                "{from} max value {val} does not fit in {to}",
1093                                from = stringify!($name),
1094                                val = r.max,
1095                                to = stringify!($smaller_name),
1096                            );
1097                        }
1098                        val
1099                    }
1100                }
1101            }
1102
1103            impl<
1104                const MIN: i128,
1105                const MAX: i128,
1106            > From<$name<MIN, MAX>> for $smaller_repr
1107            {
1108                #[inline]
1109                fn from(r: $name<MIN, MAX>) -> $smaller_repr {
1110                    <$smaller_repr>::rfrom(r)
1111                }
1112            }
1113
1114            impl<
1115                const MIN1: i128,
1116                const MAX1: i128,
1117                const MIN2: i128,
1118                const MAX2: i128,
1119            > TryRFrom<$smaller_name<MIN1, MAX1>> for $name<MIN2, MAX2>
1120            {
1121                #[inline]
1122                fn try_rfrom(
1123                    what: &'static str, r: $smaller_name<MIN1, MAX1>,
1124                ) -> Result<Self, Error> {
1125                    #[cfg(not(debug_assertions))]
1126                    {
1127                        let val = <$repr>::from(r.val);
1128                        if !Self::contains(val) {
1129                            return Err(Self::error(what, val));
1130                        }
1131                        Ok(Self { val })
1132                    }
1133                    #[cfg(debug_assertions)]
1134                    {
1135                        let val = <$repr>::from(r.val);
1136                        if !Self::contains(val) {
1137                            return Err(Self::error(what, val));
1138                        }
1139                        Ok(Self {
1140                            val: val,
1141                            min: <$repr>::from(r.min)
1142                                .clamp(Self::MIN_REPR, Self::MAX_REPR),
1143                            max: <$repr>::from(r.max)
1144                                .clamp(Self::MIN_REPR, Self::MAX_REPR),
1145                        })
1146                    }
1147                }
1148            }
1149
1150            impl<
1151                const MIN1: i128,
1152                const MAX1: i128,
1153                const MIN2: i128,
1154                const MAX2: i128,
1155            > PartialEq<$smaller_name<MIN1, MAX1>> for $name<MIN2, MAX2>
1156            {
1157                #[inline]
1158                fn eq(&self, other: &$smaller_name<MIN1, MAX1>) -> bool {
1159                    self.eq(&Self::rfrom(*other))
1160                }
1161            }
1162
1163            impl<
1164                const MIN1: i128,
1165                const MAX1: i128,
1166                const MIN2: i128,
1167                const MAX2: i128,
1168            > PartialOrd<$smaller_name<MIN1, MAX1>> for $name<MIN2, MAX2>
1169            {
1170                #[inline]
1171                fn partial_cmp(
1172                    &self,
1173                    other: &$smaller_name<MIN1, MAX1>,
1174                ) -> Option<Ordering> {
1175                    self.partial_cmp(&Self::rfrom(*other))
1176                }
1177            }
1178
1179            impl<
1180                const MIN1: i128,
1181                const MAX1: i128,
1182                const MIN2: i128,
1183                const MAX2: i128,
1184            > Add<$smaller_name<MIN1, MAX1>> for $name<MIN2, MAX2>
1185            {
1186                type Output = Self;
1187
1188                #[inline]
1189                fn add(self, rhs: $smaller_name<MIN1, MAX1>) -> Self::Output {
1190                    self.add(Self::rfrom(rhs))
1191                }
1192            }
1193
1194            impl<
1195                const MIN1: i128,
1196                const MAX1: i128,
1197                const MIN2: i128,
1198                const MAX2: i128,
1199            > AddAssign<$smaller_name<MIN1, MAX1>> for $name<MIN2, MAX2>
1200            {
1201                #[inline]
1202                fn add_assign(&mut self, rhs: $smaller_name<MIN1, MAX1>) {
1203                    self.add_assign(Self::rfrom(rhs))
1204                }
1205            }
1206
1207            impl<
1208                const MIN1: i128,
1209                const MAX1: i128,
1210                const MIN2: i128,
1211                const MAX2: i128,
1212            > Sub<$smaller_name<MIN1, MAX1>> for $name<MIN2, MAX2>
1213            {
1214                type Output = Self;
1215
1216                #[inline]
1217                fn sub(self, rhs: $smaller_name<MIN1, MAX1>) -> Self::Output {
1218                    self.sub(Self::rfrom(rhs))
1219                }
1220            }
1221
1222            impl<
1223                const MIN1: i128,
1224                const MAX1: i128,
1225                const MIN2: i128,
1226                const MAX2: i128,
1227            > SubAssign<$smaller_name<MIN1, MAX1>> for $name<MIN2, MAX2>
1228            {
1229                #[inline]
1230                fn sub_assign(&mut self, rhs: $smaller_name<MIN1, MAX1>) {
1231                    self.sub_assign(Self::rfrom(rhs))
1232                }
1233            }
1234
1235            impl<
1236                const MIN1: i128,
1237                const MAX1: i128,
1238                const MIN2: i128,
1239                const MAX2: i128,
1240            > Mul<$smaller_name<MIN1, MAX1>> for $name<MIN2, MAX2>
1241            {
1242                type Output = Self;
1243
1244                #[inline]
1245                fn mul(self, rhs: $smaller_name<MIN1, MAX1>) -> Self::Output {
1246                    self.mul(Self::rfrom(rhs))
1247                }
1248            }
1249
1250            impl<
1251                const MIN1: i128,
1252                const MAX1: i128,
1253                const MIN2: i128,
1254                const MAX2: i128,
1255            > MulAssign<$smaller_name<MIN1, MAX1>> for $name<MIN2, MAX2>
1256            {
1257                #[inline]
1258                fn mul_assign(&mut self, rhs: $smaller_name<MIN1, MAX1>) {
1259                    self.mul_assign(Self::rfrom(rhs))
1260                }
1261            }
1262
1263            impl<
1264                const MIN1: i128,
1265                const MAX1: i128,
1266                const MIN2: i128,
1267                const MAX2: i128,
1268            > Div<$smaller_name<MIN1, MAX1>> for $name<MIN2, MAX2>
1269            {
1270                type Output = Self;
1271
1272                #[inline]
1273                fn div(self, rhs: $smaller_name<MIN1, MAX1>) -> Self::Output {
1274                    self.div(Self::rfrom(rhs))
1275                }
1276            }
1277
1278            impl<
1279                const MIN1: i128,
1280                const MAX1: i128,
1281                const MIN2: i128,
1282                const MAX2: i128,
1283            > DivAssign<$smaller_name<MIN1, MAX1>> for $name<MIN2, MAX2>
1284            {
1285                #[inline]
1286                fn div_assign(&mut self, rhs: $smaller_name<MIN1, MAX1>) {
1287                    self.div_assign(Self::rfrom(rhs))
1288                }
1289            }
1290
1291            impl<
1292                const MIN1: i128,
1293                const MAX1: i128,
1294                const MIN2: i128,
1295                const MAX2: i128,
1296            > Rem<$smaller_name<MIN1, MAX1>> for $name<MIN2, MAX2>
1297            {
1298                type Output = Self;
1299
1300                #[inline]
1301                fn rem(self, rhs: $smaller_name<MIN1, MAX1>) -> Self::Output {
1302                    self.rem(Self::rfrom(rhs))
1303                }
1304            }
1305
1306            impl<
1307                const MIN1: i128,
1308                const MAX1: i128,
1309                const MIN2: i128,
1310                const MAX2: i128,
1311            > RemAssign<$smaller_name<MIN1, MAX1>> for $name<MIN2, MAX2>
1312            {
1313                #[inline]
1314                fn rem_assign(&mut self, rhs: $smaller_name<MIN1, MAX1>) {
1315                    self.rem_assign(Self::rfrom(rhs))
1316                }
1317            }
1318        )*
1319
1320        $(
1321            impl<
1322                const MIN1: i128,
1323                const MAX1: i128,
1324                const MIN2: i128,
1325                const MAX2: i128,
1326            > RFrom<$bigger_name<MIN1, MAX1>> for $name<MIN2, MAX2>
1327            {
1328                #[inline]
1329                fn rfrom(r: $bigger_name<MIN1, MAX1>) -> Self {
1330                    #[cfg(not(debug_assertions))]
1331                    {
1332                        Self { val: r.val as $repr }
1333                    }
1334                    #[cfg(debug_assertions)]
1335                    {
1336                        let Ok(val) = <$repr>::try_from(r.val) else {
1337                            panic!(
1338                                "{from} value {val} does not fit in {to}",
1339                                from = stringify!($bigger_name),
1340                                val = r.val,
1341                                to = stringify!($name),
1342                            );
1343                        };
1344                        let Ok(min) = <$repr>::try_from(r.min) else {
1345                            panic!(
1346                                "{from} min value {val} does not fit in {to}",
1347                                from = stringify!($bigger_name),
1348                                val = r.min,
1349                                to = stringify!($name),
1350                            );
1351                        };
1352                        let Ok(max) = <$repr>::try_from(r.max) else {
1353                            panic!(
1354                                "{from} max value {val} does not fit in {to}",
1355                                from = stringify!($bigger_name),
1356                                val = r.max,
1357                                to = stringify!($name),
1358                            );
1359                        };
1360                        Self { val, min, max }
1361                    }
1362                }
1363            }
1364
1365            impl<
1366                const MIN: i128,
1367                const MAX: i128,
1368            > RFrom<$name<MIN, MAX>> for $bigger_repr
1369            {
1370                #[inline]
1371                fn rfrom(r: $name<MIN, MAX>) -> $bigger_repr {
1372                    <$bigger_repr>::from(r.get())
1373                }
1374            }
1375
1376            impl<
1377                const MIN: i128,
1378                const MAX: i128,
1379            > From<$name<MIN, MAX>> for $bigger_repr
1380            {
1381                #[inline]
1382                fn from(r: $name<MIN, MAX>) -> $bigger_repr {
1383                    <$bigger_repr>::rfrom(r)
1384                }
1385            }
1386
1387            impl<
1388                const MIN1: i128,
1389                const MAX1: i128,
1390                const MIN2: i128,
1391                const MAX2: i128,
1392            > TryRFrom<$bigger_name<MIN1, MAX1>> for $name<MIN2, MAX2>
1393            {
1394                #[inline]
1395                fn try_rfrom(
1396                    what: &'static str, r: $bigger_name<MIN1, MAX1>,
1397                ) -> Result<Self, Error> {
1398                    #[cfg(not(debug_assertions))]
1399                    {
1400                        let val = <$repr>::try_from(r.val).map_err(|_| {
1401                            Error::range(what, r.val, MIN2, MAX2)
1402                        })?;
1403                        if !Self::contains(val) {
1404                            return Err(Self::error(what, val));
1405                        }
1406                        Ok(Self { val })
1407                    }
1408                    #[cfg(debug_assertions)]
1409                    {
1410                        let val = <$repr>::try_from(r.val).map_err(|_| {
1411                            Error::range(what, r.val, MIN2, MAX2)
1412                        })?;
1413                        if !Self::contains(val) {
1414                            return Err(Self::error(what, val));
1415                        }
1416                        let min = <$repr>::try_from(r.min).unwrap_or_else(|_| {
1417                            if (r.min as i128) < MIN2 {
1418                                Self::MIN_REPR
1419                            } else {
1420                                assert!(r.min as i128 > MAX2);
1421                                Self::MAX_REPR
1422                            }
1423                        });
1424                        let max = <$repr>::try_from(r.max).unwrap_or_else(|_| {
1425                            if (r.max as i128) < MIN2 {
1426                                Self::MIN_REPR
1427                            } else {
1428                                assert!(r.max as i128 > MAX2);
1429                                Self::MAX_REPR
1430                            }
1431                        });
1432                        Ok(Self {
1433                            val,
1434                            min: min.clamp(Self::MIN_REPR, Self::MAX_REPR),
1435                            max: max.clamp(Self::MIN_REPR, Self::MAX_REPR),
1436                        })
1437                    }
1438                }
1439            }
1440
1441            impl<
1442                const MIN1: i128,
1443                const MAX1: i128,
1444                const MIN2: i128,
1445                const MAX2: i128,
1446            > PartialEq<$bigger_name<MIN1, MAX1>> for $name<MIN2, MAX2>
1447            {
1448                #[inline]
1449                fn eq(&self, other: &$bigger_name<MIN1, MAX1>) -> bool {
1450                    <$bigger_name<MIN1, MAX1>>::rfrom(*self).eq(other)
1451                }
1452            }
1453
1454            impl<
1455                const MIN1: i128,
1456                const MAX1: i128,
1457                const MIN2: i128,
1458                const MAX2: i128,
1459            > PartialOrd<$bigger_name<MIN1, MAX1>> for $name<MIN2, MAX2>
1460            {
1461                #[inline]
1462                fn partial_cmp(
1463                    &self,
1464                    other: &$bigger_name<MIN1, MAX1>,
1465                ) -> Option<Ordering> {
1466                    <$bigger_name<MIN1, MAX1>>::rfrom(*self).partial_cmp(other)
1467                }
1468            }
1469
1470            impl<
1471                const MIN1: i128,
1472                const MAX1: i128,
1473                const MIN2: i128,
1474                const MAX2: i128,
1475            > Add<$bigger_name<MIN1, MAX1>> for $name<MIN2, MAX2>
1476            {
1477                type Output = Self;
1478
1479                #[inline]
1480                fn add(self, rhs: $bigger_name<MIN1, MAX1>) -> Self::Output {
1481                    self.add(Self::rfrom(rhs))
1482                }
1483            }
1484
1485            impl<
1486                const MIN1: i128,
1487                const MAX1: i128,
1488                const MIN2: i128,
1489                const MAX2: i128,
1490            > AddAssign<$bigger_name<MIN1, MAX1>> for $name<MIN2, MAX2>
1491            {
1492                #[inline]
1493                fn add_assign(&mut self, rhs: $bigger_name<MIN1, MAX1>) {
1494                    self.add_assign(Self::rfrom(rhs))
1495                }
1496            }
1497
1498            impl<
1499                const MIN1: i128,
1500                const MAX1: i128,
1501                const MIN2: i128,
1502                const MAX2: i128,
1503            > Sub<$bigger_name<MIN1, MAX1>> for $name<MIN2, MAX2>
1504            {
1505                type Output = Self;
1506
1507                #[inline]
1508                fn sub(self, rhs: $bigger_name<MIN1, MAX1>) -> Self::Output {
1509                    self.sub(Self::rfrom(rhs))
1510                }
1511            }
1512
1513            impl<
1514                const MIN1: i128,
1515                const MAX1: i128,
1516                const MIN2: i128,
1517                const MAX2: i128,
1518            > SubAssign<$bigger_name<MIN1, MAX1>> for $name<MIN2, MAX2>
1519            {
1520                #[inline]
1521                fn sub_assign(&mut self, rhs: $bigger_name<MIN1, MAX1>) {
1522                    self.sub_assign(Self::rfrom(rhs))
1523                }
1524            }
1525
1526            impl<
1527                const MIN1: i128,
1528                const MAX1: i128,
1529                const MIN2: i128,
1530                const MAX2: i128,
1531            > Mul<$bigger_name<MIN1, MAX1>> for $name<MIN2, MAX2>
1532            {
1533                type Output = Self;
1534
1535                #[inline]
1536                fn mul(self, rhs: $bigger_name<MIN1, MAX1>) -> Self::Output {
1537                    self.mul(Self::rfrom(rhs))
1538                }
1539            }
1540
1541            impl<
1542                const MIN1: i128,
1543                const MAX1: i128,
1544                const MIN2: i128,
1545                const MAX2: i128,
1546            > MulAssign<$bigger_name<MIN1, MAX1>> for $name<MIN2, MAX2>
1547            {
1548                #[inline]
1549                fn mul_assign(&mut self, rhs: $bigger_name<MIN1, MAX1>) {
1550                    self.mul_assign(Self::rfrom(rhs))
1551                }
1552            }
1553
1554            impl<
1555                const MIN1: i128,
1556                const MAX1: i128,
1557                const MIN2: i128,
1558                const MAX2: i128,
1559            > Div<$bigger_name<MIN1, MAX1>> for $name<MIN2, MAX2>
1560            {
1561                type Output = Self;
1562
1563                #[inline]
1564                fn div(self, rhs: $bigger_name<MIN1, MAX1>) -> Self::Output {
1565                    self.div(Self::rfrom(rhs))
1566                }
1567            }
1568
1569            impl<
1570                const MIN1: i128,
1571                const MAX1: i128,
1572                const MIN2: i128,
1573                const MAX2: i128,
1574            > DivAssign<$bigger_name<MIN1, MAX1>> for $name<MIN2, MAX2>
1575            {
1576                #[inline]
1577                fn div_assign(&mut self, rhs: $bigger_name<MIN1, MAX1>) {
1578                    self.div_assign(Self::rfrom(rhs))
1579                }
1580            }
1581
1582            impl<
1583                const MIN1: i128,
1584                const MAX1: i128,
1585                const MIN2: i128,
1586                const MAX2: i128,
1587            > Rem<$bigger_name<MIN1, MAX1>> for $name<MIN2, MAX2>
1588            {
1589                type Output = Self;
1590
1591                #[inline]
1592                fn rem(self, rhs: $bigger_name<MIN1, MAX1>) -> Self::Output {
1593                    self.rem(Self::rfrom(rhs))
1594                }
1595            }
1596
1597            impl<
1598                const MIN1: i128,
1599                const MAX1: i128,
1600                const MIN2: i128,
1601                const MAX2: i128,
1602            > RemAssign<$bigger_name<MIN1, MAX1>> for $name<MIN2, MAX2>
1603            {
1604                #[inline]
1605                fn rem_assign(&mut self, rhs: $bigger_name<MIN1, MAX1>) {
1606                    self.rem_assign(Self::rfrom(rhs))
1607                }
1608            }
1609        )*
1610
1611        impl<const MIN: i128, const MAX: i128> Neg for $name<MIN, MAX> {
1612            type Output = Self;
1613
1614            #[inline]
1615            fn neg(self) -> Self {
1616                #[cfg(not(debug_assertions))]
1617                {
1618                    let val = self.val.wrapping_neg();
1619                    Self { val }
1620                }
1621                #[cfg(debug_assertions)]
1622                {
1623                    let val = self.val.checked_neg().expect(concat!(
1624                        "negating ",
1625                        stringify!($name),
1626                        " values overflowed"
1627                    ));
1628                    let min = self.min.checked_neg().expect(concat!(
1629                        "negating ",
1630                        stringify!($name),
1631                        " minimums overflowed"
1632                    ));
1633                    let max = self.max.checked_neg().expect(concat!(
1634                        "negating ",
1635                        stringify!($name),
1636                        " maximums overflowed"
1637                    ));
1638                    Self { val, min, max }
1639                }
1640            }
1641        }
1642
1643        impl<
1644            const MIN1: i128,
1645            const MAX1: i128,
1646            const MIN2: i128,
1647            const MAX2: i128,
1648        > Add<$name<MIN2, MAX2>> for $name<MIN1, MAX1> {
1649            type Output = Self;
1650
1651            #[inline]
1652            fn add(self, rhs: $name<MIN2, MAX2>) -> Self::Output {
1653                #[cfg(not(debug_assertions))]
1654                {
1655                    let val = self.val.wrapping_add(rhs.val);
1656                    Self { val }
1657                }
1658                #[cfg(debug_assertions)]
1659                {
1660                    let val = self.val.checked_add(rhs.val).expect(concat!(
1661                        "adding ",
1662                        stringify!($name),
1663                        " values overflowed"
1664                    ));
1665                    let min = self.min.checked_add(rhs.min).expect(concat!(
1666                        "adding ",
1667                        stringify!($name),
1668                        " minimums overflowed"
1669                    ));
1670                    let max = self.max.checked_add(rhs.max).expect(concat!(
1671                        "adding ",
1672                        stringify!($name),
1673                        " maximums overflowed"
1674                    ));
1675                    Self { val, min, max }
1676                }
1677            }
1678        }
1679
1680        impl<
1681            const MIN1: i128,
1682            const MAX1: i128,
1683            const MIN2: i128,
1684            const MAX2: i128,
1685        > AddAssign<$name<MIN2, MAX2>> for $name<MIN1, MAX1> {
1686            #[inline]
1687            fn add_assign(&mut self, rhs: $name<MIN2, MAX2>) {
1688                *self = self.add(rhs);
1689            }
1690        }
1691
1692        impl<
1693            const MIN1: i128,
1694            const MAX1: i128,
1695            const MIN2: i128,
1696            const MAX2: i128,
1697        > Sub<$name<MIN2, MAX2>> for $name<MIN1, MAX1> {
1698            type Output = Self;
1699
1700            #[inline]
1701            fn sub(self, rhs: $name<MIN2, MAX2>) -> Self::Output {
1702                #[cfg(not(debug_assertions))]
1703                {
1704                    let val = self.val.wrapping_sub(rhs.val);
1705                    Self { val }
1706                }
1707                #[cfg(debug_assertions)]
1708                {
1709                    let val = self.val.checked_sub(rhs.val).expect(concat!(
1710                        "subtracting ",
1711                        stringify!($name),
1712                        " values overflowed"
1713                    ));
1714                    let min = self.min.checked_sub(rhs.min).expect(concat!(
1715                        "subtracting ",
1716                        stringify!($name),
1717                        " minimums overflowed"
1718                    ));
1719                    let max = self.max.checked_sub(rhs.max).expect(concat!(
1720                        "subtracting ",
1721                        stringify!($name),
1722                        " maximums overflowed"
1723                    ));
1724                    Self { val, min, max }
1725                }
1726            }
1727        }
1728
1729        impl<
1730            const MIN1: i128,
1731            const MAX1: i128,
1732            const MIN2: i128,
1733            const MAX2: i128,
1734        > SubAssign<$name<MIN2, MAX2>> for $name<MIN1, MAX1> {
1735            #[inline]
1736            fn sub_assign(&mut self, rhs: $name<MIN2, MAX2>) {
1737                *self = self.sub(rhs);
1738            }
1739        }
1740
1741        impl<
1742            const MIN1: i128,
1743            const MAX1: i128,
1744            const MIN2: i128,
1745            const MAX2: i128,
1746        > Mul<$name<MIN2, MAX2>> for $name<MIN1, MAX1> {
1747            type Output = Self;
1748
1749            #[inline]
1750            fn mul(self, rhs: $name<MIN2, MAX2>) -> Self::Output {
1751                #[cfg(not(debug_assertions))]
1752                {
1753                    let val = self.val.wrapping_mul(rhs.val);
1754                    Self { val }
1755                }
1756                #[cfg(debug_assertions)]
1757                {
1758                    let val = self.val.checked_mul(rhs.val).expect(concat!(
1759                        "multiplying ",
1760                        stringify!($name),
1761                        " values overflowed"
1762                    ));
1763                    let min = self.min.checked_mul(rhs.min).expect(concat!(
1764                        "multiplying ",
1765                        stringify!($name),
1766                        " minimums overflowed"
1767                    ));
1768                    let max = self.max.checked_mul(rhs.max).expect(concat!(
1769                        "multiplying ",
1770                        stringify!($name),
1771                        " maximums overflowed"
1772                    ));
1773                    Self { val, min, max }
1774                }
1775            }
1776        }
1777
1778        impl<
1779            const MIN1: i128,
1780            const MAX1: i128,
1781            const MIN2: i128,
1782            const MAX2: i128,
1783        > MulAssign<$name<MIN2, MAX2>> for $name<MIN1, MAX1> {
1784            #[inline]
1785            fn mul_assign(&mut self, rhs: $name<MIN2, MAX2>) {
1786                *self = self.mul(rhs);
1787            }
1788        }
1789
1790        impl<
1791            const MIN1: i128,
1792            const MAX1: i128,
1793            const MIN2: i128,
1794            const MAX2: i128,
1795        > Div<$name<MIN2, MAX2>> for $name<MIN1, MAX1> {
1796            type Output = Self;
1797
1798            #[inline]
1799            fn div(self, rhs: $name<MIN2, MAX2>) -> Self::Output {
1800                #[cfg(not(debug_assertions))]
1801                {
1802                    let val = self.val.wrapping_div_euclid(rhs.val);
1803                    Self { val }
1804                }
1805                #[cfg(debug_assertions)]
1806                {
1807                    let val =
1808                        self.val.checked_div_euclid(rhs.val).expect(concat!(
1809                            "dividing ",
1810                            stringify!($name),
1811                            " values overflowed"
1812                        ));
1813                    let min =
1814                        self.min.checked_div_euclid(rhs.min).expect(concat!(
1815                            "dividing ",
1816                            stringify!($name),
1817                            " minimums overflowed"
1818                        ));
1819                    let max =
1820                        self.max.checked_div_euclid(rhs.max).expect(concat!(
1821                            "dividing ",
1822                            stringify!($name),
1823                            " maximums overflowed"
1824                        ));
1825                    Self { val, min, max }
1826                }
1827            }
1828        }
1829
1830        impl<
1831            const MIN1: i128,
1832            const MAX1: i128,
1833            const MIN2: i128,
1834            const MAX2: i128,
1835        > DivAssign<$name<MIN2, MAX2>> for $name<MIN1, MAX1> {
1836            #[inline]
1837            fn div_assign(&mut self, rhs: $name<MIN2, MAX2>) {
1838                *self = self.div(rhs);
1839            }
1840        }
1841
1842        impl<
1843            const MIN1: i128,
1844            const MAX1: i128,
1845            const MIN2: i128,
1846            const MAX2: i128,
1847        > Rem<$name<MIN2, MAX2>> for $name<MIN1, MAX1> {
1848            type Output = Self;
1849
1850            #[inline]
1851            fn rem(self, rhs: $name<MIN2, MAX2>) -> Self::Output {
1852                #[cfg(not(debug_assertions))]
1853                {
1854                    let val = self.val.wrapping_rem_euclid(rhs.val);
1855                    Self { val }
1856                }
1857                #[cfg(debug_assertions)]
1858                {
1859                    let val =
1860                        self.val.checked_rem_euclid(rhs.val).expect(concat!(
1861                            "modulo ",
1862                            stringify!($name),
1863                            " values overflowed"
1864                        ));
1865                    let min =
1866                        self.min.checked_rem_euclid(rhs.min).expect(concat!(
1867                            "modulo ",
1868                            stringify!($name),
1869                            " minimums overflowed"
1870                        ));
1871                    let max =
1872                        self.max.checked_rem_euclid(rhs.max).expect(concat!(
1873                            "modulo ",
1874                            stringify!($name),
1875                            " maximums overflowed"
1876                        ));
1877                    Self { val, min, max }
1878                }
1879            }
1880        }
1881
1882        impl<
1883            const MIN1: i128,
1884            const MAX1: i128,
1885            const MIN2: i128,
1886            const MAX2: i128,
1887        > RemAssign<$name<MIN2, MAX2>> for $name<MIN1, MAX1> {
1888            #[inline]
1889            fn rem_assign(&mut self, rhs: $name<MIN2, MAX2>) {
1890                *self = self.rem(rhs);
1891            }
1892        }
1893
1894        impl<const MIN: i128, const MAX: i128> Add<$name<MIN, MAX>>
1895            for Constant
1896        {
1897            type Output = $name<MIN, MAX>;
1898
1899            #[inline]
1900            fn add(self, rhs: $name<MIN, MAX>) -> Self::Output {
1901                $name::rfrom(self).add(rhs)
1902            }
1903        }
1904
1905        impl<const MIN: i128, const MAX: i128> Add<Constant> for $name<MIN, MAX> {
1906            type Output = $name<MIN, MAX>;
1907
1908            #[inline]
1909            fn add(self, rhs: Constant) -> Self::Output {
1910                self.add(Self::rfrom(rhs))
1911            }
1912        }
1913
1914        impl<const MIN: i128, const MAX: i128> AddAssign<Constant> for $name<MIN, MAX> {
1915            #[inline]
1916            fn add_assign(&mut self, rhs: Constant) {
1917                self.add_assign(Self::rfrom(rhs))
1918            }
1919        }
1920
1921        impl<const MIN: i128, const MAX: i128> Sub<$name<MIN, MAX>> for Constant {
1922            type Output = $name<MIN, MAX>;
1923
1924            #[inline]
1925            fn sub(self, rhs: $name<MIN, MAX>) -> Self::Output {
1926                $name::rfrom(self).sub(rhs)
1927            }
1928        }
1929
1930        impl<const MIN: i128, const MAX: i128> Sub<Constant> for $name<MIN, MAX> {
1931            type Output = $name<MIN, MAX>;
1932
1933            #[inline]
1934            fn sub(self, rhs: Constant) -> Self::Output {
1935                self.sub(Self::rfrom(rhs))
1936            }
1937        }
1938
1939        impl<const MIN: i128, const MAX: i128> SubAssign<Constant> for $name<MIN, MAX> {
1940            #[inline]
1941            fn sub_assign(&mut self, rhs: Constant) {
1942                self.sub_assign(Self::rfrom(rhs))
1943            }
1944        }
1945
1946        impl<const MIN: i128, const MAX: i128> Mul<$name<MIN, MAX>> for Constant {
1947            type Output = $name<MIN, MAX>;
1948
1949            #[inline]
1950            fn mul(self, rhs: $name<MIN, MAX>) -> Self::Output {
1951                $name::rfrom(self).mul(rhs)
1952            }
1953        }
1954
1955        impl<const MIN: i128, const MAX: i128> Mul<Constant> for $name<MIN, MAX> {
1956            type Output = $name<MIN, MAX>;
1957
1958            #[inline]
1959            fn mul(self, rhs: Constant) -> Self::Output {
1960                self.mul(Self::rfrom(rhs))
1961            }
1962        }
1963
1964        impl<const MIN: i128, const MAX: i128> MulAssign<Constant> for $name<MIN, MAX> {
1965            #[inline]
1966            fn mul_assign(&mut self, rhs: Constant) {
1967                self.mul_assign(Self::rfrom(rhs))
1968            }
1969        }
1970
1971        impl<const MIN: i128, const MAX: i128> Div<$name<MIN, MAX>> for Constant {
1972            type Output = $name<MIN, MAX>;
1973
1974            #[inline]
1975            fn div(self, rhs: $name<MIN, MAX>) -> Self::Output {
1976                $name::rfrom(self).div(rhs)
1977            }
1978        }
1979
1980        impl<const MIN: i128, const MAX: i128> Div<Constant> for $name<MIN, MAX> {
1981            type Output = $name<MIN, MAX>;
1982
1983            #[inline]
1984            fn div(self, rhs: Constant) -> Self::Output {
1985                self.div(Self::rfrom(rhs))
1986            }
1987        }
1988        impl<const MIN: i128, const MAX: i128> DivAssign<Constant> for $name<MIN, MAX> {
1989            #[inline]
1990            fn div_assign(&mut self, rhs: Constant) {
1991                self.div_assign(Self::rfrom(rhs))
1992            }
1993        }
1994
1995        impl<const MIN: i128, const MAX: i128> Rem<$name<MIN, MAX>> for Constant {
1996            type Output = $name<MIN, MAX>;
1997
1998            #[inline]
1999            fn rem(self, rhs: $name<MIN, MAX>) -> Self::Output {
2000                $name::rfrom(self).rem(rhs)
2001            }
2002        }
2003
2004        impl<const MIN: i128, const MAX: i128> Rem<Constant> for $name<MIN, MAX> {
2005            type Output = $name<MIN, MAX>;
2006
2007            #[inline]
2008            fn rem(self, rhs: Constant) -> Self::Output {
2009                self.rem(Self::rfrom(rhs))
2010            }
2011        }
2012        impl<const MIN: i128, const MAX: i128> RemAssign<Constant> for $name<MIN, MAX> {
2013            #[inline]
2014            fn rem_assign(&mut self, rhs: Constant) {
2015                self.rem_assign(Self::rfrom(rhs))
2016            }
2017        }
2018
2019        impl<const MIN: i128, const MAX: i128> Eq for $name<MIN, MAX> {}
2020
2021        impl<
2022            const MIN1: i128,
2023            const MAX1: i128,
2024            const MIN2: i128,
2025            const MAX2: i128,
2026        > PartialEq<$name<MIN2, MAX2>> for $name<MIN1, MAX1> {
2027            #[inline]
2028            fn eq(&self, other: &$name<MIN2, MAX2>) -> bool {
2029                self.val.eq(&other.val)
2030            }
2031        }
2032
2033        impl<const MIN: i128, const MAX: i128> PartialEq<Constant> for $name<MIN, MAX> {
2034            #[inline]
2035            fn eq(&self, other: &Constant) -> bool {
2036                self.val.eq(&<$repr>::from(*other))
2037            }
2038        }
2039
2040        impl<const MIN: i128, const MAX: i128> PartialEq<$name<MIN, MAX>> for Constant {
2041            #[inline]
2042            fn eq(&self, other: &$name<MIN, MAX>) -> bool {
2043                <$repr>::from(*self).eq(&other.val)
2044            }
2045        }
2046
2047        impl<const MIN: i128, const MAX: i128> Ord for $name<MIN, MAX> {
2048            #[inline]
2049            fn cmp(&self, other: &Self) -> core::cmp::Ordering {
2050                self.val.cmp(&other.val)
2051            }
2052        }
2053
2054        impl<
2055            const MIN1: i128,
2056            const MAX1: i128,
2057            const MIN2: i128,
2058            const MAX2: i128,
2059        > PartialOrd<$name<MIN2, MAX2>> for $name<MIN1, MAX1> {
2060            #[inline]
2061            fn partial_cmp(
2062                &self,
2063                other: &$name<MIN2, MAX2>,
2064            ) -> Option<core::cmp::Ordering> {
2065                self.val.partial_cmp(&other.val)
2066            }
2067        }
2068
2069        impl<const MIN: i128, const MAX: i128> PartialOrd<Constant> for $name<MIN, MAX> {
2070            #[inline]
2071            fn partial_cmp(
2072                &self,
2073                other: &Constant,
2074            ) -> Option<core::cmp::Ordering> {
2075                self.val.partial_cmp(&<$repr>::from(*other))
2076            }
2077        }
2078
2079        impl<const MIN: i128, const MAX: i128> PartialOrd<$name<MIN, MAX>> for Constant {
2080            #[inline]
2081            fn partial_cmp(
2082                &self,
2083                other: &$name<MIN, MAX>,
2084            ) -> Option<core::cmp::Ordering> {
2085                <$repr>::from(*self).partial_cmp(&other.val)
2086            }
2087        }
2088
2089        impl<const MIN: i128, const MAX: i128> core::fmt::Display for $name<MIN, MAX> {
2090            fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
2091                // We do this dance here because a Display impl is often used
2092                // when formatting a panic message, and panicking in this
2093                // context is supremely annoying because it causes an instant
2094                // abort. So if this value is not in bounds, then we write out
2095                // its debug repr which should show some nice output.
2096                match self.checked_add(Self::N::<0>()) {
2097                    Some(val) => core::fmt::Display::fmt(&val.get(), f),
2098                    None => write!(f, "{:?}", self),
2099                }
2100            }
2101        }
2102
2103        impl<const MIN: i128, const MAX: i128> core::fmt::Debug for $name<MIN, MAX> {
2104            fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
2105                self.debug().fmt(f)
2106                /*
2107                if !f.alternate() {
2108                    self.debug().fmt(f)
2109                } else {
2110                    #[cfg(not(debug_assertions))]
2111                    {
2112                        f.debug_struct(stringify!($name))
2113                            .field("val", &self.val)
2114                            .field("MIN", &MIN)
2115                            .field("MAX", &MAX)
2116                            .finish()
2117                    }
2118                    #[cfg(debug_assertions)]
2119                    {
2120                        f.debug_struct(stringify!($name))
2121                            .field("val", &self.val)
2122                            .field("MIN", &MIN)
2123                            .field("MAX", &MAX)
2124                            .field("computed_min", &self.min)
2125                            .field("computed_max", &self.max)
2126                            .finish()
2127                    }
2128                }
2129                */
2130            }
2131        }
2132
2133        #[cfg(test)]
2134        impl<const MIN: i128, const MAX: i128> quickcheck::Arbitrary for $name<MIN, MAX> {
2135            fn arbitrary(g: &mut quickcheck::Gen) -> Self {
2136                let mut n: $repr = <$repr>::arbitrary(g);
2137                if !Self::IS_PRIMITIVE {
2138                    n = n.wrapping_rem_euclid(Self::LEN as $repr);
2139                    n += Self::MIN_REPR;
2140                }
2141                Self::new(n).unwrap()
2142            }
2143
2144            fn shrink(&self) -> alloc::boxed::Box<dyn Iterator<Item = Self>> {
2145                alloc::boxed::Box::new(self.val.shrink().filter_map(Self::new))
2146            }
2147        }
2148    };
2149}
2150
2151define_ranged!(ri8, i8, smaller {}, bigger { ri16 i16, ri32 i32, ri64 i64, ri128 i128 });
2152define_ranged!(ri16, i16, smaller { ri8 i8 }, bigger { ri32 i32, ri64 i64, ri128 i128 });
2153define_ranged!(ri32, i32, smaller { ri8 i8, ri16 i16 }, bigger { ri64 i64, ri128 i128 });
2154define_ranged!(ri64, i64, smaller { ri8 i8, ri16 i16, ri32 i32 }, bigger { ri128 i128 });
2155define_ranged!(ri128, i128, smaller { ri8 i8, ri16 i16, ri32 i32, ri64 i64 }, bigger {});
2156
2157impl<const MIN: i128, const MAX: i128> ri8<MIN, MAX> {
2158    #[inline]
2159    pub(crate) fn without_bounds(
2160        self,
2161    ) -> ri64<{ i64::MIN as i128 }, { i64::MAX as i128 }> {
2162        ri64::rfrom(self)
2163    }
2164}
2165
2166impl<const MIN: i128, const MAX: i128> ri16<MIN, MAX> {
2167    #[inline]
2168    pub(crate) fn without_bounds(
2169        self,
2170    ) -> ri64<{ i64::MIN as i128 }, { i64::MAX as i128 }> {
2171        ri64::rfrom(self)
2172    }
2173}
2174
2175impl<const MIN: i128, const MAX: i128> ri32<MIN, MAX> {
2176    #[inline]
2177    pub(crate) fn without_bounds(
2178        self,
2179    ) -> ri64<{ i64::MIN as i128 }, { i64::MAX as i128 }> {
2180        ri64::rfrom(self)
2181    }
2182}
2183
2184impl<const MIN: i128, const MAX: i128> ri64<MIN, MAX> {
2185    #[inline]
2186    pub(crate) fn without_bounds(
2187        self,
2188    ) -> ri64<{ i64::MIN as i128 }, { i64::MAX as i128 }> {
2189        ri64::rfrom(self)
2190    }
2191}
2192
2193impl<const MIN: i128, const MAX: i128> ri128<MIN, MAX> {
2194    #[inline]
2195    pub(crate) fn without_bounds(self) -> ri128<{ i128::MIN }, { i128::MAX }> {
2196        ri128::rfrom(self)
2197    }
2198}
2199
2200pub(crate) struct RangedDebug<const MIN: i128, const MAX: i128> {
2201    rint: ri128<MIN, MAX>,
2202}
2203
2204impl<const MIN: i128, const MAX: i128> core::fmt::Debug
2205    for RangedDebug<MIN, MAX>
2206{
2207    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
2208        #[cfg(not(debug_assertions))]
2209        {
2210            let val = self.rint.get_unchecked();
2211            if <ri128<MIN, MAX>>::contains(val) {
2212                val.fmt(f)
2213            } else {
2214                write!(f, "#{val:?} [out of range: {MIN}..={MAX}]#")
2215            }
2216        }
2217        #[cfg(debug_assertions)]
2218        {
2219            let val = self.rint.get_unchecked();
2220            let min = self.rint.min;
2221            let max = self.rint.max;
2222            if <ri128<MIN, MAX>>::contains(val)
2223                && <ri128<MIN, MAX>>::contains(min)
2224                && <ri128<MIN, MAX>>::contains(max)
2225            {
2226                val.fmt(f)
2227            } else {
2228                write!(
2229                    f,
2230                    "#{val:?} \
2231                     [out of range: {MIN}..={MAX}] \
2232                     [possible range: {min}..={max}]#",
2233                )
2234            }
2235        }
2236    }
2237}
2238
2239/// A trait for losslessly converting between ranged integers.
2240///
2241/// This trait exists despite the fact that the standard library `From` trait
2242/// is defined in precisely the same way. Indeed, the `From` trait _almost_
2243/// works for our use case. The problem arises from the fact that we want
2244/// to be able to write this trait impl:
2245///
2246/// ```ignore
2247/// impl<
2248///     const MIN1: i128,
2249///     const MAX1: i128,
2250///     const MIN2: i128,
2251///     const MAX2: i128,
2252/// > From<ri64<MIN1, MAX1>> for ri64<MIN2, MAX2> {
2253/// // ...
2254/// }
2255/// ```
2256///
2257/// (We want this impl because we want to be able to freely convert between any
2258/// kind of ranged integers, including ranged integers with the same primitive
2259/// representation but different bounds.)
2260///
2261/// But this trait impl can't exist because it overlaps with the blanket
2262/// `impl From<T> for T`. Indeed, here, we do not provide that blanket impl,
2263/// which lets us add the trait impl above for `RFrom`.
2264///
2265/// This would normally be a no-go because it's too important for library
2266/// crates to provide types that work with `From` as you might expect, but
2267/// range integers are thankfully a crate internal abstraction. So we just need
2268/// to write `impl RFrom<T>` and do `t.rinto()` instead of `impl From<T>` and
2269/// `t.into()`.
2270pub(crate) trait RFrom<T>: Sized {
2271    fn rfrom(value: T) -> Self;
2272}
2273
2274/// A trait for losslessly converting to ranged integers.
2275///
2276/// This goes along with `RFrom` and exists to make things like `t.rinto()`
2277/// work without the need to do `T::rfrom(..)`. Like the standard library
2278/// `Into` trait, a blanket impl is provided based on impls of `RFrom`. Callers
2279/// are not expected to implement this trait directly.
2280pub(crate) trait RInto<T>: Sized {
2281    fn rinto(self) -> T;
2282}
2283
2284impl<T, U> RInto<U> for T
2285where
2286    U: RFrom<T>,
2287{
2288    fn rinto(self) -> U {
2289        RFrom::rfrom(self)
2290    }
2291}
2292
2293pub(crate) trait TryRFrom<T>: Sized {
2294    fn try_rfrom(what: &'static str, value: T) -> Result<Self, Error>;
2295}
2296
2297pub(crate) trait TryRInto<T>: Sized {
2298    fn try_rinto(self, what: &'static str) -> Result<T, Error>;
2299}
2300
2301impl<T, U> TryRInto<U> for T
2302where
2303    U: TryRFrom<T>,
2304{
2305    #[inline]
2306    fn try_rinto(self, what: &'static str) -> Result<U, Error> {
2307        U::try_rfrom(what, self)
2308    }
2309}
2310
2311macro_rules! composite {
2312    (($($name:ident),* $(,)?) => $with:expr) => {{
2313        crate::util::rangeint::composite!(($($name = $name),*) => $with)
2314    }};
2315    (($($name:ident = $rangeint:expr),* $(,)?) => $with:expr) => {{
2316        #[cfg(not(debug_assertions))]
2317        {
2318            $(
2319                let $name = $rangeint.val;
2320            )*
2321            let val = $with;
2322            crate::util::rangeint::Composite { val }
2323        }
2324        #[cfg(debug_assertions)]
2325        {
2326            let val = {
2327                $(
2328                    let $name = $rangeint.val;
2329                )*
2330                $with
2331            };
2332            let min = {
2333                $(
2334                    let $name = $rangeint.min;
2335                )*
2336                $with
2337            };
2338            let max = {
2339                $(
2340                    let $name = $rangeint.max;
2341                )*
2342                $with
2343            };
2344            crate::util::rangeint::Composite { val, min, max }
2345        }
2346    }};
2347}
2348
2349macro_rules! uncomposite {
2350    ($composite:expr, $val:ident => ($($get:expr),* $(,)?) $(,)?) => {{
2351        #[cfg(not(debug_assertions))]
2352        {
2353            ($({
2354                let val = {
2355                    let $val = $composite.val;
2356                    $get
2357                };
2358                crate::util::rangeint::Composite { val }
2359            }),*)
2360        }
2361        #[cfg(debug_assertions)]
2362        {
2363            ($({
2364                let val = {
2365                    let $val = $composite.val;
2366                    $get
2367                };
2368                let min = {
2369                    let $val = $composite.min;
2370                    $get
2371                };
2372                let max = {
2373                    let $val = $composite.max;
2374                    $get
2375                };
2376                crate::util::rangeint::Composite { val, min, max }
2377            }),*)
2378        }
2379    }};
2380}
2381
2382pub(crate) use {composite, uncomposite};
2383
2384#[derive(Clone, Debug, Eq, PartialEq)]
2385pub(crate) struct Composite<T> {
2386    pub(crate) val: T,
2387    #[cfg(debug_assertions)]
2388    pub(crate) min: T,
2389    #[cfg(debug_assertions)]
2390    pub(crate) max: T,
2391}
2392
2393impl<T> Composite<T> {
2394    #[inline]
2395    pub(crate) fn map<U>(self, map: impl Fn(T) -> U) -> Composite<U> {
2396        #[cfg(not(debug_assertions))]
2397        {
2398            Composite { val: map(self.val) }
2399        }
2400        #[cfg(debug_assertions)]
2401        {
2402            Composite {
2403                val: map(self.val),
2404                min: map(self.min),
2405                max: map(self.max),
2406            }
2407        }
2408    }
2409
2410    #[inline]
2411    pub(crate) fn zip2<U>(self, other: Composite<U>) -> Composite<(T, U)> {
2412        #[cfg(not(debug_assertions))]
2413        {
2414            Composite { val: (self.val, other.val) }
2415        }
2416        #[cfg(debug_assertions)]
2417        {
2418            Composite {
2419                val: (self.val, other.val),
2420                min: (self.min, other.min),
2421                max: (self.max, other.max),
2422            }
2423        }
2424    }
2425}
2426
2427impl<T, U> Composite<(T, U)> {
2428    #[inline]
2429    pub(crate) fn unzip2(self) -> (Composite<T>, Composite<U>) {
2430        #[cfg(not(debug_assertions))]
2431        {
2432            (Composite { val: self.val.0 }, Composite { val: self.val.1 })
2433        }
2434        #[cfg(debug_assertions)]
2435        {
2436            (
2437                Composite {
2438                    val: self.val.0,
2439                    min: self.min.0,
2440                    max: self.max.0,
2441                },
2442                Composite {
2443                    val: self.val.1,
2444                    min: self.min.1,
2445                    max: self.max.1,
2446                },
2447            )
2448        }
2449    }
2450}
2451
2452impl Composite<i8> {
2453    pub(crate) const fn to_rint<const MIN: i128, const MAX: i128>(
2454        self,
2455    ) -> ri8<MIN, MAX> {
2456        #[cfg(not(debug_assertions))]
2457        {
2458            ri8 { val: self.val }
2459        }
2460        #[cfg(debug_assertions)]
2461        {
2462            ri8 { val: self.val, min: self.min, max: self.max }
2463        }
2464    }
2465}
2466
2467impl Composite<i16> {
2468    pub(crate) const fn to_rint<const MIN: i128, const MAX: i128>(
2469        self,
2470    ) -> ri16<MIN, MAX> {
2471        #[cfg(not(debug_assertions))]
2472        {
2473            ri16 { val: self.val }
2474        }
2475        #[cfg(debug_assertions)]
2476        {
2477            ri16 { val: self.val, min: self.min, max: self.max }
2478        }
2479    }
2480}
2481
2482impl Composite<i32> {
2483    pub(crate) const fn to_rint<const MIN: i128, const MAX: i128>(
2484        self,
2485    ) -> ri32<MIN, MAX> {
2486        #[cfg(not(debug_assertions))]
2487        {
2488            ri32 { val: self.val }
2489        }
2490        #[cfg(debug_assertions)]
2491        {
2492            ri32 { val: self.val, min: self.min, max: self.max }
2493        }
2494    }
2495}
2496
2497impl Composite<i64> {
2498    pub(crate) const fn to_rint<const MIN: i128, const MAX: i128>(
2499        self,
2500    ) -> ri64<MIN, MAX> {
2501        #[cfg(not(debug_assertions))]
2502        {
2503            ri64 { val: self.val }
2504        }
2505        #[cfg(debug_assertions)]
2506        {
2507            ri64 { val: self.val, min: self.min, max: self.max }
2508        }
2509    }
2510
2511    pub(crate) fn try_to_rint<const MIN: i128, const MAX: i128>(
2512        self,
2513        what: &'static str,
2514    ) -> Result<ri64<MIN, MAX>, Error> {
2515        #[cfg(not(debug_assertions))]
2516        {
2517            if !ri64::<MIN, MAX>::contains(self.val) {
2518                return Err(ri64::<MIN, MAX>::error(what, self.val));
2519            }
2520            Ok(ri64 { val: self.val })
2521        }
2522        #[cfg(debug_assertions)]
2523        {
2524            if !ri64::<MIN, MAX>::contains(self.val) {
2525                return Err(ri64::<MIN, MAX>::error(what, self.val));
2526            }
2527            Ok(ri64 {
2528                val: self.val,
2529                min: self.min.clamp(MIN as i64, MAX as i64),
2530                max: self.max.clamp(MIN as i64, MAX as i64),
2531            })
2532        }
2533    }
2534}
2535
2536#[cfg(test)]
2537mod tests {
2538    // use super::*;
2539
2540    // What follows below are some tests I wrote for my attempt at implementing
2541    // Ada-style modular/cyclic arithmetic on ranged integers. I found it to
2542    // be incredibly challenging. I decided that I could make do with only
2543    // using wrapping arithmetic on primitive-ranged integers and gave up.
2544    //
2545    // I did briefly look at GNAT to see if it could be of help, but I found
2546    // the source overwhelming and didn't find anything. I also could find any
2547    // help on the broader web for how to implement this correctly.
2548    //
2549    // Probably the next step here is to sit down with a pen & paper and work
2550    // out how this should be done, assuming we need/want it. One thing I ran
2551    // into was doing modular arithmetic when the range was bigger than the
2552    // underlying primitive representation. I could see how to do it if we
2553    // allowed casting up to a bigger integer representation, but I really
2554    // wanted to avoid doing that.
2555    /*
2556    type PrimitiveInt = ri8<{ i8::MIN as i128 }, { i8::MAX as i128 }>;
2557    type SmallInt = ri8<-20, 20>;
2558    type AlmostPrimitiveInt =
2559        ri8<{ i8::MIN as i128 }, { (i8::MAX - 1) as i128 }>;
2560
2561    #[test]
2562    fn wrapping_add_small() {
2563        let int = |n| SmallInt::new(n).unwrap();
2564
2565        assert_eq!(int(15).wrapping_add(int(5)), 20);
2566        assert_eq!(int(15).wrapping_add(int(6)), -20);
2567        assert_eq!(int(15).wrapping_add(int(-6)), 9);
2568        assert_eq!(int(-5).wrapping_add(int(5)), 0);
2569        assert_eq!(int(-5).wrapping_add(int(6)), 1);
2570        assert_eq!(int(-5).wrapping_add(int(3)), -2);
2571        assert_eq!(int(-5).wrapping_add(int(-3)), -8);
2572        assert_eq!(int(-5).wrapping_add(int(-13)), -18);
2573        assert_eq!(int(-5).wrapping_add(int(-15)), -20);
2574        assert_eq!(int(-5).wrapping_add(int(-16)), 20);
2575
2576        // These tests get SmallInts that are out-of-bounds (which is legal as
2577        // an intermediate value) and then try to do wrapping arithmetic on
2578        // them.
2579        let a: SmallInt = PrimitiveInt::new(127).unwrap();
2580        assert_eq!(a.wrapping_add(int(1)), 5);
2581        let a: SmallInt = PrimitiveInt::new(-128).unwrap();
2582        assert_eq!(a.wrapping_add(int(-1)), -6);
2583
2584        let a: SmallInt = PrimitiveInt::new(127).unwrap();
2585        let b: SmallInt = PrimitiveInt::new(127).unwrap();
2586        assert_eq!(a.wrapping_add(b), 8);
2587
2588        let a: SmallInt = PrimitiveInt::new(-128).unwrap();
2589        let b: SmallInt = PrimitiveInt::new(-128).unwrap();
2590        assert_eq!(a.wrapping_add(b), -10);
2591
2592        let a: SmallInt = PrimitiveInt::new(127).unwrap();
2593        let b: SmallInt = PrimitiveInt::new(-128).unwrap();
2594        assert_eq!(a.wrapping_add(b), -1);
2595
2596        let a: SmallInt = PrimitiveInt::new(-128).unwrap();
2597        let b: SmallInt = PrimitiveInt::new(127).unwrap();
2598        assert_eq!(a.wrapping_add(b), -1);
2599    }
2600
2601    #[test]
2602    fn wrapping_add_almost_primitive() {
2603        let int = |n| AlmostPrimitiveInt::new(n).unwrap();
2604
2605        assert_eq!(int(126).wrapping_add(int(126)), 0);
2606    }
2607
2608    quickcheck::quickcheck! {
2609        fn prop_wrapping_add_always_in_bounds(
2610            n1: SmallInt,
2611            n2: SmallInt
2612        ) -> bool {
2613            let sum = n1.wrapping_add(n2).get();
2614            SmallInt::contains(sum)
2615        }
2616
2617        fn prop_wrapping_add_always_in_bounds_primitive(
2618            n1: PrimitiveInt,
2619            n2: PrimitiveInt
2620        ) -> bool {
2621            let sum = n1.wrapping_add(n2).get();
2622            PrimitiveInt::contains(sum)
2623        }
2624    }
2625    */
2626}