rug/rational/mini.rs
1// Copyright © 2016–2025 Trevor Spiteri
2
3// This program is free software: you can redistribute it and/or modify it under
4// the terms of the GNU Lesser General Public License as published by the Free
5// Software Foundation, either version 3 of the License, or (at your option) any
6// later version.
7//
8// This program is distributed in the hope that it will be useful, but WITHOUT
9// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
11// details.
12//
13// You should have received a copy of the GNU Lesser General Public License and
14// a copy of the GNU General Public License along with this program. If not, see
15// <https://www.gnu.org/licenses/>.
16
17use crate::ext::xmpq;
18use crate::integer::{MiniInteger, ToMini};
19use crate::misc;
20use crate::rational::BorrowRational;
21use crate::{Assign, Rational};
22use az::Cast;
23use core::ffi::c_int;
24use core::fmt::{
25 Binary, Debug, Display, Formatter, LowerHex, Octal, Result as FmtResult, UpperHex,
26};
27use core::mem;
28use core::mem::MaybeUninit;
29#[allow(unused_imports)]
30use core::ops::Deref;
31use core::ptr::NonNull;
32use gmp_mpfr_sys::gmp;
33use gmp_mpfr_sys::gmp::{limb_t, mpq_t, mpz_t};
34
35const LIMBS_IN_SMALL: usize = (128 / gmp::LIMB_BITS) as usize;
36type Limbs = [MaybeUninit<limb_t>; LIMBS_IN_SMALL];
37
38/**
39A small rational number that does not require any memory allocation.
40
41This can be useful when you have a numerator and denominator that are primitive
42integer-types such as [`i64`] or [`u8`], and you need a reference to a
43[`Rational`].
44
45Although no allocation is required, setting the value of a `MiniRational` does
46require some computation, as the numerator and denominator need to be
47canonicalized.
48
49The [`borrow`][Self::borrow] method returns an object that can be coerced to a
50[`Rational`], as it implements
51<code>[Deref]\<[Target][Deref::Target] = [Rational]></code>.
52
53# Examples
54
55```rust
56use rug::rational::MiniRational;
57use rug::Rational;
58// `a` requires a heap allocation
59let mut a = Rational::from((100, 13));
60// `b` can reside on the stack
61let b = MiniRational::from((-100, 21));
62a /= &*b.borrow();
63assert_eq!(*a.numer(), -21);
64assert_eq!(*a.denom(), 13);
65```
66*/
67#[derive(Clone, Copy)]
68pub struct MiniRational {
69 inner: mpq_t,
70 // numerator is first in limbs if inner.num.d <= inner.den.d
71 first_limbs: Limbs,
72 last_limbs: Limbs,
73}
74
75static_assert!(mem::size_of::<Limbs>() == 16);
76
77// SAFETY: mpq_t is thread safe as guaranteed by the GMP library.
78unsafe impl Send for MiniRational {}
79unsafe impl Sync for MiniRational {}
80
81impl Default for MiniRational {
82 #[inline]
83 fn default() -> Self {
84 MiniRational::new()
85 }
86}
87
88impl Display for MiniRational {
89 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
90 Display::fmt(&*self.borrow(), f)
91 }
92}
93
94impl Debug for MiniRational {
95 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
96 Debug::fmt(&*self.borrow(), f)
97 }
98}
99
100impl Binary for MiniRational {
101 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
102 Binary::fmt(&*self.borrow(), f)
103 }
104}
105
106impl Octal for MiniRational {
107 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
108 Octal::fmt(&*self.borrow(), f)
109 }
110}
111
112impl LowerHex for MiniRational {
113 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
114 LowerHex::fmt(&*self.borrow(), f)
115 }
116}
117
118impl UpperHex for MiniRational {
119 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
120 UpperHex::fmt(&*self.borrow(), f)
121 }
122}
123
124impl MiniRational {
125 /// Creates a [`MiniRational`] with value 0.
126 ///
127 /// # Examples
128 ///
129 /// ```rust
130 /// use rug::rational::MiniRational;
131 /// let r = MiniRational::new();
132 /// let b = r.borrow();
133 /// // Use b as if it were Rational.
134 /// assert_eq!(*b.numer(), 0);
135 /// assert_eq!(*b.denom(), 1);
136 /// ```
137 #[inline]
138 pub const fn new() -> Self {
139 let d = NonNull::dangling();
140 MiniRational {
141 inner: mpq_t {
142 num: mpz_t {
143 alloc: LIMBS_IN_SMALL as c_int,
144 size: 0,
145 d,
146 },
147 den: mpz_t {
148 alloc: LIMBS_IN_SMALL as c_int,
149 size: 1,
150 d,
151 },
152 },
153 first_limbs: small_limbs![],
154 last_limbs: small_limbs![1],
155 }
156 }
157
158 /// Creates a [`MiniRational`] from a [`MiniInteger`].
159 ///
160 /// This is equivalent to `MiniRational::from(val)`, but can also be used in
161 /// constant context. Unless required in constant context, use the [`From`]
162 /// trait instead.
163 ///
164 /// # Planned deprecation
165 ///
166 /// This method will be deprecated when the [`From`] trait is usable in
167 /// constant context.
168 ///
169 /// # Examples
170 ///
171 /// ```rust
172 /// use rug::integer::MiniInteger;
173 /// use rug::rational::{BorrowRational, MiniRational};
174 /// use rug::Rational;
175 ///
176 /// const TWO_INT: MiniInteger = MiniInteger::const_from_i8(2i8);
177 /// const TWO_MINI: MiniRational = MiniRational::const_from_integer(TWO_INT);
178 /// const TWO_BORROW: BorrowRational = TWO_MINI.borrow();
179 /// const TWO: &Rational = BorrowRational::const_deref(&TWO_BORROW);
180 /// assert_eq!(*TWO, 2);
181 ///
182 /// const HALF_BORROW: BorrowRational = TWO.as_recip();
183 /// const HALF: &Rational = BorrowRational::const_deref(&HALF_BORROW);
184 /// assert_eq!(*HALF, MiniRational::from((1, 2)));
185 /// ```
186 #[inline]
187 pub const fn const_from_integer(val: MiniInteger) -> Self {
188 let MiniInteger {
189 inner: mut num_inner,
190 limbs: num_limbs,
191 } = val;
192 let MiniInteger {
193 inner: mut den_inner,
194 limbs: den_limbs,
195 } = MiniInteger::const_from_u8(1);
196 let d = NonNull::dangling();
197 // remove d pointer relation
198 num_inner.d = d;
199 den_inner.d = d;
200 MiniRational {
201 inner: mpq_t {
202 num: num_inner,
203 den: den_inner,
204 },
205 first_limbs: num_limbs,
206 last_limbs: den_limbs,
207 }
208 }
209
210 /// Returns a mutable reference to a [`Rational`] number for simple
211 /// operations that do not need to allocate more space for the numerator or
212 /// denominator.
213 ///
214 /// # Safety
215 ///
216 /// It is undefined behavior to perform operations that reallocate the
217 /// internal data of the referenced [`Rational`] number or to swap it with
218 /// another number, although it is allowed to swap the numerator and
219 /// denominator allocations, such as in the reciprocal operation
220 /// [`recip_mut`].
221 ///
222 /// Some GMP functions swap the allocations of their target operands;
223 /// calling such functions with the mutable reference returned by this
224 /// method can lead to undefined behavior.
225 ///
226 /// # Examples
227 ///
228 /// ```rust
229 /// use rug::rational::MiniRational;
230 /// let mut r = MiniRational::from((-15i32, 47i32));
231 /// let (num_capacity, den_capacity) = {
232 /// let b = r.borrow();
233 /// (b.numer().capacity(), b.denom().capacity())
234 /// };
235 /// // reciprocating this will not require reallocations
236 /// unsafe {
237 /// r.as_nonreallocating_rational().recip_mut();
238 /// }
239 /// let after = r.borrow();
240 /// assert_eq!(*after, MiniRational::from((-47, 15)));
241 /// assert_eq!(after.numer().capacity(), num_capacity);
242 /// assert_eq!(after.denom().capacity(), den_capacity);
243 /// ```
244 ///
245 /// [`recip_mut`]: `Rational::recip_mut`
246 #[inline]
247 pub unsafe fn as_nonreallocating_rational(&mut self) -> &mut Rational {
248 // Update num.d and den.d to point to limbs.
249 let first = NonNull::<[MaybeUninit<limb_t>]>::from(&self.first_limbs[..]).cast();
250 let last = NonNull::<[MaybeUninit<limb_t>]>::from(&self.last_limbs[..]).cast();
251 let (num_d, den_d) = if self.num_is_first() {
252 (first, last)
253 } else {
254 (last, first)
255 };
256 self.inner.num.d = num_d;
257 self.inner.den.d = den_d;
258 let ptr = misc::cast_ptr_mut(&mut self.inner);
259 // SAFETY: since inner.num.d and inner.den.d point to the limbs, it is
260 // in a consistent state.
261 unsafe { &mut *ptr }
262 }
263
264 /// Borrows the rational number.
265 ///
266 /// The returned object implements
267 /// <code>[Deref]\<[Target][Deref::Target] = [Rational]></code>.
268 ///
269 /// The borrow lasts until the returned object exits scope. Multiple borrows
270 /// can be taken at the same time.
271 ///
272 /// # Examples
273 ///
274 /// ```rust
275 /// use rug::rational::MiniRational;
276 /// use rug::Rational;
277 /// let r = MiniRational::from((-13i32, 5i32));
278 /// let b = r.borrow();
279 /// let abs_ref = Rational::from(b.abs_ref());
280 /// assert_eq!(*abs_ref.numer(), 13);
281 /// assert_eq!(*abs_ref.denom(), 5);
282 /// ```
283 #[inline]
284 pub const fn borrow(&self) -> BorrowRational<'_> {
285 let first_d: *const Limbs = &self.first_limbs;
286 let last_d: *const Limbs = &self.last_limbs;
287 let (num_d, den_d) = if self.num_is_first() {
288 (first_d, last_d)
289 } else {
290 (last_d, first_d)
291 };
292 // SAFETY: Since num_d and den_d point to the limbs, the mpq_t is in a
293 // consistent state. Also, the lifetime of the BorrowRational is the
294 // lifetime of self, which covers the limbs.
295 unsafe {
296 BorrowRational::from_raw(mpq_t {
297 num: mpz_t {
298 alloc: self.inner.num.alloc,
299 size: self.inner.num.size,
300 d: NonNull::new_unchecked(num_d.cast_mut().cast()),
301 },
302 den: mpz_t {
303 alloc: self.inner.den.alloc,
304 size: self.inner.den.size,
305 d: NonNull::new_unchecked(den_d.cast_mut().cast()),
306 },
307 })
308 }
309 }
310
311 /// Borrows the rational number exclusively.
312 ///
313 /// This is similar to the [`borrow`][Self::borrow] method, but it requires
314 /// exclusive access to the underlying [`MiniRational`]; the returned
315 /// reference can however be shared. The exclusive access is required to
316 /// reduce the amount of housekeeping necessary, providing a more efficient
317 /// operation.
318 ///
319 /// # Examples
320 ///
321 /// ```rust
322 /// use rug::rational::MiniRational;
323 /// use rug::Rational;
324 /// let mut r = MiniRational::from((-13i32, 5i32));
325 /// let b = r.borrow_excl();
326 /// let abs_ref = Rational::from(b.abs_ref());
327 /// assert_eq!(*abs_ref.numer(), 13);
328 /// assert_eq!(*abs_ref.denom(), 5);
329 /// ```
330 #[inline]
331 pub fn borrow_excl(&mut self) -> &Rational {
332 // SAFETY: since the return is a const reference, there will be no reallocation
333 unsafe { &*self.as_nonreallocating_rational() }
334 }
335
336 /// Creates a [`MiniRational`] from a numerator and denominator, assuming
337 /// they are in canonical form.
338 ///
339 /// # Safety
340 ///
341 /// This method leads to undefined behavior if `den` is zero or if `num` and
342 /// `den` have common factors.
343 ///
344 /// # Examples
345 ///
346 /// ```rust
347 /// use rug::rational::MiniRational;
348 /// let from_unsafe = unsafe { MiniRational::from_canonical(-13, 10) };
349 /// // from_safe is canonicalized to the same form as from_unsafe
350 /// let from_safe = MiniRational::from((130, -100));
351 /// let unsafe_borrow = from_unsafe.borrow();
352 /// let safe_borrow = from_safe.borrow();
353 /// assert_eq!(unsafe_borrow.numer(), safe_borrow.numer());
354 /// assert_eq!(unsafe_borrow.denom(), safe_borrow.denom());
355 /// ```
356 pub unsafe fn from_canonical<Num: ToMini, Den: ToMini>(num: Num, den: Den) -> Self {
357 let mut num_size = 0;
358 let mut den_size = 0;
359 let mut num_limbs: Limbs = small_limbs![];
360 let mut den_limbs: Limbs = small_limbs![];
361 num.copy(&mut num_size, &mut num_limbs);
362 den.copy(&mut den_size, &mut den_limbs);
363 // since inner.num.d == inner.den.d, first_limbs are num_limbs
364 let d = NonNull::dangling();
365 MiniRational {
366 inner: mpq_t {
367 num: mpz_t {
368 alloc: LIMBS_IN_SMALL.cast(),
369 size: num_size,
370 d,
371 },
372 den: mpz_t {
373 alloc: LIMBS_IN_SMALL.cast(),
374 size: den_size,
375 d,
376 },
377 },
378 first_limbs: num_limbs,
379 last_limbs: den_limbs,
380 }
381 }
382
383 /// Assigns a numerator and denominator to a [`MiniRational`], assuming
384 /// they are in canonical form.
385 ///
386 /// # Safety
387 ///
388 /// This method leads to undefined behavior if `den` is zero or negative, or
389 /// if `num` and `den` have common factors.
390 ///
391 /// # Examples
392 ///
393 /// ```rust
394 /// use rug::rational::MiniRational;
395 /// use rug::Assign;
396 /// let mut a = MiniRational::new();
397 /// unsafe {
398 /// a.assign_canonical(-13, 10);
399 /// }
400 /// // b is canonicalized to the same form as a
401 /// let mut b = MiniRational::new();
402 /// b.assign((130, -100));
403 /// let a_borrow = a.borrow();
404 /// let b_borrow = b.borrow();
405 /// assert_eq!(a_borrow.numer(), b_borrow.numer());
406 /// assert_eq!(a_borrow.denom(), b_borrow.denom());
407 /// ```
408 pub unsafe fn assign_canonical<Num: ToMini, Den: ToMini>(&mut self, num: Num, den: Den) {
409 // make num is first
410 self.inner.den.d = self.inner.num.d;
411 num.copy(&mut self.inner.num.size, &mut self.first_limbs);
412 den.copy(&mut self.inner.den.size, &mut self.last_limbs);
413 }
414
415 #[inline]
416 const fn num_is_first(&self) -> bool {
417 // SAFETY: num.d and den.d were created either from the same dangling
418 // pointer, or from fields in the same struct
419 let num_ptr = self.inner.num.d.as_ptr();
420 let den_ptr = self.inner.den.d.as_ptr();
421 unsafe { num_ptr.offset_from(den_ptr) <= 0 }
422 }
423}
424
425impl Assign<MiniInteger> for MiniRational {
426 #[inline]
427 fn assign(&mut self, src: MiniInteger) {
428 // make num is first
429 self.inner.den.d = self.inner.num.d;
430 self.inner.num.size = src.inner.size;
431 self.first_limbs = src.limbs;
432 self.inner.den.size = 1;
433 self.last_limbs[0] = MaybeUninit::new(1);
434 }
435}
436
437impl From<MiniInteger> for MiniRational {
438 #[inline]
439 fn from(src: MiniInteger) -> Self {
440 MiniRational::const_from_integer(src)
441 }
442}
443
444impl<Num: ToMini> Assign<Num> for MiniRational {
445 #[inline]
446 fn assign(&mut self, src: Num) {
447 // make num is first
448 self.inner.den.d = self.inner.num.d;
449 src.copy(&mut self.inner.num.size, &mut self.first_limbs);
450 self.inner.den.size = 1;
451 self.last_limbs[0] = MaybeUninit::new(1);
452 }
453}
454
455impl<Num: ToMini> From<Num> for MiniRational {
456 fn from(src: Num) -> Self {
457 let mut num_size = 0;
458 let mut num_limbs = small_limbs![];
459 src.copy(&mut num_size, &mut num_limbs);
460 // since inner.num.d == inner.den.d, first_limbs are num_limbs
461 let d = NonNull::dangling();
462 MiniRational {
463 inner: mpq_t {
464 num: mpz_t {
465 alloc: LIMBS_IN_SMALL.cast(),
466 size: num_size,
467 d,
468 },
469 den: mpz_t {
470 alloc: LIMBS_IN_SMALL.cast(),
471 size: 1,
472 d,
473 },
474 },
475 first_limbs: num_limbs,
476 last_limbs: small_limbs![1],
477 }
478 }
479}
480
481impl<Num: ToMini, Den: ToMini> Assign<(Num, Den)> for MiniRational {
482 fn assign(&mut self, src: (Num, Den)) {
483 assert!(!src.1.is_zero(), "division by zero");
484 // make num is first
485 self.inner.den.d = self.inner.num.d;
486 src.0.copy(&mut self.inner.num.size, &mut self.first_limbs);
487 src.1.copy(&mut self.inner.den.size, &mut self.last_limbs);
488 // SAFETY: canonicalization will never need to make a number larger.
489 xmpq::canonicalize(unsafe { self.as_nonreallocating_rational() });
490 }
491}
492
493impl<Num: ToMini, Den: ToMini> From<(Num, Den)> for MiniRational {
494 fn from(src: (Num, Den)) -> Self {
495 assert!(!src.1.is_zero(), "division by zero");
496 let d = NonNull::dangling();
497 let mut ret = MiniRational {
498 inner: mpq_t {
499 num: mpz_t {
500 alloc: LIMBS_IN_SMALL.cast(),
501 size: 0,
502 d,
503 },
504 den: mpz_t {
505 alloc: LIMBS_IN_SMALL.cast(),
506 size: 0,
507 d,
508 },
509 },
510 first_limbs: small_limbs![],
511 last_limbs: small_limbs![],
512 };
513 src.0.copy(&mut ret.inner.num.size, &mut ret.first_limbs);
514 src.1.copy(&mut ret.inner.den.size, &mut ret.last_limbs);
515 // SAFETY: canonicalization will never need to make a number larger.
516 xmpq::canonicalize(unsafe { ret.as_nonreallocating_rational() });
517 ret
518 }
519}
520
521impl Assign<&Self> for MiniRational {
522 #[inline]
523 fn assign(&mut self, other: &Self) {
524 self.clone_from(other);
525 }
526}
527
528impl Assign for MiniRational {
529 #[inline]
530 fn assign(&mut self, other: Self) {
531 *self = other;
532 }
533}
534
535#[cfg(test)]
536mod tests {
537 use crate::integer::MiniInteger;
538 use crate::rational::MiniRational;
539 use crate::{Assign, Rational};
540
541 #[test]
542 fn check_assign() {
543 let mut r = MiniRational::from((1, 2));
544 assert_eq!(*r.borrow_excl(), MiniRational::from((1, 2)));
545 r.assign(3);
546 assert_eq!(*r.borrow_excl(), 3);
547 let other = MiniRational::from((4, 5));
548 r.assign(&other);
549 assert_eq!(*r.borrow_excl(), MiniRational::from((4, 5)));
550 r.assign((6, 7));
551 assert_eq!(*r.borrow_excl(), MiniRational::from((6, 7)));
552 r.assign(other);
553 assert_eq!(*r.borrow_excl(), MiniRational::from((4, 5)));
554 }
555
556 fn swapped_parts(small: &MiniRational) -> bool {
557 unsafe {
558 let borrow = small.borrow();
559 let num = (*borrow.numer().as_raw()).d;
560 let den = (*borrow.denom().as_raw()).d;
561 num > den
562 }
563 }
564
565 #[test]
566 fn check_swapped_parts() {
567 let mut r = MiniRational::from((2, 3));
568 assert_eq!(*r.borrow_excl(), MiniRational::from((2, 3)));
569 assert_eq!(*r.clone().borrow_excl(), r);
570 let mut orig_swapped_parts = swapped_parts(&r);
571 unsafe {
572 r.as_nonreallocating_rational().recip_mut();
573 }
574 assert_eq!(*r.borrow_excl(), MiniRational::from((3, 2)));
575 assert_eq!(*r.clone().borrow_excl(), r);
576 assert!(swapped_parts(&r) != orig_swapped_parts);
577
578 unsafe {
579 r.assign_canonical(5, 7);
580 }
581 assert_eq!(*r.borrow_excl(), MiniRational::from((5, 7)));
582 assert_eq!(*r.clone().borrow_excl(), r);
583 orig_swapped_parts = swapped_parts(&r);
584 unsafe {
585 r.as_nonreallocating_rational().recip_mut();
586 }
587 assert_eq!(*r.borrow_excl(), MiniRational::from((7, 5)));
588 assert_eq!(*r.clone().borrow_excl(), r);
589 assert!(swapped_parts(&r) != orig_swapped_parts);
590
591 r.assign(2);
592 assert_eq!(*r.borrow_excl(), 2);
593 assert_eq!(*r.clone().borrow_excl(), r);
594 orig_swapped_parts = swapped_parts(&r);
595 unsafe {
596 r.as_nonreallocating_rational().recip_mut();
597 }
598 assert_eq!(*r.borrow_excl(), MiniRational::from((1, 2)));
599 assert_eq!(*r.clone().borrow_excl(), r);
600 assert!(swapped_parts(&r) != orig_swapped_parts);
601
602 r.assign((3, -5));
603 assert_eq!(*r.borrow_excl(), MiniRational::from((-3, 5)));
604 assert_eq!(*r.clone().borrow_excl(), r);
605 orig_swapped_parts = swapped_parts(&r);
606 unsafe {
607 r.as_nonreallocating_rational().recip_mut();
608 }
609 assert_eq!(*r.borrow_excl(), MiniRational::from((-5, 3)));
610 assert_eq!(*r.clone().borrow_excl(), r);
611 assert!(swapped_parts(&r) != orig_swapped_parts);
612 }
613
614 #[test]
615 fn check_traits() {
616 assert!(MiniRational::default().borrow_excl().is_zero());
617
618 let mini = MiniRational::from((14, -10));
619 let check = Rational::from((14, -10));
620 assert_eq!(format!("{mini}"), format!("{check}"));
621 assert_eq!(format!("{mini:?}"), format!("{check:?}"));
622 assert_eq!(format!("{mini:b}"), format!("{check:b}"));
623 assert_eq!(format!("{mini:o}"), format!("{check:o}"));
624 assert_eq!(format!("{mini:x}"), format!("{check:x}"));
625 assert_eq!(format!("{mini:X}"), format!("{check:X}"));
626 }
627
628 macro_rules! compare_conv {
629 ($T:ident, [$($val:expr),+] $( as $U:ident)?) => {
630 for &val in &[$($val),+] {
631 let integer = MiniInteger::from(val);
632 let a = MiniRational::from(integer);
633 let b = MiniRational::const_from_integer(integer);
634 let mut c = MiniInteger::new();
635 c.assign(integer);
636 assert_eq!(*a.borrow(), val $(as $U)?);
637 assert_eq!(*b.borrow(), val $(as $U)?);
638 assert_eq!(*c.borrow(), val $(as $U)?);
639 }
640 };
641 }
642
643 #[test]
644 fn check_equiv_convs() {
645 compare_conv!(bool, [false, true] as u8);
646 compare_conv!(i8, [i8::MIN, 0, i8::MAX]);
647 compare_conv!(i16, [i16::MIN, 0, i16::MAX]);
648 compare_conv!(i32, [i32::MIN, 0, i32::MAX]);
649 compare_conv!(i64, [i64::MIN, 0, i64::MAX]);
650 compare_conv!(i128, [i128::MIN, 0, i128::MAX]);
651 compare_conv!(isize, [isize::MIN, 0, isize::MAX]);
652 compare_conv!(u8, [0, u8::MAX]);
653 compare_conv!(u16, [0, u16::MAX]);
654 compare_conv!(u32, [0, u32::MAX]);
655 compare_conv!(u64, [0, u64::MAX]);
656 compare_conv!(u128, [0, u128::MAX]);
657 compare_conv!(usize, [0, usize::MAX]);
658 }
659}