We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Feature Request: Add support for vectorizing a jitted function
Currently it throws an _"unsupported callable"_ TypeError

``` python
In [151]: type(func)
Out[151]: numba.targets.registry.CPUDispatcher

In [152]: f = numba.vectorize(func.signatures, target='cpu')(func)
Traceback (most recent call last):

  File "<ipython-input-152-79c4e42b865b>", line 1, in <module>
    f = numba.vectorize(func.signatures, target='cpu')(func)

  File "C:\Python\lib\site-packages\numba\npyufunc\decorators.py", line 107, in wrap
    vec = Vectorize(func, **kws)

  File "C:\Python\lib\site-packages\numba\npyufunc\decorators.py", line 33, in __new__
    return imp(func, identity, kws)

  File "C:\Python\lib\site-packages\numba\npyufunc\dufunc.py", line 80, in __init__
    super(DUFunc, self).__init__(dispatcher, **kws)

  File "C:\Python\lib\inspect.py", line 1043, in getargspec
    getfullargspec(func)

  File "C:\Python\lib\inspect.py", line 1095, in getfullargspec
    raise TypeError('unsupported callable') from ex

TypeError: unsupported callable
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `numba/npyufunc/dufunc.py`
Content:
```
1 from __future__ import absolute_import, print_function, division
2 
3 import numpy as np
4 
5 from .. import jit, typeof, utils, types, numpy_support, sigutils
6 from ..typing import npydecl
7 from ..typing.templates import AbstractTemplate, signature
8 from . import _internal, ufuncbuilder
9 
10 
11 def make_dufunc_kernel(_dufunc):
12     from ..targets import npyimpl
13 
14     class DUFuncKernel(npyimpl._Kernel):
15         """
16         npyimpl._Kernel subclass responsible for lowering a DUFunc kernel
17         (element-wise function) inside a broadcast loop (which is
18         generated by npyimpl.numpy_ufunc_kernel()).
19         """
20         dufunc = _dufunc
21 
22         def __init__(self, context, builder, outer_sig):
23             super(DUFuncKernel, self).__init__(context, builder, outer_sig)
24             self.inner_sig, self.cres = self.dufunc.find_ewise_function(
25                 outer_sig.args)
26 
27         def generate(self, *args):
28             isig = self.inner_sig
29             osig = self.outer_sig
30             cast_args = [self.cast(val, inty, outty)
31                          for val, inty, outty in zip(args, osig.args, isig.args)]
32             if self.cres.objectmode:
33                 func_type = self.context.call_conv.get_function_type(
34                     types.pyobject, [types.pyobject] * len(isig.args))
35             else:
36                 func_type = self.context.call_conv.get_function_type(
37                     isig.return_type, isig.args)
38             module = self.builder.block.function.module
39             entry_point = module.get_or_insert_function(
40                 func_type, name=self.cres.fndesc.llvm_func_name)
41             entry_point.attributes.add("alwaysinline")
42             _, res = self.context.call_conv.call_function(
43                 self.builder, entry_point, isig.return_type, isig.args, cast_args)
44             return self.cast(res, isig.return_type, osig.return_type)
45 
46     DUFuncKernel.__name__ += _dufunc.ufunc.__name__
47     return DUFuncKernel
48 
49 
50 class DUFuncLowerer(object):
51     '''Callable class responsible for lowering calls to a specific DUFunc.
52     '''
53     def __init__(self, dufunc):
54         self.kernel = make_dufunc_kernel(dufunc)
55         self.libs = []
56 
57     def __call__(self, context, builder, sig, args):
58         from ..targets import npyimpl
59         explicit_output = len(args) > self.kernel.dufunc.ufunc.nin
60         return npyimpl.numpy_ufunc_kernel(context, builder, sig, args,
61                                           self.kernel,
62                                           explicit_output=explicit_output)
63 
64 
65 class DUFunc(_internal._DUFunc):
66     """
67     Dynamic universal function (DUFunc) intended to act like a normal
68     Numpy ufunc, but capable of call-time (just-in-time) compilation
69     of fast loops specialized to inputs.
70     """
71     # NOTE: __base_kwargs must be kept in synch with the kwlist in
72     # _internal.c:dufunc_init()
73     __base_kwargs = set(('identity', '_keepalive', 'nin', 'nout'))
74 
75     def __init__(self, py_func, identity=None, targetoptions={}):
76         self.targetoptions = targetoptions.copy()
77         kws = {}
78         kws['identity'] = ufuncbuilder.parse_identity(identity)
79         dispatcher = jit(target='npyufunc')(py_func)
80         super(DUFunc, self).__init__(dispatcher, **kws)
81         # Loop over a copy of the keys instead of the keys themselves,
82         # since we're changing the dictionary while looping.
83         self._install_type()
84         self._lower_me = DUFuncLowerer(self)
85         self._install_cg()
86         self.__name__ = py_func.__name__
87         self.__doc__ = py_func.__doc__
88 
89     def build_ufunc(self):
90         """
91         For compatibility with the various *UFuncBuilder classes.
92         """
93         return self
94 
95     @property
96     def nin(self):
97         return self.ufunc.nin
98 
99     @property
100     def nout(self):
101         return self.ufunc.nout
102 
103     @property
104     def nargs(self):
105         return self.ufunc.nargs
106 
107     @property
108     def ntypes(self):
109         return self.ufunc.ntypes
110 
111     @property
112     def types(self):
113         return self.ufunc.types
114 
115     @property
116     def identity(self):
117         return self.ufunc.identity
118 
119     def disable_compile(self):
120         """
121         Disable the compilation of new signatures at call time.
122         """
123         # If disabling compilation then there must be at least one signature
124         assert len(self._dispatcher.overloads) > 0
125         self._frozen = True
126 
127     def add(self, sig):
128         """
129         Compile the DUFunc for the given signature.
130         """
131         args, return_type = sigutils.normalize_signature(sig)
132         return self._compile_for_argtys(args, return_type)
133 
134     def _compile_for_args(self, *args, **kws):
135         nin = self.ufunc.nin
136         if kws:
137             if 'out' in kws:
138                 out = kws.pop('out')
139                 args += (out,)
140             if kws:
141                 raise TypeError("unexpected keyword arguments to ufunc: %s"
142                                 % ", ".join(repr(k) for k in sorted(kws)))
143 
144         args_len = len(args)
145         assert (args_len == nin) or (args_len == nin + self.ufunc.nout)
146         assert not kws
147         argtys = []
148         # To avoid a mismatch in how Numba types values as opposed to
149         # Numpy, we need to first check for scalars.  For example, on
150         # 64-bit systems, numba.typeof(3) => int32, but
151         # np.array(3).dtype => int64.
152         for arg in args[:nin]:
153             if numpy_support.is_arrayscalar(arg):
154                 argtys.append(numpy_support.map_arrayscalar_type(arg))
155             else:
156                 argty = typeof(arg)
157                 if isinstance(argty, types.Array):
158                     argty = argty.dtype
159                 argtys.append(argty)
160         return self._compile_for_argtys(tuple(argtys))
161 
162     def _compile_for_argtys(self, argtys, return_type=None):
163         """
164         Given a tuple of argument types (these should be the array
165         dtypes, and not the array types themselves), compile the
166         element-wise function for those inputs, generate a UFunc loop
167         wrapper, and register the loop with the Numpy ufunc object for
168         this DUFunc.
169         """
170         if self._frozen:
171             raise RuntimeError("compilation disabled for %s" % (self,))
172         assert isinstance(argtys, tuple)
173         if return_type is None:
174             sig = argtys
175         else:
176             sig = return_type(*argtys)
177         cres, argtys, return_type = ufuncbuilder._compile_element_wise_function(
178             self._dispatcher, self.targetoptions, sig)
179         actual_sig = ufuncbuilder._finalize_ufunc_signature(
180             cres, argtys, return_type)
181         dtypenums, ptr, env = ufuncbuilder._build_element_wise_ufunc_wrapper(
182             cres, actual_sig)
183         self._add_loop(utils.longint(ptr), dtypenums)
184         self._keepalive.append((ptr, cres.library, env))
185         self._lower_me.libs.append(cres.library)
186         return cres
187 
188     def _install_type(self, typingctx=None):
189         """Constructs and installs a typing class for a DUFunc object in the
190         input typing context.  If no typing context is given, then
191         _install_type() installs into the typing context of the
192         dispatcher object (should be same default context used by
193         jit() and njit()).
194         """
195         if typingctx is None:
196             typingctx = self._dispatcher.targetdescr.typing_context
197         _ty_cls = type('DUFuncTyping_' + self.ufunc.__name__,
198                        (AbstractTemplate,),
199                        dict(key=self, generic=self._type_me))
200         typingctx.insert_user_function(self, _ty_cls)
201 
202     def find_ewise_function(self, ewise_types):
203         """
204         Given a tuple of element-wise argument types, find a matching
205         signature in the dispatcher.
206 
207         Return a 2-tuple containing the matching signature, and
208         compilation result.  Will return two None's if no matching
209         signature was found.
210         """
211         if self._frozen:
212             # If we cannot compile, coerce to the best matching loop
213             loop = numpy_support.ufunc_find_matching_loop(self, ewise_types)
214             if loop is None:
215                 return None, None
216             ewise_types = tuple(loop.inputs + loop.outputs)[:len(ewise_types)]
217         for sig, cres in self._dispatcher.overloads.items():
218             if sig.args == ewise_types:
219                 return sig, cres
220         return None, None
221 
222     def _type_me(self, argtys, kwtys):
223         """
224         Implement AbstractTemplate.generic() for the typing class
225         built by DUFunc._install_type().
226 
227         Return the call-site signature after either validating the
228         element-wise signature or compiling for it.
229         """
230         assert not kwtys
231         ufunc = self.ufunc
232         _handle_inputs_result = npydecl.Numpy_rules_ufunc._handle_inputs(
233             ufunc, argtys, kwtys)
234         base_types, explicit_outputs, ndims, layout = _handle_inputs_result
235         explicit_output_count = len(explicit_outputs)
236         if explicit_output_count > 0:
237             ewise_types = tuple(base_types[:-len(explicit_outputs)])
238         else:
239             ewise_types = tuple(base_types)
240         sig, cres = self.find_ewise_function(ewise_types)
241         if sig is None:
242             # Matching element-wise signature was not found; must
243             # compile.
244             if self._frozen:
245                 raise TypeError("cannot call %s with types %s"
246                                 % (self, argtys))
247             self._compile_for_argtys(ewise_types)
248             sig, cres = self.find_ewise_function(ewise_types)
249             assert sig is not None
250         if explicit_output_count > 0:
251             outtys = list(explicit_outputs)
252         elif ufunc.nout == 1:
253             if ndims > 0:
254                 outtys = [types.Array(sig.return_type, ndims, layout)]
255             else:
256                 outtys = [sig.return_type]
257         else:
258             raise NotImplementedError("typing gufuncs (nout > 1)")
259         outtys.extend(argtys)
260         return signature(*outtys)
261 
262     def _install_cg(self, targetctx=None):
263         """
264         Install an implementation function for a DUFunc object in the
265         given target context.  If no target context is given, then
266         _install_cg() installs into the target context of the
267         dispatcher object (should be same default context used by
268         jit() and njit()).
269         """
270         if targetctx is None:
271             targetctx = self._dispatcher.targetdescr.target_context
272         _any = types.Any
273         _arr = types.Array
274         # Either all outputs are explicit or none of them are
275         sig0 = (_any,) * self.ufunc.nin + (_arr,) * self.ufunc.nout
276         sig1 = (_any,) * self.ufunc.nin
277         targetctx.insert_func_defn(
278             [(self._lower_me, self, sig) for sig in (sig0, sig1)])
279
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/numba/npyufunc/dufunc.py b/numba/npyufunc/dufunc.py
--- a/numba/npyufunc/dufunc.py
+++ b/numba/npyufunc/dufunc.py
@@ -6,6 +6,7 @@
 from ..typing import npydecl
 from ..typing.templates import AbstractTemplate, signature
 from . import _internal, ufuncbuilder
+from ..dispatcher import Dispatcher
 
 
 def make_dufunc_kernel(_dufunc):
@@ -73,6 +74,8 @@
     __base_kwargs = set(('identity', '_keepalive', 'nin', 'nout'))
 
     def __init__(self, py_func, identity=None, targetoptions={}):
+        if isinstance(py_func, Dispatcher):
+            py_func = py_func.py_func
         self.targetoptions = targetoptions.copy()
         kws = {}
         kws['identity'] = ufuncbuilder.parse_identity(identity)

{"golden_diff": "diff --git a/numba/npyufunc/dufunc.py b/numba/npyufunc/dufunc.py\n--- a/numba/npyufunc/dufunc.py\n+++ b/numba/npyufunc/dufunc.py\n@@ -6,6 +6,7 @@\n from ..typing import npydecl\n from ..typing.templates import AbstractTemplate, signature\n from . import _internal, ufuncbuilder\n+from ..dispatcher import Dispatcher\n \n \n def make_dufunc_kernel(_dufunc):\n@@ -73,6 +74,8 @@\n     __base_kwargs = set(('identity', '_keepalive', 'nin', 'nout'))\n \n     def __init__(self, py_func, identity=None, targetoptions={}):\n+        if isinstance(py_func, Dispatcher):\n+            py_func = py_func.py_func\n         self.targetoptions = targetoptions.copy()\n         kws = {}\n         kws['identity'] = ufuncbuilder.parse_identity(identity)\n", "issue": "Feature Request: Add support for vectorizing a jitted function\nCurrently it throws an _\"unsupported callable\"_ TypeError\n\n``` python\nIn [151]: type(func)\nOut[151]: numba.targets.registry.CPUDispatcher\n\nIn [152]: f = numba.vectorize(func.signatures, target='cpu')(func)\nTraceback (most recent call last):\n\n  File \"<ipython-input-152-79c4e42b865b>\", line 1, in <module>\n    f = numba.vectorize(func.signatures, target='cpu')(func)\n\n  File \"C:\\Python\\lib\\site-packages\\numba\\npyufunc\\decorators.py\", line 107, in wrap\n    vec = Vectorize(func, **kws)\n\n  File \"C:\\Python\\lib\\site-packages\\numba\\npyufunc\\decorators.py\", line 33, in __new__\n    return imp(func, identity, kws)\n\n  File \"C:\\Python\\lib\\site-packages\\numba\\npyufunc\\dufunc.py\", line 80, in __init__\n    super(DUFunc, self).__init__(dispatcher, **kws)\n\n  File \"C:\\Python\\lib\\inspect.py\", line 1043, in getargspec\n    getfullargspec(func)\n\n  File \"C:\\Python\\lib\\inspect.py\", line 1095, in getfullargspec\n    raise TypeError('unsupported callable') from ex\n\nTypeError: unsupported callable\n```\n\n", "before_files": [{"content": "from __future__ import absolute_import, print_function, division\n\nimport numpy as np\n\nfrom .. import jit, typeof, utils, types, numpy_support, sigutils\nfrom ..typing import npydecl\nfrom ..typing.templates import AbstractTemplate, signature\nfrom . import _internal, ufuncbuilder\n\n\ndef make_dufunc_kernel(_dufunc):\n    from ..targets import npyimpl\n\n    class DUFuncKernel(npyimpl._Kernel):\n        \"\"\"\n        npyimpl._Kernel subclass responsible for lowering a DUFunc kernel\n        (element-wise function) inside a broadcast loop (which is\n        generated by npyimpl.numpy_ufunc_kernel()).\n        \"\"\"\n        dufunc = _dufunc\n\n        def __init__(self, context, builder, outer_sig):\n            super(DUFuncKernel, self).__init__(context, builder, outer_sig)\n            self.inner_sig, self.cres = self.dufunc.find_ewise_function(\n                outer_sig.args)\n\n        def generate(self, *args):\n            isig = self.inner_sig\n            osig = self.outer_sig\n            cast_args = [self.cast(val, inty, outty)\n                         for val, inty, outty in zip(args, osig.args, isig.args)]\n            if self.cres.objectmode:\n                func_type = self.context.call_conv.get_function_type(\n                    types.pyobject, [types.pyobject] * len(isig.args))\n            else:\n                func_type = self.context.call_conv.get_function_type(\n                    isig.return_type, isig.args)\n            module = self.builder.block.function.module\n            entry_point = module.get_or_insert_function(\n                func_type, name=self.cres.fndesc.llvm_func_name)\n            entry_point.attributes.add(\"alwaysinline\")\n            _, res = self.context.call_conv.call_function(\n                self.builder, entry_point, isig.return_type, isig.args, cast_args)\n            return self.cast(res, isig.return_type, osig.return_type)\n\n    DUFuncKernel.__name__ += _dufunc.ufunc.__name__\n    return DUFuncKernel\n\n\nclass DUFuncLowerer(object):\n    '''Callable class responsible for lowering calls to a specific DUFunc.\n    '''\n    def __init__(self, dufunc):\n        self.kernel = make_dufunc_kernel(dufunc)\n        self.libs = []\n\n    def __call__(self, context, builder, sig, args):\n        from ..targets import npyimpl\n        explicit_output = len(args) > self.kernel.dufunc.ufunc.nin\n        return npyimpl.numpy_ufunc_kernel(context, builder, sig, args,\n                                          self.kernel,\n                                          explicit_output=explicit_output)\n\n\nclass DUFunc(_internal._DUFunc):\n    \"\"\"\n    Dynamic universal function (DUFunc) intended to act like a normal\n    Numpy ufunc, but capable of call-time (just-in-time) compilation\n    of fast loops specialized to inputs.\n    \"\"\"\n    # NOTE: __base_kwargs must be kept in synch with the kwlist in\n    # _internal.c:dufunc_init()\n    __base_kwargs = set(('identity', '_keepalive', 'nin', 'nout'))\n\n    def __init__(self, py_func, identity=None, targetoptions={}):\n        self.targetoptions = targetoptions.copy()\n        kws = {}\n        kws['identity'] = ufuncbuilder.parse_identity(identity)\n        dispatcher = jit(target='npyufunc')(py_func)\n        super(DUFunc, self).__init__(dispatcher, **kws)\n        # Loop over a copy of the keys instead of the keys themselves,\n        # since we're changing the dictionary while looping.\n        self._install_type()\n        self._lower_me = DUFuncLowerer(self)\n        self._install_cg()\n        self.__name__ = py_func.__name__\n        self.__doc__ = py_func.__doc__\n\n    def build_ufunc(self):\n        \"\"\"\n        For compatibility with the various *UFuncBuilder classes.\n        \"\"\"\n        return self\n\n    @property\n    def nin(self):\n        return self.ufunc.nin\n\n    @property\n    def nout(self):\n        return self.ufunc.nout\n\n    @property\n    def nargs(self):\n        return self.ufunc.nargs\n\n    @property\n    def ntypes(self):\n        return self.ufunc.ntypes\n\n    @property\n    def types(self):\n        return self.ufunc.types\n\n    @property\n    def identity(self):\n        return self.ufunc.identity\n\n    def disable_compile(self):\n        \"\"\"\n        Disable the compilation of new signatures at call time.\n        \"\"\"\n        # If disabling compilation then there must be at least one signature\n        assert len(self._dispatcher.overloads) > 0\n        self._frozen = True\n\n    def add(self, sig):\n        \"\"\"\n        Compile the DUFunc for the given signature.\n        \"\"\"\n        args, return_type = sigutils.normalize_signature(sig)\n        return self._compile_for_argtys(args, return_type)\n\n    def _compile_for_args(self, *args, **kws):\n        nin = self.ufunc.nin\n        if kws:\n            if 'out' in kws:\n                out = kws.pop('out')\n                args += (out,)\n            if kws:\n                raise TypeError(\"unexpected keyword arguments to ufunc: %s\"\n                                % \", \".join(repr(k) for k in sorted(kws)))\n\n        args_len = len(args)\n        assert (args_len == nin) or (args_len == nin + self.ufunc.nout)\n        assert not kws\n        argtys = []\n        # To avoid a mismatch in how Numba types values as opposed to\n        # Numpy, we need to first check for scalars.  For example, on\n        # 64-bit systems, numba.typeof(3) => int32, but\n        # np.array(3).dtype => int64.\n        for arg in args[:nin]:\n            if numpy_support.is_arrayscalar(arg):\n                argtys.append(numpy_support.map_arrayscalar_type(arg))\n            else:\n                argty = typeof(arg)\n                if isinstance(argty, types.Array):\n                    argty = argty.dtype\n                argtys.append(argty)\n        return self._compile_for_argtys(tuple(argtys))\n\n    def _compile_for_argtys(self, argtys, return_type=None):\n        \"\"\"\n        Given a tuple of argument types (these should be the array\n        dtypes, and not the array types themselves), compile the\n        element-wise function for those inputs, generate a UFunc loop\n        wrapper, and register the loop with the Numpy ufunc object for\n        this DUFunc.\n        \"\"\"\n        if self._frozen:\n            raise RuntimeError(\"compilation disabled for %s\" % (self,))\n        assert isinstance(argtys, tuple)\n        if return_type is None:\n            sig = argtys\n        else:\n            sig = return_type(*argtys)\n        cres, argtys, return_type = ufuncbuilder._compile_element_wise_function(\n            self._dispatcher, self.targetoptions, sig)\n        actual_sig = ufuncbuilder._finalize_ufunc_signature(\n            cres, argtys, return_type)\n        dtypenums, ptr, env = ufuncbuilder._build_element_wise_ufunc_wrapper(\n            cres, actual_sig)\n        self._add_loop(utils.longint(ptr), dtypenums)\n        self._keepalive.append((ptr, cres.library, env))\n        self._lower_me.libs.append(cres.library)\n        return cres\n\n    def _install_type(self, typingctx=None):\n        \"\"\"Constructs and installs a typing class for a DUFunc object in the\n        input typing context.  If no typing context is given, then\n        _install_type() installs into the typing context of the\n        dispatcher object (should be same default context used by\n        jit() and njit()).\n        \"\"\"\n        if typingctx is None:\n            typingctx = self._dispatcher.targetdescr.typing_context\n        _ty_cls = type('DUFuncTyping_' + self.ufunc.__name__,\n                       (AbstractTemplate,),\n                       dict(key=self, generic=self._type_me))\n        typingctx.insert_user_function(self, _ty_cls)\n\n    def find_ewise_function(self, ewise_types):\n        \"\"\"\n        Given a tuple of element-wise argument types, find a matching\n        signature in the dispatcher.\n\n        Return a 2-tuple containing the matching signature, and\n        compilation result.  Will return two None's if no matching\n        signature was found.\n        \"\"\"\n        if self._frozen:\n            # If we cannot compile, coerce to the best matching loop\n            loop = numpy_support.ufunc_find_matching_loop(self, ewise_types)\n            if loop is None:\n                return None, None\n            ewise_types = tuple(loop.inputs + loop.outputs)[:len(ewise_types)]\n        for sig, cres in self._dispatcher.overloads.items():\n            if sig.args == ewise_types:\n                return sig, cres\n        return None, None\n\n    def _type_me(self, argtys, kwtys):\n        \"\"\"\n        Implement AbstractTemplate.generic() for the typing class\n        built by DUFunc._install_type().\n\n        Return the call-site signature after either validating the\n        element-wise signature or compiling for it.\n        \"\"\"\n        assert not kwtys\n        ufunc = self.ufunc\n        _handle_inputs_result = npydecl.Numpy_rules_ufunc._handle_inputs(\n            ufunc, argtys, kwtys)\n        base_types, explicit_outputs, ndims, layout = _handle_inputs_result\n        explicit_output_count = len(explicit_outputs)\n        if explicit_output_count > 0:\n            ewise_types = tuple(base_types[:-len(explicit_outputs)])\n        else:\n            ewise_types = tuple(base_types)\n        sig, cres = self.find_ewise_function(ewise_types)\n        if sig is None:\n            # Matching element-wise signature was not found; must\n            # compile.\n            if self._frozen:\n                raise TypeError(\"cannot call %s with types %s\"\n                                % (self, argtys))\n            self._compile_for_argtys(ewise_types)\n            sig, cres = self.find_ewise_function(ewise_types)\n            assert sig is not None\n        if explicit_output_count > 0:\n            outtys = list(explicit_outputs)\n        elif ufunc.nout == 1:\n            if ndims > 0:\n                outtys = [types.Array(sig.return_type, ndims, layout)]\n            else:\n                outtys = [sig.return_type]\n        else:\n            raise NotImplementedError(\"typing gufuncs (nout > 1)\")\n        outtys.extend(argtys)\n        return signature(*outtys)\n\n    def _install_cg(self, targetctx=None):\n        \"\"\"\n        Install an implementation function for a DUFunc object in the\n        given target context.  If no target context is given, then\n        _install_cg() installs into the target context of the\n        dispatcher object (should be same default context used by\n        jit() and njit()).\n        \"\"\"\n        if targetctx is None:\n            targetctx = self._dispatcher.targetdescr.target_context\n        _any = types.Any\n        _arr = types.Array\n        # Either all outputs are explicit or none of them are\n        sig0 = (_any,) * self.ufunc.nin + (_arr,) * self.ufunc.nout\n        sig1 = (_any,) * self.ufunc.nin\n        targetctx.insert_func_defn(\n            [(self._lower_me, self, sig) for sig in (sig0, sig1)])\n", "path": "numba/npyufunc/dufunc.py"}], "after_files": [{"content": "from __future__ import absolute_import, print_function, division\n\nimport numpy as np\n\nfrom .. import jit, typeof, utils, types, numpy_support, sigutils\nfrom ..typing import npydecl\nfrom ..typing.templates import AbstractTemplate, signature\nfrom . import _internal, ufuncbuilder\nfrom ..dispatcher import Dispatcher\n\n\ndef make_dufunc_kernel(_dufunc):\n    from ..targets import npyimpl\n\n    class DUFuncKernel(npyimpl._Kernel):\n        \"\"\"\n        npyimpl._Kernel subclass responsible for lowering a DUFunc kernel\n        (element-wise function) inside a broadcast loop (which is\n        generated by npyimpl.numpy_ufunc_kernel()).\n        \"\"\"\n        dufunc = _dufunc\n\n        def __init__(self, context, builder, outer_sig):\n            super(DUFuncKernel, self).__init__(context, builder, outer_sig)\n            self.inner_sig, self.cres = self.dufunc.find_ewise_function(\n                outer_sig.args)\n\n        def generate(self, *args):\n            isig = self.inner_sig\n            osig = self.outer_sig\n            cast_args = [self.cast(val, inty, outty)\n                         for val, inty, outty in zip(args, osig.args, isig.args)]\n            if self.cres.objectmode:\n                func_type = self.context.call_conv.get_function_type(\n                    types.pyobject, [types.pyobject] * len(isig.args))\n            else:\n                func_type = self.context.call_conv.get_function_type(\n                    isig.return_type, isig.args)\n            module = self.builder.block.function.module\n            entry_point = module.get_or_insert_function(\n                func_type, name=self.cres.fndesc.llvm_func_name)\n            entry_point.attributes.add(\"alwaysinline\")\n            _, res = self.context.call_conv.call_function(\n                self.builder, entry_point, isig.return_type, isig.args, cast_args)\n            return self.cast(res, isig.return_type, osig.return_type)\n\n    DUFuncKernel.__name__ += _dufunc.ufunc.__name__\n    return DUFuncKernel\n\n\nclass DUFuncLowerer(object):\n    '''Callable class responsible for lowering calls to a specific DUFunc.\n    '''\n    def __init__(self, dufunc):\n        self.kernel = make_dufunc_kernel(dufunc)\n        self.libs = []\n\n    def __call__(self, context, builder, sig, args):\n        from ..targets import npyimpl\n        explicit_output = len(args) > self.kernel.dufunc.ufunc.nin\n        return npyimpl.numpy_ufunc_kernel(context, builder, sig, args,\n                                          self.kernel,\n                                          explicit_output=explicit_output)\n\n\nclass DUFunc(_internal._DUFunc):\n    \"\"\"\n    Dynamic universal function (DUFunc) intended to act like a normal\n    Numpy ufunc, but capable of call-time (just-in-time) compilation\n    of fast loops specialized to inputs.\n    \"\"\"\n    # NOTE: __base_kwargs must be kept in synch with the kwlist in\n    # _internal.c:dufunc_init()\n    __base_kwargs = set(('identity', '_keepalive', 'nin', 'nout'))\n\n    def __init__(self, py_func, identity=None, targetoptions={}):\n        if isinstance(py_func, Dispatcher):\n            py_func = py_func.py_func\n        self.targetoptions = targetoptions.copy()\n        kws = {}\n        kws['identity'] = ufuncbuilder.parse_identity(identity)\n        dispatcher = jit(target='npyufunc')(py_func)\n        super(DUFunc, self).__init__(dispatcher, **kws)\n        # Loop over a copy of the keys instead of the keys themselves,\n        # since we're changing the dictionary while looping.\n        self._install_type()\n        self._lower_me = DUFuncLowerer(self)\n        self._install_cg()\n        self.__name__ = py_func.__name__\n        self.__doc__ = py_func.__doc__\n\n    def build_ufunc(self):\n        \"\"\"\n        For compatibility with the various *UFuncBuilder classes.\n        \"\"\"\n        return self\n\n    @property\n    def nin(self):\n        return self.ufunc.nin\n\n    @property\n    def nout(self):\n        return self.ufunc.nout\n\n    @property\n    def nargs(self):\n        return self.ufunc.nargs\n\n    @property\n    def ntypes(self):\n        return self.ufunc.ntypes\n\n    @property\n    def types(self):\n        return self.ufunc.types\n\n    @property\n    def identity(self):\n        return self.ufunc.identity\n\n    def disable_compile(self):\n        \"\"\"\n        Disable the compilation of new signatures at call time.\n        \"\"\"\n        # If disabling compilation then there must be at least one signature\n        assert len(self._dispatcher.overloads) > 0\n        self._frozen = True\n\n    def add(self, sig):\n        \"\"\"\n        Compile the DUFunc for the given signature.\n        \"\"\"\n        args, return_type = sigutils.normalize_signature(sig)\n        return self._compile_for_argtys(args, return_type)\n\n    def _compile_for_args(self, *args, **kws):\n        nin = self.ufunc.nin\n        if kws:\n            if 'out' in kws:\n                out = kws.pop('out')\n                args += (out,)\n            if kws:\n                raise TypeError(\"unexpected keyword arguments to ufunc: %s\"\n                                % \", \".join(repr(k) for k in sorted(kws)))\n\n        args_len = len(args)\n        assert (args_len == nin) or (args_len == nin + self.ufunc.nout)\n        assert not kws\n        argtys = []\n        # To avoid a mismatch in how Numba types values as opposed to\n        # Numpy, we need to first check for scalars.  For example, on\n        # 64-bit systems, numba.typeof(3) => int32, but\n        # np.array(3).dtype => int64.\n        for arg in args[:nin]:\n            if numpy_support.is_arrayscalar(arg):\n                argtys.append(numpy_support.map_arrayscalar_type(arg))\n            else:\n                argty = typeof(arg)\n                if isinstance(argty, types.Array):\n                    argty = argty.dtype\n                argtys.append(argty)\n        return self._compile_for_argtys(tuple(argtys))\n\n    def _compile_for_argtys(self, argtys, return_type=None):\n        \"\"\"\n        Given a tuple of argument types (these should be the array\n        dtypes, and not the array types themselves), compile the\n        element-wise function for those inputs, generate a UFunc loop\n        wrapper, and register the loop with the Numpy ufunc object for\n        this DUFunc.\n        \"\"\"\n        if self._frozen:\n            raise RuntimeError(\"compilation disabled for %s\" % (self,))\n        assert isinstance(argtys, tuple)\n        if return_type is None:\n            sig = argtys\n        else:\n            sig = return_type(*argtys)\n        cres, argtys, return_type = ufuncbuilder._compile_element_wise_function(\n            self._dispatcher, self.targetoptions, sig)\n        actual_sig = ufuncbuilder._finalize_ufunc_signature(\n            cres, argtys, return_type)\n        dtypenums, ptr, env = ufuncbuilder._build_element_wise_ufunc_wrapper(\n            cres, actual_sig)\n        self._add_loop(utils.longint(ptr), dtypenums)\n        self._keepalive.append((ptr, cres.library, env))\n        self._lower_me.libs.append(cres.library)\n        return cres\n\n    def _install_type(self, typingctx=None):\n        \"\"\"Constructs and installs a typing class for a DUFunc object in the\n        input typing context.  If no typing context is given, then\n        _install_type() installs into the typing context of the\n        dispatcher object (should be same default context used by\n        jit() and njit()).\n        \"\"\"\n        if typingctx is None:\n            typingctx = self._dispatcher.targetdescr.typing_context\n        _ty_cls = type('DUFuncTyping_' + self.ufunc.__name__,\n                       (AbstractTemplate,),\n                       dict(key=self, generic=self._type_me))\n        typingctx.insert_user_function(self, _ty_cls)\n\n    def find_ewise_function(self, ewise_types):\n        \"\"\"\n        Given a tuple of element-wise argument types, find a matching\n        signature in the dispatcher.\n\n        Return a 2-tuple containing the matching signature, and\n        compilation result.  Will return two None's if no matching\n        signature was found.\n        \"\"\"\n        if self._frozen:\n            # If we cannot compile, coerce to the best matching loop\n            loop = numpy_support.ufunc_find_matching_loop(self, ewise_types)\n            if loop is None:\n                return None, None\n            ewise_types = tuple(loop.inputs + loop.outputs)[:len(ewise_types)]\n        for sig, cres in self._dispatcher.overloads.items():\n            if sig.args == ewise_types:\n                return sig, cres\n        return None, None\n\n    def _type_me(self, argtys, kwtys):\n        \"\"\"\n        Implement AbstractTemplate.generic() for the typing class\n        built by DUFunc._install_type().\n\n        Return the call-site signature after either validating the\n        element-wise signature or compiling for it.\n        \"\"\"\n        assert not kwtys\n        ufunc = self.ufunc\n        _handle_inputs_result = npydecl.Numpy_rules_ufunc._handle_inputs(\n            ufunc, argtys, kwtys)\n        base_types, explicit_outputs, ndims, layout = _handle_inputs_result\n        explicit_output_count = len(explicit_outputs)\n        if explicit_output_count > 0:\n            ewise_types = tuple(base_types[:-len(explicit_outputs)])\n        else:\n            ewise_types = tuple(base_types)\n        sig, cres = self.find_ewise_function(ewise_types)\n        if sig is None:\n            # Matching element-wise signature was not found; must\n            # compile.\n            if self._frozen:\n                raise TypeError(\"cannot call %s with types %s\"\n                                % (self, argtys))\n            self._compile_for_argtys(ewise_types)\n            sig, cres = self.find_ewise_function(ewise_types)\n            assert sig is not None\n        if explicit_output_count > 0:\n            outtys = list(explicit_outputs)\n        elif ufunc.nout == 1:\n            if ndims > 0:\n                outtys = [types.Array(sig.return_type, ndims, layout)]\n            else:\n                outtys = [sig.return_type]\n        else:\n            raise NotImplementedError(\"typing gufuncs (nout > 1)\")\n        outtys.extend(argtys)\n        return signature(*outtys)\n\n    def _install_cg(self, targetctx=None):\n        \"\"\"\n        Install an implementation function for a DUFunc object in the\n        given target context.  If no target context is given, then\n        _install_cg() installs into the target context of the\n        dispatcher object (should be same default context used by\n        jit() and njit()).\n        \"\"\"\n        if targetctx is None:\n            targetctx = self._dispatcher.targetdescr.target_context\n        _any = types.Any\n        _arr = types.Array\n        # Either all outputs are explicit or none of them are\n        sig0 = (_any,) * self.ufunc.nin + (_arr,) * self.ufunc.nout\n        sig1 = (_any,) * self.ufunc.nin\n        targetctx.insert_func_defn(\n            [(self._lower_me, self, sig) for sig in (sig0, sig1)])\n", "path": "numba/npyufunc/dufunc.py"}]}