-- 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