Question

Array of single bits in ada?

If I wrote

type u1 is range 0 .. 1;
type Index is range 0 .. 499999;
type U1Array is array(Index) of u1;

can I assume, that this will be a bit vector, which is packing the single u1 instances efficiently? I.e. 8 Bits/Byte?

 5  91  5
1 Jan 1970

Solution

 6

Better to check than to assume. One can check the representation of a data type using -gnatR2 (see here). A quick check below shows that U1Array will not be a bit vector. The size of its components will be 8 [bits], its total size will be 4,000,000 [bits].

To have it as a bit vector, you need to make it a "packed" array (see RM 13.2). The size of the packed array will be 500,000 [bits]. The size of its components will be 1 [bit].

foo.ads

package Foo is

   type u1 is range 0 .. 1;
   type Index is range 0 .. 499999;
   
   type U1Array is array(Index) of u1;
   type U1PackedArray is array(Index) of u1 with Pack;   

end Foo;

output

$ gcc -c foo.ads -gnatR2

Representation information for unit Foo (spec)
----------------------------------------------

for U1'Object_Size use 8;
for U1'Value_Size use 1;
for U1'Alignment use 1;

for Index'Object_Size use 32;
for Index'Value_Size use 19;
for Index'Alignment use 4;

for U1array'Size use 4000000;
for U1array'Alignment use 1;
for U1array'Component_Size use 8;

for U1packedarray'Size use 500000;
for U1packedarray'Alignment use 1;
for U1packedarray'Component_Size use 1;
2024-07-07
DeeDee

Solution

 4

Since U1 is a signed integer type (defined using range), its base type U1'Base will be roughly symmetrical around zero, including as a minimum the range -1 .. 1. On most systems, a suitable hardware type will be selected, typically one byte, -128 .. 127, or the equivalent of Interfaces.Integer_8. This base type is likely to be used as the representation of components of type U1 in the absence of any representation clauses.

When you need specific representations in Ada, you should say so:

type U1 is mod 2 with Size => 1;
type U1array is array (Index) of U1 with Component_Size => U1'Size, Size => Index'Last + 1;

The compiler will then use one bit per value in the array, packed to the bit level.

Note that the Pack aspect is only a compiler hint; the compiler is free to ignore it or to pack things less fully than possible. Size and Component_Size, on the other hand, must be obeyed fully or rejected if the compiler cannot do so.

2024-07-08
Jeffrey R. Carter