intervals 0.4.76 → 0.5.83
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/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
|