1use std::convert::TryInto;
2
3pub const FP_32_ONE: u64 = 1 << 32;
4
5pub fn fp32_div(a: u64, b_fp32: u64) -> Option<u64> {
7 ((a as u128) << 32)
8 .checked_div(b_fp32 as u128)
9 .and_then(|x| x.try_into().ok())
10}
11
12pub fn fp32_mul_floor(a: u64, b_fp32: u64) -> Option<u64> {
14 (a as u128)
15 .checked_mul(b_fp32 as u128)
16 .and_then(|x| (x >> 32).try_into().ok())
17}
18
19pub fn fp32_mul_ceil(a: u64, b_fp32: u64) -> Option<u64> {
21 (a as u128)
22 .checked_mul(b_fp32 as u128)
23 .and_then(fp32_ceil_util)
24 .and_then(|x| (x >> 32).try_into().ok())
25}
26
27pub fn ifp32_div(a: i64, b_fp32: u64) -> Option<i64> {
29 ((a.unsigned_abs() as u128) << 32)
30 .checked_div(b_fp32 as u128)
31 .and_then(|x| x.try_into().ok())
32 .map(|x: i64| a.signum() * x)
33}
34
35pub fn ifp32_mul_floor(a: i64, b_fp32: u64) -> Option<i64> {
37 (a.unsigned_abs() as u128)
38 .checked_mul(b_fp32 as u128)
39 .and_then(|x| (x >> 32).try_into().ok())
40 .map(|x: i64| a.signum() * x)
41}
42
43pub fn ifp32_mul_ceil(a: i64, b_fp32: u64) -> Option<i64> {
45 (a.unsigned_abs() as u128)
46 .checked_mul(b_fp32 as u128)
47 .and_then(fp32_ceil_util)
48 .and_then(|x| (x >> 32).try_into().ok())
49 .map(|x: i64| a.signum() * x)
50}
51
52pub fn fp64_div(a: u64, b_fp64: u64) -> Option<u64> {
54 ((a as u128) << 64)
55 .checked_div(b_fp64 as u128)
56 .and_then(|x| x.try_into().ok())
57}
58
59pub fn fp64_mul_floor(a: u64, b_fp64: u64) -> Option<u64> {
61 (a as u128)
62 .checked_mul(b_fp64 as u128)
63 .map(|x| (x >> 64))
64 .and_then(|x| x.try_into().ok())
65}
66
67pub fn fp64_mul_ceil(a: u64, b_fp64: u64) -> Option<u64> {
69 (a as u128)
70 .checked_mul(b_fp64 as u128)
71 .map(|x| (x >> 64))
72 .and_then(fp64_ceil_util)
73 .and_then(|x| x.try_into().ok())
74}
75
76#[inline(always)]
77fn fp32_ceil_util(x_fp32: u128) -> Option<u128> {
78 let add_one = (!(x_fp32 as u32)).wrapping_add(1) as u128;
79 x_fp32.checked_add(add_one)
80}
81
82#[inline(always)]
83fn fp64_ceil_util(x_fp64: u128) -> Option<u128> {
84 let add_one = (!(x_fp64 as u64)).wrapping_add(1) as u128;
85 x_fp64.checked_add(add_one)
86}
87
88#[test]
89fn test() {
90 assert_eq!(fp32_div(124345678765454, 45654 << 32).unwrap(), 2723653541);
92 assert_eq!(fp32_div(124345678765454, 6787654 << 32).unwrap(), 18319389);
93
94 assert_eq!(
96 fp32_mul_floor(5676543, 6787654 << 32).unwrap(),
97 38530409800122
98 );
99 assert_eq!(fp32_mul_floor(12454, 45654 << 32).unwrap(), 568574916);
100 assert_eq!(fp32_mul_floor(5, 1 << 31).unwrap(), 2);
101 assert_eq!(
102 fp32_mul_ceil(5676543, 6787654 << 32).unwrap(),
103 38530409800122
104 );
105 assert_eq!(fp32_mul_ceil(12454, 45654 << 32).unwrap(), 568574916);
106 assert_eq!(fp32_mul_ceil(5, 1 << 31).unwrap(), 3);
107
108 assert_eq!(ifp32_div(124345678765454, 6787654 << 32).unwrap(), 18319389);
110 assert_eq!(ifp32_div(124345678765454, 45654 << 32).unwrap(), 2723653541);
111
112 assert_eq!(
114 ifp32_mul_floor(5676543, 6787654 << 32).unwrap(),
115 38530409800122
116 );
117 assert_eq!(ifp32_mul_floor(12454, 45654 << 32).unwrap(), 568574916);
118
119 assert_eq!(fp64_div(5676543, 345678909876543456).unwrap(), 302921968);
121 assert_eq!(fp64_div(12454, 345678909876543456).unwrap(), 664592);
122
123 assert_eq!(fp64_mul_floor(5676543, 345678909876543456).unwrap(), 106374);
125 assert_eq!(fp64_mul_floor(12454, 345678909876543456).unwrap(), 233)
126}