Version 1.5 of ai12s/ai12-0184-1.txt

Unformatted version of ai12s/ai12-0184-1.txt version 1.5
Other versions for file ai12s/ai12-0184-1.txt

!standard B.3(71.3/3)          16-10-02 AI12-0184-1/03
!class Amendment 16-03-23
!status Amendment 1-2012 16-08-01
!status ARG Approved 11-0-1 16-06-12
!status work item 16-03-23
!status received 15-04-24
!priority Low Low
!difficulty Easy Easy
!subject Long Long C Data Types
!summary
Implementation Advice is added that Ada types that correspond to the C99 64-bit types be defined when possible.
!problem
The C99 standard defines some additional standard types:
long long long long int signed long long signed long long int
Long long signed integer type. Capable of containing at least the [-9223372036854775807, +9223372036854775807] range; thus, it is at least 64 bits in size.
unsigned long long unsigned long long int
Similar to long long, but unsigned. Specified since the C99 version of the standard.
!proposal
(See Wording.)
!wording
Add after B.3(71.3/3):
An implementation should provide unsigned_long_long and long_long as 64-bit modular and signed integer types (respectively) in package Interfaces.C if the C implementation supports unsigned long long and long long as 64-bit types.
!discussion
We already have Wide_Wide_ types, so there can't be any problem with Long_Long_ types. It would be cool if we had a type that was both: Wide_Wide_Long_Long_Int. ;-)
Seriously, we have to be careful here. If we just dumped these types into Interfaces.C, we're implicitly requiring all Ada compilers to support 64-bit types. That's inappropriate on embedded hardware without 64-bit support (especially so on 8-bit and 16-bit targets - even though Ada is not much used on such targets it would be silly to prevent it).
B.3(62) already allows adding any types that the implementation needs to ease interfacing with the C implementation. So, we just add Implementation Advice that the appropriate types be supported if appropriate. That requires nothing on an implementation (IA can always be ignored, if documented).
!corrigendum B.3(71.2/3)
Insert after the paragraph:
the new paragraph:
An implementation should provide unsigned_long_long and long_long as 64-bit modular and signed integer types (respectively) in package Interfaces.C if the C implementation supports unsigned long long and long long as 64-bit types.
!ASIS
No ASIS effect.
!ACATS test
An ACATS C-Test is needed to check that the new capabilities are supported.
!appendix

!topic some missing long long C data types
!reference Ada 2012 RM B.3 Interfacing with C and C++
!from Pascal Pignard 15-12-21
!keywords C type
!discussion

From https://en.wikipedia.org/wiki/C_data_types:

long long
long long int
signed long long
signed long long int
Long long signed integer type. Capable of containing at least
the [-9223372036854775807, +9223372036854775807] range; thus, it is at least
64 bits in size. Specified since the C99 version of the standard.

unsigned long long
unsigned long long int
Similar to long long, but unsigned. Specified since the C99 version of the
standard.

These new types coming with C99 are missing in the library package
Interfaces.C (annex B3).

****************************************************************

!topic some missing long long C data types
!reference Ada 2012 RM B.3 Interfacing with C and C++
!from Pascal Pignard 15-12-21
!keywords C type
!discussion

Note: I've never seen any reply on the list since I sent the message end of
last year, sorry if this has been already taken in account.

From https://en.wikipedia.org/wiki/C_data_types:
long long
long long int
signed long long
signed long long int
Long long signed integer type. Capable of containing at least
the [-9223372036854775807, +9223372036854775807] range; thus, it is at least
64 bits in size. Specified since the C99 version of the standard.

unsigned long long
unsigned long long int
Similar to long long, but unsigned. Specified since the C99 version of the
standard.

These new types coming with C99 are missing in the library package
Interfaces.C (annex B3).

****************************************************************

From: Randy Brukardt
Sent: Wednesday, March 30, 2016  6:52 PM

> !topic some missing long long C data types
>
> Note: I've never seen any reply on the list since I sent the message
> end of last year, sorry if this has been already taken in account.

No answer was necessary: the types are clearly not in Interfaces.C, and so far
as I'm aware we've never previously considered them, so we just opened an AI
so the topic gets discussion.

One question that has to be answered is how to avoid requiring 64-bit integers
on targets for which that is not appropriate (surely 8-bit targets and probably
16-bit targets as well). Just sticking the types into Interfaces.C would
certainly have that effect. It's not clear how C addresses this (it would seem
even more important there, as C is used on more 8-bit and 16-bit targets than
Ada is). Since the core of Ada only requires 16-bit integers, it would seem
like madness to require much more just in one side issue (but one that is
essentially required in a practical Ada compiler).

This is especially concerning to me, since the shared generic model of
Janus/Ada means that all operations inside of a generic unit for a formal
integer or discrete type have to use the largest supported integer type.
Forcing 64-bit support on a small target would have a devastating performance
impact on generic instantiations (like Ada.Text_IO.Integer_IO). (I remember
that supporting 16-bit integers on the Z80 was a chore - it's hard to imagine
what a 64-bit integer would be like.)

That has to be discussed.

****************************************************************

From: Randy Brukardt
Sent: Wednesday, March 30, 2016  7:14 PM

...
> No answer was necessary: the types are clearly not in Interfaces.C,
> and so far as I'm aware we've never previously considered them, so we
> just opened an AI so the topic gets discussion.

I forgot to mention the number in case you want to follow its progress: it is
AI12-0184-1. (I haven't posted it yet, it will be in the next batch, posted
sometime between now and the week of our Pisa meeting - early June.)

****************************************************************

From: Brad Moore
Sent: Wednesday, March 30, 2016  3:28 PM

>!topic some missing long long C data types

Personally, I would agree on the need for these. I recently ran into a case
where I needed two routines that perform the same function, except one which
used a subtype of Integer, and the other where I  would have used a subtype of
Long_Long_Integer, but could not so so in a portable manner so I ended up
having to create my own type, which introduced the need for explicit
conversions in many places in my code which is annoying.

****************************************************************

From: Randy Brukardt
Sent: Wednesday, March 30, 2016  7:11 PM

???

I don't see what requiring support in Intefaces.C for some predefined C types
has to do with any Ada types in Standard. Using them for other than for
interfacing is bad practice, and package Interfaces.C is optional anyway (so
depending on it is never 100% portable).

If you really care about portability you have to stick to Ada 2005 at the
absolute most (there's only one Ada 2012 compiler) so anything done now is
irrelevant for that purpose.

I can't imagine requiring 64-bit support on all possible targets; that's
essentially the same as locking the language only to 32-bit and 64-bit targets
(and it would have negative effects even on 32-bit targets -- for Janus/Ada, a
64-bit integer is a non-standard Integer type specifically to avoid those
negative effects).

Integer and Long_Long_Integer are different types, so the routines would be
different in any case. Converting between them would always need type
conversions.

Long_Long_Integer is not portable (it's not required, and in fact it is
supposed to be rejected by Restriction No_Implementation_Identifiers).

Good code never uses any of the types in Standard. (Sure, we all write sloppy
code from time-to-time, but why should the Standard encourage that?) The only
way to write portable Ada code that needs values >32767 is to declare your own
types -- that's always been true and I doubt very much that we're going to
change it just to make it easier for sloppy programs.

One thing that has been missing from Ada is the ability to declare Ada
discrete types with a C convention; the Standard requires one to derive them
from some type in Interfaces.C but it's not at all clear to me why that's a
good idea. All compilers that I am aware of treat all discrete types as
C-compatible anyway, so it's really only a problem for pedants, but it does
prevent maximizing the portability of one's code. (OTOH, we discussed this in
passing when we were dealing with the enumeration type problem and decided for
some reason that I don't recall not to fix it.)

I think I better stop! (I'm probably off on the wrong tangent for whatever
reason.)

****************************************************************

From: Tucker Taft
Sent: Wednesday, March 30, 2016  8:05 PM

> I don't see what requiring support in Intefaces.C for some predefined
> C types has to do with any Ada types in Standard. Using them for other
> than interfaces is bad practice, and package Interfaces.C is optional
> anyway (so depending on it is never 100% portable).

I have a somewhat different view.  I think that we ought to encourage
implementors to include in Interfaces.C all of the types supported by the
local "standard" C compiler.
Since "long long XXX" is now a standard part of C, we should encourage
implementors to include it in Interfaces.C.  I am guessing most of them do
already.

It is true that it won't be 100% portable, but it should be portable to all
environments where there is support for a C compiler that supports long long
(which most of them do these days).

Note that implementors are permitted to add declarations to Interfaces.C, and
I suspect many of them attempt to match whatever is provided by the supported
C compiler.

****************************************************************

From: Randy Brukardt
Sent: Wednesday, March 30, 2016  9:19 PM

???

I agree with all that you said above, but I don't see what it has to do with
what I said or what Brad said (or, for that matter, with what the Ada Standard
says). (Or why you think that your view is different than mine!)

I said (or meant, anyway) that *in non-interfacing code*, you shouldn't be
using declarations in Interfaces.C, or for that matter, declarations in
Standard. Best practice in Ada is always to declare your own integer types.
That's such a basic Ada tenet that I'd be surprised to hear anyone disagree
with it (of course in sloppy, throwaway code, one ignores lots of best
practices, but no one is likely to care about portability of that).

And if you're only worried about 99% portability, then declaring your own
types will work even for interfacing code (since all compilers I know of allow
pretty much any discrete type to be C-compatible - you don't need a convention
declaration, which is good since the language doesn't allow it anyway). You'd
use the types in Interfaces.C only if you have an API that uses one of those
predefined types.

The question I have is about the cost of *requiring* long_long_int in
Interfaces.C, as that appears to force 64-bit math regardless of the target.
I'm surely not against *allowing* or even *encouraging* (i.e. Implementation
Advice) long_long_int in Interfaces.C.

Jeff reported privately that he couldn't find anything in the C 2011 Standard
that made long_long_int optional, but of course that would mean that 8-bit C
implementations would have to support 64-bit math (or ignore C 2011) -- and
that seems to violate the Dewar rule (does the Dewar rule apply to the C
Standard?? :-). But regardless of what the C Standard does or does not do, we
need to consider whether we want to let the C people force such a requirement
on us.

I guess I do disagree with you on one point: for the vast majority of Ada
compilers that do not share code generators with the C implementation, the
cost of supporting long_long_int or any other C data type could be
significant. (In general, Janus/Ada tries to map types it implements, and
doesn't try to map types that it has no counterpart for.) That's especially
true for smaller targets -- even if the C compiler has 64-bit types, that
doesn't mean that it is somehow easy to support it in another code generator.
(It's a huge amount of work to add a new discrete representation to Janus/Ada
- it was designed with exactly 3 such representations for integers [8, 16,
and 32 using those up] - I started adding a fourth signed representation for
decimal types decades ago, but never finished it and there is no hint of an
unsigned representation. I'd think similar things would be true for other
code generators - if they don't already have 64-bit support, it would be very
expensive to add it.) Thus I don't think whether or not the C compiler has
long_long_int makes any difference -- the question is whether the Ada compiler
supports them. If it does, then it certainly should support long_long_int. And
if it doesn't, it isn't going to be able to magically support long_long_int
whether or not the C compiler does.

So I see this as an issue that potentially could prevent some existing
compilers from ever being upgraded to Ada 202x. I'd think we'd want as few
as possible barriers to implementers doing that, lest GNAT be the only
"current" Ada compiler forever.

P.S. As I mentioned before, forcing 64-bit support also would impact the
performance on any non-64-bit target. Exactly how bad that would be is not
clear to me (it's certainly not in the "sky-is-falling" category), but one has
to evaluate any runtime universal expression in the largest integer type, and
64-bit operations (especially multiply and divide) are pretty expensive on
smaller targets.

****************************************************************

From: Tucker Taft
Sent: Wednesday, March 30, 2016  9:33 PM

I don't see requiring it, since as you point out, supporting Interfaces.C is
optional to begin with.  But we could strongly encourage it for
implementations that already support 64-bit integers, and even specify the
recommended names to use.

And yes I agree it is almost always better to declare your own integer types,
but sometimes the interfacing-to-the-outside-world requirements trump that,
and you have an incentive to use the "external" types inside your program as
well, at least in certain places.

****************************************************************

From: Brad Moore
Sent: Thursday, March 31, 2016  12:02 AM

> I don't see what requiring support in Intefaces.C for some predefined
> C types has to do with any Ada types in Standard. Using them for other
> than interfaces is bad practice, and package Interfaces.C is optional
> anyway (so depending on it is never 100% portable).

Right, my response was more about the broader topic of providing support for 64
bit integers, than just within Interfaces.C. The example I brought up was more
specifically about Long_Long_Integer.

> If you really care about portability you have to stick to Ada 2005 at
> the absolute most (there's only one Ada 2012 compiler) so anything
> done now is irrelevant for that purpose.

In my case, my approach is to provide compatibility using (at least) 3 different
versions of the source.

One for Ada 95, one for Ada 2005, and one for Ada 2012.

I try to make use of the current language features applicable to each version of
the standard.

So there should be a flavour that fits most existing compilers today hopefully.
That's about as portable as one can get, I would think.

As more Ada 2012 compilers come available, more can move to the 2012 source
baseline.

> I can't imagine requiring 64-bit support on all possible targets;
> that's essentially the same as locking the language only to 32-bit and
> 64-bit targets (and it would have negative effects even on 32-bit
> targets -- for Janus/Ada, a 64-bit integer is a non-standard Integer
> type specifically to avoid those negative effects).
>
> Integer and Long_Long_Integer are different types, so the routines
> would be different in any case. Converting between them would always
> need type conversions.
>
> Long_Long_Integer is not portable (it's not required, and in fact it
> is supposed to be rejected by Restriction No_Implementation_Identifiers).

Maybe Long_Long_Integer wouldn't need to be required to be minimum 64 bits, but
rather at least as long as Long_Integer, similar to how Long_Integer doesn't
need to be more bits than Integer. There may be good reasons why that isn't
workable, but it strikes me as maybe being a better option than leaving it to be
implementation defined.

> Good code never uses any of the types in Standard. (Sure, we all write
> sloppy code from time-to-time, but why should the Standard encourage
> that?) The only way to write portable Ada code that needs values
> >32767 is to declare your own types -- that's always been true and I
> doubt very much that we're going to change it just to make it easier for
> sloppy programs.

I don't consider my situation to be sloppy code, but beauty is in the eye of the
beholder, as they say.

In my case, my goal is to provide some library calls, without using generics,
where the library calls are to be potentially retrofitted into existing code in
some cases. The intent is to have it so the library calls as much as possible,
can be inserted with a minimum amount of change to the existing code.

For example, consider library calls for parallel loops, where an iterator type
is needed for the loops.

Some loops are OK with 32 bit iterator types, but others need 64 bit iterator
types.

Ideally, the iterator type used by the library should as best as possible match
the iterator types used by the existing code, because it is the users iterator
type that the library is trying to replace. If users use either the standard
integer types directly, or hopefully at least use subtypes of those types rather
than derived types or new types, then an iterator subtype provided by the
library will match all of those cases, and not require explicit conversions. For
derived types or new integer types, type conversions are needed, but at least
the client of the library has the choice of deciding to use either approach.

If one has the loop...

    declare
      subtype My_Integer is Integer;
      Sum : My_Integer := 0;
    begin
       for I in 1 .. 10 loop
          Sum := Sum + I;
       end loop;
    end;

This compiles of course.

But, if the declaration for My_Integer is changed to;
   type My_Integer is new Integer, then the code no longer compiles,
   as explicit conversions are needed to add I to Sum.

Such loops are quite common, where the type of the Iterator really is one of the
standard types. That may be one of the big reasons why people use subtypes,
rather than new types in a lot of cases, because it fits better with the
iterator types that are being used.

I am not using Long_Integer, or Long_Long_Integer directly in my code, but
rather something like;

subtype Loop_Iteration_Index_Type is Long_Integer;

By using a subtype, my code provides more flexibility in allowing clients to
decide whether they want to use explicit casting or not.

If I used a new type, then I am forcing more explicit conversions which some
clients might find annoying.

****************************************************************

From: Randy Brukardt
Sent: Thursday, March 31, 2016  1:38 AM

> Right, my response was more about the broader topic of providing
> support for 64 bit integers, than just within Interfaces.C.
> The example I brought up was more specifically about
> Long_Long_Integer.

Please don't confuse topics. They're only vaguely related.

...
> As more Ada 2012 compilers come available, more can move to the 2012
> source baseline.

Sure, but this is Ada 202x at the earliest. That's a *new* flavor of Ada beyond
the ones we already have. Even if you have some new portability there, it sure
as heck won't change what is available in any of the older versions.

...
> > Long_Long_Integer is not portable (it's not required, and in fact it
> > is supposed to be rejected by Restriction No_Implementation_Identifiers).
>
> Maybe Long_Long_Integer wouldn't need to be required to be minimum 64
> bits, but rather at least as long as Long_Integer, similar to how
> Long_Integer doesn't need to be more bits than Integer. There may be
> good reasons why that isn't workable, but it strikes me as maybe being
> a better option than leaving it to be implementation defined.

Names like Long_Long_Integer and Wide_Wide_Character are abominations that
should not in the Standard the first place. They're obtrusive, emphasize the
wrong thing, and scale badly (even while it appears obvious -- is it really easy
to tell between Long_Long_Integer and Long_Long_Long_Integer?? 128-bit types
seem inevitable.) I'm against any expansion of the use of names like these.

The decision to make types other than Integer and Long_Integer
"implementation-defined" was quite intentional. (And not my idea, I point out.)
We didn't want people using those other types if they wanted any sort of
portability (and preferably not at all).

> > Good code never uses any of the types in Standard. (Sure, we all
> > write sloppy code from time-to-time, but why should the Standard
> > encourage
> > that?) The only way to write portable Ada code that needs values
> > >32767 is to declare your own types -- that's always been true and I
> > doubt very much that we're going to change it just to make it easier
> > for sloppy programs.
>
> I don't consider my situation to be sloppy code, but beauty is in the
> eye of the beholder, as they say.
>
> In my case, my goal is to provide some library calls, without using
> generics, where the library calls are to be potentially retrofitted
> into existing code in some cases. The intent is to have it so the
> library calls as much as possible, can be inserted with a minimum
> amount of change to the existing code.

This problem seems to be the exact reason that generics were invented. Any Ada
user would expect to instantiate a generic (just like you need to do that to get
I/O, or a container, or pretty much anything else useful).

Unless you are trying to code for Janus/Ada, generics don't even have any
significant runtime cost, so it's hard for me to see a good reason to avoid
them. (And for Janus/Ada, you can get much smaller code by using a common
generic that is instantiated a bunch of times.)

> For example, consider library calls for parallel loops, where an
> iterator type is needed for the loops.
>
> Some loops are OK with 32 bit iterator types, but others need
> 64 bit iterator types.
>
> Ideally, the iterator type used by the library should as best as
> possible match the iterator types used by the existing code, because
> it is the users iterator type that the library is trying to replace.
> If users use either the standard integer types directly, or hopefully
> at least use subtypes of those types rather than derived types or new
> types, then an iterator subtype provided by the library will match all
> of those cases, and not require explicit conversions. For derived
> types or new integer types, type conversions are needed, but at least
> the client of the library has the choice of deciding to use either
> approach.
>
> If one has the loop...
>
>     declare
>       subtype My_Integer is Integer;
>       Sum : My_Integer := 0;
>     begin
>        for I in 1 .. 10 loop
>           Sum := Sum + I;
>        end loop;
>     end;
>
> This compiles of course.
>
> But, if the declaration for My_Integer is changed to;
>    type My_Integer is new Integer, then the code no longer compiles,
>    as explicit conversions are needed to add I to Sum.

This is a red herring:
(1) If you change subtype My_Integer to "is Long_Integer", the loop doesn't
    compile anymore, either. The type-free iterator is a special case for type
    Integer only. I can see your library for the special case of type Integer
    (only); otherwise it pretty much has to be generic.
(2) If you had written the loop with a correct subtype in the first place:
      for I in My_Integer range 1 .. 10 loop
then it doesn't matter how you change the declaration of My_Integer:
       subtype My_Integer is Integer;
       subtype My_Integer is Long_Integer;
       type My_Integer is range 0 .. 1000; all work fine.

Since the original code was sloppy and mixed subtypes, it doesn't
(necessarily) continue to work when the subtype is changed.

> Such loops are quite common, where the type of the Iterator really is
> one of the standard types.

No, loops that are of type Integer are very common. Any other type has to be
explicit, and if that's the case, it takes very little work to use a proper type
(and properly model your problem).

Sloppy code is rather common, and that's a sad state of affairs, but what does
it have to do with the language? Under no circumstances should the language get
involved in making sloppy code easier -- Ada's core is strong typing and we have
come to regret many of the times that we've deviated (i.e. anonymous access
types).

> That may be one of the
> big reasons why people use subtypes, rather than new types in a lot of
> cases, because it fits better with the iterator types that are being
> used.

I think you're conflating two different issues here.

> I am not using Long_Integer, or Long_Long_Integer directly in my code,
> but rather something like;
>
> subtype Loop_Iteration_Index_Type is Long_Integer;

This seems to be the worst of both worlds. You've got a much longer name
standing in for a shorter name that you shouldn't be using explicitly in the
first place.

> By using a subtype, my code provides more flexibility in allowing
> clients to decide whether they want to use explicit casting or not.

Obviously, if your library was generic, the users would be making that decision
as well. I don't see much advantage as to avoiding the generic library here, as
you're still making the users use special subtype names and the like. (And if
they *don't* use the special name, then they're making the kind of fragile code
like that you show above. When people write stuff like that, they get what they
deserve.)

> If I used a new type, then I am forcing more explicit conversions
> which some clients might find annoying.

If you had simply used a generic, you wouldn't even have the question. And users
could be good and use a new type, or bad and use a type from Standard, and make
their own decisions. Ada 83 solved this particular problem, and nothing better
has ever appeared (in any language so far as I know). What you're talking about
sounds like a return to the bad old days.

As I noted earlier, I could see a special non-generic version for Integer, but
there doesn't seem to be any point for other types.

And I don't see any language change that is needed, unless the rest of the ARG
suddenly decided that they wanted to force 64-bit types down everybody's
throats. I don't expect that to happen, and it certainly has nothing to do with
the question of how to interface to certain C99 predefined types.

****************************************************************

From: Brad Moore
Sent: Thursday, March 31, 2016  8:40 AM

> Please don't confuse topics. They're only vaguely related.

Sorry, I should probably create a separate topic for this, but probably only
worth doing so, if I can convince myself of the need.

The problem I presented is itself not compelling enough to introduce a change.
It's more that I might have used such a type if it existed in the standard.

But I think what I really wanted is some way to use a type that can take
advantage of the maximum range of integers on the target architecture, while
being portable.

I think the best way to do that, would instead be to create my own type based on
System.Min_Int and System.Max_Int, such as;

    type Big_Num is range System.Min_Int .. System.Max_Int;

Given this, I think the issues I presented can be dropped.

More below...

>
> ...
>> As more Ada 2012 compilers come available, more can move to the 2012
>> source baseline.
>
> Sure, but this is Ada 202x at the earliest. That's a *new* flavor of
> Ada beyond the ones we already have. Even if you have some new
> portability there, it sure as heck won't change what is available in
> any of the older versions.

True enough.

>
> ...
>>> Long_Long_Integer is not portable (it's not required, and in fact it
>>> is supposed to be rejected by Restriction
> No_Implementation_Identifiers).
>>
>> Maybe Long_Long_Integer wouldn't need to be required to be minimum 64
>> bits, but rather at least as long as Long_Integer, similar to how
>> Long_Integer doesn't need to be more bits than Integer. There may be
>> good reasons why that isn't workable, but it strikes me as maybe
>> being a better option than leaving it to be implementation defined.
>
> Names like Long_Long_Integer and Wide_Wide_Character are abominations
> that should not in the Standard the first place. They're obtrusive,
> emphasize the wrong thing, and scale badly (even while it appears
> obvious -- is it really easy to tell between Long_Long_Integer and
> Long_Long_Long_Integer?? 128-bit types seem inevitable.) I'm against
> any expansion of the use of names like these.

I agree that this naming convention is not a good one. If we really wanted a
type name for something that is specifically 64 and 124 bits, something like;

Integer_64 and Integer_124 would probably be better choices.

But we actually already have such types in the standard package Interfaces.

RM B.2 (7-8) has the following Implementation Requirements;

"An implementation shall provide the following declarations in the visible part
of package Interfaces:

Signed and modular integer types of n bits, if supported by the target
architecture, for each n that is at least the size of a storage element and that
is a factor of the word size. The names of these types are of the form Integer_n
for the signed types, and Unsigned_n for the modular types; "

So if the compiler conforms to Annex B, it suggests that Integer_64 would need
to be defined if that is the word size of the target architecture. I think this
answers the need that I was presenting.

For the case of interfacing to C, maybe a 64 bit integer type could be provided
by using similar wording such that it is supported only if it is a factor of the
word size for the target architecture.

...
>> In my case, my goal is to provide some library calls, without
>> using generics, where the library calls are to be potentially
>> retrofitted into existing code in some cases. The intent is
>> to have it so the library calls as much as possible, can be
>> inserted with a minimum amount of change to the existing code.
>
> This problem seems to be the exact reason that generics were invented. Any
> Ada user would expect to instantiate a generic (just like you need to do
> that to get I/O, or a container, or pretty much anything else useful).
>
> Unless you are trying to code for Janus/Ada, generics don't even have any
> significant runtime cost, so it's hard for me to see a good reason to avoid
> them. (And for Janus/Ada, you can get much smaller code by using a common
> generic that is instantiated a bunch of times.)

In my case there are good reasons on both sides, which is why I have
both generic and non-generic libraries.

The advantages for the generic libraries include the ones that you mention.

For non-generic however there are the following benefits for the case of
parallelism loop libraries.

1) Easier to support multiple reductions in the same loop.
    This is hard to describe without going into a lot of detail,
    so I wont bother here.
    With Generics, suffice it to say that you need to provide the type
    of the reduction, and the reduction operation subprogram.
    This doesn't scale well if
    multiple reductions are involved. One could consider passing in
    arrays of class wide types, but it adds a lot of complexity.

2) Non-Generic libraries can be distributed in binary form, with or
without source code.
3) Non-Generic libraries can be called from other languages.

...
>> If one has the loop...
>>
>>      declare
>>        subtype My_Integer is Integer;
>>        Sum : My_Integer := 0;
>>      begin
>>         for I in 1 .. 10 loop
>>            Sum := Sum + I;
>>         end loop;
>>      end;
>>
>> This compiles of course.
>>
>> But, if the declaration for My_Integer is changed to;
>>     type My_Integer is new Integer, then the code no longer compiles,
>>     as explicit conversions are needed to add I to Sum.
>
> This is a red herring:
> (1) If you change subtype My_Integer to "is Long_Integer", the loop doesn't
> compile anymore, either. The type-free iterator is a special case for type
> Integer only. I can see your library for the special case of type Integer
> (only); otherwise it pretty much has to be generic.

I found this surprising to me. i.e. That one cannot write:

for I in 1 .. 8_000_000_000 loop
...
end loop;

But, as you say, can be remedied with a type conversion such as;

for I in 1 .. Big_Num (8_000_000_000) loop
    ....
end loop;

****************************************************************

From: Jean-Pierre Rosen
Sent: Thursday, March 31, 2016  3:14 AM

> The question I have is about the cost of *requiring* long_long_int in
> Interfaces.C, as that appears to force 64-bit math regardless of the target.
> I'm surely not against *allowing* or even *encouraging* (i.e.
> Implementation
> Advice) long_long_int in Interfaces.C.

Seems to me that the reasonable compromise to handle this would be to put all
types from the C standard in Interfaces.C, with an implementation permission to
omit some types if they are not supported by the C compiler you are interfacing
to.

****************************************************************

From: Randy Brukardt
Sent: Monday, August 1, 2016  11:47 PM

Another for-the-record note. In Pisa, we said that the wording (Implementation
Advice) for this AI is:

  An implementation should provide unsigned_long_long and long_long as 64-bit
  types if the C implementation supports unsigned long long and long long as
  64-bit types.

I think this is a bit sloppy, in that it doesn't define the kind of types nor
where the types ought to be provided. We can do that with just a few extra words:

  An implementation should provide unsigned_long_long and long_long as 64-bit
  modular and signed integer types (respectively) in package Interfaces.C if
  the C implementation supports unsigned long long and long long as 64-bit
  types.

Probably not something that most implementers would get wrong, but why leave
it to chance?

****************************************************************

From: Jeff Cousins
Sent: Tuesday, August 2, 2016  1:35 AM

Seems better.

****************************************************************

From: Tucker Taft
Sent: Tuesday, August 2, 2016  4:32 PM

Your suggestions are fine by me.

****************************************************************

Questions? Ask the ACAA Technical Agent