intervals 0.4.76 → 0.5.83
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION.txt +1 -1
- data/lib/interval.rb +89 -11
- data/test/assertions.rb +23 -0
- data/test/test_fpu.rb +12 -12
- data/test/test_interval.rb +82 -27
- data/test/test_struct_float.rb +4 -3
- data/var/clean-nan.rb +11 -8
- metadata +3 -2
data/VERSION.txt
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.5.83
|
data/lib/interval.rb
CHANGED
@@ -27,10 +27,6 @@ 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
|
-
|
34
30
|
# Create a closed (multi-)interval with the given numerical extrema.
|
35
31
|
#
|
36
32
|
# Interval[3] # In mathematical notation: [3,3]
|
@@ -55,9 +51,7 @@ class Interval
|
|
55
51
|
unless
|
56
52
|
array.all?{|x| Numeric === x} && array.size <= 2 ||
|
57
53
|
array.all?{|x| Array === x && x.size <= 2 && x.all?{|c| Numeric === c}}
|
58
|
-
raise
|
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}"
|
54
|
+
raise Exception::Construction, array
|
61
55
|
end
|
62
56
|
raise
|
63
57
|
end
|
@@ -99,6 +93,17 @@ class Interval
|
|
99
93
|
}.transpose.first
|
100
94
|
end
|
101
95
|
|
96
|
+
# Construct an interval by evaluating the given block using rounding
|
97
|
+
# down and rounding up modes.
|
98
|
+
#
|
99
|
+
# Interval.eval{1/3.0} # => Interval[0.333333333333333, 0.333333333333333]
|
100
|
+
#
|
101
|
+
def Interval.eval(&block)
|
102
|
+
Simple.new(
|
103
|
+
FPU.down {block.call},
|
104
|
+
FPU.up {block.call})
|
105
|
+
end
|
106
|
+
|
102
107
|
# Returns a list of the parameters that can be used to reconstruct the
|
103
108
|
# interval.
|
104
109
|
#
|
@@ -349,6 +354,14 @@ class Interval
|
|
349
354
|
all? {|x| x.sharp?}
|
350
355
|
end
|
351
356
|
|
357
|
+
# An interval is degenerate if each component includes exactly one element.
|
358
|
+
#
|
359
|
+
# Interval
|
360
|
+
#
|
361
|
+
def degenerate?
|
362
|
+
all? {|x| x.degenerate?}
|
363
|
+
end
|
364
|
+
|
352
365
|
# The hull is the smallest simple interval containing the interval itself.
|
353
366
|
#
|
354
367
|
# Interval[[1,2],[3,4]] # => Interval[1, 4]
|
@@ -516,6 +529,21 @@ class Interval::Simple < Interval
|
|
516
529
|
(inf + sup) * 2 **-1
|
517
530
|
end
|
518
531
|
|
532
|
+
# If the interval is degenerate, return its only element, else raise an exception.
|
533
|
+
#
|
534
|
+
# Interval.eval{1/2.0}.number
|
535
|
+
# # => 0.5
|
536
|
+
# Interval.eval{1/3.0}.number
|
537
|
+
# # fails
|
538
|
+
#
|
539
|
+
def number
|
540
|
+
if inf == sup
|
541
|
+
inf
|
542
|
+
else
|
543
|
+
raise Exception::Nondegenerate, self
|
544
|
+
end
|
545
|
+
end
|
546
|
+
|
519
547
|
# Used to implement Interval's plus operator (\+).
|
520
548
|
def add (other)
|
521
549
|
self.class.new(
|
@@ -528,7 +556,7 @@ class Interval::Simple < Interval
|
|
528
556
|
self.class.new(-sup,-inf)
|
529
557
|
end
|
530
558
|
|
531
|
-
# Dependent subtraction, i.e., the inverse of the addition
|
559
|
+
# Dependent subtraction, i.e., the inverse of the addition.
|
532
560
|
#
|
533
561
|
# Interval[3,4].dsub Interval[1,2]
|
534
562
|
# # => Interval[2]
|
@@ -604,12 +632,17 @@ class Interval::Simple < Interval
|
|
604
632
|
true
|
605
633
|
elsif w.kind_of?(Float) && (inf >= 0 || sup <= 0)
|
606
634
|
s1, s2 = extrema.map{|x| x.abs}.sort
|
607
|
-
s1 + s1.ulp == s2
|
635
|
+
s1 + s1.to_f.ulp == s2
|
608
636
|
else
|
609
637
|
false
|
610
638
|
end
|
611
639
|
end
|
612
640
|
|
641
|
+
# Implements Interval#degenerate?
|
642
|
+
def degenerate? # :nodoc:
|
643
|
+
inf == sup
|
644
|
+
end
|
645
|
+
|
613
646
|
# Implements Interval#exp
|
614
647
|
def exp #:nodoc:
|
615
648
|
self.class.new(FPU.exp_down(inf), FPU.exp_up(sup))
|
@@ -714,6 +747,14 @@ class Interval::Multiple < Interval
|
|
714
747
|
self
|
715
748
|
end
|
716
749
|
|
750
|
+
# Raise more expressive exceptions than NoMethodError when invoking
|
751
|
+
# methods specific to simple intervals
|
752
|
+
[:number,:midpoint,:width].each{|f|
|
753
|
+
define_method(f) {
|
754
|
+
raise Exception::Nonsimple, self
|
755
|
+
}
|
756
|
+
}
|
757
|
+
|
717
758
|
end
|
718
759
|
|
719
760
|
class Range
|
@@ -733,8 +774,7 @@ class Range
|
|
733
774
|
end]
|
734
775
|
rescue NoMethodError
|
735
776
|
if exclude_end? && !last.respond_to?(:succ)
|
736
|
-
raise Interval::
|
737
|
-
"A three-dot range with non-discrete upper bound cannot be made into a closed interval"
|
777
|
+
raise Interval::Exception::OpenRight, self
|
738
778
|
end
|
739
779
|
raise
|
740
780
|
end
|
@@ -749,6 +789,44 @@ class Interval
|
|
749
789
|
# The sharp interval that includes Pi.
|
750
790
|
PI = Math::PI + Interval[0, 2 ** -51]
|
751
791
|
|
792
|
+
# Module for the possible interval exceptions.
|
793
|
+
module Exception
|
794
|
+
|
795
|
+
# Exception class for failed preconditions on construction arguments.
|
796
|
+
class Construction < ArgumentError
|
797
|
+
def initialize(array)
|
798
|
+
super(
|
799
|
+
"An interval can only be constructed either from at most two " \
|
800
|
+
"numbers or from a sequence of arrays of at most two numbers: " +
|
801
|
+
array.inspect)
|
802
|
+
end
|
803
|
+
end
|
804
|
+
|
805
|
+
# Exception class for a failed precondition on an interval being degenerate.
|
806
|
+
class Nondegenerate < ArgumentError
|
807
|
+
def initialize(i)
|
808
|
+
super("#{i.inspect} is not degenerate.")
|
809
|
+
end
|
810
|
+
end
|
811
|
+
|
812
|
+
# Exception class for a failed precondition on an interval being simple.
|
813
|
+
class Nonsimple < ArgumentError
|
814
|
+
def initialize(i)
|
815
|
+
super("#{i.inspect} is not simple.")
|
816
|
+
end
|
817
|
+
end
|
818
|
+
|
819
|
+
# Exception class for failed preconditions on range type.
|
820
|
+
class OpenRight < ArgumentError
|
821
|
+
def initialize(range)
|
822
|
+
super(
|
823
|
+
"Cannot construct an interval from a three-dot range " \
|
824
|
+
"with end-value of type #{range.last.class}.")
|
825
|
+
end
|
826
|
+
end
|
827
|
+
|
828
|
+
end
|
829
|
+
|
752
830
|
end
|
753
831
|
|
754
832
|
require File.dirname(__FILE__) + '/../test/test_interval.rb' if __FILE__ == $0
|
data/test/assertions.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'test/unit/assertions'
|
2
|
+
|
3
|
+
module Test
|
4
|
+
module Unit
|
5
|
+
module Assertions
|
6
|
+
|
7
|
+
def assert_predicate(x, predicate, message = nil)
|
8
|
+
template = "<?> should be ?, but it is not."
|
9
|
+
assert_block(
|
10
|
+
build_message(message, template, x, predicate.to_s.gsub(/\?$/){})
|
11
|
+
) { x.send(predicate) }
|
12
|
+
end
|
13
|
+
|
14
|
+
def assert_not_predicate(x, predicate, message = nil)
|
15
|
+
template = "<?> is ?."
|
16
|
+
assert_block(
|
17
|
+
build_message(message, template, x, predicate.to_s.gsub(/\?$/){})
|
18
|
+
) { !x.send(predicate) }
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/test/test_fpu.rb
CHANGED
@@ -22,26 +22,26 @@ class FPU::TestRounding < Test::Unit::TestCase
|
|
22
22
|
|
23
23
|
# Nearest rounding of 1/3 is downwards.
|
24
24
|
def test_third
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
assert_equal 1/3.0, FPU.down {1/3.0}
|
26
|
+
assert_not_equal 1/3.0, FPU.up {1/3.0}
|
27
|
+
assert_not_equal -1/3.0, FPU.down {-1/3.0}
|
28
|
+
assert_equal -1/3.0, FPU.up {-1/3.0}
|
29
29
|
end
|
30
30
|
|
31
31
|
# 1/4 is exact.
|
32
32
|
def test_fourth
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
assert_equal 1/4.0, FPU.down {1/4.0}
|
34
|
+
assert_equal 1/4.0, FPU.up {1/4.0}
|
35
|
+
assert_equal -1/4.0, FPU.down {-1/4.0}
|
36
|
+
assert_equal -1/4.0, FPU.up {-1/4.0}
|
37
37
|
end
|
38
38
|
|
39
39
|
# Nearest rounding of 1/5 is upwards.
|
40
40
|
def test_fifth
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
41
|
+
assert_not_equal 1/5.0, FPU.down {1/5.0}
|
42
|
+
assert_equal 1/5.0, FPU.up {1/5.0}
|
43
|
+
assert_equal -1/5.0, FPU.down {-1/5.0}
|
44
|
+
assert_not_equal -1/5.0, FPU.up {-1/5.0}
|
45
45
|
end
|
46
46
|
|
47
47
|
def test_platform
|
data/test/test_interval.rb
CHANGED
@@ -8,19 +8,20 @@
|
|
8
8
|
# To control the FPU's rounding mode
|
9
9
|
require File.dirname(__FILE__) + '/../lib/interval' if __FILE__ == $0
|
10
10
|
require 'test/unit'
|
11
|
+
require File.dirname(__FILE__) + '/assertions.rb'
|
11
12
|
|
12
13
|
# Assertions to be used when testing intervals.
|
13
|
-
module
|
14
|
+
module Interval::Assertions
|
14
15
|
|
15
|
-
def assert_sharp(x)
|
16
|
-
|
17
|
-
|
16
|
+
def assert_sharp(x, message = nil)
|
17
|
+
assert_predicate(x, :sharp?)
|
18
|
+
assert_predicate(-x, :sharp?)
|
18
19
|
end
|
19
20
|
|
20
21
|
# Assert that an interval is not sharp.
|
21
|
-
def assert_fuzzy(x)
|
22
|
-
|
23
|
-
|
22
|
+
def assert_fuzzy(x, message = nil)
|
23
|
+
assert_not_predicate(x, :sharp?)
|
24
|
+
assert_not_predicate(-x, :sharp?)
|
24
25
|
end
|
25
26
|
|
26
27
|
# Assert that +s+ is a solution to +f+ == 0. Unless the +weak+ flag is set,
|
@@ -29,7 +30,7 @@ module Interval::Assertions
|
|
29
30
|
def assert_solution(s,f,expected, weak = nil)
|
30
31
|
res = s.map{|c| f.call(c)}.inject{|a,c| a|c}
|
31
32
|
# Did something spectacarly unexpected happen?
|
32
|
-
|
33
|
+
assert_predicate(res, :simple?)
|
33
34
|
# Is it a solution?
|
34
35
|
assert_include(res, 0)
|
35
36
|
# Is it minimal?
|
@@ -48,18 +49,21 @@ module Interval::Assertions
|
|
48
49
|
end
|
49
50
|
|
50
51
|
# Assert that the interval +i+ includes +x+.
|
51
|
-
def assert_include(i, x)
|
52
|
-
|
52
|
+
def assert_include(i, x, message = nil)
|
53
|
+
template = "<?> should include <?>, but it does not."
|
54
|
+
assert_block(build_message(message, template, i, x)) { i.include?(x) }
|
53
55
|
end
|
54
56
|
|
55
57
|
# Assert that the interval +i+ does not include +x+.
|
56
|
-
def assert_outside(i, x)
|
57
|
-
|
58
|
+
def assert_outside(i, x, message = nil)
|
59
|
+
template = "<?> should not include <?>, but it does."
|
60
|
+
assert_block(build_message(message, template, i, x)) { !i.include?(x) }
|
58
61
|
end
|
59
62
|
|
60
63
|
# Assert that +x+ is a subset of +y+.
|
61
|
-
def assert_subset(x,y)
|
62
|
-
|
64
|
+
def assert_subset(x, y, message = nil)
|
65
|
+
template = "<?> should be a subset of <?>, but is not."
|
66
|
+
assert_block(build_message(message, template, x, y)) { x == x & y }
|
63
67
|
end
|
64
68
|
|
65
69
|
end
|
@@ -85,11 +89,11 @@ class Interval::TestFundamentals < Test::Unit::TestCase
|
|
85
89
|
end
|
86
90
|
|
87
91
|
def test_construction_failure
|
88
|
-
assert_raise(Interval::
|
89
|
-
assert_raise(Interval::
|
90
|
-
assert_raise(Interval::
|
91
|
-
assert_raise(Interval::
|
92
|
-
assert_raise(Interval::
|
92
|
+
assert_raise(Interval::Exception::Construction) { Interval[1,[2,3]] }
|
93
|
+
assert_raise(Interval::Exception::Construction) { Interval[1,2,3] }
|
94
|
+
assert_raise(Interval::Exception::Construction) { Interval[[1],2] }
|
95
|
+
assert_raise(Interval::Exception::Construction) { Interval['a', 1] }
|
96
|
+
assert_raise(Interval::Exception::Construction) { Interval['a', 'b'] }
|
93
97
|
end
|
94
98
|
|
95
99
|
def test_inequality
|
@@ -177,7 +181,13 @@ class Interval::TestSimpleMethods < Test::Unit::TestCase
|
|
177
181
|
|
178
182
|
def test_midpoint
|
179
183
|
assert_equal(1.5,Interval[1,2].midpoint)
|
180
|
-
assert_raise(
|
184
|
+
ex = assert_raise(Interval::Exception::Nonsimple){ Interval[[1,2],[3,4]].midpoint }
|
185
|
+
end
|
186
|
+
|
187
|
+
def test_number
|
188
|
+
assert_equal(0.5, Interval.eval{1/2.0}.number)
|
189
|
+
assert_raise(Interval::Exception::Nondegenerate) { Interval.eval{1/3.0}.number }
|
190
|
+
assert_raise(Interval::Exception::Nonsimple) { Interval[[1,2],[3,4]].number }
|
181
191
|
end
|
182
192
|
|
183
193
|
def test_width
|
@@ -192,6 +202,7 @@ class Interval::TestSimpleMethods < Test::Unit::TestCase
|
|
192
202
|
tester.call(5.0)
|
193
203
|
tester.call(119.0)
|
194
204
|
tester.call(34e-4)
|
205
|
+
assert_raise(Interval::Exception::Nonsimple) { Interval[[1,2],[3,4]].width }
|
195
206
|
end
|
196
207
|
|
197
208
|
end
|
@@ -264,19 +275,22 @@ class Interval::TestMethods < Test::Unit::TestCase
|
|
264
275
|
end
|
265
276
|
|
266
277
|
def test_simple?
|
267
|
-
|
268
|
-
|
278
|
+
assert_predicate(Interval[1,2], :simple?)
|
279
|
+
assert_not_predicate(Interval[[1,2],[3,4]], :simple?)
|
269
280
|
end
|
270
281
|
|
271
282
|
def test_empty?
|
272
|
-
|
273
|
-
|
274
|
-
|
283
|
+
assert_not_predicate(Interval[1,2], :empty?)
|
284
|
+
assert_not_predicate(Interval[[1,2],[4,3]], :empty?)
|
285
|
+
assert_predicate(Interval[], :empty?)
|
275
286
|
end
|
276
287
|
|
277
288
|
def test_sharp?
|
278
289
|
assert_sharp(Interval[5,5])
|
290
|
+
assert_sharp(Interval[5,5.0])
|
291
|
+
assert_sharp(Interval[5.0,5])
|
279
292
|
assert_sharp(Interval[[1],[2]])
|
293
|
+
assert_fuzzy(Interval[5,5.1])
|
280
294
|
assert_fuzzy(Interval[[1],[2,3]])
|
281
295
|
assert_fuzzy(Interval[5,6])
|
282
296
|
assert_fuzzy(Interval[1.1,1.2])
|
@@ -291,6 +305,25 @@ class Interval::TestMethods < Test::Unit::TestCase
|
|
291
305
|
assert_fuzzy(Interval[6369051672525771, 6369051672525785] * 2.0 ** -52)
|
292
306
|
end
|
293
307
|
|
308
|
+
def test_degenerate?
|
309
|
+
assert_predicate(Interval[5], :degenerate?)
|
310
|
+
assert_predicate(Interval[5.43], :degenerate?)
|
311
|
+
assert_predicate(Interval.eval{1/2.0}, :degenerate?)
|
312
|
+
|
313
|
+
assert_not_predicate(Interval.eval{1/3.0}, :degenerate?)
|
314
|
+
assert_not_predicate(Interval.eval{1/5.0}, :degenerate?)
|
315
|
+
assert_not_predicate(Interval[1,1.1], :degenerate?)
|
316
|
+
|
317
|
+
assert_predicate(Interval[[1],[2]], :degenerate?)
|
318
|
+
assert_predicate(Interval[[1.23],[2]], :degenerate?)
|
319
|
+
assert_predicate(Interval[[1],[2.3]], :degenerate?)
|
320
|
+
assert_predicate(Interval[[1.0123],[2.3]], :degenerate?)
|
321
|
+
|
322
|
+
assert_not_predicate(Interval[[1],[1.1,1.2]], :degenerate?)
|
323
|
+
assert_not_predicate(Interval[[1,1.1],[2]], :degenerate?)
|
324
|
+
assert_not_predicate(Interval[[1,1.1],[2,3]], :degenerate?)
|
325
|
+
end
|
326
|
+
|
294
327
|
def test_hull
|
295
328
|
assert_equal(Interval[1,4], Interval[[1,2],[3,4]].hull)
|
296
329
|
assert_equal(Interval[1,4], Interval[1,4].hull)
|
@@ -301,14 +334,36 @@ class Interval::TestMethods < Test::Unit::TestCase
|
|
301
334
|
assert_equal(Interval[1.2, 5.3], (1.2 .. 5.3).to_interval)
|
302
335
|
assert_equal(Interval[1, 4], (1 .. 4).to_interval)
|
303
336
|
assert_equal(Interval[1, 3], (1 ... 4).to_interval)
|
304
|
-
assert_raise(Interval::
|
337
|
+
assert_raise(Interval::Exception::OpenRight){ (1 ... 3.1).to_interval }
|
305
338
|
if defined?(Rational)
|
306
339
|
x = Rational(1,3)
|
307
340
|
assert_equal(Interval[1, x], (1 .. x).to_interval)
|
308
|
-
assert_raise(Interval::
|
341
|
+
assert_raise(Interval::Exception::OpenRight){ (1 ... x).to_interval }
|
309
342
|
end
|
310
343
|
end
|
311
344
|
|
345
|
+
def test_eval
|
346
|
+
assert_equal(1/Interval[3.0], Interval.eval{1/3.0})
|
347
|
+
assert_equal(1/Interval[5.0], Interval.eval{1/5.0})
|
348
|
+
assert_equal(Interval[0.5], Interval.eval{1/2.0})
|
349
|
+
end
|
350
|
+
|
351
|
+
def test_exceptions
|
352
|
+
ex = assert_raise(Interval::Exception::Nonsimple){ Interval[[1,2],[3,4]].midpoint }
|
353
|
+
assert_equal("Interval[[1, 2], [3, 4]] is not simple.", ex.message)
|
354
|
+
ex = assert_raise(Interval::Exception::Nondegenerate) { Interval[1,2].number }
|
355
|
+
assert_equal("Interval[1, 2] is not degenerate.", ex.message)
|
356
|
+
ex = assert_raise(Interval::Exception::Construction) { Interval[1,2,3] }
|
357
|
+
assert_equal(
|
358
|
+
"An interval can only be constructed either from at most two " \
|
359
|
+
"numbers or from a sequence of arrays of at most two numbers: [1, 2, 3]",
|
360
|
+
ex.message)
|
361
|
+
ex = assert_raise(Interval::Exception::OpenRight){ (1 ... 3.1).to_interval }
|
362
|
+
assert_equal(
|
363
|
+
"Cannot construct an interval from a three-dot range " \
|
364
|
+
"with end-value of type Float.", ex.message)
|
365
|
+
end
|
366
|
+
|
312
367
|
end
|
313
368
|
|
314
369
|
# Tests the Interval-based non-linear solver.
|
data/test/test_struct_float.rb
CHANGED
@@ -7,6 +7,7 @@
|
|
7
7
|
|
8
8
|
require 'test/unit'
|
9
9
|
require File.dirname(__FILE__) + '/../lib/struct_float.rb' if __FILE__ == $0
|
10
|
+
require File.dirname(__FILE__) + '/assertions.rb'
|
10
11
|
|
11
12
|
# Tests Struct::Float.
|
12
13
|
class Struct::Float::Test < Test::Unit::TestCase
|
@@ -23,10 +24,10 @@ class Struct::Float::Test < Test::Unit::TestCase
|
|
23
24
|
# it does not make sense to have it as a constant as for
|
24
25
|
# Infinity. In particular a NaN has 2047 as biased exponent and
|
25
26
|
# non-zero fraction
|
26
|
-
|
27
|
-
|
27
|
+
assert_equal(2047, s.biased_exp)
|
28
|
+
assert_not_predicate(s.fraction, :zero?)
|
28
29
|
# You cannot test for NaN with equality. You MUST use nan?
|
29
|
-
|
30
|
+
assert_predicate(s.to_f, :nan?)
|
30
31
|
assert_equal(s, eval(s.inspect))
|
31
32
|
end
|
32
33
|
|
data/var/clean-nan.rb
CHANGED
@@ -13,13 +13,17 @@ module Enumerable
|
|
13
13
|
# Enumerable#min fails if the collection includes a NaN. Instead,
|
14
14
|
# this methods returns a NaN.
|
15
15
|
def ieee_min
|
16
|
-
|
16
|
+
min
|
17
|
+
rescue ArgumentError
|
18
|
+
find{|x| x.respond_to?(:nan?) && x.nan?} or raise
|
17
19
|
end
|
18
20
|
|
19
21
|
# Enumerable#max fails if the collection includes a NaN. Instead,
|
20
22
|
# this methods returns a NaN.
|
21
23
|
def ieee_max
|
22
|
-
|
24
|
+
max
|
25
|
+
rescue ArgumentError
|
26
|
+
find{|x| x.respond_to?(:nan?) && x.nan?} or raise
|
23
27
|
end
|
24
28
|
|
25
29
|
end
|
@@ -39,18 +43,17 @@ class Interval::Simple
|
|
39
43
|
|
40
44
|
end
|
41
45
|
|
46
|
+
require 'test/unit'
|
47
|
+
require File.dirname(__FILE__) + '/../test/assertions.rb'
|
48
|
+
|
42
49
|
# Tests exception-free multiplication.
|
43
50
|
class CleanNanTest < Test::Unit::TestCase
|
44
51
|
|
45
|
-
def assert_nan(s)
|
46
|
-
assert(s.nan?, "#{s} is not nan")
|
47
|
-
end
|
48
|
-
|
49
52
|
def test_ieee_min_and_max
|
50
53
|
assert_equal(1,[1,2,3].ieee_min)
|
51
54
|
assert_equal(3,[1,2,3].ieee_max)
|
52
|
-
|
53
|
-
|
55
|
+
assert_predicate([1,0.0/0.0,3].ieee_min, :nan?)
|
56
|
+
assert_predicate([1,0.0/0.0,3].ieee_max, :nan?)
|
54
57
|
end
|
55
58
|
|
56
59
|
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
|
|
3
3
|
specification_version: 1
|
4
4
|
name: intervals
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2006-04-
|
6
|
+
version: 0.5.83
|
7
|
+
date: 2006-04-13 00:00:00 +02:00
|
8
8
|
summary: Interval arithmetic in Ruby.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -40,6 +40,7 @@ files:
|
|
40
40
|
- test/test_struct_float.rb
|
41
41
|
- test/data_cos.txt
|
42
42
|
- test/test_fpu.rb
|
43
|
+
- test/assertions.rb
|
43
44
|
- ext/jamis-mod.rb
|
44
45
|
- ext/extconf.rb
|
45
46
|
- ext/fpu.c
|