1use std::ops::{Index, IndexMut};
2
3use crate::air::SP1AirBuilder;
4use arrayref::array_ref;
5use itertools::Itertools;
6use p3_air::AirBuilder;
7use p3_field::{AbstractField, Field};
8use serde::{Deserialize, Serialize};
9use sp1_derive::AlignedBorrow;
10use sp1_primitives::consts::WORD_SIZE;
11use std::array::IntoIter;
12
13#[derive(
18 AlignedBorrow, Clone, Copy, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize,
19)]
20#[repr(C)]
21pub struct Word<T>(pub [T; WORD_SIZE]);
22
23impl<T> Word<T> {
24 pub fn map<F, S>(self, f: F) -> Word<S>
26 where
27 F: FnMut(T) -> S,
28 {
29 Word(self.0.map(f))
30 }
31
32 pub fn extend_var<AB: SP1AirBuilder<Var = T>>(var: T) -> Word<AB::Expr> {
34 Word([AB::Expr::zero() + var, AB::Expr::zero(), AB::Expr::zero(), AB::Expr::zero()])
35 }
36}
37
38impl<T: AbstractField> Word<T> {
39 pub fn extend_expr<AB: SP1AirBuilder<Expr = T>>(expr: T) -> Word<AB::Expr> {
41 Word([AB::Expr::zero() + expr, AB::Expr::zero(), AB::Expr::zero(), AB::Expr::zero()])
42 }
43
44 #[must_use]
46 pub fn zero<AB: SP1AirBuilder<Expr = T>>() -> Word<T> {
47 Word([AB::Expr::zero(), AB::Expr::zero(), AB::Expr::zero(), AB::Expr::zero()])
48 }
49}
50
51impl<F: Field> Word<F> {
52 pub fn to_u32(&self) -> u32 {
54 u32::from_le_bytes(self.0.map(|x| x.to_string().parse::<u8>().unwrap()))
55 }
56}
57
58impl<V: Copy> Word<V> {
59 pub fn reduce<AB: AirBuilder<Var = V>>(&self) -> AB::Expr {
61 let base = [1, 1 << 8, 1 << 16, 1 << 24].map(AB::Expr::from_canonical_u32);
62 self.0.iter().enumerate().map(|(i, x)| base[i].clone() * *x).sum()
63 }
64}
65
66impl<T> Index<usize> for Word<T> {
67 type Output = T;
68
69 fn index(&self, index: usize) -> &Self::Output {
70 &self.0[index]
71 }
72}
73
74impl<T> IndexMut<usize> for Word<T> {
75 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
76 &mut self.0[index]
77 }
78}
79
80impl<F: AbstractField> From<u32> for Word<F> {
81 fn from(value: u32) -> Self {
82 Word(value.to_le_bytes().map(F::from_canonical_u8))
83 }
84}
85
86impl<T> IntoIterator for Word<T> {
87 type Item = T;
88 type IntoIter = IntoIter<T, WORD_SIZE>;
89
90 fn into_iter(self) -> Self::IntoIter {
91 self.0.into_iter()
92 }
93}
94
95impl<T: Clone> FromIterator<T> for Word<T> {
96 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
97 let elements = iter.into_iter().take(WORD_SIZE).collect_vec();
98
99 Word(array_ref![elements, 0, WORD_SIZE].clone())
100 }
101}