diff options
| -rw-r--r-- | build_config/serenity.rb | 26 | ||||
| -rw-r--r-- | include/mrbconf.h | 3 | ||||
| -rw-r--r-- | include/mruby.h | 1 | ||||
| -rw-r--r-- | include/mruby/boxing_word.h | 63 | ||||
| -rw-r--r-- | mrbgems/mruby-cmath/src/cmath.c | 1 | ||||
| -rw-r--r-- | mrbgems/mruby-compiler/core/codegen.c | 5 | ||||
| -rw-r--r-- | mrbgems/mruby-complex/src/complex.c | 1 | ||||
| -rw-r--r-- | mrbgems/mruby-math/src/math.c | 1 | ||||
| -rw-r--r-- | mrbgems/mruby-numeric-ext/src/numeric_ext.c | 1 | ||||
| -rw-r--r-- | mrbgems/mruby-random/src/random.c | 5 | ||||
| -rw-r--r-- | mrbgems/mruby-range-ext/src/range.c | 1 | ||||
| -rw-r--r-- | mrbgems/mruby-rational/src/rational.c | 1 | ||||
| -rw-r--r-- | mrbgems/mruby-sprintf/src/sprintf.c | 5 | ||||
| -rw-r--r-- | mrbgems/mruby-test/driver.c | 4 | ||||
| -rw-r--r-- | mrbgems/mruby-time/src/time.c | 4 | ||||
| -rw-r--r-- | src/dump.c | 4 | ||||
| -rw-r--r-- | src/etc.c | 20 | ||||
| -rw-r--r-- | src/load.c | 4 | ||||
| -rw-r--r-- | src/numeric.c | 16 | ||||
| -rw-r--r-- | src/string.c | 3 | ||||
| -rw-r--r-- | src/symbol.c | 4 | ||||
| -rw-r--r-- | src/vm.c | 3 | ||||
| -rw-r--r-- | test/t/float.rb | 14 |
23 files changed, 148 insertions, 42 deletions
diff --git a/build_config/serenity.rb b/build_config/serenity.rb new file mode 100644 index 000000000..6704d2673 --- /dev/null +++ b/build_config/serenity.rb @@ -0,0 +1,26 @@ +# Cross compiling configuration for SerenityOS +# Graphical Unix-like operating system for x86 computers. +# https://github.com/SerenityOS/serenity +# +# Should be built using the SerenityOS Ports system +# https://github.com/SerenityOS/serenity/tree/master/Ports +# +# As of 2021/08/20, SERENITY_ARCH is defined in the SerenityOS Ports +# build script to always be either "i686" or "x86_64" + +MRuby::CrossBuild.new('serenity') do |conf| + conf.toolchain :gcc + + conf.archiver.command = "#{ENV['SERENITY_ARCH']}-pc-serenity-ar" + conf.linker.command = "#{ENV['SERENITY_ARCH']}-pc-serenity-g++" + + conf.cxx.command = "#{ENV['SERENITY_ARCH']}-pc-serenity-g++" + conf.cxx.defines << (ENV['SERENITY_ARCH'].include?('64') ? 'MRB_64BIT' : 'MRB_32BIT') + + conf.cc.command = "#{ENV['SERENITY_ARCH']}-pc-serenity-gcc" + conf.cc.defines << (ENV['SERENITY_ARCH'].include?('64') ? 'MRB_64BIT' : 'MRB_32BIT') + + conf.gembox 'full-core' + + conf.test_runner.command = 'env' +end diff --git a/include/mrbconf.h b/include/mrbconf.h index 5d54a1c22..7b29cb0ba 100644 --- a/include/mrbconf.h +++ b/include/mrbconf.h @@ -42,6 +42,9 @@ #error Cannot define MRB_USE_FLOAT32 and MRB_NO_FLOAT at the same time #endif +/* if defined mruby allocates Float objects in the heap to keep full precision if needed */ +//#define MRB_USE_FLOAT_FULL_PRECISION + /* add -DMRB_NO_METHOD_CACHE to disable method cache to save memory */ //#define MRB_NO_METHOD_CACHE /* size of the method cache (need to be the power of 2) */ diff --git a/include/mruby.h b/include/mruby.h index 45736ba38..0563ab577 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -99,6 +99,7 @@ #include <mruby/version.h> #ifndef MRB_NO_FLOAT +#include <math.h> #include <float.h> #ifndef FLT_EPSILON #define FLT_EPSILON (1.19209290e-07f) diff --git a/include/mruby/boxing_word.h b/include/mruby/boxing_word.h index e64eb815e..4b80fd6c5 100644 --- a/include/mruby/boxing_word.h +++ b/include/mruby/boxing_word.h @@ -7,7 +7,11 @@ #ifndef MRUBY_BOXING_WORD_H #define MRUBY_BOXING_WORD_H -#ifndef MRB_NO_FLOAT +#if defined(MRB_32BIT) && !defined(MRB_USE_FLOAT_FULL_PRECISION) && !defined(MRB_USE_FLOAT32) +# define MRB_USE_FLOAT_FULL_PRECISION +#endif + +#if !defined(MRB_NO_FLOAT) && defined(MRB_USE_FLOAT_FULL_PRECISION) struct RFloat { MRB_OBJECT_HEADER; mrb_float f; @@ -46,15 +50,22 @@ enum mrb_special_consts { #define BOXWORD_FIXNUM_FLAG (1 << (BOXWORD_FIXNUM_BIT_POS - 1)) #define BOXWORD_FIXNUM_MASK ((1 << BOXWORD_FIXNUM_BIT_POS) - 1) -#ifdef MRB_64BIT -#define BOXWORD_SYMBOL_SHIFT 32 -#define BOXWORD_SYMBOL_FLAG 0x34 -#define BOXWORD_SYMBOL_MASK 0x3f -#else +#if defined(MRB_USE_FLOAT_FULL_PRECISION) +/* floats are allocated in heaps */ #define BOXWORD_SYMBOL_BIT_POS 2 #define BOXWORD_SYMBOL_SHIFT BOXWORD_SYMBOL_BIT_POS #define BOXWORD_SYMBOL_FLAG (1 << (BOXWORD_SYMBOL_BIT_POS - 1)) #define BOXWORD_SYMBOL_MASK ((1 << BOXWORD_SYMBOL_BIT_POS) - 1) +#else +#define BOXWORD_FLOAT_FLAG 2 +#define BOXWORD_FLOAT_MASK 3 +#if defined(MRB_64BIT) +#define BOXWORD_SYMBOL_SHIFT 32 +#else /* MRB_32BIT */ +#define BOXWORD_SYMBOL_SHIFT 5 +#endif +#define BOXWORD_SYMBOL_FLAG 0x1c +#define BOXWORD_SYMBOL_MASK 0x1f #endif #define BOXWORD_IMMEDIATE_MASK 0x07 @@ -69,12 +80,34 @@ enum mrb_special_consts { /* * mrb_value representation: * + * 64bit word with inline float: + * nil : ...0000 0000 (all bits are 0) + * false : ...0000 0100 (mrb_fixnum(v) != 0) + * true : ...0000 1100 + * undef : ...0001 0100 + * symbol: ...0001 1100 (use only upper 32-bit as symbol value with MRB_64BIT) + * fixnum: ...IIII III1 + * float : ...FFFF FF10 (51 bit significands; require MRB_64BIT) + * object: ...PPPP P000 + * + * 32bit word with inline float: * nil : ...0000 0000 (all bits are 0) * false : ...0000 0100 (mrb_fixnum(v) != 0) * true : ...0000 1100 * undef : ...0001 0100 + * symbol: ...SSS1 1100 (use only upper 32-bit as symbol value with MRB_64BIT) + * symbol: ...SSS1 0100 (symbol occupies 20bits) * fixnum: ...IIII III1 - * symbol: ...SSSS SS10 (use only upper 32-bit as symbol value on 64-bit CPU) + * float : ...FFFF FF10 (22 bit significands; require MRB_64BIT) + * object: ...PPPP P000 + * + * and word boxing without inline float: + * nil : ...0000 0000 (all bits are 0) + * false : ...0000 0100 (mrb_fixnum(v) != 0) + * true : ...0000 1100 + * undef : ...0001 0100 + * fixnum: ...IIII III1 + * symbol: ...SSSS SS10 * object: ...PPPP P000 (any bits are 1) */ typedef struct mrb_value { @@ -85,8 +118,12 @@ union mrb_value_ { void *p; struct RBasic *bp; #ifndef MRB_NO_FLOAT +#ifndef MRB_USE_FLOAT_FULL_PRECISION + mrb_float f; +#else struct RFloat *fp; #endif +#endif struct RInteger *ip; struct RCptr *vp; uintptr_t w; @@ -114,7 +151,12 @@ MRB_API mrb_value mrb_word_boxing_int_value(struct mrb_state*, mrb_int); #define mrb_ptr(o) mrb_val_union(o).p #define mrb_cptr(o) mrb_val_union(o).vp->p #ifndef MRB_NO_FLOAT -#define mrb_float(o) mrb_val_union(o).fp->f +#ifndef MRB_USE_FLOAT_FULL_PRECISION +MRB_API mrb_float mrb_word_boxing_value_float(mrb_value v); +#define mrb_float(o) mrb_word_boxing_value_float(o) +#else +#define mrb_float(o) mrb_val_union(o).fp->f +#endif #endif #define mrb_fixnum(o) (mrb_int)(((intptr_t)(o).w) >> BOXWORD_FIXNUM_SHIFT) MRB_INLINE mrb_int @@ -134,8 +176,12 @@ mrb_integer_func(mrb_value o) { #define mrb_false_p(o) ((o).w == MRB_Qfalse) #define mrb_true_p(o) ((o).w == MRB_Qtrue) #ifndef MRB_NO_FLOAT +#ifndef MRB_USE_FLOAT_FULL_PRECISION +#define mrb_float_p(o) BOXWORD_SHIFT_VALUE_P(o, FLOAT) +#else #define mrb_float_p(o) BOXWORD_OBJ_TYPE_P(o, FLOAT) #endif +#endif #define mrb_array_p(o) BOXWORD_OBJ_TYPE_P(o, ARRAY) #define mrb_string_p(o) BOXWORD_OBJ_TYPE_P(o, STRING) #define mrb_hash_p(o) BOXWORD_OBJ_TYPE_P(o, HASH) @@ -177,6 +223,7 @@ mrb_type(mrb_value o) mrb_fixnum_p(o) ? MRB_TT_INTEGER : mrb_symbol_p(o) ? MRB_TT_SYMBOL : mrb_undef_p(o) ? MRB_TT_UNDEF : + mrb_float_p(o) ? MRB_TT_FLOAT : mrb_val_union(o).bp->tt; } diff --git a/mrbgems/mruby-cmath/src/cmath.c b/mrbgems/mruby-cmath/src/cmath.c index 03b181840..8b0c4d04a 100644 --- a/mrbgems/mruby-cmath/src/cmath.c +++ b/mrbgems/mruby-cmath/src/cmath.c @@ -15,7 +15,6 @@ # error CMath conflicts with 'MRB_NO_FLOAT' configuration #endif -#include <math.h> #include <complex.h> mrb_value mrb_complex_new(mrb_state *mrb, mrb_float real, mrb_float imag); diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 3f849b0f1..4546e6cc0 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -4,9 +4,6 @@ ** See Copyright Notice in mruby.h */ -#include <ctype.h> -#include <string.h> -#include <math.h> #include <mruby.h> #include <mruby/compile.h> #include <mruby/proc.h> @@ -19,6 +16,8 @@ #include <mruby/opcode.h> #include <mruby/re.h> #include <mruby/throw.h> +#include <ctype.h> +#include <string.h> #ifndef MRB_CODEGEN_LEVEL_MAX #define MRB_CODEGEN_LEVEL_MAX 1024 diff --git a/mrbgems/mruby-complex/src/complex.c b/mrbgems/mruby-complex/src/complex.c index 286e7e38e..66176c3c1 100644 --- a/mrbgems/mruby-complex/src/complex.c +++ b/mrbgems/mruby-complex/src/complex.c @@ -2,7 +2,6 @@ #include <mruby/class.h> #include <mruby/numeric.h> #include <mruby/presym.h> -#include <math.h> #ifdef MRB_NO_FLOAT # error Complex conflicts with 'MRB_NO_FLOAT' configuration diff --git a/mrbgems/mruby-math/src/math.c b/mrbgems/mruby-math/src/math.c index 8eccc03e5..79fdb7c6f 100644 --- a/mrbgems/mruby-math/src/math.c +++ b/mrbgems/mruby-math/src/math.c @@ -12,7 +12,6 @@ #include <mruby/array.h> #include <mruby/presym.h> -#include <math.h> static void domain_error(mrb_state *mrb, const char *func) diff --git a/mrbgems/mruby-numeric-ext/src/numeric_ext.c b/mrbgems/mruby-numeric-ext/src/numeric_ext.c index 38d297374..2f2a6c755 100644 --- a/mrbgems/mruby-numeric-ext/src/numeric_ext.c +++ b/mrbgems/mruby-numeric-ext/src/numeric_ext.c @@ -1,7 +1,6 @@ #include <mruby.h> #include <mruby/numeric.h> #include <mruby/presym.h> -#include <math.h> /* * call-seq: diff --git a/mrbgems/mruby-random/src/random.c b/mrbgems/mruby-random/src/random.c index 27fd98f82..027e7ce0b 100644 --- a/mrbgems/mruby-random/src/random.c +++ b/mrbgems/mruby-random/src/random.c @@ -58,12 +58,17 @@ rand_init(rand_state *t) #endif } +static uint32_t rand_uint32(rand_state *state); + static uint32_t rand_seed(rand_state *t, uint32_t seed) { uint32_t old_seed = t->seed[SEEDPOS]; rand_init(t); t->seed[SEEDPOS] = seed; + for (int i = 0; i < 10; i++) { + rand_uint32(t); + } return old_seed; } diff --git a/mrbgems/mruby-range-ext/src/range.c b/mrbgems/mruby-range-ext/src/range.c index 2d021f31f..633c97b73 100644 --- a/mrbgems/mruby-range-ext/src/range.c +++ b/mrbgems/mruby-range-ext/src/range.c @@ -1,6 +1,5 @@ #include <mruby.h> #include <mruby/range.h> -#include <math.h> static mrb_bool r_le(mrb_state *mrb, mrb_value a, mrb_value b) diff --git a/mrbgems/mruby-rational/src/rational.c b/mrbgems/mruby-rational/src/rational.c index 7d099b1e2..dacce53eb 100644 --- a/mrbgems/mruby-rational/src/rational.c +++ b/mrbgems/mruby-rational/src/rational.c @@ -155,7 +155,6 @@ rational_new_i(mrb_state *mrb, mrb_int n, mrb_int d) } #ifndef MRB_NO_FLOAT -#include <math.h> #if defined(MRB_INT32) || defined(MRB_USE_FLOAT32) #define frexp_rat(x,exp) frexpf((float)x, exp) diff --git a/mrbgems/mruby-sprintf/src/sprintf.c b/mrbgems/mruby-sprintf/src/sprintf.c index 362d24651..ba5ba4cda 100644 --- a/mrbgems/mruby-sprintf/src/sprintf.c +++ b/mrbgems/mruby-sprintf/src/sprintf.c @@ -5,14 +5,11 @@ */ #include <mruby.h> -#include <string.h> #include <mruby/string.h> #include <mruby/hash.h> #include <mruby/numeric.h> #include <mruby/presym.h> -#ifndef MRB_NO_FLOAT -#include <math.h> -#endif +#include <string.h> #include <ctype.h> #define BIT_DIGITS(N) (((N)*146)/485 + 1) /* log2(10) =~ 146/485 */ diff --git a/mrbgems/mruby-test/driver.c b/mrbgems/mruby-test/driver.c index 3e551c560..48a964e5e 100644 --- a/mrbgems/mruby-test/driver.c +++ b/mrbgems/mruby-test/driver.c @@ -222,8 +222,12 @@ mrb_init_test_driver(mrb_state *mrb, mrb_bool verbose) #ifndef MRB_NO_FLOAT #ifdef MRB_USE_FLOAT32 +#ifdef MRB_USE_FLOAT_FULL_PRECISION mrb_define_const(mrb, mrbtest, "FLOAT_TOLERANCE", mrb_float_value(mrb, 1e-5)); #else + mrb_define_const(mrb, mrbtest, "FLOAT_TOLERANCE", mrb_float_value(mrb, 1e-4)); +#endif +#else mrb_define_const(mrb, mrbtest, "FLOAT_TOLERANCE", mrb_float_value(mrb, 1e-10)); #endif #endif diff --git a/mrbgems/mruby-time/src/time.c b/mrbgems/mruby-time/src/time.c index 99dcb2bcf..6b9762acf 100644 --- a/mrbgems/mruby-time/src/time.c +++ b/mrbgems/mruby-time/src/time.c @@ -4,10 +4,6 @@ ** See Copyright Notice in mruby.h */ -#ifndef MRB_NO_FLOAT -#include <math.h> -#endif - #include <mruby.h> #include <mruby/class.h> #include <mruby/data.h> diff --git a/src/dump.c b/src/dump.c index 94d5cf74d..4327cb375 100644 --- a/src/dump.c +++ b/src/dump.c @@ -4,12 +4,12 @@ ** See Copyright Notice in mruby.h */ -#include <string.h> -#include <math.h> +#include <mruby.h> #include <mruby/dump.h> #include <mruby/string.h> #include <mruby/irep.h> #include <mruby/debug.h> +#include <string.h> #ifndef MRB_NO_FLOAT #include <mruby/endian.h> @@ -158,11 +158,31 @@ mrb_word_boxing_float_value(mrb_state *mrb, mrb_float f) { union mrb_value_ v; +#ifndef MRB_USE_FLOAT_FULL_PRECISION +#if defined(MRB_64BIT) && defined(MRB_USE_FLOAT32) + v.w = 0; +#endif + v.f = f; + v.w = (v.w & ~3) | 2; +#else v.p = mrb_obj_alloc(mrb, MRB_TT_FLOAT, mrb->float_class); v.fp->f = f; MRB_SET_FROZEN_FLAG(v.bp); +#endif return v.value; } + + +#ifndef MRB_USE_FLOAT_FULL_PRECISION +MRB_API mrb_float +mrb_word_boxing_value_float(mrb_value v) +{ + union mrb_value_ u; + u.value = v; + u.w = u.w & ~3; + return u.f; +} +#endif #endif /* MRB_NO_FLOAT */ MRB_API mrb_value diff --git a/src/load.c b/src/load.c index 83e06f1f8..b5b069fcf 100644 --- a/src/load.c +++ b/src/load.c @@ -4,8 +4,7 @@ ** See Copyright Notice in mruby.h */ -#include <string.h> -#include <math.h> +#include <mruby.h> #include <mruby/dump.h> #include <mruby/irep.h> #include <mruby/proc.h> @@ -14,6 +13,7 @@ #include <mruby/error.h> #include <mruby/data.h> #include <mruby/endian.h> +#include <string.h> #if SIZE_MAX < UINT32_MAX # error size_t must be at least 32 bits wide diff --git a/src/numeric.c b/src/numeric.c index 5fbf9c586..1a006b7e3 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -4,17 +4,13 @@ ** See Copyright Notice in mruby.h */ -#ifndef MRB_NO_FLOAT -#include <math.h> -#endif -#include <string.h> - #include <mruby.h> #include <mruby/array.h> #include <mruby/numeric.h> #include <mruby/string.h> #include <mruby/class.h> #include <mruby/presym.h> +#include <string.h> #ifndef MRB_NO_FLOAT #ifdef MRB_USE_FLOAT32 @@ -982,6 +978,15 @@ flo_nan_p(mrb_state *mrb, mrb_value num) { return mrb_bool_value(isnan(mrb_float(num))); } + +static mrb_value +flo_abs(mrb_state *mrb, mrb_value num) +{ + mrb_float f = mrb_float(num); + + if (signbit(f)) return mrb_float_value(mrb, -f); + return num; +} #endif /* @@ -1914,6 +1919,7 @@ mrb_init_numeric(mrb_state *mrb) mrb_define_method(mrb, fl, "to_s", flo_to_s, MRB_ARGS_NONE()); /* 15.2.9.3.16(x) */ mrb_define_method(mrb, fl, "inspect", flo_to_s, MRB_ARGS_NONE()); mrb_define_method(mrb, fl, "nan?", flo_nan_p, MRB_ARGS_NONE()); + mrb_define_method(mrb, fl, "abs", flo_abs, MRB_ARGS_NONE()); /* 15.2.7.4.3 */ #ifdef INFINITY mrb_define_const_id(mrb, fl, MRB_SYM(INFINITY), mrb_float_value(mrb, INFINITY)); diff --git a/src/string.c b/src/string.c index 97e115a19..30d1bcab3 100644 --- a/src/string.c +++ b/src/string.c @@ -15,9 +15,6 @@ #include <mruby/string.h> #include <mruby/numeric.h> #include <mruby/presym.h> -#ifndef MRB_NO_FLOAT -#include <math.h> -#endif #include <string.h> typedef struct mrb_shared_string { diff --git a/src/symbol.c b/src/symbol.c index 9d68b5cf3..dbdeca459 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -73,7 +73,11 @@ static const char pack_table[] = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRS static mrb_sym sym_inline_pack(const char *name, size_t len) { +#if defined(MRB_WORD_BOXING) && defined(MRB_32BIT) && !defined(MRB_USE_FLOAT_FULL_PRECISION) + const size_t pack_length_max = 4; +#else const size_t pack_length_max = 5; +#endif char c; const char *p; @@ -20,9 +20,6 @@ #include <mruby/throw.h> #include <mruby/dump.h> #include <mruby/presym.h> -#ifndef MRB_NO_FLOAT -#include <math.h> -#endif #ifdef MRB_NO_STDIO #if defined(__cplusplus) diff --git a/test/t/float.rb b/test/t/float.rb index f6f6d01dd..e4c25b34e 100644 --- a/test/t/float.rb +++ b/test/t/float.rb @@ -277,8 +277,6 @@ assert('Float#to_s') do assert_equal("-1.0e-10", -0.0000000001.to_s) assert_equal("1.0e+20", 1e20.to_s) assert_equal("-1.0e+20", -1e20.to_s) - assert_equal("1.0e+16", 10000000000000000.0.to_s) - assert_equal("-1.0e+16", -10000000000000000.0.to_s) assert_equal("100000.0", 100000.0.to_s) assert_equal("-100000.0", -100000.0.to_s) if uses_float @@ -305,4 +303,16 @@ assert('Float#eql?') do assert_not_operator(5.0, :eql?, "5.0") end +assert('Float#abs') do + f = 1.0 + assert_equal(1.0, f.abs) + f = -1.0 + assert_equal(1.0, f.abs) + f = 0.0 + assert_equal(0.0, f.abs) + # abs(negative zero) should be positive zero + f = -0.0 + assert_equal(0.0, f.abs) +end + end # const_defined?(:Float) |
