#pragma once // Copyright (c) 2022 James Edward Anhalt III - https://github.com/jeaiii/itoa using u32 = decltype(0xffffffff); using u64 = decltype(0xffffffffffffffff); static_assert(u32(-1) > 0, "u32 must be unsigned"); static_assert(u32(0xffffffff) + u32(1) == u32(0), "u32 must be 32 bits"); static_assert(u64(-1) > 0, "u64 must be unsigned"); static_assert(u64(0xffffffffffffffff) + u32(1) == u32(0), "u64 must be 64 bits"); constexpr auto digits_00_99 = "00010203040506070809" "10111213141516171819" "20212223242526272829" "30313233343536373839" "40414243444546474849" "50515253545556575859" "60616263646566676869" "70717273747576777879" "80818283848586878889" "90919293949596979899"; struct pair { char t, o; }; #define JEAIII_W(I, U) *(pair*)&b[I] = *(pair*)&digits_00_99[(U) * 2] #define JEAIII_A(I, N) t = (u64(1) << (32 + N / 5 * N * 53 / 16)) / u32(1e##N) + 1 + N / 6 - N / 8, t *= u, t >>= N / 5 * N * 53 / 16, t += N / 6 * 4, JEAIII_W(I, t >> 32) #define JEAIII_S(I) b[I] = char(u64(10) * u32(t) >> 32) + '0' #define JEAIII_D(I) t = u64(100) * u32(t), JEAIII_W(I, t >> 32) #define JEAIII_C0(I) b[I] = char(u) + '0' #define JEAIII_C1(I) JEAIII_W(I, u) #define JEAIII_C2(I) JEAIII_A(I, 1), JEAIII_S(I + 2) #define JEAIII_C3(I) JEAIII_A(I, 2), JEAIII_D(I + 2) #define JEAIII_C4(I) JEAIII_A(I, 3), JEAIII_D(I + 2), JEAIII_S(I + 4) #define JEAIII_C5(I) JEAIII_A(I, 4), JEAIII_D(I + 2), JEAIII_D(I + 4) #define JEAIII_C6(I) JEAIII_A(I, 5), JEAIII_D(I + 2), JEAIII_D(I + 4), JEAIII_S(I + 6) #define JEAIII_C7(I) JEAIII_A(I, 6), JEAIII_D(I + 2), JEAIII_D(I + 4), JEAIII_D(I + 6) #define JEAIII_C8(I) JEAIII_A(I, 7), JEAIII_D(I + 2), JEAIII_D(I + 4), JEAIII_D(I + 6), JEAIII_S(I + 8) #define JEAIII_C9(I) JEAIII_A(I, 8), JEAIII_D(I + 2), JEAIII_D(I + 4), JEAIII_D(I + 6), JEAIII_D(I + 8) #define JEAIII_L(N, A, B) u < u32(1e##N) ? A : B #define JEAIII_L09(F) JEAIII_L(2, JEAIII_L(1, F(0), F(1)), JEAIII_L(6, JEAIII_L(4, JEAIII_L(3, F(2), F(3)), JEAIII_L(5, F(4), F(5))), JEAIII_L(8, JEAIII_L(7, F(6), F(7)), JEAIII_L(9, F(8), F(9))))) #define JEAIII_L03(F) JEAIII_L(2, JEAIII_L(1, F(0), F(1)), JEAIII_L(3, F(2), F(3))) #define JEAIII_K(N) (JEAIII_C##N(0), b + N + 1) #define JEAIII_KX(N) (JEAIII_C##N(0), u = x, JEAIII_C7(N + 1), b + N + 9) #define JEAIII_KYX(N) (JEAIII_C##N(0), u = y, JEAIII_C7(N + 1), u = x, JEAIII_C7(N + 9), b + N + 17) template struct _cond { using type = F; }; template struct _cond { using type = T; }; template using cond = typename _cond::type; template inline char* to_text_from_integer(char* b, T i) { u64 t = u64(i); if (i < T(0)) t = u64(0) - t, b[0] = '-', ++b; u32 u = cond, unsigned char>, bool>(t); // if our input type fits in 32bits, or its value does, ctreat as 32bit (the line above ensures the compiler can still know the range limits of the input type) // and optimize out cases for small integer types (if only c++ had a builtin way to get the unsigned type from a signed type) if (sizeof(i) <= sizeof(u) || u == t) return JEAIII_L09(JEAIII_K); u32 x = t % 100000000u; u = u32(t /= 100000000u); // t / 10^8 (fits in 32 bit), t % 10^8 -> ~17.5 digits if (u == t) return JEAIII_L09(JEAIII_KX); // t / 10^16 (1-4 digits), t / 10^8 % 10^8, t % 10^8 u32 y = t % 100000000u; u = u32(t / 100000000u); return JEAIII_L03(JEAIII_KYX); } inline char* to_text(char text[], signed char i) { return to_text_from_integer(text, i); } inline char* to_text(char text[], unsigned char i) { return to_text_from_integer(text, i); } inline char* to_text(char text[], short i) { return to_text_from_integer(text, i); } inline char* to_text(char text[], unsigned short i) { return to_text_from_integer(text, i); } inline char* to_text(char text[], int i) { return to_text_from_integer(text, i); } inline char* to_text(char text[], unsigned int i) { return to_text_from_integer(text, i); } inline char* to_text(char text[], long i) { return to_text_from_integer(text, i); } inline char* to_text(char text[], unsigned long i) { return to_text_from_integer(text, i); } inline char* to_text(char text[], long long i) { return to_text_from_integer(text, i); } inline char* to_text(char text[], unsigned long long i) { return to_text_from_integer(text, i); } // Copyright (c) 2022 Bill Sun #if defined(__SIZEOF_INT128__) constexpr static __uint128_t _10_19 = 10000000000000000000ull, _10_37 = _10_19*_10_19 / 10; template char* jeaiii_i128(char* buf, T v){ if constexpr (std::is_signed_v) { if (v < 0){ *(buf++) = '0'; v = -v; } } if (v > _10_37){ uint8_t vv = uint8_t(v/_10_37); // vv <<= 1; // if (vv < 20) // *buf ++ = digits_00_99[vv + 1]; // else{ // memcpy(buf, digits_00_99 + vv, 2); // buf += 2; // } *(buf++) = vv%10 + '0'; vv/=10; if (vv) { *buf = *(buf-1); *(buf++-1) = vv + '0'; } } if (v > _10_19) buf = to_text(buf, uint64_t((v/_10_19) % _10_19)); buf = to_text(buf, uint64_t(v % _10_19)); return buf; } #endif // INT128