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