[#3109] Is divmod dangerous? — Dave Thomas <Dave@...>

14 messages 2000/06/06

[#3149] Retrieving the hostname and port in net/http — Roland Jesse <jesse@...>

Hi,

12 messages 2000/06/07

[#3222] Ruby coding standard? — Robert Feldt <feldt@...>

16 messages 2000/06/09

[#3277] Re: BUG or something? — Aleksi Niemel<aleksi.niemela@...>

> |I am new to Ruby and this brings up a question I have had

17 messages 2000/06/12
[#3281] Re: BUG or something? — Dave Thomas <Dave@...> 2000/06/12

Aleksi Niemel<aleksi.niemela@cinnober.com> writes:

[#3296] RE: about documentation — Aleksi Niemel<aleksi.niemela@...>

> I want to contribute to the ruby project in my spare time.

15 messages 2000/06/12

[#3407] Waffling between Python and Ruby — "Warren Postma" <embed@...>

I was looking at the Ruby editor/IDE for windows and was disappointed with

19 messages 2000/06/14

[#3410] Exercice: Translate into Ruby :-) — Jilani Khaldi <jilanik@...>

Hi All,

17 messages 2000/06/14

[#3415] Re: Waffling between Python and Ruby — Andrew Hunt <andy@...>

>Static typing..., hmm,...

11 messages 2000/06/14

[#3453] Re: Static Typing( Was: Waffling between Python and Ruby) — Andrew Hunt <andy@...>

32 messages 2000/06/16

[#3516] Deep copy? — Hugh Sasse Staff Elec Eng <hgs@...>

Given that I cannot overload =, how should I go about ensuring a deep

20 messages 2000/06/19

[#3694] Why it's quiet — hal9000@...

We are all busy learning the new language

26 messages 2000/06/29
[#3703] Re: Why it's quiet — "NAKAMURA, Hiroshi" <nahi@...> 2000/06/30

Hi,

[#3705] Re: Why it's quiet — matz@... (Yukihiro Matsumoto) 2000/06/30

Hi,

[ruby-talk:03203] Re: Nan and Infinity

From: gotoken@... (GOTO Kentaro)
Date: 2000-06-08 18:32:41 UTC
List: ruby-talk #3203
Hi,

In message "[ruby-talk:03202] Nan and Infinity"
    on 00/06/08, Dave Thomas <Dave@thomases.com> writes:
>If the result of a floating point operation is Nan or one of the
>Infinities, is there any way to tell apart from converting the number
>to a string.
>
>Would Float#isNan? be useful?

I had written floatinternal.rb to hack floating numbers. 
It includes Float#nan? and Float#inf?. 

Hope this helps,

-- gotoken

# Apologies for absence of documnetation. 

# floatinternal.rb
# Author: gotoken
require "rational"

class FloatFormatError < StandardError
  def message
    "invalid floating point number internal format"
  end
end

class Integer
  def bin(fmt = "", width = 0, sep = ?_)
    represent(:bin, fmt, sep, width)
  end

  def oct(fmt = "", width = 0, sep = ?_)
    represent(:oct, fmt, sep, width)
  end

  def dec(fmt = "", width = 0, sep = ?_)
    represent(:dec, fmt, sep, width)
  end

  def hex(fmt = "", width = 0, sep = ?_)
    represent(:hex, fmt, sep, width)
  end

  private

  def represent(base, fmt, sep, width)
    case base
    when :bin, :oct, :dec
      fmt =~ /\A\+?(?:[0]?[1-9][0-9]*)?\Z/ or
	raise ArgumentError, "invalid format `#{fmt}'"
    when :hex
      fmt =~ /\A\+?(?:[0]?[1-9][0-9]*)?[xX]?\Z/ or
	raise ArgumentError, "invalid format `#{fmt}'"
    end
    case base
    when :bin
      buf = "%#{fmt}b" % self
    when :oct
      buf = "%#{fmt}o" % self
    when :dec
      buf = "%#{fmt}d" % self
    when :hex
      fmt += "x" unless /[xX]\Z/ =~ fmt
      buf = "%#{fmt}" % self
    end
    if width > 0
      buf[0].chr +
	buf[1..-1].reverse!.gsub(/#{"."*width}/,"\\&#{sep.chr}").reverse!
    else
      buf
    end
  end
end

class String
  def bin
    eval("0b" + (scan(/\A[01][01_]*/)[0]))
  end
end

class String
  def intern_double(base = 2)
    tmp = delete('_')
    res = catch(:error) do
      case base
      when 2
	throw(:error) unless tmp =~ /\A[01]{64,64}\Z/
	[tmp].pack("B*").unpack("G")[0]
      when 8
	throw(:error) unless tmp =~ /\A[0-7]{32,32}\Z/
	["%016x" % tmp.oct].pack("h16").unpack("G")[0]
      when 16
	throw(:error) unless tmp =~ /\A[0-9a-fA-F]{16,16}\Z/
	[tmp].pack("h16").unpack("G")[0]
      else
	throw(:error)
      end
    end
    unless res
      raise FloatFormatError,
	"invalid floating point number internal format"
    end
    res
  end
  alias network_byte_order_float_format intern_double
end

class Array
  def intern_double(base = 2)
    if size != 3 || grep(String).size != 3
      raise FloatFormatError,
	"invalid floating point number internal format"
    end
    s, e, m = self
    case base
    when 2
      unless s =~ /\A[01]\Z/ && e =~ /\A[01]{11,11}\Z/ && 
	  m =~ /\A[01]{52,52}\Z/
	raise FloatFormatError,
	  "invalid floating point number internal format"
      end
      (s + e + m).intern_double
    when 8
      unless s =~ /\A[01]\Z/ && e =~ /\A[0-7]{4,4}\Z/ && 
	  m =~ /\A[0-7]{18,18}\Z/
	raise FloatFormatError,
	  "invalid floating point number internal format"
      end
      (s.oct.bin + e.oct.bin("011") + e.oct.bin("052")).intern_double(2)
    when 16
      unless s =~ /\A[01]\Z/ && e =~ /\A[0-9a-fA-F]{3,3}\Z/ && 
	  m =~ /\A[0-9a-fA-F]{13,13}\Z/
	raise FloatFormatError,
	  "invalid floating point number internal format"
      end
      (s.hex.bin + e.hex.bin("011") + e.hex.bin("052")).intern_double(2)
    end
  end
end

class Float
  T_ZERO = "ZERO".freeze
  T_NORMAL = "NORMAL".freeze
  T_DENORMAL = "DENORMAL".freeze
  T_INF = "INF".freeze
  T_NaN = "NaN".freeze

  DoubleInternal = Struct.new("DoubleInternal", "t", "s", "e", "m")

  def intern_str(base = 2)
    bstr = [self].pack("G")
    case base
    when 2
      bstr.unpack("B64")[0]
    when 8
      bstr.unpack("h16")[0].hex.oct("032")
    when 16
      bstr.unpack("h16")[0]
    else
      raise ArgumentError,
	"illegal base `#{base}' (!= 2,8,16)"
    end
  end

  def bitstring(base = 2)
    bstr = [self].pack("G").unpack("B*")[0]
    case base
    when 2
      [bstr[0].chr, bstr[1,11], bstr[12,52]]
    when 8
      [bstr[0].chr, "%04o" % bstr[1,11].bin, "%018o" % bstr[12,52].bin]
    when 16
      [bstr[0].chr, "%03x" % bstr[1,11].bin, "%013x" % bstr[12,52].bin]
    else
      raise ArgumentError,
	"illegal base `#{base}' (!= 2,8,16)"
    end
  end

  def decomp
    bstr = bitstring
    estr, mstr = bstr[1], bstr[2]
    s, e0, m0 = bstr[0][0]-?0, estr.bin, mstr.bin
    case e0
    when 1..2046 # normal
      t = T_NORMAL
    when 0       # denormal
      t = m0 == 0 ? T_ZERO : T_DENORMAL
    when 2047
      if m0 == 0
	t = T_INF
      else
	t = T_NaN
      end
    end
    [t, s, e0, m0]
  end

  alias decompose decomp

  def mne
    t, s, e0, m0 = decomp
    case t
    when T_NORMAL
      e = e0 - 1023
      m = Rational(m0 + 2**52, 2**52)
    when T_ZERO
      e = 0
      m = Rational(0,1)
    when T_DENORMAL
      e = -1022
      m = Rational(m0, 2**52)
    when T_NaN
      return DoubleInternal.new(t, nil, e, m)
    end
    DoubleInternal.new(t, -2*s+1, e, m)
  end

  alias mantissa_and_exponent mne

  def nan?
    decomp[0] == T_NaN
  end

  def inf?
    decomp[0] == T_INF
  end
end


if __FILE__ == $0
  require "xmp"
  xmp <<-EOS
  0.1.mne

  0.1.bitstring
  0.1.bitstring(8).collect{|i| i.hex.bin}
  0.1.bitstring(8)
  (0.0/0.0).nan?
  (0.0/1.0).nan?
  (0.0/0.0).inf?
  (0.0/1.0).inf?
  EOS
end

In This Thread