diff --git a/src/Fable.Transforms/Python/Fable2Python.Transforms.fs b/src/Fable.Transforms/Python/Fable2Python.Transforms.fs index aac00e39b3..3ae486e5ee 100644 --- a/src/Fable.Transforms/Python/Fable2Python.Transforms.fs +++ b/src/Fable.Transforms/Python/Fable2Python.Transforms.fs @@ -516,10 +516,6 @@ let transformValue (com: IPythonCompiler) (ctx: Context) r value : Expression * | Fable.NumberValue.Float64 x when x = -infinity -> Expression.unaryOp (UnaryMinus, com.GetImportExpr(ctx, "math", "inf")), [] | Fable.NumberValue.Float64 x when Double.IsNaN(x) -> com.GetImportExpr(ctx, "math", "nan"), [] - | Fable.NumberValue.Float32 x when Single.IsNaN(x) -> - libCall com ctx r "core" "float32" [ Expression.stringConstant "nan" ], [] - | Fable.NumberValue.Float16 x when Single.IsNaN(x) -> - libCall com ctx r "core" "float32" [ Expression.stringConstant "nan" ], [] | Fable.NumberValue.Float16 x -> makeFloat com ctx r value.Type "float32" (float x) | Fable.NumberValue.Float32 x -> makeFloat com ctx r value.Type "float32" (float x) | Fable.NumberValue.Float64 x -> Expression.floatConstant (float x, ?loc = r), [] diff --git a/src/Fable.Transforms/Python/Fable2Python.Util.fs b/src/Fable.Transforms/Python/Fable2Python.Util.fs index d71adf1a28..51a854e994 100644 --- a/src/Fable.Transforms/Python/Fable2Python.Util.fs +++ b/src/Fable.Transforms/Python/Fable2Python.Util.fs @@ -1037,10 +1037,16 @@ module Util = | _, (:? uint64 as i) when i = 64UL -> makeFieldGet cons "SIXTY_FOUR" | _ -> Expression.call (cons, [ value ], ?loc = r), [] - let makeFloat (com: IPythonCompiler) (ctx: Context) r _t floatName x = + let makeFloat (com: IPythonCompiler) (ctx: Context) r _t floatName (x: float) = let cons = libValue com ctx "core" floatName - let value = Expression.floatConstant (x, ?loc = r) - Expression.call (cons, [ value ], ?loc = r), [] + + match x with + | x when Double.IsPositiveInfinity x -> makeFieldGet cons "infinity" + | x when Double.IsNegativeInfinity x -> makeFieldGet cons "negative_infinity" + | x when Double.IsNaN x -> makeFieldGet cons "nan" + | _ -> + let value = Expression.floatConstant (x, ?loc = r) + Expression.call (cons, [ value ], ?loc = r), [] // --------------------------------------------------------------------------- // Int32 normalization diff --git a/src/Fable.Transforms/Python/PythonPrinter.fs b/src/Fable.Transforms/Python/PythonPrinter.fs index aa89f08ed4..234c149811 100644 --- a/src/Fable.Transforms/Python/PythonPrinter.fs +++ b/src/Fable.Transforms/Python/PythonPrinter.fs @@ -792,6 +792,14 @@ module PrinterExtensions = printer.Print("\"") printer.Print(Naming.escapeString (fun _ -> false) value) printer.Print("\"") + | Constant(value = FloatLiteral value) when Double.IsNaN value || Double.IsInfinity value -> + // .NET prints these as `Infinity`, `-Infinity` and `NaN`, which are not Python names + if Double.IsNaN value then + printer.Print("float(\"nan\")") + elif Double.IsPositiveInfinity value then + printer.Print("float(\"inf\")") + else + printer.Print("float(\"-inf\")") | Constant(value = FloatLiteral value) -> let value = string value printer.Print(value) diff --git a/src/fable-library-py/fable_library/core/floats.pyi b/src/fable-library-py/fable_library/core/floats.pyi index 0ff33160ad..be85e63968 100644 --- a/src/fable-library-py/fable_library/core/floats.pyi +++ b/src/fable-library-py/fable_library/core/floats.pyi @@ -110,10 +110,10 @@ def log10(x: float) -> float: ... def log2(x: float) -> float: ... def degrees(x: float) -> float: ... def radians(x: float) -> float: ... -def is_nan(x: float) -> bool: ... -def is_infinity(x: float) -> bool: ... -def is_positive_infinity(x: float) -> bool: ... -def is_negative_infinity(x: float) -> bool: ... +def is_nan(x: SupportsFloat) -> bool: ... +def is_infinity(x: SupportsFloat) -> bool: ... +def is_positive_infinity(x: SupportsFloat) -> bool: ... +def is_negative_infinity(x: SupportsFloat) -> bool: ... def floor(x: float) -> float: ... def ceil(x: float) -> float: ... def pow(x: float, y: float | FloatNumeric) -> float: ... diff --git a/tests/Python/TestArithmetic.fs b/tests/Python/TestArithmetic.fs index 2cc90d4e6c..1bd98a9604 100644 --- a/tests/Python/TestArithmetic.fs +++ b/tests/Python/TestArithmetic.fs @@ -17,6 +17,10 @@ let notALiteral = 5 let checkTo3dp (expected: float) actual = floor (actual * 1000.) |> equal expected +let moduleSinglePositiveInfinity = Single.PositiveInfinity +let moduleSingleNegativeInfinity = Single.NegativeInfinity +let moduleSingleNaN = Single.NaN + [] let ``test Adding floats works`` () = 3.141 + 2.85 |> equal 5.991 @@ -750,6 +754,33 @@ let ``test sqrt matches .NET core implementation`` () = // let result = Single.Parse("10.5", culture) // float result |> equal 10.5 +[] +let ``test Single special values work`` () = + Single.IsPositiveInfinity Single.PositiveInfinity |> equal true + Single.IsNegativeInfinity Single.NegativeInfinity |> equal true + Single.IsInfinity Single.PositiveInfinity |> equal true + Single.IsInfinity Single.NegativeInfinity |> equal true + Single.IsNaN Single.NaN |> equal true + Single.PositiveInfinity > 0.0f |> equal true + Single.NegativeInfinity < 0.0f |> equal true + Single.PositiveInfinity |> equal infinityf + Single.NegativeInfinity |> equal -infinityf + Single.IsNaN nanf |> equal true + +[] +let ``test Single special values work as module bindings`` () = + Single.IsPositiveInfinity moduleSinglePositiveInfinity |> equal true + Single.IsNegativeInfinity moduleSingleNegativeInfinity |> equal true + Single.IsNaN moduleSingleNaN |> equal true + +[] +let ``test Double special values work`` () = + Double.IsPositiveInfinity Double.PositiveInfinity |> equal true + Double.IsNegativeInfinity Double.NegativeInfinity |> equal true + Double.IsNaN Double.NaN |> equal true + Double.PositiveInfinity |> equal infinity + Double.NegativeInfinity |> equal -infinity + [] let ``test acos works`` () = acos 0.25 |> checkTo3dp 1318.