summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--build_config/serenity.rb26
-rw-r--r--include/mrbconf.h3
-rw-r--r--include/mruby.h1
-rw-r--r--include/mruby/boxing_word.h63
-rw-r--r--mrbgems/mruby-cmath/src/cmath.c1
-rw-r--r--mrbgems/mruby-compiler/core/codegen.c5
-rw-r--r--mrbgems/mruby-complex/src/complex.c1
-rw-r--r--mrbgems/mruby-math/src/math.c1
-rw-r--r--mrbgems/mruby-numeric-ext/src/numeric_ext.c1
-rw-r--r--mrbgems/mruby-random/src/random.c5
-rw-r--r--mrbgems/mruby-range-ext/src/range.c1
-rw-r--r--mrbgems/mruby-rational/src/rational.c1
-rw-r--r--mrbgems/mruby-sprintf/src/sprintf.c5
-rw-r--r--mrbgems/mruby-test/driver.c4
-rw-r--r--mrbgems/mruby-time/src/time.c4
-rw-r--r--src/dump.c4
-rw-r--r--src/etc.c20
-rw-r--r--src/load.c4
-rw-r--r--src/numeric.c16
-rw-r--r--src/string.c3
-rw-r--r--src/symbol.c4
-rw-r--r--src/vm.c3
-rw-r--r--test/t/float.rb14
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>
diff --git a/src/etc.c b/src/etc.c
index a5c48bbe3..f2dfac9fb 100644
--- a/src/etc.c
+++ b/src/etc.c
@@ -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;
diff --git a/src/vm.c b/src/vm.c
index 57531797c..50ad3b31d 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -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)