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