1+ // ! Mathematical operations and utilities.
2+ // !
3+ // ! Provides extended GCD, modular inverse, and modular arithmetic operations.
4+
15#[allow(unused_imports)]
26use crate :: zeroable :: {IsZeroResult , NonZeroIntoImpl , Zeroable };
37#[allow(unused_imports)]
@@ -10,12 +14,24 @@ use crate::RangeCheck;
1014// TODO(yuval): use signed integers once supported.
1115// TODO(yuval): use a single impl of a trait with associated impls, once associated impls are
1216// supported.
13- /// Extended GCD: finds (g, s, t, sub_direction) such that
14- /// `g = gcd(a, b) = s * a - t * b` if `sub_direction` is true, or
15- /// `g = gcd(a, b) = t * b - s * a` if `sub_direction` is false.
16- /// `(s, -t)` or `(-s, t)` are the Bezout coefficients (according to `sub_direction`).
17+ /// Computes the extended GCD and Bezout coefficients for two numbers.
18+ ///
19+ /// Uses the Extended Euclidean algorithm to find (g, s, t, sub_direction) where `g = gcd(a, b)`.
20+ /// The relationship between inputs and outputs is:
21+ /// * If `sub_direction` is true: `g = s * a - t * b`
22+ /// * If `sub_direction` is false: `g = t * b - s * a`
23+ ///
24+ /// Returns a tuple (g, s, t, sub_direction) where g is the GCD and `(s, -t)` or `(-s, t)` are the
25+ /// Bezout coefficients (according to `sub_direction`).
1726///
18- /// Uses the Extended Euclidean algorithm.
27+ /// # Examples
28+ ///
29+ /// ```
30+ /// use core::math::egcd;
31+ ///
32+ /// let (g, s, t, dir) = egcd::<u32>(12, 8);
33+ /// assert!(g == 4);
34+ /// ```
1935pub fn egcd <
2036 T ,
2137 + Copy <T >,
@@ -47,9 +63,19 @@ pub fn egcd<
4763}
4864
4965// TODO(yuval): use signed integers once supported.
50- /// Returns `s` the inverse of `a` modulo `n` such that `as`≡ 1 modulo `n`, or None if `gcd(a, n)
51- /// > 1`.
52- /// `s` is guaranteed to be between `1` and `n - 1` (inclusive).
66+ /// Computes the modular multiplicative inverse of `a` modulo `n`.
67+ ///
68+ /// Returns `s` such that `a*s ≡ 1 (mod n)` where `s` is between `1` and `n-1` inclusive, or
69+ /// `Option::None` if `gcd(a,n) > 1` (inverse doesn't exist).
70+ ///
71+ /// # Examples
72+ ///
73+ /// ```
74+ /// use core::math::inv_mod;
75+ ///
76+ /// let inv = inv_mod::<u32>(3, 7);
77+ /// assert!(inv == Option::Some(5));
78+ /// ```
5379pub fn inv_mod <
5480 T ,
5581 + Copy <T >,
@@ -85,7 +111,8 @@ pub fn inv_mod<
85111 }
86112}
87113
88- /// Returns `1 / b (mod n)`, or None if `b` is not invertible modulo `n`.
114+ /// Returns `1 / b (mod n)`, or `None` if `b` is not invertible modulo `n`.
115+ ///
89116/// All `b`s will be considered not invertible for `n == 1`.
90117/// Additionally returns several `U128MulGuarantee`s that are required for validating the
91118/// calculation.
@@ -106,8 +133,18 @@ extern fn u256_guarantee_inv_mod_n(
106133 (U128MulGuarantee , U128MulGuarantee ),
107134> implicits (RangeCheck ) nopanic ;
108135
109- /// Returns the inverse of `a` modulo `n`, or None if `a` is not invertible modulo `n`.
136+ /// Returns the inverse of `a` modulo `n`, or `None` if `a` is not invertible modulo `n`.
137+ ///
110138/// All `a`s will be considered not invertible for `n == 1`.
139+ ///
140+ /// # Examples
141+ ///
142+ /// ```
143+ /// use core::math::u256_inv_mod;
144+ ///
145+ /// let inv = u256_inv_mod(3, 17);
146+ /// assert!(inv == Option::Some(6));
147+ /// ```
111148#[inline]
112149pub fn u256_inv_mod (a : u256 , n : NonZero <u256 >) -> Option <NonZero <u256 >> {
113150 match u256_guarantee_inv_mod_n (a , n ) {
@@ -116,26 +153,45 @@ pub fn u256_inv_mod(a: u256, n: NonZero<u256>) -> Option<NonZero<u256>> {
116153 }
117154}
118155
119- /// Returns `a / b (mod n)`, or None if `b` is not invertible modulo `n`.
156+ /// Returns `a / b (mod n)`, or `None` if `b` is not invertible modulo `n`.
157+ ///
158+ /// # Examples
159+ ///
160+ /// ```
161+ /// use core::math::u256_inv_mod;
162+ ///
163+ /// let result = u256_div_mod_n(17, 7, 29);
164+ /// assert!(result == Option::Some(19));
165+ /// ```
120166pub fn u256_div_mod_n (a : u256 , b : u256 , n : NonZero <u256 >) -> Option <u256 > {
121167 Option :: Some (u256_mul_mod_n (a , u256_inv_mod (b , n )? . into (), n ))
122168}
123169
124170/// Returns `a * b (mod n)`.
171+ ///
172+ /// # Examples
173+ ///
174+ /// ```
175+ /// use core::math::u256_mul_mod_n;
176+ ///
177+ /// let result = u256_mul_mod_n(17, 23, 29);
178+ /// assert!(result == 14);
179+ /// ```
125180pub fn u256_mul_mod_n (a : u256 , b : u256 , n : NonZero <u256 >) -> u256 {
126181 let (_ , r ) = u512_safe_div_rem_by_u256 (u256_wide_mul (a , b ), n );
127182 r
128183}
129184
130- // === Oneable ===
131185/// A trait for types that have a multiplicative identity element.
132186trait Oneable <T > {
133187 /// Returns the multiplicative identity element of Self, 1.
134188 #[must_use]
135189 fn one () -> T ;
190+
136191 /// Returns whether self is equal to 1, the multiplicative identity element.
137192 #[must_use]
138193 fn is_one (self : T ) -> bool ;
194+
139195 /// Returns whether self is not equal to 1, the multiplicative identity element.
140196 #[must_use]
141197 fn is_non_one (self : T ) -> bool ;
@@ -148,18 +204,19 @@ pub(crate) mod one_based {
148204 fn one () -> T {
149205 OneImpl :: one ()
150206 }
207+
151208 #[inline]
152209 fn is_one (self : T ) -> bool {
153210 OneImpl :: is_one (@ self )
154211 }
212+
155213 #[inline]
156214 fn is_non_one (self : T ) -> bool {
157215 OneImpl :: is_non_one (@ self )
158216 }
159217 }
160218}
161219
162- // Oneable impls
163220impl U8Oneable = one_based :: OneableImpl <u8 >;
164221impl U16Oneable = one_based :: OneableImpl <u16 >;
165222impl U32Oneable = one_based :: OneableImpl <u32 >;
0 commit comments