[M3devel] rounding very large magnitude longreal, time, events?

Rodney M. Bates rodney_bates at lcwb.coop
Fri Sep 6 22:39:14 CEST 2013



On 09/04/2013 01:28 AM, Jay K wrote:
>   AMD64_NT starting up mentor:
>
>    ***
>    *** runtime error:
>    ***    An enumeration or subrange value was out of range.
>    ***    file "..\src\EventWireRep.m3", line 89
>    ***
>
>
> This opens up a big multi-part can of worms.
> I'm not sure the order to present things.
> Please bear with me.
>
>
>
> Background:
>
>   Time.T is a double/longreal number of seconds since a platform-specific epoch.
>   This cleverly gives I guess pretty good range and precison.
>   On Windows, that is 1601.
>   The underlying system stores 64bit 100s of nanoseconds.
> This gives both good range and precision.
>   And it works ok with Modula-3.
>   On Posix is presumably 1970.
>   This is all ok. Not controversial.
>
>
>
> Corralaries:
>
> Time.Now on Windows returns around 1.3022747815483961e10.
> My simple math says that is off by a month but hopefully
> more precise math says it is exactly correct.
>   We have confusing Modula-3 code and straightforward C code to compute this.
> That it is within a month seems adequate to backup everything
> else I'm seeing/saying.
>
>
> events!EventWireRep_M3 [c:\dev2\cm3\m3-comm\events\src\eventwirerep.m3 @ 90]
>
>    Int32 = BITS 32 FOR [-2147483647-1..2147483647];
>    TRep = RECORD ts: Int32; objNum: Int32; space: EventSpaceID.T; END;
>
> VAR myTs: Int32 := ROUND(Time.Now());
>
>
>   Clearly this is a problem.
>   It runs out "soon" on 32bit Posix systems, it runs out
>   already on Win64, and on Win32, well, it produces
>   garbage one way or another, but no range errors.
>
>
> On AMD64_NT, this reasonably rounds to
>
>    13022747815 -- the full integer value of the double
>     fits in a 64bit integer.
>
> But it doesn't fit in 32 bits.
>    On I386_NT, this somewhat "correctly" rounds to
>   -2147483648
>
> Hm. Shouldn't it be nearest integer 2147483647??
>
>
> In either case, see you the problem.
>
> Ok, so this is three dilemnas/questions/bugs in one.
>
>
> http://modula3.elegosoft.com/cm3/doc/reference/complete/html/2_6_10Arithmetic_operations.html
>
>
> ROUND(r) is the nearest integer to r; ties are broken according to the constant RoundDefault
>

This has an ambiguity.  "nearest integer" could refer to the integers of mathematics, or to
INTEGER of Modula-3.  The lowercase spelling hints the former.  I think that makes more sense,
too.

By the latter interpretation, values would round to LAST(INTEGER) from far beyond.

By the former interpretation, if the nearest math integer is > LAST(INTEGER), there
should be runtime error of some kind.  But we can't rely on the assignment operation
and Modula-3's assignability rules to do that, because ROUND would have to have a result
type, big enough for all possibilities, a supertype of INTEGER.  There is no such type,
and we don't want one.  (Ever had to cope with Ada's "universal integer" type?  If not,
you're lucky.)

Which leaves making the check part of ROUND itself.

>
> 1) How should ROUND be defined? Is Modula-3 adequately safe here?
>
>
>   What should round of numbers less than FIRST(INTEGER)-1
>   or greater than LAST(INTEGER) + 1 round to?
>
>
>   By the simple definition, they should round to FIRST(INTEGER)
>   and LAST(INTEGER). But is it safe?
>
>
>   You know, I can see taking the whole part of the number
>   and losing the fractional part as being ok when desired,
>   but when the whole part doesn't fit, not even when rounded
>   up or down by 1? Doesn't that seem like it should be a range error?
>
>
>
> 2) What is up with the various implementations?
>
>
> ASSUMING Modula-3 ROUND is defined safely enough,
> is the integrated NT/x86 backend correct here?
>
>
> On I386_DARWIN:
>
> IMPORT IO, Fmt;
>
> BEGIN
> IO.Put(Fmt.Int(ROUND(1.3022747815483961e10)) & "\n");
> END Main.
>
>
> We get: 137845760.
>
>
> Wow, that is just wrong.
> Sure it got the mantissa close, but the exponent is arbitrary seeming.
> I could chalk this up to a bug in my C backend,
> but it gets constant folded in the front end.
> The backend just gets load_integer 137845760.
> This seems highly incorrect.
> Maybe bugs in Target.Float?
> Maybe overflow is being ignored??
> I'll look later, another day.
>
>
>
> 3) What to do?
>
>
> 3a) The frontend seems wrong here, no matter what.
>
> 3b) The integrated backend seems at least slightly wrong.
>
> 3c) The events code either needs widening, or perhaps
> this isn't time, but a somewhat arbitrary "fingerprint".
> Perhaps it can just use MOD?? I will likely verify if it needs to be
> time or just a reasonably volatile number to cross check sender/reciever
> and then use MOD. Posix and Win32 systems probably can't talk to each other. Lame.
>
>
>
> Someone might suggest that Win32 epoch be changed to 1970.
> I don't think so.
>
>
> 4) can anyone understand and explain the Modula-3 code we have here in Time.m3?
>
>
>
> Thank you,
>   - Jay




More information about the M3devel mailing list