Skip to content

Commit 6f1649e

Browse files
author
wyhaines
committed
ext/bigdecimal/bigdecimal.c: Backport ruby#2349 [ruby-core:26646]; fix comparisons. Also fix a bunch of bugs that lead to broken-ness and failing tests.
test/bigdecimal/test_bigdecimal.rb: Backport ruby#2349 [ruby-core:26646]; added a test suite. test/ruby/test_exception.rb: The test suite was breaking ZeroDivisionError, which in turn would break bigdecimal/test_bigdecimal.rb. Made a simple fix that keeps that test but does so non-destructively. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8_6@29025 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
1 parent 2176130 commit 6f1649e

File tree

6 files changed

+826
-36
lines changed

6 files changed

+826
-36
lines changed

ChangeLog

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
1+
Tue Aug 18 03:27:00 Kirk Haines <khaines@ruby-lang.org>
2+
3+
* ext/bigdecimal/bigdecimal.c: Backport #2349 [ruby-core:26646]; fix comparisons. Also fix a bunch of bugs that lead to broken-ness and failing tests.
4+
5+
* test/bigdecimal/test_bigdecimal.rb: Backport #2349 [ruby-core:26646]; added a test suite.
6+
7+
* test/ruby/test_exception.rb: The test suite was breaking ZeroDivisionError, which in turn would break bigdecimal/test_bigdecimal.rb. Made a simple fix that keeps that test but does so non-destructively.
8+
19
Wed Jun 23 04:26:00 Kirk Haines <khaines@ruby-lang.org>
210

3-
* io.c: Backport #2267 [ruby-core:26300]; Fix problem with IO so that the file position is correct after a direct write on BSDish platforms like OS X.
4-
* test/ruby/test_io.rb: Added a test for the fix.
11+
* io.c: Backport #2267 [ruby-core:26300]; Fix problem with IO so that the file position is correct after a direct write on BSDish platforms like OS X. r28393
12+
* test/ruby/test_io.rb: Added a test for the fix. r28393
513

614
Wed Jun 23 02:07:00 Kirk Haines <khaines@ruby-lang.org>
715

ext/bigdecimal/bigdecimal.c

Lines changed: 100 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -414,11 +414,22 @@ BigDecimal_mode(int argc, VALUE *argv, VALUE self)
414414
VpSetException((unsigned short)((val==Qtrue)?(fo|VP_EXCEPTION_INFINITY):
415415
(fo&(~VP_EXCEPTION_INFINITY))));
416416
}
417+
fo = VpGetException();
417418
if(f&VP_EXCEPTION_NaN) {
418419
VpSetException((unsigned short)((val==Qtrue)?(fo|VP_EXCEPTION_NaN):
419420
(fo&(~VP_EXCEPTION_NaN))));
420421
}
421422
fo = VpGetException();
423+
if(f&VP_EXCEPTION_UNDERFLOW) {
424+
VpSetException((unsigned short)((val==Qtrue)?(fo|VP_EXCEPTION_UNDERFLOW):
425+
(fo&(~VP_EXCEPTION_UNDERFLOW))));
426+
}
427+
fo = VpGetException();
428+
if(f&VP_EXCEPTION_ZERODIVIDE) {
429+
VpSetException((unsigned short)((val==Qtrue)?(fo|VP_EXCEPTION_ZERODIVIDE):
430+
(fo&(~VP_EXCEPTION_ZERODIVIDE))));
431+
}
432+
fo = VpGetException();
422433
return INT2FIX(fo);
423434
}
424435
if(VP_ROUND_MODE==f) {
@@ -533,14 +544,11 @@ BigDecimal_to_i(VALUE self)
533544

534545
/* Infinity or NaN not converted. */
535546
if(VpIsNaN(p)) {
536-
VpException(VP_EXCEPTION_NaN,"Computation results to 'NaN'(Not a Number)",0);
537-
return Qnil;
547+
VpException(VP_EXCEPTION_NaN,"Computation results to 'NaN'(Not a Number)",1);
538548
} else if(VpIsPosInf(p)) {
539-
VpException(VP_EXCEPTION_INFINITY,"Computation results to 'Infinity'",0);
540-
return Qnil;
549+
VpException(VP_EXCEPTION_INFINITY,"Computation results to 'Infinity'",1);
541550
} else if(VpIsNegInf(p)) {
542-
VpException(VP_EXCEPTION_INFINITY,"Computation results to '-Infinity'",0);
543-
return Qnil;
551+
VpException(VP_EXCEPTION_INFINITY,"Computation results to '-Infinity'",1);
544552
}
545553

546554
e = VpExponent10(p);
@@ -732,6 +740,7 @@ BigDecimal_sub(VALUE self, VALUE r)
732740
return ToValue(c);
733741
}
734742

743+
/*
735744
static VALUE
736745
BigDecimalCmp(VALUE self, VALUE r,char op)
737746
{
@@ -746,7 +755,7 @@ BigDecimalCmp(VALUE self, VALUE r,char op)
746755
if(e==999) return Qnil;
747756
switch(op)
748757
{
749-
case '*': return INT2FIX(e); /* any op */
758+
case '*': return INT2FIX(e);
750759
case '=': if(e==0) return Qtrue ; return Qfalse;
751760
case '!': if(e!=0) return Qtrue ; return Qfalse;
752761
case 'G': if(e>=0) return Qtrue ; return Qfalse;
@@ -756,6 +765,48 @@ BigDecimalCmp(VALUE self, VALUE r,char op)
756765
}
757766
rb_bug("Undefined operation in BigDecimalCmp()");
758767
}
768+
*/
769+
770+
771+
static VALUE
772+
BigDecimalCmp(VALUE self, VALUE r,char op)
773+
{
774+
ENTER(5);
775+
S_INT e;
776+
Real *a, *b;
777+
GUARD_OBJ(a,GetVpValue(self,1));
778+
b = GetVpValue(r,0);
779+
if(!b) {
780+
ID f = 0;
781+
782+
switch(op)
783+
{
784+
/* case '*': return rb_num_coerce_cmp(self,r,rb_intern("<=>")); */
785+
case '*': return rb_num_coerce_cmp(self,r);
786+
/* case '=': return RTEST(rb_num_coerce_cmp(self,r,rb_intern("=="))) ? Qtrue : Qfalse; */
787+
case '=': return RTEST(rb_num_coerce_cmp(self,r)) ? Qtrue : Qfalse;
788+
case 'G': f = rb_intern(">="); break;
789+
case 'L': f = rb_intern("<="); break;
790+
case '>': case '<': f = (ID)op; break;
791+
}
792+
/* return rb_num_coerce_relop(self,r,f); */
793+
return rb_num_coerce_relop(self,r);
794+
}
795+
SAVE(b);
796+
e = VpComp(a, b);
797+
if(e==999) return (op == '*') ? Qnil : Qfalse;
798+
switch(op)
799+
{
800+
case '*': return INT2FIX(e); /* any op */
801+
case '=': if(e==0) return Qtrue ; return Qfalse;
802+
case 'G': if(e>=0) return Qtrue ; return Qfalse;
803+
case '>': if(e> 0) return Qtrue ; return Qfalse;
804+
case 'L': if(e<=0) return Qtrue ; return Qfalse;
805+
case '<': if(e< 0) return Qtrue ; return Qfalse;
806+
}
807+
rb_bug("Undefined operation in BigDecimalCmp()");
808+
}
809+
759810

760811
/* Returns True if the value is zero. */
761812
static VALUE
@@ -962,7 +1013,9 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
9621013

9631014
if(VpIsNaN(a) || VpIsNaN(b)) goto NaN;
9641015
if(VpIsInf(a) || VpIsInf(b)) goto NaN;
965-
if(VpIsZero(b)) goto NaN;
1016+
if(VpIsZero(b)) {
1017+
rb_raise(rb_eZeroDivError, "divided by 0");
1018+
}
9661019
if(VpIsZero(a)) {
9671020
GUARD_OBJ(c,VpCreateRbObject(1, "0"));
9681021
GUARD_OBJ(d,VpCreateRbObject(1, "0"));
@@ -2105,9 +2158,9 @@ VpGetRoundMode(void)
21052158
VP_EXPORT int
21062159
VpIsRoundMode(unsigned long n)
21072160
{
2108-
if(n==VP_ROUND_UP || n!=VP_ROUND_DOWN ||
2109-
n==VP_ROUND_HALF_UP || n!=VP_ROUND_HALF_DOWN ||
2110-
n==VP_ROUND_CEIL || n!=VP_ROUND_FLOOR ||
2161+
if(n==VP_ROUND_UP || n==VP_ROUND_DOWN ||
2162+
n==VP_ROUND_HALF_UP || n==VP_ROUND_HALF_DOWN ||
2163+
n==VP_ROUND_CEIL || n==VP_ROUND_FLOOR ||
21112164
n==VP_ROUND_HALF_EVEN
21122165
) return 1;
21132166
return 0;
@@ -2225,18 +2278,12 @@ VpException(unsigned short f, const char *str,int always)
22252278
switch(f)
22262279
{
22272280
/*
2228-
case VP_EXCEPTION_ZERODIVIDE:
22292281
case VP_EXCEPTION_OVERFLOW:
22302282
*/
2283+
case VP_EXCEPTION_ZERODIVIDE:
22312284
case VP_EXCEPTION_INFINITY:
2232-
exc = rb_eFloatDomainError;
2233-
goto raise;
22342285
case VP_EXCEPTION_NaN:
2235-
exc = rb_eFloatDomainError;
2236-
goto raise;
22372286
case VP_EXCEPTION_UNDERFLOW:
2238-
exc = rb_eFloatDomainError;
2239-
goto raise;
22402287
case VP_EXCEPTION_OP:
22412288
exc = rb_eFloatDomainError;
22422289
goto raise;
@@ -3924,14 +3971,15 @@ VpCtoV(Real *a, const char *int_chr, U_LONG ni, const char *frac, U_LONG nf, con
39243971
{
39253972
U_LONG i, j, ind_a, ma, mi, me;
39263973
U_LONG loc;
3927-
S_INT e,es, eb, ef;
3928-
S_INT sign, signe;
3974+
S_LONG e,es, eb, ef;
3975+
S_INT sign, signe, exponent_overflow;
39293976
/* get exponent part */
39303977
e = 0;
39313978
ma = a->MaxPrec;
39323979
mi = ni;
39333980
me = ne;
39343981
signe = 1;
3982+
exponent_overflow = 0;
39353983
memset(a->frac, 0, ma * sizeof(U_LONG));
39363984
if(ne > 0) {
39373985
i = 0;
@@ -3946,8 +3994,10 @@ VpCtoV(Real *a, const char *int_chr, U_LONG ni, const char *frac, U_LONG nf, con
39463994
while(i < me) {
39473995
es = e*((S_INT)BASE_FIG);
39483996
e = e * 10 + exp_chr[i] - '0';
3949-
if(es>e*((S_INT)BASE_FIG)) {
3950-
return VpException(VP_EXCEPTION_INFINITY,"exponent overflow",0);
3997+
if(es > (S_INT)(e*BASE_FIG)) {
3998+
exponent_overflow = 1;
3999+
e = es; /* keep sign */
4000+
break;
39514001
}
39524002
++i;
39534003
}
@@ -3956,7 +4006,7 @@ VpCtoV(Real *a, const char *int_chr, U_LONG ni, const char *frac, U_LONG nf, con
39564006
/* get integer part */
39574007
i = 0;
39584008
sign = 1;
3959-
if(ni >= 0) {
4009+
if(1 /*ni >= 0*/) {
39604010
if(int_chr[0] == '-') {
39614011
sign = -1;
39624012
++i;
@@ -3989,6 +4039,18 @@ VpCtoV(Real *a, const char *int_chr, U_LONG ni, const char *frac, U_LONG nf, con
39894039

39904040
eb = e / ((S_INT)BASE_FIG);
39914041

4042+
if(exponent_overflow) {
4043+
int zero = 1;
4044+
for( ; i < mi && zero; i++) zero = int_chr[i] == '0';
4045+
for(i = 0; i < nf && zero; i++) zero = frac[i] == '0';
4046+
if(!zero && signe > 0) {
4047+
VpSetInf(a, sign);
4048+
VpException(VP_EXCEPTION_INFINITY,"exponent overflow",0);
4049+
}
4050+
else VpSetZero(a, sign);
4051+
return 1;
4052+
}
4053+
39924054
ind_a = 0;
39934055
while(i < mi) {
39944056
a->frac[ind_a] = 0;
@@ -4032,7 +4094,7 @@ VpCtoV(Real *a, const char *int_chr, U_LONG ni, const char *frac, U_LONG nf, con
40324094
++j;
40334095
}
40344096
a->Prec = ind_a + 1;
4035-
a->exponent = eb;
4097+
a->exponent = (S_INT)eb;
40364098
VpSetSign(a,sign);
40374099
VpNmlz(a);
40384100
return 1;
@@ -4633,8 +4695,20 @@ VpPower(Real *y, Real *x, S_INT n)
46334695
}
46344696
goto Exit;
46354697
}
4636-
if(!VpIsDef(x)) {
4637-
VpSetNaN(y); /* Not sure !!! */
4698+
if(VpIsNaN(x)) {
4699+
VpSetNaN(y);
4700+
goto Exit;
4701+
}
4702+
if(VpIsInf(x)) {
4703+
if(n==0) {
4704+
VpSetOne(y);
4705+
goto Exit;
4706+
}
4707+
if(n>0) {
4708+
VpSetInf(y, (n%2==0 || VpIsPosInf(x)) ? 1 : -1);
4709+
goto Exit;
4710+
}
4711+
VpSetZero(y, (n%2==0 || VpIsPosInf(x)) ? 1 : -1);
46384712
goto Exit;
46394713
}
46404714

ext/bigdecimal/bigdecimal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ extern "C" {
4545
#define VP_EXCEPTION_NaN ((unsigned short)0x0002)
4646
#define VP_EXCEPTION_UNDERFLOW ((unsigned short)0x0004)
4747
#define VP_EXCEPTION_OVERFLOW ((unsigned short)0x0001) /* 0x0008) */
48-
#define VP_EXCEPTION_ZERODIVIDE ((unsigned short)0x0001) /* 0x0010) */
48+
#define VP_EXCEPTION_ZERODIVIDE ((unsigned short)0x0010)
4949

5050
/* Following 2 exceptions cann't controlled by user */
5151
#define VP_EXCEPTION_OP ((unsigned short)0x0020)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy