Module: Flt::Support::AuxiliarFunctions

Included in:
Num
Defined in:
lib/flt/support.rb

Constant Summary

NBITS_BLOCK =
32
NBITS_LIMIT =
Math.ldexp(1,Float::MANT_DIG).to_i
NDIGITS_BLOCK =
50
NDIGITS_LIMIT =
Float::MAX.to_i

Class Method Summary (collapse)

Class Method Details

+ (Object) _nbits(x)

Number of bits in binary representation of the positive integer n, or 0 if n == 0.

Raises:

  • (TypeError)


1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
# File 'lib/flt/support.rb', line 1245

def _nbits(x)
  raise  TypeError, "The argument to _nbits should be nonnegative." if x < 0
  if x.is_a?(Fixnum)
    return 0 if x==0
    x.to_s(2).length
  elsif x <= NBITS_LIMIT
    Math.frexp(x).last
  else
    n = 0
    while x!=0
      y = x
      x >>= NBITS_BLOCK
      n += NBITS_BLOCK
    end
    n += y.to_s(2).length - NBITS_BLOCK if y!=0
    n
  end
end

+ (Object) _ndigits(x, b)

Number of base b digits in an integer

Raises:

  • (TypeError)


1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
# File 'lib/flt/support.rb', line 1267

def _ndigits(x, b)
  raise  TypeError, "The argument to _ndigits should be nonnegative." if x < 0
  return 0 unless x.is_a?(Integer)
  return _nbits(x) if b==2
  if x.is_a?(Fixnum)
    return 0 if x==0
    x.to_s(b).length
  elsif x <= NDIGITS_LIMIT
    (Math.log(x)/Math.log(b)).floor + 1
  else
    n = 0
    block = b**NDIGITS_BLOCK
    while x!=0
      y = x
      x /= block
      n += NDIGITS_BLOCK
    end
    n += y.to_s(b).length - NDIGITS_BLOCK if y!=0
    n
  end
end

+ (Object) detect_float_rounding



1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
# File 'lib/flt/support.rb', line 1291

def detect_float_rounding
  x = x = Math::ldexp(1, Float::MANT_DIG+1) # 10000...00*Float::RADIX**2 == Float::RADIX**(Float::MANT_DIG+1)
  y = x + Math::ldexp(1, 2)                 # 00000...01*Float::RADIX**2 == Float::RADIX**2
  h = Float::RADIX/2
  b = h*Float::RADIX
  z = Float::RADIX**2 - 1
  if x + 1 == y
    if (y + 1 == y) && Float::RADIX==10
      :up05
    elsif -x - 1 == -y
      :up
    else
      :ceiling
    end
  else # x + 1 == x
    if x + z == x
      if -x - z == -x
        :down
      else
        :floor
      end
    else # x + z == y
      # round to nearest
      if x + b == x
        if y + b == y
          :half_down
        else
          :half_even
        end
      else # x + b == y
        :half_up
      end
    end
  end

end