Replace characteristic with option

This commit is contained in:
wborgeaud 2021-12-13 16:20:39 +01:00
parent e6c3f35431
commit fb168b5d93
7 changed files with 33 additions and 49 deletions

View File

@ -55,13 +55,12 @@ impl<F: Extendable<2>> Field for QuadraticExtension<F> {
const TWO: Self = Self([F::TWO, F::ZERO]);
const NEG_ONE: Self = Self([F::NEG_ONE, F::ZERO]);
const CHARACTERISTIC: u64 = F::CHARACTERISTIC;
// `p^2 - 1 = (p - 1)(p + 1)`. The `p - 1` term has a two-adicity of `F::TWO_ADICITY`. As
// long as `F::TWO_ADICITY >= 2`, `p` can be written as `4n + 1`, so `p + 1` can be written as
// `2(2n + 1)`, which has a 2-adicity of 1.
const TWO_ADICITY: usize = F::TWO_ADICITY + 1;
const CHARACTERISTIC_TWO_ADICITY: usize = F::CHARACTERISTIC_TWO_ADICITY;
const CHARACTERISTIC_WITH_TWO_ADICITY: Option<(u64, usize)> =
F::CHARACTERISTIC_WITH_TWO_ADICITY;
const MULTIPLICATIVE_GROUP_GENERATOR: Self = Self(F::EXT_MULTIPLICATIVE_GROUP_GENERATOR);
const POWER_OF_TWO_GENERATOR: Self = Self(F::EXT_POWER_OF_TWO_GENERATOR);

View File

@ -56,14 +56,13 @@ impl<F: Extendable<4>> Field for QuarticExtension<F> {
const TWO: Self = Self([F::TWO, F::ZERO, F::ZERO, F::ZERO]);
const NEG_ONE: Self = Self([F::NEG_ONE, F::ZERO, F::ZERO, F::ZERO]);
const CHARACTERISTIC: u64 = F::ORDER;
// `p^4 - 1 = (p - 1)(p + 1)(p^2 + 1)`. The `p - 1` term has a two-adicity of `F::TWO_ADICITY`.
// As long as `F::TWO_ADICITY >= 2`, `p` can be written as `4n + 1`, so `p + 1` can be written as
// `2(2n + 1)`, which has a 2-adicity of 1. A similar argument can show that `p^2 + 1` also has
// a 2-adicity of 1.
const TWO_ADICITY: usize = F::TWO_ADICITY + 2;
const CHARACTERISTIC_TWO_ADICITY: usize = F::CHARACTERISTIC_TWO_ADICITY;
const CHARACTERISTIC_WITH_TWO_ADICITY: Option<(u64, usize)> =
F::CHARACTERISTIC_WITH_TWO_ADICITY;
const MULTIPLICATIVE_GROUP_GENERATOR: Self = Self(F::EXT_MULTIPLICATIVE_GROUP_GENERATOR);
const POWER_OF_TWO_GENERATOR: Self = Self(F::EXT_POWER_OF_TWO_GENERATOR);

View File

@ -47,13 +47,12 @@ pub trait Field:
const TWO: Self;
const NEG_ONE: Self;
const CHARACTERISTIC: u64;
/// The 2-adicity of this field's multiplicative group.
const TWO_ADICITY: usize;
/// The 2-adicity of this field's multiplicative group.
const CHARACTERISTIC_TWO_ADICITY: usize;
/// The field's characteristic and it's 2-adicity.
/// Set to `None` when the characteristic doesn't fit in a u64.
const CHARACTERISTIC_WITH_TWO_ADICITY: Option<(u64, usize)>;
/// Generator of the entire multiplicative group, i.e. all non-zero elements.
const MULTIPLICATIVE_GROUP_GENERATOR: Self;
@ -205,29 +204,32 @@ pub trait Field:
// exp exceeds t, we repeatedly multiply by 2^-t and reduce
// exp until it's in the right range.
let p = Self::CHARACTERISTIC;
if let Some((p, two_adicity)) = Self::CHARACTERISTIC_WITH_TWO_ADICITY {
// NB: The only reason this is split into two cases is to save
// the multiplication (and possible calculation of
// inverse_2_pow_adicity) in the usual case that exp <=
// TWO_ADICITY. Can remove the branch and simplify if that
// saving isn't worth it.
// NB: The only reason this is split into two cases is to save
// the multiplication (and possible calculation of
// inverse_2_pow_adicity) in the usual case that exp <=
// TWO_ADICITY. Can remove the branch and simplify if that
// saving isn't worth it.
if exp > two_adicity {
// NB: This should be a compile-time constant
let inverse_2_pow_adicity: Self =
Self::from_canonical_u64(p - ((p - 1) >> two_adicity));
if exp > Self::CHARACTERISTIC_TWO_ADICITY {
// NB: This should be a compile-time constant
let inverse_2_pow_adicity: Self =
Self::from_canonical_u64(p - ((p - 1) >> Self::CHARACTERISTIC_TWO_ADICITY));
let mut res = inverse_2_pow_adicity;
let mut e = exp - two_adicity;
let mut res = inverse_2_pow_adicity;
let mut e = exp - Self::CHARACTERISTIC_TWO_ADICITY;
while e > Self::CHARACTERISTIC_TWO_ADICITY {
res *= inverse_2_pow_adicity;
e -= Self::CHARACTERISTIC_TWO_ADICITY;
while e > two_adicity {
res *= inverse_2_pow_adicity;
e -= two_adicity;
}
res * Self::from_canonical_u64(p - ((p - 1) >> e))
} else {
Self::from_canonical_u64(p - ((p - 1) >> exp))
}
res * Self::from_canonical_u64(p - ((p - 1) >> e))
} else {
Self::from_canonical_u64(p - ((p - 1) >> exp))
dbg!("yo");
Self::TWO.inverse().exp_u64(exp as u64)
}
}
@ -450,15 +452,6 @@ pub trait PrimeField: Field {
}
}
pub trait SmallCharacteristicField: Field {
const SMALLCHAR: u64;
#[inline]
fn inverse_2exp(exp: usize) -> Self {
todo!()
}
}
/// An iterator over the powers of a certain base element `b`: `b^0, b^1, b^2, ...`.
#[derive(Clone)]
pub struct Powers<F: Field> {

View File

@ -66,10 +66,10 @@ impl Field for GoldilocksField {
const ONE: Self = Self(1);
const TWO: Self = Self(2);
const NEG_ONE: Self = Self(Self::ORDER - 1);
const CHARACTERISTIC: u64 = Self::ORDER;
const TWO_ADICITY: usize = 32;
const CHARACTERISTIC_TWO_ADICITY: usize = Self::TWO_ADICITY;
const CHARACTERISTIC_WITH_TWO_ADICITY: Option<(u64, usize)> =
Some((Self::ORDER, Self::TWO_ADICITY));
// Sage: `g = GF(p).multiplicative_generator()`
const MULTIPLICATIVE_GROUP_GENERATOR: Self = Self(7);

View File

@ -144,7 +144,7 @@ macro_rules! test_prime_field_arithmetic {
fn inverse_2exp() {
type F = $field;
let v = <F as Field>::PrimeField::TWO_ADICITY;
let v = <F as Field>::TWO_ADICITY;
for e in [0, 1, 2, 3, 4, v - 2, v - 1, v, v + 1, v + 2, 123 * v] {
let x = F::TWO.exp_u64(e as u64);

View File

@ -11,7 +11,6 @@ use rand::Rng;
use serde::{Deserialize, Serialize};
use crate::field::field_types::Field;
use crate::field::goldilocks_field::GoldilocksField;
/// The base field of the secp256k1 elliptic curve.
///
@ -78,10 +77,8 @@ impl Field for Secp256K1Base {
0xFFFFFFFFFFFFFFFF,
]);
// TODO: fix
const CHARACTERISTIC: u64 = 0;
const TWO_ADICITY: usize = 1;
const CHARACTERISTIC_TWO_ADICITY: usize = Self::TWO_ADICITY;
const CHARACTERISTIC_WITH_TWO_ADICITY: Option<(u64, usize)> = None;
// Sage: `g = GF(p).multiplicative_generator()`
const MULTIPLICATIVE_GROUP_GENERATOR: Self = Self([5, 0, 0, 0]);

View File

@ -12,7 +12,6 @@ use rand::Rng;
use serde::{Deserialize, Serialize};
use crate::field::field_types::Field;
use crate::field::goldilocks_field::GoldilocksField;
/// The base field of the secp256k1 elliptic curve.
///
@ -81,11 +80,8 @@ impl Field for Secp256K1Scalar {
0xFFFFFFFFFFFFFFFF,
]);
// TODO: fix
const CHARACTERISTIC: u64 = 0;
const TWO_ADICITY: usize = 6;
const CHARACTERISTIC_TWO_ADICITY: usize = 6;
const CHARACTERISTIC_WITH_TWO_ADICITY: Option<(u64, usize)> = None;
// Sage: `g = GF(p).multiplicative_generator()`
const MULTIPLICATIVE_GROUP_GENERATOR: Self = Self([7, 0, 0, 0]);