github.com/ledgerwatch/erigon-lib@v1.0.0/pedersen_hash/prime_field_element.h (about) 1 #ifndef STARKWARE_ALGEBRA_PRIME_FIELD_ELEMENT_H_ 2 #define STARKWARE_ALGEBRA_PRIME_FIELD_ELEMENT_H_ 3 4 #include <array> 5 #include <cstddef> 6 #include <cstdint> 7 #include <limits> 8 #include <string> 9 #include <tuple> 10 #include <utility> 11 #include <vector> 12 13 #include "big_int.h" 14 #include "error_handling.h" 15 #include "prng.h" 16 17 namespace starkware { 18 19 /* 20 Represents an element of GF(p) for p = 2^251 + 17 * 2^192 + 1. 21 The value is stored in Montgomery representation. 22 */ 23 class PrimeFieldElement { 24 public: 25 using ValueType = BigInt<4>; 26 static constexpr ValueType kModulus = 27 0x800000000000011000000000000000000000000000000000000000000000001_Z; 28 static constexpr ValueType kMontgomeryR = 29 0x7fffffffffffdf0ffffffffffffffffffffffffffffffffffffffffffffffe1_Z; 30 static constexpr ValueType kMontgomeryRSquared = 31 0x7ffd4ab5e008810ffffffffff6f800000000001330ffffffffffd737e000401_Z; 32 static constexpr ValueType kMontgomeryRCubed = 33 0x38e5f79873c0a6df47d84f8363000187545706677ffcc06cc7177d1406df18e_Z; 34 static constexpr uint64_t kMontgomeryMPrime = ~uint64_t(0); 35 static constexpr ValueType kHalfMultiplicativeGroupSize = 36 0x400000000000008800000000000000000000000000000000000000000000000_Z; 37 38 PrimeFieldElement() = delete; 39 40 static PrimeFieldElement FromUint(uint64_t val) { 41 return PrimeFieldElement( 42 // Note that because MontgomeryMul divides by r we need to multiply by r^2 here. 43 MontgomeryMul(ValueType(val), kMontgomeryRSquared)); 44 } 45 46 static constexpr PrimeFieldElement FromBigInt(const ValueType& val) { 47 return PrimeFieldElement( 48 // Note that because MontgomeryMul divides by r we need to multiply by r^2 here. 49 MontgomeryMul(val, kMontgomeryRSquared)); 50 } 51 52 static PrimeFieldElement RandomElement(Prng* prng); 53 54 static constexpr PrimeFieldElement Zero() { return PrimeFieldElement(ValueType({})); } 55 56 static constexpr PrimeFieldElement One() { return PrimeFieldElement(kMontgomeryR); } 57 58 PrimeFieldElement operator*(const PrimeFieldElement& rhs) const { 59 return PrimeFieldElement(MontgomeryMul(value_, rhs.value_)); 60 } 61 62 PrimeFieldElement operator+(const PrimeFieldElement& rhs) const { 63 return PrimeFieldElement{ValueType::ReduceIfNeeded(value_ + rhs.value_, kModulus)}; 64 } 65 66 PrimeFieldElement operator-(const PrimeFieldElement& rhs) const { 67 return PrimeFieldElement{(value_ >= rhs.value_) ? (value_ - rhs.value_) 68 : (value_ + kModulus - rhs.value_)}; 69 } 70 71 PrimeFieldElement operator-() const { return Zero() - *this; } 72 73 PrimeFieldElement operator/(const PrimeFieldElement& rhs) const { return *this * rhs.Inverse(); } 74 75 bool operator==(const PrimeFieldElement& rhs) const { return value_ == rhs.value_; } 76 bool operator!=(const PrimeFieldElement& rhs) const { return !(*this == rhs); } 77 78 PrimeFieldElement Inverse() const { 79 ASSERT(*this != PrimeFieldElement::Zero(), "Zero does not have an inverse"); 80 return Pow((kModulus - 0x2_Z).ToBoolVector()); 81 } 82 83 /* 84 Returns the power of a field element, where exponent_bits[0] is the least significant bit of the 85 exponent. 86 Note that this function doesn't support negative exponents. 87 */ 88 PrimeFieldElement Pow(const std::vector<bool>& exponent_bits) const; 89 90 /* 91 Returns the power of a field element for the given exponent. 92 */ 93 PrimeFieldElement Pow(const uint64_t exponent) const; 94 95 /* 96 For a field element x, returns true if there exists a field element y such that x = y^2. 97 */ 98 bool IsSquare() const; 99 100 /* 101 For a field element x, returns an element y such that y^2 = x. If no such y exists, the function 102 throws an exception. 103 */ 104 PrimeFieldElement Sqrt() const; 105 106 /* 107 Returns the standard representation. 108 109 A value in the range [0, kBigPrimeConstants::kModulus) in non-Montogomery representation. 110 */ 111 ValueType ToStandardForm() const { return MontgomeryMul(value_, ValueType::One()); } 112 113 std::string ToString() const { return ToStandardForm().ToString(); } 114 115 private: 116 explicit constexpr PrimeFieldElement(ValueType val) : value_(val) {} 117 118 static constexpr ValueType MontgomeryMul(const ValueType& x, const ValueType& y) { 119 return ValueType::MontMul(x, y, kModulus, kMontgomeryMPrime); 120 } 121 122 ValueType value_; 123 }; 124 125 inline std::ostream& operator<<(std::ostream& out, const PrimeFieldElement& element) { 126 return out << element.ToString(); 127 } 128 129 } // namespace starkware 130 131 #endif // STARKWARE_ALGEBRA_PRIME_FIELD_ELEMENT_H_