Skip to content

Commit 77d3b40

Browse files
committed
switch to npy_intp
1 parent 46878a0 commit 77d3b40

File tree

1 file changed

+19
-64
lines changed

1 file changed

+19
-64
lines changed

quaddtype/numpy_quaddtype/src/umath/binary_ops.cpp

Lines changed: 19 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -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
287287
static NPY_CASTING
288288
quad_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

Comments
 (0)