range_extd 1.1.1 → 2.0
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.
- checksums.yaml +4 -4
- data/ChangeLog +16 -0
- data/Makefile +7 -3
- data/News +4 -0
- data/README.en.rdoc +1146 -270
- data/README.ja.rdoc +1146 -270
- data/Rakefile +11 -5
- data/lib/range_extd/infinity.rb +426 -0
- data/lib/range_extd/load_all.rb +19 -0
- data/lib/range_extd/nil_class.rb +41 -0
- data/lib/range_extd/nowhere.rb +135 -0
- data/lib/range_extd/numeric.rb +160 -0
- data/lib/range_extd/object.rb +53 -0
- data/lib/range_extd/range.rb +401 -0
- data/lib/{range_extd/range_extd.rb → range_extd.rb} +387 -633
- data/range_extd.gemspec +50 -0
- data/test/all_required_test.rb +173 -0
- data/test/test_range_extd.rb +482 -148
- data/test/test_range_extd_nowhere.rb +84 -0
- metadata +29 -16
- data/lib/range_extd/infinity/infinity.rb +0 -600
@@ -1,600 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
|
3
|
-
if ! defined?(Rational)
|
4
|
-
require 'rational' # For Ruby 1.8
|
5
|
-
end
|
6
|
-
|
7
|
-
# This file is required from range_open/range_open.rb
|
8
|
-
class RangeExtd < Range
|
9
|
-
#
|
10
|
-
# =Class RangeExtd::Infinity
|
11
|
-
#
|
12
|
-
# Authors:: Masa Sakano
|
13
|
-
# License:: MIT
|
14
|
-
#
|
15
|
-
# ==Summary
|
16
|
-
#
|
17
|
-
# Class to hold just two constants:
|
18
|
-
# * RangeExtd::Infinity::NEGATIVE
|
19
|
-
# * RangeExtd::Infinity::POSITIVE
|
20
|
-
#
|
21
|
-
# and two more:
|
22
|
-
#
|
23
|
-
# * FLOAT_INFINITY (OBSOLETE; workaround for Ruby 1.8 to represent Float::INFINITY)
|
24
|
-
# * CLASSES_ACCEPTABLE (see below)
|
25
|
-
#
|
26
|
-
# There is no other object in this class (you can not create a new one).
|
27
|
-
#
|
28
|
-
# This class includes Comparable module.
|
29
|
-
#
|
30
|
-
# ==Description
|
31
|
-
#
|
32
|
-
# Both the two constant are an abstract value which is always smaller/larger,
|
33
|
-
# respectively, than any other Comparable objects (1 or -1 by i{#<=>}(obj))
|
34
|
-
# except for infinities with the same polarity, that is, positive or negative,
|
35
|
-
# in which case 0 is returned.
|
36
|
-
# See the document of the method {#==} for the definition of "infinity".
|
37
|
-
# Also, {#succ} is defined, which just returns self.
|
38
|
-
#
|
39
|
-
# There is a note of caution.
|
40
|
-
# The method {#<=>} is defined in this class as mentioned above.
|
41
|
-
# However any operator is, by Ruby's definition, not commutative,
|
42
|
-
# unless both the classes define so.
|
43
|
-
#
|
44
|
-
# There are only three built-in classes that are Comparable: String, Time and Numeric
|
45
|
-
# (except for Complex).
|
46
|
-
# Note Date and DateTime objects are so, too, however practically
|
47
|
-
# they need "require", hence are (and must be) treated, the same as any other classes.
|
48
|
-
# For String and Time class objects, the [#<=>] operator work as expected
|
49
|
-
# in the commutative way.
|
50
|
-
# ?z <=> RangeExtd::Infinity::POSITIVE # => nil
|
51
|
-
# RangeExtd::Infinity::POSITIVE <=> ?z # => 1.
|
52
|
-
#
|
53
|
-
# For Numeric, it does not.
|
54
|
-
# 50 <=> RangeExtd::Infinity::POSITIVE # => nil
|
55
|
-
# RangeExtd::Infinity::POSITIVE <=> 50 # => 1.
|
56
|
-
#
|
57
|
-
# For that reason, for example,
|
58
|
-
# ( 50 .. RangeExtd::Infinity::POSITIVE)
|
59
|
-
# raises an exception, because the Numeric instance 50 does not
|
60
|
-
# know how to compare itself with a RangeExtd::Infinity instance,
|
61
|
-
# and Range class does not allow such a case.
|
62
|
-
#
|
63
|
-
# For Numeric, this is deliberately so.
|
64
|
-
# Please use {Float::INFINITY} instead in principle;
|
65
|
-
# it will be a lot faster in run-time, though it is
|
66
|
-
# perfectly possible for you to implement the feature
|
67
|
-
# in Numeric sub-classes, if need be.
|
68
|
-
#
|
69
|
-
# Any other Comparable classes are defined by users by definition,
|
70
|
-
# whether you or authors of libraries.
|
71
|
-
# The comparison with {RangeExtd::Infinity} instances are
|
72
|
-
# implemented in {Object#<=>} in this library. Hence, as long as
|
73
|
-
# the method [#<=>] in the classes is written sensibly, that is, if it
|
74
|
-
# respects the method of the super-class when it does not know
|
75
|
-
# how to deal with an unknown object, there is no need for
|
76
|
-
# modification. Any object in your class (say, YourComparable)
|
77
|
-
# is immediately comparable with the {RangeExtd::Infinity} instances,
|
78
|
-
# YourComparable.new <=> RangeExtd::Infinity::POSITIVE # => -1
|
79
|
-
# RangeExtd::Infinity::POSITIVE <=> YourComparable.new # => 1
|
80
|
-
# except for the infinity inscances in YourComparable (see {#==}).
|
81
|
-
#
|
82
|
-
# See the document in {Object#<=>} in this code/package for detail.
|
83
|
-
#
|
84
|
-
# However, some existing Comparable classes, perhaps written by some
|
85
|
-
# one else may not be so polite, and has disabled comparison
|
86
|
-
# with any object but those intended. Unlucky you!
|
87
|
-
# For example, the classes like Date and DateTime are one of them.
|
88
|
-
#
|
89
|
-
# For that sort of circumstances,
|
90
|
-
# the class method {RangeExtd::Infinity.overwrite_compare} provides
|
91
|
-
# a convenient way to overcome this problem to make
|
92
|
-
# the operator [#<=>] commutative for a given Comparable class.
|
93
|
-
#
|
94
|
-
# Note {RangeExtd::Infinity.overwrite_compare} does nothing for the classes
|
95
|
-
# registered in the Class constant Array {RangeExtd::Infinity::CLASSES_ACCEPTABLE}.
|
96
|
-
# So, if you want to avoid such modification of the method [#<=>], perhaps
|
97
|
-
# by some other end users, you can register the class in that array.
|
98
|
-
#
|
99
|
-
# Only the methods defined in this class are
|
100
|
-
# {#===}, {#==}, {#<=>}, {#succ}, {#to_s}, {#inspect},
|
101
|
-
# {#infinity?}, {#positive?} and {#negative?}, and in addition, since Version 1.1,
|
102
|
-
# two unary operators {#@+} and {#@-} to unchange/swap the parity are defined
|
103
|
-
# ({#<} and {#>} are modified, too, to deal with Integer and Float;
|
104
|
-
# I do not know whether the default behaviour of these classes have changed
|
105
|
-
# in the recent versions of Ruby, hence resulting in the neccesity of this change).
|
106
|
-
#
|
107
|
-
# === Comparison operators
|
108
|
-
#
|
109
|
-
# {RangeExtd::Infinity::POSITIVE} and InfN {RangeExtd::Infinity::NEGATIVE}
|
110
|
-
# are always comparable with any comparable objects except for
|
111
|
-
# Float::INFINITY, in which case
|
112
|
-
#
|
113
|
-
# (RangeExtd::Infinity::POSITIVE <=> Float::INFINITY) # => nil
|
114
|
-
# (RangeExtd::Infinity::POSITIVE < Float::INFINITY) # => ArgumentError
|
115
|
-
# (RangeExtd::Infinity::POSITIVE > Float::INFINITY) # => ArgumentError
|
116
|
-
# (RangeExtd::Infinity::POSITIVE == Float::INFINITY) # => false
|
117
|
-
#
|
118
|
-
# which is what happens for the comparison operators for Float::INFINITY.
|
119
|
-
#
|
120
|
-
# Basically, the concept of {RangeExtd::Infinity::POSITIVE} is a generalised
|
121
|
-
# concept of Float::INFINITY. Therefore they are really not *equal*.
|
122
|
-
# On the other hand, {RangeExtd::Infinity::POSITIVE} is *greater* than
|
123
|
-
# any normal comparable objects (except those that are *infinite*).
|
124
|
-
# Therefore, all the following are true ({Object#<=>} and some methods
|
125
|
-
# in some classes are modified)
|
126
|
-
#
|
127
|
-
# (5 < RangeExtd::Infinity::POSITIVE)
|
128
|
-
# (5 > RangeExtd::Infinity::NEGATIVE)
|
129
|
-
#
|
130
|
-
# ("a" < RangeExtd::Infinity::POSITIVE)
|
131
|
-
# ("a" > RangeExtd::Infinity::NEGATIVE)
|
132
|
-
#
|
133
|
-
# whereas
|
134
|
-
#
|
135
|
-
# (RangeExtd::Infinity::POSITIVE < Object.new) # => ArgumentError
|
136
|
-
#
|
137
|
-
# raises ArgumentError.
|
138
|
-
#
|
139
|
-
class Infinity
|
140
|
-
|
141
|
-
include Comparable
|
142
|
-
|
143
|
-
# Obsolete Constant FLOAT_INFINITY (for the sake of Ruby 1.8 or earlier).
|
144
|
-
# Please do not use it - it will be removed some time in the future.
|
145
|
-
# n.b., Module#private_constant is introduced in Ruby 1.9.3.
|
146
|
-
begin
|
147
|
-
FLOAT_INFINITY = Float::INFINITY
|
148
|
-
rescue # Ruby 1.8 or earlier.
|
149
|
-
FLOAT_INFINITY = 1/0.0
|
150
|
-
end
|
151
|
-
|
152
|
-
# Class that accept to be compared with Infinity instances.
|
153
|
-
CLASSES_ACCEPTABLE = [self, Float, Integer, Rational, Numeric, String] # Fixnum, Bignum deprecated now.
|
154
|
-
# CLASSES_ACCEPTABLE = [self, Float, Fixnum, Bignum, Rational, Numeric, String] # , BigFloat
|
155
|
-
CLASSES_ACCEPTABLE.push BigFloat if defined? BigFloat
|
156
|
-
|
157
|
-
# Unary Operator: Plus
|
158
|
-
def +@
|
159
|
-
self
|
160
|
-
end
|
161
|
-
|
162
|
-
# Unary Operator: Minus
|
163
|
-
def -@
|
164
|
-
positive? ? NEGATIVE : POSITIVE
|
165
|
-
end
|
166
|
-
|
167
|
-
def infinity?
|
168
|
-
true
|
169
|
-
end
|
170
|
-
#alias_method :infinite?, :infinity? if !self.method_defined? :infinite? # Common with Float::INFINITY
|
171
|
-
## If the alias for :infinite? is defined as above, the following would raise
|
172
|
-
# NoMethodError: undefined method `>' for true:TrueClass
|
173
|
-
# in the operation
|
174
|
-
# Float::INFINITY <=> RangeExtd::Infinity::POSITIVE
|
175
|
-
#
|
176
|
-
|
177
|
-
def positive?
|
178
|
-
@positive
|
179
|
-
end
|
180
|
-
|
181
|
-
def negative?
|
182
|
-
!@positive
|
183
|
-
end
|
184
|
-
|
185
|
-
alias_method :cmp_before_rangeextd_infinity?, :== if ! self.method_defined?(:cmp_before_rangeextd_infinity?) # No overwriting.
|
186
|
-
|
187
|
-
# Always -1 or 1 except for itself and the corresponding infinities (== 0). See {#==}.
|
188
|
-
# Or, nil (as defined by Object), if the argument is not Comparable, such as, nil and IO.
|
189
|
-
#
|
190
|
-
# @return [Integer, nil]
|
191
|
-
def <=>(c)
|
192
|
-
if c.nil? || !c.class.method_defined?(:<=) # Not Comparable?
|
193
|
-
nil
|
194
|
-
elsif c == Float::INFINITY
|
195
|
-
nil # Special case.
|
196
|
-
else
|
197
|
-
(self == c) ? 0 : (@positive ? 1 : -1)
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
alias_method :greater_than_before_rangeextd_infinity?, :> if ! self.method_defined?(:greater_than_before_rangeextd_infinity?) # No overwriting.
|
202
|
-
# Special case for Float::INFINITY
|
203
|
-
#
|
204
|
-
# (Float::INFINITY > RangeExtd::Infinity::POSITIVE)
|
205
|
-
# raises ArgumentError and so does this method.
|
206
|
-
def >(c)
|
207
|
-
((c.abs rescue c) == Float::INFINITY) ? raise(ArgumentError, "RangeExtd::Infinity object not comparable with '#{__method__}' with Float::INFINITY") : greater_than_before_rangeextd_infinity?(c)
|
208
|
-
end
|
209
|
-
|
210
|
-
alias_method :less_than_before_rangeextd_infinity?, :< if ! self.method_defined?(:less_than_before_rangeextd_infinity?) # No overwriting.
|
211
|
-
# Special case for Float::INFINITY
|
212
|
-
#
|
213
|
-
# (Float::INFINITY > RangeExtd::Infinity::POSITIVE)
|
214
|
-
# raises ArgumentError and so does this method.
|
215
|
-
def <(c)
|
216
|
-
((c.abs rescue c) == Float::INFINITY) ? raise(ArgumentError, "RangeExtd::Infinity object not comparable with '#{__method__}' with Float::INFINITY") : less_than_before_rangeextd_infinity?(c)
|
217
|
-
end
|
218
|
-
|
219
|
-
# Always false except for itself and the corresponding {Float::INFINITY}
|
220
|
-
# and those that have methods of {#infinity?} and {#positive?}
|
221
|
-
# with the corresponding true/false values, in which case this returns true.
|
222
|
-
def ==(c)
|
223
|
-
if (Infinity === c)
|
224
|
-
(@positive ^! c.positive?) # It should be OK to compare object_id?
|
225
|
-
#elsif c == FLOAT_INFINITY && @positive
|
226
|
-
# true
|
227
|
-
#elsif c == -FLOAT_INFINITY && !@positive
|
228
|
-
# true
|
229
|
-
elsif defined?(c.infinity?) && defined?(c.positive?)
|
230
|
-
(c.infinity? && (@positive ^! c.positive?))
|
231
|
-
else
|
232
|
-
false
|
233
|
-
end
|
234
|
-
end
|
235
|
-
|
236
|
-
# Equivalent to {#==}
|
237
|
-
def ===(c)
|
238
|
-
self == c
|
239
|
-
end
|
240
|
-
|
241
|
-
# @return [Infinity] self
|
242
|
-
def succ
|
243
|
-
self
|
244
|
-
end
|
245
|
-
|
246
|
-
# @return [String]
|
247
|
-
def inspect
|
248
|
-
if @positive
|
249
|
-
"INFINITY"
|
250
|
-
else
|
251
|
-
"-INFINITY"
|
252
|
-
end
|
253
|
-
end
|
254
|
-
|
255
|
-
alias_method :to_s, :inspect
|
256
|
-
|
257
|
-
|
258
|
-
# Overwrite [#<=>] method of the given class, if necessary,
|
259
|
-
# to make its instances be comparable with RangeExtd::Infinity objects (constants).
|
260
|
-
# For example,
|
261
|
-
# RangeExtd::Infinity::NEGATIVE.<=>(any_comparable)
|
262
|
-
# always gives back -1 (except for same infinities). However the other way around,
|
263
|
-
# SomeClass.new.<=>(RangeExtd::Infinity::NEGATIVE)
|
264
|
-
# usually returns nil, which is not handy.
|
265
|
-
# Therefore, this function (Class method) provides a convenient
|
266
|
-
# way to overcome it, that is, if the given class
|
267
|
-
# (or the class of the given object) is Comparable,
|
268
|
-
# its [#<=>] method is modified (and true is returned),
|
269
|
-
# unless it has been already done so, or some classes as listed below,
|
270
|
-
# such as Numeric and String, in which case nil is returned.
|
271
|
-
# If it is not Comparable, false is returned.
|
272
|
-
# The judgement whether it is Comparable or not is based
|
273
|
-
# whether the class has an instance method ThatClass#<=
|
274
|
-
#
|
275
|
-
# In processing, this method first looks up at an Array
|
276
|
-
# {RangeExtd::Infinity::CLASSES_ACCEPTABLE},
|
277
|
-
# and if the given class is registered in it,
|
278
|
-
# it does nothing. If not, and if all the othe conditions
|
279
|
-
# are met, it overwrites its <=> method and register
|
280
|
-
# the class in the array.
|
281
|
-
#
|
282
|
-
# @param obj [Object] Either Class or its object.
|
283
|
-
# @return [Boolean, nil] (see the description).
|
284
|
-
def self.overwrite_compare(obj)
|
285
|
-
if defined? obj.instance_methods
|
286
|
-
klass = obj
|
287
|
-
else
|
288
|
-
klass = obj.class
|
289
|
-
|
290
|
-
begin
|
291
|
-
_ = 1.0 + obj # Use "rescue ArgumentError" if using "1.0<obj"
|
292
|
-
return nil # No change for Numeric
|
293
|
-
rescue TypeError
|
294
|
-
end
|
295
|
-
end # if defined? obj.instance_methods
|
296
|
-
|
297
|
-
# [Numeric, Fixnum, Bignum, Float, Rational, String, Complex].each do |i| # , BigFloat
|
298
|
-
(self::CLASSES_ACCEPTABLE+[self]).each do |i| # , BigFloat
|
299
|
-
# The class itself (RangeExtd::Infinity) must be rejected!
|
300
|
-
# Otherwise the rewrites itself, and may cause an infinite loop.
|
301
|
-
# In fact it is pre-defined in RangeExtd::Infinity, so the above addition is a duplication - just to make sure.
|
302
|
-
return nil if i == klass # No change for Numeric etc
|
303
|
-
# Built-in String, Numeric etc try to flip over "<=>" if it doesn't know the object!
|
304
|
-
end
|
305
|
-
self::CLASSES_ACCEPTABLE.push(klass) # The class is registered, so it would not come here again for the class.
|
306
|
-
|
307
|
-
a = klass.instance_methods
|
308
|
-
if !a.include?( :<= ) # NOT Comparable
|
309
|
-
return false
|
310
|
-
elsif a.include?(:compare_before_infinity)
|
311
|
-
return nil
|
312
|
-
else
|
313
|
-
# Overwrite the definition of "<=>" so that it is fliped over for Infinity.
|
314
|
-
|
315
|
-
code = <<__EOF__
|
316
|
-
alias_method :compare_before_infinity, :<=> if ! self.method_defined?(:compare_before_infinity)
|
317
|
-
def <=>(c)
|
318
|
-
if defined?(self.<=) && RangeExtd::Infinity === c
|
319
|
-
if defined?(self.infinity?) && defined?(self.positive?)
|
320
|
-
if (self.positive? ^! c.positive?)
|
321
|
-
0
|
322
|
-
elsif self.positive?
|
323
|
-
1
|
324
|
-
else
|
325
|
-
-1
|
326
|
-
end
|
327
|
-
else
|
328
|
-
if c.positive?
|
329
|
-
-1
|
330
|
-
else
|
331
|
-
1
|
332
|
-
end
|
333
|
-
end
|
334
|
-
else
|
335
|
-
compare_before_infinity(c)
|
336
|
-
end
|
337
|
-
end
|
338
|
-
__EOF__
|
339
|
-
#<<__EOF__ # for Emacs hilit.
|
340
|
-
|
341
|
-
klass.class_eval(code)
|
342
|
-
|
343
|
-
true
|
344
|
-
end
|
345
|
-
end # def self.overwrite_compare(obj)
|
346
|
-
|
347
|
-
# True if obj is a kind of Infinity like this class
|
348
|
-
#
|
349
|
-
# This is similar to the following, but is in a duck-typing way:
|
350
|
-
#
|
351
|
-
# RangeExtd::Infinity === obj
|
352
|
-
#
|
353
|
-
# Note that this returns false for Float::INFINITY.
|
354
|
-
# If you want true for Float::INFINITY, use {RangeExtd::Infinity.infinite?} instead.
|
355
|
-
#
|
356
|
-
# @param obj [Object]
|
357
|
-
def self.infinity?(obj)
|
358
|
-
kl = obj.class
|
359
|
-
kl.method_defined?(:infinity?) && kl.method_defined?(:positive?) && kl.method_defined?(:negative?)
|
360
|
-
end
|
361
|
-
|
362
|
-
# True if obj is either Float::INFINITY or Infinity type.
|
363
|
-
#
|
364
|
-
# Note +Float#infinite?+ is defined - how to memorise this method name.
|
365
|
-
#
|
366
|
-
# @param obj [Object]
|
367
|
-
def self.infinite?(obj)
|
368
|
-
kl = obj.class
|
369
|
-
(kl.method_defined?(:infinite?) && obj.infinite?) || (kl.method_defined?(:infinity?) && obj.infinity?)
|
370
|
-
end
|
371
|
-
|
372
|
-
######################################
|
373
|
-
# Special tricky routine below. Do not rouch!
|
374
|
-
######################################
|
375
|
-
|
376
|
-
private
|
377
|
-
|
378
|
-
def initialize(t)
|
379
|
-
@positive = (t && true)
|
380
|
-
end
|
381
|
-
|
382
|
-
NEGATIVE = new(false)
|
383
|
-
POSITIVE = new(true)
|
384
|
-
|
385
|
-
#NEGATIVE.freeze
|
386
|
-
#POSITIVE.freeze
|
387
|
-
|
388
|
-
end # class Infinity
|
389
|
-
|
390
|
-
|
391
|
-
class Infinity
|
392
|
-
# Disable new() so no other object will be created.
|
393
|
-
private_class_method :new
|
394
|
-
|
395
|
-
######################################
|
396
|
-
# Special tricky routine below. Do not rouch!
|
397
|
-
######################################
|
398
|
-
|
399
|
-
warn_level = $VERBOSE
|
400
|
-
begin
|
401
|
-
$VERBOSE = nil # Suppress the warning in the following line.
|
402
|
-
remove_method :initialize
|
403
|
-
ensure
|
404
|
-
$VERBOSE = warn_level
|
405
|
-
end
|
406
|
-
#undef_method :initialize
|
407
|
-
|
408
|
-
end # class Infinity
|
409
|
-
|
410
|
-
end # class RangeExtd < Range
|
411
|
-
|
412
|
-
|
413
|
-
#
|
414
|
-
# = class Object
|
415
|
-
#
|
416
|
-
# Overwrite {Object#<=>}() so all its sub-classes can be
|
417
|
-
# aware of {RangeExtd::Infinity} objects (the two constants).
|
418
|
-
#
|
419
|
-
class Object
|
420
|
-
alias_method :compare_obj_before_infinity, :<=> if ! self.method_defined?(:compare_obj_before_infinity) # No overwriting.
|
421
|
-
|
422
|
-
# Overwrite {Object#<=>}(). Then, all its sub-classes can be
|
423
|
-
# aware of RangeExtd::Infinity objects (the two constants).
|
424
|
-
#
|
425
|
-
# In this definition of {#<=>}, if self is Comparable
|
426
|
-
# (by judging whether it has the method [#<=]),
|
427
|
-
# it always returns, unless infinity? and positive? are set
|
428
|
-
# accordingly, either -1 or 1, depending which of
|
429
|
-
# RangeExtd::Infinity::(NEGATIVE|POSITIVE)
|
430
|
-
# is compared. If self is not Comparable, the original [#<=>]
|
431
|
-
# is called, which should return nil (unless both the object_id
|
432
|
-
# agree, eg., nil and nil, in which case 0 is returned).
|
433
|
-
#
|
434
|
-
# If you define your own class, which is Comparable, you should
|
435
|
-
# define the method "<=>" as follows, as in the standard practice
|
436
|
-
# when you redefine a method that exists in a superclass;
|
437
|
-
#
|
438
|
-
# @example A method definition of user-defined Comparable class
|
439
|
-
# class MyComparableClass
|
440
|
-
# include Comparable
|
441
|
-
# # alias :cmp_orig :<=> if !self.method_defined?(:cmp_orig) # if you want
|
442
|
-
# def <=>(c)
|
443
|
-
# if c._is_what_i_expect?
|
444
|
-
# # Write your definition.
|
445
|
-
# else # When self does not know what to do with c.
|
446
|
-
# super c # to call Object#<=>
|
447
|
-
# end
|
448
|
-
# end
|
449
|
-
# end
|
450
|
-
#
|
451
|
-
def <=>(c)
|
452
|
-
return (-(c.send(__method__, self) || return)) if RangeExtd::Infinity.infinity? c
|
453
|
-
compare_obj_before_infinity(c)
|
454
|
-
end # def <=>(c)
|
455
|
-
end # class Object
|
456
|
-
|
457
|
-
|
458
|
-
#
|
459
|
-
# = class Numeric
|
460
|
-
#
|
461
|
-
# Modify {Numeric#>} and {Numeric#<} because +5 < RangeExtd::Infinity::POSITIVE+
|
462
|
-
# raises ArgumentError(!). In other words, +Integer#<+ does not respect
|
463
|
-
# +Object#<=>+ but rewrites it.
|
464
|
-
#
|
465
|
-
# I do not know if it has been always the case, or some changes have been made
|
466
|
-
# in more recent versions of Ruby.
|
467
|
-
#
|
468
|
-
# Note that +Float#<+ etc need to be redefined individually, because they seem
|
469
|
-
# not to use +Numeric#<+ any more.
|
470
|
-
class Numeric
|
471
|
-
|
472
|
-
alias_method :compare_than_numeric_before_infinity?, :<=> if ! self.method_defined?(:compare_than_numeric_before_infinity?) # No overwriting.
|
473
|
-
# Special case for comparison with a {RangeExtd::Infinity} instance.
|
474
|
-
def <=>(c)
|
475
|
-
# Default if the special case INFINITY.
|
476
|
-
return compare_than_numeric_before_infinity?(c) if ((abs rescue self) == Float::INFINITY)
|
477
|
-
|
478
|
-
return (-(c.send(__method__, self) || return)) if RangeExtd::Infinity.infinity? c
|
479
|
-
compare_than_numeric_before_infinity?(c)
|
480
|
-
end
|
481
|
-
|
482
|
-
alias_method :greater_than_numeric_before_infinity?, :> if ! self.method_defined?(:greater_than_numeric_before_infinity?) # No overwriting.
|
483
|
-
# Special case for comparison with a {RangeExtd::Infinity} instance.
|
484
|
-
def >(c)
|
485
|
-
# Default if self is Complex or something not Integer, Rational, Float or alike
|
486
|
-
# or the special case INFINITY.
|
487
|
-
return greater_than_numeric_before_infinity?(c) if !self.class.method_defined?(:>) || ((abs rescue self) == Float::INFINITY)
|
488
|
-
|
489
|
-
if RangeExtd::Infinity.infinity? c
|
490
|
-
c.negative?
|
491
|
-
else
|
492
|
-
greater_than_numeric_before_infinity?(c)
|
493
|
-
end
|
494
|
-
end
|
495
|
-
|
496
|
-
alias_method :less_than_numeric_before_infinity?, :< if ! self.method_defined?(:less_than_numeric_before_infinity?) # No overwriting.
|
497
|
-
# Special case for comparison with a {RangeExtd::Infinity} instance.
|
498
|
-
def <(c)
|
499
|
-
# Default if self is Complex or something not Integer, Rational, Float or alike
|
500
|
-
# or the special case INFINITY.
|
501
|
-
return less_than_numeric_before_infinity?(c) if !self.class.method_defined?(:>) || ((abs rescue self) == Float::INFINITY)
|
502
|
-
|
503
|
-
if RangeExtd::Infinity.infinity? c
|
504
|
-
c.positive?
|
505
|
-
else
|
506
|
-
less_than_numeric_before_infinity?(c)
|
507
|
-
end
|
508
|
-
end
|
509
|
-
end # class Numeric
|
510
|
-
|
511
|
-
|
512
|
-
#
|
513
|
-
# = class Float
|
514
|
-
#
|
515
|
-
# The same as {Numeric#>} and {Numeric#<}. See them for the background.
|
516
|
-
class Float
|
517
|
-
|
518
|
-
alias_method :compare_than_float_before_infinity?, :<=> if ! self.method_defined?(:compare_than_float_before_infinity?) # No overwriting.
|
519
|
-
# Special case for comparison with a {RangeExtd::Infinity} instance.
|
520
|
-
def <=>(c)
|
521
|
-
# Default if the special case INFINITY.
|
522
|
-
return compare_than_float_before_infinity?(c) if ((abs rescue self) == Float::INFINITY)
|
523
|
-
|
524
|
-
return (-(c.send(__method__, self) || return)) if RangeExtd::Infinity.infinity? c
|
525
|
-
compare_than_float_before_infinity?(c)
|
526
|
-
end
|
527
|
-
|
528
|
-
alias_method :greater_than_float_before_infinity?, :> if ! self.method_defined?(:greater_than_float_before_infinity?) # No overwriting.
|
529
|
-
# Special case for comparison with a {RangeExtd::Infinity} instance.
|
530
|
-
def >(c)
|
531
|
-
# Default if self is Complex or something not Integer, Rational, Float or alike
|
532
|
-
# or the special case INFINITY.
|
533
|
-
return greater_than_float_before_infinity?(c) if ((abs rescue self) == Float::INFINITY)
|
534
|
-
|
535
|
-
if RangeExtd::Infinity.infinity? c
|
536
|
-
c.negative?
|
537
|
-
else
|
538
|
-
greater_than_float_before_infinity?(c)
|
539
|
-
end
|
540
|
-
end
|
541
|
-
|
542
|
-
alias_method :less_than_float_before_infinity?, :< if ! self.method_defined?(:less_than_float_before_infinity?) # No overwriting.
|
543
|
-
# Special case for comparison with a {RangeExtd::Infinity} instance.
|
544
|
-
def <(c)
|
545
|
-
# Default if self is Complex or something not Integer, Rational, Float or alike
|
546
|
-
# or the special case INFINITY.
|
547
|
-
return less_than_float_before_infinity?(c) if ((abs rescue self) == Float::INFINITY)
|
548
|
-
|
549
|
-
if RangeExtd::Infinity.infinity? c
|
550
|
-
c.positive?
|
551
|
-
else
|
552
|
-
less_than_float_before_infinity?(c)
|
553
|
-
end
|
554
|
-
end
|
555
|
-
end # class Float
|
556
|
-
|
557
|
-
|
558
|
-
#
|
559
|
-
# = class Integer
|
560
|
-
#
|
561
|
-
# The same as {Numeric#>} and {Numeric#<}. See them for the background.
|
562
|
-
class Integer
|
563
|
-
|
564
|
-
alias_method :compare_than_integer_before_infinity?, :<=> if ! self.method_defined?(:compare_than_integer_before_infinity?) # No overwriting.
|
565
|
-
# Special case for comparison with a {RangeExtd::Infinity} instance.
|
566
|
-
def <=>(c)
|
567
|
-
# Default if the special case INFINITY (never happens in Default, but a user may define Integer::INFINITY).
|
568
|
-
return compare_than_integer_before_infinity?(c) if ((abs rescue self) == Float::INFINITY)
|
569
|
-
|
570
|
-
return (-(c.send(__method__, self) || return)) if RangeExtd::Infinity.infinity? c
|
571
|
-
compare_than_integer_before_infinity?(c)
|
572
|
-
end
|
573
|
-
|
574
|
-
alias_method :greater_than_integer_before_infinity?, :> if ! self.method_defined?(:greater_than_integer_before_infinity?) # No overwriting.
|
575
|
-
# Special case for comparison with a {RangeExtd::Infinity} instance.
|
576
|
-
def >(c)
|
577
|
-
# Default if self is not comparable (in case the Integer method is redifined by a user).
|
578
|
-
return greater_than_integer_before_infinity?(c) if !self.class.method_defined?(:>)
|
579
|
-
|
580
|
-
if RangeExtd::Infinity.infinity? c
|
581
|
-
c.negative?
|
582
|
-
else
|
583
|
-
greater_than_integer_before_infinity?(c)
|
584
|
-
end
|
585
|
-
end
|
586
|
-
|
587
|
-
alias_method :less_than_integer_before_infinity?, :< if ! self.method_defined?(:less_than_integer_before_infinity?) # No overwriting.
|
588
|
-
# Special case for comparison with a {RangeExtd::Infinity} instance.
|
589
|
-
def <(c)
|
590
|
-
# Default if self is not comparable (in case the Integer method is redifined by a user).
|
591
|
-
return less_than_integer_before_infinity?(c) if !self.class.method_defined?(:>)
|
592
|
-
|
593
|
-
if RangeExtd::Infinity.infinity? c
|
594
|
-
c.positive?
|
595
|
-
else
|
596
|
-
less_than_integer_before_infinity?(c)
|
597
|
-
end
|
598
|
-
end
|
599
|
-
end # class Integer
|
600
|
-
|