[comp.lang.ada] unsigned integers in Ada

rds@moss.ATT.COM (04/21/88)

How does one implement an unsigned integer in Ada and have a maximum
value equal to 2**(number of bits) in any given implementation?

Is this an oversight or does Ada really limit maximum integer
values to 2**(# of bits MINUS ONE)-1. More verbosely put
declaring 

     type Pointer is range 0..(2**32)-1;
     for Pointer'SIZE use 32;

is invalid for a 32 bit integer implementation because (2**32)-1
is not in the INTEGER'RANGE -(2**31)..(2**31)-1. How can I use the
leftover bit?

     subtype Pointer is INTEGER range 0..(2**32)-1;
     for Pointer'SIZE use 32;

is illegal because it is not a <first named subtype> LRM 13.1 (3)

WHAT IS A FIRST NAMED SUBTYPE?? And can someone give an example?

Any assistance will keep the hair in my head for another day (Ada problem).

stt@ada-uts (04/26/88)

Ada requires that all predefined integer types be
symmetric about zero, excepting an extra negative value
(LRM 3.5.4:7), and that all integer types be
derived directly or indirectly from one of these.
However, it would be permissible to define a LONG_INTEGER
which is signed 64 bits, and then define a subtype
of that which is unsigned 32 bits, and implement it
using unsigned 32 bit representation in memory
(though the arithmetic would still have to allow
64-bit intermediate results without NUMERIC_ERROR).

Representation clauses are only allowed for "first named subtypes"
(defined in LRM 13.1:3).  The first named subtype is the
subtype identified in a "type definition."  The type
is generally anonymous and unconstrained; the identifier specified designates
a subtype.  For example
    type My_Int is range 0..15;
This is formally equivalent to (see LRM 3.5.4:5,6):
    type <anon> is new <predefined-int-type>;
    subtype My_Int is <anon> range 0..15;
"My_Int" is therefore the "first named subtype."

Allowing unsigned types in general has been proposed as
a possible addition for the next revision of Ada, but
beware that it would imply NUMERIC_ERROR if the arithmetic
result goes negative, rather than just wrapping around, as
most "C" programmers expect.  Furthermore, there would
have to be a rule for deciding which predefined
type is selected for any given integer type definition with
a non-negative range (the signed one or the unsigned one), since
this would determine the legality of negative intermediate
arithmetic results.

Tucker Taft
Intermetrics, Inc.
Cambridge, MA  02138

garym@telesoft.UUCP (Gary Morris @flash) (04/27/88)

> From: ncar!noao!mcdsun!mcdchg!clyde!rds%moss.ATT.COM@AMES.ARC.NASA.GOV
> Subject: unsigned integers in Ada
> 
> How does one implement an unsigned integer in Ada and have a maximum
> value equal to 2**(number of bits) in any given implementation?
The LRM requires that predefined integer types be symmetrical around zero
(LRM 3.5.4 (7)).  It is illegal to provide an unsigned integer type in
package standard.  So the largest type provided on a 32 bit machine will
normally be -(2**31)..(2**31)-1.  That means that you can't declare a type
that is range 0..(2**32)-1 unless the compiler supports a standard integer
type large enough to contain that range (and it must be symmetrical around
zero)!  The following declaration would require 33 bit or larger (ie: 64
bit) integer defined in package standard in order for the compiler to accept
it:

	type Unsigned_Long is range 0..(2**32)-1;	-- 64 bit base type
	for  Unsigned_Long'size use 32;			-- packed in 32 bits

The expressions using the Unsigned_Long would have to be evaluated using
64-bit arithmetic for intermediate results.  Due to these restrictions,
unsigned types in Ada are just a form of packing.  The compiler is not
allowed to perform unsigned operations on the type as you would in assembly
making operations on such types less efficient.

It would be interesting to hear why the language designers chose to restrict
types this way.  The following declaration is legal on most compilers
because most support a integer type in package standard that is 32 bits.
The operations are still done using the 32 bit base type that contains the
positive range you want but must also be symmetrical around zero:

	type Unsigned_Word is range 0..(2**16)-1;	-- 32 bit base type
	for  Unsigned_Word'size use 16;			-- packed in 16 bits

>      subtype Pointer is INTEGER range 0..(2**32)-1;
>      for Pointer'SIZE use 32;
> 
> is illegal because it is not a <first named subtype> LRM 13.1 (3)
> WHAT IS A FIRST NAMED SUBTYPE?? And can someone give an example?
You can't change the representation of a subtype unless it is a first-named
subtype since subtypes derive their representation from the base type.
A <first named subtype> is a subtype declared by a type declaration where
the base type is anonymous.  For example:
	type T is range L .. R;		-- example from LRM 3.5.4 (5)

--GaryM
P.S. Thanks go to JPD for explaining this issue.

Gary Morris		UUCP:	ucbvax!ucsd!telesoft!garym
TeleSoft, San Diego		telesoft!garym@ucsd.edu
(619) 457-2700		ARPA:	telesoft!garym@ucsd.ARPA