In Files

Parent

Included Modules

Class Index [+]

Quicksearch

Flt::FloatContext

Context class with some of the Flt::Num context functionality, to allow the use of Float numbers similarly to other Num values; this eases the implementation of functions compatible with either Num or Float values.

Public Class Methods

neighbours(x) click to toggle source

Compute the adjacent floating point values: largest value not larger than this and smallest not smaller.

     # File lib/flt/float.rb, line 386
386:     def neighbours(x)
387:       f,e = Math.frexp(x.to_f)
388:       e = Float::MIN_EXP if f==0
389:       e = [Float::MIN_EXP,e].max
390:       dx = Math.ldexp(1,e-Float::MANT_DIG) #Math.ldexp(Math.ldexp(1.0,-Float::MANT_DIG),e)
391: 
392:       min_f = 0.5 #0.5==Math.ldexp(2**(bits-1),-Float::MANT_DIG)
393:       max_f = 1.0 - Math.ldexp(1,-Float::MANT_DIG)
394: 
395:       if f==max_f
396:         high = x + dx*2
397:       elsif f==-min_f && e!=Float::MIN_EXP
398:         high = x + dx/2
399:       else
400:         high = x + dx
401:       end
402:       if e==Float::MIN_EXP || f!=min_f
403:         low = x - dx
404:       elsif f==-max_f
405:         high = x - dx*2
406:       else
407:         low = x - dx/2
408:       end
409:       [low, high]
410:     end

Public Instance Methods

Num(*args) click to toggle source
     # File lib/flt/float.rb, line 99
 99:   def Num(*args)
100:     args.flatten!
101:     case args.size
102:     when 1
103:       Float(*args)
104:     when 2
105:       Math.ldexp(args[0],args[1])
106:     when 3
107:       Math.ldexp(args[0]*args[1],args[2])
108:     end
109:   end
copy_sign(x, y) click to toggle source

Return copy of x with the sign of y

     # File lib/flt/float.rb, line 274
274:   def copy_sign(x, y)
275:     self_sign = sign(x)
276:     other_sign = y.is_a?(Integer) ? (y < 0 ? 1 : 1) : sign(y)
277:     if self_sign && other_sign
278:       if self_sign == other_sign
279:         x.to_f
280:       else
281:         -x.to_f
282:       end
283:     else
284:       nan
285:     end
286:   end
emax() click to toggle source
     # File lib/flt/float.rb, line 228
228:   def emax
229:     Float::MAX_EXP-1
230:   end
emin() click to toggle source
     # File lib/flt/float.rb, line 224
224:   def emin
225:     Float::MIN_EXP-1
226:   end
epsilon(sign=+1) click to toggle source

This is the difference between 1.0 and the smallest floating-point value greater than 1.0, radix_power(1-significand_precision)

We have:

  Float.epsilon == (1.0.next-1.0)
     # File lib/flt/float.rb, line 139
139:   def epsilon(sign=1)
140:     (sign < 0) ? -Float::EPSILON : Float::EPSILON
141:   end
etiny() click to toggle source
     # File lib/flt/float.rb, line 232
232:   def etiny
233:     Float::MIN_EXP - Float::MANT_DIG
234:   end
etop() click to toggle source
     # File lib/flt/float.rb, line 236
236:   def etop
237:     Float::MAX_EXP - Float::MANT_DIG
238:   end
eval() click to toggle source
     # File lib/flt/float.rb, line 465
465:   def eval
466:     yield self
467:   end
exact?() click to toggle source
     # File lib/flt/float.rb, line 215
215:   def exact?
216:     false
217:   end
half_epsilon(sign=+1) click to toggle source

This is the maximum relative error corresponding to 1/2 ulp:

 (radix/2)*radix_power(-significand_precision) == epsilon/2

This is called “machine epsilon” in [Goldberg] We have:

 Float.half_epsilon == 0.5*Float.epsilon
     # File lib/flt/float.rb, line 177
177:   def half_epsilon(sign=1)
178:     # 0.5*epsilon(sign)
179:     f,e = Math.frexp(1)
180:     Math.ldexp(f, e-Float::MANT_DIG)
181:   end
infinity(sign=+1) click to toggle source

infinity value with specified sign

     # File lib/flt/float.rb, line 126
126:   def infinity(sign=1)
127:     (sign < 0) ? 1.0/0.0 : 1.0/0.0 # Ruby 1.9.2: (sing < 0) ? -Float::INFINITY : Float::INFINITY
128:   end
int_radix_power(n) click to toggle source
     # File lib/flt/float.rb, line 130
130:   def int_radix_power(n)
131:     1 << n
132:   end
ln(x) click to toggle source
     # File lib/flt/float.rb, line 457
457:   def ln(x)
458:     log(x)
459:   end
math(*parameters, &blk) click to toggle source
     # File lib/flt/float.rb, line 469
469:   def math(*parameters, &blk)
470:     if parameters.empty?
471:       self.instance_eval &blk
472:     else
473:       # needs instance_exe (available in Ruby 1.9, ActiveRecord; TODO: include implementation here)
474:       self.instance_exec *parameters, &blk
475:     end
476:   end
maximum_coefficient() click to toggle source
     # File lib/flt/float.rb, line 207
207:   def maximum_coefficient
208:     int_radix_power(precision)-1
209:   end
maximum_finite(sign=+1) click to toggle source

maximum finite Float value, with specified sign

     # File lib/flt/float.rb, line 199
199:   def maximum_finite(sign=1)
200:     (sign < 0) ? -Float::MAX : Float::MAX
201:   end
maximum_subnormal(sign=+1) click to toggle source

maximum subnormal (denormalized) Float value (with specified sign)

     # File lib/flt/float.rb, line 189
189:   def maximum_subnormal(sign=1)
190:     (sign < 0) ? -Float::MAX_D : Float::MAX_D
191:   end
minimum_nonzero(sign=+1) click to toggle source

minimum (subnormal) nonzero Float value, with specified sign

     # File lib/flt/float.rb, line 194
194:   def minimum_nonzero(sign=1)
195:     (sign < 0) ? -Float::MIN_D : Float::MIN_D
196:   end
minimum_normal(sign=+1) click to toggle source

minimum normal Float value (with specified sign)

     # File lib/flt/float.rb, line 184
184:   def minimum_normal(sign=1)
185:     (sign < 0) ? -Float::MIN_N : Float::MIN_N
186:   end
minimum_normalized_coefficient() click to toggle source
     # File lib/flt/float.rb, line 211
211:   def minimum_normalized_coefficient
212:     num_class.int_radix_power(precision-1)
213:   end
minus(x) click to toggle source
     # File lib/flt/float.rb, line 379
379:   def minus(x)
380:     -x.to_f
381:   end
nan() click to toggle source

NaN (not a number value)

     # File lib/flt/float.rb, line 116
116:   def nan
117:     0.0/0.0 # Ruby 1.9.2: Float::NAN
118:   end
next_minus(x) click to toggle source
     # File lib/flt/float.rb, line 244
244:   def next_minus(x)
245:     Flt::FloatContext.neighbours(x).first
246:   end
next_plus(x) click to toggle source
     # File lib/flt/float.rb, line 240
240:   def next_plus(x)
241:     Flt::FloatContext.neighbours(x).last
242:   end
next_toward(x, y) click to toggle source
     # File lib/flt/float.rb, line 248
248:   def next_toward(x, y)
249:     x, y = x.to_f, y.to_f
250:     comparison = x <=> y
251:     return x.copy_sign(y) if comparison == 0
252:     if comparison == 1
253:       result = x.next_plus(context)
254:     else # comparison == 1
255:       result = x.next_minus(context)
256:     end
257:   end
normal?(x) click to toggle source
     # File lib/flt/float.rb, line 359
359:   def normal?(x)
360:     if x.special? || x.zero?
361:       false
362:     else
363:       x.abs >= Float::MIN_N
364:     end
365:   end
num_class() click to toggle source
    # File lib/flt/float.rb, line 95
95:   def num_class
96:     Float
97:   end
pi() click to toggle source
     # File lib/flt/float.rb, line 461
461:   def pi
462:     Float::PI
463:   end
plus(x) click to toggle source
     # File lib/flt/float.rb, line 375
375:   def plus(x)
376:     x.to_f
377:   end
precision() click to toggle source
     # File lib/flt/float.rb, line 203
203:   def precision
204:     Float::MANT_DIG
205:   end
radix() click to toggle source
     # File lib/flt/float.rb, line 111
111:   def radix
112:     Float::RADIX
113:   end
rounding() click to toggle source

detect actual rounding mode

     # File lib/flt/float.rb, line 220
220:   def rounding
221:     Flt::Support::AuxiliarFunctions.detect_float_rounding
222:   end
sign(x) click to toggle source

Sign: -1 for minus, +1 for plus, nil for nan (note that Float zero is signed)

     # File lib/flt/float.rb, line 260
260:   def sign(x)
261:     x = x.to_f
262:     if x.nan?
263:       nil
264:     elsif x.zero?
265:       # Note that (x.to_s[0,1] == "-" ? -1 : +1) fails under mswin32
266:       # because in that platform (-0.0).to_s == '0.0'
267:       (1/x < 0) ? 1 : 1
268:     else
269:       x < 0 ? 1 : 1
270:     end
271:   end
special?(x) click to toggle source
     # File lib/flt/float.rb, line 355
355:   def special?(x)
356:     x.nan? || x.infinite?
357:   end
split(x) click to toggle source

Returns the internal representation of the number, composed of:

  • a sign which is +1 for plus and -1 for minus

  • a coefficient (significand) which is a nonnegative integer

  • an exponent (an integer) or :inf, :nan or :snan for special values

The value of non-special numbers is sign*coefficient*10^exponent

     # File lib/flt/float.rb, line 293
293:   def split(x)
294:     x = x.to_f
295:     sign = sign(x)
296:     if x.nan?
297:       exp = :nan
298:     elsif x.infinite?
299:       exp = :inf
300:     else
301:       coeff,exp = Math.frexp(x)
302:       coeff = coeff.abs
303:       if exp < Float::MIN_EXP
304:         # denormalized number
305:         coeff = Math.ldexp(coeff, exp-Float::MIN_EXP+Float::MANT_DIG).to_i
306:         exp = Float::MIN_EXP-Float::MANT_DIG
307:       else
308:         # normalized number
309:         coeff = Math.ldexp(coeff, Float::MANT_DIG).to_i
310:         exp -= Float::MANT_DIG
311:       end
312:     end
313:     [sign, coeff, exp]
314:   end
strict_epsilon(sign=+1, round=nil) click to toggle source

The strict epsilon is the smallest value that produces something different from 1.0 wehen added to 1.0. It may be smaller than the general epsilon, because of the particular rounding rules used with the floating point format. This is only meaningful when well-defined rules are used for rounding the result of floating-point addition.

We have:

  (Float.strict_epsilon+1.0) == 1.0.next
  (Float.strict_epsilon.prev+1.0) == 1.0
     # File lib/flt/float.rb, line 152
152:   def strict_epsilon(sign=1, round=nil)
153:     # We don't rely on Float::ROUNDS
154:     eps = minimum_nonzero
155:     unless (1.0+eps) > 1.0
156:       f,e = Math.frexp(1)
157:       eps = Math.ldexp(f.next,e-Float::MANT_DIG)
158:       if (1.0+eps) > 1.0
159:         eps
160:       else
161:         eps = Math.ldexp(f,e-Float::MANT_DIG)
162:         unless (1.0+eps) > 1.0
163:         else
164:           eps = Math.ldexp(f,e-Float::MANT_DIG+1)
165:         end
166:       end
167:     end
168:     eps
169:   end
subnormal?() click to toggle source
     # File lib/flt/float.rb, line 367
367:   def subnormal?
368:     if x.special? || x.zero?
369:       false
370:     else
371:       x.abs < Float::MIN_N
372:     end
373:   end
to_int_scale(x) click to toggle source

Return the value of the number as an signed integer and a scale.

     # File lib/flt/float.rb, line 317
317:   def to_int_scale(x)
318:     x = x.to_f
319:     if special?(x)
320:       nil
321:     else
322:       coeff,exp = Math.frexp(x)
323:       coeff = coeff
324:       if exp < Float::MIN_EXP
325:         # denormalized number
326:         coeff = Math.ldexp(coeff, exp-Float::MIN_EXP+Float::MANT_DIG).to_i
327:         exp = Float::MIN_EXP-Float::MANT_DIG
328:       else
329:         # normalized number
330:         coeff = Math.ldexp(coeff, Float::MANT_DIG).to_i
331:         exp -= Float::MANT_DIG
332:       end
333:       [coeff, exp]
334:     end
335:   end
ulp(x, mode=:low) click to toggle source

ulp (unit in the last place) according to the definition proposed by J.M. Muller in “On the definition of ulp(x)” INRIA No. 5504

     # File lib/flt/float.rb, line 339
339:   def ulp(x, mode=:low)
340:     x = x.to_f
341:     return x if x.nan?
342:     x = x.abs
343:     if x < Math.ldexp(1,Float::MIN_EXP) # x < Float::RADIX*Float::MIN_N
344:       x = Math.ldexp(1,Float::MIN_EXP-Float::MANT_DIG) # res = Float::MIN_D
345:     elsif x > Float::MAX # x > Math.ldexp(1-Math.ldexp(1,-Float::MANT_DIG),Float::MAX_EXP)
346:       x = Math.ldexp(1,Float::MAX_EXP-Float::MANT_DIG) # res = Float::MAX - Float::MAX.prev
347:     else
348:       f,e = Math.frexp(x.to_f)
349:       e -= 1 if f==Math.ldexp(1,1) if mode==:low # assign the smaller ulp to radix powers
350:       x = Math.ldexp(1,e-Float::MANT_DIG)
351:     end
352:     x
353:   end
zero(sign=+1) click to toggle source

zero value with specified sign

     # File lib/flt/float.rb, line 121
121:   def zero(sign=1)
122:     (sign < 0) ? 0.0 : 0.0
123:   end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.