1 module fixedpoint.arithmetic;
2 import std.conv : to;
3 import fixedpoint.fixed : Fixed;
4 
5 /// Before the operation the arguments are casted to the specified type
6 T addTo(T, int a, V, int b, U)(Fixed!(a, V) lhs, Fixed!(b, U) rhs)
7 {
8     static if (a >= b)
9     {
10         return (lhs.value.to!T + rhs.value.to!T * 10 ^^ (a - b)) / lhs.factor;
11     }
12     else
13     {
14         return (lhs.value.to!T * 10 ^^ (b - a) + rhs.value.to!T) / rhs.factor;
15     }
16 }
17 
18 T subTo(T, int a, V, int b, U)(Fixed!(a, V) lhs, Fixed!(b, U) rhs)
19 {
20     static if (a >= b)
21     {
22         return (lhs.value.to!T - rhs.value.to!T * 10 ^^ (a - b)) / lhs.factor;
23     }
24     else
25     {
26         return (lhs.value.to!T * 10 ^^ (b - a) - rhs.value.to!T) / rhs.factor;
27     }
28 }
29 
30 T mulTo(T, int a, V, int b, U)(Fixed!(a, V) lhs, Fixed!(b, U) rhs)
31 {
32     return (lhs.value.to!T * rhs.value.to!T) / (lhs.factor * rhs.factor);
33 }
34 
35 T divTo(T, int a, V, int b, U)(Fixed!(a, V) lhs, Fixed!(b, U) rhs)
36 {
37     static if (a >= b)
38     {
39         return (lhs.value.to!T / rhs.value.to!T) / 10 ^^ (a - b);
40     }
41     else
42     {
43         return (lhs.value.to!T / rhs.value.to!T) * 10 ^^ (b - a);
44     }
45 }
46 
47 unittest
48 {
49     import std.stdio : writeln;
50     import fixedpoint.fixed : Fixed;
51     import std.math : isClose;
52 
53     auto op1 = Fixed!2("1.11");
54     auto op2 = Fixed!2("1.11");
55     auto op3 = Fixed!3("1.111");
56     assert(isClose(addTo!double(op1, op2), 2.22));
57     assert(isClose(subTo!double(op1, op2), 0.0));
58     assert(isClose(mulTo!double(op1, op2), 1.2321));
59     assert(isClose(divTo!double(op1, op2), 1.0));
60     assert(isClose(op1.addTo!double(op2), 2.22));
61     assert(isClose(op1.subTo!double(op2), 0.0));
62     assert(isClose(op1.mulTo!double(op2), 1.2321));
63     assert(isClose(op1.divTo!double(op2), 1.0));
64     assert(isClose(addTo!double(op1, op3), 2.221));
65     assert(isClose(subTo!double(op1, op3), -0.001));
66     assert(isClose(mulTo!double(op1, op3), 1.23321));
67     assert(isClose(divTo!double(op1, op3), 0.99909990999));
68     assert(isClose(addTo!double(op3, op1), 2.221));
69     assert(isClose(subTo!double(op3, op1), 0.001));
70     assert(isClose(mulTo!double(op3, op1), 1.23321));
71     assert(isClose(divTo!double(op3, op1), 1.0009009009));
72 }