Coalesce tree traversals made for warnings.
[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
14b18ed6 701ramap_dsubr (SCM ra0, SCM proc, SCM ras)
0f2d19dd
JB
702{
703 SCM ra1 = SCM_CAR (ras);
04b87de5
MV
704 unsigned long i0 = SCM_I_ARRAY_BASE (ra0), i1 = SCM_I_ARRAY_BASE (ra1);
705 long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc, inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
706 long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra1)->lbnd + 1;
707 ra0 = SCM_I_ARRAY_V (ra0);
708 ra1 = SCM_I_ARRAY_V (ra1);
ff467021 709 switch (SCM_TYP7 (ra0))
c209c88e
GB
710 {
711 default:
afaf9d0b 712 for (; n-- > 0; i0 += inc0, i1 += inc1)
85516012 713 GVSET (ra0, i0, scm_call_1 (proc, GVREF (ra1, i1)));
afaf9d0b 714 break;
c209c88e 715 }
0f2d19dd
JB
716 return 1;
717}
718
719
1cc91f1b 720
0f2d19dd 721static int
34d19ef6 722ramap_rp (SCM ra0, SCM proc, SCM ras)
0f2d19dd
JB
723{
724 SCM ra1 = SCM_CAR (ras), ra2 = SCM_CAR (SCM_CDR (ras));
04b87de5
MV
725 long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
726 unsigned long i0 = SCM_I_ARRAY_BASE (ra0), i1 = SCM_I_ARRAY_BASE (ra1), i2 = SCM_I_ARRAY_BASE (ra2);
727 long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
728 long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
729 long inc2 = SCM_I_ARRAY_DIMS (ra1)->inc;
730 ra0 = SCM_I_ARRAY_V (ra0);
731 ra1 = SCM_I_ARRAY_V (ra1);
732 ra2 = SCM_I_ARRAY_V (ra2);
399aba0a
MV
733
734 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
735 if (scm_is_true (scm_c_bitvector_ref (ra0, i0)))
85516012 736 if (scm_is_false (SCM_SUBRF (proc) (GVREF (ra1, i1), GVREF (ra2, i2))))
399aba0a
MV
737 scm_c_bitvector_set_x (ra0, i0, SCM_BOOL_F);
738
0f2d19dd
JB
739 return 1;
740}
741
742
1cc91f1b 743
0f2d19dd 744static int
34d19ef6 745ramap_1 (SCM ra0, SCM proc, SCM ras)
0f2d19dd
JB
746{
747 SCM ra1 = SCM_CAR (ras);
04b87de5
MV
748 long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
749 unsigned long i0 = SCM_I_ARRAY_BASE (ra0), i1 = SCM_I_ARRAY_BASE (ra1);
750 long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc, inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
751 ra0 = SCM_I_ARRAY_V (ra0);
752 ra1 = SCM_I_ARRAY_V (ra1);
95f5b0f5 753 if (scm_tc7_vector == SCM_TYP7 (ra0) || scm_tc7_wvect == SCM_TYP7 (ra0))
0f2d19dd 754 for (; n-- > 0; i0 += inc0, i1 += inc1)
85516012 755 GVSET (ra0, i0, SCM_SUBRF (proc) (GVREF (ra1, i1)));
0f2d19dd
JB
756 else
757 for (; n-- > 0; i0 += inc0, i1 += inc1)
85516012 758 GVSET (ra0, i0, SCM_SUBRF (proc) (GVREF (ra1, i1)));
0f2d19dd
JB
759 return 1;
760}
761
762
1cc91f1b 763
0f2d19dd 764static int
34d19ef6 765ramap_2o (SCM ra0, SCM proc, SCM ras)
0f2d19dd
JB
766{
767 SCM ra1 = SCM_CAR (ras);
04b87de5
MV
768 long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
769 unsigned long i0 = SCM_I_ARRAY_BASE (ra0), i1 = SCM_I_ARRAY_BASE (ra1);
770 long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc, inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
771 ra0 = SCM_I_ARRAY_V (ra0);
772 ra1 = SCM_I_ARRAY_V (ra1);
0f2d19dd 773 ras = SCM_CDR (ras);
d2e53ed6 774 if (scm_is_null (ras))
c209c88e 775 {
85516012
MV
776 for (; n-- > 0; i0 += inc0, i1 += inc1)
777 GVSET (ra0, i0, SCM_SUBRF (proc) (GVREF (ra1, i1), SCM_UNDEFINED));
c209c88e 778 }
0f2d19dd
JB
779 else
780 {
781 SCM ra2 = SCM_CAR (ras);
04b87de5
MV
782 unsigned long i2 = SCM_I_ARRAY_BASE (ra2);
783 long inc2 = SCM_I_ARRAY_DIMS (ra2)->inc;
784 ra2 = SCM_I_ARRAY_V (ra2);
85516012
MV
785 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
786 GVSET (ra0, i0, SCM_SUBRF (proc) (GVREF (ra1, i1), GVREF (ra2, i2)));
0f2d19dd
JB
787 }
788 return 1;
789}
790
791
1cc91f1b 792
0f2d19dd 793static int
34d19ef6 794ramap_a (SCM ra0, SCM proc, SCM ras)
0f2d19dd 795{
04b87de5
MV
796 long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
797 unsigned long i0 = SCM_I_ARRAY_BASE (ra0);
798 long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
799 ra0 = SCM_I_ARRAY_V (ra0);
d2e53ed6 800 if (scm_is_null (ras))
c209c88e 801 for (; n-- > 0; i0 += inc0)
85516012 802 GVSET (ra0, i0, SCM_SUBRF (proc) (GVREF (ra0, i0), SCM_UNDEFINED));
0f2d19dd
JB
803 else
804 {
805 SCM ra1 = SCM_CAR (ras);
04b87de5
MV
806 unsigned long i1 = SCM_I_ARRAY_BASE (ra1);
807 long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
808 ra1 = SCM_I_ARRAY_V (ra1);
0f2d19dd 809 for (; n-- > 0; i0 += inc0, i1 += inc1)
85516012 810 GVSET (ra0, i0, SCM_SUBRF (proc) (GVREF (ra0, i0), GVREF (ra1, i1)));
0f2d19dd
JB
811 }
812 return 1;
813}
814
f5f2dcff 815
1bbd0b84 816SCM_REGISTER_PROC(s_array_map_in_order_x, "array-map-in-order!", 2, 0, 1, scm_array_map_x);
1cc91f1b 817
718866aa 818SCM_SYMBOL (sym_b, "b");
1bbd0b84 819
3b3b36dd 820SCM_DEFINE (scm_array_map_x, "array-map!", 2, 0, 1,
c209c88e 821 (SCM ra0, SCM proc, SCM lra),
8f85c0c6 822 "@deffnx {Scheme Procedure} array-map-in-order! ra0 proc . lra\n"
b380b885
MD
823 "@var{array1}, @dots{} must have the same number of dimensions as\n"
824 "@var{array0} and have a range for each index which includes the range\n"
825 "for the corresponding index in @var{array0}. @var{proc} is applied to\n"
826 "each tuple of elements of @var{array1} @dots{} and the result is stored\n"
827 "as the corresponding element in @var{array0}. The value returned is\n"
828 "unspecified. The order of application is unspecified.")
1bbd0b84 829#define FUNC_NAME s_scm_array_map_x
0f2d19dd 830{
34d19ef6 831 SCM_VALIDATE_PROC (2, proc);
af45e3b0 832 SCM_VALIDATE_REST_ARGUMENT (lra);
f530e94f 833
0f2d19dd 834 switch (SCM_TYP7 (proc))
c209c88e
GB
835 {
836 default:
837 gencase:
838 scm_ramapc (ramap, proc, ra0, lra, FUNC_NAME);
839 return SCM_UNSPECIFIED;
840 case scm_tc7_subr_1:
f530e94f
KR
841 if (! scm_is_pair (lra))
842 SCM_WRONG_NUM_ARGS (); /* need 1 source */
c209c88e
GB
843 scm_ramapc (ramap_1, proc, ra0, lra, FUNC_NAME);
844 return SCM_UNSPECIFIED;
845 case scm_tc7_subr_2:
f530e94f
KR
846 if (! (scm_is_pair (lra) && scm_is_pair (SCM_CDR (lra))))
847 SCM_WRONG_NUM_ARGS (); /* need 2 sources */
848 goto subr_2o;
c209c88e 849 case scm_tc7_subr_2o:
f530e94f
KR
850 if (! scm_is_pair (lra))
851 SCM_WRONG_NUM_ARGS (); /* need 1 source */
852 subr_2o:
c209c88e
GB
853 scm_ramapc (ramap_2o, proc, ra0, lra, FUNC_NAME);
854 return SCM_UNSPECIFIED;
14b18ed6 855 case scm_tc7_dsubr:
f530e94f
KR
856 if (! scm_is_pair (lra))
857 SCM_WRONG_NUM_ARGS (); /* need 1 source */
14b18ed6 858 scm_ramapc (ramap_dsubr, proc, ra0, lra, FUNC_NAME);
c209c88e
GB
859 return SCM_UNSPECIFIED;
860 case scm_tc7_rpsubr:
0f2d19dd 861 {
c209c88e 862 ra_iproc *p;
718866aa 863 if (!scm_is_typed_array (ra0, sym_b))
0f2d19dd 864 goto gencase;
c209c88e
GB
865 scm_array_fill_x (ra0, SCM_BOOL_T);
866 for (p = ra_rpsubrs; p->name; p++)
bc36d050 867 if (scm_is_eq (proc, p->sproc))
c209c88e 868 {
d2e53ed6 869 while (!scm_is_null (lra) && !scm_is_null (SCM_CDR (lra)))
c209c88e
GB
870 {
871 scm_ramapc (p->vproc, SCM_UNDEFINED, ra0, lra, FUNC_NAME);
872 lra = SCM_CDR (lra);
873 }
874 return SCM_UNSPECIFIED;
875 }
d2e53ed6 876 while (!scm_is_null (lra) && !scm_is_null (SCM_CDR (lra)))
c209c88e
GB
877 {
878 scm_ramapc (ramap_rp, proc, ra0, lra, FUNC_NAME);
879 lra = SCM_CDR (lra);
880 }
0f2d19dd 881 return SCM_UNSPECIFIED;
c209c88e
GB
882 }
883 case scm_tc7_asubr:
d2e53ed6 884 if (scm_is_null (lra))
c209c88e 885 {
5d916ba3 886 SCM fill = SCM_SUBRF (proc) (SCM_UNDEFINED, SCM_UNDEFINED);
c209c88e
GB
887 scm_array_fill_x (ra0, fill);
888 }
889 else
0f2d19dd 890 {
c209c88e 891 SCM tail, ra1 = SCM_CAR (lra);
04b87de5 892 SCM v0 = (SCM_I_ARRAYP (ra0) ? SCM_I_ARRAY_V (ra0) : ra0);
0f2d19dd 893 ra_iproc *p;
c209c88e
GB
894 /* Check to see if order might matter.
895 This might be an argument for a separate
896 SERIAL-ARRAY-MAP! */
bc36d050 897 if (scm_is_eq (v0, ra1)
04b87de5 898 || (SCM_I_ARRAYP (ra1) && scm_is_eq (v0, SCM_I_ARRAY_V (ra1))))
bc36d050 899 if (!scm_is_eq (ra0, ra1)
04b87de5 900 || (SCM_I_ARRAYP(ra0) && !SCM_I_ARRAY_CONTP(ra0)))
c209c88e 901 goto gencase;
d2e53ed6 902 for (tail = SCM_CDR (lra); !scm_is_null (tail); tail = SCM_CDR (tail))
c209c88e
GB
903 {
904 ra1 = SCM_CAR (tail);
bc36d050 905 if (scm_is_eq (v0, ra1)
04b87de5 906 || (SCM_I_ARRAYP (ra1) && scm_is_eq (v0, SCM_I_ARRAY_V (ra1))))
c209c88e
GB
907 goto gencase;
908 }
909 for (p = ra_asubrs; p->name; p++)
bc36d050 910 if (scm_is_eq (proc, p->sproc))
0f2d19dd 911 {
bc36d050 912 if (!scm_is_eq (ra0, SCM_CAR (lra)))
c209c88e
GB
913 scm_ramapc (scm_array_identity, SCM_UNDEFINED, ra0, scm_cons (SCM_CAR (lra), SCM_EOL), FUNC_NAME);
914 lra = SCM_CDR (lra);
915 while (1)
0f2d19dd 916 {
c209c88e
GB
917 scm_ramapc (p->vproc, SCM_UNDEFINED, ra0, lra, FUNC_NAME);
918 if (SCM_IMP (lra) || SCM_IMP (SCM_CDR (lra)))
919 return SCM_UNSPECIFIED;
0f2d19dd
JB
920 lra = SCM_CDR (lra);
921 }
0f2d19dd 922 }
c209c88e
GB
923 scm_ramapc (ramap_2o, proc, ra0, lra, FUNC_NAME);
924 lra = SCM_CDR (lra);
925 if (SCM_NIMP (lra))
926 for (lra = SCM_CDR (lra); SCM_NIMP (lra); lra = SCM_CDR (lra))
927 scm_ramapc (ramap_a, proc, ra0, lra, FUNC_NAME);
0f2d19dd 928 }
c209c88e
GB
929 return SCM_UNSPECIFIED;
930 }
0f2d19dd 931}
1bbd0b84 932#undef FUNC_NAME
0f2d19dd 933
1cc91f1b 934
0f2d19dd 935static int
34d19ef6 936rafe (SCM ra0, SCM proc, SCM ras)
0f2d19dd 937{
04b87de5
MV
938 long i = SCM_I_ARRAY_DIMS (ra0)->lbnd;
939 unsigned long i0 = SCM_I_ARRAY_BASE (ra0);
940 long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
941 long n = SCM_I_ARRAY_DIMS (ra0)->ubnd;
942 ra0 = SCM_I_ARRAY_V (ra0);
d2e53ed6 943 if (scm_is_null (ras))
c209c88e 944 for (; i <= n; i++, i0 += inc0)
85516012 945 scm_call_1 (proc, GVREF (ra0, i0));
0f2d19dd
JB
946 else
947 {
948 SCM ra1 = SCM_CAR (ras);
34d19ef6 949 SCM args;
04b87de5
MV
950 unsigned long k, i1 = SCM_I_ARRAY_BASE (ra1);
951 long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
952 ra1 = SCM_I_ARRAY_V (ra1);
0f2d19dd 953 ras = SCM_CDR (ras);
d2e53ed6 954 if (scm_is_null(ras))
c209c88e 955 ras = scm_nullvect;
0f2d19dd 956 else
ee67e2fa 957 ras = scm_vector (ras);
0f2d19dd
JB
958 for (; i <= n; i++, i0 += inc0, i1 += inc1)
959 {
960 args = SCM_EOL;
ee67e2fa 961 for (k = scm_c_vector_length (ras); k--;)
85516012
MV
962 args = scm_cons (GVREF (scm_c_vector_ref (ras, k), i), args);
963 args = scm_cons2 (GVREF (ra0, i0), GVREF (ra1, i1), args);
fdc28395 964 scm_apply_0 (proc, args);
0f2d19dd
JB
965 }
966 }
967 return 1;
968}
969
970
3b3b36dd 971SCM_DEFINE (scm_array_for_each, "array-for-each", 2, 0, 1,
c209c88e 972 (SCM proc, SCM ra0, SCM lra),
8f85c0c6 973 "Apply @var{proc} to each tuple of elements of @var{array0} @dots{}\n"
b380b885 974 "in row-major order. The value returned is unspecified.")
1bbd0b84 975#define FUNC_NAME s_scm_array_for_each
0f2d19dd 976{
34d19ef6 977 SCM_VALIDATE_PROC (1, proc);
af45e3b0 978 SCM_VALIDATE_REST_ARGUMENT (lra);
c209c88e 979 scm_ramapc (rafe, proc, ra0, lra, FUNC_NAME);
0f2d19dd
JB
980 return SCM_UNSPECIFIED;
981}
1bbd0b84 982#undef FUNC_NAME
0f2d19dd 983
3b3b36dd 984SCM_DEFINE (scm_array_index_map_x, "array-index-map!", 2, 0, 0,
c209c88e 985 (SCM ra, SCM proc),
8f85c0c6 986 "Apply @var{proc} to the indices of each element of @var{array} in\n"
b380b885
MD
987 "turn, storing the result in the corresponding element. The value\n"
988 "returned and the order of application are unspecified.\n\n"
989 "One can implement @var{array-indexes} as\n"
1e6808ea 990 "@lisp\n"
b380b885
MD
991 "(define (array-indexes array)\n"
992 " (let ((ra (apply make-array #f (array-shape array))))\n"
993 " (array-index-map! ra (lambda x x))\n"
994 " ra))\n"
1e6808ea 995 "@end lisp\n"
b380b885 996 "Another example:\n"
1e6808ea 997 "@lisp\n"
b380b885
MD
998 "(define (apl:index-generator n)\n"
999 " (let ((v (make-uniform-vector n 1)))\n"
1000 " (array-index-map! v (lambda (i) i))\n"
1001 " v))\n"
1e6808ea 1002 "@end lisp")
1bbd0b84 1003#define FUNC_NAME s_scm_array_index_map_x
0f2d19dd 1004{
c014a02e 1005 unsigned long i;
34d19ef6 1006 SCM_VALIDATE_PROC (2, proc);
399aba0a 1007
5ead53fc 1008 if (SCM_I_ARRAYP (ra))
399aba0a
MV
1009 {
1010 SCM args = SCM_EOL;
04b87de5 1011 int j, k, kmax = SCM_I_ARRAY_NDIM (ra) - 1;
b4b33636
MV
1012 long *vinds;
1013
399aba0a
MV
1014 if (kmax < 0)
1015 return scm_array_set_x (ra, scm_call_0 (proc), SCM_EOL);
b4b33636 1016
d66b74dc
LC
1017 vinds = scm_gc_malloc_pointerless (sizeof(long) * SCM_I_ARRAY_NDIM (ra),
1018 indices_gc_hint);
b4b33636 1019
399aba0a 1020 for (k = 0; k <= kmax; k++)
04b87de5 1021 vinds[k] = SCM_I_ARRAY_DIMS (ra)[k].lbnd;
399aba0a
MV
1022 k = kmax;
1023 do
1024 {
1025 if (k == kmax)
1026 {
04b87de5 1027 vinds[k] = SCM_I_ARRAY_DIMS (ra)[k].lbnd;
b4b33636 1028 i = cind (ra, vinds);
04b87de5 1029 for (; vinds[k] <= SCM_I_ARRAY_DIMS (ra)[k].ubnd; vinds[k]++)
399aba0a
MV
1030 {
1031 for (j = kmax + 1, args = SCM_EOL; j--;)
1032 args = scm_cons (scm_from_long (vinds[j]), args);
04b87de5
MV
1033 GVSET (SCM_I_ARRAY_V (ra), i, scm_apply_0 (proc, args));
1034 i += SCM_I_ARRAY_DIMS (ra)[k].inc;
399aba0a
MV
1035 }
1036 k--;
1037 continue;
1038 }
04b87de5 1039 if (vinds[k] < SCM_I_ARRAY_DIMS (ra)[k].ubnd)
399aba0a
MV
1040 {
1041 vinds[k]++;
1042 k++;
1043 continue;
1044 }
04b87de5 1045 vinds[k] = SCM_I_ARRAY_DIMS (ra)[k].lbnd - 1;
399aba0a
MV
1046 k--;
1047 }
1048 while (k >= 0);
b4b33636 1049
399aba0a 1050 return SCM_UNSPECIFIED;
e42c09cc 1051 }
5ead53fc
MV
1052 else if (scm_is_generalized_vector (ra))
1053 {
1054 size_t length = scm_c_generalized_vector_length (ra);
1055 for (i = 0; i < length; i++)
1056 GVSET (ra, i, scm_call_1 (proc, scm_from_ulong (i)));
1057 return SCM_UNSPECIFIED;
1058 }
1059 else
399aba0a 1060 scm_wrong_type_arg_msg (NULL, 0, ra, "array");
0f2d19dd 1061}
1bbd0b84 1062#undef FUNC_NAME
0f2d19dd 1063
1cc91f1b 1064
0f2d19dd 1065static int
34d19ef6 1066raeql_1 (SCM ra0, SCM as_equal, SCM ra1)
0f2d19dd 1067{
c014a02e
ML
1068 unsigned long i0 = 0, i1 = 0;
1069 long inc0 = 1, inc1 = 1;
1070 unsigned long n;
0f2d19dd 1071 ra1 = SCM_CAR (ra1);
04b87de5 1072 if (SCM_I_ARRAYP(ra0))
c209c88e 1073 {
04b87de5
MV
1074 n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
1075 i0 = SCM_I_ARRAY_BASE (ra0);
1076 inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
1077 ra0 = SCM_I_ARRAY_V (ra0);
c209c88e 1078 }
e466c6a2 1079 else
399aba0a
MV
1080 n = scm_c_generalized_vector_length (ra0);
1081
04b87de5 1082 if (SCM_I_ARRAYP (ra1))
c209c88e 1083 {
04b87de5
MV
1084 i1 = SCM_I_ARRAY_BASE (ra1);
1085 inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
1086 ra1 = SCM_I_ARRAY_V (ra1);
c209c88e 1087 }
399aba0a
MV
1088
1089 if (scm_is_generalized_vector (ra0))
c209c88e 1090 {
c209c88e
GB
1091 for (; n--; i0 += inc0, i1 += inc1)
1092 {
7888309b 1093 if (scm_is_false (as_equal))
c209c88e 1094 {
85516012 1095 if (scm_is_false (scm_array_equal_p (GVREF (ra0, i0), GVREF (ra1, i1))))
c209c88e
GB
1096 return 0;
1097 }
85516012 1098 else if (scm_is_false (scm_equal_p (GVREF (ra0, i0), GVREF (ra1, i1))))
c209c88e
GB
1099 return 0;
1100 }
1101 return 1;
c209c88e 1102 }
399aba0a
MV
1103 else
1104 return 0;
0f2d19dd
JB
1105}
1106
1107
1cc91f1b 1108
0f2d19dd 1109static int
34d19ef6 1110raeql (SCM ra0, SCM as_equal, SCM ra1)
0f2d19dd
JB
1111{
1112 SCM v0 = ra0, v1 = ra1;
92c2555f
MV
1113 scm_t_array_dim dim0, dim1;
1114 scm_t_array_dim *s0 = &dim0, *s1 = &dim1;
c014a02e 1115 unsigned long bas0 = 0, bas1 = 0;
0f2d19dd 1116 int k, unroll = 1, vlen = 1, ndim = 1;
04b87de5 1117 if (SCM_I_ARRAYP (ra0))
c209c88e 1118 {
04b87de5
MV
1119 ndim = SCM_I_ARRAY_NDIM (ra0);
1120 s0 = SCM_I_ARRAY_DIMS (ra0);
1121 bas0 = SCM_I_ARRAY_BASE (ra0);
1122 v0 = SCM_I_ARRAY_V (ra0);
c209c88e 1123 }
0f2d19dd
JB
1124 else
1125 {
1126 s0->inc = 1;
1127 s0->lbnd = 0;
ee67e2fa 1128 s0->ubnd = scm_c_generalized_vector_length (v0) - 1;
0f2d19dd
JB
1129 unroll = 0;
1130 }
04b87de5 1131 if (SCM_I_ARRAYP (ra1))
c209c88e 1132 {
04b87de5 1133 if (ndim != SCM_I_ARRAY_NDIM (ra1))
c209c88e 1134 return 0;
04b87de5
MV
1135 s1 = SCM_I_ARRAY_DIMS (ra1);
1136 bas1 = SCM_I_ARRAY_BASE (ra1);
1137 v1 = SCM_I_ARRAY_V (ra1);
c209c88e 1138 }
0f2d19dd
JB
1139 else
1140 {
c209c88e
GB
1141 /*
1142 Huh ? Schizophrenic return type. --hwn
1143 */
0f2d19dd 1144 if (1 != ndim)
c209c88e 1145 return 0;
0f2d19dd
JB
1146 s1->inc = 1;
1147 s1->lbnd = 0;
ee67e2fa 1148 s1->ubnd = scm_c_generalized_vector_length (v1) - 1;
0f2d19dd
JB
1149 unroll = 0;
1150 }
1151 if (SCM_TYP7 (v0) != SCM_TYP7 (v1))
1152 return 0;
1153 for (k = ndim; k--;)
1154 {
1155 if (s0[k].lbnd != s1[k].lbnd || s0[k].ubnd != s1[k].ubnd)
1156 return 0;
1157 if (unroll)
1158 {
1159 unroll = (s0[k].inc == s1[k].inc);
1160 vlen *= s0[k].ubnd - s1[k].lbnd + 1;
1161 }
1162 }
bc36d050 1163 if (unroll && bas0 == bas1 && scm_is_eq (v0, v1))
c209c88e 1164 return 1;
0f2d19dd
JB
1165 return scm_ramapc (raeql_1, as_equal, ra0, scm_cons (ra1, SCM_EOL), "");
1166}
1167
1cc91f1b 1168
0f2d19dd 1169SCM
1bbd0b84 1170scm_raequal (SCM ra0, SCM ra1)
0f2d19dd 1171{
7888309b 1172 return scm_from_bool(raeql (ra0, SCM_BOOL_T, ra1));
0f2d19dd
JB
1173}
1174
4079f87e 1175#if 0
c3ee7520
GB
1176/* GJB:FIXME:: Why not use SCM_DEFINE1 for array-equal? */
1177SCM_DEFINE1 (scm_array_equal_p, "array-equal?", scm_tc7_rpsubr,
c209c88e 1178 (SCM ra0, SCM ra1),
1e6808ea
MG
1179 "Return @code{#t} iff all arguments are arrays with the same\n"
1180 "shape, the same type, and have corresponding elements which are\n"
1181 "either @code{equal?} or @code{array-equal?}. This function\n"
1182 "differs from @code{equal?} in that a one dimensional shared\n"
1183 "array may be @var{array-equal?} but not @var{equal?} to a\n"
1184 "vector or uniform vector.")
4079f87e 1185#define FUNC_NAME s_scm_array_equal_p
0f981281
GB
1186{
1187}
4079f87e
GB
1188#undef FUNC_NAME
1189#endif
1190
0f2d19dd
JB
1191static char s_array_equal_p[] = "array-equal?";
1192
1cc91f1b 1193
0f2d19dd 1194SCM
1bbd0b84 1195scm_array_equal_p (SCM ra0, SCM ra1)
0f2d19dd 1196{
04b87de5 1197 if (SCM_I_ARRAYP (ra0) || SCM_I_ARRAYP (ra1))
399aba0a
MV
1198 return scm_from_bool(raeql (ra0, SCM_BOOL_F, ra1));
1199 return scm_equal_p (ra0, ra1);
0f2d19dd
JB
1200}
1201
1202
1cc91f1b 1203static void
1bbd0b84 1204init_raprocs (ra_iproc *subra)
0f2d19dd
JB
1205{
1206 for (; subra->name; subra++)
86d31dfe 1207 {
cc95e00a 1208 SCM sym = scm_from_locale_symbol (subra->name);
86d31dfe
MV
1209 SCM var =
1210 scm_sym2var (sym, scm_current_module_lookup_closure (), SCM_BOOL_F);
1211 if (var != SCM_BOOL_F)
1212 subra->sproc = SCM_VARIABLE_REF (var);
1213 else
1214 subra->sproc = SCM_BOOL_F;
1215 }
0f2d19dd
JB
1216}
1217
1cc91f1b 1218
0f2d19dd 1219void
5d1b3b2d 1220scm_init_array_map (void)
0f2d19dd
JB
1221{
1222 init_raprocs (ra_rpsubrs);
1223 init_raprocs (ra_asubrs);
9a441ddb 1224 scm_c_define_subr (s_array_equal_p, scm_tc7_rpsubr, scm_array_equal_p);
04b87de5 1225 scm_smobs[SCM_TC2SMOBNUM (scm_i_tc16_array)].equalp = scm_raequal;
5d1b3b2d 1226#include "libguile/array-map.x"
1bbd0b84 1227 scm_add_feature (s_scm_array_for_each);
0f2d19dd 1228}
89e00824
ML
1229
1230/*
1231 Local Variables:
1232 c-file-style: "gnu"
1233 End:
1234*/