PreviousUpNext

15.4.1227  src/lib/std/src/two-word-unt.pkg

## two-word-unt.pkg
#
# Two-word unt ("unsigned int") -- 64-bit unt on 32-bit architectures, 128-bit unt on 64-bit architectures.

# Compiled by:
#     src/lib/std/src/standard-core.sublib

#   64-bit word support


###         "I am a Bear of very little brain,
###              and long words bother me."
###
###                         -- Winnie the Pooh


stipulate
    package it  =  inline_t;                            # inline_t              is from   src/lib/core/init/built-in.pkg
    package lms =  list_mergesort;                      # list_mergesort        is from   src/lib/src/list-mergesort.pkg
    package nst =  number_string;                       # number_string         is from   src/lib/std/src/number-string.pkg
    package pb  =  proto_basis;                         # proto_basis           is from   src/lib/std/src/proto-basis.pkg
herein

    package two_word_unt: (weak)  Unt {                 # Unt                   is from   src/lib/std/src/unt.api
        #
        package u1 = one_word_unt_guts;                 # one_word_unt_guts     is from   src/lib/std/src/one-word-unt-guts.pkg

        Unt = two_word_unt::Unt;

        extern = it::u2::extern;
        intern = it::u2::intern;

        unt_size = 64;                          # 64-bit issue: This will be 128 on 64-bit architectures.

        fun unimplemented _
            =
            raise exception DIE "unimplemented";

        to_large_unt   =  unimplemented;                # XXX SUCKO FIXME
        to_large_unt_x =  unimplemented;                # XXX SUCKO FIXME
        from_large_unt =  unimplemented;                # XXX SUCKO FIXME

        to_multiword_int    =  core_multiword_int::copy_inf64   o extern;
        to_multiword_int_x  =  core_multiword_int::extend_inf64 o extern;
        #
        from_multiword_int  =  intern o core_multiword_int::trunc_inf64;

        fun to_int w
            =
            case (extern w)
                #
                (0u0, lo) =>  u1::to_int lo;
                _         =>  raise exception OVERFLOW;
            esac;

        fun to_int_x w = u1::to_int_x (#2 (extern w));
        fun from_int i = intern (if (i < 0 ) 0uxffffffff; else 0u0;fi, u1::from_int i);

        fun bitwise f (w1, w2)
            =
            {   my (hi1, lo1) =  extern w1;
                my (hi2, lo2) =  extern w2;
                #
                intern  (f (hi1, hi2),  f (lo1, lo2));
            };

        bitwise_or  =  bitwise u1::bitwise_or;
        bitwise_xor =  bitwise u1::bitwise_xor;
        bitwise_and =  bitwise u1::bitwise_and;

        fun bitwise_not w
            =
            {   (extern w) -> (hi, lo);
                #
                intern  (u1::bitwise_not hi,  u1::bitwise_not lo);
            };

        fun compare (w1, w2)
            =
            {   (extern w1) ->  (hi1, lo1);
                (extern w2) ->  (hi2, lo2);

                if   (hi1 > hi2)  GREATER;
                elif (hi1 < hi2)  LESS;
                elif (lo1 > lo2)  GREATER;
                elif (lo1 < lo2)  LESS;
                else              EQUAL;
                fi;
            };

        fun (<<) (w64, w)
            =
            if (w >= 0u64  ) 0u0;                                                                       # 64-bit issue.
            elif (w > 0u32 ) intern (u1::(<<) (#2 (extern w64), w - 0u32), 0u0);                        # 64-bit issue.
            elif (w == 0u32) intern (#2 (extern w64), 0u0);                                             # 64-bit issue.
            elif (w == 0u0 ) w64;
            else
                 my (hi, lo) = extern w64;
                 intern (u1::bitwise_or (u1::(<<) (hi, w), u1::(>>) (lo, 0u32 - w)),                    # 64-bit issue.
                           u1::(<<) (lo, w));
            fi;

        fun (>>) (w64, w)
            =
            if   (w >= 0u64)  0u0;
            elif (w > 0u32 )  intern (0u0, u1::(>>) (#1 (extern w64), w - 0u32));                       # 64-bit issue.
            elif (w == 0u32)  intern (0u0, #1 (extern w64));                                            # 64-bit issue.
            elif (w == 0u0 )  w64;
            else  my (hi, lo) = extern w64;
                  intern (u1::(>>) (hi, w),
                            u1::bitwise_or (u1::(>>) (lo, w), u1::(<<) (hi, 0u32 - w)));                # 64-bit issue.
            fi;

        fun (>>>) (w64, w)
            =
            if (w == 0u0)  w64;
            else
                (extern w64) ->  (hi, lo);

                if (w >= 0u63 )                                                                         # 64-bit issue.
                      x = u1::(>>>) (hi, 0u31);                                                         # 64-bit issue.
                      intern (x, x);

                elif (w > 0u32 )                                                                        # 64-bit issue.
                    intern (u1::(>>>) (hi, 0u31), u1::(>>>) (hi, w - 0u32));                            # 64-bit issue.

                elif (w == 0u32 )
                    intern (u1::(>>>) (hi, 0u31), hi);                                                  # 64-bit issue.

                else
                    intern (u1::(>>>) (hi, w),
                             u1::bitwise_or (u1::(>>) (lo, w), u1::(<<) (hi, 0u32 - w)));               # 64-bit issue.
                fi;
            fi;


        fun min (w1: Unt, w2) =  if (w1 > w2) w1; else w2; fi;
        fun max (w1: Unt, w2) =  if (w1 > w2) w1; else w2; fi;

        fun to_string w
            =
            case (extern w)
                #          
                (0u0, lo) => u1::to_string lo;

                (hi, lo) => 
                    { my (hi, lo) = extern w;
                     u1::to_string hi + (nst::pad_left '0' 8 (u1::to_string lo));
                    };
            esac;

        fun format nst::BINARY w
                =>
                case (extern w)
                    #
                    (0u0, lo)
                        =>
                        u1::format nst::BINARY lo;
                    #
                    (hi, lo)
                        => 
                        {   u1bin =  u1::format  nst::BINARY;
                            #
                            u1bin hi + (nst::pad_left '0' 32 (u1bin lo));                       # 64-bit issue.
                        };
                esac;

           format nst::HEX w
               =>
               to_string w;

           format rdx w
                =>
                multiword_int_guts::format rdx (to_multiword_int w);            # Lazy way.
        end;

        # piggy-back on integer... 
        #
        fun scan rdx rdr s
            =
            {   fun doword s
                    =
                    multiword_int_guts::scan  rdx  rdr  s;

                xok =   rdx == nst::HEX;

                fun startscan s0
                    =
                    case (rdr s0)
                        #                  
                        THE ('0', s1)
                            =>
                            {   fun wordor0 s
                                    =
                                    case (doword s)
                                        #
                                        NULL        =>  THE (0, s1);
                                        THE (i, s') =>  THE (i, s');
                                    esac;

                                fun saww s
                                    =
                                    case (rdr s)
                                        #                                 
                                        THE ('x', s')
                                            =>
                                            if xok    wordor0 s';
                                            else      THE (0, s1);
                                            fi;

                                        _ => wordor0 s;
                                    esac;

                                case (rdr s1)
                                    #
                                    THE ('w', s2) =>   saww s2;
                                    #
                                    THE ('x', s2)
                                        =>
                                        if xok  wordor0 s2;
                                        else    THE (0, s1);
                                        fi;

                                    _   => doword s0;
                                esac;
                            };

                        _ => doword s0;
                    esac;

                case (startscan s)
                    #
                    THE (i, s')
                        =>
                        if   (i < 0                 )  NULL;
                        elif (i > 0xffffffffffffffff)  raise exception OVERFLOW;                # 64-bit issue.
                        else                           THE (from_multiword_int i, s');
                        fi;

                    NULL => NULL;
                esac;
            };

        from_string
            =
            pb::scan_string  (scan  nst::HEX);



        my (*)  : (Unt, Unt) -> Unt = (*);
        my (+)  : (Unt, Unt) -> Unt = (+);
        my (-)  : (Unt, Unt) -> Unt = (-);
        my (/)  : (Unt, Unt) -> Unt = (/);
        my (%)  : (Unt, Unt) -> Unt = (%);

        my (-_)  : Unt -> Unt = (-_);

        my (<)  : (Unt, Unt) -> Bool = (<);
        my (<=) : (Unt, Unt) -> Bool = (<=);
        my (>)  : (Unt, Unt) -> Bool = (>);
        my (>=) : (Unt, Unt) -> Bool = (>=);

        fun sum unts
            =
            sum' (unts, 0u0)
            where
                fun sum' (      [], result) =>  result;
                    sum' (u ! rest, result) =>  sum' (rest, u + result);
                end;
            end;

        fun product unts
            =
            product' (unts, 0u1)
            where
                fun product' (      [], result) =>  result;
                    product' (u ! rest, result) =>  product' (rest, u * result);
                end;
            end;

        fun list_min [] =>   raise exception DIE "Cannot do list_min on empty list";
            #
            list_min (u ! unts)
                =>
                min' (unts, u: Unt)
                where
                    fun min' (      [], result) =>  result;
                        min' (u ! rest, result) =>  min'  (rest,  u < result ?? u :: result);
                    end;
                end;
        end;

        fun list_max [] =>   raise exception DIE "Cannot do list_max on empty list";
            #
            list_max (u ! unts)
                =>
                min' (unts, u: Unt)
                where
                    fun min' (      [], result) =>  result;
                        min' (u ! rest, result) =>  min'  (rest,  u > result ?? u :: result);
                    end;
                end;
        end;

        fun sort unts
            =
            lms::sort_list (>) unts;

        fun sort_and_drop_duplicates unts
            =
            lms::sort_list_and_drop_duplicates  compare  unts;
    };
end;


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext