* Makefile.am (DEFS): Added. automake adds -I options to DEFS,
[bpt/guile.git] / libguile / ramap.c
1 /* Copyright (C) 1996, 1998, 2000 Free Software Foundation, Inc.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
7 *
8 * This program 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
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
17 *
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
20 *
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
26 *
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
29 *
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
37 *
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
40 * If you do not wish that, delete this exception notice. */
41
42 /* Software engineering face-lift by Greg J. Badros, 11-Dec-1999,
43 gjb@cs.washington.edu, http://www.cs.washington.edu/homes/gjb */
44
45 /*
46 HWN:FIXME::
47 Someone should rename this to arraymap.c; that would reflect the
48 contents better. */
49 \f
50
51
52 \f
53
54 #include <stdio.h>
55 #include "libguile/_scm.h"
56 #include "libguile/unif.h"
57 #include "libguile/smob.h"
58 #include "libguile/chars.h"
59 #include "libguile/eq.h"
60 #include "libguile/eval.h"
61 #include "libguile/feature.h"
62 #include "libguile/root.h"
63 #include "libguile/vectors.h"
64
65 #include "libguile/validate.h"
66 #include "libguile/ramap.h"
67 \f
68
69 typedef struct
70 {
71 char *name;
72 SCM sproc;
73 int (*vproc) ();
74 } ra_iproc;
75
76
77 /* These tables are a kluge that will not scale well when more
78 * vectorized subrs are added. It is tempting to steal some bits from
79 * the SCM_CAR of all subrs (like those selected by SCM_SMOBNUM) to hold an
80 * offset into a table of vectorized subrs.
81 */
82
83 static ra_iproc ra_rpsubrs[] =
84 {
85 {"=", SCM_UNDEFINED, scm_ra_eqp},
86 {"<", SCM_UNDEFINED, scm_ra_lessp},
87 {"<=", SCM_UNDEFINED, scm_ra_leqp},
88 {">", SCM_UNDEFINED, scm_ra_grp},
89 {">=", SCM_UNDEFINED, scm_ra_greqp},
90 {0, 0, 0}
91 };
92
93 static ra_iproc ra_asubrs[] =
94 {
95 {"+", SCM_UNDEFINED, scm_ra_sum},
96 {"-", SCM_UNDEFINED, scm_ra_difference},
97 {"*", SCM_UNDEFINED, scm_ra_product},
98 {"/", SCM_UNDEFINED, scm_ra_divide},
99 {0, 0, 0}
100 };
101
102
103
104 /* Fast, recycling scm_vector ref */
105 #define RVREF(ra, i, e) (e = scm_cvref(ra, i, e))
106
107 /* #define RVREF(ra, i, e) (scm_cvref(ra, i, SCM_UNDEFINED)) to turn off */
108
109 /* IVDEP means "ignore scm_vector dependencies", meaning we guarantee that
110 elements of scm_vector operands are not aliased */
111 #ifdef _UNICOS
112 #define IVDEP(test, line) if (test) {_Pragma("ivdep"); line} else {line}
113 #else
114 #define IVDEP(test, line) line
115 #endif
116
117 \f
118
119 /* inds must be a uvect or ivect, no check. */
120
121
122
123 /*
124 Yes, this is really ugly, but it prevents multiple code
125 */
126 #define BINARY_ELTS_CODE(OPERATOR, type) \
127 do { type *v0 = (type*)SCM_VELTS (ra0);\
128 type *v1 = (type*)SCM_VELTS (ra1);\
129 IVDEP (ra0 != ra1, \
130 for (; n-- > 0; i0 += inc0, i1 += inc1) \
131 v0[i0] OPERATOR v1[i1];) \
132 break; \
133 } while (0)
134
135 /* This macro is used for all but binary division and
136 multiplication of complex numbers -- see the expanded
137 version in the functions later in this file */
138 #define BINARY_PAIR_ELTS_CODE(OPERATOR, type) \
139 do { type (*v0)[2] = (type (*)[2]) SCM_VELTS (ra0);\
140 type (*v1)[2] = (type (*)[2]) SCM_VELTS (ra1);\
141 IVDEP (ra0 != ra1, \
142 for (; n-- > 0; i0 += inc0, i1 += inc1) {\
143 v0[i0][0] OPERATOR v1[i1][0]; \
144 v0[i0][1] OPERATOR v1[i1][1]; \
145 }) \
146 break; \
147 } while (0)
148
149 #define UNARY_ELTS_CODE(OPERATOR, type) \
150 do { type *v0 = (type *) SCM_VELTS (ra0);\
151 for (; n-- > 0; i0 += inc0) \
152 v0[i0] OPERATOR v0[i0];\
153 break;\
154 } while (0)
155
156
157 /* This macro is used for all but unary divison
158 of complex numbers -- see the expanded version in the
159 function later in this file. */
160 #define UNARY_PAIR_ELTS_CODE(OPERATOR, type) \
161 do { type (*v0)[2] = (type (*)[2]) SCM_VELTS (ra0);\
162 for (; n-- > 0; i0 += inc0) {\
163 v0[i0][0] OPERATOR v0[i0][0];\
164 v0[i0][1] OPERATOR v0[i0][1];\
165 }\
166 break;\
167 } while (0)
168
169 static scm_sizet
170 cind (SCM ra, SCM inds)
171 {
172 scm_sizet i;
173 int k;
174 long *ve = (long*) SCM_VELTS (inds);
175 if (!SCM_ARRAYP (ra))
176 return *ve;
177 i = SCM_ARRAY_BASE (ra);
178 for (k = 0; k < SCM_ARRAY_NDIM (ra); k++)
179 i += (ve[k] - SCM_ARRAY_DIMS (ra)[k].lbnd) * SCM_ARRAY_DIMS (ra)[k].inc;
180 return i;
181 }
182
183
184 /* Checker for scm_array mapping functions:
185 return values: 4 --> shapes, increments, and bases are the same;
186 3 --> shapes and increments are the same;
187 2 --> shapes are the same;
188 1 --> ras are at least as big as ra0;
189 0 --> no match.
190 */
191
192 int
193 scm_ra_matchp (SCM ra0, SCM ras)
194 {
195 SCM ra1;
196 scm_array_dim dims;
197 scm_array_dim *s0 = &dims;
198 scm_array_dim *s1;
199 scm_sizet bas0 = 0;
200 int i, ndim = 1;
201 int exact = 2 /* 4 */ ; /* Don't care about values >2 (yet?) */
202 if (SCM_IMP (ra0)) return 0;
203 switch (SCM_TYP7 (ra0))
204 {
205 default:
206 return 0;
207 case scm_tc7_vector:
208 case scm_tc7_wvect:
209 case scm_tc7_string:
210 case scm_tc7_byvect:
211 case scm_tc7_bvect:
212 case scm_tc7_uvect:
213 case scm_tc7_ivect:
214 case scm_tc7_svect:
215 #ifdef HAVE_LONG_LONGS
216 case scm_tc7_llvect:
217 #endif
218 case scm_tc7_fvect:
219 case scm_tc7_dvect:
220 case scm_tc7_cvect:
221 s0->lbnd = 0;
222 s0->inc = 1;
223 s0->ubnd = (long) SCM_LENGTH (ra0) - 1;
224 break;
225 case scm_tc7_smob:
226 if (!SCM_ARRAYP (ra0))
227 return 0;
228 ndim = SCM_ARRAY_NDIM (ra0);
229 s0 = SCM_ARRAY_DIMS (ra0);
230 bas0 = SCM_ARRAY_BASE (ra0);
231 break;
232 }
233 while (SCM_NIMP (ras))
234 {
235 ra1 = SCM_CAR (ras);
236 if (SCM_IMP (ra1))
237 return 0;
238 switch SCM_TYP7
239 (ra1)
240 {
241 default:
242 return 0;
243 case scm_tc7_vector:
244 case scm_tc7_wvect:
245 case scm_tc7_string:
246 case scm_tc7_byvect:
247 case scm_tc7_bvect:
248 case scm_tc7_uvect:
249 case scm_tc7_ivect:
250 case scm_tc7_svect:
251 #ifdef HAVE_LONG_LONGS
252 case scm_tc7_llvect:
253 #endif
254 case scm_tc7_fvect:
255 case scm_tc7_dvect:
256 case scm_tc7_cvect:
257 if (1 != ndim)
258 return 0;
259 switch (exact)
260 {
261 case 4:
262 if (0 != bas0)
263 exact = 3;
264 case 3:
265 if (1 != s0->inc)
266 exact = 2;
267 case 2:
268 if ((0 == s0->lbnd) && (s0->ubnd == SCM_LENGTH (ra1) - 1))
269 break;
270 exact = 1;
271 case 1:
272 if (s0->lbnd < 0 || s0->ubnd >= SCM_LENGTH (ra1))
273 return 0;
274 }
275 break;
276 case scm_tc7_smob:
277 if (!SCM_ARRAYP (ra1) || ndim != SCM_ARRAY_NDIM (ra1))
278 return 0;
279 s1 = SCM_ARRAY_DIMS (ra1);
280 if (bas0 != SCM_ARRAY_BASE (ra1))
281 exact = 3;
282 for (i = 0; i < ndim; i++)
283 switch (exact)
284 {
285 case 4:
286 case 3:
287 if (s0[i].inc != s1[i].inc)
288 exact = 2;
289 case 2:
290 if (s0[i].lbnd == s1[i].lbnd && s0[i].ubnd == s1[i].ubnd)
291 break;
292 exact = 1;
293 default:
294 if (s0[i].lbnd < s1[i].lbnd || s0[i].ubnd > s1[i].ubnd)
295 return (s0[i].lbnd <= s0[i].ubnd ? 0 : 1);
296 }
297 break;
298 }
299 ras = SCM_CDR (ras);
300 }
301 return exact;
302 }
303
304 /* array mapper: apply cproc to each dimension of the given arrays?.
305 int (*cproc) (); procedure to call on unrolled arrays?
306 cproc (dest, source list) or
307 cproc (dest, data, source list).
308 SCM data; data to give to cproc or unbound.
309 SCM ra0; destination array.
310 SCM lra; list of source arrays.
311 const char *what; caller, for error reporting. */
312 int
313 scm_ramapc (int (*cproc)(), SCM data, SCM ra0, SCM lra, const char *what)
314 {
315 SCM inds, z;
316 SCM vra0, ra1, vra1;
317 SCM lvra, *plvra;
318 long *vinds;
319 int k, kmax;
320 switch (scm_ra_matchp (ra0, lra))
321 {
322 default:
323 case 0:
324 scm_wta (ra0, "array shape mismatch", what);
325 case 2:
326 case 3:
327 case 4: /* Try unrolling arrays */
328 kmax = (SCM_ARRAYP (ra0) ? SCM_ARRAY_NDIM (ra0) - 1 : 0);
329 if (kmax < 0)
330 goto gencase;
331 vra0 = scm_array_contents (ra0, SCM_UNDEFINED);
332 if (SCM_IMP (vra0)) goto gencase;
333 if (!SCM_ARRAYP (vra0))
334 {
335 vra1 = scm_make_ra (1);
336 SCM_ARRAY_BASE (vra1) = 0;
337 SCM_ARRAY_DIMS (vra1)->lbnd = 0;
338 SCM_ARRAY_DIMS (vra1)->ubnd = SCM_LENGTH (vra0) - 1;
339 SCM_ARRAY_DIMS (vra1)->inc = 1;
340 SCM_ARRAY_V (vra1) = vra0;
341 vra0 = vra1;
342 }
343 lvra = SCM_EOL;
344 plvra = &lvra;
345 for (z = lra; SCM_NIMP (z); z = SCM_CDR (z))
346 {
347 ra1 = SCM_CAR (z);
348 vra1 = scm_make_ra (1);
349 SCM_ARRAY_DIMS (vra1)->lbnd = SCM_ARRAY_DIMS (vra0)->lbnd;
350 SCM_ARRAY_DIMS (vra1)->ubnd = SCM_ARRAY_DIMS (vra0)->ubnd;
351 if (!SCM_ARRAYP (ra1))
352 {
353 SCM_ARRAY_BASE (vra1) = 0;
354 SCM_ARRAY_DIMS (vra1)->inc = 1;
355 SCM_ARRAY_V (vra1) = ra1;
356 }
357 else if (!SCM_ARRAY_CONTP (ra1))
358 goto gencase;
359 else
360 {
361 SCM_ARRAY_BASE (vra1) = SCM_ARRAY_BASE (ra1);
362 SCM_ARRAY_DIMS (vra1)->inc = SCM_ARRAY_DIMS (ra1)[kmax].inc;
363 SCM_ARRAY_V (vra1) = SCM_ARRAY_V (ra1);
364 }
365 *plvra = scm_cons (vra1, SCM_EOL);
366 plvra = SCM_CDRLOC (*plvra);
367 }
368 return (SCM_UNBNDP (data) ? cproc(vra0, lvra) : cproc(vra0, data, lvra));
369 case 1:
370 gencase: /* Have to loop over all dimensions. */
371 vra0 = scm_make_ra (1);
372 if (SCM_ARRAYP (ra0))
373 {
374 kmax = SCM_ARRAY_NDIM (ra0) - 1;
375 if (kmax < 0)
376 {
377 SCM_ARRAY_DIMS (vra0)->lbnd = 0;
378 SCM_ARRAY_DIMS (vra0)->ubnd = 0;
379 SCM_ARRAY_DIMS (vra0)->inc = 1;
380 }
381 else
382 {
383 SCM_ARRAY_DIMS (vra0)->lbnd = SCM_ARRAY_DIMS (ra0)[kmax].lbnd;
384 SCM_ARRAY_DIMS (vra0)->ubnd = SCM_ARRAY_DIMS (ra0)[kmax].ubnd;
385 SCM_ARRAY_DIMS (vra0)->inc = SCM_ARRAY_DIMS (ra0)[kmax].inc;
386 }
387 SCM_ARRAY_BASE (vra0) = SCM_ARRAY_BASE (ra0);
388 SCM_ARRAY_V (vra0) = SCM_ARRAY_V (ra0);
389 }
390 else
391 {
392 kmax = 0;
393 SCM_ARRAY_DIMS (vra0)->lbnd = 0;
394 SCM_ARRAY_DIMS (vra0)->ubnd = SCM_LENGTH (ra0) - 1;
395 SCM_ARRAY_DIMS (vra0)->inc = 1;
396 SCM_ARRAY_BASE (vra0) = 0;
397 SCM_ARRAY_V (vra0) = ra0;
398 ra0 = vra0;
399 }
400 lvra = SCM_EOL;
401 plvra = &lvra;
402 for (z = lra; SCM_NIMP (z); z = SCM_CDR (z))
403 {
404 ra1 = SCM_CAR (z);
405 vra1 = scm_make_ra (1);
406 SCM_ARRAY_DIMS (vra1)->lbnd = SCM_ARRAY_DIMS (vra0)->lbnd;
407 SCM_ARRAY_DIMS (vra1)->ubnd = SCM_ARRAY_DIMS (vra0)->ubnd;
408 if (SCM_ARRAYP (ra1))
409 {
410 if (kmax >= 0)
411 SCM_ARRAY_DIMS (vra1)->inc = SCM_ARRAY_DIMS (ra1)[kmax].inc;
412 SCM_ARRAY_V (vra1) = SCM_ARRAY_V (ra1);
413 }
414 else
415 {
416 SCM_ARRAY_DIMS (vra1)->inc = 1;
417 SCM_ARRAY_V (vra1) = ra1;
418 }
419 *plvra = scm_cons (vra1, SCM_EOL);
420 plvra = SCM_CDRLOC (*plvra);
421 }
422 inds = scm_make_uve (SCM_ARRAY_NDIM (ra0), SCM_MAKINUM (-1L));
423 vinds = (long *) SCM_VELTS (inds);
424 for (k = 0; k <= kmax; k++)
425 vinds[k] = SCM_ARRAY_DIMS (ra0)[k].lbnd;
426 k = kmax;
427 do
428 {
429 if (k == kmax)
430 {
431 SCM y = lra;
432 SCM_ARRAY_BASE (vra0) = cind (ra0, inds);
433 for (z = lvra; SCM_NIMP (z); z = SCM_CDR (z), y = SCM_CDR (y))
434 SCM_ARRAY_BASE (SCM_CAR (z)) = cind (SCM_CAR (y), inds);
435 if (0 == (SCM_UNBNDP (data) ? cproc(vra0, lvra) : cproc(vra0, data, lvra)))
436 return 0;
437 k--;
438 continue;
439 }
440 if (vinds[k] < SCM_ARRAY_DIMS (ra0)[k].ubnd)
441 {
442 vinds[k]++;
443 k++;
444 continue;
445 }
446 vinds[k] = SCM_ARRAY_DIMS (ra0)[k].lbnd - 1;
447 k--;
448 }
449 while (k >= 0);
450 return 1;
451 }
452 }
453
454
455 SCM_DEFINE (scm_array_fill_x, "array-fill!", 2, 0, 0,
456 (SCM ra, SCM fill),
457 "Stores @var{fill} in every element of @var{array}. The value returned\n"
458 "is unspecified.")
459 #define FUNC_NAME s_scm_array_fill_x
460 {
461 scm_ramapc (scm_array_fill_int, fill, ra, SCM_EOL, FUNC_NAME);
462 return SCM_UNSPECIFIED;
463 }
464 #undef FUNC_NAME
465
466 /* to be used as cproc in scm_ramapc to fill an array dimension with
467 "fill". */
468 int
469 scm_array_fill_int (SCM ra, SCM fill, SCM ignore)
470 #define FUNC_NAME s_scm_array_fill_x
471 {
472 scm_sizet i;
473 scm_sizet n = SCM_ARRAY_DIMS (ra)->ubnd - SCM_ARRAY_DIMS (ra)->lbnd + 1;
474 long inc = SCM_ARRAY_DIMS (ra)->inc;
475 scm_sizet base = SCM_ARRAY_BASE (ra);
476
477 ra = SCM_ARRAY_V (ra);
478 switch SCM_TYP7 (ra)
479 {
480 default:
481 for (i = base; n--; i += inc)
482 scm_array_set_x (ra, fill, SCM_MAKINUM (i));
483 break;
484 case scm_tc7_vector:
485 case scm_tc7_wvect:
486 for (i = base; n--; i += inc)
487 SCM_VELTS (ra)[i] = fill;
488 break;
489 case scm_tc7_string:
490 SCM_ASRTGO (SCM_CHARP (fill), badarg2);
491 for (i = base; n--; i += inc)
492 SCM_CHARS (ra)[i] = SCM_CHAR (fill);
493 break;
494 case scm_tc7_byvect:
495 if (SCM_CHARP (fill))
496 fill = SCM_MAKINUM ((char) SCM_CHAR (fill));
497 SCM_ASRTGO (SCM_INUMP (fill)
498 && -128 <= SCM_INUM (fill) && SCM_INUM (fill) < 128,
499 badarg2);
500 for (i = base; n--; i += inc)
501 SCM_CHARS (ra)[i] = SCM_INUM (fill);
502 break;
503 case scm_tc7_bvect:
504 { /* scope */
505 long *ve = (long *) SCM_VELTS (ra);
506 if (1 == inc && (n >= SCM_LONG_BIT || n == SCM_LENGTH (ra)))
507 {
508 i = base / SCM_LONG_BIT;
509 if (SCM_FALSEP (fill))
510 {
511 if (base % SCM_LONG_BIT) /* leading partial word */
512 ve[i++] &= ~(~0L << (base % SCM_LONG_BIT));
513 for (; i < (base + n) / SCM_LONG_BIT; i++)
514 ve[i] = 0L;
515 if ((base + n) % SCM_LONG_BIT) /* trailing partial word */
516 ve[i] &= (~0L << ((base + n) % SCM_LONG_BIT));
517 }
518 else if (SCM_TRUE_P (fill))
519 {
520 if (base % SCM_LONG_BIT)
521 ve[i++] |= ~0L << (base % SCM_LONG_BIT);
522 for (; i < (base + n) / SCM_LONG_BIT; i++)
523 ve[i] = ~0L;
524 if ((base + n) % SCM_LONG_BIT)
525 ve[i] |= ~(~0L << ((base + n) % SCM_LONG_BIT));
526 }
527 else
528 badarg2:SCM_WTA (2,fill);
529 }
530 else
531 {
532 if (SCM_FALSEP (fill))
533 for (i = base; n--; i += inc)
534 ve[i / SCM_LONG_BIT] &= ~(1L << (i % SCM_LONG_BIT));
535 else if (SCM_TRUE_P (fill))
536 for (i = base; n--; i += inc)
537 ve[i / SCM_LONG_BIT] |= (1L << (i % SCM_LONG_BIT));
538 else
539 goto badarg2;
540 }
541 break;
542 }
543 case scm_tc7_uvect:
544 { /* scope */
545 unsigned long f = SCM_NUM2ULONG (2,fill);
546 unsigned long *ve = (long *) SCM_VELTS (ra);
547
548 for (i = base; n--; i += inc)
549 ve[i] = f;
550 break;
551 }
552 case scm_tc7_ivect:
553 { /* scope */
554 long f = SCM_NUM2LONG (2,fill);
555 long *ve = (long *) SCM_VELTS (ra);
556
557 for (i = base; n--; i += inc)
558 ve[i] = f;
559 break;
560 }
561 case scm_tc7_svect:
562 SCM_ASRTGO (SCM_INUMP (fill), badarg2);
563 { /* scope */
564 short f = SCM_INUM (fill);
565 short *ve = (short *) SCM_VELTS (ra);
566
567 if (f != SCM_INUM (fill))
568 SCM_OUT_OF_RANGE (2, fill);
569 for (i = base; n--; i += inc)
570 ve[i] = f;
571 break;
572 }
573 #ifdef HAVE_LONG_LONGS
574 case scm_tc7_llvect:
575 { /* scope */
576 long long f = SCM_NUM2LONG_LONG (2,fill);
577 long long *ve = (long long *) SCM_VELTS (ra);
578
579 for (i = base; n--; i += inc)
580 ve[i] = f;
581 break;
582 }
583 #endif
584 case scm_tc7_fvect:
585 { /* scope */
586 float f, *ve = (float *) SCM_VELTS (ra);
587 SCM_ASRTGO (SCM_REALP (fill), badarg2);
588 f = SCM_REALPART (fill);
589 for (i = base; n--; i += inc)
590 ve[i] = f;
591 break;
592 }
593 case scm_tc7_dvect:
594 { /* scope */
595 double f, *ve = (double *) SCM_VELTS (ra);
596 SCM_ASRTGO (SCM_REALP (fill), badarg2);
597 f = SCM_REALPART (fill);
598 for (i = base; n--; i += inc)
599 ve[i] = f;
600 break;
601 }
602 case scm_tc7_cvect:
603 { /* scope */
604 double fr, fi;
605 double (*ve)[2] = (double (*)[2]) SCM_VELTS (ra);
606 SCM_ASRTGO (SCM_INEXP (fill), badarg2);
607 fr = SCM_REALPART (fill);
608 fi = (SCM_CPLXP (fill) ? SCM_IMAG (fill) : 0.0);
609 for (i = base; n--; i += inc)
610 {
611 ve[i][0] = fr;
612 ve[i][1] = fi;
613 }
614 break;
615 }
616 }
617 return 1;
618 }
619 #undef FUNC_NAME
620
621
622
623 static int
624 racp (SCM src, SCM dst)
625 {
626 long n = (SCM_ARRAY_DIMS (src)->ubnd - SCM_ARRAY_DIMS (src)->lbnd + 1);
627 long inc_d, inc_s = SCM_ARRAY_DIMS (src)->inc;
628 scm_sizet i_d, i_s = SCM_ARRAY_BASE (src);
629 dst = SCM_CAR (dst);
630 inc_d = SCM_ARRAY_DIMS (dst)->inc;
631 i_d = SCM_ARRAY_BASE (dst);
632 src = SCM_ARRAY_V (src);
633 dst = SCM_ARRAY_V (dst);
634
635
636 /* untested optimization: don't copy if we're we. This allows the
637 ugly UNICOS macros (IVDEP) to go .
638 */
639
640 if (SCM_EQ_P (src, dst))
641 return 1 ;
642
643 switch SCM_TYP7
644 (dst)
645 {
646 default:
647 gencase:
648 case scm_tc7_vector:
649 case scm_tc7_wvect:
650
651 for (; n-- > 0; i_s += inc_s, i_d += inc_d)
652 scm_array_set_x (dst, scm_cvref (src, i_s, SCM_UNDEFINED), SCM_MAKINUM (i_d));
653 break;
654 case scm_tc7_string:
655 case scm_tc7_byvect:
656 if (scm_tc7_string != SCM_TYP7 (dst))
657 goto gencase;
658 for (; n-- > 0; i_s += inc_s, i_d += inc_d)
659 SCM_CHARS (dst)[i_d] = SCM_CHARS (src)[i_s];
660 break;
661 case scm_tc7_bvect:
662 if (scm_tc7_bvect != SCM_TYP7 (dst))
663 goto gencase;
664 if (1 == inc_d && 1 == inc_s && i_s % SCM_LONG_BIT == i_d % SCM_LONG_BIT && n >= SCM_LONG_BIT)
665 {
666 long *sv = (long *) SCM_VELTS (src);
667 long *dv = (long *) SCM_VELTS (dst);
668 sv += i_s / SCM_LONG_BIT;
669 dv += i_d / SCM_LONG_BIT;
670 if (i_s % SCM_LONG_BIT)
671 { /* leading partial word */
672 *dv = (*dv & ~(~0L << (i_s % SCM_LONG_BIT))) | (*sv & (~0L << (i_s % SCM_LONG_BIT)));
673 dv++;
674 sv++;
675 n -= SCM_LONG_BIT - (i_s % SCM_LONG_BIT);
676 }
677 for (; n >= SCM_LONG_BIT; n -= SCM_LONG_BIT, sv++, dv++)
678 * dv = *sv;
679 if (n) /* trailing partial word */
680 *dv = (*dv & (~0L << n)) | (*sv & ~(~0L << n));
681 }
682 else
683 {
684 for (; n-- > 0; i_s += inc_s, i_d += inc_d)
685 if (SCM_BITVEC_REF(src, i_s))
686 SCM_BITVEC_SET(dst, i_d);
687 else
688 SCM_BITVEC_CLR(dst, i_d);
689 }
690 break;
691 case scm_tc7_uvect:
692 if (scm_tc7_uvect != SCM_TYP7 (src))
693 goto gencase;
694 else
695 {
696 long *d = (long *) SCM_VELTS (dst), *s = (long *) SCM_VELTS (src);
697 for (; n-- > 0; i_s += inc_s, i_d += inc_d)
698 d[i_d] = s[i_s];
699 break;
700 }
701 case scm_tc7_ivect:
702 if (scm_tc7_uvect != SCM_TYP7 (src) && scm_tc7_ivect != SCM_TYP7 (src))
703 goto gencase;
704 else
705 {
706 long *d = (long *) SCM_VELTS (dst), *s = (long *) SCM_VELTS (src);
707 for (; n-- > 0; i_s += inc_s, i_d += inc_d)
708 d[i_d] = s[i_s];
709 break;
710 }
711 case scm_tc7_fvect:
712 {
713 float *d = (float *) SCM_VELTS (dst);
714 float *s = (float *) SCM_VELTS (src);
715 switch SCM_TYP7
716 (src)
717 {
718 default:
719 goto gencase;
720 case scm_tc7_ivect:
721 case scm_tc7_uvect:
722 for (; n-- > 0; i_s += inc_s, i_d += inc_d)
723 d[i_d] = ((long *) s)[i_s];
724 break;
725 case scm_tc7_fvect:
726 for (; n-- > 0; i_s += inc_s, i_d += inc_d)
727 d[i_d] = s[i_s];
728 break;
729 case scm_tc7_dvect:
730 for (; n-- > 0; i_s += inc_s, i_d += inc_d)
731 d[i_d] = ((double *) s)[i_s];
732 break;
733 }
734 break;
735 }
736 case scm_tc7_dvect:
737 {
738 double *d = (double *) SCM_VELTS (dst);
739 double *s = (double *) SCM_VELTS (src);
740 switch SCM_TYP7
741 (src)
742 {
743 default:
744 goto gencase;
745 case scm_tc7_ivect:
746 case scm_tc7_uvect:
747 for (; n-- > 0; i_s += inc_s, i_d += inc_d)
748 d[i_d] = ((long *) s)[i_s];
749 break;
750 case scm_tc7_fvect:
751 for (; n-- > 0; i_s += inc_s, i_d += inc_d)
752 d[i_d] = ((float *) s)[i_s];
753 break;
754 case scm_tc7_dvect:
755 for (; n-- > 0; i_s += inc_s, i_d += inc_d)
756 d[i_d] = s[i_s];
757 break;
758 }
759 break;
760 }
761 case scm_tc7_cvect:
762 {
763 double (*d)[2] = (double (*)[2]) SCM_VELTS (dst);
764 double (*s)[2] = (double (*)[2]) SCM_VELTS (src);
765 switch SCM_TYP7
766 (src)
767 {
768 default:
769 goto gencase;
770 case scm_tc7_ivect:
771 case scm_tc7_uvect:
772 for (; n-- > 0; i_s += inc_s, i_d += inc_d)
773 {
774 d[i_d][0] = ((long *) s)[i_s];
775 d[i_d][1] = 0.0;
776 }
777 break;
778 case scm_tc7_fvect:
779 for (; n-- > 0; i_s += inc_s, i_d += inc_d)
780 {
781 d[i_d][0] = ((float *) s)[i_s];
782 d[i_d][1] = 0.0;
783 }
784 break;
785 case scm_tc7_dvect:
786 for (; n-- > 0; i_s += inc_s, i_d += inc_d)
787 {
788 d[i_d][0] = ((double *) s)[i_s];
789 d[i_d][1] = 0.0;
790 }
791 break;
792 case scm_tc7_cvect:
793 for (; n-- > 0; i_s += inc_s, i_d += inc_d)
794 {
795 d[i_d][0] = s[i_s][0];
796 d[i_d][1] = s[i_s][1];
797 }
798 }
799 break;
800 }
801 }
802 return 1;
803 }
804
805
806 /* This name is obsolete. Will go away in release 1.5. */
807 SCM_REGISTER_PROC(s_serial_array_copy_x, "serial-array-copy!", 2, 0, 0, scm_array_copy_x);
808 SCM_REGISTER_PROC(s_array_copy_in_order_x, "array-copy-in-order!", 2, 0, 0, scm_array_copy_x);
809
810
811 SCM_DEFINE (scm_array_copy_x, "array-copy!", 2, 0, 0,
812 (SCM src, SCM dst),
813 "Copies every element from vector or array @var{source} to the\n"
814 "corresponding element of @var{destination}. @var{destination} must have\n"
815 "the same rank as @var{source}, and be at least as large in each\n"
816 "dimension. The order is unspecified.")
817 #define FUNC_NAME s_scm_array_copy_x
818 {
819 scm_ramapc (racp, SCM_UNDEFINED, src, scm_cons (dst, SCM_EOL), FUNC_NAME);
820 return SCM_UNSPECIFIED;
821 }
822 #undef FUNC_NAME
823
824 /* Functions callable by ARRAY-MAP! */
825
826
827 int
828 scm_ra_eqp (SCM ra0, SCM ras)
829 {
830 SCM ra1 = SCM_CAR (ras), ra2 = SCM_CAR (SCM_CDR (ras));
831 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
832 scm_sizet i0 = SCM_ARRAY_BASE (ra0), i1 = SCM_ARRAY_BASE (ra1), i2 = SCM_ARRAY_BASE (ra2);
833 long inc0 = SCM_ARRAY_DIMS (ra0)->inc;
834 long inc1 = SCM_ARRAY_DIMS (ra1)->inc;
835 long inc2 = SCM_ARRAY_DIMS (ra1)->inc;
836 ra0 = SCM_ARRAY_V (ra0);
837 ra1 = SCM_ARRAY_V (ra1);
838 ra2 = SCM_ARRAY_V (ra2);
839 switch (SCM_TYP7 (ra1) == SCM_TYP7 (ra2) ? SCM_TYP7 (ra1) : 0)
840 {
841 default:
842 {
843 SCM e1 = SCM_UNDEFINED, e2 = SCM_UNDEFINED;
844 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
845 if (SCM_BITVEC_REF (ra0, i0))
846 if (SCM_FALSEP(scm_eq_p (RVREF (ra1, i1, e1), RVREF (ra2, i2, e2))))
847 SCM_BITVEC_CLR (ra0, i0);
848 break;
849 }
850 case scm_tc7_uvect:
851 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
852 if (SCM_BITVEC_REF (ra0, i0))
853 if (((unsigned long *) SCM_VELTS (ra1))[i1] != ((unsigned long *) SCM_VELTS (ra2))[i2])
854 SCM_BITVEC_CLR (ra0, i0);
855 break;
856 case scm_tc7_ivect:
857 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
858 if (SCM_BITVEC_REF (ra0, i0))
859 if (((signed long *) SCM_VELTS (ra1))[i1] != ((signed long *) SCM_VELTS (ra2))[i2])
860 SCM_BITVEC_CLR (ra0, i0);
861 break;
862 case scm_tc7_fvect:
863 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
864 if (SCM_BITVEC_REF (ra0, i0))
865 if (((float *) SCM_VELTS (ra1))[i1] != ((float *) SCM_VELTS (ra2))[i2])
866 SCM_BITVEC_CLR (ra0, i0);
867 break;
868 case scm_tc7_dvect:
869 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
870 if (SCM_BITVEC_REF (ra0, i0))
871 if (((double *) SCM_VELTS (ra1))[i1] != ((double *) SCM_VELTS (ra2))[i2])
872 SCM_BITVEC_CLR (ra0, i0);
873 break;
874 case scm_tc7_cvect:
875 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
876 if (SCM_BITVEC_REF (ra0, i0))
877 if (((double *) SCM_VELTS (ra1))[2 * i1] != ((double *) SCM_VELTS (ra2))[2 * i2] ||
878 ((double *) SCM_VELTS (ra1))[2 * i1 + 1] != ((double *) SCM_VELTS (ra2))[2 * i2 + 1])
879 SCM_BITVEC_CLR (ra0, i0);
880 break;
881 }
882 return 1;
883 }
884
885 /* opt 0 means <, nonzero means >= */
886
887 static int
888 ra_compare (SCM ra0,SCM ra1,SCM ra2,int opt)
889 {
890 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
891 scm_sizet i0 = SCM_ARRAY_BASE (ra0), i1 = SCM_ARRAY_BASE (ra1), i2 = SCM_ARRAY_BASE (ra2);
892 long inc0 = SCM_ARRAY_DIMS (ra0)->inc;
893 long inc1 = SCM_ARRAY_DIMS (ra1)->inc;
894 long inc2 = SCM_ARRAY_DIMS (ra1)->inc;
895 ra0 = SCM_ARRAY_V (ra0);
896 ra1 = SCM_ARRAY_V (ra1);
897 ra2 = SCM_ARRAY_V (ra2);
898 switch (SCM_TYP7 (ra1) == SCM_TYP7 (ra2) ? SCM_TYP7 (ra1) : 0)
899 {
900 default:
901 {
902 SCM e1 = SCM_UNDEFINED, e2 = SCM_UNDEFINED;
903 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
904 if (SCM_BITVEC_REF (ra0, i0))
905 if (opt ?
906 SCM_NFALSEP (scm_less_p (RVREF (ra1, i1, e1), RVREF (ra2, i2, e2))) :
907 SCM_FALSEP (scm_less_p (RVREF (ra1, i1, e1), RVREF (ra2, i2, e2))))
908 SCM_BITVEC_CLR (ra0, i0);
909 break;
910 }
911 case scm_tc7_uvect:
912 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
913 {
914 if (SCM_BITVEC_REF (ra0, i0))
915 if (opt ?
916 ((unsigned long *) SCM_VELTS (ra1))[i1] < ((unsigned long *) SCM_VELTS (ra2))[i2] :
917 ((unsigned long *) SCM_VELTS (ra1))[i1] >= ((unsigned long *) SCM_VELTS (ra2))[i2])
918 SCM_BITVEC_CLR (ra0, i0);
919 }
920 break;
921 case scm_tc7_ivect:
922 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
923 {
924 if (SCM_BITVEC_REF (ra0, i0))
925 if (opt ?
926 ((signed long *) SCM_VELTS (ra1))[i1] < ((signed long *) SCM_VELTS (ra2))[i2] :
927 ((signed long *) SCM_VELTS (ra1))[i1] >= ((signed long *) SCM_VELTS (ra2))[i2])
928 SCM_BITVEC_CLR (ra0, i0);
929 }
930 break;
931 case scm_tc7_fvect:
932 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
933 if (SCM_BITVEC_REF(ra0, i0))
934 if (opt ?
935 ((float *) SCM_VELTS (ra1))[i1] < ((float *) SCM_VELTS (ra2))[i2] :
936 ((float *) SCM_VELTS (ra1))[i1] >= ((float *) SCM_VELTS (ra2))[i2])
937 SCM_BITVEC_CLR (ra0, i0);
938 break;
939 case scm_tc7_dvect:
940 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
941 if (SCM_BITVEC_REF (ra0, i0))
942 if (opt ?
943 ((double *) SCM_VELTS (ra1))[i1] < ((double *) SCM_VELTS (ra2))[i2] :
944 ((double *) SCM_VELTS (ra1))[i1] >= ((double *) SCM_VELTS (ra2))[i2])
945 SCM_BITVEC_CLR (ra0, i0);
946 break;
947 }
948 return 1;
949 }
950
951
952
953 int
954 scm_ra_lessp (SCM ra0, SCM ras)
955 {
956 return ra_compare (ra0, SCM_CAR (ras), SCM_CAR (SCM_CDR (ras)), 0);
957 }
958
959
960 int
961 scm_ra_leqp (SCM ra0, SCM ras)
962 {
963 return ra_compare (ra0, SCM_CAR (SCM_CDR (ras)), SCM_CAR (ras), 1);
964 }
965
966
967 int
968 scm_ra_grp (SCM ra0, SCM ras)
969 {
970 return ra_compare (ra0, SCM_CAR (SCM_CDR (ras)), SCM_CAR (ras), 0);
971 }
972
973
974 int
975 scm_ra_greqp (SCM ra0, SCM ras)
976 {
977 return ra_compare (ra0, SCM_CAR (ras), SCM_CAR (SCM_CDR (ras)), 1);
978 }
979
980
981 int
982 scm_ra_sum (SCM ra0, SCM ras)
983 {
984 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
985 scm_sizet i0 = SCM_ARRAY_BASE (ra0);
986 long inc0 = SCM_ARRAY_DIMS (ra0)->inc;
987 ra0 = SCM_ARRAY_V (ra0);
988 if (SCM_NNULLP(ras))
989 {
990 SCM ra1 = SCM_CAR (ras);
991 scm_sizet i1 = SCM_ARRAY_BASE (ra1);
992 long inc1 = SCM_ARRAY_DIMS (ra1)->inc;
993 ra1 = SCM_ARRAY_V (ra1);
994 switch (SCM_TYP7 (ra0) == SCM_TYP7 (ra1) ? SCM_TYP7 (ra0) : 0)
995 {
996 default:
997 {
998 SCM e0 = SCM_UNDEFINED, e1 = SCM_UNDEFINED;
999 for (; n-- > 0; i0 += inc0, i1 += inc1)
1000 scm_array_set_x (ra0, scm_sum (RVREF (ra0, i0, e0), RVREF (ra1, i1, e1)),
1001 SCM_MAKINUM (i0));
1002 break;
1003 }
1004 case scm_tc7_uvect:
1005 case scm_tc7_ivect:
1006 BINARY_ELTS_CODE( +=, long);
1007 case scm_tc7_fvect:
1008 BINARY_ELTS_CODE( +=, float);
1009 case scm_tc7_dvect:
1010 BINARY_ELTS_CODE( +=, double);
1011 case scm_tc7_cvect:
1012 BINARY_PAIR_ELTS_CODE( +=, double);
1013 }
1014 }
1015 return 1;
1016 }
1017
1018
1019
1020 int
1021 scm_ra_difference (SCM ra0, SCM ras)
1022 {
1023 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
1024 scm_sizet i0 = SCM_ARRAY_BASE (ra0);
1025 long inc0 = SCM_ARRAY_DIMS (ra0)->inc;
1026 ra0 = SCM_ARRAY_V (ra0);
1027 if (SCM_NULLP (ras))
1028 {
1029 switch (SCM_TYP7 (ra0))
1030 {
1031 default:
1032 {
1033 SCM e0 = SCM_UNDEFINED;
1034 for (; n-- > 0; i0 += inc0)
1035 scm_array_set_x (ra0,
1036 scm_difference (RVREF (ra0, i0, e0), SCM_UNDEFINED),
1037 SCM_MAKINUM (i0));
1038 break;
1039 }
1040 case scm_tc7_fvect:
1041 UNARY_ELTS_CODE( = -, float);
1042 case scm_tc7_dvect:
1043 UNARY_ELTS_CODE( = -, double);
1044 case scm_tc7_cvect:
1045 UNARY_PAIR_ELTS_CODE( = -, double);
1046 }
1047 }
1048 else
1049 {
1050 SCM ra1 = SCM_CAR (ras);
1051 scm_sizet i1 = SCM_ARRAY_BASE (ra1);
1052 long inc1 = SCM_ARRAY_DIMS (ra1)->inc;
1053 ra1 = SCM_ARRAY_V (ra1);
1054 switch (SCM_TYP7 (ra0) == SCM_TYP7 (ra1) ? SCM_TYP7 (ra0) : 0)
1055 {
1056 default:
1057 {
1058 SCM e0 = SCM_UNDEFINED, e1 = SCM_UNDEFINED;
1059 for (; n-- > 0; i0 += inc0, i1 += inc1)
1060 scm_array_set_x (ra0, scm_difference (RVREF (ra0, i0, e0), RVREF (ra1, i1, e1)), SCM_MAKINUM (i0));
1061 break;
1062 }
1063 case scm_tc7_fvect:
1064 BINARY_ELTS_CODE( -=, float);
1065 case scm_tc7_dvect:
1066 BINARY_ELTS_CODE( -=, double);
1067 case scm_tc7_cvect:
1068 BINARY_PAIR_ELTS_CODE( -=, double);
1069 }
1070 }
1071 return 1;
1072 }
1073
1074
1075
1076 int
1077 scm_ra_product (SCM ra0, SCM ras)
1078 {
1079 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
1080 scm_sizet i0 = SCM_ARRAY_BASE (ra0);
1081 long inc0 = SCM_ARRAY_DIMS (ra0)->inc;
1082 ra0 = SCM_ARRAY_V (ra0);
1083 if (SCM_NNULLP (ras))
1084 {
1085 SCM ra1 = SCM_CAR (ras);
1086 scm_sizet i1 = SCM_ARRAY_BASE (ra1);
1087 long inc1 = SCM_ARRAY_DIMS (ra1)->inc;
1088 ra1 = SCM_ARRAY_V (ra1);
1089 switch (SCM_TYP7 (ra0) == SCM_TYP7 (ra1) ? SCM_TYP7 (ra0) : 0)
1090 {
1091 default:
1092 {
1093 SCM e0 = SCM_UNDEFINED, e1 = SCM_UNDEFINED;
1094 for (; n-- > 0; i0 += inc0, i1 += inc1)
1095 scm_array_set_x (ra0, scm_product (RVREF (ra0, i0, e0), RVREF (ra1, i1, e1)),
1096 SCM_MAKINUM (i0));
1097 break;
1098 }
1099 case scm_tc7_uvect:
1100 case scm_tc7_ivect:
1101 BINARY_ELTS_CODE( *=, long);
1102 case scm_tc7_fvect:
1103 BINARY_ELTS_CODE( *=, float);
1104 case scm_tc7_dvect:
1105 BINARY_ELTS_CODE( *=, double);
1106 case scm_tc7_cvect:
1107 {
1108 double (*v0)[2] = (double (*)[2]) SCM_VELTS (ra0);
1109 register double r;
1110 double (*v1)[2] = (double (*)[2]) SCM_VELTS (ra1);
1111 IVDEP (ra0 != ra1,
1112 for (; n-- > 0; i0 += inc0, i1 += inc1)
1113 {
1114 r = v0[i0][0] * v1[i1][0] - v0[i0][1] * v1[i1][1];
1115 v0[i0][1] = v0[i0][0] * v1[i1][1] + v0[i0][1] * v1[i1][0];
1116 v0[i0][0] = r;
1117 }
1118 );
1119 break;
1120 }
1121 }
1122 }
1123 return 1;
1124 }
1125
1126
1127 int
1128 scm_ra_divide (SCM ra0, SCM ras)
1129 {
1130 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
1131 scm_sizet i0 = SCM_ARRAY_BASE (ra0);
1132 long inc0 = SCM_ARRAY_DIMS (ra0)->inc;
1133 ra0 = SCM_ARRAY_V (ra0);
1134 if (SCM_NULLP (ras))
1135 {
1136 switch (SCM_TYP7 (ra0))
1137 {
1138 default:
1139 {
1140 SCM e0 = SCM_UNDEFINED;
1141 for (; n-- > 0; i0 += inc0)
1142 scm_array_set_x (ra0, scm_divide (RVREF (ra0, i0, e0), SCM_UNDEFINED), SCM_MAKINUM (i0));
1143 break;
1144 }
1145 case scm_tc7_fvect:
1146 UNARY_ELTS_CODE( = 1.0 / , float);
1147 case scm_tc7_dvect:
1148 UNARY_ELTS_CODE( = 1.0 / , double);
1149 case scm_tc7_cvect:
1150 {
1151 register double d;
1152 double (*v0)[2] = (double (*)[2]) SCM_VELTS (ra0);
1153 for (; n-- > 0; i0 += inc0)
1154 {
1155 d = v0[i0][0] * v0[i0][0] + v0[i0][1] * v0[i0][1];
1156 v0[i0][0] /= d;
1157 v0[i0][1] /= -d;
1158 }
1159 break;
1160 }
1161 }
1162 }
1163 else
1164 {
1165 SCM ra1 = SCM_CAR (ras);
1166 scm_sizet i1 = SCM_ARRAY_BASE (ra1);
1167 long inc1 = SCM_ARRAY_DIMS (ra1)->inc;
1168 ra1 = SCM_ARRAY_V (ra1);
1169 switch (SCM_TYP7 (ra0) == SCM_TYP7 (ra1) ? SCM_TYP7 (ra0) : 0)
1170 {
1171 default:
1172 {
1173 SCM e0 = SCM_UNDEFINED, e1 = SCM_UNDEFINED;
1174 for (; n-- > 0; i0 += inc0, i1 += inc1)
1175 scm_array_set_x (ra0, scm_divide (RVREF (ra0, i0, e0), RVREF (ra1, i1, e1)), SCM_MAKINUM (i0));
1176 break;
1177 }
1178 case scm_tc7_fvect:
1179 BINARY_ELTS_CODE( /=, float);
1180 case scm_tc7_dvect:
1181 BINARY_ELTS_CODE( /=, double);
1182 case scm_tc7_cvect:
1183 {
1184 register double d, r;
1185 double (*v0)[2] = (double (*)[2]) SCM_VELTS (ra0);
1186 double (*v1)[2] = (double (*)[2]) SCM_VELTS (ra1);
1187 IVDEP (ra0 != ra1,
1188 for (; n-- > 0; i0 += inc0, i1 += inc1)
1189 {
1190 d = v1[i1][0] * v1[i1][0] + v1[i1][1] * v1[i1][1];
1191 r = (v0[i0][0] * v1[i1][0] + v0[i0][1] * v1[i1][1]) / d;
1192 v0[i0][1] = (v0[i0][1] * v1[i1][0] - v0[i0][0] * v1[i1][1]) / d;
1193 v0[i0][0] = r;
1194 }
1195 )
1196 break;
1197 }
1198 }
1199 }
1200 return 1;
1201 }
1202
1203
1204 int
1205 scm_array_identity (SCM dst, SCM src)
1206 {
1207 return racp (SCM_CAR (src), scm_cons (dst, SCM_EOL));
1208 }
1209
1210
1211
1212 static int
1213 ramap (SCM ra0,SCM proc,SCM ras)
1214 {
1215 long i = SCM_ARRAY_DIMS (ra0)->lbnd;
1216 long inc = SCM_ARRAY_DIMS (ra0)->inc;
1217 long n = SCM_ARRAY_DIMS (ra0)->ubnd;
1218 long base = SCM_ARRAY_BASE (ra0) - i * inc;
1219 ra0 = SCM_ARRAY_V (ra0);
1220 if (SCM_NULLP (ras))
1221 for (; i <= n; i++)
1222 scm_array_set_x (ra0, scm_apply (proc, SCM_EOL, SCM_EOL), SCM_MAKINUM (i * inc + base));
1223 else
1224 {
1225 SCM ra1 = SCM_CAR (ras);
1226 SCM args, *ve = &ras;
1227 scm_sizet k, i1 = SCM_ARRAY_BASE (ra1);
1228 long inc1 = SCM_ARRAY_DIMS (ra1)->inc;
1229 ra1 = SCM_ARRAY_V (ra1);
1230 ras = SCM_CDR (ras);
1231 if (SCM_NULLP(ras))
1232 ras = scm_nullvect;
1233 else
1234 {
1235 ras = scm_vector (ras);
1236 ve = SCM_VELTS (ras);
1237 }
1238 for (; i <= n; i++, i1 += inc1)
1239 {
1240 args = SCM_EOL;
1241 for (k = SCM_LENGTH (ras); k--;)
1242 args = scm_cons (scm_uniform_vector_ref (ve[k], SCM_MAKINUM (i)), args);
1243 args = scm_cons (scm_cvref (ra1, i1, SCM_UNDEFINED), args);
1244 scm_array_set_x (ra0, scm_apply (proc, args, SCM_EOL), SCM_MAKINUM (i * inc + base));
1245 }
1246 }
1247 return 1;
1248 }
1249
1250
1251 static int
1252 ramap_cxr (SCM ra0,SCM proc,SCM ras)
1253 {
1254 SCM ra1 = SCM_CAR (ras);
1255 SCM e1 = SCM_UNDEFINED;
1256 scm_sizet i0 = SCM_ARRAY_BASE (ra0), i1 = SCM_ARRAY_BASE (ra1);
1257 long inc0 = SCM_ARRAY_DIMS (ra0)->inc, inc1 = SCM_ARRAY_DIMS (ra1)->inc;
1258 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra1)->lbnd + 1;
1259 ra0 = SCM_ARRAY_V (ra0);
1260 ra1 = SCM_ARRAY_V (ra1);
1261 switch (SCM_TYP7 (ra0))
1262 {
1263 default:
1264 gencase:
1265 for (; n-- > 0; i0 += inc0, i1 += inc1)
1266 scm_array_set_x (ra0, scm_apply (proc, RVREF (ra1, i1, e1), scm_listofnull), SCM_MAKINUM (i0));
1267 break;
1268 case scm_tc7_fvect:
1269 {
1270 float *dst = (float *) SCM_VELTS (ra0);
1271 switch (SCM_TYP7 (ra1))
1272 {
1273 default:
1274 goto gencase;
1275 case scm_tc7_fvect:
1276 for (; n-- > 0; i0 += inc0, i1 += inc1)
1277 dst[i0] = SCM_DSUBRF (proc) ((double) ((float *) SCM_VELTS (ra1))[i1]);
1278 break;
1279 case scm_tc7_uvect:
1280 case scm_tc7_ivect:
1281 for (; n-- > 0; i0 += inc0, i1 += inc1)
1282 dst[i0] = SCM_DSUBRF (proc) (SCM_UNPACK (SCM_VELTS (ra1)[i1]));
1283 break;
1284 }
1285 break;
1286 }
1287 case scm_tc7_dvect:
1288 {
1289 double *dst = (double *) SCM_VELTS (ra0);
1290 switch (SCM_TYP7 (ra1))
1291 {
1292 default:
1293 goto gencase;
1294 case scm_tc7_dvect:
1295 for (; n-- > 0; i0 += inc0, i1 += inc1)
1296 dst[i0] = SCM_DSUBRF (proc) (((double *) SCM_VELTS (ra1))[i1]);
1297 break;
1298 case scm_tc7_uvect:
1299 case scm_tc7_ivect:
1300 for (; n-- > 0; i0 += inc0, i1 += inc1)
1301 dst[i0] = SCM_DSUBRF (proc) (SCM_UNPACK (SCM_VELTS (ra1)[i1]));
1302 break;
1303 }
1304 break;
1305 }
1306 }
1307 return 1;
1308 }
1309
1310
1311
1312 static int
1313 ramap_rp (SCM ra0,SCM proc,SCM ras)
1314 {
1315 SCM ra1 = SCM_CAR (ras), ra2 = SCM_CAR (SCM_CDR (ras));
1316 SCM e1 = SCM_UNDEFINED, e2 = SCM_UNDEFINED;
1317 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
1318 scm_sizet i0 = SCM_ARRAY_BASE (ra0), i1 = SCM_ARRAY_BASE (ra1), i2 = SCM_ARRAY_BASE (ra2);
1319 long inc0 = SCM_ARRAY_DIMS (ra0)->inc;
1320 long inc1 = SCM_ARRAY_DIMS (ra1)->inc;
1321 long inc2 = SCM_ARRAY_DIMS (ra1)->inc;
1322 ra0 = SCM_ARRAY_V (ra0);
1323 ra1 = SCM_ARRAY_V (ra1);
1324 ra2 = SCM_ARRAY_V (ra2);
1325 switch (SCM_TYP7 (ra1) == SCM_TYP7 (ra2) ? SCM_TYP7 (ra1) : 0)
1326 {
1327 default:
1328 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
1329 if (SCM_BITVEC_REF (ra0, i0))
1330 if (SCM_FALSEP (SCM_SUBRF (proc) (RVREF (ra1, i1, e1), RVREF (ra2, i2, e2))))
1331 SCM_BITVEC_CLR (ra0, i0);
1332 break;
1333 case scm_tc7_uvect:
1334 case scm_tc7_ivect:
1335 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
1336 if (SCM_BITVEC_REF (ra0, i0))
1337 {
1338 /* DIRK:FIXME:: There should be a way to access the elements
1339 of a cell as raw data. Further: How can we be sure that
1340 the values fit into an inum?
1341 */
1342 SCM n1 = SCM_MAKINUM (((long *) SCM_UNPACK (SCM_CDR (ra1)))[i1]);
1343 SCM n2 = SCM_MAKINUM (((long *) SCM_UNPACK (SCM_CDR (ra2)))[i2]);
1344 if (SCM_FALSEP (SCM_SUBRF (proc) (n1, n2)));
1345 SCM_BITVEC_CLR (ra0, i0);
1346 }
1347 break;
1348 case scm_tc7_fvect:
1349 {
1350 SCM a1 = scm_make_real (1.0), a2 = scm_make_real (1.0);
1351 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
1352 if (SCM_BITVEC_REF (ra0, i0))
1353 {
1354 SCM_REAL_VALUE (a1) = ((float *) SCM_VELTS (ra1))[i1];
1355 SCM_REAL_VALUE (a2) = ((float *) SCM_VELTS (ra2))[i2];
1356 if (SCM_FALSEP (SCM_SUBRF (proc) (a1, a2)))
1357 SCM_BITVEC_CLR (ra0, i0);
1358 }
1359 break;
1360 }
1361 case scm_tc7_dvect:
1362 {
1363 SCM a1 = scm_makdbl (1.0 / 3.0, 0.0), a2 = scm_makdbl (1.0 / 3.0, 0.0);
1364 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
1365 if (SCM_BITVEC_REF (ra0, i0))
1366 {
1367 SCM_REAL (a1) = ((double *) SCM_VELTS (ra1))[i1];
1368 SCM_REAL (a2) = ((double *) SCM_VELTS (ra2))[i2];
1369 if (SCM_FALSEP (SCM_SUBRF (proc) (a1, a2)))
1370 SCM_BITVEC_CLR (ra0, i0);
1371 }
1372 break;
1373 }
1374 case scm_tc7_cvect:
1375 {
1376 SCM a1 = scm_makdbl (1.0, 1.0), a2 = scm_makdbl (1.0, 1.0);
1377 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
1378 if (SCM_BITVEC_REF (ra0, i0))
1379 {
1380 SCM_COMPLEX_REAL (a1) = ((double *) SCM_VELTS (ra1))[2 * i1];
1381 SCM_COMPLEX_IMAG (a1) = ((double *) SCM_VELTS (ra1))[2 * i1 + 1];
1382 SCM_COMPLEX_REAL (a2) = ((double *) SCM_VELTS (ra2))[2 * i2];
1383 SCM_COMPLEX_IMAG (a2) = ((double *) SCM_VELTS (ra2))[2 * i2 + 1];
1384 if (SCM_FALSEP (SCM_SUBRF (proc) (a1, a2)))
1385 SCM_BITVEC_CLR (ra0, i0);
1386 }
1387 break;
1388 }
1389 }
1390 return 1;
1391 }
1392
1393
1394
1395 static int
1396 ramap_1 (SCM ra0,SCM proc,SCM ras)
1397 {
1398 SCM ra1 = SCM_CAR (ras);
1399 SCM e1 = SCM_UNDEFINED;
1400 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
1401 scm_sizet i0 = SCM_ARRAY_BASE (ra0), i1 = SCM_ARRAY_BASE (ra1);
1402 long inc0 = SCM_ARRAY_DIMS (ra0)->inc, inc1 = SCM_ARRAY_DIMS (ra1)->inc;
1403 ra0 = SCM_ARRAY_V (ra0);
1404 ra1 = SCM_ARRAY_V (ra1);
1405 if (scm_tc7_vector == SCM_TYP7 (ra0) || scm_tc7_wvect == SCM_TYP7 (ra0))
1406 for (; n-- > 0; i0 += inc0, i1 += inc1)
1407 scm_array_set_x (ra0, SCM_SUBRF (proc) (scm_cvref (ra1, i1, SCM_UNDEFINED)), SCM_MAKINUM (i0));
1408 else
1409 for (; n-- > 0; i0 += inc0, i1 += inc1)
1410 scm_array_set_x (ra0, SCM_SUBRF (proc) (RVREF (ra1, i1, e1)), SCM_MAKINUM (i0));
1411 return 1;
1412 }
1413
1414
1415
1416 static int
1417 ramap_2o (SCM ra0,SCM proc,SCM ras)
1418 {
1419 SCM ra1 = SCM_CAR (ras);
1420 SCM e1 = SCM_UNDEFINED;
1421 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
1422 scm_sizet i0 = SCM_ARRAY_BASE (ra0), i1 = SCM_ARRAY_BASE (ra1);
1423 long inc0 = SCM_ARRAY_DIMS (ra0)->inc, inc1 = SCM_ARRAY_DIMS (ra1)->inc;
1424 ra0 = SCM_ARRAY_V (ra0);
1425 ra1 = SCM_ARRAY_V (ra1);
1426 ras = SCM_CDR (ras);
1427 if (SCM_NULLP (ras))
1428 {
1429 if (scm_tc7_vector == SCM_TYP7 (ra0)
1430 || scm_tc7_wvect == SCM_TYP7 (ra0))
1431
1432 for (; n-- > 0; i0 += inc0, i1 += inc1)
1433 scm_array_set_x (ra0, SCM_SUBRF (proc) (scm_cvref (ra1, i1, SCM_UNDEFINED), SCM_UNDEFINED),
1434 SCM_MAKINUM (i0));
1435 else
1436 for (; n-- > 0; i0 += inc0, i1 += inc1)
1437 scm_array_set_x (ra0, SCM_SUBRF (proc) (RVREF (ra1, i1, e1), SCM_UNDEFINED),
1438 SCM_MAKINUM (i0));
1439 }
1440 else
1441 {
1442 SCM ra2 = SCM_CAR (ras);
1443 SCM e2 = SCM_UNDEFINED;
1444 scm_sizet i2 = SCM_ARRAY_BASE (ra2);
1445 long inc2 = SCM_ARRAY_DIMS (ra2)->inc;
1446 ra2 = SCM_ARRAY_V (ra2);
1447 if (scm_tc7_vector == SCM_TYP7 (ra0) || scm_tc7_wvect == SCM_TYP7 (ra0))
1448 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
1449 scm_array_set_x (ra0,
1450 SCM_SUBRF (proc) (scm_cvref (ra1, i1, SCM_UNDEFINED), scm_cvref (ra2, i2, SCM_UNDEFINED)),
1451 SCM_MAKINUM (i0));
1452 else
1453 for (; n-- > 0; i0 += inc0, i1 += inc1, i2 += inc2)
1454 scm_array_set_x (ra0,
1455 SCM_SUBRF (proc) (RVREF (ra1, i1, e1), RVREF (ra2, i2, e2)),
1456 SCM_MAKINUM (i0));
1457 }
1458 return 1;
1459 }
1460
1461
1462
1463 static int
1464 ramap_a (SCM ra0,SCM proc,SCM ras)
1465 {
1466 SCM e0 = SCM_UNDEFINED, e1 = SCM_UNDEFINED;
1467 long n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
1468 scm_sizet i0 = SCM_ARRAY_BASE (ra0);
1469 long inc0 = SCM_ARRAY_DIMS (ra0)->inc;
1470 ra0 = SCM_ARRAY_V (ra0);
1471 if (SCM_NULLP (ras))
1472 for (; n-- > 0; i0 += inc0)
1473 scm_array_set_x (ra0, SCM_SUBRF (proc) (RVREF (ra0, i0, e0), SCM_UNDEFINED), SCM_MAKINUM (i0));
1474 else
1475 {
1476 SCM ra1 = SCM_CAR (ras);
1477 scm_sizet i1 = SCM_ARRAY_BASE (ra1);
1478 long inc1 = SCM_ARRAY_DIMS (ra1)->inc;
1479 ra1 = SCM_ARRAY_V (ra1);
1480 for (; n-- > 0; i0 += inc0, i1 += inc1)
1481 scm_array_set_x (ra0, SCM_SUBRF (proc) (RVREF (ra0, i0, e0), RVREF (ra1, i1, e1)),
1482 SCM_MAKINUM (i0));
1483 }
1484 return 1;
1485 }
1486
1487 /* This name is obsolete. Will go away in release 1.5. */
1488 SCM_REGISTER_PROC(s_serial_array_map_x, "serial-array-map!", 2, 0, 1, scm_array_map_x);
1489 SCM_REGISTER_PROC(s_array_map_in_order_x, "array-map-in-order!", 2, 0, 1, scm_array_map_x);
1490
1491
1492 SCM_DEFINE (scm_array_map_x, "array-map!", 2, 0, 1,
1493 (SCM ra0, SCM proc, SCM lra),
1494 "@var{array1}, @dots{} must have the same number of dimensions as\n"
1495 "@var{array0} and have a range for each index which includes the range\n"
1496 "for the corresponding index in @var{array0}. @var{proc} is applied to\n"
1497 "each tuple of elements of @var{array1} @dots{} and the result is stored\n"
1498 "as the corresponding element in @var{array0}. The value returned is\n"
1499 "unspecified. The order of application is unspecified.")
1500 #define FUNC_NAME s_scm_array_map_x
1501 {
1502 SCM_VALIDATE_PROC (2,proc);
1503 switch (SCM_TYP7 (proc))
1504 {
1505 default:
1506 gencase:
1507 scm_ramapc (ramap, proc, ra0, lra, FUNC_NAME);
1508 return SCM_UNSPECIFIED;
1509 case scm_tc7_subr_1:
1510 scm_ramapc (ramap_1, proc, ra0, lra, FUNC_NAME);
1511 return SCM_UNSPECIFIED;
1512 case scm_tc7_subr_2:
1513 case scm_tc7_subr_2o:
1514 scm_ramapc (ramap_2o, proc, ra0, lra, FUNC_NAME);
1515 return SCM_UNSPECIFIED;
1516 case scm_tc7_cxr:
1517 if (!SCM_SUBRF (proc))
1518 goto gencase;
1519 scm_ramapc (ramap_cxr, proc, ra0, lra, FUNC_NAME);
1520 return SCM_UNSPECIFIED;
1521 case scm_tc7_rpsubr:
1522 {
1523 ra_iproc *p;
1524 if (SCM_FALSEP (scm_array_p (ra0, SCM_BOOL_T)))
1525 goto gencase;
1526 scm_array_fill_x (ra0, SCM_BOOL_T);
1527 for (p = ra_rpsubrs; p->name; p++)
1528 if (SCM_EQ_P (proc, p->sproc))
1529 {
1530 while (SCM_NNULLP (lra) && SCM_NNULLP (SCM_CDR (lra)))
1531 {
1532 scm_ramapc (p->vproc, SCM_UNDEFINED, ra0, lra, FUNC_NAME);
1533 lra = SCM_CDR (lra);
1534 }
1535 return SCM_UNSPECIFIED;
1536 }
1537 while (SCM_NNULLP (lra) && SCM_NNULLP (SCM_CDR (lra)))
1538 {
1539 scm_ramapc (ramap_rp, proc, ra0, lra, FUNC_NAME);
1540 lra = SCM_CDR (lra);
1541 }
1542 return SCM_UNSPECIFIED;
1543 }
1544 case scm_tc7_asubr:
1545 if (SCM_NULLP (lra))
1546 {
1547 SCM prot, fill = SCM_SUBRF (proc) (SCM_UNDEFINED, SCM_UNDEFINED);
1548 if (SCM_INUMP(fill))
1549 {
1550 prot = scm_array_prototype (ra0);
1551 if (SCM_INEXP (prot))
1552 fill = scm_makdbl ((double) SCM_INUM (fill), 0.0);
1553 }
1554
1555 scm_array_fill_x (ra0, fill);
1556 }
1557 else
1558 {
1559 SCM tail, ra1 = SCM_CAR (lra);
1560 SCM v0 = (SCM_ARRAYP (ra0) ? SCM_ARRAY_V (ra0) : ra0);
1561 ra_iproc *p;
1562 /* Check to see if order might matter.
1563 This might be an argument for a separate
1564 SERIAL-ARRAY-MAP! */
1565 if (SCM_EQ_P (v0, ra1)
1566 || (SCM_ARRAYP (ra1) && SCM_EQ_P (v0, SCM_ARRAY_V (ra1))))
1567 if (!SCM_EQ_P (ra0, ra1)
1568 || (SCM_ARRAYP(ra0) && !SCM_ARRAY_CONTP(ra0)))
1569 goto gencase;
1570 for (tail = SCM_CDR (lra); SCM_NNULLP (tail); tail = SCM_CDR (tail))
1571 {
1572 ra1 = SCM_CAR (tail);
1573 if (SCM_EQ_P (v0, ra1)
1574 || (SCM_ARRAYP (ra1) && SCM_EQ_P (v0, SCM_ARRAY_V (ra1))))
1575 goto gencase;
1576 }
1577 for (p = ra_asubrs; p->name; p++)
1578 if (SCM_EQ_P (proc, p->sproc))
1579 {
1580 if (!SCM_EQ_P (ra0, SCM_CAR (lra)))
1581 scm_ramapc (scm_array_identity, SCM_UNDEFINED, ra0, scm_cons (SCM_CAR (lra), SCM_EOL), FUNC_NAME);
1582 lra = SCM_CDR (lra);
1583 while (1)
1584 {
1585 scm_ramapc (p->vproc, SCM_UNDEFINED, ra0, lra, FUNC_NAME);
1586 if (SCM_IMP (lra) || SCM_IMP (SCM_CDR (lra)))
1587 return SCM_UNSPECIFIED;
1588 lra = SCM_CDR (lra);
1589 }
1590 }
1591 scm_ramapc (ramap_2o, proc, ra0, lra, FUNC_NAME);
1592 lra = SCM_CDR (lra);
1593 if (SCM_NIMP (lra))
1594 for (lra = SCM_CDR (lra); SCM_NIMP (lra); lra = SCM_CDR (lra))
1595 scm_ramapc (ramap_a, proc, ra0, lra, FUNC_NAME);
1596 }
1597 return SCM_UNSPECIFIED;
1598 }
1599 }
1600 #undef FUNC_NAME
1601
1602
1603 static int
1604 rafe (SCM ra0,SCM proc,SCM ras)
1605 {
1606 long i = SCM_ARRAY_DIMS (ra0)->lbnd;
1607 scm_sizet i0 = SCM_ARRAY_BASE (ra0);
1608 long inc0 = SCM_ARRAY_DIMS (ra0)->inc;
1609 long n = SCM_ARRAY_DIMS (ra0)->ubnd;
1610 ra0 = SCM_ARRAY_V (ra0);
1611 if (SCM_NULLP (ras))
1612 for (; i <= n; i++, i0 += inc0)
1613 scm_apply (proc, scm_cvref (ra0, i0, SCM_UNDEFINED), scm_listofnull);
1614 else
1615 {
1616 SCM ra1 = SCM_CAR (ras);
1617 SCM args, *ve = &ras;
1618 scm_sizet k, i1 = SCM_ARRAY_BASE (ra1);
1619 long inc1 = SCM_ARRAY_DIMS (ra1)->inc;
1620 ra1 = SCM_ARRAY_V (ra1);
1621 ras = SCM_CDR (ras);
1622 if (SCM_NULLP(ras))
1623 ras = scm_nullvect;
1624 else
1625 {
1626 ras = scm_vector (ras);
1627 ve = SCM_VELTS (ras);
1628 }
1629 for (; i <= n; i++, i0 += inc0, i1 += inc1)
1630 {
1631 args = SCM_EOL;
1632 for (k = SCM_LENGTH (ras); k--;)
1633 args = scm_cons (scm_uniform_vector_ref (ve[k], SCM_MAKINUM (i)), args);
1634 args = scm_cons2 (scm_cvref (ra0, i0, SCM_UNDEFINED), scm_cvref (ra1, i1, SCM_UNDEFINED), args);
1635 scm_apply (proc, args, SCM_EOL);
1636 }
1637 }
1638 return 1;
1639 }
1640
1641
1642 SCM_DEFINE (scm_array_for_each, "array-for-each", 2, 0, 1,
1643 (SCM proc, SCM ra0, SCM lra),
1644 "@var{proc} is applied to each tuple of elements of @var{array0} @dots{}\n"
1645 "in row-major order. The value returned is unspecified.")
1646 #define FUNC_NAME s_scm_array_for_each
1647 {
1648 SCM_VALIDATE_PROC (1,proc);
1649 scm_ramapc (rafe, proc, ra0, lra, FUNC_NAME);
1650 return SCM_UNSPECIFIED;
1651 }
1652 #undef FUNC_NAME
1653
1654 SCM_DEFINE (scm_array_index_map_x, "array-index-map!", 2, 0, 0,
1655 (SCM ra, SCM proc),
1656 "applies @var{proc} to the indices of each element of @var{array} in\n"
1657 "turn, storing the result in the corresponding element. The value\n"
1658 "returned and the order of application are unspecified.\n\n"
1659 "One can implement @var{array-indexes} as\n"
1660 "@example\n"
1661 "(define (array-indexes array)\n"
1662 " (let ((ra (apply make-array #f (array-shape array))))\n"
1663 " (array-index-map! ra (lambda x x))\n"
1664 " ra))\n"
1665 "@end example\n"
1666 "Another example:\n"
1667 "@example\n"
1668 "(define (apl:index-generator n)\n"
1669 " (let ((v (make-uniform-vector n 1)))\n"
1670 " (array-index-map! v (lambda (i) i))\n"
1671 " v))\n"
1672 "@end example")
1673 #define FUNC_NAME s_scm_array_index_map_x
1674 {
1675 scm_sizet i;
1676 SCM_VALIDATE_NIM (1,ra);
1677 SCM_VALIDATE_PROC (2,proc);
1678 switch (SCM_TYP7(ra))
1679 {
1680 default:
1681 badarg:SCM_WTA (1,ra);
1682 case scm_tc7_vector:
1683 case scm_tc7_wvect:
1684 {
1685 SCM *ve = SCM_VELTS (ra);
1686 for (i = 0; i < SCM_LENGTH (ra); i++)
1687 ve[i] = scm_apply (proc, SCM_MAKINUM (i), scm_listofnull);
1688 return SCM_UNSPECIFIED;
1689 }
1690 case scm_tc7_string:
1691 case scm_tc7_byvect:
1692 case scm_tc7_bvect:
1693 case scm_tc7_uvect:
1694 case scm_tc7_ivect:
1695 case scm_tc7_svect:
1696 #ifdef HAVE_LONG_LONGS
1697 case scm_tc7_llvect:
1698 #endif
1699 case scm_tc7_fvect:
1700 case scm_tc7_dvect:
1701 case scm_tc7_cvect:
1702 for (i = 0; i < SCM_LENGTH (ra); i++)
1703 scm_array_set_x (ra, scm_apply (proc, SCM_MAKINUM (i), scm_listofnull),
1704 SCM_MAKINUM (i));
1705 return SCM_UNSPECIFIED;
1706 case scm_tc7_smob:
1707 SCM_ASRTGO (SCM_ARRAYP (ra), badarg);
1708 {
1709 SCM args = SCM_EOL;
1710 SCM inds = scm_make_uve (SCM_ARRAY_NDIM (ra), SCM_MAKINUM (-1L));
1711 long *vinds = (long *) SCM_VELTS (inds);
1712 int j, k, kmax = SCM_ARRAY_NDIM (ra) - 1;
1713 if (kmax < 0)
1714 return scm_array_set_x (ra, scm_apply(proc, SCM_EOL, SCM_EOL),
1715 SCM_EOL);
1716 for (k = 0; k <= kmax; k++)
1717 vinds[k] = SCM_ARRAY_DIMS (ra)[k].lbnd;
1718 k = kmax;
1719 do
1720 {
1721 if (k == kmax)
1722 {
1723 vinds[k] = SCM_ARRAY_DIMS (ra)[k].lbnd;
1724 i = cind (ra, inds);
1725 for (; vinds[k] <= SCM_ARRAY_DIMS (ra)[k].ubnd; vinds[k]++)
1726 {
1727 for (j = kmax + 1, args = SCM_EOL; j--;)
1728 args = scm_cons (SCM_MAKINUM (vinds[j]), args);
1729 scm_array_set_x (SCM_ARRAY_V (ra),
1730 scm_apply (proc, args, SCM_EOL),
1731 SCM_MAKINUM (i));
1732 i += SCM_ARRAY_DIMS (ra)[k].inc;
1733 }
1734 k--;
1735 continue;
1736 }
1737 if (vinds[k] < SCM_ARRAY_DIMS (ra)[k].ubnd)
1738 {
1739 vinds[k]++;
1740 k++;
1741 continue;
1742 }
1743 vinds[k] = SCM_ARRAY_DIMS (ra)[k].lbnd - 1;
1744 k--;
1745 }
1746 while (k >= 0);
1747 return SCM_UNSPECIFIED;
1748 }
1749 }
1750 }
1751 #undef FUNC_NAME
1752
1753
1754 static int
1755 raeql_1 (SCM ra0,SCM as_equal,SCM ra1)
1756 {
1757 SCM e0 = SCM_UNDEFINED, e1 = SCM_UNDEFINED;
1758 scm_sizet i0 = 0, i1 = 0;
1759 long inc0 = 1, inc1 = 1;
1760 scm_sizet n = SCM_LENGTH (ra0);
1761 ra1 = SCM_CAR (ra1);
1762 if (SCM_ARRAYP(ra0))
1763 {
1764 n = SCM_ARRAY_DIMS (ra0)->ubnd - SCM_ARRAY_DIMS (ra0)->lbnd + 1;
1765 i0 = SCM_ARRAY_BASE (ra0);
1766 inc0 = SCM_ARRAY_DIMS (ra0)->inc;
1767 ra0 = SCM_ARRAY_V (ra0);
1768 }
1769 if (SCM_ARRAYP (ra1))
1770 {
1771 i1 = SCM_ARRAY_BASE (ra1);
1772 inc1 = SCM_ARRAY_DIMS (ra1)->inc;
1773 ra1 = SCM_ARRAY_V (ra1);
1774 }
1775 switch (SCM_TYP7 (ra0))
1776 {
1777 case scm_tc7_vector:
1778 case scm_tc7_wvect:
1779 default:
1780 for (; n--; i0 += inc0, i1 += inc1)
1781 {
1782 if (SCM_FALSEP (as_equal))
1783 {
1784 if (SCM_FALSEP (scm_array_equal_p (RVREF (ra0, i0, e0), RVREF (ra1, i1, e1))))
1785 return 0;
1786 }
1787 else if (SCM_FALSEP (scm_equal_p (RVREF (ra0, i0, e0), RVREF (ra1, i1, e1))))
1788 return 0;
1789 }
1790 return 1;
1791 case scm_tc7_string:
1792 case scm_tc7_byvect:
1793 {
1794 char *v0 = SCM_CHARS (ra0) + i0;
1795 char *v1 = SCM_CHARS (ra1) + i1;
1796 for (; n--; v0 += inc0, v1 += inc1)
1797 if (*v0 != *v1)
1798 return 0;
1799 return 1;
1800 }
1801 case scm_tc7_bvect:
1802 for (; n--; i0 += inc0, i1 += inc1)
1803 if (SCM_BITVEC_REF (ra0, i0) != SCM_BITVEC_REF (ra1, i1))
1804 return 0;
1805 return 1;
1806 case scm_tc7_uvect:
1807 case scm_tc7_ivect:
1808 {
1809 long *v0 = (long *) SCM_VELTS (ra0) + i0;
1810 long *v1 = (long *) SCM_VELTS (ra1) + i1;
1811 for (; n--; v0 += inc0, v1 += inc1)
1812 if (*v0 != *v1)
1813 return 0;
1814 return 1;
1815 }
1816 case scm_tc7_svect:
1817 {
1818 short *v0 = (short *) SCM_VELTS (ra0) + i0;
1819 short *v1 = (short *) SCM_VELTS (ra1) + i1;
1820 for (; n--; v0 += inc0, v1 += inc1)
1821 if (*v0 != *v1)
1822 return 0;
1823 return 1;
1824 }
1825 #ifdef HAVE_LONG_LONGS
1826 case scm_tc7_llvect:
1827 {
1828 long long *v0 = (long long *) SCM_VELTS (ra0) + i0;
1829 long long *v1 = (long long *) SCM_VELTS (ra1) + i1;
1830 for (; n--; v0 += inc0, v1 += inc1)
1831 if (*v0 != *v1)
1832 return 0;
1833 return 1;
1834 }
1835 #endif
1836 case scm_tc7_fvect:
1837 {
1838 float *v0 = (float *) SCM_VELTS (ra0) + i0;
1839 float *v1 = (float *) SCM_VELTS (ra1) + i1;
1840 for (; n--; v0 += inc0, v1 += inc1)
1841 if (*v0 != *v1)
1842 return 0;
1843 return 1;
1844 }
1845 case scm_tc7_dvect:
1846 {
1847 double *v0 = (double *) SCM_VELTS (ra0) + i0;
1848 double *v1 = (double *) SCM_VELTS (ra1) + i1;
1849 for (; n--; v0 += inc0, v1 += inc1)
1850 if (*v0 != *v1)
1851 return 0;
1852 return 1;
1853 }
1854 case scm_tc7_cvect:
1855 {
1856 double (*v0)[2] = (double (*)[2]) SCM_VELTS (ra0) + i0;
1857 double (*v1)[2] = (double (*)[2]) SCM_VELTS (ra1) + i1;
1858 for (; n--; v0 += inc0, v1 += inc1)
1859 {
1860 if ((*v0)[0] != (*v1)[0])
1861 return 0;
1862 if ((*v0)[1] != (*v1)[1])
1863 return 0;
1864 }
1865 return 1;
1866 }
1867 }
1868 }
1869
1870
1871
1872 static int
1873 raeql (SCM ra0,SCM as_equal,SCM ra1)
1874 {
1875 SCM v0 = ra0, v1 = ra1;
1876 scm_array_dim dim0, dim1;
1877 scm_array_dim *s0 = &dim0, *s1 = &dim1;
1878 scm_sizet bas0 = 0, bas1 = 0;
1879 int k, unroll = 1, vlen = 1, ndim = 1;
1880 if (SCM_ARRAYP (ra0))
1881 {
1882 ndim = SCM_ARRAY_NDIM (ra0);
1883 s0 = SCM_ARRAY_DIMS (ra0);
1884 bas0 = SCM_ARRAY_BASE (ra0);
1885 v0 = SCM_ARRAY_V (ra0);
1886 }
1887 else
1888 {
1889 s0->inc = 1;
1890 s0->lbnd = 0;
1891 s0->ubnd = SCM_LENGTH (v0) - 1;
1892 unroll = 0;
1893 }
1894 if (SCM_ARRAYP (ra1))
1895 {
1896 if (ndim != SCM_ARRAY_NDIM (ra1))
1897 return 0;
1898 s1 = SCM_ARRAY_DIMS (ra1);
1899 bas1 = SCM_ARRAY_BASE (ra1);
1900 v1 = SCM_ARRAY_V (ra1);
1901 }
1902 else
1903 {
1904 /*
1905 Huh ? Schizophrenic return type. --hwn
1906 */
1907 if (1 != ndim)
1908 return 0;
1909 s1->inc = 1;
1910 s1->lbnd = 0;
1911 s1->ubnd = SCM_LENGTH (v1) - 1;
1912 unroll = 0;
1913 }
1914 if (SCM_TYP7 (v0) != SCM_TYP7 (v1))
1915 return 0;
1916 for (k = ndim; k--;)
1917 {
1918 if (s0[k].lbnd != s1[k].lbnd || s0[k].ubnd != s1[k].ubnd)
1919 return 0;
1920 if (unroll)
1921 {
1922 unroll = (s0[k].inc == s1[k].inc);
1923 vlen *= s0[k].ubnd - s1[k].lbnd + 1;
1924 }
1925 }
1926 if (unroll && bas0 == bas1 && SCM_EQ_P (v0, v1))
1927 return 1;
1928 return scm_ramapc (raeql_1, as_equal, ra0, scm_cons (ra1, SCM_EOL), "");
1929 }
1930
1931
1932 SCM
1933 scm_raequal (SCM ra0, SCM ra1)
1934 {
1935 return SCM_BOOL(raeql (ra0, SCM_BOOL_T, ra1));
1936 }
1937
1938 #if 0
1939 /* GJB:FIXME:: Why not use SCM_DEFINE1 for array-equal? */
1940 SCM_DEFINE1 (scm_array_equal_p, "array-equal?", scm_tc7_rpsubr,
1941 (SCM ra0, SCM ra1),
1942 "Returns @code{#t} iff all arguments are arrays with the same shape, the\n"
1943 "same type, and have corresponding elements which are either\n"
1944 "@code{equal?} or @code{array-equal?}. This function differs from\n"
1945 "@code{equal?} in that a one dimensional shared array may be\n"
1946 "@var{array-equal?} but not @var{equal?} to a vector or uniform vector.")
1947 #define FUNC_NAME s_scm_array_equal_p
1948 {
1949 }
1950 #undef FUNC_NAME
1951 #endif
1952
1953 static char s_array_equal_p[] = "array-equal?";
1954
1955
1956 SCM
1957 scm_array_equal_p (SCM ra0, SCM ra1)
1958 {
1959 if (SCM_IMP (ra0) || SCM_IMP (ra1))
1960 callequal:return scm_equal_p (ra0, ra1);
1961 switch (SCM_TYP7(ra0))
1962 {
1963 default:
1964 goto callequal;
1965 case scm_tc7_bvect:
1966 case scm_tc7_string:
1967 case scm_tc7_byvect:
1968 case scm_tc7_uvect:
1969 case scm_tc7_ivect:
1970 case scm_tc7_fvect:
1971 case scm_tc7_dvect:
1972 case scm_tc7_cvect:
1973 case scm_tc7_vector:
1974 case scm_tc7_wvect:
1975 break;
1976 case scm_tc7_smob:
1977 if (!SCM_ARRAYP (ra0))
1978 goto callequal;
1979 }
1980 switch (SCM_TYP7 (ra1))
1981 {
1982 default:
1983 goto callequal;
1984 case scm_tc7_bvect:
1985 case scm_tc7_string:
1986 case scm_tc7_byvect:
1987 case scm_tc7_uvect:
1988 case scm_tc7_ivect:
1989 case scm_tc7_fvect:
1990 case scm_tc7_dvect:
1991 case scm_tc7_cvect:
1992 case scm_tc7_vector:
1993 case scm_tc7_wvect:
1994 break;
1995 case scm_tc7_smob:
1996 if (!SCM_ARRAYP (ra1))
1997 goto callequal;
1998 }
1999 return SCM_BOOL(raeql (ra0, SCM_BOOL_F, ra1));
2000 }
2001
2002
2003
2004 static void
2005 init_raprocs (ra_iproc *subra)
2006 {
2007 for (; subra->name; subra++)
2008 subra->sproc = SCM_CDR (scm_intern (subra->name, strlen (subra->name)));
2009 }
2010
2011
2012 void
2013 scm_init_ramap ()
2014 {
2015 init_raprocs (ra_rpsubrs);
2016 init_raprocs (ra_asubrs);
2017 scm_make_subr (s_array_equal_p, scm_tc7_rpsubr, scm_array_equal_p);
2018 scm_smobs[0x0ff & (scm_tc16_array >> 8)].equalp = scm_raequal;
2019 #include "libguile/ramap.x"
2020 scm_add_feature (s_scm_array_for_each);
2021 }
2022
2023 /*
2024 Local Variables:
2025 c-file-style: "gnu"
2026 End:
2027 */