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