* print.c (scm_iprin1): Handle fractions.
[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
f92e85f7 64#include <stdio.h>
47cd67db 65SCM_PRIMITIVE_GENERIC_1 (scm_eqv_p, "eqv?", scm_tc7_rpsubr,
1bbd0b84 66 (SCM x, SCM y),
cdbc7418
NJ
67 "The @code{eqv?} procedure defines a useful equivalence relation on objects.\n"
68 "Briefly, it returns @code{#t} if @var{x} and @var{y} should normally be\n"
69 "regarded as the same object. This relation is left slightly open to\n"
70 "interpretation, but works for comparing immediate integers, characters,\n"
71 "and inexact numbers.")
1bbd0b84 72#define FUNC_NAME s_scm_eqv_p
0f2d19dd 73{
fbd485ba 74 if (SCM_EQ_P (x, y))
950cc72b
MD
75 return SCM_BOOL_T;
76 if (SCM_IMP (x))
77 return SCM_BOOL_F;
78 if (SCM_IMP (y))
79 return SCM_BOOL_F;
0f2d19dd 80 /* this ensures that types and scm_length are the same. */
f92e85f7 81
fbd485ba 82 if (SCM_CELL_TYPE (x) != SCM_CELL_TYPE (y))
950cc72b 83 {
f92e85f7
MV
84 /* fractions use 0x10000 as a flag (at the suggestion of Marius Vollmer),
85 but this checks the entire type word, so fractions may be accidentally
86 flagged here as unequal. Perhaps I should use the 4th double_cell word?
87 */
88
950cc72b 89 /* treat mixes of real and complex types specially */
6b412e91 90 if (SCM_INEXACTP (x))
950cc72b 91 {
6b412e91
DH
92 if (SCM_REALP (x))
93 return SCM_BOOL (SCM_COMPLEXP (y)
96d00047
MV
94 && real_eqv (SCM_REAL_VALUE (x),
95 SCM_COMPLEX_REAL (y))
6b412e91 96 && SCM_COMPLEX_IMAG (y) == 0.0);
950cc72b 97 else
6b412e91 98 return SCM_BOOL (SCM_REALP (y)
96d00047
MV
99 && real_eqv (SCM_COMPLEX_REAL (x),
100 SCM_REAL_VALUE (y))
950cc72b
MD
101 && SCM_COMPLEX_IMAG (x) == 0.0);
102 }
f92e85f7
MV
103
104 if (SCM_FRACTIONP (x) && SCM_FRACTIONP (y))
105 return scm_i_fraction_equalp (x, y);
950cc72b
MD
106 return SCM_BOOL_F;
107 }
108 if (SCM_NUMP (x))
109 {
eb42e2f0 110 if (SCM_BIGP (x)) {
6b412e91
DH
111 return SCM_BOOL (scm_i_bigcmp (x, y) == 0);
112 } else if (SCM_REALP (x)) {
96d00047 113 return SCM_BOOL (real_eqv (SCM_REAL_VALUE (x), SCM_REAL_VALUE (y)));
f92e85f7
MV
114 } else if (SCM_FRACTIONP (x)) {
115 return scm_i_fraction_equalp (x, y);
eb42e2f0 116 } else { /* complex */
96d00047
MV
117 return SCM_BOOL (real_eqv (SCM_COMPLEX_REAL (x),
118 SCM_COMPLEX_REAL (y))
119 && real_eqv (SCM_COMPLEX_IMAG (x),
120 SCM_COMPLEX_IMAG (y)));
eb42e2f0 121 }
950cc72b 122 }
47cd67db
MD
123 if (SCM_UNPACK (g_scm_eqv_p))
124 return scm_call_generic_2 (g_scm_eqv_p, x, y);
125 else
126 return SCM_BOOL_F;
0f2d19dd 127}
1bbd0b84 128#undef FUNC_NAME
0f2d19dd
JB
129
130
a48d60b1
MD
131SCM_PRIMITIVE_GENERIC_1 (scm_equal_p, "equal?", scm_tc7_rpsubr,
132 (SCM x, SCM y),
133 "Return @code{#t} iff @var{x} and @var{y} are recursively @code{eqv?} equivalent.\n"
134 "@code{equal?} recursively compares the contents of pairs,\n"
135 "vectors, and strings, applying @code{eqv?} on other objects such as\n"
136 "numbers and symbols. A rule of thumb is that objects are generally\n"
137 "@code{equal?} if they print the same. @code{equal?} may fail to\n"
138 "terminate if its arguments are circular data structures.")
1bbd0b84 139#define FUNC_NAME s_scm_equal_p
0f2d19dd
JB
140{
141 SCM_CHECK_STACK;
950cc72b
MD
142 tailrecurse:
143 SCM_TICK;
fbd485ba 144 if (SCM_EQ_P (x, y))
950cc72b
MD
145 return SCM_BOOL_T;
146 if (SCM_IMP (x))
147 return SCM_BOOL_F;
148 if (SCM_IMP (y))
149 return SCM_BOOL_F;
22a52da1 150 if (SCM_CONSP (x) && SCM_CONSP (y))
950cc72b
MD
151 {
152 if (SCM_FALSEP (scm_equal_p (SCM_CAR (x), SCM_CAR (y))))
153 return SCM_BOOL_F;
154 x = SCM_CDR(x);
155 y = SCM_CDR(y);
156 goto tailrecurse;
157 }
baa84a20 158 if (SCM_TYP7 (x) == scm_tc7_string && SCM_TYP7 (y) == scm_tc7_string)
950cc72b
MD
159 return scm_string_equal_p (x, y);
160 /* This ensures that types and scm_length are the same. */
fbd485ba 161 if (SCM_CELL_TYPE (x) != SCM_CELL_TYPE (y))
950cc72b
MD
162 {
163 /* treat mixes of real and complex types specially */
f92e85f7 164 if (SCM_INEXACTP (x) && SCM_INEXACTP (y))
950cc72b 165 {
6b412e91
DH
166 if (SCM_REALP (x))
167 return SCM_BOOL (SCM_COMPLEXP (y)
950cc72b 168 && SCM_REAL_VALUE (x) == SCM_COMPLEX_REAL (y)
6b412e91 169 && SCM_COMPLEX_IMAG (y) == 0.0);
950cc72b 170 else
6b412e91 171 return SCM_BOOL (SCM_REALP (y)
950cc72b
MD
172 && SCM_COMPLEX_REAL (x) == SCM_REAL_VALUE (y)
173 && SCM_COMPLEX_IMAG (x) == 0.0);
0f2d19dd 174 }
f92e85f7
MV
175
176 /* should we handle fractions here also? */
177 else if ((SCM_FRACTIONP (x)) && (SCM_INEXACTP (y)))
178 {
179 if (SCM_REALP (y))
180 return SCM_BOOL (scm_i_fraction2double (x) == SCM_REAL_VALUE (y));
181 else
182 return SCM_BOOL (SCM_COMPLEX_REAL (y) == scm_i_fraction2double (x)
183 && SCM_COMPLEX_IMAG (y) == 0.0);
184 }
185 else if ((SCM_FRACTIONP (y)) && (SCM_INEXACTP (x)))
186 {
187 if (SCM_REALP (x))
188 return SCM_BOOL (scm_i_fraction2double (y) == SCM_REAL_VALUE (x));
189 else
190 return SCM_BOOL (SCM_COMPLEX_REAL (x) == scm_i_fraction2double (y)
191 && SCM_COMPLEX_IMAG (x) == 0.0);
192 }
193
950cc72b
MD
194 return SCM_BOOL_F;
195 }
196 switch (SCM_TYP7 (x))
197 {
198 default:
a48d60b1 199 break;
534c55a9
DH
200 case scm_tc7_number:
201 switch SCM_TYP16 (x)
202 {
203 case scm_tc16_big:
204 return scm_bigequal (x, y);
205 case scm_tc16_real:
206 return scm_real_equalp (x, y);
207 case scm_tc16_complex:
208 return scm_complex_equalp (x, y);
f92e85f7
MV
209 case scm_tc16_fraction:
210 return scm_i_fraction_equalp (x, y);
534c55a9 211 }
950cc72b
MD
212 case scm_tc7_vector:
213 case scm_tc7_wvect:
214 return scm_vector_equal_p (x, y);
215 case scm_tc7_smob:
216 {
217 int i = SCM_SMOBNUM (x);
218 if (!(i < scm_numsmob))
219 return SCM_BOOL_F;
220 if (scm_smobs[i].equalp)
221 return (scm_smobs[i].equalp) (x, y);
222 else
a48d60b1 223 break;
950cc72b 224 }
1a603dc0 225#if SCM_HAVE_ARRAYS
950cc72b
MD
226 case scm_tc7_bvect: case scm_tc7_uvect: case scm_tc7_ivect:
227 case scm_tc7_fvect: case scm_tc7_cvect: case scm_tc7_dvect:
228 case scm_tc7_svect:
1f4d02c2 229#if SCM_SIZEOF_LONG_LONG != 0
950cc72b 230 case scm_tc7_llvect:
0f2d19dd 231#endif
950cc72b 232 case scm_tc7_byvect:
7a7f7c53 233 if (scm_tc16_array && scm_smobs[SCM_TC2SMOBNUM (scm_tc16_array)].equalp)
950cc72b 234 return scm_array_equal_p (x, y);
afe5177e 235#endif
950cc72b 236 }
a48d60b1
MD
237 if (SCM_UNPACK (g_scm_equal_p))
238 return scm_call_generic_2 (g_scm_equal_p, x, y);
239 else
240 return SCM_BOOL_F;
0f2d19dd 241}
1bbd0b84 242#undef FUNC_NAME
0f2d19dd
JB
243
244
245\f
246
247
1cc91f1b 248
0f2d19dd
JB
249void
250scm_init_eq ()
0f2d19dd 251{
a0599745 252#include "libguile/eq.x"
0f2d19dd
JB
253}
254
89e00824
ML
255
256/*
257 Local Variables:
258 c-file-style: "gnu"
259 End:
260*/