* Makefile.am (DEFS): Added. automake adds -I options to DEFS,
[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>
a0599745
MD
48#include "libguile/_scm.h"
49#include "libguile/chars.h"
50#include "libguile/ports.h"
51#include "libguile/vectors.h"
0f2d19dd 52
a0599745
MD
53#include "libguile/validate.h"
54#include "libguile/hash.h"
0f2d19dd
JB
55\f
56
57#ifndef floor
58extern double floor();
59#endif
60
1cc91f1b 61
dba97178
DH
62/* Dirk:FIXME:: why downcase for characters? (2x: scm_hasher, scm_ihashv) */
63/* Dirk:FIXME:: scm_hasher could be made static. */
64
65
0f2d19dd 66unsigned long
1bbd0b84 67scm_hasher(SCM obj, unsigned long n, scm_sizet d)
0f2d19dd 68{
dba97178
DH
69 switch (SCM_ITAG3 (obj)) {
70 case scm_tc3_int_1:
71 case scm_tc3_int_2:
94a5efac 72 return SCM_INUM(obj) % n; /* SCM_INUMP(obj) */
dba97178
DH
73 case scm_tc3_imm24:
74 if (SCM_CHARP(obj))
7866a09b 75 return (unsigned)(scm_downcase(SCM_CHAR(obj))) % n;
dba97178 76 switch (SCM_UNPACK (obj)) {
0f2d19dd 77#ifndef SICP
dba97178 78 case SCM_EOL:
94a5efac
GB
79 d = 256;
80 break;
0f2d19dd 81#endif
dba97178 82 case SCM_BOOL_T:
94a5efac
GB
83 d = 257;
84 break;
dba97178 85 case SCM_BOOL_F:
94a5efac
GB
86 d = 258;
87 break;
dba97178 88 case SCM_EOF_VAL:
94a5efac
GB
89 d = 259;
90 break;
91 default:
92 d = 263; /* perhaps should be error */
0f2d19dd
JB
93 }
94 return d % n;
94a5efac
GB
95 default:
96 return 263 % n; /* perhaps should be error */
dba97178 97 case scm_tc3_cons:
0f2d19dd 98 switch SCM_TYP7(obj) {
94a5efac
GB
99 default:
100 return 263 % n;
0f2d19dd
JB
101 case scm_tc7_smob:
102 switch SCM_TYP16(obj) {
950cc72b 103 case scm_tc16_big:
94a5efac
GB
104 return SCM_INUM(scm_modulo(obj, SCM_MAKINUM(n)));
105 default:
106 return 263 % n;
950cc72b
MD
107 case scm_tc16_real:
108 {
0f2d19dd
JB
109 double r = SCM_REALPART(obj);
110 if (floor(r)==r) {
111 obj = scm_inexact_to_exact (obj);
112 if SCM_IMP(obj) return SCM_INUM(obj) % n;
94a5efac 113 return SCM_INUM(scm_modulo(obj, SCM_MAKINUM(n)));
0f2d19dd
JB
114 }
115 }
950cc72b 116 case scm_tc16_complex:
0f2d19dd 117 obj = scm_number_to_string(obj, SCM_MAKINUM(10));
0f2d19dd
JB
118 }
119 case scm_tcs_symbols:
120 case scm_tc7_string:
0f2d19dd 121 case scm_tc7_substring:
0f2d19dd
JB
122 return scm_strhash(SCM_ROUCHARS(obj), (scm_sizet) SCM_ROLENGTH(obj), n);
123 case scm_tc7_wvect:
124 case scm_tc7_vector:
125 {
126 scm_sizet len = SCM_LENGTH(obj);
127 SCM *data = SCM_VELTS(obj);
128 if (len>5)
129 {
130 scm_sizet i = d/2;
131 unsigned long h = 1;
132 while (i--) h = ((h<<8) + (scm_hasher(data[h % len], n, 2))) % n;
133 return h;
134 }
135 else
136 {
137 scm_sizet i = len;
138 unsigned long h = (n)-1;
139 while (i--) h = ((h<<8) + (scm_hasher(data[i], n, d/len))) % n;
140 return h;
141 }
142 }
94a5efac
GB
143 case scm_tcs_cons_imcar:
144 case scm_tcs_cons_nimcar:
0f2d19dd
JB
145 if (d) return (scm_hasher(SCM_CAR(obj), n, d/2)+scm_hasher(SCM_CDR(obj), n, d/2)) % n;
146 else return 1;
147 case scm_tc7_port:
f1267706 148 return ((SCM_RDNG & SCM_UNPACK_CAR(obj)) ? 260 : 261) % n;
94a5efac
GB
149 case scm_tcs_closures:
150 case scm_tc7_contin:
151 case scm_tcs_subrs:
0f2d19dd
JB
152 return 262 % n;
153 }
154 }
155}
156
157
158\f
159
1cc91f1b 160
0f2d19dd 161unsigned int
1bbd0b84 162scm_ihashq (SCM obj, unsigned int n)
0f2d19dd 163{
54778cd3 164 return (SCM_UNPACK (obj) >> 1) % n;
0f2d19dd
JB
165}
166
167
3b3b36dd 168SCM_DEFINE (scm_hashq, "hashq", 2, 0, 0,
94a5efac
GB
169 (SCM key, SCM size),
170 "Determine a hash value for KEY that is suitable for lookups in\n"
171 "a hashtable of size SIZE, where eq? is used as the equality\n"
172 "predicate. The function returns an integer in the range 0 to\n"
173 "SIZE - 1. NOTE that `hashq' may use internal addresses.\n"
174 "Thus two calls to hashq where the keys are eq? are not\n"
175 "guaranteed to deliver the same value if the key object gets\n"
176 "garbage collected in between. This can happen, for example\n"
3fcc798d 177 "with symbols: (hashq 'foo n) (gc) (hashq 'foo n) may produce two\n"
10d7b665 178 "different values, since 'foo will be garbage collected.")
1bbd0b84 179#define FUNC_NAME s_scm_hashq
0f2d19dd 180{
94a5efac
GB
181 SCM_VALIDATE_INUM_MIN (2, size, 0);
182 return SCM_MAKINUM (scm_ihashq (key, SCM_INUM (size)));
0f2d19dd 183}
1bbd0b84 184#undef FUNC_NAME
0f2d19dd
JB
185
186
187\f
188
1cc91f1b 189
0f2d19dd 190unsigned int
1bbd0b84 191scm_ihashv (SCM obj, unsigned int n)
0f2d19dd 192{
7866a09b
GB
193 if (SCM_CHARP(obj))
194 return ((unsigned int)(scm_downcase(SCM_CHAR(obj)))) % n; /* downcase!?!! */
0f2d19dd 195
0c95b57d 196 if (SCM_NUMP(obj))
0f2d19dd
JB
197 return (unsigned int) scm_hasher(obj, n, 10);
198 else
54778cd3 199 return SCM_UNPACK (obj) % n;
0f2d19dd
JB
200}
201
202
3b3b36dd 203SCM_DEFINE (scm_hashv, "hashv", 2, 0, 0,
94a5efac
GB
204 (SCM key, SCM size),
205 "Determine a hash value for KEY that is suitable for lookups in\n"
206 "a hashtable of size SIZE, where eqv? is used as the equality\n"
207 "predicate. The function returns an integer in the range 0 to\n"
208 "SIZE - 1. NOTE that (hashv key) may use internal addresses.\n"
209 "Thus two calls to hashv where the keys are eqv? are not\n"
210 "guaranteed to deliver the same value if the key object gets\n"
211 "garbage collected in between. This can happen, for example\n"
3fcc798d 212 "with symbols: (hashv 'foo n) (gc) (hashv 'foo n) may produce two\n"
10d7b665 213 "different values, since 'foo will be garbage collected.")
1bbd0b84 214#define FUNC_NAME s_scm_hashv
0f2d19dd 215{
94a5efac
GB
216 SCM_VALIDATE_INUM_MIN (2, size, 0);
217 return SCM_MAKINUM (scm_ihashv (key, SCM_INUM (size)));
0f2d19dd 218}
1bbd0b84 219#undef FUNC_NAME
0f2d19dd
JB
220
221
222\f
223
1cc91f1b 224
0f2d19dd 225unsigned int
1bbd0b84 226scm_ihash (SCM obj, unsigned int n)
0f2d19dd
JB
227{
228 return (unsigned int)scm_hasher (obj, n, 10);
229}
230
3b3b36dd 231SCM_DEFINE (scm_hash, "hash", 2, 0, 0,
94a5efac
GB
232 (SCM key, SCM size),
233 "Determine a hash value for KEY that is suitable for lookups in\n"
234 "a hashtable of size SIZE, where equal? is used as the equality\n"
235 "predicate. The function returns an integer in the range 0 to\n"
236 "SIZE - 1.")
1bbd0b84 237#define FUNC_NAME s_scm_hash
0f2d19dd 238{
94a5efac
GB
239 SCM_VALIDATE_INUM_MIN (2, size, 0);
240 return SCM_MAKINUM (scm_ihash (key, SCM_INUM (size)));
0f2d19dd 241}
1bbd0b84 242#undef FUNC_NAME
0f2d19dd
JB
243
244
245\f
246
1cc91f1b 247
0f2d19dd
JB
248void
249scm_init_hash ()
0f2d19dd 250{
a0599745 251#include "libguile/hash.x"
0f2d19dd
JB
252}
253
89e00824
ML
254
255/*
256 Local Variables:
257 c-file-style: "gnu"
258 End:
259*/