From 06cbefe6546eb07398136c478c32c3cebc9d2982 Mon Sep 17 00:00:00 2001 From: sabiwara Date: Fri, 16 Feb 2024 05:42:41 +0900 Subject: [PATCH 1/6] Fix non-deterministic key-value tests --- lib/elixir/lib/map.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/elixir/lib/map.ex b/lib/elixir/lib/map.ex index 8082b401686..a9507dc60bc 100644 --- a/lib/elixir/lib/map.ex +++ b/lib/elixir/lib/map.ex @@ -147,7 +147,7 @@ defmodule Map do ## Examples - iex> Map.keys(%{a: 1, b: 2}) + Map.keys(%{a: 1, b: 2}) [:a, :b] """ @@ -161,7 +161,7 @@ defmodule Map do ## Examples - iex> Map.values(%{a: 1, b: 2}) + Map.values(%{a: 1, b: 2}) [1, 2] """ From fff947b14144195c681aa1f3ae8961e165fb3a25 Mon Sep 17 00:00:00 2001 From: sabiwara Date: Fri, 16 Feb 2024 06:16:53 +0900 Subject: [PATCH 2/6] Fix non-deterministic Enum tests --- lib/elixir/lib/enum.ex | 5 +---- lib/elixir/test/elixir/enum_test.exs | 8 ++++---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/lib/elixir/lib/enum.ex b/lib/elixir/lib/enum.ex index 2ce7c7a4652..e81c961831a 100644 --- a/lib/elixir/lib/enum.ex +++ b/lib/elixir/lib/enum.ex @@ -3809,9 +3809,6 @@ defmodule Enum do iex> Enum.unzip([{:a, 1}, {:b, 2}, {:c, 3}]) {[:a, :b, :c], [1, 2, 3]} - iex> Enum.unzip(%{a: 1, b: 2}) - {[:a, :b], [1, 2]} - """ @spec unzip(t) :: {[element], [element]} @@ -4067,7 +4064,7 @@ defmodule Enum do ...> end) [{1, 2, 3}, {1, 2, 3}] - iex> enums = [[1, 2], %{a: 3, b: 4}, [5, 6]] + iex> enums = [[1, 2], [a: 3, b: 4], [5, 6]] ...> Enum.zip_reduce(enums, [], fn elements, acc -> ...> [List.to_tuple(elements) | acc] ...> end) diff --git a/lib/elixir/test/elixir/enum_test.exs b/lib/elixir/test/elixir/enum_test.exs index 11e715a0085..a7aaa90b8bb 100644 --- a/lib/elixir/test/elixir/enum_test.exs +++ b/lib/elixir/test/elixir/enum_test.exs @@ -56,9 +56,9 @@ defmodule EnumTest do end test "mix and match" do - enums = [[1, 2], %{a: 3, b: 4}, [5, 6]] + enums = [[1, 2], 3..4, [5, 6]] result = Enum.zip_reduce(enums, [], fn elements, acc -> [List.to_tuple(elements) | acc] end) - assert result == [{2, {:b, 4}, 6}, {1, {:a, 3}, 5}] + assert result == [{2, 4, 6}, {1, 3, 5}] end end @@ -412,7 +412,7 @@ defmodule EnumTest do assert Enum.into([a: 1, b: 2], %{c: 3}) == %{a: 1, b: 2, c: 3} assert Enum.into(MapSet.new(a: 1, b: 2), %{}) == %{a: 1, b: 2} assert Enum.into(MapSet.new(a: 1, b: 2), %{c: 3}) == %{a: 1, b: 2, c: 3} - assert Enum.into(%{a: 1, b: 2}, []) == [a: 1, b: 2] + assert Enum.into(%{a: 1, b: 2}, []) |> Enum.sort() == [a: 1, b: 2] assert Enum.into(1..3, []) == [1, 2, 3] assert Enum.into(["H", "i"], "") == "Hi" end @@ -1444,7 +1444,7 @@ defmodule EnumTest do test "unzip/1" do assert Enum.unzip([{:a, 1}, {:b, 2}, {:c, 3}]) == {[:a, :b, :c], [1, 2, 3]} assert Enum.unzip([]) == {[], []} - assert Enum.unzip(%{a: 1, b: 2}) == {[:a, :b], [1, 2]} + assert Enum.unzip(%{a: 1}) == {[:a], [1]} assert Enum.unzip(foo: "a", bar: "b") == {[:foo, :bar], ["a", "b"]} assert_raise FunctionClauseError, fn -> Enum.unzip([{:a, 1}, {:b, 2, "foo"}]) end From 0b7ff47d78d7b95532f2e471fab73f1fb62d3586 Mon Sep 17 00:00:00 2001 From: sabiwara Date: Fri, 16 Feb 2024 06:42:16 +0900 Subject: [PATCH 3/6] Fix :only option when deriving Inspect --- lib/elixir/lib/inspect.ex | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/elixir/lib/inspect.ex b/lib/elixir/lib/inspect.ex index d901f189166..326cefe0ba9 100644 --- a/lib/elixir/lib/inspect.ex +++ b/lib/elixir/lib/inspect.ex @@ -535,7 +535,8 @@ end defimpl Inspect, for: Any do defmacro __deriving__(module, struct, options) do - fields = Map.keys(struct) -- [:__exception__, :__struct__] + fields = Enum.sort(Map.keys(struct) -- [:__exception__, :__struct__]) + only = Keyword.get(options, :only, fields) except = Keyword.get(options, :except, []) optional = Keyword.get(options, :optional, []) @@ -545,7 +546,7 @@ defimpl Inspect, for: Any do :ok = validate_option(:optional, optional, fields, module) inspect_module = - if fields == only and except == [] do + if fields == Enum.sort(only) and except == [] do Inspect.Map else Inspect.Any From 5edfdd6d19b1a6c1a7255ec5239502e5d52d70f6 Mon Sep 17 00:00:00 2001 From: sabiwara Date: Fri, 16 Feb 2024 06:06:41 +0900 Subject: [PATCH 4/6] Float.ceil and Float.floor return -0.0 for negative numbers --- lib/elixir/lib/float.ex | 13 +++++++++++++ lib/elixir/test/elixir/float_test.exs | 22 +++++++++++++++++++--- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/lib/elixir/lib/float.ex b/lib/elixir/lib/float.ex index 305395a38f2..775e4a06e8d 100644 --- a/lib/elixir/lib/float.ex +++ b/lib/elixir/lib/float.ex @@ -275,6 +275,8 @@ defmodule Float do -56.0 iex> Float.ceil(34.251, 2) 34.26 + iex> Float.ceil(-0.01) + -0.0 """ @spec ceil(float, precision_range) :: float @@ -332,6 +334,8 @@ defmodule Float do -6.0 iex> Float.round(12.341444444444441, 15) 12.341444444444441 + iex> Float.round(-0.01) + -0.0 """ @spec round(float, precision_range) :: float @@ -340,6 +344,10 @@ defmodule Float do # and could be implemented in the future. def round(float, precision \\ 0) + def round(float, 0) when float == 0.0, do: float + + def round(float, 0) when is_float(float) and float > -0.5 and float < 0.0, do: -0.0 + def round(float, 0) when is_float(float) do float |> :erlang.round() |> :erlang.float() end @@ -365,6 +373,8 @@ defmodule Float do case rounding do :ceil when sign === 0 -> 1 / power_of_10(precision) :floor when sign === 1 -> -1 / power_of_10(precision) + :ceil when sign === 1 -> -0.0 + :half_up when sign === 1 -> -0.0 _ -> 0.0 end @@ -394,6 +404,9 @@ defmodule Float do boundary = den <<< 52 cond do + num == 0 and sign == 1 -> + -0.0 + num == 0 -> 0.0 diff --git a/lib/elixir/test/elixir/float_test.exs b/lib/elixir/test/elixir/float_test.exs index 34e991659cb..e56c3b991ae 100644 --- a/lib/elixir/test/elixir/float_test.exs +++ b/lib/elixir/test/elixir/float_test.exs @@ -104,9 +104,9 @@ defmodule FloatTest do assert Float.ceil(7.5432e3) === 7544.0 assert Float.ceil(7.5e-3) === 1.0 assert Float.ceil(-12.32453e4) === -123_245.0 - assert Float.ceil(-12.32453e-10) === 0.0 + assert Float.ceil(-12.32453e-10) === -0.0 assert Float.ceil(0.32453e-10) === 1.0 - assert Float.ceil(-0.32453e-10) === 0.0 + assert Float.ceil(-0.32453e-10) === -0.0 assert Float.ceil(1.32453e-10) === 1.0 assert Float.ceil(0.0) === 0.0 end @@ -130,7 +130,7 @@ defmodule FloatTest do assert Float.ceil(-12.524235, 3) === -12.524 assert Float.ceil(12.32453e-20, 2) === 0.01 - assert Float.ceil(-12.32453e-20, 2) === 0.0 + assert Float.ceil(-12.32453e-20, 2) === -0.0 assert Float.ceil(0.0, 2) === 0.0 @@ -139,6 +139,11 @@ defmodule FloatTest do end end + test "with small floats rounded up to -0.0" do + assert Float.ceil(-0.1, 0) === -0.0 + assert Float.ceil(-0.01, 1) === -0.0 + end + test "with subnormal floats" do assert Float.ceil(5.0e-324, 0) === 1.0 assert Float.ceil(5.0e-324, 1) === 0.1 @@ -172,6 +177,17 @@ defmodule FloatTest do end end + test "with small floats rounded to +0.0 / -0.0" do + assert Float.round(0.01, 0) === 0.0 + assert Float.round(0.01, 1) === 0.0 + + assert Float.round(-0.01, 0) === -0.0 + assert Float.round(-0.01, 1) === -0.0 + + assert Float.round(-0.49999, 0) === -0.0 + assert Float.round(-0.049999, 1) === -0.0 + end + test "with subnormal floats" do for precision <- 0..15 do assert Float.round(5.0e-324, precision) === 0.0 From ab31e6c26ee0c30a7ee24fa417910216d4f61505 Mon Sep 17 00:00:00 2001 From: sabiwara Date: Fri, 16 Feb 2024 08:44:15 +0900 Subject: [PATCH 5/6] Fix non-deterministic Registry doctest --- lib/elixir/lib/registry.ex | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/elixir/lib/registry.ex b/lib/elixir/lib/registry.ex index 42e963210a6..418bc234622 100644 --- a/lib/elixir/lib/registry.ex +++ b/lib/elixir/lib/registry.ex @@ -1301,16 +1301,16 @@ defmodule Registry do iex> Registry.start_link(keys: :unique, name: Registry.SelectAllTest) iex> {:ok, _} = Registry.register(Registry.SelectAllTest, "hello", :value) iex> {:ok, _} = Registry.register(Registry.SelectAllTest, "world", :value) - iex> Registry.select(Registry.SelectAllTest, [{{:"$1", :"$2", :"$3"}, [], [{{:"$1", :"$2", :"$3"}}]}]) - [{"world", self(), :value}, {"hello", self(), :value}] + iex> Registry.select(Registry.SelectAllTest, [{{:"$1", :"$2", :"$3"}, [], [{{:"$1", :"$2", :"$3"}}]}]) |> Enum.sort() + [{"hello", self(), :value}, {"world", self(), :value}] Get all keys in the registry: iex> Registry.start_link(keys: :unique, name: Registry.SelectAllTest) iex> {:ok, _} = Registry.register(Registry.SelectAllTest, "hello", :value) iex> {:ok, _} = Registry.register(Registry.SelectAllTest, "world", :value) - iex> Registry.select(Registry.SelectAllTest, [{{:"$1", :_, :_}, [], [:"$1"]}]) - ["world", "hello"] + iex> Registry.select(Registry.SelectAllTest, [{{:"$1", :_, :_}, [], [:"$1"]}]) |> Enum.sort() + ["hello", "world"] """ @doc since: "1.9.0" From d59afebf30e43426541facab499338a336129a3e Mon Sep 17 00:00:00 2001 From: sabiwara Date: Fri, 16 Feb 2024 11:26:28 +0900 Subject: [PATCH 6/6] Simplify check --- lib/elixir/lib/float.ex | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/elixir/lib/float.ex b/lib/elixir/lib/float.ex index 775e4a06e8d..7810d21b3bf 100644 --- a/lib/elixir/lib/float.ex +++ b/lib/elixir/lib/float.ex @@ -346,10 +346,11 @@ defmodule Float do def round(float, 0) when float == 0.0, do: float - def round(float, 0) when is_float(float) and float > -0.5 and float < 0.0, do: -0.0 - def round(float, 0) when is_float(float) do - float |> :erlang.round() |> :erlang.float() + case float |> :erlang.round() |> :erlang.float() do + zero when zero == 0.0 and float < 0.0 -> -0.0 + rounded -> rounded + end end def round(float, precision) when is_float(float) and precision in @precision_range do