@@ -1223,13 +1223,25 @@ from_quad<spec_npy_bool>(const quad_value *x, QuadBackendType backend)
12231223 }
12241224}
12251225
1226+ // NumPy convention: casting NaN to any integer type yields 0.
1227+ // Without this, SLEEF saturates NaN to INT_MAX / UINT_MAX, and the
1228+ // long-double path invokes undefined behavior. See gh-98.
1229+ static inline bool
1230+ quad_is_nan (const quad_value *x, QuadBackendType backend)
1231+ {
1232+ if (backend == BACKEND_SLEEF ) {
1233+ return quad_isnan (&x->sleef_value );
1234+ }
1235+ return std::isnan (x->longdouble_value );
1236+ }
1237+
12261238template <>
12271239inline npy_byte
12281240from_quad<npy_byte>(const quad_value *x, QuadBackendType backend)
12291241{
1230- // runtime warnings often comes from/to casting of NaN, inf
1231- // casting is used by ops at several positions leading to warnings
1232- // fix can be catching the cases and returning corresponding type value without casting
1242+ if ( quad_is_nan (x, backend)) {
1243+ return (npy_byte) 0 ;
1244+ }
12331245 if (backend == BACKEND_SLEEF ) {
12341246 return (npy_byte)Sleef_cast_to_int64q1 (x->sleef_value );
12351247 }
@@ -1242,6 +1254,9 @@ template <>
12421254inline npy_ubyte
12431255from_quad<npy_ubyte>(const quad_value *x, QuadBackendType backend)
12441256{
1257+ if (quad_is_nan (x, backend)) {
1258+ return (npy_ubyte)0 ;
1259+ }
12451260 if (backend == BACKEND_SLEEF ) {
12461261 return (npy_ubyte)Sleef_cast_to_uint64q1 (x->sleef_value );
12471262 }
@@ -1254,6 +1269,9 @@ template <>
12541269inline npy_short
12551270from_quad<npy_short>(const quad_value *x, QuadBackendType backend)
12561271{
1272+ if (quad_is_nan (x, backend)) {
1273+ return (npy_short)0 ;
1274+ }
12571275 if (backend == BACKEND_SLEEF ) {
12581276 return (npy_short)Sleef_cast_to_int64q1 (x->sleef_value );
12591277 }
@@ -1266,6 +1284,9 @@ template <>
12661284inline npy_ushort
12671285from_quad<npy_ushort>(const quad_value *x, QuadBackendType backend)
12681286{
1287+ if (quad_is_nan (x, backend)) {
1288+ return (npy_ushort)0 ;
1289+ }
12691290 if (backend == BACKEND_SLEEF ) {
12701291 return (npy_ushort)Sleef_cast_to_uint64q1 (x->sleef_value );
12711292 }
@@ -1278,6 +1299,9 @@ template <>
12781299inline npy_int
12791300from_quad<npy_int>(const quad_value *x, QuadBackendType backend)
12801301{
1302+ if (quad_is_nan (x, backend)) {
1303+ return (npy_int)0 ;
1304+ }
12811305 if (backend == BACKEND_SLEEF ) {
12821306 return (npy_int)Sleef_cast_to_int64q1 (x->sleef_value );
12831307 }
@@ -1290,6 +1314,9 @@ template <>
12901314inline npy_uint
12911315from_quad<npy_uint>(const quad_value *x, QuadBackendType backend)
12921316{
1317+ if (quad_is_nan (x, backend)) {
1318+ return (npy_uint)0 ;
1319+ }
12931320 if (backend == BACKEND_SLEEF ) {
12941321 return (npy_uint)Sleef_cast_to_uint64q1 (x->sleef_value );
12951322 }
@@ -1302,6 +1329,9 @@ template <>
13021329inline npy_long
13031330from_quad<npy_long>(const quad_value *x, QuadBackendType backend)
13041331{
1332+ if (quad_is_nan (x, backend)) {
1333+ return (npy_long)0 ;
1334+ }
13051335 if (backend == BACKEND_SLEEF ) {
13061336 return (npy_long)Sleef_cast_to_int64q1 (x->sleef_value );
13071337 }
@@ -1314,6 +1344,9 @@ template <>
13141344inline npy_ulong
13151345from_quad<npy_ulong>(const quad_value *x, QuadBackendType backend)
13161346{
1347+ if (quad_is_nan (x, backend)) {
1348+ return (npy_ulong)0 ;
1349+ }
13171350 if (backend == BACKEND_SLEEF ) {
13181351 return (npy_ulong)Sleef_cast_to_uint64q1 (x->sleef_value );
13191352 }
@@ -1326,6 +1359,9 @@ template <>
13261359inline npy_longlong
13271360from_quad<npy_longlong>(const quad_value *x, QuadBackendType backend)
13281361{
1362+ if (quad_is_nan (x, backend)) {
1363+ return (npy_longlong)0 ;
1364+ }
13291365 if (backend == BACKEND_SLEEF ) {
13301366 return Sleef_cast_to_int64q1 (x->sleef_value );
13311367 }
@@ -1338,6 +1374,9 @@ template <>
13381374inline npy_ulonglong
13391375from_quad<npy_ulonglong>(const quad_value *x, QuadBackendType backend)
13401376{
1377+ if (quad_is_nan (x, backend)) {
1378+ return (npy_ulonglong)0 ;
1379+ }
13411380 if (backend == BACKEND_SLEEF ) {
13421381 return Sleef_cast_to_uint64q1 (x->sleef_value );
13431382 }
0 commit comments