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