a/math/numbers/divisor.rs
1//! A divisor prepared for dividing many numbers by it: [`Divisor`].
2//!
3//! Before it divides, a division reads its divisor into limbs, shifts them so that the top bit is
4//! set, and computes the reciprocal of the top limbs, by which each limb of the quotient is
5//! estimated. A [`Divisor`] does that once, and keeps the results: dividing by it skips those
6//! steps, and the scan of the divisor's bytes for its length. That is most of the cost of
7//! dividing a short number, and little of dividing a long one by a long divisor. For the longest
8//! divisions, which take Newton's method, it also keeps, from the first one, the inverse of its
9//! limbs and the transforms of the products (see the division's `newton`), which make the later
10//! ones about twice as fast.
11
12use super::add::{SMALL, read_small};
13use super::div::{
14 EUCLID, Medium, Normal, Powers, Prepared, REM_1_PREPARED, Short, TRUNCATED, WIDER, Want,
15 by_medium, by_zero, compute_by, mu_prepared, normalize, prepare, rem_1, remainder_of_1,
16 wide_division, wide_number, wider_division, working_memory,
17};
18use super::mul::{Operand, Product, STACK_LIMBS, WIDE, Wide, on_heap, on_stack, put_wide};
19use super::sub::Negated;
20use super::{ByteOrder, Number};
21use core::mem::MaybeUninit;
22use core::ops::{Div, DivAssign, Rem, RemAssign};
23use core::ptr;
24use std::sync::OnceLock;
25
26/// A number prepared to divide others by: dividing by it gives what dividing by the number does,
27/// with the same operators, but skips reading the divisor and computing its reciprocal each time.
28///
29/// It keeps the magnitude of the number in limbs of eight bytes, shifted so that the top bit is
30/// set, the reciprocal of the top limbs and the sign; and from its first division by Newton's
31/// method, from 256 limbs (2 KiB) in the divisor and in the quotient, the inverse of all its limbs
32/// and the transforms of the inverse and of the divisor, 10 to 11 times the divisor's bytes in all,
33/// which that first division takes about a third longer to compute than a division by the number,
34/// and which take the later ones to about half its time. A number divided by it with `/`, `/=`, `%`
35/// or `%=`, owned or borrowed, or by its methods [`div_rem`](Self::div_rem),
36/// [`div_euclid`](Self::div_euclid) and [`rem_euclid`](Self::rem_euclid), gives the results that
37/// dividing by the number gives, in the byte order of the dividend, in the shortest form, built in
38/// the dividend's vector when the dividend is owned (which always has room, but for zero in an
39/// empty vector) and otherwise in one new vector of exactly their length.
40///
41/// # Examples
42///
43/// ```
44/// use a::math::numbers::{ByteOrder, Divisor, Number};
45///
46/// // Dividing many numbers by 10^19.
47/// let d = Divisor::new(&Number::new_from_u64(10_000_000_000_000_000_000, ByteOrder::BigEndian));
48/// let a = Number::new_from_u128(123 * 10_000_000_000_000_000_000 + 45, ByteOrder::LittleEndian);
49/// assert_eq!((&a / &d).value, [123]);
50/// assert_eq!((&a % &d).value, [45]);
51///
52/// let (q, r) = d.div_rem(&Number::new_from_i32(-7, ByteOrder::BigEndian));
53/// assert!(q.value == [0] && r.value == [7] && r.is_negative());
54/// ```
55#[derive(Clone)]
56pub struct Divisor {
57 /// The limbs of the magnitude, shifted, the least significant first, in pairs, so that they
58 /// start on 16 bytes, where the kernel of the division reads them best.
59 limbs: Vec<Pair>,
60 /// The number of limbs.
61 n: usize,
62 /// The shift that sets the top bit of the top limb.
63 shift: u32,
64 /// The reciprocal of the top limb for one limb, and of the top two otherwise.
65 v: u64,
66 /// Whether the divisor is negative.
67 negative: bool,
68 /// The magnitude and its preparation for the divisions in registers, when it fits in 16
69 /// bytes.
70 short: Option<Short>,
71 /// The limbs as the division in registers by three or four of them takes them, when the
72 /// magnitude has 17 to 32 bytes.
73 medium: Option<Medium>,
74 /// The powers of `B` modulo the magnitude for the remainders of long dividends, when it is
75 /// one limb, 2 or more.
76 powers: Option<Powers>,
77 /// The inverse of the limbs and the transforms of Newton's method, made by the first division
78 /// that takes it.
79 prepared: OnceLock<Prepared>,
80}
81
82/// Two limbs on 16 bytes: the elements of [`Divisor::limbs`].
83#[derive(Clone, Copy)]
84#[repr(align(16))]
85struct Pair(#[expect(dead_code, reason = "read through pointers to its limbs")] [u64; 2]);
86
87impl Divisor {
88 /// Prepares `d` for dividing by it: reads its magnitude into limbs, shifted, and computes the
89 /// reciprocal of the top ones. `d` may have any sign and byte order, and need not be in the
90 /// shortest form.
91 ///
92 /// Takes O(n) time for `n` bytes, and allocates one vector of their limbs.
93 ///
94 /// # Panics
95 ///
96 /// When `d` is zero, as dividing by it would.
97 ///
98 /// # Examples
99 ///
100 /// ```
101 /// use a::math::numbers::{ByteOrder, Divisor, Number};
102 ///
103 /// let d = Divisor::new(&Number::new_from_i32(-3, ByteOrder::BigEndian));
104 /// assert!(d.is_negative());
105 /// let q = &Number::new_from_i32(100, ByteOrder::LittleEndian) / &d;
106 /// assert_eq!(q.value, [33]);
107 /// assert!(q.is_negative());
108 /// ```
109 #[track_caller]
110 pub fn new(d: &Number) -> Divisor {
111 let y = Operand::of(d);
112 if y.significant == 0 {
113 by_zero::<false>();
114 }
115 let n = y.significant.div_ceil(8);
116 let mut limbs = vec![Pair([0; 2]); n.div_ceil(2)];
117 // SAFETY: the pairs hold at least the `n` limbs, from an address on 16 bytes; `d` is
118 // borrowed while it is read.
119 let normal = unsafe { normalize(y, limbs.as_mut_ptr().cast()) };
120 let short = (y.significant <= SMALL).then(|| {
121 // SAFETY: the significant bytes of the magnitude are at most 16.
122 let magnitude = unsafe {
123 let start = if y.big_endian {
124 y.len - y.significant
125 } else {
126 0
127 };
128 read_small(&d.value[start..start + y.significant], d.byte_order)
129 };
130 Short::of(magnitude, d.negative)
131 });
132 let medium = (y.significant > SMALL && y.significant <= WIDE).then(|| {
133 // SAFETY: the pairs hold the three or four limbs.
134 unsafe { Medium::normalized(normal.d, n, normal.shift, normal.v, d.negative) }
135 });
136 let powers = short
137 .map(|s| s.y)
138 .filter(|&y| (2..=u128::from(u64::MAX)).contains(&y))
139 .map(|y| Powers::of(y as u64));
140 Divisor {
141 limbs,
142 n,
143 shift: normal.shift,
144 v: normal.v,
145 negative: d.negative,
146 short,
147 medium,
148 powers,
149 prepared: OnceLock::new(),
150 }
151 }
152
153 /// Returns whether the divisor is below zero.
154 pub fn is_negative(&self) -> bool {
155 self.negative
156 }
157
158 /// Returns the quotient and the remainder of `a` divided by this divisor, `(a / d, a % d)`,
159 /// computed together, as [`Number::div_rem`] gives them: the quotient truncated toward zero,
160 /// the remainder with the sign of `a`, both in the byte order of `a` and in the shortest form,
161 /// each in one new vector of exactly its length.
162 ///
163 /// # Examples
164 ///
165 /// ```
166 /// use a::math::numbers::{ByteOrder, Divisor, Number};
167 ///
168 /// let d = Divisor::new(&Number::new_from_u16(1000, ByteOrder::BigEndian));
169 /// let (q, r) = d.div_rem(&Number::new_from_u32(1_234_567, ByteOrder::BigEndian));
170 /// assert_eq!(q.value, [0x04, 0xD2]);
171 /// assert_eq!(r.value, [0x02, 0x37]);
172 /// ```
173 pub fn div_rem(&self, a: &Number) -> (Number, Number) {
174 let order = a.byte_order;
175 if let Some((q, r)) = self.in_registers::<TRUNCATED>(a) {
176 return (wide_number(order, &q), wide_number(order, &r));
177 }
178 // SAFETY: `a` is borrowed until the results are computed.
179 unsafe {
180 self.divide::<TRUNCATED, _>(Operand::of(a), a.negative, Want::Both, |q, r| {
181 (new_number(q, order), new_number(r, order))
182 })
183 }
184 }
185
186 /// Returns the quotient of Euclid's division of `a` by this divisor, as
187 /// [`Number::div_euclid`] gives it, in one new vector.
188 ///
189 /// # Examples
190 ///
191 /// ```
192 /// use a::math::numbers::{ByteOrder, Divisor, Number};
193 ///
194 /// let d = Divisor::new(&Number::new_from_i32(2, ByteOrder::BigEndian));
195 /// let q = d.div_euclid(&Number::new_from_i32(-7, ByteOrder::BigEndian));
196 /// assert_eq!(q.value, [4]);
197 /// assert!(q.is_negative());
198 /// ```
199 pub fn div_euclid(&self, a: &Number) -> Number {
200 self.one_new::<EUCLID, false>(a)
201 }
202
203 /// Returns the remainder of Euclid's division of `a` by this divisor, `a` modulo `|d|`, as
204 /// [`Number::rem_euclid`] gives it, never negative, in one new vector.
205 ///
206 /// # Examples
207 ///
208 /// ```
209 /// use a::math::numbers::{ByteOrder, Divisor, Number};
210 ///
211 /// let d = Divisor::new(&Number::new_from_i32(-2, ByteOrder::BigEndian));
212 /// let r = d.rem_euclid(&Number::new_from_i32(-7, ByteOrder::BigEndian));
213 /// assert_eq!(r.value, [1]);
214 /// assert!(!r.is_negative());
215 /// ```
216 pub fn rem_euclid(&self, a: &Number) -> Number {
217 self.one_new::<EUCLID, true>(a)
218 }
219
220 /// Returns the quotient of `a` divided by this divisor rounded toward negative infinity, as
221 /// [`Number::div_floor`] gives it, in the byte order of `a` and in the shortest form.
222 ///
223 /// # Examples
224 ///
225 /// ```
226 /// use a::math::numbers::{Divisor, Number};
227 ///
228 /// let d = Divisor::new(&Number::from(-2));
229 /// assert_eq!(d.div_floor(&Number::from(7)), -4);
230 /// assert_eq!(d.div_floor(&Number::from(-7)), 3);
231 /// ```
232 pub fn div_floor(&self, a: &Number) -> Number {
233 if self.negative {
234 -self.one_new::<EUCLID, false>(&Negated::new(a))
235 } else {
236 self.one_new::<EUCLID, false>(a)
237 }
238 }
239
240 /// Returns the remainder of `a` divided by this divisor rounded toward negative infinity, as
241 /// [`Number::rem_floor`] gives it: it has the sign of the divisor, unless it is zero.
242 ///
243 /// # Examples
244 ///
245 /// ```
246 /// use a::math::numbers::{Divisor, Number};
247 ///
248 /// let d = Divisor::new(&Number::from(-2));
249 /// assert_eq!(d.rem_floor(&Number::from(7)), -1);
250 /// assert_eq!(d.rem_floor(&Number::from(-7)), -1);
251 /// ```
252 pub fn rem_floor(&self, a: &Number) -> Number {
253 if self.negative {
254 -self.one_new::<EUCLID, true>(&Negated::new(a))
255 } else {
256 self.one_new::<EUCLID, true>(a)
257 }
258 }
259
260 /// The divisor as the general path of the division reads it.
261 #[inline(always)]
262 fn normal(&self) -> Normal {
263 Normal {
264 d: self.limbs.as_ptr().cast(),
265 n: self.n,
266 shift: self.shift,
267 v: self.v,
268 pre: ptr::null(),
269 }
270 }
271
272 /// The quotient and the remainder of `a`, truncated, or Euclid's with `EUCLIDEAN`, computed
273 /// in registers when the divisor fits in 32 bytes and `a`'s vector in 64.
274 #[inline(always)]
275 fn in_registers<const EUCLIDEAN: bool>(&self, a: &Number) -> Option<(Wide, Wide)> {
276 let len = a.value.len();
277 // SAFETY: the dividend's vector holds at most the bytes each path reads.
278 unsafe {
279 if let Some(y) = self.short {
280 if len <= SMALL {
281 Some(wide_division::<EUCLIDEAN, 2>(a, y))
282 } else if len <= WIDE {
283 Some(wide_division::<EUCLIDEAN, 4>(a, y))
284 } else if len <= WIDER {
285 Some(wider_division::<EUCLIDEAN>(a, y))
286 } else {
287 None
288 }
289 } else if let Some(y) = self.medium
290 && len <= WIDER
291 {
292 Some(by_medium::<EUCLIDEAN>(a, y))
293 } else {
294 None
295 }
296 }
297 }
298
299 /// `a / d` (`a % d` when `REM`; Euclid's with `EUCLIDEAN`) in one new vector.
300 #[inline(never)]
301 fn one_new<const EUCLIDEAN: bool, const REM: bool>(&self, a: &Number) -> Number {
302 let order = a.byte_order;
303 if let Some((q, r)) = self.in_registers::<EUCLIDEAN>(a) {
304 return wide_number(order, if REM { &r } else { &q });
305 }
306 // SAFETY: `a` is borrowed until the result is computed.
307 unsafe {
308 self.divide::<EUCLIDEAN, _>(
309 Operand::of(a),
310 a.negative,
311 Want::of(EUCLIDEAN, REM),
312 |q, r| new_number(if REM { r } else { q }, order),
313 )
314 }
315 }
316
317 /// `a /= d` (`a %= d` when `REM`), in the vector of `a` when it has room.
318 #[inline(never)]
319 fn assign<const REM: bool>(&self, a: &mut Number) {
320 let order = a.byte_order;
321 if let Some((q, r)) = self.in_registers::<TRUNCATED>(a) {
322 let w = if REM { &r } else { &q };
323 put_wide(&mut a.value, order, w);
324 a.negative = w.negative;
325 return;
326 }
327 let (x, negative_x) = (Operand::of(a), a.negative);
328 // SAFETY: `a`'s vector is written only once it is read into limbs.
329 unsafe {
330 self.divide::<TRUNCATED, _>(x, negative_x, Want::of(TRUNCATED, REM), |q, r| {
331 let p = if REM { r } else { q };
332 p.put_in(&mut a.value, order);
333 a.negative = p.negative;
334 });
335 }
336 }
337
338 /// Divides the operand `x`, of sign `negative_x`, by this divisor on the general path and
339 /// hands the results to `place`, as the division's `divide` does with a divisor it reads.
340 ///
341 /// # Safety
342 ///
343 /// `x` must describe a vector that stays valid for reads until `place` is called.
344 #[inline(always)]
345 unsafe fn divide<const EUCLIDEAN: bool, R>(
346 &self,
347 x: Operand,
348 negative_x: bool,
349 want: Want,
350 place: impl FnOnce(&Product, &Product) -> R,
351 ) -> R {
352 if want == Want::Remainder
353 && x.significant >= REM_1_PREPARED
354 && let Some(p) = &self.powers
355 {
356 // SAFETY: as the caller guarantees.
357 let r = unsafe { rem_1(x, p) };
358 return remainder_of_1::<EUCLIDEAN, R>(r, p.d, negative_x && x.significant != 0, place);
359 }
360 let nx = x.significant.div_ceil(8).max(self.n);
361 let need = working_memory(nx, self.n, want);
362 let (mut y, negative_y) = (self.normal(), self.negative);
363 if self.n >= 3 && mu_prepared(nx + 1, self.n) {
364 // SAFETY: `n >= 3`, and the limbs at `y.d` are the divisor's, normalized, valid for
365 // reads while `self` lives, which keeps what is prepared from them.
366 y.pre = self.prepared.get_or_init(|| unsafe { prepare(y.d, y.n) });
367 }
368 let compute = |s: *mut MaybeUninit<u64>| {
369 // SAFETY: the working memory holds `need` limbs; the rest as the caller guarantees.
370 unsafe {
371 compute_by::<EUCLIDEAN, R>(s.cast(), x, y, negative_x, negative_y, want, place)
372 }
373 };
374 if need <= STACK_LIMBS {
375 on_stack(compute)
376 } else {
377 on_heap(need, compute)
378 }
379 }
380}
381
382impl Div<&Divisor> for &Number {
383 type Output = Number;
384
385 /// Returns `self / d`, truncated toward zero, as dividing by the number `d` was made from
386 /// does, in one new vector of exactly its length.
387 ///
388 /// # Examples
389 ///
390 /// ```
391 /// use a::math::numbers::{ByteOrder, Divisor, Number};
392 ///
393 /// let d = Divisor::new(&Number::new_from_u8(7, ByteOrder::BigEndian));
394 /// let q = &Number::new_from_i32(-100, ByteOrder::LittleEndian) / &d;
395 /// assert_eq!(q.value, [14]);
396 /// assert!(q.is_negative());
397 /// ```
398 fn div(self, d: &Divisor) -> Number {
399 d.one_new::<TRUNCATED, false>(self)
400 }
401}
402
403impl Div<&Divisor> for Number {
404 type Output = Number;
405
406 /// Returns `self / d`, as `self /= d` does, in the vector of `self`.
407 ///
408 /// # Examples
409 ///
410 /// ```
411 /// use a::math::numbers::{ByteOrder, Divisor, Number};
412 ///
413 /// let d = Divisor::new(&Number::new_from_u8(16, ByteOrder::BigEndian));
414 /// let a = Number::new_from_u32(0x1234_5678, ByteOrder::BigEndian);
415 /// let pointer = a.value.as_ptr();
416 /// let q = a / &d;
417 /// assert_eq!(q.value, [0x01, 0x23, 0x45, 0x67]);
418 /// assert_eq!(q.value.as_ptr(), pointer);
419 /// ```
420 fn div(mut self, d: &Divisor) -> Number {
421 self /= d;
422 self
423 }
424}
425
426impl DivAssign<&Divisor> for Number {
427 /// Divides `self` by `d`, truncating toward zero, keeping the byte order of `self`, in its
428 /// vector, which has room for the quotient unless it is empty.
429 ///
430 /// # Examples
431 ///
432 /// ```
433 /// use a::math::numbers::{ByteOrder, Divisor, Number};
434 ///
435 /// let ten = Divisor::new(&Number::new_from_u8(10, ByteOrder::BigEndian));
436 /// let mut n = Number::new_from_u32(12_345, ByteOrder::LittleEndian);
437 /// n /= &ten;
438 /// n /= &ten;
439 /// assert_eq!(n.value, [123]);
440 /// ```
441 fn div_assign(&mut self, d: &Divisor) {
442 d.assign::<false>(self);
443 }
444}
445
446impl Rem<&Divisor> for &Number {
447 type Output = Number;
448
449 /// Returns `self % d`, with the sign of `self`, as the remainder by the number `d` was made
450 /// from, in one new vector of exactly its length.
451 ///
452 /// # Examples
453 ///
454 /// ```
455 /// use a::math::numbers::{ByteOrder, Divisor, Number};
456 ///
457 /// let d = Divisor::new(&Number::new_from_i8(-7, ByteOrder::BigEndian));
458 /// let r = &Number::new_from_i32(100, ByteOrder::LittleEndian) % &d;
459 /// assert_eq!(r.value, [2]);
460 /// assert!(!r.is_negative());
461 /// ```
462 fn rem(self, d: &Divisor) -> Number {
463 d.one_new::<TRUNCATED, true>(self)
464 }
465}
466
467impl Rem<&Divisor> for Number {
468 type Output = Number;
469
470 /// Returns `self % d`, as `self %= d` does, in the vector of `self`.
471 ///
472 /// # Examples
473 ///
474 /// ```
475 /// use a::math::numbers::{ByteOrder, Divisor, Number};
476 ///
477 /// let d = Divisor::new(&Number::new_from_u16(1000, ByteOrder::BigEndian));
478 /// let r = Number::new_from_u32(1_234_567, ByteOrder::BigEndian) % &d;
479 /// assert_eq!(r.value, [0x02, 0x37]);
480 /// ```
481 fn rem(mut self, d: &Divisor) -> Number {
482 self %= d;
483 self
484 }
485}
486
487impl RemAssign<&Divisor> for Number {
488 /// Sets `self` to `self % d`, keeping the byte order of `self`, in its vector, which has room
489 /// for the remainder unless it is empty.
490 ///
491 /// # Examples
492 ///
493 /// ```
494 /// use a::math::numbers::{ByteOrder, Divisor, Number};
495 ///
496 /// let d = Divisor::new(&Number::new_from_u8(9, ByteOrder::BigEndian));
497 /// let mut n = Number::new_from_i32(-100, ByteOrder::LittleEndian);
498 /// n %= &d;
499 /// assert_eq!(n.value, [1]);
500 /// assert!(n.is_negative());
501 /// ```
502 fn rem_assign(&mut self, d: &Divisor) {
503 d.assign::<true>(self);
504 }
505}
506
507/// The result `p` as a number in one new vector of exactly its length, in the byte order `order`.
508///
509/// # Safety
510///
511/// As for [`Product::write`].
512#[inline(always)]
513unsafe fn new_number(p: &Product, order: ByteOrder) -> Number {
514 let mut v = Vec::with_capacity(p.len);
515 // SAFETY: the new vector has room for the `len` bytes, all of which are written before the
516 // length is set.
517 unsafe {
518 p.write(v.as_mut_ptr(), order);
519 v.set_len(p.len);
520 }
521 Number {
522 value: v,
523 negative: p.negative,
524 byte_order: order,
525 }
526}