Skip to content

Commit 7ca65fb

Browse files
committed
Merge pull request #15649 from JuliaLang/anj/hypot
Some changes to hypot
2 parents 64be4ee + ed8563d commit 7ca65fb

File tree

4 files changed

+51
-30
lines changed

4 files changed

+51
-30
lines changed

base/docs/helpdb/Base.jl

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -314,13 +314,6 @@ Compute a "2d histogram" with respect to the bins delimited by the edges given i
314314
"""
315315
hist2d!
316316

317-
"""
318-
hypot(x, y)
319-
320-
Compute the ``\\sqrt{x^2+y^2}`` avoiding overflow and underflow.
321-
"""
322-
hypot
323-
324317
"""
325318
airybi(x)
326319

base/math.jl

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -146,36 +146,51 @@ sqrt(x::Float32) = box(Float32,sqrt_llvm(unbox(Float32,x)))
146146
sqrt(x::Real) = sqrt(float(x))
147147
@vectorize_1arg Number sqrt
148148

149-
hypot(x::Real, y::Real) = hypot(promote(float(x), float(y))...)
150-
function hypot{T<:AbstractFloat}(x::T, y::T)
151-
x = abs(x)
152-
y = abs(y)
153-
if x < y
154-
x, y = y, x
149+
"""
150+
hypot(x, y)
151+
152+
Compute the hypotenuse ``\\sqrt{x^2+y^2}`` avoiding overflow and underflow.
153+
"""
154+
hypot(x::Number, y::Number) = hypot(promote(x, y)...)
155+
function hypot{T<:Number}(x::T, y::T)
156+
ax = abs(x)
157+
ay = abs(y)
158+
if ax < ay
159+
ax, ay = ay, ax
155160
end
156-
if x == 0
157-
r = y/one(x)
161+
if ax == 0
162+
r = ay / one(ax)
158163
else
159-
r = y/x
160-
if isnan(r)
161-
isinf(x) && return x
162-
isinf(y) && return y
163-
return r
164-
end
164+
r = ay / ax
165+
end
166+
167+
rr = ax * sqrt(1 + r * r)
168+
169+
# Use type of rr to make sure that return type is the same for
170+
# all branches
171+
if isnan(r)
172+
isinf(ax) && return oftype(rr, Inf)
173+
isinf(ay) && return oftype(rr, Inf)
174+
return oftype(rr, r)
175+
else
176+
return rr
165177
end
166-
x * sqrt(one(r)+r*r)
167178
end
179+
@vectorize_2arg Number hypot
180+
181+
"""
182+
hypot(x...)
183+
184+
Compute the hypotenuse ``\\sqrt{\\sum x_i}`` avoiding overflow and underflow.
185+
"""
186+
hypot(x::Number...) = vecnorm(x)
168187

169188
atan2(y::Real, x::Real) = atan2(promote(float(y),float(x))...)
170189
atan2{T<:AbstractFloat}(y::T, x::T) = Base.no_op_err("atan2", T)
171190

172-
for f in (:atan2, :hypot)
173-
@eval begin
174-
($f)(y::Float64, x::Float64) = ccall(($(string(f)),libm), Float64, (Float64, Float64,), y, x)
175-
($f)(y::Float32, x::Float32) = ccall(($(string(f,"f")),libm), Float32, (Float32, Float32), y, x)
176-
@vectorize_2arg Number $f
177-
end
178-
end
191+
atan2(y::Float64, x::Float64) = ccall((:atan2,libm), Float64, (Float64, Float64,), y, x)
192+
atan2(y::Float32, x::Float32) = ccall((:atan2f,libm), Float32, (Float32, Float32), y, x)
193+
@vectorize_2arg Number atan2
179194

180195
max{T<:AbstractFloat}(x::T, y::T) = ifelse((y > x) | (signbit(y) < signbit(x)),
181196
ifelse(isnan(y), x, y), ifelse(isnan(x), y, x))

doc/stdlib/math.rst

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -884,7 +884,13 @@ Mathematical Functions
884884

885885
.. Docstring generated from Julia source
886886
887-
Compute the :math:`\sqrt{x^2+y^2}` avoiding overflow and underflow.
887+
Compute the hypotenuse :math:`\sqrt{x^2+y^2}` avoiding overflow and underflow.
888+
889+
.. function:: hypot(x...)
890+
891+
.. Docstring generated from Julia source
892+
893+
Compute the hypotenuse :math:`\sqrt{\sum x_i}` avoiding overflow and underflow.
888894

889895
.. function:: log(x)
890896

test/math.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ for T in (Float32, Float64)
8989
@test_approx_eq exp2(x) exp2(big(x))
9090
@test_approx_eq expm1(x) expm1(big(x))
9191
@test_approx_eq hypot(x,y) hypot(big(x),big(y))
92+
@test_approx_eq hypot(x,x,y) hypot(hypot(big(x),big(x)),big(y))
93+
@test_approx_eq hypot(x,x,y,y) hypot(hypot(big(x),big(x)),hypot(big(y),big(y)))
9294
@test_approx_eq log(x) log(big(x))
9395
@test_approx_eq log10(x) log10(big(x))
9496
@test_approx_eq log1p(x) log1p(big(x))
@@ -177,6 +179,11 @@ for T in (Float32, Float64)
177179
@test isinf(log1p(-one(T)))
178180
@test isnan(log1p(convert(T,NaN)))
179181
@test_throws DomainError log1p(convert(T,-2.0))
182+
@test hypot(T(0), T(0)) === T(0)
183+
@test hypot(T(Inf), T(Inf)) === T(Inf)
184+
@test hypot(T(Inf), T(x)) === T(Inf)
185+
@test hypot(T(Inf), T(NaN)) === T(Inf)
186+
@test isnan(hypot(T(x), T(NaN)))
180187
end
181188
@test_approx_eq exp10(5) exp10(5.0)
182189
@test_approx_eq exp2(Float16(2.)) exp2(2.)

0 commit comments

Comments
 (0)