Shadow.py 12 KB
Newer Older
Robert Bradshaw's avatar
Robert Bradshaw committed
1
# cython.* namespace for pure mode.
2 3
from __future__ import absolute_import

Robert Bradshaw's avatar
Robert Bradshaw committed
4
__version__ = "0.24"
Robert Bradshaw's avatar
Robert Bradshaw committed
5

6 7 8 9 10
try:
    from __builtin__ import basestring
except ImportError:
    basestring = str

11 12

# BEGIN shameless copy from Cython/minivect/minitypes.py
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36

class _ArrayType(object):

    is_array = True
    subtypes = ['dtype']

    def __init__(self, dtype, ndim, is_c_contig=False, is_f_contig=False,
                 inner_contig=False, broadcasting=None):
        self.dtype = dtype
        self.ndim = ndim
        self.is_c_contig = is_c_contig
        self.is_f_contig = is_f_contig
        self.inner_contig = inner_contig or is_c_contig or is_f_contig
        self.broadcasting = broadcasting

    def __repr__(self):
        axes = [":"] * self.ndim
        if self.is_c_contig:
            axes[-1] = "::1"
        elif self.is_f_contig:
            axes[0] = "::1"

        return "%s[%s]" % (self.dtype, ", ".join(axes))

37

38 39 40 41 42 43
def index_type(base_type, item):
    """
    Support array type creation by slicing, e.g. double[:, :] specifies
    a 2D strided array of doubles. The syntax is the same as for
    Cython memoryviews.
    """
44 45 46
    class InvalidTypeSpecification(Exception):
        pass

47 48
    def verify_slice(s):
        if s.start or s.stop or s.step not in (None, 1):
49
            raise InvalidTypeSpecification(
50 51 52 53 54 55 56 57
                "Only a step of 1 may be provided to indicate C or "
                "Fortran contiguity")

    if isinstance(item, tuple):
        step_idx = None
        for idx, s in enumerate(item):
            verify_slice(s)
            if s.step and (step_idx or idx not in (0, len(item) - 1)):
58
                raise InvalidTypeSpecification(
59 60 61 62 63 64 65 66 67
                    "Step may only be provided once, and only in the "
                    "first or last dimension.")

            if s.step == 1:
                step_idx = idx

        return _ArrayType(base_type, len(item),
                          is_c_contig=step_idx == len(item) - 1,
                          is_f_contig=step_idx == 0)
68
    elif isinstance(item, slice):
69 70
        verify_slice(item)
        return _ArrayType(base_type, 1, is_c_contig=bool(item.step))
71 72
    else:
        # int[8] etc.
73
        assert int(item) == item  # array size must be a plain integer
74
        array(base_type, item)
75 76 77

# END shameless copy

78

79 80
compiled = False

81
_Unspecified = object()
82

Robert Bradshaw's avatar
Robert Bradshaw committed
83 84
# Function decorators

85 86 87
def _empty_decorator(x):
    return x

88
def locals(**arg_types):
89 90
    return _empty_decorator

91
def test_assert_path_exists(*paths):
92 93
    return _empty_decorator

94
def test_fail_if_path_exists(*paths):
95 96
    return _empty_decorator

97 98 99 100 101 102 103
class _EmptyDecoratorAndManager(object):
    def __call__(self, x):
        return x
    def __enter__(self):
        pass
    def __exit__(self, exc_type, exc_value, traceback):
        pass
104

memeplex's avatar
memeplex committed
105 106 107
class _Optimization(object):
    pass

Haoyu Bai's avatar
Haoyu Bai committed
108
cclass = ccall = cfunc = _EmptyDecoratorAndManager()
Haoyu Bai's avatar
Haoyu Bai committed
109

memeplex's avatar
memeplex committed
110 111 112
returns = wraparound = boundscheck = initializedcheck = nonecheck = \
    overflowcheck = embedsignature = cdivision = cdivision_warnings = \
    always_allows_keywords = profile = linetrace = infer_type = \
113 114
    unraisable_tracebacks = freelist = \
        lambda arg: _EmptyDecoratorAndManager()
memeplex's avatar
memeplex committed
115 116 117 118 119

optimization = _Optimization()

overflowcheck.fold = optimization.use_switch = \
    optimization.unpack_method_calls = lambda arg: _EmptyDecoratorAndManager()
120

121
final = internal = type_version_tag = no_gc_clear = no_gc = _empty_decorator
122

Stefan Behnel's avatar
Stefan Behnel committed
123

Robert Bradshaw's avatar
Robert Bradshaw committed
124
def inline(f, *args, **kwds):
Stefan Behnel's avatar
Stefan Behnel committed
125 126 127 128 129 130 131
    if isinstance(f, basestring):
        from Cython.Build.Inline import cython_inline
        return cython_inline(f, *args, **kwds)
    else:
        assert len(args) == len(kwds) == 0
        return f

Robert Bradshaw's avatar
Robert Bradshaw committed
132

Robert Bradshaw's avatar
Robert Bradshaw committed
133 134 135 136
def compile(f):
    from Cython.Build.Inline import RuntimeCompiledFunction
    return RuntimeCompiledFunction(f)

Stefan Behnel's avatar
Stefan Behnel committed
137

Robert Bradshaw's avatar
Robert Bradshaw committed
138 139 140 141 142 143 144 145 146 147 148 149 150
# Special functions

def cdiv(a, b):
    q = a / b
    if q < 0:
        q += 1

def cmod(a, b):
    r = a % b
    if (a*b) < 0:
        r -= b
    return r

151 152 153

# Emulated language constructs

memeplex's avatar
memeplex committed
154 155 156
def cast(type, *args, **kwargs):
    kwargs.pop('typecheck', None)
    assert not kwargs
157
    if hasattr(type, '__call__'):
158
        return type(*args)
159
    else:
160
        return args[0]
161

162 163
def sizeof(arg):
    return 1
164 165

def typeof(arg):
166 167
    return arg.__class__.__name__
    # return type(arg)
168

169 170
def address(arg):
    return pointer(type(arg))([arg])
171

172
def declare(type=None, value=_Unspecified, **kwds):
173
    if type not in (None, object) and hasattr(type, '__call__'):
174
        if value is not _Unspecified:
Robert Bradshaw's avatar
Robert Bradshaw committed
175 176 177
            return type(value)
        else:
            return type()
178
    else:
Robert Bradshaw's avatar
Robert Bradshaw committed
179
        return value
180

181 182 183 184 185 186 187 188 189
class _nogil(object):
    """Support for 'with nogil' statement
    """
    def __enter__(self):
        pass
    def __exit__(self, exc_class, exc, tb):
        return exc_class is None

nogil = _nogil()
Mark Florisson's avatar
Mark Florisson committed
190
gil = _nogil()
191 192
del _nogil

193 194
# Emulated types

195 196 197 198 199 200 201 202
class CythonMetaType(type):

    def __getitem__(type, ix):
        return array(type, ix)

CythonTypeObject = CythonMetaType('CythonTypeObject', (object,), {})

class CythonType(CythonTypeObject):
203 204 205 206 207 208 209 210 211

    def _pointer(self, n=1):
        for i in range(n):
            self = pointer(self)
        return self

class PointerType(CythonType):

    def __init__(self, value=None):
212
        if isinstance(value, (ArrayType, PointerType)):
213 214 215
            self._items = [cast(self._basetype, a) for a in value._items]
        elif isinstance(value, list):
            self._items = [cast(self._basetype, a) for a in value]
216
        elif value is None or value == 0:
217 218 219
            self._items = []
        else:
            raise ValueError
220

221 222
    def __getitem__(self, ix):
        if ix < 0:
223
            raise IndexError("negative indexing not allowed in C")
224
        return self._items[ix]
225

226 227
    def __setitem__(self, ix, value):
        if ix < 0:
228
            raise IndexError("negative indexing not allowed in C")
229
        self._items[ix] = cast(self._basetype, value)
230

231 232 233 234 235 236
    def __eq__(self, value):
        if value is None and not self._items:
            return True
        elif type(self) != type(value):
            return False
        else:
Robert Bradshaw's avatar
Robert Bradshaw committed
237
            return not self._items and not value._items
238

239 240 241
    def __repr__(self):
        return "%s *" % (self._basetype,)

242
class ArrayType(PointerType):
243

244 245 246 247 248
    def __init__(self):
        self._items = [None] * self._n


class StructType(CythonType):
249

250 251 252 253 254 255 256 257 258 259
    def __init__(self, cast_from=_Unspecified, **data):
        if cast_from is not _Unspecified:
            # do cast
            if len(data) > 0:
                raise ValueError('Cannot accept keyword arguments when casting.')
            if type(cast_from) is not type(self):
                raise ValueError('Cannot cast from %s'%cast_from)
            for key, value in cast_from.__dict__.items():
                setattr(self, key, value)
        else:
260
            for key, value in data.items():
261
                setattr(self, key, value)
262

263 264 265 266
    def __setattr__(self, key, value):
        if key in self._members:
            self.__dict__[key] = cast(self._members[key], value)
        else:
267
            raise AttributeError("Struct has no member '%s'" % key)
268

269 270 271

class UnionType(CythonType):

272 273 274 275 276 277 278 279 280 281 282 283 284 285
    def __init__(self, cast_from=_Unspecified, **data):
        if cast_from is not _Unspecified:
            # do type cast
            if len(data) > 0:
                raise ValueError('Cannot accept keyword arguments when casting.')
            if isinstance(cast_from, dict):
                datadict = cast_from
            elif type(cast_from) is type(self):
                datadict = cast_from.__dict__
            else:
                raise ValueError('Cannot cast from %s'%cast_from)
        else:
            datadict = data
        if len(datadict) > 1:
286
            raise AttributeError("Union can only store one field at a time.")
287
        for key, value in datadict.items():
288
            setattr(self, key, value)
289

290 291 292 293 294 295
    def __setattr__(self, key, value):
        if key in '__dict__':
            CythonType.__setattr__(self, key, value)
        elif key in self._members:
            self.__dict__ = {key: cast(self._members[key], value)}
        else:
296
            raise AttributeError("Union has no member '%s'" % key)
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311

def pointer(basetype):
    class PointerInstance(PointerType):
        _basetype = basetype
    return PointerInstance

def array(basetype, n):
    class ArrayInstance(ArrayType):
        _basetype = basetype
        _n = n
    return ArrayInstance

def struct(**members):
    class StructInstance(StructType):
        _members = members
312
    for key in members:
313 314 315 316 317 318
        setattr(StructInstance, key, None)
    return StructInstance

def union(**members):
    class UnionInstance(UnionType):
        _members = members
319
    for key in members:
320 321 322 323 324
        setattr(UnionInstance, key, None)
    return UnionInstance

class typedef(CythonType):

325
    def __init__(self, type, name=None):
326
        self._basetype = type
327
        self.name = name
328

329 330
    def __call__(self, *arg):
        value = cast(self._basetype, *arg)
331
        return value
332

333 334 335
    def __repr__(self):
        return self.name or str(self._basetype)

336 337
    __getitem__ = index_type

338
class _FusedType(CythonType):
339
    pass
340 341 342 343 344 345


def fused_type(*args):
    if not args:
        raise TypeError("Expected at least one type as argument")

346
    # Find the numeric type with biggest rank if all types are numeric
347 348 349 350 351 352 353 354 355 356 357 358 359 360
    rank = -1
    for type in args:
        if type not in (py_int, py_long, py_float, py_complex):
            break

        if type_ordering.index(type) > rank:
            result_type = type
    else:
        return result_type

    # Not a simple numeric type, return a fused type instance. The result
    # isn't really meant to be used, as we can't keep track of the context in
    # pure-mode. Casting won't do anything in this case.
    return _FusedType()
361

362

363 364 365 366 367 368
def _specialized_from_args(signatures, args, kwargs):
    "Perhaps this should be implemented in a TreeFragment in Cython code"
    raise Exception("yet to be implemented")


py_int = typedef(int, "int")
369
try:
370
    py_long = typedef(long, "long")
371
except NameError:  # Py3
372 373
    py_long = typedef(int, "long")
py_float = typedef(float, "float")
374
py_complex = typedef(complex, "double complex")
375

Robert Bradshaw's avatar
Robert Bradshaw committed
376

377 378
# Predefined types

379
int_types = ['char', 'short', 'Py_UNICODE', 'int', 'Py_UCS4', 'long', 'longlong', 'Py_ssize_t', 'size_t']
380 381
float_types = ['longdouble', 'double', 'float']
complex_types = ['longdoublecomplex', 'doublecomplex', 'floatcomplex', 'complex']
382
other_types = ['bint', 'void']
383

384 385 386 387 388 389 390 391
to_repr = {
    'longlong': 'long long',
    'longdouble': 'long double',
    'longdoublecomplex': 'long double complex',
    'doublecomplex': 'double complex',
    'floatcomplex': 'float complex',
}.get

392 393
gs = globals()

Stefan Behnel's avatar
Stefan Behnel committed
394 395 396 397 398 399 400 401 402
# note: cannot simply name the unicode type here as 2to3 gets in the way and replaces it by str
try:
    import __builtin__ as builtins
except ImportError:  # Py3
    import builtins

gs['unicode'] = typedef(getattr(builtins, 'unicode', str), 'unicode')
del builtins

403
for name in int_types:
404 405
    reprname = to_repr(name, name)
    gs[name] = typedef(py_int, reprname)
406
    if name not in ('Py_UNICODE', 'Py_UCS4') and not name.endswith('size_t'):
407 408
        gs['u'+name] = typedef(py_int, "unsigned " + reprname)
        gs['s'+name] = typedef(py_int, "signed " + reprname)
409

410
for name in float_types:
411
    gs[name] = typedef(py_float, to_repr(name, name))
412 413

for name in complex_types:
414
    gs[name] = typedef(py_complex, to_repr(name, name))
415

416 417
bint = typedef(bool, "bint")
void = typedef(int, "void")
418

419
for t in int_types + float_types + complex_types + other_types:
420 421 422
    for i in range(1, 4):
        gs["%s_%s" % ('p'*i, t)] = globals()[t]._pointer(i)

423
void = typedef(None, "void")
Robert Bradshaw's avatar
Robert Bradshaw committed
424
NULL = p_void(0)
425

426 427 428
integral = floating = numeric = _FusedType()

type_ordering = [py_int, py_long, py_float, py_complex]
429

430 431 432 433 434 435 436
class CythonDotParallel(object):
    """
    The cython.parallel module.
    """

    __all__ = ['parallel', 'prange', 'threadid']

437 438
    def parallel(self, num_threads=None):
        return nogil
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453

    def prange(self, start=0, stop=None, step=1, schedule=None, nogil=False):
        if stop is None:
            stop = start
            start = 0
        return range(start, stop, step)

    def threadid(self):
        return 0

    # def threadsavailable(self):
        # return 1

import sys
sys.modules['cython.parallel'] = CythonDotParallel()
454
del sys