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