Move characteristic to its own fn

This commit is contained in:
wborgeaud 2021-12-14 17:12:14 +01:00
parent 073fe7a6d9
commit 9211bcfed5
6 changed files with 29 additions and 16 deletions

View File

@ -59,8 +59,7 @@ impl<F: Extendable<2>> Field for QuadraticExtension<F> {
// 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_WITH_TWO_ADICITY: Option<(u64, usize)> =
F::CHARACTERISTIC_WITH_TWO_ADICITY;
const CHARACTERISTIC_TWO_ADICITY: usize = F::CHARACTERISTIC_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);
@ -70,6 +69,9 @@ impl<F: Extendable<2>> Field for QuadraticExtension<F> {
fn order() -> BigUint {
F::order() * F::order()
}
fn characteristic() -> BigUint {
F::characteristic()
}
#[inline(always)]
fn square(&self) -> Self {

View File

@ -61,8 +61,7 @@ impl<F: Extendable<4>> Field for QuarticExtension<F> {
// `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_WITH_TWO_ADICITY: Option<(u64, usize)> =
F::CHARACTERISTIC_WITH_TWO_ADICITY;
const CHARACTERISTIC_TWO_ADICITY: usize = F::CHARACTERISTIC_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);
@ -72,6 +71,9 @@ impl<F: Extendable<4>> Field for QuarticExtension<F> {
fn order() -> BigUint {
F::order().pow(4u32)
}
fn characteristic() -> BigUint {
F::characteristic()
}
#[inline(always)]
fn square(&self) -> Self {

View File

@ -4,7 +4,7 @@ use std::iter::{Product, Sum};
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
use num::bigint::BigUint;
use num::{Integer, One, Zero};
use num::{Integer, One, ToPrimitive, Zero};
use rand::Rng;
use serde::de::DeserializeOwned;
use serde::Serialize;
@ -52,7 +52,7 @@ pub trait Field:
/// 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)>;
const CHARACTERISTIC_TWO_ADICITY: usize;
/// Generator of the entire multiplicative group, i.e. all non-zero elements.
const MULTIPLICATIVE_GROUP_GENERATOR: Self;
@ -62,6 +62,7 @@ pub trait Field:
const BITS: usize;
fn order() -> BigUint;
fn characteristic() -> BigUint;
#[inline]
fn is_zero(&self) -> bool {
@ -204,24 +205,24 @@ pub trait Field:
// exp exceeds t, we repeatedly multiply by 2^-t and reduce
// exp until it's in the right range.
if let Some((p, two_adicity)) = Self::CHARACTERISTIC_WITH_TWO_ADICITY {
if let Some(p) = Self::characteristic().to_u64() {
// 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 {
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) >> two_adicity));
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 e = exp - Self::CHARACTERISTIC_TWO_ADICITY;
while e > two_adicity {
while e > Self::CHARACTERISTIC_TWO_ADICITY {
res *= inverse_2_pow_adicity;
e -= two_adicity;
e -= Self::CHARACTERISTIC_TWO_ADICITY;
}
res * Self::from_canonical_u64(p - ((p - 1) >> e))
} else {

View File

@ -68,8 +68,7 @@ impl Field for GoldilocksField {
const NEG_ONE: Self = Self(Self::ORDER - 1);
const TWO_ADICITY: usize = 32;
const CHARACTERISTIC_WITH_TWO_ADICITY: Option<(u64, usize)> =
Some((Self::ORDER, Self::TWO_ADICITY));
const CHARACTERISTIC_TWO_ADICITY: usize = Self::TWO_ADICITY;
// Sage: `g = GF(p).multiplicative_generator()`
const MULTIPLICATIVE_GROUP_GENERATOR: Self = Self(7);
@ -86,6 +85,9 @@ impl Field for GoldilocksField {
fn order() -> BigUint {
Self::ORDER.into()
}
fn characteristic() -> BigUint {
Self::order()
}
#[inline(always)]
fn try_inverse(&self) -> Option<Self> {

View File

@ -78,7 +78,7 @@ impl Field for Secp256K1Base {
]);
const TWO_ADICITY: usize = 1;
const CHARACTERISTIC_WITH_TWO_ADICITY: Option<(u64, usize)> = None;
const CHARACTERISTIC_TWO_ADICITY: usize = Self::TWO_ADICITY;
// Sage: `g = GF(p).multiplicative_generator()`
const MULTIPLICATIVE_GROUP_GENERATOR: Self = Self([5, 0, 0, 0]);
@ -94,6 +94,9 @@ impl Field for Secp256K1Base {
0xFFFFFFFF,
])
}
fn characteristic() -> BigUint {
Self::order()
}
fn try_inverse(&self) -> Option<Self> {
if self.is_zero() {

View File

@ -81,7 +81,7 @@ impl Field for Secp256K1Scalar {
]);
const TWO_ADICITY: usize = 6;
const CHARACTERISTIC_WITH_TWO_ADICITY: Option<(u64, usize)> = None;
const CHARACTERISTIC_TWO_ADICITY: usize = Self::TWO_ADICITY;
// Sage: `g = GF(p).multiplicative_generator()`
const MULTIPLICATIVE_GROUP_GENERATOR: Self = Self([7, 0, 0, 0]);
@ -103,6 +103,9 @@ impl Field for Secp256K1Scalar {
0xFFFFFFFF,
])
}
fn characteristic() -> BigUint {
Self::order()
}
fn try_inverse(&self) -> Option<Self> {
if self.is_zero() {