# $Id: hexfloat.rb,v 1.1 2003/04/25 02:45:07 nobu Exp $

class Float
  def hex
    return "nan" if nan?
    case infinite?
    when 1
      return "inf"
    when -1
      return "-inf"
    end
    s = self < 0 ? "-0x" : "0x"
    m, e = Math.frexp(abs())
    m = Math.ldexp(m, n = ((e - 1) & 3) + 1)
    e -= n
    n = m.floor
    s << "%x" % n
    if (m -= n) > 0
      s << "."
      begin
        s << "%.4x" % (n = (m *= 0x10000).floor)
      end while (m -= n) > 0
    end
    s.sub!(/([^x])0+$/, '\1')
    s.index(?.) or s << ".0"
    e.zero? or s << "p%+d" % e
    s
  end

  def bin
    [self].pack("G").gsub(/./) {|s| "%.2x" % s[0]}
  end
end

class String
  alias to_float to_f
  def to_f
    if m = /\A\s*([-+])?0b([01]+)(?:\.([01]+))?(?:p([-+]\d+))?/i.match(self)
      f = m[2]
      e = m[4].to_i
      if m[3]
        f << m[3]
        e -= m[3].size
      end
      f = f.to_i(2)
      f = Math.ldexp(f, e)
      m[1] == '-' ? -f : f
    elsif m = /\A\s*([-+])?0x([[:xdigit:]]+)(?:\.([[:xdigit:]]+))?(?:p([-+]\d+))?/i.match(self)
      f = m[2]
      e = m[4].to_i
      if m[3]
        f << m[3]
        e -= 4*m[3].size
      end
      f = f.to_i(16)
      f = Math.ldexp(f, e)
      m[1] == '-' ? -f : f
    else
      to_float()
    end
  end
end
