Skip to content

Commit 672be17

Browse files
committed
added aligned and unaligned casting loops
1 parent 2fd9cad commit 672be17

File tree

2 files changed

+119
-19
lines changed

2 files changed

+119
-19
lines changed

quaddtype/numpy_quaddtype/src/casts.cpp

Lines changed: 119 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ quad_to_quad_resolve_descriptors(PyObject *NPY_UNUSED(self),
4949
}
5050

5151
static int
52-
quad_to_quad_strided_loop(PyArrayMethod_Context *context, char *const data[],
53-
npy_intp const dimensions[], npy_intp const strides[],
54-
void *NPY_UNUSED(auxdata))
52+
quad_to_quad_strided_loop_unaligned(PyArrayMethod_Context *context, char *const data[],
53+
npy_intp const dimensions[], npy_intp const strides[],
54+
void *NPY_UNUSED(auxdata))
5555
{
5656
npy_intp N = dimensions[0];
5757
char *in_ptr = data[0];
@@ -79,6 +79,44 @@ quad_to_quad_strided_loop(PyArrayMethod_Context *context, char *const data[],
7979
return 0;
8080
}
8181

82+
static int
83+
quad_to_quad_strided_loop_aligned(PyArrayMethod_Context *context, char *const data[],
84+
npy_intp const dimensions[], npy_intp const strides[],
85+
void *NPY_UNUSED(auxdata))
86+
{
87+
npy_intp N = dimensions[0];
88+
char *in_ptr = data[0];
89+
char *out_ptr = data[1];
90+
npy_intp in_stride = strides[0];
91+
npy_intp out_stride = strides[1];
92+
93+
QuadPrecDTypeObject *descr_in = (QuadPrecDTypeObject *)context->descriptors[0];
94+
QuadPrecDTypeObject *descr_out = (QuadPrecDTypeObject *)context->descriptors[1];
95+
96+
if (descr_in->backend != descr_out->backend) {
97+
PyErr_SetString(PyExc_TypeError,
98+
"Cannot convert between different quad-precision backends");
99+
return -1;
100+
}
101+
102+
if (descr_in->backend == BACKEND_SLEEF) {
103+
while (N--) {
104+
*(Sleef_quad *)out_ptr = *(Sleef_quad *)in_ptr;
105+
in_ptr += in_stride;
106+
out_ptr += out_stride;
107+
}
108+
}
109+
else {
110+
while (N--) {
111+
*(long double *)out_ptr = *(long double *)in_ptr;
112+
in_ptr += in_stride;
113+
out_ptr += out_stride;
114+
}
115+
}
116+
117+
return 0;
118+
}
119+
82120
// Casting from other types to QuadDType
83121

84122
template <typename T>
@@ -290,9 +328,9 @@ numpy_to_quad_resolve_descriptors(PyObject *NPY_UNUSED(self), PyArray_DTypeMeta
290328

291329
template <typename T>
292330
static int
293-
numpy_to_quad_strided_loop(PyArrayMethod_Context *context, char *const data[],
294-
npy_intp const dimensions[], npy_intp const strides[],
295-
void *NPY_UNUSED(auxdata))
331+
numpy_to_quad_strided_loop_unaligned(PyArrayMethod_Context *context, char *const data[],
332+
npy_intp const dimensions[], npy_intp const strides[],
333+
void *NPY_UNUSED(auxdata))
296334
{
297335
npy_intp N = dimensions[0];
298336
char *in_ptr = data[0];
@@ -316,6 +354,36 @@ numpy_to_quad_strided_loop(PyArrayMethod_Context *context, char *const data[],
316354
return 0;
317355
}
318356

357+
template <typename T>
358+
static int
359+
numpy_to_quad_strided_loop_aligned(PyArrayMethod_Context *context, char *const data[],
360+
npy_intp const dimensions[], npy_intp const strides[],
361+
void *NPY_UNUSED(auxdata))
362+
{
363+
npy_intp N = dimensions[0];
364+
char *in_ptr = data[0];
365+
char *out_ptr = data[1];
366+
367+
QuadPrecDTypeObject *descr_out = (QuadPrecDTypeObject *)context->descriptors[1];
368+
QuadBackendType backend = descr_out->backend;
369+
370+
while (N--) {
371+
T in_val = *(T *)in_ptr;
372+
quad_value out_val = to_quad<T>(in_val, backend);
373+
374+
if (backend == BACKEND_SLEEF) {
375+
*(Sleef_quad *)(out_ptr) = out_val.sleef_value;
376+
}
377+
else {
378+
*(long double *)(out_ptr) = out_val.longdouble_value;
379+
}
380+
381+
in_ptr += strides[0];
382+
out_ptr += strides[1];
383+
}
384+
return 0;
385+
}
386+
319387
// Casting from QuadDType to other types
320388

321389
template <typename T>
@@ -493,9 +561,9 @@ quad_to_numpy_resolve_descriptors(PyObject *NPY_UNUSED(self), PyArray_DTypeMeta
493561

494562
template <typename T>
495563
static int
496-
quad_to_numpy_strided_loop(PyArrayMethod_Context *context, char *const data[],
497-
npy_intp const dimensions[], npy_intp const strides[],
498-
void *NPY_UNUSED(auxdata))
564+
quad_to_numpy_strided_loop_unaligned(PyArrayMethod_Context *context, char *const data[],
565+
npy_intp const dimensions[], npy_intp const strides[],
566+
void *NPY_UNUSED(auxdata))
499567
{
500568
npy_intp N = dimensions[0];
501569
char *in_ptr = data[0];
@@ -519,6 +587,37 @@ quad_to_numpy_strided_loop(PyArrayMethod_Context *context, char *const data[],
519587
return 0;
520588
}
521589

590+
template <typename T>
591+
static int
592+
quad_to_numpy_strided_loop_aligned(PyArrayMethod_Context *context, char *const data[],
593+
npy_intp const dimensions[], npy_intp const strides[],
594+
void *NPY_UNUSED(auxdata))
595+
{
596+
npy_intp N = dimensions[0];
597+
char *in_ptr = data[0];
598+
char *out_ptr = data[1];
599+
600+
QuadPrecDTypeObject *quad_descr = (QuadPrecDTypeObject *)context->descriptors[0];
601+
QuadBackendType backend = quad_descr->backend;
602+
603+
while (N--) {
604+
quad_value in_val;
605+
if (backend == BACKEND_SLEEF) {
606+
in_val.sleef_value = *(Sleef_quad *)in_ptr;
607+
}
608+
else {
609+
in_val.longdouble_value = *(long double *)in_ptr;
610+
}
611+
612+
T out_val = from_quad<T>(in_val, backend);
613+
*(T *)(out_ptr) = out_val;
614+
615+
in_ptr += strides[0];
616+
out_ptr += strides[1];
617+
}
618+
return 0;
619+
}
620+
522621
static PyArrayMethod_Spec *specs[NUM_CASTS + 1]; // +1 for NULL terminator
523622
static size_t spec_count = 0;
524623

@@ -537,17 +636,18 @@ add_cast_from(PyArray_DTypeMeta *to)
537636
{
538637
PyArray_DTypeMeta **dtypes = new PyArray_DTypeMeta *[2]{&QuadPrecDType, to};
539638

540-
PyType_Slot *slots = new PyType_Slot[3]{
639+
PyType_Slot *slots = new PyType_Slot[]{
541640
{NPY_METH_resolve_descriptors, (void *)&quad_to_numpy_resolve_descriptors<T>},
542-
{NPY_METH_strided_loop, (void *)&quad_to_numpy_strided_loop<T>},
641+
{NPY_METH_strided_loop, (void *)&quad_to_numpy_strided_loop_aligned<T>},
642+
{NPY_METH_unaligned_strided_loop, (void *)&quad_to_numpy_strided_loop_unaligned<T>},
543643
{0, nullptr}};
544644

545645
PyArrayMethod_Spec *spec = new PyArrayMethod_Spec{
546646
.name = "cast_QuadPrec_to_NumPy",
547647
.nin = 1,
548648
.nout = 1,
549649
.casting = NPY_UNSAFE_CASTING,
550-
.flags = (NPY_ARRAYMETHOD_FLAGS)0,
650+
.flags = NPY_METH_SUPPORTS_UNALIGNED,
551651
.dtypes = dtypes,
552652
.slots = slots,
553653
};
@@ -560,17 +660,18 @@ add_cast_to(PyArray_DTypeMeta *from)
560660
{
561661
PyArray_DTypeMeta **dtypes = new PyArray_DTypeMeta *[2]{from, &QuadPrecDType};
562662

563-
PyType_Slot *slots = new PyType_Slot[3]{
663+
PyType_Slot *slots = new PyType_Slot[]{
564664
{NPY_METH_resolve_descriptors, (void *)&numpy_to_quad_resolve_descriptors<T>},
565-
{NPY_METH_strided_loop, (void *)&numpy_to_quad_strided_loop<T>},
665+
{NPY_METH_strided_loop, (void *)&numpy_to_quad_strided_loop_aligned<T>},
666+
{NPY_METH_unaligned_strided_loop, (void *)&numpy_to_quad_strided_loop_unaligned<T>},
566667
{0, nullptr}};
567668

568669
PyArrayMethod_Spec *spec = new PyArrayMethod_Spec{
569670
.name = "cast_NumPy_to_QuadPrec",
570671
.nin = 1,
571672
.nout = 1,
572673
.casting = NPY_SAFE_CASTING,
573-
.flags = (NPY_ARRAYMETHOD_FLAGS)0,
674+
.flags = NPY_METH_SUPPORTS_UNALIGNED,
574675
.dtypes = dtypes,
575676
.slots = slots,
576677
};
@@ -583,10 +684,10 @@ init_casts_internal(void)
583684
{
584685
PyArray_DTypeMeta **quad2quad_dtypes =
585686
new PyArray_DTypeMeta *[2]{&QuadPrecDType, &QuadPrecDType};
586-
PyType_Slot *quad2quad_slots = new PyType_Slot[4]{
687+
PyType_Slot *quad2quad_slots = new PyType_Slot[]{
587688
{NPY_METH_resolve_descriptors, (void *)&quad_to_quad_resolve_descriptors},
588-
{NPY_METH_strided_loop, (void *)&quad_to_quad_strided_loop},
589-
{NPY_METH_unaligned_strided_loop, (void *)&quad_to_quad_strided_loop},
689+
{NPY_METH_strided_loop, (void *)&quad_to_quad_strided_loop_aligned},
690+
{NPY_METH_unaligned_strided_loop, (void *)&quad_to_quad_strided_loop_unaligned},
590691
{0, nullptr}};
591692

592693
PyArrayMethod_Spec *quad2quad_spec = new PyArrayMethod_Spec{

quaddtype/numpy_quaddtype/src/scalar.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ QuadPrecision_from_object(PyObject *value, QuadBackendType backend)
7979
else if (Py_TYPE(value) == &QuadPrecision_Type) {
8080
Py_DECREF(self); // discard the default one
8181
QuadPrecisionObject *quad_obj = (QuadPrecisionObject *)value;
82-
8382
// create a new one with the same backend
8483
QuadPrecisionObject *self = QuadPrecision_raw_new(quad_obj->backend);
8584
if (quad_obj->backend == BACKEND_SLEEF) {

0 commit comments

Comments
 (0)