[BACK]Return to tk_fd.rr CVS log [TXT][DIR] Up to [local] / OpenXM / src / asir-contrib / packages / src

File: [local] / OpenXM / src / asir-contrib / packages / src / tk_fd.rr (download)

Revision 1.16, Sun Aug 16 07:10:22 2015 UTC (8 years, 9 months ago) by takayama
Branch: MAIN
CVS Tags: HEAD
Changes since 1.15: +127 -1 lines

tk_fd.fd_hessian2(M,A,B,C,Xval) computes
[F_D,gradient(F_D),Hessian(F_D)]
Example: hfdtest2().

/* $OpenXM: OpenXM/src/asir-contrib/packages/src/tk_fd.rr,v 1.16 2015/08/16 07:10:22 takayama Exp $ */
/*
  2015.05.23   h-mle/FD/Prog/fdpf.rr --> tk_fd.rr
 */
#define USE_MODULE 1
import("names.rr")$
import("ot_hgm_ahg.rr")$   // for check7
import("ok_diff.rr")$  // for check7
import("taka_diffop.rr")$ //  taka_dr1.mult(F,G)  [x,dx]
/* Ref: @s/2014/05/12-my-note-FD-fdpf-rr.pdf   formulas for umat(), dmat()
*/
/* note that M is NOT used. MM! */
/* index は松本論文と同じにする */

#if  !USE_MODULE
extern Alpha$
extern MM$
extern AA$
extern BB$
extern CC$
extern Alpha_ap$  // a+1
extern Alpha_am$ // a-1
extern MyDebug$
// NN is used as a local variable.
/* for fvec_poly */
extern FD_Dmat$
extern FD_AA$
extern FD_BB$
extern FD_CC$
extern FD_XX$
extern YgFD_Dmat$
extern YgFD_AA$
extern YgFD_BB$
extern YgFD_CC$
extern YgFD_XX$
extern Hfd_H$
extern Hfd_M$
extern Hfd_psi$
extern Hfd_F$
extern Hfd_Hess$
extern Hfd_debug$
#else
module tk_fd;
static Alpha$
static MM$
static AA$
static BB$
static CC$
static Alpha_ap$  // a+1
static Alpha_am$ // a-1
static MyDebug$
/* for fvec_poly */
static FD_Dmat$
static FD_AA$
static FD_BB$
static FD_CC$
static FD_XX$
static YgFD_Dmat$
static YgFD_AA$
static YgFD_BB$
static YgFD_CC$
static YgFD_XX$
static Hfd_H$
static Hfd_M$
static Hfd_psi$
static Hfd_F$
static Hfd_Hess$
static Hfd_debug$

localf setparam$
localf setparam_by_number$
localf setparam_by_int$
localf setparam_apm$
localf setparam_abc$
localf getparam$
localf mydebug$
localf intmat$
localf check1$
localf ee$
localf vv$
localf vv0$
localf dxx$
localf xij$
localf psi$
localf mycoefl$
localf xx$
localf yrule$
localf mydiff$
localf check2$
localf mypoch$
localf tk_number_gamma$
localf tk_number_invgamma$
localf fd$
localf check3$
localf check4$
localf fdah$
localf check5$
localf check6$
localf check7$
localf mytruncate$
localf check7b$
localf check8$
localf taka_base_prod$
localf tkdiff_dvar$
localf tkdiff_fac$
localf tkdiff_deg2$
localf tkdiff_mul$
localf check8a$
localf check8b$
localf up_a0$
localf down_a0$
localf up_a$
localf down_a$
localf fdi$
localf helpc$
localf tkdiff_act$
localf check9a$
localf check9b$
localf omega0$
localf const_part$
localf umat$
localf umat_abc$
localf check10$
localf umat_gen$
localf check11$
localf dmat$
localf check12$
localf dmat_gen$
localf dmat_abc$
localf try13$
localf check14$
localf  try15$
localf fvect$
localf xvars$
localf fd15_11$
localf try16$
localf yvars$
localf fdah_poly$
localf ahvec$
localf check17$
localf fvect_poly$
localf check18$
localf tk_number_rattofloat$
localf taka_base_is_zero$
localf taka_base_equal$
localf check7c$
localf check7c_out$
localf fdah_aeqc$
localf feval$
localf check19$
localf check19_out$
localf ah_init_value$
localf ygNmat$
localf ygCmat$
localf ygRmat$
localf ygdmat_abc$
localf ygfvect_poly$
localf ygahvec$
localf ygtry15$
localf marginal2abc$
localf abc2marginal$
localf ygQmat$
localf fdA$
localf hgpoly_fd$
localf hgpoly_fd_beta$
localf hgpoly_fd0$
localf hgpoly_fd_beta0$
localf check21$
localf checkahg$
localf abc2alpha$
localf ygNmat2$
localf ygCmat2$
localf ygRmat2$
localf ygQmat2$
localf beta2marginal$
localf beta2abc$
localf atofd$
localf atofd_beta$
localf check22$
localf checkfd$
localf ygDk$
localf ygDk2$
localf containNegative$
localf check23$
localf ygDc2$
localf ygDc$
localf check24$
localf ygDa2$
localf ygDa$
localf check25$
localf poly_fd$
localf poly_fd_beta$
localf poly_fdvec$
localf poly_fdvec_beta$
localf check26$
localf ygDca2$
localf hgpoly_fd_beta1$
localf check27$
localf hgpoly_fd1$
localf fvect_poly2$
localf check28$
localf check28b$
localf ahvec_beta$
localf ahvec_abc$
localf expectation_abc$
localf abc2ahg$
localf expectation_abc_orig1$
localf ahmat_abc$
localf log_ahmat_abc$
localf fd_hessian2$
localf hfdtest2$
#endif
/* Matsumoto, page 3 */

def setparam(M) {
  MM=M;
 Alpha=newvect(MM+3);
 AA=a;
 BB=newvect(MM+1);
 for (I=1; I<=MM; I++) BB[I] = util_v(b,[I]);
 CC=c;
 Alpha[0]=-CC+base_sum(BB,0,1,MM);
 for (I=1; I<=MM; I++) Alpha[I] = -BB[I];
 Alpha[MM+1] = CC-AA;
 Alpha[MM+2] = AA;
 setparam_apm();
}
def setparam_by_number(M,Seed) {
  MM=M;
 Alpha=newvect(MM+3);
 P=pari(nextprime,Seed);
 AA=1/P;
 BB=newvect(MM+1);
 for (I=1; I<=MM; I++) { P = pari(nextprime,P+1); BB[I] = 1/P; }
 P = pari(nextprime,P+1); CC=1/P;
 Alpha[0]=-CC+base_sum(BB,0,1,MM);
 for (I=1; I<=MM; I++) Alpha[I] = -BB[I];
 Alpha[MM+1] = CC-AA;
 Alpha[MM+2] = AA;
 setparam_apm();
}

def setparam_by_int(M,Seed) {
  MM=M; 
 Alpha=newvect(MM+3);
 P=pari(nextprime,Seed);
 if  (type(getopt(aa)) > 0) AA=-getopt(aa);
 else AA=-13;
 if (AA > 0) AA = -AA;
 BB=newvect(MM+1);
 for (I=1; I<=MM; I++) { P = pari(nextprime,P+1); BB[I] = -P; }
 P = pari(nextprime,P+1); CC = P+20;
 Alpha[0]=-CC+base_sum(BB,0,1,MM);
 for (I=1; I<=MM; I++) Alpha[I] = -BB[I];
 Alpha[MM+1] = CC-AA;
 Alpha[MM+2] = AA;
 setparam_apm();
}

def setparam_apm() {
  Alpha_ap = matrix_clone(Alpha);
  Alpha_am = matrix_clone(Alpha);
  Alpha_ap[MM+1] = CC-(AA+1);
 Alpha_ap[MM+2] = AA+1;
 Alpha_am[MM+1] = CC-(AA-1);
 Alpha_am[MM+2] = AA-1;

}

/*&usage begin:setparam_abc(M,A,B,C)
Set parameters for F_D(A,B,C;x_1,...,x_M)
example: tk_fd.setparam_abc(2,a,[-3,-5],7)
end:
*/
def setparam_abc(M,A,B,C) {
  if (length(B) !=M) error("length(B) != M");
  MM=M;  
 Alpha=newvect(MM+3);
  AA=A;
 BB=newvect(MM+1);
 for (I=1; I<=MM; I++) { P = pari(nextprime,P+1); BB[I] = B[I-1]; }
 P = pari(nextprime,P+1); CC = C;
 Alpha[0]=-CC+base_sum(BB,0,1,MM);
 for (I=1; I<=MM; I++) Alpha[I] = -BB[I];
 Alpha[MM+1] = CC-AA;
 Alpha[MM+2] = AA;
 setparam_apm();
}

/*&usage begin: getparam()
See setparam_abc()
end: */
def getparam() {
   printf("MM(number of variables of F_D)=%a. ",MM);
   printf("AA=%a, BB(ignore first element)=%a, CC=%a\n",AA,BB,CC);
   printf("Alpha(Matsumoto paper)=%a\n",Alpha);
   printf("Alpha_ap(Alpha(a+1)=%a,Alpha_am(Alpha(a-1))=%a\n",Alpha_ap,Alpha_am);
   printf("MyDebug=%a\n",MyDebug);
   return [MM,AA,BB,CC,Alpha,Alpha_ap,Alpha_am,MyDebug];
}
def mydebug(F) {
  MyDebug=F;
}

/* intersection matrix C in page 17. */
def intmat() {
  D = newvect(MM+1);
  D[0] = 1/AA;
  for (I=1; I<=MM; I++) D[I] = -1/BB[I];
  C = matrix_diagonal_matrix(D);
  for (I=0; I<=MM; I++) {
    for (J=0; J<=MM; J++) {
      C[I][J] = C[I][J] + 1/(CC-AA);
    }
  }
  return C;
}

def check1() {
  C = intmat();
  D = red(matrix_det(C));
  printf("%a / ",fctr(nm(D)));
  printf("%a\n",fctr(dn(D)));
}

def ee(I) {
  E=newmat(1,MM+1);
  E[0][I] = 1;
  return E;
}

def vv(I,J) {
  if ((I==0) && (J < MM+1)) return vv0(J);
  else if (J < MM+1) return ee(I)-ee(J);
  /* J == MM+1 */
  return  ee(I);
}

def vv0(J) {
  V=ee(J)+(Alpha[MM+2]/Alpha[0])*ee(0);
  for (K=1; K<=MM; K++) {
    V += ee(K)*(Alpha[K]/Alpha[0]);
  }
  return V;
}

def dxx(I) {
  if (I == 0) return 0;
  if (I == (MM+1)) return 0;
  return util_v(dx,[I]);
}
/* bug: or specification? tk_fd.dx(1) return tk_fd.dx_1
     bug: error in module in loading by cmdasir causes a hung of asirgui.
             e.g.  function is not defined.
def dx(I) {
  if (I == 0) return 0;
  if (I == (MM+1)) return 0;
  return util_v(dx,[I]);
}
*/

/* 1/(x_i-x_j) is expressed as y_{ij} */
def xij(I,J) {
  if (I == J) error("I == J");
  return util_v(y,[I,J]);
}

/*&usage begin:
psi()
It returns the Pfaffian system for F_D in the differential form.
See the paper ... by Matsumoto
and setparam_abc().
[d-psi()] F = 0 where F=(F_D, (x_1-1)/alpha_1 dx_1 F_D, ..., (x_M-1)/alpha_M dx_M F_D)
example: tk_fd.setparam_abc(2,1/2,[1/3,1/5],1/7);
tk_fd.psi();
end:  */
def psi() {
  Psi = newmat(MM+1,MM+1);
  C = intmat();
  for (I=0; I<MM+1; I++) {
    for (J=I+1; J<= MM+1; J++) {
      Psi += Alpha[I]*Alpha[J]*C*(matrix_transpose(vv(I,J))*vv(I,J))*xij(I,J)*(dxx(I)-dxx(J));
    }
  }
  return Psi;
}

/* coef of linear expression in terms of V
   --> should be replaced with new poly_coefficient
 */
def mycoefl(F,V) {
  return poly_coefficient(F,1,V);
}

def xx(I) {
  if (I == 0) return 0;
  if (I == MM+1) return 1;
  return util_v(x,[I]);
}
def yrule() {
  R = [];
  for (I=0; I<MM+1; I++) {
    for (J= I+1; J<=MM+1; J++) {
       R = cons([util_v(y,[I,J]),1/(xx(I)-xx(J))],R);
    }
  }
  return R;
}

def mydiff(F,V) {
  if (type(F) <= 3) return diff(F,V);
  return map(diff,F,V);
}

def check2(M,Seed) {
  MM=M;
  setparam_by_number(M,Seed);
  P=psi();
  P1=base_replace(mycoefl(P,dx_1) ,yrule());
  P2=base_replace(mycoefl(P,dx_2) ,yrule());
  printf("P1=%a, \nP2=%a\n",P1,P2);
  R=mydiff(P1,x_2)+P1*P2-(mydiff(P2,x_1)+P2*P1);
  R=map(red,R);
  return R;
}

/* Series evaluation of FD and A-hg FD */
def mypoch(A,N) {
  if (N==0) return 1;
  R=1;
  for (I=0; I<N; I++) {
    R = R*(A+I);
  }
  return R;
}

/* Gamma(Z) */
/*&usage begin:
tk_number_gamma(Z)
It returns gamma(Z).
When Z is not integer, it gives an approximate value.
  end: */
def  tk_number_gamma(Z) {
  if (number_is_integer(Z)) {
    if (Z <= 0) return(@infty);
    else return fac(Z-1);
  }
  return pari(gamma,Z);
}
/*&usage begin:
tk_number_invgamma(Z)
It returns 1/gamma(Z).
When Z is not integer, it gives an approximate value.
When Z is non-positive integer, it returns 0.
end: */
def  tk_number_invgamma(Z) {
  if (number_is_integer(Z)) {
    if (Z <= 0) return 0;
    else return 1/fac(Z-1);
  }
  return 1/pari(gamma,Z);
}

/*&usage begin:
  fd(A,B,C,X | approx=N, diff=Idx)
  It returns the series for F_D(a,[b_1,...,b_m],c; x_1,...,x_m)
  up to the total degree N when A=a,B=[b_1,...,b_m],C=c,
  X=[x_1,...,x_m].
  When diff=i, the derivative of F_D with respect to x_i is returned.
  X may be numbers.
  example: tk_fd.fd(-3,[1/3,1/5],1/7,[x1,x2] | approx=3);
  end: */
/*
  fd(1/2,[1/3,1/5],1/7,[x1,x2] | approx=3);
  fd(1/2,[1/3,1/5],1/7,[x1,x2] | approx=3,diff=1);
  fd(1/2,[1/3,1/5],1/7,[x1,x2] | approx=3,diff=2);
  fd(1/2,[1/3,1/5],1/7,[1/2,1/3] | approx=3,diff=2);
 */
def fd(A,B,C,X) {
  if (type(getopt(approx)) >=0) Approx=getopt(approx);
  else Approx=2;
  if (type(getopt(diff)) >0) Diff=getopt(diff);
  else Diff=0;
  Diff=Diff-1;
  N=length(X);
  if (N != length(B)) {
    printf("B=%a\n",B);
    printf("X=%a\n",X);
     error("length(B) must be equal to length(X)");
  }
  F=dp_vtoe(newvect(N)); 
  for (I=0; I<N; I++) {
    M=newvect(N); M[I]=1;
    F = F+dp_vtoe(M);
  } 
  E=dp_vtoe(newvect(N));
  for (I=0; I<Approx; I++) {
    E = E*F;
  }
  F=0;
  while (E != 0) {
     M = dp_etov(dp_hm(E));  E = dp_rest(E);
     XX=1;  
     for (I=0; I<N; I++)  {
       if (I != Diff) XX = XX*(X[I])^M[I];
       else if (M[I] > 0) XX = XX*M[I]*(X[I])^(M[I]-1);
       else XX = 0; /* continue */
     }
     S = 0; for (I=0; I<N; I++) S = S+M[I];
     Coef=mypoch(A,S)/mypoch(C,S);   
     for (I=0; I<N; I++) Coef = Coef*mypoch(B[I],M[I])/fac(M[I]);
     F = F+Coef*XX;  
  }
  return F;
}

def check3(N) {
  A=1/2; B=[1/3,1/5,1/11]; C=1/7;
  F=fd(A,B,C,[x1,x2,x3] | approx=N);
  G=x1*diff(F,x1)+x2*diff(F,x2)+x3*diff(F,x3);
  Rule=[[x1,t],[x2,2*t],[x3,3*t]];
  F1=x1*diff(G+(C-1)*F,x1)-x1*(x1*diff(G+A*F,x1)+B[0]*(G+A*F));
  F2=x2*diff(G+(C-1)*F,x2)-x2*(x2*diff(G+A*F,x2)+B[1]*(G+A*F));
  F3=x3*diff(G+(C-1)*F,x3)-x3*(x3*diff(G+A*F,x3)+B[2]*(G+A*F));
  return base_replace([F1,F2,F3],Rule);
}

def check4(N) {
  A=1/2; B=[1/3,1/5,1/11]; C=1/7;
  F=fd(A,B,C,[x1,x2,x3] | approx=N);
  F1=diff(F,x1);
  F2=diff(F,x2);
  F3=diff(F,x3);
  Rule=[[x1,t],[x2,2*t],[x3,3*t]];
  F1=F1-fd(A,B,C,[x1,x2,x3]|approx=N,diff=1);
  F2=F2-fd(A,B,C,[x1,x2,x3]|approx=N,diff=2);
  F3=F3-fd(A,B,C,[x1,x2,x3]|approx=N,diff=3);
  return base_replace([F1,F2,F3],Rule);
}

/*&usage begin:
  fdah(A,B,C;X | approx=N, nogamma=ng, fdfunc=function)
 The return value is [F,Amat,Brule,Gf,Y] where
 F is the A-hypergeometric series associated to F_D(A,B,C;Y)  (truncated
at the degree N with respect to Y) or the matrix Amat and the parameter
vector which is given by Brule.
X is a 2 by (length(B)+1) matrix or list and
Y = [(12,21)/(11,22), (13,21)/(11,33), ... ].
Gf*F is equal to  x^e sum(x^k/gamma(e+k+1), k runs over Ker Amat)
where
e = [[-A,          0, ...,           0],
       [C-1, -B[0], ..., -B[M-1]]].
The default fdfunc function is fd(A,B,C,Y).
Gf is an approximate value and A,B,C must be numbers.  
Ref.  notes at 2014.05.*,  tk_fd.fd(),  try13().
example: tk_fd.fdah(-3,[-6,-1,-1],11,
    [[x11,x12,x13,x14],
     [x21,x22,x23,x24]] | approx=4);
  end: */
/*
  fdah(1/2,[1/3,1/5,1/11],1/7,
    [[x11,x12,x13,x14],
     [x21,x22,x23,x24]]);
 */
def fdah(A,B,C,Y) {
  /*
      -A,      0,      0,      0
    C-1,-B[0],-B[1],-B[2]
  */
  Optlist=getopt();
  NoGamma = getopt(nogamma);
  if (type(NoGamma)<0) NoGamma=0;
  FDfunc = getopt(fdfunc);
  if (type(FDfunc)<0) FDfunc=0;
   N=length(B); 
   X=newvect(N);
   for (I=0; I<N; I++) {
     X[I] = Y[0][I+1]*Y[1][0]/(Y[0][0]*Y[1][I+1]);
   }
   /* return X; */
   U = (Y[0][0]^(-A))*(Y[1][0]^(C-1));
   for (I=0; I<N; I++) {
     U = U*(Y[1][I+1])^(-B[I]);
   }

   NN=N+1;
   Amat=newmat(NN+1,2*NN);
   for (I=0; I<NN; I++) Amat[0][I] = 1;
   for (I=0; I<NN; I++) {Amat[I+1][I] = 1; Amat[I+1][NN+I]=1; }
   Rule=[[b_2,C-A-1],[b_1,-A]];
   for (I=0; I<N; I++) Rule=cons([util_v(b,[I+3]),-B[I]],Rule);
   Rule = reverse(Rule);

   /* Gamma factors, todo double check */
   if (NoGamma) {
     Gamma = "[1/gamma(e+1)]";
   }else{
    Gamma=tk_number_invgamma(-A+1)*tk_number_invgamma(C-1+1);
    for (I=0; I<N; I++) {
      Gamma=Gamma*tk_number_invgamma(-B[I]+1);
    }
   }
  
   if (FDfunc == 0) {
     Val = red(U*fd(A,B,C,X | option_list=Optlist));
   }else if (type(FDfunc) == 2) {
     Val=red(U*(*FDfunc)(A,B,C,X | option_list=Optlist));
   } else {
     Val = red(U*FDfunc);
   }
   return [Val,matrix_matrix_to_list(Amat),Rule,Gamma,X];
}

def check5(N) {
  /*
      -A,      0,      0,      0
    C-1,-B[0],-B[1],-B[2]
  */
  /*  A=1/2; B=[1/3,1/5,1/11]; C=1/7; */
  A=-5; B=[-3,-5,-11]; C=7;
  NN = length(B)+1;
  Y = newmat(2,NN);
  for (I=0; I<2; I++) for (J=0; J<NN; J++)  Y[I][J] = util_v(x,[I,J]);
  Rule = [[Y[0][0],1],[Y[1][0],1]];
  for (J=1; J<NN; J++) {
    Rule = cons([Y[0][J],J*t/100],Rule);
    Rule = cons([Y[1][J],1],Rule);
  }
  printf("Rule=%a\n",base_replace(Y,Rule));
  F = fdah(A,B,C,Y | approx=N)[0];
  /* print(F); */
  S=0;
  for (J=0; J<NN; J++)  S += Y[0][J]*diff(F,Y[0][J]);
  S = base_replace(S-(-A)*F,Rule);
  printf("111000: %a\n",eval(S));

  S=0;
  for (J=0; J<NN; J++)  S += Y[1][J]*diff(F,Y[1][J]);
  S = base_replace(S-(C-1-B[0]-B[1]-B[2])*F,Rule);
  printf("000111: %a\n",eval(S));

  for (J=1; J<NN; J++)  {
    S = diff(diff(F,Y[0][0]),Y[1][J])-diff(diff(F,Y[0][J]),Y[1][0]);
    S = base_replace(S,Rule);
    printf("00 1%a - 10 0%a: %a\n",J,J,eval(S));
  }
}

def check6(N) {
  A=1/2; B=[1/3,1/5,1/11]; C=1/7;
  NN = length(B)+1;
  Y = newmat(2,NN);
  for (I=0; I<2; I++) for (J=0; J<NN; J++)  Y[I][J] = util_v(x,[I,J]);
  Rule = [[Y[0][0],1],[Y[1][0],1]];
  for (J=1; J<NN; J++) {
    Rule = cons([Y[0][J],J/20],Rule);
    Rule = cons([Y[1][J],1],Rule);
  }
  printf("Rule=%a\n",base_replace(Y,Rule));
  FF = fdah(A,B,C,Y | approx=N);
  BRule=FF[2];
  F = FF[0];

  S=0;
  for (J=0; J<NN; J++)  S += Y[0][J]*diff(F,Y[0][J]);
  S = base_replace(S-b_1*F,append(Rule,BRule));
  printf("11110000: %a\n",eval(S));

  for (J=0; J<NN; J++) {
     S=Y[0][J]*diff(F,Y[0][J])+Y[1][J]*diff(F,Y[1][J]);
     S = base_replace(S-util_v(b,[J+2])*F,append(Rule,BRule));
     printf("J=%a : %a\n",J,eval(S));
  }
  return FF;
}

/* 
  import("ot_hgm_ahg.rr"); 
  import("ok_diff.rr");
*/
def check7(N) {
  if (type(getopt(need_grad)) >0) NeedGrad=getopt(need_grad);
  else NeedGrad=0;
  if (type(getopt(check)) >0) Check=getopt(check);
  else Check=0;
  A=1/2; B=[1/3,1/5,1/11]; C=1/7;
  NN = length(B)+1;
  Y = newmat(2,NN,[[x1,x2,x3,x4],[x5,x6,x7,x8]]);
  Dir =newmat(2,NN,[[0,1/2,1/3,1/4],[0,0,0,0]]);
  Eps = 1/10;
  Rule = [[Y[0][0],1],[Y[1][0],1]];
  for (J=1; J<NN; J++) {
    Rule = cons([Y[0][J],J/20],Rule);
    Rule = cons([Y[1][J],1],Rule);
  }
  Point = base_replace(Y,Rule);
  printf("Point=%a\n",Point);
  FF = fdah(A,B,C,Y | approx=N);
  F = FF[0];
  Amat = FF[1];
  BRule=FF[2];
  Bvec=newvect(NN+1);
  for (I=0; I<NN+1; I++) Bvec[I] = util_v(b,[I+1]);
  Ahg=tk_sm1emu.gkz([Amat,vtol(newvect(NN+1))]);
  // print(Ahg[0]);
  V = Ahg[1];
  if  (Check) {
    for (I=0; I<length(Ahg[0]); I++) {
      if (I<NN+1) Op=base_replace(Ahg[0][I]-Bvec[I],BRule);
      else Op=base_replace(Ahg[0][I],BRule);
      RR=eval(base_replace(odiff_act(Op,F,V),Rule));
      printf("Ahg[0][%a] F = %a\n",I,RR);
    }
  }
  Base=cbase(Amat);
  printf("Base=%a\n",Base);
  Iv=map(odiff_act,Base,F,V);
  Iv=map(eval,base_replace(Iv,Rule));

  Point2 = newmat(2,NN);
  for (I=0; I<2; I++)  for (J=0; J<NN; J++)  Point2[I][J] = Point[I][J] + Eps*Dir[I][J];
  Rule2=[];
  for (I=0; I<2; I++)  for (J=0; J<NN; J++)  Rule2=cons([Y[I][J],Point2[I][J]],Rule2);
  Iv2=map(odiff_act,Base,F,V);
  Iv2=map(eval,base_replace(Iv2,Rule2));

  if (NeedGrad) {
   Grads=[dx1,dx2,dx3,dx4,dx5,dx6,dx7,dx8];
   Grad=map(odiff_act,Grads,F,V);
   Grad=map(eval,base_replace(Grad,Rule));
  }

  return [Amat,V,BRule,[base_flatten(Dir),Eps],[base_flatten(Point),Iv],[base_flatten(Point2),Iv2],Grad];
}
/*
  R=check7(N);   N : approximation degree.
  R[0]   Matrix A
  R[1]   list of variables
  R[2]   Values of b_1, b_2, ....   
  R[3]   [Direction, Epsilon]
  R[4]   [Initial Point,  values]
  R[5]   [Termination Point,  values]
  values are sorted in the order of cbase(R[0]);
  Termination Point = Initia Point + base_flatten(R[3][0])*R[3][1]
  R[6]  grad F at the initial point.  (need_grad=1)
 */

/* Todo, move to number_truncate */
def  mytruncate(F) {
  if (number_abs(F) < 10^(-10)) return 0;
  else return F;
}
/*
import("ot_hgm_ahg.rr");
 P=get_mat2(A,W,Std,Mset); の時
 Mat=P[0]; RM=P[1]; Supp2=P[2]; とおくと,
 Mat*Supp2 = RM*Std
 が成り立つ.  cf. test3b();
*/
def check7b(N) {
  if (type(getopt(z)) >0) Eps=getopt(z);
  else Eps=0;

  A=1/2; B=[1/3,1/5,1/11]; C=1/7;
  NN = length(B)+1;
  Y = newmat(2,NN,[[x1,x2,x3,x4],[x5,x6,x7,x8]]);
  Dir =newmat(2,NN,[[0,1/2,1/3,1/4],[0,0,0,0]]);
  Rule = [[Y[0][0],1],[Y[1][0],1]];
  for (J=1; J<NN; J++) {
    Rule = cons([Y[0][J],J/20],Rule);  /* J/6 もやってみた. N must be large N=15 でようやく 0.000xxxx  */
    Rule = cons([Y[1][J],1],Rule);
  }
  Point = base_replace(Y,Rule);

  for (I=0; I<2; I++)  for (J=0; J<NN; J++)  Point[I][J] = Point[I][J] + Eps*Dir[I][J];

  printf("Point=%a\n",Point);
  FF = fdah(A,B,C,Y | approx=N);
  F = FF[0];
  Amat = FF[1];
  BRule=FF[2];
  GammaF=FF[3];  printf("Gamma factor is %a\n",GammaF);
  Bvec=newvect(NN+1);
  for (I=0; I<NN+1; I++) Bvec[I] = util_v(b,[I+1]);
  Ahg=tk_sm1emu.gkz([Amat,vtol(newvect(NN+1))]); /* Note: b_i's are 0 */
  V = Ahg[1];
  Base=cbase(Amat); Std=Base;
  printf("Base=%a\n",Base);
  Mset=[dx1,dx2,dx3,dx4,dx5]; // Mset=0;  We may try other Mset 
  P=get_mat2(Amat,0,Std,Mset); 
  Mat=P[0]; RM=P[1]; Supp2=P[2];
  
  Supp2v = map(odiff_act,Supp2,F,V);
  Supp2v = map(eval,base_replace(Supp2v,append(Rule,BRule)));
  Supp2v = ltov(Supp2v);
  Stdv = map(odiff_act,Std,F,V);
  Stdv = map(eval,base_replace(Stdv,append(Rule,BRule)));
  Stdv = ltov(Stdv);
  printf("Point=%a\nStd=%a\n",base_flatten(Point),vtol(Stdv));
  Matv = map(eval,base_replace(Mat,append(Rule,BRule)));
  RMv = map(eval,base_replace(RM,append(Rule,BRule)));
  // debug();
  Ans=  Matv*Supp2v - RMv*Stdv;
  return map(mytruncate,Ans);
}

/* 2014.05.05 */
def check8() {
  /* formula  1 */
  F=(x*dx+1-x/(x-1));
  G=((x-1)/(a*x))*x*dx;
  Ans=taka_dr1.mult(F,G) - taka_dr1.mult(((x-1)/(a*x))*x*dx,x*dx);
  printf("fomula1 = %a\n",Ans);
  /* formula 2 */
  F=((x-1)/(a*x))*x*dx;
  Ans=taka_dr1.mult(F,1-x)-((1-x)*((x-1)/(a*x))*x*dx-(x-1)/a);
  printf("fomula2 = %a\n",Ans);
  /* formula 1' */
}
/* 2014.05.06 */
/*&usage begin:
taka_base_prod(E,V,From,To)
returns  E[From]*E[From+1]*...*E[To].
The variable V runs over [From,To]
Ref.  base_sum
example:  taka_base_prod([1,2,3,4],0,0,3);
  end: */
def taka_base_prod(E,V,From,To) {
  Ans=1;
  if (type(V) == 0) {
    for (I=From; I<=To; I++) {
      Ans = Ans*E[I];
    }
  }else{
    error("not implemented.");
  }
  return Ans;
}
/*&usage begin:
tkdiff_dvar(V)
It returns dV.
  end: */
def tkdiff_dvar(V) {
  if ((type(V) < 4) || (type(V) == 7))  return eval_str("d"+rtostr(V));
  else map(tkdiff_dvar,V);
}
/*&usage begin:
tkdiff_fac(E)
It returns E!
When E is a list, it returns (E[0]!)*(E[1]!)*(E[2]!)*...
  end: */
def tkdiff_fac(E) {
  if (type(E) < 4) return fac(E);
  E=map(fac,E);
  return taka_base_prod(E,0,0,length(E)-1);
}
def tkdiff_deg2(V,F) { return deg(F,V); }
/*&usage begin:
tkdiff_mul(F,G,V)
It returns F*G in the ring of differential operators with rational function
coefficients Q(V)[dV].
example: tkdiff_mul( (1/x)*(x*dx+y*dy+a), (1/(x-y))*dx,[x,y]);
  end: */
def tkdiff_mul(F,G,V) {
  DV=tkdiff_dvar(V);
  DDV=tkdiff_dvar(DV);
  F1=nm(F); F2=dn(F);
  Deg=map(tkdiff_deg2,DV,F2);
  Deg=base_sum(Deg,0,0,length(Deg)-1);
  if (Deg > 0) error("Denominator contains differential operator.");  
  Deg=map(tkdiff_deg2,DV,F1);
  Deg=base_sum(Deg,0,0,length(Deg)-1);
  
  N=length(V);
  F=dp_vtoe(newvect(N)); 
  for (I=0; I<N; I++) {
    M=newvect(N); M[I]=1;
    F = F+dp_vtoe(M);
  } 
  E=dp_vtoe(newvect(N));
  for (I=0; I<Deg; I++) {
    E = E*F;
  }
  Ans=0;
  while (E != 0) {
     Mop = dp_ht(E);  M=dp_etov(Mop); E = dp_rest(E);
     C = 1/tkdiff_fac(M);
     P = odiff_act(dp_dtop(Mop,DDV),F1,DV);
     Q = odiff_act(dp_dtop(Mop,DV),G,V);
     Ans = Ans+C*P*Q;
  }
  return red(Ans/F2);
}
/*
  F=x*y*(dx+dy)^2; G=(x*dx+y*dy+z*dz)^3; 
  tk_sm1emu.mul(F,G,[x,y,z])-tkdiff_mul(F,G,[x,y,z]);
 */
/* note, 05.04 */
def check8a(II) {
  N=MM;
  V=[];
  for (I=1; I<=N; I++) V=cons(util_v(x,[I]),V);
  V=reverse(V);
  F = 0;
  for (I=1; I<=N; I++) {
    F += util_v(x,[I])*tkdiff_dvar(util_v(x,[I]));
  }
  F=(1/(CC-AA-1))*(F+AA);
  Xi=util_v(x,[II]); Di=tkdiff_dvar(Xi);
  Fi=((Xi-1)/(Xi*Alpha[II]))*Xi*Di;
  F = tkdiff_mul(Fi, F,V);

  G = up_a0(II);
  return F-tkdiff_mul(G,Fi,V);
}
def check8b(II) {
  N = MM;
  V=[];
  for (I=1; I<=N; I++) V=cons(util_v(x,[I]),V);
  V=reverse(V);
  F = 0;
  for (I=1; I<=N; I++) {
    F += (1-util_v(x,[I]))*util_v(x,[I])*tkdiff_dvar(util_v(x,[I]));
  }
  Bop = 0;
  for (I=1; I<=N; I++) Bop += BB[I]*util_v(x,[I]);
  Fac=1/(AA-1);
  F=Fac*(F+CC-AA-Bop);
  Xi=util_v(x,[II]); Di=tkdiff_dvar(Xi);
  Fi=((Xi-1)/(Xi*Alpha[II]))*Xi*Di;
  F = tkdiff_mul(Fi, F,V);

  Gall = down_a0(II);
  G=Gall[0]; G0=Gall[1];

  /*
  print(red(tkdiff_mul(Fi,Xi,V)-Xi*Fi));
  print(red(G0));
  */
  return F-(tkdiff_mul(G,Fi,V)+G0);
}
/* 2014.05.07 */
/* 1<= II <= MM */
def up_a0(II) {
  N=MM;
  Xi=util_v(x,[II]); Di=tkdiff_dvar(Xi);
  G = 0;
  for (I=1; I<=N; I++) {
    if (I != II) G += util_v(x,[I])*tkdiff_dvar(util_v(x,[I]));
  }
  G = (1/(CC-AA-1))*(G+AA);
  if (II > 0) G = G+(1/(CC-AA-1))*(Xi*Di+1-Xi/(Xi-1));
  return G;
}
def down_a0(II) {
  N=MM;
  Xi=util_v(x,[II]); Di=tkdiff_dvar(Xi);
  G = 0;
  for (I=1; I<=N; I++) {
    if (I != II) G += (1-util_v(x,[I]))*util_v(x,[I])*tkdiff_dvar(util_v(x,[I]));
  }
  Bop = 0;
  Fac=1/(AA-1);
  for (I=1; I<=N; I++) Bop +=  BB[I]*util_v(x,[I]);
  G = Fac*(G+(CC-AA)-Bop);
  G0=0;
  if (II > 0) {
    G = G+Fac*((1-Xi)*(Xi*Di+1-Xi/(Xi-1)) - Xi);
    G0=-Fac*(BB[II]*(util_v(x,[II])-1))/Alpha[II];
  }
  return [G,G0];
  /*  G fi(aa) +G0 f0(aa) = const fi(aa-1)
   */
}
/* 2014.05.08 (Thu) */
/*
  f_i (a+1) = up_a(i) f_i
 */
def up_a(II) {
  G = up_a0(II);
  G = G*(Alpha[II]/Alpha_ap[II]);
  return G;
} 
/*
  f_i (a-1) = down_a(i)[0] f_i + down_a(i)[1] f_0
 */
def down_a(II) { 
  Gall = down_a0(II);
  G = Gall[0]; G0 = Gall[1];
  Fac = (Alpha[II]/Alpha_am[II]);
  G = G*Fac;
  G0 = G0*Fac;
  return [G,G0];
}
/*&usage begin:
fdi(A,B,C,X,II | gamma=gm)
It returns f_i in the paper of Matsumoto.
F=[f_0, f_1, ..., f_m] satisfies  dF - psi() F = 0.
example: Param=tk_fd.setparam_abc(2,-2,[-3,-4],3);
  F=[tk_fd.fdi(Param[1],Param[2],Param[3],0 | approx=3),
       tk_fd.fdi(Param[1],Param[2],Param[3],1 | approx=3),
       tk_fd.fdi(Param[1],Param[2],Param[3],2 | approx=3)];
  map(red,tkdiff_diff(F,x_1)-omega0(psi(),1)*F);
  The result should be 0.
  end: */
/* Matsumoto f_i ,  i=0,...,m
     if gamma=1, then gamma factor is multiplied.
     In default, the gamma factor is not multiplied. Then fdi(A,B,C,0) = F_D.
 */
def fdi(A,B,C,X,II) {
  Approx = getopt(approx);
  if (type(Approx) < 0) Approx=2;
  Gamma = getopt(gamma);
  if (type(Gamma)<0) Gamma=0;
  if (II==0) Diff=0; else Diff=II;
  /* set alpha */
  N = length(B);
  MyAlpha=newvect(N+3);
  MyAlpha[0]=-C+base_sum(B,0,0,N-1);
  for (I=1; I<=N; I++) MyAlpha[I] = -B[I-1];
  MyAlpha[N+1] = C-A;
  MyAlpha[N+2] = A;
  if (Diff > 0) {
    Xi = X[II-1];
    F= ((Xi-1)/MyAlpha[II])*fd(A, B, C, X  |  diff=Diff, approx=Approx);
    if (Gamma == 1) {
      F=F*tk_number_gamma(A)*tk_number_gamma(C-A)*tk_number_invgamma(C);
    }
    return F;
  } else {
    F= fd(A, B, C, X  |  approx=Approx);
    if (Gamma == 1) {
      F=F*tk_number_gamma(A)*tk_number_gamma(C-A)*tk_number_invgamma(C);
    }
    return F;
  }

}
/* Todo, move to names.rr */
def helpc() {
  C="start "+getenv("APPDATA")+"\\OpenXM\\doc\\asir-contrib\\ja\\cman-html\\cman-ja_toc.html";
  shell(C);
}
/*&usage begin:
tkdiff_act(L,F,V)
example: tkdiff_act((1/x)*dx+y*dy+a, 1/(x-y),[x,y]);
  end: */
def  tkdiff_act(L,F,V) {
  G=odiff_act(nm(L),F,V);
  return red(G/dn(L));
}
// MM=1; check9a(0,3); check9a(1,3);
def check9a(II,Approx) {
  setparam_by_int(MM,2)$
  printf("MM=%a; setparam(); is the default.\n",MM)$
  printf("To change do MM=number and check9 \n")$ 
    V=[];
  for (I=1; I<=MM; I++) V=cons(util_v(x,[I]),V);
  V = reverse(V);
  G=up_a(II)*(CC-AA-1)/AA;  // no gamma, note 2014.05.08 13:15
  printf("II=%a\n",II);
  Fi = fdi(AA,cdr(vtol(BB)),CC,V,II | approx=Approx);
  printf("G(operator)=%a\n",G);
  printf("Fi=%a\n",Fi);
  //  debug();
  A=tkdiff_act(G,Fi,V)-fdi(AA+1,cdr(vtol(BB)),CC,V,II | approx=Approx);
  return A;
}
/* 2014.05.09 */
// MM=1; check9b(0,5); check9b(1,5)  Approx must be large.
// MM=2; check9b(0,8); check9b(1,8); check9b(2,8); 
def check9b(II,Approx) {
  setparam_by_int(MM,2)$
  printf("MM=%a; setparam(); is the default.\n",MM)$
  printf("To change do MM=number and check9b \n")$ 
    V=[];
  for (I=1; I<=MM; I++) V=cons(util_v(x,[I]),V);
  V = reverse(V);
  Gall=down_a(II);
  Fac= (AA-1)/(CC-AA); // no gamma, note 2014.05.08 13:15
  G=Gall[0]*Fac;
  G0=Gall[1]*Fac;
  printf("II=%a\n",II);
  Fi = fdi(AA,cdr(vtol(BB)),CC,V,II | approx=Approx);
  F0 = fdi(AA,cdr(vtol(BB)),CC,V,0| approx=Approx);
  printf("Gall(operator)=%a\n",Gall);
  printf("Fi=%a\n",Fi);
  //  debug();
  A=tkdiff_act(G,Fi,V)+G0*F0-fdi(AA-1,cdr(vtol(BB)),CC,V,II | approx=Approx);
  return A;
}
/* 2014.05.09 9:24 */
/*&usage begin:
omega0(P,II) 
end: */
/* P=psi();  F=(tild f_0, ..., tild f_m)
   dx_i F = omega0(P,i)*F
*/
def omega0(P,II) {
  Xrule = getopt(xrule);
  if (type(Xrule)<0) Xrule=0;
  Dx_i = util_v(dx,[II]);
  Yrule=yrule();
  if (Xrule != 0) Yrule=base_replace(Yrule,Xrule);
  Om = map(red,base_replace(mycoefl(P,Dx_i),Yrule));
  return Om;
}
def const_part(Op) {
  N=M=MM;
  Rule=[];
  for (I=1; I<=N; I++) {
    Rule = cons([util_v(dx,[I]),0],Rule);
  }
  return red(base_replace(Op,Rule));
}
/*&usage begin:
umat_abc(A,B,C | xrule=Rule)
 The recurrence relation F(A+1) = umat_abc()*F(A) holds 
 for 
 F(A)=[fdi(A,B,C,X,0), fdi(A,B,C,X,1), ..., fdi(A,B,C,X,M)].
 Ref.  check10(), check11(), fvect().
 example: 
 U=tk_fd.umat_abc(a,[-2,-3],5|xrule=[[x_1,1/2],[x_2,1/3]]);
end: */
def umat_abc(A,B,C) {
  Opt =getopt();
  M=length(B);
  setparam_abc(M,A,B,C);
  return umat(|option_list=Opt);
}
/*
   F(AA+1) = umat()*F(A)
 */
def umat() {
  Xrule=getopt(xrule);
  if (type(Xrule)<0) Xrule=0;
  N=M=MM;
  Omat = newvect(N+1); P=psi();
  if (Xrule != 0) P = map(red,base_replace(P,Xrule));
  for (I=1; I<=N; I++) Omat[I] = omega0(P,I | option_list=getopt());
  Umat=newmat(N+1,N+1);
  for (I=0; I<=N; I++) {
    TildU = up_a(I)*(CC-AA-1)/AA;  // no gamma, note 2014.05.08 13:15
    if (Xrule != 0) TildU = map(red,base_replace(TildU,Xrule));
    ConstPart = const_part(TildU);  
    F_i = util_v(f,[I]);
    TildU = (TildU-ConstPart)+ConstPart*F_i;
    Rule = [];
    for (J=1; J<=N; J++) {
      Omj = 0;
      for (K=0; K<=N; K++) {
        F_k = util_v(f,[K]);
        Omj += Omat[J][I][K]*F_k;
      }
      Dx_j = util_v(dx,[J]);
      Rule = cons([Dx_j,Omj],Rule);
    }
    T = base_replace(TildU,Rule);
    for (J=0; J<=N; J++)  {
      F_j = util_v(f,[J]);
      Umat[I][J] = red(mycoefl(T,F_j));
    }
  }
  return Umat;
}
/*
 MM=1$ setparam()$  
   ---> これでは 0 にならないが, 数にすると mod x^(large num) で 0 となるのが見える.
*/
def check10(Approx) {
  N=M=MM;
  V=[];
  for (I=1; I<=N; I++) V=cons(util_v(x,[I]),V);
  V = reverse(V);
  F=newvect(N+1);
  for (I=0; I<=N; I++) F[I] = fdi(AA,cdr(vtol(BB)),CC,V,I | approx=Approx);
  /* check code of diff eq */
  T=map(diff,F,x_1)-omega0(psi(),1)*F;
  printf("T(should be 0)=%a\n",map(red,T));

  Fa =  newvect(N+1);
  for (I=0; I<=N; I++) Fa[I] = fdi(AA+1,cdr(vtol(BB)),CC,V,I | approx=Approx);
  Umat=umat();
  A=Fa-Umat*F;
  return map(red,A);
}
def  umat_gen(M) {
  Opt=getopt();
  MM=M;
  setparam(M);
  return umat(|option_list=Opt);
}
def check11() {
  MM=2;
  N=M=MM;
  Umat=umat_gen(MM);
  setparam_by_int(MM,2); 
  Approx = -AA+3;
  Rule=[[x_1,1/3],[x_2,1/2],[b_1,BB[1]],[b_2,BB[2]],[c,CC]];
  Umat = base_replace(Umat,Rule);
  F=newvect(N+1);
  V=[x_1,x_2];
  for (I=0; I<=N; I++) F[I] = fdi(AA,cdr(vtol(BB)),CC,V,I | approx=Approx);
  F=base_replace(F,Rule);
  for (I=0; I<-AA; I++) {
    RuleA=[[a,AA+I]];
    Umat = base_replace(Umat,RuleA);
    printf("I=%a, F=%a\n",I,F);
    // todo, 値が正しいかの check を加える.
    F = Umat*F;
  }
  return Umat;
}
/*  Ref: note 2014.05.09 16:20   Use the result of W.Miller.
   F(AA-1) = dmat()*F(A)
 */
def dmat() {
  Xrule=getopt(xrule);
  if (type(Xrule)<0) Xrule=0;
  N=M=MM;
  Omat = newvect(N+1); P=psi();
  if (Xrule != 0) P=map(red,base_replace(P,Xrule));
  for (I=1; I<=N; I++) Omat[I] = omega0(P,I | option_list=getopt());
  Umat=newmat(N+1,N+1);
  for (I=0; I<=N; I++) {
    Fac= (AA-1)/(CC-AA); // no gamma, note 2014.05.08 13:15
    Gall = down_a(I);
    if (Xrule != 0) Gall=map(red,base_replace(Gall,Xrule));
    TildU = Gall[0]*Fac;
    ConstPart = const_part(TildU);  
    F_i = util_v(f,[I]);
    TildU = (TildU-ConstPart)+ConstPart*F_i;
    F_0 = util_v(f,[0]); TildU += Gall[1]*Fac*F_0;  // correction for down.
    Rule = [];
    for (J=1; J<=N; J++) {
      Omj = 0;
      for (K=0; K<=N; K++) {
        F_k = util_v(f,[K]);
        Omj += Omat[J][I][K]*F_k;
      }
      if (MyDebug) printf("I=%a, J=%a, K=%a, Omj=%a\n",I,J,K,Omj);
      Dx_j = util_v(dx,[J]);
      Rule = cons([Dx_j,Omj],Rule);
    }
    T = base_replace(TildU,Rule);
    for (J=0; J<=N; J++)  {
      F_j = util_v(f,[J]);
      Umat[I][J] = red(mycoefl(T,F_j));
    }
  }
  return map(red,Umat);
}
def check12(Approx) {
  N=M=MM;
  V=[];
  for (I=1; I<=N; I++) V=cons(util_v(x,[I]),V);
  V = reverse(V);
  F=newvect(N+1);
  for (I=0; I<=N; I++) F[I] = fdi(AA,cdr(vtol(BB)),CC,V,I | approx=Approx);

  Fa =  newvect(N+1);
  for (I=0; I<=N; I++) Fa[I] = fdi(AA-1,cdr(vtol(BB)),CC,V,I | approx=Approx);
  Dmat=dmat();
  A=Fa-Dmat*F;
  return map(red,A);
}
def  dmat_gen(M) {
  Opt=getopt();
  MM=M;
  setparam(MM);
  return dmat(|option_list=Opt);
}
/*&usage begin:
dmat_abc(A,B,C | xrule=Rule)
 The recurrence relation F(A-1) = dmat_abc()*F(A) holds
 for  
 F(A)=[fdi(A,B,C,X,0), fdi(A,B,C,X,1), ..., fdi(A,B,C,X,M)],
 Ref.  try13().  fvect()
 example: 
 U=tk_fd.dmat_abc(a,[-2,-5],11|xrule=[[x_1,1/2],[x_2,1/3]]);
end: */
def dmat_abc(A,B,C) {
  Opt=getopt();
  M=length(B);
  setparam_abc(M,A,B,C);
  return dmat(|option_list=Opt);
}
def try13() {
  B=[-6,-1,-1];
  C=11;
  A=dmat_abc(a,B,C);
  V=[x_1,x_2,x_3];
  A=matrix_matrix_to_list(A);
  F=fd(a,B,C,V | approx=10);
  if ((F-fd(a,B,C,V | approx=11)) != 0) error("increase approx.");
  return [A,F];
}
/* 
Performance check when X's are integers.
M can be 8 or 9.   2014.05.10
 */
def check14(M) {
  MM=N=M;
  setparam_by_int(M,2);
  Xrule=[]; 
  P=2;
  for (I=1; I<=N; I++) {
    P = pari(nextprime,P+1);
     Xrule=cons([util_v(x,[I]),1/P],Xrule);
  }
  AA=a;
  dmat(|xrule=Xrule);
}

def taka_base_is_zero(Obj) {
  if (type(Obj) < 4) {
    if (Obj == 0) return 1;
    else return 0;
  }
  for (I=0; I<length(Obj); I++) {
    if (!taka_base_is_zero(Obj[I])) return 0;
  }
  return 1;
}
def taka_base_equal(Obj1,Obj2) {
  if (type(Obj1) != type(Obj2)) {
    return 0;
  }
  if ((type(Obj1) < 4) || (type(Obj1) == 7)) return( Obj1 == Obj2);
  if ((type(Obj1) == 4) || (type(Obj1) == 5)) {
    if (length(Obj1) != length(Obj2)) return 0;
    for (I=0; I<length(Obj1); I++) {
      if (!taka_base_equal(Obj1[I],Obj2[I])) return 0;
    }
    return 1;
  }
  if (type(Obj1) == 6) {
    if (!taka_base_equal(size(Obj1),size(Obj2))) return 0;
    S=size(Obj1);
    for (I=0; I<S[0]; I++) {
      for (J=0; J<S[1]; J++) {
        if (!taka_base_equal(Obj1[I][J],Obj2[I][J])) return 0;
      }
    }
    return 1;
  }  
  error("Not implemented (taka_base_equal).");  /* todo */
}
def try15(M) {
  A=a;
  B=newvect(M);
  for (I=0; I<M; I++) B[I] = -31*(I+1);
  C=30;
  Xrule=[];
  for (I=1; I<=M; I++) Xrule=cons([util_v(x,[I]),1/(I+1)],Xrule);
  Xrule=reverse(Xrule);
  setparam_abc(M,A,B,C);
  getparam();  printf("Xrule=%a\n",Xrule);
  Dmat=dmat_abc(A,B,C | xrule=Xrule);

  /* check */
  Aval = -3;
  Fam = fvect(Aval-1,B,C,base_replace(xvars(M),Xrule) | approx=-Aval+1);
  Fa = fvect(Aval,B,C,base_replace(xvars(M),Xrule) | approx=-Aval+1);
  T=Fam - base_replace(Dmat,[[a,Aval]])*Fa;
  printf("If %a is not zero vector , then there is an error.\n",T);
  return Dmat;
}

/*&usage begin:
xvars(M)
returns [x_1,...,x_M].
  end: */
def xvars(M) {
  V=[];
  for (I=1; I<=M; I++) V=cons(util_v(x,[I]),V);
  return reverse(V);
}
/*&usage begin:
fvect(A,B,C,X | approx=N) 
returns  the vector
F=[fdi(A,B,C,X,0), fdi(A,B,C,X,1), ..., fdi(A,B,C,X,M)].
It satisfies dF - psi() F and recurrences generated by umat_abc() and dmat_abc().
Ref.  fdi()
example: tk_fd.fvect(-3,[-2,-5],4, [1/2,1/3] | approx=3);
  end: */
def fvect(A,B,C,X) {
  Opt = getopt();
  N=length(B);
  Fa =  newvect(N+1);
  for (I=0; I<=N; I++) Fa[I] = fdi(A,B,C,X,I | option_list=Opt);
  return Fa;
}

/* fd for the parameter try15(11) */
def fd15_11(A,B,C,X) {
  /* output of try15(11); */
  Dmat=
[[(a-8476789/27720)/(a-30),(31/2)/(a-30),(62/3)/(a-30),(93/4)/(a-30),(124/5)/(a-30),(155/6)/(a-30),(186/7)/(a-30),(217/8)/(a-30),(248/9)/(a-30),(279/10)/(a-30),(310/11)/(a-30),(341/12)/(a-30)],[(-1/2*a+1/2)/(a-30),(1/2*a-1/2)/(a-30),0,0,0,0,0,0,0,0,0,0],[(-2/3*a+2/3)/(a-30),0,(2/3*a-2/3)/(a-30),0,0,0,0,0,0,0,0,0],[(-3/4*a+3/4)/(a-30),0,0,(3/4*a-3/4)/(a-30),0,0,0,0,0,0,0,0],[(-4/5*a+4/5)/(a-30),0,0,0,(4/5*a-4/5)/(a-30),0,0,0,0,0,0,0],[(-5/6*a+5/6)/(a-30),0,0,0,0,(5/6*a-5/6)/(a-30),0,0,0,0,0,0],[(-6/7*a+6/7)/(a-30),0,0,0,0,0,(6/7*a-6/7)/(a-30),0,0,0,0,0],[(-7/8*a+7/8)/(a-30),0,0,0,0,0,0,(7/8*a-7/8)/(a-30),0,0,0,0],[(-8/9*a+8/9)/(a-30),0,0,0,0,0,0,0,(8/9*a-8/9)/(a-30),0,0,0],[(-9/10*a+9/10)/(a-30),0,0,0,0,0,0,0,0,(9/10*a-9/10)/(a-30),0,0],[(-10/11*a+10/11)/(a-30),0,0,0,0,0,0,0,0,0,(10/11*a-10/11)/(a-30),0],[(-11/12*a+11/12)/(a-30),0,0,0,0,0,0,0,0,0,0,(11/12*a-11/12)/(a-30)]];
  Dmat = matrix_list_to_matrix(Dmat);
  /* output of getparam(); */
  Bfix=[-31,-62,-93,-124,-155,-186,-217,-248,-279,-310,-341];
  Cfix=30;
  Xrule=[[x_1,1/2],[x_2,1/3],[x_3,1/4],[x_4,1/5],[x_5,1/6],[x_6,1/7],[x_7,1/8],[x_8,1/9],[x_9,1/10],[x_10,1/11],[x_11,1/12]];
  Xfix=base_replace(xvars(length(Bfix)),Xrule);
  if (type(getopt(test)) >= 0) {
    B=Bfix; C=Cfix; X=Xfix;
  }
  if (type(X) == 5) X=vtol(X);
  if (C != Cfix) error("C != Cfix");
  if (!taka_base_equal(B,Bfix)) error("B != Bfix");
  if (!taka_base_equal(X,Xfix)) error("X != Xfix");
  if (!number_is_integer(A)) error("A must be an integer.");
  if (A < -1) {
    F=fvect(-1,B,C,X | approx=2);
    for (I=-1; I>A; I--) {
      Down = base_replace(Dmat,[[a,I]]);
      F = Down*F;
    }
    return F[0];
  } else {
    error("A must be less than -1");
  }
}
def try16(A) {
  Bfix=[-31,-62,-93,-124,-155,-186,-217,-248,-279,-310,-341];
  Cfix=30;
  Xrule=[[x_1,1/2],[x_2,1/3],[x_3,1/4],[x_4,1/5],[x_5,1/6],[x_6,1/7],[x_7,1/8],[x_8,1/9],[x_9,1/10],[x_10,1/11],[x_11,1/12]];
  Xfix=base_replace(xvars(length(Bfix)),Xrule);
  Y = newmat(2,12);
  Y[0][0] = 1;
  for (J=0; J<12; J++) Y[1][J] = 1;
  for (J=1; J<12; J++) Y[0][J] = Xfix[J-1];
  Ans=fdah(A,Bfix,Cfix,Y | fdfunc=fd15_11);
  return eval(Ans[0]*Ans[3]*exp(0));
}

/* 2014.05.14 */
def yvars(M1) {
  Y=newmat(2,M1);
  for (I=1; I<=2; I++) {
    for (J=1; J<= M1; J++) {
      Y[I-1][J-1] = util_v(y,[I,J]);
    }
  }
  return matrix_matrix_to_list(Y);
}
/*&usage begin:
fdah_poly(A,B,C,Y)
It returns hypergeometric polynomials for 2 x (M+1) tables
with border sums
-A 
*
   C-A-1, -B[0], -B[1], ...,-B[M-1]
example: T=tk_fd.fdah(-2,[-1,-2],1,yvars(3) | approx=3);tk_fd.fdah_poly(-2,[-1,-2],1,yvars(3))-T[0]*T[3];
end: */
def fdah_poly(A,B,C,Y) {
  M=length(B);
  F=(Y[0][0]*t+Y[1][0])^(C-A-1);
  for (I=0; I<M; I++) {
    F = F*((Y[0][I+1]*t+Y[1][I+1])^(-B[I]));
  }
  /* H = poly_coefficient(F,-A,t); */
  H = coef(F,-A,t);
  /* 2014.05.15 */
  Fac=tk_number_invgamma(C-A);
  for (I=0; I<M; I++) Fac=Fac*tk_number_invgamma(1-B[I]);
  return H*Fac;
}

/*
2014.05.15
 */
/*&usage begin:
  ahvec(A,B,C,Y | norecc=n, approx=n)
  It returns R=[F,Gamma]. F*Gamma is equal to
  (dy_21 Z, dy_22 Z, ..., dy_2p Z) at y = Y where p = length(B)+1.
  y = [[y_11,y_12, ..., y_1p],[y_21,y_22,...,y_2p]].
  y_2* must not be 0. 
  When the option all=1,  R[2]*R[1] is Z (normalizing constant or hg polynomial).
  example:
  A=-3;
  B=[-2,-5];
  C=2;
  Yval=[[1,1/2,1/3],[1,1,1]];
  ahvec(A,B,C,Yval);
  example:
   F=ahvec(-1,[-2],3,[[x11,x12],[x21,x22]] | all=1);
   red(F[2]*F[1]);   
   returns hg polynomial  sum(x^u/u!)  (where Au=Beta).
  end: */
def ahvec(A,B,C,Y) {
  Opt=getopt();
  if (type(getopt(norecc)) >0) UseRecc=0; else UseRecc=1;
  if (type(getopt(all)) > 0) All=1; else All=0;
  M = length(B);
  E = newmat(2,M+1);
  E[0][0] = -A; E[1][0] = C-1;
  for (J=1; J<=M; J++) E[1][J] = -B[J-1];
  X=newvect(M);
  for (I=0; I<M; I++) {
     X[I] = Y[0][I+1]*Y[1][0]/(Y[0][0]*Y[1][I+1]);
  }
  Ye = 1;
  for (J=0; J<=M; J++) Ye = Ye*(Y[0][J]^E[0][J])*(Y[1][J]^E[1][J]);
  if (number_is_integer(A) && A < 0 && UseRecc) F=fvect_poly(A,B,C,X);
  else F=fvect(A,B,C,X | option_list=Opt);
  Fd=newvect(M+1);
  Fd[0] = F[0];  /* Fd are Euer derivatives of F_D */
  for (I=1; I<=M; I++) {
    Xi = X[I-1]; Bi = B[I-1];
    Fd[I] = F[I]*(-Bi/(Xi-1))*Xi;
  }
  Ahvec = newvect(M+1);
  E21=E[1][0]; Y21=Y[1][0];
  Ahvec[0] = (taka_base_sum(Fd,0,1,M)+E21*Fd[0])*Ye/Y21;
  for (J=1; J<=M; J++) {
    Y2j1 = Y[1][J]; E2j1 = E[1][J];
    Ahvec[J] = (-Fd[J]+E2j1*Fd[0])*Ye/Y2j1;
  }
  if (All) { Zvalue=Ye*F[0];}

  NoGamma = getopt(nogamma);
  if (type(NoGamma)<0) NoGamma=0;
   /* Gamma factors, todo double check */
  if (NoGamma) {
     Gamma = "[1/gamma(e+1)]";
  }else if (C > 0) {
    Gamma=tk_number_invgamma(-A+1)*tk_number_invgamma(C-1+1);
    for (I=0; I<M; I++) {
      Gamma=Gamma*tk_number_invgamma(-B[I]+1);
    }
  }else { Gamma=1; } /* because fvect_poly2 is called. */
  R=[vtol(Ahvec),Gamma];
  if (All) return append(R,[Zvalue]);
  else return R;
}
def check17() {
  A=-3;
  B=[-2,-5];
  C=2;
  Yval=[[1,1/2,1/3],[1,1,1]];

  T=fdah(A,B,C,Yval|approx=-A+1);
  printf("Should be 0 -->%a\n",T[0]*T[3]-fdah_poly(A,B,C,Yval));

  Y=yvars(3);
  Yrule = assoc(base_flatten(Y),base_flatten(Yval));
  print(Yrule);
  Fa=fdah_poly(A,B,C,Y);
  Favec=[diff(Fa,y_2_1),diff(Fa,y_2_2),diff(Fa,y_2_3)];
  Favec=base_replace(Favec,Yrule);

  Favec2=ahvec(A,B,C,Yval | norecc=1, approx=-A+1);
  Favec3=vtol(newvect(3,Favec2[0])*Favec2[1]);
  print(Favec);
  print(Favec3);
  return taka_base_equal(Favec,Favec3);
}
def fvect_poly(A,B,C,X) { 
  if (C <= 0) return(fvect_poly2(A,B,C,X));
  EvalDmat=1;
  if (type(X) == 4) X=newvect(length(X),X);
  if (taka_base_equal(B,FD_BB) && 
      taka_base_equal(C,FD_CC) && 
      taka_base_equal(X,FD_XX) && (FD_Dmat != 0)) EvalDmat=0;
  M = length(B);
  Xrule = assoc(xvars(M),vtol(X));
  if (EvalDmat) {
    printf("Computing Dmat for parameters B=%a,C=%a,X=%a\n",B,C,X);
    setparam_abc(M,a,B,C);
    getparam(); 
    FD_Dmat=dmat_abc(a,B,C | xrule=Xrule);
    FD_BB=B; FD_CC=C; FD_XX=X;
    printf("\nDone.\n");
  }
  Dmat = matrix_list_to_matrix(FD_Dmat);
  if (type(X) == 5) X=vtol(X);
  if (!number_is_integer(A)) error("A must be an integer.");
  if (A <= -1) {
    F=fvect(-1,B,C,X | approx=2);
    for (I=-1; I>A; I--) {
      Down = base_replace(Dmat,[[a,I]]);
      F = Down*F;
    }
    return F;
  } else {
    error("A must be less than 0");
  }
}

def check18(M) {
  if (type(getopt(fast))>=1) Fast=getopt(fast); else Fast=0;
  setparam_by_int(M,2 | aa=Fast);
  A=AA;
  B=cdr(vtol(BB));
  C=CC;
  Yval=newmat(2,M+1);
  for (I=0; I<M+1;I++) Yval[0][I]=Yval[1][I]=1;
  for (I=1; I<M+1;I++) Yval[0][I]=1/(I+1);
  Yval = matrix_matrix_to_list(Yval);

  if (!Fast) {
   T=fdah(A,B,C,Yval|approx=-A+1);
   printf("Should be 0 -->%a\n",T[0]*T[3]-fdah_poly(A,B,C,Yval));

  Y=yvars(M+1);
  Yrule = assoc(base_flatten(Y),base_flatten(Yval));
  print(Yrule);
  Fa=fdah_poly(A,B,C,Y);
  Favec=newvect(M+1);
  for (I=1; I<=M+1; I++) Favec[I-1] = diff(Fa,util_v(y,[2,I]));
  Favec=vtol(Favec);
  Favec=base_replace(Favec,Yrule);
  printf("By fdah_poly:%a\n",Favec);
  }
 
  Favec2=ahvec(A,B,C,Yval | approx=-A+1);
  Favec3=vtol(newvect(M+1,Favec2[0])*Favec2[1]);
  printf("By fvect_poly:%a\n",Favec3);
  printf("In big float:%a\n",tk_number_rattofloat(Favec3));
  if (Fast) return Favec3; else return taka_base_equal(Favec,Favec3);
}
def tk_number_rattofloat(L) {
  if (type(L) >= 4) return map(tk_number_rattofloat,L);
  return eval(L*exp(0));
}

/* 2014.05.22 */
/* 
  check7c(10 | a=1,c=1,check=1);
*/
def check7c(N) {
  if (type(getopt(need_grad)) >0) NeedGrad=getopt(need_grad);
  else NeedGrad=0;
  if (type(getopt(check)) >0) Check=getopt(check);
  else Check=0;
  if (type(getopt(a)) >0) A=getopt(a);
  else A=1/2;
  if (type(getopt(c)) >0) C=getopt(c);
  else C=1/7;
  if (type(getopt(b)) >0) B=getopt(b);
  else B=[1/3,1/5,1/11]; 
  printf("[A,B,C]=%a\n",[A,B,C]);
  NN = length(B)+1;
  V1=base_var_list(x,1,NN);
  V2=base_var_list(x,NN+1,2*NN);
  Y = newmat(2,NN,[V1,V2]);
  Dir =newmat(2,NN);
  for (J=1; J<NN; J++) Dir[0][J]=1/(J+1);
  // print(Y); print(Dir); return 0;
  if (type(getopt(eps)) > 0) Eps = getopt(eps);
  else Eps = 1/10;
  if (type(getopt(step)) > 0) Step = getopt(step);
  else Step = Eps/2;
  Rule = [[Y[0][0],1],[Y[1][0],1]];
  for (J=1; J<NN; J++) {
    Rule = cons([Y[0][J],J/20],Rule);
    Rule = cons([Y[1][J],1],Rule);
  }
  Point = base_replace(Y,Rule);
  printf("Point=%a\n",Point);
  FF = fdah(A,B,C,Y | approx=N);
  if (A == C) Fexact=fdah_aeqc(A,B,C,Y); else Fexact=0;
  F = FF[0];
  Amat = FF[1];
  BRule=FF[2];
  Bvec=newvect(NN+1);
  for (I=0; I<NN+1; I++) Bvec[I] = util_v(b,[I+1]);
  Ahg=tk_sm1emu.gkz([Amat,vtol(newvect(NN+1))]);
  // print(Ahg[0]);
  V = Ahg[1];
  if  (Check) {
    for (I=0; I<length(Ahg[0]); I++) {
      if (I<NN+1) Op=base_replace(Ahg[0][I]-Bvec[I],BRule);
      else Op=base_replace(Ahg[0][I],BRule);
      RR=eval(base_replace(odiff_act(Op,F,V),Rule));
      printf("Ahg[0][%a] F = %a\n",I,RR);
    }
    if (Fexact != 0) {
      printf("F-Fexact=%a\n",eval(base_replace(F,Rule))-eval(base_replace(Fexact,Rule))); 
    }
  }
  Base=cbase(Amat);
  printf("Base=%a\n",Base);
  Iv=map(odiff_act,Base,F,V);
  Iv=map(eval,base_replace(Iv,Rule));

  Val=[[base_flatten(Point),Iv]];

  for (T=1; T<=Eps/Step; T++) {
    printf("T=%a <= %a\n",T,Eps/Step);
    Point2 = newmat(2,NN);
    for (I=0; I<2; I++)  for (J=0; J<NN; J++)  Point2[I][J] = Point[I][J] + T*Step*Dir[I][J];
    Rule2=[];
    for (I=0; I<2; I++)  for (J=0; J<NN; J++)  Rule2=cons([Y[I][J],Point2[I][J]],Rule2);
    Iv2=map(odiff_act,Base,F,V);
    Iv2=map(eval,base_replace(Iv2,Rule2));
    Val=cons([base_flatten(Point2),Iv2],Val);
  }

  if (NeedGrad) {
   Grads=base_var_list(dx,1,2*NN);
   Grad=map(odiff_act,Grads,F,V);
   Grad=map(eval,base_replace(Grad,Rule));
  }

  return [Amat,V,BRule,[base_flatten(Dir),Eps],reverse(Val),Grad,Base,Fexact];
}

/*
  Exact values.
  check7c_out(|a=1,c=1,b=[1],approx=15);
  check7c_out(|a=1,c=1,b=[1,2],approx=15);
  check7c(15|a=1,c=1,b=[1,2],check=1);
*/
def check7c_out() {
  setprec(30);
  if (type(getopt(a)) >0) A=getopt(a);
  else A=1/2;
  if (type(getopt(c)) >0) C=getopt(c);
  else C=1/7;
  if (type(getopt(b)) >0) B=getopt(b);
  else B=0;
  if (type(getopt(step))>0) Step=getopt(step);
  else Step=1/10^12; 
  if (type(getopt(eps))>0) Eps=getopt(eps);
  else Eps=Step*10;
  if (type(getopt(approx))>0) Approx=getopt(approx);
  else Approx=15;
  R1=check7c(Approx |step=Step,eps=Eps,a=A,c=C,b=B,check=1);
  R2=check7c(Approx+2 |step=Step,eps=Eps,a=A,c=C,b=B,check=1);
  R11=base_flatten(R1[4]);
  R22=base_flatten(R2[4]);
  Err=newvect(length(R11),R11)-newvect(length(R22),R22);
  printf("/* map(mytruncate,Err)=%a */\n",map(mytruncate,Err));
  printf("Fexact=%a;\n",R2[7]);
  MyFile="/Users/nobuki/t.txt";
  printf("Output will in %a\n",MyFile);
  output(MyFile);
  if (R2[7] != 0) printf("Fexact=%a;\n",R2[7]);
  printf("A=%a;B=%a;C=%a;\n",A,B,C);
  printf("/* map(mytruncate,Err)=%a */\n\n",map(mytruncate,Err));
  printf("Step=%a; /* log10(step)=%a,approx deg=%a */\n",Step,eval(log(Step)/log(10)),Approx);
  printf("A=%a;\n",R2[0]);
  printf("V=%a;\n",R2[1]);
  printf("Brule=%a;\n",R2[2]);
  printf("Dir=%a;\n",R2[3][0]);
  printf("Base=%a;\n\n",R2[6]);
  R2=R2[4];
  printf("/* Val=[[point,value],[point,value],....]; */\n");
  printf("Val=[\n");
  for (I=0; I<length(R2); I++) {
    printf("%a",R2[I]);
    if (I < length(R2)-1) printf(",\n");
    else printf("\n];\n/**/\n");
  }
  output();
}
/* 2014.05.23 */ 
/* Degenerate case A=C */
def fdah_aeqc(A,B,C,Y) {
   if  (A!=C)  error("fdah_aeqc: A!=C");
   N=length(B); 
   X=newvect(N);
   for (I=0; I<N; I++) {
     X[I] = Y[0][I+1]*Y[1][0]/(Y[0][0]*Y[1][I+1]);
   }
   U = (Y[0][0]^(-A))*(Y[1][0]^(C-1));
   for (I=0; I<N; I++) {
     U = U*(Y[1][I+1])^(-B[I]);
   }

   FD=1;
   for (I=0; I<N; I++) {
      FD=FD*(1-X[I])^(-B[I]);
   }
   Val = red(U*FD);
   return Val;
}
def feval(F) { 
  if (type(F) >= 4) return map(feval,F);
  return eval(F*exp(0)); 
}
/* quadratic eq */
def check19() {
  Check=1;
  if (type(getopt(step))>0) Step=getopt(step);
  else Step=1/10^12; 
  if (type(getopt(eps))>0) Eps=getopt(eps);
  else Eps=Step*10;
  Bvec = [b_1,b_2];
  BRule=assoc(Bvec,[0,-1]);
  Amat=[[1,1,1],[0,1,2]];
  Ahg=tk_sm1emu.gkz([Amat,vtol(newvect(2))]);
  V = Ahg[1];
  Point=newvect(3,[2,-3,1]);  /* Solution is 2,1*/
  Dir=newvect(3,[1,1,0]);
  Rule=assoc(V,vtol(Point));  
  F = (-x2+(x2^2-4*x1*x3)^(1/2))/(2*x3); 

  if  (Check) {
    for (I=0; I<length(Ahg[0]); I++) {
      if (I<length(Bvec)) Op=base_replace(Ahg[0][I]-Bvec[I],BRule);
      else Op=base_replace(Ahg[0][I],BRule);
      RR=feval(base_replace(odiff_act(Op,F,V),Rule));
      printf("Ahg[0][%a] F = %a\n",I,RR);
    }
  }
  Base=cbase(Amat);
  printf("Base=%a\n",Base);
  Iv=map(odiff_act,Base,F,V);
  Iv=map(feval,base_replace(Iv,Rule));

  Val=[[feval(base_flatten(Point)),Iv]];

  for (T=1; T<=Eps/Step; T++) {
    printf("T=%a <= %a\n",T,Eps/Step);
    Point2 = newvect(3);
    Point2 = Point+T*Step*Dir;
    Rule2=assoc(V,vtol(Point2));
    Iv2=map(odiff_act,Base,F,V);
    Iv2=map(feval,base_replace(Iv2,Rule2));
    Val=cons([feval(base_flatten(Point2)),Iv2],Val);
  }
  return [Amat,V,BRule,[Dir,Eps],reverse(Val),0,Base,F];
}

def check19_out() {
  setprec(30);
  if (type(getopt(step))>0) Step=getopt(step);
  else Step=1/10^12; 
  if (type(getopt(eps))>0) Eps=getopt(eps);
  else Eps=Step*10;
  R2=check19(|step=Step,eps=Eps);
  R22=base_flatten(R2[4]);
  printf("Fexact=%a;\n",R2[7]);
  MyFile="/Users/nobuki/t.txt";
  printf("Output will in %a\n",MyFile);
  output(MyFile);
  if (R2[7] != 0) printf("Fexact=%a;\n",R2[7]);
  printf("Step=%a; /* log10(step)=%a,approx deg=%a */\n",Step,eval(log(Step)/log(10)),Approx);
  printf("A=%a;\n",R2[0]);
  printf("V=%a;\n",R2[1]);
  printf("Brule=%a;\n",R2[2]);
  printf("Dir=%a;\n",R2[3][0]);
  printf("Base=%a;\n\n",R2[6]);
  R2=R2[4];
  printf("/* Val=[[point,value],[point,value],....]; */\n");
  printf("Val=[\n");
  for (I=0; I<length(R2); I++) {
    printf("%a",R2[I]);
    if (I < length(R2)-1) printf(",\n");
    else printf("\n];\n/**/\n");
  }
  output();
}
/*
  check7c_out(|a=1,c=1,approx=15);
  for ndata5.txt
*/

/*
  ah_init_value(1,[1],1,[[1,1/3],[1,1]] | approx=25);
  R1=check7c(20); R2=ah_init_value(1/2,[1/3,1/5,1/11],1/7,[[1,1/20,2/20,3/20],[1,1,1,1]] | approx=20); 
  Err=matrix_list_to_matrix(base_flatten(R1[4][0]))
       -matrix_list_to_matrix(base_flatten(R2[4][0]));
  cf. check7();
*/
/*&usage begin:
  ah_init_value(A,B,C,Y|approx=n)
  A,B,C are parameters for F_D.
  Let R be the return value of this function.
  R[0]  is the matrix A which defines the corresponding A-hypergeometric system associated to F_D.
  R[1] is the list of  indnependent variables.
  R[2]  is  the values of b_1, b_2, ....   of A-hypergeometric system.
  R[3]  is 0 (dummy for the compatibility).
  R[4] is  [[initial Point Y,  values at Y]].
  R[5]   is 0 (dummy for the compatibility).
  R[6]   is a base of the Pfaffian obtained by cbase(). Values at Y (R[4]) are calculated with respect to this base.
  R[7] is an exact solution if it exists.
  When the error is more than 10^(-10), it returns 0 with the error message.
  example:
    ah_init_value(1,[1],1,[[1,1/3],[1,1]] | approx=25);
    ah_init_value(1,[1],1,[1,1/3,1,1] | approx=25);
    ah_init_value(1/2,[1/3,1/5,1/11],1/7,[[1,1/20,2/20,3/20],[1,1,1,1]] | approx=20); 
*/
def  ah_init_value(A,B,C,Y)  {
  if (type(getopt(approx)) >=0) Approx=getopt(approx);
  else Approx=10;
  Check=0;
  N = length(B)+1;
  if (length(Y) != 2) {
    Ymat=newmat(2,N);
    for (I=0; I<N; I++) {Ymat[0][I]=Y[I]; Ymat[1][I]=Y[N+I];}
    Y=matrix_matrix_to_list(Ymat);
  }
  V1=base_var_list(dx,1,N);
  V2=base_var_list(dx,N+1,2*N);
  YV=newmat(2,N,[V1,V2]);
  Point = matrix_list_to_matrix(Y);
  FF = fdah(A,B,C,Y | approx=Approx);
  if (A == C) Fexact=fdah_aeqc(A,B,C,Y); else Fexact=0;
  F = FF[0];
  Amat = FF[1];
  BRule=FF[2];
  Bvec=newvect(N+1);
  for (I=0; I<N+1; I++) Bvec[I] = util_v(b,[I+1]);
  Ahg=tk_sm1emu.gkz([Amat,vtol(newvect(N+1))]);
  // print(Ahg[0]);
  V = Ahg[1];
  if (Fexact != 0) {
      printf("F-Fexact=%a\n",feval(F)-feval(Fexact));
  }
  Base=cbase(Amat);
  printf("Base=%a\n",Base);
 
  Iv0=ahvec(A,B,C,Y|approx=Approx)[0];
  Iv1=ahvec(A,B,C,Y|approx=Approx+1)[0];
  Err0=newvect(length(Iv0),feval(Iv0))-newvect(length(Iv1),feval(Iv1));
  Err=map(mytruncate,Err0);
  printf("Err0=%a, Err=%a\n",Err0,Err);
  if (!taka_base_is_zero(Err)) {
    printf("Err0=%a,Err=%a, Approx=%a\nError: Make approx larger.\n",Err0,Err,Approx);  
    return 0;
  }
  Iv=newvect(length(Base),Base);
  for (I=0; I<length(Iv); I++) {
    if (Iv[I] == 1) Iv[I] = F;
    else {
      for (J=0; J<length(YV[1]); J++) {
         if (Iv[I] == YV[1][J]) { Iv[I]=Iv0[J];  break; }
      }
      if (J == length(YV[1])) error("failed.");
   }
  }
  Val=[ [feval(base_flatten(Point)),feval(base_flatten(Iv))]];
  return [Amat,V,BRule,0,Val,0,Base,Fexact];
}

/* 2014.06.23.  Ref: @s/2014/06/24-intersection-sabun.pdf by Y.Goto , 25-my-note-fdpf-yg-funcs.pdf 
   2014/07/14-fdpf-memo-ygfuncs.pdf   mynote in goto's note with yg-function names.
*/
def ygNmat() {
  N=newmat(MM+1,MM+1);
  for (I=0; I<MM+1; I++) for (J=0; J<MM+1; J++) N[I][J] = 1;
  return N;
}

def ygCmat() {
  L=newvect(MM+1);
  L[0] = 1/Alpha[MM+2];
  for (I=1; I<=MM; I++) L[I] = 1/Alpha[I];
  return (ygNmat()/Alpha[MM+1]) + matrix_diagonal_matrix(L);
}

def ygRmat(X,K) {
  X2=newvect(MM+2);
  X2[0]=0;
  for (I=1; I<=MM; I++) X2[I] = X[I-1];
  X2[MM+1]=1;  /* cf. def xx(I) */
  X=X2;

  Lx = newvect(MM+1);
  for (I=1; I<=MM; I++) Lx[I] = 1-X[I];
  Lx = matrix_diagonal_matrix(Lx);
  L1 = newvect(MM+1); L1[0]=1;
  L1 = matrix_diagonal_matrix(L1);
  N = ygNmat(); 
  R=N*(1-X[K])/Alpha[MM+1] + Lx*N*L1/Alpha[MM+2] - L1*N*Lx/(1-Alpha[MM+2]);

  L = newvect(MM+1);
  AX=0; for (I=0; I<=MM+1; I++) AX += Alpha[I]*X[I];
  L[0] = (1-X[K])/Alpha[MM+2] - (1/(1-Alpha[MM+2]))*(AX/Alpha[MM+2] + 1);
  for (I=1; I<=MM; I++) {
    L[I] = (X[I]-X[K])/Alpha[I];
  }
  return (R + matrix_diagonal_matrix(L));
}

def ygdmat_abc(A,B,C) {
  Xrule=getopt(xrule);
  M=length(B);
  X = xvars(M);
  if (type(Xrule)>0)  X=base_replace(X,Xrule);
  setparam_abc(M,A,B,C);
  R=ygRmat(X,M+1);
  R=((A-1)/(C-A))*R*matrix_inverse(ygCmat());
  return map(red,R);
}

def ygfvect_poly(A,B,C,X) { 
  if (C <=0 ) return(fvect_poly2(A,B,C,X));
  YgEvalDmat=1;
  if (type(X) == 4) X=newvect(length(X),X);
  if (taka_base_equal(B,YgFD_BB) && 
      taka_base_equal(C,YgFD_CC) && 
      taka_base_equal(X,YgFD_XX) && (YgFD_Dmat != 0)) YgEvalDmat=0;
  M = length(B);
  Xrule = assoc(xvars(M),vtol(X));
  if (YgEvalDmat) {
    printf("Computing ygDmat for parameters B=%a,C=%a,X=%a\n",B,C,X);
    setparam_abc(M,a,B,C);
    getparam(); 
    YgFD_Dmat=ygdmat_abc(a,B,C | xrule=Xrule);
    YgFD_BB=B; YgFD_CC=C; YgFD_XX=X;
    printf("\nDone.\n");
  }
  Dmat = matrix_list_to_matrix(YgFD_Dmat);
  if (type(X) == 5) X=vtol(X);
  if (!number_is_integer(A)) error("A must be an integer.");
  if (A <= -1) {
    F=fvect(-1,B,C,X | approx=2);
    for (I=-1; I>A; I--) {
      Down = base_replace(Dmat,[[a,I]]);
      F = Down*F;
    }
    return F;
  } else {
    error("A must be less than 0");
  }
}

def ygahvec(A,B,C,Y) {
  Opt=getopt();
  if (type(getopt(norecc)) >0) UseRecc=0; else UseRecc=1;
  if (type(getopt(all)) > 0) All=1; else All=0;
  M = length(B);
  E = newmat(2,M+1);
  E[0][0] = -A; E[1][0] = C-1;
  for (J=1; J<=M; J++) E[1][J] = -B[J-1];
  X=newvect(M);
  for (I=0; I<M; I++) {
     X[I] = Y[0][I+1]*Y[1][0]/(Y[0][0]*Y[1][I+1]);
  }
  Ye = 1;
  for (J=0; J<=M; J++) Ye = Ye*(Y[0][J]^E[0][J])*(Y[1][J]^E[1][J]);
  if (number_is_integer(A) && A < 0 && UseRecc) F=ygfvect_poly(A,B,C,X);
  else F=fvect(A,B,C,X | option_list=Opt);  
  Fd=newvect(M+1);
  Fd[0] = F[0];  /* Fd are Euer derivatives of F_D */
  for (I=1; I<=M; I++) {
    Xi = X[I-1]; Bi = B[I-1];
    Fd[I] = F[I]*(-Bi/(Xi-1))*Xi;
  }
  Ahvec = newvect(M+1);
  E21=E[1][0]; Y21=Y[1][0];
  Ahvec[0] = (taka_base_sum(Fd,0,1,M)+E21*Fd[0])*Ye/Y21;
  for (J=1; J<=M; J++) {
    Y2j1 = Y[1][J]; E2j1 = E[1][J];
    Ahvec[J] = (-Fd[J]+E2j1*Fd[0])*Ye/Y2j1;
  }
  if (All) { Zvalue=Ye*F[0];}

  NoGamma = getopt(nogamma);
  if (type(NoGamma)<0) NoGamma=0;
   /* Gamma factors, todo double check */
  if (NoGamma) {
     Gamma = "[1/gamma(e+1)]";
  }else if (C>0) {
    Gamma=tk_number_invgamma(-A+1)*tk_number_invgamma(C-1+1);
    for (I=0; I<M; I++) {
      Gamma=Gamma*tk_number_invgamma(-B[I]+1);
    }
  }else { Gamma=1; } /* ygfvect_poly2 is called. */
  R= [vtol(Ahvec),Gamma];
  if (All) return append(R,[Zvalue]);
  else return R;
}


def ygtry15(M) {
  A=a;
  B=newvect(M);
  for (I=0; I<M; I++) B[I] = -31*(I+1);
  C=30;
  Xrule=[];
  for (I=1; I<=M; I++) Xrule=cons([util_v(x,[I]),1/(I+1)],Xrule);
  Xrule=reverse(Xrule);
  setparam_abc(M,A,B,C);
  getparam();  printf("Xrule=%a\n",Xrule);
  Dmat=ygdmat_abc(A,B,C | xrule=Xrule);

  /* check */
  Aval = -3;
  Fam = fvect(Aval-1,B,C,base_replace(xvars(M),Xrule) | approx=-Aval+1);
  Fa = fvect(Aval,B,C,base_replace(xvars(M),Xrule) | approx=-Aval+1);
  T=Fam - base_replace(Dmat,[[a,Aval]])*Fa;
  printf("If %a is not zero vector , then there is an error.\n",T);
  return Dmat;
}


/* cf. fdah()  */
def marginal2abc(RSum,CSum) {
  if (length(RSum) != 2) error("length of RSum must be 2.");
  Size = length(CSum);
  CSum=newvect(Size,CSum);
  S = RSum[0]+RSum[1];
  if (S != base_sum(CSum,0,0,Size-1)) {
    T=S-base_sum(CSum,0,0,Size-2);
    printf("Warning. RSum != CSum. The last value of CSum is changed from %a to %a.\n",CSum[Size-1],T);
    CSum[Size-1] = T;
    if (T < 0) error("Changed value is negative.");
  }
  CSum = vtol(CSum);
  B=vtol(-newvect(Size-1,cdr(CSum)));
  C=RSum[1] + 1 + base_sum(B,0,0,Size-2);
  A=-RSum[0];
  if ((C < 0) && MyDebug) printf("Advise: C=%a is negative. Exchange columns so that a big value comes to the first and Exchange rows so that a big value come to the second. \n",C);
  return [A,B,C];

}
def abc2marginal(A,B,C) {
  R2=C-1-base_sum(B,0,0,length(B)-1);
  R1=-A;
  RSum=[R1,R2];
  C1=-A+C-1;
  CSum = -newvect(length(B),B);
  CSum = cons(-A+C-1,vtol(CSum));
  return [RSum,CSum];
}
// check20 in A-hg/Prog/hgpoly.rr

def ygQmat(X,K) {
  return ygRmat(X,K); /* Implement without global variables. */
}

/* 2014.08.03 from hgpoly.rr, should use hgpoly.rr with deg=... 
   2 x (M+1)
*/
def fdA(M) {
  A = newmat(M+1+1,2*(M+1));
  for (I=0; I<M+1;I++) A[0][I] =1;
  for (I=0; I<M+1; I++) {
    A[I+1][I] = 1;
    A[I+1][M+1+I] = 1;
  }
  return A;    
}
def hgpoly_fd(A,B,C) {
  Marginal = abc2marginal(A,B,C);
  if (containNegative(Marginal)) error("Negative marginal");
  M = length(B);
  Beta =cons(Marginal[0][0],Marginal[1]);
  return hgpoly_fd_beta(M,Beta);
}
def hgpoly_fd0(A,B,C) {
  Marginal = abc2marginal(A,B,C);
  if (containNegative(Marginal)) error("Negative marginal");
  M = length(B);
  Beta =cons(Marginal[0][0],Marginal[1]);
  return hgpoly_fd_beta0(M,Beta);
}
/*
  Table. B[0] is the first row sum.
  B[0] |
  CB   |
         B[1], B[2], ..., B[M+1]
 */
def hgpoly_fd_beta(M,B) {
  CB = (base_sum(B,0,0,length(B)-1)-B[0])-B[0];
  if (CB == 1) return hgpoly_fd_beta1(M,B);
  else return hgpoly_fd_beta0(M,B);
}
/* _beta0  is the bruce force method. cf _beta1 */
def hgpoly_fd_beta0(M,B) {
  /* printf("hgpoly_fd_beta0(bruce force), M=%a, Beta=%a\n",M,B); */
  A = fdA(M);
  Deg  = base_sum(B,0,0,length(B)-1)-B[0];
  if (type(getopt(deg)) >=0) Deg=eval_str(rtostr(getopt(deg))); 
  if (type(A) == 4) A=matrix_list_to_matrix(A);
  D=size(A)[0];
  N=size(A)[1];
  Ap = matrix_transpose(A);
  F=0;
  Vx=[];
  for (I=0; I<N; I++) {
    Mon = 1;
    for (J=0; J<D; J++) {
       Mon = Mon*util_v(t,[J+1])^(Ap[I][J]);
       if (Ap[I][J] < 0) error("A contains negative number.");
    }
    /* deg_1(Mon) >=1 */
    F = F+util_v(x,[I+1])*Mon;
    Vx = cons(util_v(x,[I+1]),Vx);
  }
  Vx=reverse(Vx);
  /* print(print_input_form(poly_sort(F))); */
  Fall = 1;
  for (I=1; I<=Deg; I++) {
    Fall += F^I;  /* deg_1(each term of F^p) >= p */
  }
  // printf("Fall=%a\n",Fall);
  P = coef(Fall,B[0],util_v(t,[1]));
  for (I=1; I<length(B); I++) {
    P = coef(P,B[I],util_v(t,[I+1]));
  }
  Pdist=dp_ptod(P,Vx);
  if ( P ==0 )  return 0;
  Pnew=0;
  while (Pdist != 0) {
    U = dp_ht(Pdist); U=dp_etov(U);
    Degree=base_sum(U,0,0,length(U)-1);
    Degree=fac(Degree);
    Pnew += dp_hm(Pdist)/Degree;
    Pdist = dp_rest(Pdist);
  }
  return [dp_dtop(Pnew,Vx),Pnew,Vx];
}
/* from Ogawa data. */
def check21() {
  B=[2,1,1,1,1]; print(B);
  F=hgpoly_fd_beta(3,B); print(F);
  B=[10,8,6,8]; print(B);  
  F=hgpoly_fd_beta(2,B);  print(F);
  B=[4,3,1,3,1,1]; print(B);
  F=hgpoly_fd_beta(4,B);  print(F);
  B=[5,4,2,3,2,1]; print(B);
  F=hgpoly_fd_beta(4,B);  print(F);
  B=[6,5,4,1,1,1]; print(B);  
  F=hgpoly_fd_beta(4,B);  print(F); /* takes a few seconds */
}

/*
   Beta=[3,6,3,4];
   F=hgpoly_fd_beta(2,Beta);
   checkahg(F[0],Beta,F[2]);
 */
def checkahg(F,Beta,V) {
  N=(length(Beta)-1)*2;  M=length(Beta)-2;
  if (N != length(V)) error("N != length(V)");
  DV = newvect(N) ;
  for (I=0; I<N; I++) DV[I] = eval_str("d"+rtostr(V[I]));
  EV = newvect(N);
  for (I=0; I<N; I++) EV[I] = V[I]*DV[I];
  A = fdA(M);
  E = A*EV;
  for (I=0; I<length(Beta);I++) {
    if (red(tkdiff_act(E[I]-Beta[I],F,V)) != 0) {print("No"); return(0); }
  }
  for (I=0; I<M+1; I++) {
    for (J=I+1; J<M+1; J++) {
      T=DV[I]*DV[M+1+J]-DV[J]*DV[M+1+I];
      if (red(tkdiff_act(T,F,V)) != 0) {print("No"); return(0); }
    }
  }    
  return(1);
}

/* B[0] is not a dummy. cf. in the setparam(), B[0] is a dummy. */
def abc2alpha(A,B,C) {
  M=length(B);
  Alph = newvect(M+3);
  Alph[0]=-C+base_sum(B,0,0,M-1);
  for (I=1; I<=M; I++) Alph[I] = -B[I-1];
  Alph[M+1] = C-A;
  Alph[M+2] = A;
  return(vtol(Alph)); 
}

def ygNmat2(M) {
  N=newmat(M+1,M+1);
  for (I=0; I<M+1; I++) for (J=0; J<M+1; J++) N[I][J] = 1;
  return N;
}

def ygCmat2(A,B,C) {
  M = length(B);
  Alp = abc2alpha(A,B,C);
  L=newvect(M+1);
  L[0] = 1/Alp[M+2];
  for (I=1; I<=M; I++) L[I] = 1/Alp[I];
  return (ygNmat2(M)/Alp[M+1]) + matrix_diagonal_matrix(L);
}

def ygRmat2(A,B,C,X,K) {
  M = length(B);
  Alp = abc2alpha(A,B,C);
  X2=newvect(M+2);
  X2[0]=0;
  for (I=1; I<=M; I++) X2[I] = X[I-1];
  X2[M+1]=1;  /* cf. def xx(I) */
  X=X2;

  Lx = newvect(M+1);
  for (I=1; I<=M; I++) Lx[I] = 1-X[I];
  Lx = matrix_diagonal_matrix(Lx);
  L1 = newvect(M+1); L1[0]=1;
  L1 = matrix_diagonal_matrix(L1);
  N = ygNmat2(M); 
  R=N*(1-X[K])/Alp[M+1] + Lx*N*L1/Alp[M+2] - L1*N*Lx/(1-Alp[M+2]);

  L = newvect(M+1);
  AX=0; for (I=0; I<=M+1; I++) AX += Alp[I]*X[I];
  L[0] = (1-X[K])/Alp[M+2] - (1/(1-Alp[M+2]))*(AX/Alp[M+2] + 1);
  for (I=1; I<=M; I++) {
    L[I] = (X[I]-X[K])/Alp[I];
  }
  return (R + matrix_diagonal_matrix(L));
}

def ygQmat2(A,B,C,X,K) {
  return ygRmat2(A,B,C,X,K);
}

def beta2marginal(Beta) {
  R=cdr(Beta);
  C=[Beta[0],base_sum(R,0,0,length(R)-1)-Beta[0]];
  return([C,R]);
}
def beta2abc(Beta) {
  Marginal=beta2marginal(Beta);
  return(marginal2abc(Marginal[0],Marginal[1]));
}

/* From A-hg series  to FD. */
def atofd(F,A,B,C,Z) {
  M = length(B);
  E = newmat(2,M+1);
  Y = newmat(2,M+1);
  Y[0][0] = util_v(y,[0,0]);
  for (J=0; J<=M; J++) Y[1][J] = util_v(y,[1,J]);
  E[0][0] = -A; E[1][0] = C-1;
  for (J=1; J<=M; J++) E[1][J] = -B[J-1];
  X=newvect(M);
  for (I=0; I<M; I++) {
    X[I] =util_v(x,[I+1]);
  }
  for (I=0; I<M; I++) {
    /*     X[I] = Y[0][I+1]*Y[1][0]/(Y[0][0]*Y[1][I+1]); */
    Y[0][I+1] = X[I]/(Y[1][0]/(Y[0][0]*Y[1][I+1]));
  }
  Y2 = newvect(2*(M+1));
  for (J=0; J<=M; J++) {Y2[J] = Y[0][J]; Y2[M+1+J]=Y[1][J];}
  Ye = 1;
  for (J=0; J<=M; J++) Ye = Ye*(Y[0][J]^E[0][J])*(Y[1][J]^E[1][J]);
  Rule = assoc(Z,vtol(Y2));
  if (MyDebug) printf("F=%a,\nYe=%a,\nRule=%a\n",F,Ye,Rule);
  Fd = red(base_replace(F/Ye,Rule));
  return([Fd,vtol(X)]);
}
/*
Beta=[2,1,1,1,1];
FdA=hgpoly_fd_beta(3,Beta);   
atofd_beta(FdA[0],Beta,FdA[2]);  
  Beta is the marginal sum.
  FdA[0] is the polynomial.
  FdA[1] is dp_ptod(FdA[0]);
  FdA[2] is the list of variables.
*/
def  atofd_beta(F,Beta,Z) {
  Marginal = beta2marginal(Beta);
  CSum=Marginal[1];
  RSum=Marginal[0];
  ABC=marginal2abc(RSum,CSum);
  return(atofd(F,ABC[0],ABC[1],ABC[2],Z));
}
/*
check22(-2,[-1,-2,-1],3);
 */
def check22(A,B,C) {
  M = length(B);
  Beta=newvect(M+2);
  Beta[0]=-A; 
  Beta[1]=C-1-A;
  for (I=0; I<M; I++) Beta[2+I]=-B[I];
  /* Beta=[-A,C-1-A,-B[0],-B[1],-B[2]]; */
  F=hgpoly_fd_beta(M,Beta); print(F);
  G=atofd(F[0],A,B,C,F[2]);
  R=checkfd(G[0],A,B,C,G[1]); printf("R=[0,...,0]? ===> R=%a\n",R);
  return(G);
}

/* 2014.08.05. Does F satisfy the system of equations for F_D? */
def checkfd(F,A,B,C,V) {
  M = length(B);
  DV = [];
  for (I=0; I<M; I++) DV=cons(eval_str("d"+rtostr(V[I])),DV);
  DV = reverse(DV);
  T=0; for (I=0; I<M; I++) T = T+V[I]*DV[I];
  Ans=[];
  for (I=0; I<M; I++) {
    G=odiff_act(V[I]*DV[I],odiff_act(T+C-1,F,V),V)
      -V[I]*odiff_act(T+A,odiff_act(V[I]*DV[I]+B[I],F,V),V);
    Ans = cons(G,Ans);
  }
  return(reverse(Ans));
}

/* F(b-e_k) = Dk F(b) 
   e_1, e_2, ..., but b_1=B[0]
 */
def ygDk(A,B,C,X,K) {
  Qk = ygQmat2(A+1,B,C+1,X,K); 
  Q0 = ygQmat2(A+1,B,C+1,X,0);
  return map(red,Qk*matrix_inverse(Q0));
}
def ygDk2(A,B,C,X,K) {
  return (1/(-B[K-1]+1))*ygDk(A,B,C,X,K);
}

def containNegative(L) {
  if (type(L) <= 1)  return(L<0);
  if (type(L) >=4) {
    for (I=0; I<length(L); I++) {
      if (containNegative(L[I])) return(1);
    }
    return(0);
  }
  error("Not an ordered object.");
}
/* 2014.08.09,  K=1,2,... */
def check23(K) {
   A=-3; C=-1; B=[-3,-2,-3];  
   /* A=-5; C=-6; B=[-1,-2,-3];   negative marginal */
   /* A=-5; C=-2; B=[-1,-2,-3];   */
  /* A=-5; C=2; B=[-1,-2,-3];   */
  /* A=-2; C=2; B=[-4]; */
   if (containNegative(abc2marginal(A,B,C))) error("Negative marginal");
  M = length(B);
  Alp = abc2alpha(A,B,C); 
  F=hgpoly_fd(A,B,C);  
  F=atofd(F[0],A,B,C,F[2]);
  V=F[1]; F=F[0];
  Fvec=newvect(M+1); 
  Fvec[0] = F;
  for (I=1; I<=M; I++)  Fvec[I] =  ((V[I-1]-1)/Alp[I])*diff(F,V[I-1]);
  B2 = newvect(M,B);
  B2[K-1] = B[K-1]-1; 
  B2 = vtol(B2);
  Alp2=abc2alpha(A,B2,C);
  F2=hgpoly_fd(A,B2,C);
  F2=atofd(F2[0],A,B2,C,F2[2])[0];
  printf("V=%a, B=%a, B2=%a\n",V,B,B2);
  printf("F=%a\n",F); 
  printf("F2=%a\n",F2);
  /* Todo, how to modify the constant term? --> (-B[0]) in case of C>0*/
  Fvec2=newvect(M+1); 
  Fvec2[0] = F2;
  for (I=1; I<=M; I++)  Fvec2[I] =  ((V[I-1]-1)/Alp2[I])*diff(F2,V[I-1]);
  /*  R=map(red,Fvec2-(1/(-B[K-1]+1))*ygDk(A,B,C,V,K)*Fvec); */
  R=map(red,Fvec2-ygDk2(A,B,C,V,K)*Fvec); 
  return R;
}

/* 2014.08.10 */
/* F(c-1) = Dc F(c) 
 */
def ygDc2(A,B,C,X) {
  M=length(B);
  Q0 = ygQmat2(A+1,B,C,X,0);
  Qm1 = ygQmat2(A+1,B,C,X,M+1); 
  return map(red,(C-A-1)*Q0*matrix_inverse(Qm1));
}
def ygDc(A,B,C,X) {
  return ((1/(C-1))*ygDc2(A,B,C,X));
}
def check24() {
   A=-3; C=-1; B=[-3,-2,-3];   
   /* A=-5; C=-6; B=[-1,-2,-3];   negative marginal */
   /* A=-5; C=-2; B=[-1,-2,-3];  */
   /* A=-5; C=2; B=[-1,-2,-3];   */
  /* A=-5; C=2; B=[-4];  */
   if (containNegative(abc2marginal(A,B,C))) error("Negative marginal");
  M = length(B);
  Alp = abc2alpha(A,B,C); 
  F=hgpoly_fd(A,B,C);  
  F=atofd(F[0],A,B,C,F[2]);
  V=F[1]; F=F[0];
  Fvec=newvect(M+1); 
  Fvec[0] = F;
  for (I=1; I<=M; I++)  Fvec[I] =  ((V[I-1]-1)/Alp[I])*diff(F,V[I-1]);
  C2 = C-1;
  Alp2=abc2alpha(A,B,C2);
  F2=hgpoly_fd(A,B,C2);
  F2=atofd(F2[0],A,B,C2,F2[2])[0];
  printf("V=%a, C=%a, C2=%a\n",V,C,C2);
  printf("F=%a\n",F); 
  printf("F2=%a\n",F2);
  /* Todo, how to modify the constant term? --> (-B[0]) in case of C>0*/
  Fvec2=newvect(M+1); 
  Fvec2[0] = F2;
  for (I=1; I<=M; I++)  Fvec2[I] =  ((V[I-1]-1)/Alp2[I])*diff(F2,V[I-1]);
  R=map(red,Fvec2-ygDc2(A,B,C,V)*Fvec);
  return R;
}

/* F(a-1) = Da F(a) 
 */
def ygDa2(A,B,C,X) {
  M=length(B);
  Cmat = ygCmat2(A,B,C);
  Qm1 = ygQmat2(A,B,C,X,M+1); 
  return map(red,-(1/(C-A))*Qm1*matrix_inverse(Cmat));
}
def ygDa(A,B,C,X) {
  Factor=-(A-1); /* Todo */
  return (Factor*ygDa2(A,B,C,X));
}
def check25() {
   A=-3; C=-1; B=[-3,-2,-3];   
   /* A=-5; C=-6; B=[-1,-2,-3];   negative marginal */
  /* A=-5; C=-2; B=[-1,-2,-3]; */
   /* A=-5; C=2; B=[-1,-2,-3]; */
   /* A=-5; C=2; B=[-4];   */
   if (containNegative(abc2marginal(A,B,C))) error("Negative marginal");
  M = length(B);
  Alp = abc2alpha(A,B,C); 
  F=hgpoly_fd(A,B,C);  
  F=atofd(F[0],A,B,C,F[2]);
  V=F[1]; F=F[0];
  Fvec=newvect(M+1); 
  Fvec[0] = F;
  for (I=1; I<=M; I++)  Fvec[I] =  ((V[I-1]-1)/Alp[I])*diff(F,V[I-1]);
  A2 = A-1;
  Alp2=abc2alpha(A2,B,C);
  F2=hgpoly_fd(A2,B,C);
  F2=atofd(F2[0],A2,B,C,F2[2])[0];
  printf("V=%a, A=%a, A2=%a\n",V,A,A2);
  printf("F=%a\n",F); 
  printf("F2=%a\n",F2);
  Fvec2=newvect(M+1); 
  Fvec2[0] = F2;
  for (I=1; I<=M; I++)  Fvec2[I] =  ((V[I-1]-1)/Alp2[I])*diff(F2,V[I-1]);
  R=map(red,Fvec2-ygDa2(A,B,C,V)*Fvec);
  return R;
}

/* ygDc(-4,[-1,-1],-2,[1/2,1/3]); --> det(Dm1)=(c-a)/(c-b1-b2)=0 
    if b=[-2,..] then OK.
   a,[b1,b2],c1 --fctr--> c-a-1, c-b1-b2-1
*/ 

/* 2014.08.19 */
/* Return value: [F_D like poly, V] 
  Note that the constant term is not 1 */
def poly_fd(A,B,C) {
  F=hgpoly_fd(A,B,C);
  return(atofd(F[0],A,B,C,F[2]));
}
def poly_fd_beta(Beta) {
  F=hgpoly_fd_beta(length(Beta)-2,Beta);
  return(atofd_beta(F[0],Beta,F[2]));
}

def poly_fdvec(A,B,C) {
  M = length(B);
  Alp = abc2alpha(A,B,C); 
  F=poly_fd(A,B,C);  
  V=F[1]; F=F[0];
  Fvec=newvect(M+1); 
  Fvec[0] = F;
  for (I=1; I<=M; I++)  Fvec[I] =  ((V[I-1]-1)/Alp[I])*diff(F,V[I-1]);
  return [Fvec,V];
}
def poly_fdvec_beta(Beta) {
  Marginal = beta2marginal(Beta);
  CSum=Marginal[1];
  RSum=Marginal[0];
  ABC=marginal2abc(RSum,CSum);
  return(poly_fdvec(ABC[0],ABC[1],ABC[2]));
}

def check26() {
   A=-3; C=-1; B=[-3,-2,-3];   
   /* A=-5; C=-6; B=[-1,-2,-3];   negative marginal */
  /* A=-5; C=-2; B=[-1,-2,-3]; */
   /* A=-5; C=2; B=[-1,-2,-3]; */
   /* A=-5; C=2; B=[-4];   */
   if (containNegative(abc2marginal(A,B,C))) error("Negative marginal");
  Fvec = poly_fdvec(A,B,C);
  V=Fvec[1]; Fvec=Fvec[0];
  Fvec2 = poly_fdvec(A-1,B,C)[0];
  R=map(red,Fvec2-ygDa2(A,B,C,V)*Fvec);
  return R;
}

/* Dc2*Da2 c->c-1, a->a-1. 
  C-A is canceled.  Not yet tested.
*/
def ygDca2(A,B,C,X) {
  Q0 = ygQmat2(A,B,C,X,0);
  Cmat = ygCmat2(A,B,C);
  return map(red,-Q0*matrix_inverse(Cmat));
}

/*
  Table. B[0] is the first row sum.
  B[0] |
  CB   |
         B[1], B[2], ..., B[M+1]
  hg poly in the case of CB==1.
  2014.08.20
 */
def hgpoly_fd_beta1(M,B) {
  CB = (base_sum(B,0,0,length(B)-1)-B[0])-B[0];
  if (CB != 1) error("The second row sum CB is not equal to 1.");
  /* Assume that CB == 1 */
  M = length(B)-2;
  N = (M+1)*2;
  Vx=[];
  for (I=0; I<N; I++) Vx = cons(util_v(x,[I+1]),Vx);
  Vx=reverse(Vx);
  F = 0;
  for (K=0; K<=M; K++) {
    Mon=1;
    for (J=0; J<=M; J++) {
      if (J != K) {
         Mon = Mon*(Vx[J]^(B[J+1]))/fac(B[J+1]);
      }
    }
    if (B[K+1] == 0) error("B[K+1]-1 is negative.");
    Mon = Mon*((Vx[K]^(B[K+1]-1))/fac(B[K+1]-1))*Vx[M+1+K];
    F += Mon;
  }
  return [F,dp_ptod(F,Vx),Vx];
}
def check27() {
   Beta = [7,1,5,2];
   Beta = [6,1,3,2,1]; /* A=-6, B=[-3,-2,-1],C=-4 */
   Beta = [8,2,3,2,2]; /* abc2marginal(-8,[-3,-2,-2],-5); [[8,1],[2,3,2,2]] */

   F1=hgpoly_fd_beta1(length(Beta)-2,Beta);
   F2=hgpoly_fd_beta0(length(Beta)-2,Beta);
   return F1[0]-F2[0];
}
def hgpoly_fd1(A,B,C) {
  Marginal = abc2marginal(A,B,C);
  if (containNegative(Marginal)) error("Negative marginal");
  M = length(B);
  Beta =cons(Marginal[0][0],Marginal[1]);
  return hgpoly_fd_beta1(M,Beta);
}

/* fvect_poly for C <= 0 */
def fvect_poly2(A,B,C,X) {
  if (C > 0) error("C is postive.");
  M=length(B);
  if (type(X) == 4) X=newvect(length(X),X);
  Xrule = assoc(xvars(M),vtol(X));
  CB = C-base_sum(B,0,0,length(B)-1)-1;
  if (CB == 0) {
    F = poly_fdvec(A,B,C)[0];
    return(base_replace(F,Xrule));
  }
  if (CB < 0) error("c-sum(b)-1 is negative.");
  Steps = CB-1;
  printf("Computing Dmat(ca) for parameters B=%a,X=%a\n",B,X);
  Dmat = ygDca2(a,B,c,X);
  Umat = map(red,matrix_inverse(Dmat));

  F = poly_fdvec(A-Steps,B,C-Steps)[0];
  F = base_replace(F,Xrule);
  for (I=0; I<Steps; I++) {
    Up = base_replace(Umat,[[a,A-Steps+1+I],[c,C-Steps+1+I]]);
    F = Up*F;
  }
  return(F);
}
def check28() {
  A=-5; B=[-4,-3];C=-2; X=[1/2,1/3];
  A=-5; B=[-4,-3,-2];C=-2; X=[1/2,1/3,1/5];
  printf("marginal=%a\n",abc2marginal(A,B,C));
  F1=fvect_poly2(A,B,C,X);
  printf("F1=%a, computing F2 by a bruce force method.\n",F1);
  F2=base_replace(poly_fdvec(A,B,C)[0],assoc(xvars(length(X)),X));
  return(F1-F2);
}
def check28b(T) {
  Beta=[6,5,4,1,1,1]; /* ogawa data in check21, it takes a few seconds */
  X = [1/7,1/3,1/2,1/11];
  Ma = beta2marginal(Beta);
  ABC=marginal2abc(Ma[0],Ma[1]);
  A=ABC[0]; B=ABC[1]; C=ABC[2];
  printf("marginal=%a\n",abc2marginal(A,B,C));
  F1=fvect_poly2(A,B,C,X);
  if (T == 0) return(F1);
  printf("F1=%a\n",F1);
  F=poly_fdvec_beta(Beta)[0]$   
  F2=base_replace(F,assoc(xvars(4),X));
  return(F1-F2);
}

/*
 works in case of row sum is zero or column sum is 0.
*/
def ahvec_beta(Beta,Y) {
  Opt = getopt();
  Ma=beta2marginal(Beta);
  M=length(Beta)-2;
  RS=newvect(2,Ma[0]);
  CS=newvect(M+1,Ma[1]);
  Mnew=M;
  Fvec=newvect(M+1);
  for (I=0, J=0; I<=M; I++) {
    if (CS[I]==0) {
      Mnew--; Fvec[I] = -1;
    }else{ Fvec[I] = J; J++; }
  }
  if (Mnew < 0) error("zero matrix");
  Ynew=newmat(2,Mnew+1);    
  CSnew=newvect(Mnew+1);
  for (I=0; I<=M; I++) {
    if (Fvec[I] >= 0) {
      J = Fvec[I];
      Ynew[0][J] = Y[0][I];
      Ynew[1][J] = Y[1][I];
      CSnew[J] = CS[I];
    }
  }
  if (RS[1] == 0) {
    T=RS[0]; RS[0] = RS[1]; RS[1] = T;
    for (J=0; J<=Mnew; J++) {
      T=Ynew[0][J];
      Ynew[0][J] = Ynew[1][J];
      Ynew[1][J] = T;
    }
  }
  ABCnew=marginal2abc(vtol(RS),vtol(CSnew));
  printf("RS=%a, CSnew=%a, Ynew=%a\n",RS,CSnew,Ynew);
  Tnew = ygahvec(ABCnew[0],ABCnew[1],ABCnew[2],Ynew | option_list=Opt);
  Fnew =Tnew[0];
  for (I=0; I<=M; I++) {
    if (Fvec[I] == -1) Fvec[I] = 0;
    else {
      J=Fvec[I];
      Fvec[I] = Fnew[J];
    }
  }
  return cons(Fvec,cdr(Tnew));
}
/*
ahvec_beta([3,1,2,0,3],[[1,1/2,1/3,1/5],[1,1,1,1]]|all=1);

[2402] abc2marginal(-5,[-4,-3],-2);
[[5,4],[2,4,3]]
[2403] marginal2abc([4,5],[2,4,3]);  
[-4,[-4,-3],-1]   c is again negative.

2014.08.26
ahvec_beta([10,1,2,3,4],[[3,1,1,1],[1,1/2,1/3,1/5]]|all=1);
returns "devision by 0".  Reason?

ahvec_abc(-6,[-2,-3],-4,[[1,1/2,1/3],[1,1,1]] | all=1);  
 -> 2014.08.27 it works.
cgi/r-fd.rr  r_ahvec(-6,[-2,-3],-4,[[1,1/2,1/3],[1,1,1]] | all=1);  
*/

def ahvec_abc(A,B,C,X) {
  Opt=getopt();
  Ma=abc2marginal(A,B,C);
  Beta=cons(Ma[0][0],Ma[1]);
  return ahvec_beta(Beta,X | option_list=Opt);  
}
/*
  It returns [E[U_10], E[U_11], ..., E[U_1m]]
 */
def expectation_abc_orig1(A,B,C,X) {
  R=ahvec_abc(A,B,C,X|all=1);
  Gamma=R[1];
  Der=R[0];
  /* printf("Der=%a\n",Der);  */
  Z=R[2]*Gamma;
  Der2 = newvect(length(Der));
  for (I=0; I<length(Der); I++) Der2[I] = Der[I]*Gamma;
  Der2 = vtol(Der2);
  E=newvect(length(Der));
  for (I=0; I<length(Der); I++) E[I] = X[1][I]*Der2[I]/Z;
  return(vtol(E));
}
/* 2014.12.13 */
def  abc2ahg(A,B,C) {
  M=length(B);
  Amat = [];
  R = newvect(2*(1+M));
  for (I=1+M; I<2*(1+M); I++) R[I]=1;
  Amat = cons(vtol(R),Amat);
  for (I=0; I<1+M; I++) {
    R = newvect(2*(1+M));
    R[I] = R[1+M+I] = 1;
    Amat = cons(vtol(R),Amat);
  }
  Amat = reverse(Amat);
  Bvect = newvect(2+M);
  Mar = abc2marginal(A,B,C);
  Bvect[0] = Mar[0][1];
  for (I=0; I<1+M; I++) {
    Bvect[1+I] = Mar[1][I];
  }
  return([Amat,vtol(Bvect)]);
}

/* 2014.02.28 */
/* [Z, [[d_11 Z, d_12 Z, ....],[d_21 Z, d_22 Z, ...]]] */
def ahmat_abc(A,B,C,Y) {
  R=ahvec_abc(A,B,C,Y|all=1);
  Gamma = R[1];
  Der = R[0];
  Z = R[2]*Gamma;
  /* second row */
  Der2 = newvect(length(Der));
  for (I=0; I<length(Der); I++) Der2[I] = Der[I]*Gamma;
  Mrow = abc2marginal(A,B,C)[1]; /* column marginal sums */
  /* first row */
  Der1 = newvect(length(Der));
  for (I=0; I<length(Der1); I++) {
    Der1[I] = (Mrow[I]*Z-Y[1][I]*Der2[I])/Y[0][I];
  }
  return([Z,[vtol(Der1),vtol(Der2)]]);
}

/*
  It returns [[E[U_00], E[U_01], ..., E[U_0m]], 
                  [E[U_10], E[U_11], ..., E[U_1m]]]
 */
def expectation_abc(A,B,C,X) {
  R=ahmat_abc(A,B,C,X);
  Z=R[0];
  DerMat=R[1];
  M=length(DerMat[0]);
  DerMat=newmat(2,M,DerMat)/Z;
  for (I=0; I<2;I++) for (J=0; J<M; J++) DerMat[I][J] = X[I][J]*DerMat[I][J];
  return(matrix_matrix_to_list(DerMat));
}

def log_ahmat_abc(A,B,C,X) {
   R=ahmat_abc(A,B,C,X);
   Z=R[0];
   DerMat=R[1];
   M=length(DerMat[0]);
   DerMat=newmat(2,M,DerMat)/Z;
   Z=eval(Z*exp(0));
   LogZ = eval(log(Z));
   for (I=0; I<2;I++) for (J=0; J<M; J++) DerMat[I][J] = eval(DerMat[I][J]*exp(0));
   return([LogZ,matrix_matrix_to_list(DerMat)]);
  
}

/*
  It returns
  [F=F_D,gradient(F),Hessian(F)]
  2015.08.16  copied from h-mle/A-hg2/Prog/hessian_fd.rr
 */
def fd_hessian2(A,B,C,Xval) {
  M = length(Xval);
  Hfd_M=M;
  FF=ygfvect_poly(A,B,C,Xval);  // double check. Same with Matsumoto sol base ?
  Hfd_F=FF;
  setparam_abc(M,A,B,C);
  Hfd_H = P= psi();
  V = newvect(Hfd_M);
  DV = newvect(Hfd_M);
  for (I=0; I<M; I++) {
    V[I] = util_v(x,[I+1]);
    DV[I] = util_v(dx,[I+1]);
  }
  V = vtol(V);  DV = vtol(DV);
  Rule = assoc(V,Xval);
  // [d-psi()] F = 0  
  P=base_replace(P,yrule());
  Psi = Hfd_psi= base_replace_n(P, Rule);
  Pf = newvect(M);
  for (I=0; I<M; I++) Pf[I] = map(coef,Psi,1,DV[I]);
  Grad0 = newvect(M);
  Hess0 = newmat(M,M) ;
  FF0 = FF[0];
 // F=(F_D, (x_0-1)/alpha_1 dx_0 F_D, ..., (x_{M-1}-1)/alpha_M dx_{M-1} F_D)
 // The first component of Pf[i]*F = Pfval[i]  is gradient.
  Pfval=newvect(M);
  for (I=0; I<M; I++) Pfval[I] = Pf[I]*FF;
  for (I=0; I<M; I++)  Grad0[I] = Pfval[I][0];
  // tk_fd.getparam()   return [MM,AA,BB,CC,Alpha,Alpha_ap,Alpha_am,MyDebug];

  // Set alpha.  copied from tk_fd.rr
  H_MM=M;
 H_Alpha=newvect(H_MM+3);
 H_AA=A;
 H_BB = newvect(H_MM+1);
 for (I=1; I<=H_MM; I++) H_BB[I] = B[I-1];
 H_CC=C;
 H_Alpha[0]=-H_CC+base_sum(H_BB,0,1,H_MM);
 for (I=1; I<=H_MM; I++) H_Alpha[I] = -H_BB[I];
 H_Alpha[H_MM+1] = H_CC-H_AA;
 H_Alpha[H_MM+2] = H_AA;
 if (Hfd_debug) printf("M=%a\n",M);
 if (Hfd_debug) printf("H_Alpha = %a\n",H_Alpha);
 if (Hfd_debug) printf("Xval = %a\n",Xval);

  for (I=0; I<M; I++) {
    for (J=0; J<M; J++) {
      // dx_j*F 's (i +1)-th element.  i<>j.  (x_i-1)/alpha_{i+1} dx_i*dx_j*F_D
      if (I != J) Hess0[I][J] = Pfval[J][I+1]*H_Alpha[I+1]/(Xval[I]-1);
      else {
	Hess0[I][I] = (Pfval[J][I+1]-(1/H_Alpha[I+1])*Grad0[I])*H_Alpha[I+1]/(Xval[I]-1);
      }
      /*
           dx_i*F 's (i+1) the lement.     (x_i-1)/alpha_{i+1} dx_i*dx_i*F_D 
                                      +1/alpha_{i+1} dx_i*F_D 
           Since dx_j*F=Pf[j]*F = Pfval[j], we do not need to differentiate  Pf.
           fd_hessian2() uses this method.
       */
    }
  }
  return([FF0,Grad0,Hess0]);
}

def hfdtest2() {
  printf("Starting hfdtest2().\n");
  // cf. check28.  
  A=-5; B=[-4,-3,-2];C=-2; XX=[1/2,1/3,1/5]; V=[x1,x2,x3];
  // tk_fd.fd does not work. 2015.08.15.  Done on 08.16

  /*
  A=-3$
  B=[-3,-2,-5,-4]$
  C=10$
  XX=[2,3,4,5]$
  V=[x1,x2,x3,x4];
  */

  M=length(B)$
  Hfd_Hess=HH=fd_hessian2(A,B,C,XX)$
  Hess=HH[2]$
  printf("Computing polynomial sol F_D\n");
  if (C > 0) {
    F=fd(A,B,C,V | approx=-A+1);
  }else {
  // Slow, but works for the case C < 0. 2015.08.16
     T=hgpoly_fd(A,B,C);
     T=atofd(T[0],A,B,C,T[2]);
     F=base_replace(T[0],assoc(T[1],V));
  }

  printf("F_D=%a\n",F);
  Rule=assoc(V,XX);
  T=HH[0]-base_replace(F,Rule);
  printf("fval check: %a\n",T);
  for (I=0; I<M; I++) {
    T = HH[1][I]-base_replace(diff(F,V[I]),Rule);
    printf("grad check: %a\n",T);
  }
  for (I=0; I<M; I++) {
    for (J=0; J<M; J++) {
      T = (HH[2])[I][J]-base_replace(diff(diff(F,V[I]),V[J]),Rule);
      printf("Hessian check: %a\n",T);
    }
  }
}


#if  !USE_MODULE
setparam(2)$
// setparam_by_number(2,2)$
setparam_by_int(2,2)$
getparam()$
#else
endmodule;  // endmodule of tk_fd

tk_fd.setparam_by_int(2,2)$
tk_fd.getparam()$
#endif


end$