Пример #1
0
void construct_lcp_PHI(cache_config& config)
{
    static_assert(t_width == 0 or t_width == 8 , "construct_lcp_PHI: width must be `0` for integer alphabet and `8` for byte alphabet");
    typedef int_vector<>::size_type size_type;
    typedef int_vector<t_width> text_type;
    const char* KEY_TEXT = key_text_trait<t_width>::KEY_TEXT;
    int_vector_buffer<> sa_buf(config.file_map[conf::KEY_SA]);
    size_type n = sa_buf.size();

    assert(n > 0);
    if (1 == n) {  // Handle special case: Input only the sentinel character.
        int_vector<> lcp(1, 0);
        store_to_cache(lcp, conf::KEY_LCP, config);
        return;
    }

//	(1) Calculate PHI (stored in array plcp)
    int_vector<> plcp(n, 0, sa_buf.width());
    for (size_type i=0, sai_1 = 0; i < n; ++i) {
        size_type sai = sa_buf[i];
        plcp[ sai ] = sai_1;
        sai_1 = sai;
    }

//  (2) Load text from disk
    text_type text;
    load_from_cache(text, KEY_TEXT, config);

//  (3) Calculate permuted LCP array (text order), called PLCP
    size_type max_l = 0;
    for (size_type i=0, l=0; i < n-1; ++i) {
        size_type phii = plcp[i];
        while (text[i+l] == text[phii+l]) {
            ++l;
        }
        plcp[i] = l;
        if (l) {
            max_l = std::max(max_l, l);
            --l;
        }
    }
    util::clear(text);
    uint8_t lcp_width = bits::hi(max_l)+1;

//	(4) Transform PLCP into LCP
    std::string lcp_file = cache_file_name(conf::KEY_LCP, config);
    size_type buffer_size = 1000000; // buffer_size is a multiple of 8!
    int_vector_buffer<> lcp_buf(lcp_file, std::ios::out, buffer_size, lcp_width);   // open buffer for lcp
    lcp_buf[0] = 0;
    sa_buf.buffersize(buffer_size);
    for (size_type i=1; i < n; ++i) {
        size_type sai = sa_buf[i];
        lcp_buf[i] = plcp[sai];
    }
    lcp_buf.close();
    register_cache_file(conf::KEY_LCP, config);
}
Пример #2
0
  void LCPSelfTest() {
    Matrix A(3,3);
    Vector b(3);
    {
      A(0,0) = 0; A(0,1) = 0; A(0,2) = 1;
      A(1,0) = 0; A(1,1) = 0; A(1,2) = 1;
      A(2,0) = -1; A(2,1) = -1; A(2,2) = 0;
      b(0) = -2;
      b(1) = -1;
      b(2) = 3;
      LemkeLCP lcp(A,b);
      lcp.verbose = 3;
      if(!lcp.Solve()) {
	cerr<<"LCP didn't solve!"<<endl;
	Abort();
      }
      Vector w,z;
      lcp.GetW(w);
      lcp.GetZ(z);
      cout<<"W: "<<VectorPrinter(w)<<endl;
      cout<<"Z: "<<VectorPrinter(z)<<endl;
    }
    {
      A(0,0) = -1; A(0,1) = -1; A(0,2) = 0;
      A(1,0) = 0; A(1,1) = 0; A(1,2) = 1;
      A(2,0) = 0; A(2,1) = 0; A(2,2) = 1;
      b(0) = 2;
      b(1) = -1;
      b(2) = -1;
      LemkeLCP lcp(A,b);
      lcp.verbose = 3;
      if(!lcp.Solve()) {
	cerr<<"LCP didn't solve!"<<endl;
	Abort();
      }
      Vector w,z;
      lcp.GetW(w);
      lcp.GetZ(z);
      cout<<"W: "<<VectorPrinter(w)<<endl;
      cout<<"Z: "<<VectorPrinter(z)<<endl;
    }
  }
Пример #3
0
/*
printa(int a[],int n) {
    for(int i=0;i<=n;i++) printf("%d ",a[i]);
    printf("\n");
}
*/
int main() {
    while(scanf("%s",str)==1) {
        int len=strlen(str);
        int n=2*len+1;
        for(int i=0;i<len;i++) r[i]=str[i];
        for(int i=0;i<len;i++) r[len+i+1]=str[len-1-i];
        r[n]=0;
        r[len]=1;
        da(r,sa,rank,height,n,128);
        for(int i=1;i<=n;i++) RMQ[i]=height[i];
        initRMQ(n);
        int ans=0,st,tmp;
        for(int i=0;i<len;i++) {
             tmp=lcp(i,n-i);
             if(2*tmp>ans) {
                 ans=2*tmp;
                 st=i-tmp;
             }
             tmp=lcp(i,n-i-1);
                 if(2*tmp-1>ans) {
                     ans=2*tmp-1;
                     st=i-tmp+1;
                 }
            //printf("%d %d %d\n",ans,tmp,st);
        }
        str[st+ans]=0;
        printf("%s\n",str+st);
        /*
        printa(sa,len);
        printa(rank,len);
        printa(height,len);
        for(int i=0;i<len-1;i++) {
            for(int j=i+1;j<len;j++) {
                printf("%d-%d:lcp=%d\n",i,j,lcp(i,j));
            }
        }
        */
    }
    return 0;
}
Пример #4
0
 string longestCommonPrefix(vector<string>& strs) {
     string r;
     int n = strs.size();
     if(n==0) return r;
     r = strs[0];
     for(int i=1; i<n; i++)
     {
         r = lcp(r, strs[i]);
         if(r.size() == 0)
             break;
     }
     return r;
 }
Пример #5
0
SfaType GSA::getRightBoundOnGSA(const SfaChar* pat, int len, SfaType l, SfaType r) 
{
    if ( l > r ) return r;

    if ( verbose ) std::cout << "Right bound:\n";
	int lLcp = lcp((SfaChar*)getSeq(0), pat);
	int rLcp = lcp((SfaChar*)getSeq(size-1), pat);
    if ( verbose ) printf("lLcp:%d\trLcp:%d\n", lLcp, rLcp);

	if (lLcp <  len && pat[lLcp] <= getSeq(0)[lLcp]) return 0;
	if (rLcp >= len || pat[rLcp] >= getSeq(size-1)[rLcp]) return size;

	// SfaType left = 1;
	// SfaType right = size;
	size_t left = l;
	size_t right = r;
	while (right-left > 1)
	{
		//size_t mid = left + floor((right-left)/2.0);
        size_t mid = (right+left)/2.0;
		int mLcp = lLcp <= rLcp? lLcp : rLcp;
		mLcp += lcp((SfaChar*)getSeq(mid-1)+mLcp, pat+mLcp);
        if ( verbose ) 
            printf("left:%zu right:%zu mid:%zu lLcp:%d rLcp:%d\n", left, right, mid, lLcp, rLcp);
		if (mLcp >= len || pat[mLcp] >= getSeq(mid-1)[mLcp]) { 
            left  = mid; lLcp = mLcp; 
        }
		else { 
            right = mid; rLcp = mLcp; 
        }
        if ( verbose ) 
            printf("left:%zu right:%zu mid:%zu lLcp:%d rLcp:%d mLcp:%d\n", left, right, mid, lLcp, rLcp, mLcp);

	}

    if ( verbose ) std::cout << "right bound:" << left << "\n";
	return left;
}
Пример #6
0
int main(int argc, char** argv){
	int i;
	if( argc < 2 ) exit(1);
	char* str = argv[1];
	int lcp_array[strlen(str)];
	lcp(lcp_array, str, strlen(str));

	i = 0;while( i < strlen(str)){
		printf("%d ", lcp_array[i]);
		i++;
	}
	printf("\n");
	return 0;
}
Пример #7
0
 // O(n).
 // lcp[i] means lcp(str[sa[i]..], str[sa[i + 1]..]).
 std::vector<int> get_lcp() {
   for (int i = 0; i <= n; i++)
     rank[sa[i]] = i;
   int h = 0;
   std::vector<int> lcp(n + 1);
   for (int i = 0; i < n; i++) {
     int j = sa[rank[i] - 1];
     if (h > 0)
       h--;
     for (; j + h < n && i + h < n; h++) {
       if (str[j + h] != str[i + h])
         break;
     }
     lcp[rank[i] - 1] = h;
   }
   return lcp;
 }
std::vector<int> longest_common_prefix(const T &s, const SuffixArray &sa){
	const int n = sa.size();
	std::vector<int> vs(n), isa(n), lcp(n - 1);
	for(int i = 0; i + 1 < n; ++i){ vs[i] = s[i]; }
	for(int i = 0; i < n; ++i){ isa[sa[i]] = i; }
	int h = 0;
	for(int i = 0; i < n; ++i){
		const int j = isa[i];
		if(j > 0){
			const int k = j - 1;
			while(vs[sa[j] + h] == vs[sa[k] + h]){ ++h; }
			lcp[k] = h;
			if(h > 0){ --h; }
		}
	}
	return lcp;
}
vector<int> buildLcp(const vector<int> &str, const vector<int> &sa) {
    // lcp: longest common prefix for sa[i-1] sa[i]
    int len = sa.size();
    vector<int> lcp(len, 0), idx(len);
    for(int i=0; i<len; ++i) idx[sa[i]] = i;
    for(int i=0, l=0; i<len; ++i) {
        if( idx[i] == 0 ) {
            l = 0;
            continue;
        }
        int j = sa[idx[i]-1];
        while( i+l<len && j+l<len && str[i+l]==str[j+l] )
            ++l;
        lcp[idx[i]] = l;
        l -= l>0;
    }
    return lcp;
}
Пример #10
0
int main()
{
  int t,length,sum;
  while(EOF!=scanf("%d",&t))
  {
  if(t==0)
	  break;
  memset(str,0,sizeof(str));
  getchar();
  gets(str);
  len1=strlen(str);
  length=len1;
  str[len1++]=2;
  gets(str+len1);
  len2=strlen(str+len1);
  n=len1+len2;
  str[n++]=1;
  suffixArray();
  lcp();
  init();
  for(i=2;i<n;i++)
  {
	stack[i-1].index=SA[i]+1;
	if(stack[i-1].index>=9)
		stack[i-1].flag=true;
	else
		stack[i-1].flag=false;
  }
  length=2*length;sum=0;
  for(i=1;i<length;i++)
  {
    j=i+1;
	while(RMQ(stack[i].index,stack[j].index)>=t)
	{
		if(stack[i].flag!=stack[j].flag)
		   sum+=RMQ(stack[i].index,stack[j].index)-t+1;
		j++;
	}
  }
  printf("%d\n",sum);
  }
  return 0;
}
Пример #11
0
 string longestCommonPrefix(vector<string> &strs) {
     
     if(strs.size() == 0)
         return "";
     
     vector<string> res;
     while(strs.size() > 1)
     {
         for(int i=0; i<strs.size(); i+=2)
         {
             if(i+1 < strs.size())
                 res.push_back(lcp(strs[i], strs[i+1]));
             else
                 res.push_back(strs[i]);
         }
         strs = res;
         res.clear();
     }
     return strs[0];
 }
int main(void)
{
    out("starting ...\n");
    std::cout << " Three way quick sort " << std::endl;

    std::vector<char*> strings;

    int N = 0;

    //start from 
    char str[256] = {0};
    while( scanf("%s",&str) != EOF ) {
        char * copy = strdup(str);
        strings.push_back(copy);
        int len = strnlen(copy, 256);
        for(int i = 1; i < len-1; i++) {
            strings.push_back(&copy[i]);
        }
    }
    N = strings.size();

    std::vector<int> v(N); //map to sorted strings
    for(int i = 0; i < N; i++)
        v[i] = i; //all v's entries point to initial respective locations 

    threeway_quicksort(strings, v, 0, N, 0);

    out("SORTED strings\n");
    for(int i = 0; i < N; i++) {
        out ("%s\n", strings[v[i]]);
    }

    int f = binary_search(strings, v, str, 0, N);
    if(f > 0)
        printf("found %s\n", strings[v[f]]);
    else
        printf("Not found %s\n", str);

    lcp(strings, v);
    return 0;
}
Пример #13
0
static void test_lemke()
{
	real * A = makeRandMatrix();
	real * b = makeRandVec2();
	real * x = (real *)malloc(2*NN*sizeof(real));
	real * xx = (real *)malloc(2*NN*sizeof(real));
	real * AA = makeMatrix();
	real * bb = makeRandVec2();
	std::vector<real *> vx;
//	copyMatrix(A,exaples_m2);
//	for(int i =0;i<N;i++)
//		b[i] = exaples_q2[i];
	copyMatrix(AA,A);
	memcpy(bb,b,NN*sizeof(real));
	//memset(x,0,sizeof(real)*N);
	memset(x,0,NN*sizeof(real));
	//memcpy(xx,b,N*sizeof(real));
	memset(xx,0,sizeof(real)*NN);	
	
	printf("--------------------------------------------------------\n");
	printMat("solve lcp A=",A);
	printVec("lcp b=",b);
	printf("--------------------------------------------------------\n");
	int result1 = lcp(A,b,vx,NN);	
	int result2 = lcp_lemke(A,b,x,NN);
	
	printf("lcp solve:\n");
	printf("--------------------------------------------------------\n");
	printLCPVx(vx);
	printf("lcp_lemke solve %s (%d)\n",result2?"true":"false",result2);
	printVec("lcp_lemke=",x);
	check_lcp_result(AA,bb,x,NN);
	
	freeMatrix(A);
	freeMatrix(b);
	freeMatrix(x);
	freeMatrix(AA);
	freeMatrix(bb);	
	freeLcpSolve(vx);	
}
Пример #14
0
static void test_pgs()
{
	real * A = makeRandSPDMatrix();
	real * b = makeRandVec2();
	real * x = makeRandVec2();
	real * xx = makeRandVec2();
	real * AA = makeMatrix();
	real * bb = makeRandVec2();
	std::vector<real *> vx;
	copyMatrix(AA,A);
	memcpy(bb,b,NN*sizeof(real));
	//memset(x,0,sizeof(real)*N);
	memset(x,0,NN*sizeof(real));
	//memcpy(xx,b,N*sizeof(real));
	memset(xx,0,sizeof(real)*NN);
	
	printf("--------------------------------------------------------\n");
	printMat("solve lcp A=",A);
	printVec("lcp b=",b);
	printf("--------------------------------------------------------\n");
	int result1 = lcp(A,b,vx,NN);	
	int result2 = lcp_pgs(A,b,x,NN,15,0.001);
	int result3 = Solve_GaussSeidel(AA,bb,xx,NN,15);
	printf("lcp solve:\n");
	printf("--------------------------------------------------------\n");
	printLCPVx(vx);
	printf("lcp_pgs solve %s (%d)\n",result2?"true":"false",result2);
	printVec("lcp_pgs=",x);
	check_lcp_result(AA,bb,x,NN);
	printVec("gs solve :",xx);

	freeMatrix(A);
	freeMatrix(b);
	freeMatrix(x);
	freeMatrix(AA);
	freeMatrix(bb);
	freeLcpSolve(vx);
}
Пример #15
0
int main() 
{
#ifndef ONLINE_JUDGE
	freopen("input.txt", "rt", stdin);
#endif
	scanf("%d\n%s", &N, &A);
	memcpy(A + N, A, N);
	N = 2 * N;

	A[N] = A[N + 1] = A[N + 2] = 0;
	int i;

	for (i = 0; i < N; i++)
		S[i] = A[i] - 'A';

	suffixArray(S, SA, N, 26);

	for (i = 0; i < N; i++) 
		printf("%d ", SA[i]);
	printf("\n");
	LCP = lcp(SA, A, N);

	double answer = 0;
	if (LCP)
	{
		for (i = 0; i < N; i++)
		{
			printf("%d ", LCP[i]);
			answer += LCP[i];
		}
		printf("\n");

		answer /= N - 1;
		printf("%.3lf\n", answer);
	}
	
	return 0;
}
Пример #16
0
void dSolveLCPBasic (int n, dReal *A, dReal *x, dReal *b,
		     dReal *w, int nub, dReal *lo, dReal *hi)
{
  dAASSERT (n>0 && A && x && b && w && nub == 0);

  int i,k;
  int nskip = dPAD(n);
  dReal *L = (dReal*) ALLOCA (n*nskip*sizeof(dReal));
  dReal *d = (dReal*) ALLOCA (n*sizeof(dReal));
  dReal *delta_x = (dReal*) ALLOCA (n*sizeof(dReal));
  dReal *delta_w = (dReal*) ALLOCA (n*sizeof(dReal));
  dReal *Dell = (dReal*) ALLOCA (n*sizeof(dReal));
  dReal *ell = (dReal*) ALLOCA (n*sizeof(dReal));
  dReal *tmp = (dReal*) ALLOCA (n*sizeof(dReal));
  dReal **Arows = (dReal**) ALLOCA (n*sizeof(dReal*));
  int *p = (int*) ALLOCA (n*sizeof(int));
  int *C = (int*) ALLOCA (n*sizeof(int));
  int *dummy = (int*) ALLOCA (n*sizeof(int));

  dLCP lcp (n,0,A,x,b,w,tmp,tmp,L,d,Dell,ell,tmp,dummy,dummy,p,C,Arows);
  nub = lcp.getNub();

  for (i=0; i<n; i++) {
    w[i] = lcp.AiC_times_qC (i,x) - b[i];
    if (w[i] >= 0) {
      lcp.transfer_i_to_N (i);
    }
    else {
      for (;;) {
	// compute: delta_x(C) = -A(C,C)\A(C,i)
	dSetZero (delta_x,n);
	lcp.solve1 (delta_x,i);
	delta_x[i] = 1;

	// compute: delta_w = A*delta_x
	dSetZero (delta_w,n);
	lcp.pN_equals_ANC_times_qC (delta_w,delta_x);
	lcp.pN_plusequals_ANi (delta_w,i);
        delta_w[i] = lcp.AiC_times_qC (i,delta_x) + lcp.Aii(i);

	// find index to switch
	int si = i;		// si = switch index
	int si_in_N = 0;	// set to 1 if si in N
	dReal s = -w[i]/delta_w[i];

	if (s <= 0) {
	  dMessage (d_ERR_LCP, "LCP internal error, s <= 0 (s=%.4e)",s);
	  if (i < (n-1)) {
	    dSetZero (x+i,n-i);
	    dSetZero (w+i,n-i);
	  }
	  goto done;
	}

	for (k=0; k < lcp.numN(); k++) {
	  if (delta_w[lcp.indexN(k)] < 0) {
	    dReal s2 = -w[lcp.indexN(k)] / delta_w[lcp.indexN(k)];
	    if (s2 < s) {
	      s = s2;
	      si = lcp.indexN(k);
	      si_in_N = 1;
	    }
	  }
	}
	for (k=0; k < lcp.numC(); k++) {
	  if (delta_x[lcp.indexC(k)] < 0) {
	    dReal s2 = -x[lcp.indexC(k)] / delta_x[lcp.indexC(k)];
	    if (s2 < s) {
	      s = s2;
	      si = lcp.indexC(k);
	      si_in_N = 0;
	    }
	  }
	}

	// apply x = x + s * delta_x
	lcp.pC_plusequals_s_times_qC (x,s,delta_x);
	x[i] += s;
	lcp.pN_plusequals_s_times_qN (w,s,delta_w);
	w[i] += s * delta_w[i];

	// switch indexes between sets if necessary
	if (si==i) {
	  w[i] = 0;
	  lcp.transfer_i_to_C (i);
	  break;
	}
	if (si_in_N) {
          w[si] = 0;
	  lcp.transfer_i_from_N_to_C (si);
	}
	else {
          x[si] = 0;
	  lcp.transfer_i_from_C_to_N (si);
	}
      }
    }
  }

 done:
  lcp.unpermute();
}
Пример #17
0
int main()
{
	int cas = 0;
	while (scanf("%s", s) && s[0] != '#')
	{
		int l = strlen(s);
		for (int i = 0; i < l; i++) r[i] = s[i] - 'a' + 1;
		r[l] = 0;
		da(r, sa, l+1, 27);
		calheight(r, sa, l);
		init_rmq(l);
		int ans = 0;
		for (int i = 1; i <= l / 2; i++)
		for (int j = 0; j + i < l; j+=i)
		{
			int k = lcp(j, j+i);
			int x = k / i + 1;
			if (x + 1 < ans) continue;
			int aa = i - k % i;
			bool flag = 0;
			if (j >= aa)
			{
				int kk = lcp(j-aa, j+i-aa);
				int xx = kk / i + 1;
				if (xx > x) x = xx, flag = 1;
			}

		//	if (j-aa >= 0 && lcp(j-aa, j+i-aa) >= (x+1) * (i-1)) x++, flag = 1;
			if (ans < x)
			{
				ans = x;
				cnt = 0;
				zz[cnt] = flag ? j-aa : j;
				zz1[cnt++] = i;
			}
			else if (ans == x) 
			{	
				zz[cnt] = flag ? j-aa : j;
				zz1[cnt++] = i;
			}	
		}
		printf("Case %d: ", ++cas);
		char cc = 'z';
		if (ans == 1)
		{
			for (int i = 0; i < l; i++)
				if (s[i] < cc) cc = s[i];
			printf("%c\n", cc);
			continue;
		}
		int start = zz[0];
		int l0 = zz1[0];
		for (int i = 0; i < cnt; i++)
		{
			int k = lcp(zz[i], zz[i]+zz1[i]);
			int aa = k - k % zz1[i];
			for (int j = zz[i]; j >= 0 && j >= zz[i]-aa; j--)
				if (lcp(j, j+zz1[i]) < (ans-1) * zz1[i]) break;
				else if (rank[j] < rank[start]) 
				{
					start = j;
					l0 = zz1[i];
				}
		}
		s[start+l0*ans] = '\0';
		puts(s+start);
	}
	return 0;
}
Пример #18
0
/* Function: mdlOutputs =======================================================
 * do the main optimization routine here
 * no discrete states are considered
 */
static void mdlOutputs(SimStruct *S, int_T tid)
{
	int_T i, j, Result, qinfeas=0;
	real_T  *z = ssGetOutputPortRealSignal(S,0);
	real_T  *w = ssGetOutputPortRealSignal(S,1);
	real_T  *I = ssGetOutputPortRealSignal(S,2);
	real_T  *exitflag = ssGetOutputPortRealSignal(S,3);
	real_T  *pivots = ssGetOutputPortRealSignal(S,4);
	real_T  *time = ssGetOutputPortRealSignal(S,5);

	InputRealPtrsType M = ssGetInputPortRealSignalPtrs(S,0);
	InputRealPtrsType q = ssGetInputPortRealSignalPtrs(S,1);

	ptrdiff_t pivs, info, m, n, inc=1;
	char_T T='N';
	double total_time,  alpha=1.0, tmp=-1.0, *x, *Mn, *qn, *r, *c, s=0.0, sn=0.0; 
	PT_Matrix pA; /* Problem data A = [M -1 q] */
	PT_Basis  pB; /* The basis */  
	T_Options options;  /* options structure defined in lcp_matrix.h */          

/* for RTW we do not need these variables */
#ifdef MATLAB_MEX_FILE
	const char *fname;
	mxArray *fval;
	int_T nfields;
	clock_t t1,t2;
#endif

    
	UNUSED_ARG(tid); /* not used in single tasking mode */
	
	/* default options */
	options.zerotol = 1e-10; /* zero tolerance */
	options.lextol = 1e-10; /* lexicographic tolerance - a small treshold to determine if values are equal */
	options.maxpiv = INT_MAX; /* maximum number of pivots */
	/* if LUMOD routine is chosen, this options refactorizes the basis after n steps using DGETRF
	   routine from lapack to avoid numerical problems */
	options.nstepf = 50;
	options.clock = 0; /* 0 or 1 - to print computational time */
	options.verbose = 0; /* 0 or 1 - verbose output */
	/*  which routine in Basis_solve should solve a set of linear equations: 
	    0 - corresponds to LUmod package that performs factorization in the form L*A = U. Depending on
	    the change in A factors L, U are updated. This is the fastest method.
	    1 - corresponds to DGESV simple driver 
	    which solves the system AX = B by factorizing A and overwriting B with the solution X
	    2 - corresponds to DGELS simple driver 
	    which solves overdetermined or underdetermined real linear systems min ||b - Ax||_2
	    involving an M-by-N matrix A, or its transpose, using a QR or LQ  factorization of A.  */
	options.routine = 0; 
	options.timelimit = 3600; /* time limit in seconds to interrupt iterations */
	options.normalize = 1; /* 0 or 1 - perform scaling of input matrices M, q */
    options.normalizethres = 1e6; 
    /* If the normalize option is on, then the matrix scaling is performed 
      only if 1 norm of matrix M (maximum absolute column sum) is above this threshold.
      This enforce additional control over normalization since it seems to be more
      aggressive also for well-conditioned problems. */

#ifdef MATLAB_MEX_FILE
	/* overwriting default options by the user */
	if (ssGetSFcnParamsCount(S)==3) {
		nfields = mxGetNumberOfFields(ssGetSFcnParam(S,2));
		for(i=0; i<nfields; i++){
			fname = mxGetFieldNameByNumber(ssGetSFcnParam(S,2), i);   
			fval = mxGetField(ssGetSFcnParam(S,2), 0, fname);
			if ( strcmp(fname,"zerotol")==0 )
				options.zerotol = mxGetScalar(fval);
			if ( strcmp(fname,"lextol")==0 )
				options.lextol = mxGetScalar(fval);
			if ( strcmp(fname,"maxpiv")==0 ) {
				if (mxGetScalar(fval)>=(double)INT_MAX)
					options.maxpiv = INT_MAX;
				else
					options.maxpiv = (int_T)mxGetScalar(fval);
			}
			if ( strcmp(fname,"nstepf")==0 )
				options.nstepf = (int_T)mxGetScalar(fval);
			if ( strcmp(fname,"timelimit")==0 )
				options.timelimit = mxGetScalar(fval);
			if ( strcmp(fname,"clock")==0 )
				options.clock = (int_T)mxGetScalar(fval);
			if ( strcmp(fname,"verbose")==0 )
				options.verbose = (int_T)mxGetScalar(fval);
			if ( strcmp(fname,"routine")==0 )
				options.routine = (int_T)mxGetScalar(fval);
			if ( strcmp(fname,"normalize")==0 )
				options.normalize = (int_T)mxGetScalar(fval);
            if ( strcmp(fname, "normalizethres")==0 )
                options.normalizethres = mxGetScalar(fval);          
		}
	}
#endif
    

	/* Normalize M, q to avoid numerical problems if possible 
	   Mn = diag(r)*M*diag(c) , qn = diag(r)*q  */
	/* initialize Mn, qn */
	Mn = (double *)ssGetPWork(S)[0];
	qn = (double *)ssGetPWork(S)[1];
	/* initialize vectors r, c */
	r = (double *)ssGetPWork(S)[2];
	c = (double *)ssGetPWork(S)[3];
	/* initialize auxiliary vector x */
	x = (double *)ssGetPWork(S)[4];
	/* initialize to ones */
	for (i=0; i<NSTATES(S); i++) {
		r[i] = 1.0;
		c[i] = 1.0;
	}
	m = NSTATES(S);
	n = m*m;
	/* write data to Mn = M */
	memcpy(Mn, *M, n*sizeof(double));
	/* write data to qn = q */
	memcpy(qn, *q, m*sizeof(double));
    /* check out the 1-norm of matrix M (maximum column sum) */
    for (i=0; i<m; i++) {
        sn = dasum(&m, &Mn[i*m], &inc);
        if (sn>s) {
            s = sn;
        }
    }

	/* scale matrix M, q and write scaling factors to r (rows) and c (columns) */
	if (options.normalize && s>options.normalizethres) {
		NormalizeMatrix (m, m, Mn, qn, r, c,  options);
    }
    
	/* Setup the problem */
	pA = ssGetPWork(S)[5];
	/* A(:,1:m) = M */
	memcpy(pMAT(pA), Mn, n*sizeof(double));

	/* A(:,1:m) = -A(:,1:m) */
	dscal(&n, &tmp, pMAT(pA), &inc);

	/* A(:,m+1) = -1 */
	for(i=0;i<m;i++)
		C_SEL(pA,i,m) = -1.0;

	/* A(:,m+2) = q */
	memcpy(&(C_SEL(pA,0,m+1)),qn,m*sizeof(double));

	/* initialize basis */
	pB = ssGetPWork(S)[6];

    /* check if the problem is not feasible at the beginning */
    for (i=0; i<m; i++) {
        if (qn[i]<-options.zerotol) {
            qinfeas = 1;
            break;
        }
    }


    /* Solve the LCP */
    if (qinfeas) {
#ifdef MATLAB_MEX_FILE
	t1 = clock();
#endif

    /* main LCP rouinte */    
    Result = lcp(pB, pA, &pivs, options);
        
#ifdef MATLAB_MEX_FILE
    t2 = clock();
    total_time = ((double)(t2-t1))/CLOCKS_PER_SEC;
#else
    total_time = -1;
#endif
    } else {
        pivs = 0;
        total_time = 0;
        Result = LCP_FEASIBLE;    
    }

#ifdef MATLAB_MEX_FILE
	if (options.clock) {
		printf("Time needed to perform pivoting:\n time= %i  (%lf seconds)\n",
		       t2-t1,total_time);
		printf("Pivots: %ld\n", pivs);
		printf("CLOCKS_PER_SEC = %i\n",CLOCKS_PER_SEC);
	}
#endif

	/* initialize values to 0 */
	for(i=0;i<NSTATES(S);i++)
	{
		w[i] = 0.0;
		z[i] = 0.0;
		I[i] = 0.0;
	}

	/* for a feasible basis, compute the solution */
	if ( Result == LCP_FEASIBLE || Result == LCP_PRETERMINATED )
	{
#ifdef MATLAB_MEX_FILE
		t1 = clock();
#endif
		info = Basis_Solve(pB, &(C_SEL(pA,0,m+1)), x, options);
		for (j=0,i=0;i<Index_Length(pB->pW);i++,j++)
		{
			w[Index_Get(pB->pW,i)] = x[j];
			/* add 1 due to matlab 1-indexing */
			I[j] = Index_Get(pB->pW,i)+1;
		}
		for(i=0;i<Index_Length(pB->pZ);i++,j++)
		{
			/* take only positive values */
			if (x[j] > options.zerotol ) {
				z[Index_Get(pB->pZ,i)] = x[j];
			}
			/* add 1 due to matlab 1-indexing */
			I[j] = Index_Get(pB->pZ, i)+m+1;
		}
#ifdef MATLAB_MEX_FILE
		t2 = clock();
		total_time+=(double)(t2-t1)/(double)CLOCKS_PER_SEC;
		if (options.clock) {
			printf("Time in total needed to solve LCP: %lf seconds\n",
			       total_time + (double)(t2-t1)/(double)CLOCKS_PER_SEC);
		}
#endif
		
		if (options.normalize) {
			/* do the backward normalization */
			/* z = diag(c)*zn */
			for (i=0; i<m; i++) {
				z[i] = c[i]*z[i];
			}
			
			/* since the normalization does not compute w properly, we recalculate it from
			 * recovered z */
			/* write data to Mn = M */
			memcpy(Mn, *M, n*sizeof(double));
			/* write data to qn = q */
			memcpy(qn, *q, m*sizeof(double));
			/* copy w <- q; */
			dcopy(&m, qn, &inc, w, &inc);
			/* compute w = M*z + q */
			dgemv(&T, &m, &m, &alpha, Mn, &m, z, &inc, &alpha, w, &inc);
			/* if w is less than eps, consider it as zero */
			for (i=0; i<m; i++) {
				if (w[i]<options.zerotol) {
					w[i] = 0.0;
				}
			}
		}	       
	}


	/* outputs */
	*exitflag = (real_T )Result;
	*pivots =(real_T)pivs;
	*time = (real_T)total_time;

	/* reset dimensions and values in basis for a recursive call */
	Reinitialize_Basis(m, pB);
	
}
Пример #19
0
bool dSolveLCP (int n, dReal *A, dReal *x, dReal *b,
                dReal *outer_w/*=nullptr*/, int nub, dReal *lo, dReal *hi, int *findex, bool earlyTermination)
{
  dAASSERT (n>0 && A && x && b && lo && hi && nub >= 0 && nub <= n);
# ifndef dNODEBUG
  {
    // check restrictions on lo and hi
    for (int k=0; k<n; ++k) dIASSERT (lo[k] <= 0 && hi[k] >= 0);
  }
# endif


  // if all the variables are unbounded then we can just factor, solve,
  // and return
  if (nub >= n) {
    dReal *d = new dReal[n];
    dSetZero (d, n);

    int nskip = dPAD(n);
    dFactorLDLT (A, d, n, nskip);
    dSolveLDLT (A, d, b, n, nskip);
    memcpy (x, b, n*sizeof(dReal));

    delete[] d;
    return true;
  }

  const int nskip = dPAD(n);
  dReal *L = new dReal[ (n*nskip)];
  dReal *d = new dReal[ (n)];
  dReal *w = outer_w ? outer_w : (new dReal[n]);
  dReal *delta_w = new dReal[ (n)];
  dReal *delta_x = new dReal[ (n)];
  dReal *Dell = new dReal[ (n)];
  dReal *ell = new dReal[ (n)];
#ifdef ROWPTRS
  dReal **Arows = new dReal* [n];
#else
  dReal **Arows = nullptr;
#endif
  int *p = new int[n];
  int *C = new int[n];

  // for i in N, state[i] is 0 if x(i)==lo(i) or 1 if x(i)==hi(i)
  bool *state = new bool[n];

  // create LCP object. note that tmp is set to delta_w to save space, this
  // optimization relies on knowledge of how tmp is used, so be careful!
  dLCP lcp(n,nskip,nub,A,x,b,w,lo,hi,L,d,Dell,ell,delta_w,state,findex,p,C,Arows);
  int adj_nub = lcp.getNub();

  // loop over all indexes adj_nub..n-1. for index i, if x(i),w(i) satisfy the
  // LCP conditions then i is added to the appropriate index set. otherwise
  // x(i),w(i) is driven either +ve or -ve to force it to the valid region.
  // as we drive x(i), x(C) is also adjusted to keep w(C) at zero.
  // while driving x(i) we maintain the LCP conditions on the other variables
  // 0..i-1. we do this by watching out for other x(i),w(i) values going
  // outside the valid region, and then switching them between index sets
  // when that happens.

  bool hit_first_friction_index = false;
  for (int i=adj_nub; i<n; ++i) {
    bool s_error = false;
    // the index i is the driving index and indexes i+1..n-1 are "dont care",
    // i.e. when we make changes to the system those x's will be zero and we
    // don't care what happens to those w's. in other words, we only consider
    // an (i+1)*(i+1) sub-problem of A*x=b+w.

    // if we've hit the first friction index, we have to compute the lo and
    // hi values based on the values of x already computed. we have been
    // permuting the indexes, so the values stored in the findex vector are
    // no longer valid. thus we have to temporarily unpermute the x vector. 
    // for the purposes of this computation, 0*infinity = 0 ... so if the
    // contact constraint's normal force is 0, there should be no tangential
    // force applied.

    if (!hit_first_friction_index && findex && findex[i] >= 0) {
      // un-permute x into delta_w, which is not being used at the moment
      for (int j=0; j<n; ++j) delta_w[p[j]] = x[j];

      // set lo and hi values
      for (int k=i; k<n; ++k) {
        dReal wfk = delta_w[findex[k]];
        if (wfk == 0) {
          hi[k] = 0;
          lo[k] = 0;
        }
        else {
          hi[k] = dFabs (hi[k] * wfk);
          lo[k] = -hi[k];
        }
      }
      hit_first_friction_index = true;
    }

    // thus far we have not even been computing the w values for indexes
    // greater than i, so compute w[i] now.
    w[i] = lcp.AiC_times_qC (i,x) + lcp.AiN_times_qN (i,x) - b[i];

    // if lo=hi=0 (which can happen for tangential friction when normals are
    // 0) then the index will be assigned to set N with some state. however,
    // set C's line has zero size, so the index will always remain in set N.
    // with the "normal" switching logic, if w changed sign then the index
    // would have to switch to set C and then back to set N with an inverted
    // state. this is pointless, and also computationally expensive. to
    // prevent this from happening, we use the rule that indexes with lo=hi=0
    // will never be checked for set changes. this means that the state for
    // these indexes may be incorrect, but that doesn't matter.

    // see if x(i),w(i) is in a valid region
    if (lo[i]==0 && w[i] >= 0) {
      lcp.transfer_i_to_N (i);
      state[i] = false;
    }
    else if (hi[i]==0 && w[i] <= 0) {
      lcp.transfer_i_to_N (i);
      state[i] = true;
    }
    else if (w[i]==0) {
      // this is a degenerate case. by the time we get to this test we know
      // that lo != 0, which means that lo < 0 as lo is not allowed to be +ve,
      // and similarly that hi > 0. this means that the line segment
      // corresponding to set C is at least finite in extent, and we are on it.
      // NOTE: we must call lcp.solve1() before lcp.transfer_i_to_C()
      lcp.solve1 (delta_x,i,0,1);

      lcp.transfer_i_to_C (i);
    }
    else {
      // we must push x(i) and w(i)
      for (;;) {
        int dir;
        dReal dirf;
        // find direction to push on x(i)
        if (w[i] <= 0) {
          dir = 1;
          dirf = REAL(1.0);
        }
        else {
          dir = -1;
          dirf = REAL(-1.0);
        }

        // compute: delta_x(C) = -dir*A(C,C)\A(C,i)
        lcp.solve1 (delta_x,i,dir);

        // note that delta_x[i] = dirf, but we wont bother to set it

        // compute: delta_w = A*delta_x ... note we only care about
        // delta_w(N) and delta_w(i), the rest is ignored
        lcp.pN_equals_ANC_times_qC (delta_w,delta_x);
        lcp.pN_plusequals_ANi (delta_w,i,dir);
        delta_w[i] = lcp.AiC_times_qC (i,delta_x) + lcp.Aii(i)*dirf;

        // find largest step we can take (size=s), either to drive x(i),w(i)
        // to the valid LCP region or to drive an already-valid variable
        // outside the valid region.

        int cmd = 1;		// index switching command
        int si = 0;		// si = index to switch if cmd>3
        dReal s = -w[i]/delta_w[i];
        if (dir > 0) {
          if (hi[i] < dInfinity) {
            dReal s2 = (hi[i]-x[i])*dirf;	// was (hi[i]-x[i])/dirf	// step to x(i)=hi(i)
            if (s2 < s) {
              s = s2;
              cmd = 3;
            }
          }
        }
        else {
          if (lo[i] > -dInfinity) {
            dReal s2 = (lo[i]-x[i])*dirf;	// was (lo[i]-x[i])/dirf	// step to x(i)=lo(i)
            if (s2 < s) {
              s = s2;
              cmd = 2;
            }
          }
        }

        {
          const int numN = lcp.numN();
          for (int k=0; k < numN; ++k) {
            const int indexN_k = lcp.indexN(k);
            if (!state[indexN_k] ? delta_w[indexN_k] < 0 : delta_w[indexN_k] > 0) {
                // don't bother checking if lo=hi=0
                if (lo[indexN_k] == 0 && hi[indexN_k] == 0) continue;
                dReal s2 = -w[indexN_k] / delta_w[indexN_k];
                if (s2 < s) {
                  s = s2;
                  cmd = 4;
                  si = indexN_k;
                }
            }
          }
        }

        {
          const int numC = lcp.numC();
          for (int k=adj_nub; k < numC; ++k) {
            const int indexC_k = lcp.indexC(k);
            if (delta_x[indexC_k] < 0 && lo[indexC_k] > -dInfinity) {
              dReal s2 = (lo[indexC_k]-x[indexC_k]) / delta_x[indexC_k];
              if (s2 < s) {
                s = s2;
                cmd = 5;
                si = indexC_k;
              }
            }
            if (delta_x[indexC_k] > 0 && hi[indexC_k] < dInfinity) {
              dReal s2 = (hi[indexC_k]-x[indexC_k]) / delta_x[indexC_k];
              if (s2 < s) {
                s = s2;
                cmd = 6;
                si = indexC_k;
              }
            }
          }
        }

        //static char* cmdstring[8] = {0,"->C","->NL","->NH","N->C",
        //			     "C->NL","C->NH"};
        //printf ("cmd=%d (%s), si=%d\n",cmd,cmdstring[cmd],(cmd>3) ? si : i);

        // if s <= 0 then we've got a problem. if we just keep going then
        // we're going to get stuck in an infinite loop. instead, just cross
        // our fingers and exit with the current solution.
        if (s <= REAL(0.0)) {

          if (earlyTermination) {
            if (!outer_w)
              delete[] w;
            delete[] L;
            delete[] d;
            delete[] delta_w;
            delete[] delta_x;
            delete[] Dell;
            delete[] ell;
          #ifdef ROWPTRS
            delete[] Arows;
          #endif
            delete[] p;
            delete[] C;

            delete[] state;

            return false;
          }

          // We shouldn't be overly aggressive about printing this warning,
          // because sometimes it gets spammed if s is just a tiny bit beneath
          // 0.0.
          if (s < REAL(-1e-6)) {
            dMessage (d_ERR_LCP, "LCP internal error, s <= 0 (s=%.4e)",
                      (double)s);
          }

          if (i < n) {
            dSetZero (x+i,n-i);
            dSetZero (w+i,n-i);
          }
          s_error = true;
          break;
        }

        // apply x = x + s * delta_x
        lcp.pC_plusequals_s_times_qC (x, s, delta_x);
        x[i] += s * dirf;

        // apply w = w + s * delta_w
        lcp.pN_plusequals_s_times_qN (w, s, delta_w);
        w[i] += s * delta_w[i];

        // void *tmpbuf;
        // switch indexes between sets if necessary
        switch (cmd) {
        case 1:		// done
          w[i] = 0;
          lcp.transfer_i_to_C (i);
          break;
        case 2:		// done
          x[i] = lo[i];
          state[i] = false;
          lcp.transfer_i_to_N (i);
          break;
        case 3:		// done
          x[i] = hi[i];
          state[i] = true;
          lcp.transfer_i_to_N (i);
          break;
        case 4:		// keep going
          w[si] = 0;
          lcp.transfer_i_from_N_to_C (si);
          break;
        case 5:		// keep going
          x[si] = lo[si];
          state[si] = false;
          lcp.transfer_i_from_C_to_N (si, nullptr);
          break;
        case 6:		// keep going
          x[si] = hi[si];
          state[si] = true;
          lcp.transfer_i_from_C_to_N (si, nullptr);
          break;
        }

        if (cmd <= 3) break;
      } // for (;;)
    } // else

    if (s_error) {
      break;
    }
  } // for (int i=adj_nub; i<n; ++i)

  lcp.unpermute();

  if (!outer_w)
	  delete[] w;
  delete[] L;
  delete[] d;
  delete[] delta_w;
  delete[] delta_x;
  delete[] Dell;
  delete[] ell;
#ifdef ROWPTRS
  delete[] Arows;
#endif
  delete[] p;
  delete[] C;

  delete[] state;

  return true;
}
int main()
{
//     std::ios_base::sync_with_stdio(false);

    #ifdef kimbbakar
        freopen ( "in.txt", "r", stdin );
        freopen ( "out.txt", "w", stdout );
    #endif
 
    in(n),in(q);

    for(int i=1;i<=n;i++){
        in(val[i]);    	
        cp[i-1]=val[i];
    }

    sort(cp,cp+n);

	for(int i=1;i<=n;i++){
		val[i] = lower_bound(cp,cp+n,val[i] )-cp;
	}


    int u,v;

    for(int i=1;i<n;i++){
        in(u),in(v);

        lst[u].pb(v);
        lst[v].pb(u);
    }

    dfs(1,0);
    sp_table();

    for(int i=0;i<q;i++){
    	in(u),in(v);

    	if(st[u]>st[v])
    		swap(u,v);

    	int p = lcp(u,v);  

    	assert(p<=n);

    	qu[i].idx=i;

    	if(u!=p and v!=p){
	    	qu[i].l=ed[u];
	    	qu[i].r=st[v];    		
    		qu[i].lcp=p;
    	}
    	else{
	    	qu[i].l=st[u];
	    	qu[i].r=st[v];    		
    		qu[i].lcp=-1;    		
    	} 
    }

    dv = 1000; 
    sort(qu,qu+q,cmp1);

    int l=1,r=1;  
    cnt[ val[new_array[l]] ]++;
    cc[ new_array[l]]++;
    int tmp =1;  

    for(int i=0;i<q;i++){

  	while(l<qu[i].l) chk(l++,tmp) ;   
    	while(qu[i].l<l) chk(--l,tmp);
    	while(r<qu[i].r) chk(++r,tmp) ;  
    	while(qu[i].r<r) chk(r--,tmp);

    	res[qu[i].idx]=tmp;

     	if(qu[i].lcp!=-1 and cnt[val[qu[i].lcp] ]==0 )
			res[qu[i].idx]++;     		

    } 
    for(int i=0;i<q;i++)
    	pf("%d\n",res[i]);


    return 0;
}
Пример #21
0
void construct_lcp_PHI(cache_config& config)
{
    typedef int_vector<>::size_type size_type;
    typedef int_vector<t_width> text_type;
    const char* KEY_TEXT = key_text_trait<t_width>::KEY_TEXT;
    int_vector_file_buffer<> sa_buf(config.file_map[constants::KEY_SA]);
    size_type n = sa_buf.int_vector_size;

    assert(n > 0);
    if (1 == n) {  // Handle special case: Input only the sentinel character.
        int_vector<> lcp(1, 0);
        store_to_cache(lcp, constants::KEY_LCP, config);
        return;
    }

//	(1) Calculate PHI (stored in array plcp)
    int_vector<> plcp(n, 0, sa_buf.width);
    for (size_type i=0, r_sum=0, r=sa_buf.load_next_block(), sai_1 = 0; r_sum < n;) {
        for (; i < r_sum+r; ++i) {
            size_type sai = sa_buf[i-r_sum];
            plcp[ sai ] = sai_1;
            sai_1 = sai;
        }
        r_sum += r; r = sa_buf.load_next_block();
    }

//  (2) Load text from disk
    text_type text;
    load_from_cache(text, KEY_TEXT, config);

//  (3) Calculate permuted LCP array (text order), called PLCP
    size_type max_l = 0;
    for (size_type i=0, l=0; i < n-1; ++i) {
        size_type phii = plcp[i];
        while (text[i+l] == text[phii+l]) {
            ++l;
        }
        plcp[i] = l;
        if (l) {
            max_l = std::max(max_l, l);
            --l;
        }
    }
    util::clear(text);
    uint8_t lcp_width = bits::hi(max_l)+1;

//	(4) Transform PLCP into LCP
    std::string lcp_file = cache_file_name(constants::KEY_LCP, config);
    osfstream lcp_out_buf(lcp_file, std::ios::binary | std::ios::app | std::ios::out);   // open buffer for lcp

    size_type bit_size = n*lcp_width;
    lcp_out_buf.write((char*) &(bit_size), sizeof(bit_size));	// write size of vector
    lcp_out_buf.write((char*) &(lcp_width),sizeof(lcp_width));  // write int_width of vector
    size_type wb = 0;  // bytes written into lcp int_vector

    size_type buffer_size = 1000000; // buffer_size is a multiple of 8!

    int_vector<> lcp_buf(buffer_size, 0, lcp_width);
    lcp_buf[0] = 0;
    sa_buf.reset(buffer_size);
    size_type r = 0;// sa_buf.load_next_block();
    for (size_type i=1, r_sum=0; r_sum < n;) {
        for (; i < r_sum+r; ++i) {
            size_type sai = sa_buf[i-r_sum];
            lcp_buf[ i-r_sum ] = plcp[sai];
        }
        if (r > 0) {
            size_type cur_wb = (r*lcp_buf.width()+7)/8;
            lcp_out_buf.write((const char*)lcp_buf.data(), cur_wb);
            wb += cur_wb;
        }
        r_sum += r; r = sa_buf.load_next_block();
    }
    if (wb%8) {
        lcp_out_buf.write("\0\0\0\0\0\0\0\0", 8-wb%8);
    }
    lcp_out_buf.close();
    register_cache_file(constants::KEY_LCP, config);
}
Пример #22
0
void dSolveLCPBasic (int n, dReal *A, dReal *x, dReal *b,
		     dReal *w, int nub, dReal *lo, dReal *hi)
{
  dAASSERT (n>0 && A && x && b && w && nub == 0);

  int i,k;
  int nskip = dPAD(n);
  ALLOCA (dReal,L,n*nskip*sizeof(dReal));
#ifdef dUSE_MALLOC_FOR_ALLOCA
    if (L == NULL) {
      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
      return;
    }
#endif
  ALLOCA (dReal,d,n*sizeof(dReal));
#ifdef dUSE_MALLOC_FOR_ALLOCA
    if (d == NULL) {
      UNALLOCA(L);
      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
      return;
    }
#endif
  ALLOCA (dReal,delta_x,n*sizeof(dReal));
#ifdef dUSE_MALLOC_FOR_ALLOCA
    if (delta_x == NULL) {
      UNALLOCA(d);
      UNALLOCA(L);
      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
      return;
    }
#endif
  ALLOCA (dReal,delta_w,n*sizeof(dReal));
#ifdef dUSE_MALLOC_FOR_ALLOCA
    if (delta_w == NULL) {
      UNALLOCA(delta_x);
      UNALLOCA(d);
      UNALLOCA(L);
      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
      return;
    }
#endif
  ALLOCA (dReal,Dell,n*sizeof(dReal));
#ifdef dUSE_MALLOC_FOR_ALLOCA
    if (Dell == NULL) {
      UNALLOCA(delta_w);
      UNALLOCA(delta_x);
      UNALLOCA(d);
      UNALLOCA(L);
      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
      return;
    }
#endif
  ALLOCA (dReal,ell,n*sizeof(dReal));
#ifdef dUSE_MALLOC_FOR_ALLOCA
    if (ell == NULL) {
      UNALLOCA(Dell);
      UNALLOCA(delta_w);
      UNALLOCA(delta_x);
      UNALLOCA(d);
      UNALLOCA(L);
      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
      return;
    }
#endif
  ALLOCA (dReal,tmp,n*sizeof(dReal));
#ifdef dUSE_MALLOC_FOR_ALLOCA
    if (tmp == NULL) {
      UNALLOCA(ell);
      UNALLOCA(Dell);
      UNALLOCA(delta_w);
      UNALLOCA(delta_x);
      UNALLOCA(d);
      UNALLOCA(L);
      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
      return;
    }
#endif
  ALLOCA (dReal*,Arows,n*sizeof(dReal*));
#ifdef dUSE_MALLOC_FOR_ALLOCA
    if (Arows == NULL) {
      UNALLOCA(tmp);
      UNALLOCA(ell);
      UNALLOCA(Dell);
      UNALLOCA(delta_w);
      UNALLOCA(delta_x);
      UNALLOCA(d);
      UNALLOCA(L);
      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
      return;
    }
#endif
  ALLOCA (int,p,n*sizeof(int));
#ifdef dUSE_MALLOC_FOR_ALLOCA
    if (p == NULL) {
      UNALLOCA(Arows);
      UNALLOCA(tmp);
      UNALLOCA(ell);
      UNALLOCA(Dell);
      UNALLOCA(delta_w);
      UNALLOCA(delta_x);
      UNALLOCA(d);
      UNALLOCA(L);
      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
      return;
    }
#endif
  ALLOCA (int,C,n*sizeof(int));
#ifdef dUSE_MALLOC_FOR_ALLOCA
    if (C == NULL) {
      UNALLOCA(p);
      UNALLOCA(Arows);
      UNALLOCA(tmp);
      UNALLOCA(ell);
      UNALLOCA(Dell);
      UNALLOCA(delta_w);
      UNALLOCA(delta_x);
      UNALLOCA(d);
      UNALLOCA(L);
      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
      return;
    }
#endif
  ALLOCA (int,dummy,n*sizeof(int));
#ifdef dUSE_MALLOC_FOR_ALLOCA
    if (dummy == NULL) {
      UNALLOCA(C);
      UNALLOCA(p);
      UNALLOCA(Arows);
      UNALLOCA(tmp);
      UNALLOCA(ell);
      UNALLOCA(Dell);
      UNALLOCA(delta_w);
      UNALLOCA(delta_x);
      UNALLOCA(d);
      UNALLOCA(L);
      dMemoryFlag = d_MEMORY_OUT_OF_MEMORY;
      return;
    }
#endif


  dLCP lcp (n,0,A,x,b,w,tmp,tmp,L,d,Dell,ell,tmp,dummy,dummy,p,C,Arows);
  nub = lcp.getNub();

  for (i=0; i<n; i++) {
    w[i] = lcp.AiC_times_qC (i,x) - b[i];
    if (w[i] >= 0) {
      lcp.transfer_i_to_N (i);
    }
    else {
      for (;;) {
	// compute: delta_x(C) = -A(C,C)\A(C,i)
	dSetZero (delta_x,n);
	lcp.solve1 (delta_x,i);
#ifdef dUSE_MALLOC_FOR_ALLOCA
	if (dMemoryFlag == d_MEMORY_OUT_OF_MEMORY) {
	  UNALLOCA(dummy);
	  UNALLOCA(C);
	  UNALLOCA(p);
	  UNALLOCA(Arows);
	  UNALLOCA(tmp);
	  UNALLOCA(ell);
	  UNALLOCA(Dell);
	  UNALLOCA(delta_w);
	  UNALLOCA(delta_x);
	  UNALLOCA(d);
	  UNALLOCA(L);
	  return;
	}
#endif
	delta_x[i] = 1;

	// compute: delta_w = A*delta_x
	dSetZero (delta_w,n);
	lcp.pN_equals_ANC_times_qC (delta_w,delta_x);
	lcp.pN_plusequals_ANi (delta_w,i);
        delta_w[i] = lcp.AiC_times_qC (i,delta_x) + lcp.Aii(i);

	// find index to switch
	int si = i;		// si = switch index
	int si_in_N = 0;	// set to 1 if si in N
	dReal s = -w[i]/delta_w[i];

	if (s <= 0) {
	  dMessage (d_ERR_LCP, "LCP internal error, s <= 0 (s=%.4e)",s);
	  if (i < (n-1)) {
	    dSetZero (x+i,n-i);
	    dSetZero (w+i,n-i);
	  }
	  goto done;
	}

	for (k=0; k < lcp.numN(); k++) {
	  if (delta_w[lcp.indexN(k)] < 0) {
	    dReal s2 = -w[lcp.indexN(k)] / delta_w[lcp.indexN(k)];
	    if (s2 < s) {
	      s = s2;
	      si = lcp.indexN(k);
	      si_in_N = 1;
	    }
	  }
	}
	for (k=0; k < lcp.numC(); k++) {
	  if (delta_x[lcp.indexC(k)] < 0) {
	    dReal s2 = -x[lcp.indexC(k)] / delta_x[lcp.indexC(k)];
	    if (s2 < s) {
	      s = s2;
	      si = lcp.indexC(k);
	      si_in_N = 0;
	    }
	  }
	}

	// apply x = x + s * delta_x
	lcp.pC_plusequals_s_times_qC (x,s,delta_x);
	x[i] += s;
	lcp.pN_plusequals_s_times_qN (w,s,delta_w);
	w[i] += s * delta_w[i];

	// switch indexes between sets if necessary
	if (si==i) {
	  w[i] = 0;
	  lcp.transfer_i_to_C (i);
	  break;
	}
	if (si_in_N) {
          w[si] = 0;
	  lcp.transfer_i_from_N_to_C (si);
	}
	else {
          x[si] = 0;
	  lcp.transfer_i_from_C_to_N (si);
	}
      }
    }
  }

 done:
  lcp.unpermute();

  UNALLOCA (L);
  UNALLOCA (d);
  UNALLOCA (delta_x);
  UNALLOCA (delta_w);
  UNALLOCA (Dell);
  UNALLOCA (ell);
  UNALLOCA (tmp);
  UNALLOCA (Arows);
  UNALLOCA (p);
  UNALLOCA (C);
  UNALLOCA (dummy);
}