soroban_fixed_point_math/
u64.rs1use crate::fixed_point::FixedPoint;
2
3impl FixedPoint for u64 {
4 fn fixed_mul_floor(self, y: u64, denominator: u64) -> Option<u64> {
5 mul_div_floor(self, y, denominator)
6 }
7
8 fn fixed_mul_ceil(self, y: u64, denominator: u64) -> Option<u64> {
9 mul_div_ceil(self, y, denominator)
10 }
11
12 fn fixed_div_floor(self, y: u64, denominator: u64) -> Option<u64> {
13 mul_div_floor(self, denominator, y)
14 }
15
16 fn fixed_div_ceil(self, y: u64, denominator: u64) -> Option<u64> {
17 mul_div_ceil(self, denominator, y)
18 }
19}
20
21fn mul_div_floor(x: u64, y: u64, z: u64) -> Option<u64> {
23 return match x.checked_mul(y) {
24 Some(r) => r.checked_div(z),
25 None => {
26 let res_u128 = crate::u128::mul_div_floor(x as u128, y as u128, z as u128)?;
27 if res_u128 > u64::MAX as u128 {
28 return None;
29 }
30 Some(res_u128 as u64)
31 }
32 };
33}
34
35fn mul_div_ceil(x: u64, y: u64, z: u64) -> Option<u64> {
37 return match x.checked_mul(y) {
38 Some(r) => {
39 let remainder = r.checked_rem_euclid(z)?;
40 (r / z).checked_add(if remainder > 0 { 1 } else { 0 })
42 }
43 None => {
44 let res_u128 = crate::u128::mul_div_ceil(x as u128, y as u128, z as u128)?;
45 if res_u128 > u64::MAX as u128 {
46 return None;
47 }
48 Some(res_u128 as u64)
49 }
50 };
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56
57 #[test]
60 fn test_fixed_mul_floor_rounds_down() {
61 let x: u64 = 1_5391283;
62 let y: u64 = 314_1592653;
63 let denominator: u64 = 1_0000001;
64
65 let result = x.fixed_mul_floor(y, denominator).unwrap();
66
67 assert_eq!(result, 483_5313675)
68 }
69
70 #[test]
71 fn test_fixed_mul_floor_large_number() {
72 let x: u64 = 18_446_744_073;
73 let y: u64 = 1_000_000_000;
74 let denominator: u64 = 1_000_000_000;
75
76 let result = x.fixed_mul_floor(y, denominator).unwrap();
77
78 assert_eq!(result, 18_446_744_073)
79 }
80
81 #[test]
82 fn test_fixed_mul_floor_phantom_overflow_uses_u128() {
83 let x: u64 = 18_446_744_073;
84 let y: u64 = 2_000_000_000;
85 let denominator: u64 = 1_000_000_000;
86
87 let result = x.fixed_mul_floor(y, denominator).unwrap();
88
89 assert_eq!(result, 36_893_488_146);
90 }
91
92 #[test]
93 fn test_fixed_mul_floor_result_overflow() {
94 let x: u64 = 18_446_744_073_000_000_000;
95 let y: u64 = 2_000_000_000;
96 let denominator: u64 = 1_000_000_000;
97
98 let result = x.fixed_mul_floor(y, denominator);
99
100 assert_eq!(result, None);
101 }
102
103 #[test]
106 fn test_fixed_mul_ceil_rounds_up() {
107 let x: u64 = 1_5391283;
108 let y: u64 = 314_1592653;
109 let denominator: u64 = 1_0000001;
110
111 let result = x.fixed_mul_ceil(y, denominator).unwrap();
112
113 assert_eq!(result, 483_5313676)
114 }
115
116 #[test]
117 fn test_fixed_mul_ceil_large_number() {
118 let x: u64 = 18_446_744_073;
119 let y: u64 = 1_000_000_000;
120 let denominator: u64 = 1_000_000_000;
121
122 let result = x.fixed_mul_ceil(y, denominator).unwrap();
123
124 assert_eq!(result, 18_446_744_073)
125 }
126
127 #[test]
128 fn test_fixed_mul_ceil_phantom_overflow_uses_u128() {
129 let x: u64 = 18_446_744_073;
130 let y: u64 = 2_000_000_000;
131 let denominator: u64 = 1_000_000_000;
132
133 let result = x.fixed_mul_ceil(y, denominator).unwrap();
134
135 assert_eq!(result, 36_893_488_146);
136 }
137
138 #[test]
139 fn test_fixed_mul_ceil_result_overflow() {
140 let x: u64 = 18_446_744_073_000_000_000;
141 let y: u64 = 2_000_000_000;
142 let denominator: u64 = 1_000_000_000;
143
144 let result = x.fixed_mul_ceil(y, denominator);
145
146 assert_eq!(result, None);
147 }
148
149 #[test]
152 fn test_fixed_div_floor_rounds_down() {
153 let x: u64 = 314_1592653;
154 let y: u64 = 1_5391280;
155 let denominator: u64 = 1_0000000;
156
157 let result = x.fixed_div_floor(y, denominator).unwrap();
158
159 assert_eq!(result, 204_1150997)
160 }
161
162 #[test]
163 fn test_fixed_div_floor_large_number() {
164 let x: u64 = 18_446_744_073;
165 let y: u64 = 1_000_000_000;
166 let denominator: u64 = 1_000_000_000;
167
168 let result = x.fixed_div_floor(y, denominator).unwrap();
169
170 assert_eq!(result, 18_446_744_073)
171 }
172
173 #[test]
174 fn test_fixed_div_floor_phantom_overflow_uses_u128() {
175 let x: u64 = 18_446_744_073;
176 let y: u64 = 2_000_000_000;
177 let denominator: u64 = 1_000_000_000;
178
179 let result = x.fixed_div_floor(y, denominator).unwrap();
180
181 assert_eq!(result, 9_223_372_036);
182 }
183
184 #[test]
185 fn test_fixed_div_floor_result_overflow() {
186 let x: u64 = 18_446_744_073_000_000_000;
187 let y: u64 = 2_000_000_000;
188 let denominator: u64 = 4_000_000_000;
189
190 let result = x.fixed_div_floor(y, denominator);
191
192 assert_eq!(result, None);
193 }
194
195 #[test]
198 fn test_fixed_div_ceil_rounds_up() {
199 let x: u64 = 314_1592653;
200 let y: u64 = 1_5391280;
201 let denominator: u64 = 1_0000000;
202
203 let result = x.fixed_div_ceil(y, denominator).unwrap();
204
205 assert_eq!(result, 204_1150998)
206 }
207
208 #[test]
209 fn test_fixed_div_ceil_large_number() {
210 let x: u64 = 18_446_744_073;
211 let y: u64 = 1_000_000_000;
212 let denominator: u64 = 1_000_000_000;
213
214 let result = x.fixed_div_ceil(y, denominator).unwrap();
215
216 assert_eq!(result, 18_446_744_073)
217 }
218
219 #[test]
220 fn test_fixed_div_ceil_phantom_overflow_uses_u128() {
221 let x: u64 = 18_446_744_073;
222 let y: u64 = 2_000_000_000;
223 let denominator: u64 = 1_000_000_000;
224
225 let result = x.fixed_div_ceil(y, denominator).unwrap();
226
227 assert_eq!(result, 9_223_372_037);
228 }
229
230 #[test]
231 fn test_fixed_div_ceil_result_overflow() {
232 let x: u64 = 18_446_744_073_000_000_000;
233 let y: u64 = 2_000_000_000;
234 let denominator: u64 = 4_000_000_000;
235
236 let result = x.fixed_div_ceil(y, denominator);
237
238 assert_eq!(result, None);
239 }
240}