1 // Digit sequence arithmetic
7 #include "cl_gmpconfig.h"
9 #include "cl_DS_endian.h"
10 #include "cl_alloca.h"
14 // Digit Sequence (DS)
15 // a memory range with n digits (n an uintC),
16 // between two pointers MSDptr and LSDptr.
17 #if CL_DS_BIG_ENDIAN_P
18 // MSDptr LSDptr = MSDptr+n
19 // | MSD ............. LSD |
20 // [short: MSDptr/n/LSDptr ]
21 // In C: uintD* MSDptr, uintC len, MSDptr[0] ... MSDptr[len-1] are the digits.
23 // LSDptr MSDptr = LSDptr+n
24 // | LSD ............. MSD |
25 // In C: uintD* LSDptr, uintC len, LSDptr[0] ... LSDptr[len-1] are the digits.
27 // If n = 0, this represents the number 0.
28 // If n > 0, the most significant bit (i.e. bit (intDsize-1) of
29 // MSDptr[CL_DS_BIG_ENDIAN_P?0:-1]) is the sign bit. If the sign
30 // bit were repeated infinitely often, one would get an
31 // "infinite bit sequence".
33 // A Normalised Digit Sequence (NDS) is one for which the MSD is necessary,
34 // i.e. n = 0 or (n > 0 and the most significant intDsize+1 bits are not
37 // Unsigned Digit Sequence (UDS)
38 // like DS, but without sign.
40 // Normalized Unsigned Digit Sequence (NUDS):
41 // an UDS for which the MSD is necessary, i.e. n = 0 or
42 // (n > 0 and the most significant intDsize bits are not all zero).
44 // For the construction of constant DS, using "digit_header":
45 #define D1(byte0) (uintD)(byte0)
46 #define D2(byte0,byte1) (((uintD)(byte0)<<8)|(uintD)(byte1))
47 #define D4(byte0,byte1,byte2,byte3) (((uintD)(byte0)<<24)|((uintD)(byte1)<<16)|((uintD)(byte2)<<8)|((uintD)(byte3)))
48 #define D8(byte0,byte1,byte2,byte3,byte4,byte5,byte6,byte7) (((uintD)(byte0)<<56)|((uintD)(byte1)<<48)|((uintD)(byte2)<<40)|((uintD)(byte3)<<32)|((uintD)(byte4)<<24)|((uintD)(byte5)<<16)|((uintD)(byte6)<<8)|((uintD)(byte7)))
56 // Endianness independent access of digit sequences:
57 // mspref(MSDptr,i) access a most significant digit
58 // lspref(LSDptr,i) access a least significant digit
59 // msshrink(MSDptr) shrinks the DS by throwing away the MSD
60 // msprefnext(MSDptr) combines mspref(MSDptr,0) and msshrink(MSDptr)
61 // lsshrink(LSDptr) shrinks the DS by throwing away the LSD
62 // lsprefnext(LSDptr) combines lspref(LSDptr,0) and lsshrink(LSDptr)
63 // mspop pointer operator corresponding to msshrink, arg is widened to an uintP
64 // lspop pointer operator corresponding to lsshrink, arg is widened to an uintP
65 #if CL_DS_BIG_ENDIAN_P
66 #define mspref(p,i) (p)[i]
67 #define lspref(p,i) (p)[-(uintP)(i)-1]
68 #define msshrink(p) (p)++
69 #define msprefnext(p) (*(p)++)
70 #define lsshrink(p) (p)--
71 #define lsprefnext(p) (*--(p))
75 #define mspref(p,i) (p)[-(uintP)(i)-1]
76 #define lspref(p,i) (p)[i]
77 #define msshrink(p) (p)--
78 #define msprefnext(p) (*--(p))
79 #define lsshrink(p) (p)++
80 #define lsprefnext(p) (*(p)++)
85 // Endianness independent macros for turning an array into a digit sequence.
86 // arrayMSDptr(array,length) returns the MSDptr of array[0..length-1]
87 // arrayLSDptr(array,length) returns the LSDptr of array[0..length-1]
88 #if CL_DS_BIG_ENDIAN_P
89 #define arrayMSDptr(array,length) &(array)[0]
90 #define arrayLSDptr(array,length) &(array)[length]
92 #define arrayMSDptr(array,length) &(array)[length]
93 #define arrayLSDptr(array,length) &(array)[0]
95 #define arrayLSref(array,length,i) lspref(arrayLSDptr(array,length),i)
98 // These functions on digit sequences are either inline C++ functions
99 // or external assembler functions (see files cl_asm_*).
102 // See which functions are defined as external functions.
106 // Declare the external functions.
112 extern uintD* copy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count);
114 extern uintD* copy_loop_down (const uintD* sourceptr, uintD* destptr, uintC count);
120 extern uintD* fill_loop_up (uintD* destptr, uintC count, uintD filler);
122 extern uintD* fill_loop_down (uintD* destptr, uintC count, uintD filler);
128 extern uintD* clear_loop_up (uintD* destptr, uintC count);
130 extern uintD* clear_loop_down (uintD* destptr, uintC count);
136 extern cl_boolean test_loop_up (const uintD* ptr, uintC count);
138 extern cl_boolean test_loop_down (const uintD* ptr, uintC count);
142 #if CL_DS_BIG_ENDIAN_P
146 extern void or_loop_up (uintD* xptr, const uintD* yptr, uintC count);
148 extern void xor_loop_up (uintD* xptr, const uintD* yptr, uintC count);
150 extern void and_loop_up (uintD* xptr, const uintD* yptr, uintC count);
152 extern void eqv_loop_up (uintD* xptr, const uintD* yptr, uintC count);
154 extern void nand_loop_up (uintD* xptr, const uintD* yptr, uintC count);
156 extern void nor_loop_up (uintD* xptr, const uintD* yptr, uintC count);
158 extern void andc2_loop_up (uintD* xptr, const uintD* yptr, uintC count);
160 extern void orc2_loop_up (uintD* xptr, const uintD* yptr, uintC count);
162 extern void not_loop_up (uintD* xptr, uintC count);
168 extern cl_boolean and_test_loop_up (const uintD* xptr, const uintD* yptr, uintC count);
170 extern cl_signean compare_loop_up (const uintD* xptr, const uintD* yptr, uintC count);
176 extern uintD add_loop_down (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count);
178 extern uintD addto_loop_down (const uintD* sourceptr, uintD* destptr, uintC count);
180 extern uintD inc_loop_down (uintD* ptr, uintC count);
182 extern uintD sub_loop_down (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count);
184 extern uintD subx_loop_down (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count, uintD carry);
186 extern uintD subfrom_loop_down (const uintD* sourceptr, uintD* destptr, uintC count);
188 extern uintD dec_loop_down (uintD* ptr, uintC count);
190 extern uintD neg_loop_down (uintD* ptr, uintC count);
196 extern uintD shift1left_loop_down (uintD* ptr, uintC count);
198 extern uintD shiftleft_loop_down (uintD* ptr, uintC count, uintC i, uintD carry);
200 extern uintD shiftleftcopy_loop_down (const uintD* sourceptr, uintD* destptr, uintC count, uintC i);
202 extern uintD shift1right_loop_up (uintD* ptr, uintC count, uintD carry);
204 extern uintD shiftright_loop_up (uintD* ptr, uintC count, uintC i);
206 extern uintD shiftrightsigned_loop_up (uintD* ptr, uintC count, uintC i);
208 extern uintD shiftrightcopy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry);
214 extern uintD mulusmall_loop_down (uintD digit, uintD* ptr, uintC len, uintD newdigit);
216 extern void mulu_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len);
218 extern uintD muluadd_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len);
220 extern uintD mulusub_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len);
226 extern uintD divu_loop_up (uintD digit, uintD* ptr, uintC len);
228 extern uintD divucopy_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len);
232 #else // !CL_DS_BIG_ENDIAN_P
236 extern void or_loop_down (uintD* xptr, const uintD* yptr, uintC count);
238 extern void xor_loop_down (uintD* xptr, const uintD* yptr, uintC count);
240 extern void and_loop_down (uintD* xptr, const uintD* yptr, uintC count);
242 extern void eqv_loop_down (uintD* xptr, const uintD* yptr, uintC count);
244 extern void nand_loop_down (uintD* xptr, const uintD* yptr, uintC count);
246 extern void nor_loop_down (uintD* xptr, const uintD* yptr, uintC count);
248 extern void andc2_loop_down (uintD* xptr, const uintD* yptr, uintC count);
250 extern void orc2_loop_down (uintD* xptr, const uintD* yptr, uintC count);
252 extern void not_loop_down (uintD* xptr, uintC count);
258 extern cl_boolean and_test_loop_down (const uintD* xptr, const uintD* yptr, uintC count);
260 extern cl_signean compare_loop_down (const uintD* xptr, const uintD* yptr, uintC count);
266 extern uintD add_loop_up (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count);
268 extern uintD addto_loop_up (const uintD* sourceptr, uintD* destptr, uintC count);
270 extern uintD inc_loop_up (uintD* ptr, uintC count);
272 extern uintD sub_loop_up (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count);
274 extern uintD subx_loop_up (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count, uintD carry);
276 extern uintD subfrom_loop_up (const uintD* sourceptr, uintD* destptr, uintC count);
278 extern uintD dec_loop_up (uintD* ptr, uintC count);
280 extern uintD neg_loop_up (uintD* ptr, uintC count);
286 extern uintD shift1left_loop_up (uintD* ptr, uintC count);
288 extern uintD shiftleft_loop_up (uintD* ptr, uintC count, uintC i, uintD carry);
290 extern uintD shiftleftcopy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count, uintC i);
292 extern uintD shift1right_loop_down (uintD* ptr, uintC count, uintD carry);
294 extern uintD shiftright_loop_down (uintD* ptr, uintC count, uintC i);
296 extern uintD shiftrightsigned_loop_down (uintD* ptr, uintC count, uintC i);
298 extern uintD shiftrightcopy_loop_down (const uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry);
304 extern uintD mulusmall_loop_up (uintD digit, uintD* ptr, uintC len, uintD newdigit);
306 extern void mulu_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len);
308 extern uintD muluadd_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len);
310 extern uintD mulusub_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len);
316 extern uintD divu_loop_down (uintD digit, uintD* ptr, uintC len);
318 extern uintD divucopy_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len);
322 #endif // !CL_DS_BIG_ENDIAN_P
324 // Independently of CL_DS_BIG_ENDIAN_P:
328 extern cl_signean compare_loop_up (const uintD* xptr, const uintD* yptr, uintC count);
334 extern void xor_loop_up (uintD* xptr, const uintD* yptr, uintC count);
340 extern uintD shiftleftcopy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count, uintC i);
342 extern void shiftxor_loop_up (uintD* xptr, const uintD* yptr, uintC count, uintC i);
349 #if defined(CL_USE_GMP)
351 // Supersede the functions by wrappers around calls to gmp mpn,
352 // for those functions where gmp is believed to be faster.
360 #if 0 // not worth it, since gmp's mpn_cmp is not optimized
361 inline cl_signean compare_loop_down (const uintD* xptr, const uintD* yptr, uintC count)
363 return mpn_cmp(xptr-count,yptr-count,count);
367 inline uintD add_loop_up (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count)
371 return mpn_add_n(destptr,sourceptr1,sourceptr2,count);
374 inline uintD addto_loop_up (const uintD* sourceptr, uintD* destptr, uintC count)
378 return mpn_add_n(destptr,destptr,sourceptr,count);
381 inline uintD inc_loop_up (uintD* ptr, uintC count)
385 return mpn_add_1(ptr,ptr,count,1);
388 inline uintD sub_loop_up (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count)
392 return mpn_sub_n(destptr,sourceptr1,sourceptr2,count);
395 inline uintD subx_loop_up (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count, uintD carry)
399 var uintD res_carry = mpn_sub_n(destptr,sourceptr1,sourceptr2,count);
401 res_carry |= mpn_sub_1(destptr,destptr,count,1);
405 inline uintD subfrom_loop_up (const uintD* sourceptr, uintD* destptr, uintC count)
409 return mpn_sub_n(destptr,destptr,sourceptr,count);
412 inline uintD dec_loop_up (uintD* ptr, uintC count)
416 return -mpn_sub_1(ptr,ptr,count,1);
419 #if !defined(ADDSUB_LOOPS)
420 // No equivalent for this in gmp. But we need this function, so write it in C.
421 inline uintD neg_loop_up (uintD* ptr, uintC count)
423 // erstes Digit /=0 suchen:
424 until (count==0) { if (!(*ptr == 0)) goto L1; ptr++; count--; }
426 L1: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
427 *ptr = - *ptr; count--; // 1 Digit negieren
428 dotimesC(count,count, { ptr++; *ptr = ~ *ptr; } ); // alle anderen Digits invertieren
435 inline uintD shift1left_loop_up (uintD* ptr, uintC count)
439 return mpn_lshift(ptr,ptr,count,1);
442 inline uintD shiftleft_loop_up (uintD* ptr, uintC count, uintC i, uintD carry)
446 var uintD res_carry = mpn_lshift(ptr,ptr,count,i);
451 inline uintD shiftleftcopy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count, uintC i)
455 return mpn_lshift(destptr,sourceptr,count,i);
458 inline uintD shift1right_loop_down (uintD* ptr, uintC count, uintD carry)
462 var uintD res_carry = mpn_rshift(ptr-count,ptr-count,count,1);
464 ptr[-1] |= bit(intDsize-1);
468 inline uintD shiftright_loop_down (uintD* ptr, uintC count, uintC i)
472 return mpn_rshift(ptr-count,ptr-count,count,i);
475 inline uintD shiftrightsigned_loop_down (uintD* ptr, uintC count, uintC i)
477 var uintD carry = ((sintD)ptr[-1] >> (intDsize-1)) << (intDsize-i);
478 var uintD res_carry = mpn_rshift(ptr-count,ptr-count,count,i);
483 inline uintD shiftrightcopy_loop_down (const uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry)
485 carry = carry << (intDsize-i);
488 var uintD res_carry = mpn_rshift(destptr-count,sourceptr-count,count,i);
489 destptr[-1] |= carry;
495 inline uintD mulusmall_loop_up (uintD digit, uintD* ptr, uintC len, uintD newdigit)
499 var uintD res_carry = mpn_mul_1(ptr,ptr,len,digit);
500 res_carry += mpn_add_1(ptr,ptr,len,newdigit);
504 inline void mulu_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
506 destptr[len] = (len==0 ? 0 : mpn_mul_1(destptr,sourceptr,len,digit));
509 inline uintD muluadd_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
513 return mpn_addmul_1(destptr,sourceptr,len,digit);
516 inline uintD mulusub_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
520 return mpn_submul_1(destptr,sourceptr,len,digit);
525 inline uintD divu_loop_up (uintD digit, uintD* ptr, uintC len)
527 return mpn_divrem_1(ptr,0,ptr,len,digit);
530 inline uintD divu_loop_down (uintD digit, uintD* ptr, uintC len)
532 return mpn_divrem_1(ptr-len,0,ptr-len,len,digit);
535 inline uintD divucopy_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
537 return mpn_divrem_1(destptr,0,sourceptr,len,digit);
540 inline uintD divucopy_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
542 return mpn_divrem_1(destptr-len,0,sourceptr-len,len,digit);
547 #endif // defined(CL_USE_GMP)
550 // Define the missing functions as inline functions.
555 // destptr = copy_loop_up(sourceptr,destptr,count);
556 // kopiert count (uintC>=0) Digits aufwärts von sourceptr nach destptr
557 // und liefert das neue destptr.
558 inline uintD* copy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count)
559 { dotimesC(count,count, { *destptr++ = *sourceptr++; } );
564 // destptr = copy_loop_down(sourceptr,destptr,count);
565 // kopiert count (uintC>=0) Digits abwärts von sourceptr nach destptr
566 // und liefert das neue destptr.
567 inline uintD* copy_loop_down (const uintD* sourceptr, uintD* destptr, uintC count)
568 { dotimesC(count,count, { *--destptr = *--sourceptr; } );
577 // destptr = fill_loop_up(destptr,count,filler);
578 // kopiert count (uintC>=0) mal das Digit filler aufwärts nach destptr
579 // und liefert das neue destptr.
580 inline uintD* fill_loop_up (uintD* destptr, uintC count, uintD filler)
581 { dotimesC(count,count, { *destptr++ = filler; } );
586 // destptr = fill_loop_down(destptr,count,filler);
587 // kopiert count (uintC>=0) mal das Digit filler abwärts nach destptr
588 // und liefert das neue destptr.
589 inline uintD* fill_loop_down (uintD* destptr, uintC count, uintD filler)
590 { dotimesC(count,count, { *--destptr = filler; } );
599 // destptr = clear_loop_up(destptr,count);
600 // löscht count (uintC>=0) Digits aufwärts ab destptr
601 // und liefert das neue destptr.
602 inline uintD* clear_loop_up (uintD* destptr, uintC count)
603 { dotimesC(count,count, { *destptr++ = 0; } );
608 // destptr = clear_loop_down(destptr,count);
609 // löscht count (uintC>=0) Digits abwärts ab destptr
610 // und liefert das neue destptr.
611 inline uintD* clear_loop_down (uintD* destptr, uintC count)
612 { dotimesC(count,count, { *--destptr = 0; } );
621 // test_loop_up(ptr,count)
622 // testet count (uintC>=0) Digits aufwärts ab ptr, ob darunter eines /=0 ist.
623 // Ergebnis /=0, falls ja.
624 inline cl_boolean test_loop_up (const uintD* ptr, uintC count)
625 { dotimesC(count,count, { if (*ptr++) return cl_true; } );
630 // test_loop_down(ptr,count)
631 // testet count (uintC>=0) Digits abwärts ab ptr, ob darunter eines /=0 ist.
632 // Ergebnis /=0, falls ja.
633 inline cl_boolean test_loop_down (const uintD* ptr, uintC count)
634 { dotimesC(count,count, { if (*--ptr) return cl_true; } );
640 #if CL_DS_BIG_ENDIAN_P
645 // or_loop_up(xptr,yptr,count);
646 // verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr
647 // mit Ziel ab xptr durch OR.
648 inline void or_loop_up (uintD* xptr, const uintD* yptr, uintC count)
649 { dotimesC(count,count, { *xptr++ |= *yptr++; } ); }
652 // xor_loop_up(xptr,yptr,count);
653 // verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr
654 // mit Ziel ab xptr durch XOR.
655 inline void xor_loop_up (uintD* xptr, const uintD* yptr, uintC count)
656 { dotimesC(count,count, { *xptr++ ^= *yptr++; } ); }
659 // and_loop_up(xptr,yptr,count);
660 // verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr
661 // mit Ziel ab xptr durch AND.
662 inline void and_loop_up (uintD* xptr, const uintD* yptr, uintC count)
663 { dotimesC(count,count, { *xptr++ &= *yptr++; } ); }
666 // eqv_loop_up(xptr,yptr,count);
667 // verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr
668 // mit Ziel ab xptr durch EQV (NOT XOR).
669 inline void eqv_loop_up (uintD* xptr, const uintD* yptr, uintC count)
670 { dotimesC(count,count,
671 {var uintD temp = ~ (*xptr ^ *yptr++); *xptr++ = temp; }
676 // nand_loop_up(xptr,yptr,count);
677 // verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr
678 // mit Ziel ab xptr durch NAND (NOT AND).
679 inline void nand_loop_up (uintD* xptr, const uintD* yptr, uintC count)
680 { dotimesC(count,count,
681 {var uintD temp = ~ (*xptr & *yptr++); *xptr++ = temp; }
686 // nor_loop_up(xptr,yptr,count);
687 // verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr
688 // mit Ziel ab xptr durch NOR (NOT OR).
689 inline void nor_loop_up (uintD* xptr, const uintD* yptr, uintC count)
690 { dotimesC(count,count,
691 {var uintD temp = ~ (*xptr | *yptr++); *xptr++ = temp; }
696 // andc2_loop_up(xptr,yptr,count);
697 // verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr
698 // mit Ziel ab xptr durch ANDC2 (AND NOT).
699 inline void andc2_loop_up (uintD* xptr, const uintD* yptr, uintC count)
700 { dotimesC(count,count, { *xptr++ &= ~(*yptr++); } ); }
703 // orc2_loop_up(xptr,yptr,count);
704 // verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr
705 // mit Ziel ab xptr durch ORC2 (OR NOT).
706 inline void orc2_loop_up (uintD* xptr, const uintD* yptr, uintC count)
707 { dotimesC(count,count, { *xptr++ |= ~(*yptr++); } ); }
710 // not_loop_up(xptr,count);
711 // verknüpft count (uintC>0) Digits aufwärts ab xptr mit Ziel ab xptr
713 inline void not_loop_up (uintD* xptr, uintC count)
714 { dotimespC(count,count,
715 {var uintD temp = ~ (*xptr); *xptr++ = temp; }
723 // AND-Test-Schleife:
724 // and_test_loop_up(xptr,yptr,count);
725 // verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr durch AND
726 // und testet, ob sich dabei ein Digit /=0 ergibt. Ergebnis cl_true, falls ja.
727 inline cl_boolean and_test_loop_up (const uintD* xptr, const uintD* yptr, uintC count)
728 { dotimesC(count,count, { if (*xptr++ & *yptr++) return cl_true; } );
732 // Vergleichsschleife:
733 // result = compare_loop_up(xptr,yptr,count);
734 // vergleicht nacheinander xptr[0] mit yptr[0], xptr[1] mit yptr[1], usw.,
735 // insgesamt count Digits, und liefert 0 falls alle gleich sind,
736 // +1 falls zuerst ein xptr[i]>yptr[i] ist,
737 // -1 falls zuerst ein xptr[i]<yptr[i] ist.
738 inline cl_signean compare_loop_up (const uintD* xptr, const uintD* yptr, uintC count)
739 { dotimesC(count,count,
740 { if (!(*xptr++ == *yptr++))
741 // verschiedene Digits gefunden
742 return (*--xptr > *--yptr ? signean_plus : signean_minus);
744 return signean_null; // alle Digits gleich
751 // Additionsschleife:
752 // übertrag = add_loop_down(sourceptr1,sourceptr2,destptr,count);
753 // addiert count (uintC>=0) Digits abwärts von sourceptr1, von sourceptr2
754 // abwärts nach destptr und liefert den Übertrag (0 oder /=0, was 1 bedeutet).
755 inline uintD add_loop_down (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count)
759 do { source1 = *--sourceptr1;
760 source2 = *--sourceptr2;
761 *--destptr = source1 + source2;
762 if (source1 > (uintD)(~source2)) goto carry_1;
768 do { source1 = *--sourceptr1;
769 source2 = *--sourceptr2;
770 *--destptr = source1 + source2 + 1;
771 if (source1 < (uintD)(~source2)) goto carry_0;
779 // Additionsschleife:
780 // übertrag = addto_loop_down(sourceptr,destptr,count);
781 // addiert count (uintC>=0) Digits abwärts von sourceptr, von destptr
782 // abwärts nach destptr und liefert den Übertrag (0 oder /=0, was 1 bedeutet).
783 inline uintD addto_loop_down (const uintD* sourceptr, uintD* destptr, uintC count)
787 do { source1 = *--sourceptr;
788 source2 = *--destptr;
789 *destptr = source1 + source2;
790 if (source1 > (uintD)(~source2)) goto carry_1;
796 do { source1 = *--sourceptr;
797 source2 = *--destptr;
798 *destptr = source1 + source2 + 1;
799 if (source1 < (uintD)(~source2)) goto carry_0;
807 // Incrementierschleife:
808 // übertrag = inc_loop_down(ptr,count);
809 // incrementiert count (uintC>=0) Digits abwärts von ptr, so lange bis kein
810 // Übertrag mehr auftritt und liefert den Übertrag (0 oder /=0, was 1 bedeutet).
811 inline uintD inc_loop_down (uintD* ptr, uintC count)
812 { dotimesC(count,count,
813 { if (!( ++(*--ptr) == 0 )) return 0; } // kein weiterer Übertrag
815 return 1; // weiterer Übertrag
818 // Subtraktionsschleife:
819 // übertrag = sub_loop_down(sourceptr1,sourceptr2,destptr,count);
820 // subtrahiert count (uintC>=0) Digits abwärts von sourceptr1, von sourceptr2
821 // abwärts nach destptr und liefert den Übertrag (0 oder /=0, was -1 bedeutet).
822 inline uintD sub_loop_down (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count)
826 do { source1 = *--sourceptr1;
827 source2 = *--sourceptr2;
828 *--destptr = source1 - source2;
829 if (source1 < source2) goto carry_1;
835 do { source1 = *--sourceptr1;
836 source2 = *--sourceptr2;
837 *--destptr = source1 - source2 - 1;
838 if (source1 > source2) goto carry_0;
846 // Subtraktionsschleife:
847 // übertrag = subx_loop_down(sourceptr1,sourceptr2,destptr,count,carry);
848 // subtrahiert count (uintC>=0) Digits abwärts von sourceptr1 und addiert
849 // einen Carry (0 oder -1), von sourceptr2 abwärts nach destptr und
850 // liefert den Übertrag (0 oder /=0, was -1 bedeutet).
851 inline uintD subx_loop_down (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count, uintD carry)
856 do { source1 = *--sourceptr1;
857 source2 = *--sourceptr2;
858 *--destptr = source1 - source2;
859 if (source1 < source2) goto carry_1;
868 do { source1 = *--sourceptr1;
869 source2 = *--sourceptr2;
870 *--destptr = source1 - source2 - 1;
871 if (source1 > source2) goto carry_0;
879 // Subtraktionsschleife:
880 // übertrag = subfrom_loop_down(sourceptr,destptr,count);
881 // subtrahiert count (uintC>=0) Digits abwärts von sourceptr, von destptr
882 // abwärts nach destptr (dest := dest - source)
883 // und liefert den Übertrag (0 oder /=0, was -1 bedeutet).
884 inline uintD subfrom_loop_down (const uintD* sourceptr, uintD* destptr, uintC count)
888 do { source1 = *--destptr;
889 source2 = *--sourceptr;
890 *destptr = source1 - source2;
891 if (source1 < source2) goto carry_1;
897 do { source1 = *--destptr;
898 source2 = *--sourceptr;
899 *destptr = source1 - source2 - 1;
900 if (source1 > source2) goto carry_0;
908 // Decrementierschleife:
909 // übertrag = dec_loop_down(ptr,count);
910 // decrementiert count (uintC>=0) Digits abwärts von ptr, so lange bis kein
911 // Übertrag mehr auftritt und liefert den Übertrag (0 oder -1).
912 inline uintD dec_loop_down (uintD* ptr, uintC count)
913 { dotimesC(count,count,
914 { if (!( (*--ptr)-- == 0 )) return 0; } // kein weiterer Übertrag
916 return (uintD)(-1); // weiterer Übertrag
920 // übertrag = neg_loop_down(ptr,count);
921 // negiert count (uintC>=0) Digits abwärts von ptr,
922 // und liefert den Übertrag (0 oder -1).
923 inline uintD neg_loop_down (uintD* ptr, uintC count)
924 { // erstes Digit /=0 suchen:
925 until (count==0) { if (!(*--ptr == 0)) goto L1; count--; }
927 L1: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
928 *ptr = - *ptr; count--; // 1 Digit negieren
929 dotimesC(count,count, { --ptr; *ptr = ~ *ptr; } ); // alle anderen Digits invertieren
937 // Schiebeschleife um 1 Bit nach links:
938 // übertrag = shift1left_loop_down(ptr,count);
939 // schiebt count (uintC>=0) Digits abwärts von ptr um 1 Bit nach links,
940 // und liefert den Übertrag (0 oder /=0, was 1 bedeutet).
942 inline uintD shift1left_loop_down (uintD* ptr, uintC count)
943 { var uintDD accu = 0;
944 dotimesC(count,count,
945 { accu = ((uintDD)(*--ptr)<<1)+accu; *ptr = lowD(accu);
946 accu = (uintDD)(highD(accu));
951 inline uintD shift1left_loop_down (uintD* ptr, uintC count)
952 { var uintD carry = 0;
953 dotimesC(count,count,
954 { var uintD accu = *--ptr;
955 *ptr = (accu<<1) | carry;
956 carry = accu>>(intDsize-1);
962 // Schiebeschleife um i Bits nach links:
963 // übertrag = shiftleft_loop_down(ptr,count,i,übertrag_init);
964 // schiebt count (uintC>=0) Digits abwärts von ptr um i Bits (0<i<intDsize)
965 // nach links, schiebt dabei die i Bits aus übertrag_init rechts rein,
966 // und liefert den Übertrag (was links rauskommt, >=0, <2^i).
968 inline uintD shiftleft_loop_down (uintD* ptr, uintC count, uintC i, uintD carry)
969 { var uintDD accu = (uintDD)carry;
970 dotimesC(count,count,
971 { accu = ((uintDD)(*--ptr)<<i)+accu; *ptr = lowD(accu);
972 accu = (uintDD)(highD(accu));
977 inline uintD shiftleft_loop_down (uintD* ptr, uintC count, uintC i, uintD carry)
978 { var uintC j = intDsize-i;
979 dotimesC(count,count,
980 { var uintD accu = *--ptr;
981 *ptr = (accu<<i) | carry;
988 // Schiebe- und Kopierschleife um i Bits nach links:
989 // übertrag = shiftleftcopy_loop_down(sourceptr,destptr,count,i);
990 // kopiert count (uintC>=0) Digits abwärts von sourceptr nach destptr
991 // und schiebt sie dabei um i Bits (0<i<intDsize) nach links,
992 // wobei ganz rechts mit i Nullbits aufgefüllt wird,
993 // und liefert den Übertrag (was links rauskommt, >=0, <2^i).
995 inline uintD shiftleftcopy_loop_down (const uintD* sourceptr, uintD* destptr, uintC count, uintC i)
996 { var uintDD accu = 0;
997 dotimesC(count,count,
998 { accu = ((uintDD)(*--sourceptr)<<i)+accu; *--destptr = lowD(accu);
999 accu = (uintDD)(highD(accu));
1004 inline uintD shiftleftcopy_loop_down (const uintD* sourceptr, uintD* destptr, uintC count, uintC i)
1005 { var uintC j = intDsize-i;
1006 var uintD carry = 0;
1007 dotimesC(count,count,
1008 { var uintD accu = *--sourceptr;
1009 *--destptr = (accu<<i) | carry;
1016 // Schiebeschleife um 1 Bit nach rechts:
1017 // übertrag = shift1right_loop_up(ptr,count,übertrag_init);
1018 // schiebt count (uintC>=0) Digits aufwärts von ptr um 1 Bit nach rechts,
1019 // wobei links das Bit übertrag_init (sollte =0 oder =-1 sein) hineingeschoben
1020 // wird, und liefert den Übertrag (0 oder /=0, was 1 bedeutet).
1022 inline uintD shift1right_loop_up (uintD* ptr, uintC count, uintD carry)
1023 { var uintDD accu = (sintDD)(sintD)carry & ((uintDD)1 << (2*intDsize-1)); // 0 oder bit(2*intDsize-1)
1024 dotimesC(count,count,
1025 { accu = (highlowDD_0(*ptr)>>1)+accu; *ptr++ = highD(accu);
1026 accu = highlowDD_0(lowD(accu));
1031 inline uintD shift1right_loop_up (uintD* ptr, uintC count, uintD carry)
1032 { carry = carry << (intDsize-1); // carry zu einem einzigen Bit machen
1033 dotimesC(count,count,
1034 { var uintD accu = *ptr;
1035 *ptr++ = (accu >> 1) | carry;
1036 carry = accu << (intDsize-1);
1042 // Schiebeschleife um i Bits nach rechts:
1043 // übertrag = shiftright_loop_up(ptr,count,i);
1044 // schiebt count (uintC>=0) Digits aufwärts von ptr um i Bits (0<i<intDsize)
1045 // nach rechts, wobei links Nullen eingeschoben werden,
1046 // und liefert den Übertrag (was rechts rauskommt, als Bits intDsize-1..intDsize-i).
1048 inline uintD shiftright_loop_up (uintD* ptr, uintC count, uintC i)
1049 { var uintDD accu = 0;
1050 dotimesC(count,count,
1051 { // Die oberen i Bits von (uintD)accu bilden hier den Übertrag.
1052 accu = highlowDD_0(lowD(accu));
1053 // Die oberen i Bits von (uintDD)accu bilden hier den Übertrag.
1054 accu = (highlowDD_0(*ptr)>>i)+accu; *ptr++ = highD(accu);
1059 inline uintD shiftright_loop_up (uintD* ptr, uintC count, uintC i)
1060 { var uintC j = intDsize-i;
1061 var uintD carry = 0;
1062 dotimesC(count,count,
1063 { var uintD accu = *ptr;
1064 *ptr++ = (accu >> i) | carry;
1071 // Schiebeschleife um i Bits nach rechts:
1072 // übertrag = shiftrightsigned_loop_up(ptr,count,i);
1073 // schiebt count (uintC>0) Digits aufwärts von ptr um i Bits (0<i<intDsize)
1074 // nach rechts, wobei links das MSBit ver-i-facht wird,
1075 // und liefert den Übertrag (was rechts rauskommt, als Bits intDsize-1..intDsize-i).
1077 inline uintD shiftrightsigned_loop_up (uintD* ptr, uintC count, uintC i)
1078 { var uintDD accu = // Übertrag mit i Vorzeichenbits initialisieren
1079 highlowDD_0(sign_of_sintD((sintD)(*ptr)))>>i;
1080 dotimespC(count,count,
1081 { // Die oberen i Bits von (uintD)accu bilden hier den Übertrag.
1082 accu = highlowDD_0(lowD(accu));
1083 // Die oberen i Bits von (uintDD)accu bilden hier den Übertrag.
1084 accu = (highlowDD_0(*ptr)>>i)+accu; *ptr++ = highD(accu);
1089 inline uintD shiftrightsigned_loop_up (uintD* ptr, uintC count, uintC i)
1090 { var uintC j = intDsize-i;
1092 { var uintD accu = *ptr;
1093 *ptr++ = (sintD)accu >> i;
1097 dotimesC(count,count,
1098 { var uintD accu = *ptr;
1099 *ptr++ = (accu >> i) | carry;
1106 // Schiebe- und Kopier-Schleife um i Bits nach rechts:
1107 // übertrag = shiftrightcopy_loop_up(sourceptr,destptr,count,i,carry);
1108 // kopiert count (uintC>=0) Digits aufwärts von sourceptr nach destptr
1109 // und schiebt sie dabei um i Bits (0<i<intDsize) nach rechts, wobei carry
1110 // (sozusagen als sourceptr[-1]) die i Bits ganz links bestimmt,
1111 // und liefert den Übertrag (was rechts rauskommt, als Bits intDsize-1..intDsize-i).
1113 inline uintD shiftrightcopy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry)
1114 { var uintDD accu = // Übertrag mit carry initialisieren
1115 highlowDD_0(carry)>>i;
1116 dotimesC(count,count,
1117 { // Die oberen i Bits von (uintD)accu bilden hier den Übertrag.
1118 accu = highlowDD_0(lowD(accu));
1119 // Die oberen i Bits von (uintDD)accu bilden hier den Übertrag.
1120 accu = (highlowDD_0(*sourceptr++)>>i)+accu; *destptr++ = highD(accu);
1125 inline uintD shiftrightcopy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry)
1126 { var uintC j = intDsize-i;
1128 dotimesC(count,count,
1129 { var uintD accu = *sourceptr++;
1130 *destptr++ = (accu >> i) | carry;
1141 // Multiplikations-Einfachschleife:
1142 // Multipliziert eine UDS mit einem kleinen Digit und addiert ein kleines Digit.
1143 // mulusmall_loop_down(digit,ptr,len,newdigit)
1144 // multipliziert die UDS ptr[-len..-1] mit digit (>=2, <=36),
1145 // addiert dabei newdigit (>=0, <digit) zur letzten Ziffer,
1146 // und liefert den Carry (>=0, <digit).
1148 inline uintD mulusmall_loop_down (uintD digit, uintD* ptr, uintC len, uintD newdigit)
1149 { var uintDD carry = newdigit;
1151 { // Hier ist 0 <= carry < digit.
1152 carry = carry + muluD(digit,*--ptr);
1153 // Hier ist 0 <= carry < 2^intDsize*digit.
1155 carry = (uintDD)highD(carry); // carry := floor(carry/2^intDsize) < digit
1160 inline uintD mulusmall_loop_down (uintD digit, uintD* ptr, uintC len, uintD newdigit)
1161 { var uintD carry = newdigit;
1163 { // Hier ist 0 <= carry < digit.
1166 muluD(digit,*--ptr,hi=,lo=);
1167 // Hier ist 0 <= 2^intDsize*hi + lo + carry < 2^intDsize*digit.
1168 lo += carry; if (lo < carry) { hi += 1; }
1176 // Multiplikations-Einfachschleife:
1177 // Multipliziert eine UDS mit einem Digit und legt das Ergebnis in einer
1179 // mulu_loop_down(digit,sourceptr,destptr,len);
1180 // multipliziert die UDS sourceptr[-len..-1] (len>0)
1181 // mit dem einzelnen digit
1182 // und legt das Ergebnis in der UDS destptr[-len-1..-1] ab.
1184 inline void mulu_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
1185 { var uintDD carry = 0;
1187 { // Hier ist carry=digit=0 oder 0 <= carry < digit.
1188 carry = carry + muluD(digit,*--sourceptr);
1189 // Hier ist carry=digit=0 oder 0 <= carry < 2^intDsize*digit.
1190 *--destptr = lowD(carry);
1191 carry = (uintDD)highD(carry); // carry := floor(carry/2^intDsize) < digit
1193 *--destptr = lowD(carry);
1196 inline void mulu_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
1197 { var uintD carry = 0;
1199 { // Hier ist carry=digit=0 oder 0 <= carry < digit.
1202 muluD(digit,*--sourceptr,hi=,lo=);
1203 // Hier ist 0 <= 2^intDsize*hi + lo + carry < 2^intDsize*digit oder hi=lo=carry=digit=0.
1204 lo += carry; if (lo < carry) { hi += 1; }
1212 // Multiplikations-Einfachschleife mit Akkumulation:
1213 // Multipliziert eine UDS mit einem Digit und addiert das Ergebnis zu einer
1215 // muluadd_loop_down(digit,sourceptr,destptr,len);
1216 // multipliziert die UDS sourceptr[-len..-1] (len>0)
1217 // mit dem einzelnen digit, legt das Ergebnis in der UDS destptr[-len..-1]
1218 // ab und liefert den weiteren Übertrag.
1220 inline uintD muluadd_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
1221 { var uintDD carry = 0;
1223 { dotimespC(len,len,
1224 { // Hier ist 0 <= carry <= digit.
1225 carry = carry + muluD(digit,*--sourceptr) + (uintDD)*--destptr;
1226 // Hier ist 0 <= carry <= 2^intDsize*digit + 2^intDsize-1.
1227 *destptr = lowD(carry);
1228 carry = (uintDD)highD(carry); // carry := floor(carry/2^intDsize) <= digit
1234 inline uintD muluadd_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
1235 { var uintD carry = 0;
1237 { dotimespC(len,len,
1238 { // Hier ist 0 <= carry <= digit.
1241 muluD(digit,*--sourceptr,hi=,lo=);
1242 // Hier ist 0 <= 2^intDsize*hi + lo + carry + *--destptr <= 2^intDsize*digit+2^intDsize-1.
1243 lo += carry; if (lo < carry) { hi += 1; }
1245 lo += carry; if (lo < carry) { hi += 1; }
1254 // Multiplikations-Einfachschleife mit Diminution:
1255 // Multipliziert eine UDS mit einem Digit und subtrahiert das Ergebnis von
1256 // einer zweiten UDS.
1257 // mulusub_loop_down(digit,sourceptr,destptr,len);
1258 // multipliziert die UDS sourceptr[-len..-1] (len>0) mit dem einzelnen
1259 // digit, subtrahiert das Ergebnis von der UDS destptr[-len..-1] und liefert
1260 // den weiteren Übertrag (>=0, evtl. von destptr[-len-1] zu subtrahieren).
1262 inline uintD mulusub_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
1263 { var uintDD carry = 0;
1265 { dotimespC(len,len,
1266 { // Hier ist 0 <= carry <= digit.
1267 carry = carry + muluD(digit,*--sourceptr) + (uintD)(~(*--destptr));
1268 // Hier ist 0 <= carry <= 2^intDsize*digit + 2^intDsize-1.
1269 *destptr = ~lowD(carry);
1270 carry = (uintDD)highD(carry); // carry := floor(carry/2^intDsize) <= digit
1271 // Hier ist 0 <= carry <= digit.
1276 return 0; // nichts zu subtrahieren -> kein Übertrag
1279 inline uintD mulusub_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
1280 { var uintD carry = 0;
1282 { dotimespC(len,len,
1283 { // Hier ist 0 <= carry <= digit.
1286 muluD(digit,*--sourceptr,hi=,lo=);
1287 // Hier ist 0 <= 2^intDsize*hi + lo + carry + ~(*--destptr) <= 2^intDsize*digit+2^intDsize-1.
1288 lo += carry; if (lo < carry) { hi += 1; }
1290 *destptr = carry - lo; if (carry < lo) { hi += 1; }
1296 return 0; // nichts zu subtrahieren -> kein Übertrag
1304 // Divisions-Einfachschleife:
1305 // Dividiert eine UDS durch ein Digit.
1306 // divu_loop_up(digit,ptr,len)
1307 // dividiert die UDS ptr[0..len-1] durch digit,
1308 // legt das Ergebnis in derselben UDS ab, und liefert den Rest (>=0, <digit).
1310 inline uintD divu_loop_up (uintD digit, uintD* ptr, uintC len)
1311 { var uintD rest = 0;
1313 { divuD(highlowDD(rest,*ptr),digit,*ptr =, rest =); ptr++; }
1318 inline uintD divu_loop_up (uintD digit, uintD* ptr, uintC len)
1319 { var uintD rest = 0;
1321 { divuD(rest,*ptr,digit,*ptr =, rest =); ptr++; }
1327 // Divisions-Einfachschleife:
1328 // Dividiert eine UDS durch ein Digit und legt das Ergebnis in einer
1330 // divucopy_loop_up(digit,sourceptr,destptr,len)
1331 // dividiert die UDS sourceptr[0..len-1] durch digit,
1332 // legt das Ergebnis in der UDS destptr[0..len-1] ab,
1333 // und liefert den Rest (>=0, <digit).
1335 inline uintD divucopy_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
1336 { var uintD rest = 0;
1338 { divuD(highlowDD(rest,*sourceptr++),digit,*destptr++ =, rest =); }
1343 inline uintD divucopy_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
1344 { var uintD rest = 0;
1346 { divuD(rest,*sourceptr++,digit,*destptr++ =, rest =); }
1354 #else // !CL_DS_BIG_ENDIAN_P
1359 // or_loop_down(xptr,yptr,count);
1360 // verknüpft count (uintC>=0) Digits abwärts ab xptr und ab yptr
1361 // mit Ziel ab xptr durch OR.
1362 inline void or_loop_down (uintD* xptr, const uintD* yptr, uintC count)
1363 { dotimesC(count,count, { *--xptr |= *--yptr; } ); }
1366 // xor_loop_down(xptr,yptr,count);
1367 // verknüpft count (uintC>=0) Digits abwärts ab xptr und ab yptr
1368 // mit Ziel ab xptr durch XOR.
1369 inline void xor_loop_down (uintD* xptr, const uintD* yptr, uintC count)
1370 { dotimesC(count,count, { *--xptr ^= *--yptr; } ); }
1373 // and_loop_down(xptr,yptr,count);
1374 // verknüpft count (uintC>=0) Digits abwärts ab xptr und ab yptr
1375 // mit Ziel ab xptr durch AND.
1376 inline void and_loop_down (uintD* xptr, const uintD* yptr, uintC count)
1377 { dotimesC(count,count, { *--xptr &= *--yptr; } ); }
1380 // eqv_loop_down(xptr,yptr,count);
1381 // verknüpft count (uintC>=0) Digits abwärts ab xptr und ab yptr
1382 // mit Ziel ab xptr durch EQV (NOT XOR).
1383 inline void eqv_loop_down (uintD* xptr, const uintD* yptr, uintC count)
1384 { dotimesC(count,count,
1385 {var uintD temp = ~ (*--xptr ^ *--yptr); *xptr = temp; }
1390 // nand_loop_down(xptr,yptr,count);
1391 // verknüpft count (uintC>=0) Digits abwärts ab xptr und ab yptr
1392 // mit Ziel ab xptr durch NAND (NOT AND).
1393 inline void nand_loop_down (uintD* xptr, const uintD* yptr, uintC count)
1394 { dotimesC(count,count,
1395 {var uintD temp = ~ (*--xptr & *--yptr); *xptr = temp; }
1400 // nor_loop_down(xptr,yptr,count);
1401 // verknüpft count (uintC>=0) Digits abwärts ab xptr und ab yptr
1402 // mit Ziel ab xptr durch NOR (NOT OR).
1403 inline void nor_loop_down (uintD* xptr, const uintD* yptr, uintC count)
1404 { dotimesC(count,count,
1405 {var uintD temp = ~ (*--xptr | *--yptr); *xptr = temp; }
1410 // andc2_loop_down(xptr,yptr,count);
1411 // verknüpft count (uintC>=0) Digits abwärts ab xptr und ab yptr
1412 // mit Ziel ab xptr durch ANDC2 (AND NOT).
1413 inline void andc2_loop_down (uintD* xptr, const uintD* yptr, uintC count)
1414 { dotimesC(count,count, { *--xptr &= ~(*--yptr); } ); }
1417 // orc2_loop_down(xptr,yptr,count);
1418 // verknüpft count (uintC>=0) Digits abwärts ab xptr und ab yptr
1419 // mit Ziel ab xptr durch ORC2 (OR NOT).
1420 inline void orc2_loop_down (uintD* xptr, const uintD* yptr, uintC count)
1421 { dotimesC(count,count, { *--xptr |= ~(*--yptr); } ); }
1424 // not_loop_down(xptr,count);
1425 // verknüpft count (uintC>0) Digits abwärts ab xptr mit Ziel ab xptr
1427 inline void not_loop_down (uintD* xptr, uintC count)
1428 { dotimespC(count,count,
1429 {var uintD temp = ~ (*--xptr); *xptr = temp; }
1437 // AND-Test-Schleife:
1438 // and_test_loop_down(xptr,yptr,count);
1439 // verknüpft count (uintC>=0) Digits abwärts ab xptr und ab yptr durch AND
1440 // und testet, ob sich dabei ein Digit /=0 ergibt. Ergebnis cl_true, falls ja.
1441 inline cl_boolean and_test_loop_down (const uintD* xptr, const uintD* yptr, uintC count)
1442 { dotimesC(count,count, { if (*--xptr & *--yptr) return cl_true; } );
1446 // Vergleichsschleife:
1447 // result = compare_loop_down(xptr,yptr,count);
1448 // vergleicht nacheinander xptr[-1] mit yptr[-1], xptr[-2] mit yptr[-2], usw.,
1449 // insgesamt count Digits, und liefert 0 falls alle gleich sind,
1450 // +1 falls zuerst ein xptr[i]>yptr[i] ist,
1451 // -1 falls zuerst ein xptr[i]<yptr[i] ist.
1452 inline cl_signean compare_loop_down (const uintD* xptr, const uintD* yptr, uintC count)
1453 { dotimesC(count,count,
1454 { if (!(*--xptr == *--yptr))
1455 // verschiedene Digits gefunden
1456 return (*xptr > *yptr ? signean_plus : signean_minus);
1458 return signean_null; // alle Digits gleich
1463 #ifndef ADDSUB_LOOPS
1465 // Additionsschleife:
1466 // übertrag = add_loop_up(sourceptr1,sourceptr2,destptr,count);
1467 // addiert count (uintC>=0) Digits aufwärts von sourceptr1, von sourceptr2
1468 // aufwärts nach destptr und liefert den Übertrag (0 oder /=0, was 1 bedeutet).
1469 inline uintD add_loop_up (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count)
1470 { var uintD source1;
1473 do { source1 = *sourceptr1++;
1474 source2 = *sourceptr2++;
1475 *destptr++ = source1 + source2;
1476 if (source1 > (uintD)(~source2)) goto carry_1;
1482 do { source1 = *sourceptr1++;
1483 source2 = *sourceptr2++;
1484 *destptr++ = source1 + source2 + 1;
1485 if (source1 < (uintD)(~source2)) goto carry_0;
1493 // Additionsschleife:
1494 // übertrag = addto_loop_up(sourceptr,destptr,count);
1495 // addiert count (uintC>=0) Digits aufwärts von sourceptr, von destptr
1496 // aufwärts nach destptr und liefert den Übertrag (0 oder /=0, was 1 bedeutet).
1497 inline uintD addto_loop_up (const uintD* sourceptr, uintD* destptr, uintC count)
1498 { var uintD source1;
1501 do { source1 = *sourceptr++;
1503 *destptr++ = source1 + source2;
1504 if (source1 > (uintD)(~source2)) goto carry_1;
1510 do { source1 = *sourceptr++;
1512 *destptr++ = source1 + source2 + 1;
1513 if (source1 < (uintD)(~source2)) goto carry_0;
1521 // Incrementierschleife:
1522 // übertrag = inc_loop_up(ptr,count);
1523 // incrementiert count (uintC>=0) Digits aufwärts von ptr, so lange bis kein
1524 // Übertrag mehr auftritt und liefert den Übertrag (0 oder /=0, was 1 bedeutet).
1525 inline uintD inc_loop_up (uintD* ptr, uintC count)
1526 { dotimesC(count,count,
1527 { if (!( ++(*ptr++) == 0 )) return 0; } // kein weiterer Übertrag
1529 return 1; // weiterer Übertrag
1532 // Subtraktionsschleife:
1533 // übertrag = sub_loop_up(sourceptr1,sourceptr2,destptr,count);
1534 // subtrahiert count (uintC>=0) Digits aufwärts von sourceptr1, von sourceptr2
1535 // aufwärts nach destptr und liefert den Übertrag (0 oder /=0, was -1 bedeutet).
1536 inline uintD sub_loop_up (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count)
1537 { var uintD source1;
1540 do { source1 = *sourceptr1++;
1541 source2 = *sourceptr2++;
1542 *destptr++ = source1 - source2;
1543 if (source1 < source2) goto carry_1;
1549 do { source1 = *sourceptr1++;
1550 source2 = *sourceptr2++;
1551 *destptr++ = source1 - source2 - 1;
1552 if (source1 > source2) goto carry_0;
1560 // Subtraktionsschleife:
1561 // übertrag = subx_loop_up(sourceptr1,sourceptr2,destptr,count,carry);
1562 // subtrahiert count (uintC>=0) Digits aufwärts von sourceptr1 und addiert
1563 // einen Carry (0 oder -1), von sourceptr2 aufwärts nach destptr und
1564 // liefert den Übertrag (0 oder /=0, was -1 bedeutet).
1565 inline uintD subx_loop_up (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count, uintD carry)
1566 { var uintD source1;
1570 do { source1 = *sourceptr1++;
1571 source2 = *sourceptr2++;
1572 *destptr++ = source1 - source2;
1573 if (source1 < source2) goto carry_1;
1582 do { source1 = *sourceptr1++;
1583 source2 = *sourceptr2++;
1584 *destptr++ = source1 - source2 - 1;
1585 if (source1 > source2) goto carry_0;
1593 // Subtraktionsschleife:
1594 // übertrag = subfrom_loop_up(sourceptr,destptr,count);
1595 // subtrahiert count (uintC>=0) Digits aufwärts von sourceptr, von destptr
1596 // aufwärts nach destptr (dest := dest - source)
1597 // und liefert den Übertrag (0 oder /=0, was -1 bedeutet).
1598 inline uintD subfrom_loop_up (const uintD* sourceptr, uintD* destptr, uintC count)
1599 { var uintD source1;
1602 do { source1 = *destptr;
1603 source2 = *sourceptr++;
1604 *destptr++ = source1 - source2;
1605 if (source1 < source2) goto carry_1;
1611 do { source1 = *destptr;
1612 source2 = *sourceptr++;
1613 *destptr++ = source1 - source2 - 1;
1614 if (source1 > source2) goto carry_0;
1622 // Decrementierschleife:
1623 // übertrag = dec_loop_up(ptr,count);
1624 // decrementiert count (uintC>=0) Digits aufwärts von ptr, so lange bis kein
1625 // Übertrag mehr auftritt und liefert den Übertrag (0 oder -1).
1626 inline uintD dec_loop_up (uintD* ptr, uintC count)
1627 { dotimesC(count,count,
1628 { if (!( (*ptr++)-- == 0 )) return 0; } // kein weiterer Übertrag
1630 return (uintD)(-1); // weiterer Übertrag
1634 // übertrag = neg_loop_up(ptr,count);
1635 // negiert count (uintC>=0) Digits aufwärts von ptr,
1636 // und liefert den Übertrag (0 oder -1).
1637 inline uintD neg_loop_up (uintD* ptr, uintC count)
1638 { // erstes Digit /=0 suchen:
1639 until (count==0) { if (!(*ptr == 0)) goto L1; ptr++; count--; }
1641 L1: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
1642 *ptr = - *ptr; count--; // 1 Digit negieren
1643 dotimesC(count,count, { ptr++; *ptr = ~ *ptr; } ); // alle anderen Digits invertieren
1651 // Schiebeschleife um 1 Bit nach links:
1652 // übertrag = shift1left_loop_up(ptr,count);
1653 // schiebt count (uintC>=0) Digits aufwärts von ptr um 1 Bit nach links,
1654 // und liefert den Übertrag (0 oder /=0, was 1 bedeutet).
1656 inline uintD shift1left_loop_up (uintD* ptr, uintC count)
1657 { var uintDD accu = 0;
1658 dotimesC(count,count,
1659 { accu = ((uintDD)(*ptr)<<1)+accu; *ptr++ = lowD(accu);
1660 accu = (uintDD)(highD(accu));
1665 inline uintD shift1left_loop_up (uintD* ptr, uintC count)
1666 { var uintD carry = 0;
1667 dotimesC(count,count,
1668 { var uintD accu = *ptr;
1669 *ptr++ = (accu<<1) | carry;
1670 carry = accu>>(intDsize-1);
1676 // Schiebeschleife um i Bits nach links:
1677 // übertrag = shiftleft_loop_up(ptr,count,i,übertrag_init);
1678 // schiebt count (uintC>=0) Digits aufwärts von ptr um i Bits (0<i<intDsize)
1679 // nach links, schiebt dabei die i Bits aus übertrag_init rechts rein,
1680 // und liefert den Übertrag (was links rauskommt, >=0, <2^i).
1682 inline uintD shiftleft_loop_up (uintD* ptr, uintC count, uintC i, uintD carry)
1683 { var uintDD accu = (uintDD)carry;
1684 dotimesC(count,count,
1685 { accu = ((uintDD)(*ptr)<<i)+accu; *ptr++ = lowD(accu);
1686 accu = (uintDD)(highD(accu));
1691 inline uintD shiftleft_loop_up (uintD* ptr, uintC count, uintC i, uintD carry)
1692 { var uintC j = intDsize-i;
1693 dotimesC(count,count,
1694 { var uintD accu = *ptr;
1695 *ptr++ = (accu<<i) | carry;
1702 // Schiebe- und Kopierschleife um i Bits nach links:
1703 // übertrag = shiftleftcopy_loop_up(sourceptr,destptr,count,i);
1704 // kopiert count (uintC>=0) Digits aufwärts von sourceptr nach destptr
1705 // und schiebt sie dabei um i Bits (0<i<intDsize) nach links,
1706 // wobei ganz rechts mit i Nullbits aufgefüllt wird,
1707 // und liefert den Übertrag (was links rauskommt, >=0, <2^i).
1709 inline uintD shiftleftcopy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count, uintC i)
1710 { var uintDD accu = 0;
1711 dotimesC(count,count,
1712 { accu = ((uintDD)(*sourceptr++)<<i)+accu; *destptr++ = lowD(accu);
1713 accu = (uintDD)(highD(accu));
1718 inline uintD shiftleftcopy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count, uintC i)
1719 { var uintC j = intDsize-i;
1720 var uintD carry = 0;
1721 dotimesC(count,count,
1722 { var uintD accu = *sourceptr++;
1723 *destptr++ = (accu<<i) | carry;
1730 // Schiebeschleife um 1 Bit nach rechts:
1731 // übertrag = shift1right_loop_down(ptr,count,übertrag_init);
1732 // schiebt count (uintC>=0) Digits abwärts von ptr um 1 Bit nach rechts,
1733 // wobei links das Bit übertrag_init (sollte =0 oder =-1 sein) hineingeschoben
1734 // wird, und liefert den Übertrag (0 oder /=0, was 1 bedeutet).
1736 inline uintD shift1right_loop_down (uintD* ptr, uintC count, uintD carry)
1737 { var uintDD accu = (sintDD)(sintD)carry & ((uintDD)1 << (2*intDsize-1)); // 0 oder bit(2*intDsize-1)
1738 dotimesC(count,count,
1739 { accu = (highlowDD_0(*--ptr)>>1)+accu; *ptr = highD(accu);
1740 accu = highlowDD_0(lowD(accu));
1745 inline uintD shift1right_loop_down (uintD* ptr, uintC count, uintD carry)
1746 { carry = carry << (intDsize-1); // carry zu einem einzigen Bit machen
1747 dotimesC(count,count,
1748 { var uintD accu = *--ptr;
1749 *ptr = (accu >> 1) | carry;
1750 carry = accu << (intDsize-1);
1756 // Schiebeschleife um i Bits nach rechts:
1757 // übertrag = shiftright_loop_down(ptr,count,i);
1758 // schiebt count (uintC>=0) Digits abwärts von ptr um i Bits (0<i<intDsize)
1759 // nach rechts, wobei links Nullen eingeschoben werden,
1760 // und liefert den Übertrag (was rechts rauskommt, als Bits intDsize-1..intDsize-i).
1762 inline uintD shiftright_loop_down (uintD* ptr, uintC count, uintC i)
1763 { var uintDD accu = 0;
1764 dotimesC(count,count,
1765 { // Die oberen i Bits von (uintD)accu bilden hier den Übertrag.
1766 accu = highlowDD_0(lowD(accu));
1767 // Die oberen i Bits von (uintDD)accu bilden hier den Übertrag.
1768 accu = (highlowDD_0(*--ptr)>>i)+accu; *ptr = highD(accu);
1773 inline uintD shiftright_loop_down (uintD* ptr, uintC count, uintC i)
1774 { var uintC j = intDsize-i;
1775 var uintD carry = 0;
1776 dotimesC(count,count,
1777 { var uintD accu = *--ptr;
1778 *ptr = (accu >> i) | carry;
1785 // Schiebeschleife um i Bits nach rechts:
1786 // übertrag = shiftrightsigned_loop_down(ptr,count,i);
1787 // schiebt count (uintC>0) Digits abwärts von ptr um i Bits (0<i<intDsize)
1788 // nach rechts, wobei links das MSBit ver-i-facht wird,
1789 // und liefert den Übertrag (was rechts rauskommt, als Bits intDsize-1..intDsize-i).
1791 inline uintD shiftrightsigned_loop_down (uintD* ptr, uintC count, uintC i)
1792 { var uintDD accu = // Übertrag mit i Vorzeichenbits initialisieren
1793 highlowDD_0(sign_of_sintD((sintD)(ptr[-1])))>>i;
1794 dotimespC(count,count,
1795 { // Die oberen i Bits von (uintD)accu bilden hier den Übertrag.
1796 accu = highlowDD_0(lowD(accu));
1797 // Die oberen i Bits von (uintDD)accu bilden hier den Übertrag.
1798 accu = (highlowDD_0(*--ptr)>>i)+accu; *ptr = highD(accu);
1803 inline uintD shiftrightsigned_loop_down (uintD* ptr, uintC count, uintC i)
1804 { var uintC j = intDsize-i;
1806 { var uintD accu = *--ptr;
1807 *ptr = (sintD)accu >> i;
1811 dotimesC(count,count,
1812 { var uintD accu = *--ptr;
1813 *ptr = (accu >> i) | carry;
1820 // Schiebe- und Kopier-Schleife um i Bits nach rechts:
1821 // übertrag = shiftrightcopy_loop_down(sourceptr,destptr,count,i,carry);
1822 // kopiert count (uintC>=0) Digits abwärts von sourceptr nach destptr
1823 // und schiebt sie dabei um i Bits (0<i<intDsize) nach rechts, wobei carry
1824 // (sozusagen als sourceptr[0]) die i Bits ganz links bestimmt,
1825 // und liefert den Übertrag (was rechts rauskommt, als Bits intDsize-1..intDsize-i).
1827 inline uintD shiftrightcopy_loop_down (const uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry)
1828 { var uintDD accu = // Übertrag mit carry initialisieren
1829 highlowDD_0(carry)>>i;
1830 dotimesC(count,count,
1831 { // Die oberen i Bits von (uintD)accu bilden hier den Übertrag.
1832 accu = highlowDD_0(lowD(accu));
1833 // Die oberen i Bits von (uintDD)accu bilden hier den Übertrag.
1834 accu = (highlowDD_0(*--sourceptr)>>i)+accu; *--destptr = highD(accu);
1839 inline uintD shiftrightcopy_loop_down (const uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry)
1840 { var uintC j = intDsize-i;
1842 dotimesC(count,count,
1843 { var uintD accu = *--sourceptr;
1844 *--destptr = (accu >> i) | carry;
1855 // Multiplikations-Einfachschleife:
1856 // Multipliziert eine UDS mit einem kleinen Digit und addiert ein kleines Digit.
1857 // mulusmall_loop_up(digit,ptr,len,newdigit)
1858 // multipliziert die UDS ptr[0..len-1] mit digit (>=2, <=36),
1859 // addiert dabei newdigit (>=0, <digit) zur letzten Ziffer,
1860 // und liefert den Carry (>=0, <digit).
1862 inline uintD mulusmall_loop_up (uintD digit, uintD* ptr, uintC len, uintD newdigit)
1863 { var uintDD carry = newdigit;
1865 { // Hier ist 0 <= carry < digit.
1866 carry = carry + muluD(digit,*ptr);
1867 // Hier ist 0 <= carry < 2^intDsize*digit.
1868 *ptr++ = lowD(carry);
1869 carry = (uintDD)highD(carry); // carry := floor(carry/2^intDsize) < digit
1874 inline uintD mulusmall_loop_up (uintD digit, uintD* ptr, uintC len, uintD newdigit)
1875 { var uintD carry = newdigit;
1877 { // Hier ist 0 <= carry < digit.
1880 muluD(digit,*ptr,hi=,lo=);
1881 // Hier ist 0 <= 2^intDsize*hi + lo + carry < 2^intDsize*digit.
1882 lo += carry; if (lo < carry) { hi += 1; }
1890 // Multiplikations-Einfachschleife:
1891 // Multipliziert eine UDS mit einem Digit und legt das Ergebnis in einer
1893 // mulu_loop_up(digit,sourceptr,destptr,len);
1894 // multipliziert die UDS sourceptr[0..len-1] (len>0)
1895 // mit dem einzelnen digit
1896 // und legt das Ergebnis in der UDS destptr[0..len] ab.
1898 inline void mulu_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
1899 { var uintDD carry = 0;
1901 { // Hier ist carry=digit=0 oder 0 <= carry < digit.
1902 carry = carry + muluD(digit,*sourceptr++);
1903 // Hier ist carry=digit=0 oder 0 <= carry < 2^intDsize*digit.
1904 *destptr++ = lowD(carry);
1905 carry = (uintDD)highD(carry); // carry := floor(carry/2^intDsize) < digit
1907 *destptr++ = lowD(carry);
1910 inline void mulu_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
1911 { var uintD carry = 0;
1913 { // Hier ist carry=digit=0 oder 0 <= carry < digit.
1916 muluD(digit,*sourceptr++,hi=,lo=);
1917 // Hier ist 0 <= 2^intDsize*hi + lo + carry < 2^intDsize*digit oder hi=lo=carry=digit=0.
1918 lo += carry; if (lo < carry) { hi += 1; }
1926 // Multiplikations-Einfachschleife mit Akkumulation:
1927 // Multipliziert eine UDS mit einem Digit und addiert das Ergebnis zu einer
1929 // muluadd_loop_up(digit,sourceptr,destptr,len);
1930 // multipliziert die UDS sourceptr[0..len-1] (len>0)
1931 // mit dem einzelnen digit, legt das Ergebnis in der UDS destptr[0..len-1]
1932 // ab und liefert den weiteren Übertrag.
1934 inline uintD muluadd_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
1935 { var uintDD carry = 0;
1937 { dotimespC(len,len,
1938 { // Hier ist 0 <= carry <= digit.
1939 carry = carry + muluD(digit,*sourceptr++) + (uintDD)*destptr;
1940 // Hier ist 0 <= carry <= 2^intDsize*digit + 2^intDsize-1.
1941 *destptr++ = lowD(carry);
1942 carry = (uintDD)highD(carry); // carry := floor(carry/2^intDsize) <= digit
1948 inline uintD muluadd_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
1949 { var uintD carry = 0;
1951 { dotimespC(len,len,
1952 { // Hier ist 0 <= carry <= digit.
1955 muluD(digit,*sourceptr++,hi=,lo=);
1956 // Hier ist 0 <= 2^intDsize*hi + lo + carry + *destptr <= 2^intDsize*digit+2^intDsize-1.
1957 lo += carry; if (lo < carry) { hi += 1; }
1959 lo += carry; if (lo < carry) { hi += 1; }
1968 // Multiplikations-Einfachschleife mit Diminution:
1969 // Multipliziert eine UDS mit einem Digit und subtrahiert das Ergebnis von
1970 // einer zweiten UDS.
1971 // mulusub_loop_up(digit,sourceptr,destptr,len);
1972 // multipliziert die UDS sourceptr[0..len-1] (len>0) mit dem einzelnen
1973 // digit, subtrahiert das Ergebnis von der UDS destptr[0..len-1] und liefert
1974 // den weiteren Übertrag (>=0, evtl. von destptr[len] zu subtrahieren).
1976 inline uintD mulusub_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
1977 { var uintDD carry = 0;
1979 { dotimespC(len,len,
1980 { // Hier ist 0 <= carry <= digit.
1981 carry = carry + muluD(digit,*sourceptr++) + (uintD)(~(*destptr));
1982 // Hier ist 0 <= carry <= 2^intDsize*digit + 2^intDsize-1.
1983 *destptr++ = ~lowD(carry);
1984 carry = (uintDD)highD(carry); // carry := floor(carry/2^intDsize) <= digit
1985 // Hier ist 0 <= carry <= digit.
1990 return 0; // nichts zu subtrahieren -> kein Übertrag
1993 inline uintD mulusub_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
1994 { var uintD carry = 0;
1996 { dotimespC(len,len,
1997 { // Hier ist 0 <= carry <= digit.
2000 muluD(digit,*sourceptr++,hi=,lo=);
2001 // Hier ist 0 <= 2^intDsize*hi + lo + carry + ~(*destptr) <= 2^intDsize*digit+2^intDsize-1.
2002 lo += carry; if (lo < carry) { hi += 1; }
2004 *destptr++ = carry - lo; if (carry < lo) { hi += 1; }
2010 return 0; // nichts zu subtrahieren -> kein Übertrag
2018 // Divisions-Einfachschleife:
2019 // Dividiert eine UDS durch ein Digit.
2020 // divu_loop_down(digit,ptr,len)
2021 // dividiert die UDS ptr[-len..-1] durch digit,
2022 // legt das Ergebnis in derselben UDS ab, und liefert den Rest (>=0, <digit).
2024 inline uintD divu_loop_down (uintD digit, uintD* ptr, uintC len)
2025 { var uintD rest = 0;
2027 { --ptr; divuD(highlowDD(rest,*ptr),digit,*ptr =, rest =); }
2032 inline uintD divu_loop_down (uintD digit, uintD* ptr, uintC len)
2033 { var uintD rest = 0;
2035 { --ptr; divuD(rest,*ptr,digit,*ptr =, rest =); }
2041 // Divisions-Einfachschleife:
2042 // Dividiert eine UDS durch ein Digit und legt das Ergebnis in einer
2044 // divucopy_loop_down(digit,sourceptr,destptr,len)
2045 // dividiert die UDS sourceptr[-len..-1] durch digit,
2046 // legt das Ergebnis in der UDS destptr[-len..-1] ab,
2047 // und liefert den Rest (>=0, <digit).
2049 inline uintD divucopy_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
2050 { var uintD rest = 0;
2052 { divuD(highlowDD(rest,*--sourceptr),digit,*--destptr =, rest =); }
2057 inline uintD divucopy_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
2058 { var uintD rest = 0;
2060 { divuD(rest,*--sourceptr,digit,*--destptr =, rest =); }
2068 #endif // !CL_DS_BIG_ENDIAN_P
2070 #if !defined(TEST_LOOPS) && !CL_DS_BIG_ENDIAN_P
2072 // Vergleichsschleife:
2073 // result = compare_loop_up(xptr,yptr,count);
2074 // vergleicht nacheinander xptr[0] mit yptr[0], xptr[1] mit yptr[1], usw.,
2075 // insgesamt count Digits, und liefert 0 falls alle gleich sind,
2076 // +1 falls zuerst ein xptr[i]>yptr[i] ist,
2077 // -1 falls zuerst ein xptr[i]<yptr[i] ist.
2078 inline cl_signean compare_loop_up (const uintD* xptr, const uintD* yptr, uintC count)
2079 { dotimesC(count,count,
2080 { if (!(*xptr++ == *yptr++))
2081 // verschiedene Digits gefunden
2082 return (*--xptr > *--yptr ? signean_plus : signean_minus);
2084 return signean_null; // alle Digits gleich
2089 #if !defined(LOG_LOOPS) && !CL_DS_BIG_ENDIAN_P
2092 // xor_loop_up(xptr,yptr,count);
2093 // verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr
2094 // mit Ziel ab xptr durch XOR.
2095 inline void xor_loop_up (uintD* xptr, const uintD* yptr, uintC count)
2096 { dotimesC(count,count, { *xptr++ ^= *yptr++; } ); }
2100 #if !defined(SHIFT_LOOPS) && CL_DS_BIG_ENDIAN_P
2102 // Schiebe- und Kopierschleife um i Bits nach links:
2103 // übertrag = shiftleftcopy_loop_up(sourceptr,destptr,count,i);
2104 // kopiert count (uintC>=0) Digits aufwärts von sourceptr nach destptr
2105 // und schiebt sie dabei um i Bits (0<i<intDsize) nach links,
2106 // wobei ganz rechts mit i Nullbits aufgefüllt wird,
2107 // und liefert den Übertrag (was links rauskommt, >=0, <2^i).
2109 inline uintD shiftleftcopy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count, uintC i)
2110 { var uintDD accu = 0;
2111 dotimesC(count,count,
2112 { accu = ((uintDD)(*sourceptr++)<<i)+accu; *destptr++ = lowD(accu);
2113 accu = (uintDD)(highD(accu));
2118 inline uintD shiftleftcopy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count, uintC i)
2119 { var uintC j = intDsize-i;
2120 var uintD carry = 0;
2121 dotimesC(count,count,
2122 { var uintD accu = *sourceptr++;
2123 *destptr++ = (accu<<i) | carry;
2132 #if !defined(SHIFT_LOOPS)
2134 // Schiebe- und XOR-Schleife:
2135 // shiftxor_loop_up(xptr,yptr,count,i);
2136 // verknüpft count+1 Digits aufwärts ab xptr mit count Digits aufwärts ab yptr,
2137 // um i Bits verschoben, durch XOR. (count uintC>=0, 0<i<intDsize)
2139 inline void shiftxor_loop_up (uintD* xptr, const uintD* yptr, uintC count, uintC i)
2141 { var uintD carry = xptr[0];
2142 dotimespC(count,count,
2143 { var uintDD accu = highlowDD(xptr[1],carry);
2144 accu = ((uintDD)(*yptr++)<<i) ^ accu;
2145 *xptr++ = lowD(accu);
2146 carry = highD(accu);
2151 inline void shiftxor_loop_up (uintD* xptr, const uintD* yptr, uintC count, uintC i)
2153 { var uintC j = intDsize-i;
2154 var uintD carry = *xptr;
2155 dotimespC(count,count,
2156 { var uintD accu = *yptr++;
2157 *xptr++ = (accu<<i) ^ carry;
2158 carry = (accu>>j) ^ *xptr;
2167 // Endianness independent names for these functions.
2168 #if CL_DS_BIG_ENDIAN_P
2169 #define copy_loop_msp copy_loop_up
2170 #define copy_loop_lsp copy_loop_down
2171 #define fill_loop_msp fill_loop_up
2172 #define fill_loop_lsp fill_loop_down
2173 #define clear_loop_msp clear_loop_up
2174 #define clear_loop_lsp clear_loop_down
2175 #define test_loop_msp test_loop_up
2176 #define or_loop_msp or_loop_up
2177 #define xor_loop_msp xor_loop_up
2178 #define and_loop_msp and_loop_up
2179 #define eqv_loop_msp eqv_loop_up
2180 #define nand_loop_msp nand_loop_up
2181 #define nor_loop_msp nor_loop_up
2182 #define andc2_loop_msp andc2_loop_up
2183 #define orc2_loop_msp orc2_loop_up
2184 #define not_loop_msp not_loop_up
2185 #define and_test_loop_msp and_test_loop_up
2186 #define compare_loop_msp compare_loop_up
2187 #define add_loop_lsp add_loop_down
2188 #define addto_loop_lsp addto_loop_down
2189 #define inc_loop_lsp inc_loop_down
2190 #define sub_loop_lsp sub_loop_down
2191 #define subx_loop_lsp subx_loop_down
2192 #define subfrom_loop_lsp subfrom_loop_down
2193 #define dec_loop_lsp dec_loop_down
2194 #define neg_loop_lsp neg_loop_down
2195 #define shift1left_loop_lsp shift1left_loop_down
2196 #define shiftleft_loop_lsp shiftleft_loop_down
2197 #define shiftleftcopy_loop_lsp shiftleftcopy_loop_down
2198 #define shift1right_loop_msp shift1right_loop_up
2199 #define shiftright_loop_msp shiftright_loop_up
2200 #define shiftrightsigned_loop_msp shiftrightsigned_loop_up
2201 #define shiftrightcopy_loop_msp shiftrightcopy_loop_up
2202 #define mulusmall_loop_lsp mulusmall_loop_down
2203 #define mulu_loop_lsp mulu_loop_down
2204 #define muluadd_loop_lsp muluadd_loop_down
2205 #define mulusub_loop_lsp mulusub_loop_down
2206 #define divu_loop_msp divu_loop_up
2207 #define divucopy_loop_msp divucopy_loop_up
2209 #define copy_loop_msp copy_loop_down
2210 #define copy_loop_lsp copy_loop_up
2211 #define fill_loop_msp fill_loop_down
2212 #define fill_loop_lsp fill_loop_up
2213 #define clear_loop_msp clear_loop_down
2214 #define clear_loop_lsp clear_loop_up
2215 #define test_loop_msp test_loop_down
2216 #define or_loop_msp or_loop_down
2217 #define xor_loop_msp xor_loop_down
2218 #define and_loop_msp and_loop_down
2219 #define eqv_loop_msp eqv_loop_down
2220 #define nand_loop_msp nand_loop_down
2221 #define nor_loop_msp nor_loop_down
2222 #define andc2_loop_msp andc2_loop_down
2223 #define orc2_loop_msp orc2_loop_down
2224 #define not_loop_msp not_loop_down
2225 #define and_test_loop_msp and_test_loop_down
2226 #define compare_loop_msp compare_loop_down
2227 #define add_loop_lsp add_loop_up
2228 #define addto_loop_lsp addto_loop_up
2229 #define inc_loop_lsp inc_loop_up
2230 #define sub_loop_lsp sub_loop_up
2231 #define subx_loop_lsp subx_loop_up
2232 #define subfrom_loop_lsp subfrom_loop_up
2233 #define dec_loop_lsp dec_loop_up
2234 #define neg_loop_lsp neg_loop_up
2235 #define shift1left_loop_lsp shift1left_loop_up
2236 #define shiftleft_loop_lsp shiftleft_loop_up
2237 #define shiftleftcopy_loop_lsp shiftleftcopy_loop_up
2238 #define shift1right_loop_msp shift1right_loop_down
2239 #define shiftright_loop_msp shiftright_loop_down
2240 #define shiftrightsigned_loop_msp shiftrightsigned_loop_down
2241 #define shiftrightcopy_loop_msp shiftrightcopy_loop_down
2242 #define mulusmall_loop_lsp mulusmall_loop_up
2243 #define mulu_loop_lsp mulu_loop_up
2244 #define muluadd_loop_lsp muluadd_loop_up
2245 #define mulusub_loop_lsp mulusub_loop_up
2246 #define divu_loop_msp divu_loop_down
2247 #define divucopy_loop_msp divucopy_loop_down
2250 // Endianness independent loops where the direction doesn't matter.
2251 #if CL_DS_BIG_ENDIAN_P
2252 #define DS_clear_loop(MSDptr,len,LSDptr) (void)clear_loop_up(MSDptr,len)
2253 #define DS_test_loop(MSDptr,len,LSDptr) test_loop_up(MSDptr,len)
2255 #define DS_clear_loop(MSDptr,len,LSDptr) (void)clear_loop_up(LSDptr,len)
2256 #define DS_test_loop(MSDptr,len,LSDptr) test_loop_up(LSDptr,len)
2260 // Umwandlungsroutinen Digit-Sequence-Teil <--> Longword:
2263 // holt die nächsten 32 Bits aus den 32/intDsize Digits ab ptr.
2264 // set_32_Dptr(ptr,wert);
2265 // speichert den Wert wert (32 Bits) in die 32/intDsize Digits ab ptr.
2266 // get_max32_Dptr(count,ptr)
2267 // holt die nächsten count Bits aus den ceiling(count/intDsize) Digits ab ptr.
2268 // set_max32_Dptr(count,ptr,wert)
2269 // speichert wert (count Bits) in die ceiling(count/intDsize) Digits ab ptr.
2270 // Jeweils ptr eine Variable vom Typ uintD*,
2271 // wert eine Variable vom Typ uint32,
2272 // count eine Variable oder constant-expression mit Wert >=0, <=32.
2274 inline uint32 get_32_Dptr (const uintD* ptr)
2276 return mspref(ptr,0);
2278 inline void set_32_Dptr (uintD* ptr, uint32 wert)
2280 mspref(ptr,0) = wert;
2282 inline uint32 get_max32_Dptr (uintC count, const uintD* ptr)
2284 return count==0 ? 0 :
2287 inline void set_max32_Dptr (uintC count, uintD* ptr, uint32 wert)
2289 if (count==0) return;
2290 mspref(ptr,0) = wert; return;
2294 inline uint32 get_32_Dptr (const uintD* ptr)
2296 return ((uint32)mspref(ptr,0)<<16) | (uint32)mspref(ptr,1);
2298 inline void set_32_Dptr (uintD* ptr, uint32 wert)
2300 mspref(ptr,0) = (uintD)(wert>>16); mspref(ptr,1) = (uintD)wert;
2302 inline uint32 get_max32_Dptr (uintC count, const uintD* ptr)
2304 return count==0 ? 0 :
2305 count<=16 ? mspref(ptr,0) :
2306 ((uint32)mspref(ptr,0)<<16) | (uint32)mspref(ptr,1);
2308 inline void set_max32_Dptr (uintC count, uintD* ptr, uint32 wert)
2310 if (count==0) return;
2311 if (count<=16) { mspref(ptr,0) = (uintD)wert; return; }
2312 mspref(ptr,0) = (uintD)(wert>>16); mspref(ptr,1) = (uintD)wert; return;
2316 inline uint32 get_32_Dptr (const uintD* ptr)
2318 return ((((((uint32)mspref(ptr,0) <<8) | (uint32)mspref(ptr,1)) <<8) | (uint32)mspref(ptr,2)) <<8) | (uint32)mspref(ptr,3);
2320 inline void set_32_Dptr (uintD* ptr, uint32 wert)
2322 mspref(ptr,0) = (uintD)(wert>>24); mspref(ptr,1) = (uintD)(wert>>16); mspref(ptr,2) = (uintD)(wert>>8); mspref(ptr,3) = (uintD)wert;
2324 inline uint32 get_max32_Dptr (uintC count, const uintD* ptr)
2326 return count==0 ? 0 :
2327 count<=8 ? mspref(ptr,0) :
2328 count<=16 ? ((uint32)mspref(ptr,0)<<8) | (uint32)mspref(ptr,1) :
2329 count<=24 ? ((((uint32)mspref(ptr,0)<<8) | (uint32)mspref(ptr,1))<<8) | (uint32)mspref(ptr,2) :
2330 ((((((uint32)mspref(ptr,0)<<8) | (uint32)mspref(ptr,1))<<8) | (uint32)mspref(ptr,2))<<8) | (uint32)mspref(ptr,3);
2332 inline void set_max32_Dptr (uintC count, uintD* ptr, uint32 wert)
2334 if (count==0) return;
2335 if (count<=8) { mspref(ptr,0) = (uintD)wert; return; }
2336 if (count<=16) { mspref(ptr,0) = (uintD)(wert>>8); mspref(ptr,1) = (uintD)wert; return; }
2337 if (count<=24) { mspref(ptr,0) = (uintD)(wert>>16); mspref(ptr,1) = (uintD)(wert>>8); mspref(ptr,2) = (uintD)wert; return; }
2338 mspref(ptr,0) = (uintD)(wert>>24); mspref(ptr,1) = (uintD)(wert>>16); mspref(ptr,2) = (uintD)(wert>>8); mspref(ptr,3) = (uintD)wert; return;
2342 #if (cl_word_size==64)
2344 // holt die nächsten 64 Bits aus den 64/intDsize Digits ab ptr.
2345 // set_64_Dptr(ptr,wert);
2346 // speichert den Wert wert (64 Bits) in die 64/intDsize Digits ab ptr.
2347 // get_max64_Dptr(count,ptr)
2348 // holt die nächsten count Bits aus den ceiling(count/intDsize) Digits ab ptr.
2349 // set_max64_Dptr(count,ptr,wert)
2350 // speichert wert (count Bits) in die ceiling(count/intDsize) Digits ab ptr.
2351 // Jeweils ptr eine Variable vom Typ uintD*,
2352 // wert eine Variable vom Typ uint64,
2353 // count eine Variable oder constant-expression mit Wert >=0, <=64.
2355 inline uint64 get_64_Dptr (const uintD* ptr)
2357 return mspref(ptr,0);
2359 inline void set_64_Dptr (uintD* ptr, uint64 wert)
2361 mspref(ptr,0) = wert;
2363 inline uint64 get_max64_Dptr (uintC count, const uintD* ptr)
2365 return count==0 ? 0 : mspref(ptr,0);
2367 inline void set_max64_Dptr (uintC count, uintD* ptr, uint64 wert)
2369 if (count==0) return;
2370 mspref(ptr,0) = wert; return;
2372 #else // (intDsize<=32)
2373 inline uint64 get_64_Dptr (const uintD* ptr)
2375 return ((uint64)get_32_Dptr(ptr) << 32) | (uint64)get_32_Dptr(ptr mspop 32/intDsize);
2377 inline void set_64_Dptr (uintD* ptr, uint64 wert)
2379 set_32_Dptr(ptr,(uint32)(wert>>32));
2380 set_32_Dptr(ptr mspop 32/intDsize,(uint32)wert);
2382 inline uint64 get_max64_Dptr (uintC count, const uintD* ptr)
2384 return count==0 ? 0 :
2385 count<=32 ? (uint64)get_max32_Dptr(count,ptr) :
2386 ((uint64)get_max32_Dptr(count-32,ptr) << 32) | (uint64)get_32_Dptr(ptr mspop ceiling(count-32,intDsize));
2388 inline void set_max64_Dptr (uintC count, uintD* ptr, uint64 wert)
2390 if (count==0) return;
2391 if (count<=32) { set_max32_Dptr(count,ptr,(uint32)wert); return; }
2392 set_max32_Dptr(count-32,ptr,(uint32)(wert>>32));
2393 set_32_Dptr(ptr mspop ceiling(count-32,intDsize),(uint32)wert); return;
2398 // get_uint1D_Dptr(ptr) holt 1 Digit (unsigned) ab ptr
2399 // get_uint2D_Dptr(ptr) holt 2 Digits (unsigned) ab ptr
2400 // get_uint3D_Dptr(ptr) holt 3 Digits (unsigned) ab ptr
2401 // get_uint4D_Dptr(ptr) holt 4 Digits (unsigned) ab ptr
2402 // get_sint1D_Dptr(ptr) holt 1 Digit (signed) ab ptr
2403 // get_sint2D_Dptr(ptr) holt 2 Digits (signed) ab ptr
2404 // get_sint3D_Dptr(ptr) holt 3 Digits (signed) ab ptr
2405 // get_sint4D_Dptr(ptr) holt 4 Digits (signed) ab ptr
2406 // Jeweils ptr eine Variable vom Typ uintD*.
2407 // NB: Bei intDsize==64 sind diese Funktionen nur sehr bedingt tauglich.
2408 inline uint32 get_uint1D_Dptr (const uintD* ptr)
2410 return lspref(ptr,0);
2412 inline sint32 get_sint1D_Dptr (const uintD* ptr)
2414 return (sint32)(sintD)lspref(ptr,0);
2417 inline uint32 get_uint2D_Dptr (const uintD* ptr)
2419 return ((uint32)lspref(ptr,1) << intDsize) | (uint32)lspref(ptr,0);
2421 inline sint32 get_sint2D_Dptr (const uintD* ptr)
2423 return ((uint32)(sint32)(sintD)lspref(ptr,1) << intDsize) | (uint32)lspref(ptr,0);
2426 #define get_uint2D_Dptr(ptr) get_uint1D_Dptr(ptr)
2427 #define get_sint2D_Dptr(ptr) (sint32)get_uint2D_Dptr(ptr)
2430 inline uint32 get_uint3D_Dptr (const uintD* ptr)
2432 return ((((uint32)lspref(ptr,2) << intDsize) | (uint32)lspref(ptr,1)) << intDsize) | (uint32)lspref(ptr,0);
2434 inline sint32 get_sint3D_Dptr (const uintD* ptr)
2436 return ((((uint32)(sint32)(sintD)lspref(ptr,2) << intDsize) | (uint32)lspref(ptr,1)) << intDsize) | (uint32)lspref(ptr,0);
2438 inline uint32 get_uint4D_Dptr (const uintD* ptr)
2440 return ((((((uint32)lspref(ptr,3) << intDsize) | (uint32)lspref(ptr,2)) << intDsize) | (uint32)lspref(ptr,1)) << intDsize) | (uint32)lspref(ptr,0);
2442 inline sint32 get_sint4D_Dptr (const uintD* ptr)
2444 return ((((((uint32)(sint32)(sintD)lspref(ptr,3) << intDsize) | (uint32)lspref(ptr,2)) << intDsize) | (uint32)lspref(ptr,1)) << intDsize) | (uint32)lspref(ptr,0);
2447 #define get_uint3D_Dptr(ptr) get_uint2D_Dptr(ptr)
2448 #define get_sint3D_Dptr(ptr) (sint32)get_uint3D_Dptr(ptr)
2449 #define get_uint4D_Dptr(ptr) get_uint2D_Dptr(ptr)
2450 #define get_sint4D_Dptr(ptr) (sint32)get_uint4D_Dptr(ptr)
2454 // NUM_STACK ist eine Art Zahlen-Stack-Pointer.
2456 // {CL_ALLOCA_STACK;
2458 // num_stack_alloc(...);
2460 // num_stack_array(...);
2463 // CL_ALLOCA_STACK rettet den aktuellen Wert von NUM_STACK.
2464 // Dann darf beliebig oft mit num_stack_alloc/num_stack_array Platz auf dem
2465 // Zahlen-Stack belegt werden.
2466 // Beim Ende des Blocks wird NUM_STACK wieder auf den vorigen Wert gesetzt,
2467 // und der Platz gilt als wieder freigegeben.
2468 // In jeder C-Funktion sollte CL_ALLOCA_STACK nur einmal aufgerufen werden.
2469 // Wegen eines GCC-Bugs sollten Funktionen, die diese Macros benutzen,
2470 // nicht inline deklariert sein.
2472 // num_stack_array(need, low_addr = , high_addr = );
2473 // num_stack_small_array(need, low_addr = , high_addr = );
2474 // belegt need Digits auf dem Zahlen-Stack und legt die untere Grenze des
2475 // allozierten Bereichs in low_addr und die obere Grenze in high_addr ab.
2476 // Jedes von beiden ist optional.
2478 // num_stack_alloc(need, MSDptr = , LSDptr = );
2479 // num_stack_small_alloc(need, MSDptr = , LSDptr = );
2480 // belegt need Digits auf dem Zahlen-Stack und legt den MSDptr und den
2481 // LSDptr ab. Jedes von beiden ist optional.
2483 // num_stack_alloc_1(need, MSDptr = , LSDptr = );
2484 // num_stack_small_alloc_1(need, MSDptr = , LSDptr = );
2485 // wie num_stack_alloc, nur daß unterhalb von MSDptr noch ein Digit Platz
2486 // zusätzlich belegt wird.
2488 #define num_stack_array(need,low_zuweisung,high_zuweisung) \
2489 {var uintL __need = (uintL)(need); \
2490 var uintD* __array = cl_alloc_array(uintD,__need); \
2491 unused (low_zuweisung &__array[0]); unused (high_zuweisung &__array[__need]); \
2493 #define num_stack_small_array(need,low_zuweisung,high_zuweisung) \
2494 {var uintL __need = (uintL)(need); \
2495 var uintD* __array = cl_small_alloc_array(uintD,__need); \
2496 unused (low_zuweisung &__array[0]); unused (high_zuweisung &__array[__need]); \
2498 #if CL_DS_BIG_ENDIAN_P
2499 #define num_stack_alloc(need,MSDptr_zuweisung,LSDptr_zuweisung) \
2500 num_stack_array(need,MSDptr_zuweisung,LSDptr_zuweisung)
2501 #define num_stack_small_alloc(need,MSDptr_zuweisung,LSDptr_zuweisung) \
2502 num_stack_small_array(need,MSDptr_zuweisung,LSDptr_zuweisung)
2503 #define num_stack_alloc_1(need,MSDptr_zuweisung,LSDptr_zuweisung) \
2504 num_stack_array((uintL)(need)+1,MSDptr_zuweisung 1 + ,LSDptr_zuweisung)
2505 #define num_stack_small_alloc_1(need,MSDptr_zuweisung,LSDptr_zuweisung) \
2506 num_stack_small_array((uintL)(need)+1,MSDptr_zuweisung 1 + ,LSDptr_zuweisung)
2508 #define num_stack_alloc(need,MSDptr_zuweisung,LSDptr_zuweisung) \
2509 num_stack_array(need,LSDptr_zuweisung,MSDptr_zuweisung)
2510 #define num_stack_small_alloc(need,MSDptr_zuweisung,LSDptr_zuweisung) \
2511 num_stack_small_array(need,LSDptr_zuweisung,MSDptr_zuweisung)
2512 #define num_stack_alloc_1(need,MSDptr_zuweisung,LSDptr_zuweisung) \
2513 num_stack_array((uintL)(need)+1,LSDptr_zuweisung,MSDptr_zuweisung -1 + )
2514 #define num_stack_small_alloc_1(need,MSDptr_zuweisung,LSDptr_zuweisung) \
2515 num_stack_small_array((uintL)(need)+1,LSDptr_zuweisung,MSDptr_zuweisung -1 + )
2519 // Macro: In der DS MSDptr/len/LSDptr wird eine 1 unterhalb des Pointers ptr
2520 // addiert. Unterhalb von MSDptr muß 1 Digit Platz sein.
2521 // Dabei ist ptr - MSDptr = count und 0 < count <= len .
2522 // Eventuell wird MSDptr erniedrigt und len erhöht.
2523 #define DS_1_plus(ptr,count) \
2524 {var uintD* ptr_from_DS_1_plus = (ptr); \
2525 var uintC count_from_DS_1_plus = (count); \
2526 loop { if (--count_from_DS_1_plus==0) /* Zähler erniedrigen */\
2527 { /* Beim Most Significant Digit angelangt */\
2528 lsprefnext(ptr_from_DS_1_plus) += 1; \
2529 /* jetzt ist ptr_from_DS_1_plus = MSDptr */\
2530 if (mspref(ptr_from_DS_1_plus,0) == (uintD)bit(intDsize-1)) \
2531 { /* 7FFF + 1 muß zu 00008000 werden: */\
2532 lsprefnext(MSDptr) = 0; \
2537 if (!((lsprefnext(ptr_from_DS_1_plus) += 1) == 0)) /* weiterincrementieren */\
2538 break; /* kein weiterer Übertrag -> Schleife abbrechen */\
2541 // Macro: In der DS MSDptr/len/LSDptr wird eine 1 unterhalb des Pointers ptr
2542 // subtrahiert. Unterhalb von MSDptr muß 1 Digit Platz sein.
2543 // Dabei ist ptr - MSDptr = count und 0 < count <= len .
2544 // Eventuell wird MSDptr erniedrigt und len erhöht.
2545 #define DS_minus1_plus(ptr,count) \
2546 {var uintD* ptr_from_DS_minus1_plus = (ptr); \
2547 var uintC count_from_DS_minus1_plus = (count); \
2548 loop { if (--count_from_DS_minus1_plus==0) /* Zähler erniedrigen */\
2549 { /* Beim Most Significant Digit angelangt */\
2550 lsprefnext(ptr_from_DS_minus1_plus) -= 1; \
2551 /* jetzt ist ptr_from_DS_minus1_plus = MSDptr */\
2552 if (mspref(ptr_from_DS_minus1_plus,0) == (uintD)bit(intDsize-1)-1) \
2553 { /* 8000 - 1 muß zu FFFF7FFF werden: */\
2554 lsprefnext(MSDptr) = (uintD)(-1); \
2559 if (!((sintD)(lsprefnext(ptr_from_DS_minus1_plus) -= 1) == -1)) /* weiterdecrementieren */\
2560 break; /* kein weiterer Übertrag -> Schleife abbrechen */\
2564 // Multiplikations-Doppelschleife:
2565 // Multipliziert zwei UDS und legt das Ergebnis in einer dritten UDS ab.
2566 // cl_UDS_mul(sourceptr1,len1,sourceptr2,len2,destptr);
2567 // multipliziert die UDS sourceptr1[-len1..-1] (len1>0)
2568 // mit der UDS sourceptr2[-len1..-1] (len2>0)
2569 // und legt das Ergebnis in der UDS destptr[-len..-1] (len=len1+len2) ab.
2570 // Unterhalb von destptr werden len Digits Platz benötigt.
2571 extern void cl_UDS_mul (const uintD* sourceptr1, uintC len1,
2572 const uintD* sourceptr2, uintC len2,
2574 // Spezialfall sourceptr1 == sourceptr2 && len1 == len2.
2575 extern void cl_UDS_mul_square (const uintD* sourceptr, uintC len,
2578 // Multipliziert zwei Unsigned-Digit-sequences.
2579 // UDS_UDS_mul_UDS(len1,LSDptr1, len2,LSDptr2, MSDptr=,len=,LSDptr=);
2580 // multipliziert die UDS ../len1/LSDptr1 und ../len2/LSDptr2.
2581 // Dabei sollte len1>0 und len2>0 sein.
2582 // Ergebnis ist die UDS MSDptr/len/LSDptr, mit len=len1+len2, im Stack.
2583 // Dabei wird num_stack erniedrigt.
2584 #define UDS_UDS_mul_UDS(len1,LSDptr1,len2,LSDptr2, MSDptr_zuweisung,len_zuweisung,LSDptr_zuweisung) \
2585 var uintL CONCAT(len_from_UDSmul_,__LINE__) = (uintL)(len1) + (uintL)(len2); \
2586 var uintD* CONCAT(LSDptr_from_UDSmul_,__LINE__); \
2587 unused (len_zuweisung CONCAT(len_from_UDSmul_,__LINE__)); \
2588 num_stack_alloc(CONCAT(len_from_UDSmul_,__LINE__),MSDptr_zuweisung,LSDptr_zuweisung CONCAT(LSDptr_from_UDSmul_,__LINE__) =); \
2589 cl_UDS_mul((LSDptr1),(len1),(LSDptr2),(len2),CONCAT(LSDptr_from_UDSmul_,__LINE__));
2591 // Multipliziert zwei Digit-sequences.
2592 // DS_DS_mul_DS(MSDptr1,len1,LSDptr1, MSDptr2,len2,LSDptr2, MSDptr=,len=,LSDptr=);
2593 // multipliziert die DS MSDptr1/len1/LSDptr1 und MSDptr2/len2/LSDptr2.
2594 // Dabei sollte len1>0 und len2>0 sein, und beide DS sollten /= 0 sein.
2595 // Alles sollten Variablen sein!
2596 // Ergebnis ist die DS MSDptr/len/LSDptr, mit len=len1+len2, im Stack.
2597 // Dabei wird num_stack erniedrigt.
2599 // Erst unsigned multiplizieren. Dann bis zu zwei Subtraktionen.
2600 // Sei b=2^intDsize, k=len1, l=len2, n=DS1, m=DS2.
2601 // Gesucht ist n * m.
2602 // Wir errechnen erst das unsigned-product p (mod b^(k+l)).
2603 // n>0, m>0: p = n*m, n*m = p
2604 // n<0, m>0: p = (n+b^k)*m, n*m + b^(k+l) = p - b^k * m (mod b^(k+l)).
2605 // n>0, m<0: p = n*(m+b^l), n*m + b^(k+l) = p - b^l * n (mod b^(k+l)).
2606 // n<0, m<0: p = (n+b^k)*(m+b^l),
2607 // n*m = p - b^k * (m+b^l) - b^l * (n+b^k) (mod b^(k+l)).
2608 #define DS_DS_mul_DS(MSDptr1,len1,LSDptr1,MSDptr2,len2,LSDptr2, MSDptr_zuweisung,len_zuweisung,LSDptr_zuweisung) \
2609 var uintD* MSDptr0; \
2610 var uintD* LSDptr0; \
2611 var uintL len_from_DSmal = (uintL)(len1) + (uintL)(len2); \
2612 unused (len_zuweisung len_from_DSmal); \
2613 num_stack_alloc(len_from_DSmal,MSDptr_zuweisung MSDptr0 =,LSDptr_zuweisung LSDptr0 =); \
2614 var uintD MSD1_from_DSmal = mspref(MSDptr1,0); \
2615 var uintD MSD2_from_DSmal = mspref(MSDptr2,0); \
2616 var uintL len1_from_DSmal = (len1); \
2617 var uintL len2_from_DSmal = (len2); \
2618 if (MSD1_from_DSmal==0) { msprefnext(MSDptr0) = 0; len1_from_DSmal--; } \
2619 if (MSD2_from_DSmal==0) { msprefnext(MSDptr0) = 0; len2_from_DSmal--; } \
2620 cl_UDS_mul((LSDptr1),len1_from_DSmal,(LSDptr2),len2_from_DSmal,LSDptr0); \
2621 if ((sintD)MSD1_from_DSmal < 0) /* n<0 ? */\
2622 /* muß m bzw. m+b^l subtrahieren, um k Digits verschoben: */\
2623 { subfrom_loop_lsp(LSDptr2,LSDptr0 lspop len1,len2); } \
2624 if ((sintD)MSD2_from_DSmal < 0) /* m<0 ? */\
2625 /* muß n bzw. n+b^k subtrahieren, um l Digits verschoben: */\
2626 { subfrom_loop_lsp(LSDptr1,LSDptr0 lspop len2,len1); }
2629 // Dividiert zwei Unsigned Digit sequences durcheinander.
2630 // UDS_divide(a_MSDptr,a_len,a_LSDptr, b_MSDptr,b_len,b_LSDptr, &q,&r);
2631 // Die UDS a = a_MSDptr/a_len/a_LSDptr (a>=0) wird durch
2632 // die UDS b = b_MSDptr/b_len/b_LSDptr (b>=0) dividiert:
2633 // a = q * b + r mit 0 <= r < b. Bei b=0 Error.
2634 // q der Quotient, r der Rest.
2635 // q = q_MSDptr/q_len/q_LSDptr, r = r_MSDptr/r_len/r_LSDptr beides
2636 // Normalized Unsigned Digit sequences.
2637 // Vorsicht: q_LSDptr <= r_MSDptr,
2638 // Vorzeichenerweiterung von r kann q zerstören!
2639 // Vorzeichenerweiterung von q ist erlaubt.
2640 // a und b werden nicht modifiziert.
2641 // num_stack wird erniedrigt.
2642 #define UDS_divide(a_MSDptr,a_len,a_LSDptr,b_MSDptr,b_len,b_LSDptr,q_,r_) \
2643 /* Platz fürs Ergebnis machen. Brauche maximal a_len+1 Digits. */\
2644 var uintC _a_len = (a_len); \
2645 var uintD* roomptr; num_stack_alloc_1(_a_len+1,roomptr=,); \
2646 cl_UDS_divide(a_MSDptr,_a_len,a_LSDptr,b_MSDptr,b_len,b_LSDptr,roomptr,q_,r_);
2647 extern void cl_UDS_divide (const uintD* a_MSDptr, uintC a_len, const uintD* a_LSDptr,
2648 const uintD* b_MSDptr, uintC b_len, const uintD* b_LSDptr,
2649 uintD* roomptr, DS* q_, DS* r_);
2652 // Bildet zu einer Unsigned Digit sequence a die Wurzel
2653 // (genauer: Gaußklammer aus Wurzel aus a).
2654 // UDS_sqrt(a_MSDptr,a_len,a_LSDptr, &b, squarep=)
2655 // > a_MSDptr/a_len/a_LSDptr: eine UDS
2656 // < NUDS b: Gaußklammer der Wurzel aus a
2657 // < squarep: cl_true falls a = b^2, cl_false falls b^2 < a < (b+1)^2.
2658 // a wird nicht modifiziert.
2659 // Vorzeichenerweiterung von b ist erlaubt.
2660 // num_stack wird erniedrigt.
2661 #define UDS_sqrt(a_MSDptr,a_len,a_LSDptr,b_,squarep_zuweisung) \
2662 { /* ceiling(a_len,2) Digits Platz fürs Ergebnis machen: */\
2663 var uintC _a_len = (a_len); \
2664 num_stack_alloc_1(ceiling(_a_len,2),(b_)->MSDptr=,); \
2665 squarep_zuweisung cl_UDS_sqrt(a_MSDptr,_a_len,a_LSDptr,b_); \
2667 extern cl_boolean cl_UDS_sqrt (const uintD* a_MSDptr, uintC a_len, const uintD* a_LSDptr, DS* b_);
2670 // Auxiliary function for approximately computing 1/x
2671 // using Newton iteration.
2672 extern void cl_UDS_recip (const uintD* a_MSDptr, uintC a_len,
2673 uintD* b_MSDptr, uintC b_len);
2675 // Auxiliary function for approximately computing 1/sqrt(x)
2676 // using Newton iteration.
2677 extern void cl_UDS_recipsqrt (const uintD* a_MSDptr, uintC a_len,
2678 uintD* b_MSDptr, uintC b_len);
2682 #endif /* _CL_DS_H */