/* srfi-4.c --- Homogeneous numeric vector datatypes. * * Copyright (C) 2001, 2004 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * As a special exception, the Free Software Foundation gives * permission for additional uses of the text contained in its release * of GUILE. * * The exception is that, if you link the GUILE library with other * files to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the GUILE library code into it. * * This exception does not however invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * This exception applies only to the code released by the Free * Software Foundation under the name GUILE. If you copy code from * other Free Software Foundation releases into a copy of GUILE, as * the General Public License permits, the exception does not apply to * the code that you add in this way. To avoid misleading anyone as * to the status of such modified files, you must delete this * exception notice from them. * * If you write modifications of your own for GUILE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. */ #include #include "srfi-4.h" #include #include /* For brevity and maintainability, we define our own types for the various integer and floating point types. */ typedef unsigned char int_u8; typedef signed char int_s8; typedef unsigned short int_u16; typedef signed short int_s16; typedef unsigned int int_u32; typedef signed int int_s32; #if SIZEOF_LONG == 8 typedef unsigned long int_u64; typedef signed long int_s64; #define HAVE_UVEC_64 1 #elif SIZEOF_LONG_LONG == 8 typedef unsigned long long int_u64; typedef signed long long int_s64; #define HAVE_UVEC_64 1 #else #define HAVE_UVEC_64 0 #endif /* no 64-bit integer support */ typedef float float_f32; typedef double float_f64; /* Smob type code for homogeneous numeric vectors. */ int scm_tc16_uvec = 0; /* Accessor macros for the three components of a homogeneous numeric vector: - The type tag (one of the symbolic constants below). - The vector's length (counted in elements). - The address of the data area (holding the elements of the vector). */ #define SCM_UVEC_TYPE(u) (SCM_CELL_WORD_1(u)) #define SCM_UVEC_LENGTH(u) (SCM_CELL_WORD_2(u)) #define SCM_UVEC_BASE(u) (SCM_CELL_OBJECT_3(u)) /* Symbolic constants encoding the various types of homogeneous numeric vectors. */ #define SCM_UVEC_U8 0 #define SCM_UVEC_S8 1 #define SCM_UVEC_U16 2 #define SCM_UVEC_S16 3 #define SCM_UVEC_U32 4 #define SCM_UVEC_S32 5 #define SCM_UVEC_U64 6 #define SCM_UVEC_S64 7 #define SCM_UVEC_F32 8 #define SCM_UVEC_F64 9 #define VALIDATE_UVEC(pos, obj, type) \ do { \ SCM_VALIDATE_SMOB (pos, obj, uvec); \ if (SCM_UVEC_TYPE (obj) != type) \ scm_wrong_type_arg (FUNC_NAME, 1, obj); \ } while (0) #define RANGE_CHECK_AND_COPY_UVEC_INDEX(pos, uvec, i, cindex) \ do { \ cindex = scm_num2size (i, pos, FUNC_NAME); \ if (cindex < 0 || cindex >= SCM_UVEC_LENGTH (uvec)) \ scm_out_of_range_pos (FUNC_NAME, i, SCM_MAKINUM (pos)); \ } while (0) /* This array maps type tags to the size of the elements. */ static const int uvec_sizes[] = {1, 1, 2, 2, 4, 4, 8, 8, 4, 8}; /* This array maps type tags to the bit shifts related to the sizes. */ static const int uvec_shifts[] = {0, 0, 1, 1, 2, 2, 3, 3, 2, 3}; #if HAVE_UVEC_64 /* This is a modified version of scm_iint2str and should go away once we have a public scm_print_integer or similar. */ static void print_int64 (int_s64 num, SCM port) { char num_buf[SCM_INTBUFLEN]; char *p = num_buf; const int rad = 10; size_t num_chars = 1; size_t i; int_u64 n = (num < 0) ? -num : num; for (n /= rad; n > 0; n /= rad) num_chars++; i = num_chars; if (num < 0) { *p++ = '-'; num_chars++; n = -num; } else n = num; while (i--) { int d = n % rad; n /= rad; p[i] = d + ((d < 10) ? '0' : 'a' - 10); } scm_lfwrite (num_buf, num_chars, port); } /* This is a modified version of scm_iint2str and should go away once we have a public scm_print_integer or similar. */ static void print_uint64 (int_u64 num, SCM port) { char num_buf[SCM_INTBUFLEN]; char *p = num_buf; const int rad = 10; size_t num_chars = 1; size_t i; int_u64 n = num; for (n /= rad; n > 0; n /= rad) num_chars++; i = num_chars; n = num; while (i--) { int d = n % rad; n /= rad; p[i] = d + ((d < 10) ? '0' : 'a' - 10); } scm_lfwrite (num_buf, num_chars, port); } #endif /* HAVE_UVEC_64 */ static void print_uint32 (int_u32 num, SCM port) { char num_buf[SCM_INTBUFLEN]; char *p = num_buf; const int rad = 10; size_t num_chars = 1; size_t i; int_u32 n = num; for (n /= rad; n > 0; n /= rad) num_chars++; i = num_chars; n = num; while (i--) { int d = n % rad; n /= rad; p[i] = d + ((d < 10) ? '0' : 'a' - 10); } scm_lfwrite (num_buf, num_chars, port); } /* ================================================================ */ /* SMOB procedures. */ /* ================================================================ */ /* Smob print hook for homogeneous vectors. */ static int uvec_print (SCM uvec, SCM port, scm_print_state *pstate SCM_UNUSED) { union { int_u8 *u8; int_s8 *s8; int_u16 *u16; int_s16 *s16; int_u32 *u32; int_s32 *s32; #if HAVE_UVEC_64 int_u64 *u64; int_s64 *s64; #endif float_f32 *f32; float_f64 *f64; } np; size_t i = 0; /* since SCM_UVEC_LENGTH will return something this size. */ const size_t uvlen = SCM_UVEC_LENGTH (uvec); char *tagstr; void *uptr = SCM_UVEC_BASE (uvec); switch (SCM_UVEC_TYPE (uvec)) { case SCM_UVEC_U8: tagstr = "u8"; np.u8 = (int_u8 *) uptr; break; case SCM_UVEC_S8: tagstr = "s8"; np.s8 = (int_s8 *) uptr; break; case SCM_UVEC_U16: tagstr = "u16"; np.u16 = (int_u16 *) uptr; break; case SCM_UVEC_S16: tagstr = "s16"; np.s16 = (int_s16 *) uptr; break; case SCM_UVEC_U32: tagstr = "u32"; np.u32 = (int_u32 *) uptr; break; case SCM_UVEC_S32: tagstr = "s32"; np.s32 = (int_s32 *) uptr; break; #if HAVE_UVEC_64 case SCM_UVEC_U64: tagstr = "u64"; np.u64 = (int_u64 *) uptr; break; case SCM_UVEC_S64: tagstr = "s64"; np.s64 = (int_s64 *) uptr; break; #endif case SCM_UVEC_F32: tagstr = "f32"; np.f32 = (float_f32 *) uptr; break; case SCM_UVEC_F64: tagstr = "f64"; np.f64 = (float_f64 *) uptr; break; default: abort (); /* Sanity check. */ break; } scm_putc ('#', port); scm_puts (tagstr, port); scm_putc ('(', port); while (i < uvlen) { if (i != 0) scm_puts (" ", port); switch (SCM_UVEC_TYPE (uvec)) { case SCM_UVEC_U8: scm_intprint (*np.u8, 10, port); np.u8++; break; case SCM_UVEC_S8: scm_intprint (*np.s8, 10, port); np.s8++; break; case SCM_UVEC_U16: scm_intprint (*np.u16, 10, port); np.u16++; break; case SCM_UVEC_S16: scm_intprint (*np.s16, 10, port); np.s16++; break; case SCM_UVEC_U32: print_uint32 (*np.u32, port); np.u32++; break; case SCM_UVEC_S32: scm_intprint (*np.s32, 10, port); np.s32++; break; #if HAVE_UVEC_64 case SCM_UVEC_U64: print_uint64(*np.u64, port); np.u64++; break; case SCM_UVEC_S64: print_int64(*np.s64, port); np.s64++; break; #endif case SCM_UVEC_F32: scm_iprin1 (scm_make_real (*np.f32), port, pstate); np.f32++; break; case SCM_UVEC_F64: scm_iprin1 (scm_make_real (*np.f64), port, pstate); np.f64++; break; default: abort (); /* Sanity check. */ break; } i++; } scm_remember_upto_here_1 (uvec); scm_puts (")", port); return 1; } static SCM uvec_equalp (SCM a, SCM b) { SCM result = SCM_BOOL_T; if(SCM_UVEC_TYPE (a) != SCM_UVEC_TYPE (b)) result = SCM_BOOL_F; else if(SCM_UVEC_LENGTH (a) != SCM_UVEC_LENGTH (b)) result = SCM_BOOL_F; else if(memcmp(SCM_UVEC_BASE (a), SCM_UVEC_BASE (b), SCM_UVEC_LENGTH (a) * uvec_sizes[SCM_UVEC_TYPE(a)]) != 0) result = SCM_BOOL_F; scm_remember_upto_here_2 (a, b); return result; } static size_t uvec_free (SCM uvec) { scm_must_free (SCM_UVEC_BASE (uvec)); return SCM_UVEC_LENGTH (uvec) * uvec_sizes[SCM_UVEC_TYPE (uvec)]; } /* ================================================================ */ /* Utility procedures. */ /* ================================================================ */ /* Create a new, uninitialized homogeneous numeric vector of type TYPE with space for LEN elements. */ inline static SCM make_uvec (const int pos, const char * func_name, int type, size_t len) { if (len > (((size_t)-1) >> uvec_shifts[type])) { if(pos < 0) scm_out_of_range (func_name, scm_size2num (len)); else scm_out_of_range_pos (func_name, scm_size2num (len), SCM_MAKINUM (pos)); } else { void *p = scm_must_malloc (len * uvec_sizes[type], func_name); SCM_RETURN_NEWSMOB3 (scm_tc16_uvec, type, len, p); } } inline static SCM uvec_length (SCM uvec, const int required_type, const char *FUNC_NAME) { SCM result; VALIDATE_UVEC (1, uvec, required_type); result = scm_size2num (SCM_UVEC_LENGTH (uvec)); scm_remember_upto_here_1 (uvec); return result; } /* ================================================================ */ /* U8 procedures. */ /* ================================================================ */ SCM_DEFINE (scm_u8vector_p, "u8vector?", 1, 0, 0, (SCM obj), "Return @code{#t} if @var{obj} is a vector of type u8,\n" "@code{#f} otherwise.") #define FUNC_NAME s_scm_u8vector_p { SCM result = SCM_BOOL (SCM_SMOB_PREDICATE (scm_tc16_uvec, obj) && (SCM_UVEC_TYPE (obj) == SCM_UVEC_U8)); scm_remember_upto_here_1 (obj); return result; } #undef FUNC_NAME SCM_DEFINE (scm_make_u8vector, "make-u8vector", 1, 1, 0, (SCM n, SCM fill), "Create a newly allocated homogeneous numeric vector which can\n" "hold @var{len} elements. If @var{fill} is given, it is used to\n" "initialize the elements, otherwise the contents of the vector\n" "is unspecified.") #define FUNC_NAME s_scm_make_u8vector { SCM uvec; int_u8 f; const size_t count = scm_num2size (n, 1, s_scm_make_u8vector); uvec = make_uvec (1, FUNC_NAME, SCM_UVEC_U8, count); if (SCM_UNBNDP (fill)) f = 0; else { unsigned int s = scm_num2uint (fill, 2, FUNC_NAME); f = s; if ((unsigned int) f != s) scm_out_of_range_pos (FUNC_NAME, fill, SCM_MAKINUM (2)); } memset(SCM_UVEC_BASE (uvec), f, count); return uvec; } #undef FUNC_NAME SCM_DEFINE (scm_u8vector, "u8vector", 0, 0, 1, (SCM l), "Create a newly allocated homogeneous numeric vector containing\n" "all argument values.") #define FUNC_NAME s_scm_u8vector { SCM_VALIDATE_REST_ARGUMENT (l); return scm_list_to_u8vector (l); } #undef FUNC_NAME SCM_DEFINE (scm_u8vector_length, "u8vector-length", 1, 0, 0, (SCM uvec), "Return the number of elements in the homogeneous numeric vector\n" "@var{uvec}.") #define FUNC_NAME s_scm_u8vector_length { return uvec_length (uvec, SCM_UVEC_U8, FUNC_NAME); } #undef FUNC_NAME SCM_DEFINE (scm_u8vector_ref, "u8vector-ref", 2, 0, 0, (SCM uvec, SCM index), "Return the element at @var{index} in the homogeneous numeric\n" "vector @var{uvec}.") #define FUNC_NAME s_scm_u8vector_ref { SCM result; size_t idx; VALIDATE_UVEC (1, uvec, SCM_UVEC_U8); RANGE_CHECK_AND_COPY_UVEC_INDEX (2, uvec, index, idx); result = scm_short2num (((int_u8 *) SCM_UVEC_BASE (uvec))[idx]); scm_remember_upto_here_1 (uvec); return result; } #undef FUNC_NAME SCM_DEFINE (scm_u8vector_set_x, "u8vector-set!", 3, 0, 0, (SCM uvec, SCM index, SCM value), "Set the element at @var{index} in the homogeneous numeric\n" "vector @var{uvec} to @var{value}. The return value is not\n" "specified.") #define FUNC_NAME s_scm_u8vector_set_x { size_t idx; int_u8 f; unsigned int s; VALIDATE_UVEC (1, uvec, SCM_UVEC_U8); RANGE_CHECK_AND_COPY_UVEC_INDEX (2, uvec, index, idx); s = scm_num2uint (value, 3, FUNC_NAME); f = s; if ((unsigned int) f != s) scm_out_of_range_pos (FUNC_NAME, value, SCM_MAKINUM (3)); ((int_u8 *) SCM_UVEC_BASE (uvec))[idx] = f; scm_remember_upto_here_1 (uvec); return SCM_UNSPECIFIED; } #undef FUNC_NAME SCM_DEFINE (scm_u8vector_to_list, "u8vector->list", 1, 0, 0, (SCM uvec), "Convert the homogeneous numeric vector @var{uvec} to a list.") #define FUNC_NAME s_scm_u8vector_to_list { size_t idx; int_u8 * p; SCM res = SCM_EOL; VALIDATE_UVEC (1, uvec, SCM_UVEC_U8); idx = SCM_UVEC_LENGTH (uvec); p = (int_u8 *) SCM_UVEC_BASE (uvec) + idx; while (idx-- > 0) { p--; res = scm_cons (SCM_MAKINUM (*p), res); } scm_remember_upto_here_1 (uvec); return res; } #undef FUNC_NAME SCM_DEFINE (scm_list_to_u8vector, "list->u8vector", 1, 0, 0, (SCM l), "Convert the list @var{l}, which must only contain unsigned\n" "8-bit values, to a numeric homogeneous vector.") #define FUNC_NAME s_scm_list_to_u8vector { SCM uvec; SCM tmp; int_u8 * p; long n; /* to match COPYLEN */ SCM_VALIDATE_LIST_COPYLEN (1, l, n); uvec = make_uvec (-1, FUNC_NAME, SCM_UVEC_U8, n); p = (int_u8 *) SCM_UVEC_BASE (uvec); tmp = l; while (SCM_CONSP (tmp)) { int_u8 f; unsigned int s = scm_num2uint (SCM_CAR (tmp), 2, FUNC_NAME); f = s; if ((unsigned int) f != s) scm_out_of_range (FUNC_NAME, SCM_CAR (tmp)); *p++ = f; tmp = SCM_CDR (tmp); } return uvec; } #undef FUNC_NAME /* ================================================================ */ /* S8 procedures. */ /* ================================================================ */ SCM_DEFINE (scm_s8vector_p, "s8vector?", 1, 0, 0, (SCM obj), "Return @code{#t} if @var{obj} is a vector of type s8,\n" "@code{#f} otherwise.") #define FUNC_NAME s_scm_s8vector_p { SCM result = SCM_BOOL (SCM_SMOB_PREDICATE (scm_tc16_uvec, obj) && (SCM_UVEC_TYPE (obj) == SCM_UVEC_S8)); scm_remember_upto_here_1 (obj); return result; } #undef FUNC_NAME SCM_DEFINE (scm_make_s8vector, "make-s8vector", 1, 1, 0, (SCM n, SCM fill), "Create a newly allocated homogeneous numeric vector which can\n" "hold @var{len} elements. If @var{fill} is given, it is used to\n" "initialize the elements, otherwise the contents of the vector\n" "is unspecified.") #define FUNC_NAME s_scm_make_s8vector { SCM uvec; int_s8 f; size_t count = scm_num2size (n, 1, s_scm_make_s8vector); uvec = make_uvec (1, FUNC_NAME, SCM_UVEC_S8, count); if (SCM_UNBNDP (fill)) f = 0; else { int s = scm_num2int (fill, 2, FUNC_NAME); f = s; if ((signed int) f != s) scm_out_of_range_pos (FUNC_NAME, fill, SCM_MAKINUM (2)); } memset(SCM_UVEC_BASE (uvec), f, count); return uvec; } #undef FUNC_NAME SCM_DEFINE (scm_s8vector, "s8vector", 0, 0, 1, (SCM l), "Create a newly allocated homogeneous numeric vector containing\n" "all argument values.") #define FUNC_NAME s_scm_s8vector { SCM_VALIDATE_REST_ARGUMENT (l); return scm_list_to_s8vector (l); } #undef FUNC_NAME SCM_DEFINE (scm_s8vector_length, "s8vector-length", 1, 0, 0, (SCM uvec), "Return the number of elements in the homogeneous numeric vector\n" "@var{uvec}.") #define FUNC_NAME s_scm_s8vector_length { return uvec_length (uvec, SCM_UVEC_S8, FUNC_NAME); } #undef FUNC_NAME SCM_DEFINE (scm_s8vector_ref, "s8vector-ref", 2, 0, 0, (SCM uvec, SCM index), "Return the element at @var{index} in the homogeneous numeric\n" "vector @var{uvec}.") #define FUNC_NAME s_scm_s8vector_ref { SCM result; size_t idx; VALIDATE_UVEC (1, uvec, SCM_UVEC_S8); RANGE_CHECK_AND_COPY_UVEC_INDEX (2, uvec, index, idx); result = scm_short2num (((int_s8 *) SCM_UVEC_BASE (uvec))[idx]); scm_remember_upto_here_1 (uvec); return result; } #undef FUNC_NAME SCM_DEFINE (scm_s8vector_set_x, "s8vector-set!", 3, 0, 0, (SCM uvec, SCM index, SCM value), "Set the element at @var{index} in the homogeneous numeric\n" "vector @var{uvec} to @var{value}. The return value is not\n" "specified.") #define FUNC_NAME s_scm_s8vector_set_x { size_t idx; int_s8 f; signed int s; VALIDATE_UVEC (1, uvec, SCM_UVEC_S8); RANGE_CHECK_AND_COPY_UVEC_INDEX (2, uvec, index, idx); s = scm_num2int (value, 3, FUNC_NAME); f = s; if ((signed int) f != s) scm_out_of_range_pos (FUNC_NAME, value, SCM_MAKINUM (3)); ((int_s8 *) SCM_UVEC_BASE (uvec))[idx] = f; scm_remember_upto_here_1 (uvec); return SCM_UNSPECIFIED; } #undef FUNC_NAME SCM_DEFINE (scm_s8vector_to_list, "s8vector->list", 1, 0, 0, (SCM uvec), "Convert the homogeneous numeric vector @var{uvec} to a list.") #define FUNC_NAME s_scm_s8vector_to_list { size_t idx; int_s8 * p; SCM res = SCM_EOL; VALIDATE_UVEC (1, uvec, SCM_UVEC_S8); idx = SCM_UVEC_LENGTH (uvec); p = (int_s8 *) SCM_UVEC_BASE (uvec) + idx; while (idx-- > 0) { p--; res = scm_cons (SCM_MAKINUM (*p), res); } scm_remember_upto_here_1 (uvec); return res; } #undef FUNC_NAME SCM_DEFINE (scm_list_to_s8vector, "list->s8vector", 1, 0, 0, (SCM l), "Convert the list @var{l}, which must only contain signed\n" "8-bit values, to a numeric homogeneous vector.") #define FUNC_NAME s_scm_list_to_s8vector { SCM uvec; SCM tmp; int_s8 * p; long n; /* to match COPYLEN */ SCM_VALIDATE_LIST_COPYLEN (1, l, n); uvec = make_uvec (-1, FUNC_NAME, SCM_UVEC_S8, n); p = (int_s8 *) SCM_UVEC_BASE (uvec); tmp = l; while (SCM_CONSP (tmp)) { int_s8 f; signed int s; s = scm_num2int (SCM_CAR (tmp), 2, FUNC_NAME); f = s; if ((signed int) f != s) scm_out_of_range (FUNC_NAME, SCM_CAR (tmp)); *p++ = f; tmp = SCM_CDR (tmp); } return uvec; } #undef FUNC_NAME /* ================================================================ */ /* U16 procedures. */ /* ================================================================ */ SCM_DEFINE (scm_u16vector_p, "u16vector?", 1, 0, 0, (SCM obj), "Return @code{#t} if @var{obj} is a vector of type u16,\n" "@code{#f} otherwise.") #define FUNC_NAME s_scm_u16vector_p { SCM result = SCM_BOOL (SCM_SMOB_PREDICATE (scm_tc16_uvec, obj) && SCM_UVEC_TYPE (obj) == SCM_UVEC_U16); scm_remember_upto_here_1 (obj); return result; } #undef FUNC_NAME SCM_DEFINE (scm_make_u16vector, "make-u16vector", 1, 1, 0, (SCM n, SCM fill), "Create a newly allocated homogeneous numeric vector which can\n" "hold @var{len} elements. If @var{fill} is given, it is used to\n" "initialize the elements, otherwise the contents of the vector\n" "is unspecified.") #define FUNC_NAME s_scm_make_u16vector { size_t count = scm_num2size (n, 1, s_scm_make_u16vector); SCM uvec = make_uvec (1, FUNC_NAME, SCM_UVEC_U16, count); if (SCM_UNBNDP (fill)) memset (SCM_UVEC_BASE (uvec), 0, count * sizeof (int_u16)); else { /* if we had SIZEOF_SHORT we could be more efficient here */ int_u16 * p; const unsigned int f = scm_num2uint (fill, 2, FUNC_NAME); #if SIZEOF_INT > 2 SCM_ASSERT_RANGE (2, fill, (f <= (int_u16) 65535)); #endif p = (int_u16 *) SCM_UVEC_BASE (uvec); while (count-- > 0) *p++ = f; } return uvec; } #undef FUNC_NAME SCM_DEFINE (scm_u16vector, "u16vector", 0, 0, 1, (SCM l), "Create a newly allocated homogeneous numeric vector containing\n" "all argument values.") #define FUNC_NAME s_scm_u16vector { SCM_VALIDATE_REST_ARGUMENT (l); return scm_list_to_u16vector (l); } #undef FUNC_NAME SCM_DEFINE (scm_u16vector_length, "u16vector-length", 1, 0, 0, (SCM uvec), "Return the number of elements in the homogeneous numeric vector\n" "@var{uvec}.") #define FUNC_NAME s_scm_u16vector_length { return uvec_length (uvec, SCM_UVEC_U16, FUNC_NAME); } #undef FUNC_NAME SCM_DEFINE (scm_u16vector_ref, "u16vector-ref", 2, 0, 0, (SCM uvec, SCM index), "Return the element at @var{index} in the homogeneous numeric\n" "vector @var{uvec}.") #define FUNC_NAME s_scm_u16vector_ref { SCM result; size_t idx; VALIDATE_UVEC (1, uvec, SCM_UVEC_U16); RANGE_CHECK_AND_COPY_UVEC_INDEX (2, uvec, index, idx); result = scm_ushort2num (((int_u16 *) SCM_UVEC_BASE (uvec))[idx]); scm_remember_upto_here_1 (result); return result; } #undef FUNC_NAME SCM_DEFINE (scm_u16vector_set_x, "u16vector-set!", 3, 0, 0, (SCM uvec, SCM index, SCM value), "Set the element at @var{index} in the homogeneous numeric\n" "vector @var{uvec} to @var{value}. The return value is not\n" "specified.") #define FUNC_NAME s_scm_u16vector_set_x { size_t idx; unsigned int f; VALIDATE_UVEC (1, uvec, SCM_UVEC_U16); RANGE_CHECK_AND_COPY_UVEC_INDEX (2, uvec, index, idx); /* if we had SIZEOF_SHORT we could be more efficient here */ f = scm_num2uint (value, 3, FUNC_NAME); #if SIZEOF_INT > 2 SCM_ASSERT_RANGE (2, value, (f <= (int_u16) 65535)); #endif ((int_u16 *) SCM_UVEC_BASE (uvec))[idx] = (int_u16) f; scm_remember_upto_here_1 (uvec); return SCM_UNSPECIFIED; } #undef FUNC_NAME SCM_DEFINE (scm_u16vector_to_list, "u16vector->list", 1, 0, 0, (SCM uvec), "Convert the homogeneous numeric vector @var{uvec} to a list.") #define FUNC_NAME s_scm_u16vector_to_list { size_t idx; int_u16 * p; SCM res = SCM_EOL; VALIDATE_UVEC (1, uvec, SCM_UVEC_U16); idx = SCM_UVEC_LENGTH (uvec); p = (int_u16 *) SCM_UVEC_BASE (uvec) + idx; while (idx-- > 0) { p--; res = scm_cons (SCM_MAKINUM (*p), res); } scm_remember_upto_here_1 (uvec); return res; } #undef FUNC_NAME SCM_DEFINE (scm_list_to_u16vector, "list->u16vector", 1, 0, 0, (SCM l), "Convert the list @var{l}, which must only contain unsigned\n" "16-bit values, to a numeric homogeneous vector.") #define FUNC_NAME s_scm_list_to_u16vector { SCM uvec; int_u16 * p; long n; /* to match COPYLEN */ SCM_VALIDATE_LIST_COPYLEN (1, l, n); uvec = make_uvec (-1, FUNC_NAME, SCM_UVEC_U16, n); p = (int_u16 *) SCM_UVEC_BASE (uvec); while (SCM_CONSP (l)) { int_u16 f = scm_num2ushort (SCM_CAR (l), 2, FUNC_NAME); *p++ = f; l = SCM_CDR (l); } return uvec; } #undef FUNC_NAME /* ================================================================ */ /* S16 procedures. */ /* ================================================================ */ SCM_DEFINE (scm_s16vector_p, "s16vector?", 1, 0, 0, (SCM obj), "Return @code{#t} if @var{obj} is a vector of type s16,\n" "@code{#f} otherwise.") #define FUNC_NAME s_scm_s16vector_p { const SCM result = SCM_BOOL (SCM_SMOB_PREDICATE (scm_tc16_uvec, obj) && SCM_UVEC_TYPE (obj) == SCM_UVEC_S16); scm_remember_upto_here_1 (obj); return result; } #undef FUNC_NAME SCM_DEFINE (scm_make_s16vector, "make-s16vector", 1, 1, 0, (SCM n, SCM fill), "Create a newly allocated homogeneous numeric vector which can\n" "hold @var{len} elements. If @var{fill} is given, it is used to\n" "initialize the elements, otherwise the contents of the vector\n" "is unspecified.") #define FUNC_NAME s_scm_make_s16vector { SCM uvec; size_t count = scm_num2size (n, 1, s_scm_make_s16vector); uvec = make_uvec (1, FUNC_NAME, SCM_UVEC_S16, count); if (SCM_UNBNDP (fill)) memset (SCM_UVEC_BASE (uvec), 0, count * sizeof (int_s16)); else { /* if we had SIZEOF_SHORT we could be more efficient here */ int_s16 * p; int f = scm_num2int (fill, 2, FUNC_NAME); #if SIZEOF_INT > 2 SCM_ASSERT_RANGE (2, fill, (f >= (int_s16) -32768) && (f <= (int_s16) 32767)); #endif p = (int_s16 *) SCM_UVEC_BASE (uvec); while (count-- > 0) *p++ = f; } return uvec; } #undef FUNC_NAME SCM_DEFINE (scm_s16vector, "s16vector", 0, 0, 1, (SCM l), "Create a newly allocated homogeneous numeric vector containing\n" "all argument values.") #define FUNC_NAME s_scm_s16vector { SCM_VALIDATE_REST_ARGUMENT (l); return scm_list_to_s16vector (l); } #undef FUNC_NAME SCM_DEFINE (scm_s16vector_length, "s16vector-length", 1, 0, 0, (SCM uvec), "Return the number of elements in the homogeneous numeric vector\n" "@var{uvec}.") #define FUNC_NAME s_scm_s16vector_length { return uvec_length (uvec, SCM_UVEC_S16, FUNC_NAME); } #undef FUNC_NAME SCM_DEFINE (scm_s16vector_ref, "s16vector-ref", 2, 0, 0, (SCM uvec, SCM index), "Return the element at @var{index} in the homogeneous numeric\n" "vector @var{uvec}.") #define FUNC_NAME s_scm_s16vector_ref { SCM result; size_t idx; VALIDATE_UVEC (1, uvec, SCM_UVEC_S16); RANGE_CHECK_AND_COPY_UVEC_INDEX (2, uvec, index, idx); result = scm_short2num (((int_s16 *) SCM_UVEC_BASE (uvec))[idx]); scm_remember_upto_here_1 (uvec); return result; } #undef FUNC_NAME SCM_DEFINE (scm_s16vector_set_x, "s16vector-set!", 3, 0, 0, (SCM uvec, SCM index, SCM value), "Set the element at @var{index} in the homogeneous numeric\n" "vector @var{uvec} to @var{value}. The return value is not\n" "specified.") #define FUNC_NAME s_scm_s16vector_set_x { size_t idx; int f; VALIDATE_UVEC (1, uvec, SCM_UVEC_S16); RANGE_CHECK_AND_COPY_UVEC_INDEX (2, uvec, index, idx); /* if we had SIZEOF_SHORT we could be more efficient here */ f = scm_num2int (value, 3, FUNC_NAME); #if SIZEOF_INT > 2 SCM_ASSERT_RANGE (2, value, (f >= (int_s16) -32768) && (f <= (int_s16) 32767)); #endif ((int_s16 *) SCM_UVEC_BASE (uvec))[idx] = (int_s16) f; scm_remember_upto_here_1 (uvec); return SCM_UNSPECIFIED; } #undef FUNC_NAME SCM_DEFINE (scm_s16vector_to_list, "s16vector->list", 1, 0, 0, (SCM uvec), "Convert the homogeneous numeric vector @var{uvec} to a list.") #define FUNC_NAME s_scm_s16vector_to_list { size_t idx; int_s16 * p; SCM res = SCM_EOL; VALIDATE_UVEC (1, uvec, SCM_UVEC_S16); idx = SCM_UVEC_LENGTH (uvec); p = (int_s16 *) SCM_UVEC_BASE (uvec) + idx; while (idx-- > 0) { p--; res = scm_cons (SCM_MAKINUM (*p), res); } scm_remember_upto_here_1 (uvec); return res; } #undef FUNC_NAME SCM_DEFINE (scm_list_to_s16vector, "list->s16vector", 1, 0, 0, (SCM l), "Convert the list @var{l}, which must only contain signed\n" "16-bit values, to a numeric homogeneous vector.") #define FUNC_NAME s_scm_list_to_s16vector { SCM uvec; SCM tmp; int_s16 * p; long n; /* to match COPYLEN */ SCM_VALIDATE_LIST_COPYLEN (1, l, n); uvec = make_uvec (-1, FUNC_NAME, SCM_UVEC_S16, n); p = (int_s16 *) SCM_UVEC_BASE (uvec); tmp = l; while (SCM_CONSP (tmp)) { int_s16 f = scm_num2short (SCM_CAR (tmp), 2, FUNC_NAME); *p++ = f; tmp = SCM_CDR (tmp); } return uvec; } #undef FUNC_NAME /* ================================================================ */ /* U32 procedures. */ /* ================================================================ */ SCM_DEFINE (scm_u32vector_p, "u32vector?", 1, 0, 0, (SCM obj), "Return @code{#t} if @var{obj} is a vector of type u32,\n" "@code{#f} otherwise.") #define FUNC_NAME s_scm_u32vector_p { const SCM result = SCM_BOOL (SCM_SMOB_PREDICATE (scm_tc16_uvec, obj) && SCM_UVEC_TYPE (obj) == SCM_UVEC_U32); scm_remember_upto_here_1 (obj); return result; } #undef FUNC_NAME SCM_DEFINE (scm_make_u32vector, "make-u32vector", 1, 1, 0, (SCM n, SCM fill), "Create a newly allocated homogeneous numeric vector which can\n" "hold @var{len} elements. If @var{fill} is given, it is used to\n" "initialize the elements, otherwise the contents of the vector\n" "is unspecified.") #define FUNC_NAME s_scm_make_u32vector { size_t count = scm_num2size (n, 1, s_scm_make_u32vector); SCM uvec = make_uvec (1, FUNC_NAME, SCM_UVEC_U32, count); if (SCM_UNBNDP (fill)) memset (SCM_UVEC_BASE (uvec), 0, count * sizeof (int_u32)); else { int_u32 * p; const unsigned long f = scm_num2ulong (fill, 2, FUNC_NAME); #if SIZEOF_LONG > 4 SCM_ASSERT_RANGE (2, fill, (f <= (int_u32) 0xFFFFFFFFUL)); #endif p = (int_u32 *) SCM_UVEC_BASE (uvec); while (count-- > 0) *p++ = f; } return uvec; } #undef FUNC_NAME SCM_DEFINE (scm_u32vector, "u32vector", 0, 0, 1, (SCM l), "Create a newly allocated homogeneous numeric vector containing\n" "all argument values.") #define FUNC_NAME s_scm_u32vector { SCM_VALIDATE_REST_ARGUMENT (l); return scm_list_to_u32vector (l); } #undef FUNC_NAME SCM_DEFINE (scm_u32vector_length, "u32vector-length", 1, 0, 0, (SCM uvec), "Return the number of elements in the homogeneous numeric vector\n" "@var{uvec}.") #define FUNC_NAME s_scm_u32vector_length { return uvec_length (uvec, SCM_UVEC_U32, FUNC_NAME); } #undef FUNC_NAME SCM_DEFINE (scm_u32vector_ref, "u32vector-ref", 2, 0, 0, (SCM uvec, SCM index), "Return the element at @var{index} in the homogeneous numeric\n" "vector @var{uvec}.") #define FUNC_NAME s_scm_u32vector_ref { SCM result; size_t idx; VALIDATE_UVEC (1, uvec, SCM_UVEC_U32); RANGE_CHECK_AND_COPY_UVEC_INDEX (2, uvec, index, idx); result = scm_ulong2num (((int_u32 *) SCM_UVEC_BASE (uvec))[idx]); scm_remember_upto_here_1 (uvec); return result; } #undef FUNC_NAME SCM_DEFINE (scm_u32vector_set_x, "u32vector-set!", 3, 0, 0, (SCM uvec, SCM index, SCM value), "Set the element at @var{index} in the homogeneous numeric\n" "vector @var{uvec} to @var{value}. The return value is not\n" "specified.") #define FUNC_NAME s_scm_u32vector_set_x { size_t idx; unsigned long f; VALIDATE_UVEC (1, uvec, SCM_UVEC_U32); RANGE_CHECK_AND_COPY_UVEC_INDEX (2, uvec, index, idx); f = scm_num2ulong (value, 3, FUNC_NAME); #if SIZEOF_LONG > 4 SCM_ASSERT_RANGE (2, value, (f <= (int_u32) 0xFFFFFFFFUL)); #endif ((int_u32 *) SCM_UVEC_BASE (uvec))[idx] = (int_u32) f; scm_remember_upto_here_1 (uvec); return SCM_UNSPECIFIED; } #undef FUNC_NAME SCM_DEFINE (scm_u32vector_to_list, "u32vector->list", 1, 0, 0, (SCM uvec), "Convert the homogeneous numeric vector @var{uvec} to a list.") #define FUNC_NAME s_scm_u32vector_to_list { size_t idx; int_u32 * p; SCM res = SCM_EOL; VALIDATE_UVEC (1, uvec, SCM_UVEC_U32); idx = SCM_UVEC_LENGTH (uvec); p = (int_u32 *) SCM_UVEC_BASE (uvec) + idx; while (idx-- > 0) { p--; res = scm_cons (scm_ulong2num (*p), res); } scm_remember_upto_here_1 (uvec); return res; } #undef FUNC_NAME SCM_DEFINE (scm_list_to_u32vector, "list->u32vector", 1, 0, 0, (SCM l), "Convert the list @var{l}, which must only contain unsigned\n" "32-bit values, to a numeric homogeneous vector.") #define FUNC_NAME s_scm_list_to_u32vector { SCM uvec; int_u32 *p; long n; /* to match COPYLEN */ SCM_VALIDATE_LIST_COPYLEN (1, l, n); uvec = make_uvec (-1, FUNC_NAME, SCM_UVEC_U32, n); p = (int_u32 *) SCM_UVEC_BASE (uvec); while (SCM_CONSP (l)) { int_u32 f = scm_num2ulong (SCM_CAR (l), 2, FUNC_NAME); *p++ = f; l = SCM_CDR (l); } return uvec; } #undef FUNC_NAME /* ================================================================ */ /* S32 procedures. */ /* ================================================================ */ SCM_DEFINE (scm_s32vector_p, "s32vector?", 1, 0, 0, (SCM obj), "Return @code{#t} if @var{obj} is a vector of type s32,\n" "@code{#f} otherwise.") #define FUNC_NAME s_scm_s32vector_p { SCM result = SCM_BOOL (SCM_SMOB_PREDICATE (scm_tc16_uvec, obj) && SCM_UVEC_TYPE (obj) == SCM_UVEC_S32); scm_remember_upto_here_1 (result); return result; } #undef FUNC_NAME SCM_DEFINE (scm_make_s32vector, "make-s32vector", 1, 1, 0, (SCM n, SCM fill), "Create a newly allocated homogeneous numeric vector which can\n" "hold @var{len} elements. If @var{fill} is given, it is used to\n" "initialize the elements, otherwise the contents of the vector\n" "is unspecified.") #define FUNC_NAME s_scm_make_s32vector { size_t count = scm_num2size (n, 1, s_scm_make_s32vector); SCM uvec = make_uvec (1, FUNC_NAME, SCM_UVEC_S32, count); if (SCM_UNBNDP (fill)) memset (SCM_UVEC_BASE (uvec), 0, count * sizeof (int_s32)); else { int_s32 * p; const long f = scm_num2long (fill, 2, FUNC_NAME); #if SIZEOF_LONG > 4 SCM_ASSERT_RANGE (2, fill, (f >= (int_s32) -2147483648) && (f <= (int_s32) 2147483647)); #endif p = (int_s32 *) SCM_UVEC_BASE (uvec); while (count-- > 0) *p++ = f; } return uvec; } #undef FUNC_NAME SCM_DEFINE (scm_s32vector, "s32vector", 0, 0, 1, (SCM l), "Create a newly allocated homogeneous numeric vector containing\n" "all argument values.") #define FUNC_NAME s_scm_s32vector { SCM_VALIDATE_REST_ARGUMENT (l); return scm_list_to_s32vector (l); } #undef FUNC_NAME SCM_DEFINE (scm_s32vector_length, "s32vector-length", 1, 0, 0, (SCM uvec), "Return the number of elements in the homogeneous numeric vector\n" "@var{uvec}.") #define FUNC_NAME s_scm_s32vector_length { return uvec_length (uvec, SCM_UVEC_S32, FUNC_NAME); } #undef FUNC_NAME SCM_DEFINE (scm_s32vector_ref, "s32vector-ref", 2, 0, 0, (SCM uvec, SCM index), "Return the element at @var{index} in the homogeneous numeric\n" "vector @var{uvec}.") #define FUNC_NAME s_scm_s32vector_ref { SCM result; size_t idx; VALIDATE_UVEC (1, uvec, SCM_UVEC_S32); RANGE_CHECK_AND_COPY_UVEC_INDEX (2, uvec, index, idx); result = scm_long2num (((int_s32 *) SCM_UVEC_BASE (uvec))[idx]); scm_remember_upto_here_1 (uvec); return result; } #undef FUNC_NAME SCM_DEFINE (scm_s32vector_set_x, "s32vector-set!", 3, 0, 0, (SCM uvec, SCM index, SCM value), "Set the element at @var{index} in the homogeneous numeric\n" "vector @var{uvec} to @var{value}. The return value is not\n" "specified.") #define FUNC_NAME s_scm_s32vector_set_x { size_t idx; long f; VALIDATE_UVEC (1, uvec, SCM_UVEC_S32); RANGE_CHECK_AND_COPY_UVEC_INDEX (2, uvec, index, idx); f = scm_num2long (value, 3, FUNC_NAME); #if SIZEOF_LONG > 4 SCM_ASSERT_RANGE (2, value, (f >= (int_s32) -2147483648) && (f <= (int_s32) 2147483647)); #endif ((int_s32 *) SCM_UVEC_BASE (uvec))[idx] = (int_s32) f; scm_remember_upto_here_1 (uvec); return SCM_UNSPECIFIED; } #undef FUNC_NAME SCM_DEFINE (scm_s32vector_to_list, "s32vector->list", 1, 0, 0, (SCM uvec), "Convert the homogeneous numeric vector @var{uvec} to a list.") #define FUNC_NAME s_scm_s32vector_to_list { size_t idx; int_s32 * p; SCM res = SCM_EOL; VALIDATE_UVEC (1, uvec, SCM_UVEC_S32); idx = SCM_UVEC_LENGTH (uvec); p = (int_s32 *) SCM_UVEC_BASE (uvec) + idx; while (idx-- > 0) { p--; res = scm_cons (scm_long2num (*p), res); } scm_remember_upto_here_1 (uvec); return res; } #undef FUNC_NAME SCM_DEFINE (scm_list_to_s32vector, "list->s32vector", 1, 0, 0, (SCM l), "Convert the list @var{l}, which must only contain signed\n" "32-bit values, to a numeric homogeneous vector.") #define FUNC_NAME s_scm_list_to_s32vector { SCM uvec; int_s32 *p; long n; /* to match COPYLEN */ SCM_VALIDATE_LIST_COPYLEN (1, l, n); uvec = make_uvec (-1, FUNC_NAME, SCM_UVEC_S32, n); p = (int_s32 *) SCM_UVEC_BASE (uvec); while (SCM_CONSP (l)) { int_s32 f = scm_num2long (SCM_CAR (l), 2, FUNC_NAME); *p++ = f; l = SCM_CDR (l); } return uvec; } #undef FUNC_NAME #if HAVE_UVEC_64 /* ================================================================ */ /* U64 procedures. */ /* ================================================================ */ SCM_DEFINE (scm_u64vector_p, "u64vector?", 1, 0, 0, (SCM obj), "Return @code{#t} if @var{obj} is a vector of type u64,\n" "@code{#f} otherwise.") #define FUNC_NAME s_scm_u64vector_p { SCM result = SCM_BOOL (SCM_SMOB_PREDICATE (scm_tc16_uvec, obj) && SCM_UVEC_TYPE (obj) == SCM_UVEC_U64); scm_remember_upto_here_1 (obj); return result; } #undef FUNC_NAME SCM_DEFINE (scm_make_u64vector, "make-u64vector", 1, 1, 0, (SCM n, SCM fill), "Create a newly allocated homogeneous numeric vector which can\n" "hold @var{len} elements. If @var{fill} is given, it is used to\n" "initialize the elements, otherwise the contents of the vector\n" "is unspecified.") #define FUNC_NAME s_scm_make_u64vector { size_t count = scm_num2size (n, 1, s_scm_make_u64vector); SCM uvec = make_uvec (1, FUNC_NAME, SCM_UVEC_U64, count); if (SCM_UNBNDP (fill)) memset (SCM_UVEC_BASE (uvec), 0, count * sizeof (int_u64)); else { int_u64 * p; const unsigned long long f = scm_num2ulong_long (fill, 2, FUNC_NAME); #if SIZEOF_LONG_LONG > 8 SCM_ASSERT_RANGE (2, fill, (f <= (int_u64) 0xFFFFFFFFFFFFFFFFUL)); #endif p = (int_u64 *) SCM_UVEC_BASE (uvec); while (count-- > 0) *p++ = f; } return uvec; } #undef FUNC_NAME SCM_DEFINE (scm_u64vector, "u64vector", 0, 0, 1, (SCM l), "Create a newly allocated homogeneous numeric vector containing\n" "all argument values.") #define FUNC_NAME s_scm_u64vector { SCM_VALIDATE_REST_ARGUMENT (l); return scm_list_to_u64vector (l); } #undef FUNC_NAME SCM_DEFINE (scm_u64vector_length, "u64vector-length", 1, 0, 0, (SCM uvec), "Return the number of elements in the homogeneous numeric vector\n" "@var{uvec}.") #define FUNC_NAME s_scm_u64vector_length { return uvec_length (uvec, SCM_UVEC_U64, FUNC_NAME); } #undef FUNC_NAME SCM_DEFINE (scm_u64vector_ref, "u64vector-ref", 2, 0, 0, (SCM uvec, SCM index), "Return the element at @var{index} in the homogeneous numeric\n" "vector @var{uvec}.") #define FUNC_NAME s_scm_u64vector_ref { SCM result; size_t idx; VALIDATE_UVEC (1, uvec, SCM_UVEC_U64); RANGE_CHECK_AND_COPY_UVEC_INDEX (2, uvec, index, idx); result = scm_ulong_long2num (((int_u64 *) SCM_UVEC_BASE (uvec))[idx]); scm_remember_upto_here_1 (uvec); return result; } #undef FUNC_NAME SCM_DEFINE (scm_u64vector_set_x, "u64vector-set!", 3, 0, 0, (SCM uvec, SCM index, SCM value), "Set the element at @var{index} in the homogeneous numeric\n" "vector @var{uvec} to @var{value}. The return value is not\n" "specified.") #define FUNC_NAME s_scm_u64vector_set_x { size_t idx; unsigned long long f; VALIDATE_UVEC (1, uvec, SCM_UVEC_U64); RANGE_CHECK_AND_COPY_UVEC_INDEX (2, uvec, index, idx); f = scm_num2ulong_long (value, 3, FUNC_NAME); #if SIZEOF_LONG_LONG > 8 SCM_ASSERT_RANGE (2, fill, (f <= (int_u64) 0xFFFFFFFFFFFFFFFFUL)); #endif ((int_u64 *) SCM_UVEC_BASE (uvec))[idx] = (int_u64) f; scm_remember_upto_here_1 (uvec); return SCM_UNSPECIFIED; } #undef FUNC_NAME SCM_DEFINE (scm_u64vector_to_list, "u64vector->list", 1, 0, 0, (SCM uvec), "Convert the homogeneous numeric vector @var{uvec} to a list.") #define FUNC_NAME s_scm_u64vector_to_list { size_t idx; int_u64 * p; SCM res = SCM_EOL; VALIDATE_UVEC (1, uvec, SCM_UVEC_U64); idx = SCM_UVEC_LENGTH (uvec); p = (int_u64 *) SCM_UVEC_BASE (uvec) + idx; while (idx-- > 0) { p--; res = scm_cons (scm_ulong_long2num (*p), res); } scm_remember_upto_here_1 (uvec); return res; } #undef FUNC_NAME SCM_DEFINE (scm_list_to_u64vector, "list->u64vector", 1, 0, 0, (SCM l), "Convert the list @var{l}, which must only contain unsigned\n" "64-bit values, to a numeric homogeneous vector.") #define FUNC_NAME s_scm_list_to_u64vector { SCM uvec; int_u64 *p; long n; /* to match COPYLEN */ SCM_VALIDATE_LIST_COPYLEN (1, l, n); uvec = make_uvec (-1, FUNC_NAME, SCM_UVEC_U64, n); p = (int_u64 *) SCM_UVEC_BASE (uvec); while (SCM_CONSP (l)) { int_u64 f = scm_num2ulong_long (SCM_CAR (l), 2, FUNC_NAME); *p++ = f; l = SCM_CDR (l); } return uvec; } #undef FUNC_NAME /* ================================================================ */ /* S64 procedures. */ /* ================================================================ */ SCM_DEFINE (scm_s64vector_p, "s64vector?", 1, 0, 0, (SCM obj), "Return @code{#t} if @var{obj} is a vector of type s64,\n" "@code{#f} otherwise.") #define FUNC_NAME s_scm_s64vector_p { const SCM result = SCM_BOOL (SCM_SMOB_PREDICATE (scm_tc16_uvec, obj) && SCM_UVEC_TYPE (obj) == SCM_UVEC_S64); scm_remember_upto_here_1 (obj); return result; } #undef FUNC_NAME SCM_DEFINE (scm_make_s64vector, "make-s64vector", 1, 1, 0, (SCM n, SCM fill), "Create a newly allocated homogeneous numeric vector which can\n" "hold @var{len} elements. If @var{fill} is given, it is used to\n" "initialize the elements, otherwise the contents of the vector\n" "is unspecified.") #define FUNC_NAME s_scm_make_s64vector { size_t count = scm_num2size (n, 1, s_scm_make_s64vector); SCM uvec = make_uvec (1, FUNC_NAME, SCM_UVEC_S64, count); if (SCM_UNBNDP (fill)) memset (SCM_UVEC_BASE (uvec), 0, count * sizeof (int_s64)); else { int_s64 * p; const long long f = scm_num2long_long (fill, 2, FUNC_NAME); #if SIZEOF_LONG_LONG > 8 SCM_ASSERT_RANGE (2, fill, (f >= (int_s64) -9223372036854775808) && (f <= (int_s64) 9223372036854775807)); #endif p = (int_s64 *) SCM_UVEC_BASE (uvec); while (count-- > 0) *p++ = f; } return uvec; } #undef FUNC_NAME SCM_DEFINE (scm_s64vector, "s64vector", 0, 0, 1, (SCM l), "Create a newly allocated homogeneous numeric vector containing\n" "all argument values.") #define FUNC_NAME s_scm_s64vector { SCM_VALIDATE_REST_ARGUMENT (l); return scm_list_to_s64vector (l); } #undef FUNC_NAME SCM_DEFINE (scm_s64vector_length, "s64vector-length", 1, 0, 0, (SCM uvec), "Return the number of elements in the homogeneous numeric vector\n" "@var{uvec}.") #define FUNC_NAME s_scm_s64vector_length { return uvec_length (uvec, SCM_UVEC_S64, FUNC_NAME); } #undef FUNC_NAME SCM_DEFINE (scm_s64vector_ref, "s64vector-ref", 2, 0, 0, (SCM uvec, SCM index), "Return the element at @var{index} in the homogeneous numeric\n" "vector @var{uvec}.") #define FUNC_NAME s_scm_s64vector_ref { SCM result; size_t idx; VALIDATE_UVEC (1, uvec, SCM_UVEC_S64); RANGE_CHECK_AND_COPY_UVEC_INDEX (2, uvec, index, idx); result = scm_long_long2num (((int_s64 *) SCM_UVEC_BASE (uvec))[idx]); scm_remember_upto_here_1 (uvec); return result; } #undef FUNC_NAME SCM_DEFINE (scm_s64vector_set_x, "s64vector-set!", 3, 0, 0, (SCM uvec, SCM index, SCM value), "Set the element at @var{index} in the homogeneous numeric\n" "vector @var{uvec} to @var{value}. The return value is not\n" "specified.") #define FUNC_NAME s_scm_s64vector_set_x { size_t idx; long long f; VALIDATE_UVEC (1, uvec, SCM_UVEC_S64); RANGE_CHECK_AND_COPY_UVEC_INDEX (2, uvec, index, idx); f = scm_num2long_long (value, 3, FUNC_NAME); #if SIZEOF_LONG_LONG > 8 SCM_ASSERT_RANGE (2, value, (f >= (int_s64) -9223372036854775808) && (f <= (int_s64) 9223372036854775807)); #endif ((int_s64 *) SCM_UVEC_BASE (uvec))[idx] = (int_s64) f; scm_remember_upto_here_1 (uvec); return SCM_UNSPECIFIED; } #undef FUNC_NAME SCM_DEFINE (scm_s64vector_to_list, "s64vector->list", 1, 0, 0, (SCM uvec), "Convert the homogeneous numeric vector @var{uvec} to a list.") #define FUNC_NAME s_scm_s64vector_to_list { size_t idx; int_s64 * p; SCM res = SCM_EOL; VALIDATE_UVEC (1, uvec, SCM_UVEC_S64); idx = SCM_UVEC_LENGTH (uvec); p = (int_s64 *) SCM_UVEC_BASE (uvec) + idx; while (idx-- > 0) { p--; res = scm_cons (scm_long_long2num (*p), res); } scm_remember_upto_here_1 (uvec); return res; } #undef FUNC_NAME SCM_DEFINE (scm_list_to_s64vector, "list->s64vector", 1, 0, 0, (SCM l), "Convert the list @var{l}, which must only contain signed\n" "64-bit values, to a numeric homogeneous vector.") #define FUNC_NAME s_scm_list_to_s64vector { SCM uvec; int_s64 *p; long n; /* to match COPYLEN */ SCM_VALIDATE_LIST_COPYLEN (1, l, n); uvec = make_uvec (-1, FUNC_NAME, SCM_UVEC_S64, n); p = (int_s64 *) SCM_UVEC_BASE (uvec); while (SCM_CONSP (l)) { int_s64 f = scm_num2long_long (SCM_CAR (l), 2, FUNC_NAME); *p++ = f; l = SCM_CDR (l); } return uvec; } #undef FUNC_NAME #endif /* HAVE_UVEC_64 */ /* ================================================================ */ /* F32 procedures. */ /* ================================================================ */ SCM_DEFINE (scm_f32vector_p, "f32vector?", 1, 0, 0, (SCM obj), "Return @code{#t} if @var{obj} is a vector of type f32,\n" "@code{#f} otherwise.") #define FUNC_NAME s_scm_f32vector_p { SCM result = SCM_BOOL (SCM_SMOB_PREDICATE (scm_tc16_uvec, obj) && SCM_UVEC_TYPE (obj) == SCM_UVEC_F32); scm_remember_upto_here_1 (obj); return result; } #undef FUNC_NAME SCM_DEFINE (scm_make_f32vector, "make-f32vector", 1, 1, 0, (SCM n, SCM fill), "Create a newly allocated homogeneous numeric vector which can\n" "hold @var{len} elements. If @var{fill} is given, it is used to\n" "initialize the elements, otherwise the contents of the vector\n" "is unspecified.") #define FUNC_NAME s_scm_make_f32vector { float_f32 f; float_f32 *p; size_t count = scm_num2size (n, 1, s_scm_make_f32vector); SCM uvec = make_uvec (1, FUNC_NAME, SCM_UVEC_F32, count); if (SCM_UNBNDP (fill)) f = 0; else f = scm_num2float (fill, 2, FUNC_NAME); p = (float_f32 *) SCM_UVEC_BASE (uvec); while (count-- > 0) *p++ = f; return uvec; } #undef FUNC_NAME SCM_DEFINE (scm_f32vector, "f32vector", 0, 0, 1, (SCM l), "Create a newly allocated homogeneous numeric vector containing\n" "all argument values.") #define FUNC_NAME s_scm_f32vector { SCM_VALIDATE_REST_ARGUMENT (l); return scm_list_to_f32vector (l); } #undef FUNC_NAME SCM_DEFINE (scm_f32vector_length, "f32vector-length", 1, 0, 0, (SCM uvec), "Return the number of elements in the homogeneous numeric vector\n" "@var{uvec}.") #define FUNC_NAME s_scm_f32vector_length { return uvec_length (uvec, SCM_UVEC_F32, FUNC_NAME); } #undef FUNC_NAME SCM_DEFINE (scm_f32vector_ref, "f32vector-ref", 2, 0, 0, (SCM uvec, SCM index), "Return the element at @var{index} in the homogeneous numeric\n" "vector @var{uvec}.") #define FUNC_NAME s_scm_f32vector_ref { SCM result; size_t idx; VALIDATE_UVEC (1, uvec, SCM_UVEC_F32); RANGE_CHECK_AND_COPY_UVEC_INDEX (2, uvec, index, idx); result = scm_make_real (((float_f32 *) SCM_UVEC_BASE (uvec))[idx]); scm_remember_upto_here_1 (uvec); return result; } #undef FUNC_NAME SCM_DEFINE (scm_f32vector_set_x, "f32vector-set!", 3, 0, 0, (SCM uvec, SCM index, SCM value), "Set the element at @var{index} in the homogeneous numeric\n" "vector @var{uvec} to @var{value}. The return value is not\n" "specified.") #define FUNC_NAME s_scm_f32vector_set_x { size_t idx; float f; VALIDATE_UVEC (1, uvec, SCM_UVEC_F32); RANGE_CHECK_AND_COPY_UVEC_INDEX (2, uvec, index, idx); f = scm_num2float (value, 3, FUNC_NAME); ((float_f32 *) SCM_UVEC_BASE (uvec))[idx] = f; scm_remember_upto_here_1 (uvec); return SCM_UNSPECIFIED; } #undef FUNC_NAME SCM_DEFINE (scm_f32vector_to_list, "f32vector->list", 1, 0, 0, (SCM uvec), "Convert the homogeneous numeric vector @var{uvec} to a list.") #define FUNC_NAME s_scm_f32vector_to_list { size_t idx; float_f32 * p; SCM res = SCM_EOL; VALIDATE_UVEC (1, uvec, SCM_UVEC_F32); idx = SCM_UVEC_LENGTH (uvec); p = (float_f32 *) SCM_UVEC_BASE (uvec) + idx; while (idx-- > 0) { p--; res = scm_cons (scm_float2num (*p), res); } scm_remember_upto_here_1 (uvec); return res; } #undef FUNC_NAME SCM_DEFINE (scm_list_to_f32vector, "list->f32vector", 1, 0, 0, (SCM l), "Convert the list @var{l}, which must only contain unsigned\n" "8-bit values, to a numeric homogeneous vector.") #define FUNC_NAME s_scm_list_to_f32vector { SCM uvec; float_f32 *p; long n; /* to match COPYLEN */ SCM_VALIDATE_LIST_COPYLEN (1, l, n); uvec = make_uvec (-1, FUNC_NAME, SCM_UVEC_F32, n); p = (float_f32 *) SCM_UVEC_BASE (uvec); while (SCM_CONSP (l)) { float_f32 f = scm_num2float (SCM_CAR (l), 2, FUNC_NAME); *p++ = f; l = SCM_CDR (l); } return uvec; } #undef FUNC_NAME /* ================================================================ */ /* F64 procedures. */ /* ================================================================ */ SCM_DEFINE (scm_f64vector_p, "f64vector?", 1, 0, 0, (SCM obj), "Return @code{#t} if @var{obj} is a vector of type f64,\n" "@code{#f} otherwise.") #define FUNC_NAME s_scm_f64vector_p { SCM result = SCM_BOOL (SCM_SMOB_PREDICATE (scm_tc16_uvec, obj) && SCM_UVEC_TYPE (obj) == SCM_UVEC_F64); scm_remember_upto_here_1 (obj); return result; } #undef FUNC_NAME SCM_DEFINE (scm_make_f64vector, "make-f64vector", 1, 1, 0, (SCM n, SCM fill), "Create a newly allocated homogeneous numeric vector which can\n" "hold @var{len} elements. If @var{fill} is given, it is used to\n" "initialize the elements, otherwise the contents of the vector\n" "is unspecified.") #define FUNC_NAME s_scm_make_f64vector { float_f64 f; float_f64 *p; size_t count = scm_num2size (n, 1, s_scm_make_f64vector); SCM uvec = make_uvec (1, FUNC_NAME, SCM_UVEC_F64, count); if (SCM_UNBNDP (fill)) f = 0; else f = scm_num2double (fill, 2, FUNC_NAME); p = (float_f64 *) SCM_UVEC_BASE (uvec); while (count-- > 0) *p++ = f; return uvec; } #undef FUNC_NAME SCM_DEFINE (scm_f64vector, "f64vector", 0, 0, 1, (SCM l), "Create a newly allocated homogeneous numeric vector containing\n" "all argument values.") #define FUNC_NAME s_scm_f64vector { SCM_VALIDATE_REST_ARGUMENT (l); return scm_list_to_f64vector (l); } #undef FUNC_NAME SCM_DEFINE (scm_f64vector_length, "f64vector-length", 1, 0, 0, (SCM uvec), "Return the number of elements in the homogeneous numeric vector\n" "@var{uvec}.") #define FUNC_NAME s_scm_f64vector_length { return uvec_length (uvec, SCM_UVEC_F64, FUNC_NAME); } #undef FUNC_NAME SCM_DEFINE (scm_f64vector_ref, "f64vector-ref", 2, 0, 0, (SCM uvec, SCM index), "Return the element at @var{index} in the homogeneous numeric\n" "vector @var{uvec}.") #define FUNC_NAME s_scm_f64vector_ref { SCM result; size_t idx; VALIDATE_UVEC (1, uvec, SCM_UVEC_F64); RANGE_CHECK_AND_COPY_UVEC_INDEX (2, uvec, index, idx); result = scm_make_real (((float_f64 *) SCM_UVEC_BASE (uvec))[idx]); scm_remember_upto_here_1 (uvec); return result; } #undef FUNC_NAME SCM_DEFINE (scm_f64vector_set_x, "f64vector-set!", 3, 0, 0, (SCM uvec, SCM index, SCM value), "Set the element at @var{index} in the homogeneous numeric\n" "vector @var{uvec} to @var{value}. The return value is not\n" "specified.") #define FUNC_NAME s_scm_f64vector_set_x { size_t idx; float f; VALIDATE_UVEC (1, uvec, SCM_UVEC_F64); RANGE_CHECK_AND_COPY_UVEC_INDEX (2, uvec, index, idx); f = scm_num2double (value, 3, FUNC_NAME); ((float_f64 *) SCM_UVEC_BASE (uvec))[idx] = f; scm_remember_upto_here_1 (uvec); return SCM_UNSPECIFIED; } #undef FUNC_NAME SCM_DEFINE (scm_f64vector_to_list, "f64vector->list", 1, 0, 0, (SCM uvec), "Convert the homogeneous numeric vector @var{uvec} to a list.") #define FUNC_NAME s_scm_f64vector_to_list { size_t idx; float_f64 * p; SCM res = SCM_EOL; VALIDATE_UVEC (1, uvec, SCM_UVEC_F64); idx = SCM_UVEC_LENGTH (uvec); p = (float_f64 *) SCM_UVEC_BASE (uvec) + idx; while (idx-- > 0) { p--; res = scm_cons (scm_double2num (*p), res); } scm_remember_upto_here_1 (uvec); return res; } #undef FUNC_NAME SCM_DEFINE (scm_list_to_f64vector, "list->f64vector", 1, 0, 0, (SCM l), "Convert the list @var{l}, which must only contain signed\n" "8-bit values, to a numeric homogeneous vector.") #define FUNC_NAME s_scm_list_to_f64vector { SCM uvec; float_f64 *p; long n; /* to match COPYLEN */ SCM_VALIDATE_LIST_COPYLEN (1, l, n); uvec = make_uvec (-1, FUNC_NAME, SCM_UVEC_F64, n); p = (float_f64 *) SCM_UVEC_BASE (uvec); while (SCM_CONSP (l)) { float_f64 f = scm_num2double (SCM_CAR (l), 2, FUNC_NAME); *p++ = f; l = SCM_CDR (l); } return uvec; } #undef FUNC_NAME /* Create the smob type for homogeneous numeric vectors and install the primitives. */ void scm_init_srfi_4 (void) { /* this will be a compilation-time test in future versions of guile */ if(sizeof(size_t) > sizeof(scm_t_bits)) { fprintf(stderr, "fatal: size_t will not fit in a cell (srfi-4)\n"); abort(); } scm_tc16_uvec = scm_make_smob_type ("uvec", 0); scm_set_smob_equalp (scm_tc16_uvec, uvec_equalp); scm_set_smob_free (scm_tc16_uvec, uvec_free); scm_set_smob_print (scm_tc16_uvec, uvec_print); #include "srfi/srfi-4.x" }