annotate lisp/oobr/hasht.el @ 100:4be1180a9e89 r20-1b2

Import from CVS: tag r20-1b2
author cvs
date Mon, 13 Aug 2007 09:15:11 +0200
parents 131b0175ea99
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1 ;;!emacs
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
2 ;;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
3 ;; FILE: hasht.el
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
4 ;; SUMMARY: Create hash tables from lists and operate on them.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
5 ;; USAGE: GNU Emacs Lisp Library
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
6 ;; KEYWORDS: extensions, tools
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
7 ;;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
8 ;; AUTHOR: Bob Weiner
100
4be1180a9e89 Import from CVS: tag r20-1b2
cvs
parents: 70
diff changeset
9 ;; ORG: InfoDock Associates
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
10 ;;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
11 ;; ORIG-DATE: 16-Mar-90 at 03:38:48
100
4be1180a9e89 Import from CVS: tag r20-1b2
cvs
parents: 70
diff changeset
12 ;; LAST-MOD: 20-Feb-97 at 07:04:56 by Bob Weiner
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
13 ;;
100
4be1180a9e89 Import from CVS: tag r20-1b2
cvs
parents: 70
diff changeset
14 ;; Copyright (C) 1990-1995, 1997 Free Software Foundation, Inc.
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
15 ;; See the file BR-COPY for license information.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
16 ;;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
17 ;; This file is part of the OO-Browser.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
18 ;;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
19 ;; DESCRIPTION:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
20 ;;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
21 ;; Featureful set of hash table operators for use in personal programs.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
22 ;;
100
4be1180a9e89 Import from CVS: tag r20-1b2
cvs
parents: 70
diff changeset
23 ;; `hash-make' creates a hash table from an association list, `hash-add'
4be1180a9e89 Import from CVS: tag r20-1b2
cvs
parents: 70
diff changeset
24 ;; adds a value-key pair to a hash table, and `hash-lookup' finds the value
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
25 ;; associated with a given key in a hash table, if any.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
26 ;;
100
4be1180a9e89 Import from CVS: tag r20-1b2
cvs
parents: 70
diff changeset
27 ;; `hash-map' does the same thing as `mapcar' but operates on hash tables
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
28 ;; instead.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
29 ;;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
30 ;; For a list of 300 items, these hash tables improve lookup times by a
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
31 ;; factor of between 8 and 10 to 1 over those for an unsorted list.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
32 ;;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
33 ;; Public and private function names are alphabetized for easy location.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
34 ;;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
35 ;; DESCRIP-END.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
36
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
37 ;;; ************************************************************************
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
38 ;;; Public variables
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
39 ;;; ************************************************************************
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
40
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
41 (defvar hash-merge-values-function 'hash-merge-values
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
42 "*Function to call in hash-merge to merge the values from 2 hash tables that contain the same key.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
43 It is sent the two values as arguments.")
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
44
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
45 ;;; ************************************************************************
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
46 ;;; Public functions
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
47 ;;; ************************************************************************
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
48
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
49 (defun hash-add (value key hash-table)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
50 "Add VALUE, any lisp object, referenced by KEY, a string, to HASH-TABLE.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
51 Replaces any VALUE previously referenced by KEY."
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
52 (if (hashp hash-table)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
53 (let* ((obarray (hash-obarray hash-table))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
54 (sym (intern key obarray)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
55 (if sym (set sym value)))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
56
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
57 (defun hash-copy (hash-table)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
58 "Return a copy of HASH-TABLE, list and vector elements are shared across both tables."
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
59 (if (not (hashp hash-table))
100
4be1180a9e89 Import from CVS: tag r20-1b2
cvs
parents: 70
diff changeset
60 (error "(hash-copy): Invalid hash-table: `%s'" hash-table))
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
61 (let ((htable-copy (hash-make (length (hash-obarray hash-table)))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
62 (hash-map
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
63 (function (lambda (elt) (hash-add (car elt) (cdr elt) htable-copy)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
64 hash-table)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
65 htable-copy))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
66
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
67 (defun hash-count (hash-table)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
68 "Return number of elements stored in HASH-TABLE or nil if not a valid hash table."
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
69 (if (hashp hash-table)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
70 (let ((obarray (hash-obarray hash-table))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
71 (count 0))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
72 (mapatoms (function
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
73 (lambda (sym)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
74 (and (boundp sym) sym (setq count (1+ count)))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
75 obarray)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
76 count)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
77
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
78 (defun hash-delete (key hash-table)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
79 "Delete element referenced by KEY, a string, from HASH-TABLE.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
80 Return nil if KEY is not in HASH-TABLE or non-nil otherwise."
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
81 (if (hashp hash-table)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
82 (let* ((obarray (hash-obarray hash-table))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
83 (sym (intern-soft key obarray)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
84 (and sym (boundp sym) (makunbound sym)))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
85
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
86 (defun hash-deep-copy (obj)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
87 "Return a copy of OBJ with new copies of all elements, except symbols."
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
88 (cond ((null obj) nil)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
89 ((stringp obj)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
90 (copy-sequence obj))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
91 ((hashp obj)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
92 (let ((htable-copy (hash-make (length (hash-obarray obj)))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
93 (mapcar
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
94 (function
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
95 (lambda (elt) (hash-add (car elt) (cdr elt) htable-copy)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
96 (hash-map 'hash-deep-copy obj))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
97 htable-copy))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
98 ((vectorp obj)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
99 ;; convert to list for mapping
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
100 (setq obj (append obj nil))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
101 ;; Return as a vector
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
102 (vconcat (mapcar 'hash-deep-copy obj)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
103 ((atom obj) obj)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
104 ((nlistp obj)
100
4be1180a9e89 Import from CVS: tag r20-1b2
cvs
parents: 70
diff changeset
105 (error "(hash-deep-copy): Invalid type, `%s'" obj))
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
106 (t ;; list
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
107 (cons (hash-deep-copy (car obj)) (hash-deep-copy (cdr obj))))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
108
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
109 (fset 'hash-get 'hash-lookup)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
110 (defun hash-key-p (key hash-table)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
111 "Return non-nil iff KEY is in HASH-TABLE. KEY's hash table symbol is returned."
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
112 (if (hashp hash-table)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
113 (let* ((obarray (hash-obarray hash-table))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
114 (sym (intern-soft key obarray)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
115 (if (boundp sym) sym))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
116
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
117 (defun hash-lookup (key hash-table)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
118 "Lookup KEY in HASH-TABLE and return associated value.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
119 If value is nil, this function does not tell you whether or not KEY is in the
100
4be1180a9e89 Import from CVS: tag r20-1b2
cvs
parents: 70
diff changeset
120 hash table. Use `hash-key-p' instead for that function."
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
121 (if (hashp hash-table)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
122 (let* ((obarray (hash-obarray hash-table))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
123 (sym (intern-soft key obarray)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
124 (if (boundp sym) (symbol-value sym)))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
125
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
126 (defun hash-make (initializer &optional reverse)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
127 "Create a hash table from INITIALIZER.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
128 INITIALIZER may be an alist with elements of the form (<value> . <key>) from
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
129 which the hash table is built. Alternatively, it may be a non-negative
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
130 integer which is used as the minimum size of a new, empty hash table.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
131 Optional non-nil second argument REVERSE means INITIALIZER has elements of
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
132 form (<key> . <value>)."
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
133 (if (integerp initializer)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
134 (if (>= initializer 0)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
135 (cons 'hasht (make-vector (hash-next-prime initializer) 0))
100
4be1180a9e89 Import from CVS: tag r20-1b2
cvs
parents: 70
diff changeset
136 (error "(hash-make): Initializer must be >= 0, not `%s'"
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
137 initializer))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
138 (let* ((vlen (hash-next-prime (length initializer)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
139 (obarray (make-vector vlen 0))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
140 sym)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
141 (mapcar
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
142 (function
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
143 (lambda (cns)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
144 (let ((key) (value))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
145 (if (consp cns)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
146 (if reverse
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
147 (setq key (car cns) value (cdr cns))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
148 (setq key (cdr cns) value (car cns))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
149 (if (setq sym (intern key))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
150 (set sym value)))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
151 initializer)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
152 (cons 'hasht obarray))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
153
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
154 (defun hash-map (func hash-table)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
155 "Return result of application of FUNC to each (<value> . <key>) element of HASH-TABLE."
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
156 (if (not (hashp hash-table))
100
4be1180a9e89 Import from CVS: tag r20-1b2
cvs
parents: 70
diff changeset
157 (error "(hash-map): Invalid hash-table: `%s'" hash-table))
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
158 (let ((result))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
159 (mapatoms (function
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
160 (lambda (sym)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
161 (and (boundp sym)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
162 sym
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
163 (setq result (cons (funcall
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
164 func
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
165 (cons (symbol-value sym)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
166 (symbol-name sym)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
167 result)))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
168 (hash-obarray hash-table))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
169 result))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
170
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
171 (defun hash-merge (&rest hash-tables)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
172 "Merge any number of HASH-TABLES. Return resultant hash table.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
173 A single argument consisting of a list of hash tables may also be given.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
174 Return an empty hash table if any argument from the merge list is other
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
175 than nil or a hash table."
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
176 (let ((empty-ht (hash-make 1)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
177 (and (not (hashp (car hash-tables)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
178 (listp (car hash-tables))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
179 ;; Handle situation where a list of hash-tables is passed in as a
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
180 ;; single argument, rather than as multiple arguments.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
181 (setq hash-tables (car hash-tables)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
182 (if (memq nil (mapcar (function (lambda (ht) (or (null ht) (hashp ht))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
183 hash-tables))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
184 empty-ht
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
185 (setq hash-tables
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
186 (delq nil (mapcar (function (lambda (ht)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
187 (if (equal ht empty-ht)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
188 nil ht)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
189 hash-tables)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
190 (let ((len (length hash-tables)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
191 (cond ((= len 0) empty-ht)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
192 ((= len 1) (car hash-tables))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
193 (t (let ((htable (hash-make
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
194 (apply '+ (mapcar 'hash-count hash-tables))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
195 key value)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
196 (mapcar
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
197 (function
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
198 (lambda (ht)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
199 (hash-map (function
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
200 (lambda (val-key-cons)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
201 (setq value (car val-key-cons)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
202 key (cdr val-key-cons))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
203 (if (not (hash-key-p key htable))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
204 (hash-add value key htable)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
205 ;; Merge values
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
206 (hash-add
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
207 (funcall hash-merge-values-function
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
208 (hash-get key htable)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
209 value)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
210 key htable))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
211 ht)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
212 hash-tables)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
213 htable)))))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
214
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
215 (defun hash-merge-values (value1 value2)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
216 "Return a list from merging VALUE1 and VALUE2 or creating a new list.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
217 Nil values are thrown away. If both arguments are lists, their elements are
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
218 assumed to be strings and the result is a set of ordered strings."
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
219 (cond ((and (listp value1) (listp value2))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
220 ;; Assume desired result is a set of strings.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
221 (br-set-of-strings (sort (append value1 value2) 'string<)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
222 ((null value1)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
223 value2)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
224 ((null value2)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
225 value1)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
226 ((listp value1)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
227 (cons value2 value1))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
228 ((listp value2)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
229 (cons value1 value2))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
230 (t (list value1 value2))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
231
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
232 (make-obsolete 'hash-new 'hash-make)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
233 (defun hash-new (size)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
234 "Return a new hash table of SIZE elements.
100
4be1180a9e89 Import from CVS: tag r20-1b2
cvs
parents: 70
diff changeset
235 This is obsolete. Use `hash-make' instead."
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
236 (hash-make size))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
237
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
238 (defun hash-prin1 (hash-table &optional stream)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
239 "Output the printed representation of HASH-TABLE.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
240 Quoting characters are printed when needed to make output that `read'
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
241 can handle, whenever this is possible.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
242 Output stream is STREAM, or value of `standard-output'."
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
243 (if (not (hashp hash-table))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
244 (progn (prin1 hash-table stream)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
245 (princ "\n" stream))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
246 (princ "\(\n" stream)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
247 (hash-map
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
248 (function (lambda (val-key-cons)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
249 (prin1 val-key-cons stream)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
250 (princ "\n" stream)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
251 hash-table)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
252 (princ "\)\n" stream)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
253
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
254 (defun hash-replace (value key hash-table)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
255 "Replace VALUE referenced by KEY, a string, in HASH-TABLE.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
256 An error will occur if KEY is not found in HASH-TABLE."
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
257 (if (hashp hash-table)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
258 (let* ((obarray (hash-obarray hash-table))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
259 (sym (intern-soft key obarray)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
260 (if (and (boundp sym) sym)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
261 (set sym value)
100
4be1180a9e89 Import from CVS: tag r20-1b2
cvs
parents: 70
diff changeset
262 (error "(hash-replace): `%s' key not found in hash table." key)))))
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
263
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
264 (defun hash-resize (hash-table new-size)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
265 "Resize HASH-TABLE to NEW-SIZE without losing any elements and return new table.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
266 NEW-SIZE must be greater than 0. Hashing works best if NEW-SIZE is a prime
100
4be1180a9e89 Import from CVS: tag r20-1b2
cvs
parents: 70
diff changeset
267 number. See also `hash-next-prime'."
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
268 (if (< new-size 1)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
269 (error "(hash-resize): Cannot resize hash table to size %d" new-size))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
270 (let ((htable (hash-make new-size)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
271 (hash-map (function
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
272 (lambda (elt)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
273 (hash-add (car elt) (cdr elt) htable)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
274 hash-table)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
275 htable))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
276
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
277 (defun hash-resize-p (hash-table)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
278 "Resizes HASH-TABLE to 1.5 times its size if above 80% full.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
279 Returns new hash table when resized, else nil."
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
280 (if (hashp hash-table)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
281 (let ((count (hash-count hash-table))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
282 (size (length (hash-obarray hash-table))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
283 (if (> (* count (/ count 5)) size)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
284 (hash-resize hash-table (hash-next-prime (+ size (/ size 2))))))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
285
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
286 (defun hash-size (hash-table)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
287 "Return size of HASH-TABLE which is >= number of elements in the table.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
288 Return nil if not a valid hash table."
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
289 (if (hashp hash-table)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
290 (length (hash-obarray hash-table))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
291 (fset 'hash-length 'hash-size)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
292
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
293 (defun hashp (object)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
294 "Return non-nil if OBJECT is a hash-table."
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
295 (and (listp object) (eq (car object) 'hasht)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
296 (vectorp (cdr object))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
297
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
298 ;;; ************************************************************************
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
299 ;;; Private functions
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
300 ;;; ************************************************************************
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
301
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
302 (defun hash-next-prime (n)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
303 "Return next prime number >= N."
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
304 (if (<= n 2)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
305 2
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
306 (and (= (% n 2) 0) (setq n (1+ n)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
307 (while (not (hash-prime-p n))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
308 (setq n (+ n 2)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
309 n))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
310
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
311 (defun hash-obarray (hash-table)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
312 "Return symbol table (object array) portion of HASH-TABLE."
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
313 (cdr hash-table))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
314
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
315 (defun hash-prime-p (n)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
316 "Return non-nil iff N is prime."
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
317 (if (< n 0) (setq n (- n)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
318 (let ((small-primes '(1 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
319 71 73 79 83 89)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
320 (cond ((< n 91) (memq n small-primes))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
321 ((< n 7921) ;; 89, max small-prime, squared
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
322 (let ((prime t)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
323 (pr-list small-primes))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
324 (while (and (setq pr-list (cdr pr-list))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
325 (setq prime (/= (% n (car pr-list)) 0))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
326 prime))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
327 ((or (= (% n 3) 0) (= (% n 2) 0)) nil)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
328 ((let ((factor1 5)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
329 (factor2 7)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
330 (is-prime))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
331 (while (and (<= (* factor1 factor1) n)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
332 (setq is-prime (and (/= (% n factor1) 0)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
333 (/= (% n factor2) 0))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
334 (setq factor1 (+ factor1 6)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
335 factor2 (+ factor2 6)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
336 is-prime)))))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
337
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
338 (provide 'hasht)