[Home] [Prev] [Next] [Index]

3.5 Scalar Types

3.5 Scalar Types

1
Scalar types comprise enumeration types, integer types, and real types. Enumeration types and integer types are called discrete types; each value of a discrete type has a position number which is an integer value. Integer types and real types are called numeric types. [All scalar types are ordered, that is, all relational operators are predefined for their values.]

Syntax

2
range_constraint ::=  range range

3
range ::=  range_attribute_reference
   | simple_expression .. simple_expression

3.a
Discussion:  These need to be simple_expressions rather than more general expressions because ranges appear in membership tests and other contexts where expression .. expression would be ambiguous.

4
A range has a lower bound and an upper bound and specifies a subset of the values of some scalar type (the type of the range). A range with lower bound L and upper bound R is described by "L .. R". If R is less than L, then the range is a null range, and specifies an empty set of values. Otherwise, the range specifies the values of the type from the lower bound to the upper bound, inclusive. A value belongs to a range if it is of the type of the range, and is in the subset of values specified by the range. A value satisfies a range constraint if it belongs to the associated range. One range is included in another if all values that belong to the first range also belong to the second.

Name Resolution Rules

5
For a subtype_indication containing a range_constraint, either directly or as part of some other scalar_constraint, the type of the range shall resolve to that of the type determined by the subtype_mark of the subtype_indication. For a range of a given type, the simple_expressions of the range (likewise, the simple_expressions of the equivalent range for a range_attribute_reference) are expected to be of the type of the range.

5.a
Discussion:  In Ada 9X, constraints only appear within subtype_indications; things that look like constraints that appear in type declarations are called something else like range_specifications.

5.b
We say "the expected type is ..." or "the type is expected to be ..." depending on which reads better.  They are fundamentally equivalent, and both feed into the type resolution rules of clause 8.6.

5.c
In some cases, it doesn't work to use expected types. For example, in the above rule, we say that the "type of the range shall resolve to ..." rather than "the expected type for the range is ...". We then use "expected type" for the bounds. If we used "expected" at both points, there would be an ambiguity, since one could apply the rules of 8.6 either on determining the type of the range, or on determining the types of the individual bounds.  It is clearly important to allow one bound to be of a universal type, and the other of a specific type, so we need to use "expected type" for the bounds. Hence, we used "shall resolve to" for the type of the range as a whole. There are other situations where "expected type" is not quite right, and we use "shall resolve to" instead.

Static Semantics

6
The base range of a scalar type is the range of finite values of the type that can be represented in every unconstrained object of the type; it is also the range supported at a minimum for intermediate values during the evaluation of expressions involving predefined operators of the type.

6.a
Implementation Note: Note that in some machine architectures intermediates in an expression (particularly if static), and register-resident variables might accommodate a wider range.  The base range does not include the values of this wider range that are not assignable without overflow to memory-resident objects.

6.b
Ramification: The base range of an enumeration type is the range of values of the enumeration type.

6.c
Reason: If the representation supports infinities, the base range is nevertheless restricted to include only the representable finite values, so that 'Base'First and 'Base'Last are always guaranteed to be finite.

6.d
To be honest: By a "value that can be assigned without overflow" we don't mean to restrict ourselves to values that can be represented exactly. Values between machine representable values can be assigned, but on subsequent reading, a slightly different value might be retrieved, as (partially) determined by the number of digits of precision of the type.

7
[A constrained scalar subtype is one to which a range constraint applies.] The range of a constrained scalar subtype is the range associated with the range constraint of the subtype. The range of an unconstrained scalar subtype is the base range of its type.

Dynamic Semantics

8
A range is compatible with a scalar subtype if and only if it is either a null range or each bound of the range belongs to the range of the subtype. A range_constraint is compatible with a scalar subtype if and only if its range is compatible with the subtype.

8.a
Ramification: Only range_constraints (explicit or implicit) impose conditions on the values of a scalar subtype.  The other scalar_constraints, digit_constraints and delta_constraints impose conditions on the subtype denoted by the subtype_mark in a subtype_indication, but don't impose a condition on the values of the subtype being defined.  Therefore, a scalar subtype is not called constrained if all that applies to it is a digits_constraint. Decimal subtypes are subtle, because a digits_constraint without a range_constraint nevertheless includes an implicit range_constraint.

9
The elaboration of a range_constraint consists of the evaluation of the range. The evaluation of a range determines a lower bound and an upper bound. If simple_expressions are given to specify bounds, the evaluation of the range evaluates these simple_expressions in an arbitrary order, and converts them to the type of the range. If a range_attribute_reference is given, the evaluation of the range consists of the evaluation of the range_attribute_reference.

10
Attributes

11
For every scalar subtype S, the following attributes are defined:

12S'First   S'First denotes the lower bound of the range of S.  The value of this attribute is of the type of S.

12.a
Ramification: Evaluating S'First never raises Constraint_Error.

13 S'Last   S'Last denotes the upper bound of the range of S.  The value of this attribute is of the type of S.

13.a
Ramification: Evaluating S'Last never raises Constraint_Error.

14 S'Range   S'Range is equivalent to the range S'First .. S'Last.

15 S'Base   S'Base denotes an unconstrained subtype of the type of S. This unconstrained subtype is called the base subtype of the type.

16 S'Min   S'Min denotes a function with the following specification:

17
function S'Min(Left, Right : S'Base)
  return S'Base

18
The function returns the lesser of the values of the two parameters.

18.a
Discussion:  The formal parameter names are italicized because they cannot be used in calls -     see 6.4. Such a specification cannot be written by the user because an attribute_reference is not permitted as the designator of a user-defined function, nor can its formal parameters be anonymous.

19 S'Max   S'Max denotes a function with the following specification:

20
function S'Max(Left, Right : S'Base)
  return S'Base

21
The function returns the greater of the values of the two parameters.

22 S'Succ   S'Succ denotes a function with the following specification:

23
function S'Succ(Arg : S'Base)
  return S'Base

24
For an enumeration type, the function returns the value whose position number is one more than that of the value of Arg; Constraint_Error is raised if there is no such value of the type. For an integer type, the function returns the result of adding one to the value of Arg. For a fixed point type, the function returns the result of adding small to the value of Arg. For a floating point type, the function returns the machine number (as defined in 3.5.7) immediately above the value of Arg; Constraint_Error is raised if there is no such machine number.

24.a
Ramification: S'Succ for a modular integer subtype wraps around if the value of Arg is S'Base'Last.  S'Succ for a signed integer subtype might raise Constraint_Error if the value of Arg is S'Base'Last, or it might return the out-of-base-range value S'Base'Last+1, as is permitted for all predefined numeric operations.

25 S'Pred   S'Pred denotes a function with the following specification:

26
function S'Pred(Arg : S'Base)
  return S'Base

27
For an enumeration type, the function returns the value whose position number is one less than that of the value of Arg; Constraint_Error is raised if there is no such value of the type. For an integer type, the function returns the result of subtracting one from the value of Arg. For a fixed point type, the function returns the result of subtracting small from the value of Arg. For a floating point type, the function returns the machine number (as defined in 3.5.7) immediately below the value of Arg; Constraint_Error is raised if there is no such machine number.

27.a
Ramification: S'Pred for a modular integer subtype wraps around if the value of Arg is S'Base'First.  S'Pred for a signed integer subtype might raise Constraint_Error if the value of Arg is S'Base'First, or it might return the out-of-base-range value S'Base'First-1, as is permitted for all predefined numeric operations.

28 S'Wide_Image   S'Wide_Image denotes a function with the following specification:

29
function S'Wide_Image(Arg : S'Base)
  return Wide_String

30
The function returns an image of the value of Arg, that is, a sequence of characters representing the value in display form. The lower bound of the result is one.

31
The image of an integer value is the corresponding decimal literal, without underlines, leading zeros, exponent, or trailing spaces, but with a single leading character that is either a minus sign or a space.

31.a
Implementation Note: If the machine supports negative zeros for signed integer types, it is not specified whether "-0" or " 0" should be returned for negative zero.  We don't have enough experience with such machines to know what is appropriate, and what other languages do.  In any case, the implementation should be consistent.

32
The image of an enumeration value is either the corresponding identifier in upper case or the corresponding character literal (including the two apostrophes); neither leading nor trailing spaces are included. For a nongraphic character (a value of a character type that has no enumeration literal associated with it), the result is a corresponding language-defined or implementation-defined name in upper case (for example, the image of the nongraphic character identified as nul is "NUL" - the quotes are not part of the image).

32.a
Implementation Note: For an enumeration type T that has "holes" (caused by an enumeration_representation_clause), T'Wide_Image should raise Program_Error if the value is one of the holes (which is a bounded error anyway, since holes can be generated only via uninitialized variables and similar things.

33
The image of a floating point value is a decimal real literal best approximating the value (rounded away from zero if halfway between) with a single leading character that is either a minus sign or a space, a single digit (that is nonzero unless the value is zero), a decimal point, S'Digits-1 (see 3.5.8) digits after the decimal point (but one if S'Digits is one), an upper case E, the sign of the exponent (either + or -), and two or more digits (with leading zeros if necessary) representing the exponent. If S'Signed_Zeros is True, then the leading character is a minus sign for a negatively signed zero.

33.a
To be honest: Leading zeros are present in the exponent only if necessary to make the exponent at least two digits.

33.b
Reason: This image is intended to conform to that produced by Text_IO.Float_IO.Put in its default format.

33.c
Implementation Note: The rounding direction is specified here to ensure portability of output results.

34
The image of a fixed point value is a decimal real literal best approximating the value (rounded away from zero if halfway between) with a single leading character that is either a minus sign or a space, one or more digits before the decimal point (with no redundant leading zeros), a decimal point, and S'Aft (see 3.5.10) digits after the decimal point.

34.a
Reason: This image is intended to conform to that produced by Text_IO.Fixed_IO.Put.

34.b
Implementation Note: The rounding direction is specified here to ensure portability of output results.

34.c
Implementation Note: For a machine that supports negative zeros, it is not specified whether "-0.000" or " 0.000" is returned. See corresponding comment above about integer types with signed zeros.

35 S'Image   S'Image denotes a function with the following specification:

36
function S'Image(Arg : S'Base)
  return String

37
The function returns an image of the value of Arg as a String. The lower bound of the result is one.  The image has the same sequence of graphic characters as that defined for S'Wide_Image if all the graphic characters are defined in Character; otherwise the sequence of characters is implementation defined (but no shorter than that of S'Wide_Image for the same value of Arg).

37.a
Implementation defined:  The sequence of characters of the value returned by S'Image when some of the graphic characters of S'Wide_Image are not defined in Character.

38
S'Wide_Width   S'Wide_Width denotes the maximum length of a Wide_String returned by S'Wide_Image over all values of the subtype S.  It denotes zero for a subtype that has a null range.  Its type is universal_integer.

38.a
Change: Added Wide_Width attribute as per WG9 resolution.

39 S'Width   S'Width denotes the maximum length of a String returned by S'Image over all values of the subtype S.  It denotes zero for a subtype that has a null range.  Its type is universal_integer.

40 S'Wide_Value   S'Wide_Value denotes a function with the following specification:

41
function S'Wide_Value(Arg : Wide_String)
  return S'Base

42
This function returns a value given an image of the value as a Wide_String, ignoring any leading or trailing spaces.

43
For the evaluation of a call on S'Wide_Value for an enumeration subtype S, if the sequence of characters of the parameter (ignoring leading and trailing spaces) has the syntax of an enumeration literal and if it corresponds to a literal of the type of S (or corresponds to the result of S'Wide_Image for a nongraphic character of the type), the result is the corresponding enumeration value; otherwise Constraint_Error is raised.

43.a
Discussion:  It's not crystal clear that Range_Check is appropriate here, but it doesn't seem worthwhile to invent a whole new check name just for this weird case, so we decided to lump it in with Range_Check.

44
For the evaluation of a call on S'Wide_Value (or S'Value) for an integer subtype S, if the sequence of characters of the parameter (ignoring leading and trailing spaces) has the syntax of an integer literal, with an optional leading sign character (plus or minus for a signed type; only plus for a modular type), and the corresponding numeric value belongs to the base range of the type of S, then that value is the result; otherwise Constraint_Error is raised.

44.a
Change: Changed the syntax accepted by Wide_Value for modular types to match Modular_IO.Get; the intent is that these be the same. In particular, the number can have a plus sign or no sign; it cannot have a minus sign.

44.b
Discussion:  We considered allowing 'Value to return a representable but out-of-range value without a Constraint_Error.  However, we currently require (see 4.9) in an assignment_statement like "X := <numeric_literal>;" that the value of the numeric-literal be in X's base range (at compile time), so it seems unfriendly and confusing to have a different range allowed for 'Value. Furthermore, for modular types, without the requirement for being in the base range, 'Value would have to handle arbitrarily long literals (since overflow never occurs for modular types).

45
For the evaluation of a call on S'Wide_Value (or S'Value) for a real subtype S, if the sequence of characters of the parameter (ignoring leading and trailing spaces) has the syntax of one of the following:

46 · numeric_literal

47 · numeral.[exponent]

48 · .numeral[exponent]

49 · base#based_numeral.#[exponent]

50 · base#.based_numeral#[exponent]

51
with an optional leading sign character (plus or minus), and if the corresponding numeric value belongs to the base range of the type of S, then that value is the result; otherwise Constraint_Error is raised. The sign of a zero value is preserved (positive if none has been specified) if S'Signed_Zeros is True.

52 S'Value   S'Value denotes a function with the following specification:

53
function S'Value(Arg : String)
  return S'Base

54
This function returns a value given an image of the value as a String, ignoring any leading or trailing spaces.

55
For the evaluation of a call on S'Value for an enumeration subtype S, if the sequence of characters of the parameter (ignoring leading and trailing spaces) has the syntax of an enumeration literal and if it corresponds to a literal of the type of S (or corresponds to the result of S'Image for a value of the type), the result is the corresponding enumeration value; otherwise Constraint_Error is raised. For a numeric subtype S, the evaluation of a call on S'Value with Arg of type String is equivalent to a call on S'Wide_Value for a corresponding Arg of type Wide_String.

55.a
Reason: S'Value is subtly different from S'Wide_Value for enumeration subtypes since S'Image might produce a different sequence of characters than S'Wide_Image if the enumeration literal uses characters outside of the predefined type Character. That is why we don't just define S'Value in terms of S'Wide_Value for enumeration subtypes. S'Value and S'Wide_Value for numeric subtypes yield the same result given the same sequence of characters.

Implementation Permissions

56
An implementation may extend the Wide_Value, [Value, Wide_Image, and Image] attributes of a floating point type to support special values such as infinities and NaNs.

56.a
Proof: The permission is really only necessary for Wide_Value, because Value is defined in terms of Wide_Value, and because the behavior of Wide_Image and Image is already unspecified for things like infinities and NaNs.

56.b
Reason: This is to allow implementations to define full support for IEEE arithmetic. See also the similar permission for Get in A.10.9.

NOTES

57 19
The evaluation of S'First or S'Last never raises an exception. If a scalar subtype S has a nonnull range, S'First and S'Last belong to this range.  These values can, for example, always be assigned to a variable of subtype S.

57.a
Discussion:  This paragraph addresses an issue that came up with Ada 83, where for fixed point types, the end points of the range specified in the type definition were not necessarily within the base range of the type.  However, it was later clarified (and we reconfirm it in 3.5.9, "Fixed Point Types") that the First and Last attributes reflect the true bounds chosen for the type, not the bounds specified in the type definition (which might be outside the ultimately chosen base range).

58 20
For a subtype of a scalar type, the result delivered by the attributes Succ, Pred, and Value might not belong to the subtype; similarly, the actual parameters of the attributes Succ, Pred, and Image need not belong to the subtype.

59 21
For any value V (including any nongraphic character) of an enumeration subtype S, S'Value(S'Image(V)) equals V, as does S'Wide_Value(S'Wide_Image(V)).  Neither expression ever raises Constraint_Error.

Examples

60
Examples of ranges:

61
-10 .. 10
X .. X + 1
0.0 .. 2.0*Pi
Red .. Green     -- see 3.5.1
1 .. 0           -- a null range
Table'Range      -- a range attribute reference (see 3.6)

62
Examples of range constraints:

63
range -999.0 .. +999.0
range S'First+1 .. S'Last-1

Incompatibilities With Ada 83

63.a
S'Base is no longer defined for nonscalar types. One conceivable existing use of S'Base for nonscalar types is S'Base'Size where S is a generic formal private type. However, that is not generally useful because the actual subtype corresponding to S might be a constrained array or discriminated type, which would mean that S'Base'Size might very well overflow (for example, S'Base'Size where S is a constrained subtype of String will generally be 8 * (Integer'Last + 1)). For derived discriminated types that are packed, S'Base'Size might not even be well defined if the first subtype is constrained, thereby allowing some amount of normally required "dope" to have been squeezed out in the packing.  Hence our conclusion is that S'Base'Size is not generally useful in a generic, and does not justify keeping the attribute Base for nonscalar types just so it can be used as a prefix.

Extensions to Ada 83

63.b
The attribute S'Base for a scalar subtype is now permitted anywhere a subtype_mark is permitted. S'Base'First .. S'Base'Last is the base range of the type. Using an attribute_definition_clause, one cannot specify any subtype-specific attributes for the subtype denoted by S'Base (the base subtype).

63.c
The attribute S'Range is now allowed for scalar subtypes.

63.d
The attributes S'Min and S'Max are now defined, and made available for all scalar types.

63.e
The attributes S'Succ, S'Pred, S'Image, S'Value, and S'Width are now defined for real types as well as discrete types.

63.f
Wide_String versions of S'Image and S'Value are defined. These are called S'Wide_Image and S'Wide_Value to avoid introducing ambiguities involving uses of these attributes with string literals.

Wording Changes From Ada 83

63.g
We now use the syntactic category range_attribute_reference since it is now syntactically distinguished from other attribute references.

63.h
The definition of S'Base has been moved here from 3.3.3 since it now applies only to scalar types.

63.i
More explicit rules are provided for nongraphic characters.

3.5.1 Enumeration Types

1
[An enumeration_type_definition defines an enumeration type.]

Syntax

2
enumeration_type_definition ::=
   (enumeration_literal_specification {, enumeration_literal_specification})

3
enumeration_literal_specification ::=  defining_identifier | defining_character_literal

4
defining_character_literal ::= character_literal

Legality Rules

5
[The defining_identifiers and defining_character_literals listed in an enumeration_type_definition shall be distinct.]

5.a
Proof: This is a ramification of the normal disallowance of homographs explicitly declared immediately in the same declarative region.

Static Semantics

6
Each enumeration_literal_specification is the explicit declaration of the corresponding enumeration literal: it declares a parameterless function, whose defining name is the defining_identifier or defining_character_literal, and whose result type is the enumeration type.

6.a
Reason: This rule defines the profile of the enumeration literal, which is used in the various types of conformance.

6.b
Ramification: The parameterless function associated with an enumeration literal is fully defined by the enumeration_type_definition; a body is not permitted for it, and it never fails the Elaboration_Check when called.

7
Each enumeration literal corresponds to a distinct value of the enumeration type, and to a distinct position number. The position number of the value of the first listed enumeration literal is zero; the position number of the value of each subsequent enumeration literal is one more than that of its predecessor in the list.

8
[The predefined order relations between values of the enumeration type follow the order of corresponding position numbers.]

9
[If the same defining_identifier or defining_character_literal is specified in more than one enumeration_type_definition, the corresponding enumeration literals are said to be overloaded.  At any place where an overloaded enumeration literal occurs in the text of a program, the type of the enumeration literal has to be determinable from the context (see 8.6).]

Dynamic Semantics

10
The elaboration of an enumeration_type_definition creates the enumeration type and its first subtype, which is constrained to the base range of the type.

10.a
Ramification: The first subtype of a discrete type is always constrained, except in the case of a derived type whose parent subtype is Whatever'Base.

11
When called, the parameterless function associated with an enumeration literal returns the corresponding value of the enumeration type.

NOTES

12 22
If an enumeration literal occurs in a context that does not otherwise suffice to determine the type of the literal, then qualification by the name of the enumeration type is one way to resolve the ambiguity (see 4.7).

Examples

13
Examples of enumeration types and subtypes:

14
type Day    is (Mon, Tue, Wed, Thu, Fri, Sat, Sun);
type Suit   is (Clubs, Diamonds, Hearts, Spades);
type Gender is (M, F);
type Level  is (Low, Medium, Urgent);
type Color  is (White, Red, Yellow, Green, Blue, Brown, Black);
type Light  is (Red, Amber, Green); -- Red and Green are overloaded

15
type Hexa   is ('A', 'B', 'C', 'D', 'E', 'F');
type Mixed  is ('A', 'B', '*', B, None, '?', '%');

16
subtype Weekday is Day   range Mon .. Fri;
subtype Major   is Suit  range Hearts .. Spades;
subtype Rainbow is Color range Red .. Blue;  --  the Color Red, not the Light

Wording Changes From Ada 83

16.a
The syntax rule for defining_character_literal is new. It is used for the defining occurrence of a character_literal, analogously to defining_identifier. Usage occurrences use the name or selector_name syntactic categories.

16.b
We emphasize the fact that an enumeration literal denotes a function, which is called to produce a value.

3.5.2 Character Types

Static Semantics

1
An enumeration type is said to be a character type if at least one of its enumeration literals is a character_literal.

2
The predefined type Character is a character type whose values correspond to the 256 code positions of Row 00 (also known as Latin-1) of the ISO 10646 Basic Multilingual Plane (BMP). Each of the graphic characters of Row 00 of the BMP has a corresponding character_literal in Character. Each of the nongraphic positions of Row 00 (0000-001F and 007F-009F) has a corresponding language-defined name, which is not usable as an enumeration literal, but which is usable with the attributes (Wide_)Image and (Wide_)Value; these names are given in the definition of type Character in A.1, "The Package Standard", but are set in italics.

3
The predefined type Wide_Character is a character type whose values correspond to the 65536 code positions of the ISO 10646 Basic Multilingual Plane (BMP). Each of the graphic characters of the BMP has a corresponding character_literal in Wide_Character. The first 256 values of Wide_Character have the same character_literal or language-defined name as defined for Character. The last 2 values of Wide_Character correspond to the nongraphic positions FFFE and FFFF of the BMP, and are assigned the language-defined names FFFE and FFFF.  As with the other language-defined names for nongraphic characters, the names FFFE and FFFF are usable only with the attributes (Wide_)Image and (Wide_)Value; they are not usable as enumeration literals. All other values of Wide_Character are considered graphic characters, and have a corresponding character_literal.

3.a
Reason: The language-defined names are not usable as enumeration literals to avoid "polluting" the name space.  Since Wide_Character is defined in Standard, if the names FFFE and FFFF were usable as enumeration literals, they would hide other nonoverloadable declarations with the same names in use-d packages.

3.b
ISO 10646 has not defined the meaning of all of the code positions from 0100 through FFFD, but they are all considered graphic characters by Ada to simplify the implementation, and to allow for revisions to ISO 10646. In ISO 10646, FFFE and FFFF are special, and will never be associated with graphic characters in any revision.

Implementation Permissions

4
In a nonstandard mode, an implementation may provide other interpretations for the predefined types Character and Wide_Character[, to conform to local conventions].

Implementation Advice

5
If an implementation supports a mode with alternative interpretations for Character and Wide_Character, the set of graphic characters of Character should nevertheless remain a proper subset of the set of graphic characters of Wide_Character. Any character set "localizations" should be reflected in the results of the subprograms defined in the language-defined package Characters.Handling (see A.3) available in such a mode. In a mode with an alternative interpretation of Character, the implementation should also support a corresponding change in what is a legal identifier_letter.

NOTES

6 23
The language-defined library package Characters.Latin_1 (see A.3.3) includes the declaration of constants denoting control characters, lower case characters, and special characters of the predefined type Character.

6.a
To be honest: The package ASCII does the same, but only for the first 128 characters of Character.  Hence, it is an obsolescent package, and we no longer mention it here.

7 24
A conventional character set such as EBCDIC can be declared as a character type; the internal codes of the characters can be specified by an enumeration_representation_clause as explained in clause 13.4.

Examples

8
Example of a character type:

9
type Roman_Digit is ('I', 'V', 'X', 'L', 'C', 'D', 'M');

Inconsistencies With Ada 83

9.a
The declaration of Wide_Character in package Standard hides use-visible declarations with the same defining identifier. In the unlikely event that an Ada 83 program had depended on such a use-visible declaration, and the program remains legal after the substitution of Standard.Wide_Character, the meaning of the program will be different.

Incompatibilities With Ada 83

9.b
The presence of Wide_Character in package Standard means that an expression such as

9.c
'a' = 'b'

9.d
is ambiguous in Ada 9X, whereas in Ada 83 both literals could be resolved to be of type Character.

9.e
The change in visibility rules (see 4.2) for character literals means that additional qualification might be necessary to resolve expressions involving overloaded subprograms and character literals.

Extensions to Ada 83

9.f
The type Character has been extended to have 256 positions, and the type Wide_Character has been added. Note that this change was already approved by the ARG for Ada 83 conforming compilers.

9.g
The rules for referencing character literals are changed (see 4.2), so that the declaration of the character type need not be directly visible to use its literals, similar to null and string literals. Context is used to resolve their type.

3.5.3 Boolean Types

Static Semantics

1
There is a predefined enumeration type named Boolean, [declared in the visible part of package Standard]. It has the two enumeration literals False and True ordered with the relation False < True. Any descendant of the predefined type Boolean is called a boolean type.

1.a
Implementation Note: An implementation is not required to support enumeration representation clauses on boolean types that impose an unacceptable implementation burden. See 13.4, "Enumeration Representation Clauses". However, it is generally straightforward to support representations where False is zero and True is 2**n - 1 for some n.

3.5.4 Integer Types

1
An integer_type_definition defines an integer type; it defines either a signed integer type, or a modular integer type. The base range of a signed integer type includes at least the values of the specified range. A modular type is an integer type with all arithmetic modulo a specified positive modulus; such a type corresponds to an unsigned type with wrap-around semantics.

Syntax

2
integer_type_definition ::= signed_integer_type_definition | modular_type_definition

3
signed_integer_type_definition ::= range static_simple_expression .. static_simple_expression

3.a
Discussion:  We don't call this a range_constraint, because it is rather different - not only is it required to be static, but the associated overload resolution rules are different than for normal range constraints.  A similar comment applies to real_range_specification. This used to be integer_range_specification but when we added support for modular types, it seemed overkill to have three levels of syntax rules, and just calling these signed_integer_range_specification and modular_range_specification loses the fact that they are defining different classes of types, which is important for the generic type matching rules.

4
modular_type_definition ::= mod static_expression

Name Resolution Rules

5
Each simple_expression in a signed_integer_type_definition is expected to be of any integer type; they need not be of the same type. The expression in a modular_type_definition is likewise expected to be of any integer type.

Legality Rules

6
The simple_expressions of a signed_integer_type_definition shall be static, and their values shall be in the range System.Min_Int .. System.Max_Int.

7
The expression of a modular_type_definition shall be static, and its value (the modulus) shall be positive, and shall be no greater than System.Max_Binary_Modulus if a power of 2, or no greater than System.Max_Nonbinary_Modulus if not.

7.a
Reason: For a 2's-complement machine, supporting nonbinary moduli greater than System.Max_Int can be quite difficult, whereas essentially any binary moduli are straightforward to support, up to 2*System.Max_Int+2, so this justifies having two separate limits.

Static Semantics

8
The set of values for a signed integer type is the (infinite) set of mathematical integers[, though only values of the base range of the type are fully supported for run-time operations]. The set of values for a modular integer type are the values from 0 to one less than the modulus, inclusive.

9
A signed_integer_type_definition defines an integer type whose base range includes at least the values of the simple_expressions and is symmetric about zero, excepting possibly an extra negative value. A signed_integer_type_definition also defines a constrained first subtype of the type, with a range whose bounds are given by the values of the simple_expressions, converted to the type being defined.

9.a
Implementation Note: The base range of a signed integer type might be much larger than is necessary to satisfy the aboved requirements.

10
A modular_type_definition defines a modular type whose base range is from zero to one less than the given modulus. A modular_type_definition also defines a constrained first subtype of the type with a range that is the same as the base range of the type.

11
There is a predefined signed integer subtype named Integer[, declared in the visible part of package Standard]. It is constrained to the base range of its type.

11.a
Reason: Integer is a constrained subtype, rather than an unconstrained subtype.  This means that on assignment to an object of subtype Integer, a range check is required.  On the other hand, an object of subtype Integer'Base is unconstrained, and no range check (only overflow check) is required on assignment.  For example, if the object is held in an extended-length register, its value might be outside of Integer'First .. Integer'Last.  All parameter and result subtypes of the predefined integer operators are of such unconstrained subtypes, allowing extended-length registers to be used as operands or for the result. In an earlier version of Ada 9X, Integer was unconstrained.  However, the fact that certain Constraint_Errors might be omitted or appear elsewhere was felt to be an undesirable upward inconsistency in this case. Note that for Float, the opposite conclusion was reached, partly because of the high cost of performing range checks when not actually necessary. Objects of subtype Float are unconstrained, and no range checks, only overflow checks, are performed for them.

12
Integer has two predefined subtypes, [declared in the visible part of package Standard:]

13
subtype Natural  is Integer range 0 .. Integer'Last;
subtype Positive is Integer range 1 .. Integer'Last;

14
A type defined by an integer_type_definition is implicitly derived from root_integer, an anonymous predefined (specific) integer type, whose base range is System.Min_Int .. System.Max_Int. However, the base range of the new type is not inherited from root_integer, but is instead determined by the range or modulus specified by the integer_type_definition. [Integer literals are all of the type universal_integer, the universal type (see 3.4.1) for the class rooted at root_integer, allowing their use with the operations of any integer type.]

14.a
Discussion:  This implicit derivation is not considered exactly equivalent to explicit derivation via a derived_type_definition.  In particular, integer types defined via a derived_type_definition inherit their base range from their parent type.  A type defined by an integer_type_definition does not necessarily inherit its base range from root_integer. It is not specified whether the implicit derivation from root_integer is direct or indirect, not that it really matters. All we want is for all integer types to be descendants of root_integer.

14.b
Implementation Note: It is the intent that even nonstandard integer types (see below) will be descendants of root_integer, even though they might have a base range that exceeds that of root_integer. This causes no problem for static calculations, which are performed without range restrictions (see 4.9).  However for run-time calculations, it is possible that Constraint_Error might be raised when using an operator of root_integer on the result of 'Val applied to a value of a nonstandard integer type.

15
The position number of an integer value is equal to the value.

16
For every modular subtype S, the following attribute is defined:

17
S'Modulus S'Modulus yields the modulus of the type of S, as a value of the type universal_integer.

Dynamic Semantics

18
The elaboration of an integer_type_definition creates the integer type and its first subtype.

19
For a modular type, if the result of the execution of a predefined operator (see 4.5) is outside the base range of the type, the result is reduced modulo the modulus of the type to a value that is within the base range of the type.

20
For a signed integer type, the exception Constraint_Error is raised by the execution of an operation that cannot deliver the correct result because it is outside the base range of the type. [For any integer type, Constraint_Error is raised by the operators "/", "rem", and "mod" if the right operand is zero.]

Implementation Requirements

21
In an implementation, the range of Integer shall include the range -2**15+1 .. +2**15-1.

22
If Long_Integer is predefined for an implementation, then its range shall include the range -2**31+1 .. +2**31-1.

23
System.Max_Binary_Modulus shall be at least 2**16.

Implementation Permissions

24
For the execution of a predefined operation of a signed integer type, the implementation need not raise Constraint_Error if the result is outside the base range of the type, so long as the correct result is produced.

24.a
Discussion:  Constraint_Error is never raised for operations on modular types, except for divide-by-zero (and rem/mod-by-zero).

25
An implementation may provide additional predefined signed integer types[, declared in the visible part of Standard], whose first subtypes have names of the form Short_Integer, Long_Integer, Short_Short_Integer, Long_Long_Integer, etc. Different predefined integer types are allowed to have the same base range. However, the range of Integer should be no wider than that of Long_Integer. Similarly, the range of Short_Integer (if provided) should be no wider than Integer. Corresponding recommendations apply to any other predefined integer types. There need not be a named integer type corresponding to each distinct base range supported by an implementation. The range of each first subtype should be the base range of its type.

25.a
Implementation defined:  The predefined integer types declared in Standard.

26
An implementation may provide nonstandard integer types, descendants of root_integer that are declared outside of the specification of package Standard, which need not have all the standard characteristics of a type defined by an integer_type_definition. For example, a nonstandard integer type might have an asymmetric base range or it might not be allowed as an array or loop index (a very long integer). Any type descended from a nonstandard integer type is also nonstandard. An implementation may place arbitrary restrictions on the use of such types; it is implementation defined whether operators that are predefined for "any integer type" are defined for a particular nonstandard integer type. [In any case, such types are not permitted as explicit_generic_actual_parameters for formal scalar types -see 12.5.2.]

26.a
Implementation defined:  Any nonstandard integer types and the operators defined for them.

27
For a one's complement machine, the high bound of the base range of a modular type whose modulus is one less than a power of 2 may be equal to the modulus, rather than one less than the modulus. It is implementation defined for which powers of 2, if any, this permission is exercised.

Implementation Advice

28
An implementation should support Long_Integer in addition to Integer if the target machine supports 32-bit (or longer) arithmetic. No other named integer subtypes are recommended for package Standard. Instead, appropriate named integer subtypes should be provided in the library package Interfaces (see B.2).

28.a
Implementation Note: To promote portability, implementations should explicitly declare the integer (sub)types Integer and Long_Integer in Standard, and leave other predefined integer types anonymous. For implementations that already support Byte_Integer, etc., upward compatibility argues for keeping such declarations in Standard during the transition period, but perhaps generating a warning on use. A separate package Interfaces in the predefined environment is available for pre-declaring types such as Integer_8, Integer_16, etc. See B.2. In any case, if the user declares a subtype (first or not) whose range fits in, for example, a byte, the implementation can store variables of the subtype in a single byte, even if the base range of the type is wider.

29
An implementation for a two's complement machine should support modular types with a binary modulus up to System.Max_Int*2+2. An implementation should support a nonbinary modulus up to Integer'Last.

29.a
Reason: Modular types provide bit-wise "and", "or", "xor", and "not" operations. It is important for systems programming that these be available for all integer types of the target hardware.

29.b
Ramification: Note that on a one's complement machine, the largest supported modular type would normally have a nonbinary modulus.  On a two's complement machine, the largest supported modular type would normally have a binary modulus.

29.c
Implementation Note: Supporting a nonbinary modulus greater than Integer'Last can impose an undesirable implementation burden on some machines.

NOTES

30 25
Integer literals are of the anonymous predefined integer type universal_integer.  Other integer types have no literals.  However, the overload resolution rules (see 8.6, "The Context of Overload Resolution") allow expressions of the type universal_integer whenever an integer type is expected.

31 26
The same arithmetic operators are predefined for all signed integer types defined by a signed_integer_type_definition (see 4.5, "Operators and Expression Evaluation"). For modular types, these same operators are predefined, plus bit-wise logical operators (and, or, xor, and not). In addition, for the unsigned types declared in the language-defined package Interfaces (see B.2), functions are defined that provide bit-wise shifting and rotating.

32 27
Modular types match a generic_formal_parameter_declaration of the form "type T is mod <>;"; signed integer types match "type T is range <>;" (see 12.5.2).

Examples

33
Examples of integer types and subtypes:

34
type Page_Num  is range 1 .. 2_000;
type Line_Size is range 1 .. Max_Line_Size;

35
subtype Small_Int   is Integer   range -10 .. 10;
subtype Column_Ptr  is Line_Size range 1 .. 10;
subtype Buffer_Size is Integer   range 0 .. Max;

36
type Byte        is mod 256; -- an unsigned byte
type Hash_Index  is mod 97;  -- modulus is prime

Extensions to Ada 83

36.a
An implementation is allowed to support any number of distinct base ranges for integer types, even if fewer integer types are explicitly declared in Standard.

36.b
Modular (unsigned, wrap-around) types are new.

Wording Changes From Ada 83

36.c
Ada 83's integer types are now called "signed" integer types, to contrast them with "modular" integer types.

36.d
Standard.Integer, Standard.Long_Integer, etc., denote constrained subtypes of predefined integer types, consistent with the Ada 9X model that only subtypes have names.

36.e
We now impose minimum requirements on the base range of Integer and Long_Integer.

36.f
We no longer explain integer type definition in terms of an equivalence to a normal type derivation, except to say that all integer types are by definition implicitly derived from root_integer. This is for various reasons.

36.g
First of all, the equivalence with a type derivation and a subtype declaration was not perfect, and was the source of various AIs (for example, is the conversion of the bounds static?  Is a numeric type a derived type with respect to other rules of the language?)

36.h
Secondly, we don't want to require that every integer size supported shall have a corresponding named type in Standard.  Adding named types to Standard creates nonportabilities.

36.i
Thirdly, we don't want the set of types that match a formal derived type "type T is new Integer;" to depend on the particular underlying integer representation chosen to implement a given user-defined integer type.  Hence, we would have needed anonymous integer types as parent types for the implicit derivation anyway.  We have simply chosen to identify only one anonymous integer type - root_integer, and stated that every integer type is derived from it.

36.j
Finally, the "fiction" that there were distinct preexisting predefined types for every supported representation breaks down for fixed point with arbitrary smalls, and was never exploited for enumeration types, array types, etc.  Hence, there seems little benefit to pushing an explicit equivalence between integer type definition and normal type derivation.

3.5.5 Operations of Discrete Types

Static Semantics

1
For every discrete subtype S, the following attributes are defined:

2 S'Pos   S'Pos denotes a function with the following specification:

3
function S'Pos(Arg : S'Base)
  return universal_integer

4
This function returns the position number of the value of Arg, as a value of type universal_integer.

5 S'Val   S'Val denotes a function with the following specification:

6
function S'Val(Arg : universal_integer)
  return S'Base

7
This function returns a value of the type of S whose position number equals the value of Arg. For the evaluation of a call on S'Val, if there is no value in the base range of its type with the given position number, Constraint_Error is raised.

7.a
Ramification: By the overload resolution rules, a formal parameter of type universal_integer allows an actual parameter of any integer type.

7.b
Reason: We considered allowing S'Val for a signed integer subtype S to return an out-of-range value, but since checks were required for enumeration and modular types anyway, the allowance didn't seem worth the complexity of the rule.

Implementation Advice

8
For the evaluation of a call on S'Pos for an enumeration subtype, if the value of the operand does not correspond to the internal code for any enumeration literal of its type [(perhaps due to an uninitialized variable)], then the implementation should raise Program_Error. This is particularly important for enumeration types with noncontiguous internal codes specified by an enumeration_representation_clause.

8.a
Reason: We say Program_Error here, rather than Constraint_Error, because the main reason for such values is uninitialized variables, and the normal way to indicate such a use (if detected) is to raise Program_Error. (Other reasons would involve the misuse of low-level features such as Unchecked_Conversion.)

NOTES

9 28
Indexing and loop iteration use values of discrete types.

10 29
The predefined operations of a discrete type include the assignment operation, qualification, the membership tests, and the relational operators; for a boolean type they include the short-circuit control forms and the logical operators; for an integer type they include type conversion to and from other numeric types, as well as the binary and unary adding operators - and +, the multiplying operators, the unary operator abs, and the exponentiation operator. The assignment operation is described in 5.2. The other predefined operations are described in Section 4.

11 30
As for all types, objects of a discrete type have Size and Address attributes (see 13.3).

12 31
For a subtype of a discrete type, the result delivered by the attribute Val might not belong to the subtype; similarly, the actual parameter of the attribute Pos need not belong to the subtype.  The following relations are satisfied (in the absence of an exception) by these attributes:

13
S'Val(S'Pos(X)) = X
S'Pos(S'Val(N)) = N

Examples

14
Examples of attributes of discrete subtypes:

15
--  For the types and subtypes declared in subclause 3.5.1 the following hold:

16
--  Color'First   = White,   Color'Last   = Black
--  Rainbow'First = Red,     Rainbow'Last = Blue

17
--  Color'Succ(Blue) = Rainbow'Succ(Blue) = Brown
--  Color'Pos(Blue)  = Rainbow'Pos(Blue)  = 4
--  Color'Val(0)     = Rainbow'Val(0)     = White

Extensions to Ada 83

17.a
The attributes S'Succ, S'Pred, S'Width, S'Image, and S'Value have been generalized to apply to real types as well (see 3.5, "Scalar Types").

3.5.6 Real Types

1
Real types provide approximations to the real numbers, with relative bounds on errors for floating point types, and with absolute bounds for fixed point types.

Syntax

2
real_type_definition ::=
   floating_point_definition | fixed_point_definition

Static Semantics

3
A type defined by a real_type_definition is implicitly derived from root_real, an anonymous predefined (specific) real type. [Hence, all real types, whether floating point or fixed point, are in the derivation class rooted at root_real.]

3.a
Ramification: It is not specified whether the derivation from root_real is direct or indirect, not that it really matters. All we want is for all real types to be descendants of root_real.

4
[Real literals are all of the type universal_real, the universal type (see 3.4.1) for the class rooted at root_real, allowing their use with the operations of any real type. Certain multiplying operators have a result type of universal_fixed (see 4.5.5), the universal type for the class of fixed point types, allowing the result of the multiplication or division to be used where any specific fixed point type is expected.]

Dynamic Semantics

5
The elaboration of a real_type_definition consists of the elaboration of the floating_point_definition or the fixed_point_definition.

Implementation Requirements

6
An implementation shall perform the run-time evaluation of a use of a predefined operator of root_real with an accuracy at least as great as that of any floating point type definable by a floating_point_definition.

6.a
Ramification: Static calculations using the operators of root_real are exact, as for all static calculations. See 4.9.

6.b
Implementation Note: The Digits attribute of the type used to represent root_real at run time is at least as great as that of any other floating point type defined by a floating_point_definition, and its safe range includes that of any such floating point type with the same Digits attribute. On some machines, there might be real types with less accuracy but a wider range, and hence run-time calculations with root_real might not be able to accommodate all values that can be represented at run time in such floating point or fixed point types.

Implementation Permissions

7
[For the execution of a predefined operation of a real type, the implementation need not raise Constraint_Error if the result is outside the base range of the type, so long as the correct result is produced, or the Machine_Overflows attribute of the type is false (see G.2).]

8

8.a
Implementation defined:  Any nonstandard real types and the operators defined for them.

An implementation may provide nonstandard real types, descendants of root_real that are declared outside of the specification of package Standard, which need not have all the standard characteristics of a type defined by a real_type_definition.  For example, a nonstandard real type might have an asymmetric or unsigned base range, or its predefined operations might wrap around or "saturate" rather than overflow (modular or saturating arithmetic), or it might not conform to the accuracy model (see G.2). Any type descended from a nonstandard real type is also nonstandard. An implementation may place arbitrary restrictions on the use of such types; it is implementation defined whether operators that are predefined for "any real type" are defined for a particular nonstandard real type. [In any case, such types are not permitted as explicit_generic_actual_parameters for formal scalar types - see 12.5.2.]

NOTES

9 32
As stated, real literals are of the anonymous predefined real type universal_real.  Other real types have no literals.  However, the overload resolution rules (see 8.6) allow expressions of the type universal_real whenever a real type is expected.

Wording Changes From Ada 83

9.a
The syntax rule for real_type_definition is modified to use the new syntactic categories floating_point_definition and fixed_point_definition, instead of floating_point_constraint and fixed_point_constraint, because the semantics of a type definition are significantly different than the semantics of a constraint.

9.b
All discussion of model numbers, safe ranges, and machine numbers is moved to 3.5.7, 3.5.8, and G.2. Values of a fixed point type are now described as being multiples of the small of the fixed point type, and we have no need for model numbers, safe ranges, etc. for fixed point types.

3.5.7 Floating Point Types

1
For floating point types, the error bound is specified as a relative precision by giving the required minimum number of significant decimal digits.

Syntax

2
floating_point_definition ::=
  digits static_expression [real_range_specification]

3
real_range_specification ::=
  range static_simple_expression .. static_simple_expression

Name Resolution Rules

4
The requested decimal precision, which is the minimum number of significant decimal digits required for the floating point type, is specified by the value of the expression given after the reserved word digits. This expression is expected to be of any integer type.

5
Each simple_expression of a real_range_specification is expected to be of any real type[; the types need not be the same].

Legality Rules

6
The requested decimal precision shall be specified by a static expression whose value is positive and no greater than System.Max_Base_Digits. Each simple_expression of a real_range_specification shall also be static. If the real_range_specification is omitted, the requested decimal precision shall be no greater than System.Max_Digits.

6.a
Reason: We have added Max_Base_Digits to package System.  It corresponds to the requested decimal precision of root_real.  System.Max_Digits corresponds to the maximum value for Digits that may be specified in the absence of a real_range_specification, for upward compatibility.  These might not be the same if root_real has a base range that does not include ± 10.0**(4*Max_Base_Digits).

7
A floating_point_definition is illegal if the implementation does not support a floating point type that satisfies the requested decimal precision and range.

7.a
Implementation defined:  What combinations of requested decimal precision and range are supported for floating point types.

Static Semantics

8
The set of values for a floating point type is the (infinite) set of rational numbers. The machine numbers of a floating point type are the values of the type that can be represented exactly in every unconstrained variable of the type. The base range (see 3.5) of a floating point type is symmetric around zero, except that it can include some extra negative values in some implementations.

8.a
Implementation Note: For example, if a 2's complement representation is used for the mantissa rather than a sign-mantissa or 1's complement representation, then there is usually one extra negative machine number.

8.b
To be honest: If the Signed_Zeros attribute is True, then minus zero could in a sense be considered a value of the type. However, for most purposes, minus zero behaves the same as plus zero.

9
The base decimal precision of a floating point type is the number of decimal digits of precision representable in objects of the type. The safe range of a floating point type is that part of its base range for which the accuracy corresponding to the base decimal precision is preserved by all predefined operations.

9.a
Implementation Note: In most cases, the safe range and base range are the same. However, for some hardware, values near the boundaries of the base range might result in excessive inaccuracies or spurious overflows when used with certain predefined operations.  For such hardware, the safe range would omit such values.

10
A floating_point_definition defines a floating point type whose base decimal precision is no less than the requested decimal precision. If a real_range_specification is given, the safe range of the floating point type (and hence, also its base range) includes at least the values of the simple expressions given in the real_range_specification. If a real_range_specification is not given, the safe (and base) range of the type includes at least the values of the range -10.0**(4*D) .. +10.0**(4*D) where D is the requested decimal precision. [The safe range might include other values as well.  The attributes Safe_First and Safe_Last give the actual bounds of the safe range.]

11
A floating_point_definition also defines a first subtype of the type. If a real_range_specification is given, then the subtype is constrained to a range whose bounds are given by a conversion of the values of the simple_expressions of the real_range_specification to the type being defined. Otherwise, the subtype is unconstrained.

12
There is a predefined, unconstrained, floating point subtype named Float[, declared in the visible part of package Standard].

Dynamic Semantics

13
[The elaboration of a floating_point_definition creates the floating point type and its first subtype.]

Implementation Requirements

14
In an implementation that supports floating point types with 6 or more digits of precision, the requested decimal precision for Float shall be at least 6.

15
If Long_Float is predefined for an implementation, then its requested decimal precision shall be at least 11.

Implementation Permissions

16
An implementation is allowed to provide additional predefined floating point types[, declared in the visible part of Standard], whose (unconstrained) first subtypes have names of the form Short_Float, Long_Float, Short_Short_Float, Long_Long_Float, etc. Different predefined floating point types are allowed to have the same base decimal precision. However, the precision of Float should be no greater than that of Long_Float. Similarly, the precision of Short_Float (if provided) should be no greater than Float. Corresponding recommendations apply to any other predefined floating point types. There need not be a named floating point type corresponding to each distinct base decimal precision supported by an implementation.

16.a
Implementation defined:  The predefined floating point types declared in Standard.

Implementation Advice

17
An implementation should support Long_Float in addition to Float if the target machine supports 11 or more digits of precision. No other named floating point subtypes are recommended for package Standard. Instead, appropriate named floating point subtypes should be provided in the library package Interfaces (see B.2).

17.a
Implementation Note: To promote portability, implementations should explicitly declare the floating point (sub)types Float and Long_Float in Standard, and leave other predefined float types anonymous. For implementations that already support Short_Float, etc., upward compatibility argues for keeping such declarations in Standard during the transition period, but perhaps generating a warning on use. A separate package Interfaces in the predefined environment is available for pre-declaring types such as Float_32, IEEE_Float_64, etc. See B.2.

NOTES

18 33
If a floating point subtype is unconstrained, then assignments to variables of the subtype involve only Overflow_Checks, never Range_Checks.

Examples

19
Examples of floating point types and subtypes:

20
type Coefficient is digits 10 range -1.0 .. 1.0;

21
type Real is digits 8;
type Mass is digits 7 range 0.0 .. 1.0E35;

22
subtype Probability is Real range 0.0 .. 1.0;   --   a subtype with a smaller range

Inconsistencies With Ada 83

22.a
No Range_Checks, only Overflow_Checks, are performed on variables (or parameters) of an unconstrained floating point subtype.  This is upward compatible for programs that do not raise Constraint_Error. For those that do raise Constraint_Error, it is possible that the exception will be raised at a later point, or not at all, if extended range floating point registers are used to hold the value of the variable (or parameter).

22.b
Reason: This change was felt to be justified by the possibility of improved performance on machines with extended-range floating point registers.  An implementation need not take advantage of this relaxation in the range checking; it can hide completely the use of extended range registers if desired, presumably at some run-time expense.

Wording Changes From Ada 83

22.c
The syntax rules for floating_point_constraint and floating_accuracy_definition are removed.  The syntax rules for floating_point_definition and real_range_specification are new.

22.d
A syntax rule for digits_constraint is given in 3.5.9, "Fixed Point Types".  In J.3 we indicate that a digits_constraint may be applied to a floating point subtype_mark as well (to be compatible with Ada 83's floating_point_constraint).

22.e
Discussion of model numbers is postponed to 3.5.8 and G.2. The concept of safe numbers has been replaced by the concept of the safe range of values.  The bounds of the safe range are given by T'Safe_First .. T'Safe_Last, rather than -T'Safe_Large .. T'Safe_Large, since on some machines the safe range is not perfectly symmetric. The concept of machine numbers is new, and is relevant to the definition of Succ and Pred for floating point numbers.

3.5.8 Operations of Floating Point Types

Static Semantics

1
The following attribute is defined for every floating point subtype S:

1.a
Change: Editorial change - plural to singular in above phrase.

2
S'Digits S'Digits denotes the requested decimal precision for the subtype S.  The value of this attribute is of the type universal_integer. The requested decimal precision of the base subtype of a floating point type T is defined to be the largest value of d for which ceiling(d * log(10) / log(T'Machine_Radix)) + 1 <= T'Model_Mantissa.

NOTES

3 34
The predefined operations of a floating point type include the assignment operation, qualification, the membership tests, and explicit conversion to and from other numeric types.  They also include the relational operators and the following predefined arithmetic operators: the binary and unary adding operators - and +, certain multiplying operators, the unary operator abs, and the exponentiation operator.

4 35
As for all types, objects of a floating point type have Size and Address attributes (see 13.3). Other attributes of floating point types are defined in .

3.5.9 Fixed Point Types

1
A fixed point type is either an ordinary fixed point type, or a decimal fixed point type. The error bound of a fixed point type is specified as an absolute value, called the delta of the fixed point type.

Syntax

2
fixed_point_definition ::= ordinary_fixed_point_definition | decimal_fixed_point_definition

3
ordinary_fixed_point_definition ::=
   delta static_expression  real_range_specification

4
decimal_fixed_point_definition ::=
   delta static_expression digits static_expression [real_range_specification]

5
digits_constraint ::=
   digits static_expression [range_constraint]

Name Resolution Rules

6
For a type defined by a fixed_point_definition, the delta of the type is specified by the value of the expression given after the reserved word delta; this expression is expected to be of any real type. For a type defined by a decimal_fixed_point_definition (a decimal fixed point type), the number of significant decimal digits for its first subtype (the digits of the first subtype) is specified by the expression given after the reserved word digits; this expression is expected to be of any integer type.

Legality Rules

7
In a fixed_point_definition or digits_constraint, the expressions given after the reserved words delta and digits shall be static; their values shall be positive.

8
The set of values of a fixed point type comprise the integral multiples of a number called the small of the type. For a type defined by an ordinary_fixed_point_definition (an ordinary fixed point type), the small may be specified by an attribute_definition_clause (see 13.3); if so specified, it shall be no greater than the delta of the type. If not specified, the small of an ordinary fixed point type is an implementation-defined power of two less than or equal to the delta.

8.a
Implementation defined:  The small of an ordinary fixed point type.

9
For a decimal fixed point type, the small equals the delta; the delta shall be a power of 10. If a real_range_specification is given, both bounds of the range shall be in the range -(10**digits-1)*delta .. +(10**digits-1)*delta.

10
A fixed_point_definition is illegal if the implementation does not support a fixed point type with the given small and specified range or digits.

10.a
Implementation defined:  What combinations of small, range, and digits are supported for fixed point types.

11
For a subtype_indication with a digits_constraint, the subtype_mark shall denote a decimal fixed point subtype.

11.a
To be honest: Or, as an obsolescent feature, a floating point subtype is permitted - see J.3.

Static Semantics

12
The base range (see 3.5) of a fixed point type is symmetric around zero, except possibly for an extra negative value in some implementations.

13
An ordinary_fixed_point_definition defines an ordinary fixed point type whose base range includes at least all multiples of small that are between the bounds specified in the real_range_specification.  The base range of the type does not necessarily include the specified bounds themselves. An ordinary_fixed_point_definition also defines a constrained first subtype of the type, with each bound of its range given by the closer to zero of:

14 ·
the value of the conversion to the fixed point type of the corresponding expression of the real_range_specification;

15 ·
the corresponding bound of the base range.

16
A decimal_fixed_point_definition defines a decimal fixed point type whose base range includes at least the range -(10**digits-1)*delta .. +(10**digits-1)*delta. A decimal_fixed_point_definition also defines a constrained first subtype of the type.  If a real_range_specification is given, the bounds of the first subtype are given by a conversion of the values of the expressions of the real_range_specification. Otherwise, the range of the first subtype is -(10**digits-1)*delta .. +(10**digits-1)*delta.

Dynamic Semantics

17
The elaboration of a fixed_point_definition creates the fixed point type and its first subtype.

18
For a digits_constraint on a decimal fixed point subtype with a given delta, if it does not have a range_constraint, then it specifies an implicit range -(10**D-1)*delta .. +(10**D-1)*delta, where D is the value of the expression. A digits_constraint is compatible with a decimal fixed point subtype if the value of the expression is no greater than the digits of the subtype, and if it specifies (explicitly or implicitly) a range that is compatible with the subtype.

18.a
Discussion:  Except for the requirement that the digits specified be no greater than the digits of the subtype being constrained, a digits_constraint is essentially equivalent to a range_constraint.

18.b
Consider the following example:

18.c
type D is delta 0.01 digits 7 range -0.00 .. 9999.99;

18.d
The compatibility rule implies that the digits_constraint "digits 6" specifies an implicit range of "- 99.9999 .. 99.9999".  Thus, "digits 6" is not compatible with the constraint of D, but "digits 6 range 0.00 .. 9999.99" is compatible.

18.e
A value of a scalar type belongs to a constrained subtype of the type if it belongs to the range of the subtype.  Attributes like Digits and Delta have no affect on this fundamental rule.  So the obsolescent forms of digits_constraints and delta_constraints that are called "accuracy constraints" in RM83 don't really represent constraints on the values of the subtype, but rather primarily affect compatibility of the "constraint" with the subtype being "constrained."  In this sense, they might better be called "subtype assertions" rather than "constraints."

18.f
Note that the digits_constraint on a decimal fixed point subtype is a combination of an assertion about the digits of the subtype being further constrained, and a constraint on the range of the subtype being defined, either explicit or implicit.

19
The elaboration of a digits_constraint consists of the elaboration of the range_constraint, if any. If a range_constraint is given, a check is made that the bounds of the range are both in the range -(10**D-1)*delta .. +(10**D-1)*delta, where D is the value of the (static) expression given after the reserved word digits. If this check fails, Constraint_Error is raised.

Implementation Requirements

20
The implementation shall support at least 24 bits of precision (including the sign bit) for fixed point types.

20.a
Reason: This is sufficient to represent Standard.Duration with a small no more than 50 milliseconds.

Implementation Permissions

21
Implementations are permitted to support only smalls that are a power of two.  In particular, all decimal fixed point type declarations can be disallowed. Note however that conformance with the Information Systems Annex requires support for decimal smalls, and decimal fixed point type declarations with digits up to at least 18.

21.a
Implementation Note: The accuracy requirements for multiplication, division, and conversion (see G.2.1, "Model of Floating Point Arithmetic") are such that support for arbitrary smalls should be practical without undue implementation effort.  Therefore, implementations should support fixed point types with arbitrary values for small (within reason). One reasonable limitation would be to limit support to fixed point types that can be converted to the most precise floating point type without loss of precision (so that Fixed_IO is implementable in terms of Float_IO).

NOTES

22 36
The base range of an ordinary fixed point type need not include the specified bounds themselves so that the range specification can be given in a natural way, such as:

23
type Fraction is delta 2.0**(-15) range -1.0 .. 1.0;

24
With 2's complement hardware, such a type could have a signed 16-bit representation, using 1 bit for the sign and 15 bits for fraction, resulting in a base range of -1.0 .. 1.0-2.0**(-15).

Examples

25
Examples of fixed point types and subtypes:

26
type Volt is delta 0.125 range 0.0 .. 255.0;

27
  --  A pure fraction which requires all the available
  --  space in a word can be declared as the type Fraction:
type Fraction is delta System.Fine_Delta range -1.0 .. 1.0;
  --  Fraction'Last = 1.0 - System.Fine_Delta

28
type Money is delta 0.01 digits 15;  -- decimal fixed point
subtype Salary is Money digits 10;
  -- Money'Last = 10.0**13 - 0.01, Salary'Last = 10.0**8 - 0.01

Inconsistencies With Ada 83

28.a
In Ada 9X, S'Small always equals S'Base'Small, so if an implementation chooses a small for a fixed point type smaller than required by the delta, the value of S'Small in Ada 9X might not be the same as it was in Ada 83.

Extensions to Ada 83

28.b
Decimal fixed point types are new, though their capabilities are essentially similar to that available in Ada 83 with a fixed point type whose small equals its delta equals a power of 10.  However, in the Information Systems Annex, additional requirements are placed on the support of decimal fixed point types (e.g. a minimum of 18 digits of precision).

Wording Changes From Ada 83

28.c
The syntax rules for fixed_point_constraint and fixed_accuracy_definition are removed.  The syntax rule for fixed_point_definition is new. A syntax rule for delta_constraint is included in the Obsolescent features (to be compatible with Ada 83's fixed_point_constraint).

3.5.10 Operations of Fixed Point Types

Static Semantics

1
The following attributes are defined for every fixed point subtype S:

2 S'Small   S'Small denotes the small of the type of S. The value of this attribute is of the type universal_real. Small may be specified for nonderived fixed point types via an attribute_definition_clause (see 13.3); the expression of such a clause shall be static.

3 S'Delta   S'Delta denotes the delta of the fixed point subtype S. The value of this attribute is of the type universal_real.

3.a
Reason: The delta is associated with the subtype as opposed to the type, because of the possibility of an (obsolescent) delta_constraint.

4 S'Fore   S'Fore yields the minimum number of characters needed before the decimal point for the decimal representation of any value of the subtype S, assuming that the representation does not include an exponent, but includes a one-character prefix that is either a minus sign or a space. (This minimum number does not include superfluous zeros or underlines, and is at least 2.)  The value of this attribute is of the type universal_integer.

5 S'Aft   S'Aft yields the number of decimal digits needed after the decimal point to accommodate the delta of the subtype S, unless the delta of the subtype S is greater than 0.1, in which case the attribute yields the value one.  [(S'Aft is the smallest positive integer N for which (10**N)*S'Delta is greater than or equal to one.)]  The value of this attribute is of the type universal_integer.

6
The following additional attributes are defined for every decimal fixed point subtype S:

7 S'Digits   S'Digits denotes the digits of the decimal fixed point subtype S, which corresponds to the number of decimal digits that are representable in objects of the subtype. The value of this attribute is of the type universal_integer. Its value is determined as follows:

8 ·
For a first subtype or a subtype defined by a subtype_indication with a digits_constraint, the digits is the value of the expression given after the reserved word digits;

9 ·
For a subtype defined by a subtype_indication without a digits_constraint, the digits of the subtype is the same as that of the subtype denoted by the subtype_mark in the subtype_indication.

9.a
Implementation Note: Although a decimal subtype can be both range-constrained and digits-constrained, the digits constraint is intended to control the Size attribute of the subtype.  For decimal types, Size can be important because input/output of decimal types is so common.

10 ·
The digits of a base subtype is the largest integer D such that the range -(10**D-1)*delta .. +(10**D-1)*delta is included in the base range of the type.

10.a
Change: Made 3.5.10(10);5.7 into a bullet under S'Digits, rather than separately listing it under S'Base'Digits, as per WG9 resolution.

11 S'Scale   S'Scale denotes the scale of the subtype S, defined as the value N such that S'Delta = 10.0**(-N). [The scale indicates the position of the point relative to the rightmost significant digits of values of subtype S.] The value of this attribute is of the type universal_integer.

11.a
Ramification: S'Scale is negative if S'Delta is greater than one. By contrast, S'Aft is always positive.

12 S'Round   S'Round denotes a function with the following specification:

13
function S'Round(X : universal_real)
  return S'Base

14
The function returns the value obtained by rounding X (away from 0, if X is midway between two values of the type of S).

NOTES

15 37
All subtypes of a fixed point type will have the same value for the Delta attribute, in the absence of delta_constraints (see J.3).

16 38
S'Scale is not always the same as S'Aft for a decimal subtype; for example, if S'Delta = 1.0 then S'Aft is 1 while S'Scale is 0.

17 39
The predefined operations of a fixed point type include the assignment operation, qualification, the membership tests, and explicit conversion to and from other numeric types.  They also include the relational operators and the following predefined arithmetic operators: the binary and unary adding operators - and +, multiplying operators, and the unary operator abs.

18 40
As for all types, objects of a fixed point type have Size and Address attributes (see 13.3). Other attributes of fixed point types are defined in A.5.4.



[Home] [Prev] [Next] [Index]

documentation@rational.com
Copyright © 1993-1998, Rational Software Corporation.   All rights reserved.