From: Juergen Strobel Date: 2006-07-03T01:55:30+09:00 Subject: [Solution] [QUIZ] C-Style Ints (#85) --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 # # 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<, :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 # # 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--