зеркало из https://github.com/github/ruby.git
* ext/bigdecimal/bigdecimal.c (VpSetPTR): fix for limitation of the resulting
precision. * test/bigdecimal/test_bigdecimal.rb (test_limit): add tests for the above change. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@44153 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
7d3538db3f
Коммит
df33325192
|
@ -1,3 +1,11 @@
|
||||||
|
Wed Dec 13 02:00:00 2013 Kenta Murata <mrkn@mrkn.jp>
|
||||||
|
|
||||||
|
* ext/bigdecimal/bigdecimal.c (VpSetPTR): fix for limitation of the resulting
|
||||||
|
precision.
|
||||||
|
|
||||||
|
* test/bigdecimal/test_bigdecimal.rb (test_limit): add tests for the above
|
||||||
|
change.
|
||||||
|
|
||||||
Wed Dec 13 01:56:00 2013 Kenta Murata <mrkn@mrkn.jp>
|
Wed Dec 13 01:56:00 2013 Kenta Murata <mrkn@mrkn.jp>
|
||||||
|
|
||||||
* ext/bigdecimal/bigdecimal.c (VpAddAbs): put out a conditional branch from
|
* ext/bigdecimal/bigdecimal.c (VpAddAbs): put out a conditional branch from
|
||||||
|
|
|
@ -4189,6 +4189,7 @@ VpAddAbs(Real *a, Real *b, Real *c)
|
||||||
a_pos = ap;
|
a_pos = ap;
|
||||||
b_pos = bp;
|
b_pos = bp;
|
||||||
c_pos = cp;
|
c_pos = cp;
|
||||||
|
|
||||||
if (word_shift == (size_t)-1L) return 0; /* Overflow */
|
if (word_shift == (size_t)-1L) return 0; /* Overflow */
|
||||||
if (b_pos == (size_t)-1L) goto Assign_a;
|
if (b_pos == (size_t)-1L) goto Assign_a;
|
||||||
|
|
||||||
|
@ -4380,12 +4381,19 @@ static size_t
|
||||||
VpSetPTR(Real *a, Real *b, Real *c, size_t *a_pos, size_t *b_pos, size_t *c_pos, BDIGIT *av, BDIGIT *bv)
|
VpSetPTR(Real *a, Real *b, Real *c, size_t *a_pos, size_t *b_pos, size_t *c_pos, BDIGIT *av, BDIGIT *bv)
|
||||||
{
|
{
|
||||||
size_t left_word, right_word, word_shift;
|
size_t left_word, right_word, word_shift;
|
||||||
|
|
||||||
|
size_t const round_limit = (VpGetPrecLimit() + BASE_FIG - 1) / BASE_FIG;
|
||||||
|
|
||||||
|
assert(a->exponent >= b->expoennt);
|
||||||
|
|
||||||
c->frac[0] = 0;
|
c->frac[0] = 0;
|
||||||
*av = *bv = 0;
|
*av = *bv = 0;
|
||||||
|
|
||||||
word_shift = (a->exponent - b->exponent);
|
word_shift = (a->exponent - b->exponent);
|
||||||
left_word = b->Prec + word_shift;
|
left_word = b->Prec + word_shift;
|
||||||
right_word = Max(a->Prec, left_word);
|
right_word = Max(a->Prec, left_word);
|
||||||
left_word = c->MaxPrec - 1; /* -1 ... prepare for round up */
|
left_word = c->MaxPrec - 1; /* -1 ... prepare for round up */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* check if 'round' is needed.
|
* check if 'round' is needed.
|
||||||
*/
|
*/
|
||||||
|
@ -4408,7 +4416,9 @@ VpSetPTR(Real *a, Real *b, Real *c, size_t *a_pos, size_t *b_pos, size_t *c_pos,
|
||||||
* a_pos = |
|
* a_pos = |
|
||||||
*/
|
*/
|
||||||
*a_pos = left_word;
|
*a_pos = left_word;
|
||||||
*av = a->frac[*a_pos]; /* av is 'A' shown in above. */
|
if (*a_pos <= round_limit) {
|
||||||
|
*av = a->frac[*a_pos]; /* av is 'A' shown in above. */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/*
|
/*
|
||||||
|
@ -4427,7 +4437,9 @@ VpSetPTR(Real *a, Real *b, Real *c, size_t *a_pos, size_t *b_pos, size_t *c_pos,
|
||||||
*/
|
*/
|
||||||
if (c->MaxPrec >= word_shift + 1) {
|
if (c->MaxPrec >= word_shift + 1) {
|
||||||
*b_pos = c->MaxPrec - word_shift - 1;
|
*b_pos = c->MaxPrec - word_shift - 1;
|
||||||
*bv = b->frac[*b_pos];
|
if (*b_pos + word_shift <= round_limit) {
|
||||||
|
*bv = b->frac[*b_pos];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
*b_pos = -1L;
|
*b_pos = -1L;
|
||||||
|
|
|
@ -1151,6 +1151,25 @@ class TestBigDecimal < Test::Unit::TestCase
|
||||||
assert_equal(90, x ** 4) # OK? must it be 80?
|
assert_equal(90, x ** 4) # OK? must it be 80?
|
||||||
# 3 * 3 * 3 * 3 = 10 * 3 * 3 = 30 * 3 = 90 ???
|
# 3 * 3 * 3 * 3 = 10 * 3 * 3 = 30 * 3 = 90 ???
|
||||||
assert_raise(ArgumentError) { BigDecimal.limit(-1) }
|
assert_raise(ArgumentError) { BigDecimal.limit(-1) }
|
||||||
|
|
||||||
|
bug7458 = '[ruby-core:50269] [#7458]'
|
||||||
|
one = BigDecimal('1')
|
||||||
|
epsilon = BigDecimal('0.7E-18')
|
||||||
|
BigDecimal.save_limit do
|
||||||
|
BigDecimal.limit(0)
|
||||||
|
assert_equal(BigDecimal("1.0000000000000000007"), one + epsilon, "limit(0) #{bug7458}")
|
||||||
|
|
||||||
|
1.upto(18) do |lim|
|
||||||
|
BigDecimal.limit(lim)
|
||||||
|
assert_equal(BigDecimal("1.0"), one + epsilon, "limit(#{lim}) #{bug7458}")
|
||||||
|
end
|
||||||
|
|
||||||
|
BigDecimal.limit(19)
|
||||||
|
assert_equal(BigDecimal("1.000000000000000001"), one + epsilon, "limit(19) #{bug7458}")
|
||||||
|
|
||||||
|
BigDecimal.limit(20)
|
||||||
|
assert_equal(BigDecimal("1.0000000000000000007"), one + epsilon, "limit(20) #{bug7458}")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_sign
|
def test_sign
|
||||||
|
|
Загрузка…
Ссылка в новой задаче