openvm_algebra_circuit/
lib.rs

1#![cfg_attr(feature = "tco", allow(incomplete_features))]
2#![cfg_attr(feature = "tco", feature(explicit_tail_calls))]
3#![cfg_attr(feature = "tco", allow(internal_features))]
4#![cfg_attr(feature = "tco", feature(core_intrinsics))]
5
6use std::ops::{Deref, DerefMut};
7
8use openvm_circuit::arch::DEFAULT_BLOCK_SIZE;
9use openvm_mod_circuit_builder::FieldExpressionExecutor;
10use openvm_rv32_adapters::Rv32VecHeapAdapterExecutor;
11#[cfg(feature = "cuda")]
12use {
13    openvm_mod_circuit_builder::FieldExpressionCoreRecordMut,
14    openvm_rv32_adapters::Rv32VecHeapAdapterRecord,
15};
16
17// Number of limbs for different modulus sizes (bytes)
18/// Number of limbs for 256-bit (32-byte) moduli
19pub const NUM_LIMBS_32: usize = 32;
20/// Number of limbs for 384-bit (48-byte) moduli
21pub const NUM_LIMBS_48: usize = 48;
22
23// Blocks per operation for modular arithmetic (single field element)
24/// Blocks for 32-limb modular operations: 32 / 4 = 8 blocks
25pub const MODULAR_BLOCKS_32: usize = NUM_LIMBS_32 / DEFAULT_BLOCK_SIZE;
26/// Blocks for 48-limb modular operations: 48 / 4 = 12 blocks
27pub const MODULAR_BLOCKS_48: usize = NUM_LIMBS_48 / DEFAULT_BLOCK_SIZE;
28
29// Blocks per operation for Fp2 (two field elements)
30/// Blocks for Fp2 with 32-limb base field: 2 * 8 = 16 blocks
31pub const FP2_BLOCKS_32: usize = 2 * MODULAR_BLOCKS_32;
32/// Blocks for Fp2 with 48-limb base field: 2 * 12 = 24 blocks
33pub const FP2_BLOCKS_48: usize = 2 * MODULAR_BLOCKS_48;
34
35pub mod fp2_chip;
36pub mod modular_chip;
37
38mod execution;
39mod fp2;
40pub use fp2::*;
41mod extension;
42pub use extension::*;
43pub mod fields;
44mod preflight;
45
46use fields::{get_field_type, get_fp2_field_type, FieldType};
47
48// Note: PreflightExecutor is implemented manually in preflight.rs with fast native arithmetic
49#[derive(Clone)]
50pub struct FieldExprVecHeapExecutor<
51    const BLOCKS: usize,
52    const BLOCK_SIZE: usize,
53    const IS_FP2: bool,
54> {
55    inner: FieldExpressionExecutor<
56        Rv32VecHeapAdapterExecutor<2, BLOCKS, BLOCKS, BLOCK_SIZE, BLOCK_SIZE>,
57    >,
58    pub(crate) cached_field_type: Option<FieldType>,
59}
60
61impl<const BLOCKS: usize, const BLOCK_SIZE: usize, const IS_FP2: bool>
62    FieldExprVecHeapExecutor<BLOCKS, BLOCK_SIZE, IS_FP2>
63{
64    pub fn new(
65        inner: FieldExpressionExecutor<
66            Rv32VecHeapAdapterExecutor<2, BLOCKS, BLOCKS, BLOCK_SIZE, BLOCK_SIZE>,
67        >,
68    ) -> Self {
69        let cached_field_type = if IS_FP2 {
70            get_fp2_field_type(&inner.expr.prime)
71        } else {
72            get_field_type(&inner.expr.prime)
73        };
74        Self {
75            inner,
76            cached_field_type,
77        }
78    }
79}
80
81impl<const BLOCKS: usize, const BLOCK_SIZE: usize, const IS_FP2: bool> Deref
82    for FieldExprVecHeapExecutor<BLOCKS, BLOCK_SIZE, IS_FP2>
83{
84    type Target = FieldExpressionExecutor<
85        Rv32VecHeapAdapterExecutor<2, BLOCKS, BLOCKS, BLOCK_SIZE, BLOCK_SIZE>,
86    >;
87
88    fn deref(&self) -> &Self::Target {
89        &self.inner
90    }
91}
92
93impl<const BLOCKS: usize, const BLOCK_SIZE: usize, const IS_FP2: bool> DerefMut
94    for FieldExprVecHeapExecutor<BLOCKS, BLOCK_SIZE, IS_FP2>
95{
96    fn deref_mut(&mut self) -> &mut Self::Target {
97        &mut self.inner
98    }
99}
100
101#[cfg(feature = "cuda")]
102pub(crate) type AlgebraRecord<
103    'a,
104    const NUM_READS: usize,
105    const BLOCKS: usize,
106    const BLOCK_SIZE: usize,
107> = (
108    &'a mut Rv32VecHeapAdapterRecord<NUM_READS, BLOCKS, BLOCKS, BLOCK_SIZE, BLOCK_SIZE>,
109    FieldExpressionCoreRecordMut<'a>,
110);