*** empty log message ***
[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"
a0599745
MD
39
40#include "libguile/validate.h"
41#include "libguile/ramap.h"
0f2d19dd
JB
42\f
43
0f2d19dd
JB
44typedef struct
45{
46 char *name;
47 SCM sproc;
48 int (*vproc) ();
49} ra_iproc;
50
ad310508
MD
51
52/* These tables are a kluge that will not scale well when more
53 * vectorized subrs are added. It is tempting to steal some bits from
54 * the SCM_CAR of all subrs (like those selected by SCM_SMOBNUM) to hold an
55 * offset into a table of vectorized subrs.
56 */
57
58static ra_iproc ra_rpsubrs[] =
59{
60 {"=", SCM_UNDEFINED, scm_ra_eqp},
61 {"<", SCM_UNDEFINED, scm_ra_lessp},
62 {"<=", SCM_UNDEFINED, scm_ra_leqp},
63 {">", SCM_UNDEFINED, scm_ra_grp},
64 {">=", SCM_UNDEFINED, scm_ra_greqp},
65 {0, 0, 0}
66};
67
68static ra_iproc ra_asubrs[] =
69{
70 {"+", SCM_UNDEFINED, scm_ra_sum},
71 {"-", SCM_UNDEFINED, scm_ra_difference},
72 {"*", SCM_UNDEFINED, scm_ra_product},
73 {"/", SCM_UNDEFINED, scm_ra_divide},
74 {0, 0, 0}
75};
76
0f2d19dd 77
0f2d19dd
JB
78
79/* Fast, recycling scm_vector ref */
80#define RVREF(ra, i, e) (e = scm_cvref(ra, i, e))
81
82/* #define RVREF(ra, i, e) (scm_cvref(ra, i, SCM_UNDEFINED)) to turn off */
83
84/* IVDEP means "ignore scm_vector dependencies", meaning we guarantee that
85 elements of scm_vector operands are not aliased */
86#ifdef _UNICOS
87#define IVDEP(test, line) if (test) {_Pragma("ivdep"); line} else {line}
88#else
89#define IVDEP(test, line) line
90#endif
91
92\f
93
94/* inds must be a uvect or ivect, no check. */
95
1cc91f1b 96
c209c88e
GB
97
98/*
99 Yes, this is really ugly, but it prevents multiple code
100 */
101#define BINARY_ELTS_CODE(OPERATOR, type) \
102do { type *v0 = (type*)SCM_VELTS (ra0);\
103 type *v1 = (type*)SCM_VELTS (ra1);\
104 IVDEP (ra0 != ra1, \
105 for (; n-- > 0; i0 += inc0, i1 += inc1) \
106 v0[i0] OPERATOR v1[i1];) \
c209c88e
GB
107} while (0)
108
109/* This macro is used for all but binary division and
110 multiplication of complex numbers -- see the expanded
111 version in the functions later in this file */
112#define BINARY_PAIR_ELTS_CODE(OPERATOR, type) \
113do { type (*v0)[2] = (type (*)[2]) SCM_VELTS (ra0);\
114 type (*v1)[2] = (type (*)[2]) SCM_VELTS (ra1);\
115 IVDEP (ra0 != ra1, \
116 for (; n-- > 0; i0 += inc0, i1 += inc1) {\
117 v0[i0][0] OPERATOR v1[i1][0]; \
118 v0[i0][1] OPERATOR v1[i1][1]; \
119 }) \
c209c88e
GB
120} while (0)
121
122#define UNARY_ELTS_CODE(OPERATOR, type) \
123 do { type *v0 = (type *) SCM_VELTS (ra0);\
124 for (; n-- > 0; i0 += inc0) \
125 v0[i0] OPERATOR v0[i0];\
c209c88e
GB
126 } while (0)
127
128
129/* This macro is used for all but unary divison
130 of complex numbers -- see the expanded version in the
131 function later in this file. */
132#define UNARY_PAIR_ELTS_CODE(OPERATOR, type) \
133 do { type (*v0)[2] = (type (*)[2]) SCM_VELTS (ra0);\
134 for (; n-- > 0; i0 += inc0) {\
135 v0[i0][0] OPERATOR v0[i0][0];\
136 v0[i0][1] OPERATOR v0[i0][1];\
137 }\
138 break;\
139 } while (0)
140
c014a02e 141static unsigned long
1bbd0b84 142cind (SCM ra, SCM inds)
0f2d19dd 143{
c014a02e 144 unsigned long i;
0f2d19dd 145 int k;
c014a02e 146 long *ve = (long*) SCM_VELTS (inds);
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
JB
260{
261 SCM inds, z;
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 {
e11e83f3 339 unsigned long length = scm_to_ulong (scm_uniform_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 }
e11e83f3 370 inds = scm_make_uve (SCM_ARRAY_NDIM (ra0), scm_from_int (-1));
c014a02e 371 vinds = (long *) SCM_VELTS (inds);
c209c88e
GB
372 for (k = 0; k <= kmax; k++)
373 vinds[k] = SCM_ARRAY_DIMS (ra0)[k].lbnd;
374 k = kmax;
375 do
376 {
377 if (k == kmax)
378 {
379 SCM y = lra;
380 SCM_ARRAY_BASE (vra0) = cind (ra0, inds);
381 for (z = lvra; SCM_NIMP (z); z = SCM_CDR (z), y = SCM_CDR (y))
382 SCM_ARRAY_BASE (SCM_CAR (z)) = cind (SCM_CAR (y), inds);
383 if (0 == (SCM_UNBNDP (data) ? cproc(vra0, lvra) : cproc(vra0, data, lvra)))
384 return 0;
385 k--;
386 continue;
387 }
388 if (vinds[k] < SCM_ARRAY_DIMS (ra0)[k].ubnd)
389 {
390 vinds[k]++;
391 k++;
392 continue;
393 }
394 vinds[k] = SCM_ARRAY_DIMS (ra0)[k].lbnd - 1;
395 k--;
396 }
397 while (k >= 0);
398 return 1;
0f2d19dd
JB
399 }
400}
401
402
3b3b36dd 403SCM_DEFINE (scm_array_fill_x, "array-fill!", 2, 0, 0,
c209c88e 404 (SCM ra, SCM fill),
8f85c0c6 405 "Store @var{fill} in every element of @var{array}. The value returned\n"
b380b885 406 "is unspecified.")
1bbd0b84 407#define FUNC_NAME s_scm_array_fill_x
ad310508 408{
c209c88e 409 scm_ramapc (scm_array_fill_int, fill, ra, SCM_EOL, FUNC_NAME);
ad310508
MD
410 return SCM_UNSPECIFIED;
411}
1bbd0b84 412#undef FUNC_NAME
ad310508 413
5c11cc9d
GH
414/* to be used as cproc in scm_ramapc to fill an array dimension with
415 "fill". */
0f2d19dd 416int
e81d98ec 417scm_array_fill_int (SCM ra, SCM fill, SCM ignore SCM_UNUSED)
1bbd0b84 418#define FUNC_NAME s_scm_array_fill_x
0f2d19dd 419{
c014a02e
ML
420 unsigned long i;
421 unsigned long n = SCM_ARRAY_DIMS (ra)->ubnd - SCM_ARRAY_DIMS (ra)->lbnd + 1;
422 long inc = SCM_ARRAY_DIMS (ra)->inc;
423 unsigned long base = SCM_ARRAY_BASE (ra);
5c11cc9d 424
0f2d19dd 425 ra = SCM_ARRAY_V (ra);
b4bdadde 426
399aba0a 427 if (scm_is_generalized_vector (ra))
b4bdadde
MV
428 {
429 for (i = base; n--; i += inc)
399aba0a 430 scm_c_generalized_vector_set_x (ra, i, fill);
b4bdadde 431 }
399aba0a 432 else
5c11cc9d 433 {
5c11cc9d 434 for (i = base; n--; i += inc)
e11e83f3 435 scm_array_set_x (ra, fill, scm_from_ulong (i));
5c11cc9d 436 }
0f2d19dd
JB
437 return 1;
438}
1bbd0b84 439#undef FUNC_NAME
0f2d19dd 440
0f2d19dd 441
c209c88e 442
0f2d19dd 443static int
1bbd0b84 444racp (SCM src, SCM dst)
0f2d19dd 445{
c014a02e
ML
446 long n = (SCM_ARRAY_DIMS (src)->ubnd - SCM_ARRAY_DIMS (src)->lbnd + 1);
447 long inc_d, inc_s = SCM_ARRAY_DIMS (src)->inc;
448 unsigned long i_d, i_s = SCM_ARRAY_BASE (src);
0f2d19dd
JB
449 dst = SCM_CAR (dst);
450 inc_d = SCM_ARRAY_DIMS (dst)->inc;
451 i_d = SCM_ARRAY_BASE (dst);
452 src = SCM_ARRAY_V (src);
453 dst = SCM_ARRAY_V (dst);
c209c88e 454
399aba0a
MV
455 for (; n-- > 0; i_s += inc_s, i_d += inc_d)
456 scm_array_set_x (dst, scm_cvref (src, i_s, SCM_UNDEFINED),
457 scm_from_ulong (i_d));
0f2d19dd
JB
458 return 1;
459}
460
1bbd0b84 461SCM_REGISTER_PROC(s_array_copy_in_order_x, "array-copy-in-order!", 2, 0, 0, scm_array_copy_x);
1cc91f1b 462
1bbd0b84 463
3b3b36dd 464SCM_DEFINE (scm_array_copy_x, "array-copy!", 2, 0, 0,
c209c88e 465 (SCM src, SCM dst),
8f85c0c6
NJ
466 "@deffnx {Scheme Procedure} array-copy-in-order! src dst\n"
467 "Copy every element from vector or array @var{source} to the\n"
b380b885
MD
468 "corresponding element of @var{destination}. @var{destination} must have\n"
469 "the same rank as @var{source}, and be at least as large in each\n"
470 "dimension. The order is unspecified.")
1bbd0b84 471#define FUNC_NAME s_scm_array_copy_x
0f2d19dd 472{
c209c88e 473 scm_ramapc (racp, SCM_UNDEFINED, src, scm_cons (dst, SCM_EOL), FUNC_NAME);
0f2d19dd
JB
474 return SCM_UNSPECIFIED;
475}
1bbd0b84 476#undef FUNC_NAME
0f2d19dd
JB
477
478/* Functions callable by ARRAY-MAP! */
479
1cc91f1b 480
0f2d19dd 481int
1bbd0b84 482scm_ra_eqp (SCM ra0, SCM ras)
0f2d19dd
JB
483{
484 SCM ra1 = SCM_CAR (ras), ra2 = SCM_CAR (SCM_CDR (ras));
c014a02e
ML
485 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
486 unsigned long i0 = SCM_ARRAY_BASE (ra0), i1 = SCM_ARRAY_BASE (ra1), i2 = SCM_ARRAY_BASE (ra2);
487 long inc0 = SCM_ARRAY_DIMS (ra0)->inc;
488 long inc1 = SCM_ARRAY_DIMS (ra1)->inc;
489 long inc2 = SCM_ARRAY_DIMS (ra1)->inc;
0f2d19dd
JB
490 ra0 = SCM_ARRAY_V (ra0);
491 ra1 = SCM_ARRAY_V (ra1);
492 ra2 = SCM_ARRAY_V (ra2);
399aba0a
MV
493
494 {
495 SCM e1 = SCM_UNDEFINED, e2 = SCM_UNDEFINED;
496 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
497 if (scm_is_true (scm_c_bitvector_ref (ra0, i0)))
498 if (!scm_is_eq (RVREF (ra1, i1, e1), RVREF (ra2, i2, e2)))
499 scm_c_bitvector_set_x (ra0, i0, SCM_BOOL_F);
500 }
501
0f2d19dd
JB
502 return 1;
503}
504
505/* opt 0 means <, nonzero means >= */
1cc91f1b 506
0f2d19dd 507static int
34d19ef6 508ra_compare (SCM ra0, SCM ra1, SCM ra2, int opt)
0f2d19dd 509{
c014a02e
ML
510 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
511 unsigned long i0 = SCM_ARRAY_BASE (ra0), i1 = SCM_ARRAY_BASE (ra1), i2 = SCM_ARRAY_BASE (ra2);
512 long inc0 = SCM_ARRAY_DIMS (ra0)->inc;
513 long inc1 = SCM_ARRAY_DIMS (ra1)->inc;
514 long inc2 = SCM_ARRAY_DIMS (ra1)->inc;
0f2d19dd
JB
515 ra0 = SCM_ARRAY_V (ra0);
516 ra1 = SCM_ARRAY_V (ra1);
517 ra2 = SCM_ARRAY_V (ra2);
399aba0a
MV
518
519 {
520 SCM e1 = SCM_UNDEFINED, e2 = SCM_UNDEFINED;
521 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
522 if (scm_is_true (scm_c_bitvector_ref (ra0, i0)))
523 if (opt ?
524 scm_is_true (scm_less_p (RVREF (ra1, i1, e1), RVREF (ra2, i2, e2))) :
525 scm_is_false (scm_less_p (RVREF (ra1, i1, e1), RVREF (ra2, i2, e2))))
526 scm_c_bitvector_set_x (ra0, i0, SCM_BOOL_F);
527 }
528
0f2d19dd
JB
529 return 1;
530}
531
532
1cc91f1b 533
0f2d19dd 534int
1bbd0b84 535scm_ra_lessp (SCM ra0, SCM ras)
0f2d19dd
JB
536{
537 return ra_compare (ra0, SCM_CAR (ras), SCM_CAR (SCM_CDR (ras)), 0);
538}
539
1cc91f1b 540
0f2d19dd 541int
1bbd0b84 542scm_ra_leqp (SCM ra0, SCM ras)
0f2d19dd
JB
543{
544 return ra_compare (ra0, SCM_CAR (SCM_CDR (ras)), SCM_CAR (ras), 1);
545}
546
1cc91f1b 547
0f2d19dd 548int
1bbd0b84 549scm_ra_grp (SCM ra0, SCM ras)
0f2d19dd
JB
550{
551 return ra_compare (ra0, SCM_CAR (SCM_CDR (ras)), SCM_CAR (ras), 0);
552}
553
1cc91f1b 554
0f2d19dd 555int
1bbd0b84 556scm_ra_greqp (SCM ra0, SCM ras)
0f2d19dd
JB
557{
558 return ra_compare (ra0, SCM_CAR (ras), SCM_CAR (SCM_CDR (ras)), 1);
559}
560
561
0f2d19dd 562int
1bbd0b84 563scm_ra_sum (SCM ra0, SCM ras)
0f2d19dd 564{
c014a02e
ML
565 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
566 unsigned long i0 = SCM_ARRAY_BASE (ra0);
567 long inc0 = SCM_ARRAY_DIMS (ra0)->inc;
0f2d19dd 568 ra0 = SCM_ARRAY_V (ra0);
d2e53ed6 569 if (!scm_is_null(ras))
c209c88e
GB
570 {
571 SCM ra1 = SCM_CAR (ras);
c014a02e
ML
572 unsigned long i1 = SCM_ARRAY_BASE (ra1);
573 long inc1 = SCM_ARRAY_DIMS (ra1)->inc;
c209c88e
GB
574 ra1 = SCM_ARRAY_V (ra1);
575 switch (SCM_TYP7 (ra0) == SCM_TYP7 (ra1) ? SCM_TYP7 (ra0) : 0)
576 {
577 default:
0f2d19dd 578 {
c209c88e
GB
579 SCM e0 = SCM_UNDEFINED, e1 = SCM_UNDEFINED;
580 for (; n-- > 0; i0 += inc0, i1 += inc1)
581 scm_array_set_x (ra0, scm_sum (RVREF (ra0, i0, e0), RVREF (ra1, i1, e1)),
e11e83f3 582 scm_from_ulong (i0));
c209c88e
GB
583 break;
584 }
c209c88e
GB
585 }
586 }
0f2d19dd
JB
587 return 1;
588}
589
590
1cc91f1b 591
0f2d19dd 592int
1bbd0b84 593scm_ra_difference (SCM ra0, SCM ras)
0f2d19dd 594{
c014a02e
ML
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;
0f2d19dd 598 ra0 = SCM_ARRAY_V (ra0);
d2e53ed6 599 if (scm_is_null (ras))
c209c88e
GB
600 {
601 switch (SCM_TYP7 (ra0))
602 {
603 default:
604 {
605 SCM e0 = SCM_UNDEFINED;
606 for (; n-- > 0; i0 += inc0)
607 scm_array_set_x (ra0,
608 scm_difference (RVREF (ra0, i0, e0), SCM_UNDEFINED),
e11e83f3 609 scm_from_ulong (i0));
c209c88e
GB
610 break;
611 }
c209c88e
GB
612 }
613 }
0f2d19dd
JB
614 else
615 {
616 SCM ra1 = SCM_CAR (ras);
c014a02e
ML
617 unsigned long i1 = SCM_ARRAY_BASE (ra1);
618 long inc1 = SCM_ARRAY_DIMS (ra1)->inc;
0f2d19dd
JB
619 ra1 = SCM_ARRAY_V (ra1);
620 switch (SCM_TYP7 (ra0) == SCM_TYP7 (ra1) ? SCM_TYP7 (ra0) : 0)
621 {
622 default:
623 {
624 SCM e0 = SCM_UNDEFINED, e1 = SCM_UNDEFINED;
625 for (; n-- > 0; i0 += inc0, i1 += inc1)
e11e83f3 626 scm_array_set_x (ra0, scm_difference (RVREF (ra0, i0, e0), RVREF (ra1, i1, e1)), scm_from_ulong (i0));
0f2d19dd
JB
627 break;
628 }
0f2d19dd
JB
629 }
630 }
631 return 1;
632}
633
634
1cc91f1b 635
0f2d19dd 636int
1bbd0b84 637scm_ra_product (SCM ra0, SCM ras)
0f2d19dd 638{
c014a02e
ML
639 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
640 unsigned long i0 = SCM_ARRAY_BASE (ra0);
641 long inc0 = SCM_ARRAY_DIMS (ra0)->inc;
0f2d19dd 642 ra0 = SCM_ARRAY_V (ra0);
d2e53ed6 643 if (!scm_is_null (ras))
c209c88e
GB
644 {
645 SCM ra1 = SCM_CAR (ras);
c014a02e
ML
646 unsigned long i1 = SCM_ARRAY_BASE (ra1);
647 long inc1 = SCM_ARRAY_DIMS (ra1)->inc;
c209c88e
GB
648 ra1 = SCM_ARRAY_V (ra1);
649 switch (SCM_TYP7 (ra0) == SCM_TYP7 (ra1) ? SCM_TYP7 (ra0) : 0)
650 {
651 default:
0f2d19dd 652 {
c209c88e
GB
653 SCM e0 = SCM_UNDEFINED, e1 = SCM_UNDEFINED;
654 for (; n-- > 0; i0 += inc0, i1 += inc1)
655 scm_array_set_x (ra0, scm_product (RVREF (ra0, i0, e0), RVREF (ra1, i1, e1)),
e11e83f3 656 scm_from_ulong (i0));
c209c88e
GB
657 break;
658 }
c209c88e
GB
659 }
660 }
0f2d19dd
JB
661 return 1;
662}
663
1cc91f1b 664
0f2d19dd 665int
1bbd0b84 666scm_ra_divide (SCM ra0, SCM ras)
0f2d19dd 667{
c014a02e
ML
668 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
669 unsigned long i0 = SCM_ARRAY_BASE (ra0);
670 long inc0 = SCM_ARRAY_DIMS (ra0)->inc;
0f2d19dd 671 ra0 = SCM_ARRAY_V (ra0);
d2e53ed6 672 if (scm_is_null (ras))
c209c88e
GB
673 {
674 switch (SCM_TYP7 (ra0))
675 {
676 default:
677 {
678 SCM e0 = SCM_UNDEFINED;
679 for (; n-- > 0; i0 += inc0)
e11e83f3 680 scm_array_set_x (ra0, scm_divide (RVREF (ra0, i0, e0), SCM_UNDEFINED), scm_from_ulong (i0));
c209c88e
GB
681 break;
682 }
c209c88e
GB
683 }
684 }
0f2d19dd
JB
685 else
686 {
687 SCM ra1 = SCM_CAR (ras);
c014a02e
ML
688 unsigned long i1 = SCM_ARRAY_BASE (ra1);
689 long inc1 = SCM_ARRAY_DIMS (ra1)->inc;
0f2d19dd
JB
690 ra1 = SCM_ARRAY_V (ra1);
691 switch (SCM_TYP7 (ra0) == SCM_TYP7 (ra1) ? SCM_TYP7 (ra0) : 0)
692 {
693 default:
694 {
695 SCM e0 = SCM_UNDEFINED, e1 = SCM_UNDEFINED;
696 for (; n-- > 0; i0 += inc0, i1 += inc1)
e11e83f3 697 scm_array_set_x (ra0, scm_divide (RVREF (ra0, i0, e0), RVREF (ra1, i1, e1)), scm_from_ulong (i0));
0f2d19dd
JB
698 break;
699 }
0f2d19dd
JB
700 }
701 }
702 return 1;
703}
704
1cc91f1b 705
0f2d19dd 706int
1bbd0b84 707scm_array_identity (SCM dst, SCM src)
0f2d19dd
JB
708{
709 return racp (SCM_CAR (src), scm_cons (dst, SCM_EOL));
710}
711
712
1cc91f1b 713
0f2d19dd 714static int
34d19ef6 715ramap (SCM ra0, SCM proc, SCM ras)
0f2d19dd 716{
c014a02e
ML
717 long i = SCM_ARRAY_DIMS (ra0)->lbnd;
718 long inc = SCM_ARRAY_DIMS (ra0)->inc;
719 long n = SCM_ARRAY_DIMS (ra0)->ubnd;
720 long base = SCM_ARRAY_BASE (ra0) - i * inc;
0f2d19dd 721 ra0 = SCM_ARRAY_V (ra0);
d2e53ed6 722 if (scm_is_null (ras))
c209c88e 723 for (; i <= n; i++)
e11e83f3 724 scm_array_set_x (ra0, scm_call_0 (proc), scm_from_long (i * inc + base));
0f2d19dd
JB
725 else
726 {
727 SCM ra1 = SCM_CAR (ras);
34d19ef6
HWN
728 SCM args;
729 SCM const *ve = &ras;
c014a02e
ML
730 unsigned long k, i1 = SCM_ARRAY_BASE (ra1);
731 long inc1 = SCM_ARRAY_DIMS (ra1)->inc;
0f2d19dd
JB
732 ra1 = SCM_ARRAY_V (ra1);
733 ras = SCM_CDR (ras);
d2e53ed6 734 if (scm_is_null(ras))
c209c88e 735 ras = scm_nullvect;
0f2d19dd
JB
736 else
737 {
738 ras = scm_vector (ras);
739 ve = SCM_VELTS (ras);
740 }
34d19ef6 741
0f2d19dd
JB
742 for (; i <= n; i++, i1 += inc1)
743 {
744 args = SCM_EOL;
e11e83f3
MV
745 for (k = scm_to_ulong (scm_uniform_vector_length (ras)); k--;)
746 args = scm_cons (scm_uniform_vector_ref (ve[k], scm_from_long (i)), args);
0f2d19dd 747 args = scm_cons (scm_cvref (ra1, i1, SCM_UNDEFINED), args);
e11e83f3 748 scm_array_set_x (ra0, scm_apply_0 (proc, args), scm_from_long (i * inc + base));
0f2d19dd
JB
749 }
750 }
751 return 1;
752}
753
1cc91f1b 754
0f2d19dd 755static int
14b18ed6 756ramap_dsubr (SCM ra0, SCM proc, SCM ras)
0f2d19dd
JB
757{
758 SCM ra1 = SCM_CAR (ras);
759 SCM e1 = SCM_UNDEFINED;
c014a02e
ML
760 unsigned long i0 = SCM_ARRAY_BASE (ra0), i1 = SCM_ARRAY_BASE (ra1);
761 long inc0 = SCM_ARRAY_DIMS (ra0)->inc, inc1 = SCM_ARRAY_DIMS (ra1)->inc;
762 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra1)->lbnd + 1;
0f2d19dd
JB
763 ra0 = SCM_ARRAY_V (ra0);
764 ra1 = SCM_ARRAY_V (ra1);
ff467021 765 switch (SCM_TYP7 (ra0))
c209c88e
GB
766 {
767 default:
c209c88e 768 for (; n-- > 0; i0 += inc0, i1 += inc1)
e11e83f3 769 scm_array_set_x (ra0, scm_call_1 (proc, RVREF (ra1, i1, e1)), scm_from_ulong (i0));
c209c88e 770 break;
c209c88e 771 }
0f2d19dd
JB
772 return 1;
773}
774
775
1cc91f1b 776
0f2d19dd 777static int
34d19ef6 778ramap_rp (SCM ra0, SCM proc, SCM ras)
0f2d19dd
JB
779{
780 SCM ra1 = SCM_CAR (ras), ra2 = SCM_CAR (SCM_CDR (ras));
781 SCM e1 = SCM_UNDEFINED, e2 = SCM_UNDEFINED;
c014a02e
ML
782 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
783 unsigned long i0 = SCM_ARRAY_BASE (ra0), i1 = SCM_ARRAY_BASE (ra1), i2 = SCM_ARRAY_BASE (ra2);
784 long inc0 = SCM_ARRAY_DIMS (ra0)->inc;
785 long inc1 = SCM_ARRAY_DIMS (ra1)->inc;
786 long inc2 = SCM_ARRAY_DIMS (ra1)->inc;
0f2d19dd
JB
787 ra0 = SCM_ARRAY_V (ra0);
788 ra1 = SCM_ARRAY_V (ra1);
789 ra2 = SCM_ARRAY_V (ra2);
399aba0a
MV
790
791 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
792 if (scm_is_true (scm_c_bitvector_ref (ra0, i0)))
793 if (scm_is_false (SCM_SUBRF (proc) (RVREF (ra1, i1, e1), RVREF (ra2, i2, e2))))
794 scm_c_bitvector_set_x (ra0, i0, SCM_BOOL_F);
795
0f2d19dd
JB
796 return 1;
797}
798
799
1cc91f1b 800
0f2d19dd 801static int
34d19ef6 802ramap_1 (SCM ra0, SCM proc, SCM ras)
0f2d19dd
JB
803{
804 SCM ra1 = SCM_CAR (ras);
805 SCM e1 = SCM_UNDEFINED;
c014a02e
ML
806 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
807 unsigned long i0 = SCM_ARRAY_BASE (ra0), i1 = SCM_ARRAY_BASE (ra1);
808 long inc0 = SCM_ARRAY_DIMS (ra0)->inc, inc1 = SCM_ARRAY_DIMS (ra1)->inc;
0f2d19dd
JB
809 ra0 = SCM_ARRAY_V (ra0);
810 ra1 = SCM_ARRAY_V (ra1);
95f5b0f5 811 if (scm_tc7_vector == SCM_TYP7 (ra0) || scm_tc7_wvect == SCM_TYP7 (ra0))
0f2d19dd 812 for (; n-- > 0; i0 += inc0, i1 += inc1)
e11e83f3 813 scm_array_set_x (ra0, SCM_SUBRF (proc) (scm_cvref (ra1, i1, SCM_UNDEFINED)), scm_from_ulong (i0));
0f2d19dd
JB
814 else
815 for (; n-- > 0; i0 += inc0, i1 += inc1)
e11e83f3 816 scm_array_set_x (ra0, SCM_SUBRF (proc) (RVREF (ra1, i1, e1)), scm_from_ulong (i0));
0f2d19dd
JB
817 return 1;
818}
819
820
1cc91f1b 821
0f2d19dd 822static int
34d19ef6 823ramap_2o (SCM ra0, SCM proc, SCM ras)
0f2d19dd
JB
824{
825 SCM ra1 = SCM_CAR (ras);
826 SCM e1 = SCM_UNDEFINED;
c014a02e
ML
827 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
828 unsigned long i0 = SCM_ARRAY_BASE (ra0), i1 = SCM_ARRAY_BASE (ra1);
829 long inc0 = SCM_ARRAY_DIMS (ra0)->inc, inc1 = SCM_ARRAY_DIMS (ra1)->inc;
0f2d19dd
JB
830 ra0 = SCM_ARRAY_V (ra0);
831 ra1 = SCM_ARRAY_V (ra1);
832 ras = SCM_CDR (ras);
d2e53ed6 833 if (scm_is_null (ras))
c209c88e
GB
834 {
835 if (scm_tc7_vector == SCM_TYP7 (ra0)
836 || scm_tc7_wvect == SCM_TYP7 (ra0))
95f5b0f5 837
c209c88e
GB
838 for (; n-- > 0; i0 += inc0, i1 += inc1)
839 scm_array_set_x (ra0, SCM_SUBRF (proc) (scm_cvref (ra1, i1, SCM_UNDEFINED), SCM_UNDEFINED),
e11e83f3 840 scm_from_ulong (i0));
c209c88e
GB
841 else
842 for (; n-- > 0; i0 += inc0, i1 += inc1)
843 scm_array_set_x (ra0, SCM_SUBRF (proc) (RVREF (ra1, i1, e1), SCM_UNDEFINED),
e11e83f3 844 scm_from_ulong (i0));
c209c88e 845 }
0f2d19dd
JB
846 else
847 {
848 SCM ra2 = SCM_CAR (ras);
849 SCM e2 = SCM_UNDEFINED;
c014a02e
ML
850 unsigned long i2 = SCM_ARRAY_BASE (ra2);
851 long inc2 = SCM_ARRAY_DIMS (ra2)->inc;
0f2d19dd 852 ra2 = SCM_ARRAY_V (ra2);
95f5b0f5 853 if (scm_tc7_vector == SCM_TYP7 (ra0) || scm_tc7_wvect == SCM_TYP7 (ra0))
0f2d19dd
JB
854 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
855 scm_array_set_x (ra0,
c209c88e 856 SCM_SUBRF (proc) (scm_cvref (ra1, i1, SCM_UNDEFINED), scm_cvref (ra2, i2, SCM_UNDEFINED)),
e11e83f3 857 scm_from_ulong (i0));
0f2d19dd
JB
858 else
859 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
860 scm_array_set_x (ra0,
c209c88e 861 SCM_SUBRF (proc) (RVREF (ra1, i1, e1), RVREF (ra2, i2, e2)),
e11e83f3 862 scm_from_ulong (i0));
0f2d19dd
JB
863 }
864 return 1;
865}
866
867
1cc91f1b 868
0f2d19dd 869static int
34d19ef6 870ramap_a (SCM ra0, SCM proc, SCM ras)
0f2d19dd
JB
871{
872 SCM e0 = SCM_UNDEFINED, e1 = SCM_UNDEFINED;
c014a02e
ML
873 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
874 unsigned long i0 = SCM_ARRAY_BASE (ra0);
875 long inc0 = SCM_ARRAY_DIMS (ra0)->inc;
0f2d19dd 876 ra0 = SCM_ARRAY_V (ra0);
d2e53ed6 877 if (scm_is_null (ras))
c209c88e 878 for (; n-- > 0; i0 += inc0)
e11e83f3 879 scm_array_set_x (ra0, SCM_SUBRF (proc) (RVREF (ra0, i0, e0), SCM_UNDEFINED), scm_from_ulong (i0));
0f2d19dd
JB
880 else
881 {
882 SCM ra1 = SCM_CAR (ras);
c014a02e
ML
883 unsigned long i1 = SCM_ARRAY_BASE (ra1);
884 long inc1 = SCM_ARRAY_DIMS (ra1)->inc;
0f2d19dd
JB
885 ra1 = SCM_ARRAY_V (ra1);
886 for (; n-- > 0; i0 += inc0, i1 += inc1)
887 scm_array_set_x (ra0, SCM_SUBRF (proc) (RVREF (ra0, i0, e0), RVREF (ra1, i1, e1)),
e11e83f3 888 scm_from_ulong (i0));
0f2d19dd
JB
889 }
890 return 1;
891}
892
f5f2dcff 893
1bbd0b84 894SCM_REGISTER_PROC(s_array_map_in_order_x, "array-map-in-order!", 2, 0, 1, scm_array_map_x);
1cc91f1b 895
1bbd0b84 896
3b3b36dd 897SCM_DEFINE (scm_array_map_x, "array-map!", 2, 0, 1,
c209c88e 898 (SCM ra0, SCM proc, SCM lra),
8f85c0c6 899 "@deffnx {Scheme Procedure} array-map-in-order! ra0 proc . lra\n"
b380b885
MD
900 "@var{array1}, @dots{} must have the same number of dimensions as\n"
901 "@var{array0} and have a range for each index which includes the range\n"
902 "for the corresponding index in @var{array0}. @var{proc} is applied to\n"
903 "each tuple of elements of @var{array1} @dots{} and the result is stored\n"
904 "as the corresponding element in @var{array0}. The value returned is\n"
905 "unspecified. The order of application is unspecified.")
1bbd0b84 906#define FUNC_NAME s_scm_array_map_x
0f2d19dd 907{
34d19ef6 908 SCM_VALIDATE_PROC (2, proc);
af45e3b0 909 SCM_VALIDATE_REST_ARGUMENT (lra);
0f2d19dd 910 switch (SCM_TYP7 (proc))
c209c88e
GB
911 {
912 default:
913 gencase:
914 scm_ramapc (ramap, proc, ra0, lra, FUNC_NAME);
915 return SCM_UNSPECIFIED;
916 case scm_tc7_subr_1:
917 scm_ramapc (ramap_1, proc, ra0, lra, FUNC_NAME);
918 return SCM_UNSPECIFIED;
919 case scm_tc7_subr_2:
920 case scm_tc7_subr_2o:
921 scm_ramapc (ramap_2o, proc, ra0, lra, FUNC_NAME);
922 return SCM_UNSPECIFIED;
14b18ed6
DH
923 case scm_tc7_dsubr:
924 scm_ramapc (ramap_dsubr, proc, ra0, lra, FUNC_NAME);
c209c88e
GB
925 return SCM_UNSPECIFIED;
926 case scm_tc7_rpsubr:
0f2d19dd 927 {
c209c88e 928 ra_iproc *p;
7888309b 929 if (scm_is_false (scm_array_p (ra0, SCM_BOOL_T)))
0f2d19dd 930 goto gencase;
c209c88e
GB
931 scm_array_fill_x (ra0, SCM_BOOL_T);
932 for (p = ra_rpsubrs; p->name; p++)
bc36d050 933 if (scm_is_eq (proc, p->sproc))
c209c88e 934 {
d2e53ed6 935 while (!scm_is_null (lra) && !scm_is_null (SCM_CDR (lra)))
c209c88e
GB
936 {
937 scm_ramapc (p->vproc, SCM_UNDEFINED, ra0, lra, FUNC_NAME);
938 lra = SCM_CDR (lra);
939 }
940 return SCM_UNSPECIFIED;
941 }
d2e53ed6 942 while (!scm_is_null (lra) && !scm_is_null (SCM_CDR (lra)))
c209c88e
GB
943 {
944 scm_ramapc (ramap_rp, proc, ra0, lra, FUNC_NAME);
945 lra = SCM_CDR (lra);
946 }
0f2d19dd 947 return SCM_UNSPECIFIED;
c209c88e
GB
948 }
949 case scm_tc7_asubr:
d2e53ed6 950 if (scm_is_null (lra))
c209c88e
GB
951 {
952 SCM prot, fill = SCM_SUBRF (proc) (SCM_UNDEFINED, SCM_UNDEFINED);
e11e83f3 953 if (SCM_I_INUMP(fill))
c209c88e
GB
954 {
955 prot = scm_array_prototype (ra0);
eb42e2f0 956 if (SCM_INEXACTP (prot))
d9a67fc4 957 fill = scm_from_double ((double) SCM_I_INUM (fill));
c209c88e
GB
958 }
959
960 scm_array_fill_x (ra0, fill);
961 }
962 else
0f2d19dd 963 {
c209c88e
GB
964 SCM tail, ra1 = SCM_CAR (lra);
965 SCM v0 = (SCM_ARRAYP (ra0) ? SCM_ARRAY_V (ra0) : ra0);
0f2d19dd 966 ra_iproc *p;
c209c88e
GB
967 /* Check to see if order might matter.
968 This might be an argument for a separate
969 SERIAL-ARRAY-MAP! */
bc36d050
MV
970 if (scm_is_eq (v0, ra1)
971 || (SCM_ARRAYP (ra1) && scm_is_eq (v0, SCM_ARRAY_V (ra1))))
972 if (!scm_is_eq (ra0, ra1)
fee7ef83 973 || (SCM_ARRAYP(ra0) && !SCM_ARRAY_CONTP(ra0)))
c209c88e 974 goto gencase;
d2e53ed6 975 for (tail = SCM_CDR (lra); !scm_is_null (tail); tail = SCM_CDR (tail))
c209c88e
GB
976 {
977 ra1 = SCM_CAR (tail);
bc36d050
MV
978 if (scm_is_eq (v0, ra1)
979 || (SCM_ARRAYP (ra1) && scm_is_eq (v0, SCM_ARRAY_V (ra1))))
c209c88e
GB
980 goto gencase;
981 }
982 for (p = ra_asubrs; p->name; p++)
bc36d050 983 if (scm_is_eq (proc, p->sproc))
0f2d19dd 984 {
bc36d050 985 if (!scm_is_eq (ra0, SCM_CAR (lra)))
c209c88e
GB
986 scm_ramapc (scm_array_identity, SCM_UNDEFINED, ra0, scm_cons (SCM_CAR (lra), SCM_EOL), FUNC_NAME);
987 lra = SCM_CDR (lra);
988 while (1)
0f2d19dd 989 {
c209c88e
GB
990 scm_ramapc (p->vproc, SCM_UNDEFINED, ra0, lra, FUNC_NAME);
991 if (SCM_IMP (lra) || SCM_IMP (SCM_CDR (lra)))
992 return SCM_UNSPECIFIED;
0f2d19dd
JB
993 lra = SCM_CDR (lra);
994 }
0f2d19dd 995 }
c209c88e
GB
996 scm_ramapc (ramap_2o, proc, ra0, lra, FUNC_NAME);
997 lra = SCM_CDR (lra);
998 if (SCM_NIMP (lra))
999 for (lra = SCM_CDR (lra); SCM_NIMP (lra); lra = SCM_CDR (lra))
1000 scm_ramapc (ramap_a, proc, ra0, lra, FUNC_NAME);
0f2d19dd 1001 }
c209c88e
GB
1002 return SCM_UNSPECIFIED;
1003 }
0f2d19dd 1004}
1bbd0b84 1005#undef FUNC_NAME
0f2d19dd 1006
1cc91f1b 1007
0f2d19dd 1008static int
34d19ef6 1009rafe (SCM ra0, SCM proc, SCM ras)
0f2d19dd 1010{
c014a02e
ML
1011 long i = SCM_ARRAY_DIMS (ra0)->lbnd;
1012 unsigned long i0 = SCM_ARRAY_BASE (ra0);
1013 long inc0 = SCM_ARRAY_DIMS (ra0)->inc;
1014 long n = SCM_ARRAY_DIMS (ra0)->ubnd;
0f2d19dd 1015 ra0 = SCM_ARRAY_V (ra0);
d2e53ed6 1016 if (scm_is_null (ras))
c209c88e 1017 for (; i <= n; i++, i0 += inc0)
fdc28395 1018 scm_call_1 (proc, scm_cvref (ra0, i0, SCM_UNDEFINED));
0f2d19dd
JB
1019 else
1020 {
1021 SCM ra1 = SCM_CAR (ras);
34d19ef6
HWN
1022 SCM args;
1023 SCM const*ve = &ras;
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
JB
1030 else
1031 {
1032 ras = scm_vector (ras);
1033 ve = SCM_VELTS (ras);
1034 }
1035 for (; i <= n; i++, i0 += inc0, i1 += inc1)
1036 {
1037 args = SCM_EOL;
e11e83f3
MV
1038 for (k = scm_to_ulong (scm_uniform_vector_length (ras)); k--;)
1039 args = scm_cons (scm_uniform_vector_ref (ve[k], scm_from_long (i)), args);
0f2d19dd 1040 args = scm_cons2 (scm_cvref (ra0, i0, SCM_UNDEFINED), scm_cvref (ra1, i1, SCM_UNDEFINED), args);
fdc28395 1041 scm_apply_0 (proc, args);
0f2d19dd
JB
1042 }
1043 }
1044 return 1;
1045}
1046
1047
3b3b36dd 1048SCM_DEFINE (scm_array_for_each, "array-for-each", 2, 0, 1,
c209c88e 1049 (SCM proc, SCM ra0, SCM lra),
8f85c0c6 1050 "Apply @var{proc} to each tuple of elements of @var{array0} @dots{}\n"
b380b885 1051 "in row-major order. The value returned is unspecified.")
1bbd0b84 1052#define FUNC_NAME s_scm_array_for_each
0f2d19dd 1053{
34d19ef6 1054 SCM_VALIDATE_PROC (1, proc);
af45e3b0 1055 SCM_VALIDATE_REST_ARGUMENT (lra);
c209c88e 1056 scm_ramapc (rafe, proc, ra0, lra, FUNC_NAME);
0f2d19dd
JB
1057 return SCM_UNSPECIFIED;
1058}
1bbd0b84 1059#undef FUNC_NAME
0f2d19dd 1060
3b3b36dd 1061SCM_DEFINE (scm_array_index_map_x, "array-index-map!", 2, 0, 0,
c209c88e 1062 (SCM ra, SCM proc),
8f85c0c6 1063 "Apply @var{proc} to the indices of each element of @var{array} in\n"
b380b885
MD
1064 "turn, storing the result in the corresponding element. The value\n"
1065 "returned and the order of application are unspecified.\n\n"
1066 "One can implement @var{array-indexes} as\n"
1e6808ea 1067 "@lisp\n"
b380b885
MD
1068 "(define (array-indexes array)\n"
1069 " (let ((ra (apply make-array #f (array-shape array))))\n"
1070 " (array-index-map! ra (lambda x x))\n"
1071 " ra))\n"
1e6808ea 1072 "@end lisp\n"
b380b885 1073 "Another example:\n"
1e6808ea 1074 "@lisp\n"
b380b885
MD
1075 "(define (apl:index-generator n)\n"
1076 " (let ((v (make-uniform-vector n 1)))\n"
1077 " (array-index-map! v (lambda (i) i))\n"
1078 " v))\n"
1e6808ea 1079 "@end lisp")
1bbd0b84 1080#define FUNC_NAME s_scm_array_index_map_x
0f2d19dd 1081{
c014a02e 1082 unsigned long i;
34d19ef6 1083 SCM_VALIDATE_PROC (2, proc);
399aba0a
MV
1084
1085 if (scm_is_generalized_vector (ra))
e42c09cc 1086 {
399aba0a
MV
1087 size_t length = scm_c_generalized_vector_length (ra);
1088 for (i = 0; i < length; i++)
1089 scm_c_generalized_vector_set_x (ra, i,
1090 scm_call_1 (proc, scm_from_ulong (i)));
1091 return SCM_UNSPECIFIED;
1092 }
1093 else if (SCM_ARRAYP (ra))
1094 {
1095 SCM args = SCM_EOL;
1096 SCM inds = scm_make_uve (SCM_ARRAY_NDIM (ra), scm_from_int (-1));
1097 long *vinds = (long *) SCM_VELTS (inds);
1098 int j, k, kmax = SCM_ARRAY_NDIM (ra) - 1;
1099 if (kmax < 0)
1100 return scm_array_set_x (ra, scm_call_0 (proc), SCM_EOL);
1101 for (k = 0; k <= kmax; k++)
1102 vinds[k] = SCM_ARRAY_DIMS (ra)[k].lbnd;
1103 k = kmax;
1104 do
1105 {
1106 if (k == kmax)
1107 {
1108 vinds[k] = SCM_ARRAY_DIMS (ra)[k].lbnd;
1109 i = cind (ra, inds);
1110 for (; vinds[k] <= SCM_ARRAY_DIMS (ra)[k].ubnd; vinds[k]++)
1111 {
1112 for (j = kmax + 1, args = SCM_EOL; j--;)
1113 args = scm_cons (scm_from_long (vinds[j]), args);
1114 scm_array_set_x (SCM_ARRAY_V (ra),
1115 scm_apply_0 (proc, args),
1116 scm_from_ulong (i));
1117 i += SCM_ARRAY_DIMS (ra)[k].inc;
1118 }
1119 k--;
1120 continue;
1121 }
1122 if (vinds[k] < SCM_ARRAY_DIMS (ra)[k].ubnd)
1123 {
1124 vinds[k]++;
1125 k++;
1126 continue;
1127 }
1128 vinds[k] = SCM_ARRAY_DIMS (ra)[k].lbnd - 1;
1129 k--;
1130 }
1131 while (k >= 0);
1132 return SCM_UNSPECIFIED;
e42c09cc 1133 }
399aba0a
MV
1134 else
1135 scm_wrong_type_arg_msg (NULL, 0, ra, "array");
0f2d19dd 1136}
1bbd0b84 1137#undef FUNC_NAME
0f2d19dd 1138
1cc91f1b 1139
0f2d19dd 1140static int
34d19ef6 1141raeql_1 (SCM ra0, SCM as_equal, SCM ra1)
0f2d19dd
JB
1142{
1143 SCM e0 = SCM_UNDEFINED, e1 = SCM_UNDEFINED;
c014a02e
ML
1144 unsigned long i0 = 0, i1 = 0;
1145 long inc0 = 1, inc1 = 1;
1146 unsigned long n;
0f2d19dd 1147 ra1 = SCM_CAR (ra1);
ff467021 1148 if (SCM_ARRAYP(ra0))
c209c88e
GB
1149 {
1150 n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
1151 i0 = SCM_ARRAY_BASE (ra0);
1152 inc0 = SCM_ARRAY_DIMS (ra0)->inc;
1153 ra0 = SCM_ARRAY_V (ra0);
1154 }
e466c6a2 1155 else
399aba0a
MV
1156 n = scm_c_generalized_vector_length (ra0);
1157
ff467021 1158 if (SCM_ARRAYP (ra1))
c209c88e
GB
1159 {
1160 i1 = SCM_ARRAY_BASE (ra1);
1161 inc1 = SCM_ARRAY_DIMS (ra1)->inc;
1162 ra1 = SCM_ARRAY_V (ra1);
1163 }
399aba0a
MV
1164
1165 if (scm_is_generalized_vector (ra0))
c209c88e 1166 {
c209c88e
GB
1167 for (; n--; i0 += inc0, i1 += inc1)
1168 {
7888309b 1169 if (scm_is_false (as_equal))
c209c88e 1170 {
7888309b 1171 if (scm_is_false (scm_array_equal_p (RVREF (ra0, i0, e0), RVREF (ra1, i1, e1))))
c209c88e
GB
1172 return 0;
1173 }
7888309b 1174 else if (scm_is_false (scm_equal_p (RVREF (ra0, i0, e0), RVREF (ra1, i1, e1))))
c209c88e
GB
1175 return 0;
1176 }
1177 return 1;
c209c88e 1178 }
399aba0a
MV
1179 else
1180 return 0;
0f2d19dd
JB
1181}
1182
1183
1cc91f1b 1184
0f2d19dd 1185static int
34d19ef6 1186raeql (SCM ra0, SCM as_equal, SCM ra1)
0f2d19dd
JB
1187{
1188 SCM v0 = ra0, v1 = ra1;
92c2555f
MV
1189 scm_t_array_dim dim0, dim1;
1190 scm_t_array_dim *s0 = &dim0, *s1 = &dim1;
c014a02e 1191 unsigned long bas0 = 0, bas1 = 0;
0f2d19dd 1192 int k, unroll = 1, vlen = 1, ndim = 1;
ff467021 1193 if (SCM_ARRAYP (ra0))
c209c88e
GB
1194 {
1195 ndim = SCM_ARRAY_NDIM (ra0);
1196 s0 = SCM_ARRAY_DIMS (ra0);
1197 bas0 = SCM_ARRAY_BASE (ra0);
1198 v0 = SCM_ARRAY_V (ra0);
1199 }
0f2d19dd
JB
1200 else
1201 {
1202 s0->inc = 1;
1203 s0->lbnd = 0;
e11e83f3 1204 s0->ubnd = scm_to_long (scm_uniform_vector_length (v0)) - 1;
0f2d19dd
JB
1205 unroll = 0;
1206 }
ff467021 1207 if (SCM_ARRAYP (ra1))
c209c88e
GB
1208 {
1209 if (ndim != SCM_ARRAY_NDIM (ra1))
1210 return 0;
1211 s1 = SCM_ARRAY_DIMS (ra1);
1212 bas1 = SCM_ARRAY_BASE (ra1);
1213 v1 = SCM_ARRAY_V (ra1);
1214 }
0f2d19dd
JB
1215 else
1216 {
c209c88e
GB
1217 /*
1218 Huh ? Schizophrenic return type. --hwn
1219 */
0f2d19dd 1220 if (1 != ndim)
c209c88e 1221 return 0;
0f2d19dd
JB
1222 s1->inc = 1;
1223 s1->lbnd = 0;
e11e83f3 1224 s1->ubnd = scm_to_long (scm_uniform_vector_length (v1)) - 1;
0f2d19dd
JB
1225 unroll = 0;
1226 }
1227 if (SCM_TYP7 (v0) != SCM_TYP7 (v1))
1228 return 0;
1229 for (k = ndim; k--;)
1230 {
1231 if (s0[k].lbnd != s1[k].lbnd || s0[k].ubnd != s1[k].ubnd)
1232 return 0;
1233 if (unroll)
1234 {
1235 unroll = (s0[k].inc == s1[k].inc);
1236 vlen *= s0[k].ubnd - s1[k].lbnd + 1;
1237 }
1238 }
bc36d050 1239 if (unroll && bas0 == bas1 && scm_is_eq (v0, v1))
c209c88e 1240 return 1;
0f2d19dd
JB
1241 return scm_ramapc (raeql_1, as_equal, ra0, scm_cons (ra1, SCM_EOL), "");
1242}
1243
1cc91f1b 1244
0f2d19dd 1245SCM
1bbd0b84 1246scm_raequal (SCM ra0, SCM ra1)
0f2d19dd 1247{
7888309b 1248 return scm_from_bool(raeql (ra0, SCM_BOOL_T, ra1));
0f2d19dd
JB
1249}
1250
4079f87e 1251#if 0
c3ee7520
GB
1252/* GJB:FIXME:: Why not use SCM_DEFINE1 for array-equal? */
1253SCM_DEFINE1 (scm_array_equal_p, "array-equal?", scm_tc7_rpsubr,
c209c88e 1254 (SCM ra0, SCM ra1),
1e6808ea
MG
1255 "Return @code{#t} iff all arguments are arrays with the same\n"
1256 "shape, the same type, and have corresponding elements which are\n"
1257 "either @code{equal?} or @code{array-equal?}. This function\n"
1258 "differs from @code{equal?} in that a one dimensional shared\n"
1259 "array may be @var{array-equal?} but not @var{equal?} to a\n"
1260 "vector or uniform vector.")
4079f87e 1261#define FUNC_NAME s_scm_array_equal_p
0f981281
GB
1262{
1263}
4079f87e
GB
1264#undef FUNC_NAME
1265#endif
1266
0f2d19dd
JB
1267static char s_array_equal_p[] = "array-equal?";
1268
1cc91f1b 1269
0f2d19dd 1270SCM
1bbd0b84 1271scm_array_equal_p (SCM ra0, SCM ra1)
0f2d19dd 1272{
399aba0a
MV
1273 if (SCM_ARRAYP (ra0) || SCM_ARRAYP (ra1))
1274 return scm_from_bool(raeql (ra0, SCM_BOOL_F, ra1));
1275 return scm_equal_p (ra0, ra1);
0f2d19dd
JB
1276}
1277
1278
1cc91f1b 1279static void
1bbd0b84 1280init_raprocs (ra_iproc *subra)
0f2d19dd
JB
1281{
1282 for (; subra->name; subra++)
86d31dfe 1283 {
cc95e00a 1284 SCM sym = scm_from_locale_symbol (subra->name);
86d31dfe
MV
1285 SCM var =
1286 scm_sym2var (sym, scm_current_module_lookup_closure (), SCM_BOOL_F);
1287 if (var != SCM_BOOL_F)
1288 subra->sproc = SCM_VARIABLE_REF (var);
1289 else
1290 subra->sproc = SCM_BOOL_F;
1291 }
0f2d19dd
JB
1292}
1293
1cc91f1b 1294
0f2d19dd
JB
1295void
1296scm_init_ramap ()
0f2d19dd
JB
1297{
1298 init_raprocs (ra_rpsubrs);
1299 init_raprocs (ra_asubrs);
9a441ddb 1300 scm_c_define_subr (s_array_equal_p, scm_tc7_rpsubr, scm_array_equal_p);
7a7f7c53 1301 scm_smobs[SCM_TC2SMOBNUM (scm_tc16_array)].equalp = scm_raequal;
a0599745 1302#include "libguile/ramap.x"
1bbd0b84 1303 scm_add_feature (s_scm_array_for_each);
0f2d19dd 1304}
89e00824
ML
1305
1306/*
1307 Local Variables:
1308 c-file-style: "gnu"
1309 End:
1310*/