1 module toml_foolery.decode.types.floating_point;
2 
3 import std.algorithm : filter;
4 import std.conv : to;
5 
6 version (unittest)
7 {
8     import exceeds_expectations;
9     import std.math : isNaN;
10 }
11 
12 
13 package(toml_foolery.decode) real parseTomlFloat(string value)
14 {
15     if (value[$-3 .. $] == "inf")
16     {
17         if (value[0] == '-')
18         {
19             return -real.infinity;
20         }
21 
22         return real.infinity;
23     }
24 
25     return value.filter!(e => e != '_').to!real;
26 }
27 
28 @("Fractional — Basic")
29 unittest
30 {
31     expect(parseTomlFloat("3.14159")).toApproximatelyEqual(3.14159);
32 }
33 
34 @("Fractional — With +")
35 unittest
36 {
37     expect(parseTomlFloat("+1.0")).toApproximatelyEqual(1.0);
38 }
39 
40 @("Fractional — Negative")
41 unittest
42 {
43     expect(parseTomlFloat("-1.0")).toApproximatelyEqual(-1.0);
44 }
45 
46 @("Exponential — Basic")
47 unittest
48 {
49     expect(parseTomlFloat("2e7")).toApproximatelyEqual(20_000_000.0);
50 }
51 
52 @("Exponential — With +")
53 unittest
54 {
55     expect(parseTomlFloat("3e+05")).toApproximatelyEqual(300_000.0);
56 }
57 
58 @("Exponential — Negative base/exponent/both")
59 unittest
60 {
61     expect(parseTomlFloat("-2e7")).toApproximatelyEqual(-20_000_000.0);
62     expect(parseTomlFloat("2e-7")).toApproximatelyEqual(0.0_000_002);
63     expect(parseTomlFloat("-2e-7")).toApproximatelyEqual(-0.0_000_002);
64 }
65 
66 @("Fraxponential")
67 unittest
68 {
69     expect(parseTomlFloat("-3.14159e-03")).toApproximatelyEqual(-0.003_141_59);
70 }
71 
72 @("NaN")
73 unittest
74 {
75     assert(parseTomlFloat("nan").isNaN, "Expected NaN, received: " ~ parseTomlFloat("nan").to!string);
76     assert(parseTomlFloat("+nan").isNaN, "Expected NaN, received: " ~ parseTomlFloat("+nan").to!string);
77     assert(parseTomlFloat("-nan").isNaN, "Expected NaN, received: " ~ parseTomlFloat("-nan").to!string);
78 }
79 
80 @("Infinity")
81 unittest
82 {
83     expect(parseTomlFloat("inf")).toEqual(real.infinity);
84     expect(parseTomlFloat("+inf")).toEqual(real.infinity);
85     expect(parseTomlFloat("-inf")).toEqual(-real.infinity);
86 }
87 
88 @("Underscores")
89 unittest
90 {
91     expect(parseTomlFloat("-3.1_41_59e-0_3")).toApproximatelyEqual(-0.003_141_59);
92 }