Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions fp/src/_doctest_support.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,22 @@ pub mod _doctest_field_ops {

pub type F19_2 = FpExt<Fp19Modulus, 1, 2, 1, QuadPoly, TSQuad>;
}

pub mod _doctest_f2_ext {
use crate::f2_ext::{BinaryIrreducible, F2Ext};
use crypto_bigint::Uint;

pub struct F4Poly;

impl BinaryIrreducible<1> for F4Poly {
fn modulus() -> Uint<1> {
Uint::<1>::from_u64(0b111) // x^2 + x + 1
}

fn degree() -> usize {
2usize
}
}

pub type F4 = F2Ext<1, F4Poly>;
}
56 changes: 45 additions & 11 deletions fp/src/f2_element.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
//! The binary field $\mathbb{F}_2 = \mathbb{Z} / 2\mathbb{Z}$
//!
//! # Examples
//!
//! ```
//! use fp::f2_element::F2Element;
//! use fp::field_ops::FieldOps;
//! use crypto_bigint::Uint;
//!
//! let x = F2Element::from_u64(0);
//! let y = F2Element::from_u64(1);
//! assert!(bool::from(x.is_zero()));
//! assert!(bool::from(y.is_one()));
//! assert_eq!(F2Element::characteristic(), [2]);
//! ```

use crate::field_ops::FieldFromRepr;
use crate::field_ops::{FieldOps, FieldRandom};
Expand Down Expand Up @@ -28,15 +42,6 @@ impl F2Element {
};

/// Create a new element of $\mathbb{F}_2$ from a `Uint<1>`
///
/// # Arguments
///
/// * `x` - An integer (type: `Uint<1>`)
///
/// # Returns
///
/// An element of $\mathbb{F}_2$, the reduction of `x` mod 2
/// (type: `Self`)
fn new(x: Uint<1>) -> Self {
Self {
value: x & Uint::<1>::ONE,
Expand All @@ -53,11 +58,22 @@ impl F2Element {
///
/// An element of $\mathbb{F}_2$, the reduction of `x` mod 2
/// (type: `Self`)
///
/// # Examples
///
/// ```
/// # use fp::f2_element::F2Element;
/// # use fp::field_ops::FieldOps;
/// # use crypto_bigint::Uint;
/// let x = F2Element::from_u64(1);
/// let y = F2Element::from_u64(7);
/// assert_eq!(x, y);
/// ```
pub fn from_u64(x: u64) -> Self {
Self::new(Uint::from(x & 1))
}

/// Get the `Uint<1>` from an element of $\mathbb{F}_2$
/// Get the `Uint<1>` from an element of $\mathbb{F}_2$ i.e.,
///
/// # Arguments
///
Expand All @@ -67,6 +83,15 @@ impl F2Element {
///
/// The integer in $\{ 0, 1 \}$ reducing to `x` mod 2 (type:
/// `Uint<1>`)
///
/// ```
/// # use fp::f2_element::F2Element;
/// # use fp::field_ops::FieldOps;
/// # use crypto_bigint::Uint;
/// let x = F2Element::from_u64(7);
/// let my_int = x.value();
/// assert_eq!(my_int, Uint::<1>::from_u64(1));
/// ```
pub fn value(&self) -> Uint<1> {
self.value
}
Expand All @@ -80,7 +105,16 @@ impl F2Element {
/// # Returns
///
/// The integer in $\{ 0, 1 \}$ reducing to `x` mod 2 (type:
/// `u8`)
/// `Uint<1>`)
///
/// ```
/// # use fp::f2_element::F2Element;
/// # use fp::field_ops::FieldOps;
/// # use crypto_bigint::Uint;
/// let x = F2Element::from_u64(45);
/// let my_int = x.as_u8();
/// assert_eq!(my_int, 1_u8);
/// ```
pub fn as_u8(&self) -> u8 {
self.value.to_words()[0] as u8
}
Expand Down
193 changes: 178 additions & 15 deletions fp/src/f2_ext.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,38 @@
//! Generic binary fields $\mathbb{F}\_{2^m} = \mathbb{F}\_2\[x\] / (f(x))$
//!
//! # Examples
//!
//! ```
//! use crypto_bigint::Uint;
//! use fp::f2_element::F2Element;
//! use fp::f2_ext::{BinaryIrreducible, F2Ext};
//! use fp::field_ops::FieldOps;
//!
//! /* Make the finite field F_4 */
//! struct F4Poly;
//! impl BinaryIrreducible<1> for F4Poly {
//! fn modulus() -> Uint<1> {
//! Uint::<1>::from_u64(0b111) // x^2 + x + 1
//! }
//!
//! fn degree() -> usize {
//! 2usize
//! }
//! }
//! type F4 = F2Ext<1, F4Poly>;
//!
//! /* Elements are written down by binary integers */
//! let zero = F4::from_u64(0);
//! let one = F4::from_u64(1);
//! let a = F4::from_u64(0b11);
//! let b = F4::from_u64(0b10);
//!
//! let also_zero = F4::from_u64(0b111); // x^2 + x + 1 = 0
//! let also_one = F4::from_u64(0b1000); // x^3 = x*x^2 = x^2 + x = 1
//! assert_eq!(also_zero, zero);
//! assert_eq!(also_one, one);
//! assert_eq!(a.mul(&b), one);
//! ```

use crate::field_ops::{FieldFromRepr, FieldOps, FieldRandom};
use core::ops::{Add, Mul, Neg, Sub};
Expand All @@ -21,9 +55,10 @@ use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
/// # Examples
///
/// ```
/// # use crypto_bigint::Uint;
/// # use fp::f2_element::F2Element;
/// # use fp::f2_ext::{BinaryIrreducible, F2Ext};
/// use crypto_bigint::Uint;
/// use fp::f2_element::F2Element;
/// use fp::f2_ext::{BinaryIrreducible, F2Ext};
///
/// struct MyPoly;
///
/// impl BinaryIrreducible<1> for MyPoly {
Expand Down Expand Up @@ -63,11 +98,25 @@ pub trait BinaryIrreducible<const LIMBS: usize>: 'static {
/// # Examples
///
/// ```
/// # use crypto_bigint::Uint;
/// # use fp::f2_element::F2Element;
/// # use fp::f2_ext::{BinaryIrreducible, F2Ext};
/// struct F2511Poly;
/// use crypto_bigint::Uint;
/// use fp::f2_element::F2Element;
/// use fp::f2_ext::{BinaryIrreducible, F2Ext};
///
/// /* Make the finite field F_4 */
/// struct F4Poly;
/// impl BinaryIrreducible<1> for F4Poly {
/// fn modulus() -> Uint<1> {
/// Uint::<1>::from_u64(0b111) // x^2 + x + 1
/// }
///
/// fn degree() -> usize {
/// 2usize
/// }
/// }
/// type F4 = F2Ext<1, F4Poly>;
///
/// /* Make the finite field F_{2^511} */
/// struct F2511Poly;
/// impl BinaryIrreducible<8> for F2511Poly {
/// fn modulus() -> Uint<8> {
/// let one = Uint::<8>::from_u64(1);
Expand All @@ -78,8 +127,7 @@ pub trait BinaryIrreducible<const LIMBS: usize>: 'static {
/// 511
/// }
/// }
///
/// type GF2_511 = F2Ext<8, F2511Poly>;
/// type F2_511 = F2Ext<8, F2511Poly>;
/// ```
pub struct F2Ext<const LIMBS: usize, P>
where
Expand All @@ -98,30 +146,145 @@ impl<const LIMBS: usize, P> F2Ext<LIMBS, P>
where
P: BinaryIrreducible<LIMBS>,
{
/// Make an element from the limbs
pub fn new(x: Uint<LIMBS>) -> Self {
/// Make an element of the extension from the limbs
///
/// # Arguments
///
/// * `a` - An integer written in binary as $a_0 \dots a_{64 *
/// \texttt{LIMBS}}$ and padded with 0s if nessicary (type:
/// `Uint<LIMBS>`).
///
/// # Returns
///
/// The element $\sum_{i=0}^M a_i x^i \in \mathbb{F}\_{2}\[x\] /
/// (f(x)) = \mathbb{F}\_{2^M}$ (type: `Self`).
///
/// # Examples
///
/// ```
/// # use fp::_doctest_support::_doctest_f2_ext::*;
/// # use crypto_bigint::Uint;
/// # use fp::field_ops::FieldOps;
/// let a = F4::new(Uint::<1>::from_u64(0b111)); // x^2 + x + 1 should be zero
/// let b = F4::new(Uint::<1>::from_u64(0b11)); // x + 1 = x^2
/// let c = F4::new(Uint::<1>::from_u64(0b100)); // x^2 = x + 1
/// let d = F4::new(Uint::<1>::from_u64(0b1000)); // x^3 = x^2 * x = x^2 + x = 1
/// assert!(bool::from(a.is_zero()));
/// assert_eq!(b, c);
/// assert!(bool::from(d.is_one()));
/// ```
pub fn new(a: Uint<LIMBS>) -> Self {
Self {
value: reduce::<LIMBS, P>(x),
value: reduce::<LIMBS, P>(a),
_phantom: PhantomData,
}
}

/// Make an element from a `u64`
/// Make an element of the extension from a `u64`
///
/// # Arguments
///
/// * `a` - An integer written in binary as $a_0 \dots a_{64}$ and
/// padded with 0s to 64 bits if nessicary (type: `u64`).
///
/// # Returns
///
/// The element $\sum_{i=0}^{64} a_i x^i \in \mathbb{F}\_{2}\[x\] /
/// (f(x)) = \mathbb{F}\_{2^M}$ (type: `Self`).
///
/// # Examples
///
/// ```
/// # use fp::_doctest_support::_doctest_f2_ext::*;
/// # use crypto_bigint::Uint;
/// # use fp::field_ops::FieldOps;
/// let a = F4::from_u64(0b111); // x^2 + x + 1 should be zero
/// let b = F4::from_u64(0b11); // x + 1 should be x^2
/// let c = F4::from_u64(0b100); // x + 1 should be x^2
/// let d = F4::from_u64(0b1000); // x^3 = x^2 * x = x^2 + x = 1
/// assert!(bool::from(a.is_zero()));
/// assert_eq!(b, c);
/// assert!(bool::from(d.is_one()));
/// ```
pub fn from_u64(x: u64) -> Self {
Self::new(Uint::from(x))
}

/// Make an element from a `Uint<LIMBS>`
/// Make an element of the extension from the limbs
///
/// # Arguments
///
/// * `a` - An integer written in binary as $a_0 a_1 a_2 \dots
/// a_{M}$ and then padded to the nearest 64 bits (type:
/// `Uint<LIMBS>`).
///
/// # Returns
///
/// The element $\sum_{i=0}^M a_i x^i \in \mathbb{F}\_{2}\[x\] /
/// (f(x)) = \mathbb{F}\_{2^M}$ (type: `Self`).
///
/// # Examples
///
/// ```
/// # use fp::_doctest_support::_doctest_f2_ext::*;
/// # use crypto_bigint::Uint;
/// # use fp::field_ops::FieldOps;
/// let a = F4::from_uint(Uint::<1>::from_u64(0b111)); // x^2 + x + 1 should be zero
/// let b = F4::from_uint(Uint::<1>::from_u64(0b11)); // x + 1 = x^2
/// let c = F4::from_uint(Uint::<1>::from_u64(0b100)); // x^2 = x + 1
/// let d = F4::from_uint(Uint::<1>::from_u64(0b1000)); // x^3 = x^2 * x = x^2 + x = 1
/// assert!(bool::from(a.is_zero()));
/// assert_eq!(b, c);
/// assert!(bool::from(d.is_one()));
/// ```
///
/// # Note
///
/// This is just an alias for [`F2Ext::new`]
pub fn from_uint(x: Uint<LIMBS>) -> Self {
Self::new(x)
}

/// Get a `Unit<LIMBS>` from an element
/// Get a `Uint<LIMBS>` from an element, inverting [`F2Ext::new`].
///
/// # Returns
///
/// The integer $a$ of at most $M$ bits such that applying `new`
/// gives `self`. That is, if $a$ is written in binary as $a_0
/// \dots a_M$ then $\texttt{self} = \sum_{i=0}^M a_i x^i \in
/// \mathbb{F}\_{2}\[x\] / (f(x)) = \mathbb{F}\_{2^M}$ (type:
/// `Uint<LIMBS>`).
///
/// # Examples
///
/// ```
/// # use fp::_doctest_support::_doctest_f2_ext::*;
/// # use crypto_bigint::Uint;
/// # use fp::field_ops::FieldOps;
/// let a = F4::from_uint(Uint::<1>::from_u64(0b11)); // x + 1
/// let b = F4::from_uint(Uint::<1>::from_u64(0b1000)); // x^3 = x^2 * x = x^2 + x = 1
/// assert_eq!(a.as_uint(), Uint::<1>::from_u64(0b11));
/// assert_eq!(b.as_uint(), Uint::<1>::from_u64(0b1));
/// ```
pub fn as_uint(&self) -> Uint<LIMBS> {
self.value
}

/// Get the degree of the field extension
///
/// # Returns
///
/// The degree of the field extension (type: `usize`).
///
/// # Examples
///
/// ```
/// # use fp::_doctest_support::_doctest_f2_ext::*;
/// # use crypto_bigint::Uint;
/// # use fp::field_ops::FieldOps;
/// let d = F4::degree();
/// assert_eq!(d, 2_usize);
/// ```
pub fn degree() -> usize {
P::degree()
}
Expand Down
Loading
Loading