1# cython.* namespace for pure mode.
2from __future__ import absolute_import
3
4__version__ = "0.29.13"
5
6try:
7    from __builtin__ import basestring
8except ImportError:
9    basestring = str
10
11
12# BEGIN shameless copy from Cython/minivect/minitypes.py
13
14class _ArrayType(object):
15
16    is_array = True
17    subtypes = ['dtype']
18
19    def __init__(self, dtype, ndim, is_c_contig=False, is_f_contig=False,
20                 inner_contig=False, broadcasting=None):
21        self.dtype = dtype
22        self.ndim = ndim
23        self.is_c_contig = is_c_contig
24        self.is_f_contig = is_f_contig
25        self.inner_contig = inner_contig or is_c_contig or is_f_contig
26        self.broadcasting = broadcasting
27
28    def __repr__(self):
29        axes = [":"] * self.ndim
30        if self.is_c_contig:
31            axes[-1] = "::1"
32        elif self.is_f_contig:
33            axes[0] = "::1"
34
35        return "%s[%s]" % (self.dtype, ", ".join(axes))
36
37
38def index_type(base_type, item):
39    """
40    Support array type creation by slicing, e.g. double[:, :] specifies
41    a 2D strided array of doubles. The syntax is the same as for
42    Cython memoryviews.
43    """
44    class InvalidTypeSpecification(Exception):
45        pass
46
47    def verify_slice(s):
48        if s.start or s.stop or s.step not in (None, 1):
49            raise InvalidTypeSpecification(
50                "Only a step of 1 may be provided to indicate C or "
51                "Fortran contiguity")
52
53    if isinstance(item, tuple):
54        step_idx = None
55        for idx, s in enumerate(item):
56            verify_slice(s)
57            if s.step and (step_idx or idx not in (0, len(item) - 1)):
58                raise InvalidTypeSpecification(
59                    "Step may only be provided once, and only in the "
60                    "first or last dimension.")
61
62            if s.step == 1:
63                step_idx = idx
64
65        return _ArrayType(base_type, len(item),
66                          is_c_contig=step_idx == len(item) - 1,
67                          is_f_contig=step_idx == 0)
68    elif isinstance(item, slice):
69        verify_slice(item)
70        return _ArrayType(base_type, 1, is_c_contig=bool(item.step))
71    else:
72        # int[8] etc.
73        assert int(item) == item  # array size must be a plain integer
74        array(base_type, item)
75
76# END shameless copy
77
78
79compiled = False
80
81_Unspecified = object()
82
83# Function decorators
84
85def _empty_decorator(x):
86    return x
87
88def locals(**arg_types):
89    return _empty_decorator
90
91def test_assert_path_exists(*paths):
92    return _empty_decorator
93
94def test_fail_if_path_exists(*paths):
95    return _empty_decorator
96
97class _EmptyDecoratorAndManager(object):
98    def __call__(self, x):
99        return x
100    def __enter__(self):
101        pass
102    def __exit__(self, exc_type, exc_value, traceback):
103        pass
104
105class _Optimization(object):
106    pass
107
108cclass = ccall = cfunc = _EmptyDecoratorAndManager()
109
110returns = wraparound = boundscheck = initializedcheck = nonecheck = \
111    embedsignature = cdivision = cdivision_warnings = \
112    always_allows_keywords = profile = linetrace = infer_types = \
113    unraisable_tracebacks = freelist = \
114        lambda _: _EmptyDecoratorAndManager()
115
116exceptval = lambda _=None, check=True: _EmptyDecoratorAndManager()
117
118overflowcheck = lambda _: _EmptyDecoratorAndManager()
119optimization = _Optimization()
120
121overflowcheck.fold = optimization.use_switch = \
122    optimization.unpack_method_calls = lambda arg: _EmptyDecoratorAndManager()
123
124final = internal = type_version_tag = no_gc_clear = no_gc = _empty_decorator
125
126
127_cython_inline = None
128def inline(f, *args, **kwds):
129    if isinstance(f, basestring):
130        global _cython_inline
131        if _cython_inline is None:
132            from Cython.Build.Inline import cython_inline as _cython_inline
133        return _cython_inline(f, *args, **kwds)
134    else:
135        assert len(args) == len(kwds) == 0
136        return f
137
138
139def compile(f):
140    from Cython.Build.Inline import RuntimeCompiledFunction
141    return RuntimeCompiledFunction(f)
142
143
144# Special functions
145
146def cdiv(a, b):
147    q = a / b
148    if q < 0:
149        q += 1
150    return q
151
152def cmod(a, b):
153    r = a % b
154    if (a*b) < 0:
155        r -= b
156    return r
157
158
159# Emulated language constructs
160
161def cast(type, *args, **kwargs):
162    kwargs.pop('typecheck', None)
163    assert not kwargs
164    if hasattr(type, '__call__'):
165        return type(*args)
166    else:
167        return args[0]
168
169def sizeof(arg):
170    return 1
171
172def typeof(arg):
173    return arg.__class__.__name__
174    # return type(arg)
175
176def address(arg):
177    return pointer(type(arg))([arg])
178
179def declare(type=None, value=_Unspecified, **kwds):
180    if type not in (None, object) and hasattr(type, '__call__'):
181        if value is not _Unspecified:
182            return type(value)
183        else:
184            return type()
185    else:
186        return value
187
188class _nogil(object):
189    """Support for 'with nogil' statement and @nogil decorator.
190    """
191    def __call__(self, x):
192        if callable(x):
193            # Used as function decorator => return the function unchanged.
194            return x
195        # Used as conditional context manager or to create an "@nogil(True/False)" decorator => keep going.
196        return self
197
198    def __enter__(self):
199        pass
200    def __exit__(self, exc_class, exc, tb):
201        return exc_class is None
202
203nogil = _nogil()
204gil = _nogil()
205del _nogil
206
207
208# Emulated types
209
210class CythonMetaType(type):
211
212    def __getitem__(type, ix):
213        return array(type, ix)
214
215CythonTypeObject = CythonMetaType('CythonTypeObject', (object,), {})
216
217class CythonType(CythonTypeObject):
218
219    def _pointer(self, n=1):
220        for i in range(n):
221            self = pointer(self)
222        return self
223
224class PointerType(CythonType):
225
226    def __init__(self, value=None):
227        if isinstance(value, (ArrayType, PointerType)):
228            self._items = [cast(self._basetype, a) for a in value._items]
229        elif isinstance(value, list):
230            self._items = [cast(self._basetype, a) for a in value]
231        elif value is None or value == 0:
232            self._items = []
233        else:
234            raise ValueError
235
236    def __getitem__(self, ix):
237        if ix < 0:
238            raise IndexError("negative indexing not allowed in C")
239        return self._items[ix]
240
241    def __setitem__(self, ix, value):
242        if ix < 0:
243            raise IndexError("negative indexing not allowed in C")
244        self._items[ix] = cast(self._basetype, value)
245
246    def __eq__(self, value):
247        if value is None and not self._items:
248            return True
249        elif type(self) != type(value):
250            return False
251        else:
252            return not self._items and not value._items
253
254    def __repr__(self):
255        return "%s *" % (self._basetype,)
256
257class ArrayType(PointerType):
258
259    def __init__(self):
260        self._items = [None] * self._n
261
262
263class StructType(CythonType):
264
265    def __init__(self, cast_from=_Unspecified, **data):
266        if cast_from is not _Unspecified:
267            # do cast
268            if len(data) > 0:
269                raise ValueError('Cannot accept keyword arguments when casting.')
270            if type(cast_from) is not type(self):
271                raise ValueError('Cannot cast from %s'%cast_from)
272            for key, value in cast_from.__dict__.items():
273                setattr(self, key, value)
274        else:
275            for key, value in data.items():
276                setattr(self, key, value)
277
278    def __setattr__(self, key, value):
279        if key in self._members:
280            self.__dict__[key] = cast(self._members[key], value)
281        else:
282            raise AttributeError("Struct has no member '%s'" % key)
283
284
285class UnionType(CythonType):
286
287    def __init__(self, cast_from=_Unspecified, **data):
288        if cast_from is not _Unspecified:
289            # do type cast
290            if len(data) > 0:
291                raise ValueError('Cannot accept keyword arguments when casting.')
292            if isinstance(cast_from, dict):
293                datadict = cast_from
294            elif type(cast_from) is type(self):
295                datadict = cast_from.__dict__
296            else:
297                raise ValueError('Cannot cast from %s'%cast_from)
298        else:
299            datadict = data
300        if len(datadict) > 1:
301            raise AttributeError("Union can only store one field at a time.")
302        for key, value in datadict.items():
303            setattr(self, key, value)
304
305    def __setattr__(self, key, value):
306        if key in '__dict__':
307            CythonType.__setattr__(self, key, value)
308        elif key in self._members:
309            self.__dict__ = {key: cast(self._members[key], value)}
310        else:
311            raise AttributeError("Union has no member '%s'" % key)
312
313def pointer(basetype):
314    class PointerInstance(PointerType):
315        _basetype = basetype
316    return PointerInstance
317
318def array(basetype, n):
319    class ArrayInstance(ArrayType):
320        _basetype = basetype
321        _n = n
322    return ArrayInstance
323
324def struct(**members):
325    class StructInstance(StructType):
326        _members = members
327    for key in members:
328        setattr(StructInstance, key, None)
329    return StructInstance
330
331def union(**members):
332    class UnionInstance(UnionType):
333        _members = members
334    for key in members:
335        setattr(UnionInstance, key, None)
336    return UnionInstance
337
338class typedef(CythonType):
339
340    def __init__(self, type, name=None):
341        self._basetype = type
342        self.name = name
343
344    def __call__(self, *arg):
345        value = cast(self._basetype, *arg)
346        return value
347
348    def __repr__(self):
349        return self.name or str(self._basetype)
350
351    __getitem__ = index_type
352
353class _FusedType(CythonType):
354    pass
355
356
357def fused_type(*args):
358    if not args:
359        raise TypeError("Expected at least one type as argument")
360
361    # Find the numeric type with biggest rank if all types are numeric
362    rank = -1
363    for type in args:
364        if type not in (py_int, py_long, py_float, py_complex):
365            break
366
367        if type_ordering.index(type) > rank:
368            result_type = type
369    else:
370        return result_type
371
372    # Not a simple numeric type, return a fused type instance. The result
373    # isn't really meant to be used, as we can't keep track of the context in
374    # pure-mode. Casting won't do anything in this case.
375    return _FusedType()
376
377
378def _specialized_from_args(signatures, args, kwargs):
379    "Perhaps this should be implemented in a TreeFragment in Cython code"
380    raise Exception("yet to be implemented")
381
382
383py_int = typedef(int, "int")
384try:
385    py_long = typedef(long, "long")
386except NameError:  # Py3
387    py_long = typedef(int, "long")
388py_float = typedef(float, "float")
389py_complex = typedef(complex, "double complex")
390
391
392# Predefined types
393
394int_types = ['char', 'short', 'Py_UNICODE', 'int', 'Py_UCS4', 'long', 'longlong', 'Py_ssize_t', 'size_t']
395float_types = ['longdouble', 'double', 'float']
396complex_types = ['longdoublecomplex', 'doublecomplex', 'floatcomplex', 'complex']
397other_types = ['bint', 'void', 'Py_tss_t']
398
399to_repr = {
400    'longlong': 'long long',
401    'longdouble': 'long double',
402    'longdoublecomplex': 'long double complex',
403    'doublecomplex': 'double complex',
404    'floatcomplex': 'float complex',
405}.get
406
407gs = globals()
408
409# note: cannot simply name the unicode type here as 2to3 gets in the way and replaces it by str
410try:
411    import __builtin__ as builtins
412except ImportError:  # Py3
413    import builtins
414
415gs['unicode'] = typedef(getattr(builtins, 'unicode', str), 'unicode')
416del builtins
417
418for name in int_types:
419    reprname = to_repr(name, name)
420    gs[name] = typedef(py_int, reprname)
421    if name not in ('Py_UNICODE', 'Py_UCS4') and not name.endswith('size_t'):
422        gs['u'+name] = typedef(py_int, "unsigned " + reprname)
423        gs['s'+name] = typedef(py_int, "signed " + reprname)
424
425for name in float_types:
426    gs[name] = typedef(py_float, to_repr(name, name))
427
428for name in complex_types:
429    gs[name] = typedef(py_complex, to_repr(name, name))
430
431bint = typedef(bool, "bint")
432void = typedef(None, "void")
433Py_tss_t = typedef(None, "Py_tss_t")
434
435for t in int_types + float_types + complex_types + other_types:
436    for i in range(1, 4):
437        gs["%s_%s" % ('p'*i, t)] = gs[t]._pointer(i)
438
439NULL = gs['p_void'](0)
440
441# looks like 'gs' has some users out there by now...
442#del gs
443
444integral = floating = numeric = _FusedType()
445
446type_ordering = [py_int, py_long, py_float, py_complex]
447
448class CythonDotParallel(object):
449    """
450    The cython.parallel module.
451    """
452
453    __all__ = ['parallel', 'prange', 'threadid']
454
455    def parallel(self, num_threads=None):
456        return nogil
457
458    def prange(self, start=0, stop=None, step=1, nogil=False, schedule=None, chunksize=None, num_threads=None):
459        if stop is None:
460            stop = start
461            start = 0
462        return range(start, stop, step)
463
464    def threadid(self):
465        return 0
466
467    # def threadsavailable(self):
468        # return 1
469
470import sys
471sys.modules['cython.parallel'] = CythonDotParallel()
472del sys
473