1 module nxt.conv_itos;
2 
3 @safe:
4 
5 uint fastLog10(const uint val) @safe pure nothrow @nogc
6 {
7     // in order of probability
8     if (val < 1e1) return 0;
9     if (val < 1e2) return 1;
10     if (val < 1e3) return 2;
11     if (val < 1e4) return 3;
12     if (val < 1e5) return 4;
13     if (val < 1e6) return 5;
14     if (val < 1e7) return 6;
15     if (val < 1e8) return 7;
16     if (val < 1e9) return 8;
17     if (val < 1e10) return 9;
18     return 9;
19 }
20 
21 ///
22 @safe pure unittest
23 {
24     assert(fastLog10(1) == 0);
25     assert(fastLog10(9) == 0);
26     assert(fastLog10(11) == 1);
27     assert(fastLog10(99) == 1);
28     assert(fastLog10(111) == 2);
29     assert(fastLog10(999) == 2);
30     assert(fastLog10(1_111) == 3);
31     assert(fastLog10(9_999) == 3);
32     assert(fastLog10(11_111) == 4);
33     assert(fastLog10(99_999) == 4);
34     assert(fastLog10(999_999_999) == 8);
35     assert(fastLog10(1_000_000_000) == 9);
36     assert(fastLog10(uint.max) == 9);
37 }
38 
39 uint fastLog10(const ulong val) @safe pure nothrow @nogc
40 {
41     // in order of probability
42     if (val < cast(ulong)1e1) return 0;
43     if (val < cast(ulong)1e2) return 1;
44     if (val < cast(ulong)1e3) return 2;
45     if (val < cast(ulong)1e4) return 3;
46     if (val < cast(ulong)1e5) return 4;
47     if (val < cast(ulong)1e6) return 5;
48     if (val < cast(ulong)1e7) return 6;
49     if (val < cast(ulong)1e8) return 7;
50     if (val < cast(ulong)1e9) return 8;
51     if (val < cast(ulong)1e10) return 9;
52     if (val < cast(ulong)1e11) return 10;
53     if (val < cast(ulong)1e12) return 11;
54     if (val < cast(ulong)1e13) return 12;
55     if (val < cast(ulong)1e14) return 13;
56     if (val < cast(ulong)1e15) return 14;
57     if (val < cast(ulong)1e16) return 15;
58     if (val < cast(ulong)1e17) return 16;
59     if (val < cast(ulong)1e18) return 17;
60     if (val < cast(ulong)1e19) return 18;
61     if (val < cast(ulong)1e20) return 19;
62     return 19;
63 }
64 
65 ///
66 @safe pure unittest
67 {
68     assert(fastLog10(1UL) == 0);
69     assert(fastLog10(9UL) == 0);
70     assert(fastLog10(11UL) == 1);
71     assert(fastLog10(99UL) == 1);
72     // TODO: assert(fastLog10(111UL) == 2);
73     assert(fastLog10(999UL) == 2);
74     assert(fastLog10(1_111UL) == 3);
75     assert(fastLog10(9_999UL) == 3);
76     assert(fastLog10(11_111UL) == 4);
77     assert(fastLog10(99_999UL) == 4);
78     assert(fastLog10(999_999_999UL) == 8);
79     assert(fastLog10(1_000_000_000UL) == 9);
80     assert(fastLog10(10_000_000_000UL) == 10);
81     assert(fastLog10(100_000_000_000UL) == 11);
82     assert(fastLog10(1_000_000_000_000UL) == 12);
83     assert(fastLog10(10_000_000_000_000UL) == 13);
84     assert(fastLog10(100_000_000_000_000UL) == 14);
85     assert(fastLog10(1_000_000_000_000_000UL) == 15);
86     assert(fastLog10(10_000_000_000_000_000UL) == 16);
87     assert(fastLog10(100_000_000_000_000_000UL) == 17);
88     assert(fastLog10(1_000_000_000_000_000_000UL) == 18);
89     assert(fastLog10(10_000_000_000_000_000_000UL) == 19);
90 }
91 
92 /*@unique*/
93 private static immutable fastPow10tbl_32bit_unsigned = [
94     1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000,
95     ];
96 
97 /** Convert `val` to a `string` and return it.
98  */
99 string uint_to_string(const uint val) @trusted pure nothrow
100 {
101     immutable length = fastLog10(val) + 1;
102     char[] result;
103     result.length = length;
104     foreach (immutable i; 0 .. length)
105     {
106         immutable _val = val / fastPow10tbl_32bit_unsigned[i];
107         result[length - i - 1] = cast(char)((_val % 10) + '0');
108     }
109     return cast(string) result;
110 }
111 
112 static assert(mixin(uint.max.uint_to_string) == uint.max);
113 
114 @safe pure unittest
115 {
116 }