!standard A.5.8(0) 19-02-01 AI12-0305-1/01 !class Amendment 19-02-01 !status Hold 9-0-1 19-02-26 !status work item 19-02-01 !status received 19-01-29 !priority Low !difficulty Medium !subject Bounded Big Integers !summary Define a Bounded Big Integer package to support arbitrary precision mathematics with bounded memory usage. !problem AI12-0208-1 defines big numbers packages. However, these packages have to be able to support numbers with arbitrary magintudes. As such, some sort of dynamic allocation is needed. For safety-critical applications, dynamic memory management is often not allowed, as there needs to be a guarantee that operations complete as expected. We need to provided bounded but larger than native precision mathematics for such applications. !proposal (See Summary.) !wording A.5.8 Bounded Big Integers [TBD: should Bounded Big Integers come before or after Big Rationals in the RM?] An instance of the language-defined generic package 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 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 Big_Integer is ((+256) ** Capacity); function First return Big_Integer is (-Last); - the partial view of Bounded_Big_Integers.Optional_Big_Integer includes a type invariant specification, Type_Invariant => (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 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. [TBD: change the preceding wording if we go with a predicate instead of a type invariant]. 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 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 that Constraint_Error may be raised in some cases.] Implementation Advice The implementation of (an instance of) Bounded_Big_Integers should not make use of controlled types or dynamic allocation. [end of Implementation Advice] The generic unit Numerics.Big_Numbers.Conversions provides operations for converting between the Big_Integer types declared in Numerics.Big_Numbers.Big_Integers and in an instance of Numerics.Big_Numbers.Bounded_Big_Integers. 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; generic with package Bounded is new Bounded_Big_Integers (<>); package Ada.Numerics.Big_Numbers.Conversions with Preelaborate, Nonblocking is function To_Bounded (Arg : Big_Integers.Big_Integer) return Bounded.Big_Integer; function From_Bounded (Arg : Bounded.Big_Integer) return Big_Integers.Big_Integer; end Ada.Numerics.Big_Numbers.Conversions; AARM Note: No Bounded_Big_Rationals generic package is provided. !discussion Several items have been posed as open issues about this package: * Should Capacity be expressed as a generic formal (as it is in the current proposal) or instead as a discriminant? Each approach has advantages and disadvantages. * What should the meaning of the capacity values be, and how do those map to First/Last values? The current AI has a very implementation-oriented approach, but perhaps a more user-oriented approach would be better (say, a number of decimal digits). !ASIS [Not sure. It seems like some new capabilities might be needed, but I didn't check - Editor.] !ACATS test ACATS B- and C-Tests are needed to check that the new capabilities are supported. !appendix From: Steve Baird Sent: Tuesday, January 29, 2019 7:23 PM Bounded Big Integers were originally part of AI12-0208, but it was decided to split them off into a separate AI. This decision was made in part because there was no consensus about the answers to several questions: 1) Should Capacity be expressed as a generic formal (as it is in the current proposal) or instead as a discriminant? Each approach has advantages. 2) What should the mapping from Capacity values to First/Last values be? The current proposal somewhat arbitrarily defines Last = 256**Capacity (and First=-Last). This has the advantage of portability, but perhaps it overconstrains implementations. 3) Do we have a clear understanding of what problem this language feature is intended to solve? The currently proposed wording for bounded big integers appears below. [Actually, in version /01 of the AI - Editor.] The consensus at the moment seems to be to omit bounded big integers from Ada 2020, although there has been no formal vote yet. **************************************************************** From: Randy Brukardt Sent: Friday, February 1, 2019 7:23 PM >Bounded Big Integers were originally part of AI12-0208, but it was >decided to split them off into a separate AI. This decision was made in >part because there was no consensus about the answers to several >questions: > > 1) Should Capacity be expressed as a generic formal (as it > is in the current proposal) or instead as a discriminant? > Each approach has advantages. > > 2) What should the mapping from Capacity values to > First/Last values be? The current proposal somewhat > arbitrarily defines Last = 256**Capacity (and First=-Last). > This has the advantage of portability, but perhaps it > overconstrains implementations. This is an incomplete description of my position on this issue. I think the Capacity setting should be clearly described in terms that the end-user will understand. Ada has a long tradition of using user-oriented type declarations (digits and delta and ranges); the implementation implications are secondary. In the existing presentation, nothing ever attempts to tell anyone what Capacity means. It simply is described as setting First/Last, and it's up to the user to try to figure out how that relates to what they need. That doesn't seem to be a very Ada approach. I think Steve was trying to use the capacity to describe the number of storage elements used; at a minimum, the wording needs to say that. But given that we don't even know the size of a storage element, I think we're going about this the wrong way. I would prefer have the capacity represent something directly meaningful to the end user. Since we have to avoid using BigInts to describe BigInts, we can't use a range. But we could use something like the number of decimal digits required. I'd also suggest giving minimum bounds for First and Last, rather than hard coding some values. So, one could use a decimal digit capacity and a binary implementation. Ergo, Last would be described to be at least 10**Capacity, but the actual value would be implementation-defined. (That is, have it work like an integer type declaration - what a concept! :-) I note that such a description for Capacity also answers the generic vs. discriminant issue, as it doesn't seem likely that we could ever allow expressions involving "**" and Log2 as discriminant expressions. (I know Steve tried to find some rules that would allow simple expressions involving discriminants as part of a declaaration, but I'm pretty certain a Log2 lookup table isn't part of that. ;-). So I'd be happy with just these changes (but I'm probably the only one :-). > 3) Do we have a clear understanding of what problem this language > feature is intended to solve? Well, I had to put something into the AI, so this is what I wrote: AI12-0208-1 defines big numbers packages. However, these packages have to be able to support numbers with arbitrary magintudes. As such, some sort of dynamic allocation is needed. For safety-critical applications, dynamic memory management is often not allowed, as there needs to be a guarantee that operations complete as expected. We need to provided bounded but larger than native precision mathematics for such applications. We do need to be sure we agree with this, and if we don't or aren't sure, then clearly the best course of action is "No Action". It could very well make sense to see if there really is any user demand for such a package, because if there isn't, any time spent on it is wasted. (Humm, my meter is running. Ding! $$ Ding! $$ Better move on. :-) ****************************************************************