<html>
<head>
<style><!--
.hmmessage P
{
margin:0px;
padding:0px
}
body.hmmessage
{
font-size: 10pt;
font-family:Verdana
}
--></style>
</head>
<body class='hmmessage'>
> The question remains: is LONGINT necessary or simply a kludge better satisfied by arbitrary precision arithmetic like BigInteger.T?<BR><BR>
Two of us addressed this.<BR>
The answer is not technically/scientifically pleasing.<BR>The answer is simply that in-fix operators are more convenient and libraries are not.<BR>
Obviously the general clean answer is either:<BR>
operator overloading on user defined types, making the library convenient <BR>
or maybe a language feature for fixed but arbitrary precision integers<BR>
e.g. <BR>
int1024 = BITS 1024 for INTEGER<BR>
or uint1024 = BITS 1024 for [0..Word.LShift(1, 1024)]<BR>
or uint1024 = [0..Word.LShift(1, 1024)]<BR>
<BR>
<BR>
and the compiler would be compelled to generate code for any precision.<BR>
<BR>
<BR>
These are both more work.<BR>
LONGINT is indeed a special case.<BR>
C compilers all provide it "long long" or "__int64".<BR>
File sizes are indeed probably the typical use case for C?<BR>
But also things like InterlockedCompareExchange64 of some "packed" format.<BR>
<BR>
Personally I would gladly accept<BR>
FileSize = [0..Word.LShift(1, 63 or 64)];<BR>
<BR>
<BR>
even so...the compiler/language feature could (initially) limit the "bits" to 64, but<BR>
still implement via this more general syntax and not some new special type/keyword.<BR>
<BR>
<BR>
This is the question floating around: maybe there are just integers of varying size/range.<BR>
<BR>
<BR>
Maybe the compiler can notice if the size is <= or > a natural size?<BR>
<BR>
Mixed arithmetic would be possible among arbitrary pairs of sizes and have a simple<BR>
formula for the result. Assuming "silent wraparound", addition would just pick the larger of the two.<BR>
But then, what if I assign to an even larger type? Hm.<BR>
Then you want addition of n and m to produce max(n, m) + 1, and such.<BR>
Perhaps there is some rule..you know..checked narrowing..?<BR>
And the checks can be omitted if the assignment is to a larger type?<BR>
e.g.<BR>
LONGINT := INTEGER + INTEGER => no overflow check<BR>
LONGINT := LONGINT + LONGINT => overflow check<BR>
int1024 := LONGINT + LONGINT => no overflow check<BR>
?<BR>
<BR>
<BR>
In reality I think no code would use the wider := narrow + narrow.<BR>
But it seems technically reasonable.<BR>
<BR>
<BR>
In reality code either wants the overflow check, or a type that expands its precision as needed.<BR>
("bignum", etc.)<BR>
<BR>
<BR>
- Jay<BR><BR> <BR>> From: hosking@cs.purdue.edu<BR>> Date: Fri, 8 Jan 2010 15:51:13 -0500<BR>> To: rodney_bates@lcwb.coop<BR>> CC: m3devel@elegosoft.com<BR>> Subject: Re: [M3devel] mixing INTEGER and LONGINT?<BR>> <BR>> Once more summarising the discussion so far.<BR>> <BR>> *If* we accept that LONGINT should stay then I agree we should implement Rodney's proposal (the current implementation + assignability between INTEGER and LONGINT + mixed arithmetic).<BR>> <BR>> The question remains: is LONGINT necessary or simply a kludge better satisfied by arbitrary precision arithmetic like BigInteger.T?<BR>> <BR>> On 8 Jan 2010, at 14:42, Rodney M. Bates wrote:<BR>> <BR>> > <BR>> > <BR>> > Mika Nystrom wrote:<BR>> >> Tony Hosking writes:<BR>> >> ...<BR>> >>> A type T is assignable to a type U if:<BR>> >>> <BR>> >>> =95 T <: U, or<BR>> >>> =95 U <: T and T is an array or a reference type other than =<BR>> >>> ADDRESS (This restriction is lifted in unsafe modules.), or<BR>> >>> =95 T and U are ordinal types with at least one member in =<BR>> >>> common.<BR>> >>> <BR>> >>> This suggests that we don't really need to say that INTEGER <: LONGINT.<BR>> >>> <BR>> >>> We can simply rely on the third clause regarding their both being =<BR>> >>> ordinal types with at least one member in common. Then assignment =<BR>> >>> simply needs to test that the values are in range.<BR>> >>> <BR>> >> Are you sure about this for INTEGER and LONGINT? I.e., are 0 and 0L<BR>> >> the same "member"?<BR>> >> By a similar argument, you could make REAL and LONGREAL assignable.<BR>> >> Are 0.0d0 and 0.0e0 the same "thing"? (On almost all machines they have<BR>> >> the same bit patterns, same as 0 and 0L for that matter, and I can add<BR>> >> that the way you do single-precision floating point on Alpha is by zeroing<BR>> >> a big chunk in the middle of your double-precision fp registers...)<BR>> >> I think I am with you on removing LONGINT from the language. The proper<BR>> >> way of handling file sizes (or anything else that might be a bigger number<BR>> >> than a machine word) is through abstraction. I have a suspicion that it's<BR>> >> probably a severe micro-optimization to worry about the efficiency of<BR>> >> operations on file sizes. The thought that someone is adding automatic<BR>> >> type conversion to Modula-3, a la C, makes me feel slightly sick to<BR>> >> my stomach...<BR>> > <BR>> > I agree, I hate the horrible complexities of implicit type conversions<BR>> > in other languages. But this doesn't have to be done by automatic type<BR>> > conversion, just another instance of Modula-3's existing superior concept of<BR>> > assignability between non-disjoint types.<BR>> > <BR>> >> I confess that my position is influenced by the fact that I have written<BR>> >> many programs that generate Modula-3 code as an "intermediate language".<BR>> >> I really really really need M3 to be easy to understand to get this to<BR>> >> work well. Also being able to parse interfaces and know precisely what<BR>> >> they mean is important to me. If the rules start getting sloppy.. that<BR>> >> would really upset me. On the other hand this means that if I'm faced<BR>> >> with a problem that doesn't really fit into M3 well, say, working in<BR>> >> arithmetic mod 2^(wordsize), my first instinct is not to demand changes<BR>> >> to the language definition but to write a code generator that takes<BR>> >> appropriate infix (or maybe more likely prefix) code and turns it into<BR>> >> the appropriate calls through the Word interface. It's a pain, yes, but in the long run that's the right way, because you can do so much<BR>> >> more with that approach than just unsigned integers.<BR>> >> Mika<BR>> > <BR>> > In my original proposal, I said:<BR>> > -------------------------------------------------------------------------<BR>> > This proposal satisfies (I believe) the following principles:<BR>> > <BR>> > The static correctness and type analysis of existing code written to<BR>> > the current language definition will not change with the new<BR>> > definition. This also implies that the new language definition will<BR>> > not introduce new type mismatches that would make existing pickles<BR>> > unreadable.<BR>> > <BR>> > The runtime semantics and time and space efficiency of existing code<BR>> > written to the current language definition will also not change with<BR>> > the new definition, if the native word size of the implementation does<BR>> > not change. Of course, porting existing code to an implementation<BR>> > with different native word size can change the runtime semantics by<BR>> > changing the supported value range, with or without language change.<BR>> > <BR>> > The static type analysis of programs written to the modified language<BR>> > definition will be independent of the implementation, particularly, of<BR>> > the native word size. This prevents inadvertently writing code that<BR>> > is highly nonportable among different native word sizes.<BR>> > <BR>> > The new, not-necessarily-native integer type does not extend to<BR>> > certain existing uses of INTEGER and CARDINAL that are of unlikely<BR>> > utility and would add complexity.<BR>> > <BR>> > <BR>> > -------------------------------------------------------------------------<BR>> > <BR>> > I still believe we can do these things, and also that the changes<BR>> > to the language are not too drastic. They are mostly just more<BR>> > instances of existing concepts.<BR>> <BR> </body>
</html>