20 #include "int64x64-cairo.h"
36 #define OUTPUT_SIGN(sa,sb,ua,ub) \
38 negA = _cairo_int128_negative (sa); \
39 negB = _cairo_int128_negative (sb); \
40 ua = _cairo_int128_to_uint128 (sa); \
41 ub = _cairo_int128_to_uint128 (sb); \
42 ua = negA ? _cairo_uint128_negate (ua) : ua; \
43 ub = negB ? _cairo_uint128_negate (ub) : ub; \
44 (negA && !negB) || (!negA && negB); })
47 int64x64_t::Mul (int64x64_t
const &o)
49 cairo_uint128_t a, b, result;
50 bool sign = OUTPUT_SIGN (_v, o._v, a, b);
52 _v = sign ? _cairo_uint128_negate (result) : result;
62 int64x64_t::Umul (cairo_uint128_t a, cairo_uint128_t b)
64 cairo_uint128_t result;
65 cairo_uint128_t hiPart,loPart,midPart;
71 loPart = _cairo_uint64x64_128_mul (a.lo, b.lo);
73 midPart = _cairo_uint128_add (_cairo_uint64x64_128_mul (a.lo, b.hi),
74 _cairo_uint64x64_128_mul (a.hi, b.lo));
76 result.lo = _cairo_uint64_add (loPart.hi,midPart.lo);
78 hiPart = _cairo_uint64x64_128_mul (a.hi, b.hi);
80 result.hi = _cairo_uint64_add (hiPart.lo,midPart.hi);
83 "High precision 128 bits multiplication error: multiplication overflow.");
88 int64x64_t::Div (int64x64_t
const &o)
90 cairo_uint128_t a, b, result;
91 bool sign = OUTPUT_SIGN (_v, o._v, a, b);
93 _v = sign ? _cairo_uint128_negate (result) : result;
97 int64x64_t::Udiv (cairo_uint128_t a, cairo_uint128_t b)
100 cairo_uint128_t result = _cairo_uint128_lsl (qr.quo, 64);
102 cairo_uint128_t tmp = _cairo_uint128_rsl (qr.rem, 64);
103 cairo_uint128_t zero = _cairo_uint64_to_uint128 (0);
104 cairo_uint128_t rem, div;
105 if (_cairo_uint128_eq (tmp, zero))
107 rem = _cairo_uint128_lsl (qr.rem, 64);
113 div = _cairo_uint128_rsl (b, 64);
115 qr = _cairo_uint128_divrem (rem, div);
116 result = _cairo_uint128_add (result, qr.quo);
121 int64x64_t::MulByInvert (
const int64x64_t &o)
123 bool negResult = _cairo_int128_negative (_v);
124 cairo_uint128_t a = negResult ? _cairo_int128_negate (_v) : _v;
125 cairo_uint128_t result = UmulByInvert (a, o._v);
127 _v = negResult ? _cairo_int128_negate (result) : result;
130 int64x64_t::UmulByInvert (cairo_uint128_t a, cairo_uint128_t b)
132 cairo_uint128_t result;
133 cairo_uint128_t hi, mid;
134 hi = _cairo_uint64x64_128_mul (a.hi, b.hi);
135 mid = _cairo_uint128_add (_cairo_uint64x64_128_mul (a.hi, b.lo),
136 _cairo_uint64x64_128_mul (a.lo, b.hi));
139 result = _cairo_uint128_add (hi,mid);
143 int64x64_t::Invert (uint64_t v)
146 cairo_uint128_t a, factor;
152 result._v = Udiv (a, factor);
153 int64x64_t tmp = int64x64_t (v, 0);
154 tmp.MulByInvert (result);
155 if (tmp.GetHigh () != 1)
157 cairo_uint128_t one = { 1, 0};
158 result._v = _cairo_uint128_add (result._v, one);
168 #include "cairo-wideint.c"
#define NS_ASSERT(condition)
#define NS_LOG_COMPONENT_DEFINE(name)
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if cond is true.