@@ -49,9 +49,9 @@ quad_to_quad_resolve_descriptors(PyObject *NPY_UNUSED(self),
49
49
}
50
50
51
51
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))
55
55
{
56
56
npy_intp N = dimensions[0 ];
57
57
char *in_ptr = data[0 ];
@@ -79,6 +79,44 @@ quad_to_quad_strided_loop(PyArrayMethod_Context *context, char *const data[],
79
79
return 0 ;
80
80
}
81
81
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
+
82
120
// Casting from other types to QuadDType
83
121
84
122
template <typename T>
@@ -290,9 +328,9 @@ numpy_to_quad_resolve_descriptors(PyObject *NPY_UNUSED(self), PyArray_DTypeMeta
290
328
291
329
template <typename T>
292
330
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))
296
334
{
297
335
npy_intp N = dimensions[0 ];
298
336
char *in_ptr = data[0 ];
@@ -316,6 +354,36 @@ numpy_to_quad_strided_loop(PyArrayMethod_Context *context, char *const data[],
316
354
return 0 ;
317
355
}
318
356
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
+
319
387
// Casting from QuadDType to other types
320
388
321
389
template <typename T>
@@ -493,9 +561,9 @@ quad_to_numpy_resolve_descriptors(PyObject *NPY_UNUSED(self), PyArray_DTypeMeta
493
561
494
562
template <typename T>
495
563
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))
499
567
{
500
568
npy_intp N = dimensions[0 ];
501
569
char *in_ptr = data[0 ];
@@ -519,6 +587,37 @@ quad_to_numpy_strided_loop(PyArrayMethod_Context *context, char *const data[],
519
587
return 0 ;
520
588
}
521
589
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
+
522
621
static PyArrayMethod_Spec *specs[NUM_CASTS + 1 ]; // +1 for NULL terminator
523
622
static size_t spec_count = 0 ;
524
623
@@ -537,17 +636,18 @@ add_cast_from(PyArray_DTypeMeta *to)
537
636
{
538
637
PyArray_DTypeMeta **dtypes = new PyArray_DTypeMeta *[2 ]{&QuadPrecDType, to};
539
638
540
- PyType_Slot *slots = new PyType_Slot[3 ]{
639
+ PyType_Slot *slots = new PyType_Slot[]{
541
640
{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>},
543
643
{0 , nullptr }};
544
644
545
645
PyArrayMethod_Spec *spec = new PyArrayMethod_Spec{
546
646
.name = " cast_QuadPrec_to_NumPy" ,
547
647
.nin = 1 ,
548
648
.nout = 1 ,
549
649
.casting = NPY_UNSAFE_CASTING,
550
- .flags = (NPY_ARRAYMETHOD_FLAGS) 0 ,
650
+ .flags = NPY_METH_SUPPORTS_UNALIGNED ,
551
651
.dtypes = dtypes,
552
652
.slots = slots,
553
653
};
@@ -560,17 +660,18 @@ add_cast_to(PyArray_DTypeMeta *from)
560
660
{
561
661
PyArray_DTypeMeta **dtypes = new PyArray_DTypeMeta *[2 ]{from, &QuadPrecDType};
562
662
563
- PyType_Slot *slots = new PyType_Slot[3 ]{
663
+ PyType_Slot *slots = new PyType_Slot[]{
564
664
{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>},
566
667
{0 , nullptr }};
567
668
568
669
PyArrayMethod_Spec *spec = new PyArrayMethod_Spec{
569
670
.name = " cast_NumPy_to_QuadPrec" ,
570
671
.nin = 1 ,
571
672
.nout = 1 ,
572
673
.casting = NPY_SAFE_CASTING,
573
- .flags = (NPY_ARRAYMETHOD_FLAGS) 0 ,
674
+ .flags = NPY_METH_SUPPORTS_UNALIGNED ,
574
675
.dtypes = dtypes,
575
676
.slots = slots,
576
677
};
@@ -583,10 +684,10 @@ init_casts_internal(void)
583
684
{
584
685
PyArray_DTypeMeta **quad2quad_dtypes =
585
686
new PyArray_DTypeMeta *[2 ]{&QuadPrecDType, &QuadPrecDType};
586
- PyType_Slot *quad2quad_slots = new PyType_Slot[4 ]{
687
+ PyType_Slot *quad2quad_slots = new PyType_Slot[]{
587
688
{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 },
590
691
{0 , nullptr }};
591
692
592
693
PyArrayMethod_Spec *quad2quad_spec = new PyArrayMethod_Spec{
0 commit comments