cython

Форк
0
/
Pythran.py 
223 строки · 7.0 Кб
1
from .PyrexTypes import CType, CTypedefType, CStructOrUnionType
2

3
import cython
4

5
try:
6
    import pythran
7
    pythran_is_pre_0_9 = tuple(map(int, pythran.__version__.split('.')[0:2])) < (0, 9)
8
    pythran_is_pre_0_9_6 = tuple(map(int, pythran.__version__.split('.')[0:3])) < (0, 9, 6)
9
except ImportError:
10
    pythran = None
11
    pythran_is_pre_0_9 = True
12
    pythran_is_pre_0_9_6 = True
13

14
if pythran_is_pre_0_9_6:
15
    pythran_builtins = '__builtin__'
16
else:
17
    pythran_builtins = 'builtins'
18

19

20
# Pythran/Numpy specific operations
21

22
def has_np_pythran(env):
23
    if env is None:
24
        return False
25
    directives = getattr(env, 'directives', None)
26
    return (directives and directives.get('np_pythran', False))
27

28
@cython.ccall
29
def is_pythran_supported_dtype(type_):
30
    if isinstance(type_, CTypedefType):
31
        return is_pythran_supported_type(type_.typedef_base_type)
32
    return type_.is_numeric
33

34

35
def pythran_type(Ty, ptype="ndarray"):
36
    if Ty.is_buffer:
37
        ndim,dtype = Ty.ndim, Ty.dtype
38
        if isinstance(dtype, CStructOrUnionType):
39
            ctype = dtype.cname
40
        elif isinstance(dtype, CType):
41
            ctype = dtype.sign_and_name()
42
        elif isinstance(dtype, CTypedefType):
43
            ctype = dtype.typedef_cname
44
        else:
45
            raise ValueError("unsupported type %s!" % dtype)
46
        if pythran_is_pre_0_9:
47
            return "pythonic::types::%s<%s,%d>" % (ptype,ctype, ndim)
48
        else:
49
            return "pythonic::types::%s<%s,pythonic::types::pshape<%s>>" % (ptype,ctype, ",".join(("long",)*ndim))
50
    if Ty.is_pythran_expr:
51
        return Ty.pythran_type
52
    #if Ty.is_none:
53
    #    return "decltype(pythonic::builtins::None)"
54
    if Ty.is_numeric:
55
        return Ty.sign_and_name()
56
    raise ValueError("unsupported pythran type %s (%s)" % (Ty, type(Ty)))
57

58

59
@cython.cfunc
60
def type_remove_ref(ty):
61
    return "typename std::remove_reference<%s>::type" % ty
62

63

64
def pythran_binop_type(op, tA, tB):
65
    if op == '**':
66
        return 'decltype(pythonic::numpy::functor::power{}(std::declval<%s>(), std::declval<%s>()))' % (
67
            pythran_type(tA), pythran_type(tB))
68
    else:
69
        return "decltype(std::declval<%s>() %s std::declval<%s>())" % (
70
            pythran_type(tA), op, pythran_type(tB))
71

72

73
def pythran_unaryop_type(op, type_):
74
    return "decltype(%sstd::declval<%s>())" % (
75
        op, pythran_type(type_))
76

77

78
@cython.cfunc
79
def _index_access(index_code, indices):
80
    indexing = ",".join([index_code(idx) for idx in indices])
81
    return ('[%s]' if len(indices) == 1 else '(%s)') % indexing
82

83

84
def _index_type_code(index_with_type):
85
    idx, index_type = index_with_type
86
    if idx.is_slice:
87
        n = 2 + int(not idx.step.is_none)
88
        return "pythonic::%s::functor::slice{}(%s)" % (
89
            pythran_builtins,
90
            ",".join(["0"]*n))
91
    elif index_type.is_int:
92
        return "std::declval<%s>()" % index_type.sign_and_name()
93
    elif index_type.is_pythran_expr:
94
        return "std::declval<%s>()" % index_type.pythran_type
95
    raise ValueError("unsupported indexing type %s!" % index_type)
96

97

98
def _index_code(idx):
99
    if idx.is_slice:
100
        values = idx.start, idx.stop, idx.step
101
        if idx.step.is_none:
102
            func = "contiguous_slice"
103
            values = values[:2]
104
        else:
105
            func = "slice"
106
        return "pythonic::types::%s(%s)" % (
107
            func, ",".join(v.pythran_result() for v in values))
108
    elif idx.type.is_int:
109
        return to_pythran(idx)
110
    elif idx.type.is_pythran_expr:
111
        return idx.pythran_result()
112
    raise ValueError("unsupported indexing type %s" % idx.type)
113

114

115
def pythran_indexing_type(type_, indices):
116
    return type_remove_ref("decltype(std::declval<%s>()%s)" % (
117
        pythran_type(type_),
118
        _index_access(_index_type_code, indices),
119
    ))
120

121

122
def pythran_indexing_code(indices):
123
    return _index_access(_index_code, indices)
124

125
def np_func_to_list(func):
126
    if not func.is_numpy_attribute:
127
        return []
128
    return np_func_to_list(func.obj) + [func.attribute]
129

130
if pythran is None:
131
    def pythran_is_numpy_func_supported(name):
132
        return False
133
else:
134
    def pythran_is_numpy_func_supported(func):
135
        CurF = pythran.tables.MODULES['numpy']
136
        FL = np_func_to_list(func)
137
        for F in FL:
138
            CurF = CurF.get(F, None)
139
            if CurF is None:
140
                return False
141
        return True
142

143
def pythran_functor(func):
144
    func = np_func_to_list(func)
145
    submodules = "::".join(func[:-1] + ["functor"])
146
    return "pythonic::numpy::%s::%s" % (submodules, func[-1])
147

148
def pythran_func_type(func, args):
149
    args = ",".join("std::declval<%s>()" % pythran_type(a.type) for a in args)
150
    return "decltype(%s{}(%s))" % (pythran_functor(func), args)
151

152

153
@cython.ccall
154
def to_pythran(op, ptype=None):
155
    op_type = op.type
156
    if op_type.is_int:
157
        # Make sure that integer literals always have exactly the type that the templates expect.
158
        return op_type.cast_code(op.result())
159
    if is_type(op_type, ["is_pythran_expr", "is_numeric", "is_float", "is_complex"]):
160
        return op.result()
161
    if op.is_none:
162
        return "pythonic::%s::None" % pythran_builtins
163
    if ptype is None:
164
        ptype = pythran_type(op_type)
165

166
    assert op.type.is_pyobject
167
    return "from_python<%s>(%s)" % (ptype, op.py_result())
168

169

170
@cython.cfunc
171
def is_type(type_, types):
172
    for attr in types:
173
        if getattr(type_, attr, False):
174
            return True
175
    return False
176

177

178
def is_pythran_supported_node_or_none(node):
179
    return node.is_none or is_pythran_supported_type(node.type)
180

181

182
@cython.ccall
183
def is_pythran_supported_type(type_):
184
    pythran_supported = (
185
        "is_pythran_expr", "is_int", "is_numeric", "is_float", "is_none", "is_complex")
186
    return is_type(type_, pythran_supported) or is_pythran_expr(type_)
187

188

189
def is_pythran_supported_operation_type(type_):
190
    pythran_supported = (
191
        "is_pythran_expr", "is_int", "is_numeric", "is_float", "is_complex")
192
    return is_type(type_,pythran_supported) or is_pythran_expr(type_)
193

194

195
@cython.ccall
196
def is_pythran_expr(type_):
197
    return type_.is_pythran_expr
198

199

200
def is_pythran_buffer(type_):
201
    return (type_.is_numpy_buffer and is_pythran_supported_dtype(type_.dtype) and
202
            type_.mode in ("c", "strided") and not type_.cast)
203

204
def pythran_get_func_include_file(func):
205
    func = np_func_to_list(func)
206
    return "pythonic/numpy/%s.hpp" % "/".join(func)
207

208
def include_pythran_generic(env):
209
    # Generic files
210
    env.add_include_file("pythonic/core.hpp")
211
    env.add_include_file("pythonic/python/core.hpp")
212
    env.add_include_file("pythonic/types/bool.hpp")
213
    env.add_include_file("pythonic/types/ndarray.hpp")
214
    env.add_include_file("pythonic/numpy/power.hpp")
215
    env.add_include_file("pythonic/%s/slice.hpp" % pythran_builtins)
216
    env.add_include_file("<new>")  # for placement new
217

218
    for i in (8, 16, 32, 64):
219
        env.add_include_file("pythonic/types/uint%d.hpp" % i)
220
        env.add_include_file("pythonic/types/int%d.hpp" % i)
221
    for t in ("float", "float32", "float64", "set", "slice", "tuple", "int",
222
              "complex", "complex64", "complex128"):
223
        env.add_include_file("pythonic/types/%s.hpp" % t)
224

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.