Files
powdr/std/math/ff.asm
onurinanc 14225aa1d1 Implement Fp4 for BabyBear Field in PIL (#1707)
Solves the issue in #1691

You can run the test using `--field bb`
2024-09-03 15:15:44 +00:00

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)
};