1 /**
2 Some auxiliar math funtions
3 */
4 module zmath.aux;
5 
6 import std.math;
7 
8 enum M_1_180 = 1 / 180.0L; /// Inverse of 180
9 
10 /**
11  * Clamps a float point between -1.0 and +1.0
12  * Params:
13  *	x = Float point number to clamp
14  * Returns A flot point number clamped between -1.0 and 1.0
15  */
16 @safe @nogc T clamp(T = float)(in T x) pure nothrow if (__traits(isFloating, T)) {
17   if (x > 1.0L)
18     return 1.0L;
19   if (x < -1.0L)
20     return -1.0L;
21   return x;
22 }
23 
24 unittest {
25   const double d = 25;
26   assert(clamp(d) == 1.0);
27   const real r = -25;
28   assert(clamp(r) == -1.0);
29   const float f = -0.5;
30   assert(clamp(f) == -0.5);
31 }
32 
33 /**
34  * Converts angles in degrees to radians
35  * Params:
36  * x = Angle in grades
37  * Returns angle in radians
38  */
39 @safe @nogc T toRadians(T = float)(in T x) pure nothrow if (__traits(isFloating, T)) {
40   return x * PI * M_1_180;
41 }
42 
43 unittest {
44   assert(approxEqual(toRadians(180.0), PI));
45   assert(approxEqual(toRadians(360.0), PI * 2.0));
46 }
47 
48 /**
49  * Converts angles in radians to degrees
50  * Params:
51  * x = Angle in radians
52  * REturns angle in grades
53  */
54 @safe @nogc T toDegrees(T = float)(in T x) pure nothrow if (__traits(isFloating, T)) {
55   return x * 180.0L * M_1_PI; // x * 180 / PI
56 }
57 
58 unittest {
59   assert(approxEqual(toDegrees(PI), 180.0));
60 }
61 
62 /**
63  * Compare two float point numbers with assuming that are equal if are in range
64  * of maxAbsDiff
65  * Params:
66  * a = A float point number
67  * b = Other float point
68  * maxRelDiff = Max relative difference
69  * maxAbsDiff = Max absoulte difference
70  * Returns If _a are aproximated equal that _b, returns 0. Otherwise, if _a > _b,
71  * returns 1 and if _a < _b , returns -1;
72  */
73 int cmpFloat(T = float, U = float)(in T a, in U b, T maxRelDiff = 1e-2, T maxAbsDiff = 1e-5) {
74   static assert(__traits(isFloating, T), "'a' must be a float point number");
75   static assert(__traits(isScalar, U), "'b' must be a number type");
76 
77   if (approxEqual(a, b, maxRelDiff, maxAbsDiff))
78     return 0;
79   if (a < b)
80     return -1;
81   return 1;
82 }
83 
84 unittest {
85   assert(cmpFloat(3.0, 0.0) == 1);
86   assert(cmpFloat(0.0, 3) == -1);
87   assert(cmpFloat(0.0, 0.00001) == 0);
88 }