summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@bitplanet.net>2012-05-11 23:36:20 -0400
committerKristian Høgsberg <krh@bitplanet.net>2012-05-14 09:36:38 -0400
commitf5df38959b14426f648b3359821457786e43e396 (patch)
tree1dfe052fd8e63e6337403aa32c631c9dd8a8ad28
parentfefa8c0fd5fe9b186ca1acffcc077badbd81b5ba (diff)
Optimize wl_fixed_t to/from double conversion functions
-rw-r--r--src/connection.c2
-rw-r--r--src/wayland-util.h34
-rw-r--r--tests/Makefile.am9
-rw-r--r--tests/fixed-benchmark.c88
-rw-r--r--tests/fixed-test.c90
5 files changed, 211 insertions, 12 deletions
diff --git a/src/connection.c b/src/connection.c
index a888940..5b7965e 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -853,7 +853,7 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target, int send)
break;
case 'f':
si = (int32_t) value->uint32;
- fprintf(stderr, "%f", (double) si / 256.0);
+ fprintf(stderr, "%f", wl_fixed_to_double(si));
break;
case 's':
fprintf(stderr, "\"%s\"", value->string);
diff --git a/src/wayland-util.h b/src/wayland-util.h
index 8def7ee..fa5c6c5 100644
--- a/src/wayland-util.h
+++ b/src/wayland-util.h
@@ -167,18 +167,32 @@ void *wl_array_add(struct wl_array *array, size_t size);
void wl_array_copy(struct wl_array *array, struct wl_array *source);
typedef int32_t wl_fixed_t;
-#define WL_FIXED_INVALID_VALUE ~0L
-static inline double wl_fixed_to_double(wl_fixed_t f)
+static inline double
+wl_fixed_to_double (wl_fixed_t f)
{
- return (double) f / 256.0;
-};
-static inline wl_fixed_t wl_fixed_from_double(double d)
+ union {
+ double d;
+ int64_t i;
+ } u;
+
+ u.i = ((1023LL + 44LL) << 52) + (1LL << 51) + f;
+
+ return u.d - (3LL << 43);
+}
+
+static inline wl_fixed_t
+wl_fixed_from_double(double d)
{
- if (d >= (1 << 23))
- return WL_FIXED_INVALID_VALUE;
- return (wl_fixed_t) round (d * 256.0);
-};
+ union {
+ double d;
+ int64_t i;
+ } u;
+
+ u.d = d + (3LL << (51 - 8));
+
+ return u.i;
+}
static inline int wl_fixed_to_int(wl_fixed_t f)
{
@@ -186,7 +200,7 @@ static inline int wl_fixed_to_int(wl_fixed_t f)
}
static inline wl_fixed_t wl_fixed_from_int(int i)
{
- return wl_fixed_from_double(i);
+ return i * 256;
}
#ifdef __cplusplus
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 767919e..9fdf040 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -6,12 +6,16 @@ TESTS = \
connection-test \
event-loop-test \
client-test \
- os-wrappers-test
+ os-wrappers-test \
+ fixed-test
check_PROGRAMS = \
$(TESTS) \
exec-fd-leak-checker
+noinst_PROGRAMS = \
+ fixed-benchmark
+
test_runner_src = test-runner.c test-runner.h test-helpers.c
sanity_test_SOURCES = sanity-test.c $(test_runner_src)
@@ -21,6 +25,9 @@ list_test_SOURCES = list-test.c $(test_runner_src)
connection_test_SOURCES = connection-test.c $(test_runner_src)
event_loop_test_SOURCES = event-loop-test.c $(test_runner_src)
client_test_SOURCES = client-test.c $(test_runner_src)
+fixed_test_SOURCES = fixed-test.c $(test_runner_src)
+
+fixed_benchmark_SOURCES = fixed-benchmark.c
os_wrappers_test_SOURCES = \
os-wrappers-test.c \
diff --git a/tests/fixed-benchmark.c b/tests/fixed-benchmark.c
new file mode 100644
index 0000000..3f7aae3
--- /dev/null
+++ b/tests/fixed-benchmark.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 "../src/wayland-private.h"
+
+volatile double global_d;
+
+static void
+magic_conversion(void)
+{
+ wl_fixed_t f;
+
+ for (f = 0; f < INT32_MAX; f++)
+ global_d = wl_fixed_to_double(f);
+}
+
+static void
+mul_conversion(void)
+{
+ wl_fixed_t f;
+
+ /* This will get optimized into multiplication by 1/256 */
+ for (f = 0; f < INT32_MAX; f++)
+ global_d = f / 256.0;
+}
+
+double factor = 256.0;
+
+static void
+div_conversion(void)
+{
+ wl_fixed_t f;
+
+ for (f = 0; f < INT32_MAX; f++)
+ global_d = f / 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("magic", magic_conversion);
+ benchmark("div", div_conversion);
+ benchmark("mul", mul_conversion);
+
+ return 0;
+}
diff --git a/tests/fixed-test.c b/tests/fixed-test.c
new file mode 100644
index 0000000..16fa5ff
--- /dev/null
+++ b/tests/fixed-test.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * 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 <assert.h>
+#include "../src/wayland-private.h"
+#include "test-runner.h"
+
+TEST(fixed_double_conversions)
+{
+ wl_fixed_t f;
+ double d;
+
+ d = 62.125;
+ f = wl_fixed_from_double(d);
+ fprintf(stderr, "double %lf to fixed %x\n", d, f);
+ assert(f == 0x3e20);
+
+ d = -1200.625;
+ f = wl_fixed_from_double(d);
+ fprintf(stderr, "double %lf to fixed %x\n", d, f);
+ assert(f == -0x4b0a0);
+
+ f = random();
+ d = wl_fixed_to_double(f);
+ fprintf(stderr, "fixed %x to double %lf\n", f, d);
+ assert(d == f / 256.0);
+
+ f = 0x012030;
+ d = wl_fixed_to_double(f);
+ fprintf(stderr, "fixed %x to double %lf\n", f, d);
+ assert(d == 288.1875);
+
+ f = 0x70000000;
+ d = wl_fixed_to_double(f);
+ fprintf(stderr, "fixed %x to double %lf\n", f, d);
+ assert(d == f / 256);
+
+ f = -0x012030;
+ d = wl_fixed_to_double(f);
+ fprintf(stderr, "fixed %x to double %lf\n", f, d);
+ assert(d == -288.1875);
+
+ f = 0x80000000;
+ d = wl_fixed_to_double(f);
+ fprintf(stderr, "fixed %x to double %lf\n", f, d);
+ assert(d == f / 256);
+}
+
+TEST(fixed_int_conversions)
+{
+ wl_fixed_t f;
+ int i;
+
+ i = 62;
+ f = wl_fixed_from_int(i);
+ assert(f == 62 * 256);
+
+ i = -2080;
+ f = wl_fixed_from_int(i);
+ assert(f == -2080 * 256);
+
+ f = 0x277013;
+ i = wl_fixed_to_int(f);
+ assert(i == 0x2770);
+
+ f = -0x5044;
+ i = wl_fixed_to_int(f);
+ assert(i == -0x50);
+}