summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2011-07-01 16:21:21 +0200
committerLudovic Courtès <ludo@gnu.org>2011-07-01 16:21:21 +0200
commit1e8f93922922b09c7003a357d86777b2a79e9735 (patch)
tree1b675f82f6ffca4601b4d434ad21661981d97b15
parente780c14fd0fd2572eaebc2949f6a67fc773c2835 (diff)
downloadguile-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.c44
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;
}