1 /++
2 Functions and templates that do numeric calculations or other manipulation,
3 in some way or another.
4
5 Example:
6 ---
7 immutable width = 15.getMultipleOf(4);
8 assert(width == 16);
9 immutable width2 = 16.getMultipleOf(4, alwaysOneUp: true);
10 assert(width2 == 20);
11 ---
12
13 Copyright: [JR](https://github.com/zorael)
14 License: [Boost Software License 1.0](https://www.boost.org/users/license.html)
15
16 Authors:
17 [JR](https://github.com/zorael)
18 +/
19 module lu.numeric;
20
21 private:
22
23 public:
24
25 @safe:
26
27
28 // getMultipleOf
29 /++
30 Given a number, calculate the largest multiple of `n` needed to reach that number.
31
32 It rounds up, and if supplied `alwaysOneUp: true` it will always overshoot.
33 This is good for when calculating format pattern widths.
34
35 Example:
36 ---
37 immutable width = 15.getMultipleOf(4);
38 assert(width == 16);
39 immutable width2 = 16.getMultipleOf(4, alwaysOneUp: true);
40 assert(width2 == 20);
41 ---
42
43 Params:
44 num = Number to reach.
45 n = Base value to find a multiplier for.
46 alwaysOneUp = Whether or not to always overshoot.
47
48 Returns:
49 The multiple of `n` that reaches and possibly overshoots `num`.
50 +/
51 auto getMultipleOf(Number)
52 (const Number num,
53 const int n,
54 const bool alwaysOneUp = false) pure nothrow @nogc
55 in ((n > 0), "Cannot get multiple of 0 or negatives")
56 in ((num >= 0), "Cannot get multiples for a negative number")
57 {
58 if (num == 0) return 0;
59
60 if (num == n)
61 {
62 return alwaysOneUp ? (n + 1) : n;
63 }
64
65 immutable frac = (num / double(n));
66 immutable floor_ = cast(uint)frac;
67 immutable mod = alwaysOneUp ? (floor_ + 1) : ((floor_ == frac) ? floor_ : (floor_ + 1));
68
69 return (mod * n);
70 }
71
72 ///
73 unittest
74 {
75 import std.conv : text;
76
77 immutable n1 = 15.getMultipleOf(4);
78 assert((n1 == 16), n1.text);
79
80 immutable n2 = 16.getMultipleOf(4, alwaysOneUp: true);
81 assert((n2 == 20), n2.text);
82
83 immutable n3 = 16.getMultipleOf(4);
84 assert((n3 == 16), n3.text);
85 immutable n4 = 0.getMultipleOf(5);
86 assert((n4 == 0), n4.text);
87
88 immutable n5 = 1.getMultipleOf(1);
89 assert((n5 == 1), n5.text);
90
91 immutable n6 = 1.getMultipleOf(1, alwaysOneUp: true);
92 assert((n6 == 2), n6.text);
93
94 immutable n7 = 5.getMultipleOf(5, alwaysOneUp: true);
95 assert((n7 == 6), n7.text);
96
97 immutable n8 = 5L.getMultipleOf(5L, alwaysOneUp: true);
98 assert((n8 == 6L), n8.text);
99
100 immutable n9 = 5UL.getMultipleOf(5UL, alwaysOneUp: false);
101 assert((n9 == 5UL), n9.text);
102
103 immutable n10 = (5.0).getMultipleOf(5UL, alwaysOneUp: true);
104 assert((n10 == (6.0)), n10.text);
105 }