1#![cfg_attr(not(feature = "std"), no_std)]
2#![allow(clippy::comparison_chain)]
3
4#[cfg(all(not(feature = "std"), any(test, feature = "alloc")))]
5#[cfg_attr(test, macro_use)]
6extern crate alloc;
7
8use core::{
9 fmt, ops,
10 str::{self, FromStr},
11};
12
13use crate::fr::Fr;
14
15use ark_ff::{
16 fields::{Field, Fp256, PrimeField},
17 BigInteger, BigInteger256,
18};
19use crypto_bigint::{CheckedAdd, CheckedMul, NonZero, Zero, U256};
20
21mod fr;
22
23const U256_BYTE_COUNT: usize = 32;
24
25#[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash)]
26pub struct FieldElement {
27 inner: Fr,
28}
29
30mod from_str_error {
31
32 #[derive(Debug)]
33 pub enum FromStrError {
34 InvalidCharacter,
35 OutOfRange,
36 }
37
38 #[cfg(feature = "std")]
39 impl std::error::Error for FromStrError {}
40
41 impl core::fmt::Display for FromStrError {
42 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
43 match self {
44 Self::InvalidCharacter => write!(f, "invalid character"),
45 Self::OutOfRange => write!(f, "number out of range"),
46 }
47 }
48 }
49}
50pub use from_str_error::FromStrError;
51
52mod from_bytes_slice_error {
53
54 #[derive(Debug)]
55 pub enum FromByteSliceError {
56 InvalidLength,
57 OutOfRange,
58 }
59
60 #[cfg(feature = "std")]
61 impl std::error::Error for FromByteSliceError {}
62
63 impl core::fmt::Display for FromByteSliceError {
64 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
65 match self {
66 Self::InvalidLength => write!(f, "invalid length"),
67 Self::OutOfRange => write!(f, "number out of range"),
68 }
69 }
70 }
71}
72pub use from_bytes_slice_error::FromByteSliceError;
73
74mod from_byte_array_error {
75 #[derive(Debug)]
76 pub struct FromByteArrayError;
77
78 #[cfg(feature = "std")]
79 impl std::error::Error for FromByteArrayError {}
80
81 impl core::fmt::Display for FromByteArrayError {
82 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
83 write!(f, "number out of range")
84 }
85 }
86}
87pub use from_byte_array_error::FromByteArrayError;
88
89mod value_out_of_range_error {
90 #[derive(Debug)]
91 pub struct ValueOutOfRangeError;
92
93 #[cfg(feature = "std")]
94 impl std::error::Error for ValueOutOfRangeError {}
95
96 impl core::fmt::Display for ValueOutOfRangeError {
97 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
98 write!(f, "field element value out of range")
99 }
100 }
101}
102pub use value_out_of_range_error::ValueOutOfRangeError;
103
104struct InnerDebug<'a>(pub &'a FieldElement);
105
106impl FieldElement {
107 pub const ZERO: FieldElement = FieldElement::from_mont([0, 0, 0, 0]);
109
110 pub const ONE: FieldElement = FieldElement::from_mont([
112 18446744073709551585,
113 18446744073709551615,
114 18446744073709551615,
115 576460752303422960,
116 ]);
117
118 pub const TWO: FieldElement = FieldElement::from_mont([
120 18446744073709551553,
121 18446744073709551615,
122 18446744073709551615,
123 576460752303422416,
124 ]);
125
126 pub const THREE: FieldElement = FieldElement::from_mont([
128 18446744073709551521,
129 18446744073709551615,
130 18446744073709551615,
131 576460752303421872,
132 ]);
133
134 pub const MAX: FieldElement = FieldElement::from_mont([32, 0, 0, 544]);
136
137 pub const fn from_mont(data: [u64; 4]) -> Self {
139 Self {
140 inner: Fp256::new_unchecked(BigInteger256::new(data)),
141 }
142 }
143
144 pub fn from_dec_str(value: &str) -> Result<Self, FromStrError> {
145 let mut res = U256::ZERO;
149 for b in value.bytes().map(|b| b.wrapping_sub(b'0')) {
150 if b > 9 {
151 return Err(FromStrError::InvalidCharacter);
152 }
153 let r = {
154 let product = res.checked_mul(&U256::from_u8(10));
155 if product.is_some().into() {
156 product.unwrap()
157 } else {
158 return Err(FromStrError::OutOfRange);
159 }
160 };
161 let r = {
162 let sum = r.checked_add(&U256::from_u8(b));
163 if sum.is_some().into() {
164 sum.unwrap()
165 } else {
166 return Err(FromStrError::OutOfRange);
167 }
168 };
169 res = r;
170 }
171
172 Fr::from_bigint(u256_to_biginteger256(&res))
173 .map(|inner| Self { inner })
174 .ok_or(FromStrError::OutOfRange)
175 }
176
177 pub fn from_hex_be(value: &str) -> Result<Self, FromStrError> {
178 let value = value.trim_start_matches("0x");
179
180 let hex_chars_len = value.len();
181 let expected_hex_length = U256_BYTE_COUNT * 2;
182
183 let parsed_bytes: [u8; U256_BYTE_COUNT] = if hex_chars_len == expected_hex_length {
184 let mut buffer = [0u8; U256_BYTE_COUNT];
185 hex::decode_to_slice(value, &mut buffer).map_err(|_| FromStrError::InvalidCharacter)?;
186 buffer
187 } else if hex_chars_len < expected_hex_length {
188 let mut padded_hex = str::repeat("0", expected_hex_length - hex_chars_len);
189 padded_hex.push_str(value);
190
191 let mut buffer = [0u8; U256_BYTE_COUNT];
192 hex::decode_to_slice(&padded_hex, &mut buffer)
193 .map_err(|_| FromStrError::InvalidCharacter)?;
194 buffer
195 } else {
196 return Err(FromStrError::OutOfRange);
197 };
198
199 match Self::from_bytes_be(&parsed_bytes) {
200 Ok(value) => Ok(value),
201 Err(_) => Err(FromStrError::OutOfRange),
202 }
203 }
204
205 pub fn from_bytes_be(bytes: &[u8; 32]) -> Result<Self, FromByteArrayError> {
213 Self::from_byte_slice(bytes).ok_or(FromByteArrayError)
214 }
215
216 pub fn from_byte_slice_be(bytes: &[u8]) -> Result<Self, FromByteSliceError> {
218 if bytes.len() > U256_BYTE_COUNT {
219 Err(FromByteSliceError::InvalidLength)
220 } else {
221 let mut buffer = [0u8; U256_BYTE_COUNT];
222 buffer[(U256_BYTE_COUNT - bytes.len())..].copy_from_slice(bytes);
223 Self::from_byte_slice(&buffer).ok_or(FromByteSliceError::OutOfRange)
224 }
225 }
226
227 #[cfg(feature = "bigdecimal")]
229 pub fn to_big_decimal<D: Into<i64>>(&self, decimals: D) -> bigdecimal::BigDecimal {
230 use num_bigint::{BigInt, Sign};
231
232 bigdecimal::BigDecimal::new(
233 BigInt::from_bytes_be(Sign::Plus, &self.to_bytes_be()),
234 decimals.into(),
235 )
236 }
237
238 pub fn to_bits_le(self) -> [bool; 256] {
240 let mut bits = [false; 256];
241 for (ind_element, element) in self.inner.into_bigint().0.iter().enumerate() {
242 for ind_bit in 0..64 {
243 bits[ind_element * 64 + ind_bit] = (element >> ind_bit) & 1 == 1;
244 }
245 }
246
247 bits
248 }
249
250 pub fn to_bytes_be(&self) -> [u8; 32] {
252 let mut buffer = [0u8; 32];
253 buffer.copy_from_slice(&self.inner.into_bigint().to_bytes_be());
254
255 buffer
256 }
257
258 pub const fn into_mont(self) -> [u64; 4] {
260 self.inner.0 .0
261 }
262
263 pub fn invert(&self) -> Option<FieldElement> {
264 self.inner.inverse().map(|inner| Self { inner })
265 }
266
267 pub fn sqrt(&self) -> Option<FieldElement> {
268 self.inner.sqrt().map(|inner| Self { inner })
269 }
270
271 pub fn double(&self) -> FieldElement {
272 *self + *self
273 }
274
275 pub fn floor_div(&self, rhs: FieldElement) -> FieldElement {
278 let lhs: U256 = self.into();
279 let rhs: U256 = (&rhs).into();
280 let is_rhs_zero: bool = rhs.is_zero().into();
281
282 if !is_rhs_zero {
283 let rhs = NonZero::from_uint(rhs);
284
285 let div_result = lhs.div_rem(&rhs);
286 let (quotient, _) = div_result;
287
288 FieldElement {
290 inner: Fr::from_bigint(u256_to_biginteger256("ient)).unwrap(),
291 }
292 } else {
293 panic!("division by zero");
295 }
296 }
297
298 fn from_byte_slice(bytes: &[u8]) -> Option<Self> {
300 let mut bits = [false; U256_BYTE_COUNT * 8];
301 for (ind_byte, byte) in bytes.iter().enumerate() {
302 for ind_bit in 0..8 {
303 bits[ind_byte * 8 + ind_bit] = (byte >> (7 - ind_bit)) & 1 == 1;
304 }
305 }
306
307 let big_int = BigInteger256::from_bits_be(&bits);
309 Fr::from_bigint(big_int).map(|inner| Self { inner })
310 }
311}
312
313impl Default for FieldElement {
314 fn default() -> Self {
315 Self::ZERO
316 }
317}
318
319impl AsRef<FieldElement> for FieldElement {
320 fn as_ref(&self) -> &FieldElement {
321 self
322 }
323}
324
325impl ops::Add<FieldElement> for FieldElement {
326 type Output = FieldElement;
327
328 fn add(self, rhs: FieldElement) -> Self::Output {
329 FieldElement {
330 inner: self.inner + rhs.inner,
331 }
332 }
333}
334
335impl ops::AddAssign<FieldElement> for FieldElement {
336 fn add_assign(&mut self, rhs: FieldElement) {
337 self.inner = self.inner + rhs.inner;
338 }
339}
340
341impl ops::Sub<FieldElement> for FieldElement {
342 type Output = FieldElement;
343
344 fn sub(self, rhs: FieldElement) -> Self::Output {
345 FieldElement {
346 inner: self.inner - rhs.inner,
347 }
348 }
349}
350
351impl ops::SubAssign<FieldElement> for FieldElement {
352 fn sub_assign(&mut self, rhs: FieldElement) {
353 self.inner = self.inner - rhs.inner;
354 }
355}
356
357impl ops::Mul<FieldElement> for FieldElement {
358 type Output = FieldElement;
359
360 fn mul(self, rhs: FieldElement) -> Self::Output {
361 FieldElement {
362 inner: self.inner * rhs.inner,
363 }
364 }
365}
366
367impl ops::MulAssign<FieldElement> for FieldElement {
368 fn mul_assign(&mut self, rhs: FieldElement) {
369 self.inner = self.inner * rhs.inner;
370 }
371}
372
373impl ops::Neg for FieldElement {
374 type Output = FieldElement;
375
376 fn neg(self) -> Self::Output {
377 FieldElement { inner: -self.inner }
378 }
379}
380
381impl ops::Rem<FieldElement> for FieldElement {
382 type Output = FieldElement;
383
384 fn rem(self, rhs: FieldElement) -> Self::Output {
385 if self.inner < rhs.inner {
386 return self;
387 }
388
389 let lhs: U256 = (&self).into();
390 let rhs: U256 = (&rhs).into();
391 let is_rhs_zero: bool = rhs.is_zero().into();
392
393 if !is_rhs_zero {
394 let rhs = NonZero::from_uint(rhs);
395
396 let (_, rem) = lhs.div_rem(&rhs);
397
398 FieldElement {
400 inner: Fr::from_bigint(u256_to_biginteger256(&rem)).unwrap(),
401 }
402 } else {
403 panic!("division by zero");
405 }
406 }
407}
408
409impl ops::BitAnd<FieldElement> for FieldElement {
410 type Output = FieldElement;
411
412 fn bitand(self, rhs: FieldElement) -> Self::Output {
413 let lhs: U256 = (&self).into();
414 let rhs: U256 = (&rhs).into();
415
416 FieldElement {
418 inner: Fr::from_bigint(u256_to_biginteger256(&(lhs & rhs))).unwrap(),
419 }
420 }
421}
422
423impl ops::BitOr<FieldElement> for FieldElement {
424 type Output = FieldElement;
425
426 fn bitor(self, rhs: FieldElement) -> Self::Output {
427 let lhs: U256 = (&self).into();
428 let rhs: U256 = (&rhs).into();
429
430 FieldElement {
432 inner: Fr::from_bigint(u256_to_biginteger256(&(lhs | rhs))).unwrap(),
433 }
434 }
435}
436
437impl core::iter::Sum for FieldElement {
438 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
439 let mut sum = Self::ZERO;
440 iter.for_each(|item| {
441 sum += item;
442 });
443 sum
444 }
445}
446
447impl<'a> core::iter::Sum<&'a FieldElement> for FieldElement {
448 fn sum<I: Iterator<Item = &'a FieldElement>>(iter: I) -> Self {
449 iter.copied().sum()
450 }
451}
452
453impl fmt::Debug for FieldElement {
454 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
455 f.debug_struct("FieldElement")
456 .field("inner", &InnerDebug(self))
457 .finish()
458 }
459}
460
461impl fmt::Display for FieldElement {
462 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
463 let repr: U256 = self.into();
467
468 if repr.is_zero().into() {
469 return write!(f, "0");
470 }
471
472 let mut buf = [0u8; 4 * 20];
473 let mut i = buf.len() - 1;
474 let mut current = repr;
475 let ten = U256::from_u8(10u8);
476
477 loop {
478 let digit = if current < ten {
479 current.to_words()[0] as u8
480 } else {
481 (current.checked_rem(&ten)).unwrap().to_words()[0] as u8
482 };
483 buf[i] = digit + b'0';
484 current = current.checked_div(&ten).unwrap();
485 if current.is_zero().into() {
486 break;
487 }
488 i -= 1;
489 }
490
491 let s = unsafe { str::from_utf8_unchecked(&buf[i..]) };
493 f.pad_integral(true, "", s)
494 }
495}
496
497impl fmt::LowerHex for FieldElement {
498 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
499 let repr: U256 = self.into();
500
501 let width = if f.sign_aware_zero_pad() {
502 f.width().unwrap().min(64)
503 } else {
504 1
505 };
506 if f.alternate() {
507 write!(f, "0x")?;
508 }
509 let mut latch = false;
510 let mut ind_nibble = 0;
511 for ch in u256_to_u64_array(&repr).iter().rev() {
512 for x in 0..16 {
513 let nibble = (ch & (15u64 << ((15 - x) * 4) as u64)) >> (((15 - x) * 4) as u64);
514 if !latch {
515 latch = nibble != 0 || (64 - ind_nibble <= width);
516 }
517 if latch {
518 write!(f, "{nibble:x}")?;
519 }
520 ind_nibble += 1;
521 }
522 }
523 Ok(())
524 }
525}
526
527impl fmt::UpperHex for FieldElement {
528 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
529 let repr: U256 = self.into();
530
531 let width = if f.sign_aware_zero_pad() {
532 f.width().unwrap().min(64)
533 } else {
534 1
535 };
536 if f.alternate() {
537 write!(f, "0x")?;
538 }
539 let mut latch = false;
540 let mut ind_nibble = 0;
541 for ch in u256_to_u64_array(&repr).iter().rev() {
542 for x in 0..16 {
543 let nibble = (ch & (15u64 << ((15 - x) * 4) as u64)) >> (((15 - x) * 4) as u64);
544 if !latch {
545 latch = nibble != 0 || (64 - ind_nibble <= width);
546 }
547 if latch {
548 write!(f, "{nibble:X}")?;
549 }
550 ind_nibble += 1;
551 }
552 }
553 Ok(())
554 }
555}
556
557#[cfg(feature = "serde")]
558mod serde_field_element {
559 #[cfg(feature = "std")]
560 use core::fmt::{Formatter, Result as FmtResult};
561
562 use super::*;
563 #[cfg(not(feature = "std"))]
564 use alloc::{
565 fmt::{Formatter, Result as FmtResult},
566 string::ToString,
567 };
568 use serde::{de::Visitor, Deserialize, Serialize};
569
570 struct FieldElementVisitor;
571
572 impl Serialize for FieldElement {
573 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
574 where
575 S: serde::Serializer,
576 {
577 serializer.serialize_str(&ToString::to_string(&self))
578 }
579 }
580
581 impl<'de> Deserialize<'de> for FieldElement {
582 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
583 where
584 D: serde::Deserializer<'de>,
585 {
586 deserializer.deserialize_str(FieldElementVisitor)
587 }
588 }
589
590 impl<'de> Visitor<'de> for FieldElementVisitor {
591 type Value = FieldElement;
592
593 fn expecting(&self, formatter: &mut Formatter) -> FmtResult {
594 write!(formatter, "string")
595 }
596
597 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
598 where
599 E: serde::de::Error,
600 {
601 FieldElement::from_str(v).map_err(serde::de::Error::custom)
602 }
603 }
604}
605
606impl From<u8> for FieldElement {
607 fn from(value: u8) -> Self {
608 Self {
609 inner: Fr::from_bigint(BigInteger256::new([value as u64, 0, 0, 0])).unwrap(),
610 }
611 }
612}
613
614impl From<u16> for FieldElement {
615 fn from(value: u16) -> Self {
616 Self {
617 inner: Fr::from_bigint(BigInteger256::new([value as u64, 0, 0, 0])).unwrap(),
618 }
619 }
620}
621
622impl From<u32> for FieldElement {
623 fn from(value: u32) -> Self {
624 Self {
625 inner: Fr::from_bigint(BigInteger256::new([value as u64, 0, 0, 0])).unwrap(),
626 }
627 }
628}
629
630impl From<u64> for FieldElement {
631 fn from(value: u64) -> Self {
632 Self {
633 inner: Fr::from_bigint(BigInteger256::new([value, 0, 0, 0])).unwrap(),
634 }
635 }
636}
637
638impl From<u128> for FieldElement {
639 fn from(value: u128) -> Self {
640 let low = value % (u64::MAX as u128 + 1);
641 let high = value / (u64::MAX as u128 + 1);
642
643 Self {
644 inner: Fr::from_bigint(BigInteger256::new([low as u64, high as u64, 0, 0])).unwrap(),
645 }
646 }
647}
648
649impl From<usize> for FieldElement {
650 fn from(value: usize) -> Self {
651 Self {
652 inner: Fr::from_bigint(BigInteger256::new([value as u64, 0, 0, 0])).unwrap(),
653 }
654 }
655}
656
657impl FromStr for FieldElement {
658 type Err = FromStrError;
659
660 fn from_str(s: &str) -> Result<Self, Self::Err> {
661 if s.starts_with("0x") {
662 FieldElement::from_hex_be(s)
663 } else {
664 FieldElement::from_dec_str(s)
665 }
666 }
667}
668
669impl TryFrom<FieldElement> for u8 {
670 type Error = ValueOutOfRangeError;
671
672 fn try_from(value: FieldElement) -> Result<Self, Self::Error> {
673 let repr = value.inner.into_bigint().0;
674 if repr[0] > u8::MAX as u64 || repr[1] > 0 || repr[2] > 0 || repr[3] > 0 {
675 Err(ValueOutOfRangeError)
676 } else {
677 Ok(repr[0] as u8)
678 }
679 }
680}
681
682impl TryFrom<FieldElement> for u16 {
683 type Error = ValueOutOfRangeError;
684
685 fn try_from(value: FieldElement) -> Result<Self, Self::Error> {
686 let repr = value.inner.into_bigint().0;
687 if repr[0] > u16::MAX as u64 || repr[1] > 0 || repr[2] > 0 || repr[3] > 0 {
688 Err(ValueOutOfRangeError)
689 } else {
690 Ok(repr[0] as u16)
691 }
692 }
693}
694
695impl TryFrom<FieldElement> for u32 {
696 type Error = ValueOutOfRangeError;
697
698 fn try_from(value: FieldElement) -> Result<Self, Self::Error> {
699 let repr = value.inner.into_bigint().0;
700 if repr[0] > u32::MAX as u64 || repr[1] > 0 || repr[2] > 0 || repr[3] > 0 {
701 Err(ValueOutOfRangeError)
702 } else {
703 Ok(repr[0] as u32)
704 }
705 }
706}
707
708impl TryFrom<FieldElement> for u64 {
709 type Error = ValueOutOfRangeError;
710
711 fn try_from(value: FieldElement) -> Result<Self, Self::Error> {
712 let repr = value.inner.into_bigint().0;
713 if repr[1] > 0 || repr[2] > 0 || repr[3] > 0 {
714 Err(ValueOutOfRangeError)
715 } else {
716 Ok(repr[0])
717 }
718 }
719}
720
721impl TryFrom<FieldElement> for u128 {
722 type Error = ValueOutOfRangeError;
723
724 fn try_from(value: FieldElement) -> Result<Self, Self::Error> {
725 let repr = value.inner.into_bigint().0;
726 if repr[2] > 0 || repr[3] > 0 {
727 Err(ValueOutOfRangeError)
728 } else {
729 Ok((repr[0] as u128) + (repr[1] as u128) * (u64::MAX as u128 + 1))
730 }
731 }
732}
733
734impl From<&FieldElement> for U256 {
735 #[cfg(target_pointer_width = "64")]
736 fn from(value: &FieldElement) -> Self {
737 U256::from_words(value.inner.into_bigint().0)
738 }
739
740 #[cfg(target_pointer_width = "32")]
741 fn from(value: &FieldElement) -> Self {
742 U256::from_words(unsafe {
743 core::mem::transmute::<[u64; 4], [u32; 8]>(value.inner.into_bigint().0)
744 })
745 }
746}
747
748impl<'a> fmt::Debug for InnerDebug<'a> {
749 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
750 write!(f, "{:#064x}", self.0)
751 }
752}
753
754#[inline]
755fn u256_to_biginteger256(num: &U256) -> BigInteger256 {
756 BigInteger256::new(u256_to_u64_array(num))
757}
758
759#[cfg(target_pointer_width = "64")]
760#[inline]
761fn u256_to_u64_array(num: &U256) -> [u64; 4] {
762 num.to_words()
763}
764
765#[cfg(target_pointer_width = "32")]
766#[inline]
767fn u256_to_u64_array(num: &U256) -> [u64; 4] {
768 unsafe { core::mem::transmute::<[u32; 8], [u64; 4]>(num.to_words()) }
769}
770
771#[cfg(test)]
772mod tests {
773 use super::*;
774
775 #[test]
776 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
777 fn test_default_value() {
778 assert_eq!(FieldElement::default(), FieldElement::ZERO)
779 }
780
781 #[test]
782 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
783 fn test_dec_fmt() {
784 let nums = [
785 "0",
786 "1",
787 "10",
788 "11",
789 "3618502788666131213697322783095070105623107215331596699973092056135872020480",
790 ];
791
792 for num in nums.iter() {
793 assert_eq!(
794 &format!("{}", FieldElement::from_dec_str(num).unwrap()),
795 num
796 );
797 }
798 }
799
800 #[test]
801 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
802 fn test_zero_padded_hex_fmt() {
803 let fe = FieldElement::from_hex_be("0x1234abcd").unwrap();
804
805 assert_eq!(format!("{fe:011x}"), "0001234abcd");
806 assert_eq!(format!("{fe:011X}"), "0001234ABCD");
807 assert_eq!(format!("{fe:08x}"), "1234abcd");
808 assert_eq!(format!("{fe:06x}"), "1234abcd");
809 assert_eq!(format!("{fe:#x}"), "0x1234abcd");
810 assert_eq!(
811 format!("{fe:#064x}"),
812 "0x000000000000000000000000000000000000000000000000000000001234abcd"
813 );
814
815 assert_eq!(
817 format!("{fe:#0100x}"),
818 "0x000000000000000000000000000000000000000000000000000000001234abcd"
819 );
820 }
821
822 #[test]
823 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
824 fn test_addition() {
825 let additions = [
826 ["1", "1", "2"],
827 [
828 "3618502788666131213697322783095070105623107215331596699973092056135872020480",
829 "1",
830 "0",
831 ],
832 ];
833
834 for item in additions.iter() {
835 let mut lhs = FieldElement::from_dec_str(item[0]).unwrap();
836 let rhs = FieldElement::from_dec_str(item[1]).unwrap();
837 let result = FieldElement::from_dec_str(item[2]).unwrap();
838 assert_eq!(lhs + rhs, result);
839
840 lhs += rhs;
841 assert_eq!(lhs, result);
842 }
843 }
844
845 #[test]
846 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
847 fn test_subtraction() {
848 let subtractions = [
849 ["10", "7", "3"],
850 [
851 "0",
852 "3618502788666131213697322783095070105623107215331596699973092056135872020480",
853 "1",
854 ],
855 ];
856
857 for item in subtractions.iter() {
858 let mut lhs = FieldElement::from_dec_str(item[0]).unwrap();
859 let rhs = FieldElement::from_dec_str(item[1]).unwrap();
860 let result = FieldElement::from_dec_str(item[2]).unwrap();
861 assert_eq!(lhs - rhs, result);
862
863 lhs -= rhs;
864 assert_eq!(lhs, result);
865 }
866 }
867
868 #[test]
869 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
870 fn test_multiplication() {
871 let multiplications = [
872 ["2", "3", "6"],
873 [
874 "3618502788666131213697322783095070105623107215331596699973092056135872020480",
875 "3618502788666131213697322783095070105623107215331596699973092056135872020480",
876 "1",
877 ],
878 [
879 "3141592653589793238462643383279502884197169399375105820974944592307",
880 "8164062862089986280348253421170679821480865132823066470938446095505",
881 "514834056922159274131066670130609582664841480950767778400381816737396274242",
882 ],
883 ];
884
885 for item in multiplications.iter() {
886 let mut lhs = FieldElement::from_dec_str(item[0]).unwrap();
887 let rhs = FieldElement::from_dec_str(item[1]).unwrap();
888 let result = FieldElement::from_dec_str(item[2]).unwrap();
889 assert_eq!(lhs * rhs, result);
890
891 lhs *= rhs;
892 assert_eq!(lhs, result);
893 }
894 }
895
896 #[test]
897 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
898 fn test_remainder() {
899 let remainders = [["123456", "100", "56"], ["7", "3", "1"], ["3", "6", "3"]];
900
901 for item in remainders.iter() {
902 assert_eq!(
903 FieldElement::from_dec_str(item[0]).unwrap()
904 % FieldElement::from_dec_str(item[1]).unwrap(),
905 FieldElement::from_dec_str(item[2]).unwrap()
906 );
907 }
908 }
909
910 #[test]
911 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
912 fn test_bitwise_and() {
913 let operands = [[123456_u64, 567890], [613221132151, 4523451]];
914
915 for item in operands.iter() {
916 let lhs: FieldElement = item[0].into();
917 let rhs: FieldElement = item[1].into();
918 assert_eq!(lhs & rhs, (item[0] & item[1]).into());
919 }
920 }
921
922 #[test]
923 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
924 fn test_bitwise_or() {
925 let operands = [[123456_u64, 567890], [613221132151, 4523451]];
926
927 for item in operands.iter() {
928 let lhs: FieldElement = item[0].into();
929 let rhs: FieldElement = item[1].into();
930 assert_eq!(lhs | rhs, (item[0] | item[1]).into());
931 }
932 }
933
934 #[test]
935 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
936 fn test_iter_sum() {
937 let elements = [FieldElement::ONE, FieldElement::TWO, FieldElement::THREE];
938
939 assert_eq!(
940 elements.iter().sum::<FieldElement>(),
941 FieldElement::from_dec_str("6").unwrap()
942 );
943 assert_eq!(
944 elements.into_iter().sum::<FieldElement>(),
945 FieldElement::from_dec_str("6").unwrap()
946 );
947 }
948
949 #[test]
950 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
951 fn test_floor_division() {
952 let quotients = [["123456", "100", "1234"], ["7", "3", "2"], ["3", "6", "0"]];
953
954 for item in quotients.iter() {
955 assert_eq!(
956 FieldElement::from_dec_str(item[0])
957 .unwrap()
958 .floor_div(FieldElement::from_dec_str(item[1]).unwrap()),
959 FieldElement::from_dec_str(item[2]).unwrap()
960 );
961 }
962 }
963
964 #[test]
965 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
966 fn test_to_primitives() {
967 let fe_256: FieldElement = 256u16.into();
968
969 if u8::try_from(fe_256).is_ok() {
970 panic!("invalid conversion");
971 }
972
973 assert_eq!(u16::try_from(fe_256).unwrap(), 256u16);
974 assert_eq!(u32::try_from(fe_256).unwrap(), 256u32);
975 assert_eq!(u64::try_from(fe_256).unwrap(), 256u64);
976 }
977
978 #[test]
979 #[cfg(feature = "bigdecimal")]
980 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
981 fn test_to_big_decimal() {
982 use bigdecimal::{BigDecimal, Num};
983
984 let nums = [
985 (
986 "134500",
987 5,
988 BigDecimal::from_str_radix("1.345", 10).unwrap(),
989 ),
990 (
991 "134500",
992 0,
993 BigDecimal::from_str_radix("134500", 10).unwrap(),
994 ),
995 (
996 "134500",
997 10,
998 BigDecimal::from_str_radix("0.00001345", 10).unwrap(),
999 ),
1000 ];
1001
1002 for num in nums.into_iter() {
1003 assert_eq!(
1004 FieldElement::from_dec_str(num.0)
1005 .unwrap()
1006 .to_big_decimal(num.1),
1007 num.2
1008 );
1009 }
1010 }
1011
1012 #[test]
1013 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
1014 fn test_from_str() {
1015 let nums = [
1016 ("134500", "0x20d64"),
1017 ("9999999999999999", "0x2386f26fc0ffff"),
1018 ];
1019
1020 for num in nums.into_iter() {
1021 assert_eq!(
1022 num.0.parse::<FieldElement>().unwrap(),
1023 num.1.parse::<FieldElement>().unwrap(),
1024 );
1025 }
1026 }
1027
1028 #[test]
1029 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
1030 fn test_from_byte_slice_be() {
1031 let nums = [("25800", [100u8, 200u8])];
1032
1033 for num in nums.into_iter() {
1034 assert_eq!(
1035 num.0.parse::<FieldElement>().unwrap(),
1036 FieldElement::from_byte_slice_be(&num.1).unwrap()
1037 );
1038 }
1039 }
1040
1041 #[test]
1042 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
1043 fn test_u8_conversion() {
1044 let nums = [u8::MAX, u8::MAX / 3 * 2, u8::MAX / 3];
1045
1046 for num in nums.into_iter() {
1047 let felt: FieldElement = num.into();
1048 assert_eq!(format!("{}", felt), format!("{}", num));
1049
1050 let back_to_num: u8 = felt.try_into().unwrap();
1051 assert_eq!(num, back_to_num);
1052 }
1053 }
1054
1055 #[test]
1056 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
1057 fn test_u16_conversion() {
1058 let nums = [u16::MAX, u16::MAX / 3 * 2, u16::MAX / 3];
1059
1060 for num in nums.into_iter() {
1061 let felt: FieldElement = num.into();
1062 assert_eq!(format!("{}", felt), format!("{}", num));
1063
1064 let back_to_num: u16 = felt.try_into().unwrap();
1065 assert_eq!(num, back_to_num);
1066 }
1067 }
1068
1069 #[test]
1070 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
1071 fn test_u32_conversion() {
1072 let nums = [u32::MAX, u32::MAX / 3 * 2, u32::MAX / 3];
1073
1074 for num in nums.into_iter() {
1075 let felt: FieldElement = num.into();
1076 assert_eq!(format!("{}", felt), format!("{}", num));
1077
1078 let back_to_num: u32 = felt.try_into().unwrap();
1079 assert_eq!(num, back_to_num);
1080 }
1081 }
1082
1083 #[test]
1084 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
1085 fn test_u64_conversion() {
1086 let nums = [u64::MAX, u64::MAX / 3 * 2, u64::MAX / 3];
1087
1088 for num in nums.into_iter() {
1089 let felt: FieldElement = num.into();
1090 assert_eq!(format!("{}", felt), format!("{}", num));
1091
1092 let back_to_num: u64 = felt.try_into().unwrap();
1093 assert_eq!(num, back_to_num);
1094 }
1095 }
1096
1097 #[test]
1098 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
1099 fn test_u128_conversion() {
1100 let nums = [u128::MAX, u128::MAX / 3 * 2, u128::MAX / 3];
1101
1102 for num in nums.into_iter() {
1103 let felt: FieldElement = num.into();
1104 assert_eq!(format!("{}", felt), format!("{}", num));
1105
1106 let back_to_num: u128 = felt.try_into().unwrap();
1107 assert_eq!(num, back_to_num);
1108 }
1109 }
1110}