diff options
| author | dearblue <[email protected]> | 2019-06-02 18:00:54 +0900 |
|---|---|---|
| committer | dearblue <[email protected]> | 2019-06-05 23:25:28 +0900 |
| commit | 64b3d452ec1cc3d5547da9ca37179f0e4406cc92 (patch) | |
| tree | 7bad5b64426e0798a580fedf11c26bf6763e14b3 /mrbgems/mruby-rational/src | |
| parent | 5e69760d919dd468ea8c8285f0f24affb52d3045 (diff) | |
| download | mruby-64b3d452ec1cc3d5547da9ca37179f0e4406cc92.tar.gz mruby-64b3d452ec1cc3d5547da9ca37179f0e4406cc92.zip | |
Drop precisions for rational when big numbers
Diffstat (limited to 'mrbgems/mruby-rational/src')
| -rw-r--r-- | mrbgems/mruby-rational/src/rational.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/mrbgems/mruby-rational/src/rational.c b/mrbgems/mruby-rational/src/rational.c index db9a8fbb9..31471e934 100644 --- a/mrbgems/mruby-rational/src/rational.c +++ b/mrbgems/mruby-rational/src/rational.c @@ -1,6 +1,7 @@ #include <mruby.h> #include <mruby/class.h> #include <mruby/string.h> +#include <mruby/numeric.h> struct mrb_rational { mrb_int numerator; @@ -86,7 +87,52 @@ rational_s_new(mrb_state *mrb, mrb_value self) { mrb_int numerator, denominator; +#ifdef MRB_WITHOUT_FLOAT mrb_get_args(mrb, "ii", &numerator, &denominator); +#else + +#define DROP_PRECISION(cond, num, denom) \ + do { \ + while (cond) { \ + num /= 2; \ + denom /= 2; \ + } \ + } while (0) + + mrb_value numv, denomv; + + mrb_get_args(mrb, "oo", &numv, &denomv); + if (mrb_fixnum_p(numv)) { + numerator = mrb_fixnum(numv); + + if (mrb_fixnum_p(denomv)) { + denominator = mrb_fixnum(denomv); + } + else { + mrb_float denomf = mrb_to_flo(mrb, denomv); + + DROP_PRECISION(denomf < MRB_INT_MIN || denomf > MRB_INT_MAX, numerator, denomf); + denominator = denomf; + } + } + else { + mrb_float numf = mrb_to_flo(mrb, numv); + + if (mrb_fixnum_p(denomv)) { + denominator = mrb_fixnum(denomv); + } + else { + mrb_float denomf = mrb_to_flo(mrb, denomv); + + DROP_PRECISION(denomf < MRB_INT_MIN || denomf > MRB_INT_MAX, numf, denomf); + denominator = denomf; + } + + DROP_PRECISION(numf < MRB_INT_MIN || numf > MRB_INT_MAX, numf, denominator); + numerator = numf; + } +#endif + return rational_new(mrb, numerator, denominator); } @@ -105,6 +151,9 @@ static mrb_value rational_to_i(mrb_state *mrb, mrb_value self) { struct mrb_rational *p = rational_ptr(mrb, self); + if (p->denominator == 0) { + mrb_raise(mrb, mrb_exc_get(mrb, "StandardError"), "divided by 0"); + } return mrb_fixnum_value(p->numerator / p->denominator); } |
