Class | AppMath::Iv |
In: |
interval.rb
|
Parent: | Object |
Class of real closed intervals. In most applications of intervals it is an advantage if single real values can be considered as intervals of length zero. This is possible only for closed intervals, and this is the rational for defining those in preference to open intervals. With the attributes @low and @upp, the values x which belong to interval are characterized by the formula
@low <= x <= @upp .
Hence the interval is empty (void) iff @low > @upp.
low | [R] | |
upp | [R] |
using max and min of an array for defining an interval. The values of the array components are then known to belong to to a closed interval. The smallest such interval is what his method returns.
# File interval.rb, line 81 81: def Iv.from_array(anArray) 82: n = anArray.size 83: case n 84: when 0 85: Iv.new 86: when 1 87: a0 = anArray[0] 88: Iv.new(a0) 89: else 90: x0 = anArray[0] 91: x1 = x0 92: anArray.each{ |x| 93: if x < x0 94: x0 = x 95: elsif x > x1 96: x1 = x 97: else 98: end 99: } 100: Iv.new(x0,x1) 101: end 102: end
Allowed are 0, 1, 2 arguments, which all have to be convertible to R. For no argument the empty interval is created. For one argument, an second argument 0 is understood. For two arguments, these are the boundaries of the interval and the order on input does not matter:
iv1 = Iv.new(2,3); iv2 = Iv.new(3,2)
are thus the same, non-empty, interval, which in mathematical notation would be
[2,3]
Finally
iv3 = Iv.new
is an empty interval.
# File interval.rb, line 44 44: def initialize(*arg) 45: n = arg.size 46: case n 47: when 0 48: @low = R.c1 49: @upp = R.c0 # notice: epmpty since @low > @upp 50: when 1 51: x = R.c arg[0] 52: zero = R.c0 53: if x < zero 54: @low = x 55: @upp = zero 56: else 57: @upp = x 58: @low = zero 59: end 60: when 2 61: x = R.c arg[0] 62: y = R.c arg[1] 63: if x < y 64: @low = x 65: @upp = y 66: else 67: @low = y 68: @upp = x 69: end 70: else 71: fail "Iv.new takes 0 or 1 or 2 arguments, but not " + n.to_s 72: end # case n 73: end
section, intersection meet or g.l.b (greatest lower bound) in lattice terminology
# File interval.rb, line 208 208: def &(anIv) 209: return Iv.new if empty? || anIv.empty? 210: return Iv.new if @upp < anIv.low || @low > anIv.upp 211: amin = Basics.sup(@low, anIv.low) 212: amax = Basics.inf(@upp, anIv.upp) 213: Iv.new(amin, amax) 214: end
The function creates a suitable axis sub-division for data ranging from @low to @upp. Let res be the return value of the function. Then res[0] is a proposal for the difference between adjacent axis tics and res[1] is an array of the values to which the proposed tics belong. Thus res[1].first <= @low and res[1].last >= @upp. All numbers are chosen such that they are simple when written down in normal scientific notation and the intention is to simulate the considerations that determine the axis subdivision of reasonable manually created diagrams. The argument of the function is a proposal for the number of tics to be used. Values from 5 to 10 are reasonable. To have a simple logic, we simply enforce that the interval between tics is a simple number. The initial and the final number of the axis division is chosen as an integer multiple of this inter-tic interval.
# File interval.rb, line 234 234: def axis_division(anPosInteger) 235: fail "can't divide an empty interval" if empty? 236: a = @low 237: b = @upp 238: n = anPosInteger.abs 239: n += 1 if n == 0 240: d = size/n 241: d_ = Basics.cut(d) # this is the essential point 242: fail "Zero division in function axis_division" if d_ == 0.0 243: d_inv=d_.inv; 244: epsilon = R.c 1e-6 245: k_b=(b*d_inv - epsilon).ceil 246: # without the epsilon correction it depends on roundoff 247: # errors whether b_ becomes too large 248: k_a=(a*d_inv + epsilon).floor 249: # without the epsilon correction it depends on roundoff 250: # errors whether a_ becomes too small 251: b_=k_b * d_ 252: b__ = (k_b - 0.5) * d_ 253: a_=k_a * d_ 254: res=Array.new 255: while a_ < b__ 256: res << a_ 257: a_ += d_ 258: end 259: res << b_ # we know the last item exactly, and should 260: # not spoil it by arithmetic errors 261: [ d_ , res ] 262: end
Returns the midpoint of the interval.
# File interval.rb, line 153 153: def center 154: nil if empty? 155: (@low + @upp) * R.i2 156: end
Returns true iff the interval is empty
# File interval.rb, line 136 136: def empty?; @low > @upp; end
Indicator function. Returns true if the point x belongs to self and false else.
# File interval.rb, line 166 166: def ind(x) 167: return false if empty? 168: return false if x > @upp 169: return false if x < @low 170: true 171: end
Returns the lower boundary if self is not empty and nil else.
# File interval.rb, line 140 140: def inf 141: return nil if empty? 142: @low 143: end
Metrical indicator function. Returns the distance of x from the set self if x is outside of self. If it is inside, the return value is minus the distance to the complement of self (which is not an interval but a well-defined set).
# File interval.rb, line 177 177: def met_ind(x) 178: return nil if empty? 179: y = R.c x 180: dc = (y - center).abs 181: dc - size * R.i2 182: end
Returns the length of the interval, 0 for the empty one
# File interval.rb, line 159 159: def size 160: s = @upp - @low 161: s >= R.c0 ? s : R.c0 162: end
Returns the upper boundary if self is not empty and nil else.
# File interval.rb, line 147 147: def sup 148: return nil if empty? 149: @upp 150: end
Returns an ordered equidistant array of n numbers, where the first one is @low and the last one is @upp. The positive integer n is made from the argument a in a way which depends on whether this argument is integer or not. In the first case it is taken as n and in the second case, the argment is taken as a proposal for the lattice spacing. The actual lattice spacing will be chosen as a fraction of size.
# File interval.rb, line 110 110: def to_array(a) 111: return nil if empty? 112: if a.integer? # then we interpret the argument as an intended number 113: # of lattice points 114: n = a 115: else # then we interprete the argument as an intended lattice spacing 116: d = a.abs 117: fail "can't build a lattice with spacing 0" if d.zero? 118: n = (size/d).round + 1 119: end 120: fail "number of lattice points must be larger than 1" if n < 2 121: res = Array.new 122: res << @low 123: if n > 2 124: na = n - 2 125: d = size / (n-1) 126: x = @low 127: for i in 1..na 128: x += d 129: res << x 130: end 131: end 132: res << @upp 133: end