Cython has moved to github.
cython-devel
view Cython/Compiler/Buffer.py @ 2819:3bc6d034486a
INLINE -> CYTHON_INLINE to avoid conflicts
| author | Robert Bradshaw <robertwb@math.washington.edu> |
|---|---|
| date | Mon Jan 25 22:47:09 2010 -0800 (2 years ago) |
| parents | c793d02d914b |
| children | fa6c25298b0d |
line source
1 from Visitor import VisitorTransform, CythonTransform
2 from ModuleNode import ModuleNode
3 from Nodes import *
4 from ExprNodes import *
5 from StringEncoding import EncodedString
6 from Errors import CompileError
7 from Code import UtilityCode
8 import Interpreter
9 import PyrexTypes
11 try:
12 set
13 except NameError:
14 from sets import Set as set
16 import textwrap
18 def dedent(text, reindent=0):
19 text = textwrap.dedent(text)
20 if reindent > 0:
21 indent = " " * reindent
22 text = '\n'.join([indent + x for x in text.split('\n')])
23 return text
25 class IntroduceBufferAuxiliaryVars(CythonTransform):
27 #
28 # Entry point
29 #
31 buffers_exists = False
33 def __call__(self, node):
34 assert isinstance(node, ModuleNode)
35 self.max_ndim = 0
36 result = super(IntroduceBufferAuxiliaryVars, self).__call__(node)
37 if self.buffers_exists:
38 use_py2_buffer_functions(node.scope)
39 use_empty_bufstruct_code(node.scope, self.max_ndim)
40 return result
43 #
44 # Basic operations for transforms
45 #
46 def handle_scope(self, node, scope):
47 # For all buffers, insert extra variables in the scope.
48 # The variables are also accessible from the buffer_info
49 # on the buffer entry
50 bufvars = [entry for name, entry
51 in scope.entries.iteritems()
52 if entry.type.is_buffer]
53 if len(bufvars) > 0:
54 self.buffers_exists = True
57 if isinstance(node, ModuleNode) and len(bufvars) > 0:
58 # for now...note that pos is wrong
59 raise CompileError(node.pos, "Buffer vars not allowed in module scope")
60 for entry in bufvars:
61 if entry.type.dtype.is_ptr:
62 raise CompileError(node.pos, "Buffers with pointer types not yet supported.")
64 name = entry.name
65 buftype = entry.type
66 if buftype.ndim > self.max_ndim:
67 self.max_ndim = buftype.ndim
69 # Declare auxiliary vars
70 cname = scope.mangle(Naming.bufstruct_prefix, name)
71 bufinfo = scope.declare_var(name="$%s" % cname, cname=cname,
72 type=PyrexTypes.c_py_buffer_type, pos=node.pos)
73 if entry.is_arg:
74 bufinfo.used = True # otherwise, NameNode will mark whether it is used
76 def var(prefix, idx, initval):
77 cname = scope.mangle(prefix, "%d_%s" % (idx, name))
78 result = scope.declare_var("$%s" % cname, PyrexTypes.c_py_ssize_t_type,
79 node.pos, cname=cname, is_cdef=True)
81 result.init = initval
82 if entry.is_arg:
83 result.used = True
84 return result
87 stridevars = [var(Naming.bufstride_prefix, i, "0") for i in range(entry.type.ndim)]
88 shapevars = [var(Naming.bufshape_prefix, i, "0") for i in range(entry.type.ndim)]
89 mode = entry.type.mode
90 if mode == 'full':
91 suboffsetvars = [var(Naming.bufsuboffset_prefix, i, "-1") for i in range(entry.type.ndim)]
92 else:
93 suboffsetvars = None
95 entry.buffer_aux = Symtab.BufferAux(bufinfo, stridevars, shapevars, suboffsetvars)
97 scope.buffer_entries = bufvars
98 self.scope = scope
100 def visit_ModuleNode(self, node):
101 self.handle_scope(node, node.scope)
102 self.visitchildren(node)
103 return node
105 def visit_FuncDefNode(self, node):
106 self.handle_scope(node, node.local_scope)
107 self.visitchildren(node)
108 return node
110 #
111 # Analysis
112 #
113 buffer_options = ("dtype", "ndim", "mode", "negative_indices", "cast") # ordered!
114 buffer_defaults = {"ndim": 1, "mode": "full", "negative_indices": True, "cast": False}
115 buffer_positional_options_count = 1 # anything beyond this needs keyword argument
117 ERR_BUF_OPTION_UNKNOWN = '"%s" is not a buffer option'
118 ERR_BUF_TOO_MANY = 'Too many buffer options'
119 ERR_BUF_DUP = '"%s" buffer option already supplied'
120 ERR_BUF_MISSING = '"%s" missing'
121 ERR_BUF_MODE = 'Only allowed buffer modes are: "c", "fortran", "full", "strided" (as a compile-time string)'
122 ERR_BUF_NDIM = 'ndim must be a non-negative integer'
123 ERR_BUF_DTYPE = 'dtype must be "object", numeric type or a struct'
124 ERR_BUF_BOOL = '"%s" must be a boolean'
126 def analyse_buffer_options(globalpos, env, posargs, dictargs, defaults=None, need_complete=True):
127 """
128 Must be called during type analysis, as analyse is called
129 on the dtype argument.
131 posargs and dictargs should consist of a list and a dict
132 of tuples (value, pos). Defaults should be a dict of values.
134 Returns a dict containing all the options a buffer can have and
135 its value (with the positions stripped).
136 """
137 if defaults is None:
138 defaults = buffer_defaults
140 posargs, dictargs = Interpreter.interpret_compiletime_options(posargs, dictargs, type_env=env)
142 if len(posargs) > buffer_positional_options_count:
143 raise CompileError(posargs[-1][1], ERR_BUF_TOO_MANY)
145 options = {}
146 for name, (value, pos) in dictargs.iteritems():
147 if not name in buffer_options:
148 raise CompileError(pos, ERR_BUF_OPTION_UNKNOWN % name)
149 options[name] = value
151 for name, (value, pos) in zip(buffer_options, posargs):
152 if not name in buffer_options:
153 raise CompileError(pos, ERR_BUF_OPTION_UNKNOWN % name)
154 if name in options:
155 raise CompileError(pos, ERR_BUF_DUP % name)
156 options[name] = value
158 # Check that they are all there and copy defaults
159 for name in buffer_options:
160 if not name in options:
161 try:
162 options[name] = defaults[name]
163 except KeyError:
164 if need_complete:
165 raise CompileError(globalpos, ERR_BUF_MISSING % name)
167 dtype = options.get("dtype")
168 if dtype and dtype.is_extension_type:
169 raise CompileError(globalpos, ERR_BUF_DTYPE)
171 ndim = options.get("ndim")
172 if ndim and (not isinstance(ndim, int) or ndim < 0):
173 raise CompileError(globalpos, ERR_BUF_NDIM)
175 mode = options.get("mode")
176 if mode and not (mode in ('full', 'strided', 'c', 'fortran')):
177 raise CompileError(globalpos, ERR_BUF_MODE)
179 def assert_bool(name):
180 x = options.get(name)
181 if not isinstance(x, bool):
182 raise CompileError(globalpos, ERR_BUF_BOOL % name)
184 assert_bool('negative_indices')
185 assert_bool('cast')
187 return options
190 #
191 # Code generation
192 #
195 def get_flags(buffer_aux, buffer_type):
196 flags = 'PyBUF_FORMAT'
197 mode = buffer_type.mode
198 if mode == 'full':
199 flags += '| PyBUF_INDIRECT'
200 elif mode == 'strided':
201 flags += '| PyBUF_STRIDES'
202 elif mode == 'c':
203 flags += '| PyBUF_C_CONTIGUOUS'
204 elif mode == 'fortran':
205 flags += '| PyBUF_F_CONTIGUOUS'
206 else:
207 assert False
208 if buffer_aux.writable_needed: flags += "| PyBUF_WRITABLE"
209 return flags
211 def used_buffer_aux_vars(entry):
212 buffer_aux = entry.buffer_aux
213 buffer_aux.buffer_info_var.used = True
214 for s in buffer_aux.shapevars: s.used = True
215 for s in buffer_aux.stridevars: s.used = True
216 if buffer_aux.suboffsetvars:
217 for s in buffer_aux.suboffsetvars: s.used = True
219 def put_unpack_buffer_aux_into_scope(buffer_aux, mode, code):
220 # Generate code to copy the needed struct info into local
221 # variables.
222 bufstruct = buffer_aux.buffer_info_var.cname
224 varspec = [("strides", buffer_aux.stridevars),
225 ("shape", buffer_aux.shapevars)]
226 if mode == 'full':
227 varspec.append(("suboffsets", buffer_aux.suboffsetvars))
229 for field, vars in varspec:
230 code.putln(" ".join(["%s = %s.%s[%d];" %
231 (s.cname, bufstruct, field, idx)
232 for idx, s in enumerate(vars)]))
234 def put_acquire_arg_buffer(entry, code, pos):
235 code.globalstate.use_utility_code(acquire_utility_code)
236 buffer_aux = entry.buffer_aux
237 getbuffer = get_getbuffer_call(code, entry.cname, buffer_aux, entry.type)
239 # Acquire any new buffer
240 code.putln("{")
241 code.putln("__Pyx_BufFmt_StackElem __pyx_stack[%d];" % entry.type.dtype.struct_nesting_depth())
242 code.putln(code.error_goto_if("%s == -1" % getbuffer, pos))
243 code.putln("}")
244 # An exception raised in arg parsing cannot be catched, so no
245 # need to care about the buffer then.
246 put_unpack_buffer_aux_into_scope(buffer_aux, entry.type.mode, code)
248 def put_release_buffer_code(code, entry):
249 code.globalstate.use_utility_code(acquire_utility_code)
250 code.putln("__Pyx_SafeReleaseBuffer(&%s);" % entry.buffer_aux.buffer_info_var.cname)
252 def get_getbuffer_call(code, obj_cname, buffer_aux, buffer_type):
253 ndim = buffer_type.ndim
254 cast = int(buffer_type.cast)
255 flags = get_flags(buffer_aux, buffer_type)
256 bufstruct = buffer_aux.buffer_info_var.cname
258 dtype_typeinfo = get_type_information_cname(code, buffer_type.dtype)
260 return ("__Pyx_GetBufferAndValidate(&%(bufstruct)s, "
261 "(PyObject*)%(obj_cname)s, &%(dtype_typeinfo)s, %(flags)s, %(ndim)d, "
262 "%(cast)d, __pyx_stack)" % locals())
264 def put_assign_to_buffer(lhs_cname, rhs_cname, buffer_aux, buffer_type,
265 is_initialized, pos, code):
266 """
267 Generate code for reassigning a buffer variables. This only deals with getting
268 the buffer auxiliary structure and variables set up correctly, the assignment
269 itself and refcounting is the responsibility of the caller.
271 However, the assignment operation may throw an exception so that the reassignment
272 never happens.
274 Depending on the circumstances there are two possible outcomes:
275 - Old buffer released, new acquired, rhs assigned to lhs
276 - Old buffer released, new acquired which fails, reaqcuire old lhs buffer
277 (which may or may not succeed).
278 """
280 code.globalstate.use_utility_code(acquire_utility_code)
281 bufstruct = buffer_aux.buffer_info_var.cname
282 flags = get_flags(buffer_aux, buffer_type)
284 code.putln("{") # Set up necesarry stack for getbuffer
285 code.putln("__Pyx_BufFmt_StackElem __pyx_stack[%d];" % buffer_type.dtype.struct_nesting_depth())
287 getbuffer = get_getbuffer_call(code, "%s", buffer_aux, buffer_type) # fill in object below
289 if is_initialized:
290 # Release any existing buffer
291 code.putln('__Pyx_SafeReleaseBuffer(&%s);' % bufstruct)
292 # Acquire
293 retcode_cname = code.funcstate.allocate_temp(PyrexTypes.c_int_type, manage_ref=False)
294 code.putln("%s = %s;" % (retcode_cname, getbuffer % rhs_cname))
295 code.putln('if (%s) {' % (code.unlikely("%s < 0" % retcode_cname)))
296 # If acquisition failed, attempt to reacquire the old buffer
297 # before raising the exception. A failure of reacquisition
298 # will cause the reacquisition exception to be reported, one
299 # can consider working around this later.
300 type, value, tb = [code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=False)
301 for i in range(3)]
302 code.putln('PyErr_Fetch(&%s, &%s, &%s);' % (type, value, tb))
303 code.putln('if (%s) {' % code.unlikely("%s == -1" % (getbuffer % lhs_cname)))
304 code.putln('Py_XDECREF(%s); Py_XDECREF(%s); Py_XDECREF(%s);' % (type, value, tb)) # Do not refnanny these!
305 code.globalstate.use_utility_code(raise_buffer_fallback_code)
306 code.putln('__Pyx_RaiseBufferFallbackError();')
307 code.putln('} else {')
308 code.putln('PyErr_Restore(%s, %s, %s);' % (type, value, tb))
309 for t in (type, value, tb):
310 code.funcstate.release_temp(t)
311 code.putln('}')
312 code.putln('}')
313 # Unpack indices
314 put_unpack_buffer_aux_into_scope(buffer_aux, buffer_type.mode, code)
315 code.putln(code.error_goto_if_neg(retcode_cname, pos))
316 code.funcstate.release_temp(retcode_cname)
317 else:
318 # Our entry had no previous value, so set to None when acquisition fails.
319 # In this case, auxiliary vars should be set up right in initialization to a zero-buffer,
320 # so it suffices to set the buf field to NULL.
321 code.putln('if (%s) {' % code.unlikely("%s == -1" % (getbuffer % rhs_cname)))
322 code.putln('%s = %s; __Pyx_INCREF(Py_None); %s.buf = NULL;' %
323 (lhs_cname,
324 PyrexTypes.typecast(buffer_type, PyrexTypes.py_object_type, "Py_None"),
325 bufstruct))
326 code.putln(code.error_goto(pos))
327 code.put('} else {')
328 # Unpack indices
329 put_unpack_buffer_aux_into_scope(buffer_aux, buffer_type.mode, code)
330 code.putln('}')
332 code.putln("}") # Release stack
334 def put_buffer_lookup_code(entry, index_signeds, index_cnames, directives, pos, code):
335 """
336 Generates code to process indices and calculate an offset into
337 a buffer. Returns a C string which gives a pointer which can be
338 read from or written to at will (it is an expression so caller should
339 store it in a temporary if it is used more than once).
341 As the bounds checking can have any number of combinations of unsigned
342 arguments, smart optimizations etc. we insert it directly in the function
343 body. The lookup however is delegated to a inline function that is instantiated
344 once per ndim (lookup with suboffsets tend to get quite complicated).
346 """
347 bufaux = entry.buffer_aux
348 bufstruct = bufaux.buffer_info_var.cname
349 negative_indices = directives['wraparound'] and entry.type.negative_indices
351 if directives['boundscheck']:
352 # Check bounds and fix negative indices.
353 # We allocate a temporary which is initialized to -1, meaning OK (!).
354 # If an error occurs, the temp is set to the dimension index the
355 # error is occuring at.
356 tmp_cname = code.funcstate.allocate_temp(PyrexTypes.c_int_type, manage_ref=False)
357 code.putln("%s = -1;" % tmp_cname)
358 for dim, (signed, cname, shape) in enumerate(zip(index_signeds, index_cnames,
359 bufaux.shapevars)):
360 if signed != 0:
361 # not unsigned, deal with negative index
362 code.putln("if (%s < 0) {" % cname)
363 if negative_indices:
364 code.putln("%s += %s;" % (cname, shape.cname))
365 code.putln("if (%s) %s = %d;" % (
366 code.unlikely("%s < 0" % cname), tmp_cname, dim))
367 else:
368 code.putln("%s = %d;" % (tmp_cname, dim))
369 code.put("} else ")
370 # check bounds in positive direction
371 code.putln("if (%s) %s = %d;" % (
372 code.unlikely("%s >= %s" % (cname, shape.cname)),
373 tmp_cname, dim))
374 code.globalstate.use_utility_code(raise_indexerror_code)
375 code.putln("if (%s) {" % code.unlikely("%s != -1" % tmp_cname))
376 code.putln('__Pyx_RaiseBufferIndexError(%s);' % tmp_cname)
377 code.putln(code.error_goto(pos))
378 code.putln('}')
379 code.funcstate.release_temp(tmp_cname)
380 elif negative_indices:
381 # Only fix negative indices.
382 for signed, cname, shape in zip(index_signeds, index_cnames,
383 bufaux.shapevars):
384 if signed != 0:
385 code.putln("if (%s < 0) %s += %s;" % (cname, cname, shape.cname))
387 # Create buffer lookup and return it
388 # This is done via utility macros/inline functions, which vary
389 # according to the access mode used.
390 params = []
391 nd = entry.type.ndim
392 mode = entry.type.mode
393 if mode == 'full':
394 for i, s, o in zip(index_cnames, bufaux.stridevars, bufaux.suboffsetvars):
395 params.append(i)
396 params.append(s.cname)
397 params.append(o.cname)
398 funcname = "__Pyx_BufPtrFull%dd" % nd
399 funcgen = buf_lookup_full_code
400 else:
401 if mode == 'strided':
402 funcname = "__Pyx_BufPtrStrided%dd" % nd
403 funcgen = buf_lookup_strided_code
404 elif mode == 'c':
405 funcname = "__Pyx_BufPtrCContig%dd" % nd
406 funcgen = buf_lookup_c_code
407 elif mode == 'fortran':
408 funcname = "__Pyx_BufPtrFortranContig%dd" % nd
409 funcgen = buf_lookup_fortran_code
410 else:
411 assert False
412 for i, s in zip(index_cnames, bufaux.stridevars):
413 params.append(i)
414 params.append(s.cname)
416 # Make sure the utility code is available
417 if funcname not in code.globalstate.utility_codes:
418 code.globalstate.utility_codes.add(funcname)
419 protocode = code.globalstate['utility_code_proto']
420 defcode = code.globalstate['utility_code_def']
421 funcgen(protocode, defcode, name=funcname, nd=nd)
423 ptr_type = entry.type.buffer_ptr_type
424 ptrcode = "%s(%s, %s.buf, %s)" % (funcname,
425 ptr_type.declaration_code(""),
426 bufstruct,
427 ", ".join(params))
428 return ptrcode
431 def use_empty_bufstruct_code(env, max_ndim):
432 code = dedent("""
433 Py_ssize_t __Pyx_zeros[] = {%s};
434 Py_ssize_t __Pyx_minusones[] = {%s};
435 """) % (", ".join(["0"] * max_ndim), ", ".join(["-1"] * max_ndim))
436 env.use_utility_code(UtilityCode(proto=code))
439 def buf_lookup_full_code(proto, defin, name, nd):
440 """
441 Generates a buffer lookup function for the right number
442 of dimensions. The function gives back a void* at the right location.
443 """
444 # _i_ndex, _s_tride, sub_o_ffset
445 macroargs = ", ".join(["i%d, s%d, o%d" % (i, i, i) for i in range(nd)])
446 proto.putln("#define %s(type, buf, %s) (type)(%s_imp(buf, %s))" % (name, macroargs, name, macroargs))
448 funcargs = ", ".join(["Py_ssize_t i%d, Py_ssize_t s%d, Py_ssize_t o%d" % (i, i, i) for i in range(nd)])
449 proto.putln("static CYTHON_INLINE void* %s_imp(void* buf, %s);" % (name, funcargs))
450 defin.putln(dedent("""
451 static CYTHON_INLINE void* %s_imp(void* buf, %s) {
452 char* ptr = (char*)buf;
453 """) % (name, funcargs) + "".join([dedent("""\
454 ptr += s%d * i%d;
455 if (o%d >= 0) ptr = *((char**)ptr) + o%d;
456 """) % (i, i, i, i) for i in range(nd)]
457 ) + "\nreturn ptr;\n}")
459 def buf_lookup_strided_code(proto, defin, name, nd):
460 """
461 Generates a buffer lookup function for the right number
462 of dimensions. The function gives back a void* at the right location.
463 """
464 # _i_ndex, _s_tride
465 args = ", ".join(["i%d, s%d" % (i, i) for i in range(nd)])
466 offset = " + ".join(["i%d * s%d" % (i, i) for i in range(nd)])
467 proto.putln("#define %s(type, buf, %s) (type)((char*)buf + %s)" % (name, args, offset))
469 def buf_lookup_c_code(proto, defin, name, nd):
470 """
471 Similar to strided lookup, but can assume that the last dimension
472 doesn't need a multiplication as long as.
473 Still we keep the same signature for now.
474 """
475 if nd == 1:
476 proto.putln("#define %s(type, buf, i0, s0) ((type)buf + i0)" % name)
477 else:
478 args = ", ".join(["i%d, s%d" % (i, i) for i in range(nd)])
479 offset = " + ".join(["i%d * s%d" % (i, i) for i in range(nd - 1)])
480 proto.putln("#define %s(type, buf, %s) ((type)((char*)buf + %s) + i%d)" % (name, args, offset, nd - 1))
482 def buf_lookup_fortran_code(proto, defin, name, nd):
483 """
484 Like C lookup, but the first index is optimized instead.
485 """
486 if nd == 1:
487 proto.putln("#define %s(type, buf, i0, s0) ((type)buf + i0)" % name)
488 else:
489 args = ", ".join(["i%d, s%d" % (i, i) for i in range(nd)])
490 offset = " + ".join(["i%d * s%d" % (i, i) for i in range(1, nd)])
491 proto.putln("#define %s(type, buf, %s) ((type)((char*)buf + %s) + i%d)" % (name, args, offset, 0))
494 def use_py2_buffer_functions(env):
495 # Emulation of PyObject_GetBuffer and PyBuffer_Release for Python 2.
496 # For >= 2.6 we do double mode -- use the new buffer interface on objects
497 # which has the right tp_flags set, but emulation otherwise.
499 # Search all types for __getbuffer__ overloads
500 types = []
501 visited_scopes = set()
502 def find_buffer_types(scope):
503 if scope in visited_scopes:
504 return
505 visited_scopes.add(scope)
506 for m in scope.cimported_modules:
507 find_buffer_types(m)
508 for e in scope.type_entries:
509 t = e.type
510 if t.is_extension_type:
511 release = get = None
512 for x in t.scope.pyfunc_entries:
513 if x.name == u"__getbuffer__": get = x.func_cname
514 elif x.name == u"__releasebuffer__": release = x.func_cname
515 if get:
516 types.append((t.typeptr_cname, get, release))
518 find_buffer_types(env)
520 code = dedent("""
521 #if PY_MAJOR_VERSION < 3
522 static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags) {
523 #if PY_VERSION_HEX >= 0x02060000
524 if (Py_TYPE(obj)->tp_flags & Py_TPFLAGS_HAVE_NEWBUFFER)
525 return PyObject_GetBuffer(obj, view, flags);
526 #endif
527 """)
528 if len(types) > 0:
529 clause = "if"
530 for t, get, release in types:
531 code += " %s (PyObject_TypeCheck(obj, %s)) return %s(obj, view, flags);\n" % (clause, t, get)
532 clause = "else if"
533 code += " else {\n"
534 code += dedent("""\
535 PyErr_Format(PyExc_TypeError, "'%100s' does not have the buffer interface", Py_TYPE(obj)->tp_name);
536 return -1;
537 """, 2)
538 if len(types) > 0: code += " }"
539 code += dedent("""
540 }
542 static void __Pyx_ReleaseBuffer(Py_buffer *view) {
543 PyObject* obj = view->obj;
544 if (obj) {
545 """)
546 if len(types) > 0:
547 clause = "if"
548 for t, get, release in types:
549 if release:
550 code += "%s (PyObject_TypeCheck(obj, %s)) %s(obj, view);" % (clause, t, release)
551 clause = "else if"
552 code += dedent("""
553 Py_DECREF(obj);
554 view->obj = NULL;
555 }
556 }
558 #endif
559 """)
561 env.use_utility_code(UtilityCode(
562 proto = dedent("""\
563 #if PY_MAJOR_VERSION < 3
564 static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags);
565 static void __Pyx_ReleaseBuffer(Py_buffer *view);
566 #else
567 #define __Pyx_GetBuffer PyObject_GetBuffer
568 #define __Pyx_ReleaseBuffer PyBuffer_Release
569 #endif
570 """), impl = code))
573 def mangle_dtype_name(dtype):
574 # Use prefixes to seperate user defined types from builtins
575 # (consider "typedef float unsigned_int")
576 if dtype.is_pyobject:
577 return "object"
578 elif dtype.is_ptr:
579 return "ptr"
580 else:
581 if dtype.is_typedef or dtype.is_struct_or_union:
582 prefix = "nn_"
583 else:
584 prefix = ""
585 return prefix + dtype.declaration_code("").replace(" ", "_")
587 def get_type_information_cname(code, dtype, maxdepth=None):
588 # Output the run-time type information (__Pyx_TypeInfo) for given dtype,
589 # and return the name of the type info struct.
590 #
591 # Structs with two floats of the same size are encoded as complex numbers.
592 # One can seperate between complex numbers declared as struct or with native
593 # encoding by inspecting to see if the fields field of the type is
594 # filled in.
595 namesuffix = mangle_dtype_name(dtype)
596 name = "__Pyx_TypeInfo_%s" % namesuffix
597 structinfo_name = "__Pyx_StructFields_%s" % namesuffix
599 if dtype.is_error: return "<error>"
601 # It's critical that walking the type info doesn't use more stack
602 # depth than dtype.struct_nesting_depth() returns, so use an assertion for this
603 if maxdepth is None: maxdepth = dtype.struct_nesting_depth()
604 if maxdepth <= 0:
605 assert False
607 if name not in code.globalstate.utility_codes:
608 code.globalstate.utility_codes.add(name)
609 typecode = code.globalstate['typeinfo']
611 complex_possible = dtype.is_struct_or_union and dtype.can_be_complex()
613 declcode = dtype.declaration_code("")
614 if dtype.is_simple_buffer_dtype():
615 structinfo_name = "NULL"
616 elif dtype.is_struct:
617 fields = dtype.scope.var_entries
618 # Must pre-call all used types in order not to recurse utility code
619 # writing.
620 assert len(fields) > 0
621 types = [get_type_information_cname(code, f.type, maxdepth - 1)
622 for f in fields]
623 typecode.putln("static __Pyx_StructField %s[] = {" % structinfo_name, safe=True)
624 for f, typeinfo in zip(fields, types):
625 typecode.putln(' {&%s, "%s", offsetof(%s, %s)},' %
626 (typeinfo, f.name, dtype.declaration_code(""), f.cname), safe=True)
627 typecode.putln(' {NULL, NULL, 0}', safe=True)
628 typecode.putln("};", safe=True)
629 else:
630 assert False
632 rep = str(dtype)
633 if dtype.is_int:
634 if dtype.signed == 0:
635 typegroup = 'U'
636 else:
637 typegroup = 'I'
638 elif complex_possible or dtype.is_complex:
639 typegroup = 'C'
640 elif dtype.is_float:
641 typegroup = 'R'
642 elif dtype.is_struct:
643 typegroup = 'S'
644 elif dtype.is_pyobject:
645 typegroup = 'O'
646 else:
647 print dtype
648 assert False
650 typecode.putln(('static __Pyx_TypeInfo %s = { "%s", %s, sizeof(%s), \'%s\' };'
651 ) % (name,
652 rep,
653 structinfo_name,
654 declcode,
655 typegroup,
656 ), safe=True)
657 return name
660 # Utility function to set the right exception
661 # The caller should immediately goto_error
662 raise_indexerror_code = UtilityCode(
663 proto = """\
664 static void __Pyx_RaiseBufferIndexError(int axis); /*proto*/
665 """,
666 impl = """\
667 static void __Pyx_RaiseBufferIndexError(int axis) {
668 PyErr_Format(PyExc_IndexError,
669 "Out of bounds on buffer access (axis %d)", axis);
670 }
672 """)
674 parse_typestring_repeat_code = UtilityCode(
675 proto = """
676 """,
677 impl = """
678 """)
680 raise_buffer_fallback_code = UtilityCode(
681 proto = """
682 static void __Pyx_RaiseBufferFallbackError(void); /*proto*/
683 """,
684 impl = """
685 static void __Pyx_RaiseBufferFallbackError(void) {
686 PyErr_Format(PyExc_ValueError,
687 "Buffer acquisition failed on assignment; and then reacquiring the old buffer failed too!");
688 }
690 """)
694 #
695 # Buffer format string checking
696 #
697 # Buffer type checking. Utility code for checking that acquired
698 # buffers match our assumptions. We only need to check ndim and
699 # the format string; the access mode/flags is checked by the
700 # exporter.
701 #
702 # The alignment code is copied from _struct.c in Python.
703 acquire_utility_code = UtilityCode(proto="""
704 /* Run-time type information about structs used with buffers */
705 struct __Pyx_StructField_;
707 typedef struct {
708 const char* name; /* for error messages only */
709 struct __Pyx_StructField_* fields;
710 size_t size; /* sizeof(type) */
711 char typegroup; /* _R_eal, _C_omplex, Signed _I_nt, _U_nsigned int, _S_truct, _P_ointer, _O_bject */
712 } __Pyx_TypeInfo;
714 typedef struct __Pyx_StructField_ {
715 __Pyx_TypeInfo* type;
716 const char* name;
717 size_t offset;
718 } __Pyx_StructField;
720 typedef struct {
721 __Pyx_StructField* field;
722 size_t parent_offset;
723 } __Pyx_BufFmt_StackElem;
726 static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info);
727 static int __Pyx_GetBufferAndValidate(Py_buffer* buf, PyObject* obj, __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack);
728 """, impl="""
729 static CYTHON_INLINE int __Pyx_IsLittleEndian(void) {
730 unsigned int n = 1;
731 return *(unsigned char*)(&n) != 0;
732 }
734 typedef struct {
735 __Pyx_StructField root;
736 __Pyx_BufFmt_StackElem* head;
737 size_t fmt_offset;
738 int new_count, enc_count;
739 int is_complex;
740 char enc_type;
741 char packmode;
742 } __Pyx_BufFmt_Context;
744 static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx,
745 __Pyx_BufFmt_StackElem* stack,
746 __Pyx_TypeInfo* type) {
747 stack[0].field = &ctx->root;
748 stack[0].parent_offset = 0;
749 ctx->root.type = type;
750 ctx->root.name = "buffer dtype";
751 ctx->root.offset = 0;
752 ctx->head = stack;
753 ctx->head->field = &ctx->root;
754 ctx->fmt_offset = 0;
755 ctx->head->parent_offset = 0;
756 ctx->packmode = '@';
757 ctx->new_count = 1;
758 ctx->enc_count = 0;
759 ctx->enc_type = 0;
760 ctx->is_complex = 0;
761 while (type->typegroup == 'S') {
762 ++ctx->head;
763 ctx->head->field = type->fields;
764 ctx->head->parent_offset = 0;
765 type = type->fields->type;
766 }
767 }
769 static int __Pyx_BufFmt_ParseNumber(const char** ts) {
770 int count;
771 const char* t = *ts;
772 if (*t < '0' || *t > '9') {
773 return -1;
774 } else {
775 count = *t++ - '0';
776 while (*t >= '0' && *t < '9') {
777 count *= 10;
778 count += *t++ - '0';
779 }
780 }
781 *ts = t;
782 return count;
783 }
785 static void __Pyx_BufFmt_RaiseUnexpectedChar(char ch) {
786 char msg[] = {ch, 0};
787 PyErr_Format(PyExc_ValueError, "Unexpected format string character: '%s'", msg);
788 }
790 static const char* __Pyx_BufFmt_DescribeTypeChar(char ch, int is_complex) {
791 switch (ch) {
792 case 'b': return "'char'";
793 case 'B': return "'unsigned char'";
794 case 'h': return "'short'";
795 case 'H': return "'unsigned short'";
796 case 'i': return "'int'";
797 case 'I': return "'unsigned int'";
798 case 'l': return "'long'";
799 case 'L': return "'unsigned long'";
800 case 'q': return "'long long'";
801 case 'Q': return "'unsigned long long'";
802 case 'f': return (is_complex ? "'complex float'" : "'float'");
803 case 'd': return (is_complex ? "'complex double'" : "'double'");
804 case 'g': return (is_complex ? "'complex long double'" : "'long double'");
805 case 'T': return "a struct";
806 case 'O': return "Python object";
807 case 'P': return "a pointer";
808 case 0: return "end";
809 default: return "unparseable format string";
810 }
811 }
813 static size_t __Pyx_BufFmt_TypeCharToStandardSize(char ch, int is_complex) {
814 switch (ch) {
815 case '?': case 'c': case 'b': case 'B': return 1;
816 case 'h': case 'H': return 2;
817 case 'i': case 'I': case 'l': case 'L': return 4;
818 case 'q': case 'Q': return 8;
819 case 'f': return (is_complex ? 8 : 4);
820 case 'd': return (is_complex ? 16 : 8);
821 case 'g': {
822 PyErr_SetString(PyExc_ValueError, "Python does not define a standard format string size for long double ('g')..");
823 return 0;
824 }
825 case 'O': case 'P': return sizeof(void*);
826 default:
827 __Pyx_BufFmt_RaiseUnexpectedChar(ch);
828 return 0;
829 }
830 }
832 static size_t __Pyx_BufFmt_TypeCharToNativeSize(char ch, int is_complex) {
833 switch (ch) {
834 case 'c': case 'b': case 'B': return 1;
835 case 'h': case 'H': return sizeof(short);
836 case 'i': case 'I': return sizeof(int);
837 case 'l': case 'L': return sizeof(long);
838 #ifdef HAVE_LONG_LONG
839 case 'q': case 'Q': return sizeof(PY_LONG_LONG);
840 #endif
841 case 'f': return sizeof(float) * (is_complex ? 2 : 1);
842 case 'd': return sizeof(double) * (is_complex ? 2 : 1);
843 case 'g': return sizeof(long double) * (is_complex ? 2 : 1);
844 case 'O': case 'P': return sizeof(void*);
845 default: {
846 __Pyx_BufFmt_RaiseUnexpectedChar(ch);
847 return 0;
848 }
849 }
850 }
852 typedef struct { char c; short x; } __Pyx_st_short;
853 typedef struct { char c; int x; } __Pyx_st_int;
854 typedef struct { char c; long x; } __Pyx_st_long;
855 typedef struct { char c; float x; } __Pyx_st_float;
856 typedef struct { char c; double x; } __Pyx_st_double;
857 typedef struct { char c; long double x; } __Pyx_st_longdouble;
858 typedef struct { char c; void *x; } __Pyx_st_void_p;
859 #ifdef HAVE_LONG_LONG
860 typedef struct { char c; PY_LONG_LONG x; } __Pyx_s_long_long;
861 #endif
863 static size_t __Pyx_BufFmt_TypeCharToAlignment(char ch, int is_complex) {
864 switch (ch) {
865 case '?': case 'c': case 'b': case 'B': return 1;
866 case 'h': case 'H': return sizeof(__Pyx_st_short) - sizeof(short);
867 case 'i': case 'I': return sizeof(__Pyx_st_int) - sizeof(int);
868 case 'l': case 'L': return sizeof(__Pyx_st_long) - sizeof(long);
869 #ifdef HAVE_LONG_LONG
870 case 'q': case 'Q': return sizeof(__Pyx_s_long_long) - sizeof(PY_LONG_LONG);
871 #endif
872 case 'f': return sizeof(__Pyx_st_float) - sizeof(float);
873 case 'd': return sizeof(__Pyx_st_double) - sizeof(double);
874 case 'g': return sizeof(__Pyx_st_longdouble) - sizeof(long double);
875 case 'P': case 'O': return sizeof(__Pyx_st_void_p) - sizeof(void*);
876 default:
877 __Pyx_BufFmt_RaiseUnexpectedChar(ch);
878 return 0;
879 }
880 }
882 static size_t __Pyx_BufFmt_TypeCharToGroup(char ch, int is_complex) {
883 switch (ch) {
884 case 'c': case 'b': case 'h': case 'i': case 'l': case 'q': return 'I';
885 case 'B': case 'H': case 'I': case 'L': case 'Q': return 'U';
886 case 'f': case 'd': case 'g': return (is_complex ? 'C' : 'R');
887 case 'O': return 'O';
888 case 'P': return 'P';
889 default: {
890 __Pyx_BufFmt_RaiseUnexpectedChar(ch);
891 return 0;
892 }
893 }
894 }
896 static void __Pyx_BufFmt_RaiseExpected(__Pyx_BufFmt_Context* ctx) {
897 if (ctx->head == NULL || ctx->head->field == &ctx->root) {
898 const char* expected;
899 const char* quote;
900 if (ctx->head == NULL) {
901 expected = "end";
902 quote = "";
903 } else {
904 expected = ctx->head->field->type->name;
905 quote = "'";
906 }
907 PyErr_Format(PyExc_ValueError,
908 "Buffer dtype mismatch, expected %s%s%s but got %s",
909 quote, expected, quote,
910 __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex));
911 } else {
912 __Pyx_StructField* field = ctx->head->field;
913 __Pyx_StructField* parent = (ctx->head - 1)->field;
914 PyErr_Format(PyExc_ValueError,
915 "Buffer dtype mismatch, expected '%s' but got %s in '%s.%s'",
916 field->type->name, __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex),
917 parent->type->name, field->name);
918 }
919 }
921 static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) {
922 char group;
923 size_t size, offset;
924 if (ctx->enc_type == 0) return 0;
925 group = __Pyx_BufFmt_TypeCharToGroup(ctx->enc_type, ctx->is_complex);
926 do {
927 __Pyx_StructField* field = ctx->head->field;
928 __Pyx_TypeInfo* type = field->type;
930 if (ctx->packmode == '@' || ctx->packmode == '^') {
931 size = __Pyx_BufFmt_TypeCharToNativeSize(ctx->enc_type, ctx->is_complex);
932 } else {
933 size = __Pyx_BufFmt_TypeCharToStandardSize(ctx->enc_type, ctx->is_complex);
934 }
935 if (ctx->packmode == '@') {
936 int align_at = __Pyx_BufFmt_TypeCharToAlignment(ctx->enc_type, ctx->is_complex);
937 int align_mod_offset;
938 if (align_at == 0) return -1;
939 align_mod_offset = ctx->fmt_offset % align_at;
940 if (align_mod_offset > 0) ctx->fmt_offset += align_at - align_mod_offset;
941 }
943 if (type->size != size || type->typegroup != group) {
944 if (type->typegroup == 'C' && type->fields != NULL) {
945 /* special case -- treat as struct rather than complex number */
946 size_t parent_offset = ctx->head->parent_offset + field->offset;
947 ++ctx->head;
948 ctx->head->field = type->fields;
949 ctx->head->parent_offset = parent_offset;
950 continue;
951 }
953 __Pyx_BufFmt_RaiseExpected(ctx);
954 return -1;
955 }
957 offset = ctx->head->parent_offset + field->offset;
958 if (ctx->fmt_offset != offset) {
959 PyErr_Format(PyExc_ValueError,
960 "Buffer dtype mismatch; next field is at offset %"PY_FORMAT_SIZE_T"d "
961 "but %"PY_FORMAT_SIZE_T"d expected", ctx->fmt_offset, offset);
962 return -1;
963 }
965 ctx->fmt_offset += size;
967 --ctx->enc_count; /* Consume from buffer string */
969 /* Done checking, move to next field, pushing or popping struct stack if needed */
970 while (1) {
971 if (field == &ctx->root) {
972 ctx->head = NULL;
973 if (ctx->enc_count != 0) {
974 __Pyx_BufFmt_RaiseExpected(ctx);
975 return -1;
976 }
977 break; /* breaks both loops as ctx->enc_count == 0 */
978 }
979 ctx->head->field = ++field;
980 if (field->type == NULL) {
981 --ctx->head;
982 field = ctx->head->field;
983 continue;
984 } else if (field->type->typegroup == 'S') {
985 size_t parent_offset = ctx->head->parent_offset + field->offset;
986 if (field->type->fields->type == NULL) continue; /* empty struct */
987 field = field->type->fields;
988 ++ctx->head;
989 ctx->head->field = field;
990 ctx->head->parent_offset = parent_offset;
991 break;
992 } else {
993 break;
994 }
995 }
996 } while (ctx->enc_count);
997 ctx->enc_type = 0;
998 ctx->is_complex = 0;
999 return 0;
1000 }
1002 static int __Pyx_BufFmt_FirstPack(__Pyx_BufFmt_Context* ctx) {
1003 if (ctx->enc_type != 0 || ctx->packmode != '@') {
1004 PyErr_SetString(PyExc_ValueError, "Buffer packing mode currently only allowed at beginning of format string (this is a defect)");
1005 return -1;
1006 }
1007 return 0;
1008 }
1010 static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts) {
1011 int got_Z = 0;
1012 while (1) {
1013 switch(*ts) {
1014 case 0:
1015 if (ctx->enc_type != 0 && ctx->head == NULL) {
1016 __Pyx_BufFmt_RaiseExpected(ctx);
1017 return NULL;
1018 }
1019 if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
1020 if (ctx->head != NULL) {
1021 __Pyx_BufFmt_RaiseExpected(ctx);
1022 return NULL;
1023 }
1024 return ts;
1025 case ' ':
1026 case 10:
1027 case 13:
1028 ++ts;
1029 break;
1030 case '<':
1031 if (!__Pyx_IsLittleEndian()) {
1032 PyErr_SetString(PyExc_ValueError, "Little-endian buffer not supported on big-endian compiler");
1033 return NULL;
1034 }
1035 if (__Pyx_BufFmt_FirstPack(ctx) == -1) return NULL;
1036 ctx->packmode = '=';
1037 ++ts;
1038 break;
1039 case '>':
1040 case '!':
1041 if (__Pyx_IsLittleEndian()) {
1042 PyErr_SetString(PyExc_ValueError, "Big-endian buffer not supported on little-endian compiler");
1043 return NULL;
1044 }
1045 if (__Pyx_BufFmt_FirstPack(ctx) == -1) return NULL;
1046 ctx->packmode = '=';
1047 ++ts;
1048 break;
1049 case '=':
1050 case '@':
1051 case '^':
1052 if (__Pyx_BufFmt_FirstPack(ctx) == -1) return NULL;
1053 ctx->packmode = *ts++;
1054 break;
1055 case 'T': /* substruct */
1056 {
1057 int i;
1058 const char* ts_after_sub;
1059 int struct_count = ctx->new_count;
1060 ctx->new_count = 1;
1061 ++ts;
1062 if (*ts != '{') {
1063 PyErr_SetString(PyExc_ValueError, "Buffer acquisition: Expected '{' after 'T'");
1064 return NULL;
1065 }
1066 ++ts;
1067 ts_after_sub = ts;
1068 for (i = 0; i != struct_count; ++i) {
1069 ts_after_sub = __Pyx_BufFmt_CheckString(ctx, ts);
1070 if (!ts_after_sub) return NULL;
1071 }
1072 ts = ts_after_sub;
1073 }
1074 break;
1075 case '}': /* end of substruct; either repeat or move on */
1076 ++ts;
1077 return ts;
1078 case 'x':
1079 if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
1080 ctx->fmt_offset += ctx->new_count;
1081 ctx->new_count = 1;
1082 ctx->enc_count = 0;
1083 ctx->enc_type = 0;
1084 ++ts;
1085 break;
1086 case 'Z':
1087 got_Z = 1;
1088 ++ts;
1089 if (*ts != 'f' && *ts != 'd' && *ts != 'g') {
1090 __Pyx_BufFmt_RaiseUnexpectedChar('Z');
1091 return NULL;
1092 } /* fall through */
1093 case 'c': case 'b': case 'B': case 'h': case 'H': case 'i': case 'I':
1094 case 'l': case 'L': case 'q': case 'Q':
1095 case 'f': case 'd': case 'g':
1096 case 'O':
1097 if (ctx->enc_type == *ts && got_Z == ctx->is_complex) {
1098 /* Continue pooling same type */
1099 ctx->enc_count += ctx->new_count;
1100 } else {
1101 /* New type */
1102 if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
1103 ctx->enc_count = ctx->new_count;
1104 ctx->enc_type = *ts;
1105 ctx->is_complex = got_Z;
1106 }
1107 ++ts;
1108 ctx->new_count = 1;
1109 got_Z = 0;
1110 break;
1111 default:
1112 {
1113 ctx->new_count = __Pyx_BufFmt_ParseNumber(&ts);
1114 if (ctx->new_count == -1) { /* First char was not a digit */
1115 char msg[2] = { *ts, 0 };
1116 PyErr_Format(PyExc_ValueError,
1117 "Does not understand character buffer dtype format string ('%s')", msg);
1118 return NULL;
1119 }
1120 }
1122 }
1123 }
1124 }
1126 static CYTHON_INLINE void __Pyx_ZeroBuffer(Py_buffer* buf) {
1127 buf->buf = NULL;
1128 buf->obj = NULL;
1129 buf->strides = __Pyx_zeros;
1130 buf->shape = __Pyx_zeros;
1131 buf->suboffsets = __Pyx_minusones;
1132 }
1134 static int __Pyx_GetBufferAndValidate(Py_buffer* buf, PyObject* obj, __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack) {
1135 if (obj == Py_None) {
1136 __Pyx_ZeroBuffer(buf);
1137 return 0;
1138 }
1139 buf->buf = NULL;
1140 if (__Pyx_GetBuffer(obj, buf, flags) == -1) goto fail;
1141 if (buf->ndim != nd) {
1142 PyErr_Format(PyExc_ValueError,
1143 "Buffer has wrong number of dimensions (expected %d, got %d)",
1144 nd, buf->ndim);
1145 goto fail;
1146 }
1147 if (!cast) {
1148 __Pyx_BufFmt_Context ctx;
1149 __Pyx_BufFmt_Init(&ctx, stack, dtype);
1150 if (!__Pyx_BufFmt_CheckString(&ctx, buf->format)) goto fail;
1151 }
1152 if ((unsigned)buf->itemsize != dtype->size) {
1153 PyErr_Format(PyExc_ValueError,
1154 "Item size of buffer (%"PY_FORMAT_SIZE_T"d byte%s) does not match size of '%s' (%"PY_FORMAT_SIZE_T"d byte%s)",
1155 buf->itemsize, (buf->itemsize > 1) ? "s" : "",
1156 dtype->name,
1157 dtype->size, (dtype->size > 1) ? "s" : "");
1158 goto fail;
1159 }
1160 if (buf->suboffsets == NULL) buf->suboffsets = __Pyx_minusones;
1161 return 0;
1162 fail:;
1163 __Pyx_ZeroBuffer(buf);
1164 return -1;
1165 }
1167 static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info) {
1168 if (info->buf == NULL) return;
1169 if (info->suboffsets == __Pyx_minusones) info->suboffsets = NULL;
1170 __Pyx_ReleaseBuffer(info);
1171 }
1172 """)
