# Class: Flt::FloatContext

Inherits:
Object
show all
Includes:
Singleton
Defined in:
lib/flt/float.rb

## Overview

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.

## Class Method Summary collapse

• :nodoc:.

• :nodoc:.

• :nodoc:.

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

## Instance Method Summary collapse

• Return copy of x with the sign of y.

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

• 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:.

• infinity value with specified sign.

• maximum finite Float value, with specified sign.

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

• minimum (subnormal) nonzero Float value, with specified sign.

• minimum normal Float value (with specified sign).

• NaN (not a number value).

• detect actual rounding mode.

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

• 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.

• The strict epsilon is the smallest value that produces something different from 1.0 wehen added to 1.0.

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

• ulp (unit in the last place) according to the definition proposed by J.M.

• zero value with specified sign.

## Class Method Details

### .float_binary_operator(method, op) ⇒ Object

:nodoc:

 ``` 446 447 448 449 450``` ```# File 'lib/flt/float.rb', line 446 def float_binary_operator(method, op) #:nodoc: define_method(method) do |x,y| x.to_f.send(op,y) end end```

### .float_method(*methods) ⇒ Object

:nodoc:

 ``` 433 434 435 436 437 438 439 440 441 442 443 444``` ```# File 'lib/flt/float.rb', line 433 def float_method(*methods) #:nodoc: methods.each do |method| if method.is_a?(Array) float_method, context_method = method else float_method = context_method = method end define_method(context_method) do |x| x.to_f.send float_method end end end```

### .math_function(*methods) ⇒ Object

:nodoc:

 ``` 452 453 454 455 456 457 458 459 460 461 462 463``` ```# File 'lib/flt/float.rb', line 452 def math_function(*methods) #:nodoc: methods.each do |method| define_method(method) do |*args| x = args.shift.to_f Math.send(method, x, *args) end # TODO: consider injecting the math methods into Float # Float.send(:define_method, method) do |*args| # Math.send(method, self, *args) # end end end```

### .neighbours(x) ⇒ Object

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

 ``` 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431``` ```# File 'lib/flt/float.rb', line 407 def neighbours(x) f,e = Math.frexp(x.to_f) e = Float::MIN_EXP if f==0 e = [Float::MIN_EXP,e].max dx = Math.ldexp(1,e-Float::MANT_DIG) #Math.ldexp(Math.ldexp(1.0,-Float::MANT_DIG),e) min_f = 0.5 #0.5==Math.ldexp(2**(bits-1),-Float::MANT_DIG) max_f = 1.0 - Math.ldexp(1,-Float::MANT_DIG) if f==max_f high = x + dx*2 elsif f==-min_f && e!=Float::MIN_EXP high = x + dx/2 else high = x + dx end if e==Float::MIN_EXP || f!=min_f low = x - dx elsif f==-max_f high = x - dx*2 else low = x - dx/2 end [low, high] end```

## Instance Method Details

### #copy_sign(x, y) ⇒ Object

Return copy of x with the sign of y

 ``` 276 277 278 279 280 281 282 283 284 285 286 287 288``` ```# File 'lib/flt/float.rb', line 276 def copy_sign(x, y) self_sign = sign(x) other_sign = y.is_a?(Integer) ? (y < 0 ? -1 : +1) : sign(y) if self_sign && other_sign if self_sign == other_sign x.to_f else -x.to_f end else nan end end```

### #emax ⇒ Object

 ``` 230 231 232``` ```# File 'lib/flt/float.rb', line 230 def emax Float::MAX_EXP-1 end```

### #emin ⇒ Object

 ``` 226 227 228``` ```# File 'lib/flt/float.rb', line 226 def emin Float::MIN_EXP-1 end```

### #epsilon(sign = +1) ⇒ Object

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)
``````
 ``` 141 142 143``` ```# File 'lib/flt/float.rb', line 141 def epsilon(sign=+1) (sign < 0) ? -Float::EPSILON : Float::EPSILON end```

### #etiny ⇒ Object

 ``` 234 235 236``` ```# File 'lib/flt/float.rb', line 234 def etiny Float::MIN_EXP - Float::MANT_DIG end```

### #etop ⇒ Object

 ``` 238 239 240``` ```# File 'lib/flt/float.rb', line 238 def etop Float::MAX_EXP - Float::MANT_DIG end```

### #eval {|_self| ... } ⇒ Object

Yields:

• (_self)

Yield Parameters:

• _self

the object that the method was called on

 ``` 486 487 488``` ```# File 'lib/flt/float.rb', line 486 def eval yield self end```

### #exact? ⇒ Boolean

Returns:

• (Boolean)
 ``` 217 218 219``` ```# File 'lib/flt/float.rb', line 217 def exact? false end```

### #half_epsilon(sign = +1) ⇒ Object

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
``````
 ``` 179 180 181 182 183``` ```# File 'lib/flt/float.rb', line 179 def half_epsilon(sign=+1) # 0.5*epsilon(sign) f,e = Math.frexp(1) Math.ldexp(f, e-Float::MANT_DIG) end```

### #infinity(sign = +1) ⇒ Object

infinity value with specified sign

 ``` 124 125 126``` ```# File 'lib/flt/float.rb', line 124 def infinity(sign=+1) (sign < 0) ? -1.0/0.0 : 1.0/0.0 # Ruby 1.9.2: (sing < 0) ? -Float::INFINITY : Float::INFINITY end```

### #int_radix_power(n) ⇒ Object

 ``` 132 133 134``` ```# File 'lib/flt/float.rb', line 132 def int_radix_power(n) 1 << n end```

### #ln(x) ⇒ Object

 ``` 478 479 480``` ```# File 'lib/flt/float.rb', line 478 def ln(x) log(x) end```

### #math(*parameters, &blk) ⇒ Object

 ``` 490 491 492 493 494 495 496 497``` ```# File 'lib/flt/float.rb', line 490 def math(*parameters, &blk) if parameters.empty? self.instance_eval(&blk) else # needs instance_exe (available in Ruby 1.9, ActiveRecord; TODO: include implementation here) self.instance_exec(*parameters, &blk) end end```

### #maximum_coefficient ⇒ Object

 ``` 209 210 211``` ```# File 'lib/flt/float.rb', line 209 def maximum_coefficient int_radix_power(precision)-1 end```

### #maximum_finite(sign = +1) ⇒ Object

maximum finite Float value, with specified sign

 ``` 201 202 203``` ```# File 'lib/flt/float.rb', line 201 def maximum_finite(sign=+1) (sign < 0) ? -Float::MAX : Float::MAX end```

### #maximum_subnormal(sign = +1) ⇒ Object

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

 ``` 191 192 193``` ```# File 'lib/flt/float.rb', line 191 def maximum_subnormal(sign=+1) (sign < 0) ? -Float::MAX_D : Float::MAX_D end```

### #minimum_nonzero(sign = +1) ⇒ Object

minimum (subnormal) nonzero Float value, with specified sign

 ``` 196 197 198``` ```# File 'lib/flt/float.rb', line 196 def minimum_nonzero(sign=+1) (sign < 0) ? -Float::MIN_D : Float::MIN_D end```

### #minimum_normal(sign = +1) ⇒ Object

minimum normal Float value (with specified sign)

 ``` 186 187 188``` ```# File 'lib/flt/float.rb', line 186 def minimum_normal(sign=+1) (sign < 0) ? -Float::MIN_N : Float::MIN_N end```

### #minimum_normalized_coefficient ⇒ Object

 ``` 213 214 215``` ```# File 'lib/flt/float.rb', line 213 def minimum_normalized_coefficient num_class.int_radix_power(precision-1) end```

### #minus(x) ⇒ Object

 ``` 381 382 383``` ```# File 'lib/flt/float.rb', line 381 def minus(x) -x.to_f end```

### #nan ⇒ Object

NaN (not a number value)

 ``` 114 115 116``` ```# File 'lib/flt/float.rb', line 114 def nan 0.0/0.0 # Ruby 1.9.2: Float::NAN end```

### #necessary_digits(b) ⇒ Object

 ``` 509 510 511 512 513 514 515 516 517``` ```# File 'lib/flt/float.rb', line 509 def necessary_digits(b) if b == 10 Float::DECIMAL_DIG elsif b == radix precision else (precision*log(radix, b)).ceil + 1 end end```

### #next_minus(x) ⇒ Object

 ``` 246 247 248``` ```# File 'lib/flt/float.rb', line 246 def next_minus(x) Flt::FloatContext.neighbours(x).first end```

### #next_plus(x) ⇒ Object

 ``` 242 243 244``` ```# File 'lib/flt/float.rb', line 242 def next_plus(x) Flt::FloatContext.neighbours(x).last end```

### #next_toward(x, y) ⇒ Object

 ``` 250 251 252 253 254 255 256 257 258 259``` ```# File 'lib/flt/float.rb', line 250 def next_toward(x, y) x, y = x.to_f, y.to_f comparison = x <=> y return x.copy_sign(y) if comparison == 0 if comparison == -1 result = x.next_plus(context) else # comparison == 1 result = x.next_minus(context) end end```

### #normal?(x) ⇒ Boolean

Returns:

• (Boolean)
 ``` 361 362 363 364 365 366 367``` ```# File 'lib/flt/float.rb', line 361 def normal?(x) if x.special? || x.zero? false else x.abs >= Float::MIN_N end end```

### #Num(*args) ⇒ Object

 ``` 97 98 99 100 101 102 103 104 105 106 107``` ```# File 'lib/flt/float.rb', line 97 def Num(*args) args.flatten! case args.size when 1 Float(*args) when 2 Math.ldexp(args[0],args[1]) when 3 Math.ldexp(args[0]*args[1],args[2]) end end```

### #num_class ⇒ Object

 ``` 93 94 95``` ```# File 'lib/flt/float.rb', line 93 def num_class Float end```

### #one_half ⇒ Object

 ``` 128 129 130``` ```# File 'lib/flt/float.rb', line 128 def one_half 0.5 end```

### #pi ⇒ Object

 ``` 482 483 484``` ```# File 'lib/flt/float.rb', line 482 def pi Math::PI end```

### #plus(x) ⇒ Object

 ``` 377 378 379``` ```# File 'lib/flt/float.rb', line 377 def plus(x) x.to_f end```

### #precision ⇒ Object

 ``` 205 206 207``` ```# File 'lib/flt/float.rb', line 205 def precision Float::MANT_DIG end```

### #radix ⇒ Object

 ``` 109 110 111``` ```# File 'lib/flt/float.rb', line 109 def radix Float::RADIX end```

### #rationalize(x, tol = Flt.Tolerance(:epsilon), strict = false) ⇒ Object

 ``` 389 390 391 392 393 394 395 396 397 398 399 400 401 402``` ```# File 'lib/flt/float.rb', line 389 def rationalize(x, tol = Flt.Tolerance(:epsilon), strict=false) if !strict && x.respond_to?(:rationalize) && !(Integer === tol) # Float#rationalize was introduced in Ruby 1.9.1 tol = Tolerance(tol) x.rationalize(tol[x]) else case tol when Integer Rational(*Support::Rationalizer.max_denominator(x, tol, Float)) else Rational(*Support::Rationalizer[tol].rationalize(x)) end end end```

### #representable_digits(b) ⇒ Object

 ``` 499 500 501 502 503 504 505 506 507``` ```# File 'lib/flt/float.rb', line 499 def representable_digits(b) if b == 10 Float::DIG elsif b == radix precision else ((precision-1)*log(radix, b)).floor end end```

### #rounding ⇒ Object

detect actual rounding mode

 ``` 222 223 224``` ```# File 'lib/flt/float.rb', line 222 def rounding Flt::Support::AuxiliarFunctions.detect_float_rounding end```

### #sign(x) ⇒ Object

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

 ``` 262 263 264 265 266 267 268 269 270 271 272 273``` ```# File 'lib/flt/float.rb', line 262 def sign(x) x = x.to_f if x.nan? nil elsif x.zero? # Note that (x.to_s[0,1] == "-" ? -1 : +1) fails under mswin32 # because in that platform (-0.0).to_s == '0.0' (1/x < 0) ? -1 : +1 else x < 0 ? -1 : +1 end end```

### #special?(x) ⇒ Boolean

Returns:

• (Boolean)
 ``` 357 358 359``` ```# File 'lib/flt/float.rb', line 357 def special?(x) x.nan? || x.infinite? end```

### #split(x) ⇒ Object

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

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

### #strict_epsilon(sign = +1, round = nil) ⇒ Object

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
``````
 ``` 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171``` ```# File 'lib/flt/float.rb', line 154 def strict_epsilon(sign=+1, round=nil) # We don't rely on Float::ROUNDS eps = minimum_nonzero unless (1.0+eps) > 1.0 f,e = Math.frexp(1) eps = Math.ldexp(f.next,e-Float::MANT_DIG) if (1.0+eps) > 1.0 eps else eps = Math.ldexp(f,e-Float::MANT_DIG) unless (1.0+eps) > 1.0 else eps = Math.ldexp(f,e-Float::MANT_DIG+1) end end end eps end```

### #subnormal? ⇒ Boolean

Returns:

• (Boolean)
 ``` 369 370 371 372 373 374 375``` ```# File 'lib/flt/float.rb', line 369 def subnormal? if x.special? || x.zero? false else x.abs < Float::MIN_N end end```

### #to_int_scale(x) ⇒ Object

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

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

### #to_r(x) ⇒ Object

 ``` 385 386 387``` ```# File 'lib/flt/float.rb', line 385 def to_r(x) Support::Rationalizer.to_r(x) end```

### #ulp(x, mode = :low) ⇒ Object

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

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

### #zero(sign = +1) ⇒ Object

zero value with specified sign

 ``` 119 120 121``` ```# File 'lib/flt/float.rb', line 119 def zero(sign=+1) (sign < 0) ? -0.0 : 0.0 end```