@@ -9,6 +9,7 @@ extern "C" {
9
9
#include < Python.h>
10
10
11
11
#include " numpy/arrayobject.h"
12
+ #include " numpy/halffloat.h"
12
13
#include " numpy/ndarraytypes.h"
13
14
#include " numpy/dtype_api.h"
14
15
}
@@ -20,7 +21,7 @@ extern "C" {
20
21
#include " casts.h"
21
22
#include " dtype.h"
22
23
23
- #define NUM_CASTS 29 // 14 to_casts + 14 from_casts + 1 quad_to_quad
24
+ #define NUM_CASTS 33 // 16 to_casts + 16 from_casts + 1 quad_to_quad
24
25
25
26
static NPY_CASTING
26
27
quad_to_quad_resolve_descriptors (PyObject *NPY_UNUSED (self),
@@ -150,15 +151,26 @@ quad_to_quad_strided_loop_aligned(PyArrayMethod_Context *context, char *const da
150
151
return 0 ;
151
152
}
152
153
154
+ // Template magic to ensure npy_bool/npy_ubyte and npy_half/npy_ushort do not alias in templates
155
+ struct my_npy_bool {};
156
+ struct my_npy_half {};
157
+
158
+ template <typename T>
159
+ struct NpyType { typedef T TYPE; };
160
+ template <>
161
+ struct NpyType <my_npy_bool>{ typedef npy_bool TYPE; };
162
+ template <>
163
+ struct NpyType <my_npy_half>{ typedef npy_half TYPE; };
164
+
153
165
// Casting from other types to QuadDType
154
166
155
167
template <typename T>
156
168
static inline quad_value
157
- to_quad (T x, QuadBackendType backend);
169
+ to_quad (typename NpyType<T>::TYPE x, QuadBackendType backend);
158
170
159
171
template <>
160
172
inline quad_value
161
- to_quad<npy_bool >(npy_bool x, QuadBackendType backend)
173
+ to_quad<my_npy_bool >(npy_bool x, QuadBackendType backend)
162
174
{
163
175
quad_value result;
164
176
if (backend == BACKEND_SLEEF) {
@@ -184,6 +196,20 @@ to_quad<npy_byte>(npy_byte x, QuadBackendType backend)
184
196
return result;
185
197
}
186
198
199
+ template <>
200
+ inline quad_value
201
+ to_quad<npy_ubyte>(npy_ubyte x, QuadBackendType backend)
202
+ {
203
+ quad_value result;
204
+ if (backend == BACKEND_SLEEF) {
205
+ result.sleef_value = Sleef_cast_from_uint64q1 (x);
206
+ }
207
+ else {
208
+ result.longdouble_value = (long double )x;
209
+ }
210
+ return result;
211
+ }
212
+
187
213
template <>
188
214
inline quad_value
189
215
to_quad<npy_short>(npy_short x, QuadBackendType backend)
@@ -295,6 +321,21 @@ to_quad<npy_ulonglong>(npy_ulonglong x, QuadBackendType backend)
295
321
}
296
322
return result;
297
323
}
324
+
325
+ template <>
326
+ inline quad_value
327
+ to_quad<my_npy_half>(npy_half x, QuadBackendType backend)
328
+ {
329
+ quad_value result;
330
+ if (backend == BACKEND_SLEEF) {
331
+ result.sleef_value = Sleef_cast_from_doubleq1 (npy_half_to_double (x));
332
+ }
333
+ else {
334
+ result.longdouble_value = (long double )npy_half_to_double (x);
335
+ }
336
+ return result;
337
+ }
338
+
298
339
template <>
299
340
inline quad_value
300
341
to_quad<float >(float x, QuadBackendType backend)
@@ -374,10 +415,10 @@ numpy_to_quad_strided_loop_unaligned(PyArrayMethod_Context *context, char *const
374
415
size_t elem_size = (backend == BACKEND_SLEEF) ? sizeof (Sleef_quad) : sizeof (long double );
375
416
376
417
while (N--) {
377
- T in_val;
418
+ typename NpyType<T>::TYPE in_val;
378
419
quad_value out_val;
379
420
380
- memcpy (&in_val, in_ptr, sizeof (T ));
421
+ memcpy (&in_val, in_ptr, sizeof (typename NpyType<T>::TYPE ));
381
422
out_val = to_quad<T>(in_val, backend);
382
423
memcpy (out_ptr, &out_val, elem_size);
383
424
@@ -401,7 +442,7 @@ numpy_to_quad_strided_loop_aligned(PyArrayMethod_Context *context, char *const d
401
442
QuadBackendType backend = descr_out->backend ;
402
443
403
444
while (N--) {
404
- T in_val = *(T *)in_ptr;
445
+ typename NpyType<T>::TYPE in_val = *(typename NpyType<T>::TYPE *)in_ptr;
405
446
quad_value out_val = to_quad<T>(in_val, backend);
406
447
407
448
if (backend == BACKEND_SLEEF) {
@@ -420,12 +461,12 @@ numpy_to_quad_strided_loop_aligned(PyArrayMethod_Context *context, char *const d
420
461
// Casting from QuadDType to other types
421
462
422
463
template <typename T>
423
- static inline T
464
+ static inline typename NpyType<T>::TYPE
424
465
from_quad (quad_value x, QuadBackendType backend);
425
466
426
467
template <>
427
468
inline npy_bool
428
- from_quad<npy_bool >(quad_value x, QuadBackendType backend)
469
+ from_quad<my_npy_bool >(quad_value x, QuadBackendType backend)
429
470
{
430
471
if (backend == BACKEND_SLEEF) {
431
472
return Sleef_cast_to_int64q1 (x.sleef_value ) != 0 ;
@@ -447,6 +488,18 @@ from_quad<npy_byte>(quad_value x, QuadBackendType backend)
447
488
}
448
489
}
449
490
491
+ template <>
492
+ inline npy_ubyte
493
+ from_quad<npy_ubyte>(quad_value x, QuadBackendType backend)
494
+ {
495
+ if (backend == BACKEND_SLEEF) {
496
+ return (npy_ubyte)Sleef_cast_to_uint64q1 (x.sleef_value );
497
+ }
498
+ else {
499
+ return (npy_ubyte)x.longdouble_value ;
500
+ }
501
+ }
502
+
450
503
template <>
451
504
inline npy_short
452
505
from_quad<npy_short>(quad_value x, QuadBackendType backend)
@@ -543,6 +596,18 @@ from_quad<npy_ulonglong>(quad_value x, QuadBackendType backend)
543
596
}
544
597
}
545
598
599
+ template <>
600
+ inline npy_half
601
+ from_quad<my_npy_half>(quad_value x, QuadBackendType backend)
602
+ {
603
+ if (backend == BACKEND_SLEEF) {
604
+ return npy_double_to_half (Sleef_cast_to_doubleq1 (x.sleef_value ));
605
+ }
606
+ else {
607
+ return npy_double_to_half ((double )x.longdouble_value );
608
+ }
609
+ }
610
+
546
611
template <>
547
612
inline float
548
613
from_quad<float >(quad_value x, QuadBackendType backend)
@@ -611,8 +676,8 @@ quad_to_numpy_strided_loop_unaligned(PyArrayMethod_Context *context, char *const
611
676
quad_value in_val;
612
677
memcpy (&in_val, in_ptr, elem_size);
613
678
614
- T out_val = from_quad<T>(in_val, backend);
615
- memcpy (out_ptr, &out_val, sizeof (T ));
679
+ typename NpyType<T>::TYPE out_val = from_quad<T>(in_val, backend);
680
+ memcpy (out_ptr, &out_val, sizeof (typename NpyType<T>::TYPE ));
616
681
617
682
in_ptr += strides[0 ];
618
683
out_ptr += strides[1 ];
@@ -642,8 +707,8 @@ quad_to_numpy_strided_loop_aligned(PyArrayMethod_Context *context, char *const d
642
707
in_val.longdouble_value = *(long double *)in_ptr;
643
708
}
644
709
645
- T out_val = from_quad<T>(in_val, backend);
646
- *(T *)(out_ptr) = out_val;
710
+ typename NpyType<T>::TYPE out_val = from_quad<T>(in_val, backend);
711
+ *(typename NpyType<T>::TYPE *)(out_ptr) = out_val;
647
712
648
713
in_ptr += strides[0 ];
649
714
out_ptr += strides[1 ];
@@ -739,8 +804,9 @@ init_casts_internal(void)
739
804
740
805
add_spec (quad2quad_spec);
741
806
742
- add_cast_to<npy_bool >(&PyArray_BoolDType);
807
+ add_cast_to<my_npy_bool >(&PyArray_BoolDType);
743
808
add_cast_to<npy_byte>(&PyArray_ByteDType);
809
+ add_cast_to<npy_ubyte>(&PyArray_UByteDType);
744
810
add_cast_to<npy_short>(&PyArray_ShortDType);
745
811
add_cast_to<npy_ushort>(&PyArray_UShortDType);
746
812
add_cast_to<npy_int>(&PyArray_IntDType);
@@ -749,12 +815,14 @@ init_casts_internal(void)
749
815
add_cast_to<npy_ulong>(&PyArray_ULongDType);
750
816
add_cast_to<npy_longlong>(&PyArray_LongLongDType);
751
817
add_cast_to<npy_ulonglong>(&PyArray_ULongLongDType);
818
+ add_cast_to<my_npy_half>(&PyArray_HalfDType);
752
819
add_cast_to<float >(&PyArray_FloatDType);
753
820
add_cast_to<double >(&PyArray_DoubleDType);
754
821
add_cast_to<long double >(&PyArray_LongDoubleDType);
755
822
756
- add_cast_from<npy_bool >(&PyArray_BoolDType);
823
+ add_cast_from<my_npy_bool >(&PyArray_BoolDType);
757
824
add_cast_from<npy_byte>(&PyArray_ByteDType);
825
+ add_cast_from<npy_ubyte>(&PyArray_UByteDType);
758
826
add_cast_from<npy_short>(&PyArray_ShortDType);
759
827
add_cast_from<npy_ushort>(&PyArray_UShortDType);
760
828
add_cast_from<npy_int>(&PyArray_IntDType);
@@ -763,6 +831,7 @@ init_casts_internal(void)
763
831
add_cast_from<npy_ulong>(&PyArray_ULongDType);
764
832
add_cast_from<npy_longlong>(&PyArray_LongLongDType);
765
833
add_cast_from<npy_ulonglong>(&PyArray_ULongLongDType);
834
+ add_cast_from<my_npy_half>(&PyArray_HalfDType);
766
835
add_cast_from<float >(&PyArray_FloatDType);
767
836
add_cast_from<double >(&PyArray_DoubleDType);
768
837
add_cast_from<long double >(&PyArray_LongDoubleDType);
0 commit comments