use ark_std::vec::Vec;
use ark_ff::Field;
use crate::utils::IndexMap;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub struct InternedField(u32);
#[derive(Debug, Clone, Default)]
pub struct FieldInterner<F: Field> {
pub map: IndexMap<F, InternedField>,
pub vec: Vec<F>,
}
impl<F: Field> FieldInterner<F> {
#[inline]
pub(super) fn new() -> Self {
let mut result = Self {
map: IndexMap::default(),
vec: Vec::new(),
};
result.intern(F::ONE);
result.intern(-F::ONE);
result
}
#[inline(always)]
#[allow(clippy::cast_possible_truncation)]
fn intern(&mut self, value: F) -> InternedField {
let index = self.vec.len();
let interned = InternedField(index as u32);
self.map.insert(value, interned);
self.vec.push(value);
interned
}
#[inline]
pub(crate) fn get_or_intern(&mut self, value: F) -> InternedField {
if value == F::ONE {
InternedField(0)
} else if let Some(&index) = self.map.get(&value) {
index
} else {
self.intern(value)
}
}
#[inline(always)]
pub(crate) fn value(&self, id: InternedField) -> Option<F> {
if id == InternedField(0) {
Some(F::ONE)
} else if id == InternedField(1) {
return Some(-F::ONE);
} else {
self.vec.get(id.0 as usize).copied()
}
}
}