diff --git a/internal/numeric.h b/internal/numeric.h index 6bb7baf204..3d88845a16 100644 --- a/internal/numeric.h +++ b/internal/numeric.h @@ -206,10 +206,22 @@ rb_float_flonum_value(VALUE v) return 0.0; } +#if SIZEOF_VALUE >= SIZEOF_DOUBLE || defined(UNALIGNED_WORD_ACCESS) +# define UNALIGNED_DOUBLE_ACCESS 1 +#else +# define UNALIGNED_DOUBLE_ACCESS 0 +#endif + static inline double rb_float_noflonum_value(VALUE v) { +#if UNALIGNED_DOUBLE_ACCESS return RFLOAT(v)->float_value; +#else + double d; + memcpy(&d, &RFLOAT(v)->float_value, sizeof(double)); + return d; +#endif } static inline double diff --git a/numeric.c b/numeric.c index d216240520..e12bcce5b8 100644 --- a/numeric.c +++ b/numeric.c @@ -951,7 +951,11 @@ rb_float_new_in_heap(double d) { NEWOBJ_OF(flt, struct RFloat, rb_cFloat, T_FLOAT | (RGENGC_WB_PROTECTED_FLOAT ? FL_WB_PROTECTED : 0)); +#if UNALIGNED_DOUBLE_ACCESS flt->float_value = d; +#else + memcpy(&flt->float_value, &d, sizeof(double)); +#endif OBJ_FREEZE((VALUE)flt); return (VALUE)flt; }