Index: sasmodels/autoc.py
===================================================================
--- sasmodels/autoc.py	(revision db0340684d33368d63f9c39a84e1c2398bf1e953)
+++ sasmodels/autoc.py	(revision db0340684d33368d63f9c39a84e1c2398bf1e953)
@@ -0,0 +1,112 @@
+"""
+Automatically translate python models to C
+"""
+from __future__ import print_function
+
+import ast
+import inspect
+
+import numpy as np
+
+from . import codegen
+from . import special
+
+# pylint: disable=unused-import
+try:
+    from types import ModuleType
+    #from .modelinfo import ModelInfo  # circular import
+except ImportError:
+    pass
+# pylint: enable=unused-import
+
+DEPENDENCY = {
+    'core_shell_kernel': ['lib/core_shell.c'],
+    'fractal_sq': ['lib/fractal_sq.c'],
+    'gfn4': ['lib/gfn.c'],
+    'polevl': ['lib/polevl.c'],
+    'p1evl': ['lib/polevl.c'],
+    'sas_2J1x_x': ['lib/polevl.c', 'lib/sas_J1.c'],
+    'sas_3j1x_x': ['lib/sas_3j1x_x.c'],
+    'sas_erf': ['lib/polevl.c', 'lib/sas_erf.c'],
+    'sas_erfc': ['lib/polevl.c', 'lib/sas_erf.c'],
+    'sas_gamma': ['lib/sas_gamma.c'],
+    'sas_J0': ['lib/polevl.c', 'lib/sas_J0.c'],
+    'sas_J1': ['lib/polevl.c', 'lib/sas_J1.c'],
+    'sas_JN': ['lib/polevl.c', 'lib/sas_J0.c', 'lib/sas_J1.c', 'lib/sas_JN.c'],
+    'sas_Si': ['lib/Si.c'],
+}
+
+def convert(info, module):
+    # type: ("ModelInfo", ModuleType) -> bool
+    """
+    convert Iq, Iqxy and form_volume to c
+    """
+    # Check if there is already C code
+    if info.source or info.c_code is not None:
+        print("a", info.source, info.c_code)
+        return
+
+    public_methods = "Iq", "Iqxy", "form_volume"
+
+    tagged = []
+    translate = []
+    for function_name in public_methods:
+        function = getattr(info, function_name)
+        if callable(function):
+            translate.append(function)
+            tagged.append(function_name)
+    if not translate:
+        print("b")
+        return  # nothing to translate---maybe Iq, etc. are already C snippets?
+
+    deps = []
+    code = []
+    while translate:
+        function = translate.pop(0)
+        source = inspect.getsource(function)
+        tree = ast.parse(source)
+        filename = function.__code__.co_filename
+        offset = function.__code__.co_firstlineno
+        refs = function.__code__.co_names
+        snippet = codegen.to_source(tree) #, filename, offset)
+        code.insert(0, snippet)
+        for name in refs:
+            obj = getattr(module, name, None)
+            if obj is None:
+                pass # ignore unbound variables for now
+                #raise ValueError("global %s is not defined" % name)
+            elif getattr(special, name, None):
+                # special symbol: look up depenencies
+                deps.extend(DEPENDENCY.get(name, []))
+            elif callable(obj):
+                if name not in tagged:
+                    translate.append(obj)
+                    tagged.append(name)
+            elif isinstance(obj, float):
+                code.insert(0, "const double %s = %.15g\n"%(name, obj))
+            elif isinstance(obj, int):
+                code.insert(0, "const int %s = %d\n"%(name, obj))
+            elif isinstance(obj, (list, tuple, np.ndarray)):
+                vals = ", ".join("%.15g"%v for v in obj)
+                code.insert(0, "const double %s[] = {%s};\n" %(name, vals))
+            elif isinstance(obj, special.Gauss):
+                deps.append('lib/gauss%d.c'%obj.n)
+            else:
+                raise TypeError("Could not convert global %s of type %s"
+                                % (name, str(type(obj))))
+
+    # remove duplicates from the dependecy list
+    unique_deps = []
+    for dep in deps:
+        if dep not in unique_deps:
+            unique_deps.append(dep)
+
+    info.source = unique_deps
+    info.c_code = "\n".join(code)
+
+    info.Iq = info.Iqxy = info.form_volume = None
+
+    print("source", info.source)
+    print(info.c_code)
+
+    raise RuntimeError("not yet converted...")
Index: sasmodels/codegen.py
===================================================================
--- sasmodels/codegen.py	(revision db0340684d33368d63f9c39a84e1c2398bf1e953)
+++ sasmodels/codegen.py	(revision db0340684d33368d63f9c39a84e1c2398bf1e953)
@@ -0,0 +1,674 @@
+"""
+    cdegen
+    ~~~~~~~
+
+    Extension to ast that allow ast -> python code generation.
+
+    :copyright: Copyright 2008 by Armin Ronacher.
+    :license: BSD.
+"""
+from __future__ import print_function, division
+
+import ast
+from ast import NodeVisitor
+
+BINOP_SYMBOLS = {}
+BINOP_SYMBOLS[ast.Add] = '+'
+BINOP_SYMBOLS[ast.Sub] = '-'
+BINOP_SYMBOLS[ast.Mult] = '*'
+BINOP_SYMBOLS[ast.Div] = '/'
+BINOP_SYMBOLS[ast.Mod] = '%'
+BINOP_SYMBOLS[ast.Pow] = '**'
+BINOP_SYMBOLS[ast.LShift] = '<<'
+BINOP_SYMBOLS[ast.RShift] = '>>'
+BINOP_SYMBOLS[ast.BitOr] = '|'
+BINOP_SYMBOLS[ast.BitXor] = '^'
+BINOP_SYMBOLS[ast.BitAnd] = '&'
+BINOP_SYMBOLS[ast.FloorDiv] = '//'
+
+BOOLOP_SYMBOLS = {}
+BOOLOP_SYMBOLS[ast.And] = 'and'
+BOOLOP_SYMBOLS[ast.Or] = 'or'
+
+CMPOP_SYMBOLS = {}
+CMPOP_SYMBOLS[ast.Eq] = '=='
+CMPOP_SYMBOLS[ast.NotEq] = '!='
+CMPOP_SYMBOLS[ast.Lt] = '<'
+CMPOP_SYMBOLS[ast.LtE] = '<='
+CMPOP_SYMBOLS[ast.Gt] = '>'
+CMPOP_SYMBOLS[ast.GtE] = '>='
+CMPOP_SYMBOLS[ast.Is] = 'is'
+CMPOP_SYMBOLS[ast.IsNot] = 'is not'
+CMPOP_SYMBOLS[ast.In] = 'in'
+CMPOP_SYMBOLS[ast.NotIn] = 'not in'
+
+UNARYOP_SYMBOLS = {}
+UNARYOP_SYMBOLS[ast.Invert] = '~'
+UNARYOP_SYMBOLS[ast.Not] = 'not'
+UNARYOP_SYMBOLS[ast.UAdd] = '+'
+UNARYOP_SYMBOLS[ast.USub] = '-'
+
+
+def to_source(node, indent_with=' ' * 4, add_line_information=False):
+    """This function can convert a node tree back into python sourcecode.
+    This is useful for debugging purposes, especially if you're dealing with
+    custom asts not generated by python itself.
+
+    It could be that the sourcecode is evaluable when the AST itself is not
+    compilable / evaluable.  The reason for this is that the AST contains some
+    more data than regular sourcecode does, which is dropped during
+    conversion.
+
+    Each level of indentation is replaced with `indent_with`.  Per default this
+    parameter is equal to four spaces as suggested by PEP 8, but it might be
+    adjusted to match the application's styleguide.
+
+    If `add_line_information` is set to `True` comments for the line numbers
+    of the nodes are added to the output.  This can be used to spot wrong line
+    number information of statement nodes.
+    """
+    generator = SourceGenerator(indent_with, add_line_information)
+    generator.visit(node)
+
+    return ''.join(generator.result)
+
+class SourceGenerator(NodeVisitor):
+    """This visitor is able to transform a well formed syntax tree into python
+    sourcecode.  For more details have a look at the docstring of the
+    `node_to_source` function.
+    """
+
+    def __init__(self, indent_with, add_line_information=False):
+        self.result = []
+        self.indent_with = indent_with
+        self.add_line_information = add_line_information
+        self.indentation = 0
+        self.new_lines = 0
+
+    def write(self, x):
+        if self.new_lines:
+            if self.result:
+                self.result.append('\n' * self.new_lines)
+            self.result.append(self.indent_with * self.indentation)
+            self.new_lines = 0
+        self.result.append(x)
+
+    def newline(self, node=None, extra=0):
+        self.new_lines = max(self.new_lines, 1 + extra)
+        if node is not None and self.add_line_information:
+            self.write('# line: %s' % node.lineno)
+            self.new_lines = 1
+
+    def body(self, statements):
+        self.new_line = True
+        self.indentation += 1
+        for stmt in statements:
+            self.visit(stmt)
+        self.indentation -= 1
+
+    def body_or_else(self, node):
+        self.body(node.body)
+        if node.orelse:
+            self.newline()
+            self.write('else:')
+            self.body(node.orelse)
+
+    def signature(self, node):
+        want_comma = []
+        def write_comma():
+            if want_comma:
+                self.write(', ')
+            else:
+                want_comma.append(True)
+
+        padding = [None] * (len(node.args) - len(node.defaults))
+        for arg, default in zip(node.args, padding + node.defaults):
+            write_comma()
+            self.visit(arg)
+            if default is not None:
+                self.write('=')
+                self.visit(default)
+        if node.vararg is not None:
+            write_comma()
+            try:
+                self.write('*' + node.vararg.arg)
+            except AttributeError:  # CRUFT: python 2
+                self.write('*' + node.vararg)
+        if node.kwarg is not None:
+            write_comma()
+            try:
+                self.write('**' + node.kwarg.arg)
+            except AttributeError:  # CRUFT: python 2
+                self.write('*' + node.vararg)
+
+    def decorators(self, node):
+        for decorator in node.decorator_list:
+            self.newline(decorator)
+            self.write('@')
+            self.visit(decorator)
+
+    # Statements
+
+    def visit_Assert(self, node):
+        self.newline(node)
+        self.write('assert ')
+        self.visit(node.test)
+        if node.msg is not None:
+           self.write(', ')
+           self.visit(node.msg)
+
+    def visit_Assign(self, node):
+        self.newline(node)
+        for idx, target in enumerate(node.targets):
+            if idx:
+                self.write(', ')
+            self.visit(target)
+        self.write(' = ')
+        self.visit(node.value)
+
+    def visit_AugAssign(self, node):
+        self.newline(node)
+        self.visit(node.target)
+        self.write(' ' + BINOP_SYMBOLS[type(node.op)] + '= ')
+        self.visit(node.value)
+
+    def visit_ImportFrom(self, node):
+        self.newline(node)
+        self.write('from %s%s import ' % ('.' * node.level, node.module))
+        for idx, item in enumerate(node.names):
+            if idx:
+                self.write(', ')
+            self.write(item)
+
+    def visit_Import(self, node):
+        self.newline(node)
+        for item in node.names:
+            self.write('import ')
+            self.visit(item)
+
+    def visit_Expr(self, node):
+        self.newline(node)
+        self.generic_visit(node)
+
+    def visit_FunctionDef(self, node):
+        self.newline(extra=1)
+        self.decorators(node)
+        self.newline(node)
+        self.write('def %s(' % node.name)
+        self.visit(node.args)
+        self.write('):')
+        self.body(node.body)
+
+    def visit_ClassDef(self, node):
+        have_args = []
+        def paren_or_comma():
+            if have_args:
+                self.write(', ')
+            else:
+                have_args.append(True)
+                self.write('(')
+
+        self.newline(extra=2)
+        self.decorators(node)
+        self.newline(node)
+        self.write('class %s' % node.name)
+        for base in node.bases:
+            paren_or_comma()
+            self.visit(base)
+        # XXX: the if here is used to keep this module compatible
+        #      with python 2.6.
+        if hasattr(node, 'keywords'):
+            for keyword in node.keywords:
+                paren_or_comma()
+                self.write(keyword.arg + '=')
+                self.visit(keyword.value)
+            if node.starargs is not None:
+                paren_or_comma()
+                self.write('*')
+                self.visit(node.starargs)
+            if node.kwargs is not None:
+                paren_or_comma()
+                self.write('**')
+                self.visit(node.kwargs)
+        self.write(have_args and '):' or ':')
+        self.body(node.body)
+
+    def visit_If(self, node):
+        self.newline(node)
+        self.write('if ')
+        self.visit(node.test)
+        self.write(':')
+        self.body(node.body)
+        while True:
+            else_ = node.orelse
+            if len(else_) == 0:
+                break
+            elif len(else_) == 1 and isinstance(else_[0], ast.If):
+                node = else_[0]
+                self.newline()
+                self.write('elif ')
+                self.visit(node.test)
+                self.write(':')
+                self.body(node.body)
+            else:
+                self.newline()
+                self.write('else:')
+                self.body(else_)
+                break
+
+    def visit_For(self, node):
+        self.newline(node)
+        self.write('for ')
+        self.visit(node.target)
+        self.write(' in ')
+        self.visit(node.iter)
+        self.write(':')
+        self.body_or_else(node)
+
+    def visit_While(self, node):
+        self.newline(node)
+        self.write('while ')
+        self.visit(node.test)
+        self.write(':')
+        self.body_or_else(node)
+
+    def visit_With(self, node):
+        self.newline(node)
+        self.write('with ')
+        self.visit(node.context_expr)
+        if node.optional_vars is not None:
+            self.write(' as ')
+            self.visit(node.optional_vars)
+        self.write(':')
+        self.body(node.body)
+
+    def visit_Pass(self, node):
+        self.newline(node)
+        self.write('pass')
+
+    def visit_Print(self, node):
+        # XXX: python 2.6 only
+        self.newline(node)
+        self.write('print ')
+        want_comma = False
+        if node.dest is not None:
+            self.write(' >> ')
+            self.visit(node.dest)
+            want_comma = True
+        for value in node.values:
+            if want_comma:
+                self.write(', ')
+            self.visit(value)
+            want_comma = True
+        if not node.nl:
+            self.write(',')
+
+    def visit_Delete(self, node):
+        self.newline(node)
+        self.write('del ')
+        for idx, target in enumerate(node):
+            if idx:
+                self.write(', ')
+            self.visit(target)
+
+    def visit_TryExcept(self, node):
+        self.newline(node)
+        self.write('try:')
+        self.body(node.body)
+        for handler in node.handlers:
+            self.visit(handler)
+
+    def visit_TryFinally(self, node):
+        self.newline(node)
+        self.write('try:')
+        self.body(node.body)
+        self.newline(node)
+        self.write('finally:')
+        self.body(node.finalbody)
+
+    def visit_Global(self, node):
+        self.newline(node)
+        self.write('global ' + ', '.join(node.names))
+
+    def visit_Nonlocal(self, node):
+        self.newline(node)
+        self.write('nonlocal ' + ', '.join(node.names))
+
+    def visit_Return(self, node):
+        self.newline(node)
+        if node.value is None:
+            self.write('return')
+        else:
+            self.write('return ')
+            self.visit(node.value)
+
+    def visit_Break(self, node):
+        self.newline(node)
+        self.write('break')
+
+    def visit_Continue(self, node):
+        self.newline(node)
+        self.write('continue')
+
+    def visit_Raise(self, node):
+        # XXX: Python 2.6 / 3.0 compatibility
+        self.newline(node)
+        self.write('raise')
+        if hasattr(node, 'exc') and node.exc is not None:
+            self.write(' ')
+            self.visit(node.exc)
+            if node.cause is not None:
+                self.write(' from ')
+                self.visit(node.cause)
+        elif hasattr(node, 'type') and node.type is not None:
+            self.visit(node.type)
+            if node.inst is not None:
+                self.write(', ')
+                self.visit(node.inst)
+            if node.tback is not None:
+                self.write(', ')
+                self.visit(node.tback)
+
+    # Expressions
+
+    def visit_Attribute(self, node):
+        self.visit(node.value)
+        self.write('.' + node.attr)
+
+    def visit_Call(self, node):
+        want_comma = []
+        def write_comma():
+            if want_comma:
+                self.write(', ')
+            else:
+                want_comma.append(True)
+
+        self.visit(node.func)
+        self.write('(')
+        for arg in node.args:
+            write_comma()
+            self.visit(arg)
+        for keyword in node.keywords:
+            write_comma()
+            self.write(keyword.arg + '=')
+            self.visit(keyword.value)
+        if getattr(node, 'starargs', None) is not None:
+            write_comma()
+            self.write('*')
+            self.visit(node.starargs)
+        if getattr(node, 'kwargs', None) is not None:
+            write_comma()
+            self.write('**')
+            self.visit(node.kwargs)
+        self.write(')')
+
+    def visit_Name(self, node):
+        self.write(node.id)
+
+    def visit_Str(self, node):
+        self.write(repr(node.s))
+
+    def visit_Bytes(self, node):
+        self.write(repr(node.s))
+
+    def visit_Num(self, node):
+        self.write(repr(node.n))
+
+    def visit_Tuple(self, node):
+        self.write('(')
+        idx = -1
+        for idx, item in enumerate(node.elts):
+            if idx:
+                self.write(', ')
+            self.visit(item)
+        self.write(idx and ')' or ',)')
+
+    def sequence_visit(left, right):
+        def visit(self, node):
+            self.write(left)
+            for idx, item in enumerate(node.elts):
+                if idx:
+                    self.write(', ')
+                self.visit(item)
+            self.write(right)
+        return visit
+
+    visit_List = sequence_visit('[', ']')
+    visit_Set = sequence_visit('{', '}')
+    del sequence_visit
+
+    def visit_Dict(self, node):
+        self.write('{')
+        for idx, (key, value) in enumerate(zip(node.keys, node.values)):
+            if idx:
+                self.write(', ')
+            self.visit(key)
+            self.write(': ')
+            self.visit(value)
+        self.write('}')
+
+    def visit_BinOp(self, node):
+        self.visit(node.left)
+        self.write(' %s ' % BINOP_SYMBOLS[type(node.op)])
+        self.visit(node.right)
+
+    def visit_BoolOp(self, node):
+        self.write('(')
+        for idx, value in enumerate(node.values):
+            if idx:
+                self.write(' %s ' % BOOLOP_SYMBOLS[type(node.op)])
+            self.visit(value)
+        self.write(')')
+
+    def visit_Compare(self, node):
+        self.write('(')
+        self.visit(node.left)
+        for op, right in zip(node.ops, node.comparators):
+            self.write(' %s ' % CMPOP_SYMBOLS[type(op)])
+            self.visit(right)
+        self.write(')')
+
+    def visit_UnaryOp(self, node):
+        self.write('(')
+        op = UNARYOP_SYMBOLS[type(node.op)]
+        self.write(op)
+        if op == 'not':
+            self.write(' ')
+        self.visit(node.operand)
+        self.write(')')
+
+    def visit_Subscript(self, node):
+        self.visit(node.value)
+        self.write('[')
+        self.visit(node.slice)
+        self.write(']')
+
+    def visit_Slice(self, node):
+        if node.lower is not None:
+            self.visit(node.lower)
+        self.write(':')
+        if node.upper is not None:
+            self.visit(node.upper)
+        if node.step is not None:
+            self.write(':')
+            if not (isinstance(node.step, ast.Name) and node.step.id == 'None'):
+                self.visit(node.step)
+
+    def visit_ExtSlice(self, node):
+        for idx, item in node.dims:
+            if idx:
+                self.write(', ')
+            self.visit(item)
+
+    def visit_Yield(self, node):
+        self.write('yield ')
+        self.visit(node.value)
+
+    def visit_Lambda(self, node):
+        self.write('lambda ')
+        self.visit(node.args)
+        self.write(': ')
+        self.visit(node.body)
+
+    def visit_Ellipsis(self, node):
+        self.write('Ellipsis')
+
+    def generator_visit(left, right):
+        def visit(self, node):
+            self.write(left)
+            self.visit(node.elt)
+            for comprehension in node.generators:
+                self.visit(comprehension)
+            self.write(right)
+        return visit
+
+    visit_ListComp = generator_visit('[', ']')
+    visit_GeneratorExp = generator_visit('(', ')')
+    visit_SetComp = generator_visit('{', '}')
+    del generator_visit
+
+    def visit_DictComp(self, node):
+        self.write('{')
+        self.visit(node.key)
+        self.write(': ')
+        self.visit(node.value)
+        for comprehension in node.generators:
+            self.visit(comprehension)
+        self.write('}')
+
+    def visit_IfExp(self, node):
+        self.visit(node.body)
+        self.write(' if ')
+        self.visit(node.test)
+        self.write(' else ')
+        self.visit(node.orelse)
+
+    def visit_Starred(self, node):
+        self.write('*')
+        self.visit(node.value)
+
+    def visit_Repr(self, node):
+        # XXX: python 2.6 only
+        self.write('`')
+        self.visit(node.value)
+        self.write('`')
+
+    # Helper Nodes
+
+    def visit_alias(self, node):
+        self.write(node.name)
+        if node.asname is not None:
+            self.write(' as ' + node.asname)
+
+    def visit_comprehension(self, node):
+        self.write(' for ')
+        self.visit(node.target)
+        self.write(' in ')
+        self.visit(node.iter)
+        if node.ifs:
+            for if_ in node.ifs:
+                self.write(' if ')
+                self.visit(if_)
+
+    def visit_excepthandler(self, node):
+        self.newline(node)
+        self.write('except')
+        if node.type is not None:
+            self.write(' ')
+            self.visit(node.type)
+            if node.name is not None:
+                self.write(' as ')
+                self.visit(node.name)
+        self.write(':')
+        self.body(node.body)
+
+    def visit_arguments(self, node):
+        self.signature(node)
+
+# ===== inspect.getclosurevars backport begin =====
+
+# copied from python 3
+from inspect import ismethod, isfunction, ismodule
+from collections import namedtuple
+builtins = __builtins__
+ClosureVars = namedtuple('ClosureVars', 'nonlocals globals builtins unbound')
+def py2_getclosurevars(func):
+    """
+    Get the mapping of free variables to their current values.
+
+    Returns a named tuple of dicts mapping the current nonlocal, global
+    and builtin references as seen by the body of the function. A final
+    set of unbound names that could not be resolved is also provided.
+    """
+
+    if ismethod(func):
+        func = func.__func__
+
+    if not isfunction(func):
+        raise TypeError("'{!r}' is not a Python function".format(func))
+
+    code = func.__code__
+    # Nonlocal references are named in co_freevars and resolved
+    # by looking them up in __closure__ by positional index
+    if func.__closure__ is None:
+        nonlocal_vars = {}
+    else:
+        nonlocal_vars = {
+            var : cell.cell_contents
+            for var, cell in zip(code.co_freevars, func.__closure__)
+       }
+
+    # Global and builtin references are named in co_names and resolved
+    # by looking them up in __globals__ or __builtins__
+    global_ns = func.__globals__
+    builtin_ns = global_ns.get("__builtins__", builtins.__dict__)
+    if ismodule(builtin_ns):
+        builtin_ns = builtin_ns.__dict__
+    global_vars = {}
+    builtin_vars = {}
+    unbound_names = set()
+    for name in code.co_names:
+        if name in ("None", "True", "False"):
+            # Because these used to be builtins instead of keywords, they
+            # may still show up as name references. We ignore them.
+            continue
+        try:
+            global_vars[name] = global_ns[name]
+        except KeyError:
+            try:
+                builtin_vars[name] = builtin_ns[name]
+            except KeyError:
+                unbound_names.add(name)
+
+    return ClosureVars(nonlocal_vars, global_vars,
+                       builtin_vars, unbound_names)
+
+import inspect
+if not hasattr(inspect, 'getclosurevars'):
+    inspect.getclosurevars = py2_getclosurevars
+
+# ===== inspect.getclosurevars backport end ======
+
+def print_function(f=None):
+    """
+    Print out the code for the function
+    """
+    # Include some comments to see if they get printed
+    import ast
+    import inspect
+    print("function:", f.__code__.co_name)
+    print("closure:", inspect.getclosurevars(f))
+    print("locals:", f.__code__.co_nlocals, f.__code__.co_names)
+    if f is not None:
+        tree = ast.parse(inspect.getsource(f))
+        print(to_source(tree))
+
+from math import sin
+outside = '40 C'
+def _hello(*args, **kw):
+    x = sin(y) + cos(z.real)
+    print("world", outside)
+
+if __name__ == "__main__":
+    #print_function(print_function)
+    print_function(_hello)
Index: sasmodels/generate.py
===================================================================
--- sasmodels/generate.py	(revision 2d81cfe3be42579d563407fb9275b7b516fee234)
+++ sasmodels/generate.py	(revision db0340684d33368d63f9c39a84e1c2398bf1e953)
@@ -709,4 +709,7 @@
         _add_source(source, code, path)
 
+    if model_info.c_code:
+        source.append(model_info.c_code)
+
     # Make parameters for q, qx, qy so that we can use them in declarations
     q, qx, qy = [Parameter(name=v) for v in ('q', 'qx', 'qy')]
Index: sasmodels/modelinfo.py
===================================================================
--- sasmodels/modelinfo.py	(revision 2d81cfe3be42579d563407fb9275b7b516fee234)
+++ sasmodels/modelinfo.py	(revision db0340684d33368d63f9c39a84e1c2398bf1e953)
@@ -12,6 +12,9 @@
 from os.path import abspath, basename, splitext
 import inspect
+import logging
 
 import numpy as np  # type: ignore
+
+from . import autoc
 
 # Optional typing
@@ -32,4 +35,6 @@
     TestCondition = Tuple[ParameterSetUser, TestInput, TestValue]
 # pylint: enable=unused-import
+
+logger = logging.getLogger(__name__)
 
 # If MAX_PD changes, need to change the loop macros in kernel_iq.c
@@ -789,4 +794,5 @@
     info.structure_factor = getattr(kernel_module, 'structure_factor', False)
     info.profile_axes = getattr(kernel_module, 'profile_axes', ['x', 'y'])
+    info.c_code = getattr(kernel_module, 'c_code', None)
     info.source = getattr(kernel_module, 'source', [])
     # TODO: check the structure of the tests
@@ -812,4 +818,9 @@
 
     _find_source_lines(info, kernel_module)
+    try:
+        autoc.convert(info, kernel_module)
+    except Exception as exc:
+        raise
+        logger.warn(str(exc))
 
     return info
@@ -935,4 +946,8 @@
     #: See :attr:`ER` for details on the parameters.
     VR = None               # type: Optional[Callable[[np.ndarray], Tuple[np.ndarray, np.ndarray]]]
+    #: Arbitrary C code containing supporting functions, etc., to be inserted
+    #: after everything in source.  This can include Iq and Iqxy functions with
+    #: the full function signature, including all parameters.
+    c_code = None
     #: Returns the form volume for python-based models.  Form volume is needed
     #: for volume normalization in the polydispersity integral.  If no
Index: sasmodels/special.py
===================================================================
--- sasmodels/special.py	(revision e65c3ba5944b729f651cf8747f7b64bed2cbb826)
+++ sasmodels/special.py	(revision db0340684d33368d63f9c39a84e1c2398bf1e953)
@@ -205,5 +205,7 @@
 from numpy import arctan2 as atan2
 from numpy import fmin, fmax, trunc, rint
-from numpy import NAN, inf as INFINITY
+from numpy import pi, nan, inf
+NAN = nan
+INFINITY = inf
 
 from scipy.special import gamma as sas_gamma
@@ -226,4 +228,5 @@
     """return sin(x), cos(x)"""
     return sin(x), cos(x)
+sincos = SINCOS
 
 def square(x):
@@ -294,512 +297,520 @@
 
 # Gaussians
-
-Gauss20Wt = np.array([
-    .0176140071391521,
-    .0406014298003869,
-    .0626720483341091,
-    .0832767415767047,
-    .10193011981724,
-    .118194531961518,
-    .131688638449177,
-    .142096109318382,
-    .149172986472604,
-    .152753387130726,
-    .152753387130726,
-    .149172986472604,
-    .142096109318382,
-    .131688638449177,
-    .118194531961518,
-    .10193011981724,
-    .0832767415767047,
-    .0626720483341091,
-    .0406014298003869,
-    .0176140071391521
-])
-
-Gauss20Z = np.array([
-    -.993128599185095,
-    -.963971927277914,
-    -.912234428251326,
-    -.839116971822219,
-    -.746331906460151,
-    -.636053680726515,
-    -.510867001950827,
-    -.37370608871542,
-    -.227785851141645,
-    -.076526521133497,
-    .0765265211334973,
-    .227785851141645,
-    .37370608871542,
-    .510867001950827,
-    .636053680726515,
-    .746331906460151,
-    .839116971822219,
-    .912234428251326,
-    .963971927277914,
-    .993128599185095
-])
-
-Gauss76Wt = np.array([
-    .00126779163408536,		#0
-    .00294910295364247,
-    .00462793522803742,
-    .00629918049732845,
-    .00795984747723973,
-    .00960710541471375,
-    .0112381685696677,
-    .0128502838475101,
-    .0144407317482767,
-    .0160068299122486,
-    .0175459372914742,		#10
-    .0190554584671906,
-    .020532847967908,
-    .0219756145344162,
-    .0233813253070112,
-    .0247476099206597,
-    .026072164497986,
-    .0273527555318275,
-    .028587223650054,
-    .029773487255905,
-    .0309095460374916,		#20
-    .0319934843404216,
-    .0330234743977917,
-    .0339977794120564,
-    .0349147564835508,
-    .0357728593807139,
-    .0365706411473296,
-    .0373067565423816,
-    .0379799643084053,
-    .0385891292645067,
-    .0391332242205184,		#30
-    .0396113317090621,
-    .0400226455325968,
-    .040366472122844,
-    .0406422317102947,
-    .0408494593018285,
-    .040987805464794,
-    .0410570369162294,
-    .0410570369162294,
-    .040987805464794,
-    .0408494593018285,		#40
-    .0406422317102947,
-    .040366472122844,
-    .0400226455325968,
-    .0396113317090621,
-    .0391332242205184,
-    .0385891292645067,
-    .0379799643084053,
-    .0373067565423816,
-    .0365706411473296,
-    .0357728593807139,		#50
-    .0349147564835508,
-    .0339977794120564,
-    .0330234743977917,
-    .0319934843404216,
-    .0309095460374916,
-    .029773487255905,
-    .028587223650054,
-    .0273527555318275,
-    .026072164497986,
-    .0247476099206597,		#60
-    .0233813253070112,
-    .0219756145344162,
-    .020532847967908,
-    .0190554584671906,
-    .0175459372914742,
-    .0160068299122486,
-    .0144407317482767,
-    .0128502838475101,
-    .0112381685696677,
-    .00960710541471375,		#70
-    .00795984747723973,
-    .00629918049732845,
-    .00462793522803742,
-    .00294910295364247,
-    .00126779163408536		#75 (indexed from 0)
-])
-
-Gauss76Z = np.array([
-    -.999505948362153,		#0
-    -.997397786355355,
-    -.993608772723527,
-    -.988144453359837,
-    -.981013938975656,
-    -.972229228520377,
-    -.961805126758768,
-    -.949759207710896,
-    -.936111781934811,
-    -.92088586125215,
-    -.904107119545567,		#10
-    -.885803849292083,
-    -.866006913771982,
-    -.844749694983342,
-    -.822068037328975,
-    -.7980001871612,
-    -.77258672828181,
-    -.74587051350361,
-    -.717896592387704,
-    -.688712135277641,
-    -.658366353758143,		#20
-    -.626910417672267,
-    -.594397368836793,
-    -.560882031601237,
-    -.526420920401243,
-    -.491072144462194,
-    -.454895309813726,
-    -.417951418780327,
-    -.380302767117504,
-    -.342012838966962,
-    -.303146199807908,		#30
-    -.263768387584994,
-    -.223945802196474,
-    -.183745593528914,
-    -.143235548227268,
-    -.102483975391227,
-    -.0615595913906112,
-    -.0205314039939986,
-    .0205314039939986,
-    .0615595913906112,
-    .102483975391227,			#40
-    .143235548227268,
-    .183745593528914,
-    .223945802196474,
-    .263768387584994,
-    .303146199807908,
-    .342012838966962,
-    .380302767117504,
-    .417951418780327,
-    .454895309813726,
-    .491072144462194,		#50
-    .526420920401243,
-    .560882031601237,
-    .594397368836793,
-    .626910417672267,
-    .658366353758143,
-    .688712135277641,
-    .717896592387704,
-    .74587051350361,
-    .77258672828181,
-    .7980001871612,	#60
-    .822068037328975,
-    .844749694983342,
-    .866006913771982,
-    .885803849292083,
-    .904107119545567,
-    .92088586125215,
-    .936111781934811,
-    .949759207710896,
-    .961805126758768,
-    .972229228520377,		#70
-    .981013938975656,
-    .988144453359837,
-    .993608772723527,
-    .997397786355355,
-    .999505948362153		#75
-])
-
-Gauss150Z = np.array([
-    -0.9998723404457334,
-    -0.9993274305065947,
-    -0.9983473449340834,
-    -0.9969322929775997,
-    -0.9950828645255290,
-    -0.9927998590434373,
-    -0.9900842691660192,
-    -0.9869372772712794,
-    -0.9833602541697529,
-    -0.9793547582425894,
-    -0.9749225346595943,
-    -0.9700655145738374,
-    -0.9647858142586956,
-    -0.9590857341746905,
-    -0.9529677579610971,
-    -0.9464345513503147,
-    -0.9394889610042837,
-    -0.9321340132728527,
-    -0.9243729128743136,
-    -0.9162090414984952,
-    -0.9076459563329236,
-    -0.8986873885126239,
-    -0.8893372414942055,
-    -0.8795995893549102,
-    -0.8694786750173527,
-    -0.8589789084007133,
-    -0.8481048644991847,
-    -0.8368612813885015,
-    -0.8252530581614230,
-    -0.8132852527930605,
-    -0.8009630799369827,
-    -0.7882919086530552,
-    -0.7752772600680049,
-    -0.7619248049697269,
-    -0.7482403613363824,
-    -0.7342298918013638,
-    -0.7198995010552305,
-    -0.7052554331857488,
-    -0.6903040689571928,
-    -0.6750519230300931,
-    -0.6595056411226444,
-    -0.6436719971150083,
-    -0.6275578900977726,
-    -0.6111703413658551,
-    -0.5945164913591590,
-    -0.5776035965513142,
-    -0.5604390262878617,
-    -0.5430302595752546,
-    -0.5253848818220803,
-    -0.5075105815339176,
-    -0.4894151469632753,
-    -0.4711064627160663,
-    -0.4525925063160997,
-    -0.4338813447290861,
-    -0.4149811308476706,
-    -0.3959000999390257,
-    -0.3766465660565522,
-    -0.3572289184172501,
-    -0.3376556177463400,
-    -0.3179351925907259,
-    -0.2980762356029071,
-    -0.2780873997969574,
-    -0.2579773947782034,
-    -0.2377549829482451,
-    -0.2174289756869712,
-    -0.1970082295132342,
-    -0.1765016422258567,
-    -0.1559181490266516,
-    -0.1352667186271445,
-    -0.1145563493406956,
-    -0.0937960651617229,
-    -0.0729949118337358,
-    -0.0521619529078925,
-    -0.0313062657937972,
-    -0.0104369378042598,
-    0.0104369378042598,
-    0.0313062657937972,
-    0.0521619529078925,
-    0.0729949118337358,
-    0.0937960651617229,
-    0.1145563493406956,
-    0.1352667186271445,
-    0.1559181490266516,
-    0.1765016422258567,
-    0.1970082295132342,
-    0.2174289756869712,
-    0.2377549829482451,
-    0.2579773947782034,
-    0.2780873997969574,
-    0.2980762356029071,
-    0.3179351925907259,
-    0.3376556177463400,
-    0.3572289184172501,
-    0.3766465660565522,
-    0.3959000999390257,
-    0.4149811308476706,
-    0.4338813447290861,
-    0.4525925063160997,
-    0.4711064627160663,
-    0.4894151469632753,
-    0.5075105815339176,
-    0.5253848818220803,
-    0.5430302595752546,
-    0.5604390262878617,
-    0.5776035965513142,
-    0.5945164913591590,
-    0.6111703413658551,
-    0.6275578900977726,
-    0.6436719971150083,
-    0.6595056411226444,
-    0.6750519230300931,
-    0.6903040689571928,
-    0.7052554331857488,
-    0.7198995010552305,
-    0.7342298918013638,
-    0.7482403613363824,
-    0.7619248049697269,
-    0.7752772600680049,
-    0.7882919086530552,
-    0.8009630799369827,
-    0.8132852527930605,
-    0.8252530581614230,
-    0.8368612813885015,
-    0.8481048644991847,
-    0.8589789084007133,
-    0.8694786750173527,
-    0.8795995893549102,
-    0.8893372414942055,
-    0.8986873885126239,
-    0.9076459563329236,
-    0.9162090414984952,
-    0.9243729128743136,
-    0.9321340132728527,
-    0.9394889610042837,
-    0.9464345513503147,
-    0.9529677579610971,
-    0.9590857341746905,
-    0.9647858142586956,
-    0.9700655145738374,
-    0.9749225346595943,
-    0.9793547582425894,
-    0.9833602541697529,
-    0.9869372772712794,
-    0.9900842691660192,
-    0.9927998590434373,
-    0.9950828645255290,
-    0.9969322929775997,
-    0.9983473449340834,
-    0.9993274305065947,
-    0.9998723404457334
-])
-
-Gauss150Wt = np.array([
-    0.0003276086705538,
-    0.0007624720924706,
-    0.0011976474864367,
-    0.0016323569986067,
-    0.0020663664924131,
-    0.0024994789888943,
-    0.0029315036836558,
-    0.0033622516236779,
-    0.0037915348363451,
-    0.0042191661429919,
-    0.0046449591497966,
-    0.0050687282939456,
-    0.0054902889094487,
-    0.0059094573005900,
-    0.0063260508184704,
-    0.0067398879387430,
-    0.0071507883396855,
-    0.0075585729801782,
-    0.0079630641773633,
-    0.0083640856838475,
-    0.0087614627643580,
-    0.0091550222717888,
-    0.0095445927225849,
-    0.0099300043714212,
-    0.0103110892851360,
-    0.0106876814158841,
-    0.0110596166734735,
-    0.0114267329968529,
-    0.0117888704247183,
-    0.0121458711652067,
-    0.0124975796646449,
-    0.0128438426753249,
-    0.0131845093222756,
-    0.0135194311690004,
-    0.0138484622795371,
-    0.0141714592928592,
-    0.0144882814685445,
-    0.0147987907597169,
-    0.0151028518701744,
-    0.0154003323133401,
-    0.0156911024699895,
-    0.0159750356447283,
-    0.0162520081211971,
-    0.0165218992159766,
-    0.0167845913311726,
-    0.0170399700056559,
-    0.0172879239649355,
-    0.0175283451696437,
-    0.0177611288626114,
-    0.0179861736145128,
-    0.0182033813680609,
-    0.0184126574807331,
-    0.0186139107660094,
-    0.0188070535331042,
-    0.0189920016251754,
-    0.0191686744559934,
-    0.0193369950450545,
-    0.0194968900511231,
-    0.0196482898041878,
-    0.0197911283358190,
-    0.0199253434079123,
-    0.0200508765398072,
-    0.0201676730337687,
-    0.0202756819988200,
-    0.0203748563729175,
-    0.0204651529434560,
-    0.0205465323660984,
-    0.0206189591819181,
-    0.0206824018328499,
-    0.0207368326754401,
-    0.0207822279928917,
-    0.0208185680053983,
-    0.0208458368787627,
-    0.0208640227312962,
-    0.0208731176389954,
-    0.0208731176389954,
-    0.0208640227312962,
-    0.0208458368787627,
-    0.0208185680053983,
-    0.0207822279928917,
-    0.0207368326754401,
-    0.0206824018328499,
-    0.0206189591819181,
-    0.0205465323660984,
-    0.0204651529434560,
-    0.0203748563729175,
-    0.0202756819988200,
-    0.0201676730337687,
-    0.0200508765398072,
-    0.0199253434079123,
-    0.0197911283358190,
-    0.0196482898041878,
-    0.0194968900511231,
-    0.0193369950450545,
-    0.0191686744559934,
-    0.0189920016251754,
-    0.0188070535331042,
-    0.0186139107660094,
-    0.0184126574807331,
-    0.0182033813680609,
-    0.0179861736145128,
-    0.0177611288626114,
-    0.0175283451696437,
-    0.0172879239649355,
-    0.0170399700056559,
-    0.0167845913311726,
-    0.0165218992159766,
-    0.0162520081211971,
-    0.0159750356447283,
-    0.0156911024699895,
-    0.0154003323133401,
-    0.0151028518701744,
-    0.0147987907597169,
-    0.0144882814685445,
-    0.0141714592928592,
-    0.0138484622795371,
-    0.0135194311690004,
-    0.0131845093222756,
-    0.0128438426753249,
-    0.0124975796646449,
-    0.0121458711652067,
-    0.0117888704247183,
-    0.0114267329968529,
-    0.0110596166734735,
-    0.0106876814158841,
-    0.0103110892851360,
-    0.0099300043714212,
-    0.0095445927225849,
-    0.0091550222717888,
-    0.0087614627643580,
-    0.0083640856838475,
-    0.0079630641773633,
-    0.0075585729801782,
-    0.0071507883396855,
-    0.0067398879387430,
-    0.0063260508184704,
-    0.0059094573005900,
-    0.0054902889094487,
-    0.0050687282939456,
-    0.0046449591497966,
-    0.0042191661429919,
-    0.0037915348363451,
-    0.0033622516236779,
-    0.0029315036836558,
-    0.0024994789888943,
-    0.0020663664924131,
-    0.0016323569986067,
-    0.0011976474864367,
-    0.0007624720924706,
-    0.0003276086705538
-])
+class Gauss:
+    def __init__(self, w, z):
+        self.n = len(w)
+        self.w = w
+        self.z = z
+
+gauss20 = Gauss(
+    w=np.array([
+        .0176140071391521,
+        .0406014298003869,
+        .0626720483341091,
+        .0832767415767047,
+        .10193011981724,
+        .118194531961518,
+        .131688638449177,
+        .142096109318382,
+        .149172986472604,
+        .152753387130726,
+        .152753387130726,
+        .149172986472604,
+        .142096109318382,
+        .131688638449177,
+        .118194531961518,
+        .10193011981724,
+        .0832767415767047,
+        .0626720483341091,
+        .0406014298003869,
+        .0176140071391521
+    ]),
+    z=np.array([
+        -.993128599185095,
+        -.963971927277914,
+        -.912234428251326,
+        -.839116971822219,
+        -.746331906460151,
+        -.636053680726515,
+        -.510867001950827,
+        -.37370608871542,
+        -.227785851141645,
+        -.076526521133497,
+        .0765265211334973,
+        .227785851141645,
+        .37370608871542,
+        .510867001950827,
+        .636053680726515,
+        .746331906460151,
+        .839116971822219,
+        .912234428251326,
+        .963971927277914,
+        .993128599185095
+    ])
+)
+
+gauss76 = Gauss(
+    w=np.array([
+        .00126779163408536,		#0
+        .00294910295364247,
+        .00462793522803742,
+        .00629918049732845,
+        .00795984747723973,
+        .00960710541471375,
+        .0112381685696677,
+        .0128502838475101,
+        .0144407317482767,
+        .0160068299122486,
+        .0175459372914742,		#10
+        .0190554584671906,
+        .020532847967908,
+        .0219756145344162,
+        .0233813253070112,
+        .0247476099206597,
+        .026072164497986,
+        .0273527555318275,
+        .028587223650054,
+        .029773487255905,
+        .0309095460374916,		#20
+        .0319934843404216,
+        .0330234743977917,
+        .0339977794120564,
+        .0349147564835508,
+        .0357728593807139,
+        .0365706411473296,
+        .0373067565423816,
+        .0379799643084053,
+        .0385891292645067,
+        .0391332242205184,		#30
+        .0396113317090621,
+        .0400226455325968,
+        .040366472122844,
+        .0406422317102947,
+        .0408494593018285,
+        .040987805464794,
+        .0410570369162294,
+        .0410570369162294,
+        .040987805464794,
+        .0408494593018285,		#40
+        .0406422317102947,
+        .040366472122844,
+        .0400226455325968,
+        .0396113317090621,
+        .0391332242205184,
+        .0385891292645067,
+        .0379799643084053,
+        .0373067565423816,
+        .0365706411473296,
+        .0357728593807139,		#50
+        .0349147564835508,
+        .0339977794120564,
+        .0330234743977917,
+        .0319934843404216,
+        .0309095460374916,
+        .029773487255905,
+        .028587223650054,
+        .0273527555318275,
+        .026072164497986,
+        .0247476099206597,		#60
+        .0233813253070112,
+        .0219756145344162,
+        .020532847967908,
+        .0190554584671906,
+        .0175459372914742,
+        .0160068299122486,
+        .0144407317482767,
+        .0128502838475101,
+        .0112381685696677,
+        .00960710541471375,		#70
+        .00795984747723973,
+        .00629918049732845,
+        .00462793522803742,
+        .00294910295364247,
+        .00126779163408536		#75 (indexed from 0)
+    ]),
+    z=np.array([
+        -.999505948362153,		#0
+        -.997397786355355,
+        -.993608772723527,
+        -.988144453359837,
+        -.981013938975656,
+        -.972229228520377,
+        -.961805126758768,
+        -.949759207710896,
+        -.936111781934811,
+        -.92088586125215,
+        -.904107119545567,		#10
+        -.885803849292083,
+        -.866006913771982,
+        -.844749694983342,
+        -.822068037328975,
+        -.7980001871612,
+        -.77258672828181,
+        -.74587051350361,
+        -.717896592387704,
+        -.688712135277641,
+        -.658366353758143,		#20
+        -.626910417672267,
+        -.594397368836793,
+        -.560882031601237,
+        -.526420920401243,
+        -.491072144462194,
+        -.454895309813726,
+        -.417951418780327,
+        -.380302767117504,
+        -.342012838966962,
+        -.303146199807908,		#30
+        -.263768387584994,
+        -.223945802196474,
+        -.183745593528914,
+        -.143235548227268,
+        -.102483975391227,
+        -.0615595913906112,
+        -.0205314039939986,
+        .0205314039939986,
+        .0615595913906112,
+        .102483975391227,			#40
+        .143235548227268,
+        .183745593528914,
+        .223945802196474,
+        .263768387584994,
+        .303146199807908,
+        .342012838966962,
+        .380302767117504,
+        .417951418780327,
+        .454895309813726,
+        .491072144462194,		#50
+        .526420920401243,
+        .560882031601237,
+        .594397368836793,
+        .626910417672267,
+        .658366353758143,
+        .688712135277641,
+        .717896592387704,
+        .74587051350361,
+        .77258672828181,
+        .7980001871612,	#60
+        .822068037328975,
+        .844749694983342,
+        .866006913771982,
+        .885803849292083,
+        .904107119545567,
+        .92088586125215,
+        .936111781934811,
+        .949759207710896,
+        .961805126758768,
+        .972229228520377,		#70
+        .981013938975656,
+        .988144453359837,
+        .993608772723527,
+        .997397786355355,
+        .999505948362153		#75
+    ])
+)
+
+gauss150 = Gauss(
+    z=np.array([
+        -0.9998723404457334,
+        -0.9993274305065947,
+        -0.9983473449340834,
+        -0.9969322929775997,
+        -0.9950828645255290,
+        -0.9927998590434373,
+        -0.9900842691660192,
+        -0.9869372772712794,
+        -0.9833602541697529,
+        -0.9793547582425894,
+        -0.9749225346595943,
+        -0.9700655145738374,
+        -0.9647858142586956,
+        -0.9590857341746905,
+        -0.9529677579610971,
+        -0.9464345513503147,
+        -0.9394889610042837,
+        -0.9321340132728527,
+        -0.9243729128743136,
+        -0.9162090414984952,
+        -0.9076459563329236,
+        -0.8986873885126239,
+        -0.8893372414942055,
+        -0.8795995893549102,
+        -0.8694786750173527,
+        -0.8589789084007133,
+        -0.8481048644991847,
+        -0.8368612813885015,
+        -0.8252530581614230,
+        -0.8132852527930605,
+        -0.8009630799369827,
+        -0.7882919086530552,
+        -0.7752772600680049,
+        -0.7619248049697269,
+        -0.7482403613363824,
+        -0.7342298918013638,
+        -0.7198995010552305,
+        -0.7052554331857488,
+        -0.6903040689571928,
+        -0.6750519230300931,
+        -0.6595056411226444,
+        -0.6436719971150083,
+        -0.6275578900977726,
+        -0.6111703413658551,
+        -0.5945164913591590,
+        -0.5776035965513142,
+        -0.5604390262878617,
+        -0.5430302595752546,
+        -0.5253848818220803,
+        -0.5075105815339176,
+        -0.4894151469632753,
+        -0.4711064627160663,
+        -0.4525925063160997,
+        -0.4338813447290861,
+        -0.4149811308476706,
+        -0.3959000999390257,
+        -0.3766465660565522,
+        -0.3572289184172501,
+        -0.3376556177463400,
+        -0.3179351925907259,
+        -0.2980762356029071,
+        -0.2780873997969574,
+        -0.2579773947782034,
+        -0.2377549829482451,
+        -0.2174289756869712,
+        -0.1970082295132342,
+        -0.1765016422258567,
+        -0.1559181490266516,
+        -0.1352667186271445,
+        -0.1145563493406956,
+        -0.0937960651617229,
+        -0.0729949118337358,
+        -0.0521619529078925,
+        -0.0313062657937972,
+        -0.0104369378042598,
+        0.0104369378042598,
+        0.0313062657937972,
+        0.0521619529078925,
+        0.0729949118337358,
+        0.0937960651617229,
+        0.1145563493406956,
+        0.1352667186271445,
+        0.1559181490266516,
+        0.1765016422258567,
+        0.1970082295132342,
+        0.2174289756869712,
+        0.2377549829482451,
+        0.2579773947782034,
+        0.2780873997969574,
+        0.2980762356029071,
+        0.3179351925907259,
+        0.3376556177463400,
+        0.3572289184172501,
+        0.3766465660565522,
+        0.3959000999390257,
+        0.4149811308476706,
+        0.4338813447290861,
+        0.4525925063160997,
+        0.4711064627160663,
+        0.4894151469632753,
+        0.5075105815339176,
+        0.5253848818220803,
+        0.5430302595752546,
+        0.5604390262878617,
+        0.5776035965513142,
+        0.5945164913591590,
+        0.6111703413658551,
+        0.6275578900977726,
+        0.6436719971150083,
+        0.6595056411226444,
+        0.6750519230300931,
+        0.6903040689571928,
+        0.7052554331857488,
+        0.7198995010552305,
+        0.7342298918013638,
+        0.7482403613363824,
+        0.7619248049697269,
+        0.7752772600680049,
+        0.7882919086530552,
+        0.8009630799369827,
+        0.8132852527930605,
+        0.8252530581614230,
+        0.8368612813885015,
+        0.8481048644991847,
+        0.8589789084007133,
+        0.8694786750173527,
+        0.8795995893549102,
+        0.8893372414942055,
+        0.8986873885126239,
+        0.9076459563329236,
+        0.9162090414984952,
+        0.9243729128743136,
+        0.9321340132728527,
+        0.9394889610042837,
+        0.9464345513503147,
+        0.9529677579610971,
+        0.9590857341746905,
+        0.9647858142586956,
+        0.9700655145738374,
+        0.9749225346595943,
+        0.9793547582425894,
+        0.9833602541697529,
+        0.9869372772712794,
+        0.9900842691660192,
+        0.9927998590434373,
+        0.9950828645255290,
+        0.9969322929775997,
+        0.9983473449340834,
+        0.9993274305065947,
+        0.9998723404457334
+    ]),
+    w=np.array([
+        0.0003276086705538,
+        0.0007624720924706,
+        0.0011976474864367,
+        0.0016323569986067,
+        0.0020663664924131,
+        0.0024994789888943,
+        0.0029315036836558,
+        0.0033622516236779,
+        0.0037915348363451,
+        0.0042191661429919,
+        0.0046449591497966,
+        0.0050687282939456,
+        0.0054902889094487,
+        0.0059094573005900,
+        0.0063260508184704,
+        0.0067398879387430,
+        0.0071507883396855,
+        0.0075585729801782,
+        0.0079630641773633,
+        0.0083640856838475,
+        0.0087614627643580,
+        0.0091550222717888,
+        0.0095445927225849,
+        0.0099300043714212,
+        0.0103110892851360,
+        0.0106876814158841,
+        0.0110596166734735,
+        0.0114267329968529,
+        0.0117888704247183,
+        0.0121458711652067,
+        0.0124975796646449,
+        0.0128438426753249,
+        0.0131845093222756,
+        0.0135194311690004,
+        0.0138484622795371,
+        0.0141714592928592,
+        0.0144882814685445,
+        0.0147987907597169,
+        0.0151028518701744,
+        0.0154003323133401,
+        0.0156911024699895,
+        0.0159750356447283,
+        0.0162520081211971,
+        0.0165218992159766,
+        0.0167845913311726,
+        0.0170399700056559,
+        0.0172879239649355,
+        0.0175283451696437,
+        0.0177611288626114,
+        0.0179861736145128,
+        0.0182033813680609,
+        0.0184126574807331,
+        0.0186139107660094,
+        0.0188070535331042,
+        0.0189920016251754,
+        0.0191686744559934,
+        0.0193369950450545,
+        0.0194968900511231,
+        0.0196482898041878,
+        0.0197911283358190,
+        0.0199253434079123,
+        0.0200508765398072,
+        0.0201676730337687,
+        0.0202756819988200,
+        0.0203748563729175,
+        0.0204651529434560,
+        0.0205465323660984,
+        0.0206189591819181,
+        0.0206824018328499,
+        0.0207368326754401,
+        0.0207822279928917,
+        0.0208185680053983,
+        0.0208458368787627,
+        0.0208640227312962,
+        0.0208731176389954,
+        0.0208731176389954,
+        0.0208640227312962,
+        0.0208458368787627,
+        0.0208185680053983,
+        0.0207822279928917,
+        0.0207368326754401,
+        0.0206824018328499,
+        0.0206189591819181,
+        0.0205465323660984,
+        0.0204651529434560,
+        0.0203748563729175,
+        0.0202756819988200,
+        0.0201676730337687,
+        0.0200508765398072,
+        0.0199253434079123,
+        0.0197911283358190,
+        0.0196482898041878,
+        0.0194968900511231,
+        0.0193369950450545,
+        0.0191686744559934,
+        0.0189920016251754,
+        0.0188070535331042,
+        0.0186139107660094,
+        0.0184126574807331,
+        0.0182033813680609,
+        0.0179861736145128,
+        0.0177611288626114,
+        0.0175283451696437,
+        0.0172879239649355,
+        0.0170399700056559,
+        0.0167845913311726,
+        0.0165218992159766,
+        0.0162520081211971,
+        0.0159750356447283,
+        0.0156911024699895,
+        0.0154003323133401,
+        0.0151028518701744,
+        0.0147987907597169,
+        0.0144882814685445,
+        0.0141714592928592,
+        0.0138484622795371,
+        0.0135194311690004,
+        0.0131845093222756,
+        0.0128438426753249,
+        0.0124975796646449,
+        0.0121458711652067,
+        0.0117888704247183,
+        0.0114267329968529,
+        0.0110596166734735,
+        0.0106876814158841,
+        0.0103110892851360,
+        0.0099300043714212,
+        0.0095445927225849,
+        0.0091550222717888,
+        0.0087614627643580,
+        0.0083640856838475,
+        0.0079630641773633,
+        0.0075585729801782,
+        0.0071507883396855,
+        0.0067398879387430,
+        0.0063260508184704,
+        0.0059094573005900,
+        0.0054902889094487,
+        0.0050687282939456,
+        0.0046449591497966,
+        0.0042191661429919,
+        0.0037915348363451,
+        0.0033622516236779,
+        0.0029315036836558,
+        0.0024994789888943,
+        0.0020663664924131,
+        0.0016323569986067,
+        0.0011976474864367,
+        0.0007624720924706,
+        0.0003276086705538
+    ])
+)
