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