From 3881eb19c523220e618d2daf60314087a103d7f1 Mon Sep 17 00:00:00 2001 From: pnezis Date: Mon, 9 Mar 2026 22:01:57 +0200 Subject: [PATCH] Fix `Integer.extended_gcd/2` returning negative GCD for zero base cases When one argument is 0 and the other is negative, `extended_gcd/2` was returning a negative GCD, violating both the @spec (which declares `non_neg_integer`) and consistency with `gcd/2`. --- lib/elixir/lib/integer.ex | 10 ++++++++-- lib/elixir/test/elixir/integer_test.exs | 9 ++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/lib/elixir/lib/integer.ex b/lib/elixir/lib/integer.ex index 7dd894d6860..a3f05fcc1ab 100644 --- a/lib/elixir/lib/integer.ex +++ b/lib/elixir/lib/integer.ex @@ -532,8 +532,12 @@ defmodule Integer do iex> Integer.extended_gcd(10, 0) {10, 1, 0} + iex> Integer.extended_gcd(-10, 0) + {10, -1, 0} iex> Integer.extended_gcd(0, 10) {10, 0, 1} + iex> Integer.extended_gcd(0, -10) + {10, 0, -1} iex> Integer.extended_gcd(0, 0) {0, 0, 0} @@ -541,8 +545,10 @@ defmodule Integer do @doc since: "1.12.0" @spec extended_gcd(integer, integer) :: {non_neg_integer, integer, integer} def extended_gcd(0, 0), do: {0, 0, 0} - def extended_gcd(0, b), do: {b, 0, 1} - def extended_gcd(a, 0), do: {a, 1, 0} + def extended_gcd(0, b) when b > 0, do: {b, 0, 1} + def extended_gcd(0, b) when b < 0, do: {-b, 0, -1} + def extended_gcd(a, 0) when a > 0, do: {a, 1, 0} + def extended_gcd(a, 0) when a < 0, do: {-a, -1, 0} def extended_gcd(integer1, integer2) when is_integer(integer1) and is_integer(integer2) do extended_gcd(integer2, integer1, 0, 1, 1, 0) diff --git a/lib/elixir/test/elixir/integer_test.exs b/lib/elixir/test/elixir/integer_test.exs index db94d6b07a9..a9ba693cc52 100644 --- a/lib/elixir/test/elixir/integer_test.exs +++ b/lib/elixir/test/elixir/integer_test.exs @@ -282,7 +282,7 @@ defmodule IntegerTest do end test "extended_gcd" do - # Poor's man properby based testing + # Poor's man property based testing for _ <- 1..100 do left = :rand.uniform(1000) right = :rand.uniform(1000) @@ -290,5 +290,12 @@ defmodule IntegerTest do assert Integer.gcd(left, right) == gcd assert m * left + n * right == gcd end + + # zero cases + for {left, right} <- [{10, 0}, {0, 10}, {0, -10}, {-10, 0}] do + {gcd, m, n} = Integer.extended_gcd(left, right) + assert Integer.gcd(left, right) == gcd + assert m * left + n * right == gcd + end end end