Trait PrimeCharacteristicRing
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
ZEROsatisfyingx + ZERO = x. - Inverses => For every
xthere exists a unique inverse(-x)satisfyingx + (-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
ONEsatisfyingx * ONE = x. - Distributivity => The two operations
+and*must together satisfyx * (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§
const ZERO: Self
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.
const ONE: Self
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.
const TWO: Self
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.
const NEG_ONE: Self
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§
type PrimeSubfield: PrimeField
type PrimeSubfield: PrimeField
The field ℤ/p where the characteristic of this ring is p.
Required Methods§
fn from_prime_subfield(f: Self::PrimeSubfield) -> Self
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§
fn from_u8(int: u8) -> Self
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.
fn from_u16(int: u16) -> Self
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.
fn from_u32(int: u32) -> Self
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.
fn from_u64(int: u64) -> Self
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.
fn from_u128(int: u128) -> Self
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.
fn from_usize(int: usize) -> Self
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.
fn from_i8(int: i8) -> Self
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.
fn from_i16(int: i16) -> Self
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.
fn from_i32(int: i32) -> Self
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.
fn from_i64(int: i64) -> Self
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.
fn from_i128(int: i128) -> Self
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.
fn from_isize(int: isize) -> Self
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.
fn double(&self) -> Self
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.
fn halve(&self) -> Self
fn halve(&self) -> Self
The elementary function halve(a) = a/2.
§Panics
The function will panic if the field has characteristic 2.
fn square(&self) -> Self
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.
fn cube(&self) -> Self
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.
fn xor(&self, y: &Self) -> Self
fn xor(&self, y: &Self) -> Self
Computes the arithmetic generalization of boolean xor.
For boolean inputs, x ^ y = x + y - 2 xy.
fn xor3(&self, y: &Self, z: &Self) -> Self
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.
fn andn(&self, y: &Self) -> Self
fn andn(&self, y: &Self) -> Self
Computes the arithmetic generalization of andnot.
For boolean inputs (!x) & y = (1 - x)y.
fn bool_check(&self) -> Self
fn bool_check(&self) -> Self
The vanishing polynomial for boolean values: x * (x - 1).
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.
fn exp_u64(&self, power: u64) -> Self
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.
fn exp_const_u64<const POWER: u64>(&self) -> Self
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.
fn exp_power_of_2(&self, power_log: usize) -> Self
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.
fn mul_2exp_u64(&self, exp: u64) -> Self
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.
fn div_2exp_u64(&self, exp: u64) -> Self
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.
fn powers(&self) -> Powers<Self> ⓘ
fn powers(&self) -> Powers<Self> ⓘ
Construct an iterator which returns powers of self: self^0, self^1, self^2, ....
fn shifted_powers(&self, start: Self) -> Powers<Self> ⓘ
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, ....
fn dot_product<const N: usize>(u: &[Self; N], v: &[Self; N]) -> Self
fn dot_product<const N: usize>(u: &[Self; N], v: &[Self; N]) -> Self
Compute the dot product of two vectors.
fn sum_array<const N: usize>(input: &[Self]) -> Self
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.
fn zero_vec(len: usize) -> Vec<Self>
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.