1 // Translated from C to Rust. The original C code can be found at
2 // https://github.com/ulfjack/ryu and carries the following license:
3 //
4 // Copyright 2018 Ulf Adams
5 //
6 // The contents of this file may be used under the terms of the Apache License,
7 // Version 2.0.
8 //
9 //    (See accompanying file LICENSE-Apache or copy at
10 //     http://www.apache.org/licenses/LICENSE-2.0)
11 //
12 // Alternatively, the contents of this file may be used under the terms of
13 // the Boost Software License, Version 1.0.
14 //    (See accompanying file LICENSE-Boost or copy at
15 //     https://www.boost.org/LICENSE_1_0.txt)
16 //
17 // Unless required by applicable law or agreed to in writing, this software
18 // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19 // KIND, either express or implied.
20 
21 use core::ptr;
22 
23 #[cfg_attr(feature = "no-panic", inline)]
div5(x: u64) -> u6424 pub fn div5(x: u64) -> u64 {
25     x / 5
26 }
27 
28 #[cfg_attr(feature = "no-panic", inline)]
div10(x: u64) -> u6429 pub fn div10(x: u64) -> u64 {
30     x / 10
31 }
32 
33 #[cfg_attr(feature = "no-panic", inline)]
div100(x: u64) -> u6434 pub fn div100(x: u64) -> u64 {
35     x / 100
36 }
37 
38 #[cfg_attr(feature = "no-panic", inline)]
pow5_factor(mut value: u64) -> u3239 fn pow5_factor(mut value: u64) -> u32 {
40     let mut count = 0u32;
41     loop {
42         debug_assert!(value != 0);
43         let q = div5(value);
44         let r = (value as u32).wrapping_sub(5u32.wrapping_mul(q as u32));
45         if r != 0 {
46             break;
47         }
48         value = q;
49         count += 1;
50     }
51     count
52 }
53 
54 // Returns true if value is divisible by 5^p.
55 #[cfg_attr(feature = "no-panic", inline)]
multiple_of_power_of_5(value: u64, p: u32) -> bool56 pub fn multiple_of_power_of_5(value: u64, p: u32) -> bool {
57     // I tried a case distinction on p, but there was no performance difference.
58     pow5_factor(value) >= p
59 }
60 
61 // Returns true if value is divisible by 2^p.
62 #[cfg_attr(feature = "no-panic", inline)]
multiple_of_power_of_2(value: u64, p: u32) -> bool63 pub fn multiple_of_power_of_2(value: u64, p: u32) -> bool {
64     debug_assert!(value != 0);
65     debug_assert!(p < 64);
66     // __builtin_ctzll doesn't appear to be faster here.
67     (value & ((1u64 << p) - 1)) == 0
68 }
69 
70 #[cfg_attr(feature = "no-panic", inline)]
mul_shift_64(m: u64, mul: &(u64, u64), j: u32) -> u6471 pub fn mul_shift_64(m: u64, mul: &(u64, u64), j: u32) -> u64 {
72     let b0 = m as u128 * mul.0 as u128;
73     let b2 = m as u128 * mul.1 as u128;
74     (((b0 >> 64) + b2) >> (j - 64)) as u64
75 }
76 
77 #[cfg_attr(feature = "no-panic", inline)]
mul_shift_all_64( m: u64, mul: &(u64, u64), j: u32, vp: *mut u64, vm: *mut u64, mm_shift: u32, ) -> u6478 pub unsafe fn mul_shift_all_64(
79     m: u64,
80     mul: &(u64, u64),
81     j: u32,
82     vp: *mut u64,
83     vm: *mut u64,
84     mm_shift: u32,
85 ) -> u64 {
86     ptr::write(vp, mul_shift_64(4 * m + 2, mul, j));
87     ptr::write(vm, mul_shift_64(4 * m - 1 - mm_shift as u64, mul, j));
88     mul_shift_64(4 * m, mul, j)
89 }
90