@@ -393,13 +393,17 @@ QuadPrecision_is_integer(QuadPrecisionObject *self, PyObject *Py_UNUSED(ignored)
393393 value = self -> value .sleef_value ;
394394 }
395395 else {
396+ // lets also tackle ld from sleef functions as well
396397 value = Sleef_cast_from_doubleq1 ((double )self -> value .longdouble_value );
397398 }
398399
400+ if (Sleef_iunordq1 (value , value )) {
401+ Py_RETURN_FALSE ;
402+ }
403+
399404 // Check if value is finite (not inf or nan)
400- // Using the same approach as quad_isfinite: abs(x) < inf
401405 Sleef_quad abs_value = Sleef_fabsq1 (value );
402- Sleef_quad pos_inf = Sleef_cast_from_doubleq1 ( INFINITY );
406+ Sleef_quad pos_inf = sleef_q ( +0x1000000000000LL , 0x0000000000000000ULL , 16384 );
403407 int32_t is_finite = Sleef_icmpltq1 (abs_value , pos_inf );
404408
405409 if (!is_finite ) {
@@ -421,179 +425,7 @@ QuadPrecision_is_integer(QuadPrecisionObject *self, PyObject *Py_UNUSED(ignored)
421425static PyObject *
422426QuadPrecision_as_integer_ratio (QuadPrecisionObject * self , PyObject * Py_UNUSED (ignored ))
423427{
424- Sleef_quad value ;
425-
426- if (self -> backend == BACKEND_SLEEF ) {
427- value = self -> value .sleef_value ;
428- }
429- else {
430- value = Sleef_cast_from_doubleq1 ((double )self -> value .longdouble_value );
431- }
432-
433- // Check for infinity using: abs(x) == inf
434- Sleef_quad abs_value = Sleef_fabsq1 (value );
435- Sleef_quad pos_inf = Sleef_cast_from_doubleq1 (INFINITY );
436- int32_t is_inf = Sleef_icmpeqq1 (abs_value , pos_inf );
437-
438- if (is_inf ) {
439- PyErr_SetString (PyExc_OverflowError , "cannot convert Infinity to integer ratio" );
440- return NULL ;
441- }
442-
443- // Check for NaN using: x != x (NaN property)
444- int32_t is_nan = !Sleef_icmpeqq1 (value , value );
445-
446- if (is_nan ) {
447- PyErr_SetString (PyExc_ValueError , "cannot convert NaN to integer ratio" );
448- return NULL ;
449- }
450-
451- // Handle zero
452- Sleef_quad zero = Sleef_cast_from_int64q1 (0 );
453- if (Sleef_icmpeqq1 (value , zero )) {
454- PyObject * numerator = PyLong_FromLong (0 );
455- PyObject * denominator = PyLong_FromLong (1 );
456- if (!numerator || !denominator ) {
457- Py_XDECREF (numerator );
458- Py_XDECREF (denominator );
459- return NULL ;
460- }
461- PyObject * result = PyTuple_Pack (2 , numerator , denominator );
462- Py_DECREF (numerator );
463- Py_DECREF (denominator );
464- return result ;
465- }
466-
467- // Remember the sign and work with absolute value
468- int is_negative = Sleef_icmpltq1 (value , zero );
469- abs_value = Sleef_fabsq1 (value );
470-
471- // Extract mantissa and exponent using frexp
472- // frexp returns value = mantissa * 2^exponent, where 0.5 <= |mantissa| < 1
473- int exponent ;
474- Sleef_quad mantissa = Sleef_frexpq1 (abs_value , & exponent );
475-
476- // For quad precision, we have 113 bits of precision
477- // Scale mantissa by 2^113 to get all significant bits as an integer
478- const int QUAD_MANT_DIG = 113 ;
479-
480- // We'll build the numerator by converting the mantissa to a hex string
481- // and parsing it, which preserves all the precision
482- char hex_buffer [64 ];
483- Sleef_snprintf (hex_buffer , sizeof (hex_buffer ), "%.28Qa" , mantissa );
484-
485- // Parse the hex representation to get exact mantissa bits
486- // The format is like "0x1.fffffp+0" or similar
487- // We need to extract the mantissa and exponent separately
488-
489- // Instead of using hex parsing (which is complex), let's use a different approach:
490- // Build the mantissa as an integer by extracting 64-bit chunks
491-
492- // Multiply mantissa by 2^113 to shift all bits into the integer part
493- Sleef_quad scaled = Sleef_ldexpq1 (mantissa , QUAD_MANT_DIG );
494-
495- // Now extract the integer value in two 64-bit chunks
496- // First get the upper 64 bits
497- Sleef_quad two_64 = Sleef_cast_from_doubleq1 (18446744073709551616.0 ); // 2^64
498- Sleef_quad upper_part = Sleef_floorq1 (Sleef_divq1_u05 (scaled , two_64 ));
499- uint64_t upper_bits = Sleef_cast_to_uint64q1 (upper_part );
500-
501- // Get the lower 64 bits
502- Sleef_quad lower_part_quad = Sleef_subq1_u05 (scaled , Sleef_mulq1_u05 (upper_part , two_64 ));
503- uint64_t lower_bits = Sleef_cast_to_uint64q1 (lower_part_quad );
504-
505- // Build Python integer from the two 64-bit parts
506- PyObject * upper_py = PyLong_FromUnsignedLongLong (upper_bits );
507- if (!upper_py ) {
508- return NULL ;
509- }
510-
511- PyObject * shift_64 = PyLong_FromLong (64 );
512- if (!shift_64 ) {
513- Py_DECREF (upper_py );
514- return NULL ;
515- }
516-
517- PyObject * shifted_upper = PyNumber_Lshift (upper_py , shift_64 );
518- Py_DECREF (upper_py );
519- Py_DECREF (shift_64 );
520- if (!shifted_upper ) {
521- return NULL ;
522- }
523-
524- PyObject * lower_py = PyLong_FromUnsignedLongLong (lower_bits );
525- if (!lower_py ) {
526- Py_DECREF (shifted_upper );
527- return NULL ;
528- }
529-
530- PyObject * numerator = PyNumber_Add (shifted_upper , lower_py );
531- Py_DECREF (shifted_upper );
532- Py_DECREF (lower_py );
533- if (!numerator ) {
534- return NULL ;
535- }
536-
537- // Calculate the final exponent
538- // value = mantissa * 2^exponent = (numerator / 2^113) * 2^exponent
539- // value = numerator * 2^(exponent - 113)
540- int final_exponent = exponent - QUAD_MANT_DIG ;
541-
542- PyObject * denominator ;
543- if (final_exponent >= 0 ) {
544- // Shift numerator left
545- PyObject * shift = PyLong_FromLong (final_exponent );
546- if (!shift ) {
547- Py_DECREF (numerator );
548- return NULL ;
549- }
550- PyObject * new_numerator = PyNumber_Lshift (numerator , shift );
551- Py_DECREF (shift );
552- Py_DECREF (numerator );
553- if (!new_numerator ) {
554- return NULL ;
555- }
556- numerator = new_numerator ;
557- denominator = PyLong_FromLong (1 );
558- }
559- else {
560- // Shift denominator left (denominator = 2^(-final_exponent))
561- PyObject * shift = PyLong_FromLong (- final_exponent );
562- if (!shift ) {
563- Py_DECREF (numerator );
564- return NULL ;
565- }
566- PyObject * one = PyLong_FromLong (1 );
567- if (!one ) {
568- Py_DECREF (shift );
569- Py_DECREF (numerator );
570- return NULL ;
571- }
572- denominator = PyNumber_Lshift (one , shift );
573- Py_DECREF (one );
574- Py_DECREF (shift );
575- if (!denominator ) {
576- Py_DECREF (numerator );
577- return NULL ;
578- }
579- }
580-
581- // Apply sign
582- if (is_negative ) {
583- PyObject * new_numerator = PyNumber_Negative (numerator );
584- Py_DECREF (numerator );
585- if (!new_numerator ) {
586- Py_DECREF (denominator );
587- return NULL ;
588- }
589- numerator = new_numerator ;
590- }
591428
592- // Create and return the tuple
593- PyObject * result = PyTuple_Pack (2 , numerator , denominator );
594- Py_DECREF (numerator );
595- Py_DECREF (denominator );
596- return result ;
597429}
598430
599431static PyMethodDef QuadPrecision_methods [] = {
0 commit comments