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