@@ -926,41 +926,63 @@ abstract static class RoundNode extends PythonBinaryBuiltinNode {
926
926
* The logic is borrowed from Jython.
927
927
*/
928
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
+
929
950
@ Specialization
930
951
double round (double x , long n ) {
931
952
if (Double .isNaN (x ) || Double .isInfinite (x ) || x == 0.0 ) {
932
953
// nans, infinities and zeros round to themselves
933
954
return x ;
934
- } else {
935
- // (Slightly less than) n*log2(10).
936
- float nlog2_10 = 3.3219f * n ;
937
-
938
- // x = a * 2^b and a<2.
939
- int b = Math .getExponent (x );
940
-
941
- if (nlog2_10 > 52 - b ) {
942
- // When n*log2(10) > nmax, the lsb of abs(x) is >1, so x rounds to itself.
943
- return x ;
944
- } else if (nlog2_10 < -(b + 2 )) {
945
- // When n*log2(10) < -(b+2), abs(x)<0.5*10^n so x rounds to (signed) zero.
946
- return Math .copySign (0.0 , x );
947
- } else {
948
- // We have to work it out properly.
949
- BigDecimal xx = BigDecimal .valueOf (x );
950
- BigDecimal rr = xx .setScale ((int ) n , RoundingMode .HALF_UP );
951
- return rr .doubleValue ();
952
- }
953
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 ;
954
961
}
955
962
956
- @ TruffleBoundary
957
963
@ Specialization
958
964
double round (double x , PInt n ) {
959
- 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 );
960
974
}
961
975
962
976
@ Specialization
963
- 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
+ }
964
986
return (long ) round (x , 0 );
965
987
}
966
988
0 commit comments