Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Correction of lcm() for Array arguments #56113

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions base/intfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ julia> gcd(1//3, 2)

julia> gcd(0, 0, 10, 15)
5

julia> gcd([1//3; 2//3])
1//3
```
"""
function gcd(a::T, b::T) where T<:Integer
Expand Down Expand Up @@ -125,6 +128,9 @@ julia> lcm(1//3, 2)

julia> lcm(1, 3, 5, 7)
105

julia> lcm([1//3; 2//3])
2//3
```
"""
function lcm(a::T, b::T) where T<:Integer
Expand All @@ -149,8 +155,8 @@ lcm(a::Real, b::Real, c::Real...) = lcm(a, lcm(b, c...))
gcd(a::T, b::T) where T<:Real = throw(MethodError(gcd, (a,b)))
lcm(a::T, b::T) where T<:Real = throw(MethodError(lcm, (a,b)))

gcd(abc::AbstractArray{<:Real}) = reduce(gcd, abc; init=zero(eltype(abc)))
lcm(abc::AbstractArray{<:Real}) = reduce(lcm, abc; init=one(eltype(abc)))
gcd(abc::AbstractArray{<:Real}) = reduce(gcd, abc)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand the change for lcm, but why also change this in gcd, it works fine, doesn't it?

Suggested change
gcd(abc::AbstractArray{<:Real}) = reduce(gcd, abc)
gcd(abc::AbstractArray{<:Real}) = reduce(gcd, abc; init=zero(eltype(abc)))

Copy link
Author

@cyanescent cyanescent Oct 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, but does it make sense?

EDIT: it makes sense if we also define:

lcm(abc::AbstractArray{<:Real}) = reduce(lcm, abc; init=1//zero(eltype(abc)))

or just lcm(T[]) = 1//zero(T), to prevent returning Vector{Rational} when the input is Vector{Int} for non-empty arrays.
cf. #55379 (comment)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gcd(T[]) = zero(T) is correct.

From the docstring,

Greatest common (positive) divisor (or zero if all arguments are zero).

In this case, all arguments are zero (vacuously) so the answer is explicitly documented to be zero.

lcm(abc::AbstractArray{<:Real}) = reduce(lcm, abc)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
lcm(abc::AbstractArray{<:Real}) = reduce(lcm, abc)
lcm(abc::AbstractArray{<:Integer}) = reduce(lcm, abc, init=one(eltype(abc)))
lcm(abc::AbstractArray{<:Real}) = reduce(lcm, abc)

For integers, 1 is an identity of LCM (because all integers are a multiple of 1) and is also the correct answer for the empty case (see #55379 (comment)).


function gcd(abc::AbstractArray{<:Integer})
a = zero(eltype(abc))
Expand Down
Loading