summaryrefslogtreecommitdiff
path: root/numeric.c
diff options
context:
space:
mode:
Diffstat (limited to 'numeric.c')
-rw-r--r--numeric.c346
1 files changed, 160 insertions, 186 deletions
diff --git a/numeric.c b/numeric.c
index 8cad7ff670..4db0834ae3 100644
--- a/numeric.c
+++ b/numeric.c
@@ -671,7 +671,7 @@ num_div(VALUE x, VALUE y)
* Of the Core and Standard Library classes,
* only Rational uses this implementation.
*
- * For \Rational +r+ and real number +n+, these expressions are equivalent:
+ * For Rational +r+ and real number +n+, these expressions are equivalent:
*
* r % n
* r-n*(r/n).floor
@@ -836,7 +836,7 @@ int_zero_p(VALUE num)
if (FIXNUM_P(num)) {
return FIXNUM_ZERO_P(num);
}
- assert(RB_BIGNUM_TYPE_P(num));
+ RUBY_ASSERT(RB_BIGNUM_TYPE_P(num));
return rb_bigzero_p(num);
}
@@ -862,6 +862,8 @@ rb_int_zero_p(VALUE num)
* Of the Core and Standard Library classes,
* Integer, Float, Rational, and Complex use this implementation.
*
+ * Related: #zero?
+ *
*/
static VALUE
@@ -948,7 +950,7 @@ num_negative_p(VALUE num)
* So you should know its esoteric system. See following:
*
* - https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
- * - https://github.com/rdp/ruby_tutorials_core/wiki/Ruby-Talk-FAQ#floats_imprecise
+ * - https://github.com/rdp/ruby_tutorials_core/wiki/Ruby-Talk-FAQ#-why-are-rubys-floats-imprecise
* - https://en.wikipedia.org/wiki/Floating_point#Accuracy_problems
*
* You can create a \Float object explicitly with:
@@ -963,7 +965,10 @@ num_negative_p(VALUE num)
*
* First, what's elsewhere. \Class \Float:
*
- * - Inherits from {class Numeric}[rdoc-ref:Numeric@What-27s+Here].
+ * - Inherits from
+ * {class Numeric}[rdoc-ref:Numeric@What-27s+Here]
+ * and {class Object}[rdoc-ref:Object@What-27s+Here].
+ * - Includes {module Comparable}[rdoc-ref:Comparable@What-27s+Here].
*
* Here, class \Float provides methods for:
*
@@ -999,10 +1004,10 @@ num_negative_p(VALUE num)
* - #/: Returns the quotient of +self+ and the given value.
* - #ceil: Returns the smallest number greater than or equal to +self+.
* - #coerce: Returns a 2-element array containing the given value converted to a \Float
- and +self+
+ * and +self+
* - #divmod: Returns a 2-element array containing the quotient and remainder
* results of dividing +self+ by the given value.
- * - #fdiv: Returns the Float result of dividing +self+ by the given value.
+ * - #fdiv: Returns the \Float result of dividing +self+ by the given value.
* - #floor: Returns the greatest number smaller than or equal to +self+.
* - #next_float: Returns the next-larger representable \Float.
* - #prev_float: Returns the next-smaller representable \Float.
@@ -1078,7 +1083,7 @@ flo_to_s(VALUE flt)
s = sign ? rb_usascii_str_new_cstr("-") : rb_usascii_str_new(0, 0);
if ((digs = (int)(e - p)) >= (int)sizeof(buf)) digs = (int)sizeof(buf) - 1;
memcpy(buf, p, digs);
- xfree(p);
+ free(p);
if (decpt > 0) {
if (decpt < digs) {
memmove(buf + decpt + 1, buf + decpt, digs - decpt);
@@ -1550,8 +1555,8 @@ rb_float_pow(VALUE x, VALUE y)
* 1.eql?(Rational(1, 1)) # => false
* 1.eql?(Complex(1, 0)) # => false
*
- * \Method +eql?+ is different from +==+ in that +eql?+ requires matching types,
- * while +==+ does not.
+ * \Method +eql?+ is different from <tt>==</tt> in that +eql?+ requires matching types,
+ * while <tt>==</tt> does not.
*
*/
@@ -1683,12 +1688,12 @@ rb_dbl_cmp(double a, double b)
* Examples:
*
* 2.0 <=> 2 # => 0
- 2.0 <=> 2.0 # => 0
- 2.0 <=> Rational(2, 1) # => 0
- 2.0 <=> Complex(2, 0) # => 0
- 2.0 <=> 1.9 # => 1
- 2.0 <=> 2.1 # => -1
- 2.0 <=> 'foo' # => nil
+ * 2.0 <=> 2.0 # => 0
+ * 2.0 <=> Rational(2, 1) # => 0
+ * 2.0 <=> Complex(2, 0) # => 0
+ * 2.0 <=> 1.9 # => 1
+ * 2.0 <=> 2.1 # => -1
+ * 2.0 <=> 'foo' # => nil
*
* This is the basis for the tests in the Comparable module.
*
@@ -2335,7 +2340,7 @@ int_half_p_half_down(VALUE num, VALUE n, VALUE f)
}
/*
- * Assumes num is an Integer, ndigits <= 0
+ * Assumes num is an \Integer, ndigits <= 0
*/
static VALUE
rb_int_round(VALUE num, int ndigits, enum ruby_num_rounding_mode mode)
@@ -2449,7 +2454,7 @@ rb_int_truncate(VALUE num, int ndigits)
/*
* call-seq:
- * round(ndigits = 0, half: :up]) -> integer or float
+ * round(ndigits = 0, half: :up) -> integer or float
*
* Returns +self+ rounded to the nearest value with
* a precision of +ndigits+ decimal digits.
@@ -2834,7 +2839,7 @@ ruby_num_interval_step_size(VALUE from, VALUE to, VALUE step, int excl)
}
if (RTEST(rb_funcall(from, cmp, 1, to))) return INT2FIX(0);
result = rb_funcall(rb_funcall(to, '-', 1, from), id_div, 1, step);
- if (!excl || RTEST(rb_funcall(rb_funcall(from, '+', 1, rb_funcall(result, '*', 1, step)), cmp, 1, to))) {
+ if (!excl || RTEST(rb_funcall(to, cmp, 1, rb_funcall(from, '+', 1, rb_funcall(result, '*', 1, step))))) {
result = rb_funcall(result, '+', 1, INT2FIX(1));
}
return result;
@@ -2946,88 +2951,88 @@ num_step_size(VALUE from, VALUE args, VALUE eobj)
* step(by: , to: nil) {|n| ... } -> self
* step(by: , to: nil) -> enumerator
*
- * Generates a sequence of numbers; with a block given, traverses the sequence.
+ * Generates a sequence of numbers; with a block given, traverses the sequence.
*
- * Of the Core and Standard Library classes,
- * Integer, Float, and Rational use this implementation.
- *
- * A quick example:
- *
- * squares = []
- * 1.step(by: 2, to: 10) {|i| squares.push(i*i) }
- * squares # => [1, 9, 25, 49, 81]
- *
- * The generated sequence:
- *
- * - Begins with +self+.
- * - Continues at intervals of +step+ (which may not be zero).
- * - Ends with the last number that is within or equal to +limit+;
- * that is, less than or equal to +limit+ if +step+ is positive,
- * greater than or equal to +limit+ if +step+ is negative.
- * If +limit+ is not given, the sequence is of infinite length.
- *
- * If a block is given, calls the block with each number in the sequence;
- * returns +self+. If no block is given, returns an Enumerator::ArithmeticSequence.
- *
- * <b>Keyword Arguments</b>
- *
- * With keyword arguments +by+ and +to+,
- * their values (or defaults) determine the step and limit:
- *
- * # Both keywords given.
- * squares = []
- * 4.step(by: 2, to: 10) {|i| squares.push(i*i) } # => 4
- * squares # => [16, 36, 64, 100]
- * cubes = []
- * 3.step(by: -1.5, to: -3) {|i| cubes.push(i*i*i) } # => 3
- * cubes # => [27.0, 3.375, 0.0, -3.375, -27.0]
- * squares = []
- * 1.2.step(by: 0.2, to: 2.0) {|f| squares.push(f*f) }
- * squares # => [1.44, 1.9599999999999997, 2.5600000000000005, 3.24, 4.0]
- *
- * squares = []
- * Rational(6/5).step(by: 0.2, to: 2.0) {|r| squares.push(r*r) }
- * squares # => [1.0, 1.44, 1.9599999999999997, 2.5600000000000005, 3.24, 4.0]
- *
- * # Only keyword to given.
- * squares = []
- * 4.step(to: 10) {|i| squares.push(i*i) } # => 4
- * squares # => [16, 25, 36, 49, 64, 81, 100]
- * # Only by given.
- *
- * # Only keyword by given
- * squares = []
- * 4.step(by:2) {|i| squares.push(i*i); break if i > 10 }
- * squares # => [16, 36, 64, 100, 144]
- *
- * # No block given.
- * e = 3.step(by: -1.5, to: -3) # => (3.step(by: -1.5, to: -3))
- * e.class # => Enumerator::ArithmeticSequence
- *
- * <b>Positional Arguments</b>
- *
- * With optional positional arguments +limit+ and +step+,
- * their values (or defaults) determine the step and limit:
- *
- * squares = []
- * 4.step(10, 2) {|i| squares.push(i*i) } # => 4
- * squares # => [16, 36, 64, 100]
- * squares = []
- * 4.step(10) {|i| squares.push(i*i) }
- * squares # => [16, 25, 36, 49, 64, 81, 100]
- * squares = []
- * 4.step {|i| squares.push(i*i); break if i > 10 } # => nil
- * squares # => [16, 25, 36, 49, 64, 81, 100, 121]
+ * Of the Core and Standard Library classes,
+ * Integer, Float, and Rational use this implementation.
+ *
+ * A quick example:
+ *
+ * squares = []
+ * 1.step(by: 2, to: 10) {|i| squares.push(i*i) }
+ * squares # => [1, 9, 25, 49, 81]
+ *
+ * The generated sequence:
+ *
+ * - Begins with +self+.
+ * - Continues at intervals of +by+ (which may not be zero).
+ * - Ends with the last number that is within or equal to +to+;
+ * that is, less than or equal to +to+ if +by+ is positive,
+ * greater than or equal to +to+ if +by+ is negative.
+ * If +to+ is +nil+, the sequence is of infinite length.
+ *
+ * If a block is given, calls the block with each number in the sequence;
+ * returns +self+. If no block is given, returns an Enumerator::ArithmeticSequence.
+ *
+ * <b>Keyword Arguments</b>
+ *
+ * With keyword arguments +by+ and +to+,
+ * their values (or defaults) determine the step and limit:
+ *
+ * # Both keywords given.
+ * squares = []
+ * 4.step(by: 2, to: 10) {|i| squares.push(i*i) } # => 4
+ * squares # => [16, 36, 64, 100]
+ * cubes = []
+ * 3.step(by: -1.5, to: -3) {|i| cubes.push(i*i*i) } # => 3
+ * cubes # => [27.0, 3.375, 0.0, -3.375, -27.0]
+ * squares = []
+ * 1.2.step(by: 0.2, to: 2.0) {|f| squares.push(f*f) }
+ * squares # => [1.44, 1.9599999999999997, 2.5600000000000005, 3.24, 4.0]
+ *
+ * squares = []
+ * Rational(6/5).step(by: 0.2, to: 2.0) {|r| squares.push(r*r) }
+ * squares # => [1.0, 1.44, 1.9599999999999997, 2.5600000000000005, 3.24, 4.0]
+ *
+ * # Only keyword to given.
+ * squares = []
+ * 4.step(to: 10) {|i| squares.push(i*i) } # => 4
+ * squares # => [16, 25, 36, 49, 64, 81, 100]
+ * # Only by given.
+ *
+ * # Only keyword by given
+ * squares = []
+ * 4.step(by:2) {|i| squares.push(i*i); break if i > 10 }
+ * squares # => [16, 36, 64, 100, 144]
+ *
+ * # No block given.
+ * e = 3.step(by: -1.5, to: -3) # => (3.step(by: -1.5, to: -3))
+ * e.class # => Enumerator::ArithmeticSequence
+ *
+ * <b>Positional Arguments</b>
+ *
+ * With optional positional arguments +to+ and +by+,
+ * their values (or defaults) determine the step and limit:
+ *
+ * squares = []
+ * 4.step(10, 2) {|i| squares.push(i*i) } # => 4
+ * squares # => [16, 36, 64, 100]
+ * squares = []
+ * 4.step(10) {|i| squares.push(i*i) }
+ * squares # => [16, 25, 36, 49, 64, 81, 100]
+ * squares = []
+ * 4.step {|i| squares.push(i*i); break if i > 10 } # => nil
+ * squares # => [16, 25, 36, 49, 64, 81, 100, 121]
*
* <b>Implementation Notes</b>
*
- * If all the arguments are integers, the loop operates using an integer
- * counter.
+ * If all the arguments are integers, the loop operates using an integer
+ * counter.
*
- * If any of the arguments are floating point numbers, all are converted
- * to floats, and the loop is executed
- * <i>floor(n + n*Float::EPSILON) + 1</i> times,
- * where <i>n = (limit - self)/step</i>.
+ * If any of the arguments are floating point numbers, all are converted
+ * to floats, and the loop is executed
+ * <i>floor(n + n*Float::EPSILON) + 1</i> times,
+ * where <i>n = (limit - self)/step</i>.
*
*/
@@ -3210,7 +3215,7 @@ rb_num2ulong(VALUE val)
void
rb_out_of_int(SIGNED_VALUE num)
{
- rb_raise(rb_eRangeError, "integer %"PRIdVALUE " too %s to convert to `int'",
+ rb_raise(rb_eRangeError, "integer %"PRIdVALUE " too %s to convert to 'int'",
num, num < 0 ? "small" : "big");
}
@@ -3229,12 +3234,12 @@ check_uint(unsigned long num, int sign)
if (sign) {
/* minus */
if (num < (unsigned long)INT_MIN)
- rb_raise(rb_eRangeError, "integer %ld too small to convert to `unsigned int'", (long)num);
+ rb_raise(rb_eRangeError, "integer %ld too small to convert to 'unsigned int'", (long)num);
}
else {
/* plus */
if (UINT_MAX < num)
- rb_raise(rb_eRangeError, "integer %lu too big to convert to `unsigned int'", num);
+ rb_raise(rb_eRangeError, "integer %lu too big to convert to 'unsigned int'", num);
}
}
@@ -3309,7 +3314,7 @@ NORETURN(static void rb_out_of_short(SIGNED_VALUE num));
static void
rb_out_of_short(SIGNED_VALUE num)
{
- rb_raise(rb_eRangeError, "integer %"PRIdVALUE " too %s to convert to `short'",
+ rb_raise(rb_eRangeError, "integer %"PRIdVALUE " too %s to convert to 'short'",
num, num < 0 ? "small" : "big");
}
@@ -3327,12 +3332,12 @@ check_ushort(unsigned long num, int sign)
if (sign) {
/* minus */
if (num < (unsigned long)SHRT_MIN)
- rb_raise(rb_eRangeError, "integer %ld too small to convert to `unsigned short'", (long)num);
+ rb_raise(rb_eRangeError, "integer %ld too small to convert to 'unsigned short'", (long)num);
}
else {
/* plus */
if (USHRT_MAX < num)
- rb_raise(rb_eRangeError, "integer %lu too big to convert to `unsigned short'", num);
+ rb_raise(rb_eRangeError, "integer %lu too big to convert to 'unsigned short'", num);
}
}
@@ -3488,7 +3493,10 @@ rb_num2ull(VALUE val)
*
* First, what's elsewhere. \Class \Integer:
*
- * - Inherits from {class Numeric}[rdoc-ref:Numeric@What-27s+Here].
+ * - Inherits from
+ * {class Numeric}[rdoc-ref:Numeric@What-27s+Here]
+ * and {class Object}[rdoc-ref:Object@What-27s+Here].
+ * - Includes {module Comparable}[rdoc-ref:Comparable@What-27s+Here].
*
* Here, class \Integer provides methods for:
*
@@ -3568,7 +3576,7 @@ rb_int_odd_p(VALUE num)
return RBOOL(num & 2);
}
else {
- assert(RB_BIGNUM_TYPE_P(num));
+ RUBY_ASSERT(RB_BIGNUM_TYPE_P(num));
return rb_big_odd_p(num);
}
}
@@ -3580,7 +3588,7 @@ int_even_p(VALUE num)
return RBOOL((num & 2) == 0);
}
else {
- assert(RB_BIGNUM_TYPE_P(num));
+ RUBY_ASSERT(RB_BIGNUM_TYPE_P(num));
return rb_big_even_p(num);
}
}
@@ -3837,7 +3845,7 @@ rb_int_uminus(VALUE num)
return fix_uminus(num);
}
else {
- assert(RB_BIGNUM_TYPE_P(num));
+ RUBY_ASSERT(RB_BIGNUM_TYPE_P(num));
return rb_big_uminus(num);
}
}
@@ -4096,7 +4104,13 @@ static double
fix_fdiv_double(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
- return double_div_double(FIX2LONG(x), FIX2LONG(y));
+ long iy = FIX2LONG(y);
+#if SIZEOF_LONG * CHAR_BIT > DBL_MANT_DIG
+ if ((iy < 0 ? -iy : iy) >= (1L << DBL_MANT_DIG)) {
+ return rb_big_fdiv_double(rb_int2big(FIX2LONG(x)), rb_int2big(iy));
+ }
+#endif
+ return double_div_double(FIX2LONG(x), iy);
}
else if (RB_BIGNUM_TYPE_P(y)) {
return rb_big_fdiv_double(rb_int2big(FIX2LONG(x)), y);
@@ -4114,7 +4128,7 @@ rb_int_fdiv_double(VALUE x, VALUE y)
{
if (RB_INTEGER_TYPE_P(y) && !FIXNUM_ZERO_P(y)) {
VALUE gcd = rb_gcd(x, y);
- if (!FIXNUM_ZERO_P(gcd)) {
+ if (!FIXNUM_ZERO_P(gcd) && gcd != INT2FIX(1)) {
x = rb_int_idiv(x, gcd);
y = rb_int_idiv(y, gcd);
}
@@ -4236,14 +4250,14 @@ fix_idiv(VALUE x, VALUE y)
* Performs integer division; returns the integer result of dividing +self+
* by +numeric+:
*
- * 4.div(3) # => 1
- * 4.div(-3) # => -2
- * -4.div(3) # => -2
- * -4.div(-3) # => 1
- * 4.div(3.0) # => 1
- * 4.div(Rational(3, 1)) # => 1
+ * 4.div(3) # => 1
+ * 4.div(-3) # => -2
+ * -4.div(3) # => -2
+ * -4.div(-3) # => 1
+ * 4.div(3.0) # => 1
+ * 4.div(Rational(3, 1)) # => 1
*
- * Raises an exception if +numeric+ does not have method +div+.
+ * Raises an exception if +numeric+ does not have method +div+.
*
*/
@@ -4347,7 +4361,7 @@ int_remainder(VALUE x, VALUE y)
if (FIXNUM_P(x)) {
if (FIXNUM_P(y)) {
VALUE z = fix_mod(x, y);
- assert(FIXNUM_P(z));
+ RUBY_ASSERT(FIXNUM_P(z));
if (z != INT2FIX(0) && (SIGNED_VALUE)(x ^ y) < 0)
z = fix_minus(z, y);
return z;
@@ -4697,7 +4711,7 @@ rb_int_cmp(VALUE x, VALUE y)
return rb_big_cmp(x, y);
}
else {
- rb_raise(rb_eNotImpError, "need to define `<=>' in %s", rb_obj_classname(x));
+ rb_raise(rb_eNotImpError, "need to define '<=>' in %s", rb_obj_classname(x));
}
}
@@ -5157,7 +5171,7 @@ fix_rshift(long val, unsigned long i)
*
*/
-static VALUE
+VALUE
rb_int_rshift(VALUE x, VALUE y)
{
if (FIXNUM_P(x)) {
@@ -5339,7 +5353,7 @@ int_aref(int const argc, VALUE * const argv, VALUE const num)
* 1.to_f # => 1.0
* -1.to_f # => -1.0
*
- * If the value of +self+ does not fit in a \Float,
+ * If the value of +self+ does not fit in a Float,
* the result is infinity:
*
* (10**400).to_f # => Infinity
@@ -5432,7 +5446,7 @@ rb_fix_digits(VALUE fix, long base)
VALUE digits;
long x = FIX2LONG(fix);
- assert(x >= 0);
+ RUBY_ASSERT(x >= 0);
if (base < 2)
rb_raise(rb_eArgError, "invalid radix %ld", base);
@@ -5441,11 +5455,12 @@ rb_fix_digits(VALUE fix, long base)
return rb_ary_new_from_args(1, INT2FIX(0));
digits = rb_ary_new();
- while (x > 0) {
+ while (x >= base) {
long q = x % base;
rb_ary_push(digits, LONG2NUM(q));
x /= base;
}
+ rb_ary_push(digits, LONG2NUM(x));
return digits;
}
@@ -5455,7 +5470,7 @@ rb_int_digits_bigbase(VALUE num, VALUE base)
{
VALUE digits, bases;
- assert(!rb_num_negative_p(num));
+ RUBY_ASSERT(!rb_num_negative_p(num));
if (RB_BIGNUM_TYPE_P(base))
base = rb_big_norm(base);
@@ -5655,53 +5670,7 @@ int_downto(VALUE from, VALUE to)
static VALUE
int_dotimes_size(VALUE num, VALUE args, VALUE eobj)
{
- if (FIXNUM_P(num)) {
- if (NUM2LONG(num) <= 0) return INT2FIX(0);
- }
- else {
- if (RTEST(rb_funcall(num, '<', 1, INT2FIX(0)))) return INT2FIX(0);
- }
- return num;
-}
-
-/*
- * call-seq:
- * times {|i| ... } -> self
- * times -> enumerator
- *
- * Calls the given block +self+ times with each integer in <tt>(0..self-1)</tt>:
- *
- * a = []
- * 5.times {|i| a.push(i) } # => 5
- * a # => [0, 1, 2, 3, 4]
- *
- * With no block given, returns an Enumerator.
- *
- */
-
-static VALUE
-int_dotimes(VALUE num)
-{
- RETURN_SIZED_ENUMERATOR(num, 0, 0, int_dotimes_size);
-
- if (FIXNUM_P(num)) {
- long i, end;
-
- end = FIX2LONG(num);
- for (i=0; i<end; i++) {
- rb_yield_1(LONG2FIX(i));
- }
- }
- else {
- VALUE i = INT2FIX(0);
-
- for (;;) {
- if (!RTEST(int_le(i, num))) break;
- rb_yield(i);
- i = rb_int_plus(i, INT2FIX(1));
- }
- }
- return num;
+ return int_neg_p(num) ? INT2FIX(0) : num;
}
/*
@@ -6032,9 +6001,9 @@ int_s_try_convert(VALUE self, VALUE num)
/*
* Document-class: Numeric
*
- * Numeric is the class from which all higher-level numeric classes should inherit.
+ * \Numeric is the class from which all higher-level numeric classes should inherit.
*
- * Numeric allows instantiation of heap-allocated objects. Other core numeric classes such as
+ * \Numeric allows instantiation of heap-allocated objects. Other core numeric classes such as
* Integer are implemented as immediates, which means that each Integer is a single immutable
* object which is always passed by value.
*
@@ -6048,9 +6017,9 @@ int_s_try_convert(VALUE self, VALUE num)
* 1.dup #=> 1
* 1.object_id == 1.dup.object_id #=> true
*
- * For this reason, Numeric should be used when defining other numeric classes.
+ * For this reason, \Numeric should be used when defining other numeric classes.
*
- * Classes which inherit from Numeric must implement +coerce+, which returns a two-member
+ * Classes which inherit from \Numeric must implement +coerce+, which returns a two-member
* Array containing an object that has been coerced into an instance of the new class
* and +self+ (see #coerce).
*
@@ -6243,7 +6212,6 @@ Init_Numeric(void)
rb_define_method(rb_cInteger, "nobits?", int_nobits_p, 1);
rb_define_method(rb_cInteger, "upto", int_upto, 1);
rb_define_method(rb_cInteger, "downto", int_downto, 1);
- rb_define_method(rb_cInteger, "times", int_dotimes, 0);
rb_define_method(rb_cInteger, "succ", int_succ, 0);
rb_define_method(rb_cInteger, "next", int_succ, 0);
rb_define_method(rb_cInteger, "pred", int_pred, 0);
@@ -6286,19 +6254,25 @@ Init_Numeric(void)
rb_define_method(rb_cInteger, "digits", rb_int_digits, -1);
- rb_fix_to_s_static[0] = rb_fstring_literal("0");
- rb_fix_to_s_static[1] = rb_fstring_literal("1");
- rb_fix_to_s_static[2] = rb_fstring_literal("2");
- rb_fix_to_s_static[3] = rb_fstring_literal("3");
- rb_fix_to_s_static[4] = rb_fstring_literal("4");
- rb_fix_to_s_static[5] = rb_fstring_literal("5");
- rb_fix_to_s_static[6] = rb_fstring_literal("6");
- rb_fix_to_s_static[7] = rb_fstring_literal("7");
- rb_fix_to_s_static[8] = rb_fstring_literal("8");
- rb_fix_to_s_static[9] = rb_fstring_literal("9");
- for(int i = 0; i < 10; i++) {
- rb_gc_register_mark_object(rb_fix_to_s_static[i]);
- }
+#define fix_to_s_static(n) do { \
+ VALUE lit = rb_fstring_literal(#n); \
+ rb_fix_to_s_static[n] = lit; \
+ rb_vm_register_global_object(lit); \
+ RB_GC_GUARD(lit); \
+ } while (0)
+
+ fix_to_s_static(0);
+ fix_to_s_static(1);
+ fix_to_s_static(2);
+ fix_to_s_static(3);
+ fix_to_s_static(4);
+ fix_to_s_static(5);
+ fix_to_s_static(6);
+ fix_to_s_static(7);
+ fix_to_s_static(8);
+ fix_to_s_static(9);
+
+#undef fix_to_s_static
rb_cFloat = rb_define_class("Float", rb_cNumeric);