diff options
Diffstat (limited to 'erts/emulator/beam/big.h')
-rw-r--r-- | erts/emulator/beam/big.h | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/erts/emulator/beam/big.h b/erts/emulator/beam/big.h index 48efce20e7..274482a0d2 100644 --- a/erts/emulator/beam/big.h +++ b/erts/emulator/beam/big.h @@ -70,7 +70,24 @@ typedef Uint dsize_t; /* Vector size type */ /* Check for small */ #define IS_USMALL(sgn,x) ((sgn) ? ((x) <= MAX_SMALL+1) : ((x) <= MAX_SMALL)) -#define IS_SSMALL(x) (((x) >= MIN_SMALL) && ((x) <= MAX_SMALL)) + +/* + * It seems that both clang and gcc will generate sub-optimal code + * for the more obvious way to write the range check: + * + * #define IS_SSMALL(x) (((x) >= MIN_SMALL) && ((x) <= MAX_SMALL)) + * + * Note that IS_SSMALL() may be used in the 32-bit emulator with + * a Uint64 argument. Therefore, we must test the size of the argument + * to ensure that the cast does not discard the high-order 32 bits. + */ +#if defined(ARCH_32) +# define _IS_SSMALL32(x) (((Uint32) ((((x)) >> (SMALL_BITS-1)) + 1)) < 2) +#else +# define _IS_SSMALL32(x) (1) +#endif +#define _IS_SSMALL64(x) (((Uint64) ((((x)) >> (SMALL_BITS-1)) + 1)) < 2) +#define IS_SSMALL(x) (sizeof(x) == sizeof(Uint32) ? _IS_SSMALL32(x) : _IS_SSMALL64(x)) /* The heap size needed for a bignum */ #define BIG_NEED_SIZE(x) ((x) + 1) @@ -106,10 +123,10 @@ typedef Uint dsize_t; /* Vector size type */ #endif -int big_decimal_estimate(Wterm); -Eterm erts_big_to_list(Eterm, Eterm**); -char *erts_big_to_string(Wterm x, char *buf, Uint buf_sz); -Uint erts_big_to_binary_bytes(Eterm x, char *buf, Uint buf_sz); +int big_integer_estimate(Wterm, Uint base); +Eterm erts_big_to_list(Eterm, int base, Eterm**); +char *erts_big_to_string(Wterm x, int base, char *buf, Uint buf_sz); +Uint erts_big_to_binary_bytes(Eterm x, int base, char *buf, Uint buf_sz); Eterm small_times(Sint, Sint, Eterm*); |