| version 1.6, 2018/09/28 08:20:28 | 
version 1.11, 2018/10/23 04:53:37 | 
 | 
 | 
|  /* $OpenXM: OpenXM_contrib2/asir2018/engine/nd.c,v 1.5 2018/09/27 02:39:37 noro Exp $ */ | 
 /* $OpenXM: OpenXM_contrib2/asir2018/engine/nd.c,v 1.10 2018/10/19 23:27:38 noro Exp $ */ | 
|   | 
  | 
|  #include "nd.h" | 
 #include "nd.h" | 
|   | 
  | 
|   | 
 int Nnd_add,Nf4_red; | 
|  struct oEGT eg_search; | 
 struct oEGT eg_search; | 
|   | 
  | 
|  int diag_period = 6; | 
 int diag_period = 6; | 
| Line 1125  int ndl_check_bound2(int index,UINT *d2) | 
 
  | 
| Line 1126  int ndl_check_bound2(int index,UINT *d2) | 
 
 
 | 
|  INLINE int ndl_hash_value(UINT *d) | 
 INLINE int ndl_hash_value(UINT *d) | 
|  { | 
 { | 
|      int i; | 
     int i; | 
|      int r; | 
     UINT r; | 
|   | 
  | 
|      r = 0; | 
     r = 0; | 
|      for ( i = 0; i < nd_wpd; i++ ) | 
     for ( i = 0; i < nd_wpd; i++ ) | 
|          r = ((r<<16)+d[i])%REDTAB_LEN; | 
         r = (r*10007+d[i]); | 
|   | 
     r %= REDTAB_LEN; | 
|      return r; | 
     return r; | 
|  } | 
 } | 
|   | 
  | 
| Line 1216  ND nd_add(int mod,ND p1,ND p2) | 
 
  | 
| Line 1218  ND nd_add(int mod,ND p1,ND p2) | 
 
 
 | 
|      ND r; | 
     ND r; | 
|      NM m1,m2,mr0,mr,s; | 
     NM m1,m2,mr0,mr,s; | 
|   | 
  | 
|   | 
     Nnd_add++; | 
|      if ( !p1 ) return p2; | 
     if ( !p1 ) return p2; | 
|      else if ( !p2 ) return p1; | 
     else if ( !p2 ) return p1; | 
|      else if ( mod == -1 ) return nd_add_sf(p1,p2); | 
     else if ( mod == -1 ) return nd_add_sf(p1,p2); | 
| Line 2081  NODE nd_gb(int m,int ishomo,int checkonly,int gensyz,i | 
 
  | 
| Line 2084  NODE nd_gb(int m,int ishomo,int checkonly,int gensyz,i | 
 
 
 | 
|    P cont; | 
   P cont; | 
|    LIST list; | 
   LIST list; | 
|   | 
  | 
|   | 
   Nnd_add = 0; | 
|    g = 0; d = 0; | 
   g = 0; d = 0; | 
|    for ( i = 0; i < nd_psn; i++ ) { | 
   for ( i = 0; i < nd_psn; i++ ) { | 
|      d = update_pairs(d,g,i,gensyz); | 
     d = update_pairs(d,g,i,gensyz); | 
 | 
 | 
|     } | 
    } | 
|   } | 
  } | 
|   conv_ilist(nd_demand,0,g,indp); | 
  conv_ilist(nd_demand,0,g,indp); | 
|      if ( !checkonly && DP_Print ) { printf("nd_gb done.\n"); fflush(stdout); } | 
     if ( !checkonly && DP_Print ) { printf("nd_gb done. Number of nd_add=%d\n",Nnd_add); fflush(stdout); } | 
|      return g; | 
     return g; | 
|  } | 
 } | 
|   | 
  | 
| Line 5796  int nd_to_vect(int mod,UINT *s0,int n,ND d,UINT *r) | 
 
  | 
| Line 5800  int nd_to_vect(int mod,UINT *s0,int n,ND d,UINT *r) | 
 
 
 | 
|      return i; | 
     return i; | 
|  } | 
 } | 
|   | 
  | 
|  #if defined(__GNUC__) && SIZEOF_LONG==8 | 
  | 
|   | 
  | 
|  #define MOD128(a,c,m) ((a)=(((c)!=0||((a)>=(m)))?(((((U128)(c))<<64)+(a))%(m)):(a))) | 
  | 
|   | 
  | 
|  int nd_to_vect64(int mod,UINT *s0,int n,ND d,U64 *r) | 
  | 
|  { | 
  | 
|      NM m; | 
  | 
|      UINT *t,*s; | 
  | 
|      int i; | 
  | 
|   | 
  | 
|      for ( i = 0; i < n; i++ ) r[i] = 0; | 
  | 
|      for ( i = 0, s = s0, m = BDY(d); m; m = NEXT(m) ) { | 
  | 
|          t = DL(m); | 
  | 
|          for ( ; !ndl_equal(t,s); s += nd_wpd, i++ ); | 
  | 
|          r[i] = (U64)CM(m); | 
  | 
|      } | 
  | 
|      for ( i = 0; !r[i]; i++ ); | 
  | 
|      return i; | 
  | 
|  } | 
  | 
|  #endif | 
  | 
|   | 
  | 
|  int nd_to_vect_q(UINT *s0,int n,ND d,Z *r) | 
 int nd_to_vect_q(UINT *s0,int n,ND d,Z *r) | 
|  { | 
 { | 
|      NM m; | 
     NM m; | 
| Line 5910  Z *nm_ind_pair_to_vect(int mod,UINT *s0,int n,NM_ind_p | 
 
  | 
| Line 5893  Z *nm_ind_pair_to_vect(int mod,UINT *s0,int n,NM_ind_p | 
 
 
 | 
|      return r; | 
     return r; | 
|  } | 
 } | 
|   | 
  | 
|  IndArray nm_ind_pair_to_vect_compress(int trace,UINT *s0,int n,int *s0hash,NM_ind_pair pair) | 
 IndArray nm_ind_pair_to_vect_compress(int trace,UINT *s0,int n,NM_ind_pair pair,int start) | 
|  { | 
 { | 
|      NM m; | 
     NM m; | 
|      NMV mr; | 
     NMV mr; | 
|      UINT *d,*t,*s; | 
     UINT *d,*t,*s,*u; | 
|      NDV p; | 
     NDV p; | 
|      unsigned char *ivc; | 
     unsigned char *ivc; | 
|      unsigned short *ivs; | 
     unsigned short *ivs; | 
|      UINT *v,*ivi,*s0v; | 
     UINT *v,*ivi,*s0v; | 
|      int i,j,len,prev,diff,cdiff,h; | 
     int i,j,len,prev,diff,cdiff,h,st,ed,md,c; | 
|      IndArray r; | 
     IndArray r; | 
|  struct oEGT eg0,eg1; | 
  | 
|   | 
  | 
|      m = pair->mul; | 
     m = pair->mul; | 
|      d = DL(m); | 
     d = DL(m); | 
| Line 5933  struct oEGT eg0,eg1; | 
 
  | 
| Line 5915  struct oEGT eg0,eg1; | 
 
 
 | 
|      len = LEN(p); | 
     len = LEN(p); | 
|      t = (UINT *)MALLOC(nd_wpd*sizeof(UINT)); | 
     t = (UINT *)MALLOC(nd_wpd*sizeof(UINT)); | 
|      v = (unsigned int *)MALLOC(len*sizeof(unsigned int)); | 
     v = (unsigned int *)MALLOC(len*sizeof(unsigned int)); | 
|  get_eg(&eg0); | 
     for ( prev = start, mr = BDY(p), j = 0; j < len; j++, NMV_ADV(mr) ) { | 
|      for ( i = j = 0, s = s0, mr = BDY(p); j < len; j++, NMV_ADV(mr) ) { | 
       ndl_add(d,DL(mr),t); | 
|          ndl_add(d,DL(mr),t); | 
       st = prev; | 
|      h = ndl_hash_value(t); | 
       ed = n; | 
|          for ( ; h != s0hash[i] || !ndl_equal(t,s); s += nd_wpd, i++ ); | 
       while ( ed > st ) { | 
|          v[j] = i; | 
         md = (st+ed)/2; | 
|   | 
         u = s0+md*nd_wpd; | 
|   | 
         c = DL_COMPARE(u,t); | 
|   | 
         if ( c == 0 ) break; | 
|   | 
         else if ( c > 0 ) st = md; | 
|   | 
         else ed = md; | 
|   | 
       } | 
|   | 
       prev = v[j] = md; | 
|      } | 
     } | 
|  get_eg(&eg1); add_eg(&eg_search,&eg0,&eg1); | 
  | 
|      r = (IndArray)MALLOC(sizeof(struct oIndArray)); | 
     r = (IndArray)MALLOC(sizeof(struct oIndArray)); | 
|      r->head = v[0]; | 
     r->head = v[0]; | 
|      diff = 0; | 
     diff = 0; | 
| Line 5983  void expand_array(Z *svect,Z *cvect,int n) | 
 
  | 
| Line 5971  void expand_array(Z *svect,Z *cvect,int n) | 
 
 
 | 
|          if ( svect[i] ) svect[i] = cvect[j++]; | 
         if ( svect[i] ) svect[i] = cvect[j++]; | 
|  } | 
 } | 
|   | 
  | 
|  #if 1 | 
 #if 0 | 
|  int ndv_reduce_vect_q(Z *svect,int trace,int col,IndArray *imat,NM_ind_pair *rp0,int nred) | 
 int ndv_reduce_vect_q(Z *svect,int trace,int col,IndArray *imat,NM_ind_pair *rp0,int nred) | 
|  { | 
 { | 
|      int i,j,k,len,pos,prev,nz; | 
     int i,j,k,len,pos,prev,nz; | 
| Line 6063  int ndv_reduce_vect_q(Z *svect,int trace,int col,IndAr | 
 
  | 
| Line 6051  int ndv_reduce_vect_q(Z *svect,int trace,int col,IndAr | 
 
 
 | 
|      return maxrs; | 
     return maxrs; | 
|  } | 
 } | 
|  #else | 
 #else | 
|   | 
  | 
|  /* direct mpz version */ | 
 /* direct mpz version */ | 
|  int ndv_reduce_vect_q(Z *svect0,int trace,int col,IndArray *imat,NM_ind_pair *rp0,int nred) | 
 int ndv_reduce_vect_q(Z *svect0,int trace,int col,IndArray *imat,NM_ind_pair *rp0,int nred) | 
|  { | 
 { | 
| Line 6105  int ndv_reduce_vect_q(Z *svect0,int trace,int col,IndA | 
 
  | 
| Line 6094  int ndv_reduce_vect_q(Z *svect0,int trace,int col,IndA | 
 
 
 | 
|              mpz_div(cs,svect[k],gcd); | 
             mpz_div(cs,svect[k],gcd); | 
|              mpz_div(cr,BDY(CZ(mr)),gcd); | 
             mpz_div(cr,BDY(CZ(mr)),gcd); | 
|              mpz_neg(cs,cs); | 
             mpz_neg(cs,cs); | 
|              for ( j = 0; j < col; j++ ) | 
             if ( MUNIMPZ(cr) ) | 
|                mpz_mul(svect[j],svect[j],cr); | 
               for ( j = 0; j < col; j++ ) mpz_neg(svect[j],svect[j]); | 
|   | 
             else if ( !UNIMPZ(cr) ) | 
|   | 
               for ( j = 0; j < col; j++ ) { | 
|   | 
                 if ( mpz_sgn(svect[j]) ) mpz_mul(svect[j],svect[j],cr); | 
|   | 
               } | 
|              mpz_set_ui(svect[k],0); | 
             mpz_set_ui(svect[k],0); | 
|              prev = k; | 
             prev = k; | 
|              switch ( ivect->width ) { | 
             switch ( ivect->width ) { | 
| Line 6220  int ndv_reduce_vect(int m,UINT *svect,int col,IndArray | 
 
  | 
| Line 6213  int ndv_reduce_vect(int m,UINT *svect,int col,IndArray | 
 
 
 | 
|      return maxrs; | 
     return maxrs; | 
|  } | 
 } | 
|   | 
  | 
|  #if defined(__GNUC__) && SIZEOF_LONG==8 | 
  | 
|   | 
  | 
|  int ndv_reduce_vect64(int m,U64 *svect,U64 *cvect,int col,IndArray *imat,NM_ind_pair *rp0,int nred) | 
  | 
|  { | 
  | 
|      int i,j,k,len,pos,prev; | 
  | 
|      U64 a,c,c1,c2; | 
  | 
|      IndArray ivect; | 
  | 
|      unsigned char *ivc; | 
  | 
|      unsigned short *ivs; | 
  | 
|      unsigned int *ivi; | 
  | 
|      NDV redv; | 
  | 
|      NMV mr; | 
  | 
|      NODE rp; | 
  | 
|      int maxrs; | 
  | 
|   | 
  | 
|      for ( i = 0; i < col; i++ ) cvect[i] = 0; | 
  | 
|      maxrs = 0; | 
  | 
|      for ( i = 0; i < nred; i++ ) { | 
  | 
|          ivect = imat[i]; | 
  | 
|          k = ivect->head; | 
  | 
|          a = svect[k]; c = cvect[k]; | 
  | 
|          MOD128(a,c,m); | 
  | 
|          svect[k] = a; cvect[k] = 0; | 
  | 
|          if ( (c = svect[k]) != 0 ) { | 
  | 
|              maxrs = MAX(maxrs,rp0[i]->sugar); | 
  | 
|              c = m-c; redv = nd_ps[rp0[i]->index]; | 
  | 
|              len = LEN(redv); mr = BDY(redv); | 
  | 
|              svect[k] = 0; prev = k; | 
  | 
|              switch ( ivect->width ) { | 
  | 
|                  case 1: | 
  | 
|                      ivc = ivect->index.c; | 
  | 
|                      for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) { | 
  | 
|                          pos = prev+ivc[j]; c1 = CM(mr); prev = pos; | 
  | 
|                          if ( c1 ) { | 
  | 
|                            c2 = svect[pos]+c1*c; | 
  | 
|                            if ( c2 < svect[pos] ) cvect[pos]++; | 
  | 
|                            svect[pos] = c2; | 
  | 
|                          } | 
  | 
|                      } | 
  | 
|                      break; | 
  | 
|                  case 2: | 
  | 
|                      ivs = ivect->index.s; | 
  | 
|                      for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) { | 
  | 
|                          pos = prev+ivs[j]; c1 = CM(mr); prev = pos; | 
  | 
|                          if ( c1 ) { | 
  | 
|                            c2 = svect[pos]+c1*c; | 
  | 
|                            if ( c2 < svect[pos] ) cvect[pos]++; | 
  | 
|                            svect[pos] = c2; | 
  | 
|                          } | 
  | 
|                      } | 
  | 
|                      break; | 
  | 
|                  case 4: | 
  | 
|                      ivi = ivect->index.i; | 
  | 
|                      for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) { | 
  | 
|                          pos = prev+ivi[j]; c1 = CM(mr); prev = pos; | 
  | 
|                          if ( c1 ) { | 
  | 
|                            c2 = svect[pos]+c1*c; | 
  | 
|                            if ( c2 < svect[pos] ) cvect[pos]++; | 
  | 
|                            svect[pos] = c2; | 
  | 
|                          } | 
  | 
|                      } | 
  | 
|                      break; | 
  | 
|              } | 
  | 
|          } | 
  | 
|      } | 
  | 
|      for ( i = 0; i < col; i++ ) { | 
  | 
|        a = svect[i]; c = cvect[i]; MOD128(a,c,m); svect[i] = a; | 
  | 
|      } | 
  | 
|      return maxrs; | 
  | 
|  } | 
  | 
|  #endif | 
  | 
|   | 
  | 
|  int ndv_reduce_vect_sf(int m,UINT *svect,int col,IndArray *imat,NM_ind_pair *rp0,int nred) | 
 int ndv_reduce_vect_sf(int m,UINT *svect,int col,IndArray *imat,NM_ind_pair *rp0,int nred) | 
|  { | 
 { | 
|      int i,j,k,len,pos,prev; | 
     int i,j,k,len,pos,prev; | 
| Line 6549  NDV vect_to_ndv(UINT *vect,int spcol,int col,int *rhea | 
 
  | 
| Line 6470  NDV vect_to_ndv(UINT *vect,int spcol,int col,int *rhea | 
 
 
 | 
|      } | 
     } | 
|  } | 
 } | 
|   | 
  | 
|  #if defined(__GNUC__) && SIZEOF_LONG==8 | 
  | 
|  NDV vect64_to_ndv(U64 *vect,int spcol,int col,int *rhead,UINT *s0vect) | 
  | 
|  { | 
  | 
|      int j,k,len; | 
  | 
|      UINT *p; | 
  | 
|      UINT c; | 
  | 
|      NDV r; | 
  | 
|      NMV mr0,mr; | 
  | 
|   | 
  | 
|      for ( j = 0, len = 0; j < spcol; j++ ) if ( vect[j] ) len++; | 
  | 
|      if ( !len ) return 0; | 
  | 
|      else { | 
  | 
|          mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len); | 
  | 
|  #if 0 | 
  | 
|          ndv_alloc += nmv_adv*len; | 
  | 
|  #endif | 
  | 
|          mr = mr0; | 
  | 
|          p = s0vect; | 
  | 
|          for ( j = k = 0; j < col; j++, p += nd_wpd ) | 
  | 
|              if ( !rhead[j] ) { | 
  | 
|                  if ( (c = (UINT)vect[k++]) != 0 ) { | 
  | 
|                      ndl_copy(p,DL(mr)); CM(mr) = c; NMV_ADV(mr); | 
  | 
|                  } | 
  | 
|              } | 
  | 
|          MKNDV(nd_nvar,mr0,len,r); | 
  | 
|          return r; | 
  | 
|      } | 
  | 
|  } | 
  | 
|  #endif | 
  | 
|   | 
  | 
|  NDV vect_to_ndv_2(unsigned long *vect,int col,UINT *s0vect) | 
 NDV vect_to_ndv_2(unsigned long *vect,int col,UINT *s0vect) | 
|  { | 
 { | 
|      int j,k,len; | 
     int j,k,len; | 
| Line 6791  NODE nd_f4(int m,int checkonly,int **indp) | 
 
  | 
| Line 6682  NODE nd_f4(int m,int checkonly,int **indp) | 
 
 
 | 
|  #if 0 | 
 #if 0 | 
|      ndv_alloc = 0; | 
     ndv_alloc = 0; | 
|  #endif | 
 #endif | 
|   | 
     Nf4_red=0; | 
|      g = 0; d = 0; | 
     g = 0; d = 0; | 
|      for ( i = 0; i < nd_psn; i++ ) { | 
     for ( i = 0; i < nd_psn; i++ ) { | 
|          d = update_pairs(d,g,i,0); | 
         d = update_pairs(d,g,i,0); | 
| Line 6881  NODE nd_f4(int m,int checkonly,int **indp) | 
 
  | 
| Line 6773  NODE nd_f4(int m,int checkonly,int **indp) | 
 
 
 | 
|  #if 0 | 
 #if 0 | 
|      fprintf(asir_out,"ndv_alloc=%d\n",ndv_alloc); | 
     fprintf(asir_out,"ndv_alloc=%d\n",ndv_alloc); | 
|  #endif | 
 #endif | 
|   | 
   if ( DP_Print ) | 
|   | 
     fprintf(asir_out,"number of red=%d\n",Nf4_red); | 
|    conv_ilist(nd_demand,0,g,indp); | 
   conv_ilist(nd_demand,0,g,indp); | 
|      return g; | 
     return g; | 
|  } | 
 } | 
| Line 7104  NODE nd_f4_red_2(ND_pairs sp0,UINT *s0vect,int col,NOD | 
 
  | 
| Line 6998  NODE nd_f4_red_2(ND_pairs sp0,UINT *s0vect,int col,NOD | 
 
 
 | 
|      unsigned long *v; | 
     unsigned long *v; | 
|   | 
  | 
|      get_eg(&eg0); | 
     get_eg(&eg0); | 
|  init_eg(&eg_search); | 
  | 
|      for ( sp = sp0, nsp = 0; sp; sp = NEXT(sp), nsp++ ); | 
     for ( sp = sp0, nsp = 0; sp; sp = NEXT(sp), nsp++ ); | 
|      nred = length(rp0); | 
     nred = length(rp0); | 
|      mat = alloc_matrix(nsp,col); | 
     mat = alloc_matrix(nsp,col); | 
| Line 7159  init_eg(&eg_search); | 
 
  | 
| Line 7052  init_eg(&eg_search); | 
 
 
 | 
|  NODE nd_f4_red(int m,ND_pairs sp0,int trace,UINT *s0vect,int col,NODE rp0,ND_pairs *nz) | 
 NODE nd_f4_red(int m,ND_pairs sp0,int trace,UINT *s0vect,int col,NODE rp0,ND_pairs *nz) | 
|  { | 
 { | 
|      IndArray *imat; | 
     IndArray *imat; | 
|      int nsp,nred,i; | 
     int nsp,nred,i,start; | 
|      int *rhead; | 
     int *rhead; | 
|      NODE r0,rp; | 
     NODE r0,rp; | 
|      ND_pairs sp; | 
     ND_pairs sp; | 
|      NM_ind_pair *rvect; | 
     NM_ind_pair *rvect; | 
|      UINT *s; | 
     UINT *s; | 
|      int *s0hash; | 
     int *s0hash; | 
|   | 
     struct oEGT eg0,eg1,eg_conv; | 
|   | 
  | 
|      if ( m == 2 && nd_rref2 ) | 
     if ( m == 2 && nd_rref2 ) | 
|       return nd_f4_red_2(sp0,s0vect,col,rp0,nz); | 
      return nd_f4_red_2(sp0,s0vect,col,rp0,nz); | 
|   | 
  | 
|  init_eg(&eg_search); | 
  | 
|      for ( sp = sp0, nsp = 0; sp; sp = NEXT(sp), nsp++ ); | 
     for ( sp = sp0, nsp = 0; sp; sp = NEXT(sp), nsp++ ); | 
|      nred = length(rp0); | 
     nred = length(rp0); | 
|      imat = (IndArray *)MALLOC(nred*sizeof(IndArray)); | 
     imat = (IndArray *)MALLOC(nred*sizeof(IndArray)); | 
| Line 7178  init_eg(&eg_search); | 
 
  | 
| Line 7071  init_eg(&eg_search); | 
 
 
 | 
|      for ( i = 0; i < col; i++ ) rhead[i] = 0; | 
     for ( i = 0; i < col; i++ ) rhead[i] = 0; | 
|   | 
  | 
|      /* construction of index arrays */ | 
     /* construction of index arrays */ | 
|   | 
     get_eg(&eg0); | 
|      if ( DP_Print ) { | 
     if ( DP_Print ) { | 
|      fprintf(asir_out,"%dx%d,",nsp+nred,col); | 
       fprintf(asir_out,"%dx%d,",nsp+nred,col); | 
|   | 
       fflush(asir_out); | 
|      } | 
     } | 
|      rvect = (NM_ind_pair *)MALLOC(nred*sizeof(NM_ind_pair)); | 
     rvect = (NM_ind_pair *)MALLOC(nred*sizeof(NM_ind_pair)); | 
|      s0hash = (int *)MALLOC(col*sizeof(int)); | 
     for ( start = 0, rp = rp0, i = 0; rp; i++, rp = NEXT(rp) ) { | 
|      for ( i = 0, s = s0vect; i < col; i++, s += nd_wpd ) | 
  | 
|          s0hash[i] = ndl_hash_value(s); | 
  | 
|      for ( rp = rp0, i = 0; rp; i++, rp = NEXT(rp) ) { | 
  | 
|          rvect[i] = (NM_ind_pair)BDY(rp); | 
         rvect[i] = (NM_ind_pair)BDY(rp); | 
|          imat[i] = nm_ind_pair_to_vect_compress(trace,s0vect,col,s0hash,rvect[i]); | 
         imat[i] = nm_ind_pair_to_vect_compress(trace,s0vect,col,rvect[i],start); | 
|          rhead[imat[i]->head] = 1; | 
         rhead[imat[i]->head] = 1; | 
|   | 
         start = imat[i]->head; | 
|      } | 
     } | 
|   | 
     get_eg(&eg1); init_eg(&eg_conv); add_eg(&eg_conv,&eg0,&eg1); | 
|   | 
     if ( DP_Print ) { | 
|   | 
       fprintf(asir_out,"conv=%.3fsec,",eg_conv.exectime); | 
|   | 
       fflush(asir_out); | 
|   | 
     } | 
|      if ( m > 0 ) | 
     if ( m > 0 ) | 
|  #if defined(__GNUC__) && SIZEOF_LONG==8 | 
 #if SIZEOF_LONG==8 | 
|          r0 = nd_f4_red_mod64_main(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,nz); | 
         r0 = nd_f4_red_mod64_main(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,nz); | 
|  #else | 
 #else | 
|          r0 = nd_f4_red_main(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,nz); | 
         r0 = nd_f4_red_main(m,sp0,nsp,s0vect,col,rvect,rhead,imat,nred,nz); | 
| Line 7202  init_eg(&eg_search); | 
 
  | 
| Line 7100  init_eg(&eg_search); | 
 
 
 | 
|          r0 = nd_f4_red_lf_main(m,sp0,nsp,trace,s0vect,col,rvect,rhead,imat,nred); | 
         r0 = nd_f4_red_lf_main(m,sp0,nsp,trace,s0vect,col,rvect,rhead,imat,nred); | 
|      else | 
     else | 
|          r0 = nd_f4_red_q_main(sp0,nsp,trace,s0vect,col,rvect,rhead,imat,nred); | 
         r0 = nd_f4_red_q_main(sp0,nsp,trace,s0vect,col,rvect,rhead,imat,nred); | 
|  #if 0 | 
  | 
|      if ( DP_Print ) print_eg("search",&eg_search); | 
  | 
|  #endif | 
  | 
|      return r0; | 
     return r0; | 
|  } | 
 } | 
|   | 
  | 
| Line 7296  NODE nd_f4_red_main(int m,ND_pairs sp0,int nsp,UINT *s | 
 
  | 
| Line 7191  NODE nd_f4_red_main(int m,ND_pairs sp0,int nsp,UINT *s | 
 
 
 | 
|      return r0; | 
     return r0; | 
|  } | 
 } | 
|   | 
  | 
|  #if defined(__GNUC__) && SIZEOF_LONG==8 | 
  | 
|  /* for Fp, 2^15=<p<2^29 */ | 
  | 
|   | 
  | 
|  NODE nd_f4_red_mod64_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col, | 
  | 
|          NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz) | 
  | 
|  { | 
  | 
|      int spcol,sprow,a; | 
  | 
|      int i,j,k,l,rank; | 
  | 
|      NODE r0,r; | 
  | 
|      ND_pairs sp; | 
  | 
|      ND spol; | 
  | 
|      U64 **spmat; | 
  | 
|      U64 *svect,*cvect; | 
  | 
|      U64 *v; | 
  | 
|      int *colstat; | 
  | 
|      struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2; | 
  | 
|      int maxrs; | 
  | 
|      int *spsugar; | 
  | 
|      ND_pairs *spactive; | 
  | 
|   | 
  | 
|      spcol = col-nred; | 
  | 
|      get_eg(&eg0); | 
  | 
|      /* elimination (1st step) */ | 
  | 
|      spmat = (U64 **)MALLOC(nsp*sizeof(U64 *)); | 
  | 
|      svect = (U64 *)MALLOC(col*sizeof(U64)); | 
  | 
|      cvect = (U64 *)MALLOC(col*sizeof(U64)); | 
  | 
|      spsugar = (int *)MALLOC(nsp*sizeof(int)); | 
  | 
|      spactive = !nz?0:(ND_pairs *)MALLOC(nsp*sizeof(ND_pairs)); | 
  | 
|      for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) { | 
  | 
|          nd_sp(m,0,sp,&spol); | 
  | 
|          if ( !spol ) continue; | 
  | 
|          nd_to_vect64(m,s0vect,col,spol,svect); | 
  | 
|          maxrs = ndv_reduce_vect64(m,svect,cvect,col,imat,rvect,nred); | 
  | 
|          for ( i = 0; i < col; i++ ) if ( svect[i] ) break; | 
  | 
|          if ( i < col ) { | 
  | 
|              spmat[sprow] = v = (U64 *)MALLOC_ATOMIC(spcol*sizeof(U64)); | 
  | 
|              for ( j = k = 0; j < col; j++ ) | 
  | 
|                  if ( !rhead[j] ) v[k++] = (UINT)svect[j]; | 
  | 
|              spsugar[sprow] = MAX(maxrs,SG(spol)); | 
  | 
|              if ( nz ) | 
  | 
|              spactive[sprow] = sp; | 
  | 
|              sprow++; | 
  | 
|          } | 
  | 
|          nd_free(spol); | 
  | 
|      } | 
  | 
|      get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1); | 
  | 
|      if ( DP_Print ) { | 
  | 
|          fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime); | 
  | 
|          fflush(asir_out); | 
  | 
|      } | 
  | 
|      /* free index arrays */ | 
  | 
|      for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c); | 
  | 
|   | 
  | 
|      /* elimination (2nd step) */ | 
  | 
|      colstat = (int *)MALLOC(spcol*sizeof(int)); | 
  | 
|      rank = nd_gauss_elim_mod64(spmat,spsugar,spactive,sprow,spcol,m,colstat); | 
  | 
|      r0 = 0; | 
  | 
|      for ( i = 0; i < rank; i++ ) { | 
  | 
|          NEXTNODE(r0,r); BDY(r) = | 
  | 
|            (pointer)vect64_to_ndv(spmat[i],spcol,col,rhead,s0vect); | 
  | 
|          SG((NDV)BDY(r)) = spsugar[i]; | 
  | 
|          GCFREE(spmat[i]); | 
  | 
|      } | 
  | 
|      if ( r0 ) NEXT(r) = 0; | 
  | 
|   | 
  | 
|      for ( ; i < sprow; i++ ) GCFREE(spmat[i]); | 
  | 
|      get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2); | 
  | 
|      init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2); | 
  | 
|      if ( DP_Print ) { | 
  | 
|          fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime); | 
  | 
|          fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ", | 
  | 
|              nsp,nred,sprow,spcol,rank); | 
  | 
|          fprintf(asir_out,"%.3fsec,",eg_f4.exectime); | 
  | 
|      } | 
  | 
|      if ( nz ) { | 
  | 
|          for ( i = 0; i < rank-1; i++ ) NEXT(spactive[i]) = spactive[i+1]; | 
  | 
|          if ( rank > 0 ) { | 
  | 
|              NEXT(spactive[rank-1]) = 0; | 
  | 
|              *nz = spactive[0]; | 
  | 
|          } else | 
  | 
|              *nz = 0; | 
  | 
|      } | 
  | 
|      return r0; | 
  | 
|  } | 
  | 
|  #endif | 
  | 
|   | 
  | 
|  /* for small finite fields */ | 
 /* for small finite fields */ | 
|   | 
  | 
|  NODE nd_f4_red_sf_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col, | 
 NODE nd_f4_red_sf_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col, | 
| Line 7793  int nd_gauss_elim_mod(UINT **mat0,int *sugar,ND_pairs  | 
 
  | 
| Line 7603  int nd_gauss_elim_mod(UINT **mat0,int *sugar,ND_pairs  | 
 
 
 | 
|      return rank; | 
     return rank; | 
|  } | 
 } | 
|   | 
  | 
|  #if defined(__GNUC__) && SIZEOF_LONG==8 | 
  | 
|   | 
  | 
|  int nd_gauss_elim_mod64(U64 **mat,int *sugar,ND_pairs *spactive,int row,int col,int md,int *colstat) | 
  | 
|  { | 
  | 
|    int i,j,k,l,rank,s; | 
  | 
|    U64 inv; | 
  | 
|    U64 a; | 
  | 
|    UINT c; | 
  | 
|    U64 *t,*pivot,*pk; | 
  | 
|    UINT *ck; | 
  | 
|    UINT **cmat; | 
  | 
|    UINT *ct; | 
  | 
|    ND_pairs pair; | 
  | 
|   | 
  | 
|    cmat = (UINT **)MALLOC(row*sizeof(UINT *)); | 
  | 
|    for ( i = 0; i < row; i++ ) { | 
  | 
|      cmat[i] = MALLOC_ATOMIC(col*sizeof(UINT)); | 
  | 
|      bzero(cmat[i],col*sizeof(UINT)); | 
  | 
|    } | 
  | 
|   | 
  | 
|    for ( rank = 0, j = 0; j < col; j++ ) { | 
  | 
|      for ( i = rank; i < row; i++ ) { | 
  | 
|        a = mat[i][j]; c = cmat[i][j]; | 
  | 
|        MOD128(a,c,md); | 
  | 
|        mat[i][j] = a; cmat[i][j] = 0; | 
  | 
|      } | 
  | 
|      for ( i = rank; i < row; i++ ) | 
  | 
|        if ( mat[i][j] ) | 
  | 
|          break; | 
  | 
|      if ( i == row ) { | 
  | 
|        colstat[j] = 0; | 
  | 
|        continue; | 
  | 
|      } else | 
  | 
|        colstat[j] = 1; | 
  | 
|      if ( i != rank ) { | 
  | 
|        t = mat[i]; mat[i] = mat[rank]; mat[rank] = t; | 
  | 
|        ct = cmat[i]; cmat[i] = cmat[rank]; cmat[rank] = ct; | 
  | 
|        s = sugar[i]; sugar[i] = sugar[rank]; sugar[rank] = s; | 
  | 
|        if ( spactive ) { | 
  | 
|          pair = spactive[i]; spactive[i] = spactive[rank]; | 
  | 
|          spactive[rank] = pair; | 
  | 
|        } | 
  | 
|      } | 
  | 
|      /* column j is normalized */ | 
  | 
|      s = sugar[rank]; | 
  | 
|      inv = invm((UINT)mat[rank][j],md); | 
  | 
|      /* normalize pivot row */ | 
  | 
|      for ( k = j, pk = mat[rank]+j, ck = cmat[rank]+j; k < col; k++, pk++, ck++ ) { | 
  | 
|        a = *pk; c = *ck; MOD128(a,c,md); *pk = (a*inv)%md; *ck = 0; | 
  | 
|      } | 
  | 
|      for ( i = rank+1; i < row; i++ ) { | 
  | 
|        if ( (a = mat[i][j]) != 0 ) { | 
  | 
|          sugar[i] = MAX(sugar[i],s); | 
  | 
|          red_by_vect64(md,mat[i]+j,cmat[i]+j,mat[rank]+j,(int)(md-a),col-j); | 
  | 
|        } | 
  | 
|      } | 
  | 
|      rank++; | 
  | 
|    } | 
  | 
|    for ( j = col-1, l = rank-1; j >= 0; j-- ) | 
  | 
|      if ( colstat[j] ) { | 
  | 
|        for ( k = j, pk = mat[l]+j, ck = cmat[l]+j; k < col; k++, pk++, ck++ ) { | 
  | 
|          a = *pk; c = *ck; MOD128(a,c,md); *pk = a; *ck = 0; | 
  | 
|        } | 
  | 
|        s = sugar[l]; | 
  | 
|        for ( i = 0; i < l; i++ ) { | 
  | 
|          a = mat[i][j]; c = cmat[i][j]; MOD128(a,c,md); mat[i][j] = a; cmat[i][j] = 0; | 
  | 
|          if ( a ) { | 
  | 
|            sugar[i] = MAX(sugar[i],s); | 
  | 
|            red_by_vect64(md,mat[i]+j,cmat[i]+j,mat[l]+j,(int)(md-a),col-j); | 
  | 
|          } | 
  | 
|        } | 
  | 
|        l--; | 
  | 
|      } | 
  | 
|    for ( i = 0; i < row; i++ ) GCFREE(cmat[i]); | 
  | 
|    GCFREE(cmat); | 
  | 
|    return rank; | 
  | 
|  } | 
  | 
|  #endif | 
  | 
|   | 
  | 
|  int nd_gauss_elim_sf(UINT **mat0,int *sugar,int row,int col,int md,int *colstat) | 
 int nd_gauss_elim_sf(UINT **mat0,int *sugar,int row,int col,int md,int *colstat) | 
|  { | 
 { | 
|      int i,j,k,l,inv,a,rank,s; | 
     int i,j,k,l,inv,a,rank,s; | 
| Line 8482  P ndc_div(int mod,union oNDC a,union oNDC b) | 
 
  | 
| Line 8214  P ndc_div(int mod,union oNDC a,union oNDC b) | 
 
 
 | 
|      int inv,t; | 
     int inv,t; | 
|   | 
  | 
|      if ( mod == -1 ) c.m = _mulsf(a.m,_invsf(b.m)); | 
     if ( mod == -1 ) c.m = _mulsf(a.m,_invsf(b.m)); | 
|      else if ( mod == -2 ) divlf(a.gz,b.gz,&c.gz); | 
     else if ( mod == -2 ) divlf(a.z,b.z,&c.z); | 
|      else if ( mod ) { | 
     else if ( mod ) { | 
|          inv = invm(b.m,mod); | 
         inv = invm(b.m,mod); | 
|          DMAR(a.m,inv,0,mod,t); c.m = t; | 
         DMAR(a.m,inv,0,mod,t); c.m = t; | 
| Line 8502  P ndctop(int mod,union oNDC c) | 
 
  | 
| Line 8234  P ndctop(int mod,union oNDC c) | 
 
 
 | 
|      if ( mod == -1 ) { | 
     if ( mod == -1 ) { | 
|          e = IFTOF(c.m); MKGFS(e,gfs); return (P)gfs; | 
         e = IFTOF(c.m); MKGFS(e,gfs); return (P)gfs; | 
|      } else if ( mod == -2 ) { | 
     } else if ( mod == -2 ) { | 
|         q = c.gz; return (P)q; | 
        q = c.z; return (P)q; | 
|      } else if ( mod > 0 ) { | 
     } else if ( mod > 0 ) { | 
|          STOZ(c.m,q); return (P)q; | 
         STOZ(c.m,q); return (P)q; | 
|      } else | 
     } else | 
| Line 9264  NODE nd_f4_lf_trace_main(int m,int **indp) | 
 
  | 
| Line 8996  NODE nd_f4_lf_trace_main(int m,int **indp) | 
 
 
 | 
|    conv_ilist(nd_demand,1,g,indp); | 
   conv_ilist(nd_demand,1,g,indp); | 
|      return g; | 
     return g; | 
|  } | 
 } | 
|   | 
  | 
|   | 
 #if SIZEOF_LONG==8 | 
|   | 
  | 
|   | 
 NDV vect64_to_ndv(mp_limb_t *vect,int spcol,int col,int *rhead,UINT *s0vect) | 
|   | 
 { | 
|   | 
     int j,k,len; | 
|   | 
     UINT *p; | 
|   | 
     UINT c; | 
|   | 
     NDV r; | 
|   | 
     NMV mr0,mr; | 
|   | 
  | 
|   | 
     for ( j = 0, len = 0; j < spcol; j++ ) if ( vect[j] ) len++; | 
|   | 
     if ( !len ) return 0; | 
|   | 
     else { | 
|   | 
         mr0 = (NMV)MALLOC_ATOMIC_IGNORE_OFF_PAGE(nmv_adv*len); | 
|   | 
 #if 0 | 
|   | 
         ndv_alloc += nmv_adv*len; | 
|   | 
 #endif | 
|   | 
         mr = mr0; | 
|   | 
         p = s0vect; | 
|   | 
         for ( j = k = 0; j < col; j++, p += nd_wpd ) | 
|   | 
             if ( !rhead[j] ) { | 
|   | 
                 if ( (c = (UINT)vect[k++]) != 0 ) { | 
|   | 
                     ndl_copy(p,DL(mr)); CM(mr) = c; NMV_ADV(mr); | 
|   | 
                 } | 
|   | 
             } | 
|   | 
         MKNDV(nd_nvar,mr0,len,r); | 
|   | 
         return r; | 
|   | 
     } | 
|   | 
 } | 
|   | 
  | 
|   | 
 int nd_to_vect64(int mod,UINT *s0,int n,ND d,mp_limb_t *r) | 
|   | 
 { | 
|   | 
     NM m; | 
|   | 
     UINT *t,*s,*u; | 
|   | 
     int i,st,ed,md,prev,c; | 
|   | 
  | 
|   | 
     for ( i = 0; i < n; i++ ) r[i] = 0; | 
|   | 
     prev = 0; | 
|   | 
     for ( i = 0, m = BDY(d); m; m = NEXT(m) ) { | 
|   | 
       t = DL(m); | 
|   | 
       st = prev; | 
|   | 
       ed = n; | 
|   | 
       while ( ed > st ) { | 
|   | 
         md = (st+ed)/2; | 
|   | 
         u = s0+md*nd_wpd; | 
|   | 
         c = DL_COMPARE(u,t); | 
|   | 
         if ( c == 0 ) break; | 
|   | 
         else if ( c > 0 ) st = md; | 
|   | 
         else ed = md; | 
|   | 
       } | 
|   | 
       r[md] = (mp_limb_t)CM(m); | 
|   | 
       prev = md; | 
|   | 
     } | 
|   | 
     for ( i = 0; !r[i]; i++ ); | 
|   | 
     return i; | 
|   | 
 } | 
|   | 
  | 
|   | 
 #define MOD128(a,c,m) ((a)=(((c)!=0||((a)>=(m)))?(((((U128)(c))<<64)+(a))%(m)):(a))) | 
|   | 
  | 
|   | 
 int ndv_reduce_vect64(int m,mp_limb_t *svect,mp_limb_t *cvect,int col,IndArray *imat,NM_ind_pair *rp0,int nred) | 
|   | 
 { | 
|   | 
     int i,j,k,len,pos,prev; | 
|   | 
     mp_limb_t a,c,c1,c2; | 
|   | 
     IndArray ivect; | 
|   | 
     unsigned char *ivc; | 
|   | 
     unsigned short *ivs; | 
|   | 
     unsigned int *ivi; | 
|   | 
     NDV redv; | 
|   | 
     NMV mr; | 
|   | 
     NODE rp; | 
|   | 
     int maxrs; | 
|   | 
  | 
|   | 
     for ( i = 0; i < col; i++ ) cvect[i] = 0; | 
|   | 
     maxrs = 0; | 
|   | 
     for ( i = 0; i < nred; i++ ) { | 
|   | 
         ivect = imat[i]; | 
|   | 
         k = ivect->head; | 
|   | 
         a = svect[k]; c = cvect[k]; | 
|   | 
         MOD128(a,c,m); | 
|   | 
         svect[k] = a; cvect[k] = 0; | 
|   | 
         if ( (c = svect[k]) != 0 ) { | 
|   | 
             Nf4_red++; | 
|   | 
             maxrs = MAX(maxrs,rp0[i]->sugar); | 
|   | 
             c = m-c; redv = nd_ps[rp0[i]->index]; | 
|   | 
             len = LEN(redv); mr = BDY(redv); | 
|   | 
             svect[k] = 0; prev = k; | 
|   | 
             switch ( ivect->width ) { | 
|   | 
                 case 1: | 
|   | 
                     ivc = ivect->index.c; | 
|   | 
                     for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) { | 
|   | 
                         pos = prev+ivc[j]; c1 = CM(mr); prev = pos; | 
|   | 
                         if ( c1 ) { | 
|   | 
                           c2 = svect[pos]+c1*c; | 
|   | 
                           if ( c2 < svect[pos] ) cvect[pos]++; | 
|   | 
                           svect[pos] = c2; | 
|   | 
                         } | 
|   | 
                     } | 
|   | 
                     break; | 
|   | 
                 case 2: | 
|   | 
                     ivs = ivect->index.s; | 
|   | 
                     for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) { | 
|   | 
                         pos = prev+ivs[j]; c1 = CM(mr); prev = pos; | 
|   | 
                         if ( c1 ) { | 
|   | 
                           c2 = svect[pos]+c1*c; | 
|   | 
                           if ( c2 < svect[pos] ) cvect[pos]++; | 
|   | 
                           svect[pos] = c2; | 
|   | 
                         } | 
|   | 
                     } | 
|   | 
                     break; | 
|   | 
                 case 4: | 
|   | 
                     ivi = ivect->index.i; | 
|   | 
                     for ( j = 1, NMV_ADV(mr); j < len; j++, NMV_ADV(mr) ) { | 
|   | 
                         pos = prev+ivi[j]; c1 = CM(mr); prev = pos; | 
|   | 
                         if ( c1 ) { | 
|   | 
                           c2 = svect[pos]+c1*c; | 
|   | 
                           if ( c2 < svect[pos] ) cvect[pos]++; | 
|   | 
                           svect[pos] = c2; | 
|   | 
                         } | 
|   | 
                     } | 
|   | 
                     break; | 
|   | 
             } | 
|   | 
         } | 
|   | 
     } | 
|   | 
     for ( i = 0; i < col; i++ ) { | 
|   | 
       a = svect[i]; c = cvect[i]; MOD128(a,c,m); svect[i] = a; | 
|   | 
     } | 
|   | 
     return maxrs; | 
|   | 
 } | 
|   | 
  | 
|   | 
 /* for Fp, 2^15=<p<2^29 */ | 
|   | 
  | 
|   | 
 NODE nd_f4_red_mod64_main(int m,ND_pairs sp0,int nsp,UINT *s0vect,int col, | 
|   | 
         NM_ind_pair *rvect,int *rhead,IndArray *imat,int nred,ND_pairs *nz) | 
|   | 
 { | 
|   | 
     int spcol,sprow,a; | 
|   | 
     int i,j,k,l,rank; | 
|   | 
     NODE r0,r; | 
|   | 
     ND_pairs sp; | 
|   | 
     ND spol; | 
|   | 
     mp_limb_t **spmat; | 
|   | 
     mp_limb_t *svect,*cvect; | 
|   | 
     mp_limb_t *v; | 
|   | 
     int *colstat; | 
|   | 
     struct oEGT eg0,eg1,eg2,eg_f4,eg_f4_1,eg_f4_2; | 
|   | 
     int maxrs; | 
|   | 
     int *spsugar; | 
|   | 
     ND_pairs *spactive; | 
|   | 
  | 
|   | 
     spcol = col-nred; | 
|   | 
     get_eg(&eg0); | 
|   | 
     /* elimination (1st step) */ | 
|   | 
     spmat = (mp_limb_t **)MALLOC(nsp*sizeof(mp_limb_t *)); | 
|   | 
     svect = (mp_limb_t *)MALLOC(col*sizeof(mp_limb_t)); | 
|   | 
     cvect = (mp_limb_t *)MALLOC(col*sizeof(mp_limb_t)); | 
|   | 
     spsugar = (int *)MALLOC(nsp*sizeof(int)); | 
|   | 
     spactive = !nz?0:(ND_pairs *)MALLOC(nsp*sizeof(ND_pairs)); | 
|   | 
     for ( a = sprow = 0, sp = sp0; a < nsp; a++, sp = NEXT(sp) ) { | 
|   | 
         nd_sp(m,0,sp,&spol); | 
|   | 
         if ( !spol ) continue; | 
|   | 
         nd_to_vect64(m,s0vect,col,spol,svect); | 
|   | 
         maxrs = ndv_reduce_vect64(m,svect,cvect,col,imat,rvect,nred); | 
|   | 
         for ( i = 0; i < col; i++ ) if ( svect[i] ) break; | 
|   | 
         if ( i < col ) { | 
|   | 
             spmat[sprow] = v = (mp_limb_t *)MALLOC_ATOMIC(spcol*sizeof(mp_limb_t)); | 
|   | 
             for ( j = k = 0; j < col; j++ ) | 
|   | 
                 if ( !rhead[j] ) v[k++] = (UINT)svect[j]; | 
|   | 
             spsugar[sprow] = MAX(maxrs,SG(spol)); | 
|   | 
             if ( nz ) | 
|   | 
             spactive[sprow] = sp; | 
|   | 
             sprow++; | 
|   | 
         } | 
|   | 
         nd_free(spol); | 
|   | 
     } | 
|   | 
     get_eg(&eg1); init_eg(&eg_f4_1); add_eg(&eg_f4_1,&eg0,&eg1); | 
|   | 
     if ( DP_Print ) { | 
|   | 
         fprintf(asir_out,"elim1=%.3fsec,",eg_f4_1.exectime); | 
|   | 
         fflush(asir_out); | 
|   | 
     } | 
|   | 
     /* free index arrays */ | 
|   | 
     for ( i = 0; i < nred; i++ ) GCFREE(imat[i]->index.c); | 
|   | 
  | 
|   | 
     /* elimination (2nd step) */ | 
|   | 
     colstat = (int *)MALLOC(spcol*sizeof(int)); | 
|   | 
     rank = nd_gauss_elim_mod64(spmat,spsugar,spactive,sprow,spcol,m,colstat); | 
|   | 
     r0 = 0; | 
|   | 
     for ( i = 0; i < rank; i++ ) { | 
|   | 
         NEXTNODE(r0,r); BDY(r) = | 
|   | 
           (pointer)vect64_to_ndv(spmat[i],spcol,col,rhead,s0vect); | 
|   | 
         SG((NDV)BDY(r)) = spsugar[i]; | 
|   | 
         GCFREE(spmat[i]); | 
|   | 
     } | 
|   | 
     if ( r0 ) NEXT(r) = 0; | 
|   | 
  | 
|   | 
     for ( ; i < sprow; i++ ) GCFREE(spmat[i]); | 
|   | 
     get_eg(&eg2); init_eg(&eg_f4_2); add_eg(&eg_f4_2,&eg1,&eg2); | 
|   | 
     init_eg(&eg_f4); add_eg(&eg_f4,&eg0,&eg2); | 
|   | 
     if ( DP_Print ) { | 
|   | 
         fprintf(asir_out,"elim2=%.3fsec,",eg_f4_2.exectime); | 
|   | 
         fprintf(asir_out,"nsp=%d,nred=%d,spmat=(%d,%d),rank=%d ", | 
|   | 
             nsp,nred,sprow,spcol,rank); | 
|   | 
         fprintf(asir_out,"%.3fsec,",eg_f4.exectime); | 
|   | 
     } | 
|   | 
     if ( nz ) { | 
|   | 
         for ( i = 0; i < rank-1; i++ ) NEXT(spactive[i]) = spactive[i+1]; | 
|   | 
         if ( rank > 0 ) { | 
|   | 
             NEXT(spactive[rank-1]) = 0; | 
|   | 
             *nz = spactive[0]; | 
|   | 
         } else | 
|   | 
             *nz = 0; | 
|   | 
     } | 
|   | 
     return r0; | 
|   | 
 } | 
|   | 
  | 
|   | 
 int nd_gauss_elim_mod64(mp_limb_t **mat,int *sugar,ND_pairs *spactive,int row,int col,int md,int *colstat) | 
|   | 
 { | 
|   | 
   int i,j,k,l,rank,s; | 
|   | 
   mp_limb_t inv; | 
|   | 
   mp_limb_t a; | 
|   | 
   UINT c; | 
|   | 
   mp_limb_t *t,*pivot,*pk; | 
|   | 
   UINT *ck; | 
|   | 
   UINT **cmat; | 
|   | 
   UINT *ct; | 
|   | 
   ND_pairs pair; | 
|   | 
  | 
|   | 
   cmat = (UINT **)MALLOC(row*sizeof(UINT *)); | 
|   | 
   for ( i = 0; i < row; i++ ) { | 
|   | 
     cmat[i] = MALLOC_ATOMIC(col*sizeof(UINT)); | 
|   | 
     bzero(cmat[i],col*sizeof(UINT)); | 
|   | 
   } | 
|   | 
  | 
|   | 
   for ( rank = 0, j = 0; j < col; j++ ) { | 
|   | 
     for ( i = rank; i < row; i++ ) { | 
|   | 
       a = mat[i][j]; c = cmat[i][j]; | 
|   | 
       MOD128(a,c,md); | 
|   | 
       mat[i][j] = a; cmat[i][j] = 0; | 
|   | 
     } | 
|   | 
     for ( i = rank; i < row; i++ ) | 
|   | 
       if ( mat[i][j] ) | 
|   | 
         break; | 
|   | 
     if ( i == row ) { | 
|   | 
       colstat[j] = 0; | 
|   | 
       continue; | 
|   | 
     } else | 
|   | 
       colstat[j] = 1; | 
|   | 
     if ( i != rank ) { | 
|   | 
       t = mat[i]; mat[i] = mat[rank]; mat[rank] = t; | 
|   | 
       ct = cmat[i]; cmat[i] = cmat[rank]; cmat[rank] = ct; | 
|   | 
       s = sugar[i]; sugar[i] = sugar[rank]; sugar[rank] = s; | 
|   | 
       if ( spactive ) { | 
|   | 
         pair = spactive[i]; spactive[i] = spactive[rank]; | 
|   | 
         spactive[rank] = pair; | 
|   | 
       } | 
|   | 
     } | 
|   | 
     /* column j is normalized */ | 
|   | 
     s = sugar[rank]; | 
|   | 
     inv = invm((UINT)mat[rank][j],md); | 
|   | 
     /* normalize pivot row */ | 
|   | 
     for ( k = j, pk = mat[rank]+j, ck = cmat[rank]+j; k < col; k++, pk++, ck++ ) { | 
|   | 
       a = *pk; c = *ck; MOD128(a,c,md); *pk = (a*inv)%md; *ck = 0; | 
|   | 
     } | 
|   | 
     for ( i = rank+1; i < row; i++ ) { | 
|   | 
       if ( (a = mat[i][j]) != 0 ) { | 
|   | 
         sugar[i] = MAX(sugar[i],s); | 
|   | 
         red_by_vect64(md,mat[i]+j,cmat[i]+j,mat[rank]+j,(int)(md-a),col-j); | 
|   | 
         Nf4_red++; | 
|   | 
       } | 
|   | 
     } | 
|   | 
     rank++; | 
|   | 
   } | 
|   | 
   for ( j = col-1, l = rank-1; j >= 0; j-- ) | 
|   | 
     if ( colstat[j] ) { | 
|   | 
       for ( k = j, pk = mat[l]+j, ck = cmat[l]+j; k < col; k++, pk++, ck++ ) { | 
|   | 
         a = *pk; c = *ck; MOD128(a,c,md); *pk = a; *ck = 0; | 
|   | 
       } | 
|   | 
       s = sugar[l]; | 
|   | 
       for ( i = 0; i < l; i++ ) { | 
|   | 
         a = mat[i][j]; c = cmat[i][j]; MOD128(a,c,md); mat[i][j] = a; cmat[i][j] = 0; | 
|   | 
         if ( a ) { | 
|   | 
           sugar[i] = MAX(sugar[i],s); | 
|   | 
           red_by_vect64(md,mat[i]+j,cmat[i]+j,mat[l]+j,(int)(md-a),col-j); | 
|   | 
           Nf4_red++; | 
|   | 
         } | 
|   | 
       } | 
|   | 
       l--; | 
|   | 
     } | 
|   | 
   for ( i = 0; i < row; i++ ) GCFREE(cmat[i]); | 
|   | 
   GCFREE(cmat); | 
|   | 
   return rank; | 
|   | 
 } | 
|   | 
 #endif | 
|   | 
  |