Path: utzoo!mnetor!uunet!husc6!bloom-beacon!mit-eddie!ll-xn!ames!pasteur!ucbvax!unizh.UUCP!nagler%olsen
From: nagler%olsen@unizh.UUCP (Robert Nagler)
Newsgroups: comp.lang.modula2
Subject: Re:  MathLib0 procedures
Message-ID: <8805100802.AA23848@klaus.olsen.uucp>
Date: 10 May 88 08:02:32 GMT
Sender: daemon@ucbvax.BERKELEY.EDU
Reply-To: Info-Modula2 Distribution List 
Organization: The Internet
Lines: 54

Modula-2 doesn't allow conversion of reals to integers, i.e. you can't
convert a negative integer to a real or vice-versa.  Apparently, Dr. Wirth
found this to be a needed feature, so he included it in a library.  Doing
type coercions to CARDINAL while yield incorrect results (unless there
are other bugs in the language implementation).

Enclosed (below) you will find implementations of these two routines
which are a "best guess" at how these procedures might be implemented
in a portable library.  Most compiler companies supply libraries which
play around with assembly language or floating point chips, therefore
it is often fruitless to look at them for algorithms.

NOTE: Modula-2 has problems with twos complement integers (MININT),
therefore the implementations provided will fail if they are passed MININT.
One can handle the problem, but I felt it would detract from the presentation
of the algorithm if I included the special case code.

Rob

PS. If you are wondering about the FLOAT usage (i.e. FLOAT is passed
    an integer), Modula-2 states that cardinals and integers are assignment
    compatible which means you can pass positive INTEGERs to procedures
    that accept CARDINALs.
---------------------------------------------------------
PROCEDURE real( (* Convert an integer to a real *)
    x : INTEGER (* should be in the range: [ -MAX( x ) .. MAX( x ) ] *)
    ) : REAL;
    VAR
        result : REAL;
    BEGIN (* real *)
        IF x >= 0 THEN
            RETURN FLOAT( x );
        END;
        result := FLOAT( -x );  (* breaks here if MININT (except on Univacs) *)
        RETURN -result;
    END real;

PROCEDURE entier( (* Truncate a real towards negative infinity *)
    x : REAL      (* same restrictions as "real" *)
    ) : INTEGER;
    VAR
        result : INTEGER;
    BEGIN (* entier *)
        IF x > 0.0 THEN
            RETURN TRUNC( x );
        END;
        x := -x;
        result := TRUNC( x );
        (* If the number is not exact, must adjust towards negative infinity *)
        IF FLOAT( result ) # x THEN
            INC( result );
        END;
        RETURN -result;
    END entier;