(gh_uniform_vector_length): Properly use scm_c_uniform_vector_length
[bpt/guile.git] / libguile / eq.c
CommitLineData
728ad4b7 1/* Copyright (C) 1995,1996,1997,1998,2000,2001,2003, 2004 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{
bc36d050 50 return scm_from_bool (scm_is_eq (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{
0e12d408 61 return !memcmp (&x, &y, sizeof(double)) || (x != x && y != y);
96d00047 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{
bc36d050 74 if (scm_is_eq (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 92 if (SCM_REALP (x))
7888309b 93 return scm_from_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
7888309b 98 return scm_from_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)) {
7888309b 111 return scm_from_bool (scm_i_bigcmp (x, y) == 0);
6b412e91 112 } else if (SCM_REALP (x)) {
7888309b 113 return scm_from_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 */
7888309b 117 return scm_from_bool (real_eqv (SCM_COMPLEX_REAL (x),
96d00047
MV
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;
bc36d050 144 if (scm_is_eq (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;
d2e53ed6 150 if (scm_is_pair (x) && scm_is_pair (y))
950cc72b 151 {
7888309b 152 if (scm_is_false (scm_equal_p (SCM_CAR (x), SCM_CAR (y))))
950cc72b
MD
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 159 return scm_string_equal_p (x, y);
789d2fc8
MV
160 if (SCM_TYP7 (x) == scm_tc7_smob && SCM_TYP16 (x) == SCM_TYP16 (y))
161 {
162 int i = SCM_SMOBNUM (x);
163 if (!(i < scm_numsmob))
164 return SCM_BOOL_F;
165 if (scm_smobs[i].equalp)
166 return (scm_smobs[i].equalp) (x, y);
167 else
168 goto generic_equal;
169 }
950cc72b 170 /* This ensures that types and scm_length are the same. */
fbd485ba 171 if (SCM_CELL_TYPE (x) != SCM_CELL_TYPE (y))
950cc72b
MD
172 {
173 /* treat mixes of real and complex types specially */
f92e85f7 174 if (SCM_INEXACTP (x) && SCM_INEXACTP (y))
950cc72b 175 {
6b412e91 176 if (SCM_REALP (x))
7888309b 177 return scm_from_bool (SCM_COMPLEXP (y)
950cc72b 178 && SCM_REAL_VALUE (x) == SCM_COMPLEX_REAL (y)
6b412e91 179 && SCM_COMPLEX_IMAG (y) == 0.0);
950cc72b 180 else
7888309b 181 return scm_from_bool (SCM_REALP (y)
950cc72b
MD
182 && SCM_COMPLEX_REAL (x) == SCM_REAL_VALUE (y)
183 && SCM_COMPLEX_IMAG (x) == 0.0);
0f2d19dd 184 }
f92e85f7 185
950cc72b
MD
186 return SCM_BOOL_F;
187 }
188 switch (SCM_TYP7 (x))
189 {
190 default:
a48d60b1 191 break;
534c55a9
DH
192 case scm_tc7_number:
193 switch SCM_TYP16 (x)
194 {
195 case scm_tc16_big:
196 return scm_bigequal (x, y);
197 case scm_tc16_real:
198 return scm_real_equalp (x, y);
199 case scm_tc16_complex:
200 return scm_complex_equalp (x, y);
f92e85f7
MV
201 case scm_tc16_fraction:
202 return scm_i_fraction_equalp (x, y);
534c55a9 203 }
950cc72b
MD
204 case scm_tc7_vector:
205 case scm_tc7_wvect:
206 return scm_vector_equal_p (x, y);
950cc72b 207 }
789d2fc8 208 generic_equal:
a48d60b1
MD
209 if (SCM_UNPACK (g_scm_equal_p))
210 return scm_call_generic_2 (g_scm_equal_p, x, y);
211 else
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*/