* session.scm (apropos): Use hash-for-each instead of
[bpt/guile.git] / libguile / eq.c
CommitLineData
22a52da1 1/* Copyright (C) 1995,1996,1997,1998,2000,2001 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 41
0f2d19dd 42\f
9540b68f 43
a0599745
MD
44#include "libguile/_scm.h"
45#include "libguile/ramap.h"
46#include "libguile/stackchk.h"
47#include "libguile/strorder.h"
48#include "libguile/async.h"
49#include "libguile/root.h"
50#include "libguile/smob.h"
51#include "libguile/unif.h"
52#include "libguile/vectors.h"
0f2d19dd 53
a0599745
MD
54#include "libguile/validate.h"
55#include "libguile/eq.h"
0f2d19dd 56\f
9540b68f
GH
57
58#ifdef HAVE_STRING_H
59#include <string.h>
60#endif
61\f
62
c3ee7520 63SCM_DEFINE1 (scm_eq_p, "eq?", scm_tc7_rpsubr,
1bbd0b84 64 (SCM x, SCM y),
cdbc7418
NJ
65 "Return @code{#t} iff @var{x} references the same object as @var{y}.\n"
66 "@code{eq?} is similar to @code{eqv?} except that in some cases it is\n"
67 "capable of discerning distinctions finer than those detectable by\n"
68 "@code{eqv?}.")
1bbd0b84 69#define FUNC_NAME s_scm_eq_p
0f2d19dd 70{
fbd485ba 71 return SCM_BOOL (SCM_EQ_P (x, y));
0f2d19dd 72}
1bbd0b84 73#undef FUNC_NAME
0f2d19dd 74
96d00047
MV
75/* We compare doubles in a special way for 'eqv?' to be able to
76 distinguish plus and minus zero and to identify NaNs.
77*/
78
79static int
80real_eqv (double x, double y)
81{
82 return !memcmp (&x, &y, sizeof(double));
83}
0f2d19dd 84
c3ee7520 85SCM_DEFINE1 (scm_eqv_p, "eqv?", scm_tc7_rpsubr,
1bbd0b84 86 (SCM x, SCM y),
cdbc7418
NJ
87 "The @code{eqv?} procedure defines a useful equivalence relation on objects.\n"
88 "Briefly, it returns @code{#t} if @var{x} and @var{y} should normally be\n"
89 "regarded as the same object. This relation is left slightly open to\n"
90 "interpretation, but works for comparing immediate integers, characters,\n"
91 "and inexact numbers.")
1bbd0b84 92#define FUNC_NAME s_scm_eqv_p
0f2d19dd 93{
fbd485ba 94 if (SCM_EQ_P (x, y))
950cc72b
MD
95 return SCM_BOOL_T;
96 if (SCM_IMP (x))
97 return SCM_BOOL_F;
98 if (SCM_IMP (y))
99 return SCM_BOOL_F;
0f2d19dd 100 /* this ensures that types and scm_length are the same. */
fbd485ba 101 if (SCM_CELL_TYPE (x) != SCM_CELL_TYPE (y))
950cc72b
MD
102 {
103 /* treat mixes of real and complex types specially */
104 if (SCM_SLOPPY_INEXACTP (x))
105 {
106 if (SCM_SLOPPY_REALP (x))
107 return SCM_BOOL (SCM_SLOPPY_COMPLEXP (y)
96d00047
MV
108 && real_eqv (SCM_REAL_VALUE (x),
109 SCM_COMPLEX_REAL (y))
950cc72b
MD
110 && 0.0 == SCM_COMPLEX_IMAG (y));
111 else
112 return SCM_BOOL (SCM_SLOPPY_REALP (y)
96d00047
MV
113 && real_eqv (SCM_COMPLEX_REAL (x),
114 SCM_REAL_VALUE (y))
950cc72b
MD
115 && SCM_COMPLEX_IMAG (x) == 0.0);
116 }
117 return SCM_BOOL_F;
118 }
119 if (SCM_NUMP (x))
120 {
eb42e2f0 121 if (SCM_BIGP (x)) {
950cc72b 122 return SCM_BOOL (0 == scm_bigcomp (x, y));
eb42e2f0 123 } else if (SCM_SLOPPY_REALP (x)) {
96d00047 124 return SCM_BOOL (real_eqv (SCM_REAL_VALUE (x), SCM_REAL_VALUE (y)));
eb42e2f0 125 } else { /* complex */
96d00047
MV
126 return SCM_BOOL (real_eqv (SCM_COMPLEX_REAL (x),
127 SCM_COMPLEX_REAL (y))
128 && real_eqv (SCM_COMPLEX_IMAG (x),
129 SCM_COMPLEX_IMAG (y)));
eb42e2f0 130 }
950cc72b 131 }
0f2d19dd
JB
132 return SCM_BOOL_F;
133}
1bbd0b84 134#undef FUNC_NAME
0f2d19dd
JB
135
136
c3ee7520 137SCM_DEFINE1 (scm_equal_p, "equal?", scm_tc7_rpsubr,
1bbd0b84 138 (SCM x, SCM y),
cdbc7418
NJ
139 "Return @code{#t} iff @var{x} and @var{y} are recursively @code{eqv?} equivalent.\n"
140 "@code{equal?} recursively compares the contents of pairs,\n"
141 "vectors, and strings, applying @code{eqv?} on other objects such as\n"
142 "numbers and symbols. A rule of thumb is that objects are generally\n"
143 "@code{equal?} if they print the same. @code{equal?} may fail to\n"
144 "terminate if its arguments are circular data structures.")
1bbd0b84 145#define FUNC_NAME s_scm_equal_p
0f2d19dd
JB
146{
147 SCM_CHECK_STACK;
950cc72b
MD
148 tailrecurse:
149 SCM_TICK;
fbd485ba 150 if (SCM_EQ_P (x, y))
950cc72b
MD
151 return SCM_BOOL_T;
152 if (SCM_IMP (x))
153 return SCM_BOOL_F;
154 if (SCM_IMP (y))
155 return SCM_BOOL_F;
22a52da1 156 if (SCM_CONSP (x) && SCM_CONSP (y))
950cc72b
MD
157 {
158 if (SCM_FALSEP (scm_equal_p (SCM_CAR (x), SCM_CAR (y))))
159 return SCM_BOOL_F;
160 x = SCM_CDR(x);
161 y = SCM_CDR(y);
162 goto tailrecurse;
163 }
164 if (SCM_TYP7S (x) == scm_tc7_string && SCM_TYP7S (y) == scm_tc7_string)
165 return scm_string_equal_p (x, y);
166 /* This ensures that types and scm_length are the same. */
fbd485ba 167 if (SCM_CELL_TYPE (x) != SCM_CELL_TYPE (y))
950cc72b
MD
168 {
169 /* treat mixes of real and complex types specially */
170 if (SCM_SLOPPY_INEXACTP (x))
171 {
172 if (SCM_SLOPPY_REALP (x))
173 return SCM_BOOL (SCM_SLOPPY_COMPLEXP (y)
174 && SCM_REAL_VALUE (x) == SCM_COMPLEX_REAL (y)
175 && 0.0 == SCM_COMPLEX_IMAG (y));
176 else
177 return SCM_BOOL (SCM_SLOPPY_REALP (y)
178 && SCM_COMPLEX_REAL (x) == SCM_REAL_VALUE (y)
179 && SCM_COMPLEX_IMAG (x) == 0.0);
0f2d19dd 180 }
950cc72b
MD
181 return SCM_BOOL_F;
182 }
183 switch (SCM_TYP7 (x))
184 {
185 default:
186 return SCM_BOOL_F;
187 case scm_tc7_vector:
188 case scm_tc7_wvect:
189 return scm_vector_equal_p (x, y);
190 case scm_tc7_smob:
191 {
192 int i = SCM_SMOBNUM (x);
193 if (!(i < scm_numsmob))
194 return SCM_BOOL_F;
195 if (scm_smobs[i].equalp)
196 return (scm_smobs[i].equalp) (x, y);
197 else
198 return SCM_BOOL_F;
199 }
afe5177e 200#ifdef HAVE_ARRAYS
950cc72b
MD
201 case scm_tc7_bvect: case scm_tc7_uvect: case scm_tc7_ivect:
202 case scm_tc7_fvect: case scm_tc7_cvect: case scm_tc7_dvect:
203 case scm_tc7_svect:
5c11cc9d 204#ifdef HAVE_LONG_LONGS
950cc72b 205 case scm_tc7_llvect:
0f2d19dd 206#endif
950cc72b 207 case scm_tc7_byvect:
7a7f7c53 208 if (scm_tc16_array && scm_smobs[SCM_TC2SMOBNUM (scm_tc16_array)].equalp)
950cc72b 209 return scm_array_equal_p (x, y);
afe5177e 210#endif
950cc72b
MD
211 }
212 return SCM_BOOL_F;
0f2d19dd 213}
1bbd0b84 214#undef FUNC_NAME
0f2d19dd
JB
215
216
217\f
218
219
1cc91f1b 220
0f2d19dd
JB
221void
222scm_init_eq ()
0f2d19dd 223{
a0599745 224#include "libguile/eq.x"
0f2d19dd
JB
225}
226
89e00824
ML
227
228/*
229 Local Variables:
230 c-file-style: "gnu"
231 End:
232*/