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