*** empty log message ***
[bpt/guile.git] / libguile / hash.c
CommitLineData
950cc72b 1/* Copyright (C) 1995,1996,1997, 2000 Free Software Foundation, Inc.
0f2d19dd
JB
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
82892bed
JB
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
0f2d19dd
JB
17 *
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
20 *
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
26 *
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
29 *
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
37 *
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
82892bed 40 * If you do not wish that, delete this exception notice. */
1bbd0b84
GB
41
42/* Software engineering face-lift by Greg J. Badros, 11-Dec-1999,
43 gjb@cs.washington.edu, http://www.cs.washington.edu/homes/gjb */
44
0f2d19dd
JB
45\f
46
47#include <stdio.h>
48#include "_scm.h"
20e6290e 49#include "chars.h"
f04d8caf 50#include "ports.h"
003d1fd0 51#include "vectors.h"
0f2d19dd 52
b6791b2e 53#include "validate.h"
20e6290e 54#include "hash.h"
0f2d19dd
JB
55\f
56
57#ifndef floor
58extern double floor();
59#endif
60
1cc91f1b 61
0f2d19dd 62unsigned long
1bbd0b84 63scm_hasher(SCM obj, unsigned long n, scm_sizet d)
0f2d19dd
JB
64{
65 switch (7 & (int) obj) {
94a5efac
GB
66 case 2:
67 case 6:
68 return SCM_INUM(obj) % n; /* SCM_INUMP(obj) */
0f2d19dd 69 case 4:
7866a09b
GB
70 if SCM_CHARP(obj)
71 return (unsigned)(scm_downcase(SCM_CHAR(obj))) % n;
0f2d19dd
JB
72 switch ((int) obj) {
73#ifndef SICP
94a5efac
GB
74 case (int) SCM_EOL:
75 d = 256;
76 break;
0f2d19dd 77#endif
94a5efac
GB
78 case (int) SCM_BOOL_T:
79 d = 257;
80 break;
81 case (int) SCM_BOOL_F:
82 d = 258;
83 break;
84 case (int) SCM_EOF_VAL:
85 d = 259;
86 break;
87 default:
88 d = 263; /* perhaps should be error */
0f2d19dd
JB
89 }
90 return d % n;
94a5efac
GB
91 default:
92 return 263 % n; /* perhaps should be error */
0f2d19dd
JB
93 case 0:
94 switch SCM_TYP7(obj) {
94a5efac
GB
95 default:
96 return 263 % n;
0f2d19dd
JB
97 case scm_tc7_smob:
98 switch SCM_TYP16(obj) {
950cc72b 99 case scm_tc16_big:
94a5efac
GB
100 return SCM_INUM(scm_modulo(obj, SCM_MAKINUM(n)));
101 default:
102 return 263 % n;
950cc72b
MD
103 case scm_tc16_real:
104 {
0f2d19dd
JB
105 double r = SCM_REALPART(obj);
106 if (floor(r)==r) {
107 obj = scm_inexact_to_exact (obj);
108 if SCM_IMP(obj) return SCM_INUM(obj) % n;
94a5efac 109 return SCM_INUM(scm_modulo(obj, SCM_MAKINUM(n)));
0f2d19dd
JB
110 }
111 }
950cc72b 112 case scm_tc16_complex:
0f2d19dd 113 obj = scm_number_to_string(obj, SCM_MAKINUM(10));
0f2d19dd
JB
114 }
115 case scm_tcs_symbols:
116 case scm_tc7_string:
0f2d19dd 117 case scm_tc7_substring:
0f2d19dd
JB
118 return scm_strhash(SCM_ROUCHARS(obj), (scm_sizet) SCM_ROLENGTH(obj), n);
119 case scm_tc7_wvect:
120 case scm_tc7_vector:
121 {
122 scm_sizet len = SCM_LENGTH(obj);
123 SCM *data = SCM_VELTS(obj);
124 if (len>5)
125 {
126 scm_sizet i = d/2;
127 unsigned long h = 1;
128 while (i--) h = ((h<<8) + (scm_hasher(data[h % len], n, 2))) % n;
129 return h;
130 }
131 else
132 {
133 scm_sizet i = len;
134 unsigned long h = (n)-1;
135 while (i--) h = ((h<<8) + (scm_hasher(data[i], n, d/len))) % n;
136 return h;
137 }
138 }
94a5efac
GB
139 case scm_tcs_cons_imcar:
140 case scm_tcs_cons_nimcar:
0f2d19dd
JB
141 if (d) return (scm_hasher(SCM_CAR(obj), n, d/2)+scm_hasher(SCM_CDR(obj), n, d/2)) % n;
142 else return 1;
143 case scm_tc7_port:
f1267706 144 return ((SCM_RDNG & SCM_UNPACK_CAR(obj)) ? 260 : 261) % n;
94a5efac
GB
145 case scm_tcs_closures:
146 case scm_tc7_contin:
147 case scm_tcs_subrs:
0f2d19dd
JB
148 return 262 % n;
149 }
150 }
151}
152
153
154\f
155
1cc91f1b 156
0f2d19dd 157unsigned int
1bbd0b84 158scm_ihashq (SCM obj, unsigned int n)
0f2d19dd
JB
159{
160 return (((unsigned int) obj) >> 1) % n;
161}
162
163
3b3b36dd 164SCM_DEFINE (scm_hashq, "hashq", 2, 0, 0,
94a5efac
GB
165 (SCM key, SCM size),
166 "Determine a hash value for KEY that is suitable for lookups in\n"
167 "a hashtable of size SIZE, where eq? is used as the equality\n"
168 "predicate. The function returns an integer in the range 0 to\n"
169 "SIZE - 1. NOTE that `hashq' may use internal addresses.\n"
170 "Thus two calls to hashq where the keys are eq? are not\n"
171 "guaranteed to deliver the same value if the key object gets\n"
172 "garbage collected in between. This can happen, for example\n"
3fcc798d 173 "with symbols: (hashq 'foo n) (gc) (hashq 'foo n) may produce two\n"
10d7b665 174 "different values, since 'foo will be garbage collected.")
1bbd0b84 175#define FUNC_NAME s_scm_hashq
0f2d19dd 176{
94a5efac
GB
177 SCM_VALIDATE_INUM_MIN (2, size, 0);
178 return SCM_MAKINUM (scm_ihashq (key, SCM_INUM (size)));
0f2d19dd 179}
1bbd0b84 180#undef FUNC_NAME
0f2d19dd
JB
181
182
183\f
184
1cc91f1b 185
0f2d19dd 186unsigned int
1bbd0b84 187scm_ihashv (SCM obj, unsigned int n)
0f2d19dd 188{
7866a09b
GB
189 if (SCM_CHARP(obj))
190 return ((unsigned int)(scm_downcase(SCM_CHAR(obj)))) % n; /* downcase!?!! */
0f2d19dd 191
0c95b57d 192 if (SCM_NUMP(obj))
0f2d19dd
JB
193 return (unsigned int) scm_hasher(obj, n, 10);
194 else
195 return ((unsigned int)obj) % n;
196}
197
198
3b3b36dd 199SCM_DEFINE (scm_hashv, "hashv", 2, 0, 0,
94a5efac
GB
200 (SCM key, SCM size),
201 "Determine a hash value for KEY that is suitable for lookups in\n"
202 "a hashtable of size SIZE, where eqv? is used as the equality\n"
203 "predicate. The function returns an integer in the range 0 to\n"
204 "SIZE - 1. NOTE that (hashv key) may use internal addresses.\n"
205 "Thus two calls to hashv where the keys are eqv? are not\n"
206 "guaranteed to deliver the same value if the key object gets\n"
207 "garbage collected in between. This can happen, for example\n"
3fcc798d 208 "with symbols: (hashv 'foo n) (gc) (hashv 'foo n) may produce two\n"
10d7b665 209 "different values, since 'foo will be garbage collected.")
1bbd0b84 210#define FUNC_NAME s_scm_hashv
0f2d19dd 211{
94a5efac
GB
212 SCM_VALIDATE_INUM_MIN (2, size, 0);
213 return SCM_MAKINUM (scm_ihashv (key, SCM_INUM (size)));
0f2d19dd 214}
1bbd0b84 215#undef FUNC_NAME
0f2d19dd
JB
216
217
218\f
219
1cc91f1b 220
0f2d19dd 221unsigned int
1bbd0b84 222scm_ihash (SCM obj, unsigned int n)
0f2d19dd
JB
223{
224 return (unsigned int)scm_hasher (obj, n, 10);
225}
226
3b3b36dd 227SCM_DEFINE (scm_hash, "hash", 2, 0, 0,
94a5efac
GB
228 (SCM key, SCM size),
229 "Determine a hash value for KEY that is suitable for lookups in\n"
230 "a hashtable of size SIZE, where equal? is used as the equality\n"
231 "predicate. The function returns an integer in the range 0 to\n"
232 "SIZE - 1.")
1bbd0b84 233#define FUNC_NAME s_scm_hash
0f2d19dd 234{
94a5efac
GB
235 SCM_VALIDATE_INUM_MIN (2, size, 0);
236 return SCM_MAKINUM (scm_ihash (key, SCM_INUM (size)));
0f2d19dd 237}
1bbd0b84 238#undef FUNC_NAME
0f2d19dd
JB
239
240
241\f
242
1cc91f1b 243
0f2d19dd
JB
244void
245scm_init_hash ()
0f2d19dd
JB
246{
247#include "hash.x"
248}
249