From 54e6d72bda72b5ac6cd26625888d9176ae280e4b Mon Sep 17 00:00:00 2001 From: preciz Date: Mon, 20 Jul 2026 16:05:44 +0200 Subject: [PATCH 1/2] Optimize Range.disjoint?/2 empty checks Detect valid empty ranges with direction comparisons instead of computing their exact sizes. Benchmarks average 18% faster across tested paths (7%-28%). Assisted-by: Codex:GPT-5 --- lib/elixir/lib/range.ex | 11 +++++++++-- lib/elixir/test/elixir/range_test.exs | 8 ++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/lib/elixir/lib/range.ex b/lib/elixir/lib/range.ex index 58886331864..0e57b569394 100644 --- a/lib/elixir/lib/range.ex +++ b/lib/elixir/lib/range.ex @@ -477,7 +477,7 @@ defmodule Range do @doc since: "1.8.0" @spec disjoint?(t, t) :: boolean def disjoint?(first1..last1//step1 = range1, first2..last2//step2 = range2) do - if size(range1) == 0 or size(range2) == 0 do + if empty?(range1) or empty?(range2) do true else {first1, last1, step1} = normalize(first1, last1, step1) @@ -513,7 +513,14 @@ defmodule Range do end end - @compile inline: [normalize: 3] + defp empty?(first..last//step) + when is_integer(first) and is_integer(last) and is_integer(step) and step != 0 do + (step > 0 and first > last) or (step < 0 and first < last) + end + + defp empty?(range), do: size(range) == 0 + + @compile inline: [empty?: 1, normalize: 3] defp normalize(first, last, step) when first > last, do: {first - abs(div(first - last, step) * step), first, -step} diff --git a/lib/elixir/test/elixir/range_test.exs b/lib/elixir/test/elixir/range_test.exs index 508d2d29178..6ffc68482ff 100644 --- a/lib/elixir/test/elixir/range_test.exs +++ b/lib/elixir/test/elixir/range_test.exs @@ -82,6 +82,14 @@ defmodule RangeTest do end describe "disjoint?" do + test "empty ranges are disjoint" do + for empty <- [10..0//1, 10..0//2, 0..10//-1, 0..10//-2, 0..-1//1] do + assert Range.disjoint?(empty, 0..10) + assert Range.disjoint?(0..10, empty) + assert Range.disjoint?(empty, empty) + end + end + test "returns true for disjoint ranges" do assert_disjoint(1..5, 6..9) assert_disjoint(-3..1, 2..3) From de82033944f495b3e368e9d0edda2d53f027ead0 Mon Sep 17 00:00:00 2001 From: preciz Date: Mon, 20 Jul 2026 17:54:46 +0200 Subject: [PATCH 2/2] Simplify Range.disjoint?/2 empty checks Pass valid range fields directly to an inline three-arity helper. Assisted-by: Codex:GPT-5 --- lib/elixir/lib/range.ex | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/elixir/lib/range.ex b/lib/elixir/lib/range.ex index 0e57b569394..759d21b2f93 100644 --- a/lib/elixir/lib/range.ex +++ b/lib/elixir/lib/range.ex @@ -476,8 +476,8 @@ defmodule Range do """ @doc since: "1.8.0" @spec disjoint?(t, t) :: boolean - def disjoint?(first1..last1//step1 = range1, first2..last2//step2 = range2) do - if empty?(range1) or empty?(range2) do + def disjoint?(first1..last1//step1, first2..last2//step2) do + if empty?(first1, last1, step1) or empty?(first2, last2, step2) do true else {first1, last1, step1} = normalize(first1, last1, step1) @@ -513,14 +513,14 @@ defmodule Range do end end - defp empty?(first..last//step) - when is_integer(first) and is_integer(last) and is_integer(step) and step != 0 do - (step > 0 and first > last) or (step < 0 and first < last) + @compile inline: [empty?: 3, normalize: 3] + defp empty?(first, last, step) do + case step > 0 do + true -> first > last + false -> first < last + end end - defp empty?(range), do: size(range) == 0 - - @compile inline: [empty?: 1, normalize: 3] defp normalize(first, last, step) when first > last, do: {first - abs(div(first - last, step) * step), first, -step}