*** empty log message ***
[bpt/guile.git] / libguile / srfi-4.c
CommitLineData
f8579182
MV
1/* srfi-4.c --- Homogeneous numeric vector datatypes.
2 *
3 * Copyright (C) 2001, 2004 Free Software Foundation, Inc.
4 *
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.
9 *
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.
14 *
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
18 */
19
20#include <libguile.h>
21#include <string.h>
22#include <stdio.h>
23
24#include "libguile/srfi-4.h"
25#include "libguile/error.h"
26#include "libguile/read.h"
27#include "libguile/ports.h"
28#include "libguile/chars.h"
29
30/* Smob type code for homogeneous numeric vectors. */
31int scm_tc16_uvec = 0;
32
33
34/* Accessor macros for the three components of a homogeneous numeric
35 vector:
36 - The type tag (one of the symbolic constants below).
37 - The vector's length (counted in elements).
38 - The address of the data area (holding the elements of the
39 vector). */
40#define SCM_UVEC_TYPE(u) (SCM_CELL_WORD_1(u))
41#define SCM_UVEC_LENGTH(u) ((size_t)SCM_CELL_WORD_2(u))
42#define SCM_UVEC_BASE(u) ((void *)SCM_CELL_WORD_3(u))
43
44
45/* Symbolic constants encoding the various types of homogeneous
46 numeric vectors. */
47#define SCM_UVEC_U8 0
48#define SCM_UVEC_S8 1
49#define SCM_UVEC_U16 2
50#define SCM_UVEC_S16 3
51#define SCM_UVEC_U32 4
52#define SCM_UVEC_S32 5
53#define SCM_UVEC_U64 6
54#define SCM_UVEC_S64 7
55#define SCM_UVEC_F32 8
56#define SCM_UVEC_F64 9
cbdc8379
MV
57#define SCM_UVEC_C32 10
58#define SCM_UVEC_C64 11
f8579182
MV
59
60
61/* This array maps type tags to the size of the elements. */
cbdc8379 62static const int uvec_sizes[12] = {
f8579182
MV
63 1, 1,
64 2, 2,
65 4, 4,
66 8, 8,
cbdc8379
MV
67 sizeof(float), sizeof(double),
68 2*sizeof(float), 2*sizeof(double)
f8579182
MV
69};
70
cbdc8379 71static const char *uvec_tags[12] = {
e0e49670
MV
72 "u8", "s8",
73 "u16", "s16",
74 "u32", "s32",
75 "u64", "s64",
cbdc8379
MV
76 "f32", "f64",
77 "c32", "c64",
e0e49670
MV
78};
79
cbdc8379 80static const char *uvec_names[12] = {
f8579182
MV
81 "u8vector", "s8vector",
82 "u16vector", "s16vector",
83 "u32vector", "s32vector",
84 "u64vector", "s64vector",
cbdc8379
MV
85 "f32vector", "f64vector",
86 "c32vector", "c64vector"
f8579182
MV
87};
88
89/* ================================================================ */
90/* SMOB procedures. */
91/* ================================================================ */
92
93
94/* Smob print hook for homogeneous vectors. */
95static int
96uvec_print (SCM uvec, SCM port, scm_print_state *pstate)
97{
98 union {
99 scm_t_uint8 *u8;
100 scm_t_int8 *s8;
101 scm_t_uint16 *u16;
102 scm_t_int16 *s16;
103 scm_t_uint32 *u32;
104 scm_t_int32 *s32;
105#if SCM_HAVE_T_INT64
106 scm_t_uint64 *u64;
107 scm_t_int64 *s64;
108#endif
109 float *f32;
110 double *f64;
111 } np;
112
113 size_t i = 0;
114 const size_t uvlen = SCM_UVEC_LENGTH (uvec);
f8579182
MV
115 void *uptr = SCM_UVEC_BASE (uvec);
116
117 switch (SCM_UVEC_TYPE (uvec))
118 {
e0e49670
MV
119 case SCM_UVEC_U8: np.u8 = (scm_t_uint8 *) uptr; break;
120 case SCM_UVEC_S8: np.s8 = (scm_t_int8 *) uptr; break;
121 case SCM_UVEC_U16: np.u16 = (scm_t_uint16 *) uptr; break;
122 case SCM_UVEC_S16: np.s16 = (scm_t_int16 *) uptr; break;
123 case SCM_UVEC_U32: np.u32 = (scm_t_uint32 *) uptr; break;
124 case SCM_UVEC_S32: np.s32 = (scm_t_int32 *) uptr; break;
f8579182 125#if SCM_HAVE_T_INT64
e0e49670
MV
126 case SCM_UVEC_U64: np.u64 = (scm_t_uint64 *) uptr; break;
127 case SCM_UVEC_S64: np.s64 = (scm_t_int64 *) uptr; break;
f8579182 128#endif
e0e49670
MV
129 case SCM_UVEC_F32: np.f32 = (float *) uptr; break;
130 case SCM_UVEC_F64: np.f64 = (double *) uptr; break;
cbdc8379
MV
131 case SCM_UVEC_C32: np.f32 = (float *) uptr; break;
132 case SCM_UVEC_C64: np.f64 = (double *) uptr; break;
f8579182
MV
133 default:
134 abort (); /* Sanity check. */
135 break;
136 }
137
138 scm_putc ('#', port);
e0e49670 139 scm_puts (uvec_tags [SCM_UVEC_TYPE (uvec)], port);
f8579182
MV
140 scm_putc ('(', port);
141
142 while (i < uvlen)
143 {
144 if (i != 0) scm_puts (" ", port);
145 switch (SCM_UVEC_TYPE (uvec))
146 {
147 case SCM_UVEC_U8: scm_uintprint (*np.u8, 10, port); np.u8++; break;
148 case SCM_UVEC_S8: scm_intprint (*np.s8, 10, port); np.s8++; break;
149 case SCM_UVEC_U16: scm_uintprint (*np.u16, 10, port); np.u16++; break;
150 case SCM_UVEC_S16: scm_intprint (*np.s16, 10, port); np.s16++; break;
151 case SCM_UVEC_U32: scm_uintprint (*np.u32, 10, port); np.u32++; break;
152 case SCM_UVEC_S32: scm_intprint (*np.s32, 10, port); np.s32++; break;
153#if SCM_HAVE_T_INT64
154 case SCM_UVEC_U64: scm_uintprint (*np.u64, 10, port); np.u64++; break;
155 case SCM_UVEC_S64: scm_intprint (*np.s64, 10, port); np.s64++; break;
156#endif
157 case SCM_UVEC_F32: scm_i_print_double (*np.f32, port); np.f32++; break;
158 case SCM_UVEC_F64: scm_i_print_double (*np.f64, port); np.f64++; break;
cbdc8379
MV
159 case SCM_UVEC_C32:
160 scm_i_print_complex (np.f32[0], np.f32[1], port);
161 np.f32 += 2;
162 break;
163 case SCM_UVEC_C64:
164 scm_i_print_complex (np.f64[0], np.f64[1], port);
165 np.f64 += 2;
166 break;
f8579182
MV
167 default:
168 abort (); /* Sanity check. */
169 break;
170 }
171 i++;
172 }
173 scm_remember_upto_here_1 (uvec);
174 scm_puts (")", port);
175 return 1;
176}
177
e0e49670
MV
178const char *
179scm_i_uniform_vector_tag (SCM uvec)
180{
181 return uvec_tags[SCM_UVEC_TYPE (uvec)];
182}
183
f8579182
MV
184static SCM
185uvec_equalp (SCM a, SCM b)
186{
187 SCM result = SCM_BOOL_T;
188 if (SCM_UVEC_TYPE (a) != SCM_UVEC_TYPE (b))
189 result = SCM_BOOL_F;
190 else if (SCM_UVEC_LENGTH (a) != SCM_UVEC_LENGTH (b))
191 result = SCM_BOOL_F;
192 else if (memcmp (SCM_UVEC_BASE (a), SCM_UVEC_BASE (b),
193 SCM_UVEC_LENGTH (a) * uvec_sizes[SCM_UVEC_TYPE(a)]) != 0)
194 result = SCM_BOOL_F;
195
196 scm_remember_upto_here_2 (a, b);
197 return result;
198}
199
200/* Smob free hook for homogeneous numeric vectors. */
201static size_t
202uvec_free (SCM uvec)
203{
204 int type = SCM_UVEC_TYPE (uvec);
205 scm_gc_free (SCM_UVEC_BASE (uvec),
206 SCM_UVEC_LENGTH (uvec) * uvec_sizes[type],
207 uvec_names[type]);
208 return 0;
209}
210
211/* ================================================================ */
212/* Utility procedures. */
213/* ================================================================ */
214
215static SCM_C_INLINE int
216is_uvec (int type, SCM obj)
217{
218 return (SCM_SMOB_PREDICATE (scm_tc16_uvec, obj)
219 && SCM_UVEC_TYPE (obj) == type);
220}
221
222static SCM_C_INLINE SCM
223uvec_p (int type, SCM obj)
224{
225 return scm_from_bool (is_uvec (type, obj));
226}
227
228static SCM_C_INLINE void
229uvec_assert (int type, SCM obj)
230{
231 if (!is_uvec (type, obj))
232 scm_wrong_type_arg_msg (NULL, 0, obj, uvec_names[type]);
233}
234
faa00365
MV
235static SCM
236take_uvec (int type, const void *base, size_t len)
237{
238 SCM_RETURN_NEWSMOB3 (scm_tc16_uvec, type, len, (scm_t_bits) base);
239}
240
f8579182
MV
241/* Create a new, uninitialized homogeneous numeric vector of type TYPE
242 with space for LEN elements. */
243static SCM
faa00365 244alloc_uvec (int type, size_t len)
f8579182 245{
811eb6d0
MV
246 void *base;
247 if (len > SCM_I_SIZE_MAX / uvec_sizes[type])
248 scm_out_of_range (NULL, scm_from_size_t (len));
249 base = scm_gc_malloc (len * uvec_sizes[type], uvec_names[type]);
faa00365 250 return take_uvec (type, base, len);
f8579182
MV
251}
252
253/* GCC doesn't seem to want to optimize unused switch clauses away,
254 so we use a big 'if' in the next two functions.
255*/
256
257static SCM_C_INLINE SCM
258uvec_fast_ref (int type, void *base, size_t c_idx)
259{
260 if (type == SCM_UVEC_U8)
261 return scm_from_uint8 (((scm_t_uint8*)base)[c_idx]);
262 else if (type == SCM_UVEC_S8)
263 return scm_from_int8 (((scm_t_int8*)base)[c_idx]);
264 else if (type == SCM_UVEC_U16)
265 return scm_from_uint16 (((scm_t_uint16*)base)[c_idx]);
266 else if (type == SCM_UVEC_S16)
267 return scm_from_int16 (((scm_t_int16*)base)[c_idx]);
268 else if (type == SCM_UVEC_U32)
269 return scm_from_uint32 (((scm_t_uint32*)base)[c_idx]);
270 else if (type == SCM_UVEC_S32)
271 return scm_from_int32 (((scm_t_int32*)base)[c_idx]);
272#if SCM_HAVE_T_INT64
273 else if (type == SCM_UVEC_U64)
274 return scm_from_uint64 (((scm_t_uint64*)base)[c_idx]);
275 else if (type == SCM_UVEC_S64)
276 return scm_from_int64 (((scm_t_int64*)base)[c_idx]);
277#endif
278 else if (type == SCM_UVEC_F32)
279 return scm_from_double (((float*)base)[c_idx]);
280 else if (type == SCM_UVEC_F64)
281 return scm_from_double (((double*)base)[c_idx]);
cbdc8379
MV
282 else if (type == SCM_UVEC_C32)
283 return scm_c_make_rectangular (((float*)base)[2*c_idx],
284 ((float*)base)[2*c_idx+1]);
285 else if (type == SCM_UVEC_C64)
286 return scm_c_make_rectangular (((double*)base)[2*c_idx],
287 ((double*)base)[2*c_idx+1]);
28d4aef1
MV
288 else
289 return SCM_BOOL_F;
f8579182
MV
290}
291
292static SCM_C_INLINE void
293uvec_fast_set_x (int type, void *base, size_t c_idx, SCM val)
294{
295 if (type == SCM_UVEC_U8)
296 (((scm_t_uint8*)base)[c_idx]) = scm_to_uint8 (val);
297 else if (type == SCM_UVEC_S8)
298 (((scm_t_int8*)base)[c_idx]) = scm_to_int8 (val);
299 else if (type == SCM_UVEC_U16)
300 (((scm_t_uint16*)base)[c_idx]) = scm_to_uint16 (val);
301 else if (type == SCM_UVEC_S16)
302 (((scm_t_int16*)base)[c_idx]) = scm_to_int16 (val);
303 else if (type == SCM_UVEC_U32)
304 (((scm_t_uint32*)base)[c_idx]) = scm_to_uint32 (val);
305 else if (type == SCM_UVEC_S32)
306 (((scm_t_int32*)base)[c_idx]) = scm_to_int32 (val);
307#if SCM_HAVE_T_INT64
308 else if (type == SCM_UVEC_U64)
309 (((scm_t_uint64*)base)[c_idx]) = scm_to_uint64 (val);
310 else if (type == SCM_UVEC_S64)
311 (((scm_t_int64*)base)[c_idx]) = scm_to_int64 (val);
312#endif
313 else if (type == SCM_UVEC_F32)
314 (((float*)base)[c_idx]) = scm_to_double (val);
315 else if (type == SCM_UVEC_F64)
316 (((double*)base)[c_idx]) = scm_to_double (val);
cbdc8379
MV
317 else if (type == SCM_UVEC_C32)
318 {
319 (((float*)base)[2*c_idx]) = scm_c_real_part (val);
320 (((float*)base)[2*c_idx+1]) = scm_c_imag_part (val);
321 }
322 else if (type == SCM_UVEC_C64)
323 {
324 (((double*)base)[2*c_idx]) = scm_c_real_part (val);
325 (((double*)base)[2*c_idx+1]) = scm_c_imag_part (val);
326 }
f8579182
MV
327}
328
329static SCM_C_INLINE SCM
330make_uvec (int type, SCM len, SCM fill)
331{
811eb6d0 332 size_t c_len = scm_to_size_t (len);
f8579182
MV
333 SCM uvec = alloc_uvec (type, c_len);
334 if (!SCM_UNBNDP (fill))
335 {
336 size_t idx;
337 void *base = SCM_UVEC_BASE (uvec);
338 for (idx = 0; idx < c_len; idx++)
339 uvec_fast_set_x (type, base, idx, fill);
340 }
341 return uvec;
342}
343
344static SCM_C_INLINE SCM
345uvec_length (int type, SCM uvec)
346{
347 uvec_assert (type, uvec);
348 return scm_from_size_t (SCM_UVEC_LENGTH (uvec));
349}
350
351static SCM_C_INLINE SCM
352uvec_ref (int type, SCM uvec, SCM idx)
353{
354 size_t c_idx;
355 SCM res;
356
357 uvec_assert (type, uvec);
358 c_idx = scm_to_unsigned_integer (idx, 0, SCM_UVEC_LENGTH (uvec)-1);
359 res = uvec_fast_ref (type, SCM_UVEC_BASE(uvec), c_idx);
360 scm_remember_upto_here_1 (uvec);
361 return res;
362}
363
364static SCM_C_INLINE SCM
365uvec_set_x (int type, SCM uvec, SCM idx, SCM val)
366{
367 size_t c_idx;
368
369 uvec_assert (type, uvec);
370 c_idx = scm_to_unsigned_integer (idx, 0, SCM_UVEC_LENGTH (uvec)-1);
371 uvec_fast_set_x (type, SCM_UVEC_BASE(uvec), c_idx, val);
372 scm_remember_upto_here_1 (uvec);
373 return SCM_UNSPECIFIED;
374}
375
376static SCM_C_INLINE SCM
377uvec_to_list (int type, SCM uvec)
378{
379 size_t c_idx;
380 void *base;
381 SCM res = SCM_EOL;
382
383 uvec_assert (type, uvec);
384 c_idx = SCM_UVEC_LENGTH (uvec);
385 base = SCM_UVEC_BASE (uvec);
386 while (c_idx-- > 0)
387 res = scm_cons (uvec_fast_ref (type, base, c_idx), res);
388 scm_remember_upto_here_1 (uvec);
389 return res;
390}
391
392static SCM_C_INLINE SCM
393list_to_uvec (int type, SCM list)
394{
395 SCM uvec;
396 void *base;
397 long idx;
398 long len = scm_ilength (list);
399 if (len < 0)
400 scm_wrong_type_arg_msg (NULL, 0, list, "proper list");
401
402 uvec = alloc_uvec (type, len);
403 base = SCM_UVEC_BASE (uvec);
404 idx = 0;
405 while (scm_is_pair (list) && idx < len)
406 {
407 uvec_fast_set_x (type, base, idx, SCM_CAR (list));
408 list = SCM_CDR (list);
409 idx++;
410 }
411 return uvec;
412}
413
90d4368c
MV
414static SCM
415coerce_to_uvec (int type, SCM obj)
416{
417 if (is_uvec (type, obj))
418 return obj;
419 else if (scm_is_pair (obj))
420 return list_to_uvec (type, obj);
811eb6d0 421 else if (scm_is_generalized_vector (obj))
90d4368c 422 {
811eb6d0
MV
423 size_t len = scm_c_generalized_vector_length (obj), i;
424 SCM uvec = alloc_uvec (type, len);
90d4368c 425 void *base = SCM_UVEC_BASE (uvec);
811eb6d0
MV
426 for (i = 0; i < len; i++)
427 uvec_fast_set_x (type, base, i, scm_c_generalized_vector_ref (obj, i));
90d4368c
MV
428 return uvec;
429 }
430 else
811eb6d0 431 scm_wrong_type_arg_msg (NULL, 0, obj, "list or generalized vector");
90d4368c
MV
432}
433
cbdc8379
MV
434static SCM *uvec_proc_vars[12] = {
435 &scm_i_proc_make_u8vector,
436 &scm_i_proc_make_s8vector,
437 &scm_i_proc_make_u16vector,
438 &scm_i_proc_make_s16vector,
439 &scm_i_proc_make_u32vector,
440 &scm_i_proc_make_s32vector,
441 &scm_i_proc_make_u64vector,
442 &scm_i_proc_make_s64vector,
443 &scm_i_proc_make_f32vector,
444 &scm_i_proc_make_f64vector,
445 &scm_i_proc_make_c32vector,
446 &scm_i_proc_make_c64vector
447};
f8579182 448
e0e49670 449SCM
811eb6d0 450scm_i_generalized_vector_creator (SCM v)
e0e49670 451{
811eb6d0
MV
452 if (scm_is_vector (v))
453 return scm_i_proc_make_vector;
454 else if (scm_is_string (v))
455 return scm_i_proc_make_string;
456 else if (scm_is_bitvector (v))
457 return scm_i_proc_make_bitvector;
458 else if (scm_is_uniform_vector (v))
459 return *(uvec_proc_vars[SCM_UVEC_TYPE(v)]);
460 else
461 return SCM_BOOL_F;
e0e49670
MV
462}
463
464int
465scm_is_uniform_vector (SCM obj)
466{
467 return SCM_SMOB_PREDICATE (scm_tc16_uvec, obj);
468}
469
470size_t
471scm_c_uniform_vector_length (SCM v)
472{
473 if (scm_is_uniform_vector (v))
474 return SCM_UVEC_LENGTH (v);
475 else
476 scm_wrong_type_arg_msg (NULL, 0, v, "uniform vector");
477}
478
479size_t
480scm_c_uniform_vector_size (SCM v)
481{
482 if (scm_is_uniform_vector (v))
483 return SCM_UVEC_LENGTH (v) * uvec_sizes[SCM_UVEC_TYPE (v)];
484 else
485 scm_wrong_type_arg_msg (NULL, 0, v, "uniform vector");
486}
487
488SCM_DEFINE (scm_uniform_vector_p, "uniform-vector?", 1, 0, 0,
489 (SCM obj),
490 "Return @code{#t} if @var{obj} is a uniform vector.")
491#define FUNC_NAME s_scm_uniform_vector_p
492{
493 return scm_from_bool (scm_is_uniform_vector (obj));
494}
495#undef FUNC_NAME
496
497SCM_DEFINE (scm_uniform_vector_ref, "uniform-vector-ref", 2, 0, 0,
498 (SCM v, SCM idx),
499 "Return the element at index @var{idx} of the\n"
500 "homogenous numeric vector @var{v}.")
501#define FUNC_NAME s_scm_uniform_vector_ref
502{
503 /* Support old argument convention.
504 */
505 if (scm_is_pair (idx))
506 {
507 if (!scm_is_null (SCM_CDR (idx)))
508 scm_wrong_num_args (NULL);
509 idx = SCM_CAR (idx);
510 }
511
512 if (scm_is_uniform_vector (v))
513 return uvec_ref (SCM_UVEC_TYPE (v), v, idx);
514 else
515 scm_wrong_type_arg_msg (NULL, 0, v, "uniform vector");
516}
517#undef FUNC_NAME
518
811eb6d0
MV
519SCM
520scm_c_uniform_vector_ref (SCM v, size_t idx)
521{
522 if (scm_is_uniform_vector (v))
523 {
524 if (idx < SCM_UVEC_LENGTH (v))
525 return uvec_fast_ref (SCM_UVEC_TYPE (v), SCM_UVEC_BASE (v), idx);
526 else
527 scm_out_of_range (NULL, scm_from_size_t (idx));
528 }
529 else
530 scm_wrong_type_arg_msg (NULL, 0, v, "uniform vector");
531}
532
e0e49670
MV
533SCM_DEFINE (scm_uniform_vector_set_x, "uniform-vector-set!", 3, 0, 0,
534 (SCM v, SCM idx, SCM val),
535 "Set the element at index @var{idx} of the\n"
536 "homogenous numeric vector @var{v} to @var{val}.")
537#define FUNC_NAME s_scm_uniform_vector_set_x
538{
539 /* Support old argument convention.
540 */
541 if (scm_is_pair (idx))
542 {
543 if (!scm_is_null (SCM_CDR (idx)))
544 scm_wrong_num_args (NULL);
545 idx = SCM_CAR (idx);
546 }
547
548 if (scm_is_uniform_vector (v))
549 return uvec_set_x (SCM_UVEC_TYPE (v), v, idx, val);
550 else
551 scm_wrong_type_arg_msg (NULL, 0, v, "uniform vector");
552}
553#undef FUNC_NAME
554
811eb6d0
MV
555void
556scm_c_uniform_vector_set_x (SCM v, size_t idx, SCM val)
557{
558 if (scm_is_uniform_vector (v))
559 {
560 if (idx < SCM_UVEC_LENGTH (v))
561 uvec_fast_set_x (SCM_UVEC_TYPE (v), SCM_UVEC_BASE (v), idx, val);
562 else
563 scm_out_of_range (NULL, scm_from_size_t (idx));
564 }
565 else
566 scm_wrong_type_arg_msg (NULL, 0, v, "uniform vector");
567}
568
e0e49670
MV
569SCM_DEFINE (scm_uniform_vector_to_list, "uniform-vector->list", 1, 0, 0,
570 (SCM uvec),
571 "Convert the homogeneous numeric vector @var{uvec} to a list.")
811eb6d0 572#define FUNC_NAME s_scm_uniform_vector_to_list
e0e49670
MV
573{
574 if (scm_is_uniform_vector (uvec))
575 return uvec_to_list (SCM_UVEC_TYPE (uvec), uvec);
576 else
577 scm_wrong_type_arg_msg (NULL, 0, uvec, "uniform vector");
578}
579#undef FUNC_NAME
580
581void *
582scm_uniform_vector_elements (SCM uvec)
583{
584 if (scm_is_uniform_vector (uvec))
585 return SCM_UVEC_BASE (uvec);
586 else
587 scm_wrong_type_arg_msg (NULL, 0, uvec, "uniform vector");
588}
589
590void
591scm_uniform_vector_release (SCM uvec)
592{
593 /* Nothing to do right now, but this function might come in handy
594 when uniform vectors need to be locked when giving away a pointer
595 to their elements.
faa00365 596
811eb6d0 597 Also, a call to scm_uniform_vector_release acts like
faa00365 598 scm_remember_upto_here, which is needed in any case.
e0e49670
MV
599 */
600}
601
d44ff083
MV
602void
603scm_frame_uniform_vector_release (SCM uvec)
604{
605 scm_frame_unwind_handler_with_scm (scm_uniform_vector_release, uvec,
606 SCM_F_WIND_EXPLICITLY);
607}
608
e0e49670
MV
609size_t
610scm_uniform_vector_element_size (SCM uvec)
611{
612 if (scm_is_uniform_vector (uvec))
613 return uvec_sizes[SCM_UVEC_TYPE (uvec)];
614 else
615 scm_wrong_type_arg_msg (NULL, 0, uvec, "uniform vector");
616}
617
618/* return the size of an element in a uniform array or 0 if type not
619 found. */
620size_t
621scm_uniform_element_size (SCM obj)
622{
e0e49670
MV
623 if (scm_is_uniform_vector (obj))
624 return scm_uniform_vector_element_size (obj);
90d4368c
MV
625 else
626 return 0;
e0e49670
MV
627}
628
629SCM_DEFINE (scm_uniform_vector_length, "uniform-vector-length", 1, 0, 0,
630 (SCM v),
811eb6d0 631 "Return the number of elements in the uniform vector @var{v}.")
e0e49670
MV
632#define FUNC_NAME s_scm_uniform_vector_length
633{
811eb6d0 634 return scm_from_size_t (scm_c_uniform_vector_length (v));
e0e49670
MV
635}
636#undef FUNC_NAME
637
f8579182
MV
638/* ================================================================ */
639/* Exported procedures. */
640/* ================================================================ */
641
e0e49670
MV
642#define TYPE SCM_UVEC_U8
643#define TAG u8
644#define CTYPE scm_t_uint8
f8579182
MV
645#include "libguile/srfi-4.i.c"
646
e0e49670
MV
647#define TYPE SCM_UVEC_S8
648#define TAG s8
649#define CTYPE scm_t_int8
f8579182
MV
650#include "libguile/srfi-4.i.c"
651
e0e49670
MV
652#define TYPE SCM_UVEC_U16
653#define TAG u16
654#define CTYPE scm_t_uint16
f8579182
MV
655#include "libguile/srfi-4.i.c"
656
e0e49670
MV
657#define TYPE SCM_UVEC_S16
658#define TAG s16
659#define CTYPE scm_t_int16
f8579182
MV
660#include "libguile/srfi-4.i.c"
661
e0e49670
MV
662#define TYPE SCM_UVEC_U32
663#define TAG u32
664#define CTYPE scm_t_uint32
f8579182
MV
665#include "libguile/srfi-4.i.c"
666
e0e49670
MV
667#define TYPE SCM_UVEC_S32
668#define TAG s32
669#define CTYPE scm_t_int32
f8579182
MV
670#include "libguile/srfi-4.i.c"
671
e0e49670
MV
672#define TYPE SCM_UVEC_U64
673#define TAG u64
674#define CTYPE scm_t_uint64
f8579182
MV
675#include "libguile/srfi-4.i.c"
676
e0e49670
MV
677#define TYPE SCM_UVEC_S64
678#define TAG s64
679#define CTYPE scm_t_int64
f8579182
MV
680#include "libguile/srfi-4.i.c"
681
e0e49670
MV
682#define TYPE SCM_UVEC_F32
683#define TAG f32
684#define CTYPE float
f8579182
MV
685#include "libguile/srfi-4.i.c"
686
e0e49670
MV
687#define TYPE SCM_UVEC_F64
688#define TAG f64
689#define CTYPE double
f8579182
MV
690#include "libguile/srfi-4.i.c"
691
cbdc8379
MV
692#define TYPE SCM_UVEC_C32
693#define TAG c32
694#define CTYPE float
695#include "libguile/srfi-4.i.c"
696
697#define TYPE SCM_UVEC_C64
698#define TAG c64
699#define CTYPE double
700#include "libguile/srfi-4.i.c"
701
702SCM scm_i_proc_make_u8vector;
703SCM scm_i_proc_make_s8vector;
704SCM scm_i_proc_make_u16vector;
705SCM scm_i_proc_make_s16vector;
706SCM scm_i_proc_make_u32vector;
707SCM scm_i_proc_make_s32vector;
708SCM scm_i_proc_make_u64vector;
709SCM scm_i_proc_make_s64vector;
710SCM scm_i_proc_make_f32vector;
711SCM scm_i_proc_make_f64vector;
712SCM scm_i_proc_make_c32vector;
713SCM scm_i_proc_make_c64vector;
f8579182
MV
714
715/* Create the smob type for homogeneous numeric vectors and install
716 the primitives. */
717void
718scm_init_srfi_4 (void)
719{
720 scm_tc16_uvec = scm_make_smob_type ("uvec", 0);
721 scm_set_smob_equalp (scm_tc16_uvec, uvec_equalp);
722 scm_set_smob_free (scm_tc16_uvec, uvec_free);
723 scm_set_smob_print (scm_tc16_uvec, uvec_print);
724#include "libguile/srfi-4.x"
cbdc8379
MV
725
726#define GETPROC(tag) \
727 scm_i_proc_make_##tag##vector = \
728 scm_variable_ref (scm_c_lookup ("make-"#tag"vector"))
729
730 GETPROC (u8);
731 GETPROC (s8);
732 GETPROC (u16);
733 GETPROC (s16);
734 GETPROC (u32);
735 GETPROC (s32);
736 GETPROC (u64);
737 GETPROC (s64);
738 GETPROC (f32);
739 GETPROC (f64);
740 GETPROC (c32);
741 GETPROC (c64);
f8579182
MV
742}
743
744/* End of srfi-4.c. */