Scippy

SoPlex

Sequential object-oriented simPlex

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