Skip to content

Commit 502fba0

Browse files
authored
Merge pull request #116 from SwayamInSync/fix-longdouble-padding-111
BUG: Canonicalize long-double padding across storage paths
2 parents ca9a2e8 + 8ebed7f commit 502fba0

9 files changed

Lines changed: 356 additions & 115 deletions

File tree

‎src/csrc/dtype.c‎

Lines changed: 8 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -23,36 +23,6 @@
2323
#include "constants.hpp"
2424
#include "utilities.h"
2525

26-
static inline int
27-
quad_load(void *x, char *data_ptr, QuadBackendType backend)
28-
{
29-
if (data_ptr == NULL || x == NULL) {
30-
return -1;
31-
}
32-
if (backend == BACKEND_SLEEF) {
33-
*(Sleef_quad *)x = *(Sleef_quad *)data_ptr;
34-
}
35-
else {
36-
*(long double *)x = *(long double *)data_ptr;
37-
}
38-
return 0;
39-
}
40-
41-
static inline int
42-
quad_store(char *data_ptr, void *x, QuadBackendType backend)
43-
{
44-
if (data_ptr == NULL || x == NULL) {
45-
return -1;
46-
}
47-
if (backend == BACKEND_SLEEF) {
48-
*(Sleef_quad *)data_ptr = *(Sleef_quad *)x;
49-
}
50-
else {
51-
*(long double *)data_ptr = *(long double *)x;
52-
}
53-
return 0;
54-
}
55-
5626
QuadPrecDTypeObject *
5727
new_quaddtype_instance(QuadBackendType backend)
5828
{
@@ -160,13 +130,7 @@ quadprec_setitem(QuadPrecDTypeObject *descr, PyObject *obj, char *dataptr)
160130
}
161131
}
162132

163-
if (quad_store(dataptr, &value->value, descr->backend) < 0) {
164-
Py_DECREF(value);
165-
char error_msg[100];
166-
snprintf(error_msg, sizeof(error_msg), "Invalid memory location %p", (void *)dataptr);
167-
PyErr_SetString(PyExc_ValueError, error_msg);
168-
return -1;
169-
}
133+
quad_value_store(dataptr, &value->value, descr->backend);
170134

171135
Py_DECREF(value);
172136
return 0;
@@ -179,13 +143,7 @@ quadprec_getitem(QuadPrecDTypeObject *descr, char *dataptr)
179143
if (!new) {
180144
return NULL;
181145
}
182-
if (quad_load(&new->value, dataptr, descr->backend) < 0) {
183-
Py_DECREF(new);
184-
char error_msg[100];
185-
snprintf(error_msg, sizeof(error_msg), "Invalid memory location %p", (void *)dataptr);
186-
PyErr_SetString(PyExc_ValueError, error_msg);
187-
return NULL;
188-
}
146+
quad_value_load_canonical(&new->value, dataptr, descr->backend);
189147
return (PyObject *)new;
190148
}
191149

@@ -315,9 +273,10 @@ quadprec_fill(void *buffer, npy_intp length, void *arr_)
315273
long double *buf = (long double *)buffer;
316274
long double start = buf[0];
317275
long double delta = buf[1] - start;
318-
276+
char *bytes = (char *)buffer;
277+
319278
for (i = 2; i < length; ++i) {
320-
buf[i] = start + i * delta;
279+
quad_longdouble_store(bytes + i * descr->base.elsize, start + i * delta);
321280
}
322281
}
323282

@@ -362,13 +321,8 @@ quadprec_scanfunc(FILE *fp, void *dptr, char *ignore, PyArray_Descr *descr_gener
362321
if (err < 0 || *endptr != '\0') {
363322
return 0; /* Return 0 on parse error (no items read) */
364323
}
365-
if (descr->backend == BACKEND_SLEEF) {
366-
*(Sleef_quad *)dptr = val.sleef_value;
367-
}
368-
else {
369-
*(long double *)dptr = val.longdouble_value;
370-
}
371-
324+
quad_value_store(dptr, &val, descr->backend);
325+
372326
return 1; /* Return 1 on success (1 item read) */
373327
}
374328

@@ -381,12 +335,7 @@ quadprec_fromstr(char *s, void *dptr, char **endptr, PyArray_Descr *descr_generi
381335
if (err < 0) {
382336
return -1;
383337
}
384-
if(descr->backend == BACKEND_SLEEF) {
385-
*(Sleef_quad *)dptr = val.sleef_value;
386-
}
387-
else {
388-
*(long double *)dptr = val.longdouble_value;
389-
}
338+
quad_value_store(dptr, &val, descr->backend);
390339
return 0;
391340
}
392341

‎src/csrc/scalar.c‎

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,7 @@ QuadPrecision_raw_new(QuadBackendType backend)
4343
}
4444
else {
4545
// An 80-bit long double occupies 16 bytes but writes only 10
46-
memset(&new->value, 0, sizeof(new->value));
47-
new->value.longdouble_value = 0.0L;
46+
quad_value_set_longdouble(&new->value, 0.0L);
4847
}
4948
return new;
5049
}
@@ -760,10 +759,16 @@ QuadPrecision_from_raw_bytes(PyObject *Py_UNUSED(module), PyObject *args)
760759
PyBuffer_Release(&view);
761760
return NULL;
762761
}
763-
unsigned char *dst = (backend == BACKEND_SLEEF)
764-
? (unsigned char *)&self->value.sleef_value
765-
: (unsigned char *)&self->value.longdouble_value;
766-
quad_copy_canonical(dst, (const unsigned char *)view.buf, expected);
762+
unsigned char raw[sizeof(quad_value)];
763+
quad_copy_canonical(raw, (const unsigned char *)view.buf, expected);
764+
if (backend == BACKEND_SLEEF) {
765+
memcpy(&self->value.sleef_value, raw, expected);
766+
}
767+
else {
768+
long double value;
769+
memcpy(&value, raw, expected);
770+
quad_value_set_longdouble(&self->value, value);
771+
}
767772
PyBuffer_Release(&view);
768773
return (PyObject *)self;
769774
}

‎src/csrc/umath/binary_ops.cpp‎

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -92,19 +92,17 @@ quad_generic_binop_strided_loop_unaligned(PyArrayMethod_Context *context, char *
9292

9393
QuadPrecDTypeObject *descr = (QuadPrecDTypeObject *)context->descriptors[0];
9494
QuadBackendType backend = descr->backend;
95-
size_t elem_size = (backend == BACKEND_SLEEF) ? sizeof(Sleef_quad) : sizeof(long double);
96-
9795
quad_value in1, in2, out;
9896
while (N--) {
99-
memcpy(&in1, in1_ptr, elem_size);
100-
memcpy(&in2, in2_ptr, elem_size);
97+
quad_value_load(&in1, in1_ptr, backend);
98+
quad_value_load(&in2, in2_ptr, backend);
10199
if (backend == BACKEND_SLEEF) {
102100
out.sleef_value = sleef_op(&in1.sleef_value, &in2.sleef_value);
103101
}
104102
else {
105103
out.longdouble_value = longdouble_op(&in1.longdouble_value, &in2.longdouble_value);
106104
}
107-
memcpy(out_ptr, &out, elem_size);
105+
quad_value_store(out_ptr, &out, backend);
108106

109107
in1_ptr += in1_stride;
110108
in2_ptr += in2_stride;
@@ -134,7 +132,8 @@ quad_generic_binop_strided_loop_aligned(PyArrayMethod_Context *context, char *co
134132
*(Sleef_quad *)out_ptr = sleef_op((Sleef_quad *)in1_ptr, (Sleef_quad *)in2_ptr);
135133
}
136134
else {
137-
*(long double *)out_ptr = longdouble_op((long double *)in1_ptr, (long double *)in2_ptr);
135+
quad_longdouble_store_aligned(
136+
out_ptr, longdouble_op((long double *)in1_ptr, (long double *)in2_ptr));
138137
}
139138

140139
in1_ptr += in1_stride;
@@ -222,21 +221,19 @@ quad_generic_binop_2out_strided_loop_unaligned(PyArrayMethod_Context *context, c
222221

223222
QuadPrecDTypeObject *descr = (QuadPrecDTypeObject *)context->descriptors[0];
224223
QuadBackendType backend = descr->backend;
225-
size_t elem_size = (backend == BACKEND_SLEEF) ? sizeof(Sleef_quad) : sizeof(long double);
226-
227224
quad_value in1, in2, out1, out2;
228225
while (N--) {
229-
memcpy(&in1, in1_ptr, elem_size);
230-
memcpy(&in2, in2_ptr, elem_size);
226+
quad_value_load(&in1, in1_ptr, backend);
227+
quad_value_load(&in2, in2_ptr, backend);
231228
if (backend == BACKEND_SLEEF) {
232229
sleef_op(&in1.sleef_value, &in2.sleef_value, &out1.sleef_value, &out2.sleef_value);
233230
}
234231
else {
235232
longdouble_op(&in1.longdouble_value, &in2.longdouble_value,
236233
&out1.longdouble_value, &out2.longdouble_value);
237234
}
238-
memcpy(out1_ptr, &out1, elem_size);
239-
memcpy(out2_ptr, &out2, elem_size);
235+
quad_value_store(out1_ptr, &out1, backend);
236+
quad_value_store(out2_ptr, &out2, backend);
240237

241238
in1_ptr += in1_stride;
242239
in2_ptr += in2_stride;
@@ -270,8 +267,10 @@ quad_generic_binop_2out_strided_loop_aligned(PyArrayMethod_Context *context, cha
270267
(Sleef_quad *)out1_ptr, (Sleef_quad *)out2_ptr);
271268
}
272269
else {
273-
longdouble_op((long double *)in1_ptr, (long double *)in2_ptr,
274-
(long double *)out1_ptr, (long double *)out2_ptr);
270+
long double out1, out2;
271+
longdouble_op((long double *)in1_ptr, (long double *)in2_ptr, &out1, &out2);
272+
quad_longdouble_store_aligned(out1_ptr, out1);
273+
quad_longdouble_store_aligned(out2_ptr, out2);
275274
}
276275

277276
in1_ptr += in1_stride;
@@ -338,12 +337,10 @@ quad_ldexp_strided_loop_unaligned(PyArrayMethod_Context *context, char *const da
338337

339338
QuadPrecDTypeObject *descr = (QuadPrecDTypeObject *)context->descriptors[0];
340339
QuadBackendType backend = descr->backend;
341-
size_t elem_size = (backend == BACKEND_SLEEF) ? sizeof(Sleef_quad) : sizeof(long double);
342-
343340
quad_value in1, out;
344341
npy_intp in2_intp; // Platform-native integer (int64 on 64-bit, int32 on 32-bit)
345342
while (N--) {
346-
memcpy(&in1, in1_ptr, elem_size);
343+
quad_value_load(&in1, in1_ptr, backend);
347344
memcpy(&in2_intp, in2_ptr, sizeof(npy_intp));
348345

349346
int exp_value = (int)in2_intp;
@@ -353,7 +350,7 @@ quad_ldexp_strided_loop_unaligned(PyArrayMethod_Context *context, char *const da
353350
} else {
354351
out.longdouble_value = longdouble_op(&in1.longdouble_value, &exp_value);
355352
}
356-
memcpy(out_ptr, &out, elem_size);
353+
quad_value_store(out_ptr, &out, backend);
357354

358355
in1_ptr += in1_stride;
359356
in2_ptr += in2_stride;
@@ -387,7 +384,8 @@ quad_ldexp_strided_loop_aligned(PyArrayMethod_Context *context, char *const data
387384
if (backend == BACKEND_SLEEF) {
388385
*(Sleef_quad *)out_ptr = sleef_op((Sleef_quad *)in1_ptr, &exp_value);
389386
} else {
390-
*(long double *)out_ptr = longdouble_op((long double *)in1_ptr, &exp_value);
387+
quad_longdouble_store_aligned(
388+
out_ptr, longdouble_op((long double *)in1_ptr, &exp_value));
391389
}
392390

393391
in1_ptr += in1_stride;

‎src/csrc/umath/matmul.cpp‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ naive_matmul_strided_loop(PyArrayMethod_Context *context, char *const data[],
470470
sum += a_val * b_val;
471471
}
472472

473-
memcpy(C_ij, &sum, sizeof(long double));
473+
quad_longdouble_store(C_ij, sum);
474474
}
475475
}
476476
}

‎src/csrc/umath/unary_ops.cpp‎

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -61,18 +61,16 @@ quad_generic_unary_op_strided_loop_unaligned(PyArrayMethod_Context *context, cha
6161

6262
QuadPrecDTypeObject *descr = (QuadPrecDTypeObject *)context->descriptors[0];
6363
QuadBackendType backend = descr->backend;
64-
size_t elem_size = (backend == BACKEND_SLEEF) ? sizeof(Sleef_quad) : sizeof(long double);
65-
6664
quad_value in, out;
6765
while (N--) {
68-
memcpy(&in, in_ptr, elem_size);
66+
quad_value_load(&in, in_ptr, backend);
6967
if (backend == BACKEND_SLEEF) {
7068
out.sleef_value = sleef_op(&in.sleef_value);
7169
}
7270
else {
7371
out.longdouble_value = longdouble_op(&in.longdouble_value);
7472
}
75-
memcpy(out_ptr, &out, elem_size);
73+
quad_value_store(out_ptr, &out, backend);
7674

7775
in_ptr += in_stride;
7876
out_ptr += out_stride;
@@ -100,7 +98,7 @@ quad_generic_unary_op_strided_loop_aligned(PyArrayMethod_Context *context, char
10098
*(Sleef_quad *)out_ptr = sleef_op((Sleef_quad *)in_ptr);
10199
}
102100
else {
103-
*(long double *)out_ptr = longdouble_op((long double *)in_ptr);
101+
quad_longdouble_store_aligned(out_ptr, longdouble_op((long double *)in_ptr));
104102
}
105103
in_ptr += in_stride;
106104
out_ptr += out_stride;
@@ -321,19 +319,17 @@ quad_generic_unary_op_2out_strided_loop_unaligned(PyArrayMethod_Context *context
321319

322320
QuadPrecDTypeObject *descr = (QuadPrecDTypeObject *)context->descriptors[0];
323321
QuadBackendType backend = descr->backend;
324-
size_t elem_size = (backend == BACKEND_SLEEF) ? sizeof(Sleef_quad) : sizeof(long double);
325-
326322
quad_value in, out1, out2;
327323
while (N--) {
328-
memcpy(&in, in_ptr, elem_size);
324+
quad_value_load(&in, in_ptr, backend);
329325
if (backend == BACKEND_SLEEF) {
330326
sleef_op(&in.sleef_value, &out1.sleef_value, &out2.sleef_value);
331327
}
332328
else {
333329
longdouble_op(&in.longdouble_value, &out1.longdouble_value, &out2.longdouble_value);
334330
}
335-
memcpy(out1_ptr, &out1, elem_size);
336-
memcpy(out2_ptr, &out2, elem_size);
331+
quad_value_store(out1_ptr, &out1, backend);
332+
quad_value_store(out2_ptr, &out2, backend);
337333

338334
in_ptr += in_stride;
339335
out1_ptr += out1_stride;
@@ -365,7 +361,10 @@ quad_generic_unary_op_2out_strided_loop_aligned(PyArrayMethod_Context *context,
365361
sleef_op((Sleef_quad *)in_ptr, (Sleef_quad *)out1_ptr, (Sleef_quad *)out2_ptr);
366362
}
367363
else {
368-
longdouble_op((long double *)in_ptr, (long double *)out1_ptr, (long double *)out2_ptr);
364+
long double out1, out2;
365+
longdouble_op((long double *)in_ptr, &out1, &out2);
366+
quad_longdouble_store_aligned(out1_ptr, out1);
367+
quad_longdouble_store_aligned(out2_ptr, out2);
369368
}
370369
in_ptr += in_stride;
371370
out1_ptr += out1_stride;
@@ -470,20 +469,18 @@ quad_frexp_strided_loop_unaligned(PyArrayMethod_Context *context, char *const da
470469

471470
QuadPrecDTypeObject *descr = (QuadPrecDTypeObject *)context->descriptors[0];
472471
QuadBackendType backend = descr->backend;
473-
size_t elem_size = (backend == BACKEND_SLEEF) ? sizeof(Sleef_quad) : sizeof(long double);
474-
475472
quad_value in, out_mantissa;
476473
int out_exp;
477474

478475
while (N--) {
479-
memcpy(&in, in_ptr, elem_size);
476+
quad_value_load(&in, in_ptr, backend);
480477
if (backend == BACKEND_SLEEF) {
481478
out_mantissa.sleef_value = sleef_op(&in.sleef_value, &out_exp);
482479
}
483480
else {
484481
out_mantissa.longdouble_value = longdouble_op(&in.longdouble_value, &out_exp);
485482
}
486-
memcpy(out_mantissa_ptr, &out_mantissa, elem_size);
483+
quad_value_store(out_mantissa_ptr, &out_mantissa, backend);
487484
memcpy(out_exp_ptr, &out_exp, sizeof(int));
488485

489486
in_ptr += in_stride;
@@ -520,7 +517,7 @@ quad_frexp_strided_loop_aligned(PyArrayMethod_Context *context, char *const data
520517
}
521518
else {
522519
long double mantissa = longdouble_op((long double *)in_ptr, &out_exp);
523-
memcpy(out_mantissa_ptr, &mantissa, sizeof(long double));
520+
quad_longdouble_store_aligned(out_mantissa_ptr, mantissa);
524521
}
525522
memcpy(out_exp_ptr, &out_exp, sizeof(int));
526523

‎src/csrc/utilities.c‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ cstring_to_quad_internal(const char *str, const char *start, QuadBackendType bac
158158
}
159159

160160
} else {
161-
out_value->longdouble_value = strtold(str, endptr);
161+
quad_value_set_longdouble(out_value, strtold(str, endptr));
162162
}
163163

164164
if (endptr && *endptr == str) {
@@ -218,7 +218,8 @@ NumPyOS_ascii_strtoq(const char *s, QuadBackendType backend, quad_value *out_val
218218
out_value->sleef_value = sign > 0 ? QUAD_PRECISION_INF : QUAD_PRECISION_NINF;
219219
}
220220
else {
221-
out_value->longdouble_value = sign > 0 ? strtold("inf", NULL) : strtold("-inf", NULL);
221+
quad_value_set_longdouble(out_value,
222+
sign > 0 ? strtold("inf", NULL) : strtold("-inf", NULL));
222223
}
223224

224225
if (endptr) {
@@ -252,7 +253,7 @@ NumPyOS_ascii_strtoq(const char *s, QuadBackendType backend, quad_value *out_val
252253
out_value->sleef_value = nan_val;
253254
}
254255
else {
255-
out_value->longdouble_value = sign < 0 ? -nanl("") : nanl("");
256+
quad_value_set_longdouble(out_value, sign < 0 ? -nanl("") : nanl(""));
256257
}
257258

258259
if (endptr) {

0 commit comments

Comments
 (0)