This commit is contained in:
Raúl Marín 2024-03-20 17:04:52 +01:00
parent 7ac0ebbaca
commit 225db5e253

View File

@ -28,229 +28,231 @@ namespace jeaiii
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using u32 = decltype(0xffffffff);
using u64 = decltype(0xffffffffffffffff);
struct pair
{
char dd[2];
constexpr pair(char c) : dd{c, '\0'} { }
constexpr pair(int n) : dd{"0123456789"[n / 10], "0123456789"[n % 10]} { }
};
struct pair
{
char dd[2];
constexpr pair(char c) : dd{ c, '\0' } { }
constexpr pair(int n) : dd{ "0123456789"[n / 10], "0123456789"[n % 10] } { }
constexpr struct
{
pair dd[100]{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, //
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, //
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, //
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, //
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, //
50, 51, 52, 53, 54, 55, 56, 57, 58, 59, //
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, //
70, 71, 72, 73, 74, 75, 76, 77, 78, 79, //
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, //
90, 91, 92, 93, 94, 95, 96, 97, 98, 99, //
};
pair fd[100]{
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', //
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, //
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, //
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, //
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, //
50, 51, 52, 53, 54, 55, 56, 57, 58, 59, //
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, //
70, 71, 72, 73, 74, 75, 76, 77, 78, 79, //
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, //
90, 91, 92, 93, 94, 95, 96, 97, 98, 99, //
};
} digits;
constexpr struct
constexpr UInt64 mask24 = (UInt64(1) << 24) - 1;
constexpr UInt64 mask32 = (UInt64(1) << 32) - 1;
constexpr UInt64 mask57 = (UInt64(1) << 57) - 1;
template <bool, class, 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 ALWAYS_INLINE char * to_text_from_integer(char * b, T i)
{
constexpr auto q = sizeof(T);
using U = cond<q == 1, unsigned char, cond<q <= sizeof(short), unsigned short, cond<q <= sizeof(UInt32), UInt32, UInt64>>>;
// convert bool to int before test with unary + to silence warning if T happens to be bool
U const n = +i < 0 ? *b++ = '-', U(0) - U(i) : U(i);
if (n < UInt32(1e2))
{
pair dd[100]
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
};
pair fd[100]
{
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
};
*reinterpret_cast<pair *>(b) = digits.fd[n];
return n < 10 ? b + 1 : b + 2;
}
digits;
constexpr u64 mask24 = (u64(1) << 24) - 1;
constexpr u64 mask32 = (u64(1) << 32) - 1;
constexpr u64 mask57 = (u64(1) << 57) - 1;
template<bool, class, 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 ALWAYS_INLINE
char* to_text_from_integer(char* b, T i)
if (n < UInt32(1e6))
{
constexpr auto q = sizeof(T);
using U = cond<q == 1, unsigned char, cond<q <= sizeof(short), unsigned short, cond<q <= sizeof(u32), u32, u64>>>;
// convert bool to int before test with unary + to silence warning if T happens to be bool
U const n = +i < 0 ? *b++ = '-', U(0) - U(i) : U(i);
if (n < u32(1e2))
if (n < UInt32(1e4))
{
*reinterpret_cast<pair*>(b) = digits.fd[n];
return n < 10 ? b + 1 : b + 2;
auto f0 = UInt32(10 * (1 << 24) / 1e3 + 1) * n;
*reinterpret_cast<pair *>(b) = digits.fd[f0 >> 24];
b -= n < UInt32(1e3);
auto f2 = (f0 & mask24) * 100;
*reinterpret_cast<pair *>(b + 2) = digits.dd[f2 >> 24];
return b + 4;
}
if (n < u32(1e6))
auto f0 = UInt64(10 * (1ull << 32ull) / 1e5 + 1) * n;
*reinterpret_cast<pair *>(b) = digits.fd[f0 >> 32];
b -= n < UInt32(1e5);
auto f2 = (f0 & mask32) * 100;
*reinterpret_cast<pair *>(b + 2) = digits.dd[f2 >> 32];
auto f4 = (f2 & mask32) * 100;
*reinterpret_cast<pair *>(b + 4) = digits.dd[f4 >> 32];
return b + 6;
}
if (n < UInt64(1ull << 32ull))
{
if (n < UInt32(1e8))
{
if (n < u32(1e4))
{
auto f0 = u32(10 * (1 << 24) / 1e3 + 1) * n;
*reinterpret_cast<pair*>(b) = digits.fd[f0 >> 24];
b -= n < u32(1e3);
auto f2 = (f0 & mask24) * 100;
*reinterpret_cast<pair*>(b + 2) = digits.dd[f2 >> 24];
return b + 4;
}
auto f0 = u64(10 * (1ull << 32ull)/ 1e5 + 1) * n;
*reinterpret_cast<pair*>(b) = digits.fd[f0 >> 32];
b -= n < u32(1e5);
auto f0 = UInt64(10 * (1ull << 48ull) / 1e7 + 1) * n >> 16;
*reinterpret_cast<pair *>(b) = digits.fd[f0 >> 32];
b -= n < UInt32(1e7);
auto f2 = (f0 & mask32) * 100;
*reinterpret_cast<pair*>(b + 2) = digits.dd[f2 >> 32];
*reinterpret_cast<pair *>(b + 2) = digits.dd[f2 >> 32];
auto f4 = (f2 & mask32) * 100;
*reinterpret_cast<pair*>(b + 4) = digits.dd[f4 >> 32];
return b + 6;
}
if (n < u64(1ull << 32ull))
{
if (n < u32(1e8))
{
auto f0 = u64(10 * (1ull << 48ull) / 1e7 + 1) * n >> 16;
*reinterpret_cast<pair*>(b) = digits.fd[f0 >> 32];
b -= n < u32(1e7);
auto f2 = (f0 & mask32) * 100;
*reinterpret_cast<pair*>(b + 2) = digits.dd[f2 >> 32];
auto f4 = (f2 & mask32) * 100;
*reinterpret_cast<pair*>(b + 4) = digits.dd[f4 >> 32];
auto f6 = (f4 & mask32) * 100;
*reinterpret_cast<pair*>(b + 6) = digits.dd[f6 >> 32];
return b + 8;
}
auto f0 = u64(10 * (1ull << 57ull) / 1e9 + 1) * n;
*reinterpret_cast<pair*>(b) = digits.fd[f0 >> 57];
b -= n < u32(1e9);
auto f2 = (f0 & mask57) * 100;
*reinterpret_cast<pair*>(b + 2) = digits.dd[f2 >> 57];
auto f4 = (f2 & mask57) * 100;
*reinterpret_cast<pair*>(b + 4) = digits.dd[f4 >> 57];
auto f6 = (f4 & mask57) * 100;
*reinterpret_cast<pair*>(b + 6) = digits.dd[f6 >> 57];
auto f8 = (f6 & mask57) * 100;
*reinterpret_cast<pair*>(b + 8) = digits.dd[f8 >> 57];
return b + 10;
}
// if we get here U must be u64 but some compilers don't know that, so reassign n to a u64 to avoid warnings
u32 z = n % u32(1e8);
u64 u = n / u32(1e8);
if (u < u32(1e2))
{
// u can't be 1 digit (if u < 10 it would have been handled above as a 9 digit 32bit number)
*reinterpret_cast<pair*>(b) = digits.dd[u];
b += 2;
}
else if (u < u32(1e6))
{
if (u < u32(1e4))
{
auto f0 = u32(10 * (1 << 24) / 1e3 + 1) * u;
*reinterpret_cast<pair*>(b) = digits.fd[f0 >> 24];
b -= u < u32(1e3);
auto f2 = (f0 & mask24) * 100;
*reinterpret_cast<pair*>(b + 2) = digits.dd[f2 >> 24];
b += 4;
}
else
{
auto f0 = u64(10 * (1ull << 32ull) / 1e5 + 1) * u;
*reinterpret_cast<pair*>(b) = digits.fd[f0 >> 32];
b -= u < u32(1e5);
auto f2 = (f0 & mask32) * 100;
*reinterpret_cast<pair*>(b + 2) = digits.dd[f2 >> 32];
auto f4 = (f2 & mask32) * 100;
*reinterpret_cast<pair*>(b + 4) = digits.dd[f4 >> 32];
b += 6;
}
}
else if (u < u32(1e8))
{
auto f0 = u64(10 * (1ull << 48ull) / 1e7 + 1) * u >> 16;
*reinterpret_cast<pair*>(b) = digits.fd[f0 >> 32];
b -= u < u32(1e7);
auto f2 = (f0 & mask32) * 100;
*reinterpret_cast<pair*>(b + 2) = digits.dd[f2 >> 32];
auto f4 = (f2 & mask32) * 100;
*reinterpret_cast<pair*>(b + 4) = digits.dd[f4 >> 32];
*reinterpret_cast<pair *>(b + 4) = digits.dd[f4 >> 32];
auto f6 = (f4 & mask32) * 100;
*reinterpret_cast<pair*>(b + 6) = digits.dd[f6 >> 32];
b += 8;
*reinterpret_cast<pair *>(b + 6) = digits.dd[f6 >> 32];
return b + 8;
}
else if (u < u64(1ull << 32ull))
auto f0 = UInt64(10 * (1ull << 57ull) / 1e9 + 1) * n;
*reinterpret_cast<pair *>(b) = digits.fd[f0 >> 57];
b -= n < UInt32(1e9);
auto f2 = (f0 & mask57) * 100;
*reinterpret_cast<pair *>(b + 2) = digits.dd[f2 >> 57];
auto f4 = (f2 & mask57) * 100;
*reinterpret_cast<pair *>(b + 4) = digits.dd[f4 >> 57];
auto f6 = (f4 & mask57) * 100;
*reinterpret_cast<pair *>(b + 6) = digits.dd[f6 >> 57];
auto f8 = (f6 & mask57) * 100;
*reinterpret_cast<pair *>(b + 8) = digits.dd[f8 >> 57];
return b + 10;
}
// if we get here U must be UInt64 but some compilers don't know that, so reassign n to a UInt64 to avoid warnings
UInt32 z = n % UInt32(1e8);
UInt64 u = n / UInt32(1e8);
if (u < UInt32(1e2))
{
// u can't be 1 digit (if u < 10 it would have been handled above as a 9 digit 32bit number)
*reinterpret_cast<pair *>(b) = digits.dd[u];
b += 2;
}
else if (u < UInt32(1e6))
{
if (u < UInt32(1e4))
{
auto f0 = u64(10 * (1ull << 57ull) / 1e9 + 1) * u;
*reinterpret_cast<pair*>(b) = digits.fd[f0 >> 57];
b -= u < u32(1e9);
auto f2 = (f0 & mask57) * 100;
*reinterpret_cast<pair*>(b + 2) = digits.dd[f2 >> 57];
auto f4 = (f2 & mask57) * 100;
*reinterpret_cast<pair*>(b + 4) = digits.dd[f4 >> 57];
auto f6 = (f4 & mask57) * 100;
*reinterpret_cast<pair*>(b + 6) = digits.dd[f6 >> 57];
auto f8 = (f6 & mask57) * 100;
*reinterpret_cast<pair*>(b + 8) = digits.dd[f8 >> 57];
b += 10;
auto f0 = UInt32(10 * (1 << 24) / 1e3 + 1) * u;
*reinterpret_cast<pair *>(b) = digits.fd[f0 >> 24];
b -= u < UInt32(1e3);
auto f2 = (f0 & mask24) * 100;
*reinterpret_cast<pair *>(b + 2) = digits.dd[f2 >> 24];
b += 4;
}
else
{
u32 y = u % u32(1e8);
u /= u32(1e8);
// u is 2, 3, or 4 digits (if u < 10 it would have been handled above)
if (u < u32(1e2))
{
*reinterpret_cast<pair*>(b) = digits.dd[u];
b += 2;
}
else
{
auto f0 = u32(10 * (1 << 24) / 1e3 + 1) * u;
*reinterpret_cast<pair*>(b) = digits.fd[f0 >> 24];
b -= u < u32(1e3);
auto f2 = (f0 & mask24) * 100;
*reinterpret_cast<pair*>(b + 2) = digits.dd[f2 >> 24];
b += 4;
}
// do 8 digits
auto f0 = (u64((1ull << 48ull) / 1e6 + 1) * y >> 16) + 1;
*reinterpret_cast<pair*>(b) = digits.dd[f0 >> 32];
auto f0 = UInt64(10 * (1ull << 32ull) / 1e5 + 1) * u;
*reinterpret_cast<pair *>(b) = digits.fd[f0 >> 32];
b -= u < UInt32(1e5);
auto f2 = (f0 & mask32) * 100;
*reinterpret_cast<pair*>(b + 2) = digits.dd[f2 >> 32];
*reinterpret_cast<pair *>(b + 2) = digits.dd[f2 >> 32];
auto f4 = (f2 & mask32) * 100;
*reinterpret_cast<pair*>(b + 4) = digits.dd[f4 >> 32];
auto f6 = (f4 & mask32) * 100;
*reinterpret_cast<pair*>(b + 6) = digits.dd[f6 >> 32];
b += 8;
*reinterpret_cast<pair *>(b + 4) = digits.dd[f4 >> 32];
b += 6;
}
}
else if (u < UInt32(1e8))
{
auto f0 = UInt64(10 * (1ull << 48ull) / 1e7 + 1) * u >> 16;
*reinterpret_cast<pair *>(b) = digits.fd[f0 >> 32];
b -= u < UInt32(1e7);
auto f2 = (f0 & mask32) * 100;
*reinterpret_cast<pair *>(b + 2) = digits.dd[f2 >> 32];
auto f4 = (f2 & mask32) * 100;
*reinterpret_cast<pair *>(b + 4) = digits.dd[f4 >> 32];
auto f6 = (f4 & mask32) * 100;
*reinterpret_cast<pair *>(b + 6) = digits.dd[f6 >> 32];
b += 8;
}
else if (u < UInt64(1ull << 32ull))
{
auto f0 = UInt64(10 * (1ull << 57ull) / 1e9 + 1) * u;
*reinterpret_cast<pair *>(b) = digits.fd[f0 >> 57];
b -= u < UInt32(1e9);
auto f2 = (f0 & mask57) * 100;
*reinterpret_cast<pair *>(b + 2) = digits.dd[f2 >> 57];
auto f4 = (f2 & mask57) * 100;
*reinterpret_cast<pair *>(b + 4) = digits.dd[f4 >> 57];
auto f6 = (f4 & mask57) * 100;
*reinterpret_cast<pair *>(b + 6) = digits.dd[f6 >> 57];
auto f8 = (f6 & mask57) * 100;
*reinterpret_cast<pair *>(b + 8) = digits.dd[f8 >> 57];
b += 10;
}
else
{
UInt32 y = u % UInt32(1e8);
u /= UInt32(1e8);
// u is 2, 3, or 4 digits (if u < 10 it would have been handled above)
if (u < UInt32(1e2))
{
*reinterpret_cast<pair *>(b) = digits.dd[u];
b += 2;
}
else
{
auto f0 = UInt32(10 * (1 << 24) / 1e3 + 1) * u;
*reinterpret_cast<pair *>(b) = digits.fd[f0 >> 24];
b -= u < UInt32(1e3);
auto f2 = (f0 & mask24) * 100;
*reinterpret_cast<pair *>(b + 2) = digits.dd[f2 >> 24];
b += 4;
}
// do 8 digits
auto f0 = (u64((1ull << 48ull) / 1e6 + 1) * z >> 16) + 1;
*reinterpret_cast<pair*>(b) = digits.dd[f0 >> 32];
auto f0 = (UInt64((1ull << 48ull) / 1e6 + 1) * y >> 16) + 1;
*reinterpret_cast<pair *>(b) = digits.dd[f0 >> 32];
auto f2 = (f0 & mask32) * 100;
*reinterpret_cast<pair*>(b + 2) = digits.dd[f2 >> 32];
*reinterpret_cast<pair *>(b + 2) = digits.dd[f2 >> 32];
auto f4 = (f2 & mask32) * 100;
*reinterpret_cast<pair*>(b + 4) = digits.dd[f4 >> 32];
*reinterpret_cast<pair *>(b + 4) = digits.dd[f4 >> 32];
auto f6 = (f4 & mask32) * 100;
*reinterpret_cast<pair*>(b + 6) = digits.dd[f6 >> 32];
return b + 8;
*reinterpret_cast<pair *>(b + 6) = digits.dd[f6 >> 32];
b += 8;
}
// do 8 digits
auto f0 = (UInt64((1ull << 48ull) / 1e6 + 1) * z >> 16) + 1;
*reinterpret_cast<pair *>(b) = digits.dd[f0 >> 32];
auto f2 = (f0 & mask32) * 100;
*reinterpret_cast<pair *>(b + 2) = digits.dd[f2 >> 32];
auto f4 = (f2 & mask32) * 100;
*reinterpret_cast<pair *>(b + 4) = digits.dd[f4 >> 32];
auto f6 = (f4 & mask32) * 100;
*reinterpret_cast<pair *>(b + 6) = digits.dd[f6 >> 32];
return b + 8;
}
}
namespace
{
ALWAYS_INLINE inline void outTwoDigits(char * p, uint8_t value)
{
*reinterpret_cast<jeaiii::pair*>(p) = jeaiii::digits.fd[value];
*reinterpret_cast<jeaiii::pair *>(p) = jeaiii::digits.fd[value];
}
const uint64_t max_multiple_of_hundred_that_fits_in_64_bits = 1'00'00'00'00'00'00'00'00'00ull;