speed up scm_call_N for non-programs
[bpt/guile.git] / libguile / array-map.c
CommitLineData
b6149d8d 1/* Copyright (C) 1996,1998,2000,2001,2004,2005, 2006, 2008, 2009 Free Software Foundation, Inc.
0f2d19dd 2 *
73be1d9e 3 * This library is free software; you can redistribute it and/or
53befeb7
NJ
4 * modify it under the terms of the GNU Lesser General Public License
5 * as published by the Free Software Foundation; either version 3 of
6 * the License, or (at your option) any later version.
0f2d19dd 7 *
53befeb7
NJ
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
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
53befeb7
NJ
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301 USA
73be1d9e 17 */
1bbd0b84 18
1bbd0b84 19
0f2d19dd
JB
20\f
21
22
23\f
dbb605f5
LC
24#ifdef HAVE_CONFIG_H
25# include <config.h>
26#endif
0f2d19dd 27
a0599745 28#include "libguile/_scm.h"
405aaef9 29#include "libguile/strings.h"
2fa901a5 30#include "libguile/arrays.h"
a0599745
MD
31#include "libguile/smob.h"
32#include "libguile/chars.h"
33#include "libguile/eq.h"
34#include "libguile/eval.h"
35#include "libguile/feature.h"
36#include "libguile/root.h"
37#include "libguile/vectors.h"
cf396142 38#include "libguile/bitvectors.h"
b4bdadde 39#include "libguile/srfi-4.h"
1030b450 40#include "libguile/generalized-arrays.h"
f332e957 41#include "libguile/generalized-vectors.h"
a0599745
MD
42
43#include "libguile/validate.h"
5d1b3b2d 44#include "libguile/array-map.h"
0f2d19dd
JB
45\f
46
0f2d19dd
JB
47typedef struct
48{
49 char *name;
50 SCM sproc;
51 int (*vproc) ();
52} ra_iproc;
53
ad310508
MD
54
55/* These tables are a kluge that will not scale well when more
56 * vectorized subrs are added. It is tempting to steal some bits from
57 * the SCM_CAR of all subrs (like those selected by SCM_SMOBNUM) to hold an
58 * offset into a table of vectorized subrs.
59 */
60
61static ra_iproc ra_rpsubrs[] =
62{
63 {"=", SCM_UNDEFINED, scm_ra_eqp},
64 {"<", SCM_UNDEFINED, scm_ra_lessp},
65 {"<=", SCM_UNDEFINED, scm_ra_leqp},
66 {">", SCM_UNDEFINED, scm_ra_grp},
67 {">=", SCM_UNDEFINED, scm_ra_greqp},
68 {0, 0, 0}
69};
70
71static ra_iproc ra_asubrs[] =
72{
73 {"+", SCM_UNDEFINED, scm_ra_sum},
74 {"-", SCM_UNDEFINED, scm_ra_difference},
75 {"*", SCM_UNDEFINED, scm_ra_product},
76 {"/", SCM_UNDEFINED, scm_ra_divide},
77 {0, 0, 0}
78};
79
d66b74dc
LC
80/* The WHAT argument for `scm_gc_malloc ()' et al. */
81static const char indices_gc_hint[] = "array-indices";
82
0f2d19dd 83
85516012
MV
84#define GVREF scm_c_generalized_vector_ref
85#define GVSET scm_c_generalized_vector_set_x
c209c88e 86
c014a02e 87static unsigned long
b4b33636 88cind (SCM ra, long *ve)
0f2d19dd 89{
c014a02e 90 unsigned long i;
0f2d19dd 91 int k;
04b87de5 92 if (!SCM_I_ARRAYP (ra))
0f2d19dd 93 return *ve;
04b87de5
MV
94 i = SCM_I_ARRAY_BASE (ra);
95 for (k = 0; k < SCM_I_ARRAY_NDIM (ra); k++)
96 i += (ve[k] - SCM_I_ARRAY_DIMS (ra)[k].lbnd) * SCM_I_ARRAY_DIMS (ra)[k].inc;
0f2d19dd
JB
97 return i;
98}
99
100
101/* Checker for scm_array mapping functions:
102 return values: 4 --> shapes, increments, and bases are the same;
103 3 --> shapes and increments are the same;
104 2 --> shapes are the same;
105 1 --> ras are at least as big as ra0;
106 0 --> no match.
107 */
1cc91f1b 108
0f2d19dd 109int
6e8d25a6 110scm_ra_matchp (SCM ra0, SCM ras)
0f2d19dd
JB
111{
112 SCM ra1;
92c2555f
MV
113 scm_t_array_dim dims;
114 scm_t_array_dim *s0 = &dims;
115 scm_t_array_dim *s1;
c014a02e 116 unsigned long bas0 = 0;
0f2d19dd 117 int i, ndim = 1;
399aba0a
MV
118 int exact = 2 /* 4 */ ; /* Don't care about values >2 (yet?) */
119
120 if (scm_is_generalized_vector (ra0))
c209c88e 121 {
c209c88e
GB
122 s0->lbnd = 0;
123 s0->inc = 1;
399aba0a
MV
124 s0->ubnd = scm_c_generalized_vector_length (ra0) - 1;
125 }
04b87de5 126 else if (SCM_I_ARRAYP (ra0))
399aba0a 127 {
04b87de5
MV
128 ndim = SCM_I_ARRAY_NDIM (ra0);
129 s0 = SCM_I_ARRAY_DIMS (ra0);
130 bas0 = SCM_I_ARRAY_BASE (ra0);
c209c88e 131 }
399aba0a
MV
132 else
133 return 0;
134
368cf54d 135 while (SCM_NIMP (ras))
c209c88e
GB
136 {
137 ra1 = SCM_CAR (ras);
399aba0a
MV
138
139 if (scm_is_generalized_vector (ra1))
c209c88e 140 {
399aba0a
MV
141 size_t length;
142
143 if (1 != ndim)
c209c88e 144 return 0;
399aba0a
MV
145
146 length = scm_c_generalized_vector_length (ra1);
147
148 switch (exact)
149 {
150 case 4:
151 if (0 != bas0)
152 exact = 3;
153 case 3:
154 if (1 != s0->inc)
155 exact = 2;
156 case 2:
157 if ((0 == s0->lbnd) && (s0->ubnd == length - 1))
158 break;
159 exact = 1;
160 case 1:
161 if (s0->lbnd < 0 || s0->ubnd >= length)
162 return 0;
163 }
164 }
04b87de5 165 else if (SCM_I_ARRAYP (ra1) && ndim == SCM_I_ARRAY_NDIM (ra1))
399aba0a 166 {
04b87de5
MV
167 s1 = SCM_I_ARRAY_DIMS (ra1);
168 if (bas0 != SCM_I_ARRAY_BASE (ra1))
c209c88e
GB
169 exact = 3;
170 for (i = 0; i < ndim; i++)
171 switch (exact)
172 {
173 case 4:
174 case 3:
175 if (s0[i].inc != s1[i].inc)
176 exact = 2;
177 case 2:
178 if (s0[i].lbnd == s1[i].lbnd && s0[i].ubnd == s1[i].ubnd)
179 break;
180 exact = 1;
181 default:
182 if (s0[i].lbnd < s1[i].lbnd || s0[i].ubnd > s1[i].ubnd)
183 return (s0[i].lbnd <= s0[i].ubnd ? 0 : 1);
184 }
c209c88e 185 }
399aba0a
MV
186 else
187 return 0;
188
c209c88e
GB
189 ras = SCM_CDR (ras);
190 }
399aba0a 191
0f2d19dd
JB
192 return exact;
193}
194
1bbd0b84
GB
195/* array mapper: apply cproc to each dimension of the given arrays?.
196 int (*cproc) (); procedure to call on unrolled arrays?
5c11cc9d 197 cproc (dest, source list) or
1bbd0b84
GB
198 cproc (dest, data, source list).
199 SCM data; data to give to cproc or unbound.
200 SCM ra0; destination array.
201 SCM lra; list of source arrays.
202 const char *what; caller, for error reporting. */
203int
204scm_ramapc (int (*cproc)(), SCM data, SCM ra0, SCM lra, const char *what)
0f2d19dd 205{
b4b33636 206 SCM z;
0f2d19dd
JB
207 SCM vra0, ra1, vra1;
208 SCM lvra, *plvra;
c014a02e 209 long *vinds;
0f2d19dd
JB
210 int k, kmax;
211 switch (scm_ra_matchp (ra0, lra))
212 {
213 default:
214 case 0:
9cf5d9b7 215 scm_misc_error (what, "array shape mismatch: ~S", scm_list_1 (ra0));
0f2d19dd
JB
216 case 2:
217 case 3:
218 case 4: /* Try unrolling arrays */
04b87de5 219 kmax = (SCM_I_ARRAYP (ra0) ? SCM_I_ARRAY_NDIM (ra0) - 1 : 0);
0f2d19dd
JB
220 if (kmax < 0)
221 goto gencase;
222 vra0 = scm_array_contents (ra0, SCM_UNDEFINED);
ff467021 223 if (SCM_IMP (vra0)) goto gencase;
04b87de5 224 if (!SCM_I_ARRAYP (vra0))
0f2d19dd 225 {
399aba0a 226 size_t length = scm_c_generalized_vector_length (vra0);
66b9d7d3 227 vra1 = scm_i_make_array (1);
04b87de5
MV
228 SCM_I_ARRAY_BASE (vra1) = 0;
229 SCM_I_ARRAY_DIMS (vra1)->lbnd = 0;
230 SCM_I_ARRAY_DIMS (vra1)->ubnd = length - 1;
231 SCM_I_ARRAY_DIMS (vra1)->inc = 1;
232 SCM_I_ARRAY_V (vra1) = vra0;
0f2d19dd
JB
233 vra0 = vra1;
234 }
235 lvra = SCM_EOL;
236 plvra = &lvra;
237 for (z = lra; SCM_NIMP (z); z = SCM_CDR (z))
238 {
239 ra1 = SCM_CAR (z);
66b9d7d3 240 vra1 = scm_i_make_array (1);
04b87de5
MV
241 SCM_I_ARRAY_DIMS (vra1)->lbnd = SCM_I_ARRAY_DIMS (vra0)->lbnd;
242 SCM_I_ARRAY_DIMS (vra1)->ubnd = SCM_I_ARRAY_DIMS (vra0)->ubnd;
243 if (!SCM_I_ARRAYP (ra1))
0f2d19dd 244 {
04b87de5
MV
245 SCM_I_ARRAY_BASE (vra1) = 0;
246 SCM_I_ARRAY_DIMS (vra1)->inc = 1;
247 SCM_I_ARRAY_V (vra1) = ra1;
0f2d19dd 248 }
04b87de5 249 else if (!SCM_I_ARRAY_CONTP (ra1))
0f2d19dd
JB
250 goto gencase;
251 else
252 {
04b87de5
MV
253 SCM_I_ARRAY_BASE (vra1) = SCM_I_ARRAY_BASE (ra1);
254 SCM_I_ARRAY_DIMS (vra1)->inc = SCM_I_ARRAY_DIMS (ra1)[kmax].inc;
255 SCM_I_ARRAY_V (vra1) = SCM_I_ARRAY_V (ra1);
0f2d19dd
JB
256 }
257 *plvra = scm_cons (vra1, SCM_EOL);
25d8012c 258 plvra = SCM_CDRLOC (*plvra);
0f2d19dd
JB
259 }
260 return (SCM_UNBNDP (data) ? cproc(vra0, lvra) : cproc(vra0, data, lvra));
261 case 1:
262 gencase: /* Have to loop over all dimensions. */
66b9d7d3 263 vra0 = scm_i_make_array (1);
04b87de5 264 if (SCM_I_ARRAYP (ra0))
c209c88e 265 {
04b87de5 266 kmax = SCM_I_ARRAY_NDIM (ra0) - 1;
c209c88e 267 if (kmax < 0)
0f2d19dd 268 {
04b87de5
MV
269 SCM_I_ARRAY_DIMS (vra0)->lbnd = 0;
270 SCM_I_ARRAY_DIMS (vra0)->ubnd = 0;
271 SCM_I_ARRAY_DIMS (vra0)->inc = 1;
0f2d19dd 272 }
c209c88e
GB
273 else
274 {
04b87de5
MV
275 SCM_I_ARRAY_DIMS (vra0)->lbnd = SCM_I_ARRAY_DIMS (ra0)[kmax].lbnd;
276 SCM_I_ARRAY_DIMS (vra0)->ubnd = SCM_I_ARRAY_DIMS (ra0)[kmax].ubnd;
277 SCM_I_ARRAY_DIMS (vra0)->inc = SCM_I_ARRAY_DIMS (ra0)[kmax].inc;
c209c88e 278 }
04b87de5
MV
279 SCM_I_ARRAY_BASE (vra0) = SCM_I_ARRAY_BASE (ra0);
280 SCM_I_ARRAY_V (vra0) = SCM_I_ARRAY_V (ra0);
c209c88e
GB
281 }
282 else
283 {
ee67e2fa 284 size_t length = scm_c_generalized_vector_length (ra0);
c209c88e 285 kmax = 0;
04b87de5
MV
286 SCM_I_ARRAY_DIMS (vra0)->lbnd = 0;
287 SCM_I_ARRAY_DIMS (vra0)->ubnd = length - 1;
288 SCM_I_ARRAY_DIMS (vra0)->inc = 1;
289 SCM_I_ARRAY_BASE (vra0) = 0;
290 SCM_I_ARRAY_V (vra0) = ra0;
c209c88e
GB
291 ra0 = vra0;
292 }
293 lvra = SCM_EOL;
294 plvra = &lvra;
295 for (z = lra; SCM_NIMP (z); z = SCM_CDR (z))
296 {
297 ra1 = SCM_CAR (z);
66b9d7d3 298 vra1 = scm_i_make_array (1);
04b87de5
MV
299 SCM_I_ARRAY_DIMS (vra1)->lbnd = SCM_I_ARRAY_DIMS (vra0)->lbnd;
300 SCM_I_ARRAY_DIMS (vra1)->ubnd = SCM_I_ARRAY_DIMS (vra0)->ubnd;
301 if (SCM_I_ARRAYP (ra1))
c209c88e
GB
302 {
303 if (kmax >= 0)
04b87de5
MV
304 SCM_I_ARRAY_DIMS (vra1)->inc = SCM_I_ARRAY_DIMS (ra1)[kmax].inc;
305 SCM_I_ARRAY_V (vra1) = SCM_I_ARRAY_V (ra1);
c209c88e
GB
306 }
307 else
308 {
04b87de5
MV
309 SCM_I_ARRAY_DIMS (vra1)->inc = 1;
310 SCM_I_ARRAY_V (vra1) = ra1;
c209c88e
GB
311 }
312 *plvra = scm_cons (vra1, SCM_EOL);
313 plvra = SCM_CDRLOC (*plvra);
314 }
b4b33636 315
d66b74dc
LC
316 vinds = scm_gc_malloc_pointerless (sizeof(long) * SCM_I_ARRAY_NDIM (ra0),
317 indices_gc_hint);
b4b33636 318
c209c88e 319 for (k = 0; k <= kmax; k++)
04b87de5 320 vinds[k] = SCM_I_ARRAY_DIMS (ra0)[k].lbnd;
c209c88e
GB
321 k = kmax;
322 do
323 {
324 if (k == kmax)
325 {
326 SCM y = lra;
04b87de5 327 SCM_I_ARRAY_BASE (vra0) = cind (ra0, vinds);
c209c88e 328 for (z = lvra; SCM_NIMP (z); z = SCM_CDR (z), y = SCM_CDR (y))
04b87de5 329 SCM_I_ARRAY_BASE (SCM_CAR (z)) = cind (SCM_CAR (y), vinds);
c209c88e
GB
330 if (0 == (SCM_UNBNDP (data) ? cproc(vra0, lvra) : cproc(vra0, data, lvra)))
331 return 0;
332 k--;
333 continue;
334 }
04b87de5 335 if (vinds[k] < SCM_I_ARRAY_DIMS (ra0)[k].ubnd)
c209c88e
GB
336 {
337 vinds[k]++;
338 k++;
339 continue;
340 }
04b87de5 341 vinds[k] = SCM_I_ARRAY_DIMS (ra0)[k].lbnd - 1;
c209c88e
GB
342 k--;
343 }
344 while (k >= 0);
b4b33636 345
c209c88e 346 return 1;
0f2d19dd
JB
347 }
348}
349
350
3b3b36dd 351SCM_DEFINE (scm_array_fill_x, "array-fill!", 2, 0, 0,
c209c88e 352 (SCM ra, SCM fill),
8f85c0c6 353 "Store @var{fill} in every element of @var{array}. The value returned\n"
b380b885 354 "is unspecified.")
1bbd0b84 355#define FUNC_NAME s_scm_array_fill_x
ad310508 356{
c209c88e 357 scm_ramapc (scm_array_fill_int, fill, ra, SCM_EOL, FUNC_NAME);
ad310508
MD
358 return SCM_UNSPECIFIED;
359}
1bbd0b84 360#undef FUNC_NAME
ad310508 361
5c11cc9d
GH
362/* to be used as cproc in scm_ramapc to fill an array dimension with
363 "fill". */
0f2d19dd 364int
e81d98ec 365scm_array_fill_int (SCM ra, SCM fill, SCM ignore SCM_UNUSED)
1bbd0b84 366#define FUNC_NAME s_scm_array_fill_x
0f2d19dd 367{
c014a02e 368 unsigned long i;
04b87de5
MV
369 unsigned long n = SCM_I_ARRAY_DIMS (ra)->ubnd - SCM_I_ARRAY_DIMS (ra)->lbnd + 1;
370 long inc = SCM_I_ARRAY_DIMS (ra)->inc;
371 unsigned long base = SCM_I_ARRAY_BASE (ra);
5c11cc9d 372
04b87de5 373 ra = SCM_I_ARRAY_V (ra);
b4bdadde 374
afaf9d0b 375 for (i = base; n--; i += inc)
85516012 376 GVSET (ra, i, fill);
afaf9d0b 377
0f2d19dd
JB
378 return 1;
379}
1bbd0b84 380#undef FUNC_NAME
0f2d19dd 381
0f2d19dd 382
c209c88e 383
0f2d19dd 384static int
1bbd0b84 385racp (SCM src, SCM dst)
0f2d19dd 386{
04b87de5
MV
387 long n = (SCM_I_ARRAY_DIMS (src)->ubnd - SCM_I_ARRAY_DIMS (src)->lbnd + 1);
388 long inc_d, inc_s = SCM_I_ARRAY_DIMS (src)->inc;
389 unsigned long i_d, i_s = SCM_I_ARRAY_BASE (src);
0f2d19dd 390 dst = SCM_CAR (dst);
04b87de5
MV
391 inc_d = SCM_I_ARRAY_DIMS (dst)->inc;
392 i_d = SCM_I_ARRAY_BASE (dst);
393 src = SCM_I_ARRAY_V (src);
394 dst = SCM_I_ARRAY_V (dst);
c209c88e 395
399aba0a 396 for (; n-- > 0; i_s += inc_s, i_d += inc_d)
85516012 397 GVSET (dst, i_d, GVREF (src, i_s));
0f2d19dd
JB
398 return 1;
399}
400
1bbd0b84 401SCM_REGISTER_PROC(s_array_copy_in_order_x, "array-copy-in-order!", 2, 0, 0, scm_array_copy_x);
1cc91f1b 402
1bbd0b84 403
3b3b36dd 404SCM_DEFINE (scm_array_copy_x, "array-copy!", 2, 0, 0,
c209c88e 405 (SCM src, SCM dst),
8f85c0c6
NJ
406 "@deffnx {Scheme Procedure} array-copy-in-order! src dst\n"
407 "Copy every element from vector or array @var{source} to the\n"
b380b885
MD
408 "corresponding element of @var{destination}. @var{destination} must have\n"
409 "the same rank as @var{source}, and be at least as large in each\n"
410 "dimension. The order is unspecified.")
1bbd0b84 411#define FUNC_NAME s_scm_array_copy_x
0f2d19dd 412{
c209c88e 413 scm_ramapc (racp, SCM_UNDEFINED, src, scm_cons (dst, SCM_EOL), FUNC_NAME);
0f2d19dd
JB
414 return SCM_UNSPECIFIED;
415}
1bbd0b84 416#undef FUNC_NAME
0f2d19dd
JB
417
418/* Functions callable by ARRAY-MAP! */
419
1cc91f1b 420
0f2d19dd 421int
1bbd0b84 422scm_ra_eqp (SCM ra0, SCM ras)
0f2d19dd
JB
423{
424 SCM ra1 = SCM_CAR (ras), ra2 = SCM_CAR (SCM_CDR (ras));
fab07c30
MV
425 scm_t_array_handle ra0_handle;
426 scm_t_array_dim *ra0_dims;
427 size_t n;
428 ssize_t inc0;
429 size_t i0 = 0;
430 unsigned long i1 = SCM_I_ARRAY_BASE (ra1), i2 = SCM_I_ARRAY_BASE (ra2);
04b87de5
MV
431 long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
432 long inc2 = SCM_I_ARRAY_DIMS (ra1)->inc;
04b87de5
MV
433 ra1 = SCM_I_ARRAY_V (ra1);
434 ra2 = SCM_I_ARRAY_V (ra2);
fab07c30
MV
435
436 scm_array_get_handle (ra0, &ra0_handle);
437 ra0_dims = scm_array_handle_dims (&ra0_handle);
438 n = ra0_dims[0].ubnd - ra0_dims[0].lbnd + 1;
439 inc0 = ra0_dims[0].inc;
440
399aba0a 441 {
399aba0a 442 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
fab07c30 443 if (scm_is_true (scm_array_handle_ref (&ra0_handle, i0)))
85516012 444 if (!scm_is_eq (GVREF (ra1, i1), GVREF (ra2, i2)))
fab07c30 445 scm_array_handle_set (&ra0_handle, i0, SCM_BOOL_F);
399aba0a
MV
446 }
447
fab07c30 448 scm_array_handle_release (&ra0_handle);
0f2d19dd
JB
449 return 1;
450}
451
452/* opt 0 means <, nonzero means >= */
1cc91f1b 453
0f2d19dd 454static int
34d19ef6 455ra_compare (SCM ra0, SCM ra1, SCM ra2, int opt)
0f2d19dd 456{
fab07c30
MV
457 scm_t_array_handle ra0_handle;
458 scm_t_array_dim *ra0_dims;
459 size_t n;
460 ssize_t inc0;
461 size_t i0 = 0;
462 unsigned long i1 = SCM_I_ARRAY_BASE (ra1), i2 = SCM_I_ARRAY_BASE (ra2);
04b87de5
MV
463 long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
464 long inc2 = SCM_I_ARRAY_DIMS (ra1)->inc;
04b87de5
MV
465 ra1 = SCM_I_ARRAY_V (ra1);
466 ra2 = SCM_I_ARRAY_V (ra2);
399aba0a 467
fab07c30
MV
468 scm_array_get_handle (ra0, &ra0_handle);
469 ra0_dims = scm_array_handle_dims (&ra0_handle);
470 n = ra0_dims[0].ubnd - ra0_dims[0].lbnd + 1;
471 inc0 = ra0_dims[0].inc;
472
399aba0a 473 {
399aba0a 474 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
fab07c30 475 if (scm_is_true (scm_array_handle_ref (&ra0_handle, i0)))
399aba0a 476 if (opt ?
85516012
MV
477 scm_is_true (scm_less_p (GVREF (ra1, i1), GVREF (ra2, i2))) :
478 scm_is_false (scm_less_p (GVREF (ra1, i1), GVREF (ra2, i2))))
fab07c30 479 scm_array_handle_set (&ra0_handle, i0, SCM_BOOL_F);
399aba0a
MV
480 }
481
fab07c30 482 scm_array_handle_release (&ra0_handle);
0f2d19dd
JB
483 return 1;
484}
485
486
1cc91f1b 487
0f2d19dd 488int
1bbd0b84 489scm_ra_lessp (SCM ra0, SCM ras)
0f2d19dd
JB
490{
491 return ra_compare (ra0, SCM_CAR (ras), SCM_CAR (SCM_CDR (ras)), 0);
492}
493
1cc91f1b 494
0f2d19dd 495int
1bbd0b84 496scm_ra_leqp (SCM ra0, SCM ras)
0f2d19dd
JB
497{
498 return ra_compare (ra0, SCM_CAR (SCM_CDR (ras)), SCM_CAR (ras), 1);
499}
500
1cc91f1b 501
0f2d19dd 502int
1bbd0b84 503scm_ra_grp (SCM ra0, SCM ras)
0f2d19dd
JB
504{
505 return ra_compare (ra0, SCM_CAR (SCM_CDR (ras)), SCM_CAR (ras), 0);
506}
507
1cc91f1b 508
0f2d19dd 509int
1bbd0b84 510scm_ra_greqp (SCM ra0, SCM ras)
0f2d19dd
JB
511{
512 return ra_compare (ra0, SCM_CAR (ras), SCM_CAR (SCM_CDR (ras)), 1);
513}
514
515
0f2d19dd 516int
1bbd0b84 517scm_ra_sum (SCM ra0, SCM ras)
0f2d19dd 518{
04b87de5
MV
519 long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
520 unsigned long i0 = SCM_I_ARRAY_BASE (ra0);
521 long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
522 ra0 = SCM_I_ARRAY_V (ra0);
d2e53ed6 523 if (!scm_is_null(ras))
c209c88e
GB
524 {
525 SCM ra1 = SCM_CAR (ras);
04b87de5
MV
526 unsigned long i1 = SCM_I_ARRAY_BASE (ra1);
527 long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
528 ra1 = SCM_I_ARRAY_V (ra1);
c209c88e
GB
529 switch (SCM_TYP7 (ra0) == SCM_TYP7 (ra1) ? SCM_TYP7 (ra0) : 0)
530 {
531 default:
0f2d19dd 532 {
c209c88e 533 for (; n-- > 0; i0 += inc0, i1 += inc1)
85516012 534 GVSET (ra0, i0, scm_sum (GVREF(ra0, i0), GVREF(ra1, i1)));
c209c88e
GB
535 break;
536 }
c209c88e
GB
537 }
538 }
0f2d19dd
JB
539 return 1;
540}
541
542
1cc91f1b 543
0f2d19dd 544int
1bbd0b84 545scm_ra_difference (SCM ra0, SCM ras)
0f2d19dd 546{
04b87de5
MV
547 long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
548 unsigned long i0 = SCM_I_ARRAY_BASE (ra0);
549 long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
550 ra0 = SCM_I_ARRAY_V (ra0);
d2e53ed6 551 if (scm_is_null (ras))
c209c88e
GB
552 {
553 switch (SCM_TYP7 (ra0))
554 {
555 default:
556 {
c209c88e 557 for (; n-- > 0; i0 += inc0)
85516012 558 GVSET (ra0, i0, scm_difference (GVREF(ra0, i0), SCM_UNDEFINED));
c209c88e
GB
559 break;
560 }
c209c88e
GB
561 }
562 }
0f2d19dd
JB
563 else
564 {
565 SCM ra1 = SCM_CAR (ras);
04b87de5
MV
566 unsigned long i1 = SCM_I_ARRAY_BASE (ra1);
567 long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
568 ra1 = SCM_I_ARRAY_V (ra1);
0f2d19dd
JB
569 switch (SCM_TYP7 (ra0) == SCM_TYP7 (ra1) ? SCM_TYP7 (ra0) : 0)
570 {
571 default:
572 {
0f2d19dd 573 for (; n-- > 0; i0 += inc0, i1 += inc1)
85516012
MV
574 GVSET (ra0, i0, scm_difference (GVREF (ra0, i0),
575 GVREF (ra1, i1)));
0f2d19dd
JB
576 break;
577 }
0f2d19dd
JB
578 }
579 }
580 return 1;
581}
582
583
1cc91f1b 584
0f2d19dd 585int
1bbd0b84 586scm_ra_product (SCM ra0, SCM ras)
0f2d19dd 587{
04b87de5
MV
588 long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
589 unsigned long i0 = SCM_I_ARRAY_BASE (ra0);
590 long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
591 ra0 = SCM_I_ARRAY_V (ra0);
d2e53ed6 592 if (!scm_is_null (ras))
c209c88e
GB
593 {
594 SCM ra1 = SCM_CAR (ras);
04b87de5
MV
595 unsigned long i1 = SCM_I_ARRAY_BASE (ra1);
596 long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
597 ra1 = SCM_I_ARRAY_V (ra1);
c209c88e
GB
598 switch (SCM_TYP7 (ra0) == SCM_TYP7 (ra1) ? SCM_TYP7 (ra0) : 0)
599 {
600 default:
0f2d19dd 601 {
c209c88e 602 for (; n-- > 0; i0 += inc0, i1 += inc1)
85516012
MV
603 GVSET (ra0, i0, scm_product (GVREF (ra0, i0),
604 GVREF (ra1, i1)));
c209c88e 605 }
c209c88e
GB
606 }
607 }
0f2d19dd
JB
608 return 1;
609}
610
1cc91f1b 611
0f2d19dd 612int
1bbd0b84 613scm_ra_divide (SCM ra0, SCM ras)
0f2d19dd 614{
04b87de5
MV
615 long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
616 unsigned long i0 = SCM_I_ARRAY_BASE (ra0);
617 long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
618 ra0 = SCM_I_ARRAY_V (ra0);
d2e53ed6 619 if (scm_is_null (ras))
c209c88e
GB
620 {
621 switch (SCM_TYP7 (ra0))
622 {
623 default:
624 {
c209c88e 625 for (; n-- > 0; i0 += inc0)
85516012 626 GVSET (ra0, i0, scm_divide (GVREF (ra0, i0), SCM_UNDEFINED));
c209c88e
GB
627 break;
628 }
c209c88e
GB
629 }
630 }
0f2d19dd
JB
631 else
632 {
633 SCM ra1 = SCM_CAR (ras);
04b87de5
MV
634 unsigned long i1 = SCM_I_ARRAY_BASE (ra1);
635 long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
636 ra1 = SCM_I_ARRAY_V (ra1);
0f2d19dd
JB
637 switch (SCM_TYP7 (ra0) == SCM_TYP7 (ra1) ? SCM_TYP7 (ra0) : 0)
638 {
639 default:
640 {
0f2d19dd 641 for (; n-- > 0; i0 += inc0, i1 += inc1)
afaf9d0b 642 {
85516012
MV
643 SCM res = scm_divide (GVREF (ra0, i0),
644 GVREF (ra1, i1));
645 GVSET (ra0, i0, res);
afaf9d0b 646 }
0f2d19dd
JB
647 break;
648 }
0f2d19dd
JB
649 }
650 }
651 return 1;
652}
653
1cc91f1b 654
0f2d19dd 655int
1bbd0b84 656scm_array_identity (SCM dst, SCM src)
0f2d19dd
JB
657{
658 return racp (SCM_CAR (src), scm_cons (dst, SCM_EOL));
659}
660
661
1cc91f1b 662
0f2d19dd 663static int
34d19ef6 664ramap (SCM ra0, SCM proc, SCM ras)
0f2d19dd 665{
04b87de5
MV
666 long i = SCM_I_ARRAY_DIMS (ra0)->lbnd;
667 long inc = SCM_I_ARRAY_DIMS (ra0)->inc;
668 long n = SCM_I_ARRAY_DIMS (ra0)->ubnd;
669 long base = SCM_I_ARRAY_BASE (ra0) - i * inc;
670 ra0 = SCM_I_ARRAY_V (ra0);
d2e53ed6 671 if (scm_is_null (ras))
c209c88e 672 for (; i <= n; i++)
85516012 673 GVSET (ra0, i*inc+base, scm_call_0 (proc));
0f2d19dd
JB
674 else
675 {
676 SCM ra1 = SCM_CAR (ras);
34d19ef6 677 SCM args;
04b87de5
MV
678 unsigned long k, i1 = SCM_I_ARRAY_BASE (ra1);
679 long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
680 ra1 = SCM_I_ARRAY_V (ra1);
0f2d19dd 681 ras = SCM_CDR (ras);
d2e53ed6 682 if (scm_is_null(ras))
c209c88e 683 ras = scm_nullvect;
0f2d19dd 684 else
ee67e2fa 685 ras = scm_vector (ras);
34d19ef6 686
0f2d19dd
JB
687 for (; i <= n; i++, i1 += inc1)
688 {
689 args = SCM_EOL;
ee67e2fa 690 for (k = scm_c_vector_length (ras); k--;)
85516012
MV
691 args = scm_cons (GVREF (scm_c_vector_ref (ras, k), i), args);
692 args = scm_cons (GVREF (ra1, i1), args);
693 GVSET (ra0, i*inc+base, scm_apply_0 (proc, args));
0f2d19dd
JB
694 }
695 }
696 return 1;
697}
698
1cc91f1b 699
0f2d19dd 700static int
34d19ef6 701ramap_rp (SCM ra0, SCM proc, SCM ras)
0f2d19dd
JB
702{
703 SCM ra1 = SCM_CAR (ras), ra2 = SCM_CAR (SCM_CDR (ras));
04b87de5
MV
704 long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
705 unsigned long i0 = SCM_I_ARRAY_BASE (ra0), i1 = SCM_I_ARRAY_BASE (ra1), i2 = SCM_I_ARRAY_BASE (ra2);
706 long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
707 long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
708 long inc2 = SCM_I_ARRAY_DIMS (ra1)->inc;
709 ra0 = SCM_I_ARRAY_V (ra0);
710 ra1 = SCM_I_ARRAY_V (ra1);
711 ra2 = SCM_I_ARRAY_V (ra2);
399aba0a
MV
712
713 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
714 if (scm_is_true (scm_c_bitvector_ref (ra0, i0)))
85516012 715 if (scm_is_false (SCM_SUBRF (proc) (GVREF (ra1, i1), GVREF (ra2, i2))))
399aba0a
MV
716 scm_c_bitvector_set_x (ra0, i0, SCM_BOOL_F);
717
0f2d19dd
JB
718 return 1;
719}
720
721
1cc91f1b 722
0f2d19dd 723static int
34d19ef6 724ramap_2o (SCM ra0, SCM proc, SCM ras)
0f2d19dd
JB
725{
726 SCM ra1 = SCM_CAR (ras);
04b87de5
MV
727 long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
728 unsigned long i0 = SCM_I_ARRAY_BASE (ra0), i1 = SCM_I_ARRAY_BASE (ra1);
729 long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc, inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
730 ra0 = SCM_I_ARRAY_V (ra0);
731 ra1 = SCM_I_ARRAY_V (ra1);
0f2d19dd 732 ras = SCM_CDR (ras);
d2e53ed6 733 if (scm_is_null (ras))
c209c88e 734 {
85516012
MV
735 for (; n-- > 0; i0 += inc0, i1 += inc1)
736 GVSET (ra0, i0, SCM_SUBRF (proc) (GVREF (ra1, i1), SCM_UNDEFINED));
c209c88e 737 }
0f2d19dd
JB
738 else
739 {
740 SCM ra2 = SCM_CAR (ras);
04b87de5
MV
741 unsigned long i2 = SCM_I_ARRAY_BASE (ra2);
742 long inc2 = SCM_I_ARRAY_DIMS (ra2)->inc;
743 ra2 = SCM_I_ARRAY_V (ra2);
85516012
MV
744 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
745 GVSET (ra0, i0, SCM_SUBRF (proc) (GVREF (ra1, i1), GVREF (ra2, i2)));
0f2d19dd
JB
746 }
747 return 1;
748}
749
750
1cc91f1b 751
0f2d19dd 752static int
34d19ef6 753ramap_a (SCM ra0, SCM proc, SCM ras)
0f2d19dd 754{
04b87de5
MV
755 long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
756 unsigned long i0 = SCM_I_ARRAY_BASE (ra0);
757 long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
758 ra0 = SCM_I_ARRAY_V (ra0);
d2e53ed6 759 if (scm_is_null (ras))
c209c88e 760 for (; n-- > 0; i0 += inc0)
85516012 761 GVSET (ra0, i0, SCM_SUBRF (proc) (GVREF (ra0, i0), SCM_UNDEFINED));
0f2d19dd
JB
762 else
763 {
764 SCM ra1 = SCM_CAR (ras);
04b87de5
MV
765 unsigned long i1 = SCM_I_ARRAY_BASE (ra1);
766 long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
767 ra1 = SCM_I_ARRAY_V (ra1);
0f2d19dd 768 for (; n-- > 0; i0 += inc0, i1 += inc1)
85516012 769 GVSET (ra0, i0, SCM_SUBRF (proc) (GVREF (ra0, i0), GVREF (ra1, i1)));
0f2d19dd
JB
770 }
771 return 1;
772}
773
f5f2dcff 774
1bbd0b84 775SCM_REGISTER_PROC(s_array_map_in_order_x, "array-map-in-order!", 2, 0, 1, scm_array_map_x);
1cc91f1b 776
718866aa 777SCM_SYMBOL (sym_b, "b");
1bbd0b84 778
3b3b36dd 779SCM_DEFINE (scm_array_map_x, "array-map!", 2, 0, 1,
c209c88e 780 (SCM ra0, SCM proc, SCM lra),
8f85c0c6 781 "@deffnx {Scheme Procedure} array-map-in-order! ra0 proc . lra\n"
b380b885
MD
782 "@var{array1}, @dots{} must have the same number of dimensions as\n"
783 "@var{array0} and have a range for each index which includes the range\n"
784 "for the corresponding index in @var{array0}. @var{proc} is applied to\n"
785 "each tuple of elements of @var{array1} @dots{} and the result is stored\n"
786 "as the corresponding element in @var{array0}. The value returned is\n"
787 "unspecified. The order of application is unspecified.")
1bbd0b84 788#define FUNC_NAME s_scm_array_map_x
0f2d19dd 789{
34d19ef6 790 SCM_VALIDATE_PROC (2, proc);
af45e3b0 791 SCM_VALIDATE_REST_ARGUMENT (lra);
f530e94f 792
0f2d19dd 793 switch (SCM_TYP7 (proc))
c209c88e
GB
794 {
795 default:
796 gencase:
df338a22 797 scm_ramapc (ramap, proc, ra0, lra, FUNC_NAME);
c209c88e 798 return SCM_UNSPECIFIED;
c209c88e 799 case scm_tc7_rpsubr:
0f2d19dd 800 {
c209c88e 801 ra_iproc *p;
718866aa 802 if (!scm_is_typed_array (ra0, sym_b))
0f2d19dd 803 goto gencase;
c209c88e
GB
804 scm_array_fill_x (ra0, SCM_BOOL_T);
805 for (p = ra_rpsubrs; p->name; p++)
bc36d050 806 if (scm_is_eq (proc, p->sproc))
c209c88e 807 {
d2e53ed6 808 while (!scm_is_null (lra) && !scm_is_null (SCM_CDR (lra)))
c209c88e
GB
809 {
810 scm_ramapc (p->vproc, SCM_UNDEFINED, ra0, lra, FUNC_NAME);
811 lra = SCM_CDR (lra);
812 }
813 return SCM_UNSPECIFIED;
814 }
d2e53ed6 815 while (!scm_is_null (lra) && !scm_is_null (SCM_CDR (lra)))
c209c88e
GB
816 {
817 scm_ramapc (ramap_rp, proc, ra0, lra, FUNC_NAME);
818 lra = SCM_CDR (lra);
819 }
0f2d19dd 820 return SCM_UNSPECIFIED;
c209c88e
GB
821 }
822 case scm_tc7_asubr:
d2e53ed6 823 if (scm_is_null (lra))
c209c88e 824 {
5d916ba3 825 SCM fill = SCM_SUBRF (proc) (SCM_UNDEFINED, SCM_UNDEFINED);
c209c88e
GB
826 scm_array_fill_x (ra0, fill);
827 }
828 else
0f2d19dd 829 {
c209c88e 830 SCM tail, ra1 = SCM_CAR (lra);
04b87de5 831 SCM v0 = (SCM_I_ARRAYP (ra0) ? SCM_I_ARRAY_V (ra0) : ra0);
0f2d19dd 832 ra_iproc *p;
c209c88e
GB
833 /* Check to see if order might matter.
834 This might be an argument for a separate
835 SERIAL-ARRAY-MAP! */
bc36d050 836 if (scm_is_eq (v0, ra1)
04b87de5 837 || (SCM_I_ARRAYP (ra1) && scm_is_eq (v0, SCM_I_ARRAY_V (ra1))))
bc36d050 838 if (!scm_is_eq (ra0, ra1)
04b87de5 839 || (SCM_I_ARRAYP(ra0) && !SCM_I_ARRAY_CONTP(ra0)))
c209c88e 840 goto gencase;
d2e53ed6 841 for (tail = SCM_CDR (lra); !scm_is_null (tail); tail = SCM_CDR (tail))
c209c88e
GB
842 {
843 ra1 = SCM_CAR (tail);
bc36d050 844 if (scm_is_eq (v0, ra1)
04b87de5 845 || (SCM_I_ARRAYP (ra1) && scm_is_eq (v0, SCM_I_ARRAY_V (ra1))))
c209c88e
GB
846 goto gencase;
847 }
848 for (p = ra_asubrs; p->name; p++)
bc36d050 849 if (scm_is_eq (proc, p->sproc))
0f2d19dd 850 {
bc36d050 851 if (!scm_is_eq (ra0, SCM_CAR (lra)))
c209c88e
GB
852 scm_ramapc (scm_array_identity, SCM_UNDEFINED, ra0, scm_cons (SCM_CAR (lra), SCM_EOL), FUNC_NAME);
853 lra = SCM_CDR (lra);
854 while (1)
0f2d19dd 855 {
c209c88e
GB
856 scm_ramapc (p->vproc, SCM_UNDEFINED, ra0, lra, FUNC_NAME);
857 if (SCM_IMP (lra) || SCM_IMP (SCM_CDR (lra)))
858 return SCM_UNSPECIFIED;
0f2d19dd
JB
859 lra = SCM_CDR (lra);
860 }
0f2d19dd 861 }
c209c88e
GB
862 scm_ramapc (ramap_2o, proc, ra0, lra, FUNC_NAME);
863 lra = SCM_CDR (lra);
864 if (SCM_NIMP (lra))
865 for (lra = SCM_CDR (lra); SCM_NIMP (lra); lra = SCM_CDR (lra))
866 scm_ramapc (ramap_a, proc, ra0, lra, FUNC_NAME);
0f2d19dd 867 }
c209c88e
GB
868 return SCM_UNSPECIFIED;
869 }
0f2d19dd 870}
1bbd0b84 871#undef FUNC_NAME
0f2d19dd 872
1cc91f1b 873
0f2d19dd 874static int
34d19ef6 875rafe (SCM ra0, SCM proc, SCM ras)
0f2d19dd 876{
04b87de5
MV
877 long i = SCM_I_ARRAY_DIMS (ra0)->lbnd;
878 unsigned long i0 = SCM_I_ARRAY_BASE (ra0);
879 long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
880 long n = SCM_I_ARRAY_DIMS (ra0)->ubnd;
881 ra0 = SCM_I_ARRAY_V (ra0);
d2e53ed6 882 if (scm_is_null (ras))
c209c88e 883 for (; i <= n; i++, i0 += inc0)
85516012 884 scm_call_1 (proc, GVREF (ra0, i0));
0f2d19dd
JB
885 else
886 {
887 SCM ra1 = SCM_CAR (ras);
34d19ef6 888 SCM args;
04b87de5
MV
889 unsigned long k, i1 = SCM_I_ARRAY_BASE (ra1);
890 long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
891 ra1 = SCM_I_ARRAY_V (ra1);
0f2d19dd 892 ras = SCM_CDR (ras);
d2e53ed6 893 if (scm_is_null(ras))
c209c88e 894 ras = scm_nullvect;
0f2d19dd 895 else
ee67e2fa 896 ras = scm_vector (ras);
0f2d19dd
JB
897 for (; i <= n; i++, i0 += inc0, i1 += inc1)
898 {
899 args = SCM_EOL;
ee67e2fa 900 for (k = scm_c_vector_length (ras); k--;)
85516012
MV
901 args = scm_cons (GVREF (scm_c_vector_ref (ras, k), i), args);
902 args = scm_cons2 (GVREF (ra0, i0), GVREF (ra1, i1), args);
fdc28395 903 scm_apply_0 (proc, args);
0f2d19dd
JB
904 }
905 }
906 return 1;
907}
908
909
3b3b36dd 910SCM_DEFINE (scm_array_for_each, "array-for-each", 2, 0, 1,
c209c88e 911 (SCM proc, SCM ra0, SCM lra),
8f85c0c6 912 "Apply @var{proc} to each tuple of elements of @var{array0} @dots{}\n"
b380b885 913 "in row-major order. The value returned is unspecified.")
1bbd0b84 914#define FUNC_NAME s_scm_array_for_each
0f2d19dd 915{
34d19ef6 916 SCM_VALIDATE_PROC (1, proc);
af45e3b0 917 SCM_VALIDATE_REST_ARGUMENT (lra);
c209c88e 918 scm_ramapc (rafe, proc, ra0, lra, FUNC_NAME);
0f2d19dd
JB
919 return SCM_UNSPECIFIED;
920}
1bbd0b84 921#undef FUNC_NAME
0f2d19dd 922
3b3b36dd 923SCM_DEFINE (scm_array_index_map_x, "array-index-map!", 2, 0, 0,
c209c88e 924 (SCM ra, SCM proc),
8f85c0c6 925 "Apply @var{proc} to the indices of each element of @var{array} in\n"
b380b885
MD
926 "turn, storing the result in the corresponding element. The value\n"
927 "returned and the order of application are unspecified.\n\n"
928 "One can implement @var{array-indexes} as\n"
1e6808ea 929 "@lisp\n"
b380b885
MD
930 "(define (array-indexes array)\n"
931 " (let ((ra (apply make-array #f (array-shape array))))\n"
932 " (array-index-map! ra (lambda x x))\n"
933 " ra))\n"
1e6808ea 934 "@end lisp\n"
b380b885 935 "Another example:\n"
1e6808ea 936 "@lisp\n"
b380b885
MD
937 "(define (apl:index-generator n)\n"
938 " (let ((v (make-uniform-vector n 1)))\n"
939 " (array-index-map! v (lambda (i) i))\n"
940 " v))\n"
1e6808ea 941 "@end lisp")
1bbd0b84 942#define FUNC_NAME s_scm_array_index_map_x
0f2d19dd 943{
c014a02e 944 unsigned long i;
34d19ef6 945 SCM_VALIDATE_PROC (2, proc);
399aba0a 946
5ead53fc 947 if (SCM_I_ARRAYP (ra))
399aba0a
MV
948 {
949 SCM args = SCM_EOL;
04b87de5 950 int j, k, kmax = SCM_I_ARRAY_NDIM (ra) - 1;
b4b33636
MV
951 long *vinds;
952
399aba0a
MV
953 if (kmax < 0)
954 return scm_array_set_x (ra, scm_call_0 (proc), SCM_EOL);
b4b33636 955
d66b74dc
LC
956 vinds = scm_gc_malloc_pointerless (sizeof(long) * SCM_I_ARRAY_NDIM (ra),
957 indices_gc_hint);
b4b33636 958
399aba0a 959 for (k = 0; k <= kmax; k++)
04b87de5 960 vinds[k] = SCM_I_ARRAY_DIMS (ra)[k].lbnd;
399aba0a
MV
961 k = kmax;
962 do
963 {
964 if (k == kmax)
965 {
04b87de5 966 vinds[k] = SCM_I_ARRAY_DIMS (ra)[k].lbnd;
b4b33636 967 i = cind (ra, vinds);
04b87de5 968 for (; vinds[k] <= SCM_I_ARRAY_DIMS (ra)[k].ubnd; vinds[k]++)
399aba0a
MV
969 {
970 for (j = kmax + 1, args = SCM_EOL; j--;)
971 args = scm_cons (scm_from_long (vinds[j]), args);
04b87de5
MV
972 GVSET (SCM_I_ARRAY_V (ra), i, scm_apply_0 (proc, args));
973 i += SCM_I_ARRAY_DIMS (ra)[k].inc;
399aba0a
MV
974 }
975 k--;
976 continue;
977 }
04b87de5 978 if (vinds[k] < SCM_I_ARRAY_DIMS (ra)[k].ubnd)
399aba0a
MV
979 {
980 vinds[k]++;
981 k++;
982 continue;
983 }
04b87de5 984 vinds[k] = SCM_I_ARRAY_DIMS (ra)[k].lbnd - 1;
399aba0a
MV
985 k--;
986 }
987 while (k >= 0);
b4b33636 988
399aba0a 989 return SCM_UNSPECIFIED;
e42c09cc 990 }
5ead53fc
MV
991 else if (scm_is_generalized_vector (ra))
992 {
993 size_t length = scm_c_generalized_vector_length (ra);
994 for (i = 0; i < length; i++)
995 GVSET (ra, i, scm_call_1 (proc, scm_from_ulong (i)));
996 return SCM_UNSPECIFIED;
997 }
998 else
399aba0a 999 scm_wrong_type_arg_msg (NULL, 0, ra, "array");
0f2d19dd 1000}
1bbd0b84 1001#undef FUNC_NAME
0f2d19dd 1002
1cc91f1b 1003
0f2d19dd 1004static int
34d19ef6 1005raeql_1 (SCM ra0, SCM as_equal, SCM ra1)
0f2d19dd 1006{
c014a02e
ML
1007 unsigned long i0 = 0, i1 = 0;
1008 long inc0 = 1, inc1 = 1;
1009 unsigned long n;
0f2d19dd 1010 ra1 = SCM_CAR (ra1);
04b87de5 1011 if (SCM_I_ARRAYP(ra0))
c209c88e 1012 {
04b87de5
MV
1013 n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
1014 i0 = SCM_I_ARRAY_BASE (ra0);
1015 inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
1016 ra0 = SCM_I_ARRAY_V (ra0);
c209c88e 1017 }
e466c6a2 1018 else
399aba0a
MV
1019 n = scm_c_generalized_vector_length (ra0);
1020
04b87de5 1021 if (SCM_I_ARRAYP (ra1))
c209c88e 1022 {
04b87de5
MV
1023 i1 = SCM_I_ARRAY_BASE (ra1);
1024 inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
1025 ra1 = SCM_I_ARRAY_V (ra1);
c209c88e 1026 }
399aba0a
MV
1027
1028 if (scm_is_generalized_vector (ra0))
c209c88e 1029 {
c209c88e
GB
1030 for (; n--; i0 += inc0, i1 += inc1)
1031 {
7888309b 1032 if (scm_is_false (as_equal))
c209c88e 1033 {
85516012 1034 if (scm_is_false (scm_array_equal_p (GVREF (ra0, i0), GVREF (ra1, i1))))
c209c88e
GB
1035 return 0;
1036 }
85516012 1037 else if (scm_is_false (scm_equal_p (GVREF (ra0, i0), GVREF (ra1, i1))))
c209c88e
GB
1038 return 0;
1039 }
1040 return 1;
c209c88e 1041 }
399aba0a
MV
1042 else
1043 return 0;
0f2d19dd
JB
1044}
1045
1046
1cc91f1b 1047
0f2d19dd 1048static int
34d19ef6 1049raeql (SCM ra0, SCM as_equal, SCM ra1)
0f2d19dd
JB
1050{
1051 SCM v0 = ra0, v1 = ra1;
92c2555f
MV
1052 scm_t_array_dim dim0, dim1;
1053 scm_t_array_dim *s0 = &dim0, *s1 = &dim1;
c014a02e 1054 unsigned long bas0 = 0, bas1 = 0;
0f2d19dd 1055 int k, unroll = 1, vlen = 1, ndim = 1;
04b87de5 1056 if (SCM_I_ARRAYP (ra0))
c209c88e 1057 {
04b87de5
MV
1058 ndim = SCM_I_ARRAY_NDIM (ra0);
1059 s0 = SCM_I_ARRAY_DIMS (ra0);
1060 bas0 = SCM_I_ARRAY_BASE (ra0);
1061 v0 = SCM_I_ARRAY_V (ra0);
c209c88e 1062 }
0f2d19dd
JB
1063 else
1064 {
1065 s0->inc = 1;
1066 s0->lbnd = 0;
ee67e2fa 1067 s0->ubnd = scm_c_generalized_vector_length (v0) - 1;
0f2d19dd
JB
1068 unroll = 0;
1069 }
04b87de5 1070 if (SCM_I_ARRAYP (ra1))
c209c88e 1071 {
04b87de5 1072 if (ndim != SCM_I_ARRAY_NDIM (ra1))
c209c88e 1073 return 0;
04b87de5
MV
1074 s1 = SCM_I_ARRAY_DIMS (ra1);
1075 bas1 = SCM_I_ARRAY_BASE (ra1);
1076 v1 = SCM_I_ARRAY_V (ra1);
c209c88e 1077 }
0f2d19dd
JB
1078 else
1079 {
c209c88e
GB
1080 /*
1081 Huh ? Schizophrenic return type. --hwn
1082 */
0f2d19dd 1083 if (1 != ndim)
c209c88e 1084 return 0;
0f2d19dd
JB
1085 s1->inc = 1;
1086 s1->lbnd = 0;
ee67e2fa 1087 s1->ubnd = scm_c_generalized_vector_length (v1) - 1;
0f2d19dd
JB
1088 unroll = 0;
1089 }
1090 if (SCM_TYP7 (v0) != SCM_TYP7 (v1))
1091 return 0;
1092 for (k = ndim; k--;)
1093 {
1094 if (s0[k].lbnd != s1[k].lbnd || s0[k].ubnd != s1[k].ubnd)
1095 return 0;
1096 if (unroll)
1097 {
1098 unroll = (s0[k].inc == s1[k].inc);
1099 vlen *= s0[k].ubnd - s1[k].lbnd + 1;
1100 }
1101 }
bc36d050 1102 if (unroll && bas0 == bas1 && scm_is_eq (v0, v1))
c209c88e 1103 return 1;
0f2d19dd
JB
1104 return scm_ramapc (raeql_1, as_equal, ra0, scm_cons (ra1, SCM_EOL), "");
1105}
1106
1cc91f1b 1107
0f2d19dd 1108SCM
1bbd0b84 1109scm_raequal (SCM ra0, SCM ra1)
0f2d19dd 1110{
7888309b 1111 return scm_from_bool(raeql (ra0, SCM_BOOL_T, ra1));
0f2d19dd
JB
1112}
1113
4079f87e 1114#if 0
c3ee7520
GB
1115/* GJB:FIXME:: Why not use SCM_DEFINE1 for array-equal? */
1116SCM_DEFINE1 (scm_array_equal_p, "array-equal?", scm_tc7_rpsubr,
c209c88e 1117 (SCM ra0, SCM ra1),
1e6808ea
MG
1118 "Return @code{#t} iff all arguments are arrays with the same\n"
1119 "shape, the same type, and have corresponding elements which are\n"
1120 "either @code{equal?} or @code{array-equal?}. This function\n"
1121 "differs from @code{equal?} in that a one dimensional shared\n"
1122 "array may be @var{array-equal?} but not @var{equal?} to a\n"
1123 "vector or uniform vector.")
4079f87e 1124#define FUNC_NAME s_scm_array_equal_p
0f981281
GB
1125{
1126}
4079f87e
GB
1127#undef FUNC_NAME
1128#endif
1129
0f2d19dd
JB
1130static char s_array_equal_p[] = "array-equal?";
1131
1cc91f1b 1132
0f2d19dd 1133SCM
1bbd0b84 1134scm_array_equal_p (SCM ra0, SCM ra1)
0f2d19dd 1135{
04b87de5 1136 if (SCM_I_ARRAYP (ra0) || SCM_I_ARRAYP (ra1))
399aba0a
MV
1137 return scm_from_bool(raeql (ra0, SCM_BOOL_F, ra1));
1138 return scm_equal_p (ra0, ra1);
0f2d19dd
JB
1139}
1140
1141
1cc91f1b 1142static void
1bbd0b84 1143init_raprocs (ra_iproc *subra)
0f2d19dd
JB
1144{
1145 for (; subra->name; subra++)
86d31dfe 1146 {
cc95e00a 1147 SCM sym = scm_from_locale_symbol (subra->name);
86d31dfe
MV
1148 SCM var =
1149 scm_sym2var (sym, scm_current_module_lookup_closure (), SCM_BOOL_F);
1150 if (var != SCM_BOOL_F)
1151 subra->sproc = SCM_VARIABLE_REF (var);
1152 else
1153 subra->sproc = SCM_BOOL_F;
1154 }
0f2d19dd
JB
1155}
1156
1cc91f1b 1157
0f2d19dd 1158void
5d1b3b2d 1159scm_init_array_map (void)
0f2d19dd
JB
1160{
1161 init_raprocs (ra_rpsubrs);
1162 init_raprocs (ra_asubrs);
9a441ddb 1163 scm_c_define_subr (s_array_equal_p, scm_tc7_rpsubr, scm_array_equal_p);
04b87de5 1164 scm_smobs[SCM_TC2SMOBNUM (scm_i_tc16_array)].equalp = scm_raequal;
5d1b3b2d 1165#include "libguile/array-map.x"
1bbd0b84 1166 scm_add_feature (s_scm_array_for_each);
0f2d19dd 1167}
89e00824
ML
1168
1169/*
1170 Local Variables:
1171 c-file-style: "gnu"
1172 End:
1173*/