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