1use std::char::from_digit;
2use std::cmp::Ordering;
3use std::error::Error;
4use std::fmt;
5use std::hash::{Hash, Hasher};
6use std::marker::PhantomData;
7use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
8use std::str::FromStr;
9
10use num_bigint::BigUint;
20use num_traits::identities::{One, Zero};
21use num_traits::ToPrimitive;
22
23pub mod types;
24
25
26const U64_MAX_DIGITS: u64 = 19u64;
28const U64_MAX_DECIMAL: u64 = 10_000_000_000_000_000_000u64;
32
33pub trait FixedScale {
36 const SCALE: u64;
37}
38
39pub trait RoundingMode {
41 fn round(int_value: BigUint, carrier: u8) -> BigUint;
43}
44
45pub struct RoundHalfUp {}
47impl RoundingMode for RoundHalfUp{
48 #[inline]
49 fn round(int_value: BigUint, carrier: u8) -> BigUint {
50 int_value + if carrier >= 5u8 { 1u64 } else { 0u64 }
51 }
52}
53
54pub struct RoundDown {}
56impl RoundingMode for RoundDown {
57 #[inline]
58 fn round(int_value: BigUint, _: u8) -> BigUint {
59 int_value
60 }
61}
62
63
64
65#[derive(Debug, PartialEq, Eq)]
68pub struct ParseError(String);
69
70impl fmt::Display for ParseError {
71 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
72 write!(f, "{}: {}", self.description(), self.0)
73 }
74}
75
76impl Error for ParseError {
77 fn description(&self) -> &str {
78 "Failed to parse fixed point decimal:"
79 }
80
81 fn cause(&self) -> Option<&dyn Error> {
82 None
83 }
84}
85
86#[derive(Clone)]
93pub struct FixedUnsigned<S>
94 where S: FixedScale
95{
96 int_value: BigUint,
97 scale: PhantomData<S>
98}
99
100impl<S> FixedUnsigned<S>
101 where S: FixedScale
102{
103 fn new(int_value: BigUint) -> Self {
104 Self { int_value, scale: PhantomData }
105 }
106
107 fn scale_up(mut int_value: BigUint, mut scale: u64) -> BigUint {
109 while scale >= U64_MAX_DIGITS {
110 int_value *= U64_MAX_DECIMAL;
111 scale -= U64_MAX_DIGITS;
112 }
113 while scale > 0u64 {
114 int_value *= 10u64;
115 scale -= 1;
116 }
117 int_value
118 }
119
120 fn scale_down<R: RoundingMode>(mut int_value: BigUint, mut scale: u64) -> BigUint {
122 while scale >= U64_MAX_DIGITS {
124 int_value /= U64_MAX_DECIMAL;
125 scale -= U64_MAX_DIGITS;
126 }
127 while scale > 1u64 {
129 int_value /= 10u64;
130 scale -= 1;
131 }
132 if scale > 0u64 {
134 let carrier = (&int_value % 10u64).to_u8().unwrap();
136 int_value /= 10u64;
137 int_value = R::round(int_value, carrier);
138 }
139 int_value
140 }
141
142 pub fn int_part(&self) -> BigUint {
144 Self::scale_down::<RoundDown>(self.int_value.clone(), S::SCALE)
145 }
146
147 pub fn frac_part(&self) -> BigUint {
148 unimplemented!();
149 }
150
151 pub fn scale(&self) -> u64 {
156 S::SCALE
157 }
158
159 pub fn from_bytes_be(bytes: &[u8]) -> Self {
160 Self::new(BigUint::from_bytes_be(bytes))
161 }
162
163 pub fn from_bytes_le(bytes: &[u8]) -> Self {
164 Self::new(BigUint::from_bytes_be(bytes))
165 }
166
167 pub fn to_bytes_be(&self) -> Vec<u8> {
168 self.int_value.to_bytes_be()
169 }
170
171 pub fn to_bytes_le(&self) -> Vec<u8> {
172 self.int_value.to_bytes_le()
173 }
174
175 pub fn to_radix_string(&self, radix: u8, uppercase: bool) -> String {
181 if radix == 0 || radix > 36 {
182 panic!("Radix too large: {}", radix);
183 }
184 let digits = self.int_value.to_radix_be(u32::from(radix));
185 let mut string: String = String::new();
186 let decimal_place = digits.len().checked_sub(S::SCALE as usize);
187 if let Some(0) = decimal_place {
188 string.push('0');
189 }
190 for (i, d) in digits.iter().enumerate() {
191 match decimal_place {
192 Some(dp) if dp == i => string.push('.'),
193 _ => ()
194 }
195 let c = from_digit(u32::from(*d), u32::from(radix)).unwrap();
197 string.push(if uppercase { c.to_ascii_uppercase() } else { c }); }
199 string
200 }
201
202 pub fn from_radix_string(string: &str, radix: u8) -> Result<Self, ParseError> {
210 if radix == 0 || radix > 36 {
211 panic!("Radix too large: {}", radix);
212 }
213 let mut digits: Vec<u8> = Vec::new();
214 let mut decimal_place = None;
215 for (i, c) in string.chars().enumerate() {
216 if c == '.' {
217 if decimal_place.is_some() {
218 return Err(ParseError(String::from(string)))
219 }
220 decimal_place = Some(i)
221 }
222 else {
223 digits.push(c.to_digit(u32::from(radix)).unwrap() as u8)
224 }
225 }
226 if digits.is_empty() {
227 return Err(ParseError(String::from(string)));
228 }
229 let int_value = BigUint::from_radix_be(digits.as_slice(), u32::from(radix))
231 .ok_or_else(|| ParseError(String::from(string)))?;
232 let scale = decimal_place.map(|p| string.len() - p - 1).unwrap_or(0) as u64;
235 let int_value = if scale < S::SCALE {
237 Self::scale_up(int_value, S::SCALE - scale)
238 }
239 else if scale > S::SCALE {
240 Self::scale_down::<RoundDown>(int_value, scale - S::SCALE)
241 }
242 else {
243 int_value
244 };
245 Ok(Self::new(int_value))
246 }
247
248 fn from_biguint(int_value: BigUint) -> Self {
251 Self::new(Self::scale_up(int_value, S::SCALE))
252 }
253
254 pub fn into_biguint(self) -> BigUint {
258 Self::scale_down::<RoundDown>(self.int_value, S::SCALE)
259 }
260
261 pub fn into_biguint_without_scale(self) -> BigUint {
262 self.int_value
263 }
264
265 pub fn bits(&self) -> usize {
266 self.int_value.bits()
267 }
268
269 pub fn bytes(&self) -> usize {
270 let bits = self.bits();
271 bits / 8 + if bits % 8 == 0 {0} else {1}
272 }
273
274 #[inline]
276 fn add(a: &BigUint, b: &BigUint) -> BigUint {
277 a + b
278 }
279
280 #[inline]
282 fn sub(a: &BigUint, b: &BigUint) -> BigUint {
283 a - b
284 }
285
286 #[inline]
288 fn mul(a: &BigUint, b: &BigUint) -> BigUint {
289 Self::scale_down::<RoundHalfUp>((a * b).clone(), S::SCALE)
290 }
291
292 #[inline]
294 fn div(a: &BigUint, b: &BigUint) -> BigUint {
295 Self::scale_down::<RoundHalfUp>(Self::scale_up(a.clone(), S::SCALE + 1u64) / b, 1u64)
297 }
298
299 pub fn into_scale<T: FixedScale, R: RoundingMode>(self) -> FixedUnsigned<T> {
301 FixedUnsigned::<T>::new(if S::SCALE < T::SCALE {
302 Self::scale_up(self.int_value,T::SCALE - S::SCALE)
303 }
304 else {
305 Self::scale_down::<R>(self.int_value, S::SCALE - T::SCALE)
306 })
307 }
308}
309
310impl<S> Add for FixedUnsigned<S>
311 where S: FixedScale
312{
313 type Output = Self;
314
315 fn add(self, rhs: FixedUnsigned<S>) -> Self::Output {
316 Self::new(Self::add(&(self.int_value), &(rhs.int_value)))
317 }
318}
319
320impl<'a, 'b, S> Add<&'b FixedUnsigned<S>> for &'a FixedUnsigned<S>
321 where S: FixedScale
322{
323 type Output = FixedUnsigned<S>;
324
325 fn add(self, rhs: &'b FixedUnsigned<S>) -> FixedUnsigned<S> {
326 FixedUnsigned::new(FixedUnsigned::<S>::add(&(self.int_value), &(rhs.int_value)))
327 }
328}
329
330impl<S> AddAssign for FixedUnsigned<S>
331 where S: FixedScale
332{
333 fn add_assign(&mut self, rhs: Self) {
334 self.int_value = FixedUnsigned::<S>::add(&(self.int_value), &(rhs.int_value))
335 }
336}
337
338impl<S> Sub for FixedUnsigned<S>
339 where S: FixedScale
340{
341 type Output = Self;
342
343 fn sub(self, rhs: FixedUnsigned<S>) -> Self::Output {
344 Self::new(Self::sub(&(self.int_value), &(rhs.int_value)))
345 }
346}
347
348impl<'a, 'b, S> Sub<&'b FixedUnsigned<S>> for &'a FixedUnsigned<S>
349 where S: FixedScale
350{
351 type Output = FixedUnsigned<S>;
352
353 fn sub(self, rhs: &'b FixedUnsigned<S>) -> FixedUnsigned<S> {
354 FixedUnsigned::new(FixedUnsigned::<S>::sub(&(self.int_value), &(rhs.int_value)))
355 }
356}
357
358impl<S> SubAssign for FixedUnsigned<S>
359 where S: FixedScale
360{
361 fn sub_assign(&mut self, rhs: Self) {
362 self.int_value = FixedUnsigned::<S>::sub(&(self.int_value), &(rhs.int_value))
363 }
364}
365
366impl<S> Mul for FixedUnsigned<S>
367 where S: FixedScale
368{
369 type Output = Self;
370
371 fn mul(self, rhs: FixedUnsigned<S>) -> Self::Output {
372 Self::new(Self::mul(&(self.int_value), &(rhs.int_value)))
373 }
374}
375
376impl<'a, 'b, S> Mul<&'b FixedUnsigned<S>> for &'a FixedUnsigned<S>
377 where S: FixedScale
378{
379 type Output = FixedUnsigned<S>;
380
381 fn mul(self, rhs: &'b FixedUnsigned<S>) -> FixedUnsigned<S> {
382 FixedUnsigned::new(FixedUnsigned::<S>::mul(&(self.int_value), &(rhs.int_value)))
383 }
384}
385
386impl<S> MulAssign for FixedUnsigned<S>
387 where S: FixedScale
388{
389 fn mul_assign(&mut self, rhs: Self) {
390 self.int_value = FixedUnsigned::<S>::mul(&(self.int_value), &(rhs.int_value))
391 }
392}
393
394impl<S> Div for FixedUnsigned<S>
395 where S: FixedScale
396{
397 type Output = Self;
398
399 fn div(self, rhs: FixedUnsigned<S>) -> Self::Output {
400 Self::new(Self::div(&(self.int_value), &(rhs.int_value)))
401 }
402}
403
404impl<'a, 'b, S> Div<&'b FixedUnsigned<S>> for &'a FixedUnsigned<S>
405 where S: FixedScale
406{
407 type Output = FixedUnsigned<S>;
408
409 fn div(self, rhs: &'b FixedUnsigned<S>) -> FixedUnsigned<S> {
410 FixedUnsigned::new(FixedUnsigned::<S>::div(&(self.int_value), &(rhs.int_value)))
411 }
412}
413
414impl<S> DivAssign for FixedUnsigned<S>
415 where S: FixedScale
416{
417 fn div_assign(&mut self, rhs: Self) {
418 self.int_value = FixedUnsigned::<S>::div(&(self.int_value), &(rhs.int_value))
419 }
420}
421
422impl<S> PartialEq for FixedUnsigned<S>
423 where S: FixedScale
424{
425 fn eq(&self, other: &Self) -> bool {
426 self.int_value.eq(&other.int_value)
427 }
428}
429
430impl<S> Hash for FixedUnsigned<S>
431 where S: FixedScale
432{
433 fn hash<H: Hasher>(&self, state: &mut H) {
434 self.int_value.hash(state)
435 }
436}
437
438impl<S> Eq for FixedUnsigned<S>
439 where S: FixedScale
440{
441
442}
443
444impl<S> PartialOrd for FixedUnsigned<S>
445 where S: FixedScale
446{
447 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
448 self.int_value.partial_cmp(&other.int_value)
449 }
450}
451
452impl<S> Ord for FixedUnsigned<S>
453 where S: FixedScale
454{
455 fn cmp(&self, other: &Self) -> Ordering {
456 self.int_value.cmp(&other.int_value)
457 }
458}
459
460impl<S> FromStr for FixedUnsigned<S>
473 where S: FixedScale
474{
475 type Err = ParseError;
476
477 fn from_str(s: &str) -> Result<Self, Self::Err> {
478 Self::from_radix_string(s, 10)
479 }
480}
481
482impl<S> fmt::Debug for FixedUnsigned<S>
483 where S: FixedScale
484{
485 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
486 write!(f, "FixedUnsigned({}, scale={})", self.to_radix_string(10, false), S::SCALE)
487 }
488}
489
490impl<S> fmt::Display for FixedUnsigned<S>
491 where S: FixedScale
492{
493 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
494 write!(f, "{}", self.to_radix_string(10, false))
495 }
496}
497
498impl<S> From<BigUint> for FixedUnsigned<S>
499 where S: FixedScale
500{
501 fn from(int_value: BigUint) -> Self {
502 Self::from_biguint(int_value)
503 }
504}
505
506impl<S: FixedScale> From<u64> for FixedUnsigned<S> {
519 fn from(x: u64) -> Self {
520 Self::from_biguint(BigUint::from(x))
521 }
522}
523
524impl<S: FixedScale> From<u32> for FixedUnsigned<S> {
525 fn from(x: u32) -> Self {
526 Self::from_biguint(BigUint::from(x))
527 }
528}
529
530impl<S: FixedScale> From<u16> for FixedUnsigned<S> {
531 fn from(x: u16) -> Self {
532 Self::from_biguint(BigUint::from(x))
533 }
534}
535
536impl<S: FixedScale> From<u8> for FixedUnsigned<S> {
537 fn from(x: u8) -> Self {
538 Self::from_biguint(BigUint::from(x))
539 }
540}
541
542impl<S> Zero for FixedUnsigned<S>
543 where S: FixedScale
544{
545 fn zero() -> Self {
546 Self::new(BigUint::zero())
547 }
548
549 fn is_zero(&self) -> bool {
550 self.int_value.is_zero()
551 }
552}
553
554impl<S> One for FixedUnsigned<S>
555 where S: FixedScale
556{
557 fn one() -> Self {
558 Self::from(1u64)
559 }
560}
561
562impl<S> Default for FixedUnsigned<S>
563 where S: FixedScale
564{
565 fn default() -> Self {
566 Self::zero()
567 }
568}
569
570impl<S: FixedScale> From<f64> for FixedUnsigned<S> {
572 fn from(x: f64) -> Self {
573 Self::from_str(&format!("{:.16}", x)).unwrap()
576 }
577}