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