use rand::Rng;
use std::fmt::{Display, Error, Formatter};
use std::hash::Hash;
use std::ops::{Deref, Neg};
use crate::domains::integer::Integer;
use crate::poly::gcd::PolynomialGCD;
use crate::poly::Variable::Temporary;
use crate::printer::{PrintOptions, PrintState};
use super::algebraic_number::AlgebraicExtension;
use super::integer::Z;
use super::{EuclideanDomain, Field, InternalOrdering, Ring};
const HENSEL_LIFTING_MASK: [u8; 128] = [
255, 85, 51, 73, 199, 93, 59, 17, 15, 229, 195, 89, 215, 237, 203, 33, 31, 117, 83, 105, 231,
125, 91, 49, 47, 5, 227, 121, 247, 13, 235, 65, 63, 149, 115, 137, 7, 157, 123, 81, 79, 37, 3,
153, 23, 45, 11, 97, 95, 181, 147, 169, 39, 189, 155, 113, 111, 69, 35, 185, 55, 77, 43, 129,
127, 213, 179, 201, 71, 221, 187, 145, 143, 101, 67, 217, 87, 109, 75, 161, 159, 245, 211, 233,
103, 253, 219, 177, 175, 133, 99, 249, 119, 141, 107, 193, 191, 21, 243, 9, 135, 29, 251, 209,
207, 165, 131, 25, 151, 173, 139, 225, 223, 53, 19, 41, 167, 61, 27, 241, 239, 197, 163, 57,
183, 205, 171, 1,
];
pub type Zp = FiniteField<u32>;
pub type Zp64 = FiniteField<u64>;
pub trait ToFiniteField<UField: FiniteFieldWorkspace>
where
FiniteField<UField>: FiniteFieldCore<UField>,
{
fn to_finite_field(
&self,
field: &FiniteField<UField>,
) -> <FiniteField<UField> as Ring>::Element;
}
impl ToFiniteField<u32> for u32 {
fn to_finite_field(&self, field: &FiniteField<u32>) -> <FiniteField<u32> as Ring>::Element {
field.to_element(*self)
}
}
impl ToFiniteField<u64> for u64 {
fn to_finite_field(&self, field: &FiniteField<u64>) -> <FiniteField<u64> as Ring>::Element {
field.to_element(*self)
}
}
impl ToFiniteField<Two> for u32 {
fn to_finite_field(&self, field: &FiniteField<Two>) -> <FiniteField<Two> as Ring>::Element {
field.to_element(Two((*self % 2) as u8))
}
}
impl ToFiniteField<Two> for u64 {
fn to_finite_field(&self, field: &FiniteField<Two>) -> <FiniteField<Two> as Ring>::Element {
field.to_element(Two((*self % 2) as u8))
}
}
pub trait GaloisField: Field {
type Base: Field;
fn get_extension_degree(&self) -> u64;
fn to_integer(&self, a: &Self::Element) -> Integer;
fn to_symmetric_integer(&self, a: &Self::Element) -> Integer;
fn upgrade(&self, new_pow: usize) -> AlgebraicExtension<Self::Base>
where
Self::Base: PolynomialGCD<u16>,
<Self::Base as Ring>::Element: Copy;
fn upgrade_element(
&self,
e: &Self::Element,
larger_field: &AlgebraicExtension<Self::Base>,
) -> <AlgebraicExtension<Self::Base> as Ring>::Element;
fn downgrade_element(
&self,
e: &<AlgebraicExtension<Self::Base> as Ring>::Element,
) -> Self::Element;
}
impl<UField: FiniteFieldWorkspace> GaloisField for FiniteField<UField>
where
FiniteField<UField>: Field + FiniteFieldCore<UField>,
{
type Base = Self;
fn get_extension_degree(&self) -> u64 {
1
}
fn to_integer(&self, a: &Self::Element) -> Integer {
self.from_element(a).to_integer()
}
#[inline(always)]
fn to_symmetric_integer(&self, a: &Self::Element) -> Integer {
let i = self.from_element(a).to_integer();
let p = self.get_prime().to_integer();
if &i * &2.into() > p {
&i - &p
} else {
i
}
}
fn upgrade(&self, new_pow: usize) -> AlgebraicExtension<FiniteField<UField>>
where
Self::Base: PolynomialGCD<u16>,
<Self::Base as Ring>::Element: Copy,
{
AlgebraicExtension::galois_field(self.clone(), new_pow, Temporary(0))
}
fn upgrade_element(
&self,
e: &Self::Element,
larger_field: &AlgebraicExtension<Self::Base>,
) -> <AlgebraicExtension<Self::Base> as Ring>::Element {
larger_field.constant(e.clone())
}
fn downgrade_element(
&self,
e: &<AlgebraicExtension<Self::Base> as Ring>::Element,
) -> Self::Element {
e.poly.get_constant()
}
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, PartialOrd, Eq)]
pub struct FiniteFieldElement<UField>(pub(crate) UField);
impl<UField: PartialOrd> InternalOrdering for FiniteFieldElement<UField> {
fn internal_cmp(&self, other: &Self) -> std::cmp::Ordering {
self.partial_cmp(other).unwrap_or(std::cmp::Ordering::Equal)
}
}
pub trait FiniteFieldWorkspace: Clone + Display + Eq + Hash {
fn get_large_prime() -> Self;
fn try_from_integer(n: Integer) -> Option<Self>;
fn to_integer(&self) -> Integer;
fn to_u64(&self) -> Option<u64> {
match self.to_integer() {
Integer::Natural(s) => {
if s >= 0 {
Some(s as u64)
} else {
None
}
}
Integer::Double(s) => {
if s >= 0 && s <= u64::MAX as i128 {
Some(s as u64)
} else {
None
}
}
Integer::Large(_) => None,
}
}
}
pub trait FiniteFieldCore<UField: FiniteFieldWorkspace>: Field {
fn new(p: UField) -> Self;
fn get_prime(&self) -> UField;
fn to_element(&self, a: UField) -> Self::Element;
fn from_element(&self, a: &Self::Element) -> UField;
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct FiniteField<UField> {
p: UField,
m: UField,
one: FiniteFieldElement<UField>,
}
impl Zp {
pub fn new(p: u32) -> Zp {
if p % 2 == 0 {
panic!("Prime 2 is not supported: use Z2 instead.");
}
FiniteField {
p,
m: Self::inv_2_32(p),
one: FiniteFieldElement(Self::get_one(p)),
}
}
fn get_one(a: u32) -> u32 {
if a as u64 <= 1u64 << 31 {
let res = (((1u64 << 31) % a as u64) << 1) as u32;
if res < a {
res
} else {
res - a
}
} else {
a.wrapping_neg()
}
}
fn inv_2_32(a: u32) -> u32 {
let mut ret: u32 = HENSEL_LIFTING_MASK[((a >> 1) & 127) as usize] as u32;
ret = ret.wrapping_mul(a.wrapping_mul(ret).wrapping_add(2));
ret = ret.wrapping_mul(a.wrapping_mul(ret).wrapping_add(2));
ret
}
}
impl FiniteFieldWorkspace for u32 {
fn get_large_prime() -> u32 {
2147483659
}
fn try_from_integer(n: Integer) -> Option<Self> {
match n {
Integer::Natural(s) => {
if s >= 0 && s <= u32::MAX as i64 {
Some(s as u32)
} else {
None
}
}
_ => None,
}
}
fn to_integer(&self) -> Integer {
Integer::Natural(*self as i64)
}
}
impl FiniteFieldCore<u32> for Zp {
fn new(p: u32) -> Zp {
Self::new(p)
}
fn get_prime(&self) -> u32 {
self.p
}
#[inline(always)]
fn to_element(&self, a: u32) -> FiniteFieldElement<u32> {
FiniteFieldElement((((a as u64) << 32) % self.p as u64) as u32)
}
#[inline(always)]
fn from_element(&self, a: &FiniteFieldElement<u32>) -> u32 {
self.mul(a, &FiniteFieldElement(1)).0
}
}
impl Ring for Zp {
type Element = FiniteFieldElement<u32>;
#[inline(always)]
fn add(&self, a: &Self::Element, b: &Self::Element) -> Self::Element {
let mut t = a.0 as u64 + b.0 as u64;
if t >= self.p as u64 {
t -= self.p as u64;
}
FiniteFieldElement(t as u32)
}
#[inline(always)]
fn sub(&self, a: &Self::Element, b: &Self::Element) -> Self::Element {
if a.0 >= b.0 {
FiniteFieldElement(a.0 - b.0)
} else {
FiniteFieldElement(a.0 + (self.p - b.0))
}
}
#[inline(always)]
fn mul(&self, a: &Self::Element, b: &Self::Element) -> Self::Element {
let t = a.0 as u64 * b.0 as u64;
let m = (t as u32).wrapping_mul(self.m);
let u = ((t.wrapping_add(m as u64 * self.p as u64)) >> 32) as u32;
if u < (t >> 32) as u32 {
return FiniteFieldElement(u.wrapping_sub(self.p));
}
if u >= self.p {
FiniteFieldElement(u - self.p)
} else {
FiniteFieldElement(u)
}
}
#[inline(always)]
fn add_assign(&self, a: &mut Self::Element, b: &Self::Element) {
*a = self.add(a, b);
}
#[inline(always)]
fn sub_assign(&self, a: &mut Self::Element, b: &Self::Element) {
*a = self.sub(a, b);
}
#[inline(always)]
fn mul_assign(&self, a: &mut Self::Element, b: &Self::Element) {
*a = self.mul(a, b);
}
fn add_mul_assign(&self, a: &mut Self::Element, b: &Self::Element, c: &Self::Element) {
self.add_assign(a, &self.mul(b, c));
}
fn sub_mul_assign(&self, a: &mut Self::Element, b: &Self::Element, c: &Self::Element) {
self.sub_assign(a, &self.mul(b, c));
}
#[inline]
fn neg(&self, a: &Self::Element) -> Self::Element {
if a.0 == 0 {
*a
} else {
FiniteFieldElement(self.p - a.0)
}
}
#[inline]
fn zero(&self) -> Self::Element {
FiniteFieldElement(0)
}
#[inline]
fn one(&self) -> Self::Element {
self.one
}
#[inline]
fn nth(&self, n: Integer) -> Self::Element {
n.to_finite_field(self)
}
#[inline]
fn pow(&self, b: &Self::Element, mut e: u64) -> Self::Element {
if e >= self.get_prime() as u64 - 1 {
e = e % (self.get_prime() as u64 - 1);
}
if e == 0 {
return self.one();
}
let mut x = *b;
let mut y = self.one();
while e != 1 {
if e % 2 == 1 {
y = self.mul(&y, &x);
}
x = self.mul(&x, &x);
e /= 2;
}
self.mul(&x, &y)
}
#[inline]
fn is_zero(&self, a: &Self::Element) -> bool {
a.0 == 0
}
#[inline]
fn is_one(&self, a: &Self::Element) -> bool {
a == &self.one
}
fn one_is_gcd_unit() -> bool {
true
}
fn characteristic(&self) -> Integer {
self.get_prime().into()
}
fn size(&self) -> Integer {
self.get_prime().into()
}
fn try_div(&self, a: &Self::Element, b: &Self::Element) -> Option<Self::Element> {
if self.is_zero(b) {
None
} else {
Some(self.div(a, b))
}
}
fn sample(&self, rng: &mut impl rand::RngCore, range: (i64, i64)) -> Self::Element {
let r = rng.gen_range(range.0.max(0)..range.1.min(self.p as i64));
FiniteFieldElement(r as u32)
}
fn format<W: std::fmt::Write>(
&self,
element: &Self::Element,
opts: &PrintOptions,
state: PrintState,
f: &mut W,
) -> Result<bool, Error> {
if opts.symmetric_representation_for_finite_field {
Z.format(&self.to_symmetric_integer(element), opts, state, f)
} else {
Z.format(&self.from_element(element).into(), opts, state, f)
}
}
}
impl EuclideanDomain for Zp {
#[inline]
fn rem(&self, _: &Self::Element, _: &Self::Element) -> Self::Element {
FiniteFieldElement(0)
}
#[inline]
fn quot_rem(&self, a: &Self::Element, b: &Self::Element) -> (Self::Element, Self::Element) {
(self.mul(a, &self.inv(b)), FiniteFieldElement(0))
}
#[inline]
fn gcd(&self, _: &Self::Element, _: &Self::Element) -> Self::Element {
self.one()
}
}
impl Field for Zp {
#[inline]
fn div(&self, a: &Self::Element, b: &Self::Element) -> Self::Element {
self.mul(a, &self.inv(b))
}
#[inline]
fn div_assign(&self, a: &mut Self::Element, b: &Self::Element) {
*a = self.mul(a, &self.inv(b));
}
fn inv(&self, a: &Self::Element) -> Self::Element {
assert!(a.0 != 0, "0 is not invertible");
let x_mont = self
.mul(&self.mul(a, &FiniteFieldElement(1)), &FiniteFieldElement(1))
.0;
let mut u1: u32 = 1;
let mut u3 = x_mont;
let mut v1: u32 = 0;
let mut v3 = self.p;
let mut even_iter: bool = true;
while v3 != 0 {
let q = u3 / v3;
let t3 = u3 % v3;
let t1 = u1 + q * v1;
u1 = v1;
v1 = t1;
u3 = v3;
v3 = t3;
even_iter = !even_iter;
}
debug_assert!(u3 == 1);
if even_iter {
FiniteFieldElement(u1)
} else {
FiniteFieldElement(self.p - u1)
}
}
}
impl FiniteFieldWorkspace for u64 {
fn get_large_prime() -> u64 {
18346744073709552000
}
fn try_from_integer(n: Integer) -> Option<Self> {
match n {
Integer::Natural(s) => {
if s >= 0 {
Some(s as u64)
} else {
None
}
}
Integer::Double(d) => {
if d >= 0 && d <= u64::MAX as i128 {
Some(d as u64)
} else {
None
}
}
_ => None,
}
}
#[inline]
fn to_integer(&self) -> Integer {
(*self).into()
}
}
impl Zp64 {
pub fn new(p: u64) -> Zp64 {
if p % 2 == 0 {
panic!("Prime 2 is not supported: use Z2 instead.");
}
FiniteField {
p,
m: Self::inv_2_64(p),
one: FiniteFieldElement(Self::get_one(p)),
}
}
fn get_one(a: u64) -> u64 {
if a as u128 <= 1u128 << 63 {
let res = (((1u128 << 63) % a as u128) << 1) as u64;
if res < a {
res
} else {
res - a
}
} else {
a.wrapping_neg()
}
}
fn inv_2_64(a: u64) -> u64 {
let mut ret: u64 = HENSEL_LIFTING_MASK[((a >> 1) & 127) as usize] as u64;
ret = ret.wrapping_mul(a.wrapping_mul(ret).wrapping_add(2));
ret = ret.wrapping_mul(a.wrapping_mul(ret).wrapping_add(2));
ret = ret.wrapping_mul(a.wrapping_mul(ret).wrapping_add(2));
ret
}
}
impl FiniteFieldCore<u64> for Zp64 {
fn new(p: u64) -> Zp64 {
Self::new(p)
}
fn get_prime(&self) -> u64 {
self.p
}
#[inline(always)]
fn to_element(&self, a: u64) -> FiniteFieldElement<u64> {
FiniteFieldElement((((a as u128) << 64) % self.p as u128) as u64)
}
#[inline(always)]
fn from_element(&self, a: &FiniteFieldElement<u64>) -> u64 {
self.mul(a, &FiniteFieldElement(1)).0
}
}
impl<UField: Display> Display for FiniteField<UField> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
write!(f, " % {}", self.p)
}
}
impl Ring for Zp64 {
type Element = FiniteFieldElement<u64>;
#[inline(always)]
fn add(&self, a: &Self::Element, b: &Self::Element) -> Self::Element {
let (r, overflow) = a.0.overflowing_add(b.0);
if overflow || r >= self.p {
FiniteFieldElement(r.wrapping_sub(self.p))
} else {
FiniteFieldElement(r)
}
}
#[inline(always)]
fn sub(&self, a: &Self::Element, b: &Self::Element) -> Self::Element {
if a.0 >= b.0 {
FiniteFieldElement(a.0 - b.0)
} else {
FiniteFieldElement(a.0 + (self.p - b.0))
}
}
#[inline(always)]
fn mul(&self, a: &Self::Element, b: &Self::Element) -> Self::Element {
let t = a.0 as u128 * b.0 as u128;
let m = (t as u64).wrapping_mul(self.m);
let u = ((t.wrapping_add(m as u128 * self.p as u128)) >> 64) as u64;
if u < (t >> 64) as u64 {
return FiniteFieldElement(u.wrapping_sub(self.p));
}
if u >= self.p {
FiniteFieldElement(u - self.p)
} else {
FiniteFieldElement(u)
}
}
#[inline]
fn add_assign(&self, a: &mut Self::Element, b: &Self::Element) {
*a = self.add(a, b);
}
#[inline]
fn sub_assign(&self, a: &mut Self::Element, b: &Self::Element) {
*a = self.sub(a, b);
}
#[inline]
fn mul_assign(&self, a: &mut Self::Element, b: &Self::Element) {
*a = self.mul(a, b);
}
fn add_mul_assign(&self, a: &mut Self::Element, b: &Self::Element, c: &Self::Element) {
self.add_assign(a, &self.mul(b, c));
}
fn sub_mul_assign(&self, a: &mut Self::Element, b: &Self::Element, c: &Self::Element) {
self.sub_assign(a, &self.mul(b, c));
}
#[inline]
fn neg(&self, a: &Self::Element) -> Self::Element {
if a.0 == 0 {
*a
} else {
FiniteFieldElement(self.p - a.0)
}
}
#[inline]
fn zero(&self) -> Self::Element {
FiniteFieldElement(0)
}
#[inline]
fn one(&self) -> Self::Element {
self.one
}
#[inline]
fn nth(&self, n: Integer) -> Self::Element {
n.to_finite_field(self)
}
#[inline]
fn pow(&self, b: &Self::Element, mut e: u64) -> Self::Element {
if e >= self.get_prime() as u64 - 1 {
e = e % (self.get_prime() as u64 - 1);
}
if e == 0 {
return self.one();
}
let mut x = *b;
let mut y = self.one();
while e != 1 {
if e % 2 == 1 {
y = self.mul(&y, &x);
}
x = self.mul(&x, &x);
e /= 2;
}
self.mul(&x, &y)
}
#[inline]
fn is_zero(&self, a: &Self::Element) -> bool {
a.0 == 0
}
#[inline]
fn is_one(&self, a: &Self::Element) -> bool {
a == &self.one
}
fn one_is_gcd_unit() -> bool {
true
}
fn characteristic(&self) -> Integer {
self.get_prime().into()
}
fn size(&self) -> Integer {
self.get_prime().into()
}
fn try_div(&self, a: &Self::Element, b: &Self::Element) -> Option<Self::Element> {
if self.is_zero(b) {
None
} else {
Some(self.div(a, b))
}
}
fn sample(&self, rng: &mut impl rand::RngCore, range: (i64, i64)) -> Self::Element {
let r = rng.gen_range(range.0.max(0)..range.1.min(self.p.min(i64::MAX as u64) as i64));
FiniteFieldElement(r as u64)
}
fn format<W: std::fmt::Write>(
&self,
element: &Self::Element,
opts: &PrintOptions,
state: PrintState,
f: &mut W,
) -> Result<bool, Error> {
if opts.symmetric_representation_for_finite_field {
Z.format(&self.to_symmetric_integer(element), opts, state, f)
} else {
Z.format(&self.from_element(element).into(), opts, state, f)
}
}
}
impl EuclideanDomain for Zp64 {
#[inline]
fn rem(&self, _: &Self::Element, _: &Self::Element) -> Self::Element {
FiniteFieldElement(0)
}
#[inline]
fn quot_rem(&self, a: &Self::Element, b: &Self::Element) -> (Self::Element, Self::Element) {
(self.mul(a, &self.inv(b)), FiniteFieldElement(0))
}
#[inline]
fn gcd(&self, _: &Self::Element, _: &Self::Element) -> Self::Element {
self.one()
}
}
impl Field for Zp64 {
#[inline]
fn div(&self, a: &Self::Element, b: &Self::Element) -> Self::Element {
self.mul(a, &self.inv(b))
}
#[inline]
fn div_assign(&self, a: &mut Self::Element, b: &Self::Element) {
*a = self.mul(a, &self.inv(b));
}
fn inv(&self, a: &Self::Element) -> Self::Element {
assert!(a.0 != 0, "0 is not invertible");
let x_mont = self
.mul(&self.mul(a, &FiniteFieldElement(1)), &FiniteFieldElement(1))
.0;
let mut u1: u64 = 1;
let mut u3 = x_mont;
let mut v1: u64 = 0;
let mut v3 = self.p;
let mut even_iter: bool = true;
while v3 != 0 {
let q = u3 / v3;
let t3 = u3 % v3;
let t1 = u1 + q * v1;
u1 = v1;
v1 = t1;
u3 = v3;
v3 = t3;
even_iter = !even_iter;
}
debug_assert!(u3 == 1);
if even_iter {
FiniteFieldElement(u1)
} else {
FiniteFieldElement(self.p - u1)
}
}
}
pub type Z2 = FiniteField<Two>;
pub const Z2: FiniteField<Two> = Z2::new();
#[derive(Copy, Clone, Hash, Eq, PartialEq)]
pub struct Two(pub(crate) u8);
impl Default for Z2 {
fn default() -> Self {
Self::new()
}
}
impl Z2 {
pub const fn new() -> Z2 {
FiniteField {
p: Two(2),
m: Two(2),
one: FiniteFieldElement(Two(1)),
}
}
pub fn get_prime() -> Two {
Two(2)
}
}
impl Two {
pub const fn new() -> Two {
Two(2)
}
}
impl Default for Two {
fn default() -> Self {
Two(2)
}
}
impl Deref for Two {
type Target = u8;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl std::fmt::Debug for Two {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(&self.0, f)
}
}
impl Display for Two {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
impl FiniteFieldWorkspace for Two {
fn get_large_prime() -> Two {
Two(2)
}
fn try_from_integer(n: Integer) -> Option<Self> {
if n == 0 {
Some(Two(0))
} else if n == 1 {
Some(Two(1))
} else if n == 2 {
Some(Two(2))
} else {
None
}
}
fn to_integer(&self) -> Integer {
self.0.into()
}
}
impl FiniteFieldCore<Two> for FiniteField<Two> {
fn new(p: Two) -> Self {
FiniteField {
p,
m: p,
one: FiniteFieldElement(Two(1)),
}
}
fn get_prime(&self) -> Two {
Two(2)
}
fn to_element(&self, a: Two) -> Self::Element {
a.0 % 2
}
fn from_element(&self, a: &Self::Element) -> Two {
Two(*a)
}
}
impl Ring for FiniteField<Two> {
type Element = u8;
#[inline(always)]
fn add(&self, a: &Self::Element, b: &Self::Element) -> Self::Element {
a ^ b
}
#[inline(always)]
fn sub(&self, a: &Self::Element, b: &Self::Element) -> Self::Element {
a ^ b
}
#[inline(always)]
fn mul(&self, a: &Self::Element, b: &Self::Element) -> Self::Element {
*a * *b
}
#[inline]
fn add_assign(&self, a: &mut Self::Element, b: &Self::Element) {
*a = self.add(a, b);
}
#[inline]
fn sub_assign(&self, a: &mut Self::Element, b: &Self::Element) {
*a = self.sub(a, b);
}
#[inline]
fn mul_assign(&self, a: &mut Self::Element, b: &Self::Element) {
*a = self.mul(a, b);
}
fn add_mul_assign(&self, a: &mut Self::Element, b: &Self::Element, c: &Self::Element) {
self.add_assign(a, &self.mul(b, c));
}
fn sub_mul_assign(&self, a: &mut Self::Element, b: &Self::Element, c: &Self::Element) {
self.sub_assign(a, &self.mul(b, c));
}
#[inline]
fn neg(&self, a: &Self::Element) -> Self::Element {
*a
}
#[inline]
fn zero(&self) -> Self::Element {
0
}
#[inline]
fn one(&self) -> Self::Element {
1
}
#[inline]
fn nth(&self, n: Integer) -> Self::Element {
(n % 2i32).to_i64().unwrap() as u8
}
#[inline]
fn pow(&self, b: &Self::Element, e: u64) -> Self::Element {
if e == 0 {
1
} else {
*b
}
}
#[inline]
fn is_zero(&self, a: &Self::Element) -> bool {
*a == 0
}
#[inline]
fn is_one(&self, a: &Self::Element) -> bool {
*a == 1
}
fn one_is_gcd_unit() -> bool {
true
}
fn characteristic(&self) -> Integer {
2.into()
}
fn size(&self) -> Integer {
2.into()
}
fn try_div(&self, a: &Self::Element, b: &Self::Element) -> Option<Self::Element> {
if *b == 0 {
None
} else {
Some(*a)
}
}
fn sample(&self, rng: &mut impl rand::RngCore, _range: (i64, i64)) -> Self::Element {
rng.gen_range(0..2)
}
fn format<W: std::fmt::Write>(
&self,
element: &Self::Element,
opts: &PrintOptions,
state: PrintState,
f: &mut W,
) -> Result<bool, Error> {
if opts.symmetric_representation_for_finite_field {
Z.format(&self.to_symmetric_integer(element), opts, state, f)
} else {
Z.format(&self.from_element(element).0.into(), opts, state, f)
}
}
}
impl EuclideanDomain for FiniteField<Two> {
#[inline]
fn rem(&self, _: &Self::Element, _: &Self::Element) -> Self::Element {
0
}
#[inline]
fn quot_rem(&self, a: &Self::Element, b: &Self::Element) -> (Self::Element, Self::Element) {
(self.mul(a, &self.inv(b)), 0)
}
#[inline]
fn gcd(&self, _: &Self::Element, _: &Self::Element) -> Self::Element {
1
}
}
impl Field for FiniteField<Two> {
#[inline]
fn div(&self, a: &Self::Element, b: &Self::Element) -> Self::Element {
self.mul(a, &self.inv(b))
}
#[inline]
fn div_assign(&self, a: &mut Self::Element, b: &Self::Element) {
*a = self.mul(a, &self.inv(b));
}
fn inv(&self, a: &Self::Element) -> Self::Element {
assert!(*a != 0, "0 is not invertible");
1
}
}
#[derive(Copy, Clone, Hash, Eq, PartialEq)]
pub struct Mersenne64(u64);
impl Default for Mersenne64 {
fn default() -> Self {
Self::new()
}
}
impl Mersenne64 {
pub fn new() -> Self {
Mersenne64(Self::PRIME)
}
const SHIFT: u8 = 61;
pub const PRIME: u64 = (1 << Mersenne64::SHIFT) - 1;
}
impl std::fmt::Debug for Mersenne64 {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(&self.0, f)
}
}
impl Display for Mersenne64 {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
impl FiniteFieldWorkspace for Mersenne64 {
fn get_large_prime() -> Mersenne64 {
Mersenne64(Self::PRIME)
}
fn try_from_integer(n: Integer) -> Option<Self> {
if n <= Self::PRIME {
match n {
Integer::Natural(s) => {
if s >= 0 {
Some(Mersenne64(s as u64))
} else {
None
}
}
Integer::Double(d) => {
if d >= 0 && d <= Self::PRIME as i128 {
Some(Mersenne64(d as u64))
} else {
None
}
}
_ => None,
}
} else {
None
}
}
fn to_integer(&self) -> Integer {
self.0.into()
}
}
impl FiniteFieldCore<Mersenne64> for FiniteField<Mersenne64> {
fn new(p: Mersenne64) -> Self {
FiniteField {
p,
m: p,
one: FiniteFieldElement(Mersenne64(1)),
}
}
fn get_prime(&self) -> Mersenne64 {
Mersenne64(Mersenne64::PRIME)
}
fn to_element(&self, a: Mersenne64) -> Self::Element {
if a.0 >= Mersenne64::PRIME {
a.0 - Mersenne64::PRIME
} else {
a.0
}
}
fn from_element(&self, a: &Self::Element) -> Mersenne64 {
Mersenne64(*a)
}
}
impl Ring for FiniteField<Mersenne64> {
type Element = u64;
#[inline(always)]
fn add(&self, a: &Self::Element, b: &Self::Element) -> Self::Element {
let mut sum = a + b; if sum >= Mersenne64::PRIME {
sum -= Mersenne64::PRIME;
}
sum
}
#[inline(always)]
fn sub(&self, a: &Self::Element, b: &Self::Element) -> Self::Element {
if *a >= *b {
*a - *b
} else {
*a + (Mersenne64::PRIME - *b)
}
}
#[inline(always)]
fn mul(&self, a: &Self::Element, b: &Self::Element) -> Self::Element {
let v = *a as u128 * *b as u128;
let q = (v >> Mersenne64::SHIFT) as u64;
let r = (v as u64 & Mersenne64::PRIME) + (q & Mersenne64::PRIME);
if r >= Mersenne64::PRIME {
r - Mersenne64::PRIME
} else {
r
}
}
#[inline]
fn add_assign(&self, a: &mut Self::Element, b: &Self::Element) {
*a = self.add(a, b);
}
#[inline]
fn sub_assign(&self, a: &mut Self::Element, b: &Self::Element) {
*a = self.sub(a, b);
}
#[inline]
fn mul_assign(&self, a: &mut Self::Element, b: &Self::Element) {
*a = self.mul(a, b);
}
fn add_mul_assign(&self, a: &mut Self::Element, b: &Self::Element, c: &Self::Element) {
self.add_assign(a, &self.mul(b, c));
}
fn sub_mul_assign(&self, a: &mut Self::Element, b: &Self::Element, c: &Self::Element) {
self.sub_assign(a, &self.mul(b, c));
}
#[inline]
fn neg(&self, a: &Self::Element) -> Self::Element {
if *a == 0 {
*a
} else {
Mersenne64::PRIME - a
}
}
#[inline]
fn zero(&self) -> Self::Element {
0
}
#[inline]
fn one(&self) -> Self::Element {
1
}
#[inline]
fn nth(&self, n: Integer) -> Self::Element {
self.to_element(Mersenne64(n.to_finite_field(self)))
}
#[inline]
fn pow(&self, b: &Self::Element, mut e: u64) -> Self::Element {
if e >= self.get_prime().0 - 1 {
e = e % (self.get_prime().0 - 1);
}
if e == 0 {
return self.one();
}
let mut x = *b;
let mut y = self.one();
while e != 1 {
if e % 2 == 1 {
y = self.mul(&y, &x);
}
x = self.mul(&x, &x);
e /= 2;
}
self.mul(&x, &y)
}
#[inline]
fn is_zero(&self, a: &Self::Element) -> bool {
*a == 0
}
#[inline]
fn is_one(&self, a: &Self::Element) -> bool {
*a == 1
}
fn one_is_gcd_unit() -> bool {
true
}
fn characteristic(&self) -> Integer {
Mersenne64::PRIME.into()
}
fn size(&self) -> Integer {
Mersenne64::PRIME.into()
}
fn try_div(&self, a: &Self::Element, b: &Self::Element) -> Option<Self::Element> {
if self.is_zero(b) {
None
} else {
Some(self.div(a, b))
}
}
fn sample(&self, rng: &mut impl rand::RngCore, range: (i64, i64)) -> Self::Element {
let r = rng
.gen_range(range.0.max(0)..range.1.min(Mersenne64::PRIME.min(i64::MAX as u64) as i64));
r as u64
}
fn format<W: std::fmt::Write>(
&self,
element: &Self::Element,
opts: &PrintOptions,
state: PrintState,
f: &mut W,
) -> Result<bool, Error> {
if opts.symmetric_representation_for_finite_field {
Z.format(&self.to_symmetric_integer(element), opts, state, f)
} else {
Z.format(&self.from_element(element).0.into(), opts, state, f)
}
}
}
impl EuclideanDomain for FiniteField<Mersenne64> {
#[inline]
fn rem(&self, _: &Self::Element, _: &Self::Element) -> Self::Element {
0
}
#[inline]
fn quot_rem(&self, a: &Self::Element, b: &Self::Element) -> (Self::Element, Self::Element) {
(self.mul(a, &self.inv(b)), 0)
}
#[inline]
fn gcd(&self, _: &Self::Element, _: &Self::Element) -> Self::Element {
1
}
}
impl Field for FiniteField<Mersenne64> {
#[inline]
fn div(&self, a: &Self::Element, b: &Self::Element) -> Self::Element {
self.mul(a, &self.inv(b))
}
#[inline]
fn div_assign(&self, a: &mut Self::Element, b: &Self::Element) {
*a = self.mul(a, &self.inv(b));
}
fn inv(&self, a: &Self::Element) -> Self::Element {
assert!(*a != 0, "0 is not invertible");
let mut u1: u64 = 1;
let mut u3 = *a;
let mut v1: u64 = 0;
let mut v3 = Mersenne64::PRIME;
let mut even_iter: bool = true;
while v3 != 0 {
let q = u3 / v3;
let t3 = u3 % v3;
let t1 = u1 + q * v1;
u1 = v1;
v1 = t1;
u3 = v3;
v3 = t3;
even_iter = !even_iter;
}
debug_assert!(u3 == 1);
if even_iter {
u1
} else {
Mersenne64::PRIME - u1
}
}
}
impl FiniteFieldWorkspace for Integer {
fn get_large_prime() -> Integer {
Integer::Double(85070591730234615865843651857942052871)
}
fn try_from_integer(n: Integer) -> Option<Self> {
Some(n)
}
fn to_integer(&self) -> Integer {
self.clone()
}
}
impl FiniteFieldCore<Integer> for FiniteField<Integer> {
fn new(m: Integer) -> FiniteField<Integer> {
FiniteField {
p: m.clone(),
m: Integer::one(),
one: FiniteFieldElement(Integer::one()),
}
}
#[inline]
fn get_prime(&self) -> Integer {
self.p.clone()
}
fn to_element(&self, a: Integer) -> Integer {
a.symmetric_mod(&self.p)
}
fn from_element(&self, a: &Integer) -> Integer {
if a.is_negative() {
a.clone() + &self.p
} else {
a.clone()
}
}
}
impl FiniteField<Integer> {
#[inline(always)]
fn normalize(&self, mut c: Integer) -> Integer {
self.normalize_mut(&mut c);
c
}
#[inline(always)]
fn normalize_mut(&self, c: &mut Integer) {
let two_c = &*c + &*c;
if two_c.is_negative() {
if -two_c >= self.p {
*c += &self.p;
}
} else {
if two_c >= self.p {
*c -= &self.p;
}
}
}
pub fn try_inv(&self, a: &Integer) -> Option<Integer> {
if a.is_zero() {
return None;
}
let mut u1 = Integer::one();
let mut u3 = a.clone();
let mut v1 = Integer::zero();
let mut v3 = self.get_prime();
let mut even_iter: bool = true;
while !v3.is_zero() {
let (q, t3) = Z.quot_rem(&u3, &v3);
let t1 = &u1 + &(&q * &v1);
u1 = v1;
v1 = t1;
u3 = v3;
v3 = t3;
even_iter = !even_iter;
}
if !u3.is_one() {
return None;
}
if even_iter {
Some(u1)
} else {
Some(&self.p - &u1)
}
}
}
impl Ring for FiniteField<Integer> {
type Element = Integer;
fn add(&self, a: &Self::Element, b: &Self::Element) -> Self::Element {
self.normalize(a + b)
}
fn sub(&self, a: &Self::Element, b: &Self::Element) -> Self::Element {
self.normalize(a - b)
}
fn mul(&self, a: &Self::Element, b: &Self::Element) -> Self::Element {
(a * b).symmetric_mod(&self.p)
}
fn add_assign(&self, a: &mut Self::Element, b: &Self::Element) {
*a += b;
self.normalize_mut(a);
}
fn sub_assign(&self, a: &mut Self::Element, b: &Self::Element) {
*a -= b;
self.normalize_mut(a);
}
fn mul_assign(&self, a: &mut Self::Element, b: &Self::Element) {
*a = self.mul(a, b);
}
fn add_mul_assign(&self, a: &mut Self::Element, b: &Self::Element, c: &Self::Element) {
self.add_assign(a, &self.mul(b, c));
}
fn sub_mul_assign(&self, a: &mut Self::Element, b: &Self::Element, c: &Self::Element) {
self.sub_assign(a, &self.mul(b, c));
}
fn neg(&self, a: &Self::Element) -> Self::Element {
a.neg()
}
fn zero(&self) -> Self::Element {
Integer::zero()
}
fn one(&self) -> Self::Element {
Integer::one()
}
#[inline]
fn nth(&self, n: Integer) -> Self::Element {
n.symmetric_mod(&self.p)
}
fn pow(&self, b: &Self::Element, e: u64) -> Self::Element {
b.pow(e).symmetric_mod(&self.p)
}
fn is_zero(&self, a: &Self::Element) -> bool {
a.is_zero()
}
fn is_one(&self, a: &Self::Element) -> bool {
a.is_one()
}
fn one_is_gcd_unit() -> bool {
true
}
fn characteristic(&self) -> Integer {
self.get_prime()
}
fn size(&self) -> Integer {
self.get_prime()
}
fn try_div(&self, a: &Self::Element, b: &Self::Element) -> Option<Self::Element> {
if let Some(r) = self.try_inv(b) {
Some(self.mul(a, &r))
} else {
None
}
}
fn sample(&self, rng: &mut impl rand::RngCore, range: (i64, i64)) -> Self::Element {
Z.sample(rng, range).symmetric_mod(&self.p)
}
fn format<W: std::fmt::Write>(
&self,
element: &Self::Element,
opts: &PrintOptions,
state: PrintState,
f: &mut W,
) -> Result<bool, Error> {
if opts.symmetric_representation_for_finite_field {
Z.format(&self.to_symmetric_integer(element), opts, state, f)
} else {
Z.format(&self.from_element(element).into(), opts, state, f)
}
}
}
impl EuclideanDomain for FiniteField<Integer> {
fn rem(&self, _: &Self::Element, _: &Self::Element) -> Self::Element {
Integer::zero()
}
fn quot_rem(&self, a: &Self::Element, b: &Self::Element) -> (Self::Element, Self::Element) {
(self.mul(a, &self.inv(b)), Integer::zero())
}
fn gcd(&self, _: &Self::Element, _: &Self::Element) -> Self::Element {
Integer::one()
}
}
impl Field for FiniteField<Integer> {
#[inline]
fn div(&self, a: &Self::Element, b: &Self::Element) -> Self::Element {
self.mul(a, &self.inv(b))
}
#[inline]
fn div_assign(&self, a: &mut Self::Element, b: &Self::Element) {
*a = self.mul(a, &self.inv(b));
}
fn inv(&self, a: &Self::Element) -> Self::Element {
if let Some(r) = self.try_inv(a) {
r
} else {
panic!("{} is not invertible mod {}", a, self.p);
}
}
}
pub fn is_prime_u64(n: u64) -> bool {
let witnesses: [u64; 7] = [2, 325, 9375, 28178, 450775, 9780504, 1795265022];
if n < 2 {
return false;
}
if n % 2 == 0 {
return n == 2;
}
let mut s = 0;
let mut d = n - 1;
while d % 2 == 0 {
d /= 2;
s += 1;
}
let f = Zp64::new(n);
let neg_one = FiniteFieldElement(n.wrapping_sub(f.one().0));
'test: for a in witnesses {
let a = f.to_element(a);
if a.0 == 0 {
continue;
}
let mut x = f.pow(&a, d);
if x == f.one() || x == neg_one {
continue;
}
for _ in 0..s {
x = f.mul(&x, &x);
if x == f.one() {
return false;
}
if x == neg_one {
continue 'test;
}
}
return false;
}
true
}
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
pub struct PrimeIteratorU64 {
current_number: u64,
}
impl PrimeIteratorU64 {
pub fn new(start: u64) -> PrimeIteratorU64 {
PrimeIteratorU64 {
current_number: start.max(1),
}
}
}
impl Iterator for PrimeIteratorU64 {
type Item = u64;
fn next(&mut self) -> Option<u64> {
while self.current_number < u64::MAX {
self.current_number += 1;
if is_prime_u64(self.current_number) {
return Some(self.current_number);
}
}
None
}
}
#[cfg(test)]
mod test {
use super::{FiniteFieldCore, Zp};
use crate::domains::Ring;
#[test]
fn pow() {
let field = Zp::new(31);
let mut q = field.one();
let x = field.to_element(3);
for i in 0..100 {
let r = field.pow(&x, i);
assert_eq!(r, q);
q = field.mul(&q, &x);
}
}
}