31 #include "cairo-wideint-private.h"
35 #define _cairo_uint32s_to_uint64(h,l) ((uint64_t) (h) << 32 | (l))
38 _cairo_uint64_divrem (cairo_uint64_t num, cairo_uint64_t den)
50 _cairo_uint32_to_uint64 (uint32_t i)
60 _cairo_int32_to_int64 (int32_t i)
65 q.hi = i < 0 ? -1 : 0;
70 _cairo_uint32s_to_uint64 (uint32_t h, uint32_t l)
80 _cairo_uint64_add (cairo_uint64_t a, cairo_uint64_t b)
92 _cairo_uint64_sub (cairo_uint64_t a, cairo_uint64_t b)
103 #define uint32_lo(i) ((i) & 0xffff)
104 #define uint32_hi(i) ((i) >> 16)
105 #define uint32_carry16 ((1) << 16)
108 _cairo_uint32x32_64_mul (uint32_t a, uint32_t b)
112 uint16_t ah, al, bh, bl;
113 uint32_t r0, r1, r2, r3;
120 r0 = (uint32_t) al * bl;
121 r1 = (uint32_t) al * bh;
122 r2 = (uint32_t) ah * bl;
123 r3 = (uint32_t) ah * bh;
128 r3 += uint32_carry16;
130 s.hi = r3 + uint32_hi(r1);
131 s.lo = (uint32_lo (r1) << 16) + uint32_lo (r0);
136 _cairo_int32x32_64_mul (int32_t a, int32_t b)
139 s = _cairo_uint32x32_64_mul ((uint32_t) a, (uint32_t) b);
148 _cairo_uint64_mul (cairo_uint64_t a, cairo_uint64_t b)
152 s = _cairo_uint32x32_64_mul (a.lo, b.lo);
153 s.hi += a.lo * b.hi + a.hi * b.lo;
158 _cairo_uint64_lsl (cairo_uint64_t a,
int shift)
168 a.hi = a.hi << shift | a.lo >> (32 - shift);
169 a.lo = a.lo << shift;
175 _cairo_uint64_rsl (cairo_uint64_t a,
int shift)
185 a.lo = a.lo >> shift | a.hi << (32 - shift);
186 a.hi = a.hi >> shift;
191 #define _cairo_uint32_rsa(a,n) ((uint32_t) (((int32_t) (a)) >> (n)))
194 _cairo_uint64_rsa (cairo_int64_t a,
int shift)
199 a.hi = _cairo_uint32_rsa (a.hi, 31);
204 a.lo = a.lo >> shift | a.hi << (32 - shift);
205 a.hi = _cairo_uint32_rsa (a.hi, shift);
211 _cairo_uint64_lt (cairo_uint64_t a, cairo_uint64_t b)
213 return (a.hi < b.hi ||
214 (a.hi == b.hi && a.lo < b.lo));
218 _cairo_uint64_eq (cairo_uint64_t a, cairo_uint64_t b)
220 return a.hi == b.hi && a.lo == b.lo;
224 _cairo_int64_lt (cairo_int64_t a, cairo_int64_t b)
226 if (_cairo_int64_negative (a) && !_cairo_int64_negative (b))
228 if (!_cairo_int64_negative (a) && _cairo_int64_negative (b))
230 return _cairo_uint64_lt (a, b);
234 _cairo_uint64_not (cairo_uint64_t a)
242 _cairo_uint64_negate (cairo_uint64_t a)
255 _cairo_uint64_divrem (cairo_uint64_t num, cairo_uint64_t den)
261 bit = _cairo_uint32_to_uint64 (1);
264 while (_cairo_uint64_lt (den, num) && (den.hi & 0x80000000) == 0)
266 bit = _cairo_uint64_lsl (bit, 1);
267 den = _cairo_uint64_lsl (den, 1);
269 quo = _cairo_uint32_to_uint64 (0);
272 while (bit.hi | bit.lo)
274 if (_cairo_uint64_le (den, num))
276 num = _cairo_uint64_sub (num, den);
277 quo = _cairo_uint64_add (quo, bit);
279 bit = _cairo_uint64_rsl (bit, 1);
280 den = _cairo_uint64_rsl (den, 1);
290 _cairo_int64_divrem (cairo_int64_t num, cairo_int64_t den)
292 int num_neg = _cairo_int64_negative (num);
293 int den_neg = _cairo_int64_negative (den);
298 num = _cairo_int64_negate (num);
300 den = _cairo_int64_negate (den);
301 uqr = _cairo_uint64_divrem (num, den);
303 qr.rem = _cairo_int64_negate (uqr.rem);
306 if (num_neg != den_neg)
307 qr.quo = (cairo_int64_t) _cairo_int64_negate (uqr.quo);
309 qr.quo = (cairo_int64_t) uqr.quo;
316 _cairo_uint128_divrem (cairo_uint128_t num, cairo_uint128_t den)
328 _cairo_uint32_to_uint128 (uint32_t i)
332 q.lo = _cairo_uint32_to_uint64 (i);
333 q.hi = _cairo_uint32_to_uint64 (0);
338 _cairo_int32_to_int128 (int32_t i)
342 q.lo = _cairo_int32_to_int64 (i);
343 q.hi = _cairo_int32_to_int64 (i < 0 ? -1 : 0);
348 _cairo_uint64_to_uint128 (cairo_uint64_t i)
353 q.hi = _cairo_uint32_to_uint64 (0);
358 _cairo_int64_to_int128 (cairo_int64_t i)
363 q.hi = _cairo_int32_to_int64 (_cairo_int64_negative(i) ? -1 : 0);
368 _cairo_uint128_add (cairo_uint128_t a, cairo_uint128_t b)
372 s.hi = _cairo_uint64_add (a.hi, b.hi);
373 s.lo = _cairo_uint64_add (a.lo, b.lo);
374 if (_cairo_uint64_lt (s.lo, a.lo))
375 s.hi = _cairo_uint64_add (s.hi, _cairo_uint32_to_uint64 (1));
380 _cairo_uint128_sub (cairo_uint128_t a, cairo_uint128_t b)
384 s.hi = _cairo_uint64_sub (a.hi, b.hi);
385 s.lo = _cairo_uint64_sub (a.lo, b.lo);
386 if (_cairo_uint64_gt (s.lo, a.lo))
387 s.hi = _cairo_uint64_sub (s.hi, _cairo_uint32_to_uint64(1));
393 #define uint64_lo32(i) ((i) & 0xffffffff)
394 #define uint64_hi32(i) ((i) >> 32)
395 #define uint64_lo(i) ((i) & 0xffffffff)
396 #define uint64_hi(i) ((i) >> 32)
397 #define uint64_shift32(i) ((i) << 32)
398 #define uint64_carry32 (((uint64_t) 1) << 32)
402 #define uint64_lo32(i) ((i).lo)
403 #define uint64_hi32(i) ((i).hi)
405 static cairo_uint64_t
406 uint64_lo (cairo_uint64_t i)
415 static cairo_uint64_t
416 uint64_hi (cairo_uint64_t i)
425 static cairo_uint64_t
426 uint64_shift32 (cairo_uint64_t i)
435 static const cairo_uint64_t uint64_carry32 = { 0, 1 };
440 _cairo_uint64x64_128_mul (cairo_uint64_t a, cairo_uint64_t b)
443 uint32_t ah, al, bh, bl;
444 cairo_uint64_t r0, r1, r2, r3;
446 al = uint64_lo32 (a);
447 ah = uint64_hi32 (a);
448 bl = uint64_lo32 (b);
449 bh = uint64_hi32 (b);
451 r0 = _cairo_uint32x32_64_mul (al, bl);
452 r1 = _cairo_uint32x32_64_mul (al, bh);
453 r2 = _cairo_uint32x32_64_mul (ah, bl);
454 r3 = _cairo_uint32x32_64_mul (ah, bh);
456 r1 = _cairo_uint64_add (r1, uint64_hi (r0));
457 r1 = _cairo_uint64_add (r1, r2);
458 if (_cairo_uint64_lt (r1, r2))
459 r3 = _cairo_uint64_add (r3, uint64_carry32);
461 s.hi = _cairo_uint64_add (r3, uint64_hi(r1));
462 s.lo = _cairo_uint64_add (uint64_shift32 (r1),
468 _cairo_int64x64_128_mul (cairo_int64_t a, cairo_int64_t b)
471 s = _cairo_uint64x64_128_mul (_cairo_int64_to_uint64(a),
472 _cairo_int64_to_uint64(b));
473 if (_cairo_int64_negative (a))
474 s.hi = _cairo_uint64_sub (s.hi,
475 _cairo_int64_to_uint64 (b));
476 if (_cairo_int64_negative (b))
477 s.hi = _cairo_uint64_sub (s.hi,
478 _cairo_int64_to_uint64 (a));
483 _cairo_uint128_mul (cairo_uint128_t a, cairo_uint128_t b)
487 s = _cairo_uint64x64_128_mul (a.lo, b.lo);
488 s.hi = _cairo_uint64_add (s.hi,
489 _cairo_uint64_mul (a.lo, b.hi));
490 s.hi = _cairo_uint64_add (s.hi,
491 _cairo_uint64_mul (a.hi, b.lo));
496 _cairo_uint128_lsl (cairo_uint128_t a,
int shift)
501 a.lo = _cairo_uint32_to_uint64 (0);
506 a.hi = _cairo_uint64_add (_cairo_uint64_lsl (a.hi, shift),
507 _cairo_uint64_rsl (a.lo, (64 - shift)));
508 a.lo = _cairo_uint64_lsl (a.lo, shift);
514 _cairo_uint128_rsl (cairo_uint128_t a,
int shift)
519 a.hi = _cairo_uint32_to_uint64 (0);
524 a.lo = _cairo_uint64_add (_cairo_uint64_rsl (a.lo, shift),
525 _cairo_uint64_lsl (a.hi, (64 - shift)));
526 a.hi = _cairo_uint64_rsl (a.hi, shift);
537 a.hi = _cairo_uint64_rsa (a.hi, 64-1);
542 a.lo = _cairo_uint64_add (_cairo_uint64_rsl (a.lo, shift),
543 _cairo_uint64_lsl (a.hi, (64 - shift)));
544 a.hi = _cairo_uint64_rsa (a.hi, shift);
550 _cairo_uint128_lt (cairo_uint128_t a, cairo_uint128_t b)
552 return (_cairo_uint64_lt (a.hi, b.hi) ||
553 (_cairo_uint64_eq (a.hi, b.hi) &&
554 _cairo_uint64_lt (a.lo, b.lo)));
560 if (_cairo_int128_negative (a) && !_cairo_int128_negative (b))
562 if (!_cairo_int128_negative (a) && _cairo_int128_negative (b))
564 return _cairo_uint128_lt (a, b);
568 _cairo_uint128_eq (cairo_uint128_t a, cairo_uint128_t b)
570 return (_cairo_uint64_eq (a.hi, b.hi) &&
571 _cairo_uint64_eq (a.lo, b.lo));
575 #define _cairo_msbset64(q) (q & ((uint64_t) 1 << 63))
577 #define _cairo_msbset64(q) (q.hi & ((uint32_t) 1 << 31))
581 _cairo_uint128_divrem (cairo_uint128_t num, cairo_uint128_t den)
587 bit = _cairo_uint32_to_uint128 (1);
590 while (_cairo_uint128_lt (den, num) && !_cairo_msbset64(den.hi))
592 bit = _cairo_uint128_lsl (bit, 1);
593 den = _cairo_uint128_lsl (den, 1);
595 quo = _cairo_uint32_to_uint128 (0);
598 while (_cairo_uint128_ne (bit, _cairo_uint32_to_uint128(0)))
600 if (_cairo_uint128_le (den, num))
602 num = _cairo_uint128_sub (num, den);
603 quo = _cairo_uint128_add (quo, bit);
605 bit = _cairo_uint128_rsl (bit, 1);
606 den = _cairo_uint128_rsl (den, 1);
616 a.lo = _cairo_uint64_not (a.lo);
617 a.hi = _cairo_uint64_not (a.hi);
618 return _cairo_uint128_add (a, _cairo_uint32_to_uint128 (1));
624 a.lo = _cairo_uint64_not (a.lo);
625 a.hi = _cairo_uint64_not (a.hi);
634 int num_neg = _cairo_int128_negative (num);
635 int den_neg = _cairo_int128_negative (den);
640 num = _cairo_int128_negate (num);
642 den = _cairo_int128_negate (den);
643 uqr = _cairo_uint128_divrem (num, den);
645 qr.rem = _cairo_int128_negate (uqr.rem);
648 if (num_neg != den_neg)
649 qr.quo = _cairo_int128_negate (uqr.quo);
665 _cairo_uint_96by64_32x64_divrem (cairo_uint128_t num,
669 cairo_uint64_t B = _cairo_uint32s_to_uint64 (1, 0);
674 cairo_uint64_t x = _cairo_uint128_to_uint64 (_cairo_uint128_rsl(num, 32));
677 result.quo = _cairo_uint32s_to_uint64 (-1U, -1U);
681 if (_cairo_uint64_ge (x, den)) {
685 if (_cairo_uint64_lt (x, B)) {
688 return _cairo_uint64_divrem (_cairo_uint128_to_uint64 (num), den);
698 uint32_t y = _cairo_uint128_to_uint32 (num);
699 uint32_t u = uint64_hi32 (den);
700 uint32_t v = _cairo_uint64_to_uint32 (den);
723 cairo_uint64_t remainder;
731 quorem = _cairo_uint64_divrem (x, _cairo_uint32_to_uint64 (u+1));
732 q = _cairo_uint64_to_uint32 (quorem.quo);
733 r = _cairo_uint64_to_uint32 (quorem.rem);
737 r = _cairo_uint64_to_uint32 (x);
744 quorem = _cairo_uint64_divrem (_cairo_uint32x32_64_mul (q, -v), den);
746 quorem = _cairo_uint64_divrem (_cairo_uint32s_to_uint64 (q, 0), den);
747 quotient += _cairo_uint64_to_uint32 (quorem.quo);
751 remainder = _cairo_uint32s_to_uint64 (r, y);
752 if (_cairo_uint64_ge (remainder, den)) {
753 remainder = _cairo_uint64_sub (remainder, den);
760 remainder = _cairo_uint64_add (remainder, quorem.rem);
761 if (_cairo_uint64_ge (remainder, den) ||
762 _cairo_uint64_lt (remainder, quorem.rem))
764 remainder = _cairo_uint64_sub (remainder, den);
768 result.quo = _cairo_uint32_to_uint64 (quotient);
769 result.rem = remainder;
775 _cairo_int_96by64_32x64_divrem (
cairo_int128_t num, cairo_int64_t den)
777 int num_neg = _cairo_int128_negative (num);
778 int den_neg = _cairo_int64_negative (den);
779 cairo_uint64_t nonneg_den;
784 num = _cairo_int128_negate (num);
786 nonneg_den = _cairo_int64_negate (den);
790 uqr = _cairo_uint_96by64_32x64_divrem (num, nonneg_den);
791 if (_cairo_uint64_eq (uqr.rem, _cairo_int64_to_uint64 (nonneg_den))) {
793 qr.quo = _cairo_uint32s_to_uint64 (0x7FFFFFFF, -1U);;
799 qr.rem = _cairo_int64_negate (uqr.rem);
802 if (num_neg != den_neg)
803 qr.quo = _cairo_int64_negate (uqr.quo);