--- libecb/ecb.h 2021/06/22 00:01:15 1.193 +++ libecb/ecb.h 2021/07/31 16:13:30 1.198 @@ -611,14 +611,14 @@ ecb_inline ecb_const uint64_t ecb_rotl64 (uint64_t x, unsigned int count); ecb_inline ecb_const uint64_t ecb_rotr64 (uint64_t x, unsigned int count); -ecb_inline ecb_const uint8_t ecb_rotl8 (uint8_t x, unsigned int count) { return (x >> ( 8 - count)) | (x << count); } -ecb_inline ecb_const uint8_t ecb_rotr8 (uint8_t x, unsigned int count) { return (x << ( 8 - count)) | (x >> count); } -ecb_inline ecb_const uint16_t ecb_rotl16 (uint16_t x, unsigned int count) { return (x >> (16 - count)) | (x << count); } -ecb_inline ecb_const uint16_t ecb_rotr16 (uint16_t x, unsigned int count) { return (x << (16 - count)) | (x >> count); } -ecb_inline ecb_const uint32_t ecb_rotl32 (uint32_t x, unsigned int count) { return (x >> (32 - count)) | (x << count); } -ecb_inline ecb_const uint32_t ecb_rotr32 (uint32_t x, unsigned int count) { return (x << (32 - count)) | (x >> count); } -ecb_inline ecb_const uint64_t ecb_rotl64 (uint64_t x, unsigned int count) { return (x >> (64 - count)) | (x << count); } -ecb_inline ecb_const uint64_t ecb_rotr64 (uint64_t x, unsigned int count) { return (x << (64 - count)) | (x >> count); } +ecb_inline ecb_const uint8_t ecb_rotl8 (uint8_t x, unsigned int count) { return (x >> (-count & 7)) | (x << (count & 7)); } +ecb_inline ecb_const uint8_t ecb_rotr8 (uint8_t x, unsigned int count) { return (x << (-count & 7)) | (x >> (count & 7)); } +ecb_inline ecb_const uint16_t ecb_rotl16 (uint16_t x, unsigned int count) { return (x >> (-count & 15)) | (x << (count & 15)); } +ecb_inline ecb_const uint16_t ecb_rotr16 (uint16_t x, unsigned int count) { return (x << (-count & 15)) | (x >> (count & 15)); } +ecb_inline ecb_const uint32_t ecb_rotl32 (uint32_t x, unsigned int count) { return (x >> (-count & 31)) | (x << (count & 31)); } +ecb_inline ecb_const uint32_t ecb_rotr32 (uint32_t x, unsigned int count) { return (x << (-count & 31)) | (x >> (count & 31)); } +ecb_inline ecb_const uint64_t ecb_rotl64 (uint64_t x, unsigned int count) { return (x >> (-count & 63)) | (x << (count & 63)); } +ecb_inline ecb_const uint64_t ecb_rotr64 (uint64_t x, unsigned int count) { return (x << (-count & 63)) | (x >> (count & 63)); } #if ECB_CPP @@ -776,7 +776,7 @@ ecb_inline void ecb_poke_be_u16_u (void *ptr, uint_fast16_t v) { ecb_poke_u16_u (ptr, ecb_host_to_be_u16 (v)); } ecb_inline void ecb_poke_be_u32_u (void *ptr, uint_fast32_t v) { ecb_poke_u32_u (ptr, ecb_host_to_be_u32 (v)); } ecb_inline void ecb_poke_be_u64_u (void *ptr, uint_fast64_t v) { ecb_poke_u64_u (ptr, ecb_host_to_be_u64 (v)); } - + ecb_inline void ecb_poke_le_u16_u (void *ptr, uint_fast16_t v) { ecb_poke_u16_u (ptr, ecb_host_to_le_u16 (v)); } ecb_inline void ecb_poke_le_u32_u (void *ptr, uint_fast32_t v) { ecb_poke_u32_u (ptr, ecb_host_to_le_u32 (v)); } ecb_inline void ecb_poke_le_u64_u (void *ptr, uint_fast64_t v) { ecb_poke_u64_u (ptr, ecb_host_to_le_u64 (v)); } @@ -950,6 +950,19 @@ /*******************************************************************************/ /* fast integer to ascii */ +/* + * This code is pretty complicated because it is general. The idea behind it, + * however, is pretty simple: first, the number is multiplied with a scaling + * factor (2**bits / 10**(digits-1)) to convert the integer into a fixed-point + * number with the first digit in the upper bits. + * Then this digit is converted to text and masked out. The resulting number + * is then multiplied by 10, by multiplying the fixed point representation + * by 5 and shifting the (binary) decimal point one to the right, so a 4.28 + * format becomes 5.27, 6.26 and so on. + * The rest involves only advancing the pointer if we already generated a + * non-zero digit, so leading zeroes are overwritten. + */ + // simply return a mask with "bits" bits set #define ecb_i2a_mask(type,bits) ((((type)1) << (bits)) - 1) @@ -998,29 +1011,29 @@ ecb_i2a_def (x10, ptr, v, uint64_t, 60, 1000000000, 0) // non-leading zero versions, all digits, 4 and 9 are optimal for 32/64 bit -ecb_i2a_def ( 2, ptr, v, uint32_t, 10, 10, 0) -ecb_i2a_def ( 3, ptr, v, uint32_t, 12, 100, 0) -ecb_i2a_def ( 4, ptr, v, uint32_t, 26, 1000, 0) -ecb_i2a_def ( 5, ptr, v, uint64_t, 30, 10000, 0) -ecb_i2a_def ( 6, ptr, v, uint64_t, 36, 100000, 0) -ecb_i2a_def ( 7, ptr, v, uint64_t, 44, 1000000, 0) -ecb_i2a_def ( 8, ptr, v, uint64_t, 50, 10000000, 0) -ecb_i2a_def ( 9, ptr, v, uint64_t, 56, 100000000, 0) +ecb_i2a_def ( 2, ptr, v, uint32_t, 10, 10, 0) +ecb_i2a_def ( 3, ptr, v, uint32_t, 12, 100, 0) +ecb_i2a_def ( 4, ptr, v, uint32_t, 26, 1000, 0) +ecb_i2a_def ( 5, ptr, v, uint64_t, 30, 10000, 0) +ecb_i2a_def ( 6, ptr, v, uint64_t, 36, 100000, 0) +ecb_i2a_def ( 7, ptr, v, uint64_t, 44, 1000000, 0) +ecb_i2a_def ( 8, ptr, v, uint64_t, 50, 10000000, 0) +ecb_i2a_def ( 9, ptr, v, uint64_t, 56, 100000000, 0) // leading-zero versions, all digits, 04 and 09 are optimal for 32/64 bit -ecb_i2a_def (02, ptr, v, uint32_t, 10, 10, 1) -ecb_i2a_def (03, ptr, v, uint32_t, 12, 100, 1) -ecb_i2a_def (04, ptr, v, uint32_t, 26, 1000, 1) -ecb_i2a_def (05, ptr, v, uint64_t, 30, 10000, 1) -ecb_i2a_def (06, ptr, v, uint64_t, 36, 100000, 1) -ecb_i2a_def (07, ptr, v, uint64_t, 44, 1000000, 1) -ecb_i2a_def (08, ptr, v, uint64_t, 50, 10000000, 1) -ecb_i2a_def (09, ptr, v, uint64_t, 56, 100000000, 1) +ecb_i2a_def (02, ptr, v, uint32_t, 10, 10, 1) +ecb_i2a_def (03, ptr, v, uint32_t, 12, 100, 1) +ecb_i2a_def (04, ptr, v, uint32_t, 26, 1000, 1) +ecb_i2a_def (05, ptr, v, uint64_t, 30, 10000, 1) +ecb_i2a_def (06, ptr, v, uint64_t, 36, 100000, 1) +ecb_i2a_def (07, ptr, v, uint64_t, 44, 1000000, 1) +ecb_i2a_def (08, ptr, v, uint64_t, 50, 10000000, 1) +ecb_i2a_def (09, ptr, v, uint64_t, 56, 100000000, 1) #define ECB_I2A_I32_DIGITS 11 #define ECB_I2A_U32_DIGITS 10 #define ECB_I2A_I64_DIGITS 20 -#define ECB_I2A_U32_DIGITS 21 +#define ECB_I2A_U64_DIGITS 21 #define ECB_I2A_MAX_DIGITS 21 ecb_inline char *