pyopencl 2024.2.2__cp39-cp39-macosx_11_0_arm64.whl → 2024.2.5__cp39-cp39-macosx_11_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyopencl might be problematic. Click here for more details.
- pyopencl/__init__.py +16 -4
- pyopencl/_cl.cpython-39-darwin.so +0 -0
- pyopencl/algorithm.py +3 -1
- pyopencl/bitonic_sort.py +2 -0
- pyopencl/characterize/__init__.py +23 -0
- pyopencl/compyte/.git +1 -0
- pyopencl/compyte/.gitignore +21 -0
- pyopencl/compyte/ndarray/Makefile +31 -0
- pyopencl/compyte/ndarray/gpu_ndarray.h +35 -0
- pyopencl/compyte/ndarray/pygpu_language.h +207 -0
- pyopencl/compyte/ndarray/pygpu_language_cuda.cu +622 -0
- pyopencl/compyte/ndarray/pygpu_language_opencl.cpp +317 -0
- pyopencl/compyte/ndarray/pygpu_ndarray.cpp +1546 -0
- pyopencl/compyte/ndarray/pygpu_ndarray.h +71 -0
- pyopencl/compyte/ndarray/pygpu_ndarray_object.h +232 -0
- pyopencl/tools.py +60 -56
- pyopencl/version.py +9 -3
- {pyopencl-2024.2.2.dist-info → pyopencl-2024.2.5.dist-info}/METADATA +14 -14
- pyopencl-2024.2.5.dist-info/RECORD +56 -0
- {pyopencl-2024.2.2.dist-info → pyopencl-2024.2.5.dist-info}/WHEEL +1 -1
- pyopencl-2024.2.2.data/data/CITATION.cff +0 -74
- pyopencl-2024.2.2.data/data/CMakeLists.txt +0 -83
- pyopencl-2024.2.2.data/data/Makefile.in +0 -21
- pyopencl-2024.2.2.data/data/README.rst +0 -70
- pyopencl-2024.2.2.data/data/README_SETUP.txt +0 -34
- pyopencl-2024.2.2.data/data/aksetup_helper.py +0 -1013
- pyopencl-2024.2.2.data/data/configure.py +0 -6
- pyopencl-2024.2.2.data/data/contrib/cldis.py +0 -91
- pyopencl-2024.2.2.data/data/contrib/fortran-to-opencl/README +0 -29
- pyopencl-2024.2.2.data/data/contrib/fortran-to-opencl/translate.py +0 -1441
- pyopencl-2024.2.2.data/data/contrib/pyopencl.vim +0 -84
- pyopencl-2024.2.2.data/data/doc/Makefile +0 -23
- pyopencl-2024.2.2.data/data/doc/algorithm.rst +0 -214
- pyopencl-2024.2.2.data/data/doc/array.rst +0 -305
- pyopencl-2024.2.2.data/data/doc/conf.py +0 -26
- pyopencl-2024.2.2.data/data/doc/howto.rst +0 -105
- pyopencl-2024.2.2.data/data/doc/index.rst +0 -137
- pyopencl-2024.2.2.data/data/doc/make_constants.py +0 -561
- pyopencl-2024.2.2.data/data/doc/misc.rst +0 -885
- pyopencl-2024.2.2.data/data/doc/runtime.rst +0 -51
- pyopencl-2024.2.2.data/data/doc/runtime_const.rst +0 -30
- pyopencl-2024.2.2.data/data/doc/runtime_gl.rst +0 -78
- pyopencl-2024.2.2.data/data/doc/runtime_memory.rst +0 -527
- pyopencl-2024.2.2.data/data/doc/runtime_platform.rst +0 -184
- pyopencl-2024.2.2.data/data/doc/runtime_program.rst +0 -364
- pyopencl-2024.2.2.data/data/doc/runtime_queue.rst +0 -182
- pyopencl-2024.2.2.data/data/doc/subst.rst +0 -36
- pyopencl-2024.2.2.data/data/doc/tools.rst +0 -4
- pyopencl-2024.2.2.data/data/doc/types.rst +0 -42
- pyopencl-2024.2.2.data/data/examples/black-hole-accretion.py +0 -2227
- pyopencl-2024.2.2.data/data/examples/demo-struct-reduce.py +0 -75
- pyopencl-2024.2.2.data/data/examples/demo.py +0 -39
- pyopencl-2024.2.2.data/data/examples/demo_array.py +0 -32
- pyopencl-2024.2.2.data/data/examples/demo_array_svm.py +0 -37
- pyopencl-2024.2.2.data/data/examples/demo_elementwise.py +0 -34
- pyopencl-2024.2.2.data/data/examples/demo_elementwise_complex.py +0 -53
- pyopencl-2024.2.2.data/data/examples/demo_mandelbrot.py +0 -183
- pyopencl-2024.2.2.data/data/examples/demo_meta_codepy.py +0 -56
- pyopencl-2024.2.2.data/data/examples/demo_meta_template.py +0 -55
- pyopencl-2024.2.2.data/data/examples/dump-performance.py +0 -38
- pyopencl-2024.2.2.data/data/examples/dump-properties.py +0 -86
- pyopencl-2024.2.2.data/data/examples/gl_interop_demo.py +0 -84
- pyopencl-2024.2.2.data/data/examples/gl_particle_animation.py +0 -218
- pyopencl-2024.2.2.data/data/examples/ipython-demo.ipynb +0 -203
- pyopencl-2024.2.2.data/data/examples/median-filter.py +0 -99
- pyopencl-2024.2.2.data/data/examples/n-body.py +0 -1070
- pyopencl-2024.2.2.data/data/examples/narray.py +0 -37
- pyopencl-2024.2.2.data/data/examples/noisyImage.jpg +0 -0
- pyopencl-2024.2.2.data/data/examples/pi-monte-carlo.py +0 -1166
- pyopencl-2024.2.2.data/data/examples/svm.py +0 -82
- pyopencl-2024.2.2.data/data/examples/transpose.py +0 -229
- pyopencl-2024.2.2.data/data/pytest.ini +0 -3
- pyopencl-2024.2.2.data/data/src/bitlog.cpp +0 -51
- pyopencl-2024.2.2.data/data/src/bitlog.hpp +0 -83
- pyopencl-2024.2.2.data/data/src/clinfo_ext.h +0 -134
- pyopencl-2024.2.2.data/data/src/mempool.hpp +0 -444
- pyopencl-2024.2.2.data/data/src/pyopencl_ext.h +0 -77
- pyopencl-2024.2.2.data/data/src/tools.hpp +0 -90
- pyopencl-2024.2.2.data/data/src/wrap_cl.cpp +0 -61
- pyopencl-2024.2.2.data/data/src/wrap_cl.hpp +0 -5853
- pyopencl-2024.2.2.data/data/src/wrap_cl_part_1.cpp +0 -369
- pyopencl-2024.2.2.data/data/src/wrap_cl_part_2.cpp +0 -702
- pyopencl-2024.2.2.data/data/src/wrap_constants.cpp +0 -1274
- pyopencl-2024.2.2.data/data/src/wrap_helpers.hpp +0 -213
- pyopencl-2024.2.2.data/data/src/wrap_mempool.cpp +0 -738
- pyopencl-2024.2.2.data/data/test/add-vectors-32.spv +0 -0
- pyopencl-2024.2.2.data/data/test/add-vectors-64.spv +0 -0
- pyopencl-2024.2.2.data/data/test/empty-header.h +0 -1
- pyopencl-2024.2.2.data/data/test/test_algorithm.py +0 -1180
- pyopencl-2024.2.2.data/data/test/test_array.py +0 -2392
- pyopencl-2024.2.2.data/data/test/test_arrays_in_structs.py +0 -100
- pyopencl-2024.2.2.data/data/test/test_clmath.py +0 -529
- pyopencl-2024.2.2.data/data/test/test_clrandom.py +0 -75
- pyopencl-2024.2.2.data/data/test/test_enqueue_copy.py +0 -271
- pyopencl-2024.2.2.data/data/test/test_wrapper.py +0 -1565
- pyopencl-2024.2.2.dist-info/LICENSE +0 -282
- pyopencl-2024.2.2.dist-info/RECORD +0 -123
- pyopencl-2024.2.2.dist-info/top_level.txt +0 -1
- {pyopencl-2024.2.2.data/data → pyopencl-2024.2.5.dist-info/licenses}/LICENSE +0 -0
|
@@ -1,1441 +0,0 @@
|
|
|
1
|
-
__copyright__ = "Copyright (C) 2009 Andreas Kloeckner"
|
|
2
|
-
|
|
3
|
-
__license__ = """
|
|
4
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
6
|
-
in the Software without restriction, including without limitation the rights
|
|
7
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
9
|
-
furnished to do so, subject to the following conditions:
|
|
10
|
-
|
|
11
|
-
The above copyright notice and this permission notice shall be included in
|
|
12
|
-
all copies or substantial portions of the Software.
|
|
13
|
-
|
|
14
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
20
|
-
THE SOFTWARE.
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
import re
|
|
24
|
-
from sys import intern
|
|
25
|
-
from warnings import warn
|
|
26
|
-
|
|
27
|
-
import cgen
|
|
28
|
-
import numpy as np
|
|
29
|
-
import pymbolic.primitives as p
|
|
30
|
-
import pytools.lex
|
|
31
|
-
from pymbolic.mapper import CombineMapper
|
|
32
|
-
from pymbolic.mapper.c_code import CCodeMapper as CCodeMapperBase
|
|
33
|
-
from pymbolic.parser import Parser as ExpressionParserBase
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
class TranslatorWarning(UserWarning):
|
|
37
|
-
pass
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
class TranslationError(RuntimeError):
|
|
41
|
-
pass
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
def complex_type_name(dtype):
|
|
45
|
-
if dtype == np.complex64:
|
|
46
|
-
return "cfloat"
|
|
47
|
-
if dtype == np.complex128:
|
|
48
|
-
return "cdouble"
|
|
49
|
-
else:
|
|
50
|
-
raise RuntimeError
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
# {{{ AST components
|
|
54
|
-
|
|
55
|
-
def dtype_to_ctype(dtype):
|
|
56
|
-
if dtype is None:
|
|
57
|
-
raise ValueError("dtype may not be None")
|
|
58
|
-
|
|
59
|
-
dtype = np.dtype(dtype)
|
|
60
|
-
if dtype == np.int64:
|
|
61
|
-
return "long"
|
|
62
|
-
elif dtype == np.uint64:
|
|
63
|
-
return "unsigned long"
|
|
64
|
-
elif dtype == np.int32:
|
|
65
|
-
return "int"
|
|
66
|
-
elif dtype == np.uint32:
|
|
67
|
-
return "unsigned int"
|
|
68
|
-
elif dtype == np.int16:
|
|
69
|
-
return "short int"
|
|
70
|
-
elif dtype == np.uint16:
|
|
71
|
-
return "short unsigned int"
|
|
72
|
-
elif dtype == np.int8:
|
|
73
|
-
return "signed char"
|
|
74
|
-
elif dtype == np.uint8:
|
|
75
|
-
return "unsigned char"
|
|
76
|
-
elif dtype == np.float32:
|
|
77
|
-
return "float"
|
|
78
|
-
elif dtype == np.float64:
|
|
79
|
-
return "double"
|
|
80
|
-
elif dtype == np.complex64:
|
|
81
|
-
return "cfloat_t"
|
|
82
|
-
elif dtype == np.complex128:
|
|
83
|
-
return "cdouble_t"
|
|
84
|
-
else:
|
|
85
|
-
raise ValueError("unable to map dtype '%s'" % dtype)
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
class POD(cgen.POD):
|
|
89
|
-
def get_decl_pair(self):
|
|
90
|
-
return [dtype_to_ctype(self.dtype)], self.name
|
|
91
|
-
|
|
92
|
-
# }}}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
# {{{ expression parser
|
|
96
|
-
|
|
97
|
-
_less_than = intern("less_than")
|
|
98
|
-
_greater_than = intern("greater_than")
|
|
99
|
-
_less_equal = intern("less_equal")
|
|
100
|
-
_greater_equal = intern("greater_equal")
|
|
101
|
-
_equal = intern("equal")
|
|
102
|
-
_not_equal = intern("not_equal")
|
|
103
|
-
|
|
104
|
-
_not = intern("not")
|
|
105
|
-
_and = intern("and")
|
|
106
|
-
_or = intern("or")
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
class TypedLiteral(p.Leaf):
|
|
110
|
-
def __init__(self, value, dtype):
|
|
111
|
-
self.value = value
|
|
112
|
-
self.dtype = np.dtype(dtype)
|
|
113
|
-
|
|
114
|
-
def __getinitargs__(self):
|
|
115
|
-
return self.value, self.dtype
|
|
116
|
-
|
|
117
|
-
mapper_method = intern("map_literal")
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
def simplify_typed_literal(expr):
|
|
121
|
-
if (isinstance(expr, p.Product)
|
|
122
|
-
and len(expr.children) == 2
|
|
123
|
-
and isinstance(expr.children[1], TypedLiteral)
|
|
124
|
-
and p.is_constant(expr.children[0])
|
|
125
|
-
and expr.children[0] == -1):
|
|
126
|
-
tl = expr.children[1]
|
|
127
|
-
return TypedLiteral("-"+tl.value, tl.dtype)
|
|
128
|
-
else:
|
|
129
|
-
return expr
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
class FortranExpressionParser(ExpressionParserBase):
|
|
133
|
-
# FIXME double/single prec literals
|
|
134
|
-
|
|
135
|
-
lex_table = [
|
|
136
|
-
(_less_than, pytools.lex.RE(r"\.lt\.", re.I)),
|
|
137
|
-
(_greater_than, pytools.lex.RE(r"\.gt\.", re.I)),
|
|
138
|
-
(_less_equal, pytools.lex.RE(r"\.le\.", re.I)),
|
|
139
|
-
(_greater_equal, pytools.lex.RE(r"\.ge\.", re.I)),
|
|
140
|
-
(_equal, pytools.lex.RE(r"\.eq\.", re.I)),
|
|
141
|
-
(_not_equal, pytools.lex.RE(r"\.ne\.", re.I)),
|
|
142
|
-
|
|
143
|
-
(_not, pytools.lex.RE(r"\.not\.", re.I)),
|
|
144
|
-
(_and, pytools.lex.RE(r"\.and\.", re.I)),
|
|
145
|
-
(_or, pytools.lex.RE(r"\.or\.", re.I)),
|
|
146
|
-
] + ExpressionParserBase.lex_table
|
|
147
|
-
|
|
148
|
-
def __init__(self, tree_walker):
|
|
149
|
-
self.tree_walker = tree_walker
|
|
150
|
-
|
|
151
|
-
_PREC_FUNC_ARGS = 1
|
|
152
|
-
|
|
153
|
-
def parse_terminal(self, pstate):
|
|
154
|
-
scope = self.tree_walker.scope_stack[-1]
|
|
155
|
-
|
|
156
|
-
from pymbolic.parser import _closepar, _float, _identifier, _openpar
|
|
157
|
-
|
|
158
|
-
next_tag = pstate.next_tag()
|
|
159
|
-
if next_tag is _float:
|
|
160
|
-
value = pstate.next_str_and_advance().lower()
|
|
161
|
-
if "d" in value:
|
|
162
|
-
dtype = np.float64
|
|
163
|
-
else:
|
|
164
|
-
dtype = np.float32
|
|
165
|
-
|
|
166
|
-
value = value.replace("d", "e")
|
|
167
|
-
if value.startswith("."):
|
|
168
|
-
prev_value = value
|
|
169
|
-
value = "0"+value
|
|
170
|
-
print(value, prev_value)
|
|
171
|
-
elif value.startswith("-."):
|
|
172
|
-
prev_value = value
|
|
173
|
-
value = "-0"+value[1:]
|
|
174
|
-
print(value, prev_value)
|
|
175
|
-
return TypedLiteral(value, dtype)
|
|
176
|
-
|
|
177
|
-
elif next_tag is _identifier:
|
|
178
|
-
name = pstate.next_str_and_advance()
|
|
179
|
-
|
|
180
|
-
if pstate.is_at_end() or pstate.next_tag() is not _openpar:
|
|
181
|
-
# not a subscript
|
|
182
|
-
scope.use_name(name)
|
|
183
|
-
|
|
184
|
-
return p.Variable(name)
|
|
185
|
-
|
|
186
|
-
left_exp = p.Variable(name)
|
|
187
|
-
|
|
188
|
-
pstate.advance()
|
|
189
|
-
pstate.expect_not_end()
|
|
190
|
-
|
|
191
|
-
if scope.is_known(name):
|
|
192
|
-
cls = p.Subscript
|
|
193
|
-
else:
|
|
194
|
-
cls = p.Call
|
|
195
|
-
|
|
196
|
-
if pstate.next_tag is _closepar:
|
|
197
|
-
pstate.advance()
|
|
198
|
-
left_exp = cls(left_exp, ())
|
|
199
|
-
else:
|
|
200
|
-
args = self.parse_expression(pstate, self._PREC_FUNC_ARGS)
|
|
201
|
-
if not isinstance(args, tuple):
|
|
202
|
-
args = (args,)
|
|
203
|
-
left_exp = cls(left_exp, args)
|
|
204
|
-
pstate.expect(_closepar)
|
|
205
|
-
pstate.advance()
|
|
206
|
-
|
|
207
|
-
return left_exp
|
|
208
|
-
else:
|
|
209
|
-
return ExpressionParserBase.parse_terminal(
|
|
210
|
-
self, pstate)
|
|
211
|
-
|
|
212
|
-
COMP_MAP = {
|
|
213
|
-
_less_than: "<",
|
|
214
|
-
_less_equal: "<=",
|
|
215
|
-
_greater_than: ">",
|
|
216
|
-
_greater_equal: ">=",
|
|
217
|
-
_equal: "==",
|
|
218
|
-
_not_equal: "!=",
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
def parse_prefix(self, pstate, min_precedence=0):
|
|
222
|
-
import pymbolic.primitives as primitives
|
|
223
|
-
from pymbolic.parser import _PREC_UNARY
|
|
224
|
-
|
|
225
|
-
pstate.expect_not_end()
|
|
226
|
-
|
|
227
|
-
if pstate.is_next(_not):
|
|
228
|
-
pstate.advance()
|
|
229
|
-
return primitives.LogicalNot(
|
|
230
|
-
self.parse_expression(pstate, _PREC_UNARY))
|
|
231
|
-
else:
|
|
232
|
-
return ExpressionParserBase.parse_prefix(self, pstate)
|
|
233
|
-
|
|
234
|
-
def parse_postfix(self, pstate, min_precedence, left_exp):
|
|
235
|
-
from pymbolic.parser import (
|
|
236
|
-
_PREC_CALL, _PREC_COMPARISON, _PREC_LOGICAL_AND, _PREC_LOGICAL_OR,
|
|
237
|
-
_openpar)
|
|
238
|
-
from pymbolic.primitives import Comparison, LogicalAnd, LogicalOr
|
|
239
|
-
|
|
240
|
-
next_tag = pstate.next_tag()
|
|
241
|
-
if next_tag is _openpar and _PREC_CALL > min_precedence:
|
|
242
|
-
raise TranslationError("parenthesis operator only works on names")
|
|
243
|
-
elif next_tag in self.COMP_MAP and _PREC_COMPARISON > min_precedence:
|
|
244
|
-
pstate.advance()
|
|
245
|
-
left_exp = Comparison(
|
|
246
|
-
left_exp,
|
|
247
|
-
self.COMP_MAP[next_tag],
|
|
248
|
-
self.parse_expression(pstate, _PREC_COMPARISON))
|
|
249
|
-
did_something = True
|
|
250
|
-
elif next_tag is _and and _PREC_LOGICAL_AND > min_precedence:
|
|
251
|
-
pstate.advance()
|
|
252
|
-
left_exp = LogicalAnd((left_exp,
|
|
253
|
-
self.parse_expression(pstate, _PREC_LOGICAL_AND)))
|
|
254
|
-
did_something = True
|
|
255
|
-
elif next_tag is _or and _PREC_LOGICAL_OR > min_precedence:
|
|
256
|
-
pstate.advance()
|
|
257
|
-
left_exp = LogicalOr((left_exp,
|
|
258
|
-
self.parse_expression(pstate, _PREC_LOGICAL_OR)))
|
|
259
|
-
did_something = True
|
|
260
|
-
else:
|
|
261
|
-
left_exp, did_something = ExpressionParserBase.parse_postfix(
|
|
262
|
-
self, pstate, min_precedence, left_exp)
|
|
263
|
-
|
|
264
|
-
if isinstance(left_exp, tuple) and min_precedence < self._PREC_FUNC_ARGS:
|
|
265
|
-
# this must be a complex literal
|
|
266
|
-
assert len(left_exp) == 2
|
|
267
|
-
r, i = left_exp
|
|
268
|
-
|
|
269
|
-
r = simplify_typed_literal(r)
|
|
270
|
-
i = simplify_typed_literal(i)
|
|
271
|
-
|
|
272
|
-
dtype = (r.dtype.type(0) + i.dtype.type(0)).dtype
|
|
273
|
-
if dtype == np.float32:
|
|
274
|
-
dtype = np.complex64
|
|
275
|
-
else:
|
|
276
|
-
dtype = np.complex128
|
|
277
|
-
|
|
278
|
-
left_exp = TypedLiteral(left_exp, dtype)
|
|
279
|
-
|
|
280
|
-
return left_exp, did_something
|
|
281
|
-
|
|
282
|
-
# }}}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
# {{{ expression generator
|
|
286
|
-
|
|
287
|
-
class TypeInferenceMapper(CombineMapper):
|
|
288
|
-
def __init__(self, scope):
|
|
289
|
-
self.scope = scope
|
|
290
|
-
|
|
291
|
-
def combine(self, dtypes):
|
|
292
|
-
return sum(dtype.type(1) for dtype in dtypes).dtype
|
|
293
|
-
|
|
294
|
-
def map_literal(self, expr):
|
|
295
|
-
return expr.dtype
|
|
296
|
-
|
|
297
|
-
def map_constant(self, expr):
|
|
298
|
-
return np.asarray(expr).dtype
|
|
299
|
-
|
|
300
|
-
def map_variable(self, expr):
|
|
301
|
-
return self.scope.get_type(expr.name)
|
|
302
|
-
|
|
303
|
-
def map_call(self, expr):
|
|
304
|
-
name = expr.function.name
|
|
305
|
-
if name == "fromreal":
|
|
306
|
-
arg, = expr.parameters
|
|
307
|
-
base_dtype = self.rec(arg)
|
|
308
|
-
tgt_real_dtype = (np.float32(0)+base_dtype.type(0)).dtype
|
|
309
|
-
assert tgt_real_dtype.kind == "f"
|
|
310
|
-
if tgt_real_dtype == np.float32:
|
|
311
|
-
return np.dtype(np.complex64)
|
|
312
|
-
elif tgt_real_dtype == np.float64:
|
|
313
|
-
return np.dtype(np.complex128)
|
|
314
|
-
else:
|
|
315
|
-
raise RuntimeError("unexpected complex type")
|
|
316
|
-
|
|
317
|
-
elif name in ["imag", "real", "abs", "dble"]:
|
|
318
|
-
arg, = expr.parameters
|
|
319
|
-
base_dtype = self.rec(arg)
|
|
320
|
-
|
|
321
|
-
if base_dtype == np.complex128:
|
|
322
|
-
return np.dtype(np.float64)
|
|
323
|
-
elif base_dtype == np.complex64:
|
|
324
|
-
return np.dtype(np.float32)
|
|
325
|
-
else:
|
|
326
|
-
return base_dtype
|
|
327
|
-
|
|
328
|
-
else:
|
|
329
|
-
return CombineMapper.map_call(self, expr)
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
class ComplexCCodeMapper(CCodeMapperBase):
|
|
333
|
-
def __init__(self, infer_type):
|
|
334
|
-
CCodeMapperBase.__init__(self)
|
|
335
|
-
self.infer_type = infer_type
|
|
336
|
-
|
|
337
|
-
def map_sum(self, expr, enclosing_prec):
|
|
338
|
-
tgt_dtype = self.infer_type(expr)
|
|
339
|
-
is_complex = tgt_dtype.kind == "c"
|
|
340
|
-
|
|
341
|
-
if not is_complex:
|
|
342
|
-
return CCodeMapperBase.map_sum(self, expr, enclosing_prec)
|
|
343
|
-
else:
|
|
344
|
-
tgt_name = complex_type_name(tgt_dtype)
|
|
345
|
-
|
|
346
|
-
reals = [child for child in expr.children
|
|
347
|
-
if "c" != self.infer_type(child).kind]
|
|
348
|
-
complexes = [child for child in expr.children
|
|
349
|
-
if "c" == self.infer_type(child).kind]
|
|
350
|
-
|
|
351
|
-
from pymbolic.mapper.stringifier import PREC_NONE, PREC_SUM
|
|
352
|
-
real_sum = self.join_rec(" + ", reals, PREC_SUM)
|
|
353
|
-
|
|
354
|
-
if len(complexes) == 1:
|
|
355
|
-
myprec = PREC_SUM
|
|
356
|
-
else:
|
|
357
|
-
myprec = PREC_NONE
|
|
358
|
-
|
|
359
|
-
complex_sum = self.rec(complexes[0], myprec)
|
|
360
|
-
for child in complexes[1:]:
|
|
361
|
-
complex_sum = "{}_add({}, {})".format(
|
|
362
|
-
tgt_name, complex_sum,
|
|
363
|
-
self.rec(child, PREC_NONE))
|
|
364
|
-
|
|
365
|
-
if real_sum:
|
|
366
|
-
result = "{}_add({}_fromreal({}), {})".format(
|
|
367
|
-
tgt_name, tgt_name, real_sum, complex_sum)
|
|
368
|
-
else:
|
|
369
|
-
result = complex_sum
|
|
370
|
-
|
|
371
|
-
return self.parenthesize_if_needed(result, enclosing_prec, PREC_SUM)
|
|
372
|
-
|
|
373
|
-
def map_product(self, expr, enclosing_prec):
|
|
374
|
-
tgt_dtype = self.infer_type(expr)
|
|
375
|
-
is_complex = "c" == tgt_dtype.kind
|
|
376
|
-
|
|
377
|
-
if not is_complex:
|
|
378
|
-
return CCodeMapperBase.map_product(self, expr, enclosing_prec)
|
|
379
|
-
else:
|
|
380
|
-
tgt_name = complex_type_name(tgt_dtype)
|
|
381
|
-
|
|
382
|
-
reals = [child for child in expr.children
|
|
383
|
-
if "c" != self.infer_type(child).kind]
|
|
384
|
-
complexes = [child for child in expr.children
|
|
385
|
-
if "c" == self.infer_type(child).kind]
|
|
386
|
-
|
|
387
|
-
from pymbolic.mapper.stringifier import PREC_NONE, PREC_PRODUCT
|
|
388
|
-
real_prd = self.join_rec("*", reals, PREC_PRODUCT)
|
|
389
|
-
|
|
390
|
-
if len(complexes) == 1:
|
|
391
|
-
myprec = PREC_PRODUCT
|
|
392
|
-
else:
|
|
393
|
-
myprec = PREC_NONE
|
|
394
|
-
|
|
395
|
-
complex_prd = self.rec(complexes[0], myprec)
|
|
396
|
-
for child in complexes[1:]:
|
|
397
|
-
complex_prd = "{}_mul({}, {})".format(
|
|
398
|
-
tgt_name, complex_prd,
|
|
399
|
-
self.rec(child, PREC_NONE))
|
|
400
|
-
|
|
401
|
-
if real_prd:
|
|
402
|
-
result = f"{tgt_name}_rmul({real_prd}, {complex_prd})"
|
|
403
|
-
else:
|
|
404
|
-
result = complex_prd
|
|
405
|
-
|
|
406
|
-
return self.parenthesize_if_needed(result, enclosing_prec, PREC_PRODUCT)
|
|
407
|
-
|
|
408
|
-
def map_quotient(self, expr, enclosing_prec):
|
|
409
|
-
from pymbolic.mapper.stringifier import PREC_NONE
|
|
410
|
-
n_complex = "c" == self.infer_type(expr.numerator).kind
|
|
411
|
-
d_complex = "c" == self.infer_type(expr.denominator).kind
|
|
412
|
-
|
|
413
|
-
tgt_dtype = self.infer_type(expr)
|
|
414
|
-
|
|
415
|
-
if not (n_complex or d_complex):
|
|
416
|
-
return CCodeMapperBase.map_quotient(self, expr, enclosing_prec)
|
|
417
|
-
elif n_complex and not d_complex:
|
|
418
|
-
return "{}_divider({}, {})".format(
|
|
419
|
-
complex_type_name(tgt_dtype),
|
|
420
|
-
self.rec(expr.numerator, PREC_NONE),
|
|
421
|
-
self.rec(expr.denominator, PREC_NONE))
|
|
422
|
-
elif not n_complex and d_complex:
|
|
423
|
-
return "{}_rdivide({}, {})".format(
|
|
424
|
-
complex_type_name(tgt_dtype),
|
|
425
|
-
self.rec(expr.numerator, PREC_NONE),
|
|
426
|
-
self.rec(expr.denominator, PREC_NONE))
|
|
427
|
-
else:
|
|
428
|
-
return "{}_divide({}, {})".format(
|
|
429
|
-
complex_type_name(tgt_dtype),
|
|
430
|
-
self.rec(expr.numerator, PREC_NONE),
|
|
431
|
-
self.rec(expr.denominator, PREC_NONE))
|
|
432
|
-
|
|
433
|
-
def map_remainder(self, expr, enclosing_prec):
|
|
434
|
-
tgt_dtype = self.infer_type(expr)
|
|
435
|
-
if "c" == tgt_dtype.kind:
|
|
436
|
-
raise RuntimeError("complex remainder not defined")
|
|
437
|
-
|
|
438
|
-
return CCodeMapperBase.map_remainder(self, expr, enclosing_prec)
|
|
439
|
-
|
|
440
|
-
def map_power(self, expr, enclosing_prec):
|
|
441
|
-
from pymbolic.mapper.stringifier import PREC_NONE
|
|
442
|
-
|
|
443
|
-
tgt_dtype = self.infer_type(expr)
|
|
444
|
-
if "c" == tgt_dtype.kind:
|
|
445
|
-
if expr.exponent in [2, 3, 4]:
|
|
446
|
-
value = expr.base
|
|
447
|
-
for i in range(expr.exponent-1):
|
|
448
|
-
value = value * expr.base
|
|
449
|
-
return self.rec(value, enclosing_prec)
|
|
450
|
-
else:
|
|
451
|
-
b_complex = "c" == self.infer_type(expr.base).kind
|
|
452
|
-
e_complex = "c" == self.infer_type(expr.exponent).kind
|
|
453
|
-
|
|
454
|
-
if b_complex and not e_complex:
|
|
455
|
-
return "{}_powr({}, {})".format(
|
|
456
|
-
complex_type_name(tgt_dtype),
|
|
457
|
-
self.rec(expr.base, PREC_NONE),
|
|
458
|
-
self.rec(expr.exponent, PREC_NONE))
|
|
459
|
-
else:
|
|
460
|
-
return "{}_pow({}, {})".format(
|
|
461
|
-
complex_type_name(tgt_dtype),
|
|
462
|
-
self.rec(expr.base, PREC_NONE),
|
|
463
|
-
self.rec(expr.exponent, PREC_NONE))
|
|
464
|
-
|
|
465
|
-
return CCodeMapperBase.map_power(self, expr, enclosing_prec)
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
class CCodeMapper(ComplexCCodeMapper):
|
|
469
|
-
# Whatever is needed to mop up after Fortran goes here.
|
|
470
|
-
# Stuff that deals with generating real-valued code
|
|
471
|
-
# from complex code goes above.
|
|
472
|
-
|
|
473
|
-
def __init__(self, translator, scope):
|
|
474
|
-
ComplexCCodeMapper.__init__(self, scope.get_type_inference_mapper())
|
|
475
|
-
self.translator = translator
|
|
476
|
-
self.scope = scope
|
|
477
|
-
|
|
478
|
-
def map_subscript(self, expr, enclosing_prec):
|
|
479
|
-
idx_dtype = self.infer_type(expr.index)
|
|
480
|
-
if not "i" == idx_dtype.kind or "u" == idx_dtype.kind:
|
|
481
|
-
ind_prefix = "(int) "
|
|
482
|
-
else:
|
|
483
|
-
ind_prefix = ""
|
|
484
|
-
|
|
485
|
-
idx = expr.index
|
|
486
|
-
if isinstance(idx, tuple) and len(idx) == 1:
|
|
487
|
-
idx, = idx
|
|
488
|
-
|
|
489
|
-
from pymbolic.mapper.stringifier import PREC_CALL, PREC_NONE
|
|
490
|
-
return self.parenthesize_if_needed(
|
|
491
|
-
self.format("%s[%s%s]",
|
|
492
|
-
self.scope.translate_var_name(expr.aggregate.name),
|
|
493
|
-
ind_prefix,
|
|
494
|
-
self.rec(idx, PREC_NONE)),
|
|
495
|
-
enclosing_prec, PREC_CALL)
|
|
496
|
-
|
|
497
|
-
def map_call(self, expr, enclosing_prec):
|
|
498
|
-
from pymbolic.mapper.stringifier import PREC_NONE
|
|
499
|
-
|
|
500
|
-
tgt_dtype = self.infer_type(expr)
|
|
501
|
-
arg_dtypes = [self.infer_type(par) for par in expr.parameters]
|
|
502
|
-
|
|
503
|
-
name = expr.function.name
|
|
504
|
-
if "f" == tgt_dtype.kind and name == "abs":
|
|
505
|
-
name = "fabs"
|
|
506
|
-
|
|
507
|
-
elif "c" == tgt_dtype.kind:
|
|
508
|
-
if name in ["conjg", "dconjg"]:
|
|
509
|
-
name = "conj"
|
|
510
|
-
|
|
511
|
-
if name[:2] == "cd" and name[2:] in ["log", "exp", "sqrt"]:
|
|
512
|
-
name = name[2:]
|
|
513
|
-
|
|
514
|
-
if name == "dble":
|
|
515
|
-
name = "real"
|
|
516
|
-
|
|
517
|
-
name = "{}_{}".format(
|
|
518
|
-
complex_type_name(tgt_dtype),
|
|
519
|
-
name)
|
|
520
|
-
|
|
521
|
-
elif name in ["aimag", "real", "imag"] and tgt_dtype.kind == "f":
|
|
522
|
-
arg_dtype, = arg_dtypes
|
|
523
|
-
|
|
524
|
-
if name == "aimag":
|
|
525
|
-
name = "imag"
|
|
526
|
-
|
|
527
|
-
name = "{}_{}".format(
|
|
528
|
-
complex_type_name(arg_dtype),
|
|
529
|
-
name)
|
|
530
|
-
|
|
531
|
-
elif "c" == tgt_dtype.kind and name == "abs":
|
|
532
|
-
arg_dtype, = arg_dtypes
|
|
533
|
-
|
|
534
|
-
name = "%s_abs" % (
|
|
535
|
-
complex_type_name(arg_dtype))
|
|
536
|
-
|
|
537
|
-
return self.format("%s(%s)",
|
|
538
|
-
name,
|
|
539
|
-
self.join_rec(", ", expr.parameters, PREC_NONE))
|
|
540
|
-
|
|
541
|
-
def map_variable(self, expr, enclosing_prec):
|
|
542
|
-
# guaranteed to not be a subscript or a call
|
|
543
|
-
|
|
544
|
-
name = expr.name
|
|
545
|
-
shape = self.scope.get_shape(name)
|
|
546
|
-
name = self.scope.translate_var_name(name)
|
|
547
|
-
if expr.name in self.scope.arg_names:
|
|
548
|
-
arg_idx = self.scope.arg_names.index(name)
|
|
549
|
-
if self.translator.arg_needs_pointer(
|
|
550
|
-
self.scope.subprogram_name, arg_idx):
|
|
551
|
-
return "*"+name
|
|
552
|
-
else:
|
|
553
|
-
return name
|
|
554
|
-
elif shape not in [(), None]:
|
|
555
|
-
return "*"+name
|
|
556
|
-
else:
|
|
557
|
-
return name
|
|
558
|
-
|
|
559
|
-
def map_literal(self, expr, enclosing_prec):
|
|
560
|
-
from pymbolic.mapper.stringifier import PREC_NONE
|
|
561
|
-
if expr.dtype.kind == "c":
|
|
562
|
-
r, i = expr.value
|
|
563
|
-
return "{}_new({}, {})".format(
|
|
564
|
-
complex_type_name(expr.dtype),
|
|
565
|
-
self.rec(r, PREC_NONE),
|
|
566
|
-
self.rec(i, PREC_NONE))
|
|
567
|
-
else:
|
|
568
|
-
return expr.value
|
|
569
|
-
|
|
570
|
-
def map_wildcard(self, expr, enclosing_prec):
|
|
571
|
-
return ":"
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
# }}}
|
|
575
|
-
|
|
576
|
-
class Scope:
|
|
577
|
-
def __init__(self, subprogram_name, arg_names=set()):
|
|
578
|
-
self.subprogram_name = subprogram_name
|
|
579
|
-
|
|
580
|
-
# map name to data
|
|
581
|
-
self.data_statements = {}
|
|
582
|
-
|
|
583
|
-
# map first letter to type
|
|
584
|
-
self.implicit_types = {}
|
|
585
|
-
|
|
586
|
-
# map name to dim tuple
|
|
587
|
-
self.dim_map = {}
|
|
588
|
-
|
|
589
|
-
# map name to dim tuple
|
|
590
|
-
self.type_map = {}
|
|
591
|
-
|
|
592
|
-
# map name to data
|
|
593
|
-
self.data = {}
|
|
594
|
-
|
|
595
|
-
self.arg_names = arg_names
|
|
596
|
-
|
|
597
|
-
self.used_names = set()
|
|
598
|
-
|
|
599
|
-
self.type_inf_mapper = None
|
|
600
|
-
|
|
601
|
-
def known_names(self):
|
|
602
|
-
return (self.used_names
|
|
603
|
-
| set(self.dim_map.keys())
|
|
604
|
-
| set(self.type_map.keys()))
|
|
605
|
-
|
|
606
|
-
def is_known(self, name):
|
|
607
|
-
return (name in self.used_names
|
|
608
|
-
or name in self.dim_map
|
|
609
|
-
or name in self.type_map)
|
|
610
|
-
|
|
611
|
-
def use_name(self, name):
|
|
612
|
-
self.used_names.add(name)
|
|
613
|
-
|
|
614
|
-
def get_type(self, name):
|
|
615
|
-
try:
|
|
616
|
-
return self.type_map[name]
|
|
617
|
-
except KeyError:
|
|
618
|
-
|
|
619
|
-
if self.implicit_types is None:
|
|
620
|
-
raise TranslationError(
|
|
621
|
-
"no type for '%s' found in implict none routine"
|
|
622
|
-
% name)
|
|
623
|
-
|
|
624
|
-
return self.implicit_types.get(name[0], np.dtype(np.int32))
|
|
625
|
-
|
|
626
|
-
def get_shape(self, name):
|
|
627
|
-
return self.dim_map.get(name, ())
|
|
628
|
-
|
|
629
|
-
def get_type_inference_mapper(self):
|
|
630
|
-
if self.type_inf_mapper is None:
|
|
631
|
-
self.type_inf_mapper = TypeInferenceMapper(self)
|
|
632
|
-
|
|
633
|
-
return self.type_inf_mapper
|
|
634
|
-
|
|
635
|
-
def translate_var_name(self, name):
|
|
636
|
-
shape = self.dim_map.get(name)
|
|
637
|
-
if name in self.data and shape is not None:
|
|
638
|
-
return f"{self.subprogram_name}_{name}"
|
|
639
|
-
else:
|
|
640
|
-
return name
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
class FTreeWalkerBase:
|
|
644
|
-
def __init__(self):
|
|
645
|
-
self.scope_stack = []
|
|
646
|
-
|
|
647
|
-
self.expr_parser = FortranExpressionParser(self)
|
|
648
|
-
|
|
649
|
-
def rec(self, expr, *args, **kwargs):
|
|
650
|
-
mro = list(type(expr).__mro__)
|
|
651
|
-
dispatch_class = kwargs.pop("dispatch_class", type(self))
|
|
652
|
-
|
|
653
|
-
while mro:
|
|
654
|
-
method_name = "map_"+mro.pop(0).__name__
|
|
655
|
-
|
|
656
|
-
try:
|
|
657
|
-
method = getattr(dispatch_class, method_name)
|
|
658
|
-
except AttributeError:
|
|
659
|
-
pass
|
|
660
|
-
else:
|
|
661
|
-
return method(self, expr, *args, **kwargs)
|
|
662
|
-
|
|
663
|
-
raise NotImplementedError(
|
|
664
|
-
"%s does not know how to map type '%s'"
|
|
665
|
-
% (type(self).__name__,
|
|
666
|
-
type(expr)))
|
|
667
|
-
|
|
668
|
-
ENTITY_RE = re.compile(
|
|
669
|
-
r"^(?P<name>[_0-9a-zA-Z]+)"
|
|
670
|
-
r"(\((?P<shape>[-+*0-9:a-zA-Z,]+)\))?$")
|
|
671
|
-
|
|
672
|
-
def parse_dimension_specs(self, dim_decls):
|
|
673
|
-
def parse_bounds(bounds_str):
|
|
674
|
-
start_end = bounds_str.split(":")
|
|
675
|
-
|
|
676
|
-
assert 1 <= len(start_end) <= 2
|
|
677
|
-
|
|
678
|
-
return tuple(self.parse_expr(s) for s in start_end)
|
|
679
|
-
|
|
680
|
-
for decl in dim_decls:
|
|
681
|
-
entity_match = self.ENTITY_RE.match(decl)
|
|
682
|
-
assert entity_match
|
|
683
|
-
|
|
684
|
-
groups = entity_match.groupdict()
|
|
685
|
-
name = groups["name"]
|
|
686
|
-
assert name
|
|
687
|
-
|
|
688
|
-
if groups["shape"]:
|
|
689
|
-
shape = [parse_bounds(s) for s in groups["shape"].split(",")]
|
|
690
|
-
else:
|
|
691
|
-
shape = None
|
|
692
|
-
|
|
693
|
-
yield name, shape
|
|
694
|
-
|
|
695
|
-
def __call__(self, expr, *args, **kwargs):
|
|
696
|
-
return self.rec(expr, *args, **kwargs)
|
|
697
|
-
|
|
698
|
-
# {{{ expressions
|
|
699
|
-
|
|
700
|
-
def parse_expr(self, expr_str):
|
|
701
|
-
return self.expr_parser(expr_str)
|
|
702
|
-
|
|
703
|
-
# }}}
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
class ArgumentAnalayzer(FTreeWalkerBase):
|
|
707
|
-
def __init__(self):
|
|
708
|
-
FTreeWalkerBase.__init__(self)
|
|
709
|
-
|
|
710
|
-
# map (func, arg_nr) to
|
|
711
|
-
# "w" for "needs pointer"
|
|
712
|
-
# [] for no obstacle to de-pointerification known
|
|
713
|
-
# [(func_name, arg_nr), ...] # depends on how this arg is used
|
|
714
|
-
|
|
715
|
-
self.arg_usage_info = {}
|
|
716
|
-
|
|
717
|
-
def arg_needs_pointer(self, func, arg_nr):
|
|
718
|
-
data = self.arg_usage_info.get((func, arg_nr), [])
|
|
719
|
-
|
|
720
|
-
if isinstance(data, list):
|
|
721
|
-
return any(
|
|
722
|
-
self.arg_needs_pointer(sub_func, sub_arg_nr)
|
|
723
|
-
for sub_func, sub_arg_nr in data)
|
|
724
|
-
|
|
725
|
-
return True
|
|
726
|
-
|
|
727
|
-
# {{{ map_XXX functions
|
|
728
|
-
|
|
729
|
-
def map_BeginSource(self, node):
|
|
730
|
-
scope = Scope(None)
|
|
731
|
-
self.scope_stack.append(scope)
|
|
732
|
-
|
|
733
|
-
for c in node.content:
|
|
734
|
-
self.rec(c)
|
|
735
|
-
|
|
736
|
-
def map_Subroutine(self, node):
|
|
737
|
-
scope = Scope(node.name, list(node.args))
|
|
738
|
-
self.scope_stack.append(scope)
|
|
739
|
-
|
|
740
|
-
for c in node.content:
|
|
741
|
-
self.rec(c)
|
|
742
|
-
|
|
743
|
-
self.scope_stack.pop()
|
|
744
|
-
|
|
745
|
-
def map_EndSubroutine(self, node):
|
|
746
|
-
pass
|
|
747
|
-
|
|
748
|
-
def map_Implicit(self, node):
|
|
749
|
-
pass
|
|
750
|
-
|
|
751
|
-
# {{{ types, declarations
|
|
752
|
-
|
|
753
|
-
def map_Equivalence(self, node):
|
|
754
|
-
raise NotImplementedError("equivalence")
|
|
755
|
-
|
|
756
|
-
def map_Dimension(self, node):
|
|
757
|
-
scope = self.scope_stack[-1]
|
|
758
|
-
|
|
759
|
-
for name, shape in self.parse_dimension_specs(node.items):
|
|
760
|
-
if name in scope.arg_names:
|
|
761
|
-
arg_idx = scope.arg_names.index(name)
|
|
762
|
-
self.arg_usage_info[scope.subprogram_name, arg_idx] = "w"
|
|
763
|
-
|
|
764
|
-
def map_External(self, node):
|
|
765
|
-
pass
|
|
766
|
-
|
|
767
|
-
def map_type_decl(self, node):
|
|
768
|
-
scope = self.scope_stack[-1]
|
|
769
|
-
|
|
770
|
-
for name, shape in self.parse_dimension_specs(node.entity_decls):
|
|
771
|
-
if shape is not None and name in scope.arg_names:
|
|
772
|
-
arg_idx = scope.arg_names.index(name)
|
|
773
|
-
self.arg_usage_info[scope.subprogram_name, arg_idx] = "w"
|
|
774
|
-
|
|
775
|
-
map_Logical = map_type_decl
|
|
776
|
-
map_Integer = map_type_decl
|
|
777
|
-
map_Real = map_type_decl
|
|
778
|
-
map_Complex = map_type_decl
|
|
779
|
-
|
|
780
|
-
# }}}
|
|
781
|
-
|
|
782
|
-
def map_Data(self, node):
|
|
783
|
-
pass
|
|
784
|
-
|
|
785
|
-
def map_Parameter(self, node):
|
|
786
|
-
raise NotImplementedError("parameter")
|
|
787
|
-
|
|
788
|
-
# {{{ I/O
|
|
789
|
-
|
|
790
|
-
def map_Open(self, node):
|
|
791
|
-
pass
|
|
792
|
-
|
|
793
|
-
def map_Format(self, node):
|
|
794
|
-
pass
|
|
795
|
-
|
|
796
|
-
def map_Write(self, node):
|
|
797
|
-
pass
|
|
798
|
-
|
|
799
|
-
def map_Print(self, node):
|
|
800
|
-
pass
|
|
801
|
-
|
|
802
|
-
def map_Read1(self, node):
|
|
803
|
-
pass
|
|
804
|
-
|
|
805
|
-
# }}}
|
|
806
|
-
|
|
807
|
-
def map_Assignment(self, node):
|
|
808
|
-
scope = self.scope_stack[-1]
|
|
809
|
-
|
|
810
|
-
lhs = self.parse_expr(node.variable)
|
|
811
|
-
|
|
812
|
-
if isinstance(lhs, p.Subscript):
|
|
813
|
-
lhs_name = lhs.aggregate.name
|
|
814
|
-
elif isinstance(lhs, p.Call):
|
|
815
|
-
# in absence of dim info, subscripts get parsed as calls
|
|
816
|
-
lhs_name = lhs.function.name
|
|
817
|
-
else:
|
|
818
|
-
lhs_name = lhs.name
|
|
819
|
-
|
|
820
|
-
if lhs_name in scope.arg_names:
|
|
821
|
-
arg_idx = scope.arg_names.index(lhs_name)
|
|
822
|
-
self.arg_usage_info[scope.subprogram_name, arg_idx] = "w"
|
|
823
|
-
|
|
824
|
-
def map_Allocate(self, node):
|
|
825
|
-
raise NotImplementedError("allocate")
|
|
826
|
-
|
|
827
|
-
def map_Deallocate(self, node):
|
|
828
|
-
raise NotImplementedError("deallocate")
|
|
829
|
-
|
|
830
|
-
def map_Save(self, node):
|
|
831
|
-
raise NotImplementedError("save")
|
|
832
|
-
|
|
833
|
-
def map_Line(self, node):
|
|
834
|
-
raise NotImplementedError
|
|
835
|
-
|
|
836
|
-
def map_Program(self, node):
|
|
837
|
-
raise NotImplementedError
|
|
838
|
-
|
|
839
|
-
def map_Entry(self, node):
|
|
840
|
-
raise NotImplementedError
|
|
841
|
-
|
|
842
|
-
# {{{ control flow
|
|
843
|
-
|
|
844
|
-
def map_Goto(self, node):
|
|
845
|
-
pass
|
|
846
|
-
|
|
847
|
-
def map_Call(self, node):
|
|
848
|
-
scope = self.scope_stack[-1]
|
|
849
|
-
|
|
850
|
-
for i, arg_str in enumerate(node.items):
|
|
851
|
-
arg = self.parse_expr(arg_str)
|
|
852
|
-
if isinstance(arg, (p.Variable, p.Subscript)):
|
|
853
|
-
if isinstance(arg, p.Subscript):
|
|
854
|
-
arg_name = arg.aggregate.name
|
|
855
|
-
else:
|
|
856
|
-
arg_name = arg.name
|
|
857
|
-
|
|
858
|
-
if arg_name in scope.arg_names:
|
|
859
|
-
arg_idx = scope.arg_names.index(arg_name)
|
|
860
|
-
arg_usage = self.arg_usage_info.setdefault(
|
|
861
|
-
(scope.subprogram_name, arg_idx),
|
|
862
|
-
[])
|
|
863
|
-
if isinstance(arg_usage, list):
|
|
864
|
-
arg_usage.append((node.designator, i))
|
|
865
|
-
|
|
866
|
-
def map_Return(self, node):
|
|
867
|
-
pass
|
|
868
|
-
|
|
869
|
-
def map_ArithmeticIf(self, node):
|
|
870
|
-
pass
|
|
871
|
-
|
|
872
|
-
def map_If(self, node):
|
|
873
|
-
for c in node.content:
|
|
874
|
-
self.rec(c)
|
|
875
|
-
|
|
876
|
-
def map_IfThen(self, node):
|
|
877
|
-
for c in node.content:
|
|
878
|
-
self.rec(c)
|
|
879
|
-
|
|
880
|
-
def map_ElseIf(self, node):
|
|
881
|
-
pass
|
|
882
|
-
|
|
883
|
-
def map_Else(self, node):
|
|
884
|
-
pass
|
|
885
|
-
|
|
886
|
-
def map_EndIfThen(self, node):
|
|
887
|
-
pass
|
|
888
|
-
|
|
889
|
-
def map_Do(self, node):
|
|
890
|
-
for c in node.content:
|
|
891
|
-
self.rec(c)
|
|
892
|
-
|
|
893
|
-
def map_EndDo(self, node):
|
|
894
|
-
pass
|
|
895
|
-
|
|
896
|
-
def map_Continue(self, node):
|
|
897
|
-
pass
|
|
898
|
-
|
|
899
|
-
def map_Stop(self, node):
|
|
900
|
-
pass
|
|
901
|
-
|
|
902
|
-
def map_Comment(self, node):
|
|
903
|
-
pass
|
|
904
|
-
|
|
905
|
-
# }}}
|
|
906
|
-
|
|
907
|
-
# }}}
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
# {{{ translator
|
|
911
|
-
|
|
912
|
-
class F2CLTranslator(FTreeWalkerBase):
|
|
913
|
-
def __init__(self, addr_space_hints, force_casts, arg_info,
|
|
914
|
-
use_restrict_pointers):
|
|
915
|
-
FTreeWalkerBase.__init__(self)
|
|
916
|
-
self.addr_space_hints = addr_space_hints
|
|
917
|
-
self.force_casts = force_casts
|
|
918
|
-
self.arg_info = arg_info
|
|
919
|
-
self.use_restrict_pointers = use_restrict_pointers
|
|
920
|
-
|
|
921
|
-
def arg_needs_pointer(self, subprogram_name, arg_index):
|
|
922
|
-
return self.arg_info.arg_needs_pointer(subprogram_name, arg_index)
|
|
923
|
-
|
|
924
|
-
# {{{ declaration helpers
|
|
925
|
-
|
|
926
|
-
def get_declarator(self, name):
|
|
927
|
-
scope = self.scope_stack[-1]
|
|
928
|
-
return POD(scope.get_type(name), name)
|
|
929
|
-
|
|
930
|
-
def get_declarations(self):
|
|
931
|
-
scope = self.scope_stack[-1]
|
|
932
|
-
|
|
933
|
-
result = []
|
|
934
|
-
pre_func_decl = []
|
|
935
|
-
|
|
936
|
-
def gen_shape(start_end):
|
|
937
|
-
return ":".join(self.gen_expr(s) for s in start_end)
|
|
938
|
-
|
|
939
|
-
for name in sorted(scope.known_names()):
|
|
940
|
-
shape = scope.dim_map.get(name)
|
|
941
|
-
|
|
942
|
-
if shape is not None:
|
|
943
|
-
dim_stmt = cgen.Statement(
|
|
944
|
-
'dimension \"fortran\" {}[{}]'.format(
|
|
945
|
-
scope.translate_var_name(name),
|
|
946
|
-
", ".join(gen_shape(s) for s in shape)
|
|
947
|
-
))
|
|
948
|
-
|
|
949
|
-
# cannot omit "dimension" decl even for rank-1 args:
|
|
950
|
-
result.append(dim_stmt)
|
|
951
|
-
|
|
952
|
-
if name in scope.data:
|
|
953
|
-
assert name not in scope.arg_names
|
|
954
|
-
|
|
955
|
-
data = scope.data[name]
|
|
956
|
-
|
|
957
|
-
if shape is None:
|
|
958
|
-
assert len(data) == 1
|
|
959
|
-
result.append(
|
|
960
|
-
cgen.Initializer(
|
|
961
|
-
self.get_declarator(name),
|
|
962
|
-
self.gen_expr(data[0])
|
|
963
|
-
))
|
|
964
|
-
else:
|
|
965
|
-
from cgen.opencl import CLConstant
|
|
966
|
-
pre_func_decl.append(
|
|
967
|
-
cgen.Initializer(
|
|
968
|
-
CLConstant(
|
|
969
|
-
cgen.ArrayOf(self.get_declarator(
|
|
970
|
-
f"{scope.subprogram_name}_{name}"))),
|
|
971
|
-
"{ %s }" % ",\n".join(self.gen_expr(x) for x in data)
|
|
972
|
-
))
|
|
973
|
-
else:
|
|
974
|
-
if name not in scope.arg_names:
|
|
975
|
-
if shape is not None:
|
|
976
|
-
result.append(cgen.Statement(
|
|
977
|
-
"%s %s[nitemsof(%s)]"
|
|
978
|
-
% (
|
|
979
|
-
dtype_to_ctype(scope.get_type(name)),
|
|
980
|
-
name, name)))
|
|
981
|
-
else:
|
|
982
|
-
result.append(self.get_declarator(name))
|
|
983
|
-
|
|
984
|
-
return pre_func_decl, result
|
|
985
|
-
|
|
986
|
-
def map_statement_list(self, content):
|
|
987
|
-
body = []
|
|
988
|
-
|
|
989
|
-
for c in content:
|
|
990
|
-
mapped = self.rec(c)
|
|
991
|
-
if mapped is None:
|
|
992
|
-
warn("mapping '%s' returned None" % type(c))
|
|
993
|
-
elif isinstance(mapped, list):
|
|
994
|
-
body.extend(mapped)
|
|
995
|
-
else:
|
|
996
|
-
body.append(mapped)
|
|
997
|
-
|
|
998
|
-
return body
|
|
999
|
-
|
|
1000
|
-
# }}}
|
|
1001
|
-
|
|
1002
|
-
# {{{ map_XXX functions
|
|
1003
|
-
|
|
1004
|
-
def map_BeginSource(self, node):
|
|
1005
|
-
scope = Scope(None)
|
|
1006
|
-
self.scope_stack.append(scope)
|
|
1007
|
-
|
|
1008
|
-
return self.map_statement_list(node.content)
|
|
1009
|
-
|
|
1010
|
-
def map_Subroutine(self, node):
|
|
1011
|
-
assert not node.prefix
|
|
1012
|
-
assert not hasattr(node, "suffix")
|
|
1013
|
-
|
|
1014
|
-
scope = Scope(node.name, list(node.args))
|
|
1015
|
-
self.scope_stack.append(scope)
|
|
1016
|
-
|
|
1017
|
-
body = self.map_statement_list(node.content)
|
|
1018
|
-
|
|
1019
|
-
pre_func_decl, in_func_decl = self.get_declarations()
|
|
1020
|
-
body = in_func_decl + [cgen.Line()] + body
|
|
1021
|
-
|
|
1022
|
-
if isinstance(body[-1], cgen.Statement) and body[-1].text == "return":
|
|
1023
|
-
body.pop()
|
|
1024
|
-
|
|
1025
|
-
def get_arg_decl(arg_idx, arg_name):
|
|
1026
|
-
decl = self.get_declarator(arg_name)
|
|
1027
|
-
|
|
1028
|
-
if self.arg_needs_pointer(node.name, arg_idx):
|
|
1029
|
-
hint = self.addr_space_hints.get((node.name, arg_name))
|
|
1030
|
-
if hint:
|
|
1031
|
-
decl = hint(cgen.Pointer(decl))
|
|
1032
|
-
else:
|
|
1033
|
-
if self.use_restrict_pointers:
|
|
1034
|
-
decl = cgen.RestrictPointer(decl)
|
|
1035
|
-
else:
|
|
1036
|
-
decl = cgen.Pointer(decl)
|
|
1037
|
-
|
|
1038
|
-
return decl
|
|
1039
|
-
|
|
1040
|
-
result = cgen.FunctionBody(
|
|
1041
|
-
cgen.FunctionDeclaration(
|
|
1042
|
-
cgen.Value("void", node.name),
|
|
1043
|
-
[get_arg_decl(i, arg) for i, arg in enumerate(node.args)]
|
|
1044
|
-
),
|
|
1045
|
-
cgen.Block(body))
|
|
1046
|
-
|
|
1047
|
-
self.scope_stack.pop()
|
|
1048
|
-
if pre_func_decl:
|
|
1049
|
-
return pre_func_decl + [cgen.Line(), result]
|
|
1050
|
-
else:
|
|
1051
|
-
return result
|
|
1052
|
-
|
|
1053
|
-
def map_EndSubroutine(self, node):
|
|
1054
|
-
return []
|
|
1055
|
-
|
|
1056
|
-
def map_Implicit(self, node):
|
|
1057
|
-
scope = self.scope_stack[-1]
|
|
1058
|
-
|
|
1059
|
-
if not node.items:
|
|
1060
|
-
assert not scope.implicit_types
|
|
1061
|
-
scope.implicit_types = None
|
|
1062
|
-
|
|
1063
|
-
for stmt, specs in node.items:
|
|
1064
|
-
tp = self.dtype_from_stmt(stmt)
|
|
1065
|
-
for start, end in specs:
|
|
1066
|
-
for char_code in range(ord(start), ord(end)+1):
|
|
1067
|
-
scope.implicit_types[chr(char_code)] = tp
|
|
1068
|
-
|
|
1069
|
-
return []
|
|
1070
|
-
|
|
1071
|
-
# {{{ types, declarations
|
|
1072
|
-
|
|
1073
|
-
def map_Equivalence(self, node):
|
|
1074
|
-
raise NotImplementedError("equivalence")
|
|
1075
|
-
|
|
1076
|
-
TYPE_MAP = {
|
|
1077
|
-
("real", "4"): np.float32,
|
|
1078
|
-
("real", "8"): np.float64,
|
|
1079
|
-
("real", "16"): np.float128,
|
|
1080
|
-
|
|
1081
|
-
("complex", "8"): np.complex64,
|
|
1082
|
-
("complex", "16"): np.complex128,
|
|
1083
|
-
("complex", "32"): np.complex256,
|
|
1084
|
-
|
|
1085
|
-
("integer", ""): np.int32,
|
|
1086
|
-
("integer", "4"): np.int32,
|
|
1087
|
-
("integer", "8"): np.int64,
|
|
1088
|
-
}
|
|
1089
|
-
|
|
1090
|
-
def dtype_from_stmt(self, stmt):
|
|
1091
|
-
length, kind = stmt.selector
|
|
1092
|
-
assert not kind
|
|
1093
|
-
return np.dtype(self.TYPE_MAP[(type(stmt).__name__.lower(), length)])
|
|
1094
|
-
|
|
1095
|
-
def map_type_decl(self, node):
|
|
1096
|
-
scope = self.scope_stack[-1]
|
|
1097
|
-
|
|
1098
|
-
tp = self.dtype_from_stmt(node)
|
|
1099
|
-
|
|
1100
|
-
for name, shape in self.parse_dimension_specs(node.entity_decls):
|
|
1101
|
-
if shape is not None:
|
|
1102
|
-
assert name not in scope.dim_map
|
|
1103
|
-
scope.dim_map[name] = shape
|
|
1104
|
-
scope.use_name(name)
|
|
1105
|
-
|
|
1106
|
-
assert name not in scope.type_map
|
|
1107
|
-
scope.type_map[name] = tp
|
|
1108
|
-
|
|
1109
|
-
return []
|
|
1110
|
-
|
|
1111
|
-
map_Logical = map_type_decl
|
|
1112
|
-
map_Integer = map_type_decl
|
|
1113
|
-
map_Real = map_type_decl
|
|
1114
|
-
map_Complex = map_type_decl
|
|
1115
|
-
|
|
1116
|
-
def map_Dimension(self, node):
|
|
1117
|
-
scope = self.scope_stack[-1]
|
|
1118
|
-
|
|
1119
|
-
for name, shape in self.parse_dimension_specs(node.items):
|
|
1120
|
-
if shape is not None:
|
|
1121
|
-
assert name not in scope.dim_map
|
|
1122
|
-
scope.dim_map[name] = shape
|
|
1123
|
-
scope.use_name(name)
|
|
1124
|
-
|
|
1125
|
-
return []
|
|
1126
|
-
|
|
1127
|
-
def map_External(self, node):
|
|
1128
|
-
raise NotImplementedError("external")
|
|
1129
|
-
|
|
1130
|
-
# }}}
|
|
1131
|
-
|
|
1132
|
-
def map_Data(self, node):
|
|
1133
|
-
scope = self.scope_stack[-1]
|
|
1134
|
-
|
|
1135
|
-
for name, data in node.stmts:
|
|
1136
|
-
name, = name
|
|
1137
|
-
assert name not in scope.data
|
|
1138
|
-
scope.data[name] = [self.parse_expr(i) for i in data]
|
|
1139
|
-
|
|
1140
|
-
return []
|
|
1141
|
-
|
|
1142
|
-
def map_Parameter(self, node):
|
|
1143
|
-
raise NotImplementedError("parameter")
|
|
1144
|
-
|
|
1145
|
-
# {{{ I/O
|
|
1146
|
-
|
|
1147
|
-
def map_Open(self, node):
|
|
1148
|
-
raise NotImplementedError
|
|
1149
|
-
|
|
1150
|
-
def map_Format(self, node):
|
|
1151
|
-
warn("'format' unsupported", TranslatorWarning)
|
|
1152
|
-
|
|
1153
|
-
def map_Write(self, node):
|
|
1154
|
-
warn("'write' unsupported", TranslatorWarning)
|
|
1155
|
-
|
|
1156
|
-
def map_Print(self, node):
|
|
1157
|
-
warn("'print' unsupported", TranslatorWarning)
|
|
1158
|
-
|
|
1159
|
-
def map_Read1(self, node):
|
|
1160
|
-
warn("'read' unsupported", TranslatorWarning)
|
|
1161
|
-
|
|
1162
|
-
# }}}
|
|
1163
|
-
|
|
1164
|
-
def map_Assignment(self, node):
|
|
1165
|
-
lhs = self.parse_expr(node.variable)
|
|
1166
|
-
from pymbolic.primitives import Subscript
|
|
1167
|
-
if isinstance(lhs, Subscript):
|
|
1168
|
-
lhs_name = lhs.aggregate.name
|
|
1169
|
-
else:
|
|
1170
|
-
lhs_name = lhs.name
|
|
1171
|
-
|
|
1172
|
-
scope = self.scope_stack[-1]
|
|
1173
|
-
scope.use_name(lhs_name)
|
|
1174
|
-
infer_type = scope.get_type_inference_mapper()
|
|
1175
|
-
|
|
1176
|
-
rhs = self.parse_expr(node.expr)
|
|
1177
|
-
lhs_dtype = infer_type(lhs)
|
|
1178
|
-
rhs_dtype = infer_type(rhs)
|
|
1179
|
-
|
|
1180
|
-
# check for silent truncation of complex
|
|
1181
|
-
if lhs_dtype.kind != "c" and rhs_dtype.kind == "c":
|
|
1182
|
-
from pymbolic import var
|
|
1183
|
-
rhs = var("real")(rhs)
|
|
1184
|
-
# check for silent widening of real
|
|
1185
|
-
if lhs_dtype.kind == "c" and rhs_dtype.kind != "c":
|
|
1186
|
-
from pymbolic import var
|
|
1187
|
-
rhs = var("fromreal")(rhs)
|
|
1188
|
-
|
|
1189
|
-
return cgen.Assign(self.gen_expr(lhs), self.gen_expr(rhs))
|
|
1190
|
-
|
|
1191
|
-
def map_Allocate(self, node):
|
|
1192
|
-
raise NotImplementedError("allocate")
|
|
1193
|
-
|
|
1194
|
-
def map_Deallocate(self, node):
|
|
1195
|
-
raise NotImplementedError("deallocate")
|
|
1196
|
-
|
|
1197
|
-
def map_Save(self, node):
|
|
1198
|
-
raise NotImplementedError("save")
|
|
1199
|
-
|
|
1200
|
-
def map_Line(self, node):
|
|
1201
|
-
#from warnings import warn
|
|
1202
|
-
#warn("Encountered a 'line': %s" % node)
|
|
1203
|
-
raise NotImplementedError
|
|
1204
|
-
|
|
1205
|
-
def map_Program(self, node):
|
|
1206
|
-
raise NotImplementedError
|
|
1207
|
-
|
|
1208
|
-
def map_Entry(self, node):
|
|
1209
|
-
raise NotImplementedError
|
|
1210
|
-
|
|
1211
|
-
# {{{ control flow
|
|
1212
|
-
|
|
1213
|
-
def map_Goto(self, node):
|
|
1214
|
-
return cgen.Statement("goto label_%s" % node.label)
|
|
1215
|
-
|
|
1216
|
-
def map_Call(self, node):
|
|
1217
|
-
def transform_arg(i, arg_str):
|
|
1218
|
-
expr = self.parse_expr(arg_str)
|
|
1219
|
-
result = self.gen_expr(expr)
|
|
1220
|
-
if self.arg_needs_pointer(node.designator, i):
|
|
1221
|
-
result = "&"+result
|
|
1222
|
-
|
|
1223
|
-
cast = self.force_casts.get(
|
|
1224
|
-
(node.designator, i))
|
|
1225
|
-
if cast is not None:
|
|
1226
|
-
result = f"({cast}) ({result})"
|
|
1227
|
-
|
|
1228
|
-
return result
|
|
1229
|
-
|
|
1230
|
-
return cgen.Statement("{}({})".format(
|
|
1231
|
-
node.designator,
|
|
1232
|
-
", ".join(transform_arg(i, arg_str)
|
|
1233
|
-
for i, arg_str in enumerate(node.items))))
|
|
1234
|
-
|
|
1235
|
-
def map_Return(self, node):
|
|
1236
|
-
return cgen.Statement("return")
|
|
1237
|
-
|
|
1238
|
-
def map_ArithmeticIf(self, node):
|
|
1239
|
-
raise NotImplementedError
|
|
1240
|
-
|
|
1241
|
-
def map_If(self, node):
|
|
1242
|
-
return cgen.If(self.transform_expr(node.expr),
|
|
1243
|
-
self.rec(node.content[0]))
|
|
1244
|
-
|
|
1245
|
-
def map_IfThen(self, node):
|
|
1246
|
-
current_cond = self.transform_expr(node.expr)
|
|
1247
|
-
|
|
1248
|
-
blocks_and_conds = []
|
|
1249
|
-
else_block = []
|
|
1250
|
-
|
|
1251
|
-
def end_block():
|
|
1252
|
-
if current_body:
|
|
1253
|
-
if current_cond is None:
|
|
1254
|
-
else_block[:] = self.map_statement_list(current_body)
|
|
1255
|
-
else:
|
|
1256
|
-
blocks_and_conds.append(
|
|
1257
|
-
(current_cond, cgen.block_if_necessary(
|
|
1258
|
-
self.map_statement_list(current_body))))
|
|
1259
|
-
|
|
1260
|
-
del current_body[:]
|
|
1261
|
-
|
|
1262
|
-
from fparser.statements import Else, ElseIf
|
|
1263
|
-
i = 0
|
|
1264
|
-
current_body = []
|
|
1265
|
-
while i < len(node.content):
|
|
1266
|
-
c = node.content[i]
|
|
1267
|
-
if isinstance(c, ElseIf):
|
|
1268
|
-
end_block()
|
|
1269
|
-
current_cond = self.transform_expr(c.expr)
|
|
1270
|
-
elif isinstance(c, Else):
|
|
1271
|
-
end_block()
|
|
1272
|
-
current_cond = None
|
|
1273
|
-
else:
|
|
1274
|
-
current_body.append(c)
|
|
1275
|
-
|
|
1276
|
-
i += 1
|
|
1277
|
-
end_block()
|
|
1278
|
-
|
|
1279
|
-
def block_or_none(body):
|
|
1280
|
-
if not body:
|
|
1281
|
-
return None
|
|
1282
|
-
else:
|
|
1283
|
-
return cgen.block_if_necessary(body)
|
|
1284
|
-
|
|
1285
|
-
return cgen.make_multiple_ifs(
|
|
1286
|
-
blocks_and_conds,
|
|
1287
|
-
block_or_none(else_block))
|
|
1288
|
-
|
|
1289
|
-
def map_EndIfThen(self, node):
|
|
1290
|
-
return []
|
|
1291
|
-
|
|
1292
|
-
def map_Do(self, node):
|
|
1293
|
-
scope = self.scope_stack[-1]
|
|
1294
|
-
|
|
1295
|
-
body = self.map_statement_list(node.content)
|
|
1296
|
-
|
|
1297
|
-
if node.loopcontrol:
|
|
1298
|
-
loop_var, loop_bounds = node.loopcontrol.split("=")
|
|
1299
|
-
loop_var = loop_var.strip()
|
|
1300
|
-
scope.use_name(loop_var)
|
|
1301
|
-
loop_bounds = [self.parse_expr(s) for s in loop_bounds.split(",")]
|
|
1302
|
-
|
|
1303
|
-
if len(loop_bounds) == 2:
|
|
1304
|
-
start, stop = loop_bounds
|
|
1305
|
-
step = 1
|
|
1306
|
-
elif len(loop_bounds) == 3:
|
|
1307
|
-
start, stop, step = loop_bounds
|
|
1308
|
-
else:
|
|
1309
|
-
raise RuntimeError("loop bounds not understood: %s"
|
|
1310
|
-
% node.loopcontrol)
|
|
1311
|
-
|
|
1312
|
-
if not isinstance(step, int):
|
|
1313
|
-
print(type(step))
|
|
1314
|
-
raise TranslationError(
|
|
1315
|
-
"non-constant steps not yet supported: %s" % step)
|
|
1316
|
-
|
|
1317
|
-
if step < 0:
|
|
1318
|
-
comp_op = ">="
|
|
1319
|
-
else:
|
|
1320
|
-
comp_op = "<="
|
|
1321
|
-
|
|
1322
|
-
return cgen.For(
|
|
1323
|
-
"{} = {}".format(loop_var, self.gen_expr(start)),
|
|
1324
|
-
"{} {} {}".format(loop_var, comp_op, self.gen_expr(stop)),
|
|
1325
|
-
"{} += {}".format(loop_var, self.gen_expr(step)),
|
|
1326
|
-
cgen.block_if_necessary(body))
|
|
1327
|
-
|
|
1328
|
-
else:
|
|
1329
|
-
raise NotImplementedError("unbounded do loop")
|
|
1330
|
-
|
|
1331
|
-
def map_EndDo(self, node):
|
|
1332
|
-
return []
|
|
1333
|
-
|
|
1334
|
-
def map_Continue(self, node):
|
|
1335
|
-
return cgen.Statement("label_%s:" % node.label)
|
|
1336
|
-
|
|
1337
|
-
def map_Stop(self, node):
|
|
1338
|
-
raise NotImplementedError("stop")
|
|
1339
|
-
|
|
1340
|
-
def map_Comment(self, node):
|
|
1341
|
-
if node.content:
|
|
1342
|
-
return cgen.LineComment(node.content.strip())
|
|
1343
|
-
else:
|
|
1344
|
-
return []
|
|
1345
|
-
|
|
1346
|
-
# }}}
|
|
1347
|
-
|
|
1348
|
-
# }}}
|
|
1349
|
-
|
|
1350
|
-
# {{{ expressions
|
|
1351
|
-
|
|
1352
|
-
def gen_expr(self, expr):
|
|
1353
|
-
scope = self.scope_stack[-1]
|
|
1354
|
-
return CCodeMapper(self, scope)(expr)
|
|
1355
|
-
|
|
1356
|
-
def transform_expr(self, expr_str):
|
|
1357
|
-
return self.gen_expr(self.expr_parser(expr_str))
|
|
1358
|
-
|
|
1359
|
-
# }}}
|
|
1360
|
-
|
|
1361
|
-
# }}}
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
def f2cl(source, free_form=False, strict=True,
|
|
1365
|
-
addr_space_hints={}, force_casts={},
|
|
1366
|
-
do_arg_analysis=True,
|
|
1367
|
-
use_restrict_pointers=False,
|
|
1368
|
-
try_compile=False):
|
|
1369
|
-
from fparser import api
|
|
1370
|
-
tree = api.parse(source, isfree=free_form, isstrict=strict,
|
|
1371
|
-
analyze=False, ignore_comments=False)
|
|
1372
|
-
|
|
1373
|
-
arg_info = ArgumentAnalayzer()
|
|
1374
|
-
if do_arg_analysis:
|
|
1375
|
-
arg_info(tree)
|
|
1376
|
-
|
|
1377
|
-
source = F2CLTranslator(addr_space_hints, force_casts,
|
|
1378
|
-
arg_info, use_restrict_pointers=use_restrict_pointers)(tree)
|
|
1379
|
-
|
|
1380
|
-
func_decls = []
|
|
1381
|
-
for entry in source:
|
|
1382
|
-
if isinstance(entry, cgen.FunctionBody):
|
|
1383
|
-
func_decls.append(entry.fdecl)
|
|
1384
|
-
|
|
1385
|
-
mod = cgen.Module(func_decls + [cgen.Line()] + source)
|
|
1386
|
-
|
|
1387
|
-
#open("pre-cnd.cl", "w").write(str(mod))
|
|
1388
|
-
|
|
1389
|
-
from cnd import transform_cl
|
|
1390
|
-
str_mod = transform_cl(str(mod))
|
|
1391
|
-
|
|
1392
|
-
if try_compile:
|
|
1393
|
-
import pyopencl as cl
|
|
1394
|
-
ctx = cl.create_some_context()
|
|
1395
|
-
cl.Program(ctx, """
|
|
1396
|
-
#if __OPENCL_VERSION__ <= CL_VERSION_1_1
|
|
1397
|
-
#pragma OPENCL EXTENSION cl_khr_fp64: enable
|
|
1398
|
-
#endif
|
|
1399
|
-
#include <pyopencl-complex.h>
|
|
1400
|
-
""").build()
|
|
1401
|
-
return str_mod
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
def f2cl_files(source_file, target_file, **kwargs):
|
|
1405
|
-
mod = f2cl(open(source_file).read(), **kwargs)
|
|
1406
|
-
open(target_file, "w").write(mod)
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
if __name__ == "__main__":
|
|
1410
|
-
import logging
|
|
1411
|
-
console = logging.StreamHandler()
|
|
1412
|
-
console.setLevel(logging.DEBUG)
|
|
1413
|
-
formatter = logging.Formatter("%(name)-12s: %(levelname)-8s %(message)s")
|
|
1414
|
-
console.setFormatter(formatter)
|
|
1415
|
-
logging.getLogger("fparser").addHandler(console)
|
|
1416
|
-
|
|
1417
|
-
from cgen.opencl import CLConstant
|
|
1418
|
-
|
|
1419
|
-
if 0:
|
|
1420
|
-
f2cl_files("hank107.f", "hank107.cl",
|
|
1421
|
-
addr_space_hints={
|
|
1422
|
-
("hank107p", "p"): CLConstant,
|
|
1423
|
-
("hank107pc", "p"): CLConstant,
|
|
1424
|
-
},
|
|
1425
|
-
force_casts={
|
|
1426
|
-
("hank107p", 0): "__constant cdouble_t *",
|
|
1427
|
-
})
|
|
1428
|
-
|
|
1429
|
-
f2cl_files("cdjseval2d.f", "cdjseval2d.cl")
|
|
1430
|
-
|
|
1431
|
-
f2cl_files("hank103.f", "hank103.cl",
|
|
1432
|
-
addr_space_hints={
|
|
1433
|
-
("hank103p", "p"): CLConstant,
|
|
1434
|
-
("hank103pc", "p"): CLConstant,
|
|
1435
|
-
},
|
|
1436
|
-
force_casts={
|
|
1437
|
-
("hank103p", 0): "__constant cdouble_t *",
|
|
1438
|
-
},
|
|
1439
|
-
try_compile=True)
|
|
1440
|
-
|
|
1441
|
-
# vim: foldmethod=marker
|