The OpenD Programming Language

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