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