PreviousUpNext

15.4.715  src/lib/core/init/core-two-word-unt.pkg

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

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

#   Basic (simulated) 64-bit word support.



###                    "I don't think there ever was a lazy man in this world.
###
###                    "Every man has some sort of gift, and he prizes that gift
###                     beyond all others. He may be a professional billiard-player,
###                     or a Paderewski, or a poet -- I don't care what it is.
###
###                    "But whatever it is, he takes a native delight in exploiting that gift,
###                     and you will find it is difficult to beguile him away from it.
###
###                    "Well, there are thousands of other interests occupying other men,
###                     but those interests don't appeal to the special tastes of
###                     the billiard champion or Paderewski. They are set down, therefore,
###                     as too lazy to do that or do this -- to do, in short what they have
###                     no taste or inclination to do.
###
###                    "In that sense, then I am phenomenally lazy.
###
###                    "But when it comes to writing a book--I am not lazy.
###                     My family find it difficult to dig me out of my chair."
###
###                                                  -- Mark Twain,
###                                                     quoted in Sydney Morning Herald,
###                                                     9/17/1895



package core_two_word_unt {
    #                                                                                                   # inline        is from   src/lib/compiler/front/semantic/symbolmapstack/base-types-and-ops.pkg
    stipulate

        infix my o;              (o) = inline::compose;

        not = inline::not_macro;

        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;

        fun lift1' f = f o inline::u64p;
        fun lift1 f = inline::p64u o lift1' f;
        fun lift2' f (x, y) = f (inline::u64p x, inline::u64p y);
        fun lift2 f = inline::p64u o lift2' f;

        fun split16 w32
            =
            (w32 >> 0u16, w32 & 0uxffff);

        fun neg64 (hi, 0u0) =>  (inline::u1_negate      hi,  0u0);
            neg64 (hi, lo ) =>  (inline::u1_bitwise_not hi,  inline::u1_negate lo);
        end;

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

                ( lo < lo1   ??    hi + 0u1
                             ::    hi,

                  lo
                );
            };

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

                ( lo1 < lo   ??   hi - 0u1
                             ::   hi,
                  lo
                );
            };

        fun mul64 ((hi1, lo1), (hi2, lo2))
            =
            {   my ((a1, b1), (c1, d1)) = (split16 hi1, split16 lo1);
                my ((a2, b2), (c2, d2)) = (split16 hi2, split16 lo2);
                dd = d1 * d2;
                my (cd, dc) = (c1 * d2, d1 * c2);
                my (bd, cc, db) = (b1 * d2, c1 * c2, d1 * b2);
                my (ad, bc, cb, da) = (a1 * d2, b1 * c2, c1 * b2, d1 * a2);
                diag0 = dd;
                diag1 = cd + dc;
                diag1carry = if (diag1 < cd ) 0ux10000; else 0u0;fi;
                diag2 = bd + cc + db;
                diag3 = ad + bc + cb + da;
                lo = diag0 + (diag1 << 0u16);
                locarry = if (lo < diag0 ) 0u1; else 0u0;fi;
                hi = (diag1 >> 0u16) + diag2 + (diag3 << 0u16)
                         + locarry + diag1carry;
             (hi, lo);
            };

        stipulate

              package cii = core_multiword_int;

              up = cii::copy_inf64;
              dn = cii::trunc_inf64;

        herein

            # This is even more inefficient 
            # than doing it the hard way,
            # but I am lazy...  XXX BUGGO FIXME
            #
            fun div64 (x, y)
                =
                dn (cii::div (up x, up 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))
            =
            hi1 < hi2 or (inline::u1_eq (hi1, hi2) and lo1 < lo2);

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

    herein

        extern = inline::u64p;
        intern = inline::p64u;

        (-_) = lift1 neg64;
        neg  = lift1 neg64;

        (+)  = lift2 add64;
        (-)  = lift2 sub64;
        (*)  = lift2 mul64;
        div  = lift2 div64;

        mod  = lift2 mod64;

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


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext