Skip to content

API for a bitset data type  #221

Closed
Closed
@wclodius2

Description

@wclodius2

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:

  1. How the range is defined for CLEAR_RANGE, FLIP_RANGE, and
    SET_RANGE. I have roughly followed Java's bitset here.

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

  3. That the I/O procedures INPUT, OUTPUT, PRINT_BITSET, and
    READ_BITSET have STATUS flags.

  4. That the procedures often ignore user specification of positions
    outside the range 0 to BITS-1. An alternative is to make the
    procedures impure and invoking ERROR STOP. Another option is to
    add a STATUS argument, but I am reluctant to do that for a simple
    user error.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    implementationImplementation in experimental and submission of a PR

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions