[BACK]Return to dist.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / asir2000 / engine

Diff for /OpenXM_contrib2/asir2000/engine/dist.c between version 1.25 and 1.41

version 1.25, 2003/07/09 07:11:08 version 1.41, 2006/08/08 02:39:17
Line 45 
Line 45 
  * DEVELOPER SHALL HAVE NO LIABILITY IN CONNECTION WITH THE USE,   * DEVELOPER SHALL HAVE NO LIABILITY IN CONNECTION WITH THE USE,
  * PERFORMANCE OR NON-PERFORMANCE OF THE SOFTWARE.   * PERFORMANCE OR NON-PERFORMANCE OF THE SOFTWARE.
  *   *
  * $OpenXM: OpenXM_contrib2/asir2000/engine/dist.c,v 1.24 2003/06/19 07:08:19 noro Exp $   * $OpenXM: OpenXM_contrib2/asir2000/engine/dist.c,v 1.40 2006/04/16 00:51:13 noro Exp $
 */  */
 #include "ca.h"  #include "ca.h"
   
Line 72  int (*primitive_cmpdl[3])() = {cmpdl_revgradlex,cmpdl_
Line 72  int (*primitive_cmpdl[3])() = {cmpdl_revgradlex,cmpdl_
 int do_weyl;  int do_weyl;
   
 int dp_nelim,dp_fcoeffs;  int dp_nelim,dp_fcoeffs;
 struct order_spec dp_current_spec;  struct order_spec *dp_current_spec;
   struct modorder_spec *dp_current_modspec;
 int *dp_dl_work;  int *dp_dl_work;
   
 void comm_muld_trunc(VL vl,DP p1,DP p2,DL dl,DP *pr);  void comm_muld_trunc(VL vl,DP p1,DP p2,DL dl,DP *pr);
Line 80  void comm_quod(VL vl,DP p1,DP p2,DP *pr);
Line 81  void comm_quod(VL vl,DP p1,DP p2,DP *pr);
 void muldm_trunc(VL vl,DP p,MP m0,DL dl,DP *pr);  void muldm_trunc(VL vl,DP p,MP m0,DL dl,DP *pr);
 void muldc_trunc(VL vl,DP p,P c,DL dl,DP *pr);  void muldc_trunc(VL vl,DP p,P c,DL dl,DP *pr);
   
   void order_init()
   {
           struct order_spec *spec;
   
           create_order_spec(0,0,&spec);
           initd(spec);
           create_modorder_spec(0,0,&dp_current_modspec);
   }
   
 int has_sfcoef(DP f)  int has_sfcoef(DP f)
 {  {
         MP t;          MP t;
Line 111  int has_sfcoef_p(P f)
Line 121  int has_sfcoef_p(P f)
 void initd(struct order_spec *spec)  void initd(struct order_spec *spec)
 {  {
         switch ( spec->id ) {          switch ( spec->id ) {
                   case 3:
                           cmpdl = cmpdl_composite;
                           dp_dl_work = (int *)MALLOC_ATOMIC(spec->nv*sizeof(int));
                           break;
                 case 2:                  case 2:
                         cmpdl = cmpdl_matrix;                          cmpdl = cmpdl_matrix;
                         dp_dl_work = (int *)MALLOC_ATOMIC(spec->nv*sizeof(int));                          dp_dl_work = (int *)MALLOC_ATOMIC(spec->nv*sizeof(int));
Line 151  void initd(struct order_spec *spec)
Line 165  void initd(struct order_spec *spec)
                         }                          }
                         break;                          break;
         }          }
         dp_current_spec = *spec;          dp_current_spec = spec;
 }  }
   
 void ptod(VL vl,VL dvl,P p,DP *pr)  void ptod(VL vl,VL dvl,P p,DP *pr)
Line 286  void addd(VL vl,DP p1,DP p2,DP *pr)
Line 300  void addd(VL vl,DP p1,DP p2,DP *pr)
         int n;          int n;
         MP m1,m2,mr,mr0;          MP m1,m2,mr,mr0;
         P t;          P t;
           DL d;
   
         if ( !p1 )          if ( !p1 )
                 *pr = p2;                  *pr = p2;
         else if ( !p2 )          else if ( !p2 )
                 *pr = p1;                  *pr = p1;
         else {          else {
                   if ( OID(p1) <= O_R ) {
                           n = NV(p2);     NEWDL(d,n);
                           NEWMP(m1); m1->dl = d; C(m1) = (P)p1; NEXT(m1) = 0;
                           MKDP(n,m1,p1); (p1)->sugar = 0;
                   }
                   if ( OID(p2) <= O_R ) {
                           n = NV(p1);     NEWDL(d,n);
                           NEWMP(m2); m2->dl = d; C(m2) = (P)p2; NEXT(m2) = 0;
                           MKDP(n,m2,p2); (p2)->sugar = 0;
                   }
                 for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; )                  for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; )
                         switch ( (*cmpdl)(n,m1->dl,m2->dl) ) {                          switch ( (*cmpdl)(n,m1->dl,m2->dl) ) {
                                 case 0:                                  case 0:
Line 409  NODE symb_merge(NODE m1,NODE m2,int n)
Line 434  NODE symb_merge(NODE m1,NODE m2,int n)
                 while ( cur && m ) {                  while ( cur && m ) {
                         d1 = (DL)BDY(cur);                          d1 = (DL)BDY(cur);
                         d2 = (DL)BDY(m);                          d2 = (DL)BDY(m);
   #if 1
                           switch ( (*cmpdl)(n,(DL)BDY(cur),(DL)BDY(m)) ) {
   #else
                           /* XXX only valid for DRL */
                         if ( d1->td > d2->td )                          if ( d1->td > d2->td )
                                 c = 1;                                  c = 1;
                         else if ( d1->td < d2->td )                          else if ( d1->td < d2->td )
Line 422  NODE symb_merge(NODE m1,NODE m2,int n)
Line 451  NODE symb_merge(NODE m1,NODE m2,int n)
                                 else                                  else
                                         c = -1;                                          c = -1;
                         }                          }
 #if 0  
                         switch ( (*cmpdl)(n,(DL)BDY(cur),(DL)BDY(m)) ) {  
 #else  
                         switch ( c ) {                          switch ( c ) {
 #endif  #endif
                                 case 0:                                  case 0:
Line 570  void subd(VL vl,DP p1,DP p2,DP *pr)
Line 596  void subd(VL vl,DP p1,DP p2,DP *pr)
 void chsgnd(DP p,DP *pr)  void chsgnd(DP p,DP *pr)
 {  {
         MP m,mr,mr0;          MP m,mr,mr0;
           Obj r;
   
         if ( !p )          if ( !p )
                 *pr = 0;                  *pr = 0;
         else {          else if ( OID(p) <= O_R ) {
                   chsgnr((Obj)p,&r); *pr = (DP)r;
           } else {
                 for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {                  for ( mr0 = 0, m = BDY(p); m; m = NEXT(m) ) {
                         NEXTMP(mr0,mr); chsgnp(C(m),&C(mr)); mr->dl = m->dl;                          NEXTMP(mr0,mr); chsgnp(C(m),&C(mr)); mr->dl = m->dl;
                 }                  }
Line 1092  int compd(VL vl,DP p1,DP p2)
Line 1121  int compd(VL vl,DP p1,DP p2)
                 return p2 ? -1 : 0;                  return p2 ? -1 : 0;
         else if ( !p2 )          else if ( !p2 )
                 return 1;                  return 1;
           else if ( NV(p1) != NV(p2) )
                   error("compd : size mismatch");
         else {          else {
                 for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2);                  for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2);
                         m1 && m2; m1 = NEXT(m1), m2 = NEXT(m2) )                          m1 && m2; m1 = NEXT(m1), m2 = NEXT(m2) )
Line 1466  int cmpdl_order_pair(int n,DL d1,DL d2)
Line 1497  int cmpdl_order_pair(int n,DL d1,DL d2)
         int len,head;          int len,head;
         struct order_pair *pair;          struct order_pair *pair;
   
         len = dp_current_spec.ord.block.length;          len = dp_current_spec->ord.block.length;
         pair = dp_current_spec.ord.block.order_pair;          if ( n != dp_current_spec->nv )
                   error("cmpdl_order_pair : incompatible order specification");
           pair = dp_current_spec->ord.block.order_pair;
   
         head = 0;          head = 0;
         for ( i = 0, t1 = d1->d, t2 = d2->d; i < len; i++ ) {          for ( i = 0, t1 = d1->d, t2 = d2->d; i < len; i++ ) {
Line 1516  int cmpdl_order_pair(int n,DL d1,DL d2)
Line 1549  int cmpdl_order_pair(int n,DL d1,DL d2)
         return 0;          return 0;
 }  }
   
   int cmpdl_composite(int nv,DL d1,DL d2)
   {
           int n,i,j,k,start,s,len;
           int *dw;
           struct sparse_weight *sw;
           struct weight_or_block *worb;
           int *w,*t1,*t2;
   
           n = dp_current_spec->ord.composite.length;
           worb = dp_current_spec->ord.composite.w_or_b;
           w = dp_dl_work;
           for ( i = 0, t1 = d1->d, t2 = d2->d; i < nv; i++ )
                   w[i] = t1[i]-t2[i];
           for ( i = 0; i < n; i++, worb++ ) {
                   len = worb->length;
                   switch ( worb->type ) {
                           case IS_DENSE_WEIGHT:
                                   dw = worb->body.dense_weight;
                                   for ( j = 0, s = 0; j < len; j++ )
                                           s += dw[j]*w[j];
                                   if ( s > 0 ) return 1;
                                   else if ( s < 0 ) return -1;
                                   break;
                           case IS_SPARSE_WEIGHT:
                                   sw = worb->body.sparse_weight;
                                   for ( j = 0, s = 0; j < len; j++ )
                                           s += sw[j].value*w[sw[j].pos];
                                   if ( s > 0 ) return 1;
                                   else if ( s < 0 ) return -1;
                                   break;
                           case IS_BLOCK:
                                   start = worb->body.block.start;
                                   switch ( worb->body.block.order ) {
                                           case 0:
                                                   for ( j = 0, k = start, s = 0; j < len; j++, k++ ) {
                                                           s += MUL_WEIGHT(w[k],k);
                                                   }
                                                   if ( s > 0 ) return 1;
                                                   else if ( s < 0 ) return -1;
                                                   else {
                                                           for ( j = k-1; j >= start && w[j] == 0; j-- );
                                                           if ( j >= start )
                                                                   return w[j] < 0 ? 1 : -1;
                                                   }
                                                   break;
                                           case 1:
                                                   for ( j = 0, k = start, s = 0; j < len; j++, k++ ) {
                                                           s += MUL_WEIGHT(w[k],k);
                                                   }
                                                   if ( s > 0 ) return 1;
                                                   else if ( s < 0 ) return -1;
                                                   else {
                                                           for ( j = 0, k = start;  j < len && w[j] == 0; j++, k++ );
                                                           if ( j < len )
                                                                   return w[j] > 0 ? 1 : -1;
                                                   }
                                                   break;
                                           case 2:
                                                   for ( j = 0, k = start;  j < len && w[j] == 0; j++, k++ );
                                                   if ( j < len )
                                                           return w[j] > 0 ? 1 : -1;
                                                   break;
                                   }
                                   break;
                   }
           }
           return 0;
   }
   
 int cmpdl_matrix(int n,DL d1,DL d2)  int cmpdl_matrix(int n,DL d1,DL d2)
 {  {
         int *v,*w,*t1,*t2;          int *v,*w,*t1,*t2;
Line 1524  int cmpdl_matrix(int n,DL d1,DL d2)
Line 1626  int cmpdl_matrix(int n,DL d1,DL d2)
   
         for ( i = 0, t1 = d1->d, t2 = d2->d, w = dp_dl_work; i < n; i++ )          for ( i = 0, t1 = d1->d, t2 = d2->d, w = dp_dl_work; i < n; i++ )
                 w[i] = t1[i]-t2[i];                  w[i] = t1[i]-t2[i];
         len = dp_current_spec.ord.matrix.row;          len = dp_current_spec->ord.matrix.row;
         matrix = dp_current_spec.ord.matrix.matrix;          matrix = dp_current_spec->ord.matrix.matrix;
         for ( j = 0; j < len; j++ ) {          for ( j = 0; j < len; j++ ) {
                 v = matrix[j];                  v = matrix[j];
                 for ( i = 0, s = 0; i < n; i++ )                  for ( i = 0, s = 0; i < n; i++ )
Line 1590  DL remove_head_bucket(GeoBucket g,int nv)
Line 1692  DL remove_head_bucket(GeoBucket g,int nv)
                 return d;                  return d;
         }          }
 }  }
   
   /*  DPV functions */
   
   void adddv(VL vl,DPV p1,DPV p2,DPV *pr)
   {
           int i,len;
           DP *e;
   
           if ( !p1 || !p2 )
                   error("adddv : invalid argument");
           else if ( p1->len != p2->len )
                   error("adddv : size mismatch");
           else {
                   len = p1->len;
                   e = (DP *)MALLOC(p1->len*sizeof(DP));
                   for ( i = 0; i < len; i++ )
                           addd(vl,p1->body[i],p2->body[i],&e[i]);
                   MKDPV(len,e,*pr);
                   (*pr)->sugar = MAX(p1->sugar,p2->sugar);
           }
   }
   
   void subdv(VL vl,DPV p1,DPV p2,DPV *pr)
   {
           int i,len;
           DP *e;
   
           if ( !p1 || !p2 )
                   error("subdv : invalid argument");
           else if ( p1->len != p2->len )
                   error("subdv : size mismatch");
           else {
                   len = p1->len;
                   e = (DP *)MALLOC(p1->len*sizeof(DP));
                   for ( i = 0; i < len; i++ )
                           subd(vl,p1->body[i],p2->body[i],&e[i]);
                   MKDPV(len,e,*pr);
                   (*pr)->sugar = MAX(p1->sugar,p2->sugar);
           }
   }
   
   void chsgndv(DPV p1,DPV *pr)
   {
           int i,len;
           DP *e;
   
           if ( !p1 )
                   error("subdv : invalid argument");
           else {
                   len = p1->len;
                   e = (DP *)MALLOC(p1->len*sizeof(DP));
                   for ( i = 0; i < len; i++ )
                           chsgnd(p1->body[i],&e[i]);
                   MKDPV(len,e,*pr);
                   (*pr)->sugar = p1->sugar;
           }
   }
   
   void muldv(VL vl,DP p1,DPV p2,DPV *pr)
   {
           int i,len;
           DP *e;
   
           len = p2->len;
           e = (DP *)MALLOC(p2->len*sizeof(DP));
           if ( !p1 ) {
                   MKDPV(len,e,*pr);
                   (*pr)->sugar = 0;
           } else {
                   for ( i = 0; i < len; i++ )
                           muld(vl,p1,p2->body[i],&e[i]);
                   MKDPV(len,e,*pr);
                   (*pr)->sugar = p1->sugar + p2->sugar;
           }
   }
   
   int compdv(VL vl,DPV p1,DPV p2)
   {
           int i,t,len;
   
           if ( p1->len != p2->len )
                   error("compdv : size mismatch");
           else {
                   len = p1->len;
                   for ( i = 0; i < len; i++ )
                           if ( t = compd(vl,p1->body[i],p2->body[i]) )
                                   return t;
                   return 0;
           }
   }
   
   int ni_next(int *a,int n)
   {
           int i,j,k,kj;
   
           /* find the first nonzero a[j] */
           for ( j = 0; j < n && a[j] == 0; j++ );
           /* find the first zero a[k] after a[j] */
           for ( k = j; k < n && a[k] == 1; k++ );
           if ( k == n ) return 0;
           /* a[0] = 0, ... , a[j-1] = 0, a[j] = 1, ..., a[k-1] = 1, a[k] = 0 */
           /* a[0] = 1,..., a[k-j-2] = 1, a[k-j-1] = 0, ..., a[k-1] = 0, a[k] = 1 */
           kj = k-j-1;
           for ( i = 0; i < kj; i++ ) a[i] = 1;
           for ( ; i < k; i++ ) a[i] = 0;
           a[k] = 1;
           return 1;
   }
   
   int comp_nbm(NBM a,NBM b)
   {
           int d,i,w,ai,bi;
           int *ab,*bb;
   
           if ( a->d > b->d ) return 1;
           else if ( a->d < b->d ) return -1;
           else {
                   d = a->d; ab = a->b; bb = b->b;
   #if 0
                   w = (d+31)/32;
                   for ( i = 0; i < w; i++ )
                           if ( ab[i] > bb[i] ) return 1;
                           else if ( ab[i] < bb[i] ) return -1;
   #else
                   for ( i = 0; i < d; i++ ) {
                           ai = NBM_GET(ab,i);
                           bi = NBM_GET(bb,i);
                           if ( ai > bi ) return 1;
                           else if ( ai < bi ) return -1;
                   }
   #endif
                   return 0;
           }
   }
   
   NBM mul_nbm(NBM a,NBM b)
   {
           int ad,bd,d,i,j;
           int *ab,*bb,*mb;
           NBM m;
           NODE r;
           NBP u;
   
           ad = a->d; bd = b->d; ab = a->b; bb = b->b;
           d = ad + bd;
           NEWNBM(m); NEWNBMBDY(m,d);
           m->d = d; mulp(CO,a->c,b->c,&m->c); mb = m->b;
           j = 0;
           for ( i = 0; i < ad; i++, j++ )
                   if ( NBM_GET(ab,i) ) NBM_SET(mb,j);
                   else NBM_CLR(mb,j);
           for ( i = 0; i < bd; i++, j++ )
                   if ( NBM_GET(bb,i) ) NBM_SET(mb,j);
                   else NBM_CLR(mb,j);
           return m;
   }
   
   NBP nbmtonbp(NBM m)
   {
           NODE n;
           NBP u;
   
           MKNODE(n,m,0);
           MKNBP(u,n);
           return u;
   }
   
   /* a=c*x*rest -> a0= x*rest, ah=x, ar=rest */
   
   P separate_nbm(NBM a,NBP *a0,NBP *ah,NBP *ar)
   {
           int i,d1;
           NBM t;
   
           if ( !a->d ) error("separate_nbm : invalid argument");
   
           if ( a0 ) {
                   NEWNBM(t); t->d = a->d; t->b = a->b; t->c = (P)ONE;
                   *a0 = nbmtonbp(t);
           }
   
           if ( ah ) {
                   NEWNBM(t); NEWNBMBDY(t,1); t->d = 1; t->c = (P)ONE;
                   if ( NBM_GET(a->b,0) ) NBM_SET(t->b,0);
                   else NBM_CLR(t->b,0);
                   *ah = nbmtonbp(t);
           }
   
           if ( ar ) {
                   d1 = a->d-1;
                   NEWNBM(t); NEWNBMBDY(t,d1); t->d = d1; t->c = (P)ONE;
                   for ( i = 0; i < d1; i++ ) {
                           if ( NBM_GET(a->b,i+1) ) NBM_SET(t->b,i);
                           else NBM_CLR(t->b,i);
                   }
                   *ar = nbmtonbp(t);
           }
   
           return a->c;
   }
   
   NBP make_xky(int k)
   {
           int k1,i;
           NBM t;
   
           NEWNBM(t); NEWNBMBDY(t,k); t->d = k; t->c = (P)ONE;
           k1 = k-1;
           for ( i = 0; i < k1; i++ ) NBM_SET(t->b,i);
           NBM_CLR(t->b,i);
           return nbmtonbp(t);
   }
   
   /* a=c*x^(k-1)*y*rest -> a0= x^(k-1)*y*rest, ah=x^(k-1)*y, ar=rest */
   
   P separate_xky_nbm(NBM a,NBP *a0,NBP *ah,NBP *ar)
   {
           int i,d1,k,k1;
           NBM t;
   
           if ( !a->d )
                   error("separate_nbm : invalid argument");
           for ( i = 0; i < a->d && NBM_GET(a->b,i); i++ );
           if ( i == a->d )
                   error("separate_nbm : invalid argument");
           k1 = i;
           k = i+1;
   
           if ( a0 ) {
                   NEWNBM(t); t->d = a->d; t->b = a->b; t->c = (P)ONE;
                   *a0 = nbmtonbp(t);
           }
   
           if ( ah ) {
                   NEWNBM(t); NEWNBMBDY(t,k); t->d = k; t->c = (P)ONE;
                   for ( i = 0; i < k1; i++ ) NBM_SET(t->b,i);
                   NBM_CLR(t->b,i);
                   *ah = nbmtonbp(t);
           }
   
           if ( ar ) {
                   d1 = a->d-k;
                   NEWNBM(t); NEWNBMBDY(t,d1); t->d = d1; t->c = (P)ONE;
                   for ( i = 0; i < d1; i++ ) {
                           if ( NBM_GET(a->b,i+k) ) NBM_SET(t->b,i);
                           else NBM_CLR(t->b,i);
                   }
                   *ar = nbmtonbp(t);
           }
   
           return a->c;
   }
   
   void shuffle_mulnbp(VL vl,NBP p1,NBP p2, NBP *rp);
   void harmonic_mulnbp(VL vl,NBP p1,NBP p2, NBP *rp);
   void mulnbmnbp(VL vl,NBM m,NBP p, NBP *rp);
   void mulnbpnbm(VL vl,NBP p,NBM m, NBP *rp);
   
   NBP shuffle_mul_nbm(NBM a,NBM b)
   {
           NBP u,a0,ah,ar,b0,bh,br,a1,b1,t;
           P ac,bc,c;
   
           if ( !a->d || !b->d )
                   u = nbmtonbp(mul_nbm(a,b));
           else {
                   ac = separate_nbm(a,&a0,&ah,&ar);
                   bc = separate_nbm(b,&b0,&bh,&br);
                   mulp(CO,ac,bc,&c);
                   shuffle_mulnbp(CO,ar,b0,&t); mulnbp(CO,ah,t,&a1);
                   shuffle_mulnbp(CO,a0,br,&t); mulnbp(CO,bh,t,&b1);
                   addnbp(CO,a1,b1,&t); mulnbp(CO,(NBP)c,t,&u);
           }
           return u;
   }
   
   NBP harmonic_mul_nbm(NBM a,NBM b)
   {
           NBP u,a0,ah,ar,b0,bh,br,a1,b1,t,s,abk,ab1;
           P ac,bc,c;
   
           if ( !a->d || !b->d )
                   u = nbmtonbp(mul_nbm(a,b));
           else {
                   mulp(CO,a->c,b->c,&c);
                   ac = separate_xky_nbm(a,&a0,&ah,&ar);
                   bc = separate_xky_nbm(b,&b0,&bh,&br);
                   mulp(CO,ac,bc,&c);
                   harmonic_mulnbp(CO,ar,b0,&t); mulnbp(CO,ah,t,&a1);
                   harmonic_mulnbp(CO,a0,br,&t); mulnbp(CO,bh,t,&b1);
                   abk = make_xky(((NBM)BDY(BDY(ah)))->d+((NBM)BDY(BDY(bh)))->d);
                   harmonic_mulnbp(CO,ar,br,&t); mulnbp(CO,abk,t,&ab1);
                   addnbp(CO,a1,b1,&t); addnbp(CO,t,ab1,&s); mulnbp(CO,(NBP)c,s,&u);
           }
           return u;
   
   }
   
   void addnbp(VL vl,NBP p1,NBP p2, NBP *rp)
   {
           NODE b1,b2,br,br0;
           NBM m1,m2,m;
           P c;
   
           if ( !p1 )
                   *rp = p2;
           else if ( !p2 )
                   *rp = p1;
           else {
                   for ( b1 = BDY(p1), b2 = BDY(p2), br0 = 0; b1 && b2; ) {
                           m1 = (NBM)BDY(b1); m2 = (NBM)BDY(b2);
                           switch ( comp_nbm(m1,m2) ) {
                                   case 0:
                                           addp(CO,m1->c,m2->c,&c);
                                           if ( c ) {
                                                   NEXTNODE(br0,br);
                                                   NEWNBM(m); m->d = m1->d; m->c = c; m->b = m1->b;
                                                   BDY(br) = (pointer)m;
                                           }
                                           b1 = NEXT(b1); b2 = NEXT(b2); break;
                                   case 1:
                                           NEXTNODE(br0,br); BDY(br) = BDY(b1);
                                           b1 = NEXT(b1); break;
                                   case -1:
                                           NEXTNODE(br0,br); BDY(br) = BDY(b2);
                                           b2 = NEXT(b2); break;
                           }
                   }
                   if ( !br0 )
                           if ( b1 )
                                   br0 = b1;
                           else if ( b2 )
                                   br0 = b2;
                           else {
                                   *rp = 0;
                                   return;
                           }
                   else if ( b1 )
                           NEXT(br) = b1;
                   else if ( b2 )
                                   NEXT(br) = b2;
                   else
                           NEXT(br) = 0;
                   MKNBP(*rp,br0);
           }
   }
   
   void subnbp(VL vl,NBP p1,NBP p2, NBP *rp)
   {
           NBP t;
   
           chsgnnbp(p2,&t);
           addnbp(vl,p1,t,rp);
   }
   
   void chsgnnbp(NBP p,NBP *rp)
   {
           NODE r0,r,b;
           NBM m,m1;
   
           for ( r0 = 0, b = BDY(p); b; b = NEXT(b) ) {
                   NEXTNODE(r0,r);
                   m = (NBM)BDY(b);
                   NEWNBM(m1); m1->d = m->d; m1->b = m->b; chsgnp(m->c,&m1->c);
                   BDY(r) = m1;
           }
           if ( r0 ) NEXT(r) = 0;
           MKNBP(*rp,r0);
   }
   
   void mulnbp(VL vl,NBP p1,NBP p2, NBP *rp)
   {
           NODE b,n;
           NBP r,t,s;
           NBM m;
   
           if ( !p1 || !p2 ) {
                   *rp = 0; return;
           }
           if ( OID(p1) != O_NBP ) {
                   if ( !POLY(p1) )
                           error("mulnbp : invalid argument");
                   NEWNBM(m); m->d = 0; m->b = 0; m->c = (P)p1;
                   MKNODE(n,m,0); MKNBP(p1,n);
           }
           if ( OID(p2) != O_NBP ) {
                   if ( !POLY(p2) )
                           error("mulnbp : invalid argument");
                   NEWNBM(m); m->d = 0; m->b = 0; m->c = (P)p2;
                   MKNODE(n,m,0); MKNBP(p2,n);
           }
           if ( length(BDY(p1)) < length(BDY(p2)) ) {
                   for ( r = 0, b = BDY(p1); b; b = NEXT(b) ) {
                           mulnbmnbp(vl,(NBM)BDY(b),p2,&t);
                           addnbp(vl,r,t,&s); r = s;
                   }
                   *rp = r;
           } else {
                   for ( r = 0, b = BDY(p2); b; b = NEXT(b) ) {
                           mulnbpnbm(vl,p1,(NBM)BDY(b),&t);
                           addnbp(vl,r,t,&s); r = s;
                   }
                   *rp = r;
           }
   }
   
   void mulnbmnbp(VL vl,NBM m,NBP p, NBP *rp)
   {
           NODE b,r0,r;
   
           if ( !p ) *rp = 0;
           else {
                   for ( r0 = 0, b = BDY(p); b; b = NEXT(b) ) {
                           NEXTNODE(r0,r);
                           BDY(r) = mul_nbm(m,(NBM)BDY(b));
                   }
                   if ( r0 ) NEXT(r) = 0;
                   MKNBP(*rp,r0);
           }
   }
   
   void mulnbpnbm(VL vl,NBP p,NBM m, NBP *rp)
   {
           NODE b,r0,r;
   
           if ( !p ) *rp = 0;
           else {
                   for ( r0 = 0, b = BDY(p); b; b = NEXT(b) ) {
                           NEXTNODE(r0,r);
                           BDY(r) = mul_nbm((NBM)BDY(b),m);
                   }
                   if ( r0 ) NEXT(r) = 0;
                   MKNBP(*rp,r0);
           }
   }
   
   void pwrnbp(VL vl,NBP a,Q q,NBP *c)
   {
           int t;
           NBP a1,a2;
           N n1;
           Q q1;
           NBM m;
           NODE r;
   
           if ( !q ) {
                    NEWNBM(m); m->d = 0; m->c = (P)ONE; m->b = 0;
                    MKNODE(r,m,0); MKNBP(*c,r);
           } else if ( !a )
                   *c = 0;
           else if ( UNIQ(q) )
                   *c = a;
           else {
                   t = divin(NM(q),2,&n1); NTOQ(n1,1,q1);
                   pwrnbp(vl,a,q1,&a1);
                   mulnbp(vl,a1,a1,&a2);
                   if ( t )
                           mulnbp(vl,a2,a,c);
                   else
                           *c = a2;
           }
   }
   
   int compnbp(VL vl,NBP p1,NBP p2)
   {
           NODE n1,n2;
           NBM m1,m2;
           int t;
   
           if ( !p1 )
                   return p2 ? -1 : 0;
           else if ( !p2 )
                   return 1;
           else {
                   for ( n1 = BDY(p1), n2 = BDY(p2);
                           n1 && n2; n1 = NEXT(n1), n2 = NEXT(n2) ) {
                           m1 = (NBM)BDY(n1); m2 = (NBM)BDY(n2);
                           if ( (t = comp_nbm(m1,m2)) || (t = compp(CO,m1->c,m2->c) ) )
                                   return t;
                   }
                   if ( n1 )
                           return 1;
                   else if ( n2 )
                           return -1;
                   else
                           return 0;
           }
   }
   
   void shuffle_mulnbp(VL vl,NBP p1,NBP p2, NBP *rp)
   {
           NODE b1,b2,n;
           NBP r,t,s;
           NBM m;
   
           if ( !p1 || !p2 ) {
                   *rp = 0; return;
           }
           if ( OID(p1) != O_NBP ) {
                   if ( !POLY(p1) )
                           error("shuffle_mulnbp : invalid argument");
                   NEWNBM(m); m->d = 0; m->b = 0; m->c = (P)p1;
                   MKNODE(n,m,0); MKNBP(p1,n);
           }
           if ( OID(p2) != O_NBP ) {
                   if ( !POLY(p2) )
                           error("shuffle_mulnbp : invalid argument");
                   NEWNBM(m); m->d = 0; m->b = 0; m->c = (P)p2;
                   MKNODE(n,m,0); MKNBP(p2,n);
           }
           for ( r = 0, b1 = BDY(p1); b1; b1 = NEXT(b1) )
                   for ( m = BDY(b1), b2 = BDY(p2); b2; b2 = NEXT(b2) ) {
                           t = shuffle_mul_nbm(m,(NBM)BDY(b2));
                           addnbp(vl,r,t,&s); r = s;
                   }
           *rp = r;
   }
   
   void harmonic_mulnbp(VL vl,NBP p1,NBP p2, NBP *rp)
   {
           NODE b1,b2,n;
           NBP r,t,s;
           NBM m;
   
           if ( !p1 || !p2 ) {
                   *rp = 0; return;
           }
           if ( OID(p1) != O_NBP ) {
                   if ( !POLY(p1) )
                           error("harmonic_mulnbp : invalid argument");
                   NEWNBM(m); m->d = 0; m->b = 0; m->c = (P)p1;
                   MKNODE(n,m,0); MKNBP(p1,n);
           }
           if ( OID(p2) != O_NBP ) {
                   if ( !POLY(p2) )
                           error("harmonic_mulnbp : invalid argument");
                   NEWNBM(m); m->d = 0; m->b = 0; m->c = (P)p2;
                   MKNODE(n,m,0); MKNBP(p2,n);
           }
           for ( r = 0, b1 = BDY(p1); b1; b1 = NEXT(b1) )
                   for ( m = BDY(b1), b2 = BDY(p2); b2; b2 = NEXT(b2) ) {
                           t = harmonic_mul_nbm(m,(NBM)BDY(b2));
                           addnbp(vl,r,t,&s); r = s;
                   }
           *rp = r;
   }
   
   #if 0
   NBP shuffle_mul_nbm(NBM a,NBM b)
   {
           int ad,bd,d,i,ai,bi,bit,s;
           int *ab,*bb,*wmb,*w;
           NBM wm,tm;
           P c,c1;
           NODE r,t,t1,p;
           NBP u;
   
           ad = a->d; bd = b->d; ab = a->b; bb = b->b;
           d = ad + bd;
           w = (int *)ALLOCA(d*sizeof(int));
           NEWNBM(wm); NEWNBMBDY(wm,d); wmb = wm->b;
           for ( i = 0; i < ad; i++ ) w[i] = 1;
           for ( ; i < d; i++ ) w[i] = 0;
           mulp(CO,a->c,b->c,&c);
           r = 0;
           do {
                   wm->d = d; wm->c = c;
                   ai = 0; bi = 0;
                   for ( i = 0; i < d; i++ ) {
                           if ( w[i] ) { bit = NBM_GET(ab,ai); ai++; }
                           else { bit = NBM_GET(bb,bi); bi++; }
                           if ( bit ) NBM_SET(wmb,i);
                           else NBM_CLR(wmb,i);
                   }
                   for ( p = 0, t = r; t; p = t, t = NEXT(t) ) {
                           tm = (NBM)BDY(t);
                           s = comp_nbm(tm,wm);
                           if ( s < 0 ) {
                                   /* insert */
                                   MKNODE(t1,wm,t);
                                   if ( !p ) r = t1;
                                   else NEXT(p) = t1;
                                   NEWNBM(wm); NEWNBMBDY(wm,d); wmb = wm->b;
                                   break;
                           } else if ( s == 0 ) {
                                   /* add coefs */
                                   addp(CO,tm->c,c,&c1);
                                   if ( c1 ) tm->c = c1;
                                   else NEXT(p) = NEXT(t);
                                   break;
                           }
                   }
                   if ( !t ) {
                           /* append */
                           MKNODE(t1,wm,t);
                           if ( !p ) r = t1;
                           else NEXT(p) = t1;
                           NEWNBM(wm); NEWNBMBDY(wm,d); wmb = wm->b;
                   }
           } while ( ni_next(w,d) );
           MKNBP(u,r);
           return u;
   }
   
   int nbmtoxky(NBM a,int *b)
   {
           int d,i,j,k;
           int *p;
   
           d = a->d; p = a->b;
           for ( i = j = 0, k = 1; i < d; i++ ) {
                   if ( !NBM_GET(p,i) ) {
                           b[j++] = k;
                           k = 1;
                   } else k++;
           }
           return j;
   }
   
   NBP harmonic_mul_nbm(NBM a,NBM b)
   {
           int da,db,d,la,lb,lmax,lmin,l,lab,la1,lb1,lab1;
           int i,j,k,ia,ib,s;
           int *wa,*wb,*w,*wab,*wa1,*wmb;
           P c,c1;
           NBM wm,tm;
           NODE r,t1,t,p;
           NBP u;
   
           da = a->d; db = b->d; d = da+db;
           wa = (int *)ALLOCA(da*sizeof(int));
           wb = (int *)ALLOCA(db*sizeof(int));
           la = nbmtoxky(a,wa);
           lb = nbmtoxky(b,wb);
           mulp(CO,a->c,b->c,&c);
           /* wa[0],..,wa[la-1] <-> x^wa[0]y x^wa[1]y .. */
           /* lmax : total length */
           lmax = la+lb;
           lmin = la>lb?la:lb;
           w = (int *)ALLOCA(lmax*sizeof(int));
           /* position of a+b */
           wab = (int *)ALLOCA(lmax*sizeof(int));
           /* position of a */
           wa1 = (int *)ALLOCA(lmax*sizeof(int));
           NEWNBM(wm); NEWNBMBDY(wm,d); wmb = wm->b;
           for ( l = lmin, r = 0; l <= lmax; l++ ) {
                   lab = lmax - l;
                   la1 = la - lab;
                   lb1 = lb - lab;
                   lab1 = l-lab;
                   /* partion l into three parts: a, b, a+b */
                   /* initialize wab */
                   for ( i = 0; i < lab; i++ ) wab[i] = 1;
                   for ( ; i < l; i++ ) wab[i] = 0;
                   do {
                           /* initialize wa1 */
                           for ( i = 0; i < la1; i++ ) wa1[i] = 1;
                           for ( ; i < lab1; i++ ) wa1[i] = 0;
                           do {
                                   ia = 0; ib = 0;
                                   for ( i = j = 0; i < l; i++ )
                                           if ( wab[i] ) w[i] = wa[ia++]+wb[ib++];
                                           else if ( wa1[j++] ) w[i] = wa[ia++];
                                           else w[i] = wb[ib++];
                                   for ( i = j = 0; i < l; i++ ) {
                                           for ( k = w[i]-1; k > 0; k--, j++ ) NBM_SET(wmb,j);
                                           NBM_CLR(wmb,j); j++;
                                   }
                                   wm->d = j; wm->c = c;
                                   for ( p = 0, t = r; t; p = t, t = NEXT(t) ) {
                                           tm = (NBM)BDY(t);
                                           s = comp_nbm(tm,wm);
                                           if ( s < 0 ) {
                                                   /* insert */
                                                   MKNODE(t1,wm,t);
                                                   if ( !p ) r = t1;
                                                   else NEXT(p) = t1;
                                                   NEWNBM(wm); NEWNBMBDY(wm,d); wmb = wm->b;
                                                   break;
                                           } else if ( s == 0 ) {
                                                   /* add coefs */
                                                   addp(CO,tm->c,c,&c1);
                                                   if ( c1 ) tm->c = c1;
                                                   else NEXT(p) = NEXT(t);
                                                   break;
                                           }
                                   }
                                   if ( !t ) {
                                           /* append */
                                           MKNODE(t1,wm,t);
                                           if ( !p ) r = t1;
                                           else NEXT(p) = t1;
                                           NEWNBM(wm); NEWNBMBDY(wm,d); wmb = wm->b;
                                   }
                           } while ( ni_next(wa1,lab1) );
                   } while ( ni_next(wab,l) );
           }
           MKNBP(u,r);
           return u;
   }
   #endif

Legend:
Removed from v.1.25  
changed lines
  Added in v.1.41

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>