34
   35:- module(rbtrees,
   36          [ rb_new/1,                      37            rb_empty/1,                    38            rb_lookup/3,                   39            rb_update/4,                   40            rb_update/5,                   41            rb_apply/4,                    42            rb_insert/4,                   43            rb_insert_new/4,               44            rb_delete/3,                   45            rb_delete/4,                   46            rb_visit/2,                    47            rb_keys/2,                     48            rb_map/2,                      49            rb_map/3,                      50            rb_partial_map/4,              51            rb_fold/4,                     52            rb_clone/3,                    53            rb_min/3,                      54            rb_max/3,                      55            rb_del_min/4,                  56            rb_del_max/4,                  57            rb_next/4,                     58            rb_previous/4,                 59            list_to_rbtree/2,              60            ord_list_to_rbtree/2,          61            is_rbtree/1,                   62            rb_size/2,                     63            rb_in/3                        64          ]).   65:- autoload(library(error), [domain_error/2]).   66
  101
  107
  112
  113:- meta_predicate
  114    rb_map(+,2,-),
  115    rb_map(?,1),
  116    rb_partial_map(+,+,2,-),
  117    rb_apply(+,+,2,-),
  118    rb_fold(3,+,+,-).  119
  142
  148
  149:- det(rb_new/1).  150rb_new(t(Nil,Nil)) :-
  151    Nil = black('',_,_,'').
  152
  156
  157rb_empty(t(Nil,Nil)) :-
  158    Nil = black('',_,_,'').
  159
  168
  169rb_lookup(Key, Val, t(_,Tree)) =>
  170    lookup(Key, Val, Tree).
  171
  172lookup(_Key, _Val, black('',_,_,'')) => fail.
  173lookup(Key, Val, Tree) =>
  174    arg(2,Tree,KA),
  175    compare(Cmp,KA,Key),
  176    lookup(Cmp,Key,Val,Tree).
  177
  178lookup(>, K, V, Tree) :-
  179    arg(1,Tree,NTree),
  180    lookup(K, V, NTree).
  181lookup(<, K, V, Tree) :-
  182    arg(4,Tree,NTree),
  183    lookup(K, V, NTree).
  184lookup(=, _, V, Tree) :-
  185    arg(3,Tree,V).
  186
  190
  191rb_min(t(_,Tree), Key, Val) =>
  192    min(Tree, Key, Val).
  193
  194min(red(black('',_,_,_),Key0,Val0,_), Key, Val) => Key0=Key, Val0=Val.
  195min(black(black('',_,_,_),Key0,Val0,_), Key, Val) => Key0=Key, Val0=Val.
  196min(red(Right,_,_,_), Key, Val) =>
  197    min(Right,Key,Val).
  198min(black(Right,_,_,_), Key, Val) =>
  199    min(Right,Key,Val).
  200min('', _Key, _Val) => fail.
  201
  205
  206rb_max(t(_,Tree), Key, Val) =>
  207    max(Tree, Key, Val).
  208
  209max(red(_,Key0,Val0,black('',_,_,_)), Key, Val) => Key0=Key, Val0=Val.
  210max(black(_,Key0,Val0,black('',_,_,_)), Key, Val) =>Key0=Key, Val0=Val.
  211max(red(_,_,_,Left), Key, Val) =>
  212    max(Left,Key,Val).
  213max(black(_,_,_,Left), Key, Val) =>
  214    max(Left,Key,Val).
  215max('', _Key, _Val) => fail.
  216
  221
  222rb_next(t(_,Tree), Key, Next, Val) =>
  223    next(Tree, Key, Next, Val, []).
  224
  225next(black('',_,_,''), _, _, _, _) => fail.
  226next(Tree, Key, Next, Val, Candidate) =>
  227    arg(2,Tree,KA),
  228    arg(3,Tree,VA),
  229    compare(Cmp,KA,Key),
  230    next(Cmp, Key, KA, VA, Next, Val, Tree, Candidate).
  231
  232next(>, K, KA, VA, NK, V, Tree, _) :-
  233    arg(1,Tree,NTree),
  234    next(NTree,K,NK,V,KA-VA).
  235next(<, K, _, _, NK, V, Tree, Candidate) :-
  236    arg(4,Tree,NTree),
  237    next(NTree,K,NK,V,Candidate).
  238next(=, _, _, _, NK, Val, Tree, Candidate) :-
  239    arg(4,Tree,NTree),
  240    (   min(NTree, NK, Val)
  241    ->  true
  242    ;   Candidate = (NK-Val)
  243    ).
  244
  250
  251rb_previous(t(_,Tree), Key, Previous, Val) =>
  252    previous(Tree, Key, Previous, Val, []).
  253
  254previous(black('',_,_,''), _, _, _, _) => fail.
  255previous(Tree, Key, Previous, Val, Candidate) =>
  256    arg(2,Tree,KA),
  257    arg(3,Tree,VA),
  258    compare(Cmp,KA,Key),
  259    previous(Cmp, Key, KA, VA, Previous, Val, Tree, Candidate).
  260
  261previous(>, K, _, _, NK, V, Tree, Candidate) :-
  262    arg(1,Tree,NTree),
  263    previous(NTree,K,NK,V,Candidate).
  264previous(<, K, KA, VA, NK, V, Tree, _) :-
  265    arg(4,Tree,NTree),
  266    previous(NTree,K,NK,V,KA-VA).
  267previous(=, _, _, _, K, Val, Tree, Candidate) :-
  268    arg(1,Tree,NTree),
  269    (   max(NTree, K, Val)
  270    ->  true
  271    ;   Candidate = (K-Val)
  272    ).
  273
  282
  283rb_update(t(Nil,OldTree), Key, OldVal, Val, NewTree2) =>
  284    NewTree2 = t(Nil,NewTree),
  285    update(OldTree, Key, OldVal, Val, NewTree).
  286
  291
  292rb_update(t(Nil,OldTree), Key, Val, NewTree2) =>
  293    NewTree2 = t(Nil,NewTree),
  294    update(OldTree, Key, _, Val, NewTree).
  295
  296update(black(Left,Key0,Val0,Right), Key, OldVal, Val, NewTree) :-
  297    Left \= [],
  298    compare(Cmp,Key0,Key),
  299    (   Cmp == (=)
  300    ->  OldVal = Val0,
  301        NewTree = black(Left,Key0,Val,Right)
  302    ;   Cmp == (>)
  303    ->  NewTree = black(NewLeft,Key0,Val0,Right),
  304        update(Left, Key, OldVal, Val, NewLeft)
  305    ;   NewTree = black(Left,Key0,Val0,NewRight),
  306        update(Right, Key, OldVal, Val, NewRight)
  307    ).
  308update(red(Left,Key0,Val0,Right), Key, OldVal, Val, NewTree) :-
  309    compare(Cmp,Key0,Key),
  310    (   Cmp == (=)
  311    ->  OldVal = Val0,
  312        NewTree = red(Left,Key0,Val,Right)
  313    ;   Cmp == (>)
  314    ->  NewTree = red(NewLeft,Key0,Val0,Right),
  315        update(Left, Key, OldVal, Val, NewLeft)
  316    ;   NewTree = red(Left,Key0,Val0,NewRight),
  317        update(Right, Key, OldVal, Val, NewRight)
  318    ).
  319
  326
  327rb_apply(t(Nil,OldTree), Key, Goal, NewTree2) =>
  328    NewTree2 = t(Nil,NewTree),
  329    apply(OldTree, Key, Goal, NewTree).
  330
  331:- meta_predicate apply(+,?,2,-).  333apply(black(Left,Key0,Val0,Right), Key, Goal,
  334      black(NewLeft,Key0,Val,NewRight)) :-
  335    Left \= [],
  336    compare(Cmp,Key0,Key),
  337    (   Cmp == (=)
  338    ->  NewLeft = Left,
  339        NewRight = Right,
  340        call(Goal,Val0,Val)
  341    ;   Cmp == (>)
  342    ->  NewRight = Right,
  343        Val = Val0,
  344        apply(Left, Key, Goal, NewLeft)
  345    ;   NewLeft = Left,
  346        Val = Val0,
  347        apply(Right, Key, Goal, NewRight)
  348    ).
  349apply(red(Left,Key0,Val0,Right), Key, Goal,
  350      red(NewLeft,Key0,Val,NewRight)) :-
  351    compare(Cmp,Key0,Key),
  352    (   Cmp == (=)
  353    ->  NewLeft = Left,
  354        NewRight = Right,
  355        call(Goal,Val0,Val)
  356    ;   Cmp == (>)
  357    ->  NewRight = Right,
  358        Val = Val0,
  359        apply(Left, Key, Goal, NewLeft)
  360    ;   NewLeft = Left,
  361        Val = Val0,
  362        apply(Right, Key, Goal, NewRight)
  363    ).
  364
  374
  375rb_in(Key, Val, t(_,T)) =>
  376    enum(Key, Val, T).
  377
  378enum(Key, Val, black(L,K,V,R)) =>
  379    L \= '',
  380    enum_cases(Key, Val, L, K, V, R).
  381enum(Key, Val, red(L,K,V,R)) =>
  382    enum_cases(Key, Val, L, K, V, R).
  383enum(_Key, _Val, _Tree) => fail.
  384
  385enum_cases(Key, Val, L, _, _, _) :-
  386    enum(Key, Val, L).
  387enum_cases(Key, Val, _, Key, Val, _).
  388enum_cases(Key, Val, _, _, _, R) :-
  389    enum(Key, Val, R).
  390
  391
  392
  393                   396
  398
  406
  407:- det(rb_insert/4).  408rb_insert(t(Nil,Tree0),Key,Val,NewTree) =>
  409    NewTree = t(Nil,Tree),
  410    insert(Tree0,Key,Val,Nil,Tree).
  411
  412
  413insert(Tree0,Key,Val,Nil,Tree) :-
  414    insert2(Tree0,Key,Val,Nil,TreeI,_),
  415    fix_root(TreeI,Tree).
  416
  434
  435
  436
  440insert2(black('',_,_,''), K, V, Nil, T, Status) =>
  441    T = red(Nil,K,V,Nil),
  442    Status = not_done.
  443insert2(red(L,K0,V0,R), K, V, Nil, NT, Flag) =>
  444    (   K @< K0
  445    ->  NT = red(NL,K0,V0,R),
  446        insert2(L, K, V, Nil, NL, Flag)
  447    ;   K == K0
  448    ->  NT = red(L,K0,V,R),
  449        Flag = done
  450    ;   NT = red(L,K0,V0,NR),
  451        insert2(R, K, V, Nil, NR, Flag)
  452    ).
  453insert2(black(L,K0,V0,R), K, V, Nil, NT, Flag) =>
  454    (   K @< K0
  455    ->  insert2(L, K, V, Nil, IL, Flag0),
  456        fix_left(Flag0, black(IL,K0,V0,R), NT, Flag)
  457    ;   K == K0
  458    ->  NT = black(L,K0,V,R),
  459        Flag = done
  460    ;   insert2(R, K, V, Nil, IR, Flag0),
  461        fix_right(Flag0, black(L,K0,V0,IR), NT, Flag)
  462    ).
  463
  465
  472
  473rb_insert_new(t(Nil,Tree0),Key,Val,NewTree) =>
  474    NewTree = t(Nil,Tree),
  475    insert_new(Tree0,Key,Val,Nil,Tree).
  476
  477insert_new(Tree0,Key,Val,Nil,Tree) :-
  478    insert_new_2(Tree0,Key,Val,Nil,TreeI,_),
  479    fix_root(TreeI,Tree).
  480
  484insert_new_2(black('',_,_,''), K, V, Nil, T, Status) =>
  485    T = red(Nil,K,V,Nil),
  486    Status = not_done.
  487insert_new_2(red(L,K0,V0,R), K, V, Nil, NT, Flag) =>
  488    (   K @< K0
  489    ->  NT = red(NL,K0,V0,R),
  490        insert_new_2(L, K, V, Nil, NL, Flag)
  491    ;   K == K0
  492    ->  fail
  493    ;   NT = red(L,K0,V0,NR),
  494        insert_new_2(R, K, V, Nil, NR, Flag)
  495    ).
  496insert_new_2(black(L,K0,V0,R), K, V, Nil, NT, Flag) =>
  497    (   K @< K0
  498    ->  insert_new_2(L, K, V, Nil, IL, Flag0),
  499        fix_left(Flag0, black(IL,K0,V0,R), NT, Flag)
  500    ;   K == K0
  501    ->  fail
  502    ;   insert_new_2(R, K, V, Nil, IR, Flag0),
  503        fix_right(Flag0, black(L,K0,V0,IR), NT, Flag)
  504    ).
  505
  509:- det(fix_root/2).  510fix_root(black(L,K,V,R), Root) => Root = black(L,K,V,R).
  511fix_root(red(L,K,V,R), Root) => Root = black(L,K,V,R).
  512
  516:- det(fix_left/4).  517fix_left(done,T0,T,Done) => T = T0, Done = done.
  518fix_left(not_done,Tmp,Final,Done) =>
  519    fix_left(Tmp,Final,Done).
  520
  521:- det(fix_left/3).  525fix_left(black(red(Al,AK,AV,red(Be,BK,BV,Ga)),KC,VC,red(De,KD,VD,Ep)),
  526        red(black(Al,AK,AV,red(Be,BK,BV,Ga)),KC,VC,black(De,KD,VD,Ep)),
  527        not_done) :- !.
  528fix_left(black(red(red(Al,KA,VA,Be),KB,VB,Ga),KC,VC,red(De,KD,VD,Ep)),
  529        red(black(red(Al,KA,VA,Be),KB,VB,Ga),KC,VC,black(De,KD,VD,Ep)),
  530        not_done) :- !.
  534fix_left(black(red(Al,KA,VA,red(Be,KB,VB,Ga)),KC,VC,De),
  535        black(red(Al,KA,VA,Be),KB,VB,red(Ga,KC,VC,De)),
  536        done) :- !.
  540fix_left(black(red(red(Al,KA,VA,Be),KB,VB,Ga),KC,VC,De),
  541        black(red(Al,KA,VA,Be),KB,VB,red(Ga,KC,VC,De)),
  542        done) :- !.
  546fix_left(T,T,done).
  547
  551:- det(fix_right/4).  552fix_right(done,T0,T,Done) => T0 = T, Done = done.
  553fix_right(not_done,Tmp,Final,Done) =>
  554    fix_right(Tmp,Final,Done).
  555
  556:- det(fix_right/3).  560fix_right(black(red(Ep,KD,VD,De),KC,VC,red(red(Ga,KB,VB,Be),KA,VA,Al)),
  561          red(black(Ep,KD,VD,De),KC,VC,black(red(Ga,KB,VB,Be),KA,VA,Al)),
  562          not_done) :- !.
  563fix_right(black(red(Ep,KD,VD,De),KC,VC,red(Ga,Ka,Va,red(Be,KB,VB,Al))),
  564          red(black(Ep,KD,VD,De),KC,VC,black(Ga,Ka,Va,red(Be,KB,VB,Al))),
  565          not_done) :- !.
  569fix_right(black(De,KC,VC,red(red(Ga,KB,VB,Be),KA,VA,Al)),
  570          black(red(De,KC,VC,Ga),KB,VB,red(Be,KA,VA,Al)),
  571          done) :- !.
  575fix_right(black(De,KC,VC,red(Ga,KB,VB,red(Be,KA,VA,Al))),
  576          black(red(De,KC,VC,Ga),KB,VB,red(Be,KA,VA,Al)),
  577          done) :- !.
  581fix_right(T,T,done).
  582
  583
  591
  592rb_delete(t(Nil,T), K, NewTree) =>
  593    NewTree = t(Nil,NT),
  594    delete(T, K, _, NT, _).
  595
  600
  601rb_delete(t(Nil,T), K, V, NewTree) =>
  602    NewTree = t(Nil,NT),
  603    delete(T, K, V0, NT, _),
  604    V = V0.
  605
  609delete(red(L,K0,V0,R), K, V, NT, Flag) =>
  610    delete_red(L,K0,V0,R, K, V, NT, Flag).
  611delete(black(L,K0,V0,R), K, V, NT, Flag) =>
  612    delete_black(L,K0,V0,R, K, V, NT, Flag).
  613delete('', _K, _V, _NT, _Flag) =>
  614    fail.
  615
  616delete_red(L,K0,V0,R, K, V, NT, Flag), K @< K0 =>
  617    delete(L, K, V, NL, Flag0),
  618    fixup_left(Flag0,red(NL,K0,V0,R),NT, Flag).
  619delete_red(L,K0,V0,R, K, V, NT, Flag), K @> K0 =>
  620    delete(R, K, V, NR, Flag0),
  621    fixup_right(Flag0,red(L,K0,V0,NR),NT, Flag).
  622delete_red(L,_,V0,R, _, V, Out, Flag) =>   623    V0 = V,
  624    delete_red_node(L,R,Out,Flag).
  625
  626delete_black(L,K0,V0,R, K, V, NT, Flag), K @< K0 =>
  627    delete(L, K, V, NL, Flag0),
  628    fixup_left(Flag0,black(NL,K0,V0,R),NT, Flag).
  629delete_black(L,K0,V0,R, K, V, NT, Flag), K @> K0 =>
  630    delete(R, K, V, NR, Flag0),
  631    fixup_right(Flag0,black(L,K0,V0,NR),NT, Flag).
  632delete_black(L,_,V0,R, _, V, Out, Flag) =>   633    V0 = V,
  634    delete_black_node(L,R,Out,Flag).
  635
  641
  642rb_del_min(t(Nil,T), K, Val, NewTree) =>
  643    NewTree = t(Nil,NT),
  644    del_min(T, K, Val, Nil, NT, _).
  645
  646del_min(red(black('',_,_,_),K,V,R), K, V, Nil, Out, Flag) :-
  647    !,
  648    delete_red_node(Nil,R,Out,Flag).
  649del_min(red(L,K0,V0,R), K, V, Nil, NT, Flag) :-
  650    del_min(L, K, V, Nil, NL, Flag0),
  651    fixup_left(Flag0,red(NL,K0,V0,R), NT, Flag).
  652del_min(black(black('',_,_,_),K,V,R), K, V, Nil, Out, Flag) :-
  653    !,
  654    delete_black_node(Nil,R,Out,Flag).
  655del_min(black(L,K0,V0,R), K, V, Nil, NT, Flag) :-
  656    del_min(L, K, V, Nil, NL, Flag0),
  657    fixup_left(Flag0,black(NL,K0,V0,R),NT, Flag).
  658
  659
  665
  666rb_del_max(t(Nil,T), K, Val, NewTree) =>
  667    NewTree = t(Nil,NT),
  668    del_max(T, K, Val, Nil, NT, _).
  669
  670del_max(red(L,K,V,black('',_,_,_)), K, V, Nil, Out, Flag) :-
  671    !,
  672    delete_red_node(L,Nil,Out,Flag).
  673del_max(red(L,K0,V0,R), K, V, Nil, NT, Flag) :-
  674    del_max(R, K, V, Nil, NR, Flag0),
  675    fixup_right(Flag0,red(L,K0,V0,NR),NT, Flag).
  676del_max(black(L,K,V,black('',_,_,_)), K, V, Nil, Out, Flag) :-
  677    !,
  678    delete_black_node(L,Nil,Out,Flag).
  679del_max(black(L,K0,V0,R), K, V, Nil, NT, Flag) :-
  680    del_max(R, K, V, Nil, NR, Flag0),
  681    fixup_right(Flag0,black(L,K0,V0,NR), NT, Flag).
  682
  683delete_red_node(L1,L2,L1,done) :- L1 == L2, !.
  684delete_red_node(black('',_,_,''),R,R,done) :-  !.
  685delete_red_node(L,black('',_,_,''),L,done) :-  !.
  686delete_red_node(L,R,Out,Done) :-
  687    delete_next(R,NK,NV,NR,Done0),
  688    fixup_right(Done0,red(L,NK,NV,NR),Out,Done).
  689
  690delete_black_node(L1,L2,L1,not_done) :-         L1 == L2, !.
  691delete_black_node(black('',_,_,''),red(L,K,V,R),black(L,K,V,R),done) :- !.
  692delete_black_node(black('',_,_,''),R,R,not_done) :- !.
  693delete_black_node(red(L,K,V,R),black('',_,_,''),black(L,K,V,R),done) :- !.
  694delete_black_node(L,black('',_,_,''),L,not_done) :- !.
  695delete_black_node(L,R,Out,Done) :-
  696    delete_next(R,NK,NV,NR,Done0),
  697    fixup_right(Done0,black(L,NK,NV,NR),Out,Done).
  698
  699delete_next(red(black('',_,_,''),K,V,R),K,V,R,done) :-  !.
  700delete_next(black(black('',_,_,''),K,V,red(L1,K1,V1,R1)),
  701        K,V,black(L1,K1,V1,R1),done) :- !.
  702delete_next(black(black('',_,_,''),K,V,R),K,V,R,not_done) :- !.
  703delete_next(red(L,K,V,R),K0,V0,Out,Done) :-
  704    delete_next(L,K0,V0,NL,Done0),
  705    fixup_left(Done0,red(NL,K,V,R),Out,Done).
  706delete_next(black(L,K,V,R),K0,V0,Out,Done) :-
  707    delete_next(L,K0,V0,NL,Done0),
  708    fixup_left(Done0,black(NL,K,V,R),Out,Done).
  709
  710fixup_left(done,T,T,done).
  711fixup_left(not_done,T,NT,Done) :-
  712    fixup2(T,NT,Done).
  713
  718fixup2(black(black(Al,KA,VA,Be),KB,VB,
  719             red(black(Ga,KC,VC,De),KD,VD,
  720                 black(Ep,KE,VE,Fi))),
  721        black(T1,KD,VD,black(Ep,KE,VE,Fi)),done) :-
  722    !,
  723    fixup2(red(black(Al,KA,VA,Be),KB,VB,black(Ga,KC,VC,De)),
  724            T1,
  725            _).
  729fixup2(red(black(Al,KA,VA,Be),KB,VB,
  730           black(black(Ga,KC,VC,De),KD,VD,
  731                 black(Ep,KE,VE,Fi))),
  732        black(black(Al,KA,VA,Be),KB,VB,
  733              red(black(Ga,KC,VC,De),KD,VD,
  734                  black(Ep,KE,VE,Fi))),done) :- !.
  735fixup2(black(black(Al,KA,VA,Be),KB,VB,
  736             black(black(Ga,KC,VC,De),KD,VD,
  737                   black(Ep,KE,VE,Fi))),
  738        black(black(Al,KA,VA,Be),KB,VB,
  739              red(black(Ga,KC,VC,De),KD,VD,
  740                  black(Ep,KE,VE,Fi))),not_done) :- !.
  744fixup2(red(black(Al,KA,VA,Be),KB,VB,
  745           black(red(Ga,KC,VC,De),KD,VD,
  746                 black(Ep,KE,VE,Fi))),
  747        red(black(black(Al,KA,VA,Be),KB,VB,Ga),KC,VC,
  748            black(De,KD,VD,black(Ep,KE,VE,Fi))),
  749        done) :- !.
  750fixup2(black(black(Al,KA,VA,Be),KB,VB,
  751             black(red(Ga,KC,VC,De),KD,VD,
  752                   black(Ep,KE,VE,Fi))),
  753        black(black(black(Al,KA,VA,Be),KB,VB,Ga),KC,VC,
  754              black(De,KD,VD,black(Ep,KE,VE,Fi))),
  755        done) :- !.
  759fixup2(red(black(Al,KA,VA,Be),KB,VB,
  760           black(C,KD,VD,red(Ep,KE,VE,Fi))),
  761        red(black(black(Al,KA,VA,Be),KB,VB,C),KD,VD,
  762            black(Ep,KE,VE,Fi)),
  763        done).
  764fixup2(black(black(Al,KA,VA,Be),KB,VB,
  765             black(C,KD,VD,red(Ep,KE,VE,Fi))),
  766       black(black(black(Al,KA,VA,Be),KB,VB,C),KD,VD,
  767             black(Ep,KE,VE,Fi)),
  768       done).
  769
  770fixup_right(done,T,T,done).
  771fixup_right(not_done,T,NT,Done) :-
  772    fixup3(T,NT,Done).
  773
  777fixup3(black(red(black(Fi,KE,VE,Ep),KD,VD,
  778                 black(De,KC,VC,Ga)),KB,VB,
  779             black(Be,KA,VA,Al)),
  780        black(black(Fi,KE,VE,Ep),KD,VD,T1),done) :-
  781    !,
  782    fixup3(red(black(De,KC,VC,Ga),KB,VB,
  783               black(Be,KA,VA,Al)),T1,_).
  784
  788fixup3(red(black(black(Fi,KE,VE,Ep),KD,VD,
  789                 black(De,KC,VC,Ga)),KB,VB,
  790           black(Be,KA,VA,Al)),
  791       black(red(black(Fi,KE,VE,Ep),KD,VD,
  792                 black(De,KC,VC,Ga)),KB,VB,
  793             black(Be,KA,VA,Al)),
  794       done) :- !.
  795fixup3(black(black(black(Fi,KE,VE,Ep),KD,VD,
  796                   black(De,KC,VC,Ga)),KB,VB,
  797             black(Be,KA,VA,Al)),
  798       black(red(black(Fi,KE,VE,Ep),KD,VD,
  799                 black(De,KC,VC,Ga)),KB,VB,
  800             black(Be,KA,VA,Al)),
  801       not_done):- !.
  805fixup3(red(black(black(Fi,KE,VE,Ep),KD,VD,
  806                 red(De,KC,VC,Ga)),KB,VB,
  807           black(Be,KA,VA,Al)),
  808       red(black(black(Fi,KE,VE,Ep),KD,VD,De),KC,VC,
  809           black(Ga,KB,VB,black(Be,KA,VA,Al))),
  810       done) :- !.
  811fixup3(black(black(black(Fi,KE,VE,Ep),KD,VD,
  812                   red(De,KC,VC,Ga)),KB,VB,
  813             black(Be,KA,VA,Al)),
  814       black(black(black(Fi,KE,VE,Ep),KD,VD,De),KC,VC,
  815             black(Ga,KB,VB,black(Be,KA,VA,Al))),
  816       done) :- !.
  820fixup3(red(black(red(Fi,KE,VE,Ep),KD,VD,C),KB,VB,black(Be,KA,VA,Al)),
  821       red(black(Fi,KE,VE,Ep),KD,VD,black(C,KB,VB,black(Be,KA,VA,Al))),
  822       done).
  823fixup3(black(black(red(Fi,KE,VE,Ep),KD,VD,C),KB,VB,black(Be,KA,VA,Al)),
  824       black(black(Fi,KE,VE,Ep),KD,VD,black(C,KB,VB,black(Be,KA,VA,Al))),
  825       done).
  826
  831
  832:- det(rb_visit/2).  833rb_visit(t(_,T),Lf) =>
  834    visit(T,[],Lf).
  835
  836visit(black('',_,_,_),L0,L) => L0 = L.
  837visit(red(L,K,V,R),L0,Lf) =>
  838    visit(L,[K-V|L1],Lf),
  839    visit(R,L0,L1).
  840visit(black(L,K,V,R),L0,Lf) =>
  841    visit(L,[K-V|L1],Lf),
  842    visit(R,L0,L1).
  843
  844:- meta_predicate map(?,2,?,?).    845
  855
  856rb_map(t(Nil,Tree),Goal,NewTree2) =>
  857    NewTree2 = t(Nil,NewTree),
  858    map(Tree,Goal,NewTree,Nil).
  859
  860
  861map(black('',_,_,''),_,Nil0,Nil) => Nil0 = Nil.
  862map(red(L,K,V,R),Goal,NewTree,Nil) =>
  863    NewTree = red(NL,K,NV,NR),
  864    call(Goal,V,NV),
  865    map(L,Goal,NL,Nil),
  866    map(R,Goal,NR,Nil).
  867map(black(L,K,V,R),Goal,NewTree,Nil) =>
  868    NewTree = black(NL,K,NV,NR),
  869    call(Goal,V,NV),
  870    map(L,Goal,NL,Nil),
  871    map(R,Goal,NR,Nil).
  872
  873:- meta_predicate map(?,1).    874
  878
  879rb_map(t(_,Tree),Goal) =>
  880    map(Tree,Goal).
  881
  882
  883map(black('',_,_,''),_) => true.
  884map(red(L,_,V,R),Goal) =>
  885    call(Goal,V),
  886    map(L,Goal),
  887    map(R,Goal).
  888map(black(L,_,V,R),Goal) =>
  889    call(Goal,V),
  890    map(L,Goal),
  891    map(R,Goal).
  892
  902
  903rb_fold(Pred, t(_,T), S1, S2) =>
  904    fold(T, Pred, S1, S2).
  905
  906fold(black(L,K,V,R), Pred) -->
  907    (   {L == ''}
  908    ->  []
  909    ;   fold_parts(Pred, L, K-V, R)
  910    ).
  911fold(red(L,K,V,R), Pred) -->
  912    fold_parts(Pred, L, K-V, R).
  913
  914fold_parts(Pred, L, KV, R) -->
  915    fold(L, Pred),
  916    call(Pred, KV),
  917    fold(R, Pred).
  918
  924
  925:- det(rb_clone/3).  926rb_clone(t(Nil,T),TreeOut,Ns) =>
  927    TreeOut = t(Nil,NT),
  928    clone(T,Nil,NT,Ns,[]).
  929
  930clone(black('',_,_,''),Nil0,Nil,Ns0,Ns) => Nil0=Nil, Ns0=Ns.
  931clone(red(L,K,_,R),Nil,TreeOut,NsF,Ns0) =>
  932    TreeOut = red(NL,K,NV,NR),
  933    clone(L,Nil,NL,NsF,[K-NV|Ns1]),
  934    clone(R,Nil,NR,Ns1,Ns0).
  935clone(black(L,K,_,R),Nil,TreeOut,NsF,Ns0) =>
  936    TreeOut = black(NL,K,NV,NR),
  937    clone(L,Nil,NL,NsF,[K-NV|Ns1]),
  938    clone(R,Nil,NR,Ns1,Ns0).
  939
  948
  949rb_partial_map(t(Nil,T0), Map, Goal, NewTree) =>
  950    NewTree = t(Nil,TF),
  951    partial_map(T0, Map, [], Nil, Goal, TF).
  952
  953partial_map(T,[],[],_,_,T) :- !.
  954partial_map(black('',_,_,_),Map,Map,Nil,_,Nil) :- !.
  955partial_map(red(L,K,V,R),Map,MapF,Nil,Goal,red(NL,K,NV,NR)) :-
  956    partial_map(L,Map,MapI,Nil,Goal,NL),
  957    (   MapI == []
  958    ->  NR = R, NV = V, MapF = []
  959    ;   MapI = [K1|MapR],
  960        (   K == K1
  961        ->  (   call(Goal,V,NV)
  962            ->  true
  963            ;   NV = V
  964            ),
  965            MapN = MapR
  966        ;   NV = V,
  967            MapN = MapI
  968        ),
  969        partial_map(R,MapN,MapF,Nil,Goal,NR)
  970    ).
  971partial_map(black(L,K,V,R),Map,MapF,Nil,Goal,black(NL,K,NV,NR)) :-
  972    partial_map(L,Map,MapI,Nil,Goal,NL),
  973    (   MapI == []
  974    ->  NR = R, NV = V, MapF = []
  975    ;   MapI = [K1|MapR],
  976        (   K == K1
  977        ->  (   call(Goal,V,NV)
  978            ->  true
  979            ;   NV = V
  980            ),
  981            MapN = MapR
  982        ;   NV = V,
  983            MapN = MapI
  984        ),
  985        partial_map(R,MapN,MapF,Nil,Goal,NR)
  986    ).
  987
  988
  993
  994:- det(rb_keys/2).  995rb_keys(t(_,T),Lf) =>
  996    keys(T,[],Lf).
  997
  998keys(black('',_,_,''),L0,L) => L0 = L.
  999keys(red(L,K,_,R),L0,Lf) =>
 1000    keys(L,[K|L1],Lf),
 1001    keys(R,L0,L1).
 1002keys(black(L,K,_,R),L0,Lf) =>
 1003    keys(L,[K|L1],Lf),
 1004    keys(R,L0,L1).
 1005
 1006
 1013
 1014:- det(list_to_rbtree/2). 1015list_to_rbtree(List, T) :-
 1016    sort(List,Sorted),
 1017    ord_list_to_rbtree(Sorted, T).
 1018
 1026
 1027:- det(ord_list_to_rbtree/2). 1028ord_list_to_rbtree([], Tree) =>
 1029    Tree = t(Nil,Nil),
 1030    Nil = black('', _, _, '').
 1031ord_list_to_rbtree([K-V], Tree) =>
 1032    Tree = t(Nil,black(Nil,K,V,Nil)),
 1033    Nil = black('', _, _, '').
 1034ord_list_to_rbtree(List, Tree2) =>
 1035    Tree2 = t(Nil,Tree),
 1036    Nil = black('', _, _, ''),
 1037    Ar =.. [seq|List],
 1038    functor(Ar,_,L),
 1039    Height is truncate(log(L)/log(2)),
 1040    construct_rbtree(1, L, Ar, Height, Nil, Tree).
 1041
 1042construct_rbtree(L, M, _, _, Nil, Nil) :- M < L, !.
 1043construct_rbtree(L, L, Ar, Depth, Nil, Node) :-
 1044    !,
 1045    arg(L, Ar, K-Val),
 1046    build_node(Depth, Nil, K, Val, Nil, Node).
 1047construct_rbtree(I0, Max, Ar, Depth, Nil, Node) :-
 1048    I is (I0+Max)//2,
 1049    arg(I, Ar, K-Val),
 1050    build_node(Depth, Left, K, Val, Right, Node),
 1051    I1 is I-1,
 1052    NewDepth is Depth-1,
 1053    construct_rbtree(I0, I1, Ar, NewDepth, Nil, Left),
 1054    I2 is I+1,
 1055    construct_rbtree(I2, Max, Ar, NewDepth, Nil, Right).
 1056
 1057build_node( 0, Left, K, Val, Right, red(Left, K, Val, Right)) :- !.
 1058build_node( _, Left, K, Val, Right, black(Left, K, Val, Right)).
 1059
 1060
 1064
 1065:- det(rb_size/2). 1066rb_size(t(_,T),Size) =>
 1067    size(T,0,Size).
 1068
 1069size(black('',_,_,_),Sz,Sz) :- !.
 1070size(red(L,_,_,R),Sz0,Szf) :-
 1071    Sz1 is Sz0+1,
 1072    size(L,Sz1,Sz2),
 1073    size(R,Sz2,Szf).
 1074size(black(L,_,_,R),Sz0,Szf) :-
 1075    Sz1 is Sz0+1,
 1076    size(L,Sz1,Sz2),
 1077    size(R,Sz2,Szf).
 1078
 1085
 1086is_rbtree(X), var(X) =>
 1087    fail.
 1088is_rbtree(t(Nil,Nil)) => true.
 1089is_rbtree(t(_,T)) =>
 1090    Err = error(_,_),
 1091    catch(check_rbtree(T), Err, is_rbtree_error(Err)).
 1092is_rbtree(_) =>
 1093    fail.
 1094
 1095is_rbtree_error(Err), Err = error(resource_error(_),_) => throw(Err).
 1096is_rbtree_error(_) => fail.
 1097
 1099
 1100check_rbtree(black(L,K,_,R)) =>
 1101    find_path_blacks(L, 0, Bls),
 1102    check_rbtree(L,-inf,K,Bls),
 1103    check_rbtree(R,K,+inf,Bls).
 1104check_rbtree(Node), Node = red(_,_,_,_) =>
 1105    domain_error(rb_black, Node).
 1106
 1107
 1108find_path_blacks(black('',_,_,''), Bls0, Bls) => Bls = Bls0.
 1109find_path_blacks(black(L,_,_,_), Bls0, Bls) =>
 1110    Bls1 is Bls0+1,
 1111    find_path_blacks(L, Bls1, Bls).
 1112find_path_blacks(red(L,_,_,_), Bls0, Bls) =>
 1113    find_path_blacks(L, Bls0, Bls).
 1114
 1115check_rbtree(black('',_,_,''),Min,Max,Bls0) =>
 1116    check_height(Bls0,Min,Max).
 1117check_rbtree(red(L,K,_,R),Min,Max,Bls) =>
 1118    check_val(K,Min,Max),
 1119    check_red_child(L),
 1120    check_red_child(R),
 1121    check_rbtree(L,Min,K,Bls),
 1122    check_rbtree(R,K,Max,Bls).
 1123check_rbtree(black(L,K,_,R),Min,Max,Bls0) =>
 1124    check_val(K,Min,Max),
 1125    Bls is Bls0-1,
 1126    check_rbtree(L,Min,K,Bls),
 1127    check_rbtree(R,K,Max,Bls).
 1128
 1129check_height(0,_,_) => true.
 1130check_height(Bls0,Min,Max) =>
 1131    throw(error(rbtree(balance(Bls0, Min, Max)), _)).
 1132
 1133check_val(K, Min, Max), (K @> Min ; Min == -inf), (K @< Max ; Max == +inf) =>
 1134    true.
 1135check_val(K, Min, Max) =>
 1136    throw(error(rbtree(order(K, Min, Max)), _)).
 1137
 1138check_red_child(black(_,_,_,_)) => true.
 1139check_red_child(Node), Node = red(_,_,_,_) =>
 1140    domain_error(rb_black, Node).
 1141
 1142
 1143		  1146
 1147:- multifile
 1148    prolog:error_message//1. 1149
 1150prolog:error_message(rbtree(balance(Bls0, Min, Max))) -->
 1151    [ 'Unbalance ~d between ~w and ~w'-[Bls0,Min,Max] ].
 1152prolog:error_message(rbtree(order(K, Min, Max))) -->
 1153    [ 'not ordered: ~w not between ~w and ~w'-[K,Min,Max] ]