1use crate::errors::{ByteConversionError, CreationError};
2use crate::field::errors::FieldError;
3use crate::field::traits::IsField;
4use crate::traits::ByteConversion;
5use crate::unsigned_integer::element::UnsignedInteger;
6use crate::unsigned_integer::montgomery::MontgomeryAlgorithms;
7use crate::unsigned_integer::traits::IsUnsignedInteger;
8#[cfg(feature = "alloc")]
9use alloc::{
10 format,
11 string::{String, ToString},
12};
13use core::fmt;
14use core::fmt::Debug;
15use core::iter::Sum;
16#[cfg(any(
17 feature = "lambdaworks-serde-binary",
18 feature = "lambdaworks-serde-string"
19))]
20use core::marker::PhantomData;
21use core::ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, Sub};
22use num_bigint::BigUint;
23use num_traits::Num;
24#[cfg(any(
25 feature = "lambdaworks-serde-binary",
26 feature = "lambdaworks-serde-string"
27))]
28use serde::de::{self, Deserializer, MapAccess, SeqAccess, Visitor};
29#[cfg(any(
30 feature = "lambdaworks-serde-binary",
31 feature = "lambdaworks-serde-string"
32))]
33use serde::ser::{Serialize, SerializeStruct, Serializer};
34#[cfg(any(
35 feature = "lambdaworks-serde-binary",
36 feature = "lambdaworks-serde-string"
37))]
38use serde::Deserialize;
39
40use super::fields::montgomery_backed_prime_fields::{IsModulus, MontgomeryBackendPrimeField};
41use super::traits::{IsPrimeField, IsSubFieldOf, LegendreSymbol};
42
43#[allow(clippy::derived_hash_with_manual_eq)]
45#[derive(Debug, Clone, Hash, Copy)]
46pub struct FieldElement<F: IsField> {
47 value: F::BaseType,
48}
49
50#[cfg(feature = "alloc")]
51impl<F: IsField> FieldElement<F> {
52 pub fn inplace_batch_inverse(numbers: &mut [Self]) -> Result<(), FieldError> {
57 if numbers.is_empty() {
58 return Ok(());
59 }
60 let count = numbers.len();
61 let mut prod_prefix = alloc::vec::Vec::with_capacity(count);
62 prod_prefix.push(numbers[0].clone());
63 for i in 1..count {
64 prod_prefix.push(&prod_prefix[i - 1] * &numbers[i]);
65 }
66 let mut bi_inv = prod_prefix[count - 1].inv()?;
67 for i in (1..count).rev() {
68 let ai_inv = &bi_inv * &prod_prefix[i - 1];
69 bi_inv = &bi_inv * &numbers[i];
70 numbers[i] = ai_inv;
71 }
72 numbers[0] = bi_inv;
73 Ok(())
74 }
75
76 #[inline(always)]
77 pub fn to_subfield_vec<S>(self) -> alloc::vec::Vec<FieldElement<S>>
78 where
79 S: IsSubFieldOf<F>,
80 {
81 S::to_subfield_vec(self.value)
82 .into_iter()
83 .map(|x| FieldElement::from_raw(x))
84 .collect()
85 }
86}
87
88impl<F> From<&F::BaseType> for FieldElement<F>
90where
91 F::BaseType: Clone,
92 F: IsField,
93{
94 fn from(value: &F::BaseType) -> Self {
95 Self {
96 value: F::from_base_type(value.clone()),
97 }
98 }
99}
100
101impl<F> From<u64> for FieldElement<F>
103where
104 F: IsField,
105{
106 fn from(value: u64) -> Self {
107 Self {
108 value: F::from_u64(value),
109 }
110 }
111}
112
113#[cfg(feature = "alloc")]
114impl<F> TryFrom<BigUint> for FieldElement<F>
118where
119 Self: ByteConversion,
120 F: IsPrimeField,
121{
122 type Error = ByteConversionError;
123 fn try_from(value: BigUint) -> Result<Self, ByteConversionError> {
124 FieldElement::<F>::from_reduced_big_uint(&value)
125 }
126}
127
128impl<F> FieldElement<F>
129where
130 F::BaseType: Clone,
131 F: IsField,
132{
133 pub fn from_raw(value: F::BaseType) -> Self {
134 Self { value }
135 }
136
137 pub const fn const_from_raw(value: F::BaseType) -> Self {
138 Self { value }
139 }
140}
141
142impl<F> PartialEq<FieldElement<F>> for FieldElement<F>
144where
145 F: IsField,
146{
147 fn eq(&self, other: &FieldElement<F>) -> bool {
148 F::eq(&self.value, &other.value)
149 }
150}
151
152impl<F> Eq for FieldElement<F> where F: IsField {}
153
154impl<F, L> Add<&FieldElement<L>> for &FieldElement<F>
156where
157 F: IsSubFieldOf<L>,
158 L: IsField,
159{
160 type Output = FieldElement<L>;
161
162 fn add(self, rhs: &FieldElement<L>) -> Self::Output {
163 Self::Output {
164 value: <F as IsSubFieldOf<L>>::add(&self.value, &rhs.value),
165 }
166 }
167}
168
169impl<F, L> Add<FieldElement<L>> for FieldElement<F>
170where
171 F: IsSubFieldOf<L>,
172 L: IsField,
173{
174 type Output = FieldElement<L>;
175
176 fn add(self, rhs: FieldElement<L>) -> Self::Output {
177 &self + &rhs
178 }
179}
180
181impl<F, L> Add<&FieldElement<L>> for FieldElement<F>
182where
183 F: IsSubFieldOf<L>,
184 L: IsField,
185{
186 type Output = FieldElement<L>;
187
188 fn add(self, rhs: &FieldElement<L>) -> Self::Output {
189 &self + rhs
190 }
191}
192
193impl<F, L> Add<FieldElement<L>> for &FieldElement<F>
194where
195 F: IsSubFieldOf<L>,
196 L: IsField,
197{
198 type Output = FieldElement<L>;
199
200 fn add(self, rhs: FieldElement<L>) -> Self::Output {
201 self + &rhs
202 }
203}
204
205impl<F, L> AddAssign<FieldElement<F>> for FieldElement<L>
207where
208 F: IsSubFieldOf<L>,
209 L: IsField,
210{
211 fn add_assign(&mut self, rhs: FieldElement<F>) {
212 self.value = <F as IsSubFieldOf<L>>::add(&rhs.value, &self.value);
213 }
214}
215
216impl<F> Sum<FieldElement<F>> for FieldElement<F>
218where
219 F: IsField,
220{
221 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
222 iter.fold(Self::zero(), |augend, addend| augend + addend)
223 }
224}
225
226impl<F, L> Sub<&FieldElement<L>> for &FieldElement<F>
228where
229 F: IsSubFieldOf<L>,
230 L: IsField,
231{
232 type Output = FieldElement<L>;
233
234 fn sub(self, rhs: &FieldElement<L>) -> Self::Output {
235 Self::Output {
236 value: <F as IsSubFieldOf<L>>::sub(&self.value, &rhs.value),
237 }
238 }
239}
240
241impl<F, L> Sub<FieldElement<L>> for FieldElement<F>
242where
243 F: IsSubFieldOf<L>,
244 L: IsField,
245{
246 type Output = FieldElement<L>;
247
248 fn sub(self, rhs: FieldElement<L>) -> Self::Output {
249 &self - &rhs
250 }
251}
252
253impl<F, L> Sub<&FieldElement<L>> for FieldElement<F>
254where
255 F: IsSubFieldOf<L>,
256 L: IsField,
257{
258 type Output = FieldElement<L>;
259
260 fn sub(self, rhs: &FieldElement<L>) -> Self::Output {
261 &self - rhs
262 }
263}
264
265impl<F, L> Sub<FieldElement<L>> for &FieldElement<F>
266where
267 F: IsSubFieldOf<L>,
268 L: IsField,
269{
270 type Output = FieldElement<L>;
271
272 fn sub(self, rhs: FieldElement<L>) -> Self::Output {
273 self - &rhs
274 }
275}
276
277impl<F, L> Mul<&FieldElement<L>> for &FieldElement<F>
279where
280 F: IsSubFieldOf<L>,
281 L: IsField,
282{
283 type Output = FieldElement<L>;
284
285 fn mul(self, rhs: &FieldElement<L>) -> Self::Output {
286 Self::Output {
287 value: <F as IsSubFieldOf<L>>::mul(&self.value, &rhs.value),
288 }
289 }
290}
291
292impl<F, L> Mul<FieldElement<L>> for FieldElement<F>
293where
294 F: IsSubFieldOf<L>,
295 L: IsField,
296{
297 type Output = FieldElement<L>;
298
299 fn mul(self, rhs: FieldElement<L>) -> Self::Output {
300 &self * &rhs
301 }
302}
303
304impl<F, L> Mul<&FieldElement<L>> for FieldElement<F>
305where
306 F: IsSubFieldOf<L>,
307 L: IsField,
308{
309 type Output = FieldElement<L>;
310
311 fn mul(self, rhs: &FieldElement<L>) -> Self::Output {
312 &self * rhs
313 }
314}
315
316impl<F, L> Mul<FieldElement<L>> for &FieldElement<F>
317where
318 F: IsSubFieldOf<L>,
319 L: IsField,
320{
321 type Output = FieldElement<L>;
322
323 fn mul(self, rhs: FieldElement<L>) -> Self::Output {
324 self * &rhs
325 }
326}
327
328impl<F, L> MulAssign<FieldElement<F>> for FieldElement<L>
330where
331 F: IsSubFieldOf<L>,
332 L: IsField,
333{
334 fn mul_assign(&mut self, rhs: FieldElement<F>) {
335 self.value = <F as IsSubFieldOf<L>>::mul(&rhs.value, &self.value);
336 }
337}
338
339impl<F, L> MulAssign<&FieldElement<F>> for FieldElement<L>
341where
342 F: IsSubFieldOf<L>,
343 L: IsField,
344{
345 fn mul_assign(&mut self, rhs: &FieldElement<F>) {
346 self.value = <F as IsSubFieldOf<L>>::mul(&rhs.value, &self.value);
347 }
348}
349
350impl<F, L> Div<&FieldElement<L>> for &FieldElement<F>
352where
353 F: IsSubFieldOf<L>,
354 L: IsField,
355{
356 type Output = Result<FieldElement<L>, FieldError>;
357
358 fn div(self, rhs: &FieldElement<L>) -> Self::Output {
359 let value = <F as IsSubFieldOf<L>>::div(&self.value, &rhs.value)?;
360 Ok(FieldElement::<L> { value })
361 }
362}
363
364impl<F, L> Div<FieldElement<L>> for FieldElement<F>
365where
366 F: IsSubFieldOf<L>,
367 L: IsField,
368{
369 type Output = Result<FieldElement<L>, FieldError>;
370
371 fn div(self, rhs: FieldElement<L>) -> Self::Output {
372 &self / &rhs
373 }
374}
375
376impl<F, L> Div<&FieldElement<L>> for FieldElement<F>
377where
378 F: IsSubFieldOf<L>,
379 L: IsField,
380{
381 type Output = Result<FieldElement<L>, FieldError>;
382
383 fn div(self, rhs: &FieldElement<L>) -> Self::Output {
384 &self / rhs
385 }
386}
387
388impl<F, L> Div<FieldElement<L>> for &FieldElement<F>
389where
390 F: IsSubFieldOf<L>,
391 L: IsField,
392{
393 type Output = Result<FieldElement<L>, FieldError>;
394
395 fn div(self, rhs: FieldElement<L>) -> Self::Output {
396 self / &rhs
397 }
398}
399
400impl<F> Neg for &FieldElement<F>
402where
403 F: IsField,
404{
405 type Output = FieldElement<F>;
406
407 fn neg(self) -> Self::Output {
408 Self::Output {
409 value: F::neg(&self.value),
410 }
411 }
412}
413
414impl<F> Neg for FieldElement<F>
415where
416 F: IsField,
417{
418 type Output = FieldElement<F>;
419
420 fn neg(self) -> Self::Output {
421 -&self
422 }
423}
424
425impl<F> Default for FieldElement<F>
426where
427 F: IsField,
428{
429 fn default() -> Self {
430 Self { value: F::zero() }
431 }
432}
433
434impl<F> FieldElement<F>
438where
439 F: IsField,
440{
441 #[inline(always)]
443 pub fn new(value: F::BaseType) -> Self {
444 Self {
445 value: F::from_base_type(value),
446 }
447 }
448
449 #[inline(always)]
451 pub fn value(&self) -> &F::BaseType {
452 &self.value
453 }
454
455 #[inline(always)]
457 pub fn inv(&self) -> Result<Self, FieldError> {
458 let value = F::inv(&self.value)?;
459 Ok(Self { value })
460 }
461
462 #[inline(always)]
464 pub fn square(&self) -> Self {
465 Self {
466 value: F::square(&self.value),
467 }
468 }
469
470 #[inline(always)]
472 pub fn double(&self) -> Self {
473 Self {
474 value: F::double(&self.value),
475 }
476 }
477
478 #[inline(always)]
480 pub fn pow<T>(&self, exponent: T) -> Self
481 where
482 T: IsUnsignedInteger,
483 {
484 Self {
485 value: F::pow(&self.value, exponent),
486 }
487 }
488
489 #[inline(always)]
491 pub fn one() -> Self {
492 Self { value: F::one() }
493 }
494
495 #[inline(always)]
497 pub fn zero() -> Self {
498 Self { value: F::zero() }
499 }
500
501 pub fn to_raw(self) -> F::BaseType {
503 self.value
504 }
505
506 #[inline(always)]
507 pub fn to_extension<L: IsField>(self) -> FieldElement<L>
508 where
509 F: IsSubFieldOf<L>,
510 {
511 FieldElement {
512 value: <F as IsSubFieldOf<L>>::embed(self.value),
513 }
514 }
515
516 #[cfg(feature = "alloc")]
517 pub fn from_reduced_big_uint(value: &BigUint) -> Result<Self, ByteConversionError>
520 where
521 Self: ByteConversion,
522 F: IsPrimeField,
523 {
524 let mod_minus_one = F::modulus_minus_one().to_string();
525
526 let (digits, radix) = if let Some(hex) = mod_minus_one
529 .strip_prefix("0x")
530 .or_else(|| mod_minus_one.strip_prefix("0X"))
531 {
532 (hex, 16)
533 } else {
534 (mod_minus_one.as_str(), 10)
535 };
536
537 let modulus =
538 BigUint::from_str_radix(digits, radix).expect("invalid modulus representation") + 1u32;
539
540 if value >= &modulus {
541 Err(ByteConversionError::ValueNotReduced)
542 } else {
543 let mut bytes = value.to_bytes_le();
544 bytes.resize(core::mem::size_of::<F::BaseType>(), 0);
546 Self::from_bytes_le(&bytes)
547 }
548 }
549
550 #[cfg(feature = "alloc")]
551 pub fn to_big_uint(&self) -> BigUint
553 where
554 Self: ByteConversion,
555 {
556 BigUint::from_bytes_be(&self.to_bytes_be())
557 }
558
559 #[cfg(feature = "alloc")]
560 pub fn from_hex_str(hex: &str) -> Result<Self, CreationError>
563 where
564 Self: ByteConversion,
565 F: IsPrimeField,
566 {
567 let hex_str = hex.strip_prefix("0x").unwrap_or(hex);
568 if hex_str.is_empty() {
569 return Err(CreationError::EmptyString);
570 }
571
572 let value =
573 BigUint::from_str_radix(hex_str, 16).map_err(|_| CreationError::InvalidHexString)?;
574
575 Self::from_reduced_big_uint(&value).map_err(|_| CreationError::InvalidHexString)
576 }
577
578 #[cfg(feature = "alloc")]
579 pub fn to_hex_str(&self) -> String
581 where
582 Self: ByteConversion,
583 {
584 format!("0x{:02X}", self.to_big_uint())
585 }
586}
587
588impl<F: IsPrimeField> FieldElement<F> {
589 pub fn representative(&self) -> F::RepresentativeType {
591 F::representative(self.value())
592 }
593
594 pub fn sqrt(&self) -> Option<(Self, Self)> {
597 let sqrts = F::sqrt(&self.value);
598 sqrts.map(|(sqrt1, sqrt2)| (Self { value: sqrt1 }, Self { value: sqrt2 }))
599 }
600
601 pub fn legendre_symbol(&self) -> LegendreSymbol {
603 F::legendre_symbol(&self.value)
604 }
605
606 pub fn from_hex(hex_string: &str) -> Result<Self, CreationError> {
614 if hex_string.is_empty() {
615 return Err(CreationError::EmptyString);
616 }
617 let value = F::from_hex(hex_string)?;
618 Ok(Self { value })
619 }
620
621 #[cfg(feature = "std")]
622 pub fn to_hex(&self) -> String {
624 F::to_hex(&self.value)
625 }
626}
627
628#[cfg(feature = "lambdaworks-serde-binary")]
629impl<F> Serialize for FieldElement<F>
630where
631 F: IsField,
632 F::BaseType: ByteConversion,
633{
634 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
635 where
636 S: Serializer,
637 {
638 let mut state = serializer.serialize_struct("FieldElement", 1)?;
639 let data = self.value().to_bytes_be();
640 state.serialize_field("value", &data)?;
641 state.end()
642 }
643}
644
645#[cfg(all(
646 feature = "lambdaworks-serde-string",
647 not(feature = "lambdaworks-serde-binary")
648))]
649impl<F: IsPrimeField> Serialize for FieldElement<F> {
650 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
651 where
652 S: Serializer,
653 {
654 use crate::alloc::string::ToString;
655 let mut state = serializer.serialize_struct("FieldElement", 1)?;
656 state.serialize_field("value", &F::representative(self.value()).to_string())?;
657 state.end()
658 }
659}
660
661#[cfg(feature = "lambdaworks-serde-binary")]
662impl<'de, F> Deserialize<'de> for FieldElement<F>
663where
664 F: IsField,
665 F::BaseType: ByteConversion,
666{
667 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
668 where
669 D: Deserializer<'de>,
670 {
671 #[derive(Deserialize)]
672 #[serde(field_identifier, rename_all = "lowercase")]
673 enum Field {
674 Value,
675 }
676
677 struct FieldElementVisitor<F>(PhantomData<fn() -> F>);
678
679 impl<'de, F: IsField> Visitor<'de> for FieldElementVisitor<F> {
680 type Value = FieldElement<F>;
681
682 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
683 formatter.write_str("struct FieldElement")
684 }
685
686 fn visit_map<M>(self, mut map: M) -> Result<FieldElement<F>, M::Error>
687 where
688 M: MapAccess<'de>,
689 {
690 let mut value: Option<alloc::vec::Vec<u8>> = None;
691 while let Some(key) = map.next_key()? {
692 match key {
693 Field::Value => {
694 if value.is_some() {
695 return Err(de::Error::duplicate_field("value"));
696 }
697 value = Some(map.next_value()?);
698 }
699 }
700 }
701 let value = value.ok_or_else(|| de::Error::missing_field("value"))?;
702 let val = F::BaseType::from_bytes_be(&value).unwrap();
703 Ok(FieldElement::from_raw(val))
704 }
705
706 fn visit_seq<S>(self, mut seq: S) -> Result<FieldElement<F>, S::Error>
707 where
708 S: SeqAccess<'de>,
709 {
710 let mut value: Option<alloc::vec::Vec<u8>> = None;
711 while let Some(val) = seq.next_element()? {
712 if value.is_some() {
713 return Err(de::Error::duplicate_field("value"));
714 }
715 value = Some(val);
716 }
717 let value = value.ok_or_else(|| de::Error::missing_field("value"))?;
718 let val = F::BaseType::from_bytes_be(&value).unwrap();
719 Ok(FieldElement::from_raw(val))
720 }
721 }
722
723 const FIELDS: &[&str] = &["value"];
724 deserializer.deserialize_struct("FieldElement", FIELDS, FieldElementVisitor(PhantomData))
725 }
726}
727
728#[cfg(all(
729 feature = "lambdaworks-serde-string",
730 not(feature = "lambdaworks-serde-binary")
731))]
732impl<'de, F: IsPrimeField> Deserialize<'de> for FieldElement<F> {
733 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
734 where
735 D: Deserializer<'de>,
736 {
737 #[derive(Deserialize)]
738 #[serde(field_identifier, rename_all = "lowercase")]
739 enum Field {
740 Value,
741 }
742
743 struct FieldElementVisitor<F>(PhantomData<fn() -> F>);
744
745 impl<'de, F: IsPrimeField> Visitor<'de> for FieldElementVisitor<F> {
746 type Value = FieldElement<F>;
747
748 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
749 formatter.write_str("struct FieldElement")
750 }
751
752 fn visit_map<M>(self, mut map: M) -> Result<FieldElement<F>, M::Error>
753 where
754 M: MapAccess<'de>,
755 {
756 let mut value: Option<&str> = None;
757 while let Some(key) = map.next_key()? {
758 match key {
759 Field::Value => {
760 if value.is_some() {
761 return Err(de::Error::duplicate_field("value"));
762 }
763 value = Some(map.next_value()?);
764 }
765 }
766 }
767 let value = value.ok_or_else(|| de::Error::missing_field("value"))?;
768 FieldElement::from_hex(&value).map_err(|_| de::Error::custom("invalid hex"))
769 }
770
771 fn visit_seq<S>(self, mut seq: S) -> Result<FieldElement<F>, S::Error>
772 where
773 S: SeqAccess<'de>,
774 {
775 let mut value: Option<&str> = None;
776 while let Some(val) = seq.next_element()? {
777 if value.is_some() {
778 return Err(de::Error::duplicate_field("value"));
779 }
780 value = Some(val);
781 }
782 let value = value.ok_or_else(|| de::Error::missing_field("value"))?;
783 FieldElement::from_hex(&value).map_err(|_| de::Error::custom("invalid hex"))
784 }
785 }
786
787 const FIELDS: &[&str] = &["value"];
788 deserializer.deserialize_struct("FieldElement", FIELDS, FieldElementVisitor(PhantomData))
789 }
790}
791
792impl<M, const NUM_LIMBS: usize> fmt::Display
793 for FieldElement<MontgomeryBackendPrimeField<M, NUM_LIMBS>>
794where
795 M: IsModulus<UnsignedInteger<NUM_LIMBS>> + Clone + Debug,
796{
797 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
798 let value: UnsignedInteger<NUM_LIMBS> = self.representative();
799 write!(f, "{value}")
800 }
801}
802
803impl<M, const NUM_LIMBS: usize> FieldElement<MontgomeryBackendPrimeField<M, NUM_LIMBS>>
804where
805 M: IsModulus<UnsignedInteger<NUM_LIMBS>> + Clone + Debug,
806{
807 pub const fn from_hex_unchecked(hex: &str) -> Self {
811 let integer = UnsignedInteger::<NUM_LIMBS>::from_hex_unchecked(hex);
812 Self {
813 value: MontgomeryAlgorithms::cios(
814 &integer,
815 &MontgomeryBackendPrimeField::<M, NUM_LIMBS>::R2,
816 &M::MODULUS,
817 &MontgomeryBackendPrimeField::<M, NUM_LIMBS>::MU,
818 ),
819 }
820 }
821}
822
823#[cfg(test)]
824mod tests {
825 use super::*;
826 use crate::elliptic_curve::short_weierstrass::curves::bn_254::field_extension::BN254PrimeField;
827 use crate::field::fields::fft_friendly::{
828 babybear_u32::Babybear31PrimeField, stark_252_prime_field::Stark252PrimeField,
829 };
830 use crate::field::fields::montgomery_backed_prime_fields::U384PrimeField;
831 use crate::field::fields::u64_prime_field::U64PrimeField;
832 use crate::field::test_fields::u64_test_field::U64TestField;
833 #[cfg(feature = "alloc")]
834 use crate::unsigned_integer::element::UnsignedInteger;
835 use crate::unsigned_integer::element::U384;
836 #[cfg(feature = "alloc")]
837 use alloc::vec::Vec;
838 use num_bigint::BigUint;
839 #[cfg(feature = "alloc")]
840 use proptest::collection;
841 use proptest::{prelude::*, prop_compose, proptest, strategy::Strategy};
842
843 #[test]
844 fn test_std_iter_sum_field_element() {
845 let n = 164;
846 const MODULUS: u64 = 18446744069414584321;
847 assert_eq!(
848 (0..n)
849 .map(|x| { FieldElement::<U64TestField>::from(x) })
850 .sum::<FieldElement<U64TestField>>()
851 .value,
852 ((n - 1) as f64 / 2. * ((n - 1) as f64 + 1.)) as u64 % MODULUS
853 );
854 }
855
856 #[test]
857 fn test_std_iter_sum_field_element_zero_length() {
858 let n = 0;
859 assert_eq!(
860 (0..n)
861 .map(|x| { FieldElement::<U64TestField>::from(x) })
862 .sum::<FieldElement<U64TestField>>()
863 .value,
864 0
865 );
866 }
867
868 #[cfg(feature = "alloc")]
869 #[test]
870 fn test_display_montgomery_field() {
871 use alloc::format;
872
873 let zero_field_element = FieldElement::<Stark252PrimeField>::from(0);
874 assert_eq!(format!("{zero_field_element}"), "0x0");
875
876 let some_field_element =
877 FieldElement::<Stark252PrimeField>::from(&UnsignedInteger::from_limbs([
878 0x0, 0x1, 0x0, 0x1,
879 ]));
880
881 assert_eq!(
883 format!("{some_field_element}"),
884 format!("0x{}{}{}{}", "1", "0".repeat(16), "0".repeat(15), "1")
885 );
886 }
887
888 #[test]
889 fn one_of_sqrt_roots_for_4_is_2() {
890 type FrField = Stark252PrimeField;
891 type FrElement = FieldElement<FrField>;
892
893 let input = FrElement::from(4);
894 let sqrt = input.sqrt().unwrap();
895 let result = FrElement::from(2);
896 assert_eq!(sqrt.0, result);
897 }
898
899 #[test]
900 fn one_of_sqrt_roots_for_5_is_28_mod_41() {
901 let input = FieldElement::<U64PrimeField<41>>::from(5);
902 let sqrt = input.sqrt().unwrap();
903 let result = FieldElement::from(28);
904 assert_eq!(sqrt.0, result);
905 assert_eq!(sqrt.1, -result);
906 }
907
908 #[test]
909 fn one_of_sqrt_roots_for_25_is_5() {
910 type FrField = Stark252PrimeField;
911 type FrElement = FieldElement<FrField>;
912 let input = FrElement::from(25);
913 let sqrt = input.sqrt().unwrap();
914 let five = FrElement::from(5);
915 assert!(sqrt.1 == five || sqrt.0 == five);
916 }
917
918 #[test]
919 fn sqrt_works_for_prime_minus_one() {
920 type FrField = Stark252PrimeField;
921 type FrElement = FieldElement<FrField>;
922
923 let input = -FrElement::from(1);
924 let sqrt = input.sqrt().unwrap();
925 assert_eq!(sqrt.0.square(), input);
926 assert_eq!(sqrt.1.square(), input);
927 assert_ne!(sqrt.0, sqrt.1);
928 }
929
930 #[test]
931 fn one_of_sqrt_roots_for_25_is_5_in_stark_field() {
932 type FrField = Stark252PrimeField;
933 type FrElement = FieldElement<FrField>;
934
935 let input = FrElement::from(25);
936 let sqrt = input.sqrt().unwrap();
937 let result = FrElement::from(5);
938 assert_eq!(sqrt.0, result);
939 assert_eq!(sqrt.1, -result);
940 }
941
942 #[test]
943 fn sqrt_roots_for_0_are_0_in_stark_field() {
944 type FrField = Stark252PrimeField;
945 type FrElement = FieldElement<FrField>;
946
947 let input = FrElement::from(0);
948 let sqrt = input.sqrt().unwrap();
949 let result = FrElement::from(0);
950 assert_eq!(sqrt.0, result);
951 assert_eq!(sqrt.1, result);
952 }
953
954 #[test]
955 fn sqrt_of_27_for_stark_field_does_not_exist() {
956 type FrField = Stark252PrimeField;
957 type FrElement = FieldElement<FrField>;
958
959 let input = FrElement::from(27);
960 let sqrt = input.sqrt();
961 assert!(sqrt.is_none());
962 }
963
964 #[test]
965 fn from_hex_1a_is_26_for_stark252_prime_field_element() {
966 type F = Stark252PrimeField;
967 type FE = FieldElement<F>;
968 assert_eq!(FE::from_hex("1a").unwrap(), FE::from(26))
969 }
970
971 #[test]
972 fn from_hex_unchecked_zero_x_1a_is_26_for_stark252_prime_field_element() {
973 type F = Stark252PrimeField;
974 type FE = FieldElement<F>;
975 assert_eq!(FE::from_hex_unchecked("0x1a"), FE::from(26))
976 }
977
978 #[test]
979 fn construct_new_field_element_from_empty_string_errs() {
980 type F = Stark252PrimeField;
981 type FE = FieldElement<F>;
982 assert!(FE::from_hex("").is_err());
983 }
984
985 #[test]
986 fn construct_new_field_element_from_value_bigger_than_modulus() {
987 type F = Stark252PrimeField;
988 type FE = FieldElement<F>;
989 assert!(FE::from_hex(&format!("0x{}", "f".repeat(65))).is_err());
991 }
992
993 prop_compose! {
994 fn field_element()(num in any::<u64>().prop_filter("Avoid null coefficients", |x| x != &0)) -> FieldElement::<Stark252PrimeField> {
995 FieldElement::<Stark252PrimeField>::from(num)
996 }
997 }
998
999 prop_compose! {
1000 #[cfg(feature = "alloc")]
1001 fn field_vec(max_exp: u8)(vec in collection::vec(field_element(), 0..1 << max_exp)) -> Vec<FieldElement::<Stark252PrimeField>> {
1002 vec
1003 }
1004 }
1005
1006 proptest! {
1007 #[cfg(feature = "alloc")]
1008 #[test]
1009 fn test_inplace_batch_inverse_returns_inverses(vec in field_vec(10)) {
1010 let input: Vec<_> = vec.into_iter().filter(|x| x != &FieldElement::<Stark252PrimeField>::zero()).collect();
1011 let mut inverses = input.clone();
1012 FieldElement::inplace_batch_inverse(&mut inverses).unwrap();
1013
1014 for (i, x) in inverses.into_iter().enumerate() {
1015 prop_assert_eq!(x * input[i], FieldElement::<Stark252PrimeField>::one());
1016 }
1017 }
1018 }
1019
1020 type U64F17 = U64PrimeField<17>;
1025 type U64F17Element = FieldElement<U64F17>;
1026
1027 type BabyBear = Babybear31PrimeField;
1029 type BabyBearElement = FieldElement<BabyBear>;
1030
1031 #[derive(Clone, Debug)]
1033 struct U384Modulus23;
1034 impl IsModulus<U384> for U384Modulus23 {
1035 const MODULUS: U384 = UnsignedInteger::from_u64(23);
1036 }
1037 type U384F23 = U384PrimeField<U384Modulus23>;
1038 type U384F23Element = FieldElement<U384F23>;
1039
1040 #[test]
1041 fn test_reduced_biguint_conversion_u64_field() {
1042 let value = BigUint::from(10u32);
1043 let fe = U64F17Element::try_from(value.clone()).unwrap();
1044 let back_to_biguint = fe.to_big_uint();
1045 assert_eq!(value, back_to_biguint);
1046 }
1047
1048 #[test]
1049 fn test_reduced_biguint_conversion_baby_bear() {
1050 let value = BigUint::from(1000u32);
1051 let fe = BabyBearElement::from_reduced_big_uint(&value).unwrap();
1052 assert_eq!(fe, BabyBearElement::from(1000));
1053 let back_to_biguint = fe.to_big_uint();
1054 assert_eq!(value, back_to_biguint);
1055 }
1056
1057 #[test]
1058 fn test_reduced_biguint_conversion_u384_field() {
1059 let value = BigUint::from(22u32);
1060 let fe = U384F23Element::from_reduced_big_uint(&value).unwrap();
1061 let back_to_biguint = fe.to_big_uint();
1062 assert_eq!(value, back_to_biguint);
1063 }
1064 #[test]
1065 fn test_bn254_field_biguint_conversion() {
1066 type BN254Element = FieldElement<BN254PrimeField>;
1067 let value = BigUint::from(1001u32);
1068 let fe = BN254Element::from_reduced_big_uint(&value).unwrap();
1069 let back_to_biguint = fe.to_big_uint();
1070 assert_eq!(value, back_to_biguint);
1071 }
1072
1073 #[test]
1074 fn non_reduced_biguint_value_conversion_errors_u64_field() {
1075 let value = BigUint::from(17u32);
1076 let result = U64F17Element::from_reduced_big_uint(&value);
1077 assert_eq!(result, Err(ByteConversionError::ValueNotReduced));
1078 }
1079
1080 #[test]
1081 fn non_reduced_biguint_value_conversion_errors_baby_bear() {
1082 let value = BigUint::from(2013265921u32);
1083 let result = BabyBearElement::try_from(value);
1084 assert_eq!(result, Err(ByteConversionError::ValueNotReduced));
1085 }
1086
1087 #[test]
1088 fn non_reduced_biguint_value_conversion_errors_u384_field() {
1089 let value = BigUint::from(30u32);
1090 let result = U384F23Element::try_from(value);
1091 assert_eq!(result, Err(ByteConversionError::ValueNotReduced));
1092 }
1093
1094 #[test]
1095 fn test_hex_string_conversion_u64_field() {
1096 let hex_str = "0x0a";
1097 let fe = U64F17Element::from_hex_str(hex_str).unwrap();
1098 assert_eq!(fe, U64F17Element::from(10));
1099 assert_eq!(fe.to_hex_str(), "0x0A");
1100 }
1101
1102 #[test]
1103 fn test_hex_string_conversion_baby_bear() {
1104 let hex_str = "0x77FFFFFF"; let fe = BabyBearElement::from_hex_str(hex_str).unwrap();
1106 assert_eq!(fe, BabyBearElement::from(2013265919));
1107 assert_eq!(fe.to_hex_str(), "0x77FFFFFF");
1108 }
1109
1110 #[test]
1111 fn test_hex_string_conversion_u384_field() {
1112 let hex_str = "0x14"; let fe = U384F23Element::from_hex_str(hex_str).unwrap();
1114 assert_eq!(fe, U384F23Element::from(20));
1115 assert_eq!(fe.to_hex_str(), "0x14");
1116 }
1117
1118 #[test]
1119 fn test_invalid_hex_string_u64_field() {
1120 let hex_str = "0xzz";
1121 let result = U64F17Element::from_hex_str(hex_str);
1122 assert!(result.is_err());
1123 }
1124
1125 #[test]
1126 fn test_invalid_hex_string_baby_bear() {
1127 let hex_str = "0x78000001";
1129 let result = BabyBearElement::from_hex_str(hex_str);
1130 assert!(result.is_err());
1131 }
1132
1133 #[test]
1134 fn test_empty_hex_string() {
1135 let hex_str = "";
1136 let result = U64F17Element::from_hex_str(hex_str);
1137 assert!(result.is_err());
1138 }
1139}