Cython has moved to github.
cython-devel
view Cython/Includes/numpy.pxd @ 1235:5de00fce9b73
Buffers: NumPy record array support, format string parsing improvements
| author | Dag Sverre Seljebotn <dagss@student.matnat.uio.no> |
|---|---|
| date | Sat Oct 11 18:48:15 2008 +0200 (3 years ago) |
| parents | 6f928ec0df43 |
| children | aa87fed4f334 |
line source
1 cimport python_buffer as pybuf
2 cimport stdlib
4 cdef extern from "Python.h":
5 ctypedef int Py_intptr_t
7 cdef extern from "numpy/arrayobject.h":
8 ctypedef Py_intptr_t npy_intp
10 cdef enum:
11 NPY_BOOL,
12 NPY_BYTE, NPY_UBYTE,
13 NPY_SHORT, NPY_USHORT,
14 NPY_INT, NPY_UINT,
15 NPY_LONG, NPY_ULONG,
16 NPY_LONGLONG, NPY_ULONGLONG,
17 NPY_FLOAT, NPY_DOUBLE, NPY_LONGDOUBLE,
18 NPY_CFLOAT, NPY_CDOUBLE, NPY_CLONGDOUBLE,
19 NPY_OBJECT,
20 NPY_STRING, NPY_UNICODE,
21 NPY_VOID,
22 NPY_NTYPES,
23 NPY_NOTYPE,
24 NPY_CHAR,
25 NPY_USERDEF,
27 NPY_C_CONTIGUOUS,
28 NPY_F_CONTIGUOUS
30 ctypedef class numpy.dtype [object PyArray_Descr]:
31 cdef int type_num
32 cdef object fields
33 cdef object names
36 ctypedef class numpy.ndarray [object PyArrayObject]:
37 cdef __cythonbufferdefaults__ = {"mode": "strided"}
39 cdef:
40 char *data
41 int ndim "nd"
42 npy_intp *shape "dimensions"
43 npy_intp *strides
44 int flags
45 dtype descr
47 # Note: This syntax (function definition in pxd files) is an
48 # experimental exception made for __getbuffer__ and __releasebuffer__
49 # -- the details of this may change.
50 def __getbuffer__(ndarray self, Py_buffer* info, int flags):
51 # This implementation of getbuffer is geared towards Cython
52 # requirements, and does not yet fullfill the PEP.
53 # In particular strided access is always provided regardless
54 # of flags
55 if sizeof(npy_intp) != sizeof(Py_ssize_t):
56 raise RuntimeError("Py_intptr_t and Py_ssize_t differs in size, numpy.pxd does not support this")
58 if ((flags & pybuf.PyBUF_C_CONTIGUOUS == pybuf.PyBUF_C_CONTIGUOUS)
59 and not PyArray_CHKFLAGS(self, NPY_C_CONTIGUOUS)):
60 raise ValueError("ndarray is not C contiguous")
62 if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)
63 and not PyArray_CHKFLAGS(self, NPY_F_CONTIGUOUS)):
64 raise ValueError("ndarray is not Fortran contiguous")
66 info.buf = PyArray_DATA(self)
67 info.ndim = PyArray_NDIM(self)
68 info.strides = <Py_ssize_t*>PyArray_STRIDES(self)
69 info.shape = <Py_ssize_t*>PyArray_DIMS(self)
70 info.suboffsets = NULL
71 info.itemsize = PyArray_ITEMSIZE(self)
72 info.readonly = not PyArray_ISWRITEABLE(self)
74 cdef int t
75 cdef char* f = NULL
76 cdef dtype descr = self.descr
77 cdef list stack
79 cdef bint hasfields = PyDataType_HASFIELDS(descr)
81 # Ugly hack warning:
82 # Cython currently will not support helper functions in
83 # pxd files -- so we must keep our own, manual stack!
84 # In addition, avoid allocation of the stack in the common
85 # case that we are dealing with a single non-nested datatype...
86 # (this would look much prettier if we could use utility
87 # functions).
90 if not hasfields:
91 info.obj = None # do not call releasebuffer
92 t = descr.type_num
93 if t == NPY_BYTE: f = "b"
94 elif t == NPY_UBYTE: f = "B"
95 elif t == NPY_SHORT: f = "h"
96 elif t == NPY_USHORT: f = "H"
97 elif t == NPY_INT: f = "i"
98 elif t == NPY_UINT: f = "I"
99 elif t == NPY_LONG: f = "l"
100 elif t == NPY_ULONG: f = "L"
101 elif t == NPY_LONGLONG: f = "q"
102 elif t == NPY_ULONGLONG: f = "Q"
103 elif t == NPY_FLOAT: f = "f"
104 elif t == NPY_DOUBLE: f = "d"
105 elif t == NPY_LONGDOUBLE: f = "g"
106 elif t == NPY_CFLOAT: f = "Zf"
107 elif t == NPY_CDOUBLE: f = "Zd"
108 elif t == NPY_CLONGDOUBLE: f = "Zg"
109 elif t == NPY_OBJECT: f = "O"
110 else:
111 raise ValueError("unknown dtype code in numpy.pxd (%d)" % t)
112 info.format = f
113 return
114 else:
115 info.obj = self # need to call releasebuffer
116 info.format = <char*>stdlib.malloc(255) # static size
117 f = info.format
118 stack = [iter(descr.fields.iteritems())]
120 while True:
121 iterator = stack[-1]
122 descr = None
123 while descr is None:
124 try:
125 descr = iterator.next()[1][0]
126 except StopIteration:
127 stack.pop()
128 if len(stack) > 0:
129 f[0] = "}"
130 f += 1
131 iterator = stack[-1]
132 else:
133 f[0] = 0 # Terminate string!
134 return
136 hasfields = PyDataType_HASFIELDS(descr)
137 if not hasfields:
138 t = descr.type_num
139 if f - info.format > 240: # this should leave room for "T{" and "}" as well
140 raise RuntimeError("Format string allocated too short.")
142 if t == NPY_BYTE: f[0] = "b"
143 elif t == NPY_UBYTE: f[0] = "B"
144 elif t == NPY_SHORT: f[0] = "h"
145 elif t == NPY_USHORT: f[0] = "H"
146 elif t == NPY_INT: f[0] = "i"
147 elif t == NPY_UINT: f[0] = "I"
148 elif t == NPY_LONG: f[0] = "l"
149 elif t == NPY_ULONG: f[0] = "L"
150 elif t == NPY_LONGLONG: f[0] = "q"
151 elif t == NPY_ULONGLONG: f[0] = "Q"
152 elif t == NPY_FLOAT: f[0] = "f"
153 elif t == NPY_DOUBLE: f[0] = "d"
154 elif t == NPY_LONGDOUBLE: f[0] = "g"
155 elif t == NPY_CFLOAT: f[0] = "Z"; f[1] = "f"; f += 1
156 elif t == NPY_CDOUBLE: f[0] = "Z"; f[1] = "d"; f += 1
157 elif t == NPY_CLONGDOUBLE: f[0] = "Z"; f[1] = "g"; f += 1
158 elif t == NPY_OBJECT: f[0] = "O"
159 else:
160 raise ValueError("unknown dtype code in numpy.pxd (%d)" % t)
161 f += 1
162 else:
163 f[0] = "T"
164 f[1] = "{"
165 f += 2
166 stack.append(iter(descr.fields.iteritems()))
168 def __releasebuffer__(ndarray self, Py_buffer* info):
169 # This can not be called unless format needs to be freed (as
170 # obj is set to NULL in those case)
171 stdlib.free(info.format)
174 cdef void* PyArray_DATA(ndarray arr)
175 cdef int PyArray_TYPE(ndarray arr)
176 cdef int PyArray_NDIM(ndarray arr)
177 cdef int PyArray_ISWRITEABLE(ndarray arr)
178 cdef npy_intp PyArray_STRIDES(ndarray arr)
179 cdef npy_intp PyArray_DIMS(ndarray arr)
180 cdef Py_ssize_t PyArray_ITEMSIZE(ndarray arr)
181 cdef int PyArray_CHKFLAGS(ndarray arr, int flags)
182 cdef int PyArray_HASFIELDS(ndarray arr, int flags)
184 cdef int PyDataType_HASFIELDS(dtype obj)
186 ctypedef signed int npy_byte
187 ctypedef signed int npy_short
188 ctypedef signed int npy_int
189 ctypedef signed int npy_long
190 ctypedef signed int npy_longlong
192 ctypedef unsigned int npy_ubyte
193 ctypedef unsigned int npy_ushort
194 ctypedef unsigned int npy_uint
195 ctypedef unsigned int npy_ulong
196 ctypedef unsigned int npy_ulonglong
198 ctypedef float npy_float
199 ctypedef float npy_double
200 ctypedef float npy_longdouble
202 ctypedef signed int npy_int8
203 ctypedef signed int npy_int16
204 ctypedef signed int npy_int32
205 ctypedef signed int npy_int64
206 ctypedef signed int npy_int96
207 ctypedef signed int npy_int128
209 ctypedef unsigned int npy_uint8
210 ctypedef unsigned int npy_uint16
211 ctypedef unsigned int npy_uint32
212 ctypedef unsigned int npy_uint64
213 ctypedef unsigned int npy_uint96
214 ctypedef unsigned int npy_uint128
216 ctypedef float npy_float32
217 ctypedef float npy_float64
218 ctypedef float npy_float80
219 ctypedef float npy_float96
220 ctypedef float npy_float128
222 # Typedefs that matches the runtime dtype objects in
223 # the numpy module.
225 # The ones that are commented out needs an IFDEF function
226 # in Cython to enable them only on the right systems.
228 ctypedef npy_int8 int8_t
229 ctypedef npy_int16 int16_t
230 ctypedef npy_int32 int32_t
231 ctypedef npy_int64 int64_t
232 #ctypedef npy_int96 int96_t
233 #ctypedef npy_int128 int128_t
235 ctypedef npy_uint8 uint8_t
236 ctypedef npy_uint16 uint16_t
237 ctypedef npy_uint32 uint32_t
238 ctypedef npy_uint64 uint64_t
239 #ctypedef npy_uint96 uint96_t
240 #ctypedef npy_uint128 uint128_t
242 ctypedef npy_float32 float32_t
243 ctypedef npy_float64 float64_t
244 #ctypedef npy_float80 float80_t
245 #ctypedef npy_float128 float128_t
247 # The int types are mapped a bit surprising --
248 # numpy.int corresponds to 'l' and numpy.long to 'q'
249 ctypedef npy_long int_t
250 ctypedef npy_longlong long_t
252 ctypedef npy_ulong uint_t
253 ctypedef npy_ulonglong ulong_t
255 ctypedef npy_double float_t
256 ctypedef npy_double double_t
257 ctypedef npy_longdouble longdouble_t
