mirror of
https://github.com/powdr-labs/powdr.git
synced 2026-04-20 03:03:25 -04:00
53 lines
1.6 KiB
Rust
53 lines
1.6 KiB
Rust
use std::convert::fe;
|
|
use std::convert::int;
|
|
|
|
/// Inverts `x` in the finite field with modulus `modulus`.
|
|
/// Assumes that `modulus` is prime, but does not check it.
|
|
let inverse = |x, modulus|
|
|
if x <= 0 || x >= modulus {
|
|
if x == 0 {
|
|
std::check::panic("Tried to compute the inverse of zero.")
|
|
} else {
|
|
std::check::panic("Tried to compute the inverse of a negative number or a number outside the field.")
|
|
}
|
|
} else {
|
|
let (r, _) = extended_gcd(x, modulus);
|
|
reduce(r, modulus)
|
|
};
|
|
|
|
/// Field inversion (defined on fe instead of int)
|
|
let inv_field: fe -> fe = |x| fe(inverse(int(x), std::field::modulus()));
|
|
|
|
/// Computes `x + y` modulo the modulus.
|
|
let add = |x, y, modulus| reduce(x + y, modulus);
|
|
|
|
/// Computes `x - y` modulo the modulus.
|
|
let sub = |x, y, modulus| reduce(x - y, modulus);
|
|
|
|
/// Computes `x * y` modulo the modulus.
|
|
let mul = |x, y, modulus| reduce(x * y, modulus);
|
|
|
|
/// Computes `x / y` modulo the modulus.
|
|
let div = |x, y, modulus| mul(x, inverse(y, modulus), modulus);
|
|
|
|
/// Reduces `x` modulo `modulus`, so that it is in the range
|
|
/// between `0` and `modulus`. Works on negative `x`.
|
|
let reduce = |x, modulus|
|
|
if x < 0 {
|
|
(modulus - ((-x) % modulus)) % modulus
|
|
} else {
|
|
x % modulus
|
|
};
|
|
|
|
let extended_gcd = |a, b|
|
|
if b == 0 {
|
|
if a == 1 {
|
|
(1, 0)
|
|
} else {
|
|
// a is the gcd, but we do not really want to compute it.
|
|
std::check::panic("Inputs are not co-prime, inverse does not exist.")
|
|
}
|
|
} else {
|
|
let (r1, r2) = extended_gcd(b, a % b);
|
|
(r2, r1 - (a / b) * r2)
|
|
}; |