1use core::fmt::{self, Debug, Formatter};
24
25use aluvm::{CoreExt, NoExt, Register, Supercore};
26use amplify::num::{u256, u4};
27
28use crate::fe256;
29
30pub const FIELD_ORDER_25519: u256 =
32 u256::from_inner([0xFFFF_FFFF_FFFF_FFEC, 0xFFFF_FFFF_FFFF_FFFF, 0xFFFF_FFFF_FFFF_FFFF, 0x8FFF_FFFF_FFFF_FFFF]);
33pub const FIELD_ORDER_STARK: u256 = u256::from_inner([1, 0, 17, 0x0800_0000_0000_0000]);
35pub const FIELD_ORDER_SECP: u256 =
37 u256::from_inner([0xFFFF_FFFE_FFFF_FC2E, 0xFFFF_FFFF_FFFF_FFFF, 0xFFFF_FFFF_FFFF_FFFF, 0xFFFF_FFFF_FFFF_FFFF]);
38
39impl Default for GfaConfig {
40 fn default() -> Self {
41 Self {
42 field_order: FIELD_ORDER_25519,
43 }
44 }
45}
46
47#[derive(Copy, Clone, Eq, PartialEq)]
49pub struct GfaCore {
50 pub(super) fq: u256,
52 pub(super) e: [Option<fe256>; 16],
53}
54
55#[derive(Copy, Clone, Eq, PartialEq)]
57pub struct GfaConfig {
58 pub field_order: u256,
60}
61
62impl CoreExt for GfaCore {
63 type Reg = RegE;
64 type Config = GfaConfig; #[inline]
67 fn with(config: Self::Config) -> Self {
68 GfaCore {
69 fq: config.field_order,
70 e: [None; 16],
71 }
72 }
73
74 #[inline]
75 fn get(&self, reg: Self::Reg) -> Option<fe256> { self.e[reg as usize] }
76
77 #[inline]
78 fn clr(&mut self, reg: Self::Reg) { self.e[reg as usize] = None; }
79
80 #[inline]
81 fn put(&mut self, reg: Self::Reg, val: Option<fe256>) {
82 let Some(val) = val else {
83 self.e[reg as usize] = None;
84 return;
85 };
86 assert!(val.to_u256() < self.fq, "value {val} exceeds field order {}", self.fq);
87 self.e[reg as usize] = Some(val);
88 }
89
90 #[inline]
91 fn reset(&mut self) { self.e = [None; 16]; }
92}
93
94impl Supercore<NoExt> for GfaCore {
95 fn subcore(&self) -> NoExt { NoExt }
96
97 fn merge_subcore(&mut self, _subcore: NoExt) {}
98}
99
100#[cfg_attr(coverage_nightly, coverage(off))]
101impl Debug for GfaCore {
102 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
103 let (sect, reg, val, reset) =
104 if f.alternate() { ("\x1B[0;4;1m", "\x1B[0;1m", "\x1B[0;32m", "\x1B[0m") } else { ("", "", "", "") };
105
106 writeln!(f)?;
107 writeln!(f, "{reg}FQ{reset} {val}{:X}{reset}#h", self.fq)?;
108 writeln!(f, "{sect}E-regs:{reset}")?;
109 for (no, item) in self.e.iter().enumerate() {
110 write!(f, "{reg}{}{reset} ", RegE::from(u4::with(no as u8)))?;
111 if let Some(e) = item {
112 writeln!(f, "{val}{e}{reset}#h")?;
113 } else {
114 writeln!(f, "~")?;
115 }
116 }
117 writeln!(f)
118 }
119}
120
121#[allow(missing_docs)]
134#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Display)]
135#[display(uppercase)]
136#[repr(u8)]
137pub enum RegE {
138 E1 = 0b_0000,
139 E2 = 0b_0001,
140 E3 = 0b_0010,
141 E4 = 0b_0011,
142 E5 = 0b_0100,
143 E6 = 0b_0101,
144 E7 = 0b_0110,
145 E8 = 0b_0111,
146 EA = 0b_1000,
147 EB = 0b_1001,
148 EC = 0b_1010,
149 ED = 0b_1011,
150 EE = 0b_1100,
151 EF = 0b_1101,
152 EG = 0b_1110,
153 EH = 0b_1111,
154}
155
156impl Register for RegE {
157 type Value = fe256;
158
159 #[inline]
160 fn bytes(self) -> u16 { 32 }
161}
162
163impl From<u4> for RegE {
164 fn from(val: u4) -> Self {
165 match val {
166 x if x == RegE::E1.to_u4() => RegE::E1,
167 x if x == RegE::E2.to_u4() => RegE::E2,
168 x if x == RegE::E3.to_u4() => RegE::E3,
169 x if x == RegE::E4.to_u4() => RegE::E4,
170 x if x == RegE::E5.to_u4() => RegE::E5,
171 x if x == RegE::E6.to_u4() => RegE::E6,
172 x if x == RegE::E7.to_u4() => RegE::E7,
173 x if x == RegE::E8.to_u4() => RegE::E8,
174 x if x == RegE::EA.to_u4() => RegE::EA,
175 x if x == RegE::EB.to_u4() => RegE::EB,
176 x if x == RegE::EC.to_u4() => RegE::EC,
177 x if x == RegE::ED.to_u4() => RegE::ED,
178 x if x == RegE::EE.to_u4() => RegE::EE,
179 x if x == RegE::EF.to_u4() => RegE::EF,
180 x if x == RegE::EG.to_u4() => RegE::EG,
181 x if x == RegE::EH.to_u4() => RegE::EH,
182 _ => unreachable!(),
183 }
184 }
185}
186
187impl RegE {
188 pub const ALL: [Self; 16] = [
190 RegE::E1,
191 RegE::E2,
192 RegE::E3,
193 RegE::E4,
194 RegE::E5,
195 RegE::E6,
196 RegE::E7,
197 RegE::E8,
198 RegE::EA,
199 RegE::EB,
200 RegE::EC,
201 RegE::ED,
202 RegE::EE,
203 RegE::EF,
204 RegE::EG,
205 RegE::EH,
206 ];
207
208 #[inline]
210 pub const fn to_u4(self) -> u4 { u4::with(self as u8) }
211}