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-11 23:36:20 -0400
commitf266d2d83fdeadac2673e1d15cf3e3509abeeaa0 (patch)
tree5f3c535cf7d67dcaca3c1f4633cb8fd6254cf6d2
parentfefa8c0fd5fe9b186ca1acffcc077badbd81b5ba (diff)
Optimize wl_fixed_t to/from double conversion functionsfixed-optimization
-rw-r--r--src/connection.c2
-rw-r--r--src/wayland-util.h34
-rw-r--r--tests/Makefile.am4
-rw-r--r--tests/fixed-test.c90
4 files changed, 118 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..3ba6928 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -6,7 +6,8 @@ TESTS = \
connection-test \
event-loop-test \
client-test \
- os-wrappers-test
+ os-wrappers-test \
+ fixed-test
check_PROGRAMS = \
$(TESTS) \
@@ -21,6 +22,7 @@ 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)
os_wrappers_test_SOURCES = \
os-wrappers-test.c \
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);
+}