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