Version 1.1 of ais/ai-00105.txt

Unformatted version of ais/ai-00105.txt version 1.1
Other versions for file ais/ai-00105.txt

!standard 03.05.04 (09)          98-04-01 AI95-00105/02
!class confirmation 96-04-04
!status ARG Approved 9-0-0 98-04-01
!status work item 96-05-07
!status received 96-04-04
!priority Medium
!difficulty Medium
!subject extra negative value
!summary 98-03-27
The RM does not specify whether implementations must support integer and fixed point types that allow the "extra negative value" of 3.5.4(9) and 3.5.9(12). There is no Implementation Advice as to whether or not such extra negative values should be supported on a two's complement machine.
!question 96-04-04
The following questions apply to implementations on two's complement machines.
Should implementations support integer and fixed point types that allow the "extra negative value" of 3.5.4(9) and 3.5.9(12)?
If not necessarily, then should implementations do so if the type declaration would otherwise require a larger size?
If not necessarily, then should implementations do so in the presense of a size clause specifying the smaller size? AARM 13.3(55b) indicates so, but this isn't in RM95, even though there are other two's complement "shoulds", such as 3.5.4(29).
Should the permission of 3.5.9(13) to exclude both the lower and upper bounds apply when all the values are exactly representable in the available size? The Note in 3.5.9(22) explaining this permission implies that this wasn't the intent.
!response 98-04-01
(See summary.)
!appendix

!section 3.5.4(09)
!subject extra negative value
!reference RM95-3.5.4(9)
!reference RM95-3.5.4(29)
!reference RM95-3.5.9(12)
!reference RM95-3.5.9(13)
!reference RM95-3.5.9(22)
!reference RM95-13.3(55)
!reference AARM95-13.3(55b)
!from Dan Eilers 95-10-28
!reference 95-5370.a Dan Eilers  95-10-29>>
!discussion

The following questions apply to implementations on two's complement
machines.

Should implementations support integer and fixed point types that allow
the "extra negative value" of 3.5.4(9) and 3.5.9(12)?

If not necessarily, then should implementations do so if the type
declaration would otherwise require a larger size?

If not necessarily, then should implementations do so in the presense
of a size clause specifying the smaller size?  AARM 13.3(55b) indicates
so, but this isn't in RM95, even though there are other two's complement
"shoulds", such as 3.5.4(29).

Should the permission of 3.5.9(13) to exclude both the lower and upper
bounds apply when all the values are exactly representable in the
available size?  The Note in 3.5.9(22) explaining this permission
implies that this wasn't the intent.

-- Dan Eilers

****************************************************************

!section 3.5.4(09)
!subject extra negative value
!reference RM95-3.5.4(9)
!reference RM95-3.5.4(29)
!reference RM95-3.5.9(12)
!reference RM95-3.5.9(13)
!reference RM95-3.5.9(22)
!reference RM95-13.3(55)
!reference AARM95-13.3(55b)
!reference 95-5370.a Dan Eilers  95-10-29
!from Bob Duff
!reference 96-5455.a Robert A Duff 96-4-8>>
!discussion

Dan,

I don't understand your questions.  Perhaps you could send a
clarification to ada-comment.

> The following questions apply to implementations on two's complement
> machines.
> 
> Should implementations support integer and fixed point types that allow
> the "extra negative value" of 3.5.4(9) and 3.5.9(12)?

As far as I can tell, the RM doesn't say "should" -- it entirely up to
the implementation.  Most implementations *do* support the extra
negative value, but I can imagine an implementation that used it for
detecting uninitialized variables, for example.

> If not necessarily, then should implementations do so if the type
> declaration would otherwise require a larger size?

I don't understand how it could require a larger size, because the extra
negative value of 3.5.4(9) is a value of the base subtype, not the first
subtype.  E.g. if I write "type T is range -4..3;" then T'Size is 3 by
default, by 13.3(55) and C.2.  The RM doesn't say whether or not T'Base
contains an extra negative value, or what the value of T'Base'Size is.

> If not necessarily, then should implementations do so in the presense
> of a size clause specifying the smaller size?  AARM 13.3(55b) indicates
> so, but this isn't in RM95, even though there are other two's complement
> "shoulds", such as 3.5.4(29).

In the example above, the implementation has to support "for T'Size
use 3;", by 13.3(55) and C.2 -- 13.3(55.b) clarifies that this is
really intended.  But this still has no effect on whether T'Base has
the extra negative value.

In any case, most objects of subtype T will be allocated (say) 32
bits, or perhaps 8 bits.  The 'Size only applies to components of
packed composite types, and it affects the semantics of
Unchecked_Conversion.

> Should the permission of 3.5.9(13) to exclude both the lower and upper
> bounds apply when all the values are exactly representable in the
> available size?  The Note in 3.5.9(22) explaining this permission
> implies that this wasn't the intent.

Again, as far as I can tell, the RM has no "should" applying to this
issue.  One has to trust the implementer to do something sensible.
One possibility is to include the bounds if it doesn't increase the
size of the base subtype, but this is not required, or even advised,
by the RM.

Anyway, I fear I'm missing your point.  Perhaps an example would help,
or an explanation of why you're asking.

- Bob

****************************************************************

!section 3.5.4(09)
!subject extra negative value
!reference RM95-3.5.4(9)
!reference RM95-3.5.4(29)
!reference RM95-3.5.9(12)
!reference RM95-3.5.9(13)
!reference RM95-3.5.9(22)
!reference RM95-13.3(55)
!reference AARM95-13.3(55b)
!reference 95-5370.a Dan Eilers  95-10-29
!reference 96-5455.a Robert A Duff 96-4-8
!from Dan Lehman
!reference 96-5513.a Dan Lehman 96-4-24>>
!discussion

Another "Dan" will take up Dan Eilers's 95-10-29 questions.

Bob Duff writes:

> Anyway, I fear I'm missing your point.  Perhaps an example would help,
> or an explanation of why you're asking.

> E.g. if I write "type T is range -4..3;" then T'Size is 3 by
> default, by 13.3(55) and C.2.  The RM doesn't say whether or not T'Base
> contains an extra negative value, or what the value of T'Base'Size is.

> In the example above, the implementation has to support "for T'Size
> use 3;", by 13.3(55) and C.2 -- 13.3(55.b) clarifies that this is
> really intended.  But this still has no effect on whether T'Base has
> the extra negative value.

I understand Dan Eilers's point to be the question Must an implementation
on a 2s-complement computer system have the extra negative value that is
normally associated with such systems, or might instead the implementation
use such a representation to indicate that an object is uninitialized?

Bob's response seems to be inconsistent:

     while he admits "I can imagine an implementation that used it for
     detecting uninitialized variables,"

     he nevertheless insists that the implementation has to support

        type T is range -4..3; for  T'Size use 3;

     --so where does that leave an implementation model intended
     to detect unitialized variables, including components?

---Dan Lehman
============== *

****************************************************************

!section 3.5.4(09)
!subject extra negative value
!reference RM95-3.5.4(9)
!reference RM95-3.5.4(29)
!reference RM95-3.5.9(12)
!reference RM95-3.5.9(13)
!reference RM95-3.5.9(22)
!reference RM95-13.3(55)
!reference AARM95-13.3(55b)
!reference 95-5370.a Dan Eilers  95-10-29
!reference 96-5455.a Robert A Duff 96-4-8>>
!from Dan Eilers 96-04-24
!reference 96-5514.a Dan Eilers  96-4-24>>
!discussion

> I don't understand your questions.  Perhaps you could send a
> clarification to ada-comment.
> ...
> Anyway, I fear I'm missing your point.  Perhaps an example would help,
> or an explanation of why you're asking.
>
> - Bob

My questions are motivated by implementations that unnecessarily
exclude endpoints (possibly unintentionally).  This has a detrimental
effect on portability.  For example, in GNAT V2.07 (but improved in
GNAT V3.01), _both_ endpoints are unnecessarily excluded:

--test11.ads:4:14: warning: static value out of range
--test11.ads:4:14: warning: "constraint_error" will be raised at runtime
--test11.ads:7:15: warning: value not in range of type "fix" declared at line 2
--test11.ads:7:15: warning: "constraint_error" will be raised at runtime
package test11 is
   type fix is delta 1.0 range -2.0..1.0;
      for fix'size use 2;
   a: fix := -2.0;
   b: fix := -1.0;
   c: fix :=  0.0;
   d: fix :=  1.0;
end test11;

My recommendation is that absent a good reason (such as a one's
complement machine, or detecting uninitialized values), that the
language should at least recommend, if not require, that endpoints
that can be represented should be allowed.

        -- Dan

****************************************************************

!section 3.5.4(09)
!subject extra negative value
!reference RM95-3.5.4(9)
!reference RM95-3.5.4(29)
!reference RM95-3.5.9(12)
!reference RM95-3.5.9(13)
!reference RM95-3.5.9(22)
!reference RM95-13.3(55)
!reference AARM95-13.3(55b)
!reference 95-5370.a Dan Eilers  95-10-29
!reference 96-5455.a Robert A Duff 96-4-8
!reference 96-5514.a Dan Eilers 96-4-24 
!from Robert I. Eachus 96-4-26
!reference 96-5515.a Robert I. Eachus 96-4-25>>
!discussion

   Dan Eilers says:

  > My questions are motivated by implementations that unnecessarily
  > exclude endpoints (possibly unintentionally).  This has a detrimental
  > effect on portability.  For example, in GNAT V2.07 (but improved in
  > GNAT V3.01), _both_ endpoints are unnecessarily excluded...

  > package test11 is
  >    type fix is delta 1.0 range -2.0..1.0;
  >      for fix'size use 2;
  >    a: fix := -2.0;
  >    b: fix := -1.0;
  >    c: fix :=  0.0;
  >    d: fix :=  1.0;
  > end test11;

  > My recommendation is that absent a good reason (such as a one's
  > complement machine, or detecting uninitialized values), that the
  > language should at least recommend, if not require, that endpoints
  > that can be represented should be allowed.

    I think this is an unnecessary change to the language, and the
example given is probably the only non-pathological case where it
makes a difference.  The range given above has two values required to
be represented by 3.5.9(13).  Should an implementation be required to
support a 'SIZE clause requiring a one bit representation?  In Ada 83
exactly that model was required--see AI-143.

    It may be silly seeming to declare a type as:

    type Fix is delta 1.0 range -2.0..2.0;
    for Fix'Size use 2;

    To get a type with values -2.0, -1.0, 0.0, 1.0 on a two's
complement machine, but that is the way it has always been in Ada.
(Jean Ichbiah preferred it because type declarations like:

      type foo is delta 2.0**(-31) range -1.0..1.0;

   look a lot cleaner than:

      type foo is delta 2.0**(-31) range -1.0..1.0-2.0**(-31);

  but most programmers write the latter anyway.)

****************************************************************

!section 3.5.4(09)
!subject extra negative value
!reference AI95-00105/00
!reference RM95-3.5.4(9)
!reference RM95-3.5.4(29)
!reference RM95-3.5.9(12)
!reference RM95-3.5.9(13)
!reference RM95-3.5.9(22)
!reference RM95-13.3(55)
!reference AARM95-13.3(55b)
!reference 95-5370.a Dan Eilers  95-10-29
!reference 96-5455.a Robert A Duff 96-4-8
!reference 96-5514.a Dan Eilers 96-4-24
!from Dan Eilers 96-4-26
!reference 96-5516.a Dan Eilers  96-4-25>>
!discussion

Robert Eachus writes:
>     It may be silly seeming to declare a type as:
>
>     type Fix is delta 1.0 range -2.0..2.0;
>     for Fix'Size use 2;
>
>     To get a type with values -2.0, -1.0, 0.0, 1.0 on a two's
> complement machine, but that is the way it has always been in Ada.
> (Jean Ichbiah preferred it because type declarations like:
>
>       type foo is delta 2.0**(-31) range -1.0..1.0;
>
>    look a lot cleaner than:
>
>       type foo is delta 2.0**(-31) range -1.0..1.0-2.0**(-31);
>
>   but most programmers write the latter anyway.)

I agree.
I am only asking that when the representation chosen (either by the compiler
or by a SIZE clause) has the bits available to represent either endpoint,
that such endpoints should not be arbitrarily excluded.

>   > My questions are motivated by implementations that unnecessarily
>   > exclude endpoints (possibly unintentionally).  This has a detrimental
>   > effect on portability.  For example, in GNAT V2.07 (but improved in
>   > GNAT V3.01), _both_ endpoints are unnecessarily excluded...
>
>   > package test11 is
>   >    type fix is delta 1.0 range -2.0..1.0;
>   >      for fix'size use 2;
>   >    a: fix := -2.0;
>   >    b: fix := -1.0;
>   >    c: fix :=  0.0;
>   >    d: fix :=  1.0;
>   > end test11;
>
>   > My recommendation is that absent a good reason (such as a one's
>   > complement machine, or detecting uninitialized values), that the
>   > language should at least recommend, if not require, that endpoints
>   > that can be represented should be allowed.
>
>     I think this is an unnecessary change to the language, and the
> example given is probably the only non-pathological case where it
> makes a difference.  The range given above has two values required to
> be represented by 3.5.9(13).  Should an implementation be required to
> support a 'SIZE clause requiring a one bit representation?  In Ada 83
> exactly that model was required--see AI-143.

I can live with this rule, but would prefer to allow the upper bound
to be excluded only if it is a power of 2 _and_ not less than the
absolute value of the lower bound.  I'd prefer the lower bound to
be excluded only for negative powers of two with absolute value
greater than the upper bound on a one's complement machine.

In any case, with a 2-bit size clause, there are enough bits to
require support for both endpoints on a two's complement machine.

        -- Dan

****************************************************************

!section 3.5.4(09)
!subject extra negative value
!reference RM95-3.5.4(9)
!reference RM95-3.5.4(29)
!reference RM95-3.5.9(12)
!reference RM95-3.5.9(13)
!reference RM95-3.5.9(22)
!reference RM95-13.3(55)
!reference AARM95-13.3(55b)
!reference 95-5370.a Dan Eilers  95-10-29
!reference 96-5455.a Robert A Duff 96-4-8
!reference 96-5513.a Dan Lehman 96-4-24
!from Bob Duff
!reference 96-5541.a Robert A Duff 96-5-8>>
!discussion

> Bob's response seems to be inconsistent:
> 
>      while he admits "I can imagine an implementation that used it for
>      detecting uninitialized variables,"
> 
>      he nevertheless insists that the implementation has to support
> 
>         type T is range -4..3; for  T'Size use 3;
> 
>      --so where does that leave an implementation model intended
>      to detect unitialized variables, including components?

See 13.3(55.i), which makes the same point.  An implementation can, in
*most* cases, add an extra value, initialize objects to that value, and
check for it on every read, thus detecting uninitialized objects.

However, there are some cases in which that implementation is wrong.  In
particular, if the language requires a certain object to fit into a
certain number of bits, AND the subtype of the object uses up all the
available bit patterns (which means that adding an extra value adds an
extra bit), then the implementation cannot use this method to detect
uninitialized variables.  For example, each component of a packed array
of Booleans has to fit in 1 bit -- the implementation cannot allocate 2
bits, and thus cannot use this method, IN THIS CASE.

The method is still potentially beneficial, since in *most* cases, it
works.  The implementation would use this method when it works (or
perhaps when it works and is "reasonably" efficient), but would turn off
this feature in cases like the packed-array-of-Boolean example.

I imagine that any implementation that supported this method would want
to have a way to turn it off *anyway*, since it is potentially costly at
run time.  I would expect the implementation to define an
implementation-defined check name, like Initialization_Check, for use in
pragma Suppress.  Alternatively, the implementation might leave it off
by default, and use a command-line switch to turn it on.

- Bob


****************************************************************

!section 3.5.9(00)
!subject Fixed-point base ranges
!reference RM95-3.5.9
!reference RM95-G.2.3
!from Keith Thompson 96-05-21
!reference 96-5607.a Keith Thompson 96-6-21>>
!discussion

The Ada 95 definition of the base range of a fixed point type is less
stringent than the Ada 83 definition involving model numbers.

In either Ada 83 or Ada 95, given a type declaration like

    type Fixed is delta 0.125 range -16.0 .. +16.0;

the declared bounds may or may not be values of the type (due to the
accursed RM83-3.5.9(6) / RM95-3.5.9(13)).  For an 8-bit 2's-complement
representation, the model numbers (Ada 83) or the base range (Ada 95)
might typically include the values -16.0, -15.875, ..., 0.0, ..., +15.75,
+15.875 (but not +16.0).

Ada 95 drops the explicit requirement that the base range is defined
by a binary representation.  As far as I can tell from the current
wording, given a declaration like

    type Fixed2 is delta 1.0 range -5.0 .. +5.0;

an implementation could legally exclude -5.0 and +5.0 from the base
range even though they're not powers of two.  Even the model of fixed
point arithmetic in G.2.3 doesn't change this.

Question: is it true that an implementation may exclude the values -5.0
and +5.0 in the base range of type Fixed2?  If so, this is a serious
incompatibility with Ada 83.  If not, what is the justification in the RM?

My concern is not that some implementation might be so perverse as to
exclude the bounds of Fixed2, but that the apparently straightforward
declaration of Fixed2 might be strictly non-portable.

Digression:
    If you hadn't guessed from my use of the word "accursed" above, I
    intensely dislike the permission of RM95-3.5.9(13) to exclude the
    explicitly declared bounds of a fixed-point type.  I still have
    fantasies of changing this in Ada 200Y.
end Digression;

****************************************************************

Questions? Ask the ACAA Technical Agent