cairo_int64_t
_cairo_int32x32_64_mul (int32_t a, int32_t b)
{
cairo_int64_t s;
s = _cairo_uint32x32_64_mul ((uint32_t) a, (uint32_t) b); if (a < 0)
s.hi -= b; if (b < 0)
s.hi -= a; return s;
}
cairo_uint64_t
_cairo_uint64_mul (cairo_uint64_t a, cairo_uint64_t b)
{
cairo_uint64_t s;
int
_cairo_uint64_lt (cairo_uint64_t a, cairo_uint64_t b)
{ return (a.hi < b.hi ||
(a.hi == b.hi && a.lo < b.lo));
}
int
_cairo_uint64_eq (cairo_uint64_t a, cairo_uint64_t b)
{ return a.hi == b.hi && a.lo == b.lo;
}
int
_cairo_int64_lt (cairo_int64_t a, cairo_int64_t b)
{ if (_cairo_int64_negative (a) && !_cairo_int64_negative (b)) return1; if (!_cairo_int64_negative (a) && _cairo_int64_negative (b)) return0; return _cairo_uint64_lt (a, b);
}
int
_cairo_uint64_cmp (cairo_uint64_t a, cairo_uint64_t b)
{ if (a.hi < b.hi) return -1; elseif (a.hi > b.hi) return1; elseif (a.lo < b.lo) return -1; elseif (a.lo > b.lo) return1; else return0;
}
int
_cairo_int64_cmp (cairo_int64_t a, cairo_int64_t b)
{ if (_cairo_int64_negative (a) && !_cairo_int64_negative (b)) return -1; if (!_cairo_int64_negative (a) && _cairo_int64_negative (b)) return1;
/* normalize to make den >= num, but not overflow */ while (_cairo_uint64_lt (den, num) && (den.hi & 0x80000000) == 0)
{
bit = _cairo_uint64_lsl (bit, 1);
den = _cairo_uint64_lsl (den, 1);
}
quo = _cairo_uint32_to_uint64 (0);
/* generate quotient, one bit at a time */ while (bit.hi | bit.lo)
{ if (_cairo_uint64_le (den, num))
{
num = _cairo_uint64_sub (num, den);
quo = _cairo_uint64_add (quo, bit);
}
bit = _cairo_uint64_rsl (bit, 1);
den = _cairo_uint64_rsl (den, 1);
}
qr.quo = quo;
qr.rem = num; return qr;
}
int
_cairo_int128_cmp (cairo_int128_t a, cairo_int128_t b)
{ if (_cairo_int128_negative (a) && !_cairo_int128_negative (b)) return -1; if (!_cairo_int128_negative (a) && _cairo_int128_negative (b)) return1;
return _cairo_uint128_cmp (a, b);
}
int
_cairo_uint128_eq (cairo_uint128_t a, cairo_uint128_t b)
{ return (_cairo_uint64_eq (a.hi, b.hi) &&
_cairo_uint64_eq (a.lo, b.lo));
}
/* normalize to make den >= num, but not overflow */ while (_cairo_uint128_lt (den, num) && !_cairo_msbset64(den.hi))
{
bit = _cairo_uint128_lsl (bit, 1);
den = _cairo_uint128_lsl (den, 1);
}
quo = _cairo_uint32_to_uint128 (0);
/* generate quotient, one bit at a time */ while (_cairo_uint128_ne (bit, _cairo_uint32_to_uint128(0)))
{ if (_cairo_uint128_le (den, num))
{
num = _cairo_uint128_sub (num, den);
quo = _cairo_uint128_add (quo, bit);
}
bit = _cairo_uint128_rsl (bit, 1);
den = _cairo_uint128_rsl (den, 1);
}
qr.quo = quo;
qr.rem = num; return qr;
}
/* These are the high 64 bits of the *96* bit numerator. We're *goingtorepresentthenumeratorasxB+y,wherexisa64,
* and y is a 32 bit number. */
cairo_uint64_t x = _cairo_uint128_to_uint64 (_cairo_uint128_rsl(num, 32));
/* Initialise the result to indicate overflow. */
result.quo = _cairo_uint32s_to_uint64 (-1U, -1U);
result.rem = den;
/* Don't bother if the quotient is going to overflow. */ if (_cairo_uint64_ge (x, den)) { return/* overflow */ result;
}
if (_cairo_uint64_lt (x, B)) { /* When the final quotient is known to fit in 32 bits, then
* num < 2^64 if and only if den < 2^32. */ return _cairo_uint64_divrem (_cairo_uint128_to_uint64 (num), den);
} else { /* Denominator is >= 2^32. the numerator is >= 2^64, and the *divisionwon'toverflow:needtwodivrems.Writethe *numeratoranddenominatoras * *num=xB+yx:64bits,y:32bits *den=uB+vu,v:32bits
*/
uint32_t y = _cairo_uint128_to_uint32 (num);
uint32_t u = uint64_hi32 (den);
uint32_t v = _cairo_uint64_to_uint32 (den);
/* Compute a lower bound approximate quotient of num/den *fromx/(u+1).Thenwehave * *x=q(u+1)+r;q:32bits,r<=u:32bits. * *xB+y=q(u+1)B+(rB+y) *=q(uB+B+v-v)+(rB+y) *=q(uB+v)+qB-qv+(rB+y) *=q(uB+v)+q(B-v)+(rB+y) * *Thetruequotientofnum/denthenisqplusthe *contributionofq(B-v)+(rB+y).Themaincontribution *comesfromthetermq(B-v),withtheterm(rB+y)only *contributingatmostonepart. * *Thetermq(B-v)mustfitinto64bits,sinceqfitsinto32 *bitsonaccountofbeingalowerboundtothetrue *quotient,andasB-v<=2^32,wemaysafelyuseasingle
* 64/64 bit division to find its contribution. */
cairo_uquorem64_t quorem;
cairo_uint64_t remainder; /* will contain final remainder */
uint32_t quotient; /* will contain final quotient. */
uint32_t q;
uint32_t r;
/* Approximate quotient by dividing the high 64 bits of num by
* u+1. Watch out for overflow of u+1. */ if (u+1) {
quorem = _cairo_uint64_divrem (x, _cairo_uint32_to_uint64 (u+1));
q = _cairo_uint64_to_uint32 (quorem.quo);
r = _cairo_uint64_to_uint32 (quorem.rem);
} else {
q = uint64_hi32 (x);
r = _cairo_uint64_to_uint32 (x);
}
quotient = q;
/* Add the main term's contribution to quotient. Note B-v =
* -v as an uint32 (unless v = 0) */ if (v)
quorem = _cairo_uint64_divrem (_cairo_uint32x32_64_mul (q, -v), den); else
quorem = _cairo_uint64_divrem (_cairo_uint32s_to_uint64 (q, 0), den);
quotient += _cairo_uint64_to_uint32 (quorem.quo);
/* Add the contribution of the subterm and start computing the
* true remainder. */
remainder = _cairo_uint32s_to_uint64 (r, y); if (_cairo_uint64_ge (remainder, den)) {
remainder = _cairo_uint64_sub (remainder, den);
quotient++;
}
/* Add the contribution of the main term's remainder. The *funkytestherechecksthatremainder+main_rem>=den,
* taking into account overflow of the addition. */
remainder = _cairo_uint64_add (remainder, quorem.rem); if (_cairo_uint64_ge (remainder, den) ||
_cairo_uint64_lt (remainder, quorem.rem))
{
remainder = _cairo_uint64_sub (remainder, den);
quotient++;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.