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§
Sourceconst 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.
Sourceconst 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.
Sourceconst 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.
Sourceconst 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§
Sourcetype PrimeSubfield: PrimeField
type PrimeSubfield: PrimeField
The field ℤ/p where the characteristic of this ring is p.
Required Methods§
Sourcefn 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§
Sourcefn 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.
Sourcefn 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.
Sourcefn 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.
Sourcefn 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.
Sourcefn 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.
Sourcefn 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.
Sourcefn 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.
Sourcefn 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.
Sourcefn 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.
Sourcefn 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.
Sourcefn 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.
Sourcefn 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.
Sourcefn 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.
Sourcefn 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.
Sourcefn 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.
Sourcefn 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.
Sourcefn 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.
Sourcefn 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.
Sourcefn 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.
Sourcefn bool_check(&self) -> Self
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.
Sourcefn 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.
Sourcefn 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.
Sourcefn 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.
Sourcefn 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.
Sourcefn 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.
Sourcefn powers(&self) -> Powers<Self> ⓘ
fn powers(&self) -> Powers<Self> ⓘ
Construct an iterator which returns powers of self: self^0, self^1, self^2, ....
Sourcefn 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, ....
Sourcefn 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.
Sourcefn 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.
Sourcefn 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.