Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Scalar type for finite field example #11

Closed
wants to merge 10 commits into from
Closed
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
1 change: 1 addition & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
push:
branches:
- master
- clean
tags:
- 'v*.*.*'
pull_request:
Expand Down
72 changes: 68 additions & 4 deletions examples/finite_prime_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,64 @@ use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, Sub, Su
/// We take here, as an example, the skeleton implementation of a finite field.
/// Where `L` number of words and `D` number of words are used to represent the field.
/// The modulus is the order of the field, which would be prime or a prime power

#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq)]

pub struct FieldElement<const L: usize>([u64; L]);

impl<const L: usize> Zero for FieldElement<L> {
fn zero() -> Self {
Self([0; L])
}

fn is_zero(&self) -> bool {
self.0[0] == 0
}
}

impl<const L: usize> One for FieldElement<L> {
fn one() -> Self {
let mut arr = [0; L];
arr[0] = 1;
Self(arr)
}
}

impl<const L: usize> Add for FieldElement<L> {
type Output = Self;

fn add(self, rhs: Self) -> Self::Output {
let mut result = [0; L];
let mut carry = 0u64;
for (i, (&self_val, &rhs_val)) in self.0.iter().zip(rhs.0.iter()).enumerate() {
let sum = self_val as u128 + rhs_val as u128 + carry as u128;
result[i] = sum as u64;
carry = (sum >> 64) as u64;
}
Self(result)
}
}

impl<const L: usize> Mul for FieldElement<L> {
type Output = Self;

fn mul(self, rhs: Self) -> Self::Output {
let mut result = [0u64; L];
for (i, &self_val) in self.0.iter().enumerate() {
let mut carry = 0u128;
for (j, &rhs_val) in rhs.0.iter().enumerate() {
if i + j >= L {
break;
}
let prod = (self_val as u128) * (rhs_val as u128) + (result[i + j] as u128) + carry;
result[i + j] = prod as u64;
carry = prod >> 64;
}
}

Self(result)
}
}
#[derive(Clone, Copy, Debug)]
pub struct FinitePrimeField<const L: usize, const D: usize> {
modulus: [u64; L],
Expand Down Expand Up @@ -175,12 +233,18 @@ impl<const L: usize, const D: usize> AssociativeMultiplication for FinitePrimeFi
impl<const L: usize, const D: usize> Distributive for FinitePrimeField<L, D> {}

impl<const L: usize, const D: usize> FiniteField for FinitePrimeField<L, D> {
fn characteristic() -> u64 {
todo!()
type ScalarType = FieldElement<L>;

fn characteristic() -> Self::ScalarType {
// For a prime field, the characteristic is the same as the modulus
// This is a placeholder implementation
FieldElement([2; L]) // Example: characteristic 2
}

fn order() -> u64 {
todo!()
fn order() -> Self::ScalarType {
// For a prime field, the order is the same as the modulus
// This is a placeholder implementation
FieldElement([4; L]) // Example: order 4
}
}

Expand Down
70 changes: 68 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -411,8 +411,8 @@ pub trait Field: EuclideanDomain + MultiplicativeAbelianGroup {}
/// # Properties
/// - The number of elements is always a prime power p^n
pub trait FiniteField: Field {
///allos for an arbitrary size representation without specificing type
type ScalarType: Clone + PartialOrd + Zero + One + Debug;
///Allows for an arbitrary size representation without specificing type
type ScalarType: Clone + PartialOrd + Zero + One;

/// Returns the characteristic of the field.
fn characteristic() -> Self::ScalarType;
Expand Down Expand Up @@ -518,6 +518,72 @@ pub trait FieldExtensionTower: FieldExtension {
fn extension_degree(i: usize) -> usize;
}


/// Represents a join-semilattice
/// //a Partially ordered set which admits all finite joins, or equivalently which admits a bottom element ⊥ and binary joins a ∨ b
/// # Mathematical Definition
/// A join-semilattice, is a partially ordered set where any two elements have a unique least upper bound.
///
/// Properties:
/// * ∨ (join) is idempotent, commutative, and associative
pub trait JoinSemilattice: PartialOrd{
fn join(&self, other: &Self) -> Self;
}

/// Represents a meet-semilattice
/// # Mathematical Definition
/// a meet-semilattice aka lower semilattice is Partially ordered set which admits all finite meets, including a top element ⊤ and binary meets ∧
/// OR
/// meet-semilattice aka lower semilattice is a partially ordered set which has a meet (or greatest lower bound) for any nonempty finite subset.
/// Every join-semilattice is a meet-semilattice in the inverse order and vice versa.

pub trait MeetSemilattice: PartialOrd{
fn meet(&self, other: &Self) -> Self;
}


/// Represents a Lattice
/// # Mathematical Definition
/// A lattice is a partially ordered set that is both a join-semilattice and a meet-semilattice.
/// Properties:
/// * ∧ and ∨ are each idempotent, commutative, and associative
/// * Absorption laws:
/// - a∨(a∧b)=a
/// - a∧(a∨b)=a
pub trait Lattice: JoinSemilattice + MeetSemilattice{}

pub trait DistributiveLattice: Lattice{}

pub trait ModularLattice: Lattice{}

/// Represents a bounded lattice
/// # Mathematical Definition
/// A bounded lattice is a lattice that has a top(greatest element) and bottom (least element) / a partially ordered set that has top and bottom elements
/// Properties:
/// * ⊤ (top) is the identity element for ∧ (meet)
/// * ⊥ (bottom) is the identity element for ∨ (join)

pub trait BoundedLattice: Lattice{
/// Returns the top of the lattice
fn top() -> Self;

/// Returns the bottom of the lattice
fn bottom() -> Self;
}

/// Represents a complemented lattice
/// # Mathematical definition
/// A Complemented lattice is a lattice where all elements have atleast one complement
pub trait ComplementedLattice: BoundedLattice{
///Checks if a given element is a valid complement
fn is_complement(&self, other: &Self) -> bool{
self.join(other) == Self::top() && self.meet(other) == Self::bottom()
}
/// Returns a complement of the element
fn complement(&self) -> Self;

}

// Blanket implementations for basic operation traits
impl<T: Add<Output = T>> ClosedAdd for T {}
impl<T: for<'a> Add<&'a T, Output = T>> ClosedAddRef for T {}
Expand Down