Skip to content

Commit

Permalink
Define sincos
Browse files Browse the repository at this point in the history
Fix #10442
  • Loading branch information
yuyichao committed May 6, 2017
1 parent 22901aa commit 27a96d2
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 6 deletions.
1 change: 1 addition & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@ export
significand,
sin,
sinc,
sincos,
sind,
sinh,
sinpi,
Expand Down
40 changes: 40 additions & 0 deletions base/fastmath.jl
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ const fast_op =
:min => :min_fast,
:minmax => :minmax_fast,
:sin => :sin_fast,
:sincos => :sincos_fast,
:sinh => :sinh_fast,
:sqrt => :sqrt_fast,
:tan => :tan_fast,
Expand Down Expand Up @@ -273,6 +274,45 @@ atan2_fast(x::Float64, y::Float64) =

# explicit implementations

# FIXME: Change to `ccall((:sincos, libm))` when `Ref` calling convention can be
# stack allocated.
@inline function sincos_fast(v::Float64)
return Base.llvmcall("""
%f = bitcast i8 *%1 to void (double, double *, double *)*
%ps = alloca double
%pc = alloca double
call void %f(double %0, double *%ps, double *%pc)
%s = load double, double* %ps
%c = load double, double* %pc
%res0 = insertvalue [2 x double] undef, double %s, 0
%res = insertvalue [2 x double] %res0, double %c, 1
ret [2 x double] %res
""", Tuple{Float64,Float64}, Tuple{Float64,Ptr{Void}}, v, cglobal((:sincos, libm)))
end

@inline function sincos_fast(v::Float32)
return Base.llvmcall("""
%f = bitcast i8 *%1 to void (float, float *, float *)*
%ps = alloca float
%pc = alloca float
call void %f(float %0, float *%ps, float *%pc)
%s = load float, float* %ps
%c = load float, float* %pc
%res0 = insertvalue [2 x float] undef, float %s, 0
%res = insertvalue [2 x float] %res0, float %c, 1
ret [2 x float] %res
""", Tuple{Float32,Float32}, Tuple{Float32,Ptr{Void}}, v, cglobal((:sincosf, libm)))
end

@inline function sincos_fast(v::Float16)
s, c = sincos_fast(Float32(v))
return Float16(s), Float16(c)
end

sincos_fast(v::AbstractFloat) = (sin_fast(v), cos_fast(v))
sincos_fast(v::Real) = sincos_fast(float(v)::AbstractFloat)
sincos_fast(v) = (sin_fast(v), cos_fast(v))

@fastmath begin
exp10_fast(x::T) where {T<:FloatTypes} = exp2(log2(T(10))*x)
exp10_fast(x::Integer) = exp10(float(x))
Expand Down
10 changes: 9 additions & 1 deletion base/math.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

module Math

export sin, cos, tan, sinh, cosh, tanh, asin, acos, atan,
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,
Expand Down Expand Up @@ -419,6 +419,14 @@ for f in (:sin, :cos, :tan, :asin, :acos, :acosh, :atanh, :log, :log2, :log10,
end
end

@inline function sincos(x)
res = Base.FastMath.sincos_fast(x)
if (isnan(res[1]) | isnan(res[2])) & !isnan(x)
throw(DomainError())
end
return res
end

sqrt(x::Float64) = sqrt_llvm(x)
sqrt(x::Float32) = sqrt_llvm(x)

Expand Down
13 changes: 12 additions & 1 deletion base/mpfr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import
nextfloat, prevfloat, promote_rule, rem, rem2pi, round, show,
sum, sqrt, string, print, trunc, precision, exp10, expm1,
gamma, lgamma, log1p,
eps, signbit, sin, cos, tan, sec, csc, cot, acos, asin, atan,
eps, signbit, sin, cos, sincos, tan, sec, csc, cot, acos, asin, atan,
cosh, sinh, tanh, sech, csch, coth, acosh, asinh, atanh, atan2,
cbrt, typemax, typemin, unsafe_trunc, realmin, realmax, rounding,
setrounding, maxintfloat, widen, significand, frexp, tryparse, iszero
Expand All @@ -24,6 +24,8 @@ import Base.GMP: ClongMax, CulongMax, CdoubleMax, Limb

import Base.Math.lgamma_r

import Base.FastMath.sincos_fast

function __init__()
try
# set exponent to full range by default
Expand Down Expand Up @@ -511,6 +513,15 @@ for f in (:exp, :exp2, :exp10, :expm1, :cosh, :sinh, :tanh, :sech, :csch, :coth,
end
end

function sincos_fast(v::BigFloat)
s = BigFloat()
c = BigFloat()
ccall((:mpfr_sin_cos, :libmpfr), Int32, (Ptr{BigFloat}, Ptr{BigFloat}, Ptr{BigFloat}, Int32),
&s, &c, &v, ROUNDING_MODE[])
return (s, c)
end
sincos(v::BigFloat) = sincos_fast(v)

# return log(2)
function big_ln2()
c = BigFloat()
Expand Down
8 changes: 4 additions & 4 deletions base/sysimg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,10 @@ importall .Order
include("sort.jl")
importall .Sort

# Fast math
include("fastmath.jl")
importall .FastMath

function deepcopy_internal end

# BigInts and BigFloats
Expand Down Expand Up @@ -340,10 +344,6 @@ importall .DFT
include("dsp.jl")
importall .DSP

# Fast math
include("fastmath.jl")
importall .FastMath

# libgit2 support
include("libgit2/libgit2.jl")

Expand Down

0 comments on commit 27a96d2

Please sign in to comment.