1
1
#include <Python.h>
2
- #include <sleef.h>
3
- #include <sleefquad.h>
2
+ #include <sleef.h>
3
+ #include <sleefquad.h>
4
4
5
- #define PY_ARRAY_UNIQUE_SYMBOL quaddtype_ARRAY_API
6
- #define PY_UFUNC_UNIQUE_SYMBOL quaddtype_UFUNC_API
5
+ #define PY_ARRAY_UNIQUE_SYMBOL QuadPrecType_ARRAY_API
6
+ #define PY_UFUNC_UNIQUE_SYMBOL QuadPrecType_UFUNC_API
7
7
#define NPY_NO_DEPRECATED_API NPY_2_0_API_VERSION
8
8
#define NPY_TARGET_VERSION NPY_2_0_API_VERSION
9
9
#define NO_IMPORT_ARRAY
10
10
#define NO_IMPORT_UFUNC
11
- #include "numpy/ndarraytypes.h"
12
11
#include "numpy/arrayobject.h"
12
+ #include "numpy/ndarraytypes.h"
13
13
#include "numpy/dtype_api.h"
14
+ #include "numpy/_public_dtype_api_table.h" // not included in dtype_api.h
14
15
16
+ #include "scalar.h"
15
17
#include "dtype.h"
16
18
19
+ static inline int quad_load (Sleef_quad * x , char * data_ptr )
20
+ {
21
+ if (data_ptr == NULL || x == NULL )
22
+ {
23
+ PyErr_SetString (PyExc_ValueError , "Invalid memory location" );
24
+ return -1 ;
25
+ }
26
+ * x = * (Sleef_quad * )data_ptr ;
27
+ return 0 ;
28
+ }
17
29
18
- PyTypeObject * QuadScalar_Type = NULL ;
30
+ static inline int quad_store (char * data_ptr , Sleef_quad x )
31
+ {
32
+ if (data_ptr == NULL )
33
+ {
34
+ PyErr_SetString (PyExc_ValueError , "Invalid memory location" );
35
+ return -1 ;
36
+ }
37
+ * (Sleef_quad * )data_ptr = x ;
38
+ return 0 ;
39
+ }
19
40
20
- QuadDTypeObject * new_quaddtype_instance (void )
41
+ QuadPrecDTypeObject * new_quaddtype_instance (void )
21
42
{
22
- QuadDTypeObject * new =
23
- (QuadDTypeObject * )PyArrayDescr_Type .tp_new ((PyTypeObject * )& QuadDType , NULL , NULL );
43
+ QuadPrecDTypeObject * new = (QuadPrecDTypeObject * )PyArrayDescr_Type .tp_new ((PyTypeObject * )& QuadPrecDType , NULL , NULL );
24
44
if (new == NULL ) {
25
45
return NULL ;
26
46
}
27
-
28
47
new -> base .elsize = sizeof (Sleef_quad );
29
48
new -> base .alignment = _Alignof(Sleef_quad );
49
+ new -> base .flags |= NPY_NEEDS_INIT ; // Indicates memory for this data-type must be initialized (set to 0) on creation.
50
+
30
51
return new ;
31
52
}
32
53
33
- static PyObject * quaddtype_new ( PyTypeObject * NPY_UNUSED ( cls ), PyObject * args , PyObject * kwargs )
54
+ static QuadPrecDTypeObject * ensure_canonical ( QuadPrecDTypeObject * self )
34
55
{
35
- return (PyObject * )new_quaddtype_instance ();
56
+ Py_INCREF (self );
57
+ return self ;
36
58
}
37
59
38
- static void quaddtype_dealloc ( QuadDTypeObject * self )
60
+ static QuadPrecDTypeObject * common_instance ( QuadPrecDTypeObject * dtype1 , QuadPrecDTypeObject * dtype2 )
39
61
{
40
- PyArrayDescr_Type .tp_dealloc ((PyObject * )self );
62
+ Py_INCREF (dtype1 );
63
+ return dtype1 ;
41
64
}
42
65
43
- static PyObject * quaddtype_repr (QuadDTypeObject * self )
66
+
67
+ static PyArray_DTypeMeta * common_dtype (PyArray_DTypeMeta * cls , PyArray_DTypeMeta * other )
44
68
{
45
- PyObject * res = PyUnicode_FromString ("This is a Sleef based quad (128-bit float) dtype." );
46
- return res ;
47
- }
69
+ // Promote integer and floating-point types to QuadPrecDType
70
+ if (other -> type_num >= 0 &&
71
+ (PyTypeNum_ISINTEGER (other -> type_num ) ||
72
+ PyTypeNum_ISFLOAT (other -> type_num ))) {
73
+ Py_INCREF (cls );
74
+ return cls ;
75
+ }
76
+ // Don't promote complex types
77
+ if (PyTypeNum_ISCOMPLEX (other -> type_num )) {
78
+ Py_INCREF (Py_NotImplemented );
79
+ return (PyArray_DTypeMeta * )Py_NotImplemented ;
80
+ }
48
81
49
- PyArray_DTypeMeta QuadDType = {
50
- {{
51
- PyVarObject_HEAD_INIT (NULL , 0 ).tp_name = "quaddtype.QuadDType" ,
52
- .tp_basicsize = sizeof (QuadDTypeObject ),
53
- .tp_new = quaddtype_new ,
54
- .tp_dealloc = (destructor )quaddtype_dealloc ,
55
- .tp_repr = (reprfunc )quaddtype_repr ,
56
- .tp_str = (reprfunc )quaddtype_repr ,
57
- }},
58
- };
82
+ Py_INCREF (Py_NotImplemented );
83
+ return (PyArray_DTypeMeta * )Py_NotImplemented ;
84
+ }
59
85
60
- int init_quad_dtype (void )
86
+ static PyArray_Descr *
87
+ quadprec_discover_descriptor_from_pyobject (PyArray_DTypeMeta * NPY_UNUSED (cls ), PyObject * obj )
61
88
{
62
- PyArrayMethod_Spec * casts [] = {
63
- NULL ,
64
- };
65
-
66
- PyArrayDTypeMeta_Spec QuadDType_DTypeSpec = {
67
- .flags = NPY_DT_NUMERIC ,
68
- .casts = casts ,
69
- .typeobj = QuadScalar_Type ,
70
- .slots = NULL ,
71
- };
89
+ if (Py_TYPE (obj ) != & QuadPrecision_Type )
90
+ {
91
+ PyErr_SetString (PyExc_TypeError , "Can only store QuadPrecision in a QuadPrecDType array." );
92
+ return NULL ;
93
+ }
94
+ return (PyArray_Descr * )new_quaddtype_instance ();
95
+ }
72
96
73
- ((PyObject * )& QuadDType )-> ob_type = & PyArrayDTypeMeta_Type ;
74
- ((PyTypeObject * )& QuadDType )-> tp_base = & PyArrayDescr_Type ;
75
- if (PyType_Ready ((PyTypeObject * )& QuadDType ) < 0 ) {
76
- return -1 ;
97
+ static int quadprec_setitem (QuadPrecDTypeObject * descr , PyObject * obj , char * dataptr )
98
+ {
99
+ QuadPrecisionObject * value ;
100
+ if (PyObject_TypeCheck (obj , & QuadPrecision_Type ))
101
+ {
102
+ Py_INCREF (obj );
103
+ value = (QuadPrecisionObject * )obj ;
104
+ }
105
+ else
106
+ {
107
+ value = QuadPrecision_from_object (obj );
108
+ if (value == NULL ) {
109
+ return -1 ;
110
+ }
77
111
}
78
112
79
- if (PyArrayInitDTypeMeta_FromSpec (& QuadDType , & QuadDType_DTypeSpec ) < 0 ) {
113
+ if (quad_store (dataptr , value -> quad .value ) < 0 )
114
+ {
115
+ Py_DECREF (value );
80
116
return -1 ;
81
117
}
82
118
83
- QuadDType . singleton = PyArray_GetDefaultDescr ( & QuadDType );
119
+ Py_DECREF ( value );
84
120
return 0 ;
85
121
}
86
122
123
+ static PyObject * quadprec_getitem (QuadPrecDTypeObject * descr , char * dataptr )
124
+ {
125
+ QuadPrecisionObject * new = QuadPrecision_raw_new ();
126
+ if (!new )
127
+ {
128
+ return NULL ;
129
+ }
130
+ if (quad_load (& new -> quad .value , dataptr ) < 0 )
131
+ {
132
+ Py_DECREF (new );
133
+ return NULL ;
134
+ }
135
+ return (PyObject * )new ;
136
+ }
137
+
138
+ static PyType_Slot QuadPrecDType_Slots [] =
139
+ {
140
+ {NPY_DT_ensure_canonical , & ensure_canonical },
141
+ {NPY_DT_common_instance , & common_instance },
142
+ {NPY_DT_common_dtype , & common_dtype },
143
+ {NPY_DT_discover_descr_from_pyobject , & quadprec_discover_descriptor_from_pyobject },
144
+ {NPY_DT_setitem , & quadprec_setitem },
145
+ {NPY_DT_getitem , & quadprec_getitem },
146
+ {0 , NULL }
147
+ };
148
+
87
149
150
+ static PyObject * QuadPrecDType_new (PyTypeObject * NPY_UNUSED (cls ), PyObject * args , PyObject * kwds )
151
+ {
152
+ if (PyTuple_GET_SIZE (args ) != 0 || (kwds != NULL && PyDict_Size (kwds ) != 0 )) {
153
+ PyErr_SetString (PyExc_TypeError ,
154
+ "QuadPrecDType takes no arguments" );
155
+ return NULL ;
156
+ }
88
157
158
+ return (PyObject * )new_quaddtype_instance ();
159
+ }
89
160
161
+ static PyObject * QuadPrecDType_repr (QuadPrecDTypeObject * self )
162
+ {
163
+ return PyUnicode_FromString ("QuadPrecDType()" );
164
+ }
165
+
166
+ PyArray_DTypeMeta QuadPrecDType = {
167
+ {{
168
+ PyVarObject_HEAD_INIT (NULL , 0 )
169
+ .tp_name = "QuadPrecDType.QuadPrecDType" ,
170
+ .tp_basicsize = sizeof (QuadPrecDTypeObject ),
171
+ .tp_new = QuadPrecDType_new ,
172
+ .tp_repr = (reprfunc )QuadPrecDType_repr ,
173
+ .tp_str = (reprfunc )QuadPrecDType_repr ,
174
+ }},
175
+ };
176
+
177
+ int init_quadprec_dtype (void )
178
+ {
179
+ PyArrayMethod_Spec * * casts = NULL ; // Initialize casts if needed
180
+
181
+ PyArrayDTypeMeta_Spec QuadPrecDType_DTypeSpec = {
182
+ .flags = NPY_DT_NUMERIC ,
183
+ .casts = casts ,
184
+ .typeobj = & QuadPrecision_Type ,
185
+ .slots = QuadPrecDType_Slots ,
186
+ };
187
+
188
+ ((PyObject * )& QuadPrecDType )-> ob_type = & PyArrayDTypeMeta_Type ;
189
+
190
+ ((PyTypeObject * )& QuadPrecDType )-> tp_base = & PyArrayDescr_Type ;
191
+
192
+ if (PyType_Ready ((PyTypeObject * )& QuadPrecDType ) < 0 )
193
+ {
194
+ return -1 ;
195
+ }
196
+
197
+ if (PyArrayInitDTypeMeta_FromSpec (& QuadPrecDType , & QuadPrecDType_DTypeSpec ) < 0 )
198
+ {
199
+ return -1 ;
200
+ }
201
+ return 0 ;
202
+ }
0 commit comments