PrimeCharacteristicRing

Trait PrimeCharacteristicRing 

Source
pub trait PrimeCharacteristicRing:
    Sized
    + Default
    + Clone
    + Add<Output = Self>
    + AddAssign
    + Sub<Output = Self>
    + SubAssign
    + Neg<Output = Self>
    + Mul<Output = Self>
    + MulAssign
    + Sum
    + Product
    + Debug {
    type PrimeSubfield: PrimeField;

    const ZERO: Self;
    const ONE: Self;
    const TWO: Self;
    const NEG_ONE: Self;
Show 32 methods // Required method fn from_prime_subfield(f: Self::PrimeSubfield) -> Self; // Provided methods fn from_bool(b: bool) -> Self { ... } fn from_u8(int: u8) -> Self { ... } fn from_u16(int: u16) -> Self { ... } fn from_u32(int: u32) -> Self { ... } fn from_u64(int: u64) -> Self { ... } fn from_u128(int: u128) -> Self { ... } fn from_usize(int: usize) -> Self { ... } fn from_i8(int: i8) -> Self { ... } fn from_i16(int: i16) -> Self { ... } fn from_i32(int: i32) -> Self { ... } fn from_i64(int: i64) -> Self { ... } fn from_i128(int: i128) -> Self { ... } fn from_isize(int: isize) -> Self { ... } fn double(&self) -> Self { ... } fn halve(&self) -> Self { ... } fn square(&self) -> Self { ... } fn cube(&self) -> Self { ... } fn xor(&self, y: &Self) -> Self { ... } fn xor3(&self, y: &Self, z: &Self) -> Self { ... } fn andn(&self, y: &Self) -> Self { ... } fn bool_check(&self) -> Self { ... } fn exp_u64(&self, power: u64) -> Self { ... } fn exp_const_u64<const POWER: u64>(&self) -> Self { ... } fn exp_power_of_2(&self, power_log: usize) -> Self { ... } fn mul_2exp_u64(&self, exp: u64) -> Self { ... } fn div_2exp_u64(&self, exp: u64) -> Self { ... } fn powers(&self) -> Powers<Self> { ... } fn shifted_powers(&self, start: Self) -> Powers<Self> { ... } fn dot_product<const N: usize>(u: &[Self; N], v: &[Self; N]) -> Self { ... } fn sum_array<const N: usize>(input: &[Self]) -> Self { ... } fn zero_vec(len: usize) -> Vec<Self> { ... }
}
Expand description

A commutative ring, R, with prime characteristic, p.

This permits elements like:

  • A single finite field element.
  • A symbolic expression which would evaluate to a field element.
  • An array of finite field elements.
  • A polynomial with coefficients in a finite field.

§Mathematical Description

Mathematically, a commutative ring is a set of objects which supports an addition-like like operation, +, and a multiplication-like operation *.

Let x, y, z denote arbitrary elements of the set.

Then, an operation is addition-like if it satisfies the following properties:

  • Commutativity => x + y = y + x
  • Associativity => x + (y + z) = (x + y) + z
  • Unit => There exists an identity element ZERO satisfying x + ZERO = x.
  • Inverses => For every x there exists a unique inverse (-x) satisfying x + (-x) = ZERO

Similarly, an operation is multiplication-like if it satisfies the following properties:

  • Commutativity => x * y = y * x
  • Associativity => x * (y * z) = (x * y) * z
  • Unit => There exists an identity element ONE satisfying x * ONE = x.
  • Distributivity => The two operations + and * must together satisfy x * (y + z) = (x * y) + (x * z)

Unlike in the addition case, we do not require inverses to exist with respect to *.

The simplest examples of commutative rings are the integers (), and the integers mod N (ℤ/N).

The characteristic of a ring is the smallest positive integer r such that 0 = r . 1 = 1 + 1 + ... + 1 (r times). For example, the characteristic of the modulo ring ℤ/N is N.

Rings with prime characteristic are particularly special due to their close relationship with finite fields.

Required Associated Constants§

Source

const ZERO: Self

The additive identity of the ring.

For every element a in the ring we require the following properties:

a + ZERO = ZERO + a = a,

a + (-a) = (-a) + a = ZERO.

Source

const ONE: Self

The multiplicative identity of the ring.

For every element a in the ring we require the following property:

a*ONE = ONE*a = a.

Source

const TWO: Self

The element in the ring given by ONE + ONE.

This is provided as a convenience as TWO occurs regularly in the proving system. This also is slightly faster than computing it via addition. Note that multiplication by TWO is discouraged. Instead of a * TWO use a.double() which will be faster.

If the field has characteristic 2 this is equal to ZERO.

Source

const NEG_ONE: Self

The element in the ring given by -ONE.

This is provided as a convenience as NEG_ONE occurs regularly in the proving system. This also is slightly faster than computing it via negation. Note that where possible NEG_ONE should be absorbed into mathematical operations. For example a - b will be faster than a + NEG_ONE * b and similarly (-b) is faster than NEG_ONE * b.

If the field has characteristic 2 this is equal to ONE.

Required Associated Types§

Source

type PrimeSubfield: PrimeField

The field ℤ/p where the characteristic of this ring is p.

Required Methods§

Source

fn from_prime_subfield(f: Self::PrimeSubfield) -> Self

Embed an element of the prime field ℤ/p into the ring R.

Given any element [r] ∈ ℤ/p, represented by an integer r between 0 and p - 1 from_prime_subfield([r]) will be equal to:

Self::ONE + ... + Self::ONE (r times)

Provided Methods§

Source

fn from_bool(b: bool) -> Self

Return Self::ONE if b is true and Self::ZERO if b is false.

Source

fn from_u8(int: u8) -> Self

Given an integer r, return the sum of r copies of ONE:

r * Self::ONE = Self::ONE + ... + Self::ONE (r times).

Note that the output only depends on r mod p.

This should be avoided in performance critical locations.

Source

fn from_u16(int: u16) -> Self

Given an integer r, return the sum of r copies of ONE:

r * Self::ONE = Self::ONE + ... + Self::ONE (r times).

Note that the output only depends on r mod p.

This should be avoided in performance critical locations.

Source

fn from_u32(int: u32) -> Self

Given an integer r, return the sum of r copies of ONE:

r * Self::ONE = Self::ONE + ... + Self::ONE (r times).

Note that the output only depends on r mod p.

This should be avoided in performance critical locations.

Source

fn from_u64(int: u64) -> Self

Given an integer r, return the sum of r copies of ONE:

r * Self::ONE = Self::ONE + ... + Self::ONE (r times).

Note that the output only depends on r mod p.

This should be avoided in performance critical locations.

Source

fn from_u128(int: u128) -> Self

Given an integer r, return the sum of r copies of ONE:

r * Self::ONE = Self::ONE + ... + Self::ONE (r times).

Note that the output only depends on r mod p.

This should be avoided in performance critical locations.

Source

fn from_usize(int: usize) -> Self

Given an integer r, return the sum of r copies of ONE:

r * Self::ONE = Self::ONE + ... + Self::ONE (r times).

Note that the output only depends on r mod p.

This should be avoided in performance critical locations.

Source

fn from_i8(int: i8) -> Self

Given an integer r, return the sum of r copies of ONE:

r * Self::ONE = Self::ONE + ... + Self::ONE (r times).

Note that the output only depends on r mod p.

This should be avoided in performance critical locations.

Source

fn from_i16(int: i16) -> Self

Given an integer r, return the sum of r copies of ONE:

r * Self::ONE = Self::ONE + ... + Self::ONE (r times).

Note that the output only depends on r mod p.

This should be avoided in performance critical locations.

Source

fn from_i32(int: i32) -> Self

Given an integer r, return the sum of r copies of ONE:

r * Self::ONE = Self::ONE + ... + Self::ONE (r times).

Note that the output only depends on r mod p.

This should be avoided in performance critical locations.

Source

fn from_i64(int: i64) -> Self

Given an integer r, return the sum of r copies of ONE:

r * Self::ONE = Self::ONE + ... + Self::ONE (r times).

Note that the output only depends on r mod p.

This should be avoided in performance critical locations.

Source

fn from_i128(int: i128) -> Self

Given an integer r, return the sum of r copies of ONE:

r * Self::ONE = Self::ONE + ... + Self::ONE (r times).

Note that the output only depends on r mod p.

This should be avoided in performance critical locations.

Source

fn from_isize(int: isize) -> Self

Given an integer r, return the sum of r copies of ONE:

r * Self::ONE = Self::ONE + ... + Self::ONE (r times).

Note that the output only depends on r mod p.

This should be avoided in performance critical locations.

Source

fn double(&self) -> Self

The elementary function double(a) = 2*a.

This function should be preferred over calling a + a or TWO * a as a faster implementation may be available for some rings. If the field has characteristic 2 then this returns 0.

Source

fn halve(&self) -> Self

The elementary function halve(a) = a/2.

§Panics

The function will panic if the field has characteristic 2.

Source

fn square(&self) -> Self

The elementary function square(a) = a^2.

This function should be preferred over calling a * a, as a faster implementation may be available for some rings.

Source

fn cube(&self) -> Self

The elementary function cube(a) = a^3.

This function should be preferred over calling a * a * a, as a faster implementation may be available for some rings.

Source

fn xor(&self, y: &Self) -> Self

Computes the arithmetic generalization of boolean xor.

For boolean inputs, x ^ y = x + y - 2 xy.

Source

fn xor3(&self, y: &Self, z: &Self) -> Self

Computes the arithmetic generalization of a triple xor.

For boolean inputs x ^ y ^ z = x + y + z - 2(xy + xz + yz) + 4xyz.

Source

fn andn(&self, y: &Self) -> Self

Computes the arithmetic generalization of andnot.

For boolean inputs (!x) & y = (1 - x)y.

Source

fn bool_check(&self) -> Self

The vanishing polynomial for boolean values: x * (1 - x).

This is a polynomial of degree 2 that evaluates to 0 if the input is 0 or 1. If our space is a field, then this will be nonzero on all other inputs.

Source

fn exp_u64(&self, power: u64) -> Self

Exponentiation by a u64 power.

This uses the standard square and multiply approach. For specific powers regularly used and known in advance, this will be slower than custom addition chain exponentiation.

Source

fn exp_const_u64<const POWER: u64>(&self) -> Self

Exponentiation by a small constant power.

For a collection of small values we implement custom multiplication chain circuits which can be faster than the simpler square and multiply approach.

For large values this defaults back to self.exp_u64.

Source

fn exp_power_of_2(&self, power_log: usize) -> Self

The elementary function exp_power_of_2(a, power_log) = a^{2^power_log}.

Computed via repeated squaring.

Source

fn mul_2exp_u64(&self, exp: u64) -> Self

The elementary function mul_2exp_u64(a, exp) = a * 2^{exp}.

Here 2^{exp} is computed using the square and multiply approach.

Source

fn div_2exp_u64(&self, exp: u64) -> Self

Divide by a given power of two. div_2exp_u64(a, exp) = a/2^exp

§Panics

The function will panic if the field has characteristic 2.

Source

fn powers(&self) -> Powers<Self>

Construct an iterator which returns powers of self: self^0, self^1, self^2, ....

Source

fn shifted_powers(&self, start: Self) -> Powers<Self>

Construct an iterator which returns powers of self shifted by start: start, start*self^1, start*self^2, ....

Source

fn dot_product<const N: usize>(u: &[Self; N], v: &[Self; N]) -> Self

Compute the dot product of two vectors.

Source

fn sum_array<const N: usize>(input: &[Self]) -> Self

Compute the sum of a slice of elements whose length is a compile time constant.

The rust compiler doesn’t realize that add is associative so we help it out and minimize the dependency chains by hand. Thus while this function has the same throughput as input.iter().sum(), it will usually have much lower latency.

§Panics

May panic if the length of the input slice is not equal to N.

Source

fn zero_vec(len: usize) -> Vec<Self>

Allocates a vector of zero elements of length len. Many operating systems zero pages before assigning them to a userspace process. In that case, our process should not need to write zeros, which would be redundant. However, the compiler may not always recognize this.

In particular, vec![Self::ZERO; len] appears to result in redundant userspace zeroing. This is the default implementation, but implementers may wish to provide their own implementation which transmutes something like vec![0u32; len].

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§