From 260968beacb1a2e1c6bdd652f75fe087f907ce0f Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Wed, 12 Feb 2014 20:25:27 -0800 Subject: * eval.c (eval_init): Register hash_guni and hash_gisec as intrinsics. * hash.c (hash_guni, hash_gisec): New functions. (hash_isec): Bugfix: since gethash was naively used, keys in hash2 associated with the value nil were erroneously omitted from the intersection. * hash.h (hash_guni, hash_gisec): Declared. * txr.1: Documented new functions. --- hash.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) (limited to 'hash.c') diff --git a/hash.c b/hash.c index f9548c3c..0941effb 100644 --- a/hash.c +++ b/hash.c @@ -952,6 +952,37 @@ val hash_uni(val hash1, val hash2) } } +val hash_guni(val hash1, val hash2) +{ + struct hash *h1 = (struct hash *) cobj_handle(hash1, hash_s); + struct hash *h2 = (struct hash *) cobj_handle(hash2, hash_s); + + if (h1->hash_fun != h2->hash_fun) + uw_throwf(error_s, lit("hash-guni: ~a and ~a are incompatible hashes"), hash1, hash2, nao); + + { + val hout = make_similar_hash(hash1); + val hiter, entry; + + for (hiter = hash_begin(hash1), entry = hash_next(hiter); + entry; + entry = hash_next(hiter)) + { + sethash(hout, car(entry), cdr(entry)); + } + + for (hiter = hash_begin(hash2), entry = hash_next(hiter); + entry; + entry = hash_next(hiter)) + { + val *loc = gethash_l(hout, car(entry), 0); + set(*loc, append2(*loc, cdr(entry))); + } + + return hout; + } +} + val hash_diff(val hash1, val hash2) { struct hash *h1 = (struct hash *) cobj_handle(hash1, hash_s); @@ -991,7 +1022,9 @@ val hash_isec(val hash1, val hash2) entry; entry = hash_next(hiter)) { - if (gethash(hash2, car(entry))) + val found; + gethash_f(hash2, car(entry), &found); + if (found) sethash(hout, car(entry), cdr(entry)); } @@ -999,6 +1032,32 @@ val hash_isec(val hash1, val hash2) } } +val hash_gisec(val hash1, val hash2) +{ + struct hash *h1 = (struct hash *) cobj_handle(hash1, hash_s); + struct hash *h2 = (struct hash *) cobj_handle(hash2, hash_s); + + if (h1->hash_fun != h2->hash_fun) + uw_throwf(error_s, lit("hash-uni: ~a and ~a are incompatible hashes"), hash1, hash2, nao); + + { + val hout = make_similar_hash(hash1); + val hiter, entry; + + for (hiter = hash_begin(hash1), entry = hash_next(hiter); + entry; + entry = hash_next(hiter)) + { + val found; + val data2 = gethash_f(hash2, car(entry), &found); + if (found) + sethash(hout, car(entry), append2(cdr(entry), data2)); + } + + return hout; + } +} + val hash_update(val hash, val fun) { val iter = hash_begin(hash); -- cgit v1.2.3