File: [local] / OpenXM_contrib2 / asir2000 / engine / Z.c (download)
Revision 1.9, Sun Feb 18 05:36:27 2007 UTC (17 years, 7 months ago) by ohara
Branch: MAIN
CVS Tags: DEB_REL_1_2_3-9 Changes since 1.8: +2 -2
lines
Fixed for MacOS X. This work is temporary.
Risa/Asir cannot be built on MacOS X 10.4 (i386).
TODO: Upgrade gc6.5 to 6.8.
|
#include "ca.h"
#include "base.h"
#include "inline.h"
#if defined(__GNUC__)
#define INLINE inline
#elif defined(VISUAL)
#define INLINE __inline
#else
#define INLINE
#endif
INLINE void _addz(Z n1,Z n2,Z nr);
INLINE void _subz(Z n1,Z n2,Z nr);
INLINE void _mulz(Z n1,Z n2,Z nr);
int _addz_main(unsigned int *m1,int d1,unsigned int *m2,int d2,unsigned int *mr);
int _subz_main(unsigned int *m1,int d1,unsigned int *m2,int d2,unsigned int *mr);
/* immediate int -> Z */
#define UTOZ(c,n) (n)=(!((unsigned int)(c))?0:(((unsigned int)(c))<=IMM_MAX?((Z)((((unsigned int)(c))<<1)|1)):utoz((unsigned int)(c))))
#define STOZ(c,n) (n)=(!((int)(c))?0:(((int)(c))>=IMM_MIN&&((int)(c))<=IMM_MAX?((Z)((((int)(c))<<1)|1)):stoz((int)(c))))
/* immediate Z ? */
#define IS_IMM(c) (((unsigned int)c)&1)
/* Z can be conver to immediate ? */
#define IS_SZ(n) (((SL(n) == 1)||(SL(n)==-1))&&BD(n)[0]<=IMM_MAX)
/* Z -> immediate Z */
#define SZTOZ(n,z) (z)=(Z)(SL(n)<0?(((-BD(n)[0])<<1)|1):(((BD(n)[0])<<1)|1))
/* Z -> immediate int */
#define ZTOS(c) (((int)(c))>>1)
int uniz(Z a)
{
if ( IS_IMM(a) && ZTOS(a) == 1 ) return 1;
else return 0;
}
int cmpz(Z a,Z b)
{
int *ma,*mb;
int sa,sb,da,db,ca,cb,i;
if ( !a )
return -sgnz(b);
else if ( !b )
return sgnz(a);
else {
sa = sgnz(a); sb = sgnz(b);
if ( sa > sb ) return 1;
else if ( sa < sb ) return -1;
else if ( IS_IMM(a) )
if ( IS_IMM(b) ) {
ca = ZTOS(a); cb = ZTOS(b);
if ( ca > cb ) return sa;
else if ( ca < cb ) return -sa;
else return 0;
} else
return -sa;
else if ( IS_IMM(b) )
return sa;
else {
da = SL(a)*sa; db = SL(b)*sa;
if ( da > db ) return sa;
else if ( da < db ) return -sa;
else {
for ( i = da-1, ma = BD(a)+i, mb = BD(b)+i; i >= 0; i-- )
if ( *ma > *mb ) return sa;
else if ( *ma < *mb ) return -sa;
return 0;
}
}
}
}
Z stoz(int c)
{
Z z;
z = ZALLOC(1);
if ( c < 0 ) {
SL(z) = -1; BD(z)[0] = -c;
} else {
SL(z) = 1; BD(z)[0] = c;
}
return z;
}
Z utoz(unsigned int c)
{
Z z;
z = ZALLOC(1);
SL(z) = 1; BD(z)[0] = c;
return z;
}
Z simpz(Z n)
{
Z n1;
if ( !n ) return 0;
else if ( IS_IMM(n) ) return n;
else if ( IS_SZ(n) ) {
SZTOZ(n,n1); return n1;
} else
return n;
}
int sgnz(Z n)
{
if ( !n ) return 0;
else if ( IS_IMM(n) ) return ZTOS(n)>0?1:-1;
else if ( SL(n) < 0 ) return -1;
else return 1;
}
z_mag(Z n)
{
int c,i;
if ( !n ) return 0;
else if ( IS_IMM(n) ) {
c = ZTOS(n);
if ( c < 0 ) c = -c;
for ( i = 0; c; c >>= 1, i++ );
return i;
}
else return n_bits((N)n);
}
Z qtoz(Q n)
{
Z r,t;
int c;
if ( !n ) return 0;
else if ( !INT(n) )
error("qtoz : invalid input");
else {
t = (Z)NM(n);
if ( IS_SZ(t) ) {
c = SGN(n) < 0 ? -BD(t)[0] : BD(t)[0];
STOZ(c,r);
} else {
r = dupz((Z)t);
if ( SGN(n) < 0 ) SL(r) = -SL(r);
}
return r;
}
}
Q ztoq(Z n)
{
Q r;
Z nm;
int sgn,c;
if ( !n ) return 0;
else if ( IS_IMM(n) ) {
c = ZTOS(n);
STOQ(c,r);
return r;
} else {
nm = dupz(n);
if ( SL(nm) < 0 ) {
sgn = -1;
SL(nm) = -SL(nm);
} else
sgn = 1;
NTOQ((N)nm,sgn,r);
return r;
}
}
Z dupz(Z n)
{
Z r;
int sd,i;
if ( !n ) return 0;
else if ( IS_IMM(n) ) return n;
else {
if ( (sd = SL(n)) < 0 ) sd = -sd;
r = ZALLOC(sd);
SL(r) = SL(n);
for ( i = 0; i < sd; i++ ) BD(r)[i] = BD(n)[i];
return r;
}
}
Z chsgnz(Z n)
{
Z r;
int c;
if ( !n ) return 0;
else if ( IS_IMM(n) ) {
c = -ZTOS(n);
STOZ(c,r);
return r;
} else {
r = dupz(n);
SL(r) = -SL(r);
return r;
}
}
Z absz(Z n)
{
Z r;
int c;
if ( !n ) return 0;
else if ( sgnz(n) > 0 )
return n;
else
return chsgnz(n);
}
Z addz(Z n1,Z n2)
{
int d1,d2,d,c;
Z r,r1;
struct oZ t;
if ( !n1 ) return dupz(n2);
else if ( !n2 ) return dupz(n1);
else if ( IS_IMM(n1) ) {
if ( IS_IMM(n2) ) {
c = ZTOS(n1)+ZTOS(n2);
STOZ(c,r);
} else {
c = ZTOS(n1);
if ( c < 0 ) {
t.p = -1; t.b[0] = -c;
} else {
t.p = 1; t.b[0] = c;
}
if ( (d2 = SL(n2)) < 0 ) d2 = -d2;
r = ZALLOC(d2+1);
_addz(&t,n2,r);
if ( !SL(r) ) r = 0;
}
} else if ( IS_IMM(n2) ) {
c = ZTOS(n2);
if ( c < 0 ) {
t.p = -1; t.b[0] = -c;
} else {
t.p = 1; t.b[0] = c;
}
if ( (d1 = SL(n1)) < 0 ) d1 = -d1;
r = ZALLOC(d1+1);
_addz(n1,&t,r);
if ( !SL(r) ) r = 0;
} else {
if ( (d1 = SL(n1)) < 0 ) d1 = -d1;
if ( (d2 = SL(n2)) < 0 ) d2 = -d2;
d = MAX(d1,d2)+1;
r = ZALLOC(d);
_addz(n1,n2,r);
if ( !SL(r) ) r = 0;
}
if ( r && !((int)r&1) && IS_SZ(r) ) {
SZTOZ(r,r1); r = r1;
}
return r;
}
Z subz(Z n1,Z n2)
{
int d1,d2,d,c;
Z r,r1;
struct oZ t;
if ( !n1 )
return chsgnz(n2);
else if ( !n2 ) return n1;
else if ( IS_IMM(n1) ) {
if ( IS_IMM(n2) ) {
c = ZTOS(n1)-ZTOS(n2);
STOZ(c,r);
} else {
c = ZTOS(n1);
if ( c < 0 ) {
t.p = -1; t.b[0] = -c;
} else {
t.p = 1; t.b[0] = c;
}
if ( (d2 = SL(n2)) < 0 ) d2 = -d2;
r = ZALLOC(d2+1);
_subz(&t,n2,r);
if ( !SL(r) ) r = 0;
}
} else if ( IS_IMM(n2) ) {
c = ZTOS(n2);
if ( c < 0 ) {
t.p = -1; t.b[0] = -c;
} else {
t.p = 1; t.b[0] = c;
}
if ( (d1 = SL(n1)) < 0 ) d1 = -d1;
r = ZALLOC(d1+1);
_subz(n1,&t,r);
if ( !SL(r) ) r = 0;
} else {
if ( (d1 = SL(n1)) < 0 ) d1 = -d1;
if ( (d2 = SL(n2)) < 0 ) d2 = -d2;
d = MAX(d1,d2)+1;
r = ZALLOC(d);
_subz(n1,n2,r);
if ( !SL(r) ) r = 0;
}
if ( r && !((int)r&1) && IS_SZ(r) ) {
SZTOZ(r,r1); r = r1;
}
return r;
}
Z mulz(Z n1,Z n2)
{
int d1,d2,sgn,i;
int c1,c2;
unsigned int u1,u2,u,l;
Z r;
if ( !n1 || !n2 ) return 0;
if ( IS_IMM(n1) ) {
c1 = ZTOS(n1);
if ( IS_IMM(n2) ) {
c2 = ZTOS(n2);
if ( c1 == 1 )
return n2;
else if ( c1 == -1 )
return chsgnz(n2);
else if ( c2 == 1 )
return n1;
else if ( c2 == -1 )
return chsgnz(n1);
else {
sgn = 1;
if ( c1 < 0 ) { c1 = -c1; sgn = -sgn; }
if ( c2 < 0 ) { c2 = -c2; sgn = -sgn; }
u1 = (unsigned int)c1; u2 = (unsigned int)c2;
DM(u1,u2,u,l);
if ( !u ) {
UTOZ(l,r);
} else {
r = ZALLOC(2); SL(r) = 2; BD(r)[1] = u; BD(r)[0] = l;
}
}
} else {
sgn = 1;
if ( c1 < 0 ) { c1 = -c1; sgn = -sgn; }
u1 = (unsigned int)c1;
if ( (d2 = SL(n2)) < 0 ) { sgn = -sgn; d2 = -d2; }
r = ZALLOC(d2+1);
for ( i = d2; i >= 0; i-- ) BD(r)[i] = 0;
muln_1(BD(n2),d2,u1,BD(r));
SL(r) = BD(r)[d2]?d2+1:d2;
}
} else if ( IS_IMM(n2) ) {
c2 = ZTOS(n2);
if ( c2 == 1 )
return n1;
else if ( c2 == -1 )
return chsgnz(n1);
sgn = 1;
if ( c2 < 0 ) { sgn = -sgn; c2 = -c2; }
u2 = (unsigned int)c2;
if ( (d1 = SL(n1)) < 0 ) { sgn = -sgn; d1 = -d1; }
r = ZALLOC(d1+1);
for ( i = d1; i >= 0; i-- ) BD(r)[i] = 0;
muln_1(BD(n1),d1,u2,BD(r));
SL(r) = BD(r)[d1]?d1+1:d1;
} else {
sgn = 1;
if ( (d1 = SL(n1)) < 0 ) d1 = -d1;
if ( (d2 = SL(n2)) < 0 ) d2 = -d2;
r = ZALLOC(d1+d2);
_mulz(n1,n2,r);
}
if ( sgn < 0 ) r = chsgnz(r);
return r;
}
/* kokokara */
#if 0
Z divsz(Z n1,Z n2)
{
int sgn,d1,d2;
Z q;
if ( !n2 ) error("divsz : division by 0");
if ( !n1 ) return 0;
if ( IS_IMM(n1) ) {
if ( !IS_IMM(n2) )
error("divsz : cannot happen");
c = ZTOS(n1)/ZTOS(n2);
STOZ(c,q);
return q;
}
if ( IS_IMM(n2) ) {
sgn = 1;
u2 = ZTOS(n2); if ( u2 < 0 ) { sgn = -sgn; u2 = -u2; }
diviz(n1,u2,&q);
if ( sgn < 0 ) SL(q) = -SL(q);
return q;
}
sgn = 1;
if ( (d2 = SL(n2)) < 0 ) { sgn = -sgn; d2 = -d2; }
if ( d2 == 1 ) {
diviz(n1,BD(u2)[0],&q);
if ( sgn < 0 ) SL(q) = -SL(q);
return q;
}
if ( (d1 = SL(n1)) < 0 ) { sgn = -sgn; d1 = -d1; }
if ( d1 < d2 ) error("divsz : cannot happen");
return q;
}
#endif
/* XXX */
Z divz(Z n1,Z n2,Z *r)
{
int s1,s2;
Q t1,t2,qq,rq;
N qn,rn;
if ( !n1 ) {
*r = 0; return 0;
}
if ( !n2 )
error("divz : division by 0");
t1 = ztoq(n1); t2 = ztoq(n2);
s1 = sgnz(n1); s2 = sgnz(n2);
/* n1 = qn*SGN(n1)*SGN(n2)*n2+SGN(n1)*rn */
divn(NM(t1),NM(t2),&qn,&rn);
NTOQ(qn,s1*s2,qq);
NTOQ(rn,s1,rq);
*r = qtoz(rq);
return qtoz(qq);
}
Z divsz(Z n1,Z n2)
{
int s1,s2;
Q t1,t2,qq;
N qn;
if ( !n1 )
return 0;
if ( !n2 )
error("divsz : division by 0");
t1 = ztoq(n1); t2 = ztoq(n2);
s1 = sgnz(n1); s2 = sgnz(n2);
/* n1 = qn*SGN(n1)*SGN(n2)*n2 */
divsn(NM(t1),NM(t2),&qn);
NTOQ(qn,s1*s2,qq);
return qtoz(qq);
}
int gcdimm(int c1,int c2)
{
int r;
if ( !c1 ) return c2;
else if ( !c2 ) return c1;
while ( 1 ) {
r = c1%c2;
if ( !r ) return c2;
c1 = c2; c2 = r;
}
}
Z gcdz(Z n1,Z n2)
{
int c1,c2,g;
Z gcd,r;
N gn;
if ( !n1 ) return n2;
else if ( !n2 ) return n1;
if ( IS_IMM(n1) ) {
c1 = ZTOS(n1);
if ( c1 < 0 ) c1 = -c1;
if ( IS_IMM(n2) )
c2 = ZTOS(n2);
else
c2 = remzi(n2,c1>0?c1:-c1);
if ( c2 < 0 ) c2 = -c2;
g = gcdimm(c1,c2);
STOZ(g,gcd);
return gcd;
} else if ( IS_IMM(n2) ) {
c2 = ZTOS(n2);
if ( c2 < 0 ) c2 = -c2;
c1 = remzi(n1,c2>0?c2:-c2);
if ( c1 < 0 ) c1 = -c1;
g = gcdimm(c1,c2);
STOZ(g,gcd);
return gcd;
} else {
n1 = dupz(n1);
if ( SL(n1) < 0 ) SL(n1) = -SL(n1);
n2 = dupz(n2);
if ( SL(n2) < 0 ) SL(n2) = -SL(n2);
gcdn((N)n1,(N)n2,&gn);
gcd = (Z)gn;
if ( IS_SZ(gcd) ) {
SZTOZ(gcd,r); gcd = r;
}
return gcd;
}
}
int remzi(Z n,int m)
{
unsigned int *x;
unsigned int t,r;
int i,c;
if ( !n ) return 0;
if ( IS_IMM(n) ) {
c = ZTOS(n)%m;
if ( c < 0 ) c += m;
return c;
}
i = SL(n);
if ( i < 0 ) i = -i;
for ( i--, x = BD(n)+i, r = 0; i >= 0; i--, x-- ) {
#if defined(sparc)
r = dsa(m,r,*x);
#else
DSAB(m,r,*x,t,r);
#endif
}
if ( r && SL(n) < 0 )
r = m-r;
return r;
}
Z gcdz_cofactor(Z n1,Z n2,Z *c1,Z *c2)
{
Z gcd;
gcd = gcdz(n1,n2);
*c1 = divsz(n1,gcd);
*c2 = divsz(n2,gcd);
return gcd;
}
#if 0
Z estimate_array_gcdz(Z *b,int n)
{
int m,i,j,sd;
Z *a;
Z s,t;
a = (Z *)ALLOCA(n*sizeof(Z));
for ( i = j = 0; i < n; i++ ) if ( b[i] ) a[j++] = b[i];
n = j;
if ( !n ) return 0;
if ( n == 1 ) return a[0];
m = n/2;
for ( i = 0, s = 0; i < m; i++ ) {
if ( !a[i] ) continue;
else s = (SL(a[i])<0)?subz(s,a[i]):addz(s,a[i]);
}
for ( t = 0; i < n; i++ ) {
if ( !a[i] ) continue;
else t = (SL(a[i])<0)?subz(t,a[i]):addz(t,a[i]);
}
return gcdz(s,t);
}
Z array_gcdz(Z *b,int n)
{
int m,i,j,sd;
Z *a;
Z gcd;
a = (Z *)ALLOCA(n*sizeof(Z));
for ( i = j = 0; i < n; i++ ) if ( b[i] ) a[j++] = b[i];
n = j;
if ( !n ) return 0;
if ( n == 1 ) return a[0];
gcd = a[0];
for ( i = 1; i < n; i++ )
gcd = gcdz(gcd,a[i]);
return gcd;
}
#endif
void _copyz(Z n1,Z n2)
{
int n,i;
if ( !n1 || !SL(n1) ) SL(n2) = 0;
else {
n = SL(n2) = SL(n1);
if ( n < 0 ) n = -n;
for ( i = 0; i < n; i++ ) BD(n2)[i] = BD(n1)[i];
}
}
void _addz(Z n1,Z n2,Z nr)
{
int d1,d2;
if ( !n1 || !SL(n1) ) _copyz(n2,nr);
else if ( !n2 || !SL(n2) ) _copyz(n1,nr);
else if ( (d1=SL(n1)) > 0 )
if ( (d2=SL(n2)) > 0 )
SL(nr) = _addz_main(BD(n1),d1,BD(n2),d2,BD(nr));
else
SL(nr) = _subz_main(BD(n1),d1,BD(n2),-d2,BD(nr));
else if ( (d2=SL(n2)) > 0 )
SL(nr) = _subz_main(BD(n2),d2,BD(n1),-d1,BD(nr));
else
SL(nr) = -_addz_main(BD(n1),-d1,BD(n2),-d2,BD(nr));
}
void _subz(Z n1,Z n2,Z nr)
{
int d1,d2;
if ( !n1 || !SL(n1) ) _copyz(n2,nr);
else if ( !n2 || !SL(n2) ) {
_copyz(n1,nr);
SL(nr) = -SL(nr);
} else if ( (d1=SL(n1)) > 0 )
if ( (d2=SL(n2)) > 0 )
SL(nr) = _subz_main(BD(n1),d1,BD(n2),d2,BD(nr));
else
SL(nr) = _addz_main(BD(n1),d1,BD(n2),-d2,BD(nr));
else if ( (d2=SL(n2)) > 0 )
SL(nr) = -_addz_main(BD(n1),-d1,BD(n2),d2,BD(nr));
else
SL(nr) = -_subz_main(BD(n1),-d1,BD(n2),-d2,BD(nr));
}
void _mulz(Z n1,Z n2,Z nr)
{
int d1,d2;
int i,d,sgn;
unsigned int mul;
unsigned int *m1,*m2;
if ( !n1 || !SL(n1) || !n2 || !SL(n2) )
SL(nr) = 0;
else {
d1 = SL(n1); d2 = SL(n2);
sgn = 1;
if ( d1 < 0 ) { sgn = -sgn; d1 = -d1; }
if ( d2 < 0 ) { sgn = -sgn; d2 = -d2; }
d = d1+d2;
for ( i = d-1, m1 = BD(nr); i >= 0; i-- ) *m1++ = 0;
for ( i = 0, m1 = BD(n1), m2 = BD(n2); i < d2; i++, m2++ )
if ( mul = *m2 ) muln_1(m1,d1,mul,BD(nr)+i);
SL(nr) = sgn*(BD(nr)[d-1]?d:d-1);
}
}
int _addz_main(unsigned int *m1,int d1,unsigned int *m2,int d2,unsigned int *mr)
{
int d,i;
unsigned int tmp,c;
unsigned int *t;
if ( d2 > d1 ) {
t = m1; m1 = m2; m2 = t;
d = d1; d1 = d2; d2 = d;
}
#if defined(VISUAL)
__asm {
push esi
push edi
mov esi,m1
mov edi,m2
mov ebx,mr
mov ecx,d2
xor eax,eax
Lstart__addz:
mov eax,DWORD PTR [esi]
mov edx,DWORD PTR [edi]
adc eax,edx
mov DWORD PTR [ebx],eax
lea esi,DWORD PTR [esi+4]
lea edi,DWORD PTR [edi+4]
lea ebx,DWORD PTR [ebx+4]
dec ecx
jnz Lstart__addz
pop edi
pop esi
mov eax,0
adc eax,eax
mov c,eax
}
#elif ( defined(i386) && !defined(__DARWIN__) )
asm volatile("\
movl %1,%%esi;\
movl %2,%%edi;\
movl %3,%%ebx;\
movl %4,%%ecx;\
testl %%eax,%%eax;\
Lstart__addz:;\
movl (%%esi),%%eax;\
movl (%%edi),%%edx;\
adcl %%edx,%%eax;\
movl %%eax,(%%ebx);\
leal 4(%%esi),%%esi;\
leal 4(%%edi),%%edi;\
leal 4(%%ebx),%%ebx;\
decl %%ecx;\
jnz Lstart__addz;\
movl $0,%%eax;\
adcl %%eax,%%eax;\
movl %%eax,%0"\
:"=m"(c)\
:"m"(m1),"m"(m2),"m"(mr),"m"(d2)\
:"eax","ebx","ecx","edx","esi","edi");
#else
for ( i = 0, c = 0; i < d2; i++, m1++, m2++, mr++ ) {
tmp = *m1 + *m2;
if ( tmp < *m1 ) {
tmp += c;
c = 1;
} else {
tmp += c;
c = tmp < c ? 1 : 0;
}
*mr = tmp;
}
#endif
for ( i = d2, m1 += d2, mr += d2; (i < d1) && c ; i++ ) {
tmp = *m1++ + c;
c = tmp < c ? 1 : 0;
*mr++ = tmp;
}
for ( ; i < d1; i++ )
*mr++ = *m1++;
*mr = c;
return (c?d1+1:d1);
}
int _subz_main(unsigned int *m1,int d1,unsigned int *m2,int d2,unsigned int *mr)
{
int d,i,sgn;
unsigned int t,tmp,br;
unsigned int *m;
if ( d1 > d2 ) sgn = 1;
else if ( d1 < d2 ) sgn = -1;
else {
for ( i = d1-1; i >= 0 && m1[i] == m2[i]; i-- );
if ( i < 0 ) return 0;
if ( m1[i] > m2[i] ) sgn = 1;
else if ( m1[i] < m2[i] ) sgn = -1;
}
if ( sgn < 0 ) {
m = m1; m1 = m2; m2 = m;
d = d1; d1 = d2; d2 = d;
}
#if defined(VISUAL)
__asm {
push esi
push edi
mov esi,m1
mov edi,m2
mov ebx,mr
mov ecx,d2
xor eax,eax
Lstart__subz:
mov eax,DWORD PTR [esi]
mov edx,DWORD PTR [edi]
sbb eax,edx
mov DWORD PTR [ebx],eax
lea esi,DWORD PTR [esi+4]
lea edi,DWORD PTR [edi+4]
lea ebx,DWORD PTR [ebx+4]
dec ecx
jnz Lstart__subz
pop edi
pop esi
mov eax,0
adc eax,eax
mov br,eax
}
#elif ( defined(i386) && !defined(__DARWIN__) )
asm volatile("\
movl %1,%%esi;\
movl %2,%%edi;\
movl %3,%%ebx;\
movl %4,%%ecx;\
testl %%eax,%%eax;\
Lstart__subz:;\
movl (%%esi),%%eax;\
movl (%%edi),%%edx;\
sbbl %%edx,%%eax;\
movl %%eax,(%%ebx);\
leal 4(%%esi),%%esi;\
leal 4(%%edi),%%edi;\
leal 4(%%ebx),%%ebx;\
decl %%ecx;\
jnz Lstart__subz;\
movl $0,%%eax;\
adcl %%eax,%%eax;\
movl %%eax,%0"\
:"=m"(br)\
:"m"(m1),"m"(m2),"m"(mr),"m"(d2)\
:"eax","ebx","ecx","edx","esi","edi");
#else
for ( i = 0, br = 0; i < d2; i++, mr++ ) {
t = *m1++;
tmp = *m2++ + br;
if ( br > 0 && !tmp ) {
/* tmp = 2^32 => br = 1 */
}else {
tmp = t-tmp;
br = tmp > t ? 1 : 0;
*mr = tmp;
}
}
#endif
for ( i = d2, m1 += d2, mr += d2; (i < d1) && br; i++ ) {
t = *m1++;
tmp = t - br;
br = tmp > t ? 1 : 0;
*mr++ = tmp;
}
for ( ; i < d1; i++ )
*mr++ = *m1++;
for ( i = d1-1, mr--; i >= 0 && !*mr--; i-- );
return sgn*(i+1);
}
/* XXX */
void printz(Z n)
{
int sd,u;
if ( !n )
fprintf(asir_out,"0");
else if ( IS_IMM(n) ) {
u = ZTOS(n);
fprintf(asir_out,"%d",u);
} else {
if ( (sd = SL(n)) < 0 ) { SL(n) = -SL(n); fprintf(asir_out,"-"); }
printn((N)n);
if ( sd < 0 ) SL(n) = -SL(n);
}
}
/*
* Dx^k*x^l = W(k,l,0)*x^l*Dx^k+W(k,l,1)*x^(l-1)*x^(k-1)*+...
*
* t = [W(k,l,0) W(k,l,1) ... W(k,l,min(k,l)]
* where W(k,l,i) = i! * kCi * lCi
*/
void mkwcz(int k,int l,Z *t)
{
int i,n,up,low;
N nm,d,c;
n = MIN(k,l);
for ( t[0] = (Z)ONEN, i = 1; i <= n; i++ ) {
DM(k-i+1,l-i+1,up,low);
if ( up ) {
nm = NALLOC(2); PL(nm) = 2; BD(nm)[0] = low; BD(nm)[1] = up;
} else {
nm = NALLOC(1); PL(nm) = 1; BD(nm)[0] = low;
}
kmuln((N)t[i-1],nm,&d); divin(d,i,&c); t[i] = (Z)c;
}
}