]> www.ginac.de Git - cln.git/blob - src/base/digitseq/cl_DS.h
* Removed internal gmp/ directory and other traces of it like $GMP_INCLUDES.
[cln.git] / src / base / digitseq / cl_DS.h
1 // Digit sequence arithmetic
2
3 #ifndef _CL_DS_H
4 #define _CL_DS_H
5
6 #include "cl_types.h"
7 #include "cl_gmpconfig.h"
8 #include "cl_D.h"
9 #include "cl_DS_endian.h"
10 #include "cl_alloca.h"
11
12 // Digit Sequence (DS)
13 // a memory range with n digits (n an uintC),
14 // between two pointers MSDptr and LSDptr.
15 #if CL_DS_BIG_ENDIAN_P
16 //  MSDptr                  LSDptr = MSDptr+n
17 // | MSD ............. LSD |
18 // [short: MSDptr/n/LSDptr ]
19 // In C: uintD* MSDptr, uintC len, MSDptr[0] ... MSDptr[len-1] are the digits.
20 #else
21 //  LSDptr                  MSDptr = LSDptr+n
22 // | LSD ............. MSD |
23 // In C: uintD* LSDptr, uintC len, LSDptr[0] ... LSDptr[len-1] are the digits.
24 #endif
25 // If n = 0, this represents the number 0.
26 // If n > 0, the most significant bit (i.e. bit (intDsize-1) of
27 //           MSDptr[CL_DS_BIG_ENDIAN_P?0:-1]) is the sign bit. If the sign
28 //           bit were repeated infinitely often, one would get an
29 //           "infinite bit sequence".
30 //
31 // A Normalised Digit Sequence (NDS) is one for which the MSD is necessary,
32 // i.e. n = 0 or (n > 0 and the most significant intDsize+1 bits are not
33 // all the same).
34
35 // Unsigned Digit Sequence (UDS)
36 // like DS, but without sign.
37 //
38 // Normalized Unsigned Digit Sequence (NUDS):
39 // an UDS for which the MSD is necessary, i.e. n = 0 or
40 // (n > 0 and the most significant intDsize bits are not all zero).
41
42 // For the construction of constant DS, using "digit_header":
43 #define D1(byte0)  (uintD)(byte0)
44 #define D2(byte0,byte1)  (((uintD)(byte0)<<8)|(uintD)(byte1))
45 #define D4(byte0,byte1,byte2,byte3)  (((uintD)(byte0)<<24)|((uintD)(byte1)<<16)|((uintD)(byte2)<<8)|((uintD)(byte3)))
46 #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)))
47
48 struct DS {
49         uintD* MSDptr;
50         unsigned int len;
51         uintD* LSDptr;
52 };
53
54 // Endianness independent access of digit sequences:
55 // mspref(MSDptr,i)    access a most significant digit
56 // lspref(LSDptr,i)    access a least significant digit
57 // msshrink(MSDptr)    shrinks the DS by throwing away the MSD
58 // msprefnext(MSDptr)  combines mspref(MSDptr,0) and msshrink(MSDptr)
59 // lsshrink(LSDptr)    shrinks the DS by throwing away the LSD
60 // lsprefnext(LSDptr)  combines lspref(LSDptr,0) and lsshrink(LSDptr)
61 // mspop     pointer operator corresponding to msshrink, arg is widened to an uintP
62 // lspop     pointer operator corresponding to lsshrink, arg is widened to an uintP
63 #if CL_DS_BIG_ENDIAN_P
64   #define mspref(p,i)  (p)[i]
65   #define lspref(p,i)  (p)[-(uintP)(i)-1]
66   #define msshrink(p)  (p)++
67   #define msprefnext(p)  (*(p)++)
68   #define lsshrink(p)  (p)--
69   #define lsprefnext(p)  (*--(p))
70   #define mspop  +
71   #define lspop  -
72 #else
73   #define mspref(p,i)  (p)[-(uintP)(i)-1]
74   #define lspref(p,i)  (p)[i]
75   #define msshrink(p)  (p)--
76   #define msprefnext(p)  (*--(p))
77   #define lsshrink(p)  (p)++
78   #define lsprefnext(p)  (*(p)++)
79   #define mspop  -
80   #define lspop  +
81 #endif
82
83 // Endianness independent macros for turning an array into a digit sequence.
84 // arrayMSDptr(array,length)  returns the MSDptr of array[0..length-1]
85 // arrayLSDptr(array,length)  returns the LSDptr of array[0..length-1]
86 #if CL_DS_BIG_ENDIAN_P
87   #define arrayMSDptr(array,length)  &(array)[0]
88   #define arrayLSDptr(array,length)  &(array)[length]
89 #else
90   #define arrayMSDptr(array,length)  &(array)[length]
91   #define arrayLSDptr(array,length)  &(array)[0]
92 #endif
93 #define arrayLSref(array,length,i)  lspref(arrayLSDptr(array,length),i)
94
95
96 // These functions on digit sequences are either inline C++ functions
97 // or external assembler functions (see files cl_asm_*).
98
99
100 // See which functions are defined as external functions.
101 #include "cl_asm.h"
102
103
104 // Declare the external functions.
105
106 extern "C" {
107
108 #ifdef COPY_LOOPS
109
110 extern uintD* copy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count);
111
112 extern uintD* copy_loop_down (const uintD* sourceptr, uintD* destptr, uintC count);
113
114 #endif
115
116 #ifdef FILL_LOOPS
117
118 extern uintD* fill_loop_up (uintD* destptr, uintC count, uintD filler);
119
120 extern uintD* fill_loop_down (uintD* destptr, uintC count, uintD filler);
121
122 #endif
123
124 #ifdef CLEAR_LOOPS
125
126 extern uintD* clear_loop_up (uintD* destptr, uintC count);
127
128 extern uintD* clear_loop_down (uintD* destptr, uintC count);
129
130 #endif
131
132 #ifdef TEST_LOOPS
133
134 extern cl_boolean test_loop_up (const uintD* ptr, uintC count);
135
136 extern cl_boolean test_loop_down (const uintD* ptr, uintC count);
137
138 #endif
139
140 #if CL_DS_BIG_ENDIAN_P
141
142 #ifdef LOG_LOOPS
143
144 extern void or_loop_up (uintD* xptr, const uintD* yptr, uintC count);
145
146 extern void xor_loop_up (uintD* xptr, const uintD* yptr, uintC count);
147
148 extern void and_loop_up (uintD* xptr, const uintD* yptr, uintC count);
149
150 extern void eqv_loop_up (uintD* xptr, const uintD* yptr, uintC count);
151
152 extern void nand_loop_up (uintD* xptr, const uintD* yptr, uintC count);
153
154 extern void nor_loop_up (uintD* xptr, const uintD* yptr, uintC count);
155
156 extern void andc2_loop_up (uintD* xptr, const uintD* yptr, uintC count);
157
158 extern void orc2_loop_up (uintD* xptr, const uintD* yptr, uintC count);
159
160 extern void not_loop_up (uintD* xptr, uintC count);
161
162 #endif
163
164 #ifdef TEST_LOOPS
165
166 extern cl_boolean and_test_loop_up (const uintD* xptr, const uintD* yptr, uintC count);
167
168 extern cl_signean compare_loop_up (const uintD* xptr, const uintD* yptr, uintC count);
169
170 #endif
171
172 #ifdef ADDSUB_LOOPS
173
174 extern uintD add_loop_down (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count);
175
176 extern uintD addto_loop_down (const uintD* sourceptr, uintD* destptr, uintC count);
177
178 extern uintD inc_loop_down (uintD* ptr, uintC count);
179
180 extern uintD sub_loop_down (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count);
181
182 extern uintD subx_loop_down (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count, uintD carry);
183
184 extern uintD subfrom_loop_down (const uintD* sourceptr, uintD* destptr, uintC count);
185
186 extern uintD dec_loop_down (uintD* ptr, uintC count);
187
188 extern uintD neg_loop_down (uintD* ptr, uintC count);
189
190 #endif
191
192 #ifdef SHIFT_LOOPS
193
194 extern uintD shift1left_loop_down (uintD* ptr, uintC count);
195
196 extern uintD shiftleft_loop_down (uintD* ptr, uintC count, uintC i, uintD carry);
197
198 extern uintD shiftleftcopy_loop_down (const uintD* sourceptr, uintD* destptr, uintC count, uintC i);
199
200 extern uintD shift1right_loop_up (uintD* ptr, uintC count, uintD carry);
201
202 extern uintD shiftright_loop_up (uintD* ptr, uintC count, uintC i);
203
204 extern uintD shiftrightsigned_loop_up (uintD* ptr, uintC count, uintC i);
205
206 extern uintD shiftrightcopy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry);
207
208 #endif
209
210 #ifdef MUL_LOOPS
211
212 extern uintD mulusmall_loop_down (uintD digit, uintD* ptr, uintC len, uintD newdigit);
213
214 extern void mulu_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len);
215
216 extern uintD muluadd_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len);
217
218 extern uintD mulusub_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len);
219
220 #endif
221
222 #ifdef DIV_LOOPS
223
224 extern uintD divu_loop_up (uintD digit, uintD* ptr, uintC len);
225
226 extern uintD divucopy_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len);
227
228 #endif
229
230 #else // !CL_DS_BIG_ENDIAN_P
231
232 #ifdef LOG_LOOPS
233
234 extern void or_loop_down (uintD* xptr, const uintD* yptr, uintC count);
235
236 extern void xor_loop_down (uintD* xptr, const uintD* yptr, uintC count);
237
238 extern void and_loop_down (uintD* xptr, const uintD* yptr, uintC count);
239
240 extern void eqv_loop_down (uintD* xptr, const uintD* yptr, uintC count);
241
242 extern void nand_loop_down (uintD* xptr, const uintD* yptr, uintC count);
243
244 extern void nor_loop_down (uintD* xptr, const uintD* yptr, uintC count);
245
246 extern void andc2_loop_down (uintD* xptr, const uintD* yptr, uintC count);
247
248 extern void orc2_loop_down (uintD* xptr, const uintD* yptr, uintC count);
249
250 extern void not_loop_down (uintD* xptr, uintC count);
251
252 #endif
253
254 #ifdef TEST_LOOPS
255
256 extern cl_boolean and_test_loop_down (const uintD* xptr, const uintD* yptr, uintC count);
257
258 extern cl_signean compare_loop_down (const uintD* xptr, const uintD* yptr, uintC count);
259
260 #endif
261
262 #ifdef ADDSUB_LOOPS
263
264 extern uintD add_loop_up (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count);
265
266 extern uintD addto_loop_up (const uintD* sourceptr, uintD* destptr, uintC count);
267
268 extern uintD inc_loop_up (uintD* ptr, uintC count);
269
270 extern uintD sub_loop_up (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count);
271
272 extern uintD subx_loop_up (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count, uintD carry);
273
274 extern uintD subfrom_loop_up (const uintD* sourceptr, uintD* destptr, uintC count);
275
276 extern uintD dec_loop_up (uintD* ptr, uintC count);
277
278 extern uintD neg_loop_up (uintD* ptr, uintC count);
279
280 #endif
281
282 #ifdef SHIFT_LOOPS
283
284 extern uintD shift1left_loop_up (uintD* ptr, uintC count);
285
286 extern uintD shiftleft_loop_up (uintD* ptr, uintC count, uintC i, uintD carry);
287
288 extern uintD shiftleftcopy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count, uintC i);
289
290 extern uintD shift1right_loop_down (uintD* ptr, uintC count, uintD carry);
291
292 extern uintD shiftright_loop_down (uintD* ptr, uintC count, uintC i);
293
294 extern uintD shiftrightsigned_loop_down (uintD* ptr, uintC count, uintC i);
295
296 extern uintD shiftrightcopy_loop_down (const uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry);
297
298 #endif
299
300 #ifdef MUL_LOOPS
301
302 extern uintD mulusmall_loop_up (uintD digit, uintD* ptr, uintC len, uintD newdigit);
303
304 extern void mulu_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len);
305
306 extern uintD muluadd_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len);
307
308 extern uintD mulusub_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len);
309
310 #endif
311
312 #ifdef DIV_LOOPS
313
314 extern uintD divu_loop_down (uintD digit, uintD* ptr, uintC len);
315
316 extern uintD divucopy_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len);
317
318 #endif
319
320 #endif // !CL_DS_BIG_ENDIAN_P
321
322 // Independently of CL_DS_BIG_ENDIAN_P:
323
324 #ifdef TEST_LOOPS
325
326 extern cl_signean compare_loop_up (const uintD* xptr, const uintD* yptr, uintC count);
327
328 #endif
329
330 #ifdef LOG_LOOPS
331
332 extern void xor_loop_up (uintD* xptr, const uintD* yptr, uintC count);
333
334 #endif
335
336 #ifdef SHIFT_LOOPS
337
338 extern uintD shiftleftcopy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count, uintC i);
339
340 extern void shiftxor_loop_up (uintD* xptr, const uintD* yptr, uintC count, uintC i);
341
342 #endif
343
344 } // "C" extern.
345
346
347 #if defined(CL_USE_GMP)
348
349 // Supersede the functions by wrappers around calls to gmp mpn,
350 // for those functions where gmp is believed to be faster.
351
352 #include <gmp.h>
353
354 #if 0 // not worth it, since gmp's mpn_cmp is not optimized
355 inline cl_signean compare_loop_down (const uintD* xptr, const uintD* yptr, uintC count)
356 {
357         return mpn_cmp(xptr-count,yptr-count,count);
358 }
359 #endif
360
361 inline uintD add_loop_up (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count)
362 {
363         if (count == 0)
364                 return 0;
365         return mpn_add_n(destptr,sourceptr1,sourceptr2,count);
366 }
367
368 inline uintD addto_loop_up (const uintD* sourceptr, uintD* destptr, uintC count)
369 {
370         if (count == 0)
371                 return 0;
372         return mpn_add_n(destptr,destptr,sourceptr,count);
373 }
374
375 inline uintD inc_loop_up (uintD* ptr, uintC count)
376 {
377         if (count == 0)
378                 return 1;
379         return mpn_add_1(ptr,ptr,count,1);
380 }
381
382 inline uintD sub_loop_up (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count)
383 {
384         if (count == 0)
385                 return 0;
386         return mpn_sub_n(destptr,sourceptr1,sourceptr2,count);
387 }
388
389 inline uintD subx_loop_up (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count, uintD carry)
390 {
391         if (count == 0)
392                 return carry;
393         var uintD res_carry = mpn_sub_n(destptr,sourceptr1,sourceptr2,count);
394         if (carry)
395                 res_carry |= mpn_sub_1(destptr,destptr,count,1);
396         return res_carry;
397 }
398
399 inline uintD subfrom_loop_up (const uintD* sourceptr, uintD* destptr, uintC count)
400 {
401         if (count == 0)
402                 return 0;
403         return mpn_sub_n(destptr,destptr,sourceptr,count);
404 }
405
406 inline uintD dec_loop_up (uintD* ptr, uintC count)
407 {
408         if (count == 0)
409                 return (uintD)(-1);
410         return -mpn_sub_1(ptr,ptr,count,1);
411 }
412
413 #if !defined(ADDSUB_LOOPS)
414 // No equivalent for this in gmp. But we need this function, so write it in C.
415 inline uintD neg_loop_up (uintD* ptr, uintC count)
416 {
417         // erstes Digit /=0 suchen:
418         until (count==0) { if (!(*ptr == 0)) goto L1; ptr++; count--; }
419         return 0;
420     L1: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
421         *ptr = - *ptr; count--; // 1 Digit negieren
422         dotimesC(count,count, { ptr++; *ptr = ~ *ptr; } ); // alle anderen Digits invertieren
423         return (uintD)(-1);
424 }
425 #endif
426
427 #define ADDSUB_LOOPS
428
429 inline uintD shift1left_loop_up (uintD* ptr, uintC count)
430 {
431         if (count == 0)
432                 return 0;
433         return mpn_lshift(ptr,ptr,count,1);
434 }
435
436 inline uintD shiftleft_loop_up (uintD* ptr, uintC count, uintC i, uintD carry)
437 {
438         if (count == 0)
439                 return carry;
440         var uintD res_carry = mpn_lshift(ptr,ptr,count,i);
441         ptr[0] |= carry;
442         return res_carry;
443 }
444
445 inline uintD shiftleftcopy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count, uintC i)
446 {
447         if (count == 0)
448                 return 0;
449         return mpn_lshift(destptr,sourceptr,count,i);
450 }
451
452 inline uintD shift1right_loop_down (uintD* ptr, uintC count, uintD carry)
453 {
454         if (count == 0)
455                 return carry;
456         var uintD res_carry = mpn_rshift(ptr-count,ptr-count,count,1);
457         if (carry)
458                 ptr[-1] |= bit(intDsize-1);
459         return res_carry;
460 }
461
462 inline uintD shiftright_loop_down (uintD* ptr, uintC count, uintC i)
463 {
464         if (count == 0)
465                 return 0;
466         return mpn_rshift(ptr-count,ptr-count,count,i);
467 }
468
469 inline uintD shiftrightsigned_loop_down (uintD* ptr, uintC count, uintC i)
470 {
471         var uintD carry = ((sintD)ptr[-1] >> (intDsize-1)) << (intDsize-i);
472         var uintD res_carry = mpn_rshift(ptr-count,ptr-count,count,i);
473         ptr[-1] |= carry;
474         return res_carry;
475 }
476
477 inline uintD shiftrightcopy_loop_down (const uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry)
478 {
479         carry = carry << (intDsize-i);
480         if (count == 0)
481                 return carry;
482         var uintD res_carry = mpn_rshift(destptr-count,sourceptr-count,count,i);
483         destptr[-1] |= carry;
484         return res_carry;
485 }
486
487 #define SHIFT_LOOPS
488
489 inline uintD mulusmall_loop_up (uintD digit, uintD* ptr, uintC len, uintD newdigit)
490 {
491         if (len == 0)
492                 return newdigit;
493         var uintD res_carry = mpn_mul_1(ptr,ptr,len,digit);
494         res_carry += mpn_add_1(ptr,ptr,len,newdigit);
495         return res_carry;
496 }
497
498 inline void mulu_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
499 {
500         destptr[len] = (len==0 ? 0 : mpn_mul_1(destptr,sourceptr,len,digit));
501 }
502
503 inline uintD muluadd_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
504 {
505         if (len == 0)
506                 return 0;
507         return mpn_addmul_1(destptr,sourceptr,len,digit);
508 }
509
510 inline uintD mulusub_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
511 {
512         if (len == 0)
513                 return 0;
514         return mpn_submul_1(destptr,sourceptr,len,digit);
515 }
516
517 #define MUL_LOOPS
518
519 inline uintD divu_loop_up (uintD digit, uintD* ptr, uintC len)
520 {
521         return mpn_divrem_1(ptr,0,ptr,len,digit);
522 }
523
524 inline uintD divu_loop_down (uintD digit, uintD* ptr, uintC len)
525 {
526         return mpn_divrem_1(ptr-len,0,ptr-len,len,digit);
527 }
528
529 inline uintD divucopy_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
530 {
531         return mpn_divrem_1(destptr,0,sourceptr,len,digit);
532 }
533
534 inline uintD divucopy_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
535 {
536         return mpn_divrem_1(destptr-len,0,sourceptr-len,len,digit);
537 }
538
539 #define DIV_LOOPS
540
541 #endif // defined(CL_USE_GMP)
542
543
544 // Define the missing functions as inline functions.
545
546 #ifndef COPY_LOOPS
547
548 // Kopierschleife:
549 // destptr = copy_loop_up(sourceptr,destptr,count);
550 // kopiert count (uintC>=0) Digits aufwärts von sourceptr nach destptr
551 // und liefert das neue destptr.
552   inline uintD* copy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count)
553     { dotimesC(count,count, { *destptr++ = *sourceptr++; } );
554       return destptr;
555     }
556
557 // Kopierschleife:
558 // destptr = copy_loop_down(sourceptr,destptr,count);
559 // kopiert count (uintC>=0) Digits abwärts von sourceptr nach destptr
560 // und liefert das neue destptr.
561   inline uintD* copy_loop_down (const uintD* sourceptr, uintD* destptr, uintC count)
562     { dotimesC(count,count, { *--destptr = *--sourceptr; } );
563       return destptr;
564     }
565
566 #endif
567
568 #ifndef FILL_LOOPS
569
570 // Füllschleife:
571 // destptr = fill_loop_up(destptr,count,filler);
572 // kopiert count (uintC>=0) mal das Digit filler aufwärts nach destptr
573 // und liefert das neue destptr.
574   inline uintD* fill_loop_up (uintD* destptr, uintC count, uintD filler)
575     { dotimesC(count,count, { *destptr++ = filler; } );
576       return destptr;
577     }
578
579 // Füllschleife:
580 // destptr = fill_loop_down(destptr,count,filler);
581 // kopiert count (uintC>=0) mal das Digit filler abwärts nach destptr
582 // und liefert das neue destptr.
583   inline uintD* fill_loop_down (uintD* destptr, uintC count, uintD filler)
584     { dotimesC(count,count, { *--destptr = filler; } );
585       return destptr;
586     }
587
588 #endif
589
590 #ifndef CLEAR_LOOPS
591
592 // Lösch-Schleife:
593 // destptr = clear_loop_up(destptr,count);
594 // löscht count (uintC>=0) Digits aufwärts ab destptr
595 // und liefert das neue destptr.
596   inline uintD* clear_loop_up (uintD* destptr, uintC count)
597     { dotimesC(count,count, { *destptr++ = 0; } );
598       return destptr;
599     }
600
601 // Lösch-Schleife:
602 // destptr = clear_loop_down(destptr,count);
603 // löscht count (uintC>=0) Digits abwärts ab destptr
604 // und liefert das neue destptr.
605   inline uintD* clear_loop_down (uintD* destptr, uintC count)
606     { dotimesC(count,count, { *--destptr = 0; } );
607       return destptr;
608     }
609
610 #endif
611
612 #ifndef TEST_LOOPS
613
614 // Test-Schleife:
615 // test_loop_up(ptr,count)
616 // testet count (uintC>=0) Digits aufwärts ab ptr, ob darunter eines /=0 ist.
617 // Ergebnis /=0, falls ja.
618   inline cl_boolean test_loop_up (const uintD* ptr, uintC count)
619     { dotimesC(count,count, { if (*ptr++) return cl_true; } );
620       return cl_false;
621     }
622
623 // Test-Schleife:
624 // test_loop_down(ptr,count)
625 // testet count (uintC>=0) Digits abwärts ab ptr, ob darunter eines /=0 ist.
626 // Ergebnis /=0, falls ja.
627   inline cl_boolean test_loop_down (const uintD* ptr, uintC count)
628     { dotimesC(count,count, { if (*--ptr) return cl_true; } );
629       return cl_false;
630     }
631
632 #endif
633
634 #if CL_DS_BIG_ENDIAN_P
635
636 #ifndef LOG_LOOPS
637
638 // OR-Schleife:
639 // or_loop_up(xptr,yptr,count);
640 // verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr
641 // mit Ziel ab xptr durch OR.
642   inline void or_loop_up (uintD* xptr, const uintD* yptr, uintC count)
643     { dotimesC(count,count, { *xptr++ |= *yptr++; } ); }
644
645 // XOR-Schleife:
646 // xor_loop_up(xptr,yptr,count);
647 // verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr
648 // mit Ziel ab xptr durch XOR.
649   inline void xor_loop_up (uintD* xptr, const uintD* yptr, uintC count)
650     { dotimesC(count,count, { *xptr++ ^= *yptr++; } ); }
651
652 // AND-Schleife:
653 // and_loop_up(xptr,yptr,count);
654 // verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr
655 // mit Ziel ab xptr durch AND.
656   inline void and_loop_up (uintD* xptr, const uintD* yptr, uintC count)
657     { dotimesC(count,count, { *xptr++ &= *yptr++; } ); }
658
659 // EQV-Schleife:
660 // eqv_loop_up(xptr,yptr,count);
661 // verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr
662 // mit Ziel ab xptr durch EQV (NOT XOR).
663   inline void eqv_loop_up (uintD* xptr, const uintD* yptr, uintC count)
664     { dotimesC(count,count,
665         {var uintD temp = ~ (*xptr ^ *yptr++); *xptr++ = temp; }
666         );
667     }
668
669 // NAND-Schleife:
670 // nand_loop_up(xptr,yptr,count);
671 // verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr
672 // mit Ziel ab xptr durch NAND (NOT AND).
673   inline void nand_loop_up (uintD* xptr, const uintD* yptr, uintC count)
674     { dotimesC(count,count,
675         {var uintD temp = ~ (*xptr & *yptr++); *xptr++ = temp; }
676         );
677     }
678
679 // NOR-Schleife:
680 // nor_loop_up(xptr,yptr,count);
681 // verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr
682 // mit Ziel ab xptr durch NOR (NOT OR).
683   inline void nor_loop_up (uintD* xptr, const uintD* yptr, uintC count)
684     { dotimesC(count,count,
685         {var uintD temp = ~ (*xptr | *yptr++); *xptr++ = temp; }
686         );
687     }
688
689 // ANDC2-Schleife:
690 // andc2_loop_up(xptr,yptr,count);
691 // verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr
692 // mit Ziel ab xptr durch ANDC2 (AND NOT).
693   inline void andc2_loop_up (uintD* xptr, const uintD* yptr, uintC count)
694     { dotimesC(count,count, { *xptr++ &= ~(*yptr++); } ); }
695
696 // ORC2-Schleife:
697 // orc2_loop_up(xptr,yptr,count);
698 // verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr
699 // mit Ziel ab xptr durch ORC2 (OR NOT).
700   inline void orc2_loop_up (uintD* xptr, const uintD* yptr, uintC count)
701     { dotimesC(count,count, { *xptr++ |= ~(*yptr++); } ); }
702
703 // NOT-Schleife:
704 // not_loop_up(xptr,count);
705 // verknüpft count (uintC>0) Digits aufwärts ab xptr mit Ziel ab xptr
706 // durch NOT.
707   inline void not_loop_up (uintD* xptr, uintC count)
708     { dotimespC(count,count,
709         {var uintD temp = ~ (*xptr); *xptr++ = temp; }
710         );
711     }
712
713 #endif
714
715 #ifndef TEST_LOOPS
716
717 // AND-Test-Schleife:
718 // and_test_loop_up(xptr,yptr,count);
719 // verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr durch AND
720 // und testet, ob sich dabei ein Digit /=0 ergibt. Ergebnis cl_true, falls ja.
721   inline cl_boolean and_test_loop_up (const uintD* xptr, const uintD* yptr, uintC count)
722     { dotimesC(count,count, { if (*xptr++ & *yptr++) return cl_true; } );
723       return cl_false;
724     }
725
726 // Vergleichsschleife:
727 // result = compare_loop_up(xptr,yptr,count);
728 // vergleicht nacheinander xptr[0] mit yptr[0], xptr[1] mit yptr[1], usw.,
729 // insgesamt count Digits, und liefert 0 falls alle gleich sind,
730 // +1 falls zuerst ein xptr[i]>yptr[i] ist,
731 // -1 falls zuerst ein xptr[i]<yptr[i] ist.
732   inline cl_signean compare_loop_up (const uintD* xptr, const uintD* yptr, uintC count)
733     { dotimesC(count,count,
734         { if (!(*xptr++ == *yptr++))
735             // verschiedene Digits gefunden
736             return (*--xptr > *--yptr ? signean_plus : signean_minus);
737         });
738       return signean_null; // alle Digits gleich
739     }
740
741 #endif
742
743 #ifndef ADDSUB_LOOPS
744
745 // Additionsschleife:
746 // übertrag = add_loop_down(sourceptr1,sourceptr2,destptr,count);
747 // addiert count (uintC>=0) Digits abwärts von sourceptr1, von sourceptr2
748 // abwärts nach destptr und liefert den Übertrag (0 oder /=0, was 1 bedeutet).
749   inline uintD add_loop_down (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count)
750     { var uintD source1;
751       var uintD source2;
752       if (!(count==0))
753       do { source1 = *--sourceptr1;
754            source2 = *--sourceptr2;
755            *--destptr = source1 + source2;
756            if (source1 > (uintD)(~source2)) goto carry_1;
757            carry_0:
758            count--;
759          }
760          until (count==0);
761       return 0;
762       do { source1 = *--sourceptr1;
763            source2 = *--sourceptr2;
764            *--destptr = source1 + source2 + 1;
765            if (source1 < (uintD)(~source2)) goto carry_0;
766            carry_1:
767            count--;
768          }
769          until (count==0);
770       return 1;
771     }
772
773 // Additionsschleife:
774 // übertrag = addto_loop_down(sourceptr,destptr,count);
775 // addiert count (uintC>=0) Digits abwärts von sourceptr, von destptr
776 // abwärts nach destptr und liefert den Übertrag (0 oder /=0, was 1 bedeutet).
777   inline uintD addto_loop_down (const uintD* sourceptr, uintD* destptr, uintC count)
778     { var uintD source1;
779       var uintD source2;
780       if (!(count==0))
781       do { source1 = *--sourceptr;
782            source2 = *--destptr;
783            *destptr = source1 + source2;
784            if (source1 > (uintD)(~source2)) goto carry_1;
785            carry_0:
786            count--;
787          }
788          until (count==0);
789       return 0;
790       do { source1 = *--sourceptr;
791            source2 = *--destptr;
792            *destptr = source1 + source2 + 1;
793            if (source1 < (uintD)(~source2)) goto carry_0;
794            carry_1:
795            count--;
796          }
797          until (count==0);
798       return 1;
799     }
800
801 // Incrementierschleife:
802 // übertrag = inc_loop_down(ptr,count);
803 // incrementiert count (uintC>=0) Digits abwärts von ptr, so lange bis kein
804 // Übertrag mehr auftritt und liefert den Übertrag (0 oder /=0, was 1 bedeutet).
805   inline uintD inc_loop_down (uintD* ptr, uintC count)
806     { dotimesC(count,count,
807         { if (!( ++(*--ptr) == 0 )) return 0; } // kein weiterer Übertrag
808         );
809       return 1; // weiterer Übertrag
810     }
811
812 // Subtraktionsschleife:
813 // übertrag = sub_loop_down(sourceptr1,sourceptr2,destptr,count);
814 // subtrahiert count (uintC>=0) Digits abwärts von sourceptr1, von sourceptr2
815 // abwärts nach destptr und liefert den Übertrag (0 oder /=0, was -1 bedeutet).
816   inline uintD sub_loop_down (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count)
817     { var uintD source1;
818       var uintD source2;
819       if (!(count==0))
820       do { source1 = *--sourceptr1;
821            source2 = *--sourceptr2;
822            *--destptr = source1 - source2;
823            if (source1 < source2) goto carry_1;
824            carry_0:
825            count--;
826          }
827          until (count==0);
828       return 0;
829       do { source1 = *--sourceptr1;
830            source2 = *--sourceptr2;
831            *--destptr = source1 - source2 - 1;
832            if (source1 > source2) goto carry_0;
833            carry_1:
834            count--;
835          }
836          until (count==0);
837       return (uintD)(-1);
838     }
839
840 // Subtraktionsschleife:
841 // übertrag = subx_loop_down(sourceptr1,sourceptr2,destptr,count,carry);
842 // subtrahiert count (uintC>=0) Digits abwärts von sourceptr1 und addiert
843 // einen Carry (0 oder -1), von sourceptr2 abwärts nach destptr und
844 // liefert den Übertrag (0 oder /=0, was -1 bedeutet).
845   inline uintD subx_loop_down (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count, uintD carry)
846     { var uintD source1;
847       var uintD source2;
848       if (carry==0)
849         { if (!(count==0))
850             do { source1 = *--sourceptr1;
851                  source2 = *--sourceptr2;
852                  *--destptr = source1 - source2;
853                  if (source1 < source2) goto carry_1;
854                  carry_0:
855                  count--;
856                }
857                until (count==0);
858           return 0;
859         }
860         else
861         { if (!(count==0))
862             do { source1 = *--sourceptr1;
863                  source2 = *--sourceptr2;
864                  *--destptr = source1 - source2 - 1;
865                  if (source1 > source2) goto carry_0;
866                  carry_1:
867                  count--;
868                }
869                until (count==0);
870           return (uintD)(-1);
871     }   }
872
873 // Subtraktionsschleife:
874 // übertrag = subfrom_loop_down(sourceptr,destptr,count);
875 // subtrahiert count (uintC>=0) Digits abwärts von sourceptr, von destptr
876 // abwärts nach destptr (dest := dest - source)
877 // und liefert den Übertrag (0 oder /=0, was -1 bedeutet).
878   inline uintD subfrom_loop_down (const uintD* sourceptr, uintD* destptr, uintC count)
879     { var uintD source1;
880       var uintD source2;
881       if (!(count==0))
882       do { source1 = *--destptr;
883            source2 = *--sourceptr;
884            *destptr = source1 - source2;
885            if (source1 < source2) goto carry_1;
886            carry_0:
887            count--;
888          }
889          until (count==0);
890       return 0;
891       do { source1 = *--destptr;
892            source2 = *--sourceptr;
893            *destptr = source1 - source2 - 1;
894            if (source1 > source2) goto carry_0;
895            carry_1:
896            count--;
897          }
898          until (count==0);
899       return (uintD)(-1);
900     }
901
902 // Decrementierschleife:
903 // übertrag = dec_loop_down(ptr,count);
904 // decrementiert count (uintC>=0) Digits abwärts von ptr, so lange bis kein
905 // Übertrag mehr auftritt und liefert den Übertrag (0 oder -1).
906   inline uintD dec_loop_down (uintD* ptr, uintC count)
907     { dotimesC(count,count,
908         { if (!( (*--ptr)-- == 0 )) return 0; } // kein weiterer Übertrag
909         );
910       return (uintD)(-1); // weiterer Übertrag
911     }
912
913 // Negierschleife:
914 // übertrag = neg_loop_down(ptr,count);
915 // negiert count (uintC>=0) Digits abwärts von ptr,
916 // und liefert den Übertrag (0 oder -1).
917   inline uintD neg_loop_down (uintD* ptr, uintC count)
918     { // erstes Digit /=0 suchen:
919       until (count==0) { if (!(*--ptr == 0)) goto L1; count--; }
920       return 0;
921       L1: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
922       *ptr = - *ptr; count--; // 1 Digit negieren
923       dotimesC(count,count, { --ptr; *ptr = ~ *ptr; } ); // alle anderen Digits invertieren
924       return (uintD)(-1);
925     }
926
927 #endif
928
929 #ifndef SHIFT_LOOPS
930
931 // Schiebeschleife um 1 Bit nach links:
932 // übertrag = shift1left_loop_down(ptr,count);
933 // schiebt count (uintC>=0) Digits abwärts von ptr um 1 Bit nach links,
934 // und liefert den Übertrag (0 oder /=0, was 1 bedeutet).
935   #if HAVE_DD
936   inline uintD shift1left_loop_down (uintD* ptr, uintC count)
937     { var uintDD accu = 0;
938       dotimesC(count,count,
939         { accu = ((uintDD)(*--ptr)<<1)+accu; *ptr = lowD(accu);
940           accu = (uintDD)(highD(accu));
941         });
942       return (uintD)accu;
943     }
944   #else
945   inline uintD shift1left_loop_down (uintD* ptr, uintC count)
946     { var uintD carry = 0;
947       dotimesC(count,count,
948         { var uintD accu = *--ptr;
949           *ptr = (accu<<1) | carry;
950           carry = accu>>(intDsize-1);
951         });
952       return carry;
953     }
954   #endif
955
956 // Schiebeschleife um i Bits nach links:
957 // übertrag = shiftleft_loop_down(ptr,count,i,übertrag_init);
958 // schiebt count (uintC>=0) Digits abwärts von ptr um i Bits (0<i<intDsize)
959 // nach links, schiebt dabei die i Bits aus übertrag_init rechts rein,
960 // und liefert den Übertrag (was links rauskommt, >=0, <2^i).
961   #if HAVE_DD
962   inline uintD shiftleft_loop_down (uintD* ptr, uintC count, uintC i, uintD carry)
963     { var uintDD accu = (uintDD)carry;
964       dotimesC(count,count,
965         { accu = ((uintDD)(*--ptr)<<i)+accu; *ptr = lowD(accu);
966           accu = (uintDD)(highD(accu));
967         });
968       return (uintD)accu;
969     }
970   #else
971   inline uintD shiftleft_loop_down (uintD* ptr, uintC count, uintC i, uintD carry)
972     { var uintC j = intDsize-i;
973       dotimesC(count,count,
974         { var uintD accu = *--ptr;
975           *ptr = (accu<<i) | carry;
976           carry = accu>>j;
977         });
978       return carry;
979     }
980   #endif
981
982 // Schiebe- und Kopierschleife um i Bits nach links:
983 // übertrag = shiftleftcopy_loop_down(sourceptr,destptr,count,i);
984 // kopiert count (uintC>=0) Digits abwärts von sourceptr nach destptr
985 // und schiebt sie dabei um i Bits (0<i<intDsize) nach links,
986 // wobei ganz rechts mit i Nullbits aufgefüllt wird,
987 // und liefert den Übertrag (was links rauskommt, >=0, <2^i).
988   #if HAVE_DD
989   inline uintD shiftleftcopy_loop_down (const uintD* sourceptr, uintD* destptr, uintC count, uintC i)
990     { var uintDD accu = 0;
991       dotimesC(count,count,
992         { accu = ((uintDD)(*--sourceptr)<<i)+accu; *--destptr = lowD(accu);
993           accu = (uintDD)(highD(accu));
994         });
995       return (uintD)accu;
996     }
997   #else
998   inline uintD shiftleftcopy_loop_down (const uintD* sourceptr, uintD* destptr, uintC count, uintC i)
999     { var uintC j = intDsize-i;
1000       var uintD carry = 0;
1001       dotimesC(count,count,
1002         { var uintD accu = *--sourceptr;
1003           *--destptr = (accu<<i) | carry;
1004           carry = accu>>j;
1005         });
1006       return carry;
1007     }
1008   #endif
1009
1010 // Schiebeschleife um 1 Bit nach rechts:
1011 // übertrag = shift1right_loop_up(ptr,count,übertrag_init);
1012 // schiebt count (uintC>=0) Digits aufwärts von ptr um 1 Bit nach rechts,
1013 // wobei links das Bit übertrag_init (sollte =0 oder =-1 sein) hineingeschoben
1014 // wird, und liefert den Übertrag (0 oder /=0, was 1 bedeutet).
1015   #if HAVE_DD
1016   inline uintD shift1right_loop_up (uintD* ptr, uintC count, uintD carry)
1017     { var uintDD accu = (sintDD)(sintD)carry & ((uintDD)1 << (2*intDsize-1)); // 0 oder bit(2*intDsize-1)
1018       dotimesC(count,count,
1019         { accu = (highlowDD_0(*ptr)>>1)+accu; *ptr++ = highD(accu);
1020           accu = highlowDD_0(lowD(accu));
1021         });
1022       return highD(accu);
1023     }
1024   #else
1025   inline uintD shift1right_loop_up (uintD* ptr, uintC count, uintD carry)
1026     { carry = carry << (intDsize-1); // carry zu einem einzigen Bit machen
1027       dotimesC(count,count,
1028         { var uintD accu = *ptr;
1029           *ptr++ = (accu >> 1) | carry;
1030           carry = accu << (intDsize-1);
1031         });
1032       return carry;
1033     }
1034   #endif
1035
1036 // Schiebeschleife um i Bits nach rechts:
1037 // übertrag = shiftright_loop_up(ptr,count,i);
1038 // schiebt count (uintC>=0) Digits aufwärts von ptr um i Bits (0<i<intDsize)
1039 // nach rechts, wobei links Nullen eingeschoben werden,
1040 // und liefert den Übertrag (was rechts rauskommt, als Bits intDsize-1..intDsize-i).
1041   #if HAVE_DD
1042   inline uintD shiftright_loop_up (uintD* ptr, uintC count, uintC i)
1043     { var uintDD accu = 0;
1044       dotimesC(count,count,
1045         { // Die oberen i Bits von (uintD)accu bilden hier den Übertrag.
1046           accu = highlowDD_0(lowD(accu));
1047           // Die oberen i Bits von (uintDD)accu bilden hier den Übertrag.
1048           accu = (highlowDD_0(*ptr)>>i)+accu; *ptr++ = highD(accu);
1049         });
1050       return lowD(accu);
1051     }
1052   #else
1053   inline uintD shiftright_loop_up (uintD* ptr, uintC count, uintC i)
1054     { var uintC j = intDsize-i;
1055       var uintD carry = 0;
1056       dotimesC(count,count,
1057         { var uintD accu = *ptr;
1058           *ptr++ = (accu >> i) | carry;
1059           carry = accu << j;
1060         });
1061       return carry;
1062     }
1063   #endif
1064
1065 // Schiebeschleife um i Bits nach rechts:
1066 // übertrag = shiftrightsigned_loop_up(ptr,count,i);
1067 // schiebt count (uintC>0) Digits aufwärts von ptr um i Bits (0<i<intDsize)
1068 // nach rechts, wobei links das MSBit ver-i-facht wird,
1069 // und liefert den Übertrag (was rechts rauskommt, als Bits intDsize-1..intDsize-i).
1070   #if HAVE_DD
1071   inline uintD shiftrightsigned_loop_up (uintD* ptr, uintC count, uintC i)
1072     { var uintDD accu = // Übertrag mit i Vorzeichenbits initialisieren
1073                            highlowDD_0(sign_of_sintD((sintD)(*ptr)))>>i;
1074       dotimespC(count,count,
1075         { // Die oberen i Bits von (uintD)accu bilden hier den Übertrag.
1076           accu = highlowDD_0(lowD(accu));
1077           // Die oberen i Bits von (uintDD)accu bilden hier den Übertrag.
1078           accu = (highlowDD_0(*ptr)>>i)+accu; *ptr++ = highD(accu);
1079         });
1080       return lowD(accu);
1081     }
1082   #else
1083   inline uintD shiftrightsigned_loop_up (uintD* ptr, uintC count, uintC i)
1084     { var uintC j = intDsize-i;
1085       var uintD carry;
1086       { var uintD accu = *ptr;
1087         *ptr++ = (sintD)accu >> i;
1088         carry = accu << j;
1089         count--;
1090       }
1091       dotimesC(count,count,
1092         { var uintD accu = *ptr;
1093           *ptr++ = (accu >> i) | carry;
1094           carry = accu << j;
1095         });
1096       return carry;
1097     }
1098   #endif
1099
1100 // Schiebe- und Kopier-Schleife um i Bits nach rechts:
1101 // übertrag = shiftrightcopy_loop_up(sourceptr,destptr,count,i,carry);
1102 // kopiert count (uintC>=0) Digits aufwärts von sourceptr nach destptr
1103 // und schiebt sie dabei um i Bits (0<i<intDsize) nach rechts, wobei carry
1104 // (sozusagen als sourceptr[-1]) die i Bits ganz links bestimmt,
1105 // und liefert den Übertrag (was rechts rauskommt, als Bits intDsize-1..intDsize-i).
1106   #if HAVE_DD
1107   inline uintD shiftrightcopy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry)
1108     { var uintDD accu = // Übertrag mit carry initialisieren
1109                            highlowDD_0(carry)>>i;
1110       dotimesC(count,count,
1111         { // Die oberen i Bits von (uintD)accu bilden hier den Übertrag.
1112           accu = highlowDD_0(lowD(accu));
1113           // Die oberen i Bits von (uintDD)accu bilden hier den Übertrag.
1114           accu = (highlowDD_0(*sourceptr++)>>i)+accu; *destptr++ = highD(accu);
1115         });
1116       return lowD(accu);
1117     }
1118   #else
1119   inline uintD shiftrightcopy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry)
1120     { var uintC j = intDsize-i;
1121       carry = carry << j;
1122       dotimesC(count,count,
1123         { var uintD accu = *sourceptr++;
1124           *destptr++ = (accu >> i) | carry;
1125           carry = accu << j;
1126         });
1127       return carry;
1128     }
1129   #endif
1130
1131 #endif
1132
1133 #ifndef MUL_LOOPS
1134
1135 // Multiplikations-Einfachschleife:
1136 // Multipliziert eine UDS mit einem kleinen Digit und addiert ein kleines Digit.
1137 // mulusmall_loop_down(digit,ptr,len,newdigit)
1138 // multipliziert die UDS  ptr[-len..-1]  mit digit (>=2, <=36),
1139 // addiert dabei newdigit (>=0, <digit) zur letzten Ziffer,
1140 // und liefert den Carry (>=0, <digit).
1141   #if HAVE_DD
1142   inline uintD mulusmall_loop_down (uintD digit, uintD* ptr, uintC len, uintD newdigit)
1143     { var uintDD carry = newdigit;
1144       dotimesC(len,len,
1145         { // Hier ist 0 <= carry < digit.
1146           carry = carry + muluD(digit,*--ptr);
1147           // Hier ist 0 <= carry < 2^intDsize*digit.
1148           *ptr = lowD(carry);
1149           carry = (uintDD)highD(carry); // carry := floor(carry/2^intDsize) < digit
1150         });
1151       return lowD(carry);
1152     }
1153   #else
1154   inline uintD mulusmall_loop_down (uintD digit, uintD* ptr, uintC len, uintD newdigit)
1155     { var uintD carry = newdigit;
1156       dotimesC(len,len,
1157         { // Hier ist 0 <= carry < digit.
1158           var uintD hi;
1159           var uintD lo;
1160           muluD(digit,*--ptr,hi=,lo=);
1161           // Hier ist 0 <= 2^intDsize*hi + lo + carry < 2^intDsize*digit.
1162           lo += carry; if (lo < carry) { hi += 1; }
1163           *ptr = lo;
1164           carry = hi;
1165         });
1166       return carry;
1167     }
1168   #endif
1169
1170 // Multiplikations-Einfachschleife:
1171 // Multipliziert eine UDS mit einem Digit und legt das Ergebnis in einer
1172 // zweiten UDS ab.
1173 // mulu_loop_down(digit,sourceptr,destptr,len);
1174 // multipliziert die UDS  sourceptr[-len..-1]  (len>0)
1175 // mit dem einzelnen  digit
1176 // und legt das Ergebnis in der UDS  destptr[-len-1..-1]  ab.
1177   #if HAVE_DD
1178   inline void mulu_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
1179     { var uintDD carry = 0;
1180       dotimespC(len,len,
1181         { // Hier ist carry=digit=0 oder 0 <= carry < digit.
1182           carry = carry + muluD(digit,*--sourceptr);
1183           // Hier ist carry=digit=0 oder 0 <= carry < 2^intDsize*digit.
1184           *--destptr = lowD(carry);
1185           carry = (uintDD)highD(carry); // carry := floor(carry/2^intDsize) < digit
1186         });
1187       *--destptr = lowD(carry);
1188     }
1189   #else
1190   inline void mulu_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
1191     { var uintD carry = 0;
1192       dotimespC(len,len,
1193         { // Hier ist carry=digit=0 oder 0 <= carry < digit.
1194           var uintD hi;
1195           var uintD lo;
1196           muluD(digit,*--sourceptr,hi=,lo=);
1197           // Hier ist 0 <= 2^intDsize*hi + lo + carry < 2^intDsize*digit oder hi=lo=carry=digit=0.
1198           lo += carry; if (lo < carry) { hi += 1; }
1199           *--destptr = lo;
1200           carry = hi;
1201         });
1202       *--destptr = carry;
1203     }
1204   #endif
1205
1206 // Multiplikations-Einfachschleife mit Akkumulation:
1207 // Multipliziert eine UDS mit einem Digit und addiert das Ergebnis zu einer
1208 // zweiten UDS auf.
1209 // muluadd_loop_down(digit,sourceptr,destptr,len);
1210 // multipliziert die UDS  sourceptr[-len..-1]  (len>0)
1211 // mit dem einzelnen digit, legt das Ergebnis in der UDS  destptr[-len..-1]
1212 // ab und liefert den weiteren Übertrag.
1213   #if HAVE_DD
1214   inline uintD muluadd_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
1215     { var uintDD carry = 0;
1216       if (!(digit==0))
1217         { dotimespC(len,len,
1218             { // Hier ist 0 <= carry <= digit.
1219               carry = carry + muluD(digit,*--sourceptr) + (uintDD)*--destptr;
1220               // Hier ist 0 <= carry <= 2^intDsize*digit + 2^intDsize-1.
1221               *destptr = lowD(carry);
1222               carry = (uintDD)highD(carry); // carry := floor(carry/2^intDsize) <= digit
1223             });
1224         }
1225       return lowD(carry);
1226     }
1227   #else
1228   inline uintD muluadd_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
1229     { var uintD carry = 0;
1230       if (!(digit==0))
1231         { dotimespC(len,len,
1232             { // Hier ist 0 <= carry <= digit.
1233               var uintD hi;
1234               var uintD lo;
1235               muluD(digit,*--sourceptr,hi=,lo=);
1236               // Hier ist 0 <= 2^intDsize*hi + lo + carry + *--destptr <= 2^intDsize*digit+2^intDsize-1.
1237               lo += carry; if (lo < carry) { hi += 1; }
1238               carry = *--destptr;
1239               lo += carry; if (lo < carry) { hi += 1; }
1240               *destptr = lo;
1241               carry = hi;
1242             });
1243         }
1244       return carry;
1245     }
1246   #endif
1247
1248 // Multiplikations-Einfachschleife mit Diminution:
1249 // Multipliziert eine UDS mit einem Digit und subtrahiert das Ergebnis von
1250 // einer zweiten UDS.
1251 // mulusub_loop_down(digit,sourceptr,destptr,len);
1252 // multipliziert die UDS  sourceptr[-len..-1]  (len>0)  mit dem einzelnen
1253 // digit, subtrahiert das Ergebnis von der UDS  destptr[-len..-1]  und liefert
1254 // den weiteren Übertrag (>=0, evtl. von destptr[-len-1] zu subtrahieren).
1255   #if HAVE_DD
1256   inline uintD mulusub_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
1257     { var uintDD carry = 0;
1258       if (!(digit==0))
1259         { dotimespC(len,len,
1260             { // Hier ist 0 <= carry <= digit.
1261               carry = carry + muluD(digit,*--sourceptr) + (uintD)(~(*--destptr));
1262               // Hier ist 0 <= carry <= 2^intDsize*digit + 2^intDsize-1.
1263               *destptr = ~lowD(carry);
1264               carry = (uintDD)highD(carry); // carry := floor(carry/2^intDsize) <= digit
1265               // Hier ist 0 <= carry <= digit.
1266             });
1267           return lowD(carry);
1268         }
1269         else
1270         return 0; // nichts zu subtrahieren -> kein Übertrag
1271     }
1272   #else
1273   inline uintD mulusub_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
1274     { var uintD carry = 0;
1275       if (!(digit==0))
1276         { dotimespC(len,len,
1277             { // Hier ist 0 <= carry <= digit.
1278               var uintD hi;
1279               var uintD lo;
1280               muluD(digit,*--sourceptr,hi=,lo=);
1281               // Hier ist 0 <= 2^intDsize*hi + lo + carry + ~(*--destptr) <= 2^intDsize*digit+2^intDsize-1.
1282               lo += carry; if (lo < carry) { hi += 1; }
1283               carry = *--destptr;
1284               *destptr = carry - lo; if (carry < lo) { hi += 1; }
1285               carry = hi;
1286             });
1287           return carry;
1288         }
1289         else
1290         return 0; // nichts zu subtrahieren -> kein Übertrag
1291     }
1292   #endif
1293
1294 #endif
1295
1296 #ifndef DIV_LOOPS
1297
1298 // Divisions-Einfachschleife:
1299 // Dividiert eine UDS durch ein Digit.
1300 // divu_loop_up(digit,ptr,len)
1301 // dividiert die UDS  ptr[0..len-1] durch digit,
1302 // legt das Ergebnis in derselben UDS ab, und liefert den Rest (>=0, <digit).
1303   #if HAVE_DD
1304   inline uintD divu_loop_up (uintD digit, uintD* ptr, uintC len)
1305     { var uintD rest = 0;
1306       dotimesC(len,len,
1307         { divuD(highlowDD(rest,*ptr),digit,*ptr =, rest =); ptr++; }
1308         );
1309       return rest;
1310     }
1311   #else
1312   inline uintD divu_loop_up (uintD digit, uintD* ptr, uintC len)
1313     { var uintD rest = 0;
1314       dotimesC(len,len,
1315         { divuD(rest,*ptr,digit,*ptr =, rest =); ptr++; }
1316         );
1317       return rest;
1318     }
1319   #endif
1320
1321 // Divisions-Einfachschleife:
1322 // Dividiert eine UDS durch ein Digit und legt das Ergebnis in einer
1323 // zweiten UDS ab.
1324 // divucopy_loop_up(digit,sourceptr,destptr,len)
1325 // dividiert die UDS  sourceptr[0..len-1]  durch digit,
1326 // legt das Ergebnis in der UDS  destptr[0..len-1]  ab,
1327 // und liefert den Rest (>=0, <digit).
1328   #if HAVE_DD
1329   inline uintD divucopy_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
1330     { var uintD rest = 0;
1331       dotimesC(len,len,
1332         { divuD(highlowDD(rest,*sourceptr++),digit,*destptr++ =, rest =); }
1333         );
1334       return rest;
1335     }
1336   #else
1337   inline uintD divucopy_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
1338     { var uintD rest = 0;
1339       dotimesC(len,len,
1340         { divuD(rest,*sourceptr++,digit,*destptr++ =, rest =); }
1341         );
1342       return rest;
1343     }
1344   #endif
1345
1346 #endif
1347
1348 #else // !CL_DS_BIG_ENDIAN_P
1349
1350 #ifndef LOG_LOOPS
1351
1352 // OR-Schleife:
1353 // or_loop_down(xptr,yptr,count);
1354 // verknüpft count (uintC>=0) Digits abwärts ab xptr und ab yptr
1355 // mit Ziel ab xptr durch OR.
1356   inline void or_loop_down (uintD* xptr, const uintD* yptr, uintC count)
1357     { dotimesC(count,count, { *--xptr |= *--yptr; } ); }
1358
1359 // XOR-Schleife:
1360 // xor_loop_down(xptr,yptr,count);
1361 // verknüpft count (uintC>=0) Digits abwärts ab xptr und ab yptr
1362 // mit Ziel ab xptr durch XOR.
1363   inline void xor_loop_down (uintD* xptr, const uintD* yptr, uintC count)
1364     { dotimesC(count,count, { *--xptr ^= *--yptr; } ); }
1365
1366 // AND-Schleife:
1367 // and_loop_down(xptr,yptr,count);
1368 // verknüpft count (uintC>=0) Digits abwärts ab xptr und ab yptr
1369 // mit Ziel ab xptr durch AND.
1370   inline void and_loop_down (uintD* xptr, const uintD* yptr, uintC count)
1371     { dotimesC(count,count, { *--xptr &= *--yptr; } ); }
1372
1373 // EQV-Schleife:
1374 // eqv_loop_down(xptr,yptr,count);
1375 // verknüpft count (uintC>=0) Digits abwärts ab xptr und ab yptr
1376 // mit Ziel ab xptr durch EQV (NOT XOR).
1377   inline void eqv_loop_down (uintD* xptr, const uintD* yptr, uintC count)
1378     { dotimesC(count,count,
1379         {var uintD temp = ~ (*--xptr ^ *--yptr); *xptr = temp; }
1380         );
1381     }
1382
1383 // NAND-Schleife:
1384 // nand_loop_down(xptr,yptr,count);
1385 // verknüpft count (uintC>=0) Digits abwärts ab xptr und ab yptr
1386 // mit Ziel ab xptr durch NAND (NOT AND).
1387   inline void nand_loop_down (uintD* xptr, const uintD* yptr, uintC count)
1388     { dotimesC(count,count,
1389         {var uintD temp = ~ (*--xptr & *--yptr); *xptr = temp; }
1390         );
1391     }
1392
1393 // NOR-Schleife:
1394 // nor_loop_down(xptr,yptr,count);
1395 // verknüpft count (uintC>=0) Digits abwärts ab xptr und ab yptr
1396 // mit Ziel ab xptr durch NOR (NOT OR).
1397   inline void nor_loop_down (uintD* xptr, const uintD* yptr, uintC count)
1398     { dotimesC(count,count,
1399         {var uintD temp = ~ (*--xptr | *--yptr); *xptr = temp; }
1400         );
1401     }
1402
1403 // ANDC2-Schleife:
1404 // andc2_loop_down(xptr,yptr,count);
1405 // verknüpft count (uintC>=0) Digits abwärts ab xptr und ab yptr
1406 // mit Ziel ab xptr durch ANDC2 (AND NOT).
1407   inline void andc2_loop_down (uintD* xptr, const uintD* yptr, uintC count)
1408     { dotimesC(count,count, { *--xptr &= ~(*--yptr); } ); }
1409
1410 // ORC2-Schleife:
1411 // orc2_loop_down(xptr,yptr,count);
1412 // verknüpft count (uintC>=0) Digits abwärts ab xptr und ab yptr
1413 // mit Ziel ab xptr durch ORC2 (OR NOT).
1414   inline void orc2_loop_down (uintD* xptr, const uintD* yptr, uintC count)
1415     { dotimesC(count,count, { *--xptr |= ~(*--yptr); } ); }
1416
1417 // NOT-Schleife:
1418 // not_loop_down(xptr,count);
1419 // verknüpft count (uintC>0) Digits abwärts ab xptr mit Ziel ab xptr
1420 // durch NOT.
1421   inline void not_loop_down (uintD* xptr, uintC count)
1422     { dotimespC(count,count,
1423         {var uintD temp = ~ (*--xptr); *xptr = temp; }
1424         );
1425     }
1426
1427 #endif
1428
1429 #ifndef TEST_LOOPS
1430
1431 // AND-Test-Schleife:
1432 // and_test_loop_down(xptr,yptr,count);
1433 // verknüpft count (uintC>=0) Digits abwärts ab xptr und ab yptr durch AND
1434 // und testet, ob sich dabei ein Digit /=0 ergibt. Ergebnis cl_true, falls ja.
1435   inline cl_boolean and_test_loop_down (const uintD* xptr, const uintD* yptr, uintC count)
1436     { dotimesC(count,count, { if (*--xptr & *--yptr) return cl_true; } );
1437       return cl_false;
1438     }
1439
1440 // Vergleichsschleife:
1441 // result = compare_loop_down(xptr,yptr,count);
1442 // vergleicht nacheinander xptr[-1] mit yptr[-1], xptr[-2] mit yptr[-2], usw.,
1443 // insgesamt count Digits, und liefert 0 falls alle gleich sind,
1444 // +1 falls zuerst ein xptr[i]>yptr[i] ist,
1445 // -1 falls zuerst ein xptr[i]<yptr[i] ist.
1446   inline cl_signean compare_loop_down (const uintD* xptr, const uintD* yptr, uintC count)
1447     { dotimesC(count,count,
1448         { if (!(*--xptr == *--yptr))
1449             // verschiedene Digits gefunden
1450             return (*xptr > *yptr ? signean_plus : signean_minus);
1451         });
1452       return signean_null; // alle Digits gleich
1453     }
1454
1455 #endif
1456
1457 #ifndef ADDSUB_LOOPS
1458
1459 // Additionsschleife:
1460 // übertrag = add_loop_up(sourceptr1,sourceptr2,destptr,count);
1461 // addiert count (uintC>=0) Digits aufwärts von sourceptr1, von sourceptr2
1462 // aufwärts nach destptr und liefert den Übertrag (0 oder /=0, was 1 bedeutet).
1463   inline uintD add_loop_up (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count)
1464     { var uintD source1;
1465       var uintD source2;
1466       if (!(count==0))
1467       do { source1 = *sourceptr1++;
1468            source2 = *sourceptr2++;
1469            *destptr++ = source1 + source2;
1470            if (source1 > (uintD)(~source2)) goto carry_1;
1471            carry_0:
1472            count--;
1473          }
1474          until (count==0);
1475       return 0;
1476       do { source1 = *sourceptr1++;
1477            source2 = *sourceptr2++;
1478            *destptr++ = source1 + source2 + 1;
1479            if (source1 < (uintD)(~source2)) goto carry_0;
1480            carry_1:
1481            count--;
1482          }
1483          until (count==0);
1484       return 1;
1485     }
1486
1487 // Additionsschleife:
1488 // übertrag = addto_loop_up(sourceptr,destptr,count);
1489 // addiert count (uintC>=0) Digits aufwärts von sourceptr, von destptr
1490 // aufwärts nach destptr und liefert den Übertrag (0 oder /=0, was 1 bedeutet).
1491   inline uintD addto_loop_up (const uintD* sourceptr, uintD* destptr, uintC count)
1492     { var uintD source1;
1493       var uintD source2;
1494       if (!(count==0))
1495       do { source1 = *sourceptr++;
1496            source2 = *destptr;
1497            *destptr++ = source1 + source2;
1498            if (source1 > (uintD)(~source2)) goto carry_1;
1499            carry_0:
1500            count--;
1501          }
1502          until (count==0);
1503       return 0;
1504       do { source1 = *sourceptr++;
1505            source2 = *destptr;
1506            *destptr++ = source1 + source2 + 1;
1507            if (source1 < (uintD)(~source2)) goto carry_0;
1508            carry_1:
1509            count--;
1510          }
1511          until (count==0);
1512       return 1;
1513     }
1514
1515 // Incrementierschleife:
1516 // übertrag = inc_loop_up(ptr,count);
1517 // incrementiert count (uintC>=0) Digits aufwärts von ptr, so lange bis kein
1518 // Übertrag mehr auftritt und liefert den Übertrag (0 oder /=0, was 1 bedeutet).
1519   inline uintD inc_loop_up (uintD* ptr, uintC count)
1520     { dotimesC(count,count,
1521         { if (!( ++(*ptr++) == 0 )) return 0; } // kein weiterer Übertrag
1522         );
1523       return 1; // weiterer Übertrag
1524     }
1525
1526 // Subtraktionsschleife:
1527 // übertrag = sub_loop_up(sourceptr1,sourceptr2,destptr,count);
1528 // subtrahiert count (uintC>=0) Digits aufwärts von sourceptr1, von sourceptr2
1529 // aufwärts nach destptr und liefert den Übertrag (0 oder /=0, was -1 bedeutet).
1530   inline uintD sub_loop_up (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count)
1531     { var uintD source1;
1532       var uintD source2;
1533       if (!(count==0))
1534       do { source1 = *sourceptr1++;
1535            source2 = *sourceptr2++;
1536            *destptr++ = source1 - source2;
1537            if (source1 < source2) goto carry_1;
1538            carry_0:
1539            count--;
1540          }
1541          until (count==0);
1542       return 0;
1543       do { source1 = *sourceptr1++;
1544            source2 = *sourceptr2++;
1545            *destptr++ = source1 - source2 - 1;
1546            if (source1 > source2) goto carry_0;
1547            carry_1:
1548            count--;
1549          }
1550          until (count==0);
1551       return (uintD)(-1);
1552     }
1553
1554 // Subtraktionsschleife:
1555 // übertrag = subx_loop_up(sourceptr1,sourceptr2,destptr,count,carry);
1556 // subtrahiert count (uintC>=0) Digits aufwärts von sourceptr1 und addiert
1557 // einen Carry (0 oder -1), von sourceptr2 aufwärts nach destptr und
1558 // liefert den Übertrag (0 oder /=0, was -1 bedeutet).
1559   inline uintD subx_loop_up (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count, uintD carry)
1560     { var uintD source1;
1561       var uintD source2;
1562       if (carry==0)
1563         { if (!(count==0))
1564             do { source1 = *sourceptr1++;
1565                  source2 = *sourceptr2++;
1566                  *destptr++ = source1 - source2;
1567                  if (source1 < source2) goto carry_1;
1568                  carry_0:
1569                  count--;
1570                }
1571                until (count==0);
1572           return 0;
1573         }
1574         else
1575         { if (!(count==0))
1576             do { source1 = *sourceptr1++;
1577                  source2 = *sourceptr2++;
1578                  *destptr++ = source1 - source2 - 1;
1579                  if (source1 > source2) goto carry_0;
1580                  carry_1:
1581                  count--;
1582                }
1583                until (count==0);
1584           return (uintD)(-1);
1585     }   }
1586
1587 // Subtraktionsschleife:
1588 // übertrag = subfrom_loop_up(sourceptr,destptr,count);
1589 // subtrahiert count (uintC>=0) Digits aufwärts von sourceptr, von destptr
1590 // aufwärts nach destptr (dest := dest - source)
1591 // und liefert den Übertrag (0 oder /=0, was -1 bedeutet).
1592   inline uintD subfrom_loop_up (const uintD* sourceptr, uintD* destptr, uintC count)
1593     { var uintD source1;
1594       var uintD source2;
1595       if (!(count==0))
1596       do { source1 = *destptr;
1597            source2 = *sourceptr++;
1598            *destptr++ = source1 - source2;
1599            if (source1 < source2) goto carry_1;
1600            carry_0:
1601            count--;
1602          }
1603          until (count==0);
1604       return 0;
1605       do { source1 = *destptr;
1606            source2 = *sourceptr++;
1607            *destptr++ = source1 - source2 - 1;
1608            if (source1 > source2) goto carry_0;
1609            carry_1:
1610            count--;
1611          }
1612          until (count==0);
1613       return (uintD)(-1);
1614     }
1615
1616 // Decrementierschleife:
1617 // übertrag = dec_loop_up(ptr,count);
1618 // decrementiert count (uintC>=0) Digits aufwärts von ptr, so lange bis kein
1619 // Übertrag mehr auftritt und liefert den Übertrag (0 oder -1).
1620   inline uintD dec_loop_up (uintD* ptr, uintC count)
1621     { dotimesC(count,count,
1622         { if (!( (*ptr++)-- == 0 )) return 0; } // kein weiterer Übertrag
1623         );
1624       return (uintD)(-1); // weiterer Übertrag
1625     }
1626
1627 // Negierschleife:
1628 // übertrag = neg_loop_up(ptr,count);
1629 // negiert count (uintC>=0) Digits aufwärts von ptr,
1630 // und liefert den Übertrag (0 oder -1).
1631   inline uintD neg_loop_up (uintD* ptr, uintC count)
1632     { // erstes Digit /=0 suchen:
1633       until (count==0) { if (!(*ptr == 0)) goto L1; ptr++; count--; }
1634       return 0;
1635       L1: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
1636       *ptr = - *ptr; count--; // 1 Digit negieren
1637       dotimesC(count,count, { ptr++; *ptr = ~ *ptr; } ); // alle anderen Digits invertieren
1638       return (uintD)(-1);
1639     }
1640
1641 #endif
1642
1643 #ifndef SHIFT_LOOPS
1644
1645 // Schiebeschleife um 1 Bit nach links:
1646 // übertrag = shift1left_loop_up(ptr,count);
1647 // schiebt count (uintC>=0) Digits aufwärts von ptr um 1 Bit nach links,
1648 // und liefert den Übertrag (0 oder /=0, was 1 bedeutet).
1649   #if HAVE_DD
1650   inline uintD shift1left_loop_up (uintD* ptr, uintC count)
1651     { var uintDD accu = 0;
1652       dotimesC(count,count,
1653         { accu = ((uintDD)(*ptr)<<1)+accu; *ptr++ = lowD(accu);
1654           accu = (uintDD)(highD(accu));
1655         });
1656       return (uintD)accu;
1657     }
1658   #else
1659   inline uintD shift1left_loop_up (uintD* ptr, uintC count)
1660     { var uintD carry = 0;
1661       dotimesC(count,count,
1662         { var uintD accu = *ptr;
1663           *ptr++ = (accu<<1) | carry;
1664           carry = accu>>(intDsize-1);
1665         });
1666       return carry;
1667     }
1668   #endif
1669
1670 // Schiebeschleife um i Bits nach links:
1671 // übertrag = shiftleft_loop_up(ptr,count,i,übertrag_init);
1672 // schiebt count (uintC>=0) Digits aufwärts von ptr um i Bits (0<i<intDsize)
1673 // nach links, schiebt dabei die i Bits aus übertrag_init rechts rein,
1674 // und liefert den Übertrag (was links rauskommt, >=0, <2^i).
1675   #if HAVE_DD
1676   inline uintD shiftleft_loop_up (uintD* ptr, uintC count, uintC i, uintD carry)
1677     { var uintDD accu = (uintDD)carry;
1678       dotimesC(count,count,
1679         { accu = ((uintDD)(*ptr)<<i)+accu; *ptr++ = lowD(accu);
1680           accu = (uintDD)(highD(accu));
1681         });
1682       return (uintD)accu;
1683     }
1684   #else
1685   inline uintD shiftleft_loop_up (uintD* ptr, uintC count, uintC i, uintD carry)
1686     { var uintC j = intDsize-i;
1687       dotimesC(count,count,
1688         { var uintD accu = *ptr;
1689           *ptr++ = (accu<<i) | carry;
1690           carry = accu>>j;
1691         });
1692       return carry;
1693     }
1694   #endif
1695
1696 // Schiebe- und Kopierschleife um i Bits nach links:
1697 // übertrag = shiftleftcopy_loop_up(sourceptr,destptr,count,i);
1698 // kopiert count (uintC>=0) Digits aufwärts von sourceptr nach destptr
1699 // und schiebt sie dabei um i Bits (0<i<intDsize) nach links,
1700 // wobei ganz rechts mit i Nullbits aufgefüllt wird,
1701 // und liefert den Übertrag (was links rauskommt, >=0, <2^i).
1702   #if HAVE_DD
1703   inline uintD shiftleftcopy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count, uintC i)
1704     { var uintDD accu = 0;
1705       dotimesC(count,count,
1706         { accu = ((uintDD)(*sourceptr++)<<i)+accu; *destptr++ = lowD(accu);
1707           accu = (uintDD)(highD(accu));
1708         });
1709       return (uintD)accu;
1710     }
1711   #else
1712   inline uintD shiftleftcopy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count, uintC i)
1713     { var uintC j = intDsize-i;
1714       var uintD carry = 0;
1715       dotimesC(count,count,
1716         { var uintD accu = *sourceptr++;
1717           *destptr++ = (accu<<i) | carry;
1718           carry = accu>>j;
1719         });
1720       return carry;
1721     }
1722   #endif
1723
1724 // Schiebeschleife um 1 Bit nach rechts:
1725 // übertrag = shift1right_loop_down(ptr,count,übertrag_init);
1726 // schiebt count (uintC>=0) Digits abwärts von ptr um 1 Bit nach rechts,
1727 // wobei links das Bit übertrag_init (sollte =0 oder =-1 sein) hineingeschoben
1728 // wird, und liefert den Übertrag (0 oder /=0, was 1 bedeutet).
1729   #if HAVE_DD
1730   inline uintD shift1right_loop_down (uintD* ptr, uintC count, uintD carry)
1731     { var uintDD accu = (sintDD)(sintD)carry & ((uintDD)1 << (2*intDsize-1)); // 0 oder bit(2*intDsize-1)
1732       dotimesC(count,count,
1733         { accu = (highlowDD_0(*--ptr)>>1)+accu; *ptr = highD(accu);
1734           accu = highlowDD_0(lowD(accu));
1735         });
1736       return highD(accu);
1737     }
1738   #else
1739   inline uintD shift1right_loop_down (uintD* ptr, uintC count, uintD carry)
1740     { carry = carry << (intDsize-1); // carry zu einem einzigen Bit machen
1741       dotimesC(count,count,
1742         { var uintD accu = *--ptr;
1743           *ptr = (accu >> 1) | carry;
1744           carry = accu << (intDsize-1);
1745         });
1746       return carry;
1747     }
1748   #endif
1749
1750 // Schiebeschleife um i Bits nach rechts:
1751 // übertrag = shiftright_loop_down(ptr,count,i);
1752 // schiebt count (uintC>=0) Digits abwärts von ptr um i Bits (0<i<intDsize)
1753 // nach rechts, wobei links Nullen eingeschoben werden,
1754 // und liefert den Übertrag (was rechts rauskommt, als Bits intDsize-1..intDsize-i).
1755   #if HAVE_DD
1756   inline uintD shiftright_loop_down (uintD* ptr, uintC count, uintC i)
1757     { var uintDD accu = 0;
1758       dotimesC(count,count,
1759         { // Die oberen i Bits von (uintD)accu bilden hier den Übertrag.
1760           accu = highlowDD_0(lowD(accu));
1761           // Die oberen i Bits von (uintDD)accu bilden hier den Übertrag.
1762           accu = (highlowDD_0(*--ptr)>>i)+accu; *ptr = highD(accu);
1763         });
1764       return lowD(accu);
1765     }
1766   #else
1767   inline uintD shiftright_loop_down (uintD* ptr, uintC count, uintC i)
1768     { var uintC j = intDsize-i;
1769       var uintD carry = 0;
1770       dotimesC(count,count,
1771         { var uintD accu = *--ptr;
1772           *ptr = (accu >> i) | carry;
1773           carry = accu << j;
1774         });
1775       return carry;
1776     }
1777   #endif
1778
1779 // Schiebeschleife um i Bits nach rechts:
1780 // übertrag = shiftrightsigned_loop_down(ptr,count,i);
1781 // schiebt count (uintC>0) Digits abwärts von ptr um i Bits (0<i<intDsize)
1782 // nach rechts, wobei links das MSBit ver-i-facht wird,
1783 // und liefert den Übertrag (was rechts rauskommt, als Bits intDsize-1..intDsize-i).
1784   #if HAVE_DD
1785   inline uintD shiftrightsigned_loop_down (uintD* ptr, uintC count, uintC i)
1786     { var uintDD accu = // Übertrag mit i Vorzeichenbits initialisieren
1787                            highlowDD_0(sign_of_sintD((sintD)(ptr[-1])))>>i;
1788       dotimespC(count,count,
1789         { // Die oberen i Bits von (uintD)accu bilden hier den Übertrag.
1790           accu = highlowDD_0(lowD(accu));
1791           // Die oberen i Bits von (uintDD)accu bilden hier den Übertrag.
1792           accu = (highlowDD_0(*--ptr)>>i)+accu; *ptr = highD(accu);
1793         });
1794       return lowD(accu);
1795     }
1796   #else
1797   inline uintD shiftrightsigned_loop_down (uintD* ptr, uintC count, uintC i)
1798     { var uintC j = intDsize-i;
1799       var uintD carry;
1800       { var uintD accu = *--ptr;
1801         *ptr = (sintD)accu >> i;
1802         carry = accu << j;
1803         count--;
1804       }
1805       dotimesC(count,count,
1806         { var uintD accu = *--ptr;
1807           *ptr = (accu >> i) | carry;
1808           carry = accu << j;
1809         });
1810       return carry;
1811     }
1812   #endif
1813
1814 // Schiebe- und Kopier-Schleife um i Bits nach rechts:
1815 // übertrag = shiftrightcopy_loop_down(sourceptr,destptr,count,i,carry);
1816 // kopiert count (uintC>=0) Digits abwärts von sourceptr nach destptr
1817 // und schiebt sie dabei um i Bits (0<i<intDsize) nach rechts, wobei carry
1818 // (sozusagen als sourceptr[0]) die i Bits ganz links bestimmt,
1819 // und liefert den Übertrag (was rechts rauskommt, als Bits intDsize-1..intDsize-i).
1820   #if HAVE_DD
1821   inline uintD shiftrightcopy_loop_down (const uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry)
1822     { var uintDD accu = // Übertrag mit carry initialisieren
1823                            highlowDD_0(carry)>>i;
1824       dotimesC(count,count,
1825         { // Die oberen i Bits von (uintD)accu bilden hier den Übertrag.
1826           accu = highlowDD_0(lowD(accu));
1827           // Die oberen i Bits von (uintDD)accu bilden hier den Übertrag.
1828           accu = (highlowDD_0(*--sourceptr)>>i)+accu; *--destptr = highD(accu);
1829         });
1830       return lowD(accu);
1831     }
1832   #else
1833   inline uintD shiftrightcopy_loop_down (const uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry)
1834     { var uintC j = intDsize-i;
1835       carry = carry << j;
1836       dotimesC(count,count,
1837         { var uintD accu = *--sourceptr;
1838           *--destptr = (accu >> i) | carry;
1839           carry = accu << j;
1840         });
1841       return carry;
1842     }
1843   #endif
1844
1845 #endif
1846
1847 #ifndef MUL_LOOPS
1848
1849 // Multiplikations-Einfachschleife:
1850 // Multipliziert eine UDS mit einem kleinen Digit und addiert ein kleines Digit.
1851 // mulusmall_loop_up(digit,ptr,len,newdigit)
1852 // multipliziert die UDS  ptr[0..len-1]  mit digit (>=2, <=36),
1853 // addiert dabei newdigit (>=0, <digit) zur letzten Ziffer,
1854 // und liefert den Carry (>=0, <digit).
1855   #if HAVE_DD
1856   inline uintD mulusmall_loop_up (uintD digit, uintD* ptr, uintC len, uintD newdigit)
1857     { var uintDD carry = newdigit;
1858       dotimesC(len,len,
1859         { // Hier ist 0 <= carry < digit.
1860           carry = carry + muluD(digit,*ptr);
1861           // Hier ist 0 <= carry < 2^intDsize*digit.
1862           *ptr++ = lowD(carry);
1863           carry = (uintDD)highD(carry); // carry := floor(carry/2^intDsize) < digit
1864         });
1865       return lowD(carry);
1866     }
1867   #else
1868   inline uintD mulusmall_loop_up (uintD digit, uintD* ptr, uintC len, uintD newdigit)
1869     { var uintD carry = newdigit;
1870       dotimesC(len,len,
1871         { // Hier ist 0 <= carry < digit.
1872           var uintD hi;
1873           var uintD lo;
1874           muluD(digit,*ptr,hi=,lo=);
1875           // Hier ist 0 <= 2^intDsize*hi + lo + carry < 2^intDsize*digit.
1876           lo += carry; if (lo < carry) { hi += 1; }
1877           *ptr++ = lo;
1878           carry = hi;
1879         });
1880       return carry;
1881     }
1882   #endif
1883
1884 // Multiplikations-Einfachschleife:
1885 // Multipliziert eine UDS mit einem Digit und legt das Ergebnis in einer
1886 // zweiten UDS ab.
1887 // mulu_loop_up(digit,sourceptr,destptr,len);
1888 // multipliziert die UDS  sourceptr[0..len-1]  (len>0)
1889 // mit dem einzelnen  digit
1890 // und legt das Ergebnis in der UDS  destptr[0..len]  ab.
1891   #if HAVE_DD
1892   inline void mulu_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
1893     { var uintDD carry = 0;
1894       dotimespC(len,len,
1895         { // Hier ist carry=digit=0 oder 0 <= carry < digit.
1896           carry = carry + muluD(digit,*sourceptr++);
1897           // Hier ist carry=digit=0 oder 0 <= carry < 2^intDsize*digit.
1898           *destptr++ = lowD(carry);
1899           carry = (uintDD)highD(carry); // carry := floor(carry/2^intDsize) < digit
1900         });
1901       *destptr++ = lowD(carry);
1902     }
1903   #else
1904   inline void mulu_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
1905     { var uintD carry = 0;
1906       dotimespC(len,len,
1907         { // Hier ist carry=digit=0 oder 0 <= carry < digit.
1908           var uintD hi;
1909           var uintD lo;
1910           muluD(digit,*sourceptr++,hi=,lo=);
1911           // Hier ist 0 <= 2^intDsize*hi + lo + carry < 2^intDsize*digit oder hi=lo=carry=digit=0.
1912           lo += carry; if (lo < carry) { hi += 1; }
1913           *destptr++ = lo;
1914           carry = hi;
1915         });
1916       *destptr++ = carry;
1917     }
1918   #endif
1919
1920 // Multiplikations-Einfachschleife mit Akkumulation:
1921 // Multipliziert eine UDS mit einem Digit und addiert das Ergebnis zu einer
1922 // zweiten UDS auf.
1923 // muluadd_loop_up(digit,sourceptr,destptr,len);
1924 // multipliziert die UDS  sourceptr[0..len-1]  (len>0)
1925 // mit dem einzelnen digit, legt das Ergebnis in der UDS  destptr[0..len-1]
1926 // ab und liefert den weiteren Übertrag.
1927   #if HAVE_DD
1928   inline uintD muluadd_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
1929     { var uintDD carry = 0;
1930       if (!(digit==0))
1931         { dotimespC(len,len,
1932             { // Hier ist 0 <= carry <= digit.
1933               carry = carry + muluD(digit,*sourceptr++) + (uintDD)*destptr;
1934               // Hier ist 0 <= carry <= 2^intDsize*digit + 2^intDsize-1.
1935               *destptr++ = lowD(carry);
1936               carry = (uintDD)highD(carry); // carry := floor(carry/2^intDsize) <= digit
1937             });
1938         }
1939       return lowD(carry);
1940     }
1941   #else
1942   inline uintD muluadd_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
1943     { var uintD carry = 0;
1944       if (!(digit==0))
1945         { dotimespC(len,len,
1946             { // Hier ist 0 <= carry <= digit.
1947               var uintD hi;
1948               var uintD lo;
1949               muluD(digit,*sourceptr++,hi=,lo=);
1950               // Hier ist 0 <= 2^intDsize*hi + lo + carry + *destptr <= 2^intDsize*digit+2^intDsize-1.
1951               lo += carry; if (lo < carry) { hi += 1; }
1952               carry = *destptr;
1953               lo += carry; if (lo < carry) { hi += 1; }
1954               *destptr++ = lo;
1955               carry = hi;
1956             });
1957         }
1958       return carry;
1959     }
1960   #endif
1961
1962 // Multiplikations-Einfachschleife mit Diminution:
1963 // Multipliziert eine UDS mit einem Digit und subtrahiert das Ergebnis von
1964 // einer zweiten UDS.
1965 // mulusub_loop_up(digit,sourceptr,destptr,len);
1966 // multipliziert die UDS  sourceptr[0..len-1]  (len>0)  mit dem einzelnen
1967 // digit, subtrahiert das Ergebnis von der UDS  destptr[0..len-1]  und liefert
1968 // den weiteren Übertrag (>=0, evtl. von destptr[len] zu subtrahieren).
1969   #if HAVE_DD
1970   inline uintD mulusub_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
1971     { var uintDD carry = 0;
1972       if (!(digit==0))
1973         { dotimespC(len,len,
1974             { // Hier ist 0 <= carry <= digit.
1975               carry = carry + muluD(digit,*sourceptr++) + (uintD)(~(*destptr));
1976               // Hier ist 0 <= carry <= 2^intDsize*digit + 2^intDsize-1.
1977               *destptr++ = ~lowD(carry);
1978               carry = (uintDD)highD(carry); // carry := floor(carry/2^intDsize) <= digit
1979               // Hier ist 0 <= carry <= digit.
1980             });
1981           return lowD(carry);
1982         }
1983         else
1984         return 0; // nichts zu subtrahieren -> kein Übertrag
1985     }
1986   #else
1987   inline uintD mulusub_loop_up (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
1988     { var uintD carry = 0;
1989       if (!(digit==0))
1990         { dotimespC(len,len,
1991             { // Hier ist 0 <= carry <= digit.
1992               var uintD hi;
1993               var uintD lo;
1994               muluD(digit,*sourceptr++,hi=,lo=);
1995               // Hier ist 0 <= 2^intDsize*hi + lo + carry + ~(*destptr) <= 2^intDsize*digit+2^intDsize-1.
1996               lo += carry; if (lo < carry) { hi += 1; }
1997               carry = *destptr;
1998               *destptr++ = carry - lo; if (carry < lo) { hi += 1; }
1999               carry = hi;
2000             });
2001           return carry;
2002         }
2003         else
2004         return 0; // nichts zu subtrahieren -> kein Übertrag
2005     }
2006   #endif
2007
2008 #endif
2009
2010 #ifndef DIV_LOOPS
2011
2012 // Divisions-Einfachschleife:
2013 // Dividiert eine UDS durch ein Digit.
2014 // divu_loop_down(digit,ptr,len)
2015 // dividiert die UDS  ptr[-len..-1] durch digit,
2016 // legt das Ergebnis in derselben UDS ab, und liefert den Rest (>=0, <digit).
2017   #if HAVE_DD
2018   inline uintD divu_loop_down (uintD digit, uintD* ptr, uintC len)
2019     { var uintD rest = 0;
2020       dotimesC(len,len,
2021         { --ptr; divuD(highlowDD(rest,*ptr),digit,*ptr =, rest =); }
2022         );
2023       return rest;
2024     }
2025   #else
2026   inline uintD divu_loop_down (uintD digit, uintD* ptr, uintC len)
2027     { var uintD rest = 0;
2028       dotimesC(len,len,
2029         { --ptr; divuD(rest,*ptr,digit,*ptr =, rest =); }
2030         );
2031       return rest;
2032     }
2033   #endif
2034
2035 // Divisions-Einfachschleife:
2036 // Dividiert eine UDS durch ein Digit und legt das Ergebnis in einer
2037 // zweiten UDS ab.
2038 // divucopy_loop_down(digit,sourceptr,destptr,len)
2039 // dividiert die UDS  sourceptr[-len..-1]  durch digit,
2040 // legt das Ergebnis in der UDS  destptr[-len..-1]  ab,
2041 // und liefert den Rest (>=0, <digit).
2042   #if HAVE_DD
2043   inline uintD divucopy_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
2044     { var uintD rest = 0;
2045       dotimesC(len,len,
2046         { divuD(highlowDD(rest,*--sourceptr),digit,*--destptr =, rest =); }
2047         );
2048       return rest;
2049     }
2050   #else
2051   inline uintD divucopy_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len)
2052     { var uintD rest = 0;
2053       dotimesC(len,len,
2054         { divuD(rest,*--sourceptr,digit,*--destptr =, rest =); }
2055         );
2056       return rest;
2057     }
2058   #endif
2059
2060 #endif
2061
2062 #endif // !CL_DS_BIG_ENDIAN_P
2063
2064 #if !defined(TEST_LOOPS) && !CL_DS_BIG_ENDIAN_P
2065
2066 // Vergleichsschleife:
2067 // result = compare_loop_up(xptr,yptr,count);
2068 // vergleicht nacheinander xptr[0] mit yptr[0], xptr[1] mit yptr[1], usw.,
2069 // insgesamt count Digits, und liefert 0 falls alle gleich sind,
2070 // +1 falls zuerst ein xptr[i]>yptr[i] ist,
2071 // -1 falls zuerst ein xptr[i]<yptr[i] ist.
2072   inline cl_signean compare_loop_up (const uintD* xptr, const uintD* yptr, uintC count)
2073     { dotimesC(count,count,
2074         { if (!(*xptr++ == *yptr++))
2075             // verschiedene Digits gefunden
2076             return (*--xptr > *--yptr ? signean_plus : signean_minus);
2077         });
2078       return signean_null; // alle Digits gleich
2079     }
2080
2081 #endif
2082
2083 #if !defined(LOG_LOOPS) && !CL_DS_BIG_ENDIAN_P
2084
2085 // XOR-Schleife:
2086 // xor_loop_up(xptr,yptr,count);
2087 // verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr
2088 // mit Ziel ab xptr durch XOR.
2089   inline void xor_loop_up (uintD* xptr, const uintD* yptr, uintC count)
2090     { dotimesC(count,count, { *xptr++ ^= *yptr++; } ); }
2091
2092 #endif
2093
2094 #if !defined(SHIFT_LOOPS) && CL_DS_BIG_ENDIAN_P
2095
2096 // Schiebe- und Kopierschleife um i Bits nach links:
2097 // übertrag = shiftleftcopy_loop_up(sourceptr,destptr,count,i);
2098 // kopiert count (uintC>=0) Digits aufwärts von sourceptr nach destptr
2099 // und schiebt sie dabei um i Bits (0<i<intDsize) nach links,
2100 // wobei ganz rechts mit i Nullbits aufgefüllt wird,
2101 // und liefert den Übertrag (was links rauskommt, >=0, <2^i).
2102   #if HAVE_DD
2103   inline uintD shiftleftcopy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count, uintC i)
2104     { var uintDD accu = 0;
2105       dotimesC(count,count,
2106         { accu = ((uintDD)(*sourceptr++)<<i)+accu; *destptr++ = lowD(accu);
2107           accu = (uintDD)(highD(accu));
2108         });
2109       return (uintD)accu;
2110     }
2111   #else
2112   inline uintD shiftleftcopy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count, uintC i)
2113     { var uintC j = intDsize-i;
2114       var uintD carry = 0;
2115       dotimesC(count,count,
2116         { var uintD accu = *sourceptr++;
2117           *destptr++ = (accu<<i) | carry;
2118           carry = accu>>j;
2119         });
2120       return carry;
2121     }
2122   #endif
2123
2124 #endif
2125
2126 #if !defined(SHIFT_LOOPS)
2127
2128 // Schiebe- und XOR-Schleife:
2129 // shiftxor_loop_up(xptr,yptr,count,i);
2130 // verknüpft count+1 Digits aufwärts ab xptr mit count Digits aufwärts ab yptr,
2131 // um i Bits verschoben, durch XOR. (count uintC>=0, 0<i<intDsize)
2132   #if HAVE_DD
2133   inline void shiftxor_loop_up (uintD* xptr, const uintD* yptr, uintC count, uintC i)
2134     { if (count > 0)
2135         { var uintD carry = xptr[0];
2136           dotimespC(count,count,
2137             { var uintDD accu = highlowDD(xptr[1],carry);
2138               accu = ((uintDD)(*yptr++)<<i) ^ accu;
2139               *xptr++ = lowD(accu);
2140               carry = highD(accu);
2141             });
2142           *xptr = carry;
2143     }   }
2144   #else
2145   inline void shiftxor_loop_up (uintD* xptr, const uintD* yptr, uintC count, uintC i)
2146     { if (count > 0)
2147         { var uintC j = intDsize-i;
2148           var uintD carry = *xptr;
2149           dotimespC(count,count,
2150             { var uintD accu = *yptr++;
2151               *xptr++ = (accu<<i) ^ carry;
2152               carry = (accu>>j) ^ *xptr;
2153             });
2154           *xptr = carry;
2155     }   }
2156   #endif
2157
2158 #endif
2159
2160
2161 // Endianness independent names for these functions.
2162 #if CL_DS_BIG_ENDIAN_P
2163   #define copy_loop_msp              copy_loop_up
2164   #define copy_loop_lsp              copy_loop_down
2165   #define fill_loop_msp              fill_loop_up
2166   #define fill_loop_lsp              fill_loop_down
2167   #define clear_loop_msp             clear_loop_up
2168   #define clear_loop_lsp             clear_loop_down
2169   #define test_loop_msp              test_loop_up
2170   #define or_loop_msp                or_loop_up
2171   #define xor_loop_msp               xor_loop_up
2172   #define and_loop_msp               and_loop_up
2173   #define eqv_loop_msp               eqv_loop_up
2174   #define nand_loop_msp              nand_loop_up
2175   #define nor_loop_msp               nor_loop_up
2176   #define andc2_loop_msp             andc2_loop_up
2177   #define orc2_loop_msp              orc2_loop_up
2178   #define not_loop_msp               not_loop_up
2179   #define and_test_loop_msp          and_test_loop_up
2180   #define compare_loop_msp           compare_loop_up
2181   #define add_loop_lsp               add_loop_down
2182   #define addto_loop_lsp             addto_loop_down
2183   #define inc_loop_lsp               inc_loop_down
2184   #define sub_loop_lsp               sub_loop_down
2185   #define subx_loop_lsp              subx_loop_down
2186   #define subfrom_loop_lsp           subfrom_loop_down
2187   #define dec_loop_lsp               dec_loop_down
2188   #define neg_loop_lsp               neg_loop_down
2189   #define shift1left_loop_lsp        shift1left_loop_down
2190   #define shiftleft_loop_lsp         shiftleft_loop_down
2191   #define shiftleftcopy_loop_lsp     shiftleftcopy_loop_down
2192   #define shift1right_loop_msp       shift1right_loop_up
2193   #define shiftright_loop_msp        shiftright_loop_up
2194   #define shiftrightsigned_loop_msp  shiftrightsigned_loop_up
2195   #define shiftrightcopy_loop_msp    shiftrightcopy_loop_up
2196   #define mulusmall_loop_lsp         mulusmall_loop_down
2197   #define mulu_loop_lsp              mulu_loop_down
2198   #define muluadd_loop_lsp           muluadd_loop_down
2199   #define mulusub_loop_lsp           mulusub_loop_down
2200   #define divu_loop_msp              divu_loop_up
2201   #define divucopy_loop_msp          divucopy_loop_up
2202 #else
2203   #define copy_loop_msp              copy_loop_down
2204   #define copy_loop_lsp              copy_loop_up
2205   #define fill_loop_msp              fill_loop_down
2206   #define fill_loop_lsp              fill_loop_up
2207   #define clear_loop_msp             clear_loop_down
2208   #define clear_loop_lsp             clear_loop_up
2209   #define test_loop_msp              test_loop_down
2210   #define or_loop_msp                or_loop_down
2211   #define xor_loop_msp               xor_loop_down
2212   #define and_loop_msp               and_loop_down
2213   #define eqv_loop_msp               eqv_loop_down
2214   #define nand_loop_msp              nand_loop_down
2215   #define nor_loop_msp               nor_loop_down
2216   #define andc2_loop_msp             andc2_loop_down
2217   #define orc2_loop_msp              orc2_loop_down
2218   #define not_loop_msp               not_loop_down
2219   #define and_test_loop_msp          and_test_loop_down
2220   #define compare_loop_msp           compare_loop_down
2221   #define add_loop_lsp               add_loop_up
2222   #define addto_loop_lsp             addto_loop_up
2223   #define inc_loop_lsp               inc_loop_up
2224   #define sub_loop_lsp               sub_loop_up
2225   #define subx_loop_lsp              subx_loop_up
2226   #define subfrom_loop_lsp           subfrom_loop_up
2227   #define dec_loop_lsp               dec_loop_up
2228   #define neg_loop_lsp               neg_loop_up
2229   #define shift1left_loop_lsp        shift1left_loop_up
2230   #define shiftleft_loop_lsp         shiftleft_loop_up
2231   #define shiftleftcopy_loop_lsp     shiftleftcopy_loop_up
2232   #define shift1right_loop_msp       shift1right_loop_down
2233   #define shiftright_loop_msp        shiftright_loop_down
2234   #define shiftrightsigned_loop_msp  shiftrightsigned_loop_down
2235   #define shiftrightcopy_loop_msp    shiftrightcopy_loop_down
2236   #define mulusmall_loop_lsp         mulusmall_loop_up
2237   #define mulu_loop_lsp              mulu_loop_up
2238   #define muluadd_loop_lsp           muluadd_loop_up
2239   #define mulusub_loop_lsp           mulusub_loop_up
2240   #define divu_loop_msp              divu_loop_down
2241   #define divucopy_loop_msp          divucopy_loop_down
2242 #endif
2243
2244 // Endianness independent loops where the direction doesn't matter.
2245 #if CL_DS_BIG_ENDIAN_P
2246   #define DS_clear_loop(MSDptr,len,LSDptr)  (void)clear_loop_up(MSDptr,len)
2247   #define DS_test_loop(MSDptr,len,LSDptr)  test_loop_up(MSDptr,len)
2248 #else
2249   #define DS_clear_loop(MSDptr,len,LSDptr)  (void)clear_loop_up(LSDptr,len)
2250   #define DS_test_loop(MSDptr,len,LSDptr)  test_loop_up(LSDptr,len)
2251 #endif
2252
2253
2254 // Umwandlungsroutinen Digit-Sequence-Teil <--> Longword:
2255
2256 // get_32_Dptr(ptr)
2257 //   holt die nächsten 32 Bits aus den 32/intDsize Digits ab ptr.
2258 // set_32_Dptr(ptr,wert);
2259 //   speichert den Wert wert (32 Bits) in die 32/intDsize Digits ab ptr.
2260 // get_max32_Dptr(count,ptr)
2261 //   holt die nächsten count Bits aus den ceiling(count/intDsize) Digits ab ptr.
2262 // set_max32_Dptr(count,ptr,wert)
2263 //   speichert wert (count Bits) in die ceiling(count/intDsize) Digits ab ptr.
2264 // Jeweils ptr eine Variable vom Typ uintD*,
2265 //         wert eine Variable vom Typ uint32,
2266 //         count eine Variable oder constant-expression mit Wert >=0, <=32.
2267   #if (intDsize==32)
2268     inline uint32 get_32_Dptr (const uintD* ptr)
2269     {
2270         return mspref(ptr,0);
2271     }
2272     inline void set_32_Dptr (uintD* ptr, uint32 wert)
2273     {
2274         mspref(ptr,0) = wert;
2275     }
2276     inline uint32 get_max32_Dptr (uintC count, const uintD* ptr)
2277     {
2278         return count==0 ? 0 :
2279                           mspref(ptr,0);
2280     }
2281     inline void set_max32_Dptr (uintC count, uintD* ptr, uint32 wert)
2282     {
2283         if (count==0) return;
2284         mspref(ptr,0) = wert; return;
2285     }
2286   #endif
2287   #if (intDsize==16)
2288     inline uint32 get_32_Dptr (const uintD* ptr)
2289     {
2290         return ((uint32)mspref(ptr,0)<<16) | (uint32)mspref(ptr,1);
2291     }
2292     inline void set_32_Dptr (uintD* ptr, uint32 wert)
2293     {
2294         mspref(ptr,0) = (uintD)(wert>>16); mspref(ptr,1) = (uintD)wert;
2295     }
2296     inline uint32 get_max32_Dptr (uintC count, const uintD* ptr)
2297     {
2298         return count==0 ? 0 :
2299                count<=16 ? mspref(ptr,0) :
2300                            ((uint32)mspref(ptr,0)<<16) | (uint32)mspref(ptr,1);
2301     }
2302     inline void set_max32_Dptr (uintC count, uintD* ptr, uint32 wert)
2303     {
2304         if (count==0) return;
2305         if (count<=16) { mspref(ptr,0) = (uintD)wert; return; }
2306         mspref(ptr,0) = (uintD)(wert>>16); mspref(ptr,1) = (uintD)wert; return;
2307     }
2308   #endif
2309   #if (intDsize==8)
2310     inline uint32 get_32_Dptr (const uintD* ptr)
2311     {
2312         return ((((((uint32)mspref(ptr,0) <<8) | (uint32)mspref(ptr,1)) <<8) | (uint32)mspref(ptr,2)) <<8) | (uint32)mspref(ptr,3);
2313     }
2314     inline void set_32_Dptr (uintD* ptr, uint32 wert)
2315     {
2316         mspref(ptr,0) = (uintD)(wert>>24); mspref(ptr,1) = (uintD)(wert>>16); mspref(ptr,2) = (uintD)(wert>>8); mspref(ptr,3) = (uintD)wert;
2317     }
2318     inline uint32 get_max32_Dptr (uintC count, const uintD* ptr)
2319     {
2320         return count==0 ? 0 :
2321                count<=8 ? mspref(ptr,0) :
2322                count<=16 ? ((uint32)mspref(ptr,0)<<8) | (uint32)mspref(ptr,1) :
2323                count<=24 ? ((((uint32)mspref(ptr,0)<<8) | (uint32)mspref(ptr,1))<<8) | (uint32)mspref(ptr,2) :
2324                            ((((((uint32)mspref(ptr,0)<<8) | (uint32)mspref(ptr,1))<<8) | (uint32)mspref(ptr,2))<<8) | (uint32)mspref(ptr,3);
2325     }
2326     inline void set_max32_Dptr (uintC count, uintD* ptr, uint32 wert)
2327     {
2328         if (count==0) return;
2329         if (count<=8) { mspref(ptr,0) = (uintD)wert; return; }
2330         if (count<=16) { mspref(ptr,0) = (uintD)(wert>>8); mspref(ptr,1) = (uintD)wert; return; }
2331         if (count<=24) { mspref(ptr,0) = (uintD)(wert>>16); mspref(ptr,1) = (uintD)(wert>>8); mspref(ptr,2) = (uintD)wert; return; }
2332         mspref(ptr,0) = (uintD)(wert>>24); mspref(ptr,1) = (uintD)(wert>>16); mspref(ptr,2) = (uintD)(wert>>8); mspref(ptr,3) = (uintD)wert; return;
2333     }
2334   #endif
2335
2336 #if (cl_word_size==64)
2337 // get_64_Dptr(ptr)
2338 //   holt die nächsten 64 Bits aus den 64/intDsize Digits ab ptr.
2339 // set_64_Dptr(ptr,wert);
2340 //   speichert den Wert wert (64 Bits) in die 64/intDsize Digits ab ptr.
2341 // get_max64_Dptr(count,ptr)
2342 //   holt die nächsten count Bits aus den ceiling(count/intDsize) Digits ab ptr.
2343 // set_max64_Dptr(count,ptr,wert)
2344 //   speichert wert (count Bits) in die ceiling(count/intDsize) Digits ab ptr.
2345 // Jeweils ptr eine Variable vom Typ uintD*,
2346 //         wert eine Variable vom Typ uint64,
2347 //         count eine Variable oder constant-expression mit Wert >=0, <=64.
2348   #if (intDsize==64)
2349     inline uint64 get_64_Dptr (const uintD* ptr)
2350     {
2351         return mspref(ptr,0);
2352     }
2353     inline void set_64_Dptr (uintD* ptr, uint64 wert)
2354     {
2355         mspref(ptr,0) = wert;
2356     }
2357     inline uint64 get_max64_Dptr (uintC count, const uintD* ptr)
2358     {
2359         return count==0 ? 0 : mspref(ptr,0);
2360     }
2361     inline void set_max64_Dptr (uintC count, uintD* ptr, uint64 wert)
2362     {
2363         if (count==0) return;
2364         mspref(ptr,0) = wert; return;
2365     }
2366   #else // (intDsize<=32)
2367     inline uint64 get_64_Dptr (const uintD* ptr)
2368     {
2369         return ((uint64)get_32_Dptr(ptr) << 32) | (uint64)get_32_Dptr(ptr mspop 32/intDsize);
2370     }
2371     inline void set_64_Dptr (uintD* ptr, uint64 wert)
2372     {
2373         set_32_Dptr(ptr,(uint32)(wert>>32));
2374         set_32_Dptr(ptr mspop 32/intDsize,(uint32)wert);
2375     }
2376     inline uint64 get_max64_Dptr (uintC count, const uintD* ptr)
2377     {
2378         return count==0 ? 0 :
2379                count<=32 ? (uint64)get_max32_Dptr(count,ptr) :
2380                            ((uint64)get_max32_Dptr(count-32,ptr) << 32) | (uint64)get_32_Dptr(ptr mspop ceiling(count-32,intDsize));
2381     }
2382     inline void set_max64_Dptr (uintC count, uintD* ptr, uint64 wert)
2383     {
2384         if (count==0) return;
2385         if (count<=32) { set_max32_Dptr(count,ptr,(uint32)wert); return; }
2386         set_max32_Dptr(count-32,ptr,(uint32)(wert>>32));
2387         set_32_Dptr(ptr mspop ceiling(count-32,intDsize),(uint32)wert); return;
2388     }
2389   #endif
2390 #endif
2391
2392 // get_uint1D_Dptr(ptr)  holt 1 Digit (unsigned) ab ptr
2393 // get_uint2D_Dptr(ptr)  holt 2 Digits (unsigned) ab ptr
2394 // get_uint3D_Dptr(ptr)  holt 3 Digits (unsigned) ab ptr
2395 // get_uint4D_Dptr(ptr)  holt 4 Digits (unsigned) ab ptr
2396 // get_sint1D_Dptr(ptr)  holt 1 Digit (signed) ab ptr
2397 // get_sint2D_Dptr(ptr)  holt 2 Digits (signed) ab ptr
2398 // get_sint3D_Dptr(ptr)  holt 3 Digits (signed) ab ptr
2399 // get_sint4D_Dptr(ptr)  holt 4 Digits (signed) ab ptr
2400 // Jeweils ptr eine Variable vom Typ uintD*.
2401 // NB: Bei intDsize==64 sind diese Funktionen nur sehr bedingt tauglich.
2402   inline uint32 get_uint1D_Dptr (const uintD* ptr)
2403   {
2404         return lspref(ptr,0);
2405   }
2406   inline sint32 get_sint1D_Dptr (const uintD* ptr)
2407   {
2408         return (sint32)(sintD)lspref(ptr,0);
2409   }
2410   #if (intDsize < 32)
2411   inline uint32 get_uint2D_Dptr (const uintD* ptr)
2412   {
2413         return ((uint32)lspref(ptr,1) << intDsize) | (uint32)lspref(ptr,0);
2414   }
2415   inline sint32 get_sint2D_Dptr (const uintD* ptr)
2416   {
2417         return ((uint32)(sint32)(sintD)lspref(ptr,1) << intDsize) | (uint32)lspref(ptr,0);
2418   }
2419   #else
2420   #define get_uint2D_Dptr(ptr)  get_uint1D_Dptr(ptr)
2421   #define get_sint2D_Dptr(ptr)  (sint32)get_uint2D_Dptr(ptr)
2422   #endif
2423   #if (intDsize < 16)
2424   inline uint32 get_uint3D_Dptr (const uintD* ptr)
2425   {
2426         return ((((uint32)lspref(ptr,2) << intDsize) | (uint32)lspref(ptr,1)) << intDsize) | (uint32)lspref(ptr,0);
2427   }
2428   inline sint32 get_sint3D_Dptr (const uintD* ptr)
2429   {
2430         return ((((uint32)(sint32)(sintD)lspref(ptr,2) << intDsize) | (uint32)lspref(ptr,1)) << intDsize) | (uint32)lspref(ptr,0);
2431   }
2432   inline uint32 get_uint4D_Dptr (const uintD* ptr)
2433   {
2434         return ((((((uint32)lspref(ptr,3) << intDsize) | (uint32)lspref(ptr,2)) << intDsize) | (uint32)lspref(ptr,1)) << intDsize) | (uint32)lspref(ptr,0);
2435   }
2436   inline sint32 get_sint4D_Dptr (const uintD* ptr)
2437   {
2438         return ((((((uint32)(sint32)(sintD)lspref(ptr,3) << intDsize) | (uint32)lspref(ptr,2)) << intDsize) | (uint32)lspref(ptr,1)) << intDsize) | (uint32)lspref(ptr,0);
2439   }
2440   #else
2441   #define get_uint3D_Dptr(ptr)  get_uint2D_Dptr(ptr)
2442   #define get_sint3D_Dptr(ptr)  (sint32)get_uint3D_Dptr(ptr)
2443   #define get_uint4D_Dptr(ptr)  get_uint2D_Dptr(ptr)
2444   #define get_sint4D_Dptr(ptr)  (sint32)get_uint4D_Dptr(ptr)
2445   #endif
2446
2447
2448 // NUM_STACK ist eine Art Zahlen-Stack-Pointer.
2449 // Verwendung:
2450 //   {CL_ALLOCA_STACK;
2451 //    ...
2452 //    num_stack_alloc(...);
2453 //    ...
2454 //    num_stack_array(...);
2455 //    ...
2456 //   }
2457 // CL_ALLOCA_STACK rettet den aktuellen Wert von NUM_STACK.
2458 // Dann darf beliebig oft mit num_stack_alloc/num_stack_array Platz auf dem
2459 // Zahlen-Stack belegt werden.
2460 // Beim Ende des Blocks wird NUM_STACK wieder auf den vorigen Wert gesetzt,
2461 // und der Platz gilt als wieder freigegeben.
2462 // In jeder C-Funktion sollte CL_ALLOCA_STACK nur einmal aufgerufen werden.
2463 // Wegen eines GCC-Bugs sollten Funktionen, die diese Macros benutzen,
2464 // nicht inline deklariert sein.
2465
2466 // num_stack_array(need, low_addr = , high_addr = );
2467 // num_stack_small_array(need, low_addr = , high_addr = );
2468 // belegt need Digits auf dem Zahlen-Stack und legt die untere Grenze des
2469 // allozierten Bereichs in low_addr und die obere Grenze in high_addr ab.
2470 // Jedes von beiden ist optional.
2471
2472 // num_stack_alloc(need, MSDptr = , LSDptr = );
2473 // num_stack_small_alloc(need, MSDptr = , LSDptr = );
2474 // belegt need Digits auf dem Zahlen-Stack und legt den MSDptr und den
2475 // LSDptr ab. Jedes von beiden ist optional.
2476
2477 // num_stack_alloc_1(need, MSDptr = , LSDptr = );
2478 // num_stack_small_alloc_1(need, MSDptr = , LSDptr = );
2479 // wie num_stack_alloc, nur daß unterhalb von MSDptr noch ein Digit Platz
2480 // zusätzlich belegt wird.
2481
2482 #define num_stack_array(need,low_zuweisung,high_zuweisung)  \
2483   {var uintL __need = (uintL)(need);                            \
2484    var uintD* __array = cl_alloc_array(uintD,__need);           \
2485    unused (low_zuweisung &__array[0]); unused (high_zuweisung &__array[__need]); \
2486   }
2487 #define num_stack_small_array(need,low_zuweisung,high_zuweisung)  \
2488   {var uintL __need = (uintL)(need);                            \
2489    var uintD* __array = cl_small_alloc_array(uintD,__need);     \
2490    unused (low_zuweisung &__array[0]); unused (high_zuweisung &__array[__need]); \
2491   }
2492 #if CL_DS_BIG_ENDIAN_P
2493   #define num_stack_alloc(need,MSDptr_zuweisung,LSDptr_zuweisung)  \
2494     num_stack_array(need,MSDptr_zuweisung,LSDptr_zuweisung)
2495   #define num_stack_small_alloc(need,MSDptr_zuweisung,LSDptr_zuweisung)  \
2496     num_stack_small_array(need,MSDptr_zuweisung,LSDptr_zuweisung)
2497   #define num_stack_alloc_1(need,MSDptr_zuweisung,LSDptr_zuweisung)  \
2498     num_stack_array((uintL)(need)+1,MSDptr_zuweisung 1 + ,LSDptr_zuweisung)
2499   #define num_stack_small_alloc_1(need,MSDptr_zuweisung,LSDptr_zuweisung)  \
2500     num_stack_small_array((uintL)(need)+1,MSDptr_zuweisung 1 + ,LSDptr_zuweisung)
2501 #else
2502   #define num_stack_alloc(need,MSDptr_zuweisung,LSDptr_zuweisung)  \
2503     num_stack_array(need,LSDptr_zuweisung,MSDptr_zuweisung)
2504   #define num_stack_small_alloc(need,MSDptr_zuweisung,LSDptr_zuweisung)  \
2505     num_stack_small_array(need,LSDptr_zuweisung,MSDptr_zuweisung)
2506   #define num_stack_alloc_1(need,MSDptr_zuweisung,LSDptr_zuweisung)  \
2507     num_stack_array((uintL)(need)+1,LSDptr_zuweisung,MSDptr_zuweisung -1 + )
2508   #define num_stack_small_alloc_1(need,MSDptr_zuweisung,LSDptr_zuweisung)  \
2509     num_stack_small_array((uintL)(need)+1,LSDptr_zuweisung,MSDptr_zuweisung -1 + )
2510 #endif
2511
2512
2513 // Macro: In der DS MSDptr/len/LSDptr wird eine 1 unterhalb des Pointers ptr
2514 // addiert. Unterhalb von MSDptr muß 1 Digit Platz sein.
2515 // Dabei ist  ptr - MSDptr = count  und  0 < count <= len .
2516 // Eventuell wird MSDptr erniedrigt und len erhöht.
2517   #define DS_1_plus(ptr,count)  \
2518     {var uintD* ptr_from_DS_1_plus = (ptr);                             \
2519      var uintC count_from_DS_1_plus = (count);                          \
2520      loop { if (--count_from_DS_1_plus==0) /* Zähler erniedrigen      */\
2521               { /* Beim Most Significant Digit angelangt              */\
2522                 lsprefnext(ptr_from_DS_1_plus) += 1;                    \
2523                 /* jetzt ist ptr_from_DS_1_plus = MSDptr              */\
2524                 if (mspref(ptr_from_DS_1_plus,0) == (uintD)bit(intDsize-1)) \
2525                   { /* 7FFF + 1 muß zu 00008000 werden:               */\
2526                     lsprefnext(MSDptr) = 0;                             \
2527                     len++;                                              \
2528                   }                                                     \
2529                 break;                                                  \
2530               }                                                         \
2531             if (!((lsprefnext(ptr_from_DS_1_plus) += 1) == 0)) /* weiterincrementieren */\
2532               break; /* kein weiterer Übertrag -> Schleife abbrechen  */\
2533     }     }
2534
2535 // Macro: In der DS MSDptr/len/LSDptr wird eine 1 unterhalb des Pointers ptr
2536 // subtrahiert. Unterhalb von MSDptr muß 1 Digit Platz sein.
2537 // Dabei ist  ptr - MSDptr = count  und  0 < count <= len .
2538 // Eventuell wird MSDptr erniedrigt und len erhöht.
2539   #define DS_minus1_plus(ptr,count)  \
2540     {var uintD* ptr_from_DS_minus1_plus = (ptr);                        \
2541      var uintC count_from_DS_minus1_plus = (count);                     \
2542      loop { if (--count_from_DS_minus1_plus==0) /* Zähler erniedrigen */\
2543               { /* Beim Most Significant Digit angelangt              */\
2544                 lsprefnext(ptr_from_DS_minus1_plus) -= 1;               \
2545                 /* jetzt ist ptr_from_DS_minus1_plus = MSDptr         */\
2546                 if (mspref(ptr_from_DS_minus1_plus,0) == (uintD)bit(intDsize-1)-1) \
2547                   { /* 8000 - 1 muß zu FFFF7FFF werden:               */\
2548                     lsprefnext(MSDptr) = (uintD)(-1);                   \
2549                     len++;                                              \
2550                   }                                                     \
2551                 break;                                                  \
2552               }                                                         \
2553             if (!((sintD)(lsprefnext(ptr_from_DS_minus1_plus) -= 1) == -1)) /* weiterdecrementieren */\
2554               break; /* kein weiterer Übertrag -> Schleife abbrechen  */\
2555     }     }
2556
2557
2558 // Multiplikations-Doppelschleife:
2559 // Multipliziert zwei UDS und legt das Ergebnis in einer dritten UDS ab.
2560 // cl_UDS_mul(sourceptr1,len1,sourceptr2,len2,destptr);
2561 // multipliziert die UDS  sourceptr1[-len1..-1]  (len1>0)
2562 //           mit der UDS  sourceptr2[-len1..-1]  (len2>0)
2563 // und legt das Ergebnis in der UDS  destptr[-len..-1]  (len=len1+len2) ab.
2564 // Unterhalb von destptr werden len Digits Platz benötigt.
2565 extern void cl_UDS_mul (const uintD* sourceptr1, uintC len1,
2566                         const uintD* sourceptr2, uintC len2,
2567                         uintD* destptr);
2568 // Spezialfall sourceptr1 == sourceptr2 && len1 == len2.
2569 extern void cl_UDS_mul_square (const uintD* sourceptr, uintC len,
2570                                uintD* destptr);
2571
2572 // Multipliziert zwei Unsigned-Digit-sequences.
2573 // UDS_UDS_mul_UDS(len1,LSDptr1, len2,LSDptr2, MSDptr=,len=,LSDptr=);
2574 // multipliziert die UDS ../len1/LSDptr1 und ../len2/LSDptr2.
2575 // Dabei sollte len1>0 und len2>0 sein.
2576 // Ergebnis ist die UDS MSDptr/len/LSDptr, mit len=len1+len2, im Stack.
2577 // Dabei wird num_stack erniedrigt.
2578   #define UDS_UDS_mul_UDS(len1,LSDptr1,len2,LSDptr2, MSDptr_zuweisung,len_zuweisung,LSDptr_zuweisung)  \
2579     var uintL CONCAT(len_from_UDSmul_,__LINE__) = (uintL)(len1) + (uintL)(len2); \
2580     var uintD* CONCAT(LSDptr_from_UDSmul_,__LINE__);                            \
2581     unused (len_zuweisung CONCAT(len_from_UDSmul_,__LINE__));                   \
2582     num_stack_alloc(CONCAT(len_from_UDSmul_,__LINE__),MSDptr_zuweisung,LSDptr_zuweisung CONCAT(LSDptr_from_UDSmul_,__LINE__) =); \
2583     cl_UDS_mul((LSDptr1),(len1),(LSDptr2),(len2),CONCAT(LSDptr_from_UDSmul_,__LINE__));
2584
2585 // Multipliziert zwei Digit-sequences.
2586 // DS_DS_mul_DS(MSDptr1,len1,LSDptr1, MSDptr2,len2,LSDptr2, MSDptr=,len=,LSDptr=);
2587 // multipliziert die DS MSDptr1/len1/LSDptr1 und MSDptr2/len2/LSDptr2.
2588 // Dabei sollte len1>0 und len2>0 sein, und beide DS sollten /= 0 sein.
2589 // Alles sollten Variablen sein!
2590 // Ergebnis ist die DS MSDptr/len/LSDptr, mit len=len1+len2, im Stack.
2591 // Dabei wird num_stack erniedrigt.
2592   // Methode:
2593   // Erst unsigned multiplizieren. Dann bis zu zwei Subtraktionen.
2594   // Sei b=2^intDsize, k=len1, l=len2, n=DS1, m=DS2.
2595   // Gesucht ist n * m.
2596   // Wir errechnen erst das unsigned-product p (mod b^(k+l)).
2597   // n>0, m>0: p = n*m,             n*m = p
2598   // n<0, m>0: p = (n+b^k)*m,       n*m + b^(k+l) = p - b^k * m (mod b^(k+l)).
2599   // n>0, m<0: p = n*(m+b^l),       n*m + b^(k+l) = p - b^l * n (mod b^(k+l)).
2600   // n<0, m<0: p = (n+b^k)*(m+b^l),
2601   //           n*m = p - b^k * (m+b^l) - b^l * (n+b^k) (mod b^(k+l)).
2602   #define DS_DS_mul_DS(MSDptr1,len1,LSDptr1,MSDptr2,len2,LSDptr2, MSDptr_zuweisung,len_zuweisung,LSDptr_zuweisung)  \
2603     var uintD* MSDptr0;                                                 \
2604     var uintD* LSDptr0;                                                 \
2605     var uintL len_from_DSmal = (uintL)(len1) + (uintL)(len2);           \
2606     unused (len_zuweisung len_from_DSmal);                              \
2607     num_stack_alloc(len_from_DSmal,MSDptr_zuweisung MSDptr0 =,LSDptr_zuweisung LSDptr0 =); \
2608     var uintD MSD1_from_DSmal = mspref(MSDptr1,0);                      \
2609     var uintD MSD2_from_DSmal = mspref(MSDptr2,0);                      \
2610     var uintL len1_from_DSmal = (len1);                                 \
2611     var uintL len2_from_DSmal = (len2);                                 \
2612     if (MSD1_from_DSmal==0) { msprefnext(MSDptr0) = 0; len1_from_DSmal--; } \
2613     if (MSD2_from_DSmal==0) { msprefnext(MSDptr0) = 0; len2_from_DSmal--; } \
2614     cl_UDS_mul((LSDptr1),len1_from_DSmal,(LSDptr2),len2_from_DSmal,LSDptr0); \
2615     if ((sintD)MSD1_from_DSmal < 0) /* n<0 ?                          */\
2616       /* muß m bzw. m+b^l subtrahieren, um k Digits verschoben:       */\
2617       { subfrom_loop_lsp(LSDptr2,LSDptr0 lspop len1,len2); }            \
2618     if ((sintD)MSD2_from_DSmal < 0) /* m<0 ?                          */\
2619       /* muß n bzw. n+b^k subtrahieren, um l Digits verschoben:       */\
2620       { subfrom_loop_lsp(LSDptr1,LSDptr0 lspop len2,len1); }
2621
2622
2623 // Dividiert zwei Unsigned Digit sequences durcheinander.
2624 // UDS_divide(a_MSDptr,a_len,a_LSDptr, b_MSDptr,b_len,b_LSDptr, &q,&r);
2625 // Die UDS a = a_MSDptr/a_len/a_LSDptr (a>=0) wird durch
2626 // die UDS b = b_MSDptr/b_len/b_LSDptr (b>=0) dividiert:
2627 // a = q * b + r mit 0 <= r < b. Bei b=0 Error.
2628 // q der Quotient, r der Rest.
2629 // q = q_MSDptr/q_len/q_LSDptr, r = r_MSDptr/r_len/r_LSDptr beides
2630 // Normalized Unsigned Digit sequences.
2631 // Vorsicht: q_LSDptr <= r_MSDptr,
2632 //           Vorzeichenerweiterung von r kann q zerstören!
2633 //           Vorzeichenerweiterung von q ist erlaubt.
2634 // a und b werden nicht modifiziert.
2635 // num_stack wird erniedrigt.
2636   #define UDS_divide(a_MSDptr,a_len,a_LSDptr,b_MSDptr,b_len,b_LSDptr,q_,r_)  \
2637     /* Platz fürs Ergebnis machen. Brauche maximal a_len+1 Digits.    */\
2638     var uintC _a_len = (a_len);                                         \
2639     var uintD* roomptr; num_stack_alloc_1(_a_len+1,roomptr=,);          \
2640     cl_UDS_divide(a_MSDptr,_a_len,a_LSDptr,b_MSDptr,b_len,b_LSDptr,roomptr,q_,r_);
2641   extern void cl_UDS_divide (const uintD* a_MSDptr, uintC a_len, const uintD* a_LSDptr,
2642                              const uintD* b_MSDptr, uintC b_len, const uintD* b_LSDptr,
2643                              uintD* roomptr, DS* q_, DS* r_);
2644
2645
2646 // Bildet zu einer Unsigned Digit sequence a die Wurzel
2647 // (genauer: Gaußklammer aus Wurzel aus a).
2648 // UDS_sqrt(a_MSDptr,a_len,a_LSDptr, &b, squarep=)
2649 // > a_MSDptr/a_len/a_LSDptr: eine UDS
2650 // < NUDS b: Gaußklammer der Wurzel aus a
2651 // < squarep: cl_true falls a = b^2, cl_false falls b^2 < a < (b+1)^2.
2652 // a wird nicht modifiziert.
2653 // Vorzeichenerweiterung von b ist erlaubt.
2654 // num_stack wird erniedrigt.
2655   #define UDS_sqrt(a_MSDptr,a_len,a_LSDptr,b_,squarep_zuweisung)  \
2656     { /* ceiling(a_len,2) Digits Platz fürs Ergebnis machen:          */\
2657       var uintC _a_len = (a_len);                                       \
2658       num_stack_alloc_1(ceiling(_a_len,2),(b_)->MSDptr=,);              \
2659       squarep_zuweisung cl_UDS_sqrt(a_MSDptr,_a_len,a_LSDptr,b_);       \
2660     }
2661   extern cl_boolean cl_UDS_sqrt (const uintD* a_MSDptr, uintC a_len, const uintD* a_LSDptr, DS* b_);
2662
2663
2664 // Auxiliary function for approximately computing 1/x
2665 // using Newton iteration.
2666   extern void cl_UDS_recip (const uintD* a_MSDptr, uintC a_len,
2667                             uintD* b_MSDptr, uintC b_len);
2668
2669 // Auxiliary function for approximately computing 1/sqrt(x)
2670 // using Newton iteration.
2671   extern void cl_UDS_recipsqrt (const uintD* a_MSDptr, uintC a_len,
2672                                 uintD* b_MSDptr, uintC b_len);
2673
2674
2675 #endif /* _CL_DS_H */