Commit 9b4e8e56 authored by Yukihiro "Matz" Matsumoto's avatar Yukihiro "Matz" Matsumoto

Merge pull request #873 from monaka/pr-cleanup-numeric-20130223

Clean numeric.c up.
parents 71a13f9e 4c968174
...@@ -25,8 +25,6 @@ ...@@ -25,8 +25,6 @@
#include <ieeefp.h> #include <ieeefp.h>
#endif #endif
#define RSHIFT(x,y) ((x)>>(int)(y))
#ifdef MRB_USE_FLOAT #ifdef MRB_USE_FLOAT
#define floor(f) floorf(f) #define floor(f) floorf(f)
#define ceil(f) ceilf(f) #define ceil(f) ceilf(f)
...@@ -184,6 +182,7 @@ flo_to_s(mrb_state *mrb, mrb_value flt) ...@@ -184,6 +182,7 @@ flo_to_s(mrb_state *mrb, mrb_value flt)
{ {
char buf[32]; char buf[32];
int n; int n;
mrb_float value = mrb_float(flt); mrb_float value = mrb_float(flt);
if (isinf(value)) { if (isinf(value)) {
...@@ -243,22 +242,25 @@ flo_mul(mrb_state *mrb, mrb_value x) ...@@ -243,22 +242,25 @@ flo_mul(mrb_state *mrb, mrb_value x)
static void static void
flodivmod(mrb_state *mrb, mrb_float x, mrb_float y, mrb_float *divp, mrb_float *modp) flodivmod(mrb_state *mrb, mrb_float x, mrb_float y, mrb_float *divp, mrb_float *modp)
{ {
mrb_float div, mod; mrb_float div;
mrb_float mod;
if (y == 0.0) { if (y == 0.0) {
*divp = str_to_mrb_float("inf"); div = str_to_mrb_float("inf");
*modp = str_to_mrb_float("nan"); mod = str_to_mrb_float("nan");
return;
} }
mod = fmod(x, y); else {
if (isinf(x) && !isinf(y) && !isnan(y)) mod = fmod(x, y);
div = x; if (isinf(x) && !isinf(y) && !isnan(y))
else div = x;
div = (x - mod) / y; else
if (y*mod < 0) { div = (x - mod) / y;
mod += y; if (y*mod < 0) {
div -= 1.0; mod += y;
div -= 1.0;
}
} }
if (modp) *modp = mod; if (modp) *modp = mod;
if (divp) *divp = div; if (divp) *divp = div;
} }
...@@ -280,6 +282,7 @@ flo_mod(mrb_state *mrb, mrb_value x) ...@@ -280,6 +282,7 @@ flo_mod(mrb_state *mrb, mrb_value x)
{ {
mrb_value y; mrb_value y;
mrb_float fy, mod; mrb_float fy, mod;
mrb_get_args(mrb, "o", &y); mrb_get_args(mrb, "o", &y);
fy = mrb_to_flo(mrb, y); fy = mrb_to_flo(mrb, y);
...@@ -339,6 +342,7 @@ flo_eq(mrb_state *mrb, mrb_value x) ...@@ -339,6 +342,7 @@ flo_eq(mrb_state *mrb, mrb_value x)
{ {
mrb_value y; mrb_value y;
volatile mrb_float a, b; volatile mrb_float a, b;
mrb_get_args(mrb, "o", &y); mrb_get_args(mrb, "o", &y);
switch (mrb_type(y)) { switch (mrb_type(y)) {
...@@ -727,6 +731,7 @@ static mrb_value ...@@ -727,6 +731,7 @@ static mrb_value
fix_mul(mrb_state *mrb, mrb_value x) fix_mul(mrb_state *mrb, mrb_value x)
{ {
mrb_value y; mrb_value y;
mrb_get_args(mrb, "o", &y); mrb_get_args(mrb, "o", &y);
return mrb_fixnum_mul(mrb, x, y); return mrb_fixnum_mul(mrb, x, y);
} }
...@@ -736,6 +741,8 @@ fixdivmod(mrb_state *mrb, mrb_int x, mrb_int y, mrb_int *divp, mrb_int *modp) ...@@ -736,6 +741,8 @@ fixdivmod(mrb_state *mrb, mrb_int x, mrb_int y, mrb_int *divp, mrb_int *modp)
{ {
mrb_int div, mod; mrb_int div, mod;
/* TODO: add assert(y != 0) to make sure */
if (y < 0) { if (y < 0) {
if (x < 0) if (x < 0)
div = -x / -y; div = -x / -y;
...@@ -802,6 +809,7 @@ static mrb_value ...@@ -802,6 +809,7 @@ static mrb_value
fix_divmod(mrb_state *mrb, mrb_value x) fix_divmod(mrb_state *mrb, mrb_value x)
{ {
mrb_value y; mrb_value y;
mrb_get_args(mrb, "o", &y); mrb_get_args(mrb, "o", &y);
if (mrb_fixnum_p(y)) { if (mrb_fixnum_p(y)) {
...@@ -841,6 +849,7 @@ static mrb_value ...@@ -841,6 +849,7 @@ static mrb_value
fix_equal(mrb_state *mrb, mrb_value x) fix_equal(mrb_state *mrb, mrb_value x)
{ {
mrb_value y; mrb_value y;
mrb_get_args(mrb, "o", &y); mrb_get_args(mrb, "o", &y);
if (mrb_obj_equal(mrb, x, y)) return mrb_true_value(); if (mrb_obj_equal(mrb, x, y)) return mrb_true_value();
...@@ -900,6 +909,7 @@ fix_and(mrb_state *mrb, mrb_value x) ...@@ -900,6 +909,7 @@ fix_and(mrb_state *mrb, mrb_value x)
{ {
mrb_value y; mrb_value y;
mrb_int val; mrb_int val;
mrb_get_args(mrb, "o", &y); mrb_get_args(mrb, "o", &y);
y = bit_coerce(mrb, y); y = bit_coerce(mrb, y);
...@@ -920,6 +930,7 @@ fix_or(mrb_state *mrb, mrb_value x) ...@@ -920,6 +930,7 @@ fix_or(mrb_state *mrb, mrb_value x)
{ {
mrb_value y; mrb_value y;
mrb_int val; mrb_int val;
mrb_get_args(mrb, "o", &y); mrb_get_args(mrb, "o", &y);
y = bit_coerce(mrb, y); y = bit_coerce(mrb, y);
...@@ -942,31 +953,51 @@ fix_xor(mrb_state *mrb, mrb_value x) ...@@ -942,31 +953,51 @@ fix_xor(mrb_state *mrb, mrb_value x)
mrb_int val; mrb_int val;
mrb_get_args(mrb, "o", &y); mrb_get_args(mrb, "o", &y);
y = bit_coerce(mrb, y); y = bit_coerce(mrb, y);
val = mrb_fixnum(x) ^ mrb_fixnum(y); val = mrb_fixnum(x) ^ mrb_fixnum(y);
return mrb_fixnum_value(val); return mrb_fixnum_value(val);
} }
#define NUMERIC_SHIFT_WIDTH_MAX (sizeof(mrb_int)*CHAR_BIT-1)
static mrb_value static mrb_value
lshift(mrb_state *mrb, mrb_int val, int width) lshift(mrb_state *mrb, mrb_int val, int width)
{ {
if (width > (sizeof(mrb_int)*CHAR_BIT-1)) { if (width > NUMERIC_SHIFT_WIDTH_MAX) {
mrb_raisef(mrb, E_RANGE_ERROR, "width(%d) > (%d:sizeof(mrb_int)*CHAR_BIT-1)", width, mrb_raisef(mrb, E_RANGE_ERROR, "width(%d) > (%d:sizeof(mrb_int)*CHAR_BIT-1)", width,
sizeof(mrb_int)*CHAR_BIT-1); NUMERIC_SHIFT_WIDTH_MAX);
} }
val = val << width; val = val << width;
return mrb_fixnum_value(val); return mrb_fixnum_value(val);
} }
static mrb_value static mrb_value
rshift(mrb_int val, int i) rshift(mrb_int val, int width)
{ {
if (i >= sizeof(mrb_int)*CHAR_BIT-1) { if (width >= NUMERIC_SHIFT_WIDTH_MAX) {
if (val < 0) return mrb_fixnum_value(-1); if (val < 0) {
return mrb_fixnum_value(0); val = -1;
} }
val = RSHIFT(val, i); else {
return mrb_fixnum_value(val); val = 0;
}
}
else {
val = val >> width;
}
return mrb_fixnum_value(val);
}
static inline void
fix_shift_get_width(mrb_state *mrb, mrb_int *width)
{
mrb_value y;
mrb_get_args(mrb, "o", &y);
y = bit_coerce(mrb, y);
*width = mrb_fixnum(y);
} }
/* 15.2.8.3.12 */ /* 15.2.8.3.12 */
...@@ -980,16 +1011,27 @@ rshift(mrb_int val, int i) ...@@ -980,16 +1011,27 @@ rshift(mrb_int val, int i)
static mrb_value static mrb_value
fix_lshift(mrb_state *mrb, mrb_value x) fix_lshift(mrb_state *mrb, mrb_value x)
{ {
mrb_value y; mrb_int width;
mrb_int val, width; mrb_value result;
mrb_get_args(mrb, "o", &y); fix_shift_get_width(mrb, &width);
val = mrb_fixnum(x);
y = bit_coerce(mrb, y); if (width == 0) {
width = mrb_fixnum(y); result = x;
if (width < 0) }
return rshift(val, -width); else {
return lshift(mrb, val, width); mrb_int val;
val = mrb_fixnum(x);
if (width < 0) {
result = rshift(val, -width);
}
else {
result = lshift(mrb, val, width);
}
}
return result;
} }
/* 15.2.8.3.13 */ /* 15.2.8.3.13 */
...@@ -1003,17 +1045,27 @@ fix_lshift(mrb_state *mrb, mrb_value x) ...@@ -1003,17 +1045,27 @@ fix_lshift(mrb_state *mrb, mrb_value x)
static mrb_value static mrb_value
fix_rshift(mrb_state *mrb, mrb_value x) fix_rshift(mrb_state *mrb, mrb_value x)
{ {
mrb_value y; mrb_int width;
mrb_int i, val; mrb_value result;
mrb_get_args(mrb, "o", &y); fix_shift_get_width(mrb, &width);
val = mrb_fixnum(x);
y = bit_coerce(mrb, y); if (width == 0) {
i = mrb_fixnum(y); result = x;
if (i == 0) return x; }
if (i < 0) else {
return lshift(mrb, val, -i); mrb_int val;
return rshift(val, i);
val = mrb_fixnum(x);
if (width < 0) {
result = lshift(mrb, val, -width);
}
else {
result = rshift(val, width);
}
}
return result;
} }
/* 15.2.8.3.23 */ /* 15.2.8.3.23 */
...@@ -1148,14 +1200,6 @@ fix_minus(mrb_state *mrb, mrb_value self) ...@@ -1148,14 +1200,6 @@ fix_minus(mrb_state *mrb, mrb_value self)
return mrb_fixnum_minus(mrb, self, other); return mrb_fixnum_minus(mrb, self, other);
} }
/* 15.2.8.3.29 (x) */
/*
* call-seq:
* fix > other => true or false
*
* Returns <code>true</code> if the value of <code>fix</code> is
* greater than that of <code>other</code>.
*/
mrb_value mrb_value
mrb_fix2str(mrb_state *mrb, mrb_value x, int base) mrb_fix2str(mrb_state *mrb, mrb_value x, int base)
...@@ -1279,6 +1323,7 @@ void ...@@ -1279,6 +1323,7 @@ void
mrb_init_numeric(mrb_state *mrb) mrb_init_numeric(mrb_state *mrb)
{ {
struct RClass *numeric, *integer, *fixnum, *fl; struct RClass *numeric, *integer, *fixnum, *fl;
/* Numeric Class */ /* Numeric Class */
numeric = mrb_define_class(mrb, "Numeric", mrb->object_class); numeric = mrb_define_class(mrb, "Numeric", mrb->object_class);
mrb_include_module(mrb, numeric, mrb_class_get(mrb, "Comparable")); mrb_include_module(mrb, numeric, mrb_class_get(mrb, "Comparable"));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment