!standard G.2.3(23) 19-02-25 AI12-0300-1/03
!class binding interpretation 19-01-07
!status Amendment 1-2012 19-01-15
!status WG9 Approved 22-06-22
!status ARG Approved 11-0-0 19-01-14
!status work item 19-01-07
!status received 18-12-11
!priority Low
!difficulty Easy
!qualifier Clarification
!subject Annex G text for Fixed * integer
!summary
For fixed times integer multiplications, the integer type is always
Standard.Integer.
!question
G.2.3(23) says in part:
A multiplication P * Q of an operand of a fixed point type F by an operand
of an integer type I, or vice-versa, and a division P / Q of an operand of
a fixed point type F by an operand of an integer type I, are also allowed.
In these cases, the result has a type of F; explicit conversion of the
result is never required.
This implies that (any-fixed * any-integer) is supported, when in fact
(any-fixed * Integer) is what that language allows. We had a customer who
presumed there was something wrong with the compiler because it didn't allow
a (fixed * My_Integer_Type) computation without an explicit conversion.
Should this be fixed? (Yes.)
!recommendation
(See Summary.)
!wording
Modify G.2.3(23):
A multiplication P * Q of an operand of a fixed point type F by an operand
of [an integer type I] {type Integer}, or vice{ }[-]versa, and a division P / Q
of an operand of a fixed point type F by an operand of [an integer type I]
{type Integer}, are also allowed. In these cases, the result has (the)[a]
type of F; explicit conversion of the result is never required. The accuracy
required in these cases is the same as that required for a multiplication
F(P * Q) or a division F(P / Q) obtained by interpreting the operand of the
integer type to have a fixed point type with a small of 1.0.
!discussion
The multiplying operators for fixed point types are defined in 4.5.5, which
include:
function "*"(Left : T; Right : Integer) return T
function "*"(Left : Integer; Right : T) return T
function "/"(Left : T; Right : Integer) return T
No other operators are defined with fixed and integer operands. (The root-real
and root-integer operators are only usable with values of universal types.)
Editor's Note: The original wording used "vice-versa", when the correct
spelling is "vice versa". I was asked to change these throughout the Standard
(uses are about 50-50 for each spelling); such changes refer to this AI and
this note. None of the uses changed are normative (they're all in AARM notes
and user notes), thus there's no value to handling in a presentation AI.
!corrigendum G.2.3(23)
@drepl
A multiplication P * Q of an operand of a fixed point type F by an operand of
an integer type I, or vice-versa, and a division P / Q of an operand of a
fixed point type F by an operand of an integer type I, are also allowed. In
these cases, the result has a type of F; explicit conversion of the result is
never required. The accuracy required in these cases is the same as that
required for a multiplication F(P * Q) or a division F(P / Q) obtained by
interpreting the operand of the integer type to have a fixed point type with a
@i of 1.0.
@dby
A multiplication P * Q of an operand of a fixed point type F by an operand of
type Integer, or vice versa, and a division P / Q of an operand of a
fixed point type F by an operand of type Integer, are also allowed. In
these cases, the result has the type of F; explicit conversion of the result is
never required. The accuracy required in these cases is the same as that
required for a multiplication F(P * Q) or a division F(P / Q) obtained by
interpreting the operand of the integer type to have a fixed point type with a
@i of 1.0.
!ASIS
No ASIS effect.
!ACATS test
This should be covered by the usual tests for 4.5.5, and any accuracy tests
for G.2.3.
!appendix
From: Tucker Taft
Sent: Tuesday, December 11, 2018 8:35 AM
We just bumped into the following misleading text in G.2.3(23):
23 A multiplication P * Q of an operand of a fixed point type F by an
operand of an integer type I, or vice-versa, and a division P / Q
of an operand of a fixed point type F by an operand of an integer type I,
are also allowed. In these cases, the result has a type of F; explicit
conversion of the result is never required.
This implies that (any-fixed * any-integer) is supported, when in fact
(any-fixed * Integer) is what that language allows. We had a customer who
presumed there was something wrong with the compiler because it didn't allow
a (fixed * My_Integer_Type) computation without an explicit conversion.
The obvious fix to paragraph 6.2.3(23) is as follows:
23 A multiplication P * Q of an operand of a fixed point type F by an
operand of [an integer type I] {type Integer}, or vice-versa, and a
division P / Q of an operand of a fixed point type F by an operand of
[an integer type I] {type Integer}, are also allowed. In these cases,
the result has a type of F; explicit conversion of the result is never
required.
****************************************************************
From: Jean-Pierre Rosen
Sent: Tuesday, December 11, 2018 9:33 AM
> This implies that (any-fixed * any-integer) is supported, when in fact
> (any-fixed * Integer) is what that language allows.
True, and I regret it ever since Ada83. It's presumably too late for Ada 2020,
but it is one of the few cases where you cannot escape Integer.
Maybe due to some resolution issue?
****************************************************************
From: Edmond Schonberg
Sent: Tuesday, December 11, 2018 9:40 AM
The motivation is probably lost to history, but i would imagine that this
operation is intended as a scaling of a fixed value by a factor that is a
pure number (I would say dimensionless) and Integer is the only one that makes
sense, YMMV.
****************************************************************
From: Tucker Taft
Sent: Tuesday, December 11, 2018 10:13 AM
I agree, that is the intent I would associate with this choice. It is similar
to the rule for exponentiation, where the exponent has to be Integer.
****************************************************************
From: Erhard Ploedereder
Sent: Wednesday, December 12, 2018 7:35 PM
Hmmm. I look at A.1. and see
29
function "*" (Left : root_integer; Right : root_real)
return root_real;
30
function "*" (Left : root_real; Right : root_integer)
return root_real;
and words elewhere (in 3.*) that make root_real an ancestor of all float and
fixed-point types, while root_integer is ancestor to all integer types.
What makes you say that the language allows only
function "*"(left: any-fixed; Right: Integer) ?
****************************************************************
From: Tucker Taft
Sent: Wednesday, December 12, 2018 7:44 PM
The predefined operators are not inherited. They appear where they are
defined to appear in Chapter 4 (see 4.5(9) for the general rule). Yes, this
is a language kludge, but it is an *old* kludge... ;-)
The only predefined multiplying operators between fixed-point and integer
types require Standard.Integer, as defined in 4.5.5. AARM 4.5.5(15.a)
addresses the issue about the multiplying operators between root-real and
root-integer, and how they are *not* more generally usable.
****************************************************************