* Unified some rest argument checking and handling.
[bpt/guile.git] / libguile / unif.c
1 /* Copyright (C) 1995,1996,1997,1998, 2000 Free Software Foundation, Inc.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
17 *
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
20 *
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
26 *
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
29 *
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
37 *
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
40 * If you do not wish that, delete this exception notice. */
41
42 /* Software engineering face-lift by Greg J. Badros, 11-Dec-1999,
43 gjb@cs.washington.edu, http://www.cs.washington.edu/homes/gjb */
44
45 /*
46 This file has code for arrays in lots of variants (double, integer,
47 unsigned etc. ). It suffers from hugely repetitive code because
48 there is similar (but different) code for every variant included. (urg.)
49
50 --hwn
51 */
52 \f
53
54 #include <stdio.h>
55 #include "libguile/_scm.h"
56 #include "libguile/chars.h"
57 #include "libguile/eval.h"
58 #include "libguile/fports.h"
59 #include "libguile/smob.h"
60 #include "libguile/strop.h"
61 #include "libguile/feature.h"
62 #include "libguile/root.h"
63 #include "libguile/strings.h"
64 #include "libguile/vectors.h"
65
66 #include "libguile/validate.h"
67 #include "libguile/unif.h"
68 #include "libguile/ramap.h"
69
70 #ifdef HAVE_UNISTD_H
71 #include <unistd.h>
72 #endif
73
74 \f
75 /* The set of uniform scm_vector types is:
76 * Vector of: Called:
77 * unsigned char string
78 * char byvect
79 * boolean bvect
80 * signed long ivect
81 * unsigned long uvect
82 * float fvect
83 * double dvect
84 * complex double cvect
85 * short svect
86 * long long llvect
87 */
88
89 long scm_tc16_array;
90
91 /* return the size of an element in a uniform array or 0 if type not
92 found. */
93 scm_sizet
94 scm_uniform_element_size (SCM obj)
95 {
96 scm_sizet result;
97
98 switch (SCM_TYP7 (obj))
99 {
100 case scm_tc7_bvect:
101 case scm_tc7_uvect:
102 case scm_tc7_ivect:
103 result = sizeof (long);
104 break;
105
106 case scm_tc7_byvect:
107 result = sizeof (char);
108 break;
109
110 case scm_tc7_svect:
111 result = sizeof (short);
112 break;
113
114 #ifdef HAVE_LONG_LONGS
115 case scm_tc7_llvect:
116 result = sizeof (long_long);
117 break;
118 #endif
119
120 case scm_tc7_fvect:
121 result = sizeof (float);
122 break;
123
124 case scm_tc7_dvect:
125 result = sizeof (double);
126 break;
127
128 case scm_tc7_cvect:
129 result = 2 * sizeof (double);
130 break;
131
132 default:
133 result = 0;
134 }
135 return result;
136 }
137
138 /* Silly function used not to modify the semantics of the silly
139 * prototype system in order to be backward compatible.
140 */
141 static int
142 singp (SCM obj)
143 {
144 if (!SCM_SLOPPY_REALP (obj))
145 return 0;
146 else
147 {
148 double x = SCM_REAL_VALUE (obj);
149 float fx = x;
150 return (- SCM_FLTMAX < x) && (x < SCM_FLTMAX) && (fx == x);
151 }
152 }
153
154 SCM
155 scm_make_uve (long k, SCM prot)
156 {
157 SCM v;
158 long i, type;
159 if (SCM_TRUE_P (prot))
160 {
161 i = sizeof (long) * ((k + SCM_LONG_BIT - 1) / SCM_LONG_BIT);
162 type = scm_tc7_bvect;
163 }
164 else if (SCM_CHARP (prot) && (SCM_CHAR (prot) == '\0'))
165 {
166 i = sizeof (char) * k;
167 type = scm_tc7_byvect;
168 }
169 else if (SCM_CHARP (prot))
170 {
171 i = sizeof (char) * k;
172 type = scm_tc7_string;
173 }
174 else if (SCM_INUMP (prot))
175 {
176 i = sizeof (long) * k;
177 if (SCM_INUM (prot) > 0)
178 type = scm_tc7_uvect;
179 else
180 type = scm_tc7_ivect;
181 }
182 else if (SCM_SYMBOLP (prot) && (1 == SCM_LENGTH (prot)))
183 {
184 char s;
185
186 s = SCM_CHARS (prot)[0];
187 if (s == 's')
188 {
189 i = sizeof (short) * k;
190 type = scm_tc7_svect;
191 }
192 #ifdef HAVE_LONG_LONGS
193 else if (s == 'l')
194 {
195 i = sizeof (long_long) * k;
196 type = scm_tc7_llvect;
197 }
198 #endif
199 else
200 {
201 return scm_make_vector (SCM_MAKINUM (k), SCM_UNDEFINED);
202 }
203 }
204 else
205 if (SCM_IMP (prot) || !SCM_INEXACTP (prot))
206 /* Huge non-unif vectors are NOT supported. */
207 /* no special scm_vector */
208 return scm_make_vector (SCM_MAKINUM (k), SCM_UNDEFINED);
209 else if (singp (prot))
210 {
211 i = sizeof (float) * k;
212 type = scm_tc7_fvect;
213 }
214 else if (SCM_COMPLEXP (prot))
215 {
216 i = 2 * sizeof (double) * k;
217 type = scm_tc7_cvect;
218 }
219 else
220 {
221 i = sizeof (double) * k;
222 type = scm_tc7_dvect;
223 }
224
225 SCM_NEWCELL (v);
226 SCM_DEFER_INTS;
227 SCM_SETCHARS (v, (char *) scm_must_malloc (i ? i : 1, "vector"));
228 SCM_SETLENGTH (v, (k < SCM_LENGTH_MAX ? k : SCM_LENGTH_MAX), type);
229 SCM_ALLOW_INTS;
230 return v;
231 }
232
233 SCM_DEFINE (scm_uniform_vector_length, "uniform-vector-length", 1, 0, 0,
234 (SCM v),
235 "Returns the number of elements in @var{uve}.")
236 #define FUNC_NAME s_scm_uniform_vector_length
237 {
238 SCM_ASRTGO (SCM_NIMP (v), badarg1);
239 switch SCM_TYP7
240 (v)
241 {
242 default:
243 badarg1:SCM_WTA(1,v);
244 case scm_tc7_bvect:
245 case scm_tc7_string:
246 case scm_tc7_byvect:
247 case scm_tc7_uvect:
248 case scm_tc7_ivect:
249 case scm_tc7_fvect:
250 case scm_tc7_dvect:
251 case scm_tc7_cvect:
252 case scm_tc7_vector:
253 case scm_tc7_wvect:
254 case scm_tc7_svect:
255 #ifdef HAVE_LONG_LONGS
256 case scm_tc7_llvect:
257 #endif
258 return SCM_MAKINUM (SCM_LENGTH (v));
259 }
260 }
261 #undef FUNC_NAME
262
263 SCM_DEFINE (scm_array_p, "array?", 1, 1, 0,
264 (SCM v, SCM prot),
265 "Returns @code{#t} if the @var{obj} is an array, and @code{#f} if not.\n\n"
266 "The @var{prototype} argument is used with uniform arrays and is described\n"
267 "elsewhere.")
268 #define FUNC_NAME s_scm_array_p
269 {
270 int nprot;
271 int enclosed;
272 nprot = SCM_UNBNDP (prot);
273 enclosed = 0;
274 if (SCM_IMP (v))
275 return SCM_BOOL_F;
276
277 while (SCM_TYP7 (v) == scm_tc7_smob)
278 {
279 if (!SCM_ARRAYP (v))
280 return SCM_BOOL_F;
281 if (nprot)
282 return SCM_BOOL_T;
283 if (enclosed++)
284 return SCM_BOOL_F;
285 v = SCM_ARRAY_V (v);
286 }
287 if (nprot)
288 return SCM_BOOL(nprot);
289 else
290 {
291 int protp = 0;
292
293 switch (SCM_TYP7 (v))
294 {
295 case scm_tc7_bvect:
296 protp = (SCM_TRUE_P (prot));
297 case scm_tc7_string:
298 protp = SCM_CHARP(prot) && (SCM_CHAR (prot) != '\0');
299 case scm_tc7_byvect:
300 protp = SCM_EQ_P (prot, SCM_MAKE_CHAR ('\0'));
301 case scm_tc7_uvect:
302 protp = SCM_INUMP(prot) && SCM_INUM(prot)>0;
303 case scm_tc7_ivect:
304 protp = SCM_INUMP(prot) && SCM_INUM(prot)<=0;
305
306 case scm_tc7_svect:
307 protp = SCM_SYMBOLP (prot)
308 && (1 == SCM_LENGTH (prot))
309 && ('s' == SCM_CHARS (prot)[0]);
310 #ifdef HAVE_LONG_LONGS
311 case scm_tc7_llvect:
312 protp = SCM_SYMBOLP (prot)
313 && (1 == SCM_LENGTH (prot))
314 && ('s' == SCM_CHARS (prot)[0]);
315 #endif
316 case scm_tc7_fvect:
317 protp = singp (prot);
318 case scm_tc7_dvect:
319 protp = SCM_REALP(prot);
320 case scm_tc7_cvect:
321 protp = SCM_COMPLEXP(prot);
322 case scm_tc7_vector:
323 case scm_tc7_wvect:
324 protp = SCM_NULLP(prot);
325 default:
326 /* no default */
327 ;
328 }
329 return SCM_BOOL(protp);
330 }
331 }
332 #undef FUNC_NAME
333
334
335 SCM_DEFINE (scm_array_rank, "array-rank", 1, 0, 0,
336 (SCM ra),
337 "Returns the number of dimensions of @var{obj}. If @var{obj} is not an\n"
338 "array, @code{0} is returned.")
339 #define FUNC_NAME s_scm_array_rank
340 {
341 if (SCM_IMP (ra))
342 return SCM_INUM0;
343 switch (SCM_TYP7 (ra))
344 {
345 default:
346 return SCM_INUM0;
347 case scm_tc7_string:
348 case scm_tc7_vector:
349 case scm_tc7_wvect:
350 case scm_tc7_byvect:
351 case scm_tc7_uvect:
352 case scm_tc7_ivect:
353 case scm_tc7_fvect:
354 case scm_tc7_cvect:
355 case scm_tc7_dvect:
356 #ifdef HAVE_LONG_LONGS
357 case scm_tc7_llvect:
358 #endif
359 case scm_tc7_svect:
360 return SCM_MAKINUM (1L);
361 case scm_tc7_smob:
362 if (SCM_ARRAYP (ra))
363 return SCM_MAKINUM (SCM_ARRAY_NDIM (ra));
364 return SCM_INUM0;
365 }
366 }
367 #undef FUNC_NAME
368
369
370 SCM_DEFINE (scm_array_dimensions, "array-dimensions", 1, 0, 0,
371 (SCM ra),
372 "@code{Array-dimensions} is similar to @code{array-shape} but replaces\n"
373 "elements with a @code{0} minimum with one greater than the maximum. So:\n"
374 "@example\n"
375 "(array-dimensions (make-array 'foo '(-1 3) 5)) @result{} ((-1 3) 5)\n"
376 "@end example")
377 #define FUNC_NAME s_scm_array_dimensions
378 {
379 SCM res = SCM_EOL;
380 scm_sizet k;
381 scm_array_dim *s;
382 if (SCM_IMP (ra))
383 return SCM_BOOL_F;
384 switch (SCM_TYP7 (ra))
385 {
386 default:
387 return SCM_BOOL_F;
388 case scm_tc7_string:
389 case scm_tc7_vector:
390 case scm_tc7_wvect:
391 case scm_tc7_bvect:
392 case scm_tc7_byvect:
393 case scm_tc7_uvect:
394 case scm_tc7_ivect:
395 case scm_tc7_fvect:
396 case scm_tc7_cvect:
397 case scm_tc7_dvect:
398 case scm_tc7_svect:
399 #ifdef HAVE_LONG_LONGS
400 case scm_tc7_llvect:
401 #endif
402 return scm_cons (SCM_MAKINUM (SCM_LENGTH (ra)), SCM_EOL);
403 case scm_tc7_smob:
404 if (!SCM_ARRAYP (ra))
405 return SCM_BOOL_F;
406 k = SCM_ARRAY_NDIM (ra);
407 s = SCM_ARRAY_DIMS (ra);
408 while (k--)
409 res = scm_cons (s[k].lbnd
410 ? scm_cons2 (SCM_MAKINUM (s[k].lbnd),
411 SCM_MAKINUM (s[k].ubnd),
412 SCM_EOL)
413 : SCM_MAKINUM (1 + s[k].ubnd),
414 res);
415 return res;
416 }
417 }
418 #undef FUNC_NAME
419
420
421 SCM_DEFINE (scm_shared_array_root, "shared-array-root", 1, 0, 0,
422 (SCM ra),
423 "Return the root vector of a shared array.")
424 #define FUNC_NAME s_scm_shared_array_root
425 {
426 SCM_ASSERT (SCM_ARRAYP (ra), ra, SCM_ARG1, FUNC_NAME);
427 return SCM_ARRAY_V (ra);
428 }
429 #undef FUNC_NAME
430
431
432 SCM_DEFINE (scm_shared_array_offset, "shared-array-offset", 1, 0, 0,
433 (SCM ra),
434 "Return the root vector index of the first element in the array.")
435 #define FUNC_NAME s_scm_shared_array_offset
436 {
437 SCM_ASSERT (SCM_ARRAYP (ra), ra, SCM_ARG1, FUNC_NAME);
438 return SCM_MAKINUM (SCM_ARRAY_BASE (ra));
439 }
440 #undef FUNC_NAME
441
442
443 SCM_DEFINE (scm_shared_array_increments, "shared-array-increments", 1, 0, 0,
444 (SCM ra),
445 "For each dimension, return the distance between elements in the root vector.")
446 #define FUNC_NAME s_scm_shared_array_increments
447 {
448 SCM res = SCM_EOL;
449 scm_sizet k;
450 scm_array_dim *s;
451 SCM_ASSERT (SCM_ARRAYP (ra), ra, SCM_ARG1, FUNC_NAME);
452 k = SCM_ARRAY_NDIM (ra);
453 s = SCM_ARRAY_DIMS (ra);
454 while (k--)
455 res = scm_cons (SCM_MAKINUM (s[k].inc), res);
456 return res;
457 }
458 #undef FUNC_NAME
459
460
461 static char s_bad_ind[] = "Bad scm_array index";
462
463
464 long
465 scm_aind (SCM ra, SCM args, const char *what)
466 {
467 SCM ind;
468 register long j;
469 register scm_sizet pos = SCM_ARRAY_BASE (ra);
470 register scm_sizet k = SCM_ARRAY_NDIM (ra);
471 scm_array_dim *s = SCM_ARRAY_DIMS (ra);
472 if (SCM_INUMP (args))
473 {
474 SCM_ASSERT (1 == k, scm_makfrom0str (what), SCM_WNA, NULL);
475 return pos + (SCM_INUM (args) - s->lbnd) * (s->inc);
476 }
477 while (k && SCM_NIMP (args))
478 {
479 ind = SCM_CAR (args);
480 args = SCM_CDR (args);
481 SCM_ASSERT (SCM_INUMP (ind), ind, s_bad_ind, what);
482 j = SCM_INUM (ind);
483 SCM_ASSERT (j >= (s->lbnd) && j <= (s->ubnd), ind, SCM_OUTOFRANGE, what);
484 pos += (j - s->lbnd) * (s->inc);
485 k--;
486 s++;
487 }
488 SCM_ASSERT (0 == k && SCM_NULLP (args), scm_makfrom0str (what), SCM_WNA,
489 NULL);
490 return pos;
491 }
492
493
494
495 SCM
496 scm_make_ra (int ndim)
497 {
498 SCM ra;
499 SCM_NEWCELL (ra);
500 SCM_DEFER_INTS;
501 SCM_NEWSMOB(ra, ((long) ndim << 17) + scm_tc16_array,
502 scm_must_malloc ((long) (sizeof (scm_array) + ndim * sizeof (scm_array_dim)),
503 "array"));
504 SCM_ARRAY_V (ra) = scm_nullvect;
505 SCM_ALLOW_INTS;
506 return ra;
507 }
508
509 static char s_bad_spec[] = "Bad scm_array dimension";
510 /* Increments will still need to be set. */
511
512
513 SCM
514 scm_shap2ra (SCM args, const char *what)
515 {
516 scm_array_dim *s;
517 SCM ra, spec, sp;
518 int ndim = scm_ilength (args);
519 SCM_ASSERT (0 <= ndim, args, s_bad_spec, what);
520 ra = scm_make_ra (ndim);
521 SCM_ARRAY_BASE (ra) = 0;
522 s = SCM_ARRAY_DIMS (ra);
523 for (; SCM_NIMP (args); s++, args = SCM_CDR (args))
524 {
525 spec = SCM_CAR (args);
526 if (SCM_IMP (spec))
527
528 {
529 SCM_ASSERT (SCM_INUMP (spec) && SCM_INUM (spec) >= 0, spec,
530 s_bad_spec, what);
531 s->lbnd = 0;
532 s->ubnd = SCM_INUM (spec) - 1;
533 s->inc = 1;
534 }
535 else
536 {
537 SCM_ASSERT (SCM_CONSP (spec) && SCM_INUMP (SCM_CAR (spec)), spec,
538 s_bad_spec, what);
539 s->lbnd = SCM_INUM (SCM_CAR (spec));
540 sp = SCM_CDR (spec);
541 SCM_ASSERT (SCM_CONSP (sp)
542 && SCM_INUMP (SCM_CAR (sp)) && SCM_NULLP (SCM_CDR (sp)),
543 spec, s_bad_spec, what);
544 s->ubnd = SCM_INUM (SCM_CAR (sp));
545 s->inc = 1;
546 }
547 }
548 return ra;
549 }
550
551 SCM_DEFINE (scm_dimensions_to_uniform_array, "dimensions->uniform-array", 2, 1, 0,
552 (SCM dims, SCM prot, SCM fill),
553 "@deffnx primitive make-uniform-vector length prototype [fill]\n"
554 "Creates and returns a uniform array or vector of type corresponding to\n"
555 "@var{prototype} with dimensions @var{dims} or length @var{length}. If\n"
556 "@var{fill} is supplied, it's used to fill the array, otherwise \n"
557 "@var{prototype} is used.")
558 #define FUNC_NAME s_scm_dimensions_to_uniform_array
559 {
560 scm_sizet k, vlen = 1;
561 long rlen = 1;
562 scm_array_dim *s;
563 SCM ra;
564 if (SCM_INUMP (dims))
565 {
566 if (SCM_INUM (dims) < SCM_LENGTH_MAX)
567 {
568 SCM answer = scm_make_uve (SCM_INUM (dims), prot);
569
570 if (!SCM_UNBNDP (fill))
571 scm_array_fill_x (answer, fill);
572 else if (SCM_SYMBOLP (prot))
573 scm_array_fill_x (answer, SCM_MAKINUM (0));
574 else
575 scm_array_fill_x (answer, prot);
576 return answer;
577 }
578 else
579 dims = scm_cons (dims, SCM_EOL);
580 }
581 SCM_ASSERT (SCM_NULLP (dims) || SCM_CONSP (dims),
582 dims, SCM_ARG1, FUNC_NAME);
583 ra = scm_shap2ra (dims, FUNC_NAME);
584 SCM_SETOR_CAR (ra, SCM_ARRAY_CONTIGUOUS);
585 s = SCM_ARRAY_DIMS (ra);
586 k = SCM_ARRAY_NDIM (ra);
587 while (k--)
588 {
589 s[k].inc = (rlen > 0 ? rlen : 0);
590 rlen = (s[k].ubnd - s[k].lbnd + 1) * s[k].inc;
591 vlen *= (s[k].ubnd - s[k].lbnd + 1);
592 }
593 if (rlen < SCM_LENGTH_MAX)
594 SCM_ARRAY_V (ra) = scm_make_uve ((rlen > 0 ? rlen : 0L), prot);
595 else
596 {
597 scm_sizet bit;
598 switch (SCM_TYP7 (scm_make_uve (0L, prot)))
599 {
600 default:
601 bit = SCM_LONG_BIT;
602 break;
603 case scm_tc7_bvect:
604 bit = 1;
605 break;
606 case scm_tc7_string:
607 bit = SCM_CHAR_BIT;
608 break;
609 case scm_tc7_fvect:
610 bit = sizeof (float) * SCM_CHAR_BIT / sizeof (char);
611 break;
612 case scm_tc7_dvect:
613 bit = sizeof (double) * SCM_CHAR_BIT / sizeof (char);
614 break;
615 case scm_tc7_cvect:
616 bit = 2 * sizeof (double) * SCM_CHAR_BIT / sizeof (char);
617 break;
618 }
619 SCM_ARRAY_BASE (ra) = (SCM_LONG_BIT + bit - 1) / bit;
620 rlen += SCM_ARRAY_BASE (ra);
621 SCM_ARRAY_V (ra) = scm_make_uve (rlen, prot);
622 *((long *) SCM_VELTS (SCM_ARRAY_V (ra))) = rlen;
623 }
624 if (!SCM_UNBNDP (fill))
625 {
626 scm_array_fill_x (ra, fill);
627 }
628 else if (SCM_SYMBOLP (prot))
629 scm_array_fill_x (ra, SCM_MAKINUM (0));
630 else
631 scm_array_fill_x (ra, prot);
632 if (1 == SCM_ARRAY_NDIM (ra) && 0 == SCM_ARRAY_BASE (ra))
633 if (s->ubnd < s->lbnd || (0 == s->lbnd && 1 == s->inc))
634 return SCM_ARRAY_V (ra);
635 return ra;
636 }
637 #undef FUNC_NAME
638
639
640 void
641 scm_ra_set_contp (SCM ra)
642 {
643 scm_sizet k = SCM_ARRAY_NDIM (ra);
644 if (k)
645 {
646 long inc = SCM_ARRAY_DIMS (ra)[k - 1].inc;
647 while (k--)
648 {
649 if (inc != SCM_ARRAY_DIMS (ra)[k].inc)
650 {
651 SCM_SETAND_CAR (ra, ~SCM_ARRAY_CONTIGUOUS);
652 return;
653 }
654 inc *= (SCM_ARRAY_DIMS (ra)[k].ubnd
655 - SCM_ARRAY_DIMS (ra)[k].lbnd + 1);
656 }
657 }
658 SCM_SETOR_CAR (ra, SCM_ARRAY_CONTIGUOUS);
659 }
660
661
662 SCM_DEFINE (scm_make_shared_array, "make-shared-array", 2, 0, 1,
663 (SCM oldra, SCM mapfunc, SCM dims),
664 "@code{make-shared-array} can be used to create shared subarrays of other\n"
665 "arrays. The @var{mapper} is a function that translates coordinates in\n"
666 "the new array into coordinates in the old array. A @var{mapper} must be\n"
667 "linear, and its range must stay within the bounds of the old array, but\n"
668 "it can be otherwise arbitrary. A simple example:\n"
669 "@example\n"
670 "(define fred (make-array #f 8 8))\n"
671 "(define freds-diagonal\n"
672 " (make-shared-array fred (lambda (i) (list i i)) 8))\n"
673 "(array-set! freds-diagonal 'foo 3)\n"
674 "(array-ref fred 3 3) @result{} foo\n"
675 "(define freds-center\n"
676 " (make-shared-array fred (lambda (i j) (list (+ 3 i) (+ 3 j))) 2 2))\n"
677 "(array-ref freds-center 0 0) @result{} foo\n"
678 "@end example")
679 #define FUNC_NAME s_scm_make_shared_array
680 {
681 SCM ra;
682 SCM inds, indptr;
683 SCM imap;
684 scm_sizet i, k;
685 long old_min, new_min, old_max, new_max;
686 scm_array_dim *s;
687 SCM_VALIDATE_ARRAY (1,oldra);
688 SCM_VALIDATE_PROC (2,mapfunc);
689 ra = scm_shap2ra (dims, FUNC_NAME);
690 if (SCM_ARRAYP (oldra))
691 {
692 SCM_ARRAY_V (ra) = SCM_ARRAY_V (oldra);
693 old_min = old_max = SCM_ARRAY_BASE (oldra);
694 s = SCM_ARRAY_DIMS (oldra);
695 k = SCM_ARRAY_NDIM (oldra);
696 while (k--)
697 {
698 if (s[k].inc > 0)
699 old_max += (s[k].ubnd - s[k].lbnd) * s[k].inc;
700 else
701 old_min += (s[k].ubnd - s[k].lbnd) * s[k].inc;
702 }
703 }
704 else
705 {
706 SCM_ARRAY_V (ra) = oldra;
707 old_min = 0;
708 old_max = (long) SCM_LENGTH (oldra) - 1;
709 }
710 inds = SCM_EOL;
711 s = SCM_ARRAY_DIMS (ra);
712 for (k = 0; k < SCM_ARRAY_NDIM (ra); k++)
713 {
714 inds = scm_cons (SCM_MAKINUM (s[k].lbnd), inds);
715 if (s[k].ubnd < s[k].lbnd)
716 {
717 if (1 == SCM_ARRAY_NDIM (ra))
718 ra = scm_make_uve (0L, scm_array_prototype (ra));
719 else
720 SCM_ARRAY_V (ra) = scm_make_uve (0L, scm_array_prototype (ra));
721 return ra;
722 }
723 }
724 imap = scm_apply (mapfunc, scm_reverse (inds), SCM_EOL);
725 if (SCM_ARRAYP (oldra))
726 i = (scm_sizet) scm_aind (oldra, imap, FUNC_NAME);
727 else
728 {
729 if (SCM_NINUMP (imap))
730
731 {
732 SCM_ASSERT (1 == scm_ilength (imap) && SCM_INUMP (SCM_CAR (imap)),
733 imap, s_bad_ind, FUNC_NAME);
734 imap = SCM_CAR (imap);
735 }
736 i = SCM_INUM (imap);
737 }
738 SCM_ARRAY_BASE (ra) = new_min = new_max = i;
739 indptr = inds;
740 k = SCM_ARRAY_NDIM (ra);
741 while (k--)
742 {
743 if (s[k].ubnd > s[k].lbnd)
744 {
745 SCM_SETCAR (indptr, SCM_MAKINUM (SCM_INUM (SCM_CAR (indptr)) + 1));
746 imap = scm_apply (mapfunc, scm_reverse (inds), SCM_EOL);
747 if (SCM_ARRAYP (oldra))
748
749 s[k].inc = scm_aind (oldra, imap, FUNC_NAME) - i;
750 else
751 {
752 if (SCM_NINUMP (imap))
753
754 {
755 SCM_ASSERT (1 == scm_ilength (imap) && SCM_INUMP (SCM_CAR (imap)),
756 imap, s_bad_ind, FUNC_NAME);
757 imap = SCM_CAR (imap);
758 }
759 s[k].inc = (long) SCM_INUM (imap) - i;
760 }
761 i += s[k].inc;
762 if (s[k].inc > 0)
763 new_max += (s[k].ubnd - s[k].lbnd) * s[k].inc;
764 else
765 new_min += (s[k].ubnd - s[k].lbnd) * s[k].inc;
766 }
767 else
768 s[k].inc = new_max - new_min + 1; /* contiguous by default */
769 indptr = SCM_CDR (indptr);
770 }
771 SCM_ASSERT (old_min <= new_min && old_max >= new_max, SCM_UNDEFINED,
772 "mapping out of range", FUNC_NAME);
773 if (1 == SCM_ARRAY_NDIM (ra) && 0 == SCM_ARRAY_BASE (ra))
774 {
775 if (1 == s->inc && 0 == s->lbnd
776 && SCM_LENGTH (SCM_ARRAY_V (ra)) == 1 + s->ubnd)
777 return SCM_ARRAY_V (ra);
778 if (s->ubnd < s->lbnd)
779 return scm_make_uve (0L, scm_array_prototype (ra));
780 }
781 scm_ra_set_contp (ra);
782 return ra;
783 }
784 #undef FUNC_NAME
785
786
787 /* args are RA . DIMS */
788 SCM_DEFINE (scm_transpose_array, "transpose-array", 1, 0, 1,
789 (SCM ra, SCM args),
790 "Returns an array sharing contents with @var{array}, but with dimensions\n"
791 "arranged in a different order. There must be one @var{dim} argument for\n"
792 "each dimension of @var{array}. @var{dim0}, @var{dim1}, @dots{} should\n"
793 "be integers between 0 and the rank of the array to be returned. Each\n"
794 "integer in that range must appear at least once in the argument list.\n\n"
795 "The values of @var{dim0}, @var{dim1}, @dots{} correspond to dimensions\n"
796 "in the array to be returned, their positions in the argument list to\n"
797 "dimensions of @var{array}. Several @var{dim}s may have the same value,\n"
798 "in which case the returned array will have smaller rank than\n"
799 "@var{array}.\n\n"
800 "examples:\n"
801 "@example\n"
802 "(transpose-array '#2((a b) (c d)) 1 0) @result{} #2((a c) (b d))\n"
803 "(transpose-array '#2((a b) (c d)) 0 0) @result{} #1(a d)\n"
804 "(transpose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 1 0) @result{}\n"
805 " #2((a 4) (b 5) (c 6))\n"
806 "@end example")
807 #define FUNC_NAME s_scm_transpose_array
808 {
809 SCM res, vargs, *ve = &vargs;
810 scm_array_dim *s, *r;
811 int ndim, i, k;
812
813 SCM_ASSERT (SCM_NIMP (ra), ra, SCM_ARG1, FUNC_NAME);
814 switch (SCM_TYP7 (ra))
815 {
816 default:
817 badarg:SCM_WTA (1,ra);
818 case scm_tc7_bvect:
819 case scm_tc7_string:
820 case scm_tc7_byvect:
821 case scm_tc7_uvect:
822 case scm_tc7_ivect:
823 case scm_tc7_fvect:
824 case scm_tc7_dvect:
825 case scm_tc7_cvect:
826 case scm_tc7_svect:
827 #ifdef HAVE_LONG_LONGS
828 case scm_tc7_llvect:
829 #endif
830 SCM_ASSERT (!SCM_NULLP (args) && SCM_NULLP (SCM_CDR (args)),
831 scm_makfrom0str (FUNC_NAME), SCM_WNA, NULL);
832 SCM_ASSERT (SCM_INUMP (SCM_CAR (args)), SCM_CAR (args), SCM_ARG2,
833 FUNC_NAME);
834 SCM_ASSERT (SCM_EQ_P (SCM_INUM0, SCM_CAR (args)), SCM_CAR (args), SCM_OUTOFRANGE,
835 FUNC_NAME);
836 return ra;
837 case scm_tc7_smob:
838 SCM_ASRTGO (SCM_ARRAYP (ra), badarg);
839 vargs = scm_vector (args);
840 SCM_ASSERT (SCM_LENGTH (vargs) == SCM_ARRAY_NDIM (ra),
841 scm_makfrom0str (FUNC_NAME), SCM_WNA, NULL);
842 ve = SCM_VELTS (vargs);
843 ndim = 0;
844 for (k = 0; k < SCM_ARRAY_NDIM (ra); k++)
845 {
846 SCM_ASSERT (SCM_INUMP (ve[k]), ve[k], (SCM_ARG2 + k),
847 FUNC_NAME);
848 i = SCM_INUM (ve[k]);
849 SCM_ASSERT (i >= 0 && i < SCM_ARRAY_NDIM (ra), ve[k],
850 SCM_OUTOFRANGE, FUNC_NAME);
851 if (ndim < i)
852 ndim = i;
853 }
854 ndim++;
855 res = scm_make_ra (ndim);
856 SCM_ARRAY_V (res) = SCM_ARRAY_V (ra);
857 SCM_ARRAY_BASE (res) = SCM_ARRAY_BASE (ra);
858 for (k = ndim; k--;)
859 {
860 SCM_ARRAY_DIMS (res)[k].lbnd = 0;
861 SCM_ARRAY_DIMS (res)[k].ubnd = -1;
862 }
863 for (k = SCM_ARRAY_NDIM (ra); k--;)
864 {
865 i = SCM_INUM (ve[k]);
866 s = &(SCM_ARRAY_DIMS (ra)[k]);
867 r = &(SCM_ARRAY_DIMS (res)[i]);
868 if (r->ubnd < r->lbnd)
869 {
870 r->lbnd = s->lbnd;
871 r->ubnd = s->ubnd;
872 r->inc = s->inc;
873 ndim--;
874 }
875 else
876 {
877 if (r->ubnd > s->ubnd)
878 r->ubnd = s->ubnd;
879 if (r->lbnd < s->lbnd)
880 {
881 SCM_ARRAY_BASE (res) += (s->lbnd - r->lbnd) * r->inc;
882 r->lbnd = s->lbnd;
883 }
884 r->inc += s->inc;
885 }
886 }
887 SCM_ASSERT (ndim <= 0, args, "bad argument list", FUNC_NAME);
888 scm_ra_set_contp (res);
889 return res;
890 }
891 }
892 #undef FUNC_NAME
893
894 /* args are RA . AXES */
895 SCM_DEFINE (scm_enclose_array, "enclose-array", 1, 0, 1,
896 (SCM ra, SCM axes),
897 "@var{dim0}, @var{dim1} @dots{} should be nonnegative integers less than\n"
898 "the rank of @var{array}. @var{enclose-array} returns an array\n"
899 "resembling an array of shared arrays. The dimensions of each shared\n"
900 "array are the same as the @var{dim}th dimensions of the original array,\n"
901 "the dimensions of the outer array are the same as those of the original\n"
902 "array that did not match a @var{dim}.\n\n"
903 "An enclosed array is not a general Scheme array. Its elements may not\n"
904 "be set using @code{array-set!}. Two references to the same element of\n"
905 "an enclosed array will be @code{equal?} but will not in general be\n"
906 "@code{eq?}. The value returned by @var{array-prototype} when given an\n"
907 "enclosed array is unspecified.\n\n"
908 "examples:\n"
909 "@example\n"
910 "(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1) @result{}\n"
911 " #<enclosed-array (#1(a d) #1(b e) #1(c f)) (#1(1 4) #1(2 5) #1(3 6))>\n\n"
912 "(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 0) @result{}\n"
913 " #<enclosed-array #2((a 1) (d 4)) #2((b 2) (e 5)) #2((c 3) (f 6))>\n"
914 "@end example")
915 #define FUNC_NAME s_scm_enclose_array
916 {
917 SCM axv, res, ra_inr;
918 scm_array_dim vdim, *s = &vdim;
919 int ndim, j, k, ninr, noutr;
920
921 if (SCM_NULLP (axes))
922 axes = scm_cons ((SCM_ARRAYP (ra) ? SCM_MAKINUM (SCM_ARRAY_NDIM (ra) - 1) : SCM_INUM0), SCM_EOL);
923 ninr = scm_ilength (axes);
924 SCM_ASSERT (0 <= ninr, scm_makfrom0str (FUNC_NAME), SCM_WNA, NULL);
925 ra_inr = scm_make_ra (ninr);
926 SCM_ASRTGO (SCM_NIMP (ra), badarg1);
927 switch SCM_TYP7
928 (ra)
929 {
930 default:
931 badarg1:SCM_WTA (1,ra);
932 case scm_tc7_string:
933 case scm_tc7_bvect:
934 case scm_tc7_byvect:
935 case scm_tc7_uvect:
936 case scm_tc7_ivect:
937 case scm_tc7_fvect:
938 case scm_tc7_dvect:
939 case scm_tc7_cvect:
940 case scm_tc7_vector:
941 case scm_tc7_wvect:
942 case scm_tc7_svect:
943 #ifdef HAVE_LONG_LONGS
944 case scm_tc7_llvect:
945 #endif
946 s->lbnd = 0;
947 s->ubnd = SCM_LENGTH (ra) - 1;
948 s->inc = 1;
949 SCM_ARRAY_V (ra_inr) = ra;
950 SCM_ARRAY_BASE (ra_inr) = 0;
951 ndim = 1;
952 break;
953 case scm_tc7_smob:
954 SCM_ASRTGO (SCM_ARRAYP (ra), badarg1);
955 s = SCM_ARRAY_DIMS (ra);
956 SCM_ARRAY_V (ra_inr) = SCM_ARRAY_V (ra);
957 SCM_ARRAY_BASE (ra_inr) = SCM_ARRAY_BASE (ra);
958 ndim = SCM_ARRAY_NDIM (ra);
959 break;
960 }
961 noutr = ndim - ninr;
962 axv = scm_make_string (SCM_MAKINUM (ndim), SCM_MAKE_CHAR (0));
963 SCM_ASSERT (0 <= noutr, scm_makfrom0str (FUNC_NAME), SCM_WNA, NULL);
964 res = scm_make_ra (noutr);
965 SCM_ARRAY_BASE (res) = SCM_ARRAY_BASE (ra_inr);
966 SCM_ARRAY_V (res) = ra_inr;
967 for (k = 0; k < ninr; k++, axes = SCM_CDR (axes))
968 {
969 SCM_ASSERT (SCM_INUMP (SCM_CAR (axes)), SCM_CAR (axes), "bad axis", FUNC_NAME);
970 j = SCM_INUM (SCM_CAR (axes));
971 SCM_ARRAY_DIMS (ra_inr)[k].lbnd = s[j].lbnd;
972 SCM_ARRAY_DIMS (ra_inr)[k].ubnd = s[j].ubnd;
973 SCM_ARRAY_DIMS (ra_inr)[k].inc = s[j].inc;
974 SCM_CHARS (axv)[j] = 1;
975 }
976 for (j = 0, k = 0; k < noutr; k++, j++)
977 {
978 while (SCM_CHARS (axv)[j])
979 j++;
980 SCM_ARRAY_DIMS (res)[k].lbnd = s[j].lbnd;
981 SCM_ARRAY_DIMS (res)[k].ubnd = s[j].ubnd;
982 SCM_ARRAY_DIMS (res)[k].inc = s[j].inc;
983 }
984 scm_ra_set_contp (ra_inr);
985 scm_ra_set_contp (res);
986 return res;
987 }
988 #undef FUNC_NAME
989
990
991
992 SCM_DEFINE (scm_array_in_bounds_p, "array-in-bounds?", 1, 0, 1,
993 (SCM v, SCM args),
994 "Returns @code{#t} if its arguments would be acceptable to array-ref.")
995 #define FUNC_NAME s_scm_array_in_bounds_p
996 {
997 SCM ind = SCM_EOL;
998 long pos = 0;
999 register scm_sizet k;
1000 register long j;
1001 scm_array_dim *s;
1002
1003 SCM_ASRTGO (SCM_NIMP (v), badarg1);
1004 if (SCM_NIMP (args))
1005
1006 {
1007 ind = SCM_CAR (args);
1008 args = SCM_CDR (args);
1009 SCM_ASSERT (SCM_INUMP (ind), ind, SCM_ARG2, FUNC_NAME);
1010 pos = SCM_INUM (ind);
1011 }
1012 tail:
1013 switch SCM_TYP7
1014 (v)
1015 {
1016 default:
1017 badarg1:SCM_WTA (1,v);
1018 wna: scm_wrong_num_args (scm_makfrom0str (FUNC_NAME));
1019 case scm_tc7_smob:
1020 k = SCM_ARRAY_NDIM (v);
1021 s = SCM_ARRAY_DIMS (v);
1022 pos = SCM_ARRAY_BASE (v);
1023 if (!k)
1024 {
1025 SCM_ASRTGO (SCM_NULLP (ind), wna);
1026 ind = SCM_INUM0;
1027 }
1028 else
1029 while (!0)
1030 {
1031 j = SCM_INUM (ind);
1032 if (!(j >= (s->lbnd) && j <= (s->ubnd)))
1033 {
1034 SCM_ASRTGO (--k == scm_ilength (args), wna);
1035 return SCM_BOOL_F;
1036 }
1037 pos += (j - s->lbnd) * (s->inc);
1038 if (!(--k && SCM_NIMP (args)))
1039 break;
1040 ind = SCM_CAR (args);
1041 args = SCM_CDR (args);
1042 s++;
1043 SCM_ASSERT (SCM_INUMP (ind), ind, s_bad_ind, FUNC_NAME);
1044 }
1045 SCM_ASRTGO (0 == k, wna);
1046 v = SCM_ARRAY_V (v);
1047 goto tail;
1048 case scm_tc7_bvect:
1049 case scm_tc7_string:
1050 case scm_tc7_byvect:
1051 case scm_tc7_uvect:
1052 case scm_tc7_ivect:
1053 case scm_tc7_fvect:
1054 case scm_tc7_dvect:
1055 case scm_tc7_cvect:
1056 case scm_tc7_svect:
1057 #ifdef HAVE_LONG_LONGS
1058 case scm_tc7_llvect:
1059 #endif
1060 case scm_tc7_vector:
1061 case scm_tc7_wvect:
1062 SCM_ASRTGO (SCM_NULLP (args) && SCM_INUMP (ind), wna);
1063 return SCM_BOOL(pos >= 0 && pos < SCM_LENGTH (v));
1064 }
1065 }
1066 #undef FUNC_NAME
1067
1068
1069 SCM_REGISTER_PROC(s_array_ref, "array-ref", 1, 0, 1, scm_uniform_vector_ref);
1070
1071
1072 SCM_DEFINE (scm_uniform_vector_ref, "uniform-vector-ref", 2, 0, 0,
1073 (SCM v, SCM args),
1074 "Returns the element at the @code{(index1, index2)} element in @var{array}.")
1075 #define FUNC_NAME s_scm_uniform_vector_ref
1076 {
1077 long pos;
1078
1079 if (SCM_IMP (v))
1080 {
1081 SCM_ASRTGO (SCM_NULLP (args), badarg);
1082 return v;
1083 }
1084 else if (SCM_ARRAYP (v))
1085 {
1086 pos = scm_aind (v, args, FUNC_NAME);
1087 v = SCM_ARRAY_V (v);
1088 }
1089 else
1090 {
1091 if (SCM_NIMP (args))
1092
1093 {
1094 SCM_ASSERT (SCM_CONSP (args) && SCM_INUMP (SCM_CAR (args)), args, SCM_ARG2, FUNC_NAME);
1095 pos = SCM_INUM (SCM_CAR (args));
1096 SCM_ASRTGO (SCM_NULLP (SCM_CDR (args)), wna);
1097 }
1098 else
1099 {
1100 SCM_VALIDATE_INUM (2,args);
1101 pos = SCM_INUM (args);
1102 }
1103 SCM_ASRTGO (pos >= 0 && pos < SCM_LENGTH (v), outrng);
1104 }
1105 switch SCM_TYP7
1106 (v)
1107 {
1108 default:
1109 if (SCM_NULLP (args))
1110 return v;
1111 badarg:
1112 SCM_WTA (1,v);
1113 abort ();
1114
1115 outrng:
1116 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (pos));
1117 wna:
1118 scm_wrong_num_args (SCM_FUNC_NAME);
1119 case scm_tc7_smob:
1120 { /* enclosed */
1121 int k = SCM_ARRAY_NDIM (v);
1122 SCM res = scm_make_ra (k);
1123 SCM_ARRAY_V (res) = SCM_ARRAY_V (v);
1124 SCM_ARRAY_BASE (res) = pos;
1125 while (k--)
1126 {
1127 SCM_ARRAY_DIMS (res)[k].lbnd = SCM_ARRAY_DIMS (v)[k].lbnd;
1128 SCM_ARRAY_DIMS (res)[k].ubnd = SCM_ARRAY_DIMS (v)[k].ubnd;
1129 SCM_ARRAY_DIMS (res)[k].inc = SCM_ARRAY_DIMS (v)[k].inc;
1130 }
1131 return res;
1132 }
1133 case scm_tc7_bvect:
1134 if (SCM_BITVEC_REF (v, pos))
1135 return SCM_BOOL_T;
1136 else
1137 return SCM_BOOL_F;
1138 case scm_tc7_string:
1139 return SCM_MAKE_CHAR (SCM_UCHARS (v)[pos]);
1140 case scm_tc7_byvect:
1141 return SCM_MAKINUM (((char *)SCM_CHARS (v))[pos]);
1142 case scm_tc7_uvect:
1143 return scm_ulong2num (((unsigned long *) SCM_VELTS (v))[pos]);
1144 case scm_tc7_ivect:
1145 return scm_long2num(((signed long *) SCM_VELTS (v))[pos]);
1146
1147 case scm_tc7_svect:
1148 return SCM_MAKINUM (((short *) SCM_CELL_WORD_1 (v))[pos]);
1149 #ifdef HAVE_LONG_LONGS
1150 case scm_tc7_llvect:
1151 return scm_long_long2num (((long_long *) SCM_CELL_WORD_1 (v))[pos]);
1152 #endif
1153
1154 case scm_tc7_fvect:
1155 return scm_make_real (((float *) SCM_CELL_WORD_1 (v))[pos]);
1156 case scm_tc7_dvect:
1157 return scm_make_real (((double *) SCM_CELL_WORD_1 (v))[pos]);
1158 case scm_tc7_cvect:
1159 return scm_make_complex (((double *) SCM_CELL_WORD_1 (v))[2 * pos],
1160 ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1]);
1161 case scm_tc7_vector:
1162 case scm_tc7_wvect:
1163 return SCM_VELTS (v)[pos];
1164 }
1165 }
1166 #undef FUNC_NAME
1167
1168 /* Internal version of scm_uniform_vector_ref for uves that does no error checking and
1169 tries to recycle conses. (Make *sure* you want them recycled.) */
1170
1171 SCM
1172 scm_cvref (SCM v, scm_sizet pos, SCM last)
1173 {
1174 switch SCM_TYP7 (v)
1175 {
1176 default:
1177 scm_wta (v, (char *) SCM_ARG1, "PROGRAMMING ERROR: scm_cvref");
1178 case scm_tc7_bvect:
1179 if (SCM_BITVEC_REF(v,pos))
1180 return SCM_BOOL_T;
1181 else
1182 return SCM_BOOL_F;
1183 case scm_tc7_string:
1184 return SCM_MAKE_CHAR (SCM_UCHARS (v)[pos]);
1185 case scm_tc7_byvect:
1186 return SCM_MAKINUM (((char *)SCM_CHARS (v))[pos]);
1187 case scm_tc7_uvect:
1188 return scm_ulong2num(((unsigned long *) SCM_VELTS (v))[pos]);
1189 case scm_tc7_ivect:
1190 return scm_long2num(((signed long *) SCM_VELTS (v))[pos]);
1191 case scm_tc7_svect:
1192 return SCM_MAKINUM (((short *) SCM_CELL_WORD_1 (v))[pos]);
1193 #ifdef HAVE_LONG_LONGS
1194 case scm_tc7_llvect:
1195 return scm_long_long2num (((long_long *) SCM_CELL_WORD_1 (v))[pos]);
1196 #endif
1197 case scm_tc7_fvect:
1198 if (SCM_NIMP (last) && !SCM_EQ_P (last, scm_flo0) && SCM_SLOPPY_REALP (last))
1199 {
1200 SCM_REAL_VALUE (last) = ((float *) SCM_CELL_WORD_1 (v))[pos];
1201 return last;
1202 }
1203 return scm_make_real (((float *) SCM_CELL_WORD_1 (v))[pos]);
1204 case scm_tc7_dvect:
1205 if (SCM_NIMP (last) && !SCM_EQ_P (last, scm_flo0) && SCM_SLOPPY_REALP (last))
1206 {
1207 SCM_REAL_VALUE (last) = ((double *) SCM_CELL_WORD_1 (v))[pos];
1208 return last;
1209 }
1210 return scm_make_real (((double *) SCM_CELL_WORD_1 (v))[pos]);
1211 case scm_tc7_cvect:
1212 if (SCM_NIMP (last) && SCM_SLOPPY_COMPLEXP (last))
1213 {
1214 SCM_COMPLEX_REAL (last) = ((double *) SCM_CELL_WORD_1 (v))[2 * pos];
1215 SCM_COMPLEX_IMAG (last) = ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1];
1216 return last;
1217 }
1218 return scm_make_complex (((double *) SCM_CELL_WORD_1 (v))[2 * pos],
1219 ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1]);
1220 case scm_tc7_vector:
1221 case scm_tc7_wvect:
1222 return SCM_VELTS (v)[pos];
1223 case scm_tc7_smob:
1224 { /* enclosed scm_array */
1225 int k = SCM_ARRAY_NDIM (v);
1226 SCM res = scm_make_ra (k);
1227 SCM_ARRAY_V (res) = SCM_ARRAY_V (v);
1228 SCM_ARRAY_BASE (res) = pos;
1229 while (k--)
1230 {
1231 SCM_ARRAY_DIMS (res)[k].ubnd = SCM_ARRAY_DIMS (v)[k].ubnd;
1232 SCM_ARRAY_DIMS (res)[k].lbnd = SCM_ARRAY_DIMS (v)[k].lbnd;
1233 SCM_ARRAY_DIMS (res)[k].inc = SCM_ARRAY_DIMS (v)[k].inc;
1234 }
1235 return res;
1236 }
1237 }
1238 }
1239
1240 SCM_REGISTER_PROC(s_uniform_array_set1_x, "uniform-array-set1!", 3, 0, 0, scm_array_set_x);
1241
1242
1243 /* Note that args may be a list or an immediate object, depending which
1244 PROC is used (and it's called from C too). */
1245 SCM_DEFINE (scm_array_set_x, "array-set!", 2, 0, 1,
1246 (SCM v, SCM obj, SCM args),
1247 "Sets the element at the @code{(index1, index2)} element in @var{array} to\n"
1248 "@var{new-value}. The value returned by array-set! is unspecified.")
1249 #define FUNC_NAME s_scm_array_set_x
1250 {
1251 long pos = 0;
1252 SCM_ASRTGO (SCM_NIMP (v), badarg1);
1253 if (SCM_ARRAYP (v))
1254 {
1255 pos = scm_aind (v, args, FUNC_NAME);
1256 v = SCM_ARRAY_V (v);
1257 }
1258 else
1259 {
1260 if (SCM_NIMP (args))
1261 {
1262 SCM_ASSERT (SCM_CONSP(args) && SCM_INUMP (SCM_CAR (args)), args,
1263 SCM_ARG3, FUNC_NAME);
1264 SCM_ASRTGO (SCM_NULLP (SCM_CDR (args)), wna);
1265 pos = SCM_INUM (SCM_CAR (args));
1266 }
1267 else
1268 {
1269 SCM_VALIDATE_INUM_COPY (3,args,pos);
1270 }
1271 SCM_ASRTGO (pos >= 0 && pos < SCM_LENGTH (v), outrng);
1272 }
1273 switch (SCM_TYP7 (v))
1274 {
1275 default: badarg1:
1276 SCM_WTA (1,v);
1277 abort ();
1278 outrng:
1279 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (pos));
1280 wna:
1281 scm_wrong_num_args (SCM_FUNC_NAME);
1282 case scm_tc7_smob: /* enclosed */
1283 goto badarg1;
1284 case scm_tc7_bvect:
1285 if (SCM_FALSEP (obj))
1286 SCM_BITVEC_CLR(v,pos);
1287 else if (SCM_TRUE_P (obj))
1288 SCM_BITVEC_SET(v,pos);
1289 else
1290 badobj:SCM_WTA (2,obj);
1291 break;
1292 case scm_tc7_string:
1293 SCM_ASRTGO (SCM_CHARP (obj), badobj);
1294 SCM_UCHARS (v)[pos] = SCM_CHAR (obj);
1295 break;
1296 case scm_tc7_byvect:
1297 if (SCM_CHARP (obj))
1298 obj = SCM_MAKINUM ((char) SCM_CHAR (obj));
1299 SCM_ASRTGO (SCM_INUMP (obj), badobj);
1300 ((char *)SCM_CHARS (v))[pos] = SCM_INUM (obj);
1301 break;
1302 case scm_tc7_uvect:
1303 SCM_VELTS(v)[pos] = SCM_PACK (scm_num2ulong(obj, (char *)SCM_ARG2, FUNC_NAME));
1304 break;
1305 case scm_tc7_ivect:
1306 SCM_VELTS(v)[pos] = SCM_PACK (scm_num2long(obj, (char *)SCM_ARG2, FUNC_NAME));
1307 break;
1308 case scm_tc7_svect:
1309 SCM_ASRTGO (SCM_INUMP (obj), badobj);
1310 ((short *) SCM_CELL_WORD_1 (v))[pos] = SCM_INUM (obj);
1311 break;
1312 #ifdef HAVE_LONG_LONGS
1313 case scm_tc7_llvect:
1314 ((long_long *) SCM_CELL_WORD_1 (v))[pos] = scm_num2long_long (obj, (char *)SCM_ARG2, FUNC_NAME);
1315 break;
1316 #endif
1317
1318
1319 case scm_tc7_fvect:
1320 ((float *) SCM_CELL_WORD_1 (v))[pos] = (float) scm_num2dbl (obj, FUNC_NAME);
1321 break;
1322 case scm_tc7_dvect:
1323 ((double *) SCM_CELL_WORD_1 (v))[pos] = scm_num2dbl (obj, FUNC_NAME);
1324 break;
1325 case scm_tc7_cvect:
1326 SCM_ASRTGO (SCM_INEXACTP (obj), badobj);
1327 if (SCM_REALP (obj)) {
1328 ((double *) SCM_CELL_WORD_1 (v))[2 * pos] = SCM_REAL_VALUE (obj);
1329 ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1] = 0.0;
1330 } else {
1331 ((double *) SCM_CELL_WORD_1 (v))[2 * pos] = SCM_COMPLEX_REAL (obj);
1332 ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1] = SCM_COMPLEX_IMAG (obj);
1333 }
1334 break;
1335 case scm_tc7_vector:
1336 case scm_tc7_wvect:
1337 SCM_VELTS (v)[pos] = obj;
1338 break;
1339 }
1340 return SCM_UNSPECIFIED;
1341 }
1342 #undef FUNC_NAME
1343
1344 /* attempts to unroll an array into a one-dimensional array.
1345 returns the unrolled array or #f if it can't be done. */
1346 /* if strict is not SCM_UNDEFINED, return #f if returned array
1347 wouldn't have contiguous elements. */
1348 SCM_DEFINE (scm_array_contents, "array-contents", 1, 1, 0,
1349 (SCM ra, SCM strict),
1350 "@deffnx primitive array-contents array strict\n"
1351 "If @var{array} may be @dfn{unrolled} into a one dimensional shared array\n"
1352 "without changing their order (last subscript changing fastest), then\n"
1353 "@code{array-contents} returns that shared array, otherwise it returns\n"
1354 "@code{#f}. All arrays made by @var{make-array} and\n"
1355 "@var{make-uniform-array} may be unrolled, some arrays made by\n"
1356 "@var{make-shared-array} may not be.\n\n"
1357 "If the optional argument @var{strict} is provided, a shared array will\n"
1358 "be returned only if its elements are stored internally contiguous in\n"
1359 "memory.")
1360 #define FUNC_NAME s_scm_array_contents
1361 {
1362 SCM sra;
1363 if (SCM_IMP (ra))
1364 return SCM_BOOL_F;
1365 switch SCM_TYP7 (ra)
1366 {
1367 default:
1368 return SCM_BOOL_F;
1369 case scm_tc7_vector:
1370 case scm_tc7_wvect:
1371 case scm_tc7_string:
1372 case scm_tc7_bvect:
1373 case scm_tc7_byvect:
1374 case scm_tc7_uvect:
1375 case scm_tc7_ivect:
1376 case scm_tc7_fvect:
1377 case scm_tc7_dvect:
1378 case scm_tc7_cvect:
1379 case scm_tc7_svect:
1380 #ifdef HAVE_LONG_LONGS
1381 case scm_tc7_llvect:
1382 #endif
1383 return ra;
1384 case scm_tc7_smob:
1385 {
1386 scm_sizet k, ndim = SCM_ARRAY_NDIM (ra), len = 1;
1387 if (!SCM_ARRAYP (ra) || !SCM_ARRAY_CONTP (ra))
1388 return SCM_BOOL_F;
1389 for (k = 0; k < ndim; k++)
1390 len *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1391 if (!SCM_UNBNDP (strict))
1392 {
1393 if (ndim && (1 != SCM_ARRAY_DIMS (ra)[ndim - 1].inc))
1394 return SCM_BOOL_F;
1395 if (scm_tc7_bvect == SCM_TYP7 (SCM_ARRAY_V (ra)))
1396 {
1397 if (len != SCM_LENGTH (SCM_ARRAY_V (ra)) ||
1398 SCM_ARRAY_BASE (ra) % SCM_LONG_BIT ||
1399 len % SCM_LONG_BIT)
1400 return SCM_BOOL_F;
1401 }
1402 }
1403 if ((len == SCM_LENGTH (SCM_ARRAY_V (ra))) && 0 == SCM_ARRAY_BASE (ra) && SCM_ARRAY_DIMS (ra)->inc)
1404 return SCM_ARRAY_V (ra);
1405 sra = scm_make_ra (1);
1406 SCM_ARRAY_DIMS (sra)->lbnd = 0;
1407 SCM_ARRAY_DIMS (sra)->ubnd = len - 1;
1408 SCM_ARRAY_V (sra) = SCM_ARRAY_V (ra);
1409 SCM_ARRAY_BASE (sra) = SCM_ARRAY_BASE (ra);
1410 SCM_ARRAY_DIMS (sra)->inc = (ndim ? SCM_ARRAY_DIMS (ra)[ndim - 1].inc : 1);
1411 return sra;
1412 }
1413 }
1414 }
1415 #undef FUNC_NAME
1416
1417
1418 SCM
1419 scm_ra2contig (SCM ra, int copy)
1420 {
1421 SCM ret;
1422 long inc = 1;
1423 scm_sizet k, len = 1;
1424 for (k = SCM_ARRAY_NDIM (ra); k--;)
1425 len *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1426 k = SCM_ARRAY_NDIM (ra);
1427 if (SCM_ARRAY_CONTP (ra) && ((0 == k) || (1 == SCM_ARRAY_DIMS (ra)[k - 1].inc)))
1428 {
1429 if (scm_tc7_bvect != SCM_TYP7 (ra))
1430 return ra;
1431 if ((len == SCM_LENGTH (SCM_ARRAY_V (ra)) &&
1432 0 == SCM_ARRAY_BASE (ra) % SCM_LONG_BIT &&
1433 0 == len % SCM_LONG_BIT))
1434 return ra;
1435 }
1436 ret = scm_make_ra (k);
1437 SCM_ARRAY_BASE (ret) = 0;
1438 while (k--)
1439 {
1440 SCM_ARRAY_DIMS (ret)[k].lbnd = SCM_ARRAY_DIMS (ra)[k].lbnd;
1441 SCM_ARRAY_DIMS (ret)[k].ubnd = SCM_ARRAY_DIMS (ra)[k].ubnd;
1442 SCM_ARRAY_DIMS (ret)[k].inc = inc;
1443 inc *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1444 }
1445 SCM_ARRAY_V (ret) = scm_make_uve ((inc - 1), scm_array_prototype (ra));
1446 if (copy)
1447 scm_array_copy_x (ra, ret);
1448 return ret;
1449 }
1450
1451
1452
1453 SCM_DEFINE (scm_uniform_array_read_x, "uniform-array-read!", 1, 3, 0,
1454 (SCM ra, SCM port_or_fd, SCM start, SCM end),
1455 "@deffnx primitive uniform-vector-read! uve [port-or-fdes] [start] [end]\n"
1456 "Attempts to read all elements of @var{ura}, in lexicographic order, as\n"
1457 "binary objects from @var{port-or-fdes}.\n"
1458 "If an end of file is encountered during\n"
1459 "uniform-array-read! the objects up to that point only are put into @var{ura}\n"
1460 "(starting at the beginning) and the remainder of the array is\n"
1461 "unchanged.\n\n"
1462 "The optional arguments @var{start} and @var{end} allow\n"
1463 "a specified region of a vector (or linearized array) to be read,\n"
1464 "leaving the remainder of the vector unchanged.\n\n"
1465 "@code{uniform-array-read!} returns the number of objects read.\n"
1466 "@var{port-or-fdes} may be omitted, in which case it defaults to the value\n"
1467 "returned by @code{(current-input-port)}.")
1468 #define FUNC_NAME s_scm_uniform_array_read_x
1469 {
1470 SCM cra = SCM_UNDEFINED, v = ra;
1471 long sz, vlen, ans;
1472 long cstart = 0;
1473 long cend;
1474 long offset = 0;
1475
1476 SCM_ASRTGO (SCM_NIMP (v), badarg1);
1477 if (SCM_UNBNDP (port_or_fd))
1478 port_or_fd = scm_cur_inp;
1479 else
1480 SCM_ASSERT (SCM_INUMP (port_or_fd)
1481 || (SCM_OPINPORTP (port_or_fd)),
1482 port_or_fd, SCM_ARG2, FUNC_NAME);
1483 vlen = SCM_LENGTH (v);
1484
1485 loop:
1486 switch SCM_TYP7 (v)
1487 {
1488 default:
1489 badarg1:SCM_WTA (SCM_ARG1,v);
1490 case scm_tc7_smob:
1491 SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
1492 cra = scm_ra2contig (ra, 0);
1493 cstart += SCM_ARRAY_BASE (cra);
1494 vlen = SCM_ARRAY_DIMS (cra)->inc *
1495 (SCM_ARRAY_DIMS (cra)->ubnd - SCM_ARRAY_DIMS (cra)->lbnd + 1);
1496 v = SCM_ARRAY_V (cra);
1497 goto loop;
1498 case scm_tc7_string:
1499 case scm_tc7_byvect:
1500 sz = sizeof (char);
1501 break;
1502 case scm_tc7_bvect:
1503 vlen = (vlen + SCM_LONG_BIT - 1) / SCM_LONG_BIT;
1504 cstart /= SCM_LONG_BIT;
1505 case scm_tc7_uvect:
1506 case scm_tc7_ivect:
1507 sz = sizeof (long);
1508 break;
1509 case scm_tc7_svect:
1510 sz = sizeof (short);
1511 break;
1512 #ifdef HAVE_LONG_LONGS
1513 case scm_tc7_llvect:
1514 sz = sizeof (long_long);
1515 break;
1516 #endif
1517 case scm_tc7_fvect:
1518 sz = sizeof (float);
1519 break;
1520 case scm_tc7_dvect:
1521 sz = sizeof (double);
1522 break;
1523 case scm_tc7_cvect:
1524 sz = 2 * sizeof (double);
1525 break;
1526 }
1527
1528 cend = vlen;
1529 if (!SCM_UNBNDP (start))
1530 {
1531 offset =
1532 SCM_NUM2LONG (3, start);
1533
1534 if (offset < 0 || offset >= cend)
1535 scm_out_of_range (FUNC_NAME, start);
1536
1537 if (!SCM_UNBNDP (end))
1538 {
1539 long tend =
1540 SCM_NUM2LONG (4, end);
1541
1542 if (tend <= offset || tend > cend)
1543 scm_out_of_range (FUNC_NAME, end);
1544 cend = tend;
1545 }
1546 }
1547
1548 if (SCM_NIMP (port_or_fd))
1549 {
1550 scm_port *pt = SCM_PTAB_ENTRY (port_or_fd);
1551 int remaining = (cend - offset) * sz;
1552 char *dest = SCM_CHARS (v) + (cstart + offset) * sz;
1553
1554 if (pt->rw_active == SCM_PORT_WRITE)
1555 scm_flush (port_or_fd);
1556
1557 ans = cend - offset;
1558 while (remaining > 0)
1559 {
1560 if (pt->read_pos < pt->read_end)
1561 {
1562 int to_copy = min (pt->read_end - pt->read_pos,
1563 remaining);
1564
1565 memcpy (dest, pt->read_pos, to_copy);
1566 pt->read_pos += to_copy;
1567 remaining -= to_copy;
1568 dest += to_copy;
1569 }
1570 else
1571 {
1572 if (scm_fill_input (port_or_fd) == EOF)
1573 {
1574 if (remaining % sz != 0)
1575 {
1576 SCM_MISC_ERROR ("unexpected EOF", SCM_EOL);
1577 }
1578 ans -= remaining / sz;
1579 break;
1580 }
1581 }
1582 }
1583
1584 if (pt->rw_random)
1585 pt->rw_active = SCM_PORT_READ;
1586 }
1587 else /* file descriptor. */
1588 {
1589 SCM_SYSCALL (ans = read (SCM_INUM (port_or_fd),
1590 SCM_CHARS (v) + (cstart + offset) * sz,
1591 (scm_sizet) (sz * (cend - offset))));
1592 if (ans == -1)
1593 SCM_SYSERROR;
1594 }
1595 if (SCM_TYP7 (v) == scm_tc7_bvect)
1596 ans *= SCM_LONG_BIT;
1597
1598 if (!SCM_EQ_P (v, ra) && !SCM_EQ_P (cra, ra))
1599 scm_array_copy_x (cra, ra);
1600
1601 return SCM_MAKINUM (ans);
1602 }
1603 #undef FUNC_NAME
1604
1605 SCM_DEFINE (scm_uniform_array_write, "uniform-array-write", 1, 3, 0,
1606 (SCM v, SCM port_or_fd, SCM start, SCM end),
1607 "@deffnx primitive uniform-vector-write uve [port-or-fdes] [start] [end]\n"
1608 "Writes all elements of @var{ura} as binary objects to\n"
1609 "@var{port-or-fdes}.\n\n"
1610 "The optional arguments @var{start}\n"
1611 "and @var{end} allow\n"
1612 "a specified region of a vector (or linearized array) to be written.\n\n"
1613 "The number of objects actually written is returned. \n"
1614 "@var{port-or-fdes} may be\n"
1615 "omitted, in which case it defaults to the value returned by\n"
1616 "@code{(current-output-port)}.")
1617 #define FUNC_NAME s_scm_uniform_array_write
1618 {
1619 long sz, vlen, ans;
1620 long offset = 0;
1621 long cstart = 0;
1622 long cend;
1623
1624 port_or_fd = SCM_COERCE_OUTPORT (port_or_fd);
1625
1626 SCM_ASRTGO (SCM_NIMP (v), badarg1);
1627 if (SCM_UNBNDP (port_or_fd))
1628 port_or_fd = scm_cur_outp;
1629 else
1630 SCM_ASSERT (SCM_INUMP (port_or_fd)
1631 || (SCM_OPOUTPORTP (port_or_fd)),
1632 port_or_fd, SCM_ARG2, FUNC_NAME);
1633 vlen = SCM_LENGTH (v);
1634
1635 loop:
1636 switch SCM_TYP7 (v)
1637 {
1638 default:
1639 badarg1:SCM_WTA (1, v);
1640 case scm_tc7_smob:
1641 SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
1642 v = scm_ra2contig (v, 1);
1643 cstart = SCM_ARRAY_BASE (v);
1644 vlen = SCM_ARRAY_DIMS (v)->inc
1645 * (SCM_ARRAY_DIMS (v)->ubnd - SCM_ARRAY_DIMS (v)->lbnd + 1);
1646 v = SCM_ARRAY_V (v);
1647 goto loop;
1648 case scm_tc7_string:
1649 case scm_tc7_byvect:
1650 sz = sizeof (char);
1651 break;
1652 case scm_tc7_bvect:
1653 vlen = (vlen + SCM_LONG_BIT - 1) / SCM_LONG_BIT;
1654 cstart /= SCM_LONG_BIT;
1655 case scm_tc7_uvect:
1656 case scm_tc7_ivect:
1657 sz = sizeof (long);
1658 break;
1659 case scm_tc7_svect:
1660 sz = sizeof (short);
1661 break;
1662 #ifdef HAVE_LONG_LONGS
1663 case scm_tc7_llvect:
1664 sz = sizeof (long_long);
1665 break;
1666 #endif
1667 case scm_tc7_fvect:
1668 sz = sizeof (float);
1669 break;
1670 case scm_tc7_dvect:
1671 sz = sizeof (double);
1672 break;
1673 case scm_tc7_cvect:
1674 sz = 2 * sizeof (double);
1675 break;
1676 }
1677
1678 cend = vlen;
1679 if (!SCM_UNBNDP (start))
1680 {
1681 offset =
1682 SCM_NUM2LONG (3, start);
1683
1684 if (offset < 0 || offset >= cend)
1685 scm_out_of_range (FUNC_NAME, start);
1686
1687 if (!SCM_UNBNDP (end))
1688 {
1689 long tend =
1690 SCM_NUM2LONG (4, end);
1691
1692 if (tend <= offset || tend > cend)
1693 scm_out_of_range (FUNC_NAME, end);
1694 cend = tend;
1695 }
1696 }
1697
1698 if (SCM_NIMP (port_or_fd))
1699 {
1700 char *source = SCM_CHARS (v) + (cstart + offset) * sz;
1701
1702 ans = cend - offset;
1703 scm_lfwrite (source, ans * sz, port_or_fd);
1704 }
1705 else /* file descriptor. */
1706 {
1707 SCM_SYSCALL (ans = write (SCM_INUM (port_or_fd),
1708 SCM_CHARS (v) + (cstart + offset) * sz,
1709 (scm_sizet) (sz * (cend - offset))));
1710 if (ans == -1)
1711 SCM_SYSERROR;
1712 }
1713 if (SCM_TYP7 (v) == scm_tc7_bvect)
1714 ans *= SCM_LONG_BIT;
1715
1716 return SCM_MAKINUM (ans);
1717 }
1718 #undef FUNC_NAME
1719
1720
1721 static char cnt_tab[16] =
1722 {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
1723
1724 SCM_DEFINE (scm_bit_count, "bit-count", 2, 0, 0,
1725 (SCM item, SCM seq),
1726 "Returns the number occurrences of @var{bool} in @var{bv}.")
1727 #define FUNC_NAME s_scm_bit_count
1728 {
1729 long i;
1730 register unsigned long cnt = 0;
1731 register unsigned long w;
1732 SCM_VALIDATE_INUM (2,seq);
1733 switch SCM_TYP7 (seq)
1734 {
1735 default:
1736 SCM_WTA (2,seq);
1737 case scm_tc7_bvect:
1738 if (0 == SCM_LENGTH (seq))
1739 return SCM_INUM0;
1740 i = (SCM_LENGTH (seq) - 1) / SCM_LONG_BIT;
1741 w = SCM_UNPACK (SCM_VELTS (seq)[i]);
1742 if (SCM_FALSEP (item))
1743 w = ~w;
1744 w <<= SCM_LONG_BIT - 1 - ((SCM_LENGTH (seq) - 1) % SCM_LONG_BIT);
1745 while (!0)
1746 {
1747 for (; w; w >>= 4)
1748 cnt += cnt_tab[w & 0x0f];
1749 if (0 == i--)
1750 return SCM_MAKINUM (cnt);
1751 w = SCM_UNPACK (SCM_VELTS (seq)[i]);
1752 if (SCM_FALSEP (item))
1753 w = ~w;
1754 }
1755 }
1756 }
1757 #undef FUNC_NAME
1758
1759
1760 SCM_DEFINE (scm_bit_position, "bit-position", 3, 0, 0,
1761 (SCM item, SCM v, SCM k),
1762 "Returns the minimum index of an occurrence of @var{bool} in @var{bv}\n"
1763 "which is at least @var{k}. If no @var{bool} occurs within the specified\n"
1764 "range @code{#f} is returned.")
1765 #define FUNC_NAME s_scm_bit_position
1766 {
1767 long i, lenw, xbits, pos;
1768 register unsigned long w;
1769 SCM_VALIDATE_NIM (2,v);
1770 SCM_VALIDATE_INUM_COPY (3,k,pos);
1771 SCM_ASSERT ((pos <= SCM_LENGTH (v)) && (pos >= 0),
1772 k, SCM_OUTOFRANGE, FUNC_NAME);
1773 if (pos == SCM_LENGTH (v))
1774 return SCM_BOOL_F;
1775 switch SCM_TYP7 (v)
1776 {
1777 default:
1778 SCM_WTA (2,v);
1779 case scm_tc7_bvect:
1780 if (0 == SCM_LENGTH (v))
1781 return SCM_MAKINUM (-1L);
1782 lenw = (SCM_LENGTH (v) - 1) / SCM_LONG_BIT; /* watch for part words */
1783 i = pos / SCM_LONG_BIT;
1784 w = SCM_UNPACK (SCM_VELTS (v)[i]);
1785 if (SCM_FALSEP (item))
1786 w = ~w;
1787 xbits = (pos % SCM_LONG_BIT);
1788 pos -= xbits;
1789 w = ((w >> xbits) << xbits);
1790 xbits = SCM_LONG_BIT - 1 - (SCM_LENGTH (v) - 1) % SCM_LONG_BIT;
1791 while (!0)
1792 {
1793 if (w && (i == lenw))
1794 w = ((w << xbits) >> xbits);
1795 if (w)
1796 while (w)
1797 switch (w & 0x0f)
1798 {
1799 default:
1800 return SCM_MAKINUM (pos);
1801 case 2:
1802 case 6:
1803 case 10:
1804 case 14:
1805 return SCM_MAKINUM (pos + 1);
1806 case 4:
1807 case 12:
1808 return SCM_MAKINUM (pos + 2);
1809 case 8:
1810 return SCM_MAKINUM (pos + 3);
1811 case 0:
1812 pos += 4;
1813 w >>= 4;
1814 }
1815 if (++i > lenw)
1816 break;
1817 pos += SCM_LONG_BIT;
1818 w = SCM_UNPACK (SCM_VELTS (v)[i]);
1819 if (SCM_FALSEP (item))
1820 w = ~w;
1821 }
1822 return SCM_BOOL_F;
1823 }
1824 }
1825 #undef FUNC_NAME
1826
1827
1828 SCM_DEFINE (scm_bit_set_star_x, "bit-set*!", 3, 0, 0,
1829 (SCM v, SCM kv, SCM obj),
1830 "If uve is a bit-vector @var{bv} and uve must be of the same length. If\n"
1831 "@var{bool} is @code{#t}, uve is OR'ed into @var{bv}; If @var{bool} is @code{#f}, the\n"
1832 "inversion of uve is AND'ed into @var{bv}.\n\n"
1833 "If uve is a unsigned integer vector all the elements of uve must be\n"
1834 "between 0 and the @code{LENGTH} of @var{bv}. The bits of @var{bv}\n"
1835 "corresponding to the indexes in uve are set to @var{bool}.\n\n"
1836 "The return value is unspecified.")
1837 #define FUNC_NAME s_scm_bit_set_star_x
1838 {
1839 register long i, k, vlen;
1840 SCM_ASRTGO (SCM_NIMP (v), badarg1);
1841 SCM_ASRTGO (SCM_NIMP (kv), badarg2);
1842 switch SCM_TYP7 (kv)
1843 {
1844 default:
1845 badarg2:SCM_WTA (2,kv);
1846 case scm_tc7_uvect:
1847 switch SCM_TYP7 (v)
1848 {
1849 default:
1850 badarg1: SCM_WTA (1,v);
1851 case scm_tc7_bvect:
1852 vlen = SCM_LENGTH (v);
1853 if (SCM_FALSEP (obj))
1854 for (i = SCM_LENGTH (kv); i;)
1855 {
1856 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
1857 SCM_ASSERT ((k < vlen), SCM_MAKINUM (k), SCM_OUTOFRANGE, FUNC_NAME);
1858 SCM_BITVEC_CLR(v,k);
1859 }
1860 else if (SCM_TRUE_P (obj))
1861 for (i = SCM_LENGTH (kv); i;)
1862 {
1863 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
1864 SCM_ASSERT ((k < vlen), SCM_MAKINUM (k), SCM_OUTOFRANGE, FUNC_NAME);
1865 SCM_BITVEC_SET(v,k);
1866 }
1867 else
1868 badarg3:SCM_WTA (3,obj);
1869 }
1870 break;
1871 case scm_tc7_bvect:
1872 SCM_ASRTGO (SCM_TYP7 (v) == scm_tc7_bvect && SCM_LENGTH (v) == SCM_LENGTH (kv), badarg1);
1873 if (SCM_FALSEP (obj))
1874 for (k = (SCM_LENGTH (v) + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
1875 SCM_UNPACK (SCM_VELTS (v)[k]) &= ~ SCM_UNPACK(SCM_VELTS (kv)[k]);
1876 else if (SCM_TRUE_P (obj))
1877 for (k = (SCM_LENGTH (v) + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
1878 SCM_UNPACK (SCM_VELTS (v)[k]) |= SCM_UNPACK (SCM_VELTS (kv)[k]);
1879 else
1880 goto badarg3;
1881 break;
1882 }
1883 return SCM_UNSPECIFIED;
1884 }
1885 #undef FUNC_NAME
1886
1887
1888 SCM_DEFINE (scm_bit_count_star, "bit-count*", 3, 0, 0,
1889 (SCM v, SCM kv, SCM obj),
1890 "Returns\n"
1891 "@example\n"
1892 "(bit-count (bit-set*! (if bool bv (bit-invert! bv)) uve #t) #t).\n"
1893 "@end example\n"
1894 "@var{bv} is not modified.")
1895 #define FUNC_NAME s_scm_bit_count_star
1896 {
1897 register long i, vlen, count = 0;
1898 register unsigned long k;
1899 int fObj = 0;
1900
1901 SCM_ASRTGO (SCM_NIMP (v), badarg1);
1902 SCM_ASRTGO (SCM_NIMP (kv), badarg2);
1903 switch SCM_TYP7 (kv)
1904 {
1905 default:
1906 badarg2:
1907 SCM_WTA (2,kv);
1908 case scm_tc7_uvect:
1909 switch SCM_TYP7
1910 (v)
1911 {
1912 default:
1913 badarg1:
1914 SCM_WTA (1,v);
1915 case scm_tc7_bvect:
1916 vlen = SCM_LENGTH (v);
1917 if (SCM_FALSEP (obj))
1918 for (i = SCM_LENGTH (kv); i;)
1919 {
1920 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
1921 SCM_ASSERT ((k < vlen), SCM_MAKINUM (k), SCM_OUTOFRANGE, FUNC_NAME);
1922 if (!SCM_BITVEC_REF(v,k))
1923 count++;
1924 }
1925 else if (SCM_TRUE_P (obj))
1926 for (i = SCM_LENGTH (kv); i;)
1927 {
1928 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
1929 SCM_ASSERT ((k < vlen), SCM_MAKINUM (k), SCM_OUTOFRANGE, FUNC_NAME);
1930 if (SCM_BITVEC_REF (v,k))
1931 count++;
1932 }
1933 else
1934 badarg3:SCM_WTA (3,obj);
1935 }
1936 break;
1937 case scm_tc7_bvect:
1938 SCM_ASRTGO (SCM_TYP7 (v) == scm_tc7_bvect && SCM_LENGTH (v) == SCM_LENGTH (kv), badarg1);
1939 if (0 == SCM_LENGTH (v))
1940 return SCM_INUM0;
1941 SCM_ASRTGO (SCM_BOOLP (obj), badarg3);
1942 fObj = SCM_TRUE_P (obj);
1943 i = (SCM_LENGTH (v) - 1) / SCM_LONG_BIT;
1944 k = SCM_UNPACK (SCM_VELTS (kv)[i]) & (fObj ? SCM_UNPACK (SCM_VELTS (v)[i]) : ~ SCM_UNPACK (SCM_VELTS (v)[i]));
1945 k <<= SCM_LONG_BIT - 1 - ((SCM_LENGTH (v) - 1) % SCM_LONG_BIT);
1946 while (1)
1947 {
1948 for (; k; k >>= 4)
1949 count += cnt_tab[k & 0x0f];
1950 if (0 == i--)
1951 return SCM_MAKINUM (count);
1952
1953 /* urg. repetitive (see above.) */
1954 k = SCM_UNPACK (SCM_VELTS (kv)[i]) & (fObj ? SCM_UNPACK(SCM_VELTS (v)[i]) : ~SCM_UNPACK (SCM_VELTS (v)[i]));
1955 }
1956 }
1957 return SCM_MAKINUM (count);
1958 }
1959 #undef FUNC_NAME
1960
1961
1962 SCM_DEFINE (scm_bit_invert_x, "bit-invert!", 1, 0, 0,
1963 (SCM v),
1964 "Modifies @var{bv} by replacing each element with its negation.")
1965 #define FUNC_NAME s_scm_bit_invert_x
1966 {
1967 register long k;
1968 SCM_ASRTGO (SCM_NIMP (v), badarg1);
1969 k = SCM_LENGTH (v);
1970 switch SCM_TYP7
1971 (v)
1972 {
1973 case scm_tc7_bvect:
1974 for (k = (k + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
1975 SCM_UNPACK (SCM_VELTS (v)[k]) = ~SCM_UNPACK(SCM_VELTS (v)[k]);
1976 break;
1977 default:
1978 badarg1:SCM_WTA (1,v);
1979 }
1980 return SCM_UNSPECIFIED;
1981 }
1982 #undef FUNC_NAME
1983
1984
1985 SCM
1986 scm_istr2bve (char *str, long len)
1987 {
1988 SCM v = scm_make_uve (len, SCM_BOOL_T);
1989 long *data = (long *) SCM_VELTS (v);
1990 register unsigned long mask;
1991 register long k;
1992 register long j;
1993 for (k = 0; k < (len + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k++)
1994 {
1995 data[k] = 0L;
1996 j = len - k * SCM_LONG_BIT;
1997 if (j > SCM_LONG_BIT)
1998 j = SCM_LONG_BIT;
1999 for (mask = 1L; j--; mask <<= 1)
2000 switch (*str++)
2001 {
2002 case '0':
2003 break;
2004 case '1':
2005 data[k] |= mask;
2006 break;
2007 default:
2008 return SCM_BOOL_F;
2009 }
2010 }
2011 return v;
2012 }
2013
2014
2015
2016 static SCM
2017 ra2l (SCM ra,scm_sizet base,scm_sizet k)
2018 {
2019 register SCM res = SCM_EOL;
2020 register long inc = SCM_ARRAY_DIMS (ra)[k].inc;
2021 register scm_sizet i;
2022 if (SCM_ARRAY_DIMS (ra)[k].ubnd < SCM_ARRAY_DIMS (ra)[k].lbnd)
2023 return SCM_EOL;
2024 i = base + (1 + SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd) * inc;
2025 if (k < SCM_ARRAY_NDIM (ra) - 1)
2026 {
2027 do
2028 {
2029 i -= inc;
2030 res = scm_cons (ra2l (ra, i, k + 1), res);
2031 }
2032 while (i != base);
2033 }
2034 else
2035 do
2036 {
2037 i -= inc;
2038 res = scm_cons (scm_uniform_vector_ref (SCM_ARRAY_V (ra), SCM_MAKINUM (i)), res);
2039 }
2040 while (i != base);
2041 return res;
2042 }
2043
2044
2045 SCM_DEFINE (scm_array_to_list, "array->list", 1, 0, 0,
2046 (SCM v),
2047 "Returns a list consisting of all the elements, in order, of @var{array}.")
2048 #define FUNC_NAME s_scm_array_to_list
2049 {
2050 SCM res = SCM_EOL;
2051 register long k;
2052 SCM_ASRTGO (SCM_NIMP (v), badarg1);
2053 switch SCM_TYP7
2054 (v)
2055 {
2056 default:
2057 badarg1:SCM_WTA (1,v);
2058 case scm_tc7_smob:
2059 SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
2060 return ra2l (v, SCM_ARRAY_BASE (v), 0);
2061 case scm_tc7_vector:
2062 case scm_tc7_wvect:
2063 return scm_vector_to_list (v);
2064 case scm_tc7_string:
2065 return scm_string_to_list (v);
2066 case scm_tc7_bvect:
2067 {
2068 long *data = (long *) SCM_VELTS (v);
2069 register unsigned long mask;
2070 for (k = (SCM_LENGTH (v) - 1) / SCM_LONG_BIT; k > 0; k--)
2071 for (mask = 1UL << (SCM_LONG_BIT - 1); mask; mask >>= 1)
2072 res = scm_cons (SCM_BOOL(((long *) data)[k] & mask), res);
2073 for (mask = 1L << ((SCM_LENGTH (v) % SCM_LONG_BIT) - 1); mask; mask >>= 1)
2074 res = scm_cons (SCM_BOOL(((long *) data)[k] & mask), res);
2075 return res;
2076 }
2077 case scm_tc7_uvect: {
2078 long *data = (long *)SCM_VELTS(v);
2079 for (k = SCM_LENGTH(v) - 1; k >= 0; k--)
2080 res = scm_cons(scm_ulong2num(data[k]), res);
2081 return res;
2082 }
2083 case scm_tc7_ivect: {
2084 long *data = (long *)SCM_VELTS(v);
2085 for (k = SCM_LENGTH(v) - 1; k >= 0; k--)
2086 res = scm_cons(scm_long2num(data[k]), res);
2087 return res;
2088 }
2089 case scm_tc7_svect: {
2090 short *data;
2091 data = (short *)SCM_VELTS(v);
2092 for (k = SCM_LENGTH(v) - 1; k >= 0; k--)
2093 res = scm_cons(SCM_MAKINUM (data[k]), res);
2094 return res;
2095 }
2096 #ifdef HAVE_LONG_LONGS
2097 case scm_tc7_llvect: {
2098 long_long *data;
2099 data = (long_long *)SCM_VELTS(v);
2100 for (k = SCM_LENGTH(v) - 1; k >= 0; k--)
2101 res = scm_cons(scm_long_long2num(data[k]), res);
2102 return res;
2103 }
2104 #endif
2105
2106
2107 case scm_tc7_fvect:
2108 {
2109 float *data = (float *) SCM_VELTS (v);
2110 for (k = SCM_LENGTH (v) - 1; k >= 0; k--)
2111 res = scm_cons (scm_make_real (data[k]), res);
2112 return res;
2113 }
2114 case scm_tc7_dvect:
2115 {
2116 double *data = (double *) SCM_VELTS (v);
2117 for (k = SCM_LENGTH (v) - 1; k >= 0; k--)
2118 res = scm_cons (scm_make_real (data[k]), res);
2119 return res;
2120 }
2121 case scm_tc7_cvect:
2122 {
2123 double (*data)[2] = (double (*)[2]) SCM_VELTS (v);
2124 for (k = SCM_LENGTH (v) - 1; k >= 0; k--)
2125 res = scm_cons (scm_make_complex (data[k][0], data[k][1]), res);
2126 return res;
2127 }
2128 }
2129 }
2130 #undef FUNC_NAME
2131
2132
2133 static char s_bad_ralst[] = "Bad scm_array contents list";
2134
2135 static int l2ra(SCM lst, SCM ra, scm_sizet base, scm_sizet k);
2136
2137 SCM_DEFINE (scm_list_to_uniform_array, "list->uniform-array", 3, 0, 0,
2138 (SCM ndim, SCM prot, SCM lst),
2139 "@deffnx procedure list->uniform-vector prot lst\n"
2140 "Returns a uniform array of the type indicated by prototype @var{prot}\n"
2141 "with elements the same as those of @var{lst}. Elements must be of the\n"
2142 "appropriate type, no coercions are done.")
2143 #define FUNC_NAME s_scm_list_to_uniform_array
2144 {
2145 SCM shp = SCM_EOL;
2146 SCM row = lst;
2147 SCM ra;
2148 scm_sizet k;
2149 long n;
2150 SCM_VALIDATE_INUM_COPY (1,ndim,k);
2151 while (k--)
2152 {
2153 n = scm_ilength (row);
2154 SCM_ASSERT (n >= 0, lst, SCM_ARG3, FUNC_NAME);
2155 shp = scm_cons (SCM_MAKINUM (n), shp);
2156 if (SCM_NIMP (row))
2157 row = SCM_CAR (row);
2158 }
2159 ra = scm_dimensions_to_uniform_array (scm_reverse (shp), prot,
2160 SCM_UNDEFINED);
2161 if (SCM_NULLP (shp))
2162
2163 {
2164 SCM_ASRTGO (1 == scm_ilength (lst), badlst);
2165 scm_array_set_x (ra, SCM_CAR (lst), SCM_EOL);
2166 return ra;
2167 }
2168 if (!SCM_ARRAYP (ra))
2169 {
2170 for (k = 0; k < SCM_LENGTH (ra); k++, lst = SCM_CDR (lst))
2171 scm_array_set_x (ra, SCM_CAR (lst), SCM_MAKINUM (k));
2172 return ra;
2173 }
2174 if (l2ra (lst, ra, SCM_ARRAY_BASE (ra), 0))
2175 return ra;
2176 else
2177 badlst:scm_wta (lst, s_bad_ralst, FUNC_NAME);
2178 return SCM_BOOL_F;
2179 }
2180 #undef FUNC_NAME
2181
2182 static int
2183 l2ra (SCM lst, SCM ra, scm_sizet base, scm_sizet k)
2184 {
2185 register long inc = SCM_ARRAY_DIMS (ra)[k].inc;
2186 register long n = (1 + SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd);
2187 int ok = 1;
2188 if (n <= 0)
2189 return (SCM_NULLP (lst));
2190 if (k < SCM_ARRAY_NDIM (ra) - 1)
2191 {
2192 while (n--)
2193 {
2194 if (SCM_IMP (lst) || SCM_NCONSP (lst))
2195 return 0;
2196 ok = ok && l2ra (SCM_CAR (lst), ra, base, k + 1);
2197 base += inc;
2198 lst = SCM_CDR (lst);
2199 }
2200 if (SCM_NNULLP (lst))
2201 return 0;
2202 }
2203 else
2204 {
2205 while (n--)
2206 {
2207 if (SCM_IMP (lst) || SCM_NCONSP (lst))
2208 return 0;
2209 scm_array_set_x (SCM_ARRAY_V (ra), SCM_CAR (lst), SCM_MAKINUM (base));
2210 base += inc;
2211 lst = SCM_CDR (lst);
2212 }
2213 if (SCM_NNULLP (lst))
2214 return 0;
2215 }
2216 return ok;
2217 }
2218
2219
2220 static void
2221 rapr1 (SCM ra,scm_sizet j,scm_sizet k,SCM port,scm_print_state *pstate)
2222 {
2223 long inc = 1;
2224 long n = SCM_LENGTH (ra);
2225 int enclosed = 0;
2226 tail:
2227 switch SCM_TYP7 (ra)
2228 {
2229 case scm_tc7_smob:
2230 if (enclosed++)
2231 {
2232 SCM_ARRAY_BASE (ra) = j;
2233 if (n-- > 0)
2234 scm_iprin1 (ra, port, pstate);
2235 for (j += inc; n-- > 0; j += inc)
2236 {
2237 scm_putc (' ', port);
2238 SCM_ARRAY_BASE (ra) = j;
2239 scm_iprin1 (ra, port, pstate);
2240 }
2241 break;
2242 }
2243 if (k + 1 < SCM_ARRAY_NDIM (ra))
2244 {
2245 long i;
2246 inc = SCM_ARRAY_DIMS (ra)[k].inc;
2247 for (i = SCM_ARRAY_DIMS (ra)[k].lbnd; i < SCM_ARRAY_DIMS (ra)[k].ubnd; i++)
2248 {
2249 scm_putc ('(', port);
2250 rapr1 (ra, j, k + 1, port, pstate);
2251 scm_puts (") ", port);
2252 j += inc;
2253 }
2254 if (i == SCM_ARRAY_DIMS (ra)[k].ubnd)
2255 { /* could be zero size. */
2256 scm_putc ('(', port);
2257 rapr1 (ra, j, k + 1, port, pstate);
2258 scm_putc (')', port);
2259 }
2260 break;
2261 }
2262 if SCM_ARRAY_NDIM
2263 (ra)
2264 { /* Could be zero-dimensional */
2265 inc = SCM_ARRAY_DIMS (ra)[k].inc;
2266 n = (SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1);
2267 }
2268 else
2269 n = 1;
2270 ra = SCM_ARRAY_V (ra);
2271 goto tail;
2272 default:
2273 /* scm_tc7_bvect and scm_tc7_llvect only? */
2274 if (n-- > 0)
2275 scm_iprin1 (scm_uniform_vector_ref (ra, SCM_MAKINUM (j)), port, pstate);
2276 for (j += inc; n-- > 0; j += inc)
2277 {
2278 scm_putc (' ', port);
2279 scm_iprin1 (scm_cvref (ra, j, SCM_UNDEFINED), port, pstate);
2280 }
2281 break;
2282 case scm_tc7_string:
2283 if (n-- > 0)
2284 scm_iprin1 (SCM_MAKE_CHAR (SCM_UCHARS (ra)[j]), port, pstate);
2285 if (SCM_WRITINGP (pstate))
2286 for (j += inc; n-- > 0; j += inc)
2287 {
2288 scm_putc (' ', port);
2289 scm_iprin1 (SCM_MAKE_CHAR (SCM_UCHARS (ra)[j]), port, pstate);
2290 }
2291 else
2292 for (j += inc; n-- > 0; j += inc)
2293 scm_putc (SCM_CHARS (ra)[j], port);
2294 break;
2295 case scm_tc7_byvect:
2296 if (n-- > 0)
2297 scm_intprint (((char *) SCM_CELL_WORD_1 (ra))[j], 10, port);
2298 for (j += inc; n-- > 0; j += inc)
2299 {
2300 scm_putc (' ', port);
2301 scm_intprint (((char *)SCM_CELL_WORD_1 (ra))[j], 10, port);
2302 }
2303 break;
2304
2305 case scm_tc7_uvect:
2306 {
2307 char str[11];
2308
2309 if (n-- > 0)
2310 {
2311 /* intprint can't handle >= 2^31. */
2312 sprintf (str, "%lu", ((unsigned long *) SCM_VELTS (ra))[j]);
2313 scm_puts (str, port);
2314 }
2315 for (j += inc; n-- > 0; j += inc)
2316 {
2317 scm_putc (' ', port);
2318 sprintf (str, "%lu", ((unsigned long *) SCM_VELTS (ra))[j]);
2319 scm_puts (str, port);
2320 }
2321 }
2322 case scm_tc7_ivect:
2323 if (n-- > 0)
2324 scm_intprint (((signed long *) SCM_VELTS (ra))[j], 10, port);
2325 for (j += inc; n-- > 0; j += inc)
2326 {
2327 scm_putc (' ', port);
2328 scm_intprint (((signed long *) SCM_VELTS (ra))[j], 10, port);
2329 }
2330 break;
2331
2332 case scm_tc7_svect:
2333 if (n-- > 0)
2334 scm_intprint (((short *) SCM_CELL_WORD_1 (ra))[j], 10, port);
2335 for (j += inc; n-- > 0; j += inc)
2336 {
2337 scm_putc (' ', port);
2338 scm_intprint (((short *) SCM_CELL_WORD_1 (ra))[j], 10, port);
2339 }
2340 break;
2341
2342 case scm_tc7_fvect:
2343 if (n-- > 0)
2344 {
2345 SCM z = scm_make_real (1.0);
2346 SCM_REAL_VALUE (z) = ((float *) SCM_VELTS (ra))[j];
2347 scm_print_real (z, port, pstate);
2348 for (j += inc; n-- > 0; j += inc)
2349 {
2350 scm_putc (' ', port);
2351 SCM_REAL_VALUE (z) = ((float *) SCM_VELTS (ra))[j];
2352 scm_print_real (z, port, pstate);
2353 }
2354 }
2355 break;
2356 case scm_tc7_dvect:
2357 if (n-- > 0)
2358 {
2359 SCM z = scm_make_real (1.0 / 3.0);
2360 SCM_REAL_VALUE (z) = ((double *) SCM_VELTS (ra))[j];
2361 scm_print_real (z, port, pstate);
2362 for (j += inc; n-- > 0; j += inc)
2363 {
2364 scm_putc (' ', port);
2365 SCM_REAL_VALUE (z) = ((double *) SCM_VELTS (ra))[j];
2366 scm_print_real (z, port, pstate);
2367 }
2368 }
2369 break;
2370 case scm_tc7_cvect:
2371 if (n-- > 0)
2372 {
2373 SCM cz = scm_make_complex (0.0, 1.0), z = scm_make_real (1.0 / 3.0);
2374 SCM_REAL_VALUE (z) =
2375 SCM_COMPLEX_REAL (cz) = ((double *) SCM_VELTS (ra))[2 * j];
2376 SCM_COMPLEX_IMAG (cz) = ((double *) SCM_VELTS (ra))[2 * j + 1];
2377 scm_print_complex ((0.0 == SCM_COMPLEX_IMAG (cz) ? z : cz),
2378 port, pstate);
2379 for (j += inc; n-- > 0; j += inc)
2380 {
2381 scm_putc (' ', port);
2382 SCM_REAL_VALUE (z)
2383 = SCM_COMPLEX_REAL (cz) = ((double *) SCM_VELTS (ra))[2 * j];
2384 SCM_COMPLEX_IMAG (cz) = ((double *) SCM_VELTS (ra))[2 * j + 1];
2385 scm_print_complex ((0.0 == SCM_COMPLEX_IMAG (cz) ? z : cz),
2386 port, pstate);
2387 }
2388 }
2389 break;
2390 }
2391 }
2392
2393
2394
2395 int
2396 scm_raprin1 (SCM exp, SCM port, scm_print_state *pstate)
2397 {
2398 SCM v = exp;
2399 scm_sizet base = 0;
2400 scm_putc ('#', port);
2401 tail:
2402 switch SCM_TYP7 (v)
2403 {
2404 case scm_tc7_smob:
2405 {
2406 long ndim = SCM_ARRAY_NDIM (v);
2407 base = SCM_ARRAY_BASE (v);
2408 v = SCM_ARRAY_V (v);
2409 if (SCM_ARRAYP (v))
2410
2411 {
2412 scm_puts ("<enclosed-array ", port);
2413 rapr1 (exp, base, 0, port, pstate);
2414 scm_putc ('>', port);
2415 return 1;
2416 }
2417 else
2418 {
2419 scm_intprint (ndim, 10, port);
2420 goto tail;
2421 }
2422 }
2423 case scm_tc7_bvect:
2424 if (SCM_EQ_P (exp, v))
2425 { /* a uve, not an scm_array */
2426 register long i, j, w;
2427 scm_putc ('*', port);
2428 for (i = 0; i < (SCM_LENGTH (exp)) / SCM_LONG_BIT; i++)
2429 {
2430 scm_bits_t w = SCM_UNPACK (SCM_VELTS (exp)[i]);
2431 for (j = SCM_LONG_BIT; j; j--)
2432 {
2433 scm_putc (w & 1 ? '1' : '0', port);
2434 w >>= 1;
2435 }
2436 }
2437 j = SCM_LENGTH (exp) % SCM_LONG_BIT;
2438 if (j)
2439 {
2440 w = SCM_UNPACK (SCM_VELTS (exp)[SCM_LENGTH (exp) / SCM_LONG_BIT]);
2441 for (; j; j--)
2442 {
2443 scm_putc (w & 1 ? '1' : '0', port);
2444 w >>= 1;
2445 }
2446 }
2447 return 1;
2448 }
2449 else
2450 scm_putc ('b', port);
2451 break;
2452 case scm_tc7_string:
2453 scm_putc ('a', port);
2454 break;
2455 case scm_tc7_byvect:
2456 scm_putc ('y', port);
2457 break;
2458 case scm_tc7_uvect:
2459 scm_putc ('u', port);
2460 break;
2461 case scm_tc7_ivect:
2462 scm_putc ('e', port);
2463 break;
2464 case scm_tc7_svect:
2465 scm_putc ('h', port);
2466 break;
2467 #ifdef HAVE_LONG_LONGS
2468 case scm_tc7_llvect:
2469 scm_putc ('l', port);
2470 break;
2471 #endif
2472 case scm_tc7_fvect:
2473 scm_putc ('s', port);
2474 break;
2475 case scm_tc7_dvect:
2476 scm_putc ('i', port);
2477 break;
2478 case scm_tc7_cvect:
2479 scm_putc ('c', port);
2480 break;
2481 }
2482 scm_putc ('(', port);
2483 rapr1 (exp, base, 0, port, pstate);
2484 scm_putc (')', port);
2485 return 1;
2486 }
2487
2488 SCM_DEFINE (scm_array_prototype, "array-prototype", 1, 0, 0,
2489 (SCM ra),
2490 "Returns an object that would produce an array of the same type as\n"
2491 "@var{array}, if used as the @var{prototype} for\n"
2492 "@code{make-uniform-array}.")
2493 #define FUNC_NAME s_scm_array_prototype
2494 {
2495 int enclosed = 0;
2496 SCM_ASRTGO (SCM_NIMP (ra), badarg);
2497 loop:
2498 switch SCM_TYP7
2499 (ra)
2500 {
2501 default:
2502 badarg:SCM_WTA (1,ra);
2503 case scm_tc7_smob:
2504 SCM_ASRTGO (SCM_ARRAYP (ra), badarg);
2505 if (enclosed++)
2506 return SCM_UNSPECIFIED;
2507 ra = SCM_ARRAY_V (ra);
2508 goto loop;
2509 case scm_tc7_vector:
2510 case scm_tc7_wvect:
2511 return SCM_EOL;
2512 case scm_tc7_bvect:
2513 return SCM_BOOL_T;
2514 case scm_tc7_string:
2515 return SCM_MAKE_CHAR ('a');
2516 case scm_tc7_byvect:
2517 return SCM_MAKE_CHAR ('\0');
2518 case scm_tc7_uvect:
2519 return SCM_MAKINUM (1L);
2520 case scm_tc7_ivect:
2521 return SCM_MAKINUM (-1L);
2522 case scm_tc7_svect:
2523 return SCM_CDR (scm_intern ("s", 1));
2524 #ifdef HAVE_LONG_LONGS
2525 case scm_tc7_llvect:
2526 return SCM_CDR (scm_intern ("l", 1));
2527 #endif
2528 case scm_tc7_fvect:
2529 return scm_make_real (1.0);
2530 case scm_tc7_dvect:
2531 return scm_make_real (1.0 / 3.0);
2532 case scm_tc7_cvect:
2533 return scm_make_complex (0.0, 1.0);
2534 }
2535 }
2536 #undef FUNC_NAME
2537
2538
2539 static SCM
2540 markra (SCM ptr)
2541 {
2542 return SCM_ARRAY_V (ptr);
2543 }
2544
2545
2546 static scm_sizet
2547 freera (SCM ptr)
2548 {
2549 scm_must_free (SCM_CHARS (ptr));
2550 return sizeof (scm_array) + SCM_ARRAY_NDIM (ptr) * sizeof (scm_array_dim);
2551 }
2552
2553 void
2554 scm_init_unif ()
2555 {
2556 scm_tc16_array = scm_make_smob_type_mfpe ("array", 0,
2557 markra,
2558 freera,
2559 scm_raprin1,
2560 scm_array_equal_p);
2561 scm_add_feature ("array");
2562 #include "libguile/unif.x"
2563 }
2564
2565 /*
2566 Local Variables:
2567 c-file-style: "gnu"
2568 End:
2569 */