* numbers.c (scm_make_complex), gc-card.c (scm_i_sweep_card): Use
[bpt/guile.git] / libguile / eq.c
CommitLineData
6b412e91 1/* Copyright (C) 1995,1996,1997,1998,2000,2001,2003 Free Software Foundation, Inc.
0f2d19dd 2 *
73be1d9e
MV
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
0f2d19dd 7 *
73be1d9e
MV
8 * This library 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 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
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
1bbd0b84 17
0f2d19dd 18\f
1f4d02c2
RB
19#if HAVE_CONFIG_H
20# include <config.h>
21#endif
9540b68f 22
a0599745
MD
23#include "libguile/_scm.h"
24#include "libguile/ramap.h"
25#include "libguile/stackchk.h"
26#include "libguile/strorder.h"
27#include "libguile/async.h"
28#include "libguile/root.h"
29#include "libguile/smob.h"
30#include "libguile/unif.h"
31#include "libguile/vectors.h"
0f2d19dd 32
a0599745
MD
33#include "libguile/validate.h"
34#include "libguile/eq.h"
0f2d19dd 35\f
9540b68f
GH
36
37#ifdef HAVE_STRING_H
38#include <string.h>
39#endif
40\f
41
c3ee7520 42SCM_DEFINE1 (scm_eq_p, "eq?", scm_tc7_rpsubr,
1bbd0b84 43 (SCM x, SCM y),
cdbc7418
NJ
44 "Return @code{#t} iff @var{x} references the same object as @var{y}.\n"
45 "@code{eq?} is similar to @code{eqv?} except that in some cases it is\n"
46 "capable of discerning distinctions finer than those detectable by\n"
47 "@code{eqv?}.")
1bbd0b84 48#define FUNC_NAME s_scm_eq_p
0f2d19dd 49{
fbd485ba 50 return SCM_BOOL (SCM_EQ_P (x, y));
0f2d19dd 51}
1bbd0b84 52#undef FUNC_NAME
0f2d19dd 53
96d00047
MV
54/* We compare doubles in a special way for 'eqv?' to be able to
55 distinguish plus and minus zero and to identify NaNs.
56*/
57
58static int
59real_eqv (double x, double y)
60{
61 return !memcmp (&x, &y, sizeof(double));
62}
0f2d19dd 63
47cd67db 64SCM_PRIMITIVE_GENERIC_1 (scm_eqv_p, "eqv?", scm_tc7_rpsubr,
1bbd0b84 65 (SCM x, SCM y),
cdbc7418
NJ
66 "The @code{eqv?} procedure defines a useful equivalence relation on objects.\n"
67 "Briefly, it returns @code{#t} if @var{x} and @var{y} should normally be\n"
68 "regarded as the same object. This relation is left slightly open to\n"
69 "interpretation, but works for comparing immediate integers, characters,\n"
70 "and inexact numbers.")
1bbd0b84 71#define FUNC_NAME s_scm_eqv_p
0f2d19dd 72{
fbd485ba 73 if (SCM_EQ_P (x, y))
950cc72b
MD
74 return SCM_BOOL_T;
75 if (SCM_IMP (x))
76 return SCM_BOOL_F;
77 if (SCM_IMP (y))
78 return SCM_BOOL_F;
0f2d19dd 79 /* this ensures that types and scm_length are the same. */
fbd485ba 80 if (SCM_CELL_TYPE (x) != SCM_CELL_TYPE (y))
950cc72b
MD
81 {
82 /* treat mixes of real and complex types specially */
6b412e91 83 if (SCM_INEXACTP (x))
950cc72b 84 {
6b412e91
DH
85 if (SCM_REALP (x))
86 return SCM_BOOL (SCM_COMPLEXP (y)
96d00047
MV
87 && real_eqv (SCM_REAL_VALUE (x),
88 SCM_COMPLEX_REAL (y))
6b412e91 89 && SCM_COMPLEX_IMAG (y) == 0.0);
950cc72b 90 else
6b412e91 91 return SCM_BOOL (SCM_REALP (y)
96d00047
MV
92 && real_eqv (SCM_COMPLEX_REAL (x),
93 SCM_REAL_VALUE (y))
950cc72b
MD
94 && SCM_COMPLEX_IMAG (x) == 0.0);
95 }
96 return SCM_BOOL_F;
97 }
98 if (SCM_NUMP (x))
99 {
eb42e2f0 100 if (SCM_BIGP (x)) {
6b412e91
DH
101 return SCM_BOOL (scm_i_bigcmp (x, y) == 0);
102 } else if (SCM_REALP (x)) {
96d00047 103 return SCM_BOOL (real_eqv (SCM_REAL_VALUE (x), SCM_REAL_VALUE (y)));
eb42e2f0 104 } else { /* complex */
96d00047
MV
105 return SCM_BOOL (real_eqv (SCM_COMPLEX_REAL (x),
106 SCM_COMPLEX_REAL (y))
107 && real_eqv (SCM_COMPLEX_IMAG (x),
108 SCM_COMPLEX_IMAG (y)));
eb42e2f0 109 }
950cc72b 110 }
47cd67db
MD
111 if (SCM_UNPACK (g_scm_eqv_p))
112 return scm_call_generic_2 (g_scm_eqv_p, x, y);
113 else
114 return SCM_BOOL_F;
0f2d19dd 115}
1bbd0b84 116#undef FUNC_NAME
0f2d19dd
JB
117
118
a48d60b1
MD
119SCM_PRIMITIVE_GENERIC_1 (scm_equal_p, "equal?", scm_tc7_rpsubr,
120 (SCM x, SCM y),
121 "Return @code{#t} iff @var{x} and @var{y} are recursively @code{eqv?} equivalent.\n"
122 "@code{equal?} recursively compares the contents of pairs,\n"
123 "vectors, and strings, applying @code{eqv?} on other objects such as\n"
124 "numbers and symbols. A rule of thumb is that objects are generally\n"
125 "@code{equal?} if they print the same. @code{equal?} may fail to\n"
126 "terminate if its arguments are circular data structures.")
1bbd0b84 127#define FUNC_NAME s_scm_equal_p
0f2d19dd
JB
128{
129 SCM_CHECK_STACK;
950cc72b
MD
130 tailrecurse:
131 SCM_TICK;
fbd485ba 132 if (SCM_EQ_P (x, y))
950cc72b
MD
133 return SCM_BOOL_T;
134 if (SCM_IMP (x))
135 return SCM_BOOL_F;
136 if (SCM_IMP (y))
137 return SCM_BOOL_F;
22a52da1 138 if (SCM_CONSP (x) && SCM_CONSP (y))
950cc72b
MD
139 {
140 if (SCM_FALSEP (scm_equal_p (SCM_CAR (x), SCM_CAR (y))))
141 return SCM_BOOL_F;
142 x = SCM_CDR(x);
143 y = SCM_CDR(y);
144 goto tailrecurse;
145 }
baa84a20 146 if (SCM_TYP7 (x) == scm_tc7_string && SCM_TYP7 (y) == scm_tc7_string)
950cc72b
MD
147 return scm_string_equal_p (x, y);
148 /* This ensures that types and scm_length are the same. */
fbd485ba 149 if (SCM_CELL_TYPE (x) != SCM_CELL_TYPE (y))
950cc72b
MD
150 {
151 /* treat mixes of real and complex types specially */
6b412e91 152 if (SCM_INEXACTP (x))
950cc72b 153 {
6b412e91
DH
154 if (SCM_REALP (x))
155 return SCM_BOOL (SCM_COMPLEXP (y)
950cc72b 156 && SCM_REAL_VALUE (x) == SCM_COMPLEX_REAL (y)
6b412e91 157 && SCM_COMPLEX_IMAG (y) == 0.0);
950cc72b 158 else
6b412e91 159 return SCM_BOOL (SCM_REALP (y)
950cc72b
MD
160 && SCM_COMPLEX_REAL (x) == SCM_REAL_VALUE (y)
161 && SCM_COMPLEX_IMAG (x) == 0.0);
0f2d19dd 162 }
950cc72b
MD
163 return SCM_BOOL_F;
164 }
165 switch (SCM_TYP7 (x))
166 {
167 default:
a48d60b1 168 break;
950cc72b
MD
169 case scm_tc7_vector:
170 case scm_tc7_wvect:
171 return scm_vector_equal_p (x, y);
172 case scm_tc7_smob:
173 {
174 int i = SCM_SMOBNUM (x);
175 if (!(i < scm_numsmob))
176 return SCM_BOOL_F;
177 if (scm_smobs[i].equalp)
178 return (scm_smobs[i].equalp) (x, y);
179 else
a48d60b1 180 break;
950cc72b 181 }
1a603dc0 182#if SCM_HAVE_ARRAYS
950cc72b
MD
183 case scm_tc7_bvect: case scm_tc7_uvect: case scm_tc7_ivect:
184 case scm_tc7_fvect: case scm_tc7_cvect: case scm_tc7_dvect:
185 case scm_tc7_svect:
1f4d02c2 186#if SCM_SIZEOF_LONG_LONG != 0
950cc72b 187 case scm_tc7_llvect:
0f2d19dd 188#endif
950cc72b 189 case scm_tc7_byvect:
7a7f7c53 190 if (scm_tc16_array && scm_smobs[SCM_TC2SMOBNUM (scm_tc16_array)].equalp)
950cc72b 191 return scm_array_equal_p (x, y);
afe5177e 192#endif
950cc72b 193 }
a48d60b1
MD
194 if (SCM_UNPACK (g_scm_equal_p))
195 return scm_call_generic_2 (g_scm_equal_p, x, y);
196 else
197 return SCM_BOOL_F;
0f2d19dd 198}
1bbd0b84 199#undef FUNC_NAME
0f2d19dd
JB
200
201
202\f
203
204
1cc91f1b 205
0f2d19dd
JB
206void
207scm_init_eq ()
0f2d19dd 208{
a0599745 209#include "libguile/eq.x"
0f2d19dd
JB
210}
211
89e00824
ML
212
213/*
214 Local Variables:
215 c-file-style: "gnu"
216 End:
217*/