# Definitionen und portabler C-Code zu ARILEV1.D, Inline-Version #ifndef COPY_LOOPS # Kopierschleife: # destptr = copy_loop_up(sourceptr,destptr,count); # kopiert count (uintC>=0) Digits aufwärts von sourceptr nach destptr # und liefert das neue destptr. inline local uintD* copy_loop_up (const uintD* sourceptr, uintD* destptr, uintC count) { dotimesC(count,count, { *destptr++ = *sourceptr++; }); return destptr; } # Kopierschleife: # destptr = copy_loop_down(sourceptr,destptr,count); # kopiert count (uintC>=0) Digits abwärts von sourceptr nach destptr # und liefert das neue destptr. inline local uintD* copy_loop_down (const uintD* sourceptr, uintD* destptr, uintC count) { dotimesC(count,count, { *--destptr = *--sourceptr; }); return destptr; } #endif #ifndef FILL_LOOPS # Füllschleife: # destptr = fill_loop_up(destptr,count,filler); # kopiert count (uintC>=0) mal das Digit filler aufwärts nach destptr # und liefert das neue destptr. inline local uintD* fill_loop_up (uintD* destptr, uintC count, uintD filler) { dotimesC(count,count, { *destptr++ = filler; }); return destptr; } # Füllschleife: # destptr = fill_loop_down(destptr,count,filler); # kopiert count (uintC>=0) mal das Digit filler abwärts nach destptr # und liefert das neue destptr. inline local uintD* fill_loop_down (uintD* destptr, uintC count, uintD filler) { dotimesC(count,count, { *--destptr = filler; }); return destptr; } #endif #ifndef CLEAR_LOOPS # Lösch-Schleife: # destptr = clear_loop_up(destptr,count); # löscht count (uintC>=0) Digits aufwärts ab destptr # und liefert das neue destptr. inline local uintD* clear_loop_up (uintD* destptr, uintC count) { dotimesC(count,count, { *destptr++ = 0; }); return destptr; } # Lösch-Schleife: # destptr = clear_loop_down(destptr,count); # löscht count (uintC>=0) Digits abwärts ab destptr # und liefert das neue destptr. inline local uintD* clear_loop_down (uintD* destptr, uintC count) { dotimesC(count,count, { *--destptr = 0; }); return destptr; } #endif #ifndef LOG_LOOPS # OR-Schleife: # or_loop_up(xptr,yptr,count); # verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr # mit Ziel ab xptr durch OR. inline local void or_loop_up (uintD* xptr, const uintD* yptr, uintC count) { dotimesC(count,count, { *xptr++ |= *yptr++; }); } # XOR-Schleife: # xor_loop_up(xptr,yptr,count); # verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr # mit Ziel ab xptr durch XOR. inline local void xor_loop_up (uintD* xptr, const uintD* yptr, uintC count) { dotimesC(count,count, { *xptr++ ^= *yptr++; }); } # AND-Schleife: # and_loop_up(xptr,yptr,count); # verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr # mit Ziel ab xptr durch AND. inline local void and_loop_up (uintD* xptr, const uintD* yptr, uintC count) { dotimesC(count,count, { *xptr++ &= *yptr++; }); } # EQV-Schleife: # eqv_loop_up(xptr,yptr,count); # verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr # mit Ziel ab xptr durch EQV (NOT XOR). inline local void eqv_loop_up (uintD* xptr, const uintD* yptr, uintC count) { dotimesC(count,count, { var uintD temp = ~ (*xptr ^ *yptr++); *xptr++ = temp; }); } # NAND-Schleife: # nand_loop_up(xptr,yptr,count); # verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr # mit Ziel ab xptr durch NAND (NOT AND). inline local void nand_loop_up (uintD* xptr, const uintD* yptr, uintC count) { dotimesC(count,count, { var uintD temp = ~ (*xptr & *yptr++); *xptr++ = temp; }); } # NOR-Schleife: # nor_loop_up(xptr,yptr,count); # verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr # mit Ziel ab xptr durch NOR (NOT OR). inline local void nor_loop_up (uintD* xptr, const uintD* yptr, uintC count) { dotimesC(count,count, { var uintD temp = ~ (*xptr | *yptr++); *xptr++ = temp; }); } # ANDC2-Schleife: # andc2_loop_up(xptr,yptr,count); # verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr # mit Ziel ab xptr durch ANDC2 (AND NOT). inline local void andc2_loop_up (uintD* xptr, const uintD* yptr, uintC count) { dotimesC(count,count, { *xptr++ &= ~(*yptr++); }); } # ORC2-Schleife: # orc2_loop_up(xptr,yptr,count); # verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr # mit Ziel ab xptr durch ORC2 (OR NOT). inline local void orc2_loop_up (uintD* xptr, const uintD* yptr, uintC count) { dotimesC(count,count, { *xptr++ |= ~(*yptr++); }); } # NOT-Schleife: # not_loop_up(xptr,count); # verknüpft count (uintC>0) Digits aufwärts ab xptr mit Ziel ab xptr # durch NOT. inline local void not_loop_up (uintD* xptr, uintC count) { dotimespC(count,count, { var uintD temp = ~ (*xptr); *xptr++ = temp; }); } #endif #ifndef TEST_LOOPS # AND-Test-Schleife: # and_test_loop_up(xptr,yptr,count); # verknüpft count (uintC>=0) Digits aufwärts ab xptr und ab yptr durch AND # und testet, ob sich dabei ein Digit /=0 ergibt. Ergebnis /=0, falls ja. inline local /*bool*/int and_test_loop_up (const uintD* xptr, const uintD* yptr, uintC count) { dotimesC(count,count, { if (*xptr++ & *yptr++) return true; }); return false; } # Test-Schleife: # test_loop_up(ptr,count) # testet count (uintC>=0) Digits aufwärts ab ptr, ob darunter eines /=0 ist. # Ergebnis /=0, falls ja. inline local /*bool*/int test_loop_up (const uintD* ptr, uintC count) { dotimesC(count,count, { if (*ptr++) return true; }); return false; } # Vergleichsschleife: # result = compare_loop_up(xptr,yptr,count); # vergleicht nacheinander xptr[0] mit yptr[0], xptr[1] mit yptr[1], usw., # insgesamt count Digits, und liefert 0 falls alle gleich sind, # +1 falls zuerst ein xptr[i]>yptr[i] ist, # -1 falls zuerst ein xptr[i] *--yptr ? signean_plus : signean_minus); }); return signean_null; # alle Digits gleich } #endif #ifndef ADDSUB_LOOPS # Additionsschleife: # übertrag = add_loop_down(sourceptr1,sourceptr2,destptr,count); # addiert count (uintC>=0) Digits abwärts von sourceptr1, von sourceptr2 # abwärts nach destptr und liefert den Übertrag (0 oder /=0, was 1 bedeutet). inline local uintD add_loop_down (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count) { if (!(count==0)) do { { var uintD source1 = *--sourceptr1; var uintD source2 = *--sourceptr2; *--destptr = source1 + source2; if (source1 > (uintD)(~source2)) goto carry_1; } carry_0: count--; } while (count != 0); return 0; do { { var uintD source1 = *--sourceptr1; var uintD source2 = *--sourceptr2; *--destptr = source1 + source2 + 1; if (source1 < (uintD)(~source2)) goto carry_0; } carry_1: count--; } while (count != 0); return 1; } # Additionsschleife: # übertrag = addto_loop_down(sourceptr,destptr,count); # addiert count (uintC>=0) Digits abwärts von sourceptr, von destptr # abwärts nach destptr und liefert den Übertrag (0 oder /=0, was 1 bedeutet). inline local uintD addto_loop_down (const uintD* sourceptr, uintD* destptr, uintC count) { if (!(count==0)) do { { var uintD source1 = *--sourceptr; var uintD source2 = *--destptr; *destptr = source1 + source2; if (source1 > (uintD)(~source2)) goto carry_1; } carry_0: count--; } while (count != 0); return 0; do { { var uintD source1 = *--sourceptr; var uintD source2 = *--destptr; *destptr = source1 + source2 + 1; if (source1 < (uintD)(~source2)) goto carry_0; } carry_1: count--; } while (count != 0); return 1; } # Incrementierschleife: # übertrag = inc_loop_down(ptr,count); # incrementiert count (uintC>=0) Digits abwärts von ptr, so lange bis kein # Übertrag mehr auftritt und liefert den Übertrag (0 oder /=0, was 1 bedeutet). inline local uintD inc_loop_down (uintD* ptr, uintC count) { dotimesC(count,count, { if (!( ++(*--ptr) == 0 )) return 0; # kein weiterer Übertrag }); return 1; # weiterer Übertrag } # Subtraktionsschleife: # übertrag = sub_loop_down(sourceptr1,sourceptr2,destptr,count); # subtrahiert count (uintC>=0) Digits abwärts von sourceptr1, von sourceptr2 # abwärts nach destptr und liefert den Übertrag (0 oder /=0, was -1 bedeutet). inline local uintD sub_loop_down (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count) { if (!(count==0)) do { { var uintD source1 = *--sourceptr1; var uintD source2 = *--sourceptr2; *--destptr = source1 - source2; if (source1 < source2) goto carry_1; } carry_0: count--; } while (count != 0); return 0; do { { var uintD source1 = *--sourceptr1; var uintD source2 = *--sourceptr2; *--destptr = source1 - source2 - 1; if (source1 > source2) goto carry_0; } carry_1: count--; } while (count != 0); return (uintD)-1; } # Subtraktionsschleife: # übertrag = subx_loop_down(sourceptr1,sourceptr2,destptr,count,carry); # subtrahiert count (uintC>=0) Digits abwärts von sourceptr1 und addiert # einen Carry (0 oder -1), von sourceptr2 abwärts nach destptr und # liefert den Übertrag (0 oder /=0, was -1 bedeutet). inline local uintD subx_loop_down (const uintD* sourceptr1, const uintD* sourceptr2, uintD* destptr, uintC count, uintD carry) { if (carry==0) { if (!(count==0)) do { { var uintD source1 = *--sourceptr1; var uintD source2 = *--sourceptr2; *--destptr = source1 - source2; if (source1 < source2) goto carry_1; } carry_0: count--; } while (count != 0); return 0; } else { if (!(count==0)) do { { var uintD source1 = *--sourceptr1; var uintD source2 = *--sourceptr2; *--destptr = source1 - source2 - 1; if (source1 > source2) goto carry_0; } carry_1: count--; } while (count != 0); return (uintD)-1; } } # Subtraktionsschleife: # übertrag = subfrom_loop_down(sourceptr,destptr,count); # subtrahiert count (uintC>=0) Digits abwärts von sourceptr, von destptr # abwärts nach destptr (dest := dest - source) # und liefert den Übertrag (0 oder /=0, was -1 bedeutet). inline local uintD subfrom_loop_down (const uintD* sourceptr, uintD* destptr, uintC count) { if (!(count==0)) do { { var uintD source1 = *--destptr; var uintD source2 = *--sourceptr; *destptr = source1 - source2; if (source1 < source2) goto carry_1; } carry_0: count--; } while (count != 0); return 0; do { { var uintD source1 = *--destptr; var uintD source2 = *--sourceptr; *destptr = source1 - source2 - 1; if (source1 > source2) goto carry_0; } carry_1: count--; } while (count != 0); return (uintD)-1; } # Decrementierschleife: # übertrag = dec_loop_down(ptr,count); # decrementiert count (uintC>=0) Digits abwärts von ptr, so lange bis kein # Übertrag mehr auftritt und liefert den Übertrag (0 oder -1). inline local uintD dec_loop_down (uintD* ptr, uintC count) { dotimesC(count,count, { if (!( (*--ptr)-- == 0 )) return 0; # kein weiterer Übertrag }); return (uintD)-1; # weiterer Übertrag } # Negierschleife: # übertrag = neg_loop_down(ptr,count); # negiert count (uintC>=0) Digits abwärts von ptr, # und liefert den Übertrag (0 oder -1). inline local uintD neg_loop_down (uintD* ptr, uintC count) { # erstes Digit /=0 suchen: while (count != 0) { if (!(*--ptr == 0)) goto L1; count--; } return 0; L1: # erstes Digit /=0 gefunden, ab jetzt gibt's Carrys *ptr = - *ptr; count--; # 1 Digit negieren dotimesC(count,count, { # alle anderen Digits invertieren --ptr; *ptr = ~ *ptr; }); return (uintD)-1; } #endif #ifndef SHIFT_LOOPS # Schiebeschleife um 1 Bit nach links: # übertrag = shift1left_loop_down(ptr,count); # schiebt count (uintC>=0) Digits abwärts von ptr um 1 Bit nach links, # und liefert den Übertrag (0 oder /=0, was 1 bedeutet). inline local uintD shift1left_loop_down (uintD* ptr, uintC count) { #if HAVE_DD var uintDD accu = 0; dotimesC(count,count, { accu = ((uintDD)(*--ptr)<<1)+accu; *ptr = lowD(accu); accu = (uintDD)(highD(accu)); }); return (uintD)accu; #else var uintD carry = 0; dotimesC(count,count, { var uintD accu = *--ptr; *ptr = (accu<<1) | carry; carry = accu>>(intDsize-1); }); return carry; #endif } # Schiebeschleife um i Bits nach links: # übertrag = shiftleft_loop_down(ptr,count,i,übertrag_init); # schiebt count (uintC>=0) Digits abwärts von ptr um i Bits (0=0, <2^i). inline local uintD shiftleft_loop_down (uintD* ptr, uintC count, uintC i, uintD carry) { #if HAVE_DD var uintDD accu = (uintDD)carry; dotimesC(count,count, { accu = ((uintDD)(*--ptr)< 0) { var uintC j = intDsize-i; dotimespC(count,count, { var uintD accu = *--ptr; *ptr = (accu<>j; }); } return carry; #endif } # Schiebe- und Kopierschleife um i Bits nach links: # übertrag = shiftleftcopy_loop_down(sourceptr,destptr,count,i); # kopiert count (uintC>=0) Digits abwärts von sourceptr nach destptr # und schiebt sie dabei um i Bits (0=0, <2^i). inline local uintD shiftleftcopy_loop_down (const uintD* sourceptr, uintD* destptr, uintC count, uintC i) { #if HAVE_DD var uintDD accu = 0; dotimesC(count,count, { accu = ((uintDD)(*--sourceptr)< 0) { var uintC j = intDsize-i; dotimespC(count,count, { var uintD accu = *--sourceptr; *--destptr = (accu<>j; }); } return carry; #endif } # Schiebeschleife um 1 Bit nach rechts: # übertrag = shift1right_loop_up(ptr,count,übertrag_init); # schiebt count (uintC>=0) Digits aufwärts von ptr um 1 Bit nach rechts, # wobei links das Bit übertrag_init (sollte =0 oder =-1 sein) hineingeschoben # wird, und liefert den Übertrag (0 oder /=0, was 1 bedeutet). inline local uintD shift1right_loop_up (uintD* ptr, uintC count, uintD carry) { #if HAVE_DD var uintDD accu = (sintDD)(sintD)carry & ((uintDD)1 << (2*intDsize-1)); # 0 oder bit(2*intDsize-1) dotimesC(count,count, { accu = (highlowDD_0(*ptr)>>1)+accu; *ptr++ = highD(accu); accu = highlowDD_0(lowD(accu)); }); return highD(accu); #else carry = carry << (intDsize-1); # carry zu einem einzigen Bit machen dotimesC(count,count, { var uintD accu = *ptr; *ptr++ = (accu >> 1) | carry; carry = accu << (intDsize-1); }); return carry; #endif } # Schiebeschleife um i Bits nach rechts: # übertrag = shiftright_loop_up(ptr,count,i); # schiebt count (uintC>=0) Digits aufwärts von ptr um i Bits (0>i)+accu; *ptr++ = highD(accu); }); return lowD(accu); #else var uintD carry = 0; if (count > 0) { var uintC j = intDsize-i; dotimespC(count,count, { var uintD accu = *ptr; *ptr++ = (accu >> i) | carry; carry = accu << j; }); } return carry; #endif } # Schiebeschleife um i Bits nach rechts: # übertrag = shiftrightsigned_loop_up(ptr,count,i); # schiebt count (uintC>0) Digits aufwärts von ptr um i Bits (0>i; dotimespC(count,count, { # Die oberen i Bits von (uintD)accu bilden hier den Übertrag. accu = highlowDD_0(lowD(accu)); # Die oberen i Bits von (uintDD)accu bilden hier den Übertrag. accu = (highlowDD_0(*ptr)>>i)+accu; *ptr++ = highD(accu); }); return lowD(accu); #else var uintC j = intDsize-i; var uintD carry; { var uintD accu = *ptr; *ptr++ = (sintD)accu >> i; carry = accu << j; count--; } dotimesC(count,count, { var uintD accu = *ptr; *ptr++ = (accu >> i) | carry; carry = accu << j; }); return carry; #endif } # Schiebe- und Kopier-Schleife um i Bits nach rechts: # übertrag = shiftrightcopy_loop_up(sourceptr,destptr,count,i,carry); # kopiert count (uintC>=0) Digits aufwärts von sourceptr nach destptr # und schiebt sie dabei um i Bits (0>i; dotimesC(count,count, { # Die oberen i Bits von (uintD)accu bilden hier den Übertrag. accu = highlowDD_0(lowD(accu)); # Die oberen i Bits von (uintDD)accu bilden hier den Übertrag. accu = (highlowDD_0(*sourceptr++)>>i)+accu; *destptr++ = highD(accu); }); return lowD(accu); #else var uintC j = intDsize-i; carry = carry << j; dotimesC(count,count, { var uintD accu = *sourceptr++; *destptr++ = (accu >> i) | carry; carry = accu << j; }); return carry; #endif } #endif #ifndef MUL_LOOPS # Multiplikations-Einfachschleife: # Multipliziert eine UDS mit einem kleinen Digit und addiert ein kleines Digit. # mulusmall_loop_down(digit,ptr,len,newdigit) # multipliziert die UDS ptr[-len..-1] mit digit (>=2, <=36), # addiert dabei newdigit (>=0, =0, 0) # mit dem einzelnen digit # und legt das Ergebnis in der UDS destptr[-len-1..-1] ab. inline local void mulu_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len) { #if HAVE_DD var uintDD carry = 0; dotimespC(len,len, { # Hier ist carry=digit=0 oder 0 <= carry < digit. carry = carry + muluD(digit,*--sourceptr); # Hier ist carry=digit=0 oder 0 <= carry < 2^intDsize*digit. *--destptr = lowD(carry); carry = (uintDD)highD(carry); # carry := floor(carry/2^intDsize) < digit }); *--destptr = lowD(carry); #else var uintD carry = 0; dotimespC(len,len, { # Hier ist carry=digit=0 oder 0 <= carry < digit. var uintD hi; var uintD lo; muluD(digit,*--sourceptr,hi=,lo=); # Hier ist 0 <= 2^intDsize*hi + lo + carry < 2^intDsize*digit oder hi=lo=carry=digit=0. lo += carry; if (lo < carry) { hi += 1; } *--destptr = lo; carry = hi; }); *--destptr = carry; #endif } # Multiplikations-Einfachschleife mit Akkumulation: # Multipliziert eine UDS mit einem Digit und addiert das Ergebnis zu einer # zweiten UDS auf. # muluadd_loop_down(digit,sourceptr,destptr,len); # multipliziert die UDS sourceptr[-len..-1] (len>0) # mit dem einzelnen digit, legt das Ergebnis in der UDS destptr[-len..-1] # ab und liefert den weiteren Übertrag. inline local uintD muluadd_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len) { #if HAVE_DD var uintDD carry = 0; if (!(digit==0)) { dotimespC(len,len, { # Hier ist 0 <= carry <= digit. carry = carry + muluD(digit,*--sourceptr) + (uintDD)*--destptr; # Hier ist 0 <= carry <= 2^intDsize*digit + 2^intDsize-1. *destptr = lowD(carry); carry = (uintDD)highD(carry); # carry := floor(carry/2^intDsize) <= digit }); } return lowD(carry); #else var uintD carry = 0; if (!(digit==0)) { dotimespC(len,len, { # Hier ist 0 <= carry <= digit. var uintD hi; var uintD lo; muluD(digit,*--sourceptr,hi=,lo=); # Hier ist 0 <= 2^intDsize*hi + lo + carry + *--destptr <= 2^intDsize*digit+2^intDsize-1. lo += carry; if (lo < carry) { hi += 1; } carry = *--destptr; lo += carry; if (lo < carry) { hi += 1; } *destptr = lo; carry = hi; }); } return carry; #endif } # Multiplikations-Einfachschleife mit Diminution: # Multipliziert eine UDS mit einem Digit und subtrahiert das Ergebnis von # einer zweiten UDS. # mulusub_loop_down(digit,sourceptr,destptr,len); # multipliziert die UDS sourceptr[-len..-1] (len>0) mit dem einzelnen # digit, subtrahiert das Ergebnis von der UDS destptr[-len..-1] und liefert # den weiteren Übertrag (>=0, evtl. von destptr[-len-1] zu subtrahieren). inline local uintD mulusub_loop_down (uintD digit, const uintD* sourceptr, uintD* destptr, uintC len) { #if HAVE_DD var uintDD carry = 0; if (!(digit==0)) { dotimespC(len,len, { # Hier ist 0 <= carry <= digit. carry = carry + muluD(digit,*--sourceptr) + (uintD)(~(*--destptr)); # Hier ist 0 <= carry <= 2^intDsize*digit + 2^intDsize-1. *destptr = ~lowD(carry); carry = (uintDD)highD(carry); # carry := floor(carry/2^intDsize) <= digit # Hier ist 0 <= carry <= digit. }); return lowD(carry); } else return 0; # nichts zu subtrahieren -> kein Übertrag #else var uintD carry = 0; if (!(digit==0)) { dotimespC(len,len, { # Hier ist 0 <= carry <= digit. var uintD hi; var uintD lo; muluD(digit,*--sourceptr,hi=,lo=); # Hier ist 0 <= 2^intDsize*hi + lo + carry + ~(*--destptr) <= 2^intDsize*digit+2^intDsize-1. lo += carry; if (lo < carry) { hi += 1; } carry = *--destptr; *destptr = carry - lo; if (carry < lo) { hi += 1; } carry = hi; }); return carry; } else return 0; # nichts zu subtrahieren -> kein Übertrag #endif } #endif #ifndef DIV_LOOPS # Divisions-Einfachschleife: # Dividiert eine UDS durch ein Digit. # divu_loop_up(digit,ptr,len) # dividiert die UDS ptr[0..len-1] durch digit, # legt das Ergebnis in derselben UDS ab, und liefert den Rest (>=0, =0,