a/math/numbers/root.rs
1//! Integer roots of [`Number`]s: [`Number::isqrt`], [`Number::isqrt_rem`] and
2//! [`Number::nth_root`].
3//!
4//! A root is truncated toward zero, as GMP's `mpz_sqrt` and `mpz_root` and Rust's `isqrt` truncate
5//! it: the square root of a number is the largest integer whose square is not above it, and the
6//! `n`-th root of a negative number for an odd `n` is the root of its magnitude, negated. A zero
7//! magnitude is zero whatever `negative` says, and zero bytes above the most significant one count
8//! for nothing.
9//!
10//! Magnitudes whose vectors hold at most 16 bytes are rooted in registers: as a `u128`, from a
11//! floating-point estimate made exact (see [`sqrt::sqrt_rem_u128`] and [`small_root`]). Longer
12//! ones are read into limbs of eight bytes, native `u64`s, the least significant first, in
13//! working memory on the stack, or on the heap for the longest: square roots by Zimmermann's
14//! Karatsuba square root (see [`sqrt`]), other roots by Newton's method at doubling precision
15//! (see [`nth`]). The results are written in the byte order of `self`, in the shortest form.
16
17mod nth;
18mod sqrt;
19
20use super::add::{SMALL, read_small, write_small};
21use super::mul::{Operand, Product, STACK_LIMBS, WIDE, on_heap, on_stack, read_wide, to_limbs};
22use super::{ByteOrder, Number};
23use core::mem::MaybeUninit;
24
25pub(super) use nth::quotient;
26pub(super) use sqrt::sqrt_rem_u128;
27
28impl Number {
29 /// Returns the square root of `self` rounded down, `floor(sqrt(self))`: the largest integer
30 /// whose square is not above `self`, in the byte order of `self`, in the shortest form, in one
31 /// new vector.
32 ///
33 /// Up to 16 bytes the root is computed in registers; longer magnitudes by Zimmermann's
34 /// Karatsuba square root, in the time of a product of their limbs, up to a constant.
35 ///
36 /// # Panics
37 ///
38 /// When `self` is negative, with the message of `i64::isqrt`; a negative zero is zero.
39 ///
40 /// # Examples
41 ///
42 /// ```
43 /// use a::math::numbers::{ByteOrder, Number};
44 ///
45 /// let n = Number::new_from_u64(1_000_000_000_000, ByteOrder::BigEndian);
46 /// assert_eq!(n.isqrt().value, Number::new_from_u32(1_000_000, ByteOrder::BigEndian).value);
47 ///
48 /// // 99 is not a square: its root is rounded down.
49 /// assert_eq!(Number::new_from_u8(99, ByteOrder::LittleEndian).isqrt().value, [9]);
50 /// ```
51 #[track_caller]
52 pub fn isqrt(&self) -> Number {
53 if self.value.len() <= SMALL {
54 // SAFETY: the vector holds at most 16 bytes.
55 let x = unsafe { read_small(&self.value, self.byte_order) };
56 if self.negative && x != 0 {
57 negative_square_root();
58 }
59 let (s, _) = sqrt_rem_u128(x);
60 return small_number(self.byte_order, u128::from(s), false);
61 }
62 if self.value.len() <= WIDE {
63 return wide_square_root::<false>(self).0;
64 }
65 long_square_root::<false>(self).0
66 }
67
68 /// Returns the square root of `self` rounded down and the remainder: `(s, r)` with
69 /// `s = floor(sqrt(self))` and `r = self - s^2`, which is at most `2s`, both in the byte order
70 /// of `self`, in the shortest form, in one new vector each.
71 ///
72 /// # Panics
73 ///
74 /// When `self` is negative, with the message of `i64::isqrt`; a negative zero is zero.
75 ///
76 /// # Examples
77 ///
78 /// ```
79 /// use a::math::numbers::{ByteOrder, Number};
80 ///
81 /// // 1000 = 31^2 + 39.
82 /// let (s, r) = Number::new_from_u16(1000, ByteOrder::BigEndian).isqrt_rem();
83 /// assert_eq!(s.value, [31]);
84 /// assert_eq!(r.value, [39]);
85 /// ```
86 #[track_caller]
87 pub fn isqrt_rem(&self) -> (Number, Number) {
88 if self.value.len() <= SMALL {
89 // SAFETY: the vector holds at most 16 bytes.
90 let x = unsafe { read_small(&self.value, self.byte_order) };
91 if self.negative && x != 0 {
92 negative_square_root();
93 }
94 let (s, r) = sqrt_rem_u128(x);
95 let order = self.byte_order;
96 return (
97 small_number(order, u128::from(s), false),
98 small_number(order, r, false),
99 );
100 }
101 if self.value.len() <= WIDE {
102 return wide_square_root::<true>(self);
103 }
104 long_square_root::<true>(self)
105 }
106
107 /// Returns the `n`-th root of `self` truncated toward zero: for a `self` that is not negative,
108 /// the largest integer whose `n`-th power is not above `self`, and for a negative `self` and an
109 /// odd `n`, the root of its magnitude negated, as GMP's `mpz_root` and num-integer's
110 /// `Roots::nth_root` give it. The root is in the byte order of `self`, in the shortest form,
111 /// in one new vector.
112 ///
113 /// `n = 1` gives `self` and `n = 2` its square root, as [`isqrt`](Self::isqrt) does. Up to 16
114 /// bytes the root is computed in registers; for longer magnitudes, by Newton's method at
115 /// doubling precision, as GMP's `mpn_rootrem` does.
116 ///
117 /// # Panics
118 ///
119 /// When `n` is 0, with the message `root degree n must be at least 1`, and when `self` is
120 /// negative and `n` even, with the message `even roots of a negative are imaginary`, as
121 /// num-integer's `Roots::nth_root` panics; a negative zero is zero.
122 ///
123 /// # Examples
124 ///
125 /// ```
126 /// use a::math::numbers::{ByteOrder, Number};
127 ///
128 /// // 10^18 = (10^6)^3, and the cube root of -999,999 is -99.
129 /// let n = Number::new_from_u64(1_000_000_000_000_000_000, ByteOrder::BigEndian);
130 /// assert_eq!(n.nth_root(3).value, Number::new_from_u32(1_000_000, ByteOrder::BigEndian).value);
131 /// let m = Number::new_from_i32(-999_999, ByteOrder::LittleEndian);
132 /// let root = m.nth_root(3);
133 /// assert_eq!(root.value, [99]);
134 /// assert!(root.is_negative());
135 /// ```
136 #[track_caller]
137 pub fn nth_root(&self, n: u32) -> Number {
138 if n == 0 {
139 zero_degree();
140 }
141 if self.value.len() <= SMALL {
142 // SAFETY: the vector holds at most 16 bytes.
143 let x = unsafe { read_small(&self.value, self.byte_order) };
144 let negative = self.negative && x != 0;
145 if negative && n.is_multiple_of(2) {
146 imaginary_root();
147 }
148 return small_number(self.byte_order, small_root(x, n), negative);
149 }
150 long_root(self, n)
151 }
152}
153
154/// Panics as `i64::isqrt` does for a negative argument.
155#[cold]
156#[inline(never)]
157#[track_caller]
158fn negative_square_root() -> ! {
159 panic!("argument of integer square root cannot be negative")
160}
161
162/// Panics as num-integer's `Roots::nth_root` does for a root of degree 0.
163#[cold]
164#[inline(never)]
165#[track_caller]
166fn zero_degree() -> ! {
167 panic!("root degree n must be at least 1")
168}
169
170/// Panics as num-integer's `Roots::nth_root` does for an even root of a negative number.
171#[cold]
172#[inline(never)]
173#[track_caller]
174fn imaginary_root() -> ! {
175 panic!("even roots of a negative are imaginary")
176}
177
178// Small numbers
179
180/// The magnitude `v` of at most 16 bytes, its sign `negative` (dropped for zero) and the byte order
181/// `order` as a number in one new vector of exactly its length.
182pub(super) fn small_number(order: ByteOrder, v: u128, negative: bool) -> Number {
183 let len = 16 - (v | 1).leading_zeros() as usize / 8;
184 let mut value = Vec::with_capacity(len);
185 // SAFETY: the new vector has room for the `len` bytes, from 1 to 16, all of which are written
186 // before the length is set.
187 unsafe {
188 write_small(value.as_mut_ptr(), order, v as u64, (v >> 64) as u64, len);
189 value.set_len(len);
190 }
191 Number {
192 value,
193 negative: negative && v != 0,
194 byte_order: order,
195 }
196}
197
198/// The `n`-th root of `x`, truncated: the largest `s` with `s^n <= x`.
199///
200/// For `n >= 3` the root is below `2^43`. Its estimate in double precision, `x^(1/n)` (the cube
201/// root for `n = 3`, which the system computes faster), is off by far less than one; the root is
202/// its floor, or one less or one more, which two powers computed exactly side by side tell, and
203/// steps of one in the rare other cases.
204pub(super) fn small_root(x: u128, n: u32) -> u128 {
205 match n {
206 1 => return x,
207 2 => return u128::from(sqrt_rem_u128(x).0),
208 _ => {}
209 }
210 let bits = 128 - x.leading_zeros();
211 if bits <= n {
212 // `1 <= x < 2^n`: the root is 1, or 0 for 0.
213 return u128::from(x != 0);
214 }
215 let estimate = if bits.div_ceil(n) <= ROUGH_BITS {
216 let top = (x << x.leading_zeros() >> 64) as u64;
217 rough_root(top, u64::from(bits), n)
218 } else {
219 let xf = ((x >> 64) as u64) as f64 * 18_446_744_073_709_551_616.0 + (x as u64) as f64;
220 if n == 3 {
221 xf.cbrt()
222 } else {
223 xf.powf(1.0 / f64::from(n))
224 }
225 };
226 // At least 1, as `x >= 2^n`, and below `2^43`.
227 let s = u128::from((estimate as u64).max(1));
228 let (low, high) = (power_at_most(s, n, x), power_at_most(s + 1, n, x));
229 if low && !high {
230 return s;
231 }
232 small_root_steps(x, n, s, low)
233}
234
235/// Whether `s^n <= x`, for `s` below `2^44`.
236#[inline(always)]
237fn power_at_most(s: u128, n: u32, x: u128) -> bool {
238 power_u128(s, n).is_some_and(|p| p <= x)
239}
240
241/// [`small_root`] from an estimate `s` that is not the root: one less while `s^n > x`, when `low`
242/// says `s^n <= x` is false, and otherwise one more while `(s + 1)^n <= x`.
243#[cold]
244#[inline(never)]
245fn small_root_steps(x: u128, n: u32, mut s: u128, low: bool) -> u128 {
246 let below = |s: u128| power_at_most(s, n, x);
247 if !low {
248 s -= 1;
249 while !below(s) {
250 s -= 1;
251 }
252 return s;
253 }
254 while below(s + 1) {
255 s += 1;
256 }
257 s
258}
259
260/// The roots of at most this many bits are estimated by [`rough_root`].
261pub(super) const ROUGH_BITS: u32 = 18;
262
263/// An estimate of `T^(1/n)` for a `T` of `bits` bits whose top 64 are `top`, for a root of at
264/// most [`ROUGH_BITS`] bits: `2^(log2(T) / n)` with `log2` and `2^x` from polynomials on `[0, 1)`
265/// fitted at Chebyshev points (errors of `2.2 10^-6` and `1.1 10^-7`), so within a part in a
266/// million of the root, below 0.3 for a root of 18 bits, in about a quarter of the time of the
267/// system's `powf`, whose latency was about 80 cycles on an Apple M4 Max.
268pub(super) fn rough_root(top: u64, bits: u64, n: u32) -> f64 {
269 // `T = 2^(bits - 1) (1 + f)`.
270 let f = (top >> 11) as f64 * (1.0 / 4_503_599_627_370_496.0) - 1.0;
271 let horner = |c: &[f64], x: f64| c.iter().fold(0.0, |acc, &c| acc * x + c);
272 let log1p = horner(
273 &[
274 -0.025_123_203_286_102_475,
275 0.119_298_237_706_177_92,
276 -0.274_623_257_617_108_6,
277 0.455_527_088_061_034_7,
278 -0.717_557_872_422_149_5,
279 1.442_475_314_822_074_8,
280 2.123_740_891_505_907_2e-6,
281 ],
282 f,
283 );
284 let l = ((bits - 1) as f64 + log1p) / f64::from(n);
285 let i = l.floor();
286 let exp = horner(
287 &[
288 0.001_895_107_290_998_152_7,
289 0.008_946_214_666_338_551,
290 0.055_863_282_659_265_955,
291 0.240_140_770_091_823_9,
292 0.693_154_620_003_301_9,
293 0.999_999_895_763_136,
294 ],
295 l - i,
296 );
297 // `2^i` for `0 <= i <= ROUGH_BITS`, from its exponent bits.
298 exp * f64::from_bits((i as u64 + 1023) << 52)
299}
300
301/// `s^n`, or `None` above `u128::MAX`, by squares and products: unchecked when the bits of `s`
302/// show that the power fits, `s^n < 2^(bits n) <= 2^128`, `None` at once when they show it does
303/// not, `s^n >= 2^((bits - 1) n) >= 2^128`, and checked at each step in between.
304#[inline(always)]
305fn power_u128(s: u128, n: u32) -> Option<u128> {
306 let bits = u64::from(128 - s.leading_zeros());
307 let n64 = u64::from(n);
308 if s.is_power_of_two() {
309 // `2^((bits - 1) n)`: a shift.
310 let shift = (bits - 1) * n64;
311 return if shift < 128 { Some(1 << shift) } else { None };
312 }
313 if bits * n64 <= 128 {
314 Some(s.wrapping_pow(n))
315 } else if bits.saturating_sub(1) * n64 >= 128 {
316 None
317 } else {
318 s.checked_pow(n)
319 }
320}
321
322// Numbers of up to 32 bytes
323
324/// The square root of `a` and, with `REM`, the remainder, for a vector of 17 to 32 bytes: in
325/// registers, by [`sqrt::sqrt_rem_wide`] for a magnitude of at least `2^128`. Without `REM`, the
326/// remainder returned is an empty number.
327#[inline(never)]
328#[track_caller]
329fn wide_square_root<const REM: bool>(a: &Number) -> (Number, Number) {
330 let order = a.byte_order;
331 // SAFETY: the vector holds at most 32 bytes.
332 let x = unsafe { read_wide(&a.value, a.byte_order) };
333 if a.negative && x != [0; 4] {
334 negative_square_root();
335 }
336 if x[2] == 0 && x[3] == 0 {
337 let (s, r) = sqrt_rem_u128(u128::from(x[1]) << 64 | u128::from(x[0]));
338 let rem = if REM {
339 small_number(order, r, false)
340 } else {
341 empty(order)
342 };
343 return (small_number(order, u128::from(s), false), rem);
344 }
345 let (s, r) = sqrt::sqrt_rem_wide::<REM>(x);
346 let rem = if REM {
347 // SAFETY: the array holds the remainder's three limbs.
348 unsafe { limbs_number(r.as_ptr(), 3, false, order) }
349 } else {
350 empty(order)
351 };
352 (small_number(order, s, false), rem)
353}
354
355// Long numbers
356
357/// The square root of `a` and, with `REM`, the remainder, for a vector of more than 16 bytes:
358/// in registers up to 16 significant bytes, and otherwise by [`sqrt::sqrtrem`] on its limbs.
359/// Without `REM`, the remainder returned is an empty number.
360#[inline(never)]
361#[track_caller]
362fn long_square_root<const REM: bool>(a: &Number) -> (Number, Number) {
363 let x = Operand::of(a);
364 let order = a.byte_order;
365 if a.negative && x.significant != 0 {
366 negative_square_root();
367 }
368 if x.significant <= SMALL {
369 // SAFETY: the operand is that of `a`.
370 let (s, r) = sqrt_rem_u128(unsafe { small_value(x) });
371 let rem = if REM {
372 small_number(order, r, false)
373 } else {
374 empty(order)
375 };
376 return (small_number(order, u128::from(s), false), rem);
377 }
378 let an = x.significant.div_ceil(8);
379 let tn = an.div_ceil(2);
380 // The magnitude, the root and the remainder, each in an even number of limbs, then the working
381 // memory of `sqrtrem`.
382 let need =
383 even(an) + even(tn + 1) + if REM { even(tn + 1) } else { 0 } + sqrt::sqrtrem_itch(an);
384 let compute = |w: *mut MaybeUninit<u64>| {
385 let w: *mut u64 = w.cast();
386 // SAFETY: the working memory holds the `need` limbs counted above; the operand is that of
387 // `a`, borrowed until the results are written.
388 unsafe {
389 let (m, s) = (w, w.add(even(an)));
390 let r = s.add(even(tn + 1));
391 let t = if REM { r.add(even(tn + 1)) } else { r };
392 to_limbs(x, m);
393 let rn = sqrt::sqrtrem::<REM>(s, r, m, an, t);
394 let root = limbs_number(s, tn, false, order);
395 let rem = if REM {
396 limbs_number(r, rn, false, order)
397 } else {
398 empty(order)
399 };
400 (root, rem)
401 }
402 };
403 if need <= LOCAL_LIMBS {
404 let mut local = [PAIR; LOCAL_LIMBS / 2];
405 compute(local.as_mut_ptr().cast())
406 } else if need <= STACK_LIMBS {
407 on_stack(compute)
408 } else {
409 on_heap(need, compute)
410 }
411}
412
413/// The limbs of working memory up to which a root is computed in a buffer of its function's own
414/// frame, instead of the larger one of `on_stack`.
415const LOCAL_LIMBS: usize = 64;
416
417/// Two limbs of working memory, aligned to 16 bytes, as the kernels read them in pairs.
418#[derive(Clone, Copy)]
419#[repr(C, align(16))]
420struct Pair([MaybeUninit<u64>; 2]);
421
422/// An uninitialised pair of limbs.
423const PAIR: Pair = Pair([MaybeUninit::uninit(); 2]);
424
425/// The `n`-th root of `a` for a vector of more than 16 bytes and `n >= 1`: in registers up to 16
426/// significant bytes, 1 for magnitudes of at most `n` bits, and otherwise by [`nth::root`] on its
427/// limbs.
428#[inline(never)]
429#[track_caller]
430fn long_root(a: &Number, n: u32) -> Number {
431 let x = Operand::of(a);
432 let order = a.byte_order;
433 let negative = a.negative && x.significant != 0;
434 if negative && n.is_multiple_of(2) {
435 imaginary_root();
436 }
437 if x.significant <= SMALL {
438 // SAFETY: the operand is that of `a`.
439 let v = unsafe { small_value(x) };
440 return small_number(order, small_root(v, n), negative);
441 }
442 if n == 2 {
443 // Not negative, or the even root would have panicked.
444 return a.isqrt();
445 }
446 let an = x.significant.div_ceil(8);
447 if 8 * x.significant as u64 <= u64::from(n) {
448 // A magnitude of at most `n` bits, not zero, is below `2^n`: its root is 1.
449 return small_number(order, 1, negative);
450 }
451 if n == 1 {
452 let compute = |w: *mut MaybeUninit<u64>| {
453 let w: *mut u64 = w.cast();
454 // SAFETY: the working memory holds the operand's limbs; the operand is that of `a`.
455 unsafe {
456 to_limbs(x, w);
457 limbs_number(w, an, negative, order)
458 }
459 };
460 return if an <= STACK_LIMBS {
461 on_stack(compute)
462 } else {
463 on_heap(an, compute)
464 };
465 }
466 // The magnitude, then the working memory of `nth::root`, which starts with the root.
467 let need = even(an) + nth::root_itch(an, n);
468 let compute = |w: *mut MaybeUninit<u64>| {
469 let w: *mut u64 = w.cast();
470 // SAFETY: the working memory holds the `need` limbs counted above; the operand is that of
471 // `a`, borrowed until the root is written.
472 unsafe {
473 let (m, r) = (w, w.add(even(an)));
474 to_limbs(x, m);
475 let sn = nth::root(m, an, n, r);
476 limbs_number(r, sn, negative, order)
477 }
478 };
479 if need <= STACK_LIMBS {
480 on_stack(compute)
481 } else {
482 on_heap(need, compute)
483 }
484}
485
486/// The magnitude of the operand `x` of at most 16 significant bytes, as a `u128`.
487///
488/// # Safety
489///
490/// The operand's vector must be valid for reads.
491unsafe fn small_value(x: Operand) -> u128 {
492 let mut l = [0u64; 2];
493 // SAFETY: the significant bytes fill at most two limbs.
494 unsafe { to_limbs(x, l.as_mut_ptr()) };
495 u128::from(l[0]) | (u128::from(l[1]) << 64)
496}
497
498/// A number with an empty vector, which allocates nothing: the remainder `long_square_root` does
499/// not compute.
500fn empty(order: ByteOrder) -> Number {
501 Number {
502 value: Vec::new(),
503 negative: false,
504 byte_order: order,
505 }
506}
507
508/// `n` rounded up to an even number of limbs, so that a buffer after `n` limbs of one that starts
509/// on 16 bytes starts on 16 bytes too.
510const fn even(n: usize) -> usize {
511 (n + 1) & !1
512}
513
514/// The `n` limbs at `r` as a number in one new vector of exactly its length, in the byte order
515/// `order`, in the shortest form: without the zero limbs at the top, and zero as `[0]`, never
516/// negative.
517///
518/// # Safety
519///
520/// The limbs must be valid for reads.
521pub(super) unsafe fn limbs_number(
522 r: *const u64,
523 n: usize,
524 negative: bool,
525 order: ByteOrder,
526) -> Number {
527 // SAFETY: as the caller guarantees.
528 unsafe {
529 let mut top = n;
530 while top > 0 && *r.add(top - 1) == 0 {
531 top -= 1;
532 }
533 let product = if top == 0 {
534 Product {
535 r: core::ptr::null(),
536 len: 1,
537 negative: false,
538 }
539 } else {
540 let len = 8 * top - (*r.add(top - 1)).leading_zeros() as usize / 8;
541 Product { r, len, negative }
542 };
543 let mut v = Vec::with_capacity(product.len);
544 product.write(v.as_mut_ptr(), order);
545 v.set_len(product.len);
546 Number {
547 value: v,
548 negative: product.negative,
549 byte_order: order,
550 }
551 }
552}
553
554// Shared limb helpers
555
556/// Sets the `n` limbs at `dst` to the `n` limbs at `src` shifted left by `s < 64` bits, and returns
557/// the bits shifted out of the top one.
558///
559/// # Safety
560///
561/// The limbs at `src` must be valid for reads and those at `dst` for writes; `dst` may be `src`,
562/// or above it.
563pub(super) unsafe fn lshift(dst: *mut u64, src: *const u64, n: usize, s: u32) -> u64 {
564 // SAFETY: as the caller guarantees; from the top down, each limb of `src` is read before the
565 // limb of `dst` at or above it is written.
566 unsafe {
567 if s == 0 {
568 core::ptr::copy(src, dst, n);
569 return 0;
570 }
571 let out = *src.add(n - 1) >> (64 - s);
572 for i in (1..n).rev() {
573 *dst.add(i) = (*src.add(i) << s) | (*src.add(i - 1) >> (64 - s));
574 }
575 *dst = *src << s;
576 out
577 }
578}
579
580/// Sets the `n` limbs at `dst` to the `n` limbs at `src` shifted right by `0 < s < 64` bits.
581///
582/// # Safety
583///
584/// The limbs at `src` must be valid for reads and those at `dst` for writes; `dst` may be `src`,
585/// or below it.
586pub(super) unsafe fn rshift(dst: *mut u64, src: *const u64, n: usize, s: u32) {
587 debug_assert!(0 < s && s < 64);
588 // SAFETY: as the caller guarantees; from the bottom up, each limb of `src` is read before the
589 // limb of `dst` at or below it is written.
590 unsafe {
591 for i in 0..n - 1 {
592 *dst.add(i) = (*src.add(i) >> s) | (*src.add(i + 1) << (64 - s));
593 }
594 *dst.add(n - 1) = *src.add(n - 1) >> s;
595 }
596}
597
598/// Sets the `n` limbs at `r` to the `n` limbs at `x` times `y`, and returns the limb above them.
599///
600/// # Safety
601///
602/// The limbs at `x` must be valid for reads and those at `r` for writes; `r` may be `x`.
603pub(super) unsafe fn mul_1(r: *mut u64, x: *const u64, n: usize, y: u64) -> u64 {
604 let mut carry = 0;
605 // SAFETY: as the caller guarantees; limb `i` of `x` is read before limb `i` of `r` is written.
606 unsafe {
607 for i in 0..n {
608 let p = u128::from(*x.add(i)) * u128::from(y) + u128::from(carry);
609 *r.add(i) = p as u64;
610 carry = (p >> 64) as u64;
611 }
612 }
613 carry
614}
615
616/// Adds the `n` limbs at `x` times `y` to the `n` limbs at `r`, and returns the limb that carries
617/// out of them.
618///
619/// # Safety
620///
621/// The limbs at `x` must be valid for reads and those at `r` for reads and writes, apart.
622pub(super) unsafe fn addmul_1(r: *mut u64, x: *const u64, n: usize, y: u64) -> u64 {
623 let mut carry = 0;
624 // SAFETY: as the caller guarantees; `x y + r + carry` fits a `u128`.
625 unsafe {
626 for i in 0..n {
627 let p =
628 u128::from(*x.add(i)) * u128::from(y) + u128::from(*r.add(i)) + u128::from(carry);
629 *r.add(i) = p as u64;
630 carry = (p >> 64) as u64;
631 }
632 }
633 carry
634}