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