1 // Copyright (c) 1997-2007 ETH Zurich (Switzerland).
2 // All rights reserved.
3 //
4 // This file is part of CGAL (www.cgal.org).
5 //
6 // $URL: https://github.com/CGAL/cgal/blob/v5.3/QP_solver/include/CGAL/QP_solver/QP_basis_inverse_impl.h $
7 // $Id: QP_basis_inverse_impl.h a91f023 2021-01-29T10:05:48+01:00 Sébastien Loriot
8 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
9 //
10 //
11 // Author(s) : Sven Schoenherr
12 // Bernd Gaertner <gaertner@inf.ethz.ch>
13 // Franz Wessendorp
14 // Kaspar Fischer
15
16 namespace CGAL {
17
18 // =============================
19 // class implementation (cont'd)
20 // =============================
21
22 // creation and initialization
23 // ---------------------------
24 // set-up
25 template < class ET_, class Is_LP_ >
26 void QP_basis_inverse<ET_,Is_LP_>::
set(int n,int m,int nr_equalities)27 set( int n, int m, int nr_equalities)
28 {
29 CGAL_qpe_assertion( n >= 0);
30 CGAL_qpe_assertion( m >= 0);
31 b = s = 0;
32 // l is the maximum size of the basis in phase I
33 l = (std::min)( n+nr_equalities+1, m);
34 if ( ! M.empty()) M.clear();
35 set( Is_LP());
36
37 if ( ! x_l.empty()) x_l.clear();
38 if ( ! x_x.empty()) x_x.clear();
39
40 x_l.insert( x_l.end(), l, et0);
41 x_x.insert( x_x.end(), l, et0); // has to grow later QP-case
42
43 if ( ! tmp_l.empty()) tmp_l.clear();
44 if ( ! tmp_x.empty()) tmp_x.clear();
45
46 tmp_l.insert( tmp_l.end(), l, et0);
47 tmp_x.insert( tmp_x.end(), l, et0); // has to grow later QP-case
48
49 }
50
51 // update functions
52 // ----------------
53 // leaving of original variable (update type U2)
54 template < class ET_, class Is_LP_ >
55 void QP_basis_inverse<ET_,Is_LP_>::
leave_original()56 leave_original( )
57 {
58 // assert QP case
59 Assert_compile_time_tag( Tag_false(), Is_LP());
60
61 // determine new denominator (`z')
62 --b;
63 ET z = M[ l+b][ l+b];
64 bool z_neg = ( z < et0);
65 CGAL_qpe_assertion( z != et0);
66
67 // update matrix in place
68 update_inplace_QP( M[ l+b].begin(), M[ l+b].begin()+l,
69 -z, ( z_neg ? d : -d));
70
71 // store new denominator
72 d = ( z_neg ? -z : z);
73 CGAL_qpe_assertion( d > et0);
74
75 CGAL_qpe_debug {
76 if ( vout.verbose()) print();
77 }
78 }
79
80 // entering of slack variable (update type U3)
81 template < class ET_, class Is_LP_ >
82 void QP_basis_inverse<ET_,Is_LP_>::
enter_slack()83 enter_slack( )
84 {
85 // assert QP case
86 Assert_compile_time_tag( Tag_false(), Is_LP());
87
88 // determine new denominator (`z')
89 --s;
90 ET z = M[ s][ s];
91 bool z_neg = ( z < et0);
92 CGAL_qpe_assertion( z != et0);
93
94 // update matrix in place
95 typename Matrix::iterator col_it;
96 typename Row ::iterator x_it;
97 unsigned int col;
98 for ( col = 0, col_it = M.begin()+l, x_it = x_x.begin();
99 col < b;
100 ++col, ++col_it, ++x_it ) {
101 *x_it = (*col_it)[ s];
102 }
103 update_inplace_QP( M[ s].begin(), x_x.begin(), -z, ( z_neg ? d : -d));
104
105 // store new denominator
106 d = ( z_neg ? -z : z);
107 CGAL_qpe_assertion( d > et0);
108
109 CGAL_qpe_debug {
110 if ( vout.verbose()) print();
111 }
112 }
113
114 // replacing of original by slack variable (update type U8)
115 template < class ET_, class Is_LP_ >
116 void QP_basis_inverse<ET_,Is_LP_>::
enter_slack_leave_original()117 enter_slack_leave_original( )
118 {
119 // assert LP case or phase I
120 CGAL_qpe_assertion( is_LP || is_phaseI);
121
122 // update matrix in-place
123 // ----------------------
124 typename Matrix::iterator matrix_it;
125 typename Row ::iterator x_it;
126 unsigned int row;
127
128 // QP (in phase I)?
129 matrix_it = M.begin();
130 if ( is_QP) matrix_it += l;
131
132 // get last column of basis inverse (store it in 'x_x')
133 --s; --b;
134 for ( row = 0, x_it = x_x.begin();
135 row < s;
136 ++row, ++x_it, ++matrix_it) {
137 *x_it = (*matrix_it)[ b];
138 }
139 ET z = (*matrix_it)[ b];
140 bool z_neg = ( z < et0);
141 CGAL_qpe_assertion( z != et0);
142
143 // update matrix
144 update_inplace_LP( matrix_it->begin(), x_x.begin(), -z, ( z_neg ? d : -d));
145
146 // store new denominator
147 // ---------------------
148 d = ( z_neg ? -z : z);
149 CGAL_qpe_assertion( d > et0);
150
151 CGAL_qpe_debug {
152 if ( vout.verbose()) print();
153 }
154 }
155
156
157 // replacing of original by original variable with precondition in QP-case
158 // for phaseII (update type UZ_1)
159 template < class ET_, class Is_LP_ >
160 template < class ForwardIterator >
161 void QP_basis_inverse<ET_,Is_LP_>::
z_replace_original_by_original(ForwardIterator y_l_it,ForwardIterator y_x_it,const ET & s_delta,const ET & s_nu,unsigned int k_i)162 z_replace_original_by_original(ForwardIterator y_l_it,
163 ForwardIterator y_x_it, const ET& s_delta,
164 const ET& s_nu, unsigned int k_i)
165 {
166
167 // assert QP case and phaseII
168 CGAL_qpe_assertion(is_QP && is_phaseII);
169
170
171 // prepare \hat{k}_{1} -scalar
172 ET hat_k_1 = *(y_x_it + k_i);
173
174 // prepare \hat{\rho} -vector in x_l, x_x
175 copy_row_in_B_O(x_l.begin(), x_x.begin(), k_i);
176
177 // prepare \hat{v} -vector in tmp_l, tmp_x
178
179 // tmp_l -part
180 std::transform(y_l_it, (y_l_it+s), x_l.begin(), tmp_l.begin(),
181 [&s_delta](const ET& v1, const ET& v2){ return std::plus<ET>()(v1, s_delta * v2); });
182 // tmp_x -part
183 std::transform(y_x_it, (y_x_it+b), x_x.begin(), tmp_x.begin(),
184 [&s_delta](const ET& v1, const ET& v2){ return std::plus<ET>()(v1, s_delta * v2); });
185 tmp_x[k_i] -= d;
186
187 // prepare \hat{k}_{2} -scalar
188 ET hat_k_2 = s_nu - (et2 * s_delta * hat_k_1);
189
190 CGAL_qpe_assertion( d != et0);
191
192 // update matrix in place
193 z_update_inplace(x_l.begin(), x_x.begin(), tmp_l.begin(), tmp_x.begin(),
194 hat_k_1 * hat_k_1, -hat_k_2, -hat_k_1, d*d);
195
196 // store new denominator
197 d = CGAL::integral_division(hat_k_1 * hat_k_1, d);
198
199 CGAL_qpe_assertion( d > et0);
200
201 CGAL_qpe_debug {
202 if ( vout.verbose()) print();
203 }
204
205 }
206
207
208 // replacing of original by slack variable with precondition in QP-case
209 // for phaseII (update type UZ_2)
210 template < class ET_, class Is_LP_ >
211 void QP_basis_inverse<ET_,Is_LP_>::
z_replace_original_by_slack()212 z_replace_original_by_slack( )
213 {
214
215 // assert QP case and phaseII
216 CGAL_qpe_assertion(is_QP && is_phaseII);
217
218 // adapt s and b
219 --s; --b;
220
221 // prepare \hat{\rho} -vector in x_l, x_x
222 copy_row_in_B_O(x_l.begin(), x_x.begin(), b);
223
224 // prepare \hat{\varrho} -vector in tmp_l, tmp_x
225 copy_row_in_C(tmp_l.begin(), tmp_x.begin(), s);
226
227 // prepare \hat{\kappa} -scalar
228 ET hat_kappa = M[l+b][s];
229
230 // prepare \hat{\xi} -scalar
231 ET hat_xi = M[s][s];
232
233 CGAL_qpe_assertion( d != et0);
234
235 // update matrix in place
236 z_update_inplace(x_l.begin(), x_x.begin(), tmp_l.begin(), tmp_x.begin(),
237 hat_kappa * hat_kappa, hat_xi, -hat_kappa, d * d);
238
239 // store new denominator
240 d = CGAL::integral_division(hat_kappa * hat_kappa, d);
241
242 CGAL_qpe_assertion( d > et0);
243
244 CGAL_qpe_debug {
245 if ( vout.verbose()) print();
246 }
247
248 }
249
250
251 // replacing of slack by original variable with precondition in QP-case
252 // for phaseII (update type UZ_3)
253 template < class ET_, class Is_LP_ >
254 template < class ForwardIterator >
255 void QP_basis_inverse<ET_,Is_LP_>::
z_replace_slack_by_original(ForwardIterator y_l_it,ForwardIterator y_x_it,ForwardIterator u_x_it,const ET & hat_kappa,const ET & hat_nu)256 z_replace_slack_by_original(ForwardIterator y_l_it,
257 ForwardIterator y_x_it,
258 ForwardIterator u_x_it, const ET& hat_kappa,
259 const ET& hat_nu)
260 {
261 // assert QP case and phaseII
262 CGAL_qpe_assertion(is_QP && is_phaseII);
263
264 // get copies of y_l_it and y_x_it for later use
265 ForwardIterator y_l_it_copy = y_l_it;
266 ForwardIterator y_x_it_copy = y_x_it;
267
268 CGAL_qpe_assertion( d != et0);
269
270 // prepare \hat{\phi}
271
272 // prepare \hat{\varphi} -vector in x_l, x_x
273 multiply(u_x_it, u_x_it, x_l.begin(), x_x.begin(), Tag_false(),
274 Tag_false());
275
276 // prepare \hat{\kappa} -scalar
277
278 // prepare \hat{\nu} -scalar
279
280 // update matrix in place
281 z_update_inplace(x_l.begin(), x_x.begin(), y_l_it, y_x_it,
282 hat_kappa * hat_kappa, -hat_nu, hat_kappa, d * d);
283
284 // append new rows and columns
285 // ---------------------------
286 typename Row ::iterator row_it, x_l_it, x_x_it;
287 typename Matrix::iterator matrix_it;
288 unsigned int count;
289
290 // insert new row and column at the end of block P
291 CGAL_qpe_assertion(M.size()>=s+1);
292 if (M[s].size()==0) {
293 // row has to be filled first
294 M[s].insert(M[s].end(), s+1, et0);
295 }
296
297
298 // P-block: left of diagonal (including element on diagonal)
299 y_l_it = y_l_it_copy;
300 for ( row_it = M[s].begin(), x_l_it = x_l.begin();
301 row_it != M[s].end() - 1;
302 ++row_it, ++x_l_it, ++y_l_it ) {
303 *row_it =
304 CGAL::integral_division((hat_nu * *x_l_it)-(hat_kappa * *y_l_it), d);
305 }
306 *row_it = -hat_nu;
307
308 // Q-block
309 y_x_it = y_x_it_copy;
310 for ( matrix_it = M.begin()+l, count = 0, x_x_it = x_x.begin();
311 count < b;
312 ++matrix_it, ++count, ++x_x_it, ++y_x_it ) {
313 (*matrix_it)[s] =
314 CGAL::integral_division((hat_nu * *x_x_it) - (hat_kappa * *y_x_it), d);
315 }
316
317 // insert new row and column at the end of blocks Q and R
318 ensure_physical_row(l+b);
319
320 // Q-block
321 for ( row_it = M[l+b].begin(), count = 0, x_l_it = x_l.begin();
322 count < s;
323 ++row_it, ++count, ++x_l_it ) {
324 *row_it = CGAL::integral_division(-hat_kappa * *x_l_it, d);
325 }
326 *row_it = hat_kappa;
327
328 // R-block
329 for ( row_it = M[l+b].begin()+l, count = 0, x_x_it = x_x.begin();
330 count < b;
331 ++row_it, ++count, ++x_x_it ) {
332 *row_it = CGAL::integral_division(-hat_kappa * *x_x_it, d);
333 }
334 *row_it = et0;
335
336 //adapt s and b
337 ++s; ++b;
338
339 // store new denominator
340 d = CGAL::integral_division(hat_kappa * hat_kappa, d);
341
342 CGAL_qpe_assertion( d > et0);
343
344 CGAL_qpe_debug {
345 if ( vout.verbose()) print();
346 }
347
348 }
349
350
351 // replacing of slack by slack variable with precondition in QP-case
352 // for phaseII (update type UZ_4)
353 template < class ET_, class Is_LP_ >
354 template < class ForwardIterator >
355 void QP_basis_inverse<ET_,Is_LP_>::
z_replace_slack_by_slack(ForwardIterator u_x_it,unsigned int k_j)356 z_replace_slack_by_slack(ForwardIterator u_x_it, unsigned int k_j)
357 {
358
359 // assert QP case and phaseII
360 CGAL_qpe_assertion(is_QP && is_phaseII);
361
362 // prepare \hat{v} -vector in x_l, x_x
363 multiply(u_x_it, u_x_it, x_l.begin(), x_x.begin(),Tag_false(),
364 Tag_false());
365 x_l[k_j] -= d;
366
367 // prepare \hat{\varrho} -vector in tmp_l, tmp_x
368 copy_row_in_C(tmp_l.begin(), tmp_x.begin(), k_j);
369
370 // prepare \hat{k}_{1} -scalar
371 ET hat_k_1 = inner_product_x(tmp_x.begin(), u_x_it);
372
373 // prepare \hat{k}_{3} -scalar
374 ET hat_k_3 = -M[k_j][k_j];
375
376 CGAL_qpe_assertion( d != et0);
377
378 // update matrix in place
379 z_update_inplace(x_l.begin(), x_x.begin(), tmp_l.begin(), tmp_x.begin(),
380 hat_k_1 * hat_k_1, -hat_k_3, -hat_k_1, d * d);
381
382 // store new denominator
383 d = CGAL::integral_division(hat_k_1 * hat_k_1, d);
384
385 CGAL_qpe_assertion( d > et0);
386
387 CGAL_qpe_debug {
388 if ( vout.verbose()) print();
389 }
390
391 }
392
393
394 // copying of reduced basis inverse row in (upper) C-half
395 template < class ET_, class Is_LP_ >
396 template < class OutIt >
397 void QP_basis_inverse<ET_,Is_LP_>::
copy_row_in_C(OutIt y_l_it,OutIt y_x_it,unsigned int r)398 copy_row_in_C(OutIt y_l_it, OutIt y_x_it, unsigned int r)
399 {
400 typename Matrix::const_iterator matrix_it;
401 typename Row ::const_iterator row_it;
402 unsigned int count;
403
404 // P-block: left of diagonal (including element on diagonal)
405 matrix_it = M.begin()+r;
406 for ( row_it = matrix_it->begin();
407 row_it != matrix_it->end();
408 ++row_it, ++y_l_it ) {
409 *y_l_it = *row_it;
410 }
411
412 // P-block: right of diagonal (excluding element on diagonal)
413 for ( matrix_it = M.begin()+r+1, count = r+1;
414 count < s;
415 ++matrix_it, ++count, ++y_l_it ) {
416 *y_l_it = (*matrix_it)[r];
417 }
418
419 // Q-block
420 for ( matrix_it = M.begin()+l, count = 0;
421 count < b;
422 ++matrix_it, ++count, ++y_x_it ) {
423 *y_x_it = (*matrix_it)[r];
424 }
425 }
426
427
428 // copying of reduced basis inverse row in (lower) B_O-half
429 template < class ET_, class Is_LP_ >
430 template < class OutIt >
431 void QP_basis_inverse<ET_,Is_LP_>::
copy_row_in_B_O(OutIt y_l_it,OutIt y_x_it,unsigned int r)432 copy_row_in_B_O(OutIt y_l_it, OutIt y_x_it, unsigned int r)
433 {
434 typename Matrix::const_iterator matrix_it;
435 typename Row ::const_iterator row_it;
436 unsigned int count;
437
438 // Q-block
439 matrix_it = M.begin()+l+r;
440 for ( row_it = matrix_it->begin(), count = 0;
441 count < s;
442 ++row_it, ++count, ++y_l_it ) {
443 *y_l_it = *row_it;
444 }
445
446 // R-block: left of diagonal (including element on diagonal)
447 for ( row_it = matrix_it->begin()+l;
448 row_it != matrix_it->end();
449 ++row_it, ++y_x_it ) {
450 *y_x_it = *row_it;
451 }
452
453 // R-block: right of diagonal (excluding element on diagonal)
454 for ( matrix_it = M.begin()+l+r+1, count = r+1;
455 count < b;
456 ++matrix_it, ++count, ++y_x_it ) {
457 *y_x_it = (*matrix_it)[l+r];
458 }
459
460 }
461
462 template < class ET_, class Is_LP_ >
463 template < class ForIt >
464 void QP_basis_inverse<ET_,Is_LP_>::
z_update_inplace(ForIt psi1_l_it,ForIt psi1_x_it,ForIt psi2_l_it,ForIt psi2_x_it,const ET & omega0,const ET & omega1,const ET & omega2,const ET & omega3)465 z_update_inplace( ForIt psi1_l_it, ForIt psi1_x_it,
466 ForIt psi2_l_it, ForIt psi2_x_it,
467 const ET& omega0, const ET& omega1,
468 const ET& omega2, const ET& omega3)
469 {
470 typename Matrix:: iterator matrix_it;
471 typename Row :: iterator row_it;
472 typename Row ::const_iterator y_it1_r, y_it1_c, y_it2_r, y_it2_c;
473
474 unsigned int row, col, k = l+b;
475 ET u_elem;
476
477 // rows: 0..s-1 ( P )
478 for ( row = 0, matrix_it = M.begin(),
479 y_it1_r = psi1_l_it, y_it2_r = psi2_l_it;
480 row < s;
481 ++row, ++matrix_it, ++y_it1_r, ++y_it2_r ) {
482
483 // columns: 0..row ( P )
484 for ( row_it = matrix_it->begin(),
485 y_it1_c = psi1_l_it, y_it2_c = psi2_l_it;
486 row_it != matrix_it->end();
487 ++row_it, ++y_it1_c, ++y_it2_c ) {
488
489 u_elem = (*y_it1_r * *y_it2_c) + (*y_it2_r * *y_it1_c);
490 u_elem *= omega2;
491 u_elem += omega1 * *y_it1_r * *y_it1_c;
492 update_entry( *row_it, omega0, u_elem, omega3);
493 }
494 }
495
496 // rows: l..k-1 ( Q R )
497 for ( row = l, matrix_it = M.begin()+l,
498 y_it1_r = psi1_x_it, y_it2_r = psi2_x_it;
499 row != k;
500 ++row, ++matrix_it, ++y_it1_r, ++y_it2_r ) {
501
502 // columns: 0..s-1 ( Q )
503 for ( col = 0, row_it = matrix_it->begin(),
504 y_it1_c = psi1_l_it, y_it2_c = psi2_l_it;
505 col < s;
506 ++col, ++row_it, ++y_it1_c, ++y_it2_c ){
507
508 u_elem = (*y_it1_r * *y_it2_c) + (*y_it2_r * *y_it1_c);
509 u_elem *= omega2;
510 u_elem += omega1 * *y_it1_r * *y_it1_c;
511 update_entry( *row_it, omega0, u_elem, omega3);
512 }
513
514 // columns: l..k-1 ( R )
515 for ( row_it = matrix_it->begin()+l,
516 y_it1_c = psi1_x_it, y_it2_c = psi2_x_it;
517 row_it != matrix_it->end();
518 ++row_it, ++y_it1_c, ++y_it2_c ){
519
520 u_elem = (*y_it1_r * *y_it2_c) + (*y_it2_r * *y_it1_c);
521 u_elem *= omega2;
522 u_elem += omega1 * *y_it1_r * *y_it1_c;
523 update_entry( *row_it, omega0, u_elem, omega3);
524 }
525
526 }
527
528 }
529
530
531 // swap functions
532 // --------------
533 // swap variable ``to the end'' of R
534 template < class ET_, class Is_LP_ > // LP case
535 void QP_basis_inverse<ET_,Is_LP_>::
swap_variable(unsigned int j,Tag_true)536 swap_variable( unsigned int j, Tag_true)
537 {
538 unsigned int k = b-1;
539 if ( j == k) return;
540
541 // swap rows
542 // ---------
543 typename Row::iterator row_j_it = M[ j].begin();
544 typename Row::iterator row_k_it = M[ k].begin();
545 unsigned int count;
546
547 // swap entries 0..b-1 (row <-> row) [in Q]
548 for ( count = 0;
549 count < b;
550 ++count, ++row_j_it, ++row_k_it) {
551 std::iter_swap( row_j_it, row_k_it);
552 }
553 }
554
555 template < class ET_, class Is_LP_ > // QP case
556 void QP_basis_inverse<ET_,Is_LP_>::
swap_variable(unsigned int j,Tag_false)557 swap_variable( unsigned int j, Tag_false)
558 {
559 unsigned int i = l+j, k = l+b-1;
560 if ( i == k) return;
561
562 // swap rows and columns
563 // ---------------------
564 typename Row::iterator row_i_it = M[ i].begin();
565 typename Row::iterator row_k_it = M[ k].begin();
566 typename Matrix::iterator matrix_it = M.begin()+(i+1);
567 unsigned int count;
568
569 // swap entries 0..s-1 (row <-> row) [in Q]
570 for ( count = 0;
571 count < s;
572 ++count, ++row_i_it, ++row_k_it) {
573 std::iter_swap( row_i_it, row_k_it);
574 }
575
576 if ( is_phaseII) {
577
578 // swap entries l..i-1 (row <-> row) [in R]
579 for ( count = l, row_i_it += l-s, row_k_it += l-s;
580 count < i;
581 ++count, ++row_i_it, ++row_k_it ) {
582 std::iter_swap( row_i_it, row_k_it);
583 }
584
585 // swap entries i+1..k-1 (column <-> row) [in R]
586 for ( ++count, ++row_k_it;
587 count < k;
588 ++count, ++matrix_it, ++row_k_it) {
589 std::swap( ( *matrix_it)[ i], *row_k_it);
590 }
591
592 // swap entries i,i with k,k (entry <-> entry) [in R]
593 std::iter_swap( row_i_it, row_k_it);
594 }
595 }
596
597 // swap constraint ``to the end'' of P
598 template < class ET_, class Is_LP_ > // LP case
599 void QP_basis_inverse<ET_,Is_LP_>::
swap_constraint(unsigned int i,Tag_true)600 swap_constraint( unsigned int i, Tag_true)
601 {
602 unsigned int k = s-1;
603 if ( i == k) return;
604
605 // swap columns
606 // ------------
607 typename Matrix::iterator matrix_it = M.begin();
608 unsigned int count;
609
610 // swap entries 0..s-1 (column <-> column) [in Q]
611 for ( count = 0;
612 count < s;
613 ++count, ++matrix_it) {
614 std::swap( ( *matrix_it)[ i], ( *matrix_it)[ k]);
615 }
616 }
617
618 template < class ET_, class Is_LP_ > // QP case
619 void QP_basis_inverse<ET_,Is_LP_>::
swap_constraint(unsigned int i,Tag_false)620 swap_constraint( unsigned int i, Tag_false)
621 {
622
623 if ( i == s-1) return;
624
625 // swap rows and columns
626 // ---------------------
627 typename Row::iterator row_i_it = M[ i].begin();
628 typename Row::iterator row_k_it = M[ s-1].begin();
629 typename Matrix::iterator matrix_it = M.begin()+i;
630 unsigned int count;
631
632 if ( is_phaseI) {
633
634 // skip empty P
635 matrix_it =M.begin() + l;
636
637 } else {
638
639 // swap entries 0..i-1 (row <-> row) [in P]
640 for ( count = 0;
641 count < i;
642 ++count, ++row_i_it, ++row_k_it) {
643 std::iter_swap( row_i_it, row_k_it);
644 }
645
646 // swap entries i+1..s-2 (column <-> row) [in P]
647 for ( count = i + 1, ++matrix_it, ++row_k_it;
648 count < s-1;
649 ++count, ++matrix_it, ++row_k_it) {
650 std::swap( ( *matrix_it)[ i], *row_k_it);
651 }
652 // the remaining two entries to be swapped on the main diagonal
653 std::swap(M[i][i], M[s-1][s-1]);
654
655 // advance to Q
656 matrix_it = M.begin() + l;
657 }
658
659 // swap entries l..l+b (column <-> column) [in Q]
660 for ( count = 0;
661 count < b;
662 ++count, ++matrix_it) {
663 std::swap( ( *matrix_it)[ i], ( *matrix_it)[ s-1]);
664 }
665 }
666
667 // diagnostic output
668 // -----------------
669 template < class ET_, class Is_LP_ >
670 void QP_basis_inverse<ET_,Is_LP_>::
print()671 print( )
672 {
673 // P
674 if ( is_LP || is_phaseII) {
675 for ( unsigned int row = 0; row < s; ++row) {
676 std::copy( M[ row].begin(),
677 M[ row].begin() + ( is_LP ? s : row+1),
678 std::ostream_iterator<ET>( vout.out(), " "));
679 vout.out() << std::endl;
680 }
681 if ( is_QP) vout.out() << "= = = = = = = = = =" << std::endl;
682 }
683
684 // Q & R
685 if ( is_QP) {
686 for ( unsigned int row = l; row < l+b; ++row) {
687 std::copy( M[ row].begin(), M[ row].begin()+s,
688 std::ostream_iterator<ET>( vout.out(), " "));
689 if ( is_phaseII) {
690 vout.out() << "|| ";
691 std::copy( M[ row].begin()+l, M[ row].end(),
692 std::ostream_iterator<ET>( vout.out(), " "));
693 }
694 vout.out() << std::endl;
695 }
696 }
697 vout.out() << "denominator = " << d << std::endl;
698 }
699
700 } //namespace CGAL
701
702 // ===== EOF ==================================================================
703