1#![allow(dead_code)]
2
3use super::ct::*;
4
5pub type Limb = u64;
6
7pub type Borrow = u8;
8pub type IBorrow = i8;
9
10pub struct LimbsLE<'a>(pub &'a [Limb]);
11
12pub struct LimbsBE<'a>(pub &'a [Limb]);
13
14impl<'a> LimbsLE<'a> {
15 pub fn len(&self) -> usize {
16 self.0.len()
17 }
18 pub fn iter_from_high(&self) -> core::iter::Rev<std::slice::Iter<'a, u64>> {
19 self.0.iter().rev()
20 }
21
22 pub fn iter_from_low(&self) -> std::slice::Iter<'a, u64> {
23 self.0.iter()
24 }
25}
26
27impl<'a> LimbsBE<'a> {
28 pub fn len(&self) -> usize {
29 self.0.len()
30 }
31 pub fn iter_from_high(&self) -> std::slice::Iter<'a, u64> {
32 self.0.iter()
33 }
34
35 pub fn iter_from_low(&self) -> core::iter::Rev<std::slice::Iter<'a, u64>> {
36 self.0.iter().rev()
37 }
38}
39
40fn limb_subborrow(out1: &mut u64, out2: &mut Borrow, arg1: Borrow, arg2: u64, arg3: u64) -> () {
42 let x1: i128 = ((arg2 as i128) - (arg1 as i128)) - (arg3 as i128);
43 let x2: IBorrow = (x1 >> 64) as IBorrow;
44 let x3: u64 = (x1 & (0xffffffffffffffff as i128)) as u64;
45 *out1 = x3;
46 *out2 = ((0x0 as IBorrow) - (x2 as IBorrow)) as Borrow;
47}
48
49pub fn limbsbe_le<'a, 'b>(a: LimbsBE<'a>, b: LimbsBE<'b>) -> Choice {
51 assert_eq!(a.len(), b.len());
52
53 let mut borrow: Borrow = 0;
54 let mut out = 0u64;
55 for (x, y) in b.iter_from_low().zip(a.iter_from_low()) {
56 let copied_borrow = borrow;
57 limb_subborrow(&mut out, &mut borrow, copied_borrow, *x, *y);
58 }
59 Choice(1 ^ borrow as u64)
60}
61
62pub fn limbsbe_lt<'a, 'b>(a: LimbsBE<'a>, b: LimbsBE<'b>) -> Choice {
63 assert_eq!(a.len(), b.len());
64
65 let mut borrow: Borrow = 0;
66 let mut out = 0u64;
67 for (x, y) in a.iter_from_low().zip(b.iter_from_low()) {
68 let copied_borrow = borrow;
69 limb_subborrow(&mut out, &mut borrow, copied_borrow, *x, *y);
70 }
71 let borrow = borrow as u64;
72 Choice((borrow | borrow.wrapping_neg()) >> 63)
73}
74
75pub fn limbsle_le<'a, 'b>(a: LimbsLE<'a>, b: LimbsLE<'b>) -> Choice {
76 assert_eq!(a.len(), b.len());
77
78 let mut borrow: Borrow = 0;
79 let mut out = 0u64;
80 for (x, y) in b.iter_from_low().zip(a.iter_from_low()) {
81 let copied_borrow = borrow;
82 limb_subborrow(&mut out, &mut borrow, copied_borrow, *x, *y)
83 }
84 Choice(1 ^ borrow as u64)
85}
86
87pub fn limbsle_lt<'a, 'b>(a: LimbsLE<'a>, b: LimbsLE<'b>) -> Choice {
88 assert_eq!(a.len(), b.len());
89
90 let mut borrow: Borrow = 0;
91 let mut out = 0u64;
92 for (x, y) in a.iter_from_low().zip(b.iter_from_low()) {
93 let copied_borrow = borrow;
94 limb_subborrow(&mut out, &mut borrow, copied_borrow, *x, *y);
95 }
96 let borrow = borrow as u64;
97 Choice((borrow | borrow.wrapping_neg()) >> 63)
98}
99
100impl<'a> CtEqual for LimbsLE<'a> {
101 fn ct_eq(&self, b: &Self) -> Choice {
102 self.0.ct_eq(b.0)
103 }
104}
105
106impl<'a> CtEqual for LimbsBE<'a> {
107 fn ct_eq(&self, b: &Self) -> Choice {
108 self.0.ct_eq(b.0)
109 }
110}
111
112impl<'a> CtZero for LimbsLE<'a> {
113 fn ct_zero(&self) -> Choice {
114 self.0.ct_zero()
115 }
116 fn ct_nonzero(&self) -> Choice {
117 self.0.ct_nonzero()
118 }
119}
120
121impl<'a> CtLesser for LimbsLE<'a> {
122 fn ct_lt(a: Self, b: Self) -> Choice {
123 limbsle_lt(a, b)
124 }
125}
126
127impl<'a> CtLesser for LimbsBE<'a> {
128 fn ct_lt(a: Self, b: Self) -> Choice {
129 limbsbe_lt(a, b)
130 }
131}
132
133#[cfg(test)]
134mod tests {
135 use super::*;
136
137 #[test]
138 fn le() {
139 assert_eq!(
140 false,
141 limbsbe_le(
142 LimbsBE(&[1, 0, 0, 0]),
143 LimbsBE(&[0, u64::MAX, u64::MAX, u64::MAX])
144 )
145 .into()
146 );
147 assert_eq!(
148 true,
149 limbsbe_le(LimbsBE(&[1, 2, 3]), LimbsBE(&[1, 2, 3])).into()
150 );
151 assert_eq!(
152 true,
153 limbsbe_le(LimbsBE(&[1, 2, 3]), LimbsBE(&[1, 3, 3])).into()
154 );
155 assert_eq!(
156 true,
157 limbsbe_le(LimbsBE(&[0, 2, 3]), LimbsBE(&[1, 2, 3])).into(),
158 );
159 assert_eq!(
160 false,
161 limbsbe_le(LimbsBE(&[1, 4, 2]), LimbsBE(&[1, 2, 3])).into(),
162 );
163 assert_eq!(
164 false,
165 limbsbe_le(LimbsBE(&[2, 0, 2]), LimbsBE(&[1, 2, 3])).into(),
166 );
167 }
168
169 #[test]
170 fn lt() {
171 assert_eq!(
172 false,
173 limbsbe_le(
174 LimbsBE(&[1, 0, 0, 0]),
175 LimbsBE(&[0, u64::MAX, u64::MAX, u64::MAX])
176 )
177 .into(),
178 );
179 assert_eq!(
180 false,
181 limbsbe_lt(LimbsBE(&[1, 2, 3]), LimbsBE(&[1, 2, 3])).into(),
182 );
183 assert_eq!(
184 true,
185 limbsbe_lt(LimbsBE(&[1, 2, 3]), LimbsBE(&[1, 3, 3])).into(),
186 );
187 assert_eq!(
188 true,
189 limbsbe_lt(LimbsBE(&[0, 2, 3]), LimbsBE(&[1, 2, 3])).into(),
190 );
191 assert_eq!(
192 false,
193 limbsbe_lt(LimbsBE(&[1, 4, 2]), LimbsBE(&[1, 2, 3])).into(),
194 );
195 assert_eq!(
196 false,
197 limbsbe_lt(LimbsBE(&[2, 0, 2]), LimbsBE(&[1, 2, 3])).into(),
198 );
199 }
200}