--KdquIMZPjGJQvRdI
Content-Type: text/plain; charset=iso-8859-1
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable
Hello,
I am lazy, so I avoided math as much as possible. In fact, I went to
some length to avoid dealing with the problem altogether, delegating
to ruby's Integer and even let ruby define my delegated functions :)
# Fixed Width Integer Class for Ruby Quiz #85
# (C) 2006 J=FCrgen Strobel <juergen / strobel.info>
#
# This program is free software; you can redistribute it
# and/or modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation;
# either version 2 of the License, or (at your option) any
# later version.
require "forwardable.rb"
# Base class for Integer classes with a fixed bit width
#
# Almost all methods are delegated to an encapsulated integer object.
# Metaprogramming is used to automate delegation & conversion.
#
class FixedWidthInt=20
include Comparable
extend Forwardable
private_class_method :new
=20
def self.def_fwi_delegator(accessor, method) # taken from forward.rb
module_eval(<<-EOS, "(__FWI_DELEGATION__)", 1)
def #{method}(*args, &block)
begin
#puts "delegating #{method} and converting the result"
self.class.new(#{accessor}.__send__(:#{method}, *args, &block), w=
idth)
rescue Exception
$@.delete_if{|s| /^\\(__FWI_DELEGATION__\\):/ =3D~ s} unless Forw=
ardable::debug
Kernel::raise
end
end
EOS
end
def method_missing(op, *args) # a method is missing?
if @i.respond_to?(op) # our @i could handle it?
#puts "defining new method #{op}"
FixedWidthInt.def_fwi_delegator :@i, op # define it by delegation!
self.send(op, *args) # and try again
else # else
super # NoMethodError
end
end
=20
def initialize(i =3D 0, w =3D 8)
w =3D w.to_i
raise "Invalid width" unless w >=3D 1
@width, @i =3D w, i.to_i & ((1<<w) - 1)
end
def coerce_to_width(nw)
self.class.new(i, nw)
end
def inspect
"#{self.i}(#{self.class.name[0,1]}#{width})"
end
attr_reader :i, :width
def_delegators :@i, :[], :zero?
def_delegators :i, :to_i, :to_s, :<=3D>, :times, :coerce, :divmod, :quo, =
:to_f
# We might have to define or delegate more methods explicitly which
# are not working correctly with #method_missing. Especially those
# not returning a FixedWidthInt.
end
# A fixed width unsigned integer
class UnsignedFixedWidthInt < FixedWidthInt
public_class_method :new
end
# A fixed width signed integer
class SignedFixedWidthInt < FixedWidthInt
public_class_method :new
# Interpret @i differently if the highest bit is set, everything
# else works magically thanks to 2's complement arithmentic.
def i
if (@i >> (width-1)).zero?
@i
else
@i - (1 << width)
end
end
end=20
############ snip
I also took the tests from the irb session und extended them:
#!/usr/bin/ruby
# Fixed Width Integer Class Unit Tests (Ruby Quiz #85)
# (C) 2006 J=FCrgen Strobel <juergen / strobel.info>
#
# This program is free software; you can redistribute it
# and/or modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation;
# either version 2 of the License, or (at your option) any
# later version.
require "fixed_width_int.rb"
require 'test/unit'
class FWITest < Test::Unit::TestCase
def test_unsigned
assert_equal 255, (n =3D UnsignedFixedWidthInt.new(0xff, 8))
assert_equal 1, (n +=3D 2)
assert_equal 2, (n =3D n << 1)
assert_equal 1, (n =3D n >> 1)
assert_equal 254, (~n)
assert_equal 13, (n +=3D 12)
assert_equal 12, (n =3D n & 0x0E)
=20
assert_kind_of FixedWidthInt, n
assert_instance_of UnsignedFixedWidthInt, n
assert_equal 144, (n * n)
assert_equal 0, (n-n)
assert_equal 3, (m =3D -9 + n)
assert_kind_of Integer, m
assert_kind_of Float, n.to_f
end
def test_signed
assert_equal 1, (n =3D SignedFixedWidthInt.new(0x01, 8))
assert_equal -128, (n =3D n << 7)
assert_equal 127, (n -=3D 1)
assert_equal 1, (n =3D n >> 6)
assert_equal -1, (n -=3D 2)
assert_equal 12, (n =3D n ^ 0xF3)
assert_equal 13, (n =3D n | 0x01)
=20
assert_kind_of FixedWidthInt, n
assert_instance_of SignedFixedWidthInt, n
assert_equal -169&0xff, (n * (-n))
assert_equal 0, (n-n)
assert_equal -1, (m =3D -14 + n)
assert_kind_of Integer, m
assert_kind_of Float, n.quo(17)
end
=20
def test_too_wide
assert_equal 0, (n =3D UnsignedFixedWidthInt.new(0x0, 8))
assert_equal 238, (n +=3D 0xFFEE)
end
end
############### snip
~/ruby/% ruby test_fixed_width_int.rb
Loaded suite test_fixed_width_int
Started
=2E..
Finished in 0.023573 seconds.
-J=FCrgen
--=20
The box said it requires Windows 95 or better so I installed Linux
--KdquIMZPjGJQvRdI
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: Digital signature
Content-Disposition: inline
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.3 (GNU/Linux)
iQEVAwUBRKf6fvy64gyiEfXtAQIorgf/ZqH71zObLEH8tulw0qG77uv/hBYyz1H6
com5Y+xTjCewmvfWM6EYbJYxg63bmoEdsHzI4LFCliadNh3NMY7W3ynw3a17HoeX
FwP1zxEgKa+Amy7PfM5sZpg5yFkXo0UClj71gq/P72lnQCuRD2gcrvPigT+P0/sX
vWM4VKa+YyGKv/McX/fhwO74XJjaceAP9+FPKXQswH84eA5hp6cyf26/PJz39FT2
pbrSfgOFss8ujZNSbk+U0HQUcOUTcMoTPTW9b0/HvafuUMhPs7HnRLiVTfVOuIyr
CSXyimvZLmUv7WuNampkWY1r+UIlDlEyPvPbCg18B4RDb5O6zKk5Ow==
=B1xf
-----END PGP SIGNATURE-----
--KdquIMZPjGJQvRdI--