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