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 coercion_cost overloads = func.overloads # ------------------------------------------------- # Find candidates candidates = find_matches(overloads, argtypes, constraints or []) # ------------------------------------------------- # Weigh candidates matches = defaultdict(list) for match in candidates: in_signature = T.Function(*argtypes + [T.TypeVar('R')]) signature = match.sig try: weight = coercion_cost(in_signature, signature) 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" % (overload.resolved_sig,) for overload in candidates))) else: return candidates[0]
def test_coercion(self): self.assertEqual(coercion_cost(t1, t2), 0) self.assertGreater(coercion_cost(t3, t2), 0) self.assertEqual(coercion_cost(rt1, rt2), 0)
def test_coercion(self): self.assertGreater(coercion_cost(t3, t2), 0)
def test_coerce_src_ellipsis(self): a, b, c = dshapes('10, ..., float32', 'X, Y, float64', 'X, ..., float64') self.assertGreater(coercion_cost(a, b), coercion_cost(a, c))
def test_coerce_traits(self): a, b, c = dshapes('10, 10, float32', '10, X, A : floating', '10, X, float32') self.assertGreater(coercion_cost(a, b), coercion_cost(a, c))
def test_coerce_broadcasting3(self): a, b, c = dshapes('10, 10, float32', '10, 10, 10, float32', '1, 10, 10, float32') self.assertGreater(coercion_cost(a, b), coercion_cost(a, c))
def test_coerce_constrained_typevars(self): a, b, c = dshapes('10, 10, float32', 'X, Y, float64', 'X, X, float64') self.assertGreater(coercion_cost(a, b), coercion_cost(a, c))
def test_coercion_transitivity(self): a, b, c = dshapes('int8', 'complex128', 'float64') self.assertGreater(coercion_cost(a, b), coercion_cost(a, c))
def test_coerce_numeric(self): a, b = dshapes('float32', 'float64') self.assertGreater(coercion_cost(a, b), 0)
def test_coerce_ctype(self): a, b, c = dshapes('float32', 'float32', 'float64') self.assertLess(coercion_cost(a, b), coercion_cost(a, c))
def test_coerce_numeric(self): a, b = dshapes('float32', 'float64') self.assertEqual(coercion_cost(a, b), 1)
def test_coerce_ctype(self): a, b = dshapes('float32', 'float32') self.assertEqual(coercion_cost(a, b), 0)