o1vm/
ramlookup.rs

1use ark_ff::{Field, One, Zero};
2use kimchi_msm::{Logup, LookupTableID};
3
4/// Enum representing the two different modes of a RAMLookup
5#[derive(Copy, Clone, Debug)]
6pub enum LookupMode {
7    Read,
8    Write,
9}
10
11/// Struct containing a RAMLookup
12#[derive(Clone, Debug)]
13pub struct RAMLookup<T, ID: LookupTableID> {
14    /// The table ID corresponding to this lookup
15    pub(crate) table_id: ID,
16    /// Whether it is a read or write lookup
17    pub(crate) mode: LookupMode,
18    /// The number of times that this lookup value should be added to / subtracted from the lookup accumulator.
19    pub(crate) magnitude: T,
20    /// The columns containing the content of this lookup
21    pub(crate) value: Vec<T>,
22}
23
24impl<T, ID> RAMLookup<T, ID>
25where
26    T: Clone
27        + std::ops::Add<T, Output = T>
28        + std::ops::Sub<T, Output = T>
29        + std::ops::Mul<T, Output = T>
30        + std::fmt::Debug
31        + One
32        + Zero,
33    ID: LookupTableID,
34{
35    /// Creates a new RAMLookup from a mode, a table ID, a magnitude, and a value
36    pub fn new(mode: LookupMode, table_id: ID, magnitude: T, value: &[T]) -> Self {
37        Self {
38            mode,
39            table_id,
40            magnitude,
41            value: value.to_vec(),
42        }
43    }
44
45    /// Returns the numerator corresponding to this lookup in the Logup argument
46    pub fn numerator(&self) -> T {
47        match self.mode {
48            LookupMode::Read => T::zero() - self.magnitude.clone(),
49            LookupMode::Write => self.magnitude.clone(),
50        }
51    }
52
53    /// Transforms the current RAMLookup into an equivalent Logup
54    pub fn into_logup(self) -> Logup<T, ID> {
55        Logup::new(self.table_id, self.numerator(), &self.value)
56    }
57
58    /// Reads one value when `if_is_true` is 1.
59    pub fn read_if(if_is_true: T, table_id: ID, value: Vec<T>) -> Self {
60        Self {
61            mode: LookupMode::Read,
62            magnitude: if_is_true,
63            table_id,
64            value,
65        }
66    }
67
68    /// Writes one value when `if_is_true` is 1.
69    pub fn write_if(if_is_true: T, table_id: ID, value: Vec<T>) -> Self {
70        Self {
71            mode: LookupMode::Write,
72            magnitude: if_is_true,
73            table_id,
74            value,
75        }
76    }
77
78    /// Reads one value from a table.
79    pub fn read_one(table_id: ID, value: Vec<T>) -> Self {
80        Self {
81            mode: LookupMode::Read,
82            magnitude: T::one(),
83            table_id,
84            value,
85        }
86    }
87
88    /// Writes one value to a table.
89    pub fn write_one(table_id: ID, value: Vec<T>) -> Self {
90        Self {
91            mode: LookupMode::Write,
92            magnitude: T::one(),
93            table_id,
94            value,
95        }
96    }
97}
98
99impl<F: std::fmt::Display + Field, ID: LookupTableID> std::fmt::Display for RAMLookup<F, ID> {
100    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
101        let numerator = match self.mode {
102            LookupMode::Read => -self.magnitude,
103            LookupMode::Write => self.magnitude,
104        };
105        write!(
106            formatter,
107            "numerator: {}\ntable_id: {:?}\nvalue:\n[\n",
108            numerator,
109            self.table_id.to_field::<F>()
110        )?;
111        for value in self.value.iter() {
112            writeln!(formatter, "\t{}", value)?;
113        }
114        write!(formatter, "]")?;
115        Ok(())
116    }
117}