PreviousUpNext

15.4.1016  src/lib/src/tuplebasex.pkg

## tuplebasex.pkg
#
# Just like   src/lib/src/tuplebase.pkg
# except Atom(X) replaces Atom (etc).

# Compiled by:
#     src/lib/std/standard.lib


stipulate
    package im1  =  int_red_black_map;                                          # int_red_black_map                             is from   src/lib/src/int-red-black-map.pkg
    package is1  =  int_red_black_set;                                          # int_red_black_set                             is from   src/lib/src/int-red-black-set.pkg
herein

    package tuplebasex
    :       Tuplebasex                                                          # Tuplebasex                                    is from   src/lib/src/tuplebasex.api
    {
        Atom_Datum(X) = NONE
                      | FLOAT  Float
                      | STRING String
                      | OTHER  X
                      ;

        Atom(X) = { id:         Int,
                    datum:      Atom_Datum(X)
                  };

        Duple(X)  = (Atom(X), Atom(X));
        Triple(X) = (Atom(X), Atom(X), Atom(X));

        fun compare_i2
              ( ( i1a: Int,
                  i1b: Int
                ),
                ( i2a: Int,
                  i2b: Int
                )
              )
            =
            case (int::compare (i1a, i2a))
                #
                GREATER =>  GREATER;
                LESS    =>  LESS;
                EQUAL   =>  int::compare (i1b, i2b);
            esac;

        fun compare_12of2
              ( ( { id => id1a, ... },
                  { id => id1b, ... }
                ):                              Duple(X),
                ( { id => id2a, ... },
                  { id => id2b, ... }
                ):                              Duple(X)
              )
            =
            case (int::compare (id1a, id2a))
                #
                GREATER =>  GREATER;
                LESS    =>  LESS;
                EQUAL   =>  (int::compare (id1b, id2b));
            esac;

        fun compare_12of3
              ( ( { id => id1a, ... },
                  { id => id1b, ... },
                  { id => id1c, ... }
                ):                              Triple(X),
                ( { id => id2a, ... },
                  { id => id2b, ... },
                  { id => id2c, ... }
                ):                              Triple(X)
              )
            =
            case (int::compare (id1a, id2a))
                #
                GREATER =>  GREATER;
                LESS    =>  LESS;
                EQUAL   =>  (int::compare (id1b, id2b));
            esac;

        fun compare_13of3
              ( ( { id => id1a, ... },
                  { id => id1b, ... },
                  { id => id1c, ... }
                ):                              Triple(X),
                ( { id => id2a, ... },
                  { id => id2b, ... },
                  { id => id2c, ... }
                ):                              Triple(X)
              )
            =
            case (int::compare (id1a, id2a))
                #
                GREATER =>  GREATER;
                LESS    =>  LESS;
                EQUAL   =>  (int::compare (id1c, id2c));
            esac;

        fun compare_23of3
              ( ( { id => id1a, ... },
                  { id => id1b, ... },
                  { id => id1c, ... }
                ):                              Triple(X),
                ( { id => id2a, ... },
                  { id => id2b, ... },
                  { id => id2c, ... }
                ):                              Triple(X)
              )
            =
            case (int::compare (id1b, id2b))
                #
                GREATER =>  GREATER;
                LESS    =>  LESS;
                EQUAL   =>  (int::compare (id1c, id2c));
            esac;

        fun compare_123of3
              ( ( { id => id1a, ... },
                  { id => id1b, ... },
                  { id => id1c, ... }
                ):                              Triple(X),
                ( { id => id2a, ... },
                  { id => id2b, ... },
                  { id => id2c, ... }
                ):                              Triple(X)
              )
            =
            case (int::compare (id1a, id2a))
                #
                GREATER =>  GREATER;
                LESS    =>  LESS;
                EQUAL   =>  case (int::compare (id1b, id2b))
                                GREATER =>  GREATER;
                                LESS    =>  LESS;
                                EQUAL   =>  int::compare (id1c, id2c);
                            esac;
            esac;

        fun compare_123of3
              ( ( { id => id1a, ... },
                  { id => id1b, ... },
                  { id => id1c, ... }
                ):                              Triple(X),
                ( { id => id2a, ... },
                  { id => id2b, ... },
                  { id => id2c, ... }
                ):                              Triple(X)
              )
            =
            case (int::compare (id1a, id2a))
                #
                GREATER =>  GREATER;
                LESS    =>  LESS;
                EQUAL   =>  case (int::compare (id1b, id2b))
                                GREATER =>  GREATER;
                                LESS    =>  LESS;
                                EQUAL   =>  int::compare (id1c, id2c);
                            esac;
            esac;

        package im2
            =
            red_black_map_g (
                #
                package {
                    Key = (Int, Int);
                    #
                    compare = compare_i2;
                }
            );

        package ds                                                              # Sets of Duples
            =
            red_black_setx_g (                                                  # red_black_setx_g                              is from   src/lib/src/red-black-setx-g.pkg
                #
                package {
                    Key(X) = Duple(X);
                    #
                    compare = compare_12of2;
                }
            );

        package ts                                                              # Sets of Triples
            =
            red_black_setx_g (                                                  # red_black_setx_g                              is from   src/lib/src/red-black-setx-g.pkg
                #
                package {
                    Key(X) = Triple(X);
                    #
                    compare = compare_123of3;
                }
            );


        Tuplebase(X)
          =
          { index_1of2:         im1::Map( ds::Set(X) ),
            index_2of2:         im1::Map( ds::Set(X) ),
            #
            index_12of2:                  ds::Set(X),
            #
            #
            index_1of3:         im1::Map( ts::Set(X) ),
            index_2of3:         im1::Map( ts::Set(X) ),
            index_3of3:         im1::Map( ts::Set(X) ),
            #
            index_12of3:        im2::Map( ts::Set(X) ),
            index_13of3:        im2::Map( ts::Set(X) ),
            index_23of3:        im2::Map( ts::Set(X) ),
            #
            index_123of3:                 ts::Set(X)
          };


        empty_tuplebase
          =
          { index_1of2   =>     im1::empty:     im1::Map( ds::Set(X) ),
            index_2of2   =>     im1::empty:     im1::Map( ds::Set(X) ),
            #
            index_12of2  =>     ds::empty:                ds::Set(X),
            #
            #
            index_1of3   =>     im1::empty:     im1::Map( ts::Set(X) ),
            index_2of3   =>     im1::empty:     im1::Map( ts::Set(X) ),
            index_3of3   =>     im1::empty:     im1::Map( ts::Set(X) ),
            #
            index_12of3  =>     im2::empty:     im2::Map( ts::Set(X) ),
            index_13of3  =>     im2::empty:     im2::Map( ts::Set(X) ),
            index_23of3  =>     im2::empty:     im2::Map( ts::Set(X) ),
            #
            index_123of3 =>     ts::empty:                ts::Set(X)
          };

        fun  put_duple
              (
                { index_1of2,
                  index_2of2,
                  #
                  index_12of2,
                  #
                  #
                  index_1of3,
                  index_2of3,
                  index_3of3,
                  #
                  index_12of3,
                  index_13of3,
                  index_23of3,
                  #
                  index_123of3
                }:                                                      Tuplebase(X),
                duple as
                ( atom1 as { id => id1, ... },
                  atom2 as { id => id2, ... }
                ):                                                      Duple(X)
              )
            =
            {   index_1of2
                    =
                    case (im1::get (index_1of2, id1))
                        #
                        THE set =>  im1::set (index_1of2, id1, ds::add (set, duple));
                        NULL    =>  im1::set (index_1of2, id1, ds::singleton(duple));
                    esac;

                index_2of2
                    =
                    case (im1::get (index_2of2, id2))
                        #
                        THE set =>  im1::set (index_2of2, id2, ds::add (set, duple));
                        NULL    =>  im1::set (index_2of2, id2, ds::singleton(duple));
                    esac;

                index_12of2
                    =
                    ds::add (index_12of2, duple);

                { index_1of2,
                  index_2of2,
                  #
                  index_12of2,
                  #
                  #
                  index_1of3,
                  index_2of3,
                  index_3of3,
                  #
                  index_12of3,
                  index_13of3,
                  index_23of3,
                  #
                  index_123of3
                }:                                                      Tuplebase(X);
            };

        fun  put_triple
              (
                { index_1of2,
                  index_2of2,
                  #
                  index_12of2,
                  #
                  #
                  index_1of3,
                  index_2of3,
                  index_3of3,
                  #
                  index_12of3,
                  index_13of3,
                  index_23of3,
                  #
                  index_123of3
                }:                                                      Tuplebase(X),
                triple as
                ( atom1 as { id => id1, ... },
                  atom2 as { id => id2, ... },
                  atom3 as { id => id3, ... }
                ):                                                      Triple(X)
              )
            =
            {   index_1of3
                    =
                    case (im1::get (index_1of3, id1))
                        #
                        THE set =>  im1::set (index_1of3, id1, ts::add (set, triple));
                        NULL    =>  im1::set (index_1of3, id1, ts::singleton(triple));
                    esac;

                index_2of3
                    =
                    case (im1::get (index_2of3, id2))
                        #
                        THE set =>  im1::set (index_2of3, id2, ts::add (set, triple));
                        NULL    =>  im1::set (index_2of3, id2, ts::singleton(triple));
                    esac;

                index_3of3
                    =
                    case (im1::get (index_3of3, id3))
                        #
                        THE set =>  im1::set (index_3of3, id3, ts::add (set, triple));
                        NULL    =>  im1::set (index_3of3, id3, ts::singleton(triple));
                    esac;


                index_12of3
                    =
                    case (im2::get (index_12of3, (id1, id2)))
                        #
                        THE set =>  im2::set (index_12of3, (id1, id2), ts::add (set, triple));
                        NULL    =>  im2::set (index_12of3, (id1, id2), ts::singleton(triple));
                    esac;

                index_13of3
                    =
                    case (im2::get (index_13of3, (id1, id3)))
                        #
                        THE set =>  im2::set (index_13of3, (id1, id3), ts::add (set, triple));
                        NULL    =>  im2::set (index_13of3, (id1, id3), ts::singleton(triple));
                    esac;

                index_23of3
                    =
                    case (im2::get (index_23of3, (id2, id3)))
                        #
                        THE set =>  im2::set (index_23of3, (id2, id3), ts::add (set, triple));
                        NULL    =>  im2::set (index_23of3, (id2, id3), ts::singleton(triple));
                    esac;


                index_123of3
                    =
                    ts::add (index_123of3, triple);


                { index_1of2,
                  index_2of2,
                  #
                  index_12of2,
                  #
                  #
                  index_1of3,
                  index_2of3,
                  index_3of3,
                  #
                  index_12of3,
                  index_13of3,
                  index_23of3,
                  #
                  index_123of3
                }:                                                      Tuplebase(X);
            };


        fun  drop_duple
              (
                { index_1of2,
                  index_2of2,
                  #
                  index_12of2,
                  #
                  #
                  index_1of3,
                  index_2of3,
                  index_3of3,
                  #
                  index_12of3,
                  index_13of3,
                  index_23of3,
                  #
                  index_123of3
                }:                                                      Tuplebase(X),
                duple as
                ( atom1 as { id => id1, ... },
                  atom2 as { id => id2, ... }
                ):                                                      Duple(X)
              )
            =
            {   index_1of2
                    =
                    case (im1::get (index_1of2, id1))
                        #
                        THE set =>  if (ds::vals_count(set) > 1)  im1::set  (index_1of2, id1, ds::drop (set, duple));
                                    else                          im1::drop (index_1of2, id1);
                                    fi;
                        NULL    =>  index_1of2;                 # Duple isn't in tuplebase. Possibly we should raise an exception here.
                    esac;

                index_2of2
                    =
                    case (im1::get (index_2of2, id2))
                        #
                        THE set =>  if (ds::vals_count(set) > 1)  im1::set  (index_2of2, id2, ds::drop (set, duple));
                                    else                          im1::drop (index_1of2, id2);
                                    fi;
                        NULL    =>  index_2of2;                 # Duple isn't in tuplebase. Possibly we should raise an exception here.
                    esac;


                index_12of2
                    =
                    ds::drop (index_12of2, duple);


                { index_1of2,
                  index_2of2,
                  #
                  index_12of2,
                  #
                  #
                  index_1of3,
                  index_2of3,
                  index_3of3,
                  #
                  index_12of3,
                  index_13of3,
                  index_23of3,
                  #
                  index_123of3
                }:                                                      Tuplebase(X);
            };

        fun  drop_triple
              (
                { index_1of2,
                  index_2of2,
                  #
                  index_12of2,
                  #
                  #
                  index_1of3,
                  index_2of3,
                  index_3of3,
                  #
                  index_12of3,
                  index_13of3,
                  index_23of3,
                  #
                  index_123of3
                }:                                                      Tuplebase(X),
                triple as
                ( atom1 as { id => id1, ... },
                  atom2 as { id => id2, ... },
                  atom3 as { id => id3, ... }
                ):                                                      Triple(X)
              )
            =
            {   index_1of3
                    =
                    case (im1::get (index_1of3, id1))
                        #
                        THE set =>  if (ts::vals_count(set) > 1)  im1::set  (index_1of3, id1, ts::drop (set, triple));
                                    else                          im1::drop (index_1of3, id1);
                                    fi;
                        NULL    =>  index_1of3;                 # Triple isn't in tuplebase. Possibly we should raise an exception here.
                    esac;

                index_2of3
                    =
                    case (im1::get (index_2of3, id2))
                        #
                        THE set =>  if (ts::vals_count(set) > 1)  im1::set  (index_2of3, id2, ts::drop (set, triple));
                                    else                          im1::drop (index_2of3, id2);
                                    fi;
                        NULL    =>  index_2of3;                 # Triple isn't in tuplebase. Possibly we should raise an exception here.
                    esac;

                index_3of3
                    =
                    case (im1::get (index_3of3, id3))
                        #
                        THE set =>  if (ts::vals_count(set) > 1)  im1::set  (index_3of3, id3, ts::drop (set, triple));
                                    else                          im1::drop (index_3of3, id3);
                                    fi;
                        NULL    =>  index_3of3;                 # Triple isn't in tuplebase. Possibly we should raise an exception here.
                    esac;


                index_12of3
                    =
                    case (im2::get (index_12of3, (id1, id2)))
                        #
                        THE set =>  if (ts::vals_count(set) > 1)  im2::set  (index_12of3, (id1, id2), ts::drop (set, triple));
                                    else                          im2::drop (index_12of3, (id1, id2));
                                    fi;
                        NULL    =>  index_12of3;                # Triple isn't in tuplebase. Possibly we should raise an exception here.
                    esac;

                index_13of3
                    =
                    case (im2::get (index_13of3, (id1, id3)))
                        #
                        THE set =>  if (ts::vals_count(set) > 1)  im2::set  (index_13of3, (id1, id3), ts::drop (set, triple));
                                    else                          im2::drop (index_13of3, (id1, id3));
                                    fi;
                        NULL    =>  index_13of3;                # Triple isn't in tuplebase. Possibly we should raise an exception here.
                    esac;

                index_23of3
                    =
                    case (im2::get (index_23of3, (id2, id3)))
                        #
                        THE set =>  if (ts::vals_count(set) > 1)  im2::set  (index_23of3, (id2, id3), ts::drop (set, triple));
                                    else                          im2::drop (index_23of3, (id2, id3));
                                    fi;
                        NULL    =>  index_23of3;                # Triple isn't in tuplebase. Possibly we should raise an exception here.
                    esac;



                index_123of3
                    =
                    ts::drop (index_123of3, triple);


                { index_1of2,
                  index_2of2,
                  #
                  index_12of2,
                  #
                  #
                  index_1of3,
                  index_2of3,
                  index_3of3,
                  #
                  index_12of3,
                  index_13of3,
                  index_23of3,
                  #
                  index_123of3
                }:                                                      Tuplebase(X);
            };


        fun get_duples    (t: Tuplebase(X))                   =              t.index_12of2;
        #
        fun get_duples1   (t: Tuplebase(X), a: Atom(X))          =  im1::get   (t.index_1of2, a.id);
        fun get_duples2   (t: Tuplebase(X), a: Atom(X))          =  im1::get   (t.index_2of2, a.id);
        #
        fun has_duple     (t: Tuplebase(X), d: Duple(X))         =  ds::member (t.index_12of2, d);

        fun get_triples   (t: Tuplebase(X))                   =              t.index_123of3;
        #
        fun get_triples1  (t: Tuplebase(X), a: Atom(X))          =  im1::get   (t.index_1of3, a.id);
        fun get_triples2  (t: Tuplebase(X), a: Atom(X))          =  im1::get   (t.index_2of3, a.id);
        fun get_triples3  (t: Tuplebase(X), a: Atom(X))          =  im1::get   (t.index_3of3, a.id);
        #
        fun get_triples12 (t: Tuplebase(X), a: Atom(X), b: Atom(X)) =  im2::get   (t.index_12of3, (a.id, b.id));
        fun get_triples13 (t: Tuplebase(X), a: Atom(X), c: Atom(X)) =  im2::get   (t.index_13of3, (a.id, c.id));
        fun get_triples23 (t: Tuplebase(X), b: Atom(X), c: Atom(X)) =  im2::get   (t.index_23of3, (b.id, c.id));
        #
        fun has_triple    (t: Tuplebase(X), d: Triple(X))        =  ts::member (t.index_123of3, d);


        fun make_atom ()
            =
            { id    =>  id_to_int (issue_unique_id ()),
              datum =>  NONE
            };

        fun make_string_atom (s: String)
            =
            { id    =>  id_to_int (issue_unique_id ()),
              datum =>  STRING s
            };

        fun make_float_atom (f: Float)
            =
            { id    =>  id_to_int (issue_unique_id ()),
              datum =>  FLOAT f
            };

        fun make_other_atom (x: X)
            =
            { id    =>  id_to_int (issue_unique_id ()),
              datum =>  OTHER x
            };

        fun string_of ({ id, datum => STRING s }: Atom(X)) =>  THE s;
            string_of _                                    =>  NULL;
        end;

        fun float_of  ({ id, datum => FLOAT  f }: Atom(X)) =>  THE f;
            float_of  _                                    =>  NULL;
        end;

        fun other_of  ({ id, datum => OTHER  x }: Atom(X)) =>  THE x;
            other_of  _                                    =>  NULL;
        end;

        fun atoms_apply                                                         # Apply do_atom to all Atoms in Tuplebase. 
              ( { index_12of2,
                  index_123of3,
                  ...
                }:      Tuplebase(X)
              )
              (do_atom: Atom(X) -> Void)
            =
            {   ds::apply  do_duple   index_12of2;
                ts::apply  do_triple  index_123of3;
            }
            where
                already_seen =  REF is1::empty;
                #
                fun do_duple ((a1, a2): Duple(X))
                    =
                    {
                        if (not (is1::member (*already_seen, a1.id)))
                            #
                            already_seen :=  is1::add (*already_seen, a1.id);

                            do_atom  a1;
                        fi;

                        if (not (is1::member (*already_seen, a2.id)))
                            #
                            already_seen :=  is1::add (*already_seen, a2.id);

                            do_atom  a2;
                        fi;
                    };


                fun do_triple ((a1, a2, a3): Triple(X))
                    =
                    {
                        if (not (is1::member (*already_seen, a1.id)))
                            #
                            already_seen :=  is1::add (*already_seen, a1.id);

                            do_atom  a1;
                        fi;

                        if (not (is1::member (*already_seen, a2.id)))
                            #
                            already_seen :=  is1::add (*already_seen, a2.id);

                            do_atom  a2;
                        fi;

                        if (not (is1::member (*already_seen, a3.id)))
                            #
                            already_seen :=  is1::add (*already_seen, a3.id);

                            do_atom  a3;
                        fi;
                    };
            end;

    };
end;





Comments and suggestions to: bugs@mythryl.org

PreviousUpNext