--- ai12s/ai12-0208-1.txt 2019/02/07 06:31:29 1.19 +++ ai12s/ai12-0208-1.txt 2019/02/22 06:50:38 1.20 @@ -1,4 +1,4 @@ -!standard A.5.5(0) 19-02-01 AI12-0208-1/08 +!standard A.5.5(0) 19-02-22 AI12-0208-1/09 !standard A.5.6(0) !standard A.5.7(0) !standard A.5.8(0) @@ -29,7 +29,7 @@ Support is provided for integer arithmetic involving values larger than than those supported by the target machine, and for arbitrary-precision -rationals. +reals. The package Ada.Numerics.Big_Numbers has the following declaration: @@ -199,111 +199,111 @@ Default_Initialized_Object : Big_Integer; is required to propagate Assertion_Error. -A.5.7 Big Rationals +A.5.7 Big Reals -The package Numerics.Big_Numbers.Big_Rationals has the +The package Numerics.Big_Numbers.Big_Reals has the following declaration: with Ada.Numerics.Big_Numbers.Big_Integers; with Ada.Streams; - package Ada.Numerics.Big_Numbers.Big_Rationals + package Ada.Numerics.Big_Numbers.Big_Reals with Preelaborate, Nonblocking is use Big_Integers; - type Optional_Big_Rational is private with - Default_Initial_Condition => not Is_Present (Optional_Big_Rational), + type Optional_Big_Real is private with + Default_Initial_Condition => not Is_Present (Optional_Big_Real), Real_Literal => From_String, Put_Image => Put_Image; - function Is_Present (Arg : Optional_Big_Rational) return Boolean; + function Is_Present (Arg : Optional_Big_Real) return Boolean; - function No_Big_Rational return Optional_Big_Rational - with Post => not Is_Present (No_Big_Rational'Result); + function No_Big_Real return Optional_Big_Real + with Post => not Is_Present (No_Big_Real'Result); - subtype Big_Rational is Optional_Big_Rational - with Dynamic_Predicate => Is_Present (Big_Rational), + subtype Big_Real is Optional_Big_Real + with Dynamic_Predicate => Is_Present (Big_Real), Predicate_Failure => (raise Constraint_Error); - function "/" (Num, Den : Big_Integer) return Big_Rational + function "/" (Num, Den : Big_Integer) return Big_Real with Pre => (Den /= 0) or else (raise Constraint_Error); - function Numerator (Arg : Big_Rational) return Big_Integer; - function Denominator (Arg : Big_Rational) return Big_Positive + function Numerator (Arg : Big_Real) return Big_Integer; + function Denominator (Arg : Big_Real) return Big_Positive with Post => (Arg = 0.0) or else (Greatest_Common_Divisor (Numerator (Arg), Denominator'Result) = 1); - function To_Big_Rational (Arg : Big_Integer) return Big_Rational is + function To_Big_Real (Arg : Big_Integer) return Big_Real is (Arg / 1); - function "+" (Arg : Integer) return Big_Rational - renames To_Big_Rational; + function "+" (Arg : Integer) return Big_Real + renames To_Big_Real; -- **** Editor's note: This function is nonsense as written. - function To_Rational (Arg : Integer) return Big_Rational is ((+Arg) / 1); + function To_Real (Arg : Integer) return Big_Real is ((+Arg) / 1); - function "=" (L, R : Big_Rational) return Boolean; - function "<" (L, R : Big_Rational) return Boolean; - function "<=" (L, R : Big_Rational) return Boolean; - function ">" (L, R : Big_Rational) return Boolean; - function ">=" (L, R : Big_Rational) return Boolean; + function "=" (L, R : Big_Real) return Boolean; + function "<" (L, R : Big_Real) return Boolean; + function "<=" (L, R : Big_Real) return Boolean; + function ">" (L, R : Big_Real) return Boolean; + function ">=" (L, R : Big_Real) return Boolean; - function In_Range (Arg, Low, High : Big_Rational) return Boolean is + function In_Range (Arg, Low, High : Big_Real) return Boolean is ((Low <= Arg) and (Arg <= High)); generic type Num is digits <>; package Float_Conversions is - function To_Big_Rational (Arg : Num) return Big_Rational; + function To_Big_Real (Arg : Num) return Big_Real; - function From_Big_Rational (Arg : Big_Rational) return Num + function From_Big_Real (Arg : Big_Real) return Num with Pre => In_Range (Arg, - Low => To_Big_Rational (Num'First), - High => To_Big_Rational (Num'Last)) + Low => To_Big_Real (Num'First), + High => To_Big_Real (Num'Last)) or else (raise Constraint_Error); end Float_Conversions; generic type Num is delta <>; package Fixed_Conversions is - function To_Big_Rational (Arg : Num) return Big_Rational; + function To_Big_Real (Arg : Num) return Big_Real; - function From_Big_Rational (Arg : Big_Rational) return Num + function From_Big_Real (Arg : Big_Real) return Num with Pre => In_Range (Arg, - Low => To_Big_Rational (Num'First), - High => To_Big_Rational (Num'Last)) + Low => To_Big_Real (Num'First), + High => To_Big_Real (Num'Last)) or else (raise Constraint_Error); end Fixed_Conversions; - function To_String (Arg : Big_Rational; + function To_String (Arg : Big_Real; Fore : Field := 2; Aft : Field := 3; Exp : Field := 0) return String with Post => To_String'Result'First = 1; - function From_String (Arg : String) return Big_Rational; + function From_String (Arg : String) return Big_Real; - function To_Quotient_String (Arg : Big_Rational) return String is + function To_Quotient_String (Arg : Big_Real) return String is (To_String (Numerator (Arg)) & " / " & To_String (Denominator (Arg))); - function From_Quotient_String (Arg : String) return Big_Rational; + function From_Quotient_String (Arg : String) return Big_Real; procedure Put_Image - (Arg : Big_Rational; + (Arg : Big_Real; Stream : not null access Ada.Streams.Root_Stream_Type'Class); - function "-" (L : Big_Rational) return Big_Rational; - function "abs" (L : Big_Rational) return Big_Rational; - function "+" (L, R : Big_Rational) return Big_Rational; - function "-" (L, R : Big_Rational) return Big_Rational; - function "*" (L, R : Big_Rational) return Big_Rational; - function "/" (L, R : Big_Rational) return Big_Rational; - function "**" (L : Big_Rational; R : Integer) - return Big_Rational; - function Min (L, R : Big_Rational) return Big_Rational; - function Max (L, R : Big_Rational) return Big_Rational; + function "-" (L : Big_Real) return Big_Real; + function "abs" (L : Big_Real) return Big_Real; + function "+" (L, R : Big_Real) return Big_Real; + function "-" (L, R : Big_Real) return Big_Real; + function "*" (L, R : Big_Real) return Big_Real; + function "/" (L, R : Big_Real) return Big_Real; + function "**" (L : Big_Real; R : Integer) + return Big_Real; + function Min (L, R : Big_Real) return Big_Real; + function Max (L, R : Big_Real) return Big_Real; private ... -- not specified by the language - end Ada.Numerics.Big_Numbers.Big_Rationals; + end Ada.Numerics.Big_Numbers.Big_Reals; To_String and From_String behave analogously to the Put and Get procedures defined in Text_IO.Float_IO (in particular, with respect to the @@ -314,9 +314,9 @@ converts that String to a Wide_Wide_String using To_Wide_Wide_String, and the resulting value to the stream using Wide_Wide_String'Write. -For an instance of Float_Conversions or Fixed_Conversions, To_Big_Rational +For an instance of Float_Conversions or Fixed_Conversions, To_Big_Real is exact (i.e., the result represents exactly the same -mathematical value as the argument) and From_Big_Rational is subject to +mathematical value as the argument) and From_Big_Real is subject to the same precision rules as a type conversion of a value of type T to the target type Num, where T is a hypothetical floating point type whose model numbers include all of the model numbers of Num as well as the @@ -325,47 +325,24 @@ The other functions have their usual mathematical meanings. Implementation Requirements - No storage associated with an Optional_Big_Rational object shall be lost + No storage associated with an Optional_Big_Real object shall be lost upon assignment or scope exit. AARM note: The "No storage ... shall be lost" requirement does not preclude implementation techniques such as caching or unique number tables. For purposes of determining whether predicate checks are performed - as part of default initialization, the type Optional_Big_Rational + as part of default initialization, the type Optional_Big_Real shall be considered to have a subcomponent that has a default_expression. AARM Note: This means that the elaboration of - Default_Initialized_Object : Big_Rational; + Default_Initialized_Object : Big_Real; is required to propagate Assertion_Error. -==== - -This section, or at least the AARM note, is intended to follow -the structure of the analogous wording for AI12-0112-1 (contracts for -containers). - -Add after 11.5(23): - -Big_Number_Check - -Perform the checks associated with Pre, Static_Predicate, Dynamic_Predicate, -or Type_Invariant aspect specifications occuring in the visible part of -package Numerics.Big_Numbers or of any of its descendants. - -AARM Reason: One could use the Assertion_Policy to eliminate such checks, -but that would require recompiling the Ada.Big_Numbers packages (the -assertion policy that determines whether the checks are made is that -used to compile the unit). In addition, we do not want to specify the -behavior of the Ada.Big_Numbers operations if a precondition or predicate -fails; that is different than the usual behavior of Assertion_Policy. -By using Suppress for this purpose, we make it clear that suppressing -a check that would have failed results in erroneous execution. - - !discussion -** None yet. +We presume that AI12-0311-1 is approved, which will allow the preconditions +and predicates of these packages to be suppressed. !ASIS @@ -6396,5 +6373,336 @@ [See the last part of Randy's message of January 8, 2019 7:56 PM for this text - Editor.] + +**************************************************************** + +From: John Barnes +Sent: Thursday, February 7, 2019 7:06 AM + +I have been fretting about this topic for some time – with some restless +nights. + +Please find attached some thoughts. I fear they are in Word rather than plain +text for typographical reasons. + +[Editor's note: These thoughts are found in the Grab-Bag on Ada-Auth.org: + http://www.ada-auth.org/ai-files/grab_bag/literals.pdf ] + +Jeff has helped me with getting my thoughts in order for which I am most +grateful. + +I also have a problem with being very busy with a course at Oxford this term. + +**************************************************************** + +From: Randy Brukardt +Sent: Thursday, February 7, 2019 7:45 PM + +>I have been fretting about this topic for some time - with some +>restless nights. + +I'm the only one that's allowed to have sleepless nights over unimportant Ada +issues. ;-) + +>Please find attached some thoughts. + +[Some thoughts quoted below...] + +> So what to do. Well maybe change AI-249 to provide only one literal +> and please call it just Literal and change the !subject of the AI to +> "User-defined literals". + +The problem with this is that there are three other kinds of user-defined +literals defined in other AIs. We adopted the string literal AI as well (left +the character and null literals for the future, since uses of those are a +stretch). + +Merging real and integer literals also has the very significant downside of +changing a compile-time error into an exception raised in the case of +operations that only want integer literals (like Big_Integer). If + Int : Big_Integer := 3.14; +is legal but raises an exception at runtime, we've lost something significant. + +>I think that if AI-249 defines aspects for Real_Literal and +>Integer_Literal + +>then it ought to say exactly what they are. + +They correspond to a use of the corresponding lexical construct. This is +described in the Dynamic Semantics of each aspect (see 4.2.1 in the draft +RM): + + For the evaluation of an integer (or real) literal with expected type + having an Integer_Literal (or Real_Literal) aspect specified ... + +There might be a clearer way to state this in the wording, and especially in +the AI presentation, but that's the point of editorial review. + +One thing that immediately stands out to me is that it isn't clear that this +is really two separate rules: + + For the evaluation of an integer literal with expected type having an + Integer_Literal aspect specified ... + +and + + For the evaluation of a real literal with expected type having a Real_Literal + aspect specified ... + +Tucker tried to save some wording here, but I don't think the result is +particularly clear (one could easily read these as one single rule, from your +various gripes it appears that you did that), and two shorter sentences (even +if very repetitive) would be better than one longer one. + +This seems like a clear editorial review correction, if you want to request it. + +>Remember also that a key goal of Ada has always been that programs should +>be easy to maintain by someone other than the author. Perhaps we need some +>mark to indicate that the literal has come via an aspect. + +No, that would destroy the purpose (to make the use of user-defined types the +same as the use of built-in types). Ideally, one would get rid of the built-in +types altogether and define everything in packages using these aspects +(literals, indexing, de-reference, iterators, and so on). + +>We might write +> BI: Big_Integer := [-123456]; + +The thing is square brackets is an array/container aggregate in Ada 2020. +Supporting this syntax for literals would destroy the critical reason for +introducing the square bracket syntax for aggregates in the first place: the +ability to write single-valued aggregates in a natural way. + +So you need a different syntax. + +... + +> 1. Do nothing, leave it as it is. There is a risk that old John will +> resign from the ARG and not review anything else ever, ever! A bit +> unlikely since one supposes that he has to update his book. But he is +> very grumpy. + +I don't think we will leave it *exactly* as it is, but I don't think there are +going to be major changes. I had some other thoughts, but they are best kept +to myself. :-) + +> 3. Do something more exciting as outlined above. But at least get rid +> of the Real_Literal and Integer_Literal aspects. Make it just Literal. +> Or if you must keep them, define exactly what the literal form is and +> provide a third aspect Literal for the ambitious user. Or maybe give +> the user the ability to add aspects so that Rational_Literal can be added. + +The reason for Real_Literal and Integer_Literal being separate was discussed +above. There is a third aspect, String_Literal (see AI12-0295-1, which you +haven't reviewed yet). It was split out because people wanted to vote +separately on the different aspects. + +Since these things are tied to the lexical structure of the program, adding +something more is complicated. And it is likely that an ambitious user could +use String_Literal for the sorts of suggestions that you have. + +> 4. Do not confuse rational numbers with a means of providing highly +> accurate real arithmetic. Define Big_Float or Big_Real. Preferably +Big_Real. + +Ah, here we have an actionable suggestion. One has to use rational numbers to +*implement* accurate real arithmetic, but one does not have to *present* it +that way. + +Would you be happier if we renamed the current package and types to "Big_Real" +(no other changes)? This a change I could get behind, as I don't think anyone +really wants rational numbers (certainly not enough people to justify a +standard package), but lots of people want more accurate real numbers. Our +compiler's package calls these things "Univ_Real" (short for universal_real); +there's no sign of rational until you look under the covers. + +>To provide rationals is so easy that it hardly merits being in the language. +>But if it is, provide it as a separate item and do it properly. + +It's not remotely easy (to do correctly and efficiently). One has to reduce +the rationals frequently in order to avoid unbounded memory usage -- but you +can't do that after every operation because it is too expensive. In any case, +rationals are a rare need that doesn't need to be in the language per-se. + +Of course, someone could use the "Big_Real" package for rational math, (the +operations still all being there) but it wouldn't be presented that way. + +>Whatever is done, correct the phrase arbitrary-precision rationals from A.5.5. +>Rationals are always precise. + +Should say "arbitrary-precision reals", of course. That's what people +want/understand. + +**************************************************************** + +From: Tucker Taft +Sent: Thursday, February 7, 2019 9:05 PM + +I understand some of your concerns, John, but I also have experience with +supporting the use literals with user-defined types much as we have proposed, +and it is extremely valuable. I also think the use of the term "Big_Rational" +has set you on edge, and I would agree with Randy that we should change these +to "Big_Real" to avoid the confusion. If they are really viewed externally +as rationals, then you are right that the correct syntax for defining one +would be "N / M" where N and M are integer literals. Instead, they are +intended to be used for arbitrary-precision real values, as is needed, say, +for your average Ada compiler front end. + +The point of AI-249 is not to support odd-ball syntaxes for literals, but +rather to allow the *existing* syntax for numeric literals to be used with +private types. If the AI made you think that users were being given the +opportunity to invent some new kind of syntax for literals, it definitely +needs to be clarified. The first thing to change is the !subject -- instead +of "user-defined numeric literals" it should be "numeric literals for +user-defined types." And we should use that terminology throughout, rather +than ever saying "user-defined literals." We really are not supporting that +in this AI. + +**************************************************************** + +From: John Barnes +Sent: Tuesday, February 12, 2019 9:27 AM + +Changing the title of 249 as you suggest would help a lot. I completely +misunderstood the purpose. + +And making it Big_Real would be excellent. Don't call them rationals +externally. That was the big mistake which as you say set me on edge. + +Make such changes and then I can go to my grave in peace. (well apart from +anonymous access types of course) + +So at the bottom of the problem is that the rationale for these AIs was not +clearly stated. + +**************************************************************** + +From: Bob Duff +Sent: Tuesday, February 12, 2019 11:08 AM + +> And making it Big_Real would be excellent. + +Why on earth would we call something a "real" +if it can't represent irrational numbers such as square root of 2? + +As for literals, you want to be able to say things like: + + X := 1/3; + +where X is a Big_Rat. And you CAN say that. I don't see why it makes any +difference that the RM doesn't call that notation a "literal". You can +think of it as a "literal" notation if you like. + +**************************************************************** + +From: Jean-Pierre Rosen +Sent: Tuesday, February 12, 2019 11:16 AM + +> Why on earth would we call something a "real" +> if it can't represent irrational numbers such as square root of 2? + +Because since FORTRAN-2, it is a tradition to have the false advertisement +of calling "Real" a finite number of values from a bounded segment of the +rationals... + +**************************************************************** + +From: Tucker Taft +Sent: Tuesday, February 12, 2019 11:25 AM + +>> And making it Big_Real would be excellent. +> +> Why on earth would we call something a "real" +> if it can't represent irrational numbers such as square root of 2? + +Well Ada has "universal-real" and it has the same problem. In the context +of Ada, I think Big_Real would be a reasonable name. I agree in a wider +context, it could be misleading. + +> As for literals, you want to be able to say things like: +> +> X := 1/3; +> +> where X is a Big_Rat. And you CAN say that. I don't see why it makes +> any difference that the RM doesn't call that notation a "literal". +> You can think of it as a "literal" notation if you like. + +It is worth pointing out that we do include in the "big-num" AI a "/" operator +that takes two (big) integers and produces a Big_R... We also have a "/" that +takes 2 Big_Rs and produces another Big_R. + +**************************************************************** + +From: Steve Baird +Sent: Tuesday, February 12, 2019 11:31 AM + +> Why on earth would we call something a "real" +> if it can't represent irrational numbers such as square root of 2? +> +> As for literals, you want to be able to say things like: +> +> X := 1/3; +> +> where X is a Big_Rat. And you CAN say that. I don't see why it makes +> any difference that the RM doesn't call that notation a "literal". +> You can think of it as a "literal" notation if you like. + +I agree with Bob. + +And don't forget that we have + function Numerator (Arg : Big_Rational) return Big_Integer; + function Denominator (Arg : Big_Rational) return Big_Positive ... ; which, +to me, strongly suggests that we are talking about rationals here. + +**************************************************************** + +From: Randy Brukardt +Sent: Tuesday, February 12, 2019 3:15 PM + +You are confusing implementation with intended use. Conservatively, 95% of +users of this package are interested in getting exact real math, as in static +universal real calculations. They probably care little about the +implementation technique. I know I find the use of rationals in our universal +math package more annoying that useful. For that large subset of users, they +want "Big_Real" and could care less about rational anything. + +Note that Big_Real usage is the justification for supporting real literals +with the package. I agree with John in the sense that 0.0 makes no sense as a +rational number. But of course it is completely sensible for a Big_Real +number. + +The number of users that actually would want a rational number package is +small enough that we couldn't justify spending any time on standardizing it. + +It would make perfect sense to scrub this package of the operations which +expose a rational implementation, and literally make it a Big_Real package. +But the implementation still would have to be using rationals. + +There's no need to expose the rational implementation for most users, but it's +also harmless to do so for that <5% that actually care for some reason (and it +adds a bit of utility to the package). It's very much like Claw in this +regard: Claw has a handle interface which lets one access the underlying +Windows handles. But hardly anyone should ever need that (I've never used it, +for instance); it just exists for that rare user that has a need. + +One thing I would suggest is to place any of the operations that expose the +implementation dead last in the package (there shouldn't be many), so that the +typical user doesn't have to wade through irrelevant junk to get to the meat. + +**************************************************************** + +From: Steve Baird +Sent: Tuesday, February 12, 2019 6:13 PM + +> Well Ada has "universal-real" and it has the same problem. In the context +> of Ada, I think Big_Real would be a reasonable name. + +I'd still prefer Big_Rational, but I agree that what you are saying makes +sense. + +Ada, for example, defines a type Integer rather than Bounded_Integer even +though the notion of Integer'Last is mathematically somewhat dubious. + +I can live with Big_Real. ****************************************************************

Questions? Ask the ACAA Technical Agent