* __scm.h: Added SCM_DEBUG as default debug option.
[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;
4260a7fc 159 if (SCM_TRUE_P (prot))
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:
4260a7fc 296 protp = (SCM_TRUE_P (prot));
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 */
3b3b36dd 788SCM_DEFINE (scm_transpose_array, "transpose-array", 0, 0, 1,
1bbd0b84 789 (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
JB
808{
809 SCM ra, res, vargs, *ve = &vargs;
810 scm_array_dim *s, *r;
811 int ndim, i, k;
1bbd0b84 812 SCM_ASSERT (SCM_NNULLP (args), scm_makfrom0str (FUNC_NAME),
f5bf2977 813 SCM_WNA, NULL);
0f2d19dd 814 ra = SCM_CAR (args);
1bbd0b84 815 SCM_ASSERT (SCM_NIMP (ra), ra, SCM_ARG1, FUNC_NAME);
0f2d19dd 816 args = SCM_CDR (args);
f5bf2977 817 switch (SCM_TYP7 (ra))
0f2d19dd
JB
818 {
819 default:
1bbd0b84 820 badarg:SCM_WTA (1,ra);
0f2d19dd
JB
821 case scm_tc7_bvect:
822 case scm_tc7_string:
823 case scm_tc7_byvect:
824 case scm_tc7_uvect:
825 case scm_tc7_ivect:
826 case scm_tc7_fvect:
827 case scm_tc7_dvect:
828 case scm_tc7_cvect:
829 case scm_tc7_svect:
5c11cc9d 830#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
831 case scm_tc7_llvect:
832#endif
f5bf2977 833 SCM_ASSERT (SCM_NIMP (args) && SCM_NULLP (SCM_CDR (args)),
1bbd0b84 834 scm_makfrom0str (FUNC_NAME), SCM_WNA, NULL);
f5bf2977 835 SCM_ASSERT (SCM_INUMP (SCM_CAR (args)), SCM_CAR (args), SCM_ARG2,
1bbd0b84 836 FUNC_NAME);
4260a7fc 837 SCM_ASSERT (SCM_EQ_P (SCM_INUM0, SCM_CAR (args)), SCM_CAR (args), SCM_OUTOFRANGE,
1bbd0b84 838 FUNC_NAME);
0f2d19dd
JB
839 return ra;
840 case scm_tc7_smob:
841 SCM_ASRTGO (SCM_ARRAYP (ra), badarg);
842 vargs = scm_vector (args);
f5bf2977 843 SCM_ASSERT (SCM_LENGTH (vargs) == SCM_ARRAY_NDIM (ra),
1bbd0b84 844 scm_makfrom0str (FUNC_NAME), SCM_WNA, NULL);
f5bf2977 845 ve = SCM_VELTS (vargs);
0f2d19dd
JB
846 ndim = 0;
847 for (k = 0; k < SCM_ARRAY_NDIM (ra); k++)
848 {
20a54673 849 SCM_ASSERT (SCM_INUMP (ve[k]), ve[k], (SCM_ARG2 + k),
1bbd0b84 850 FUNC_NAME);
0f2d19dd 851 i = SCM_INUM (ve[k]);
20a54673 852 SCM_ASSERT (i >= 0 && i < SCM_ARRAY_NDIM (ra), ve[k],
1bbd0b84 853 SCM_OUTOFRANGE, FUNC_NAME);
0f2d19dd
JB
854 if (ndim < i)
855 ndim = i;
856 }
857 ndim++;
858 res = scm_make_ra (ndim);
859 SCM_ARRAY_V (res) = SCM_ARRAY_V (ra);
860 SCM_ARRAY_BASE (res) = SCM_ARRAY_BASE (ra);
861 for (k = ndim; k--;)
862 {
863 SCM_ARRAY_DIMS (res)[k].lbnd = 0;
864 SCM_ARRAY_DIMS (res)[k].ubnd = -1;
865 }
866 for (k = SCM_ARRAY_NDIM (ra); k--;)
867 {
868 i = SCM_INUM (ve[k]);
869 s = &(SCM_ARRAY_DIMS (ra)[k]);
870 r = &(SCM_ARRAY_DIMS (res)[i]);
871 if (r->ubnd < r->lbnd)
872 {
873 r->lbnd = s->lbnd;
874 r->ubnd = s->ubnd;
875 r->inc = s->inc;
876 ndim--;
877 }
878 else
879 {
880 if (r->ubnd > s->ubnd)
881 r->ubnd = s->ubnd;
882 if (r->lbnd < s->lbnd)
883 {
884 SCM_ARRAY_BASE (res) += (s->lbnd - r->lbnd) * r->inc;
885 r->lbnd = s->lbnd;
886 }
887 r->inc += s->inc;
888 }
889 }
1bbd0b84 890 SCM_ASSERT (ndim <= 0, args, "bad argument list", FUNC_NAME);
0f2d19dd
JB
891 scm_ra_set_contp (res);
892 return res;
893 }
894}
1bbd0b84 895#undef FUNC_NAME
0f2d19dd
JB
896
897/* args are RA . AXES */
3b3b36dd 898SCM_DEFINE (scm_enclose_array, "enclose-array", 0, 0, 1,
1bbd0b84 899 (SCM axes),
b380b885
MD
900 "@var{dim0}, @var{dim1} @dots{} should be nonnegative integers less than\n"
901 "the rank of @var{array}. @var{enclose-array} returns an array\n"
902 "resembling an array of shared arrays. The dimensions of each shared\n"
903 "array are the same as the @var{dim}th dimensions of the original array,\n"
904 "the dimensions of the outer array are the same as those of the original\n"
905 "array that did not match a @var{dim}.\n\n"
906 "An enclosed array is not a general Scheme array. Its elements may not\n"
907 "be set using @code{array-set!}. Two references to the same element of\n"
908 "an enclosed array will be @code{equal?} but will not in general be\n"
909 "@code{eq?}. The value returned by @var{array-prototype} when given an\n"
910 "enclosed array is unspecified.\n\n"
911 "examples:\n"
912 "@example\n"
913 "(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1) @result{}\n"
914 " #<enclosed-array (#1(a d) #1(b e) #1(c f)) (#1(1 4) #1(2 5) #1(3 6))>\n\n"
915 "(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 0) @result{}\n"
916 " #<enclosed-array #2((a 1) (d 4)) #2((b 2) (e 5)) #2((c 3) (f 6))>\n"
917 "@end example")
1bbd0b84 918#define FUNC_NAME s_scm_enclose_array
0f2d19dd
JB
919{
920 SCM axv, ra, res, ra_inr;
921 scm_array_dim vdim, *s = &vdim;
922 int ndim, j, k, ninr, noutr;
1bbd0b84 923 SCM_ASSERT (SCM_NIMP (axes), scm_makfrom0str (FUNC_NAME), SCM_WNA,
f5bf2977 924 NULL);
0f2d19dd
JB
925 ra = SCM_CAR (axes);
926 axes = SCM_CDR (axes);
927 if (SCM_NULLP (axes))
0f2d19dd
JB
928 axes = scm_cons ((SCM_ARRAYP (ra) ? SCM_MAKINUM (SCM_ARRAY_NDIM (ra) - 1) : SCM_INUM0), SCM_EOL);
929 ninr = scm_ilength (axes);
930 ra_inr = scm_make_ra (ninr);
931 SCM_ASRTGO (SCM_NIMP (ra), badarg1);
932 switch SCM_TYP7
933 (ra)
934 {
935 default:
1bbd0b84 936 badarg1:SCM_WTA (1,ra);
0f2d19dd
JB
937 case scm_tc7_string:
938 case scm_tc7_bvect:
939 case scm_tc7_byvect:
940 case scm_tc7_uvect:
941 case scm_tc7_ivect:
942 case scm_tc7_fvect:
943 case scm_tc7_dvect:
944 case scm_tc7_cvect:
945 case scm_tc7_vector:
95f5b0f5 946 case scm_tc7_wvect:
0f2d19dd 947 case scm_tc7_svect:
5c11cc9d 948#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
949 case scm_tc7_llvect:
950#endif
951 s->lbnd = 0;
952 s->ubnd = SCM_LENGTH (ra) - 1;
953 s->inc = 1;
954 SCM_ARRAY_V (ra_inr) = ra;
955 SCM_ARRAY_BASE (ra_inr) = 0;
956 ndim = 1;
957 break;
958 case scm_tc7_smob:
959 SCM_ASRTGO (SCM_ARRAYP (ra), badarg1);
960 s = SCM_ARRAY_DIMS (ra);
961 SCM_ARRAY_V (ra_inr) = SCM_ARRAY_V (ra);
962 SCM_ARRAY_BASE (ra_inr) = SCM_ARRAY_BASE (ra);
963 ndim = SCM_ARRAY_NDIM (ra);
964 break;
965 }
966 noutr = ndim - ninr;
7866a09b 967 axv = scm_make_string (SCM_MAKINUM (ndim), SCM_MAKE_CHAR (0));
1bbd0b84 968 SCM_ASSERT (0 <= noutr && 0 <= ninr, scm_makfrom0str (FUNC_NAME),
f5bf2977 969 SCM_WNA, NULL);
0f2d19dd
JB
970 res = scm_make_ra (noutr);
971 SCM_ARRAY_BASE (res) = SCM_ARRAY_BASE (ra_inr);
972 SCM_ARRAY_V (res) = ra_inr;
973 for (k = 0; k < ninr; k++, axes = SCM_CDR (axes))
974 {
1bbd0b84 975 SCM_ASSERT (SCM_INUMP (SCM_CAR (axes)), SCM_CAR (axes), "bad axis", FUNC_NAME);
0f2d19dd
JB
976 j = SCM_INUM (SCM_CAR (axes));
977 SCM_ARRAY_DIMS (ra_inr)[k].lbnd = s[j].lbnd;
978 SCM_ARRAY_DIMS (ra_inr)[k].ubnd = s[j].ubnd;
979 SCM_ARRAY_DIMS (ra_inr)[k].inc = s[j].inc;
980 SCM_CHARS (axv)[j] = 1;
981 }
982 for (j = 0, k = 0; k < noutr; k++, j++)
983 {
984 while (SCM_CHARS (axv)[j])
985 j++;
986 SCM_ARRAY_DIMS (res)[k].lbnd = s[j].lbnd;
987 SCM_ARRAY_DIMS (res)[k].ubnd = s[j].ubnd;
988 SCM_ARRAY_DIMS (res)[k].inc = s[j].inc;
989 }
990 scm_ra_set_contp (ra_inr);
991 scm_ra_set_contp (res);
992 return res;
993}
1bbd0b84 994#undef FUNC_NAME
0f2d19dd
JB
995
996
997
3b3b36dd 998SCM_DEFINE (scm_array_in_bounds_p, "array-in-bounds?", 0, 0, 1,
1bbd0b84 999 (SCM args),
b380b885 1000 "Returns @code{#t} if its arguments would be acceptable to array-ref.")
1bbd0b84 1001#define FUNC_NAME s_scm_array_in_bounds_p
0f2d19dd
JB
1002{
1003 SCM v, ind = SCM_EOL;
1004 long pos = 0;
1005 register scm_sizet k;
1006 register long j;
1007 scm_array_dim *s;
1bbd0b84 1008 SCM_ASSERT (SCM_NIMP (args), scm_makfrom0str (FUNC_NAME),
f5bf2977 1009 SCM_WNA, NULL);
0f2d19dd
JB
1010 v = SCM_CAR (args);
1011 args = SCM_CDR (args);
1012 SCM_ASRTGO (SCM_NIMP (v), badarg1);
1013 if (SCM_NIMP (args))
1014
1015 {
1016 ind = SCM_CAR (args);
1017 args = SCM_CDR (args);
1bbd0b84 1018 SCM_ASSERT (SCM_INUMP (ind), ind, SCM_ARG2, FUNC_NAME);
0f2d19dd
JB
1019 pos = SCM_INUM (ind);
1020 }
1021tail:
1022 switch SCM_TYP7
1023 (v)
1024 {
1025 default:
1bbd0b84
GB
1026 badarg1:SCM_WTA (1,v);
1027 wna: scm_wrong_num_args (scm_makfrom0str (FUNC_NAME));
0f2d19dd
JB
1028 case scm_tc7_smob:
1029 k = SCM_ARRAY_NDIM (v);
1030 s = SCM_ARRAY_DIMS (v);
1031 pos = SCM_ARRAY_BASE (v);
1032 if (!k)
1033 {
1034 SCM_ASRTGO (SCM_NULLP (ind), wna);
1035 ind = SCM_INUM0;
1036 }
1037 else
1038 while (!0)
1039 {
1040 j = SCM_INUM (ind);
1041 if (!(j >= (s->lbnd) && j <= (s->ubnd)))
1042 {
1043 SCM_ASRTGO (--k == scm_ilength (args), wna);
1044 return SCM_BOOL_F;
1045 }
1046 pos += (j - s->lbnd) * (s->inc);
1047 if (!(--k && SCM_NIMP (args)))
1048 break;
1049 ind = SCM_CAR (args);
1050 args = SCM_CDR (args);
1051 s++;
1bbd0b84 1052 SCM_ASSERT (SCM_INUMP (ind), ind, s_bad_ind, FUNC_NAME);
0f2d19dd
JB
1053 }
1054 SCM_ASRTGO (0 == k, wna);
1055 v = SCM_ARRAY_V (v);
1056 goto tail;
1057 case scm_tc7_bvect:
1058 case scm_tc7_string:
1059 case scm_tc7_byvect:
1060 case scm_tc7_uvect:
1061 case scm_tc7_ivect:
1062 case scm_tc7_fvect:
1063 case scm_tc7_dvect:
1064 case scm_tc7_cvect:
1065 case scm_tc7_svect:
5c11cc9d 1066#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
1067 case scm_tc7_llvect:
1068#endif
1069 case scm_tc7_vector:
95f5b0f5 1070 case scm_tc7_wvect:
0f2d19dd 1071 SCM_ASRTGO (SCM_NULLP (args) && SCM_INUMP (ind), wna);
1bbd0b84 1072 return SCM_BOOL(pos >= 0 && pos < SCM_LENGTH (v));
0f2d19dd
JB
1073 }
1074}
1bbd0b84 1075#undef FUNC_NAME
0f2d19dd
JB
1076
1077
1bbd0b84 1078SCM_REGISTER_PROC(s_array_ref, "array-ref", 1, 0, 1, scm_uniform_vector_ref);
1cc91f1b 1079
1bbd0b84 1080
3b3b36dd 1081SCM_DEFINE (scm_uniform_vector_ref, "uniform-vector-ref", 2, 0, 0,
1bbd0b84 1082 (SCM v, SCM args),
b380b885 1083 "Returns the element at the @code{(index1, index2)} element in @var{array}.")
1bbd0b84 1084#define FUNC_NAME s_scm_uniform_vector_ref
0f2d19dd
JB
1085{
1086 long pos;
0f2d19dd 1087
35de7ebe 1088 if (SCM_IMP (v))
0f2d19dd
JB
1089 {
1090 SCM_ASRTGO (SCM_NULLP (args), badarg);
1091 return v;
1092 }
1093 else if (SCM_ARRAYP (v))
0f2d19dd 1094 {
1bbd0b84 1095 pos = scm_aind (v, args, FUNC_NAME);
0f2d19dd
JB
1096 v = SCM_ARRAY_V (v);
1097 }
1098 else
1099 {
1100 if (SCM_NIMP (args))
1101
1102 {
1bbd0b84 1103 SCM_ASSERT (SCM_CONSP (args) && SCM_INUMP (SCM_CAR (args)), args, SCM_ARG2, FUNC_NAME);
0f2d19dd
JB
1104 pos = SCM_INUM (SCM_CAR (args));
1105 SCM_ASRTGO (SCM_NULLP (SCM_CDR (args)), wna);
1106 }
1107 else
1108 {
3b3b36dd 1109 SCM_VALIDATE_INUM (2,args);
0f2d19dd
JB
1110 pos = SCM_INUM (args);
1111 }
1112 SCM_ASRTGO (pos >= 0 && pos < SCM_LENGTH (v), outrng);
1113 }
1114 switch SCM_TYP7
1115 (v)
1116 {
1117 default:
1118 if (SCM_NULLP (args))
1119 return v;
35de7ebe 1120 badarg:
1bbd0b84 1121 SCM_WTA (1,v);
35de7ebe 1122 abort ();
c209c88e
GB
1123
1124 outrng:
1125 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (pos));
1126 wna:
1127 scm_wrong_num_args (SCM_FUNC_NAME);
0f2d19dd
JB
1128 case scm_tc7_smob:
1129 { /* enclosed */
1130 int k = SCM_ARRAY_NDIM (v);
1131 SCM res = scm_make_ra (k);
1132 SCM_ARRAY_V (res) = SCM_ARRAY_V (v);
1133 SCM_ARRAY_BASE (res) = pos;
1134 while (k--)
1135 {
1136 SCM_ARRAY_DIMS (res)[k].lbnd = SCM_ARRAY_DIMS (v)[k].lbnd;
1137 SCM_ARRAY_DIMS (res)[k].ubnd = SCM_ARRAY_DIMS (v)[k].ubnd;
1138 SCM_ARRAY_DIMS (res)[k].inc = SCM_ARRAY_DIMS (v)[k].inc;
1139 }
1140 return res;
1141 }
1142 case scm_tc7_bvect:
c209c88e 1143 if (SCM_BITVEC_REF (v, pos))
0f2d19dd
JB
1144 return SCM_BOOL_T;
1145 else
1146 return SCM_BOOL_F;
1147 case scm_tc7_string:
7866a09b 1148 return SCM_MAKE_CHAR (SCM_UCHARS (v)[pos]);
0f2d19dd
JB
1149 case scm_tc7_byvect:
1150 return SCM_MAKINUM (((char *)SCM_CHARS (v))[pos]);
0f2d19dd 1151 case scm_tc7_uvect:
fee7ef83 1152 return scm_ulong2num (((unsigned long *) SCM_VELTS (v))[pos]);
0f2d19dd 1153 case scm_tc7_ivect:
fee7ef83 1154 return scm_long2num(((signed long *) SCM_VELTS (v))[pos]);
0f2d19dd
JB
1155
1156 case scm_tc7_svect:
4260a7fc 1157 return SCM_MAKINUM (((short *) SCM_CELL_WORD_1 (v))[pos]);
5c11cc9d 1158#ifdef HAVE_LONG_LONGS
0f2d19dd 1159 case scm_tc7_llvect:
4260a7fc 1160 return scm_long_long2num (((long_long *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd
JB
1161#endif
1162
0f2d19dd 1163 case scm_tc7_fvect:
4260a7fc 1164 return scm_make_real (((float *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1165 case scm_tc7_dvect:
4260a7fc 1166 return scm_make_real (((double *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1167 case scm_tc7_cvect:
4260a7fc
DH
1168 return scm_make_complex (((double *) SCM_CELL_WORD_1 (v))[2 * pos],
1169 ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1]);
0f2d19dd 1170 case scm_tc7_vector:
95f5b0f5 1171 case scm_tc7_wvect:
0f2d19dd
JB
1172 return SCM_VELTS (v)[pos];
1173 }
1174}
1bbd0b84 1175#undef FUNC_NAME
0f2d19dd
JB
1176
1177/* Internal version of scm_uniform_vector_ref for uves that does no error checking and
1178 tries to recycle conses. (Make *sure* you want them recycled.) */
1cc91f1b 1179
0f2d19dd 1180SCM
6e8d25a6 1181scm_cvref (SCM v, scm_sizet pos, SCM last)
0f2d19dd 1182{
5c11cc9d 1183 switch SCM_TYP7 (v)
0f2d19dd
JB
1184 {
1185 default:
1186 scm_wta (v, (char *) SCM_ARG1, "PROGRAMMING ERROR: scm_cvref");
1187 case scm_tc7_bvect:
c209c88e 1188 if (SCM_BITVEC_REF(v,pos))
0f2d19dd
JB
1189 return SCM_BOOL_T;
1190 else
1191 return SCM_BOOL_F;
1192 case scm_tc7_string:
7866a09b 1193 return SCM_MAKE_CHAR (SCM_UCHARS (v)[pos]);
0f2d19dd
JB
1194 case scm_tc7_byvect:
1195 return SCM_MAKINUM (((char *)SCM_CHARS (v))[pos]);
0f2d19dd 1196 case scm_tc7_uvect:
fee7ef83 1197 return scm_ulong2num(((unsigned long *) SCM_VELTS (v))[pos]);
0f2d19dd 1198 case scm_tc7_ivect:
fee7ef83 1199 return scm_long2num(((signed long *) SCM_VELTS (v))[pos]);
0f2d19dd 1200 case scm_tc7_svect:
4260a7fc 1201 return SCM_MAKINUM (((short *) SCM_CELL_WORD_1 (v))[pos]);
5c11cc9d 1202#ifdef HAVE_LONG_LONGS
0f2d19dd 1203 case scm_tc7_llvect:
4260a7fc 1204 return scm_long_long2num (((long_long *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1205#endif
0f2d19dd 1206 case scm_tc7_fvect:
fee7ef83 1207 if (SCM_NIMP (last) && !SCM_EQ_P (last, scm_flo0) && SCM_SLOPPY_REALP (last))
0f2d19dd 1208 {
4260a7fc 1209 SCM_REAL_VALUE (last) = ((float *) SCM_CELL_WORD_1 (v))[pos];
0f2d19dd
JB
1210 return last;
1211 }
4260a7fc 1212 return scm_make_real (((float *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1213 case scm_tc7_dvect:
fee7ef83 1214 if (SCM_NIMP (last) && !SCM_EQ_P (last, scm_flo0) && SCM_SLOPPY_REALP (last))
0f2d19dd 1215 {
4260a7fc 1216 SCM_REAL_VALUE (last) = ((double *) SCM_CELL_WORD_1 (v))[pos];
0f2d19dd
JB
1217 return last;
1218 }
4260a7fc 1219 return scm_make_real (((double *) SCM_CELL_WORD_1 (v))[pos]);
0f2d19dd 1220 case scm_tc7_cvect:
bc86da5d 1221 if (SCM_NIMP (last) && SCM_SLOPPY_COMPLEXP (last))
0f2d19dd 1222 {
4260a7fc
DH
1223 SCM_COMPLEX_REAL (last) = ((double *) SCM_CELL_WORD_1 (v))[2 * pos];
1224 SCM_COMPLEX_IMAG (last) = ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1];
0f2d19dd
JB
1225 return last;
1226 }
4260a7fc
DH
1227 return scm_make_complex (((double *) SCM_CELL_WORD_1 (v))[2 * pos],
1228 ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1]);
0f2d19dd 1229 case scm_tc7_vector:
95f5b0f5 1230 case scm_tc7_wvect:
0f2d19dd
JB
1231 return SCM_VELTS (v)[pos];
1232 case scm_tc7_smob:
1233 { /* enclosed scm_array */
1234 int k = SCM_ARRAY_NDIM (v);
1235 SCM res = scm_make_ra (k);
1236 SCM_ARRAY_V (res) = SCM_ARRAY_V (v);
1237 SCM_ARRAY_BASE (res) = pos;
1238 while (k--)
1239 {
1240 SCM_ARRAY_DIMS (res)[k].ubnd = SCM_ARRAY_DIMS (v)[k].ubnd;
1241 SCM_ARRAY_DIMS (res)[k].lbnd = SCM_ARRAY_DIMS (v)[k].lbnd;
1242 SCM_ARRAY_DIMS (res)[k].inc = SCM_ARRAY_DIMS (v)[k].inc;
1243 }
1244 return res;
1245 }
1246 }
1247}
1248
1bbd0b84
GB
1249SCM_REGISTER_PROC(s_uniform_array_set1_x, "uniform-array-set1!", 3, 0, 0, scm_array_set_x);
1250
1cc91f1b 1251
0aa0871f
GH
1252/* Note that args may be a list or an immediate object, depending which
1253 PROC is used (and it's called from C too). */
3b3b36dd 1254SCM_DEFINE (scm_array_set_x, "array-set!", 2, 0, 1,
1bbd0b84 1255 (SCM v, SCM obj, SCM args),
b380b885
MD
1256 "Sets the element at the @code{(index1, index2)} element in @var{array} to\n"
1257 "@var{new-value}. The value returned by array-set! is unspecified.")
1bbd0b84 1258#define FUNC_NAME s_scm_array_set_x
0f2d19dd 1259{
f3667f52 1260 long pos = 0;
0f2d19dd
JB
1261 SCM_ASRTGO (SCM_NIMP (v), badarg1);
1262 if (SCM_ARRAYP (v))
0f2d19dd 1263 {
1bbd0b84 1264 pos = scm_aind (v, args, FUNC_NAME);
0f2d19dd
JB
1265 v = SCM_ARRAY_V (v);
1266 }
1267 else
1268 {
1269 if (SCM_NIMP (args))
0f2d19dd 1270 {
0aa0871f 1271 SCM_ASSERT (SCM_CONSP(args) && SCM_INUMP (SCM_CAR (args)), args,
1bbd0b84 1272 SCM_ARG3, FUNC_NAME);
0f2d19dd 1273 SCM_ASRTGO (SCM_NULLP (SCM_CDR (args)), wna);
0aa0871f 1274 pos = SCM_INUM (SCM_CAR (args));
0f2d19dd
JB
1275 }
1276 else
1277 {
3b3b36dd 1278 SCM_VALIDATE_INUM_COPY (3,args,pos);
0f2d19dd
JB
1279 }
1280 SCM_ASRTGO (pos >= 0 && pos < SCM_LENGTH (v), outrng);
1281 }
1282 switch (SCM_TYP7 (v))
1283 {
35de7ebe 1284 default: badarg1:
1bbd0b84 1285 SCM_WTA (1,v);
35de7ebe 1286 abort ();
c209c88e
GB
1287 outrng:
1288 scm_out_of_range (FUNC_NAME, SCM_MAKINUM (pos));
1289 wna:
1290 scm_wrong_num_args (SCM_FUNC_NAME);
0f2d19dd
JB
1291 case scm_tc7_smob: /* enclosed */
1292 goto badarg1;
1293 case scm_tc7_bvect:
4260a7fc 1294 if (SCM_FALSEP (obj))
c209c88e 1295 SCM_BITVEC_CLR(v,pos);
4260a7fc 1296 else if (SCM_TRUE_P (obj))
c209c88e 1297 SCM_BITVEC_SET(v,pos);
0f2d19dd 1298 else
1bbd0b84 1299 badobj:SCM_WTA (2,obj);
0f2d19dd
JB
1300 break;
1301 case scm_tc7_string:
7866a09b
GB
1302 SCM_ASRTGO (SCM_CHARP (obj), badobj);
1303 SCM_UCHARS (v)[pos] = SCM_CHAR (obj);
0f2d19dd
JB
1304 break;
1305 case scm_tc7_byvect:
7866a09b
GB
1306 if (SCM_CHARP (obj))
1307 obj = SCM_MAKINUM ((char) SCM_CHAR (obj));
0aa0871f 1308 SCM_ASRTGO (SCM_INUMP (obj), badobj);
0f2d19dd
JB
1309 ((char *)SCM_CHARS (v))[pos] = SCM_INUM (obj);
1310 break;
1bbd0b84 1311 case scm_tc7_uvect:
f1267706 1312 SCM_VELTS(v)[pos] = SCM_PACK (scm_num2ulong(obj, (char *)SCM_ARG2, FUNC_NAME));
c209c88e 1313 break;
1bbd0b84 1314 case scm_tc7_ivect:
f1267706 1315 SCM_VELTS(v)[pos] = SCM_PACK (scm_num2long(obj, (char *)SCM_ARG2, FUNC_NAME));
c209c88e 1316 break;
0f2d19dd 1317 case scm_tc7_svect:
0aa0871f 1318 SCM_ASRTGO (SCM_INUMP (obj), badobj);
4260a7fc 1319 ((short *) SCM_CELL_WORD_1 (v))[pos] = SCM_INUM (obj);
0f2d19dd 1320 break;
5c11cc9d 1321#ifdef HAVE_LONG_LONGS
0f2d19dd 1322 case scm_tc7_llvect:
4260a7fc 1323 ((long_long *) SCM_CELL_WORD_1 (v))[pos] = scm_num2long_long (obj, (char *)SCM_ARG2, FUNC_NAME);
0f2d19dd
JB
1324 break;
1325#endif
1326
1327
0f2d19dd 1328 case scm_tc7_fvect:
4260a7fc 1329 ((float *) SCM_CELL_WORD_1 (v))[pos] = (float) scm_num2dbl (obj, FUNC_NAME);
0f2d19dd 1330 break;
0f2d19dd 1331 case scm_tc7_dvect:
4260a7fc 1332 ((double *) SCM_CELL_WORD_1 (v))[pos] = scm_num2dbl (obj, FUNC_NAME);
0f2d19dd
JB
1333 break;
1334 case scm_tc7_cvect:
eb42e2f0
DH
1335 SCM_ASRTGO (SCM_INEXACTP (obj), badobj);
1336 if (SCM_REALP (obj)) {
1337 ((double *) SCM_CELL_WORD_1 (v))[2 * pos] = SCM_REAL_VALUE (obj);
1338 ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1] = 0.0;
1339 } else {
1340 ((double *) SCM_CELL_WORD_1 (v))[2 * pos] = SCM_COMPLEX_REAL (obj);
1341 ((double *) SCM_CELL_WORD_1 (v))[2 * pos + 1] = SCM_COMPLEX_IMAG (obj);
1342 }
0f2d19dd 1343 break;
0f2d19dd 1344 case scm_tc7_vector:
95f5b0f5 1345 case scm_tc7_wvect:
0f2d19dd
JB
1346 SCM_VELTS (v)[pos] = obj;
1347 break;
1348 }
1349 return SCM_UNSPECIFIED;
1350}
1bbd0b84 1351#undef FUNC_NAME
0f2d19dd 1352
1d7bdb25
GH
1353/* attempts to unroll an array into a one-dimensional array.
1354 returns the unrolled array or #f if it can't be done. */
1bbd0b84 1355 /* if strict is not SCM_UNDEFINED, return #f if returned array
1d7bdb25 1356 wouldn't have contiguous elements. */
3b3b36dd 1357SCM_DEFINE (scm_array_contents, "array-contents", 1, 1, 0,
1bbd0b84 1358 (SCM ra, SCM strict),
b380b885
MD
1359 "@deffnx primitive array-contents array strict\n"
1360 "If @var{array} may be @dfn{unrolled} into a one dimensional shared array\n"
1361 "without changing their order (last subscript changing fastest), then\n"
1362 "@code{array-contents} returns that shared array, otherwise it returns\n"
1363 "@code{#f}. All arrays made by @var{make-array} and\n"
1364 "@var{make-uniform-array} may be unrolled, some arrays made by\n"
1365 "@var{make-shared-array} may not be.\n\n"
1366 "If the optional argument @var{strict} is provided, a shared array will\n"
1367 "be returned only if its elements are stored internally contiguous in\n"
1368 "memory.")
1bbd0b84 1369#define FUNC_NAME s_scm_array_contents
0f2d19dd
JB
1370{
1371 SCM sra;
1372 if (SCM_IMP (ra))
f3667f52 1373 return SCM_BOOL_F;
5c11cc9d 1374 switch SCM_TYP7 (ra)
0f2d19dd
JB
1375 {
1376 default:
1377 return SCM_BOOL_F;
1378 case scm_tc7_vector:
95f5b0f5 1379 case scm_tc7_wvect:
0f2d19dd
JB
1380 case scm_tc7_string:
1381 case scm_tc7_bvect:
1382 case scm_tc7_byvect:
1383 case scm_tc7_uvect:
1384 case scm_tc7_ivect:
1385 case scm_tc7_fvect:
1386 case scm_tc7_dvect:
1387 case scm_tc7_cvect:
1388 case scm_tc7_svect:
5c11cc9d 1389#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
1390 case scm_tc7_llvect:
1391#endif
1392 return ra;
1393 case scm_tc7_smob:
1394 {
1395 scm_sizet k, ndim = SCM_ARRAY_NDIM (ra), len = 1;
1396 if (!SCM_ARRAYP (ra) || !SCM_ARRAY_CONTP (ra))
1397 return SCM_BOOL_F;
1398 for (k = 0; k < ndim; k++)
1399 len *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1400 if (!SCM_UNBNDP (strict))
1401 {
0f2d19dd
JB
1402 if (ndim && (1 != SCM_ARRAY_DIMS (ra)[ndim - 1].inc))
1403 return SCM_BOOL_F;
1404 if (scm_tc7_bvect == SCM_TYP7 (SCM_ARRAY_V (ra)))
1405 {
1406 if (len != SCM_LENGTH (SCM_ARRAY_V (ra)) ||
1407 SCM_ARRAY_BASE (ra) % SCM_LONG_BIT ||
1408 len % SCM_LONG_BIT)
1409 return SCM_BOOL_F;
1410 }
1411 }
1412 if ((len == SCM_LENGTH (SCM_ARRAY_V (ra))) && 0 == SCM_ARRAY_BASE (ra) && SCM_ARRAY_DIMS (ra)->inc)
1413 return SCM_ARRAY_V (ra);
1414 sra = scm_make_ra (1);
1415 SCM_ARRAY_DIMS (sra)->lbnd = 0;
1416 SCM_ARRAY_DIMS (sra)->ubnd = len - 1;
1417 SCM_ARRAY_V (sra) = SCM_ARRAY_V (ra);
1418 SCM_ARRAY_BASE (sra) = SCM_ARRAY_BASE (ra);
1419 SCM_ARRAY_DIMS (sra)->inc = (ndim ? SCM_ARRAY_DIMS (ra)[ndim - 1].inc : 1);
1420 return sra;
1421 }
1422 }
1423}
1bbd0b84 1424#undef FUNC_NAME
0f2d19dd 1425
1cc91f1b 1426
0f2d19dd 1427SCM
6e8d25a6 1428scm_ra2contig (SCM ra, int copy)
0f2d19dd
JB
1429{
1430 SCM ret;
1431 long inc = 1;
1432 scm_sizet k, len = 1;
1433 for (k = SCM_ARRAY_NDIM (ra); k--;)
1434 len *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1435 k = SCM_ARRAY_NDIM (ra);
1436 if (SCM_ARRAY_CONTP (ra) && ((0 == k) || (1 == SCM_ARRAY_DIMS (ra)[k - 1].inc)))
1437 {
1438 if (scm_tc7_bvect != SCM_TYP7 (ra))
1439 return ra;
1440 if ((len == SCM_LENGTH (SCM_ARRAY_V (ra)) &&
1441 0 == SCM_ARRAY_BASE (ra) % SCM_LONG_BIT &&
1442 0 == len % SCM_LONG_BIT))
1443 return ra;
1444 }
1445 ret = scm_make_ra (k);
1446 SCM_ARRAY_BASE (ret) = 0;
1447 while (k--)
1448 {
1449 SCM_ARRAY_DIMS (ret)[k].lbnd = SCM_ARRAY_DIMS (ra)[k].lbnd;
1450 SCM_ARRAY_DIMS (ret)[k].ubnd = SCM_ARRAY_DIMS (ra)[k].ubnd;
1451 SCM_ARRAY_DIMS (ret)[k].inc = inc;
1452 inc *= SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1;
1453 }
1454 SCM_ARRAY_V (ret) = scm_make_uve ((inc - 1), scm_array_prototype (ra));
1455 if (copy)
1456 scm_array_copy_x (ra, ret);
1457 return ret;
1458}
1459
1460
1461
3b3b36dd 1462SCM_DEFINE (scm_uniform_array_read_x, "uniform-array-read!", 1, 3, 0,
1bbd0b84 1463 (SCM ra, SCM port_or_fd, SCM start, SCM end),
b380b885
MD
1464 "@deffnx primitive uniform-vector-read! uve [port-or-fdes] [start] [end]\n"
1465 "Attempts to read all elements of @var{ura}, in lexicographic order, as\n"
1466 "binary objects from @var{port-or-fdes}.\n"
1467 "If an end of file is encountered during\n"
1468 "uniform-array-read! the objects up to that point only are put into @var{ura}\n"
1469 "(starting at the beginning) and the remainder of the array is\n"
1470 "unchanged.\n\n"
1471 "The optional arguments @var{start} and @var{end} allow\n"
1472 "a specified region of a vector (or linearized array) to be read,\n"
1473 "leaving the remainder of the vector unchanged.\n\n"
1474 "@code{uniform-array-read!} returns the number of objects read.\n"
1475 "@var{port-or-fdes} may be omitted, in which case it defaults to the value\n"
1476 "returned by @code{(current-input-port)}.")
1bbd0b84 1477#define FUNC_NAME s_scm_uniform_array_read_x
0f2d19dd 1478{
35de7ebe 1479 SCM cra = SCM_UNDEFINED, v = ra;
3d8d56df 1480 long sz, vlen, ans;
1146b6cd
GH
1481 long cstart = 0;
1482 long cend;
1483 long offset = 0;
35de7ebe 1484
0f2d19dd 1485 SCM_ASRTGO (SCM_NIMP (v), badarg1);
3d8d56df
GH
1486 if (SCM_UNBNDP (port_or_fd))
1487 port_or_fd = scm_cur_inp;
1488 else
1489 SCM_ASSERT (SCM_INUMP (port_or_fd)
0c95b57d 1490 || (SCM_OPINPORTP (port_or_fd)),
1bbd0b84 1491 port_or_fd, SCM_ARG2, FUNC_NAME);
3d8d56df 1492 vlen = SCM_LENGTH (v);
35de7ebe 1493
0f2d19dd 1494loop:
35de7ebe 1495 switch SCM_TYP7 (v)
0f2d19dd
JB
1496 {
1497 default:
5d2d2ffc 1498 badarg1:SCM_WTA (SCM_ARG1,v);
0f2d19dd
JB
1499 case scm_tc7_smob:
1500 SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
1501 cra = scm_ra2contig (ra, 0);
1146b6cd 1502 cstart += SCM_ARRAY_BASE (cra);
3d8d56df 1503 vlen = SCM_ARRAY_DIMS (cra)->inc *
0f2d19dd
JB
1504 (SCM_ARRAY_DIMS (cra)->ubnd - SCM_ARRAY_DIMS (cra)->lbnd + 1);
1505 v = SCM_ARRAY_V (cra);
1506 goto loop;
1507 case scm_tc7_string:
1508 case scm_tc7_byvect:
1509 sz = sizeof (char);
1510 break;
1511 case scm_tc7_bvect:
3d8d56df 1512 vlen = (vlen + SCM_LONG_BIT - 1) / SCM_LONG_BIT;
1146b6cd 1513 cstart /= SCM_LONG_BIT;
0f2d19dd
JB
1514 case scm_tc7_uvect:
1515 case scm_tc7_ivect:
1516 sz = sizeof (long);
1517 break;
1518 case scm_tc7_svect:
1519 sz = sizeof (short);
1520 break;
5c11cc9d 1521#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
1522 case scm_tc7_llvect:
1523 sz = sizeof (long_long);
1524 break;
1525#endif
0f2d19dd
JB
1526 case scm_tc7_fvect:
1527 sz = sizeof (float);
1528 break;
0f2d19dd
JB
1529 case scm_tc7_dvect:
1530 sz = sizeof (double);
1531 break;
1532 case scm_tc7_cvect:
1533 sz = 2 * sizeof (double);
1534 break;
0f2d19dd 1535 }
3d8d56df 1536
1146b6cd
GH
1537 cend = vlen;
1538 if (!SCM_UNBNDP (start))
3d8d56df 1539 {
1146b6cd 1540 offset =
4638e087 1541 SCM_NUM2LONG (3, start);
35de7ebe 1542
1146b6cd 1543 if (offset < 0 || offset >= cend)
1bbd0b84 1544 scm_out_of_range (FUNC_NAME, start);
1146b6cd
GH
1545
1546 if (!SCM_UNBNDP (end))
1547 {
1548 long tend =
4638e087 1549 SCM_NUM2LONG (4, end);
3d8d56df 1550
1146b6cd 1551 if (tend <= offset || tend > cend)
1bbd0b84 1552 scm_out_of_range (FUNC_NAME, end);
1146b6cd
GH
1553 cend = tend;
1554 }
0f2d19dd 1555 }
35de7ebe 1556
3d8d56df
GH
1557 if (SCM_NIMP (port_or_fd))
1558 {
6c951427
GH
1559 scm_port *pt = SCM_PTAB_ENTRY (port_or_fd);
1560 int remaining = (cend - offset) * sz;
1561 char *dest = SCM_CHARS (v) + (cstart + offset) * sz;
1562
1563 if (pt->rw_active == SCM_PORT_WRITE)
affc96b5 1564 scm_flush (port_or_fd);
6c951427
GH
1565
1566 ans = cend - offset;
1567 while (remaining > 0)
3d8d56df 1568 {
6c951427
GH
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 {
affc96b5 1581 if (scm_fill_input (port_or_fd) == EOF)
6c951427
GH
1582 {
1583 if (remaining % sz != 0)
1584 {
5d2d2ffc 1585 SCM_MISC_ERROR ("unexpected EOF", SCM_EOL);
6c951427
GH
1586 }
1587 ans -= remaining / sz;
1588 break;
1589 }
6c951427 1590 }
3d8d56df 1591 }
6c951427
GH
1592
1593 if (pt->rw_random)
1594 pt->rw_active = SCM_PORT_READ;
3d8d56df
GH
1595 }
1596 else /* file descriptor. */
1597 {
1598 SCM_SYSCALL (ans = read (SCM_INUM (port_or_fd),
1146b6cd
GH
1599 SCM_CHARS (v) + (cstart + offset) * sz,
1600 (scm_sizet) (sz * (cend - offset))));
3d8d56df 1601 if (ans == -1)
1bbd0b84 1602 SCM_SYSERROR;
3d8d56df 1603 }
0f2d19dd
JB
1604 if (SCM_TYP7 (v) == scm_tc7_bvect)
1605 ans *= SCM_LONG_BIT;
35de7ebe 1606
fee7ef83 1607 if (!SCM_EQ_P (v, ra) && !SCM_EQ_P (cra, ra))
0f2d19dd 1608 scm_array_copy_x (cra, ra);
35de7ebe 1609
0f2d19dd
JB
1610 return SCM_MAKINUM (ans);
1611}
1bbd0b84 1612#undef FUNC_NAME
0f2d19dd 1613
3b3b36dd 1614SCM_DEFINE (scm_uniform_array_write, "uniform-array-write", 1, 3, 0,
1bbd0b84 1615 (SCM v, SCM port_or_fd, SCM start, SCM end),
b380b885
MD
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)}.")
1bbd0b84 1626#define FUNC_NAME s_scm_uniform_array_write
0f2d19dd 1627{
3d8d56df 1628 long sz, vlen, ans;
1146b6cd
GH
1629 long offset = 0;
1630 long cstart = 0;
1631 long cend;
3d8d56df 1632
78446828
MV
1633 port_or_fd = SCM_COERCE_OUTPORT (port_or_fd);
1634
0f2d19dd 1635 SCM_ASRTGO (SCM_NIMP (v), badarg1);
3d8d56df
GH
1636 if (SCM_UNBNDP (port_or_fd))
1637 port_or_fd = scm_cur_outp;
1638 else
1639 SCM_ASSERT (SCM_INUMP (port_or_fd)
0c95b57d 1640 || (SCM_OPOUTPORTP (port_or_fd)),
1bbd0b84 1641 port_or_fd, SCM_ARG2, FUNC_NAME);
3d8d56df
GH
1642 vlen = SCM_LENGTH (v);
1643
0f2d19dd 1644loop:
3d8d56df 1645 switch SCM_TYP7 (v)
0f2d19dd
JB
1646 {
1647 default:
4638e087 1648 badarg1:SCM_WTA (1, v);
0f2d19dd
JB
1649 case scm_tc7_smob:
1650 SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
1651 v = scm_ra2contig (v, 1);
1146b6cd 1652 cstart = SCM_ARRAY_BASE (v);
3d8d56df
GH
1653 vlen = SCM_ARRAY_DIMS (v)->inc
1654 * (SCM_ARRAY_DIMS (v)->ubnd - SCM_ARRAY_DIMS (v)->lbnd + 1);
0f2d19dd
JB
1655 v = SCM_ARRAY_V (v);
1656 goto loop;
0f2d19dd 1657 case scm_tc7_string:
3d8d56df 1658 case scm_tc7_byvect:
0f2d19dd
JB
1659 sz = sizeof (char);
1660 break;
1661 case scm_tc7_bvect:
3d8d56df 1662 vlen = (vlen + SCM_LONG_BIT - 1) / SCM_LONG_BIT;
1146b6cd 1663 cstart /= SCM_LONG_BIT;
0f2d19dd
JB
1664 case scm_tc7_uvect:
1665 case scm_tc7_ivect:
1666 sz = sizeof (long);
1667 break;
1668 case scm_tc7_svect:
1669 sz = sizeof (short);
1670 break;
5c11cc9d 1671#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
1672 case scm_tc7_llvect:
1673 sz = sizeof (long_long);
1674 break;
1675#endif
0f2d19dd
JB
1676 case scm_tc7_fvect:
1677 sz = sizeof (float);
1678 break;
0f2d19dd
JB
1679 case scm_tc7_dvect:
1680 sz = sizeof (double);
1681 break;
1682 case scm_tc7_cvect:
1683 sz = 2 * sizeof (double);
1684 break;
0f2d19dd 1685 }
3d8d56df 1686
1146b6cd
GH
1687 cend = vlen;
1688 if (!SCM_UNBNDP (start))
3d8d56df 1689 {
1146b6cd 1690 offset =
4638e087 1691 SCM_NUM2LONG (3, start);
3d8d56df 1692
1146b6cd 1693 if (offset < 0 || offset >= cend)
1bbd0b84 1694 scm_out_of_range (FUNC_NAME, start);
1146b6cd
GH
1695
1696 if (!SCM_UNBNDP (end))
1697 {
1698 long tend =
4638e087 1699 SCM_NUM2LONG (4, end);
3d8d56df 1700
1146b6cd 1701 if (tend <= offset || tend > cend)
1bbd0b84 1702 scm_out_of_range (FUNC_NAME, end);
1146b6cd
GH
1703 cend = tend;
1704 }
3d8d56df
GH
1705 }
1706
1707 if (SCM_NIMP (port_or_fd))
1708 {
6c951427 1709 char *source = SCM_CHARS (v) + (cstart + offset) * sz;
6c951427
GH
1710
1711 ans = cend - offset;
265e6a4d 1712 scm_lfwrite (source, ans * sz, port_or_fd);
3d8d56df
GH
1713 }
1714 else /* file descriptor. */
1715 {
1716 SCM_SYSCALL (ans = write (SCM_INUM (port_or_fd),
1146b6cd
GH
1717 SCM_CHARS (v) + (cstart + offset) * sz,
1718 (scm_sizet) (sz * (cend - offset))));
3d8d56df 1719 if (ans == -1)
1bbd0b84 1720 SCM_SYSERROR;
3d8d56df 1721 }
0f2d19dd
JB
1722 if (SCM_TYP7 (v) == scm_tc7_bvect)
1723 ans *= SCM_LONG_BIT;
3d8d56df 1724
0f2d19dd
JB
1725 return SCM_MAKINUM (ans);
1726}
1bbd0b84 1727#undef FUNC_NAME
0f2d19dd
JB
1728
1729
1730static char cnt_tab[16] =
1731{0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
1732
3b3b36dd 1733SCM_DEFINE (scm_bit_count, "bit-count", 2, 0, 0,
1bbd0b84 1734 (SCM item, SCM seq),
b380b885 1735 "Returns the number occurrences of @var{bool} in @var{bv}.")
1bbd0b84 1736#define FUNC_NAME s_scm_bit_count
0f2d19dd
JB
1737{
1738 long i;
c209c88e
GB
1739 register unsigned long cnt = 0;
1740 register unsigned long w;
3b3b36dd 1741 SCM_VALIDATE_INUM (2,seq);
5c11cc9d 1742 switch SCM_TYP7 (seq)
0f2d19dd
JB
1743 {
1744 default:
1bbd0b84 1745 SCM_WTA (2,seq);
0f2d19dd
JB
1746 case scm_tc7_bvect:
1747 if (0 == SCM_LENGTH (seq))
1748 return SCM_INUM0;
1749 i = (SCM_LENGTH (seq) - 1) / SCM_LONG_BIT;
f1267706 1750 w = SCM_UNPACK (SCM_VELTS (seq)[i]);
0f2d19dd
JB
1751 if (SCM_FALSEP (item))
1752 w = ~w;
1753 w <<= SCM_LONG_BIT - 1 - ((SCM_LENGTH (seq) - 1) % SCM_LONG_BIT);
1754 while (!0)
1755 {
1756 for (; w; w >>= 4)
1757 cnt += cnt_tab[w & 0x0f];
1758 if (0 == i--)
1759 return SCM_MAKINUM (cnt);
f1267706 1760 w = SCM_UNPACK (SCM_VELTS (seq)[i]);
0f2d19dd
JB
1761 if (SCM_FALSEP (item))
1762 w = ~w;
1763 }
1764 }
1765}
1bbd0b84 1766#undef FUNC_NAME
0f2d19dd
JB
1767
1768
3b3b36dd 1769SCM_DEFINE (scm_bit_position, "bit-position", 3, 0, 0,
1bbd0b84 1770 (SCM item, SCM v, SCM k),
b380b885
MD
1771 "Returns the minimum index of an occurrence of @var{bool} in @var{bv}\n"
1772 "which is at least @var{k}. If no @var{bool} occurs within the specified\n"
1773 "range @code{#f} is returned.")
1bbd0b84 1774#define FUNC_NAME s_scm_bit_position
0f2d19dd 1775{
1bbd0b84 1776 long i, lenw, xbits, pos;
0f2d19dd 1777 register unsigned long w;
6b5a304f 1778 SCM_VALIDATE_NIM (2,v);
3b3b36dd 1779 SCM_VALIDATE_INUM_COPY (3,k,pos);
0f2d19dd 1780 SCM_ASSERT ((pos <= SCM_LENGTH (v)) && (pos >= 0),
1bbd0b84 1781 k, SCM_OUTOFRANGE, FUNC_NAME);
0f2d19dd
JB
1782 if (pos == SCM_LENGTH (v))
1783 return SCM_BOOL_F;
5c11cc9d 1784 switch SCM_TYP7 (v)
0f2d19dd
JB
1785 {
1786 default:
1bbd0b84 1787 SCM_WTA (2,v);
0f2d19dd
JB
1788 case scm_tc7_bvect:
1789 if (0 == SCM_LENGTH (v))
1790 return SCM_MAKINUM (-1L);
1791 lenw = (SCM_LENGTH (v) - 1) / SCM_LONG_BIT; /* watch for part words */
1792 i = pos / SCM_LONG_BIT;
f1267706 1793 w = SCM_UNPACK (SCM_VELTS (v)[i]);
0f2d19dd
JB
1794 if (SCM_FALSEP (item))
1795 w = ~w;
1796 xbits = (pos % SCM_LONG_BIT);
1797 pos -= xbits;
1798 w = ((w >> xbits) << xbits);
1799 xbits = SCM_LONG_BIT - 1 - (SCM_LENGTH (v) - 1) % SCM_LONG_BIT;
1800 while (!0)
1801 {
1802 if (w && (i == lenw))
1803 w = ((w << xbits) >> xbits);
1804 if (w)
1805 while (w)
1806 switch (w & 0x0f)
1807 {
1808 default:
1809 return SCM_MAKINUM (pos);
1810 case 2:
1811 case 6:
1812 case 10:
1813 case 14:
1814 return SCM_MAKINUM (pos + 1);
1815 case 4:
1816 case 12:
1817 return SCM_MAKINUM (pos + 2);
1818 case 8:
1819 return SCM_MAKINUM (pos + 3);
1820 case 0:
1821 pos += 4;
1822 w >>= 4;
1823 }
1824 if (++i > lenw)
1825 break;
1826 pos += SCM_LONG_BIT;
f1267706 1827 w = SCM_UNPACK (SCM_VELTS (v)[i]);
0f2d19dd
JB
1828 if (SCM_FALSEP (item))
1829 w = ~w;
1830 }
1831 return SCM_BOOL_F;
1832 }
1833}
1bbd0b84 1834#undef FUNC_NAME
0f2d19dd
JB
1835
1836
3b3b36dd 1837SCM_DEFINE (scm_bit_set_star_x, "bit-set*!", 3, 0, 0,
1bbd0b84 1838 (SCM v, SCM kv, SCM obj),
b380b885
MD
1839 "If uve is a bit-vector @var{bv} and uve must be of the same length. If\n"
1840 "@var{bool} is @code{#t}, uve is OR'ed into @var{bv}; If @var{bool} is @code{#f}, the\n"
1841 "inversion of uve is AND'ed into @var{bv}.\n\n"
1842 "If uve is a unsigned integer vector all the elements of uve must be\n"
1843 "between 0 and the @code{LENGTH} of @var{bv}. The bits of @var{bv}\n"
1844 "corresponding to the indexes in uve are set to @var{bool}.\n\n"
1845 "The return value is unspecified.")
1bbd0b84 1846#define FUNC_NAME s_scm_bit_set_star_x
0f2d19dd
JB
1847{
1848 register long i, k, vlen;
1849 SCM_ASRTGO (SCM_NIMP (v), badarg1);
1850 SCM_ASRTGO (SCM_NIMP (kv), badarg2);
5c11cc9d 1851 switch SCM_TYP7 (kv)
0f2d19dd
JB
1852 {
1853 default:
1bbd0b84 1854 badarg2:SCM_WTA (2,kv);
0f2d19dd 1855 case scm_tc7_uvect:
5c11cc9d 1856 switch SCM_TYP7 (v)
0f2d19dd
JB
1857 {
1858 default:
c209c88e 1859 badarg1: SCM_WTA (1,v);
0f2d19dd
JB
1860 case scm_tc7_bvect:
1861 vlen = SCM_LENGTH (v);
4260a7fc 1862 if (SCM_FALSEP (obj))
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_CLR(v,k);
0f2d19dd 1868 }
4260a7fc 1869 else if (SCM_TRUE_P (obj))
0f2d19dd
JB
1870 for (i = SCM_LENGTH (kv); i;)
1871 {
f1267706 1872 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
1bbd0b84 1873 SCM_ASSERT ((k < vlen), SCM_MAKINUM (k), SCM_OUTOFRANGE, FUNC_NAME);
c209c88e 1874 SCM_BITVEC_SET(v,k);
0f2d19dd
JB
1875 }
1876 else
1bbd0b84 1877 badarg3:SCM_WTA (3,obj);
0f2d19dd
JB
1878 }
1879 break;
1880 case scm_tc7_bvect:
1881 SCM_ASRTGO (SCM_TYP7 (v) == scm_tc7_bvect && SCM_LENGTH (v) == SCM_LENGTH (kv), badarg1);
4260a7fc 1882 if (SCM_FALSEP (obj))
0f2d19dd 1883 for (k = (SCM_LENGTH (v) + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
f1267706 1884 SCM_UNPACK (SCM_VELTS (v)[k]) &= ~ SCM_UNPACK(SCM_VELTS (kv)[k]);
4260a7fc 1885 else if (SCM_TRUE_P (obj))
0f2d19dd 1886 for (k = (SCM_LENGTH (v) + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
f1267706 1887 SCM_UNPACK (SCM_VELTS (v)[k]) |= SCM_UNPACK (SCM_VELTS (kv)[k]);
0f2d19dd
JB
1888 else
1889 goto badarg3;
1890 break;
1891 }
1892 return SCM_UNSPECIFIED;
1893}
1bbd0b84 1894#undef FUNC_NAME
0f2d19dd
JB
1895
1896
3b3b36dd 1897SCM_DEFINE (scm_bit_count_star, "bit-count*", 3, 0, 0,
1bbd0b84 1898 (SCM v, SCM kv, SCM obj),
b380b885
MD
1899 "Returns\n"
1900 "@example\n"
1901 "(bit-count (bit-set*! (if bool bv (bit-invert! bv)) uve #t) #t).\n"
1902 "@end example\n"
1903 "@var{bv} is not modified.")
1bbd0b84 1904#define FUNC_NAME s_scm_bit_count_star
0f2d19dd
JB
1905{
1906 register long i, vlen, count = 0;
1907 register unsigned long k;
41b0806d 1908 int fObj = 0;
c209c88e 1909
0f2d19dd
JB
1910 SCM_ASRTGO (SCM_NIMP (v), badarg1);
1911 SCM_ASRTGO (SCM_NIMP (kv), badarg2);
5c11cc9d 1912 switch SCM_TYP7 (kv)
0f2d19dd
JB
1913 {
1914 default:
c209c88e
GB
1915 badarg2:
1916 SCM_WTA (2,kv);
0f2d19dd
JB
1917 case scm_tc7_uvect:
1918 switch SCM_TYP7
1919 (v)
1920 {
1921 default:
c209c88e
GB
1922 badarg1:
1923 SCM_WTA (1,v);
0f2d19dd
JB
1924 case scm_tc7_bvect:
1925 vlen = SCM_LENGTH (v);
4260a7fc 1926 if (SCM_FALSEP (obj))
0f2d19dd
JB
1927 for (i = SCM_LENGTH (kv); i;)
1928 {
f1267706 1929 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
1bbd0b84 1930 SCM_ASSERT ((k < vlen), SCM_MAKINUM (k), SCM_OUTOFRANGE, FUNC_NAME);
c209c88e 1931 if (!SCM_BITVEC_REF(v,k))
0f2d19dd
JB
1932 count++;
1933 }
4260a7fc 1934 else if (SCM_TRUE_P (obj))
0f2d19dd
JB
1935 for (i = SCM_LENGTH (kv); i;)
1936 {
f1267706 1937 k = SCM_UNPACK (SCM_VELTS (kv)[--i]);
1bbd0b84 1938 SCM_ASSERT ((k < vlen), SCM_MAKINUM (k), SCM_OUTOFRANGE, FUNC_NAME);
c209c88e 1939 if (SCM_BITVEC_REF (v,k))
0f2d19dd
JB
1940 count++;
1941 }
1942 else
1bbd0b84 1943 badarg3:SCM_WTA (3,obj);
0f2d19dd
JB
1944 }
1945 break;
1946 case scm_tc7_bvect:
1947 SCM_ASRTGO (SCM_TYP7 (v) == scm_tc7_bvect && SCM_LENGTH (v) == SCM_LENGTH (kv), badarg1);
1948 if (0 == SCM_LENGTH (v))
1949 return SCM_INUM0;
4260a7fc
DH
1950 SCM_ASRTGO (SCM_BOOLP (obj), badarg3);
1951 fObj = SCM_TRUE_P (obj);
0f2d19dd 1952 i = (SCM_LENGTH (v) - 1) / SCM_LONG_BIT;
f1267706 1953 k = SCM_UNPACK (SCM_VELTS (kv)[i]) & (fObj ? SCM_UNPACK (SCM_VELTS (v)[i]) : ~ SCM_UNPACK (SCM_VELTS (v)[i]));
0f2d19dd 1954 k <<= SCM_LONG_BIT - 1 - ((SCM_LENGTH (v) - 1) % SCM_LONG_BIT);
c209c88e 1955 while (1)
0f2d19dd
JB
1956 {
1957 for (; k; k >>= 4)
1958 count += cnt_tab[k & 0x0f];
1959 if (0 == i--)
1960 return SCM_MAKINUM (count);
c209c88e
GB
1961
1962 /* urg. repetitive (see above.) */
f1267706 1963 k = SCM_UNPACK (SCM_VELTS (kv)[i]) & (fObj ? SCM_UNPACK(SCM_VELTS (v)[i]) : ~SCM_UNPACK (SCM_VELTS (v)[i]));
0f2d19dd
JB
1964 }
1965 }
1966 return SCM_MAKINUM (count);
1967}
1bbd0b84 1968#undef FUNC_NAME
0f2d19dd
JB
1969
1970
3b3b36dd 1971SCM_DEFINE (scm_bit_invert_x, "bit-invert!", 1, 0, 0,
1bbd0b84 1972 (SCM v),
b380b885 1973 "Modifies @var{bv} by replacing each element with its negation.")
1bbd0b84 1974#define FUNC_NAME s_scm_bit_invert_x
0f2d19dd
JB
1975{
1976 register long k;
1977 SCM_ASRTGO (SCM_NIMP (v), badarg1);
1978 k = SCM_LENGTH (v);
1979 switch SCM_TYP7
1980 (v)
1981 {
1982 case scm_tc7_bvect:
1983 for (k = (k + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k--;)
f1267706 1984 SCM_UNPACK (SCM_VELTS (v)[k]) = ~SCM_UNPACK(SCM_VELTS (v)[k]);
0f2d19dd
JB
1985 break;
1986 default:
1bbd0b84 1987 badarg1:SCM_WTA (1,v);
0f2d19dd
JB
1988 }
1989 return SCM_UNSPECIFIED;
1990}
1bbd0b84 1991#undef FUNC_NAME
0f2d19dd
JB
1992
1993
0f2d19dd 1994SCM
1bbd0b84 1995scm_istr2bve (char *str, long len)
0f2d19dd
JB
1996{
1997 SCM v = scm_make_uve (len, SCM_BOOL_T);
1998 long *data = (long *) SCM_VELTS (v);
1999 register unsigned long mask;
2000 register long k;
2001 register long j;
2002 for (k = 0; k < (len + SCM_LONG_BIT - 1) / SCM_LONG_BIT; k++)
2003 {
2004 data[k] = 0L;
2005 j = len - k * SCM_LONG_BIT;
2006 if (j > SCM_LONG_BIT)
2007 j = SCM_LONG_BIT;
2008 for (mask = 1L; j--; mask <<= 1)
2009 switch (*str++)
2010 {
2011 case '0':
2012 break;
2013 case '1':
2014 data[k] |= mask;
2015 break;
2016 default:
2017 return SCM_BOOL_F;
2018 }
2019 }
2020 return v;
2021}
2022
2023
1cc91f1b 2024
0f2d19dd 2025static SCM
1bbd0b84 2026ra2l (SCM ra,scm_sizet base,scm_sizet k)
0f2d19dd
JB
2027{
2028 register SCM res = SCM_EOL;
2029 register long inc = SCM_ARRAY_DIMS (ra)[k].inc;
2030 register scm_sizet i;
2031 if (SCM_ARRAY_DIMS (ra)[k].ubnd < SCM_ARRAY_DIMS (ra)[k].lbnd)
2032 return SCM_EOL;
2033 i = base + (1 + SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd) * inc;
2034 if (k < SCM_ARRAY_NDIM (ra) - 1)
2035 {
2036 do
2037 {
2038 i -= inc;
2039 res = scm_cons (ra2l (ra, i, k + 1), res);
2040 }
2041 while (i != base);
2042 }
2043 else
2044 do
2045 {
2046 i -= inc;
2047 res = scm_cons (scm_uniform_vector_ref (SCM_ARRAY_V (ra), SCM_MAKINUM (i)), res);
2048 }
2049 while (i != base);
2050 return res;
2051}
2052
2053
3b3b36dd 2054SCM_DEFINE (scm_array_to_list, "array->list", 1, 0, 0,
1bbd0b84 2055 (SCM v),
b380b885 2056 "Returns a list consisting of all the elements, in order, of @var{array}.")
1bbd0b84 2057#define FUNC_NAME s_scm_array_to_list
0f2d19dd
JB
2058{
2059 SCM res = SCM_EOL;
2060 register long k;
2061 SCM_ASRTGO (SCM_NIMP (v), badarg1);
2062 switch SCM_TYP7
2063 (v)
2064 {
2065 default:
1bbd0b84 2066 badarg1:SCM_WTA (1,v);
0f2d19dd
JB
2067 case scm_tc7_smob:
2068 SCM_ASRTGO (SCM_ARRAYP (v), badarg1);
2069 return ra2l (v, SCM_ARRAY_BASE (v), 0);
2070 case scm_tc7_vector:
95f5b0f5 2071 case scm_tc7_wvect:
0f2d19dd
JB
2072 return scm_vector_to_list (v);
2073 case scm_tc7_string:
2074 return scm_string_to_list (v);
2075 case scm_tc7_bvect:
2076 {
2077 long *data = (long *) SCM_VELTS (v);
2078 register unsigned long mask;
2079 for (k = (SCM_LENGTH (v) - 1) / SCM_LONG_BIT; k > 0; k--)
cdbadcac 2080 for (mask = 1UL << (SCM_LONG_BIT - 1); mask; mask >>= 1)
156dcb09 2081 res = scm_cons (SCM_BOOL(((long *) data)[k] & mask), res);
0f2d19dd 2082 for (mask = 1L << ((SCM_LENGTH (v) % SCM_LONG_BIT) - 1); mask; mask >>= 1)
156dcb09 2083 res = scm_cons (SCM_BOOL(((long *) data)[k] & mask), res);
0f2d19dd
JB
2084 return res;
2085 }
0f2d19dd
JB
2086 case scm_tc7_uvect: {
2087 long *data = (long *)SCM_VELTS(v);
2088 for (k = SCM_LENGTH(v) - 1; k >= 0; k--)
2089 res = scm_cons(scm_ulong2num(data[k]), res);
2090 return res;
2091 }
2092 case scm_tc7_ivect: {
2093 long *data = (long *)SCM_VELTS(v);
2094 for (k = SCM_LENGTH(v) - 1; k >= 0; k--)
2095 res = scm_cons(scm_long2num(data[k]), res);
2096 return res;
2097 }
0f2d19dd
JB
2098 case scm_tc7_svect: {
2099 short *data;
2100 data = (short *)SCM_VELTS(v);
2101 for (k = SCM_LENGTH(v) - 1; k >= 0; k--)
2102 res = scm_cons(SCM_MAKINUM (data[k]), res);
2103 return res;
2104 }
5c11cc9d 2105#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
2106 case scm_tc7_llvect: {
2107 long_long *data;
2108 data = (long_long *)SCM_VELTS(v);
2109 for (k = SCM_LENGTH(v) - 1; k >= 0; k--)
2110 res = scm_cons(scm_long_long2num(data[k]), res);
2111 return res;
2112 }
2113#endif
2114
2115
0f2d19dd
JB
2116 case scm_tc7_fvect:
2117 {
2118 float *data = (float *) SCM_VELTS (v);
2119 for (k = SCM_LENGTH (v) - 1; k >= 0; k--)
bc86da5d 2120 res = scm_cons (scm_make_real (data[k]), res);
0f2d19dd
JB
2121 return res;
2122 }
0f2d19dd
JB
2123 case scm_tc7_dvect:
2124 {
2125 double *data = (double *) SCM_VELTS (v);
2126 for (k = SCM_LENGTH (v) - 1; k >= 0; k--)
f8de44c1 2127 res = scm_cons (scm_make_real (data[k]), res);
0f2d19dd
JB
2128 return res;
2129 }
2130 case scm_tc7_cvect:
2131 {
2132 double (*data)[2] = (double (*)[2]) SCM_VELTS (v);
2133 for (k = SCM_LENGTH (v) - 1; k >= 0; k--)
f8de44c1 2134 res = scm_cons (scm_make_complex (data[k][0], data[k][1]), res);
0f2d19dd
JB
2135 return res;
2136 }
0f2d19dd
JB
2137 }
2138}
1bbd0b84 2139#undef FUNC_NAME
0f2d19dd
JB
2140
2141
20a54673 2142static char s_bad_ralst[] = "Bad scm_array contents list";
1cc91f1b 2143
1bbd0b84 2144static int l2ra(SCM lst, SCM ra, scm_sizet base, scm_sizet k);
1cc91f1b 2145
3b3b36dd 2146SCM_DEFINE (scm_list_to_uniform_array, "list->uniform-array", 3, 0, 0,
1bbd0b84 2147 (SCM ndim, SCM prot, SCM lst),
b380b885
MD
2148 "@deffnx procedure list->uniform-vector prot lst\n"
2149 "Returns a uniform array of the type indicated by prototype @var{prot}\n"
2150 "with elements the same as those of @var{lst}. Elements must be of the\n"
2151 "appropriate type, no coercions are done.")
1bbd0b84 2152#define FUNC_NAME s_scm_list_to_uniform_array
0f2d19dd
JB
2153{
2154 SCM shp = SCM_EOL;
2155 SCM row = lst;
2156 SCM ra;
2157 scm_sizet k;
2158 long n;
3b3b36dd 2159 SCM_VALIDATE_INUM_COPY (1,ndim,k);
0f2d19dd
JB
2160 while (k--)
2161 {
2162 n = scm_ilength (row);
1bbd0b84 2163 SCM_ASSERT (n >= 0, lst, SCM_ARG3, FUNC_NAME);
0f2d19dd
JB
2164 shp = scm_cons (SCM_MAKINUM (n), shp);
2165 if (SCM_NIMP (row))
2166 row = SCM_CAR (row);
2167 }
d12feca3
GH
2168 ra = scm_dimensions_to_uniform_array (scm_reverse (shp), prot,
2169 SCM_UNDEFINED);
0f2d19dd
JB
2170 if (SCM_NULLP (shp))
2171
2172 {
2173 SCM_ASRTGO (1 == scm_ilength (lst), badlst);
2174 scm_array_set_x (ra, SCM_CAR (lst), SCM_EOL);
2175 return ra;
2176 }
2177 if (!SCM_ARRAYP (ra))
2178 {
2179 for (k = 0; k < SCM_LENGTH (ra); k++, lst = SCM_CDR (lst))
2180 scm_array_set_x (ra, SCM_CAR (lst), SCM_MAKINUM (k));
2181 return ra;
2182 }
2183 if (l2ra (lst, ra, SCM_ARRAY_BASE (ra), 0))
2184 return ra;
2185 else
1bbd0b84 2186 badlst:scm_wta (lst, s_bad_ralst, FUNC_NAME);
0f2d19dd
JB
2187 return SCM_BOOL_F;
2188}
1bbd0b84 2189#undef FUNC_NAME
0f2d19dd 2190
0f2d19dd 2191static int
1bbd0b84 2192l2ra (SCM lst, SCM ra, scm_sizet base, scm_sizet k)
0f2d19dd
JB
2193{
2194 register long inc = SCM_ARRAY_DIMS (ra)[k].inc;
2195 register long n = (1 + SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd);
2196 int ok = 1;
2197 if (n <= 0)
4260a7fc 2198 return (SCM_NULLP (lst));
0f2d19dd
JB
2199 if (k < SCM_ARRAY_NDIM (ra) - 1)
2200 {
2201 while (n--)
2202 {
2203 if (SCM_IMP (lst) || SCM_NCONSP (lst))
2204 return 0;
2205 ok = ok && l2ra (SCM_CAR (lst), ra, base, k + 1);
2206 base += inc;
2207 lst = SCM_CDR (lst);
2208 }
2209 if (SCM_NNULLP (lst))
2210 return 0;
2211 }
2212 else
2213 {
2214 while (n--)
2215 {
2216 if (SCM_IMP (lst) || SCM_NCONSP (lst))
2217 return 0;
baa702c8 2218 scm_array_set_x (SCM_ARRAY_V (ra), SCM_CAR (lst), SCM_MAKINUM (base));
0f2d19dd
JB
2219 base += inc;
2220 lst = SCM_CDR (lst);
2221 }
2222 if (SCM_NNULLP (lst))
fee7ef83 2223 return 0;
0f2d19dd
JB
2224 }
2225 return ok;
2226}
2227
1cc91f1b 2228
0f2d19dd 2229static void
1bbd0b84 2230rapr1 (SCM ra,scm_sizet j,scm_sizet k,SCM port,scm_print_state *pstate)
0f2d19dd
JB
2231{
2232 long inc = 1;
2233 long n = SCM_LENGTH (ra);
2234 int enclosed = 0;
2235tail:
5c11cc9d 2236 switch SCM_TYP7 (ra)
0f2d19dd
JB
2237 {
2238 case scm_tc7_smob:
2239 if (enclosed++)
2240 {
2241 SCM_ARRAY_BASE (ra) = j;
2242 if (n-- > 0)
9882ea19 2243 scm_iprin1 (ra, port, pstate);
0f2d19dd
JB
2244 for (j += inc; n-- > 0; j += inc)
2245 {
b7f3516f 2246 scm_putc (' ', port);
0f2d19dd 2247 SCM_ARRAY_BASE (ra) = j;
9882ea19 2248 scm_iprin1 (ra, port, pstate);
0f2d19dd
JB
2249 }
2250 break;
2251 }
2252 if (k + 1 < SCM_ARRAY_NDIM (ra))
2253 {
2254 long i;
2255 inc = SCM_ARRAY_DIMS (ra)[k].inc;
2256 for (i = SCM_ARRAY_DIMS (ra)[k].lbnd; i < SCM_ARRAY_DIMS (ra)[k].ubnd; i++)
2257 {
b7f3516f 2258 scm_putc ('(', port);
9882ea19 2259 rapr1 (ra, j, k + 1, port, pstate);
b7f3516f 2260 scm_puts (") ", port);
0f2d19dd
JB
2261 j += inc;
2262 }
2263 if (i == SCM_ARRAY_DIMS (ra)[k].ubnd)
2264 { /* could be zero size. */
b7f3516f 2265 scm_putc ('(', port);
9882ea19 2266 rapr1 (ra, j, k + 1, port, pstate);
b7f3516f 2267 scm_putc (')', port);
0f2d19dd
JB
2268 }
2269 break;
2270 }
2271 if SCM_ARRAY_NDIM
2272 (ra)
2273 { /* Could be zero-dimensional */
2274 inc = SCM_ARRAY_DIMS (ra)[k].inc;
2275 n = (SCM_ARRAY_DIMS (ra)[k].ubnd - SCM_ARRAY_DIMS (ra)[k].lbnd + 1);
2276 }
2277 else
2278 n = 1;
2279 ra = SCM_ARRAY_V (ra);
2280 goto tail;
2281 default:
5c11cc9d 2282 /* scm_tc7_bvect and scm_tc7_llvect only? */
0f2d19dd 2283 if (n-- > 0)
9882ea19 2284 scm_iprin1 (scm_uniform_vector_ref (ra, SCM_MAKINUM (j)), port, pstate);
0f2d19dd
JB
2285 for (j += inc; n-- > 0; j += inc)
2286 {
b7f3516f 2287 scm_putc (' ', port);
9882ea19 2288 scm_iprin1 (scm_cvref (ra, j, SCM_UNDEFINED), port, pstate);
0f2d19dd
JB
2289 }
2290 break;
2291 case scm_tc7_string:
2292 if (n-- > 0)
7866a09b 2293 scm_iprin1 (SCM_MAKE_CHAR (SCM_UCHARS (ra)[j]), port, pstate);
9882ea19 2294 if (SCM_WRITINGP (pstate))
0f2d19dd
JB
2295 for (j += inc; n-- > 0; j += inc)
2296 {
b7f3516f 2297 scm_putc (' ', port);
7866a09b 2298 scm_iprin1 (SCM_MAKE_CHAR (SCM_UCHARS (ra)[j]), port, pstate);
0f2d19dd
JB
2299 }
2300 else
2301 for (j += inc; n-- > 0; j += inc)
b7f3516f 2302 scm_putc (SCM_CHARS (ra)[j], port);
0f2d19dd
JB
2303 break;
2304 case scm_tc7_byvect:
2305 if (n-- > 0)
4260a7fc 2306 scm_intprint (((char *) SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2307 for (j += inc; n-- > 0; j += inc)
2308 {
b7f3516f 2309 scm_putc (' ', port);
4260a7fc 2310 scm_intprint (((char *)SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2311 }
2312 break;
2313
2314 case scm_tc7_uvect:
5c11cc9d
GH
2315 {
2316 char str[11];
2317
2318 if (n-- > 0)
2319 {
2320 /* intprint can't handle >= 2^31. */
fee7ef83 2321 sprintf (str, "%lu", ((unsigned long *) SCM_VELTS (ra))[j]);
5c11cc9d
GH
2322 scm_puts (str, port);
2323 }
2324 for (j += inc; n-- > 0; j += inc)
2325 {
2326 scm_putc (' ', port);
fee7ef83 2327 sprintf (str, "%lu", ((unsigned long *) SCM_VELTS (ra))[j]);
5c11cc9d
GH
2328 scm_puts (str, port);
2329 }
2330 }
0f2d19dd
JB
2331 case scm_tc7_ivect:
2332 if (n-- > 0)
fee7ef83 2333 scm_intprint (((signed long *) SCM_VELTS (ra))[j], 10, port);
0f2d19dd
JB
2334 for (j += inc; n-- > 0; j += inc)
2335 {
b7f3516f 2336 scm_putc (' ', port);
fee7ef83 2337 scm_intprint (((signed long *) SCM_VELTS (ra))[j], 10, port);
0f2d19dd
JB
2338 }
2339 break;
2340
2341 case scm_tc7_svect:
2342 if (n-- > 0)
4260a7fc 2343 scm_intprint (((short *) SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2344 for (j += inc; n-- > 0; j += inc)
2345 {
b7f3516f 2346 scm_putc (' ', port);
4260a7fc 2347 scm_intprint (((short *) SCM_CELL_WORD_1 (ra))[j], 10, port);
0f2d19dd
JB
2348 }
2349 break;
2350
0f2d19dd
JB
2351 case scm_tc7_fvect:
2352 if (n-- > 0)
2353 {
bc86da5d
MD
2354 SCM z = scm_make_real (1.0);
2355 SCM_REAL_VALUE (z) = ((float *) SCM_VELTS (ra))[j];
2356 scm_print_real (z, port, pstate);
0f2d19dd
JB
2357 for (j += inc; n-- > 0; j += inc)
2358 {
b7f3516f 2359 scm_putc (' ', port);
bc86da5d
MD
2360 SCM_REAL_VALUE (z) = ((float *) SCM_VELTS (ra))[j];
2361 scm_print_real (z, port, pstate);
0f2d19dd
JB
2362 }
2363 }
2364 break;
0f2d19dd
JB
2365 case scm_tc7_dvect:
2366 if (n-- > 0)
2367 {
bc86da5d
MD
2368 SCM z = scm_make_real (1.0 / 3.0);
2369 SCM_REAL_VALUE (z) = ((double *) SCM_VELTS (ra))[j];
2370 scm_print_real (z, port, pstate);
0f2d19dd
JB
2371 for (j += inc; n-- > 0; j += inc)
2372 {
b7f3516f 2373 scm_putc (' ', port);
bc86da5d
MD
2374 SCM_REAL_VALUE (z) = ((double *) SCM_VELTS (ra))[j];
2375 scm_print_real (z, port, pstate);
0f2d19dd
JB
2376 }
2377 }
2378 break;
2379 case scm_tc7_cvect:
2380 if (n-- > 0)
2381 {
bc86da5d
MD
2382 SCM cz = scm_make_complex (0.0, 1.0), z = scm_make_real (1.0 / 3.0);
2383 SCM_REAL_VALUE (z) =
2384 SCM_COMPLEX_REAL (cz) = ((double *) SCM_VELTS (ra))[2 * j];
2385 SCM_COMPLEX_IMAG (cz) = ((double *) SCM_VELTS (ra))[2 * j + 1];
2386 scm_print_complex ((0.0 == SCM_COMPLEX_IMAG (cz) ? z : cz),
2387 port, pstate);
0f2d19dd
JB
2388 for (j += inc; n-- > 0; j += inc)
2389 {
b7f3516f 2390 scm_putc (' ', port);
bc86da5d
MD
2391 SCM_REAL_VALUE (z)
2392 = SCM_COMPLEX_REAL (cz) = ((double *) SCM_VELTS (ra))[2 * j];
2393 SCM_COMPLEX_IMAG (cz) = ((double *) SCM_VELTS (ra))[2 * j + 1];
2394 scm_print_complex ((0.0 == SCM_COMPLEX_IMAG (cz) ? z : cz),
2395 port, pstate);
0f2d19dd
JB
2396 }
2397 }
2398 break;
0f2d19dd
JB
2399 }
2400}
2401
2402
1cc91f1b 2403
0f2d19dd 2404int
1bbd0b84 2405scm_raprin1 (SCM exp, SCM port, scm_print_state *pstate)
0f2d19dd
JB
2406{
2407 SCM v = exp;
2408 scm_sizet base = 0;
b7f3516f 2409 scm_putc ('#', port);
0f2d19dd 2410tail:
5c11cc9d 2411 switch SCM_TYP7 (v)
0f2d19dd
JB
2412 {
2413 case scm_tc7_smob:
2414 {
2415 long ndim = SCM_ARRAY_NDIM (v);
2416 base = SCM_ARRAY_BASE (v);
2417 v = SCM_ARRAY_V (v);
2418 if (SCM_ARRAYP (v))
2419
2420 {
b7f3516f 2421 scm_puts ("<enclosed-array ", port);
9882ea19 2422 rapr1 (exp, base, 0, port, pstate);
b7f3516f 2423 scm_putc ('>', port);
0f2d19dd
JB
2424 return 1;
2425 }
2426 else
2427 {
2428 scm_intprint (ndim, 10, port);
2429 goto tail;
2430 }
2431 }
2432 case scm_tc7_bvect:
fee7ef83 2433 if (SCM_EQ_P (exp, v))
0f2d19dd
JB
2434 { /* a uve, not an scm_array */
2435 register long i, j, w;
b7f3516f 2436 scm_putc ('*', port);
0f2d19dd
JB
2437 for (i = 0; i < (SCM_LENGTH (exp)) / SCM_LONG_BIT; i++)
2438 {
f1267706 2439 scm_bits_t w = SCM_UNPACK (SCM_VELTS (exp)[i]);
0f2d19dd
JB
2440 for (j = SCM_LONG_BIT; j; j--)
2441 {
b7f3516f 2442 scm_putc (w & 1 ? '1' : '0', port);
0f2d19dd
JB
2443 w >>= 1;
2444 }
2445 }
2446 j = SCM_LENGTH (exp) % SCM_LONG_BIT;
2447 if (j)
2448 {
f1267706 2449 w = SCM_UNPACK (SCM_VELTS (exp)[SCM_LENGTH (exp) / SCM_LONG_BIT]);
0f2d19dd
JB
2450 for (; j; j--)
2451 {
b7f3516f 2452 scm_putc (w & 1 ? '1' : '0', port);
0f2d19dd
JB
2453 w >>= 1;
2454 }
2455 }
2456 return 1;
2457 }
2458 else
b7f3516f 2459 scm_putc ('b', port);
0f2d19dd
JB
2460 break;
2461 case scm_tc7_string:
b7f3516f 2462 scm_putc ('a', port);
0f2d19dd
JB
2463 break;
2464 case scm_tc7_byvect:
05c33d09 2465 scm_putc ('y', port);
0f2d19dd
JB
2466 break;
2467 case scm_tc7_uvect:
b7f3516f 2468 scm_putc ('u', port);
0f2d19dd
JB
2469 break;
2470 case scm_tc7_ivect:
b7f3516f 2471 scm_putc ('e', port);
0f2d19dd
JB
2472 break;
2473 case scm_tc7_svect:
05c33d09 2474 scm_putc ('h', port);
0f2d19dd 2475 break;
5c11cc9d 2476#ifdef HAVE_LONG_LONGS
0f2d19dd 2477 case scm_tc7_llvect:
5c11cc9d 2478 scm_putc ('l', port);
0f2d19dd
JB
2479 break;
2480#endif
0f2d19dd 2481 case scm_tc7_fvect:
b7f3516f 2482 scm_putc ('s', port);
0f2d19dd 2483 break;
0f2d19dd 2484 case scm_tc7_dvect:
b7f3516f 2485 scm_putc ('i', port);
0f2d19dd
JB
2486 break;
2487 case scm_tc7_cvect:
b7f3516f 2488 scm_putc ('c', port);
0f2d19dd 2489 break;
0f2d19dd 2490 }
b7f3516f 2491 scm_putc ('(', port);
9882ea19 2492 rapr1 (exp, base, 0, port, pstate);
b7f3516f 2493 scm_putc (')', port);
0f2d19dd
JB
2494 return 1;
2495}
2496
3b3b36dd 2497SCM_DEFINE (scm_array_prototype, "array-prototype", 1, 0, 0,
1bbd0b84 2498 (SCM ra),
b380b885
MD
2499 "Returns an object that would produce an array of the same type as\n"
2500 "@var{array}, if used as the @var{prototype} for\n"
2501 "@code{make-uniform-array}.")
1bbd0b84 2502#define FUNC_NAME s_scm_array_prototype
0f2d19dd
JB
2503{
2504 int enclosed = 0;
2505 SCM_ASRTGO (SCM_NIMP (ra), badarg);
2506loop:
2507 switch SCM_TYP7
2508 (ra)
2509 {
2510 default:
1bbd0b84 2511 badarg:SCM_WTA (1,ra);
0f2d19dd
JB
2512 case scm_tc7_smob:
2513 SCM_ASRTGO (SCM_ARRAYP (ra), badarg);
2514 if (enclosed++)
2515 return SCM_UNSPECIFIED;
2516 ra = SCM_ARRAY_V (ra);
2517 goto loop;
2518 case scm_tc7_vector:
95f5b0f5 2519 case scm_tc7_wvect:
0f2d19dd
JB
2520 return SCM_EOL;
2521 case scm_tc7_bvect:
2522 return SCM_BOOL_T;
2523 case scm_tc7_string:
7866a09b 2524 return SCM_MAKE_CHAR ('a');
0f2d19dd 2525 case scm_tc7_byvect:
7866a09b 2526 return SCM_MAKE_CHAR ('\0');
0f2d19dd
JB
2527 case scm_tc7_uvect:
2528 return SCM_MAKINUM (1L);
2529 case scm_tc7_ivect:
2530 return SCM_MAKINUM (-1L);
2531 case scm_tc7_svect:
2532 return SCM_CDR (scm_intern ("s", 1));
5c11cc9d 2533#ifdef HAVE_LONG_LONGS
0f2d19dd
JB
2534 case scm_tc7_llvect:
2535 return SCM_CDR (scm_intern ("l", 1));
2536#endif
0f2d19dd 2537 case scm_tc7_fvect:
bc86da5d 2538 return scm_make_real (1.0);
0f2d19dd 2539 case scm_tc7_dvect:
bc86da5d 2540 return scm_make_real (1.0 / 3.0);
0f2d19dd 2541 case scm_tc7_cvect:
bc86da5d 2542 return scm_make_complex (0.0, 1.0);
0f2d19dd
JB
2543 }
2544}
1bbd0b84 2545#undef FUNC_NAME
0f2d19dd 2546
1cc91f1b 2547
0f2d19dd 2548static SCM
1bbd0b84 2549markra (SCM ptr)
0f2d19dd 2550{
0f2d19dd
JB
2551 return SCM_ARRAY_V (ptr);
2552}
2553
1cc91f1b 2554
0f2d19dd 2555static scm_sizet
1bbd0b84 2556freera (SCM ptr)
0f2d19dd
JB
2557{
2558 scm_must_free (SCM_CHARS (ptr));
2559 return sizeof (scm_array) + SCM_ARRAY_NDIM (ptr) * sizeof (scm_array_dim);
2560}
2561
0f2d19dd
JB
2562void
2563scm_init_unif ()
0f2d19dd 2564{
23a62151
MD
2565 scm_tc16_array = scm_make_smob_type_mfpe ("array", 0,
2566 markra,
2567 freera,
2568 scm_raprin1,
2569 scm_array_equal_p);
0f2d19dd 2570 scm_add_feature ("array");
a0599745 2571#include "libguile/unif.x"
0f2d19dd 2572}
89e00824
ML
2573
2574/*
2575 Local Variables:
2576 c-file-style: "gnu"
2577 End:
2578*/