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