(scm_make_shared_array): Use it instead of scm_aind; use handle
[bpt/guile.git] / libguile / ramap.c
CommitLineData
ac3c6ad6 1/* Copyright (C) 1996,1998,2000,2001,2004 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
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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
0f2d19dd
JB
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
1cc91f1b 97
c209c88e
GB
98
99/*
100 Yes, this is really ugly, but it prevents multiple code
101 */
102#define BINARY_ELTS_CODE(OPERATOR, type) \
103do { 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];) \
c209c88e
GB
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) \
114do { 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 }) \
c209c88e
GB
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];\
c209c88e
GB
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
c014a02e 142static unsigned long
b4b33636 143cind (SCM ra, long *ve)
0f2d19dd 144{
c014a02e 145 unsigned long i;
0f2d19dd 146 int k;
0f2d19dd
JB
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 */
1cc91f1b 163
0f2d19dd 164int
6e8d25a6 165scm_ra_matchp (SCM ra0, SCM ras)
0f2d19dd
JB
166{
167 SCM ra1;
92c2555f
MV
168 scm_t_array_dim dims;
169 scm_t_array_dim *s0 = &dims;
170 scm_t_array_dim *s1;
c014a02e 171 unsigned long bas0 = 0;
0f2d19dd 172 int i, ndim = 1;
399aba0a
MV
173 int exact = 2 /* 4 */ ; /* Don't care about values >2 (yet?) */
174
175 if (scm_is_generalized_vector (ra0))
c209c88e 176 {
c209c88e
GB
177 s0->lbnd = 0;
178 s0->inc = 1;
399aba0a
MV
179 s0->ubnd = scm_c_generalized_vector_length (ra0) - 1;
180 }
181 else if (SCM_ARRAYP (ra0))
182 {
c209c88e
GB
183 ndim = SCM_ARRAY_NDIM (ra0);
184 s0 = SCM_ARRAY_DIMS (ra0);
185 bas0 = SCM_ARRAY_BASE (ra0);
c209c88e 186 }
399aba0a
MV
187 else
188 return 0;
189
368cf54d 190 while (SCM_NIMP (ras))
c209c88e
GB
191 {
192 ra1 = SCM_CAR (ras);
399aba0a
MV
193
194 if (scm_is_generalized_vector (ra1))
c209c88e 195 {
399aba0a
MV
196 size_t length;
197
198 if (1 != ndim)
c209c88e 199 return 0;
399aba0a
MV
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 {
c209c88e
GB
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 }
c209c88e 240 }
399aba0a
MV
241 else
242 return 0;
243
c209c88e
GB
244 ras = SCM_CDR (ras);
245 }
399aba0a 246
0f2d19dd
JB
247 return exact;
248}
249
1bbd0b84
GB
250/* array mapper: apply cproc to each dimension of the given arrays?.
251 int (*cproc) (); procedure to call on unrolled arrays?
5c11cc9d 252 cproc (dest, source list) or
1bbd0b84
GB
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. */
258int
259scm_ramapc (int (*cproc)(), SCM data, SCM ra0, SCM lra, const char *what)
0f2d19dd 260{
b4b33636 261 SCM z;
0f2d19dd
JB
262 SCM vra0, ra1, vra1;
263 SCM lvra, *plvra;
c014a02e 264 long *vinds;
0f2d19dd
JB
265 int k, kmax;
266 switch (scm_ra_matchp (ra0, lra))
267 {
268 default:
269 case 0:
9cf5d9b7 270 scm_misc_error (what, "array shape mismatch: ~S", scm_list_1 (ra0));
0f2d19dd
JB
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);
ff467021 278 if (SCM_IMP (vra0)) goto gencase;
0f2d19dd
JB
279 if (!SCM_ARRAYP (vra0))
280 {
399aba0a 281 size_t length = scm_c_generalized_vector_length (vra0);
0f2d19dd
JB
282 vra1 = scm_make_ra (1);
283 SCM_ARRAY_BASE (vra1) = 0;
284 SCM_ARRAY_DIMS (vra1)->lbnd = 0;
b226e5f6 285 SCM_ARRAY_DIMS (vra1)->ubnd = length - 1;
0f2d19dd
JB
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);
25d8012c 313 plvra = SCM_CDRLOC (*plvra);
0f2d19dd
JB
314 }
315 return (SCM_UNBNDP (data) ? cproc(vra0, lvra) : cproc(vra0, data, lvra));
316 case 1:
317 gencase: /* Have to loop over all dimensions. */
c209c88e
GB
318 vra0 = scm_make_ra (1);
319 if (SCM_ARRAYP (ra0))
320 {
321 kmax = SCM_ARRAY_NDIM (ra0) - 1;
322 if (kmax < 0)
0f2d19dd 323 {
c209c88e
GB
324 SCM_ARRAY_DIMS (vra0)->lbnd = 0;
325 SCM_ARRAY_DIMS (vra0)->ubnd = 0;
326 SCM_ARRAY_DIMS (vra0)->inc = 1;
0f2d19dd 327 }
c209c88e
GB
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 {
ee67e2fa 339 size_t length = scm_c_generalized_vector_length (ra0);
c209c88e
GB
340 kmax = 0;
341 SCM_ARRAY_DIMS (vra0)->lbnd = 0;
b226e5f6 342 SCM_ARRAY_DIMS (vra0)->ubnd = length - 1;
c209c88e
GB
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 }
b4b33636
MV
370
371 scm_frame_begin (0);
372
373 vinds = scm_malloc (sizeof(long) * SCM_ARRAY_NDIM (ra0));
374 scm_frame_free (vinds);
375
c209c88e
GB
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;
b4b33636 384 SCM_ARRAY_BASE (vra0) = cind (ra0, vinds);
c209c88e 385 for (z = lvra; SCM_NIMP (z); z = SCM_CDR (z), y = SCM_CDR (y))
b4b33636 386 SCM_ARRAY_BASE (SCM_CAR (z)) = cind (SCM_CAR (y), vinds);
c209c88e
GB
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);
b4b33636
MV
402
403 scm_frame_end ();
c209c88e 404 return 1;
0f2d19dd
JB
405 }
406}
407
408
3b3b36dd 409SCM_DEFINE (scm_array_fill_x, "array-fill!", 2, 0, 0,
c209c88e 410 (SCM ra, SCM fill),
8f85c0c6 411 "Store @var{fill} in every element of @var{array}. The value returned\n"
b380b885 412 "is unspecified.")
1bbd0b84 413#define FUNC_NAME s_scm_array_fill_x
ad310508 414{
c209c88e 415 scm_ramapc (scm_array_fill_int, fill, ra, SCM_EOL, FUNC_NAME);
ad310508
MD
416 return SCM_UNSPECIFIED;
417}
1bbd0b84 418#undef FUNC_NAME
ad310508 419
5c11cc9d
GH
420/* to be used as cproc in scm_ramapc to fill an array dimension with
421 "fill". */
0f2d19dd 422int
e81d98ec 423scm_array_fill_int (SCM ra, SCM fill, SCM ignore SCM_UNUSED)
1bbd0b84 424#define FUNC_NAME s_scm_array_fill_x
0f2d19dd 425{
c014a02e
ML
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);
5c11cc9d 430
0f2d19dd 431 ra = SCM_ARRAY_V (ra);
b4bdadde 432
399aba0a 433 if (scm_is_generalized_vector (ra))
b4bdadde
MV
434 {
435 for (i = base; n--; i += inc)
399aba0a 436 scm_c_generalized_vector_set_x (ra, i, fill);
b4bdadde 437 }
399aba0a 438 else
5c11cc9d 439 {
5c11cc9d 440 for (i = base; n--; i += inc)
e11e83f3 441 scm_array_set_x (ra, fill, scm_from_ulong (i));
5c11cc9d 442 }
0f2d19dd
JB
443 return 1;
444}
1bbd0b84 445#undef FUNC_NAME
0f2d19dd 446
0f2d19dd 447
c209c88e 448
0f2d19dd 449static int
1bbd0b84 450racp (SCM src, SCM dst)
0f2d19dd 451{
c014a02e
ML
452 long n = (SCM_ARRAY_DIMS (src)->ubnd - SCM_ARRAY_DIMS (src)->lbnd + 1);
453 long inc_d, inc_s = SCM_ARRAY_DIMS (src)->inc;
454 unsigned long i_d, i_s = SCM_ARRAY_BASE (src);
0f2d19dd
JB
455 dst = SCM_CAR (dst);
456 inc_d = SCM_ARRAY_DIMS (dst)->inc;
457 i_d = SCM_ARRAY_BASE (dst);
458 src = SCM_ARRAY_V (src);
459 dst = SCM_ARRAY_V (dst);
c209c88e 460
399aba0a
MV
461 for (; n-- > 0; i_s += inc_s, i_d += inc_d)
462 scm_array_set_x (dst, scm_cvref (src, i_s, SCM_UNDEFINED),
463 scm_from_ulong (i_d));
0f2d19dd
JB
464 return 1;
465}
466
1bbd0b84 467SCM_REGISTER_PROC(s_array_copy_in_order_x, "array-copy-in-order!", 2, 0, 0, scm_array_copy_x);
1cc91f1b 468
1bbd0b84 469
3b3b36dd 470SCM_DEFINE (scm_array_copy_x, "array-copy!", 2, 0, 0,
c209c88e 471 (SCM src, SCM dst),
8f85c0c6
NJ
472 "@deffnx {Scheme Procedure} array-copy-in-order! src dst\n"
473 "Copy every element from vector or array @var{source} to the\n"
b380b885
MD
474 "corresponding element of @var{destination}. @var{destination} must have\n"
475 "the same rank as @var{source}, and be at least as large in each\n"
476 "dimension. The order is unspecified.")
1bbd0b84 477#define FUNC_NAME s_scm_array_copy_x
0f2d19dd 478{
c209c88e 479 scm_ramapc (racp, SCM_UNDEFINED, src, scm_cons (dst, SCM_EOL), FUNC_NAME);
0f2d19dd
JB
480 return SCM_UNSPECIFIED;
481}
1bbd0b84 482#undef FUNC_NAME
0f2d19dd
JB
483
484/* Functions callable by ARRAY-MAP! */
485
1cc91f1b 486
0f2d19dd 487int
1bbd0b84 488scm_ra_eqp (SCM ra0, SCM ras)
0f2d19dd
JB
489{
490 SCM ra1 = SCM_CAR (ras), ra2 = SCM_CAR (SCM_CDR (ras));
c014a02e
ML
491 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
492 unsigned long i0 = SCM_ARRAY_BASE (ra0), i1 = SCM_ARRAY_BASE (ra1), i2 = SCM_ARRAY_BASE (ra2);
493 long inc0 = SCM_ARRAY_DIMS (ra0)->inc;
494 long inc1 = SCM_ARRAY_DIMS (ra1)->inc;
495 long inc2 = SCM_ARRAY_DIMS (ra1)->inc;
0f2d19dd
JB
496 ra0 = SCM_ARRAY_V (ra0);
497 ra1 = SCM_ARRAY_V (ra1);
498 ra2 = SCM_ARRAY_V (ra2);
399aba0a
MV
499
500 {
501 SCM e1 = SCM_UNDEFINED, e2 = SCM_UNDEFINED;
502 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
503 if (scm_is_true (scm_c_bitvector_ref (ra0, i0)))
504 if (!scm_is_eq (RVREF (ra1, i1, e1), RVREF (ra2, i2, e2)))
505 scm_c_bitvector_set_x (ra0, i0, SCM_BOOL_F);
506 }
507
0f2d19dd
JB
508 return 1;
509}
510
511/* opt 0 means <, nonzero means >= */
1cc91f1b 512
0f2d19dd 513static int
34d19ef6 514ra_compare (SCM ra0, SCM ra1, SCM ra2, int opt)
0f2d19dd 515{
c014a02e
ML
516 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
517 unsigned long i0 = SCM_ARRAY_BASE (ra0), i1 = SCM_ARRAY_BASE (ra1), i2 = SCM_ARRAY_BASE (ra2);
518 long inc0 = SCM_ARRAY_DIMS (ra0)->inc;
519 long inc1 = SCM_ARRAY_DIMS (ra1)->inc;
520 long inc2 = SCM_ARRAY_DIMS (ra1)->inc;
0f2d19dd
JB
521 ra0 = SCM_ARRAY_V (ra0);
522 ra1 = SCM_ARRAY_V (ra1);
523 ra2 = SCM_ARRAY_V (ra2);
399aba0a
MV
524
525 {
526 SCM e1 = SCM_UNDEFINED, e2 = SCM_UNDEFINED;
527 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
528 if (scm_is_true (scm_c_bitvector_ref (ra0, i0)))
529 if (opt ?
530 scm_is_true (scm_less_p (RVREF (ra1, i1, e1), RVREF (ra2, i2, e2))) :
531 scm_is_false (scm_less_p (RVREF (ra1, i1, e1), RVREF (ra2, i2, e2))))
532 scm_c_bitvector_set_x (ra0, i0, SCM_BOOL_F);
533 }
534
0f2d19dd
JB
535 return 1;
536}
537
538
1cc91f1b 539
0f2d19dd 540int
1bbd0b84 541scm_ra_lessp (SCM ra0, SCM ras)
0f2d19dd
JB
542{
543 return ra_compare (ra0, SCM_CAR (ras), SCM_CAR (SCM_CDR (ras)), 0);
544}
545
1cc91f1b 546
0f2d19dd 547int
1bbd0b84 548scm_ra_leqp (SCM ra0, SCM ras)
0f2d19dd
JB
549{
550 return ra_compare (ra0, SCM_CAR (SCM_CDR (ras)), SCM_CAR (ras), 1);
551}
552
1cc91f1b 553
0f2d19dd 554int
1bbd0b84 555scm_ra_grp (SCM ra0, SCM ras)
0f2d19dd
JB
556{
557 return ra_compare (ra0, SCM_CAR (SCM_CDR (ras)), SCM_CAR (ras), 0);
558}
559
1cc91f1b 560
0f2d19dd 561int
1bbd0b84 562scm_ra_greqp (SCM ra0, SCM ras)
0f2d19dd
JB
563{
564 return ra_compare (ra0, SCM_CAR (ras), SCM_CAR (SCM_CDR (ras)), 1);
565}
566
567
0f2d19dd 568int
1bbd0b84 569scm_ra_sum (SCM ra0, SCM ras)
0f2d19dd 570{
c014a02e
ML
571 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
572 unsigned long i0 = SCM_ARRAY_BASE (ra0);
573 long inc0 = SCM_ARRAY_DIMS (ra0)->inc;
0f2d19dd 574 ra0 = SCM_ARRAY_V (ra0);
d2e53ed6 575 if (!scm_is_null(ras))
c209c88e
GB
576 {
577 SCM ra1 = SCM_CAR (ras);
c014a02e
ML
578 unsigned long i1 = SCM_ARRAY_BASE (ra1);
579 long inc1 = SCM_ARRAY_DIMS (ra1)->inc;
c209c88e
GB
580 ra1 = SCM_ARRAY_V (ra1);
581 switch (SCM_TYP7 (ra0) == SCM_TYP7 (ra1) ? SCM_TYP7 (ra0) : 0)
582 {
583 default:
0f2d19dd 584 {
c209c88e
GB
585 SCM e0 = SCM_UNDEFINED, e1 = SCM_UNDEFINED;
586 for (; n-- > 0; i0 += inc0, i1 += inc1)
587 scm_array_set_x (ra0, scm_sum (RVREF (ra0, i0, e0), RVREF (ra1, i1, e1)),
e11e83f3 588 scm_from_ulong (i0));
c209c88e
GB
589 break;
590 }
c209c88e
GB
591 }
592 }
0f2d19dd
JB
593 return 1;
594}
595
596
1cc91f1b 597
0f2d19dd 598int
1bbd0b84 599scm_ra_difference (SCM ra0, SCM ras)
0f2d19dd 600{
c014a02e
ML
601 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
602 unsigned long i0 = SCM_ARRAY_BASE (ra0);
603 long inc0 = SCM_ARRAY_DIMS (ra0)->inc;
0f2d19dd 604 ra0 = SCM_ARRAY_V (ra0);
d2e53ed6 605 if (scm_is_null (ras))
c209c88e
GB
606 {
607 switch (SCM_TYP7 (ra0))
608 {
609 default:
610 {
611 SCM e0 = SCM_UNDEFINED;
612 for (; n-- > 0; i0 += inc0)
613 scm_array_set_x (ra0,
614 scm_difference (RVREF (ra0, i0, e0), SCM_UNDEFINED),
e11e83f3 615 scm_from_ulong (i0));
c209c88e
GB
616 break;
617 }
c209c88e
GB
618 }
619 }
0f2d19dd
JB
620 else
621 {
622 SCM ra1 = SCM_CAR (ras);
c014a02e
ML
623 unsigned long i1 = SCM_ARRAY_BASE (ra1);
624 long inc1 = SCM_ARRAY_DIMS (ra1)->inc;
0f2d19dd
JB
625 ra1 = SCM_ARRAY_V (ra1);
626 switch (SCM_TYP7 (ra0) == SCM_TYP7 (ra1) ? SCM_TYP7 (ra0) : 0)
627 {
628 default:
629 {
630 SCM e0 = SCM_UNDEFINED, e1 = SCM_UNDEFINED;
631 for (; n-- > 0; i0 += inc0, i1 += inc1)
e11e83f3 632 scm_array_set_x (ra0, scm_difference (RVREF (ra0, i0, e0), RVREF (ra1, i1, e1)), scm_from_ulong (i0));
0f2d19dd
JB
633 break;
634 }
0f2d19dd
JB
635 }
636 }
637 return 1;
638}
639
640
1cc91f1b 641
0f2d19dd 642int
1bbd0b84 643scm_ra_product (SCM ra0, SCM ras)
0f2d19dd 644{
c014a02e
ML
645 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
646 unsigned long i0 = SCM_ARRAY_BASE (ra0);
647 long inc0 = SCM_ARRAY_DIMS (ra0)->inc;
0f2d19dd 648 ra0 = SCM_ARRAY_V (ra0);
d2e53ed6 649 if (!scm_is_null (ras))
c209c88e
GB
650 {
651 SCM ra1 = SCM_CAR (ras);
c014a02e
ML
652 unsigned long i1 = SCM_ARRAY_BASE (ra1);
653 long inc1 = SCM_ARRAY_DIMS (ra1)->inc;
c209c88e
GB
654 ra1 = SCM_ARRAY_V (ra1);
655 switch (SCM_TYP7 (ra0) == SCM_TYP7 (ra1) ? SCM_TYP7 (ra0) : 0)
656 {
657 default:
0f2d19dd 658 {
c209c88e
GB
659 SCM e0 = SCM_UNDEFINED, e1 = SCM_UNDEFINED;
660 for (; n-- > 0; i0 += inc0, i1 += inc1)
661 scm_array_set_x (ra0, scm_product (RVREF (ra0, i0, e0), RVREF (ra1, i1, e1)),
e11e83f3 662 scm_from_ulong (i0));
c209c88e
GB
663 break;
664 }
c209c88e
GB
665 }
666 }
0f2d19dd
JB
667 return 1;
668}
669
1cc91f1b 670
0f2d19dd 671int
1bbd0b84 672scm_ra_divide (SCM ra0, SCM ras)
0f2d19dd 673{
c014a02e
ML
674 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
675 unsigned long i0 = SCM_ARRAY_BASE (ra0);
676 long inc0 = SCM_ARRAY_DIMS (ra0)->inc;
0f2d19dd 677 ra0 = SCM_ARRAY_V (ra0);
d2e53ed6 678 if (scm_is_null (ras))
c209c88e
GB
679 {
680 switch (SCM_TYP7 (ra0))
681 {
682 default:
683 {
684 SCM e0 = SCM_UNDEFINED;
685 for (; n-- > 0; i0 += inc0)
e11e83f3 686 scm_array_set_x (ra0, scm_divide (RVREF (ra0, i0, e0), SCM_UNDEFINED), scm_from_ulong (i0));
c209c88e
GB
687 break;
688 }
c209c88e
GB
689 }
690 }
0f2d19dd
JB
691 else
692 {
693 SCM ra1 = SCM_CAR (ras);
c014a02e
ML
694 unsigned long i1 = SCM_ARRAY_BASE (ra1);
695 long inc1 = SCM_ARRAY_DIMS (ra1)->inc;
0f2d19dd
JB
696 ra1 = SCM_ARRAY_V (ra1);
697 switch (SCM_TYP7 (ra0) == SCM_TYP7 (ra1) ? SCM_TYP7 (ra0) : 0)
698 {
699 default:
700 {
701 SCM e0 = SCM_UNDEFINED, e1 = SCM_UNDEFINED;
702 for (; n-- > 0; i0 += inc0, i1 += inc1)
e11e83f3 703 scm_array_set_x (ra0, scm_divide (RVREF (ra0, i0, e0), RVREF (ra1, i1, e1)), scm_from_ulong (i0));
0f2d19dd
JB
704 break;
705 }
0f2d19dd
JB
706 }
707 }
708 return 1;
709}
710
1cc91f1b 711
0f2d19dd 712int
1bbd0b84 713scm_array_identity (SCM dst, SCM src)
0f2d19dd
JB
714{
715 return racp (SCM_CAR (src), scm_cons (dst, SCM_EOL));
716}
717
718
1cc91f1b 719
0f2d19dd 720static int
34d19ef6 721ramap (SCM ra0, SCM proc, SCM ras)
0f2d19dd 722{
c014a02e
ML
723 long i = SCM_ARRAY_DIMS (ra0)->lbnd;
724 long inc = SCM_ARRAY_DIMS (ra0)->inc;
725 long n = SCM_ARRAY_DIMS (ra0)->ubnd;
726 long base = SCM_ARRAY_BASE (ra0) - i * inc;
0f2d19dd 727 ra0 = SCM_ARRAY_V (ra0);
d2e53ed6 728 if (scm_is_null (ras))
c209c88e 729 for (; i <= n; i++)
e11e83f3 730 scm_array_set_x (ra0, scm_call_0 (proc), scm_from_long (i * inc + base));
0f2d19dd
JB
731 else
732 {
733 SCM ra1 = SCM_CAR (ras);
34d19ef6 734 SCM args;
c014a02e
ML
735 unsigned long k, i1 = SCM_ARRAY_BASE (ra1);
736 long inc1 = SCM_ARRAY_DIMS (ra1)->inc;
0f2d19dd
JB
737 ra1 = SCM_ARRAY_V (ra1);
738 ras = SCM_CDR (ras);
d2e53ed6 739 if (scm_is_null(ras))
c209c88e 740 ras = scm_nullvect;
0f2d19dd 741 else
ee67e2fa 742 ras = scm_vector (ras);
34d19ef6 743
0f2d19dd
JB
744 for (; i <= n; i++, i1 += inc1)
745 {
746 args = SCM_EOL;
ee67e2fa
MV
747 for (k = scm_c_vector_length (ras); k--;)
748 args = scm_cons (scm_c_generalized_vector_ref (scm_c_vector_ref (ras, k), i), args);
0f2d19dd 749 args = scm_cons (scm_cvref (ra1, i1, SCM_UNDEFINED), args);
e11e83f3 750 scm_array_set_x (ra0, scm_apply_0 (proc, args), scm_from_long (i * inc + base));
0f2d19dd
JB
751 }
752 }
753 return 1;
754}
755
1cc91f1b 756
0f2d19dd 757static int
14b18ed6 758ramap_dsubr (SCM ra0, SCM proc, SCM ras)
0f2d19dd
JB
759{
760 SCM ra1 = SCM_CAR (ras);
761 SCM e1 = SCM_UNDEFINED;
c014a02e
ML
762 unsigned long i0 = SCM_ARRAY_BASE (ra0), i1 = SCM_ARRAY_BASE (ra1);
763 long inc0 = SCM_ARRAY_DIMS (ra0)->inc, inc1 = SCM_ARRAY_DIMS (ra1)->inc;
764 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra1)->lbnd + 1;
0f2d19dd
JB
765 ra0 = SCM_ARRAY_V (ra0);
766 ra1 = SCM_ARRAY_V (ra1);
ff467021 767 switch (SCM_TYP7 (ra0))
c209c88e
GB
768 {
769 default:
c209c88e 770 for (; n-- > 0; i0 += inc0, i1 += inc1)
e11e83f3 771 scm_array_set_x (ra0, scm_call_1 (proc, RVREF (ra1, i1, e1)), scm_from_ulong (i0));
c209c88e 772 break;
c209c88e 773 }
0f2d19dd
JB
774 return 1;
775}
776
777
1cc91f1b 778
0f2d19dd 779static int
34d19ef6 780ramap_rp (SCM ra0, SCM proc, SCM ras)
0f2d19dd
JB
781{
782 SCM ra1 = SCM_CAR (ras), ra2 = SCM_CAR (SCM_CDR (ras));
783 SCM e1 = SCM_UNDEFINED, e2 = SCM_UNDEFINED;
c014a02e
ML
784 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
785 unsigned long i0 = SCM_ARRAY_BASE (ra0), i1 = SCM_ARRAY_BASE (ra1), i2 = SCM_ARRAY_BASE (ra2);
786 long inc0 = SCM_ARRAY_DIMS (ra0)->inc;
787 long inc1 = SCM_ARRAY_DIMS (ra1)->inc;
788 long inc2 = SCM_ARRAY_DIMS (ra1)->inc;
0f2d19dd
JB
789 ra0 = SCM_ARRAY_V (ra0);
790 ra1 = SCM_ARRAY_V (ra1);
791 ra2 = SCM_ARRAY_V (ra2);
399aba0a
MV
792
793 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
794 if (scm_is_true (scm_c_bitvector_ref (ra0, i0)))
795 if (scm_is_false (SCM_SUBRF (proc) (RVREF (ra1, i1, e1), RVREF (ra2, i2, e2))))
796 scm_c_bitvector_set_x (ra0, i0, SCM_BOOL_F);
797
0f2d19dd
JB
798 return 1;
799}
800
801
1cc91f1b 802
0f2d19dd 803static int
34d19ef6 804ramap_1 (SCM ra0, SCM proc, SCM ras)
0f2d19dd
JB
805{
806 SCM ra1 = SCM_CAR (ras);
807 SCM e1 = SCM_UNDEFINED;
c014a02e
ML
808 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
809 unsigned long i0 = SCM_ARRAY_BASE (ra0), i1 = SCM_ARRAY_BASE (ra1);
810 long inc0 = SCM_ARRAY_DIMS (ra0)->inc, inc1 = SCM_ARRAY_DIMS (ra1)->inc;
0f2d19dd
JB
811 ra0 = SCM_ARRAY_V (ra0);
812 ra1 = SCM_ARRAY_V (ra1);
95f5b0f5 813 if (scm_tc7_vector == SCM_TYP7 (ra0) || scm_tc7_wvect == SCM_TYP7 (ra0))
0f2d19dd 814 for (; n-- > 0; i0 += inc0, i1 += inc1)
e11e83f3 815 scm_array_set_x (ra0, SCM_SUBRF (proc) (scm_cvref (ra1, i1, SCM_UNDEFINED)), scm_from_ulong (i0));
0f2d19dd
JB
816 else
817 for (; n-- > 0; i0 += inc0, i1 += inc1)
e11e83f3 818 scm_array_set_x (ra0, SCM_SUBRF (proc) (RVREF (ra1, i1, e1)), scm_from_ulong (i0));
0f2d19dd
JB
819 return 1;
820}
821
822
1cc91f1b 823
0f2d19dd 824static int
34d19ef6 825ramap_2o (SCM ra0, SCM proc, SCM ras)
0f2d19dd
JB
826{
827 SCM ra1 = SCM_CAR (ras);
828 SCM e1 = SCM_UNDEFINED;
c014a02e
ML
829 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
830 unsigned long i0 = SCM_ARRAY_BASE (ra0), i1 = SCM_ARRAY_BASE (ra1);
831 long inc0 = SCM_ARRAY_DIMS (ra0)->inc, inc1 = SCM_ARRAY_DIMS (ra1)->inc;
0f2d19dd
JB
832 ra0 = SCM_ARRAY_V (ra0);
833 ra1 = SCM_ARRAY_V (ra1);
834 ras = SCM_CDR (ras);
d2e53ed6 835 if (scm_is_null (ras))
c209c88e
GB
836 {
837 if (scm_tc7_vector == SCM_TYP7 (ra0)
838 || scm_tc7_wvect == SCM_TYP7 (ra0))
95f5b0f5 839
c209c88e
GB
840 for (; n-- > 0; i0 += inc0, i1 += inc1)
841 scm_array_set_x (ra0, SCM_SUBRF (proc) (scm_cvref (ra1, i1, SCM_UNDEFINED), SCM_UNDEFINED),
e11e83f3 842 scm_from_ulong (i0));
c209c88e
GB
843 else
844 for (; n-- > 0; i0 += inc0, i1 += inc1)
845 scm_array_set_x (ra0, SCM_SUBRF (proc) (RVREF (ra1, i1, e1), SCM_UNDEFINED),
e11e83f3 846 scm_from_ulong (i0));
c209c88e 847 }
0f2d19dd
JB
848 else
849 {
850 SCM ra2 = SCM_CAR (ras);
851 SCM e2 = SCM_UNDEFINED;
c014a02e
ML
852 unsigned long i2 = SCM_ARRAY_BASE (ra2);
853 long inc2 = SCM_ARRAY_DIMS (ra2)->inc;
0f2d19dd 854 ra2 = SCM_ARRAY_V (ra2);
95f5b0f5 855 if (scm_tc7_vector == SCM_TYP7 (ra0) || scm_tc7_wvect == SCM_TYP7 (ra0))
0f2d19dd
JB
856 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
857 scm_array_set_x (ra0,
c209c88e 858 SCM_SUBRF (proc) (scm_cvref (ra1, i1, SCM_UNDEFINED), scm_cvref (ra2, i2, SCM_UNDEFINED)),
e11e83f3 859 scm_from_ulong (i0));
0f2d19dd
JB
860 else
861 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
862 scm_array_set_x (ra0,
c209c88e 863 SCM_SUBRF (proc) (RVREF (ra1, i1, e1), RVREF (ra2, i2, e2)),
e11e83f3 864 scm_from_ulong (i0));
0f2d19dd
JB
865 }
866 return 1;
867}
868
869
1cc91f1b 870
0f2d19dd 871static int
34d19ef6 872ramap_a (SCM ra0, SCM proc, SCM ras)
0f2d19dd
JB
873{
874 SCM e0 = SCM_UNDEFINED, e1 = SCM_UNDEFINED;
c014a02e
ML
875 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
876 unsigned long i0 = SCM_ARRAY_BASE (ra0);
877 long inc0 = SCM_ARRAY_DIMS (ra0)->inc;
0f2d19dd 878 ra0 = SCM_ARRAY_V (ra0);
d2e53ed6 879 if (scm_is_null (ras))
c209c88e 880 for (; n-- > 0; i0 += inc0)
e11e83f3 881 scm_array_set_x (ra0, SCM_SUBRF (proc) (RVREF (ra0, i0, e0), SCM_UNDEFINED), scm_from_ulong (i0));
0f2d19dd
JB
882 else
883 {
884 SCM ra1 = SCM_CAR (ras);
c014a02e
ML
885 unsigned long i1 = SCM_ARRAY_BASE (ra1);
886 long inc1 = SCM_ARRAY_DIMS (ra1)->inc;
0f2d19dd
JB
887 ra1 = SCM_ARRAY_V (ra1);
888 for (; n-- > 0; i0 += inc0, i1 += inc1)
889 scm_array_set_x (ra0, SCM_SUBRF (proc) (RVREF (ra0, i0, e0), RVREF (ra1, i1, e1)),
e11e83f3 890 scm_from_ulong (i0));
0f2d19dd
JB
891 }
892 return 1;
893}
894
f5f2dcff 895
1bbd0b84 896SCM_REGISTER_PROC(s_array_map_in_order_x, "array-map-in-order!", 2, 0, 1, scm_array_map_x);
1cc91f1b 897
1bbd0b84 898
3b3b36dd 899SCM_DEFINE (scm_array_map_x, "array-map!", 2, 0, 1,
c209c88e 900 (SCM ra0, SCM proc, SCM lra),
8f85c0c6 901 "@deffnx {Scheme Procedure} array-map-in-order! ra0 proc . lra\n"
b380b885
MD
902 "@var{array1}, @dots{} must have the same number of dimensions as\n"
903 "@var{array0} and have a range for each index which includes the range\n"
904 "for the corresponding index in @var{array0}. @var{proc} is applied to\n"
905 "each tuple of elements of @var{array1} @dots{} and the result is stored\n"
906 "as the corresponding element in @var{array0}. The value returned is\n"
907 "unspecified. The order of application is unspecified.")
1bbd0b84 908#define FUNC_NAME s_scm_array_map_x
0f2d19dd 909{
34d19ef6 910 SCM_VALIDATE_PROC (2, proc);
af45e3b0 911 SCM_VALIDATE_REST_ARGUMENT (lra);
e96a9fad
KR
912 /* This is done as a test on lra, rather than an extra mandatory parameter
913 eval could check, so that the prototype for scm_array_map_x stays as it
914 was in the past. scm_array_map_x isn't actually documented, but did
915 get a mention in the NEWS file, so is best left alone. */
916 if (scm_is_null (lra))
917 SCM_WRONG_NUM_ARGS ();
0f2d19dd 918 switch (SCM_TYP7 (proc))
c209c88e
GB
919 {
920 default:
921 gencase:
922 scm_ramapc (ramap, proc, ra0, lra, FUNC_NAME);
923 return SCM_UNSPECIFIED;
924 case scm_tc7_subr_1:
925 scm_ramapc (ramap_1, proc, ra0, lra, FUNC_NAME);
926 return SCM_UNSPECIFIED;
927 case scm_tc7_subr_2:
928 case scm_tc7_subr_2o:
929 scm_ramapc (ramap_2o, proc, ra0, lra, FUNC_NAME);
930 return SCM_UNSPECIFIED;
14b18ed6
DH
931 case scm_tc7_dsubr:
932 scm_ramapc (ramap_dsubr, proc, ra0, lra, FUNC_NAME);
c209c88e
GB
933 return SCM_UNSPECIFIED;
934 case scm_tc7_rpsubr:
0f2d19dd 935 {
c209c88e 936 ra_iproc *p;
7888309b 937 if (scm_is_false (scm_array_p (ra0, SCM_BOOL_T)))
0f2d19dd 938 goto gencase;
c209c88e
GB
939 scm_array_fill_x (ra0, SCM_BOOL_T);
940 for (p = ra_rpsubrs; p->name; p++)
bc36d050 941 if (scm_is_eq (proc, p->sproc))
c209c88e 942 {
d2e53ed6 943 while (!scm_is_null (lra) && !scm_is_null (SCM_CDR (lra)))
c209c88e
GB
944 {
945 scm_ramapc (p->vproc, SCM_UNDEFINED, ra0, lra, FUNC_NAME);
946 lra = SCM_CDR (lra);
947 }
948 return SCM_UNSPECIFIED;
949 }
d2e53ed6 950 while (!scm_is_null (lra) && !scm_is_null (SCM_CDR (lra)))
c209c88e
GB
951 {
952 scm_ramapc (ramap_rp, proc, ra0, lra, FUNC_NAME);
953 lra = SCM_CDR (lra);
954 }
0f2d19dd 955 return SCM_UNSPECIFIED;
c209c88e
GB
956 }
957 case scm_tc7_asubr:
d2e53ed6 958 if (scm_is_null (lra))
c209c88e 959 {
5d916ba3 960 SCM fill = SCM_SUBRF (proc) (SCM_UNDEFINED, SCM_UNDEFINED);
c209c88e
GB
961 scm_array_fill_x (ra0, fill);
962 }
963 else
0f2d19dd 964 {
c209c88e
GB
965 SCM tail, ra1 = SCM_CAR (lra);
966 SCM v0 = (SCM_ARRAYP (ra0) ? SCM_ARRAY_V (ra0) : ra0);
0f2d19dd 967 ra_iproc *p;
c209c88e
GB
968 /* Check to see if order might matter.
969 This might be an argument for a separate
970 SERIAL-ARRAY-MAP! */
bc36d050
MV
971 if (scm_is_eq (v0, ra1)
972 || (SCM_ARRAYP (ra1) && scm_is_eq (v0, SCM_ARRAY_V (ra1))))
973 if (!scm_is_eq (ra0, ra1)
fee7ef83 974 || (SCM_ARRAYP(ra0) && !SCM_ARRAY_CONTP(ra0)))
c209c88e 975 goto gencase;
d2e53ed6 976 for (tail = SCM_CDR (lra); !scm_is_null (tail); tail = SCM_CDR (tail))
c209c88e
GB
977 {
978 ra1 = SCM_CAR (tail);
bc36d050
MV
979 if (scm_is_eq (v0, ra1)
980 || (SCM_ARRAYP (ra1) && scm_is_eq (v0, SCM_ARRAY_V (ra1))))
c209c88e
GB
981 goto gencase;
982 }
983 for (p = ra_asubrs; p->name; p++)
bc36d050 984 if (scm_is_eq (proc, p->sproc))
0f2d19dd 985 {
bc36d050 986 if (!scm_is_eq (ra0, SCM_CAR (lra)))
c209c88e
GB
987 scm_ramapc (scm_array_identity, SCM_UNDEFINED, ra0, scm_cons (SCM_CAR (lra), SCM_EOL), FUNC_NAME);
988 lra = SCM_CDR (lra);
989 while (1)
0f2d19dd 990 {
c209c88e
GB
991 scm_ramapc (p->vproc, SCM_UNDEFINED, ra0, lra, FUNC_NAME);
992 if (SCM_IMP (lra) || SCM_IMP (SCM_CDR (lra)))
993 return SCM_UNSPECIFIED;
0f2d19dd
JB
994 lra = SCM_CDR (lra);
995 }
0f2d19dd 996 }
c209c88e
GB
997 scm_ramapc (ramap_2o, proc, ra0, lra, FUNC_NAME);
998 lra = SCM_CDR (lra);
999 if (SCM_NIMP (lra))
1000 for (lra = SCM_CDR (lra); SCM_NIMP (lra); lra = SCM_CDR (lra))
1001 scm_ramapc (ramap_a, proc, ra0, lra, FUNC_NAME);
0f2d19dd 1002 }
c209c88e
GB
1003 return SCM_UNSPECIFIED;
1004 }
0f2d19dd 1005}
1bbd0b84 1006#undef FUNC_NAME
0f2d19dd 1007
1cc91f1b 1008
0f2d19dd 1009static int
34d19ef6 1010rafe (SCM ra0, SCM proc, SCM ras)
0f2d19dd 1011{
c014a02e
ML
1012 long i = SCM_ARRAY_DIMS (ra0)->lbnd;
1013 unsigned long i0 = SCM_ARRAY_BASE (ra0);
1014 long inc0 = SCM_ARRAY_DIMS (ra0)->inc;
1015 long n = SCM_ARRAY_DIMS (ra0)->ubnd;
0f2d19dd 1016 ra0 = SCM_ARRAY_V (ra0);
d2e53ed6 1017 if (scm_is_null (ras))
c209c88e 1018 for (; i <= n; i++, i0 += inc0)
fdc28395 1019 scm_call_1 (proc, scm_cvref (ra0, i0, SCM_UNDEFINED));
0f2d19dd
JB
1020 else
1021 {
1022 SCM ra1 = SCM_CAR (ras);
34d19ef6 1023 SCM args;
c014a02e
ML
1024 unsigned long k, i1 = SCM_ARRAY_BASE (ra1);
1025 long inc1 = SCM_ARRAY_DIMS (ra1)->inc;
0f2d19dd
JB
1026 ra1 = SCM_ARRAY_V (ra1);
1027 ras = SCM_CDR (ras);
d2e53ed6 1028 if (scm_is_null(ras))
c209c88e 1029 ras = scm_nullvect;
0f2d19dd 1030 else
ee67e2fa 1031 ras = scm_vector (ras);
0f2d19dd
JB
1032 for (; i <= n; i++, i0 += inc0, i1 += inc1)
1033 {
1034 args = SCM_EOL;
ee67e2fa
MV
1035 for (k = scm_c_vector_length (ras); k--;)
1036 args = scm_cons (scm_c_generalized_vector_ref (scm_c_vector_ref (ras, k), i), args);
0f2d19dd 1037 args = scm_cons2 (scm_cvref (ra0, i0, SCM_UNDEFINED), scm_cvref (ra1, i1, SCM_UNDEFINED), args);
fdc28395 1038 scm_apply_0 (proc, args);
0f2d19dd
JB
1039 }
1040 }
1041 return 1;
1042}
1043
1044
3b3b36dd 1045SCM_DEFINE (scm_array_for_each, "array-for-each", 2, 0, 1,
c209c88e 1046 (SCM proc, SCM ra0, SCM lra),
8f85c0c6 1047 "Apply @var{proc} to each tuple of elements of @var{array0} @dots{}\n"
b380b885 1048 "in row-major order. The value returned is unspecified.")
1bbd0b84 1049#define FUNC_NAME s_scm_array_for_each
0f2d19dd 1050{
34d19ef6 1051 SCM_VALIDATE_PROC (1, proc);
af45e3b0 1052 SCM_VALIDATE_REST_ARGUMENT (lra);
c209c88e 1053 scm_ramapc (rafe, proc, ra0, lra, FUNC_NAME);
0f2d19dd
JB
1054 return SCM_UNSPECIFIED;
1055}
1bbd0b84 1056#undef FUNC_NAME
0f2d19dd 1057
3b3b36dd 1058SCM_DEFINE (scm_array_index_map_x, "array-index-map!", 2, 0, 0,
c209c88e 1059 (SCM ra, SCM proc),
8f85c0c6 1060 "Apply @var{proc} to the indices of each element of @var{array} in\n"
b380b885
MD
1061 "turn, storing the result in the corresponding element. The value\n"
1062 "returned and the order of application are unspecified.\n\n"
1063 "One can implement @var{array-indexes} as\n"
1e6808ea 1064 "@lisp\n"
b380b885
MD
1065 "(define (array-indexes array)\n"
1066 " (let ((ra (apply make-array #f (array-shape array))))\n"
1067 " (array-index-map! ra (lambda x x))\n"
1068 " ra))\n"
1e6808ea 1069 "@end lisp\n"
b380b885 1070 "Another example:\n"
1e6808ea 1071 "@lisp\n"
b380b885
MD
1072 "(define (apl:index-generator n)\n"
1073 " (let ((v (make-uniform-vector n 1)))\n"
1074 " (array-index-map! v (lambda (i) i))\n"
1075 " v))\n"
1e6808ea 1076 "@end lisp")
1bbd0b84 1077#define FUNC_NAME s_scm_array_index_map_x
0f2d19dd 1078{
c014a02e 1079 unsigned long i;
34d19ef6 1080 SCM_VALIDATE_PROC (2, proc);
399aba0a
MV
1081
1082 if (scm_is_generalized_vector (ra))
e42c09cc 1083 {
399aba0a
MV
1084 size_t length = scm_c_generalized_vector_length (ra);
1085 for (i = 0; i < length; i++)
1086 scm_c_generalized_vector_set_x (ra, i,
1087 scm_call_1 (proc, scm_from_ulong (i)));
1088 return SCM_UNSPECIFIED;
1089 }
1090 else if (SCM_ARRAYP (ra))
1091 {
1092 SCM args = SCM_EOL;
399aba0a 1093 int j, k, kmax = SCM_ARRAY_NDIM (ra) - 1;
b4b33636
MV
1094 long *vinds;
1095
399aba0a
MV
1096 if (kmax < 0)
1097 return scm_array_set_x (ra, scm_call_0 (proc), SCM_EOL);
b4b33636
MV
1098
1099 scm_frame_begin (0);
1100
1101 vinds = scm_malloc (sizeof(long) * SCM_ARRAY_NDIM (ra));
1102 scm_frame_free (vinds);
1103
399aba0a
MV
1104 for (k = 0; k <= kmax; k++)
1105 vinds[k] = SCM_ARRAY_DIMS (ra)[k].lbnd;
1106 k = kmax;
1107 do
1108 {
1109 if (k == kmax)
1110 {
1111 vinds[k] = SCM_ARRAY_DIMS (ra)[k].lbnd;
b4b33636 1112 i = cind (ra, vinds);
399aba0a
MV
1113 for (; vinds[k] <= SCM_ARRAY_DIMS (ra)[k].ubnd; vinds[k]++)
1114 {
1115 for (j = kmax + 1, args = SCM_EOL; j--;)
1116 args = scm_cons (scm_from_long (vinds[j]), args);
1117 scm_array_set_x (SCM_ARRAY_V (ra),
1118 scm_apply_0 (proc, args),
1119 scm_from_ulong (i));
1120 i += SCM_ARRAY_DIMS (ra)[k].inc;
1121 }
1122 k--;
1123 continue;
1124 }
1125 if (vinds[k] < SCM_ARRAY_DIMS (ra)[k].ubnd)
1126 {
1127 vinds[k]++;
1128 k++;
1129 continue;
1130 }
1131 vinds[k] = SCM_ARRAY_DIMS (ra)[k].lbnd - 1;
1132 k--;
1133 }
1134 while (k >= 0);
b4b33636
MV
1135
1136 scm_frame_end ();
399aba0a 1137 return SCM_UNSPECIFIED;
e42c09cc 1138 }
399aba0a
MV
1139 else
1140 scm_wrong_type_arg_msg (NULL, 0, ra, "array");
0f2d19dd 1141}
1bbd0b84 1142#undef FUNC_NAME
0f2d19dd 1143
1cc91f1b 1144
0f2d19dd 1145static int
34d19ef6 1146raeql_1 (SCM ra0, SCM as_equal, SCM ra1)
0f2d19dd
JB
1147{
1148 SCM e0 = SCM_UNDEFINED, e1 = SCM_UNDEFINED;
c014a02e
ML
1149 unsigned long i0 = 0, i1 = 0;
1150 long inc0 = 1, inc1 = 1;
1151 unsigned long n;
0f2d19dd 1152 ra1 = SCM_CAR (ra1);
ff467021 1153 if (SCM_ARRAYP(ra0))
c209c88e
GB
1154 {
1155 n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
1156 i0 = SCM_ARRAY_BASE (ra0);
1157 inc0 = SCM_ARRAY_DIMS (ra0)->inc;
1158 ra0 = SCM_ARRAY_V (ra0);
1159 }
e466c6a2 1160 else
399aba0a
MV
1161 n = scm_c_generalized_vector_length (ra0);
1162
ff467021 1163 if (SCM_ARRAYP (ra1))
c209c88e
GB
1164 {
1165 i1 = SCM_ARRAY_BASE (ra1);
1166 inc1 = SCM_ARRAY_DIMS (ra1)->inc;
1167 ra1 = SCM_ARRAY_V (ra1);
1168 }
399aba0a
MV
1169
1170 if (scm_is_generalized_vector (ra0))
c209c88e 1171 {
c209c88e
GB
1172 for (; n--; i0 += inc0, i1 += inc1)
1173 {
7888309b 1174 if (scm_is_false (as_equal))
c209c88e 1175 {
7888309b 1176 if (scm_is_false (scm_array_equal_p (RVREF (ra0, i0, e0), RVREF (ra1, i1, e1))))
c209c88e
GB
1177 return 0;
1178 }
7888309b 1179 else if (scm_is_false (scm_equal_p (RVREF (ra0, i0, e0), RVREF (ra1, i1, e1))))
c209c88e
GB
1180 return 0;
1181 }
1182 return 1;
c209c88e 1183 }
399aba0a
MV
1184 else
1185 return 0;
0f2d19dd
JB
1186}
1187
1188
1cc91f1b 1189
0f2d19dd 1190static int
34d19ef6 1191raeql (SCM ra0, SCM as_equal, SCM ra1)
0f2d19dd
JB
1192{
1193 SCM v0 = ra0, v1 = ra1;
92c2555f
MV
1194 scm_t_array_dim dim0, dim1;
1195 scm_t_array_dim *s0 = &dim0, *s1 = &dim1;
c014a02e 1196 unsigned long bas0 = 0, bas1 = 0;
0f2d19dd 1197 int k, unroll = 1, vlen = 1, ndim = 1;
ff467021 1198 if (SCM_ARRAYP (ra0))
c209c88e
GB
1199 {
1200 ndim = SCM_ARRAY_NDIM (ra0);
1201 s0 = SCM_ARRAY_DIMS (ra0);
1202 bas0 = SCM_ARRAY_BASE (ra0);
1203 v0 = SCM_ARRAY_V (ra0);
1204 }
0f2d19dd
JB
1205 else
1206 {
1207 s0->inc = 1;
1208 s0->lbnd = 0;
ee67e2fa 1209 s0->ubnd = scm_c_generalized_vector_length (v0) - 1;
0f2d19dd
JB
1210 unroll = 0;
1211 }
ff467021 1212 if (SCM_ARRAYP (ra1))
c209c88e
GB
1213 {
1214 if (ndim != SCM_ARRAY_NDIM (ra1))
1215 return 0;
1216 s1 = SCM_ARRAY_DIMS (ra1);
1217 bas1 = SCM_ARRAY_BASE (ra1);
1218 v1 = SCM_ARRAY_V (ra1);
1219 }
0f2d19dd
JB
1220 else
1221 {
c209c88e
GB
1222 /*
1223 Huh ? Schizophrenic return type. --hwn
1224 */
0f2d19dd 1225 if (1 != ndim)
c209c88e 1226 return 0;
0f2d19dd
JB
1227 s1->inc = 1;
1228 s1->lbnd = 0;
ee67e2fa 1229 s1->ubnd = scm_c_generalized_vector_length (v1) - 1;
0f2d19dd
JB
1230 unroll = 0;
1231 }
1232 if (SCM_TYP7 (v0) != SCM_TYP7 (v1))
1233 return 0;
1234 for (k = ndim; k--;)
1235 {
1236 if (s0[k].lbnd != s1[k].lbnd || s0[k].ubnd != s1[k].ubnd)
1237 return 0;
1238 if (unroll)
1239 {
1240 unroll = (s0[k].inc == s1[k].inc);
1241 vlen *= s0[k].ubnd - s1[k].lbnd + 1;
1242 }
1243 }
bc36d050 1244 if (unroll && bas0 == bas1 && scm_is_eq (v0, v1))
c209c88e 1245 return 1;
0f2d19dd
JB
1246 return scm_ramapc (raeql_1, as_equal, ra0, scm_cons (ra1, SCM_EOL), "");
1247}
1248
1cc91f1b 1249
0f2d19dd 1250SCM
1bbd0b84 1251scm_raequal (SCM ra0, SCM ra1)
0f2d19dd 1252{
7888309b 1253 return scm_from_bool(raeql (ra0, SCM_BOOL_T, ra1));
0f2d19dd
JB
1254}
1255
4079f87e 1256#if 0
c3ee7520
GB
1257/* GJB:FIXME:: Why not use SCM_DEFINE1 for array-equal? */
1258SCM_DEFINE1 (scm_array_equal_p, "array-equal?", scm_tc7_rpsubr,
c209c88e 1259 (SCM ra0, SCM ra1),
1e6808ea
MG
1260 "Return @code{#t} iff all arguments are arrays with the same\n"
1261 "shape, the same type, and have corresponding elements which are\n"
1262 "either @code{equal?} or @code{array-equal?}. This function\n"
1263 "differs from @code{equal?} in that a one dimensional shared\n"
1264 "array may be @var{array-equal?} but not @var{equal?} to a\n"
1265 "vector or uniform vector.")
4079f87e 1266#define FUNC_NAME s_scm_array_equal_p
0f981281
GB
1267{
1268}
4079f87e
GB
1269#undef FUNC_NAME
1270#endif
1271
0f2d19dd
JB
1272static char s_array_equal_p[] = "array-equal?";
1273
1cc91f1b 1274
0f2d19dd 1275SCM
1bbd0b84 1276scm_array_equal_p (SCM ra0, SCM ra1)
0f2d19dd 1277{
399aba0a
MV
1278 if (SCM_ARRAYP (ra0) || SCM_ARRAYP (ra1))
1279 return scm_from_bool(raeql (ra0, SCM_BOOL_F, ra1));
1280 return scm_equal_p (ra0, ra1);
0f2d19dd
JB
1281}
1282
1283
1cc91f1b 1284static void
1bbd0b84 1285init_raprocs (ra_iproc *subra)
0f2d19dd
JB
1286{
1287 for (; subra->name; subra++)
86d31dfe 1288 {
cc95e00a 1289 SCM sym = scm_from_locale_symbol (subra->name);
86d31dfe
MV
1290 SCM var =
1291 scm_sym2var (sym, scm_current_module_lookup_closure (), SCM_BOOL_F);
1292 if (var != SCM_BOOL_F)
1293 subra->sproc = SCM_VARIABLE_REF (var);
1294 else
1295 subra->sproc = SCM_BOOL_F;
1296 }
0f2d19dd
JB
1297}
1298
1cc91f1b 1299
0f2d19dd
JB
1300void
1301scm_init_ramap ()
0f2d19dd
JB
1302{
1303 init_raprocs (ra_rpsubrs);
1304 init_raprocs (ra_asubrs);
9a441ddb 1305 scm_c_define_subr (s_array_equal_p, scm_tc7_rpsubr, scm_array_equal_p);
7a7f7c53 1306 scm_smobs[SCM_TC2SMOBNUM (scm_tc16_array)].equalp = scm_raequal;
a0599745 1307#include "libguile/ramap.x"
1bbd0b84 1308 scm_add_feature (s_scm_array_for_each);
0f2d19dd 1309}
89e00824
ML
1310
1311/*
1312 Local Variables:
1313 c-file-style: "gnu"
1314 End:
1315*/