source: sasmodels/sasmodels/autoc.py @ db03406

Last change on this file since db03406 was db03406, checked in by Paul Kienzle <pkienzle@…>, 6 years ago

first pass at python to C translator for kernels

  • Property mode set to 100644
File size: 3.6 KB
Line 
1"""
2Automatically translate python models to C
3"""
4from __future__ import print_function
5
6import ast
7import inspect
8
9import numpy as np
10
11from . import codegen
12from . import special
13
14# pylint: disable=unused-import
15try:
16    from types import ModuleType
17    #from .modelinfo import ModelInfo  # circular import
18except ImportError:
19    pass
20# pylint: enable=unused-import
21
22DEPENDENCY = {
23    'core_shell_kernel': ['lib/core_shell.c'],
24    'fractal_sq': ['lib/fractal_sq.c'],
25    'gfn4': ['lib/gfn.c'],
26    'polevl': ['lib/polevl.c'],
27    'p1evl': ['lib/polevl.c'],
28    'sas_2J1x_x': ['lib/polevl.c', 'lib/sas_J1.c'],
29    'sas_3j1x_x': ['lib/sas_3j1x_x.c'],
30    'sas_erf': ['lib/polevl.c', 'lib/sas_erf.c'],
31    'sas_erfc': ['lib/polevl.c', 'lib/sas_erf.c'],
32    'sas_gamma': ['lib/sas_gamma.c'],
33    'sas_J0': ['lib/polevl.c', 'lib/sas_J0.c'],
34    'sas_J1': ['lib/polevl.c', 'lib/sas_J1.c'],
35    'sas_JN': ['lib/polevl.c', 'lib/sas_J0.c', 'lib/sas_J1.c', 'lib/sas_JN.c'],
36    'sas_Si': ['lib/Si.c'],
37}
38
39def convert(info, module):
40    # type: ("ModelInfo", ModuleType) -> bool
41    """
42    convert Iq, Iqxy and form_volume to c
43    """
44    # Check if there is already C code
45    if info.source or info.c_code is not None:
46        print("a", info.source, info.c_code)
47        return
48
49    public_methods = "Iq", "Iqxy", "form_volume"
50
51    tagged = []
52    translate = []
53    for function_name in public_methods:
54        function = getattr(info, function_name)
55        if callable(function):
56            translate.append(function)
57            tagged.append(function_name)
58    if not translate:
59        print("b")
60        return  # nothing to translate---maybe Iq, etc. are already C snippets?
61
62    deps = []
63    code = []
64    while translate:
65        function = translate.pop(0)
66        source = inspect.getsource(function)
67        tree = ast.parse(source)
68        filename = function.__code__.co_filename
69        offset = function.__code__.co_firstlineno
70        refs = function.__code__.co_names
71        snippet = codegen.to_source(tree) #, filename, offset)
72        code.insert(0, snippet)
73        for name in refs:
74            obj = getattr(module, name, None)
75            if obj is None:
76                pass # ignore unbound variables for now
77                #raise ValueError("global %s is not defined" % name)
78            elif getattr(special, name, None):
79                # special symbol: look up depenencies
80                deps.extend(DEPENDENCY.get(name, []))
81            elif callable(obj):
82                if name not in tagged:
83                    translate.append(obj)
84                    tagged.append(name)
85            elif isinstance(obj, float):
86                code.insert(0, "const double %s = %.15g\n"%(name, obj))
87            elif isinstance(obj, int):
88                code.insert(0, "const int %s = %d\n"%(name, obj))
89            elif isinstance(obj, (list, tuple, np.ndarray)):
90                vals = ", ".join("%.15g"%v for v in obj)
91                code.insert(0, "const double %s[] = {%s};\n" %(name, vals))
92            elif isinstance(obj, special.Gauss):
93                deps.append('lib/gauss%d.c'%obj.n)
94            else:
95                raise TypeError("Could not convert global %s of type %s"
96                                % (name, str(type(obj))))
97
98    # remove duplicates from the dependecy list
99    unique_deps = []
100    for dep in deps:
101        if dep not in unique_deps:
102            unique_deps.append(dep)
103
104    info.source = unique_deps
105    info.c_code = "\n".join(code)
106
107    info.Iq = info.Iqxy = info.form_volume = None
108
109    print("source", info.source)
110    print(info.c_code)
111
112    raise RuntimeError("not yet converted...")
Note: See TracBrowser for help on using the repository browser.