intervals 0.3.63 → 0.4.75
Sign up to get free protection for your applications and to get access to all the features.
- data/README.txt +5 -0
- data/VERSION.txt +1 -1
- data/lib/fpu.rb +5 -204
- data/lib/interval.rb +59 -509
- data/lib/struct_float.rb +1 -65
- data/test/runall.rb +14 -0
- data/test/test_fpu.rb +210 -0
- data/test/test_interval.rb +645 -0
- data/test/test_struct_float.rb +72 -0
- data/var/clean-nan.rb +59 -0
- metadata +8 -3
data/README.txt
CHANGED
@@ -191,6 +191,11 @@ Interval
|
|
191
191
|
Analysis}[http://www.ebooks.dekker.com/eBookCover.asp?eBookID=0824758706&type=ISBN] -
|
192
192
|
Second Edition, Revised and Expanded. John Dekker, Inc., 2003.
|
193
193
|
|
194
|
+
David Goldberg, {What Every Computer Scientist Should Know About
|
195
|
+
Floating-Point
|
196
|
+
Arithmetic}[http://docs-pdf.sun.com/800-7895/800-7895.pdf], ACM
|
197
|
+
Computing Surveys, vol. 23 (1991), pp. 5--48.
|
198
|
+
|
194
199
|
== Author & License
|
195
200
|
|
196
201
|
Copyright (c) 2006, Stefano Taschini.
|
data/VERSION.txt
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.75
|
data/lib/fpu.rb
CHANGED
@@ -27,6 +27,10 @@ end
|
|
27
27
|
|
28
28
|
require File.dirname(__FILE__) + '/struct_float'
|
29
29
|
|
30
|
+
# This module provides the way of controlling the rounding mode of the
|
31
|
+
# floating-point unit (FPU) and also provides mathematical functions
|
32
|
+
# that round their result consistently with the specified rounding
|
33
|
+
# mode.
|
30
34
|
module FPU
|
31
35
|
|
32
36
|
#
|
@@ -81,207 +85,4 @@ module FPU
|
|
81
85
|
|
82
86
|
end
|
83
87
|
|
84
|
-
require 'test/
|
85
|
-
|
86
|
-
# Tests the FPU rounding modes.
|
87
|
-
class FPU::TestRounding < Test::Unit::TestCase
|
88
|
-
include FPU
|
89
|
-
|
90
|
-
def setup
|
91
|
-
@saved = rounding
|
92
|
-
end
|
93
|
-
|
94
|
-
def teardown
|
95
|
-
self.rounding = @saved
|
96
|
-
end
|
97
|
-
|
98
|
-
# Nearest rounding of 1/3 is downwards.
|
99
|
-
def test_third
|
100
|
-
assert(FPU.down {1/3.0} == 1/3.0, "1/3 to -");
|
101
|
-
assert(FPU.up {1/3.0} != 1/3.0, "1/3 to +");
|
102
|
-
assert(FPU.down {-1/3.0} != -1/3.0, "-1/3 to -");
|
103
|
-
assert(FPU.up {-1/3.0} == -1/3.0, "-1/3 to +");
|
104
|
-
end
|
105
|
-
|
106
|
-
# 1/4 is exact.
|
107
|
-
def test_fourth
|
108
|
-
assert(FPU.down {1/4.0} == 1/4.0, "1/4 to -");
|
109
|
-
assert(FPU.up {1/4.0} == 1/4.0, "1/4 to +");
|
110
|
-
assert(FPU.down {-1/4.0} == -1/4.0, "-1/4 to -");
|
111
|
-
assert(FPU.up {-1/4.0} == -1/4.0, "-1/4 to +");
|
112
|
-
end
|
113
|
-
|
114
|
-
# Nearest rounding of 1/5 is upwards.
|
115
|
-
def test_fifth
|
116
|
-
assert(FPU.down {1/5.0} != 1/5.0, "1/5 to -");
|
117
|
-
assert(FPU.up {1/5.0} == 1/5.0, "1/5 to +");
|
118
|
-
assert(FPU.down {-1/5.0} == -1/5.0, "-1/5 to -");
|
119
|
-
assert(FPU.up {-1/5.0} != -1/5.0, "-1/5 to +");
|
120
|
-
end
|
121
|
-
|
122
|
-
def test_platform
|
123
|
-
modes = case (RUBY_PLATFORM)
|
124
|
-
when /powerpc/ then [0,2,3]
|
125
|
-
when /i[0-9]86/ then [0,0x0800,0x0400]
|
126
|
-
when /sparc/ then [0,0x80000000, 0xC0000000]
|
127
|
-
else flunk("Cannot be sure of the processor flags for platform "+RUBY_PLATFORM)
|
128
|
-
end
|
129
|
-
assert_equal(modes,
|
130
|
-
[rounding, FPU.up { rounding }, FPU.down { rounding }])
|
131
|
-
end
|
132
|
-
|
133
|
-
def test_rounding_consts
|
134
|
-
assert_equal(PlusRounding , FPU.up { FPU.rounding })
|
135
|
-
assert_equal(MinusRounding , FPU.down { FPU.rounding })
|
136
|
-
assert_equal(StandardRounding, rounding)
|
137
|
-
|
138
|
-
tester = proc { |x| assert_equal(x, (self.rounding = x; FPU.rounding))}
|
139
|
-
tester.call(PlusRounding);
|
140
|
-
tester.call(MinusRounding);
|
141
|
-
tester.call(StandardRounding);
|
142
|
-
end
|
143
|
-
|
144
|
-
def test_exception_safety
|
145
|
-
assert_raise(ArgumentError){FPU.up {[2.0, 0/0.0].sort}}
|
146
|
-
assert_equal(StandardRounding, rounding)
|
147
|
-
assert_raise(ArgumentError){FPU.down {[2.0, 0/0.0].sort}}
|
148
|
-
assert_equal(StandardRounding, rounding)
|
149
|
-
end
|
150
|
-
|
151
|
-
def test_power
|
152
|
-
x = 1/3.0;
|
153
|
-
# The cube of one third should depend on the rounding mode
|
154
|
-
assert_operator(FPU.down{x*x*x}, :<, FPU.up{x*x*x})
|
155
|
-
# But using the built-in power operator, usually it doesn't
|
156
|
-
# assert_equal(FPU.down{x**3}, FPU.up{x**3})
|
157
|
-
# So we define an integer power methods that does
|
158
|
-
assert_operator(FPU.down{FPU.power(x, 3)}, :<, FPU.up{FPU.power(x, 3)})
|
159
|
-
|
160
|
-
assert_equal(32, FPU.power(2, 5))
|
161
|
-
assert_equal([FPU.down{x*x*x}, FPU.up{x*x*x}],[FPU.down{FPU.power(x, 3)},FPU.up{FPU.power(x, 3)}])
|
162
|
-
assert_equal(1.25 ** 13, FPU.power(1.25, 13))
|
163
|
-
assert_equal((-1.25) ** 17, FPU.power(-1.25, 17))
|
164
|
-
assert_equal((-1.25) ** 18, FPU.power(-1.25, 18))
|
165
|
-
(1..10).each {|i|
|
166
|
-
assert_equal(2.0 ** i, FPU.power(2.0, i))
|
167
|
-
}
|
168
|
-
|
169
|
-
end
|
170
|
-
|
171
|
-
end
|
172
|
-
|
173
|
-
if !FPU.respond_to?(:exp_up)
|
174
|
-
warn "***\n*** Module fpu is compiled without transcendetal functions\n***"
|
175
|
-
else
|
176
|
-
# Tests the correct-rounding transcendental functions, if they exist.
|
177
|
-
class FPU::TestTranscendental < Test::Unit::TestCase
|
178
|
-
require 'enumerator'
|
179
|
-
|
180
|
-
def locate(name)
|
181
|
-
([File.dirname(__FILE__)] + $LOAD_PATH).
|
182
|
-
map{|p| File.expand_path("../test/#{name}", File.expand_path(p))}.
|
183
|
-
find(proc {raise LoadError, "Cannot locate #{name}"}) {|p|
|
184
|
-
File.exist?(p)
|
185
|
-
}
|
186
|
-
end
|
187
|
-
|
188
|
-
@@test_vectors_cache = {}
|
189
|
-
|
190
|
-
def get_vectors (name)
|
191
|
-
@@test_vectors_cache[name] ||= IO.readlines(locate(name)).map{|x|
|
192
|
-
e1,m1,e2,m2 = x.chomp.split(' ').map{|y| y.to_i}
|
193
|
-
[e1,m1,e2,m2,e2,m2 - 1].enum_slice(2).map{|e,m| Math::ldexp(m,e)}}
|
194
|
-
end
|
195
|
-
|
196
|
-
def test_easy
|
197
|
-
a, b, c= [
|
198
|
-
[-1, 1008, 2553927345288884],
|
199
|
-
[1, 1022, 4503168880409012],
|
200
|
-
[1, 1022, 4503168880409011]].map{|x| Struct::Float[*x].to_f}
|
201
|
-
assert_equal(b, FPU.exp_up(a))
|
202
|
-
assert_equal(c, FPU.exp_down(a))
|
203
|
-
|
204
|
-
assert_equal(Infinity, FPU.exp_up(Infinity))
|
205
|
-
assert_equal(Infinity, FPU.exp_down(Infinity))
|
206
|
-
assert_equal(0, FPU.exp_up(-Infinity))
|
207
|
-
assert_equal(0, FPU.exp_down(-Infinity))
|
208
|
-
|
209
|
-
assert_equal(Infinity, FPU.log_up(Infinity))
|
210
|
-
assert_equal(Infinity, FPU.log_down(Infinity))
|
211
|
-
assert_equal(-Infinity, FPU.log_up(0))
|
212
|
-
assert_equal(-Infinity, FPU.log_down(0))
|
213
|
-
|
214
|
-
assert_equal(Math::PI, 2*FPU.atan_down(Infinity))
|
215
|
-
assert_equal(Math::PI+2 ** -51, 2*FPU.atan_up(Infinity))
|
216
|
-
assert_equal(-Math::PI, 2*FPU.atan_up(-Infinity))
|
217
|
-
assert_equal(-Math::PI-2 ** -51, 2*FPU.atan_down(-Infinity))
|
218
|
-
end
|
219
|
-
|
220
|
-
def test_exp
|
221
|
-
get_vectors("data_exp.txt").map{|x,y,z|
|
222
|
-
assert_equal(y, FPU.exp_up(x))
|
223
|
-
assert_equal(z, FPU.exp_down(x))
|
224
|
-
}
|
225
|
-
end
|
226
|
-
|
227
|
-
def test_log
|
228
|
-
get_vectors("data_log.txt").map{|x,y,z|
|
229
|
-
assert_equal(y, FPU.log_up(x))
|
230
|
-
assert_equal(z, FPU.log_down(x))
|
231
|
-
}
|
232
|
-
end
|
233
|
-
|
234
|
-
def test_atan
|
235
|
-
get_vectors("data_atan.txt").map{|x,y,z|
|
236
|
-
assert_equal(y, FPU.atan_up(x))
|
237
|
-
assert_equal(z, FPU.atan_down(x))
|
238
|
-
}
|
239
|
-
end
|
240
|
-
|
241
|
-
def test_cos
|
242
|
-
get_vectors("data_cos.txt").map{|x,y,z|
|
243
|
-
assert_equal(y, FPU.cos_up(x))
|
244
|
-
assert_equal(z, FPU.cos_down(x))
|
245
|
-
}
|
246
|
-
end
|
247
|
-
|
248
|
-
def test_sin
|
249
|
-
get_vectors("data_sin.txt").map{|x,y,z|
|
250
|
-
assert_equal(y, FPU.sin_up(x))
|
251
|
-
assert_equal(z, FPU.sin_down(x))
|
252
|
-
}
|
253
|
-
end
|
254
|
-
|
255
|
-
def test_tan
|
256
|
-
get_vectors("data_tan.txt").map{|x,y,z|
|
257
|
-
assert_equal(y, FPU.tan_up(x))
|
258
|
-
assert_equal(z, FPU.tan_down(x))
|
259
|
-
}
|
260
|
-
end
|
261
|
-
|
262
|
-
def test_cosh
|
263
|
-
get_vectors("data_cosh.txt").map{|x,y,z|
|
264
|
-
assert_equal(y, FPU.cosh_up(x))
|
265
|
-
assert_equal(z, FPU.cosh_down(x))
|
266
|
-
}
|
267
|
-
end
|
268
|
-
|
269
|
-
def test_sinh
|
270
|
-
get_vectors("data_sinh.txt").map{|x,y,z|
|
271
|
-
assert_equal(y, FPU.sinh_up(x))
|
272
|
-
assert_equal(z, FPU.sinh_down(x))
|
273
|
-
}
|
274
|
-
end
|
275
|
-
|
276
|
-
# It can happen, depending on the implementation, that Math::sinh is broken
|
277
|
-
def broken_math #:nodoc:
|
278
|
-
x = -8218111829489689 * 2.0 **(-67)
|
279
|
-
y = -8218111833737307 * 2.0 **(-67)
|
280
|
-
assert_equal(y, FPU.sinh_up(x))
|
281
|
-
z = Math::sinh(x);
|
282
|
-
assert(z <= y, [FPU.split(x), FPU.split(z), FPU.split(y)].inspect)
|
283
|
-
end
|
284
|
-
|
285
|
-
end end
|
286
|
-
|
287
|
-
Test::Unit.run = (__FILE__ != $0)
|
88
|
+
require File.dirname(__FILE__) + '/../test/test_fpu.rb' if __FILE__ == $0
|
data/lib/interval.rb
CHANGED
@@ -27,6 +27,10 @@ end
|
|
27
27
|
class Interval
|
28
28
|
include Enumerable
|
29
29
|
|
30
|
+
# Exception class for failed preconditions on construction arguments.
|
31
|
+
class ConstructionError < ArgumentError
|
32
|
+
end
|
33
|
+
|
30
34
|
# Create a closed (multi-)interval with the given numerical extrema.
|
31
35
|
#
|
32
36
|
# Interval[3] # In mathematical notation: [3,3]
|
@@ -38,25 +42,34 @@ class Interval
|
|
38
42
|
# Interval[[1,3],[2,4]] # => Interval[1, 4]
|
39
43
|
#
|
40
44
|
def Interval.[](*array)
|
41
|
-
|
45
|
+
union(*
|
42
46
|
if array.empty?
|
43
47
|
[]
|
44
|
-
elsif array.first.kind_of?(
|
45
|
-
|
48
|
+
elsif array.first.kind_of?(Array)
|
49
|
+
array.select{|x| !x.empty?}.map { |x| Simple.new(*x) }
|
46
50
|
else
|
47
|
-
|
51
|
+
[Simple.new(*array)]
|
48
52
|
end
|
49
53
|
)
|
54
|
+
rescue StandardError
|
55
|
+
unless
|
56
|
+
array.all?{|x| Numeric === x} && array.size <= 2 ||
|
57
|
+
array.all?{|x| Array === x && x.size <= 2 && x.all?{|c| Numeric === c}}
|
58
|
+
raise ConstructionError,
|
59
|
+
"An interval can only be constructed either from at most two numbers or from a " \
|
60
|
+
"sequence of arrays of at most two numbers: #{array.inspect}"
|
61
|
+
end
|
62
|
+
raise
|
50
63
|
end
|
51
64
|
|
52
|
-
# Create
|
65
|
+
# Create the union of an array of intervals.
|
53
66
|
#
|
54
|
-
# Interval.
|
67
|
+
# Interval.union(Interval[1,2], Interval[3,4])
|
55
68
|
# # => Interval[[1, 2], [3, 4]]
|
56
69
|
#
|
57
|
-
def Interval.
|
70
|
+
def Interval.union(*array)
|
58
71
|
l = []
|
59
|
-
|
72
|
+
array.map{|x| x.components}.flatten.sort_by{|x| x.inf}.each{|x|
|
60
73
|
if x.sup < x.inf
|
61
74
|
# skip it
|
62
75
|
elsif l.empty? || x.inf > l.last.sup
|
@@ -72,6 +85,20 @@ class Interval
|
|
72
85
|
end
|
73
86
|
end
|
74
87
|
|
88
|
+
# Add all the arguments using Kahan's summation formula, which
|
89
|
+
# provides sharper results than conventional sum.
|
90
|
+
def Interval.sum(*array)
|
91
|
+
Interval.union *array.inject([[Interval[0],Interval[0]]]) {|sc, xx|
|
92
|
+
sc.inject([]){|a1,(s,c)|
|
93
|
+
xx.inject(a1){|a2,x|
|
94
|
+
y = x.dsub(c)
|
95
|
+
t = s + y
|
96
|
+
a2 + [[t, t.dsub(s).dsub(y)]]
|
97
|
+
}
|
98
|
+
}
|
99
|
+
}.transpose.first
|
100
|
+
end
|
101
|
+
|
75
102
|
# Returns a list of the parameters that can be used to reconstruct the
|
76
103
|
# interval.
|
77
104
|
#
|
@@ -222,7 +249,7 @@ class Interval
|
|
222
249
|
## Implement unary operations
|
223
250
|
[:inverse, :exp, :log, :atan, :cos, :sin, :tan, :cosh, :sinh].each {|op|
|
224
251
|
define_method(op) {
|
225
|
-
Interval.
|
252
|
+
Interval.union(*map{|x| x.send(op)})
|
226
253
|
}
|
227
254
|
}
|
228
255
|
|
@@ -231,7 +258,7 @@ class Interval
|
|
231
258
|
# Interval[-2,2]**2 # => Interval[0, 4]
|
232
259
|
#
|
233
260
|
def ** (n)
|
234
|
-
Interval.
|
261
|
+
Interval.union(*map{|x| (x**n)})
|
235
262
|
end
|
236
263
|
|
237
264
|
# Sum of intervals.
|
@@ -282,7 +309,7 @@ class Interval
|
|
282
309
|
## Implement binary operations: Sum (+), Multiplication (*) and Intersection (&)
|
283
310
|
[[:+, :add], [:*, :multiply], [:&, :intersect]].each {|op, meth|
|
284
311
|
define_method(op) {|other|
|
285
|
-
Interval.
|
312
|
+
Interval.union(*other.to_interval.map {|y| self.map {|x| x.send(meth,y) } }.flatten)
|
286
313
|
}
|
287
314
|
}
|
288
315
|
|
@@ -302,7 +329,7 @@ class Interval
|
|
302
329
|
# # => Interval[1, 4]
|
303
330
|
#
|
304
331
|
def | (other)
|
305
|
-
Interval.
|
332
|
+
Interval.union(other.to_interval, self)
|
306
333
|
end
|
307
334
|
|
308
335
|
# True if the interval has no elements.
|
@@ -334,10 +361,10 @@ class Interval
|
|
334
361
|
end
|
335
362
|
end
|
336
363
|
|
337
|
-
|
364
|
+
# The default options for Interval#newton.
|
365
|
+
NewtonOptions = {
|
338
366
|
:maxIterations => 100,
|
339
|
-
:verbose => false
|
340
|
-
}
|
367
|
+
:verbose => false }
|
341
368
|
|
342
369
|
# Solve a non-linear equation using the Newton-Raphson method,
|
343
370
|
# finding all solutions in a in interval.
|
@@ -354,7 +381,7 @@ class Interval
|
|
354
381
|
# a sharp result showing the three roots -1, 0 and +1.
|
355
382
|
#
|
356
383
|
def newton(f, fp, opts = {})
|
357
|
-
effectiveOpts =
|
384
|
+
effectiveOpts = NewtonOptions.dup.update(opts)
|
358
385
|
verbose = effectiveOpts[:verbose]
|
359
386
|
puts "Starting on #{self}" if verbose
|
360
387
|
step = proc {|w,ww| (w - f.call(Interval[w]) / fp.call(ww) ) & ww}
|
@@ -428,21 +455,14 @@ class Interval::Simple < Interval
|
|
428
455
|
[self]
|
429
456
|
end
|
430
457
|
|
431
|
-
# Constructs a simple interval with given extrema.
|
432
|
-
#
|
433
|
-
# Interval::Simple[1] # => Interval[1]
|
434
|
-
# Interval::Simple[1,2] # => Interval[1,2]
|
435
|
-
#
|
436
|
-
def Simple.[](a, b = a)
|
437
|
-
new(a, b)
|
438
|
-
end
|
439
|
-
|
440
458
|
# Constructs a simple interval, with given lower and upper bounds.
|
441
459
|
#
|
442
|
-
# Interval::Simple.new(1
|
460
|
+
# Interval::Simple.new(1) # => Interval[1]
|
443
461
|
# Interval::Simple.new(1,2) # => Interval[1,2]
|
444
462
|
#
|
445
|
-
def initialize (a, b)
|
463
|
+
def initialize (a, b = a)
|
464
|
+
raise ArgumentError, "Extrema must be numeric: #{[a,b].uniq.inspect}" unless
|
465
|
+
Numeric === a && Numeric === b
|
446
466
|
if (a.respond_to?(:nan?) && a.nan? ) || (b.respond_to?(:nan?) && b.nan?)
|
447
467
|
@inf, @sup = -Infinity, Infinity
|
448
468
|
else
|
@@ -515,9 +535,9 @@ class Interval::Simple < Interval
|
|
515
535
|
# Interval[1,2] + Interval[2]
|
516
536
|
# # => Interval[3,4]
|
517
537
|
def dsub(other)
|
518
|
-
|
538
|
+
self.class.new(
|
519
539
|
FPU.down{inf - other.inf},
|
520
|
-
FPU.up {sup - other.sup}
|
540
|
+
FPU.up {sup - other.sup})
|
521
541
|
end
|
522
542
|
|
523
543
|
# Used to implement Interval's multiplicative operator (\*).
|
@@ -529,6 +549,9 @@ class Interval::Simple < Interval
|
|
529
549
|
FPU.up {
|
530
550
|
[inf * other.inf, inf * other.sup,
|
531
551
|
sup * other.inf, sup * other.sup]}.max)
|
552
|
+
# min and max fail if any of the products is a NaN, which can only
|
553
|
+
# be generated by 0 * Infinity. In this case, the result is the
|
554
|
+
# whole R-star.
|
532
555
|
rescue ArgumentError
|
533
556
|
self.class.new(-Infinity, Infinity)
|
534
557
|
end
|
@@ -708,6 +731,12 @@ class Range
|
|
708
731
|
else
|
709
732
|
last
|
710
733
|
end]
|
734
|
+
rescue NoMethodError
|
735
|
+
if exclude_end? && !last.respond_to?(:succ)
|
736
|
+
raise Interval::ConstructionError,
|
737
|
+
"A three-dot range with non-discrete upper bound cannot be made into a closed interval"
|
738
|
+
end
|
739
|
+
raise
|
711
740
|
end
|
712
741
|
|
713
742
|
end
|
@@ -722,483 +751,4 @@ class Interval
|
|
722
751
|
|
723
752
|
end
|
724
753
|
|
725
|
-
require 'test/
|
726
|
-
|
727
|
-
# Assertions to be used when testing intervals.
|
728
|
-
module Interval::Assertions
|
729
|
-
|
730
|
-
def assert_sharp(x)
|
731
|
-
assert(x.sharp?, x.inspect + " should be sharp.")
|
732
|
-
assert((-x).sharp?, (-x).inspect + " should be sharp.")
|
733
|
-
end
|
734
|
-
|
735
|
-
# Assert that an interval is not sharp.
|
736
|
-
def assert_fuzzy(x)
|
737
|
-
assert(!x.sharp?, x.inspect + " should not be sharp.")
|
738
|
-
assert(!(-x).sharp?, (-x).inspect + " should not be sharp.")
|
739
|
-
end
|
740
|
-
|
741
|
-
# Assert that +s+ is a solution to +f+ == 0. Unless the +weak+ flag is set,
|
742
|
-
# assert also that +s+ == +expected+.
|
743
|
-
# If the +weak+ flag is set, assert that +s+ includes +expected+.
|
744
|
-
def assert_solution(s,f,expected, weak = nil)
|
745
|
-
res = s.map{|c| f.call(c)}.inject{|a,c| a|c}
|
746
|
-
# Did something spectacarly unexpected happen?
|
747
|
-
assert(res.simple?, res)
|
748
|
-
# Is it a solution?
|
749
|
-
assert_include(res, 0)
|
750
|
-
# Is it minimal?
|
751
|
-
assert(s.all? {|x| x.extrema.all? {|y| f.call(Interval[y]).include?(0)}}, s.inspect +
|
752
|
-
" is non minmal")
|
753
|
-
# Is it the expected solution?
|
754
|
-
if weak
|
755
|
-
# check the granularity
|
756
|
-
assert_equal(expected.components.size, s.components.size, [expected,s].inspect)
|
757
|
-
# check for inclusion
|
758
|
-
assert_subset(expected, s)
|
759
|
-
else
|
760
|
-
# check for equality
|
761
|
-
assert_equal(expected,s)
|
762
|
-
end
|
763
|
-
end
|
764
|
-
|
765
|
-
# Assert that the interval +i+ includes +x+.
|
766
|
-
def assert_include(i, x)
|
767
|
-
assert(i.include?(x), i.inspect + " should include " + x.inspect)
|
768
|
-
end
|
769
|
-
|
770
|
-
# Assert that the interval +i+ does not include +x+.
|
771
|
-
def assert_outside(i, x)
|
772
|
-
assert(!i.include?(x), i.inspect + " should not include " + x.inspect)
|
773
|
-
end
|
774
|
-
|
775
|
-
# Assert that +x+ is a subset of +y+.
|
776
|
-
def assert_subset(x,y)
|
777
|
-
assert(x == x & y, x.inspect + " should be a subset of " + y.inspect)
|
778
|
-
end
|
779
|
-
|
780
|
-
end
|
781
|
-
|
782
|
-
# Tests Interval fundamentals: construction, equality and inspection.
|
783
|
-
class Interval::TestFundamentals < Test::Unit::TestCase
|
784
|
-
|
785
|
-
def test_constructor_and_equality
|
786
|
-
tester = proc {|i,ex,klass|
|
787
|
-
assert_equal(klass, i.class)
|
788
|
-
assert_equal(ex, i.construction)
|
789
|
-
assert_equal(i, Interval[*i.construction])
|
790
|
-
}
|
791
|
-
|
792
|
-
tester.call Interval[1], [1], Interval::Simple
|
793
|
-
tester.call Interval[1,2], [1,2], Interval::Simple
|
794
|
-
tester.call Interval[[1,2],[3,4]], [[1,2],[3,4]], Interval::Multiple
|
795
|
-
tester.call Interval[[1],[2]], [[1],[2]], Interval::Multiple
|
796
|
-
tester.call Interval[[1]], [1], Interval::Simple
|
797
|
-
tester.call Interval[2,0/0.0], [-Infinity,+Infinity], Interval::Simple
|
798
|
-
tester.call Interval[0/0.0,9], [-Infinity,+Infinity], Interval::Simple
|
799
|
-
tester.call Interval[[1,3],[4,6],[2,5],[9,9]], [[1,6],[9]], Interval::Multiple
|
800
|
-
end
|
801
|
-
|
802
|
-
def test_construction_failure
|
803
|
-
assert_raise(NoMethodError) { Interval[1,[2,3]] }
|
804
|
-
assert_raise(ArgumentError) { Interval[1,2,3] }
|
805
|
-
assert_raise(NoMethodError) { Interval[1,[2,3]] }
|
806
|
-
assert_raise(NoMethodError) { Interval[[1],2] }
|
807
|
-
end
|
808
|
-
|
809
|
-
def test_inequality
|
810
|
-
assert_not_equal(Interval[1,2], Interval[1,3])
|
811
|
-
assert_not_equal(Interval[1,2], Interval[0,2])
|
812
|
-
assert_not_equal(Interval[1,2], Interval[0,3])
|
813
|
-
assert_not_equal(Interval[1,2], 3)
|
814
|
-
assert_not_equal(Interval[[1,2],[3,4]], Interval[[1,0],[3,4]])
|
815
|
-
end
|
816
|
-
|
817
|
-
def test_inspect_and_to_s
|
818
|
-
tester = proc {|s|
|
819
|
-
i = eval(s)
|
820
|
-
assert_equal(s,i.inspect)
|
821
|
-
assert_equal(s,i.to_s)
|
822
|
-
}
|
823
|
-
tester.call "Interval[1]"
|
824
|
-
tester.call "Interval[1, 2]"
|
825
|
-
tester.call "Interval[[1, 2], [3, 4]]"
|
826
|
-
tester.call "Interval[[1, 2], [4], [5, 6], [Infinity]]"
|
827
|
-
tester.call "Interval[1, 2]"
|
828
|
-
end
|
829
|
-
|
830
|
-
end
|
831
|
-
|
832
|
-
# Tests the arithmetic of Interval::Simple.
|
833
|
-
class Interval::TestSimpleArithmetic < Test::Unit::TestCase
|
834
|
-
|
835
|
-
def test_plus
|
836
|
-
assert_equal(Interval[-Infinity,+Infinity], Interval[-Infinity] + Interval[Infinity])
|
837
|
-
assert_equal(Interval[4,6], Interval[1,2] + Interval[3,4])
|
838
|
-
assert_equal(Interval[3,Infinity], Interval[1,Infinity]+Interval[2])
|
839
|
-
assert_equal(Interval[-Infinity,+Infinity],Interval[-Infinity,-1] + Interval[2,+Infinity])
|
840
|
-
assert_equal(Interval[-Infinity,+Infinity],Interval[-Infinity] + Interval[8,+Infinity])
|
841
|
-
end
|
842
|
-
|
843
|
-
def test_minus
|
844
|
-
assert_equal(Interval[-2,-1], -Interval[1,2])
|
845
|
-
end
|
846
|
-
|
847
|
-
def test_dsub
|
848
|
-
assert_equal(Interval[2], Interval[3,4].dsub(Interval[1,2]))
|
849
|
-
assert_equal(Interval[3,4], Interval[4,6].dsub(Interval[1,2]))
|
850
|
-
assert_equal(Interval[], Interval[3,4].dsub(Interval[0,2]))
|
851
|
-
|
852
|
-
end
|
853
|
-
|
854
|
-
def test_times
|
855
|
-
assert_equal(Interval[-Infinity,+Infinity],Interval[Infinity] * Interval[0])
|
856
|
-
assert_equal(Interval[+Infinity],Interval[Infinity] * Interval[3])
|
857
|
-
assert_equal(Interval[-8,+10], Interval[1,2] * Interval[-4,5])
|
858
|
-
assert_equal(Interval[3,8], Interval[1,2] * Interval[3,4])
|
859
|
-
assert_equal(Interval[-Infinity,+Infinity],Interval[0,1] * Interval[2,Infinity])
|
860
|
-
assert_equal(Interval[2, Infinity], Interval[-Infinity,-2] * Interval[-Infinity,-1])
|
861
|
-
end
|
862
|
-
|
863
|
-
def test_inverse
|
864
|
-
assert_equal(Interval[0.5,1],Interval[1,2].inverse)
|
865
|
-
assert_equal(Interval[-1,-0.5],(-Interval[1,2]).inverse)
|
866
|
-
assert_equal(Interval[[-Infinity,-1],[0.5,+Infinity]],Interval[-1,2].inverse)
|
867
|
-
assert_equal(Interval[[-Infinity],[1,+Infinity]],Interval[0,1].inverse)
|
868
|
-
end
|
869
|
-
|
870
|
-
def test_power
|
871
|
-
assert_equal((-Interval[1,2]).inverse, (-Interval[1,2]) ** -1)
|
872
|
-
assert_equal(Interval[0,4], Interval[-1,2]**2)
|
873
|
-
assert_equal(Interval[-27,8], Interval[-3,2]**3)
|
874
|
-
|
875
|
-
assert_equal(
|
876
|
-
Interval[FPU.down{(1/3.0)*(1/3.0)},FPU.up{(1/3.0)*(1/3.0)}],
|
877
|
-
(Interval[1]/3.0) ** 2)
|
878
|
-
|
879
|
-
assert_equal(
|
880
|
-
Interval[
|
881
|
-
FPU.down{(1/3.0)*(1/3.0)*(1/3.0)},
|
882
|
-
FPU.up{(1/3.0)*(1/3.0)*(1/3.0)}],
|
883
|
-
(Interval[1]/3.0) ** 3)
|
884
|
-
end
|
885
|
-
|
886
|
-
end
|
887
|
-
|
888
|
-
# Tests other methods of Interval::Simple.
|
889
|
-
class Interval::TestSimpleMethods < Test::Unit::TestCase
|
890
|
-
|
891
|
-
def test_midpoint
|
892
|
-
assert_equal(1.5,Interval[1,2].midpoint)
|
893
|
-
assert_raise(NoMethodError){ Interval[[1,2],[3,4]].midpoint }
|
894
|
-
end
|
895
|
-
|
896
|
-
def test_width
|
897
|
-
assert_equal(1, Interval[1,2].width)
|
898
|
-
assert_equal(1, Interval[1,2].width)
|
899
|
-
tester = proc{|x|
|
900
|
-
assert_equal(
|
901
|
-
2.0 ** (-(Math.log(x)/Math.log(2)).ceil - 52),
|
902
|
-
(1/Interval[x]).width)
|
903
|
-
}
|
904
|
-
tester.call(3.0)
|
905
|
-
tester.call(5.0)
|
906
|
-
tester.call(119.0)
|
907
|
-
tester.call(34e-4)
|
908
|
-
end
|
909
|
-
|
910
|
-
end
|
911
|
-
|
912
|
-
# Tests Interval algebra.
|
913
|
-
class Interval::TestAlgebra < Test::Unit::TestCase
|
914
|
-
|
915
|
-
def test_union
|
916
|
-
assert_equal(Interval[[1, 6], [9, 9]], Interval[[1, 3],[4, 6]] | Interval[[2, 5], [9,9]])
|
917
|
-
end
|
918
|
-
|
919
|
-
def test_plus
|
920
|
-
tester = proc{|x,y,sum|
|
921
|
-
assert_equal(sum,x+y)
|
922
|
-
assert_equal(sum,y+x)
|
923
|
-
}
|
924
|
-
tester.call(Interval[[1,2],[10,Infinity]], Interval[[1,9],[-2,-1]], Interval[[-1,1],[2,Infinity]])
|
925
|
-
tester.call(Interval[1,9], Interval[[1,2],[10,Infinity]], Interval[2,Infinity])
|
926
|
-
tester.call(Interval[1,2], 2, Interval[3,4])
|
927
|
-
end
|
928
|
-
|
929
|
-
def test_intersection
|
930
|
-
tester = proc{|x,y,z|
|
931
|
-
assert_equal(z, x & y)
|
932
|
-
assert_equal(z, y & x)
|
933
|
-
}
|
934
|
-
tester.call(Interval[1,2], Interval[0,3], Interval[1,2])
|
935
|
-
tester.call(Interval[1.1,1.9], Interval[1.3,2.5], Interval[1.3, 1.9])
|
936
|
-
tester.call(Interval[1.1,1.9], Interval[0.3,0.7], Interval[])
|
937
|
-
end
|
938
|
-
|
939
|
-
def test_inverse
|
940
|
-
assert_equal(Interval[[-Infinity, -2.0],[0.0, Infinity]],Interval[[-0.5,0.5],[0.2,Infinity]].inverse)
|
941
|
-
end
|
942
|
-
|
943
|
-
def test_minus
|
944
|
-
assert_equal(Interval[[-4,-3],[-2,-1]], -Interval[[1,2],[3,4]])
|
945
|
-
end
|
946
|
-
|
947
|
-
def test_times
|
948
|
-
tester = proc{|x,y,z|
|
949
|
-
assert_equal(z,x*y)
|
950
|
-
assert_equal(z,y*x)
|
951
|
-
}
|
952
|
-
tester.call(Interval[[1, 2], [3, 4]], Interval[0.5, 2], Interval[0.5,8])
|
953
|
-
tester.call(Interval[1,2], 2, Interval[2,4])
|
954
|
-
end
|
955
|
-
|
956
|
-
def test_division
|
957
|
-
assert_equal(Interval[-Infinity, Infinity], Interval[0,1]/Interval[0,1])
|
958
|
-
assert_equal(Interval[0.5], Interval[1]/2)
|
959
|
-
end
|
960
|
-
|
961
|
-
def test_power
|
962
|
-
assert_equal(Interval[-1,2], (Interval[-1,2]**-1)**-1)
|
963
|
-
end
|
964
|
-
|
965
|
-
end
|
966
|
-
|
967
|
-
#Tests other Interval methods.
|
968
|
-
class Interval::TestMethods < Test::Unit::TestCase
|
969
|
-
include Interval::Assertions
|
970
|
-
|
971
|
-
def test_include?
|
972
|
-
assert_include(Interval[1,2], 1.5)
|
973
|
-
assert_include(Interval[1,2], 1)
|
974
|
-
assert_include(Interval[1,2], 2)
|
975
|
-
assert_outside(Interval[1,2], 0)
|
976
|
-
assert_outside(Interval[1,2], 4)
|
977
|
-
end
|
978
|
-
|
979
|
-
def test_simple?
|
980
|
-
assert(Interval[1,2].simple?)
|
981
|
-
assert(!Interval[[1,2],[3,4]].simple?)
|
982
|
-
end
|
983
|
-
|
984
|
-
def test_empty?
|
985
|
-
assert(!Interval[1,2].empty?)
|
986
|
-
assert(!Interval[[1,2],[4,3]].empty?)
|
987
|
-
assert(Interval[].empty?)
|
988
|
-
end
|
989
|
-
|
990
|
-
def test_sharp?
|
991
|
-
assert_sharp(Interval[5,5])
|
992
|
-
assert_sharp(Interval[[1],[2]])
|
993
|
-
assert_fuzzy(Interval[[1],[2,3]])
|
994
|
-
assert_fuzzy(Interval[5,6])
|
995
|
-
assert_fuzzy(Interval[1.1,1.2])
|
996
|
-
assert_fuzzy(Interval[Struct::Float[-1,0,1].to_f,Struct::Float[+1,0,1].to_f])
|
997
|
-
assert_sharp(Interval[Struct::Float[1,1022,2**52-1].to_f,1])
|
998
|
-
assert_sharp(Interval[Struct::Float[1,1029,2**52-1].to_f,128])
|
999
|
-
assert_sharp(Interval[-0.0,0.0])
|
1000
|
-
assert_sharp(Interval[0.0,Struct::Float[1,0,1].to_f])
|
1001
|
-
assert_sharp(Interval[6369051672525772, 6369051672525773] * 2.0 ** -52)
|
1002
|
-
assert_sharp(Interval[6369051672525772, 6369051672525772] * 2.0 ** -52)
|
1003
|
-
assert_fuzzy(Interval[6369051672525771, 6369051672525773] * 2.0 ** -52)
|
1004
|
-
assert_fuzzy(Interval[6369051672525771, 6369051672525785] * 2.0 ** -52)
|
1005
|
-
end
|
1006
|
-
|
1007
|
-
def test_hull
|
1008
|
-
assert_equal(Interval[1,4], Interval[[1,2],[3,4]].hull)
|
1009
|
-
assert_equal(Interval[1,4], Interval[1,4].hull)
|
1010
|
-
assert_equal(Interval[], Interval[].hull)
|
1011
|
-
end
|
1012
|
-
|
1013
|
-
def test_conversion_from_range
|
1014
|
-
assert_equal(Interval[1.2, 5.3], (1.2 .. 5.3).to_interval)
|
1015
|
-
assert_equal(Interval[1, 4], (1 .. 4).to_interval)
|
1016
|
-
assert_equal(Interval[1, 3], (1 ... 4).to_interval)
|
1017
|
-
assert_raise(NoMethodError){ (1 ... 3.1).to_interval }
|
1018
|
-
end
|
1019
|
-
|
1020
|
-
end
|
1021
|
-
|
1022
|
-
# Tests the Interval-based non-linear solver.
|
1023
|
-
class Interval::TestNewton < Test::Unit::TestCase
|
1024
|
-
include Interval::Assertions
|
1025
|
-
|
1026
|
-
def test_sqrt2
|
1027
|
-
f, fp = proc {|x| x**2 - 2}, proc {|x| 2*x}
|
1028
|
-
s = Math::sqrt(2)
|
1029
|
-
assert_equal(6369051672525773 * 2.0 **-52, s)
|
1030
|
-
assert_equal(Interval[s], Interval[0.1,5.0].newton(f, fp))
|
1031
|
-
assert_equal(Interval[], Interval[2.0,5.0].newton(f,fp))
|
1032
|
-
assert_equal(Interval[s], Interval[-1.0,10.0].newton(f,fp))
|
1033
|
-
assert_equal(Interval[-s], Interval[-5.0,0].newton(f,fp))
|
1034
|
-
assert_equal(Interval[[-s],[s]], Interval[-5.0,5.0].newton(f,fp))
|
1035
|
-
end
|
1036
|
-
|
1037
|
-
def test_cubic_1
|
1038
|
-
f, fp = proc {|x| x**3 + x - 10}, proc {|x| 3*x**2 + 1}
|
1039
|
-
s = Interval[-1,5].newton(f,fp)
|
1040
|
-
assert_solution(s, f, Interval[2])
|
1041
|
-
end
|
1042
|
-
|
1043
|
-
def test_cubic_2
|
1044
|
-
f, fp = proc {|x| x**3 + x - 15}, proc {|x| 3*x**2 + 1}
|
1045
|
-
s = Interval[-1.0,5.0].newton(f,fp)
|
1046
|
-
assert_solution(s, f, Interval[5249383869325654 * 2.0 ** -51])
|
1047
|
-
end
|
1048
|
-
|
1049
|
-
def test_cubic_3
|
1050
|
-
f, fp = proc {|x| x * (x ** 2 - 1)}, proc {|x| 3*x**2 - 1}
|
1051
|
-
s = Interval[-5.0,5.0].newton(f,fp)
|
1052
|
-
assert_solution(s, f, Interval[[-1],[0],[1]])
|
1053
|
-
end
|
1054
|
-
|
1055
|
-
def test_dennis_schnabel
|
1056
|
-
f1 = proc {|x| (((x-12) * x + 47 ) * x - 60 )* x}
|
1057
|
-
f2 = proc {|x| f1.call(x) + 24 }
|
1058
|
-
f3 = proc {|x| f1.call(x) + 24.1 }
|
1059
|
-
fp = proc {|x| ((4 * x - 12*3) * x + 47*2) * x - 60}
|
1060
|
-
|
1061
|
-
assert_solution(Interval[-1e2,1e2].newton(f1,fp), f1, Interval[[0],[3],[4],[5]],:weak)
|
1062
|
-
assert_solution(Interval[-1e2,1e2].newton(f2,fp), f2, Interval[[0.888305779071752],[1]], :weak)
|
1063
|
-
assert_equal(Interval[], Interval[-1e2,1e2].newton(f3,fp))
|
1064
|
-
end
|
1065
|
-
|
1066
|
-
if FPU.respond_to?(:exp_up)
|
1067
|
-
def test_exp
|
1068
|
-
f, fp = proc{|x| x.exp + x}, proc {|x| x.exp + 1}
|
1069
|
-
z0 = Interval[-1e2,1e2].newton(f,fp)
|
1070
|
-
assert_solution(z0, f, Interval[-0.56714329040978384])
|
1071
|
-
|
1072
|
-
f, fp = proc{|x| x*(-x).exp + 1}, proc {|x| (1-x)*(-x).exp}
|
1073
|
-
z1 = Interval[-1e2,1e2].newton(f,fp)
|
1074
|
-
assert_solution(z0, f, z0, :weak)
|
1075
|
-
assert_sharp(z1)
|
1076
|
-
end end
|
1077
|
-
|
1078
|
-
if FPU.respond_to?(:exp_up)
|
1079
|
-
def test_trig
|
1080
|
-
f = proc{|x| (x*Interval::PI/3.0).cos() -0.5}
|
1081
|
-
fp = proc{|x| -(x*Interval::PI/3).sin() * Interval::PI/3}
|
1082
|
-
s = Interval[-10.0,10.0].newton(f, fp)
|
1083
|
-
assert_solution(s, f, Interval[[-7], [-5], [-1], [1], [5], [7]], :weak)
|
1084
|
-
end end
|
1085
|
-
|
1086
|
-
end
|
1087
|
-
|
1088
|
-
if FPU.respond_to?(:exp_up)
|
1089
|
-
# Tests Interval transcendental functions.
|
1090
|
-
class Interval::TestTranscendental < Test::Unit::TestCase
|
1091
|
-
include Interval::Assertions
|
1092
|
-
|
1093
|
-
def test_exp
|
1094
|
-
assert_equal(Interval::E, Interval[1].exp)
|
1095
|
-
assert_equal(Interval[1,Interval::E.sup], Interval[0,1].exp)
|
1096
|
-
assert_equal(Interval[Interval::E.inf, Infinity], Interval[1,Infinity].exp)
|
1097
|
-
assert_equal(Interval[0], Interval[-Infinity].exp)
|
1098
|
-
assert_equal(Interval[[0, 1], [Math::E, Infinity]], Interval[[-Infinity,0],[1,Infinity]].exp)
|
1099
|
-
end
|
1100
|
-
|
1101
|
-
def test_log
|
1102
|
-
assert_equal(Interval[-Infinity, 0], Interval[-1,+1].log)
|
1103
|
-
assert_equal(Interval[0], Interval[1].log)
|
1104
|
-
assert_equal(Interval[], Interval[-2,-1].log)
|
1105
|
-
assert_equal(Interval[-Infinity], Interval[-2,0].log)
|
1106
|
-
assert_equal(Interval[-Infinity,0], Interval[0,1].log)
|
1107
|
-
assert_include(Interval::E.log, 1)
|
1108
|
-
assert_equal(3 * 2 ** -53, Interval[1].exp.log.width)
|
1109
|
-
end
|
1110
|
-
|
1111
|
-
def test_atan
|
1112
|
-
assert_equal(Interval::PI, 4 * Interval[1].atan)
|
1113
|
-
assert_equal(Interval[-Interval::PI.sup, Interval::PI.sup], 2 * Interval[-Infinity,Infinity].atan)
|
1114
|
-
assert_equal(Interval[0], Interval[0].atan)
|
1115
|
-
end
|
1116
|
-
|
1117
|
-
def test_cosh
|
1118
|
-
assert_sharp(Interval[1].cosh)
|
1119
|
-
assert_equal(Interval[1], Interval[0].cosh)
|
1120
|
-
assert_equal((Interval[1].cosh | Interval[3].cosh).hull, Interval[1,3].cosh)
|
1121
|
-
assert_equal(Interval[1,3].cosh, Interval[-3,-1].cosh)
|
1122
|
-
assert_equal((Interval[0] | Interval[3].cosh).hull, Interval[-1,3].cosh)
|
1123
|
-
assert_equal(Interval[-1,3].cosh, Interval[-3,1].cosh)
|
1124
|
-
assert_equal(Interval[0, Infinity], Interval[-Infinity,Infinity].cosh)
|
1125
|
-
end
|
1126
|
-
|
1127
|
-
def test_sinh
|
1128
|
-
assert_sharp(Interval[1].sinh)
|
1129
|
-
assert_equal(Interval[0], Interval[0].sinh)
|
1130
|
-
assert_equal((Interval[-1].sinh | Interval[3].sinh).hull, Interval[-1,3].sinh)
|
1131
|
-
assert_equal(Interval[-Infinity, Infinity], Interval[-Infinity,Infinity].sinh)
|
1132
|
-
end
|
1133
|
-
|
1134
|
-
def test_cos
|
1135
|
-
assert_equal(Interval[-1,-1 + 2 ** -53], Interval::PI.cos)
|
1136
|
-
assert_equal(Interval[1 - 2 ** -53, 1], (2*Interval::PI).cos)
|
1137
|
-
assert_equal(Interval[-1,1], Interval[Infinity].cos)
|
1138
|
-
assert_equal(Interval[-1,1], Interval[-Infinity].cos)
|
1139
|
-
onehalf = (Interval::PI/3).cos
|
1140
|
-
assert_include(onehalf, 0.5)
|
1141
|
-
assert_equal(Interval[onehalf.inf,1], (-Interval::PI/4 | Interval::PI/3).hull.cos)
|
1142
|
-
minusonehalf = (2*Interval::PI/3).cos
|
1143
|
-
assert_include(minusonehalf, -0.5)
|
1144
|
-
assert_equal(Interval[-1,minusonehalf.sup], (5*Interval::PI/4 | 2*Interval::PI/3).hull.cos)
|
1145
|
-
assert_equal((minusonehalf | onehalf).hull, ((Interval::PI | 2*Interval::PI).hull/3).cos)
|
1146
|
-
full = (5 * Interval::PI/3 | 3.5 * Interval::PI).hull
|
1147
|
-
assert_equal(Interval[-1,1], full.cos)
|
1148
|
-
assert_equal(Interval[-1,1], (full + 2 * Interval::PI).cos)
|
1149
|
-
assert_equal(Interval[-1,1], (full + 4 * Interval::PI).cos)
|
1150
|
-
assert_equal(Interval[-1,1], (full + 6 * Interval::PI).cos)
|
1151
|
-
assert_equal(Interval[-1,1], (full + 8 * Interval::PI).cos)
|
1152
|
-
assert_equal(Interval[-1,1], (full - 2 * Interval::PI).cos)
|
1153
|
-
assert_equal(Interval[-1,1], (full - 4 * Interval::PI).cos)
|
1154
|
-
assert_equal(Interval[-1,1], (full - 6 * Interval::PI).cos)
|
1155
|
-
assert_equal(Interval[-1,1], (full - 8 * Interval::PI).cos)
|
1156
|
-
end
|
1157
|
-
|
1158
|
-
def test_sin
|
1159
|
-
assert_equal(Interval[-1,-1 + 2 ** -53], (3*Interval::PI/2).sin)
|
1160
|
-
assert_equal(Interval[1 - 2 ** -53, 1], (Interval::PI/2).sin)
|
1161
|
-
assert_equal(Interval[-1,1], Interval[Infinity].sin)
|
1162
|
-
assert_equal(Interval[-1,1], Interval[-Infinity].sin)
|
1163
|
-
onehalf = (Interval::PI/6).sin
|
1164
|
-
assert_include(onehalf, 0.5)
|
1165
|
-
assert_equal(Interval[onehalf.inf,1], (3 * Interval::PI/4 | Interval::PI/6).hull.sin)
|
1166
|
-
minusonehalf = (7*Interval::PI/6).sin
|
1167
|
-
assert_include(minusonehalf, -0.5)
|
1168
|
-
assert_equal(Interval[-1,minusonehalf.sup], (7*Interval::PI/4 | 7*Interval::PI/6).hull.sin)
|
1169
|
-
assert_equal((-onehalf | onehalf).hull, ((Interval::PI | -Interval::PI).hull/6.0).sin)
|
1170
|
-
full = ((5 * Interval::PI/3 | 3.5 * Interval::PI) + Interval::PI/2).hull
|
1171
|
-
assert_equal(Interval[-1,1], full.sin)
|
1172
|
-
assert_equal(Interval[-1,1], (full + 2 * Interval::PI).cos)
|
1173
|
-
assert_equal(Interval[-1,1], (full + 4 * Interval::PI).cos)
|
1174
|
-
assert_equal(Interval[-1,1], (full + 6 * Interval::PI).cos)
|
1175
|
-
assert_equal(Interval[-1,1], (full + 8 * Interval::PI).cos)
|
1176
|
-
assert_equal(Interval[-1,1], (full - 2 * Interval::PI).cos)
|
1177
|
-
assert_equal(Interval[-1,1], (full - 4 * Interval::PI).cos)
|
1178
|
-
assert_equal(Interval[-1,1], (full - 6 * Interval::PI).cos)
|
1179
|
-
assert_equal(Interval[-1,1], (full - 8 * Interval::PI).cos)
|
1180
|
-
end
|
1181
|
-
|
1182
|
-
def test_tan
|
1183
|
-
assert_equal(Interval[0], Interval[0].tan)
|
1184
|
-
assert_equal(Interval[], Interval[].tan)
|
1185
|
-
assert_equal(Interval[-Infinity, Infinity], Interval[0,6].tan)
|
1186
|
-
assert_equal(Interval[-Infinity, Infinity], (-Interval::PI/2 | Interval::PI/2).hull.tan)
|
1187
|
-
assert_equal(Interval[-Infinity, Infinity], (- Interval::PI/4 | Interval::PI * 1.25).hull.tan)
|
1188
|
-
assert_equal(Interval[-Infinity, Infinity], (4.75 *Interval::PI | Interval::PI * 6.25).hull.tan)
|
1189
|
-
|
1190
|
-
assert_equal(2 ** -51, Interval::PI.tan.width)
|
1191
|
-
assert_include(Interval::PI.tan, 0)
|
1192
|
-
assert_equal(3 * 2 ** -53, (Interval::PI/4).tan.width)
|
1193
|
-
assert_include((Interval::PI/4).tan, 1)
|
1194
|
-
|
1195
|
-
x = (Interval::PI/4 | Interval::PI * 0.75).hull
|
1196
|
-
assert_equal((Interval[x.sup].tan | -Infinity).hull | (Interval[x.inf].tan | Infinity).hull, x.tan)
|
1197
|
-
|
1198
|
-
x = (Interval::PI | -Interval::PI).hull/4
|
1199
|
-
assert_equal((Interval[x.inf].tan | Interval[x.sup].tan).hull, x.tan)
|
1200
|
-
end
|
1201
|
-
|
1202
|
-
end end
|
1203
|
-
|
1204
|
-
Test::Unit.run = (__FILE__ != $0)
|
754
|
+
require File.dirname(__FILE__) + '/../test/test_interval.rb' if __FILE__ == $0
|