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