[PATCH weston v2 12/21] Introduce a 'double fixed' data type abstraction
Giulio Camuffo
giuliocamuffo at gmail.com
Wed May 13 03:44:02 PDT 2015
2015-05-13 13:26 GMT+03:00 Jonas Ådahl <jadahl at gmail.com>:
> The 'double fixed' value type is a fixed point data type implemented as
> two signed 32 bit integers. It is intended to be sent over the wire and
> used when wl_fixed_t is not detailed enough.
>
> Two helper functions are introduced: wl_double_fixed_to_double and
> wl_double_fixed_from_double that can be used for conversion.
>
> The type is implemented by separating the integral part from the
> fractional part, storing them in individual signed 32 bit integers.
>
> Converting to a double could be implemented with:
>
> double = integral + fraction / 2147483648
>
> Converting to a double could be implemented with:
>
> integral = integral part of double
> fraction = fractional part of double * 2147483648
>
> The implementation provided in this patch is slightly faster than the
> above methods, but assumes that the IEEE 754 double-precision binary
> floating-point format is used internally. It is based on the wl_fixed_t
> conversion functions from wayland-util.h.
>
> Signed-off-by: Jonas Ådahl <jadahl at gmail.com>
> ---
> Makefile.am | 6 +++
> shared/util.h | 57 +++++++++++++++++++++
> tests/double-fixed-benchmark.c | 110 +++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 173 insertions(+)
> create mode 100644 shared/util.h
> create mode 100644 tests/double-fixed-benchmark.c
>
> diff --git a/Makefile.am b/Makefile.am
> index 2f16fac..0a30cb4 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -990,6 +990,7 @@ noinst_PROGRAMS += \
> $(shared_tests) \
> $(weston_tests) \
> $(ivi_tests) \
> + double-fixed-benchmark \
> matrix-test
>
> test_module_ldflags = \
> @@ -1102,6 +1103,11 @@ matrix_test_SOURCES = \
> matrix_test_CPPFLAGS = -DUNIT_TEST
> matrix_test_LDADD = -lm -lrt
>
> +double_fixed_benchmark_SOURCES = \
> + tests/double-fixed-benchmark.c \
> + shared/util.h
> +double_fixed_benchmark_LDADD = -lm
> +
> if ENABLE_IVI_SHELL
> module_tests += \
> ivi-layout-internal-test.la \
> diff --git a/shared/util.h b/shared/util.h
> new file mode 100644
> index 0000000..97a6f9b
> --- /dev/null
> +++ b/shared/util.h
> @@ -0,0 +1,57 @@
> +/*
> + * Copyright © 2008 Kristian Høgsberg
> + * Copyright © 2015 Red Hat Inc.
> + *
> + * Permission to use, copy, modify, distribute, and sell this software and its
> + * documentation for any purpose is hereby granted without fee, provided that
> + * the above copyright notice appear in all copies and that both that copyright
> + * notice and this permission notice appear in supporting documentation, and
> + * that the name of the copyright holders not be used in advertising or
> + * publicity pertaining to distribution of the software without specific,
> + * written prior permission. The copyright holders make no representations
> + * about the suitability of this software for any purpose. It is provided "as
> + * is" without express or implied warranty.
> + *
> + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
> + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
> + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
> + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
> + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
> + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
> + * OF THIS SOFTWARE.
> + */
> +
> +#ifndef WESTON_SHARED_UTIL_H
> +#define WESTON_SHARED_UTIL_H
> +
> +#include <math.h>
> +
> +static inline double
> +wl_double_fixed_to_double(int32_t i, int32_t f)
Should we have a struct wl_fixed_double_t { int32 i, int32 t } instead
of having the two ints separated?
> +{
> + union {
> + double d;
> + int64_t i;
> + } u;
> +
> + u.i = ((1023LL + (52LL - 31LL)) << 52) + (1LL << 51) + f;
> +
> + return i + (u.d - (3LL << (52 - 32)));
> +}
> +
> +static inline void
> +wl_double_fixed_from_double(double d, int32_t *i, int32_t *f)
> +{
> + double integral;
> + union {
> + double d;
> + int64_t i;
> + } u;
> +
> + u.d = modf(d, &integral) + (3LL << (51 - 31));
> +
> + *i = integral;
> + *f = u.i;
> +}
> +
> +#endif /* WESTON_SHARED_UTIL_H */
> diff --git a/tests/double-fixed-benchmark.c b/tests/double-fixed-benchmark.c
> new file mode 100644
> index 0000000..e4e5685
> --- /dev/null
> +++ b/tests/double-fixed-benchmark.c
> @@ -0,0 +1,110 @@
> +/*
> + * Copyright © 2012 Intel Corporation
> + * Copyright © 2015 Red Hat Inc.
> + *
> + * Permission to use, copy, modify, distribute, and sell this software and its
> + * documentation for any purpose is hereby granted without fee, provided that
> + * the above copyright notice appear in all copies and that both that copyright
> + * notice and this permission notice appear in supporting documentation, and
> + * that the name of the copyright holders not be used in advertising or
> + * publicity pertaining to distribution of the software without specific,
> + * written prior permission. The copyright holders make no representations
> + * about the suitability of this software for any purpose. It is provided "as
> + * is" without express or implied warranty.
> + *
> + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
> + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
> + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
> + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
> + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
> + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
> + * OF THIS SOFTWARE.
> + */
> +
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <time.h>
> +#include <assert.h>
> +#include <stdint.h>
> +#include "shared/util.h"
> +
> +volatile double global_d;
> +
> +static void
> +noop_conversion(void)
> +{
> + int32_t fp;
> +
> + union {
> + int64_t i;
> + double d;
> + } u;
> +
> + for (fp = 0; fp < INT32_MAX; fp++) {
> + u.i = fp;
> + global_d = u.d;
> + }
> +}
> +
> +static void
> +magic_conversion(void)
> +{
> + int32_t fp;
> +
> + for (fp = 0; fp < INT32_MAX; fp++) {
> + global_d = wl_double_fixed_to_double(fp, fp);
> + }
> +}
> +
> +static void
> +mul_conversion(void)
> +{
> + int32_t fp;
> +
> + for (fp = 0; fp < INT32_MAX; fp++) {
> + global_d = fp + fp / 2147483648.0;
> + }
> +}
> +
> +double factor = 2147483648.0;
> +
> +static void
> +div_conversion(void)
> +{
> + int32_t fp;
> +
> + for (fp = 0; fp < INT32_MAX; fp++) {
> + global_d = fp + fp / factor;
> + }
> +}
> +
> +static void
> +benchmark(const char *s, void (*f)(void))
> +{
> + struct timespec start, stop, elapsed;
> +
> + clock_gettime(CLOCK_MONOTONIC, &start);
> + f();
> + clock_gettime(CLOCK_MONOTONIC, &stop);
> +
> + elapsed.tv_sec = stop.tv_sec - start.tv_sec;
> + elapsed.tv_nsec = stop.tv_nsec - start.tv_nsec;
> + if (elapsed.tv_nsec < 0) {
> + elapsed.tv_nsec += 1000000000;
> + elapsed.tv_sec--;
> + }
> + printf("benchmarked %s:\t%ld.%09lds\n",
> + s, elapsed.tv_sec, elapsed.tv_nsec);
> +}
> +
> +int
> +main(int argc, char *argv[])
> +{
> + benchmark("noop", noop_conversion);
> + benchmark("magic", magic_conversion);
> + benchmark("div", div_conversion);
> + benchmark("mul", mul_conversion);
> +
> + return 0;
> +}
> --
> 2.1.4
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
More information about the wayland-devel
mailing list