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