-- This file is free software, which comes along with SmartEiffel. This -- software is distributed in the hope that it will be useful, but WITHOUT -- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- FITNESS FOR A PARTICULAR PURPOSE. You can modify it as you want, provided -- this header is kept unaltered, and a notification of the changes is added. -- You are allowed to redistribute it and sell it, alone or as a part of -- another product. -- Copyright (C) 1994-2002 LORIA - INRIA - U.H.P. Nancy 1 - FRANCE -- Dominique COLNET and Suzanne COLLIN - SmartEiffel@loria.fr -- http://SmartEiffel.loria.fr -- expanded class BIT_N -- -- Indexed Bit sequences of length `N'. This class is a template, -- not a real class; to obtain a meaningful class, replace `N' -- with a positive integer throughout. -- -- An INTEGER index can be used to access each bit of the sequence. -- The leftmost bit has index 1 and the rightmost bit has index `N'. -- -- Note 1 : corresponding C mapping depends on actual `N' and is -- PLATFORM dependant (see class PLATFORM). -- When `N' is in range [0 .. Character_bits], C type -- is a simple "unsigned char". -- When `N' is in range [Character_bits+1 .. Integer_bits], -- C type is "unsigned". -- When `N' is greater than Integer_bits, C type is C array -- of "unsigned" of the form : -- "unsigned storage[`N' div Integer_bits]" -- The array is obviously big enough to fit with `N'. As -- for previous mapping, the left most bit (at index 1 in -- Eiffel) is always the left most in C memory. -- -- Note 2 : Eiffel BIT code is portable. Generated C code for class -- BIT may not be portable (because sizeof(int) may change). -- To produce a portable C code, you can compile your Eiffel -- code using a machine with very small sizeof(int). Also note -- that doing this may run a little bit slowly. -- -- Also consider class BIT_STRING for very long bit sequences. -- inherit ANY redefine out_in_tagged_out_memory, fill_tagged_out_memory end feature -- Basic Accessing: count: INTEGER is -- Number of bits in the sequence (the value of `N'). external "SmartEiffel" end item(idx: INTEGER): BOOLEAN is -- True if `idx'-th bit is 1, false otherwise. require inside_bounds: 1 <= idx and then idx <= count external "SmartEiffel" end put(value: BOOLEAN; idx: INTEGER) is -- Set bit `idx' to 1 if value is true, 0 otherwise. require inside_bounds: 1 <= idx and idx <= count external "SmartEiffel" ensure value = item(idx) end put_1(idx: INTEGER) is -- Set bit `idx' to 1. require inside_bounds: 1 <= idx and idx <= count external "SmartEiffel" ensure item(idx) end put_0(idx: INTEGER) is -- Set bit `idx' to 0. require inside_bounds: 1 <= idx and idx <= count external "SmartEiffel" ensure not item(idx) end first: BOOLEAN is -- The value of the right-most bit. do Result := item(1) ensure definition: Result = item(1) end last: BOOLEAN is -- The value of the right-most bit. external "SmartEiffel" ensure definition: Result = item(count) end feature -- Rotating and shifting: infix "^" (s: INTEGER): like Current is -- Sequence shifted by `s' positions (positive `s' shifts -- right, negative left; bits falling off the sequence's -- bounds are lost). -- See also infix "|>>" and infix "|<<". require s.abs < count do if s >= 0 then if s = 0 then Result := Current else Result := Current |>> s end else Result := Current |<< -s end end infix "|>>" (s: INTEGER): like Current is -- Sequence shifted right by `s' positions. -- Same as infix "^" when `s' is positive (may run a little -- bit faster). require s > 0 external "SmartEiffel" end infix "@>>" (s: INTEGER): like Current is obsolete "Use %"|>>%" instead of %"@>>%" (september 2002)." do Result := Current |>> s end infix "|<<" (s: INTEGER): like Current is -- Sequence shifted left by `s' positions. -- Same as infix "^" when `s' is negative (may run a little -- bit faster. require s > 0 external "SmartEiffel" end infix "@<<" (s: INTEGER): like Current is obsolete "Use %"|<<%" instead of %"@<<%" (september 2002)." do Result := Current |<< s end infix "#" (s: INTEGER): like Current is -- Sequence rotated by `s' positions (positive right, -- negative left). require s.abs < count do if s >= 0 then Result := Current #>> s else Result := Current #<< -s end end infix "#>>" (s: INTEGER): like Current is -- Sequence rotated by `s' positions right. require s >= 0 s < count local i: INTEGER bit: BOOLEAN do Result := Current from i := s until i = 0 loop bit := Result.item(count) Result := Result |>> 1 Result.put(bit,1) i := i - 1 end end infix "#<<" (s: INTEGER): like Current is -- Sequence rotated by `s' positions left. require s >= 0 s < count local i: INTEGER bit: BOOLEAN do from i := s Result := Current until i = 0 loop bit := Result.item(1) Result := Result |<< 1 Result.put(bit,count) i := i - 1 end end feature -- Bitwise Logical Operators: infix "and" (other: like Current): like Current is -- Bitwise `and' of Current with `other' external "SmartEiffel" end infix "implies" (other: like Current): like Current is -- Bitwise implication of Current with `other' do Result := (not Current) or other end prefix "not": like Current is -- Bitwise `not' of Current. external "SmartEiffel" end infix "or" (other: like Current): like Current is -- Bitwise `or' of Current with `other' external "SmartEiffel" end infix "xor" (other : like Current) : like Current is -- Bitwise `xor' of Current with `other' external "SmartEiffel" end feature -- Conversions: to_string: STRING is -- String representation of bit sequence. -- A zero bit is mapped to '0', a one bit to '1'. -- Leftmost bit is at index 1 in the returned string. -- -- Note: see `append_in' to save memory. do string_buffer.clear append_in(string_buffer) Result := string_buffer.twin ensure then Result.count = count end to_integer_8: INTEGER_8 is -- The corresponding INTEGER value. -- No sign-extension when `count' < 8. require count <= 8 do Result := to_integer.to_integer_8 end to_integer_16: INTEGER_16 is -- The corresponding INTEGER value. -- No sign-extension when `count' < 16. require count <= 16 do Result := to_integer.to_integer_16 end to_integer, to_integer_32: INTEGER_32 is -- The corresponding INTEGER value. -- No sign-extension when `count' < 32. require count <= 32 external "SmartEiffel" end to_integer_64: INTEGER_64 is -- The corresponding INTEGER value. -- No sign-extension when `count' < 64. require count <= 64 do Result := to_integer.to_integer_64 end to_character: CHARACTER is require count <= Character_bits external "SmartEiffel" end to_boolean: BOOLEAN is -- Return false if and only if all bits are set to 0, -- true otherwise. local zero: like Current do Result := Current /= zero end to_bit_string: BIT_STRING is local i: INTEGER do from !!Result.make(count) i := count until i = 0 loop if item(i) then Result.put_1(i) end i := i - 1 end ensure count = Result.count end feature -- Others: all_cleared, all_default: BOOLEAN is -- Are all bits set to 0 ? local zero: like Current do Result := Current = zero end all_set: BOOLEAN is -- Are all bits set to 1 ? local zero: like Current do Result := Current = not zero end feature -- Printing: append_in(str: STRING) is local i: INTEGER do from i := 1 until i > count loop if item(i) then str.extend('1') else str.extend('0') end i := i + 1 end end out_in_tagged_out_memory, fill_tagged_out_memory is do Current.append_in(tagged_out_memory) tagged_out_memory.extend('B') end feature {NONE} string_buffer: STRING is once create Result.make(128) end end -- BIT_N