Revision 6046c620 include/qemu/int128.h
b/include/qemu/int128.h | ||
---|---|---|
1 | 1 |
#ifndef INT128_H |
2 | 2 |
#define INT128_H |
3 | 3 |
|
4 |
#include <assert.h> |
|
5 |
#include <stdint.h> |
|
6 |
#include <stdbool.h> |
|
7 |
|
|
4 | 8 |
typedef struct Int128 Int128; |
5 | 9 |
|
6 | 10 |
struct Int128 { |
... | ... | |
55 | 59 |
|
56 | 60 |
static inline Int128 int128_add(Int128 a, Int128 b) |
57 | 61 |
{ |
58 |
Int128 r = { a.lo + b.lo, a.hi + b.hi }; |
|
59 |
r.hi += (r.lo < a.lo) || (r.lo < b.lo); |
|
60 |
return r; |
|
62 |
uint64_t lo = a.lo + b.lo; |
|
63 |
|
|
64 |
/* a.lo <= a.lo + b.lo < a.lo + k (k is the base, 2^64). Hence, |
|
65 |
* a.lo + b.lo >= k implies 0 <= lo = a.lo + b.lo - k < a.lo. |
|
66 |
* Similarly, a.lo + b.lo < k implies a.lo <= lo = a.lo + b.lo < k. |
|
67 |
* |
|
68 |
* So the carry is lo < a.lo. |
|
69 |
*/ |
|
70 |
return (Int128) { lo, (uint64_t)a.hi + b.hi + (lo < a.lo) }; |
|
61 | 71 |
} |
62 | 72 |
|
63 | 73 |
static inline Int128 int128_neg(Int128 a) |
64 | 74 |
{ |
65 |
a.lo = ~a.lo; |
|
66 |
a.hi = ~a.hi; |
|
67 |
return int128_add(a, int128_one()); |
|
75 |
uint64_t lo = -a.lo; |
|
76 |
return (Int128) { lo, ~(uint64_t)a.hi + !lo }; |
|
68 | 77 |
} |
69 | 78 |
|
70 | 79 |
static inline Int128 int128_sub(Int128 a, Int128 b) |
71 | 80 |
{ |
72 |
return int128_add(a, int128_neg(b));
|
|
81 |
return (Int128){ a.lo - b.lo, a.hi - b.hi - (a.lo < b.lo) };
|
|
73 | 82 |
} |
74 | 83 |
|
75 | 84 |
static inline bool int128_nonneg(Int128 a) |
... | ... | |
89 | 98 |
|
90 | 99 |
static inline bool int128_ge(Int128 a, Int128 b) |
91 | 100 |
{ |
92 |
return int128_nonneg(int128_sub(a, b));
|
|
101 |
return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo);
|
|
93 | 102 |
} |
94 | 103 |
|
95 | 104 |
static inline bool int128_lt(Int128 a, Int128 b) |
Also available in: Unified diff