af_core/math/
float.rs

1// Copyright © 2021 Alexandra Frydl
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7use crate::prelude::*;
8
9/// An extension trait for `f32` and `f64`.
10pub trait FloatExt {
11  /// Rounds the number up to a specified number of decimal places.
12  ///
13  /// Calling `ceil_to_places(0)` is equivalent to calling `ceil()`.
14  fn ceil_to_places(self, places: usize) -> Self;
15
16  /// Rounds the number down to a specified number of decimal places.
17  ///
18  /// Calling `floor_to_places(0)` is equivalent to calling `floor()`.
19  fn floor_to_places(self, places: usize) -> Self;
20
21  /// Rounds the number to a specified number of decimal places.
22  ///
23  /// Calling `round_to_places(0)` is equivalent to calling `round()`.
24  fn round_to_places(self, places: usize) -> Self;
25}
26
27/// Returns a multiplier representing a number of decimal places.
28fn places_f32(places: usize) -> f32 {
29  assert!(places < i32::MAX as usize, "`places` must be less than {}", i32::MAX);
30
31  match places {
32    0 => 1.0,
33    1 => 10.0,
34    2 => 100.0,
35    3 => 1000.0,
36    n => 10.0f32.powi(n as i32),
37  }
38}
39
40/// Returns a multiplier representing a number of decimal places.
41fn places_f64(places: usize) -> f64 {
42  assert!(places < i32::MAX as usize, "`places` must be less than {}", i32::MAX);
43
44  match places {
45    0 => 1.0,
46    1 => 10.0,
47    2 => 100.0,
48    3 => 1000.0,
49    n => 10.0f64.powi(n as i32),
50  }
51}
52
53impl FloatExt for f32 {
54  fn ceil_to_places(self, places: usize) -> Self {
55    let mult = places_f32(places);
56
57    (self * mult).ceil() / mult
58  }
59
60  fn floor_to_places(self, places: usize) -> Self {
61    let mult = places_f32(places);
62
63    (self * mult).floor() / mult
64  }
65
66  fn round_to_places(self, places: usize) -> Self {
67    let mult = places_f32(places);
68
69    (self * mult).round() / mult
70  }
71}
72
73impl FloatExt for f64 {
74  fn ceil_to_places(self, places: usize) -> Self {
75    let mult = places_f64(places);
76
77    (self * mult).ceil() / mult
78  }
79
80  fn floor_to_places(self, places: usize) -> Self {
81    let mult = places_f64(places);
82
83    (self * mult).floor() / mult
84  }
85
86  fn round_to_places(self, places: usize) -> Self {
87    let mult = places_f64(places);
88
89    (self * mult).round() / mult
90  }
91}