Merge remote-tracking branch 'origin/stable-2.0'
[bpt/guile.git] / libguile / eq.c
CommitLineData
2e6e1933 1/* Copyright (C) 1995,1996,1997,1998,2000,2001,2003, 2004, 2006, 2009, 2010, 2011 Free Software Foundation, Inc.
0f2d19dd 2 *
73be1d9e 3 * This library is free software; you can redistribute it and/or
53befeb7
NJ
4 * modify it under the terms of the GNU Lesser General Public License
5 * as published by the Free Software Foundation; either version 3 of
6 * the License, or (at your option) any later version.
0f2d19dd 7 *
53befeb7
NJ
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
0f2d19dd 12 *
73be1d9e
MV
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
53befeb7
NJ
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301 USA
73be1d9e 17 */
1bbd0b84 18
0f2d19dd 19\f
dbb605f5 20#ifdef HAVE_CONFIG_H
1f4d02c2
RB
21# include <config.h>
22#endif
9540b68f 23
2e6e1933
MW
24#include <math.h>
25
a0599745 26#include "libguile/_scm.h"
5d1b3b2d 27#include "libguile/array-map.h"
a0599745
MD
28#include "libguile/stackchk.h"
29#include "libguile/strorder.h"
30#include "libguile/async.h"
31#include "libguile/root.h"
32#include "libguile/smob.h"
2fa901a5 33#include "libguile/arrays.h"
a0599745 34#include "libguile/vectors.h"
c99de5aa 35#include "libguile/hashtab.h"
807e5a66 36#include "libguile/bytevectors.h"
0f2d19dd 37
d15ad007
LC
38#include "libguile/struct.h"
39#include "libguile/goops.h"
d15ad007 40
a0599745
MD
41#include "libguile/validate.h"
42#include "libguile/eq.h"
22fc179a
HWN
43
44#include "libguile/private-options.h"
45
0f2d19dd 46\f
9540b68f
GH
47
48#ifdef HAVE_STRING_H
49#include <string.h>
50#endif
51\f
52
f1d19308 53static SCM scm_i_eq_p (SCM x, SCM y, SCM rest);
8a1f4f98
AW
54SCM_DEFINE (scm_i_eq_p, "eq?", 0, 2, 1,
55 (SCM x, SCM y, SCM rest),
602d32dd
KR
56 "Return @code{#t} if @var{x} and @var{y} are the same object,\n"
57 "except for numbers and characters. For example,\n"
58 "\n"
59 "@example\n"
60 "(define x (vector 1 2 3))\n"
61 "(define y (vector 1 2 3))\n"
62 "\n"
63 "(eq? x x) @result{} #t\n"
64 "(eq? x y) @result{} #f\n"
65 "@end example\n"
66 "\n"
67 "Numbers and characters are not equal to any other object, but\n"
68 "the problem is they're not necessarily @code{eq?} to themselves\n"
69 "either. This is even so when the number comes directly from a\n"
70 "variable,\n"
71 "\n"
72 "@example\n"
73 "(let ((n (+ 2 3)))\n"
74 " (eq? n n)) @result{} *unspecified*\n"
75 "@end example\n"
76 "\n"
77 "Generally @code{eqv?} should be used when comparing numbers or\n"
78 "characters. @code{=} or @code{char=?} can be used too.\n"
79 "\n"
4450a227
KR
80 "It's worth noting that end-of-list @code{()}, @code{#t},\n"
81 "@code{#f}, a symbol of a given name, and a keyword of a given\n"
82 "name, are unique objects. There's just one of each, so for\n"
83 "instance no matter how @code{()} arises in a program, it's the\n"
84 "same object and can be compared with @code{eq?},\n"
602d32dd
KR
85 "\n"
86 "@example\n"
87 "(define x (cdr '(123)))\n"
88 "(define y (cdr '(456)))\n"
89 "(eq? x y) @result{} #t\n"
90 "\n"
4450a227 91 "(define x (string->symbol \"foo\"))\n"
602d32dd
KR
92 "(eq? x 'foo) @result{} #t\n"
93 "@end example")
8a1f4f98 94#define FUNC_NAME s_scm_i_eq_p
0f2d19dd 95{
8a1f4f98
AW
96 if (SCM_UNBNDP (x) || SCM_UNBNDP (y))
97 return SCM_BOOL_T;
98 while (scm_is_pair (rest))
99 {
100 if (!scm_is_eq (x, y))
101 return SCM_BOOL_F;
102 x = y;
103 y = scm_car (rest);
104 rest = scm_cdr (rest);
105 }
bc36d050 106 return scm_from_bool (scm_is_eq (x, y));
0f2d19dd 107}
1bbd0b84 108#undef FUNC_NAME
0f2d19dd 109
8a1f4f98
AW
110SCM
111scm_eq_p (SCM x, SCM y)
112{
113 return scm_from_bool (scm_is_eq (x, y));
114}
115
96d00047
MV
116/* We compare doubles in a special way for 'eqv?' to be able to
117 distinguish plus and minus zero and to identify NaNs.
118*/
119
120static int
121real_eqv (double x, double y)
122{
2e6e1933
MW
123 return !memcmp (&x, &y, sizeof(double))
124 || (SCM_UNLIKELY (isnan (x)) && SCM_UNLIKELY (isnan (y)));
125}
126
127SCM
128scm_real_equalp (SCM x, SCM y)
129{
130 return scm_from_bool (real_eqv (SCM_REAL_VALUE (x),
131 SCM_REAL_VALUE (y)));
132}
133
134SCM
135scm_bigequal (SCM x, SCM y)
136{
137 return scm_from_bool (scm_i_bigcmp (x, y) == 0);
138}
139
140SCM
141scm_complex_equalp (SCM x, SCM y)
142{
143 return scm_from_bool (real_eqv (SCM_COMPLEX_REAL (x),
144 SCM_COMPLEX_REAL (y))
145 && real_eqv (SCM_COMPLEX_IMAG (x),
146 SCM_COMPLEX_IMAG (y)));
147}
148
149SCM
150scm_i_fraction_equalp (SCM x, SCM y)
151{
152 return scm_from_bool
153 (scm_is_true (scm_equal_p (SCM_FRACTION_NUMERATOR (x),
154 SCM_FRACTION_NUMERATOR (y)))
155 && scm_is_true (scm_equal_p (SCM_FRACTION_DENOMINATOR (x),
156 SCM_FRACTION_DENOMINATOR (y))));
96d00047 157}
0f2d19dd 158
f1d19308 159static SCM scm_i_eqv_p (SCM x, SCM y, SCM rest);
f92e85f7 160#include <stdio.h>
8a1f4f98
AW
161SCM_DEFINE (scm_i_eqv_p, "eqv?", 0, 2, 1,
162 (SCM x, SCM y, SCM rest),
602d32dd
KR
163 "Return @code{#t} if @var{x} and @var{y} are the same object, or\n"
164 "for characters and numbers the same value.\n"
165 "\n"
166 "On objects except characters and numbers, @code{eqv?} is the\n"
167 "same as @code{eq?}, it's true if @var{x} and @var{y} are the\n"
168 "same object.\n"
169 "\n"
170 "If @var{x} and @var{y} are numbers or characters, @code{eqv?}\n"
171 "compares their type and value. An exact number is not\n"
172 "@code{eqv?} to an inexact number (even if their value is the\n"
173 "same).\n"
174 "\n"
175 "@example\n"
176 "(eqv? 3 (+ 1 2)) @result{} #t\n"
177 "(eqv? 1 1.0) @result{} #f\n"
178 "@end example")
8a1f4f98
AW
179#define FUNC_NAME s_scm_i_eqv_p
180{
181 if (SCM_UNBNDP (x) || SCM_UNBNDP (y))
182 return SCM_BOOL_T;
183 while (!scm_is_null (rest))
184 {
185 if (!scm_is_true (scm_eqv_p (x, y)))
186 return SCM_BOOL_F;
187 x = y;
188 y = scm_car (rest);
189 rest = scm_cdr (rest);
190 }
191 return scm_eqv_p (x, y);
192}
193#undef FUNC_NAME
194
195SCM scm_eqv_p (SCM x, SCM y)
196#define FUNC_NAME s_scm_i_eqv_p
0f2d19dd 197{
bc36d050 198 if (scm_is_eq (x, y))
950cc72b
MD
199 return SCM_BOOL_T;
200 if (SCM_IMP (x))
201 return SCM_BOOL_F;
202 if (SCM_IMP (y))
203 return SCM_BOOL_F;
f92e85f7 204
2e6e1933 205 /* this ensures that types and scm_length are the same. */
fbd485ba 206 if (SCM_CELL_TYPE (x) != SCM_CELL_TYPE (y))
2e6e1933
MW
207 return SCM_BOOL_F;
208 switch (SCM_TYP7 (x))
950cc72b 209 {
2e6e1933
MW
210 default:
211 break;
212 case scm_tc7_number:
213 switch SCM_TYP16 (x)
214 {
215 case scm_tc16_big:
216 return scm_bigequal (x, y);
217 case scm_tc16_real:
218 return scm_real_equalp (x, y);
219 case scm_tc16_complex:
220 return scm_complex_equalp (x, y);
221 case scm_tc16_fraction:
222 return scm_i_fraction_equalp (x, y);
223 }
950cc72b 224 }
ab455d1f 225 return SCM_BOOL_F;
0f2d19dd 226}
1bbd0b84 227#undef FUNC_NAME
0f2d19dd
JB
228
229
f1d19308 230static SCM scm_i_equal_p (SCM, SCM, SCM);
8a1f4f98
AW
231SCM_PRIMITIVE_GENERIC (scm_i_equal_p, "equal?", 0, 2, 1,
232 (SCM x, SCM y, SCM rest),
233 "Return @code{#t} if @var{x} and @var{y} are the same type, and\n"
234 "their contents or value are equal.\n"
235 "\n"
236 "For a pair, string, vector or array, @code{equal?} compares the\n"
237 "contents, and does so using using the same @code{equal?}\n"
238 "recursively, so a deep structure can be traversed.\n"
239 "\n"
240 "@example\n"
241 "(equal? (list 1 2 3) (list 1 2 3)) @result{} #t\n"
242 "(equal? (list 1 2 3) (vector 1 2 3)) @result{} #f\n"
243 "@end example\n"
244 "\n"
245 "For other objects, @code{equal?} compares as per @code{eqv?},\n"
246 "which means characters and numbers are compared by type and\n"
247 "value (and like @code{eqv?}, exact and inexact numbers are not\n"
248 "@code{equal?}, even if their value is the same).\n"
249 "\n"
250 "@example\n"
251 "(equal? 3 (+ 1 2)) @result{} #t\n"
252 "(equal? 1 1.0) @result{} #f\n"
253 "@end example\n"
254 "\n"
255 "Hash tables are currently only compared as per @code{eq?}, so\n"
256 "two different tables are not @code{equal?}, even if their\n"
257 "contents are the same.\n"
258 "\n"
259 "@code{equal?} does not support circular data structures, it may\n"
260 "go into an infinite loop if asked to compare two circular lists\n"
261 "or similar.\n"
262 "\n"
263 "New application-defined object types (Smobs) have an\n"
264 "@code{equalp} handler which is called by @code{equal?}. This\n"
265 "lets an application traverse the contents or control what is\n"
266 "considered @code{equal?} for two such objects. If there's no\n"
267 "handler, the default is to just compare as per @code{eq?}.")
268#define FUNC_NAME s_scm_i_equal_p
269{
270 if (SCM_UNBNDP (x) || SCM_UNBNDP (y))
271 return SCM_BOOL_T;
272 while (!scm_is_null (rest))
273 {
274 if (!scm_is_true (scm_equal_p (x, y)))
275 return SCM_BOOL_F;
276 x = y;
277 y = scm_car (rest);
278 rest = SCM_CDR (rest);
279 }
280 return scm_equal_p (x, y);
281}
282#undef FUNC_NAME
283
284SCM
285scm_equal_p (SCM x, SCM y)
286#define FUNC_NAME s_scm_i_equal_p
0f2d19dd
JB
287{
288 SCM_CHECK_STACK;
950cc72b
MD
289 tailrecurse:
290 SCM_TICK;
bc36d050 291 if (scm_is_eq (x, y))
950cc72b
MD
292 return SCM_BOOL_T;
293 if (SCM_IMP (x))
294 return SCM_BOOL_F;
295 if (SCM_IMP (y))
296 return SCM_BOOL_F;
d2e53ed6 297 if (scm_is_pair (x) && scm_is_pair (y))
950cc72b 298 {
7888309b 299 if (scm_is_false (scm_equal_p (SCM_CAR (x), SCM_CAR (y))))
950cc72b
MD
300 return SCM_BOOL_F;
301 x = SCM_CDR(x);
302 y = SCM_CDR(y);
303 goto tailrecurse;
304 }
baa84a20 305 if (SCM_TYP7 (x) == scm_tc7_string && SCM_TYP7 (y) == scm_tc7_string)
950cc72b 306 return scm_string_equal_p (x, y);
807e5a66
LC
307 if (SCM_TYP7 (x) == scm_tc7_bytevector && SCM_TYP7 (y) == scm_tc7_bytevector)
308 return scm_bytevector_eq_p (x, y);
789d2fc8
MV
309 if (SCM_TYP7 (x) == scm_tc7_smob && SCM_TYP16 (x) == SCM_TYP16 (y))
310 {
311 int i = SCM_SMOBNUM (x);
312 if (!(i < scm_numsmob))
313 return SCM_BOOL_F;
314 if (scm_smobs[i].equalp)
315 return (scm_smobs[i].equalp) (x, y);
316 else
317 goto generic_equal;
318 }
cb2d8076
LC
319 if (SCM_POINTER_P (x) && SCM_POINTER_P (y))
320 return scm_from_bool (SCM_POINTER_VALUE (x) == SCM_POINTER_VALUE (y));
321
950cc72b 322 /* This ensures that types and scm_length are the same. */
fbd485ba 323 if (SCM_CELL_TYPE (x) != SCM_CELL_TYPE (y))
950cc72b 324 {
af4f8612
MV
325 /* Vectors can be equal to one-dimensional arrays.
326 */
a587d6a9 327 if (scm_is_array (x) && scm_is_array (y))
af4f8612
MV
328 return scm_array_equal_p (x, y);
329
950cc72b
MD
330 return SCM_BOOL_F;
331 }
332 switch (SCM_TYP7 (x))
333 {
334 default:
f135fc3e
MW
335 /* Check equality between structs of equal type (see cell-type test above). */
336 if (SCM_STRUCTP (x))
337 {
338 if (SCM_INSTANCEP (x))
339 goto generic_equal;
340 else
341 return scm_i_struct_equalp (x, y);
342 }
a48d60b1 343 break;
534c55a9
DH
344 case scm_tc7_number:
345 switch SCM_TYP16 (x)
346 {
347 case scm_tc16_big:
348 return scm_bigequal (x, y);
349 case scm_tc16_real:
350 return scm_real_equalp (x, y);
351 case scm_tc16_complex:
352 return scm_complex_equalp (x, y);
f92e85f7
MV
353 case scm_tc16_fraction:
354 return scm_i_fraction_equalp (x, y);
534c55a9 355 }
950cc72b
MD
356 case scm_tc7_vector:
357 case scm_tc7_wvect:
354116f7 358 return scm_i_vector_equal_p (x, y);
950cc72b 359 }
d15ad007 360
ab455d1f
AW
361 /* Otherwise just return false. Dispatching to the generic is the wrong thing
362 here, as we can hit this case for any two objects of the same type that we
363 think are distinct, like different symbols. */
364 return SCM_BOOL_F;
365
789d2fc8 366 generic_equal:
8a1f4f98 367 if (SCM_UNPACK (g_scm_i_equal_p))
fa075d40 368 return scm_call_2 (g_scm_i_equal_p, x, y);
a48d60b1
MD
369 else
370 return SCM_BOOL_F;
0f2d19dd 371}
1bbd0b84 372#undef FUNC_NAME
0f2d19dd
JB
373
374
375\f
376
377
1cc91f1b 378
0f2d19dd
JB
379void
380scm_init_eq ()
0f2d19dd 381{
a0599745 382#include "libguile/eq.x"
0f2d19dd
JB
383}
384
89e00824
ML
385
386/*
387 Local Variables:
388 c-file-style: "gnu"
389 End:
390*/