aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2013-06-20 16:19:32 +0200
committerPaolo Bonzini <pbonzini@redhat.com>2013-07-02 08:17:01 +0200
commit6046c620866f6f5c53eaece9f4ad8d44a12e1185 (patch)
tree54fcfbdf8f15d62f5e2c8ac9d2f43f80222ee9b7 /include
parent1acd5a373905ddb28957842256a038956941f332 (diff)
int128: optimize and add test cases
For add, the carry only requires checking one of the arguments. For sub and neg, we can similarly optimize computation of the carry. For ge, we can just do lexicographic order. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'include')
-rw-r--r--include/qemu/int128.h25
1 files changed, 17 insertions, 8 deletions
diff --git a/include/qemu/int128.h b/include/qemu/int128.h
index bfe7678a04..9ed47aafd3 100644
--- a/include/qemu/int128.h
+++ b/include/qemu/int128.h
@@ -1,6 +1,10 @@
#ifndef INT128_H
#define INT128_H
+#include <assert.h>
+#include <stdint.h>
+#include <stdbool.h>
+
typedef struct Int128 Int128;
struct Int128 {
@@ -55,21 +59,26 @@ static inline Int128 int128_rshift(Int128 a, int n)
static inline Int128 int128_add(Int128 a, Int128 b)
{
- Int128 r = { a.lo + b.lo, a.hi + b.hi };
- r.hi += (r.lo < a.lo) || (r.lo < b.lo);
- return r;
+ uint64_t lo = a.lo + b.lo;
+
+ /* a.lo <= a.lo + b.lo < a.lo + k (k is the base, 2^64). Hence,
+ * a.lo + b.lo >= k implies 0 <= lo = a.lo + b.lo - k < a.lo.
+ * Similarly, a.lo + b.lo < k implies a.lo <= lo = a.lo + b.lo < k.
+ *
+ * So the carry is lo < a.lo.
+ */
+ return (Int128) { lo, (uint64_t)a.hi + b.hi + (lo < a.lo) };
}
static inline Int128 int128_neg(Int128 a)
{
- a.lo = ~a.lo;
- a.hi = ~a.hi;
- return int128_add(a, int128_one());
+ uint64_t lo = -a.lo;
+ return (Int128) { lo, ~(uint64_t)a.hi + !lo };
}
static inline Int128 int128_sub(Int128 a, Int128 b)
{
- return int128_add(a, int128_neg(b));
+ return (Int128){ a.lo - b.lo, a.hi - b.hi - (a.lo < b.lo) };
}
static inline bool int128_nonneg(Int128 a)
@@ -89,7 +98,7 @@ static inline bool int128_ne(Int128 a, Int128 b)
static inline bool int128_ge(Int128 a, Int128 b)
{
- return int128_nonneg(int128_sub(a, b));
+ return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo);
}
static inline bool int128_lt(Int128 a, Int128 b)