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