1
1
# This file is part of the IntervalArithmetic.jl package; MIT licensed
2
2
3
- half_pi (:: Type{T} ) where T = pi_interval (T) / 2
4
- half_pi (x:: T ) where T<: AbstractFloat = half_pi (T)
5
3
6
- two_pi (:: Type{T} ) where T = pi_interval (T) * 2
4
+ # hard code this for efficiency:
5
+ const one_over_half_pi_interval = inv (0.5 * pi_interval (Float64))
6
+
7
+ """
8
+ Multiply an interval by a positive constant.
9
+ For efficiency, does not check that the constant is positive.
10
+ """
11
+ multiply_by_positive_constant (α, x:: Interval ) = @round (α* x. lo, α* x. hi)
12
+
13
+ half_pi (:: Type{Float64} ) = multiply_by_positive_constant (0.5 , pi_interval (Float64))
14
+ half_pi (:: Type{T} ) where {T} = 0.5 * pi_interval (T)
15
+ half_pi (x:: T ) where {T<: AbstractFloat } = half_pi (T)
16
+
17
+ two_pi (:: Type{Float64} ) = multiply_by_positive_constant (2.0 , pi_interval (Float64))
18
+ two_pi (:: Type{T} ) where {T} = 2 * pi_interval (T)
7
19
8
20
range_atan2 (:: Type{T} ) where {T<: Real } = Interval (- (pi_interval (T). hi), pi_interval (T). hi)
9
21
half_range_atan2 (:: Type{T} ) where {T} = (temp = half_pi (T); Interval (- (temp. hi), temp. hi) )
@@ -19,9 +31,17 @@ This is a rather indirect way to determine if π/2 and 3π/2 are contained
19
31
in the interval; cf. the formula for sine of an interval in
20
32
Tucker, *Validated Numerics*."""
21
33
22
- function find_quadrants (x:: T ) where {T<: AbstractFloat }
34
+ function find_quadrants (x:: T ) where {T}
23
35
temp = atomic (Interval{T}, x) / half_pi (x)
24
- (floor (temp. lo), floor (temp. hi))
36
+
37
+ return SVector (floor (temp. lo), floor (temp. hi))
38
+ end
39
+
40
+ function find_quadrants (x:: Float64 )
41
+ temp = multiply_by_positive_constant (x, one_over_half_pi_interval)
42
+ # x / half_pi(Float64)
43
+
44
+ return SVector (floor (temp. lo), floor (temp. hi))
25
45
end
26
46
27
47
function sin (a:: Interval{T} ) where T
@@ -31,6 +51,8 @@ function sin(a::Interval{T}) where T
31
51
32
52
diam (a) > two_pi (T). lo && return whole_range
33
53
54
+ # The following is equiavlent to doing temp = a / half_pi and
55
+ # taking floor(a.lo), floor(a.hi)
34
56
lo_quadrant = minimum (find_quadrants (a. lo))
35
57
hi_quadrant = maximum (find_quadrants (a. hi))
36
58
@@ -109,14 +131,19 @@ function cos(a::Interval{T}) where T
109
131
end
110
132
end
111
133
134
+ function find_quadrants_tan (x:: T ) where {T}
135
+ temp = atomic (Interval{T}, x) / half_pi (x)
136
+
137
+ return SVector (floor (temp. lo), floor (temp. hi))
138
+ end
112
139
113
140
function tan (a:: Interval{T} ) where T
114
141
isempty (a) && return a
115
142
116
143
diam (a) > pi_interval (T). lo && return entireinterval (a)
117
144
118
- lo_quadrant = minimum (find_quadrants (a. lo))
119
- hi_quadrant = maximum (find_quadrants (a. hi))
145
+ lo_quadrant = minimum (find_quadrants_tan (a. lo))
146
+ hi_quadrant = maximum (find_quadrants_tan (a. hi))
120
147
121
148
lo_quadrant_mod = mod (lo_quadrant, 2 )
122
149
hi_quadrant_mod = mod (hi_quadrant, 2 )
0 commit comments