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