@@ -777,8 +777,8 @@ function sinpi(x::T) where T<:AbstractFloat
777
777
end
778
778
end
779
779
780
- # Integers and Rationals
781
- function sinpi (x:: T ) where T<: Union{Integer, Rational}
780
+ # Rationals
781
+ function sinpi (x:: T ) where T<: Rational
782
782
Tf = float (T)
783
783
if ! isfinite (x)
784
784
throw (DomainError (x, " `x` must be finite." ))
@@ -836,8 +836,8 @@ function cospi(x::T) where T<:AbstractFloat
836
836
end
837
837
end
838
838
839
- # Integers and Rationals
840
- function cospi (x:: T ) where T<: Union{Integer, Rational}
839
+ # Rationals
840
+ function cospi (x:: T ) where T<: Rational
841
841
if ! isfinite (x)
842
842
throw (DomainError (x, " `x` must be finite." ))
843
843
end
@@ -860,10 +860,79 @@ function cospi(x::T) where T<:Union{Integer,Rational}
860
860
end
861
861
end
862
862
863
+ """
864
+ sincospi(x)
865
+
866
+ Simultaneously compute `sinpi(x)` and `cospi(x)`, where the `x` is in radians.
867
+ """
868
+ function sincospi (x:: T ) where T<: AbstractFloat
869
+ if ! isfinite (x)
870
+ isnan (x) && return x, x
871
+ throw (DomainError (x, " `x` cannot be infinite." ))
872
+ end
873
+
874
+ ax = abs (x)
875
+ s = maxintfloat (T)
876
+ ax >= s && return (copysign (zero (T), x), one (T)) # even integer-valued
877
+
878
+ # reduce to interval [-1,1]
879
+ # assumes RoundNearest rounding mode
880
+ t = 3 * (s/ 2 )
881
+ rx = x- ((x+ t)- t) # zeros may be incorrectly signed
882
+ arx = abs (rx)
883
+
884
+ # same selection scheme as sinpi and cospi
885
+ if (arx == 0 ) | (arx == 1 )
886
+ return copysign (zero (T), x), ifelse (ax % 2 == 0 , one (T), - one (T))
887
+ elseif arx < 0.25
888
+ return sincos_kernel (mulpi_ext (rx))
889
+ elseif arx < 0.75
890
+ y = mulpi_ext (T (0.5 ) - arx)
891
+ return copysign (cos_kernel (y), rx), sin_kernel (y)
892
+ else
893
+ y_si = mulpi_ext (copysign (one (T), rx) - rx)
894
+ y_co = mulpi_ext (one (T) - arx)
895
+ return sin_kernel (y_si), - cos_kernel (y_co)
896
+ end
897
+ end
898
+
899
+ # Rationals
900
+ function sincospi (x:: T ) where T<: Rational
901
+ Tf = float (T)
902
+ if ! isfinite (x)
903
+ throw (DomainError (x, " `x` must be finite." ))
904
+ end
905
+
906
+ # until we get an IEEE remainder function (#9283)
907
+ rx = rem (x,2 )
908
+ if rx > 1
909
+ rx -= 2
910
+ elseif rx < - 1
911
+ rx += 2
912
+ end
913
+ arx = abs (rx)
914
+
915
+ # same selection scheme as sinpi and cospi
916
+ if (arx == 0 ) | (arx == 1 )
917
+ return copysign (zero (Tf),x), ifelse (iseven (numerator (x)), one (Tf), - one (Tf))
918
+ elseif arx < 0.25
919
+ return sincos_kernel (mulpi_ext (rx))
920
+ elseif arx < 0.75
921
+ y = mulpi_ext (T (0.5 ) - arx)
922
+ return copysign (cos_kernel (y), rx), sin_kernel (y)
923
+ else
924
+ y_si = mulpi_ext (copysign (one (T), rx) - rx)
925
+ y_co = mulpi_ext (one (T) - arx)
926
+ return sin_kernel (y_si), - cos_kernel (y_co)
927
+ end
928
+ end
929
+
863
930
sinpi (x:: T ) where {T<: Integer } = zero (signed (T))
864
931
cospi (x:: T ) where {T<: Integer } = isodd (x) ? - one (signed (T)) : one (signed (T))
932
+ sincospi (x:: Integer ) = (sinpi (x), cospi (x))
865
933
sinpi (x:: Real ) = sinpi (float (x))
866
934
cospi (x:: Real ) = cospi (float (x))
935
+ sincospi (x:: Real ) = sincospi (float (x))
867
936
868
937
function sinpi (z:: Complex{T} ) where T
869
938
F = float (T)
@@ -893,7 +962,8 @@ function sinpi(z::Complex{T}) where T
893
962
end
894
963
else
895
964
pizi = pi * zi
896
- Complex (sinpi (zr)* cosh (pizi), cospi (zr)* sinh (pizi))
965
+ sipi, copi = sincospi (zr)
966
+ Complex (sipi* cosh (pizi), copi* sinh (pizi))
897
967
end
898
968
end
899
969
@@ -928,7 +998,55 @@ function cospi(z::Complex{T}) where T
928
998
end
929
999
else
930
1000
pizi = pi * zi
931
- Complex (cospi (zr)* cosh (pizi), - sinpi (zr)* sinh (pizi))
1001
+ sipi, copi = sincospi (zr)
1002
+ Complex (copi* cosh (pizi), - sipi* sinh (pizi))
1003
+ end
1004
+ end
1005
+
1006
+ function sincospi (z:: Complex{T} ) where T
1007
+ F = float (T)
1008
+ zr, zi = reim (z)
1009
+ if isinteger (zr)
1010
+ # zr = ...,-2,-1,0,1,2,...
1011
+ # sin(pi*zr) == ±0
1012
+ # cos(pi*zr) == ±1
1013
+ # cosh(pi*zi) > 0
1014
+ s = copysign (zero (F),zr)
1015
+ c_pos = isa (zr,Integer) ? iseven (zr) : isinteger (zr/ 2 )
1016
+ pizi = pi * zi
1017
+ sh, ch = sinh (pizi), cosh (pizi)
1018
+ (
1019
+ Complex (s, c_pos ? sh : - sh),
1020
+ Complex (c_pos ? ch : - ch, isnan (zi) ? s : - flipsign (s,zi)),
1021
+ )
1022
+ elseif isinteger (2 * zr)
1023
+ # zr = ...,-1.5,-0.5,0.5,1.5,2.5,...
1024
+ # sin(pi*zr) == ±1
1025
+ # cos(pi*zr) == +0
1026
+ # sign(sinh(pi*zi)) == sign(zi)
1027
+ s_pos = isinteger ((2 * zr- 1 )/ 4 )
1028
+ pizi = pi * zi
1029
+ sh, ch = sinh (pizi), cosh (pizi)
1030
+ (
1031
+ Complex (s_pos ? ch : - ch, isnan (zi) ? zero (F) : copysign (zero (F),zi)),
1032
+ Complex (zero (F), s_pos ? - sh : sh),
1033
+ )
1034
+ elseif ! isfinite (zr)
1035
+ if zi == 0
1036
+ Complex (F (NaN ), F (zi)), Complex (F (NaN ), isnan (zr) ? zero (F) : - flipsign (F (zi),zr))
1037
+ elseif isinf (zi)
1038
+ Complex (F (NaN ), F (zi)), Complex (F (Inf ), F (NaN ))
1039
+ else
1040
+ Complex (F (NaN ), F (NaN )), Complex (F (NaN ), F (NaN ))
1041
+ end
1042
+ else
1043
+ pizi = pi * zi
1044
+ sipi, copi = sincospi (zr)
1045
+ sihpi, cohpi = sinh (pizi), cosh (pizi)
1046
+ (
1047
+ Complex (sipi* cohpi, copi* sihpi),
1048
+ Complex (copi* cohpi, - sipi* sihpi),
1049
+ )
932
1050
end
933
1051
end
934
1052
0 commit comments