1 /* srfi-4.c --- Homogeneous numeric vector datatypes.
3 * Copyright (C) 2001, 2004 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
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "libguile/_scm.h"
29 #include "libguile/__scm.h"
30 #include "libguile/srfi-4.h"
31 #include "libguile/error.h"
32 #include "libguile/read.h"
33 #include "libguile/ports.h"
34 #include "libguile/chars.h"
35 #include "libguile/vectors.h"
36 #include "libguile/unif.h"
37 #include "libguile/strings.h"
38 #include "libguile/dynwind.h"
39 #include "libguile/deprecation.h"
49 /* Smob type code for homogeneous numeric vectors. */
50 int scm_tc16_uvec
= 0;
52 #define SCM_IS_UVEC(obj) SCM_SMOB_PREDICATE (scm_tc16_uvec, (obj))
54 /* Accessor macros for the three components of a homogeneous numeric
56 - The type tag (one of the symbolic constants below).
57 - The vector's length (counted in elements).
58 - The address of the data area (holding the elements of the
60 #define SCM_UVEC_TYPE(u) (SCM_CELL_WORD_1(u))
61 #define SCM_UVEC_LENGTH(u) ((size_t)SCM_CELL_WORD_2(u))
62 #define SCM_UVEC_BASE(u) ((void *)SCM_CELL_WORD_3(u))
65 /* Symbolic constants encoding the various types of homogeneous
69 #define SCM_UVEC_U16 2
70 #define SCM_UVEC_S16 3
71 #define SCM_UVEC_U32 4
72 #define SCM_UVEC_S32 5
73 #define SCM_UVEC_U64 6
74 #define SCM_UVEC_S64 7
75 #define SCM_UVEC_F32 8
76 #define SCM_UVEC_F64 9
77 #define SCM_UVEC_C32 10
78 #define SCM_UVEC_C64 11
81 /* This array maps type tags to the size of the elements. */
82 static const int uvec_sizes
[12] = {
87 sizeof(float), sizeof(double),
88 2*sizeof(float), 2*sizeof(double)
91 static const char *uvec_tags
[12] = {
100 static const char *uvec_names
[12] = {
101 "u8vector", "s8vector",
102 "u16vector", "s16vector",
103 "u32vector", "s32vector",
104 "u64vector", "s64vector",
105 "f32vector", "f64vector",
106 "c32vector", "c64vector"
109 /* ================================================================ */
110 /* SMOB procedures. */
111 /* ================================================================ */
114 /* Smob print hook for homogeneous vectors. */
116 uvec_print (SCM uvec
, SCM port
, scm_print_state
*pstate
)
134 const size_t uvlen
= SCM_UVEC_LENGTH (uvec
);
135 void *uptr
= SCM_UVEC_BASE (uvec
);
137 switch (SCM_UVEC_TYPE (uvec
))
139 case SCM_UVEC_U8
: np
.u8
= (scm_t_uint8
*) uptr
; break;
140 case SCM_UVEC_S8
: np
.s8
= (scm_t_int8
*) uptr
; break;
141 case SCM_UVEC_U16
: np
.u16
= (scm_t_uint16
*) uptr
; break;
142 case SCM_UVEC_S16
: np
.s16
= (scm_t_int16
*) uptr
; break;
143 case SCM_UVEC_U32
: np
.u32
= (scm_t_uint32
*) uptr
; break;
144 case SCM_UVEC_S32
: np
.s32
= (scm_t_int32
*) uptr
; break;
146 case SCM_UVEC_U64
: np
.u64
= (scm_t_uint64
*) uptr
; break;
147 case SCM_UVEC_S64
: np
.s64
= (scm_t_int64
*) uptr
; break;
149 case SCM_UVEC_F32
: np
.f32
= (float *) uptr
; break;
150 case SCM_UVEC_F64
: np
.f64
= (double *) uptr
; break;
151 case SCM_UVEC_C32
: np
.f32
= (float *) uptr
; break;
152 case SCM_UVEC_C64
: np
.f64
= (double *) uptr
; break;
154 abort (); /* Sanity check. */
158 scm_putc ('#', port
);
159 scm_puts (uvec_tags
[SCM_UVEC_TYPE (uvec
)], port
);
160 scm_putc ('(', port
);
164 if (i
!= 0) scm_puts (" ", port
);
165 switch (SCM_UVEC_TYPE (uvec
))
167 case SCM_UVEC_U8
: scm_uintprint (*np
.u8
, 10, port
); np
.u8
++; break;
168 case SCM_UVEC_S8
: scm_intprint (*np
.s8
, 10, port
); np
.s8
++; break;
169 case SCM_UVEC_U16
: scm_uintprint (*np
.u16
, 10, port
); np
.u16
++; break;
170 case SCM_UVEC_S16
: scm_intprint (*np
.s16
, 10, port
); np
.s16
++; break;
171 case SCM_UVEC_U32
: scm_uintprint (*np
.u32
, 10, port
); np
.u32
++; break;
172 case SCM_UVEC_S32
: scm_intprint (*np
.s32
, 10, port
); np
.s32
++; break;
174 case SCM_UVEC_U64
: scm_uintprint (*np
.u64
, 10, port
); np
.u64
++; break;
175 case SCM_UVEC_S64
: scm_intprint (*np
.s64
, 10, port
); np
.s64
++; break;
177 case SCM_UVEC_F32
: scm_i_print_double (*np
.f32
, port
); np
.f32
++; break;
178 case SCM_UVEC_F64
: scm_i_print_double (*np
.f64
, port
); np
.f64
++; break;
180 scm_i_print_complex (np
.f32
[0], np
.f32
[1], port
);
184 scm_i_print_complex (np
.f64
[0], np
.f64
[1], port
);
188 abort (); /* Sanity check. */
193 scm_remember_upto_here_1 (uvec
);
194 scm_puts (")", port
);
199 scm_i_uniform_vector_tag (SCM uvec
)
201 return uvec_tags
[SCM_UVEC_TYPE (uvec
)];
205 uvec_equalp (SCM a
, SCM b
)
207 SCM result
= SCM_BOOL_T
;
208 if (SCM_UVEC_TYPE (a
) != SCM_UVEC_TYPE (b
))
210 else if (SCM_UVEC_LENGTH (a
) != SCM_UVEC_LENGTH (b
))
212 else if (memcmp (SCM_UVEC_BASE (a
), SCM_UVEC_BASE (b
),
213 SCM_UVEC_LENGTH (a
) * uvec_sizes
[SCM_UVEC_TYPE(a
)]) != 0)
216 scm_remember_upto_here_2 (a
, b
);
220 /* Smob free hook for homogeneous numeric vectors. */
224 int type
= SCM_UVEC_TYPE (uvec
);
225 scm_gc_free (SCM_UVEC_BASE (uvec
),
226 SCM_UVEC_LENGTH (uvec
) * uvec_sizes
[type
],
231 /* ================================================================ */
232 /* Utility procedures. */
233 /* ================================================================ */
235 static SCM_C_INLINE
int
236 is_uvec (int type
, SCM obj
)
238 if (SCM_IS_UVEC (obj
))
239 return SCM_UVEC_TYPE (obj
) == type
;
240 if (SCM_I_ARRAYP (obj
) && SCM_I_ARRAY_NDIM (obj
) == 1)
242 SCM v
= SCM_I_ARRAY_V (obj
);
243 return SCM_IS_UVEC (v
) && SCM_UVEC_TYPE (v
) == type
;
248 static SCM_C_INLINE SCM
249 uvec_p (int type
, SCM obj
)
251 return scm_from_bool (is_uvec (type
, obj
));
254 static SCM_C_INLINE
void
255 uvec_assert (int type
, SCM obj
)
257 if (!is_uvec (type
, obj
))
258 scm_wrong_type_arg_msg (NULL
, 0, obj
, uvec_names
[type
]);
262 take_uvec (int type
, const void *base
, size_t len
)
264 SCM_RETURN_NEWSMOB3 (scm_tc16_uvec
, type
, len
, (scm_t_bits
) base
);
267 /* Create a new, uninitialized homogeneous numeric vector of type TYPE
268 with space for LEN elements. */
270 alloc_uvec (int type
, size_t len
)
273 if (len
> SCM_I_SIZE_MAX
/ uvec_sizes
[type
])
274 scm_out_of_range (NULL
, scm_from_size_t (len
));
275 base
= scm_gc_malloc (len
* uvec_sizes
[type
], uvec_names
[type
]);
276 return take_uvec (type
, base
, len
);
279 /* GCC doesn't seem to want to optimize unused switch clauses away,
280 so we use a big 'if' in the next two functions.
283 static SCM_C_INLINE SCM
284 uvec_fast_ref (int type
, const void *base
, size_t c_idx
)
286 if (type
== SCM_UVEC_U8
)
287 return scm_from_uint8 (((scm_t_uint8
*)base
)[c_idx
]);
288 else if (type
== SCM_UVEC_S8
)
289 return scm_from_int8 (((scm_t_int8
*)base
)[c_idx
]);
290 else if (type
== SCM_UVEC_U16
)
291 return scm_from_uint16 (((scm_t_uint16
*)base
)[c_idx
]);
292 else if (type
== SCM_UVEC_S16
)
293 return scm_from_int16 (((scm_t_int16
*)base
)[c_idx
]);
294 else if (type
== SCM_UVEC_U32
)
295 return scm_from_uint32 (((scm_t_uint32
*)base
)[c_idx
]);
296 else if (type
== SCM_UVEC_S32
)
297 return scm_from_int32 (((scm_t_int32
*)base
)[c_idx
]);
299 else if (type
== SCM_UVEC_U64
)
300 return scm_from_uint64 (((scm_t_uint64
*)base
)[c_idx
]);
301 else if (type
== SCM_UVEC_S64
)
302 return scm_from_int64 (((scm_t_int64
*)base
)[c_idx
]);
304 else if (type
== SCM_UVEC_F32
)
305 return scm_from_double (((float*)base
)[c_idx
]);
306 else if (type
== SCM_UVEC_F64
)
307 return scm_from_double (((double*)base
)[c_idx
]);
308 else if (type
== SCM_UVEC_C32
)
309 return scm_c_make_rectangular (((float*)base
)[2*c_idx
],
310 ((float*)base
)[2*c_idx
+1]);
311 else if (type
== SCM_UVEC_C64
)
312 return scm_c_make_rectangular (((double*)base
)[2*c_idx
],
313 ((double*)base
)[2*c_idx
+1]);
318 static SCM_C_INLINE
void
319 uvec_fast_set_x (int type
, void *base
, size_t c_idx
, SCM val
)
321 if (type
== SCM_UVEC_U8
)
322 (((scm_t_uint8
*)base
)[c_idx
]) = scm_to_uint8 (val
);
323 else if (type
== SCM_UVEC_S8
)
324 (((scm_t_int8
*)base
)[c_idx
]) = scm_to_int8 (val
);
325 else if (type
== SCM_UVEC_U16
)
326 (((scm_t_uint16
*)base
)[c_idx
]) = scm_to_uint16 (val
);
327 else if (type
== SCM_UVEC_S16
)
328 (((scm_t_int16
*)base
)[c_idx
]) = scm_to_int16 (val
);
329 else if (type
== SCM_UVEC_U32
)
330 (((scm_t_uint32
*)base
)[c_idx
]) = scm_to_uint32 (val
);
331 else if (type
== SCM_UVEC_S32
)
332 (((scm_t_int32
*)base
)[c_idx
]) = scm_to_int32 (val
);
334 else if (type
== SCM_UVEC_U64
)
335 (((scm_t_uint64
*)base
)[c_idx
]) = scm_to_uint64 (val
);
336 else if (type
== SCM_UVEC_S64
)
337 (((scm_t_int64
*)base
)[c_idx
]) = scm_to_int64 (val
);
339 else if (type
== SCM_UVEC_F32
)
340 (((float*)base
)[c_idx
]) = scm_to_double (val
);
341 else if (type
== SCM_UVEC_F64
)
342 (((double*)base
)[c_idx
]) = scm_to_double (val
);
343 else if (type
== SCM_UVEC_C32
)
345 (((float*)base
)[2*c_idx
]) = scm_c_real_part (val
);
346 (((float*)base
)[2*c_idx
+1]) = scm_c_imag_part (val
);
348 else if (type
== SCM_UVEC_C64
)
350 (((double*)base
)[2*c_idx
]) = scm_c_real_part (val
);
351 (((double*)base
)[2*c_idx
+1]) = scm_c_imag_part (val
);
355 static SCM_C_INLINE SCM
356 make_uvec (int type
, SCM len
, SCM fill
)
358 size_t c_len
= scm_to_size_t (len
);
359 SCM uvec
= alloc_uvec (type
, c_len
);
360 if (!SCM_UNBNDP (fill
))
363 void *base
= SCM_UVEC_BASE (uvec
);
364 for (idx
= 0; idx
< c_len
; idx
++)
365 uvec_fast_set_x (type
, base
, idx
, fill
);
370 static SCM_C_INLINE
void *
371 uvec_writable_elements (int type
, SCM uvec
, scm_t_array_handle
*handle
,
372 size_t *lenp
, ssize_t
*incp
)
377 if (SCM_I_ARRAYP (v
))
378 v
= SCM_I_ARRAY_V (v
);
379 uvec_assert (type
, v
);
382 return scm_uniform_vector_writable_elements (uvec
, handle
, lenp
, incp
);
385 static SCM_C_INLINE
const void *
386 uvec_elements (int type
, SCM uvec
, scm_t_array_handle
*handle
,
387 size_t *lenp
, ssize_t
*incp
)
389 return uvec_writable_elements (type
, uvec
, handle
, lenp
, incp
);
393 uvec_type (scm_t_array_handle
*h
)
396 if (SCM_I_ARRAYP (v
))
397 v
= SCM_I_ARRAY_V (v
);
398 return SCM_UVEC_TYPE (v
);
402 uvec_to_list (int type
, SCM uvec
)
404 scm_t_array_handle handle
;
410 elts
= uvec_elements (type
, uvec
, &handle
, &len
, &inc
);
411 for (i
= len
*inc
; i
> 0;)
414 res
= scm_cons (scm_array_handle_ref (&handle
, i
), res
);
416 scm_array_handle_release (&handle
);
420 static SCM_C_INLINE SCM
421 uvec_length (int type
, SCM uvec
)
423 scm_t_array_handle handle
;
426 uvec_elements (type
, uvec
, &handle
, &len
, &inc
);
427 scm_array_handle_release (&handle
);
428 return scm_from_size_t (len
);
431 static SCM_C_INLINE SCM
432 uvec_ref (int type
, SCM uvec
, SCM idx
)
434 scm_t_array_handle handle
;
440 elts
= uvec_elements (type
, uvec
, &handle
, &len
, &inc
);
442 type
= uvec_type (&handle
);
443 i
= scm_to_unsigned_integer (idx
, 0, len
-1);
444 res
= uvec_fast_ref (type
, elts
, i
*inc
);
445 scm_array_handle_release (&handle
);
449 static SCM_C_INLINE SCM
450 uvec_set_x (int type
, SCM uvec
, SCM idx
, SCM val
)
452 scm_t_array_handle handle
;
457 elts
= uvec_writable_elements (type
, uvec
, &handle
, &len
, &inc
);
459 type
= uvec_type (&handle
);
460 i
= scm_to_unsigned_integer (idx
, 0, len
-1);
461 uvec_fast_set_x (type
, elts
, i
*inc
, val
);
462 scm_array_handle_release (&handle
);
463 return SCM_UNSPECIFIED
;
466 static SCM_C_INLINE SCM
467 list_to_uvec (int type
, SCM list
)
472 long len
= scm_ilength (list
);
474 scm_wrong_type_arg_msg (NULL
, 0, list
, "proper list");
476 uvec
= alloc_uvec (type
, len
);
477 base
= SCM_UVEC_BASE (uvec
);
479 while (scm_is_pair (list
) && idx
< len
)
481 uvec_fast_set_x (type
, base
, idx
, SCM_CAR (list
));
482 list
= SCM_CDR (list
);
489 coerce_to_uvec (int type
, SCM obj
)
491 if (is_uvec (type
, obj
))
493 else if (scm_is_pair (obj
))
494 return list_to_uvec (type
, obj
);
495 else if (scm_is_generalized_vector (obj
))
497 scm_t_array_handle handle
;
498 size_t len
= scm_c_generalized_vector_length (obj
), i
;
499 SCM uvec
= alloc_uvec (type
, len
);
500 scm_array_get_handle (uvec
, &handle
);
501 for (i
= 0; i
< len
; i
++)
502 scm_array_handle_set (&handle
, i
,
503 scm_c_generalized_vector_ref (obj
, i
));
504 scm_array_handle_release (&handle
);
508 scm_wrong_type_arg_msg (NULL
, 0, obj
, "list or generalized vector");
511 SCM_SYMBOL (scm_sym_a
, "a");
512 SCM_SYMBOL (scm_sym_b
, "b");
515 scm_i_generalized_vector_type (SCM v
)
517 if (scm_is_vector (v
))
519 else if (scm_is_string (v
))
521 else if (scm_is_bitvector (v
))
523 else if (scm_is_uniform_vector (v
))
524 return scm_from_locale_symbol (uvec_tags
[SCM_UVEC_TYPE(v
)]);
530 scm_is_uniform_vector (SCM obj
)
532 if (SCM_IS_UVEC (obj
))
534 if (SCM_I_ARRAYP (obj
) && SCM_I_ARRAY_NDIM (obj
) == 1)
536 SCM v
= SCM_I_ARRAY_V (obj
);
537 return SCM_IS_UVEC (v
);
543 scm_c_uniform_vector_length (SCM uvec
)
545 /* scm_generalized_vector_get_handle will ultimately call us to get
546 the length of uniform vectors, so we can't use uvec_elements for
550 if (SCM_IS_UVEC (uvec
))
551 return SCM_UVEC_LENGTH (uvec
);
554 scm_t_array_handle handle
;
557 uvec_elements (-1, uvec
, &handle
, &len
, &inc
);
558 scm_array_handle_release (&handle
);
563 SCM_DEFINE (scm_uniform_vector_p
, "uniform-vector?", 1, 0, 0,
565 "Return @code{#t} if @var{obj} is a uniform vector.")
566 #define FUNC_NAME s_scm_uniform_vector_p
568 return scm_from_bool (scm_is_uniform_vector (obj
));
573 scm_c_uniform_vector_ref (SCM v
, size_t idx
)
575 scm_t_array_handle handle
;
580 uvec_elements (-1, v
, &handle
, &len
, &inc
);
582 scm_out_of_range (NULL
, scm_from_size_t (idx
));
583 res
= scm_array_handle_ref (&handle
, idx
*inc
);
584 scm_array_handle_release (&handle
);
588 SCM_DEFINE (scm_uniform_vector_ref
, "uniform-vector-ref", 2, 0, 0,
590 "Return the element at index @var{idx} of the\n"
591 "homogenous numeric vector @var{v}.")
592 #define FUNC_NAME s_scm_uniform_vector_ref
594 #if SCM_ENABLE_DEPRECATED
595 /* Support old argument convention.
597 if (scm_is_pair (idx
))
599 scm_c_issue_deprecation_warning
600 ("Using a list as the index to uniform-vector-ref is deprecated.");
601 if (!scm_is_null (SCM_CDR (idx
)))
602 scm_wrong_num_args (NULL
);
607 return scm_c_uniform_vector_ref (v
, scm_to_size_t (idx
));
612 scm_c_uniform_vector_set_x (SCM v
, size_t idx
, SCM val
)
614 scm_t_array_handle handle
;
618 uvec_writable_elements (-1, v
, &handle
, &len
, &inc
);
620 scm_out_of_range (NULL
, scm_from_size_t (idx
));
621 scm_array_handle_set (&handle
, idx
*inc
, val
);
622 scm_array_handle_release (&handle
);
625 SCM_DEFINE (scm_uniform_vector_set_x
, "uniform-vector-set!", 3, 0, 0,
626 (SCM v
, SCM idx
, SCM val
),
627 "Set the element at index @var{idx} of the\n"
628 "homogenous numeric vector @var{v} to @var{val}.")
629 #define FUNC_NAME s_scm_uniform_vector_set_x
631 #if SCM_ENABLE_DEPRECATED
632 /* Support old argument convention.
634 if (scm_is_pair (idx
))
636 scm_c_issue_deprecation_warning
637 ("Using a list as the index to uniform-vector-set! is deprecated.");
638 if (!scm_is_null (SCM_CDR (idx
)))
639 scm_wrong_num_args (NULL
);
644 scm_c_uniform_vector_set_x (v
, scm_to_size_t (idx
), val
);
645 return SCM_UNSPECIFIED
;
649 SCM_DEFINE (scm_uniform_vector_to_list
, "uniform-vector->list", 1, 0, 0,
651 "Convert the homogeneous numeric vector @var{uvec} to a list.")
652 #define FUNC_NAME s_scm_uniform_vector_to_list
654 return uvec_to_list (-1, uvec
);
659 scm_array_handle_uniform_element_size (scm_t_array_handle
*h
)
662 if (SCM_I_ARRAYP (vec
))
663 vec
= SCM_I_ARRAY_V (vec
);
664 if (scm_is_uniform_vector (vec
))
665 return uvec_sizes
[SCM_UVEC_TYPE(vec
)];
666 scm_wrong_type_arg_msg (NULL
, 0, h
->array
, "uniform array");
669 #if SCM_ENABLE_DEPRECATED
671 /* return the size of an element in a uniform array or 0 if type not
674 scm_uniform_element_size (SCM obj
)
676 scm_c_issue_deprecation_warning
677 ("scm_uniform_element_size is deprecated. "
678 "Use scm_array_handle_uniform_element_size instead.");
680 if (SCM_IS_UVEC (obj
))
681 return uvec_sizes
[SCM_UVEC_TYPE(obj
)];
689 scm_array_handle_uniform_elements (scm_t_array_handle
*h
)
691 return scm_array_handle_uniform_writable_elements (h
);
695 scm_array_handle_uniform_writable_elements (scm_t_array_handle
*h
)
698 if (SCM_I_ARRAYP (vec
))
699 vec
= SCM_I_ARRAY_V (vec
);
700 if (SCM_IS_UVEC (vec
))
702 size_t size
= uvec_sizes
[SCM_UVEC_TYPE(vec
)];
703 char *elts
= SCM_UVEC_BASE (vec
);
704 return (void *) (elts
+ size
*h
->base
);
706 scm_wrong_type_arg_msg (NULL
, 0, h
->array
, "uniform array");
710 scm_uniform_vector_elements (SCM uvec
,
711 scm_t_array_handle
*h
,
712 size_t *lenp
, ssize_t
*incp
)
714 return scm_uniform_vector_writable_elements (uvec
, h
, lenp
, incp
);
718 scm_uniform_vector_writable_elements (SCM uvec
,
719 scm_t_array_handle
*h
,
720 size_t *lenp
, ssize_t
*incp
)
722 scm_generalized_vector_get_handle (uvec
, h
);
725 scm_t_array_dim
*dim
= scm_array_handle_dims (h
);
726 *lenp
= dim
->ubnd
- dim
->lbnd
+ 1;
729 return scm_array_handle_uniform_writable_elements (h
);
732 SCM_DEFINE (scm_uniform_vector_length
, "uniform-vector-length", 1, 0, 0,
734 "Return the number of elements in the uniform vector @var{v}.")
735 #define FUNC_NAME s_scm_uniform_vector_length
737 return uvec_length (-1, v
);
741 SCM_DEFINE (scm_uniform_vector_read_x
, "uniform-vector-read!", 1, 3, 0,
742 (SCM uvec
, SCM port_or_fd
, SCM start
, SCM end
),
743 "Fill the elements of @var{uvec} by reading\n"
744 "raw bytes from @var{port-or-fdes}, using host byte order.\n\n"
745 "The optional arguments @var{start} (inclusive) and @var{end}\n"
746 "(exclusive) allow a specified region to be read,\n"
747 "leaving the remainder of the vector unchanged.\n\n"
748 "When @var{port-or-fdes} is a port, all specified elements\n"
749 "of @var{uvec} are attempted to be read, potentially blocking\n"
750 "while waiting formore input or end-of-file.\n"
751 "When @var{port-or-fd} is an integer, a single call to\n"
752 "read(2) is made.\n\n"
753 "An error is signalled when the last element has only\n"
754 "been partially filled before reaching end-of-file or in\n"
755 "the single call to read(2).\n\n"
756 "@code{uniform-vector-read!} returns the number of elements\n"
758 "@var{port-or-fdes} may be omitted, in which case it defaults\n"
759 "to the value returned by @code{(current-input-port)}.")
760 #define FUNC_NAME s_scm_uniform_vector_read_x
762 scm_t_array_handle handle
;
763 size_t vlen
, sz
, ans
;
766 size_t remaining
, off
;
769 if (SCM_UNBNDP (port_or_fd
))
770 port_or_fd
= scm_cur_inp
;
772 SCM_ASSERT (scm_is_integer (port_or_fd
)
773 || (SCM_OPINPORTP (port_or_fd
)),
774 port_or_fd
, SCM_ARG2
, FUNC_NAME
);
776 if (!scm_is_uniform_vector (uvec
))
777 scm_wrong_type_arg_msg (NULL
, 0, uvec
, "uniform vector");
779 base
= scm_uniform_vector_writable_elements (uvec
, &handle
, &vlen
, &inc
);
780 sz
= scm_array_handle_uniform_element_size (&handle
);
784 /* XXX - we should of course support non contiguous vectors. */
785 scm_misc_error (NULL
, "only contiguous vectors are supported: ~a",
791 if (!SCM_UNBNDP (start
))
793 cstart
= scm_to_unsigned_integer (start
, 0, vlen
);
794 if (!SCM_UNBNDP (end
))
795 cend
= scm_to_unsigned_integer (end
, cstart
, vlen
);
798 remaining
= (cend
- cstart
) * sz
;
801 if (SCM_NIMP (port_or_fd
))
803 scm_t_port
*pt
= SCM_PTAB_ENTRY (port_or_fd
);
805 if (pt
->rw_active
== SCM_PORT_WRITE
)
806 scm_flush (port_or_fd
);
809 while (remaining
> 0)
811 if (pt
->read_pos
< pt
->read_end
)
813 size_t to_copy
= min (pt
->read_end
- pt
->read_pos
,
816 memcpy (base
+ off
, pt
->read_pos
, to_copy
);
817 pt
->read_pos
+= to_copy
;
818 remaining
-= to_copy
;
823 if (scm_fill_input (port_or_fd
) == EOF
)
825 if (remaining
% sz
!= 0)
826 SCM_MISC_ERROR ("unexpected EOF", SCM_EOL
);
827 ans
-= remaining
/ sz
;
834 pt
->rw_active
= SCM_PORT_READ
;
836 else /* file descriptor. */
838 int fd
= scm_to_int (port_or_fd
);
841 SCM_SYSCALL (n
= read (fd
, base
+ off
, remaining
));
845 SCM_MISC_ERROR ("unexpected EOF", SCM_EOL
);
849 scm_array_handle_release (&handle
);
851 return scm_from_size_t (ans
);
855 SCM_DEFINE (scm_uniform_vector_write
, "uniform-vector-write", 1, 3, 0,
856 (SCM uvec
, SCM port_or_fd
, SCM start
, SCM end
),
857 "Write the elements of @var{uvec} as raw bytes to\n"
858 "@var{port-or-fdes}, in the host byte order.\n\n"
859 "The optional arguments @var{start} (inclusive)\n"
860 "and @var{end} (exclusive) allow\n"
861 "a specified region to be written.\n\n"
862 "When @var{port-or-fdes} is a port, all specified elements\n"
863 "of @var{uvec} are attempted to be written, potentially blocking\n"
864 "while waiting for more room.\n"
865 "When @var{port-or-fd} is an integer, a single call to\n"
866 "write(2) is made.\n\n"
867 "An error is signalled when the last element has only\n"
868 "been partially written in the single call to write(2).\n\n"
869 "The number of objects actually written is returned.\n"
870 "@var{port-or-fdes} may be\n"
871 "omitted, in which case it defaults to the value returned by\n"
872 "@code{(current-output-port)}.")
873 #define FUNC_NAME s_scm_uniform_vector_write
875 scm_t_array_handle handle
;
876 size_t vlen
, sz
, ans
;
882 port_or_fd
= SCM_COERCE_OUTPORT (port_or_fd
);
884 if (SCM_UNBNDP (port_or_fd
))
885 port_or_fd
= scm_cur_outp
;
887 SCM_ASSERT (scm_is_integer (port_or_fd
)
888 || (SCM_OPOUTPORTP (port_or_fd
)),
889 port_or_fd
, SCM_ARG2
, FUNC_NAME
);
891 base
= scm_uniform_vector_elements (uvec
, &handle
, &vlen
, &inc
);
892 sz
= scm_array_handle_uniform_element_size (&handle
);
896 /* XXX - we should of course support non contiguous vectors. */
897 scm_misc_error (NULL
, "only contiguous vectors are supported: ~a",
903 if (!SCM_UNBNDP (start
))
905 cstart
= scm_to_unsigned_integer (start
, 0, vlen
);
906 if (!SCM_UNBNDP (end
))
907 cend
= scm_to_unsigned_integer (end
, cstart
, vlen
);
910 amount
= (cend
- cstart
) * sz
;
913 if (SCM_NIMP (port_or_fd
))
915 scm_lfwrite (base
+ off
, amount
, port_or_fd
);
918 else /* file descriptor. */
920 int fd
= scm_to_int (port_or_fd
), n
;
921 SCM_SYSCALL (n
= write (fd
, base
+ off
, amount
));
925 SCM_MISC_ERROR ("last element only written partially", SCM_EOL
);
929 scm_array_handle_release (&handle
);
931 return scm_from_size_t (ans
);
935 /* ================================================================ */
936 /* Exported procedures. */
937 /* ================================================================ */
939 #define TYPE SCM_UVEC_U8
941 #define CTYPE scm_t_uint8
942 #include "libguile/srfi-4.i.c"
944 #define TYPE SCM_UVEC_S8
946 #define CTYPE scm_t_int8
947 #include "libguile/srfi-4.i.c"
949 #define TYPE SCM_UVEC_U16
951 #define CTYPE scm_t_uint16
952 #include "libguile/srfi-4.i.c"
954 #define TYPE SCM_UVEC_S16
956 #define CTYPE scm_t_int16
957 #include "libguile/srfi-4.i.c"
959 #define TYPE SCM_UVEC_U32
961 #define CTYPE scm_t_uint32
962 #include "libguile/srfi-4.i.c"
964 #define TYPE SCM_UVEC_S32
966 #define CTYPE scm_t_int32
967 #include "libguile/srfi-4.i.c"
969 #define TYPE SCM_UVEC_U64
971 #define CTYPE scm_t_uint64
972 #include "libguile/srfi-4.i.c"
974 #define TYPE SCM_UVEC_S64
976 #define CTYPE scm_t_int64
977 #include "libguile/srfi-4.i.c"
979 #define TYPE SCM_UVEC_F32
982 #include "libguile/srfi-4.i.c"
984 #define TYPE SCM_UVEC_F64
987 #include "libguile/srfi-4.i.c"
989 #define TYPE SCM_UVEC_C32
992 #include "libguile/srfi-4.i.c"
994 #define TYPE SCM_UVEC_C64
997 #include "libguile/srfi-4.i.c"
999 static scm_i_t_array_ref uvec_reffers
[12] = {
1008 static scm_i_t_array_set uvec_setters
[12] = {
1018 scm_i_uniform_vector_ref_proc (SCM uvec
)
1020 return uvec_reffers
[SCM_UVEC_TYPE(uvec
)];
1024 scm_i_uniform_vector_set_proc (SCM uvec
)
1026 return uvec_setters
[SCM_UVEC_TYPE(uvec
)];
1030 scm_init_srfi_4 (void)
1032 scm_tc16_uvec
= scm_make_smob_type ("uvec", 0);
1033 scm_set_smob_equalp (scm_tc16_uvec
, uvec_equalp
);
1034 scm_set_smob_free (scm_tc16_uvec
, uvec_free
);
1035 scm_set_smob_print (scm_tc16_uvec
, uvec_print
);
1037 #include "libguile/srfi-4.x"
1041 /* End of srfi-4.c. */