#![no_std]
#[macro_use]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std;
pub mod aead;
pub mod dsa;
pub mod ecdh;
pub mod hash;
pub mod ies;
pub mod merkle;
pub mod rand;
pub mod utils;
pub use miden_field::{Felt, Word, WordError, word};
pub mod field {
pub use miden_field::{
Algebra, BasedVectorSpace, BinomialExtensionField, BinomiallyExtendable,
BinomiallyExtendableAlgebra, BoundedPowers, ExtensionField, Field,
HasTwoAdicBinomialExtension, InjectiveMonomial, Packable, PermutationMonomial, Powers,
PrimeCharacteristicRing, PrimeField, PrimeField64, QuotientMap, RawDataSerializable,
TwoAdicField, batch_multiplicative_inverse,
};
pub use super::batch_inversion::batch_inversion_allow_zeros;
}
pub mod parallel {
pub use p3_maybe_rayon::prelude::*;
}
pub mod stark {
pub use miden_lifted_stark::{GenericStarkConfig, StarkConfig};
pub use miden_lifted_stark::{
air, debug, fri, hasher, lmcs, proof, prover, transcript, verifier,
};
pub mod challenger {
pub use p3_challenger::{
CanFinalizeDigest, CanObserve, DuplexChallenger, FieldChallenger, GrindingChallenger,
HashChallenger, SerializingChallenger64,
};
}
pub mod dft {
pub use p3_dft::{NaiveDft, Radix2DitParallel, TwoAdicSubgroupDft};
}
pub mod matrix {
pub use p3_matrix::{Matrix, dense::RowMajorMatrix};
}
pub mod symmetric {
pub use p3_symmetric::{
CompressionFunctionFromHasher, CryptographicPermutation, PaddingFreeSponge,
Permutation, SerializingHasher, TruncatedPermutation,
};
}
}
#[cfg(feature = "std")]
pub type Map<K, V> = std::collections::HashMap<K, V>;
#[cfg(not(feature = "std"))]
pub type Map<K, V> = alloc::collections::BTreeMap<K, V>;
#[cfg(not(feature = "std"))]
pub use alloc::collections::btree_map::Entry as MapEntry;
#[cfg(not(feature = "std"))]
pub use alloc::collections::btree_map::IntoIter as MapIntoIter;
#[cfg(feature = "std")]
pub use std::collections::hash_map::Entry as MapEntry;
#[cfg(feature = "std")]
pub use std::collections::hash_map::IntoIter as MapIntoIter;
#[cfg(feature = "std")]
pub type Set<V> = std::collections::HashSet<V>;
#[cfg(not(feature = "std"))]
pub type Set<V> = alloc::collections::BTreeSet<V>;
pub const ZERO: Felt = Felt::ZERO;
pub const ONE: Felt = Felt::ONE;
pub const EMPTY_WORD: Word = Word::new([ZERO; Word::NUM_ELEMENTS]);
pub trait SequentialCommit {
type Commitment: From<Word>;
fn to_commitment(&self) -> Self::Commitment {
hash::poseidon2::Poseidon2::hash_elements(&self.to_elements()).into()
}
fn to_elements(&self) -> alloc::vec::Vec<Felt>;
}
mod batch_inversion {
use p3_maybe_rayon::prelude::*;
use super::{Felt, ONE, ZERO, field::Field};
pub fn batch_inversion_allow_zeros(values: &mut [Felt]) {
const CHUNK_SIZE: usize = 1024;
values.par_chunks_mut(CHUNK_SIZE).for_each(|output_chunk| {
let len = output_chunk.len();
let mut scratch = [ZERO; CHUNK_SIZE];
scratch[..len].copy_from_slice(output_chunk);
batch_inversion_helper(&scratch[..len], output_chunk);
});
}
fn batch_inversion_helper(values: &[Felt], result: &mut [Felt]) {
debug_assert_eq!(values.len(), result.len());
if values.is_empty() {
return;
}
let mut last = ONE;
for (result, &value) in result.iter_mut().zip(values.iter()) {
*result = last;
if value != ZERO {
last *= value;
}
}
last = last.inverse();
for i in (0..values.len()).rev() {
if values[i] == ZERO {
result[i] = ZERO;
} else {
result[i] *= last;
last *= values[i];
}
}
}
#[cfg(test)]
mod tests {
use alloc::vec::Vec;
use super::*;
#[test]
fn test_batch_inversion_allow_zeros() {
let mut column = Vec::from([
Felt::new_unchecked(2),
ZERO,
Felt::new_unchecked(4),
Felt::new_unchecked(5),
]);
batch_inversion_allow_zeros(&mut column);
assert_eq!(column[0], Felt::new_unchecked(2).inverse());
assert_eq!(column[1], ZERO);
assert_eq!(column[2], Felt::new_unchecked(4).inverse());
assert_eq!(column[3], Felt::new_unchecked(5).inverse());
}
#[test]
fn test_batch_inversion_allow_zeros_spans_fixed_chunks() {
let mut v: Vec<Felt> = (1_u64..=2050).map(Felt::new_unchecked).collect();
let expected: Vec<Felt> = v.iter().copied().map(|x| x.inverse()).collect();
batch_inversion_allow_zeros(&mut v);
assert_eq!(v, expected);
}
#[test]
fn test_batch_inversion_allow_zeros_zero_on_chunk_boundary() {
let mut v = vec![Felt::new_unchecked(7); 1025];
v[1023] = ZERO;
batch_inversion_allow_zeros(&mut v);
assert_eq!(v[1023], ZERO);
for i in (0..1023).chain(1024..1025) {
assert_eq!(v[i], Felt::new_unchecked(7).inverse());
}
}
}
}
#[cfg(test)]
mod tests {
#[test]
#[should_panic]
fn debug_assert_is_checked() {
debug_assert!(false);
}
#[test]
#[should_panic]
#[allow(arithmetic_overflow)]
fn overflow_panics_for_test() {
let a = 1_u64;
let b = 64;
assert_ne!(a << b, 0);
}
}