@@ -283,7 +283,7 @@ quad_generic_binop_2out_strided_loop_aligned(PyArrayMethod_Context *context, cha
283283}
284284
285285// todo: I'll preferrable get all this code duplication in templates later
286- // Special resolve descriptors for ldexp (QuadPrecDType, int32 ) -> QuadPrecDType
286+ // resolve descriptors for ldexp (QuadPrecDType, int ) -> QuadPrecDType
287287static NPY_CASTING
288288quad_ldexp_resolve_descriptors (PyObject *self, PyArray_DTypeMeta *const dtypes[],
289289 PyArray_Descr *const given_descrs[],
@@ -296,13 +296,9 @@ quad_ldexp_resolve_descriptors(PyObject *self, PyArray_DTypeMeta *const dtypes[]
296296 Py_INCREF (given_descrs[0 ]);
297297 loop_descrs[0 ] = given_descrs[0 ];
298298
299- // Input 1: int (no need to incref, it's a builtin dtype)
300- if (given_descrs[1 ] == NULL ) {
301- loop_descrs[1 ] = PyArray_DescrFromType (NPY_INT);
302- } else {
303- Py_INCREF (given_descrs[1 ]);
304- loop_descrs[1 ] = given_descrs[1 ];
305- }
299+ // Input 1: Use NPY_INTP (int64 on 64-bit, int32 on 32-bit) to match platform integer size
300+ // This ensures we can handle the full range of PyArray_PyLongDType without data loss
301+ loop_descrs[1 ] = PyArray_DescrFromType (NPY_INTP);
306302
307303 // Output: QuadPrecDType with same backend as input
308304 if (given_descrs[2 ] == NULL ) {
@@ -322,7 +318,8 @@ quad_ldexp_resolve_descriptors(PyObject *self, PyArray_DTypeMeta *const dtypes[]
322318 loop_descrs[2 ] = given_descrs[2 ];
323319 }
324320 }
325- return NPY_NO_CASTING;
321+ // Return SAFE_CASTING to allow conversion from other integer types to intp
322+ return NPY_SAFE_CASTING;
326323}
327324
328325// Strided loop for ldexp (unaligned)
@@ -333,9 +330,9 @@ quad_ldexp_strided_loop_unaligned(PyArrayMethod_Context *context, char *const da
333330 NpyAuxData *auxdata)
334331{
335332 npy_intp N = dimensions[0 ];
336- char *in1_ptr = data[0 ]; // quad
337- char *in2_ptr = data[1 ]; // int32
338- char *out_ptr = data[2 ]; // quad
333+ char *in1_ptr = data[0 ];
334+ char *in2_ptr = data[1 ];
335+ char *out_ptr = data[2 ];
339336 npy_intp in1_stride = strides[0 ];
340337 npy_intp in2_stride = strides[1 ];
341338 npy_intp out_stride = strides[2 ];
@@ -344,42 +341,18 @@ quad_ldexp_strided_loop_unaligned(PyArrayMethod_Context *context, char *const da
344341 QuadBackendType backend = descr->backend ;
345342 size_t elem_size = (backend == BACKEND_SLEEF) ? sizeof (Sleef_quad) : sizeof (long double );
346343
347- // Get the actual integer descriptor to determine its size
348- PyArray_Descr *int_descr = context->descriptors [1 ];
349- int int_size = int_descr->elsize ;
350-
351344 quad_value in1, out;
352- int in2;
345+ npy_intp in2_intp; // Platform-native integer (int64 on 64-bit, int32 on 32-bit)
353346 while (N--) {
354347 memcpy (&in1, in1_ptr, elem_size);
348+ memcpy (&in2_intp, in2_ptr, sizeof (npy_intp));
355349
356- // Read the integer value correctly based on its actual size
357- // to handle endianness properly
358- if (int_size == sizeof (npy_int32)) {
359- npy_int32 temp_int;
360- memcpy (&temp_int, in2_ptr, sizeof (npy_int32));
361- in2 = (int )temp_int;
362- } else if (int_size == sizeof (npy_int64)) {
363- npy_int64 temp_int;
364- memcpy (&temp_int, in2_ptr, sizeof (npy_int64));
365- in2 = (int )temp_int;
366- } else if (int_size == sizeof (npy_int16)) {
367- npy_int16 temp_int;
368- memcpy (&temp_int, in2_ptr, sizeof (npy_int16));
369- in2 = (int )temp_int;
370- } else if (int_size == sizeof (npy_int8)) {
371- npy_int8 temp_int;
372- memcpy (&temp_int, in2_ptr, sizeof (npy_int8));
373- in2 = (int )temp_int;
374- } else {
375- // Fallback for other sizes
376- memcpy (&in2, in2_ptr, sizeof (int ));
377- }
350+ int exp_value = (int )in2_intp;
378351
379352 if (backend == BACKEND_SLEEF) {
380- out.sleef_value = sleef_op (&in1.sleef_value , &in2 );
353+ out.sleef_value = sleef_op (&in1.sleef_value , &exp_value );
381354 } else {
382- out.longdouble_value = longdouble_op (&in1.longdouble_value , &in2 );
355+ out.longdouble_value = longdouble_op (&in1.longdouble_value , &exp_value );
383356 }
384357 memcpy (out_ptr, &out, elem_size);
385358
@@ -398,37 +371,19 @@ quad_ldexp_strided_loop_aligned(PyArrayMethod_Context *context, char *const data
398371 NpyAuxData *auxdata)
399372{
400373 npy_intp N = dimensions[0 ];
401- char *in1_ptr = data[0 ]; // quad
402- char *in2_ptr = data[1 ]; // int32
403- char *out_ptr = data[2 ]; // quad
374+ char *in1_ptr = data[0 ];
375+ char *in2_ptr = data[1 ];
376+ char *out_ptr = data[2 ];
404377 npy_intp in1_stride = strides[0 ];
405378 npy_intp in2_stride = strides[1 ];
406379 npy_intp out_stride = strides[2 ];
407380
408381 QuadPrecDTypeObject *descr = (QuadPrecDTypeObject *)context->descriptors [0 ];
409382 QuadBackendType backend = descr->backend ;
410383
411- // Get the actual integer descriptor to determine its size
412- PyArray_Descr *int_descr = context->descriptors [1 ];
413- int int_size = int_descr->elsize ;
414-
415384 while (N--) {
416- int exp_value;
417-
418- // Read the integer value correctly based on its actual size
419- // to handle endianness properly
420- if (int_size == sizeof (npy_int32)) {
421- exp_value = (int )(*(npy_int32 *)in2_ptr);
422- } else if (int_size == sizeof (npy_int64)) {
423- exp_value = (int )(*(npy_int64 *)in2_ptr);
424- } else if (int_size == sizeof (npy_int16)) {
425- exp_value = (int )(*(npy_int16 *)in2_ptr);
426- } else if (int_size == sizeof (npy_int8)) {
427- exp_value = (int )(*(npy_int8 *)in2_ptr);
428- } else {
429- // Fallback: cast directly (may not work on big-endian)
430- exp_value = *(int *)in2_ptr;
431- }
385+ npy_intp exp_intp = *(npy_intp *)in2_ptr;
386+ int exp_value = (int )exp_intp;
432387
433388 if (backend == BACKEND_SLEEF) {
434389 *(Sleef_quad *)out_ptr = sleef_op ((Sleef_quad *)in1_ptr, &exp_value);
0 commit comments