1 /** Computer Science Units.
2     Copyright: Per Nordlöw 2018-.
3     License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
4     Authors: $(WEB Per Nordlöw)
5  */
6 module nxt.csunits;
7 
8 /** Prefix Multipliers.
9     See_Also: http://searchstorage.techtarget.com/definition/Kilo-mega-giga-tera-peta-and-all-that
10 */
11 enum PrefixMultipliers
12 {
13     yocto = -24, // y
14     zepto = -21, // z
15     atto  = -18, // a
16     femto = -15, // f
17     pico  = -12, // p
18     nano  =  -9, // n
19     micro =  -6, // m
20     milli =  -3, // m
21     centi =  -2, // c
22     deci  =  -1, // d
23     none  =   0,
24     deka  =   1, // D
25     hecto =   2, // h
26     kilo  =   3, // k
27     mega  =   6, // M
28     giga  =   9, // G
29     tera  =  12, // T
30     peta  =  15, // P
31     exa   =  18, // E
32     zetta =  21, // Z
33     yotta =  24, // Y
34 }
35 
36 /** Bytes (Count) Unit. */
37 struct Bytes(T: ulong)
38 {
39     alias _value this;
40 
41     inout(T) value() @property inout @safe pure nothrow { return _value; }
42 
43     /**
44        See_Also: http://searchstorage.techtarget.com/definition/Kilo-mega-giga-tera-peta-and-all-that
45        See_Also: https://en.wikipedia.org/wiki/Exabyte
46      */
47     string toString(bool inBits = false) const @property @trusted /* pure nothrow */
48     {
49         // import core.internal.traits : Unqual;
50 
51         string name = void;
52         T val = void;
53         if (inBits)
54         {
55             name = "Bits"; // Unqual!(typeof(this)).stringof; // Unqual: "const(Bytes)" => "Bytes"
56             val = 8*_value;
57         }
58         else
59         {
60             name = "Bytes"; // Unqual!(typeof(this)).stringof; // Unqual: "const(Bytes)" => "Bytes"
61             val = _value;
62         }
63 
64         import std.conv : to;
65         if      (val < 1024^^1) { return to!string(val) ~ " " ~ name; }
66         else if (val < 1024^^2) { return to!string(cast(real)val / 1024^^1) ~ " kilo" ~ name; }
67         else if (val < 1024^^3) { return to!string(cast(real)val / 1024^^2) ~ " Mega" ~ name; }
68         else if (val < 1024^^4) { return to!string(cast(real)val / 1024^^3) ~ " Giga" ~ name; }
69         else if (val < 1024^^5) { return to!string(cast(real)val / 1024^^4) ~ " Tera" ~ name; }
70         else if (val < 1024^^6) { return to!string(cast(real)val / 1024^^5) ~ " Peta" ~ name; }
71         else if (val < 1024^^7) { return to!string(cast(real)val / 1024^^6) ~ " Exa" ~ name; }
72         else if (val < 1024^^8) { return to!string(cast(real)val / 1024^^7) ~ " Zetta" ~ name; }
73         else /* if (val < 1024^^9) */ { return to!string(cast(real)val / 1024^^8) ~ " Yotta" ~ name;
74         /* } else { */
75         /*     return to!string(val) ~ " " ~ name; */
76         }
77     }
78 
79     T opUnary(string op, string file = __FILE__, int line = __LINE__)()
80     {
81         T tmp = void; mixin("tmp = " ~ op ~ " _value;"); return tmp;
82     }
83 
84     T opBinary(string op, string file = __FILE__, int line = __LINE__)(T rhs)
85     {
86         T tmp = void; mixin("tmp = _value " ~ op ~ "rhs;"); return tmp;
87     }
88 
89     T opOpAssign(string op, string file = __FILE__, int line = __LINE__)(T rhs)
90     {
91         mixin("_value = _value " ~ op ~ "rhs;"); return _value;
92     }
93 
94     T opAssign(T rhs, string file = __FILE__, int line = __LINE__)
95     {
96         return _value = rhs;
97     }
98 
99 /* private: */
100     T _value;
101 }
102 
103 /** $(D Bytes) Instantiator. */
104 auto bytes(T)(T value) { return Bytes!T(value); }
105 
106 @safe pure nothrow @nogc unittest
107 {
108     immutable a = bytes(1);
109     immutable b = bytes(1);
110     immutable c = a + b;
111     assert(c == 2);
112     assert(1.bytes == 1);
113 }
114 
115 auto inPercent       (T)(T a) { return to!string(a * 1e2) ~ " \u0025"; }
116 auto inPerMille      (T)(T a) { return to!string(a * 1e3) ~ " \u2030"; }
117 auto inPerTenThousand(T)(T a) { return to!string(a * 1e4) ~ " \u2031"; }
118 auto inDegrees       (T)(T a) { return to!string(a      ) ~ " \u00B0"; }