Skip to main content

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}