--- ai12s/ai12-0208-1.txt 2019/01/08 06:27:03 1.16 +++ ai12s/ai12-0208-1.txt 2019/01/09 02:21:19 1.17 @@ -1,4 +1,4 @@ -!standard A.5.5(0) 18-12-02 AI12-0208-1/06 +!standard A.5.5(0) 19-01-07 AI12-0208-1/07 !standard A.5.6(0) !standard A.5.7(0) !standard A.5.8(0) @@ -42,48 +42,57 @@ A.5.6 Big Integers -The package Ada.Numerics.Big_Numbers.Big_Integers has the following definition: +The package Ada.Numerics.Big_Numbers.Big_Integers has the +following declaration: with Ada.Streams; package Ada.Numerics.Big_Numbers.Big_Integers with Preelaborate, Nonblocking is - type Big_Integer is private with - Default_Initial_Condition => not Is_Valid (Big_Integer), + type Optional_Big_Integer is private with + Default_Initial_Condition => not Is_Present (Optional_Big_Integer), Integer_Literal => From_String, Put_Image => Put_Image; - function Is_Valid (Arg : Big_Integer) return Boolean; + function Is_Present (Arg : Optional_Big_Integer) return Boolean; - subtype Valid_Big_Integer is Big_Integer - with Dynamic_Predicate => Is_Valid (Valid_Big_Integer), + subtype Big_Integer is Optional_Big_Integer + with Dynamic_Predicate => Is_Present (Big_Integer), Predicate_Failure => (raise Constraint_Error); - function Invalid return Big_Integer - with Post => not Is_Valid (Invalid'Result); + function Invalid return Optional_Big_Integer + with Post => not Is_Present (Invalid'Result); - function "=" (L, R : Valid_Big_Integer) return Boolean; - function "<" (L, R : Valid_Big_Integer) return Boolean; - function "<=" (L, R : Valid_Big_Integer) return Boolean; - function ">" (L, R : Valid_Big_Integer) return Boolean; - function ">=" (L, R : Valid_Big_Integer) return Boolean; - - function "+" (Arg : Integer) return Valid_Big_Integer; - function To_Big_Integer (Arg : Integer) return Valid_Big_Integer - renames "+"; + function "=" (L, R : Big_Integer) return Boolean; + function "<" (L, R : Big_Integer) return Boolean; + function "<=" (L, R : Big_Integer) return Boolean; + function ">" (L, R : Big_Integer) return Boolean; + function ">=" (L, R : Big_Integer) return Boolean; + + function To_Big_Integer (Arg : Integer) return Big_Integer; + function "+" (Arg : Integer) return Big_Integer + renames To_Big_Integer; - subtype Big_Positive is Valid_Big_Integer + subtype Optional_Big_Positive is Optional_Big_Integer + with Dynamic_Predicate => Optional_Big_Positive > 0, + Predicate_Failure => (raise Constraint_Error); + + subtype Optional_Big_Natural is Optional_Big_Integer + with Dynamic_Predicate => Optional_Big_Natural >= 0, + Predicate_Failure => (raise Constraint_Error); + + subtype Big_Positive is Big_Integer with Dynamic_Predicate => Big_Positive > 0, Predicate_Failure => (raise Constraint_Error); - subtype Big_Natural is Valid_Big_Integer + subtype Big_Natural is Big_Integer with Dynamic_Predicate => Big_Natural >= 0, Predicate_Failure => (raise Constraint_Error); - function In_Range (Arg, Low, High : Valid_Big_Integer) return Boolean is + function In_Range (Arg, Low, High : Big_Integer) return Boolean is ((Low <= Arg) and (Arg <= High)); - function To_Integer (Arg : Valid_Big_Integer) return Integer + function To_Integer (Arg : Big_Integer) return Integer with Pre => In_Range (Arg, Low => +Integer'First, High => +Integer'Last) @@ -92,8 +101,8 @@ generic type Int is range <>; package Signed_Conversions is - function To_Big_Integer (Arg : Int) return Valid_Big_Integer; - function From_Big_Integer (Arg : Valid_Big_Integer) return Int + function To_Big_Integer (Arg : Int) return Big_Integer; + function From_Big_Integer (Arg : Big_Integer) return Int with Pre => In_Range (Arg, Low => To_Big_Integer (Int'First), High => To_Big_Integer (Int'Last)) @@ -103,40 +112,39 @@ generic type Int is mod <>; package Unsigned_Conversions is - function To_Big_Integer (Arg : Int) return Valid_Big_Integer; - function From_Big_Integer (Arg : Valid_Big_Integer) return Int + function To_Big_Integer (Arg : Int) return Big_Integer; + function From_Big_Integer (Arg : Big_Integer) return Int with Pre => In_Range (Arg, Low => To_Big_Integer (Int'First), High => To_Big_Integer (Int'Last)) or else (raise Constraint_Error); end Unsigned_Conversions; - function To_String (Arg : Valid_Big_Integer; + function To_String (Arg : Big_Integer; Width : Field := 0; Base : Number_Base := 10) return String with Post => To_String'Result'First = 1; - function From_String (Arg : String; - Width : Field := 0) return Valid_Big_Integer; + function From_String (Arg : String) return Big_Integer; procedure Put_Image - (Arg : Valid_Big_Integer; + (Arg : Big_Integer; Stream : not null access Ada.Streams.Root_Stream_Type'Class); - function "-" (L : Valid_Big_Integer) return Valid_Big_Integer; - function "abs" (L : Valid_Big_Integer) return Valid_Big_Integer; - function "+" (L, R : Valid_Big_Integer) return Valid_Big_Integer; - function "-" (L, R : Valid_Big_Integer) return Valid_Big_Integer; - function "*" (L, R : Valid_Big_Integer) return Valid_Big_Integer; - function "/" (L, R : Valid_Big_Integer) return Valid_Big_Integer; - function "mod" (L, R : Valid_Big_Integer) return Valid_Big_Integer; - function "rem" (L, R : Valid_Big_Integer) return Valid_Big_Integer; - function "**" (L : Valid_Big_Integer; R : Natural) - return Valid_Big_Integer; - function Min (L, R : Valid_Big_Integer) return Valid_Big_Integer; - function Max (L, R : Valid_Big_Integer) return Valid_Big_Integer; + function "-" (L : Big_Integer) return Big_Integer; + function "abs" (L : Big_Integer) return Big_Integer; + function "+" (L, R : Big_Integer) return Big_Integer; + function "-" (L, R : Big_Integer) return Big_Integer; + function "*" (L, R : Big_Integer) return Big_Integer; + function "/" (L, R : Big_Integer) return Big_Integer; + function "mod" (L, R : Big_Integer) return Big_Integer; + function "rem" (L, R : Big_Integer) return Big_Integer; + function "**" (L : Big_Integer; R : Natural) + return Big_Integer; + function Min (L, R : Big_Integer) return Big_Integer; + function Max (L, R : Big_Integer) return Big_Integer; function Greatest_Common_Divisor - (L, R : Valid_Big_Integer) return Big_Positive with + (L, R : Big_Integer) return Big_Positive with Pre => (L /= 0 and R /= 0) or else (raise Constraint_Error); private @@ -157,52 +165,62 @@ The other functions have their usual mathematical meanings. +The type Optional_Big_Integer requires finalization. + Implementation Requirements - No storage associated with a Big_Integer object shall be lost upon + No storage associated with an Optional_Big_Integer object shall be lost upon assignment or scope exit. For purposes of determining whether predicate checks are performed - as part of default initialization, the type Big_Integer + as part of default initialization, the type Optional_Big_Integer shall be considered to have a subcomponent that has a default_expression. AARM Note: This means that the elaboration of - Default_Initialized_Object : Valid_Big_Integer; + Default_Initialized_Object : Big_Integer; is required to propagate Assertion_Error. A.5.7 Bounded Big Integers An instance of the language-defined generic package -Numerics.Big_Numbers.Bounded_Big_Integers provides a Big_Integer type and -operations corresponding to those declared in +Numerics.Big_Numbers.Bounded_Big_Integers provides an Optional_Big_Integer +type and operations corresponding to those declared in Numerics.Big_Numbers.Big_Integers, but with the difference that the maximum storage (and, consequently, the set of representable values) is bounded. -The declaration of the generic library package Big_Numbers.Bounded_Big_Integers -has the same contents and semantics as Big_Numbers.Big_Integer except: +The declaration of the generic library package +Numerics.Big_Numbers.Bounded_Big_Integers has the same contents and semantics as +Numerics.Big_Numbers.Big_Integers except: - Bounded_Big_Integers is a generic package and takes a generic formal: Capacity : Natural; - two additional visible expression functions are declared: - function Last return Valid_Big_Integer is ((+256) ** Capacity); - function First return Valid_Big_Integer is (-Last); + function Last return Big_Integer is ((+256) ** Capacity); + function First return Big_Integer is (-Last); - - the partial view of Bounded_Big_Integers.Big_Integer includes + - the partial view of Bounded_Big_Integers.Optional_Big_Integer includes a type invariant specification, Type_Invariant => - (if Is_Valid (Bounded_Big_Integer) then - In_Range (Bounded_Big_Integer, First, Last) + (if Is_Present (Optional_Big_Integer) then + In_Range (Optional_Big_Integer, First, Last) or else (raise Constraint_Error)) + [TBD: instead express this as a Dynamic_Predicate? If so, on + Optional_Big_Integer or on Big_Integer?] -Each subprogram of an instance of Bounded_Big_Integers.Bounded_Big_Integer -behaves like the corresponding Big_Numbers.Big_Integers subprogram except -that type invariant checks are performed as described in 7.3.2. +Each subprogram of an instance of +Numerics.Big_Numbers.Bounded_Big_Integers +behaves like the corresponding Numerics.Big_Numbers.Big_Integers subprogram +except that type invariant checks are performed as described in 7.3.2. +The type Optional_Big_Integer declared by an instance of Bounded_Big_Integers +does not require finalization. + Implementation Requirements For each instance of Bounded_Big_Integers, the output generated by -Big_Integer'Output or Big_Integer'Write shall be readable by the -corresponding Input or Read operations of the Big_Integer type +Optional_Big_Integer'Output or Optional_Big_Integer'Write shall be +readable by the +corresponding Input or Read operations of the Optional_Big_Integer type declared in either another instance of Bounded_Big_Integers or in the package Numerics.Big_Numbers.Big_Integers. [This is subject to the preceding requirement that type invariant checks are performed, so @@ -215,13 +233,13 @@ [end of Implementation Advice] -The generic unit Ada.Numerics.Big_Numbers.Conversions +The generic unit Numerics.Big_Numbers.Conversions provides operations for converting between the Big_Integer types declared -in Big_Numbers.Big_Integers and in an instance of - Big_Numbers.Bounded_Big_Integers. +in Numerics.Big_Numbers.Big_Integers and in an instance of +Numeerics.Big_Numbers.Bounded_Big_Integers. -The generic package Ada.Numerics.Big_Numbers.Conversions -has the following definition: +The generic package Numerics.Big_Numbers.Conversions has the +following declaration: with Ada.Numerics.Big_Numbers.Big_Integers; with Ada.Numerics.Big_Numbers.Bounded_Big_Integers; @@ -231,16 +249,17 @@ with Preelaborate, Nonblocking is function To_Bounded - (Arg : Big_Integers.Valid_Big_Integer) - return Bounded.Valid_Big_Integer; + (Arg : Big_Integers.Big_Integer) + return Bounded.Big_Integer; function From_Bounded - (Arg : Bounded.Valid_Big_Integer) - return Big_Integers.Valid_Big_Integer; + (Arg : Bounded.Big_Integer) + return Big_Integers.Big_Integer; end Ada.Numerics.Big_Numbers.Conversions; A.5.8 Big Rationals -The package Ada.Numerics.Big_Numbers.Big_Rationals has the following definition: +The package Numerics.Big_Numbers.Big_Rationals has the +following declaration: with Ada.Numerics.Big_Numbers.Big_Integers; with Ada.Streams; @@ -249,109 +268,119 @@ is use Big_Integers; - type Big_Rational is private with - Default_Initial_Condition => not Is_Valid (Big_Rational), + type Optional_Big_Rational is private with + Default_Initial_Condition => not Is_Present (Optional_Big_Rational), Real_Literal => From_String, - Put_Image => Put_Image, - Type_Invariant => - (not Is_Valid (Big_Rational)) or else - (Big_Rational = 0.0) or else - (Greatest_Common_Divisor - (Numerator (Big_Rational), - Denominator (Big_Rational)) = 1); + Put_Image => Put_Image; - function Is_Valid (Arg : Big_Rational) return Boolean; + function Is_Present (Arg : Optional_Big_Rational) return Boolean; - function Invalid return Big_Rational - with Post => not Is_Valid (Invalid'Result); + function Invalid return Optional_Big_Rational + with Post => not Is_Present (Invalid'Result); - subtype Valid_Big_Rational is Big_Rational - with Dynamic_Predicate => Is_Valid (Valid_Big_Rational), + subtype Big_Rational is Optional_Big_Rational + with Dynamic_Predicate => Is_Present (Big_Rational), Predicate_Failure => (raise Constraint_Error); - function "/" (Num, Den : Valid_Big_Integer) return Valid_Big_Rational + function "/" (Num, Den : Big_Integer) return Big_Rational 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 + with Post => + (Arg = 0.0) or else + (Greatest_Common_Divisor + (Numerator (Arg), Denominator'Result) = 1); - function Numerator (Arg : Valid_Big_Rational) return Valid_Big_Integer; - function Denominator (Arg : Valid_Big_Rational) return Big_Positive; + function To_Big_Rational (Arg : Big_Integer) return Big_Rational is + (Arg / 1); - function "+" (Arg : Integer) return Valid_Big_Rational is - ((+Arg) / 1); + function "+" (Arg : Integer) return Big_Rational + renames To_Big_Rational; - function To_Big_Rational (Arg : Integer) return Valid_Big_Rational - renames "+"; + function To_Rational (Arg : Integer) return Big_Rational is ((+Arg) / 1); - function "=" (L, R : Valid_Big_Rational) return Boolean; - function "<" (L, R : Valid_Big_Rational) return Boolean; - function "<=" (L, R : Valid_Big_Rational) return Boolean; - function ">" (L, R : Valid_Big_Rational) return Boolean; - function ">=" (L, R : Valid_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_Rational) return Boolean; - function In_Range (Arg, Low, High : Valid_Big_Rational) return Boolean is + function In_Range (Arg, Low, High : Big_Rational) return Boolean is ((Low <= Arg) and (Arg <= High)); generic type Num is digits <>; package Float_Conversions is - function To_Big_Rational (Arg : Num) return Valid_Big_Rational; + function To_Big_Rational (Arg : Num) return Big_Rational; - function From_Big_Rational (Arg : Valid_Big_Rational) return Num + function From_Big_Rational (Arg : Big_Rational) return Num with Pre => In_Range (Arg, Low => To_Big_Rational (Num'First), High => To_Big_Rational (Num'Last)) or else (raise Constraint_Error); end Float_Conversions; - function To_String (Arg : Valid_Big_Rational; + generic + type Num is delta <>; + package Fixed_Conversions is + function To_Big_Rational (Arg : Num) return Big_Rational; + + function From_Big_Rational (Arg : Big_Rational) return Num + with Pre => In_Range (Arg, + Low => To_Big_Rational (Num'First), + High => To_Big_Rational (Num'Last)) + or else (raise Constraint_Error); + end Fixed_Conversions; + + function To_String (Arg : Big_Rational; Fore : Field := 2; Aft : Field := 3; Exp : Field := 0) return String with Post => To_String'Result'First = 1; - function From_String (Arg : String; - Width : Field := 0) return Valid_Big_Rational; + function From_String (Arg : String) return Big_Rational; - function To_Quotient_String (Arg : Valid_Big_Rational) return String is - (To_String (Numerator (Arg)) & " /" & To_String (Denominator (Arg))); - function From_Quotient_String (Arg : String) return Valid_Big_Rational; + function To_Quotient_String (Arg : Big_Rational) return String is + (To_String (Numerator (Arg)) & " / " & To_String (Denominator (Arg))); + function From_Quotient_String (Arg : String) return Big_Rational; procedure Put_Image - (Arg : Valid_Big_Rational; + (Arg : Big_Rational; Stream : not null access Ada.Streams.Root_Stream_Type'Class); - function "-" (L : Valid_Big_Rational) return Valid_Big_Rational; - function "abs" (L : Valid_Big_Rational) return Valid_Big_Rational; - function "+" (L, R : Valid_Big_Rational) return Valid_Big_Rational; - function "-" (L, R : Valid_Big_Rational) return Valid_Big_Rational; - function "*" (L, R : Valid_Big_Rational) return Valid_Big_Rational; - function "/" (L, R : Valid_Big_Rational) return Valid_Big_Rational; - function "**" (L : Valid_Big_Rational; R : Integer) - return Valid_Big_Rational; - function Min (L, R : Valid_Big_Rational) return Valid_Big_Rational; - function Max (L, R : Valid_Big_Rational) return Valid_Big_Rational; + 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 : Big_Integer) + return Big_Rational; + function Min (L, R : Big_Rational) return Big_Rational; + function Max (L, R : Big_Rational) return Big_Rational; private ... -- not specified by the language end Ada.Numerics.Big_Numbers.Big_Rationals; 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 -interpretation of the Fore, Aft, Exp, and Width parameters), except that +interpretation of the Fore, Aft, and Exp parameters), except that Constraint_Error (not Data_Error) is propagated in error cases. From_Quotient_String implements the inverse function of To_Quotient_String; Constraint_Error is propagated in error cases. Put_Image calls To_String, 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. -To_Big_Rational is exact (i.e., the result represents exactly the same -mathematical value as the argument). From_Big_Rational is subject to +For an instance of Float_Conversions or Fixed_Conversions, To_Big_Rational +is exact (i.e., the result represents exactly the same +mathematical value as the argument) and From_Big_Rational 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 exact mathematical value of the argument. [TBD: Is Constraint_Error the exception we want on the Predicate_Failure -aspect specs for Valid_Big_Integer and Valid_Big_Rational?] -[TBD: do we want a Fixed_Conversions generic package analogous to -Float_Conversions?] +aspect specs for Big_Integer and Big_Rational?] [TBD: the range check on From_Big_Rational is slightly too tight. For example, X : IEEE_Float32 := @@ -362,15 +391,15 @@ The other functions have their usual mathematical meanings. Implementation Requirements - No storage associated with a Big_Rational object shall be lost upon - assignment or scope exit. + No storage associated with an Optional_Big_Rational object shall be lost + upon assignment or scope exit. For purposes of determining whether predicate checks are performed - as part of default initialization, the type Big_Rational + as part of default initialization, the type Optional_Big_Rational shall be considered to have a subcomponent that has a default_expression. AARM Note: This means that the elaboration of - Default_Initialized_Object : Valid_Big_Rational; + Default_Initialized_Object : Big_Rational; is required to propagate Assertion_Error. AARM Note: No Bounded_Big_Rationals generic package is provided. @@ -387,7 +416,7 @@ Perform the checks associated with Pre, Static_Predicate, Dynamic_Predicate, or Type_Invariant aspect specifications occuring in the visible part of -package Ada.Big_Numbers or of any of its descendants. +package Numerics.Big_Numbers or of any of its descendants. [TBD: Include Static_Predicate in this list just for completeness, even though it happens that there are no Static_Predicate specifications in @@ -4928,13 +4957,13 @@ From: John Barnes Sent: Monday, December 10, 2018 4:31 PM -Reading some more BigNum. I hadn't expected to cover rationals as well as -integers but seems an interesting idea. +Reading some more BigNum. I hadn't expected to cover rationals as well as +integers but seems an interesting idea. -I see that the type invariant ensures that they are reduced so that the gcd +I see that the type invariant ensures that they are reduced so that the gcd is always 1. In the type invariant it says (Big_Rational = 0.0) ... -How does that 0.0 work? I assume there is an AI that covers the use of +How does that 0.0 work? I assume there is an AI that covers the use of literals in that context that I have missed. And generally where does Is_Valid come from? @@ -4946,27 +4975,27 @@ Do you have to send this base64 stuff? See here: -> DQpSZWFkaW5nIHNvbWUgbW9yZSBCaWdOdW0uIEkgaGFkbid0IGV4cGVjdGVkIHRvIGNvdmVyIHJh -> dGlvbmFscyBhcyB3ZWxsIGFzIGludGVnZXJzIGJ1dCBzZWVtcyBhbiBpbnRlcmVzdGluZyBpZGVh -> LiANCg0KSSBzZWUgdGhhdCB0aGUgdHlwZSBpbnZhcmlhbnQgZW5zdXJlcyB0aGF0IHRoZXkgYXJl -> IHJlZHVjZWQgc28gdGhhdCB0aGUgZ2NkIGlzIGFsd2F5cyAxLiBJbiB0aGUgdHlwZSBpbnZhcmlh -> bnQgaXQgc2F5cyAoQmlnX1JhdGlvbmFsID0gMC4wKSAuLi4NCg0KSG93IGRvZXMgdGhhdCAwLjAg -> d29yaz8gIEkgYXNzdW1lIHRoZXJlIGlzIGFuIEFJIHRoYXQgY292ZXJzIHRoZSB1c2Ugb2YgbGl0 +> DQpSZWFkaW5nIHNvbWUgbW9yZSBCaWdOdW0uIEkgaGFkbid0IGV4cGVjdGVkIHRvIGNvdmVyIHJh +> dGlvbmFscyBhcyB3ZWxsIGFzIGludGVnZXJzIGJ1dCBzZWVtcyBhbiBpbnRlcmVzdGluZyBpZGVh +> LiANCg0KSSBzZWUgdGhhdCB0aGUgdHlwZSBpbnZhcmlhbnQgZW5zdXJlcyB0aGF0IHRoZXkgYXJl +> IHJlZHVjZWQgc28gdGhhdCB0aGUgZ2NkIGlzIGFsd2F5cyAxLiBJbiB0aGUgdHlwZSBpbnZhcmlh +> bnQgaXQgc2F5cyAoQmlnX1JhdGlvbmFsID0gMC4wKSAuLi4NCg0KSG93IGRvZXMgdGhhdCAwLjAg +> d29yaz8gIEkgYXNzdW1lIHRoZXJlIGlzIGFuIEFJIHRoYXQgY292ZXJzIHRoZSB1c2Ugb2YgbGl0 > ZXJhbHMgaW4gdGhhdCBjb250ZXh0IHRoYXQgSSBoYXZlIG1pc3NlZC4NCg0KQW5kIGdlbm > VyYWxs eSB3aGVyZSBkb2VzIElzX1ZhbGlkIGNvbWUgZnJvbT8NCg0KSm9obg0K Anyway: -> How does that 0.0 work? I assume there is an AI that covers the use +> How does that 0.0 work? I assume there is an AI that covers the use > of literals in that context that I have missed. -That's AI12-0249-1, User-defined literals. And note the "Real_Literal => ..." +That's AI12-0249-1, User-defined literals. And note the "Real_Literal => ..." on the type decl. Randy, I suppose that should be "User-defined numeric literals", ^^^^^^^ since we decided to split off: -AI12-0295-1.TXT : !subject User-defined string literals +AI12-0295-1.TXT : !subject User-defined string literals AI12-0296-1.TXT : !subject User-defined character and null literals > And generally where does Is_Valid come from? @@ -4980,20 +5009,20 @@ > Do you have to send this base64 stuff? See here: -John will have to answer that, but I'll point out that when doing so, the -list footers get trashed, the messages get delayed (because of encoding -issues), and I've seen messages that show up blank in people's inboxes -(luckily, that hasn't happened yet with John's messages). So I hope he can +John will have to answer that, but I'll point out that when doing so, the +list footers get trashed, the messages get delayed (because of encoding +issues), and I've seen messages that show up blank in people's inboxes +(luckily, that hasn't happened yet with John's messages). So I hope he can find a way to turn it off when sending to ARG. ... > Randy, I suppose that should be "User-defined numeric literals", -It was that for a while, but it seems to have disappeared in the posted -version. Not sure why (hopefully nothing else important disappeared - this +It was that for a while, but it seems to have disappeared in the posted +version. Not sure why (hopefully nothing else important disappeared - this sometimes happens when I manage to open two copies of a file and put some of -the mods in one copy and some in the other). I note that the clause title -remains "User-Defined Literals", as we did approve the string literals as well +the mods in one copy and some in the other). I note that the clause title +remains "User-Defined Literals", as we did approve the string literals as well (just in a separate AI). **************************************************************** @@ -5001,13 +5030,13 @@ From: John Barnes Sent: Tuesday, December 11, 2018 5:08 AM ->> How does that 0.0 work? I assume there is an AI that covers the use +>> How does that 0.0 work? I assume there is an AI that covers the use >> of literals in that context that I have missed. ->That's AI12-0249-1, User-defined literals. And note the "Real_Literal +>That's AI12-0249-1, User-defined literals. And note the "Real_Literal >=> ..." on the type decl. -I would expect the literal for a rational number to be something like 23/55. +I would expect the literal for a rational number to be something like 23/55. And in this case 0/1 or just plain 0 rather than 0.0 **************************************************************** @@ -5018,10 +5047,10 @@ Hmm. But Real_Literal aspect says From_String so I would have expected "0.0". In any case it is surely asking for trouble to use a real_literal as a literal -for a rational number. Is there not a way of expressing that the literal +for a rational number. Is there not a way of expressing that the literal should be of the form integer_literal/integer_literal? -Sorry I have got years behind in following this largely because of 1) maths at +Sorry I have got years behind in following this largely because of 1) maths at Oxford, 2) getting old, 3)Brexit. **************************************************************** @@ -5029,18 +5058,18 @@ From: Bob Duff Sent: Saturday, December 15, 2018 10:21 AM -> Hmm. But Real_Literal aspect says From_String so I would have expected +> Hmm. But Real_Literal aspect says From_String so I would have expected > "0.0". Yes. -> In any case it is surely asking for trouble to use a real_literal as a +> In any case it is surely asking for trouble to use a real_literal as a > literal for a rational number. -Why is that? Every real_literal can be represented exactly as a Big_Integer, +Why is that? Every real_literal can be represented exactly as a Big_Integer, so I don't see the "trouble". ->... Is there not a way of expressing that the literal should be of the +>... Is there not a way of expressing that the literal should be of the >form integer_literal/integer_literal? You can write 1/3, because of this: @@ -5065,7 +5094,7 @@ Another suggestion: Change Ada.Numerics.Big_Numbers to Ada.Big_Numbers. -I think "numerics" (short for "numerical analysis") generally implies +I think "numerics" (short for "numerical analysis") generally implies "floating point" in computer science. https://en.wikipedia.org/wiki/Numerical_analysis @@ -5083,11 +5112,11 @@ From: John Barnes Sent: Saturday, December 15, 2018 10:49 AM -I don't see Numerics as being short for Numerical analysis at all. In any -event it is possibly rather narrow-minded to think that numerics implies -approximations. I see numerics as being about all sorts of numbers. And it -just depends upon the field one is working in. It could be a finite field say -integers mod 4. +I don't see Numerics as being short for Numerical analysis at all. In any +event it is possibly rather narrow-minded to think that numerics implies +approximations. I see numerics as being about all sorts of numbers. And it +just depends upon the field one is working in. It could be a finite field say +integers mod 4. No I prefer leaving the package name alone. That's OK. @@ -5096,11 +5125,11 @@ From: Bob Duff Sent: Saturday, December 15, 2018 10:53 AM -Should Big_Rats have an operation for throwing away some precision? Like -Round X to the nearest multiple of Y. Or maybe the rounding should be +Should Big_Rats have an operation for throwing away some precision? Like +Round X to the nearest multiple of Y. Or maybe the rounding should be relative to the magnitude of X, or something like that. -The purpose would be to shrink the size (not in terms of magnitude, but in +The purpose would be to shrink the size (not in terms of magnitude, but in terms of memory use). **************************************************************** @@ -5108,17 +5137,17 @@ From: John Barnes Sent: Saturday, December 15, 2018 11:03 AM ->> In any case it is surely asking for trouble to use a real_literal as +>> In any case it is surely asking for trouble to use a real_literal as >> a literal for a rational number. >Why is that? Every real_literal can be represented exactly as a Big_Integer, >so I don't see the "trouble". -Yes but the real trouble is that every rational number cannot be represented -as a real_literal. Note that 5/7 can be represented as a real literal by +Yes but the real trouble is that every rational number cannot be represented +as a real_literal. Note that 5/7 can be represented as a real literal by 7#0.5#. Bur one cannot do it with say 15/17. ->>... Is there not a way of expressing that the literal should be of +>>... Is there not a way of expressing that the literal should be of >>the form integer_literal/integer_literal? > You can write 1/3, because of this: @@ -5129,7 +5158,7 @@ > But 1/3 is not a literal, it's two Big_Integer literals and a division. > I think we'll train GNAT to evaluate that at compile time. -I see 1/3 as the obvious literal form of a rational number. +I see 1/3 as the obvious literal form of a rational number. > We also have this: @@ -5144,23 +5173,23 @@ From: Bob Duff Sent: Saturday, December 15, 2018 11:56 AM -> Yes but the real trouble is that every rational number cannot be +> Yes but the real trouble is that every rational number cannot be > represented as a real_literal. True. But that causes trouble for To_String (solved with the Fore/Aft/Exp kludgery). -But when you write a literal in your program, you're going the other -direction, so it doesn't matter that it's impossible to write a literal for +But when you write a literal in your program, you're going the other +direction, so it doesn't matter that it's impossible to write a literal for every rational number. It still makes sense to write 1.234_567 instead of 1_234_567/1_000_000. Or did I count the zeros wrong? ;-) -> I see 1/3 as the obvious literal form of a rational number. +> I see 1/3 as the obvious literal form of a rational number. -You can think of it that way if you like, but it is not any form of literal +You can think of it that way if you like, but it is not any form of literal allowed by Ada syntax. We could allow quoted literals: @@ -5169,18 +5198,18 @@ but I don't see the point of that. -It's analogous to the fact that -1 (meaning negative one) is not a literal in +It's analogous to the fact that -1 (meaning negative one) is not a literal in Ada. It's a call to the unary minus op, passing the literal 1. In any case, you're free to always use the "/" notation. > > We also have this: -> -> > function "/" (L, R : Valid_Big_Rational) return +> +> > function "/" (L, R : Valid_Big_Rational) return > Valid_Big_Rational; -> +> > >which allows 1.0/3.0, or 123.456/7.89 . -> +> > And that is really disgusting. As Bad as Brexit!! Not THAT bad. @@ -5200,7 +5229,7 @@ From: Ben Brosgol Sent: Saturday, December 15, 2018 11:16 AM -As I recall the history, the child package name "Numerics" was chosen as a +As I recall the history, the child package name "Numerics" was chosen as a compromise, to avoid an Anglo-American dust-up over "Maths" versus "Math" as the name :-). It had nothing to do with an implication of numerical analysis / floating point. @@ -5224,7 +5253,7 @@ https://scicomp.stackexchange.com/questions/tagged/numerics -has a bunch of questions tagged "numerics". I didn't look carefully, but +has a bunch of questions tagged "numerics". I didn't look carefully, but most/all seem to be about floating point. These: @@ -5236,11 +5265,11 @@ Are not "numerical analysis" and "numerical methods" more or less the same thing? -> ... In any event it is possibly rather narrow-minded to think that -> numerics implies approximations. I see numerics as being about all -> sorts of numbers. And it just depends upon the field one is working +> ... In any event it is possibly rather narrow-minded to think that +> numerics implies approximations. I see numerics as being about all +> sorts of numbers. And it just depends upon the field one is working > in. It could be a finite field say integers mod 4. -> +> > No I prefer leaving the package name alone. That's OK. But anyway, my main objection is that the name is too long. @@ -5254,8 +5283,8 @@ And get rid of Big_Numbers, and move its content into Numerics. -P.S. The course "Combinatorial Analysis" at CMU was commonly referred to as -"Combinatorics". It was also called "Combinatorture", because it was hard. +P.S. The course "Combinatorial Analysis" at CMU was commonly referred to as +"Combinatorics". It was also called "Combinatorture", because it was hard. How can the study of counting be hard? ;-) **************************************************************** @@ -5263,15 +5292,15 @@ From: Bob Duff Sent: Saturday, December 15, 2018 11:40 AM -> As I recall the history, the child package name "Numerics" was chosen -> as a compromise, to avoid an Anglo-American dust-up over "Maths" +> As I recall the history, the child package name "Numerics" was chosen +> as a compromise, to avoid an Anglo-American dust-up over "Maths" > versus "Math" as the name :-). I would have been happier with Maths. ;-) ->... It had nothing to do with an implication of numerical analysis / +>... It had nothing to do with an implication of numerical analysis / >floating point. -> +> > In any event I agree with John. An argument in your favor is Ada.Numerics.Discrete_Random. @@ -5290,43 +5319,43 @@ From: Ben Brosgol Sent: Saturday, December 15, 2018 1:53 PM ->> As I recall the history, the child package name "Numerics" was chosen ->> as a compromise, to avoid an Anglo-American dust-up over "Maths" +>> As I recall the history, the child package name "Numerics" was chosen +>> as a compromise, to avoid an Anglo-American dust-up over "Maths" >> versus "Math" as the name :-). -> +> > I would have been happier with Maths. ; That might have been a fair trade for the American culturally imperialistic "Initialize" and "Finalize" spellings :-) ->> ... It had nothing to do with an implication of numerical analysis / +>> ... It had nothing to do with an implication of numerical analysis / >> floating point. >> >> In any event I agree with John. -> +> > An argument in your favor is Ada.Numerics.Discrete_Random. > That's the ONLY one that is not all about floating point. -...and seems sufficient to debunk the claim that Numerics means +...and seems sufficient to debunk the claim that Numerics means floating-point. -> +> > Ada has a well-deserved reputation for verbosity. > That's often a good thing, but here it's just noise. It reflects the logical categorization. -> +> > What about my second suggestion for shortening the names? -If there are future standard packages related to integer or discrete +If there are future standard packages related to integer or discrete arithmetic, should these also come in as immediate children of Ada? I think that Ada.Numerics is the logical parent for bignums as well as any such future packages. > P.S. I shall attempt to refrain from further bikeshedding. -Right, no sense bikeshedding. Instead let's rearrange the deck chairs on the +Right, no sense bikeshedding. Instead let's rearrange the deck chairs on the Titanic(*) :-) > Maybe others will weigh in, or we can have a straw poll. @@ -5342,21 +5371,21 @@ ... > Change Ada.Numerics.Big_Numbers to Ada.Big_Numbers. -> I think "numerics" (short for "numerical analysis") generally implies +> I think "numerics" (short for "numerical analysis") generally implies > "floating point" in computer science. ... -> And a shorter name is better, given that Numerics doesn't add any +> And a shorter name is better, given that Numerics doesn't add any > readability benefit. -Ada has a tradition of having a small number of 2nd-level root packages, -with almost everything else built on top of that: Ada.Characters, -Ada.Strings, Ada.Containers. - -(Aside: Ada 95 clearly messed up the IO packages here, there should have -been Ada.IO (contents of IO_Exceptions), with Ada.IO.Text, -Ada.IO.Sequential, Ada.IO.Direct, etc. The renames could have still used +Ada has a tradition of having a small number of 2nd-level root packages, +with almost everything else built on top of that: Ada.Characters, +Ada.Strings, Ada.Containers. + +(Aside: Ada 95 clearly messed up the IO packages here, there should have +been Ada.IO (contents of IO_Exceptions), with Ada.IO.Text, +Ada.IO.Sequential, Ada.IO.Direct, etc. The renames could have still used the old names. I don't remember, perhaps this was proposed but rejected as -a bridge too far at the time? The whole idea of child packages was new then, +a bridge too far at the time? The whole idea of child packages was new then, it's kinda taken over since.) **************************************************************** @@ -5368,14 +5397,14 @@ > Ada has a well-deserved reputation for verbosity. > That's often a good thing, but here it's just noise. -Not necessarily. My model for suppressing language-defined preconditions is -that is available on a per-subsystem basis (we don't want too many of these -check names). "Big_Numbers" isn't important enough to be a subsystem by +Not necessarily. My model for suppressing language-defined preconditions is +that is available on a per-subsystem basis (we don't want too many of these +check names). "Big_Numbers" isn't important enough to be a subsystem by itself, I would say. Besides, if there ever was a package that would be "used", it's Big_Integer. Even I would "use" that package (and I won't even "use" -Ada.Strings.Unbounded). So the name is nearly irrelevant; I'd be more worried +Ada.Strings.Unbounded). So the name is nearly irrelevant; I'd be more worried about having to write Ada.Unchecked_Deallocation all over the place. (Which we already do...) @@ -5386,8 +5415,8 @@ >Should Big_Rats have an operation for throwing away some precision? -I see the whole purpose of working with rationals to be precise. It wouldn't -make sense to me to throw accuracy away. Encryption/Decryption wouldn't work +I see the whole purpose of working with rationals to be precise. It wouldn't +make sense to me to throw accuracy away. Encryption/Decryption wouldn't work if you chucked bits away. **************************************************************** @@ -5400,17 +5429,17 @@ That's the main purpose. But you might want much-higher precision than the biggest floating-point type, -but still not exact precision. If you can't throw away precision, repeated +but still not exact precision. If you can't throw away precision, repeated calculations can use up memory without bound. -> ...It wouldn't make sense to me to throw accuracy away. +> ...It wouldn't make sense to me to throw accuracy away. > Encryption/Decryption wouldn't work if you chucked bits away. Encryption can use Big_Integers, not Big_Rationals. Here I'm talking only about Big_Rationals. -Actually, encryption wants to use Bounded_Big_Integers, except it wants -modular arithmetic. Hmm. Maybe we should provide such (functions that take +Actually, encryption wants to use Bounded_Big_Integers, except it wants +modular arithmetic. Hmm. Maybe we should provide such (functions that take a Modulus param). ...which leads me to question: @@ -5424,8 +5453,8 @@ function Last return Valid_Big_Integer is ((+256) ** Capacity); function First return Valid_Big_Integer is (-Last); -Why 256? You want it to have an array of word-sized super-digits, not -byte-sized ones. And this is the first time Ada is biased against (say) +Why 256? You want it to have an array of word-sized super-digits, not +byte-sized ones. And this is the first time Ada is biased against (say) 36-bit machines. - the partial view of Bounded_Big_Integers.Big_Integer includes @@ -5435,10 +5464,10 @@ In_Range (Bounded_Big_Integer, First, Last) or else (raise Constraint_Error)) -How does that work? You can't compute numbers bigger than Last (because they +How does that work? You can't compute numbers bigger than Last (because they can't be represented) and then check that they're <= Last. -And there's confusion about the type name -- is it Big_Integer or +And there's confusion about the type name -- is it Big_Integer or Bounded_Big_Integer? And doesn't Last check the invariant, causing infinite recursion? @@ -5451,25 +5480,25 @@ Sent: Sunday, December 16, 2018 12:36 AM > > I see the whole purpose of working with rationals to be precise. -> +> > That's the main purpose. -> -> But you might want much-higher precision than the biggest +> +> But you might want much-higher precision than the biggest > floating-point type, but still not exact precision. -> If you can't throw away precision, repeated calculations can use up +> If you can't throw away precision, repeated calculations can use up > memory without bound. Yes, of course, that's the nature of the beast. Which of course is why memory has to be reclaimed. (Big_Integer alone being almost never necessary these days with 64-bit integers being available.) -And whatever you do to try to minimize the use of such memory also has a +And whatever you do to try to minimize the use of such memory also has a substantial cost. There's no free lunch here. ... > Lots of evidence here that we should standardize existing practice! -Is there any existing practice that would actually be suitable for the Ada +Is there any existing practice that would actually be suitable for the Ada runtime? Most of it is in garbage collected interpreted languages, and hardly any languages actually worry about tasking/parallel operation. @@ -5488,17 +5517,17 @@ Sent: Sunday, December 16, 2018 4:05 AM Waking up in the night and fretting about Brexit I thought I agreed with Bob -that we should drop Numerics since the big numbers and rationals are exact -and all the Numerics stuff was about rough old floating point. Then Ben +that we should drop Numerics since the big numbers and rationals are exact +and all the Numerics stuff was about rough old floating point. Then Ben pointed out that random numbers are in numerics. So stuff it. -But do something about that horrid literal 0.0. It has absolutely no place in -a big number or rational package. Maybe the user defined literals need to be -revisited. Maybe we don't need literals for Rationals anyway. - -And big numbers are typically very big in my view. If you look in my book Nice -Numbers on pages 31 and 32 you will find some fairly big numbers. They have -about 400 digits. They were done by my little Ada 95 package that I wrote a +But do something about that horrid literal 0.0. It has absolutely no place in +a big number or rational package. Maybe the user defined literals need to be +revisited. Maybe we don't need literals for Rationals anyway. + +And big numbers are typically very big in my view. If you look in my book Nice +Numbers on pages 31 and 32 you will find some fairly big numbers. They have +about 400 digits. They were done by my little Ada 95 package that I wrote a long long time ago. **************************************************************** @@ -5508,11 +5537,11 @@ PS -And I really think we should have a procedure that does division and returns -both quotient and remainder in one go to save wasting time doing the job +And I really think we should have a procedure that does division and returns +both quotient and remainder in one go to save wasting time doing the job twice. -Also, as I mentioned before I would like square root returning the largest +Also, as I mentioned before I would like square root returning the largest integer whose square is less than or equal to the integer operand and also returns the remainder. It's easy to write crudely but there are probably short cuts that would be useful. @@ -5523,7 +5552,7 @@ Sent: Sunday, December 16, 2018 11:41 AM > And I really think we should have a procedure that does division and returns -> both quotient and remainder in one go to save wasting time doing the job +> both quotient and remainder in one go to save wasting time doing the job > twice. Hear, Hear! This has been dearly missing since day 1. @@ -5533,20 +5562,20 @@ From: Bob Duff Sent: Sunday, December 16, 2018 1:50 PM -> And I really think we should have a procedure that does division and -> returns both quotient and remainder in one go to save wasting time +> And I really think we should have a procedure that does division and +> returns both quotient and remainder in one go to save wasting time > doing the job twice. Seems reasonable. -> Also, as I mentioned before I would like square root returning the -> largest integer whose square is less than or equal to the integer -> operand and also returns the remainder. It's easy to write crudely but +> Also, as I mentioned before I would like square root returning the +> largest integer whose square is less than or equal to the integer +> operand and also returns the remainder. It's easy to write crudely but > there are probably short cuts that would be useful. But that one seems pretty specialized. What would one use it for? -By the way, "floor of square root" was an example exercise at the SPARK +By the way, "floor of square root" was an example exercise at the SPARK training course I attended years ago. The parameter is 0..System.Max_Int, and it's a little tricky to avoid overflow (and get SPARK to prove that you avoided overflow). Fun example. @@ -5556,7 +5585,7 @@ From: Bob Duff Sent: Sunday, December 16, 2018 1:50 PM -> ... My model for suppressing language-defined preconditions is that is +> ... My model for suppressing language-defined preconditions is that is > available on a per-subsystem basis... Reasonable argument. @@ -5568,7 +5597,7 @@ > > Lots of evidence here that we should standardize existing practice! > -> Is there any existing practice that would actually be suitable for the +> Is there any existing practice that would actually be suitable for the > Ada runtime? Not yet. ;-) @@ -5584,18 +5613,18 @@ From: Bob Duff Sent: Sunday, December 16, 2018 1:50 PM -> (Aside: Ada 95 clearly messed up the IO packages here, there should -> have been Ada.IO (contents of IO_Exceptions), with Ada.IO.Text, -> Ada.IO.Sequential, Ada.IO.Direct, etc. The renames could have still -> used the old names. I don't remember, perhaps this was proposed but +> (Aside: Ada 95 clearly messed up the IO packages here, there should +> have been Ada.IO (contents of IO_Exceptions), with Ada.IO.Text, +> Ada.IO.Sequential, Ada.IO.Direct, etc. The renames could have still +> used the old names. I don't remember, perhaps this was proposed but > rejected as a bridge too far at the time? I don't remember that being proposed. -If I were designing the I/O stuff from scratch, I would separate Output from +If I were designing the I/O stuff from scratch, I would separate Output from Input. They're not just flip sides of each other. ->... The whole idea of child packages was new then, it's kinda taken +>... The whole idea of child packages was new then, it's kinda taken >over since.) **************************************************************** @@ -5607,7 +5636,7 @@ > If they're not, then we're wasting our time designing its spec. Why do you refer to adacore in the third person :-)? -I think the algorithms in unintp and urealp are an excellent starting point +I think the algorithms in unintp and urealp are an excellent starting point anyway, Robert used every trick described in Knuth 2 to make them efficient. i’m certainly eager to start the implementation of 2020. @@ -5621,20 +5650,20 @@ Because I'm not AdaCore. ;-) -I'm an employee of AdaCore, and I'm not in a position to dictate which 2020 -features AdaCore should implement when, and who should do the work. I can +I'm an employee of AdaCore, and I'm not in a position to dictate which 2020 +features AdaCore should implement when, and who should do the work. I can make recommendations to AdaCore management, of course. -> I think the algorithms in unintp and urealp are an excellent starting -> point anyway, Robert used every trick described in Knuth 2 to make +> I think the algorithms in unintp and urealp are an excellent starting +> point anyway, Robert used every trick described in Knuth 2 to make > them efficient. -Whoever implements it should look at those for sure, plus the codepeer -implementation, and the libadalang implementation, and libgmp, and probably +Whoever implements it should look at those for sure, plus the codepeer +implementation, and the libadalang implementation, and libgmp, and probably others. -I'm happy to do that, and Steve has also expressed an interest, and you would -also be a good candidate. But I can't just go and do that without explicit +I'm happy to do that, and Steve has also expressed an interest, and you would +also be a good candidate. But I can't just go and do that without explicit direction from AdaCore management. > i’m certainly eager to start the implementation of 2020. @@ -5646,8 +5675,8 @@ From: Jeff Cousins Sent: Sunday, December 16, 2018 5:01 PM -I thought that half the motivation for thus AI was that it was thought that -compilers had to have something similar internally anyway so implementation +I thought that half the motivation for thus AI was that it was thought that +compilers had to have something similar internally anyway so implementation wouldn't be too expensive? **************************************************************** @@ -5655,13 +5684,13 @@ From: Edmond Schonberg Sent: Sunday, December 16, 2018 9:38 PM -indeed, every conforming Ada compiler needs such a facility to handle -universal integers and universal reals. so they are built into the front-ends +indeed, every conforming Ada compiler needs such a facility to handle +universal integers and universal reals. so they are built into the front-ends of these compilers. Adapting them for run-time use will require some work, in -particular to meet the proposed requirements of storage management (no leaks? -very slow leaks?) but there is a good starting point. Incidentally, every -compiler is equipped to handle a conversion from standard floating-point -notation to rational internal representation, so I agree with John that this +particular to meet the proposed requirements of storage management (no leaks? +very slow leaks?) but there is a good starting point. Incidentally, every +compiler is equipped to handle a conversion from standard floating-point +notation to rational internal representation, so I agree with John that this should be provided in the new packages. **************************************************************** @@ -5669,20 +5698,20 @@ From: John Barnes Sent: Monday, December 17, 2018 2:05 AM -> Also, as I mentioned before I would like square root returning the -> largest integer whose square is less than or equal to the integer -> operand and also returns the remainder. It's easy to write crudely but +> Also, as I mentioned before I would like square root returning the +> largest integer whose square is less than or equal to the integer +> operand and also returns the remainder. It's easy to write crudely but > there are probably short cuts that would be useful. >But that one seems pretty specialized. What would one use it for? -For one thing Its used in Fermat's method for finding prime factors. See -Nice Numbers page 166. I make the students do it on my numbers course at +For one thing Its used in Fermat's method for finding prime factors. See +Nice Numbers page 166. I make the students do it on my numbers course at Oxford. ->By the way, "floor of square root" was an example exercise at the SPARK ->training course I attended years ago. The parameter is 0..System.Max_Int, ->and it's a little tricky to avoid overflow (and get SPARK +>By the way, "floor of square root" was an example exercise at the SPARK +>training course I attended years ago. The parameter is 0..System.Max_Int, +>and it's a little tricky to avoid overflow (and get SPARK > to prove that you avoided overflow). Fun example. There you are, important stuff. @@ -5692,33 +5721,33 @@ From: Randy Brukardt Sent: Monday, December 17, 2018 3:41 PM ->>I thought that half the motivation for thus AI was that it was thought that ->>compilers had to have something similar internally anyway so implementation +>>I thought that half the motivation for thus AI was that it was thought that +>>compilers had to have something similar internally anyway so implementation >>wouldn't be too expensive? >indeed, every conforming Ada compiler needs such a facility to handle >universal integers and universal reals. so they are built into the front-ends >of these compilers. Adapting them for run-time use will require some work, ->in particular to meet the proposed requirements of storage management (no +>in particular to meet the proposed requirements of storage management (no >leaks? very slow leaks?) but there is a good starting point. -Right, but Bob's (unspoken) concern is that once we put these things into the -Standard library, some users are going to want to use them in ways that -require high performance. The version used in the compiler doesn't have any -significant performance concern: even if a multiply took 1/10 second, it -wouldn't noticeably change the compilation time for the vast majority of -units. There are just not that many static expressions to evaluate in most +Right, but Bob's (unspoken) concern is that once we put these things into the +Standard library, some users are going to want to use them in ways that +require high performance. The version used in the compiler doesn't have any +significant performance concern: even if a multiply took 1/10 second, it +wouldn't noticeably change the compilation time for the vast majority of +units. There are just not that many static expressions to evaluate in most units. Even if there are, any sane performance will do. -OTOH, if someone wants to do complex calculations to 400 digits in real-time, -the performance could be a big deal. That's likely to lead to pressure on -implementers to spend extra effort on these packages and on how the compiler +OTOH, if someone wants to do complex calculations to 400 digits in real-time, +the performance could be a big deal. That's likely to lead to pressure on +implementers to spend extra effort on these packages and on how the compiler uses them (perhaps special conversions). -BTW, I don't see a problem with leaking (the Janus/Ada packages never leaked, -we couldn't afford to lose any memory). But the Janus/Ada packages (which were -designed for Ada 83) use limited types with an explicit deallocator call. And -in practice, most of the operations are done with procedure calls, to avoid +BTW, I don't see a problem with leaking (the Janus/Ada packages never leaked, +we couldn't afford to lose any memory). But the Janus/Ada packages (which were +designed for Ada 83) use limited types with an explicit deallocator call. And +in practice, most of the operations are done with procedure calls, to avoid creating temporaries. Something like: -- Find 'Base'Last for an integer type of Size: @@ -5732,32 +5761,609 @@ Udispose (Temp); end; -Of course, no one would want a package like this. But the counterpart would +Of course, no one would want a package like this. But the counterpart would be a controlled type and operator functions. While this would look good: Type_Rec.Last := (2 ** Integer(Size_in_Bits)) - 1; - -It would create and destroy a number of controlled temporaries, which would + +It would create and destroy a number of controlled temporaries, which would likely be more expensive than the original version. -One could mitigate that somewhat by using built-in compiler transformations +One could mitigate that somewhat by using built-in compiler transformations to the procedure form, but obviously that would put a lot of extra stress on -the implementer. (And there has been a lot of resistance to doing that sort +the implementer. (And there has been a lot of resistance to doing that sort of transformation for Reference/Constant_Reference.) -So the best path forward isn't completely clear, even though compilers have +So the best path forward isn't completely clear, even though compilers have such implementations. ->Incidentally, every compiler is equipped to handle a conversion from ->standard floating-point notation to rational internal representation, +>Incidentally, every compiler is equipped to handle a conversion from +>standard floating-point notation to rational internal representation, >so I agree with John that this should be provided in the new packages. It *is* provided in the new packages, and John appeared to be arguing -*against* providing it. That didn't make a lot of sense to me. Janus/Ada -doesn't, however, provide the conversion from rational to real notation -string (we of course do provide a conversion to 32 and 64 bit float values, +*against* providing it. That didn't make a lot of sense to me. Janus/Ada +doesn't, however, provide the conversion from rational to real notation +string (we of course do provide a conversion to 32 and 64 bit float values, but we didn't need the strings outside of the calculator test program, so we didn't figure out how to do that). **************************************************************** +From: Steve Baird +Sent: Monday, January 7, 2018 2:51 PM + +The attached version #5 of this AI [Regardless of what this message says, +this is version /07 of this AI - Editor] is intended to address +issues/questions raised since distribution of version #4 on 12/2/18. + +Thanks, in particular, to Bob and Randy for their careful review and +thoughtful comments. + +A summary of those issues/questions, along with their proposed resolutions, +follows below. + +==== + +1) Delete Width parameter from From_String functions? +Yes; removed in version 5. + +2) Should unary "+" rename To_Big_Integer instead of vice versa (and similarly + for To_Big_Rational)? +Yes; change is in version 5. + +3) "has the following definition" => "has the following declaration" + wording change? +Yes; change is in version 5. + +4) Change names? + Big_Integer => Optional_Big_Integer + Valid_Big_Integer => Big_Integer + Is_Valid => Is_Present + (and similarly for Big_Rational) + and add Optional_Big_Natural, Optional_Big_Positive subtypes. +Yes; change is in version 5. The Is_Valid -> Is_Present substitution wasn't +mentioned in the discussion, but it seems obvious now that we are no longer +talking about validity. + +5) Add a Big_Int -> Big_Rational conversion function? + Similarly, add a Big_Rat exponentiation operator that takes + a Big_Integer instead of an Integer for the exponent argument? +Further discussion is needed here. +There are changes in version 5 for this, but they are not what was +requested. +The problem (which was not mentioned in the original discussion) +is to avoid introducing ambiguity in the case of a call +where the actual parameter is a numeric literal. +This non-overloading requirement makes the problem trickier. +We could introduce a nested package, but the obvious solution is +to avoid overloading by using different names for the function pairs. +In the case of exponentiation, choosing a name other than "**" would +defeat the whole point, so we just give up and don't provide a +version that takes a Standard.Integer exponent (we only provide +the Big_Integer exponent version - in version #4, only a +Standard.Integer exponent version was provided, but if we are +only going to provide one then shouldn't it be the Big_Integer version?). +In the case of To_Big_Rational, we've got + To_Big_Rational, going from Big_Integer to Big_Rational +and + To_Rational, going from Standard.Integer to Big_Rational +. This is a bit ugly - for example, it's not obvious why the names +shouldn't be reversed. Perhaps the name should be Integer_To_Big_Rational? +Other candidate names include "Make" or "Convert".] + +6) Missing blank in To_Quotient_String? +Yes; change is in version 5. +Indeed, the intent is to generate a string like "123 / 4567". + +7) Do we want a Fixed_Conversions generic package analogous to + Float_Conversions? +Consensus seems to be yes and, in particular, that the implementability +issues that Randy raised have been addressed; change is in version 5. +The precision requirement wording is the same for both +Some_Instance_Of_Float_Conversions.To_Big_Rational and for +Some_Instance_Of_Fixed_Conversions.To_Big_Rational. An equivalence rule +is used to avoid any need to talk about support/non-support of Annex G. + +8) Avoid long package names by eliminating Big_Numbers package or + moving Big_Numbers package out of Numerics (so that it is + Ada.Big_Numbers instead of Ada.Numerics.Big_Numbers). +In the opinion of the AI author, this is not a good idea. The originally +chosen names are consistent with Ada's naming conventions in other +cases, and are just fine as proposed. +No changes in version 5 related to this issue. + +9) Do we want some sort of a "coarsen" operator whose informal idea is + "given a Big_Rational argument, return a value that is close to the + given value but which takes up less storage"? In some cases, + "1 / 1" might be preferable to something like + "999999999999999999999999999998 / 999999999999999999999999999999". +This sounds like a good idea, but it is not clear what the spec should +look like. One idea is a Round_To_Nearest_Multiple function, where the +user passes in a delta value (a positive big_rational) and the function +returns a result which is an exact integral multiple of that delta value +(with tiebreaker rules based on Ada's rules for converting to a fixed +point type). Another idea is a Best_Approximation function where +the user passes in a denominator value (a positive big_integer) and the +function computes the closest continued fraction approximation +having a denominator no greater than the specified denominator value. +It would be nice to simply require that the function returns the closest +approximation to the given argument subject to the denominator +constraint, but I don't know how to implement that. [It has to do with +not just computing convergents, but also semi-convergents; for more +details, see the site I mentioned in a message to the ARG list last +January, + +shreevatsa.wordpress.com/2011/01/10/not-all-best-rational-approximations-are-the-convergents-of-the-continued-fraction +].It does seem clear that the function, however it is defined, +should be portable. I'm leaning toward the Round_To_Nearest_Multiple +approach, but it seems like more discussion is needed. + +10) Get rid of the GCD type invariant for big rationals + and replace it with a functionally equivalent + postcondition on Denominator? [this question came up in private + communication with Randy] +Yes; change is in version 5. + +11) For each of the types defined in the AI, specify whether the + type needs finalization? [point brought up by Randy] +Yes; change is in version 5. + +12) There are 3 relatively unimportant TBD's remaining in version 5, +left over from version 4. These have to do with whether we want +Constraint_Error (as opposed to some other exception) raised in certain +cases, do we care if the range check on From_Big_Rational is +ever-so-slightly too tight, and whether we should mention Static_Predicate +in the Big_Number_Check rules. [There is also fourth TBD having to do +with the proposed type invariant for Bounded big integers, but that is +discussed below in item #14.] +status: unchanged since version 4. + +13) Is the standard "No storage .. shall be lost" implementation +requirement what we want here? For example, does this wording preclude a +"unique number table" type of implementation and, if it does, is +this a problem? +status: undecided + +14) The thorniest set of problems has to do with Bounded_Big_Integers. +Bob and Randy argue that Bounded_Big_Integers should not be a generic +with a formal Capacity parameter and that instead it should be a +non-generic package and the type +Bounded_Big_Integers.Optional_Big_Integer should have a visible +Capacity discriminant (with no default value). +There are other questions too, but let's start with that one. + +There are drawbacks to the discriminated approach: + - Equality: presumably we don't want the discriminant value to + participate in equality. So just have an explicitly-declared + "=" function that does the right thing; this isn't much of a + problem, although this definition of equality can lead to + unintuitive results in some cases. + + - Assignment: assignment between objects with differing discriminant + values will fail a discriminant check, so users will have to + somehow avoid this. This gets messy. + + One solution is to use procedures instead of functions, where we + pass in the result as an out-mode parameter. It's ugly, + and it is a very different way of doing things than what the + unbounded version provides. Another solution + is to use a Copy function which creates a copy of a given + number having a given discriminant value. With this approach, an + aggregate might look something like + + S_Capacity : constant Capacity_Type := ... ; + subtype S is Bounded.Big_Integer (Capacity => S_Capacity); + + type R is + record + ... <other fields> ... + Big_Int : S; + end record; + + X : R := ( ..., + Big_Int => Copy (Some_Big_Int + Another_Big_Int, + Capacity => S_Capacity)); + + In addition to being ugly, this approach has a performance + impact (those Copy calls won't be free). + + - Function results: + There is the question of what the discriminant + values should be for the results of the various functions + defined in the spec. We certainly do not want those to be + implementation-dependent (why would we want to introduce a + substantial portability problem?), so they would need to be + defined. What should those definitions be? [Note that there + seem to be some holes in the RM in this area for functions + that return bounded containers. If you try to answer this + question by asking "Well, how was this issue handled for + unbounded vectors?", you will be disappointed.] + + The discriminated approach would also mean that function + calls would have to use the presumably-less-efficient + unconstrained function result mechanism. If a function call + provides the value for a component of an aggregate, for example, + the address of the component of the aggregate's object can + be passed in for the callee to fill in (i.e. build in place) + in the undiscriminated implementation, but probably not + in the discriminated case. + +Another question whose answer does not seem obvious has to do with +the mapping from Capacity values (whether expressed as a generic formal +or as a discriminant) to bounds. The current proposal defines this via + function Last return Big_Integer is ((+256) ** Capacity); + function First return Big_Integer is (-Last); +. I think we want this mapping to be portable (although there +may be performance-based arguments for making this mapping +implementation dependent), but even so it is not at all obvious that +the above mapping is the best one. + +There is also a related TBD issue in version 5 regarding the question +of whether we want to use a type invariant, a subtype predicate, or +something else to express this range "constraint". In version 5, we have + Type_Invariant => + (if Is_Present (Optional_Big_Integer) then + In_Range (Optional_Big_Integer, First, Last) + or else (raise Constraint_Error)) +but perhaps this idea should be expressed as a dynamic predicate on +the subtype Big_Integer. + +Bob suggests that we consider completely omitting the bounded version +from this AI on the grounds that we don't know enough yet to make +informed decisions about these issues. For clients who want to support +N-bit arithmetic where N is large but fixed (e.g., 1024-bit integers), +perhaps we want to provide "wrapping" operators (similar to the +operations of modular types). +Perhaps standardizing the bounded version would be premature. + +**************************************************************** + +From: Tucker Taft +Sent: Monday, January 7, 2018 3:13 PM + +> 5) ... +> +> In the case of exponentiation, choosing a name other than "**" would +> defeat the whole point, so we just give up and don't provide a version +> that takes a Standard.Integer exponent (we only provide the +> Big_Integer exponent version - in version #4, only a Standard.Integer +> exponent version was provided, but if we are only going to provide one +> then shouldn't it be the Big_Integer version?).... + +I think exponentiation is really a special case, and Standard.Integer should +be the exponent for X ** <int>. Even for user-defined integer types, the +exponent is still Standard.Integer. It is inconceivable that we could +represent values with exponents larger than Integer'Last unless the base is +0, 1, or -1. + +As a fall-back for those really interested in Aleph-1-sized values (and with +appropriate amount of memory to go with it ;-), presumably you could use +Big_Rat ** Big_Rat, and then convert the result to Big_Int. + +**************************************************************** + +From: Steve Baird +Sent: Monday, January 7, 2018 5:02 PM + +> I think exponentiation is really a special case, and Standard.Integer +> should be the exponent for X ** <int>. +... +> It is inconceivable that we could represent values with exponents +> larger than Integer'Last unless + +Fine with me, as long as you promise not to complain the next time you want +to estimate the number of possible orderings of the atoms in the known +universe. + +**************************************************************** + +From: Randy Brukardt +Sent: Monday, January 7, 2018 5:16 PM + +Remember that Ada only requires Integer'Last >= 32767, and 2 ** 32768 isn't +completely impossible. + +**************************************************************** + +From: Tucker Taft +Sent: Monday, January 7, 2018 5:28 PM + +I'm not worried about this particular issue, personally. ;-) + +**************************************************************** + +From: Tucker Taft +Sent: Monday, January 7, 2018 3:20 PM + +> 4) Change names? +> Big_Integer => Optional_Big_Integer +> Valid_Big_Integer => Big_Integer +> Is_Valid => Is_Present +> (and similarly for Big_Rational) +> and add Optional_Big_Natural, Optional_Big_Positive subtypes. +> Yes; change is in version 5. The Is_Valid -> Is_Present substitution +> wasn't mentioned in the discussion, but it seems obvious now that we +> are no longer talking about validity. + +I will say I am not in love with "Is_Present" as a way to check whether an +Optional_Integer has been initialized. I think the name of the constant +representing the default value of an Optional_integer (in this case, still +"Invalid") should determine the name of the query function. So I would stick +with "Is_Valid" if the named constant is "Invalid." If we change the constant +to be named something else, such as "Null_Big_Integer" then "Not_Null" and +"Is_Null" would be nice query functions. + +In general, I don't think of an "Optional_Integer" as being optionally +"present," but rather being optionally "initialized." But in any case, I +think the name of the constant and the name of the query should be aligned. +We could name the constant "Absent_Integer" I suppose, but that just seems +weird. ;-) + +**************************************************************** + + +From: Steve Baird +Sent: Monday, January 7, 2018 4:36 PM + +> So I would stick with "Is_Valid" if the named constant is "Invalid." + +That was an oversight on my part. I intended to remove all references to +validity but forgot about Invalid (which, incidentally, is defined as a +parameterless function). I'd say those functions should be named +Null_Big_Integer and Null_Big_Rational. + +And I certainly agree with you about the undesirable inconsistency of +Is_Present and Invalid. + +**************************************************************** + +From: Tucker Taft +Sent: Monday, January 7, 2018 4:56 PM + +>> So I would stick with "Is_Valid" if the named constant is "Invalid." + +> That was an oversight on my part. I intended to remove all references +> to validity but forgot about Invalid (which, incidentally, is defined +> as a parameterless function). I'd say those functions should be named +> Null_Big_Integer and Null_Big_Rational. + +Then I would argue for providing Not_Null and perhaps also Is_Null as +query functions, rather than Is_Present. + +**************************************************************** + +From: Randy Brukardt +Sent: Tuesday, January 8, 2018 8:12 PM + +> I'd say those functions should be named +> Null_Big_Integer and Null_Big_Rational. + +Gee, if we hadn't deferred the Null_Literal aspect (now, AI12-0296-1), you +could have called them "null". (Ducking incoming brickbats... :-) + +**************************************************************** + +From: Tucker Taft +Sent: Monday, January 7, 2018 3:32 PM + +> 13) Is the standard "No storage .. shall be lost" implementation +> requirement what we want here? For example, does this wording preclude +> a "unique number table" type of implementation and, if it does, is +> this a problem? +> status: undecided +> +> 14) The thorniest set of problems has to do with Bounded_Big_Integers. +> Bob and Randy argue that Bounded_Big_Integers should not be a generic +> with a formal Capacity parameter and that instead it should be a +> non-generic package and the type +> Bounded_Big_Integers.Optional_Big_Integer should have a visible +> Capacity discriminant (with no default value). +> There are other questions too, but let's start with that one. +> +> There are drawbacks to the discriminated approach:... + +I think we can leave the wording about "No storage shall be lost" as is. We +could add an AARM note clarifying that this is intended to permit caching or +unique-num tables. I don't see the need for an explicit "Implementation +Permission." Compiler customers will make their concerns known if they really +care. + +I agree with keeping the bound as a generic formal. Bounded_String works this +way, so that is a precedent. And anything where each object has its own bound +seems like a nightmare to maintain as the rest of the code changes. And as you +point out, if it is a discriminant that will inevitably mean heavier use of +more expensive function returns, which runs counter to the purpose of bounding +the size. + +I would also support carving bounded big nums off as a separate AI, and not +including it in this revision of the standard, but having it "out there" as +an AI for anyone to use as a model for a package they implement, should they +so choose. + +*************************************************************** + +From: Randy Brukardt +Sent: Monday, January 7, 2018 4:01 PM + +> I think we can leave the wording about "No storage shall be lost" as +> is. We could add an AARM note clarifying that this is intended to +> permit caching or unique-num tables. I don't see the need for an +> explicit "Implementation Permission." +> Compiler customers will make their concerns known if they really care. + +I agree. Storage being lost would be a significant problem for long running +programs, so it seems wrong for a general-purpose library. The RM should be +clear that never recovering storage is incorrect. However, how often storage +is recovered and similar topics, though, are between an implementer and their +customers. + +> I agree with keeping the bound as a generic formal. +> Bounded_String works this way, so that is a precedent. + +Yup, it's bad enough that there is almost no use to bounded strings. :-) I've +stopped trying to use them at all because of that. Surely, let's double down +on a mistake. + +> And anything where each object has its own bound seems like a +> nightmare to maintain as the rest of the code changes. And as you +> point out, if it is a discriminant that will inevitably mean heavier +> use of more expensive function returns, which runs counter to the +> purpose of bounding the size. + +I don't understand this last point. A discriminant is just a constant +component, and build-in-place works the same way for records regardless of +the component types (assuming the type is not mutable). + +Moreover, for Janus/Ada, adding genericity makes things slower in general +(since it requires passing around descriptors), so it seems likely that the +discriminant approach would be a bit more efficient (fewer things to pass into +these functions). + +Moral: I don't think we ought to make the decision here based on efficiency +concerns -- they vary wildly -- usability is much more important. Steve's +arguments about assignment are much more important than anything to do with +efficiency. (Aside: The bounded containers use a procedure Assign for +assignment; that wasn't an option that Steve considered, I'm not sure why. +Perhaps assignment is less likely for the containers than for BigNums.) + +> I would also support carving bounded big nums off as a separate AI, +> and not including it in this revision of the standard, but having it +> "out there" as an AI for anyone to use as a model for a package they +> implement, should they so choose. + +Yes, I fully concur with this. This doesn't seem sufficiently baked at the +moment, and I'm not sure there is enough baking time left. (We don't want to +be that chef that serves our clients raw bread pudding. ;-) + +We need to figure out a reasonable implementation-independent way to specify +the capacity that makes sense for the user view (and not from some theoretical +implementation view). Perhaps that would answer the other questions anyway (if +the capacity is specified as a real value, then it can't be a discriminant). + +One possibility is to simply specify the bounds (like with other integer +types), probably as real values, and left the implementation figure out how +convert that into bytes or nibbles or whatever representation it is using. +(It would be tempting to specify the bounds as unbounded bignums, but that +of course eliminates the solution.) + +**************************************************************** + +From: Tucker Taft +Sent: Monday, January 7, 2018 5:00 PM + +>> ... +> +>> And anything where each object has its own bound seems like a +>> nightmare to maintain as the rest of the code changes. And as you +>> point out, if it is a discriminant that will inevitably mean heavier +>> use of more expensive function returns, which runs counter to the +>> purpose of bounding the size. +> +> I don't understand this last point. A discriminant is just a constant +> component, and build-in-place works the same way for records +> regardless of the component types (assuming the type is not mutable). + +If the caller doesn't know the size of the object being returned, then you +inevitably end up doing some sort of secondary stack or heap allocation. +The point of having a bounded type is usually to reduce the amount of dynamic +allocation, so having object's whose size is unknown to the caller makes +function return more expensive, even if you are doing build in place. + +In any case, if we agree to defer bounded big nums, then we don't have to +agree on the bounding mechanism. + +**************************************************************** + +From: Randy Brukardt +Sent: Tuesday, January 8, 2018 7:56 PM + +> The attached version #5 of this AI is intended to address +> issues/questions raised since distribution of version #4 on 12/2/18. + +Typos that I fixed while posting: + +Start of A.5.7: + +> The declaration of the generic library package +Big_Numbers.Bounded_Big_Integers +> has the same contents and semantics as +> Big_Numbers.Optional_Big_Integer +except: + +Cool! There is a package Optional_Big_Integer! I wonder if it is optional? +:-) + +It looks like the original name was missing the "s" (Big_Integer{s}), and thus +the global replace went too far. + +Also, when naming packages in the Standard, we usually drop "Ada" and leave +everything else. (That was the silliest decision ever; I recall someone wanted +the text of the Standard to be shorter, and that was the MRT response +- drop 4 characters in a handful of places.) + +So this needs to include the "Numerics" part in this wording. (See how A.5.2 +and A.5.3 present their packages.) And drop "Ada." wherever it appears in the +text. (Gotta save those 4 characters! :-) + +> Each subprogram of an instance of +> Bounded_Big_Integers.Bounded_Optional_Big_Integer +> behaves like the corresponding Big_Numbers.Big_Integers subprogram +> except that type invariant checks are performed as described in 7.3.2. + +??? What is Bounded_Optional_Big_Integer? It isn't mentioned anywhere else. +Is this supposed to be +Big_Numbers.Bounded_Big_Integers? I've assumed that's the intent. + +> 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 Ada.Big_Numbers or of any of its descendants. + +No package "Ada.Big_Numbers", it's "Ada.Numerics.Big_Numbers" (and we always +drop the "Ada." in text). + +============ + +Technical issues on this (I didn't make any of these changes): + +My intent was that there was one such suppression check per subsystem, so this +would be: + +Numeric_Check + +Perform the checks associated with Pre, Static_Predicate, Dynamic_Predicate, +or Type_Invariant aspect specifications occuring in the visible part of +package Numerics or of any of its descendants. + +The idea is that there would also be "String_Check" (for Ada.Strings), +"Character_Check" (for Ada.Characters), "IO_Check" (for the packages that +should have been in Ada.IO, Text_IO, Sequential_IO, etc.), "System_Check" +(for System), and "Interface_Check" (for Interfaces). Of course, those only +matter if we start defining preconditions and the like for them. + +---- + +Type_Invariants are required to be followed by 1.1.3(17.1/5); there's no +reason to suppress them as they can't fail for a correct implementation (same +reason we don't include postconditions here). I could see a compiler +generating them for debugging purposes, but that wouldn't be the standard +mode (what compiler wants to generate unnecessary code??). + +---- + +Aspect specifications are "associated" with a declaration, it would be clearer +to use that wording I think (it's certainly closer to the Containers wording). + +---- + +We need to mention instances of generic units here as well. Adapting the +current wording of the Containers version with all of the above: + +Perform the checks associated with the Pre, Static_Predicate, or +Dynamic_Predicate aspects associated with an entity declared in a descendant +unit of Numerics or in an instance of a generic unit that is declared in, or +is, a descendant unit of Numerics. + +****************************************************************

Questions? Ask the ACAA Technical Agent