Skip to content

Commit

Permalink
Add sincosd function (#30134)
Browse files Browse the repository at this point in the history
The function `sincosd` simultaneously computes the sine and cosine
in which the input angle is in degrees.
  • Loading branch information
ronisbr authored and JeffBezanson committed Aug 9, 2019
1 parent 3419e3c commit 850c6e4
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 1 deletion.
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ New language features

* Support for Unicode 12.1.0 ([#32002]).
* Methods can now be added to an abstract type ([#31916]).
* Added `sincosd(x)` to simultaneously compute the sine and cosine of `x`, where `x` is in degrees ([#30134]).

Language changes
----------------
Expand Down
1 change: 1 addition & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ export
sin,
sinc,
sincos,
sincosd,
sind,
sinh,
sinpi,
Expand Down
2 changes: 1 addition & 1 deletion base/math.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export sin, cos, sincos, tan, sinh, cosh, tanh, asin, acos, atan,
asinh, acosh, atanh, sec, csc, cot, asec, acsc, acot,
sech, csch, coth, asech, acsch, acoth,
sinpi, cospi, sinc, cosc,
cosd, cotd, cscd, secd, sind, tand,
cosd, cotd, cscd, secd, sind, tand, sincosd,
acosd, acotd, acscd, asecd, asind, atand,
rad2deg, deg2rad,
log, log2, log10, log1p, exponent, exp, exp2, exp10, expm1,
Expand Down
22 changes: 22 additions & 0 deletions base/special/trig.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1073,6 +1073,28 @@ end

tand(x::Real) = sind(x) / cosd(x)

"""
sincosd(x)
Simultaneously compute the sine and cosine of `x`, where `x` is in degrees.
!!! compat "Julia 1.3"
This function requires at least Julia 1.3.
"""
function sincosd(x::Real)
if isinf(x)
return throw(DomainError(x, "sincosd(x) is only defined for finite `x`."))
elseif isnan(x)
return (oftype(x,NaN), oftype(x,NaN))
end

# It turns out that calling those functions separately yielded better
# performance than considering each case and calling `sincos_kernel`.
return (sind(x), cosd(x))
end

sincosd(::Missing) = (missing, missing)

for (fd, f, fn) in ((:sind, :sin, "sine"), (:cosd, :cos, "cosine"), (:tand, :tan, "tangent"))
name = string(fd)
@eval begin
Expand Down
15 changes: 15 additions & 0 deletions test/math.jl
Original file line number Diff line number Diff line change
Expand Up @@ -369,9 +369,14 @@ end
@testset "degree-based trig functions" begin
@testset "$T" for T = (Float32,Float64,Rational{Int})
fT = typeof(float(one(T)))
fTsc = typeof( (float(one(T)), float(one(T))) )
for x = -400:40:400
@test sind(convert(T,x))::fT convert(fT,sin(pi/180*x)) atol=eps(deg2rad(convert(fT,x)))
@test cosd(convert(T,x))::fT convert(fT,cos(pi/180*x)) atol=eps(deg2rad(convert(fT,x)))

s,c = sincosd(convert(T,x))
@test s::fT convert(fT,sin(pi/180*x)) atol=eps(deg2rad(convert(fT,x)))
@test c::fT convert(fT,cos(pi/180*x)) atol=eps(deg2rad(convert(fT,x)))
end
@testset "sind" begin
@test sind(convert(T,0.0))::fT === zero(fT)
Expand All @@ -387,6 +392,16 @@ end
@test cosd(convert(T,-90))::fT === zero(fT)
@test cosd(convert(T,-270))::fT === zero(fT)
end
@testset "sincosd" begin
@test sincosd(convert(T,-360))::fTsc === ( -zero(fT), one(fT) )
@test sincosd(convert(T,-270))::fTsc === ( one(fT), zero(fT) )
@test sincosd(convert(T,-180))::fTsc === ( -zero(fT), -one(fT) )
@test sincosd(convert(T, -90))::fTsc === ( -one(fT), zero(fT) )
@test sincosd(convert(T, 0))::fTsc === ( zero(fT), one(fT) )
@test sincosd(convert(T, 90))::fTsc === ( one(fT), zero(fT) )
@test sincosd(convert(T, 180))::fTsc === ( zero(fT), -one(fT) )
@test sincosd(convert(T, 270))::fTsc === ( -one(fT), zero(fT) )
end

@testset "sinpi and cospi" begin
for x = -3:0.3:3
Expand Down

2 comments on commit 850c6e4

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

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

Executing the daily benchmark build, I will reply here when finished:

@nanosoldier runbenchmarks(ALL, isdaily = true)

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

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

Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @ararslan

Please sign in to comment.