1 /* srfi-4.c --- Uniform numeric vector datatypes.
3 * Copyright (C) 2001, 2004, 2006, 2009 Free Software Foundation, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public License
7 * as published by the Free Software Foundation; either version 3 of
8 * the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
29 #include "libguile/_scm.h"
30 #include "libguile/__scm.h"
31 #include "libguile/bdw-gc.h"
32 #include "libguile/srfi-4.h"
33 #include "libguile/bitvectors.h"
34 #include "libguile/bytevectors.h"
35 #include "libguile/generalized-vectors.h"
36 #include "libguile/uniform.h"
37 #include "libguile/error.h"
38 #include "libguile/eval.h"
39 #include "libguile/read.h"
40 #include "libguile/ports.h"
41 #include "libguile/chars.h"
42 #include "libguile/vectors.h"
43 #include "libguile/arrays.h"
44 #include "libguile/strings.h"
45 #include "libguile/strports.h"
46 #include "libguile/dynwind.h"
47 #include "libguile/deprecation.h"
57 /* Smob type code for uniform numeric vectors. */
58 int scm_tc16_uvec
= 0;
60 #define SCM_IS_UVEC(obj) SCM_SMOB_PREDICATE (scm_tc16_uvec, (obj))
62 /* Accessor macros for the three components of a uniform numeric
64 - The type tag (one of the symbolic constants below).
65 - The vector's length (counted in elements).
66 - The address of the data area (holding the elements of the
68 #define SCM_UVEC_TYPE(u) (SCM_CELL_WORD_1(u))
69 #define SCM_UVEC_LENGTH(u) ((size_t)SCM_CELL_WORD_2(u))
70 #define SCM_UVEC_BASE(u) ((void *)SCM_CELL_WORD_3(u))
73 /* Symbolic constants encoding the various types of uniform
77 #define SCM_UVEC_U16 2
78 #define SCM_UVEC_S16 3
79 #define SCM_UVEC_U32 4
80 #define SCM_UVEC_S32 5
81 #define SCM_UVEC_U64 6
82 #define SCM_UVEC_S64 7
83 #define SCM_UVEC_F32 8
84 #define SCM_UVEC_F64 9
85 #define SCM_UVEC_C32 10
86 #define SCM_UVEC_C64 11
89 /* This array maps type tags to the size of the elements. */
90 static const int uvec_sizes
[12] = {
97 sizeof (SCM
), sizeof (SCM
),
99 sizeof(float), sizeof(double),
100 2*sizeof(float), 2*sizeof(double)
103 static const char *uvec_tags
[12] = {
112 static const char *uvec_names
[12] = {
113 "u8vector", "s8vector",
114 "u16vector", "s16vector",
115 "u32vector", "s32vector",
116 "u64vector", "s64vector",
117 "f32vector", "f64vector",
118 "c32vector", "c64vector"
121 /* ================================================================ */
122 /* SMOB procedures. */
123 /* ================================================================ */
126 /* Smob print hook for uniform vectors. */
128 uvec_print (SCM uvec
, SCM port
, scm_print_state
*pstate
)
147 const size_t uvlen
= SCM_UVEC_LENGTH (uvec
);
148 void *uptr
= SCM_UVEC_BASE (uvec
);
150 switch (SCM_UVEC_TYPE (uvec
))
152 case SCM_UVEC_U8
: np
.u8
= (scm_t_uint8
*) uptr
; break;
153 case SCM_UVEC_S8
: np
.s8
= (scm_t_int8
*) uptr
; break;
154 case SCM_UVEC_U16
: np
.u16
= (scm_t_uint16
*) uptr
; break;
155 case SCM_UVEC_S16
: np
.s16
= (scm_t_int16
*) uptr
; break;
156 case SCM_UVEC_U32
: np
.u32
= (scm_t_uint32
*) uptr
; break;
157 case SCM_UVEC_S32
: np
.s32
= (scm_t_int32
*) uptr
; break;
159 case SCM_UVEC_U64
: np
.u64
= (scm_t_uint64
*) uptr
; break;
160 case SCM_UVEC_S64
: np
.s64
= (scm_t_int64
*) uptr
; break;
163 case SCM_UVEC_S64
: np
.fake_64
= (SCM
*) uptr
; break;
165 case SCM_UVEC_F32
: np
.f32
= (float *) uptr
; break;
166 case SCM_UVEC_F64
: np
.f64
= (double *) uptr
; break;
167 case SCM_UVEC_C32
: np
.f32
= (float *) uptr
; break;
168 case SCM_UVEC_C64
: np
.f64
= (double *) uptr
; break;
170 abort (); /* Sanity check. */
174 scm_putc ('#', port
);
175 scm_puts (uvec_tags
[SCM_UVEC_TYPE (uvec
)], port
);
176 scm_putc ('(', port
);
180 if (i
!= 0) scm_puts (" ", port
);
181 switch (SCM_UVEC_TYPE (uvec
))
183 case SCM_UVEC_U8
: scm_uintprint (*np
.u8
, 10, port
); np
.u8
++; break;
184 case SCM_UVEC_S8
: scm_intprint (*np
.s8
, 10, port
); np
.s8
++; break;
185 case SCM_UVEC_U16
: scm_uintprint (*np
.u16
, 10, port
); np
.u16
++; break;
186 case SCM_UVEC_S16
: scm_intprint (*np
.s16
, 10, port
); np
.s16
++; break;
187 case SCM_UVEC_U32
: scm_uintprint (*np
.u32
, 10, port
); np
.u32
++; break;
188 case SCM_UVEC_S32
: scm_intprint (*np
.s32
, 10, port
); np
.s32
++; break;
190 case SCM_UVEC_U64
: scm_uintprint (*np
.u64
, 10, port
); np
.u64
++; break;
191 case SCM_UVEC_S64
: scm_intprint (*np
.s64
, 10, port
); np
.s64
++; break;
194 case SCM_UVEC_S64
: scm_iprin1 (*np
.fake_64
, port
, pstate
);
197 case SCM_UVEC_F32
: scm_i_print_double (*np
.f32
, port
); np
.f32
++; break;
198 case SCM_UVEC_F64
: scm_i_print_double (*np
.f64
, port
); np
.f64
++; break;
200 scm_i_print_complex (np
.f32
[0], np
.f32
[1], port
);
204 scm_i_print_complex (np
.f64
[0], np
.f64
[1], port
);
208 abort (); /* Sanity check. */
213 scm_remember_upto_here_1 (uvec
);
214 scm_puts (")", port
);
219 scm_i_uniform_vector_tag (SCM uvec
)
221 return uvec_tags
[SCM_UVEC_TYPE (uvec
)];
225 uvec_equalp (SCM a
, SCM b
)
227 SCM result
= SCM_BOOL_T
;
228 if (SCM_UVEC_TYPE (a
) != SCM_UVEC_TYPE (b
))
230 else if (SCM_UVEC_LENGTH (a
) != SCM_UVEC_LENGTH (b
))
232 #if SCM_HAVE_T_INT64 == 0
233 else if (SCM_UVEC_TYPE (a
) == SCM_UVEC_U64
234 || SCM_UVEC_TYPE (a
) == SCM_UVEC_S64
)
236 SCM
*aptr
= (SCM
*)SCM_UVEC_BASE (a
), *bptr
= (SCM
*)SCM_UVEC_BASE (b
);
237 size_t len
= SCM_UVEC_LENGTH (a
), i
;
238 for (i
= 0; i
< len
; i
++)
239 if (scm_is_false (scm_num_eq_p (*aptr
++, *bptr
++)))
246 else if (memcmp (SCM_UVEC_BASE (a
), SCM_UVEC_BASE (b
),
247 SCM_UVEC_LENGTH (a
) * uvec_sizes
[SCM_UVEC_TYPE(a
)]) != 0)
250 scm_remember_upto_here_2 (a
, b
);
255 /* ================================================================ */
256 /* Utility procedures. */
257 /* ================================================================ */
259 static SCM_C_INLINE_KEYWORD
int
260 is_uvec (int type
, SCM obj
)
262 if (SCM_IS_UVEC (obj
))
263 return SCM_UVEC_TYPE (obj
) == type
;
264 if (SCM_I_ARRAYP (obj
) && SCM_I_ARRAY_NDIM (obj
) == 1)
266 SCM v
= SCM_I_ARRAY_V (obj
);
267 return SCM_IS_UVEC (v
) && SCM_UVEC_TYPE (v
) == type
;
272 static SCM_C_INLINE_KEYWORD SCM
273 uvec_p (int type
, SCM obj
)
275 return scm_from_bool (is_uvec (type
, obj
));
278 static SCM_C_INLINE_KEYWORD
void
279 uvec_assert (int type
, SCM obj
)
281 if (!is_uvec (type
, obj
))
282 scm_wrong_type_arg_msg (NULL
, 0, obj
, uvec_names
[type
]);
285 /* Invoke free(3) on DATA, a user-provided buffer passed to one of the
286 `scm_take_' functions. */
288 free_user_data (GC_PTR data
, GC_PTR unused
)
294 take_uvec (int type
, void *base
, size_t len
)
296 SCM_RETURN_NEWSMOB3 (scm_tc16_uvec
, type
, len
, (scm_t_bits
) base
);
299 /* Create a new, uninitialized uniform numeric vector of type TYPE
300 with space for LEN elements. */
302 alloc_uvec (int type
, size_t len
)
305 if (len
> SCM_I_SIZE_MAX
/ uvec_sizes
[type
])
306 scm_out_of_range (NULL
, scm_from_size_t (len
));
307 base
= scm_gc_malloc (len
* uvec_sizes
[type
], uvec_names
[type
]);
308 #if SCM_HAVE_T_INT64 == 0
309 if (type
== SCM_UVEC_U64
|| type
== SCM_UVEC_S64
)
311 SCM
*ptr
= (SCM
*)base
;
313 for (i
= 0; i
< len
; i
++)
314 *ptr
++ = SCM_UNSPECIFIED
;
317 return take_uvec (type
, base
, len
);
320 /* GCC doesn't seem to want to optimize unused switch clauses away,
321 so we use a big 'if' in the next two functions.
324 static SCM_C_INLINE_KEYWORD SCM
325 uvec_fast_ref (int type
, const void *base
, size_t c_idx
)
327 if (type
== SCM_UVEC_U8
)
328 return scm_from_uint8 (((scm_t_uint8
*)base
)[c_idx
]);
329 else if (type
== SCM_UVEC_S8
)
330 return scm_from_int8 (((scm_t_int8
*)base
)[c_idx
]);
331 else if (type
== SCM_UVEC_U16
)
332 return scm_from_uint16 (((scm_t_uint16
*)base
)[c_idx
]);
333 else if (type
== SCM_UVEC_S16
)
334 return scm_from_int16 (((scm_t_int16
*)base
)[c_idx
]);
335 else if (type
== SCM_UVEC_U32
)
336 return scm_from_uint32 (((scm_t_uint32
*)base
)[c_idx
]);
337 else if (type
== SCM_UVEC_S32
)
338 return scm_from_int32 (((scm_t_int32
*)base
)[c_idx
]);
340 else if (type
== SCM_UVEC_U64
)
341 return scm_from_uint64 (((scm_t_uint64
*)base
)[c_idx
]);
342 else if (type
== SCM_UVEC_S64
)
343 return scm_from_int64 (((scm_t_int64
*)base
)[c_idx
]);
345 else if (type
== SCM_UVEC_U64
)
346 return ((SCM
*)base
)[c_idx
];
347 else if (type
== SCM_UVEC_S64
)
348 return ((SCM
*)base
)[c_idx
];
350 else if (type
== SCM_UVEC_F32
)
351 return scm_from_double (((float*)base
)[c_idx
]);
352 else if (type
== SCM_UVEC_F64
)
353 return scm_from_double (((double*)base
)[c_idx
]);
354 else if (type
== SCM_UVEC_C32
)
355 return scm_c_make_rectangular (((float*)base
)[2*c_idx
],
356 ((float*)base
)[2*c_idx
+1]);
357 else if (type
== SCM_UVEC_C64
)
358 return scm_c_make_rectangular (((double*)base
)[2*c_idx
],
359 ((double*)base
)[2*c_idx
+1]);
364 #if SCM_HAVE_T_INT64 == 0
365 static SCM scm_uint64_min
, scm_uint64_max
;
366 static SCM scm_int64_min
, scm_int64_max
;
369 assert_exact_integer_range (SCM val
, SCM min
, SCM max
)
371 if (!scm_is_integer (val
)
372 || scm_is_false (scm_exact_p (val
)))
373 scm_wrong_type_arg_msg (NULL
, 0, val
, "exact integer");
374 if (scm_is_true (scm_less_p (val
, min
))
375 || scm_is_true (scm_gr_p (val
, max
)))
376 scm_out_of_range (NULL
, val
);
380 static SCM_C_INLINE_KEYWORD
void
381 uvec_fast_set_x (int type
, void *base
, size_t c_idx
, SCM val
)
383 if (type
== SCM_UVEC_U8
)
384 (((scm_t_uint8
*)base
)[c_idx
]) = scm_to_uint8 (val
);
385 else if (type
== SCM_UVEC_S8
)
386 (((scm_t_int8
*)base
)[c_idx
]) = scm_to_int8 (val
);
387 else if (type
== SCM_UVEC_U16
)
388 (((scm_t_uint16
*)base
)[c_idx
]) = scm_to_uint16 (val
);
389 else if (type
== SCM_UVEC_S16
)
390 (((scm_t_int16
*)base
)[c_idx
]) = scm_to_int16 (val
);
391 else if (type
== SCM_UVEC_U32
)
392 (((scm_t_uint32
*)base
)[c_idx
]) = scm_to_uint32 (val
);
393 else if (type
== SCM_UVEC_S32
)
394 (((scm_t_int32
*)base
)[c_idx
]) = scm_to_int32 (val
);
396 else if (type
== SCM_UVEC_U64
)
397 (((scm_t_uint64
*)base
)[c_idx
]) = scm_to_uint64 (val
);
398 else if (type
== SCM_UVEC_S64
)
399 (((scm_t_int64
*)base
)[c_idx
]) = scm_to_int64 (val
);
401 else if (type
== SCM_UVEC_U64
)
403 assert_exact_integer_range (val
, scm_uint64_min
, scm_uint64_max
);
404 ((SCM
*)base
)[c_idx
] = val
;
406 else if (type
== SCM_UVEC_S64
)
408 assert_exact_integer_range (val
, scm_int64_min
, scm_int64_max
);
409 ((SCM
*)base
)[c_idx
] = val
;
412 else if (type
== SCM_UVEC_F32
)
413 (((float*)base
)[c_idx
]) = scm_to_double (val
);
414 else if (type
== SCM_UVEC_F64
)
415 (((double*)base
)[c_idx
]) = scm_to_double (val
);
416 else if (type
== SCM_UVEC_C32
)
418 (((float*)base
)[2*c_idx
]) = scm_c_real_part (val
);
419 (((float*)base
)[2*c_idx
+1]) = scm_c_imag_part (val
);
421 else if (type
== SCM_UVEC_C64
)
423 (((double*)base
)[2*c_idx
]) = scm_c_real_part (val
);
424 (((double*)base
)[2*c_idx
+1]) = scm_c_imag_part (val
);
428 static SCM_C_INLINE_KEYWORD SCM
429 make_uvec (int type
, SCM len
, SCM fill
)
431 size_t c_len
= scm_to_size_t (len
);
432 SCM uvec
= alloc_uvec (type
, c_len
);
433 if (!SCM_UNBNDP (fill
))
436 void *base
= SCM_UVEC_BASE (uvec
);
437 for (idx
= 0; idx
< c_len
; idx
++)
438 uvec_fast_set_x (type
, base
, idx
, fill
);
443 static SCM_C_INLINE_KEYWORD
void *
444 uvec_writable_elements (int type
, SCM uvec
, scm_t_array_handle
*handle
,
445 size_t *lenp
, ssize_t
*incp
)
450 if (SCM_I_ARRAYP (v
))
451 v
= SCM_I_ARRAY_V (v
);
452 uvec_assert (type
, v
);
455 return scm_uniform_vector_writable_elements (uvec
, handle
, lenp
, incp
);
458 static SCM_C_INLINE_KEYWORD
const void *
459 uvec_elements (int type
, SCM uvec
, scm_t_array_handle
*handle
,
460 size_t *lenp
, ssize_t
*incp
)
462 return uvec_writable_elements (type
, uvec
, handle
, lenp
, incp
);
466 uvec_type (scm_t_array_handle
*h
)
469 if (SCM_I_ARRAYP (v
))
470 v
= SCM_I_ARRAY_V (v
);
471 return SCM_UVEC_TYPE (v
);
475 uvec_to_list (int type
, SCM uvec
)
477 scm_t_array_handle handle
;
483 elts
= uvec_elements (type
, uvec
, &handle
, &len
, &inc
);
484 for (i
= len
- 1; i
>= 0; i
--)
485 res
= scm_cons (scm_array_handle_ref (&handle
, i
*inc
), res
);
486 scm_array_handle_release (&handle
);
490 static SCM_C_INLINE_KEYWORD SCM
491 uvec_length (int type
, SCM uvec
)
493 scm_t_array_handle handle
;
496 uvec_elements (type
, uvec
, &handle
, &len
, &inc
);
497 scm_array_handle_release (&handle
);
498 return scm_from_size_t (len
);
501 static SCM_C_INLINE_KEYWORD SCM
502 uvec_ref (int type
, SCM uvec
, SCM idx
)
504 scm_t_array_handle handle
;
510 elts
= uvec_elements (type
, uvec
, &handle
, &len
, &inc
);
512 type
= uvec_type (&handle
);
513 i
= scm_to_unsigned_integer (idx
, 0, len
-1);
514 res
= uvec_fast_ref (type
, elts
, i
*inc
);
515 scm_array_handle_release (&handle
);
519 static SCM_C_INLINE_KEYWORD SCM
520 uvec_set_x (int type
, SCM uvec
, SCM idx
, SCM val
)
522 scm_t_array_handle handle
;
527 elts
= uvec_writable_elements (type
, uvec
, &handle
, &len
, &inc
);
529 type
= uvec_type (&handle
);
530 i
= scm_to_unsigned_integer (idx
, 0, len
-1);
531 uvec_fast_set_x (type
, elts
, i
*inc
, val
);
532 scm_array_handle_release (&handle
);
533 return SCM_UNSPECIFIED
;
536 static SCM_C_INLINE_KEYWORD SCM
537 list_to_uvec (int type
, SCM list
)
542 long len
= scm_ilength (list
);
544 scm_wrong_type_arg_msg (NULL
, 0, list
, "proper list");
546 uvec
= alloc_uvec (type
, len
);
547 base
= SCM_UVEC_BASE (uvec
);
549 while (scm_is_pair (list
) && idx
< len
)
551 uvec_fast_set_x (type
, base
, idx
, SCM_CAR (list
));
552 list
= SCM_CDR (list
);
558 SCM_SYMBOL (scm_sym_a
, "a");
559 SCM_SYMBOL (scm_sym_b
, "b");
562 scm_i_generalized_vector_type (SCM v
)
564 if (scm_is_vector (v
))
566 else if (scm_is_string (v
))
568 else if (scm_is_bitvector (v
))
570 else if (scm_is_uniform_vector (v
))
571 return scm_from_locale_symbol (uvec_tags
[SCM_UVEC_TYPE(v
)]);
572 else if (scm_is_bytevector (v
))
573 return scm_from_locale_symbol ("vu8");
578 SCM_DEFINE (scm_uniform_vector_read_x
, "uniform-vector-read!", 1, 3, 0,
579 (SCM uvec
, SCM port_or_fd
, SCM start
, SCM end
),
580 "Fill the elements of @var{uvec} by reading\n"
581 "raw bytes from @var{port-or-fdes}, using host byte order.\n\n"
582 "The optional arguments @var{start} (inclusive) and @var{end}\n"
583 "(exclusive) allow a specified region to be read,\n"
584 "leaving the remainder of the vector unchanged.\n\n"
585 "When @var{port-or-fdes} is a port, all specified elements\n"
586 "of @var{uvec} are attempted to be read, potentially blocking\n"
587 "while waiting formore input or end-of-file.\n"
588 "When @var{port-or-fd} is an integer, a single call to\n"
589 "read(2) is made.\n\n"
590 "An error is signalled when the last element has only\n"
591 "been partially filled before reaching end-of-file or in\n"
592 "the single call to read(2).\n\n"
593 "@code{uniform-vector-read!} returns the number of elements\n"
595 "@var{port-or-fdes} may be omitted, in which case it defaults\n"
596 "to the value returned by @code{(current-input-port)}.")
597 #define FUNC_NAME s_scm_uniform_vector_read_x
599 scm_t_array_handle handle
;
600 size_t vlen
, sz
, ans
;
603 size_t remaining
, off
;
606 if (SCM_UNBNDP (port_or_fd
))
607 port_or_fd
= scm_current_input_port ();
609 SCM_ASSERT (scm_is_integer (port_or_fd
)
610 || (SCM_OPINPORTP (port_or_fd
)),
611 port_or_fd
, SCM_ARG2
, FUNC_NAME
);
613 if (!scm_is_uniform_vector (uvec
))
614 scm_wrong_type_arg_msg (NULL
, 0, uvec
, "uniform vector");
616 base
= scm_uniform_vector_writable_elements (uvec
, &handle
, &vlen
, &inc
);
617 sz
= scm_array_handle_uniform_element_size (&handle
);
621 /* XXX - we should of course support non contiguous vectors. */
622 scm_misc_error (NULL
, "only contiguous vectors are supported: ~a",
628 if (!SCM_UNBNDP (start
))
630 cstart
= scm_to_unsigned_integer (start
, 0, vlen
);
631 if (!SCM_UNBNDP (end
))
632 cend
= scm_to_unsigned_integer (end
, cstart
, vlen
);
635 remaining
= (cend
- cstart
) * sz
;
638 if (SCM_NIMP (port_or_fd
))
641 remaining
-= scm_c_read (port_or_fd
, base
+ off
, remaining
);
642 if (remaining
% sz
!= 0)
643 SCM_MISC_ERROR ("unexpected EOF", SCM_EOL
);
644 ans
-= remaining
/ sz
;
646 else /* file descriptor. */
648 int fd
= scm_to_int (port_or_fd
);
651 SCM_SYSCALL (n
= read (fd
, base
+ off
, remaining
));
655 SCM_MISC_ERROR ("unexpected EOF", SCM_EOL
);
659 scm_array_handle_release (&handle
);
661 return scm_from_size_t (ans
);
665 SCM_DEFINE (scm_uniform_vector_write
, "uniform-vector-write", 1, 3, 0,
666 (SCM uvec
, SCM port_or_fd
, SCM start
, SCM end
),
667 "Write the elements of @var{uvec} as raw bytes to\n"
668 "@var{port-or-fdes}, in the host byte order.\n\n"
669 "The optional arguments @var{start} (inclusive)\n"
670 "and @var{end} (exclusive) allow\n"
671 "a specified region to be written.\n\n"
672 "When @var{port-or-fdes} is a port, all specified elements\n"
673 "of @var{uvec} are attempted to be written, potentially blocking\n"
674 "while waiting for more room.\n"
675 "When @var{port-or-fd} is an integer, a single call to\n"
676 "write(2) is made.\n\n"
677 "An error is signalled when the last element has only\n"
678 "been partially written in the single call to write(2).\n\n"
679 "The number of objects actually written is returned.\n"
680 "@var{port-or-fdes} may be\n"
681 "omitted, in which case it defaults to the value returned by\n"
682 "@code{(current-output-port)}.")
683 #define FUNC_NAME s_scm_uniform_vector_write
685 scm_t_array_handle handle
;
686 size_t vlen
, sz
, ans
;
692 port_or_fd
= SCM_COERCE_OUTPORT (port_or_fd
);
694 if (SCM_UNBNDP (port_or_fd
))
695 port_or_fd
= scm_current_output_port ();
697 SCM_ASSERT (scm_is_integer (port_or_fd
)
698 || (SCM_OPOUTPORTP (port_or_fd
)),
699 port_or_fd
, SCM_ARG2
, FUNC_NAME
);
701 base
= scm_uniform_vector_elements (uvec
, &handle
, &vlen
, &inc
);
702 sz
= scm_array_handle_uniform_element_size (&handle
);
706 /* XXX - we should of course support non contiguous vectors. */
707 scm_misc_error (NULL
, "only contiguous vectors are supported: ~a",
713 if (!SCM_UNBNDP (start
))
715 cstart
= scm_to_unsigned_integer (start
, 0, vlen
);
716 if (!SCM_UNBNDP (end
))
717 cend
= scm_to_unsigned_integer (end
, cstart
, vlen
);
720 amount
= (cend
- cstart
) * sz
;
723 if (SCM_NIMP (port_or_fd
))
725 scm_lfwrite (base
+ off
, amount
, port_or_fd
);
728 else /* file descriptor. */
730 int fd
= scm_to_int (port_or_fd
), n
;
731 SCM_SYSCALL (n
= write (fd
, base
+ off
, amount
));
735 SCM_MISC_ERROR ("last element only written partially", SCM_EOL
);
739 scm_array_handle_release (&handle
);
741 return scm_from_size_t (ans
);
745 /* ================================================================ */
746 /* Exported procedures. */
747 /* ================================================================ */
749 #define TYPE SCM_UVEC_U8
751 #define CTYPE scm_t_uint8
752 #include "libguile/srfi-4.i.c"
754 #define TYPE SCM_UVEC_S8
756 #define CTYPE scm_t_int8
757 #include "libguile/srfi-4.i.c"
759 #define TYPE SCM_UVEC_U16
761 #define CTYPE scm_t_uint16
762 #include "libguile/srfi-4.i.c"
764 #define TYPE SCM_UVEC_S16
766 #define CTYPE scm_t_int16
767 #include "libguile/srfi-4.i.c"
769 #define TYPE SCM_UVEC_U32
771 #define CTYPE scm_t_uint32
772 #include "libguile/srfi-4.i.c"
774 #define TYPE SCM_UVEC_S32
776 #define CTYPE scm_t_int32
777 #include "libguile/srfi-4.i.c"
779 #define TYPE SCM_UVEC_U64
781 #if SCM_HAVE_T_UINT64
782 #define CTYPE scm_t_uint64
784 #include "libguile/srfi-4.i.c"
786 #define TYPE SCM_UVEC_S64
789 #define CTYPE scm_t_int64
791 #include "libguile/srfi-4.i.c"
793 #define TYPE SCM_UVEC_F32
796 #include "libguile/srfi-4.i.c"
798 #define TYPE SCM_UVEC_F64
801 #include "libguile/srfi-4.i.c"
803 #define TYPE SCM_UVEC_C32
806 #include "libguile/srfi-4.i.c"
808 #define TYPE SCM_UVEC_C64
811 #include "libguile/srfi-4.i.c"
813 #define DEFINE_SCHEME_PROXY100(cname, modname, scmname) \
814 SCM cname (SCM arg1) \
816 static SCM var = SCM_BOOL_F; \
817 if (scm_is_false (var)) \
818 var = scm_c_module_lookup (scm_c_resolve_module (modname), scmname); \
819 return scm_call_1 (SCM_VARIABLE_REF (var), arg1); \
822 #define DEFPROXY100(cname, scmname) \
823 DEFINE_SCHEME_PROXY100 (cname, MOD, scmname)
825 #define DEFINE_SRFI_4_GNU_PROXIES(tag) \
826 DEFPROXY100 (scm_any_to_##tag##vector, "any->" #tag "vector")
828 #define MOD "srfi srfi-4 gnu"
829 DEFINE_SRFI_4_GNU_PROXIES (u8
);
830 DEFINE_SRFI_4_GNU_PROXIES (s8
);
831 DEFINE_SRFI_4_GNU_PROXIES (u16
);
832 DEFINE_SRFI_4_GNU_PROXIES (s16
);
833 DEFINE_SRFI_4_GNU_PROXIES (u32
);
834 DEFINE_SRFI_4_GNU_PROXIES (s32
);
835 DEFINE_SRFI_4_GNU_PROXIES (u64
);
836 DEFINE_SRFI_4_GNU_PROXIES (s64
);
837 DEFINE_SRFI_4_GNU_PROXIES (f32
);
838 DEFINE_SRFI_4_GNU_PROXIES (f64
);
839 DEFINE_SRFI_4_GNU_PROXIES (c32
);
840 DEFINE_SRFI_4_GNU_PROXIES (c64
);
843 static scm_i_t_array_ref uvec_reffers
[12] = {
852 static scm_i_t_array_set uvec_setters
[12] = {
862 uvec_handle_ref (scm_t_array_handle
*h
, size_t index
)
864 return uvec_reffers
[SCM_UVEC_TYPE(h
->array
)] (h
, index
);
868 uvec_handle_set (scm_t_array_handle
*h
, size_t index
, SCM val
)
870 uvec_setters
[SCM_UVEC_TYPE(h
->array
)] (h
, index
, val
);
874 uvec_get_handle (SCM v
, scm_t_array_handle
*h
)
880 h
->dim0
.ubnd
= SCM_UVEC_LENGTH (v
) - 1;
882 h
->element_type
= SCM_UVEC_TYPE (v
) + SCM_ARRAY_ELEMENT_TYPE_U8
;
883 h
->elements
= h
->writable_elements
= SCM_UVEC_BASE (v
);
886 SCM_ARRAY_IMPLEMENTATION (scm_tc16_uvec
, 0xffff,
887 uvec_handle_ref
, uvec_handle_set
,
891 scm_init_srfi_4 (void)
893 scm_tc16_uvec
= scm_make_smob_type ("uvec", 0);
894 scm_set_smob_equalp (scm_tc16_uvec
, uvec_equalp
);
895 scm_set_smob_print (scm_tc16_uvec
, uvec_print
);
897 #if SCM_HAVE_T_INT64 == 0
898 scm_uint64_min
= scm_from_int (0);
899 scm_uint64_max
= scm_c_read_string ("18446744073709551615");
900 scm_int64_min
= scm_c_read_string ("-9223372036854775808");
901 scm_int64_max
= scm_c_read_string ("9223372036854775807");
904 #define REGISTER(tag, TAG) \
905 scm_i_register_vector_constructor \
906 (scm_i_array_element_types[SCM_ARRAY_ELEMENT_TYPE_##TAG], \
907 scm_make_##tag##vector)
922 #include "libguile/srfi-4.x"
926 /* End of srfi-4.c. */