diff options
author | Ludovic Courtès <ludo@gnu.org> | 2011-07-01 16:21:21 +0200 |
---|---|---|
committer | Ludovic Courtès <ludo@gnu.org> | 2011-07-01 16:21:21 +0200 |
commit | 1e8f93922922b09c7003a357d86777b2a79e9735 (patch) | |
tree | 1b675f82f6ffca4601b4d434ad21661981d97b15 | |
parent | e780c14fd0fd2572eaebc2949f6a67fc773c2835 (diff) | |
download | guile-1e8f93922922b09c7003a357d86777b2a79e9735.tar.gz |
Fix unaligned accesses for bytevectors of complex numbers.
* libguile/bytevectors.c (bytevector_ref_c32, bytevector_ref_c64,
bytevector_set_c32, bytevector_set_c64): Use `memcpy' to avoid
unaligned accesses. This fixes SIGBUS on SPARC and possibly other
alignment-sensitive platforms.
-rw-r--r-- | libguile/bytevectors.c | 44 |
1 files changed, 34 insertions, 10 deletions
diff --git a/libguile/bytevectors.c b/libguile/bytevectors.c index 5a83967c3..b8af53ad3 100644 --- a/libguile/bytevectors.c +++ b/libguile/bytevectors.c @@ -2096,17 +2096,27 @@ SCM_DEFINE (scm_utf32_to_string, "utf32->string", static SCM bytevector_ref_c32 (SCM bv, SCM idx) { /* FIXME add some checks */ - const float *contents = (const float*)SCM_BYTEVECTOR_CONTENTS (bv); + float real, imag; + const char *contents = (char *) SCM_BYTEVECTOR_CONTENTS (bv); size_t i = scm_to_size_t (idx); - return scm_c_make_rectangular (contents[i/4], contents[i/4 + 1]); + + memcpy (&real, &contents[i], sizeof (float)); + memcpy (&imag, &contents[i + sizeof (float)], sizeof (float)); + + return scm_c_make_rectangular (real, imag); } static SCM bytevector_ref_c64 (SCM bv, SCM idx) { /* FIXME add some checks */ - const double *contents = (const double*)SCM_BYTEVECTOR_CONTENTS (bv); + double real, imag; + const char *contents = (char *) SCM_BYTEVECTOR_CONTENTS (bv); size_t i = scm_to_size_t (idx); - return scm_c_make_rectangular (contents[i/8], contents[i/8 + 1]); + + memcpy (&real, &contents[i], sizeof (double)); + memcpy (&imag, &contents[i + sizeof (double)], sizeof (double)); + + return scm_c_make_rectangular (real, imag); } typedef SCM (*scm_t_bytevector_ref_fn)(SCM, SCM); @@ -2146,19 +2156,33 @@ bv_handle_ref (scm_t_array_handle *h, size_t index) /* FIXME add checks!!! */ static SCM bytevector_set_c32 (SCM bv, SCM idx, SCM val) -{ float *contents = (float*)SCM_BYTEVECTOR_CONTENTS (bv); +{ + float imag, real; + char *contents = (char *) SCM_BYTEVECTOR_CONTENTS (bv); size_t i = scm_to_size_t (idx); - contents[i/4] = scm_c_real_part (val); - contents[i/4 + 1] = scm_c_imag_part (val); + + real = scm_c_real_part (val); + imag = scm_c_imag_part (val); + + memcpy (&contents[i], &real, sizeof (float)); + memcpy (&contents[i + sizeof (float)], &imag, sizeof (float)); + return SCM_UNSPECIFIED; } static SCM bytevector_set_c64 (SCM bv, SCM idx, SCM val) -{ double *contents = (double*)SCM_BYTEVECTOR_CONTENTS (bv); +{ + double imag, real; + char *contents = (char *) SCM_BYTEVECTOR_CONTENTS (bv); size_t i = scm_to_size_t (idx); - contents[i/8] = scm_c_real_part (val); - contents[i/8 + 1] = scm_c_imag_part (val); + + real = scm_c_real_part (val); + imag = scm_c_imag_part (val); + + memcpy (&contents[i], &real, sizeof (double)); + memcpy (&contents[i + sizeof (double)], &imag, sizeof (double)); + return SCM_UNSPECIFIED; } |