etc.c: inline special float values in word boxing rotation encoding

Encode 0.0, -0.0, +Inf, -Inf, and NaN as small sentinel constants
with the float tag pattern, avoiding heap allocation for these common
special values.  All NaN bit patterns are normalized to a single
canonical NaN.  The 5 obscure floats near 2^(-255) whose rotation
encoding would collide with a sentinel are heap-allocated instead.

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Yukihiro "Matz" Matsumoto
2026-02-18 10:34:03 +09:00
parent b6148c893f
commit 9910444212
+45 -2
View File
@@ -198,12 +198,25 @@ mrb_obj_id(mrb_value obj)
* The addend shifts the exponent so that biased exponents [768, 1279]
* (actual [-255, +256]) produce the correct tag pattern after rotation.
* This covers all practical float values with full precision.
*
* Special values (0.0, -0.0, +Inf, -Inf) are encoded as small sentinel
* constants that also have bottom 2 bits == 10. This avoids heap
* allocation for these common values. The 4 obscure floats whose
* rotation would collide with a sentinel are heap-allocated instead.
*/
#define WORDBOX_FLOAT_ROTATE 3
#define WORDBOX_FLOAT_EXP_MIN (1023 - 255) /* 768 */
#define WORDBOX_FLOAT_EXP_MAX (1023 + 256) /* 1279 */
#define WORDBOX_FLOAT_ADDEND ((uint64_t)((int64_t)(WORDBOX_FLOAT_EXP_MIN - (WORDBOX_FLOAT_FLAG << 9)) << 52))
/* sentinel values for special floats (all have & 3 == 2) */
#define WORDBOX_FLOAT_PZERO 0x02 /* +0.0 */
#define WORDBOX_FLOAT_NZERO 0x06 /* -0.0 */
#define WORDBOX_FLOAT_PINF 0x0a /* +Infinity */
#define WORDBOX_FLOAT_NINF 0x0e /* -Infinity */
#define WORDBOX_FLOAT_NAN 0x12 /* NaN (all NaN bit patterns normalize to this) */
#define WORDBOX_FLOAT_SENTINEL_MAX WORDBOX_FLOAT_NAN
static uint64_t
wordbox_rotl64(uint64_t a, int n)
{
@@ -244,10 +257,30 @@ mrb_word_boxing_float_value(mrb_state *mrb, mrb_float f)
{
uint64_t bits = wordbox_float64_to_u64((double)f);
uint64_t exp = (bits >> 52) & 0x7FF;
if (exp >= WORDBOX_FLOAT_EXP_MIN && exp <= WORDBOX_FLOAT_EXP_MAX) {
v.w = (uintptr_t)wordbox_rotl64(bits - WORDBOX_FLOAT_ADDEND, WORDBOX_FLOAT_ROTATE);
if (exp == 0) {
/* +0.0 or -0.0 (subnormals also fall here, go to heap) */
if (bits == UINT64_C(0))
v.w = WORDBOX_FLOAT_PZERO;
else if (bits == UINT64_C(0x8000000000000000))
v.w = WORDBOX_FLOAT_NZERO;
else goto float_heap;
}
else if (exp == 0x7FF) {
/* +Inf, -Inf, or NaN */
if (bits == UINT64_C(0x7FF0000000000000))
v.w = WORDBOX_FLOAT_PINF;
else if (bits == UINT64_C(0xFFF0000000000000))
v.w = WORDBOX_FLOAT_NINF;
else
v.w = WORDBOX_FLOAT_NAN;
}
else if (exp >= WORDBOX_FLOAT_EXP_MIN && exp <= WORDBOX_FLOAT_EXP_MAX) {
uintptr_t w = (uintptr_t)wordbox_rotl64(bits - WORDBOX_FLOAT_ADDEND, WORDBOX_FLOAT_ROTATE);
if (w <= WORDBOX_FLOAT_SENTINEL_MAX) goto float_heap;
v.w = w;
}
else {
float_heap:
v.p = mrb_obj_alloc(mrb, MRB_TT_FLOAT, mrb->float_class);
v.fp->f = f;
v.bp->frozen = 1;
@@ -279,6 +312,16 @@ mrb_word_boxing_value_float(mrb_value v)
return u.f;
#elif defined(MRB_64BIT)
if ((v.w & WORDBOX_FLOAT_MASK) == WORDBOX_FLOAT_FLAG) {
if (v.w <= WORDBOX_FLOAT_SENTINEL_MAX) {
switch (v.w) {
case WORDBOX_FLOAT_PZERO: return (mrb_float)( 0.0);
case WORDBOX_FLOAT_NZERO: return (mrb_float)(-0.0);
case WORDBOX_FLOAT_PINF: return (mrb_float)( INFINITY);
case WORDBOX_FLOAT_NINF: return (mrb_float)(-INFINITY);
case WORDBOX_FLOAT_NAN: return (mrb_float) NAN;
default: break; /* not reached */
}
}
return (mrb_float)wordbox_u64_to_float64(
wordbox_rotl64((uint64_t)v.w, 64 - WORDBOX_FLOAT_ROTATE) + WORDBOX_FLOAT_ADDEND);
}