@@ -1611,16 +1611,26 @@ int_ceil(mrb_state *mrb, mrb_value x)
16111611if (mrb_nil_p(f)) return x;
16121612#ifdef MRB_USE_BIGINT
16131613if (mrb_bigint_p(x)) {
1614-return mrb_bint_add(mrb, x, mrb_bint_sub(mrb, x, mrb_bint_mod(mrb, x, f)));
1614+x = mrb_bint_add_d(mrb, x, f);
1615+return mrb_bint_sub(mrb, x, mrb_bint_mod(mrb, x, f));
16151616 }
16161617#endif
16171618mrb_int a = mrb_integer(x);
16181619mrb_int b = mrb_integer(f);
1620+mrb_int c = a % b;
16191621int neg = a < 0;
1620-if (neg) a = -a;
1621-else a += b - 1;
1622-a = a / b * b;
1623-if (neg) a = -a;
1622+a -= c;
1623+if (!neg) {
1624+if (mrb_int_add_overflow(a, b, &c)) {
1625+#ifdef MRB_USE_BIGINT
1626+x = mrb_bint_new_int(mrb, a);
1627+return mrb_bint_add(mrb, x, f);
1628+#else
1629+mrb_int_overflow(mrb, "ceil");
1630+#endif
1631+ }
1632+a = c;
1633+ }
16241634return mrb_int_value(mrb, a);
16251635}
16261636@@ -1648,10 +1658,20 @@ int_floor(mrb_state *mrb, mrb_value x)
16481658#endif
16491659mrb_int a = mrb_integer(x);
16501660mrb_int b = mrb_integer(f);
1661+mrb_int c = a % b;
16511662int neg = a < 0;
1652-if (neg) a = -a + b - 1;
1653-a = a / b * b;
1654-if (neg) a = -a;
1663+a -= c;
1664+if (neg) {
1665+if (mrb_int_sub_overflow(a, b, &c)) {
1666+#ifdef MRB_USE_BIGINT
1667+x = mrb_bint_new_int(mrb, a);
1668+return mrb_bint_sub(mrb, x, f);
1669+#else
1670+mrb_int_overflow(mrb, "floor");
1671+#endif
1672+ }
1673+a = c;
1674+ }
16551675return mrb_int_value(mrb, a);
16561676}
16571677@@ -1677,7 +1697,7 @@ int_round(mrb_state *mrb, mrb_value x)
16771697mrb_value r = mrb_bint_mod(mrb, x, f);
16781698mrb_value n = mrb_bint_sub(mrb, x, r);
16791699mrb_value h = mrb_bigint_p(f) ? mrb_bint_rshift(mrb, f, 1) : mrb_int_value(mrb, mrb_integer(f)>>1);
1680-mrb_int cmp = mrb_bigint_p(r) ? mrb_bint_cmp(mrb, r, h) : (mrb_integer(r) - mrb_integer(h));
1700+mrb_int cmp = mrb_bigint_p(r) ? mrb_bint_cmp(mrb, r, h) : (mrb_bigint_p(h) ? -mrb_bint_cmp(mrb, h, r) : (mrb_integer(r)-mrb_integer(h)));
16811701if ((cmp > 0) || (cmp == 0 && mrb_bint_cmp(mrb, x, mrb_fixnum_value(0)) > 0)) {
16821702n = mrb_as_bint(mrb, n);
16831703n = mrb_bint_add(mrb, n, f);
@@ -1687,10 +1707,35 @@ int_round(mrb_state *mrb, mrb_value x)
16871707#endif
16881708mrb_int a = mrb_integer(x);
16891709mrb_int b = mrb_integer(f);
1690-int neg = a < 0;
1691-if (neg) a = -a;
1692-a = (a + b / 2) / b * b;
1693-if (neg) a = -a;
1710+mrb_int c = a % b;
1711+a -= c;
1712+if (c < 0) {
1713+c = -c;
1714+if (b/2 < c) {
1715+if (mrb_int_sub_overflow(a, b, &c)) {
1716+#ifdef MRB_USE_BIGINT
1717+x = mrb_bint_new_int(mrb, a);
1718+return mrb_bint_sub(mrb, x, f);
1719+#else
1720+mrb_int_overflow(mrb, "round");
1721+#endif
1722+ }
1723+ }
1724+a = c;
1725+ }
1726+else {
1727+if (b/2 < c) {
1728+if (mrb_int_add_overflow(a, b, &c)) {
1729+#ifdef MRB_USE_BIGINT
1730+x = mrb_bint_new_int(mrb, a);
1731+return mrb_bint_add(mrb, x, f);
1732+#else
1733+mrb_int_overflow(mrb, "round");
1734+#endif
1735+ }
1736+ }
1737+a = c;
1738+ }
16941739return mrb_int_value(mrb, a);
16951740}
16961741@@ -1714,21 +1759,16 @@ int_truncate(mrb_state *mrb, mrb_value x)
17141759#ifdef MRB_USE_BIGINT
17151760if (mrb_bigint_p(x)) {
17161761mrb_value m = mrb_bint_mod(mrb, x, f);
1762+x = mrb_bint_sub_d(mrb, x, m);
17171763if (mrb_bint_cmp(mrb, x, mrb_fixnum_value(0)) < 0) {
1718-return mrb_bint_add(mrb, x, mrb_bint_sub(mrb, x, m));
1719- }
1720-else {
1721-return mrb_bint_sub(mrb, x, m);
1764+return mrb_bint_add(mrb, x, f);
17221765 }
1766+return x;
17231767 }
17241768#endif
17251769mrb_int a = mrb_integer(x);
17261770mrb_int b = mrb_integer(f);
1727-int neg = a < 0;
1728-if (neg) a = -a;
1729-a = a / b * b;
1730-if (neg) a = -a;
1731-return mrb_int_value(mrb, a);
1771+return mrb_int_value(mrb, a - (a % b));
17321772}
1733177317341774/* 15.2.8.3.23 */