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"
48 /* Smob type code for homogeneous numeric vectors. */
49 int scm_tc16_uvec
= 0;
51 #define SCM_IS_UVEC(obj) SCM_SMOB_PREDICATE (scm_tc16_uvec, (obj))
53 /* Accessor macros for the three components of a homogeneous numeric
55 - The type tag (one of the symbolic constants below).
56 - The vector's length (counted in elements).
57 - The address of the data area (holding the elements of the
59 #define SCM_UVEC_TYPE(u) (SCM_CELL_WORD_1(u))
60 #define SCM_UVEC_LENGTH(u) ((size_t)SCM_CELL_WORD_2(u))
61 #define SCM_UVEC_BASE(u) ((void *)SCM_CELL_WORD_3(u))
64 /* Symbolic constants encoding the various types of homogeneous
68 #define SCM_UVEC_U16 2
69 #define SCM_UVEC_S16 3
70 #define SCM_UVEC_U32 4
71 #define SCM_UVEC_S32 5
72 #define SCM_UVEC_U64 6
73 #define SCM_UVEC_S64 7
74 #define SCM_UVEC_F32 8
75 #define SCM_UVEC_F64 9
76 #define SCM_UVEC_C32 10
77 #define SCM_UVEC_C64 11
80 /* This array maps type tags to the size of the elements. */
81 static const int uvec_sizes
[12] = {
86 sizeof(float), sizeof(double),
87 2*sizeof(float), 2*sizeof(double)
90 static const char *uvec_tags
[12] = {
99 static const char *uvec_names
[12] = {
100 "u8vector", "s8vector",
101 "u16vector", "s16vector",
102 "u32vector", "s32vector",
103 "u64vector", "s64vector",
104 "f32vector", "f64vector",
105 "c32vector", "c64vector"
108 /* ================================================================ */
109 /* SMOB procedures. */
110 /* ================================================================ */
113 /* Smob print hook for homogeneous vectors. */
115 uvec_print (SCM uvec
, SCM port
, scm_print_state
*pstate
)
133 const size_t uvlen
= SCM_UVEC_LENGTH (uvec
);
134 void *uptr
= SCM_UVEC_BASE (uvec
);
136 switch (SCM_UVEC_TYPE (uvec
))
138 case SCM_UVEC_U8
: np
.u8
= (scm_t_uint8
*) uptr
; break;
139 case SCM_UVEC_S8
: np
.s8
= (scm_t_int8
*) uptr
; break;
140 case SCM_UVEC_U16
: np
.u16
= (scm_t_uint16
*) uptr
; break;
141 case SCM_UVEC_S16
: np
.s16
= (scm_t_int16
*) uptr
; break;
142 case SCM_UVEC_U32
: np
.u32
= (scm_t_uint32
*) uptr
; break;
143 case SCM_UVEC_S32
: np
.s32
= (scm_t_int32
*) uptr
; break;
145 case SCM_UVEC_U64
: np
.u64
= (scm_t_uint64
*) uptr
; break;
146 case SCM_UVEC_S64
: np
.s64
= (scm_t_int64
*) uptr
; break;
148 case SCM_UVEC_F32
: np
.f32
= (float *) uptr
; break;
149 case SCM_UVEC_F64
: np
.f64
= (double *) uptr
; break;
150 case SCM_UVEC_C32
: np
.f32
= (float *) uptr
; break;
151 case SCM_UVEC_C64
: np
.f64
= (double *) uptr
; break;
153 abort (); /* Sanity check. */
157 scm_putc ('#', port
);
158 scm_puts (uvec_tags
[SCM_UVEC_TYPE (uvec
)], port
);
159 scm_putc ('(', port
);
163 if (i
!= 0) scm_puts (" ", port
);
164 switch (SCM_UVEC_TYPE (uvec
))
166 case SCM_UVEC_U8
: scm_uintprint (*np
.u8
, 10, port
); np
.u8
++; break;
167 case SCM_UVEC_S8
: scm_intprint (*np
.s8
, 10, port
); np
.s8
++; break;
168 case SCM_UVEC_U16
: scm_uintprint (*np
.u16
, 10, port
); np
.u16
++; break;
169 case SCM_UVEC_S16
: scm_intprint (*np
.s16
, 10, port
); np
.s16
++; break;
170 case SCM_UVEC_U32
: scm_uintprint (*np
.u32
, 10, port
); np
.u32
++; break;
171 case SCM_UVEC_S32
: scm_intprint (*np
.s32
, 10, port
); np
.s32
++; break;
173 case SCM_UVEC_U64
: scm_uintprint (*np
.u64
, 10, port
); np
.u64
++; break;
174 case SCM_UVEC_S64
: scm_intprint (*np
.s64
, 10, port
); np
.s64
++; break;
176 case SCM_UVEC_F32
: scm_i_print_double (*np
.f32
, port
); np
.f32
++; break;
177 case SCM_UVEC_F64
: scm_i_print_double (*np
.f64
, port
); np
.f64
++; break;
179 scm_i_print_complex (np
.f32
[0], np
.f32
[1], port
);
183 scm_i_print_complex (np
.f64
[0], np
.f64
[1], port
);
187 abort (); /* Sanity check. */
192 scm_remember_upto_here_1 (uvec
);
193 scm_puts (")", port
);
198 scm_i_uniform_vector_tag (SCM uvec
)
200 return uvec_tags
[SCM_UVEC_TYPE (uvec
)];
204 uvec_equalp (SCM a
, SCM b
)
206 SCM result
= SCM_BOOL_T
;
207 if (SCM_UVEC_TYPE (a
) != SCM_UVEC_TYPE (b
))
209 else if (SCM_UVEC_LENGTH (a
) != SCM_UVEC_LENGTH (b
))
211 else if (memcmp (SCM_UVEC_BASE (a
), SCM_UVEC_BASE (b
),
212 SCM_UVEC_LENGTH (a
) * uvec_sizes
[SCM_UVEC_TYPE(a
)]) != 0)
215 scm_remember_upto_here_2 (a
, b
);
219 /* Smob free hook for homogeneous numeric vectors. */
223 int type
= SCM_UVEC_TYPE (uvec
);
224 scm_gc_free (SCM_UVEC_BASE (uvec
),
225 SCM_UVEC_LENGTH (uvec
) * uvec_sizes
[type
],
230 /* ================================================================ */
231 /* Utility procedures. */
232 /* ================================================================ */
234 static SCM_C_INLINE
int
235 is_uvec (int type
, SCM obj
)
237 if (SCM_IS_UVEC (obj
))
238 return SCM_UVEC_TYPE (obj
) == type
;
239 if (SCM_ARRAYP (obj
) && SCM_ARRAY_NDIM (obj
) == 1)
241 SCM v
= SCM_ARRAY_V (obj
);
242 return SCM_IS_UVEC (v
) && SCM_UVEC_TYPE (v
) == type
;
247 static SCM_C_INLINE SCM
248 uvec_p (int type
, SCM obj
)
250 return scm_from_bool (is_uvec (type
, obj
));
253 static SCM_C_INLINE
void
254 uvec_assert (int type
, SCM obj
)
256 if (!is_uvec (type
, obj
))
257 scm_wrong_type_arg_msg (NULL
, 0, obj
, uvec_names
[type
]);
261 take_uvec (int type
, const void *base
, size_t len
)
263 SCM_RETURN_NEWSMOB3 (scm_tc16_uvec
, type
, len
, (scm_t_bits
) base
);
266 /* Create a new, uninitialized homogeneous numeric vector of type TYPE
267 with space for LEN elements. */
269 alloc_uvec (int type
, size_t len
)
272 if (len
> SCM_I_SIZE_MAX
/ uvec_sizes
[type
])
273 scm_out_of_range (NULL
, scm_from_size_t (len
));
274 base
= scm_gc_malloc (len
* uvec_sizes
[type
], uvec_names
[type
]);
275 return take_uvec (type
, base
, len
);
278 /* GCC doesn't seem to want to optimize unused switch clauses away,
279 so we use a big 'if' in the next two functions.
282 static SCM_C_INLINE SCM
283 uvec_fast_ref (int type
, const void *base
, size_t c_idx
)
285 if (type
== SCM_UVEC_U8
)
286 return scm_from_uint8 (((scm_t_uint8
*)base
)[c_idx
]);
287 else if (type
== SCM_UVEC_S8
)
288 return scm_from_int8 (((scm_t_int8
*)base
)[c_idx
]);
289 else if (type
== SCM_UVEC_U16
)
290 return scm_from_uint16 (((scm_t_uint16
*)base
)[c_idx
]);
291 else if (type
== SCM_UVEC_S16
)
292 return scm_from_int16 (((scm_t_int16
*)base
)[c_idx
]);
293 else if (type
== SCM_UVEC_U32
)
294 return scm_from_uint32 (((scm_t_uint32
*)base
)[c_idx
]);
295 else if (type
== SCM_UVEC_S32
)
296 return scm_from_int32 (((scm_t_int32
*)base
)[c_idx
]);
298 else if (type
== SCM_UVEC_U64
)
299 return scm_from_uint64 (((scm_t_uint64
*)base
)[c_idx
]);
300 else if (type
== SCM_UVEC_S64
)
301 return scm_from_int64 (((scm_t_int64
*)base
)[c_idx
]);
303 else if (type
== SCM_UVEC_F32
)
304 return scm_from_double (((float*)base
)[c_idx
]);
305 else if (type
== SCM_UVEC_F64
)
306 return scm_from_double (((double*)base
)[c_idx
]);
307 else if (type
== SCM_UVEC_C32
)
308 return scm_c_make_rectangular (((float*)base
)[2*c_idx
],
309 ((float*)base
)[2*c_idx
+1]);
310 else if (type
== SCM_UVEC_C64
)
311 return scm_c_make_rectangular (((double*)base
)[2*c_idx
],
312 ((double*)base
)[2*c_idx
+1]);
317 static SCM_C_INLINE
void
318 uvec_fast_set_x (int type
, void *base
, size_t c_idx
, SCM val
)
320 if (type
== SCM_UVEC_U8
)
321 (((scm_t_uint8
*)base
)[c_idx
]) = scm_to_uint8 (val
);
322 else if (type
== SCM_UVEC_S8
)
323 (((scm_t_int8
*)base
)[c_idx
]) = scm_to_int8 (val
);
324 else if (type
== SCM_UVEC_U16
)
325 (((scm_t_uint16
*)base
)[c_idx
]) = scm_to_uint16 (val
);
326 else if (type
== SCM_UVEC_S16
)
327 (((scm_t_int16
*)base
)[c_idx
]) = scm_to_int16 (val
);
328 else if (type
== SCM_UVEC_U32
)
329 (((scm_t_uint32
*)base
)[c_idx
]) = scm_to_uint32 (val
);
330 else if (type
== SCM_UVEC_S32
)
331 (((scm_t_int32
*)base
)[c_idx
]) = scm_to_int32 (val
);
333 else if (type
== SCM_UVEC_U64
)
334 (((scm_t_uint64
*)base
)[c_idx
]) = scm_to_uint64 (val
);
335 else if (type
== SCM_UVEC_S64
)
336 (((scm_t_int64
*)base
)[c_idx
]) = scm_to_int64 (val
);
338 else if (type
== SCM_UVEC_F32
)
339 (((float*)base
)[c_idx
]) = scm_to_double (val
);
340 else if (type
== SCM_UVEC_F64
)
341 (((double*)base
)[c_idx
]) = scm_to_double (val
);
342 else if (type
== SCM_UVEC_C32
)
344 (((float*)base
)[2*c_idx
]) = scm_c_real_part (val
);
345 (((float*)base
)[2*c_idx
+1]) = scm_c_imag_part (val
);
347 else if (type
== SCM_UVEC_C64
)
349 (((double*)base
)[2*c_idx
]) = scm_c_real_part (val
);
350 (((double*)base
)[2*c_idx
+1]) = scm_c_imag_part (val
);
354 static SCM_C_INLINE SCM
355 make_uvec (int type
, SCM len
, SCM fill
)
357 size_t c_len
= scm_to_size_t (len
);
358 SCM uvec
= alloc_uvec (type
, c_len
);
359 if (!SCM_UNBNDP (fill
))
362 void *base
= SCM_UVEC_BASE (uvec
);
363 for (idx
= 0; idx
< c_len
; idx
++)
364 uvec_fast_set_x (type
, base
, idx
, fill
);
369 static SCM_C_INLINE
void *
370 uvec_writable_elements (int type
, SCM uvec
, scm_t_array_handle
*handle
,
371 size_t *lenp
, ssize_t
*incp
)
378 uvec_assert (type
, v
);
381 return scm_uniform_vector_writable_elements (uvec
, handle
, lenp
, incp
);
384 static SCM_C_INLINE
const void *
385 uvec_elements (int type
, SCM uvec
, scm_t_array_handle
*handle
,
386 size_t *lenp
, ssize_t
*incp
)
388 return uvec_writable_elements (type
, uvec
, handle
, lenp
, incp
);
392 uvec_to_list (int type
, SCM uvec
)
394 scm_t_array_handle handle
;
400 elts
= uvec_elements (type
, uvec
, &handle
, &len
, &inc
);
401 for (i
= len
*inc
; i
> 0;)
404 res
= scm_cons (uvec_fast_ref (type
, elts
, i
), res
);
406 scm_array_handle_release (&handle
);
410 static SCM_C_INLINE SCM
411 uvec_length (int type
, SCM uvec
)
413 scm_t_array_handle handle
;
416 uvec_elements (type
, uvec
, &handle
, &len
, &inc
);
417 scm_array_handle_release (&handle
);
418 return scm_from_size_t (len
);
421 static SCM_C_INLINE SCM
422 uvec_ref (int type
, SCM uvec
, SCM idx
)
424 scm_t_array_handle handle
;
430 elts
= uvec_elements (type
, uvec
, &handle
, &len
, &inc
);
431 i
= scm_to_unsigned_integer (idx
, 0, len
-1);
432 res
= uvec_fast_ref (type
, elts
, i
*inc
);
433 scm_array_handle_release (&handle
);
437 static SCM_C_INLINE SCM
438 uvec_set_x (int type
, SCM uvec
, SCM idx
, SCM val
)
440 scm_t_array_handle handle
;
445 elts
= uvec_writable_elements (type
, uvec
, &handle
, &len
, &inc
);
446 i
= scm_to_unsigned_integer (idx
, 0, len
-1);
447 uvec_fast_set_x (type
, elts
, i
*inc
, val
);
448 scm_array_handle_release (&handle
);
449 return SCM_UNSPECIFIED
;
452 static SCM_C_INLINE SCM
453 list_to_uvec (int type
, SCM list
)
458 long len
= scm_ilength (list
);
460 scm_wrong_type_arg_msg (NULL
, 0, list
, "proper list");
462 uvec
= alloc_uvec (type
, len
);
463 base
= SCM_UVEC_BASE (uvec
);
465 while (scm_is_pair (list
) && idx
< len
)
467 uvec_fast_set_x (type
, base
, idx
, SCM_CAR (list
));
468 list
= SCM_CDR (list
);
475 coerce_to_uvec (int type
, SCM obj
)
477 if (is_uvec (type
, obj
))
479 else if (scm_is_pair (obj
))
480 return list_to_uvec (type
, obj
);
481 else if (scm_is_generalized_vector (obj
))
483 size_t len
= scm_c_generalized_vector_length (obj
), i
;
484 SCM uvec
= alloc_uvec (type
, len
);
485 void *base
= SCM_UVEC_BASE (uvec
);
486 for (i
= 0; i
< len
; i
++)
487 uvec_fast_set_x (type
, base
, i
, scm_c_generalized_vector_ref (obj
, i
));
491 scm_wrong_type_arg_msg (NULL
, 0, obj
, "list or generalized vector");
494 SCM_SYMBOL (scm_sym_a
, "a");
495 SCM_SYMBOL (scm_sym_b
, "b");
498 scm_i_generalized_vector_type (SCM v
)
500 if (scm_is_vector (v
))
502 else if (scm_is_string (v
))
504 else if (scm_is_bitvector (v
))
506 else if (scm_is_uniform_vector (v
))
507 return scm_from_locale_symbol (uvec_tags
[SCM_UVEC_TYPE(v
)]);
513 scm_is_uniform_vector (SCM obj
)
515 if (SCM_IS_UVEC (obj
))
517 if (SCM_ARRAYP (obj
) && SCM_ARRAY_NDIM (obj
) == 1)
519 SCM v
= SCM_ARRAY_V (obj
);
520 return SCM_IS_UVEC (v
);
526 scm_c_uniform_vector_length (SCM uvec
)
528 /* scm_generalized_vector_get_handle will ultimately call us to get
529 the length of uniform vectors, so we can't use uvec_elements for
533 if (SCM_IS_UVEC (uvec
))
534 return SCM_UVEC_LENGTH (uvec
);
537 scm_t_array_handle handle
;
540 uvec_elements (-1, uvec
, &handle
, &len
, &inc
);
541 scm_array_handle_release (&handle
);
546 SCM_DEFINE (scm_uniform_vector_p
, "uniform-vector?", 1, 0, 0,
548 "Return @code{#t} if @var{obj} is a uniform vector.")
549 #define FUNC_NAME s_scm_uniform_vector_p
551 return scm_from_bool (scm_is_uniform_vector (obj
));
556 scm_c_uniform_vector_ref (SCM v
, size_t idx
)
558 scm_t_array_handle handle
;
564 elts
= uvec_elements (-1, v
, &handle
, &len
, &inc
);
566 scm_out_of_range (NULL
, scm_from_size_t (idx
));
567 res
= uvec_fast_ref (SCM_UVEC_TYPE (v
), elts
, idx
*inc
);
568 scm_array_handle_release (&handle
);
572 SCM_DEFINE (scm_uniform_vector_ref
, "uniform-vector-ref", 2, 0, 0,
574 "Return the element at index @var{idx} of the\n"
575 "homogenous numeric vector @var{v}.")
576 #define FUNC_NAME s_scm_uniform_vector_ref
578 #if SCM_ENABLE_DEPRECATED
579 /* Support old argument convention.
581 if (scm_is_pair (idx
))
583 scm_c_issue_deprecation_warning
584 ("Using a list as the index to uniform-vector-ref is deprecated.");
585 if (!scm_is_null (SCM_CDR (idx
)))
586 scm_wrong_num_args (NULL
);
591 return scm_c_uniform_vector_ref (v
, scm_to_size_t (idx
));
596 scm_c_uniform_vector_set_x (SCM v
, size_t idx
, SCM val
)
598 scm_t_array_handle handle
;
603 elts
= uvec_writable_elements (-1, v
, &handle
, &len
, &inc
);
605 scm_out_of_range (NULL
, scm_from_size_t (idx
));
606 uvec_fast_set_x (SCM_UVEC_TYPE (v
), elts
, idx
*inc
, val
);
607 scm_array_handle_release (&handle
);
610 SCM_DEFINE (scm_uniform_vector_set_x
, "uniform-vector-set!", 3, 0, 0,
611 (SCM v
, SCM idx
, SCM val
),
612 "Set the element at index @var{idx} of the\n"
613 "homogenous numeric vector @var{v} to @var{val}.")
614 #define FUNC_NAME s_scm_uniform_vector_set_x
616 #if SCM_ENABLE_DEPRECATED
617 /* Support old argument convention.
619 if (scm_is_pair (idx
))
621 scm_c_issue_deprecation_warning
622 ("Using a list as the index to uniform-vector-set! is deprecated.");
623 if (!scm_is_null (SCM_CDR (idx
)))
624 scm_wrong_num_args (NULL
);
629 scm_c_uniform_vector_set_x (v
, scm_to_size_t (idx
), val
);
630 return SCM_UNSPECIFIED
;
634 SCM_DEFINE (scm_uniform_vector_to_list
, "uniform-vector->list", 1, 0, 0,
636 "Convert the homogeneous numeric vector @var{uvec} to a list.")
637 #define FUNC_NAME s_scm_uniform_vector_to_list
639 return uvec_to_list (-1, uvec
);
644 scm_array_handle_uniform_element_size (scm_t_array_handle
*h
)
647 if (SCM_ARRAYP (vec
))
648 vec
= SCM_ARRAY_V (vec
);
649 if (scm_is_uniform_vector (vec
))
650 return uvec_sizes
[SCM_UVEC_TYPE(vec
)];
651 scm_wrong_type_arg_msg (NULL
, 0, h
->array
, "uniform array");
654 /* return the size of an element in a uniform array or 0 if type not
657 scm_uniform_element_size (SCM obj
)
659 if (SCM_IS_UVEC (obj
))
660 return uvec_sizes
[SCM_UVEC_TYPE(obj
)];
666 scm_array_handle_uniform_elements (scm_t_array_handle
*h
)
668 return scm_array_handle_uniform_writable_elements (h
);
672 scm_array_handle_uniform_writable_elements (scm_t_array_handle
*h
)
675 if (SCM_ARRAYP (vec
))
676 vec
= SCM_ARRAY_V (vec
);
677 if (SCM_IS_UVEC (vec
))
679 size_t size
= uvec_sizes
[SCM_UVEC_TYPE(vec
)];
680 char *elts
= SCM_UVEC_BASE (vec
);
681 return (void *) (elts
+ size
*h
->base
);
683 scm_wrong_type_arg_msg (NULL
, 0, h
->array
, "uniform array");
687 scm_uniform_vector_elements (SCM uvec
,
688 scm_t_array_handle
*h
,
689 size_t *lenp
, ssize_t
*incp
)
691 return scm_uniform_vector_writable_elements (uvec
, h
, lenp
, incp
);
695 scm_uniform_vector_writable_elements (SCM uvec
,
696 scm_t_array_handle
*h
,
697 size_t *lenp
, ssize_t
*incp
)
699 scm_generalized_vector_get_handle (uvec
, h
);
702 scm_t_array_dim
*dim
= scm_array_handle_dims (h
);
703 *lenp
= dim
->ubnd
- dim
->lbnd
+ 1;
706 return scm_array_handle_uniform_writable_elements (h
);
709 SCM_DEFINE (scm_uniform_vector_length
, "uniform-vector-length", 1, 0, 0,
711 "Return the number of elements in the uniform vector @var{v}.")
712 #define FUNC_NAME s_scm_uniform_vector_length
714 return uvec_length (-1, v
);
718 SCM_DEFINE (scm_uniform_vector_read_x
, "uniform-vector-read!", 1, 3, 0,
719 (SCM uvec
, SCM port_or_fd
, SCM start
, SCM end
),
720 "Fill the elements of @var{uvec} by reading\n"
721 "raw bytes from @var{port-or-fdes}, using host byte order.\n\n"
722 "The optional arguments @var{start} (inclusive) and @var{end}\n"
723 "(exclusive) allow a specified region to be read,\n"
724 "leaving the remainder of the vector unchanged.\n\n"
725 "When @var{port-or-fdes} is a port, all specified elements\n"
726 "of @var{uvec} are attempted to be read, potentially blocking\n"
727 "while waiting formore input or end-of-file.\n"
728 "When @var{port-or-fd} is an integer, a single call to\n"
729 "read(2) is made.\n\n"
730 "An error is signalled when the last element has only\n"
731 "been partially filled before reaching end-of-file or in\n"
732 "the single call to read(2).\n\n"
733 "@code{uniform-vector-read!} returns the number of elements\n"
735 "@var{port-or-fdes} may be omitted, in which case it defaults\n"
736 "to the value returned by @code{(current-input-port)}.")
737 #define FUNC_NAME s_scm_uniform_vector_read_x
739 scm_t_array_handle handle
;
740 size_t vlen
, sz
, ans
;
743 size_t remaining
, off
;
746 if (SCM_UNBNDP (port_or_fd
))
747 port_or_fd
= scm_cur_inp
;
749 SCM_ASSERT (scm_is_integer (port_or_fd
)
750 || (SCM_OPINPORTP (port_or_fd
)),
751 port_or_fd
, SCM_ARG2
, FUNC_NAME
);
753 if (!scm_is_uniform_vector (uvec
))
754 scm_wrong_type_arg_msg (NULL
, 0, uvec
, "uniform vector");
756 base
= scm_uniform_vector_writable_elements (uvec
, &handle
, &vlen
, &inc
);
757 sz
= scm_array_handle_uniform_element_size (&handle
);
761 /* XXX - we should of course support non contiguous vectors. */
762 scm_misc_error (NULL
, "only contiguous vectors are supported: ~a",
768 if (!SCM_UNBNDP (start
))
770 cstart
= scm_to_unsigned_integer (start
, 0, vlen
);
771 if (!SCM_UNBNDP (end
))
772 cend
= scm_to_unsigned_integer (end
, cstart
, vlen
);
775 remaining
= (cend
- cstart
) * sz
;
778 if (SCM_NIMP (port_or_fd
))
780 scm_t_port
*pt
= SCM_PTAB_ENTRY (port_or_fd
);
782 if (pt
->rw_active
== SCM_PORT_WRITE
)
783 scm_flush (port_or_fd
);
786 while (remaining
> 0)
788 if (pt
->read_pos
< pt
->read_end
)
790 size_t to_copy
= min (pt
->read_end
- pt
->read_pos
,
793 memcpy (base
+ off
, pt
->read_pos
, to_copy
);
794 pt
->read_pos
+= to_copy
;
795 remaining
-= to_copy
;
800 if (scm_fill_input (port_or_fd
) == EOF
)
802 if (remaining
% sz
!= 0)
803 SCM_MISC_ERROR ("unexpected EOF", SCM_EOL
);
804 ans
-= remaining
/ sz
;
811 pt
->rw_active
= SCM_PORT_READ
;
813 else /* file descriptor. */
815 int fd
= scm_to_int (port_or_fd
);
818 SCM_SYSCALL (n
= read (fd
, base
+ off
, remaining
));
822 SCM_MISC_ERROR ("unexpected EOF", SCM_EOL
);
826 scm_array_handle_release (&handle
);
828 return scm_from_size_t (ans
);
832 SCM_DEFINE (scm_uniform_vector_write
, "uniform-vector-write", 1, 3, 0,
833 (SCM uvec
, SCM port_or_fd
, SCM start
, SCM end
),
834 "Write the elements of @var{uvec} as raw bytes to\n"
835 "@var{port-or-fdes}, in the host byte order.\n\n"
836 "The optional arguments @var{start} (inclusive)\n"
837 "and @var{end} (exclusive) allow\n"
838 "a specified region to be written.\n\n"
839 "When @var{port-or-fdes} is a port, all specified elements\n"
840 "of @var{uvec} are attempted to be written, potentially blocking\n"
841 "while waiting for more room.\n"
842 "When @var{port-or-fd} is an integer, a single call to\n"
843 "write(2) is made.\n\n"
844 "An error is signalled when the last element has only\n"
845 "been partially written in the single call to write(2).\n\n"
846 "The number of objects actually written is returned.\n"
847 "@var{port-or-fdes} may be\n"
848 "omitted, in which case it defaults to the value returned by\n"
849 "@code{(current-output-port)}.")
850 #define FUNC_NAME s_scm_uniform_vector_write
852 scm_t_array_handle handle
;
853 size_t vlen
, sz
, ans
;
859 port_or_fd
= SCM_COERCE_OUTPORT (port_or_fd
);
861 if (SCM_UNBNDP (port_or_fd
))
862 port_or_fd
= scm_cur_outp
;
864 SCM_ASSERT (scm_is_integer (port_or_fd
)
865 || (SCM_OPOUTPORTP (port_or_fd
)),
866 port_or_fd
, SCM_ARG2
, FUNC_NAME
);
868 base
= scm_uniform_vector_elements (uvec
, &handle
, &vlen
, &inc
);
869 sz
= scm_array_handle_uniform_element_size (&handle
);
873 /* XXX - we should of course support non contiguous vectors. */
874 scm_misc_error (NULL
, "only contiguous vectors are supported: ~a",
880 if (!SCM_UNBNDP (start
))
882 cstart
= scm_to_unsigned_integer (start
, 0, vlen
);
883 if (!SCM_UNBNDP (end
))
884 cend
= scm_to_unsigned_integer (end
, cstart
, vlen
);
887 amount
= (cend
- cstart
) * sz
;
890 if (SCM_NIMP (port_or_fd
))
892 scm_lfwrite (base
+ off
, amount
, port_or_fd
);
895 else /* file descriptor. */
897 int fd
= scm_to_int (port_or_fd
), n
;
898 SCM_SYSCALL (n
= write (fd
, base
+ off
, amount
));
902 SCM_MISC_ERROR ("last element only written partially", SCM_EOL
);
906 scm_array_handle_release (&handle
);
908 return scm_from_size_t (ans
);
912 /* ================================================================ */
913 /* Exported procedures. */
914 /* ================================================================ */
916 #define TYPE SCM_UVEC_U8
918 #define CTYPE scm_t_uint8
919 #include "libguile/srfi-4.i.c"
921 #define TYPE SCM_UVEC_S8
923 #define CTYPE scm_t_int8
924 #include "libguile/srfi-4.i.c"
926 #define TYPE SCM_UVEC_U16
928 #define CTYPE scm_t_uint16
929 #include "libguile/srfi-4.i.c"
931 #define TYPE SCM_UVEC_S16
933 #define CTYPE scm_t_int16
934 #include "libguile/srfi-4.i.c"
936 #define TYPE SCM_UVEC_U32
938 #define CTYPE scm_t_uint32
939 #include "libguile/srfi-4.i.c"
941 #define TYPE SCM_UVEC_S32
943 #define CTYPE scm_t_int32
944 #include "libguile/srfi-4.i.c"
946 #define TYPE SCM_UVEC_U64
948 #define CTYPE scm_t_uint64
949 #include "libguile/srfi-4.i.c"
951 #define TYPE SCM_UVEC_S64
953 #define CTYPE scm_t_int64
954 #include "libguile/srfi-4.i.c"
956 #define TYPE SCM_UVEC_F32
959 #include "libguile/srfi-4.i.c"
961 #define TYPE SCM_UVEC_F64
964 #include "libguile/srfi-4.i.c"
966 #define TYPE SCM_UVEC_C32
969 #include "libguile/srfi-4.i.c"
971 #define TYPE SCM_UVEC_C64
974 #include "libguile/srfi-4.i.c"
977 scm_init_srfi_4 (void)
979 scm_tc16_uvec
= scm_make_smob_type ("uvec", 0);
980 scm_set_smob_equalp (scm_tc16_uvec
, uvec_equalp
);
981 scm_set_smob_free (scm_tc16_uvec
, uvec_free
);
982 scm_set_smob_print (scm_tc16_uvec
, uvec_print
);
984 #include "libguile/srfi-4.x"
988 /* End of srfi-4.c. */