2
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
3
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
5
/*~ OPERATIONS DE BASE (NOYAU) ~*/
7
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
8
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
9
/* This file was modified by W. Schelter to be suitable for optimization
10
and inlining of assembler for maximum speed
21
plong s=signe(y),ly=lgef(y),i;
22
GEN z,zp,yp; ulong hiremainder;
24
if((!x)||(!s)) return gzero;
27
if (x < 0) /* -2^31 */
28
{return mulii(stoi(1<<31),y);}
32
MP_START_LOW(yp,y,ly); MP_START_LOW(zp,z,ly+1);
34
WHILE_COUNT(--i) { MP_NEXT_UP(zp) = addmul(x,MP_NEXT_UP(yp));}
35
if(hiremainder) {MP_NEXT_UP(zp)=hiremainder;
37
else {avma+=4;z[1]=z[0]-1;z++;setlgef(z,ly);}
38
setsigne(z,s);return z;
46
return lx==2 ? -8388608 : ((lx-2)<<5)-bfffo(x[2])-1;
58
if(!x) return icopy(y);
59
sy=signe(y);if(!sy) return stoi(x);
62
if (x < 0) /* x=-2^31 */
63
return addii(MOST_NEGS,y);
71
z=cgeti(ly+1);z[ly]=p;
72
for(i=ly-1;(i>2)&&(y[i-1]==0xffffffff);i--) z[i]=0;
75
z[i]=y[i-1]+1;i--;while(i>=3) {z[i]=y[i-1];i--;}
76
z[2]=z[1]=z[0]-1;z++;avma+=4;
78
else {z[2]=1;z[1]=z[0];}
82
z=cgeti(ly);z[ly-1]=p;for(i=1;i<ly-1;i++) z[i]=y[i];
90
if((ulong)y[2]>(ulong)x)
92
z=cgeti(3);z[1]=(sy<<24)+3;z[2]=y[2]-x;return z;
94
if(y[2]==x) return gzero;
95
z=cgeti(3);z[1]=((-sy)<<24)+3;z[2]=x-y[2];return z;
100
z=cgeti(ly);z[ly-1]=p;
101
for(i=ly-2;!(y[i]);i--) z[i]=0xffffffff;
103
if((i>2)||z[i]) {i--;for(;i>=1;i--) z[i]=y[i];}
106
z[2]=z[1]=z[0]-1;z++;avma+=4;setsigne(z,sy);
111
z=cgeti(ly);z[ly-1]=p;for(i=1;i<ly-1;i++) z[i]=y[i];
120
plong sx,sy,sz,lx,ly,i,j,p;
121
GEN z,xp,yp,zp,xpp,xhigh; TEMPVARS
125
if (lx< ly) {z=x;x=y;y=z; sx=lx; lx=ly; ly=sx;}
126
/* lx>=ly so sx==0 ==> sy==0 */
128
if (0 == (sy=signe(y))) return icopy(x);
133
z=cgeti(lx+1);overflow=0;
134
MP_START_LOW(zp,z,lx+1);
135
MP_START_LOW(xp,x,lx);
136
MP_START_LOW(yp,y,ly);
140
QUICK_LOOP(i,ADDXCC);
144
{ADDLLX(MP_NEXT_UP(xp),MP_NEXT_UP(yp),MP_NEXT_UP(zp));}
149
{ GEN xhigh = &MP_HIGH(x,lx);
151
{ GEN xpp = &MP_NEXT_UP(xp);
153
{ if (*xpp == 0xffffffff)
158
{ MP_NEXT_UP(zp) = *xpp + 1;
159
while ((xpp = &MP_NEXT_UP(xp)) >= xhigh)
160
{ MP_NEXT_UP(zp) = *xpp ;}
161
z[1]=z[0]-1;z[2]=x[1];z++;avma+=4;}}
162
else {z[2]=1;z[1]=x[1]+1;}
165
{ j = COUNT(lx - ly);
167
{ MP_NEXT_UP(zp) = MP_NEXT_UP(xp);}
168
z[1]=z[0]-1;z[2]=x[1];z++;avma+=4;
174
/* we have to compare x and y */
175
{ j = MP_COUNT_LG(lx);
176
MP_START_HIGH(xp,x,lx);
177
MP_START_HIGH(yp,y,lx);
179
{ ulong tx = MP_NEXT_DOWN(xp);
180
ulong ty = MP_NEXT_DOWN(yp);
182
{z=x;x=y;y=z;sz=sx;sx=sy;sy=sz;
191
z=cgeti(lx);overflow=0;
192
MP_START_LOW(xp,x,lx);MP_START_LOW(yp,y,ly);MP_START_LOW(zp,z,lx);
197
QUICK_LOOP(i,SUBXCC);
201
{SUBLLX(MP_NEXT_UP(xp),MP_NEXT_UP(yp),MP_NEXT_UP(zp));}
206
while((tx=MP_NEXT_UP(xp)) == 0)
207
MP_NEXT_UP(zp) = 0xffffffff;
208
if (xp >= (xhigh = &MP_HIGH(x,lx)))
209
{ MP_NEXT_UP(zp) = tx -1;
210
while ((xpp = &MP_NEXT_UP(xp)) >= xhigh)
211
{ MP_NEXT_UP(zp) = *xpp;}}
214
{ i = COUNT(lx - ly);
216
MP_NEXT_UP(zp) = MP_NEXT_UP(xp);
221
while (*zp ==0){zp++;} /* x was != y by above */
224
zp[1] = (zp[0] = z[0]-i);
237
GEN z; ulong hiremainder;
239
if((!x)||(!y)) return gzero;
245
return mulsi(y,stoi(x));
250
return mulsi((s > 0 ? x : -x),ABS_MOST_NEGS);
253
if(hiremainder) {z=cgeti(4);z[2]=hiremainder;z[3]=p1;}
254
else {z=cgeti(3);z[2]=p1;}
255
z[1]=z[0];setsigne(z,s);return z;
262
plong i,j,lx=lgef(x),ly=lgef(y),sx,sy,lz,p1,p2;
270
sx=signe(x);if(!sx) return gzero;
271
sy=signe(y);if(!sy) return gzero;
273
if(lx>ly) {z=x;x=y;y=z;lz=lx;lx=ly;ly=lz;}
274
lz=lx+ly-2;if(lz>=0x10000) err(muler1);
275
z=cgeti(lz);z[1]=z[0];setsigne(z,sx);
277
MP_START_LOW(xx,x,lx);
282
MP_START_LOW(yy,y,ly);
283
MP_START_LOW(zz,z,lz);
286
{ MP_NEXT_UP(zz) = addmul(p1,MP_NEXT_UP(yy));}
288
MP_NEXT_UP(zz) = hiremainder;
290
/* restart zz one above bottom */
291
MP_START_LOW(zz,z,lz);
293
MP_START_LOW(ylow,y,ly);
294
ly = COUNT(ly - MP_CODE_WORDS);
296
while (--lx > 0) /* one less iteration first term of x, already used */
299
p11 = MP_NEXT_UP(xx);
302
zp = &MP_NEXT_UP(zz); /* *zp = second from low word of z first time through */
304
/* ZerO is just a 68k kludge to getit to keep 0 in a reg during this loop*/
309
{ p2 = MP_NEXT_UP(yy);
310
p2 = mulul(p2,p11,hiremainder);
312
p2 = add_carry(p2,*zp,hiremainder);
313
p2 = add_carry(p2,tem,hiremainder);
318
MP_NEXT_UP(zp) = hiremainder;
325
{ /* shift header one along decreasing lg and lgef */
326
z[2]=z[1]-1;z[1]=z[0]-1;z++;avma+=4;
334
plong lx=lg(x),ex= -expo(x)-1,ex1,av=avma,ly,ey;
335
plong lr,nbdec,k,i,j; ulong hiremainder;
338
ey=((lx-2)<<5)+ex;ly=(ey+63)>>5;y=cgeti(ly);ex1=ex>>5; /* 95 dans mp.s faux? */
339
for(i=0;i<ex1;i++) y[i]=0;
341
if(!ex) for(j=2;j<lx;j++) y[i++]=x[j];
345
for(j=2;j<lx;j++) {y[i++]=shiftlr(x[j],ex)+k;k=hiremainder;}
349
nbdec=ey*0.30103+1;lr=(nbdec+17)/9;res=cgeti(lr);
354
for(i=ly-1;i>=0;i--) y[i]=addmul(y[i],1000000000);
360
/* x/y : uses hiremainder for return */
368
return divis(stoi(x),y);
369
hiremainder=0;p1=divll((ulong)abs(x),(ulong)abs(y));
370
if(y<0) {hiremainder= -((plong)hiremainder);p1= -p1;}
378
plong y1; ulong hiremainder;
382
return modis(stoi(x),y);
383
hiremainder=0;divll(abs(x),y1=abs(y));
384
if(!hiremainder) return gzero;
385
return (((plong)hiremainder)<0) ? stoi(y1-hiremainder) : stoi(hiremainder);
392
hiremainder=0;divll(abs(x),abs(y));
393
return (y<0) ? stoi(-((plong)hiremainder)) : stoi(hiremainder);
396
/* uses hiremainder for return */
401
plong s=signe(y),ly=lgef(y),p1;
404
if((!x)||(ly>3)||(y[2]<0)) {hiremainder=x;return gzero;}
406
return divii(stoi(x),y);
407
hiremainder=0;p1=divll(abs(x),y[2]);
408
if(signe(y)<0) {hiremainder= -((plong)hiremainder);p1= -p1;}
413
/* this uses the GLOBAL hiremainder to return its remainder
414
We cannot make it a local.
420
plong s=signe(y),ly=lgef(y),i,d;
424
if(!s) {hiremainder=0;return gzero;}
425
if(x<0) {s= -s;x= -x;
427
return divii(y,stoi(x));
429
if((ulong)x>(ulong)y[2])
431
if(ly==3) {hiremainder=itos(y);return gzero;}
432
else {z=cgeti(ly-1);d=1;hi=y[2];}
434
else {z=cgeti(ly);d=0;hi=0;}
435
for(i=d+2;i<ly;i++) z[i-d]=divul(y[i],x,hi);
436
z[1]=z[0];setsigne(z,s);
437
hiremainder= (s < 0 ? -((plong)hi) : hi) ;
442
# entree : x pointe sur i2 de type I (dividende)
443
# y pointe sur i1 de type I (diviseur)
444
# z contient un pointeur sur le reste si l'on
445
# veut a la fois q et r, 0 si l'on ne veut que le
446
# quotient, -1 si l'on ne veut que le reste
447
# sortie : resultat est q si celui-ci est attendu, et sinon r
448
# r. z pointe sur r si q et r sont attendus
449
# (toutes les zones sont creees)
450
# remarque : il s'agit de la 'fausse division' ; le reste est
451
# du signe du dividende
457
plong av,lx,ly,lz,i,j,dec,sh,k,k1,sx=signe(x),sy=signe(y);
458
plong saux,k3,k4,av1,flk4;
460
GEN p1,p2,p3,p4,xp,p1p,p2p,pp; TEMPVARS
461
ulong hiremainder,overflow;
466
if(((plong)z==0xffffffff)||((plong)z==0)) return gzero;
467
*z=gzero;return gzero;
469
lx=lgef(x);ly=lgef(y);lz=lx-ly;
472
if((plong)z==0xffffffff) return icopy(x);
473
if(z==0) return gzero;
474
*z=icopy(x);return gzero;
476
av=avma;if(sx<0) sy= -sy;
480
MP_START_HIGH(xp,x,lx);
481
if (si > (ulong)MP_HIGH(x,lx))
482
{ lgp1=lx-1; hiremainder= MP_NEXT_DOWN(xp);}
483
else { lgp1=lx; hiremainder=0;}
484
p1 = cgeti(lgp1); i = MP_COUNT_LG(lgp1);
485
MP_START_HIGH(p1p,p1,lgp1);
486
WHILE_COUNT(--i) { MP_NEXT_DOWN(p1p) = divll(MP_NEXT_DOWN(xp),si);}
488
if((plong)z==0xffffffff)
490
avma=av;if(!hiremainder) return gzero;
491
p2=cgeti(3);p2[1]=(sx<<24)+3;p2[2]=hiremainder;return p2;
493
if(lgp1!= 2) {p1[1]=p1[0];setsigne(p1,sy);} else {avma=av;p1=gzero;}
495
if(!hiremainder) *z=gzero;
496
else {p2=cgeti(3);p2[1]=(sx<<24)+3;p2[2]=hiremainder;*z=p2;}
505
MP_START_HIGH(yp,y,ly);
507
k=shiftl(MP_NEXT_DOWN(yp),sh);
508
MP_START_HIGH(p2p,p2,ly);
509
i = MP_COUNT_LG(ly-1);
512
k1=shiftl(MP_NEXT_DOWN(yp),sh);
513
MP_NEXT_DOWN(p2p) = k + hiremainder;
516
MP_NEXT_DOWN(p2p) = k ; k=0;
518
MP_START_HIGH(xp,x,lx);
519
MP_START_HIGH(p1p,p1,lx);
520
MP_NEXT_UP(p1p) ; /* yes go out of range !! */
523
{ k1 = shiftl(MP_NEXT_DOWN(xp),sh);
524
MP_NEXT_DOWN(p1p) = k + hiremainder; k = k1;
526
MP_NEXT_DOWN(p1p) = k;
529
MP_START_HIGH(xp,x,lx);
530
MP_START_HIGH(p1p,p1,lx);
531
MP_NEXT_UP(p1p) ; /* yes go out of range !! */
532
MP_NEXT_DOWN(p1p) = 0;
535
{ MP_NEXT_DOWN(p1p) = MP_NEXT_DOWN(xp);}
538
MP_START_HIGH(p1p,p1,lx); MP_NEXT_UP(p1p) ; /* out of bound */
543
if(MP_NEXT_DOWN(p1p)==si)
544
{ /* Using fact that next_down does post increment */
545
qp=0xffffffff;k=addll(si,*p1p);
550
hiremainder=p1p[-1];qp=divll(*p1p,si);
551
overflow=0;k=hiremainder;
555
/* k1=mulll(qp,saux);k3=subll(k1,p1p[1]);k+=overflow;
556
flk4=((ulong)hiremainder>(ulong)k);k4=subll(hiremainder,k);
557
while(flk4) {qp--;k3=subll(k3,saux);
558
k4-=overflow;flk4=((ulong)k4>(ulong)si);
561
k1=mulll(qp,saux);k3=subll(k1,p1p[1]);
562
k4=subllx(hiremainder,k);
563
while((!overflow)&&k4) {qp--;k3=subll(k3,saux);k4=subllx(k4,si);}
569
MP_START_LOW(pp,p1p,ly-2);
570
MP_START_LOW(p2p,p2,ly);
573
k1=addmul(qp,MP_NEXT_UP(p2p));
574
ppp = &MP_NEXT_UP(pp);
575
*ppp =subll(*ppp,k1);hiremainder+=overflow;
577
if((ulong)p1p[-1]<(ulong)hiremainder)
581
MP_START_LOW(pp,p1p,ly-2);
582
MP_START_LOW(p2p,p2,ly);
583
WHILE_COUNT(--j){ GEN ppp = &MP_NEXT_UP(pp);
584
ADDLLX(*ppp,MP_NEXT_UP(p2p),*ppp);}
590
if((plong)z!=0xffffffff)
591
{ulong lgp3 = lz + 2;
592
MP_START_LOW(p1p,p1,lgp3);
594
else if (lz==0) sy=0;
596
MP_START_LOW(pp,p3,lgp3);
597
j = MP_COUNT_LG(lgp3);
599
{MP_NEXT_UP(pp) = MP_NEXT_UP(p1p) ;}
600
if(lgp3<3) {p3[1]=2;} else {p3[1]=p3[0];setsigne(p3,sy);}
604
for(j=lz+2;(j<lx)&&(!p1[j]);j++);
605
if(j==lx) p4=icopy(gzero);
608
p4=cgeti(lx-j+2);p4[1]=p4[0];
609
if(!sh) for(i=2;j<lx;j++,i++) p4[i]=p1[j];
612
hiremainder=0;k1=shiftlr(p1[j++],sh);k=hiremainder;
613
if(k1) {p4[2]=k1;dec=1;} else
614
{p4[1]=p4[0]-1;p4++;avma+=4;p4[1]=p4[0];dec=0;}
615
for(i=2+dec;j<lx;j++,i++)
617
p4[i]=shiftlr(p1[j],sh)+k;k=hiremainder;
623
if((plong)z==0xffffffff) return gerepile(av,av1,p4);
624
if((plong)z==0) return gerepile(av,av1,p3);
625
dec=lpile(av,av1,0)>>2;*z=p4+dec;return p3+dec;
628
/* machines which provide an inline version of mulul need
629
to provide a function for calls where that inlining can't take place
635
{ return mulul(a,b,*c);}
642
{ return divul(a,b,*c);}
647
;;- version-control:t