compiler: Implement abs() for scalars

GitHub: Fixes #1303.
This commit is contained in:
David Nadlinger 2019-04-13 00:43:45 +01:00 committed by Sébastien Bourdeauducq
parent 25e7e0c177
commit cdaf554736
7 changed files with 52 additions and 0 deletions

View File

@ -181,6 +181,9 @@ def fn_len():
def fn_round(): def fn_round():
return types.TBuiltinFunction("round") return types.TBuiltinFunction("round")
def fn_abs():
return types.TBuiltinFunction("abs")
def fn_min(): def fn_min():
return types.TBuiltinFunction("min") return types.TBuiltinFunction("min")

View File

@ -29,6 +29,7 @@ def globals():
# Built-in Python functions # Built-in Python functions
"len": builtins.fn_len(), "len": builtins.fn_len(),
"round": builtins.fn_round(), "round": builtins.fn_round(),
"abs": builtins.fn_abs(),
"min": builtins.fn_min(), "min": builtins.fn_min(),
"max": builtins.fn_max(), "max": builtins.fn_max(),
"print": builtins.fn_print(), "print": builtins.fn_print(),

View File

@ -1700,6 +1700,16 @@ class ARTIQIRGenerator(algorithm.Visitor):
return self.append(ir.Builtin("round", [arg], node.type)) return self.append(ir.Builtin("round", [arg], node.type))
else: else:
assert False assert False
elif types.is_builtin(typ, "abs"):
if len(node.args) == 1 and len(node.keywords) == 0:
arg = self.visit(node.args[0])
neg = self.append(
ir.Arith(ast.Sub(loc=None), ir.Constant(0, arg.type), arg))
cond = self.append(
ir.Compare(ast.Lt(loc=None), arg, ir.Constant(0, arg.type)))
return self.append(ir.Select(cond, neg, arg))
else:
assert False
elif types.is_builtin(typ, "min"): elif types.is_builtin(typ, "min"):
if len(node.args) == 2 and len(node.keywords) == 0: if len(node.args) == 2 and len(node.keywords) == 0:
arg0, arg1 = map(self.visit, node.args) arg0, arg1 = map(self.visit, node.args)

View File

@ -811,6 +811,28 @@ class Inferencer(algorithm.Visitor):
arg.loc, None) arg.loc, None)
else: else:
diagnose(valid_forms()) diagnose(valid_forms())
elif types.is_builtin(typ, "abs"):
fn = typ.name
valid_forms = lambda: [
valid_form("abs(x:numpy.int?) -> numpy.int?"),
valid_form("abs(x:float) -> float")
]
if len(node.args) == 1 and len(node.keywords) == 0:
(arg,) = node.args
if builtins.is_int(arg.type) or builtins.is_float(arg.type):
self._unify(arg.type, node.type,
arg.loc, node.loc)
elif types.is_var(arg.type):
pass # undetermined yet
else:
diag = diagnostic.Diagnostic("error",
"the arguments of abs() must be of a numeric type", {},
node.func.loc)
self.engine.process(diag)
else:
diagnose(valid_forms())
elif types.is_builtin(typ, "min") or types.is_builtin(typ, "max"): elif types.is_builtin(typ, "min") or types.is_builtin(typ, "max"):
fn = typ.name fn = typ.name

View File

@ -30,3 +30,9 @@ len([])
# CHECK-L: round:<function round>(1.0:float):numpy.int? # CHECK-L: round:<function round>(1.0:float):numpy.int?
round(1.0) round(1.0)
# CHECK-L: abs:<function abs>(1:numpy.int?):numpy.int?
abs(1)
# CHECK-L: abs:<function abs>(1.0:float):float
abs(1.0)

View File

@ -10,5 +10,8 @@ list(1)
# CHECK-L: ${LINE:+1}: error: the arguments of min() must be of a numeric type # CHECK-L: ${LINE:+1}: error: the arguments of min() must be of a numeric type
min([1], [1]) min([1], [1])
# CHECK-L: ${LINE:+1}: error: the arguments of abs() must be of a numeric type
abs([1.0])
# CHECK-L: ${LINE:+1}: error: strings currently cannot be constructed # CHECK-L: ${LINE:+1}: error: strings currently cannot be constructed
str(1) str(1)

View File

@ -0,0 +1,7 @@
# RUN: %python -m artiq.compiler.testbench.jit %s
# RUN: %python %s
assert abs(1234) == 1234
assert abs(-1234) == 1234
assert abs(1234.0) == 1234.0
assert abs(-1234.0) == 1234