intervals 0.3.63 → 0.4.75
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|