1 /* 128 bit integer arithmetic.
2  *
3  * Not optimized for speed.
4  *
5  * Copyright: Copyright D Language Foundation 2022.
6  * License:   $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
7  * Authors:   Walter Bright
8  * Source:    $(DRUNTIMESRC core/_int128.d)
9  */
10 
11 module core.int128;
12 
13 nothrow:
14 @safe:
15 @nogc:
16 
17 alias I = long;
18 alias U = ulong;
19 enum Ubits = uint(U.sizeof * 8);
20 
21 version (DigitalMars)
22 {
23     /* The alignment should follow target.stackAlign(),
24      * which is `isXmmSupported() ? 16 : (is64bit ? 8 : 4)
25      */
26     version (D_SIMD)
27         private enum Cent_alignment = 16;
28     else version (X86_64)
29         private enum Cent_alignment = 8;
30     else
31         private enum Cent_alignment = 4;
32 }
33 else
34 {
35     version (X86_64) private enum Cent_alignment = 16;
36     else             private enum Cent_alignment = (size_t.sizeof * 2);
37 }
38 
39 align(Cent_alignment) struct Cent
40 {
41     version (LittleEndian)
42     {
43         U lo;  // low 64 bits
44         U hi;  // high 64 bits
45     }
46     else
47     {
48         U hi;  // high 64 bits
49         U lo;  // low 64 bits
50     }
51 }
52 
53 enum Cent One = { lo:1 };
54 enum Cent Zero = { lo:0 };
55 enum Cent MinusOne = neg(One);
56 
57 /*****************************
58  * Test against 0
59  * Params:
60  *      c = Cent to test
61  * Returns:
62  *      true if != 0
63  */
64 pure
65 bool tst(Cent c)
66 {
67     return c.hi || c.lo;
68 }
69 
70 
71 /*****************************
72  * Complement
73  * Params:
74  *      c = Cent to complement
75  * Returns:
76  *      complemented value
77  */
78 pure
79 Cent com(Cent c)
80 {
81     c.lo = ~c.lo;
82     c.hi = ~c.hi;
83     return c;
84 }
85 
86 /*****************************
87  * Negate
88  * Params:
89  *      c = Cent to negate
90  * Returns:
91  *      negated value
92  */
93 pure
94 Cent neg(Cent c)
95 {
96     if (c.lo == 0)
97         c.hi = -c.hi;
98     else
99     {
100         c.lo = -c.lo;
101         c.hi = ~c.hi;
102     }
103     return c;
104 }
105 
106 /*****************************
107  * Increment
108  * Params:
109  *      c = Cent to increment
110  * Returns:
111  *      incremented value
112  */
113 pure
114 Cent inc(Cent c)
115 {
116     return add(c, One);
117 }
118 
119 /*****************************
120  * Decrement
121  * Params:
122  *      c = Cent to decrement
123  * Returns:
124  *      incremented value
125  */
126 pure
127 Cent dec(Cent c)
128 {
129     return sub(c, One);
130 }
131 
132 /*****************************
133  * Shift left one bit
134  * Params:
135  *      c = Cent to shift
136  * Returns:
137  *      shifted value
138  */
139 pure
140 Cent shl1(Cent c)
141 {
142     c.hi = (c.hi << 1) | (cast(I)c.lo < 0);
143     c.lo <<= 1;
144     return c;
145 }
146 
147 /*****************************
148  * Unsigned shift right one bit
149  * Params:
150  *      c = Cent to shift
151  * Returns:
152  *      shifted value
153  */
154 pure
155 Cent shr1(Cent c)
156 {
157     c.lo = (c.lo >> 1) | ((c.hi & 1) << (Ubits - 1));
158     c.hi >>= 1;
159     return c;
160 }
161 
162 
163 /*****************************
164  * Arithmetic shift right one bit
165  * Params:
166  *      c = Cent to shift
167  * Returns:
168  *      shifted value
169  */
170 pure
171 Cent sar1(Cent c)
172 {
173     c.lo = (c.lo >> 1) | ((c.hi & 1) << (Ubits - 1));
174     c.hi = cast(I)c.hi >> 1;
175     return c;
176 }
177 
178 /*****************************
179  * Shift left n bits
180  * Params:
181  *      c = Cent to shift
182  *      n = number of bits to shift
183  * Returns:
184  *      shifted value
185  */
186 pure
187 Cent shl(Cent c, uint n)
188 {
189     if (n >= Ubits * 2)
190         return Zero;
191 
192     if (n >= Ubits)
193     {
194         c.hi = c.lo << (n - Ubits);
195         c.lo = 0;
196     }
197     else
198     {
199         c.hi = ((c.hi << n) | (c.lo >> (Ubits - n - 1) >> 1));
200         c.lo = c.lo << n;
201     }
202     return c;
203 }
204 
205 /*****************************
206  * Unsigned shift right n bits
207  * Params:
208  *      c = Cent to shift
209  *      n = number of bits to shift
210  * Returns:
211  *      shifted value
212  */
213 pure
214 Cent shr(Cent c, uint n)
215 {
216     if (n >= Ubits * 2)
217         return Zero;
218 
219     if (n >= Ubits)
220     {
221         c.lo = c.hi >> (n - Ubits);
222         c.hi = 0;
223     }
224     else
225     {
226         c.lo = ((c.lo >> n) | (c.hi << (Ubits - n - 1) << 1));
227         c.hi = c.hi >> n;
228     }
229     return c;
230 }
231 
232 /*****************************
233  * Arithmetic shift right n bits
234  * Params:
235  *      c = Cent to shift
236  *      n = number of bits to shift
237  * Returns:
238  *      shifted value
239  */
240 pure
241 Cent sar(Cent c, uint n)
242 {
243     const signmask = -(c.hi >> (Ubits - 1));
244     const signshift = (Ubits * 2) - n;
245     c = shr(c, n);
246 
247     // Sign extend all bits beyond the precision of Cent.
248     if (n >= Ubits * 2)
249     {
250         c.hi = signmask;
251         c.lo = signmask;
252     }
253     else if (signshift >= Ubits * 2)
254     {
255     }
256     else if (signshift >= Ubits)
257     {
258         c.hi &= ~(U.max << (signshift - Ubits));
259         c.hi |= signmask << (signshift - Ubits);
260     }
261     else
262     {
263         c.hi = signmask;
264         c.lo &= ~(U.max << signshift);
265         c.lo |= signmask << signshift;
266     }
267     return c;
268 }
269 
270 /*****************************
271  * Rotate left one bit
272  * Params:
273  *      c = Cent to rotate
274  * Returns:
275  *      rotated value
276  */
277 pure
278 Cent rol1(Cent c)
279 {
280     int carry = cast(I)c.hi < 0;
281 
282     c.hi = (c.hi << 1) | (cast(I)c.lo < 0);
283     c.lo = (c.lo << 1) | carry;
284     return c;
285 }
286 
287 /*****************************
288  * Rotate right one bit
289  * Params:
290  *      c = Cent to rotate
291  * Returns:
292  *      rotated value
293  */
294 pure
295 Cent ror1(Cent c)
296 {
297     int carry = c.lo & 1;
298     c.lo = (c.lo >> 1) | (cast(U)(c.hi & 1) << (Ubits - 1));
299     c.hi = (c.hi >> 1) | (cast(U)carry << (Ubits - 1));
300     return c;
301 }
302 
303 
304 /*****************************
305  * Rotate left n bits
306  * Params:
307  *      c = Cent to rotate
308  *      n = number of bits to rotate
309  * Returns:
310  *      rotated value
311  */
312 pure
313 Cent rol(Cent c, uint n)
314 {
315     n &= Ubits * 2 - 1;
316     Cent l = shl(c, n);
317     Cent r = shr(c, Ubits * 2 - n);
318     return or(l, r);
319 }
320 
321 /*****************************
322  * Rotate right n bits
323  * Params:
324  *      c = Cent to rotate
325  *      n = number of bits to rotate
326  * Returns:
327  *      rotated value
328  */
329 pure
330 Cent ror(Cent c, uint n)
331 {
332     n &= Ubits * 2 - 1;
333     Cent r = shr(c, n);
334     Cent l = shl(c, Ubits * 2 - n);
335     return or(r, l);
336 }
337 
338 /****************************
339  * And c1 & c2.
340  * Params:
341  *      c1 = operand 1
342  *      c2 = operand 2
343  * Returns:
344  *      c1 & c2
345  */
346 pure
347 Cent and(Cent c1, Cent c2)
348 {
349     const Cent ret = { lo:c1.lo & c2.lo, hi:c1.hi & c2.hi };
350     return ret;
351 }
352 
353 /****************************
354  * Or c1 | c2.
355  * Params:
356  *      c1 = operand 1
357  *      c2 = operand 2
358  * Returns:
359  *      c1 | c2
360  */
361 pure
362 Cent or(Cent c1, Cent c2)
363 {
364     const Cent ret = { lo:c1.lo | c2.lo, hi:c1.hi | c2.hi };
365     return ret;
366 }
367 
368 /****************************
369  * Xor c1 ^ c2.
370  * Params:
371  *      c1 = operand 1
372  *      c2 = operand 2
373  * Returns:
374  *      c1 ^ c2
375  */
376 pure
377 Cent xor(Cent c1, Cent c2)
378 {
379     const Cent ret = { lo:c1.lo ^ c2.lo, hi:c1.hi ^ c2.hi };
380     return ret;
381 }
382 
383 /****************************
384  * Add c1 to c2.
385  * Params:
386  *      c1 = operand 1
387  *      c2 = operand 2
388  * Returns:
389  *      c1 + c2
390  */
391 pure
392 Cent add(Cent c1, Cent c2)
393 {
394     U r = cast(U)(c1.lo + c2.lo);
395     const Cent ret = { lo:r, hi:cast(U)(c1.hi + c2.hi + (r < c1.lo)) };
396     return ret;
397 }
398 
399 /****************************
400  * Subtract c2 from c1.
401  * Params:
402  *      c1 = operand 1
403  *      c2 = operand 2
404  * Returns:
405  *      c1 - c2
406  */
407 pure
408 Cent sub(Cent c1, Cent c2)
409 {
410     return add(c1, neg(c2));
411 }
412 
413 /****************************
414  * Multiply c1 * c2.
415  * Params:
416  *      c1 = operand 1
417  *      c2 = operand 2
418  * Returns:
419  *      c1 * c2
420  */
421 pure
422 Cent mul(Cent c1, Cent c2)
423 {
424     enum mulmask = (1UL << (Ubits / 2)) - 1;
425     enum mulshift = Ubits / 2;
426 
427     // This algorithm splits the operands into 4 words, then computes and sums
428     // the partial products of each part.
429     const c2l0 = c2.lo & mulmask;
430     const c2l1 = c2.lo >> mulshift;
431     const c2h0 = c2.hi & mulmask;
432     const c2h1 = c2.hi >> mulshift;
433 
434     const c1l0 = c1.lo & mulmask;
435     U r0 = c1l0 * c2l0;
436     U r1 = c1l0 * c2l1 + (r0 >> mulshift);
437     U r2 = c1l0 * c2h0 + (r1 >> mulshift);
438     U r3 = c1l0 * c2h1 + (r2 >> mulshift);
439 
440     const c1l1 = c1.lo >> mulshift;
441     r1 = c1l1 * c2l0 + (r1 & mulmask);
442     r2 = c1l1 * c2l1 + (r2 & mulmask) + (r1 >> mulshift);
443     r3 = c1l1 * c2h0 + (r3 & mulmask) + (r2 >> mulshift);
444 
445     const c1h0 = c1.hi & mulmask;
446     r2 = c1h0 * c2l0 + (r2 & mulmask);
447     r3 = c1h0 * c2l1 + (r3 & mulmask) + (r2 >> mulshift);
448 
449     const c1h1 = c1.hi >> mulshift;
450     r3 = c1h1 * c2l0 + (r3 & mulmask);
451 
452     const Cent ret = { lo:(r0 & mulmask) + (r1 & mulmask) * (mulmask + 1),
453                        hi:(r2 & mulmask) + (r3 & mulmask) * (mulmask + 1) };
454     return ret;
455 }
456 
457 
458 /****************************
459  * Unsigned divide c1 / c2.
460  * Params:
461  *      c1 = dividend
462  *      c2 = divisor
463  * Returns:
464  *      quotient c1 / c2
465  */
466 pure
467 Cent udiv(Cent c1, Cent c2)
468 {
469     Cent modulus;
470     return udivmod(c1, c2, modulus);
471 }
472 
473 /****************************
474  * Unsigned divide c1 / c2. The remainder after division is stored to modulus.
475  * Params:
476  *      c1 = dividend
477  *      c2 = divisor
478  *      modulus = set to c1 % c2
479  * Returns:
480  *      quotient c1 / c2
481  */
482 pure
483 Cent udivmod(Cent c1, Cent c2, out Cent modulus)
484 {
485     //printf("udiv c1(%llx,%llx) c2(%llx,%llx)\n", c1.lo, c1.hi, c2.lo, c2.hi);
486     // Based on "Unsigned Doubleword Division" in Hacker's Delight
487     import core.bitop;
488 
489     // Divides a 128-bit dividend by a 64-bit divisor.
490     // The result must fit in 64 bits.
491     static U udivmod128_64(Cent c1, U c2, out U modulus)
492     {
493         // We work in base 2^^32
494         enum base = 1UL << 32;
495         enum divmask = (1UL << (Ubits / 2)) - 1;
496         enum divshift = Ubits / 2;
497 
498         // Check for overflow and divide by 0
499         if (c1.hi >= c2)
500         {
501             modulus = 0UL;
502             return ~0UL;
503         }
504 
505         // Computes [num1 num0] / den
506         static uint udiv96_64(U num1, uint num0, U den)
507         {
508             // Extract both digits of the denominator
509             const den1 = cast(uint)(den >> divshift);
510             const den0 = cast(uint)(den & divmask);
511             // Estimate ret as num1 / den1, and then correct it
512             U ret = num1 / den1;
513             const t2 = (num1 % den1) * base + num0;
514             const t1 = ret * den0;
515             if (t1 > t2)
516                 ret -= (t1 - t2 > den) ? 2 : 1;
517             return cast(uint)ret;
518         }
519 
520         // Determine the normalization factor. We multiply c2 by this, so that its leading
521         // digit is at least half base. In binary this means just shifting left by the number
522         // of leading zeros, so that there's a 1 in the MSB.
523         // We also shift number by the same amount. This cannot overflow because c1.hi < c2.
524         const shift = (Ubits - 1) - bsr(c2);
525         c2 <<= shift;
526         U num2 = c1.hi;
527         num2 <<= shift;
528         num2 |= (c1.lo >> (-shift & 63)) & (-cast(I)shift >> 63);
529         c1.lo <<= shift;
530 
531         // Extract the low digits of the numerator (after normalizing)
532         const num1 = cast(uint)(c1.lo >> divshift);
533         const num0 = cast(uint)(c1.lo & divmask);
534 
535         // Compute q1 = [num2 num1] / c2
536         const q1 = udiv96_64(num2, num1, c2);
537         // Compute the true (partial) remainder
538         const rem = num2 * base + num1 - q1 * c2;
539         // Compute q0 = [rem num0] / c2
540         const q0 = udiv96_64(rem, num0, c2);
541 
542         modulus = (rem * base + num0 - q0 * c2) >> shift;
543         return (cast(U)q1 << divshift) | q0;
544     }
545 
546     // Special cases
547     if (!tst(c2))
548     {
549         // Divide by zero
550         modulus = Zero;
551         return com(modulus);
552     }
553     if (c1.hi == 0 && c2.hi == 0)
554     {
555         // Single precision divide
556         const Cent rem = { lo:c1.lo % c2.lo };
557         modulus = rem;
558         const Cent ret = { lo:c1.lo / c2.lo };
559         return ret;
560     }
561     if (c1.hi == 0)
562     {
563         // Numerator is smaller than the divisor
564         modulus = c1;
565         return Zero;
566     }
567     if (c2.hi == 0)
568     {
569         // Divisor is a 64-bit value, so we just need one 128/64 division.
570         // If c1 / c2 would overflow, break c1 up into two halves.
571         const q1 = (c1.hi < c2.lo) ? 0 : (c1.hi / c2.lo);
572         if (q1)
573             c1.hi = c1.hi % c2.lo;
574         Cent rem;
575         const q0 = udivmod128_64(c1, c2.lo, rem.lo);
576         modulus = rem;
577         const Cent ret = { lo:q0, hi:q1 };
578         return ret;
579     }
580 
581     // Full cent precision division.
582     // Here c2 >= 2^^64
583     // We know that c2.hi != 0, so count leading zeros is OK
584     // We have 0 <= shift <= 63
585     const shift = (Ubits - 1) - bsr(c2.hi);
586 
587     // Normalize the divisor so its MSB is 1
588     // v1 = (c2 << shift) >> 64
589     U v1 = shl(c2, shift).hi;
590 
591     // To ensure no overflow.
592     Cent u1 = shr1(c1);
593 
594     // Get quotient from divide unsigned operation.
595     U rem_ignored;
596     const Cent q1 = { lo:udivmod128_64(u1, v1, rem_ignored) };
597 
598     // Undo normalization and division of c1 by 2.
599     Cent quotient = shr(shl(q1, shift), 63);
600 
601     // Make quotient correct or too small by 1
602     if (tst(quotient))
603         quotient = dec(quotient);
604 
605     // Now quotient is correct.
606     // Compute rem = c1 - (quotient * c2);
607     Cent rem = sub(c1, mul(quotient, c2));
608 
609     // Check if remainder is larger than the divisor
610     if (uge(rem, c2))
611     {
612         // Increment quotient
613         quotient = inc(quotient);
614         // Subtract c2 from remainder
615         rem = sub(rem, c2);
616     }
617     modulus = rem;
618     //printf("quotient "); print(quotient);
619     //printf("modulus  "); print(modulus);
620     return quotient;
621 }
622 
623 
624 /****************************
625  * Signed divide c1 / c2.
626  * Params:
627  *      c1 = dividend
628  *      c2 = divisor
629  * Returns:
630  *      quotient c1 / c2
631  */
632 pure
633 Cent div(Cent c1, Cent c2)
634 {
635     Cent modulus;
636     return divmod(c1, c2, modulus);
637 }
638 
639 /****************************
640  * Signed divide c1 / c2. The remainder after division is stored to modulus.
641  * Params:
642  *      c1 = dividend
643  *      c2 = divisor
644  *      modulus = set to c1 % c2
645  * Returns:
646  *      quotient c1 / c2
647  */
648 pure
649 Cent divmod(Cent c1, Cent c2, out Cent modulus)
650 {
651     /* Muck about with the signs so we can use the unsigned divide
652      */
653     if (cast(I)c1.hi < 0)
654     {
655         if (cast(I)c2.hi < 0)
656         {
657             Cent r = udivmod(neg(c1), neg(c2), modulus);
658             modulus = neg(modulus);
659             return r;
660         }
661         Cent r = neg(udivmod(neg(c1), c2, modulus));
662         modulus = neg(modulus);
663         return r;
664     }
665     else if (cast(I)c2.hi < 0)
666     {
667         return neg(udivmod(c1, neg(c2), modulus));
668     }
669     else
670         return udivmod(c1, c2, modulus);
671 }
672 
673 /****************************
674  * If c1 > c2 unsigned
675  * Params:
676  *      c1 = operand 1
677  *      c2 = operand 2
678  * Returns:
679  *      true if c1 > c2
680  */
681 pure
682 bool ugt(Cent c1, Cent c2)
683 {
684     return (c1.hi == c2.hi) ? (c1.lo > c2.lo) : (c1.hi > c2.hi);
685 }
686 
687 /****************************
688  * If c1 >= c2 unsigned
689  * Params:
690  *      c1 = operand 1
691  *      c2 = operand 2
692  * Returns:
693  *      true if c1 >= c2
694  */
695 pure
696 bool uge(Cent c1, Cent c2)
697 {
698     return !ugt(c2, c1);
699 }
700 
701 /****************************
702  * If c1 < c2 unsigned
703  * Params:
704  *      c1 = operand 1
705  *      c2 = operand 2
706  * Returns:
707  *      true if c1 < c2
708  */
709 pure
710 bool ult(Cent c1, Cent c2)
711 {
712     return ugt(c2, c1);
713 }
714 
715 /****************************
716  * If c1 <= c2 unsigned
717  * Params:
718  *      c1 = operand 1
719  *      c2 = operand 2
720  * Returns:
721  *      true if c1 <= c2
722  */
723 pure
724 bool ule(Cent c1, Cent c2)
725 {
726     return !ugt(c1, c2);
727 }
728 
729 /****************************
730  * If c1 > c2 signed
731  * Params:
732  *      c1 = operand 1
733  *      c2 = operand 2
734  * Returns:
735  *      true if c1 > c2
736  */
737 pure
738 bool gt(Cent c1, Cent c2)
739 {
740     return (c1.hi == c2.hi)
741         ? (c1.lo > c2.lo)
742         : (cast(I)c1.hi > cast(I)c2.hi);
743 }
744 
745 /****************************
746  * If c1 >= c2 signed
747  * Params:
748  *      c1 = operand 1
749  *      c2 = operand 2
750  * Returns:
751  *      true if c1 >= c2
752  */
753 pure
754 bool ge(Cent c1, Cent c2)
755 {
756     return !gt(c2, c1);
757 }
758 
759 /****************************
760  * If c1 < c2 signed
761  * Params:
762  *      c1 = operand 1
763  *      c2 = operand 2
764  * Returns:
765  *      true if c1 < c2
766  */
767 pure
768 bool lt(Cent c1, Cent c2)
769 {
770     return gt(c2, c1);
771 }
772 
773 /****************************
774  * If c1 <= c2 signed
775  * Params:
776  *      c1 = operand 1
777  *      c2 = operand 2
778  * Returns:
779  *      true if c1 <= c2
780  */
781 pure
782 bool le(Cent c1, Cent c2)
783 {
784     return !gt(c1, c2);
785 }
786 
787 /*******************************************************/
788 
789 version (unittest)
790 {
791     version (none)
792     {
793         import core.stdc.stdio;
794 
795         @trusted
796         void print(Cent c)
797         {
798             printf("%lld, %lld\n", cast(ulong)c.lo, cast(ulong)c.hi);
799             printf("x%llx, x%llx\n", cast(ulong)c.lo, cast(ulong)c.hi);
800         }
801     }
802 }
803 
804 unittest
805 {
806     const Cent C0 = Zero;
807     const Cent C1 = One;
808     const Cent C2 = { lo:2 };
809     const Cent C3 = { lo:3 };
810     const Cent C5 = { lo:5 };
811     const Cent C10 = { lo:10 };
812     const Cent C20 = { lo:20 };
813     const Cent C30 = { lo:30 };
814     const Cent C100 = { lo:100 };
815 
816     const Cent Cm1 =  neg(One);
817     const Cent Cm3 =  neg(C3);
818     const Cent Cm10 = neg(C10);
819 
820     const Cent C3_1 = { lo:1, hi:3 };
821     const Cent C3_2 = { lo:2, hi:3 };
822     const Cent C4_8  = { lo:8, hi:4 };
823     const Cent C5_0  = { lo:0, hi:5 };
824     const Cent C7_1 = { lo:1, hi:7 };
825     const Cent C7_9 = { lo:9, hi:7 };
826     const Cent C9_3 = { lo:3, hi:9 };
827     const Cent C10_0 = { lo:0, hi:10 };
828     const Cent C10_1 = { lo:1, hi:10 };
829     const Cent C10_3 = { lo:3, hi:10 };
830     const Cent C11_3 = { lo:3, hi:11 };
831     const Cent C20_0 = { lo:0, hi:20 };
832     const Cent C90_30 = { lo:30, hi:90 };
833 
834     const Cent Cm10_0 = inc(com(C10_0)); // Cent(lo=0,  hi=-10);
835     const Cent Cm10_1 = inc(com(C10_1)); // Cent(lo=-1, hi=-11);
836     const Cent Cm10_3 = inc(com(C10_3)); // Cent(lo=-3, hi=-11);
837     const Cent Cm20_0 = inc(com(C20_0)); // Cent(lo=0,  hi=-20);
838 
839     enum Cent Cs_3 = { lo:3, hi:I.min };
840 
841     const Cent Cbig_1 = { lo:0xa3ccac1832952398, hi:0xc3ac542864f652f8 };
842     const Cent Cbig_2 = { lo:0x5267b85f8a42fc20, hi:0 };
843     const Cent Cbig_3 = { lo:0xf0000000ffffffff, hi:0 };
844 
845     /************************/
846 
847     assert( ugt(C1, C0) );
848     assert( ult(C1, C2) );
849     assert( uge(C1, C0) );
850     assert( ule(C1, C2) );
851 
852     assert( !ugt(C0, C1) );
853     assert( !ult(C2, C1) );
854     assert( !uge(C0, C1) );
855     assert( !ule(C2, C1) );
856 
857     assert( !ugt(C1, C1) );
858     assert( !ult(C1, C1) );
859     assert( uge(C1, C1) );
860     assert( ule(C2, C2) );
861 
862     assert( ugt(C10_3, C10_1) );
863     assert( ugt(C11_3, C10_3) );
864     assert( !ugt(C9_3, C10_3) );
865     assert( !ugt(C9_3, C9_3) );
866 
867     assert( gt(C2, C1) );
868     assert( !gt(C1, C2) );
869     assert( !gt(C1, C1) );
870     assert( gt(C0, Cm1) );
871     assert( gt(Cm1, neg(C10)));
872     assert( !gt(Cm1, Cm1) );
873     assert( !gt(Cm1, C0) );
874 
875     assert( !lt(C2, C1) );
876     assert( !le(C2, C1) );
877     assert( ge(C2, C1) );
878 
879     assert(neg(C10_0) == Cm10_0);
880     assert(neg(C10_1) == Cm10_1);
881     assert(neg(C10_3) == Cm10_3);
882 
883     assert(add(C7_1,C3_2) == C10_3);
884     assert(sub(C1,C2) == Cm1);
885 
886     assert(inc(C3_1) == C3_2);
887     assert(dec(C3_2) == C3_1);
888 
889     assert(shl(C10,0) == C10);
890     assert(shl(C10,Ubits) == C10_0);
891     assert(shl(C10,1) == C20);
892     assert(shl(C10,Ubits * 2) == C0);
893     assert(shr(C10_0,0) == C10_0);
894     assert(shr(C10_0,Ubits) == C10);
895     assert(shr(C10_0,Ubits - 1) == C20);
896     assert(shr(C10_0,Ubits + 1) == C5);
897     assert(shr(C10_0,Ubits * 2) == C0);
898     assert(sar(C10_0,0) == C10_0);
899     assert(sar(C10_0,Ubits) == C10);
900     assert(sar(C10_0,Ubits - 1) == C20);
901     assert(sar(C10_0,Ubits + 1) == C5);
902     assert(sar(C10_0,Ubits * 2) == C0);
903     assert(sar(Cm1,Ubits * 2) == Cm1);
904 
905     assert(shl1(C10) == C20);
906     assert(shr1(C10_0) == C5_0);
907     assert(sar1(C10_0) == C5_0);
908     assert(sar1(Cm1) == Cm1);
909 
910     Cent modulus;
911 
912     assert(udiv(C10,C2) == C5);
913     assert(udivmod(C10,C2, modulus) ==  C5);   assert(modulus == C0);
914     assert(udivmod(C10,C3, modulus) ==  C3);   assert(modulus == C1);
915     assert(udivmod(C10,C0, modulus) == Cm1);   assert(modulus == C0);
916     assert(udivmod(C2,C90_30, modulus) == C0); assert(modulus == C2);
917     assert(udiv(mul(C90_30, C2), C2) == C90_30);
918     assert(udiv(mul(C90_30, C2), C90_30) == C2);
919 
920     assert(div(C10,C3) == C3);
921     assert(divmod( C10,  C3, modulus) ==  C3); assert(modulus ==  C1);
922     assert(divmod(Cm10,  C3, modulus) == Cm3); assert(modulus == Cm1);
923     assert(divmod( C10, Cm3, modulus) == Cm3); assert(modulus ==  C1);
924     assert(divmod(Cm10, Cm3, modulus) ==  C3); assert(modulus == Cm1);
925     assert(divmod(C2, C90_30, modulus) == C0); assert(modulus == C2);
926     assert(div(mul(C90_30, C2), C2) == C90_30);
927     assert(div(mul(C90_30, C2), C90_30) == C2);
928 
929     const Cent Cb1divb2 = { lo:0x4496aa309d4d4a2f, hi:U.max };
930     const Cent Cb1modb2 = { lo:0xd83203d0fdc799b8, hi:U.max };
931     assert(divmod(Cbig_1, Cbig_2, modulus) == Cb1divb2);
932     assert(modulus == Cb1modb2);
933 
934     const Cent Cb1udivb2 = { lo:0x5fe0e9bace2bedad, hi:2 };
935     const Cent Cb1umodb2 = { lo:0x2c923125a68721f8, hi:0 };
936     assert(udivmod(Cbig_1, Cbig_2, modulus) == Cb1udivb2);
937     assert(modulus == Cb1umodb2);
938 
939     const Cent Cb1divb3 = { lo:0xbfa6c02b5aff8b86, hi:U.max };
940     const Cent Cb1udivb3 = { lo:0xd0b7d13b48cb350f, hi:0 };
941     assert(div(Cbig_1, Cbig_3) == Cb1divb3);
942     assert(udiv(Cbig_1, Cbig_3) == Cb1udivb3);
943 
944     assert(mul(Cm10, C1) == Cm10);
945     assert(mul(C1, Cm10) == Cm10);
946     assert(mul(C9_3, C10) == C90_30);
947     assert(mul(Cs_3, C10) == C30);
948     assert(mul(Cm10, Cm10) == C100);
949     assert(mul(C20_0, Cm1) == Cm20_0);
950 
951     assert( or(C4_8, C3_1) == C7_9);
952     assert(and(C4_8, C7_9) == C4_8);
953     assert(xor(C4_8, C7_9) == C3_1);
954 
955     assert(rol(Cm1,  1) == Cm1);
956     assert(ror(Cm1, 45) == Cm1);
957     assert(rol(ror(C7_9, 5), 5) == C7_9);
958     assert(rol(C7_9, 1) == rol1(C7_9));
959     assert(ror(C7_9, 1) == ror1(C7_9));
960 }