c_extensions/c_bignums_no_parens.rb

tests/_examples/c_extensions/c_bignums_no_parens.rb in the metorex repository.

# A C extension converting Integers too wide for a fixnum to and from C
# numbers and strings, comparing them, packing them into longs, and reading
# any number as a C double.
require "tmpdir"
require "stringio"
require_relative "build_helper"

class Measured
  def to_f
    2.5
  end
end

class Wrong
  def to_f
    "no"
  end
end

directory = Dir.mktmpdir
require build_extension("c_bignums.c", "c_bignums", directory)
bignums = CBignums.new
long_max = 2**63 - 1
long_min = -2**63

p [bignums.to_long(long_max), bignums.to_long(long_min), bignums.to_long(5)]
report { bignums.to_long long_max + 1 }
report { bignums.to_long long_min - 1 }
report { bignums.to_long 2**70 }
p bignums.to_long_long long_min
report { bignums.to_long_long long_max + 1 }
report { bignums.to_long_long 2**70 }
p [bignums.to_unsigned_long(2**64 - 1), bignums.to_unsigned_long(-1), bignums.to_unsigned_long(long_min)]
report { bignums.to_unsigned_long long_min - 1 }
report { bignums.to_unsigned_long 2**64 }

p bignums.to_double 2**70
$stderr = StringIO.new
$VERBOSE = true
p bignums.to_double(-(10**400))
warned = $stderr.string
$stderr = STDERR
$VERBOSE = false
puts warned.sub(/\A.*warning: /, "warning: ")
p bignums.from_double 219238102380912830988.5
p bignums.from_double(-2.75)
report { bignums.from_double Float::INFINITY }
report { bignums.from_double(-Float::INFINITY) }
report { bignums.from_double Float::NAN }

p bignums.to_text(2**70, 10)
p bignums.to_text(2**70, 16)
p [bignums.sign(2**70), bignums.sign(-(2**70)), bignums.sign(0)]
p [bignums.compare(2**70, 2**71), bignums.compare(2**70, 5), bignums.compare(2**70, 2**70)]

p bignums.pack(2**64 - 1, 2)
p bignums.pack(-(2**71 + 1), 2)
p bignums.pack(5, 1)
p [bignums.size(2**71), bignums.size(255), bignums.size(-256), bignums.size(0)]

p [bignums.to_c_double(3), bignums.to_c_double(2**70), bignums.to_c_double(1.5), bignums.to_c_double(Rational(1, 4))]
p bignums.to_c_double Measured.new
report { bignums.to_c_double nil }
report { bignums.to_c_double true }
report { bignums.to_c_double :sym }
report { bignums.to_c_double "1.5" }
report { bignums.to_c_double Object.new }
report { bignums.to_c_double Wrong.new }
p bignums.empty

FileUtils.rm_rf directory

Output:

[9223372036854775807, -9223372036854775808, 5]
RangeError: bignum too big to convert into 'long'
RangeError: bignum too big to convert into 'long'
RangeError: bignum too big to convert into 'long'
-9223372036854775808
RangeError: bignum too big to convert into 'long long'
RangeError: bignum too big to convert into 'long long'
[18446744073709551615, 18446744073709551615, 9223372036854775808]
RangeError: bignum out of range of unsigned long
RangeError: bignum too big to convert into 'unsigned long'
1.1805916207174113e+21
-Infinity
warning: Integer out of Float range
219238102380912836608
-2
FloatDomainError: Infinity
FloatDomainError: -Infinity
FloatDomainError: NaN
"1180591620717411303424"
"400000000000000000"
[[1, true, false], [0, false, true], [1, true, false]]
[-1, 1, 0]
[18446744073709551615, 0]
[18446744073709551615, 18446744073709551487]
[5]
[[9, 0, 9], [1, 0, 1], [2, 7, 2], [0, 0, 0]]
[3.0, 1.1805916207174113e+21, 1.5, 0.25]
2.5
TypeError: no implicit conversion of nil into Float
TypeError: no implicit conversion of true into Float
TypeError: no implicit conversion of Symbol into Float
TypeError: no implicit conversion of String into Float
TypeError: can't convert Object into Float
TypeError: can't convert Wrong to Float (Wrong#to_f gives String)
[]