sp1_core_machine/operations/
bitwise_u16.rs1use super::{BitwiseOperation, BitwiseOperationInput, U16toU8Operation};
2use crate::{
3 air::{SP1Operation, SP1OperationBuilder},
4 operations::{U16toU8OperationUnsafe, U16toU8OperationUnsafeInput},
5};
6use serde::{Deserialize, Serialize};
7use slop_air::AirBuilder;
8use slop_algebra::{AbstractField, Field};
9use sp1_core_executor::{events::ByteRecord, Opcode};
10use sp1_derive::{AlignedBorrow, InputExpr, InputParams, IntoShape, SP1OperationBuilder};
11use sp1_hypercube::{air::SP1AirBuilder, Word};
12use struct_reflection::{StructReflection, StructReflectionHelper};
13
14#[derive(
16 AlignedBorrow,
17 StructReflection,
18 Default,
19 Debug,
20 Clone,
21 Copy,
22 Serialize,
23 Deserialize,
24 IntoShape,
25 SP1OperationBuilder,
26)]
27#[repr(C)]
28pub struct BitwiseU16Operation<T> {
29 pub b_low_bytes: U16toU8Operation<T>,
31
32 pub c_low_bytes: U16toU8Operation<T>,
34
35 pub bitwise_operation: BitwiseOperation<T>,
37}
38
39impl<F: Field> BitwiseU16Operation<F> {
40 pub fn populate_bitwise(
41 &mut self,
42 record: &mut impl ByteRecord,
43 a_u64: u64,
44 b_u64: u64,
45 c_u64: u64,
46 opcode: Opcode,
47 ) {
48 self.b_low_bytes.populate_u16_to_u8_unsafe(b_u64);
49 self.c_low_bytes.populate_u16_to_u8_unsafe(c_u64);
50 self.bitwise_operation.populate_bitwise(record, a_u64, b_u64, c_u64, opcode);
51 }
52
53 fn eval_bitwise_u16<AB>(
59 builder: &mut AB,
60 b: Word<AB::Expr>,
61 c: Word<AB::Expr>,
62 cols: BitwiseU16Operation<AB::Var>,
63 opcode: AB::Expr,
64 is_real: AB::Expr,
65 ) -> Word<AB::Expr>
66 where
67 AB: SP1AirBuilder
68 + SP1OperationBuilder<U16toU8OperationUnsafe>
69 + SP1OperationBuilder<BitwiseOperation<<AB as AirBuilder>::F>>,
70 {
71 builder.assert_bool(is_real.clone());
73
74 let b_input = U16toU8OperationUnsafeInput::new(b.0, cols.b_low_bytes);
77 let b_bytes = U16toU8OperationUnsafe::eval(builder, b_input);
78 let c_input = U16toU8OperationUnsafeInput::new(c.0, cols.c_low_bytes);
79 let c_bytes = U16toU8OperationUnsafe::eval(builder, c_input);
80
81 BitwiseOperation::<AB::F>::eval(
83 builder,
84 BitwiseOperationInput::<AB>::new(
85 b_bytes,
86 c_bytes,
87 cols.bitwise_operation,
88 opcode,
89 is_real,
90 ),
91 );
92
93 let result_limb0 = cols.bitwise_operation.result[0]
95 + cols.bitwise_operation.result[1] * AB::F::from_canonical_u32(1 << 8);
96 let result_limb1 = cols.bitwise_operation.result[2]
97 + cols.bitwise_operation.result[3] * AB::F::from_canonical_u32(1 << 8);
98 let result_limb2 = cols.bitwise_operation.result[4]
99 + cols.bitwise_operation.result[5] * AB::F::from_canonical_u32(1 << 8);
100 let result_limb3 = cols.bitwise_operation.result[6]
101 + cols.bitwise_operation.result[7] * AB::F::from_canonical_u32(1 << 8);
102 Word([result_limb0, result_limb1, result_limb2, result_limb3])
103 }
104}
105
106#[derive(Clone, InputParams, InputExpr)]
107pub struct BitwiseU16OperationInput<AB: SP1AirBuilder> {
108 pub b: Word<AB::Expr>,
109 pub c: Word<AB::Expr>,
110 pub cols: BitwiseU16Operation<AB::Var>,
111 pub opcode: AB::Expr,
112 pub is_real: AB::Expr,
113}
114
115impl<AB> SP1Operation<AB> for BitwiseU16Operation<AB::F>
116where
117 AB: SP1AirBuilder
118 + SP1OperationBuilder<U16toU8OperationUnsafe>
119 + SP1OperationBuilder<BitwiseOperation<<AB as AirBuilder>::F>>,
120{
121 type Input = BitwiseU16OperationInput<AB>;
122 type Output = Word<AB::Expr>;
123
124 fn lower(builder: &mut AB, input: Self::Input) -> Word<AB::Expr> {
125 Self::eval_bitwise_u16(builder, input.b, input.c, input.cols, input.opcode, input.is_real)
126 }
127}