Shadow.py 11 KB
Newer Older
Robert Bradshaw's avatar
Robert Bradshaw committed
1
# cython.* namespace for pure mode.
Stefan Behnel's avatar
Stefan Behnel committed
2
__version__ = "0.21.1pre"
Robert Bradshaw's avatar
Robert Bradshaw committed
3

4 5

# BEGIN shameless copy from Cython/minivect/minitypes.py
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

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))

30

31 32 33 34 35 36 37 38
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.
    """
    assert isinstance(item, (tuple, slice))

39 40 41
    class InvalidTypeSpecification(Exception):
        pass

42 43
    def verify_slice(s):
        if s.start or s.stop or s.step not in (None, 1):
44
            raise InvalidTypeSpecification(
45 46 47 48 49 50 51 52
                "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)):
53
                raise InvalidTypeSpecification(
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
                    "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)
    else:
        verify_slice(item)
        return _ArrayType(base_type, 1, is_c_contig=bool(item.step))

# END shameless copy

69

70 71
compiled = False

72
_Unspecified = object()
73

Robert Bradshaw's avatar
Robert Bradshaw committed
74 75
# Function decorators

76 77 78
def _empty_decorator(x):
    return x

79
def locals(**arg_types):
80 81
    return _empty_decorator

82
def test_assert_path_exists(*paths):
83 84
    return _empty_decorator

85
def test_fail_if_path_exists(*paths):
86 87
    return _empty_decorator

88 89 90 91 92 93 94
class _EmptyDecoratorAndManager(object):
    def __call__(self, x):
        return x
    def __enter__(self):
        pass
    def __exit__(self, exc_type, exc_value, traceback):
        pass
95

Haoyu Bai's avatar
Haoyu Bai committed
96
cclass = ccall = cfunc = _EmptyDecoratorAndManager()
Haoyu Bai's avatar
Haoyu Bai committed
97

98 99
returns = lambda type_arg: _EmptyDecoratorAndManager()

100
final = internal = type_version_tag = no_gc_clear = _empty_decorator
101

Robert Bradshaw's avatar
Robert Bradshaw committed
102 103 104 105 106 107 108 109
def inline(f, *args, **kwds):
  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
110 111 112 113
def compile(f):
    from Cython.Build.Inline import RuntimeCompiledFunction
    return RuntimeCompiledFunction(f)

Robert Bradshaw's avatar
Robert Bradshaw committed
114 115 116 117 118 119 120 121 122 123 124 125 126
# 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

Robert Bradshaw's avatar
Robert Bradshaw committed
127 128 129

# Emulated language constructs

130
def cast(type, *args):
131
    if hasattr(type, '__call__'):
132
        return type(*args)
Robert Bradshaw's avatar
Robert Bradshaw committed
133
    else:
134
        return args[0]
135

136 137
def sizeof(arg):
    return 1
Robert Bradshaw's avatar
Robert Bradshaw committed
138 139

def typeof(arg):
140 141
    return arg.__class__.__name__
    # return type(arg)
Robert Bradshaw's avatar
Robert Bradshaw committed
142

Robert Bradshaw's avatar
Robert Bradshaw committed
143 144
def address(arg):
    return pointer(type(arg))([arg])
Robert Bradshaw's avatar
Robert Bradshaw committed
145

146
def declare(type=None, value=_Unspecified, **kwds):
147
    if type not in (None, object) and hasattr(type, '__call__'):
148
        if value is not _Unspecified:
Robert Bradshaw's avatar
Robert Bradshaw committed
149 150 151
            return type(value)
        else:
            return type()
Robert Bradshaw's avatar
Robert Bradshaw committed
152
    else:
Robert Bradshaw's avatar
Robert Bradshaw committed
153
        return value
Robert Bradshaw's avatar
Robert Bradshaw committed
154

155 156 157 158 159 160 161 162 163
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
164
gil = _nogil()
165 166
del _nogil

Robert Bradshaw's avatar
Robert Bradshaw committed
167 168
# Emulated types

169 170 171 172 173 174 175 176
class CythonMetaType(type):

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

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

class CythonType(CythonTypeObject):
Robert Bradshaw's avatar
Robert Bradshaw committed
177 178 179 180 181 182 183 184 185

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

class PointerType(CythonType):

    def __init__(self, value=None):
186
        if isinstance(value, (ArrayType, PointerType)):
Robert Bradshaw's avatar
Robert Bradshaw committed
187 188 189
            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]
190
        elif value is None or value == 0:
Robert Bradshaw's avatar
Robert Bradshaw committed
191 192 193
            self._items = []
        else:
            raise ValueError
Robert Bradshaw's avatar
Robert Bradshaw committed
194

Robert Bradshaw's avatar
Robert Bradshaw committed
195 196
    def __getitem__(self, ix):
        if ix < 0:
197
            raise IndexError("negative indexing not allowed in C")
Robert Bradshaw's avatar
Robert Bradshaw committed
198
        return self._items[ix]
Robert Bradshaw's avatar
Robert Bradshaw committed
199

Robert Bradshaw's avatar
Robert Bradshaw committed
200 201
    def __setitem__(self, ix, value):
        if ix < 0:
202
            raise IndexError("negative indexing not allowed in C")
Robert Bradshaw's avatar
Robert Bradshaw committed
203
        self._items[ix] = cast(self._basetype, value)
Robert Bradshaw's avatar
Robert Bradshaw committed
204

205 206 207 208 209 210
    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
211
            return not self._items and not value._items
212

213 214 215
    def __repr__(self):
        return "%s *" % (self._basetype,)

Robert Bradshaw's avatar
Robert Bradshaw committed
216
class ArrayType(PointerType):
Robert Bradshaw's avatar
Robert Bradshaw committed
217

Robert Bradshaw's avatar
Robert Bradshaw committed
218 219 220 221 222
    def __init__(self):
        self._items = [None] * self._n


class StructType(CythonType):
Robert Bradshaw's avatar
Robert Bradshaw committed
223

224 225 226 227 228 229 230 231 232 233 234 235
    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:
            for key, value in data.iteritems():
                setattr(self, key, value)
Robert Bradshaw's avatar
Robert Bradshaw committed
236

Robert Bradshaw's avatar
Robert Bradshaw committed
237 238 239 240
    def __setattr__(self, key, value):
        if key in self._members:
            self.__dict__[key] = cast(self._members[key], value)
        else:
241
            raise AttributeError("Struct has no member '%s'" % key)
Robert Bradshaw's avatar
Robert Bradshaw committed
242

Robert Bradshaw's avatar
Robert Bradshaw committed
243 244 245

class UnionType(CythonType):

246 247 248 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 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:
260
            raise AttributeError("Union can only store one field at a time.")
261
        for key, value in datadict.iteritems():
Robert Bradshaw's avatar
Robert Bradshaw committed
262
            setattr(self, key, value)
Robert Bradshaw's avatar
Robert Bradshaw committed
263

Robert Bradshaw's avatar
Robert Bradshaw committed
264 265 266 267 268 269
    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:
270
            raise AttributeError("Union has no member '%s'" % key)
Robert Bradshaw's avatar
Robert Bradshaw committed
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285

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
286
    for key in members:
Robert Bradshaw's avatar
Robert Bradshaw committed
287 288 289 290 291 292
        setattr(StructInstance, key, None)
    return StructInstance

def union(**members):
    class UnionInstance(UnionType):
        _members = members
293
    for key in members:
Robert Bradshaw's avatar
Robert Bradshaw committed
294 295 296 297 298
        setattr(UnionInstance, key, None)
    return UnionInstance

class typedef(CythonType):

299
    def __init__(self, type, name=None):
Robert Bradshaw's avatar
Robert Bradshaw committed
300
        self._basetype = type
301
        self.name = name
Robert Bradshaw's avatar
Robert Bradshaw committed
302

303 304
    def __call__(self, *arg):
        value = cast(self._basetype, *arg)
Robert Bradshaw's avatar
Robert Bradshaw committed
305
        return value
Robert Bradshaw's avatar
Robert Bradshaw committed
306

307 308 309
    def __repr__(self):
        return self.name or str(self._basetype)

310 311
    __getitem__ = index_type

312
class _FusedType(CythonType):
313
    pass
314 315 316 317 318 319


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

320
    # Find the numeric type with biggest rank if all types are numeric
321 322 323 324 325 326 327 328 329 330 331 332 333 334
    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()
Robert Bradshaw's avatar
Robert Bradshaw committed
335

336

337 338 339 340 341 342
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")
343
try:
344
    py_long = typedef(long, "long")
345
except NameError: # Py3
346 347
    py_long = typedef(int, "long")
py_float = typedef(float, "float")
348
py_complex = typedef(complex, "double complex")
349

Robert Bradshaw's avatar
Robert Bradshaw committed
350

Robert Bradshaw's avatar
Robert Bradshaw committed
351 352
# Predefined types

353
int_types = ['char', 'short', 'Py_UNICODE', 'int', 'Py_UCS4', 'long', 'longlong', 'Py_ssize_t', 'size_t']
354 355
float_types = ['longdouble', 'double', 'float']
complex_types = ['longdoublecomplex', 'doublecomplex', 'floatcomplex', 'complex']
356
other_types = ['bint', 'void']
357

358 359 360 361 362 363 364 365
to_repr = {
    'longlong': 'long long',
    'longdouble': 'long double',
    'longdoublecomplex': 'long double complex',
    'doublecomplex': 'double complex',
    'floatcomplex': 'float complex',
}.get

Robert Bradshaw's avatar
Robert Bradshaw committed
366 367 368
gs = globals()

for name in int_types:
369 370
    reprname = to_repr(name, name)
    gs[name] = typedef(py_int, reprname)
371
    if name not in ('Py_UNICODE', 'Py_UCS4') and not name.endswith('size_t'):
372 373
        gs['u'+name] = typedef(py_int, "unsigned " + reprname)
        gs['s'+name] = typedef(py_int, "signed " + reprname)
Robert Bradshaw's avatar
Robert Bradshaw committed
374

375
for name in float_types:
376
    gs[name] = typedef(py_float, to_repr(name, name))
377 378

for name in complex_types:
379
    gs[name] = typedef(py_complex, to_repr(name, name))
380

381 382
bint = typedef(bool, "bint")
void = typedef(int, "void")
Robert Bradshaw's avatar
Robert Bradshaw committed
383

384
for t in int_types + float_types + complex_types + other_types:
Robert Bradshaw's avatar
Robert Bradshaw committed
385 386 387
    for i in range(1, 4):
        gs["%s_%s" % ('p'*i, t)] = globals()[t]._pointer(i)

388
void = typedef(None, "void")
Robert Bradshaw's avatar
Robert Bradshaw committed
389
NULL = p_void(0)
390

391 392 393
integral = floating = numeric = _FusedType()

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

395 396 397 398 399 400 401
class CythonDotParallel(object):
    """
    The cython.parallel module.
    """

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

402 403
    def parallel(self, num_threads=None):
        return nogil
404 405 406 407 408 409 410 411 412 413 414 415 416 417 418

    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()
419
del sys