Description
Both C++ and Java define a bitset type, so I propose that the standard
library also have a module implementing a bitset type. My first draft
for a public API for that module is as follows.
The module name is STDLIB_BITSETS
.
The module exports one constant, BITS_KIND
, to be used as a KIND
value in addressing bits in the bitset. This will initially be
INT32
.
The module exports one derived type, BITSETS
, with a plural name so
that users can name their scalar realizations as BITSET
. The type
will contain two private components: BITS
a scalar integer of kind
BITS_KIND
giving the number of bits in a bitset entity, and a rank
one allocatable integer array BLOCK
of private kind BLOCK_KIND
,
that will be INT32
, to be used in holding the bit values. The type
has an ASSIGNMENT(=) operation defined.
BITSETS
will have the following procedures: ALL
, AND
, AND_NOT
,
ANY_BIT
, BIT_COUNT
, BITS
, CLEAR
, EOR
, EQUIV
, EXTRACT
,
FLIP
, INIT
, INPUT
, MAX_SET_BIT
, NONE
, OR
, OUTPUT
,
PRINT_BITSET
, READ_BITSET
, SET
, TEST
, and VALUE
. Some of
these procedures will be overloaded:
interface clear
module procedure clear_bit, clear_range
end interface clear
interface flip
module procedure flip_bit, flip_range
end interface flip
interface init
module procedure init_copy, init_zero
end interface init
interface set
module procedure set_bit, set_range
end interface set
interface print_bitset
module procedure print_bitset_string, print_bitset_unit
end interface print_bitset
interface read_bitset
module procedure read_bitset_string, read_bitset_unit
end interface read_bitset
The API for the individual procedures is listed below. The following
aspects of the API may be controversial:
-
How the range is defined for
CLEAR_RANGE
,FLIP_RANGE
, and
SET_RANGE
. I have roughly followed Java's bitset here. -
That the first argument is modified in
AND
,AND_NOT
,EOR
, and
OR
. That is how it is done in the Java bitset, but I can see
having a function that returns the result rather than a subroutine
that modifies the first argument. -
That the I/O procedures
INPUT
,OUTPUT
,PRINT_BITSET
, and
READ_BITSET
haveSTATUS
flags. -
That the procedures often ignore user specification of positions
outside the range 0 toBITS-1
. An alternative is to make the
procedures impure and invokingERROR STOP
. Another option is to
add aSTATUS
argument, but I am reluctant to do that for a simple
user error. -
The names of some of the procedures could be more similar to the
names of Fortran's bit intrinsics.
subroutine init_copy(set, aset, bits)
: Creates the bitset SET
, of size BITS
if present, otherwise of the
size of ASET
. All bits in the range of ASET
are copied from ASET
. If
BITS
is present and larger than the size of ASET
then all additional
bits are zero.
subroutine init_zero(set, bits)
: Creates the bitset, SET
, of size BITS,
with all bits initialized to
zero. BITS
must be non-negative.
elemental function all_bits( set )
: Returns .TRUE.
if all bits in SET
are 1, .FALSE.
otherwise.
elemental subroutine and(set1, set2)
: Sets the bits in SET1
to the bitwise AND
of the original bits in
SET1
and SET2
. If SET1
has fewer bits than SET2
then the
additional bits in SET2
are ignored. If SET1
has more bits than
SET2
, then the absent SET2
bits are treated as if present with
zero value.
elemental subroutine and_not(set1, set2)
: Sets the bits in SET1
to the bitwise and of the original bits in
SET1
with the bitwise negation of SET2
. If SET1
has fewer bits
than SET2
then the additional bits in SET2
are ignored. If SET1
has more bits, then the absent SET2
bits are treated as if present
with zero value.
elemental function any_bit(set)
: Returns .TRUE.
if any bit in SET
is 1, .FALSE.
otherwise
elemental function bit_count(set)
: Returns the number of non-zero bits in SET
.
elemental function bits(set)
: Returns the number of bit positions in SET
.
elemental subroutine clear_bit(set, pos)
: Sets to zero the POS
position in SET
. If POS
is less than zero
or greater than BITS(SET)-1
it is ignored.
pure subroutine clear_range(set, start_pos, stop_pos)
: Sets to zero all bits from the START_POS
to STOP_POS
positions in
SET
. If STOP_POS < START_POS
then no bits are modified. Positions
outside the range 0 to BITS(SET)-1
are ignored.
elemental subroutine eor(set1, set2)
: Sets the bits in SET1
to the bitwise EOR
of the original bits in
SET1
and SET2
. If SET1
has fewer bits than SET2
then the
additional bits in SET2
are ignored. If SET1
has more bits than
SET2
, then the absent SET2
bits are treated as if present with
zero value.
elemental function equiv(set1, set2)
: Returns .TRUE.
if all bits in SET1
and SET2
have the same
value, .FALSE.
otherwise. If the sets differ in size a value true
will be returned if and only if the sets are equivalent in the
overlapping range, and all bits outside the overlapping range are
zero.
pure function extract(set, start_pos, stop_pos)
: Creates a new bitset from a range, START_POS
to STOP_POS
, in
bitset SET
.
elemental subroutine flip_bit(set, pos)
: Flips the value at the POS
position in SET
, provided the
position is valid. If POS
is less than 0 or greater than
BITS(SET)-1
, then no value is changed.
pure subroutine flip_range(set, start_pos, stop_pos)
: Flips all valid bits from the START_POS
to STOP_POS
positions in
SET
. If STOP_POS < START_POS
no bits are flipped. Positions less
than 0 or greater than BITS(SET)-1
are ignored.
subroutine input(unit, set, status)
: Reads the components of the bitset, SET
, from the logical unit,
UNIT
, assuming that the components were written using OUTPUT
.
elemental function max_set_bit( set )
: Returns the maximum position with a set bit. If no bit is set
returns -1.
elemental function none(set)
: Returns .TRUE.
if none of the bits in SET
have the value 1.
elemental subroutine or(set1, set2)
: Sets the bits in SET1
to the bitwise OR
of the original bits in
SET1
and SET2
. If SET1
has fewer bits than SET2
then the
additional bits in SET2
are ignored. If SET1
has more bits than
SET2
, then the absent SET2
bits are treated as if present with
zero value.
subroutine output(unit, set, status)
: Writes the components of the bitset, SET
, to the logical unit,
UNIT
, in a unformatted sequence compatible with INPUT
.
subroutine print_bitset_string(string, set)
: Writes a BITSETS
literal to the allocatable default character
STRING
, representing the individual bit values in the bitsets,
SET
.
subroutine print_bitset_unit(unit, set, status, advance)
: Writes a bitsets literal to the logical unit, UNIT
, representing
the individual bit values in the bitsets, SET
. If STATUS
is not
present and an error occurs then processing stops with an error
message. If STATUS
is present then it has the error code SUCCESS
if no error occurs, has the value ALLOC_FAULT
if failure is due to
the allocation of a temporary and, has the value WRITE_FAULT
if an
error occurs in the write to the unit. By default or if ADVANCE
is
present with the value 'YES'
, advancing output is used. If ADVANCE
is present with the value 'NO'
, then the current record is not
advanced by the write.
subroutine read_bitset_string(string, set, status)
: Uses the bitsets literal in the default character STRING
, to
define the bitset, SET
. The literal may be preceded by an an
arbitrary sequence of blank characters. If STATUS
is not present
then an error results in the sending an error message to ERROR_UNIT
and the termination of the program. If STATUS
is present then it has
the error code SUCCESS
if no error occurs, the value
INVALID_STRING
if the sequence of characters after an initial
sequence of blanks is not a BITSETS
literal, the value
INVALID_ARRAY_SIZE
if the literal's bit size is too large to be
represented by the bit size integer kind, the value ALLOC_FAULT if
allocation of SET
failed for the specified BITSIZE
, or
INVALID_INTEGER
if the HEX literal constant is too large to be
represented by a bit size binary integer. If STATUS
is present with
the value SUCCESS
then SET
is defined, otherwise it is not
defined.
subroutine read_bitset_unit(unit, set, status)
: Uses the bitsets literal at the current position in the formatted
file with logical unit, UNIT
, to define the bitset, SET
. The
literal may be preceded by an an arbitrary sequence of blank
characters. If STATUS
is not present then an error results in the
sending an error message to ERROR_UNIT
and the termination of the
program. If STATUS
is present then it has the error code SUCCESS
if no error occurs, the value INVALID_STRING
if the sequence of
characters after an initial sequence of blanks is not a BITSETS
literal, the value INVALID_ARRAY_SIZE
if the literal's bitsize is
too large to be represented by the bitsize integer kind, the value
ALLOC_FAULT
if allocation of SET
failed for the specified bitsize,
or INVALID_INTEGER
if the HEX
literal constant is too large to be
represented by a bitsize binary integer. If STATUS
is present with
the value SUCCESS
then SET
is defined, otherwise it is not
defined.
elemental subroutine set_bit(set, pos)
: Sets the value at the POS
position in SET
, provided the position
is valid. If the position is less than 0 or greater than BITS(SET)-1
then SET
is unchanged.
pure subroutine set_range(set, start_pos, stop_pos)
: Sets all valid bits to 1 from the START_POS
to the STOP_POS
positions in SET
. If STOP_POS < START_POS
no bits are
changed. Positions outside the range 0 to BITS(SET)-1
are ignored.
elemental function test(set, pos)
: Returns .TRUE.
if the POS
position is set, .FALSE.
otherwise. If POS
is negative or greater than BITS(SET) - 1
the
result is .FALSE.
.
elemental function value(set, pos)
: Returns 1 if the POS
position is set, 0 otherwise. If POS
is
negative or greater than BITS(SET) - 1
the result is 0.