1use crate::common::util::add_carry;
4use crate::common::util::shift_slice_right;
5use crate::common::util::{shift_slice_left, sub_borrow};
6use crate::defs::{DoubleWord, SignedWord, Word, WORD_BASE, WORD_MAX};
7use core::ops::Deref;
8use core::ops::DerefMut;
9use itertools::izip;
10
11#[derive(Debug)]
13enum SliceWithSignType<'a> {
14 Mut(&'a mut [Word]),
15 Immut(&'a [Word]),
16}
17
18#[derive(Debug)]
20pub struct SliceWithSign<'a> {
21 m: SliceWithSignType<'a>,
22 sign: i8,
23}
24
25impl<'a> SliceWithSign<'a> {
26 pub fn new_mut(m: &'a mut [Word], sign: i8) -> Self {
27 SliceWithSign {
28 m: SliceWithSignType::Mut(m),
29 sign,
30 }
31 }
32
33 pub fn new(m: &'a [Word], sign: i8) -> Self {
34 SliceWithSign {
35 m: SliceWithSignType::Immut(m),
36 sign,
37 }
38 }
39
40 #[inline]
41 pub fn add(&self, s2: &SliceWithSign<'_>, dst: &mut SliceWithSign<'_>) {
42 self.add_sub(s2, dst, 1);
43 }
44
45 #[inline]
46 pub fn sub(&self, s2: &SliceWithSign<'_>, dst: &mut SliceWithSign<'_>) {
47 self.add_sub(s2, dst, -1);
48 }
49
50 #[inline]
51 pub fn add_assign(&mut self, s2: &SliceWithSign<'_>) {
52 self.add_sub_assign(s2, 1);
53 }
54
55 #[inline]
56 pub fn sub_assign(&mut self, s2: &SliceWithSign<'_>) {
57 self.add_sub_assign(s2, -1);
58 }
59
60 fn add_sub(&self, s2: &SliceWithSign<'_>, dst: &mut SliceWithSign<'_>, op: i8) {
61 if (self.sign != s2.sign && op > 0) || (op < 0 && self.sign == s2.sign) {
62 let cmp = Self::abs_cmp(self, s2);
64
65 if cmp > 0 {
66 dst.sign = self.sign;
67 Self::abs_sub(self, s2, dst);
68 } else if cmp < 0 {
69 dst.sign = s2.sign * op;
70 Self::abs_sub(s2, self, dst);
71 } else {
72 dst.fill(0);
73 };
74 } else {
75 dst.sign = self.sign;
76 Self::abs_add(self, s2, dst);
77 }
78 }
79
80 fn add_sub_assign(&mut self, s2: &SliceWithSign<'_>, op: i8) {
81 if (self.sign != s2.sign && op > 0) || (op < 0 && self.sign == s2.sign) {
82 let cmp = Self::abs_cmp(self, s2);
84 if cmp > 0 {
85 Self::abs_sub_assign_1(self, s2);
86 } else if cmp < 0 {
87 Self::abs_sub_assign_2(self, s2);
88 self.sign = s2.sign * op;
89 } else {
90 self.fill(0);
91 };
92 } else {
93 Self::abs_add_assign(self, s2);
94 }
95 }
96
97 #[cfg(test)]
98 pub fn mul_assign<'c>(&mut self, s2: &SliceWithSign<'c>, work_buf: &mut [Word]) {
99 work_buf.fill(0);
100 for (i, d1mi) in self.deref().iter().enumerate() {
101 let d1mi = *d1mi as DoubleWord;
102 if d1mi == 0 {
103 continue;
104 }
105
106 let mut k = 0;
107 for (m2j, m3ij) in s2.deref().iter().zip(work_buf[i..].iter_mut()) {
108 let m = d1mi * (*m2j as DoubleWord) + *m3ij as DoubleWord + k;
109
110 *m3ij = m as Word;
111 k = m >> (crate::WORD_BIT_SIZE);
112 }
113 work_buf[i + s2.len()] += k as Word;
114 }
115 self.deref_mut().copy_from_slice(work_buf);
116 self.sign *= s2.sign;
117 }
118
119 #[inline]
120 pub fn shift_left(&mut self, shift: usize) {
121 shift_slice_left(self, shift);
122 }
123
124 #[inline]
125 pub fn shift_right(&mut self, shift: usize) {
126 shift_slice_right(self, shift);
127 }
128
129 pub fn div_by_word(&mut self, d: Word) {
130 debug_assert!(d != 0);
131
132 let d = d as DoubleWord;
133 let mut rh = 0;
134 let m = self.deref_mut();
135 let mut iter = m.iter_mut().rev();
136 let mut val;
137
138 if let Some(v) = iter.next() {
139 val = v;
140 } else {
141 return;
142 }
143
144 if (*val as DoubleWord) < d {
145 rh = *val as DoubleWord;
146 *val = 0;
147 if let Some(v) = iter.next() {
148 val = v;
149 } else {
150 return;
151 }
152 }
153
154 loop {
155 let qh = rh * WORD_BASE as DoubleWord + *val as DoubleWord;
156
157 rh = qh % d;
158
159 *val = (qh / d) as Word;
160
161 if let Some(v) = iter.next() {
162 val = v;
163 } else {
164 break;
165 }
166 }
167 }
168
169 pub fn copy_from(&mut self, s2: &SliceWithSign<'_>) {
170 match &mut self.m {
171 SliceWithSignType::Mut(m) => {
172 match &s2.m {
173 SliceWithSignType::Mut(s) => m[..s.len()].copy_from_slice(s),
174 SliceWithSignType::Immut(s) => m[..s.len()].copy_from_slice(s),
175 };
176 }
177 _ => panic!(),
178 }
179 }
180
181 fn abs_add(s1: &[Word], s2: &[Word], dst: &mut [Word]) {
182 let mut c = 0;
183
184 let (iter1, mut iter2) = if s1.len() < s2.len() {
185 (s1.iter(), s2.iter())
186 } else {
187 (s2.iter(), s1.iter())
188 };
189
190 let mut iter3 = dst.iter_mut();
191
192 for (a, b, x) in izip!(iter1, iter2.by_ref(), iter3.by_ref()) {
193 c = add_carry(*a, *b, c, x);
194 }
195
196 for (b, x) in iter2.zip(iter3.by_ref()) {
197 c = add_carry(0, *b, c, x);
198 }
199
200 if c > 0 {
201 *iter3.next().unwrap() = c as Word; }
203
204 for v in iter3 {
205 *v = 0;
206 }
207 }
208
209 fn abs_add_assign(s1: &mut [Word], s2: &[Word]) {
210 let mut c = 0;
211 let mut iter1 = s1.iter_mut();
212 let iter2 = s2.iter();
213
214 for (b, a) in izip!(iter2, iter1.by_ref()) {
215 c = add_carry(*a, *b, c, a);
216 }
217
218 for a in iter1 {
219 c = add_carry(*a, 0, c, a);
220 }
221 }
222
223 fn abs_sub_assign_1(s1: &mut [Word], s2: &[Word]) {
225 let mut c = 0;
226 let mut iter1 = s1.iter_mut();
227 let iter2 = s2.iter();
228
229 for (b, a) in izip!(iter2, iter1.by_ref()) {
230 c = sub_borrow(*a, *b, c, a);
231 }
232
233 for a in iter1 {
234 c = sub_borrow(*a, 0, c, a);
235 }
236
237 debug_assert!(c == 0);
238 }
239
240 fn abs_sub_assign_2(s1: &mut [Word], s2: &[Word]) {
242 let mut c = 0;
243
244 for (a, b) in s2.iter().zip(s1.iter_mut()) {
245 c = sub_borrow(*a, *b, c, b);
246 }
247
248 debug_assert!(c == 0);
249 }
250
251 fn abs_sub(s1: &[Word], s2: &[Word], dst: &mut [Word]) {
252 let mut c = 0;
253
254 let mut iter1 = s1.iter();
255 let iter2 = s2.iter();
256 let mut iter3 = dst.iter_mut();
257
258 for (b, a, d) in izip!(iter2, iter1.by_ref(), iter3.by_ref()) {
259 c = sub_borrow(*a, *b, c, d);
260 }
261
262 if c > 0 {
263 for (a, d) in iter1.zip(iter3.by_ref()) {
264 c = sub_borrow(*a, 0, c, d);
265 }
266 } else {
267 for (a, d) in iter1.zip(iter3.by_ref()) {
268 *d = *a;
269 }
270 }
271
272 for v in iter3 {
273 *v = 0;
274 }
275 }
276
277 pub fn decrement_abs(&mut self) {
279 for v in self.iter_mut() {
280 if *v == 0 {
281 *v = WORD_MAX;
282 } else {
283 *v -= 1;
284 return;
285 }
286 }
287 panic!("numeric overflow");
288 }
289
290 pub fn is_zero(&self) -> bool {
291 for v in self.iter() {
292 if *v != 0 {
293 return false;
294 }
295 }
296 true
297 }
298
299 fn abs_cmp(s1: &[Word], s2: &[Word]) -> SignedWord {
300 let len = s1.len().min(s2.len());
301
302 for v in &s1[len..] {
303 if *v != 0 {
304 return 1;
305 }
306 }
307
308 for v in &s2[len..] {
309 if *v != 0 {
310 return -1;
311 }
312 }
313
314 for (a, b) in core::iter::zip(s1[..len].iter().rev(), s2[..len].iter().rev()) {
315 let diff = *a as SignedWord - *b as SignedWord;
316 if diff != 0 {
317 return diff;
318 }
319 }
320
321 0
322 }
323
324 #[inline]
325 pub fn set_sign(&mut self, sign: i8) {
326 self.sign = sign;
327 }
328
329 #[inline]
330 pub fn sign(&self) -> i8 {
331 self.sign
332 }
333
334 pub fn cmp(&self, d2: &Self) -> SignedWord {
335 if self.is_zero() && d2.is_zero() {
336 return 0;
337 }
338
339 if self.sign != d2.sign {
340 return self.sign as SignedWord;
341 }
342
343 Self::abs_cmp(self, d2) * self.sign as SignedWord
344 }
345}
346
347impl<'a> Deref for SliceWithSign<'a> {
348 type Target = [Word];
349
350 #[inline]
351 fn deref(&self) -> &[Word] {
352 match &self.m {
353 SliceWithSignType::Mut(m) => m,
354 SliceWithSignType::Immut(m) => m,
355 }
356 }
357}
358
359impl<'a> DerefMut for SliceWithSign<'a> {
360 #[inline]
361 fn deref_mut(&mut self) -> &mut [Word] {
362 match &mut self.m {
363 SliceWithSignType::Mut(m) => m,
364 _ => panic!(),
365 }
366 }
367}