cvs diff - library additions
Christopher Rodd SPEIRS
crs at students.cs.mu.oz.au
Thu Feb 13 17:45:19 AEDT 1997
Hi fergus,
here are the new and improved library additions for your reviewing.
instead of including a diff of the changes to bag.m, ive included bag.m. (the
diff was the same size as bag.m)
Thanks, Chris
===============================================================================
library/bag.m
Made some extensive additions to bag.m to include the standard set
operations (union, intersection, subtraction). Also added some other useful
predicates to operate on bags.
%---------------------------------------------------------------------------%
% Copyright (C) 1995 University of Melbourne.
% This file may only be copied under the terms of the GNU Library General
% Public License - see the file COPYING.LIB in the Mercury distribution.
%---------------------------------------------------------------------------%
%
% file: bag.m
% An implementation of multisets.
% main author: conway, crs.
% stability: medium
%
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- module bag.
:- interface.
:- type bag(T).
% create an empty bag
:- pred bag__init(bag(T)).
:- mode bag__init(out) is det.
% insert a particular value in a bag
:- pred bag__insert(bag(T), T, bag(T)).
:- mode bag__insert(in, in, out) is det.
% insert a list of values into a bag
:- pred bag__insert_list(bag(T), list(T), bag(T)).
:- mode bag__insert_list(in, in, out) is det.
% make a bag from a list
:- pred bag__from_list(list(T), bag(T)).
:- mode bag__from_list(in, out) is det.
% given a bag, produce a sorted list with no duplicates
% containing all the values in the bag
:- pred bag__to_list_without_duplicates(bag(T), list(T)).
:- mode bag__to_list_without_duplicates(in, out) is det.
% remove one occurrence of a particular value from a bag
% fail if the item does not exist in the bag
:- pred bag__remove(bag(T), T, bag(T)).
:- mode bag__remove(in, in, out) is semidet.
% remove one occurrence of a particular value from a bag
% abort if the item does not exist in the bag
:- pred bag__det_remove(bag(T), T, bag(T)).
:- mode bag__det_remove(in, in, out) is det.
% delete one occurrence of a particular value from a bag
% if the key is not present, leave the map unchanged
:- pred bag__delete(bag(T), T, bag(T)).
:- mode bag__delete(in, in, out) is det.
% remove all occurrences of a particular value from a bag
% fail if the item does not exist in the bag
:- pred bag__remove_all(bag(T), T, bag(T)).
:- mode bag__remove_all(in, in, out) is semidet.
% delete all occurrences of a particular value from a bag
:- pred bag__delete_all(bag(T), T, bag(T)).
:- mode bag__delete_all(in, in, out) is det.
% check whether a bag contains a particular value
:- pred bag__contains(bag(T), T).
:- mode bag__contains(in, in) is semidet.
% bag__subtract(Bag0, SubBag, Bag)
% subtracts SubBag from Bag0 to produce Bag
% each element in SubBag is removed from Bag0 to produce Bag
% if an element exists in SubBag, but not in Bag, then that
% element is not removed.
% e.g. bag__subtract({1, 1, 2, 2, 3 }, {1, 1, 2, 3, 3, 3}, {2}).
:- pred bag__subtract(bag(T), bag(T), bag(T)).
:- mode bag__subtract(in, in, out) is det.
% The third bag is the union of the first 2 bags.
% e.g. {1, 1, 2, 2} U {2, 2, 3, 3} = {1, 1, 2, 2, 2, 2, 3, 3}
:- pred bag__union(bag(T), bag(T), bag(T)).
:- mode bag__union(in, in, out) is det.
% The third bag is the intersection of the first 2 bags
% every element in the third bag exists in both of the first 2 bags
% e.g. bag__intersect({1, 2, 2, 3, 3}, {2, 2, 3, 4}, {2, 2, 3}).
:- pred bag__intersect(bag(T), bag(T), bag(T)).
:- mode bag__intersect(in, in, out) is det.
% fails if there is no intersection between the 2 bags
% bag__intersect(A, B) :- bag__intersect(A, B, C), not bag__is_empty(C).
:- pred bag__intersect(bag(T), bag(T)).
:- mode bag__intersect(in, in) is semidet.
% fails if the first bag is not a subbag of the second.
% bag__is_subbag(A, B). implies that every element in the bag A
% is also in the bag B. If an element is in bag A multiple times, it
% must be in bag B at least as many times.
% e.g. bag__is_subbag({1, 1, 2}, {1, 1, 2, 2, 3}).
% e.g. bag__is_subbag({1, 1, 2}, {1, 2, 3}) :- fail.
:- pred bag__is_subbag(bag(T), bag(T)).
:- mode bag__is_subbag(in, in) is semidet.
% Check whether a bag is empty.
:- pred bag__is_empty(bag(T)).
:- mode bag__is_empty(in) is semidet.
% fails if the bag is empty
:- pred bag__remove_smallest(bag(T), T, bag(T)).
:- mode bag__remove_smallest(in, out, out) is semidet.
% compares the two bags, and returns whether the first bag is a
% subset (<), is equal (=), or is a superset (>) of the second
% bag__subset_compare(<, {apple, orange}, {apple, apple, orange}).
% bag__subset_compare(=, {apple, orange}, {apple, orange}).
% bag__subset_compare(>, {apple, apple, orange}, {apple, orange}).
% bag__subset_compare(_, {apple, apple}, {orange, orange}) :- fail.
:- pred bag__subset_compare(comparison_result, bag(T), bag(T)).
:- mode bag__subset_compare(out, in, in) is semidet.
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- implementation.
:- import_module map, int, require.
:- type bag(T) == map(T, int).
%---------------------------------------------------------------------------%
bag__init(Bag) :-
map__init(Bag).
%---------------------------------------------------------------------------%
bag__insert(Bag0, Item, Bag) :-
(
map__search(Bag0, Item, Count0)
->
Count is Count0 + 1
;
Count = 1
),
map__set(Bag0, Item, Count, Bag).
%---------------------------------------------------------------------------%
:- bag__insert_list(_, List, _) when List.
bag__insert_list(Bag, [], Bag).
bag__insert_list(Bag0, [Item|Items], Bag) :-
bag__insert(Bag0, Item, Bag1),
bag__insert_list(Bag1, Items, Bag).
bag__from_list(List, Bag) :-
bag__init(Bag0),
bag__insert_list(Bag0, List, Bag).
%---------------------------------------------------------------------------%
bag__delete(Bag0, Item, Bag) :- % det
( bag__remove(Bag0, Item, Bag1) ->
Bag = Bag1
;
Bag = Bag0
).
bag__remove(Bag0, Item, Bag) :- % semidet
map__search(Bag0, Item, Count0),
(
Count0 > 1
->
Count is Count0 - 1,
map__set(Bag0, Item, Count, Bag)
;
map__delete(Bag0, Item, Bag)
).
bag__det_remove(Bag0, Item, Bag) :- % det
( bag__remove(Bag0, Item, Bag1) ->
Bag = Bag1
;
error("bag__det_remove: Missing item in bag."),
Bag = Bag0
).
bag__remove_all(Bag0, Item, Bag) :- % semidet
map__remove(Bag0, Item, _Val, Bag).
bag__delete_all(Bag0, Item, Bag) :- % det
map__delete(Bag0, Item, Bag).
%---------------------------------------------------------------------------%
bag__contains(Bag, Item) :-
map__contains(Bag, Item).
%---------------------------------------------------------------------------%
bag__to_list_without_duplicates(Bag, List) :-
map__keys(Bag, List).
%---------------------------------------------------------------------------%
bag__subtract(Bag0, SubBag, Bag) :-
( map__remove_smallest(SubBag, SubKey, SubVal, SubBag0) ->
( map__search(Bag0, SubKey, Val) ->
NewVal = Val - SubVal,
( NewVal > 0 ->
map__det_update(Bag0, SubKey, NewVal, Bag1)
;
map__det_remove(Bag0, SubKey, _Val, Bag1)
)
;
Bag1 = Bag0
),
bag__subtract(Bag1, SubBag0, Bag)
;
Bag = Bag0
).
bag__union(A, B, Out) :-
( map__remove_smallest(A, Key, AVal,A0) ->
( map__search(B, Key, BVal) ->
NewVal = AVal + BVal,
map__det_update(B, Key, NewVal, B0)
;
map__det_insert(B, Key, AVal, B0)
),
bag__union(A0, B0, Out)
;
Out = B
).
bag__intersect(A, B, Out) :-
bag__init(Out0),
bag__intersect_2(A, B, Out0, Out).
:- pred bag__intersect_2(bag(T), bag(T), bag(T), bag(T)).
:- mode bag__intersect_2(in, in, in, out) is det.
bag__intersect_2(A, B, Out0, Out) :-
( map__remove_smallest(A, Key, AVal,A0) ->
( map__search(B, Key, BVal) ->
int__max(AVal, BVal, Val),
map__det_insert(Out0, Key, Val, Out1)
;
map__det_insert(Out0, Key, AVal, Out1)
),
bag__intersect_2(A0, B, Out1, Out)
;
Out = Out0
).
bag__intersect(A, B) :-
map__remove_smallest(A, Key, _AVal,A0),
( map__contains(B, Key) ->
true
;
bag__intersect(A0, B)
).
%---------------------------------------------------------------------------%
bag__is_subbag(SubBag, BigBag) :-
bag__subtract(SubBag, BigBag, SubBag0),
bag__is_empty(SubBag0).
%---------------------------------------------------------------------------%
bag__is_empty(Bag) :-
map__is_empty(Bag).
%---------------------------------------------------------------------------%
bag__remove_smallest(Bag0, Item, Bag) :-
map__remove_smallest(Bag0, Item, Val, Bag1),
( Val > 1 ->
NewVal = Val - 1,
map__det_insert(Bag1, Item, NewVal, Bag)
;
Bag = Bag1
).
% compares the two bags, and returns whether the first bag is a
% subset (<), is equal (=), or is a superset (>) of the second
% bag__subset_compare(<, {apple, orange}, {apple, apple, orange}).
% bag__subset_compare(=, {apple, orange}, {apple, orange}).
% bag__subset_compare(>, {apple, apple, orange}, {apple, orange}).
% bag__subset_compare(_, {apple, apple}, {orange, orange}) :- fail.
% :- pred bag__subset_compare(comparison_result, bag(T), bag(T)).
% :- mode bag__subset_compare(out, in, in) is semidet.
bag__subset_compare(Res, A, B) :-
( map__remove_smallest(A, Key, AVal, A0) ->
( map__remove(B, Key, BVal, B0) ->
compare(ValRes, AVal, BVal),
(
ValRes = (>),
bag__is_subbag(B0, A0),
Res = (>)
;
ValRes = (=),
bag__subset_compare(Res, A0, B0)
;
ValRes = (<),
bag__is_subbag(A0, B0),
Res = (<)
)
;
% B is empty, but A is not
Res = (>)
)
;
% A is empty
( map__is_empty(B) ->
Res = (=)
;
Res = (<)
)
).
===============================================================================
library/io.m
Added predicates io__tmpnam and io__remove_file, as they were
required by termination.m
Index: io.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/library/io.m,v
retrieving revision 1.110
diff -u -r1.110 io.m
--- io.m 1997/02/08 16:35:55 1.110
+++ io.m 1997/02/13 05:56:58
@@ -673,6 +673,17 @@
%-----------------------------------------------------------------------------%
+% returns a unique temporary filename.
+:- pred io__tmpnam(string, io__state, io__state).
+:- mode io__tmpnam(out, di, uo) is det.
+
+% deletes a file
+:- pred io__remove_file(string, io__res, io__state, io__state).
+:- mode io__remove_file(in, out, di, uo) is det.
+
+
+%-----------------------------------------------------------------------------%
+
% Memory management predicates.
% Write some memory/time usage statistics to stdout.
@@ -2069,6 +2080,55 @@
:- pragma(c_code, io__putenv(VarAndValue::in), "
SUCCESS_INDICATOR = (putenv(VarAndValue) == 0);
").
+
+/*---------------------------------------------------------------------------*/
+%#include <stdio.h>
+:- pragma(c_code, io__tmpnam(FileName::out, IO0::di, IO::uo), "{
+ Word tmp;
+ char *retval;
+
+ incr_hp_atomic(tmp, (L_tmpnam + sizeof(Word)) / sizeof(Word));
+ if (tmpnam((char *)tmp) == NULL) {
+ fprintf(stderr,
+ ""Mercury runtime: unable to create temporary filename\\n"");
+ }
+ FileName = (char *)tmp;
+ update_io(IO0, IO);
+}").
+
+/*---------------------------------------------------------------------------*/
+
+io__remove_file(FileName, Result, IO, IO) :-
+ io__remove_file_2(FileName, Res, ResString),
+ ( Res < 0 ->
+ Result = error(ResString)
+ ;
+ Result = ok
+ ).
+
+
+:- pred io__remove_file_2(string, int, string).
+:- mode io__remove_file_2(in, out, out) is det.
+
+%#include <string.h>
+%#include <errno.h>
+%#include "prof.h" % for strerror
+:- pragma(c_code, io__remove_file_2(FileName::in, RetVal::out, RetStr::out), "{
+ Word tmp;
+ char *buf;
+
+ RetVal = remove(FileName);
+
+ if (RetVal < 0) {
+ buf = strerror(errno);
+ incr_hp_atomic(tmp,(strlen(buf)+sizeof(Word)) / sizeof(Word));
+ RetStr = (char *)tmp;
+ strcpy(RetStr, (char *)tmp);
+ } else {
+ RetStr = NULL;
+ }
+}").
+
/*---------------------------------------------------------------------------*/
===============================================================================
library/list.m
added predicates list__sort_and_remove_dups/4 and
list__merge_and_remove_dups/4. These additions made the set of list__sort
and list__merge operations more complete. Before these additions, there was
list__sort/3, list__sort/4, and list__sort_and_remove_dups/3. It was the
same for list__merge.
Index: list.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/library/list.m,v
retrieving revision 1.64
diff -u -r1.64 list.m
--- list.m 1996/10/24 05:57:42 1.64
+++ list.m 1997/02/13 06:17:01
@@ -384,6 +384,14 @@
:- pred list__sort(pred(X, X, comparison_result), list(X), list(X)).
:- mode list__sort(pred(in, in, out) is det, in, out) is det.
+ % list__sort_and_remove_dups(Compare, Unsorted, Sorted) is true iff
+ % Sorted is a list containing the same elements as Unsorted, but with
+ % any duplicates removed. Where Sorted is a sorted list, wrt the
+ % ordering defined by the predicate term Compare.
+:- pred list__sort_and_remove_dups(pred(X, X, comparison_result), list(X),
+ list(X)).
+:- mode list__sort_and_remove_dups(pred(in, in, out) is det, in, out) is det.
+
% list__merge(Compare, As, Bs, Sorted) is true iff Sorted is a
% list containing the elements of As and Bs in the order implied
% by their sorted merge. The ordering of elements is defined by
@@ -392,6 +400,12 @@
:- pred list__merge(pred(X, X, comparison_result), list(X), list(X), list(X)).
:- mode list__merge(pred(in, in, out) is det, in, in, out) is det.
+:- pred list__merge_and_remove_dups(pred(X, X, comparison_result),
+ list(X), list(X), list(X)).
+:- mode list__merge_and_remove_dups(pred(in, in, out) is det,
+ in, in, out) is det.
+
+
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
@@ -878,6 +892,10 @@
list__filter_map(P, T0, L1).
+list__sort_and_remove_dups(P, L0, L) :-
+ list__sort(P, L0, L1),
+ list__remove_adjacent_dups(L1, L).
+
list__sort(P, L0, L) :-
list__length(L0, N),
(
@@ -950,6 +968,26 @@
L = [H2|T],
list__merge(P, [H1|T1], T2, T)
).
+
+list__merge_and_remove_dups(_P, [], [], []).
+list__merge_and_remove_dups(_P, [], [Y|Ys], [Y|Ys]).
+list__merge_and_remove_dups(_P, [X|Xs], [], [X|Xs]).
+list__merge_and_remove_dups(P, [H1|T1], [H2|T2], L) :-
+ call(P, H1, H2, C),
+ (
+ C = (<),
+ L = [H1|T],
+ list__merge(P, T1, [H2|T2], T)
+ ;
+ C = (=),
+ L = [H1 | T],
+ list__merge(P, T1, T2, T)
+ ;
+ C = (>),
+ L = [H2|T],
+ list__merge(P, [H1|T1], T2, T)
+ ).
+
%-----------------------------------------------------------------------------%
More information about the developers
mailing list