682 lines
11 KiB
C
682 lines
11 KiB
C
|
/*******************************************************************************
|
||
|
* *
|
||
|
* Copyright (c) Martin Nicolay, 22. Nov. 1988 *
|
||
|
* *
|
||
|
* Wenn diese (oder sinngemaess uebersetzte) Copyright-Angabe enthalten *
|
||
|
* bleibt, darf diese Source fuer jeden nichtkomerziellen Zweck weiter *
|
||
|
* verwendet werden. *
|
||
|
* *
|
||
|
* martin@trillian.megalon.de *
|
||
|
* *
|
||
|
*******************************************************************************/
|
||
|
|
||
|
#include "arith.h"
|
||
|
|
||
|
/*
|
||
|
* !!!!!!!!!!!!!!!!!!!!!!!!!!!! ACHTUNG !!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||
|
* Es findet keinerlei Ueberpruefung auf Bereichsueberschreitung
|
||
|
* statt. Alle Werte muessen natuerliche Zahlen aus dem Bereich
|
||
|
* 0 ... (MAXINT+1)^MAXLEN-1 sein.
|
||
|
*
|
||
|
*
|
||
|
* Bei keiner Funktion oder Hilsfunktion werden Annahmen getroffen,
|
||
|
* ueber die Verschiedenheit von Eingabe- & Ausgabe-Werten.
|
||
|
*
|
||
|
*
|
||
|
* Funktionen:
|
||
|
*
|
||
|
* a_add( s1, s2, d )
|
||
|
* NUMBER *s1,*s2,*d;
|
||
|
* *d = *s1 + *s2;
|
||
|
*
|
||
|
* a_assign( *d, *s )
|
||
|
* NUMBER *d,*s;
|
||
|
* *d = *s;
|
||
|
*
|
||
|
* int a_cmp( c1, c2 )
|
||
|
* NUMBER *c1,*c2;
|
||
|
* 1 : falls *c1 > *c2
|
||
|
* 0 : falls *c1 == *c2
|
||
|
* -1 : falls *c1 < *c2
|
||
|
*
|
||
|
* a_div( d1, d2, q, r )
|
||
|
* NUMBER *d1,*d2,*q,*r;
|
||
|
* *q = *d1 / *d2 Rest *r;
|
||
|
*
|
||
|
* a_div2( n )
|
||
|
* NUMBER *n;
|
||
|
* *n /= 2;
|
||
|
*
|
||
|
* a_ggt( a, b, f )
|
||
|
* NUMBER *a,*b,*f;
|
||
|
* *f = ( *a, *b );
|
||
|
*
|
||
|
* a_imult( n, m, d )
|
||
|
* NUMBER *n;
|
||
|
* INT m;
|
||
|
* NUMBER *d;
|
||
|
* *d = *n * m
|
||
|
*
|
||
|
* a_mult( m1, m2, d )
|
||
|
* NUMBER *m1,*m2,*d;
|
||
|
* *d = *m1 * *m2;
|
||
|
*
|
||
|
* a_sub( s1, s2, d )
|
||
|
* NUMBER *s1,*s2,*d;
|
||
|
* *d = *s1 - *s2;
|
||
|
*
|
||
|
* Modulare Funktionen
|
||
|
* m_init( n, o )
|
||
|
* NUMBER *n,*o;
|
||
|
* Initialsierung der Modularen Funktionen
|
||
|
* o != 0 : *o = alter Wert
|
||
|
*
|
||
|
* m_add( s1, s2, d )
|
||
|
* NUMBER *s1, *s2, *d;
|
||
|
* *d = *s1 + *s2;
|
||
|
*
|
||
|
* m_mult( m1, m2, d )
|
||
|
* NUMBER *m1,*m2,*d;
|
||
|
*
|
||
|
* m_exp( x, n, z )
|
||
|
* NUMBER *x,*n,*z;
|
||
|
* *z = *x exp *n;
|
||
|
*
|
||
|
*
|
||
|
* Hilfs-Funktionen:
|
||
|
*
|
||
|
* int n_bits( n, b )
|
||
|
* NUMBER *n;
|
||
|
* int b;
|
||
|
* return( unterste b Bits der Dualdarstellung von n)
|
||
|
*
|
||
|
* n_div( d1, z2, q, r )
|
||
|
* NUMBER *d1,z2[MAXBIT],*q,*r;
|
||
|
* *q = *d1 / z2[0] Rest *r;
|
||
|
* z2[i] = z2[0] * 2^i, i=0..MAXBIT-1
|
||
|
*
|
||
|
* int n_cmp( i1, i2, l )
|
||
|
* INT i1[l], i2[l];
|
||
|
* 1 : falls i1 > i2
|
||
|
* 0 : falls i1 == i2
|
||
|
* -1 : falls i1 < i2
|
||
|
*
|
||
|
* int n_mult( n, m, d, l)
|
||
|
* INT n[l], m, d[];
|
||
|
* d = m * n;
|
||
|
* return( sizeof(d) ); d.h. 'l' oder 'l+1'
|
||
|
*
|
||
|
* int n_sub( p1, p2, p3, l, lo )
|
||
|
* INT p1[l], p2[lo], p3[];
|
||
|
* p3 = p1 - p2;
|
||
|
* return( sizeof(p3) ); d.h. '<= min(l,lo)'
|
||
|
*
|
||
|
* int n_bitlen( n )
|
||
|
* NUMBER *n;
|
||
|
* return( sizeof(n) in bits )
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Konstante 1, 2
|
||
|
*/
|
||
|
NUMBER a_one = {
|
||
|
1,
|
||
|
{ (INT)1, },
|
||
|
};
|
||
|
|
||
|
NUMBER a_two = {
|
||
|
#if MAXINT == 1
|
||
|
2,
|
||
|
{ 0, (INT)1, },
|
||
|
#else
|
||
|
1,
|
||
|
{ (INT)2, },
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Vergleiche zwei INT arrays der Laenge l
|
||
|
*/
|
||
|
int n_cmp( i1, i2, l )
|
||
|
INT *i1,*i2;
|
||
|
{
|
||
|
i1 += (l-1); /* Pointer ans Ende */
|
||
|
i2 += (l-1);
|
||
|
|
||
|
for (;l--;)
|
||
|
if ( *i1-- != *i2-- )
|
||
|
return( i1[1] > i2[1] ? 1 : -1 );
|
||
|
|
||
|
return(0);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Vergleiche zwei NUMBER
|
||
|
*/
|
||
|
int a_cmp( c1, c2 )
|
||
|
NUMBER *c1,*c2;
|
||
|
{
|
||
|
int l;
|
||
|
/* bei verschiedener Laenge klar*/
|
||
|
if ( (l=c1->n_len) != c2->n_len)
|
||
|
return( l - c2->n_len);
|
||
|
|
||
|
/* vergleiche als arrays */
|
||
|
return( n_cmp( c1->n_part, c2->n_part, l) );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Zuweisung einer NUMBER (d = s)
|
||
|
*/
|
||
|
void a_assign( d, s )
|
||
|
NUMBER *d,*s;
|
||
|
{
|
||
|
int l;
|
||
|
|
||
|
if (s == d) /* nichts zu kopieren */
|
||
|
return;
|
||
|
|
||
|
if ((l=s->n_len))
|
||
|
memcpy( d->n_part, s->n_part, sizeof(INT)*l);
|
||
|
|
||
|
d->n_len = l;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Addiere zwei NUMBER (d = s1 + s2)
|
||
|
*/
|
||
|
void a_add( s1, s2, d )
|
||
|
NUMBER *s1,*s2,*d;
|
||
|
{
|
||
|
int l,lo,ld,same;
|
||
|
register LONG sum;
|
||
|
register INT *p1,*p2,*p3;
|
||
|
register INT b;
|
||
|
|
||
|
/* setze s1 auch die groessere Zahl */
|
||
|
l = s1->n_len;
|
||
|
if ( (l=s1->n_len) < s2->n_len ) {
|
||
|
NUMBER *tmp = s1;
|
||
|
|
||
|
s1 = s2;
|
||
|
s2 = tmp;
|
||
|
|
||
|
l = s1->n_len;
|
||
|
}
|
||
|
|
||
|
ld = l;
|
||
|
lo = s2->n_len;
|
||
|
p1 = s1->n_part;
|
||
|
p2 = s2->n_part;
|
||
|
p3 = d->n_part;
|
||
|
same = (s1 == d);
|
||
|
sum = 0;
|
||
|
|
||
|
while (l --) {
|
||
|
if (lo) { /* es ist noch was von s2 da */
|
||
|
lo--;
|
||
|
b = *p2++;
|
||
|
}
|
||
|
else
|
||
|
b = 0; /* ansonten 0 nehmen */
|
||
|
|
||
|
sum += (LONG)*p1++ + (LONG)b;
|
||
|
*p3++ = TOINT(sum);
|
||
|
|
||
|
if (sum > (LONG)MAXINT) { /* carry merken */
|
||
|
sum = 1;
|
||
|
}
|
||
|
else
|
||
|
sum = 0;
|
||
|
|
||
|
if (!lo && same && !sum) /* nichts mehr zu tuen */
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (sum) { /* letztes carry beruecksichtigen */
|
||
|
ld++;
|
||
|
*p3 = sum;
|
||
|
}
|
||
|
|
||
|
d->n_len = ld; /* Laenge setzen */
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Subtrahiere zwei INT arrays. return( Laenge Ergebniss )
|
||
|
* l == Laenge p1
|
||
|
* lo== Laenge p3
|
||
|
*/
|
||
|
int n_sub( p1, p2, p3, l, lo )
|
||
|
INT *p1,*p2,*p3;
|
||
|
int l,lo;
|
||
|
{
|
||
|
int ld,lc,same;
|
||
|
int over = 0;
|
||
|
register LONG dif;
|
||
|
LONG a,b;
|
||
|
|
||
|
same = (p1 == p3); /* frueher Abbruch moeglich */
|
||
|
|
||
|
for (lc=1, ld=0; l--; lc++) {
|
||
|
a = (LONG)*p1++;
|
||
|
if (lo) { /* ist noch was von p2 da ? */
|
||
|
lo--;
|
||
|
b = (LONG)*p2++;
|
||
|
}
|
||
|
else
|
||
|
b=0; /* ansonten 0 nehmen */
|
||
|
|
||
|
if (over) /* frueherer Overflow */
|
||
|
b++;
|
||
|
if ( b > a ) { /* jetzt Overflow ? */
|
||
|
over = 1;
|
||
|
dif = (MAXINT +1) + a;
|
||
|
}
|
||
|
else {
|
||
|
over = 0;
|
||
|
dif = a;
|
||
|
}
|
||
|
dif -= b;
|
||
|
*p3++ = (INT)dif;
|
||
|
|
||
|
if (dif) /* Teil != 0 : Laenge neu */
|
||
|
ld = lc;
|
||
|
if (!lo && same && !over) { /* nichts mehr zu tuen */
|
||
|
if (l > 0) /* Laenge korrigieren */
|
||
|
ld = lc + l;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return( ld );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Subtrahiere zwei NUMBER (d= s1 - s2)
|
||
|
*/
|
||
|
void a_sub( s1, s2, d )
|
||
|
NUMBER *s1,*s2,*d;
|
||
|
{
|
||
|
d->n_len = n_sub( s1->n_part, s2->n_part, d->n_part
|
||
|
,s1->n_len, s2->n_len );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Mulitipliziere INT array der Laenge l mit einer INT (d = n * m)
|
||
|
* return neue Laenge
|
||
|
*/
|
||
|
int n_mult( n, m, d, l)
|
||
|
register INT *n;
|
||
|
register INT m;
|
||
|
INT *d;
|
||
|
{
|
||
|
int i;
|
||
|
register LONG mul;
|
||
|
|
||
|
for (i=l,mul=0; i; i--) {
|
||
|
mul += (LONG)m * (LONG)*n++;
|
||
|
*d++ = TOINT(mul);
|
||
|
mul = DIVMAX1( mul );
|
||
|
}
|
||
|
|
||
|
if (mul) { /* carry ? */
|
||
|
l++;
|
||
|
*d = mul;
|
||
|
}
|
||
|
|
||
|
return( l );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Mulitipliziere eine NUMBER mit einer INT (d = n * m)
|
||
|
*/
|
||
|
void a_imult( n, m, d )
|
||
|
NUMBER *n;
|
||
|
INT m;
|
||
|
NUMBER *d;
|
||
|
{
|
||
|
if (m == 0)
|
||
|
d->n_len=0;
|
||
|
else if (m == 1)
|
||
|
a_assign( d, n );
|
||
|
else
|
||
|
d->n_len = n_mult( n->n_part, m, d->n_part, n->n_len );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Multipliziere zwei NUMBER (d = m1 * m2)
|
||
|
*/
|
||
|
void a_mult( m1, m2, d )
|
||
|
NUMBER *m1,*m2,*d;
|
||
|
{
|
||
|
static INT id[ MAXLEN ]; /* Zwischenspeicher */
|
||
|
register INT *vp; /* Pointer darin */
|
||
|
register LONG sum; /* Summe fuer jede Stelle */
|
||
|
register LONG tp1; /* Zwischenspeicher fuer m1 */
|
||
|
register INT *p2;
|
||
|
INT *p1;
|
||
|
int l1,l2,ld,lc,l,i,j;
|
||
|
|
||
|
l1 = m1->n_len;
|
||
|
l2 = m2->n_len;
|
||
|
l = l1 + l2;
|
||
|
if (l >= MAXLEN)
|
||
|
abort();
|
||
|
|
||
|
for (i=l, vp=id; i--;)
|
||
|
*vp++ = 0;
|
||
|
|
||
|
/* ohne Uebertrag in Zwischenspeicher multiplizieren */
|
||
|
for ( p1 = m1->n_part, i=0; i < l1 ; i++, p1++ ) {
|
||
|
|
||
|
tp1 = (LONG)*p1;
|
||
|
vp = &id[i];
|
||
|
sum = 0;
|
||
|
for ( p2 = m2->n_part, j = l2; j--;) {
|
||
|
sum += (LONG)*vp + (tp1 * (LONG)*p2++);
|
||
|
*vp++ = TOINT( sum );
|
||
|
sum = DIVMAX1(sum);
|
||
|
}
|
||
|
*vp++ += (INT)sum;
|
||
|
}
|
||
|
|
||
|
/* jetzt alle Uebertraege beruecksichtigen */
|
||
|
ld = 0;
|
||
|
for (lc=0, vp=id, p1=d->n_part; lc++ < l;) {
|
||
|
if (( *p1++ = *vp++ ))
|
||
|
ld = lc;
|
||
|
}
|
||
|
|
||
|
d->n_len = ld;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Dividiere Zwei NUMBER mit Rest (q= d1 / z2[0] Rest r)
|
||
|
* z2[i] = z2[0] * 2^i, i=0..MAXBIT-1
|
||
|
* r = 0 : kein Rest
|
||
|
* q = 0 : kein Quotient
|
||
|
*/
|
||
|
void n_div( d1, z2, q, r )
|
||
|
NUMBER *d1,*z2,*q,*r;
|
||
|
{
|
||
|
static NUMBER dummy_rest; /* Dummy Variable, falls r = 0 */
|
||
|
static NUMBER dummy_quot; /* Dummy Variable, falla q = 0 */
|
||
|
INT *i1,*i1e,*i3;
|
||
|
int l2,ld,l,lq;
|
||
|
#if MAXINT != 1
|
||
|
INT z;
|
||
|
int pw,l2t;
|
||
|
#endif
|
||
|
|
||
|
if (!z2->n_len)
|
||
|
abort();
|
||
|
|
||
|
if (!r)
|
||
|
r = &dummy_rest;
|
||
|
if (!q)
|
||
|
q = &dummy_quot;
|
||
|
|
||
|
a_assign( r, d1 ); /* Kopie von d1 in den Rest */
|
||
|
|
||
|
l2= z2->n_len; /* Laenge von z2[0] */
|
||
|
l = r->n_len - l2; /* Laenge des noch ''rechts'' liegenden
|
||
|
Stuecks von d1 */
|
||
|
lq= l +1; /* Laenge des Quotienten */
|
||
|
i3= q->n_part + l;
|
||
|
i1= r->n_part + l;
|
||
|
ld = l2; /* aktuelle Laenge des ''Vergleichsstuecks''
|
||
|
von d1 */
|
||
|
i1e= i1 + (ld-1);
|
||
|
|
||
|
for (; l >= 0; ld++, i1--, i1e--, l--, i3--) {
|
||
|
*i3 = 0;
|
||
|
|
||
|
if (ld == l2 && ! *i1e) {
|
||
|
ld--;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ( ld > l2 || (ld == l2 && n_cmp( i1, z2->n_part, l2) >= 0 ) ) {
|
||
|
#if MAXINT != 1
|
||
|
/* nach 2er-Potenzen zerlegen */
|
||
|
for (pw=MAXBIT-1, z=(INT)HIGHBIT; pw >= 0; pw--, z /= 2) {
|
||
|
if ( ld > (l2t= z2[pw].n_len)
|
||
|
|| (ld == l2t
|
||
|
&& n_cmp( i1, z2[pw].n_part, ld) >= 0) ) {
|
||
|
ld = n_sub( i1, z2[pw].n_part, i1, ld, l2t );
|
||
|
(*i3) += z;
|
||
|
}
|
||
|
}
|
||
|
#else
|
||
|
/* bei MAXINT == 1 alles viel einfacher */
|
||
|
ld = n_sub( i1, z2->n_part, i1, ld, l2 );
|
||
|
(*i3) ++;
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Korrektur, falls l von Anfang an Negativ war */
|
||
|
l ++;
|
||
|
lq -= l;
|
||
|
ld += l;
|
||
|
|
||
|
if (lq>0 && !q->n_part[lq -1]) /* evtl. Laenge korrigieren */
|
||
|
lq--;
|
||
|
|
||
|
q->n_len = lq;
|
||
|
r->n_len = ld -1;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Dividiere Zwei NUMBER mit Rest (q= d1 / z2[0] Rest r)
|
||
|
* z2[i] = z2[0] * 2^i, i=0..MAXBIT-1
|
||
|
* r = 0 : kein Rest
|
||
|
* q = 0 : kein Quotient
|
||
|
*/
|
||
|
void a_div( d1, d2, q, r )
|
||
|
NUMBER *d1,*d2,*q,*r;
|
||
|
{
|
||
|
#if MAXINT != 1
|
||
|
NUMBER z2[MAXBIT];
|
||
|
INT z;
|
||
|
int i;
|
||
|
|
||
|
a_assign( &z2[0], d2 );
|
||
|
for (i=1,z=2; i < MAXBIT; i++, z *= 2)
|
||
|
a_imult( d2, z, &z2[i] );
|
||
|
|
||
|
d2 = z2;
|
||
|
#endif
|
||
|
|
||
|
n_div( d1, d2, q, r );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Dividiere eine NUMBER durch 2
|
||
|
*/
|
||
|
void a_div2( n )
|
||
|
NUMBER *n;
|
||
|
{
|
||
|
#if MAXBIT == LOWBITS
|
||
|
register INT *p;
|
||
|
int i;
|
||
|
|
||
|
#if MAXINT != 1
|
||
|
register INT h;
|
||
|
register int c;
|
||
|
|
||
|
c=0;
|
||
|
i= n->n_len;
|
||
|
p= &n->n_part[i-1];
|
||
|
|
||
|
for (; i--;) {
|
||
|
if (c) {
|
||
|
c = (h= *p) & 1;
|
||
|
h /= 2;
|
||
|
h |= HIGHBIT;
|
||
|
}
|
||
|
else {
|
||
|
c = (h= *p) & 1;
|
||
|
h /= 2;
|
||
|
}
|
||
|
|
||
|
*p-- = h;
|
||
|
}
|
||
|
|
||
|
if ( (i= n->n_len) && n->n_part[i-1] == 0 )
|
||
|
n->n_len = i-1;
|
||
|
|
||
|
#else /* MAXBIT != 1 */
|
||
|
p = n->n_part;
|
||
|
i = n->n_len;
|
||
|
|
||
|
if (i) {
|
||
|
n->n_len = i-1;
|
||
|
for (; --i ; p++)
|
||
|
p[0] = p[1];
|
||
|
}
|
||
|
#endif /* MAXBIT != 1 */
|
||
|
#else /* MAXBIT == LOWBITS */
|
||
|
a_div( n, &a_two, n, NUM0P );
|
||
|
#endif /* MAXBIT == LOWBITS */
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* MODULO-FUNKTIONEN
|
||
|
*/
|
||
|
|
||
|
static NUMBER mod_z2[ MAXBIT ];
|
||
|
|
||
|
/*
|
||
|
* Init
|
||
|
*/
|
||
|
void m_init( n, o )
|
||
|
NUMBER *n,*o;
|
||
|
{
|
||
|
INT z;
|
||
|
int i;
|
||
|
|
||
|
if (o)
|
||
|
a_assign( o, &mod_z2[0] );
|
||
|
|
||
|
if (! a_cmp( n, &mod_z2[0] ) )
|
||
|
return;
|
||
|
|
||
|
for (i=0,z=1; i < MAXBIT; i++, z *= 2)
|
||
|
a_imult( n, z, &mod_z2[i] );
|
||
|
}
|
||
|
|
||
|
void m_add( s1, s2, d )
|
||
|
NUMBER *s1, *s2, *d;
|
||
|
{
|
||
|
a_add( s1, s2, d );
|
||
|
if (a_cmp( d, mod_z2 ) >= 0)
|
||
|
a_sub( d, mod_z2, d );
|
||
|
}
|
||
|
|
||
|
void m_mult( m1, m2, d )
|
||
|
NUMBER *m1,*m2,*d;
|
||
|
{
|
||
|
a_mult( m1, m2, d );
|
||
|
n_div( d, mod_z2, NUM0P, d );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Restklassen Exponent
|
||
|
*/
|
||
|
void m_exp( x, n, z )
|
||
|
NUMBER *x,*n,*z;
|
||
|
{
|
||
|
NUMBER xt,nt;
|
||
|
|
||
|
a_assign( &nt, n );
|
||
|
a_assign( &xt, x );
|
||
|
a_assign( z, &a_one );
|
||
|
|
||
|
while (nt.n_len) {
|
||
|
while ( ! (nt.n_part[0] & 1) ) {
|
||
|
m_mult( &xt, &xt, &xt );
|
||
|
a_div2( &nt );
|
||
|
}
|
||
|
m_mult( &xt, z, z );
|
||
|
a_sub( &nt, &a_one, &nt );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* GGT
|
||
|
*/
|
||
|
void a_ggt( a, b, f )
|
||
|
NUMBER *a,*b,*f;
|
||
|
{
|
||
|
NUMBER t[2];
|
||
|
int at,bt, tmp;
|
||
|
|
||
|
a_assign( &t[0], a ); at= 0;
|
||
|
a_assign( &t[1], b ); bt= 1;
|
||
|
|
||
|
if ( a_cmp( &t[at], &t[bt] ) < 0 ) {
|
||
|
tmp= at; at= bt; bt= tmp;
|
||
|
}
|
||
|
/* euklidischer Algorithmus */
|
||
|
while ( t[bt].n_len ) {
|
||
|
a_div( &t[at], &t[bt], NUM0P, &t[at] );
|
||
|
tmp= at; at= bt; bt= tmp;
|
||
|
}
|
||
|
|
||
|
a_assign( f, &t[at] );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* die untersten b bits der Dualdarstellung von n
|
||
|
* die bits muessen in ein int passen
|
||
|
*/
|
||
|
int n_bits(n,b)
|
||
|
NUMBER *n;
|
||
|
{
|
||
|
INT *p;
|
||
|
int l;
|
||
|
unsigned r;
|
||
|
int m = (1<<b) -1;
|
||
|
|
||
|
if ( n->n_len == 0)
|
||
|
return(0);
|
||
|
|
||
|
if (LOWBITS >= b)
|
||
|
return( n->n_part[0] & m );
|
||
|
|
||
|
#if LOWBITS != 0
|
||
|
l = (b-1) / LOWBITS;
|
||
|
#else
|
||
|
l = n->n_len -1;
|
||
|
#endif
|
||
|
for (p= &n->n_part[l],r=0; l-- >= 0 && b > 0; b-= LOWBITS, p--) {
|
||
|
r = MULMAX1( r );
|
||
|
r += (unsigned)*p;
|
||
|
}
|
||
|
|
||
|
return( r & m );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Anzahl der bits von n bei Dualdarstellung
|
||
|
*/
|
||
|
int n_bitlen( n )
|
||
|
NUMBER *n;
|
||
|
{
|
||
|
NUMBER b;
|
||
|
int i;
|
||
|
|
||
|
a_assign( &b, &a_one );
|
||
|
|
||
|
for (i=0; a_cmp( &b, n ) <= 0; a_mult( &b, &a_two, &b ), i++)
|
||
|
;
|
||
|
|
||
|
return(i);
|
||
|
}
|