Skip to content

Commit fd52126

Browse files
nsajkostevengj
andauthored
test: math: test floating-point behavior when mapping zero to zero (#59265)
The idea for this addition to the test suite originates here, where stevengj suggested to do this test for `cosc` specifically: * #59087 (comment) This PR instead tests all applicable functions I could find. Also fix the sign of `cosc(::BigFloat)` for zero input, thanks to stevengj. --------- Co-authored-by: Steven G. Johnson <[email protected]>
1 parent 7b9f532 commit fd52126

File tree

2 files changed

+34
-0
lines changed

2 files changed

+34
-0
lines changed

base/special/trig.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,6 +1112,7 @@ function _cosc(x::Number)
11121112
# generic Taylor series: π ∑ (-1)^n (πx)^{2n-1}/a(n) where
11131113
# a(n) = (1+2n)*(2n-1)! (= OEIS A174549)
11141114
s = (term = -*x))/3
1115+
iszero(s) && return s # preserve floating-point signed zero
11151116
π²x² = term^2
11161117
ε = eps(fastabs(term)) # error threshold to stop sum
11171118
n = 1

test/math.jl

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,39 @@ end
590590
@test ismissing(scdm[2])
591591
end
592592

593+
@testset "behavior at signed zero of monotonic floating-point functions mapping zero to zero" begin
594+
function rounder(rm::RoundingMode)
595+
function closure(::Type{T}, x::AbstractFloat) where {T <: AbstractFloat}
596+
round(T, x, rm)
597+
end
598+
end
599+
rounding_modes = (
600+
RoundNearest, RoundNearestTiesAway, RoundNearestTiesUp, RoundToZero, RoundFromZero, RoundUp, RoundDown,
601+
)
602+
rounders = map(rounder, rounding_modes)
603+
@testset "typ: $typ" for typ in (Float16, Float32, Float64, BigFloat)
604+
(n0, n1) = typ.(0:1)
605+
rounders_typ = Base.Fix1.(rounders, typ)
606+
@testset "f: $f" for f in (
607+
# all strictly increasing
608+
identity, deg2rad, rad2deg, cbrt, log1p, expm1, sinh, tanh, asinh, atanh,
609+
sin, sind, sinpi, tan, tand, tanpi, asin, asind, atan, atand, Base.Fix2(atan, n1), Base.Fix2(atand, n1),
610+
Base.Fix1(round, typ), Base.Fix1(trunc, typ), +, (-, -), (-, cosc),
611+
rounders_typ...,
612+
Base.Fix1(*, n1), Base.Fix2(*, n1), Base.Fix2(/, n1),
613+
)
614+
@testset "s: $s" for s in (-1, 1)
615+
z = s * n0
616+
z::typ
617+
@test z == f(z)::typ
618+
@test signbit(z) === signbit(f(z))
619+
isbitstype(typ) &&
620+
@test z === @inferred f(z)
621+
end
622+
end
623+
end
624+
end
625+
593626
@testset "Integer and Inf args for sinpi/cospi/tanpi/sinc/cosc" begin
594627
for (sinpi, cospi) in ((sinpi, cospi), (x->sincospi(x)[1], x->sincospi(x)[2]))
595628
@test sinpi(1) === 0.0

0 commit comments

Comments
 (0)