def best_match(func, argtypes, constraints=None): """ Find a best match in for overloaded function `func` given `argtypes`. Parameters ---------- func: Dispatcher Overloaded Blaze function argtypes: [Mono] List of input argument types constraints: [(TypeVar, Mono)] Optional set of constraints, see unification.py Returns ------- Overloaded function as an `Overload` instance. """ from blaze.datashape import coerce overloads = func.overloads # ------------------------------------------------- # Find candidates candidates = find_matches(overloads, argtypes, constraints or []) # ------------------------------------------------- # Weigh candidates matches = defaultdict(list) for match in candidates: params = match.resolved_sig.parameters[:-1] try: weight = sum([coerce(a, p) for a, p in zip(argtypes, params)]) except error.CoercionError: pass else: matches[weight].append(match) if not matches: raise error.OverloadError( "No overload for function %s matches for argtypes (%s)" % ( func, ", ".join(map(str, argtypes)))) # ------------------------------------------------- # Return candidate with minimum weight candidates = matches[min(matches)] if len(candidates) > 1: raise error.OverloadError( "Ambiguous overload for function %s with inputs (%s): \n%s" % ( func, ", ".join(map(str, argtypes)), "\n".join(" %s" % (sig,) for _, sig, _ in candidates))) else: return candidates[0]
def test_coerce_src_ellipsis(self): a, b, c = dshapes('10, ..., float32', 'X, Y, float64', 'X, ..., float64') self.assertGreater(coerce(a, b), coerce(a, c))
def test_coerce_traits(self): a, b, c = dshapes('10, 10, float32', '10, X, A : floating', '10, X, float32') self.assertGreater(coerce(a, b), coerce(a, c))
def test_coerce_broadcasting3(self): a, b, c = dshapes('10, 10, float32', '10, 10, 10, float32', '1, 10, 10, float32') self.assertGreater(coerce(a, b), coerce(a, c))
def test_coerce_constrained_typevars(self): a, b, c = dshapes('10, 10, float32', 'X, Y, float64', 'X, X, float64') self.assertGreater(coerce(a, b), coerce(a, c))
def test_coercion_transitivity(self): a, b, c = dshapes('int8', 'complex128', 'float64') self.assertGreater(coerce(a, b), coerce(a, c))
def test_coerce_numeric(self): a, b = dshapes('float32', 'float64') self.assertEqual(coerce(a, b), 1)
def test_coerce_ctype(self): a, b = dshapes('float32', 'float32') self.assertEqual(coerce(a, b), 0)
def test_coercion(self): self.assertEqual(coerce(t1, t2), 0) self.assertGreater(coerce(t3, t2), 0) self.assertEqual(coerce(rt1, rt2), 0)
def test_coerce_src_ellipsis(self): a, b, c = dshapes("10, ..., float32", "X, Y, float64", "X, ..., float64") self.assertGreater(coerce(a, b), coerce(a, c))
def test_coerce_broadcasting2(self): a, b, c = dshapes("10, 10, float32", "1, 10, 10, float32", "10, 10, float32") self.assertGreater(coerce(a, b), coerce(a, c))
def test_coerce_typevars(self): a, b, c = dshapes("10, 11, float32", "X, Y, float64", "10, Y, float64") self.assertGreater(coerce(a, b), coerce(a, c))
def test_coercion_transitivity(self): a, b, c = dshapes("int8", "complex128", "float64") self.assertGreater(coerce(a, b), coerce(a, c))
def test_coerce_numeric(self): a, b = dshapes("float32", "float64") self.assertEqual(coerce(a, b), 1)
def test_coerce_ctype(self): a, b = dshapes("float32", "float32") self.assertEqual(coerce(a, b), 0)