a/math/numbers/div.rs
1//! Division of [`Number`]s: `/` and `/=` for the quotient and `%` and `%=` for the remainder, with
2//! either operand owned or borrowed, and [`Number::div_rem`], [`Number::div_euclid`] and
3//! [`Number::rem_euclid`].
4//!
5//! The rules are those of Rust's primitive integers. The quotient `a / b` is truncated toward
6//! zero, and the remainder `a % b` is what is left, `a - (a / b) b`: it has the sign of `a` and a
7//! magnitude below that of `b`, so `-7 / 2 = -3` and `-7 % 2 = -1`. `div_euclid` and `rem_euclid`
8//! give Euclid's division instead, whose remainder is never negative: `-7 = 2 (-4) + 1`. Dividing by
9//! zero panics, as it does for `i32`. A zero magnitude is zero whatever `negative` says, and zero
10//! bytes above the most significant one count for nothing.
11//!
12//! Operands whose vectors both hold at most 16 bytes take a short path in registers: their
13//! magnitudes are read into `u128`s as the addition reads them and divided, and the result is
14//! written in the byte order of the left operand. A dividend of up to 64 bytes by a divisor of up
15//! to 16 is divided in registers too, by the steps below.
16//!
17//! Longer operands are read into limbs of eight bytes, native `u64`s, the least significant first,
18//! in working memory on the stack, or on the heap for the longest. Both are shifted left by the
19//! same number of bits, so that the divisor's top bit is set: its top limbs then give each limb of
20//! the quotient by a multiplication with their precomputed reciprocal (see [`limbs`]). A divisor of
21//! one limb or two divides limb by limb; a longer one by the schoolbook method, each quotient limb
22//! times the divisor subtracted from the partial remainder by kernels in inline assembly on 64-bit
23//! little-endian `aarch64` and, with BMI2, on `x86_64`, and portable Rust elsewhere and under Miri;
24//! a divisor of 40 limbs or more by divide and conquer, on the multiplication; and the longest
25//! divisions, from 128 limbs in the divisor and 768 in the quotient, the quotient at least an
26//! eighth of the divisor, by Newton's method (see [`newton`]). The remainder is shifted back, and the quotient and the remainder are written as
27//! the operators promise. `/` computes the quotient alone, from the top limbs of the operands when
28//! it is much shorter than the divisor, and `%` by a divisor of one limb the remainder alone.
29//!
30//! A quotient is never longer than the dividend, nor a remainder than the divisor or the dividend,
31//! so the dividend's vector, when it is taken by value or is the target of `/=` or `%=`, has room
32//! for the result, except for zero in an empty vector, and so has the divisor's for a remainder.
33//!
34//! [`Number::div_exact`] and [`Number::is_multiple_of`] are in [`exact`], and a divisor prepared
35//! for many divisions, [`Divisor`](super::Divisor), divides by the same steps.
36
37// The kernel of the schoolbook method under the name `kernels`, chosen as those of the addition
38// are: assembly on 64-bit little-endian aarch64 where the system allows unaligned accesses and on
39// x86_64, and portable Rust elsewhere and under Miri.
40mod exact;
41#[cfg(all(
42 target_arch = "aarch64",
43 target_endian = "little",
44 target_pointer_width = "64",
45 any(
46 target_vendor = "apple",
47 target_os = "linux",
48 target_os = "android",
49 target_os = "windows",
50 target_os = "freebsd",
51 target_os = "netbsd",
52 target_os = "openbsd",
53 target_os = "fuchsia"
54 ),
55 not(miri)
56))]
57#[path = "div/aarch64.rs"]
58mod kernels;
59#[cfg(all(target_arch = "x86_64", not(miri)))]
60#[path = "div/x86_64.rs"]
61mod kernels;
62#[cfg(not(any(
63 all(
64 target_arch = "aarch64",
65 target_endian = "little",
66 target_pointer_width = "64",
67 any(
68 target_vendor = "apple",
69 target_os = "linux",
70 target_os = "android",
71 target_os = "windows",
72 target_os = "freebsd",
73 target_os = "netbsd",
74 target_os = "openbsd",
75 target_os = "fuchsia"
76 ),
77 not(miri)
78 ),
79 all(target_arch = "x86_64", not(miri))
80)))]
81#[path = "div/portable.rs"]
82mod kernels;
83pub(super) mod limbs;
84mod newton;
85mod rem1;
86
87pub(super) use limbs::{div_2by1 as divide_2by1, invert_limb as reciprocal};
88pub(super) use rem1::{
89 Powers, REM_1_BYTES, REM_1_BYTES_WIDE, REM_1_MAX, REM_1_PREPARED, limb_of, rem_1,
90};
91
92use super::add::{SMALL, read, read_small, small, write_small};
93use super::mul::limbs::{add_1, sub_n};
94use super::mul::{
95 Operand, Product, STACK_LIMBS, WIDE, Wide, on_heap, on_stack, put_wide, read_wide,
96};
97use super::sub::Negated;
98use super::{ByteOrder, Number};
99use core::cmp::Ordering::Less;
100use core::mem::{self, MaybeUninit};
101use core::ops::{Div, DivAssign, Rem, RemAssign};
102use core::ptr;
103use limbs::{
104 DC_DIV, DC_DIV_Q, Found, check_itch, check_q_top, div_2by1, div_3by2, div_q, div_q_split,
105 div_q_top, div_qr, div_qr_1, div_qr_2, from_top, invert_3by2, invert_limb, q_itch, qr_itch,
106 rshift, split_itch, split_low, top_itch,
107};
108pub(super) use newton::{Prepared, mu, mu_prepared, prepare};
109use newton::{mu_div_prepared, mu_div_q};
110
111impl Div<&Number> for &Number {
112 type Output = Number;
113
114 /// Returns `self / rhs`, truncated toward zero, in the byte order of `self`, in the shortest
115 /// form.
116 ///
117 /// The quotient is built in one new vector of exactly its length (one byte for zero); both
118 /// operands are left as they were. The operands may have any signs, byte orders and lengths,
119 /// and need not be in the shortest form.
120 ///
121 /// # Panics
122 ///
123 /// When `rhs` is zero.
124 ///
125 /// # Examples
126 ///
127 /// ```
128 /// use a::math::numbers::{ByteOrder, Number};
129 ///
130 /// // -0x01_00 / 3 = -0x55, truncated toward zero, in the byte order of the left operand.
131 /// let a = Number::new_from_i32(-0x0100, ByteOrder::BigEndian);
132 /// let b = Number::new_from_i32(3, ByteOrder::LittleEndian);
133 /// let quotient = &a / &b;
134 /// assert_eq!(quotient.value, [0x55]);
135 /// assert!(quotient.is_negative());
136 /// assert!(quotient.byte_order() == ByteOrder::BigEndian);
137 /// ```
138 #[track_caller]
139 fn div(self, rhs: &Number) -> Number {
140 if small(self, rhs) {
141 let (q, _) = small_division::<TRUNCATED, false>(self, rhs);
142 return small_number(self.byte_order, q);
143 }
144 ref_by_ref::<TRUNCATED, false>(self, rhs)
145 }
146}
147
148impl Div<&Number> for Number {
149 type Output = Number;
150
151 /// Returns `self / rhs`, truncated toward zero, in the byte order of `self`, in the shortest
152 /// form, as `self /= rhs` does.
153 ///
154 /// The quotient is built in the vector of `self`, which has room for it unless `self` is an
155 /// empty vector; `rhs` is left as it was.
156 ///
157 /// # Panics
158 ///
159 /// When `rhs` is zero.
160 ///
161 /// # Examples
162 ///
163 /// ```
164 /// use a::math::numbers::{ByteOrder, Number};
165 ///
166 /// let a = Number::new(vec![0x01, 0x00, 0x00], ByteOrder::BigEndian);
167 /// let pointer = a.value.as_ptr();
168 ///
169 /// // 0x01_00_00 / 0x01_01 = 0xFF, in the vector of `a`.
170 /// let quotient = a / &Number::new_from_u16(0x0101, ByteOrder::LittleEndian);
171 /// assert_eq!(quotient.value, [0xFF]);
172 /// assert_eq!(quotient.value.as_ptr(), pointer);
173 /// ```
174 #[track_caller]
175 fn div(mut self, rhs: &Number) -> Number {
176 self /= rhs;
177 self
178 }
179}
180
181impl Div<Number> for &Number {
182 type Output = Number;
183
184 /// Returns `self / rhs`, truncated toward zero, in the byte order of `self`, in the shortest
185 /// form.
186 ///
187 /// The quotient is built in the vector of `rhs` when its capacity has room for it, also when
188 /// `rhs` is in the other byte order; otherwise it gets one new vector of exactly its length.
189 /// `self` is left as it was.
190 ///
191 /// # Panics
192 ///
193 /// When `rhs` is zero.
194 ///
195 /// # Examples
196 ///
197 /// ```
198 /// use a::math::numbers::{ByteOrder, Number};
199 ///
200 /// let a = Number::new_from_u16(0x0300, ByteOrder::BigEndian);
201 /// let mut value = Vec::with_capacity(2);
202 /// value.push(3);
203 /// let b = Number::new(value, ByteOrder::LittleEndian);
204 /// let pointer = b.value.as_ptr();
205 ///
206 /// // 0x03_00 / 3 = 0x01_00, big-endian, in the vector of `b`.
207 /// let quotient = &a / b;
208 /// assert_eq!(quotient.value, [0x01, 0x00]);
209 /// assert_eq!(quotient.value.as_ptr(), pointer);
210 /// ```
211 #[track_caller]
212 fn div(self, mut rhs: Number) -> Number {
213 if small(self, &rhs) {
214 let (q, _) = small_division::<TRUNCATED, false>(self, &rhs);
215 put_small(&mut rhs.value, self.byte_order, q);
216 return Number {
217 value: rhs.value,
218 negative: q.negative,
219 byte_order: self.byte_order,
220 };
221 }
222 // `rhs` is dropped on return, with the vector it holds then, if any.
223 ref_by_value::<false>(self, &mut rhs)
224 }
225}
226
227impl Div<Number> for Number {
228 type Output = Number;
229
230 /// Returns `self / rhs`, truncated toward zero, in the byte order of `self`, in the shortest
231 /// form, as `self /= rhs` does.
232 ///
233 /// The quotient is built in the vector of `self`, which has room for it unless `self` is an
234 /// empty vector, and then in the vector of `rhs` when that has room.
235 ///
236 /// # Panics
237 ///
238 /// When `rhs` is zero.
239 ///
240 /// # Examples
241 ///
242 /// ```
243 /// use a::math::numbers::{ByteOrder, Number};
244 ///
245 /// // -7 / -2 = 3.
246 /// let a = Number::new_from_i32(-7, ByteOrder::LittleEndian);
247 /// let b = Number::new_from_i32(-2, ByteOrder::BigEndian);
248 /// let quotient = a / b;
249 /// assert_eq!(quotient.value, [3]);
250 /// assert!(!quotient.is_negative());
251 /// ```
252 #[track_caller]
253 fn div(mut self, rhs: Number) -> Number {
254 self /= rhs;
255 self
256 }
257}
258
259impl DivAssign<&Number> for Number {
260 /// Divides `self` by `rhs`, truncating toward zero, keeping the byte order of `self`, in the
261 /// shortest form.
262 ///
263 /// The quotient is built in the vector of `self`, which has room for it unless `self` is an
264 /// empty vector; `rhs` is left as it was.
265 ///
266 /// # Panics
267 ///
268 /// When `rhs` is zero.
269 ///
270 /// # Examples
271 ///
272 /// ```
273 /// use a::math::numbers::{ByteOrder, Number};
274 ///
275 /// let mut n = Number::new_from_u16(0x1000, ByteOrder::LittleEndian);
276 /// n /= &Number::new_from_u8(0x10, ByteOrder::BigEndian);
277 /// assert_eq!(n.value, [0x00, 0x01]);
278 /// n /= &Number::new_from_i8(-3, ByteOrder::BigEndian);
279 /// assert_eq!(n.value, [0x55]);
280 /// assert!(n.is_negative());
281 /// ```
282 #[inline]
283 #[track_caller]
284 fn div_assign(&mut self, rhs: &Number) {
285 if small(self, rhs) {
286 let (q, _) = small_division::<TRUNCATED, false>(self, rhs);
287 put_small(&mut self.value, self.byte_order, q);
288 self.negative = q.negative;
289 return;
290 }
291 assign_ref::<false>(self, rhs);
292 }
293}
294
295impl DivAssign<Number> for Number {
296 /// Divides `self` by `rhs`, truncating toward zero, keeping the byte order of `self`, in the
297 /// shortest form.
298 ///
299 /// The quotient is built in the vector of `self`, which has room for it unless `self` is an
300 /// empty vector, and then in the vector of `rhs` when that has room.
301 ///
302 /// # Panics
303 ///
304 /// When `rhs` is zero.
305 ///
306 /// # Examples
307 ///
308 /// ```
309 /// use a::math::numbers::{ByteOrder, Number};
310 ///
311 /// let mut n = Number::new_from_u32(1_000_000, ByteOrder::BigEndian);
312 /// n /= Number::new_from_u16(1000, ByteOrder::BigEndian);
313 /// assert_eq!(n.value, [0x03, 0xE8]);
314 /// ```
315 #[inline]
316 #[track_caller]
317 fn div_assign(&mut self, mut rhs: Number) {
318 if small(self, &rhs) {
319 let (q, _) = small_division::<TRUNCATED, false>(self, &rhs);
320 if self.value.capacity() < q.len && rhs.value.capacity() >= q.len {
321 // The vector of `self` goes to `rhs`, and is dropped with it.
322 mem::swap(&mut self.value, &mut rhs.value);
323 }
324 put_small(&mut self.value, self.byte_order, q);
325 self.negative = q.negative;
326 return;
327 }
328 // `rhs` is dropped on return, with the vector it holds then.
329 assign_value::<false>(self, &mut rhs);
330 }
331}
332
333impl Rem<&Number> for &Number {
334 type Output = Number;
335
336 /// Returns `self % rhs`, the remainder of the division truncated toward zero, in the byte
337 /// order of `self`, in the shortest form: it has the sign of `self`, unless it is zero, and a
338 /// magnitude below that of `rhs`.
339 ///
340 /// The remainder is built in one new vector of exactly its length (one byte for zero); both
341 /// operands are left as they were.
342 ///
343 /// # Panics
344 ///
345 /// When `rhs` is zero.
346 ///
347 /// # Examples
348 ///
349 /// ```
350 /// use a::math::numbers::{ByteOrder, Number};
351 ///
352 /// // -7 % 2 = -1 and 7 % -2 = 1, as for `i32`.
353 /// let two = Number::new_from_i32(2, ByteOrder::BigEndian);
354 /// let remainder = &Number::new_from_i32(-7, ByteOrder::BigEndian) % &two;
355 /// assert_eq!(remainder.value, [1]);
356 /// assert!(remainder.is_negative());
357 ///
358 /// let minus_two = Number::new_from_i32(-2, ByteOrder::BigEndian);
359 /// let remainder = &Number::new_from_i32(7, ByteOrder::BigEndian) % &minus_two;
360 /// assert_eq!(remainder.value, [1]);
361 /// assert!(!remainder.is_negative());
362 /// ```
363 #[track_caller]
364 fn rem(self, rhs: &Number) -> Number {
365 if small(self, rhs) {
366 let (_, r) = small_division::<TRUNCATED, true>(self, rhs);
367 return small_number(self.byte_order, r);
368 }
369 ref_by_ref::<TRUNCATED, true>(self, rhs)
370 }
371}
372
373impl Rem<&Number> for Number {
374 type Output = Number;
375
376 /// Returns `self % rhs` as `&self % rhs` does, as `self %= rhs` does.
377 ///
378 /// The remainder is built in the vector of `self`, which has room for it unless `self` is an
379 /// empty vector; `rhs` is left as it was.
380 ///
381 /// # Panics
382 ///
383 /// When `rhs` is zero.
384 ///
385 /// # Examples
386 ///
387 /// ```
388 /// use a::math::numbers::{ByteOrder, Number};
389 ///
390 /// let a = Number::new_from_u32(1_000_003, ByteOrder::LittleEndian);
391 /// let pointer = a.value.as_ptr();
392 /// let remainder = a % &Number::new_from_u16(1000, ByteOrder::BigEndian);
393 /// assert_eq!(remainder.value, [3]);
394 /// assert_eq!(remainder.value.as_ptr(), pointer);
395 /// ```
396 #[track_caller]
397 fn rem(mut self, rhs: &Number) -> Number {
398 self %= rhs;
399 self
400 }
401}
402
403impl Rem<Number> for &Number {
404 type Output = Number;
405
406 /// Returns `self % rhs` as `&self % &rhs` does.
407 ///
408 /// The remainder is built in the vector of `rhs`, which always has room for it, as it is
409 /// shorter than `rhs`, also when `rhs` is in the other byte order. `self` is left as it was.
410 ///
411 /// # Panics
412 ///
413 /// When `rhs` is zero.
414 ///
415 /// # Examples
416 ///
417 /// ```
418 /// use a::math::numbers::{ByteOrder, Number};
419 ///
420 /// let a = Number::new_from_u32(0x01_02_03, ByteOrder::BigEndian);
421 /// let b = Number::new_from_u16(0x0100, ByteOrder::LittleEndian);
422 /// let pointer = b.value.as_ptr();
423 ///
424 /// // 0x01_02_03 % 0x01_00 = 3, big-endian, in the vector of `b`.
425 /// let remainder = &a % b;
426 /// assert_eq!(remainder.value, [3]);
427 /// assert_eq!(remainder.value.as_ptr(), pointer);
428 /// ```
429 #[track_caller]
430 fn rem(self, mut rhs: Number) -> Number {
431 if small(self, &rhs) {
432 let (_, r) = small_division::<TRUNCATED, true>(self, &rhs);
433 put_small(&mut rhs.value, self.byte_order, r);
434 return Number {
435 value: rhs.value,
436 negative: r.negative,
437 byte_order: self.byte_order,
438 };
439 }
440 ref_by_value::<true>(self, &mut rhs)
441 }
442}
443
444impl Rem<Number> for Number {
445 type Output = Number;
446
447 /// Returns `self % rhs` as `&self % &rhs` does, as `self %= rhs` does.
448 ///
449 /// The remainder is built in the vector of `self`, which has room for it unless `self` is an
450 /// empty vector, and then in the vector of `rhs`.
451 ///
452 /// # Panics
453 ///
454 /// When `rhs` is zero.
455 ///
456 /// # Examples
457 ///
458 /// ```
459 /// use a::math::numbers::{ByteOrder, Number};
460 ///
461 /// let a = Number::new_from_i32(-1000, ByteOrder::BigEndian);
462 /// let b = Number::new_from_i32(7, ByteOrder::BigEndian);
463 /// let remainder = a % b;
464 /// // -1000 = 7 (-142) - 6.
465 /// assert_eq!(remainder.value, [6]);
466 /// assert!(remainder.is_negative());
467 /// ```
468 #[track_caller]
469 fn rem(mut self, rhs: Number) -> Number {
470 self %= rhs;
471 self
472 }
473}
474
475impl RemAssign<&Number> for Number {
476 /// Sets `self` to `self % rhs`, keeping the byte order of `self`, in the shortest form.
477 ///
478 /// The remainder is built in the vector of `self`, which has room for it unless `self` is an
479 /// empty vector; `rhs` is left as it was.
480 ///
481 /// # Panics
482 ///
483 /// When `rhs` is zero.
484 ///
485 /// # Examples
486 ///
487 /// ```
488 /// use a::math::numbers::{ByteOrder, Number};
489 ///
490 /// let mut n = Number::new_from_u32(0x0102_0304, ByteOrder::LittleEndian);
491 /// n %= &Number::new_from_u32(0x0001_0000, ByteOrder::BigEndian);
492 /// assert_eq!(n.value, [0x04, 0x03]);
493 /// ```
494 #[inline]
495 #[track_caller]
496 fn rem_assign(&mut self, rhs: &Number) {
497 if small(self, rhs) {
498 let (_, r) = small_division::<TRUNCATED, true>(self, rhs);
499 put_small(&mut self.value, self.byte_order, r);
500 self.negative = r.negative;
501 return;
502 }
503 assign_ref::<true>(self, rhs);
504 }
505}
506
507impl RemAssign<Number> for Number {
508 /// Sets `self` to `self % rhs`, keeping the byte order of `self`, in the shortest form.
509 ///
510 /// The remainder is built in the vector of `self`, which has room for it unless `self` is an
511 /// empty vector, and then in the vector of `rhs`.
512 ///
513 /// # Panics
514 ///
515 /// When `rhs` is zero.
516 ///
517 /// # Examples
518 ///
519 /// ```
520 /// use a::math::numbers::{ByteOrder, Number};
521 ///
522 /// let mut n = Number::new_from_i32(-0x0105, ByteOrder::BigEndian);
523 /// n %= Number::new_from_i32(-0x0100, ByteOrder::BigEndian);
524 /// assert_eq!(n.value, [5]);
525 /// assert!(n.is_negative());
526 /// ```
527 #[inline]
528 #[track_caller]
529 fn rem_assign(&mut self, mut rhs: Number) {
530 if small(self, &rhs) {
531 let (_, r) = small_division::<TRUNCATED, true>(self, &rhs);
532 if self.value.capacity() < r.len {
533 mem::swap(&mut self.value, &mut rhs.value);
534 }
535 put_small(&mut self.value, self.byte_order, r);
536 self.negative = r.negative;
537 return;
538 }
539 assign_value::<true>(self, &mut rhs);
540 }
541}
542
543impl Number {
544 /// Returns the quotient and the remainder of `self` divided by `rhs`, `(self / rhs, self %
545 /// rhs)`, computed together: the quotient truncated toward zero, the remainder with the sign of
546 /// `self`, both in the byte order of `self` and in the shortest form.
547 ///
548 /// Each is built in one new vector of exactly its length (one byte for zero); both operands
549 /// are left as they were.
550 ///
551 /// # Panics
552 ///
553 /// When `rhs` is zero.
554 ///
555 /// # Examples
556 ///
557 /// ```
558 /// use a::math::numbers::{ByteOrder, Number};
559 ///
560 /// // -1000 = 7 (-142) - 6.
561 /// let a = Number::new_from_i32(-1000, ByteOrder::BigEndian);
562 /// let (q, r) = a.div_rem(&Number::new_from_i32(7, ByteOrder::BigEndian));
563 /// assert_eq!(q.value, [142]);
564 /// assert!(q.is_negative());
565 /// assert_eq!(r.value, [6]);
566 /// assert!(r.is_negative());
567 /// ```
568 #[track_caller]
569 pub fn div_rem(&self, rhs: &Number) -> (Number, Number) {
570 if small(self, rhs) {
571 let (q, r) = small_division::<TRUNCATED, false>(self, rhs);
572 return (
573 small_number(self.byte_order, q),
574 small_number(self.byte_order, r),
575 );
576 }
577 both::<TRUNCATED>(self, rhs)
578 }
579
580 /// Returns the quotient of Euclid's division of `self` by `rhs`: the `q` for which `self = rhs
581 /// q + r` with `0 <= r < |rhs|`, in the byte order of `self` and in the shortest form, as
582 /// `i32::div_euclid` gives it.
583 ///
584 /// It is `self / rhs` unless the remainder `self % rhs` is below zero, and then one further
585 /// from zero: `-7 / 2 = -3`, but the Euclidean quotient is `-4`. It is built in one new vector
586 /// of exactly its length.
587 ///
588 /// # Panics
589 ///
590 /// When `rhs` is zero.
591 ///
592 /// # Examples
593 ///
594 /// ```
595 /// use a::math::numbers::{ByteOrder, Number};
596 ///
597 /// let a = Number::new_from_i32(-7, ByteOrder::BigEndian);
598 /// let q = a.div_euclid(&Number::new_from_i32(2, ByteOrder::BigEndian));
599 /// assert_eq!(q.value, [4]);
600 /// assert!(q.is_negative());
601 ///
602 /// let q = a.div_euclid(&Number::new_from_i32(-2, ByteOrder::BigEndian));
603 /// assert_eq!(q.value, [4]);
604 /// assert!(!q.is_negative());
605 /// ```
606 #[track_caller]
607 pub fn div_euclid(&self, rhs: &Number) -> Number {
608 if small(self, rhs) {
609 let (q, _) = small_division::<EUCLID, false>(self, rhs);
610 return small_number(self.byte_order, q);
611 }
612 ref_by_ref::<EUCLID, false>(self, rhs)
613 }
614
615 /// Returns the remainder of Euclid's division of `self` by `rhs`, `self` modulo `|rhs|`: the
616 /// `r` for which `self = rhs q + r` with `0 <= r < |rhs|`, in the byte order of `self` and in
617 /// the shortest form, as `i32::rem_euclid` gives it. It is never negative.
618 ///
619 /// It is `self % rhs` when that is not below zero, and `self % rhs + |rhs|` otherwise. It is
620 /// built in one new vector of exactly its length.
621 ///
622 /// # Panics
623 ///
624 /// When `rhs` is zero.
625 ///
626 /// # Examples
627 ///
628 /// ```
629 /// use a::math::numbers::{ByteOrder, Number};
630 ///
631 /// let a = Number::new_from_i32(-7, ByteOrder::BigEndian);
632 /// let r = a.rem_euclid(&Number::new_from_i32(2, ByteOrder::BigEndian));
633 /// assert_eq!(r.value, [1]);
634 /// assert!(!r.is_negative());
635 ///
636 /// let r = a.rem_euclid(&Number::new_from_i32(-2, ByteOrder::BigEndian));
637 /// assert_eq!(r.value, [1]);
638 /// assert!(!r.is_negative());
639 /// ```
640 #[track_caller]
641 pub fn rem_euclid(&self, rhs: &Number) -> Number {
642 if small(self, rhs) {
643 let (_, r) = small_division::<EUCLID, true>(self, rhs);
644 return small_number(self.byte_order, r);
645 }
646 ref_by_ref::<EUCLID, true>(self, rhs)
647 }
648}
649
650impl Number {
651 /// Returns the quotient of `self` divided by `rhs` rounded toward negative infinity, `⌊self /
652 /// rhs⌋`, in the byte order of `self` and in the shortest form, as Python's `//` and GMP's
653 /// `mpz_fdiv_q` give it.
654 ///
655 /// It is `self / rhs` unless the remainder `self % rhs` is not zero and the operands have
656 /// different signs, and then one less: `-7 / 2 = -3`, but `⌊-7 / 2⌋ = -4`. For a positive
657 /// `rhs` it is [`div_euclid`](Self::div_euclid); for a negative one, `-((-self).div_euclid(rhs))`,
658 /// which is how it is computed, with `-self` a view of `self` with the other sign, so that it
659 /// costs what `div_euclid` does.
660 ///
661 /// # Panics
662 ///
663 /// When `rhs` is zero.
664 ///
665 /// # Examples
666 ///
667 /// ```
668 /// use a::math::numbers::{ByteOrder, Number};
669 ///
670 /// let a = Number::new_from_i32(-7, ByteOrder::BigEndian);
671 /// assert_eq!(a.div_floor(&Number::from(2)), -4);
672 /// assert_eq!(a.div_floor(&Number::from(-2)), 3);
673 /// assert_eq!(Number::from(7).div_floor(&Number::from(-2)), -4);
674 /// ```
675 #[track_caller]
676 pub fn div_floor(&self, rhs: &Number) -> Number {
677 if rhs.is_negative() {
678 -Negated::new(self).div_euclid(rhs)
679 } else {
680 self.div_euclid(rhs)
681 }
682 }
683
684 /// Returns the remainder of `self` divided by `rhs` rounded toward negative infinity, `self -
685 /// rhs·⌊self / rhs⌋`, in the byte order of `self` and in the shortest form, as Python's `%`
686 /// and GMP's `mpz_fdiv_r` give it: it has the sign of `rhs`, unless it is zero, and a magnitude
687 /// below that of `rhs`.
688 ///
689 /// For a positive `rhs` it is [`rem_euclid`](Self::rem_euclid); for a negative one,
690 /// `-((-self).rem_euclid(rhs))`, computed as [`div_floor`](Self::div_floor) is.
691 ///
692 /// # Panics
693 ///
694 /// When `rhs` is zero.
695 ///
696 /// # Examples
697 ///
698 /// ```
699 /// use a::math::numbers::{ByteOrder, Number};
700 ///
701 /// let a = Number::new_from_i32(-7, ByteOrder::BigEndian);
702 /// assert_eq!(a.rem_floor(&Number::from(2)), 1);
703 /// assert_eq!(a.rem_floor(&Number::from(-2)), -1);
704 /// assert_eq!(Number::from(7).rem_floor(&Number::from(-2)), -1);
705 /// ```
706 #[track_caller]
707 pub fn rem_floor(&self, rhs: &Number) -> Number {
708 if rhs.is_negative() {
709 -Negated::new(self).rem_euclid(rhs)
710 } else {
711 self.rem_euclid(rhs)
712 }
713 }
714}
715
716/// The division whose quotient is truncated toward zero, and whose remainder has the sign of the
717/// dividend: `/`, `%` and `div_rem`.
718pub(super) const TRUNCATED: bool = false;
719
720/// Euclid's division, whose remainder is never negative: `div_euclid` and `rem_euclid`.
721pub(super) const EUCLID: bool = true;
722
723/// Panics for a division by zero, with the message of the primitive integers: of `%` when
724/// `REM`, of `/` otherwise.
725#[cold]
726#[inline(never)]
727#[track_caller]
728pub(super) fn by_zero<const REM: bool>() -> ! {
729 if REM {
730 panic!("attempt to calculate the remainder with a divisor of zero")
731 } else {
732 panic!("attempt to divide by zero")
733 }
734}
735
736// Small numbers
737
738/// A quotient or a remainder of two small operands, as the small path computes it in registers.
739#[derive(Clone, Copy)]
740struct Small {
741 /// The low eight bytes of the magnitude.
742 lo: u64,
743 /// The next eight bytes of the magnitude.
744 hi: u64,
745 /// The length in the shortest form, from 1 to 16: one byte for zero.
746 len: usize,
747 /// Whether it is negative; never for zero.
748 negative: bool,
749}
750
751impl Small {
752 /// The magnitude `m` with the sign `negative`, which zero does not keep.
753 #[inline(always)]
754 fn of(m: u128, negative: bool) -> Small {
755 Small {
756 lo: m as u64,
757 hi: (m >> 64) as u64,
758 len: 16 - (m | 1).leading_zeros() as usize / 8,
759 negative: negative && m != 0,
760 }
761 }
762}
763
764/// The quotient and the remainder of the small operands `a` and `b`: truncated, or Euclid's with
765/// `EUCLIDEAN`. Panics with the message of `%` when `REM`, of `/` otherwise, when `b` is zero.
766#[inline(always)]
767#[track_caller]
768fn small_division<const EUCLIDEAN: bool, const REM: bool>(
769 a: &Number,
770 b: &Number,
771) -> (Small, Small) {
772 // SAFETY: both vectors hold at most 16 bytes, as `small` checked.
773 let (x, y) = unsafe {
774 (
775 read_small(&a.value, a.byte_order),
776 read_small(&b.value, b.byte_order),
777 )
778 };
779 if y == 0 {
780 by_zero::<REM>();
781 }
782 let (q, r) = div_u128(x, y);
783 let negative_a = a.negative && x != 0;
784 if EUCLIDEAN && negative_a && r != 0 {
785 // One further from zero, which leaves the remainder `y - r`: with `r != 0`, `y >= 2`, and
786 // `q <= x / 2` does not overflow.
787 return (
788 Small::of(q + 1, a.negative != b.negative),
789 Small::of(y - r, false),
790 );
791 }
792 (
793 Small::of(q, a.negative != b.negative),
794 Small::of(r, negative_a && !EUCLIDEAN),
795 )
796}
797
798/// The quotient and the remainder of `x` by `y > 0`: by the hardware's division when both fit in
799/// a limb; by a divisor of one limb, normalized, its reciprocal computed and the two limbs of `x`
800/// divided by [`div_2by1`] steps, when only `y` does, which took 30 cycles instead of the 56 of the
801/// `u128` division of the compiler's runtime on an Apple M4 Max; and by that division otherwise,
802/// whose quotient is then a single limb.
803#[inline(always)]
804fn div_u128(x: u128, y: u128) -> (u128, u128) {
805 if y >> 64 == 0 {
806 let y = y as u64;
807 if x >> 64 == 0 {
808 let x = x as u64;
809 return (u128::from(x / y), u128::from(x % y));
810 }
811 let s = y.leading_zeros();
812 let (d, u) = (y << s, x << s);
813 let v = invert_limb(d);
814 // The bits shifted out of the top, below `2^s`, are below `d`.
815 let top = ((x >> 64) as u64 >> 1) >> (63 - s);
816 let (q1, t) = div_2by1(top, (u >> 64) as u64, d, v);
817 let (q0, r) = div_2by1(t, u as u64, d, v);
818 return ((u128::from(q1) << 64) | u128::from(q0), u128::from(r >> s));
819 }
820 (x / y, x % y)
821}
822
823/// Writes the small result `s` as the whole value of `v`, in its vector when it has room, in a new
824/// one otherwise.
825#[inline(always)]
826fn put_small(v: &mut Vec<u8>, order: ByteOrder, s: Small) {
827 if v.capacity() >= s.len {
828 // SAFETY: the vector has room for the `s.len` bytes, all of which are written before the
829 // length is set.
830 unsafe {
831 write_small(v.as_mut_ptr(), order, s.lo, s.hi, s.len);
832 v.set_len(s.len);
833 }
834 } else {
835 replace_small(v, order, s);
836 }
837}
838
839/// Replaces `v` with one new vector of exactly the small result's length, holding it. Out of line
840/// and cold, so that the small path saves no registers for it.
841#[cold]
842#[inline(never)]
843fn replace_small(v: &mut Vec<u8>, order: ByteOrder, s: Small) {
844 *v = new_small(order, s);
845}
846
847/// The small result `s` in one new vector of exactly its length.
848#[inline(always)]
849fn new_small(order: ByteOrder, s: Small) -> Vec<u8> {
850 let mut v = Vec::with_capacity(s.len);
851 // SAFETY: the new vector has room for the `s.len` bytes, all of which are written before the
852 // length is set.
853 unsafe {
854 write_small(v.as_mut_ptr(), order, s.lo, s.hi, s.len);
855 v.set_len(s.len);
856 }
857 v
858}
859
860/// The small result `s` as a number in one new vector, in the byte order `order`. Out of line, so
861/// that the small path saves no registers for the allocation.
862#[inline(never)]
863fn small_number(order: ByteOrder, s: Small) -> Number {
864 Number {
865 value: new_small(order, s),
866 negative: s.negative,
867 byte_order: order,
868 }
869}
870
871// Dividends of up to 64 bytes by divisors of up to 32
872
873/// The longest vector, in bytes, of a dividend that [`wider_division`] divides in registers.
874pub(super) const WIDER: usize = 64;
875
876/// Whether `a / b` is computed in registers by [`register_division`]: the dividend's vector holds
877/// at most [`WIDER`] bytes and the divisor's at most [`WIDE`].
878#[inline(always)]
879fn wide(a: &Number, b: &Number) -> bool {
880 a.value.len() <= WIDER && b.value.len() <= WIDE
881}
882
883/// The quotient and the remainder of a dividend of up to 64 bytes by a divisor of up to 32: by a
884/// divisor of up to 16 significant bytes, as [`wide_division`] computes them up to 32 bytes and
885/// [`wider_division`] beyond; by a longer one, as [`wider_by_wide`] does. Panics with the message
886/// of `%` when `REM`, of `/` otherwise, when the divisor is zero.
887///
888/// # Safety
889///
890/// As for [`wider_division`], and the divisor's vector must hold at most [`WIDE`] bytes.
891#[inline(always)]
892#[track_caller]
893unsafe fn register_division<const EUCLIDEAN: bool, const REM: bool>(
894 a: &Number,
895 b: &Number,
896) -> (Wide, Wide) {
897 // SAFETY: as the caller guarantees, with the length checked for the shorter one.
898 unsafe {
899 let y = if b.value.len() <= SMALL {
900 read_small(&b.value, b.byte_order)
901 } else {
902 let y = read_wide(&b.value, b.byte_order);
903 if y[2] | y[3] != 0 {
904 return by_medium::<EUCLIDEAN>(a, Medium::of(y, b.negative));
905 }
906 u128::from(y[0]) | (u128::from(y[1]) << 64)
907 };
908 if y == 0 {
909 by_zero::<REM>();
910 }
911 let y = Short::of(y, b.negative);
912 if a.value.len() <= WIDE {
913 wide_division::<EUCLIDEAN, 4>(a, y)
914 } else {
915 wider_division::<EUCLIDEAN>(a, y)
916 }
917 }
918}
919
920/// A divisor of up to 16 bytes, not zero, as the divisions in registers use it: its magnitude
921/// `y`, the shift `s` that sets its top bit and the magnitude so shifted, `d`, the reciprocal `v`
922/// of `d`'s top limb when `y` is one limb and of both otherwise, and its sign.
923#[derive(Clone, Copy)]
924pub(super) struct Short {
925 pub(super) y: u128,
926 s: u32,
927 d: u128,
928 v: u64,
929 negative: bool,
930}
931
932impl Short {
933 /// The magnitude `y`, not zero, and the sign `negative`, prepared.
934 #[inline(always)]
935 pub(super) fn of(y: u128, negative: bool) -> Short {
936 let (y1, y0) = ((y >> 64) as u64, y as u64);
937 let s = if y1 == 0 {
938 y0.leading_zeros()
939 } else {
940 y1.leading_zeros()
941 };
942 let d = y << s;
943 let v = if y1 == 0 {
944 invert_limb(d as u64)
945 } else {
946 invert_3by2((d >> 64) as u64, d as u64)
947 };
948 Short {
949 y,
950 s,
951 d,
952 v,
953 negative,
954 }
955 }
956}
957
958/// The quotient and the remainder of a dividend of up to `8 LIMBS` bytes, 16 or 32, by the short
959/// divisor `y`, truncated, or Euclid's with `EUCLIDEAN`, computed in registers. The dividend is
960/// read as limbs, as the addition or the multiplication reads it, shifted so that the divisor's top
961/// bit is set, and its limbs divided by [`div_2by1`] steps for a divisor of one limb, or
962/// [`div_3by2`] steps for two, unrolled.
963///
964/// # Safety
965///
966/// The dividend's vector must hold at most `8 LIMBS` bytes.
967#[inline(always)]
968pub(super) unsafe fn wide_division<const EUCLIDEAN: bool, const LIMBS: usize>(
969 a: &Number,
970 y: Short,
971) -> (Wide, Wide) {
972 // SAFETY: as the caller guarantees.
973 let x = unsafe {
974 if LIMBS == 2 {
975 let x = read_small(&a.value, a.byte_order);
976 [x as u64, (x >> 64) as u64, 0, 0]
977 } else {
978 read_wide(&a.value, a.byte_order)
979 }
980 };
981 let u = shifted(x, y.s);
982 let mut q = [0; 4];
983 let r = if y.y >> 64 == 0 {
984 let d = y.d as u64;
985 let mut t = u[LIMBS];
986 for i in (0..LIMBS).rev() {
987 (q[i], t) = div_2by1(t, u[i], d, y.v);
988 }
989 u128::from(t >> y.s)
990 } else {
991 let (d1, d0) = ((y.d >> 64) as u64, y.d as u64);
992 let (mut t1, mut t0) = (u[LIMBS], u[LIMBS - 1]);
993 for i in (0..LIMBS - 1).rev() {
994 (q[i], t1, t0) = div_3by2(t1, t0, u[i], d1, d0, y.v);
995 }
996 ((u128::from(t1) << 64) | u128::from(t0)) >> y.s
997 };
998 let negative_a = a.negative && x != [0; 4];
999 if EUCLIDEAN && negative_a && r != 0 {
1000 // One further from zero, which leaves the remainder `y - r`: with `r != 0`, `y >= 2`, and
1001 // the quotient, at most half the dividend, does not overflow.
1002 let mut carry = true;
1003 for l in &mut q {
1004 (*l, carry) = l.overflowing_add(u64::from(carry));
1005 }
1006 return wide_results::<true>(q4(q), y.y - r, a.negative != y.negative, false);
1007 }
1008 // The quotient's length without a branch by one limb, whose quotients of 24 or 25 bytes for
1009 // a dividend of 32 are a coin toss; by two, where it took 82 cycles against 75 for 32 bytes
1010 // by 16, with one.
1011 if y.y >> 64 == 0 {
1012 wide_results::<true>(q4(q), r, a.negative != y.negative, negative_a && !EUCLIDEAN)
1013 } else {
1014 wide_results::<false>(q4(q), r, a.negative != y.negative, negative_a && !EUCLIDEAN)
1015 }
1016}
1017
1018/// The four limbs `q` as eight.
1019#[inline(always)]
1020fn q4(q: [u64; 4]) -> [u64; 8] {
1021 [q[0], q[1], q[2], q[3], 0, 0, 0, 0]
1022}
1023
1024/// The quotient `q` and the remainder `r` of a division in registers as results to write, with the
1025/// signs `negative_q` and `negative_r`, which zero does not keep; the quotient's length found
1026/// without a branch with `BRANCHLESS` (see [`wide_of`]).
1027#[inline(always)]
1028fn wide_results<const BRANCHLESS: bool>(
1029 q: [u64; 8],
1030 r: u128,
1031 negative_q: bool,
1032 negative_r: bool,
1033) -> (Wide, Wide) {
1034 (
1035 wide_of::<BRANCHLESS>(q, negative_q),
1036 wide_of::<false>([r as u64, (r >> 64) as u64, 0, 0, 0, 0, 0, 0], negative_r),
1037 )
1038}
1039
1040/// [`wide_division`] for a dividend of 33 to 64 bytes: its limbs are read shifted into memory, and
1041/// divided by a loop of steps.
1042///
1043/// # Safety
1044///
1045/// The dividend's vector must hold at most [`WIDER`] bytes.
1046#[inline(always)]
1047pub(super) unsafe fn wider_division<const EUCLIDEAN: bool>(a: &Number, y: Short) -> (Wide, Wide) {
1048 let x = Operand {
1049 ptr: a.value.as_ptr(),
1050 len: a.value.len(),
1051 big_endian: a.byte_order == ByteOrder::BigEndian,
1052 significant: a.value.len(),
1053 };
1054 let n = x.len.div_ceil(8);
1055 let mut u = [0; 9];
1056 // SAFETY: the dividend's `n <= 8` limbs and the one above them fit.
1057 unsafe { u[n] = to_limbs_shifted(x, u.as_mut_ptr(), y.s) };
1058 let mut q = [0; 8];
1059 let r = if y.y >> 64 == 0 {
1060 let d = y.d as u64;
1061 let mut t = u[n];
1062 for i in (0..n).rev() {
1063 (q[i], t) = div_2by1(t, u[i], d, y.v);
1064 }
1065 u128::from(t >> y.s)
1066 } else {
1067 let (d1, d0) = ((y.d >> 64) as u64, y.d as u64);
1068 let (mut t1, mut t0) = (u[n], u[n - 1]);
1069 for i in (0..n - 1).rev() {
1070 (q[i], t1, t0) = div_3by2(t1, t0, u[i], d1, d0, y.v);
1071 }
1072 ((u128::from(t1) << 64) | u128::from(t0)) >> y.s
1073 };
1074 let negative_a = a.negative && u != [0; 9];
1075 if EUCLIDEAN && negative_a && r != 0 {
1076 // As in `wide_division`.
1077 let mut carry = true;
1078 for l in &mut q {
1079 (*l, carry) = l.overflowing_add(u64::from(carry));
1080 }
1081 return wide_results::<false>(q, y.y - r, a.negative != y.negative, false);
1082 }
1083 wide_results::<false>(q, r, a.negative != y.negative, negative_a && !EUCLIDEAN)
1084}
1085
1086/// A divisor of three or four limbs, 17 to 32 significant bytes, as [`wider_by_wide`] uses it: its
1087/// limbs `d` shifted left by `s` bits so that the top bit of the top one is set, their number
1088/// `n`, the reciprocal `v` of their top two, and its sign.
1089#[derive(Clone, Copy)]
1090pub(super) struct Medium {
1091 d: [u64; 4],
1092 s: u32,
1093 n: usize,
1094 v: u64,
1095 negative: bool,
1096}
1097
1098impl Medium {
1099 /// The magnitude of the limbs `y`, of which the third or the fourth is not zero, and the sign
1100 /// `negative`, prepared.
1101 #[inline(always)]
1102 pub(super) fn of(y: [u64; 4], negative: bool) -> Medium {
1103 let n = if y[3] != 0 { 4 } else { 3 };
1104 let s = y[n - 1].leading_zeros();
1105 let above = |l: u64| (l >> 1) >> (63 - s);
1106 let d = [
1107 y[0] << s,
1108 (y[1] << s) | above(y[0]),
1109 (y[2] << s) | above(y[1]),
1110 (y[3] << s) | above(y[2]),
1111 ];
1112 let v = invert_3by2(d[n - 1], d[n - 2]);
1113 Medium {
1114 d,
1115 s,
1116 n,
1117 v,
1118 negative,
1119 }
1120 }
1121
1122 /// The divisor normalized in the `n` limbs at `d` by the shift `s`, `n` three or four, their
1123 /// reciprocal `v`, and the sign `negative`.
1124 ///
1125 /// # Safety
1126 ///
1127 /// The limbs at `d` must be valid for reads.
1128 #[inline(always)]
1129 pub(super) unsafe fn normalized(
1130 d: *const u64,
1131 n: usize,
1132 s: u32,
1133 v: u64,
1134 negative: bool,
1135 ) -> Medium {
1136 let mut limbs = [0; 4];
1137 // SAFETY: as the caller guarantees.
1138 unsafe { ptr::copy_nonoverlapping(d, limbs.as_mut_ptr(), n) };
1139 Medium {
1140 d: limbs,
1141 s,
1142 n,
1143 v,
1144 negative,
1145 }
1146 }
1147}
1148
1149/// The quotient and the remainder of a dividend of up to 64 bytes by the divisor `y`, by
1150/// [`wider_by_wide`] for its number of limbs.
1151///
1152/// # Safety
1153///
1154/// The dividend's vector must hold at most [`WIDER`] bytes.
1155#[inline(always)]
1156pub(super) unsafe fn by_medium<const EUCLIDEAN: bool>(a: &Number, y: Medium) -> (Wide, Wide) {
1157 // SAFETY: as the caller guarantees.
1158 unsafe {
1159 if y.n == 4 {
1160 wider_by_wide::<EUCLIDEAN, 4>(a, y)
1161 } else {
1162 wider_by_wide::<EUCLIDEAN, 3>(a, y)
1163 }
1164 }
1165}
1166
1167/// The quotient and the remainder of a dividend of up to 64 bytes by the divisor `y` of `NY`
1168/// limbs, truncated, or Euclid's with `EUCLIDEAN`: the steps of the schoolbook division on limbs
1169/// in arrays, the divisor's top two and their reciprocal in registers, and the products of a
1170/// quotient limb by its other one or two limbs inline.
1171///
1172/// # Safety
1173///
1174/// The dividend's vector must hold at most [`WIDER`] bytes.
1175#[inline(always)]
1176unsafe fn wider_by_wide<const EUCLIDEAN: bool, const NY: usize>(
1177 a: &Number,
1178 y: Medium,
1179) -> (Wide, Wide) {
1180 debug_assert!(y.n == NY);
1181 let (ny, d, s, v) = (NY, y.d, y.s, y.v);
1182 let x = Operand {
1183 ptr: a.value.as_ptr(),
1184 len: a.value.len(),
1185 big_endian: a.byte_order == ByteOrder::BigEndian,
1186 significant: a.value.len(),
1187 };
1188 let n = x.len.div_ceil(8);
1189 let mut u = [0; 9];
1190 // SAFETY: the dividend's `n <= 8` limbs and the one above them fit.
1191 unsafe { u[n] = to_limbs_shifted(x, u.as_mut_ptr(), s) };
1192 let negative_a = a.negative && u != [0; 9];
1193 let (d1, d0) = (d[ny - 1], d[ny - 2]);
1194 let mut q = [0; 8];
1195 let nn = n.max(ny);
1196 // Without bits shifted out above the dividend, the top quotient limb is 0 or 1, from a
1197 // comparison instead of a step, as for the general path.
1198 let steps = if u[nn] == 0 {
1199 let k = nn - ny;
1200 if (0..ny)
1201 .rev()
1202 .map(|j| u[k + j].cmp(&d[j]))
1203 .find(|o| o.is_ne())
1204 != Some(Less)
1205 {
1206 let mut borrow = false;
1207 for j in 0..ny {
1208 let (l, b1) = u[k + j].overflowing_sub(d[j]);
1209 let (l, b2) = l.overflowing_sub(u64::from(borrow));
1210 (u[k + j], borrow) = (l, b1 | b2);
1211 }
1212 q[k] = 1;
1213 }
1214 k
1215 } else {
1216 nn - ny + 1
1217 };
1218 // The limb above the dividend's is below `d1`, whose top bit is set, and each step leaves the
1219 // partial remainder below the divisor: the top two limbs of a step are at most `d1 B + d0`.
1220 for i in (0..steps).rev() {
1221 let (u2, u1) = (u[i + ny], u[i + ny - 1]);
1222 if u2 == d1 && u1 == d0 {
1223 q[i] = all_ones_step(&mut u, i, &d, ny);
1224 continue;
1225 }
1226 let (mut qi, mut r1, mut r0) = div_3by2(u2, u1, u[i + ny - 2], d1, d0, v);
1227 // The quotient limb times the divisor's limbs below its top two.
1228 let mut borrow = 0;
1229 for j in 0..ny - 2 {
1230 let p = u128::from(qi) * u128::from(d[j]) + u128::from(borrow);
1231 let (l, b) = u[i + j].overflowing_sub(p as u64);
1232 u[i + j] = l;
1233 borrow = (p >> 64) as u64 + u64::from(b);
1234 }
1235 let b0;
1236 (r0, b0) = r0.overflowing_sub(borrow);
1237 let b1;
1238 (r1, b1) = r1.overflowing_sub(u64::from(b0));
1239 if b1 {
1240 // One too large: the divisor is added back.
1241 let mut carry = false;
1242 for j in 0..ny - 2 {
1243 (u[i + j], carry) = carrying(u[i + j], d[j], carry);
1244 }
1245 (r0, carry) = carrying(r0, d0, carry);
1246 r1 = r1.wrapping_add(d1).wrapping_add(u64::from(carry));
1247 qi -= 1;
1248 }
1249 (u[i + ny - 2], u[i + ny - 1], u[i + ny]) = (r0, r1, 0);
1250 q[i] = qi;
1251 }
1252 let remainder = u[..ny] != [0; NY];
1253 if EUCLIDEAN && negative_a && remainder {
1254 // One further from zero, which leaves the remainder `y - r`, from the limbs as they are
1255 // shifted: the quotient, below `B^6` as the divisor is at least `B^2`, does not overflow.
1256 let mut carry = true;
1257 for l in &mut q {
1258 (*l, carry) = l.overflowing_add(u64::from(carry));
1259 }
1260 let mut borrow = false;
1261 for j in 0..ny {
1262 let (l, b1) = d[j].overflowing_sub(u[j]);
1263 let (l, b2) = l.overflowing_sub(u64::from(borrow));
1264 (u[j], borrow) = (l, b1 | b2);
1265 }
1266 }
1267 // The remainder, shifted back: `(l << 1) << (63 - s)` is `l << (64 - s)`, and zero for `s = 0`.
1268 let below = |l: u64| (l << 1) << (63 - s);
1269 let mut r = [0; 8];
1270 for j in 0..ny {
1271 r[j] = (u[j] >> s) | below(u[j + 1]);
1272 }
1273 (
1274 wide_of::<false>(q, a.negative != y.negative),
1275 wide_of::<false>(r, negative_a && !EUCLIDEAN),
1276 )
1277}
1278
1279/// `a + b + carry` and its carry out.
1280#[inline(always)]
1281fn carrying(a: u64, b: u64, carry: bool) -> (u64, bool) {
1282 let (s, c1) = a.overflowing_add(b);
1283 let (s, c2) = s.overflowing_add(u64::from(carry));
1284 (s, c1 | c2)
1285}
1286
1287/// The step of [`wider_by_wide`] whose partial remainder, in limbs `i..=i + ny` of `u`, has the
1288/// top two limbs of the normalized divisor `d` of `ny` limbs, which `div_3by2` cannot divide: its
1289/// quotient limb is `B - 1`, as in `sb_div_qr`, and `(B - 1) d` is subtracted, which cancels the
1290/// top limb. Returns the quotient limb.
1291#[cold]
1292#[inline(never)]
1293fn all_ones_step(u: &mut [u64; 9], i: usize, d: &[u64; 4], ny: usize) -> u64 {
1294 // `(B - 1) d = d B - d`: `d` added, and `d` subtracted one limb up.
1295 let mut carry = false;
1296 for j in 0..ny {
1297 (u[i + j], carry) = carrying(u[i + j], d[j], carry);
1298 }
1299 u[i + ny] = u[i + ny].wrapping_add(u64::from(carry));
1300 let mut borrow = false;
1301 for j in 0..ny {
1302 let (l, b1) = u[i + j + 1].overflowing_sub(d[j]);
1303 let (l, b2) = l.overflowing_sub(u64::from(borrow));
1304 (u[i + j + 1], borrow) = (l, b1 | b2);
1305 }
1306 debug_assert!(u[i + ny] == 0, "the top limb cancels");
1307 u64::MAX
1308}
1309
1310/// The four limbs `x` shifted left by `s` bits, `s < 64`, into five.
1311#[inline(always)]
1312fn shifted(x: [u64; 4], s: u32) -> [u64; 5] {
1313 // `(l >> 1) >> (63 - s)` is `l >> (64 - s)`, and zero for `s = 0`, with shifts below 64.
1314 let out = |l: u64| (l >> 1) >> (63 - s);
1315 [
1316 x[0] << s,
1317 (x[1] << s) | out(x[0]),
1318 (x[2] << s) | out(x[1]),
1319 (x[3] << s) | out(x[2]),
1320 out(x[3]),
1321 ]
1322}
1323
1324/// The limbs `l` as a result of a division in registers, with its length in the shortest form
1325/// and the sign `negative`, which zero does not keep; the length found without a branch with
1326/// `BRANCHLESS`.
1327///
1328/// Whether a quotient's top limb is zero is as good as random, and a mispredicted branch on it
1329/// cost a third of a division of 32 bytes by 8, measured on an Apple M4 Max: 77 cycles against
1330/// 65. That is for the quotient of [`wide_division`], whose limbs are in registers; for those of
1331/// [`wider_division`] and [`wider_by_wide`], in memory, the length found without a branch made
1332/// the stores of the result wait for all of them, and a division of 64 bytes by 8 took 160
1333/// cycles against 110.
1334#[inline(always)]
1335fn wide_of<const BRANCHLESS: bool>(l: [u64; 8], negative: bool) -> Wide {
1336 let len = if BRANCHLESS {
1337 // The top limb that is not zero, `t`, from a bit for each, and its bytes; zero is one
1338 // byte, of limb 0.
1339 let mut nonzero = 1;
1340 for (i, &x) in l.iter().enumerate() {
1341 nonzero |= u32::from(x != 0) << i;
1342 }
1343 let t = 31 - nonzero.leading_zeros() as usize;
1344 (8 * t + 8 - l[t].leading_zeros() as usize / 8).max(1)
1345 } else {
1346 match l.iter().rposition(|&x| x != 0) {
1347 Some(t) => 8 * t + 8 - l[t].leading_zeros() as usize / 8,
1348 None => 1,
1349 }
1350 };
1351 Wide {
1352 limbs: l,
1353 len,
1354 negative: negative && l != [0; 8],
1355 }
1356}
1357
1358/// The result `w` of [`wide_division`] as a number in one new vector of exactly its length.
1359#[inline(always)]
1360pub(super) fn wide_number(order: ByteOrder, w: &Wide) -> Number {
1361 let mut value = Vec::new();
1362 put_wide(&mut value, order, w);
1363 Number {
1364 value,
1365 negative: w.negative,
1366 byte_order: order,
1367 }
1368}
1369
1370// The general path: operands of more than 16 bytes, out of line, so that the small path saves no
1371// registers for it.
1372
1373/// The operands of a division with at least one of more than 16 bytes, read for the general path;
1374/// panics with the message of `%` when `REM`, of `/` otherwise, when the divisor is zero.
1375#[inline(always)]
1376#[track_caller]
1377fn operands<const REM: bool>(a: &Number, b: &Number) -> (Operand, Operand) {
1378 let (x, y) = (Operand::of(a), Operand::of(b));
1379 if y.significant == 0 {
1380 by_zero::<REM>();
1381 }
1382 (x, y)
1383}
1384
1385/// `a / b` (`a % b` when `REM`; Euclid's with `EUCLIDEAN`) for borrowed operands, in one new
1386/// vector.
1387#[inline(never)]
1388#[track_caller]
1389fn ref_by_ref<const EUCLIDEAN: bool, const REM: bool>(a: &Number, b: &Number) -> Number {
1390 let order = a.byte_order;
1391 if wide(a, b) {
1392 // SAFETY: the vectors hold at most 64 and 32 bytes.
1393 let (q, r) = unsafe { register_division::<EUCLIDEAN, REM>(a, b) };
1394 return wide_number(order, if REM { &r } else { &q });
1395 }
1396 let (x, y) = operands::<REM>(a, b);
1397 // SAFETY: the operands are those of `a` and `b`, which are borrowed until the result is
1398 // computed.
1399 unsafe {
1400 divide::<EUCLIDEAN, _>(
1401 x,
1402 y,
1403 a.negative,
1404 b.negative,
1405 Want::of(EUCLIDEAN, REM),
1406 |q, r| new_number(if REM { r } else { q }, order),
1407 )
1408 }
1409}
1410
1411/// `div_rem` for borrowed operands: both results, in one new vector each.
1412#[inline(never)]
1413#[track_caller]
1414fn both<const EUCLIDEAN: bool>(a: &Number, b: &Number) -> (Number, Number) {
1415 let order = a.byte_order;
1416 if wide(a, b) {
1417 // SAFETY: the vectors hold at most 64 and 32 bytes.
1418 let (q, r) = unsafe { register_division::<EUCLIDEAN, false>(a, b) };
1419 return (wide_number(order, &q), wide_number(order, &r));
1420 }
1421 let (x, y) = operands::<false>(a, b);
1422 // SAFETY: as in `ref_by_ref`.
1423 unsafe {
1424 divide::<EUCLIDEAN, _>(x, y, a.negative, b.negative, Want::Both, |q, r| {
1425 (new_number(q, order), new_number(r, order))
1426 })
1427 }
1428}
1429
1430/// `a / b` (`a % b` when `REM`) for a borrowed `a` and an owned `b`: the result takes the vector of
1431/// `b` when it is built there, leaving `b` an empty one; the caller drops `b` either way.
1432#[inline(never)]
1433#[track_caller]
1434fn ref_by_value<const REM: bool>(a: &Number, b: &mut Number) -> Number {
1435 let order = a.byte_order;
1436 if wide(a, b) {
1437 // SAFETY: the vectors hold at most 64 and 32 bytes.
1438 let (q, r) = unsafe { register_division::<TRUNCATED, REM>(a, b) };
1439 let w = if REM { &r } else { &q };
1440 put_wide(&mut b.value, order, w);
1441 return Number {
1442 value: mem::take(&mut b.value),
1443 negative: w.negative,
1444 byte_order: order,
1445 };
1446 }
1447 let (x, y) = operands::<REM>(a, b);
1448 // SAFETY: the operands are those of `a` and `b`; `b`'s vector is written only once both are
1449 // read into limbs.
1450 unsafe {
1451 divide::<TRUNCATED, _>(
1452 x,
1453 y,
1454 a.negative,
1455 b.negative,
1456 Want::of(TRUNCATED, REM),
1457 |q, r| {
1458 let p = if REM { r } else { q };
1459 p.put_in(&mut b.value, order);
1460 Number {
1461 value: mem::take(&mut b.value),
1462 negative: p.negative,
1463 byte_order: order,
1464 }
1465 },
1466 )
1467 }
1468}
1469
1470/// `a /= b` (`a %= b` when `REM`) for a borrowed `b`.
1471#[inline(never)]
1472#[track_caller]
1473fn assign_ref<const REM: bool>(a: &mut Number, b: &Number) {
1474 let order = a.byte_order;
1475 if wide(a, b) {
1476 // SAFETY: the vectors hold at most 64 and 32 bytes.
1477 let (q, r) = unsafe { register_division::<TRUNCATED, REM>(a, b) };
1478 let w = if REM { &r } else { &q };
1479 put_wide(&mut a.value, order, w);
1480 a.negative = w.negative;
1481 return;
1482 }
1483 let (x, y) = operands::<REM>(a, b);
1484 // SAFETY: the operands are those of `a` and `b`; `a`'s vector is written only once both are
1485 // read into limbs.
1486 unsafe {
1487 divide::<TRUNCATED, _>(
1488 x,
1489 y,
1490 a.negative,
1491 b.negative,
1492 Want::of(TRUNCATED, REM),
1493 |q, r| {
1494 let p = if REM { r } else { q };
1495 p.put_in(&mut a.value, order);
1496 a.negative = p.negative;
1497 },
1498 );
1499 }
1500}
1501
1502/// `a /= b` (`a %= b` when `REM`) for an owned `b`: when the result is built in the vector of `b`,
1503/// the vector of `a` goes to `b`; the caller drops `b` either way.
1504#[inline(never)]
1505#[track_caller]
1506fn assign_value<const REM: bool>(a: &mut Number, b: &mut Number) {
1507 let order = a.byte_order;
1508 if wide(a, b) {
1509 // SAFETY: the vectors hold at most 64 and 32 bytes.
1510 let (q, r) = unsafe { register_division::<TRUNCATED, REM>(a, b) };
1511 let w = if REM { &r } else { &q };
1512 if a.value.capacity() < w.len && b.value.capacity() >= w.len {
1513 mem::swap(&mut a.value, &mut b.value);
1514 }
1515 put_wide(&mut a.value, order, w);
1516 a.negative = w.negative;
1517 return;
1518 }
1519 let (x, y) = operands::<REM>(a, b);
1520 // SAFETY: as in `assign_ref`.
1521 unsafe {
1522 divide::<TRUNCATED, _>(
1523 x,
1524 y,
1525 a.negative,
1526 b.negative,
1527 Want::of(TRUNCATED, REM),
1528 |q, r| {
1529 let p = if REM { r } else { q };
1530 if a.value.capacity() < p.len && b.value.capacity() >= p.len {
1531 mem::swap(&mut a.value, &mut b.value);
1532 }
1533 p.put_in(&mut a.value, order);
1534 a.negative = p.negative;
1535 },
1536 );
1537 }
1538}
1539
1540/// The result `p` as a number in one new vector of exactly its length, in the byte order `order`.
1541///
1542/// # Safety
1543///
1544/// As for [`Product::write`].
1545#[inline(always)]
1546unsafe fn new_number(p: &Product, order: ByteOrder) -> Number {
1547 let mut v = Vec::with_capacity(p.len);
1548 // SAFETY: the new vector has room for the `len` bytes, all of which are written before the
1549 // length is set.
1550 unsafe {
1551 p.write(v.as_mut_ptr(), order);
1552 v.set_len(p.len);
1553 }
1554 Number {
1555 value: v,
1556 negative: p.negative,
1557 byte_order: order,
1558 }
1559}
1560
1561/// Divides the operand `x` by the operand `y`, of signs `negative_x` and `negative_y`, and hands
1562/// the quotient and the remainder to `place`, which writes them where they belong; returns what
1563/// `place` returns. The division is truncated, or Euclid's with `EUCLIDEAN`. When `want` asks for
1564/// one result alone, the other is not computed, and `place` gets zero for it.
1565///
1566/// # Safety
1567///
1568/// The operands must describe vectors that stay valid for reads until `place` is called, and `y`
1569/// must not be zero.
1570#[inline(always)]
1571unsafe fn divide<const EUCLIDEAN: bool, R>(
1572 x: Operand,
1573 y: Operand,
1574 negative_x: bool,
1575 negative_y: bool,
1576 want: Want,
1577 place: impl FnOnce(&Product, &Product) -> R,
1578) -> R {
1579 let ny = y.significant.div_ceil(8);
1580 if ny == 1 && want == Want::Remainder && x.significant >= REM_1_BYTES.min(REM_1_BYTES_WIDE) {
1581 // SAFETY: the divisor has one limb.
1582 let d = unsafe { limb_of(y) };
1583 let from = if d <= REM_1_MAX {
1584 REM_1_BYTES
1585 } else {
1586 REM_1_BYTES_WIDE
1587 };
1588 if d >= 2 && x.significant >= from {
1589 // SAFETY: as the caller guarantees.
1590 let r = unsafe { rem_1(x, &Powers::of(d)) };
1591 return remainder_of_1::<EUCLIDEAN, R>(r, d, negative_x && x.significant != 0, place);
1592 }
1593 }
1594 let nx = x.significant.div_ceil(8).max(ny);
1595 // The divisor, normalized, and a limb to start it on 16 bytes, then what `compute_by` needs.
1596 let need = ny + 1 + working_memory(nx, ny, want);
1597 let compute = |s: *mut MaybeUninit<u64>| {
1598 // SAFETY: the working memory holds `need` limbs; the rest as the caller guarantees.
1599 unsafe { compute::<EUCLIDEAN, R>(s.cast(), x, y, negative_x, negative_y, want, place) }
1600 };
1601 if need <= STACK_LIMBS {
1602 on_stack(compute)
1603 } else {
1604 on_heap(need, compute)
1605 }
1606}
1607
1608/// Hands the remainder `r` by the one-limb divisor `d` of a dividend of sign `negative_x` (not set
1609/// for zero) to `place`, with zero for the quotient: truncated, or Euclid's with `EUCLIDEAN`.
1610#[inline(always)]
1611pub(super) fn remainder_of_1<const EUCLIDEAN: bool, R>(
1612 r: u64,
1613 d: u64,
1614 negative_x: bool,
1615 place: impl FnOnce(&Product, &Product) -> R,
1616) -> R {
1617 let r = if EUCLIDEAN && negative_x && r != 0 {
1618 d - r
1619 } else {
1620 r
1621 };
1622 let remainder = Product {
1623 r: if r == 0 { ptr::null() } else { &r },
1624 len: 8 - (r | 1).leading_zeros() as usize / 8,
1625 negative: negative_x && !EUCLIDEAN && r != 0,
1626 };
1627 place(&ZERO, &remainder)
1628}
1629
1630/// The limbs of working memory that [`compute_by`] needs for a dividend of `nx` limbs, at least as
1631/// many as the divisor's `ny`: the dividend shifted, with a limb above it, the quotient with a limb
1632/// above it for Euclid's, and the scratch of divide and conquer, or of a quotient alone computed
1633/// from the top limbs of the operands.
1634#[inline(always)]
1635pub(super) fn working_memory(nx: usize, ny: usize, want: Want) -> usize {
1636 let qn = nx - ny + 1;
1637 let mut need = (nx + 1) + (qn + 1);
1638 if want == Want::Quotient && ny >= 3 && from_top(nx + 1, ny) {
1639 // The top limbs of both operands, a limb to align the divisor's, their quotient and the
1640 // scratch of their division; or the product that checks it.
1641 let k = qn;
1642 let top = (2 * k + 2) + 1 + 2 * (k + 1) + top_itch(k);
1643 need += top.max(check_itch(nx + 1, ny));
1644 } else if ny >= DC_DIV {
1645 // The exact division by divide and conquer, of the dividend with the limb above it or
1646 // without (see `compute_by`), and for a quotient alone of its top limbs, or with the low
1647 // ones from the top ones; below `DC_DIV` limbs, none.
1648 let itch = |nn: usize| {
1649 let mut itch = qr_itch(nn, ny);
1650 if want == Want::Quotient && ny >= 3 {
1651 if mu(nn, ny) {
1652 // Newton's method allocates its own.
1653 } else if ny < DC_DIV_Q {
1654 itch = itch.max(q_itch(nn, ny));
1655 } else if let l @ 1.. = split_low(nn, ny) {
1656 itch = itch.max(split_itch(nn, ny, l));
1657 }
1658 }
1659 itch
1660 };
1661 need += itch(nx + 1).max(itch(nx));
1662 }
1663 need
1664}
1665
1666/// A divisor of the general path as the division reads it: its `n` limbs at `d`, the least
1667/// significant first, shifted left by `shift` bits so that the top bit is set, starting on 16
1668/// bytes, and their reciprocal `v`, of the top limb for one limb and of the top two otherwise;
1669/// and what a [`Divisor`](super::Divisor) keeps for Newton's method, when it has it, at `pre`
1670/// (null otherwise).
1671#[derive(Clone, Copy)]
1672pub(super) struct Normal {
1673 pub(super) d: *const u64,
1674 pub(super) n: usize,
1675 pub(super) shift: u32,
1676 pub(super) v: u64,
1677 pub(super) pre: *const Prepared,
1678}
1679
1680/// The shift that sets the top bit of the operand `y`, not zero, from its most significant byte,
1681/// which is its top limb's `y.significant - 8 (n - 1)`-th.
1682///
1683/// # Safety
1684///
1685/// The operand's vector must be valid for reads.
1686#[inline(always)]
1687unsafe fn normalizing_shift(y: Operand) -> u32 {
1688 // SAFETY: the most significant byte lies inside the vector.
1689 let top = unsafe {
1690 if y.big_endian {
1691 *y.ptr.add(y.len - y.significant)
1692 } else {
1693 *y.ptr.add(y.significant - 1)
1694 }
1695 };
1696 8 * (8 * y.significant.div_ceil(8) - y.significant) as u32 + top.leading_zeros()
1697}
1698
1699/// Reads the divisor `y`, not zero, normalized into its limbs at `d`, which start on 16 bytes, and
1700/// computes their reciprocal.
1701///
1702/// # Safety
1703///
1704/// The operand's vector must be valid for reads and `d` for writing its limbs.
1705#[inline(always)]
1706pub(super) unsafe fn normalize(y: Operand, d: *mut u64) -> Normal {
1707 let n = y.significant.div_ceil(8);
1708 // SAFETY: as the caller guarantees.
1709 unsafe {
1710 let shift = normalizing_shift(y);
1711 to_limbs_shifted(y, d, shift);
1712 let v = if n == 1 {
1713 invert_limb(*d)
1714 } else {
1715 invert_3by2(*d.add(n - 1), *d.add(n - 2))
1716 };
1717 Normal {
1718 d,
1719 n,
1720 shift,
1721 v,
1722 pre: ptr::null(),
1723 }
1724 }
1725}
1726
1727/// [`divide`] in the working memory at `s`: the divisor is read into its first limbs, normalized,
1728/// and the dividend divided by it with [`compute_by`] in the rest, but for a quotient alone much
1729/// shorter than the divisor, which needs only the divisor's top limbs.
1730///
1731/// # Safety
1732///
1733/// As for [`divide`], with `s` valid for the limbs that `divide` counts.
1734#[inline(always)]
1735unsafe fn compute<const EUCLIDEAN: bool, R>(
1736 s: *mut u64,
1737 x: Operand,
1738 y: Operand,
1739 negative_x: bool,
1740 negative_y: bool,
1741 want: Want,
1742 place: impl FnOnce(&Product, &Product) -> R,
1743) -> R {
1744 let ny = y.significant.div_ceil(8);
1745 let nx = x.significant.div_ceil(8).max(ny);
1746 // SAFETY: the working memory holds the divisor's `ny` limbs from an address on 16 bytes, and
1747 // after them the limbs of `compute_by`.
1748 unsafe {
1749 // The divisor starts on 16 bytes, which the kernel reads in pairs of limbs for every limb
1750 // of the quotient: at 8 bytes off, a division of 72 limbs by 36 took 4100 cycles instead of
1751 // 2760 on an Apple M4 Max, whenever the stack put it there.
1752 let d = s.add((s.addr() / 8) & 1);
1753 let w = s.add(ny + 1);
1754 if want == Want::Quotient && ny >= 3 && from_top(nx + 1, ny) {
1755 let k = nx + 1 - ny;
1756 let (u, q) = (w, w.add(nx + 1));
1757 let t = q.add(k + 1);
1758 let shift = normalizing_shift(y);
1759 quotient_from_top(x, Top::Operand(y, d), ny, shift, u, q, t);
1760 let quotient = result(q, k, (negative_x && x.significant != 0) != negative_y);
1761 return place("ient, &ZERO);
1762 }
1763 let normal = normalize(y, d);
1764 compute_by::<EUCLIDEAN, R>(w, x, normal, negative_x, negative_y, want, place)
1765 }
1766}
1767
1768/// Divides the operand `x`, of sign `negative_x`, by the normalized divisor `y`, of sign
1769/// `negative_y`, in the working memory at `s`, and hands the results to `place`, as [`divide`]
1770/// does.
1771///
1772/// # Safety
1773///
1774/// As for [`divide`], with `s` valid for the [`working_memory`] limbs of `x` and `y`.
1775#[inline(always)]
1776pub(super) unsafe fn compute_by<const EUCLIDEAN: bool, R>(
1777 s: *mut u64,
1778 x: Operand,
1779 y: Normal,
1780 negative_x: bool,
1781 negative_y: bool,
1782 want: Want,
1783 place: impl FnOnce(&Product, &Product) -> R,
1784) -> R {
1785 let (d, ny, shift) = (y.d, y.n, y.shift);
1786 let lx = x.significant.div_ceil(8);
1787 let nx = lx.max(ny);
1788 let qn = nx - ny + 1;
1789 let negative_x = negative_x && x.significant != 0;
1790 // SAFETY: the working memory holds the `nx + 1` limbs of the dividend, the `qn + 1` of the
1791 // quotient and the scratch, which every step stays inside.
1792 unsafe {
1793 let u = s;
1794 let q = u.add(nx + 1);
1795 let t = q.add(qn + 1);
1796 if want == Want::Quotient && ny >= 3 && from_top(nx + 1, ny) {
1797 quotient_from_top(x, Top::Normal(d), ny, shift, u, q, t);
1798 let quotient = result(q, qn, negative_x != negative_y);
1799 return place("ient, &ZERO);
1800 }
1801 read_dividend(x, u, nx, shift);
1802 *q.add(qn) = 0;
1803 match ny {
1804 1 => {
1805 *u = if want == Want::Remainder {
1806 div_qr_1::<false>(q, u, nx, *u.add(nx), *d, y.v)
1807 } else {
1808 div_qr_1::<true>(q, u, nx, *u.add(nx), *d, y.v)
1809 };
1810 }
1811 2 => {
1812 let (r1, r0) = div_qr_2(q, u, nx + 1, *d.add(1), *d, y.v);
1813 (*u, *u.add(1)) = (r0, r1);
1814 }
1815 _ => {
1816 // The limb above the dividend takes part only when the shift put bits in it; the
1817 // quotient's top limb then comes out of the steps, and otherwise from the
1818 // comparison that precedes them.
1819 let nn = if *u.add(nx) != 0 { nx + 1 } else { nx };
1820 let qh = if !y.pre.is_null() && mu_prepared(nn, ny) {
1821 // A divisor's inverse and transforms, kept for its divisions.
1822 mu_div_prepared(q, u, nn, d, ny, y.v, &*y.pre, want != Want::Quotient)
1823 } else if want != Want::Quotient {
1824 div_qr(q, u, nn, d, ny, y.v, t)
1825 } else if mu(nn, ny) {
1826 // The quotient alone by Newton's method, whose last block skips its remainder.
1827 mu_div_q(q, u, nn, d, ny)
1828 } else if ny < DC_DIV_Q {
1829 // The quotient alone: its last limbs from a shrinking divisor, the others
1830 // exactly.
1831 match div_q(q, u, nn, d, ny, y.v, t) {
1832 Some(qh) => qh,
1833 None => exactly_after_all(q, u, nn, x, y, t),
1834 }
1835 } else if split_low(nn, ny) > 0 {
1836 // The quotient alone of a long division: its low limbs from the top ones.
1837 div_q_split(q, u, nn, d, ny, y.v, t)
1838 } else {
1839 div_qr(q, u, nn, d, ny, y.v, t)
1840 };
1841 if nn == nx {
1842 *q.add(nx - ny) = u64::from(qh);
1843 }
1844 }
1845 }
1846 if want == Want::Quotient {
1847 let quotient = result(q, qn + 1, negative_x != negative_y);
1848 return place("ient, &ZERO);
1849 }
1850 let remainder = (0..ny).any(|i| *u.add(i) != 0);
1851 if EUCLIDEAN && negative_x && remainder {
1852 // Euclid's quotient is one further from zero, and its remainder `|y| - r`: shifted, as
1853 // the divisor and the remainder still are.
1854 sub_n(u, d, u, ny);
1855 if want != Want::Remainder {
1856 add_1(q, qn + 1, 1);
1857 }
1858 }
1859 if shift != 0 {
1860 rshift(u, ny, shift);
1861 }
1862 // Without the quotient, the limbs of a quotient of a divisor of one limb are not written.
1863 let quotient = if want == Want::Remainder {
1864 ZERO
1865 } else {
1866 result(q, qn + 1, negative_x != negative_y)
1867 };
1868 let remainder = result(u, ny, negative_x && !EUCLIDEAN);
1869 place("ient, &remainder)
1870 }
1871}
1872
1873/// Reads the dividend `x` into the `nx + 1` limbs at `u`, shifted left by `shift` bits, `nx` at
1874/// least its limbs: a dividend shorter than the divisor gets zero limbs up to the divisor's length,
1875/// and its quotient is then zero, its remainder the dividend.
1876///
1877/// # Safety
1878///
1879/// The operand's vector must be valid for reads, and `u` for writing `nx + 1` limbs.
1880#[inline(always)]
1881unsafe fn read_dividend(x: Operand, u: *mut u64, nx: usize, shift: u32) {
1882 let lx = x.significant.div_ceil(8);
1883 // SAFETY: as the caller guarantees.
1884 unsafe {
1885 *u.add(lx) = to_limbs_shifted(x, u, shift);
1886 if lx < nx {
1887 ptr::write_bytes(u.add(lx + 1), 0, nx - lx);
1888 }
1889 }
1890}
1891
1892/// The quotient of [`div_qr`] after all, when [`div_q`] gave up on the dividend `x` of `nn`
1893/// limbs by the divisor `y`: the dividend is read again into the limbs at `u`. Returns the
1894/// quotient's limb above the `nn - y.n` at `q`.
1895///
1896/// # Safety
1897///
1898/// As for `div_qr`, with the operand's vector valid for reads.
1899#[cold]
1900#[inline(never)]
1901unsafe fn exactly_after_all(
1902 q: *mut u64,
1903 u: *mut u64,
1904 nn: usize,
1905 x: Operand,
1906 y: Normal,
1907 t: *mut u64,
1908) -> bool {
1909 // SAFETY: as the caller guarantees: the limbs are those `compute_by` read, of which the
1910 // division takes `nn`.
1911 unsafe {
1912 read_dividend(x, u, x.significant.div_ceil(8).max(y.n), y.shift);
1913 div_qr(q, u, nn, y.d, y.n, y.v, t)
1914 }
1915}
1916
1917/// Where [`quotient_from_top`] gets the divisor from: an operand, of which it reads only the top
1918/// limbs, and the whole, into the limbs at the pointer, for the rare check; or normalized limbs.
1919#[derive(Clone, Copy)]
1920enum Top {
1921 Operand(Operand, *mut u64),
1922 Normal(*const u64),
1923}
1924
1925/// The quotient alone of a division whose quotient is much shorter than the divisor
1926/// ([`from_top`]), in the `k` limbs at `q`: from the top `2k + 2` limbs of the dividend and the top
1927/// `k + 1` of the divisor of `ny` limbs, shifted by `shift`, by [`div_q_top`]. The whole dividend
1928/// is read, into the limbs at `u`, only for the rare check. Out of line, so that the shorter
1929/// divisions keep their registers.
1930///
1931/// # Safety
1932///
1933/// As for [`compute_by`], with `u` valid for the dividend's `nx + 1` limbs, `q` for the quotient's
1934/// `k`, and `t` for the scratch of `div_q_top` and of `check_q_top`, as [`working_memory`] counts
1935/// them, and the divisor's limbs as `y` describes them.
1936#[inline(never)]
1937unsafe fn quotient_from_top(
1938 x: Operand,
1939 y: Top,
1940 ny: usize,
1941 shift: u32,
1942 u: *mut u64,
1943 q: *mut u64,
1944 t: *mut u64,
1945) {
1946 let lx = x.significant.div_ceil(8);
1947 let nx = lx.max(ny);
1948 let k = nx + 1 - ny;
1949 // SAFETY: the copies of the top limbs, their quotient and the scratch of their division lie in
1950 // the scratch at `t`, as `working_memory` counts it, and so does the check's.
1951 unsafe {
1952 let w = t;
1953 let dt = w.add(2 * k + 2);
1954 let dt = dt.add((dt.addr() / 8) & 1);
1955 let h = dt.add(k + 1);
1956 let top: *const u64 = match y {
1957 Top::Operand(y, _) => {
1958 shifted_limbs(y, ny - (k + 1), ny, shift, dt);
1959 dt
1960 }
1961 Top::Normal(d) => d.add(ny - (k + 1)),
1962 };
1963 shifted_limbs(x, nx + 1 - (2 * k + 2), nx + 1, shift, w);
1964 let v = invert_3by2(*top.add(k), *top.add(k - 1));
1965 let found = div_q_top(h, w, k, top, v, h.add(k + 1));
1966 debug_assert!(
1967 found != Found::AllOnes,
1968 "the dividend's top limb is below the divisor's"
1969 );
1970 ptr::copy_nonoverlapping(h.add(1), q, k);
1971 if found == Found::Check {
1972 read_dividend(x, u, nx, shift);
1973 let d = match y {
1974 Top::Operand(y, d) => {
1975 to_limbs_shifted(y, d, shift);
1976 d.cast_const()
1977 }
1978 Top::Normal(d) => d,
1979 };
1980 check_q_top(q, u, nx + 1, d, ny, t);
1981 }
1982 }
1983}
1984
1985/// What a division on the general path computes: both results, or the quotient or the remainder
1986/// alone, which spares the steps that only the other needs.
1987#[derive(Clone, Copy, PartialEq)]
1988pub(super) enum Want {
1989 Both,
1990 Quotient,
1991 Remainder,
1992}
1993
1994impl Want {
1995 /// What `/` and `/=` (`%` and `%=` with `REM`) need, or, with `EUCLIDEAN`, `div_euclid` and
1996 /// `rem_euclid`: a Euclidean result is adjusted with both.
1997 #[inline(always)]
1998 pub(super) const fn of(euclidean: bool, rem: bool) -> Want {
1999 match (euclidean, rem) {
2000 (false, false) => Want::Quotient,
2001 (_, true) => Want::Remainder,
2002 (true, false) => Want::Both,
2003 }
2004 }
2005}
2006
2007/// The zero that [`compute`] hands to `place` as the result it does not compute.
2008const ZERO: Product = Product {
2009 r: ptr::null(),
2010 len: 1,
2011 negative: false,
2012};
2013
2014/// Limb `i` of the magnitude of the operand `x`: its `x.significant.div_ceil(8)` limbs read as
2015/// [`to_limbs_shifted`] reads them, and zero above them.
2016///
2017/// # Safety
2018///
2019/// The operand's vector must be valid for reads.
2020#[inline(always)]
2021unsafe fn limb(x: Operand, i: usize) -> u64 {
2022 let l = x.significant;
2023 let (full, rem) = (l / 8, l % 8);
2024 // SAFETY: every read lies inside the significant bytes, as in `to_limbs_shifted`.
2025 unsafe {
2026 let end = x.ptr.add(x.len);
2027 if i < full {
2028 if x.big_endian {
2029 u64::from_be_bytes(read(end.sub(8 * i + 8)))
2030 } else {
2031 u64::from_le_bytes(read(x.ptr.add(8 * i)))
2032 }
2033 } else if i == full && rem > 0 {
2034 if l >= 8 {
2035 let v = if x.big_endian {
2036 u64::from_be_bytes(read(end.sub(l)))
2037 } else {
2038 u64::from_le_bytes(read(x.ptr.add(l - 8)))
2039 };
2040 v >> (8 * (8 - rem))
2041 } else if x.big_endian {
2042 read_small(
2043 core::slice::from_raw_parts(end.sub(l), rem),
2044 ByteOrder::BigEndian,
2045 ) as u64
2046 } else {
2047 read_small(
2048 core::slice::from_raw_parts(x.ptr, rem),
2049 ByteOrder::LittleEndian,
2050 ) as u64
2051 }
2052 } else {
2053 0
2054 }
2055 }
2056}
2057
2058/// Writes limbs `from..to` of the magnitude of the operand `x` shifted left by `s` bits, `s < 64`,
2059/// at `out`: each from the limb at its place and the one below it. The whole limbs go through a
2060/// loop of their own, for either byte order, and the partial limb above them and the zero limbs
2061/// through [`limb`].
2062///
2063/// # Safety
2064///
2065/// The operand's vector must be valid for reads, and `out` for writing `to - from` limbs.
2066#[inline(always)]
2067unsafe fn shifted_limbs(x: Operand, from: usize, to: usize, s: u32, out: *mut u64) {
2068 let above = |v: u64| (v >> 1) >> (63 - s);
2069 let full = (x.significant / 8).clamp(from, to);
2070 // SAFETY: as the caller guarantees; the limbs below `full` are whole limbs of the operand.
2071 unsafe {
2072 let mut below = if from > 0 { limb(x, from - 1) } else { 0 };
2073 let end = x.ptr.add(x.len);
2074 if x.big_endian {
2075 for i in from..full {
2076 let v = u64::from_be_bytes(read(end.sub(8 * i + 8)));
2077 *out.add(i - from) = (v << s) | above(below);
2078 below = v;
2079 }
2080 } else {
2081 for i in from..full {
2082 let v = u64::from_le_bytes(read(x.ptr.add(8 * i)));
2083 *out.add(i - from) = (v << s) | above(below);
2084 below = v;
2085 }
2086 }
2087 for i in full..to {
2088 let v = limb(x, i);
2089 *out.add(i - from) = (v << s) | above(below);
2090 below = v;
2091 }
2092 }
2093}
2094
2095/// Reads the significant bytes of the operand `x` into `x.significant.div_ceil(8)` limbs at `out`,
2096/// the least significant first, as the multiplication's `to_limbs` does, shifted left by `s` bits
2097/// on the way, `s < 64`; returns the bits shifted out of the top limb.
2098///
2099/// # Safety
2100///
2101/// The operand's vector must be valid for reads, and `out` for writing its limbs.
2102#[inline(always)]
2103unsafe fn to_limbs_shifted(x: Operand, out: *mut u64, s: u32) -> u64 {
2104 let l = x.significant;
2105 let (full, rem) = (l / 8, l % 8);
2106 // The bits of `v` above `64 - s`, `v >> (64 - s)`, and none for `s = 0`, with shifts below 64.
2107 let above = |v: u64| (v >> 1) >> (63 - s);
2108 let mut below = 0;
2109 // SAFETY: every read lies inside the significant bytes: big-endian the last `l` of the
2110 // vector, little-endian the first `l`.
2111 unsafe {
2112 let end = x.ptr.add(x.len);
2113 for i in 0..full {
2114 let v = if x.big_endian {
2115 u64::from_be_bytes(read(end.sub(8 * i + 8)))
2116 } else {
2117 u64::from_le_bytes(read(x.ptr.add(8 * i)))
2118 };
2119 *out.add(i) = (v << s) | above(below);
2120 below = v;
2121 }
2122 if rem > 0 {
2123 // The `rem` bytes above the whole limbs: from 8 bytes up, the eight that end at the
2124 // top, shifted down to them; below, as the addition reads a short magnitude.
2125 let v = if l >= 8 {
2126 let v = if x.big_endian {
2127 u64::from_be_bytes(read(end.sub(l)))
2128 } else {
2129 u64::from_le_bytes(read(x.ptr.add(l - 8)))
2130 };
2131 v >> (8 * (8 - rem))
2132 } else if x.big_endian {
2133 read_small(
2134 core::slice::from_raw_parts(end.sub(l), rem),
2135 ByteOrder::BigEndian,
2136 ) as u64
2137 } else {
2138 read_small(
2139 core::slice::from_raw_parts(x.ptr, rem),
2140 ByteOrder::LittleEndian,
2141 ) as u64
2142 };
2143 *out.add(full) = (v << s) | above(below);
2144 below = v;
2145 }
2146 }
2147 above(below)
2148}
2149
2150/// The `n` limbs at `r` as a result to write: their length in the shortest form, and the sign
2151/// `negative`, which zero does not keep.
2152///
2153/// # Safety
2154///
2155/// The limbs must be valid for reads.
2156#[inline(always)]
2157unsafe fn result(r: *const u64, n: usize, negative: bool) -> Product {
2158 // SAFETY: as the caller guarantees.
2159 unsafe {
2160 let mut top = n;
2161 while top > 0 && *r.add(top - 1) == 0 {
2162 top -= 1;
2163 }
2164 if top == 0 {
2165 return Product {
2166 r: ptr::null(),
2167 len: 1,
2168 negative: false,
2169 };
2170 }
2171 let len = 8 * top - (*r.add(top - 1)).leading_zeros() as usize / 8;
2172 Product { r, len, negative }
2173 }
2174}