1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// SPDX-FileCopyrightText: 2026 John Moxley
// SPDX-License-Identifier: MIT OR Apache-2.0
//! `div_native` -- decimal division via the hardware `i128` path, for narrow
//! storage widths (`N <= 2`, i.e. D18 / D38).
//!
//! When the storage fits a single `i128` (`N == 1` is `i64`-backed but
//! widens losslessly; `N == 2` *is* `i128`), the whole scale-then-divide can
//! be done in hardware integers instead of forming a `2N`-limb scaled
//! numerator in a scratch buffer and routing it through the slice divide.
//!
//! Two specialised arms, selected on `N` at compile time (the unused arm is
//! dead-code-eliminated per monomorphisation):
//!
//! * **`N == 1` (D18):** the scaled numerator `a * 10^SCALE` fits `i128` (an
//! `i64` magnitude times `10^18 < 2^60`) and the divisor `b` is an `i64`
//! magnitude that fits `u64`. The rescale is therefore an `i128 / u64`
//! schoolbook divide -- two hardware `divq` via
//! [`crate::macros::arithmetic::i128_divrem_by_u64_with_mode`] -- not the
//! LLVM `__divti3` soft-call an `i128 / i128` (the `apply_rounding`
//! double-divmod) would lower to. `b`'s sign is folded into the numerator so
//! the directed-rounding tie-break sees the true quotient sign.
//! * **`N == 2` (D38):** the divisor can be a full `i128` and the scaled
//! numerator can exceed `i128`, so the rescale delegates to the shared
//! hardware kernel
//! [`crate::algos::support::mg_divide::div_pow10_div_with`] (an `i128` fast
//! path with a `256`-bit fallback; returns `None` on a zero divisor or on
//! `i128` overflow of the quotient).
//!
//! # Overflow / divide-by-zero contract
//!
//! A zero divisor panics up front (matching `i128 /` and the `WidenScale`
//! kernel). `div_pow10_div_with` returns `None` for an out-of-range quotient
//! (and for the zero divisor it never sees, guarded here): the default
//! operator panics on that overflow in BOTH debug and release — a fixed-width
//! decimal has no ±∞/NaN, so silently returning a wrapped value is a wrong
//! number with no signal. The explicit `wrapping_div` / `checked_div` /
//! `saturating_div` / `overflowing_div` variants (in `crate::macros::overflow`)
//! carry the modular / `None` / clamp / flag policies via their own `Int<N>`
//! paths, not this kernel.
//!
//! # Layering
//!
//! All arithmetic is `i128` / `Int<N>` integer work dispatched DOWN to the
//! int layer and the shared `mg_divide` leaf; this fn never calls a decimal
//! method on its own value. Valid only for `N <= 2` (where `as_i128` is
//! lossless) -- [`crate::policy::div`] routes only `N == 1 | 2` here.
use cratediv_pow10_div_with;
use crateInt;
use crateRoundingMode;
/// Hardware-`i128` decimal divide kernel for narrow storage (`N <= 2`).
///
/// Computes `(a * 10^SCALE) / b` rounded under `mode`. Panics on a zero
/// divisor and on `i128` overflow of the quotient in BOTH debug and release
/// per the decimal default-operator contract.
pub