module IEEE_FPU
FPU parameters can be assigneed passign a hash to the scope method:
IEEE_FPU.scope(:precision=>:single) { puts eval(expr) }
An array can be passed for one (only one) of the parameters; the block will be repeated with every value of the parameter and the results will be collected in an array. For example this checks the result of an expression in all the rounding modes:
puts IEEE_FPU.scope(:rounding=>[:even,:up,:down,:zero]) { 1.0 + Float::EPSILON/2 }.inspect
Different parameters can be passed to each call of the block by assigning an array to :parameters For example, interval arithmetic could be implementes like this:
def sum_intervals(i1,i2) IEEE_FPU.scope(:rounding=>[:down,:up],:parameters=>[0,1]) do |fpu,i| i1[i]+i2[i] end end i = sum_intervals([1.0]*2, [Float::EPSILON/2]*2)
use ieee_fpu extension
Constants
- Controlfp
- DN_FLUSH
- DN_SAVE
- EM_DENORMAL
- EM_INEXACT
- EM_INVALID
- EM_OVERFLOW
- EM_UNDERFLOW
- EM_ZERODIVIDE
- FE_DBLPREC
- FE_DOWNWARD
- FE_FLTPREC
- FE_LDBLPREC
- FE_TONEAREST
- FE_TOWARDZERO
- FE_UPWARD
- FPU_DOUBLE
- FPU_EXTENDED
- FPU_RC_DOWN
- FPU_RC_NEAREST
- FPU_RC_UP
- FPU_RC_ZERO
- FPU_SINGLE
- IC_AFFINE
- IC_PROJECTIVE
- MCW_DN
- MCW_EM
- MCW_IC
- MCW_PC
- MCW_RC
- PC_24
- PC_53
- PC_64
- RC_CHOP
- RC_DOWN
- RC_NEAR
- RC_UP
Public Class Methods
fegetprec()
click to toggle source
static VALUE mIEEE_FPU_fegetprec(VALUE self) { return UINT2NUM(fegetprec()); }
fegetround()
click to toggle source
static VALUE mIEEE_FPU_fegetround(VALUE self) { return UINT2NUM(fegetround()); }
fesetprec(p1)
click to toggle source
static VALUE mIEEE_FPU_fesetprec(VALUE self, VALUE prec) { fesetprec(NUM2UINT(prec)); return UINT2NUM(fegetprec()); }
fesetround(p1)
click to toggle source
Set the FPU's rounding mode.
static VALUE mIEEE_FPU_fesetround(VALUE self, VALUE mode) { fesetround(NUM2UINT(mode)); return UINT2NUM(fegetround()); }
fpu_getprec()
click to toggle source
static VALUE mIEEE_FPU_fpu_getprec(VALUE self) { fpu_control_t mask = (_FPU_EXTENDED|_FPU_DOUBLE|_FPU_SINGLE); fpu_control_t c; _FPU_GETCW(c); return UINT2NUM(c & mask); }
fpu_getround()
click to toggle source
static VALUE mIEEE_FPU_fpu_getround(VALUE self) { fpu_control_t mask = (_FPU_RC_NEAREST|_FPU_RC_DOWN|_FPU_RC_UP|_FPU_RC_ZERO); fpu_control_t c; _FPU_GETCW(c); return UINT2NUM(c & mask); }
fpu_setprec(p1)
click to toggle source
static VALUE mIEEE_FPU_fpu_setprec(VALUE self, VALUE prec) { fpu_control_t mask = (_FPU_EXTENDED|_FPU_DOUBLE|_FPU_SINGLE); fpu_control_t c, new_c; _FPU_GETCW(c); new_c = c; new_c &= ~mask; new_c |= NUM2UINT(prec); _FPU_SETCW(new_c); return UINT2NUM(c & mask); }
fpu_setround(p1)
click to toggle source
static VALUE mIEEE_FPU_fpu_setround(VALUE self, VALUE mode) { fpu_control_t mask = (_FPU_RC_NEAREST|_FPU_RC_DOWN|_FPU_RC_UP|_FPU_RC_ZERO); fpu_control_t c, new_c; _FPU_GETCW(c); new_c = c; new_c &= ~mask; new_c |= NUM2UINT(mode); _FPU_SETCW(new_c); return UINT2NUM(c & mask); }
get_status()
click to toggle source
# File lib/ieee-fpu.rb, line 85 def self.get_status Controlfp.call(0,0) end
precision()
click to toggle source
# File lib/ieee-fpu.rb, line 124 def self.precision v = get_status & MCW_PC p = nil case v when PC_24 p = :single when PC_53 p = :double when PC_64 p = :extended end p end
precision=(p)
click to toggle source
# File lib/ieee-fpu.rb, line 137 def self.precision=(p) v = nil case p when :single, 24 v = PC_24 when :double, 53 v = PC_53 when :extended, 64, 112 v = PC_64 else raise Error, "Invalid precision #{p.inspect}" end Controlfp.call(v,MCW_PC) unless v.nil? p end
rounding()
click to toggle source
# File lib/ieee-fpu.rb, line 153 def self.rounding v = get_status & MCW_RC r = nil case v when RC_UP r = :up when RC_DOWN r = :down when RC_CHOP r = :zero when RC_NEAR r = :even end r end
rounding=(r)
click to toggle source
# File lib/ieee-fpu.rb, line 169 def self.rounding=(r) v = nil case r when :up, :plus_infinity, :positive_infinity v = RC_UP when :down, :minus_inifinity, :negative_infinity v = RC_DOWN when :zero, :truncate, :chop v = RC_CHOP when :even, :near, :unbiased v = RC_NEAR else raise Error, "Invalid rounding mode #{r}" end Controlfp.call(v,MCW_RC) unless v.nil? r end
scope(assignments={}) { |self, param| ... }
click to toggle source
# File lib/ieee-fpu.rb, line 91 def self.scope(assignments={}) v = nil s = get_status prc = assignments[:precision] rnd = assignments[:rounding] self.precision = prc if prc && !(Array===prc) self.rounding =rnd if rnd && !(Array===rnd) if Array===prc param = assignments[:parameters] || [nil]*prc.size v = [] i = 0 prc.each do |p| self.precision = p v << yield(self, param[i]) i += 1 end elsif Array===rnd param = assignments[:parameters] || [nil]*rnd.size v = [] i = 0 rnd.each do |r| self.rounding = r v << yield(self, param[i]) i += 1 end else v = yield(self) end v ensure set_status s end
set_status(s)
click to toggle source
# File lib/ieee-fpu.rb, line 88 def self.set_status(s) Controlfp.call(s,MCW_DN|MCW_EM|MCW_IC|MCW_RC|MCW_PC) end
supported_precisions()
click to toggle source
# File lib/ieee-fpu.rb, line 187 def self.supported_precisions [:single, :double, :extended] end