PreviousUpNext

15.4.714  src/lib/core/init/core-two-word-int.pkg

## core-two-word-int.pkg
## Author: Matthias Blume (blume@tti-c.org)

# Compiled by:
#     src/lib/core/init/init.cmi

#   Basic (simulated) 64-bit integer support.




###                 "But we are all that way:
###                  when we know a thing
###                  we have only scorn for other people
###                  who don't happen to know it."
###
###                            -- Mark Twain,
###                               Personal Recollections of Joan of Arc



package core_two_word_int {
    #
    stipulate
                                                                                                        # inline        is from   src/lib/compiler/front/semantic/symbolmapstack/base-types-and-ops.pkg
        package cii = core_multiword_int;

        infix my o;                     (o)    = inline::compose;
        infix my 80 * ;                 (*)    = inline::u1_mul;
        infix my 70 + - ;               (+)    = inline::u1_add;                (-)  = inline::u1_subtract;
        infix my 60 << >> >>> ;         (<<)   = inline::u1_lshift;             (>>) = inline::u1_rshiftl;
        infix my 60 & ;                 (&)    = inline::u1_bitwise_and;
        infix my 50 < ;                 (<)    = inline::u1_lt;
        infix my 50 != ;                (!=)   = inline::u1_ne;
        infix my 50 ==== ;              (====) = inline::u1_eq;

        not = inline::not_macro;

        (-_) = inline::u1_negate;
        neg  = inline::u1_negate;
        (^_) = inline::u1_bitwise_not;

        fun lift1' f        =  f o inline::i64p;
        fun lift1  f        =  inline::p64i o lift1' f;

        fun lift2' f (x, y) =  f (inline::i64p x, inline::i64p y);
        fun lift2  f        =  inline::p64i o lift2' f;

        fun neg64 (0ux80000000, 0u0) => raise exception runtime::OVERFLOW;
            neg64 (hi, 0u0) => (-hi, 0u0);
            neg64 (hi, lo) => (^hi, -lo);
        end;

        fun negbit hi =  hi  &  0ux80000000;
        fun isneg hi  =  negbit hi != 0u0;

        fun add64 ((hi1, lo1), (hi2, lo2))
            =
            {   hi =  hi1 + hi2;
                lo =  lo1 + lo2;

                hi = if (lo < lo1)  hi + 0u1;
                     else           hi;
                     fi;

                nb1 = negbit hi1;

                if (nb1 != negbit hi2
                or nb1 ==== negbit hi)
                     (hi, lo);
                else
                     raise exception runtime::OVERFLOW;
                fi;
            };

        fun sub64 ((hi1, lo1), (hi2, lo2))
            =
            {   hi =  hi1 - hi2;
                lo =  lo1 - lo2;

                hi =    if (lo1 < lo)   hi - 0u1;
                        else            hi;
                        fi;

                nb1 = negbit hi1;

               if (nb1 ==== negbit hi2
               or  nb1 ==== negbit hi)
                    (hi, lo);
               else
                    raise exception runtime::OVERFLOW;
               fi;
            };

        # I am definitely too lazy to do
        # this the pedestrian way, so
        # here we go:                                   XXX BUGGO FIXME
        #
        fun mul64 (x, y)
            =
            cii::test_inf64 ((cii::(*)) (cii::extend_inf64 x, cii::extend_inf64 y));

        fun div64 (_, (0u0, 0u0)) => raise exception runtime::DIVIDE_BY_ZERO;
            div64 (x, (0u0, 0u1)) => x;
            div64 (x, (0uxffffffff, 0uxffffffff)) => neg64 x;
            div64 (x, y) =>
               #  Again, the easy way out... 
               cii::trunc_inf64 (cii::div (cii::extend_inf64 x, cii::extend_inf64 y));
        end;

        fun mod64 (x, y)
            =
            sub64 (x, mul64 (div64 (x, y), y));

        fun swap (x, y) = (y, x);

        fun lt64 ((hi1, lo1), (hi2, lo2))
            =
            {   fun normal ()
                    =
                    hi1 < hi2  or  (hi1 ==== hi2  and  lo1 < lo2);

                if (isneg hi1)
                    if (isneg hi2)  normal ();
                    else            TRUE;
                    fi;
                else
                    normal ();
                fi;
            };

        gt64 = lt64 o swap;
        le64 = not o gt64;
        ge64 = not o lt64;

        fun abs64 (hi, lo)
            =
            if (isneg hi)    neg64 (hi, lo);
            else                   (hi, lo);
            fi;

    herein

        extern = inline::i64p;
        intern = inline::p64i;

        neg  = lift1 neg64;

        (-_) = lift1 neg64;
        (+)  = lift2 add64;
        (-)  = lift2 sub64;
        (*)  = lift2 mul64;

        div = lift2 div64;
        mod = lift2 mod64;

        (<) = lift2' lt64;
        <=  = lift2' le64;
        >   = lift2' gt64;
        >=  = lift2' ge64;
        abs = lift1 abs64;
    end;
};


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext