You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
122 lines
5.3 KiB
122 lines
5.3 KiB
#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<bool B, class T, class F> struct _cond { using type = F; };
|
|
template<class T, class F> struct _cond<true, T, F> { using type = T; };
|
|
template<bool B, class T, class F> using cond = typename _cond<B, T, F>::type;
|
|
|
|
template<class T> 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<T(1) != T(2), cond<sizeof(T) != 1, cond<sizeof(T) != sizeof(short), u32, unsigned short>, 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<class T>
|
|
char* jeaiii_i128(char* buf, T v){
|
|
if constexpr (std::is_signed_v<T>) {
|
|
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
|