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