1#![allow(dead_code)]
6#![allow(non_camel_case_types)]
7
8use crate::*;
9use crate::stdlib::fmt;
10
11use num_traits::{WrappingAdd, WrappingSub, AsPrimitive};
12
13
14pub trait RadixType: Copy + Clone + Default + fmt::Debug {
16 type Base
18 : 'static
19 + Copy
20 + fmt::Debug
21 + num_integer::Integer
22 + num_traits::PrimInt
23 + num_traits::FromPrimitive
24 + num_traits::AsPrimitive<Self::BaseDouble>
25 + num_traits::Zero
26 + num_traits::One
27 + num_traits::WrappingSub
28 + num_traits::Pow<u8, Output = Self::Base>
29 + AddAssign
30 + From<bool>
31 + From<u8>;
32
33 type BaseDouble
35 : 'static
36 + Copy
37 + num_integer::Integer
38 + num_traits::PrimInt
39 + num_traits::FromPrimitive
40 + num_traits::AsPrimitive<Self::Base>
41 + num_traits::Zero
42 + num_traits::One
43 + num_traits::WrappingAdd
44 + num_traits::WrappingSub
45 + AddAssign
46 + From<u8>
47 + From<Self::Base>;
48
49 type SignedBase
51 : 'static
52 + Copy
53 + num_integer::Integer
54 + num_traits::PrimInt
55 + num_traits::FromPrimitive
56 + num_traits::Zero
57 + num_traits::One
58 + num_traits::Signed;
59
60 const RADIX: Self::BaseDouble;
62
63 fn validate_digits<'a, I: IntoIterator<Item = &'a Self::Base>>(i: I) -> bool {
65 i.into_iter().map(|&d| d.into()).all(|d| Self::BaseDouble::zero() <= d && d < Self::RADIX)
66 }
67
68 fn max() -> Self::Base {
70 (Self::RADIX - One::one()).as_()
71 }
72
73 fn is_max(n: Self::Base) -> bool {
75 n == Self::max()
76 }
77
78 fn split_single(n: Self::Base) -> (Self::Base, Self::Base) {
81 let (hi, lo) = num_integer::div_rem(n.as_(), Self::RADIX);
82 return (hi.as_(), lo.as_());
83 }
84
85 fn split_doublewide(n: Self::BaseDouble) -> (Self::BaseDouble, Self::Base) {
87 let (hi, lo) = num_integer::div_rem(n, Self::RADIX);
88 return (hi, lo.as_());
89 }
90
91 fn split_wide_digit(n: Self::BaseDouble) -> (Self::Base, Self::Base) {
97 let (hi, lo) = num_integer::div_rem(n, Self::RADIX);
98 if true {
if !(hi < Self::RADIX) {
::core::panicking::panic("assertion failed: hi < Self::RADIX")
};
};debug_assert!(hi < Self::RADIX);
99 return (hi.as_(), lo.as_());
100 }
101
102 fn add_carry(n: Self::Base, carry: &mut Self::Base) -> Self::Base {
104 let (hi, lo) = Self::expanding_add(n, *carry);
105 *carry = hi;
106 lo
107 }
108
109 fn addassign_carry(n: &mut Self::Base, carry: &mut Self::Base) {
111 let (hi, lo) = Self::expanding_add(*n, *carry);
112 *carry = hi;
113 *n = lo;
114 }
115
116 fn addassign_with_carry(n: &mut Self::Base, a: Self::Base, carry: &mut Self::Base) {
118 let sum = n.as_() + a.as_() + carry.as_();
119 let (hi, lo) = Self::split_wide_digit(sum);
120 *carry = hi;
121 *n = lo;
122 }
123
124 fn add_expand_doublewide(a: Self::Base, b: Self::BaseDouble) -> (Self::Base, Self::Base) {
126 let a: Self::BaseDouble = a.into();
127 Self::split_wide_digit(a + b)
128 }
129
130 fn expanding_add(a: Self::Base, b: Self::Base) -> (Self::Base, Self::Base) {
132 let a: Self::BaseDouble = a.into();
133 let b: Self::BaseDouble = b.into();
134 Self::split_wide_digit(a + b)
135 }
136
137 fn expanding_mul(a: Self::Base, b: Self::Base) -> (Self::Base, Self::Base) {
139 let a: Self::BaseDouble = a.into();
140 let b: Self::BaseDouble = b.into();
141 Self::split_wide_digit(a * b)
142 }
143
144 fn fused_mul_add(a: Self::Base, b: Self::Base, c: Self::Base) -> (Self::Base, Self::Base) {
146 let a: Self::BaseDouble = a.into();
147 let b: Self::BaseDouble = b.into();
148 let c: Self::BaseDouble = c.into();
149 Self::split_wide_digit(a * b + c)
150 }
151
152 fn carrying_mul_add(
154 a: Self::Base,
155 b: Self::Base,
156 c: Self::Base,
157 d: Self::Base,
158 ) -> (Self::Base, Self::Base) {
159 let a: Self::BaseDouble = a.into();
160 let b: Self::BaseDouble = b.into();
161 let c: Self::BaseDouble = c.into();
162 let d: Self::BaseDouble = d.into();
163 Self::split_wide_digit(a * b + c + d)
164 }
165
166 fn carrying_mul_add_inplace(
168 a: Self::Base,
169 b: Self::Base,
170 c: &mut Self::Base,
171 carry: &mut Self::Base,
172 ) {
173 let a: Self::BaseDouble = a.into();
174 let b: Self::BaseDouble = b.into();
175 let (hi, lo) = Self::split_wide_digit(a * b + (*c).into() + (*carry).into());
176 *c = lo;
177 *carry = hi;
178 }
179
180 fn add_carry_into_slice(dest: &mut [Self::Base], c: &mut Self::Base) {
185 Self::add_carry_into(dest.iter_mut(), c)
186 }
187
188 fn add_carry_into<'a, I: Iterator<Item=&'a mut Self::Base>>(dest: I, c: &mut Self::Base) {
194 for d in dest {
195 if c.is_zero() {
196 return;
197 }
198
199 let (overflow, sum) = Self::expanding_add(*c, *d);
200 *d = sum;
201 *c = overflow;
202 }
203 }
204
205 fn mulassign_add_carry(
207 a: &mut Self::Base,
208 b: Self::Base,
209 carry: &mut Self::Base,
210 ) {
211 let (hi, lo) = Self::expanding_mul(*a, b);
212 *a = Self::add_carry(lo, carry);
213 *carry += hi;
214 }
215
216 fn sub_with_carry_borrow(
218 lhs: Self::Base,
219 rhs: Self::Base,
220 carry: &mut Self::Base,
221 borrow: &mut Self::Base,
222 ) -> Self::Base {
223 let mut result = Self::BaseDouble::from(lhs);
224 result = result
225 .wrapping_sub(&Self::BaseDouble::from(rhs))
226 .wrapping_add(&(*carry).as_())
227 .wrapping_sub(&(*borrow).as_());
228
229 *borrow = Self::Base::from(result >= (Self::RADIX << 1));
230 result = result.wrapping_add(&(borrow.as_() * Self::RADIX));
231 if true {
if !(result < (Self::RADIX << 1)) {
::core::panicking::panic("assertion failed: result < (Self::RADIX << 1)")
};
};debug_assert!(result < (Self::RADIX << 1));
232
233 *carry = Self::Base::from(result >= Self::RADIX);
234 result = result - carry.as_() * Self::RADIX;
235
236 return result.as_();
237 }
238}
239
240)]
242pub struct RADIX_10_u8;
243
244)]
246pub struct RADIX_10p4_i16;
247
248)]
250pub struct RADIX_10p9_u32;
251
252)]
254pub struct RADIX_10p19_u64;
255
256)]
258pub struct RADIX_u32;
259
260)]
262pub struct RADIX_u64;
263
264
265pub(crate) trait RadixPowerOfTen: RadixType {
266 const DIGITS: usize;
267
268 fn divceil_digit_count(digit_count: usize) -> usize {
270 use num_integer::Integer;
271 Integer::div_ceil(&digit_count, &Self::DIGITS)
272 }
273
274 fn divmod_digit_count(digit_count: usize) -> (usize, usize) {
276 use num_integer::Integer;
277 Integer::div_rem(&digit_count, &Self::DIGITS)
278 }
279}
280
281impl RadixPowerOfTen for RADIX_10p19_u64 {
282 const DIGITS: usize = 19;
283}
284impl RadixPowerOfTen for RADIX_10p9_u32 {
285 const DIGITS: usize = 9;
286}
287impl RadixPowerOfTen for RADIX_10_u8 {
288 const DIGITS: usize = 1;
289}
290impl RadixPowerOfTen for RADIX_10p4_i16 {
291 const DIGITS: usize = 4;
292}
293
294impl RADIX_10p19_u64 {
295 pub(crate) fn rotating_div_u64_radix(hi: u64, lo: &mut u64) -> <Self as RadixType>::Base {
298 use num_integer::div_rem;
299 type BaseDouble = <RADIX_10p19_u64 as RadixType>::BaseDouble;
300
301 let num = BaseDouble::from(*lo) + (BaseDouble::from(hi) << 64);
302 let (q, r) = div_rem(num, Self::RADIX);
303 *lo = q.as_();
304 r.as_()
305 }
306}
307
308#[cfg(test)]
309mod test_validate {
310 use super::*;
311
312 macro_rules! impl_case {
313 (valid $name:ident : $radix:ident ~ $values:expr) => {
314 #[test]
315 fn $name() {
316 assert!($radix::validate_digits($values.iter()));
317 }
318 };
319 (invalid $name:ident : $radix:ident ~ $values:expr) => {
320 #[test]
321 fn $name() {
322 assert!(!$radix::validate_digits($values.iter()));
323 }
324 };
325 }
326
327 impl_case!(valid case_valid: RADIX_10p4_i16 ~ [1, 2, 3, 4, 5, 600]);
328 impl_case!(invalid case_invalid_too_big: RADIX_10p4_i16 ~ [10000, 1, 2, 3, 4, 5, 600]);
329 impl_case!(invalid case_invalid_negative: RADIX_10p4_i16 ~ [1, 2, -3, 4, 5, 600]);
330 impl_case!(invalid case_invalid_leading_zeros: RADIX_10p4_i16 ~ [0, 1, 2, -3, 4, 5, 600]);
331 impl_case!(invalid case_p9_toobig: RADIX_10p9_u32 ~ [3330199352]);
332}
333
334impl RadixType for RADIX_u32 {
335 type Base = u32;
336 type BaseDouble = u64;
337 type SignedBase = i32;
338
339 const RADIX: Self::BaseDouble = 1u64 << 32;
340
341 fn validate_digits<'a, I: IntoIterator<Item = &'a Self::Base>>(_: I) -> bool {
343 true
344 }
345
346 fn expanding_add(a: u32, b: u32) -> (u32, u32) {
347 let (sum, overflow) = a.overflowing_add(b);
348 (u32::from(overflow), sum)
349 }
350}
351
352impl RadixType for RADIX_u64 {
353 type Base = u64;
354 type BaseDouble = u128;
355 type SignedBase = i64;
356
357 const RADIX: Self::BaseDouble = 1u128 << 64;
358
359 fn validate_digits<'a, I: IntoIterator<Item = &'a Self::Base>>(_: I) -> bool {
361 true
362 }
363
364 fn expanding_add(a: u64, b: u64) -> (u64, u64) {
365 let (sum, overflow) = a.overflowing_add(b);
366 (u64::from(overflow), sum)
367 }
368}
369
370impl RadixType for RADIX_10p4_i16 {
371 type Base = i16;
372 type BaseDouble = i32;
373 type SignedBase = i64;
374
375 const RADIX: Self::BaseDouble = 10_000;
376}
377
378impl RadixType for RADIX_10p9_u32 {
379 type Base = u32;
380 type BaseDouble = u64;
381 type SignedBase = i32;
382
383 const RADIX: Self::BaseDouble = 1_000_000_000;
384}
385
386impl RadixType for RADIX_10p19_u64 {
387 type Base = u64;
388 type BaseDouble = u128;
389 type SignedBase = i64;
390
391 const RADIX: Self::BaseDouble = 10_000_000_000_000_000_000;
392}
393
394impl RadixType for RADIX_10_u8 {
395 type Base = u8;
396 type BaseDouble = u8;
397 type SignedBase = i8;
398
399 const RADIX: Self::BaseDouble = 10;
400}
401
402#[cfg(test)]
403mod tests {
404 use super::*;
405
406 include!("radix.tests.rs");
407}