1 /* Copyright (C) 1995,1996,1997,1998,2000,2001,2003, 2004, 2006, 2009, 2010, 2011 Free Software Foundation, Inc.
2  *
3  * This library is free software; you can redistribute it and/or
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.
7  *
8  * This library is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * Lesser General Public License for more details.
12  *
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
15  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16  * 02110-1301 USA
17  */
18 
19 
20 #ifdef HAVE_CONFIG_H
21 #  include <config.h>
22 #endif
23 
24 #include <math.h>
25 
26 #include "libguile/_scm.h"
27 #include "libguile/array-map.h"
28 #include "libguile/stackchk.h"
29 #include "libguile/strorder.h"
30 #include "libguile/async.h"
31 #include "libguile/smob.h"
32 #include "libguile/arrays.h"
33 #include "libguile/vectors.h"
34 #include "libguile/hashtab.h"
35 #include "libguile/bytevectors.h"
36 #include "libguile/syntax.h"
37 
38 #include "libguile/struct.h"
39 #include "libguile/goops.h"
40 
41 #include "libguile/validate.h"
42 #include "libguile/eq.h"
43 
44 #include "libguile/private-options.h"
45 
46 
47 
48 #ifdef HAVE_STRING_H
49 #include <string.h>
50 #endif
51 
52 
53 static SCM scm_i_eq_p (SCM x, SCM y, SCM rest);
54 SCM_DEFINE (scm_i_eq_p, "eq?", 0, 2, 1,
55             (SCM x, SCM y, SCM rest),
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"
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"
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"
91 	    "(define x (string->symbol \"foo\"))\n"
92 	    "(eq? x 'foo) @result{} #t\n"
93 	    "@end example")
94 #define FUNC_NAME s_scm_i_eq_p
95 {
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     }
106   return scm_from_bool (scm_is_eq (x, y));
107 }
108 #undef FUNC_NAME
109 
110 SCM
scm_eq_p(SCM x,SCM y)111 scm_eq_p (SCM x, SCM y)
112 {
113   return scm_from_bool (scm_is_eq (x, y));
114 }
115 
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 
120 static int
real_eqv(double x,double y)121 real_eqv (double x, double y)
122 {
123   return !memcmp (&x, &y, sizeof(double))
124     || (SCM_UNLIKELY (isnan (x)) && SCM_UNLIKELY (isnan (y)));
125 }
126 
127 SCM
scm_real_equalp(SCM x,SCM y)128 scm_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 
134 SCM
scm_bigequal(SCM x,SCM y)135 scm_bigequal (SCM x, SCM y)
136 {
137   return scm_from_bool (scm_i_bigcmp (x, y) == 0);
138 }
139 
140 SCM
scm_complex_equalp(SCM x,SCM y)141 scm_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 
149 SCM
scm_i_fraction_equalp(SCM x,SCM y)150 scm_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))));
157 }
158 
159 static SCM scm_i_eqv_p (SCM x, SCM y, SCM rest);
160 #include <stdio.h>
161 SCM_DEFINE (scm_i_eqv_p, "eqv?", 0, 2, 1,
162             (SCM x, SCM y, SCM rest),
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")
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 
scm_eqv_p(SCM x,SCM y)195 SCM scm_eqv_p (SCM x, SCM y)
196 #define FUNC_NAME s_scm_i_eqv_p
197 {
198   if (scm_is_eq (x, y))
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;
204 
205   /* this ensures that types and scm_length are the same. */
206   if (SCM_CELL_TYPE (x) != SCM_CELL_TYPE (y))
207     return SCM_BOOL_F;
208   switch (SCM_TYP7 (x))
209     {
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         }
224     }
225   return SCM_BOOL_F;
226 }
227 #undef FUNC_NAME
228 
229 
230 static SCM scm_i_equal_p (SCM, SCM, SCM);
231 SCM_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 
284 SCM
scm_equal_p(SCM x,SCM y)285 scm_equal_p (SCM x, SCM y)
286 #define FUNC_NAME s_scm_i_equal_p
287 {
288   SCM_CHECK_STACK;
289  tailrecurse:
290   SCM_TICK;
291   if (scm_is_eq (x, y))
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;
297   if (scm_is_pair (x) && scm_is_pair (y))
298     {
299       if (scm_is_false (scm_equal_p (SCM_CAR (x), SCM_CAR (y))))
300 	return SCM_BOOL_F;
301       x = SCM_CDR(x);
302       y = SCM_CDR(y);
303       goto tailrecurse;
304     }
305   if (SCM_TYP7 (x) == scm_tc7_smob && SCM_TYP16 (x) == SCM_TYP16 (y))
306     {
307       int i = SCM_SMOBNUM (x);
308       if (!(i < scm_numsmob))
309 	return SCM_BOOL_F;
310       if (scm_smobs[i].equalp)
311 	return (scm_smobs[i].equalp) (x, y);
312       else
313 	goto generic_equal;
314     }
315 
316   /* This ensures that types and scm_length are the same.  */
317   if (SCM_CELL_TYPE (x) != SCM_CELL_TYPE (y))
318     {
319       /* Vectors can be equal to one-dimensional arrays.
320        */
321       if (scm_is_array (x) && scm_is_array (y))
322 	return scm_array_equal_p (x, y);
323 
324       return SCM_BOOL_F;
325     }
326   switch (SCM_TYP7 (x))
327     {
328     default:
329       /* Check equality between structs of equal type (see cell-type test above). */
330       if (SCM_STRUCTP (x))
331 	{
332 	  if (SCM_INSTANCEP (x))
333 	    goto generic_equal;
334 	  else
335 	    return scm_i_struct_equalp (x, y);
336 	}
337       break;
338     case scm_tc7_number:
339       switch SCM_TYP16 (x)
340         {
341         case scm_tc16_big:
342           return scm_bigequal (x, y);
343         case scm_tc16_real:
344           return scm_real_equalp (x, y);
345         case scm_tc16_complex:
346           return scm_complex_equalp (x, y);
347 	case scm_tc16_fraction:
348           return scm_i_fraction_equalp (x, y);
349         default:
350           /* assert not reached? */
351           return SCM_BOOL_F;
352         }
353     case scm_tc7_pointer:
354       return scm_from_bool (SCM_POINTER_VALUE (x) == SCM_POINTER_VALUE (y));
355     case scm_tc7_string:
356       return scm_string_equal_p (x, y);
357     case scm_tc7_bytevector:
358       return scm_bytevector_eq_p (x, y);
359     case scm_tc7_array:
360       return scm_array_equal_p (x, y);
361     case scm_tc7_bitvector:
362       return scm_i_bitvector_equal_p (x, y);
363     case scm_tc7_vector:
364     case scm_tc7_wvect:
365       return scm_i_vector_equal_p (x, y);
366     case scm_tc7_syntax:
367       if (scm_is_false (scm_equal_p (scm_syntax_wrap (x),
368                                      scm_syntax_wrap (y))))
369         return SCM_BOOL_F;
370       if (scm_is_false (scm_equal_p (scm_syntax_module (x),
371                                      scm_syntax_module (y))))
372         return SCM_BOOL_F;
373       x = scm_syntax_expression (x);
374       y = scm_syntax_expression (y);
375       goto tailrecurse;
376     }
377 
378   /* Otherwise just return false. Dispatching to the generic is the wrong thing
379      here, as we can hit this case for any two objects of the same type that we
380      think are distinct, like different symbols. */
381   return SCM_BOOL_F;
382 
383  generic_equal:
384   if (SCM_UNPACK (g_scm_i_equal_p))
385     return scm_call_2 (g_scm_i_equal_p, x, y);
386   else
387     return SCM_BOOL_F;
388 }
389 #undef FUNC_NAME
390 
391 
392 
393 
394 
395 
396 void
scm_init_eq()397 scm_init_eq ()
398 {
399 #include "libguile/eq.x"
400 }
401 
402 
403 /*
404   Local Variables:
405   c-file-style: "gnu"
406   End:
407 */
408