Scippy

SoPlex

Sequential object-oriented simPlex

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