@@ -49,9 +49,9 @@ quad_to_quad_resolve_descriptors(PyObject *NPY_UNUSED(self),
4949}
5050
5151static 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
84122template <typename T>
@@ -290,9 +328,9 @@ numpy_to_quad_resolve_descriptors(PyObject *NPY_UNUSED(self), PyArray_DTypeMeta
290328
291329template <typename T>
292330static 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
321389template <typename T>
@@ -493,9 +561,9 @@ quad_to_numpy_resolve_descriptors(PyObject *NPY_UNUSED(self), PyArray_DTypeMeta
493561
494562template <typename T>
495563static 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+
522621static PyArrayMethod_Spec *specs[NUM_CASTS + 1 ]; // +1 for NULL terminator
523622static 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{
0 commit comments