zkaluvm/core/
microcode.rs1use aluvm::regs::Status;
24use aluvm::CoreExt;
25use amplify::num::u256;
26
27use crate::gfa::Bits;
28use crate::{fe256, GfaCore, RegE};
29
30impl GfaCore {
32 pub fn fq(&self) -> u256 { self.fq }
33
34 pub fn test(&self, src: RegE) -> Status {
35 if self.get(src).is_some() {
36 Status::Ok
37 } else {
38 Status::Fail
39 }
40 }
41
42 pub fn fits(&self, src: RegE, bits: Bits) -> Option<bool> {
43 let order = self.fq();
44 let a = self.get(src)?;
45 debug_assert!(a.to_u256() < order);
46 let check = a.to_u256() >> bits.bit_len();
47 Some(check == u256::ZERO)
48 }
49
50 pub fn mov(&mut self, dst: RegE, src: RegE) {
51 match self.get(src) {
52 Some(val) => {
53 self.set(dst, val);
54 }
55 None => {
56 self.clr(dst);
57 }
58 }
59 }
60
61 pub fn eqv(&mut self, src1: RegE, src2: RegE) -> Status {
62 let a = self.get(src1);
63 let b = self.get(src2);
64 if a == b {
65 Status::Ok
66 } else {
67 Status::Fail
68 }
69 }
70
71 #[inline]
72 pub fn add_mod(&mut self, dst_src: RegE, src: RegE) -> Status {
73 let order = self.fq();
74
75 let Some(a) = self.get(dst_src) else {
76 return Status::Fail;
77 };
78 let Some(b) = self.get(src) else {
79 return Status::Fail;
80 };
81
82 let a = a.to_u256();
83 let b = b.to_u256();
84 debug_assert!(a < order && b < order);
85
86 let (mut res, overflow) = a.overflowing_add(b);
87 if overflow {
88 res += u256::MAX - order;
89 }
90
91 let res = res % order;
92 self.set(dst_src, fe256::from(res));
93 Status::Ok
94 }
95
96 #[inline]
97 pub fn mul_mod(&mut self, dst_src: RegE, src: RegE) -> Status {
98 let order = self.fq();
99
100 let Some(a) = self.get(dst_src) else {
101 return Status::Fail;
102 };
103 let Some(b) = self.get(src) else {
104 return Status::Fail;
105 };
106
107 let a = a.to_u256();
108 let b = b.to_u256();
109 debug_assert!(a < order && b < order);
110
111 let (res, _) = mul_mod_int(order, a, b);
112
113 let res = res % order;
114 self.set(dst_src, fe256::from(res));
115 Status::Ok
116 }
117
118 #[inline]
119 pub fn neg_mod(&mut self, dst_src: RegE, src: RegE) -> Status {
120 let order = self.fq();
121
122 let Some(a) = self.get(src) else {
123 return Status::Fail;
124 };
125
126 debug_assert!(a.to_u256() < order);
127
128 let res = order - a.to_u256();
129 self.set(dst_src, fe256::from(res));
130 Status::Ok
131 }
132}
133
134fn mul_mod_int(order: u256, a: u256, b: u256) -> (u256, bool) {
135 let (mut res, overflow) = a.overflowing_mul(b);
136 if overflow {
137 let rem = u256::MAX - order;
138 res = mul_mod_int(order, res, rem).0;
139 }
140 (res % order, overflow)
141}