@@ -458,9 +458,9 @@ private double doSpecialCases(double left, double right, BranchProfile negativeR
458
458
// v**(+/-)inf is 1.0 if abs(v) == 1, unlike on Java
459
459
return 1 ;
460
460
}
461
- if (left == 0 && right < 0 ) {
461
+ if (left == 0 && right < 0 && Double . isFinite ( right ) ) {
462
462
negativeRaise .enter ();
463
- // 0**w is an error if w is negative, unlike Java
463
+ // 0**w is an error if w is finite and negative, unlike Java
464
464
throw raise (PythonBuiltinClassType .ZeroDivisionError , ErrorMessages .POW_ZERO_CANNOT_RAISE_TO_NEGATIVE_POWER );
465
465
}
466
466
return 0 ;
@@ -480,7 +480,7 @@ private double doOperation(double left, double right, BranchProfile negativeRais
480
480
if (doSpecialCases (left , right , negativeRaise ) == 1 ) {
481
481
return 1.0 ;
482
482
}
483
- if (left < 0 && (right % 1 != 0 )) {
483
+ if (left < 0 && Double . isFinite ( left ) && Double . isFinite ( right ) && (right % 1 != 0 )) {
484
484
CompilerDirectives .transferToInterpreterAndInvalidate ();
485
485
// Negative numbers raised to fractional powers become complex.
486
486
throw new UnexpectedResultException (callPow .execute (frame , factory ().createComplex (left , 0 ), factory ().createComplex (right , 0 ), none ));
@@ -495,7 +495,7 @@ Object doDDToComplex(VirtualFrame frame, double left, double right, PNone none,
495
495
if (doSpecialCases (left , right , negativeRaise ) == 1 ) {
496
496
return 1.0 ;
497
497
}
498
- if (left < 0 && (right % 1 != 0 )) {
498
+ if (left < 0 && Double . isFinite ( left ) && Double . isFinite ( right ) && (right % 1 != 0 )) {
499
499
// Negative numbers raised to fractional powers become complex.
500
500
return callPow .execute (frame , factory ().createComplex (left , 0 ), factory ().createComplex (right , 0 ), none );
501
501
}
@@ -608,19 +608,19 @@ abstract static class DivModNode extends FloatBinaryBuiltinNode {
608
608
@ Specialization
609
609
PTuple doDL (double left , long right ) {
610
610
raiseDivisionByZero (right == 0 );
611
- return factory ().createTuple (new Object []{Math .floor (left / right ), left % right });
611
+ return factory ().createTuple (new Object []{Math .floor (left / right ), ModNode . op ( left , right ) });
612
612
}
613
613
614
614
@ Specialization
615
615
PTuple doDD (double left , double right ) {
616
616
raiseDivisionByZero (right == 0.0 );
617
- return factory ().createTuple (new Object []{Math .floor (left / right ), left % right });
617
+ return factory ().createTuple (new Object []{Math .floor (left / right ), ModNode . op ( left , right ) });
618
618
}
619
619
620
620
@ Specialization
621
621
PTuple doLD (long left , double right ) {
622
622
raiseDivisionByZero (right == 0.0 );
623
- return factory ().createTuple (new Object []{Math .floor (left / right ), left % right });
623
+ return factory ().createTuple (new Object []{Math .floor (left / right ), ModNode . op ( left , right ) });
624
624
}
625
625
626
626
@ Specialization (guards = {"accepts(left)" , "accepts(right)" })
@@ -820,42 +820,54 @@ public String hexD(double value) {
820
820
@ Builtin (name = __MOD__ , minNumOfPositionalArgs = 2 )
821
821
@ TypeSystemReference (PythonArithmeticTypes .class )
822
822
@ GenerateNodeFactory
823
- abstract static class ModNode extends FloatBinaryBuiltinNode {
823
+ public abstract static class ModNode extends FloatBinaryBuiltinNode {
824
824
@ Specialization
825
825
double doDL (double left , long right ) {
826
826
raiseDivisionByZero (right == 0 );
827
- return left % right ;
827
+ return op ( left , right ) ;
828
828
}
829
829
830
830
@ Specialization
831
831
double doDL (double left , PInt right ) {
832
832
raiseDivisionByZero (right .isZero ());
833
- return left % right .doubleValue ();
833
+ return op ( left , right .doubleValue () );
834
834
}
835
835
836
836
@ Specialization
837
837
double doDD (double left , double right ) {
838
838
raiseDivisionByZero (right == 0.0 );
839
- return left % right ;
839
+ return op ( left , right ) ;
840
840
}
841
841
842
842
@ Specialization
843
843
double doLD (long left , double right ) {
844
844
raiseDivisionByZero (right == 0.0 );
845
- return left % right ;
845
+ return op ( left , right ) ;
846
846
}
847
847
848
848
@ Specialization
849
849
double doPiD (PInt left , double right ) {
850
850
raiseDivisionByZero (right == 0.0 );
851
- return left .doubleValue () % right ;
851
+ return op ( left .doubleValue (), right ) ;
852
852
}
853
853
854
854
@ SuppressWarnings ("unused" )
855
855
@ Fallback
856
856
PNotImplemented doGeneric (Object right , Object left ) {
857
857
return PNotImplemented .NOT_IMPLEMENTED ;
858
858
}
859
+
860
+ public static double op (double left , double right ) {
861
+ double mod = left % right ;
862
+ if (mod != 0.0 ) {
863
+ if ((right < 0 ) != (mod < 0 )) {
864
+ mod += right ;
865
+ }
866
+ } else {
867
+ mod = right < 0 ? -0.0 : 0.0 ;
868
+ }
869
+ return mod ;
870
+ }
859
871
}
860
872
861
873
@ Builtin (name = __RTRUEDIV__ , minNumOfPositionalArgs = 2 , reverseOperation = true )
@@ -914,41 +926,63 @@ abstract static class RoundNode extends PythonBinaryBuiltinNode {
914
926
* The logic is borrowed from Jython.
915
927
*/
916
928
@ TruffleBoundary
929
+ private static double op (double x , long n ) {
930
+ // (Slightly less than) n*log2(10).
931
+ float nlog2_10 = 3.3219f * n ;
932
+
933
+ // x = a * 2^b and a<2.
934
+ int b = Math .getExponent (x );
935
+
936
+ if (nlog2_10 > 52 - b ) {
937
+ // When n*log2(10) > nmax, the lsb of abs(x) is >1, so x rounds to itself.
938
+ return x ;
939
+ } else if (nlog2_10 < -(b + 2 )) {
940
+ // When n*log2(10) < -(b+2), abs(x)<0.5*10^n so x rounds to (signed) zero.
941
+ return Math .copySign (0.0 , x );
942
+ } else {
943
+ // We have to work it out properly.
944
+ BigDecimal xx = BigDecimal .valueOf (x );
945
+ BigDecimal rr = xx .setScale ((int ) n , RoundingMode .HALF_UP );
946
+ return rr .doubleValue ();
947
+ }
948
+ }
949
+
917
950
@ Specialization
918
951
double round (double x , long n ) {
919
952
if (Double .isNaN (x ) || Double .isInfinite (x ) || x == 0.0 ) {
920
953
// nans, infinities and zeros round to themselves
921
954
return x ;
922
- } else {
923
- // (Slightly less than) n*log2(10).
924
- float nlog2_10 = 3.3219f * n ;
925
-
926
- // x = a * 2^b and a<2.
927
- int b = Math .getExponent (x );
928
-
929
- if (nlog2_10 > 52 - b ) {
930
- // When n*log2(10) > nmax, the lsb of abs(x) is >1, so x rounds to itself.
931
- return x ;
932
- } else if (nlog2_10 < -(b + 2 )) {
933
- // When n*log2(10) < -(b+2), abs(x)<0.5*10^n so x rounds to (signed) zero.
934
- return Math .copySign (0.0 , x );
935
- } else {
936
- // We have to work it out properly.
937
- BigDecimal xx = BigDecimal .valueOf (x );
938
- BigDecimal rr = xx .setScale ((int ) n , RoundingMode .HALF_UP );
939
- return rr .doubleValue ();
940
- }
941
955
}
956
+ double d = op (x , n );
957
+ if (Double .isInfinite (d )) {
958
+ throw raise (OverflowError , ErrorMessages .ROUNDED_VALUE_TOO_LARGE );
959
+ }
960
+ return d ;
942
961
}
943
962
944
- @ TruffleBoundary
945
963
@ Specialization
946
964
double round (double x , PInt n ) {
947
- return round (x , n .longValue ());
965
+ long nLong ;
966
+ if (n .compareTo (Long .MAX_VALUE ) > 0 ) {
967
+ nLong = Long .MAX_VALUE ;
968
+ } else if (n .compareTo (Long .MIN_VALUE ) < 0 ) {
969
+ nLong = Long .MIN_VALUE ;
970
+ } else {
971
+ nLong = n .longValue ();
972
+ }
973
+ return round (x , nLong );
948
974
}
949
975
950
976
@ Specialization
951
- long round (double x , @ SuppressWarnings ("unused" ) PNone none ) {
977
+ long round (double x , @ SuppressWarnings ("unused" ) PNone none ,
978
+ @ Cached ("createBinaryProfile()" ) ConditionProfile nanProfile ,
979
+ @ Cached ("createBinaryProfile()" ) ConditionProfile infProfile ) {
980
+ if (nanProfile .profile (Double .isNaN (x ))) {
981
+ throw raise (PythonErrorType .ValueError , ErrorMessages .CANNOT_CONVERT_S_TO_INT , "float NaN" );
982
+ }
983
+ if (infProfile .profile (Double .isInfinite (x ))) {
984
+ throw raise (PythonErrorType .OverflowError , ErrorMessages .CANNOT_CONVERT_S_TO_INT , "float infinity" );
985
+ }
952
986
return (long ) round (x , 0 );
953
987
}
954
988
@@ -1541,4 +1575,19 @@ protected void raiseDivisionByZero(boolean cond) {
1541
1575
}
1542
1576
}
1543
1577
}
1578
+
1579
+ @ Builtin (name = "is_integer" , minNumOfPositionalArgs = 1 )
1580
+ @ GenerateNodeFactory
1581
+ abstract static class IsIntegerNode extends PythonUnaryBuiltinNode {
1582
+ @ Specialization
1583
+ boolean isInteger (double value ) {
1584
+ return Double .isFinite (value ) && (long ) value == value ;
1585
+ }
1586
+
1587
+ @ Specialization
1588
+ boolean trunc (PFloat pValue ) {
1589
+ return isInteger (pValue .getValue ());
1590
+ }
1591
+
1592
+ }
1544
1593
}
0 commit comments