diff --git a/meson.build b/meson.build index 978ed8f8ea48125375e62cde6df3ab683f0b5127..13bb8027069b28e4d5646b9a230bd74215489b61 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,4 @@ -# SPDX-FileCopyrightText: 2018, 2019 Bruce Cowan -# +# SPDX-FileCopyrightText: 2018-2020 Bruce Cowan # SPDX-License-Identifier: CC0-1.0 project('stdlib', 'c', @@ -18,6 +17,10 @@ if cc.has_function('reallocarray', prefix: '#define _GNU_SOURCE\n#include <stdli conf_data.set('HAVE_REALLOCARRAY', 1) endif +if cc.has_header('endian.h') + has_endian_h = true +endif + configure_file(configuration: conf_data, output: 'config.h') config_dep = declare_dependency(include_directories: '.') diff --git a/src/bytedouble.c b/src/bytedouble.c index 35b9f65d7615848d9d39aa6cb030be257da190f6..daf6950c5664fe8113dc6a364c4cef2293a68beb 100644 --- a/src/bytedouble.c +++ b/src/bytedouble.c @@ -2,31 +2,100 @@ * SPDX-FileCopyrightText: 2020 Bruce Cowan <bruce@bcowan.me.uk> * SPDX-License-Identifier: Apache-2.0 */ + +#include <endian.h> +#include <errno.h> #include <inttypes.h> -#include <math.h> #include <stdint.h> -#include <stdio.h> #include <stdlib.h> +#include <stdio.h> +#include <string.h> -#define DOUBLE_TO_BYTES(d) ((uint8_t *) &(d)) -#define BYTES_TO_DOUBLE(b) (*((double *) (b))) +typedef union +{ + uint8_t bytes[sizeof (double)]; + double d; +} DoubleBytes; -int -main (void) +static void +bytes_to_be (uint8_t *bytes) +{ + uint64_t ret = htobe64 ((uint64_t) *(uint64_t *) bytes); + memcpy (bytes, &ret, 8); +} + +static void +bytes_from_be (uint8_t *bytes) { - double pi = M_PI; + uint64_t ret = be64toh ((uint64_t) * (uint64_t *) bytes); + memcpy (bytes, &ret, 8); +} - uint8_t *bytes = DOUBLE_TO_BYTES (pi); +static void +double_to_be_bytes (double d, + uint8_t *bytes) +{ + DoubleBytes db; + db.d = d; + bytes_to_be (db.bytes); + memcpy (bytes, db.bytes, sizeof (double)); +} + +static double +be_bytes_to_double (uint8_t *bytes) +{ + DoubleBytes db; + memcpy (db.bytes, bytes, sizeof (double)); + bytes_from_be (db.bytes); + + return db.d; +} + +static void +print_bytes (uint8_t *bytes, + size_t len) +{ printf ("Bytes are ["); - for (int i = 0; i < 7; i++) + for (size_t i = 0; i < len-1; i++) printf ("%02" PRIx8 ", ", bytes[i]); - printf ("%02" PRIx8 "]\n", bytes[7]); + printf ("%02" PRIx8 "]\n", bytes[len-1]); +} + +int +main (void) +{ + errno = 0; + char buf[32]; + char *endptr; + + puts ("Please enter a floating point number"); + fgets (buf, 31, stdin); + double val = strtod (buf, &endptr); + if (errno) + { + perror ("strtod"); + return EXIT_FAILURE; + } + if (buf == endptr) + { + fputs ("No digits found\n", stderr); + return EXIT_FAILURE; + } + + uint8_t bytes[sizeof (double)]; + + memcpy (bytes, &val, sizeof (double)); + print_bytes (bytes, sizeof (double)); + + double_to_be_bytes (val, bytes); + puts ("After swapping:"); + print_bytes (bytes, sizeof (double)); - double d = BYTES_TO_DOUBLE (bytes); - printf ("Converting back, the value is %f\n", d); + double d = be_bytes_to_double (bytes); + printf ("Converting back, the value is %.15g\n", d); return 0; } diff --git a/src/meson.build b/src/meson.build index 2682858a112beaf9a22d5d29bf919ff5fb1d5d58..4b20046244d7952dbff9a4bd3ae3e1d5e3a262bf 100644 --- a/src/meson.build +++ b/src/meson.build @@ -6,7 +6,6 @@ executable('angle', 'angle.c', dependencies: libm) executable('array-length', 'array-length.c', dependencies: types_dep) executable('binary', 'binary.c') executable('binary2', 'binary2.c', dependencies: utils_dep) -executable('bytedouble', 'bytedouble.c') executable('complex', 'complex.c', dependencies: libm) executable('doubles', 'doubles.c') executable('einstein', 'einstein.c') @@ -30,6 +29,10 @@ executable('world', 'world.c') subdir('sockets') +if has_endian_h + executable('bytedouble', 'bytedouble.c') +endif + if openmp_dep.found() subdir('openmp') endif