!standard G.2.3(23) 19-01-07 AI12-0300-1/01 !class binding interpretation 19-01-07 !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 Fixed values can only be directly multipled by type 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 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.) !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 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. !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. **************************************************************** From: Tucker Taft Sent: Tuesday, December 11, 2018 8:35 AM ****************************************************************