Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[mypyc] Inline math literals #15324

Merged
merged 3 commits into from
Jun 2, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions mypyc/codegen/emitfunc.py
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,8 @@ def reg(self, reg: Value) -> str:
return "INFINITY"
elif r == "-inf":
return "-INFINITY"
elif r == "nan":
return "NAN"
return r
else:
return self.emitter.reg(reg)
Expand Down
2 changes: 2 additions & 0 deletions mypyc/codegen/literals.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@ def float_to_c(x: float) -> str:
return "INFINITY"
elif s == "-inf":
return "-INFINITY"
elif s == "nan":
return "NAN"
return s


Expand Down
3 changes: 3 additions & 0 deletions mypyc/irbuild/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,9 @@ def load_bytes_from_str_literal(self, value: str) -> Value:
def load_int(self, value: int) -> Value:
return self.builder.load_int(value)

def load_float(self, value: float) -> Value:
return self.builder.load_float(value)

def unary_op(self, lreg: Value, expr_op: str, line: int) -> Value:
return self.builder.unary_op(lreg, expr_op, line)

Expand Down
24 changes: 24 additions & 0 deletions mypyc/irbuild/expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from __future__ import annotations

import math
from typing import Callable, Sequence

from mypy.nodes import (
Expand Down Expand Up @@ -128,6 +129,10 @@ def transform_name_expr(builder: IRBuilder, expr: NameExpr) -> Value:
if fullname == "builtins.False":
return builder.false()

math_literal = transform_math_literal(builder, fullname)
if math_literal is not None:
return math_literal

if isinstance(expr.node, Var) and expr.node.is_final:
value = builder.emit_load_final(
expr.node,
Expand Down Expand Up @@ -192,6 +197,10 @@ def transform_member_expr(builder: IRBuilder, expr: MemberExpr) -> Value:
if value is not None:
return value

math_literal = transform_math_literal(builder, expr.fullname)
if math_literal is not None:
return math_literal

if isinstance(expr.node, MypyFile) and expr.node.fullname in builder.imports:
return builder.load_module(expr.node.fullname)

Expand Down Expand Up @@ -1043,3 +1052,18 @@ def transform_assignment_expr(builder: IRBuilder, o: AssignmentExpr) -> Value:
target = builder.get_assignment_target(o.target)
builder.assign(target, value, o.line)
return value


def transform_math_literal(builder: IRBuilder, fullname: str) -> Value | None:
if fullname == "math.e":
return builder.load_float(math.e)
if fullname == "math.pi":
return builder.load_float(math.pi)
if fullname == "math.inf":
return builder.load_float(math.inf)
if fullname == "math.nan":
return builder.load_float(math.nan)
if fullname == "math.tau":
return builder.load_float(math.tau)
dosisod marked this conversation as resolved.
Show resolved Hide resolved

return None
18 changes: 18 additions & 0 deletions mypyc/test-data/run-math.test
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from typing import Any, Callable
from typing_extensions import Final
import math
from math import pi, e, tau, inf, nan
from testutil import assertRaises, float_vals, assertDomainError, assertMathRangeError

pymath: Any = math
Expand Down Expand Up @@ -86,3 +87,20 @@ def test_isinf() -> None:
def test_isnan() -> None:
for x in float_vals:
assert repr(math.isnan(x)) == repr(pymath.isnan(x))


def test_pi_is_inlined_correctly() -> None:
assert math.pi == pi == 3.141592653589793
dosisod marked this conversation as resolved.
Show resolved Hide resolved

def test_e_is_inlined_correctly() -> None:
assert math.e == e == 2.718281828459045

def test_tau_is_inlined_correctly() -> None:
assert math.tau == tau == 6.283185307179586

def test_inf_is_inlined_correctly() -> None:
assert math.inf == inf == float("inf")

def test_nan_is_inlined_correctly() -> None:
assert math.isnan(math.nan)
assert math.isnan(nan)