pub mod depth;
pub mod display;
pub mod domain;
pub mod eval_const;
mod eval_proptests;
pub mod expr;
pub mod expr_props;
pub mod func_arity;
pub mod pool;
pub mod pool_persist;
mod printer_roundtrip;
mod proptests;
pub mod subs;
pub use depth::{check_expr_depth, check_expr_depths, DepthLimitError, MAX_EXPR_DEPTH};
pub use display::{render_latex, render_unicode};
pub use domain::Domain;
pub use eval_const::{
integer_is_exact_f64, integer_to_f64, pow_f64, pow_f64_integer_exponent, rational_to_f64,
try_expr_f64, try_predicate_bool, try_predicate_bool_from_expr,
};
pub use expr::{BigFloat, BigInt, BigRat, ExprData, ExprId};
pub use expr_props::{
contains_non_finite_atom, expr_contains_noncommutative_symbol, is_non_finite_atom,
mult_tree_is_commutative,
};
pub use func_arity::{func_arity_ok, known_func_arity, FuncArityError};
pub use pool::{ExprDisplay, ExprPool};
#[allow(deprecated)]
pub use pool_persist::PoolPersistError;
pub use pool_persist::{load_from, open_persistent, save_to, IoError};
pub use subs::{fold_predicates, subs};
pub(crate) type IdBuildHasher = foldhash::fast::FixedState;
pub(crate) type IdMap<V> = std::collections::HashMap<ExprId, V, IdBuildHasher>;
pub(crate) type IdSet = std::collections::HashSet<ExprId, IdBuildHasher>;
pub(crate) struct IdSeen {
inline: [ExprId; IdSeen::INLINE],
len: usize,
spill: IdSet,
}
impl Default for IdSeen {
fn default() -> Self {
IdSeen {
inline: [ExprId(0); IdSeen::INLINE],
len: 0,
spill: IdSet::default(),
}
}
}
impl IdSeen {
const INLINE: usize = 16;
pub(crate) fn insert(&mut self, id: ExprId) -> bool {
if self.len < Self::INLINE {
if self.inline[..self.len].contains(&id) {
return false;
}
self.inline[self.len] = id;
self.len += 1;
return true;
}
if self.spill.is_empty() {
if self.inline.contains(&id) {
return false;
}
self.spill.reserve(2 * Self::INLINE);
self.spill.extend(self.inline);
}
self.spill.insert(id)
}
}
#[cfg(test)]
mod id_seen_tests {
use super::*;
#[test]
fn id_seen_matches_a_hash_set_across_the_spill() {
let mut state = 0x2545_F491_4F6C_DD1D_u64;
for round in 0..200u32 {
let universe = 1 + round % 60;
let mut seen = IdSeen::default();
let mut reference = std::collections::HashSet::new();
for _ in 0..(3 * universe) {
state ^= state << 13;
state ^= state >> 7;
state ^= state << 17;
let id = ExprId((state % u64::from(universe)) as u32);
assert_eq!(seen.insert(id), reference.insert(id), "round {round}");
}
}
}
}