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