Skip to content

Commit a72f18b

Browse files
committed
Fix Range.disjoint?/2
1 parent a1a37c6 commit a72f18b

File tree

1 file changed

+27
-18
lines changed

1 file changed

+27
-18
lines changed

lib/elixir/lib/range.ex

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -294,22 +294,24 @@ defmodule Range do
294294
iex> Range.disjoint?(1..10//2, 2..10//2)
295295
true
296296
297-
# First element in common in all below is 29
298-
iex> Range.disjoint?(2..100//3, 9..100//5)
299-
false
300-
iex> Range.disjoint?(101..2//-3, 99..9//-5)
301-
false
297+
# First element in common is 29
302298
iex> Range.disjoint?(1..100//14, 8..100//21)
303299
false
304300
iex> Range.disjoint?(57..-1//-14, 8..100//21)
305301
false
306-
iex> Range.disjoint?(1..100//14, 51..8//-21)
302+
iex> Range.disjoint?(1..100//14, 50..8//-21)
307303
false
308-
309-
# If 29 is out of range
310304
iex> Range.disjoint?(1..28//14, 8..28//21)
311305
true
306+
307+
# First element in common is 14
312308
iex> Range.disjoint?(2..28//3, 9..28//5)
309+
false
310+
iex> Range.disjoint?(26..2//-3, 29..9//-5)
311+
false
312+
313+
# Starting from the back without alignment
314+
iex> Range.disjoint?(27..11//-3, 30..0//-7)
313315
true
314316
315317
"""
@@ -334,21 +336,28 @@ defmodule Range do
334336
# progressions and see if they belong within the ranges
335337
# https://math.stackexchange.com/questions/1656120/formula-to-find-the-first-intersection-of-two-arithmetic-progressions
336338
{gcd, u, v} = Integer.extended_gcd(-step1, step2)
337-
c = first1 - first2 + step2 - step1
338-
t1 = -c / step1 * u
339-
t2 = -c / step2 * v
340-
t = max(floor(t1) + 1, floor(t2) + 1)
341-
x = div(c * u + t * step2, gcd) - 1
342-
y = div(c * v + t * step1, gcd) - 1
343-
344-
x < 0 or first1 + x * step1 > last1 or
345-
y < 0 or first2 + y * step2 > last2
339+
340+
if rem(first2 - first1, gcd) == 0 do
341+
c = first1 - first2 + step2 - step1
342+
t1 = -c / step2 * u
343+
t2 = -c / step1 * v
344+
t = max(floor(t1) + 1, floor(t2) + 1)
345+
x = div(c * u + t * step2, gcd) - 1
346+
y = div(c * v + t * step1, gcd) - 1
347+
348+
x < 0 or first1 + x * step1 > last1 or
349+
y < 0 or first2 + y * step2 > last2
350+
else
351+
true
352+
end
346353
end
347354
end
348355
end
349356

350357
@compile inline: [normalize: 3]
351-
defp normalize(first, last, step) when first > last, do: {last, first, -step}
358+
defp normalize(first, last, step) when first > last,
359+
do: {first - abs(div(first - last, step) * step), first, -step}
360+
352361
defp normalize(first, last, step), do: {first, last, step}
353362

354363
@doc false

0 commit comments

Comments
 (0)