* Fix range checks of SCM_VALIDATE* macros.
[bpt/guile.git] / libguile / unif.c
CommitLineData
bc86da5d 1/* Copyright (C) 1995,1996,1997,1998, 2000 Free Software Foundation, Inc.
0f2d19dd
JB
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
82892bed
JB
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
0f2d19dd
JB
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.
82892bed 40 * If you do not wish that, delete this exception notice. */
1bbd0b84
GB
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
c209c88e
GB
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*/
0f2d19dd
JB
52\f
53
54#include <stdio.h>
a0599745
MD
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"
0f2d19dd 69
3d8d56df
GH
70#ifdef HAVE_UNISTD_H
71#include <unistd.h>
72#endif
73
0f2d19dd
JB
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
a515d287
MD
80 * signed long ivect
81 * unsigned long uvect
0f2d19dd
JB
82 * float fvect
83 * double dvect
84 * complex double cvect
85 * short svect
5c11cc9d 86 * long long llvect
0f2d19dd
JB
87 */
88
89long scm_tc16_array;
90
afe5177e
GH
91/* return the size of an element in a uniform array or 0 if type not
92 found. */
93scm_sizet
94scm_uniform_element_size (SCM obj)
0f2d19dd 95{
afe5177e 96 scm_sizet result;
0f2d19dd 97
afe5177e 98 switch (SCM_TYP7 (obj))
0f2d19dd 99 {
0f2d19dd 100 case scm_tc7_bvect:
0f2d19dd
JB
101 case scm_tc7_uvect:
102 case scm_tc7_ivect:
afe5177e 103 result = sizeof (long);
0f2d19dd 104 break;
afe5177e 105
0f2d19dd 106 case scm_tc7_byvect:
afe5177e 107 result = sizeof (char);
0f2d19dd
JB
108 break;
109
110 case scm_tc7_svect:
afe5177e 111 result = sizeof (short);
0f2d19dd 112 break;
afe5177e 113
5c11cc9d 114#ifdef HAVE_LONG_LONGS
0f2d19dd 115 case scm_tc7_llvect:
afe5177e 116 result = sizeof (long_long);
0f2d19dd
JB
117 break;
118#endif
119
0f2d19dd 120 case scm_tc7_fvect:
afe5177e 121 result = sizeof (float);
0f2d19dd 122 break;
afe5177e 123
0f2d19dd 124 case scm_tc7_dvect:
afe5177e 125 result = sizeof (double);
0f2d19dd 126 break;
afe5177e 127
0f2d19dd 128 case scm_tc7_cvect:
afe5177e 129 result = 2 * sizeof (double);
0f2d19dd 130 break;
afe5177e
GH
131
132 default:
133 result = 0;
0f2d19dd 134 }
afe5177e 135 return result;
0f2d19dd
JB
136}
137
bc86da5d
MD
138/* Silly function used not to modify the semantics of the silly
139 * prototype system in order to be backward compatible.
140 */
141static int
142singp (SCM obj)
0f2d19dd 143{
bc86da5d
MD
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 }
0f2d19dd 152}
1cc91f1b 153
0f2d19dd 154SCM
1bbd0b84 155scm_make_uve (long k, SCM prot)
0f2d19dd
JB
156{
157 SCM v;
158 long i, type;
9a09deb1 159 if (SCM_EQ_P (prot, SCM_BOOL_T))
0f2d19dd
JB
160 {
161 i = sizeof (long) * ((k + SCM_LONG_BIT - 1) / SCM_LONG_BIT);
162 type = scm_tc7_bvect;
163 }
4260a7fc 164 else if (SCM_CHARP (prot) && (SCM_CHAR (prot) == '\0'))
0f2d19dd
JB
165 {
166 i = sizeof (char) * k;
167 type = scm_tc7_byvect;
168 }
7866a09b 169 else if (SCM_CHARP (prot))
0f2d19dd
JB
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 }
0c95b57d 182 else if (SCM_SYMBOLP (prot) && (1 == SCM_LENGTH (prot)))
0f2d19dd
JB
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 }
5c11cc9d 192#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
193 else if (s == 'l')
194 {
195 i = sizeof (long_long) * k;
196 type = scm_tc7_llvect;
197 }
198#endif
199 else
200 {
a8741caa 201 return scm_make_vector (SCM_MAKINUM (k), SCM_UNDEFINED);
0f2d19dd
JB
202 }
203 }
204 else
eb42e2f0 205 if (SCM_IMP (prot) || !SCM_INEXACTP (prot))
0f2d19dd 206 /* Huge non-unif vectors are NOT supported. */
5c11cc9d
GH
207 /* no special scm_vector */
208 return scm_make_vector (SCM_MAKINUM (k), SCM_UNDEFINED);
bc86da5d 209 else if (singp (prot))
0f2d19dd
JB
210 {
211 i = sizeof (float) * k;
212 type = scm_tc7_fvect;
213 }
eb42e2f0 214 else if (SCM_COMPLEXP (prot))
0f2d19dd
JB
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 }
0f2d19dd
JB
224
225 SCM_NEWCELL (v);
226 SCM_DEFER_INTS;
5c11cc9d 227 SCM_SETCHARS (v, (char *) scm_must_malloc (i ? i : 1, "vector"));
0f2d19dd
JB
228 SCM_SETLENGTH (v, (k < SCM_LENGTH_MAX ? k : SCM_LENGTH_MAX), type);
229 SCM_ALLOW_INTS;
230 return v;
231}
232
3b3b36dd 233SCM_DEFINE (scm_uniform_vector_length, "uniform-vector-length", 1, 0, 0,
1bbd0b84 234 (SCM v),
b380b885 235 "Returns the number of elements in @var{uve}.")
1bbd0b84 236#define FUNC_NAME s_scm_uniform_vector_length
0f2d19dd
JB
237{
238 SCM_ASRTGO (SCM_NIMP (v), badarg1);
239 switch SCM_TYP7
240 (v)
241 {
242 default:
1bbd0b84 243 badarg1:SCM_WTA(1,v);
0f2d19dd
JB
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:
95f5b0f5 253 case scm_tc7_wvect:
0f2d19dd 254 case scm_tc7_svect:
5c11cc9d 255#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
256 case scm_tc7_llvect:
257#endif
258 return SCM_MAKINUM (SCM_LENGTH (v));
259 }
260}
1bbd0b84 261#undef FUNC_NAME
0f2d19dd 262
3b3b36dd 263SCM_DEFINE (scm_array_p, "array?", 1, 1, 0,
1bbd0b84 264 (SCM v, SCM prot),
b380b885
MD
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.")
1bbd0b84 268#define FUNC_NAME s_scm_array_p
0f2d19dd
JB
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;
c209c88e
GB
276
277 while (SCM_TYP7 (v) == scm_tc7_smob)
0f2d19dd 278 {
0f2d19dd
JB
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);
c209c88e
GB
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:
9a09deb1 296 protp = (SCM_EQ_P (prot, SCM_BOOL_T));
c209c88e 297 case scm_tc7_string:
4260a7fc 298 protp = SCM_CHARP(prot) && (SCM_CHAR (prot) != '\0');
c209c88e 299 case scm_tc7_byvect:
4260a7fc 300 protp = SCM_EQ_P (prot, SCM_MAKE_CHAR ('\0'));
c209c88e
GB
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]);
5c11cc9d 310#ifdef HAVE_LONG_LONGS
c209c88e
GB
311 case scm_tc7_llvect:
312 protp = SCM_SYMBOLP (prot)
313 && (1 == SCM_LENGTH (prot))
314 && ('s' == SCM_CHARS (prot)[0]);
0f2d19dd 315#endif
c209c88e 316 case scm_tc7_fvect:
bc86da5d 317 protp = singp (prot);
c209c88e
GB
318 case scm_tc7_dvect:
319 protp = SCM_REALP(prot);
320 case scm_tc7_cvect:
eb42e2f0 321 protp = SCM_COMPLEXP(prot);
c209c88e
GB
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);
0f2d19dd 330 }
0f2d19dd 331}
1bbd0b84 332#undef FUNC_NAME
0f2d19dd
JB
333
334
3b3b36dd 335SCM_DEFINE (scm_array_rank, "array-rank", 1, 0, 0,
1bbd0b84 336 (SCM ra),
b380b885
MD
337 "Returns the number of dimensions of @var{obj}. If @var{obj} is not an\n"
338 "array, @code{0} is returned.")
1bbd0b84 339#define FUNC_NAME s_scm_array_rank
0f2d19dd
JB
340{
341 if (SCM_IMP (ra))
1bbd0b84 342 return SCM_INUM0;
0f2d19dd
JB
343 switch (SCM_TYP7 (ra))
344 {
345 default:
346 return SCM_INUM0;
347 case scm_tc7_string:
348 case scm_tc7_vector:
95f5b0f5 349 case scm_tc7_wvect:
0f2d19dd
JB
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:
5c11cc9d 356#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
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}
1bbd0b84 367#undef FUNC_NAME
0f2d19dd
JB
368
369
3b3b36dd 370SCM_DEFINE (scm_array_dimensions, "array-dimensions", 1, 0, 0,
1bbd0b84 371 (SCM ra),
b380b885
MD
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")
1bbd0b84 377#define FUNC_NAME s_scm_array_dimensions
0f2d19dd
JB
378{
379 SCM res = SCM_EOL;
380 scm_sizet k;
381 scm_array_dim *s;
382 if (SCM_IMP (ra))
1bbd0b84 383 return SCM_BOOL_F;
0f2d19dd
JB
384 switch (SCM_TYP7 (ra))
385 {
386 default:
387 return SCM_BOOL_F;
388 case scm_tc7_string:
389 case scm_tc7_vector:
95f5b0f5 390 case scm_tc7_wvect:
0f2d19dd
JB
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:
5c11cc9d 399#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
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--)
e2d37336
MD
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);
0f2d19dd
JB
415 return res;
416 }
417}
1bbd0b84 418#undef FUNC_NAME
0f2d19dd
JB
419
420
e2d37336
MD
421SCM_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
432SCM_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
443SCM_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
0f2d19dd
JB
461static char s_bad_ind[] = "Bad scm_array index";
462
1cc91f1b 463
0f2d19dd 464long
1bbd0b84 465scm_aind (SCM ra, SCM args, const char *what)
0f2d19dd
JB
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))
0f2d19dd 473 {
f5bf2977 474 SCM_ASSERT (1 == k, scm_makfrom0str (what), SCM_WNA, NULL);
0f2d19dd
JB
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 }
f5bf2977
GH
488 SCM_ASSERT (0 == k && SCM_NULLP (args), scm_makfrom0str (what), SCM_WNA,
489 NULL);
0f2d19dd
JB
490 return pos;
491}
492
493
1cc91f1b 494
0f2d19dd 495SCM
1bbd0b84 496scm_make_ra (int ndim)
0f2d19dd
JB
497{
498 SCM ra;
499 SCM_NEWCELL (ra);
500 SCM_DEFER_INTS;
23a62151
MD
501 SCM_NEWSMOB(ra, ((long) ndim << 17) + scm_tc16_array,
502 scm_must_malloc ((long) (sizeof (scm_array) + ndim * sizeof (scm_array_dim)),
0f2d19dd 503 "array"));
0f2d19dd
JB
504 SCM_ARRAY_V (ra) = scm_nullvect;
505 SCM_ALLOW_INTS;
506 return ra;
507}
508
509static char s_bad_spec[] = "Bad scm_array dimension";
510/* Increments will still need to be set. */
511
1cc91f1b 512
0f2d19dd 513SCM
1bbd0b84 514scm_shap2ra (SCM args, const char *what)
0f2d19dd
JB
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 {
20a54673
GH
529 SCM_ASSERT (SCM_INUMP (spec) && SCM_INUM (spec) >= 0, spec,
530 s_bad_spec, what);
0f2d19dd
JB
531 s->lbnd = 0;
532 s->ubnd = SCM_INUM (spec) - 1;
533 s->inc = 1;
534 }
535 else
536 {
20a54673
GH
537 SCM_ASSERT (SCM_CONSP (spec) && SCM_INUMP (SCM_CAR (spec)), spec,
538 s_bad_spec, what);
0f2d19dd
JB
539 s->lbnd = SCM_INUM (SCM_CAR (spec));
540 sp = SCM_CDR (spec);
0c95b57d 541 SCM_ASSERT (SCM_CONSP (sp)
20a54673
GH
542 && SCM_INUMP (SCM_CAR (sp)) && SCM_NULLP (SCM_CDR (sp)),
543 spec, s_bad_spec, what);
0f2d19dd
JB
544 s->ubnd = SCM_INUM (SCM_CAR (sp));
545 s->inc = 1;
546 }
547 }
548 return ra;
549}
550
3b3b36dd 551SCM_DEFINE (scm_dimensions_to_uniform_array, "dimensions->uniform-array", 2, 1, 0,
1bbd0b84 552 (SCM dims, SCM prot, SCM fill),
b380b885
MD
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.")
1bbd0b84 558#define FUNC_NAME s_scm_dimensions_to_uniform_array
0f2d19dd
JB
559{
560 scm_sizet k, vlen = 1;
561 long rlen = 1;
562 scm_array_dim *s;
563 SCM ra;
564 if (SCM_INUMP (dims))
cda139a7 565 {
0f2d19dd
JB
566 if (SCM_INUM (dims) < SCM_LENGTH_MAX)
567 {
5c11cc9d
GH
568 SCM answer = scm_make_uve (SCM_INUM (dims), prot);
569
570 if (!SCM_UNBNDP (fill))
571 scm_array_fill_x (answer, fill);
0c95b57d 572 else if (SCM_SYMBOLP (prot))
0f2d19dd
JB
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);
cda139a7 580 }
0c95b57d
GB
581 SCM_ASSERT (SCM_NULLP (dims) || SCM_CONSP (dims),
582 dims, SCM_ARG1, FUNC_NAME);
1bbd0b84 583 ra = scm_shap2ra (dims, FUNC_NAME);
898a256f 584 SCM_SETOR_CAR (ra, SCM_ARRAY_CONTIGUOUS);
0f2d19dd
JB
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 }
5c11cc9d 624 if (!SCM_UNBNDP (fill))
0f2d19dd 625 {
5c11cc9d 626 scm_array_fill_x (ra, fill);
0f2d19dd 627 }
0c95b57d 628 else if (SCM_SYMBOLP (prot))
0f2d19dd
JB
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}
1bbd0b84 637#undef FUNC_NAME
0f2d19dd 638
1cc91f1b 639
0f2d19dd 640void
1bbd0b84 641scm_ra_set_contp (SCM ra)
0f2d19dd
JB
642{
643 scm_sizet k = SCM_ARRAY_NDIM (ra);
0f2d19dd 644 if (k)
0f2d19dd 645 {
fe0c6dae
JB
646 long inc = SCM_ARRAY_DIMS (ra)[k - 1].inc;
647 while (k--)
0f2d19dd 648 {
fe0c6dae
JB
649 if (inc != SCM_ARRAY_DIMS (ra)[k].inc)
650 {
898a256f 651 SCM_SETAND_CAR (ra, ~SCM_ARRAY_CONTIGUOUS);
fe0c6dae
JB
652 return;
653 }
654 inc *= (SCM_ARRAY_DIMS (ra)[k].ubnd
655 - SCM_ARRAY_DIMS (ra)[k].lbnd + 1);
0f2d19dd 656 }
0f2d19dd 657 }
898a256f 658 SCM_SETOR_CAR (ra, SCM_ARRAY_CONTIGUOUS);
0f2d19dd
JB
659}
660
661
3b3b36dd 662SCM_DEFINE (scm_make_shared_array, "make-shared-array", 2, 0, 1,
1bbd0b84 663 (SCM oldra, SCM mapfunc, SCM dims),
b380b885
MD
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")
1bbd0b84 679#define FUNC_NAME s_scm_make_shared_array
0f2d19dd
JB
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;
3b3b36dd
GB
687 SCM_VALIDATE_ARRAY (1,oldra);
688 SCM_VALIDATE_PROC (2,mapfunc);
1bbd0b84 689 ra = scm_shap2ra (dims, FUNC_NAME);
0f2d19dd
JB
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 }
92396c0a 724 imap = scm_apply (mapfunc, scm_reverse (inds), SCM_EOL);
0f2d19dd 725 if (SCM_ARRAYP (oldra))
1bbd0b84 726 i = (scm_sizet) scm_aind (oldra, imap, FUNC_NAME);
0f2d19dd
JB
727 else
728 {
729 if (SCM_NINUMP (imap))
730
731 {
732 SCM_ASSERT (1 == scm_ilength (imap) && SCM_INUMP (SCM_CAR (imap)),
1bbd0b84 733 imap, s_bad_ind, FUNC_NAME);
0f2d19dd
JB
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 {
898a256f 745 SCM_SETCAR (indptr, SCM_MAKINUM (SCM_INUM (SCM_CAR (indptr)) + 1));
0f2d19dd
JB
746 imap = scm_apply (mapfunc, scm_reverse (inds), SCM_EOL);
747 if (SCM_ARRAYP (oldra))
748
1bbd0b84 749 s[k].inc = scm_aind (oldra, imap, FUNC_NAME) - i;
0f2d19dd
JB
750 else
751 {
752 if (SCM_NINUMP (imap))
753
754 {
755 SCM_ASSERT (1 == scm_ilength (imap) && SCM_INUMP (SCM_CAR (imap)),
1bbd0b84 756 imap, s_bad_ind, FUNC_NAME);
0f2d19dd
JB
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,
1bbd0b84 772 "mapping out of range", FUNC_NAME);
0f2d19dd
JB
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}
1bbd0b84 784#undef FUNC_NAME
0f2d19dd
JB
785
786
787/* args are RA . DIMS */
af45e3b0
DH
788SCM_DEFINE (scm_transpose_array, "transpose-array", 1, 0, 1,
789 (SCM ra, SCM args),
b380b885
MD
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")
1bbd0b84 807#define FUNC_NAME s_scm_transpose_array
0f2d19dd 808{
af45e3b0 809 SCM res, vargs, *ve = &vargs;
0f2d19dd
JB
810 scm_array_dim *s, *r;
811 int ndim, i, k;
af45e3b0 812
1bbd0b84 813 SCM_ASSERT (SCM_NIMP (ra), ra, SCM_ARG1, FUNC_NAME);
f5bf2977 814 switch (SCM_TYP7 (ra))
0f2d19dd
JB
815 {
816 default:
1bbd0b84 817 badarg:SCM_WTA (1,ra);
0f2d19dd
JB
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:
5c11cc9d 827#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
828 case scm_tc7_llvect:
829#endif
af45e3b0 830 SCM_ASSERT (!SCM_NULLP (args) && SCM_NULLP (SCM_CDR (args)),
1bbd0b84 831 scm_makfrom0str (FUNC_NAME), SCM_WNA, NULL);
f5bf2977 832 SCM_ASSERT (SCM_INUMP (SCM_CAR (args)), SCM_CAR (args), SCM_ARG2,
1bbd0b84 833 FUNC_NAME);
4260a7fc 834 SCM_ASSERT (SCM_EQ_P (SCM_INUM0, SCM_CAR (args)), SCM_CAR (args), SCM_OUTOFRANGE,
1bbd0b84 835 FUNC_NAME);
0f2d19dd
JB
836 return ra;
837 case scm_tc7_smob:
838 SCM_ASRTGO (SCM_ARRAYP (ra), badarg);
839 vargs = scm_vector (args);
f5bf2977 840 SCM_ASSERT (SCM_LENGTH (vargs) == SCM_ARRAY_NDIM (ra),
1bbd0b84 841 scm_makfrom0str (FUNC_NAME), SCM_WNA, NULL);
f5bf2977 842 ve = SCM_VELTS (vargs);
0f2d19dd
JB
843 ndim = 0;
844 for (k = 0; k < SCM_ARRAY_NDIM (ra); k++)
845 {
20a54673 846 SCM_ASSERT (SCM_INUMP (ve[k]), ve[k], (SCM_ARG2 + k),
1bbd0b84 847 FUNC_NAME);
0f2d19dd 848 i = SCM_INUM (ve[k]);
20a54673 849 SCM_ASSERT (i >= 0 && i < SCM_ARRAY_NDIM (ra), ve[k],
1bbd0b84 850 SCM_OUTOFRANGE, FUNC_NAME);
0f2d19dd
JB
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 }
1bbd0b84 887 SCM_ASSERT (ndim <= 0, args, "bad argument list", FUNC_NAME);
0f2d19dd
JB
888 scm_ra_set_contp (res);
889 return res;
890 }
891}
1bbd0b84 892#undef FUNC_NAME
0f2d19dd
JB
893
894/* args are RA . AXES */
af45e3b0
DH
895SCM_DEFINE (scm_enclose_array, "enclose-array", 1, 0, 1,
896 (SCM ra, SCM axes),
b380b885
MD
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")
1bbd0b84 915#define FUNC_NAME s_scm_enclose_array
0f2d19dd 916{
af45e3b0 917 SCM axv, res, ra_inr;
0f2d19dd
JB
918 scm_array_dim vdim, *s = &vdim;
919 int ndim, j, k, ninr, noutr;
af45e3b0 920
0f2d19dd 921 if (SCM_NULLP (axes))
0f2d19dd
JB
922 axes = scm_cons ((SCM_ARRAYP (ra) ? SCM_MAKINUM (SCM_ARRAY_NDIM (ra) - 1) : SCM_INUM0), SCM_EOL);
923 ninr = scm_ilength (axes);
af45e3b0 924 SCM_ASSERT (0 <= ninr, scm_makfrom0str (FUNC_NAME), SCM_WNA, NULL);
0f2d19dd
JB
925 ra_inr = scm_make_ra (ninr);
926 SCM_ASRTGO (SCM_NIMP (ra), badarg1);
927 switch SCM_TYP7
928 (ra)
929 {
930 default:
1bbd0b84 931 badarg1:SCM_WTA (1,ra);
0f2d19dd
JB
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:
95f5b0f5 941 case scm_tc7_wvect:
0f2d19dd 942 case scm_tc7_svect:
5c11cc9d 943#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
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;
7866a09b 962 axv = scm_make_string (SCM_MAKINUM (ndim), SCM_MAKE_CHAR (0));
af45e3b0 963 SCM_ASSERT (0 <= noutr, scm_makfrom0str (FUNC_NAME), SCM_WNA, NULL);
0f2d19dd
JB
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 {
1bbd0b84 969 SCM_ASSERT (SCM_INUMP (SCM_CAR (axes)), SCM_CAR (axes), "bad axis", FUNC_NAME);
0f2d19dd
JB
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}
1bbd0b84 988#undef FUNC_NAME
0f2d19dd
JB
989
990
991
af45e3b0
DH
992SCM_DEFINE (scm_array_in_bounds_p, "array-in-bounds?", 1, 0, 1,
993 (SCM v, SCM args),
b380b885 994 "Returns @code{#t} if its arguments would be acceptable to array-ref.")
1bbd0b84 995#define FUNC_NAME s_scm_array_in_bounds_p
0f2d19dd 996{
af45e3b0 997 SCM ind = SCM_EOL;
0f2d19dd
JB
998 long pos = 0;
999 register scm_sizet k;
1000 register long j;
1001 scm_array_dim *s;
af45e3b0 1002
0f2d19dd
JB
1003 SCM_ASRTGO (SCM_NIMP (v), badarg1);
1004 if (SCM_NIMP (args))
1005
1006 {
1007 ind = SCM_CAR (args);
1008 args = SCM_CDR (args);
1bbd0b84 1009 SCM_ASSERT (SCM_INUMP (ind), ind, SCM_ARG2, FUNC_NAME);
0f2d19dd
JB
1010 pos = SCM_INUM (ind);
1011 }
1012tail:
1013 switch SCM_TYP7
1014 (v)
1015 {
1016 default:
1bbd0b84
GB
1017 badarg1:SCM_WTA (1,v);
1018 wna: scm_wrong_num_args (scm_makfrom0str (FUNC_NAME));
0f2d19dd
JB
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++;
1bbd0b84 1043 SCM_ASSERT (SCM_INUMP (ind), ind, s_bad_ind, FUNC_NAME);
0f2d19dd
JB
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:
5c11cc9d 1057#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
1058 case scm_tc7_llvect:
1059#endif
1060 case scm_tc7_vector:
95f5b0f5 1061 case scm_tc7_wvect:
0f2d19dd 1062 SCM_ASRTGO (SCM_NULLP (args) && SCM_INUMP (ind), wna);
1bbd0b84 1063 return SCM_BOOL(pos >= 0 && pos < SCM_LENGTH (v));
0f2d19dd
JB
1064 }
1065}
1bbd0b84 1066#undef FUNC_NAME
0f2d19dd
JB
1067
1068
1bbd0b84 1069SCM_REGISTER_PROC(s_array_ref, "array-ref", 1, 0, 1, scm_uniform_vector_ref);
1cc91f1b 1070
1bbd0b84 1071
3b3b36dd 1072SCM_DEFINE (scm_uniform_vector_ref, "uniform-vector-ref", 2, 0, 0,
1bbd0b84 1073 (SCM v, SCM args),
b380b885 1074 "Returns the element at the @code{(index1, index2)} element in @var{array}.")
1bbd0b84 1075#define FUNC_NAME s_scm_uniform_vector_ref
0f2d19dd
JB
1076{
1077 long pos;
0f2d19dd 1078
35de7ebe 1079 if (SCM_IMP (v))
0f2d19dd
JB
1080 {
1081 SCM_ASRTGO (SCM_NULLP (args), badarg);
1082 return v;
1083 }
1084 else if (SCM_ARRAYP (v))
0f2d19dd 1085 {
1bbd0b84 1086 pos = scm_aind (v, args, FUNC_NAME);
0f2d19dd
JB
1087 v = SCM_ARRAY_V (v);
1088 }
1089 else
1090 {
1091 if (SCM_NIMP (args))
1092
1093 {
1bbd0b84 1094 SCM_ASSERT (SCM_CONSP (args) && SCM_INUMP (SCM_CAR (args)), args, SCM_ARG2, FUNC_NAME);
0f2d19dd
JB
1095 pos = SCM_INUM (SCM_CAR (args));
1096 SCM_ASRTGO (SCM_NULLP (SCM_CDR (args)), wna);
1097 }
1098 else
1099 {
3b3b36dd 1100 SCM_VALIDATE_INUM (2,args);
0f2d19dd
JB
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;
35de7ebe 1111 badarg:
1bbd0b84 1112 SCM_WTA (1,v);
35de7ebe 1113 abort ();
c209c88e
GB
1114
1115 outrng:
1116 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (pos));
1117 wna:
1118 scm_wrong_num_args (SCM_FUNC_NAME);
0f2d19dd
JB
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:
c209c88e 1134 if (SCM_BITVEC_REF (v, pos))
0f2d19dd
JB
1135 return SCM_BOOL_T;
1136 else
1137 return SCM_BOOL_F;
1138 case scm_tc7_string:
7866a09b 1139 return SCM_MAKE_CHAR (SCM_UCHARS (v)[pos]);
0f2d19dd
JB
1140 case scm_tc7_byvect:
1141 return SCM_MAKINUM (((char *)SCM_CHARS (v))[pos]);
0f2d19dd 1142 case scm_tc7_uvect:
fee7ef83 1143 return scm_ulong2num (((unsigned long *) SCM_VELTS (v))[pos]);
0f2d19dd 1144 case scm_tc7_ivect:
fee7ef83 1145 return scm_long2num(((signed long *) SCM_VELTS (v))[pos]);
0f2d19dd
JB
1146
1147 case scm_tc7_svect:
4260a7fc 1148 return SCM_MAKINUM (((short *) SCM_CELL_WORD_1 (v))[pos]);
5c11cc9d 1149#ifdef HAVE_LONG_LONGS
0f2d19dd 1150 case scm_tc7_llvect:
4260a7fc 1151 return scm_long_long2num (((long_long *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd
JB
1152#endif
1153
0f2d19dd 1154 case scm_tc7_fvect:
4260a7fc 1155 return scm_make_real (((float *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1156 case scm_tc7_dvect:
4260a7fc 1157 return scm_make_real (((double *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1158 case scm_tc7_cvect:
4260a7fc
DH
1159 return scm_make_complex (((double *) SCM_CELL_WORD_1 (v))[2 * pos],
1160 ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1]);
0f2d19dd 1161 case scm_tc7_vector:
95f5b0f5 1162 case scm_tc7_wvect:
0f2d19dd
JB
1163 return SCM_VELTS (v)[pos];
1164 }
1165}
1bbd0b84 1166#undef FUNC_NAME
0f2d19dd
JB
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.) */
1cc91f1b 1170
0f2d19dd 1171SCM
6e8d25a6 1172scm_cvref (SCM v, scm_sizet pos, SCM last)
0f2d19dd 1173{
5c11cc9d 1174 switch SCM_TYP7 (v)
0f2d19dd
JB
1175 {
1176 default:
1177 scm_wta (v, (char *) SCM_ARG1, "PROGRAMMING ERROR: scm_cvref");
1178 case scm_tc7_bvect:
c209c88e 1179 if (SCM_BITVEC_REF(v,pos))
0f2d19dd
JB
1180 return SCM_BOOL_T;
1181 else
1182 return SCM_BOOL_F;
1183 case scm_tc7_string:
7866a09b 1184 return SCM_MAKE_CHAR (SCM_UCHARS (v)[pos]);
0f2d19dd
JB
1185 case scm_tc7_byvect:
1186 return SCM_MAKINUM (((char *)SCM_CHARS (v))[pos]);
0f2d19dd 1187 case scm_tc7_uvect:
fee7ef83 1188 return scm_ulong2num(((unsigned long *) SCM_VELTS (v))[pos]);
0f2d19dd 1189 case scm_tc7_ivect:
fee7ef83 1190 return scm_long2num(((signed long *) SCM_VELTS (v))[pos]);
0f2d19dd 1191 case scm_tc7_svect:
4260a7fc 1192 return SCM_MAKINUM (((short *) SCM_CELL_WORD_1 (v))[pos]);
5c11cc9d 1193#ifdef HAVE_LONG_LONGS
0f2d19dd 1194 case scm_tc7_llvect:
4260a7fc 1195 return scm_long_long2num (((long_long *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1196#endif
0f2d19dd 1197 case scm_tc7_fvect:
fee7ef83 1198 if (SCM_NIMP (last) && !SCM_EQ_P (last, scm_flo0) && SCM_SLOPPY_REALP (last))
0f2d19dd 1199 {
4260a7fc 1200 SCM_REAL_VALUE (last) = ((float *) SCM_CELL_WORD_1 (v))[pos];
0f2d19dd
JB
1201 return last;
1202 }
4260a7fc 1203 return scm_make_real (((float *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1204 case scm_tc7_dvect:
fee7ef83 1205 if (SCM_NIMP (last) && !SCM_EQ_P (last, scm_flo0) && SCM_SLOPPY_REALP (last))
0f2d19dd 1206 {
4260a7fc 1207 SCM_REAL_VALUE (last) = ((double *) SCM_CELL_WORD_1 (v))[pos];
0f2d19dd
JB
1208 return last;
1209 }
4260a7fc 1210 return scm_make_real (((double *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1211 case scm_tc7_cvect:
bc86da5d 1212 if (SCM_NIMP (last) && SCM_SLOPPY_COMPLEXP (last))
0f2d19dd 1213 {
4260a7fc
DH
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];
0f2d19dd
JB
1216 return last;
1217 }
4260a7fc
DH
1218 return scm_make_complex (((double *) SCM_CELL_WORD_1 (v))[2 * pos],
1219 ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1]);
0f2d19dd 1220 case scm_tc7_vector:
95f5b0f5 1221 case scm_tc7_wvect:
0f2d19dd
JB
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
1bbd0b84
GB
1240SCM_REGISTER_PROC(s_uniform_array_set1_x, "uniform-array-set1!", 3, 0, 0, scm_array_set_x);
1241
1cc91f1b 1242
0aa0871f
GH
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). */
3b3b36dd 1245SCM_DEFINE (scm_array_set_x, "array-set!", 2, 0, 1,
1bbd0b84 1246 (SCM v, SCM obj, SCM args),
b380b885
MD
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.")
1bbd0b84 1249#define FUNC_NAME s_scm_array_set_x
0f2d19dd 1250{
f3667f52 1251 long pos = 0;
0f2d19dd
JB
1252 SCM_ASRTGO (SCM_NIMP (v), badarg1);
1253 if (SCM_ARRAYP (v))
0f2d19dd 1254 {
1bbd0b84 1255 pos = scm_aind (v, args, FUNC_NAME);
0f2d19dd
JB
1256 v = SCM_ARRAY_V (v);
1257 }
1258 else
1259 {
1260 if (SCM_NIMP (args))
0f2d19dd 1261 {
0aa0871f 1262 SCM_ASSERT (SCM_CONSP(args) && SCM_INUMP (SCM_CAR (args)), args,
1bbd0b84 1263 SCM_ARG3, FUNC_NAME);
0f2d19dd 1264 SCM_ASRTGO (SCM_NULLP (SCM_CDR (args)), wna);
0aa0871f 1265 pos = SCM_INUM (SCM_CAR (args));
0f2d19dd
JB
1266 }
1267 else
1268 {
3b3b36dd 1269 SCM_VALIDATE_INUM_COPY (3,args,pos);
0f2d19dd
JB
1270 }
1271 SCM_ASRTGO (pos >= 0 && pos < SCM_LENGTH (v), outrng);
1272 }
1273 switch (SCM_TYP7 (v))
1274 {
35de7ebe 1275 default: badarg1:
1bbd0b84 1276 SCM_WTA (1,v);
35de7ebe 1277 abort ();
c209c88e
GB
1278 outrng:
1279 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (pos));
1280 wna:
1281 scm_wrong_num_args (SCM_FUNC_NAME);
0f2d19dd
JB
1282 case scm_tc7_smob: /* enclosed */
1283 goto badarg1;
1284 case scm_tc7_bvect:
4260a7fc 1285 if (SCM_FALSEP (obj))
c209c88e 1286 SCM_BITVEC_CLR(v,pos);
9a09deb1 1287 else if (SCM_EQ_P (obj, SCM_BOOL_T))
c209c88e 1288 SCM_BITVEC_SET(v,pos);
0f2d19dd 1289 else
1bbd0b84 1290 badobj:SCM_WTA (2,obj);
0f2d19dd
JB
1291 break;
1292 case scm_tc7_string:
7866a09b
GB
1293 SCM_ASRTGO (SCM_CHARP (obj), badobj);
1294 SCM_UCHARS (v)[pos] = SCM_CHAR (obj);
0f2d19dd
JB
1295 break;
1296 case scm_tc7_byvect:
7866a09b
GB
1297 if (SCM_CHARP (obj))
1298 obj = SCM_MAKINUM ((char) SCM_CHAR (obj));
0aa0871f 1299 SCM_ASRTGO (SCM_INUMP (obj), badobj);
0f2d19dd
JB
1300 ((char *)SCM_CHARS (v))[pos] = SCM_INUM (obj);
1301 break;
1bbd0b84 1302 case scm_tc7_uvect:
f1267706 1303 SCM_VELTS(v)[pos] = SCM_PACK (scm_num2ulong(obj, (char *)SCM_ARG2, FUNC_NAME));
c209c88e 1304 break;
1bbd0b84 1305 case scm_tc7_ivect:
f1267706 1306 SCM_VELTS(v)[pos] = SCM_PACK (scm_num2long(obj, (char *)SCM_ARG2, FUNC_NAME));
c209c88e 1307 break;
0f2d19dd 1308 case scm_tc7_svect:
0aa0871f 1309 SCM_ASRTGO (SCM_INUMP (obj), badobj);
4260a7fc 1310 ((short *) SCM_CELL_WORD_1 (v))[pos] = SCM_INUM (obj);
0f2d19dd 1311 break;
5c11cc9d 1312#ifdef HAVE_LONG_LONGS
0f2d19dd 1313 case scm_tc7_llvect:
4260a7fc 1314 ((long_long *) SCM_CELL_WORD_1 (v))[pos] = scm_num2long_long (obj, (char *)SCM_ARG2, FUNC_NAME);
0f2d19dd
JB
1315 break;
1316#endif
1317
1318
0f2d19dd 1319 case scm_tc7_fvect:
4260a7fc 1320 ((float *) SCM_CELL_WORD_1 (v))[pos] = (float) scm_num2dbl (obj, FUNC_NAME);
0f2d19dd 1321 break;
0f2d19dd 1322 case scm_tc7_dvect:
4260a7fc 1323 ((double *) SCM_CELL_WORD_1 (v))[pos] = scm_num2dbl (obj, FUNC_NAME);
0f2d19dd
JB
1324 break;
1325 case scm_tc7_cvect:
eb42e2f0
DH
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 }
0f2d19dd 1334 break;
0f2d19dd 1335 case scm_tc7_vector:
95f5b0f5 1336 case scm_tc7_wvect:
0f2d19dd
JB
1337 SCM_VELTS (v)[pos] = obj;
1338 break;
1339 }
1340 return SCM_UNSPECIFIED;
1341}
1bbd0b84 1342#undef FUNC_NAME
0f2d19dd 1343
1d7bdb25
GH
1344/* attempts to unroll an array into a one-dimensional array.
1345 returns the unrolled array or #f if it can't be done. */
1bbd0b84 1346 /* if strict is not SCM_UNDEFINED, return #f if returned array
1d7bdb25 1347 wouldn't have contiguous elements. */
3b3b36dd 1348SCM_DEFINE (scm_array_contents, "array-contents", 1, 1, 0,
1bbd0b84 1349 (SCM ra, SCM strict),
b380b885
MD
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.")
1bbd0b84 1360#define FUNC_NAME s_scm_array_contents
0f2d19dd
JB
1361{
1362 SCM sra;
1363 if (SCM_IMP (ra))
f3667f52 1364 return SCM_BOOL_F;
5c11cc9d 1365 switch SCM_TYP7 (ra)
0f2d19dd
JB
1366 {
1367 default:
1368 return SCM_BOOL_F;
1369 case scm_tc7_vector:
95f5b0f5 1370 case scm_tc7_wvect:
0f2d19dd
JB
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:
5c11cc9d 1380#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
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 {
0f2d19dd
JB
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}
1bbd0b84 1415#undef FUNC_NAME
0f2d19dd 1416
1cc91f1b 1417
0f2d19dd 1418SCM
6e8d25a6 1419scm_ra2contig (SCM ra, int copy)
0f2d19dd
JB
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
3b3b36dd 1453SCM_DEFINE (scm_uniform_array_read_x, "uniform-array-read!", 1, 3, 0,
1bbd0b84 1454 (SCM ra, SCM port_or_fd, SCM start, SCM end),
b380b885
MD
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)}.")
1bbd0b84 1468#define FUNC_NAME s_scm_uniform_array_read_x
0f2d19dd 1469{
35de7ebe 1470 SCM cra = SCM_UNDEFINED, v = ra;
3d8d56df 1471 long sz, vlen, ans;
1146b6cd
GH
1472 long cstart = 0;
1473 long cend;
1474 long offset = 0;
35de7ebe 1475
0f2d19dd 1476 SCM_ASRTGO (SCM_NIMP (v), badarg1);
3d8d56df
GH
1477 if (SCM_UNBNDP (port_or_fd))
1478 port_or_fd = scm_cur_inp;
1479 else
1480 SCM_ASSERT (SCM_INUMP (port_or_fd)
0c95b57d 1481 || (SCM_OPINPORTP (port_or_fd)),
1bbd0b84 1482 port_or_fd, SCM_ARG2, FUNC_NAME);
3d8d56df 1483 vlen = SCM_LENGTH (v);
35de7ebe 1484
0f2d19dd 1485loop:
35de7ebe 1486 switch SCM_TYP7 (v)
0f2d19dd
JB
1487 {
1488 default:
5d2d2ffc 1489 badarg1:SCM_WTA (SCM_ARG1,v);
0f2d19dd
JB
1490 case scm_tc7_smob:
1491 SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
1492 cra = scm_ra2contig (ra, 0);
1146b6cd 1493 cstart += SCM_ARRAY_BASE (cra);
3d8d56df 1494 vlen = SCM_ARRAY_DIMS (cra)->inc *
0f2d19dd
JB
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:
3d8d56df 1503 vlen = (vlen + SCM_LONG_BIT - 1) / SCM_LONG_BIT;
1146b6cd 1504 cstart /= SCM_LONG_BIT;
0f2d19dd
JB
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;
5c11cc9d 1512#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
1513 case scm_tc7_llvect:
1514 sz = sizeof (long_long);
1515 break;
1516#endif
0f2d19dd
JB
1517 case scm_tc7_fvect:
1518 sz = sizeof (float);
1519 break;
0f2d19dd
JB
1520 case scm_tc7_dvect:
1521 sz = sizeof (double);
1522 break;
1523 case scm_tc7_cvect:
1524 sz = 2 * sizeof (double);
1525 break;
0f2d19dd 1526 }
3d8d56df 1527
1146b6cd
GH
1528 cend = vlen;
1529 if (!SCM_UNBNDP (start))
3d8d56df 1530 {
1146b6cd 1531 offset =
4638e087 1532 SCM_NUM2LONG (3, start);
35de7ebe 1533
1146b6cd 1534 if (offset < 0 || offset >= cend)
1bbd0b84 1535 scm_out_of_range (FUNC_NAME, start);
1146b6cd
GH
1536
1537 if (!SCM_UNBNDP (end))
1538 {
1539 long tend =
4638e087 1540 SCM_NUM2LONG (4, end);
3d8d56df 1541
1146b6cd 1542 if (tend <= offset || tend > cend)
1bbd0b84 1543 scm_out_of_range (FUNC_NAME, end);
1146b6cd
GH
1544 cend = tend;
1545 }
0f2d19dd 1546 }
35de7ebe 1547
3d8d56df
GH
1548 if (SCM_NIMP (port_or_fd))
1549 {
6c951427
GH
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)
affc96b5 1555 scm_flush (port_or_fd);
6c951427
GH
1556
1557 ans = cend - offset;
1558 while (remaining > 0)
3d8d56df 1559 {
6c951427
GH
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 {
affc96b5 1572 if (scm_fill_input (port_or_fd) == EOF)
6c951427
GH
1573 {
1574 if (remaining % sz != 0)
1575 {
5d2d2ffc 1576 SCM_MISC_ERROR ("unexpected EOF", SCM_EOL);
6c951427
GH
1577 }
1578 ans -= remaining / sz;
1579 break;
1580 }
6c951427 1581 }
3d8d56df 1582 }
6c951427
GH
1583
1584 if (pt->rw_random)
1585 pt->rw_active = SCM_PORT_READ;
3d8d56df
GH
1586 }
1587 else /* file descriptor. */
1588 {
1589 SCM_SYSCALL (ans = read (SCM_INUM (port_or_fd),
1146b6cd
GH
1590 SCM_CHARS (v) + (cstart + offset) * sz,
1591 (scm_sizet) (sz * (cend - offset))));
3d8d56df 1592 if (ans == -1)
1bbd0b84 1593 SCM_SYSERROR;
3d8d56df 1594 }
0f2d19dd
JB
1595 if (SCM_TYP7 (v) == scm_tc7_bvect)
1596 ans *= SCM_LONG_BIT;
35de7ebe 1597
fee7ef83 1598 if (!SCM_EQ_P (v, ra) && !SCM_EQ_P (cra, ra))
0f2d19dd 1599 scm_array_copy_x (cra, ra);
35de7ebe 1600
0f2d19dd
JB
1601 return SCM_MAKINUM (ans);
1602}
1bbd0b84 1603#undef FUNC_NAME
0f2d19dd 1604
3b3b36dd 1605SCM_DEFINE (scm_uniform_array_write, "uniform-array-write", 1, 3, 0,
1bbd0b84 1606 (SCM v, SCM port_or_fd, SCM start, SCM end),
b380b885
MD
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)}.")
1bbd0b84 1617#define FUNC_NAME s_scm_uniform_array_write
0f2d19dd 1618{
3d8d56df 1619 long sz, vlen, ans;
1146b6cd
GH
1620 long offset = 0;
1621 long cstart = 0;
1622 long cend;
3d8d56df 1623
78446828
MV
1624 port_or_fd = SCM_COERCE_OUTPORT (port_or_fd);
1625
0f2d19dd 1626 SCM_ASRTGO (SCM_NIMP (v), badarg1);
3d8d56df
GH
1627 if (SCM_UNBNDP (port_or_fd))
1628 port_or_fd = scm_cur_outp;
1629 else
1630 SCM_ASSERT (SCM_INUMP (port_or_fd)
0c95b57d 1631 || (SCM_OPOUTPORTP (port_or_fd)),
1bbd0b84 1632 port_or_fd, SCM_ARG2, FUNC_NAME);
3d8d56df
GH
1633 vlen = SCM_LENGTH (v);
1634
0f2d19dd 1635loop:
3d8d56df 1636 switch SCM_TYP7 (v)
0f2d19dd
JB
1637 {
1638 default:
4638e087 1639 badarg1:SCM_WTA (1, v);
0f2d19dd
JB
1640 case scm_tc7_smob:
1641 SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
1642 v = scm_ra2contig (v, 1);
1146b6cd 1643 cstart = SCM_ARRAY_BASE (v);
3d8d56df
GH
1644 vlen = SCM_ARRAY_DIMS (v)->inc
1645 * (SCM_ARRAY_DIMS (v)->ubnd - SCM_ARRAY_DIMS (v)->lbnd + 1);
0f2d19dd
JB
1646 v = SCM_ARRAY_V (v);
1647 goto loop;
0f2d19dd 1648 case scm_tc7_string:
3d8d56df 1649 case scm_tc7_byvect:
0f2d19dd
JB
1650 sz = sizeof (char);
1651 break;
1652 case scm_tc7_bvect:
3d8d56df 1653 vlen = (vlen + SCM_LONG_BIT - 1) / SCM_LONG_BIT;
1146b6cd 1654 cstart /= SCM_LONG_BIT;
0f2d19dd
JB
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;
5c11cc9d 1662#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
1663 case scm_tc7_llvect:
1664 sz = sizeof (long_long);
1665 break;
1666#endif
0f2d19dd
JB
1667 case scm_tc7_fvect:
1668 sz = sizeof (float);
1669 break;
0f2d19dd
JB
1670 case scm_tc7_dvect:
1671 sz = sizeof (double);
1672 break;
1673 case scm_tc7_cvect:
1674 sz = 2 * sizeof (double);
1675 break;
0f2d19dd 1676 }
3d8d56df 1677
1146b6cd
GH
1678 cend = vlen;
1679 if (!SCM_UNBNDP (start))
3d8d56df 1680 {
1146b6cd 1681 offset =
4638e087 1682 SCM_NUM2LONG (3, start);
3d8d56df 1683
1146b6cd 1684 if (offset < 0 || offset >= cend)
1bbd0b84 1685 scm_out_of_range (FUNC_NAME, start);
1146b6cd
GH
1686
1687 if (!SCM_UNBNDP (end))
1688 {
1689 long tend =
4638e087 1690 SCM_NUM2LONG (4, end);
3d8d56df 1691
1146b6cd 1692 if (tend <= offset || tend > cend)
1bbd0b84 1693 scm_out_of_range (FUNC_NAME, end);
1146b6cd
GH
1694 cend = tend;
1695 }
3d8d56df
GH
1696 }
1697
1698 if (SCM_NIMP (port_or_fd))
1699 {
6c951427 1700 char *source = SCM_CHARS (v) + (cstart + offset) * sz;
6c951427
GH
1701
1702 ans = cend - offset;
265e6a4d 1703 scm_lfwrite (source, ans * sz, port_or_fd);
3d8d56df
GH
1704 }
1705 else /* file descriptor. */
1706 {
1707 SCM_SYSCALL (ans = write (SCM_INUM (port_or_fd),
1146b6cd
GH
1708 SCM_CHARS (v) + (cstart + offset) * sz,
1709 (scm_sizet) (sz * (cend - offset))));
3d8d56df 1710 if (ans == -1)
1bbd0b84 1711 SCM_SYSERROR;
3d8d56df 1712 }
0f2d19dd
JB
1713 if (SCM_TYP7 (v) == scm_tc7_bvect)
1714 ans *= SCM_LONG_BIT;
3d8d56df 1715
0f2d19dd
JB
1716 return SCM_MAKINUM (ans);
1717}
1bbd0b84 1718#undef FUNC_NAME
0f2d19dd
JB
1719
1720
1721static char cnt_tab[16] =
1722{0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
1723
3b3b36dd 1724SCM_DEFINE (scm_bit_count, "bit-count", 2, 0, 0,
44e47754
DH
1725 (SCM b, SCM bitvector),
1726 "Returns the number of occurrences of the boolean B in BITVECTOR.")
1bbd0b84 1727#define FUNC_NAME s_scm_bit_count
0f2d19dd 1728{
44e47754
DH
1729 SCM_VALIDATE_BOOL (1, b);
1730 SCM_ASSERT (!SCM_IMP (bitvector) && SCM_TYP7 (bitvector) == scm_tc7_bvect,
1731 bitvector, 2, FUNC_NAME);
1732 if (SCM_LENGTH (bitvector) == 0) {
1733 return SCM_INUM0;
1734 } else {
1735 unsigned long int count = 0;
1736 unsigned long int i = (SCM_LENGTH (bitvector) - 1) / SCM_LONG_BIT;
1737 unsigned long int w = SCM_UNPACK (SCM_VELTS (bitvector)[i]);
1738 if (SCM_FALSEP (b)) {
1739 w = ~w;
1740 };
1741 w <<= SCM_LONG_BIT - 1 - ((SCM_LENGTH (bitvector) - 1) % SCM_LONG_BIT);
1742 while (1) {
1743 while (w) {
1744 count += cnt_tab[w & 0x0f];
1745 w >>= 4;
1746 }
1747 if (i == 0) {
1748 return SCM_MAKINUM (count);
1749 } else {
1750 --i;
1751 w = SCM_UNPACK (SCM_VELTS (bitvector)[i]);
1752 if (SCM_FALSEP (b)) {
1753 w = ~w;
0f2d19dd 1754 }
44e47754 1755 }
0f2d19dd 1756 }
44e47754 1757 }
0f2d19dd 1758}
1bbd0b84 1759#undef FUNC_NAME
0f2d19dd
JB
1760
1761
3b3b36dd 1762SCM_DEFINE (scm_bit_position, "bit-position", 3, 0, 0,
1bbd0b84 1763 (SCM item, SCM v, SCM k),
b380b885
MD
1764 "Returns the minimum index of an occurrence of @var{bool} in @var{bv}\n"
1765 "which is at least @var{k}. If no @var{bool} occurs within the specified\n"
1766 "range @code{#f} is returned.")
1bbd0b84 1767#define FUNC_NAME s_scm_bit_position
0f2d19dd 1768{
1bbd0b84 1769 long i, lenw, xbits, pos;
0f2d19dd 1770 register unsigned long w;
6b5a304f 1771 SCM_VALIDATE_NIM (2,v);
3b3b36dd 1772 SCM_VALIDATE_INUM_COPY (3,k,pos);
0f2d19dd 1773 SCM_ASSERT ((pos <= SCM_LENGTH (v)) && (pos >= 0),
1bbd0b84 1774 k, SCM_OUTOFRANGE, FUNC_NAME);
0f2d19dd
JB
1775 if (pos == SCM_LENGTH (v))
1776 return SCM_BOOL_F;
5c11cc9d 1777 switch SCM_TYP7 (v)
0f2d19dd
JB
1778 {
1779 default:
1bbd0b84 1780 SCM_WTA (2,v);
0f2d19dd
JB
1781 case scm_tc7_bvect:
1782 if (0 == SCM_LENGTH (v))
1783 return SCM_MAKINUM (-1L);
1784 lenw = (SCM_LENGTH (v) - 1) / SCM_LONG_BIT; /* watch for part words */
1785 i = pos / SCM_LONG_BIT;
f1267706 1786 w = SCM_UNPACK (SCM_VELTS (v)[i]);
0f2d19dd
JB
1787 if (SCM_FALSEP (item))
1788 w = ~w;
1789 xbits = (pos % SCM_LONG_BIT);
1790 pos -= xbits;
1791 w = ((w >> xbits) << xbits);
1792 xbits = SCM_LONG_BIT - 1 - (SCM_LENGTH (v) - 1) % SCM_LONG_BIT;
1793 while (!0)
1794 {
1795 if (w && (i == lenw))
1796 w = ((w << xbits) >> xbits);
1797 if (w)
1798 while (w)
1799 switch (w & 0x0f)
1800 {
1801 default:
1802 return SCM_MAKINUM (pos);
1803 case 2:
1804 case 6:
1805 case 10:
1806 case 14:
1807 return SCM_MAKINUM (pos + 1);
1808 case 4:
1809 case 12:
1810 return SCM_MAKINUM (pos + 2);
1811 case 8:
1812 return SCM_MAKINUM (pos + 3);
1813 case 0:
1814 pos += 4;
1815 w >>= 4;
1816 }
1817 if (++i > lenw)
1818 break;
1819 pos += SCM_LONG_BIT;
f1267706 1820 w = SCM_UNPACK (SCM_VELTS (v)[i]);
0f2d19dd
JB
1821 if (SCM_FALSEP (item))
1822 w = ~w;
1823 }
1824 return SCM_BOOL_F;
1825 }
1826}
1bbd0b84 1827#undef FUNC_NAME
0f2d19dd
JB
1828
1829
3b3b36dd 1830SCM_DEFINE (scm_bit_set_star_x, "bit-set*!", 3, 0, 0,
1bbd0b84 1831 (SCM v, SCM kv, SCM obj),
b380b885
MD
1832 "If uve is a bit-vector @var{bv} and uve must be of the same length. If\n"
1833 "@var{bool} is @code{#t}, uve is OR'ed into @var{bv}; If @var{bool} is @code{#f}, the\n"
1834 "inversion of uve is AND'ed into @var{bv}.\n\n"
1835 "If uve is a unsigned integer vector all the elements of uve must be\n"
1836 "between 0 and the @code{LENGTH} of @var{bv}. The bits of @var{bv}\n"
1837 "corresponding to the indexes in uve are set to @var{bool}.\n\n"
1838 "The return value is unspecified.")
1bbd0b84 1839#define FUNC_NAME s_scm_bit_set_star_x
0f2d19dd
JB
1840{
1841 register long i, k, vlen;
1842 SCM_ASRTGO (SCM_NIMP (v), badarg1);
1843 SCM_ASRTGO (SCM_NIMP (kv), badarg2);
5c11cc9d 1844 switch SCM_TYP7 (kv)
0f2d19dd
JB
1845 {
1846 default:
1bbd0b84 1847 badarg2:SCM_WTA (2,kv);
0f2d19dd 1848 case scm_tc7_uvect:
5c11cc9d 1849 switch SCM_TYP7 (v)
0f2d19dd
JB
1850 {
1851 default:
c209c88e 1852 badarg1: SCM_WTA (1,v);
0f2d19dd
JB
1853 case scm_tc7_bvect:
1854 vlen = SCM_LENGTH (v);
4260a7fc 1855 if (SCM_FALSEP (obj))
0f2d19dd
JB
1856 for (i = SCM_LENGTH (kv); i;)
1857 {
f1267706 1858 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
1bbd0b84 1859 SCM_ASSERT ((k < vlen), SCM_MAKINUM (k), SCM_OUTOFRANGE, FUNC_NAME);
c209c88e 1860 SCM_BITVEC_CLR(v,k);
0f2d19dd 1861 }
9a09deb1 1862 else if (SCM_EQ_P (obj, SCM_BOOL_T))
0f2d19dd
JB
1863 for (i = SCM_LENGTH (kv); i;)
1864 {
f1267706 1865 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
1bbd0b84 1866 SCM_ASSERT ((k < vlen), SCM_MAKINUM (k), SCM_OUTOFRANGE, FUNC_NAME);
c209c88e 1867 SCM_BITVEC_SET(v,k);
0f2d19dd
JB
1868 }
1869 else
1bbd0b84 1870 badarg3:SCM_WTA (3,obj);
0f2d19dd
JB
1871 }
1872 break;
1873 case scm_tc7_bvect:
1874 SCM_ASRTGO (SCM_TYP7 (v) == scm_tc7_bvect && SCM_LENGTH (v) == SCM_LENGTH (kv), badarg1);
4260a7fc 1875 if (SCM_FALSEP (obj))
0f2d19dd 1876 for (k = (SCM_LENGTH (v) + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
f1267706 1877 SCM_UNPACK (SCM_VELTS (v)[k]) &= ~ SCM_UNPACK(SCM_VELTS (kv)[k]);
9a09deb1 1878 else if (SCM_EQ_P (obj, SCM_BOOL_T))
0f2d19dd 1879 for (k = (SCM_LENGTH (v) + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
f1267706 1880 SCM_UNPACK (SCM_VELTS (v)[k]) |= SCM_UNPACK (SCM_VELTS (kv)[k]);
0f2d19dd
JB
1881 else
1882 goto badarg3;
1883 break;
1884 }
1885 return SCM_UNSPECIFIED;
1886}
1bbd0b84 1887#undef FUNC_NAME
0f2d19dd
JB
1888
1889
3b3b36dd 1890SCM_DEFINE (scm_bit_count_star, "bit-count*", 3, 0, 0,
1bbd0b84 1891 (SCM v, SCM kv, SCM obj),
b380b885
MD
1892 "Returns\n"
1893 "@example\n"
1894 "(bit-count (bit-set*! (if bool bv (bit-invert! bv)) uve #t) #t).\n"
1895 "@end example\n"
1896 "@var{bv} is not modified.")
1bbd0b84 1897#define FUNC_NAME s_scm_bit_count_star
0f2d19dd
JB
1898{
1899 register long i, vlen, count = 0;
1900 register unsigned long k;
41b0806d 1901 int fObj = 0;
c209c88e 1902
0f2d19dd
JB
1903 SCM_ASRTGO (SCM_NIMP (v), badarg1);
1904 SCM_ASRTGO (SCM_NIMP (kv), badarg2);
5c11cc9d 1905 switch SCM_TYP7 (kv)
0f2d19dd
JB
1906 {
1907 default:
c209c88e
GB
1908 badarg2:
1909 SCM_WTA (2,kv);
0f2d19dd
JB
1910 case scm_tc7_uvect:
1911 switch SCM_TYP7
1912 (v)
1913 {
1914 default:
c209c88e
GB
1915 badarg1:
1916 SCM_WTA (1,v);
0f2d19dd
JB
1917 case scm_tc7_bvect:
1918 vlen = SCM_LENGTH (v);
4260a7fc 1919 if (SCM_FALSEP (obj))
0f2d19dd
JB
1920 for (i = SCM_LENGTH (kv); i;)
1921 {
f1267706 1922 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
1bbd0b84 1923 SCM_ASSERT ((k < vlen), SCM_MAKINUM (k), SCM_OUTOFRANGE, FUNC_NAME);
c209c88e 1924 if (!SCM_BITVEC_REF(v,k))
0f2d19dd
JB
1925 count++;
1926 }
9a09deb1 1927 else if (SCM_EQ_P (obj, SCM_BOOL_T))
0f2d19dd
JB
1928 for (i = SCM_LENGTH (kv); i;)
1929 {
f1267706 1930 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
1bbd0b84 1931 SCM_ASSERT ((k < vlen), SCM_MAKINUM (k), SCM_OUTOFRANGE, FUNC_NAME);
c209c88e 1932 if (SCM_BITVEC_REF (v,k))
0f2d19dd
JB
1933 count++;
1934 }
1935 else
1bbd0b84 1936 badarg3:SCM_WTA (3,obj);
0f2d19dd
JB
1937 }
1938 break;
1939 case scm_tc7_bvect:
1940 SCM_ASRTGO (SCM_TYP7 (v) == scm_tc7_bvect && SCM_LENGTH (v) == SCM_LENGTH (kv), badarg1);
1941 if (0 == SCM_LENGTH (v))
1942 return SCM_INUM0;
4260a7fc 1943 SCM_ASRTGO (SCM_BOOLP (obj), badarg3);
9a09deb1 1944 fObj = SCM_EQ_P (obj, SCM_BOOL_T);
0f2d19dd 1945 i = (SCM_LENGTH (v) - 1) / SCM_LONG_BIT;
f1267706 1946 k = SCM_UNPACK (SCM_VELTS (kv)[i]) & (fObj ? SCM_UNPACK (SCM_VELTS (v)[i]) : ~ SCM_UNPACK (SCM_VELTS (v)[i]));
0f2d19dd 1947 k <<= SCM_LONG_BIT - 1 - ((SCM_LENGTH (v) - 1) % SCM_LONG_BIT);
c209c88e 1948 while (1)
0f2d19dd
JB
1949 {
1950 for (; k; k >>= 4)
1951 count += cnt_tab[k & 0x0f];
1952 if (0 == i--)
1953 return SCM_MAKINUM (count);
c209c88e
GB
1954
1955 /* urg. repetitive (see above.) */
f1267706 1956 k = SCM_UNPACK (SCM_VELTS (kv)[i]) & (fObj ? SCM_UNPACK(SCM_VELTS (v)[i]) : ~SCM_UNPACK (SCM_VELTS (v)[i]));
0f2d19dd
JB
1957 }
1958 }
1959 return SCM_MAKINUM (count);
1960}
1bbd0b84 1961#undef FUNC_NAME
0f2d19dd
JB
1962
1963
3b3b36dd 1964SCM_DEFINE (scm_bit_invert_x, "bit-invert!", 1, 0, 0,
1bbd0b84 1965 (SCM v),
b380b885 1966 "Modifies @var{bv} by replacing each element with its negation.")
1bbd0b84 1967#define FUNC_NAME s_scm_bit_invert_x
0f2d19dd
JB
1968{
1969 register long k;
1970 SCM_ASRTGO (SCM_NIMP (v), badarg1);
1971 k = SCM_LENGTH (v);
1972 switch SCM_TYP7
1973 (v)
1974 {
1975 case scm_tc7_bvect:
1976 for (k = (k + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
f1267706 1977 SCM_UNPACK (SCM_VELTS (v)[k]) = ~SCM_UNPACK(SCM_VELTS (v)[k]);
0f2d19dd
JB
1978 break;
1979 default:
1bbd0b84 1980 badarg1:SCM_WTA (1,v);
0f2d19dd
JB
1981 }
1982 return SCM_UNSPECIFIED;
1983}
1bbd0b84 1984#undef FUNC_NAME
0f2d19dd
JB
1985
1986
0f2d19dd 1987SCM
1bbd0b84 1988scm_istr2bve (char *str, long len)
0f2d19dd
JB
1989{
1990 SCM v = scm_make_uve (len, SCM_BOOL_T);
1991 long *data = (long *) SCM_VELTS (v);
1992 register unsigned long mask;
1993 register long k;
1994 register long j;
1995 for (k = 0; k < (len + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k++)
1996 {
1997 data[k] = 0L;
1998 j = len - k * SCM_LONG_BIT;
1999 if (j > SCM_LONG_BIT)
2000 j = SCM_LONG_BIT;
2001 for (mask = 1L; j--; mask <<= 1)
2002 switch (*str++)
2003 {
2004 case '0':
2005 break;
2006 case '1':
2007 data[k] |= mask;
2008 break;
2009 default:
2010 return SCM_BOOL_F;
2011 }
2012 }
2013 return v;
2014}
2015
2016
1cc91f1b 2017
0f2d19dd 2018static SCM
1bbd0b84 2019ra2l (SCM ra,scm_sizet base,scm_sizet k)
0f2d19dd
JB
2020{
2021 register SCM res = SCM_EOL;
2022 register long inc = SCM_ARRAY_DIMS (ra)[k].inc;
2023 register scm_sizet i;
2024 if (SCM_ARRAY_DIMS (ra)[k].ubnd < SCM_ARRAY_DIMS (ra)[k].lbnd)
2025 return SCM_EOL;
2026 i = base + (1 + SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd) * inc;
2027 if (k < SCM_ARRAY_NDIM (ra) - 1)
2028 {
2029 do
2030 {
2031 i -= inc;
2032 res = scm_cons (ra2l (ra, i, k + 1), res);
2033 }
2034 while (i != base);
2035 }
2036 else
2037 do
2038 {
2039 i -= inc;
2040 res = scm_cons (scm_uniform_vector_ref (SCM_ARRAY_V (ra), SCM_MAKINUM (i)), res);
2041 }
2042 while (i != base);
2043 return res;
2044}
2045
2046
3b3b36dd 2047SCM_DEFINE (scm_array_to_list, "array->list", 1, 0, 0,
1bbd0b84 2048 (SCM v),
b380b885 2049 "Returns a list consisting of all the elements, in order, of @var{array}.")
1bbd0b84 2050#define FUNC_NAME s_scm_array_to_list
0f2d19dd
JB
2051{
2052 SCM res = SCM_EOL;
2053 register long k;
2054 SCM_ASRTGO (SCM_NIMP (v), badarg1);
2055 switch SCM_TYP7
2056 (v)
2057 {
2058 default:
1bbd0b84 2059 badarg1:SCM_WTA (1,v);
0f2d19dd
JB
2060 case scm_tc7_smob:
2061 SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
2062 return ra2l (v, SCM_ARRAY_BASE (v), 0);
2063 case scm_tc7_vector:
95f5b0f5 2064 case scm_tc7_wvect:
0f2d19dd
JB
2065 return scm_vector_to_list (v);
2066 case scm_tc7_string:
2067 return scm_string_to_list (v);
2068 case scm_tc7_bvect:
2069 {
2070 long *data = (long *) SCM_VELTS (v);
2071 register unsigned long mask;
2072 for (k = (SCM_LENGTH (v) - 1) / SCM_LONG_BIT; k > 0; k--)
cdbadcac 2073 for (mask = 1UL << (SCM_LONG_BIT - 1); mask; mask >>= 1)
156dcb09 2074 res = scm_cons (SCM_BOOL(((long *) data)[k] & mask), res);
0f2d19dd 2075 for (mask = 1L << ((SCM_LENGTH (v) % SCM_LONG_BIT) - 1); mask; mask >>= 1)
156dcb09 2076 res = scm_cons (SCM_BOOL(((long *) data)[k] & mask), res);
0f2d19dd
JB
2077 return res;
2078 }
0f2d19dd
JB
2079 case scm_tc7_uvect: {
2080 long *data = (long *)SCM_VELTS(v);
2081 for (k = SCM_LENGTH(v) - 1; k >= 0; k--)
2082 res = scm_cons(scm_ulong2num(data[k]), res);
2083 return res;
2084 }
2085 case scm_tc7_ivect: {
2086 long *data = (long *)SCM_VELTS(v);
2087 for (k = SCM_LENGTH(v) - 1; k >= 0; k--)
2088 res = scm_cons(scm_long2num(data[k]), res);
2089 return res;
2090 }
0f2d19dd
JB
2091 case scm_tc7_svect: {
2092 short *data;
2093 data = (short *)SCM_VELTS(v);
2094 for (k = SCM_LENGTH(v) - 1; k >= 0; k--)
2095 res = scm_cons(SCM_MAKINUM (data[k]), res);
2096 return res;
2097 }
5c11cc9d 2098#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
2099 case scm_tc7_llvect: {
2100 long_long *data;
2101 data = (long_long *)SCM_VELTS(v);
2102 for (k = SCM_LENGTH(v) - 1; k >= 0; k--)
2103 res = scm_cons(scm_long_long2num(data[k]), res);
2104 return res;
2105 }
2106#endif
2107
2108
0f2d19dd
JB
2109 case scm_tc7_fvect:
2110 {
2111 float *data = (float *) SCM_VELTS (v);
2112 for (k = SCM_LENGTH (v) - 1; k >= 0; k--)
bc86da5d 2113 res = scm_cons (scm_make_real (data[k]), res);
0f2d19dd
JB
2114 return res;
2115 }
0f2d19dd
JB
2116 case scm_tc7_dvect:
2117 {
2118 double *data = (double *) SCM_VELTS (v);
2119 for (k = SCM_LENGTH (v) - 1; k >= 0; k--)
f8de44c1 2120 res = scm_cons (scm_make_real (data[k]), res);
0f2d19dd
JB
2121 return res;
2122 }
2123 case scm_tc7_cvect:
2124 {
2125 double (*data)[2] = (double (*)[2]) SCM_VELTS (v);
2126 for (k = SCM_LENGTH (v) - 1; k >= 0; k--)
f8de44c1 2127 res = scm_cons (scm_make_complex (data[k][0], data[k][1]), res);
0f2d19dd
JB
2128 return res;
2129 }
0f2d19dd
JB
2130 }
2131}
1bbd0b84 2132#undef FUNC_NAME
0f2d19dd
JB
2133
2134
20a54673 2135static char s_bad_ralst[] = "Bad scm_array contents list";
1cc91f1b 2136
1bbd0b84 2137static int l2ra(SCM lst, SCM ra, scm_sizet base, scm_sizet k);
1cc91f1b 2138
3b3b36dd 2139SCM_DEFINE (scm_list_to_uniform_array, "list->uniform-array", 3, 0, 0,
1bbd0b84 2140 (SCM ndim, SCM prot, SCM lst),
b380b885
MD
2141 "@deffnx procedure list->uniform-vector prot lst\n"
2142 "Returns a uniform array of the type indicated by prototype @var{prot}\n"
2143 "with elements the same as those of @var{lst}. Elements must be of the\n"
2144 "appropriate type, no coercions are done.")
1bbd0b84 2145#define FUNC_NAME s_scm_list_to_uniform_array
0f2d19dd
JB
2146{
2147 SCM shp = SCM_EOL;
2148 SCM row = lst;
2149 SCM ra;
2150 scm_sizet k;
2151 long n;
3b3b36dd 2152 SCM_VALIDATE_INUM_COPY (1,ndim,k);
0f2d19dd
JB
2153 while (k--)
2154 {
2155 n = scm_ilength (row);
1bbd0b84 2156 SCM_ASSERT (n >= 0, lst, SCM_ARG3, FUNC_NAME);
0f2d19dd
JB
2157 shp = scm_cons (SCM_MAKINUM (n), shp);
2158 if (SCM_NIMP (row))
2159 row = SCM_CAR (row);
2160 }
d12feca3
GH
2161 ra = scm_dimensions_to_uniform_array (scm_reverse (shp), prot,
2162 SCM_UNDEFINED);
0f2d19dd
JB
2163 if (SCM_NULLP (shp))
2164
2165 {
2166 SCM_ASRTGO (1 == scm_ilength (lst), badlst);
2167 scm_array_set_x (ra, SCM_CAR (lst), SCM_EOL);
2168 return ra;
2169 }
2170 if (!SCM_ARRAYP (ra))
2171 {
2172 for (k = 0; k < SCM_LENGTH (ra); k++, lst = SCM_CDR (lst))
2173 scm_array_set_x (ra, SCM_CAR (lst), SCM_MAKINUM (k));
2174 return ra;
2175 }
2176 if (l2ra (lst, ra, SCM_ARRAY_BASE (ra), 0))
2177 return ra;
2178 else
1bbd0b84 2179 badlst:scm_wta (lst, s_bad_ralst, FUNC_NAME);
0f2d19dd
JB
2180 return SCM_BOOL_F;
2181}
1bbd0b84 2182#undef FUNC_NAME
0f2d19dd 2183
0f2d19dd 2184static int
1bbd0b84 2185l2ra (SCM lst, SCM ra, scm_sizet base, scm_sizet k)
0f2d19dd
JB
2186{
2187 register long inc = SCM_ARRAY_DIMS (ra)[k].inc;
2188 register long n = (1 + SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd);
2189 int ok = 1;
2190 if (n <= 0)
4260a7fc 2191 return (SCM_NULLP (lst));
0f2d19dd
JB
2192 if (k < SCM_ARRAY_NDIM (ra) - 1)
2193 {
2194 while (n--)
2195 {
2196 if (SCM_IMP (lst) || SCM_NCONSP (lst))
2197 return 0;
2198 ok = ok && l2ra (SCM_CAR (lst), ra, base, k + 1);
2199 base += inc;
2200 lst = SCM_CDR (lst);
2201 }
2202 if (SCM_NNULLP (lst))
2203 return 0;
2204 }
2205 else
2206 {
2207 while (n--)
2208 {
2209 if (SCM_IMP (lst) || SCM_NCONSP (lst))
2210 return 0;
baa702c8 2211 scm_array_set_x (SCM_ARRAY_V (ra), SCM_CAR (lst), SCM_MAKINUM (base));
0f2d19dd
JB
2212 base += inc;
2213 lst = SCM_CDR (lst);
2214 }
2215 if (SCM_NNULLP (lst))
fee7ef83 2216 return 0;
0f2d19dd
JB
2217 }
2218 return ok;
2219}
2220
1cc91f1b 2221
0f2d19dd 2222static void
1bbd0b84 2223rapr1 (SCM ra,scm_sizet j,scm_sizet k,SCM port,scm_print_state *pstate)
0f2d19dd
JB
2224{
2225 long inc = 1;
2226 long n = SCM_LENGTH (ra);
2227 int enclosed = 0;
2228tail:
5c11cc9d 2229 switch SCM_TYP7 (ra)
0f2d19dd
JB
2230 {
2231 case scm_tc7_smob:
2232 if (enclosed++)
2233 {
2234 SCM_ARRAY_BASE (ra) = j;
2235 if (n-- > 0)
9882ea19 2236 scm_iprin1 (ra, port, pstate);
0f2d19dd
JB
2237 for (j += inc; n-- > 0; j += inc)
2238 {
b7f3516f 2239 scm_putc (' ', port);
0f2d19dd 2240 SCM_ARRAY_BASE (ra) = j;
9882ea19 2241 scm_iprin1 (ra, port, pstate);
0f2d19dd
JB
2242 }
2243 break;
2244 }
2245 if (k + 1 < SCM_ARRAY_NDIM (ra))
2246 {
2247 long i;
2248 inc = SCM_ARRAY_DIMS (ra)[k].inc;
2249 for (i = SCM_ARRAY_DIMS (ra)[k].lbnd; i < SCM_ARRAY_DIMS (ra)[k].ubnd; i++)
2250 {
b7f3516f 2251 scm_putc ('(', port);
9882ea19 2252 rapr1 (ra, j, k + 1, port, pstate);
b7f3516f 2253 scm_puts (") ", port);
0f2d19dd
JB
2254 j += inc;
2255 }
2256 if (i == SCM_ARRAY_DIMS (ra)[k].ubnd)
2257 { /* could be zero size. */
b7f3516f 2258 scm_putc ('(', port);
9882ea19 2259 rapr1 (ra, j, k + 1, port, pstate);
b7f3516f 2260 scm_putc (')', port);
0f2d19dd
JB
2261 }
2262 break;
2263 }
2264 if SCM_ARRAY_NDIM
2265 (ra)
2266 { /* Could be zero-dimensional */
2267 inc = SCM_ARRAY_DIMS (ra)[k].inc;
2268 n = (SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1);
2269 }
2270 else
2271 n = 1;
2272 ra = SCM_ARRAY_V (ra);
2273 goto tail;
2274 default:
5c11cc9d 2275 /* scm_tc7_bvect and scm_tc7_llvect only? */
0f2d19dd 2276 if (n-- > 0)
9882ea19 2277 scm_iprin1 (scm_uniform_vector_ref (ra, SCM_MAKINUM (j)), port, pstate);
0f2d19dd
JB
2278 for (j += inc; n-- > 0; j += inc)
2279 {
b7f3516f 2280 scm_putc (' ', port);
9882ea19 2281 scm_iprin1 (scm_cvref (ra, j, SCM_UNDEFINED), port, pstate);
0f2d19dd
JB
2282 }
2283 break;
2284 case scm_tc7_string:
2285 if (n-- > 0)
7866a09b 2286 scm_iprin1 (SCM_MAKE_CHAR (SCM_UCHARS (ra)[j]), port, pstate);
9882ea19 2287 if (SCM_WRITINGP (pstate))
0f2d19dd
JB
2288 for (j += inc; n-- > 0; j += inc)
2289 {
b7f3516f 2290 scm_putc (' ', port);
7866a09b 2291 scm_iprin1 (SCM_MAKE_CHAR (SCM_UCHARS (ra)[j]), port, pstate);
0f2d19dd
JB
2292 }
2293 else
2294 for (j += inc; n-- > 0; j += inc)
b7f3516f 2295 scm_putc (SCM_CHARS (ra)[j], port);
0f2d19dd
JB
2296 break;
2297 case scm_tc7_byvect:
2298 if (n-- > 0)
4260a7fc 2299 scm_intprint (((char *) SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2300 for (j += inc; n-- > 0; j += inc)
2301 {
b7f3516f 2302 scm_putc (' ', port);
4260a7fc 2303 scm_intprint (((char *)SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2304 }
2305 break;
2306
2307 case scm_tc7_uvect:
5c11cc9d
GH
2308 {
2309 char str[11];
2310
2311 if (n-- > 0)
2312 {
2313 /* intprint can't handle >= 2^31. */
fee7ef83 2314 sprintf (str, "%lu", ((unsigned long *) SCM_VELTS (ra))[j]);
5c11cc9d
GH
2315 scm_puts (str, port);
2316 }
2317 for (j += inc; n-- > 0; j += inc)
2318 {
2319 scm_putc (' ', port);
fee7ef83 2320 sprintf (str, "%lu", ((unsigned long *) SCM_VELTS (ra))[j]);
5c11cc9d
GH
2321 scm_puts (str, port);
2322 }
2323 }
0f2d19dd
JB
2324 case scm_tc7_ivect:
2325 if (n-- > 0)
fee7ef83 2326 scm_intprint (((signed long *) SCM_VELTS (ra))[j], 10, port);
0f2d19dd
JB
2327 for (j += inc; n-- > 0; j += inc)
2328 {
b7f3516f 2329 scm_putc (' ', port);
fee7ef83 2330 scm_intprint (((signed long *) SCM_VELTS (ra))[j], 10, port);
0f2d19dd
JB
2331 }
2332 break;
2333
2334 case scm_tc7_svect:
2335 if (n-- > 0)
4260a7fc 2336 scm_intprint (((short *) SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2337 for (j += inc; n-- > 0; j += inc)
2338 {
b7f3516f 2339 scm_putc (' ', port);
4260a7fc 2340 scm_intprint (((short *) SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2341 }
2342 break;
2343
0f2d19dd
JB
2344 case scm_tc7_fvect:
2345 if (n-- > 0)
2346 {
bc86da5d
MD
2347 SCM z = scm_make_real (1.0);
2348 SCM_REAL_VALUE (z) = ((float *) SCM_VELTS (ra))[j];
2349 scm_print_real (z, port, pstate);
0f2d19dd
JB
2350 for (j += inc; n-- > 0; j += inc)
2351 {
b7f3516f 2352 scm_putc (' ', port);
bc86da5d
MD
2353 SCM_REAL_VALUE (z) = ((float *) SCM_VELTS (ra))[j];
2354 scm_print_real (z, port, pstate);
0f2d19dd
JB
2355 }
2356 }
2357 break;
0f2d19dd
JB
2358 case scm_tc7_dvect:
2359 if (n-- > 0)
2360 {
bc86da5d
MD
2361 SCM z = scm_make_real (1.0 / 3.0);
2362 SCM_REAL_VALUE (z) = ((double *) SCM_VELTS (ra))[j];
2363 scm_print_real (z, port, pstate);
0f2d19dd
JB
2364 for (j += inc; n-- > 0; j += inc)
2365 {
b7f3516f 2366 scm_putc (' ', port);
bc86da5d
MD
2367 SCM_REAL_VALUE (z) = ((double *) SCM_VELTS (ra))[j];
2368 scm_print_real (z, port, pstate);
0f2d19dd
JB
2369 }
2370 }
2371 break;
2372 case scm_tc7_cvect:
2373 if (n-- > 0)
2374 {
bc86da5d
MD
2375 SCM cz = scm_make_complex (0.0, 1.0), z = scm_make_real (1.0 / 3.0);
2376 SCM_REAL_VALUE (z) =
2377 SCM_COMPLEX_REAL (cz) = ((double *) SCM_VELTS (ra))[2 * j];
2378 SCM_COMPLEX_IMAG (cz) = ((double *) SCM_VELTS (ra))[2 * j + 1];
2379 scm_print_complex ((0.0 == SCM_COMPLEX_IMAG (cz) ? z : cz),
2380 port, pstate);
0f2d19dd
JB
2381 for (j += inc; n-- > 0; j += inc)
2382 {
b7f3516f 2383 scm_putc (' ', port);
bc86da5d
MD
2384 SCM_REAL_VALUE (z)
2385 = SCM_COMPLEX_REAL (cz) = ((double *) SCM_VELTS (ra))[2 * j];
2386 SCM_COMPLEX_IMAG (cz) = ((double *) SCM_VELTS (ra))[2 * j + 1];
2387 scm_print_complex ((0.0 == SCM_COMPLEX_IMAG (cz) ? z : cz),
2388 port, pstate);
0f2d19dd
JB
2389 }
2390 }
2391 break;
0f2d19dd
JB
2392 }
2393}
2394
2395
1cc91f1b 2396
0f2d19dd 2397int
1bbd0b84 2398scm_raprin1 (SCM exp, SCM port, scm_print_state *pstate)
0f2d19dd
JB
2399{
2400 SCM v = exp;
2401 scm_sizet base = 0;
b7f3516f 2402 scm_putc ('#', port);
0f2d19dd 2403tail:
5c11cc9d 2404 switch SCM_TYP7 (v)
0f2d19dd
JB
2405 {
2406 case scm_tc7_smob:
2407 {
2408 long ndim = SCM_ARRAY_NDIM (v);
2409 base = SCM_ARRAY_BASE (v);
2410 v = SCM_ARRAY_V (v);
2411 if (SCM_ARRAYP (v))
2412
2413 {
b7f3516f 2414 scm_puts ("<enclosed-array ", port);
9882ea19 2415 rapr1 (exp, base, 0, port, pstate);
b7f3516f 2416 scm_putc ('>', port);
0f2d19dd
JB
2417 return 1;
2418 }
2419 else
2420 {
2421 scm_intprint (ndim, 10, port);
2422 goto tail;
2423 }
2424 }
2425 case scm_tc7_bvect:
fee7ef83 2426 if (SCM_EQ_P (exp, v))
0f2d19dd
JB
2427 { /* a uve, not an scm_array */
2428 register long i, j, w;
b7f3516f 2429 scm_putc ('*', port);
0f2d19dd
JB
2430 for (i = 0; i < (SCM_LENGTH (exp)) / SCM_LONG_BIT; i++)
2431 {
f1267706 2432 scm_bits_t w = SCM_UNPACK (SCM_VELTS (exp)[i]);
0f2d19dd
JB
2433 for (j = SCM_LONG_BIT; j; j--)
2434 {
b7f3516f 2435 scm_putc (w & 1 ? '1' : '0', port);
0f2d19dd
JB
2436 w >>= 1;
2437 }
2438 }
2439 j = SCM_LENGTH (exp) % SCM_LONG_BIT;
2440 if (j)
2441 {
f1267706 2442 w = SCM_UNPACK (SCM_VELTS (exp)[SCM_LENGTH (exp) / SCM_LONG_BIT]);
0f2d19dd
JB
2443 for (; j; j--)
2444 {
b7f3516f 2445 scm_putc (w & 1 ? '1' : '0', port);
0f2d19dd
JB
2446 w >>= 1;
2447 }
2448 }
2449 return 1;
2450 }
2451 else
b7f3516f 2452 scm_putc ('b', port);
0f2d19dd
JB
2453 break;
2454 case scm_tc7_string:
b7f3516f 2455 scm_putc ('a', port);
0f2d19dd
JB
2456 break;
2457 case scm_tc7_byvect:
05c33d09 2458 scm_putc ('y', port);
0f2d19dd
JB
2459 break;
2460 case scm_tc7_uvect:
b7f3516f 2461 scm_putc ('u', port);
0f2d19dd
JB
2462 break;
2463 case scm_tc7_ivect:
b7f3516f 2464 scm_putc ('e', port);
0f2d19dd
JB
2465 break;
2466 case scm_tc7_svect:
05c33d09 2467 scm_putc ('h', port);
0f2d19dd 2468 break;
5c11cc9d 2469#ifdef HAVE_LONG_LONGS
0f2d19dd 2470 case scm_tc7_llvect:
5c11cc9d 2471 scm_putc ('l', port);
0f2d19dd
JB
2472 break;
2473#endif
0f2d19dd 2474 case scm_tc7_fvect:
b7f3516f 2475 scm_putc ('s', port);
0f2d19dd 2476 break;
0f2d19dd 2477 case scm_tc7_dvect:
b7f3516f 2478 scm_putc ('i', port);
0f2d19dd
JB
2479 break;
2480 case scm_tc7_cvect:
b7f3516f 2481 scm_putc ('c', port);
0f2d19dd 2482 break;
0f2d19dd 2483 }
b7f3516f 2484 scm_putc ('(', port);
9882ea19 2485 rapr1 (exp, base, 0, port, pstate);
b7f3516f 2486 scm_putc (')', port);
0f2d19dd
JB
2487 return 1;
2488}
2489
3b3b36dd 2490SCM_DEFINE (scm_array_prototype, "array-prototype", 1, 0, 0,
1bbd0b84 2491 (SCM ra),
b380b885
MD
2492 "Returns an object that would produce an array of the same type as\n"
2493 "@var{array}, if used as the @var{prototype} for\n"
2494 "@code{make-uniform-array}.")
1bbd0b84 2495#define FUNC_NAME s_scm_array_prototype
0f2d19dd
JB
2496{
2497 int enclosed = 0;
2498 SCM_ASRTGO (SCM_NIMP (ra), badarg);
2499loop:
2500 switch SCM_TYP7
2501 (ra)
2502 {
2503 default:
1bbd0b84 2504 badarg:SCM_WTA (1,ra);
0f2d19dd
JB
2505 case scm_tc7_smob:
2506 SCM_ASRTGO (SCM_ARRAYP (ra), badarg);
2507 if (enclosed++)
2508 return SCM_UNSPECIFIED;
2509 ra = SCM_ARRAY_V (ra);
2510 goto loop;
2511 case scm_tc7_vector:
95f5b0f5 2512 case scm_tc7_wvect:
0f2d19dd
JB
2513 return SCM_EOL;
2514 case scm_tc7_bvect:
2515 return SCM_BOOL_T;
2516 case scm_tc7_string:
7866a09b 2517 return SCM_MAKE_CHAR ('a');
0f2d19dd 2518 case scm_tc7_byvect:
7866a09b 2519 return SCM_MAKE_CHAR ('\0');
0f2d19dd
JB
2520 case scm_tc7_uvect:
2521 return SCM_MAKINUM (1L);
2522 case scm_tc7_ivect:
2523 return SCM_MAKINUM (-1L);
2524 case scm_tc7_svect:
2525 return SCM_CDR (scm_intern ("s", 1));
5c11cc9d 2526#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
2527 case scm_tc7_llvect:
2528 return SCM_CDR (scm_intern ("l", 1));
2529#endif
0f2d19dd 2530 case scm_tc7_fvect:
bc86da5d 2531 return scm_make_real (1.0);
0f2d19dd 2532 case scm_tc7_dvect:
bc86da5d 2533 return scm_make_real (1.0 / 3.0);
0f2d19dd 2534 case scm_tc7_cvect:
bc86da5d 2535 return scm_make_complex (0.0, 1.0);
0f2d19dd
JB
2536 }
2537}
1bbd0b84 2538#undef FUNC_NAME
0f2d19dd 2539
1cc91f1b 2540
0f2d19dd 2541static SCM
1bbd0b84 2542markra (SCM ptr)
0f2d19dd 2543{
0f2d19dd
JB
2544 return SCM_ARRAY_V (ptr);
2545}
2546
1cc91f1b 2547
0f2d19dd 2548static scm_sizet
1bbd0b84 2549freera (SCM ptr)
0f2d19dd
JB
2550{
2551 scm_must_free (SCM_CHARS (ptr));
2552 return sizeof (scm_array) + SCM_ARRAY_NDIM (ptr) * sizeof (scm_array_dim);
2553}
2554
0f2d19dd
JB
2555void
2556scm_init_unif ()
0f2d19dd 2557{
23a62151
MD
2558 scm_tc16_array = scm_make_smob_type_mfpe ("array", 0,
2559 markra,
2560 freera,
2561 scm_raprin1,
2562 scm_array_equal_p);
0f2d19dd 2563 scm_add_feature ("array");
a0599745 2564#include "libguile/unif.x"
0f2d19dd 2565}
89e00824
ML
2566
2567/*
2568 Local Variables:
2569 c-file-style: "gnu"
2570 End:
2571*/