1
/* Copyright (C) 1996,1998,2000,2001,2004,2005, 2006 Free Software Foundation, Inc.
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.
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.
13
* You should have received a copy of the GNU Lesser General Public
14
* License along with this library; if not, write to the Free Software
15
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
Someone should rename this to arraymap.c; that would reflect the
28
#include "libguile/_scm.h"
29
#include "libguile/strings.h"
30
#include "libguile/unif.h"
31
#include "libguile/smob.h"
32
#include "libguile/chars.h"
33
#include "libguile/eq.h"
34
#include "libguile/eval.h"
35
#include "libguile/feature.h"
36
#include "libguile/root.h"
37
#include "libguile/vectors.h"
38
#include "libguile/srfi-4.h"
39
#include "libguile/dynwind.h"
41
#include "libguile/validate.h"
42
#include "libguile/ramap.h"
53
/* These tables are a kluge that will not scale well when more
54
* vectorized subrs are added. It is tempting to steal some bits from
55
* the SCM_CAR of all subrs (like those selected by SCM_SMOBNUM) to hold an
56
* offset into a table of vectorized subrs.
59
static ra_iproc ra_rpsubrs[] =
61
{"=", SCM_UNDEFINED, scm_ra_eqp},
62
{"<", SCM_UNDEFINED, scm_ra_lessp},
63
{"<=", SCM_UNDEFINED, scm_ra_leqp},
64
{">", SCM_UNDEFINED, scm_ra_grp},
65
{">=", SCM_UNDEFINED, scm_ra_greqp},
69
static ra_iproc ra_asubrs[] =
71
{"+", SCM_UNDEFINED, scm_ra_sum},
72
{"-", SCM_UNDEFINED, scm_ra_difference},
73
{"*", SCM_UNDEFINED, scm_ra_product},
74
{"/", SCM_UNDEFINED, scm_ra_divide},
79
#define GVREF scm_c_generalized_vector_ref
80
#define GVSET scm_c_generalized_vector_set_x
83
cind (SCM ra, long *ve)
87
if (!SCM_I_ARRAYP (ra))
89
i = SCM_I_ARRAY_BASE (ra);
90
for (k = 0; k < SCM_I_ARRAY_NDIM (ra); k++)
91
i += (ve[k] - SCM_I_ARRAY_DIMS (ra)[k].lbnd) * SCM_I_ARRAY_DIMS (ra)[k].inc;
96
/* Checker for scm_array mapping functions:
97
return values: 4 --> shapes, increments, and bases are the same;
98
3 --> shapes and increments are the same;
99
2 --> shapes are the same;
100
1 --> ras are at least as big as ra0;
105
scm_ra_matchp (SCM ra0, SCM ras)
108
scm_t_array_dim dims;
109
scm_t_array_dim *s0 = &dims;
111
unsigned long bas0 = 0;
113
int exact = 2 /* 4 */ ; /* Don't care about values >2 (yet?) */
115
if (scm_is_generalized_vector (ra0))
119
s0->ubnd = scm_c_generalized_vector_length (ra0) - 1;
121
else if (SCM_I_ARRAYP (ra0))
123
ndim = SCM_I_ARRAY_NDIM (ra0);
124
s0 = SCM_I_ARRAY_DIMS (ra0);
125
bas0 = SCM_I_ARRAY_BASE (ra0);
130
while (SCM_NIMP (ras))
134
if (scm_is_generalized_vector (ra1))
141
length = scm_c_generalized_vector_length (ra1);
152
if ((0 == s0->lbnd) && (s0->ubnd == length - 1))
156
if (s0->lbnd < 0 || s0->ubnd >= length)
160
else if (SCM_I_ARRAYP (ra1) && ndim == SCM_I_ARRAY_NDIM (ra1))
162
s1 = SCM_I_ARRAY_DIMS (ra1);
163
if (bas0 != SCM_I_ARRAY_BASE (ra1))
165
for (i = 0; i < ndim; i++)
170
if (s0[i].inc != s1[i].inc)
173
if (s0[i].lbnd == s1[i].lbnd && s0[i].ubnd == s1[i].ubnd)
177
if (s0[i].lbnd < s1[i].lbnd || s0[i].ubnd > s1[i].ubnd)
178
return (s0[i].lbnd <= s0[i].ubnd ? 0 : 1);
190
/* array mapper: apply cproc to each dimension of the given arrays?.
191
int (*cproc) (); procedure to call on unrolled arrays?
192
cproc (dest, source list) or
193
cproc (dest, data, source list).
194
SCM data; data to give to cproc or unbound.
195
SCM ra0; destination array.
196
SCM lra; list of source arrays.
197
const char *what; caller, for error reporting. */
199
scm_ramapc (int (*cproc)(), SCM data, SCM ra0, SCM lra, const char *what)
206
switch (scm_ra_matchp (ra0, lra))
210
scm_misc_error (what, "array shape mismatch: ~S", scm_list_1 (ra0));
213
case 4: /* Try unrolling arrays */
214
kmax = (SCM_I_ARRAYP (ra0) ? SCM_I_ARRAY_NDIM (ra0) - 1 : 0);
217
vra0 = scm_array_contents (ra0, SCM_UNDEFINED);
218
if (SCM_IMP (vra0)) goto gencase;
219
if (!SCM_I_ARRAYP (vra0))
221
size_t length = scm_c_generalized_vector_length (vra0);
222
vra1 = scm_i_make_ra (1, 0);
223
SCM_I_ARRAY_BASE (vra1) = 0;
224
SCM_I_ARRAY_DIMS (vra1)->lbnd = 0;
225
SCM_I_ARRAY_DIMS (vra1)->ubnd = length - 1;
226
SCM_I_ARRAY_DIMS (vra1)->inc = 1;
227
SCM_I_ARRAY_V (vra1) = vra0;
232
for (z = lra; SCM_NIMP (z); z = SCM_CDR (z))
235
vra1 = scm_i_make_ra (1, 0);
236
SCM_I_ARRAY_DIMS (vra1)->lbnd = SCM_I_ARRAY_DIMS (vra0)->lbnd;
237
SCM_I_ARRAY_DIMS (vra1)->ubnd = SCM_I_ARRAY_DIMS (vra0)->ubnd;
238
if (!SCM_I_ARRAYP (ra1))
240
SCM_I_ARRAY_BASE (vra1) = 0;
241
SCM_I_ARRAY_DIMS (vra1)->inc = 1;
242
SCM_I_ARRAY_V (vra1) = ra1;
244
else if (!SCM_I_ARRAY_CONTP (ra1))
248
SCM_I_ARRAY_BASE (vra1) = SCM_I_ARRAY_BASE (ra1);
249
SCM_I_ARRAY_DIMS (vra1)->inc = SCM_I_ARRAY_DIMS (ra1)[kmax].inc;
250
SCM_I_ARRAY_V (vra1) = SCM_I_ARRAY_V (ra1);
252
*plvra = scm_cons (vra1, SCM_EOL);
253
plvra = SCM_CDRLOC (*plvra);
255
return (SCM_UNBNDP (data) ? cproc(vra0, lvra) : cproc(vra0, data, lvra));
257
gencase: /* Have to loop over all dimensions. */
258
vra0 = scm_i_make_ra (1, 0);
259
if (SCM_I_ARRAYP (ra0))
261
kmax = SCM_I_ARRAY_NDIM (ra0) - 1;
264
SCM_I_ARRAY_DIMS (vra0)->lbnd = 0;
265
SCM_I_ARRAY_DIMS (vra0)->ubnd = 0;
266
SCM_I_ARRAY_DIMS (vra0)->inc = 1;
270
SCM_I_ARRAY_DIMS (vra0)->lbnd = SCM_I_ARRAY_DIMS (ra0)[kmax].lbnd;
271
SCM_I_ARRAY_DIMS (vra0)->ubnd = SCM_I_ARRAY_DIMS (ra0)[kmax].ubnd;
272
SCM_I_ARRAY_DIMS (vra0)->inc = SCM_I_ARRAY_DIMS (ra0)[kmax].inc;
274
SCM_I_ARRAY_BASE (vra0) = SCM_I_ARRAY_BASE (ra0);
275
SCM_I_ARRAY_V (vra0) = SCM_I_ARRAY_V (ra0);
279
size_t length = scm_c_generalized_vector_length (ra0);
281
SCM_I_ARRAY_DIMS (vra0)->lbnd = 0;
282
SCM_I_ARRAY_DIMS (vra0)->ubnd = length - 1;
283
SCM_I_ARRAY_DIMS (vra0)->inc = 1;
284
SCM_I_ARRAY_BASE (vra0) = 0;
285
SCM_I_ARRAY_V (vra0) = ra0;
290
for (z = lra; SCM_NIMP (z); z = SCM_CDR (z))
293
vra1 = scm_i_make_ra (1, 0);
294
SCM_I_ARRAY_DIMS (vra1)->lbnd = SCM_I_ARRAY_DIMS (vra0)->lbnd;
295
SCM_I_ARRAY_DIMS (vra1)->ubnd = SCM_I_ARRAY_DIMS (vra0)->ubnd;
296
if (SCM_I_ARRAYP (ra1))
299
SCM_I_ARRAY_DIMS (vra1)->inc = SCM_I_ARRAY_DIMS (ra1)[kmax].inc;
300
SCM_I_ARRAY_V (vra1) = SCM_I_ARRAY_V (ra1);
304
SCM_I_ARRAY_DIMS (vra1)->inc = 1;
305
SCM_I_ARRAY_V (vra1) = ra1;
307
*plvra = scm_cons (vra1, SCM_EOL);
308
plvra = SCM_CDRLOC (*plvra);
311
scm_dynwind_begin (0);
313
vinds = scm_malloc (sizeof(long) * SCM_I_ARRAY_NDIM (ra0));
314
scm_dynwind_free (vinds);
316
for (k = 0; k <= kmax; k++)
317
vinds[k] = SCM_I_ARRAY_DIMS (ra0)[k].lbnd;
324
SCM_I_ARRAY_BASE (vra0) = cind (ra0, vinds);
325
for (z = lvra; SCM_NIMP (z); z = SCM_CDR (z), y = SCM_CDR (y))
326
SCM_I_ARRAY_BASE (SCM_CAR (z)) = cind (SCM_CAR (y), vinds);
327
if (0 == (SCM_UNBNDP (data) ? cproc(vra0, lvra) : cproc(vra0, data, lvra)))
332
if (vinds[k] < SCM_I_ARRAY_DIMS (ra0)[k].ubnd)
338
vinds[k] = SCM_I_ARRAY_DIMS (ra0)[k].lbnd - 1;
349
SCM_DEFINE (scm_array_fill_x, "array-fill!", 2, 0, 0,
351
"Store @var{fill} in every element of @var{array}. The value returned\n"
353
#define FUNC_NAME s_scm_array_fill_x
355
scm_ramapc (scm_array_fill_int, fill, ra, SCM_EOL, FUNC_NAME);
356
return SCM_UNSPECIFIED;
360
/* to be used as cproc in scm_ramapc to fill an array dimension with
363
scm_array_fill_int (SCM ra, SCM fill, SCM ignore SCM_UNUSED)
364
#define FUNC_NAME s_scm_array_fill_x
367
unsigned long n = SCM_I_ARRAY_DIMS (ra)->ubnd - SCM_I_ARRAY_DIMS (ra)->lbnd + 1;
368
long inc = SCM_I_ARRAY_DIMS (ra)->inc;
369
unsigned long base = SCM_I_ARRAY_BASE (ra);
371
ra = SCM_I_ARRAY_V (ra);
373
for (i = base; n--; i += inc)
383
racp (SCM src, SCM dst)
385
long n = (SCM_I_ARRAY_DIMS (src)->ubnd - SCM_I_ARRAY_DIMS (src)->lbnd + 1);
386
long inc_d, inc_s = SCM_I_ARRAY_DIMS (src)->inc;
387
unsigned long i_d, i_s = SCM_I_ARRAY_BASE (src);
389
inc_d = SCM_I_ARRAY_DIMS (dst)->inc;
390
i_d = SCM_I_ARRAY_BASE (dst);
391
src = SCM_I_ARRAY_V (src);
392
dst = SCM_I_ARRAY_V (dst);
394
for (; n-- > 0; i_s += inc_s, i_d += inc_d)
395
GVSET (dst, i_d, GVREF (src, i_s));
399
SCM_REGISTER_PROC(s_array_copy_in_order_x, "array-copy-in-order!", 2, 0, 0, scm_array_copy_x);
402
SCM_DEFINE (scm_array_copy_x, "array-copy!", 2, 0, 0,
404
"@deffnx {Scheme Procedure} array-copy-in-order! src dst\n"
405
"Copy every element from vector or array @var{source} to the\n"
406
"corresponding element of @var{destination}. @var{destination} must have\n"
407
"the same rank as @var{source}, and be at least as large in each\n"
408
"dimension. The order is unspecified.")
409
#define FUNC_NAME s_scm_array_copy_x
411
scm_ramapc (racp, SCM_UNDEFINED, src, scm_cons (dst, SCM_EOL), FUNC_NAME);
412
return SCM_UNSPECIFIED;
416
/* Functions callable by ARRAY-MAP! */
420
scm_ra_eqp (SCM ra0, SCM ras)
422
SCM ra1 = SCM_CAR (ras), ra2 = SCM_CAR (SCM_CDR (ras));
423
scm_t_array_handle ra0_handle;
424
scm_t_array_dim *ra0_dims;
428
unsigned long i1 = SCM_I_ARRAY_BASE (ra1), i2 = SCM_I_ARRAY_BASE (ra2);
429
long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
430
long inc2 = SCM_I_ARRAY_DIMS (ra1)->inc;
431
ra1 = SCM_I_ARRAY_V (ra1);
432
ra2 = SCM_I_ARRAY_V (ra2);
434
scm_array_get_handle (ra0, &ra0_handle);
435
ra0_dims = scm_array_handle_dims (&ra0_handle);
436
n = ra0_dims[0].ubnd - ra0_dims[0].lbnd + 1;
437
inc0 = ra0_dims[0].inc;
440
for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
441
if (scm_is_true (scm_array_handle_ref (&ra0_handle, i0)))
442
if (!scm_is_eq (GVREF (ra1, i1), GVREF (ra2, i2)))
443
scm_array_handle_set (&ra0_handle, i0, SCM_BOOL_F);
446
scm_array_handle_release (&ra0_handle);
450
/* opt 0 means <, nonzero means >= */
453
ra_compare (SCM ra0, SCM ra1, SCM ra2, int opt)
455
scm_t_array_handle ra0_handle;
456
scm_t_array_dim *ra0_dims;
460
unsigned long i1 = SCM_I_ARRAY_BASE (ra1), i2 = SCM_I_ARRAY_BASE (ra2);
461
long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
462
long inc2 = SCM_I_ARRAY_DIMS (ra1)->inc;
463
ra1 = SCM_I_ARRAY_V (ra1);
464
ra2 = SCM_I_ARRAY_V (ra2);
466
scm_array_get_handle (ra0, &ra0_handle);
467
ra0_dims = scm_array_handle_dims (&ra0_handle);
468
n = ra0_dims[0].ubnd - ra0_dims[0].lbnd + 1;
469
inc0 = ra0_dims[0].inc;
472
for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
473
if (scm_is_true (scm_array_handle_ref (&ra0_handle, i0)))
475
scm_is_true (scm_less_p (GVREF (ra1, i1), GVREF (ra2, i2))) :
476
scm_is_false (scm_less_p (GVREF (ra1, i1), GVREF (ra2, i2))))
477
scm_array_handle_set (&ra0_handle, i0, SCM_BOOL_F);
480
scm_array_handle_release (&ra0_handle);
487
scm_ra_lessp (SCM ra0, SCM ras)
489
return ra_compare (ra0, SCM_CAR (ras), SCM_CAR (SCM_CDR (ras)), 0);
494
scm_ra_leqp (SCM ra0, SCM ras)
496
return ra_compare (ra0, SCM_CAR (SCM_CDR (ras)), SCM_CAR (ras), 1);
501
scm_ra_grp (SCM ra0, SCM ras)
503
return ra_compare (ra0, SCM_CAR (SCM_CDR (ras)), SCM_CAR (ras), 0);
508
scm_ra_greqp (SCM ra0, SCM ras)
510
return ra_compare (ra0, SCM_CAR (ras), SCM_CAR (SCM_CDR (ras)), 1);
515
scm_ra_sum (SCM ra0, SCM ras)
517
long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
518
unsigned long i0 = SCM_I_ARRAY_BASE (ra0);
519
long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
520
ra0 = SCM_I_ARRAY_V (ra0);
521
if (!scm_is_null(ras))
523
SCM ra1 = SCM_CAR (ras);
524
unsigned long i1 = SCM_I_ARRAY_BASE (ra1);
525
long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
526
ra1 = SCM_I_ARRAY_V (ra1);
527
switch (SCM_TYP7 (ra0) == SCM_TYP7 (ra1) ? SCM_TYP7 (ra0) : 0)
531
for (; n-- > 0; i0 += inc0, i1 += inc1)
532
GVSET (ra0, i0, scm_sum (GVREF(ra0, i0), GVREF(ra1, i1)));
543
scm_ra_difference (SCM ra0, SCM ras)
545
long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
546
unsigned long i0 = SCM_I_ARRAY_BASE (ra0);
547
long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
548
ra0 = SCM_I_ARRAY_V (ra0);
549
if (scm_is_null (ras))
551
switch (SCM_TYP7 (ra0))
555
for (; n-- > 0; i0 += inc0)
556
GVSET (ra0, i0, scm_difference (GVREF(ra0, i0), SCM_UNDEFINED));
563
SCM ra1 = SCM_CAR (ras);
564
unsigned long i1 = SCM_I_ARRAY_BASE (ra1);
565
long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
566
ra1 = SCM_I_ARRAY_V (ra1);
567
switch (SCM_TYP7 (ra0) == SCM_TYP7 (ra1) ? SCM_TYP7 (ra0) : 0)
571
for (; n-- > 0; i0 += inc0, i1 += inc1)
572
GVSET (ra0, i0, scm_difference (GVREF (ra0, i0),
584
scm_ra_product (SCM ra0, SCM ras)
586
long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
587
unsigned long i0 = SCM_I_ARRAY_BASE (ra0);
588
long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
589
ra0 = SCM_I_ARRAY_V (ra0);
590
if (!scm_is_null (ras))
592
SCM ra1 = SCM_CAR (ras);
593
unsigned long i1 = SCM_I_ARRAY_BASE (ra1);
594
long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
595
ra1 = SCM_I_ARRAY_V (ra1);
596
switch (SCM_TYP7 (ra0) == SCM_TYP7 (ra1) ? SCM_TYP7 (ra0) : 0)
600
for (; n-- > 0; i0 += inc0, i1 += inc1)
601
GVSET (ra0, i0, scm_product (GVREF (ra0, i0),
611
scm_ra_divide (SCM ra0, SCM ras)
613
long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
614
unsigned long i0 = SCM_I_ARRAY_BASE (ra0);
615
long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
616
ra0 = SCM_I_ARRAY_V (ra0);
617
if (scm_is_null (ras))
619
switch (SCM_TYP7 (ra0))
623
for (; n-- > 0; i0 += inc0)
624
GVSET (ra0, i0, scm_divide (GVREF (ra0, i0), SCM_UNDEFINED));
631
SCM ra1 = SCM_CAR (ras);
632
unsigned long i1 = SCM_I_ARRAY_BASE (ra1);
633
long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
634
ra1 = SCM_I_ARRAY_V (ra1);
635
switch (SCM_TYP7 (ra0) == SCM_TYP7 (ra1) ? SCM_TYP7 (ra0) : 0)
639
for (; n-- > 0; i0 += inc0, i1 += inc1)
641
SCM res = scm_divide (GVREF (ra0, i0),
643
GVSET (ra0, i0, res);
654
scm_array_identity (SCM dst, SCM src)
656
return racp (SCM_CAR (src), scm_cons (dst, SCM_EOL));
662
ramap (SCM ra0, SCM proc, SCM ras)
664
long i = SCM_I_ARRAY_DIMS (ra0)->lbnd;
665
long inc = SCM_I_ARRAY_DIMS (ra0)->inc;
666
long n = SCM_I_ARRAY_DIMS (ra0)->ubnd;
667
long base = SCM_I_ARRAY_BASE (ra0) - i * inc;
668
ra0 = SCM_I_ARRAY_V (ra0);
669
if (scm_is_null (ras))
671
GVSET (ra0, i*inc+base, scm_call_0 (proc));
674
SCM ra1 = SCM_CAR (ras);
676
unsigned long k, i1 = SCM_I_ARRAY_BASE (ra1);
677
long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
678
ra1 = SCM_I_ARRAY_V (ra1);
680
if (scm_is_null(ras))
683
ras = scm_vector (ras);
685
for (; i <= n; i++, i1 += inc1)
688
for (k = scm_c_vector_length (ras); k--;)
689
args = scm_cons (GVREF (scm_c_vector_ref (ras, k), i), args);
690
args = scm_cons (GVREF (ra1, i1), args);
691
GVSET (ra0, i*inc+base, scm_apply_0 (proc, args));
699
ramap_dsubr (SCM ra0, SCM proc, SCM ras)
701
SCM ra1 = SCM_CAR (ras);
702
unsigned long i0 = SCM_I_ARRAY_BASE (ra0), i1 = SCM_I_ARRAY_BASE (ra1);
703
long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc, inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
704
long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra1)->lbnd + 1;
705
ra0 = SCM_I_ARRAY_V (ra0);
706
ra1 = SCM_I_ARRAY_V (ra1);
707
switch (SCM_TYP7 (ra0))
710
for (; n-- > 0; i0 += inc0, i1 += inc1)
711
GVSET (ra0, i0, scm_call_1 (proc, GVREF (ra1, i1)));
720
ramap_rp (SCM ra0, SCM proc, SCM ras)
722
SCM ra1 = SCM_CAR (ras), ra2 = SCM_CAR (SCM_CDR (ras));
723
long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
724
unsigned long i0 = SCM_I_ARRAY_BASE (ra0), i1 = SCM_I_ARRAY_BASE (ra1), i2 = SCM_I_ARRAY_BASE (ra2);
725
long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
726
long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
727
long inc2 = SCM_I_ARRAY_DIMS (ra1)->inc;
728
ra0 = SCM_I_ARRAY_V (ra0);
729
ra1 = SCM_I_ARRAY_V (ra1);
730
ra2 = SCM_I_ARRAY_V (ra2);
732
for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
733
if (scm_is_true (scm_c_bitvector_ref (ra0, i0)))
734
if (scm_is_false (SCM_SUBRF (proc) (GVREF (ra1, i1), GVREF (ra2, i2))))
735
scm_c_bitvector_set_x (ra0, i0, SCM_BOOL_F);
743
ramap_1 (SCM ra0, SCM proc, SCM ras)
745
SCM ra1 = SCM_CAR (ras);
746
long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
747
unsigned long i0 = SCM_I_ARRAY_BASE (ra0), i1 = SCM_I_ARRAY_BASE (ra1);
748
long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc, inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
749
ra0 = SCM_I_ARRAY_V (ra0);
750
ra1 = SCM_I_ARRAY_V (ra1);
751
if (scm_tc7_vector == SCM_TYP7 (ra0) || scm_tc7_wvect == SCM_TYP7 (ra0))
752
for (; n-- > 0; i0 += inc0, i1 += inc1)
753
GVSET (ra0, i0, SCM_SUBRF (proc) (GVREF (ra1, i1)));
755
for (; n-- > 0; i0 += inc0, i1 += inc1)
756
GVSET (ra0, i0, SCM_SUBRF (proc) (GVREF (ra1, i1)));
763
ramap_2o (SCM ra0, SCM proc, SCM ras)
765
SCM ra1 = SCM_CAR (ras);
766
long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
767
unsigned long i0 = SCM_I_ARRAY_BASE (ra0), i1 = SCM_I_ARRAY_BASE (ra1);
768
long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc, inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
769
ra0 = SCM_I_ARRAY_V (ra0);
770
ra1 = SCM_I_ARRAY_V (ra1);
772
if (scm_is_null (ras))
774
for (; n-- > 0; i0 += inc0, i1 += inc1)
775
GVSET (ra0, i0, SCM_SUBRF (proc) (GVREF (ra1, i1), SCM_UNDEFINED));
779
SCM ra2 = SCM_CAR (ras);
780
unsigned long i2 = SCM_I_ARRAY_BASE (ra2);
781
long inc2 = SCM_I_ARRAY_DIMS (ra2)->inc;
782
ra2 = SCM_I_ARRAY_V (ra2);
783
for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
784
GVSET (ra0, i0, SCM_SUBRF (proc) (GVREF (ra1, i1), GVREF (ra2, i2)));
792
ramap_a (SCM ra0, SCM proc, SCM ras)
794
long n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
795
unsigned long i0 = SCM_I_ARRAY_BASE (ra0);
796
long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
797
ra0 = SCM_I_ARRAY_V (ra0);
798
if (scm_is_null (ras))
799
for (; n-- > 0; i0 += inc0)
800
GVSET (ra0, i0, SCM_SUBRF (proc) (GVREF (ra0, i0), SCM_UNDEFINED));
803
SCM ra1 = SCM_CAR (ras);
804
unsigned long i1 = SCM_I_ARRAY_BASE (ra1);
805
long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
806
ra1 = SCM_I_ARRAY_V (ra1);
807
for (; n-- > 0; i0 += inc0, i1 += inc1)
808
GVSET (ra0, i0, SCM_SUBRF (proc) (GVREF (ra0, i0), GVREF (ra1, i1)));
814
SCM_REGISTER_PROC(s_array_map_in_order_x, "array-map-in-order!", 2, 0, 1, scm_array_map_x);
816
SCM_SYMBOL (sym_b, "b");
818
SCM_DEFINE (scm_array_map_x, "array-map!", 2, 0, 1,
819
(SCM ra0, SCM proc, SCM lra),
820
"@deffnx {Scheme Procedure} array-map-in-order! ra0 proc . lra\n"
821
"@var{array1}, @dots{} must have the same number of dimensions as\n"
822
"@var{array0} and have a range for each index which includes the range\n"
823
"for the corresponding index in @var{array0}. @var{proc} is applied to\n"
824
"each tuple of elements of @var{array1} @dots{} and the result is stored\n"
825
"as the corresponding element in @var{array0}. The value returned is\n"
826
"unspecified. The order of application is unspecified.")
827
#define FUNC_NAME s_scm_array_map_x
829
SCM_VALIDATE_PROC (2, proc);
830
SCM_VALIDATE_REST_ARGUMENT (lra);
832
switch (SCM_TYP7 (proc))
836
scm_ramapc (ramap, proc, ra0, lra, FUNC_NAME);
837
return SCM_UNSPECIFIED;
839
if (! scm_is_pair (lra))
840
SCM_WRONG_NUM_ARGS (); /* need 1 source */
841
scm_ramapc (ramap_1, proc, ra0, lra, FUNC_NAME);
842
return SCM_UNSPECIFIED;
844
if (! (scm_is_pair (lra) && scm_is_pair (SCM_CDR (lra))))
845
SCM_WRONG_NUM_ARGS (); /* need 2 sources */
847
case scm_tc7_subr_2o:
848
if (! scm_is_pair (lra))
849
SCM_WRONG_NUM_ARGS (); /* need 1 source */
851
scm_ramapc (ramap_2o, proc, ra0, lra, FUNC_NAME);
852
return SCM_UNSPECIFIED;
854
if (! scm_is_pair (lra))
855
SCM_WRONG_NUM_ARGS (); /* need 1 source */
856
scm_ramapc (ramap_dsubr, proc, ra0, lra, FUNC_NAME);
857
return SCM_UNSPECIFIED;
861
if (!scm_is_typed_array (ra0, sym_b))
863
scm_array_fill_x (ra0, SCM_BOOL_T);
864
for (p = ra_rpsubrs; p->name; p++)
865
if (scm_is_eq (proc, p->sproc))
867
while (!scm_is_null (lra) && !scm_is_null (SCM_CDR (lra)))
869
scm_ramapc (p->vproc, SCM_UNDEFINED, ra0, lra, FUNC_NAME);
872
return SCM_UNSPECIFIED;
874
while (!scm_is_null (lra) && !scm_is_null (SCM_CDR (lra)))
876
scm_ramapc (ramap_rp, proc, ra0, lra, FUNC_NAME);
879
return SCM_UNSPECIFIED;
882
if (scm_is_null (lra))
884
SCM fill = SCM_SUBRF (proc) (SCM_UNDEFINED, SCM_UNDEFINED);
885
scm_array_fill_x (ra0, fill);
889
SCM tail, ra1 = SCM_CAR (lra);
890
SCM v0 = (SCM_I_ARRAYP (ra0) ? SCM_I_ARRAY_V (ra0) : ra0);
892
/* Check to see if order might matter.
893
This might be an argument for a separate
895
if (scm_is_eq (v0, ra1)
896
|| (SCM_I_ARRAYP (ra1) && scm_is_eq (v0, SCM_I_ARRAY_V (ra1))))
897
if (!scm_is_eq (ra0, ra1)
898
|| (SCM_I_ARRAYP(ra0) && !SCM_I_ARRAY_CONTP(ra0)))
900
for (tail = SCM_CDR (lra); !scm_is_null (tail); tail = SCM_CDR (tail))
902
ra1 = SCM_CAR (tail);
903
if (scm_is_eq (v0, ra1)
904
|| (SCM_I_ARRAYP (ra1) && scm_is_eq (v0, SCM_I_ARRAY_V (ra1))))
907
for (p = ra_asubrs; p->name; p++)
908
if (scm_is_eq (proc, p->sproc))
910
if (!scm_is_eq (ra0, SCM_CAR (lra)))
911
scm_ramapc (scm_array_identity, SCM_UNDEFINED, ra0, scm_cons (SCM_CAR (lra), SCM_EOL), FUNC_NAME);
915
scm_ramapc (p->vproc, SCM_UNDEFINED, ra0, lra, FUNC_NAME);
916
if (SCM_IMP (lra) || SCM_IMP (SCM_CDR (lra)))
917
return SCM_UNSPECIFIED;
921
scm_ramapc (ramap_2o, proc, ra0, lra, FUNC_NAME);
924
for (lra = SCM_CDR (lra); SCM_NIMP (lra); lra = SCM_CDR (lra))
925
scm_ramapc (ramap_a, proc, ra0, lra, FUNC_NAME);
927
return SCM_UNSPECIFIED;
934
rafe (SCM ra0, SCM proc, SCM ras)
936
long i = SCM_I_ARRAY_DIMS (ra0)->lbnd;
937
unsigned long i0 = SCM_I_ARRAY_BASE (ra0);
938
long inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
939
long n = SCM_I_ARRAY_DIMS (ra0)->ubnd;
940
ra0 = SCM_I_ARRAY_V (ra0);
941
if (scm_is_null (ras))
942
for (; i <= n; i++, i0 += inc0)
943
scm_call_1 (proc, GVREF (ra0, i0));
946
SCM ra1 = SCM_CAR (ras);
948
unsigned long k, i1 = SCM_I_ARRAY_BASE (ra1);
949
long inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
950
ra1 = SCM_I_ARRAY_V (ra1);
952
if (scm_is_null(ras))
955
ras = scm_vector (ras);
956
for (; i <= n; i++, i0 += inc0, i1 += inc1)
959
for (k = scm_c_vector_length (ras); k--;)
960
args = scm_cons (GVREF (scm_c_vector_ref (ras, k), i), args);
961
args = scm_cons2 (GVREF (ra0, i0), GVREF (ra1, i1), args);
962
scm_apply_0 (proc, args);
969
SCM_DEFINE (scm_array_for_each, "array-for-each", 2, 0, 1,
970
(SCM proc, SCM ra0, SCM lra),
971
"Apply @var{proc} to each tuple of elements of @var{array0} @dots{}\n"
972
"in row-major order. The value returned is unspecified.")
973
#define FUNC_NAME s_scm_array_for_each
975
SCM_VALIDATE_PROC (1, proc);
976
SCM_VALIDATE_REST_ARGUMENT (lra);
977
scm_ramapc (rafe, proc, ra0, lra, FUNC_NAME);
978
return SCM_UNSPECIFIED;
982
SCM_DEFINE (scm_array_index_map_x, "array-index-map!", 2, 0, 0,
984
"Apply @var{proc} to the indices of each element of @var{array} in\n"
985
"turn, storing the result in the corresponding element. The value\n"
986
"returned and the order of application are unspecified.\n\n"
987
"One can implement @var{array-indexes} as\n"
989
"(define (array-indexes array)\n"
990
" (let ((ra (apply make-array #f (array-shape array))))\n"
991
" (array-index-map! ra (lambda x x))\n"
996
"(define (apl:index-generator n)\n"
997
" (let ((v (make-uniform-vector n 1)))\n"
998
" (array-index-map! v (lambda (i) i))\n"
1001
#define FUNC_NAME s_scm_array_index_map_x
1004
SCM_VALIDATE_PROC (2, proc);
1006
if (SCM_I_ARRAYP (ra))
1009
int j, k, kmax = SCM_I_ARRAY_NDIM (ra) - 1;
1013
return scm_array_set_x (ra, scm_call_0 (proc), SCM_EOL);
1015
scm_dynwind_begin (0);
1017
vinds = scm_malloc (sizeof(long) * SCM_I_ARRAY_NDIM (ra));
1018
scm_dynwind_free (vinds);
1020
for (k = 0; k <= kmax; k++)
1021
vinds[k] = SCM_I_ARRAY_DIMS (ra)[k].lbnd;
1027
vinds[k] = SCM_I_ARRAY_DIMS (ra)[k].lbnd;
1028
i = cind (ra, vinds);
1029
for (; vinds[k] <= SCM_I_ARRAY_DIMS (ra)[k].ubnd; vinds[k]++)
1031
for (j = kmax + 1, args = SCM_EOL; j--;)
1032
args = scm_cons (scm_from_long (vinds[j]), args);
1033
GVSET (SCM_I_ARRAY_V (ra), i, scm_apply_0 (proc, args));
1034
i += SCM_I_ARRAY_DIMS (ra)[k].inc;
1039
if (vinds[k] < SCM_I_ARRAY_DIMS (ra)[k].ubnd)
1045
vinds[k] = SCM_I_ARRAY_DIMS (ra)[k].lbnd - 1;
1051
return SCM_UNSPECIFIED;
1053
else if (scm_is_generalized_vector (ra))
1055
size_t length = scm_c_generalized_vector_length (ra);
1056
for (i = 0; i < length; i++)
1057
GVSET (ra, i, scm_call_1 (proc, scm_from_ulong (i)));
1058
return SCM_UNSPECIFIED;
1061
scm_wrong_type_arg_msg (NULL, 0, ra, "array");
1067
raeql_1 (SCM ra0, SCM as_equal, SCM ra1)
1069
unsigned long i0 = 0, i1 = 0;
1070
long inc0 = 1, inc1 = 1;
1072
ra1 = SCM_CAR (ra1);
1073
if (SCM_I_ARRAYP(ra0))
1075
n = SCM_I_ARRAY_DIMS (ra0)->ubnd - SCM_I_ARRAY_DIMS (ra0)->lbnd + 1;
1076
i0 = SCM_I_ARRAY_BASE (ra0);
1077
inc0 = SCM_I_ARRAY_DIMS (ra0)->inc;
1078
ra0 = SCM_I_ARRAY_V (ra0);
1081
n = scm_c_generalized_vector_length (ra0);
1083
if (SCM_I_ARRAYP (ra1))
1085
i1 = SCM_I_ARRAY_BASE (ra1);
1086
inc1 = SCM_I_ARRAY_DIMS (ra1)->inc;
1087
ra1 = SCM_I_ARRAY_V (ra1);
1090
if (scm_is_generalized_vector (ra0))
1092
for (; n--; i0 += inc0, i1 += inc1)
1094
if (scm_is_false (as_equal))
1096
if (scm_is_false (scm_array_equal_p (GVREF (ra0, i0), GVREF (ra1, i1))))
1099
else if (scm_is_false (scm_equal_p (GVREF (ra0, i0), GVREF (ra1, i1))))
1111
raeql (SCM ra0, SCM as_equal, SCM ra1)
1113
SCM v0 = ra0, v1 = ra1;
1114
scm_t_array_dim dim0, dim1;
1115
scm_t_array_dim *s0 = &dim0, *s1 = &dim1;
1116
unsigned long bas0 = 0, bas1 = 0;
1117
int k, unroll = 1, vlen = 1, ndim = 1;
1118
if (SCM_I_ARRAYP (ra0))
1120
ndim = SCM_I_ARRAY_NDIM (ra0);
1121
s0 = SCM_I_ARRAY_DIMS (ra0);
1122
bas0 = SCM_I_ARRAY_BASE (ra0);
1123
v0 = SCM_I_ARRAY_V (ra0);
1129
s0->ubnd = scm_c_generalized_vector_length (v0) - 1;
1132
if (SCM_I_ARRAYP (ra1))
1134
if (ndim != SCM_I_ARRAY_NDIM (ra1))
1136
s1 = SCM_I_ARRAY_DIMS (ra1);
1137
bas1 = SCM_I_ARRAY_BASE (ra1);
1138
v1 = SCM_I_ARRAY_V (ra1);
1143
Huh ? Schizophrenic return type. --hwn
1149
s1->ubnd = scm_c_generalized_vector_length (v1) - 1;
1152
if (SCM_TYP7 (v0) != SCM_TYP7 (v1))
1154
for (k = ndim; k--;)
1156
if (s0[k].lbnd != s1[k].lbnd || s0[k].ubnd != s1[k].ubnd)
1160
unroll = (s0[k].inc == s1[k].inc);
1161
vlen *= s0[k].ubnd - s1[k].lbnd + 1;
1164
if (unroll && bas0 == bas1 && scm_is_eq (v0, v1))
1166
return scm_ramapc (raeql_1, as_equal, ra0, scm_cons (ra1, SCM_EOL), "");
1171
scm_raequal (SCM ra0, SCM ra1)
1173
return scm_from_bool(raeql (ra0, SCM_BOOL_T, ra1));
1177
/* GJB:FIXME:: Why not use SCM_DEFINE1 for array-equal? */
1178
SCM_DEFINE1 (scm_array_equal_p, "array-equal?", scm_tc7_rpsubr,
1180
"Return @code{#t} iff all arguments are arrays with the same\n"
1181
"shape, the same type, and have corresponding elements which are\n"
1182
"either @code{equal?} or @code{array-equal?}. This function\n"
1183
"differs from @code{equal?} in that a one dimensional shared\n"
1184
"array may be @var{array-equal?} but not @var{equal?} to a\n"
1185
"vector or uniform vector.")
1186
#define FUNC_NAME s_scm_array_equal_p
1192
static char s_array_equal_p[] = "array-equal?";
1196
scm_array_equal_p (SCM ra0, SCM ra1)
1198
if (SCM_I_ARRAYP (ra0) || SCM_I_ARRAYP (ra1))
1199
return scm_from_bool(raeql (ra0, SCM_BOOL_F, ra1));
1200
return scm_equal_p (ra0, ra1);
1205
init_raprocs (ra_iproc *subra)
1207
for (; subra->name; subra++)
1209
SCM sym = scm_from_locale_symbol (subra->name);
1211
scm_sym2var (sym, scm_current_module_lookup_closure (), SCM_BOOL_F);
1212
if (var != SCM_BOOL_F)
1213
subra->sproc = SCM_VARIABLE_REF (var);
1215
subra->sproc = SCM_BOOL_F;
1223
init_raprocs (ra_rpsubrs);
1224
init_raprocs (ra_asubrs);
1225
scm_c_define_subr (s_array_equal_p, scm_tc7_rpsubr, scm_array_equal_p);
1226
scm_smobs[SCM_TC2SMOBNUM (scm_i_tc16_array)].equalp = scm_raequal;
1227
#include "libguile/ramap.x"
1228
scm_add_feature (s_scm_array_for_each);