1
1
#define PY_ARRAY_UNIQUE_SYMBOL QuadPrecType_ARRAY_API
2
2
#define PY_UFUNC_UNIQUE_SYMBOL QuadPrecType_UFUNC_API
3
- #define NPY_NO_DEPRECATED_API NPY_2_0_API_VERSION
4
- #define NPY_TARGET_VERSION NPY_2_0_API_VERSION
3
+ #define NPY_NO_DEPRECATED_API NPY_2_4_API_VERSION
4
+ #define NPY_TARGET_VERSION NPY_2_4_API_VERSION
5
5
#define NO_IMPORT_ARRAY
6
6
#define NO_IMPORT_UFUNC
7
7
@@ -157,7 +157,7 @@ void_to_quad_resolve_descriptors(PyObject *NPY_UNUSED(self), PyArray_DTypeMeta *
157
157
PyArray_Descr *given_descrs[2], PyArray_Descr *loop_descrs[2],
158
158
npy_intp *view_offset)
159
159
{
160
- PyErr_SetString (PyExc_TypeError,
160
+ PyErr_SetString (PyExc_TypeError,
161
161
" Void to QuadPrecision cast is not implemented" );
162
162
return (NPY_CASTING)-1 ;
163
163
}
@@ -401,7 +401,7 @@ to_quad<long double>(long double x, QuadBackendType backend)
401
401
}
402
402
403
403
template <typename T>
404
- static NPY_CASTING
404
+ static int
405
405
numpy_to_quad_resolve_descriptors (PyObject *NPY_UNUSED (self), PyArray_DTypeMeta *dtypes[2],
406
406
PyArray_Descr *given_descrs[2], PyArray_Descr *loop_descrs[2],
407
407
npy_intp *view_offset)
@@ -419,7 +419,11 @@ numpy_to_quad_resolve_descriptors(PyObject *NPY_UNUSED(self), PyArray_DTypeMeta
419
419
}
420
420
421
421
loop_descrs[0 ] = PyArray_GetDefaultDescr (dtypes[0 ]);
422
+ #if NPY_FEATURE_VERSION > NPY_2_3_API_VERSION
423
+ return NPY_SAFE_CASTING | NPY_SAME_VALUE_CASTING_FLAG;
424
+ #else
422
425
return NPY_SAFE_CASTING;
426
+ #endif
423
427
}
424
428
425
429
template <typename T>
@@ -666,6 +670,28 @@ from_quad<long double>(quad_value x, QuadBackendType backend)
666
670
}
667
671
}
668
672
673
+ template <typename T>
674
+ static inline int
675
+ from_quad_checked (quad_value x, QuadBackendType backend, typename NpyType<T>::TYPE *ret) {
676
+ *ret = from_quad<typename NpyType<T>::TYPE>(x, backend);
677
+ quad_value check = to_quad<typename NpyType<T>::TYPE>(*ret, backend);
678
+ if (backend == BACKEND_SLEEF) {
679
+ if (check.sleef_value == x.sleef_value ) {
680
+ return 0 ;
681
+ }
682
+ }
683
+ else {
684
+ if (check.longdouble_value == x.longdouble_value ) {
685
+ return 0 ;
686
+ }
687
+ }
688
+ NPY_ALLOW_C_API_DEF;
689
+ NPY_ALLOW_C_API;
690
+ PyErr_SetString (PyExc_ValueError, " could not cast 'same_value' to QuadType" );
691
+ NPY_DISABLE_C_API;
692
+ return -1 ;
693
+ }
694
+
669
695
template <typename T>
670
696
static NPY_CASTING
671
697
quad_to_numpy_resolve_descriptors (PyObject *NPY_UNUSED (self), PyArray_DTypeMeta *dtypes[2],
@@ -685,6 +711,9 @@ quad_to_numpy_strided_loop_unaligned(PyArrayMethod_Context *context, char *const
685
711
npy_intp const dimensions[], npy_intp const strides[],
686
712
void *NPY_UNUSED (auxdata))
687
713
{
714
+ #if NPY_FEATURE_VERSION > NPY_2_3_API_VERSION
715
+ int same_value_casting = ((context->flags & NPY_SAME_VALUE_CONTEXT_FLAG) == NPY_SAME_VALUE_CONTEXT_FLAG);
716
+ #endif
688
717
npy_intp N = dimensions[0 ];
689
718
char *in_ptr = data[0 ];
690
719
char *out_ptr = data[1 ];
@@ -694,6 +723,24 @@ quad_to_numpy_strided_loop_unaligned(PyArrayMethod_Context *context, char *const
694
723
695
724
size_t elem_size = (backend == BACKEND_SLEEF) ? sizeof (Sleef_quad) : sizeof (long double );
696
725
726
+ #if NPY_FEATURE_VERSION > NPY_2_3_API_VERSION
727
+ if (same_value_casting) {
728
+ while (N--) {
729
+ quad_value in_val;
730
+ memcpy (&in_val, in_ptr, elem_size);
731
+ typename NpyType<T>::TYPE out_val;
732
+ if (from_quad_checked<T>(in_val, backend, &out_val) < 0 ) {
733
+ return -1 ;
734
+ }
735
+ memcpy (out_ptr, &out_val, sizeof (typename NpyType<T>::TYPE));
736
+
737
+ in_ptr += strides[0 ];
738
+ out_ptr += strides[1 ];
739
+ }
740
+ } else {
741
+ #else
742
+ {
743
+ #endif
697
744
while (N--) {
698
745
quad_value in_val;
699
746
memcpy (&in_val, in_ptr, elem_size);
@@ -703,7 +750,7 @@ quad_to_numpy_strided_loop_unaligned(PyArrayMethod_Context *context, char *const
703
750
704
751
in_ptr += strides[0 ];
705
752
out_ptr += strides[1 ];
706
- }
753
+ }}
707
754
return 0 ;
708
755
}
709
756
@@ -716,10 +763,36 @@ quad_to_numpy_strided_loop_aligned(PyArrayMethod_Context *context, char *const d
716
763
npy_intp N = dimensions[0 ];
717
764
char *in_ptr = data[0 ];
718
765
char *out_ptr = data[1 ];
766
+ #if NPY_FEATURE_VERSION > NPY_2_3_API_VERSION
767
+ int same_value_casting = ((context->flags & NPY_SAME_VALUE_CONTEXT_FLAG) == NPY_SAME_VALUE_CONTEXT_FLAG);
768
+ #endif
719
769
720
770
QuadPrecDTypeObject *quad_descr = (QuadPrecDTypeObject *)context->descriptors [0 ];
721
771
QuadBackendType backend = quad_descr->backend ;
722
772
773
+ #if NPY_FEATURE_VERSION > NPY_2_3_API_VERSION
774
+ if (same_value_casting) {
775
+ while (N--) {
776
+ quad_value in_val;
777
+ if (backend == BACKEND_SLEEF) {
778
+ in_val.sleef_value = *(Sleef_quad *)in_ptr;
779
+ }
780
+ else {
781
+ in_val.longdouble_value = *(long double *)in_ptr;
782
+ }
783
+
784
+ typename NpyType<T>::TYPE out_val;
785
+ if (from_quad_checked<T>(in_val, backend, &out_val) < 0 ) {
786
+ return -1 ;
787
+ }
788
+ *(typename NpyType<T>::TYPE *)(out_ptr) = out_val;
789
+
790
+ in_ptr += strides[0 ];
791
+ out_ptr += strides[1 ];
792
+ }} else {
793
+ #else
794
+ {
795
+ #endif
723
796
while (N--) {
724
797
quad_value in_val;
725
798
if (backend == BACKEND_SLEEF) {
@@ -734,7 +807,7 @@ quad_to_numpy_strided_loop_aligned(PyArrayMethod_Context *context, char *const d
734
807
735
808
in_ptr += strides[0 ];
736
809
out_ptr += strides[1 ];
737
- }
810
+ }}
738
811
return 0 ;
739
812
}
740
813
@@ -771,7 +844,11 @@ add_cast_from(PyArray_DTypeMeta *to)
771
844
.name = " cast_QuadPrec_to_NumPy" ,
772
845
.nin = 1 ,
773
846
.nout = 1 ,
847
+ #if NPY_FEATURE_VERSION > NPY_2_3_API_VERSION
848
+ .casting = NPY_SAME_VALUE_CASTING,
849
+ #else
774
850
.casting = NPY_UNSAFE_CASTING,
851
+ #endif
775
852
.flags = NPY_METH_SUPPORTS_UNALIGNED,
776
853
.dtypes = dtypes,
777
854
.slots = slots,
@@ -904,4 +981,4 @@ free_casts(void)
904
981
}
905
982
}
906
983
spec_count = 0 ;
907
- }
984
+ }
0 commit comments