1    	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2    	/*                                                                           */
3    	/*                  This file is part of the class library                   */
4    	/*       SoPlex --- the Sequential object-oriented simPlex.                  */
5    	/*                                                                           */
6    	/*    Copyright (C) 1996-2022 Konrad-Zuse-Zentrum                            */
7    	/*                            fuer Informationstechnik Berlin                */
8    	/*                                                                           */
9    	/*  SoPlex is distributed under the terms of the ZIB Academic Licence.       */
10   	/*                                                                           */
11   	/*  You should have received a copy of the ZIB Academic License              */
12   	/*  along with SoPlex; see the file COPYING. If not email to soplex@zib.de.  */
13   	/*                                                                           */
14   	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15   	
16   	#include <assert.h>
17   	#include "soplex/cring.h"
18   	
19   	namespace soplex
20   	{
21   	/* This number is used to decide wether a value is zero
22   	 * or was explicitly set to zero.
23   	 */
24   	/*
25   	#define MARKER     1e-100
26   	*/
27   	
28   	static const Real verySparseFactorRat = 0.001;
29   	static const Real verySparseFactor4rightRat = 0.2;
30   	
31   	/* generic heap management */
32   	static void enQueueMaxRat(int* heap, int* size, int elem)
33   	{
34   	   int i, j;
35   	
36   	   j = (*size)++;
37   	
38   	   while(j > 0)
39   	   {
40   	      i = (j - 1) / 2;
41   	
42   	      if(elem > heap[i])
43   	      {
44   	         heap[j] = heap[i];
45   	         j = i;
46   	      }
47   	      else
48   	         break;
49   	   }
50   	
51   	   heap[j] = elem;
52   	
53   	#ifdef SOPLEX_DEBUG
54   	
55   	   // no NDEBUG define, since this block is really expensive
56   	   for(i = 1; i < *size; ++i)
57   	      for(j = 0; j < i; ++j)
58   	         assert(heap[i] != heap[j]);
59   	
60   	#endif  /* SOPLEX_DEBUG */
61   	}
62   	
63   	static int deQueueMaxRat(int* heap, int* size)
64   	{
65   	   int e, elem;
66   	   int i, j, s;
67   	   int e1, e2;
68   	
69   	   elem = *heap;
70   	   e = heap[s = --(*size)];
71   	   --s;
72   	
73   	   for(j = 0, i = 1; i < s; i = 2 * j + 1)
74   	   {
75   	      e1 = heap[i];
76   	      e2 = heap[i + 1];
77   	
78   	      if(e1 > e2)
79   	      {
80   	         if(e < e1)
81   	         {
82   	            heap[j] = e1;
83   	            j = i;
84   	         }
85   	         else
86   	         {
87   	            heap[j] = e;
88   	            return elem;
89   	         }
90   	      }
91   	      else
92   	      {
93   	         if(e < e2)
94   	         {
95   	            heap[j] = e2;
96   	            j = i + 1;
97   	         }
98   	         else
99   	         {
100  	            heap[j] = e;
101  	            return elem;
102  	         }
103  	      }
104  	   }
105  	
106  	   if(i < *size && e < heap[i])
107  	   {
108  	      heap[j] = heap[i];
109  	      j = i;
110  	   }
111  	
112  	   heap[j] = e;
113  	
114  	   return elem;
115  	}
116  	
117  	static void enQueueMinRat(int* heap, int* size, int elem)
118  	{
119  	   int i, j;
120  	
121  	   j = (*size)++;
122  	
123  	   while(j > 0)
124  	   {
125  	      i = (j - 1) / 2;
126  	
127  	      if(elem < heap[i])
128  	      {
129  	         heap[j] = heap[i];
130  	         j = i;
131  	      }
132  	      else
133  	         break;
134  	   }
135  	
136  	   heap[j] = elem;
137  	
138  	#ifdef SOPLEX_DEBUG
139  	
140  	   // no NDEBUG define, since this block is really expensive
141  	   for(i = 1; i < *size; ++i)
142  	      for(j = 0; j < i; ++j)
143  	         assert(heap[i] != heap[j]);
144  	
145  	#endif  /* SOPLEX_DEBUG */
146  	}
147  	
148  	static int deQueueMinRat(int* heap, int* size)
149  	{
150  	   int e, elem;
151  	   int i, j, s;
152  	   int e1, e2;
153  	
154  	   elem = *heap;
155  	   e = heap[s = --(*size)];
156  	   --s;
157  	
158  	   for(j = 0, i = 1; i < s; i = 2 * j + 1)
159  	   {
160  	      e1 = heap[i];
161  	      e2 = heap[i + 1];
162  	
163  	      if(e1 < e2)
164  	      {
165  	         if(e > e1)
166  	         {
167  	            heap[j] = e1;
168  	            j = i;
169  	         }
170  	         else
171  	         {
172  	            heap[j] = e;
173  	            return elem;
174  	         }
175  	      }
176  	      else
177  	      {
178  	         if(e > e2)
179  	         {
180  	            heap[j] = e2;
181  	            j = i + 1;
182  	         }
183  	         else
184  	         {
185  	            heap[j] = e;
186  	            return elem;
187  	         }
188  	      }
189  	   }
190  	
191  	   if(i < *size && e > heap[i])
192  	   {
193  	      heap[j] = heap[i];
194  	      j = i;
195  	   }
196  	
197  	   heap[j] = e;
198  	
199  	   return elem;
200  	}
201  	
202  	/************************************************************/
203  	inline CLUFactorRational::Temp::Temp()
204  	   : s_mark(0)
205  	   , s_cact(0)
206  	   , stage(0)
207  	   , pivot_col(0)
208  	   , pivot_colNZ(0)
209  	   , pivot_row(0)
210  	   , pivot_rowNZ(0)
211  	{}
212  	
213  	inline void CLUFactorRational::Temp::init(int p_dim)
214  	{
215  	   s_max.reDim(p_dim);
216  	   spx_realloc(s_cact, p_dim);
217  	   spx_realloc(s_mark, p_dim);
218  	   stage = 0;
219  	}
220  	
221  	inline void CLUFactorRational::Temp::clear()
222  	{
223  	   if(s_mark != 0)
224  	      spx_free(s_mark);
225  	
226  	   if(s_cact != 0)
227  	      spx_free(s_cact);
228  	
229  	   if(pivot_col != 0)
230  	      spx_free(pivot_col);
231  	
232  	   if(pivot_colNZ != 0)
233  	      spx_free(pivot_colNZ);
234  	
235  	   if(pivot_row != 0)
236  	      spx_free(pivot_row);
237  	
238  	   if(pivot_rowNZ != 0)
239  	      spx_free(pivot_rowNZ);
240  	
241  	   try
242  	   {
243  	      s_max.reDim(0);
244  	   }
245  	   catch(const SPxMemoryException& x)
246  	   {
(1) Event exception_thrown: An exception of type "soplex::SPxMemoryException const" is thrown.
247  	      throw x;
248  	   }
249  	}
250  	
(1) Event exn_spec_violation: An exception of type "soplex::SPxMemoryException const" is thrown but the exception specification "noexcept" doesn't allow it to be thrown. This will result in a call to terminate().
Also see events: [fun_call_w_exception]
251  	inline CLUFactorRational::Temp::~Temp()
252  	{
(2) Event fun_call_w_exception: Called function throws an exception of type "soplex::SPxMemoryException const". [details]
Also see events: [exn_spec_violation]
253  	   clear();
254  	}
255  	
256  	/************************************************************/
257  	inline void CLUFactorRational::initPerm()
258  	{
259  	
260  	   for(int i = 0; i < thedim; ++i)
261  	      row.orig[i] = row.perm[i] = col.orig[i] = col.perm[i] = -1;
262  	}
263  	
264  	/*****************************************************************************/
265  	
266  	inline void CLUFactorRational::setPivot(const int p_stage,
267  	                                        const int p_col,
268  	                                        const int p_row,
269  	                                        const Rational& val)
270  	{
271  	   assert(row.perm[p_row] < 0);
272  	   assert(col.perm[p_col] < 0);
273  	
274  	   row.orig[p_stage] = p_row;
275  	   col.orig[p_stage] = p_col;
276  	   row.perm[p_row]   = p_stage;
277  	   col.perm[p_col]   = p_stage;
278  	   diag[p_row]       = 1.0 / val;
279  	
280  	   if(spxAbs(diag[p_row]) > maxabs)
281  	      maxabs = spxAbs(diag[p_row]);
282  	}
283  	
284  	/*****************************************************************************/
285  	/*
286  	 *      Perform garbage collection on row file
287  	 */
288  	inline void CLUFactorRational::packRows()
289  	{
290  	   int n, i, j, l_row;
291  	   Dring* ring, *list;
292  	
293  	   int* l_ridx = u.row.idx;
294  	   VectorRational& l_rval = u.row.val;
295  	   int* l_rlen = u.row.len;
296  	   int* l_rmax = u.row.max;
297  	   int* l_rbeg = u.row.start;
298  	
299  	   n = 0;
300  	   list = &(u.row.list);
301  	
302  	   for(ring = list->next; ring != list; ring = ring->next)
303  	   {
304  	      l_row = ring->idx;
305  	
306  	      if(l_rbeg[l_row] != n)
307  	      {
308  	         do
309  	         {
310  	            l_row = ring->idx;
311  	            i = l_rbeg[l_row];
312  	            assert(l_rlen[l_row] <= l_rmax[l_row]);
313  	            l_rbeg[l_row] = n;
314  	            l_rmax[l_row] = l_rlen[l_row];
315  	            j = i + l_rlen[l_row];
316  	
317  	            for(; i < j; ++i, ++n)
318  	            {
319  	               assert(n <= i);
320  	               l_ridx[n] = l_ridx[i];
321  	               l_rval[n] = l_rval[i];
322  	            }
323  	
324  	            ring = ring->next;
325  	         }
326  	         while(ring != list);
327  	
328  	         goto terminatePackRows;
329  	      }
330  	
331  	      n += l_rlen[l_row];
332  	
333  	      l_rmax[l_row] = l_rlen[l_row];
334  	   }
335  	
336  	terminatePackRows:
337  	
338  	   u.row.max[thedim] = 0;
339  	   u.row.used = n;
340  	}
341  	
342  	/*****************************************************************************/
343  	/*
344  	 *      Perform garbage collection on column file
345  	 */
346  	inline void CLUFactorRational::forestPackColumns()
347  	{
348  	   int n, i, j, colno;
349  	   Dring* ring, *list;
350  	
351  	   VectorRational& cval = u.col.val;
352  	   int* cidx = u.col.idx;
353  	   int* clen = u.col.len;
354  	   int* cmax = u.col.max;
355  	   int* cbeg = u.col.start;
356  	
357  	   n = 0;
358  	   list = &u.col.list;
359  	
360  	   for(ring = list->next; ring != list; ring = ring->next)
361  	   {
362  	      colno = ring->idx;
363  	
364  	      if(cbeg[colno] != n)
365  	      {
366  	         do
367  	         {
368  	            colno = ring->idx;
369  	            i = cbeg[colno];
370  	            cbeg[colno] = n;
371  	            cmax[colno] = clen[colno];
372  	            j = i + clen[colno];
373  	
374  	            for(; i < j; ++i)
375  	            {
376  	               cval[n] = cval[i];
377  	               cidx[n++] = cidx[i];
378  	            }
379  	
380  	            ring = ring->next;
381  	         }
382  	         while(ring != list);
383  	
384  	         goto terminatePackColumns;
385  	      }
386  	
387  	      n += clen[colno];
388  	
389  	      cmax[colno] = clen[colno];
390  	   }
391  	
392  	terminatePackColumns :
393  	
394  	   u.col.used = n;
395  	   u.col.max[thedim] = 0;
396  	}
397  	
398  	/*
399  	 *      Make row of fac large enough to hold len nonzeros.
400  	 */
401  	inline void CLUFactorRational::remaxRow(int p_row, int len)
402  	{
403  	   assert(u.row.max[p_row] < len);
404  	
405  	   if(u.row.elem[p_row].next == &(u.row.list))      /* last in row file */
406  	   {
407  	      int delta = len - u.row.max[p_row];
408  	
409  	      if(delta > u.row.val.dim() - u.row.used)
410  	      {
411  	         packRows();
412  	         delta = len - u.row.max[p_row];  // packRows() changes u.row.max[] !
413  	
414  	         if(u.row.val.dim() < rowMemMult * u.row.used + len)
415  	            minRowMem(2 * u.row.used + len);
416  	
417  	         /* minRowMem(rowMemMult * u.row.used + len); */
418  	      }
419  	
420  	      assert(delta <= u.row.val.dim() - u.row.used
421  	
422  	             && "ERROR: could not allocate memory for row file");
423  	
424  	      u.row.used += delta;
425  	      u.row.max[p_row] = len;
426  	   }
427  	   else                        /* row must be moved to end of row file */
428  	   {
429  	      int i, j, k;
430  	      VectorRational& val = u.row.val;
431  	      Dring* ring;
432  	
433  	      if(len > u.row.val.dim() - u.row.used)
434  	      {
435  	         packRows();
436  	
437  	         if(u.row.val.dim() < rowMemMult * u.row.used + len)
438  	            minRowMem(2 * u.row.used + len);
439  	
440  	         /* minRowMem(rowMemMult * u.row.used + len);*/
441  	      }
442  	
443  	      assert(len <= u.row.val.dim() - u.row.used
444  	
445  	             && "ERROR: could not allocate memory for row file");
446  	
447  	      int* idx = u.row.idx;
448  	      j = u.row.used;
449  	      i = u.row.start[p_row];
450  	      k = u.row.len[p_row] + i;
451  	      u.row.start[p_row] = j;
452  	      u.row.used += len;
453  	
454  	      u.row.max[u.row.elem[p_row].prev->idx] += u.row.max[p_row];
455  	      u.row.max[p_row] = len;
456  	      removeDR(u.row.elem[p_row]);
457  	      ring = u.row.list.prev;
458  	      init2DR(u.row.elem[p_row], *ring);
459  	
460  	      for(; i < k; ++i, ++j)
461  	      {
462  	         val[j] = val[i];
463  	         idx[j] = idx[i];
464  	      }
465  	   }
466  	
467  	   assert(u.row.start[u.row.list.prev->idx] + u.row.max[u.row.list.prev->idx]
468  	
469  	          == u.row.used);
470  	}
471  	
472  	/*************************************************************************/
473  	/*
474  	 *      Perform garbage collection on column file
475  	 */
476  	inline void CLUFactorRational::packColumns()
477  	{
478  	   int n, i, j, l_col;
479  	   Dring* ring, *list;
480  	
481  	   int* l_cidx = u.col.idx;
482  	   int* l_clen = u.col.len;
483  	   int* l_cmax = u.col.max;
484  	   int* l_cbeg = u.col.start;
485  	
486  	   n = 0;
487  	   list = &(u.col.list);
488  	
489  	   for(ring = list->next; ring != list; ring = ring->next)
490  	   {
491  	      l_col = ring->idx;
492  	
493  	      if(l_cbeg[l_col] != n)
494  	      {
495  	         do
496  	         {
497  	            l_col = ring->idx;
498  	            i = l_cbeg[l_col];
499  	            l_cbeg[l_col] = n;
500  	            l_cmax[l_col] = l_clen[l_col];
501  	            j = i + l_clen[l_col];
502  	
503  	            for(; i < j; ++i)
504  	               l_cidx[n++] = l_cidx[i];
505  	
506  	            ring = ring->next;
507  	         }
508  	         while(ring != list);
509  	
510  	         goto terminatePackColumns;
511  	      }
512  	
513  	      n += l_clen[l_col];
514  	
515  	      l_cmax[l_col] = l_clen[l_col];
516  	   }
517  	
518  	terminatePackColumns :
519  	
520  	   u.col.used = n;
521  	   u.col.max[thedim] = 0;
522  	}
523  	
524  	/*
525  	 *      Make column col of fac large enough to hold len nonzeros.
526  	 */
527  	inline void CLUFactorRational::remaxCol(int p_col, int len)
528  	{
529  	   assert(u.col.max[p_col] < len);
530  	
531  	   if(u.col.elem[p_col].next == &(u.col.list))      /* last in column file */
532  	   {
533  	      int delta = len - u.col.max[p_col];
534  	
535  	      if(delta > u.col.size - u.col.used)
536  	      {
537  	         packColumns();
538  	         delta = len - u.col.max[p_col];
539  	
540  	         if(u.col.size < colMemMult * u.col.used + len)
541  	            minColMem(2 * u.col.used + len);
542  	
543  	         /* minColMem(colMemMult * u.col.used + len); */
544  	      }
545  	
546  	      assert(delta <= u.col.size - u.col.used
547  	
548  	             && "ERROR: could not allocate memory for column file");
549  	
550  	      u.col.used += delta;
551  	      u.col.max[p_col] = len;
552  	   }
553  	
554  	   else                        /* column must be moved to end of column file */
555  	   {
556  	      int i, j, k;
557  	      int* idx;
558  	      Dring* ring;
559  	
560  	      if(len > u.col.size - u.col.used)
561  	      {
562  	         packColumns();
563  	
564  	         if(u.col.size < colMemMult * u.col.used + len)
565  	            minColMem(2 * u.col.used + len);
566  	
567  	         /* minColMem(colMemMult * u.col.used + len); */
568  	      }
569  	
570  	      assert(len <= u.col.size - u.col.used
571  	
572  	             && "ERROR: could not allocate memory for column file");
573  	
574  	      j = u.col.used;
575  	      i = u.col.start[p_col];
576  	      k = u.col.len[p_col] + i;
577  	      u.col.start[p_col] = j;
578  	      u.col.used += len;
579  	
580  	      u.col.max[u.col.elem[p_col].prev->idx] += u.col.max[p_col];
581  	      u.col.max[p_col] = len;
582  	      removeDR(u.col.elem[p_col]);
583  	      ring = u.col.list.prev;
584  	      init2DR(u.col.elem[p_col], *ring);
585  	
586  	      idx = u.col.idx;
587  	
588  	      for(; i < k; ++i)
589  	         idx[j++] = idx[i];
590  	   }
591  	}
592  	
593  	/*
594  	 *      Make column col of fac large enough to hold len nonzeros.
595  	 */
596  	inline void CLUFactorRational::forestReMaxCol(int p_col, int len)
597  	{
598  	   assert(u.col.max[p_col] < len);
599  	
600  	   if(u.col.elem[p_col].next == &(u.col.list))      /* last in column file */
601  	   {
602  	      int delta = len - u.col.max[p_col];
603  	
604  	      if(delta > u.col.size - u.col.used)
605  	      {
606  	         forestPackColumns();
607  	         delta = len - u.col.max[p_col];
608  	
609  	         if(u.col.size < colMemMult * u.col.used + len)
610  	            forestMinColMem(int(colMemMult * u.col.used + len));
611  	      }
612  	
613  	      assert(delta <= u.col.size - u.col.used
614  	
615  	             && "ERROR: could not allocate memory for column file");
616  	
617  	      u.col.used += delta;
618  	      u.col.max[p_col] = len;
619  	   }
620  	
621  	   else                        /* column must be moved to end of column file */
622  	   {
623  	      int i, j, k;
624  	      int* idx = u.col.idx;
625  	      VectorRational& val = u.col.val;
626  	      Dring* ring;
627  	
628  	      if(len > u.col.size - u.col.used)
629  	      {
630  	         forestPackColumns();
631  	
632  	         if(u.col.size < colMemMult * u.col.used + len)
633  	            forestMinColMem(int(colMemMult * u.col.used + len));
634  	      }
635  	
636  	      assert(len <= u.col.size - u.col.used
637  	
638  	             && "ERROR: could not allocate memory for column file");
639  	
640  	      j = u.col.used;
641  	      i = u.col.start[p_col];
642  	      k = u.col.len[p_col] + i;
643  	      u.col.start[p_col] = j;
644  	      u.col.used += len;
645  	
646  	      u.col.max[u.col.elem[p_col].prev->idx] += u.col.max[p_col];
647  	      u.col.max[p_col] = len;
648  	      removeDR(u.col.elem[p_col]);
649  	      ring = u.col.list.prev;
650  	      init2DR(u.col.elem[p_col], *ring);
651  	
652  	      for(; i < k; ++i)
653  	      {
654  	         val[j] = val[i];
655  	         idx[j++] = idx[i];
656  	      }
657  	   }
658  	}
659  	
660  	/*****************************************************************************/
661  	
662  	/**
663  	 *   \brief Performs the Forrest-Tomlin update of the LU factorization.
664  	 *
665  	 *   BH: I suppose this is implemented as described in UH Suhl, LM Suhl: A fast LU
666  	 *       update for linear programming, Annals of OR 43, p. 33-47, 1993.
667  	 *
668  	 *   @param  p_col      Index of basis column to replace.
669  	 *   @param  p_work     Dense vector to substitute in the basis.
670  	 *   @param  num        Number of nonzeros in vector represented by p_work.
671  	 *   @param  nonz       Indices of nonzero elements in vector p_work.
672  	 *
673  	 *   The parameters num and nonz are used for the following optimization: If both
674  	 *   are nonzero, indices of the nonzero elements provided in nonz (num giving
675  	 *   their number) allow to access only those nonzero entries.  Otherwise we have
676  	 *   to go through the entire dense vector element by element.
677  	 *
678  	 *   After copying p_work into U, p_work is used to expand the row r, which is
679  	 *   needed to restore the triangular structure of U.
680  	 *
681  	 *   Also num and nonz are used to maintain a heap if there are only very few
682  	 *   nonzeros to be eliminated. This is plainly wrong if the method is called with
683  	 *   nonz==0, see todo at the corresponding place below.
684  	 *
685  	 *   @throw SPxStatusException if the loaded matrix is singular
686  	 *
687  	 *   @todo Use an extra member variable as a buffer for working with the dense
688  	 *         row instead of misusing p_work. I think that should be as efficient and
689  	 *         much cleaner.
690  	 */
691  	
692  	inline void CLUFactorRational::forestUpdate(int p_col, Rational* p_work, int num, int* nonz)
693  	{
694  	   int i, j, k, h, m, n;
695  	   int ll, c, r, rowno;
696  	   Rational x;
697  	
698  	   int* lbeg = l.start;
699  	
700  	   VectorRational& cval = u.col.val;
701  	   int* cidx = u.col.idx;
702  	   int* cmax = u.col.max;
703  	   int* clen = u.col.len;
704  	   int* cbeg = u.col.start;
705  	
706  	   VectorRational& rval = u.row.val;
707  	   int* ridx = u.row.idx;
708  	   int* rmax = u.row.max;
709  	   int* rlen = u.row.len;
710  	   int* rbeg = u.row.start;
711  	
712  	   int* rperm = row.perm;
713  	   int* rorig = row.orig;
714  	   int* cperm = col.perm;
715  	   int* corig = col.orig;
716  	
717  	   Rational l_maxabs = maxabs;
718  	   int dim = thedim;
719  	
720  	   /*  Remove column p_col from U
721  	    */
722  	   j = cbeg[p_col];
723  	   i = clen[p_col];
724  	   nzCnt -= i;
725  	
726  	   for(i += j - 1; i >= j; --i)
727  	   {
728  	      m = cidx[i];          // remove column p_col from row m
729  	      k = rbeg[m];
730  	      h = --(rlen[m]) + k;    // decrease length of row m
731  	
732  	      while(ridx[k] != p_col)
733  	         ++k;
734  	
735  	      assert(k <= h);       // k is the position of p_col, h is last position
736  	
737  	      ridx[k] = ridx[h];    // store last index at the position of p_col
738  	
739  	      rval[k] = rval[h];
740  	   }
741  	
742  	   /*  Insert new vector column p_col thereby determining the highest permuted
743  	    *       row index r.
744  	    *
745  	    *       Distinguish between optimized call (num > 0, nonz != 0) and
746  	    *       non-optimized one.
747  	    */
748  	   assert(num);   // otherwise the assert( nonz != 0 ) below should fail
749  	
750  	   if(num)
751  	   {
752  	      // Optimized call.
753  	      assert(nonz != 0);
754  	
755  	      clen[p_col] = 0;
756  	
757  	      if(num > cmax[p_col])
758  	         forestReMaxCol(p_col, num);
759  	
760  	      cidx = u.col.idx;
761  	
762  	      cval = u.col.val;
763  	
764  	      k = cbeg[p_col];
765  	
766  	      r = 0;
767  	
768  	      for(j = 0; j < num; ++j)
769  	      {
770  	         i = nonz[j];
771  	         x = p_work[i];
772  	         p_work[i] = 0;
773  	
774  	         if(x != 0)
775  	         {
776  	            if(spxAbs(x) > l_maxabs)
777  	               l_maxabs = spxAbs(x);
778  	
779  	            /* insert to column file */
780  	            assert(k - cbeg[p_col] < cmax[p_col]);
781  	
782  	            cval[k] = x;
783  	
784  	            cidx[k++] = i;
785  	
786  	            /* insert to row file */
787  	            if(rmax[i] <= rlen[i])
788  	            {
789  	               remaxRow(i, rlen[i] + 1);
790  	               rval = u.row.val;
791  	               ridx = u.row.idx;
792  	            }
793  	
794  	            h = rbeg[i] + (rlen[i])++;
795  	
796  	            rval[h] = x;
797  	            ridx[h] = p_col;
798  	
799  	            /* check permuted row index */
800  	
801  	            if(rperm[i] > r)
802  	               r = rperm[i];
803  	         }
804  	      }
805  	
806  	      nzCnt += (clen[p_col] = k - cbeg[p_col]);
807  	   }
808  	   else
809  	   {
810  	      // Non-optimized call: We have to access all elements of p_work.
811  	      assert(nonz == 0);
812  	
813  	      /*
814  	       *      clen[col] = 0;
815  	       *      reMaxCol(fac, col, dim);
816  	       */
817  	      cidx = u.col.idx;
818  	      cval = u.col.val;
819  	      k = cbeg[p_col];
820  	      j = k + cmax[p_col];
821  	      r = 0;
822  	
823  	      for(i = 0; i < dim; ++i)
824  	      {
825  	         x = p_work[i];
826  	         p_work[i] = 0;
827  	
828  	         if(x != 0)
829  	         {
830  	            if(spxAbs(x) > l_maxabs)
831  	               l_maxabs = spxAbs(x);
832  	
833  	            /* insert to column file */
834  	            if(k >= j)
835  	            {
836  	               clen[p_col] = k - cbeg[p_col];
837  	               forestReMaxCol(p_col, dim - i);
838  	               cidx = u.col.idx;
839  	               cval = u.col.val;
840  	               k = cbeg[p_col];
841  	               j = k + cmax[p_col];
842  	               k += clen[p_col];
843  	            }
844  	
845  	            assert(k - cbeg[p_col] < cmax[p_col]);
846  	
847  	            cval[k] = x;
848  	            cidx[k++] = i;
849  	
850  	            /* insert to row file */
851  	
852  	            if(rmax[i] <= rlen[i])
853  	            {
854  	               remaxRow(i, rlen[i] + 1);
855  	               rval = u.row.val;
856  	               ridx = u.row.idx;
857  	            }
858  	
859  	            h = rbeg[i] + (rlen[i])++;
860  	
861  	            rval[h] = x;
862  	            ridx[h] = p_col;
863  	
864  	            /* check permuted row index */
865  	
866  	            if(rperm[i] > r)
867  	               r = rperm[i];
868  	         }
869  	      }
870  	
871  	      nzCnt += (clen[p_col] = k - cbeg[p_col]);
872  	
873  	      if(cbeg[p_col] + cmax[p_col] == u.col.used)
874  	      {
875  	         u.col.used -= cmax[p_col];
876  	         cmax[p_col] = clen[p_col];
877  	         u.col.used += cmax[p_col];
878  	      }
879  	   }
880  	
881  	   c = cperm[p_col];
882  	
883  	   if(r > c)                          /* Forest Tomlin update */
884  	   {
885  	      /*      update permutations
886  	       */
887  	      j = rorig[c];
888  	
889  	      // memmove is more efficient than a for loop
890  	      // for ( i = c; i < r; ++i )
891  	      //    rorig[i] = rorig[i + 1];
892  	      memmove(&rorig[c], &rorig[c + 1], (unsigned int)(r - c) * sizeof(int));
893  	
894  	      rorig[r] = j;
895  	
896  	      for(i = c; i <= r; ++i)
897  	         rperm[rorig[i]] = i;
898  	
899  	      j = corig[c];
900  	
901  	      // memmove is more efficient than a for loop
902  	      // for ( i = c; i < r; ++i )
903  	      //    corig[i] = corig[i + 1];
904  	      memmove(&corig[c], &corig[c + 1], (unsigned int)(r - c) * sizeof(int));
905  	
906  	      corig[r] = j;
907  	
908  	      for(i = c; i <= r; ++i)
909  	         cperm[corig[i]] = i;
910  	
911  	
912  	      rowno = rorig[r];
913  	
914  	      j = rbeg[rowno];
915  	
916  	      i = rlen[rowno];
917  	
918  	      nzCnt -= i;
919  	
920  	      if(i < verySparseFactorRat * (dim - c))      // few nonzeros to be eliminated
921  	      {
922  	         /**
923  	          *          The following assert is obviously violated if this method is called
924  	          *          with nonzero==0.
925  	          *
926  	          *          @todo Use an extra member variable as a buffer for the heap instead of
927  	          *                misusing nonz and num. The method enQueueMinRat() seems to
928  	          *                sort the nonzeros or something, for which it only needs
929  	          *                some empty vector of size num.
930  	          */
931  	         assert(nonz != 0);
932  	
933  	         /*  move row r from U to p_work
934  	          */
935  	         num = 0;
936  	
937  	         for(i += j - 1; i >= j; --i)
938  	         {
939  	            k = ridx[i];
940  	            p_work[k] = rval[i];
941  	            enQueueMinRat(nonz, &num, cperm[k]);
942  	            m = --(clen[k]) + cbeg[k];
943  	
944  	            for(h = m; cidx[h] != rowno; --h)
945  	               ;
946  	
947  	            cidx[h] = cidx[m];
948  	
949  	            cval[h] = cval[m];
950  	         }
951  	
952  	
953  	         /*  Eliminate row r from U to L file
954  	          */
955  	         ll = makeLvec(r - c, rowno);
956  	
957  	         VectorRational& lval = l.val;
958  	         int* lidx = l.idx;
959  	
960  	         assert((num == 0) || (nonz != 0));
961  	
962  	         /* for(i = c; i < r; ++i)       */
963  	         while(num)
964  	         {
965  	#ifndef NDEBUG
966  	            // The numbers seem to be often 1e-100, is this ok ?
967  	
968  	            for(i = 0; i < num; ++i)
969  	               assert(p_work[corig[nonz[i]]] != 0);
970  	
971  	#endif // NDEBUG
972  	            i = deQueueMinRat(nonz, &num);
973  	
974  	            if(i == r)
975  	               break;
976  	
977  	            k = corig[i];
978  	
979  	            assert(p_work[k] != 0);
980  	
981  	            n = rorig[i];
982  	
983  	            x = p_work[k] * diag[n];
984  	
985  	            lidx[ll] = n;
986  	
987  	            lval[ll] = x;
988  	
989  	            p_work[k] = 0;
990  	
991  	            ll++;
992  	
993  	            if(spxAbs(x) > l_maxabs)
994  	               l_maxabs = spxAbs(x);
995  	
996  	            j = rbeg[n];
997  	
998  	            m = rlen[n] + j;
999  	
1000 	            for(; j < m; ++j)
1001 	            {
1002 	               int jj = ridx[j];
1003 	               Rational y = p_work[jj];
1004 	
1005 	               if(y == 0)
1006 	                  enQueueMinRat(nonz, &num, cperm[jj]);
1007 	
1008 	               y -= x * rval[j];
1009 	
1010 	               //p_work[jj] = y + (( y == 0 ) ? MARKER : 0 );
1011 	               p_work[jj] = y;
1012 	            }
1013 	         }
1014 	
1015 	         if(lbeg[l.firstUnused - 1] == ll)
1016 	            (l.firstUnused)--;
1017 	         else
1018 	            lbeg[l.firstUnused] = ll;
1019 	
1020 	
1021 	         /*  Set diagonal value
1022 	          */
1023 	         if(i != r)
1024 	         {
1025 	            stat = SLinSolverRational::SINGULAR;
1026 	            throw SPxStatusException("XFORE01 The loaded matrix is singular");
1027 	         }
1028 	
1029 	         k = corig[r];
1030 	
1031 	         x = p_work[k];
1032 	         diag[rowno] = 1 / x;
1033 	         p_work[k] = 0;
1034 	
1035 	
1036 	         /*  make row large enough to fit all nonzeros.
1037 	          */
1038 	
1039 	         if(rmax[rowno] < num)
1040 	         {
1041 	            rlen[rowno] = 0;
1042 	            remaxRow(rowno, num);
1043 	            rval = u.row.val;
1044 	            ridx = u.row.idx;
1045 	         }
1046 	
1047 	         nzCnt += num;
1048 	
1049 	         /*  Insert work to updated row thereby clearing work;
1050 	          */
1051 	         n = rbeg[rowno];
1052 	
1053 	         for(i = 0; i < num; ++i)
1054 	         {
1055 	            j = corig[nonz[i]];
1056 	            x = p_work[j];
1057 	
1058 	            // BH 2005-08-24: This if is very important. It may well happen that
1059 	            // during the elimination of row r a nonzero elements cancels out
1060 	            // and becomes zero. This would lead to an infinite loop in the
1061 	            // above elimination code, since the corresponding column index would
1062 	            // be enqueued for further elimination again and agian.
1063 	
1064 	            if(x != 0)
1065 	            {
1066 	               if(spxAbs(x) > l_maxabs)
1067 	                  l_maxabs = spxAbs(x);
1068 	
1069 	               ridx[n] = j;
1070 	
1071 	               rval[n] = x;
1072 	
1073 	               p_work[j] = 0;
1074 	
1075 	               ++n;
1076 	
1077 	               if(clen[j] >= cmax[j])
1078 	               {
1079 	                  forestReMaxCol(j, clen[j] + 1);
1080 	                  cidx = u.col.idx;
1081 	                  cval = u.col.val;
1082 	               }
1083 	
1084 	               cval[cbeg[j] + clen[j]] = x;
1085 	
1086 	               cidx[cbeg[j] + clen[j]++] = rowno;
1087 	            }
1088 	         }
1089 	
1090 	         rlen[rowno] = n - rbeg[rowno];
1091 	      }
1092 	      else            /* few nonzeros to be eliminated        */
1093 	      {
1094 	         /*  move row r from U to p_work
1095 	          */
1096 	         for(i += j - 1; i >= j; --i)
1097 	         {
1098 	            k = ridx[i];
1099 	            p_work[k] = rval[i];
1100 	            m = --(clen[k]) + cbeg[k];
1101 	
1102 	            for(h = m; cidx[h] != rowno; --h)
1103 	               ;
1104 	
1105 	            cidx[h] = cidx[m];
1106 	
1107 	            cval[h] = cval[m];
1108 	         }
1109 	
1110 	
1111 	         /*  Eliminate row r from U to L file
1112 	          */
1113 	         ll = makeLvec(r - c, rowno);
1114 	
1115 	         VectorRational& lval = l.val;
1116 	         int* lidx = l.idx;
1117 	
1118 	         for(i = c; i < r; ++i)
1119 	         {
1120 	            k = corig[i];
1121 	
1122 	            if(p_work[k] != 0)
1123 	            {
1124 	               n = rorig[i];
1125 	               x = p_work[k] * diag[n];
1126 	               lidx[ll] = n;
1127 	               lval[ll] = x;
1128 	               p_work[k] = 0;
1129 	               ll++;
1130 	
1131 	               if(spxAbs(x) > l_maxabs)
1132 	                  l_maxabs = spxAbs(x);
1133 	
1134 	               j = rbeg[n];
1135 	
1136 	               m = rlen[n] + j;
1137 	
1138 	               for(; j < m; ++j)
1139 	                  p_work[ridx[j]] -= x * rval[j];
1140 	            }
1141 	         }
1142 	
1143 	         if(lbeg[l.firstUnused - 1] == ll)
1144 	            (l.firstUnused)--;
1145 	         else
1146 	            lbeg[l.firstUnused] = ll;
1147 	
1148 	
1149 	         /*  Set diagonal value
1150 	          */
1151 	         k = corig[r];
1152 	
1153 	         x = p_work[k];
1154 	
1155 	         if(x == 0)
1156 	         {
1157 	            stat = SLinSolverRational::SINGULAR;
1158 	            throw SPxStatusException("XFORE02 The loaded matrix is singular");
1159 	            //            return;
1160 	         }
1161 	
1162 	         diag[rowno] = 1 / x;
1163 	
1164 	         p_work[k] = 0;
1165 	
1166 	
1167 	         /*  count remaining nonzeros in work and make row large enough
1168 	          *  to fit them all.
1169 	          */
1170 	         n = 0;
1171 	
1172 	         for(i = r + 1; i < dim; ++i)
1173 	            if(p_work[corig[i]] != 0)
1174 	               n++;
1175 	
1176 	         if(rmax[rowno] < n)
1177 	         {
1178 	            rlen[rowno] = 0;
1179 	            remaxRow(rowno, n);
1180 	            rval = u.row.val;
1181 	            ridx = u.row.idx;
1182 	         }
1183 	
1184 	         nzCnt += n;
1185 	
1186 	         /*  Insert p_work to updated row thereby clearing p_work;
1187 	          */
1188 	         n = rbeg[rowno];
1189 	
1190 	         for(i = r + 1; i < dim; ++i)
1191 	         {
1192 	            j = corig[i];
1193 	            x = p_work[j];
1194 	
1195 	            if(x != 0)
1196 	            {
1197 	               if(spxAbs(x) > l_maxabs)
1198 	                  l_maxabs = spxAbs(x);
1199 	
1200 	               ridx[n] = j;
1201 	
1202 	               rval[n] = x;
1203 	
1204 	               p_work[j] = 0;
1205 	
1206 	               ++n;
1207 	
1208 	               if(clen[j] >= cmax[j])
1209 	               {
1210 	                  forestReMaxCol(j, clen[j] + 1);
1211 	                  cidx = u.col.idx;
1212 	                  cval = u.col.val;
1213 	               }
1214 	
1215 	               cval[cbeg[j] + clen[j]] = x;
1216 	
1217 	               cidx[cbeg[j] + clen[j]++] = rowno;
1218 	            }
1219 	         }
1220 	
1221 	         rlen[rowno] = n - rbeg[rowno];
1222 	      }
1223 	   }
1224 	
1225 	   else if(r == c)
1226 	   {
1227 	      /*  Move diagonal element to diag.  Note, that it must be the last
1228 	       *  element, since it has just been inserted above.
1229 	       */
1230 	      rowno = rorig[r];
1231 	      i = rbeg[rowno] + --(rlen[rowno]);
1232 	      diag[rowno] = 1 / rval[i];
1233 	
1234 	      for(j = i = --(clen[p_col]) + cbeg[p_col]; cidx[i] != rowno; --i)
1235 	         ;
1236 	
1237 	      cidx[i] = cidx[j];
1238 	
1239 	      cval[i] = cval[j];
1240 	   }
1241 	   else /* r < c */
1242 	   {
1243 	      stat = SLinSolverRational::SINGULAR;
1244 	      throw SPxStatusException("XFORE03 The loaded matrix is singular");
1245 	      //      return;
1246 	   }
1247 	
1248 	   maxabs = l_maxabs;
1249 	
1250 	   assert(isConsistent());
1251 	   stat = SLinSolverRational::OK;
1252 	}
1253 	
1254 	inline void CLUFactorRational::update(int p_col, Rational* p_work, const int* p_idx, int num)
1255 	{
1256 	   int ll, i, j;
1257 	   Rational x, rezi;
1258 	
1259 	   assert(p_work[p_col] != 0);
1260 	   rezi = 1 / p_work[p_col];
1261 	   p_work[p_col] = 0;
1262 	
1263 	   ll = makeLvec(num, p_col);
1264 	   //   ll = fac->makeLvec(num, col);
1265 	   VectorRational& lval = l.val;
1266 	   int* lidx = l.idx;
1267 	
1268 	   for(i = num - 1; (j = p_idx[i]) != p_col; --i)
1269 	   {
1270 	      lidx[ll] = j;
1271 	      lval[ll] = rezi * p_work[j];
1272 	      p_work[j] = 0;
1273 	      ++ll;
1274 	   }
1275 	
1276 	   lidx[ll] = p_col;
1277 	
1278 	   lval[ll] = 1 - rezi;
1279 	   ++ll;
1280 	
1281 	   for(--i; i >= 0; --i)
1282 	   {
1283 	      j = p_idx[i];
1284 	      lidx[ll] = j;
1285 	      lval[ll] = x = rezi * p_work[j];
1286 	      p_work[j] = 0;
1287 	      ++ll;
1288 	
1289 	      if(spxAbs(x) > maxabs)
1290 	         maxabs = spxAbs(x);
1291 	   }
1292 	
1293 	   stat = SLinSolverRational::OK;
1294 	}
1295 	
1296 	inline void CLUFactorRational::updateNoClear(
1297 	   int p_col,
1298 	   const Rational* p_work,
1299 	   const int* p_idx,
1300 	   int num)
1301 	{
1302 	   int ll, i, j;
1303 	   Rational x, rezi;
1304 	
1305 	   assert(p_work[p_col] != 0);
1306 	   rezi = 1 / p_work[p_col];
1307 	   ll = makeLvec(num, p_col);
1308 	   //ll = fac->makeLvec(num, col);
1309 	   VectorRational& lval = l.val;
1310 	   int* lidx = l.idx;
1311 	
1312 	   for(i = num - 1; (j = p_idx[i]) != p_col; --i)
1313 	   {
1314 	      lidx[ll] = j;
1315 	      lval[ll] = rezi * p_work[j];
1316 	      ++ll;
1317 	   }
1318 	
1319 	   lidx[ll] = p_col;
1320 	
1321 	   lval[ll] = 1 - rezi;
1322 	   ++ll;
1323 	
1324 	   for(--i; i >= 0; --i)
1325 	   {
1326 	      j = p_idx[i];
1327 	      lidx[ll] = j;
1328 	      lval[ll] = x = rezi * p_work[j];
1329 	      ++ll;
1330 	
1331 	      if(spxAbs(x) > maxabs)
1332 	         maxabs = spxAbs(x);
1333 	   }
1334 	
1335 	   stat = SLinSolverRational::OK;
1336 	}
1337 	
1338 	/*****************************************************************************/
1339 	/*
1340 	 *      Temporary data structures.
1341 	 */
1342 	
1343 	/*
1344 	 *        For the i=th column the situation might look like this:
1345 	 *
1346 	 * \begin{verbatim}
1347 	 *        idx     = ....................iiiIIIIII-----..............
1348 	 *        cbeg[i] =                     ^
1349 	 *        cact[i] =                        +----+
1350 	 *        clen[i] =                     +-------+
1351 	 *        cmax[i] =                     +------------+
1352 	 *
1353 	 *        Indices clen[i]-cbeg[i]:      ^^^
1354 	 * \end{verbatim}
1355 	 *        belong to column i, but have already been pivotal and don't belong to
1356 	 *        the active submatrix.
1357 	 */
1358 	
1359 	/****************************************************************************/
1360 	/*
1361 	 *      Initialize row and column file of working matrix and
1362 	 *      mark column singletons.
1363 	 */
1364 	inline void CLUFactorRational::initFactorMatrix(const SVectorRational** vec)
1365 	{
1366 	
1367 	   Rational x;
1368 	   int m;
1369 	   int tot;
1370 	   Dring* rring, *lastrring;
1371 	   Dring* cring, *lastcring;
1372 	   const SVectorRational* psv;
1373 	   int* sing = temp.s_mark;
1374 	
1375 	   /*  Initialize:
1376 	    *  - column file thereby remembering column singletons in |sing|.
1377 	    *  - nonzeros counts per row
1378 	    *  - total number of nonzeros
1379 	    */
1380 	
1381 	   for(int i = 0; i < thedim; i++)
1382 	      u.row.max[i] = u.row.len[i] = 0;
1383 	
1384 	   tot = 0;
1385 	
1386 	   for(int i = 0; i < thedim; i++)
1387 	   {
1388 	      int k;
1389 	
1390 	      psv = vec[i];
1391 	      k = psv->size();
1392 	
1393 	      if(k > 1)
1394 	      {
1395 	         tot += k;
1396 	
1397 	         for(int j = 0; j < k; ++j)
1398 	            u.row.max[psv->index(j)]++;
1399 	      }
1400 	      else if(k == 0)
1401 	      {
1402 	         stat = SLinSolverRational::SINGULAR;
1403 	         return;
1404 	      }
1405 	   }
1406 	
1407 	   /*  Resize nonzero memory if necessary
1408 	    */
1409 	   minRowMem(int(rowMemMult * tot));
1410 	
1411 	   minColMem(int(colMemMult * tot));
1412 	
1413 	   minLMem(int(lMemMult * tot));
1414 	
1415 	
1416 	   /*  Initialize:
1417 	    *  - row ring lists
1418 	    *  - row vectors in file
1419 	    *  - column ring lists
1420 	    */
1421 	   u.row.start[0] = 0;
1422 	
1423 	   rring = u.row.elem;
1424 	
1425 	   lastrring = &(u.row.list);
1426 	
1427 	   lastrring->idx = thedim;
1428 	
1429 	   lastrring->next = rring;
1430 	
1431 	   cring = u.col.elem;
1432 	
1433 	   lastcring = &(u.col.list);
1434 	
1435 	   lastcring->idx = thedim;
1436 	
1437 	   lastcring->next = cring;
1438 	
1439 	   m = 0;
1440 	
1441 	   for(int i = 0; i < thedim; i++)
1442 	   {
1443 	      u.row.start[i] = m;
1444 	      m += u.row.max[i];
1445 	
1446 	      rring->idx = i;
1447 	      rring->prev = lastrring;
1448 	      lastrring->next = rring;
1449 	      lastrring = rring;
1450 	      ++rring;
1451 	
1452 	      cring->idx = i;
1453 	      cring->prev = lastcring;
1454 	      lastcring->next = cring;
1455 	      lastcring = cring;
1456 	      ++cring;
1457 	   }
1458 	
1459 	   u.row.start[thedim]       = 0;
1460 	
1461 	   u.row.max[thedim]       = 0;
1462 	   u.row.used = m;
1463 	
1464 	   lastrring->next = &(u.row.list);
1465 	   lastrring->next->prev = lastrring;
1466 	
1467 	   lastcring->next = &(u.col.list);
1468 	   lastcring->next->prev = lastcring;
1469 	
1470 	   /*  Copy matrix to row and column file
1471 	    *  excluding and marking column singletons!
1472 	    */
1473 	   m = 0;
1474 	   temp.stage = 0;
1475 	
1476 	   initMaxabs = 0;
1477 	
1478 	   for(int i = 0; i < thedim; i++)
1479 	   {
1480 	      int nnonzeros;
1481 	
1482 	      psv = vec[i];
1483 	      u.col.start[i] = m;
1484 	
1485 	      /* check whether number of nonzeros above tolerance is 0, 1 or >= 2 */
1486 	      nnonzeros = 0;
1487 	
1488 	      for(int j = 0; j < psv->size() && nnonzeros <= 1; j++)
1489 	      {
1490 	         if(psv->value(j) != 0)
1491 	            nnonzeros++;
1492 	      }
1493 	
1494 	      /* basis is singular due to empty column */
1495 	      if(nnonzeros == 0)
1496 	      {
1497 	         stat = SLinSolverRational::SINGULAR;
1498 	         return;
1499 	      }
1500 	
1501 	      /* exclude column singletons */
1502 	      else if(nnonzeros == 1)
1503 	      {
1504 	         int j;
1505 	
1506 	         /* find nonzero */
1507 	
1508 	         for(j = 0; psv->value(j) == 0; j++)
1509 	            ;
1510 	
1511 	         assert(j < psv->size());
1512 	
1513 	         /* basis is singular due to two linearly dependent column singletons */
1514 	         if(row.perm[psv->index(j)] >= 0)
1515 	         {
1516 	            stat = SLinSolverRational::SINGULAR;
1517 	            return;
1518 	         }
1519 	
1520 	         /* update maximum absolute nonzero value */
1521 	         x = psv->value(j);
1522 	
1523 	         if(spxAbs(x) > initMaxabs)
1524 	            initMaxabs = spxAbs(x);
1525 	
1526 	         /* permute to front and mark as singleton */
1527 	         setPivot(temp.stage, i, psv->index(j), x);
1528 	
1529 	         sing[temp.stage] = i;
1530 	
1531 	         temp.stage++;
1532 	
1533 	         /* set column length to zero */
1534 	         temp.s_cact[i] = u.col.len[i] = u.col.max[i] = 0;
1535 	      }
1536 	
1537 	      /* add to active matrix if not a column singleton */
1538 	      else
1539 	      {
1540 	         int end;
1541 	         int k;
1542 	
1543 	         /* go through all nonzeros in column */
1544 	         assert(nnonzeros >= 2);
1545 	         nnonzeros = 0;
1546 	
1547 	         for(int j = 0; j < psv->size(); j++)
1548 	         {
1549 	            x = psv->value(j);
1550 	
1551 	            if(x != 0)
1552 	            {
1553 	               /* add to column array */
1554 	               k = psv->index(j);
1555 	               u.col.idx[m] = k;
1556 	               m++;
1557 	
1558 	               /* add to row array */
1559 	               end = u.row.start[k] + u.row.len[k];
1560 	               u.row.idx[end] = i;
1561 	               u.row.val[end] = x;
1562 	               u.row.len[k]++;
1563 	
1564 	               /* update maximum absolute nonzero value */
1565 	
1566 	               if(spxAbs(x) > initMaxabs)
1567 	                  initMaxabs = spxAbs(x);
1568 	
1569 	               nnonzeros++;
1570 	            }
1571 	         }
1572 	
1573 	         assert(nnonzeros >= 2);
1574 	
1575 	         /* set column length */
1576 	         temp.s_cact[i] = u.col.len[i] = u.col.max[i] = nnonzeros;
1577 	      }
1578 	   }
1579 	
1580 	   u.col.used = m;
1581 	}
1582 	
1583 	
1584 	
1585 	/*****************************************************************************/
1586 	/*
1587 	 *      Remove column singletons
1588 	 */
1589 	
1590 	inline void CLUFactorRational::colSingletons()
1591 	{
1592 	   int i, j, k, n;
1593 	   int len;
1594 	   int p_col, p_row, newrow;
1595 	   int* idx;
1596 	   int* rorig = row.orig;
1597 	   int* rperm = row.perm;
1598 	   int* sing = temp.s_mark;
1599 	
1600 	
1601 	   /*  Iteratively update column counts due to removed column singletons
1602 	    *  thereby removing new arising columns singletons
1603 	    *  and computing the index of the first row singleton (-1)
1604 	    *  until no more can be found.
1605 	    */
1606 	
1607 	   for(i = 0; i < temp.stage; ++i)
1608 	   {
1609 	      p_row = rorig[i];
1610 	      assert(p_row >= 0);
1611 	      idx = &(u.row.idx[u.row.start[p_row]]);
1612 	      len = u.row.len[p_row];
1613 	
1614 	      for(j = 0; j < len; ++j)
1615 	      {
1616 	         /*  Move pivotal nonzeros to front of column.
1617 	          */
1618 	         p_col = idx[j];
1619 	         assert(temp.s_cact[p_col] > 0);
1620 	
1621 	         n = u.col.start[p_col] + u.col.len[p_col] - temp.s_cact[p_col];
1622 	
1623 	         for(k = n; u.col.idx[k] != p_row; ++k)
1624 	            ;
1625 	
1626 	         assert(k < u.col.start[p_col] + u.col.len[p_col]);
1627 	
1628 	         u.col.idx[k] = u.col.idx[n];
1629 	
1630 	         u.col.idx[n] = p_row;
1631 	
1632 	         n = --(temp.s_cact[p_col]);          /* column nonzeros of ACTIVE matrix */
1633 	
1634 	         if(n == 1)                   /* Here is another singleton */
1635 	         {
1636 	            newrow = u.col.idx[--u.col.len[p_col] + u.col.start[p_col]];
1637 	
1638 	            /*      Ensure, matrix not singular
1639 	             */
1640 	
1641 	            if(rperm[newrow] >= 0)
1642 	            {
1643 	               stat = SLinSolverRational::SINGULAR;
1644 	               return;
1645 	            }
1646 	
1647 	            /*      Find singleton in row.
1648 	             */
1649 	            n = u.row.start[newrow] + (--(u.row.len[newrow]));
1650 	
1651 	            for(k = n; u.row.idx[k] != p_col; --k)
1652 	               ;
1653 	
1654 	            /*      Remove singleton from column.
1655 	             */
1656 	            setPivot(temp.stage, p_col, newrow, u.row.val[k]);
1657 	
1658 	            sing[temp.stage++] = p_col;
1659 	
1660 	            /*      Move pivot element to diag.
1661 	             */
1662 	            u.row.val[k] = u.row.val[n];
1663 	
1664 	            u.row.idx[k] = u.row.idx[n];
1665 	         }
1666 	         else if(n == 0)
1667 	         {
1668 	            stat = SLinSolverRational::SINGULAR;
1669 	            return;
1670 	         }
1671 	      }
1672 	   }
1673 	
1674 	   assert(temp.stage <= thedim);
1675 	}
1676 	
1677 	
1678 	/*****************************************************************************/
1679 	/*
1680 	 *      Remove row singletons
1681 	 */
1682 	inline void CLUFactorRational::rowSingletons()
1683 	{
1684 	   Rational pval;
1685 	   int i, j, k, ll, r;
1686 	   int p_row, p_col, len, rs, lk;
1687 	   int* idx;
1688 	   int* rperm = row.perm;
1689 	   int* sing = temp.s_mark;
1690 	
1691 	   /*  Mark row singletons
1692 	    */
1693 	   rs = temp.stage;
1694 	
1695 	   for(i = 0; i < thedim; ++i)
1696 	   {
1697 	      if(rperm[i] < 0 && u.row.len[i] == 1)
1698 	         sing[temp.stage++] = i;
1699 	   }
1700 	
1701 	   /*  Eliminate row singletons
1702 	    *  thereby marking newly arising ones
1703 	    *  until no more can be found.
1704 	    */
1705 	   for(; rs < temp.stage; ++rs)
1706 	   {
1707 	      /*      Move pivot element from row file to diag
1708 	       */
1709 	      p_row = sing[rs];
1710 	      j = u.row.start[p_row];
1711 	      p_col = u.row.idx[j];
1712 	      pval = u.row.val[j];
1713 	      setPivot(rs, p_col, p_row, pval);
1714 	      u.row.len[p_row] = 0;
1715 	
1716 	      /*      Remove pivot column form workingmatrix
1717 	       *      thereby building up L vector.
1718 	       */
1719 	      idx = &(u.col.idx[u.col.start[p_col]]);
1720 	      i = temp.s_cact[p_col];                /* nr. nonzeros of new L vector */
1721 	      lk = makeLvec(i - 1, p_row);
1722 	      len = u.col.len[p_col];
1723 	      i = (u.col.len[p_col] -= i);         /* remove pivot column from U */
1724 	
1725 	      for(; i < len; ++i)
1726 	      {
1727 	         r = idx[i];
1728 	
1729 	         if(r != p_row)
1730 	         {
1731 	            /*      Find pivot column in row.
1732 	             */
1733 	            ll = --(u.row.len[r]);
1734 	            k = u.row.start[r] + ll;
1735 	
1736 	            for(j = k; u.row.idx[j] != p_col; --j)
1737 	               ;
1738 	
1739 	            assert(k >= u.row.start[r]);
1740 	
1741 	            /*      Initialize L vector
1742 	             */
1743 	            l.idx[lk] = r;
1744 	
1745 	            l.val[lk] = u.row.val[j] / pval;
1746 	
1747 	            ++lk;
1748 	
1749 	            /*      Remove pivot column from row.
1750 	             */
1751 	            u.row.idx[j] = u.row.idx[k];
1752 	
1753 	            u.row.val[j] = u.row.val[k];
1754 	
1755 	            /*      Check new row length.
1756 	             */
1757 	            if(ll == 1)
1758 	               sing[temp.stage++] = r;
1759 	            else if(ll == 0)
1760 	            {
1761 	               stat = SLinSolverRational::SINGULAR;
1762 	               return;
1763 	            }
1764 	         }
1765 	      }
1766 	   }
1767 	}
1768 	
1769 	
1770 	/*****************************************************************************/
1771 	/*
1772 	 *      Init nonzero number Ring lists
1773 	 *      and required entries of arrays max and mark
1774 	 */
1775 	
1776 	inline void CLUFactorRational::initFactorRings()
1777 	{
1778 	   int i;
1779 	   int* rperm = row.perm;
1780 	   int* cperm = col.perm;
1781 	   CLUFactorRational::Pring* ring;
1782 	
1783 	   assert(thedim >= 0);
1784 	   spx_alloc(temp.pivot_col,   thedim + 1);
1785 	   spx_alloc(temp.pivot_colNZ, thedim + 1);
1786 	   spx_alloc(temp.pivot_row,   thedim + 1);
1787 	   spx_alloc(temp.pivot_rowNZ, thedim + 1);
1788 	
1789 	   for(i = thedim - temp.stage; i >= 0; --i)
1790 	   {
1791 	      initDR(temp.pivot_colNZ[i]);
1792 	      initDR(temp.pivot_rowNZ[i]);
1793 	   }
1794 	
1795 	   for(i = 0; i < thedim; ++i)
1796 	   {
1797 	      if(rperm[i] < 0)
1798 	      {
1799 	         if(u.row.len[i] <= 0)
1800 	         {
1801 	            stat = SLinSolverRational::SINGULAR;
1802 	            return;
1803 	         }
1804 	
1805 	         ring = &(temp.pivot_rowNZ[u.row.len[i]]);
1806 	
1807 	         init2DR(temp.pivot_row[i], *ring);
1808 	         temp.pivot_row[i].idx = i;
1809 	         temp.s_max[i] = -1;
1810 	      }
1811 	
1812 	      if(cperm[i] < 0)
1813 	      {
1814 	         if(temp.s_cact[i] <= 0)
1815 	         {
1816 	            stat = SLinSolverRational::SINGULAR;
1817 	            return;
1818 	         }
1819 	
1820 	         ring = &(temp.pivot_colNZ[temp.s_cact[i]]);
1821 	
1822 	         init2DR(temp.pivot_col[i], *ring);
1823 	         temp.pivot_col[i].idx = i;
1824 	         temp.s_mark[i] = 0;
1825 	      }
1826 	   }
1827 	}
1828 	
1829 	inline void CLUFactorRational::freeFactorRings(void)
1830 	{
1831 	
1832 	   if(temp.pivot_col)
1833 	      spx_free(temp.pivot_col);
1834 	
1835 	   if(temp.pivot_colNZ)
1836 	      spx_free(temp.pivot_colNZ);
1837 	
1838 	   if(temp.pivot_row)
1839 	      spx_free(temp.pivot_row);
1840 	
1841 	   if(temp.pivot_rowNZ)
1842 	      spx_free(temp.pivot_rowNZ);
1843 	}
1844 	
1845 	
1846 	/*
1847 	 *      Eliminate all row singletons from nucleus.
1848 	 *      A row singleton may well be column singleton at the same time!
1849 	 */
1850 	inline void CLUFactorRational::eliminateRowSingletons()
1851 	{
1852 	   int i, j, k, ll, r;
1853 	   int len, lk;
1854 	   int pcol, prow;
1855 	   Rational pval;
1856 	   int* idx;
1857 	   CLUFactorRational::Pring* sing;
1858 	
1859 	   for(sing = temp.pivot_rowNZ[1].prev; sing != &(temp.pivot_rowNZ[1]); sing = sing->prev)
1860 	   {
1861 	      prow = sing->idx;
1862 	      i = u.row.start[prow];
1863 	      pcol = u.row.idx[i];
1864 	      pval = u.row.val[i];
1865 	      setPivot(temp.stage++, pcol, prow, pval);
1866 	      u.row.len[prow] = 0;
1867 	      removeDR(temp.pivot_col[pcol]);
1868 	
1869 	      /*      Eliminate pivot column and build L vector.
1870 	       */
1871 	      i = temp.s_cact[pcol];
1872 	
1873 	      if(i > 1)
1874 	      {
1875 	         idx = &(u.col.idx[u.col.start[pcol]]);
1876 	         len = u.col.len[pcol];
1877 	         lk = makeLvec(i - 1, prow);
1878 	         i = u.col.len[pcol] -= i;
1879 	
1880 	         for(; (r = idx[i]) != prow; ++i)
1881 	         {
1882 	            /*      Find pivot column in row.
1883 	             */
1884 	            ll = --(u.row.len[r]);
1885 	            k = u.row.start[r] + ll;
1886 	
1887 	            for(j = k; u.row.idx[j] != pcol; --j)
1888 	               ;
1889 	
1890 	            assert(j >= u.row.start[r]);
1891 	
1892 	            /*      Initialize L vector
1893 	             */
1894 	            l.idx[lk] = r;
1895 	
1896 	            l.val[lk] = u.row.val[j] / pval;
1897 	
1898 	            ++lk;
1899 	
1900 	            /*      Remove pivot column from row.
1901 	             */
1902 	            u.row.idx[j] = u.row.idx[k];
1903 	
1904 	            u.row.val[j] = u.row.val[k];
1905 	
1906 	            /*      Move column to appropriate nonzero ring.
1907 	             */
1908 	            removeDR(temp.pivot_row[r]);
1909 	
1910 	            init2DR(temp.pivot_row[r], temp.pivot_rowNZ[ll]);
1911 	
1912 	            assert(row.perm[r] < 0);
1913 	
1914 	            temp.s_max[r] = -1;
1915 	         }
1916 	
1917 	         /* skip pivot element */
1918 	         assert(i < len && "ERROR: pivot column does not contain pivot row");
1919 	
1920 	         for(++i; i < len; ++i)
1921 	         {
1922 	            /*      Find pivot column in row.
1923 	             */
1924 	            r = idx[i];
1925 	            ll = --(u.row.len[r]);
1926 	            k = u.row.start[r] + ll;
1927 	
1928 	            for(j = k; u.row.idx[j] != pcol; --j)
1929 	               ;
1930 	
1931 	            assert(j >= u.row.start[r]);
1932 	
1933 	            /*      Initialize L vector
1934 	             */
1935 	            l.idx[lk] = r;
1936 	
1937 	            l.val[lk] = u.row.val[j] / pval;
1938 	
1939 	            ++lk;
1940 	
1941 	            /*      Remove pivot column from row.
1942 	             */
1943 	            u.row.idx[j] = u.row.idx[k];
1944 	
1945 	            u.row.val[j] = u.row.val[k];
1946 	
1947 	            /*      Move column to appropriate nonzero ring.
1948 	             */
1949 	            removeDR(temp.pivot_row[r]);
1950 	
1951 	            init2DR(temp.pivot_row[r], temp.pivot_rowNZ[ll]);
1952 	
1953 	            assert(row.perm[r] < 0);
1954 	
1955 	            temp.s_max[r] = -1;
1956 	         }
1957 	      }
1958 	      else
1959 	         u.col.len[pcol] -= i;
1960 	   }
1961 	
1962 	   initDR(temp.pivot_rowNZ[1]);    /* Remove all row singletons from list */
1963 	}
1964 	
1965 	
1966 	
1967 	/*
1968 	 *      Eliminate all column singletons from nucleus.
1969 	 *      A column singleton must not be row singleton at the same time!
1970 	 */
1971 	inline void CLUFactorRational::eliminateColSingletons()
1972 	{
1973 	   int i, j, k, m, c;
1974 	   int pcol, prow;
1975 	   CLUFactorRational::Pring* sing;
1976 	
1977 	   for(sing = temp.pivot_colNZ[1].prev;
1978 	         sing != &(temp.pivot_colNZ[1]);
1979 	         sing = sing->prev)
1980 	   {
1981 	      /*      Find pivot value
1982 	       */
1983 	      pcol = sing->idx;
1984 	      j = --(u.col.len[pcol]) + u.col.start[pcol];   /* remove pivot column */
1985 	      prow = u.col.idx[j];
1986 	      removeDR(temp.pivot_row[prow]);
1987 	
1988 	      j = --(u.row.len[prow]) + u.row.start[prow];
1989 	
1990 	      for(i = j; (c = u.row.idx[i]) != pcol; --i)
1991 	      {
1992 	         m = u.col.len[c] + u.col.start[c] - (temp.s_cact[c])--;
1993 	
1994 	         for(k = m; u.col.idx[k] != prow; ++k)
1995 	            ;
1996 	
1997 	         u.col.idx[k] = u.col.idx[m];
1998 	
1999 	         u.col.idx[m] = prow;
2000 	
2001 	         m = temp.s_cact[c];
2002 	
2003 	         removeDR(temp.pivot_col[c]);
2004 	
2005 	         init2DR(temp.pivot_col[c], temp.pivot_colNZ[m]);
2006 	
2007 	         assert(col.perm[c] < 0);
2008 	      }
2009 	
2010 	      /*      remove pivot element from pivot row
2011 	       */
2012 	      setPivot(temp.stage++, pcol, prow, u.row.val[i]);
2013 	
2014 	      u.row.idx[i] = u.row.idx[j];
2015 	
2016 	      u.row.val[i] = u.row.val[j];
2017 	
2018 	      j = u.row.start[prow];
2019 	
2020 	      for(--i; i >= j; --i)
2021 	      {
2022 	         c = u.row.idx[i];
2023 	         m = u.col.len[c] + u.col.start[c] - (temp.s_cact[c])--;
2024 	
2025 	         for(k = m; u.col.idx[k] != prow; ++k)
2026 	            ;
2027 	
2028 	         u.col.idx[k] = u.col.idx[m];
2029 	
2030 	         u.col.idx[m] = prow;
2031 	
2032 	         m = temp.s_cact[c];
2033 	
2034 	         removeDR(temp.pivot_col[c]);
2035 	
2036 	         init2DR(temp.pivot_col[c], temp.pivot_colNZ[m]);
2037 	
2038 	         assert(col.perm[c] < 0);
2039 	      }
2040 	   }
2041 	
2042 	   initDR(temp.pivot_colNZ[1]);    /* Remove all column singletons from list */
2043 	}
2044 	
2045 	/*
2046 	 * No singletons available: Select pivot elements.
2047 	 */
2048 	inline void CLUFactorRational::selectPivots(const Rational& threshold)
2049 	{
2050 	   int ii;
2051 	   int i;
2052 	   int j;
2053 	   int k;
2054 	   int ll = -1; // This value should never be used.
2055 	   int kk;
2056 	   int m;
2057 	   int count;
2058 	   int num;
2059 	   int rw = -1; // This value should never be used.
2060 	   int cl = -1; // This value should never be used.
2061 	   int len;
2062 	   int beg;
2063 	   Rational l_maxabs;
2064 	   Rational x = 0; // This value should never be used.
2065 	   int mkwtz;
2066 	   int candidates;
2067 	
2068 	   candidates = thedim - temp.stage - 1;
2069 	
2070 	   if(candidates > 4)
2071 	      candidates = 4;
2072 	
2073 	   num = 0;
2074 	
2075 	   count = 2;
2076 	
2077 	   for(;;)
2078 	   {
2079 	      ii = -1;
2080 	
2081 	      if(temp.pivot_rowNZ[count].next != &(temp.pivot_rowNZ[count]))
2082 	      {
2083 	         rw = temp.pivot_rowNZ[count].next->idx;
2084 	         beg = u.row.start[rw];
2085 	         len = u.row.len[rw] + beg - 1;
2086 	
2087 	         /*  set l_maxabs to maximum absolute value in row
2088 	          *  (compute it if necessary).
2089 	          */
2090 	
2091 	         if(temp.s_max[rw] < 0)
2092 	         {
2093 	            l_maxabs = spxAbs(u.row.val[len]);
2094 	
2095 	            for(i = len - 1; i >= beg; --i)
2096 	               if(l_maxabs < spxAbs(u.row.val[i]))
2097 	                  l_maxabs = spxAbs(u.row.val[i]);
2098 	
2099 	            temp.s_max[rw] = l_maxabs;               /* ##### */
2100 	         }
2101 	         else
2102 	            l_maxabs = temp.s_max[rw];
2103 	
2104 	         l_maxabs *= threshold;
2105 	
2106 	         /*  select pivot element with lowest markowitz number in row
2107 	          */
2108 	         mkwtz = thedim + 1;
2109 	
2110 	         for(i = len; i >= beg; --i)
2111 	         {
2112 	            k = u.row.idx[i];
2113 	            j = temp.s_cact[k];
2114 	            x = u.row.val[i];
2115 	
2116 	            if(j < mkwtz && spxAbs(x) > l_maxabs)
2117 	            {
2118 	               mkwtz = j;
2119 	               cl = k;
2120 	               ii = i;
2121 	
2122 	               if(j <= count)               /* ##### */
2123 	                  break;
2124 	            }
2125 	         }
2126 	      }
2127 	      else if(temp.pivot_colNZ[count].next != &(temp.pivot_colNZ[count]))
2128 	      {
2129 	         cl = temp.pivot_colNZ[count].next->idx;
2130 	         beg = u.col.start[cl];
2131 	         len = u.col.len[cl] + beg - 1;
2132 	         beg = len - temp.s_cact[cl] + 1;
2133 	         assert(count == temp.s_cact[cl]);
2134 	
2135 	         /*  select pivot element with lowest markowitz number in column
2136 	          */
2137 	         mkwtz = thedim + 1;
2138 	
2139 	         for(i = len; i >= beg; --i)
2140 	         {
2141 	            k = u.col.idx[i];
2142 	            j = u.row.len[k];
2143 	
2144 	            if(j < mkwtz)
2145 	            {
2146 	               /*  ensure that element (cl,k) is stable.
2147 	                */
2148 	               if(temp.s_max[k] > 0)
2149 	               {
2150 	                  /*  case 1: l_maxabs is known
2151 	                   */
2152 	                  for(m = u.row.start[k], kk = m + u.row.len[k] - 1;
2153 	                        kk >= m; --kk)
2154 	                  {
2155 	                     if(u.row.idx[kk] == cl)
2156 	                     {
2157 	                        x = u.row.val[kk];
2158 	                        ll = kk;
2159 	                        break;
2160 	                     }
2161 	                  }
2162 	
2163 	                  l_maxabs = temp.s_max[k];
2164 	               }
2165 	               else
2166 	               {
2167 	                  /*  case 2: l_maxabs needs to be computed
2168 	                   */
2169 	                  m = u.row.start[k];
2170 	                  l_maxabs = spxAbs(u.row.val[m]);
2171 	
2172 	                  for(kk = m + u.row.len[k] - 1; kk >= m; --kk)
2173 	                  {
2174 	                     if(l_maxabs < spxAbs(u.row.val[kk]))
2175 	                        l_maxabs = spxAbs(u.row.val[kk]);
2176 	
2177 	                     if(u.row.idx[kk] == cl)
2178 	                     {
2179 	                        x = u.row.val[kk];
2180 	                        ll = kk;
2181 	                        break;
2182 	                     }
2183 	                  }
2184 	
2185 	                  for(--kk; kk > m; --kk)
2186 	                  {
2187 	                     if(l_maxabs < spxAbs(u.row.val[kk]))
2188 	                        l_maxabs = spxAbs(u.row.val[kk]);
2189 	                  }
2190 	
2191 	                  temp.s_max[k] = l_maxabs;
2192 	               }
2193 	
2194 	               l_maxabs *= threshold;
2195 	
2196 	               if(spxAbs(x) > l_maxabs)
2197 	               {
2198 	                  mkwtz = j;
2199 	                  rw = k;
2200 	                  ii = ll;
2201 	
2202 	                  if(j <= count + 1)
2203 	                     break;
2204 	               }
2205 	            }
2206 	         }
2207 	      }
2208 	      else
2209 	      {
2210 	         ++count;
2211 	         continue;
2212 	      }
2213 	
2214 	      assert(cl >= 0);
2215 	
2216 	      removeDR(temp.pivot_col[cl]);
2217 	      initDR(temp.pivot_col[cl]);
2218 	
2219 	      if(ii >= 0)
2220 	      {
2221 	         /*  Initialize selected pivot element
2222 	          */
2223 	         CLUFactorRational::Pring* pr;
2224 	         temp.pivot_row[rw].pos = ii - u.row.start[rw];
2225 	         temp.pivot_row[rw].mkwtz = mkwtz = (mkwtz - 1) * (count - 1);
2226 	         // ??? mkwtz originally was long,
2227 	         // maybe to avoid an overflow in this instruction?
2228 	
2229 	         for(pr = temp.pivots.next; pr->idx >= 0; pr = pr->next)
2230 	         {
2231 	            if(pr->idx == rw || pr->mkwtz >= mkwtz)
2232 	               break;
2233 	         }
2234 	
2235 	         pr = pr->prev;
2236 	
2237 	         if(pr->idx != rw)
2238 	         {
2239 	            removeDR(temp.pivot_row[rw]);
2240 	            init2DR(temp.pivot_row[rw], *pr);
2241 	         }
2242 	
2243 	         num++;
2244 	
2245 	         if(num >= candidates)
2246 	            break;
2247 	      }
2248 	   }
2249 	
2250 	   /*
2251 	    *     while(temp.temp.next->mkwtz < temp.temp.prev->mkwtz)
2252 	    *     {
2253 	    *     Pring   *pr;
2254 	    *     pr = temp.temp.prev;
2255 	    *     removeDR(*pr);
2256 	    *     init2DR (*pr, rowNZ[u.row.len[pr->idx]]);
2257 	    }
2258 	    */
2259 	
2260 	   assert(row.perm[rw] < 0);
2261 	
2262 	   assert(col.perm[cl] < 0);
2263 	}
2264 	
2265 	
2266 	/*
2267 	 *      Perform L and update loop for row r
2268 	 */
2269 	inline int CLUFactorRational::updateRow(int r,
2270 	                                        int lv,
2271 	                                        int prow,
2272 	                                        int pcol,
2273 	                                        const Rational& pval)
2274 	{
2275 	   int fill;
2276 	   Rational x, lx;
2277 	   int c, i, j, k, ll, m, n;
2278 	
2279 	   n = u.row.start[r];
2280 	   m = --(u.row.len[r]) + n;
2281 	
2282 	   /*  compute L vector entry and
2283 	    *  and remove pivot column form row file
2284 	    */
2285 	
2286 	   for(j = m; u.row.idx[j] != pcol; --j)
2287 	      ;
2288 	
2289 	   lx = u.row.val[j] / pval;
2290 	
2291 	   l.val[lv] = lx;
2292 	
2293 	   l.idx[lv] = r;
2294 	
2295 	   ++lv;
2296 	
2297 	   u.row.idx[j] = u.row.idx[m];
2298 	
2299 	   u.row.val[j] = u.row.val[m];
2300 	
2301 	
2302 	   /*  update loop (I) and
2303 	    *  computing expected fill
2304 	    */
2305 	   fill = u.row.len[prow];
2306 	
2307 	   for(j = m - 1; j >= n; --j)
2308 	   {
2309 	      c = u.row.idx[j];
2310 	
2311 	      if(temp.s_mark[c])
2312 	      {
2313 	         /*  count fill elements.
2314 	          */
2315 	         temp.s_mark[c] = 0;
2316 	         --fill;
2317 	
2318 	         /*  update row values
2319 	          */
2320 	         x = u.row.val[j] -= work[c] * lx;
2321 	
2322 	         if(x == 0)
2323 	         {
2324 	            /* Eliminate zero from row r
2325 	             */
2326 	            --u.row.len[r];
2327 	            --m;
2328 	            u.row.val[j] = u.row.val[m];
2329 	            u.row.idx[j] = u.row.idx[m];
2330 	
2331 	            /* Eliminate zero from column c
2332 	             */
2333 	            --(temp.s_cact[c]);
2334 	            k = --(u.col.len[c]) + u.col.start[c];
2335 	
2336 	            for(i = k; u.col.idx[i] != r; --i)
2337 	               ;
2338 	
2339 	            u.col.idx[i] = u.col.idx[k];
2340 	         }
2341 	      }
2342 	   }
2343 	
2344 	
2345 	   /*  create space for fill in row file
2346 	    */
2347 	   ll = u.row.len[r];
2348 	
2349 	   if(ll + fill > u.row.max[r])
2350 	      remaxRow(r, ll + fill);
2351 	
2352 	   ll += u.row.start[r];
2353 	
2354 	   /*  fill creating update loop (II)
2355 	    */
2356 	   for(j = u.row.start[prow], m = j + u.row.len[prow]; j < m; ++j)
2357 	   {
2358 	      c = u.row.idx[j];
2359 	
2360 	      if(temp.s_mark[c])
2361 	      {
2362 	         x = - work[c] * lx;
2363 	
2364 	         if(x != 0)
2365 	         {
2366 	            /* produce fill element in row r
2367 	             */
2368 	            u.row.val[ll] = x;
2369 	            u.row.idx[ll] = c;
2370 	            ll++;
2371 	            u.row.len[r]++;
2372 	
2373 	            /* produce fill element in column c
2374 	             */
2375 	
2376 	            if(u.col.len[c] >= u.col.max[c])
2377 	               remaxCol(c, u.col.len[c] + 1);
2378 	
2379 	            u.col.idx[u.col.start[c] + (u.col.len[c])++] = r;
2380 	
2381 	            temp.s_cact[c]++;
2382 	         }
2383 	      }
2384 	      else
2385 	         temp.s_mark[c] = 1;
2386 	   }
2387 	
2388 	   /*  move row to appropriate list.
2389 	    */
2390 	   removeDR(temp.pivot_row[r]);
2391 	
2392 	   init2DR(temp.pivot_row[r], temp.pivot_rowNZ[u.row.len[r]]);
2393 	
2394 	   assert(row.perm[r] < 0);
2395 	
2396 	   temp.s_max[r] = -1;
2397 	
2398 	   return lv;
2399 	}
2400 	
2401 	/*
2402 	 *      Eliminate pivot element
2403 	 */
2404 	inline void CLUFactorRational::eliminatePivot(int prow, int pos)
2405 	{
2406 	   int i, j, k, m = -1;
2407 	   int lv = -1;  // This value should never be used.
2408 	   int pcol;
2409 	   Rational pval;
2410 	   int pbeg = u.row.start[prow];
2411 	   int plen = --(u.row.len[prow]);
2412 	   int pend = pbeg + plen;
2413 	
2414 	
2415 	   /*  extract pivot element   */
2416 	   i = pbeg + pos;
2417 	   pcol = u.row.idx[i];
2418 	   pval = u.row.val[i];
2419 	   removeDR(temp.pivot_col[pcol]);
2420 	   initDR(temp.pivot_col[pcol]);
2421 	
2422 	   /*  remove pivot from pivot row     */
2423 	   u.row.idx[i] = u.row.idx[pend];
2424 	   u.row.val[i] = u.row.val[pend];
2425 	
2426 	   /*  set pivot element and construct L vector */
2427 	   setPivot(temp.stage++, pcol, prow, pval);
2428 	
2429 	   /**@todo If this test failes, lv has no value. I suppose that in this
2430 	    *       case none of the loops below that uses lv is executed.
2431 	    *       But this is unproven.
2432 	    */
2433 	
2434 	   if(temp.s_cact[pcol] - 1 > 0)
2435 	      lv = makeLvec(temp.s_cact[pcol] - 1, prow);
2436 	
2437 	   /*  init working vector,
2438 	    *  remove pivot row from working matrix
2439 	    *  and remove columns from list.
2440 	    */
2441 	   for(i = pbeg; i < pend; ++i)
2442 	   {
2443 	      j = u.row.idx[i];
2444 	      temp.s_mark[j] = 1;
2445 	      work[j] = u.row.val[i];
2446 	      removeDR(temp.pivot_col[j]);
2447 	      m = u.col.start[j] + u.col.len[j] - temp.s_cact[j];
2448 	
2449 	      for(k = m; u.col.idx[k] != prow; ++k)
2450 	         ;
2451 	
2452 	      u.col.idx[k] = u.col.idx[m];
2453 	
2454 	      u.col.idx[m] = prow;
2455 	
2456 	      temp.s_cact[j]--;
2457 	   }
2458 	
2459 	   /*  perform L and update loop
2460 	    */
2461 	   for(i = u.col.len[pcol] - temp.s_cact[pcol];
2462 	         (m = u.col.idx[u.col.start[pcol] + i]) != prow;
2463 	         ++i)
2464 	   {
2465 	      assert(row.perm[m] < 0);
2466 	      assert(lv >= 0);
2467 	      /* coverity[negative_returns] */
2468 	      updateRow(m, lv++, prow, pcol, pval);
2469 	   }
2470 	
2471 	   /*  skip pivot row  */
2472 	
2473 	   m = u.col.len[pcol];
2474 	
2475 	   for(++i; i < m; ++i)
2476 	   {
2477 	      assert(lv >= 0);
2478 	      /* coverity[negative_returns] */
2479 	      updateRow(u.col.idx[u.col.start[pcol] + i], lv++, prow, pcol, pval);
2480 	   }
2481 	
2482 	   /*  remove pivot column from column file.
2483 	    */
2484 	   u.col.len[pcol] -= temp.s_cact[pcol];
2485 	
2486 	   /*  clear working vector and reinsert columns to lists
2487 	    */
2488 	   for(i = u.row.start[prow], pend = i + plen; i < pend; ++i)
2489 	   {
2490 	      j = u.row.idx[i];
2491 	      work[j] = 0;
2492 	      temp.s_mark[j] = 0;
2493 	      init2DR(temp.pivot_col[j], temp.pivot_colNZ[temp.s_cact[j]]);
2494 	      assert(col.perm[j] < 0);
2495 	   }
2496 	}
2497 	
2498 	
2499 	/*
2500 	 *      Factorize nucleus.
2501 	 */
2502 	inline void CLUFactorRational::eliminateNucleus(const Rational& threshold)
2503 	{
2504 	   int r, c;
2505 	   CLUFactorRational::Pring* pivot;
2506 	
2507 	   if(stat == SLinSolverRational::SINGULAR)
2508 	      return;
2509 	
2510 	   temp.pivots.mkwtz = -1;
2511 	
2512 	   temp.pivots.idx = -1;
2513 	
2514 	   temp.pivots.pos = -1;
2515 	
2516 	   while(temp.stage < thedim - 1)
2517 	   {
2518 	#ifndef NDEBUG
2519 	      int i;
2520 	      // CLUFactorRationalIsConsistent(fac);
2521 	
2522 	      for(i = 0; i < thedim; ++i)
2523 	         if(col.perm[i] < 0)
2524 	            assert(temp.s_mark[i] == 0);
2525 	
2526 	#endif
2527 	
2528 	      if(temp.pivot_rowNZ[1].next != &(temp.pivot_rowNZ[1]))
2529 	      {
2530 	         if(timeLimitReached())
2531 	            return;
2532 	
2533 	         /* row singleton available */
2534 	         eliminateRowSingletons();
2535 	      }
2536 	      else if(temp.pivot_colNZ[1].next != &(temp.pivot_colNZ[1]))
2537 	      {
2538 	         if(timeLimitReached())
2539 	            return;
2540 	
2541 	         /* column singleton available */
2542 	         eliminateColSingletons();
2543 	      }
2544 	      else
2545 	      {
2546 	         initDR(temp.pivots);
2547 	         selectPivots(threshold);
2548 	
2549 	         assert(temp.pivots.next != &temp.pivots &&
2550 	                "ERROR: no pivot element selected");
2551 	
2552 	         for(pivot = temp.pivots.next; pivot != &temp.pivots;
2553 	               pivot = pivot->next)
2554 	         {
2555 	            if(timeLimitReached())
2556 	               return;
2557 	
2558 	            eliminatePivot(pivot->idx, pivot->pos);
2559 	         }
2560 	      }
2561 	
2562 	      if(temp.pivot_rowNZ->next != temp.pivot_rowNZ ||
2563 	            temp.pivot_colNZ->next != temp.pivot_colNZ)
2564 	      {
2565 	         stat = SLinSolverRational::SINGULAR;
2566 	         return;
2567 	      }
2568 	   }
2569 	
2570 	   if(temp.stage < thedim)
2571 	   {
2572 	      /*      Eliminate remaining element.
2573 	       *      Note, that this must be both, column and row singleton.
2574 	       */
2575 	      assert(temp.pivot_rowNZ[1].next != &(temp.pivot_rowNZ[1]) &&
2576 	             "ERROR: one row must be left");
2577 	      assert(temp.pivot_colNZ[1].next != &(temp.pivot_colNZ[1]) &&
2578 	             "ERROR: one col must be left");
2579 	      r = temp.pivot_rowNZ[1].next->idx;
2580 	      c = temp.pivot_colNZ[1].next->idx;
2581 	      u.row.len[r] = 0;
2582 	      u.col.len[c]--;
2583 	      setPivot(temp.stage, c, r, u.row.val[u.row.start[r]]);
2584 	   }
2585 	}
2586 	
2587 	/*****************************************************************************/
2588 	
2589 	inline int CLUFactorRational::setupColVals()
2590 	{
2591 	   int i;
2592 	   int n = thedim;
2593 	
2594 	   u.col.val.reDim(u.col.size);
2595 	
2596 	   for(i = 0; i < thedim; i++)
2597 	      u.col.len[i] = 0;
2598 	
2599 	   maxabs = 0;
2600 	
2601 	   for(i = 0; i < thedim; i++)
2602 	   {
2603 	      int     k   = u.row.start[i];
2604 	      int*    idx = &u.row.idx[k];
2605 	      Rational*   val = &u.row.val[k];
2606 	      int     len = u.row.len[i];
2607 	
2608 	      n += len;
2609 	
2610 	      while(len-- > 0)
2611 	      {
2612 	         assert((*idx >= 0) && (*idx < thedim));
2613 	
2614 	         k = u.col.start[*idx] + u.col.len[*idx];
2615 	
2616 	         assert((k >= 0) && (k < u.col.size));
2617 	
2618 	         u.col.len[*idx]++;
2619 	
2620 	         assert(u.col.len[*idx] <= u.col.max[*idx]);
2621 	
2622 	         u.col.idx[k] = i;
2623 	         u.col.val[k] = *val;
2624 	
2625 	         if(spxAbs(*val) > maxabs)
2626 	            maxabs = spxAbs(*val);
2627 	
2628 	         idx++;
2629 	
2630 	         val++;
2631 	      }
2632 	   }
2633 	
2634 	   return n;
2635 	}
2636 	
2637 	/*****************************************************************************/
2638 	
2639 	#ifdef WITH_L_ROWS
2640 	inline void CLUFactorRational::setupRowVals()
2641 	{
2642 	   int   i, j, k, m;
2643 	   int   vecs, mem;
2644 	   int*  l_row;
2645 	   int*  idx;
2646 	   int*  beg;
2647 	   int*  l_ridx;
2648 	   int*  l_rbeg;
2649 	   int*  rorig;
2650 	   int*  rrorig;
2651 	   int*  rperm;
2652 	   int*  rrperm;
2653 	
2654 	   vecs  = l.firstUpdate;
2655 	   l_row = l.row;
2656 	   idx   = l.idx;
2657 	   VectorRational& val = l.val;
2658 	   int validx = 0;
2659 	   beg   = l.start;
2660 	   mem   = beg[vecs];
2661 	
2662 	   if(l.ridx)
2663 	      spx_free(l.ridx);
2664 	
2665 	   if(l.rbeg)
2666 	      spx_free(l.rbeg);
2667 	
2668 	   if(l.rorig)
2669 	      spx_free(l.rorig);
2670 	
2671 	   if(l.rperm)
2672 	      spx_free(l.rperm);
2673 	
2674 	   l.rval.reDim(mem);
2675 	
2676 	   spx_alloc(l.ridx, mem);
2677 	
2678 	   spx_alloc(l.rbeg, thedim + 1);
2679 	
2680 	   spx_alloc(l.rorig, thedim);
2681 	
2682 	   spx_alloc(l.rperm, thedim);
2683 	
2684 	   l_ridx = l.ridx;
2685 	
2686 	   VectorRational& l_rval = l.rval;
2687 	
2688 	   l_rbeg = l.rbeg;
2689 	
2690 	   rorig  = l.rorig;
2691 	
2692 	   rrorig = row.orig;
2693 	
2694 	   rperm  = l.rperm;
2695 	
2696 	   rrperm = row.perm;
2697 	
2698 	   for(i = thedim; i--; *l_rbeg++ = 0)
2699 	   {
2700 	      *rorig++ = *rrorig++;
2701 	      *rperm++ = *rrperm++;
2702 	   }
2703 	
2704 	   *l_rbeg = 0;
2705 	
2706 	   l_rbeg = l.rbeg + 1;
2707 	
2708 	   for(i = mem; i--;)
2709 	      l_rbeg[*idx++]++;
2710 	
2711 	   idx = l.idx;
2712 	
2713 	   for(m = 0, i = thedim; i--; l_rbeg++)
2714 	   {
2715 	      j = *l_rbeg;
2716 	      *l_rbeg = m;
2717 	      m += j;
2718 	   }
2719 	
2720 	   assert(m == mem);
2721 	
2722 	   l_rbeg = l.rbeg + 1;
2723 	
2724 	   for(i = j = 0; i < vecs; ++i)
2725 	   {
2726 	      m = l_row[i];
2727 	      assert(idx == &l.idx[l.start[i]]);
2728 	
2729 	      for(; j < beg[i + 1]; j++)
2730 	      {
2731 	         k = l_rbeg[*idx++]++;
2732 	         assert(k < mem);
2733 	         l_ridx[k] = m;
2734 	         l_rval[k] = val[validx];
2735 	         validx++; // was l_rval[k] = *val++; with Rational* val
2736 	      }
2737 	   }
2738 	
2739 	   assert(l.rbeg[thedim] == mem);
2740 	
2741 	   assert(l.rbeg[0] == 0);
2742 	}
2743 	
2744 	#endif
2745 	
2746 	/*****************************************************************************/
2747 	
2748 	inline void CLUFactorRational::factor(
2749 	   const SVectorRational** vec,         ///< Array of column vector pointers
2750 	   const Rational& threshold            ///< pivoting threshold
2751 	)
2752 	{
2753 	   MSG_DEBUG(std::cout << "CLUFactorRational::factor()\n");
2754 	
2755 	   factorTime->start();
2756 	
2757 	   stat = SLinSolverRational::OK;
2758 	
2759 	   l.start[0]    = 0;
2760 	   l.firstUpdate = 0;
2761 	   l.firstUnused = 0;
2762 	
2763 	   temp.init(thedim);
2764 	   initPerm();
2765 	
2766 	   initFactorMatrix(vec);
2767 	
2768 	   if(stat)
2769 	      goto TERMINATE;
2770 	
2771 	   if(timeLimitReached())
2772 	      goto TERMINATE;
2773 	
2774 	   //   initMaxabs = initMaxabs;
2775 	
2776 	   colSingletons();
2777 	
2778 	   if(stat != SLinSolverRational::OK)
2779 	      goto TERMINATE;
2780 	
2781 	   if(timeLimitReached())
2782 	      goto TERMINATE;
2783 	
2784 	   rowSingletons();
2785 	
2786 	   if(stat != SLinSolverRational::OK)
2787 	      goto TERMINATE;
2788 	
2789 	   if(temp.stage < thedim)
2790 	   {
2791 	      if(timeLimitReached())
2792 	         goto TERMINATE;
2793 	
2794 	      initFactorRings();
2795 	      eliminateNucleus(threshold);
2796 	      freeFactorRings();
2797 	   }
2798 	
2799 	TERMINATE:
2800 	
2801 	   l.firstUpdate = l.firstUnused;
2802 	
2803 	   if(stat == SLinSolverRational::OK)
2804 	   {
2805 	#ifdef WITH_L_ROWS
2806 	      setupRowVals();
2807 	#endif
2808 	      nzCnt = setupColVals();
2809 	   }
2810 	
2811 	   factorTime->stop();
2812 	
2813 	   factorCount++;
2814 	}
2815 	
2816 	inline void CLUFactorRational::dump() const
2817 	{
2818 	   int i, j, k;
2819 	
2820 	   // Dump regardless of the verbosity level if this method is called;
2821 	
2822 	   /*  Dump U:
2823 	    */
2824 	
2825 	   for(i = 0; i < thedim; ++i)
2826 	   {
2827 	      if(row.perm[i] >= 0)
2828 	         std::cout << "DCLUFA01 diag[" << i << "]: [" << col.orig[row.perm[i]]
2829 	                   << "] = " << diag[i] << std::endl;
2830 	
2831 	      for(j = 0; j < u.row.len[i]; ++j)
2832 	         std::cout << "DCLUFA02   u[" << i << "]: ["
2833 	                   << u.row.idx[u.row.start[i] + j] << "] = "
2834 	                   << u.row.val[u.row.start[i] + j] << std::endl;
2835 	   }
2836 	
2837 	   /*  Dump L:
2838 	    */
2839 	   for(i = 0; i < thedim; ++i)
2840 	   {
2841 	      for(j = 0; j < l.firstUnused; ++j)
2842 	         if(col.orig[row.perm[l.row[j]]] == i)
2843 	         {
2844 	            std::cout << "DCLUFA03 l[" << i << "]" << std::endl;
2845 	
2846 	            for(k = l.start[j]; k < l.start[j + 1]; ++k)
2847 	               std::cout << "DCLUFA04   l[" << k - l.start[j]
2848 	                         << "]:  [" << l.idx[k]
2849 	                         << "] = "  << l.val[k] << std::endl;
2850 	
2851 	            break;
2852 	         }
2853 	   }
2854 	
2855 	   return;
2856 	}
2857 	
2858 	/*****************************************************************************/
2859 	/*
2860 	 *      Ensure that row memory is at least size.
2861 	 */
2862 	inline void CLUFactorRational::minRowMem(int size)
2863 	{
2864 	   if(u.row.val.dim() < size)
2865 	   {
2866 	      u.row.val.reDim(size);
2867 	      spx_realloc(u.row.idx, size);
2868 	   }
2869 	
2870 	   assert(u.row.val.dim() >= size);
2871 	}
2872 	
2873 	/*****************************************************************************/
2874 	/*
2875 	 *      Ensure that column memory is at least size.
2876 	 */
2877 	inline void CLUFactorRational::minColMem(int size)
2878 	{
2879 	
2880 	   if(u.col.size < size)
2881 	   {
2882 	      u.col.size = size;
2883 	      spx_realloc(u.col.idx, size);
2884 	   }
2885 	}
2886 	
2887 	inline void CLUFactorRational::forestMinColMem(int size)
2888 	{
2889 	
2890 	   if(u.col.size < size)
2891 	   {
2892 	      u.col.size = size;
2893 	      spx_realloc(u.col.idx, size);
2894 	      u.col.val.reDim(size);
2895 	   }
2896 	}
2897 	
2898 	inline void CLUFactorRational::minLMem(int size)
2899 	{
2900 	
2901 	   if(size > l.val.dim())
2902 	   {
2903 	      int newsize = int(0.2 * l.val.dim() + size);
2904 	      l.val.reDim(newsize);
2905 	      spx_realloc(l.idx, l.val.dim());
2906 	   }
2907 	}
2908 	
2909 	
2910 	inline int CLUFactorRational::makeLvec(int p_len, int p_row)
2911 	{
2912 	
2913 	   if(l.firstUnused >= l.startSize)
2914 	   {
2915 	      l.startSize += 100;
2916 	      spx_realloc(l.start, l.startSize);
2917 	   }
2918 	
2919 	   int* p_lrow = l.row;
2920 	
2921 	   int* p_lbeg = l.start;
2922 	   int first   = p_lbeg[l.firstUnused];
2923 	
2924 	   assert(p_len > 0 && "ERROR: no empty columns allowed in L vectors");
2925 	
2926 	   minLMem(first + p_len);
2927 	   p_lrow[l.firstUnused] = p_row;
2928 	   l.start[++(l.firstUnused)] = first + p_len;
2929 	
2930 	   assert(l.start[l.firstUnused] <= l.val.dim());
2931 	   assert(l.firstUnused <= l.startSize);
2932 	   return first;
2933 	}
2934 	
2935 	
2936 	/*****************************************************************************/
2937 	
2938 	inline bool CLUFactorRational::isConsistent() const
2939 	{
2940 	#ifdef ENABLE_CONSISTENCY_CHECKS
2941 	   int              i, j, k, ll;
2942 	   Dring*            ring;
2943 	   CLUFactorRational::Pring* pring;
2944 	
2945 	   /*  Consistency only relevant for real factorizations
2946 	    */
2947 	
2948 	   if(stat)
2949 	      return true;
2950 	
2951 	   /*  Test column ring list consistency.
2952 	    */
2953 	   i = 0;
2954 	
2955 	   for(ring = u.col.list.next; ring != &(u.col.list); ring = ring->next)
2956 	   {
2957 	      assert(ring->idx >= 0);
2958 	      assert(ring->idx < thedim);
2959 	      assert(ring->prev->next == ring);
2960 	
2961 	      if(ring != u.col.list.next)
2962 	      {
2963 	         assert(u.col.start[ring->prev->idx] + u.col.max[ring->prev->idx]
2964 	                == u.col.start[ring->idx]);
2965 	      }
2966 	
2967 	      ++i;
2968 	   }
2969 	
2970 	   assert(i == thedim);
2971 	
2972 	   assert(u.col.start[ring->prev->idx] + u.col.max[ring->prev->idx]
2973 	          == u.col.used);
2974 	
2975 	
2976 	   /*  Test row ring list consistency.
2977 	    */
2978 	   i = 0;
2979 	
2980 	   for(ring = u.row.list.next; ring != &(u.row.list); ring = ring->next)
2981 	   {
2982 	      assert(ring->idx >= 0);
2983 	      assert(ring->idx < thedim);
2984 	      assert(ring->prev->next == ring);
2985 	      assert(u.row.start[ring->prev->idx] + u.row.max[ring->prev->idx]
2986 	             == u.row.start[ring->idx]);
2987 	      ++i;
2988 	   }
2989 	
2990 	   assert(i == thedim);
2991 	
2992 	   assert(u.row.start[ring->prev->idx] + u.row.max[ring->prev->idx]
2993 	          == u.row.used);
2994 	
2995 	
2996 	   /*  Test consistency of individual svectors.
2997 	    */
2998 	
2999 	   for(i = 0; i < thedim; ++i)
3000 	   {
3001 	      assert(u.row.max[i] >= u.row.len[i]);
3002 	      assert(u.col.max[i] >= u.col.len[i]);
3003 	   }
3004 	
3005 	
3006 	   /*  Test consistency of column file to row file of U
3007 	    */
3008 	   for(i = 0; i < thedim; ++i)
3009 	   {
3010 	      for(j = u.row.start[i] + u.row.len[i] - 1; j >= u.row.start[i]; j--)
3011 	      {
3012 	         k = u.row.idx[j];
3013 	
3014 	         for(ll = u.col.start[k] + u.col.len[k] - 1; ll >= u.col.start[k]; ll--)
3015 	         {
3016 	            if(u.col.idx[ll] == i)
3017 	               break;
3018 	         }
3019 	
3020 	         assert(u.col.idx[ll] == i);
3021 	
3022 	         if(row.perm[i] < 0)
3023 	         {
3024 	            assert(col.perm[k] < 0);
3025 	         }
3026 	         else
3027 	         {
3028 	            assert(col.perm[k] < 0 || col.perm[k] > row.perm[i]);
3029 	         }
3030 	      }
3031 	   }
3032 	
3033 	   /*  Test consistency of row file to column file of U
3034 	    */
3035 	   for(i = 0; i < thedim; ++i)
3036 	   {
3037 	      for(j = u.col.start[i] + u.col.len[i] - 1; j >= u.col.start[i]; j--)
3038 	      {
3039 	         k = u.col.idx[j];
3040 	
3041 	         for(ll = u.row.start[k] + u.row.len[k] - 1; ll >= u.row.start[k]; ll--)
3042 	         {
3043 	            if(u.row.idx[ll] == i)
3044 	               break;
3045 	         }
3046 	
3047 	         assert(u.row.idx[ll] == i);
3048 	
3049 	         assert(col.perm[i] < 0 || row.perm[k] < col.perm[i]);
3050 	      }
3051 	   }
3052 	
3053 	   /*  Test consistency of nonzero count lists
3054 	    */
3055 	   if(temp.pivot_colNZ && temp.pivot_rowNZ)
3056 	   {
3057 	      for(i = 0; i < thedim - temp.stage; ++i)
3058 	      {
3059 	         for(pring = temp.pivot_rowNZ[i].next; pring != &(temp.pivot_rowNZ[i]); pring = pring->next)
3060 	         {
3061 	            assert(row.perm[pring->idx] < 0);
3062 	         }
3063 	
3064 	         for(pring = temp.pivot_colNZ[i].next; pring != &(temp.pivot_colNZ[i]); pring = pring->next)
3065 	         {
3066 	            assert(col.perm[pring->idx] < 0);
3067 	         }
3068 	      }
3069 	   }
3070 	
3071 	#endif // CONSISTENCY_CHECKS
3072 	
3073 	   return true;
3074 	}
3075 	
3076 	inline void CLUFactorRational::solveUright(Rational* wrk, Rational* vec)
3077 	{
3078 	
3079 	   for(int i = thedim - 1; i >= 0; i--)
3080 	   {
3081 	      int  r = row.orig[i];
3082 	      int  c = col.orig[i];
3083 	      Rational x = wrk[c] = diag[r] * vec[r];
3084 	
3085 	      vec[r] = 0;
3086 	
3087 	      if(x != 0)
3088 	         //if (isNotZero(x))
3089 	      {
3090 	         if(timeLimitReached())
3091 	            return;
3092 	
3093 	         for(int j = u.col.start[c]; j < u.col.start[c] + u.col.len[c]; j++)
3094 	            vec[u.col.idx[j]] -= x * u.col.val[j];
3095 	      }
3096 	   }
3097 	}
3098 	
3099 	inline int CLUFactorRational::solveUrightEps(Rational* vec, int* nonz, Rational* rhs)
3100 	{
3101 	   int i, j, r, c, n;
3102 	   int* rorig, *corig;
3103 	   int* cidx, *clen, *cbeg;
3104 	   Rational x;
3105 	
3106 	   int* idx;
3107 	   Rational* val;
3108 	
3109 	   rorig = row.orig;
3110 	   corig = col.orig;
3111 	
3112 	   cidx = u.col.idx;
3113 	   VectorRational& cval = u.col.val;
3114 	   clen = u.col.len;
3115 	   cbeg = u.col.start;
3116 	
3117 	   n = 0;
3118 	
3119 	   for(i = thedim - 1; i >= 0; --i)
3120 	   {
3121 	      r = rorig[i];
3122 	      x = diag[r] * rhs[r];
3123 	
3124 	      if(x != 0)
3125 	      {
3126 	         c = corig[i];
3127 	         vec[c] = x;
3128 	         nonz[n++] = c;
3129 	         val = &cval[cbeg[c]];
3130 	         idx = &cidx[cbeg[c]];
3131 	         j = clen[c];
3132 	
3133 	         while(j-- > 0)
3134 	            rhs[*idx++] -= x * (*val++);
3135 	      }
3136 	   }
3137 	
3138 	   return n;
3139 	}
3140 	
3141 	inline void CLUFactorRational::solveUright2(Rational* p_work1, Rational* vec1, Rational* p_work2,
3142 	      Rational* vec2)
3143 	{
3144 	   int i, j, r, c;
3145 	   int* rorig, *corig;
3146 	   int* cidx, *clen, *cbeg;
3147 	   Rational x1, x2;
3148 	
3149 	   int* idx;
3150 	   Rational* val;
3151 	
3152 	   rorig = row.orig;
3153 	   corig = col.orig;
3154 	
3155 	   cidx = u.col.idx;
3156 	   VectorRational& cval = u.col.val;
3157 	   clen = u.col.len;
3158 	   cbeg = u.col.start;
3159 	
3160 	   for(i = thedim - 1; i >= 0; --i)
3161 	   {
3162 	      r = rorig[i];
3163 	      c = corig[i];
3164 	      p_work1[c] = x1 = diag[r] * vec1[r];
3165 	      p_work2[c] = x2 = diag[r] * vec2[r];
3166 	      vec1[r] = vec2[r] = 0;
3167 	
3168 	      if(x1 != 0 && x2 != 0)
3169 	      {
3170 	         val = &cval[cbeg[c]];
3171 	         idx = &cidx[cbeg[c]];
3172 	         j = clen[c];
3173 	
3174 	         while(j-- > 0)
3175 	         {
3176 	            vec1[*idx] -= x1 * (*val);
3177 	            vec2[*idx++] -= x2 * (*val++);
3178 	         }
3179 	      }
3180 	      else if(x1 != 0)
3181 	      {
3182 	         val = &cval[cbeg[c]];
3183 	         idx = &cidx[cbeg[c]];
3184 	         j = clen[c];
3185 	
3186 	         while(j-- > 0)
3187 	            vec1[*idx++] -= x1 * (*val++);
3188 	      }
3189 	      else if(x2 != 0)
3190 	      {
3191 	         val = &cval[cbeg[c]];
3192 	         idx = &cidx[cbeg[c]];
3193 	         j = clen[c];
3194 	
3195 	         while(j-- > 0)
3196 	            vec2[*idx++] -= x2 * (*val++);
3197 	      }
3198 	   }
3199 	}
3200 	
3201 	inline int CLUFactorRational::solveUright2eps(Rational* p_work1, Rational* vec1, Rational* p_work2,
3202 	      Rational* vec2, int* nonz)
3203 	{
3204 	   int i, j, r, c, n;
3205 	   int* rorig, *corig;
3206 	   int* cidx, *clen, *cbeg;
3207 	   bool notzero1, notzero2;
3208 	   Rational x1, x2;
3209 	
3210 	   int* idx;
3211 	   Rational* val;
3212 	
3213 	   rorig = row.orig;
3214 	   corig = col.orig;
3215 	
3216 	   cidx = u.col.idx;
3217 	   VectorRational& cval = u.col.val;
3218 	   clen = u.col.len;
3219 	   cbeg = u.col.start;
3220 	
3221 	   n = 0;
3222 	
3223 	   for(i = thedim - 1; i >= 0; --i)
3224 	   {
3225 	      c = corig[i];
3226 	      r = rorig[i];
3227 	      p_work1[c] = x1 = diag[r] * vec1[r];
3228 	      p_work2[c] = x2 = diag[r] * vec2[r];
3229 	      vec1[r] = vec2[r] = 0;
3230 	      notzero1 = x1 != 0 ? 1 : 0;
3231 	      notzero2 = x2 != 0 ? 1 : 0;
3232 	
3233 	      if(notzero1 && notzero2)
3234 	      {
3235 	         *nonz++ = c;
3236 	         n++;
3237 	         val = &cval[cbeg[c]];
3238 	         idx = &cidx[cbeg[c]];
3239 	         j = clen[c];
3240 	
3241 	         while(j-- > 0)
3242 	         {
3243 	            vec1[*idx] -= x1 * (*val);
3244 	            vec2[*idx++] -= x2 * (*val++);
3245 	         }
3246 	      }
3247 	      else if(notzero1)
3248 	      {
3249 	         p_work2[c] = 0;
3250 	         *nonz++ = c;
3251 	         n++;
3252 	         val = &cval[cbeg[c]];
3253 	         idx = &cidx[cbeg[c]];
3254 	         j = clen[c];
3255 	
3256 	         while(j-- > 0)
3257 	            vec1[*idx++] -= x1 * (*val++);
3258 	      }
3259 	      else if(notzero2)
3260 	      {
3261 	         p_work1[c] = 0;
3262 	         val = &cval[cbeg[c]];
3263 	         idx = &cidx[cbeg[c]];
3264 	         j = clen[c];
3265 	
3266 	         while(j-- > 0)
3267 	            vec2[*idx++] -= x2 * (*val++);
3268 	      }
3269 	      else
3270 	      {
3271 	         p_work1[c] = 0;
3272 	         p_work2[c] = 0;
3273 	      }
3274 	   }
3275 	
3276 	   return n;
3277 	}
3278 	
3279 	inline void CLUFactorRational::solveLright(Rational* vec)
3280 	{
3281 	   int i, j, k;
3282 	   int end;
3283 	   Rational x;
3284 	   Rational* val;
3285 	   int* lrow, *lidx, *idx;
3286 	   int* lbeg;
3287 	
3288 	   VectorRational& lval = l.val;
3289 	   lidx = l.idx;
3290 	   lrow = l.row;
3291 	   lbeg = l.start;
3292 	
3293 	   end = l.firstUpdate;
3294 	
3295 	   for(i = 0; i < end; ++i)
3296 	   {
3297 	      if((x = vec[lrow[i]]) != 0)
3298 	      {
3299 	         if(timeLimitReached())
3300 	            return;
3301 	
3302 	         MSG_DEBUG(std::cout << "y" << lrow[i] << "=" << vec[lrow[i]] << std::endl;)
3303 	
3304 	         k = lbeg[i];
3305 	         idx = &(lidx[k]);
3306 	         val = &(lval[k]);
3307 	
3308 	         for(j = lbeg[i + 1]; j > k; --j)
3309 	         {
3310 	            MSG_DEBUG(std::cout << "                         -> y" << *idx << " -= " << x << " * " << *val <<
3311 	                      " = " << x * (*val) << "    -> " << vec[*idx] - x * (*val) << std::endl;)
3312 	            vec[*idx++] -= x * (*val++);
3313 	         }
3314 	      }
3315 	   }
3316 	
3317 	   if(l.updateType)                      /* Forest-Tomlin Updates */
3318 	   {
3319 	      MSG_DEBUG(std::cout << "performing FT updates..." << std::endl;)
3320 	
3321 	      end = l.firstUnused;
3322 	
3323 	      for(; i < end; ++i)
3324 	      {
3325 	         x = 0;
3326 	         k = lbeg[i];
3327 	         idx = &(lidx[k]);
3328 	         val = &(lval[k]);
3329 	
3330 	         for(j = lbeg[i + 1]; j > k; --j)
3331 	            x += vec[*idx++] * (*val++);
3332 	
3333 	         vec[lrow[i]] -= x;
3334 	
3335 	         MSG_DEBUG(std::cout << "y" << lrow[i] << "=" << vec[lrow[i]] << std::endl;)
3336 	      }
3337 	
3338 	      MSG_DEBUG(std::cout << "finished FT updates." << std::endl;)
3339 	   }
3340 	}
3341 	
3342 	inline void CLUFactorRational::solveLright2(Rational* vec1, Rational* vec2)
3343 	{
3344 	   int i, j, k;
3345 	   int end;
3346 	   Rational x2;
3347 	   Rational x1;
3348 	   Rational* val;
3349 	   int* lrow, *lidx, *idx;
3350 	   int* lbeg;
3351 	
3352 	   VectorRational& lval = l.val;
3353 	   lidx = l.idx;
3354 	   lrow = l.row;
3355 	   lbeg = l.start;
3356 	
3357 	   end = l.firstUpdate;
3358 	
3359 	   for(i = 0; i < end; ++i)
3360 	   {
3361 	      x1 = vec1[lrow[i]];
3362 	      x2 = vec2[lrow[i]];
3363 	
3364 	      if(x1 != 0 && x2 != 0)
3365 	      {
3366 	         k = lbeg[i];
3367 	         idx = &(lidx[k]);
3368 	         val = &(lval[k]);
3369 	
3370 	         for(j = lbeg[i + 1]; j > k; --j)
3371 	         {
3372 	            vec1[*idx] -= x1 * (*val);
3373 	            vec2[*idx++] -= x2 * (*val++);
3374 	         }
3375 	      }
3376 	      else if(x1 != 0)
3377 	      {
3378 	         k = lbeg[i];
3379 	         idx = &(lidx[k]);
3380 	         val = &(lval[k]);
3381 	
3382 	         for(j = lbeg[i + 1]; j > k; --j)
3383 	            vec1[*idx++] -= x1 * (*val++);
3384 	      }
3385 	      else if(x2 != 0)
3386 	      {
3387 	         k = lbeg[i];
3388 	         idx = &(lidx[k]);
3389 	         val = &(lval[k]);
3390 	
3391 	         for(j = lbeg[i + 1]; j > k; --j)
3392 	            vec2[*idx++] -= x2 * (*val++);
3393 	      }
3394 	   }
3395 	
3396 	   if(l.updateType)                      /* Forest-Tomlin Updates */
3397 	   {
3398 	      end = l.firstUnused;
3399 	
3400 	      for(; i < end; ++i)
3401 	      {
3402 	         x1 = 0;
3403 	         x2 = 0;
3404 	         k = lbeg[i];
3405 	         idx = &(lidx[k]);
3406 	         val = &(lval[k]);
3407 	
3408 	         for(j = lbeg[i + 1]; j > k; --j)
3409 	         {
3410 	            x1 += vec1[*idx] * (*val);
3411 	            x2 += vec2[*idx++] * (*val++);
3412 	         }
3413 	
3414 	         vec1[lrow[i]] -= x1;
3415 	
3416 	         vec2[lrow[i]] -= x2;
3417 	      }
3418 	   }
3419 	}
3420 	
3421 	inline void CLUFactorRational::solveUpdateRight(Rational* vec)
3422 	{
3423 	   int i, j, k;
3424 	   int end;
3425 	   Rational x;
3426 	   Rational* val;
3427 	   int* lrow, *lidx, *idx;
3428 	   int* lbeg;
3429 	
3430 	   assert(!l.updateType);               /* no Forest-Tomlin Updates */
3431 	
3432 	   VectorRational& lval = l.val;
3433 	   lidx = l.idx;
3434 	   lrow = l.row;
3435 	   lbeg = l.start;
3436 	
3437 	   end = l.firstUnused;
3438 	
3439 	   for(i = l.firstUpdate; i < end; ++i)
3440 	   {
3441 	      if((x = vec[lrow[i]]) != 0)
3442 	      {
3443 	         k = lbeg[i];
3444 	         idx = &(lidx[k]);
3445 	         val = &(lval[k]);
3446 	
3447 	         for(j = lbeg[i + 1]; j > k; --j)
3448 	            vec[*idx++] -= x * (*val++);
3449 	      }
3450 	   }
3451 	}
3452 	
3453 	inline void CLUFactorRational::solveUpdateRight2(Rational* vec1, Rational* vec2)
3454 	{
3455 	   int i, j, k;
3456 	   int end;
3457 	   Rational x1, x2;
3458 	   int* lrow, *lidx;
3459 	   int* lbeg;
3460 	
3461 	   int* idx;
3462 	   Rational* val;
3463 	
3464 	   assert(!l.updateType);               /* no Forest-Tomlin Updates */
3465 	
3466 	   VectorRational& lval = l.val;
3467 	   lidx = l.idx;
3468 	   lrow = l.row;
3469 	   lbeg = l.start;
3470 	
3471 	   end = l.firstUnused;
3472 	
3473 	   for(i = l.firstUpdate; i < end; ++i)
3474 	   {
3475 	      x1 = vec1[lrow[i]];
3476 	      x2 = vec2[lrow[i]];
3477 	
3478 	      if(x1 != 0 && x2 != 0)
3479 	      {
3480 	         k = lbeg[i];
3481 	         idx = &(lidx[k]);
3482 	         val = &(lval[k]);
3483 	
3484 	         for(j = lbeg[i + 1]; j > k; --j)
3485 	         {
3486 	            vec1[*idx] -= x1 * (*val);
3487 	            vec2[*idx++] -= x2 * (*val++);
3488 	         }
3489 	      }
3490 	      else if(x1 != 0)
3491 	      {
3492 	         k = lbeg[i];
3493 	         idx = &(lidx[k]);
3494 	         val = &(lval[k]);
3495 	
3496 	         for(j = lbeg[i + 1]; j > k; --j)
3497 	            vec1[*idx++] -= x1 * (*val++);
3498 	      }
3499 	      else if(x2 != 0)
3500 	      {
3501 	         k = lbeg[i];
3502 	         idx = &(lidx[k]);
3503 	         val = &(lval[k]);
3504 	
3505 	         for(j = lbeg[i + 1]; j > k; --j)
3506 	            vec2[*idx++] -= x2 * (*val++);
3507 	      }
3508 	   }
3509 	}
3510 	
3511 	inline int CLUFactorRational::solveRight4update(Rational* vec, int* nonz,
3512 	      Rational* rhs, Rational* forest, int* forestNum, int* forestIdx)
3513 	{
3514 	   solveLright(rhs);
3515 	
3516 	   if(forest)
3517 	   {
3518 	      int n = 0;
3519 	
3520 	      for(int i = 0; i < thedim; i++)
3521 	      {
3522 	         forestIdx[n] = i;
3523 	         forest[i]    = rhs[i];
3524 	         n           += rhs[i] != 0 ? 1 : 0;
3525 	      }
3526 	
3527 	      *forestNum = n;
3528 	   }
3529 	
3530 	   if(!l.updateType)             /* no Forest-Tomlin Updates */
3531 	   {
3532 	      solveUright(vec, rhs);
3533 	      solveUpdateRight(vec);
3534 	      return 0;
3535 	   }
3536 	   else
3537 	      return solveUrightEps(vec, nonz, rhs);
3538 	}
3539 	
3540 	inline void CLUFactorRational::solveRight(Rational* vec, Rational* rhs)
3541 	{
3542 	   solveLright(rhs);
3543 	   solveUright(vec, rhs);
3544 	
3545 	   if(!l.updateType)             /* no Forest-Tomlin Updates */
3546 	      solveUpdateRight(vec);
3547 	}
3548 	
3549 	inline int CLUFactorRational::solveRight2update(Rational* vec1,
3550 	      Rational* vec2,
3551 	      Rational* rhs1,
3552 	      Rational* rhs2,
3553 	      int* nonz,
3554 	      Rational* forest,
3555 	      int* forestNum,
3556 	      int* forestIdx)
3557 	{
3558 	   solveLright2(rhs1, rhs2);
3559 	
3560 	   if(forest)
3561 	   {
3562 	      int n = 0;
3563 	
3564 	      for(int i = 0; i < thedim; i++)
3565 	      {
3566 	         forestIdx[n] = i;
3567 	         forest[i]    = rhs1[i];
3568 	         n           += rhs1[i] != 0 ? 1 : 0;
3569 	      }
3570 	
3571 	      *forestNum = n;
3572 	   }
3573 	
3574 	   if(!l.updateType)            /* no Forest-Tomlin Updates */
3575 	   {
3576 	      solveUright2(vec1, rhs1, vec2, rhs2);
3577 	      solveUpdateRight2(vec1, vec2);
3578 	      return 0;
3579 	   }
3580 	   else
3581 	      return solveUright2eps(vec1, rhs1, vec2, rhs2, nonz);
3582 	}
3583 	
3584 	inline void CLUFactorRational::solveRight2(
3585 	   Rational* vec1,
3586 	   Rational* vec2,
3587 	   Rational* rhs1,
3588 	   Rational* rhs2)
3589 	{
3590 	   solveLright2(rhs1, rhs2);
3591 	
3592 	   if(l.updateType)              /* Forest-Tomlin Updates */
3593 	      solveUright2(vec1, rhs1, vec2, rhs2);
3594 	   else
3595 	   {
3596 	      solveUright2(vec1, rhs1, vec2, rhs2);
3597 	      solveUpdateRight2(vec1, vec2);
3598 	   }
3599 	}
3600 	
3601 	/*****************************************************************************/
3602 	inline void CLUFactorRational::solveUleft(Rational* p_work, Rational* vec)
3603 	{
3604 	   for(int i = 0; i < thedim; ++i)
3605 	   {
3606 	      int  c  = col.orig[i];
3607 	      int  r  = row.orig[i];
3608 	
3609 	      assert(c >= 0);    // Inna/Tobi: otherwise, vec[c] would be strange...
3610 	      assert(r >= 0);    // Inna/Tobi: otherwise, diag[r] would be strange...
3611 	
3612 	      Rational x  = vec[c];
3613 	
3614 	      vec[c]  = 0;
3615 	
3616 	      if(x != 0)
3617 	      {
3618 	         if(timeLimitReached())
3619 	            return;
3620 	
3621 	         x        *= diag[r];
3622 	         p_work[r] = x;
3623 	
3624 	         int end = u.row.start[r] + u.row.len[r];
3625 	
3626 	         for(int m = u.row.start[r]; m < end; m++)
3627 	         {
3628 	            vec[u.row.idx[m]] -= x * u.row.val[m];
3629 	         }
3630 	      }
3631 	   }
3632 	}
3633 	
3634 	
3635 	
3636 	inline void CLUFactorRational::solveUleft2(Rational* p_work1, Rational* vec1, Rational* p_work2,
3637 	      Rational* vec2)
3638 	{
3639 	   Rational x1;
3640 	   Rational x2;
3641 	   int i, k, r, c;
3642 	   int* rorig, *corig;
3643 	   int* ridx, *rlen, *rbeg, *idx;
3644 	   Rational* val;
3645 	
3646 	   rorig = row.orig;
3647 	   corig = col.orig;
3648 	
3649 	   ridx = u.row.idx;
3650 	   VectorRational& rval = u.row.val;
3651 	   rlen = u.row.len;
3652 	   rbeg = u.row.start;
3653 	
3654 	   for(i = 0; i < thedim; ++i)
3655 	   {
3656 	      c = corig[i];
3657 	      r = rorig[i];
3658 	      x1 = vec1[c];
3659 	      x2 = vec2[c];
3660 	
3661 	      if((x1 != 0) && (x2 != 0))
3662 	      {
3663 	         x1 *= diag[r];
3664 	         x2 *= diag[r];
3665 	         p_work1[r] = x1;
3666 	         p_work2[r] = x2;
3667 	         k = rbeg[r];
3668 	         idx = &ridx[k];
3669 	         val = &rval[k];
3670 	
3671 	         for(int m = rlen[r]; m != 0; --m)
3672 	         {
3673 	            vec1[*idx] -= x1 * (*val);
3674 	            vec2[*idx] -= x2 * (*val++);
3675 	            idx++;
3676 	         }
3677 	      }
3678 	      else if(x1 != 0)
3679 	      {
3680 	         x1 *= diag[r];
3681 	         p_work1[r] = x1;
3682 	         k = rbeg[r];
3683 	         idx = &ridx[k];
3684 	         val = &rval[k];
3685 	
3686 	         for(int m = rlen[r]; m != 0; --m)
3687 	            vec1[*idx++] -= x1 * (*val++);
3688 	      }
3689 	      else if(x2 != 0)
3690 	      {
3691 	         x2 *= diag[r];
3692 	         p_work2[r] = x2;
3693 	         k = rbeg[r];
3694 	         idx = &ridx[k];
3695 	         val = &rval[k];
3696 	
3697 	         for(int m = rlen[r]; m != 0; --m)
3698 	            vec2[*idx++] -= x2 * (*val++);
3699 	      }
3700 	   }
3701 	}
3702 	
3703 	inline int CLUFactorRational::solveLleft2forest(Rational* vec1, int* /* nonz */, Rational* vec2)
3704 	{
3705 	   int i;
3706 	   int j;
3707 	   int k;
3708 	   int end;
3709 	   Rational x1, x2;
3710 	   Rational* val;
3711 	   int* lidx, *idx, *lrow;
3712 	   int* lbeg;
3713 	
3714 	   VectorRational& lval = l.val;
3715 	   lidx = l.idx;
3716 	   lrow = l.row;
3717 	   lbeg = l.start;
3718 	
3719 	   end = l.firstUpdate;
3720 	
3721 	   for(i = l.firstUnused - 1; i >= end; --i)
3722 	   {
3723 	      j = lrow[i];
3724 	      x1 = vec1[j];
3725 	      x2 = vec2[j];
3726 	
3727 	      if(x1 != 0)
3728 	      {
3729 	         if(x2 != 0)
3730 	         {
3731 	            k = lbeg[i];
3732 	            val = &lval[k];
3733 	            idx = &lidx[k];
3734 	
3735 	            for(j = lbeg[i + 1]; j > k; --j)
3736 	            {
3737 	               vec1[*idx] -= x1 * (*val);
3738 	               vec2[*idx++] -= x2 * (*val++);
3739 	            }
3740 	         }
3741 	         else
3742 	         {
3743 	            k = lbeg[i];
3744 	            val = &lval[k];
3745 	            idx = &lidx[k];
3746 	
3747 	            for(j = lbeg[i + 1]; j > k; --j)
3748 	               vec1[*idx++] -= x1 * (*val++);
3749 	         }
3750 	      }
3751 	      else if(x2 != 0)
3752 	      {
3753 	         k = lbeg[i];
3754 	         val = &lval[k];
3755 	         idx = &lidx[k];
3756 	
3757 	         for(j = lbeg[i + 1]; j > k; --j)
3758 	            vec2[*idx++] -= x2 * (*val++);
3759 	      }
3760 	   }
3761 	
3762 	   return 0;
3763 	}
3764 	
3765 	inline void CLUFactorRational::solveLleft2(Rational* vec1, int* /* nonz */, Rational* vec2)
3766 	{
3767 	   int i, j, k, r;
3768 	   int x1not0, x2not0;
3769 	   Rational x1, x2;
3770 	
3771 	   Rational* val;
3772 	   int* ridx, *idx;
3773 	   int* rbeg;
3774 	   int* rorig;
3775 	
3776 	   ridx  = l.ridx;
3777 	   VectorRational& rval = l.rval;
3778 	   rbeg  = l.rbeg;
3779 	   rorig = l.rorig;
3780 	
3781 	#ifndef WITH_L_ROWS
3782 	   VectorRational& lval  = l.val;
3783 	   int*    lidx  = l.idx;
3784 	   int*    lrow  = l.row;
3785 	   int*    lbeg  = l.start;
3786 	
3787 	   i = l.firstUpdate - 1;
3788 	
3789 	   for(; i >= 0; --i)
3790 	   {
3791 	      k = lbeg[i];
3792 	      val = &lval[k];
3793 	      idx = &lidx[k];
3794 	      x1 = 0;
3795 	      x2 = 0;
3796 	
3797 	      for(j = lbeg[i + 1]; j > k; --j)
3798 	      {
3799 	         x1 += vec1[*idx] * (*val);
3800 	         x2 += vec2[*idx++] * (*val++);
3801 	      }
3802 	
3803 	      vec1[lrow[i]] -= x1;
3804 	
3805 	      vec2[lrow[i]] -= x2;
3806 	   }
3807 	
3808 	#else
3809 	
3810 	   for(i = thedim; i--;)
3811 	   {
3812 	      r = rorig[i];
3813 	      x1 = vec1[r];
3814 	      x2 = vec2[r];
3815 	      x1not0 = (x1 != 0);
3816 	      x2not0 = (x2 != 0);
3817 	
3818 	      if(x1not0 && x2not0)
3819 	      {
3820 	         k = rbeg[r];
3821 	         j = rbeg[r + 1] - k;
3822 	         val = &rval[k];
3823 	         idx = &ridx[k];
3824 	
3825 	         while(j-- > 0)
3826 	         {
3827 	            assert(row.perm[*idx] < i);
3828 	            vec1[*idx] -= x1 * *val;
3829 	            vec2[*idx++] -= x2 * *val++;
3830 	         }
3831 	      }
3832 	      else if(x1not0)
3833 	      {
3834 	         k = rbeg[r];
3835 	         j = rbeg[r + 1] - k;
3836 	         val = &rval[k];
3837 	         idx = &ridx[k];
3838 	
3839 	         while(j-- > 0)
3840 	         {
3841 	            assert(row.perm[*idx] < i);
3842 	            vec1[*idx++] -= x1 * *val++;
3843 	         }
3844 	      }
3845 	      else if(x2not0)
3846 	      {
3847 	         k = rbeg[r];
3848 	         j = rbeg[r + 1] - k;
3849 	         val = &rval[k];
3850 	         idx = &ridx[k];
3851 	
3852 	         while(j-- > 0)
3853 	         {
3854 	            assert(row.perm[*idx] < i);
3855 	            vec2[*idx++] -= x2 * *val++;
3856 	         }
3857 	      }
3858 	   }
3859 	
3860 	#endif
3861 	}
3862 	
3863 	inline int CLUFactorRational::solveLleftForest(Rational* vec, int* /* nonz */)
3864 	{
3865 	   int i, j, k, end;
3866 	   Rational x;
3867 	   Rational* val;
3868 	   int* idx, *lidx, *lrow, *lbeg;
3869 	
3870 	   VectorRational& lval = l.val;
3871 	   lidx = l.idx;
3872 	   lrow = l.row;
3873 	   lbeg = l.start;
3874 	
3875 	   end = l.firstUpdate;
3876 	
3877 	   for(i = l.firstUnused - 1; i >= end; --i)
3878 	   {
3879 	      if((x = vec[lrow[i]]) != 0)
3880 	      {
3881 	         if(timeLimitReached())
3882 	            return 0;
3883 	
3884 	         k = lbeg[i];
3885 	         val = &lval[k];
3886 	         idx = &lidx[k];
3887 	
3888 	         for(j = lbeg[i + 1]; j > k; --j)
3889 	            vec[*idx++] -= x * (*val++);
3890 	      }
3891 	   }
3892 	
3893 	   return 0;
3894 	}
3895 	
3896 	inline void CLUFactorRational::solveLleft(Rational* vec)
3897 	{
3898 	
3899 	#ifndef WITH_L_ROWS
3900 	   int*  idx;
3901 	   Rational* val;
3902 	   VectorRational& lval  = l.val;
3903 	   int*  lidx  = l.idx;
3904 	   int*  lrow  = l.row;
3905 	   int*  lbeg  = l.start;
3906 	
3907 	   for(int i = l.firstUpdate - 1; i >= 0; --i)
3908 	   {
3909 	      if(timeLimitReached())
3910 	         return;
3911 	
3912 	      int k = lbeg[i];
3913 	      val = &lval[k];
3914 	      idx = &lidx[k];
3915 	      x = 0;
3916 	
3917 	      for(int j = lbeg[i + 1]; j > k; --j)
3918 	         x += vec[*idx++] * (*val++);
3919 	
3920 	      vec[lrow[i]] -= x;
3921 	   }
3922 	
3923 	#else
3924 	
3925 	   for(int i = thedim - 1; i >= 0; --i)
3926 	   {
3927 	      int  r = l.rorig[i];
3928 	      Rational x = vec[r];
3929 	
3930 	      if(x != 0)
3931 	      {
3932 	         if(timeLimitReached())
3933 	            return;
3934 	
3935 	         for(int k = l.rbeg[r]; k < l.rbeg[r + 1]; k++)
3936 	         {
3937 	            int j = l.ridx[k];
3938 	
3939 	            assert(l.rperm[j] < i);
3940 	
3941 	            vec[j] -= x * l.rval[k];
3942 	         }
3943 	      }
3944 	   }
3945 	
3946 	#endif // WITH_L_ROWS
3947 	}
3948 	
3949 	inline int CLUFactorRational::solveLleftEps(Rational* vec, int* nonz)
3950 	{
3951 	   int i, j, k, n;
3952 	   int r;
3953 	   Rational x;
3954 	   Rational* val;
3955 	   int* ridx, *idx;
3956 	   int* rbeg;
3957 	   int* rorig;
3958 	
3959 	   ridx = l.ridx;
3960 	   VectorRational& rval = l.rval;
3961 	   rbeg = l.rbeg;
3962 	   rorig = l.rorig;
3963 	   n = 0;
3964 	#ifndef WITH_L_ROWS
3965 	   VectorRational& lval = l.val;
3966 	   int*  lidx = l.idx;
3967 	   int*  lrow = l.row;
3968 	   int*  lbeg = l.start;
3969 	
3970 	   for(i = l.firstUpdate - 1; i >= 0; --i)
3971 	   {
3972 	      k = lbeg[i];
3973 	      val = &lval[k];
3974 	      idx = &lidx[k];
3975 	      x = 0;
3976 	
3977 	      for(j = lbeg[i + 1]; j > k; --j)
3978 	         x += vec[*idx++] * (*val++);
3979 	
3980 	      vec[lrow[i]] -= x;
3981 	   }
3982 	
3983 	#else
3984 	
3985 	   for(i = thedim; i--;)
3986 	   {
3987 	      r = rorig[i];
3988 	      x = vec[r];
3989 	
3990 	      if(x != 0)
3991 	      {
3992 	         *nonz++ = r;
3993 	         n++;
3994 	         k = rbeg[r];
3995 	         j = rbeg[r + 1] - k;
3996 	         val = &rval[k];
3997 	         idx = &ridx[k];
3998 	
3999 	         while(j-- > 0)
4000 	         {
4001 	            assert(row.perm[*idx] < i);
4002 	            vec[*idx++] -= x * *val++;
4003 	         }
4004 	      }
4005 	      else
4006 	         vec[r] = 0;
4007 	   }
4008 	
4009 	#endif
4010 	
4011 	   return n;
4012 	}
4013 	
4014 	inline void CLUFactorRational::solveUpdateLeft(Rational* vec)
4015 	{
4016 	   int i, j, k, end;
4017 	   Rational x;
4018 	   Rational* val;
4019 	   int* lrow, *lidx, *idx;
4020 	   int* lbeg;
4021 	
4022 	   VectorRational& lval = l.val;
4023 	   lidx = l.idx;
4024 	   lrow = l.row;
4025 	   lbeg = l.start;
4026 	
4027 	   assert(!l.updateType);               /* Forest-Tomlin Updates */
4028 	
4029 	   end = l.firstUpdate;
4030 	
4031 	   for(i = l.firstUnused - 1; i >= end; --i)
4032 	   {
4033 	      k = lbeg[i];
4034 	      val = &lval[k];
4035 	      idx = &lidx[k];
4036 	      x = 0;
4037 	
4038 	      for(j = lbeg[i + 1]; j > k; --j)
4039 	         x += vec[*idx++] * (*val++);
4040 	
4041 	      vec[lrow[i]] -= x;
4042 	   }
4043 	}
4044 	
4045 	inline void CLUFactorRational::solveUpdateLeft2(Rational* vec1, Rational* vec2)
4046 	{
4047 	   int i, j, k, end;
4048 	   Rational x1, x2;
4049 	   Rational* val;
4050 	   int* lrow, *lidx, *idx;
4051 	   int* lbeg;
4052 	
4053 	   VectorRational& lval = l.val;
4054 	   lidx = l.idx;
4055 	   lrow = l.row;
4056 	   lbeg = l.start;
4057 	
4058 	   assert(!l.updateType);               /* Forest-Tomlin Updates */
4059 	
4060 	   end = l.firstUpdate;
4061 	
4062 	   for(i = l.firstUnused - 1; i >= end; --i)
4063 	   {
4064 	      k = lbeg[i];
4065 	      val = &lval[k];
4066 	      idx = &lidx[k];
4067 	      x1 = 0;
4068 	      x2 = 0;
4069 	
4070 	      for(j = lbeg[i + 1]; j > k; --j)
4071 	      {
4072 	         x1 += vec1[*idx] * (*val);
4073 	         x2 += vec2[*idx++] * (*val++);
4074 	      }
4075 	
4076 	      vec1[lrow[i]] -= x1;
4077 	
4078 	      vec2[lrow[i]] -= x2;
4079 	   }
4080 	}
4081 	
4082 	inline int CLUFactorRational::solveUpdateLeft(Rational* vec, int* nonz, int n)
4083 	{
4084 	   int i, j, k, end;
4085 	   Rational x, y;
4086 	   Rational* val;
4087 	   int* lrow, *lidx, *idx;
4088 	   int* lbeg;
4089 	
4090 	   assert(!l.updateType);               /* no Forest-Tomlin Updates! */
4091 	
4092 	   VectorRational& lval = l.val;
4093 	   lidx = l.idx;
4094 	   lrow = l.row;
4095 	   lbeg = l.start;
4096 	
4097 	   end = l.firstUpdate;
4098 	
4099 	   for(i = l.firstUnused - 1; i >= end; --i)
4100 	   {
4101 	      k = lbeg[i];
4102 	      assert(k >= 0 && k < l.val.dim());
4103 	      val = &lval[k];
4104 	      idx = &lidx[k];
4105 	      x = 0;
4106 	
4107 	      for(j = lbeg[i + 1]; j > k; --j)
4108 	      {
4109 	         assert(*idx >= 0 && *idx < thedim);
4110 	         x += vec[*idx++] * (*val++);
4111 	      }
4112 	
4113 	      k = lrow[i];
4114 	
4115 	      y = vec[k];
4116 	
4117 	      if(y == 0)
4118 	      {
4119 	         y = -x;
4120 	
4121 	         if(y != 0)
4122 	         {
4123 	            nonz[n++] = k;
4124 	            vec[k] = y;
4125 	         }
4126 	      }
4127 	      else
4128 	      {
4129 	         y -= x;
4130 	         //vec[k] = ( y != 0 ) ? y : MARKER;
4131 	         vec[k] = y;
4132 	      }
4133 	   }
4134 	
4135 	   return n;
4136 	}
4137 	
4138 	inline void CLUFactorRational::solveLeft(Rational* vec, Rational* rhs)
4139 	{
4140 	
4141 	   if(!l.updateType)             /* no Forest-Tomlin Updates */
4142 	   {
4143 	      solveUpdateLeft(rhs);
4144 	      solveUleft(vec, rhs);
4145 	      solveLleft(vec);
4146 	   }
4147 	   else
4148 	   {
4149 	      solveUleft(vec, rhs);
4150 	      solveLleftForest(vec, 0);
4151 	      solveLleft(vec);
4152 	   }
4153 	}
4154 	
4155 	inline int CLUFactorRational::solveLeftEps(Rational* vec, Rational* rhs, int* nonz)
4156 	{
4157 	
4158 	   if(!l.updateType)             /* no Forest-Tomlin Updates */
4159 	   {
4160 	      solveUpdateLeft(rhs);
4161 	      solveUleft(vec, rhs);
4162 	      return solveLleftEps(vec, nonz);
4163 	   }
4164 	   else
4165 	   {
4166 	      solveUleft(vec, rhs);
4167 	      solveLleftForest(vec, nonz);
4168 	      return solveLleftEps(vec, nonz);
4169 	   }
4170 	}
4171 	
4172 	inline int CLUFactorRational::solveLeft2(
4173 	   Rational* vec1,
4174 	   int* nonz,
4175 	   Rational* vec2,
4176 	   Rational* rhs1,
4177 	   Rational* rhs2)
4178 	{
4179 	
4180 	   if(!l.updateType)             /* no Forest-Tomlin Updates */
4181 	   {
4182 	      solveUpdateLeft2(rhs1, rhs2);
4183 	      solveUleft2(vec1, rhs1, vec2, rhs2);
4184 	      solveLleft2(vec1, nonz, vec2);
4185 	      return 0;
4186 	   }
4187 	   else
4188 	   {
4189 	      solveUleft2(vec1, rhs1, vec2, rhs2);
4190 	      solveLleft2forest(vec1, nonz, vec2);
4191 	      solveLleft2(vec1, nonz, vec2);
4192 	      return 0;
4193 	   }
4194 	}
4195 	
4196 	inline int CLUFactorRational::solveUleft(Rational* vec, int* vecidx,
4197 	      Rational* rhs, int* rhsidx, int rhsn)
4198 	{
4199 	   Rational x, y;
4200 	   int i, j, k, n, r, c;
4201 	   int* rorig, *corig, *cperm;
4202 	   int* ridx, *rlen, *rbeg, *idx;
4203 	   Rational* val;
4204 	
4205 	   rorig = row.orig;
4206 	   corig = col.orig;
4207 	   cperm = col.perm;
4208 	
4209 	   /*  move rhsidx to a heap
4210 	    */
4211 	
4212 	   for(i = 0; i < rhsn;)
4213 	      enQueueMinRat(rhsidx, &i, cperm[rhsidx[i]]);
4214 	
4215 	   ridx = u.row.idx;
4216 	
4217 	   VectorRational& rval = u.row.val;
4218 	
4219 	   rlen = u.row.len;
4220 	
4221 	   rbeg = u.row.start;
4222 	
4223 	   n = 0;
4224 	
4225 	   while(rhsn > 0)
4226 	   {
4227 	      i = deQueueMinRat(rhsidx, &rhsn);
4228 	      assert(i >= 0 && i < thedim);
4229 	      c = corig[i];
4230 	      assert(c >= 0 && c < thedim);
4231 	      x = rhs[c];
4232 	      rhs[c] = 0;
4233 	
4234 	      if(x != 0)
4235 	      {
4236 	         r = rorig[i];
4237 	         assert(r >= 0 && r < thedim);
4238 	         vecidx[n++] = r;
4239 	         x *= diag[r];
4240 	         vec[r] = x;
4241 	         k = rbeg[r];
4242 	         assert(k >= 0 && k < u.row.val.dim());
4243 	         idx = &ridx[k];
4244 	         val = &rval[k];
4245 	
4246 	         for(int m = rlen[r]; m; --m)
4247 	         {
4248 	            j = *idx++;
4249 	            assert(j >= 0 && j < thedim);
4250 	            y = rhs[j];
4251 	
4252 	            if(y == 0)
4253 	            {
4254 	               y = -x * (*val++);
4255 	
4256 	               if(y != 0)
4257 	               {
4258 	                  rhs[j] = y;
4259 	                  enQueueMinRat(rhsidx, &rhsn, cperm[j]);
4260 	               }
4261 	            }
4262 	            else
4263 	            {
4264 	               y -= x * (*val++);
4265 	               //               rhs[j] = ( y != 0 ) ? y : MARKER;
4266 	               rhs[j] = y;
4267 	            }
4268 	         }
4269 	      }
4270 	   }
4271 	
4272 	   return n;
4273 	}
4274 	
4275 	
4276 	inline void CLUFactorRational::solveUleftNoNZ(Rational* vec, Rational* rhs, int* rhsidx, int rhsn)
4277 	{
4278 	   Rational x, y;
4279 	   int i, j, k, r, c;
4280 	   int* rorig, *corig, *cperm;
4281 	   int* ridx, *rlen, *rbeg, *idx;
4282 	   Rational* val;
4283 	
4284 	   rorig = row.orig;
4285 	   corig = col.orig;
4286 	   cperm = col.perm;
4287 	
4288 	   /*  move rhsidx to a heap
4289 	    */
4290 	
4291 	   for(i = 0; i < rhsn;)
4292 	      enQueueMinRat(rhsidx, &i, cperm[rhsidx[i]]);
4293 	
4294 	   ridx = u.row.idx;
4295 	
4296 	   VectorRational& rval = u.row.val;
4297 	
4298 	   rlen = u.row.len;
4299 	
4300 	   rbeg = u.row.start;
4301 	
4302 	   while(rhsn > 0)
4303 	   {
4304 	      i = deQueueMinRat(rhsidx, &rhsn);
4305 	      assert(i >= 0 && i < thedim);
4306 	      c = corig[i];
4307 	      assert(c >= 0 && c < thedim);
4308 	      x = rhs[c];
4309 	      rhs[c] = 0;
4310 	
4311 	      if(x != 0)
4312 	      {
4313 	         r = rorig[i];
4314 	         assert(r >= 0 && r < thedim);
4315 	         x *= diag[r];
4316 	         vec[r] = x;
4317 	         k = rbeg[r];
4318 	         assert(k >= 0 && k < u.row.val.dim());
4319 	         idx = &ridx[k];
4320 	         val = &rval[k];
4321 	
4322 	         for(int m = rlen[r]; m; --m)
4323 	         {
4324 	            j = *idx++;
4325 	            assert(j >= 0 && j < thedim);
4326 	            y = rhs[j];
4327 	
4328 	            if(y == 0)
4329 	            {
4330 	               y = -x * (*val++);
4331 	
4332 	               if(y != 0)
4333 	               {
4334 	                  rhs[j] = y;
4335 	                  enQueueMinRat(rhsidx, &rhsn, cperm[j]);
4336 	               }
4337 	            }
4338 	            else
4339 	            {
4340 	               y -= x * (*val++);
4341 	               //               rhs[j] = ( y != 0 ) ? y : MARKER;
4342 	               rhs[j] = y;
4343 	            }
4344 	         }
4345 	      }
4346 	   }
4347 	}
4348 	
4349 	
4350 	inline int CLUFactorRational::solveLleftForest(Rational* vec, int* nonz, int n)
4351 	{
4352 	   int i, j, k, end;
4353 	   Rational x, y;
4354 	   Rational* val;
4355 	   int* idx, *lidx, *lrow, *lbeg;
4356 	
4357 	   VectorRational& lval = l.val;
4358 	   lidx = l.idx;
4359 	   lrow = l.row;
4360 	   lbeg = l.start;
4361 	   end = l.firstUpdate;
4362 	
4363 	   for(i = l.firstUnused - 1; i >= end; --i)
4364 	   {
4365 	      assert(i >= 0 && i < l.val.dim());
4366 	
4367 	      if((x = vec[lrow[i]]) != 0)
4368 	      {
4369 	         k = lbeg[i];
4370 	         assert(k >= 0 && k < l.val.dim());
4371 	         val = &lval[k];
4372 	         idx = &lidx[k];
4373 	
4374 	         for(j = lbeg[i + 1]; j > k; --j)
4375 	         {
4376 	            int m = *idx++;
4377 	            assert(m >= 0 && m < thedim);
4378 	            y = vec[m];
4379 	
4380 	            if(y == 0)
4381 	            {
4382 	               y = -x * (*val++);
4383 	
4384 	               if(y != 0)
4385 	               {
4386 	                  vec[m] = y;
4387 	                  nonz[n++] = m;
4388 	               }
4389 	            }
4390 	            else
4391 	            {
4392 	               y -= x * (*val++);
4393 	
4394 	            }
4395 	         }
4396 	      }
4397 	   }
4398 	
4399 	   return n;
4400 	}
4401 	
4402 	
4403 	inline void CLUFactorRational::solveLleftForestNoNZ(Rational* vec)
4404 	{
4405 	   int i, j, k, end;
4406 	   Rational x;
4407 	   Rational* val;
4408 	   int* idx, *lidx, *lrow, *lbeg;
4409 	
4410 	   VectorRational& lval = l.val;
4411 	   lidx = l.idx;
4412 	   lrow = l.row;
4413 	   lbeg = l.start;
4414 	   end = l.firstUpdate;
4415 	
4416 	   for(i = l.firstUnused - 1; i >= end; --i)
4417 	   {
4418 	      if((x = vec[lrow[i]]) != 0)
4419 	      {
4420 	         assert(i >= 0 && i < l.val.dim());
4421 	         k = lbeg[i];
4422 	         assert(k >= 0 && k < l.val.dim());
4423 	         val = &lval[k];
4424 	         idx = &lidx[k];
4425 	
4426 	         for(j = lbeg[i + 1]; j > k; --j)
4427 	         {
4428 	            assert(*idx >= 0 && *idx < thedim);
4429 	            vec[*idx++] -= x * (*val++);
4430 	         }
4431 	      }
4432 	   }
4433 	}
4434 	
4435 	
4436 	inline int CLUFactorRational::solveLleft(Rational* vec, int* nonz, int rn)
4437 	{
4438 	   int i, j, k, n;
4439 	   int r;
4440 	   Rational x, y;
4441 	   Rational* val;
4442 	   int* ridx, *idx;
4443 	   int* rbeg;
4444 	   int* rorig, *rperm;
4445 	   int* last;
4446 	
4447 	   ridx  = l.ridx;
4448 	   VectorRational& rval  = l.rval;
4449 	   rbeg  = l.rbeg;
4450 	   rorig = l.rorig;
4451 	   rperm = l.rperm;
4452 	   n     = 0;
4453 	
4454 	   i = l.firstUpdate - 1;
4455 	#ifndef WITH_L_ROWS
4456 	#pragma warn "Not yet implemented, define WITH_L_ROWS"
4457 	   VectorRational& lval = l.val;
4458 	   int*    lidx = l.idx;
4459 	   int*    lrow = l.row;
4460 	   int*    lbeg = l.start;
4461 	
4462 	   for(; i >= 0; --i)
4463 	   {
4464 	      k   = lbeg[i];
4465 	      val = &lval[k];
4466 	      idx = &lidx[k];
4467 	      x   = 0;
4468 	
4469 	      for(j = lbeg[i + 1]; j > k; --j)
4470 	         x += vec[*idx++] * (*val++);
4471 	
4472 	      vec[lrow[i]] -= x;
4473 	   }
4474 	
4475 	#else
4476 	
4477 	   /*  move rhsidx to a heap
4478 	    */
4479 	   for(i = 0; i < rn;)
4480 	      enQueueMaxRat(nonz, &i, rperm[nonz[i]]);
4481 	
4482 	   last = nonz + thedim;
4483 	
4484 	   while(rn > 0)
4485 	   {
4486 	      i = deQueueMaxRat(nonz, &rn);
4487 	      r = rorig[i];
4488 	      x = vec[r];
4489 	
4490 	      if(x != 0)
4491 	      {
4492 	         *(--last) = r;
4493 	         n++;
4494 	         k = rbeg[r];
4495 	         j = rbeg[r + 1] - k;
4496 	         val = &rval[k];
4497 	         idx = &ridx[k];
4498 	
4499 	         while(j-- > 0)
4500 	         {
4501 	            assert(l.rperm[*idx] < i);
4502 	            int m = *idx++;
4503 	            y = vec[m];
4504 	
4505 	            if(y == 0)
4506 	            {
4507 	               y = -x * *val++;
4508 	
4509 	               if(y != 0)
4510 	               {
4511 	                  vec[m] = y;
4512 	                  enQueueMaxRat(nonz, &rn, rperm[m]);
4513 	               }
4514 	            }
4515 	            else
4516 	            {
4517 	               y -= x * *val++;
4518 	               //               vec[m] = ( y != 0 ) ? y : MARKER;
4519 	               vec[m] = y;
4520 	            }
4521 	         }
4522 	      }
4523 	      else
4524 	         vec[r] = 0;
4525 	   }
4526 	
4527 	   for(i = 0; i < n; ++i)
4528 	      *nonz++ = *last++;
4529 	
4530 	#endif
4531 	
4532 	   return n;
4533 	}
4534 	
4535 	
4536 	inline void CLUFactorRational::solveLleftNoNZ(Rational* vec)
4537 	{
4538 	   int i, j, k;
4539 	   int r;
4540 	   Rational x;
4541 	   Rational* val;
4542 	   int* ridx, *idx;
4543 	   int* rbeg;
4544 	   int* rorig;
4545 	
4546 	   ridx = l.ridx;
4547 	   VectorRational& rval = l.rval;
4548 	   rbeg = l.rbeg;
4549 	   rorig = l.rorig;
4550 	
4551 	#ifndef WITH_L_ROWS
4552 	   VectorRational& lval = l.val;
4553 	   int*    lidx = l.idx;
4554 	   int*    lrow = l.row;
4555 	   int*    lbeg = l.start;
4556 	
4557 	   i = l.firstUpdate - 1;
4558 	   assert(i < thedim);
4559 	
4560 	   for(; i >= 0; --i)
4561 	   {
4562 	      k = lbeg[i];
4563 	      assert(k >= 0 && k < l.val.dim());
4564 	      val = &lval[k];
4565 	      idx = &lidx[k];
4566 	      x = 0;
4567 	
4568 	      for(j = lbeg[i + 1]; j > k; --j)
4569 	      {
4570 	         assert(*idx >= 0 && *idx < thedim);
4571 	         x += vec[*idx++] * (*val++);
4572 	      }
4573 	
4574 	      vec[lrow[i]] -= x;
4575 	   }
4576 	
4577 	#else
4578 	
4579 	   for(i = thedim; i--;)
4580 	   {
4581 	      r = rorig[i];
4582 	      x = vec[r];
4583 	
4584 	      if(x != 0)
4585 	      {
4586 	         k = rbeg[r];
4587 	         j = rbeg[r + 1] - k;
4588 	         val = &rval[k];
4589 	         idx = &ridx[k];
4590 	
4591 	         while(j-- > 0)
4592 	         {
4593 	            assert(l.rperm[*idx] < i);
4594 	            vec[*idx++] -= x * *val++;
4595 	         }
4596 	      }
4597 	   }
4598 	
4599 	#endif
4600 	}
4601 	
4602 	inline int CLUFactorRational::vSolveLright(Rational* vec, int* ridx, int rn)
4603 	{
4604 	   int i, j, k, n;
4605 	   int end;
4606 	   Rational x;
4607 	   Rational* val;
4608 	   int* lrow, *lidx, *idx;
4609 	   int* lbeg;
4610 	
4611 	   VectorRational& lval = l.val;
4612 	   lidx = l.idx;
4613 	   lrow = l.row;
4614 	   lbeg = l.start;
4615 	
4616 	   end = l.firstUpdate;
4617 	
4618 	   for(i = 0; i < end; ++i)
4619 	   {
4620 	      x = vec[lrow[i]];
4621 	
4622 	      if(x != 0)
4623 	      {
4624 	         k = lbeg[i];
4625 	         idx = &(lidx[k]);
4626 	         val = &(lval[k]);
4627 	
4628 	         for(j = lbeg[i + 1]; j > k; --j)
4629 	         {
4630 	            assert(*idx >= 0 && *idx < thedim);
4631 	            ridx[rn] = n = *idx++;
4632 	            rn += (vec[n] == 0) ? 1 : 0;
4633 	            vec[n] -= x * (*val++);
4634 	            //            vec[n] += ( vec[n] == 0 ) ? MARKER : 0;
4635 	         }
4636 	      }
4637 	   }
4638 	
4639 	   if(l.updateType)                      /* Forest-Tomlin Updates */
4640 	   {
4641 	      end = l.firstUnused;
4642 	
4643 	      for(; i < end; ++i)
4644 	      {
4645 	         x = 0;
4646 	         k = lbeg[i];
4647 	         idx = &(lidx[k]);
4648 	         val = &(lval[k]);
4649 	
4650 	         for(j = lbeg[i + 1]; j > k; --j)
4651 	         {
4652 	            assert(*idx >= 0 && *idx < thedim);
4653 	            x += vec[*idx++] * (*val++);
4654 	         }
4655 	
4656 	         ridx[rn] = j = lrow[i];
4657 	
4658 	         rn += (vec[j] == 0) ? 1 : 0;
4659 	         vec[j] -= x;
4660 	         //         vec[j] += ( vec[j] == 0 ) ? MARKER : 0;
4661 	      }
4662 	   }
4663 	
4664 	   return rn;
4665 	}
4666 	
4667 	inline void CLUFactorRational::vSolveLright2(Rational* vec, int* ridx, int* rnptr,
4668 	      Rational* vec2, int* ridx2, int* rn2ptr)
4669 	{
4670 	   int i, j, k, n;
4671 	   int end;
4672 	   Rational x, y;
4673 	   Rational x2, y2;
4674 	   Rational* val;
4675 	   int* lrow, *lidx, *idx;
4676 	   int* lbeg;
4677 	
4678 	   int rn = *rnptr;
4679 	   int rn2 = *rn2ptr;
4680 	
4681 	   VectorRational& lval = l.val;
4682 	   lidx = l.idx;
4683 	   lrow = l.row;
4684 	   lbeg = l.start;
4685 	
4686 	   end = l.firstUpdate;
4687 	
4688 	   for(i = 0; i < end; ++i)
4689 	   {
4690 	      j = lrow[i];
4691 	      x2 = vec2[j];
4692 	      x = vec[j];
4693 	
4694 	      if(x != 0)
4695 	      {
4696 	         k = lbeg[i];
4697 	         idx = &(lidx[k]);
4698 	         val = &(lval[k]);
4699 	
4700 	         if(x2 != 0)
4701 	         {
4702 	            for(j = lbeg[i + 1]; j > k; --j)
4703 	            {
4704 	               assert(*idx >= 0 && *idx < thedim);
4705 	               ridx[rn] = ridx2[rn2] = n = *idx++;
4706 	               y = vec[n];
4707 	               y2 = vec2[n];
4708 	               rn += (y == 0) ? 1 : 0;
4709 	               rn2 += (y2 == 0) ? 1 : 0;
4710 	               y -= x * (*val);
4711 	               y2 -= x2 * (*val++);
4712 	               //               vec[n] = y + ( y == 0 ? MARKER : 0 );
4713 	               //               vec2[n] = y2 + ( y2 == 0 ? MARKER : 0 );
4714 	               vec[n] = y;
4715 	               vec2[n] = y2;
4716 	            }
4717 	         }
4718 	         else
4719 	         {
4720 	            for(j = lbeg[i + 1]; j > k; --j)
4721 	            {
4722 	               assert(*idx >= 0 && *idx < thedim);
4723 	               ridx[rn] = n = *idx++;
4724 	               y = vec[n];
4725 	               rn += (y == 0) ? 1 : 0;
4726 	               y -= x * (*val++);
4727 	               //               vec[n] = y + ( y == 0 ? MARKER : 0 );
4728 	               vec[n] = y;
4729 	            }
4730 	         }
4731 	      }
4732 	      else if(x2 != 0)
4733 	      {
4734 	         k = lbeg[i];
4735 	         idx = &(lidx[k]);
4736 	         val = &(lval[k]);
4737 	
4738 	         for(j = lbeg[i + 1]; j > k; --j)
4739 	         {
4740 	            assert(*idx >= 0 && *idx < thedim);
4741 	            ridx2[rn2] = n = *idx++;
4742 	            y2 = vec2[n];
4743 	            rn2 += (y2 == 0) ? 1 : 0;
4744 	            y2 -= x2 * (*val++);
4745 	            //               vec2[n] = y2 + ( y2 == 0 ? MARKER : 0 );
4746 	            vec2[n] = y2;
4747 	         }
4748 	      }
4749 	   }
4750 	
4751 	   if(l.updateType)                      /* Forest-Tomlin Updates */
4752 	   {
4753 	      end = l.firstUnused;
4754 	
4755 	      for(; i < end; ++i)
4756 	      {
4757 	         x = x2 = 0;
4758 	         k = lbeg[i];
4759 	         idx = &(lidx[k]);
4760 	         val = &(lval[k]);
4761 	
4762 	         for(j = lbeg[i + 1]; j > k; --j)
4763 	         {
4764 	            assert(*idx >= 0 && *idx < thedim);
4765 	            x += vec[*idx] * (*val);
4766 	            x2 += vec2[*idx++] * (*val++);
4767 	         }
4768 	
4769 	         ridx[rn] = ridx2[rn2] = j = lrow[i];
4770 	
4771 	         rn += (vec[j] == 0) ? 1 : 0;
4772 	         rn2 += (vec2[j] == 0) ? 1 : 0;
4773 	         vec[j] -= x;
4774 	         vec2[j] -= x2;
4775 	         //         vec[j] += ( vec[j] == 0 ) ? MARKER : 0;
4776 	         //         vec2[j] += ( vec2[j] == 0 ) ? MARKER : 0;
4777 	      }
4778 	   }
4779 	
4780 	   *rnptr = rn;
4781 	
4782 	   *rn2ptr = rn2;
4783 	}
4784 	
4785 	inline void CLUFactorRational::vSolveLright3(Rational* vec, int* ridx, int* rnptr,
4786 	      Rational* vec2, int* ridx2, int* rn2ptr,
4787 	      Rational* vec3, int* ridx3, int* rn3ptr)
4788 	{
4789 	   int i, j, k, n;
4790 	   int end;
4791 	   Rational x, y;
4792 	   Rational x2, y2;
4793 	   Rational x3, y3;
4794 	   Rational* val;
4795 	   int* lrow, *lidx, *idx;
4796 	   int* lbeg;
4797 	
4798 	   int rn = *rnptr;
4799 	   int rn2 = *rn2ptr;
4800 	   int rn3 = *rn3ptr;
4801 	
4802 	   VectorRational& lval = l.val;
4803 	   lidx = l.idx;
4804 	   lrow = l.row;
4805 	   lbeg = l.start;
4806 	
4807 	   end = l.firstUpdate;
4808 	
4809 	   for(i = 0; i < end; ++i)
4810 	   {
4811 	      j = lrow[i];
4812 	      x3 = vec3[j];
4813 	      x2 = vec2[j];
4814 	      x = vec[j];
4815 	
4816 	      if(x != 0)
4817 	      {
4818 	         k = lbeg[i];
4819 	         idx = &(lidx[k]);
4820 	         val = &(lval[k]);
4821 	
4822 	         if(x2 != 0)
4823 	         {
4824 	            if(x3 != 0)
4825 	            {
4826 	               // case 1: all three vectors are nonzero at j
4827 	               for(j = lbeg[i + 1]; j > k; --j)
4828 	               {
4829 	                  assert(*idx >= 0 && *idx < thedim);
4830 	                  ridx[rn] = ridx2[rn2] = ridx3[rn3] = n = *idx++;
4831 	                  y = vec[n];
4832 	                  y2 = vec2[n];
4833 	                  y3 = vec3[n];
4834 	                  rn += (y == 0) ? 1 : 0;
4835 	                  rn2 += (y2 == 0) ? 1 : 0;
4836 	                  rn3 += (y3 == 0) ? 1 : 0;
4837 	                  y -= x * (*val);
4838 	                  y2 -= x2 * (*val);
4839 	                  y3 -= x3 * (*val++);
4840 	                  //                  vec[n] = y + ( y == 0 ? MARKER : 0 );
4841 	                  //                  vec2[n] = y2 + ( y2 == 0 ? MARKER : 0 );
4842 	                  //                  vec3[n] = y3 + ( y3 == 0 ? MARKER : 0 );
4843 	                  vec[n] = y;
4844 	                  vec2[n] = y2;
4845 	                  vec3[n] = y3;
4846 	               }
4847 	            }
4848 	            else
4849 	            {
4850 	               // case 2: 1 and 2 are nonzero at j
4851 	               for(j = lbeg[i + 1]; j > k; --j)
4852 	               {
4853 	                  assert(*idx >= 0 && *idx < thedim);
4854 	                  ridx[rn] = ridx2[rn2] = n = *idx++;
4855 	                  y = vec[n];
4856 	                  y2 = vec2[n];
4857 	                  rn += (y == 0) ? 1 : 0;
4858 	                  rn2 += (y2 == 0) ? 1 : 0;
4859 	                  y -= x * (*val);
4860 	                  y2 -= x2 * (*val++);
4861 	                  //                  vec[n] = y + ( y == 0 ? MARKER : 0 );
4862 	                  //vec2[n] = y2 + ( y2 == 0 ? MARKER : 0 );
4863 	                  vec[n] = y;
4864 	                  vec2[n] = y2;
4865 	               }
4866 	            }
4867 	         }
4868 	         else if(x3 != 0)
4869 	         {
4870 	            // case 3: 1 and 3 are nonzero at j
4871 	            for(j = lbeg[i + 1]; j > k; --j)
4872 	            {
4873 	               assert(*idx >= 0 && *idx < thedim);
4874 	               ridx[rn] = ridx3[rn3] = n = *idx++;
4875 	               y = vec[n];
4876 	               y3 = vec3[n];
4877 	               rn += (y == 0) ? 1 : 0;
4878 	               rn3 += (y3 == 0) ? 1 : 0;
4879 	               y -= x * (*val);
4880 	               y3 -= x3 * (*val++);
4881 	               //                  vec[n] = y + ( y == 0 ? MARKER : 0 );
4882 	               //                  vec3[n] = y3 + ( y3 == 0 ? MARKER : 0 );
4883 	               vec[n] = y;
4884 	               vec3[n] = y3;
4885 	            }
4886 	         }
4887 	         else
4888 	         {
4889 	            // case 4: only 1 is nonzero at j
4890 	            for(j = lbeg[i + 1]; j > k; --j)
4891 	            {
4892 	               assert(*idx >= 0 && *idx < thedim);
4893 	               ridx[rn] = n = *idx++;
4894 	               y = vec[n];
4895 	               rn += (y == 0) ? 1 : 0;
4896 	               y -= x * (*val++);
4897 	               //                  vec[n] = y + ( y == 0 ? MARKER : 0 );
4898 	               vec[n] = y;
4899 	            }
4900 	         }
4901 	      }
4902 	      else if(x2 != 0)
4903 	      {
4904 	         k = lbeg[i];
4905 	         idx = &(lidx[k]);
4906 	         val = &(lval[k]);
4907 	
4908 	         if(x3 != 0)
4909 	         {
4910 	            // case 5: 2 and 3 are nonzero at j
4911 	            for(j = lbeg[i + 1]; j > k; --j)
4912 	            {
4913 	               assert(*idx >= 0 && *idx < thedim);
4914 	               ridx2[rn2] = ridx3[rn3] = n = *idx++;
4915 	               y2 = vec2[n];
4916 	               y3 = vec3[n];
4917 	               rn2 += (y2 == 0) ? 1 : 0;
4918 	               rn3 += (y3 == 0) ? 1 : 0;
4919 	               y2 -= x2 * (*val);
4920 	               y3 -= x3 * (*val++);
4921 	               //                  vec2[n] = y2 + ( y2 == 0 ? MARKER : 0 );
4922 	               //                  vec3[n] = y3 + ( y3 == 0 ? MARKER : 0 );
4923 	               vec2[n] = y2;
4924 	               vec3[n] = y3;
4925 	            }
4926 	         }
4927 	         else
4928 	         {
4929 	            // case 6: only 2 is nonzero at j
4930 	            for(j = lbeg[i + 1]; j > k; --j)
4931 	            {
4932 	               assert(*idx >= 0 && *idx < thedim);
4933 	               ridx2[rn2] = n = *idx++;
4934 	               y2 = vec2[n];
4935 	               rn2 += (y2 == 0) ? 1 : 0;
4936 	               y2 -= x2 * (*val++);
4937 	               //                  vec2[n] = y2 + ( y2 == 0 ? MARKER : 0 );
4938 	               vec2[n] = y2;
4939 	            }
4940 	         }
4941 	      }
4942 	      else if(x3 != 0)
4943 	      {
4944 	         // case 7: only 3 is nonzero at j
4945 	         k = lbeg[i];
4946 	         idx = &(lidx[k]);
4947 	         val = &(lval[k]);
4948 	
4949 	         for(j = lbeg[i + 1]; j > k; --j)
4950 	         {
4951 	            assert(*idx >= 0 && *idx < thedim);
4952 	            ridx3[rn3] = n = *idx++;
4953 	            y3 = vec3[n];
4954 	            rn3 += (y3 == 0) ? 1 : 0;
4955 	            y3 -= x3 * (*val++);
4956 	            //                  vec3[n] = y3 + ( y3 == 0 ? MARKER : 0 );
4957 	            vec3[n] = y3;
4958 	         }
4959 	      }
4960 	   }
4961 	
4962 	   if(l.updateType)                      /* Forest-Tomlin Updates */
4963 	   {
4964 	      end = l.firstUnused;
4965 	
4966 	      for(; i < end; ++i)
4967 	      {
4968 	         x = x2 = x3 = 0;
4969 	         k = lbeg[i];
4970 	         idx = &(lidx[k]);
4971 	         val = &(lval[k]);
4972 	
4973 	         for(j = lbeg[i + 1]; j > k; --j)
4974 	         {
4975 	            assert(*idx >= 0 && *idx < thedim);
4976 	            x += vec[*idx] * (*val);
4977 	            x2 += vec2[*idx] * (*val);
4978 	            x3 += vec3[*idx++] * (*val++);
4979 	         }
4980 	
4981 	         ridx[rn] = ridx2[rn2] = ridx3[rn3] = j = lrow[i];
4982 	
4983 	         rn += (vec[j] == 0) ? 1 : 0;
4984 	         rn2 += (vec2[j] == 0) ? 1 : 0;
4985 	         rn3 += (vec3[j] == 0) ? 1 : 0;
4986 	         vec[j] -= x;
4987 	         vec2[j] -= x2;
4988 	         vec3[j] -= x3;
4989 	         //         vec[j] += ( vec[j] == 0 ) ? MARKER : 0;
4990 	         //         vec2[j] += ( vec2[j] == 0 ) ? MARKER : 0;
4991 	         //         vec3[j] += ( vec3[j] == 0 ) ? MARKER : 0;
4992 	      }
4993 	   }
4994 	
4995 	   *rnptr = rn;
4996 	
4997 	   *rn2ptr = rn2;
4998 	   *rn3ptr = rn3;
4999 	}
5000 	
5001 	inline int CLUFactorRational::vSolveUright(Rational* vec, int* vidx,
5002 	      Rational* rhs, int* ridx, int rn)
5003 	{
5004 	   int i, j, k, r, c, n;
5005 	   int* rorig, *corig;
5006 	   int* rperm;
5007 	   int* cidx, *clen, *cbeg;
5008 	   Rational x, y;
5009 	
5010 	   int* idx;
5011 	   Rational* val;
5012 	
5013 	   rorig = row.orig;
5014 	   corig = col.orig;
5015 	   rperm = row.perm;
5016 	
5017 	   cidx = u.col.idx;
5018 	   VectorRational& cval = u.col.val;
5019 	   clen = u.col.len;
5020 	   cbeg = u.col.start;
5021 	
5022 	   n = 0;
5023 	
5024 	   while(rn > 0)
5025 	   {
5026 	      /*      Find nonzero with highest permuted row index and setup i and r
5027 	       */
5028 	      i = deQueueMaxRat(ridx, &rn);
5029 	      assert(i >= 0 && i < thedim);
5030 	      r = rorig[i];
5031 	      assert(r >= 0 && r < thedim);
5032 	
5033 	      x = diag[r] * rhs[r];
5034 	      rhs[r] = 0;
5035 	
5036 	      if(x != 0)
5037 	      {
5038 	         c = corig[i];
5039 	         assert(c >= 0 && c < thedim);
5040 	         vidx[n++] = c;
5041 	         vec[c] = x;
5042 	         val = &cval[cbeg[c]];
5043 	         idx = &cidx[cbeg[c]];
5044 	         j = clen[c];
5045 	
5046 	         while(j-- > 0)
5047 	         {
5048 	            assert(*idx >= 0 && *idx < thedim);
5049 	            k = *idx++;
5050 	            assert(k >= 0 && k < thedim);
5051 	            y = rhs[k];
5052 	
5053 	            if(y == 0)
5054 	            {
5055 	               y = -x * (*val++);
5056 	
5057 	               if(y != 0)
5058 	               {
5059 	                  rhs[k] = y;
5060 	                  enQueueMaxRat(ridx, &rn, rperm[k]);
5061 	               }
5062 	            }
5063 	            else
5064 	            {
5065 	               y -= x * (*val++);
5066 	               //               y += ( y == 0 ) ? MARKER : 0;
5067 	               rhs[k] = y;
5068 	            }
5069 	         }
5070 	
5071 	         if(rn > i * verySparseFactor4rightRat)
5072 	         {
5073 	            /* continue with dense case */
5074 	            for(i = *ridx; i >= 0; --i)
5075 	            {
5076 	               r = rorig[i];
5077 	               assert(r >= 0 && r < thedim);
5078 	               x = diag[r] * rhs[r];
5079 	               rhs[r] = 0;
5080 	
5081 	               if(x != 0)
5082 	               {
5083 	                  c = corig[i];
5084 	                  assert(c >= 0 && c < thedim);
5085 	                  vidx[n++] = c;
5086 	                  vec[c] = x;
5087 	                  val = &cval[cbeg[c]];
5088 	                  idx = &cidx[cbeg[c]];
5089 	                  j = clen[c];
5090 	
5091 	                  while(j-- > 0)
5092 	                  {
5093 	                     assert(*idx >= 0 && *idx < thedim);
5094 	                     rhs[*idx++] -= x * (*val++);
5095 	                  }
5096 	               }
5097 	            }
5098 	
5099 	            break;
5100 	         }
5101 	      }
5102 	   }
5103 	
5104 	   return n;
5105 	}
5106 	
5107 	
5108 	inline void CLUFactorRational::vSolveUrightNoNZ(Rational* vec, Rational* rhs, int* ridx, int rn)
5109 	{
5110 	   int i, j, k, r, c;
5111 	   int* rorig, *corig;
5112 	   int* rperm;
5113 	   int* cidx, *clen, *cbeg;
5114 	   Rational x, y;
5115 	
5116 	   int* idx;
5117 	   Rational* val;
5118 	
5119 	   rorig = row.orig;
5120 	   corig = col.orig;
5121 	   rperm = row.perm;
5122 	
5123 	   cidx = u.col.idx;
5124 	   VectorRational& cval = u.col.val;
5125 	   clen = u.col.len;
5126 	   cbeg = u.col.start;
5127 	
5128 	   while(rn > 0)
5129 	   {
5130 	      if(rn > *ridx * verySparseFactor4rightRat)
5131 	      {
5132 	         /* continue with dense case */
5133 	         for(i = *ridx; i >= 0; --i)
5134 	         {
5135 	            assert(i >= 0 && i < thedim);
5136 	            r = rorig[i];
5137 	            assert(r >= 0 && r < thedim);
5138 	            x = diag[r] * rhs[r];
5139 	            rhs[r] = 0;
5140 	
5141 	            if(x != 0)
5142 	            {
5143 	               c = corig[i];
5144 	               vec[c] = x;
5145 	               val = &cval[cbeg[c]];
5146 	               idx = &cidx[cbeg[c]];
5147 	               j = clen[c];
5148 	
5149 	               while(j-- > 0)
5150 	               {
5151 	                  assert(*idx >= 0 && *idx < thedim);
5152 	                  rhs[*idx++] -= x * (*val++);
5153 	               }
5154 	            }
5155 	         }
5156 	
5157 	         break;
5158 	      }
5159 	
5160 	      /*      Find nonzero with highest permuted row index and setup i and r
5161 	       */
5162 	      i = deQueueMaxRat(ridx, &rn);
5163 	
5164 	      assert(i >= 0 && i < thedim);
5165 	
5166 	      r = rorig[i];
5167 	
5168 	      assert(r >= 0 && r < thedim);
5169 	
5170 	      x = diag[r] * rhs[r];
5171 	
5172 	      rhs[r] = 0;
5173 	
5174 	      if(x != 0)
5175 	      {
5176 	         c = corig[i];
5177 	         vec[c] = x;
5178 	         val = &cval[cbeg[c]];
5179 	         idx = &cidx[cbeg[c]];
5180 	         j = clen[c];
5181 	
5182 	         while(j-- > 0)
5183 	         {
5184 	            k = *idx++;
5185 	            assert(k >= 0 && k < thedim);
5186 	            y = rhs[k];
5187 	
5188 	            if(y == 0)
5189 	            {
5190 	               y = -x * (*val++);
5191 	
5192 	               if(y != 0)
5193 	               {
5194 	                  rhs[k] = y;
5195 	                  enQueueMaxRat(ridx, &rn, rperm[k]);
5196 	               }
5197 	            }
5198 	            else
5199 	            {
5200 	               y -= x * (*val++);
5201 	               //               y += ( y == 0 ) ? MARKER : 0;
5202 	               rhs[k] = y;
5203 	            }
5204 	         }
5205 	      }
5206 	   }
5207 	}
5208 	
5209 	
5210 	inline int CLUFactorRational::vSolveUright2(Rational* vec, int* vidx, Rational* rhs, int* ridx,
5211 	      int rn,
5212 	      Rational* vec2, Rational* rhs2, int* ridx2, int rn2)
5213 	{
5214 	   int i, j, k, r, c, n;
5215 	   int* rorig, *corig;
5216 	   int* rperm;
5217 	   int* cidx, *clen, *cbeg;
5218 	   Rational x, y;
5219 	   Rational x2, y2;
5220 	
5221 	   int* idx;
5222 	   Rational* val;
5223 	
5224 	   rorig = row.orig;
5225 	   corig = col.orig;
5226 	   rperm = row.perm;
5227 	
5228 	   cidx = u.col.idx;
5229 	   VectorRational& cval = u.col.val;
5230 	   clen = u.col.len;
5231 	   cbeg = u.col.start;
5232 	
5233 	   n = 0;
5234 	
5235 	   while(rn + rn2 > 0)
5236 	   {
5237 	      /*      Find nonzero with highest permuted row index and setup i and r
5238 	       */
5239 	      if(rn <= 0)
5240 	         i = deQueueMaxRat(ridx2, &rn2);
5241 	      else if(rn2 <= 0)
5242 	         i = deQueueMaxRat(ridx, &rn);
5243 	      else if(*ridx2 > *ridx)
5244 	         i = deQueueMaxRat(ridx2, &rn2);
5245 	      else if(*ridx2 < *ridx)
5246 	         i = deQueueMaxRat(ridx, &rn);
5247 	      else
5248 	      {
5249 	         (void) deQueueMaxRat(ridx, &rn);
5250 	         i = deQueueMaxRat(ridx2, &rn2);
5251 	      }
5252 	
5253 	      assert(i >= 0 && i < thedim);
5254 	
5255 	      r = rorig[i];
5256 	      assert(r >= 0 && r < thedim);
5257 	
5258 	      x = diag[r] * rhs[r];
5259 	      x2 = diag[r] * rhs2[r];
5260 	      rhs[r] = 0;
5261 	      rhs2[r] = 0;
5262 	
5263 	      if(x != 0)
5264 	      {
5265 	         c = corig[i];
5266 	         vidx[n++] = c;
5267 	         vec[c] = x;
5268 	         vec2[c] = x2;
5269 	         val = &cval[cbeg[c]];
5270 	         idx = &cidx[cbeg[c]];
5271 	         j = clen[c];
5272 	
5273 	         if(x2 != 0)
5274 	         {
5275 	            while(j-- > 0)
5276 	            {
5277 	               k = *idx++;
5278 	               assert(k >= 0 && k < thedim);
5279 	               y2 = rhs2[k];
5280 	
5281 	               if(y2 == 0)
5282 	               {
5283 	                  y2 = -x2 * (*val);
5284 	
5285 	                  if(y2 != 0)
5286 	                  {
5287 	                     rhs2[k] = y2;
5288 	                     enQueueMaxRat(ridx2, &rn2, rperm[k]);
5289 	                  }
5290 	               }
5291 	               else
5292 	               {
5293 	                  y2 -= x2 * (*val);
5294 	                  //                  rhs2[k] = ( y2 != 0 ) ? y2 : MARKER;
5295 	                  rhs2[k] = y2;
5296 	               }
5297 	
5298 	               y = rhs[k];
5299 	
5300 	               if(y == 0)
5301 	               {
5302 	                  y = -x * (*val++);
5303 	
5304 	                  if(y != 0)
5305 	                  {
5306 	                     rhs[k] = y;
5307 	                     enQueueMaxRat(ridx, &rn, rperm[k]);
5308 	                  }
5309 	               }
5310 	               else
5311 	               {
5312 	                  y -= x * (*val++);
5313 	                  //                  y += ( y == 0 ) ? MARKER : 0;
5314 	                  rhs[k] = y;
5315 	               }
5316 	            }
5317 	         }
5318 	         else
5319 	         {
5320 	            while(j-- > 0)
5321 	            {
5322 	               k = *idx++;
5323 	               assert(k >= 0 && k < thedim);
5324 	               y = rhs[k];
5325 	
5326 	               if(y == 0)
5327 	               {
5328 	                  y = -x * (*val++);
5329 	
5330 	                  if(y != 0)
5331 	                  {
5332 	                     rhs[k] = y;
5333 	                     enQueueMaxRat(ridx, &rn, rperm[k]);
5334 	                  }
5335 	               }
5336 	               else
5337 	               {
5338 	                  y -= x * (*val++);
5339 	                  //                  y += ( y == 0 ) ? MARKER : 0;
5340 	                  rhs[k] = y;
5341 	               }
5342 	            }
5343 	         }
5344 	      }
5345 	      else if(x2 != 0)
5346 	      {
5347 	         c = corig[i];
5348 	         assert(c >= 0 && c < thedim);
5349 	         vec2[c] = x2;
5350 	         val = &cval[cbeg[c]];
5351 	         idx = &cidx[cbeg[c]];
5352 	         j = clen[c];
5353 	
5354 	         while(j-- > 0)
5355 	         {
5356 	            k = *idx++;
5357 	            assert(k >= 0 && k < thedim);
5358 	            y2 = rhs2[k];
5359 	
5360 	            if(y2 == 0)
5361 	            {
5362 	               y2 = -x2 * (*val++);
5363 	
5364 	               if(y2 != 0)
5365 	               {
5366 	                  rhs2[k] = y2;
5367 	                  enQueueMaxRat(ridx2, &rn2, rperm[k]);
5368 	               }
5369 	            }
5370 	            else
5371 	            {
5372 	               y2 -= x2 * (*val++);
5373 	               //                  rhs2[k] = ( y2 != 0 ) ? y2 : MARKER;
5374 	               rhs2[k] = y2;
5375 	            }
5376 	         }
5377 	      }
5378 	
5379 	      if(rn + rn2 > i * verySparseFactor4rightRat)
5380 	      {
5381 	         /* continue with dense case */
5382 	         if(*ridx > *ridx2)
5383 	            i = *ridx;
5384 	         else
5385 	            i = *ridx2;
5386 	
5387 	         for(; i >= 0; --i)
5388 	         {
5389 	            assert(i < thedim);
5390 	            r = rorig[i];
5391 	            assert(r >= 0 && r < thedim);
5392 	            x = diag[r] * rhs[r];
5393 	            x2 = diag[r] * rhs2[r];
5394 	            rhs[r] = 0;
5395 	            rhs2[r] = 0;
5396 	
5397 	            if(x2 != 0)
5398 	            {
5399 	               c = corig[i];
5400 	               assert(c >= 0 && c < thedim);
5401 	               vec2[c] = x2;
5402 	               val = &cval[cbeg[c]];
5403 	               idx = &cidx[cbeg[c]];
5404 	               j = clen[c];
5405 	
5406 	               if(x != 0)
5407 	               {
5408 	                  vidx[n++] = c;
5409 	                  vec[c] = x;
5410 	
5411 	                  while(j-- > 0)
5412 	                  {
5413 	                     assert(*idx >= 0 && *idx < thedim);
5414 	                     rhs[*idx] -= x * (*val);
5415 	                     rhs2[*idx++] -= x2 * (*val++);
5416 	                  }
5417 	               }
5418 	               else
5419 	               {
5420 	                  while(j-- > 0)
5421 	                  {
5422 	                     assert(*idx >= 0 && *idx < thedim);
5423 	                     rhs2[*idx++] -= x2 * (*val++);
5424 	                  }
5425 	               }
5426 	            }
5427 	            else if(x != 0)
5428 	            {
5429 	               c = corig[i];
5430 	               assert(c >= 0 && c < thedim);
5431 	               vidx[n++] = c;
5432 	               vec[c] = x;
5433 	               val = &cval[cbeg[c]];
5434 	               idx = &cidx[cbeg[c]];
5435 	               j = clen[c];
5436 	
5437 	               while(j-- > 0)
5438 	               {
5439 	                  assert(*idx >= 0 && *idx < thedim);
5440 	                  rhs[*idx++] -= x * (*val++);
5441 	               }
5442 	            }
5443 	         }
5444 	
5445 	         break;
5446 	      }
5447 	   }
5448 	
5449 	   return n;
5450 	}
5451 	
5452 	inline int CLUFactorRational::vSolveUpdateRight(Rational* vec, int* ridx, int n)
5453 	{
5454 	   int i, j, k;
5455 	   int end;
5456 	   Rational x, y;
5457 	   Rational* val;
5458 	   int* lrow, *lidx, *idx;
5459 	   int* lbeg;
5460 	
5461 	   assert(!l.updateType);               /* no Forest-Tomlin Updates */
5462 	
5463 	   VectorRational& lval = l.val;
5464 	   lidx = l.idx;
5465 	   lrow = l.row;
5466 	   lbeg = l.start;
5467 	   end = l.firstUnused;
5468 	
5469 	   for(i = l.firstUpdate; i < end; ++i)
5470 	   {
5471 	      assert(i >= 0 && i < thedim);
5472 	      x = vec[lrow[i]];
5473 	
5474 	      if(x != 0)
5475 	      {
5476 	         k = lbeg[i];
5477 	         assert(k >= 0 && k < l.val.dim());
5478 	         idx = &(lidx[k]);
5479 	         val = &(lval[k]);
5480 	
5481 	         for(j = lbeg[i + 1]; j > k; --j)
5482 	         {
5483 	            int m = ridx[n] = *idx++;
5484 	            assert(m >= 0 && m < thedim);
5485 	            y = vec[m];
5486 	            n += (y == 0) ? 1 : 0;
5487 	            y = y - x * (*val++);
5488 	            //            vec[m] = ( y != 0 ) ? y : MARKER;
5489 	            vec[m] = y;
5490 	         }
5491 	      }
5492 	   }
5493 	
5494 	   return n;
5495 	}
5496 	
5497 	inline void CLUFactorRational::vSolveUpdateRightNoNZ(Rational* vec)
5498 	{
5499 	   int i, j, k;
5500 	   int end;
5501 	   Rational x;
5502 	   Rational* val;
5503 	   int* lrow, *lidx, *idx;
5504 	   int* lbeg;
5505 	
5506 	   assert(!l.updateType);               /* no Forest-Tomlin Updates */
5507 	
5508 	   VectorRational& lval = l.val;
5509 	   lidx = l.idx;
5510 	   lrow = l.row;
5511 	   lbeg = l.start;
5512 	   end = l.firstUnused;
5513 	
5514 	   for(i = l.firstUpdate; i < end; ++i)
5515 	   {
5516 	      assert(i >= 0 && i < thedim);
5517 	
5518 	      if((x = vec[lrow[i]]) != 0)
5519 	      {
5520 	         k = lbeg[i];
5521 	         assert(k >= 0 && k < l.val.dim());
5522 	         idx = &(lidx[k]);
5523 	         val = &(lval[k]);
5524 	
5525 	         for(j = lbeg[i + 1]; j > k; --j)
5526 	         {
5527 	            assert(*idx >= 0 && *idx < thedim);
5528 	            vec[*idx++] -= x * (*val++);
5529 	         }
5530 	      }
5531 	   }
5532 	}
5533 	
5534 	
5535 	inline int CLUFactorRational::vSolveRight4update(Rational* vec,
5536 	      int* idx,                              /* result */
5537 	      Rational* rhs, int* ridx, int rn,                    /* rhs    */
5538 	      Rational* forest, int* forestNum, int* forestIdx)
5539 	{
5540 	   rn = vSolveLright(rhs, ridx, rn);
5541 	
5542 	   /*  turn index list into a heap
5543 	    */
5544 	
5545 	   if(forest)
5546 	   {
5547 	      Rational x;
5548 	      int i, j, k;
5549 	      int* rperm;
5550 	      int* it = forestIdx;
5551 	
5552 	      rperm = row.perm;
5553 	
5554 	      for(i = j = 0; i < rn; ++i)
5555 	      {
5556 	         k = ridx[i];
5557 	         assert(k >= 0 && k < thedim);
5558 	         x = rhs[k];
5559 	
5560 	         if(x != 0)
5561 	         {
5562 	            enQueueMaxRat(ridx, &j, rperm[*it++ = k]);
5563 	            forest[k] = x;
5564 	         }
5565 	         else
5566 	            rhs[k] = 0;
5567 	      }
5568 	
5569 	      *forestNum = rn = j;
5570 	   }
5571 	   else
5572 	   {
5573 	      Rational x;
5574 	      int i, j, k;
5575 	      int* rperm;
5576 	
5577 	      rperm = row.perm;
5578 	
5579 	      for(i = j = 0; i < rn; ++i)
5580 	      {
5581 	         k = ridx[i];
5582 	         assert(k >= 0 && k < thedim);
5583 	         x = rhs[k];
5584 	
5585 	         if(x != 0)
5586 	            enQueueMaxRat(ridx, &j, rperm[k]);
5587 	         else
5588 	            rhs[k] = 0;
5589 	      }
5590 	
5591 	      rn = j;
5592 	   }
5593 	
5594 	   rn = vSolveUright(vec, idx, rhs, ridx, rn);
5595 	
5596 	   if(!l.updateType)             /* no Forest-Tomlin Updates */
5597 	      rn = vSolveUpdateRight(vec, idx, rn);
5598 	
5599 	   return rn;
5600 	}
5601 	
5602 	inline int CLUFactorRational::vSolveRight4update2(Rational* vec,
5603 	      int* idx,                              /* result1 */
5604 	      Rational* rhs, int* ridx, int rn,                    /* rhs1    */
5605 	      Rational* vec2,                                      /* result2 */
5606 	      Rational* rhs2, int* ridx2, int rn2,                 /* rhs2    */
5607 	      Rational* forest, int* forestNum, int* forestIdx)
5608 	{
5609 	   vSolveLright2(rhs, ridx, &rn, rhs2, ridx2, &rn2);
5610 	
5611 	   /*  turn index list into a heap
5612 	    */
5613 	
5614 	   if(forest)
5615 	   {
5616 	      Rational x;
5617 	      int i, j, k;
5618 	      int* rperm;
5619 	      int* it = forestIdx;
5620 	
5621 	      rperm = row.perm;
5622 	
5623 	      for(i = j = 0; i < rn; ++i)
5624 	      {
5625 	         k = ridx[i];
5626 	         assert(k >= 0 && k < thedim);
5627 	         x = rhs[k];
5628 	
5629 	         if(x != 0)
5630 	         {
5631 	            enQueueMaxRat(ridx, &j, rperm[*it++ = k]);
5632 	            forest[k] = x;
5633 	         }
5634 	         else
5635 	            rhs[k] = 0;
5636 	      }
5637 	
5638 	      *forestNum = rn = j;
5639 	   }
5640 	   else
5641 	   {
5642 	      Rational x;
5643 	      int i, j, k;
5644 	      int* rperm;
5645 	
5646 	      rperm = row.perm;
5647 	
5648 	      for(i = j = 0; i < rn; ++i)
5649 	      {
5650 	         k = ridx[i];
5651 	         assert(k >= 0 && k < thedim);
5652 	         x = rhs[k];
5653 	
5654 	         if(x != 0)
5655 	            enQueueMaxRat(ridx, &j, rperm[k]);
5656 	         else
5657 	            rhs[k] = 0;
5658 	      }
5659 	
5660 	      rn = j;
5661 	   }
5662 	
5663 	   if(rn2 > thedim * verySparseFactor4rightRat)
5664 	   {
5665 	      ridx2[0] = thedim - 1;
5666 	      /* ridx2[1] = thedim - 2; */
5667 	   }
5668 	   else
5669 	   {
5670 	      Rational x;
5671 	      /*      Rational  maxabs; */
5672 	      int i, j, k;
5673 	      int* rperm;
5674 	
5675 	      /*      maxabs = 1;    */
5676 	      rperm = row.perm;
5677 	
5678 	      for(i = j = 0; i < rn2; ++i)
5679 	      {
5680 	         k = ridx2[i];
5681 	         assert(k >= 0 && k < thedim);
5682 	         x = rhs2[k];
5683 	
5684 	         if(x == 0)
5685 	         {
5686 	            /*              maxabs = (maxabs < -x) ? -x : maxabs;  */
5687 	            enQueueMaxRat(ridx2, &j, rperm[k]);
5688 	         }
5689 	         else
5690 	            rhs2[k] = 0;
5691 	      }
5692 	
5693 	      rn2 = j;
5694 	
5695 	   }
5696 	
5697 	   rn = vSolveUright(vec, idx, rhs, ridx, rn);
5698 	
5699 	   vSolveUrightNoNZ(vec2, rhs2, ridx2, rn2);
5700 	
5701 	   /*
5702 	    *  rn = vSolveUright2(vec, idx, rhs, ridx, rn, vec2, rhs2, ridx2, rn2 );
5703 	    */
5704 	
5705 	   if(!l.updateType)             /* no Forest-Tomlin Updates */
5706 	   {
5707 	      rn = vSolveUpdateRight(vec, idx, rn);
5708 	      vSolveUpdateRightNoNZ(vec2);
5709 	   }
5710 	
5711 	   return rn;
5712 	}
5713 	
5714 	inline int CLUFactorRational::vSolveRight4update3(Rational* vec,
5715 	      int* idx,                              /* result1 */
5716 	      Rational* rhs, int* ridx, int rn,                    /* rhs1    */
5717 	      Rational* vec2,                                      /* result2 */
5718 	      Rational* rhs2, int* ridx2, int rn2,                 /* rhs2    */
5719 	      Rational* vec3,                                      /* result3 */
5720 	      Rational* rhs3, int* ridx3, int rn3,                 /* rhs3    */
5721 	      Rational* forest, int* forestNum, int* forestIdx)
5722 	{
5723 	
5724 	   vSolveLright3(rhs, ridx, &rn, rhs2, ridx2, &rn2, rhs3, ridx3, &rn3);
5725 	   assert(rn >= 0 && rn <= thedim);
5726 	   assert(rn2 >= 0 && rn2 <= thedim);
5727 	   assert(rn3 >= 0 && rn3 <= thedim);
5728 	
5729 	   /*  turn index list into a heap
5730 	    */
5731 	
5732 	   if(forest)
5733 	   {
5734 	      Rational x;
5735 	      int i, j, k;
5736 	      int* rperm;
5737 	      int* it = forestIdx;
5738 	
5739 	      rperm = row.perm;
5740 	
5741 	      for(i = j = 0; i < rn; ++i)
5742 	      {
5743 	         k = ridx[i];
5744 	         assert(k >= 0 && k < thedim);
5745 	         x = rhs[k];
5746 	
5747 	         if(x != 0)
5748 	         {
5749 	            enQueueMaxRat(ridx, &j, rperm[*it++ = k]);
5750 	            forest[k] = x;
5751 	         }
5752 	         else
5753 	            rhs[k] = 0;
5754 	      }
5755 	
5756 	      *forestNum = rn = j;
5757 	   }
5758 	   else
5759 	   {
5760 	      Rational x;
5761 	      int i, j, k;
5762 	      int* rperm;
5763 	
5764 	      rperm = row.perm;
5765 	
5766 	      for(i = j = 0; i < rn; ++i)
5767 	      {
5768 	         k = ridx[i];
5769 	         assert(k >= 0 && k < thedim);
5770 	         x = rhs[k];
5771 	
5772 	         if(x != 0)
5773 	            enQueueMaxRat(ridx, &j, rperm[k]);
5774 	         else
5775 	            rhs[k] = 0;
5776 	      }
5777 	
5778 	      rn = j;
5779 	   }
5780 	
5781 	   if(rn2 > thedim * verySparseFactor4rightRat)
5782 	   {
5783 	      ridx2[0] = thedim - 1;
5784 	   }
5785 	   else
5786 	   {
5787 	      Rational x;
5788 	      int i, j, k;
5789 	      int* rperm;
5790 	
5791 	      rperm = row.perm;
5792 	
5793 	      for(i = j = 0; i < rn2; ++i)
5794 	      {
5795 	         k = ridx2[i];
5796 	         assert(k >= 0 && k < thedim);
5797 	         x = rhs2[k];
5798 	
5799 	         if(x == 0)
5800 	         {
5801 	            enQueueMaxRat(ridx2, &j, rperm[k]);
5802 	         }
5803 	         else
5804 	            rhs2[k] = 0;
5805 	      }
5806 	
5807 	      rn2 = j;
5808 	   }
5809 	
5810 	   if(rn3 > thedim * verySparseFactor4rightRat)
5811 	   {
5812 	      ridx3[0] = thedim - 1;
5813 	   }
5814 	   else
5815 	   {
5816 	      Rational x;
5817 	      int i, j, k;
5818 	      int* rperm;
5819 	
5820 	      rperm = row.perm;
5821 	
5822 	      for(i = j = 0; i < rn3; ++i)
5823 	      {
5824 	         k = ridx3[i];
5825 	         assert(k >= 0 && k < thedim);
5826 	         x = rhs3[k];
5827 	
5828 	         if(x == 0)
5829 	         {
5830 	            enQueueMaxRat(ridx3, &j, rperm[k]);
5831 	         }
5832 	         else
5833 	            rhs3[k] = 0;
5834 	      }
5835 	
5836 	      rn3 = j;
5837 	   }
5838 	
5839 	   rn = vSolveUright(vec, idx, rhs, ridx, rn);
5840 	
5841 	   vSolveUrightNoNZ(vec2, rhs2, ridx2, rn2);
5842 	   vSolveUrightNoNZ(vec3, rhs3, ridx3, rn3);
5843 	
5844 	   if(!l.updateType)             /* no Forest-Tomlin Updates */
5845 	   {
5846 	      rn = vSolveUpdateRight(vec, idx, rn);
5847 	      vSolveUpdateRightNoNZ(vec2);
5848 	      vSolveUpdateRightNoNZ(vec3);
5849 	   }
5850 	
5851 	   return rn;
5852 	}
5853 	
5854 	inline void CLUFactorRational::vSolveRightNoNZ(Rational*
5855 	      vec2,                          /* result2 */
5856 	      Rational* rhs2, int* ridx2, int rn2)    /* rhs2    */
5857 	{
5858 	   rn2 = vSolveLright(rhs2, ridx2, rn2);
5859 	   assert(rn2 >= 0 && rn2 <= thedim);
5860 	
5861 	   if(rn2 > thedim * verySparseFactor4rightRat)
5862 	   {
5863 	      *ridx2 = thedim - 1;
5864 	   }
5865 	   else
5866 	   {
5867 	      Rational x;
5868 	      /*      Rational  maxabs; */
5869 	      int i, j, k;
5870 	      int* rperm;
5871 	
5872 	      /*      maxabs = 1;    */
5873 	      rperm = row.perm;
5874 	
5875 	      for(i = j = 0; i < rn2; ++i)
5876 	      {
5877 	         k = ridx2[i];
5878 	         assert(k >= 0 && k < thedim);
5879 	         x = rhs2[k];
5880 	
5881 	         if(x == 0)
5882 	         {
5883 	            /*              maxabs = (maxabs < -x) ? -x : maxabs;  */
5884 	            enQueueMaxRat(ridx2, &j, rperm[k]);
5885 	         }
5886 	         else
5887 	            rhs2[k] = 0;
5888 	      }
5889 	
5890 	      rn2 = j;
5891 	   }
5892 	
5893 	   vSolveUrightNoNZ(vec2, rhs2, ridx2, rn2);
5894 	
5895 	   if(!l.updateType)             /* no Forest-Tomlin Updates */
5896 	      vSolveUpdateRightNoNZ(vec2);
5897 	}
5898 	
5899 	inline int CLUFactorRational::vSolveLeft(Rational* vec, int* idx,                      /* result */
5900 	      Rational* rhs, int* ridx, int rn)            /* rhs    */
5901 	{
5902 	
5903 	   if(!l.updateType)             /* no Forest-Tomlin Updates */
5904 	   {
5905 	      rn = solveUpdateLeft(rhs, ridx, rn);
5906 	      rn = solveUleft(vec, idx, rhs, ridx, rn);
5907 	   }
5908 	   else
5909 	   {
5910 	      rn = solveUleft(vec, idx, rhs, ridx, rn);
5911 	      rn = solveLleftForest(vec, idx, rn);
5912 	   }
5913 	
5914 	   return solveLleft(vec, idx, rn);
5915 	}
5916 	
5917 	inline int CLUFactorRational::vSolveLeft2(Rational* vec,
5918 	      int* idx,                       /* result */
5919 	      Rational* rhs, int* ridx, int rn,             /* rhs    */
5920 	      Rational* vec2,                               /* result2 */
5921 	      Rational* rhs2, int* ridx2, int rn2)          /* rhs2    */
5922 	{
5923 	
5924 	   if(!l.updateType)             /* no Forest-Tomlin Updates */
5925 	   {
5926 	      rn = solveUpdateLeft(rhs, ridx, rn);
5927 	      rn = solveUleft(vec, idx, rhs, ridx, rn);
5928 	      rn2 = solveUpdateLeft(rhs2, ridx2, rn2);
5929 	      solveUleftNoNZ(vec2, rhs2, ridx2, rn2);
5930 	   }
5931 	   else
5932 	   {
5933 	      rn = solveUleft(vec, idx, rhs, ridx, rn);
5934 	      rn = solveLleftForest(vec, idx, rn);
5935 	      solveUleftNoNZ(vec2, rhs2, ridx2, rn2);
5936 	      solveLleftForestNoNZ(vec2);
5937 	   }
5938 	
5939 	   rn = solveLleft(vec, idx, rn);
5940 	
5941 	   solveLleftNoNZ(vec2);
5942 	
5943 	   return rn;
5944 	}
5945 	
5946 	inline int CLUFactorRational::vSolveLeft3(Rational* vec,
5947 	      int* idx,                       /* result */
5948 	      Rational* rhs, int* ridx, int rn,             /* rhs    */
5949 	      Rational* vec2,                               /* result2 */
5950 	      Rational* rhs2, int* ridx2, int rn2,          /* rhs2    */
5951 	      Rational* vec3,                               /* result3 */
5952 	      Rational* rhs3, int* ridx3, int rn3)          /* rhs3    */
5953 	{
5954 	
5955 	   if(!l.updateType)             /* no Forest-Tomlin Updates */
5956 	   {
5957 	      rn = solveUpdateLeft(rhs, ridx, rn);
5958 	      rn = solveUleft(vec, idx, rhs, ridx, rn);
5959 	      rn2 = solveUpdateLeft(rhs2, ridx2, rn2);
5960 	      solveUleftNoNZ(vec2, rhs2, ridx2, rn2);
5961 	      rn3 = solveUpdateLeft(rhs3, ridx3, rn3);
5962 	      solveUleftNoNZ(vec3, rhs3, ridx3, rn3);
5963 	   }
5964 	   else
5965 	   {
5966 	      rn = solveUleft(vec, idx, rhs, ridx, rn);
5967 	      rn = solveLleftForest(vec, idx, rn);
5968 	      solveUleftNoNZ(vec2, rhs2, ridx2, rn2);
5969 	      solveLleftForestNoNZ(vec2);
5970 	      solveUleftNoNZ(vec3, rhs3, ridx3, rn3);
5971 	      solveLleftForestNoNZ(vec3);
5972 	   }
5973 	
5974 	   rn = solveLleft(vec, idx, rn);
5975 	
5976 	   solveLleftNoNZ(vec2);
5977 	   solveLleftNoNZ(vec3);
5978 	
5979 	   return rn;
5980 	}
5981 	
5982 	inline void CLUFactorRational::vSolveLeftNoNZ(Rational*
5983 	      vec2,                             /* result2 */
5984 	      Rational* rhs2, int* ridx2, int rn2)       /* rhs2    */
5985 	{
5986 	
5987 	   if(!l.updateType)             /* no Forest-Tomlin Updates */
5988 	   {
5989 	      rn2 = solveUpdateLeft(rhs2, ridx2, rn2);
5990 	      solveUleftNoNZ(vec2, rhs2, ridx2, rn2);
5991 	   }
5992 	   else
5993 	   {
5994 	      solveUleftNoNZ(vec2, rhs2, ridx2, rn2);
5995 	      solveLleftForestNoNZ(vec2);
5996 	   }
5997 	
5998 	   solveLleftNoNZ(vec2);
5999 	}
6000 	} // namespace soplex
6001