1use crate::ParseFeltError;
2
3use crate::bigint_felt::{FeltBigInt, FIELD_HIGH, FIELD_LOW};
4use num_bigint::{BigInt, BigUint, U64Digits};
5use num_integer::Integer;
6use num_traits::{Bounded, FromPrimitive, Num, One, Pow, Signed, ToPrimitive, Zero};
7use serde::{Deserialize, Serialize};
8
9use core::{
10 convert::Into,
11 fmt,
12 iter::Sum,
13 ops::{
14 Add, AddAssign, BitAnd, BitOr, BitXor, Div, Mul, MulAssign, Neg, Rem, Shl, Shr, ShrAssign,
15 Sub, SubAssign,
16 },
17};
18
19#[cfg(all(not(feature = "std"), feature = "alloc"))]
20use alloc::{string::String, vec::Vec};
21
22#[cfg(all(feature = "arbitrary", feature = "std"))]
23use arbitrary::Arbitrary;
24
25pub(crate) trait FeltOps {
26 fn new<T: Into<FeltBigInt<FIELD_HIGH, FIELD_LOW>>>(value: T) -> Self;
27
28 fn modpow(
29 &self,
30 exponent: &FeltBigInt<FIELD_HIGH, FIELD_LOW>,
31 modulus: &FeltBigInt<FIELD_HIGH, FIELD_LOW>,
32 ) -> Self;
33
34 fn iter_u64_digits(&self) -> U64Digits;
35
36 #[cfg(any(feature = "std", feature = "alloc"))]
37 fn to_signed_bytes_le(&self) -> Vec<u8>;
38
39 #[cfg(any(feature = "std", feature = "alloc"))]
40 fn to_bytes_be(&self) -> Vec<u8>;
41
42 fn parse_bytes(buf: &[u8], radix: u32) -> Option<FeltBigInt<FIELD_HIGH, FIELD_LOW>>;
43
44 fn from_bytes_be(bytes: &[u8]) -> Self;
45
46 fn from_bytes_le(bytes: &[u8]) -> Self;
47
48 #[cfg(any(feature = "std", feature = "alloc"))]
49 fn to_str_radix(&self, radix: u32) -> String;
50
51 fn to_signed_felt(&self) -> BigInt;
52
53 fn to_bigint(&self) -> BigInt;
54
55 fn to_biguint(&self) -> BigUint;
56
57 fn bits(&self) -> u64;
58
59 fn prime() -> BigUint;
60}
61
62#[macro_export]
63macro_rules! felt_str {
64 ($val: expr) => {
65 $crate::Felt252::parse_bytes($val.as_bytes(), 10_u32).expect("Couldn't parse bytes")
66 };
67 ($val: expr, $opt: expr) => {
68 $crate::Felt252::parse_bytes($val.as_bytes(), $opt as u32).expect("Couldn't parse bytes")
69 };
70}
71
72#[cfg_attr(all(feature = "arbitrary", feature = "std"), derive(Arbitrary))]
73#[derive(Eq, Hash, PartialEq, PartialOrd, Ord, Clone, Deserialize, Default, Serialize)]
74pub struct Felt252 {
75 pub(crate) value: FeltBigInt<FIELD_HIGH, FIELD_LOW>,
76}
77
78macro_rules! from_num {
79 ($type:ty) => {
80 impl From<$type> for Felt252 {
81 fn from(value: $type) -> Self {
82 Self {
83 value: value.into(),
84 }
85 }
86 }
87 };
88}
89
90from_num!(i8);
91from_num!(i16);
92from_num!(i32);
93from_num!(i64);
94from_num!(i128);
95from_num!(isize);
96from_num!(u8);
97from_num!(u16);
98from_num!(u32);
99from_num!(u64);
100from_num!(u128);
101from_num!(usize);
102from_num!(BigInt);
103from_num!(&BigInt);
104from_num!(BigUint);
105from_num!(&BigUint);
106
107impl From<bool> for Felt252 {
108 fn from(flag: bool) -> Self {
109 if flag {
110 Self::one()
111 } else {
112 Self::zero()
113 }
114 }
115}
116
117impl Felt252 {
118 pub fn new<T: Into<Felt252>>(value: T) -> Self {
119 value.into()
120 }
121
122 #[deprecated]
123 pub fn modpow(&self, exponent: &Felt252, modulus: &Felt252) -> Self {
124 Self {
125 value: self.value.modpow(&exponent.value, &modulus.value),
126 }
127 }
128
129 pub fn iter_u64_digits(&self) -> U64Digits {
130 self.value.iter_u64_digits()
131 }
132
133 pub fn to_le_bytes(&self) -> [u8; 32] {
134 let mut res = [0u8; 32];
135 let mut iter = self.iter_u64_digits();
136 let (d0, d1, d2, d3) = (
137 iter.next().unwrap_or_default().to_le_bytes(),
138 iter.next().unwrap_or_default().to_le_bytes(),
139 iter.next().unwrap_or_default().to_le_bytes(),
140 iter.next().unwrap_or_default().to_le_bytes(),
141 );
142 res[..8].copy_from_slice(&d0);
143 res[8..16].copy_from_slice(&d1);
144 res[16..24].copy_from_slice(&d2);
145 res[24..].copy_from_slice(&d3);
146 res
147 }
148
149 pub fn to_be_bytes(&self) -> [u8; 32] {
150 let mut bytes = self.to_le_bytes();
151 bytes.reverse();
152 bytes
153 }
154
155 pub fn to_le_digits(&self) -> [u64; 4] {
156 let mut iter = self.iter_u64_digits();
157 [
158 iter.next().unwrap_or_default(),
159 iter.next().unwrap_or_default(),
160 iter.next().unwrap_or_default(),
161 iter.next().unwrap_or_default(),
162 ]
163 }
164
165 #[cfg(any(feature = "std", feature = "alloc"))]
166 #[deprecated]
167 pub fn to_signed_bytes_le(&self) -> Vec<u8> {
168 self.value.to_signed_bytes_le()
170 }
171 #[cfg(any(feature = "std", feature = "alloc"))]
172 pub fn to_bytes_be(&self) -> Vec<u8> {
173 self.value.to_bytes_be()
174 }
175
176 pub fn parse_bytes(buf: &[u8], radix: u32) -> Option<Self> {
177 Some(Self {
178 value: FeltBigInt::parse_bytes(buf, radix)?,
179 })
180 }
181 pub fn from_bytes_be(bytes: &[u8]) -> Self {
182 Self {
183 value: FeltBigInt::from_bytes_be(bytes),
184 }
185 }
186 pub fn from_bytes_le(bytes: &[u8]) -> Self {
187 Self {
188 value: FeltBigInt::from_bytes_le(bytes),
189 }
190 }
191 pub fn from_bytes_ne(bytes: &[u8]) -> Self {
192 #[cfg(target_endian = "little")]
194 let res = Self::from_bytes_le(bytes);
195 #[cfg(target_endian = "big")]
196 let res = Self::from_bytes_be(bytes);
197 res
198 }
199 #[cfg(any(feature = "std", feature = "alloc"))]
200 pub fn to_str_radix(&self, radix: u32) -> String {
201 self.value.to_str_radix(radix)
202 }
203
204 pub fn to_signed_felt(&self) -> BigInt {
219 #[allow(deprecated)]
220 self.value.to_signed_felt()
221 }
222
223 pub fn to_bigint(&self) -> BigInt {
226 #[allow(deprecated)]
227 self.value.to_bigint()
228 }
229
230 pub fn to_biguint(&self) -> BigUint {
245 #[allow(deprecated)]
246 self.value.to_biguint()
247 }
248 pub fn sqrt(&self) -> Self {
249 if self.is_zero() || self.is_one() {
252 return self.clone();
253 }
254
255 let max_felt = Felt252::max_value();
256 let trailing_prime = Felt252::max_value() >> 192; let a = self.pow(&trailing_prime);
259 let d = (&Felt252::new(3_i32)).pow(&trailing_prime);
260 let mut m = Felt252::zero();
261 let mut exponent = Felt252::one() << 191_u32;
262 let mut adm;
263 for i in 0..192_u32 {
264 adm = &a * &(&d).pow(&m);
265 adm = (&adm).pow(&exponent);
266 exponent >>= 1;
267 if adm == max_felt {
269 m += Felt252::one() << i;
270 }
271 }
272 let root_1 = self.pow(&((trailing_prime + 1_u32) >> 1)) * (&d).pow(&(m >> 1));
273 let root_2 = &max_felt - &root_1 + 1_usize;
274 if root_1 < root_2 {
275 root_1
276 } else {
277 root_2
278 }
279 }
280
281 pub fn bits(&self) -> u64 {
282 self.value.bits()
283 }
284
285 pub fn prime() -> BigUint {
286 FeltBigInt::prime()
287 }
288}
289
290impl Add for Felt252 {
291 type Output = Self;
292 fn add(self, rhs: Self) -> Self {
293 Self {
294 value: self.value + rhs.value,
295 }
296 }
297}
298
299impl<'a> Add for &'a Felt252 {
300 type Output = Felt252;
301 fn add(self, rhs: Self) -> Self::Output {
302 Self::Output {
303 value: &self.value + &rhs.value,
304 }
305 }
306}
307
308impl<'a> Add<&'a Felt252> for Felt252 {
309 type Output = Self;
310 fn add(self, rhs: &Self) -> Self::Output {
311 Self::Output {
312 value: self.value + &rhs.value,
313 }
314 }
315}
316
317impl Add<u32> for Felt252 {
318 type Output = Self;
319 fn add(self, rhs: u32) -> Self {
320 Self {
321 value: self.value + rhs,
322 }
323 }
324}
325
326impl Add<usize> for Felt252 {
327 type Output = Self;
328 fn add(self, rhs: usize) -> Self {
329 Self {
330 value: self.value + rhs,
331 }
332 }
333}
334
335impl<'a> Add<usize> for &'a Felt252 {
336 type Output = Felt252;
337 fn add(self, rhs: usize) -> Self::Output {
338 Self::Output {
339 value: &self.value + rhs,
340 }
341 }
342}
343
344impl Add<u64> for &Felt252 {
345 type Output = Felt252;
346 fn add(self, rhs: u64) -> Self::Output {
347 Self::Output {
348 value: &self.value + rhs,
349 }
350 }
351}
352
353impl Add<&Felt252> for u64 {
363 type Output = Option<u64>;
364
365 fn add(self, rhs: &Felt252) -> Option<u64> {
366 const PRIME_DIGITS_LE_HI: (u64, u64, u64) =
367 (0x0000000000000000, 0x0000000000000000, 0x0800000000000011);
368 const PRIME_MINUS_U64_MAX_DIGITS_LE_HI: (u64, u64, u64) =
369 (0xffffffffffffffff, 0xffffffffffffffff, 0x0800000000000010);
370
371 let mut rhs_digits = rhs.iter_u64_digits();
374 let Some(low) = rhs_digits.next() else {
376 return Some(self);
377 };
378 let Some(h0) = rhs_digits.next() else {
380 return self.checked_add(low)
381 };
382 let (h1, h2) = (rhs_digits.next()?, rhs_digits.next()?);
386 match (h0, h1, h2) {
387 #[allow(clippy::suspicious_arithmetic_impl)]
390 PRIME_DIGITS_LE_HI => self.checked_sub(1),
391 #[allow(clippy::suspicious_arithmetic_impl)]
402 PRIME_MINUS_U64_MAX_DIGITS_LE_HI if low >= 2 => {
403 (self).checked_sub(u64::MAX - (low - 2))
404 }
405 _ => None,
408 }
409 }
410}
411
412impl AddAssign for Felt252 {
413 fn add_assign(&mut self, rhs: Self) {
414 self.value += rhs.value;
415 }
416}
417
418impl<'a> AddAssign<&'a Felt252> for Felt252 {
419 fn add_assign(&mut self, rhs: &Self) {
420 self.value += &rhs.value;
421 }
422}
423
424impl Sum for Felt252 {
425 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
426 iter.fold(Felt252::zero(), |mut acc, x| {
427 acc += x;
428 acc
429 })
430 }
431}
432
433impl Neg for Felt252 {
434 type Output = Self;
435 fn neg(self) -> Self {
436 Self {
437 value: self.value.neg(),
438 }
439 }
440}
441
442impl<'a> Neg for &'a Felt252 {
443 type Output = Felt252;
444 fn neg(self) -> Self::Output {
445 Self::Output {
446 value: (&self.value).neg(),
447 }
448 }
449}
450
451impl Sub for Felt252 {
452 type Output = Self;
453 fn sub(self, rhs: Self) -> Self {
454 Self {
455 value: self.value - rhs.value,
456 }
457 }
458}
459
460impl<'a> Sub for &'a Felt252 {
461 type Output = Felt252;
462 fn sub(self, rhs: Self) -> Self::Output {
463 Self::Output {
464 value: &self.value - &rhs.value,
465 }
466 }
467}
468
469impl<'a> Sub<&'a Felt252> for Felt252 {
470 type Output = Self;
471 fn sub(self, rhs: &Self) -> Self {
472 Self {
473 value: self.value - &rhs.value,
474 }
475 }
476}
477
478impl Sub<&Felt252> for usize {
479 type Output = Felt252;
480 fn sub(self, rhs: &Self::Output) -> Self::Output {
481 Self::Output {
482 value: self - &rhs.value,
483 }
484 }
485}
486
487impl SubAssign for Felt252 {
488 fn sub_assign(&mut self, rhs: Self) {
489 self.value -= rhs.value
490 }
491}
492
493impl<'a> SubAssign<&'a Felt252> for Felt252 {
494 fn sub_assign(&mut self, rhs: &Self) {
495 self.value -= &rhs.value;
496 }
497}
498
499impl Sub<u32> for Felt252 {
500 type Output = Self;
501 fn sub(self, rhs: u32) -> Self {
502 Self {
503 value: self.value - rhs,
504 }
505 }
506}
507
508impl<'a> Sub<u32> for &'a Felt252 {
509 type Output = Felt252;
510 fn sub(self, rhs: u32) -> Self::Output {
511 Self::Output {
512 value: &self.value - rhs,
513 }
514 }
515}
516
517impl Sub<usize> for Felt252 {
518 type Output = Self;
519 fn sub(self, rhs: usize) -> Self {
520 Self {
521 value: self.value - rhs,
522 }
523 }
524}
525
526impl Mul for Felt252 {
527 type Output = Self;
528 fn mul(self, rhs: Self) -> Self {
529 Self {
530 value: self.value * rhs.value,
531 }
532 }
533}
534
535impl<'a> Mul for &'a Felt252 {
536 type Output = Felt252;
537 fn mul(self, rhs: Self) -> Self::Output {
538 Self::Output {
539 value: &self.value * &rhs.value,
540 }
541 }
542}
543
544impl<'a> Mul<&'a Felt252> for Felt252 {
545 type Output = Self;
546 fn mul(self, rhs: &Self) -> Self {
547 Self {
548 value: self.value * &rhs.value,
549 }
550 }
551}
552
553impl<'a> MulAssign<&'a Felt252> for Felt252 {
554 fn mul_assign(&mut self, rhs: &Self) {
555 self.value *= &rhs.value;
556 }
557}
558
559impl Pow<u32> for Felt252 {
560 type Output = Self;
561 fn pow(self, rhs: u32) -> Self {
562 Self {
563 value: self.value.pow(rhs),
564 }
565 }
566}
567
568impl<'a> Pow<u32> for &'a Felt252 {
569 type Output = Felt252;
570 fn pow(self, rhs: u32) -> Self::Output {
571 Self::Output {
572 value: (&self.value).pow(rhs),
573 }
574 }
575}
576
577impl<'a> Pow<&'a Felt252> for &'a Felt252 {
578 type Output = Felt252;
579 fn pow(self, rhs: &'a Felt252) -> Self::Output {
580 Self::Output {
581 value: (&self.value).pow(&rhs.value),
582 }
583 }
584}
585
586impl Div for Felt252 {
587 type Output = Self;
588 fn div(self, rhs: Self) -> Self {
589 Self {
590 value: self.value / rhs.value,
591 }
592 }
593}
594
595impl<'a> Div for &'a Felt252 {
596 type Output = Felt252;
597 fn div(self, rhs: Self) -> Self::Output {
598 Self::Output {
599 value: &self.value / &rhs.value,
600 }
601 }
602}
603
604impl<'a> Div<Felt252> for &'a Felt252 {
605 type Output = Felt252;
606 fn div(self, rhs: Self::Output) -> Self::Output {
607 Self::Output {
608 value: &self.value / rhs.value,
609 }
610 }
611}
612
613impl Rem for Felt252 {
614 type Output = Self;
615 fn rem(self, rhs: Self) -> Self {
616 Self {
617 value: self.value % rhs.value,
618 }
619 }
620}
621
622impl<'a> Rem<&'a Felt252> for Felt252 {
623 type Output = Self;
624 fn rem(self, rhs: &Self) -> Self {
625 Self {
626 value: self.value % &rhs.value,
627 }
628 }
629}
630
631impl Zero for Felt252 {
632 fn zero() -> Self {
633 Self {
634 value: FeltBigInt::zero(),
635 }
636 }
637
638 fn is_zero(&self) -> bool {
639 self.value.is_zero()
640 }
641}
642
643impl One for Felt252 {
644 fn one() -> Self {
645 Self {
646 value: FeltBigInt::one(),
647 }
648 }
649
650 fn is_one(&self) -> bool {
651 self.value.is_one()
652 }
653}
654
655impl Bounded for Felt252 {
656 fn min_value() -> Self {
657 Self {
658 value: FeltBigInt::min_value(),
659 }
660 }
661
662 fn max_value() -> Self {
663 Self {
664 value: FeltBigInt::max_value(),
665 }
666 }
667}
668
669impl Num for Felt252 {
670 type FromStrRadixErr = ParseFeltError;
671 fn from_str_radix(string: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
672 Ok(Self {
673 value: FeltBigInt::from_str_radix(string, radix)?,
674 })
675 }
676}
677
678impl Integer for Felt252 {
679 fn div_floor(&self, rhs: &Self) -> Self {
680 Self {
681 value: self.value.div_floor(&rhs.value),
682 }
683 }
684
685 fn div_rem(&self, other: &Self) -> (Self, Self) {
686 let (div, rem) = self.value.div_rem(&other.value);
687 (Self { value: div }, Self { value: rem })
688 }
689
690 fn divides(&self, other: &Self) -> bool {
691 self.value.divides(&other.value)
692 }
693
694 fn gcd(&self, other: &Self) -> Self {
695 Self {
696 value: self.value.gcd(&other.value),
697 }
698 }
699
700 fn is_even(&self) -> bool {
701 self.value.is_even()
702 }
703
704 fn is_multiple_of(&self, other: &Self) -> bool {
705 self.value.is_multiple_of(&other.value)
706 }
707
708 fn is_odd(&self) -> bool {
709 self.value.is_odd()
710 }
711
712 fn lcm(&self, other: &Self) -> Self {
713 Self {
714 value: self.value.lcm(&other.value),
715 }
716 }
717
718 fn mod_floor(&self, rhs: &Self) -> Self {
719 Self {
720 value: self.value.mod_floor(&rhs.value),
721 }
722 }
723}
724
725impl Signed for Felt252 {
726 fn abs(&self) -> Self {
727 Self {
728 value: self.value.abs(),
729 }
730 }
731
732 fn abs_sub(&self, other: &Self) -> Self {
733 Self {
734 value: self.value.abs_sub(&other.value),
735 }
736 }
737
738 fn signum(&self) -> Self {
739 Self {
740 value: self.value.signum(),
741 }
742 }
743
744 fn is_positive(&self) -> bool {
745 self.value.is_positive()
746 }
747
748 fn is_negative(&self) -> bool {
749 self.value.is_negative()
750 }
751}
752
753impl Shl<u32> for Felt252 {
754 type Output = Self;
755 fn shl(self, rhs: u32) -> Self {
756 Self {
757 value: self.value << rhs,
758 }
759 }
760}
761
762impl<'a> Shl<u32> for &'a Felt252 {
763 type Output = Felt252;
764 fn shl(self, rhs: u32) -> Self::Output {
765 Self::Output {
766 value: &self.value << rhs,
767 }
768 }
769}
770
771impl Shl<usize> for Felt252 {
772 type Output = Self;
773 fn shl(self, rhs: usize) -> Self {
774 Self {
775 value: self.value << rhs,
776 }
777 }
778}
779
780impl<'a> Shl<usize> for &'a Felt252 {
781 type Output = Felt252;
782 fn shl(self, rhs: usize) -> Self::Output {
783 Self::Output {
784 value: &self.value << rhs,
785 }
786 }
787}
788
789impl Shr<u32> for Felt252 {
790 type Output = Self;
791 fn shr(self, rhs: u32) -> Self {
792 Self {
793 value: self.value >> rhs,
794 }
795 }
796}
797
798impl<'a> Shr<u32> for &'a Felt252 {
799 type Output = Felt252;
800 fn shr(self, rhs: u32) -> Self::Output {
801 Self::Output {
802 value: &self.value >> rhs,
803 }
804 }
805}
806
807impl ShrAssign<usize> for Felt252 {
808 fn shr_assign(&mut self, rhs: usize) {
809 self.value >>= rhs
810 }
811}
812
813impl<'a> BitAnd for &'a Felt252 {
814 type Output = Felt252;
815 fn bitand(self, rhs: Self) -> Self::Output {
816 Self::Output {
817 value: &self.value & &rhs.value,
818 }
819 }
820}
821
822impl<'a> BitAnd<&'a Felt252> for Felt252 {
823 type Output = Self;
824 fn bitand(self, rhs: &Self) -> Self {
825 Self {
826 value: self.value & &rhs.value,
827 }
828 }
829}
830
831impl<'a> BitAnd<Felt252> for &'a Felt252 {
832 type Output = Felt252;
833 fn bitand(self, rhs: Self::Output) -> Self::Output {
834 Self::Output {
835 value: &self.value & rhs.value,
836 }
837 }
838}
839
840impl<'a> BitOr for &'a Felt252 {
841 type Output = Felt252;
842 fn bitor(self, rhs: Self) -> Self::Output {
843 Self::Output {
844 value: &self.value | &rhs.value,
845 }
846 }
847}
848
849impl<'a> BitXor for &'a Felt252 {
850 type Output = Felt252;
851 fn bitxor(self, rhs: Self) -> Self::Output {
852 Self::Output {
853 value: &self.value ^ &rhs.value,
854 }
855 }
856}
857
858impl ToPrimitive for Felt252 {
859 fn to_u128(&self) -> Option<u128> {
860 self.value.to_u128()
861 }
862
863 fn to_u64(&self) -> Option<u64> {
864 self.value.to_u64()
865 }
866
867 fn to_i64(&self) -> Option<i64> {
868 self.value.to_i64()
869 }
870}
871
872impl FromPrimitive for Felt252 {
873 fn from_u64(n: u64) -> Option<Self> {
874 FeltBigInt::from_u64(n).map(|n| Self { value: n })
875 }
876
877 fn from_i64(n: i64) -> Option<Self> {
878 FeltBigInt::from_i64(n).map(|n| Self { value: n })
879 }
880}
881
882impl fmt::Display for Felt252 {
883 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
884 write!(f, "{}", self.value)
885 }
886}
887
888impl fmt::Debug for Felt252 {
889 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
890 write!(f, "{}", self.value)
891 }
892}
893
894macro_rules! assert_felt_methods {
895 ($type:ty) => {
896 const _: () = {
897 fn assert_felt_ops<T: FeltOps>() {}
898 fn assertion() {
899 assert_felt_ops::<$type>();
900 }
901 };
902 };
903}
904
905macro_rules! assert_felt_impl {
906 ($type:ty) => {
907 const _: () = {
908 fn assert_add<T: Add>() {}
909 fn assert_add_ref<'a, T: Add<&'a $type>>() {}
910 fn assert_add_u32<T: Add<u32>>() {}
911 fn assert_add_usize<T: Add<usize>>() {}
912 fn assert_add_assign<T: AddAssign>() {}
913 fn assert_add_assign_ref<'a, T: AddAssign<&'a $type>>() {}
914 fn assert_sum<T: Sum<$type>>() {}
915 fn assert_neg<T: Neg>() {}
916 fn assert_sub<T: Sub>() {}
917 fn assert_sub_ref<'a, T: Sub<&'a $type>>() {}
918 fn assert_sub_assign<T: SubAssign>() {}
919 fn assert_sub_assign_ref<'a, T: SubAssign<&'a $type>>() {}
920 fn assert_sub_u32<T: Sub<u32>>() {}
921 fn assert_sub_usize<T: Sub<usize>>() {}
922 fn assert_mul<T: Mul>() {}
923 fn assert_mul_ref<'a, T: Mul<&'a $type>>() {}
924 fn assert_mul_assign_ref<'a, T: MulAssign<&'a $type>>() {}
925 fn assert_pow_u32<T: Pow<u32>>() {}
926 fn assert_pow_felt<'a, T: Pow<&'a $type>>() {}
927 fn assert_div<T: Div>() {}
928 fn assert_ref_div<T: Div<$type>>() {}
929 fn assert_rem<T: Rem>() {}
930 fn assert_rem_ref<'a, T: Rem<&'a $type>>() {}
931 fn assert_zero<T: Zero>() {}
932 fn assert_one<T: One>() {}
933 fn assert_bounded<T: Bounded>() {}
934 fn assert_num<T: Num>() {}
935 fn assert_integer<T: Integer>() {}
936 fn assert_signed<T: Signed>() {}
937 fn assert_shl_u32<T: Shl<u32>>() {}
938 fn assert_shl_usize<T: Shl<usize>>() {}
939 fn assert_shr_u32<T: Shr<u32>>() {}
940 fn assert_shr_assign_usize<T: ShrAssign<usize>>() {}
941 fn assert_bitand<T: BitAnd>() {}
942 fn assert_bitand_ref<'a, T: BitAnd<&'a $type>>() {}
943 fn assert_ref_bitand<T: BitAnd<$type>>() {}
944 fn assert_bitor<T: BitOr>() {}
945 fn assert_bitxor<T: BitXor>() {}
946 fn assert_from_primitive<T: FromPrimitive>() {}
947 fn assert_to_primitive<T: ToPrimitive>() {}
948 fn assert_display<T: fmt::Display>() {}
949 fn assert_debug<T: fmt::Debug>() {}
950
951 #[allow(dead_code)]
952 fn assert_all() {
953 assert_add::<$type>();
954 assert_add::<&$type>();
955 assert_add_ref::<$type>();
956 assert_add_u32::<$type>();
957 assert_add_usize::<$type>();
958 assert_add_usize::<&$type>();
959 assert_add_assign::<$type>();
960 assert_add_assign_ref::<$type>();
961 assert_sum::<$type>();
962 assert_neg::<$type>();
963 assert_neg::<&$type>();
964 assert_sub::<$type>();
965 assert_sub::<&$type>();
966 assert_sub_ref::<$type>();
967 assert_sub_assign::<$type>();
968 assert_sub_assign_ref::<$type>();
969 assert_sub_u32::<$type>();
970 assert_sub_u32::<&$type>();
971 assert_sub_usize::<$type>();
972 assert_mul::<$type>();
973 assert_mul::<&$type>();
974 assert_mul_ref::<$type>();
975 assert_mul_assign_ref::<$type>();
976 assert_pow_u32::<$type>();
977 assert_pow_felt::<&$type>();
978 assert_div::<$type>();
979 assert_div::<&$type>();
980 assert_ref_div::<&$type>();
981 assert_rem::<$type>();
982 assert_rem_ref::<$type>();
983 assert_zero::<$type>();
984 assert_one::<$type>();
985 assert_bounded::<$type>();
986 assert_num::<$type>();
987 assert_integer::<$type>();
988 assert_signed::<$type>();
989 assert_shl_u32::<$type>();
990 assert_shl_u32::<&$type>();
991 assert_shl_usize::<$type>();
992 assert_shl_usize::<&$type>();
993 assert_shr_u32::<$type>();
994 assert_shr_u32::<&$type>();
995 assert_shr_assign_usize::<$type>();
996 assert_bitand::<&$type>();
997 assert_bitand_ref::<$type>();
998 assert_ref_bitand::<&$type>();
999 assert_bitor::<&$type>();
1000 assert_bitxor::<&$type>();
1001 assert_from_primitive::<$type>();
1002 assert_to_primitive::<$type>();
1003 assert_display::<$type>();
1004 assert_debug::<$type>();
1005 }
1006 };
1007 };
1008}
1009
1010assert_felt_methods!(FeltBigInt<FIELD_HIGH, FIELD_LOW>);
1011assert_felt_impl!(FeltBigInt<FIELD_HIGH, FIELD_LOW>);
1012assert_felt_impl!(Felt252);
1013
1014#[cfg(test)]
1015mod test {
1016 use super::*;
1017 use crate::{arbitrary::nonzero_felt252, PRIME_STR};
1018 use core::cmp;
1019 use rstest::rstest;
1020
1021 use proptest::prelude::*;
1022
1023 proptest! {
1024 #[test]
1025 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1026 fn new_in_range(ref x in any::<[u8; 40]>()) {
1032 let x = Felt252::from_bytes_be(x);
1033 let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
1034 prop_assert!(&x.to_biguint() < p);
1035 }
1036
1037 #[test]
1038 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1039 fn from_bytes_be(high: u128, low: u128) {
1040 let expected = (Felt252::from(high) << 128_usize) + Felt252::from(low);
1041 let mut bytes = [0; 32];
1042 bytes[..16].copy_from_slice(&high.to_be_bytes());
1044 bytes[16..].copy_from_slice(&low.to_be_bytes());
1045 let got = Felt252::from_bytes_be(&bytes);
1046 prop_assert_eq!(got, expected);
1047 }
1048
1049 #[test]
1050 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1051 fn from_bytes_le(high: u128, low: u128) {
1052 let expected = (Felt252::from(high) << 128_usize) + Felt252::from(low);
1053 let mut bytes = [0; 32];
1054 bytes[..16].copy_from_slice(&low.to_le_bytes());
1056 bytes[16..].copy_from_slice(&high.to_le_bytes());
1057 let got = Felt252::from_bytes_le(&bytes);
1058 prop_assert_eq!(got, expected);
1059 }
1060
1061
1062 #[test]
1063 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1064 fn to_be_bytes(ref x in any::<Felt252>()) {
1065 let bytes = x.to_be_bytes();
1066 let y = &Felt252::from_bytes_be(&bytes);
1067 prop_assert_eq!(x, y);
1068 }
1069
1070 #[test]
1071 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1072 fn to_le_bytes(ref x in any::<Felt252>()) {
1073 let mut bytes = x.to_le_bytes();
1074 bytes.reverse();
1076 let y = &Felt252::from_bytes_be(&bytes);
1077 prop_assert_eq!(x, y);
1078 }
1079
1080 #[test]
1081 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1082 fn to_le_digits(ref x in any::<Felt252>()) {
1083 let digits: [u64; 4] = x.to_le_digits();
1084 let mut bytes: Vec<_> = digits
1085 .into_iter()
1086 .flat_map(|x| x.to_le_bytes())
1087 .collect();
1088 bytes.reverse();
1090 let y = &Felt252::from_bytes_be(&bytes);
1091 prop_assert_eq!(x, y);
1092 }
1093
1094 #[test]
1095 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1096 fn to_u128_ok(x in any::<u128>()) {
1097 let y = Felt252::from(x);
1098 let y = y.to_u128();
1099 prop_assert_eq!(Some(x), y);
1100 }
1101
1102 #[test]
1103 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1104 fn to_u128_out_of_range(x in nonzero_felt252()) {
1105 let y = x + Felt252::from(u128::MAX);
1106 let y = y.to_u128();
1107 prop_assert_eq!(None, y);
1108 }
1109
1110 #[test]
1111 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1112 fn from_bytes_be_in_range(ref x in any::<[u8; 40]>()) {
1118 let x = Felt252::from_bytes_be(x);
1119 let max_felt = Felt252::max_value();
1120 prop_assert!(x <= max_felt);
1121 }
1122
1123 #[test]
1124 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1125 fn neg_in_range(x in any::<Felt252>()) {
1128 let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
1129
1130 let neg = -x.clone();
1131 let as_uint = &neg.to_biguint();
1132 prop_assert!(as_uint < p);
1133
1134 let neg = -&x;
1136 let as_uint = &neg.to_biguint();
1137 prop_assert!(as_uint < p);
1138 }
1139
1140 #[test]
1141 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1142 fn sub(ref x in any::<Felt252>(), ref y in any::<Felt252>()) {
1146 let (x_int, y_int) = (&x.to_biguint(), &y.to_biguint());
1147 let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
1148
1149 let sub_xy = x - y;
1150 prop_assert!(&sub_xy.to_biguint() < p);
1151 prop_assert_eq!(Felt252::from(p + x_int - y_int), sub_xy);
1152
1153 let sub_yx = y - x;
1154 prop_assert!(&sub_yx.to_biguint() < p);
1155 prop_assert_eq!(Felt252::from(p + y_int - x_int), sub_yx);
1156 }
1157
1158 #[test]
1159 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1160 fn sub_assign_in_range(mut x in any::<Felt252>(), y in any::<Felt252>()) {
1164 let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
1165
1166 x -= y.clone();
1167 let as_uint = &x.to_biguint();
1168 prop_assert!(as_uint < p, "{}", as_uint);
1169
1170 x -= &y;
1172 let as_uint = &x.to_biguint();
1173 prop_assert!(as_uint < p, "{}", as_uint);
1174 }
1175
1176 #[test]
1177 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1178 fn mul(ref x in any::<Felt252>(), ref y in any::<Felt252>()) {
1183 let xy_int = x.to_biguint() * y.to_biguint();
1184
1185 let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
1186
1187 let (xy, yx) = (x * y, y * x);
1188 prop_assert_eq!(&xy, &yx);
1189 prop_assert_eq!(xy.to_biguint(), xy_int.mod_floor(p));
1190 prop_assert!(&xy.to_biguint() < p);
1191 }
1192
1193 #[test]
1194 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1195 fn mul_assign_in_range(mut x in any::<Felt252>(), y in any::<Felt252>()) {
1200 let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
1201
1202 x *= &y;
1203 let as_uint = &x.to_biguint();
1204 prop_assert!(as_uint < p, "{}", as_uint);
1205 }
1206
1207 #[test]
1208 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1209 fn div_is_mul_inv(ref x in any::<Felt252>(), ref y in nonzero_felt252()) {
1215 let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
1216 prop_assume!(!y.is_zero());
1217
1218 let q = x / y;
1219 let as_uint = &q.to_biguint();
1220 prop_assert!(as_uint < p, "{}", as_uint);
1221 prop_assert_eq!(&(q * y), x);
1222 }
1223
1224 #[test]
1225 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1226 fn shift_left_in_range(value in any::<Felt252>(), shift_amount in 0..1000_u32){
1230 let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
1231
1232 let result = (value.clone() << shift_amount).to_biguint();
1233 prop_assert!(&result < p);
1234
1235 let result = (&value << shift_amount).to_biguint();
1236 prop_assert!(&result < p);
1237 }
1238
1239 #[test]
1240 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1241 fn shift_right_in_range(value in any::<Felt252>(), shift_amount in 0..1000_u32){
1245 let result = (value >> shift_amount).to_biguint();
1246 let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
1247 prop_assert!(&result < p);
1248 }
1249
1250 #[test]
1251 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1252 fn shift_right_assign_in_range(mut value in any::<Felt252>(), shift_amount in 0..1000_usize){
1258 let p = BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
1259 value >>= shift_amount;
1260 prop_assert!(value.to_biguint() < p);
1261 }
1262
1263 #[test]
1264 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1265 fn bitand_in_range(x in any::<Felt252>(), y in any::<Felt252>()){
1269 let p = BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
1270 let result = x & &y;
1271 result.to_biguint();
1272 prop_assert!(result.to_biguint() < p);
1273 }
1274
1275 #[test]
1276 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1277 fn bitor_in_range(x in any::<Felt252>(), y in any::<Felt252>()){
1281 let p = BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
1282 let result = &x | &y;
1283 prop_assert!(result.to_biguint() < p);
1284 }
1285
1286 #[test]
1287 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1288 fn bitxor_in_range(x in any::<Felt252>(), y in any::<Felt252>()){
1292 let p = BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
1293 let result = &x ^ &y;
1294 prop_assert!(result.to_biguint() < p);
1295 }
1296
1297 #[test]
1298 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1299 fn pow_in_range(base in any::<Felt252>(), exp in 0..100_u32){
1303 let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
1304
1305 let result = Pow::pow(base.clone(), exp);
1306 let as_uint = &result.to_biguint();
1307 prop_assert!(as_uint < p, "{}", as_uint);
1308
1309 let result = Pow::pow(&base, exp);
1311 let as_uint = &result.to_biguint();
1312 prop_assert!(as_uint < p, "{}", as_uint);
1313 }
1314
1315 #[test]
1316 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1317 fn pow_felt_in_range(base in any::<Felt252>(), exponent in any::<Felt252>()){
1321 let p = BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
1322
1323 let result = Pow::pow(&base, &exponent);
1324 let as_uint = result.to_biguint();
1325 prop_assert!(as_uint < p, "{}", as_uint);
1326
1327 let result: Felt252 = Pow::pow(&base, &exponent);
1329 let as_uint = result.to_biguint();
1330 prop_assert!(as_uint < p, "{}", as_uint);
1331 }
1332
1333 #[test]
1334 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1335 fn sum_in_range(x in any::<Felt252>(), y in any::<Felt252>()){
1339 let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
1340
1341 let result = x + y;
1342 let as_uint = &result.to_biguint();
1343 prop_assert!(as_uint < p, "{}", as_uint);
1344 }
1345
1346 #[test]
1347 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1348 fn rem_in_range(x in any::<Felt252>(), y in nonzero_felt252()) {
1354 let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
1355
1356 let result = x.clone() % y.clone();
1357 let as_uint = &result.to_biguint();
1358 prop_assert!(as_uint < p, "{}", as_uint);
1359
1360 let result = x % &y;
1362 let as_uint = &result.to_biguint();
1363 prop_assert!(as_uint < p, "{}", as_uint);
1364 }
1365
1366 #[test]
1367 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1368 fn from_u64_and_to_u64_primitive(x in any::<u64>()) {
1372 let x_felt:Felt252 = Felt252::from_u64(x).unwrap();
1373 let x_u64:u64 = Felt252::to_u64(&x_felt).unwrap();
1374
1375 prop_assert_eq!(x, x_u64);
1376 }
1377
1378 #[test]
1379 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1380 fn from_i64_and_to_i64_primitive(x in any::<u32>()) {
1381 let x: i64 = x as i64;
1382 let x_felt:Felt252 = Felt252::from_i64(x).unwrap();
1383 let x_i64:i64 = Felt252::to_i64(&x_felt).unwrap();
1384 prop_assert_eq!(x, x_i64);
1385 }
1386
1387 #[test]
1388 fn lcm_doesnt_panic(x in any::<Felt252>(), y in any::<Felt252>()) {
1391 let lcm = x.lcm(&y);
1392 prop_assert!(lcm == cmp::max(x, y));
1393 }
1394
1395 #[test]
1396 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1397 fn is_multiple_of_doesnt_panic(x in any::<Felt252>(), y in any::<Felt252>()) {
1400 prop_assert!(x.is_multiple_of(&y));
1401 }
1402
1403 #[test]
1404 fn divides_doesnt_panic(x in any::<Felt252>(), y in any::<Felt252>()) {
1405 prop_assert!(x.divides(&y));
1406 }
1407
1408 #[test]
1409 fn gcd_doesnt_panic(x in any::<Felt252>(), y in any::<Felt252>()) {
1410 let gcd1 = x.gcd(&y);
1411 let gcd2 = y.gcd(&x);
1412 prop_assert_eq!(gcd1, gcd2);
1413 }
1414
1415 #[test]
1416 fn is_even(x in any::<Felt252>()) {
1417 prop_assert_eq!(x.is_even(), x.to_biguint().is_even());
1418 }
1419
1420 #[test]
1421 fn is_odd(x in any::<Felt252>()) {
1422 prop_assert_eq!(x.is_odd(), x.to_biguint().is_odd());
1423 }
1424
1425 #[test]
1432 fn zero_additive_identity(ref x in any::<Felt252>()) {
1433 let zero = Felt252::zero();
1434 prop_assert_eq!(x, &(x + &zero));
1435 prop_assert_eq!(x, &(&zero + x));
1436 }
1437
1438 #[test]
1445 fn one_multiplicative_identity(ref x in any::<Felt252>()) {
1446 let one = Felt252::one();
1447 prop_assert_eq!(x, &(x * &one));
1448 prop_assert_eq!(x, &(&one * x));
1449 }
1450
1451 #[test]
1452 fn felt_is_always_positive(x in any::<Felt252>()) {
1453 prop_assert!(x.is_positive())
1454 }
1455
1456 #[test]
1457 fn felt_is_never_negative(x in any::<Felt252>()) {
1458 prop_assert!(!x.is_negative())
1459 }
1460
1461 #[test]
1462 fn non_zero_felt_signum_is_always_one(ref x in nonzero_felt252()) {
1463 let one = Felt252::one();
1464 prop_assert_eq!(x.signum(), one)
1465 }
1466
1467 #[test]
1468 fn sub_abs(x in any::<Felt252>(), y in any::<Felt252>()) {
1469 let expected_abs_sub = if x > y {&x - &y} else {&y - &x};
1470
1471 prop_assert_eq!(x.abs_sub(&y), expected_abs_sub)
1472 }
1473
1474 #[test]
1475 fn abs(x in any::<Felt252>()) {
1476 prop_assert_eq!(&x, &x.abs())
1477 }
1478
1479 #[test]
1480 fn modpow_in_range(x in any::<Felt252>(), y in any::<Felt252>()) {
1481 let p = BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
1482
1483 let p_felt = Felt252::max_value();
1484
1485 #[allow(deprecated)]
1486 let modpow = x.modpow(&y, &p_felt).to_biguint();
1487 prop_assert!(modpow < p, "{}", modpow);
1488 }
1489
1490 #[test]
1491 fn sqrt_in_range(x in any::<Felt252>()) {
1492 let p = BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
1493
1494 let sqrt = x.sqrt().to_biguint();
1495 prop_assert!(sqrt < p, "{}", sqrt);
1496 }
1497
1498 #[test]
1499 fn sqrt_is_inv_square(x in any::<Felt252>()) {
1500 let x_sq = &x * &x;
1501 let sqrt = x_sq.sqrt();
1502
1503 if sqrt != x {
1504 prop_assert_eq!(Felt252::max_value() - sqrt + 1_usize, x);
1505 } else {
1506 prop_assert_eq!(sqrt, x);
1507 }
1508 }
1509
1510 #[test]
1511 fn add_to_u64(x in any::<u64>(), ref felt in any::<Felt252>()) {
1512 let sum = (felt + x).to_u64();
1513 prop_assert_eq!(x + felt, sum);
1514 }
1515
1516 #[test]
1517 fn add_to_u64_extremes(x in any::<u64>()) {
1518 let big_zero = &Felt252::zero();
1519 let big_max = &Felt252::max_value();
1520 let big_min = &(big_zero + (i64::MIN as usize));
1521
1522 let sum_max = (big_max + x).to_u64();
1523 prop_assert_eq!(x + big_max, sum_max);
1524 let sum_min = (big_min + x).to_u64();
1525 prop_assert_eq!(x + big_min, sum_min);
1526 let sum_zero = (big_zero + x).to_u64();
1527 prop_assert_eq!(x + big_zero, sum_zero);
1528 }
1529
1530 #[test]
1531 fn add_u32_in_range(x in any::<Felt252>(), y in any::<u32>()) {
1532 let p = BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
1533 let x_add_y = (x + y).to_biguint();
1534 prop_assert!(x_add_y < p, "{}", x_add_y);
1535 }
1536
1537 #[test]
1538 fn add_u32_is_inv_sub(x in any::<Felt252>(), y in any::<u32>()) {
1539 let expected_y = (x.clone() + y - x).to_u32().unwrap();
1540 prop_assert_eq!(expected_y, y, "{}", expected_y);
1541 }
1542
1543 #[test]
1544 fn sub_u32_in_range(x in any::<Felt252>(), y in any::<u32>()) {
1545 let p = BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
1546 let x_sub_y = (x - y).to_biguint();
1547 prop_assert!(x_sub_y < p, "{}", x_sub_y);
1548 }
1549
1550 #[test]
1551 fn sub_u32_is_inv_add(x in any::<Felt252>(), y in any::<u32>()) {
1552 prop_assert_eq!(x.clone() - y + y, x)
1553 }
1554
1555 #[test]
1556 fn sub_usize_in_range(x in any::<Felt252>(), y in any::<usize>()) {
1557 let p = BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
1558 let x_sub_y = (x - y).to_biguint();
1559 prop_assert!(x_sub_y < p, "{}", x_sub_y);
1560 }
1561
1562 #[test]
1563 fn sub_usize_is_inv_add(x in any::<Felt252>(), y in any::<usize>()) {
1564 prop_assert_eq!(x.clone() - y + y, x)
1565 }
1566
1567 #[test]
1568 fn add_in_range(x in any::<Felt252>(), y in any::<Felt252>()) {
1569 let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
1570
1571 let sub = x + y;
1572 let as_uint = &sub.to_biguint();
1573 prop_assert!(as_uint < p, "{}", as_uint);
1574 }
1575
1576 #[test]
1577 fn add_is_inv_sub(ref x in any::<Felt252>(), ref y in any::<Felt252>()) {
1578 let expected_y = x + y - x;
1579 prop_assert_eq!(&expected_y, y, "{}", y);
1580 }
1581
1582 #[test]
1583 fn add_assign_in_range(mut x in any::<Felt252>(), y in any::<Felt252>()) {
1584 let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
1585
1586 x += y.clone();
1587 let as_uint = &x.to_biguint();
1588 prop_assert!(as_uint < p, "{}", as_uint);
1589
1590 x += &y;
1592 let as_uint = &x.to_biguint();
1593 prop_assert!(as_uint < p, "{}", as_uint);
1594 }
1595 }
1596
1597 #[rstest]
1598 fn add_to_u64_edge_cases(
1599 #[values(0, 1, u64::MAX)] x: u64,
1600 #[values(-2, -1, 0, 1, 1i128.neg(), i64::MIN as i128, u64::MAX as i128, u64::MAX as i128 + 1, (u64::MAX as i128).neg())]
1601 y: i128,
1602 ) {
1603 let y = Felt252::from(y);
1604 assert_eq!(x + &y, (&y + x).to_u64());
1605 }
1606
1607 #[test]
1608 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1609 fn sum_zeros_in_range() {
1611 let x = Felt252::new(0);
1612 let y = Felt252::new(0);
1613 let z = Felt252::new(0);
1614 assert_eq!(x + y, z)
1615 }
1616
1617 #[test]
1618 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1619 fn mul_zeros_in_range() {
1621 let x = Felt252::new(0);
1622 let y = Felt252::new(0);
1623 let z = Felt252::new(0);
1624 assert_eq!(x * y, z)
1625 }
1626
1627 #[test]
1628 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1629 fn bit_and_zeros_in_range() {
1631 let x = Felt252::new(0);
1632 let y = Felt252::new(0);
1633 let z = Felt252::new(0);
1634 assert_eq!(&x & &y, z)
1635 }
1636
1637 #[test]
1638 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1639 fn bit_or_zeros_in_range() {
1641 let x = Felt252::new(0);
1642 let y = Felt252::new(0);
1643 let z = Felt252::new(0);
1644 assert_eq!(&x | &y, z)
1645 }
1646
1647 #[test]
1648 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1649 fn bit_xor_zeros_in_range() {
1651 let x = Felt252::new(0);
1652 let y = Felt252::new(0);
1653 let z = Felt252::new(0);
1654 assert_eq!(&x ^ &y, z)
1655 }
1656
1657 #[test]
1658 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1659 fn upper_bound() {
1661 let prime = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
1662 let unit = BigUint::one();
1663 let felt_max_value = Felt252::max_value().to_biguint();
1664 assert_eq!(prime - unit, felt_max_value)
1665 }
1666
1667 #[test]
1668 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1669 fn lower_bound() {
1671 let zero = BigUint::zero();
1672 let felt_min_value = Felt252::min_value().to_biguint();
1673 assert_eq!(zero, felt_min_value)
1674 }
1675
1676 #[test]
1677 fn zero_value() {
1678 let zero = BigUint::zero();
1679 let felt_zero = Felt252::zero().to_biguint();
1680 assert_eq!(zero, felt_zero)
1681 }
1682
1683 #[test]
1684 fn is_zero() {
1685 let felt_zero = Felt252::zero();
1686 let felt_non_zero = Felt252::new(3);
1687 assert!(felt_zero.is_zero());
1688 assert!(!felt_non_zero.is_zero())
1689 }
1690
1691 #[test]
1692 fn one_value() {
1693 let one = BigUint::one();
1694 let felt_one = Felt252::one().to_biguint();
1695 assert_eq!(one, felt_one)
1696 }
1697
1698 #[test]
1699 fn is_one() {
1700 let felt_one = Felt252::one();
1701 let felt_non_one = Felt252::new(8);
1702 assert!(felt_one.is_one());
1703 assert!(!felt_non_one.is_one())
1704 }
1705
1706 #[test]
1707 fn signum_of_zero_is_zero() {
1708 let zero = Felt252::zero();
1709 assert_eq!(&zero.signum(), &zero)
1710 }
1711
1712 #[test]
1713 fn from_bytes_ne() {
1714 let expected = Felt252::zero();
1715 let bytes = [0; 32];
1716 let got = Felt252::from_bytes_ne(&bytes);
1717 assert_eq!(got, expected);
1718 }
1719}