view vx.c @ 0:e0bbaa717f41 draft default tip

lol J
author Jordi Gutiérrez Hermoso <jordigh@octave.org>
date Mon, 25 Nov 2013 11:56:30 -0500
parents
children
line wrap: on
line source

/* Copyright 1990-2011, Jsoftware Inc.  All rights reserved. */
/* License in license.txt.                                   */
/*                                                                         */
/* Verbs: Extended Precision Integers                                      */

#include "j.h"
#include "ve.h"


X jtxev1(J jt,A w,C*s){A y; 
 RZ(y=df1(cvt(XNUM,w),eval(s)));
 ASSERTSYS(!AR(y),"xev1");
 if(!(XNUM&AT(y)))RZ(y=cvt(XNUM,y)); 
 R*XAV(y);
}

X jtxev2(J jt,A a,A w,C*s){A y; 
 RZ(y=df2(cvt(XNUM,a),cvt(XNUM,w),eval(s))); 
 ASSERTSYS(!AR(y),"xev2");
 if(!(XNUM&AT(y)))RZ(y=cvt(XNUM,y)); 
 R*XAV(y);
}

X jtxc(J jt,I n){I m=1,p,*zv;X z; 
 p=n; while(p/=XBASE)++m;
 GA(z,INT,m,1,0); zv=AV(z);
 p=n; DO(m, zv[i]=p%XBASE; p/=XBASE;);
 R z;
}    /* n is non-negative */

D xdouble(X w){D z=0;I c,n,*v;
 n=AN(w); v=n+AV(w); c=*--v;
 if(c==XPINF)R inf; else if(c==XNINF)R infm;
 DO(n, z=*v--+z*XBASE;);
 R z;   
}

I jtxint(J jt,X w){I c,n,*v,z;
 n=AN(w); v=AV(w); v+=n; c=z=*--v;
 ASSERT(n<=XIDIG&&c!=XPINF&&c!=XNINF,EVDOMAIN);
 DO(n-1, z=*--v+z*XBASE;);
 ASSERT((c<0)==(z<0),EVDOMAIN);
 R z;
}

XF1(jtxstd){A z;B b;I c=0,d,i,j,k,m=XBASE,n,*zv;
 RZ(w);
 n=AN(w); RZ(z=ca(w)); zv=AV(z);
 b=0; j=n; DO(n, --j; if(zv[j]){b=0<zv[j]; break;});
 if(b) for(i=0;i<n;++i){
  k=zv[i]+=c; 
  if     (0>  k){c=-1-(-k)/m; zv[i]=d=m-(-k)%m; if(d== m){zv[i]=0; ++c;}}
  else if(m<= k){c=k/m;       zv[i]=k%m;}
  else          c=0;
 }else for(i=0;i<n;++i){
  k=zv[i]+=c; 
  if     (0<  k){c=1+k/m;     zv[i]=d=(k%m)-m;  if(d==-m){zv[i]=0; --c;}}
  else if(m<=-k){c=-(-k)/m;   zv[i]=-(-k)%m;}
  else          c=0;
 }
 if(c)R over(z,sc(c));
 j=n-1; while(j&&!zv[j])--j; ++j;
 R j==n?z:vec(INT,j,zv);
}    /* convert to standard form */

int jtxcompare(J jt,X a,X w){I*av,j,m,n,x,y,*wv;int s,t;
 RE(1);
 m=AN(a); av=AV(a); x=av[m-1]; s=SGN(x);
 n=AN(w); wv=AV(w); y=wv[n-1]; t=SGN(y);
 if(s!=t)R s?s:-t;
 if(1==m&&(x==XPINF||x==XNINF))R 0<x? !(1==n&&y==XPINF):-!(1==n&&y==XNINF);
 if(1==n&&(y==XPINF||y==XNINF))R 0<y?-!(1==m&&x==XPINF): !(1==m&&x==XNINF);
 if(m!=n)R m>n?s:-s;
 j=m; DO(m, --j; if(av[j]!=wv[j])R av[j]>wv[j]?1:-1;);
 R 0;
}    /* _1 0 1 depending on whether a<w, a=w, a>w */


XF1(jtxsgn){I x=XDIG(w); R xc(SGN(x));}

XF2(jtxplus){PROLOG;A z;I an,*av,c,d,m,n,wn,*wv,*zv;
 RZ(a&&w);
 an=AN(a); av=AV(a); c=av[an-1];
 wn=AN(w); wv=AV(w); d=wv[wn-1];
 if(c==XPINF||c==XNINF||d==XPINF||d==XNINF){
  ASSERT(!(c==XPINF&&d==XNINF||c==XNINF&&d==XPINF),EVNAN);
  R vci(c==XPINF||d==XPINF?XPINF:XNINF);
 }
 m=MAX(an,wn); n=MIN(an,wn);
 GA(z,INT,m,1,0); zv=AV(z);
 DO(n, *zv++=*av+++*wv++;);
 if(m>n)ICPY(zv,an>wn?av:wv,m-n);
 EPILOG(xstd(z));
}

XF2(jtxminus){PROLOG;A z;I an,*av,c,d,m,n,wn,*wv,*zv;
 RZ(a&&w);
 an=AN(a); av=AV(a); c=av[an-1];
 wn=AN(w); wv=AV(w); d=wv[wn-1];
 if(c==XPINF||c==XNINF||d==XPINF||d==XNINF){
  ASSERT(c!=d,EVNAN);
  R vci(c==XPINF||d==XNINF?XPINF:XNINF);
 }
 m=MAX(an,wn); n=MIN(an,wn);
 GA(z,INT,m,1,0); zv=AV(z);
 DO(n, *zv++=*av++-*wv++;);
 if(m>n){if(an>wn)ICPY(zv,av,m-n); else DO(m-n, *zv++=-*wv++;);}
 EPILOG(xstd(z));
}

XF2(jtxtymes){A z;I an,*av,c,d,e,i,j,m=XBASE,n,*v,wn,*wv,*zv;
 RZ(a&&w);
 an=AN(a); av=AV(a); c=av[an-1];
 wn=AN(w); wv=AV(w); d=wv[wn-1];
 if(!c||!d)R xzero;
 if(c==XPINF||c==XNINF||d==XPINF||d==XNINF)R vci(0<c*d?XPINF:XNINF);
 n=an+wn; GA(z,INT,n,1,0); zv=v=AV(z); memset(zv,C0,n*SZI);
 for(i=0;i<an;++i,++zv){
  if(c=av[i])for(j=0;j<wn;++j){
   d=zv[j]+=c*wv[j];
   if     (m<= d){e=  d /m; zv[j]-=e*m; zv[1+j]+=e;}
   else if(m<=-d){e=(-d)/m; zv[j]+=e*m; zv[1+j]-=e;}
 }}
 R v[n-1]?z:vec(INT,v[n-2]?n-1:1,v);
}

static X jtshift10(J jt,I e,X w){A z;I c,d,k,m,n,q,r,*wv,*zv;
 n=AN(w); wv=AV(w); c=wv[n-1];
 q=e/XBASEN; r=e%XBASEN; d=0==r?1:1==r?10:2==r?100:1000;
 m=n+q+(XBASE<=c*d);
 GA(z,INT,m,1,0); zv=AV(z);
 DO(q, *zv++=0;);
 if(r){c=0; DO(n, k=c+d**wv++; *zv++=k%XBASE; c=k/XBASE;); if(c)*zv=c;}
 else DO(n, *zv++=*wv++;);
 R z;
}    /* w*10^e, positive w */

B jtxdivrem(J jt,X a,X w,X*qz,X*rz){B b,c;I*av,d,j,n,*qv,r,y;X q;
 j=n=AN(a); av=AV(a); b=0<=av[n-1];
 y=*AV(w); c=0<=y; if(!c)y=-y; r=0;
 GA(q,INT,n,1,0); qv=AV(q);
 switch(2*b+c){
  case 0: DO(n, --j; d=r*XBASE-av[j]; r=d%y; qv[j]=  d/y ;); r=-r;      break;
  case 1: DO(n, --j; d=r*XBASE-av[j]; r=d%y; qv[j]=-(d/y);); r=r?y-r:0; break;
  case 2: DO(n, --j; d=r*XBASE+av[j]; r=d%y; qv[j]=-(d/y);); r=r?r-y:0; break;
  case 3: DO(n, --j; d=r*XBASE+av[j]; r=d%y; qv[j]=  d/y ;);            break;
 }
 if(r&&b!=c){--qv[0]; DO(n-1, if(qv[i]>-XBASE)break; qv[i]=0; --qv[1+i];);}
 if(1<n&&!qv[n-1])AN(q)=*AS(q)=n-1;
 *qz=q; *rz=vec(INT,1L,&r); R 1;
}    /* (<.a%w),(w|a) where w has a single "digit" and is nonzero */
 
X jtxdiv(J jt,X a,X w,I mode){PROLOG;B di;I an,*av,c,c0,d,e,k,s,u[2],u1,wn,*wv,yn;X q,r,y;
 RZ(a&&w&&!jt->jerr);
 an=AN(a); av=AV(a); c=c0=av[an-1];
 wn=AN(w); wv=AV(w); d=   wv[wn-1]; di=d==XPINF||d==XNINF;
 if(c&&!d)R vci(0<c?XPINF:XNINF);
 if(c==XPINF||c==XNINF){ASSERT(!di,EVNAN); R vci(0<c*d?XPINF:XNINF);}
 if(di)R xzero;
 if(1==wn&&d){I*v;
  RZ(xdivrem(a,w,&q,&r));
  if(!*AV(r)||mode==XMFLR)R q;
  ASSERT(mode==XMCEIL,EWRAT);
  v=AV(q); ++*v; 
  R XBASE>*v?q:xstd(q);
 }
 switch((0<=c?2:0)+(0<=d)){
  case 0: R xdiv(negate(a),negate(w),mode);
  case 1: R negate(xdiv(negate(a),w,mode==XMFLR?XMCEIL:mode==XMCEIL?XMFLR:mode));
  case 2: R negate(xdiv(a,negate(w),mode==XMFLR?XMCEIL:mode==XMCEIL?XMFLR:mode));
  default:
   if(1!=(e=xcompare(a,w))){
    ASSERT(!(c&&e&&mode==XMEXACT),EWRAT); 
    d=c&&(mode||!e); 
    R vec(INT,1L,&d);
   }
   if(1<an)c=av[an-2]+c*XBASE;
   if(1<wn)d=wv[wn-2]+d*XBASE;
   e=c>=d?c/d:(I)((XBASE*(D)c)/d); u[0]=e%XBASE; u[1]=u1=e/XBASE; 
   RZ(q=vec(INT,u1?2L:1L,u)); 
   RZ(y=xtymes(w,q)); yn=AN(y); e=*(AV(y)+yn-1);
   k=c0>=e?c0/e:e/c0; 
   k=k<=3?0:k>3162?4:3<k&&k<=32?1:32<k&&k<=316?2:3;
   s=XBASEN*(an-yn)+(c0>=e?k:-k); 
   if(s){q=shift10(s,q); y=shift10(s,y);}
   EPILOG(xplus(q,xdiv(xminus(a,y),w,mode)));
}}   /* <.a%w (mode=XMFLR) or >.a%w (mode=XMCEIL) or a%w (mode=XMEXACT) */

XF2(jtxrem){I c,d,e;X q,r,y;
 RZ(a&&w);
 c=XDIG(a); d=XDIG(w);
 if(!c)R w;
 ASSERT(!(d==XPINF||d==XNINF),EVNAN);
 if(c==XPINF)R 0<=d?w:a;
 if(c==XNINF)R 0>=d?w:a;
 if(1==AN(a)&&c){RZ(xdivrem(w,a,&q,&r)); R r;}
 switch((0<=c?2:0)+(0<=d)){
  case 0:  R negate(xrem(negate(a),negate(w)));
  case 1:  y=xrem(negate(a),w); R xcompare(y,xzero)? xplus(a,y):y;
  case 2:  y=xrem(a,negate(w)); R xcompare(y,xzero)?xminus(a,y):y;
  default: R 0<=(e=xcompare(a,w)) ? (e?w:xzero) : xminus(w,xtymes(a,xdiv(w,a,XMFLR)));
}}
                                             
XF2(jtxgcd){I c,d,old;X p,q,t;
 RZ(a&&w);
 c=XDIG(a); if(0>c)RZ(a=negate(a)); 
 d=XDIG(w); if(0>d)RZ(w=negate(w));
 ASSERT(!(c==XPINF||c==XNINF||d==XPINF||d==XNINF),EVNAN);
 if(!c)R w;
 if(!d)R a;
 p=a; q=w; old=jt->tbase+jt->ttop;
 while(XDIG(p)){
  t=p;
  RZ(p=xrem(p,q));
  q=t;
  gc3(p,q,0L,old);
 }
 R q;
}

XF2(jtxlcm){R xtymes(a,xdiv(w,xgcd(a,w),XMEXACT));}

static X jtxexp(J jt,X w,I mode){I k,m;X s,y;
 RZ(w);
 k=XDIG(w);
 ASSERT(!k||mode!=XMEXACT,EWIRR);
 if(0>k)R xc(mode);
 m=(I)(2.71828*xint(w)); k=2; s=xplus(xone,w); y=w;
 DO(m, y=xtymes(y,w); s=xplus(xtymes(s,xc(k)),y); ++k;);
 R xdiv(s,xev1(apv(1+m,1L,1L),"*/"),mode);
}

XF2(jtxpow){PROLOG;I c,d,e,r;X m,t,z;
 RZ(a&&w);
 c=XDIG(a); d=XDIG(w); e=*AV(w);
 if(c==XPINF||c==XNINF){
  ASSERT(0<c||d!=XPINF,EVDOMAIN); 
  R vci(!d?1L:0>d?0L:0<c?c:1&e?XNINF:XPINF);
 }
 if(d==XPINF||d==XNINF){
  ASSERT(0<=c||d==XNINF,EVDOMAIN); 
  R vci(1==c&&1==AN(a)?1L:!c&&0>d||c&&0<d?XPINF:0L);
 }
 if(1==AN(a)&&(1==c||-1==c))R 1==c||0==e%2?xone:xc(-1L); 
 if(!c){ASSERT(0<=d,EWRAT); R d?xzero:xone;}
 if(0>d){
  ASSERT(!jt->xmod,EVDOMAIN); 
  ASSERT(jt->xmode!=XMEXACT,EWRAT); 
  r=jt->xmode==XMCEIL; R xc(0<c?r:1&e?r-1:r);
 }
 t=a; z=xone; m=jt->xmod?*XAV(jt->xmod):0;
 if(!m||1>xcompare(w,xc(IMAX))){
  ASSERT(m||2>=AN(w),EVLIMIT);
  RE(e=xint(w));
  if(m)while(e){if(1&e)RZ(z=xrem(m,xtymes(z,t))); RZ(t=xrem(m,xsq(t))); e>>=1;}
  else while(e){if(1&e)RZ(z=       xtymes(z,t) ); RZ(t=       xsq(t) ); e>>=1;}
 }else{B b;I n,*u,*v;X e;
  RZ(e=ca(w)); n=AN(e); v=AV(e);
  while(n){
   if(1&*v)RZ(z=xrem(m,xtymes(z,t))); 
   RZ(t=xrem(m,xtymes(t,t))); 
   b=1; c=0; u=v+n;
   DO(n, d=c+*--u; c=1&d?XBASE:0; *u=d>>1; if(b&=!*u)--n;);  /* e=.<.e%2 */
 }}
 EPILOG(z);
}

XF1(jtxsq){R xtymes(w,w);}

XF1(jtxsqrt){I c,m,n,p,q,*wv;X e,x;
 RZ(w);
 n=AN(w); wv=AV(w); c=wv[n-1];
 ASSERT(0<=c,EWIMAG);
 if(!(1&n))c=wv[n-2]+c*XBASE;
 m=(1+n)/2; RZ(x=apv(m,0L,0L)); *(AV(x)+m-1)=(I)sqrt((D)c);
 RZ(e=xc(2L));
 p=m*XBASEN; q=0; while(p){++q; p>>=1;} 
 DO(1+q, RZ(x=xdiv(xplus(x,xdiv(w,x,XMFLR)),e,XMFLR)););
 p=xcompare(w,xsq(x));
 switch(jt->xmode){
  default:     ASSERTSYS(0,"xsqrt");
  case XMFLR:  if(-1==p){--*AV(x); R xstd(x);}else R x;
  case XMCEIL: if( 1==p){++*AV(x); R xstd(x);}else R x;
  case XMEXACT: 
   if(!p)R x; 
   *AV(x)+=p; RZ(x=xstd(x));
   ASSERT(!xcompare(w,xsq(x)),EWIRR);
   R x;
}}

static XF2(jtxroot){A q;D x;I an,*av,c,d,r,wn,*wv;X n,n1,p,t,z;
 an=AN(a); av=AV(a); c=av[an-1];
 wn=AN(w); wv=AV(w); d=wv[wn-1]; 
 ASSERT(0<=d,EWIMAG);
 if(1==wn&&(0==d||1==d))R 1==d?xone:0<=c?xzero:vci(XPINF);
 if(!c&&0<d)R vci(XPINF);
 r=xint(a); if(jt->jerr){RESETERR; R xone;}
 if(2==r)R xsqrt(w);
 x=xlogabs(w)/r;
 if(x<709.78){RZ(q=ceil1(cvt(RAT,scf(exp(x))))); z=*XAV(q);}
 else        {RZ(q=cvt(XNUM,scf(ceil(x)))); z=xexp(*XAV(q),XMCEIL);}
 RZ(n=xc(r)); RZ(n1=xc(r-1));
 RZ(t=xdiv(w,p=xpow(z,n1),XMFLR));
 RZ(z=xdiv(xplus(t,xtymes(z,n1)),n,XMFLR))
 while(1){
  RZ(t=xdiv(w,p=xpow(z,n1),XMFLR));
  if(1>xcompare(z,t))break;
  RZ(z=xdiv(xplus(t,xtymes(z,n1)),n,XMFLR))
 }
 if(XMFLR==jt->xmode||!xcompare(w,xtymes(z,p)))R z;
 if(XMCEIL==jt->xmode)R xplus(z,xone);
 ASSERT(0,EWIRR);
}

D jtxlogabs(J jt,X w){D c;I m,n,*v;
 n=AN(w); m=MIN(n,20/XBASEN); v=n+AV(w);
 c=0.0; DO(m, c=c*XBASE+(D)*--v;);
 R log(ABS(c))+XBASEN*(n-m)*2.3025850929940457;
}

static XF1(jtxlog1){B b;I c;
 c=XDIG(w); b=1==c&&1==AN(w);
 ASSERT(0<=c,EWIMAG);
 ASSERT(b||jt->xmode!=XMEXACT,EWIRR);
 R xc((I)xlogabs(w)+(!b&&jt->xmode==XMCEIL));
}

static D jtxlogd1(J jt,X w){ASSERT(0<=XDIG(w),EWIMAG); R xlogabs(w);}

static Z jtxlogz1(J jt,X w){Z z; z.re=xlogabs(w); z.im=0>XDIG(w)?PI:0.0; R z;}


static XF2(jtxlog2sub){ASSERT(0,EVNONCE);}

static XF2(jtxlog2){D c,d,x,y;I an,*av,j,k,m,n,wn,*wv;X p,q;
 RZ(a&&w);
 an=AN(a); av=AV(a); c=(D)av[an-1]; if(1<an)c=av[an-2]+c*XBASE;
 wn=AN(w); wv=AV(w); d=(D)wv[wn-1]; if(1<wn)d=wv[wn-2]+d*XBASE;
 if(2<an)R xlog2sub(a,w);
 ASSERT(0<=c,EWIMAG);
 if(!c){ASSERT(d,EVDOMAIN); R xzero;}
 if(!d){ASSERT(0<c,EVDOMAIN); R vci(XNINF);}
 ASSERT(0<d,EVDOMAIN);
 if(1==c)R 1==d?xzero:vci(XPINF);
 x=log(c)+XBASEN*(2<an?an-2:0)*2.3025850929940457;
 y=log(d)+XBASEN*(2<wn?wn-2:0)*2.3025850929940457;
 m=n=(I)(y/x+(an<wn));
 RZ(p=q=xpow(a,xc(m))); j=k=xcompare(p,w);
 if     (0<j){--m; RZ(p=xdiv(p,a,XMEXACT)); j=xcompare(p,w); if(0<j)R xlog2sub(a,w);}
 else if(0>j){++n; RZ(q=xtymes(p,a));       k=xcompare(q,w); if(0>k)R xlog2sub(a,w);}
 ASSERT(jt->xmode!=XMEXACT||!j||!k,EWIRR); 
 R xc(!j?m:!k?n:jt->xmode==XMCEIL?n:m);
}

F2(jtxlog2a){A z; GA(z,XNUM,1L,0L,0L); *XAV(z)=xlog2(*XAV(a),*XAV(w)); RNE(z);}
F2(jtxroota){A z; GA(z,XNUM,1L,0L,0L); *XAV(z)=xroot(*XAV(a),*XAV(w)); RNE(z);}

XF1(jtxfact){I n;
 n=*AV(w);
 if(n==XPINF||n==XNINF)R vci(XPINF);
 RE(n=xint(w)); 
 if(0>n)R vci(n%2?XPINF:XNINF);
 R xev1(apv(n,1L,1L),"*/");
}

static XF2(jtxbinp){PROLOG;D m;I i,n;X c,d,p,q,r,s;
 RZ(d=xminus(w,a)); s=1==xcompare(a,d)?d:a; RE(n=xint(s));
 m=xdouble(w);
 if(m<=IMAX){
  RZ(p=less(ravel(factor(apv(n,(I)m,-1L))),zero));
  RZ(q=less(ravel(factor(apv(n,1L,   1L))),zero));
  c=over(p,q);
  d=repeat(v2(AN(p),AN(q)),v2(1L,-1L));
  EPILOG(xev1(repeat(ev2(c,d,"+//."),nub(c)),"*/"));
 }else{
  p=q=xone; r=w;  
  for(i=0;i<n;++i){
   p=xtymes(p,r); r=xminus(r,xone);  
   q=xtymes(q,s); s=xminus(s,xone);
   d=xgcd(p,q); p=xdiv(p,d,XMEXACT); q=xdiv(q,d,XMEXACT);
   if(jt->jerr)R 0;
  }
  EPILOG(p);
}}   /* non-negative x,y; x<=y */

XF2(jtxbin){X d,z;
 RZ(d=xminus(w,a));
 switch(4*(0>XDIG(a))+2*(0>XDIG(w))+(0>XDIG(d))){
  default:             ASSERTSYS(0,"xbin");
  case 2: /* 0 1 0 */  /* Impossible */
  case 5: /* 1 0 1 */  /* Impossible */
  case 1: /* 0 0 1 */ 
  case 4: /* 1 0 0 */ 
  case 7: /* 1 1 1 */  R xzero;
  case 0: /* 0 0 0 */  R xbinp(a,w);
  case 3: /* 0 1 1 */  
   z=xbinp(a,xminus(a,xplus(w,xone)));           R*AV(a)%2?negate(z):z;
  case 6: /* 1 1 0 */  
   z=xbinp(xminus(xc(-1L),w),xminus(xc(-1L),a)); R*AV(d)%2?negate(z):z;
}}

static A jtpiev(J jt,I n,X b){A e;I ek,i,n1=n-1;X bi,e0,e1,*ev,t;
 GA(e,XNUM,n,1,0); ev=XAV(e);
 bi=e0=e1=xone;
 for(i=0,ek=1;i<n1;++i,ek+=3){
  ev[i]=xtymes(e0,xtymes(XCUBE(e1),bi));
  t=xtymes(xc(ek),xtymes(xc(1+ek),xc(2+ek)));
  e0=xtymes(e0,t);        /* e0 = ! 3*i */
  e1=xtymes(e1,xc(1+i));  /* e1 = ! i   */
  bi=xtymes(bi,b);        /* bi = b^i   */
 }
 ev[i]=xtymes(e0,xtymes(XCUBE(e1),bi));
 RE(e); R e;
}

static XF1(jtxpi){A e;B p;I i,n,n1,sk;X a,b,c,d,*ev,k,f,m,q,s,s0,t;
 RZ(w);
 if(!XDIG(w))R xzero;
 ASSERT(jt->xmode!=XMEXACT,EVDOMAIN);
 RZ(a=xc(545140134L));
 RZ(b=XCUBE(xc(640320L)));
 RZ(c=xc(13591409L));
 RZ(d=xplus(xc(541681608L),xtymes(xc(10L),xc(600000000L))));
 n1=(13+AN(w)*XBASEN)/14; n=1+n1;
 RZ(e=piev(n,b)); ev=XAV(e); m=ev[n1];
 f=xzero; s0=xone; sk=1;
 for(i=p=0;;++i,p=!p){
  s=xtymes(s0,xplus(c,xtymes(a,xc(i))));
  t=xdiv(xtymes(s,m),ev[i],XMEXACT);
  f=p?xminus(f,t):xplus(f,t);
  if(i==n1)break;
  DO(6, s0=xtymes(s0,xc(sk++));); RE(s0);  /* s0 = ! 6*i */
 }
 f=xtymes(d,f);
 q=xpow(xc(10L),xc(14*n1));
 k=xtymes(xtymes(a,m),xsqrt(xtymes(b,xsq(q))));
 R xdiv(xtymes(k,w),xtymes(f,q),jt->xmode);
}    /* Chudnovsky Bros. */

APFX( plusXX, X,X,X, xplus )
APFX(minusXX, X,X,X, xminus)
APFX(tymesXX, X,X,X, xtymes)
APFX(  divXX, X,X,X, XDIV  )
APFX(  remXX, X,X,X, xrem  )
APFX(  gcdXX, X,X,X, xgcd  )
APFX(  lcmXX, X,X,X, xlcm  )
APFX(  minXX, X,X,X, XMIN  )
APFX(  maxXX, X,X,X, XMAX  )
APFX(  powXX, X,X,X, xpow  )
APFX(  binXX, X,X,X, xbin  )

AMON( sgnX, X,X, *z=  xsgn(*x);)
AMON(sqrtX, X,X, *z= xsqrt(*x);)
AMON( expX, X,X, *z=  xexp(*x,jt->xmode);)
AMON( logX, X,X, *z= xlog1(*x);)
AMON(logXD, D,X, *z=xlogd1(*x);)
AMON(logXZ, Z,X, *z=xlogz1(*x);)
AMON( absX, X,X, *z=   mag(*x);)
AMON(factX, X,X, *z= xfact(*x);)
AMON( pixX, X,X, *z=   xpi(*x);)


F1(jtdigits10){A z;B b=0;I c,m,n,*v,*zv,*zv0;X x;
 RZ(w);
 if(!AR(w))switch(AT(w)){
  case INT:  b=0<=*AV(w); break;
  case XNUM: x=*XAV(w); n=AN(x); v=AV(x); b=0<=v[n-1]; break;
  case RAT:  x=*XAV(w); n=AN(x); v=AV(x); b=0<=v[n-1]&&equ(iv1,QAV(w)->d);
 }
 if(!b)R rank1ex(thorn1(w),0L,0L,jtexec1);
 m=INT&AT(w)?(SY_64?19:10):XBASEN*AN(x);
 GA(z,INT,m,1,0); zv=zv0=AV(z);
 if(INT&AT(w)){c=*AV(w); *zv++=c%10; while(c/=10)*zv++=c%10;}
 else{
  DO(n-1, c=*v++; DO(XBASEN, *zv++=c%10; c/=10;););
  c=*v++; if(c||1==n)*zv++=c%10; while(c/=10)*zv++=c%10;
 }
 AN(z)=*AS(z)=n=zv-zv0; 
 zv=zv0; v=zv0+n-1; DO(n/2, c=*zv; *zv++=*v; *v--=c;); /* reverse in place */
 R z;
}    /* "."0@": w */


#define DXBODY(exp)  DECLG;A y=sv->h,z;I m=jt->xmode; jt->xmode=XMFLR; z=exp; jt->xmode=m; R z
#define DX1(f,exp)   DF1(f){DXBODY(exp);} 
#define DX2(f,exp)   DF2(f){DXBODY(exp);}
#define XT(w)        tymes(y,w)

static DX1(postmult1, XT(CALL1(g1,  w,gs)))
static DX2(postmult2, XT(CALL2(g2,a,w,gs)))

static DX1(premult1, CALL1(g1,      XT(w),gs))
static DX2(premult2, CALL2(g2,XT(a),XT(w),gs))

static DX1(ydiv1, CALL2(g2,y,    w,gs))
static DX2(ydiv2, CALL2(g2,XT(a),w,gs))

static DX1(ysqrt, CALL1(g1,tymes(w,XT(y)),gs))