Bug Summary

File:usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/bits/predefined_ops.h
Warning:line 43, column 16
Use of zero-allocated memory

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name CglProbing.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -D HAVE_CONFIG_H -I . -I . -I .. -I ./.. -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/coinmp/CoinUtils/src -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/coinmp/Osi/src/Osi -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/coinmp/CoinUtils/src -D NDEBUG -D CGL_BUILD -D PIC -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wwrite-strings -Wno-unknown-pragmas -Wno-long-long -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/coinmp/Cgl/src/CglProbing -ferror-limit 19 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ CglProbing.cpp

CglProbing.cpp

1// $Id: CglProbing.cpp 1123 2013-04-06 20:47:24Z stefan $
2// Copyright (C) 2002, International Business Machines
3// Corporation and others. All Rights Reserved.
4// This code is licensed under the terms of the Eclipse Public License (EPL).
5
6#include <cstdlib>
7#include <cstdio>
8#include <cmath>
9#include <cfloat>
10#include <cassert>
11#include <iostream>
12#define PROBING1000 0
13//#define PRINT_DEBUG
14//#define CGL_DEBUG 1
15//#undef NDEBUG
16#include "CoinPragma.hpp"
17#include "CoinHelperFunctions.hpp"
18#include "CoinPackedVector.hpp"
19#include "CoinPackedMatrix.hpp"
20#include "CoinFinite.hpp"
21#include "OsiRowCutDebugger.hpp"
22#include "CglProbing.hpp"
23//#define PROBING_EXTRA_STUFF true
24#define PROBING_EXTRA_STUFFfalse false
25#define FIXED_ALLOWANCE10 10
26#define SIZE_ROW_MULT4 4
27#define SIZE_ROW_ADD2000 2000
28typedef struct {double infeasibility;int sequence;} double_int_pair;
29class double_int_pair_compare {
30public:
31 bool operator() (double_int_pair x , double_int_pair y) const
32 {
33 return ( x.infeasibility < y.infeasibility);
34 }
35};
36// for hashing
37typedef struct {
38 int index, next;
39} CoinHashLink;
40static double multiplier[] = {1.23456789e2,-9.87654321};
41static int hashCut (const OsiRowCut2 & x, int size)
42{
43 int xN =x.row().getNumElements();
44 double xLb = x.lb();
45 double xUb = x.ub();
46 const int * xIndices = x.row().getIndices();
47 const double * xElements = x.row().getElements();
48 unsigned int hashValue;
49 double value=1.0;
50 if (xLb>-1.0e10)
51 value += xLb*multiplier[0];
52 if (xUb<1.0e10)
53 value += xUb*multiplier[1];
54 for( int j=0;j<xN;j++) {
55 int xColumn = xIndices[j];
56 double xValue = xElements[j];
57 int k=(j&1);
58 value += (j+1)*multiplier[k]*(xColumn+1)*xValue;
59 }
60 // should be compile time but too lazy for now
61 if (sizeof(value)>sizeof(hashValue)) {
62 assert (sizeof(value)==2*sizeof(hashValue))(static_cast<void> (0));
63 union { double d; int i[2]; } xx;
64 xx.d = value;
65 hashValue = (xx.i[0] + xx.i[1]);
66 } else {
67 assert (sizeof(value)==sizeof(hashValue))(static_cast<void> (0));
68 union { double d; unsigned int i[2]; } xx;
69 xx.d = value;
70 hashValue = xx.i[0];
71 }
72 return hashValue%(size);
73}
74static bool same (const OsiRowCut2 & x, const OsiRowCut2 & y)
75{
76 int xN =x.row().getNumElements();
77 int yN =y.row().getNumElements();
78 bool identical=false;
79 if (xN==yN) {
80 double xLb = x.lb();
81 double xUb = x.ub();
82 double yLb = y.lb();
83 double yUb = y.ub();
84 if (fabs(xLb-yLb)<1.0e-8&&fabs(xUb-yUb)<1.0e-8) {
85 const int * xIndices = x.row().getIndices();
86 const double * xElements = x.row().getElements();
87 const int * yIndices = y.row().getIndices();
88 const double * yElements = y.row().getElements();
89 int j;
90 for( j=0;j<xN;j++) {
91 if (xIndices[j]!=yIndices[j])
92 break;
93 if (fabs(xElements[j]-yElements[j])>1.0e-12)
94 break;
95 }
96 identical = (j==xN);
97 }
98 }
99 return identical;
100}
101class row_cut {
102public:
103
104 row_cut(int nRows, bool initialPass )
105 {
106 numberCuts_=0;
107 if (nRows<500) {
108 maxSize_ = SIZE_ROW_MULT4*nRows + SIZE_ROW_ADD2000;
109 } else if (nRows<5000) {
110 maxSize_ = (SIZE_ROW_MULT4*nRows + SIZE_ROW_ADD2000)>>1;
111 } else if (nRows<10000) {
112 maxSize_ = (SIZE_ROW_MULT4*(nRows>>1) + SIZE_ROW_ADD2000)>>1;
113 } else {
114 maxSize_ = (SIZE_ROW_MULT4*CoinMin(nRows,100000) + SIZE_ROW_ADD2000)>>2;
115 }
116 size_ = (maxSize_>>3)+10;
117 if (initialPass)
118 size_ = size_>>1;
119 if (size_<1000)
120 hashSize_=4*size_;
121 else
122 hashSize_=2*size_;
123 nRows_ = nRows;
124 rowCut_ = new OsiRowCut2 * [size_];
125 hash_ = new CoinHashLink[hashSize_];
126 for (int i=0;i<hashSize_;i++) {
127 hash_[i].index=-1;
128 hash_[i].next=-1;
129 }
130 numberCuts_=0;
131 lastHash_=-1;
132 }
133 ~row_cut()
134 {
135 for (int i=0;i<numberCuts_;i++)
136 delete rowCut_[i];
137 delete [] rowCut_;
138 delete [] hash_;
139 }
140 OsiRowCut2 * cut(int i) const
141 { return rowCut_[i];}
142 int numberCuts() const
143 { return numberCuts_;}
144 inline bool outOfSpace() const
145 { return maxSize_==numberCuts_;}
146 OsiRowCut2 ** rowCut_;
147 /// Hash table
148 CoinHashLink *hash_;
149 int size_;
150 int maxSize_;
151 int hashSize_;
152 int nRows_;
153 int numberCuts_;
154 int lastHash_;
155 // Return 0 if added, 1 if not, -1 if not added because of space
156 int addCutIfNotDuplicate(OsiRowCut & cut,int whichRow=-1)
157 {
158 if (numberCuts_==size_&&numberCuts_<maxSize_) {
159 size_ = CoinMin(2*size_+100,maxSize_);
160 if (size_<1000)
161 hashSize_=4*size_;
162 else
163 hashSize_=2*size_;
164#ifdef COIN_DEVELOP
165 printf("increaing size from %d to %d (hash size %d, maxsize %d)\n",
166 numberCuts_,size_,hashSize_,maxSize_);
167#endif
168 OsiRowCut2 ** temp = new OsiRowCut2 * [size_];
169 delete [] hash_;
170 hash_ = new CoinHashLink[hashSize_];
171 for (int i=0;i<hashSize_;i++) {
172 hash_[i].index=-1;
173 hash_[i].next=-1;
174 }
175 for (int i=0;i<numberCuts_;i++) {
176 temp[i]=rowCut_[i];
177 int ipos = hashCut(*temp[i],hashSize_);
178 int found = -1;
179 int jpos=ipos;
180 while ( true ) {
181 int j1 = hash_[ipos].index;
182
183 if ( j1 >= 0 ) {
184 if ( !same(*temp[i],*temp[j1]) ) {
185 int k = hash_[ipos].next;
186 if ( k != -1 )
187 ipos = k;
188 else
189 break;
190 } else {
191 found = j1;
192 break;
193 }
194 } else {
195 break;
196 }
197 }
198 if (found<0) {
199 assert (hash_[ipos].next==-1)(static_cast<void> (0));
200 if (ipos==jpos) {
201 // first
202 hash_[ipos].index=i;
203 } else {
204 // find next space
205 while ( true ) {
206 ++lastHash_;
207 assert (lastHash_<hashSize_)(static_cast<void> (0));
208 if ( hash_[lastHash_].index == -1 )
209 break;
210 }
211 hash_[ipos].next = lastHash_;
212 hash_[lastHash_].index = i;
213 }
214 }
215 }
216 delete [] rowCut_;
217 rowCut_ = temp;
218 }
219 if (numberCuts_<size_) {
220 double newLb = cut.lb();
221 double newUb = cut.ub();
222 CoinPackedVector vector = cut.row();
223 int numberElements =vector.getNumElements();
224 int * newIndices = vector.getIndices();
225 double * newElements = vector.getElements();
226 CoinSort_2(newIndices,newIndices+numberElements,newElements);
227 int i;
228 bool bad=false;
229 for (i=0;i<numberElements;i++) {
230 double value = fabs(newElements[i]);
231 if (value<1.0e-12||value>1.0e12)
232 bad=true;
233 }
234 if (bad)
235 return 1;
236 OsiRowCut2 newCut(whichRow);
237 newCut.setLb(newLb);
238 newCut.setUb(newUb);
239 newCut.setRow(vector);
240 int ipos = hashCut(newCut,hashSize_);
241 int found = -1;
242 int jpos=ipos;
243 while ( true ) {
244 int j1 = hash_[ipos].index;
245
246 if ( j1 >= 0 ) {
247 if ( !same(newCut,*rowCut_[j1]) ) {
248 int k = hash_[ipos].next;
249 if ( k != -1 )
250 ipos = k;
251 else
252 break;
253 } else {
254 found = j1;
255 break;
256 }
257 } else {
258 break;
259 }
260 }
261 if (found<0) {
262 assert (hash_[ipos].next==-1)(static_cast<void> (0));
263 if (ipos==jpos) {
264 // first
265 hash_[ipos].index=numberCuts_;
266 } else {
267 // find next space
268 while ( true ) {
269 ++lastHash_;
270 assert (lastHash_<hashSize_)(static_cast<void> (0));
271 if ( hash_[lastHash_].index == -1 )
272 break;
273 }
274 hash_[ipos].next = lastHash_;
275 hash_[lastHash_].index = numberCuts_;
276 }
277 OsiRowCut2 * newCutPtr = new OsiRowCut2(whichRow);
278 newCutPtr->setLb(newLb);
279 newCutPtr->setUb(newUb);
280 newCutPtr->setRow(vector);
281 rowCut_[numberCuts_++]=newCutPtr;
282 return 0;
283 } else {
284 return 1;
285 }
286 } else {
287 return -1;
288 }
289 }
290 void addCuts(OsiCuts & cs, OsiRowCut ** whichRow,int iPass)
291 {
292 int numberCuts=cs.sizeRowCuts();
293 int i ;
294 if (numberCuts_<nRows_) {
295 if ((iPass&1)==1) {
296 for (i=0;i<numberCuts_;i++) {
297 cs.insert(*rowCut_[i]);
298 if (whichRow) {
299 int iRow= rowCut_[i]->whichRow();
300 if (iRow>=0&&!whichRow[iRow])
301 whichRow[iRow]=cs.rowCutPtr(numberCuts);;
302 }
303 numberCuts++;
304 }
305 } else {
306 for (i=numberCuts_-1;i>=0;i--) {
307 cs.insert(*rowCut_[i]);
308 if (whichRow) {
309 int iRow= rowCut_[i]->whichRow();
310 if (iRow>=0&&!whichRow[iRow])
311 whichRow[iRow]=cs.rowCutPtr(numberCuts);;
312 }
313 numberCuts++;
314 }
315 }
316 } else {
317 // just best
318 double * effectiveness = new double[numberCuts_];
319 int iCut=0;
320 for (i=0;i<numberCuts_;i++) {
321 double value = -rowCut_[i]->effectiveness();
322 if (whichRow) {
323 int iRow= rowCut_[i]->whichRow();
324 if (iRow>=0)
325 value -= 1.0e10;
326 }
327 effectiveness[iCut++]=value;
328 }
329 std::sort(effectiveness,effectiveness+numberCuts_);
330 double threshold = -1.0e20;
331 if (iCut>nRows_)
332 threshold = effectiveness[nRows_];
333 for ( i=0;i<numberCuts_;i++) {
334 if (rowCut_[i]->effectiveness()>threshold) {
335 cs.insert(*rowCut_[i]);
336 if (whichRow) {
337 int iRow= rowCut_[i]->whichRow();
338 if (iRow>=0&&!whichRow[iRow])
339 whichRow[iRow]=cs.rowCutPtr(numberCuts);;
340 }
341 numberCuts++;
342 }
343 }
344 delete[] effectiveness ;
345 }
346 for (i = 0 ; i < numberCuts_ ; i++)
347 { delete rowCut_[i] ;
348 rowCut_[i] = 0 ; }
349 numberCuts_=0;
350 }
351};
352// Adds in cut to list
353#ifdef CGL_DEBUG
354// Checks bounds okay against debugger
355static void checkBounds(const OsiRowCutDebugger * debugger,OsiColCut & cut)
356{
357 if (debugger) {
358 // on optimal path
359 const double * optimal = debugger->optimalSolution();
360 int i;
361 int nIndex;
362 const double * values;
363 const int * index;
364 const CoinPackedVector & lbs = cut.lbs();
365 values = lbs.getElements();
366 nIndex = lbs.getNumElements();
367 index = lbs.getIndices();
368 for (i=0;i<nIndex;i++) {
369 double value=values[i];
370 int iColumn = index[i];
371 printf("%d optimal %g lower %g\n",iColumn,optimal[iColumn],value);
372 assert(value<=optimal[iColumn]+1.0e-5)(static_cast<void> (0));
373 }
374 const CoinPackedVector & ubs = cut.ubs();
375 values = ubs.getElements();
376 nIndex = ubs.getNumElements();
377 index = ubs.getIndices();
378 for (i=0;i<nIndex;i++) {
379 double value=values[i];
380 int iColumn = index[i];
381 printf("%d optimal %g upper %g\n",iColumn,optimal[iColumn],value);
382 assert(value>=optimal[iColumn]-1.0e-5)(static_cast<void> (0));
383 }
384 }
385}
386#endif
387#define CGL_REASONABLE_INTEGER_BOUND1.23456789e10 1.23456789e10
388// This tightens column bounds (and can declare infeasibility)
389// It may also declare rows to be redundant
390int
391CglProbing::tighten(double *colLower, double * colUpper,
392 const int *column, const double *rowElements,
393 const CoinBigIndex *rowStart,
394 const CoinBigIndex * rowStartPos,const int * rowLength,
395 double *rowLower, double *rowUpper,
396 int nRows,int nCols,char * intVar,int maxpass,
397 double tolerance)
398{
399 int i, j, k, kre;
400 int krs;
401 int dolrows;
402 int iflagu, iflagl;
403 int ntotal=0,nchange=1,jpass=0;
404 double dmaxup, dmaxdown, dbound;
405 int ninfeas=0;
406 // For clique stuff
407 double * cliqueMin=NULL__null;
408 double * cliqueMax=NULL__null;
409 // And second best ones
410 double * cliqueMin2 = NULL__null;
411 double * cliqueMax2 = NULL__null;
412 if (cliqueRowStart_&&numberRows_&&cliqueRowStart_[numberRows_]) {
413 cliqueMin = new double[nCols];
414 cliqueMax = new double[nCols];
415 cliqueMin2 = new double[nCols];
416 cliqueMax2 = new double[nCols];
417 } else {
418 // do without cliques and using sorted version
419 assert (rowStartPos)(static_cast<void> (0));
420 while(nchange) {
421 nchange = 0;
422 if (jpass==maxpass) break;
423 jpass++;
424 dolrows = (jpass & 1) == 1;
425
426 for (i = 0; i < nRows; ++i) {
427 if (rowLower[i]>-1.0e20||rowUpper[i]<1.0e20) {
428 int iflagu = 0;
429 int iflagl = 0;
430 double dmaxup = 0.0;
431 double dmaxdown = 0.0;
432 int krs = rowStart[i];
433 int krs2 = rowStartPos[i];
434 int kre = rowStart[i]+rowLength[i];
435
436 /* ------------------------------------------------------------*/
437 /* Compute L(i) and U(i) */
438 /* ------------------------------------------------------------*/
439 for (k = krs; k < krs2; ++k) {
440 double value=rowElements[k];
441 int j = column[k];
442 if (colUpper[j] < 1.0e12)
443 dmaxdown += colUpper[j] * value;
444 else
445 ++iflagl;
446 if (colLower[j] > -1.0e12)
447 dmaxup += colLower[j] * value;
448 else
449 ++iflagu;
450 }
451 for (k = krs2; k < kre; ++k) {
452 double value=rowElements[k];
453 int j = column[k];
454 if (colUpper[j] < 1.0e12)
455 dmaxup += colUpper[j] * value;
456 else
457 ++iflagu;
458 if (colLower[j] > -1.0e12)
459 dmaxdown += colLower[j] * value;
460 else
461 ++iflagl;
462 }
463 if (iflagu)
464 dmaxup=1.0e31;
465 if (iflagl)
466 dmaxdown=-1.0e31;
467 if (dmaxup <= rowUpper[i] + tolerance && dmaxdown >= rowLower[i] - tolerance) {
468 /*
469 * The sum of the column maxs is at most the row ub, and
470 * the sum of the column mins is at least the row lb;
471 * this row says nothing at all.
472 * I suspect that this corresponds to
473 * an implied column singleton in the paper (viii, on p. 325),
474 * where the singleton in question is the row slack.
475 */
476 ++nchange;
477 rowLower[i]=-COIN_DBL_MAX;
478 rowUpper[i]=COIN_DBL_MAX;
479 } else {
480 if (dmaxup < rowLower[i] -tolerance || dmaxdown > rowUpper[i]+tolerance) {
481 ninfeas++;
482 break;
483 }
484 /* Finite U(i) */
485 /* -------------------------------------------------------------*/
486 /* below is deliberate mistake (previously was by chance) */
487 /* never do both */
488 if (iflagu == 0 && rowLower[i] > 0.0 && iflagl == 0 && rowUpper[i] < 1e15) {
489 if (dolrows) {
490 iflagu = 1;
491 } else {
492 iflagl = 1;
493 }
494 }
495 if (iflagu == 0 && rowLower[i] > -1e15) {
496 for (k = krs; k < kre; ++k) {
497 double value=rowElements[k];
498 j = column[k];
499 if (value > 0.0) {
500 if (colUpper[j] < 1.0e12) {
501 dbound = colUpper[j] + (rowLower[i] - dmaxup) / value;
502 if (dbound > colLower[j] + 1.0e-8) {
503 /* we can tighten the lower bound */
504 /* the paper mentions this as a possibility on p. 227 */
505 colLower[j] = dbound;
506 ++nchange;
507
508 /* this may have fixed the variable */
509 /* I believe that this roughly corresponds to a
510 * forcing constraint in the paper (p. 226).
511 * If there is a forcing constraint (with respect
512 * to the original, untightened bounds), then in this
513 * loop we will go through all the columns and fix
514 * each of them to their implied bound, rather than
515 * determining that the row as a whole is forced
516 * and just fixing them without doing computation for
517 * each column (as in the paper).
518 * By doing it this way, we can tighten bounds and
519 * get forcing constraints for free.
520 */
521 if (colUpper[j] - colLower[j] <= tolerance) {
522 /* --------------------------------------------------*/
523 /* check if infeasible !!!!! */
524 /* --------------------------------------------------*/
525 if (colUpper[j] - colLower[j] < -100.0*tolerance) {
526 ninfeas++;
527 }
528 }
529 }
530 }
531 } else {
532 if (colLower[j] > -1.0e12) {
533 dbound = colLower[j] + (rowLower[i] - dmaxup) / value;
534 if (dbound < colUpper[j] - 1.0e-8) {
535 colUpper[j] = dbound;
536 ++nchange;
537 if (colUpper[j] - colLower[j] <= tolerance) {
538 /* --------------------------------------------------*/
539 /* check if infeasible !!!!! */
540 /* --------------------------------------------------*/
541 if (colUpper[j] - colLower[j] < -100.0*tolerance) {
542 ninfeas++;
543 }
544 }
545 }
546 }
547 }
548 }
549 }
550
551 /* ----------------------------------------------------------------*/
552 /* Finite L(i) */
553 /* ----------------------------------------------------------------*/
554 if (iflagl == 0 && rowUpper[i] < 1e15) {
555 for (k = krs; k < kre; ++k) {
556 double value=rowElements[k];
557 j = column[k];
558 if (value < 0.0) {
559 if (colUpper[j] < 1.0e12) {
560 dbound = colUpper[j] + (rowUpper[i] - dmaxdown) / value;
561 if (dbound > colLower[j] + 1.0e-8) {
562 colLower[j] = dbound;
563 ++nchange;
564 if (! (colUpper[j] - colLower[j] > tolerance)) {
565 /* --------------------------------------------------*/
566 /* check if infeasible !!!!! */
567 /* --------------------------------------------------*/
568 if (colUpper[j] - colLower[j] < -100.0*tolerance) {
569 ninfeas++;
570 }
571 }
572 }
573 }
574 } else {
575 if (colLower[j] > -1.0e12) {
576 dbound = colLower[j] + (rowUpper[i] - dmaxdown) / value;
577 if (dbound < colUpper[j] - 1.0e-8) {
578 colUpper[j] = dbound;
579 ++nchange;
580 if (! (colUpper[j] - colLower[j] > tolerance)) {
581 /* --------------------------------------------------*/
582 /* check if infeasible !!!!! */
583 /* --------------------------------------------------*/
584 if (colUpper[j] - colLower[j] < -100.0*tolerance) {
585 ninfeas++;
586 }
587 }
588 }
589 }
590 }
591 }
592 }
593 }
594 }
595 }
596 for (j = 0; j < nCols; ++j) {
597 if (intVar[j]) {
598 if (colUpper[j]-colLower[j]>1.0e-8) {
599 if (floor(colUpper[j]+1.0e-4)<colUpper[j])
600 nchange++;
601 // clean up anyway
602 colUpper[j]=floor(colUpper[j]+1.0e-4);
603 if (ceil(colLower[j]-1.0e-4)>colLower[j])
604 nchange++;
605 // clean up anyway
606 colLower[j]=ceil(colLower[j]-1.0e-4);
607 if (colUpper[j]<colLower[j]) {
608 /*printf("infeasible\n");*/
609 ninfeas++;
610 }
611 }
612 }
613 }
614 if (ninfeas) break;
615 }
616 return (ninfeas);
617 }
618
619 while(nchange) {
620 int ilbred = 0; /* bounds reduced */
621 int iubred = 0; /* bounds reduced */
622 int nrwdrp = 0; /* redundant rows */
623 if (jpass==maxpass) break;
624 jpass++;
625 dolrows = (jpass & 1) == 1;
626
627 for (i = 0; i < nRows; ++i) {
628 bool cliqueChanges=false;
629 if (rowLower[i]>-1.0e20||rowUpper[i]<1.0e20) {
630 iflagu = 0;
631 iflagl = 0;
632 dmaxup = 0.0;
633 dmaxdown = 0.0;
634 krs = rowStart[i];
635 kre = rowStart[i]+rowLength[i];
636
637 /* ------------------------------------------------------------*/
638 /* Compute L(i) and U(i) */
639 /* ------------------------------------------------------------*/
640 if (!cliqueMin||i>=numberRows_||cliqueRowStart_[i]==cliqueRowStart_[i+1]) {
641 // without cliques
642 for (k = krs; k < kre; ++k) {
643 double value=rowElements[k];
644 j = column[k];
645 if (value > 0.0) {
646 if (colUpper[j] < 1.0e12)
647 dmaxup += colUpper[j] * value;
648 else
649 ++iflagu;
650 if (colLower[j] > -1.0e12)
651 dmaxdown += colLower[j] * value;
652 else
653 ++iflagl;
654 } else if (value<0.0) {
655 if (colUpper[j] < 1.0e12)
656 dmaxdown += colUpper[j] * value;
657 else
658 ++iflagl;
659 if (colLower[j] > -1.0e12)
660 dmaxup += colLower[j] * value;
661 else
662 ++iflagu;
663 }
664 }
665 if (iflagu)
666 dmaxup=1.0e31;
667 if (iflagl)
668 dmaxdown=-1.0e31;
669 } else {
670 // with cliques
671 int nClique=0;
672 int bias = cliqueRowStart_[i]-krs;
673 double dmaxup2=0.0;
674 double dmaxdown2=0.0;
675 double sumZeroFixes=0.0;
676 for (k = krs; k < kre; ++k) {
677 double value=rowElements[k];
678 j = column[k];
679 int iClique = sequenceInCliqueEntry(cliqueRow_[k+bias]);
680 bool oneFixes = oneFixesInCliqueEntry(cliqueRow_[k+bias]);
681 if (iClique>=numberColumns_||colUpper[j]==colLower[j]) {
682 if (value > 0.0) {
683 if (colUpper[j] >= 1.0e12) {
684 dmaxup = 1e31;
685 ++iflagu;
686 } else {
687 dmaxup += colUpper[j] * value;
688 }
689 if (colLower[j] <= -1.0e12) {
690 dmaxdown = -1e31;
691 ++iflagl;
692 } else {
693 dmaxdown += colLower[j] * value;
694 }
695 } else if (value<0.0) {
696 if (colUpper[j] >= 1.0e12) {
697 dmaxdown = -1e31;
698 ++iflagl;
699 } else {
700 dmaxdown += colUpper[j] * value;
701 }
702 if (colLower[j] <= -1.0e12) {
703 dmaxup = 1e31;
704 ++iflagu;
705 } else {
706 dmaxup += colLower[j] * value;
707 }
708 }
709 } else {
710 // clique may help
711 if (iClique>=nClique) {
712 //zero out
713 for (int j=nClique;j<=iClique;j++) {
714 cliqueMin[j]=0.0;
715 cliqueMax[j]=0.0;
716 cliqueMin2[j]=0.0;
717 cliqueMax2[j]=0.0;
718 }
719 nClique=iClique+1;
720 }
721 // Update best and second best
722 if (oneFixes) {
723 if (value > 0.0) {
724 dmaxup2 += value;
725 cliqueMax2[iClique] = cliqueMax[iClique];
726 cliqueMax[iClique] = CoinMax(cliqueMax[iClique],value);
727 } else if (value<0.0) {
728 dmaxdown2 += value;
729 cliqueMin2[iClique] = cliqueMin[iClique];
730 cliqueMin[iClique] = CoinMin(cliqueMin[iClique],value);
731 }
732 } else {
733 sumZeroFixes += value;
734 if (value > 0.0) {
735 dmaxup2 += value;
736 cliqueMin2[iClique] = cliqueMin[iClique];
737 cliqueMin[iClique] = CoinMin(cliqueMin[iClique],-value);
738 } else if (value<0.0) {
739 dmaxdown2 += value;
740 cliqueMax2[iClique] = cliqueMax[iClique];
741 cliqueMax[iClique] = CoinMax(cliqueMax[iClique],-value);
742 }
743 }
744 }
745 }
746 double dmaxup3 = dmaxup + sumZeroFixes;
747 double dmaxdown3 = dmaxdown + sumZeroFixes;
748 for (int iClique=0;iClique<nClique;iClique++) {
749 dmaxup3 += cliqueMax[iClique];
750 dmaxdown3 += cliqueMin[iClique];
751 }
752 dmaxup += dmaxup2;
753 dmaxdown += dmaxdown2;
754 assert (dmaxup3<=dmaxup+1.0e-8)(static_cast<void> (0));
755 assert (dmaxdown3>=dmaxdown-1.0e-8)(static_cast<void> (0));
756 if (dmaxup3<dmaxup-1.0e-8||dmaxdown3>dmaxdown+1.0e-8) {
757 cliqueChanges=true;
758 //printf("normal min/max %g , %g clique %g , %g\n",
759 // dmaxdown,dmaxup,dmaxdown3,dmaxup3);
760 dmaxdown=dmaxdown3;
761 dmaxup=dmaxup3;
762 }
763 }
764 if (dmaxup <= rowUpper[i] + tolerance && dmaxdown >= rowLower[i] - tolerance) {
765 /*
766 * The sum of the column maxs is at most the row ub, and
767 * the sum of the column mins is at least the row lb;
768 * this row says nothing at all.
769 * I suspect that this corresponds to
770 * an implied column singleton in the paper (viii, on p. 325),
771 * where the singleton in question is the row slack.
772 */
773 ++nrwdrp;
774 rowLower[i]=-COIN_DBL_MAX;
775 rowUpper[i]=COIN_DBL_MAX;
776 } else {
777 if (dmaxup < rowLower[i] -tolerance || dmaxdown > rowUpper[i]+tolerance) {
778 ninfeas++;
779 assert (!cliqueChanges)(static_cast<void> (0));
780 break;
781 }
782 /* Finite U(i) */
783 /* -------------------------------------------------------------*/
784 /* below is deliberate mistake (previously was by chance) */
785 /* never do both */
786 if (iflagu == 0 && rowLower[i] > 0.0 && iflagl == 0 && rowUpper[i] < 1e15) {
787 if (dolrows) {
788 iflagu = 1;
789 } else {
790 iflagl = 1;
791 }
792 }
793 if (!cliqueChanges) {
794 // without cliques
795 if (iflagu == 0 && rowLower[i] > -1e15) {
796 for (k = krs; k < kre; ++k) {
797 double value=rowElements[k];
798 j = column[k];
799 if (value > 0.0) {
800 if (colUpper[j] < 1.0e12) {
801 dbound = colUpper[j] + (rowLower[i] - dmaxup) / value;
802 if (dbound > colLower[j] + 1.0e-8) {
803 /* we can tighten the lower bound */
804 /* the paper mentions this as a possibility on p. 227 */
805 colLower[j] = dbound;
806 ++ilbred;
807
808 /* this may have fixed the variable */
809 /* I believe that this roughly corresponds to a
810 * forcing constraint in the paper (p. 226).
811 * If there is a forcing constraint (with respect
812 * to the original, untightened bounds), then in this
813 * loop we will go through all the columns and fix
814 * each of them to their implied bound, rather than
815 * determining that the row as a whole is forced
816 * and just fixing them without doing computation for
817 * each column (as in the paper).
818 * By doing it this way, we can tighten bounds and
819 * get forcing constraints for free.
820 */
821 if (colUpper[j] - colLower[j] <= tolerance) {
822 /* --------------------------------------------------*/
823 /* check if infeasible !!!!! */
824 /* --------------------------------------------------*/
825 if (colUpper[j] - colLower[j] < -100.0*tolerance) {
826 ninfeas++;
827 }
828 }
829 }
830 }
831 } else {
832 if (colLower[j] > -1.0e12) {
833 dbound = colLower[j] + (rowLower[i] - dmaxup) / value;
834 if (dbound < colUpper[j] - 1.0e-8) {
835 colUpper[j] = dbound;
836 ++iubred;
837 if (colUpper[j] - colLower[j] <= tolerance) {
838 /* --------------------------------------------------*/
839 /* check if infeasible !!!!! */
840 /* --------------------------------------------------*/
841 if (colUpper[j] - colLower[j] < -100.0*tolerance) {
842 ninfeas++;
843 }
844 }
845 }
846 }
847 }
848 }
849 }
850
851 /* ----------------------------------------------------------------*/
852 /* Finite L(i) */
853 /* ----------------------------------------------------------------*/
854 if (iflagl == 0 && rowUpper[i] < 1e15) {
855 for (k = krs; k < kre; ++k) {
856 double value=rowElements[k];
857 j = column[k];
858 if (value < 0.0) {
859 if (colUpper[j] < 1.0e12) {
860 dbound = colUpper[j] + (rowUpper[i] - dmaxdown) / value;
861 if (dbound > colLower[j] + 1.0e-8) {
862 colLower[j] = dbound;
863 ++ilbred;
864 if (! (colUpper[j] - colLower[j] > tolerance)) {
865 /* --------------------------------------------------*/
866 /* check if infeasible !!!!! */
867 /* --------------------------------------------------*/
868 if (colUpper[j] - colLower[j] < -100.0*tolerance) {
869 ninfeas++;
870 }
871 }
872 }
873 }
874 } else {
875 if (colLower[j] > -1.0e12) {
876 dbound = colLower[j] + (rowUpper[i] - dmaxdown) / value;
877 if (dbound < colUpper[j] - 1.0e-8) {
878 colUpper[j] = dbound;
879 ++iubred;
880 if (! (colUpper[j] - colLower[j] > tolerance)) {
881 /* --------------------------------------------------*/
882 /* check if infeasible !!!!! */
883 /* --------------------------------------------------*/
884 if (colUpper[j] - colLower[j] < -100.0*tolerance) {
885 ninfeas++;
886 }
887 }
888 }
889 }
890 }
891 }
892 }
893 } else {
894 // with cliques
895 int bias = cliqueRowStart_[i]-krs;
896 if (iflagu == 0 && rowLower[i] > -1e15) {
897 for (k = krs; k < kre; ++k) {
898 double value=rowElements[k];
899 j = column[k];
900 int iClique = sequenceInCliqueEntry(cliqueRow_[k+bias]);
901 //bool oneFixes = (cliqueRow_[k+bias].oneFixes!=0);
902 if (iClique>=numberColumns_) {
903 if (value > 0.0) {
904 if (colUpper[j] < 1.0e12) {
905 dbound = colUpper[j] + (rowLower[i] - dmaxup) / value;
906 if (dbound > colLower[j] + 1.0e-8) {
907 /* we can tighten the lower bound */
908 /* the paper mentions this as a possibility on p. 227 */
909 colLower[j] = dbound;
910 ++ilbred;
911
912 /* this may have fixed the variable */
913 /* I believe that this roughly corresponds to a
914 * forcing constraint in the paper (p. 226).
915 * If there is a forcing constraint (with respect
916 * to the original, untightened bounds), then in this
917 * loop we will go through all the columns and fix
918 * each of them to their implied bound, rather than
919 * determining that the row as a whole is forced
920 * and just fixing them without doing computation for
921 * each column (as in the paper).
922 * By doing it this way, we can tighten bounds and
923 * get forcing constraints for free.
924 */
925 if (colUpper[j] - colLower[j] <= tolerance) {
926 /* --------------------------------------------------*/
927 /* check if infeasible !!!!! */
928 /* --------------------------------------------------*/
929 if (colUpper[j] - colLower[j] < -100.0*tolerance) {
930 ninfeas++;
931 }
932 }
933#if 0
934 } else if (intVar[j]==1 && rowUpper[i]>1.0e20) {
935 // can we modify coefficient
936 if (dmaxdown+value>rowLower[i]+1.0e-8) {
937 assert (dmaxdown<rowLower[i]+1.0e-8)(static_cast<void> (0));
938 double change = dmaxdown+value - rowLower[i];
939 double newValue = value - change;
940 if (newValue<1.0e-12)
941 newValue=0.0;
942 printf("Could change value from %g to %g\n",
943 value,newValue);
944 // dmaxup -= change;
945 }
946#endif
947 }
948 }
949 } else {
950 if (colLower[j] > -1.0e12) {
951 dbound = colLower[j] + (rowLower[i] - dmaxup) / value;
952 if (dbound < colUpper[j] - 1.0e-8) {
953 colUpper[j] = dbound;
954 ++iubred;
955 if (colUpper[j] - colLower[j] <= tolerance) {
956 /* --------------------------------------------------*/
957 /* check if infeasible !!!!! */
958 /* --------------------------------------------------*/
959 if (colUpper[j] - colLower[j] < -100.0*tolerance) {
960 ninfeas++;
961 }
962 }
963#if 0
964 } else if (intVar[j]==1 && rowUpper[i]>1.0e20) {
965 // can we modify coefficient
966 if (dmaxdown-value>rowLower[i]+1.0e-8) {
967 assert (dmaxdown<rowLower[i]+1.0e-8)(static_cast<void> (0));
968 double change = dmaxdown-value-rowLower[i];
969 double newValue = value+change;
970 double newLower = rowLower[i]+change;
971 if (newValue<1.0e-12)
972 newValue=0.0;
973 printf("Could change value from %g to %g and lorow from %g to %g\n",
974 value,newValue,rowLower[i],newLower);
975 // dmaxdown += change
976 }
977#endif
978 }
979 }
980 }
981 } else if (colUpper[j]>colLower[j]) {
982 // in clique
983 // adjustment
984 double dmaxup2=dmaxup;
985 assert (cliqueMax[iClique]>=0)(static_cast<void> (0));
986 assert (cliqueMax2[iClique]>=0)(static_cast<void> (0));
987 /* get max up if at other bound
988 May not go down at all but will not go up */
989 if (fabs(value)==fabs(cliqueMax[iClique]))
990 dmaxup2 -= cliqueMax[iClique]-cliqueMax2[iClique];
991 if (dmaxup2<rowLower[i]-1.0e-8) {
992 /* --------------------------------------------------*/
993 /* check if infeasible !!!!! */
994 /* --------------------------------------------------*/
995 if ( dmaxup<rowLower[i]-1.0e-8) {
996 ninfeas++;
997 } else {
998 if (value > 0.0) {
999 colLower[j] = 1.0;
1000 ++ilbred;
1001 } else {
1002 colUpper[j] = 0.0;
1003 ++iubred;
1004 }
1005 }
1006 }
1007 }
1008 }
1009 }
1010
1011 /* ----------------------------------------------------------------*/
1012 /* Finite L(i) */
1013 /* ----------------------------------------------------------------*/
1014 if (iflagl == 0 && rowUpper[i] < 1e15) {
1015 for (k = krs; k < kre; ++k) {
1016 double value=rowElements[k];
1017 j = column[k];
1018 int iClique = sequenceInCliqueEntry(cliqueRow_[k+bias]);
1019 //bool oneFixes = (cliqueRow_[k+bias].oneFixes!=0);
1020 if (iClique>=numberColumns_) {
1021 if (value < 0.0) {
1022 if (colUpper[j] < 1.0e12) {
1023 dbound = colUpper[j] + (rowUpper[i] - dmaxdown) / value;
1024 if (dbound > colLower[j] + 1.0e-8) {
1025 colLower[j] = dbound;
1026 ++ilbred;
1027 if (! (colUpper[j] - colLower[j] > tolerance)) {
1028 /* --------------------------------------------------*/
1029 /* check if infeasible !!!!! */
1030 /* --------------------------------------------------*/
1031 if (colUpper[j] - colLower[j] < -100.0*tolerance) {
1032 ninfeas++;
1033 }
1034 }
1035#if 0
1036 } else if (intVar[j]==1 && rowLower[i]<-1.0e20) {
1037 // can we modify coefficient
1038 if (dmaxup+value<rowUpper[i]-1.0e-8) {
1039 assert (dmaxup>rowUpper[i]-1.0e-8)(static_cast<void> (0));
1040 double change = dmaxup+value - rowUpper[i];
1041 double newValue = value - change;
1042 if (newValue<1.0e-12)
1043 newValue=0.0;
1044 printf("Could change value from %g to %g b\n",
1045 value,newValue);
1046 // dmaxdown -= change;
1047 }
1048#endif
1049 }
1050 }
1051 } else {
1052 if (colLower[j] > -1.0e12) {
1053 dbound = colLower[j] + (rowUpper[i] - dmaxdown) / value;
1054 if (dbound < colUpper[j] - 1.0e-8) {
1055 colUpper[j] = dbound;
1056 ++iubred;
1057 if (! (colUpper[j] - colLower[j] > tolerance)) {
1058 /* --------------------------------------------------*/
1059 /* check if infeasible !!!!! */
1060 /* --------------------------------------------------*/
1061 if (colUpper[j] - colLower[j] < -100.0*tolerance) {
1062 ninfeas++;
1063 }
1064 }
1065#if 0
1066 } else if (intVar[j]==1 && rowLower[i]<-1.0e20) {
1067 // can we modify coefficient
1068 if (dmaxup-value<rowUpper[i]-1.0e-8) {
1069 assert (dmaxup>rowUpper[i]-1.0e-8)(static_cast<void> (0));
1070 double change = dmaxup-value-rowUpper[i];
1071 double newValue = value+change;
1072 double newUpper = rowUpper[i]+change;
1073 if (newValue<1.0e-12)
1074 newValue=0.0;
1075 printf("Could change value from %g to %g and uprow from %g to %g b\n",
1076 value,newValue,rowLower[i],newUpper);
1077 // dmaxup += change
1078 }
1079#endif
1080 }
1081 }
1082 }
1083 } else if (colUpper[j]>colLower[j]) {
1084 // in clique
1085 // adjustment
1086 double dmaxdown2=dmaxdown;
1087 assert (cliqueMin[iClique]<=0)(static_cast<void> (0));
1088 assert (cliqueMin2[iClique]<=0)(static_cast<void> (0));
1089 /* get max down if this is at other bound
1090 May not go up at all but will not go down */
1091 if (fabs(value)==fabs(cliqueMin[iClique]))
1092 dmaxdown2 -= cliqueMin[iClique]-cliqueMin2[iClique];
1093 if (dmaxdown2>rowUpper[i]+1.0e-8) {
1094 /* --------------------------------------------------*/
1095 /* check if infeasible !!!!! */
1096 /* --------------------------------------------------*/
1097 if ( dmaxdown>rowUpper[i]+1.0e-8) {
1098 ninfeas++;
1099 } else {
1100 if (value < 0.0) {
1101 colLower[j] = 1.0;
1102 ++ilbred;
1103 } else {
1104 colUpper[j] = 0.0;
1105 ++iubred;
1106 }
1107 }
1108 }
1109 }
1110 }
1111 }
1112 }
1113 }
1114 }
1115 }
1116 for (j = 0; j < nCols; ++j) {
1117 if (intVar[j]) {
1118 if (colUpper[j]-colLower[j]>1.0e-8) {
1119 if (floor(colUpper[j]+1.0e-4)<colUpper[j])
1120 nchange++;
1121 // clean up anyway
1122 colUpper[j]=floor(colUpper[j]+1.0e-4);
1123 if (ceil(colLower[j]-1.0e-4)>colLower[j])
1124 nchange++;
1125 // clean up anyway
1126 colLower[j]=ceil(colLower[j]-1.0e-4);
1127 if (colUpper[j]<colLower[j]) {
1128 /*printf("infeasible\n");*/
1129 ninfeas++;
1130 }
1131 }
1132 }
1133 }
1134 nchange=ilbred+iubred+nrwdrp;
1135 ntotal += nchange;
1136 if (ninfeas) break;
1137 }
1138 delete [] cliqueMin;
1139 delete [] cliqueMax;
1140 delete [] cliqueMin2;
1141 delete [] cliqueMax2;
1142 return (ninfeas);
1143}
1144// This just sets minima and maxima on rows
1145void
1146CglProbing::tighten2(double *colLower, double * colUpper,
1147 const int *column, const double *rowElements,
1148 const CoinBigIndex *rowStart,
1149 const int * rowLength,
1150 double *rowLower, double *rowUpper,
1151 double * minR, double * maxR, int * markR,
1152 int nRows)
1153{
1154 int i, j, k, kre;
1155 int krs;
1156 int iflagu, iflagl;
1157 double dmaxup, dmaxdown;
1158
1159 for (i = 0; i < nRows; ++i) {
1160 if (rowLower[i]>-1.0e20||rowUpper[i]<1.0e20) {
1161 iflagu = 0;
1162 iflagl = 0;
1163 dmaxup = 0.0;
1164 dmaxdown = 0.0;
1165 krs = rowStart[i];
1166 kre = rowStart[i]+rowLength[i];
1167
1168 /* ------------------------------------------------------------*/
1169 /* Compute L(i) and U(i) */
1170 /* ------------------------------------------------------------*/
1171 for (k = krs; k < kre; ++k) {
1172 double value=rowElements[k];
1173 j = column[k];
1174 if (value > 0.0) {
1175 if (colUpper[j] < 1.0e12)
1176 dmaxup += colUpper[j] * value;
1177 else
1178 ++iflagu;
1179 if (colLower[j] > -1.0e12)
1180 dmaxdown += colLower[j] * value;
1181 else
1182 ++iflagl;
1183 } else if (value<0.0) {
1184 if (colUpper[j] < 1.0e12)
1185 dmaxdown += colUpper[j] * value;
1186 else
1187 ++iflagl;
1188 if (colLower[j] > -1.0e12)
1189 dmaxup += colLower[j] * value;
1190 else
1191 ++iflagu;
1192 }
1193 }
1194 if (iflagu)
1195 maxR[i]=1.0e60;
1196 else
1197 maxR[i]=dmaxup;
1198 if (iflagl)
1199 minR[i]=-1.0e60;
1200 else
1201 minR[i]=dmaxdown;
1202#if 0
1203 if (minR[i]<-1.0e10&&maxR[i]>1.0e10) {
1204 markR[i]=-2;
1205 } else {
1206#endif
1207 markR[i]=-1;
1208#if 0
1209 }
1210#endif
1211 } else {
1212 minR[i]=-1.0e60;
1213 maxR[i]=1.0e60;
1214#if 0
1215 markR[i]=-2;
1216 abort();
1217#else
1218 markR[i]=-1;
1219#endif
1220 }
1221 }
1222}
1223#ifdef CGL_DEBUG
1224static int nPath=0;
1225#endif
1226//-------------------------------------------------------------------
1227// Generate disaggregation cuts
1228//-------------------------------------------------------------------
1229void CglProbing::generateCuts(const OsiSolverInterface & si, OsiCuts & cs,
1230 const CglTreeInfo info2)
1231{
1232
1233#ifdef CGL_DEBUG
1234 const OsiRowCutDebugger * debugger = si.getRowCutDebugger();
1235 if (debugger&&debugger->onOptimalPath(si)) {
1236 printf("On optimal path %d\n",nPath);
1237 nPath++;
1238 int nCols=si.getNumCols();
1239 int i;
1240 const double * solution = si.getColSolution();
1241 const double * lower = si.getColLower();
1242 const double * upper = si.getColUpper();
1243 const double * optimal = debugger->optimalSolution();
1244 const double * objective = si.getObjCoefficients();
1245 double objval1=0.0,objval2=0.0;
1246 for (i=0;i<nCols;i++) {
1247#if CGL_DEBUG>1
1248 printf("%d %g %g %g %g\n",i,lower[i],solution[i],upper[i],optimal[i]);
1249#endif
1250 objval1 += solution[i]*objective[i];
1251 objval2 += optimal[i]*objective[i];
1252 assert(optimal[i]>=lower[i]&&optimal[i]<=upper[i])(static_cast<void> (0));
1253 }
1254 printf("current obj %g, integer %g\n",objval1,objval2);
1255 }
1256#endif
1257 int saveRowCuts=rowCuts_;
1258 if (rowCuts_<0) {
1259 if (info2.inTree)
1260 rowCuts_=4;
1261 else
1262 rowCuts_=-rowCuts_;
1263 }
1264 int nRows=si.getNumRows();
1265 double * rowLower = new double[nRows+1];
1266 double * rowUpper = new double[nRows+1];
1267
1268 int nCols=si.getNumCols();
1269 // Set size if not set
1270 if (!rowCopy_) {
1271 numberRows_=nRows;
1272 numberColumns_=nCols;
1273 }
1274 double * colLower = new double[nCols];
1275 double * colUpper = new double[nCols];
1276
1277 CglTreeInfo info = info2;
1278 int ninfeas=gutsOfGenerateCuts(si,cs,rowLower,rowUpper,colLower,colUpper,&info);
1279 if (ninfeas) {
1280 // generate infeasible cut and return
1281 OsiRowCut rc;
1282 rc.setLb(COIN_DBL_MAX);
1283 rc.setUb(0.0);
1284 cs.insert(rc);
1285#ifdef CGL_DEBUG
1286 const OsiRowCutDebugger * debugger = si.getRowCutDebugger();
1287 if (debugger&&debugger->onOptimalPath(si))
1288 assert(!debugger->invalidCut(rc))(static_cast<void> (0));
1289#endif
1290 }
1291 delete [] rowLower;
1292 delete [] rowUpper;
1293 delete [] colLower;
1294 delete [] colUpper;
1295 delete [] colLower_;
1296 delete [] colUpper_;
1297 colLower_ = NULL__null;
1298 colUpper_ = NULL__null;
1299 rowCuts_=saveRowCuts;
1300}
1301int CglProbing::generateCutsAndModify(const OsiSolverInterface & si,
1302 OsiCuts & cs,
1303 CglTreeInfo * info)
1304{
1305#ifdef CGL_DEBUG
1306 const OsiRowCutDebugger * debugger = si.getRowCutDebugger();
1307 if (debugger&&debugger->onOptimalPath(si)) {
1308 printf("On optimal path %d\n",nPath);
1309 nPath++;
1310 int nCols=si.getNumCols();
1311 int i;
1312 const double * solution = si.getColSolution();
1313 const double * lower = si.getColLower();
1314 const double * upper = si.getColUpper();
1315 const double * optimal = debugger->optimalSolution();
1316 const double * objective = si.getObjCoefficients();
1317 double objval1=0.0,objval2=0.0;
1318 for (i=0;i<nCols;i++) {
1319#if CGL_DEBUG>1
1320 printf("%d %g %g %g %g\n",i,lower[i],solution[i],upper[i],optimal[i]);
1321#endif
1322 objval1 += solution[i]*objective[i];
1323 objval2 += optimal[i]*objective[i];
1324 assert(optimal[i]>=lower[i]-1.0e-5&&optimal[i]<=upper[i]+1.0e-5)(static_cast<void> (0));
1325 }
1326 printf("current obj %g, integer %g\n",objval1,objval2);
1327 }
1328#endif
1329 int saveRowCuts=rowCuts_;
1330 if (rowCuts_<0) {
1331 if (info->inTree)
1332 rowCuts_=4;
1333 else
1334 rowCuts_=-rowCuts_;
1335 }
1336 int saveMode = mode_;
1337 bool rowCliques=false;
1338 if (!mode_) {
1339 if (info->pass!=4||info->inTree) {
1340 mode_=1;
1341 } else {
1342 saveMode=1; // make sure do just once
1343 rowCliques=true;
1344 }
1345 }
1346 int nRows=si.getNumRows();
1347 double * rowLower = new double[nRows+1];
1348 double * rowUpper = new double[nRows+1];
1349
1350 int nCols=si.getNumCols();
1351 double * colLower = new double[nCols];
1352 double * colUpper = new double[nCols];
1353
1354 int ninfeas=gutsOfGenerateCuts(si,cs,rowLower,rowUpper,colLower,colUpper,info);
1355 if (ninfeas) {
1356 // generate infeasible cut and return
1357 OsiRowCut rc;
1358 rc.setLb(COIN_DBL_MAX);
1359 rc.setUb(0.0);
1360 cs.insert(rc);
1361#ifdef CGL_DEBUG
1362 const OsiRowCutDebugger * debugger = si.getRowCutDebugger();
1363 if (debugger&&debugger->onOptimalPath(si))
1364 assert(!debugger->invalidCut(rc))(static_cast<void> (0));
1365#endif
1366 }
1367 rowCuts_=saveRowCuts;
1368 mode_=saveMode;
1369 // move bounds so can be used by user
1370 if (mode_==3) {
1371 delete [] rowLower_;
1372 delete [] rowUpper_;
1373 rowLower_ = rowLower;
1374 rowUpper_ = rowUpper;
1375 } else {
1376 delete [] rowLower;
1377 delete [] rowUpper;
1378 }
1379 delete [] colLower_;
1380 delete [] colUpper_;
1381 colLower_ = colLower;
1382 colUpper_ = colUpper;
1383 // Setup information
1384 if (rowCliques&&numberRows_&&numberColumns_)
1385 setupRowCliqueInformation(si);
1386 return ninfeas;
1387}
1388bool analyze(const OsiSolverInterface * solverX, char * intVar,
1389 double * lower, double * upper)
1390{
1391 OsiSolverInterface * solver = solverX->clone();
1392 const double *objective = solver->getObjCoefficients() ;
1393 int numberColumns = solver->getNumCols() ;
1394 int numberRows = solver->getNumRows();
1395 double direction = solver->getObjSense();
1396 int iRow,iColumn;
1397
1398 // Row copy
1399 CoinPackedMatrix matrixByRow(*solver->getMatrixByRow());
1400 const double * elementByRow = matrixByRow.getElements();
1401 const int * column = matrixByRow.getIndices();
1402 const CoinBigIndex * rowStart = matrixByRow.getVectorStarts();
1403 const int * rowLength = matrixByRow.getVectorLengths();
1404
1405 // Column copy
1406 CoinPackedMatrix matrixByCol(*solver->getMatrixByCol());
1407 const double * element = matrixByCol.getElements();
1408 const int * row = matrixByCol.getIndices();
1409 const CoinBigIndex * columnStart = matrixByCol.getVectorStarts();
1410 const int * columnLength = matrixByCol.getVectorLengths();
1411
1412 const double * rowLower = solver->getRowLower();
1413 const double * rowUpper = solver->getRowUpper();
1414
1415 char * ignore = new char [numberRows];
1416 int * which = new int[numberRows];
1417 double * changeRhs = new double[numberRows];
1418 memset(changeRhs,0,numberRows*sizeof(double));
1419 memset(ignore,0,numberRows);
1420 int numberChanged=0;
1421 bool finished=false;
1422 while (!finished) {
1423 int saveNumberChanged = numberChanged;
1424 for (iRow=0;iRow<numberRows;iRow++) {
1425 int numberContinuous=0;
1426 double value1=0.0,value2=0.0;
1427 bool allIntegerCoeff=true;
1428 double sumFixed=0.0;
1429 int jColumn1=-1,jColumn2=-1;
1430 for (CoinBigIndex j=rowStart[iRow];j<rowStart[iRow]+rowLength[iRow];j++) {
1431 int jColumn = column[j];
1432 double value = elementByRow[j];
1433 if (upper[jColumn] > lower[jColumn]+1.0e-8) {
1434 if (!intVar[jColumn]) {
1435 if (numberContinuous==0) {
1436 jColumn1=jColumn;
1437 value1=value;
1438 } else {
1439 jColumn2=jColumn;
1440 value2=value;
1441 }
1442 numberContinuous++;
1443 } else {
1444 if (fabs(value-floor(value+0.5))>1.0e-12)
1445 allIntegerCoeff=false;
1446 }
1447 } else {
1448 sumFixed += lower[jColumn]*value;
1449 }
1450 }
1451 double low = rowLower[iRow];
1452 if (low>-1.0e20) {
1453 low -= sumFixed;
1454 if (fabs(low-floor(low+0.5))>1.0e-12)
1455 allIntegerCoeff=false;
1456 }
1457 double up = rowUpper[iRow];
1458 if (up<1.0e20) {
1459 up -= sumFixed;
1460 if (fabs(up-floor(up+0.5))>1.0e-12)
1461 allIntegerCoeff=false;
1462 }
1463 if (!allIntegerCoeff)
1464 continue; // can't do
1465 if (numberContinuous==1) {
1466 // see if really integer
1467 // This does not allow for complicated cases
1468 if (low==up) {
1469 if (fabs(value1)>1.0e-3) {
1470 value1 = 1.0/value1;
1471 if (fabs(value1-floor(value1+0.5))<1.0e-12) {
1472 // integer
1473 numberChanged++;
1474 intVar[jColumn1]=77;
1475 }
1476 }
1477 } else {
1478 if (fabs(value1)>1.0e-3) {
1479 value1 = 1.0/value1;
1480 if (fabs(value1-floor(value1+0.5))<1.0e-12) {
1481 // This constraint will not stop it being integer
1482 ignore[iRow]=1;
1483 }
1484 }
1485 }
1486 } else if (numberContinuous==2) {
1487 if (low==up) {
1488 /* need general theory - for now just look at 2 cases -
1489 1 - +- 1 one in column and just costs i.e. matching objective
1490 2 - +- 1 two in column but feeds into G/L row which will try and minimize
1491 (take out 2 for now - until fixed)
1492 */
1493 if (fabs(value1)==1.0&&value1*value2==-1.0&&!lower[jColumn1]
1494 &&!lower[jColumn2]&&columnLength[jColumn1]==1&&columnLength[jColumn2]==1) {
1495 int n=0;
1496 int i;
1497 double objChange=direction*(objective[jColumn1]+objective[jColumn2]);
1498 double bound = CoinMin(upper[jColumn1],upper[jColumn2]);
1499 bound = CoinMin(bound,1.0e20);
1500 for ( i=columnStart[jColumn1];i<columnStart[jColumn1]+columnLength[jColumn1];i++) {
1501 int jRow = row[i];
1502 double value = element[i];
1503 if (jRow!=iRow) {
1504 which[n++]=jRow;
1505 changeRhs[jRow]=value;
1506 }
1507 }
1508 for ( i=columnStart[jColumn2];i<columnStart[jColumn2]+columnLength[jColumn2];i++) {
1509 int jRow = row[i];
1510 double value = element[i];
1511 if (jRow!=iRow) {
1512 if (!changeRhs[jRow]) {
1513 which[n++]=jRow;
1514 changeRhs[jRow]=value;
1515 } else {
1516 changeRhs[jRow]+=value;
1517 }
1518 }
1519 }
1520 if (objChange>=0.0) {
1521 // see if all rows OK
1522 bool good=true;
1523 for (i=0;i<n;i++) {
1524 int jRow = which[i];
1525 double value = changeRhs[jRow];
1526 if (value) {
1527 value *= bound;
1528 if (rowLength[jRow]==1) {
1529 if (value>0.0) {
1530 double rhs = rowLower[jRow];
1531 if (rhs>0.0) {
1532 double ratio =rhs/value;
1533 if (fabs(ratio-floor(ratio+0.5))>1.0e-12)
1534 good=false;
1535 }
1536 } else {
1537 double rhs = rowUpper[jRow];
1538 if (rhs<0.0) {
1539 double ratio =rhs/value;
1540 if (fabs(ratio-floor(ratio+0.5))>1.0e-12)
1541 good=false;
1542 }
1543 }
1544 } else if (rowLength[jRow]==2) {
1545 if (value>0.0) {
1546 if (rowLower[jRow]>-1.0e20)
1547 good=false;
1548 } else {
1549 if (rowUpper[jRow]<1.0e20)
1550 good=false;
1551 }
1552 } else {
1553 good=false;
1554 }
1555 }
1556 }
1557 if (good) {
1558 // both can be integer
1559 numberChanged++;
1560 intVar[jColumn1]=77;
1561 numberChanged++;
1562 intVar[jColumn2]=77;
1563 }
1564 }
1565 // clear
1566 for (i=0;i<n;i++) {
1567 changeRhs[which[i]]=0.0;
1568 }
1569 }
1570 }
1571 }
1572 }
1573 for (iColumn=0;iColumn<numberColumns;iColumn++) {
1574 if (upper[iColumn] > lower[iColumn]+1.0e-8&&!intVar[iColumn]) {
1575 double value;
1576 value = upper[iColumn];
1577 if (value<1.0e20&&fabs(value-floor(value+0.5))>1.0e-12)
1578 continue;
1579 value = lower[iColumn];
1580 if (value>-1.0e20&&fabs(value-floor(value+0.5))>1.0e-12)
1581 continue;
1582 bool integer=true;
1583 for (CoinBigIndex j=columnStart[iColumn];j<columnStart[iColumn]+columnLength[iColumn];j++) {
1584 int iRow = row[j];
1585 if (!ignore[iRow]) {
1586 integer=false;
1587 break;
1588 }
1589 }
1590 if (integer) {
1591 // integer
1592 numberChanged++;
1593 intVar[iColumn]=77;
1594 }
1595 }
1596 }
1597 finished = numberChanged==saveNumberChanged;
1598 }
1599 bool feasible=true;
1600 for (iColumn=0;iColumn<numberColumns;iColumn++) {
1601 if (intVar[iColumn]==77) {
1602 if (upper[iColumn]>1.0e20) {
1603 upper[iColumn] = 1.0e20;
1604 } else {
1605 upper[iColumn] = floor(upper[iColumn]+1.0e-5);
1606 }
1607 if (lower[iColumn]<-1.0e20) {
1608 lower[iColumn] = -1.0e20;
1609 } else {
1610 lower[iColumn] = ceil(lower[iColumn]-1.0e-5);
1611 if (lower[iColumn]>upper[iColumn])
1612 feasible=false;
1613 }
1614 if (lower[iColumn]==0.0&&upper[iColumn]==1.0)
1615 intVar[iColumn]=1;
1616 else if (lower[iColumn]==upper[iColumn])
1617 intVar[iColumn]=0;
1618 else
1619 intVar[iColumn]=2;
1620 }
1621 }
1622 delete [] which;
1623 delete [] changeRhs;
1624 delete [] ignore;
1625 //if (numberChanged)
1626 //printf("%d variables could be made integer\n",numberChanged);
1627 delete solver;
1628 return feasible;
1629}
1630int CglProbing::gutsOfGenerateCuts(const OsiSolverInterface & si,
1631 OsiCuts & cs ,
1632 double * rowLower, double * rowUpper,
1633 double * colLower, double * colUpper,
1634 CglTreeInfo * info)
1635{
1636 //printf("PASS\n");
1637 // Get basic problem information
1638 int nRows;
1639
1640 CoinPackedMatrix * rowCopy=NULL__null;
1641 int numberRowCutsBefore = cs.sizeRowCuts();
1642
1643 // get branch and bound cutoff
1644 double cutoff;
1645 bool cutoff_available = si.getDblParam(OsiDualObjectiveLimit,cutoff);
1646 if (!cutoff_available||usingObjective_<0) { // cut off isn't set or isn't valid
1
Assuming 'cutoff_available' is true
2
Assuming field 'usingObjective_' is >= 0
3
Taking false branch
1647 cutoff = si.getInfinity();
1648 }
1649 cutoff *= si.getObjSense();
1650 if (fabs(cutoff)>1.0e30)
4
Assuming the condition is false
5
Taking false branch
1651 assert (cutoff>1.0e30)(static_cast<void> (0));
1652 int mode=mode_;
1653
1654 int nCols=si.getNumCols();
1655
1656 // get integer variables
1657 const char * intVarOriginal = si.getColType(true);
1658 char * intVar = CoinCopyOfArray(intVarOriginal,nCols);
1659 int i;
1660 int numberIntegers=0;
1661 CoinMemcpyN(si.getColLower(),nCols,colLower);
1662 CoinMemcpyN(si.getColUpper(),nCols,colUpper);
1663 const double * colsol =si.getColSolution();
1664 // and put reasonable bounds on integer variables
1665 for (i=0;i<nCols;i++) {
6
Assuming 'i' is >= 'nCols'
7
Loop condition is false. Execution continues on line 1677
1666 if (intVar[i]) {
1667 numberIntegers++;
1668 if (intVar[i]==2) {
1669 // make sure reasonable bounds
1670 if (colsol[i]<1.0e10&&colUpper[i]>1.0e12)
1671 colUpper[i] = CGL_REASONABLE_INTEGER_BOUND1.23456789e10;
1672 if (colsol[i]>-1.0e10&&colLower[i]<-1.0e12)
1673 colLower[i] = -CGL_REASONABLE_INTEGER_BOUND1.23456789e10;
1674 }
1675 }
1676 }
1677 bool feasible=true;
1678 if (!info->inTree&&!info->pass) {
8
Assuming field 'inTree' is true
1679 // make more integer
1680 feasible = analyze(&si,intVar,colLower,colUpper);
1681 }
1682 if (feasible
8.1
'feasible' is true
8.1
'feasible' is true
8.1
'feasible' is true
&&PROBING_EXTRA_STUFFfalse) {
9
Taking false branch
1683 // tighten bounds on djs
1684 // should be in CbcCutGenerator and check if basic
1685 const double * djs =si.getReducedCost();
1686 const double * colsol =si.getColSolution();
1687 double direction = si.getObjSense();
1688 double cutoff;
1689 bool cutoff_available = si.getDblParam(OsiDualObjectiveLimit,cutoff);
1690 if (!cutoff_available||usingObjective_<0) { // cut off isn't set or isn't valid
1691 cutoff = si.getInfinity();
1692 }
1693 cutoff *= direction;
1694 if (fabs(cutoff)>1.0e30)
1695 assert (cutoff>1.0e30)(static_cast<void> (0));
1696 double current = si.getObjValue();
1697 current *= direction;
1698 double gap=CoinMax(cutoff-current,1.0e-1);
1699 for (int i = 0; i < nCols; ++i) {
1700 double djValue = djs[i]*direction;
1701 if (colUpper[i]-colLower[i]>1.0e-8) {
1702 if (colsol[i]<colLower[i]+primalTolerance_) {
1703 if (djValue>gap) {
1704 if (si.isInteger(i)) {
1705 printf("why int %d not fixed at lb\n",i);
1706 colUpper[i]= colLower[i];
1707 } else {
1708 double newUpper = colLower[i] + gap/djValue;
1709 if (newUpper<colUpper[i]) {
1710 //printf("%d ub from %g to %g\n",i,colUpper[i],newUpper);
1711 colUpper[i]= CoinMax(newUpper,colLower[i]+1.0e-5);
1712 }
1713 }
1714 }
1715 } else if (colsol[i]>colUpper[i]-primalTolerance_) {
1716 if (-djValue>gap) {
1717 if (si.isInteger(i)) {
1718 printf("why int %d not fixed at ub\n",i);
1719 colLower[i]= colUpper[i];
1720 } else {
1721 double newLower = colUpper[i] + gap/djValue;
1722 if (newLower>colLower[i]) {
1723 //printf("%d lb from %g to %g\n",i,colLower[i],newLower);
1724 colLower[i]= CoinMin(newLower,colUpper[i]-1.0e-5);
1725 }
1726 }
1727 }
1728 }
1729 }
1730 }
1731 }
1732 int ninfeas=0;
1733 // Set up maxes
1734 int maxProbe = info->inTree
9.1
Field 'inTree' is true
9.1
Field 'inTree' is true
9.1
Field 'inTree' is true
? maxProbe_ : maxProbeRoot_;
10
'?' condition is true
1735 int maxElements = info->inTree
10.1
Field 'inTree' is true
10.1
Field 'inTree' is true
10.1
Field 'inTree' is true
? maxElements_ : maxElementsRoot_;
11
'?' condition is true
1736 //if (!info->inTree&&!info->pass)
1737 //maxElements=nCols;
1738 // Get objective offset
1739 double offset;
1740 si.getDblParam(OsiObjOffset,offset);
1741#ifdef COIN_DEVELOP
1742 if (offset&&!info->inTree&&!info->pass)
1743 printf("CglProbing obj offset %g\n",offset);
1744#endif
1745 // see if using cached copy or not
1746 if (!rowCopy_) {
12
Assuming field 'rowCopy_' is non-null
13
Taking false branch
1747 // create from current
1748 nRows=si.getNumRows();
1749
1750 // mode==0 is invalid if going from current matrix
1751 if (mode==0)
1752 mode=1;
1753 // add in objective if there is a cutoff
1754 if (cutoff<1.0e30&&usingObjective_>0) {
1755 rowCopy = new CoinPackedMatrix(*si.getMatrixByRow(),1,nCols,false);
1756 } else {
1757 rowCopy = new CoinPackedMatrix(*si.getMatrixByRow());
1758 }
1759 // add in objective if there is a cutoff
1760 if (cutoff<1.0e30&&usingObjective_>0) {
1761 int * columns = new int[nCols];
1762 double * elements = new double[nCols];
1763 int n=0;
1764 const double * objective = si.getObjCoefficients();
1765 bool maximize = (si.getObjSense()==-1);
1766 for (i=0;i<nCols;i++) {
1767 if (objective[i]) {
1768 elements[n]= (maximize) ? -objective[i] : objective[i];
1769 columns[n++]=i;
1770 }
1771 }
1772 rowCopy->appendRow(n,columns,elements);
1773 delete [] columns;
1774 delete [] elements;
1775 CoinMemcpyN(si.getRowLower(),nRows,rowLower);
1776 CoinMemcpyN(si.getRowUpper(),nRows,rowUpper);
1777 rowLower[nRows]=-COIN_DBL_MAX;
1778 rowUpper[nRows]=cutoff+offset;
1779 nRows++;
1780 } else {
1781 CoinMemcpyN(si.getRowLower(),nRows,rowLower);
1782 CoinMemcpyN(si.getRowUpper(),nRows,rowUpper);
1783 }
1784 } else {
1785 // use snapshot
1786 nRows=numberRows_;
1787 assert(nCols==numberColumns_)(static_cast<void> (0));
1788
1789 rowCopy = new CoinPackedMatrix(*rowCopy_);
1790 assert (rowCopy_->getNumRows()==numberRows_)(static_cast<void> (0));
1791 rowLower = new double[nRows];
1792 rowUpper = new double[nRows];
1793 CoinMemcpyN(rowLower_,nRows,rowLower);
1794 CoinMemcpyN(rowUpper_,nRows,rowUpper);
1795 if (usingObjective_>0) {
14
Assuming field 'usingObjective_' is <= 0
15
Taking false branch
1796 rowLower[nRows-1]=-COIN_DBL_MAX;
1797 rowUpper[nRows-1]=cutoff+offset;
1798 }
1799 }
1800 CoinBigIndex * rowStartPos = NULL__null;
1801 int * realRows = NULL__null;
1802 {
1803 // Now take out rows with too many elements
1804 int * rowLength = rowCopy->getMutableVectorLengths();
1805 //#define OUTRUBBISH
1806 double * elements = rowCopy->getMutableElements();
1807 int * column = rowCopy->getMutableIndices();
1808 CoinBigIndex * rowStart = rowCopy->getMutableVectorStarts();
1809#ifdef OUTRUBBISH
1810 double large=1.0e3;
1811#endif
1812 int nDelete = 0;
1813 int nKeep=0;
1814 int * which = new int[nRows];
1815 int nElements=rowCopy->getNumElements();
1816 int nTotalOut=0;
1817 int nRealRows = si.getNumRows();
1818 for (i=0;i<nRows;i++) {
16
Assuming 'i' is >= 'nRows'
17
Loop condition is false. Execution continues on line 1826
1819 if (rowLength[i]>maxElements||(rowLower[i]<-1.0e20&&rowUpper[i]>1.0e20)) {
1820 // keep objective
1821 if (i<nRealRows)
1822 nTotalOut+=rowLength[i];
1823 }
1824 }
1825 // keep all if only a few dense
1826 if (nTotalOut*10<nElements)
18
Assuming the condition is false
19
Taking false branch
1827 maxElements=nCols;
1828#ifdef OUTRUBBISH
1829 int nExtraDel=0;
1830#endif
1831 for (i=0;i
19.1
'i' is >= 'nRows'
19.1
'i' is >= 'nRows'
19.1
'i' is >= 'nRows'
<nRows;i++) {
20
Loop condition is false. Execution continues on line 1946
1832 if ((rowLength[i]>maxElements&&i<nRealRows)||
1833 (rowLower[i]<-1.0e20&&rowUpper[i]>1.0e20)) {
1834 which[nDelete++]=i;
1835 } else {
1836#ifdef OUTRUBBISH
1837 // out all rows with infinite plus and minus
1838 int nPlus=rowUpper[i]>-large ? 0 : 1;
1839 int nMinus=rowLower[i]<large ? 0 : 1;
1840 CoinBigIndex start = rowStart[i];
1841 CoinBigIndex end = start + rowLength[i];
1842 for (CoinBigIndex j=start; j<end ; j++) {
1843 int iColumn = column[j];
1844 if (colUpper[iColumn]>large) {
1845 if (elements[j]>0.0)
1846 nPlus++;
1847 else
1848 nMinus++;
1849 }
1850 if (colLower[iColumn]<-large) {
1851 if (elements[j]<0.0)
1852 nPlus++;
1853 else
1854 nMinus++;
1855 }
1856 }
1857 if (!nPlus||!nMinus) {
1858 rowLower[nKeep]=rowLower[i];
1859 rowUpper[nKeep]=rowUpper[i];
1860 nKeep++;
1861 } else {
1862 nExtraDel++;
1863 which[nDelete++]=i;
1864 }
1865#else
1866 if (info->strengthenRow&&!info->pass&&(rowLower[i]<-1.0e20||rowUpper[i]>1.0e20)) {
1867 int nPlus=0;
1868 int nMinus=0;
1869 for (CoinBigIndex j=rowStart[i];j<rowStart[i+1];j++) {
1870 int jColumn=column[j];
1871 if (intVar[jColumn]&&colLower[jColumn]==0.0&&colUpper[jColumn]==1.0) {
1872 double value=elements[j];
1873 if (value>0.0) {
1874 nPlus++;
1875 } else {
1876 nMinus++;
1877 }
1878 } else {
1879 nPlus=2;
1880 nMinus=2;
1881 break;
1882 }
1883 }
1884 double effectiveness=0.0;
1885 if (nPlus==1&&rowUpper[i]>0.0&&rowUpper[i]<1.0e10) {
1886 // can make element smaller
1887 for (CoinBigIndex j=rowStart[i];j<rowStart[i+1];j++) {
1888 double value=elements[j];
1889 if (value>0.0) {
1890 elements[j] -= rowUpper[i];
1891 //printf("pass %d row %d plus el from %g to %g\n",info->pass,
1892 // i,elements[j]+rowUpper[i],elements[j]);
1893 }
1894 effectiveness += fabs(elements[j]);
1895 }
1896 rowUpper[i]=0.0;
1897 } else if (nMinus==1&&rowLower[i]<0.0&&rowLower[i]>-1.0e10) {
1898 // can make element smaller in magnitude
1899 for (CoinBigIndex j=rowStart[i];j<rowStart[i+1];j++) {
1900 double value=elements[j];
1901 if (value<0.0) {
1902 elements[j] -= rowLower[i];
1903 //printf("pass %d row %d minus el from %g to %g\n",info->pass,
1904 // i,elements[j]+rowLower[i],elements[j]);
1905 }
1906 effectiveness += fabs(elements[j]);
1907 }
1908 rowLower[i]=0.0;
1909 }
1910 if (effectiveness) {
1911 OsiRowCut rc;
1912 rc.setLb(rowLower[i]);
1913 rc.setUb(rowUpper[i]);
1914 int start = rowStart[i];
1915 int n = rowLength[i];
1916 rc.setRow(rowLength[i],column+start,elements+start,false);
1917 // but get rid of tinies
1918 CoinPackedVector & row = rc.mutableRow();
1919 double * elements = row.getElements();
1920 int n2=0;
1921 for (n2=0;n2<n;n2++) {
1922 if (fabs(elements[n2])<1.0e-12)
1923 break;
1924 }
1925 if (n2<n) {
1926 int * columns = row.getIndices();
1927 for (int i=n2+1;i<n;i++) {
1928 if (fabs(elements[i])>1.0e-12) {
1929 elements[n2]=elements[i];
1930 columns[n2++]=columns[i];
1931 }
1932 }
1933 row.truncate(n2);
1934 }
1935 rc.setEffectiveness(effectiveness);
1936 assert (!info->strengthenRow[i])(static_cast<void> (0));
1937 info->strengthenRow[i]=rc.clone();
1938 }
1939 }
1940 rowLower[nKeep]=rowLower[i];
1941 rowUpper[nKeep]=rowUpper[i];
1942 nKeep++;
1943#endif
1944 }
1945 }
1946 if (nDelete
20.1
'nDelete' is 0
20.1
'nDelete' is 0
20.1
'nDelete' is 0
) {
21
Taking false branch
1947#ifdef OUTRUBBISH
1948 if (nExtraDel) {
1949 printf("%d rows deleted (extra %d)\n",nDelete,nExtraDel);
1950 }
1951#else
1952#endif
1953 if (info->strengthenRow) {
1954 // Set up pointers to real rows
1955 realRows = new int [nRows];
1956 CoinZeroN(realRows,nRows);
1957 for (i=0;i<nDelete;i++)
1958 realRows[which[i]]=-1;
1959 int k=0;
1960 for (i=0;i<nRows;i++) {
1961 if (!realRows[i]) {
1962 if (i<nRealRows)
1963 realRows[k++]=i; // keep
1964 else
1965 realRows[k++]=-1; // objective - discard
1966 }
1967 }
1968 }
1969 rowCopy->deleteRows(nDelete,which);
1970 nRows=nKeep;
1971 }
1972 delete [] which;
1973 if (!nRows
21.1
'nRows' is not equal to 0
21.1
'nRows' is not equal to 0
21.1
'nRows' is not equal to 0
) {
22
Taking false branch
1974#ifdef COIN_DEVELOP
1975 printf("All rows too long for probing\n");
1976#endif
1977 // nothing left!!
1978 // delete stuff
1979 delete rowCopy;
1980 if (rowCopy_) {
1981 delete [] rowLower;
1982 delete [] rowUpper;
1983 }
1984 delete [] intVar;
1985 // and put back unreasonable bounds on integer variables
1986 const double * trueLower = si.getColLower();
1987 const double * trueUpper = si.getColUpper();
1988 for (i=0;i<nCols;i++) {
1989 if (intVarOriginal[i]==2) {
1990 if (colUpper[i] == CGL_REASONABLE_INTEGER_BOUND1.23456789e10)
1991 colUpper[i] = trueUpper[i];
1992 if (colLower[i] == -CGL_REASONABLE_INTEGER_BOUND1.23456789e10)
1993 colLower[i] = trueLower[i];
1994 }
1995 }
1996 delete [] realRows;
1997 return 0;
1998 }
1999 // Out elements for fixed columns and sort
2000 elements = rowCopy->getMutableElements();
2001 column = rowCopy->getMutableIndices();
2002 rowStart = rowCopy->getMutableVectorStarts();
2003 rowLength = rowCopy->getMutableVectorLengths();
2004#if 0
2005 int nFixed=0;
2006 for (i=0;i<nCols;i++) {
2007 if (colUpper[i]==colLower[i])
2008 nFixed++;
2009 }
2010 printf("%d columns fixed\n",nFixed);
2011#endif
2012 CoinBigIndex newSize=0;
2013 int * column2 = new int[nCols];
2014 double * elements2 = new double[nCols];
2015 rowStartPos = new CoinBigIndex [nRows];
2016 for (i=0;i
22.1
'i' is >= 'nRows'
22.1
'i' is >= 'nRows'
22.1
'i' is >= 'nRows'
<nRows;i++) {
23
Loop condition is false. Execution continues on line 2051
2017 double offset = 0.0;
2018 CoinBigIndex start = rowStart[i];
2019 rowStart[i]=newSize;
2020 CoinBigIndex save=newSize;
2021 CoinBigIndex end = start + rowLength[i];
2022 int nOther=0;
2023 for (CoinBigIndex j=start; j<end ; j++) {
2024 int iColumn = column[j];
2025 if (colUpper[iColumn]>colLower[iColumn]) {
2026 double value = elements[j];
2027 if (value<0.0) {
2028 elements[newSize]=value;
2029 column[newSize++]=iColumn;
2030 } else if (value>0.0) {
2031 elements2[nOther]=value;
2032 column2[nOther++]=iColumn;
2033 }
2034 } else {
2035 offset += colUpper[iColumn]*elements[j];
2036 }
2037 }
2038 rowStartPos[i] = newSize;
2039 for (int k=0;k<nOther;k++) {
2040 elements[newSize]=elements2[k];
2041 column[newSize++]=column2[k];
2042 }
2043 rowLength[i]=newSize-save;
2044 if (offset) {
2045 if (rowLower[i]>-1.0e20)
2046 rowLower[i] -= offset;
2047 if (rowUpper[i]<1.0e20)
2048 rowUpper[i] -= offset;
2049 }
2050 }
2051 delete [] column2;
2052 delete [] elements2;
2053 rowStart[nRows]=newSize;
2054 rowCopy->setNumElements(newSize);
2055 }
2056 CoinPackedMatrix * columnCopy=new CoinPackedMatrix(*rowCopy,0,0,true);
2057 int nRowsSafe=CoinMin(nRows,si.getNumRows());
2058#ifdef CGL_DEBUG
2059 const OsiRowCutDebugger * debugger = si.getRowCutDebugger();
2060 if (debugger&&!debugger->onOptimalPath(si))
2061 debugger = NULL__null;
2062#else
2063 const OsiRowCutDebugger * debugger = NULL__null;
2064#endif
2065
2066 const int * column = rowCopy->getIndices();
2067 const CoinBigIndex * rowStart = rowCopy->getVectorStarts();
2068 const int * rowLength = rowCopy->getVectorLengths();
2069 const double * rowElements = rowCopy->getElements();
2070 // Arrays so user can find out what happened
2071 if (!lookedAt_) {
24
Assuming field 'lookedAt_' is non-null
25
Taking false branch
2072 lookedAt_ = new int[nCols];
2073 }
2074 numberThisTime_=0;
2075 // Let us never add more than twice the number of rows worth of row cuts
2076 // Keep cuts out of cs until end so we can find duplicates quickly
2077 int nRowsFake = info->inTree
25.1
Field 'inTree' is true
25.1
Field 'inTree' is true
25.1
Field 'inTree' is true
? nRowsSafe/3 : nRowsSafe;
26
'?' condition is true
2078 if (!info->inTree
26.1
Field 'inTree' is true
26.1
Field 'inTree' is true
26.1
Field 'inTree' is true
&&!info->pass)
2079 nRowsFake *= 5;
2080 row_cut rowCut(nRowsFake,!info->inTree);
2081 int * markR = new int [nRows];
2082 double * minR = new double [nRows];
2083 double * maxR = new double [nRows];
2084 if (mode) {
27
Assuming 'mode' is 0
28
Taking false branch
2085 ninfeas= tighten(colLower, colUpper, column, rowElements,
2086 rowStart, rowStartPos ,rowLength, rowLower, rowUpper,
2087 nRows, nCols, intVar, 2, primalTolerance_);
2088 if (!feasible)
2089 ninfeas=1;
2090 if (!ninfeas) {
2091 // create column cuts where integer bounds have changed
2092 {
2093 const double * lower = si.getColLower();
2094 const double * upper = si.getColUpper();
2095 const double * colsol = si.getColSolution();
2096 int numberChanged=0,ifCut=0;
2097 CoinPackedVector lbs;
2098 CoinPackedVector ubs;
2099 for (i = 0; i < nCols; ++i) {
2100 if (intVar[i]) {
2101 colUpper[i] = CoinMin(upper[i],floor(colUpper[i]+1.0e-4));
2102 if (colUpper[i]<upper[i]-1.0e-8) {
2103 if (colUpper[i]<colsol[i]-1.0e-8)
2104 ifCut=1;
2105 ubs.insert(i,colUpper[i]);
2106 numberChanged++;
2107 }
2108 colLower[i] = CoinMax(lower[i],ceil(colLower[i]-1.0e-4));
2109 if (colLower[i]>lower[i]+1.0e-8) {
2110 if (colLower[i]>colsol[i]+1.0e-8)
2111 ifCut=1;
2112 lbs.insert(i,colLower[i]);
2113 numberChanged++;
2114 }
2115 }
2116 }
2117 if (numberChanged) {
2118 OsiColCut cc;
2119 cc.setUbs(ubs);
2120 cc.setLbs(lbs);
2121 if (ifCut) {
2122 cc.setEffectiveness(100.0);
2123 } else {
2124 cc.setEffectiveness(1.0e-5);
2125 }
2126#ifdef CGL_DEBUG
2127 checkBounds(debugger,cc);
2128#endif
2129 cs.insert(cc);
2130 }
2131 }
2132 if (maxProbe>0) {
2133 numberThisTime_=0;
2134 // get min max etc for rows
2135 tighten2(colLower, colUpper, column, rowElements,
2136 rowStart, rowLength, rowLower, rowUpper,
2137 minR , maxR , markR, nRows);
2138 // decide what to look at
2139 if (mode==1) {
2140 const double * colsol = si.getColSolution();
2141 double_int_pair * array = new double_int_pair [nCols];
2142# ifdef ZEROFAULT
2143 std::memset(array,0,sizeof(double_int_pair)*nCols) ;
2144# endif
2145 double multiplier = -1.0;
2146 if (info->inTree||(info->pass&1)!=0)
2147 multiplier=1.0;
2148 //const int * columnLength = si.getMatrixByCol()->getVectorLengths();
2149 for (i=0;i<nCols;i++) {
2150 if (intVar[i]&&colUpper[i]-colLower[i]>1.0e-8) {
2151 double away = fabs(0.5-(colsol[i]-floor(colsol[i])));
2152 if (away<0.49999||!info->inTree) {
2153 //array[numberThisTime_].infeasibility=away;
2154 array[numberThisTime_].infeasibility=away*multiplier;
2155 //array[numberThisTime_].infeasibility=-columnLength[i];
2156 array[numberThisTime_++].sequence=i;
2157 }
2158 }
2159 }
2160 //printf("maxP %d num %d\n",maxProbe,numberThisTime_);
2161 std::sort(array,array+numberThisTime_,double_int_pair_compare());
2162 //numberThisTime_=CoinMin(numberThisTime_,maxProbe);
2163 for (i=0;i<numberThisTime_;i++) {
2164 lookedAt_[i]=array[i].sequence;
2165 }
2166 delete [] array;
2167 } else {
2168 for (i=0;i<nCols;i++) {
2169 if (intVar[i]&&colUpper[i]-colLower[i]>1.0e-8) {
2170 lookedAt_[numberThisTime_++]=i;
2171 }
2172 }
2173 }
2174#if 0
2175 // Only look at short rows
2176 for (i=0;i<nRows;i++) {
2177 if (rowLength[i]>maxElements)
2178 abort(); //markR[i]=-2;
2179 }
2180#endif
2181 // sort to be clean
2182 //std::sort(lookedAt_,lookedAt_+numberThisTime_);
2183 if (!numberCliques_) {
2184 ninfeas= probe(si, debugger, cs, colLower, colUpper, rowCopy,columnCopy,
2185 rowStartPos, realRows, rowLower, rowUpper,
2186 intVar, minR, maxR, markR,
2187 info);
2188 } else {
2189 ninfeas= probeCliques(si, debugger, cs, colLower, colUpper, rowCopy,columnCopy,
2190 realRows,rowLower, rowUpper,
2191 intVar, minR, maxR, markR,
2192 info);
2193 }
2194 }
2195 }
2196 } else if (maxProbe>0) {
29
Assuming 'maxProbe' is > 0
30
Taking true branch
2197 // global cuts from previous calculations
2198 // could check more thoroughly that integers are correct
2199 assert(numberIntegers==numberIntegers_)(static_cast<void> (0));
2200 // make up list of new variables to look at
2201 numberThisTime_=0;
2202 const double * colsol = si.getColSolution();
2203 double_int_pair * array = new double_int_pair [nCols];
2204# ifdef ZEROFAULT
2205 std::memset(array,0,sizeof(double_int_pair)*nCols) ;
2206# endif
2207 for (i=0;i<number01Integers_;i++) {
31
Assuming 'i' is >= field 'number01Integers_'
32
Loop condition is false. Execution continues on line 2215
2208 int j=cutVector_[i].sequence;
2209 if (!cutVector_[i].index&&colUpper[j]-colLower[j]>1.0e-8) {
2210 double away = fabs(0.5-(colsol[j]-floor(colsol[j])));
2211 array[numberThisTime_].infeasibility=away;
2212 array[numberThisTime_++].sequence=i;
2213 }
2214 }
2215 std::sort(array,array+numberThisTime_,double_int_pair_compare());
2216 numberThisTime_=CoinMin(numberThisTime_,maxProbe);
2217 for (i=0;i<numberThisTime_;i++) {
33
Loop condition is false. Execution continues on line 2222
2218 lookedAt_[i]=array[i].sequence;
2219 }
2220 // sort to be clean
2221 //std::sort(lookedAt_,lookedAt_+numberThisTime_);
2222 delete [] array;
2223 // get min max etc for rows
2224 tighten2(colLower, colUpper, column, rowElements,
2225 rowStart, rowLength, rowLower, rowUpper,
2226 minR , maxR , markR, nRows);
2227 OsiCuts csNew;
2228 // don't do cuts at all if 0 (i.e. we are just checking bounds)
2229 if (rowCuts_) {
34
Assuming field 'rowCuts_' is not equal to 0
35
Taking true branch
2230#if 0
2231 // Only look at short rows
2232 for (i=0;i<nRows;i++) {
2233 if (rowLength[i]>maxElements)
2234 abort(); //markR[i]=-2;
2235 }
2236#endif
2237 ninfeas= probeCliques(si, debugger, csNew, colLower, colUpper, rowCopy,columnCopy,
2238 realRows, rowLower, rowUpper,
2239 intVar, minR, maxR, markR,
2240 info);
2241 }
2242 if (!ninfeas) {
36
Assuming 'ninfeas' is 0
37
Taking true branch
2243 // go through row cuts
2244 int nCuts = csNew.sizeRowCuts();
2245 int iCut;
2246 // need space for backward lookup
2247 // just for ones being looked at
2248 int * backward = new int [2*nCols];
2249 int * onList = backward + nCols;
2250 for (i=0;i
37.1
'i' is >= 'nCols'
37.1
'i' is >= 'nCols'
37.1
'i' is >= 'nCols'
<nCols;i++) {
38
Loop condition is false. Execution continues on line 2254
2251 backward[i]=-1;
2252 onList[i]=0;
2253 }
2254 for (i=0;i<number01Integers_;i++) {
39
Assuming 'i' is < field 'number01Integers_'
40
Loop condition is true. Entering loop body
41
Assuming 'i' is >= field 'number01Integers_'
42
Loop condition is false. Execution continues on line 2261
2255 int j=cutVector_[i].sequence;
2256 backward[j]=i;
2257 onList[j]=1;
2258 }
2259 // first do counts
2260 // we know initialized to zero
2261 for (iCut=0;iCut<nCuts;iCut++) {
43
Assuming 'iCut' is >= 'nCuts'
44
Loop condition is false. Execution continues on line 2353
2262 OsiRowCut rcut;
2263 CoinPackedVector rpv;
2264 rcut = csNew.rowCut(iCut);
2265 rpv = rcut.row();
2266 assert(rpv.getNumElements()==2)(static_cast<void> (0));
2267 const int * indices = rpv.getIndices();
2268 double* elements = rpv.getElements();
2269 double lb=rcut.lb();
2270 // find out which integer
2271 int which=0;
2272 i=backward[indices[0]];
2273 if (i<0||!onList[indices[0]]) {
2274 which=1;
2275 i=backward[indices[1]];
2276 // Just possible variable was general integer but now 0-1
2277 if (!onList[indices[which]])
2278 continue;
2279 }
2280 int other = indices[1-which];
2281 if (lb==-COIN_DBL_MAX) {
2282 if (!rcut.ub()) {
2283 // UB
2284 if (elements[which]<0.0) {
2285 //assert (elements[1-which]>0.0);
2286 // delta to 0 => x to 0.0
2287 cutVector_[i].length++;
2288 } else {
2289 if (elements[1-which]<0.0&&fabs(elements[which]/elements[1-which]-
2290 colUpper[other])<1.0e-5) {
2291 // delta to 1 => x to upper bound
2292 cutVector_[i].length++;
2293 } else {
2294 if (onList[other]) {
2295 double value0 = elements[0];
2296 double value1 = elements[1];
2297 if (value0*value1==-1.0) {
2298 // can do something ?
2299 int j=backward[other];
2300 cutVector_[i].length++;
2301 cutVector_[j].length++;
2302 } else {
2303 continue;
2304 }
2305 }
2306 }
2307 }
2308 } else {
2309 if (onList[other]) {
2310 if (elements[0]==1.0&&elements[1]==1.0&&rcut.ub()==1.0) {
2311 // can do something ?
2312 int j=backward[other];
2313 cutVector_[i].length++;
2314 cutVector_[j].length++;
2315 } else {
2316 continue;
2317 }
2318 }
2319 }
2320 } else {
2321 assert(rcut.ub()==DBL_MAX)(static_cast<void> (0));
2322 if (!lb) {
2323 // LB
2324 if (elements[which]>0.0) {
2325 //assert (elements[1-which]<0.0);
2326 // delta to 0 => x to 0.0
2327 // flip so same as UB
2328 cutVector_[i].length++;
2329 } else {
2330 if (elements[1-which]<0.0&&fabs(elements[which]/elements[1-which]-
2331 colUpper[other])<1.0e-5) {
2332 // delta to 1 => x to upper bound
2333 cutVector_[i].length++;
2334 } else {
2335 if (onList[other]) {
2336 double value0 = elements[0];
2337 double value1 = elements[1];
2338 if (value0*value1==-1.0) {
2339 // can do something ?
2340 int j=backward[other];
2341 cutVector_[i].length++;
2342 cutVector_[j].length++;
2343 } else {
2344 continue;
2345 }
2346 }
2347 }
2348 }
2349 }
2350 }
2351 }
2352 // allocate space
2353 for (i=0;i<number01Integers_;i++) {
45
Loop condition is true. Entering loop body
47
Loop condition is false. Execution continues on line 2362
2354 int j=cutVector_[i].sequence;
2355 if (onList[j]&&!cutVector_[i].index) {
46
Assuming the condition is false
2356 disaggregation thisOne=cutVector_[i];
2357 cutVector_[i].index=new disaggregationAction [thisOne.length];
2358 cutVector_[i].length=0;
2359 }
2360 }
2361 // now put in
2362 for (iCut=0;iCut
47.1
'iCut' is >= 'nCuts'
47.1
'iCut' is >= 'nCuts'
47.1
'iCut' is >= 'nCuts'
<nCuts;iCut++) {
48
Loop condition is false. Execution continues on line 2532
2363 OsiRowCut rcut;
2364 CoinPackedVector rpv;
2365 int iput;
2366 rcut = csNew.rowCut(iCut);
2367 rpv = rcut.row();
2368 assert(rpv.getNumElements()==2)(static_cast<void> (0));
2369 const int * indices = rpv.getIndices();
2370 double* elements = rpv.getElements();
2371 double lb=rcut.lb();
2372 // find out which integer
2373 // find out which integer
2374 int which=0;
2375 i=backward[indices[0]];
2376 if (i<0||!onList[indices[0]]) {
2377 which=1;
2378 i=backward[indices[1]];
2379 // Just possible variable was general integer but now 0-1
2380 if (!onList[indices[which]])
2381 continue;
2382 }
2383 int other = indices[1-which];
2384 int j = other ? backward[other] : -1;
2385 if (lb==-COIN_DBL_MAX) {
2386 if (!rcut.ub()) {
2387 // UB
2388 if (elements[which]<0.0) {
2389 iput=cutVector_[i].length;
2390 if (j>=0)
2391 setAffectedInDisaggregation(cutVector_[i].index[iput],j);
2392 else
2393 setAffectedInDisaggregation(cutVector_[i].index[iput],other);
2394 setWhenAtUBInDisaggregation(cutVector_[i].index[iput],false);
2395 setAffectedToUBInDisaggregation(cutVector_[i].index[iput],false);
2396 setZeroOneInDisaggregation(cutVector_[i].index[iput],onList[other]!=0);
2397 cutVector_[i].length++;
2398 } else {
2399 if (elements[1-which]<0.0&&fabs(elements[which]/elements[1-which]-
2400 colUpper[other])<1.0e-5) {
2401 // delta to 1 => x to upper bound
2402 iput=cutVector_[i].length;
2403 if (j>=0)
2404 setAffectedInDisaggregation(cutVector_[i].index[iput],j);
2405 else
2406 setAffectedInDisaggregation(cutVector_[i].index[iput],other);
2407 setWhenAtUBInDisaggregation(cutVector_[i].index[iput],true);
2408 setAffectedToUBInDisaggregation(cutVector_[i].index[iput],true);
2409 setZeroOneInDisaggregation(cutVector_[i].index[iput],onList[other]!=0);
2410 cutVector_[i].length++;
2411 } else {
2412 if (onList[other]) {
2413 double value0 = elements[0];
2414 double value1 = elements[1];
2415 if (value0*value1==-1.0) {
2416 // can do something ?
2417 int j=backward[other];
2418 assert (j>=0)(static_cast<void> (0));
2419 // flip so value0 1.0
2420 if (value1==1.0) {
2421 j=i;
2422 i=backward[other];
2423 value1=value0;
2424 value0=1.0;
2425 }
2426 assert (value0==1.0)(static_cast<void> (0));
2427 assert (value1==-1.0)(static_cast<void> (0));
2428 iput=cutVector_[i].length;
2429 setAffectedInDisaggregation(cutVector_[i].index[iput],j);
2430 setWhenAtUBInDisaggregation(cutVector_[i].index[iput],true);
2431 setAffectedToUBInDisaggregation(cutVector_[i].index[iput],true);
2432 setZeroOneInDisaggregation(cutVector_[i].index[iput],true);
2433 cutVector_[i].length++;
2434 iput=cutVector_[j].length;
2435 setAffectedInDisaggregation(cutVector_[j].index[iput],i);
2436 setWhenAtUBInDisaggregation(cutVector_[j].index[iput],false);
2437 setAffectedToUBInDisaggregation(cutVector_[j].index[iput],false);
2438 setZeroOneInDisaggregation(cutVector_[j].index[iput],true);
2439 cutVector_[j].length++;
2440 }
2441 }
2442 }
2443 }
2444 } else {
2445 if (onList[other]) {
2446 if (elements[0]==1.0&&elements[1]==1.0&&rcut.ub()==1.0) {
2447 // can do something ?
2448 int j=backward[other];
2449 assert (j>=0)(static_cast<void> (0));
2450 iput=cutVector_[i].length;
2451 setAffectedInDisaggregation(cutVector_[i].index[iput],j);
2452 setWhenAtUBInDisaggregation(cutVector_[i].index[iput],true);
2453 setAffectedToUBInDisaggregation(cutVector_[i].index[iput],false);
2454 setZeroOneInDisaggregation(cutVector_[i].index[iput],true);
2455 cutVector_[i].length++;
2456 iput=cutVector_[j].length;
2457 setAffectedInDisaggregation(cutVector_[j].index[iput],i);
2458 setWhenAtUBInDisaggregation(cutVector_[j].index[iput],true);
2459 setAffectedToUBInDisaggregation(cutVector_[j].index[iput],false);
2460 setZeroOneInDisaggregation(cutVector_[j].index[iput],true);
2461 cutVector_[j].length++;
2462 } else {
2463#ifdef COIN_DEVELOP
2464 abort();
2465#endif
2466 continue;
2467 }
2468 }
2469 }
2470 } else {
2471 assert(rcut.ub()==DBL_MAX)(static_cast<void> (0));
2472 if (!lb) {
2473 // LB
2474 if (elements[which]>0.0) {
2475 iput=cutVector_[i].length;
2476 if (j>=0)
2477 setAffectedInDisaggregation(cutVector_[i].index[iput],j);
2478 else
2479 setAffectedInDisaggregation(cutVector_[i].index[iput],other);
2480 setWhenAtUBInDisaggregation(cutVector_[i].index[iput],false);
2481 setAffectedToUBInDisaggregation(cutVector_[i].index[iput],false);
2482 setZeroOneInDisaggregation(cutVector_[i].index[iput],onList[other]!=0);
2483 cutVector_[i].length++;
2484 } else {
2485 if (elements[1-which]<0.0&&fabs(elements[which]/elements[1-which]-
2486 colUpper[other])<1.0e-5) {
2487 iput=cutVector_[i].length;
2488 if (j>=0)
2489 setAffectedInDisaggregation(cutVector_[i].index[iput],j);
2490 else
2491 setAffectedInDisaggregation(cutVector_[i].index[iput],other);
2492 setWhenAtUBInDisaggregation(cutVector_[i].index[iput],true);
2493 setAffectedToUBInDisaggregation(cutVector_[i].index[iput],true);
2494 setZeroOneInDisaggregation(cutVector_[i].index[iput],onList[other]!=0);
2495 cutVector_[i].length++;
2496 } else {
2497 if (onList[other]) {
2498 double value0 = elements[0];
2499 double value1 = elements[1];
2500 if (value0*value1==-1.0) {
2501 // can do something ?
2502 int j=backward[other];
2503 assert (j>=0)(static_cast<void> (0));
2504 // flip so value0 -1.0
2505 if (value1==-1.0) {
2506 j=i;
2507 i=backward[other];
2508 value1=value0;
2509 value0=-1.0;
2510 }
2511 assert (value0==-1.0)(static_cast<void> (0));
2512 assert (value1==1.0)(static_cast<void> (0));
2513 iput=cutVector_[i].length;
2514 setAffectedInDisaggregation(cutVector_[i].index[iput],j);
2515 setWhenAtUBInDisaggregation(cutVector_[i].index[iput],true);
2516 setAffectedToUBInDisaggregation(cutVector_[i].index[iput],true);
2517 setZeroOneInDisaggregation(cutVector_[i].index[iput],true);
2518 cutVector_[i].length++;
2519 iput=cutVector_[j].length;
2520 setAffectedInDisaggregation(cutVector_[j].index[iput],i);
2521 setWhenAtUBInDisaggregation(cutVector_[j].index[iput],false);
2522 setAffectedToUBInDisaggregation(cutVector_[j].index[iput],false);
2523 setZeroOneInDisaggregation(cutVector_[j].index[iput],true);
2524 cutVector_[j].length++;
2525 }
2526 }
2527 }
2528 }
2529 }
2530 }
2531 }
2532 delete [] backward;
2533 // Now sort and get rid of duplicates
2534 // could also see if any are cliques
2535 int longest=0;
2536 for (i=0;i<number01Integers_;i++)
49
Loop condition is true. Entering loop body
50
Loop condition is false. Execution continues on line 2538
2537 longest = CoinMax(longest, cutVector_[i].length);
2538 unsigned int * sortit = new unsigned int[longest];
51
Memory is allocated
2539 for (i=0;i<number01Integers_;i++) {
52
Loop condition is true. Entering loop body
2540 disaggregation & thisOne=cutVector_[i];
2541 int k;
2542 int number = thisOne.length;
2543 for (k=0;k
52.1
'k' is >= 'number'
52.1
'k' is >= 'number'
52.1
'k' is >= 'number'
<number;k++) {
53
Loop condition is false. Execution continues on line 2550
2544 int affected = affectedInDisaggregation(thisOne.index[k]);
2545 int zeroOne = zeroOneInDisaggregation(thisOne.index[k]) ? 1 : 0;
2546 int whenAtUB = whenAtUBInDisaggregation(thisOne.index[k]) ? 1 : 0;
2547 int affectedToUB = affectedToUBInDisaggregation(thisOne.index[k]) ? 1: 0;
2548 sortit[k]=(affected<<3)|(zeroOne<<2)|(whenAtUB<<1)|affectedToUB;
2549 }
2550 std::sort(sortit,sortit+number);
54
Calling 'sort<unsigned int *>'
2551 int affectedLast = 0xffffffff;
2552 int zeroOneLast = 0;
2553 int whenAtUBLast = 0;
2554 int affectedToUBLast = 0;
2555 int put=0;
2556 for (k=0;k<number;k++) {
2557 int affected = sortit[k]>>3;
2558 int zeroOne = (sortit[k]&4)>>2;
2559 int whenAtUB = (sortit[k]&2)>>1;
2560 int affectedToUB = sortit[k]&1;
2561 disaggregationAction action;
2562 action.affected=0;
2563 setAffectedInDisaggregation(action,affected);
2564 setZeroOneInDisaggregation(action,zeroOne!=0);
2565 setWhenAtUBInDisaggregation(action,whenAtUB!=0);
2566 setAffectedToUBInDisaggregation(action,affectedToUB!=0);
2567 if (affected!=affectedLast||zeroOne!=zeroOneLast) {
2568 // new variable
2569 thisOne.index[put++]=action;
2570 } else if (whenAtUB!=whenAtUBLast||affectedToUB!=affectedToUBLast) {
2571 // new action - what can we discover
2572 thisOne.index[put++]=action;
2573 int j=cutVector_[i].sequence;
2574 int k=affected;
2575 if (zeroOne) {
2576 k=cutVector_[k].sequence;
2577 if (logLevel_>1)
2578 printf("For %d %d 0-1 pair",j,k) ;
2579 } else {
2580 if (logLevel_>1)
2581 printf("For %d %d pair",j,k) ;
2582 }
2583 if (logLevel_>1)
2584 printf(" old whenAtUB, affectedToUB %d %d, new whenAtUB, affectedToUB %d %d\n",
2585 whenAtUBLast, affectedToUBLast,whenAtUB, affectedToUB);
2586 }
2587 affectedLast=affected;
2588 zeroOneLast=zeroOne;
2589 whenAtUBLast=whenAtUB;
2590 affectedToUBLast=affectedToUB;
2591 }
2592 if (put<number) {
2593 //printf("%d reduced from %d to %d\n",i,number,put);
2594 thisOne.length=put;
2595 }
2596 }
2597 // And look at all where two 0-1 variables involved
2598 for (i=0;i<number01Integers_;i++) {
2599 disaggregation & thisOne=cutVector_[i];
2600 int k;
2601 int number = thisOne.length;
2602 for (k=0;k<number;k++) {
2603 int affected = affectedInDisaggregation(thisOne.index[k]);
2604 bool zeroOne = zeroOneInDisaggregation(thisOne.index[k]);
2605 if (zeroOne&&static_cast<int>(affected)>i) {
2606 bool whenAtUB = whenAtUBInDisaggregation(thisOne.index[k]);
2607 bool affectedToUB = affectedToUBInDisaggregation(thisOne.index[k]);
2608 disaggregation otherOne=cutVector_[affected];
2609 int numberOther = otherOne.length;
2610 // Could do binary search if a lot
2611 int lastAction=-1;
2612 for (int j=0;j<numberOther;j++) {
2613 if (affectedInDisaggregation(otherOne.index[j])==i) {
2614 bool whenAtUBOther = whenAtUBInDisaggregation(otherOne.index[j]);
2615 bool affectedToUBOther = affectedToUBInDisaggregation(otherOne.index[j]);
2616 /* action -
2617 0 -> x + y <=1 (1,1 impossible)
2618 1 -> x - y <=0 (1,0 impossible)
2619 2 -> -x + y <=0 (0,1 impossible)
2620 3 -> -x -y <= -1 (0,0 impossible)
2621 10 -> x == y
2622 11 -> x + y == 1
2623 20 -> x == 0
2624 21 -> x == 1
2625 22 -> y == 0
2626 23 -> y == 1
2627 */
2628 int action=-1;
2629 if (whenAtUB) {
2630 if (affectedToUB) {
2631 // x -> 1 => y -> 1
2632 if (whenAtUBOther) {
2633 if (affectedToUBOther) {
2634 // y -> 1 => x -> 1
2635 action=10; // x,y must be same
2636 } else {
2637 // y -> 1 => x -> 0
2638 action=20; // If x is 1 then contradiction
2639 }
2640 } else {
2641 if (affectedToUBOther) {
2642 // y -> 0 => x -> 1
2643 action=23; // if y is 0 then contradiction
2644 } else {
2645 // y -> 0 => x -> 0
2646 action=1; // x,y 1,0 impossible
2647 }
2648 }
2649 } else {
2650 // x -> 1 => y -> 0
2651 if (whenAtUBOther) {
2652 if (affectedToUBOther) {
2653 // y -> 1 => x -> 1
2654 action=22; // If y is 1 then contradiction
2655 } else {
2656 // y -> 1 => x -> 0
2657 action=0;
2658 }
2659 } else {
2660 if (affectedToUBOther) {
2661 // y -> 0 => x -> 1
2662 action=11; // x,y with same values impossible
2663 } else {
2664 // y -> 0 => x -> 0
2665 action=20; // If x is 1 then contradiction
2666 }
2667 }
2668 }
2669 } else {
2670 if (affectedToUB) {
2671 // x -> 0 => y -> 1
2672 if (whenAtUBOther) {
2673 if (affectedToUBOther) {
2674 // y -> 1 => x -> 1
2675 action=21; // If x is 0 then contradiction
2676 } else {
2677 // y -> 1 => x -> 0
2678 action=11; // x,y must be different
2679 }
2680 } else {
2681 if (affectedToUBOther) {
2682 // y -> 0 => x -> 1
2683 action=3; // one of x,y must be 1
2684 } else {
2685 // y -> 0 => x -> 0
2686 action=23; // if y is 0 then contradiction
2687 }
2688 }
2689 } else {
2690 // x -> 0 => y -> 0
2691 if (whenAtUBOther) {
2692 if (affectedToUBOther) {
2693 // y -> 1 => x -> 1
2694 action=2; // x,y 0,1 impossible
2695 } else {
2696 // y -> 1 => x -> 0
2697 action=22; // If y is 1 then contradiction
2698 }
2699 } else {
2700 if (affectedToUBOther) {
2701 // y -> 0 => x -> 1
2702 action=21; // if x is 0 then contradiction
2703 } else {
2704 // y -> 0 => x -> 0
2705 action=10; // x,y must be same
2706 }
2707 }
2708 }
2709 }
2710 assert (action>=0)(static_cast<void> (0));
2711 if (action<4) {
2712 // clique - see if there
2713 if (oneFixStart_) {
2714 switch (action) {
2715 case 0:
2716 break;
2717 case 1:
2718 break;
2719 case 2:
2720 break;
2721 case 3:
2722 break;
2723 }
2724 // If not can we add or strengthen
2725 }
2726 // check last action
2727 if (lastAction>=0) {
2728 if (logLevel_>1)
2729 printf("XX lastAction %d, this %d\n",lastAction,action);
2730 }
2731 } else if (action<12) {
2732 if (logLevel_>1)
2733 printf("XX Could eliminate one of %d %d 0-1 variables %c\n",i,affected,
2734 (lastAction>=0) ? '*' : ' ');
2735 if (info->strengthenRow) {
2736 OsiRowCut rc;
2737 int index[2];
2738 double element[2];
2739 index[0]=cutVector_[i].sequence;
2740 element[0]=1.0;
2741 index[1]=cutVector_[affected].sequence;
2742 if (action==10) {
2743 // 10 -> x == y
2744 rc.setLb(0.0);
2745 rc.setUb(0.0);
2746 element[1]= -1.0;
2747 } else {
2748 // 11 -> x + y == 1
2749 rc.setLb(1.0);
2750 rc.setUb(1.0);
2751 element[1]= 1.0;
2752 }
2753 rc.setRow(2,index,element,false);
2754 cs.insert(rc);
2755 }
2756 } else {
2757 if (action<22) {
2758 if (logLevel_>1)
2759 printf("XX Could fix a 0-1 variable %d\n",i);
2760 } else {
2761 if (logLevel_>1)
2762 printf("XX Could fix a 0-1 variable %d\n",affected);
2763 }
2764 }
2765 //printf("%d when %d forces %d to %d , %d when %d forces %d to %d\n",
2766 // i,whenAtUB,affected,affectedToUB,
2767 // affected, whenAtUBOther,i, affectedToUBOther);
2768 }
2769 }
2770 }
2771 }
2772 }
2773 delete [] sortit;
2774 }
2775 if (cutVector_) {
2776 // now see if any disaggregation cuts are violated
2777 for (i=0;i<number01Integers_;i++) {
2778 int j=cutVector_[i].sequence;
2779 double solInt=colsol[j];
2780 double upper, solValue;
2781 int icol;
2782 int index[2];
2783 double element[2];
2784 if (colUpper[j]-colLower[j]>1.0e-8) {
2785 double away = fabs(0.5-(solInt-floor(solInt)));
2786 if (away<0.4999999) {
2787 disaggregation thisOne=cutVector_[i];
2788 int k;
2789 OsiRowCut rc;
2790 for (k=0;k<thisOne.length;k++) {
2791 icol = affectedInDisaggregation(thisOne.index[k]);
2792 if (zeroOneInDisaggregation(thisOne.index[k]))
2793 icol = cutVector_[icol].sequence;
2794 solValue=colsol[icol];
2795 upper=colUpper_[icol];
2796 double infeasibility=0.0;
2797 if (!whenAtUBInDisaggregation(thisOne.index[k])) {
2798 if (!affectedToUBInDisaggregation(thisOne.index[k])) {
2799 // delta -> 0 => x to lb (at present just 0)
2800 infeasibility = solValue - upper * solInt;
2801 if (infeasibility > 1.0e-3) {
2802 rc.setLb(-COIN_DBL_MAX);
2803 rc.setUb(0.0);
2804 index[0]=icol;
2805 element[0]=1.0;
2806 index[1]=j;
2807 element[1]= -upper;
2808 } else {
2809 infeasibility=0.0;
2810 }
2811 } else {
2812 // delta -> 0 => x to ub
2813 abort();
2814 }
2815 } else {
2816 if (affectedToUBInDisaggregation(thisOne.index[k])) {
2817 // delta -> 1 => x to ub (?)
2818 icol = affectedInDisaggregation(thisOne.index[k]);
2819 if (zeroOneInDisaggregation(thisOne.index[k]))
2820 icol = cutVector_[icol].sequence;
2821 solValue=colsol[icol];
2822 upper=colUpper_[icol];
2823 if (!colLower[icol]) {
2824 infeasibility = upper * solInt - solValue;
2825 if (infeasibility > 1.0e-3) {
2826 rc.setLb(-COIN_DBL_MAX);
2827 rc.setUb(0.0);
2828 index[0]=icol;
2829 element[0]=-1.0;
2830 index[1]=j;
2831 element[1]= upper;
2832 } else {
2833 infeasibility=0.0;
2834 }
2835 } else {
2836 assert (upper==colLower[icol])(static_cast<void> (0));
2837 infeasibility=0.0;
2838 }
2839 } else {
2840 // delta + delta2 <= 1
2841 assert (zeroOneInDisaggregation(thisOne.index[k]))(static_cast<void> (0));
2842 // delta -> 1 => delta2 -> 0
2843 icol = affectedInDisaggregation(thisOne.index[k]);
2844 icol = cutVector_[icol].sequence;
2845 // only do if icol > j
2846 if (icol >j && colUpper[icol] ) {
2847 solValue=colsol[icol];
2848 if (!colLower[icol]) {
2849 infeasibility = solInt + solValue - 1.0;
2850 if (infeasibility > 1.0e-3) {
2851 rc.setLb(-COIN_DBL_MAX);
2852 rc.setUb(1.0);
2853 index[0]=icol;
2854 element[0]=1.0;
2855 index[1]=j;
2856 element[1]= 1.0;
2857 } else {
2858 infeasibility=0.0;
2859 }
2860 } else {
2861 assert (upper==colLower[icol])(static_cast<void> (0));
2862 infeasibility=0.0;
2863 }
2864 }
2865 }
2866 }
2867 if (infeasibility) {
2868 rc.setEffectiveness(infeasibility);
2869 rc.setRow(2,index,element,false);
2870 if (logLevel_>1)
2871 printf("%g <= %g * x%d + %g * x%d <= %g\n",
2872 rc.lb(),element[0],index[0],element[1],index[1],rc.ub());
2873#ifdef CGL_DEBUG
2874 if (debugger) assert(!debugger->invalidCut(rc))(static_cast<void> (0));
2875#endif
2876 rowCut.addCutIfNotDuplicate(rc);
2877 }
2878 }
2879 }
2880 }
2881 }
2882 }
2883 }
2884 delete [] markR;
2885 delete [] minR;
2886 delete [] maxR;
2887 // Add in row cuts
2888 if (!ninfeas) {
2889 rowCut.addCuts(cs,info->strengthenRow,0);
2890 }
2891 // delete stuff
2892 delete rowCopy;
2893 delete columnCopy;
2894 if (rowCopy_) {
2895 delete [] rowLower;
2896 delete [] rowUpper;
2897 }
2898 delete [] intVar;
2899 delete [] rowStartPos;
2900 delete [] realRows;
2901 // and put back unreasonable bounds on integer variables
2902 const double * trueLower = si.getColLower();
2903 const double * trueUpper = si.getColUpper();
2904 if (!ninfeas) {
2905 for (i=0;i<nCols;i++) {
2906 if (intVarOriginal[i]==2) {
2907 if (colUpper[i] == CGL_REASONABLE_INTEGER_BOUND1.23456789e10)
2908 colUpper[i] = trueUpper[i];
2909 if (colLower[i] == -CGL_REASONABLE_INTEGER_BOUND1.23456789e10)
2910 colLower[i] = trueLower[i];
2911 }
2912 }
2913 } else {
2914 memcpy(colLower,trueLower,nCols*sizeof(double));
2915 memcpy(colUpper,trueUpper,nCols*sizeof(double));
2916 }
2917 if (!info->inTree&&((info->options&4)==4||((info->options&8)&&!info->pass))) {
2918 int numberRowCutsAfter = cs.sizeRowCuts();
2919 for (int i=numberRowCutsBefore;i<numberRowCutsAfter;i++)
2920 cs.rowCutPtr(i)->setGloballyValid();
2921 }
2922 return ninfeas;
2923}
2924// Does probing and adding cuts
2925int CglProbing::probe( const OsiSolverInterface & si,
2926 const OsiRowCutDebugger *
2927#ifdef CGL_DEBUG
2928 debugger
2929#endif
2930 ,OsiCuts & cs,
2931 double * colLower, double * colUpper,
2932 CoinPackedMatrix *rowCopy,
2933 CoinPackedMatrix *columnCopy,
2934 const CoinBigIndex * rowStartPos,const int * realRows,
2935 const double * rowLower, const double * rowUpper,
2936 const char * intVar, double * minR, double * maxR,
2937 int * markR,
2938 CglTreeInfo * info)
2939{
2940 int nRows=rowCopy->getNumRows();
2941 int nRowsSafe=CoinMin(nRows,si.getNumRows());
2942 int nCols=rowCopy->getNumCols();
2943 const double * currentColLower = si.getColLower();
2944 const double * currentColUpper = si.getColUpper();
2945 // Set up maxes
2946 int maxStack = info->inTree ? maxStack_ : maxStackRoot_;
2947 int maxPass = info->inTree ? maxPass_ : maxPassRoot_;
2948 if ((totalTimesCalled_%10)==-1) {
2949 int newMax=CoinMin(2*maxStack,50);
2950 maxStack=CoinMax(newMax,maxStack);
2951 }
2952#define ONE_ARRAY
2953#ifdef ONE_ARRAY
2954 unsigned int DIratio = sizeof(double)/sizeof(int);
2955 assert (DIratio==1||DIratio==2)(static_cast<void> (0));
2956 int nSpace = 8*nCols+4*nRows+2*maxStack;
2957 nSpace += (4*nCols+nRows+maxStack+DIratio-1)>>(DIratio-1);
2958 double * colsol = new double[nSpace];
2959 double * djs = colsol + nCols;
2960 double * columnGap = djs + nCols;
2961 double * saveL = columnGap + nCols;
2962 double * saveU = saveL + 2*nCols;
2963 double * saveMin = saveU + 2*nCols;
2964 double * saveMax = saveMin + nRows;
2965 double * largestPositiveInRow = saveMax + nRows;
2966 double * largestNegativeInRow = largestPositiveInRow + nRows;
2967 double * element = largestNegativeInRow + nRows;
2968 double * lo0 = element + nCols;
2969 double * up0 = lo0 + maxStack;
2970 int * markC = reinterpret_cast<int *> (up0+maxStack);
2971 int * stackC = markC + nCols;
2972 int * stackR = stackC + 2*nCols;
2973 int * index = stackR + nRows;
2974 int * stackC0 = index + nCols;
2975#else
2976 double * colsol = new double[nCols];
2977 double * djs = new double[nCols];
2978 double * columnGap = new double [nCols];
2979 double * saveL = new double [2*nCols];
2980 double * saveU = new double [2*nCols];
2981 double * saveMin = new double [nRows];
2982 double * saveMax = new double [nRows];
2983 double * largestPositiveInRow = new double [nRows];
2984 double * largestNegativeInRow = new double [nRows];
2985 double * element = new double[nCols];
2986 double * lo0 = new double[maxStack];
2987 double * up0 = new double[maxStack];
2988 int * markC = new int [nCols];
2989 int * stackC = new int [2*nCols];
2990 int * stackR = new int [nRows];
2991 int * index = new int[nCols];
2992 int * stackC0 = new int[maxStack];
2993#endif
2994 // Let us never add more than twice the number of rows worth of row cuts
2995 // Keep cuts out of cs until end so we can find duplicates quickly
2996#define PROBING4
2997#ifdef PROBING4
2998 int nRowsFake = info->inTree ? nRowsSafe/3 : nRowsSafe*10;
2999#else
3000 int nRowsFake = info->inTree ? nRowsSafe/3 : nRowsSafe;
3001#endif
3002 if (!info->inTree&&!info->pass)
3003 nRowsFake *= 10;
3004 bool justReplace = ((info->options&64)!=0)&&(realRows!=NULL__null);
3005 if (justReplace) {
3006 nRowsFake=nRows;
3007 }
3008 row_cut rowCut(nRowsFake, !info->inTree);
3009 totalTimesCalled_++;
3010 const int * column = rowCopy->getIndices();
3011 const CoinBigIndex * rowStart = rowCopy->getVectorStarts();
3012 const double * rowElements = rowCopy->getElements();
3013 const int * row = columnCopy->getIndices();
3014 const CoinBigIndex * columnStart = columnCopy->getVectorStarts();
3015 const int * columnLength = columnCopy->getVectorLengths();
3016 const double * columnElements = columnCopy->getElements();
3017#define MOVE_SINGLETONS
3018#ifdef MOVE_SINGLETONS
3019 const double * objective = si.getObjCoefficients();
3020 const int * columnLength2 = si.getMatrixByCol()->getVectorLengths();
3021#endif
3022 bool anyColumnCuts=false;
3023 int ninfeas=0;
3024 int rowCuts;
3025 double disaggEffectiveness;
3026 /* clean up djs and solution */
3027 CoinMemcpyN(si.getReducedCost(),nCols,djs);
3028 CoinMemcpyN( si.getColSolution(),nCols,colsol);
3029 disaggEffectiveness=1.0e-3;
3030 rowCuts=rowCuts_;
3031 //CoinBigIndex * rowStartPos = new CoinBigIndex [nRows];
3032#ifndef NDEBUG1
3033 const int * rowLength = rowCopy->getVectorLengths();
3034#endif
3035 for (int i=0;i<nRows;i++) {
3036 assert (rowStart[i]+rowLength[i]==rowStart[i+1])(static_cast<void> (0));
3037 int kk;
3038#ifndef NDEBUG1
3039 for ( kk =rowStart[i];kk<rowStart[i+1];kk++) {
3040 double value = rowElements[kk];
3041 if (value>0.0)
3042 break;
3043 }
3044 assert (rowStartPos[i]==kk)(static_cast<void> (0));
3045#endif
3046 double value;
3047 value=0.0;
3048 for ( kk =rowStart[i];kk<rowStartPos[i];kk++) {
3049 int iColumn = column[kk];
3050 double gap = CoinMin(1.0e100,colUpper[iColumn]-colLower[iColumn]);
3051 value = CoinMin(value,gap*rowElements[kk]);
3052 }
3053 largestNegativeInRow[i]=value;
3054 value=0.0;
3055 for ( ;kk<rowStart[i+1];kk++) {
3056 int iColumn = column[kk];
3057 double gap = CoinMin(1.0e100,colUpper[iColumn]-colLower[iColumn]);
3058 value = CoinMax(value,gap*rowElements[kk]);
3059 }
3060 largestPositiveInRow[i]=value;
3061 }
3062 double direction = si.getObjSense();
3063 for (int i = 0; i < nCols; ++i) {
3064 double djValue = djs[i]*direction;
3065 double gap=colUpper[i]-colLower[i];
3066 if (gap>1.0e-8) {
3067 if (colsol[i]<colLower[i]+primalTolerance_) {
3068 colsol[i]=colLower[i];
3069 djs[i] = CoinMax(0.0,djValue);
3070 } else if (colsol[i]>colUpper[i]-primalTolerance_) {
3071 colsol[i]=colUpper[i];
3072 djs[i] = CoinMin(0.0,djValue);
3073 } else {
3074 djs[i]=0.0;
3075 }
3076 }
3077 columnGap[i]=gap-primalTolerance_;
3078 }
3079
3080 int ipass=0,nfixed=-1;
3081
3082 double cutoff;
3083 bool cutoff_available = si.getDblParam(OsiDualObjectiveLimit,cutoff);
3084 if (!cutoff_available||usingObjective_<0) { // cut off isn't set or isn't valid
3085 cutoff = si.getInfinity();
3086 }
3087 cutoff *= direction;
3088 if (fabs(cutoff)>1.0e30)
3089 assert (cutoff>1.0e30)(static_cast<void> (0));
3090 double current = si.getObjValue();
3091 current *= direction;
3092 /* for both way coding */
3093 int nstackC0=-1;
3094 int nstackR,nstackC;
3095 //int nFix=0;
3096 for (int i=0;i<nCols;i++) {
3097 if (colUpper[i]-colLower[i]<1.0e-8) {
3098 markC[i]=3;
3099 //nFix++;
3100 } else {
3101 markC[i]=0;
3102 if (colUpper[i]>1.0e10)
3103 markC[i] |= 8;
3104 if (colLower[i]<-1.0e10)
3105 markC[i] |= 4;
3106 }
3107 }
3108 //printf("PROBE %d fixed out of %d\n",nFix,nCols);
3109 double tolerance = 1.0e1*primalTolerance_;
3110 // If we are going to replace coefficient then we don't need to be effective
3111 //double needEffectiveness = info->strengthenRow ? -1.0e10 : 1.0e-3;
3112 double needEffectiveness = info->strengthenRow ? 1.0e-8 : 1.0e-3;
3113 if (justReplace&&(info->pass&1)!=0)
3114 needEffectiveness=-1.0e10;
3115 if (PROBING_EXTRA_STUFFfalse) {
3116 int nCut=0;
3117 for (int iRow=0;iRow<nRows;iRow++) {
3118 int numberInt=0;
3119 int whichInt=-1;
3120 int numberNeg=0;
3121 double sumFixed=0.0;
3122 double intValue=0.0;
3123 for (CoinBigIndex j=rowStart[iRow];j<rowStart[iRow+1];j++) {
3124 int jColumn = column[j];
3125 double value = rowElements[j];
3126 if (colUpper[jColumn] > colLower[jColumn]+1.0e-8) {
3127 if (intVar[jColumn]) {
3128 numberInt++;
3129 whichInt=jColumn;
3130 intValue=value;
3131 } else if (value<0) {
3132 numberNeg++;
3133 }
3134 } else {
3135 sumFixed += colLower[jColumn]*value;
3136 }
3137 }
3138 if (numberInt==1&&numberNeg==0&&intValue<0.0&&!rowUpper[iRow]&&rowLower[iRow]<-1.0e30&&!sumFixed) {
3139 double intSol = colsol[whichInt];
3140 for (CoinBigIndex j=rowStart[iRow];j<rowStart[iRow+1];j++) {
3141 int jColumn = column[j];
3142 //double value = rowElements[j];
3143 if (colUpper[jColumn] > colLower[jColumn]+1.0e-8) {
3144 if (!intVar[jColumn]) {
3145 if (colLower[jColumn]||colUpper[jColumn]>1.0)
3146 continue;;
3147 double upper = colUpper[jColumn];
3148 if (colsol[jColumn]>intSol*upper+1.0e-4) {
3149 nCut++;
3150 OsiRowCut rc;
3151 rc.setLb(-COIN_DBL_MAX);
3152 rc.setUb(0.0);
3153 rc.setEffectiveness(1.0e-5);
3154 int index[2];
3155 double element[2];
3156 index[0]=jColumn;
3157 index[1]=whichInt;
3158 element[0]=1.0;
3159 element[1]=-upper;
3160 rc.setRow(2,index,element,false);
3161 cs.insert(rc);
3162 }
3163 }
3164 }
3165 }
3166 }
3167 }
3168 if (nCut)
3169 printf("%d possible cuts\n",nCut);
3170 }
3171 bool saveFixingInfo = false;
3172#if PROBING1000
3173 CglTreeProbingInfo * probingInfo = dynamic_cast<CglTreeProbingInfo *> (info);
3174 const int * backward = NULL__null;
3175 const int * integerVariable = NULL__null;
3176 const int * toZero = NULL__null;
3177 const int * toOne = NULL__null;
3178 const fixEntry * fixEntries=NULL__null;
3179#endif
3180 if (info->inTree) {
3181#if PROBING1000
3182 backward = probingInfo->backward();
3183 integerVariable = probingInfo->integerVariable();
3184 toZero = probingInfo->toZero();
3185 toOne = probingInfo->toOne();
3186 fixEntries=probingInfo->fixEntries();
3187#endif
3188 } else {
3189 saveFixingInfo = (info->initializeFixing(&si)>0);
3190 }
3191 while (ipass<maxPass&&nfixed) {
3192 int iLook;
3193 ipass++;
3194 //printf("pass %d\n",ipass);
3195 nfixed=0;
3196 int justFix= (!info->inTree&&!info->pass) ? -1 : 0;
3197 int maxProbe = info->inTree ? maxProbe_ : maxProbeRoot_;
3198 if (justFix<0)
3199 maxProbe=numberThisTime_;
3200 if (maxProbe==123) {
3201 // Try and be a bit intelligent
3202 maxProbe=0;
3203 if (!info->inTree) {
3204 if (!info->pass||numberThisTime_<-100) {
3205 maxProbe=numberThisTime_;
3206 } else {
3207 int cutDown = 4;
3208 int offset = info->pass % cutDown;
3209 int i;
3210 int k=0;
3211 int kk=offset;
3212 for (i=0;i<numberThisTime_;i++) {
3213 if (!kk) {
3214#define XXXXXX
3215#ifdef XXXXXX
3216 lookedAt_[maxProbe]=lookedAt_[i];
3217#endif
3218 maxProbe++;
3219 kk=cutDown-1;
3220 } else {
3221 stackC[k++]=lookedAt_[i];
3222 kk--;
3223 }
3224 }
3225#ifdef XXXXXX
3226 memcpy(lookedAt_+maxProbe,stackC,k*sizeof(int));
3227#endif
3228 }
3229 } else {
3230 // in tree
3231 if (numberThisTime_<200) {
3232 maxProbe=numberThisTime_;
3233 } else {
3234 int cutDown = CoinMax(numberThisTime_/100,4);
3235 int offset = info->pass % cutDown;
3236 int i;
3237 int k=0;
3238 int kk=offset;
3239 for (i=0;i<numberThisTime_;i++) {
3240 if (!kk) {
3241#ifdef XXXXXX
3242 lookedAt_[maxProbe]=lookedAt_[i];
3243#endif
3244 maxProbe++;
3245 kk=cutDown-1;
3246 } else {
3247 stackC[k++]=lookedAt_[i];
3248 kk--;
3249 }
3250 }
3251#ifdef XXXXXX
3252 memcpy(lookedAt_+maxProbe,stackC,k*sizeof(int));
3253#endif
3254 }
3255 }
3256 }
3257 int leftTotalStack=maxStack*CoinMax(200,maxProbe);
3258#ifdef PROBING5
3259 if (!info->inTree&&!info->pass)
3260 leftTotalStack = 1234567890;
3261#endif
3262 //printf("maxStack %d maxPass %d numberThisTime %d info pass %d\n",
3263 // maxStack,maxPass,numberThisTime_,info->pass);
3264 for (iLook=0;iLook<numberThisTime_;iLook++) {
3265 double solval;
3266 double down;
3267 double up;
3268 if (rowCut.outOfSpace()||leftTotalStack<=0) {
3269 if (!justFix&&(!nfixed||info->inTree)) {
3270#ifdef COIN_DEVELOP
3271 if (!info->inTree)
3272 printf("Exiting a on pass %d, maxProbe %d\n",
3273 ipass,maxProbe);
3274#endif
3275 break;
3276 } else if (justFix<=0) {
3277 if (!info->inTree) {
3278 rowCuts=0;
3279 justFix=1;
3280 disaggEffectiveness=COIN_DBL_MAX;
3281 needEffectiveness=COIN_DBL_MAX;
3282 //maxStack=10;
3283 maxPass=1;
3284 } else if (!nfixed) {
3285#ifdef COIN_DEVELOP
3286 printf("Exiting b on pass %d, maxProbe %d\n",
3287 ipass,maxProbe);
3288#endif
3289 break;
3290 }
3291 }
3292 }
3293 int j=lookedAt_[iLook];
3294 //if (j==231||j==226)
3295 //printf("size %d %d j is %d\n",rowCut.numberCuts(),cs.sizeRowCuts(),j);//printf("looking at %d (%d out of %d)\n",j,iLook,numberThisTime_);
3296 solval=colsol[j];
3297 down = floor(solval+tolerance);
3298 up = ceil(solval-tolerance);
3299 if(columnGap[j]<0.0) markC[j]=3;
3300 if ((markC[j]&3)!=0||!intVar[j]) continue;
3301 double saveSolval = solval;
3302 if (solval>=colUpper[j]-tolerance||solval<=colLower[j]+tolerance||up==down) {
3303 if (solval<=colLower[j]+2.0*tolerance) {
3304 solval = colLower[j]+1.0e-1;
3305 down=colLower[j];
3306 up=down+1.0;
3307 } else if (solval>=colUpper[j]-2.0*tolerance) {
3308 solval = colUpper[j]-1.0e-1;
3309 up=colUpper[j];
3310 down=up-1;
3311 } else {
3312 // odd
3313 up=down+1.0;
3314 solval = down+1.0e-1;
3315 }
3316 }
3317 assert (up<=colUpper[j])(static_cast<void> (0));
3318 assert (down>=colLower[j])(static_cast<void> (0));
3319 assert (up>down)(static_cast<void> (0));
3320 int istackC,iway, istackR;
3321 int way[]={1,2,1};
3322 int feas[]={1,2,4};
3323 int feasible=0;
3324 int notFeasible;
3325 for (iway=0;iway<3;iway ++) {
3326 int fixThis=0;
3327 double objVal=current;
3328 int goingToTrueBound=0;
3329 stackC[0]=j;
3330 markC[j]=way[iway];
3331 double solMovement;
3332 double movement;
3333 if (way[iway]==1) {
3334 movement=down-colUpper[j];
3335 solMovement = down-colsol[j];
3336 assert(movement<-0.99999)(static_cast<void> (0));
3337 if (fabs(down-colLower[j])<1.0e-7) {
3338 goingToTrueBound=2;
3339 down=colLower[j];
3340 }
3341 } else {
3342 movement=up-colLower[j];
3343 solMovement = up-colsol[j];
3344 assert(movement>0.99999)(static_cast<void> (0));
3345 if (fabs(up-colUpper[j])<1.0e-7) {
3346 goingToTrueBound=2;
3347 up=colUpper[j];
3348 }
3349 }
3350 if (goingToTrueBound&&(colUpper[j]-colLower[j]>1.5||colLower[j]))
3351 goingToTrueBound=1;
3352 // switch off disaggregation if not wanted
3353 if ((rowCuts&1)==0)
3354 goingToTrueBound=0;
3355 bool canReplace = info->strengthenRow&&(goingToTrueBound==2);
3356#ifdef PRINT_DEBUG
3357 if (fabs(movement)>1.01) {
3358 printf("big %d %g %g %g\n",j,colLower[j],solval,colUpper[j]);
3359 }
3360#endif
3361 if (solMovement*djs[j]>0.0)
3362 objVal += solMovement*djs[j];
3363 nstackC=1;
3364 nstackR=0;
3365 saveL[0]=colLower[j];
3366 saveU[0]=colUpper[j];
3367 assert (saveU[0]>saveL[0])(static_cast<void> (0));
3368 notFeasible=0;
3369 if (movement<0.0) {
3370 colUpper[j] += movement;
3371 colUpper[j] = floor(colUpper[j]+0.5);
3372 columnGap[j] = colUpper[j]-colLower[j]-primalTolerance_;
3373#ifdef PRINT_DEBUG
3374 printf("** Trying %d down to 0\n",j);
3375#endif
3376 } else {
3377 colLower[j] += movement;
3378 colLower[j] = floor(colLower[j]+0.5);
3379 columnGap[j] = colUpper[j]-colLower[j]-primalTolerance_;
3380#ifdef PRINT_DEBUG
3381 printf("** Trying %d up to 1\n",j);
3382#endif
3383 }
3384 if (fabs(colUpper[j]-colLower[j])<1.0e-6)
3385 markC[j]=3; // say fixed
3386 markC[j] &= ~12;
3387 if (colUpper[j]>1.0e10)
3388 markC[j] |= 8;
3389 if (colLower[j]<-1.0e10)
3390 markC[j] |= 4;
3391 istackC=0;
3392 /* update immediately */
3393 int k;
3394 for ( k=columnStart[j];k<columnStart[j]+columnLength[j];k++) {
3395 int irow = row[k];
3396 double value = columnElements[k];
3397 assert (markR[irow]!=-2)(static_cast<void> (0));
3398 if (markR[irow]==-1) {
3399 stackR[nstackR]=irow;
3400 markR[irow]=nstackR;
3401 saveMin[nstackR]=minR[irow];
3402 saveMax[nstackR]=maxR[irow];
3403 nstackR++;
3404#if 0
3405 } else if (markR[irow]==-2) {
3406 continue;
3407#endif
3408 }
3409 /* could check immediately if violation */
3410 if (movement>0.0) {
3411 /* up */
3412 if (value>0.0) {
3413 /* up does not change - down does */
3414 if (minR[irow]>-1.0e10)
3415 minR[irow] += value;
3416 if (minR[irow]>rowUpper[irow]+1.0e-5) {
3417 notFeasible=1;
3418 istackC=1;
3419 break;
3420 }
3421 } else {
3422 /* down does not change - up does */
3423 if (maxR[irow]<1.0e10)
3424 maxR[irow] += value;
3425 if (maxR[irow]<rowLower[irow]-1.0e-5) {
3426 notFeasible=1;
3427 istackC=1;
3428 break;
3429 }
3430 }
3431 } else {
3432 /* down */
3433 if (value<0.0) {
3434 /* up does not change - down does */
3435 if (minR[irow]>-1.0e10)
3436 minR[irow] -= value;
3437 if (minR[irow]>rowUpper[irow]+1.0e-5) {
3438 notFeasible=1;
3439 istackC=1;
3440 break;
3441 }
3442 } else {
3443 /* down does not change - up does */
3444 if (maxR[irow]<1.0e10)
3445 maxR[irow] -= value;
3446 if (maxR[irow]<rowLower[irow]-1.0e-5) {
3447 notFeasible=1;
3448 istackC=1;
3449 break;
3450 }
3451 }
3452 }
3453 }
3454 while (istackC<nstackC&&nstackC<maxStack) { // could be istackC<maxStack?
3455 leftTotalStack--;
3456 int jway;
3457 int jcol =stackC[istackC];
3458 jway=markC[jcol];
3459 // If not first and fixed then skip
3460 if ((jway&3)==3&&istackC) {
3461 //istackC++;
3462 //continue;
3463 //printf("fixed %d on stack\n",jcol);
3464 }
3465#if PROBING1000
3466 if (backward) {
3467 int jColumn = backward[jcol];
3468 if (jColumn>=0) {
3469 int nFix=0;
3470 // 0-1 see what else could be fixed
3471 if (jway==1) {
3472 // fixed to 0
3473 int j;
3474 for ( j=toZero_[jColumn];j<toOne_[jColumn];j++) {
3475 int kColumn=fixEntry_[j].sequence;
3476 kColumn = integerVariable_[kColumn];
3477 bool fixToOne = fixEntry_[j].oneFixed;
3478 if (fixToOne) {
3479 if (colLower[kColumn]==0.0) {
3480 if (colUpper[kColumn]==1.0) {
3481 // See if on list
3482 if (!(markC[kColumn]&3)) {
3483 if(nStackC<nCols) {
3484 stackC[nstackC]=kColumn;
3485 saveL[nstackC]=colLower[kColumn];
3486 saveU[nstackC]=colUpper[kColumn];
3487 assert (saveU[nstackC]>saveL[nstackC])(static_cast<void> (0));
3488 assert (nstackC<nCols)(static_cast<void> (0));
3489 nstackC++;
3490 markC[kColumn]|=2;
3491 nFix++;
3492 }
3493 } else if ((markC[kColumn]&3)==1) {
3494 notFeasible=true;
3495 }
3496 } else {
3497 // infeasible!
3498 notFeasible=true;
3499 }
3500 }
3501 } else {
3502 if (colUpper[kColumn]==1.0) {
3503 if (colLower[kColumn]==0.0) {
3504 // See if on list
3505 if (!(markC[kColumn]&3)) {
3506 if(nStackC<nCols) {
3507 stackC[nstackC]=kColumn;
3508 saveL[nstackC]=colLower[kColumn];
3509 saveU[nstackC]=colUpper[kColumn];
3510 assert (saveU[nstackC]>saveL[nstackC])(static_cast<void> (0));
3511 assert (nstackC<nCols)(static_cast<void> (0));
3512 nstackC++;
3513 markC[kColumn]|=1;
3514 nFix++;
3515 }
3516 } else if ((markC[kColumn]&3)==2) {
3517 notFeasible=true;
3518 }
3519 } else {
3520 // infeasible!
3521 notFeasible=true;
3522 }
3523 }
3524 }
3525 }
3526 } else if (jway==2) {
3527 int j;
3528 for ( j=toOne_[jColumn];j<toZero_[jColumn+1];j++) {
3529 int kColumn=fixEntry_[j].sequence;
3530 kColumn = integerVariable_[kColumn];
3531 bool fixToOne = fixEntry_[j].oneFixed;
3532 if (fixToOne) {
3533 if (colLower[kColumn]==0.0) {
3534 if (colUpper[kColumn]==1.0) {
3535 // See if on list
3536 if (!(markC[kColumn]&3)) {
3537 if(nStackC<nCols) {
3538 stackC[nstackC]=kColumn;
3539 saveL[nstackC]=colLower[kColumn];
3540 saveU[nstackC]=colUpper[kColumn];
3541 assert (saveU[nstackC]>saveL[nstackC])(static_cast<void> (0));
3542 assert (nstackC<nCols)(static_cast<void> (0));
3543 nstackC++;
3544 markC[kColumn]|=2;
3545 nFix++;
3546 }
3547 } else if ((markC[kColumn]&3)==1) {
3548 notFeasible=true;
3549 }
3550 } else {
3551 // infeasible!
3552 notFeasible=true;
3553 }
3554 }
3555 } else {
3556 if (colUpper[kColumn]==1.0) {
3557 if (colLower[kColumn]==0.0) {
3558 // See if on list
3559 if (!(markC[kColumn]&3)) {
3560 if(nStackC<nCols) {
3561 stackC[nstackC]=kColumn;
3562 saveL[nstackC]=colLower[kColumn];
3563 saveU[nstackC]=colUpper[kColumn];
3564 assert (saveU[nstackC]>saveL[nstackC])(static_cast<void> (0));
3565 assert (nstackC<nCols)(static_cast<void> (0));
3566 nstackC++;
3567 markC[kColumn]|=1;
3568 nFix++;
3569 }
3570 } else if ((markC[kColumn]&3)==2) {
3571 notFeasible=true;
3572 }
3573 } else {
3574 // infeasible!
3575 notFeasible=true;
3576 }
3577 }
3578 }
3579 }
3580 }
3581 }
3582 }
3583#endif
3584 for (k=columnStart[jcol];k<columnStart[jcol]+columnLength[jcol];k++) {
3585 // break if found not feasible
3586 if (notFeasible)
3587 break;
3588 int irow = row[k];
3589 /* see if anything forced */
3590 int rStart = rowStart[irow];
3591 int rEnd = rowStartPos[irow];
3592 double rowUp = rowUpper[irow];
3593 double rowUp2=0.0;
3594 bool doRowUpN;
3595 bool doRowUpP;
3596 if (rowUp<1.0e10) {
3597 doRowUpN=true;
3598 doRowUpP=true;
3599 rowUp2 = rowUp-minR[irow];
3600 if (rowUp2<-primalTolerance_) {
3601 notFeasible=true;
3602 break;
3603 } else {
3604 if (rowUp2+largestNegativeInRow[irow]>0)
3605 doRowUpN=false;
3606 if (rowUp2-largestPositiveInRow[irow]>0)
3607 doRowUpP=false;
3608 }
3609 } else {
3610 doRowUpN=false;
3611 doRowUpP=false;
3612 rowUp2=COIN_DBL_MAX;
3613 }
3614 double rowLo = rowLower[irow];
3615 double rowLo2=0.0;
3616 bool doRowLoN;
3617 bool doRowLoP;
3618 if (rowLo>-1.0e10) {
3619 doRowLoN=true;
3620 doRowLoP=true;
3621 rowLo2 = rowLo-maxR[irow];
3622 if (rowLo2>primalTolerance_) {
3623 notFeasible=true;
3624 break;
3625 } else {
3626 if (rowLo2-largestNegativeInRow[irow]<0)
3627 doRowLoN=false;
3628 if (rowLo2+largestPositiveInRow[irow]<0)
3629 doRowLoP=false;
3630 }
3631 } else {
3632 doRowLoN=false;
3633 doRowLoP=false;
3634 rowLo2=-COIN_DBL_MAX;
3635 }
3636 if (doRowUpN&&doRowLoN) {
3637 //doRowUpN=doRowLoN=false;
3638 // Start neg values loop
3639 for (int kk =rStart;kk<rEnd;kk++) {
3640 int kcol=column[kk];
3641 int markIt=markC[kcol];
3642 if ((markIt&3)!=3) {
3643 double value2=rowElements[kk];
3644 if (colUpper[kcol]<=1e10)
3645 assert ((markIt&8)==0)(static_cast<void> (0));
3646 else
3647 assert ((markIt&8)!=0)(static_cast<void> (0));
3648 if (colLower[kcol]>=-1e10)
3649 assert ((markIt&4)==0)(static_cast<void> (0));
3650 else
3651 assert ((markIt&4)!=0)(static_cast<void> (0));
3652 assert (value2<0.0)(static_cast<void> (0));
3653 double gap = columnGap[kcol]*value2;
3654 bool doUp = (rowUp2 + gap < 0.0);
3655 bool doDown = (rowLo2 -gap > 0.0);
3656 if (doUp||doDown) {
3657 double moveUp=0.0;
3658 double moveDown=0.0;
3659 double newUpper=-1.0;
3660 double newLower=1.0;
3661 if ( doUp&&(markIt&(2+8))==0) {
3662 double dbound = colUpper[kcol]+rowUp2/value2;
3663 if (intVar[kcol]) {
3664 markIt |= 2;
3665 newLower = ceil(dbound-primalTolerance_);
3666 } else {
3667 newLower=dbound;
3668 if (newLower+primalTolerance_>colUpper[kcol]&&
3669 newLower-primalTolerance_<=colUpper[kcol]) {
3670 newLower=colUpper[kcol];
3671 markIt |= 2;
3672 //markIt=3;
3673 } else {
3674 // avoid problems - fix later ?
3675 markIt=3;
3676 }
3677 }
3678 moveUp = newLower-colLower[kcol];
3679 }
3680 if ( doDown&&(markIt&(1+4))==0) {
3681 double dbound = colLower[kcol] + rowLo2/value2;
3682 if (intVar[kcol]) {
3683 markIt |= 1;
3684 newUpper = floor(dbound+primalTolerance_);
3685 } else {
3686 newUpper=dbound;
3687 if (newUpper-primalTolerance_<colLower[kcol]&&
3688 newUpper+primalTolerance_>=colLower[kcol]) {
3689 newUpper=colLower[kcol];
3690 markIt |= 1;
3691 //markIt=3;
3692 } else {
3693 // avoid problems - fix later ?
3694 markIt=3;
3695 }
3696 }
3697 moveDown = newUpper-colUpper[kcol];
3698 }
3699 if (!moveUp&&!moveDown)
3700 continue;
3701 bool onList = ((markC[kcol]&3)!=0);
3702 if (nstackC<2*maxStack) {
3703 markC[kcol] = markIt;
3704 }
3705 if (moveUp&&nstackC<2*maxStack) {
3706 fixThis++;
3707 if (!onList) {
3708 stackC[nstackC]=kcol;
3709 saveL[nstackC]=colLower[kcol];
3710 saveU[nstackC]=colUpper[kcol];
3711 assert (saveU[nstackC]>saveL[nstackC])(static_cast<void> (0));
3712 assert (nstackC<nCols)(static_cast<void> (0));
3713 nstackC++;
3714 onList=true;
3715 }
3716 if (newLower>colsol[kcol]) {
3717 if (djs[kcol]<0.0) {
3718 /* should be infeasible */
3719 assert (newLower>colUpper[kcol]+primalTolerance_)(static_cast<void> (0));
3720 } else {
3721 objVal += moveUp*djs[kcol];
3722 }
3723 }
3724 if (intVar[kcol])
3725 newLower = CoinMax(colLower[kcol],ceil(newLower-1.0e-4));
3726 colLower[kcol]=newLower;
3727 columnGap[kcol] = colUpper[kcol]-newLower-primalTolerance_;
3728 if (fabs(colUpper[kcol]-colLower[kcol])<1.0e-6) {
3729 markC[kcol]=3; // say fixed
3730 }
3731 markC[kcol] &= ~12;
3732 if (colUpper[kcol]>1.0e10)
3733 markC[kcol] |= 8;
3734 if (colLower[kcol]<-1.0e10)
3735 markC[kcol] |= 4;
3736 /* update immediately */
3737 for (int jj =columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) {
3738 int krow = row[jj];
3739 double value = columnElements[jj];
3740 assert (markR[krow]!=-2)(static_cast<void> (0));
3741 if (markR[krow]==-1) {
3742 stackR[nstackR]=krow;
3743 markR[krow]=nstackR;
3744 saveMin[nstackR]=minR[krow];
3745 saveMax[nstackR]=maxR[krow];
3746 nstackR++;
3747 }
3748 /* could check immediately if violation */
3749 /* up */
3750 if (value>0.0) {
3751 /* up does not change - down does */
3752 if (minR[krow]>-1.0e10)
3753 minR[krow] += value*moveUp;
3754 if (krow==irow)
3755 rowUp2 = rowUp-minR[irow];
3756 if (minR[krow]>rowUpper[krow]+1.0e-5) {
3757 colUpper[kcol]=-1.0e50; /* force infeasible */
3758 break;
3759 }
3760 } else {
3761 /* down does not change - up does */
3762 if (maxR[krow]<1.0e10)
3763 maxR[krow] += value*moveUp;
3764 if (krow==irow)
3765 rowLo2 = rowLo-maxR[irow];
3766 if (maxR[krow]<rowLower[krow]-1.0e-5) {
3767 colUpper[kcol]=-1.0e50; /* force infeasible */
3768 break;
3769 }
3770 }
3771 }
3772 }
3773 if (moveDown&&nstackC<2*maxStack) {
3774 fixThis++;
3775 if (!onList) {
3776 stackC[nstackC]=kcol;
3777 saveL[nstackC]=colLower[kcol];
3778 saveU[nstackC]=colUpper[kcol];
3779 assert (saveU[nstackC]>saveL[nstackC])(static_cast<void> (0));
3780 assert (nstackC<nCols)(static_cast<void> (0));
3781 nstackC++;
3782 onList=true;
3783 }
3784 if (newUpper<colsol[kcol]) {
3785 if (djs[kcol]>0.0) {
3786 /* should be infeasible */
3787 assert (colLower[kcol]>newUpper+primalTolerance_)(static_cast<void> (0));
3788 } else {
3789 objVal += moveDown*djs[kcol];
3790 }
3791 }
3792 if (intVar[kcol])
3793 newUpper = CoinMin(colUpper[kcol],floor(newUpper+1.0e-4));
3794 colUpper[kcol]=newUpper;
3795 columnGap[kcol] = newUpper-colLower[kcol]-primalTolerance_;
3796 if (fabs(colUpper[kcol]-colLower[kcol])<1.0e-6) {
3797 markC[kcol]=3; // say fixed
3798 }
3799 markC[kcol] &= ~12;
3800 if (colUpper[kcol]>1.0e10)
3801 markC[kcol] |= 8;
3802 if (colLower[kcol]<-1.0e10)
3803 markC[kcol] |= 4;
3804 /* update immediately */
3805 for (int jj =columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) {
3806 int krow = row[jj];
3807 double value = columnElements[jj];
3808 assert (markR[krow]!=-2)(static_cast<void> (0));
3809 if (markR[krow]==-1) {
3810 stackR[nstackR]=krow;
3811 markR[krow]=nstackR;
3812 saveMin[nstackR]=minR[krow];
3813 saveMax[nstackR]=maxR[krow];
3814 nstackR++;
3815 }
3816 /* could check immediately if violation */
3817 /* down */
3818 if (value<0.0) {
3819 /* up does not change - down does */
3820 if (minR[krow]>-1.0e10)
3821 minR[krow] += value*moveDown;
3822 if (krow==irow)
3823 rowUp2 = rowUp-minR[irow];
3824 if (minR[krow]>rowUpper[krow]+1.0e-5) {
3825 colUpper[kcol]=-1.0e50; /* force infeasible */
3826 columnGap[kcol] = -1.0e50;
3827 break;
3828 }
3829 } else {
3830 /* down does not change - up does */
3831 if (maxR[krow]<1.0e10)
3832 maxR[krow] += value*moveDown;
3833 if (krow==irow)
3834 rowLo2 = rowLo-maxR[irow];
3835 if (maxR[krow]<rowLower[krow]-1.0e-5) {
3836 colUpper[kcol]=-1.0e50; /* force infeasible */
3837 columnGap[kcol] = -1.0e50;
3838 break;
3839 }
3840 }
3841 }
3842 }
3843 if (colLower[kcol]>colUpper[kcol]+primalTolerance_) {
3844 notFeasible=1;;
3845 k=columnStart[jcol]+columnLength[jcol];
3846 istackC=nstackC+1;
3847 break;
3848 }
3849 }
3850 }
3851 } // end big loop rStart->rPos
3852 } else if (doRowUpN) {
3853 // Start neg values loop
3854 for (int kk =rStart;kk<rEnd;kk++) {
3855 int kcol =column[kk];
3856 int markIt=markC[kcol];
3857 if ((markIt&3)!=3) {
3858 double value2=rowElements[kk];
3859 double gap = columnGap[kcol]*value2;
3860 if (!(rowUp2 + gap < 0.0))
3861 continue;
3862 double moveUp=0.0;
3863 double newLower=1.0;
3864 if ((markIt&(2+8))==0) {
3865 double dbound = colUpper[kcol]+rowUp2/value2;
3866 if (intVar[kcol]) {
3867 markIt |= 2;
3868 newLower = ceil(dbound-primalTolerance_);
3869 } else {
3870 newLower=dbound;
3871 if (newLower+primalTolerance_>colUpper[kcol]&&
3872 newLower-primalTolerance_<=colUpper[kcol]) {
3873 newLower=colUpper[kcol];
3874 markIt |= 2;
3875 //markIt=3;
3876 } else {
3877 // avoid problems - fix later ?
3878 markIt=3;
3879 }
3880 }
3881 moveUp = newLower-colLower[kcol];
3882 if (!moveUp)
3883 continue;
3884 bool onList = ((markC[kcol]&3)!=0);
3885 if (nstackC<2*maxStack) {
3886 markC[kcol] = markIt;
3887 }
3888 if (moveUp&&nstackC<2*maxStack) {
3889 fixThis++;
3890 if (!onList) {
3891 stackC[nstackC]=kcol;
3892 saveL[nstackC]=colLower[kcol];
3893 saveU[nstackC]=colUpper[kcol];
3894 assert (saveU[nstackC]>saveL[nstackC])(static_cast<void> (0));
3895 assert (nstackC<nCols)(static_cast<void> (0));
3896 nstackC++;
3897 onList=true;
3898 }
3899 if (newLower>colsol[kcol]) {
3900 if (djs[kcol]<0.0) {
3901 /* should be infeasible */
3902 assert (newLower>colUpper[kcol]+primalTolerance_)(static_cast<void> (0));
3903 } else {
3904 objVal += moveUp*djs[kcol];
3905 }
3906 }
3907 if (intVar[kcol])
3908 newLower = CoinMax(colLower[kcol],ceil(newLower-1.0e-4));
3909 colLower[kcol]=newLower;
3910 columnGap[kcol] = colUpper[kcol]-newLower-primalTolerance_;
3911 if (fabs(colUpper[kcol]-colLower[kcol])<1.0e-6) {
3912 markC[kcol]=3; // say fixed
3913 }
3914 markC[kcol] &= ~12;
3915 if (colUpper[kcol]>1.0e10)
3916 markC[kcol] |= 8;
3917 if (colLower[kcol]<-1.0e10)
3918 markC[kcol] |= 4;
3919 /* update immediately */
3920 for (int jj =columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) {
3921 int krow = row[jj];
3922 double value = columnElements[jj];
3923 assert (markR[krow]!=-2)(static_cast<void> (0));
3924 if (markR[krow]==-1) {
3925 stackR[nstackR]=krow;
3926 markR[krow]=nstackR;
3927 saveMin[nstackR]=minR[krow];
3928 saveMax[nstackR]=maxR[krow];
3929 nstackR++;
3930 }
3931 /* could check immediately if violation */
3932 /* up */
3933 if (value>0.0) {
3934 /* up does not change - down does */
3935 if (minR[krow]>-1.0e10)
3936 minR[krow] += value*moveUp;
3937 if (krow==irow)
3938 rowUp2 = rowUp-minR[irow];
3939 if (minR[krow]>rowUpper[krow]+1.0e-5) {
3940 colUpper[kcol]=-1.0e50; /* force infeasible */
3941 columnGap[kcol] = -1.0e50;
3942 break;
3943 }
3944 } else {
3945 /* down does not change - up does */
3946 if (maxR[krow]<1.0e10)
3947 maxR[krow] += value*moveUp;
3948 if (krow==irow)
3949 rowLo2 = rowLo-maxR[irow];
3950 if (maxR[krow]<rowLower[krow]-1.0e-5) {
3951 colUpper[kcol]=-1.0e50; /* force infeasible */
3952 columnGap[kcol] = -1.0e50;
3953 break;
3954 }
3955 }
3956 }
3957 }
3958 if (colLower[kcol]>colUpper[kcol]+primalTolerance_) {
3959 notFeasible=1;;
3960 k=columnStart[jcol]+columnLength[jcol];
3961 istackC=nstackC+1;
3962 break;
3963 }
3964 }
3965 }
3966 } // end big loop rStart->rPos
3967 } else if (doRowLoN) {
3968 // Start neg values loop
3969 for (int kk =rStart;kk<rEnd;kk++) {
3970 int kcol =column[kk];
3971 if ((markC[kcol]&3)!=3) {
3972 double moveDown=0.0;
3973 double newUpper=-1.0;
3974 double value2=rowElements[kk];
3975 int markIt=markC[kcol];
3976 assert (value2<0.0)(static_cast<void> (0));
3977 double gap = columnGap[kcol]*value2;
3978 bool doDown = (rowLo2 -gap > 0.0);
3979 if (doDown&& (markIt&(1+4))==0 ) {
3980 double dbound = colLower[kcol] + rowLo2/value2;
3981 if (intVar[kcol]) {
3982 markIt |= 1;
3983 newUpper = floor(dbound+primalTolerance_);
3984 } else {
3985 newUpper=dbound;
3986 if (newUpper-primalTolerance_<colLower[kcol]&&
3987 newUpper+primalTolerance_>=colLower[kcol]) {
3988 newUpper=colLower[kcol];
3989 markIt |= 1;
3990 //markIt=3;
3991 } else {
3992 // avoid problems - fix later ?
3993 markIt=3;
3994 }
3995 }
3996 moveDown = newUpper-colUpper[kcol];
3997 if (!moveDown)
3998 continue;
3999 bool onList = ((markC[kcol]&3)!=0);
4000 if (nstackC<2*maxStack) {
4001 markC[kcol] = markIt;
4002 }
4003 if (moveDown&&nstackC<2*maxStack) {
4004 fixThis++;
4005 if (!onList) {
4006 stackC[nstackC]=kcol;
4007 saveL[nstackC]=colLower[kcol];
4008 saveU[nstackC]=colUpper[kcol];
4009 assert (saveU[nstackC]>saveL[nstackC])(static_cast<void> (0));
4010 assert (nstackC<nCols)(static_cast<void> (0));
4011 nstackC++;
4012 onList=true;
4013 }
4014 if (newUpper<colsol[kcol]) {
4015 if (djs[kcol]>0.0) {
4016 /* should be infeasible */
4017 assert (colLower[kcol]>newUpper+primalTolerance_)(static_cast<void> (0));
4018 } else {
4019 objVal += moveDown*djs[kcol];
4020 }
4021 }
4022 if (intVar[kcol])
4023 newUpper = CoinMin(colUpper[kcol],floor(newUpper+1.0e-4));
4024 colUpper[kcol]=newUpper;
4025 columnGap[kcol] = newUpper-colLower[kcol]-primalTolerance_;
4026 if (fabs(colUpper[kcol]-colLower[kcol])<1.0e-6) {
4027 markC[kcol]=3; // say fixed
4028 }
4029 markC[kcol] &= ~12;
4030 if (colUpper[kcol]>1.0e10)
4031 markC[kcol] |= 8;
4032 if (colLower[kcol]<-1.0e10)
4033 markC[kcol] |= 4;
4034 /* update immediately */
4035 for (int jj =columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) {
4036 int krow = row[jj];
4037 double value = columnElements[jj];
4038 assert (markR[krow]!=-2)(static_cast<void> (0));
4039 if (markR[krow]==-1) {
4040 stackR[nstackR]=krow;
4041 markR[krow]=nstackR;
4042 saveMin[nstackR]=minR[krow];
4043 saveMax[nstackR]=maxR[krow];
4044 nstackR++;
4045 }
4046 /* could check immediately if violation */
4047 /* down */
4048 if (value<0.0) {
4049 /* up does not change - down does */
4050 if (minR[krow]>-1.0e10)
4051 minR[krow] += value*moveDown;
4052 if (krow==irow)
4053 rowUp2 = rowUp-minR[irow];
4054 if (minR[krow]>rowUpper[krow]+1.0e-5) {
4055 colUpper[kcol]=-1.0e50; /* force infeasible */
4056 columnGap[kcol] = -1.0e50;
4057 break;
4058 }
4059 } else {
4060 /* down does not change - up does */
4061 if (maxR[krow]<1.0e10)
4062 maxR[krow] += value*moveDown;
4063 if (krow==irow)
4064 rowLo2 = rowLo-maxR[irow];
4065 if (maxR[krow]<rowLower[krow]-1.0e-5) {
4066 colUpper[kcol]=-1.0e50; /* force infeasible */
4067 columnGap[kcol] = -1.0e50;
4068 break;
4069 }
4070 }
4071 }
4072 }
4073 if (colLower[kcol]>colUpper[kcol]+primalTolerance_) {
4074 notFeasible=1;;
4075 k=columnStart[jcol]+columnLength[jcol];
4076 istackC=nstackC+1;
4077 break;
4078 }
4079 }
4080 }
4081 } // end big loop rStart->rPos
4082 }
4083 rStart = rEnd;
4084 rEnd = rowStart[irow+1];
4085 if (doRowUpP&&doRowLoP) {
4086 //doRowUpP=doRowLoP=false;
4087 // Start pos values loop
4088 for (int kk =rStart;kk<rEnd;kk++) {
4089 int kcol=column[kk];
4090 int markIt=markC[kcol];
4091 if ((markIt&3)!=3) {
4092 double value2=rowElements[kk];
4093 assert (value2 > 0.0)(static_cast<void> (0));
4094 /* positive element */
4095 double gap = columnGap[kcol]*value2;
4096 bool doDown = (rowLo2 + gap > 0.0);
4097 bool doUp = (rowUp2 - gap < 0.0);
4098 if (doDown||doUp) {
4099 double moveUp=0.0;
4100 double moveDown=0.0;
4101 double newUpper=-1.0;
4102 double newLower=1.0;
4103 if (doDown&&(markIt&(2+8))==0) {
4104 double dbound = colUpper[kcol] + rowLo2/value2;
4105 if (intVar[kcol]) {
4106 markIt |= 2;
4107 newLower = ceil(dbound-primalTolerance_);
4108 } else {
4109 newLower=dbound;
4110 if (newLower+primalTolerance_>colUpper[kcol]&&
4111 newLower-primalTolerance_<=colUpper[kcol]) {
4112 newLower=colUpper[kcol];
4113 markIt |= 2;
4114 //markIt=3;
4115 } else {
4116 // avoid problems - fix later ?
4117 markIt=3;
4118 }
4119 }
4120 moveUp = newLower-colLower[kcol];
4121 }
4122 if (doUp&&(markIt&(1+4))==0) {
4123 double dbound = colLower[kcol] + rowUp2/value2;
4124 if (intVar[kcol]) {
4125 markIt |= 1;
4126 newUpper = floor(dbound+primalTolerance_);
4127 } else {
4128 newUpper=dbound;
4129 if (newUpper-primalTolerance_<colLower[kcol]&&
4130 newUpper+primalTolerance_>=colLower[kcol]) {
4131 newUpper=colLower[kcol];
4132 markIt |= 1;
4133 //markIt=3;
4134 } else {
4135 // avoid problems - fix later ?
4136 markIt=3;
4137 }
4138 }
4139 moveDown = newUpper-colUpper[kcol];
4140 }
4141 if (!moveUp&&!moveDown)
4142 continue;
4143 bool onList = ((markC[kcol]&3)!=0);
4144 if (nstackC<2*maxStack) {
4145 markC[kcol] = markIt;
4146 }
4147 if (moveUp&&nstackC<2*maxStack) {
4148 fixThis++;
4149 if (!onList) {
4150 stackC[nstackC]=kcol;
4151 saveL[nstackC]=colLower[kcol];
4152 saveU[nstackC]=colUpper[kcol];
4153 assert (saveU[nstackC]>saveL[nstackC])(static_cast<void> (0));
4154 assert (nstackC<nCols)(static_cast<void> (0));
4155 nstackC++;
4156 onList=true;
4157 }
4158 if (newLower>colsol[kcol]) {
4159 if (djs[kcol]<0.0) {
4160 /* should be infeasible */
4161 assert (newLower>colUpper[kcol]+primalTolerance_)(static_cast<void> (0));
4162 } else {
4163 objVal += moveUp*djs[kcol];
4164 }
4165 }
4166 if (intVar[kcol])
4167 newLower = CoinMax(colLower[kcol],ceil(newLower-1.0e-4));
4168 colLower[kcol]=newLower;
4169 columnGap[kcol] = colUpper[kcol]-newLower-primalTolerance_;
4170 if (fabs(colUpper[kcol]-colLower[kcol])<1.0e-6) {
4171 markC[kcol]=3; // say fixed
4172 }
4173 markC[kcol] &= ~12;
4174 if (colUpper[kcol]>1.0e10)
4175 markC[kcol] |= 8;
4176 if (colLower[kcol]<-1.0e10)
4177 markC[kcol] |= 4;
4178 /* update immediately */
4179 for (int jj =columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) {
4180 int krow = row[jj];
4181 double value = columnElements[jj];
4182 assert (markR[krow]!=-2)(static_cast<void> (0));
4183 if (markR[krow]==-1) {
4184 stackR[nstackR]=krow;
4185 markR[krow]=nstackR;
4186 saveMin[nstackR]=minR[krow];
4187 saveMax[nstackR]=maxR[krow];
4188 nstackR++;
4189 }
4190 /* could check immediately if violation */
4191 /* up */
4192 if (value>0.0) {
4193 /* up does not change - down does */
4194 if (minR[krow]>-1.0e10)
4195 minR[krow] += value*moveUp;
4196 if (krow==irow)
4197 rowUp2 = rowUp-minR[irow];
4198 if (minR[krow]>rowUpper[krow]+1.0e-5) {
4199 colUpper[kcol]=-1.0e50; /* force infeasible */
4200 columnGap[kcol] = -1.0e50;
4201 break;
4202 }
4203 } else {
4204 /* down does not change - up does */
4205 if (maxR[krow]<1.0e10)
4206 maxR[krow] += value*moveUp;
4207 if (krow==irow)
4208 rowLo2 = rowLo-maxR[irow];
4209 if (maxR[krow]<rowLower[krow]-1.0e-5) {
4210 colUpper[kcol]=-1.0e50; /* force infeasible */
4211 columnGap[kcol] = -1.0e50;
4212 break;
4213 }
4214 }
4215 }
4216 }
4217 if (moveDown&&nstackC<2*maxStack) {
4218 fixThis++;
4219 if (!onList) {
4220 stackC[nstackC]=kcol;
4221 saveL[nstackC]=colLower[kcol];
4222 saveU[nstackC]=colUpper[kcol];
4223 assert (saveU[nstackC]>saveL[nstackC])(static_cast<void> (0));
4224 assert (nstackC<nCols)(static_cast<void> (0));
4225 nstackC++;
4226 onList=true;
4227 }
4228 if (newUpper<colsol[kcol]) {
4229 if (djs[kcol]>0.0) {
4230 /* should be infeasible */
4231 assert (colLower[kcol]>newUpper+primalTolerance_)(static_cast<void> (0));
4232 } else {
4233 objVal += moveDown*djs[kcol];
4234 }
4235 }
4236 if (intVar[kcol])
4237 newUpper = CoinMin(colUpper[kcol],floor(newUpper+1.0e-4));
4238 colUpper[kcol]=newUpper;
4239 columnGap[kcol] = newUpper-colLower[kcol]-primalTolerance_;
4240 if (fabs(colUpper[kcol]-colLower[kcol])<1.0e-6) {
4241 markC[kcol]=3; // say fixed
4242 }
4243 markC[kcol] &= ~12;
4244 if (colUpper[kcol]>1.0e10)
4245 markC[kcol] |= 8;
4246 if (colLower[kcol]<-1.0e10)
4247 markC[kcol] |= 4;
4248 /* update immediately */
4249 for (int jj =columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) {
4250 int krow = row[jj];
4251 double value = columnElements[jj];
4252 assert (markR[krow]!=-2)(static_cast<void> (0));
4253 if (markR[krow]==-1) {
4254 stackR[nstackR]=krow;
4255 markR[krow]=nstackR;
4256 saveMin[nstackR]=minR[krow];
4257 saveMax[nstackR]=maxR[krow];
4258 nstackR++;
4259 }
4260 /* could check immediately if violation */
4261 /* down */
4262 if (value<0.0) {
4263 /* up does not change - down does */
4264 if (minR[krow]>-1.0e10)
4265 minR[krow] += value*moveDown;
4266 if (krow==irow)
4267 rowUp2 = rowUp-minR[irow];
4268 if (minR[krow]>rowUpper[krow]+1.0e-5) {
4269 colUpper[kcol]=-1.0e50; /* force infeasible */
4270 columnGap[kcol] = -1.0e50;
4271 break;
4272 }
4273 } else {
4274 /* down does not change - up does */
4275 if (maxR[krow]<1.0e10)
4276 maxR[krow] += value*moveDown;
4277 if (krow==irow)
4278 rowLo2 = rowLo-maxR[irow];
4279 if (maxR[krow]<rowLower[krow]-1.0e-5) {
4280 colUpper[kcol]=-1.0e50; /* force infeasible */
4281 columnGap[kcol] = -1.0e50;
4282 break;
4283 }
4284 }
4285 }
4286 }
4287 if (colLower[kcol]>colUpper[kcol]+primalTolerance_) {
4288 notFeasible=1;;
4289 k=columnStart[jcol]+columnLength[jcol];
4290 istackC=nstackC+1;
4291 break;
4292 }
4293 }
4294 }
4295 } // end big loop rPos->rEnd
4296 } else if (doRowUpP) {
4297 // Start pos values loop
4298 for (int kk =rStart;kk<rEnd;kk++) {
4299 int kcol =column[kk];
4300 int markIt=markC[kcol];
4301 if ((markIt&3)!=3) {
4302 double value2=rowElements[kk];
4303 assert (value2 > 0.0)(static_cast<void> (0));
4304 /* positive element */
4305 double gap = columnGap[kcol]*value2;
4306 bool doUp = (rowUp2 - gap < 0.0);
4307 if (doUp&&(markIt&(1+4))==0) {
4308 double newUpper=-1.0;
4309 double dbound = colLower[kcol] + rowUp2/value2;
4310 if (intVar[kcol]) {
4311 markIt |= 1;
4312 newUpper = floor(dbound+primalTolerance_);
4313 } else {
4314 newUpper=dbound;
4315 if (newUpper-primalTolerance_<colLower[kcol]&&
4316 newUpper+primalTolerance_>=colLower[kcol]) {
4317 newUpper=colLower[kcol];
4318 markIt |= 1;
4319 //markIt=3;
4320 } else {
4321 // avoid problems - fix later ?
4322 markIt=3;
4323 }
4324 }
4325 double moveDown = newUpper-colUpper[kcol];
4326 if (!moveDown)
4327 continue;
4328 bool onList = ((markC[kcol]&3)!=0);
4329 if (nstackC<2*maxStack) {
4330 markC[kcol] = markIt;
4331 }
4332 if (nstackC<2*maxStack) {
4333 fixThis++;
4334 if (!onList) {
4335 stackC[nstackC]=kcol;
4336 saveL[nstackC]=colLower[kcol];
4337 saveU[nstackC]=colUpper[kcol];
4338 assert (saveU[nstackC]>saveL[nstackC])(static_cast<void> (0));
4339 assert (nstackC<nCols)(static_cast<void> (0));
4340 nstackC++;
4341 onList=true;
4342 }
4343 if (newUpper<colsol[kcol]) {
4344 if (djs[kcol]>0.0) {
4345 /* should be infeasible */
4346 assert (colLower[kcol]>newUpper+primalTolerance_)(static_cast<void> (0));
4347 } else {
4348 objVal += moveDown*djs[kcol];
4349 }
4350 }
4351 if (intVar[kcol])
4352 newUpper = CoinMin(colUpper[kcol],floor(newUpper+1.0e-4));
4353 colUpper[kcol]=newUpper;
4354 columnGap[kcol] = newUpper-colLower[kcol]-primalTolerance_;
4355 if (fabs(colUpper[kcol]-colLower[kcol])<1.0e-6) {
4356 markC[kcol]=3; // say fixed
4357 }
4358 markC[kcol] &= ~12;
4359 if (colUpper[kcol]>1.0e10)
4360 markC[kcol] |= 8;
4361 if (colLower[kcol]<-1.0e10)
4362 markC[kcol] |= 4;
4363 /* update immediately */
4364 for (int jj =columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) {
4365 int krow = row[jj];
4366 double value = columnElements[jj];
4367 assert (markR[krow]!=-2)(static_cast<void> (0));
4368 if (markR[krow]==-1) {
4369 stackR[nstackR]=krow;
4370 markR[krow]=nstackR;
4371 saveMin[nstackR]=minR[krow];
4372 saveMax[nstackR]=maxR[krow];
4373 nstackR++;
4374 }
4375 /* could check immediately if violation */
4376 /* down */
4377 if (value<0.0) {
4378 /* up does not change - down does */
4379 if (minR[krow]>-1.0e10)
4380 minR[krow] += value*moveDown;
4381 if (krow==irow)
4382 rowUp2 = rowUp-minR[irow];
4383 if (minR[krow]>rowUpper[krow]+1.0e-5) {
4384 colUpper[kcol]=-1.0e50; /* force infeasible */
4385 columnGap[kcol] = -1.0e50;
4386 break;
4387 }
4388 } else {
4389 /* down does not change - up does */
4390 if (maxR[krow]<1.0e10)
4391 maxR[krow] += value*moveDown;
4392 if (krow==irow)
4393 rowLo2 = rowLo-maxR[irow];
4394 if (maxR[krow]<rowLower[krow]-1.0e-5) {
4395 colUpper[kcol]=-1.0e50; /* force infeasible */
4396 columnGap[kcol] = -1.0e50;
4397 break;
4398 }
4399 }
4400 }
4401 }
4402 if (colLower[kcol]>colUpper[kcol]+primalTolerance_) {
4403 notFeasible=1;;
4404 k=columnStart[jcol]+columnLength[jcol];
4405 istackC=nstackC+1;
4406 break;
4407 }
4408 }
4409 }
4410 } // end big loop rPos->rEnd
4411 } else if (doRowLoP) {
4412 // Start pos values loop
4413 for (int kk =rStart;kk<rEnd;kk++) {
4414 int kcol =column[kk];
4415 if ((markC[kcol]&3)!=3) {
4416 double value2=rowElements[kk];
4417 int markIt=markC[kcol];
4418 assert (value2 > 0.0)(static_cast<void> (0));
4419 /* positive element */
4420 double gap = columnGap[kcol]*value2;
4421 bool doDown = (rowLo2 +gap > 0.0);
4422 if (doDown&&(markIt&(2+8))==0) {
4423 double newLower=1.0;
4424 double dbound = colUpper[kcol] + rowLo2/value2;
4425 if (intVar[kcol]) {
4426 markIt |= 2;
4427 newLower = ceil(dbound-primalTolerance_);
4428 } else {
4429 newLower=dbound;
4430 if (newLower+primalTolerance_>colUpper[kcol]&&
4431 newLower-primalTolerance_<=colUpper[kcol]) {
4432 newLower=colUpper[kcol];
4433 markIt |= 2;
4434 //markIt=3;
4435 } else {
4436 // avoid problems - fix later ?
4437 markIt=3;
4438 }
4439 }
4440 double moveUp = newLower-colLower[kcol];
4441 if (!moveUp)
4442 continue;
4443 bool onList = ((markC[kcol]&3)!=0);
4444 if (nstackC<2*maxStack) {
4445 markC[kcol] = markIt;
4446 }
4447 if (nstackC<2*maxStack) {
4448 fixThis++;
4449 if (!onList) {
4450 stackC[nstackC]=kcol;
4451 saveL[nstackC]=colLower[kcol];
4452 saveU[nstackC]=colUpper[kcol];
4453 assert (saveU[nstackC]>saveL[nstackC])(static_cast<void> (0));
4454 assert (nstackC<nCols)(static_cast<void> (0));
4455 nstackC++;
4456 onList=true;
4457 }
4458 if (newLower>colsol[kcol]) {
4459 if (djs[kcol]<0.0) {
4460 /* should be infeasible */
4461 assert (newLower>colUpper[kcol]+primalTolerance_)(static_cast<void> (0));
4462 } else {
4463 objVal += moveUp*djs[kcol];
4464 }
4465 }
4466 if (intVar[kcol])
4467 newLower = CoinMax(colLower[kcol],ceil(newLower-1.0e-4));
4468 colLower[kcol]=newLower;
4469 columnGap[kcol] = colUpper[kcol]-newLower-primalTolerance_;
4470 if (fabs(colUpper[kcol]-colLower[kcol])<1.0e-6) {
4471 markC[kcol]=3; // say fixed
4472 }
4473 markC[kcol] &= ~12;
4474 if (colUpper[kcol]>1.0e10)
4475 markC[kcol] |= 8;
4476 if (colLower[kcol]<-1.0e10)
4477 markC[kcol] |= 4;
4478 /* update immediately */
4479 for (int jj =columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) {
4480 int krow = row[jj];
4481 double value = columnElements[jj];
4482 assert (markR[krow]!=-2)(static_cast<void> (0));
4483 if (markR[krow]==-1) {
4484 stackR[nstackR]=krow;
4485 markR[krow]=nstackR;
4486 saveMin[nstackR]=minR[krow];
4487 saveMax[nstackR]=maxR[krow];
4488 nstackR++;
4489 }
4490 /* could check immediately if violation */
4491 /* up */
4492 if (value>0.0) {
4493 /* up does not change - down does */
4494 if (minR[krow]>-1.0e10)
4495 minR[krow] += value*moveUp;
4496 if (krow==irow)
4497 rowUp2 = rowUp-minR[irow];
4498 if (minR[krow]>rowUpper[krow]+1.0e-5) {
4499 colUpper[kcol]=-1.0e50; /* force infeasible */
4500 columnGap[kcol] = -1.0e50;
4501 break;
4502 }
4503 } else {
4504 /* down does not change - up does */
4505 if (maxR[krow]<1.0e10)
4506 maxR[krow] += value*moveUp;
4507 if (krow==irow)
4508 rowLo2 = rowLo-maxR[irow];
4509 if (maxR[krow]<rowLower[krow]-1.0e-5) {
4510 colUpper[kcol]=-1.0e50; /* force infeasible */
4511 columnGap[kcol] = -1.0e50;
4512 break;
4513 }
4514 }
4515 }
4516 }
4517 if (colLower[kcol]>colUpper[kcol]+primalTolerance_) {
4518 notFeasible=1;;
4519 k=columnStart[jcol]+columnLength[jcol];
4520 istackC=nstackC+1;
4521 break;
4522 }
4523 }
4524 }
4525 } // end big loop rPos->rEnd
4526 }
4527 }
4528 istackC++;
4529 }
4530 if (!notFeasible) {
4531 if (objVal<=cutoff) {
4532 feasible |= feas[iway];
4533 } else {
4534#ifdef PRINT_DEBUG
4535 printf("not feasible on dj\n");
4536#endif
4537 notFeasible=1;
4538 if (iway==1&&feasible==0) {
4539 /* not feasible at all */
4540 ninfeas=1;
4541 j=nCols-1;
4542 break;
4543 }
4544 }
4545 if (!notFeasible&&saveFixingInfo) {
4546 // save fixing info
4547 assert (j==stackC[0])(static_cast<void> (0));
4548 int toValue = (way[iway]==1) ? -1 : +1;
4549 for (istackC=1;istackC<nstackC;istackC++) {
4550 int icol=stackC[istackC];
4551 // for now back to just 0-1
4552 if (colUpper[icol]-colLower[icol]<1.0e-12&&!saveL[istackC]&&saveU[istackC]==1.0) {
4553 assert(saveL[istackC]==colLower[icol]||(static_cast<void> (0))
4554 saveU[istackC]==colUpper[icol])(static_cast<void> (0));
4555 saveFixingInfo = info->fixes(j,toValue,
4556 icol,colLower[icol]==saveL[istackC]);
4557 }
4558 }
4559 }
4560 } else if (iway==1&&feasible==0) {
4561 /* not feasible at all */
4562 ninfeas=1;
4563 j=nCols-1;
4564 iLook=numberThisTime_;
4565 ipass=maxPass;
4566 break;
4567 }
4568 if (notFeasible)
4569 goingToTrueBound=0;
4570 if (iway==2||(iway==1&&feasible==2)) {
4571 /* keep */
4572 iway=3;
4573 nfixed++;
4574 OsiColCut cc;
4575 int nTot=0,nFix=0,nInt=0;
4576 bool ifCut=false;
4577 for (istackC=0;istackC<nstackC;istackC++) {
4578 int icol=stackC[istackC];
4579 if (intVar[icol]) {
4580 if (colUpper[icol]<currentColUpper[icol]-1.0e-4) {
4581 element[nFix]=colUpper[icol];
4582 index[nFix++]=icol;
4583 nInt++;
4584 if (colsol[icol]>colUpper[icol]+primalTolerance_) {
4585 ifCut=true;
4586 anyColumnCuts=true;
4587 }
4588 }
4589 }
4590 }
4591 if (nFix) {
4592 nTot=nFix;
4593 cc.setUbs(nFix,index,element);
4594 nFix=0;
4595 }
4596 for (istackC=0;istackC<nstackC;istackC++) {
4597 int icol=stackC[istackC];
4598 if (intVar[icol]) {
4599 if (colLower[icol]>currentColLower[icol]+1.0e-4) {
4600 element[nFix]=colLower[icol];
4601 index[nFix++]=icol;
4602 nInt++;
4603 if (colsol[icol]<colLower[icol]-primalTolerance_) {
4604 ifCut=true;
4605 anyColumnCuts=true;
4606 }
4607 }
4608 }
4609 }
4610 if (nFix) {
4611 nTot+=nFix;
4612 cc.setLbs(nFix,index,element);
4613 }
4614 // could tighten continuous as well
4615 if (nInt) {
4616 if (ifCut) {
4617 cc.setEffectiveness(100.0);
4618 } else {
4619 cc.setEffectiveness(1.0e-5);
4620 }
4621#ifdef CGL_DEBUG
4622 checkBounds(debugger,cc);
4623#endif
4624 cs.insert(cc);
4625 }
4626 for (istackC=0;istackC<nstackC;istackC++) {
4627 int icol=stackC[istackC];
4628 if (colUpper[icol]-colLower[icol]>primalTolerance_) {
4629 markC[icol]&= ~3;
4630 } else {
4631 markC[icol]=3;
4632 }
4633 }
4634 for (istackR=0;istackR<nstackR;istackR++) {
4635 int irow=stackR[istackR];
4636 markR[irow]=-1;
4637 }
4638 } else {
4639 /* is it worth seeing if can increase coefficients
4640 or maybe better see if it is a cut */
4641 if (iway==0) {
4642 nstackC0=CoinMin(nstackC,maxStack);
4643 double solMove = saveSolval-down;
4644 double boundChange;
4645 if (notFeasible) {
4646 nstackC0=0;
4647 } else {
4648 for (istackC=0;istackC<nstackC0;istackC++) {
4649 int icol=stackC[istackC];
4650 stackC0[istackC]=icol;
4651 lo0[istackC]=colLower[icol];
4652 up0[istackC]=colUpper[icol];
4653 }
4654 }
4655 /* restore all */
4656 assert (iway==0)(static_cast<void> (0));
4657 for (istackC=nstackC-1;istackC>=0;istackC--) {
4658 int icol=stackC[istackC];
4659 double oldU=saveU[istackC];
4660 double oldL=saveL[istackC];
4661 if(goingToTrueBound==2&&istackC&&!justReplace) {
4662 // upper disaggregation cut would be
4663 // xval < upper + (old_upper-upper) (jval-down)
4664 boundChange = oldU-colUpper[icol];
4665 if (boundChange>0.0&&oldU<1.0e10&&
4666 (colsol[icol]>colUpper[icol]
4667 + boundChange*solMove+primalTolerance_)) {
4668 // create cut
4669 OsiRowCut rc;
4670 rc.setLb(-COIN_DBL_MAX);
4671 rc.setUb(colUpper[icol]-down*boundChange);
4672 index[0]=icol;
4673 element[0]=1.0;
4674 index[1]=j;
4675 element[1]= - boundChange;
4676 // effectiveness is how far j moves
4677 double newSol = (colsol[icol]-colUpper[icol])/
4678 boundChange;
4679 assert(newSol>solMove)(static_cast<void> (0));
4680 rc.setEffectiveness(newSol-solMove);
4681 if (rc.effectiveness()>disaggEffectiveness) {
4682 rc.setRow(2,index,element,false);
4683#ifdef CGL_DEBUG
4684 if (debugger) assert(!debugger->invalidCut(rc))(static_cast<void> (0));
4685#endif
4686 rowCut.addCutIfNotDuplicate(rc);
4687 }
4688 }
4689 // lower disaggregation cut would be
4690 // xval > lower + (old_lower-lower) (jval-down)
4691 boundChange = oldL-colLower[icol];
4692 if (boundChange<0.0&&oldL>-1.0e10&&
4693 (colsol[icol]<colLower[icol]
4694 + boundChange*solMove-primalTolerance_)) {
4695 // create cut
4696 OsiRowCut rc;
4697 rc.setLb(colLower[icol]-down*boundChange);
4698 rc.setUb(COIN_DBL_MAX);
4699 index[0]=icol;
4700 element[0]=1.0;
4701 index[1]=j;
4702 element[1]=- boundChange;
4703 // effectiveness is how far j moves
4704 double newSol = (colsol[icol]-colLower[icol])/
4705 boundChange;
4706 assert(newSol>solMove)(static_cast<void> (0));
4707 rc.setEffectiveness(newSol-solMove);
4708 if (rc.effectiveness()>disaggEffectiveness) {
4709 rc.setRow(2,index,element,false);
4710#ifdef CGL_DEBUG
4711 if (debugger) assert(!debugger->invalidCut(rc))(static_cast<void> (0));
4712#endif
4713 rowCut.addCutIfNotDuplicate(rc);
4714#if 0
4715 printf("%d original bounds %g, %g new Lo %g sol= %g int %d sol= %g\n",icol,oldL,oldU,colLower[icol],colsol[icol], j, colsol[j]);
4716 printf("-1.0 * x(%d) + %g * y(%d) <= %g\n",
4717 icol,boundChange,j,rc.ub());
4718#endif
4719 }
4720 }
4721 }
4722 colUpper[icol]=oldU;
4723 colLower[icol]=oldL;
4724 columnGap[icol] = oldU-oldL-primalTolerance_;
4725 markC[icol]= 0;
4726 if (oldU>1.0e10)
4727 markC[icol] |= 8;
4728 if (oldL<-1.0e10)
4729 markC[icol] |= 4;
4730 }
4731 for (istackR=0;istackR<nstackR;istackR++) {
4732 int irow=stackR[istackR];
4733 // switch off strengthening if not wanted
4734 if ((rowCuts&2)!=0&&goingToTrueBound) {
4735 bool ifCut=anyColumnCuts;
4736 double gap = rowUpper[irow]-maxR[irow];
4737 double sum=0.0;
4738 if (!ifCut&&(gap>primalTolerance_&&gap<1.0e8)) {
4739 // see if the strengthened row is a cut
4740 // also see if singletons can go to good objective
4741 // Taken out as should be found elsewhere
4742 // and has to be original column length
4743#ifdef MOVE_SINGLETONS
4744 bool moveSingletons=true;
4745#endif
4746 for (int kk =rowStart[irow];kk<rowStart[irow+1];
4747 kk++) {
4748 int iColumn = column[kk];
4749 double value = rowElements[kk];
4750 sum += value*colsol[iColumn];
4751#ifdef MOVE_SINGLETONS
4752 if (moveSingletons&&j!=iColumn) {
4753 if (colUpper[iColumn]>colLower[iColumn]) {
4754 if (columnLength2[iColumn]!=1) {
4755 moveSingletons=false;
4756 }
4757 }
4758 }
4759#endif
4760 }
4761#ifdef MOVE_SINGLETONS
4762 if (moveSingletons) {
4763 // can fix any with good costs
4764 for (int kk =rowStart[irow];kk<rowStart[irow+1];
4765 kk++) {
4766 int iColumn = column[kk];
4767 if (j!=iColumn) {
4768 if (colUpper[iColumn]>colLower[iColumn]) {
4769 if (columnLength2[iColumn]==1) {
4770 double value = rowElements[kk];
4771 if (direction*objective[iColumn]*value<0.0&&!(markC[iColumn]&3)) {
4772 // Fix
4773 if (nstackC0+1<maxStack) {
4774 stackC0[nstackC0]=iColumn;
4775 if (value>0.0) {
4776 lo0[nstackC0]=colUpper[iColumn];
4777 up0[nstackC0]=colUpper[iColumn];
4778 } else {
4779 lo0[nstackC0]=colLower[iColumn];
4780 up0[nstackC0]=colLower[iColumn];
4781 }
4782 nstackC0++;
4783 }
4784 }
4785 }
4786 }
4787 }
4788 }
4789 }
4790#endif
4791 if (sum-gap*colsol[j]>maxR[irow]+primalTolerance_||(info->strengthenRow&&rowLower[irow]<-1.0e20)) {
4792 // can be a cut
4793 // subtract gap from upper and integer coefficient
4794 // saveU and saveL spare
4795 int * index = reinterpret_cast<int *>(saveL);
4796 double * element = saveU;
4797 int n=0;
4798 bool coefficientExists=false;
4799 double sum2=0.0;
4800 for (int kk =rowStart[irow];kk<rowStart[irow+1];
4801 kk++) {
4802 int kColumn = column[kk];
4803 double el = rowElements[kk];
4804 if (kColumn!=j) {
4805 index[n]=kColumn;
4806 element[n++]=el;
4807 } else {
4808 el=el-gap;
4809 if (fabs(el)>1.0e-12) {
4810 index[n]=kColumn;
4811 element[n++]=el;
4812 }
4813 coefficientExists=true;
4814 }
4815 sum2 += colsol[kColumn]*el;
4816 }
4817 if (!coefficientExists) {
4818 index[n]=j;
4819 element[n++]=-gap;
4820 sum2 -= colsol[j]*gap;
4821 }
4822 OsiRowCut rc;
4823 rc.setLb(-COIN_DBL_MAX);
4824 double ub =rowUpper[irow]-gap*(colLower[j]+1.0);
4825 rc.setUb(ub);
4826 double effectiveness=sum2-ub;
4827 effectiveness = CoinMax(effectiveness,
4828 (sum-gap*colsol[j]
4829 -maxR[irow])/gap);
4830 if (!coefficientExists)
4831 effectiveness=CoinMax(1.0e-7,
4832 effectiveness);
4833 rc.setEffectiveness(effectiveness);
4834 //rc.setEffectiveness((sum-gap*colsol[j]-maxR[irow])/gap);
4835 if (rc.effectiveness()>needEffectiveness) {
4836 rc.setRow(n,index,element,false);
4837#ifdef CGL_DEBUG
4838 if (debugger) assert(!debugger->invalidCut(rc))(static_cast<void> (0));
4839#endif
4840 // If strengthenRow point to row
4841 //if(info->strengthenRow)
4842 //printf("a point to row %d\n",irow);
4843 //#define STRENGTHEN_PRINT
4844#ifdef STRENGTHEN_PRINT
4845 if (canReplace&&rowLower[irow]<-1.0e20) {
4846 printf("1Cut %g <= ",rc.lb());
4847 int k;
4848 //printf("original row %d - %g <= <= %g - j = %d\n",iow,rowLower[irow],rowUpper[irow],j);
4849 //for (int kk=rowStart[irow];kk<rowStart[irow+1];kk++)
4850 //printf("(%d,%g) ",column[kk],rowElements[kk]);
4851 //printf("\n");
4852 for ( k=0;k<n;k++) {
4853 int iColumn = index[k];
4854 printf("%g*",element[k]);
4855 if (si.isInteger(iColumn))
4856 printf("i%d ",iColumn);
4857 else
4858 printf("x%d ",iColumn);
4859 }
4860 printf("<= %g\n",rc.ub());
4861 printf("Row %g <= ",rowLower[irow]);
4862 for (k=rowStart[irow];k<rowStart[irow+1];k++) {
4863 int iColumn = column[k];
4864 printf("%g*",rowElements[k]);
4865 if (si.isInteger(iColumn))
4866 printf("i%d ",iColumn);
4867 else
4868 printf("x%d ",iColumn);
4869 }
4870 printf("<= %g\n",rowUpper[irow]);
4871 }
4872#endif
4873 int realRow = (canReplace&&rowLower[irow]<-1.0e20) ? irow : -1;
4874 if (realRows&&realRow>=0)
4875 realRow=realRows[realRow];
4876 if (!justReplace) {
4877 rowCut.addCutIfNotDuplicate(rc,realRow);
4878 } else if (realRow>=0) {
4879 double effectiveness=0.0;
4880 for (int i=0;i<n;i++)
4881 effectiveness+=fabs(element[i]);
4882 if (!info->strengthenRow[realRow]||info->strengthenRow[realRow]->effectiveness()>effectiveness) {
4883 delete info->strengthenRow[realRow];
4884 rc.setEffectiveness(effectiveness);
4885 info->strengthenRow[realRow]=rc.clone();
4886 }
4887 }
4888 }
4889 }
4890 }
4891 gap = minR[irow]-rowLower[irow];
4892 if (!ifCut&&(gap>primalTolerance_&&gap<1.0e8)) {
4893 // see if the strengthened row is a cut
4894 sum =0.0;
4895 // also see if singletons can go to good objective
4896#ifdef MOVE_SINGLETONS
4897 bool moveSingletons=true;
4898#endif
4899 for (int kk =rowStart[irow];kk<rowStart[irow+1];
4900 kk++) {
4901 int iColumn = column[kk];
4902 double value = rowElements[kk];
4903 sum += value*colsol[iColumn];
4904#ifdef MOVE_SINGLETONS
4905 if (moveSingletons&&j!=iColumn) {
4906 if (colUpper[iColumn]>colLower[iColumn]) {
4907 if (columnLength2[iColumn]!=1) {
4908 moveSingletons=false;
4909 }
4910 }
4911 }
4912#endif
4913 }
4914#ifdef MOVE_SINGLETONS
4915 if (moveSingletons) {
4916 // can fix any with good costs
4917 for (int kk =rowStart[irow];kk<rowStart[irow+1];
4918 kk++) {
4919 int iColumn = column[kk];
4920 if (j!=iColumn) {
4921 if (colUpper[iColumn]>colLower[iColumn]) {
4922 if (columnLength2[iColumn]==1) {
4923 double value = rowElements[kk];
4924 if (direction*objective[iColumn]*value>0.0&&!(markC[iColumn]&3)) {
4925 // Fix
4926 if (nstackC0+1<maxStack) {
4927 stackC0[nstackC0]=iColumn;
4928 if (value<0.0) {
4929 lo0[nstackC0]=colUpper[iColumn];
4930 up0[nstackC0]=colUpper[iColumn];
4931 } else {
4932 lo0[nstackC0]=colLower[iColumn];
4933 up0[nstackC0]=colLower[iColumn];
4934 }
4935 nstackC0++;
4936 }
4937 }
4938 }
4939 }
4940 }
4941 }
4942 }
4943#endif
4944 if (sum+gap*colsol[j]<minR[irow]-primalTolerance_||(info->strengthenRow&&rowUpper[irow]>1.0e20)) {
4945 // can be a cut
4946 // add gap to lower and integer coefficient
4947 // saveU and saveL spare
4948 int * index = reinterpret_cast<int *>(saveL);
4949 double * element = saveU;
4950 int n=0;
4951 bool coefficientExists=false;
4952 double sum2=0.0;
4953 for (int kk =rowStart[irow];kk<rowStart[irow+1];
4954 kk++) {
4955 int kColumn = column[kk];
4956 double el = rowElements[kk];
4957 if (kColumn!=j) {
4958 index[n]=kColumn;
4959 element[n++]=el;
4960 } else {
4961 el=el+gap;
4962 if (fabs(el)>1.0e-12) {
4963 index[n]=kColumn;
4964 element[n++]=el;
4965 }
4966 coefficientExists=true;
4967 }
4968 sum2 += colsol[kColumn]*el;
4969 }
4970 if (!coefficientExists) {
4971 index[n]=j;
4972 element[n++]=gap;
4973 sum2 += colsol[j]*gap;
4974 }
4975 OsiRowCut rc;
4976 double lb = rowLower[irow]+gap*(colLower[j]+1.0);
4977 rc.setLb(lb);
4978 rc.setUb(COIN_DBL_MAX);
4979 // effectiveness
4980 double effectiveness=lb-sum2;
4981 effectiveness = CoinMax(effectiveness,
4982 (minR[irow]-
4983 sum-gap*colsol[j])/gap);
4984 if (!coefficientExists)
4985 effectiveness=CoinMax(1.0e-7,
4986 effectiveness);
4987 rc.setEffectiveness(effectiveness);
4988 if (rc.effectiveness()>needEffectiveness) {
4989 rc.setRow(n,index,element,false);
4990#ifdef CGL_DEBUG
4991 if (debugger) assert(!debugger->invalidCut(rc))(static_cast<void> (0));
4992#endif
4993 //if(info->strengthenRow)
4994 //printf("b point to row %d\n",irow);
4995#ifdef STRENGTHEN_PRINT
4996 if (canReplace&&rowUpper[irow]>1.0e20) {
4997 printf("2Cut %g <= ",rc.lb());
4998 int k;
4999 for ( k=0;k<n;k++) {
5000 int iColumn = index[k];
5001 printf("%g*",element[k]);
5002 if (si.isInteger(iColumn))
5003 printf("i%d ",iColumn);
5004 else
5005 printf("x%d ",iColumn);
5006 }
5007 printf("<= %g\n",rc.ub());
5008 printf("Row %g <= ",rowLower[irow]);
5009 for (k=rowStart[irow];k<rowStart[irow+1];k++) {
5010 int iColumn = column[k];
5011 printf("%g*",rowElements[k]);
5012 if (si.isInteger(iColumn))
5013 printf("i%d ",iColumn);
5014 else
5015 printf("x%d ",iColumn);
5016 }
5017 printf("<= %g\n",rowUpper[irow]);
5018 }
5019#endif
5020 int realRow = (canReplace&&rowUpper[irow]>1.0e20) ? irow : -1;
5021 if (realRows&&realRow>=0)
5022 realRow=realRows[realRow];
5023 if (!justReplace) {
5024 rowCut.addCutIfNotDuplicate(rc,realRow);
5025 } else if (realRow>=0) {
5026 double effectiveness=0.0;
5027 for (int i=0;i<n;i++)
5028 effectiveness+=fabs(element[i]);
5029 if (!info->strengthenRow[realRow]||info->strengthenRow[realRow]->effectiveness()>effectiveness) {
5030 delete info->strengthenRow[realRow];
5031 rc.setEffectiveness(effectiveness);
5032 info->strengthenRow[realRow]=rc.clone();
5033 }
5034 }
5035 }
5036 }
5037 }
5038 }
5039 minR[irow]=saveMin[istackR];
5040 maxR[irow]=saveMax[istackR];
5041 markR[irow]=-1;
5042 }
5043 } else {
5044 if (iway==1&&feasible==3) {
5045 iway=3;
5046#ifdef MOVE_SINGLETONS
5047 // look for singletons that can move (just at root)
5048 if ((rowCuts&2)!=0&&goingToTrueBound&&info->strengthenRow) {
5049 for (istackR=0;istackR<nstackR;istackR++) {
5050 int irow=stackR[istackR];
5051 double gap = rowUpper[irow]-maxR[irow];
5052 if (gap>primalTolerance_) {
5053 // also see if singletons can go to good objective
5054 bool moveSingletons=true;
5055 for (int kk =rowStart[irow];kk<rowStart[irow+1];
5056 kk++) {
5057 int iColumn = column[kk];
5058 if (moveSingletons&&j!=iColumn) {
5059 if (colUpper[iColumn]>colLower[iColumn]) {
5060 if (columnLength2[iColumn]!=1) {
5061 moveSingletons=false;
5062 }
5063 }
5064 }
5065 }
5066 if (moveSingletons) {
5067 // can fix any with good costs
5068 for (int kk =rowStart[irow];kk<rowStart[irow+1];
5069 kk++) {
5070 int iColumn = column[kk];
5071 if (j!=iColumn) {
5072 if (colUpper[iColumn]>colLower[iColumn]) {
5073 if (columnLength2[iColumn]==1) {
5074 double value = rowElements[kk];
5075 if (direction*objective[iColumn]*value<0.0&&!(markC[iColumn]&3)) {
5076 // Fix
5077 stackC[nstackC]=iColumn;
5078 saveL[nstackC]=colLower[iColumn];
5079 saveU[nstackC]=colUpper[iColumn];
5080 assert (saveU[nstackC]>saveL[nstackC])(static_cast<void> (0));
5081 if (value>0.0) {
5082 colLower[iColumn]=colUpper[iColumn];
5083 } else {
5084 colUpper[iColumn]=colLower[iColumn];
5085 }
5086 columnGap[iColumn] = -primalTolerance_;
5087 assert (nstackC<nCols)(static_cast<void> (0));
5088 nstackC++;
5089 }
5090 }
5091 }
5092 }
5093 }
5094 }
5095 }
5096 gap = minR[irow]-rowLower[irow];
5097 if (gap>primalTolerance_) {
5098 // also see if singletons can go to good objective
5099 bool moveSingletons=true;
5100 for (int kk =rowStart[irow];kk<rowStart[irow+1];
5101 kk++) {
5102 int iColumn = column[kk];
5103 if (moveSingletons&&j!=iColumn) {
5104 if (colUpper[iColumn]>colLower[iColumn]) {
5105 if (columnLength2[iColumn]!=1) {
5106 moveSingletons=false;
5107 }
5108 }
5109 }
5110 }
5111 if (moveSingletons) {
5112 // can fix any with good costs
5113 for (int kk =rowStart[irow];kk<rowStart[irow+1];
5114 kk++) {
5115 int iColumn = column[kk];
5116 if (j!=iColumn) {
5117 if (colUpper[iColumn]>colLower[iColumn]) {
5118 if (columnLength2[iColumn]==1) {
5119 double value = rowElements[kk];
5120 if (direction*objective[iColumn]*value>0.0&&!(markC[iColumn]&3)) {
5121 // Fix
5122 stackC[nstackC]=iColumn;
5123 saveL[nstackC]=colLower[iColumn];
5124 saveU[nstackC]=colUpper[iColumn];
5125 assert (saveU[nstackC]>saveL[nstackC])(static_cast<void> (0));
5126 if (value<0.0) {
5127 colLower[iColumn]=colUpper[iColumn];
5128 } else {
5129 colUpper[iColumn]=colLower[iColumn];
5130 }
5131 columnGap[iColumn] = -primalTolerance_;
5132 assert (nstackC<nCols)(static_cast<void> (0));
5133 nstackC++;
5134 }
5135 }
5136 }
5137 }
5138 }
5139 }
5140 }
5141 }
5142 }
5143#endif
5144 /* point back to stack */
5145 for (istackC=nstackC-1;istackC>=0;istackC--) {
5146 int icol=stackC[istackC];
5147 markC[icol]=istackC+1000;
5148 }
5149 OsiColCut cc;
5150 int nTot=0,nFix=0,nInt=0;
5151 bool ifCut=false;
5152 for (istackC=1;istackC<nstackC0;istackC++) {
5153 int icol=stackC0[istackC];
5154 int istackC1=markC[icol]-1000;
5155 if (istackC1>=0) {
5156 if (CoinMin(lo0[istackC],colLower[icol])>saveL[istackC1]+1.0e-4) {
5157 saveL[istackC1]=CoinMin(lo0[istackC],colLower[icol]);
5158 if (intVar[icol]/*||!info->inTree*/) {
5159 element[nFix]=saveL[istackC1];
5160 index[nFix++]=icol;
5161 nInt++;
5162 if (colsol[icol]<saveL[istackC1]-primalTolerance_)
5163 ifCut=true;
5164 }
5165 nfixed++;
5166 }
5167 }
5168 }
5169 if (nFix) {
5170 nTot=nFix;
5171 cc.setLbs(nFix,index,element);
5172 nFix=0;
5173 }
5174 for (istackC=1;istackC<nstackC0;istackC++) {
5175 int icol=stackC0[istackC];
5176 int istackC1=markC[icol]-1000;
5177 if (istackC1>=0) {
5178 if (CoinMax(up0[istackC],colUpper[icol])<saveU[istackC1]-1.0e-4) {
5179 saveU[istackC1]=CoinMax(up0[istackC],colUpper[icol]);
5180 if (intVar[icol]/*||!info->inTree*/) {
5181 element[nFix]=saveU[istackC1];
5182 index[nFix++]=icol;
5183 nInt++;
5184 if (colsol[icol]>saveU[istackC1]+primalTolerance_)
5185 ifCut=true;
5186 }
5187 nfixed++;
5188 } else if (!info->inTree&&saveL[0]==0.0&&saveU[0]==1.0) {
5189 // See if can do two cut
5190 double upperWhenDown = up0[istackC];
5191 double lowerWhenDown = lo0[istackC];
5192 double upperWhenUp = colUpper[icol];
5193 double lowerWhenUp = colLower[icol];
5194 double upperOriginal = saveU[istackC1];
5195 double lowerOriginal = saveL[istackC1];
5196 if (upperWhenDown<lowerOriginal+1.0e-12&&lowerWhenUp>upperOriginal-1.0e-12) {
5197 OsiRowCut rc;
5198 rc.setLb(lowerOriginal);
5199 rc.setUb(lowerOriginal);
5200 rc.setEffectiveness(1.0e-5);
5201 int index[2];
5202 double element[2];
5203 index[0]=j;
5204 index[1]=icol;
5205 element[0]=-(upperOriginal-lowerOriginal);
5206 // If zero then - must have been fixed without noticing!
5207 if (fabs(element[0])>1.0e-8) {
5208 element[1]=1.0;
5209 rc.setRow(2,index,element,false);
5210 cs.insert(rc);
5211 }
5212 } else if (upperWhenUp<lowerOriginal+1.0e-12&&lowerWhenDown>upperOriginal-1.0e-12) {
5213 OsiRowCut rc;
5214 rc.setLb(upperOriginal);
5215 rc.setUb(upperOriginal);
5216 rc.setEffectiveness(1.0e-5);
5217 int index[2];
5218 double element[2];
5219 index[0]=j;
5220 index[1]=icol;
5221 element[0]=upperOriginal-lowerOriginal;
5222 element[1]=1.0;
5223 rc.setRow(2,index,element,false);
5224 cs.insert(rc);
5225 }
5226 }
5227 }
5228 }
5229 if (nFix) {
5230 nTot+=nFix;
5231 cc.setUbs(nFix,index,element);
5232 }
5233 // could tighten continuous as well
5234 if (nInt) {
5235 if (ifCut) {
5236 cc.setEffectiveness(100.0);
5237 } else {
5238 cc.setEffectiveness(1.0e-5);
5239 }
5240#ifdef CGL_DEBUG
5241 checkBounds(debugger,cc);
5242#endif
5243 cs.insert(cc);
5244 }
5245 } else {
5246 goingToTrueBound=0;
5247 }
5248 double solMove = up-saveSolval;
5249 double boundChange;
5250 /* restore all */
5251 for (istackC=nstackC-1;istackC>=0;istackC--) {
5252 int icol=stackC[istackC];
5253 double oldU=saveU[istackC];
5254 double oldL=saveL[istackC];
5255 if(goingToTrueBound==2&&istackC&&!justReplace) {
5256 // upper disaggregation cut would be
5257 // xval < upper + (old_upper-upper) (up-jval)
5258 boundChange = oldU-colUpper[icol];
5259 if (boundChange>0.0&&oldU<1.0e10&&
5260 (colsol[icol]>colUpper[icol]
5261 + boundChange*solMove+primalTolerance_)) {
5262 // create cut
5263 OsiRowCut rc;
5264 rc.setLb(-COIN_DBL_MAX);
5265 rc.setUb(colUpper[icol]+up*boundChange);
5266 index[0]=icol;
5267 element[0]=1.0;
5268 index[1]=j;
5269 element[1]= + boundChange;
5270 // effectiveness is how far j moves
5271 double newSol = (colsol[icol]-colUpper[icol])/
5272 boundChange;
5273 assert(newSol>solMove)(static_cast<void> (0));
5274 rc.setEffectiveness(newSol-solMove);
5275 if (rc.effectiveness()>disaggEffectiveness) {
5276 rc.setRow(2,index,element,false);
5277#ifdef CGL_DEBUG
5278 if (debugger) assert(!debugger->invalidCut(rc))(static_cast<void> (0));
5279#endif
5280 rowCut.addCutIfNotDuplicate(rc);
5281 }
5282 }
5283 // lower disaggregation cut would be
5284 // xval > lower + (old_lower-lower) (up-jval)
5285 boundChange = oldL-colLower[icol];
5286 if (boundChange<0.0&&oldL>-1.0e10&&
5287 (colsol[icol]<colLower[icol]
5288 + boundChange*solMove-primalTolerance_)) {
5289 // create cut
5290 OsiRowCut rc;
5291 rc.setLb(colLower[icol]+up*boundChange);
5292 rc.setUb(COIN_DBL_MAX);
5293 index[0]=icol;
5294 element[0]=1.0;
5295 index[1]=j;
5296 element[1]= + boundChange;
5297 // effectiveness is how far j moves
5298 double newSol = (colsol[icol]-colLower[icol])/
5299 boundChange;
5300 assert(newSol>solMove)(static_cast<void> (0));
5301 rc.setEffectiveness(newSol-solMove);
5302 if (rc.effectiveness()>disaggEffectiveness) {
5303 rc.setRow(2,index,element,false);
5304#ifdef CGL_DEBUG
5305 if (debugger) assert(!debugger->invalidCut(rc))(static_cast<void> (0));
5306#endif
5307 rowCut.addCutIfNotDuplicate(rc);
5308 }
5309 }
5310 }
5311 colUpper[icol]=oldU;
5312 colLower[icol]=oldL;
5313 columnGap[icol] = oldU-oldL-primalTolerance_;
5314 if (oldU>oldL+1.0e-4) {
5315 markC[icol]=0;
5316 if (oldU>1.0e10)
5317 markC[icol] |= 8;
5318 if (oldL<-1.0e10)
5319 markC[icol] |= 4;
5320 } else {
5321 markC[icol]=3;
5322 }
5323 }
5324 for (istackR=0;istackR<nstackR;istackR++) {
5325 int irow=stackR[istackR];
5326 // switch off strengthening if not wanted
5327 if ((rowCuts&2)!=0&&goingToTrueBound) {
5328 bool canReplace = info->strengthenRow&&(goingToTrueBound==2);
5329 bool ifCut=anyColumnCuts;
5330 double gap = rowUpper[irow]-maxR[irow];
5331 double sum=0.0;
5332 if (!ifCut&&(gap>primalTolerance_&&gap<1.0e8)) {
5333 // see if the strengthened row is a cut
5334 for (int kk =rowStart[irow];kk<rowStart[irow+1];
5335 kk++) {
5336 sum += rowElements[kk]*colsol[column[kk]];
5337 }
5338 if (sum+gap*colsol[j]>rowUpper[irow]+primalTolerance_||(canReplace&&rowLower[irow]<-1.e20)) {
5339 // can be a cut
5340 // add gap to integer coefficient
5341 // saveU and saveL spare
5342 int * index = reinterpret_cast<int *>(saveL);
5343 double * element = saveU;
5344 int n=0;
5345 bool coefficientExists=false;
5346 double sum2=0.0;
5347 for (int kk =rowStart[irow];kk<rowStart[irow+1];
5348 kk++) {
5349 int kColumn = column[kk];
5350 double el = rowElements[kk];
5351 if (kColumn!=j) {
5352 index[n]=kColumn;
5353 element[n++]=el;
5354 } else {
5355 el=el+gap;
5356 if (fabs(el)>1.0e-12) {
5357 index[n]=kColumn;
5358 element[n++]=el;
5359 }
5360 coefficientExists=true;
5361 }
5362 sum2 += colsol[kColumn]*el;
5363 }
5364 if (!coefficientExists) {
5365 index[n]=j;
5366 element[n++]=gap;
5367 sum2 += colsol[j]*gap;
5368 }
5369 OsiRowCut rc;
5370 rc.setLb(-COIN_DBL_MAX);
5371 double ub = rowUpper[irow]+gap*(colUpper[j]-1.0);
5372 rc.setUb(ub);
5373 // effectiveness
5374 double effectiveness=sum2-ub;
5375 effectiveness = CoinMax(effectiveness,
5376 (sum+gap*colsol[j]-
5377 rowUpper[irow])/gap);
5378 if (!coefficientExists)
5379 effectiveness=CoinMax(1.0e-7,
5380 effectiveness);
5381 rc.setEffectiveness(effectiveness);
5382 if (rc.effectiveness()>needEffectiveness) {
5383 rc.setRow(n,index,element,false);
5384#ifdef CGL_DEBUG
5385 if (debugger) assert(!debugger->invalidCut(rc))(static_cast<void> (0));
5386#endif
5387 //if(canReplace)
5388 //printf("c point to row %d\n",irow);
5389#ifdef STRENGTHEN_PRINT
5390 if (canReplace&&rowLower[irow]<-1.0e20) {
5391 printf("3Cut %g <= ",rc.lb());
5392 int k;
5393 for ( k=0;k<n;k++) {
5394 int iColumn = index[k];
5395 printf("%g*",element[k]);
5396 if (si.isInteger(iColumn))
5397 printf("i%d ",iColumn);
5398 else
5399 printf("x%d ",iColumn);
5400 }
5401 printf("<= %g\n",rc.ub());
5402 printf("Row %g <= ",rowLower[irow]);
5403 for (k=rowStart[irow];k<rowStart[irow+1];k++) {
5404 int iColumn = column[k];
5405 printf("%g*",rowElements[k]);
5406 if (si.isInteger(iColumn))
5407 printf("i%d ",iColumn);
5408 else
5409 printf("x%d ",iColumn);
5410 }
5411 printf("<= %g\n",rowUpper[irow]);
5412 }
5413#endif
5414 int realRow = (canReplace&&rowLower[irow]<-1.0e20) ? irow : -1;
5415 if (realRows&&realRow>=0)
5416 realRow=realRows[realRow];
5417 if (!justReplace) {
5418 rowCut.addCutIfNotDuplicate(rc,realRow);
5419 } else if (realRow>=0) {
5420 double effectiveness=0.0;
5421 for (int i=0;i<n;i++)
5422 effectiveness+=fabs(element[i]);
5423 if (!info->strengthenRow[realRow]||info->strengthenRow[realRow]->effectiveness()>effectiveness) {
5424 delete info->strengthenRow[realRow];
5425 rc.setEffectiveness(effectiveness);
5426 info->strengthenRow[realRow]=rc.clone();
5427 }
5428 }
5429 }
5430 }
5431 }
5432 gap = minR[irow]-rowLower[irow];
5433 if (!ifCut&&(gap>primalTolerance_&&gap<1.0e8)) {
5434 // see if the strengthened row is a cut
5435 if (!sum) {
5436 for (int kk =rowStart[irow];kk<rowStart[irow+1];
5437 kk++) {
5438 sum += rowElements[kk]*colsol[column[kk]];
5439 }
5440 }
5441 if (sum-gap*colsol[j]<rowLower[irow]-primalTolerance_||(canReplace&&rowUpper[irow]>1.0e20)) {
5442 // can be a cut
5443 // subtract gap from integer coefficient
5444 // saveU and saveL spare
5445 int * index = reinterpret_cast<int *>(saveL);
5446 double * element = saveU;
5447 int n=0;
5448 bool coefficientExists=false;
5449 double sum2=0.0;
5450 for (int kk =rowStart[irow];kk<rowStart[irow+1];
5451 kk++) {
5452 int kColumn = column[kk];
5453 double el = rowElements[kk];
5454 if (kColumn!=j) {
5455 index[n]=kColumn;
5456 element[n++]=el;
5457 } else {
5458 el=el-gap;
5459 if (fabs(el)>1.0e-12) {
5460 index[n]=kColumn;
5461 element[n++]=el;
5462 }
5463 coefficientExists=true;
5464 }
5465 sum2 += colsol[kColumn]*el;
5466 }
5467 if (!coefficientExists) {
5468 index[n]=j;
5469 element[n++]=-gap;
5470 sum2 -= colsol[j]*gap;
5471 }
5472 OsiRowCut rc;
5473 double lb = rowLower[irow]-gap*(colUpper[j]-1);
5474 rc.setLb(lb);
5475 rc.setUb(COIN_DBL_MAX);
5476 double effectiveness=lb-sum2;
5477 effectiveness = CoinMax(effectiveness,
5478 (rowLower[irow]-
5479 sum+gap*colsol[j])/gap);
5480 if (!coefficientExists)
5481 effectiveness=CoinMax(1.0e-7,
5482 effectiveness);
5483 rc.setEffectiveness(effectiveness);
5484 if (rc.effectiveness()>needEffectiveness) {
5485 rc.setRow(n,index,element,false);
5486#ifdef CGL_DEBUG
5487 if (debugger) assert(!debugger->invalidCut(rc))(static_cast<void> (0));
5488#endif
5489 //if(canReplace)
5490 //printf("d point to row %d\n",irow);
5491#ifdef STRENGTHEN_PRINT
5492 if (canReplace&&rowUpper[irow]>1.0e20) {
5493 printf("4Cut %g <= ",rc.lb());
5494 int k;
5495 for ( k=0;k<n;k++) {
5496 int iColumn = index[k];
5497 printf("%g*",element[k]);
5498 if (si.isInteger(iColumn))
5499 printf("i%d ",iColumn);
5500 else
5501 printf("x%d ",iColumn);
5502 }
5503 printf("<= %g\n",rc.ub());
5504 printf("Row %g <= ",rowLower[irow]);
5505 for (k=rowStart[irow];k<rowStart[irow+1];k++) {
5506 int iColumn = column[k];
5507 printf("%g*",rowElements[k]);
5508 if (si.isInteger(iColumn))
5509 printf("i%d ",iColumn);
5510 else
5511 printf("x%d ",iColumn);
5512 }
5513 printf("<= %g\n",rowUpper[irow]);
5514 }
5515#endif
5516 int realRow = (canReplace&&rowUpper[irow]>1.0e20) ? irow : -1;
5517 if (realRows&&realRow>=0)
5518 realRow=realRows[realRow];
5519 if (!justReplace) {
5520 rowCut.addCutIfNotDuplicate(rc,realRow);
5521 } else if (realRow>=0) {
5522 double effectiveness=0.0;
5523 for (int i=0;i<n;i++)
5524 effectiveness+=fabs(element[i]);
5525 if (!info->strengthenRow[realRow]||info->strengthenRow[realRow]->effectiveness()>effectiveness) {
5526 delete info->strengthenRow[realRow];
5527 rc.setEffectiveness(effectiveness);
5528 info->strengthenRow[realRow]=rc.clone();
5529 }
5530 }
5531 }
5532 }
5533 }
5534 }
5535 minR[irow]=saveMin[istackR];
5536 maxR[irow]=saveMax[istackR];
5537 markR[irow]=-1;
5538 }
5539 }
5540 }
5541 }
5542 }
5543 }
5544 if ((!ninfeas&&!rowCut.outOfSpace())&&(info->strengthenRow||
5545 !rowCut.numberCuts())&&rowCuts) {
5546 // Try and find ALL big M's
5547 for (int i = 0; i < nRowsSafe; ++i) {
5548 if ((rowLower[i]>-1.0e20||rowUpper[i]<1.0e20)&&
5549 (!info->strengthenRow||!info->strengthenRow[i])) {
5550 int iflagu = 0;
5551 int iflagl = 0;
5552 double dmaxup = 0.0;
5553 double dmaxdown = 0.0;
5554 int krs = rowStart[i];
5555 int kre = rowStart[i+1];
5556 int kInt = -1;
5557 double rhsAdjustment=0.0;
5558 int nPosInt=0;
5559 int nNegInt=0;
5560 double valueInteger=0.0;
5561 // Find largest integer coefficient
5562 int k;
5563 for ( k = krs; k < kre; ++k) {
5564 int j = column[k];
5565 if (intVar[j]) {
5566 double value=rowElements[k];
5567 if (colUpper[j]>colLower[j]&&!colLower[j]&&
5568 fabs(value)>fabs(valueInteger)) {
5569 kInt=j;
5570 valueInteger=value;
5571 }
5572 }
5573 }
5574 if (kInt>=0) {
5575 double upperBound = CoinMin(colUpper[kInt],static_cast<double>(COIN_INT_MAX));
5576 double upAdjust=0.0;
5577 double downAdjust=0.0;
5578 for (k = krs; k < kre; ++k) {
5579 double value=rowElements[k];
5580 int j = column[k];
5581 if (colUpper[j]==colLower[j]) {
5582 rhsAdjustment += colUpper[j]*value;
5583 continue;
5584 }
5585 if (intVar[j]) {
5586 if (value>0.0)
5587 nPosInt++;
5588 else
5589 nNegInt++;
5590 } else {
5591 nPosInt = -nCols;
5592 }
5593 if (j!=kInt) {
5594 // treat as continuous
5595 if (value > 0.0) {
5596 if (colUpper[j] >= 1e15) {
5597 dmaxup = 1e31;
5598 ++iflagu;
5599 } else {
5600 dmaxup += colUpper[j] * value;
5601 }
5602 if (colLower[j] <= -1e15) {
5603 dmaxdown = -1e31;
5604 ++iflagl;
5605 } else {
5606 dmaxdown += colLower[j] * value;
5607 }
5608 } else if (value<0.0) {
5609 if (colUpper[j] >= 1e15) {
5610 dmaxdown = -1e31;
5611 ++iflagl;
5612 } else {
5613 dmaxdown += colUpper[j] * value;
5614 }
5615 if (colLower[j] <= -1e15) {
5616 dmaxup = 1e31;
5617 ++iflagu;
5618 } else {
5619 dmaxup += colLower[j] * value;
5620 }
5621 }
5622 } else {
5623 // Chosen variable
5624 if (value > 0.0) {
5625 if (colUpper[j] >= 1e15) {
5626 upAdjust = 1e31;
5627 } else {
5628 upAdjust = colUpper[j] * value;
5629 }
5630 if (colLower[j] <= -1e15) {
5631 downAdjust = -1e31;
5632 } else {
5633 downAdjust = colLower[j] * value;
5634 }
5635 } else if (value<0.0) {
5636 if (colUpper[j] >= 1e15) {
5637 downAdjust = -1e31;
5638 } else {
5639 downAdjust = colUpper[j] * value;
5640 }
5641 if (colLower[j] <= -1e15) {
5642 upAdjust = 1e31;
5643 } else {
5644 upAdjust = colLower[j] * value;
5645 }
5646 }
5647 }
5648 }
5649 dmaxup += rhsAdjustment;
5650 dmaxdown += rhsAdjustment;
5651 // end of row
5652 if (iflagu)
5653 dmaxup=1.0e31;
5654 if (iflagl)
5655 dmaxdown=-1.0e31;
5656 // See if redundant
5657 if (dmaxdown+downAdjust>rowLower[i]-tolerance&&
5658 dmaxup+upAdjust<rowUpper[i]+tolerance)
5659 continue;
5660 if (dmaxdown+valueInteger*upperBound>rowLower[i]&&
5661 dmaxup+valueInteger*upperBound<rowUpper[i]) {
5662 // check to see if always feasible at 1 but not always at 0
5663 if (dmaxdown+valueInteger>rowLower[i]&&dmaxup+valueInteger<rowUpper[i]&&
5664 (dmaxdown<rowLower[i]-primalTolerance_||dmaxup>rowUpper[i]+primalTolerance_)) {
5665 // can tighten (maybe)
5666 double saveValue = valueInteger;
5667 if (valueInteger>0.0) {
5668 assert (dmaxdown<rowLower[i])(static_cast<void> (0));
5669 valueInteger = rowLower[i]-dmaxdown;
5670 } else {
5671 assert (dmaxup>rowUpper[i])(static_cast<void> (0));
5672 valueInteger = rowUpper[i]-dmaxup;
5673 }
5674 if (fabs(saveValue-valueInteger)>1.0e-12) {
5675 // take
5676 OsiRowCut rc;
5677 rc.setLb(rowLower[i]);
5678 rc.setUb(rowUpper[i]);
5679 int n=0;
5680 double sum=0.0;
5681 for (int kk=rowStart[i];kk<rowStart[i+1];kk++) {
5682 int j=column[kk];
5683 if (j!=kInt) {
5684 sum += colsol[j]*rowElements[kk];
5685 index[n]=j;
5686 element[n++]=rowElements[kk];
5687 } else {
5688 sum += colsol[j]*valueInteger;
5689 assert (rowElements[kk]*valueInteger>=0.0)(static_cast<void> (0));
5690#if 0
5691 if (fabs(rowElements[kk])>1.01*fabs(valueInteger)) {
5692 printf("row %d changing coefficient of %d from %g to %g\n",
5693 i,kInt,rowElements[kk],valueInteger);
5694 }
5695#endif
5696 if (fabs(valueInteger)>1.0e-12) {
5697 index[n]=column[kk];
5698 element[n++]=valueInteger;
5699 }
5700 }
5701 }
5702 double gap = 0.0;
5703 if (sum<rowLower[i])
5704 gap=rowLower[i]-sum;
5705 else if (sum>rowUpper[i])
5706 gap=sum-rowUpper[i];
5707 if (gap>1.0e-4||info->strengthenRow!=NULL__null) {
5708 gap += 1.0e5;
5709 rc.setEffectiveness(gap);
5710 rc.setRow(n,index,element,false);
5711#ifdef STRENGTHEN_PRINT
5712 {
5713 printf("1aCut %g <= ",rc.lb());
5714 int irow =i;
5715 int k;
5716 for ( k=0;k<n;k++) {
5717 int iColumn = index[k];
5718 printf("%g*",element[k]);
5719 if (si.isInteger(iColumn))
5720 printf("i%d ",iColumn);
5721 else
5722 printf("x%d ",iColumn);
5723 }
5724 printf("<= %g\n",rc.ub());
5725 printf("Row %g <= ",rowLower[irow]);
5726 for (k=rowStart[irow];k<rowStart[irow+1];k++) {
5727 int iColumn = column[k];
5728 printf("%g*",rowElements[k]);
5729 if (si.isInteger(iColumn))
5730 printf("i%d ",iColumn);
5731 else
5732 printf("x%d ",iColumn);
5733 }
5734 printf("<= %g\n",rowUpper[irow]);
5735 }
5736#endif
5737 int returnCode=rowCut.addCutIfNotDuplicate(rc,i);
5738 if (returnCode<0)
5739 break; // out of space
5740 }
5741 }
5742 }
5743 }
5744 }
5745 }
5746 }
5747 }
5748#ifndef ONE_ARRAY
5749 delete [] stackC0;
5750 delete [] lo0;
5751 delete [] up0;
5752 delete [] columnGap;
5753 delete [] markC;
5754 delete [] stackC;
5755 delete [] stackR;
5756 delete [] saveL;
5757 delete [] saveU;
5758 delete [] saveMin;
5759 delete [] saveMax;
5760 delete [] index;
5761 delete [] element;
5762 delete [] djs;
5763 delete [] largestPositiveInRow;
5764 delete [] largestNegativeInRow;
5765#endif
5766 delete [] colsol;
5767 // Add in row cuts
5768 if (!ninfeas) {
5769 if (!justReplace) {
5770 rowCut.addCuts(cs,info->strengthenRow,info->pass);
5771 } else {
5772 for (int i=0;i<nRows;i++) {
5773 int realRow=realRows[i];
5774 if (realRow>=0) {
5775 OsiRowCut * cut = info->strengthenRow[realRow];
5776 if (cut) {
5777#ifdef CLP_INVESTIGATE
5778 printf("Row %d, real row %d effectiveness %g\n",i,realRow,cut->effectiveness());
5779#endif
5780 cs.insert(cut);
5781 }
5782 }
5783 }
5784 }
5785 }
5786#if 0
5787 {
5788 int numberRowCutsAfter = cs.sizeRowCuts() ;
5789 int k ;
5790 for (k = 0;k<numberRowCutsAfter;k++) {
5791 OsiRowCut thisCut = cs.rowCut(k) ;
5792 printf("Cut %d is %g <=",k,thisCut.lb());
5793 int n=thisCut.row().getNumElements();
5794 const int * column = thisCut.row().getIndices();
5795 const double * element = thisCut.row().getElements();
5796 assert (n)(static_cast<void> (0));
5797 for (int i=0;i<n;i++) {
5798 printf(" %g*x%d",element[i],column[i]);
5799 }
5800 printf(" <= %g\n",thisCut.ub());
5801 }
5802 }
5803#endif
5804 return (ninfeas);
5805}
5806// Does probing and adding cuts
5807int CglProbing::probeCliques( const OsiSolverInterface & si,
5808 const OsiRowCutDebugger *
5809#ifdef CGL_DEBUG
5810 debugger
5811#endif
5812 ,OsiCuts & cs,
5813 double * colLower, double * colUpper,
5814 CoinPackedMatrix *rowCopy,
5815 CoinPackedMatrix *columnCopy, const int * realRows,
5816 double * rowLower, double * rowUpper,
5817 char * intVar, double * minR, double * maxR,
5818 int * markR,
5819 CglTreeInfo * info)
5820{
5821 // Set up maxes
5822 int maxStack = info->inTree ? maxStack_ : maxStackRoot_;
5823 int nRows=rowCopy->getNumRows();
5824 int nCols=rowCopy->getNumCols();
5825 double * colsol = new double[nCols];
5826 double * djs = new double[nCols];
5827 const double * currentColLower = si.getColLower();
5828 const double * currentColUpper = si.getColUpper();
5829 double * tempL = new double [nCols];
5830 double * tempU = new double [nCols];
5831 int * markC = new int [nCols];
5832 int * stackC = new int [2*nCols];
5833 int * stackR = new int [nRows];
5834 double * saveL = new double [2*nCols];
5835 double * saveU = new double [2*nCols];
5836 double * saveMin = new double [nRows];
5837 double * saveMax = new double [nRows];
5838 double * element = new double[nCols];
5839 int * index = new int[nCols];
5840 // For trying to extend cliques
5841 int * cliqueStack=NULL__null;
5842 int * cliqueCount=NULL__null;
5843 int * to_01=NULL__null;
5844 if (!mode_) {
5845 to_01 = new int[nCols];
5846 cliqueStack = new int[numberCliques_];
5847 cliqueCount = new int[numberCliques_];
5848 int i;
5849 for (i=0;i<numberCliques_;i++) {
5850 cliqueCount[i]=cliqueStart_[i+1]-cliqueStart_[i];
5851 }
5852 for (i=0;i<nCols;i++)
5853 to_01[i]=-1;
5854 for (i=0;i<number01Integers_;i++) {
5855 int j=cutVector_[i].sequence;
5856 to_01[j]=i;
5857 }
5858 }
5859 // Let us never add more than twice the number of rows worth of row cuts
5860 // Keep cuts out of cs until end so we can find duplicates quickly
5861 int nRowsFake = info->inTree ? nRows/3 : nRows;
5862 row_cut rowCut(nRowsFake, !info->inTree);
5863 const int * column = rowCopy->getIndices();
5864 const CoinBigIndex * rowStart = rowCopy->getVectorStarts();
5865 const int * rowLength = rowCopy->getVectorLengths();
5866 const double * rowElements = rowCopy->getElements();
5867 const int * row = columnCopy->getIndices();
5868 const CoinBigIndex * columnStart = columnCopy->getVectorStarts();
5869 const int * columnLength = columnCopy->getVectorLengths();
5870 const double * columnElements = columnCopy->getElements();
5871 double movement;
5872 int i, j, k,kk,jj;
5873 int kcol,krow;
5874 bool anyColumnCuts=false;
5875 double dbound, value, value2;
5876 int ninfeas=0;
5877 int rowCuts;
5878 double disaggEffectiveness;
5879 if (mode_) {
5880 /* clean up djs and solution */
5881 CoinMemcpyN(si.getReducedCost(),nCols,djs);
5882 CoinMemcpyN( si.getColSolution(),nCols,colsol);
5883 disaggEffectiveness=1.0e-3;
5884 rowCuts=rowCuts_;
5885 } else {
5886 // need to go from a neutral place
5887 memset(djs,0,nCols*sizeof(double));
5888 CoinMemcpyN( si.getColSolution(),nCols,colsol);
5889 disaggEffectiveness=-1.0e10;
5890 if (rowCuts_!=4)
5891 rowCuts=1;
5892 else
5893 rowCuts=4;
5894 }
5895 for (i = 0; i < nCols; ++i) {
5896 /* was if (intVar[i]) */
5897 if (1) {
5898 if (colUpper[i]-colLower[i]>1.0e-8) {
5899 if (colsol[i]<colLower[i]+primalTolerance_) {
5900 colsol[i]=colLower[i];
5901 djs[i] = CoinMax(0.0,djs[i]);
5902 } else if (colsol[i]>colUpper[i]-primalTolerance_) {
5903 colsol[i]=colUpper[i];
5904 djs[i] = CoinMin(0.0,djs[i]);
5905 } else {
5906 djs[i]=0.0;
5907 }
5908 /*if (fabs(djs[i])<1.0e-5)
5909 djs[i]=0.0;*/
5910 }
5911 }
5912 }
5913
5914 int ipass=0,nfixed=-1;
5915
5916 double cutoff;
5917 bool cutoff_available = si.getDblParam(OsiDualObjectiveLimit,cutoff);
5918 if (!cutoff_available||usingObjective_<0) { // cut off isn't set or isn't valid
5919 cutoff = si.getInfinity();
5920 }
5921 cutoff *= si.getObjSense();
5922 if (fabs(cutoff)>1.0e30)
5923 assert (cutoff>1.0e30)(static_cast<void> (0));
5924 double current = si.getObjValue();
5925 // make irrelevant if mode is 0
5926 if (!mode_)
5927 cutoff=COIN_DBL_MAX;
5928 /* for both way coding */
5929 int nstackC0=-1;
5930 int * stackC0 = new int[maxStack];
5931 double * lo0 = new double[maxStack];
5932 double * up0 = new double[maxStack];
5933 int nstackR,nstackC;
5934 for (i=0;i<nCols;i++) {
5935 if (colUpper[i]-colLower[i]<1.0e-8) {
5936 markC[i]=3;
5937 } else {
5938 markC[i]=0;
5939 }
5940 }
5941 double tolerance = 1.0e1*primalTolerance_;
5942 int maxPass = info->inTree ? maxPass_ : maxPassRoot_;
5943 // If we are going to replace coefficient then we don't need to be effective
5944 double needEffectiveness = info->strengthenRow ? -1.0e10 : 1.0e-3;
5945 while (ipass<maxPass&&nfixed) {
5946 int iLook;
5947 ipass++;
5948 nfixed=0;
5949 for (iLook=0;iLook<numberThisTime_;iLook++) {
5950 double solval;
5951 double down;
5952 double up;
5953 j=lookedAt_[iLook];
5954 solval=colsol[j];
5955 down = floor(solval+tolerance);
5956 up = ceil(solval-tolerance);
5957 if(colUpper[j]-colLower[j]<1.0e-8) markC[j]=3;
5958 if (markC[j]||!intVar[j]) continue;
5959 double saveSolval = solval;
5960 if (solval>=colUpper[j]-tolerance||solval<=colLower[j]+tolerance||up==down) {
5961 if (solval<=colLower[j]+2.0*tolerance) {
5962 solval = colLower[j]+1.0e-1;
5963 down=colLower[j];
5964 up=down+1.0;
5965 } else if (solval>=colUpper[j]-2.0*tolerance) {
5966 solval = colUpper[j]-1.0e-1;
5967 up=colUpper[j];
5968 down=up-1;
5969 } else {
5970 // odd
5971 up=down+1.0;
5972 solval = down+1.0e-1;
5973 }
5974 }
5975 assert (up<=colUpper[j])(static_cast<void> (0));
5976 assert (down>=colLower[j])(static_cast<void> (0));
5977 assert (up>down)(static_cast<void> (0));
5978 if ((solval-down>1.0e-6&&up-solval>1.0e-6)||mode_!=1) {
5979 int istackC,iway, istackR;
5980 int way[]={1,2,1};
5981 int feas[]={1,2,4};
5982 int feasible=0;
5983 int notFeasible;
5984 for (iway=0;iway<3;iway ++) {
5985 int fixThis=0;
5986 double objVal=current;
5987 int goingToTrueBound=0;
5988 stackC[0]=j;
5989 markC[j]=way[iway];
5990 double solMovement;
5991 if (way[iway]==1) {
5992 movement=down-colUpper[j];
5993 solMovement = down-colsol[j];
5994 assert(movement<-0.99999)(static_cast<void> (0));
5995 if (fabs(down-colLower[j])<1.0e-7) {
5996 goingToTrueBound=2;
5997 down=colLower[j];
5998 }
5999 } else {
6000 movement=up-colLower[j];
6001 solMovement = up-colsol[j];
6002 assert(movement>0.99999)(static_cast<void> (0));
6003 if (fabs(up-colUpper[j])<1.0e-7) {
6004 goingToTrueBound=2;
6005 up=colUpper[j];
6006 }
6007 }
6008 if (goingToTrueBound&&(colUpper[j]-colLower[j]>1.5||colLower[j]))
6009 goingToTrueBound=1;
6010 // switch off disaggregation if not wanted
6011 if ((rowCuts&1)==0)
6012 goingToTrueBound=0;
6013#ifdef PRINT_DEBUG
6014 if (fabs(movement)>1.01) {
6015 printf("big %d %g %g %g\n",j,colLower[j],solval,colUpper[j]);
6016 }
6017#endif
6018 if (solMovement*djs[j]>0.0)
6019 objVal += solMovement*djs[j];
6020 nstackC=1;
6021 nstackR=0;
6022 saveL[0]=colLower[j];
6023 saveU[0]=colUpper[j];
6024 assert (saveU[0]>saveL[0])(static_cast<void> (0));
6025 notFeasible=0;
6026 if (movement<0.0) {
6027 colUpper[j] += movement;
6028 colUpper[j] = floor(colUpper[j]+0.5);
6029#ifdef PRINT_DEBUG
6030 printf("** Trying %d down to 0\n",j);
6031#endif
6032 } else {
6033 colLower[j] += movement;
6034 colLower[j] = floor(colLower[j]+0.5);
6035#ifdef PRINT_DEBUG
6036 printf("** Trying %d up to 1\n",j);
6037#endif
6038 }
6039 if (fabs(colUpper[j]-colLower[j])<1.0e-6)
6040 markC[j]=3; // say fixed
6041 istackC=0;
6042 /* update immediately */
6043 for (k=columnStart[j];k<columnStart[j]+columnLength[j];k++) {
6044 int irow = row[k];
6045 value = columnElements[k];
6046 assert (markR[irow]!=-2)(static_cast<void> (0));
6047 if (markR[irow]==-1) {
6048 stackR[nstackR]=irow;
6049 markR[irow]=nstackR;
6050 saveMin[nstackR]=minR[irow];
6051 saveMax[nstackR]=maxR[irow];
6052 nstackR++;
6053#if 0
6054 } else if (markR[irow]==-2) {
6055 continue;
6056#endif
6057 }
6058 /* could check immediately if violation */
6059 if (movement>0.0) {
6060 /* up */
6061 if (value>0.0) {
6062 /* up does not change - down does */
6063 if (minR[irow]>-1.0e10)
6064 minR[irow] += value;
6065 if (minR[irow]>rowUpper[irow]+1.0e-5) {
6066 notFeasible=1;
6067 istackC=1;
6068 break;
6069 }
6070 } else {
6071 /* down does not change - up does */
6072 if (maxR[irow]<1.0e10)
6073 maxR[irow] += value;
6074 if (maxR[irow]<rowLower[irow]-1.0e-5) {
6075 notFeasible=1;
6076 istackC=1;
6077 break;
6078 }
6079 }
6080 } else {
6081 /* down */
6082 if (value<0.0) {
6083 /* up does not change - down does */
6084 if (minR[irow]>-1.0e10)
6085 minR[irow] -= value;
6086 if (minR[irow]>rowUpper[irow]+1.0e-5) {
6087 notFeasible=1;
6088 istackC=1;
6089 break;
6090 }
6091 } else {
6092 /* down does not change - up does */
6093 if (maxR[irow]<1.0e10)
6094 maxR[irow] -= value;
6095 if (maxR[irow]<rowLower[irow]-1.0e-5) {
6096 notFeasible=1;
6097 istackC=1;
6098 break;
6099 }
6100 }
6101 }
6102 }
6103 while (istackC<nstackC&&nstackC<maxStack) {
6104 int jway;
6105 int jcol =stackC[istackC];
6106 jway=markC[jcol];
6107 // If not first and fixed then skip
6108 if (jway==3&&istackC) {
6109 //istackC++;
6110 //continue;
6111 //printf("fixed %d on stack\n",jcol);
6112 }
6113 // Do cliques
6114 if (oneFixStart_&&oneFixStart_[jcol]>=0) {
6115 int start;
6116 int end;
6117 if (colLower[jcol]>saveL[istackC]) {
6118 // going up
6119 start = oneFixStart_[jcol];
6120 end = zeroFixStart_[jcol];
6121 } else {
6122 assert (colUpper[jcol]<saveU[istackC])(static_cast<void> (0));
6123 // going down
6124 start = zeroFixStart_[jcol];
6125 end = endFixStart_[jcol];
6126 }
6127 for (int i=start;i<end;i++) {
6128 int iClique = whichClique_[i];
6129 for (int k=cliqueStart_[iClique];k<cliqueStart_[iClique+1];k++) {
6130 int kcol = sequenceInCliqueEntry(cliqueEntry_[k]);
6131 if (jcol==kcol)
6132 continue;
6133 int kway = oneFixesInCliqueEntry(cliqueEntry_[k]);
6134 if (kcol!=jcol) {
6135 if (!markC[kcol]) {
6136 // not on list yet
6137 if (nstackC<2*maxStack) {
6138 markC[kcol] = 3; // say fixed
6139 fixThis++;
6140 stackC[nstackC]=kcol;
6141 saveL[nstackC]=colLower[kcol];
6142 saveU[nstackC]=colUpper[kcol];
6143 assert (saveU[nstackC]>saveL[nstackC])(static_cast<void> (0));
6144 nstackC++;
6145 if (!kway) {
6146 // going up
6147 double solMovement=1.0-colsol[kcol];
6148 if (solMovement>0.0001) {
6149 assert (djs[kcol]>=0.0)(static_cast<void> (0));
6150 objVal += djs[kcol]*solMovement;
6151 }
6152 colLower[kcol]=1.0;
6153 /* update immediately */
6154 for (int jj =columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) {
6155 krow = row[jj];
6156 value = columnElements[jj];
6157 assert (markR[krow]!=-2)(static_cast<void> (0));
6158 if (markR[krow]==-1) {
6159 stackR[nstackR]=krow;
6160 markR[krow]=nstackR;
6161 saveMin[nstackR]=minR[krow];
6162 saveMax[nstackR]=maxR[krow];
6163 nstackR++;
6164#if 0
6165 } else if (markR[krow]==-2) {
6166 continue;
6167#endif
6168 }
6169 /* could check immediately if violation */
6170 /* up */
6171 if (value>0.0) {
6172 /* up does not change - down does */
6173 if (minR[krow]>-1.0e10)
6174 minR[krow] += value;
6175 if (minR[krow]>rowUpper[krow]+1.0e-5) {
6176 colUpper[kcol]=-1.0e50; /* force infeasible */
6177 break;
6178 }
6179 } else {
6180 /* down does not change - up does */
6181 if (maxR[krow]<1.0e10)
6182 maxR[krow] += value;
6183 if (maxR[krow]<rowLower[krow]-1.0e-5) {
6184 notFeasible=1;
6185 break;
6186 }
6187 }
6188 }
6189 } else {
6190 // going down
6191 double solMovement=0.0-colsol[kcol];
6192 if (solMovement<-0.0001) {
6193 assert (djs[kcol]<=0.0)(static_cast<void> (0));
6194 objVal += djs[kcol]*solMovement;
6195 }
6196 colUpper[kcol]=0.0;
6197 /* update immediately */
6198 for (int jj =columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) {
6199 krow = row[jj];
6200 value = columnElements[jj];
6201 assert (markR[krow]!=-2)(static_cast<void> (0));
6202 if (markR[krow]==-1) {
6203 stackR[nstackR]=krow;
6204 markR[krow]=nstackR;
6205 saveMin[nstackR]=minR[krow];
6206 saveMax[nstackR]=maxR[krow];
6207 nstackR++;
6208#if 0
6209 } else if (markR[krow]==-2) {
6210 continue;
6211#endif
6212 }
6213 /* could check immediately if violation */
6214 /* down */
6215 if (value<0.0) {
6216 /* up does not change - down does */
6217 if (minR[krow]>-1.0e10)
6218 minR[krow] -= value;
6219 if (minR[krow]>rowUpper[krow]+1.0e-5) {
6220 notFeasible=1;
6221 break;
6222 }
6223 } else {
6224 /* down does not change - up does */
6225 if (maxR[krow]<1.0e10)
6226 maxR[krow] -= value;
6227 if (maxR[krow]<rowLower[krow]-1.0e-5) {
6228 notFeasible=1;
6229 break;
6230 }
6231 }
6232 }
6233 }
6234 }
6235 } else if (markC[kcol]==1) {
6236 // marked as going to 0
6237 assert (!colUpper[kcol])(static_cast<void> (0));
6238 if (!kway) {
6239 // contradiction
6240 notFeasible=1;
6241 break;
6242 }
6243 } else if (markC[kcol]==2) {
6244 // marked as going to 1
6245 assert (colLower[kcol])(static_cast<void> (0));
6246 if (kway) {
6247 // contradiction
6248 notFeasible=1;
6249 break;
6250 }
6251 } else {
6252 // marked as fixed
6253 assert (markC[kcol]==3)(static_cast<void> (0));
6254 int jkway;
6255 if (colLower[kcol])
6256 jkway=1;
6257 else
6258 jkway=0;
6259 if (kway==jkway) {
6260 // contradiction
6261 notFeasible=1;
6262 break;
6263 }
6264 }
6265 }
6266 }
6267 if (notFeasible)
6268 break;
6269 }
6270 if (notFeasible)
6271 istackC=nstackC+1;
6272 }
6273 for (k=columnStart[jcol];k<columnStart[jcol]+columnLength[jcol];k++) {
6274 // break if found not feasible
6275 if (notFeasible)
6276 break;
6277 int irow = row[k];
6278 /*value = columnElements[k];*/
6279 assert (markR[irow]!=-2)(static_cast<void> (0));
6280#if 0
6281 if (markR[irow]!=-2) {
6282#endif
6283 /* see if anything forced */
6284 for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow];kk++) {
6285 double moveUp=0.0;
6286 double moveDown=0.0;
6287 double newUpper=-1.0,newLower=1.0;
6288 kcol=column[kk];
6289 bool onList = (markC[kcol]!=0);
6290 if (markC[kcol]!=3) {
6291 value2=rowElements[kk];
6292 int markIt=markC[kcol];
6293 if (value2 < 0.0) {
6294 if (colUpper[kcol] < 1e10 && (markIt&2)==0 &&
6295 rowUpper[irow]<1.0e10) {
6296 dbound = colUpper[kcol]+
6297 (rowUpper[irow]-minR[irow])/value2;
6298 if (dbound > colLower[kcol] + primalTolerance_) {
6299 if (intVar[kcol]) {
6300 markIt |= 2;
6301 newLower = ceil(dbound-primalTolerance_);
6302 } else {
6303 newLower=dbound;
6304 if (newLower+primalTolerance_>colUpper[kcol]&&
6305 newLower-primalTolerance_<=colUpper[kcol]) {
6306 newLower=colUpper[kcol];
6307 markIt |= 2;
6308 //markIt=3;
6309 } else {
6310 // avoid problems - fix later ?
6311 markIt=3;
6312 }
6313 }
6314 moveUp = newLower-colLower[kcol];
6315 }
6316 }
6317 if (colLower[kcol] > -1e10 && (markIt&1)==0 &&
6318 rowLower[irow]>-1.0e10) {
6319 dbound = colLower[kcol] +
6320 (rowLower[irow]-maxR[irow])/value2;
6321 if (dbound < colUpper[kcol] - primalTolerance_) {
6322 if (intVar[kcol]) {
6323 markIt |= 1;
6324 newUpper = floor(dbound+primalTolerance_);
6325 } else {
6326 newUpper=dbound;
6327 if (newUpper-primalTolerance_<colLower[kcol]&&
6328 newUpper+primalTolerance_>=colLower[kcol]) {
6329 newUpper=colLower[kcol];
6330 markIt |= 1;
6331 //markIt=3;
6332 } else {
6333 // avoid problems - fix later ?
6334 markIt=3;
6335 }
6336 }
6337 moveDown = newUpper-colUpper[kcol];
6338 }
6339 }
6340 } else {
6341 /* positive element */
6342 if (colUpper[kcol] < 1e10 && (markIt&2)==0 &&
6343 rowLower[irow]>-1.0e10) {
6344 dbound = colUpper[kcol] +
6345 (rowLower[irow]-maxR[irow])/value2;
6346 if (dbound > colLower[kcol] + primalTolerance_) {
6347 if (intVar[kcol]) {
6348 markIt |= 2;
6349 newLower = ceil(dbound-primalTolerance_);
6350 } else {
6351 newLower=dbound;
6352 if (newLower+primalTolerance_>colUpper[kcol]&&
6353 newLower-primalTolerance_<=colUpper[kcol]) {
6354 newLower=colUpper[kcol];
6355 markIt |= 2;
6356 //markIt=3;
6357 } else {
6358 // avoid problems - fix later ?
6359 markIt=3;
6360 }
6361 }
6362 moveUp = newLower-colLower[kcol];
6363 }
6364 }
6365 if (colLower[kcol] > -1e10 && (markIt&1)==0 &&
6366 rowUpper[irow]<1.0e10) {
6367 dbound = colLower[kcol] +
6368 (rowUpper[irow]-minR[irow])/value2;
6369 if (dbound < colUpper[kcol] - primalTolerance_) {
6370 if (intVar[kcol]) {
6371 markIt |= 1;
6372 newUpper = floor(dbound+primalTolerance_);
6373 } else {
6374 newUpper=dbound;
6375 if (newUpper-primalTolerance_<colLower[kcol]&&
6376 newUpper+primalTolerance_>=colLower[kcol]) {
6377 newUpper=colLower[kcol];
6378 markIt |= 1;
6379 //markIt=3;
6380 } else {
6381 // avoid problems - fix later ?
6382 markIt=3;
6383 }
6384 }
6385 moveDown = newUpper-colUpper[kcol];
6386 }
6387 }
6388 }
6389 if (nstackC<2*maxStack) {
6390 markC[kcol] = markIt;
6391 }
6392 if (moveUp&&nstackC<2*maxStack) {
6393 fixThis++;
6394#ifdef PRINT_DEBUG
6395 printf("lower bound on %d increased from %g to %g by row %d %g %g\n",kcol,colLower[kcol],newLower,irow,rowLower[irow],rowUpper[irow]);
6396 value=0.0;
6397 for (jj=rowStart[irow];jj<rowStart[irow]+rowLength[irow];jj++) {
6398 int ii=column[jj];
6399 if (colUpper[ii]-colLower[ii]>primalTolerance_) {
6400 printf("(%d, %g) ",ii,rowElements[jj]);
6401 } else {
6402 value += rowElements[jj]*colLower[ii];
6403 }
6404 }
6405 printf(" - fixed %g\n",value);
6406 for (jj=rowStart[irow];jj<rowStart[irow]+rowLength[irow];jj++) {
6407 int ii=column[jj];
6408 if (colUpper[ii]-colLower[ii]<primalTolerance_) {
6409 printf("(%d, %g, %g) ",ii,rowElements[jj],colLower[ii]);
6410 }
6411 }
6412 printf("\n");
6413#endif
6414 if (!onList) {
6415 stackC[nstackC]=kcol;
6416 saveL[nstackC]=colLower[kcol];
6417 saveU[nstackC]=colUpper[kcol];
6418 assert (saveU[nstackC]>saveL[nstackC])(static_cast<void> (0));
6419 nstackC++;
6420 onList=true;
6421 }
6422 if (newLower>colsol[kcol]) {
6423 if (djs[kcol]<0.0) {
6424 /* should be infeasible */
6425 assert (newLower>colUpper[kcol]+primalTolerance_)(static_cast<void> (0));
6426 } else {
6427 objVal += moveUp*djs[kcol];
6428 }
6429 }
6430 if (intVar[kcol])
6431 newLower = CoinMax(colLower[kcol],ceil(newLower-1.0e-4));
6432 colLower[kcol]=newLower;
6433 if (fabs(colUpper[kcol]-colLower[kcol])<1.0e-6) {
6434 markC[kcol]=3; // say fixed
6435 }
6436 /* update immediately */
6437 for (jj=columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) {
6438 krow = row[jj];
6439 value = columnElements[jj];
6440 assert (markR[krow]!=-2)(static_cast<void> (0));
6441 if (markR[krow]==-1) {
6442 stackR[nstackR]=krow;
6443 markR[krow]=nstackR;
6444 saveMin[nstackR]=minR[krow];
6445 saveMax[nstackR]=maxR[krow];
6446 nstackR++;
6447#if 0
6448 } else if (markR[krow]==-2) {
6449 continue;
6450#endif
6451 }
6452 /* could check immediately if violation */
6453 /* up */
6454 if (value>0.0) {
6455 /* up does not change - down does */
6456 if (minR[krow]>-1.0e10)
6457 minR[krow] += value*moveUp;
6458 if (minR[krow]>rowUpper[krow]+1.0e-5) {
6459 colUpper[kcol]=-1.0e50; /* force infeasible */
6460 break;
6461 }
6462 } else {
6463 /* down does not change - up does */
6464 if (maxR[krow]<1.0e10)
6465 maxR[krow] += value*moveUp;
6466 if (maxR[krow]<rowLower[krow]-1.0e-5) {
6467 colUpper[kcol]=-1.0e50; /* force infeasible */
6468 break;
6469 }
6470 }
6471 }
6472 }
6473 if (moveDown&&nstackC<2*maxStack) {
6474 fixThis++;
6475#ifdef PRINT_DEBUG
6476 printf("upper bound on %d decreased from %g to %g by row %d %g %g\n",kcol,colUpper[kcol],newUpper,irow,rowLower[irow],rowUpper[irow]);
6477 value=0.0;
6478 for (jj=rowStart[irow];jj<rowStart[irow]+rowLength[irow];jj++) {
6479 int ii=column[jj];
6480 if (colUpper[ii]-colLower[ii]>primalTolerance_) {
6481 printf("(%d, %g) ",ii,rowElements[jj]);
6482 } else {
6483 value += rowElements[jj]*colLower[ii];
6484 }
6485 }
6486 printf(" - fixed %g\n",value);
6487 for (jj=rowStart[irow];jj<rowStart[irow]+rowLength[irow];jj++) {
6488 int ii=column[jj];
6489 if (colUpper[ii]-colLower[ii]<primalTolerance_) {
6490 printf("(%d, %g, %g) ",ii,rowElements[jj],colLower[ii]);
6491 }
6492 }
6493 printf("\n");
6494#endif
6495 if (!onList) {
6496 stackC[nstackC]=kcol;
6497 saveL[nstackC]=colLower[kcol];
6498 saveU[nstackC]=colUpper[kcol];
6499 assert (saveU[nstackC]>saveL[nstackC])(static_cast<void> (0));
6500 nstackC++;
6501 onList=true;
6502 }
6503 if (newUpper<colsol[kcol]) {
6504 if (djs[kcol]>0.0) {
6505 /* should be infeasible */
6506 assert (colLower[kcol]>newUpper+primalTolerance_)(static_cast<void> (0));
6507 } else {
6508 objVal += moveDown*djs[kcol];
6509 }
6510 }
6511 if (intVar[kcol])
6512 newUpper = CoinMin(colUpper[kcol],floor(newUpper+1.0e-4));
6513 colUpper[kcol]=newUpper;
6514 if (fabs(colUpper[kcol]-colLower[kcol])<1.0e-6) {
6515 markC[kcol]=3; // say fixed
6516 }
6517 /* update immediately */
6518 for (jj=columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) {
6519 krow = row[jj];
6520 value = columnElements[jj];
6521 assert (markR[krow]!=-2)(static_cast<void> (0));
6522 if (markR[krow]==-1) {
6523 stackR[nstackR]=krow;
6524 markR[krow]=nstackR;
6525 saveMin[nstackR]=minR[krow];
6526 saveMax[nstackR]=maxR[krow];
6527 nstackR++;
6528#if 0
6529 } else if (markR[krow]==-2) {
6530#endif
6531 continue;
6532 }
6533 /* could check immediately if violation */
6534 /* down */
6535 if (value<0.0) {
6536 /* up does not change - down does */
6537 if (minR[krow]>-1.0e10)
6538 minR[krow] += value*moveDown;
6539 if (minR[krow]>rowUpper[krow]+1.0e-5) {
6540 colUpper[kcol]=-1.0e50; /* force infeasible */
6541 break;
6542 }
6543 } else {
6544 /* down does not change - up does */
6545 if (maxR[krow]<1.0e10)
6546 maxR[krow] += value*moveDown;
6547 if (maxR[krow]<rowLower[krow]-1.0e-5) {
6548 colUpper[kcol]=-1.0e50; /* force infeasible */
6549 break;
6550 }
6551 }
6552 }
6553 }
6554 if (colLower[kcol]>colUpper[kcol]+primalTolerance_) {
6555 notFeasible=1;;
6556 k=columnStart[jcol]+columnLength[jcol];
6557 istackC=nstackC+1;
6558#ifdef PRINT_DEBUG
6559 printf("** not feasible this way\n");
6560#endif
6561 break;
6562 }
6563 }
6564 }
6565#if 0
6566 }
6567#endif
6568 }
6569 istackC++;
6570 }
6571 if (!notFeasible) {
6572 if (objVal<=cutoff) {
6573 feasible |= feas[iway];
6574 } else {
6575#ifdef PRINT_DEBUG
6576 printf("not feasible on dj\n");
6577#endif
6578 notFeasible=1;
6579 if (iway==1&&feasible==0) {
6580 /* not feasible at all */
6581 ninfeas=1;
6582 j=nCols-1;
6583 break;
6584 }
6585 }
6586 } else if (iway==1&&feasible==0) {
6587 /* not feasible at all */
6588 ninfeas=1;
6589 j=nCols-1;
6590 iLook=numberThisTime_;
6591 ipass=maxPass;
6592 break;
6593 }
6594 if (notFeasible)
6595 goingToTrueBound=0;
6596 if (iway==2||(iway==1&&feasible==2)) {
6597 /* keep */
6598 iway=3;
6599 nfixed++;
6600 if (mode_) {
6601 OsiColCut cc;
6602 int nTot=0,nFix=0,nInt=0;
6603 bool ifCut=false;
6604 for (istackC=0;istackC<nstackC;istackC++) {
6605 int icol=stackC[istackC];
6606 if (intVar[icol]) {
6607 if (colUpper[icol]<currentColUpper[icol]-1.0e-4) {
6608 element[nFix]=colUpper[icol];
6609 index[nFix++]=icol;
6610 nInt++;
6611 if (colsol[icol]>colUpper[icol]+primalTolerance_) {
6612 ifCut=true;
6613 anyColumnCuts=true;
6614 }
6615 }
6616 }
6617 }
6618 if (nFix) {
6619 nTot=nFix;
6620 cc.setUbs(nFix,index,element);
6621 nFix=0;
6622 }
6623 for (istackC=0;istackC<nstackC;istackC++) {
6624 int icol=stackC[istackC];
6625 if (intVar[icol]) {
6626 if (colLower[icol]>currentColLower[icol]+1.0e-4) {
6627 element[nFix]=colLower[icol];
6628 index[nFix++]=icol;
6629 nInt++;
6630 if (colsol[icol]<colLower[icol]-primalTolerance_) {
6631 ifCut=true;
6632 anyColumnCuts=true;
6633 }
6634 }
6635 }
6636 }
6637 if (nFix) {
6638 nTot+=nFix;
6639 cc.setLbs(nFix,index,element);
6640 }
6641 // could tighten continuous as well
6642 if (nInt) {
6643 if (ifCut) {
6644 cc.setEffectiveness(100.0);
6645 } else {
6646 cc.setEffectiveness(1.0e-5);
6647 }
6648#ifdef CGL_DEBUG
6649 checkBounds(debugger,cc);
6650#endif
6651 cs.insert(cc);
6652 }
6653 }
6654 for (istackC=0;istackC<nstackC;istackC++) {
6655 int icol=stackC[istackC];
6656 if (colUpper[icol]-colLower[icol]>primalTolerance_) {
6657 markC[icol]=0;
6658 } else {
6659 markC[icol]=3;
6660 }
6661 }
6662 for (istackR=0;istackR<nstackR;istackR++) {
6663 int irow=stackR[istackR];
6664 markR[irow]=-1;
6665 }
6666 } else {
6667 /* is it worth seeing if can increase coefficients
6668 or maybe better see if it is a cut */
6669 if (iway==0) {
6670 nstackC0=CoinMin(nstackC,maxStack);
6671 double solMove = saveSolval-down;
6672 double boundChange;
6673 if (notFeasible) {
6674 nstackC0=0;
6675 } else {
6676 for (istackC=0;istackC<nstackC0;istackC++) {
6677 int icol=stackC[istackC];
6678 stackC0[istackC]=icol;
6679 lo0[istackC]=colLower[icol];
6680 up0[istackC]=colUpper[icol];
6681 }
6682 }
6683 /* restore all */
6684 int nCliquesAffected=0;
6685 assert (iway==0)(static_cast<void> (0));
6686 for (istackC=nstackC-1;istackC>=0;istackC--) {
6687 int icol=stackC[istackC];
6688 double oldU=saveU[istackC];
6689 double oldL=saveL[istackC];
6690 if(goingToTrueBound==2&&istackC) {
6691 // Work for extending cliques
6692 if (!mode_&&numberCliques_) {
6693 int i_01 = to_01[icol];
6694 if (i_01>=0) {
6695 int start;
6696 int end;
6697 if (colLower[icol]) {
6698 // going up - but we want weak way
6699 start = zeroFixStart_[icol];
6700 end = endFixStart_[icol];
6701 } else {
6702 // going down - but we want weak way
6703 start = oneFixStart_[icol];
6704 end = zeroFixStart_[icol];
6705 }
6706 //if (end>start)
6707 //printf("j %d, other %d is in %d cliques\n",
6708 // j,i_01,end-start);
6709 for (int i=start;i<end;i++) {
6710 int iClique = whichClique_[i];
6711 int size = cliqueStart_[iClique+1]-cliqueStart_[iClique];
6712 if (cliqueCount[iClique]==size) {
6713 // first time
6714 cliqueStack[nCliquesAffected++]=iClique;
6715 }
6716 // decrement counts
6717 cliqueCount[iClique]--;
6718 }
6719 }
6720 }
6721 // upper disaggregation cut would be
6722 // xval < upper + (old_upper-upper) (jval-down)
6723 boundChange = oldU-colUpper[icol];
6724 if (boundChange>0.0&&oldU<1.0e10&&
6725 (!mode_||colsol[icol]>colUpper[icol]
6726 + boundChange*solMove+primalTolerance_)) {
6727 // create cut
6728 OsiRowCut rc;
6729 rc.setLb(-COIN_DBL_MAX);
6730 rc.setUb(colUpper[icol]-down*boundChange);
6731 index[0]=icol;
6732 element[0]=1.0;
6733 index[1]=j;
6734 element[1]= - boundChange;
6735 // effectiveness is how far j moves
6736 double newSol = (colsol[icol]-colUpper[icol])/
6737 boundChange;
6738 if (mode_)
6739 assert(newSol>solMove)(static_cast<void> (0));
6740 rc.setEffectiveness(newSol-solMove);
6741 if (rc.effectiveness()>disaggEffectiveness) {
6742 rc.setRow(2,index,element,false);
6743#ifdef CGL_DEBUG
6744 if (debugger) assert(!debugger->invalidCut(rc))(static_cast<void> (0));
6745#endif
6746 rowCut.addCutIfNotDuplicate(rc);
6747 }
6748 }
6749 // lower disaggregation cut would be
6750 // xval > lower + (old_lower-lower) (jval-down)
6751 boundChange = oldL-colLower[icol];
6752 if (boundChange<0.0&&oldL>-1.0e10&&
6753 (!mode_||colsol[icol]<colLower[icol]
6754 + boundChange*solMove-primalTolerance_)) {
6755 // create cut
6756 OsiRowCut rc;
6757 rc.setLb(colLower[icol]-down*boundChange);
6758 rc.setUb(COIN_DBL_MAX);
6759 index[0]=icol;
6760 element[0]=1.0;
6761 index[1]=j;
6762 element[1]=- boundChange;
6763 // effectiveness is how far j moves
6764 double newSol = (colsol[icol]-colLower[icol])/
6765 boundChange;
6766 if (mode_)
6767 assert(newSol>solMove)(static_cast<void> (0));
6768 rc.setEffectiveness(newSol-solMove);
6769 if (rc.effectiveness()>disaggEffectiveness) {
6770 rc.setRow(2,index,element,false);
6771#ifdef CGL_DEBUG
6772 if (debugger) assert(!debugger->invalidCut(rc))(static_cast<void> (0));
6773#endif
6774 rowCut.addCutIfNotDuplicate(rc);
6775#if 0
6776 printf("%d original bounds %g, %g new Lo %g sol= %g int %d sol= %g\n",icol,oldL,oldU,colLower[icol],colsol[icol], j, colsol[j]);
6777 printf("-1.0 * x(%d) + %g * y(%d) <= %g\n",
6778 icol,boundChange,j,rc.ub());
6779#endif
6780 }
6781 }
6782 }
6783 colUpper[icol]=oldU;
6784 colLower[icol]=oldL;
6785 markC[icol]=0;
6786 }
6787 if (nCliquesAffected) {
6788 for (int i=0;i<nCliquesAffected;i++) {
6789 int iClique = cliqueStack[i];
6790 int size = cliqueCount[iClique];
6791 // restore
6792 cliqueCount[iClique]= cliqueStart_[iClique+1]-cliqueStart_[iClique];
6793 if (!size) {
6794 if (logLevel_>1)
6795 printf("** could extend clique by adding j!\n");
6796 }
6797 }
6798 }
6799 for (istackR=0;istackR<nstackR;istackR++) {
6800 int irow=stackR[istackR];
6801 // switch off strengthening if not wanted
6802 if ((rowCuts&2)!=0&&goingToTrueBound) {
6803 bool ifCut=anyColumnCuts;
6804 double gap = rowUpper[irow]-maxR[irow];
6805 double sum=0.0;
6806 if (!ifCut&&(gap>primalTolerance_&&gap<1.0e8)) {
6807 // see if the strengthened row is a cut
6808 for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow];
6809 kk++) {
6810 sum += rowElements[kk]*colsol[column[kk]];
6811 }
6812 if (sum-gap*colsol[j]>maxR[irow]+primalTolerance_||(info->strengthenRow&&rowLower[irow]<-1.0e20)) {
6813 // can be a cut
6814 // subtract gap from upper and integer coefficient
6815 // saveU and saveL spare
6816 int * index = reinterpret_cast<int *>(saveL);
6817 double * element = saveU;
6818 int n=0;
6819 bool coefficientExists=false;
6820 for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow];
6821 kk++) {
6822 if (column[kk]!=j) {
6823 index[n]=column[kk];
6824 element[n++]=rowElements[kk];
6825 } else {
6826 double value=rowElements[kk]-gap;
6827 if (fabs(value)>1.0e-12) {
6828 index[n]=column[kk];
6829 element[n++]=value;
6830 }
6831 coefficientExists=true;
6832 }
6833 }
6834 if (!coefficientExists) {
6835 index[n]=j;
6836 element[n++]=-gap;
6837 }
6838 OsiRowCut rc;
6839 rc.setLb(-COIN_DBL_MAX);
6840 rc.setUb(rowUpper[irow]-gap*(colLower[j]+1.0));
6841 // effectiveness is how far j moves
6842 rc.setEffectiveness((sum-gap*colsol[j]-maxR[irow])/gap);
6843 if (rc.effectiveness()>needEffectiveness) {
6844 rc.setRow(n,index,element,false);
6845#ifdef CGL_DEBUG
6846 if (debugger) assert(!debugger->invalidCut(rc))(static_cast<void> (0));
6847#endif
6848 // If strengthenRow point to row
6849 //if(info->strengthenRow)
6850 //printf("a point to row %d\n",irow);
6851#ifdef STRENGTHEN_PRINT
6852 if (rowLower[irow]<-1.0e20) {
6853 printf("5Cut %g <= ",rc.lb());
6854 int k;
6855 for ( k=0;k<n;k++) {
6856 int iColumn = index[k];
6857 printf("%g*",element[k]);
6858 if (si.isInteger(iColumn))
6859 printf("i%d ",iColumn);
6860 else
6861 printf("x%d ",iColumn);
6862 }
6863 printf("<= %g\n",rc.ub());
6864 printf("Row %g <= ",rowLower[irow]);
6865 for (k=rowStart[irow];k<rowStart[irow]+rowLength[irow];k++) {
6866 int iColumn = column[k];
6867 printf("%g*",rowElements[k]);
6868 if (si.isInteger(iColumn))
6869 printf("i%d ",iColumn);
6870 else
6871 printf("x%d ",iColumn);
6872 }
6873 printf("<= %g\n",rowUpper[irow]);
6874 }
6875#endif
6876 int realRow = (rowLower[irow]<-1.0e20) ? irow : -1;
6877 if (realRows&&realRow>0)
6878 realRow=realRows[realRow];
6879 rowCut.addCutIfNotDuplicate(rc,realRow);
6880 }
6881 }
6882 }
6883 gap = minR[irow]-rowLower[irow];
6884 if (!ifCut&&(gap>primalTolerance_&&gap<1.0e8)) {
6885 // see if the strengthened row is a cut
6886 if (!sum) {
6887 for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow];
6888 kk++) {
6889 sum += rowElements[kk]*colsol[column[kk]];
6890 }
6891 }
6892 if (sum+gap*colsol[j]<minR[irow]+primalTolerance_||(info->strengthenRow&&rowUpper[irow]>1.0e20)) {
6893 // can be a cut
6894 // add gap to lower and integer coefficient
6895 // saveU and saveL spare
6896 int * index = reinterpret_cast<int *>(saveL);
6897 double * element = saveU;
6898 int n=0;
6899 bool coefficientExists=false;
6900 for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow];
6901 kk++) {
6902 if (column[kk]!=j) {
6903 index[n]=column[kk];
6904 element[n++]=rowElements[kk];
6905 } else {
6906 double value=rowElements[kk]+gap;
6907 if (fabs(value)>1.0e-12) {
6908 index[n]=column[kk];
6909 element[n++]=value;
6910 }
6911 coefficientExists=true;
6912 }
6913 }
6914 if (!coefficientExists) {
6915 index[n]=j;
6916 element[n++]=gap;
6917 }
6918 OsiRowCut rc;
6919 rc.setLb(rowLower[irow]+gap*(colLower[j]+1.0));
6920 rc.setUb(COIN_DBL_MAX);
6921 // effectiveness is how far j moves
6922 rc.setEffectiveness((minR[irow]-sum-gap*colsol[j])/gap);
6923 if (rc.effectiveness()>needEffectiveness) {
6924 rc.setRow(n,index,element,false);
6925#ifdef CGL_DEBUG
6926 if (debugger) assert(!debugger->invalidCut(rc))(static_cast<void> (0));
6927#endif
6928 //if(info->strengthenRow)
6929 //printf("b point to row %d\n",irow);
6930#ifdef STRENGTHEN_PRINT
6931 if (rowUpper[irow]>1.0e20) {
6932 printf("6Cut %g <= ",rc.lb());
6933 int k;
6934 for ( k=0;k<n;k++) {
6935 int iColumn = index[k];
6936 printf("%g*",element[k]);
6937 if (si.isInteger(iColumn))
6938 printf("i%d ",iColumn);
6939 else
6940 printf("x%d ",iColumn);
6941 }
6942 printf("<= %g\n",rc.ub());
6943 printf("Row %g <= ",rowLower[irow]);
6944 for (k=rowStart[irow];k<rowStart[irow]+rowLength[irow];k++) {
6945 int iColumn = column[k];
6946 printf("%g*",rowElements[k]);
6947 if (si.isInteger(iColumn))
6948 printf("i%d ",iColumn);
6949 else
6950 printf("x%d ",iColumn);
6951 }
6952 printf("<= %g\n",rowUpper[irow]);
6953 }
6954#endif
6955 int realRow = (rowUpper[irow]>1.0e20) ? irow : -1;
6956 if (realRows&&realRow>0)
6957 realRow=realRows[realRow];
6958 rowCut.addCutIfNotDuplicate(rc,realRow);
6959 }
6960 }
6961 }
6962 }
6963 minR[irow]=saveMin[istackR];
6964 maxR[irow]=saveMax[istackR];
6965 markR[irow]=-1;
6966 }
6967 } else {
6968 if (iway==1&&feasible==3) {
6969 iway=3;
6970 /* point back to stack */
6971 for (istackC=nstackC-1;istackC>=0;istackC--) {
6972 int icol=stackC[istackC];
6973 markC[icol]=istackC+1000;
6974 }
6975 if (mode_) {
6976 OsiColCut cc;
6977 int nTot=0,nFix=0,nInt=0;
6978 bool ifCut=false;
6979 for (istackC=0;istackC<nstackC0;istackC++) {
6980 int icol=stackC0[istackC];
6981 int istackC1=markC[icol]-1000;
6982 if (istackC1>=0) {
6983 if (CoinMin(lo0[istackC],colLower[icol])>saveL[istackC1]+1.0e-4) {
6984 saveL[istackC1]=CoinMin(lo0[istackC],colLower[icol]);
6985 if (intVar[icol]) {
6986 element[nFix]=saveL[istackC1];
6987 index[nFix++]=icol;
6988 nInt++;
6989 if (colsol[icol]<saveL[istackC1]-primalTolerance_)
6990 ifCut=true;
6991 }
6992 nfixed++;
6993 }
6994 }
6995 }
6996 if (nFix) {
6997 nTot=nFix;
6998 cc.setLbs(nFix,index,element);
6999 nFix=0;
7000 }
7001 for (istackC=0;istackC<nstackC0;istackC++) {
7002 int icol=stackC0[istackC];
7003 int istackC1=markC[icol]-1000;
7004 if (istackC1>=0) {
7005 if (CoinMax(up0[istackC],colUpper[icol])<saveU[istackC1]-1.0e-4) {
7006 saveU[istackC1]=CoinMax(up0[istackC],colUpper[icol]);
7007 if (intVar[icol]) {
7008 element[nFix]=saveU[istackC1];
7009 index[nFix++]=icol;
7010 nInt++;
7011 if (colsol[icol]>saveU[istackC1]+primalTolerance_)
7012 ifCut=true;
7013 }
7014 nfixed++;
7015 }
7016 }
7017 }
7018 if (nFix) {
7019 nTot+=nFix;
7020 cc.setUbs(nFix,index,element);
7021 }
7022 // could tighten continuous as well
7023 if (nInt) {
7024 if (ifCut) {
7025 cc.setEffectiveness(100.0);
7026 } else {
7027 cc.setEffectiveness(1.0e-5);
7028 }
7029#ifdef CGL_DEBUG
7030 checkBounds(debugger,cc);
7031#endif
7032 cs.insert(cc);
7033 }
7034 }
7035 } else {
7036 goingToTrueBound=0;
7037 }
7038 double solMove = up-saveSolval;
7039 double boundChange;
7040 /* restore all */
7041 int nCliquesAffected=0;
7042 for (istackC=nstackC-1;istackC>=0;istackC--) {
7043 int icol=stackC[istackC];
7044 double oldU=saveU[istackC];
7045 double oldL=saveL[istackC];
7046 if(goingToTrueBound==2&&istackC) {
7047 // Work for extending cliques
7048 if (!mode_&&numberCliques_&&iway==3) {
7049 int i_01 = to_01[icol];
7050 if (i_01>=0) {
7051 int start;
7052 int end;
7053 if (colLower[icol]) {
7054 // going up - but we want weak way
7055 start = zeroFixStart_[icol];
7056 end = endFixStart_[icol];
7057 } else {
7058 // going down - but we want weak way
7059 start = oneFixStart_[icol];
7060 end = zeroFixStart_[icol];
7061 }
7062 //if (end>start)
7063 //printf("up j %d, other %d is in %d cliques\n",
7064 // j,i_01,end-start);
7065 for (int i=start;i<end;i++) {
7066 int iClique = whichClique_[i];
7067 int size = cliqueStart_[iClique+1]-cliqueStart_[iClique];
7068 if (cliqueCount[iClique]==size) {
7069 // first time
7070 cliqueStack[nCliquesAffected++]=iClique;
7071 }
7072 // decrement counts
7073 cliqueCount[iClique]--;
7074 }
7075 }
7076 }
7077 // upper disaggregation cut would be
7078 // xval < upper + (old_upper-upper) (up-jval)
7079 boundChange = oldU-colUpper[icol];
7080 if (boundChange>0.0&&oldU<1.0e10&&
7081 (!mode_||colsol[icol]>colUpper[icol]
7082 + boundChange*solMove+primalTolerance_)) {
7083 // create cut
7084 OsiRowCut rc;
7085 rc.setLb(-COIN_DBL_MAX);
7086 rc.setUb(colUpper[icol]+up*boundChange);
7087 index[0]=icol;
7088 element[0]=1.0;
7089 index[1]=j;
7090 element[1]= + boundChange;
7091 // effectiveness is how far j moves
7092 double newSol = (colsol[icol]-colUpper[icol])/
7093 boundChange;
7094 if (mode_)
7095 assert(newSol>solMove)(static_cast<void> (0));
7096 rc.setEffectiveness(newSol-solMove);
7097 if (rc.effectiveness()>disaggEffectiveness) {
7098 rc.setRow(2,index,element,false);
7099#ifdef CGL_DEBUG
7100 if (debugger) assert(!debugger->invalidCut(rc))(static_cast<void> (0));
7101#endif
7102 rowCut.addCutIfNotDuplicate(rc);
7103 }
7104 }
7105 // lower disaggregation cut would be
7106 // xval > lower + (old_lower-lower) (up-jval)
7107 boundChange = oldL-colLower[icol];
7108 if (boundChange<0.0&&oldL>-1.0e10&&
7109 (!mode_||colsol[icol]<colLower[icol]
7110 + boundChange*solMove-primalTolerance_)) {
7111 // create cut
7112 OsiRowCut rc;
7113 rc.setLb(colLower[icol]+up*boundChange);
7114 rc.setUb(COIN_DBL_MAX);
7115 index[0]=icol;
7116 element[0]=1.0;
7117 index[1]=j;
7118 element[1]= + boundChange;
7119 // effectiveness is how far j moves
7120 double newSol = (colsol[icol]-colLower[icol])/
7121 boundChange;
7122 if (mode_)
7123 assert(newSol>solMove)(static_cast<void> (0));
7124 rc.setEffectiveness(newSol-solMove);
7125 if (rc.effectiveness()>disaggEffectiveness) {
7126 rc.setRow(2,index,element,false);
7127#ifdef CGL_DEBUG
7128 if (debugger) assert(!debugger->invalidCut(rc))(static_cast<void> (0));
7129#endif
7130 rowCut.addCutIfNotDuplicate(rc);
7131 }
7132 }
7133 }
7134 colUpper[icol]=oldU;
7135 colLower[icol]=oldL;
7136 if (oldU>oldL+1.0e-4)
7137 markC[icol]=0;
7138 else
7139 markC[icol]=3;
7140 }
7141 if (nCliquesAffected) {
7142 for (int i=0;i<nCliquesAffected;i++) {
7143 int iClique = cliqueStack[i];
7144 int size = cliqueCount[iClique];
7145 // restore
7146 cliqueCount[iClique]= cliqueStart_[iClique+1]-cliqueStart_[iClique];
7147 if (!size) {
7148 if (logLevel_>1)
7149 printf("** could extend clique by adding j!\n");
7150 }
7151 }
7152 }
7153 for (istackR=0;istackR<nstackR;istackR++) {
7154 int irow=stackR[istackR];
7155 // switch off strengthening if not wanted
7156 if ((rowCuts&2)!=0&&goingToTrueBound) {
7157 bool ifCut=anyColumnCuts;
7158 double gap = rowUpper[irow]-maxR[irow];
7159 double sum=0.0;
7160 if (!ifCut&&(gap>primalTolerance_&&gap<1.0e8)) {
7161 // see if the strengthened row is a cut
7162 for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow];
7163 kk++) {
7164 sum += rowElements[kk]*colsol[column[kk]];
7165 }
7166 if (sum+gap*colsol[j]>rowUpper[irow]+primalTolerance_||(info->strengthenRow&&rowLower[irow]<-1.0e20)) {
7167 // can be a cut
7168 // add gap to integer coefficient
7169 // saveU and saveL spare
7170 int * index = reinterpret_cast<int *>(saveL);
7171 double * element = saveU;
7172 int n=0;
7173 bool coefficientExists=false;
7174 for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow];
7175 kk++) {
7176 if (column[kk]!=j) {
7177 index[n]=column[kk];
7178 element[n++]=rowElements[kk];
7179 } else {
7180 double value=rowElements[kk]+gap;
7181 if (fabs(value)>1.0e-12) {
7182 index[n]=column[kk];
7183 element[n++]=value;
7184 }
7185 coefficientExists=true;
7186 }
7187 }
7188 if (!coefficientExists) {
7189 index[n]=j;
7190 element[n++]=gap;
7191 }
7192 OsiRowCut rc;
7193 rc.setLb(-COIN_DBL_MAX);
7194 rc.setUb(rowUpper[irow]+gap*(colUpper[j]-1.0));
7195 // effectiveness is how far j moves
7196 rc.setEffectiveness((sum+gap*colsol[j]-rowUpper[irow])/gap);
7197 if (rc.effectiveness()>needEffectiveness) {
7198 rc.setRow(n,index,element,false);
7199#ifdef CGL_DEBUG
7200 if (debugger) assert(!debugger->invalidCut(rc))(static_cast<void> (0));
7201#endif
7202 //if(info->strengthenRow)
7203 //printf("c point to row %d\n",irow);
7204#ifdef STRENGTHEN_PRINT
7205 if (rowLower[irow]<-1.0e20) {
7206 printf("7Cut %g <= ",rc.lb());
7207 int k;
7208 for ( k=0;k<n;k++) {
7209 int iColumn = index[k];
7210 printf("%g*",element[k]);
7211 if (si.isInteger(iColumn))
7212 printf("i%d ",iColumn);
7213 else
7214 printf("x%d ",iColumn);
7215 }
7216 printf("<= %g\n",rc.ub());
7217 printf("Row %g <= ",rowLower[irow]);
7218 for (k=rowStart[irow];k<rowStart[irow]+rowLength[irow];k++) {
7219 int iColumn = column[k];
7220 printf("%g*",rowElements[k]);
7221 if (si.isInteger(iColumn))
7222 printf("i%d ",iColumn);
7223 else
7224 printf("x%d ",iColumn);
7225 }
7226 printf("<= %g\n",rowUpper[irow]);
7227 }
7228#endif
7229 int realRow = (rowLower[irow]<-1.0e20) ? irow : -1;
7230 if (realRows&&realRow>0)
7231 realRow=realRows[realRow];
7232 rowCut.addCutIfNotDuplicate(rc,realRow);
7233 }
7234 }
7235 }
7236 gap = minR[irow]-rowLower[irow];
7237 if (!ifCut&&(gap>primalTolerance_&&gap<1.0e8)) {
7238 // see if the strengthened row is a cut
7239 if (!sum) {
7240 for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow];
7241 kk++) {
7242 sum += rowElements[kk]*colsol[column[kk]];
7243 }
7244 }
7245 if (sum-gap*colsol[j]<rowLower[irow]+primalTolerance_||(info->strengthenRow&&rowUpper[irow]>1.0e20)) {
7246 // can be a cut
7247 // subtract gap from integer coefficient
7248 // saveU and saveL spare
7249 int * index = reinterpret_cast<int *>(saveL);
7250 double * element = saveU;
7251 int n=0;
7252 bool coefficientExists=false;
7253 for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow];
7254 kk++) {
7255 if (column[kk]!=j) {
7256 index[n]=column[kk];
7257 element[n++]=rowElements[kk];
7258 } else {
7259 double value=rowElements[kk]-gap;
7260 if (fabs(value)>1.0e-12) {
7261 index[n]=column[kk];
7262 element[n++]=value;
7263 }
7264 coefficientExists=true;
7265 }
7266 }
7267 if (!coefficientExists) {
7268 index[n]=j;
7269 element[n++]=-gap;
7270 }
7271 OsiRowCut rc;
7272 rc.setLb(rowLower[irow]-gap*(colUpper[j]-1));
7273 rc.setUb(COIN_DBL_MAX);
7274 // effectiveness is how far j moves
7275 rc.setEffectiveness((rowLower[irow]-sum+gap*colsol[j])/gap);
7276 if (rc.effectiveness()>needEffectiveness) {
7277 rc.setRow(n,index,element,false);
7278#ifdef CGL_DEBUG
7279 if (debugger) assert(!debugger->invalidCut(rc))(static_cast<void> (0));
7280#endif
7281 //if(info->strengthenRow)
7282 //printf("d point to row %d\n",irow);
7283#ifdef STRENGTHEN_PRINT
7284 if (rowUpper[irow]>1.0e20) {
7285 printf("8Cut %g <= ",rc.lb());
7286 int k;
7287 for ( k=0;k<n;k++) {
7288 int iColumn = index[k];
7289 printf("%g*",element[k]);
7290 if (si.isInteger(iColumn))
7291 printf("i%d ",iColumn);
7292 else
7293 printf("x%d ",iColumn);
7294 }
7295 printf("<= %g\n",rc.ub());
7296 printf("Row %g <= ",rowLower[irow]);
7297 for (k=rowStart[irow];k<rowStart[irow]+rowLength[irow];k++) {
7298 int iColumn = column[k];
7299 printf("%g*",rowElements[k]);
7300 if (si.isInteger(iColumn))
7301 printf("i%d ",iColumn);
7302 else
7303 printf("x%d ",iColumn);
7304 }
7305 printf("<= %g\n",rowUpper[irow]);
7306 }
7307#endif
7308 int realRow = (rowUpper[irow]>1.0e20) ? irow : -1;
7309 if (realRows&&realRow>0)
7310 realRow=realRows[realRow];
7311 rowCut.addCutIfNotDuplicate(rc,realRow);
7312 }
7313 }
7314 }
7315 }
7316 minR[irow]=saveMin[istackR];
7317 maxR[irow]=saveMax[istackR];
7318 markR[irow]=-1;
7319 }
7320 }
7321 }
7322 }
7323 }
7324 }
7325 }
7326 delete [] cliqueStack;
7327 delete [] cliqueCount;
7328 delete [] to_01;
7329 delete [] stackC0;
7330 delete [] lo0;
7331 delete [] up0;
7332 delete [] tempL;
7333 delete [] tempU;
7334 delete [] markC;
7335 delete [] stackC;
7336 delete [] stackR;
7337 delete [] saveL;
7338 delete [] saveU;
7339 delete [] saveMin;
7340 delete [] saveMax;
7341 delete [] index;
7342 delete [] element;
7343 delete [] djs;
7344 delete [] colsol;
7345 // Add in row cuts
7346 if (!ninfeas) {
7347 rowCut.addCuts(cs,info->strengthenRow,0);
7348 }
7349 return (ninfeas);
7350}
7351// Does probing and adding cuts for clique slacks
7352int
7353CglProbing::probeSlacks( const OsiSolverInterface & si,
7354 const OsiRowCutDebugger *
7355#ifdef CGL_DEBUG
7356 debugger
7357#endif
7358 ,OsiCuts & cs,
7359 double * colLower, double * colUpper, CoinPackedMatrix *rowCopy,
7360 CoinPackedMatrix *columnCopy,
7361 double * rowLower, double * rowUpper,
7362 char * intVar, double * minR, double * maxR,int * markR,
7363 CglTreeInfo * info)
7364{
7365 if (!numberCliques_)
7366 return 0;
7367 // Set up maxes
7368 int maxProbe = info->inTree ? maxProbe_ : maxProbeRoot_;
7369 int maxStack = info->inTree ? maxStack_ : maxStackRoot_;
7370 int nRows=rowCopy->getNumRows();
7371 int nCols=rowCopy->getNumCols();
7372 double * colsol = new double[nCols];
7373 CoinMemcpyN( si.getColSolution(),nCols,colsol);
7374 int rowCuts=rowCuts_;
7375 double_int_pair * array = new double_int_pair [numberCliques_];
7376 // look at <= cliques
7377 int iClique;
7378 int nLook=0;
7379 for (iClique=0;iClique<numberCliques_;iClique++) {
7380 if (!cliqueType_[iClique].equality) {
7381 double sum=0.0;
7382 for (int j=cliqueStart_[iClique];j<cliqueStart_[iClique+1];j++) {
7383 int iColumn = sequenceInCliqueEntry(cliqueEntry_[j]);
7384 double value = colsol[iColumn];
7385 if (oneFixesInCliqueEntry(cliqueEntry_[j]))
7386 sum += value;
7387 else
7388 sum -= value;
7389 }
7390 double away = fabs(0.5-(sum-floor(sum)));
7391 if (away<0.49999) {
7392 array[nLook].infeasibility=away;
7393 array[nLook++].sequence=iClique;
7394 }
7395 }
7396 }
7397 std::sort(array,array+nLook,double_int_pair_compare());
7398 nLook=CoinMin(nLook,maxProbe);
7399 const double * currentColLower = si.getColLower();
7400 const double * currentColUpper = si.getColUpper();
7401 double * tempL = new double [nCols];
7402 double * tempU = new double [nCols];
7403 int * markC = new int [nCols];
7404 int * stackC = new int [2*nCols];
7405 int * stackR = new int [nRows];
7406 double * saveL = new double [2*nCols];
7407 double * saveU = new double [2*nCols];
7408 double * saveMin = new double [nRows];
7409 double * saveMax = new double [nRows];
7410 double * element = new double[nCols];
7411 int * index = new int[nCols];
7412 // Let us never add more than twice the number of rows worth of row cuts
7413 // Keep cuts out of cs until end so we can find duplicates quickly
7414 int nRowsFake = info->inTree ? nRows/3 : nRows;
7415 row_cut rowCut(nRowsFake, !info->inTree);
7416 const int * column = rowCopy->getIndices();
7417 const CoinBigIndex * rowStart = rowCopy->getVectorStarts();
7418 const int * rowLength = rowCopy->getVectorLengths();
7419 const double * rowElements = rowCopy->getElements();
7420 const int * row = columnCopy->getIndices();
7421 const CoinBigIndex * columnStart = columnCopy->getVectorStarts();
7422 const int * columnLength = columnCopy->getVectorLengths();
7423 const double * columnElements = columnCopy->getElements();
7424 double movement;
7425 int i, j, k,kk,jj;
7426 int kcol,irow,krow;
7427 bool anyColumnCuts=false;
7428 double dbound, value, value2;
7429 int ninfeas=0;
7430 for (i = 0; i < nCols; ++i) {
7431 if (colUpper[i]-colLower[i]>1.0e-8) {
7432 if (colsol[i]<colLower[i]+primalTolerance_) {
7433 colsol[i]=colLower[i];
7434 } else if (colsol[i]>colUpper[i]-primalTolerance_) {
7435 colsol[i]=colUpper[i];
7436 }
7437 }
7438 }
7439
7440 int ipass=0,nfixed=-1;
7441
7442 /* for both way coding */
7443 int nstackC0=-1;
7444 int * stackC0 = new int[maxStack];
7445 double * lo0 = new double[maxStack];
7446 double * up0 = new double[maxStack];
7447 int nstackR,nstackC;
7448 for (i=0;i<nCols;i++) {
7449 if (colUpper[i]-colLower[i]<1.0e-8) {
7450 markC[i]=3;
7451 } else {
7452 markC[i]=0;
7453 }
7454 }
7455 double tolerance = 1.0e1*primalTolerance_;
7456 // If we are going to replace coefficient then we don't need to be effective
7457 int maxPass = info->inTree ? maxPass_ : maxPassRoot_;
7458 double needEffectiveness = info->strengthenRow ? -1.0e10 : 1.0e-3;
7459 while (ipass<maxPass&&nfixed) {
7460 int iLook;
7461 ipass++;
7462 nfixed=0;
7463 for (iLook=0;iLook<nLook;iLook++) {
7464 double solval;
7465 double down;
7466 double up;
7467 int iClique=array[iLook].sequence;
7468 solval=0.0;
7469 j=0;
7470 for (j=cliqueStart_[iClique];j<cliqueStart_[iClique+1];j++) {
7471 int iColumn = sequenceInCliqueEntry(cliqueEntry_[j]);
7472 double value = colsol[iColumn];
7473 if (oneFixesInCliqueEntry(cliqueEntry_[j]))
7474 solval += value;
7475 else
7476 solval -= value;
7477 }
7478 down = floor(solval+tolerance);
7479 up = ceil(solval-tolerance);
7480 int istackC,iway, istackR;
7481 int way[]={1,2,1};
7482 int feas[]={1,2,4};
7483 int feasible=0;
7484 int notFeasible;
7485 for (iway=0;iway<3;iway ++) {
7486 int fixThis=0;
7487 stackC[0]=j;
7488 markC[j]=way[iway];
7489 if (way[iway]==1) {
7490 movement=down-colUpper[j];
7491 assert(movement<-0.99999)(static_cast<void> (0));
7492 down=colLower[j];
7493 } else {
7494 movement=up-colLower[j];
7495 assert(movement>0.99999)(static_cast<void> (0));
7496 up=colUpper[j];
7497 }
7498 nstackC=1;
7499 nstackR=0;
7500 saveL[0]=colLower[j];
7501 saveU[0]=colUpper[j];
7502 assert (saveU[0]>saveL[0])(static_cast<void> (0));
7503 notFeasible=0;
7504 if (movement<0.0) {
7505 colUpper[j] += movement;
7506 colUpper[j] = floor(colUpper[j]+0.5);
7507#ifdef PRINT_DEBUG
7508 printf("** Trying %d down to 0\n",j);
7509#endif
7510 } else {
7511 colLower[j] += movement;
7512 colLower[j] = floor(colLower[j]+0.5);
7513#ifdef PRINT_DEBUG
7514 printf("** Trying %d up to 1\n",j);
7515#endif
7516 }
7517 if (fabs(colUpper[j]-colLower[j])<1.0e-6)
7518 markC[j]=3; // say fixed
7519 istackC=0;
7520 /* update immediately */
7521 for (k=columnStart[j];k<columnStart[j]+columnLength[j];k++) {
7522 int irow = row[k];
7523 value = columnElements[k];
7524 if (markR[irow]==-1) {
7525 stackR[nstackR]=irow;
7526 markR[irow]=nstackR;
7527 saveMin[nstackR]=minR[irow];
7528 saveMax[nstackR]=maxR[irow];
7529 nstackR++;
7530 } else if (markR[irow]==-2) {
7531 continue;
7532 }
7533 /* could check immediately if violation */
7534 if (movement>0.0) {
7535 /* up */
7536 if (value>0.0) {
7537 /* up does not change - down does */
7538 if (minR[irow]>-1.0e10)
7539 minR[irow] += value;
7540 if (minR[irow]>rowUpper[irow]+1.0e-5) {
7541 notFeasible=1;
7542 istackC=1;
7543 break;
7544 }
7545 } else {
7546 /* down does not change - up does */
7547 if (maxR[irow]<1.0e10)
7548 maxR[irow] += value;
7549 if (maxR[irow]<rowLower[irow]-1.0e-5) {
7550 notFeasible=1;
7551 istackC=1;
7552 break;
7553 }
7554 }
7555 } else {
7556 /* down */
7557 if (value<0.0) {
7558 /* up does not change - down does */
7559 if (minR[irow]>-1.0e10)
7560 minR[irow] -= value;
7561 if (minR[irow]>rowUpper[irow]+1.0e-5) {
7562 notFeasible=1;
7563 istackC=1;
7564 break;
7565 }
7566 } else {
7567 /* down does not change - up does */
7568 if (maxR[irow]<1.0e10)
7569 maxR[irow] -= value;
7570 if (maxR[irow]<rowLower[irow]-1.0e-5) {
7571 notFeasible=1;
7572 istackC=1;
7573 break;
7574 }
7575 }
7576 }
7577 }
7578 while (istackC<nstackC&&nstackC<maxStack) {
7579 int jway;
7580 int jcol =stackC[istackC];
7581 jway=markC[jcol];
7582 // If not first and fixed then skip
7583 if (jway==3&&istackC) {
7584 //istackC++;
7585 //continue;
7586 //printf("fixed %d on stack\n",jcol);
7587 }
7588 // Do cliques
7589 if (oneFixStart_&&oneFixStart_[jcol]>=0) {
7590 int start;
7591 int end;
7592 if (colLower[jcol]>saveL[istackC]) {
7593 // going up
7594 start = oneFixStart_[jcol];
7595 end = zeroFixStart_[jcol];
7596 } else {
7597 assert (colUpper[jcol]<saveU[istackC])(static_cast<void> (0));
7598 // going down
7599 start = zeroFixStart_[jcol];
7600 end = endFixStart_[jcol];
7601 }
7602 for (int i=start;i<end;i++) {
7603 int iClique = whichClique_[i];
7604 for (int k=cliqueStart_[iClique];k<cliqueStart_[iClique+1];k++) {
7605 int kcol = sequenceInCliqueEntry(cliqueEntry_[k]);
7606 if (jcol==kcol)
7607 continue;
7608 int kway = oneFixesInCliqueEntry(cliqueEntry_[k]);
7609 if (kcol!=jcol) {
7610 if (!markC[kcol]) {
7611 // not on list yet
7612 if (nstackC<2*maxStack) {
7613 markC[kcol] = 3; // say fixed
7614 fixThis++;
7615 stackC[nstackC]=kcol;
7616 saveL[nstackC]=colLower[kcol];
7617 saveU[nstackC]=colUpper[kcol];
7618 assert (saveU[nstackC]>saveL[nstackC])(static_cast<void> (0));
7619 nstackC++;
7620 if (!kway) {
7621 // going up
7622 colLower[kcol]=1.0;
7623 /* update immediately */
7624 for (jj=columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) {
7625 krow = row[jj];
7626 value = columnElements[jj];
7627 if (markR[krow]==-1) {
7628 stackR[nstackR]=krow;
7629 markR[krow]=nstackR;
7630 saveMin[nstackR]=minR[krow];
7631 saveMax[nstackR]=maxR[krow];
7632 nstackR++;
7633 } else if (markR[krow]==-2) {
7634 continue;
7635 }
7636 /* could check immediately if violation */
7637 /* up */
7638 if (value>0.0) {
7639 /* up does not change - down does */
7640 if (minR[krow]>-1.0e10)
7641 minR[krow] += value;
7642 if (minR[krow]>rowUpper[krow]+1.0e-5) {
7643 colUpper[kcol]=-1.0e50; /* force infeasible */
7644 break;
7645 }
7646 } else {
7647 /* down does not change - up does */
7648 if (maxR[krow]<1.0e10)
7649 maxR[krow] += value;
7650 if (maxR[krow]<rowLower[krow]-1.0e-5) {
7651 notFeasible=1;
7652 break;
7653 }
7654 }
7655 }
7656 } else {
7657 // going down
7658 colUpper[kcol]=0.0;
7659 /* update immediately */
7660 for (jj=columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) {
7661 krow = row[jj];
7662 value = columnElements[jj];
7663 if (markR[krow]==-1) {
7664 stackR[nstackR]=krow;
7665 markR[krow]=nstackR;
7666 saveMin[nstackR]=minR[krow];
7667 saveMax[nstackR]=maxR[krow];
7668 nstackR++;
7669 } else if (markR[krow]==-2) {
7670 continue;
7671 }
7672 /* could check immediately if violation */
7673 /* down */
7674 if (value<0.0) {
7675 /* up does not change - down does */
7676 if (minR[krow]>-1.0e10)
7677 minR[krow] -= value;
7678 if (minR[krow]>rowUpper[krow]+1.0e-5) {
7679 notFeasible=1;
7680 break;
7681 }
7682 } else {
7683 /* down does not change - up does */
7684 if (maxR[krow]<1.0e10)
7685 maxR[krow] -= value;
7686 if (maxR[krow]<rowLower[krow]-1.0e-5) {
7687 notFeasible=1;
7688 break;
7689 }
7690 }
7691 }
7692 }
7693 }
7694 } else if (markC[kcol]==1) {
7695 // marked as going to 0
7696 assert (!colUpper[kcol])(static_cast<void> (0));
7697 if (!kway) {
7698 // contradiction
7699 notFeasible=1;
7700 break;
7701 }
7702 } else if (markC[kcol]==2) {
7703 // marked as going to 1
7704 assert (colLower[kcol])(static_cast<void> (0));
7705 if (kway) {
7706 // contradiction
7707 notFeasible=1;
7708 break;
7709 }
7710 } else {
7711 // marked as fixed
7712 assert (markC[kcol]==3)(static_cast<void> (0));
7713 int jkway;
7714 if (colLower[kcol])
7715 jkway=1;
7716 else
7717 jkway=0;
7718 if (kway==jkway) {
7719 // contradiction
7720 notFeasible=1;
7721 break;
7722 }
7723 }
7724 }
7725 }
7726 if (notFeasible)
7727 break;
7728 }
7729 if (notFeasible)
7730 istackC=nstackC+1;
7731 }
7732 for (k=columnStart[jcol];k<columnStart[jcol]+columnLength[jcol];k++) {
7733 // break if found not feasible
7734 if (notFeasible)
7735 break;
7736 irow = row[k];
7737 /*value = columnElements[k];*/
7738 if (markR[irow]!=-2) {
7739 /* see if anything forced */
7740 for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow];kk++) {
7741 double moveUp=0.0;
7742 double moveDown=0.0;
7743 double newUpper=-1.0,newLower=1.0;
7744 kcol=column[kk];
7745 bool onList = (markC[kcol]!=0);
7746 if (markC[kcol]!=3) {
7747 value2=rowElements[kk];
7748 int markIt=markC[kcol];
7749 if (value2 < 0.0) {
7750 if (colUpper[kcol] < 1e10 && (markIt&2)==0 &&
7751 rowUpper[irow]<1.0e10) {
7752 dbound = colUpper[kcol]+
7753 (rowUpper[irow]-minR[irow])/value2;
7754 if (dbound > colLower[kcol] + primalTolerance_) {
7755 if (intVar[kcol]) {
7756 markIt |= 2;
7757 newLower = ceil(dbound-primalTolerance_);
7758 } else {
7759 newLower=dbound;
7760 if (newLower+primalTolerance_>colUpper[kcol]&&
7761 newLower-primalTolerance_<=colUpper[kcol]) {
7762 newLower=colUpper[kcol];
7763 markIt |= 2;
7764 markIt=3;
7765 } else {
7766 // avoid problems - fix later ?
7767 markIt=3;
7768 }
7769 }
7770 moveUp = newLower-colLower[kcol];
7771 }
7772 }
7773 if (colLower[kcol] > -1e10 && (markIt&1)==0 &&
7774 rowLower[irow]>-1.0e10) {
7775 dbound = colLower[kcol] +
7776 (rowLower[irow]-maxR[irow])/value2;
7777 if (dbound < colUpper[kcol] - primalTolerance_) {
7778 if (intVar[kcol]) {
7779 markIt |= 1;
7780 newUpper = floor(dbound+primalTolerance_);
7781 } else {
7782 newUpper=dbound;
7783 if (newUpper-primalTolerance_<colLower[kcol]&&
7784 newUpper+primalTolerance_>=colLower[kcol]) {
7785 newUpper=colLower[kcol];
7786 markIt |= 1;
7787 markIt=3;
7788 } else {
7789 // avoid problems - fix later ?
7790 markIt=3;
7791 }
7792 }
7793 moveDown = newUpper-colUpper[kcol];
7794 }
7795 }
7796 } else {
7797 /* positive element */
7798 if (colUpper[kcol] < 1e10 && (markIt&2)==0 &&
7799 rowLower[irow]>-1.0e10) {
7800 dbound = colUpper[kcol] +
7801 (rowLower[irow]-maxR[irow])/value2;
7802 if (dbound > colLower[kcol] + primalTolerance_) {
7803 if (intVar[kcol]) {
7804 markIt |= 2;
7805 newLower = ceil(dbound-primalTolerance_);
7806 } else {
7807 newLower=dbound;
7808 if (newLower+primalTolerance_>colUpper[kcol]&&
7809 newLower-primalTolerance_<=colUpper[kcol]) {
7810 newLower=colUpper[kcol];
7811 markIt |= 2;
7812 markIt=3;
7813 } else {
7814 // avoid problems - fix later ?
7815 markIt=3;
7816 }
7817 }
7818 moveUp = newLower-colLower[kcol];
7819 }
7820 }
7821 if (colLower[kcol] > -1e10 && (markIt&1)==0 &&
7822 rowUpper[irow]<1.0e10) {
7823 dbound = colLower[kcol] +
7824 (rowUpper[irow]-minR[irow])/value2;
7825 if (dbound < colUpper[kcol] - primalTolerance_) {
7826 if (intVar[kcol]) {
7827 markIt |= 1;
7828 newUpper = floor(dbound+primalTolerance_);
7829 } else {
7830 newUpper=dbound;
7831 if (newUpper-primalTolerance_<colLower[kcol]&&
7832 newUpper+primalTolerance_>=colLower[kcol]) {
7833 newUpper=colLower[kcol];
7834 markIt |= 1;
7835 markIt=3;
7836 } else {
7837 // avoid problems - fix later ?
7838 markIt=3;
7839 }
7840 }
7841 moveDown = newUpper-colUpper[kcol];
7842 }
7843 }
7844 }
7845 if (nstackC<2*maxStack) {
7846 markC[kcol] = markIt;
7847 }
7848 if (moveUp&&nstackC<2*maxStack) {
7849 fixThis++;
7850#ifdef PRINT_DEBUG
7851 printf("lower bound on %d increased from %g to %g by row %d %g %g\n",kcol,colLower[kcol],newLower,irow,rowLower[irow],rowUpper[irow]);
7852 value=0.0;
7853 for (jj=rowStart[irow];jj<rowStart[irow]+rowLength[irow];jj++) {
7854 int ii=column[jj];
7855 if (colUpper[ii]-colLower[ii]>primalTolerance_) {
7856 printf("(%d, %g) ",ii,rowElements[jj]);
7857 } else {
7858 value += rowElements[jj]*colLower[ii];
7859 }
7860 }
7861 printf(" - fixed %g\n",value);
7862 for (jj=rowStart[irow];jj<rowStart[irow]+rowLength[irow];jj++) {
7863 int ii=column[jj];
7864 if (colUpper[ii]-colLower[ii]<primalTolerance_) {
7865 printf("(%d, %g, %g) ",ii,rowElements[jj],colLower[ii]);
7866 }
7867 }
7868 printf("\n");
7869#endif
7870 if (!onList) {
7871 stackC[nstackC]=kcol;
7872 saveL[nstackC]=colLower[kcol];
7873 saveU[nstackC]=colUpper[kcol];
7874 assert (saveU[nstackC]>saveL[nstackC])(static_cast<void> (0));
7875 nstackC++;
7876 onList=true;
7877 }
7878 if (intVar[kcol])
7879 newLower = CoinMax(colLower[kcol],ceil(newLower-1.0e-4));
7880 colLower[kcol]=newLower;
7881 if (fabs(colUpper[kcol]-colLower[kcol])<1.0e-6) {
7882 markC[kcol]=3; // say fixed
7883 }
7884 /* update immediately */
7885 for (jj=columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) {
7886 krow = row[jj];
7887 value = columnElements[jj];
7888 if (markR[krow]==-1) {
7889 stackR[nstackR]=krow;
7890 markR[krow]=nstackR;
7891 saveMin[nstackR]=minR[krow];
7892 saveMax[nstackR]=maxR[krow];
7893 nstackR++;
7894 } else if (markR[krow]==-2) {
7895 continue;
7896 }
7897 /* could check immediately if violation */
7898 /* up */
7899 if (value>0.0) {
7900 /* up does not change - down does */
7901 if (minR[krow]>-1.0e10)
7902 minR[krow] += value*moveUp;
7903 if (minR[krow]>rowUpper[krow]+1.0e-5) {
7904 colUpper[kcol]=-1.0e50; /* force infeasible */
7905 break;
7906 }
7907 } else {
7908 /* down does not change - up does */
7909 if (maxR[krow]<1.0e10)
7910 maxR[krow] += value*moveUp;
7911 if (maxR[krow]<rowLower[krow]-1.0e-5) {
7912 colUpper[kcol]=-1.0e50; /* force infeasible */
7913 break;
7914 }
7915 }
7916 }
7917 }
7918 if (moveDown&&nstackC<2*maxStack) {
7919 fixThis++;
7920#ifdef PRINT_DEBUG
7921 printf("upper bound on %d decreased from %g to %g by row %d %g %g\n",kcol,colUpper[kcol],newUpper,irow,rowLower[irow],rowUpper[irow]);
7922 value=0.0;
7923 for (jj=rowStart[irow];jj<rowStart[irow]+rowLength[irow];jj++) {
7924 int ii=column[jj];
7925 if (colUpper[ii]-colLower[ii]>primalTolerance_) {
7926 printf("(%d, %g) ",ii,rowElements[jj]);
7927 } else {
7928 value += rowElements[jj]*colLower[ii];
7929 }
7930 }
7931 printf(" - fixed %g\n",value);
7932 for (jj=rowStart[irow];jj<rowStart[irow]+rowLength[irow];jj++) {
7933 int ii=column[jj];
7934 if (colUpper[ii]-colLower[ii]<primalTolerance_) {
7935 printf("(%d, %g, %g) ",ii,rowElements[jj],colLower[ii]);
7936 }
7937 }
7938 printf("\n");
7939#endif
7940 if (!onList) {
7941 stackC[nstackC]=kcol;
7942 saveL[nstackC]=colLower[kcol];
7943 saveU[nstackC]=colUpper[kcol];
7944 assert (saveU[nstackC]>saveL[nstackC])(static_cast<void> (0));
7945 nstackC++;
7946 onList=true;
7947 }
7948 if (intVar[kcol])
7949 newUpper = CoinMin(colUpper[kcol],floor(newUpper+1.0e-4));
7950 colUpper[kcol]=newUpper;
7951 if (fabs(colUpper[kcol]-colLower[kcol])<1.0e-6) {
7952 markC[kcol]=3; // say fixed
7953 }
7954 /* update immediately */
7955 for (jj=columnStart[kcol];jj<columnStart[kcol]+columnLength[kcol];jj++) {
7956 krow = row[jj];
7957 value = columnElements[jj];
7958 if (markR[krow]==-1) {
7959 stackR[nstackR]=krow;
7960 markR[krow]=nstackR;
7961 saveMin[nstackR]=minR[krow];
7962 saveMax[nstackR]=maxR[krow];
7963 nstackR++;
7964 } else if (markR[krow]==-2) {
7965 continue;
7966 }
7967 /* could check immediately if violation */
7968 /* down */
7969 if (value<0.0) {
7970 /* up does not change - down does */
7971 if (minR[krow]>-1.0e10)
7972 minR[krow] += value*moveDown;
7973 if (minR[krow]>rowUpper[krow]+1.0e-5) {
7974 colUpper[kcol]=-1.0e50; /* force infeasible */
7975 break;
7976 }
7977 } else {
7978 /* down does not change - up does */
7979 if (maxR[krow]<1.0e10)
7980 maxR[krow] += value*moveDown;
7981 if (maxR[krow]<rowLower[krow]-1.0e-5) {
7982 colUpper[kcol]=-1.0e50; /* force infeasible */
7983 break;
7984 }
7985 }
7986 }
7987 }
7988 if (colLower[kcol]>colUpper[kcol]+primalTolerance_) {
7989 notFeasible=1;;
7990 k=columnStart[jcol]+columnLength[jcol];
7991 istackC=nstackC+1;
7992#ifdef PRINT_DEBUG
7993 printf("** not feasible this way\n");
7994#endif
7995 break;
7996 }
7997 }
7998 }
7999 }
8000 }
8001 istackC++;
8002 }
8003 if (!notFeasible) {
8004 feasible |= feas[iway];
8005 } else if (iway==1&&feasible==0) {
8006 /* not feasible at all */
8007 ninfeas=1;
8008 j=nCols-1;
8009 iLook=nLook;
8010 ipass=maxPass;
8011 break;
8012 }
8013 if (iway==2||(iway==1&&feasible==2)) {
8014 /* keep */
8015 iway=3;
8016 nfixed++;
8017 if (mode_) {
8018 OsiColCut cc;
8019 int nTot=0,nFix=0,nInt=0;
8020 bool ifCut=false;
8021 for (istackC=0;istackC<nstackC;istackC++) {
8022 int icol=stackC[istackC];
8023 if (intVar[icol]) {
8024 if (colUpper[icol]<currentColUpper[icol]-1.0e-4) {
8025 element[nFix]=colUpper[icol];
8026 index[nFix++]=icol;
8027 nInt++;
8028 if (colsol[icol]>colUpper[icol]+primalTolerance_) {
8029 ifCut=true;
8030 anyColumnCuts=true;
8031 }
8032 }
8033 }
8034 }
8035 if (nFix) {
8036 nTot=nFix;
8037 cc.setUbs(nFix,index,element);
8038 nFix=0;
8039 }
8040 for (istackC=0;istackC<nstackC;istackC++) {
8041 int icol=stackC[istackC];
8042 if (intVar[icol]) {
8043 if (colLower[icol]>currentColLower[icol]+1.0e-4) {
8044 element[nFix]=colLower[icol];
8045 index[nFix++]=icol;
8046 nInt++;
8047 if (colsol[icol]<colLower[icol]-primalTolerance_) {
8048 ifCut=true;
8049 anyColumnCuts=true;
8050 }
8051 }
8052 }
8053 }
8054 if (nFix) {
8055 nTot+=nFix;
8056 cc.setLbs(nFix,index,element);
8057 }
8058 // could tighten continuous as well
8059 if (nInt) {
8060 if (ifCut) {
8061 cc.setEffectiveness(100.0);
8062 } else {
8063 cc.setEffectiveness(1.0e-5);
8064 }
8065#ifdef CGL_DEBUG
8066 checkBounds(debugger,cc);
8067#endif
8068 cs.insert(cc);
8069 }
8070 }
8071 for (istackC=0;istackC<nstackC;istackC++) {
8072 int icol=stackC[istackC];
8073 if (colUpper[icol]-colLower[icol]>primalTolerance_) {
8074 markC[icol]=0;
8075 } else {
8076 markC[icol]=3;
8077 }
8078 }
8079 for (istackR=0;istackR<nstackR;istackR++) {
8080 int irow=stackR[istackR];
8081 markR[irow]=-1;
8082 }
8083 } else {
8084 /* is it worth seeing if can increase coefficients
8085 or maybe better see if it is a cut */
8086 if (iway==0) {
8087 nstackC0=CoinMin(nstackC,maxStack);
8088 if (notFeasible) {
8089 nstackC0=0;
8090 } else {
8091 for (istackC=0;istackC<nstackC0;istackC++) {
8092 int icol=stackC[istackC];
8093 stackC0[istackC]=icol;
8094 lo0[istackC]=colLower[icol];
8095 up0[istackC]=colUpper[icol];
8096 }
8097 }
8098 /* restore all */
8099 assert (iway==0)(static_cast<void> (0));
8100 for (istackC=nstackC-1;istackC>=0;istackC--) {
8101 int icol=stackC[istackC];
8102 double oldU=saveU[istackC];
8103 double oldL=saveL[istackC];
8104 colUpper[icol]=oldU;
8105 colLower[icol]=oldL;
8106 markC[icol]=0;
8107 }
8108 for (istackR=0;istackR<nstackR;istackR++) {
8109 int irow=stackR[istackR];
8110 // switch off strengthening if not wanted
8111 if ((rowCuts&2)!=0) {
8112 bool ifCut=anyColumnCuts;
8113 double gap = rowUpper[irow]-maxR[irow];
8114 double sum=0.0;
8115 if (!ifCut&&(gap>primalTolerance_&&gap<1.0e8)) {
8116 // see if the strengthened row is a cut
8117 for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow];
8118 kk++) {
8119 sum += rowElements[kk]*colsol[column[kk]];
8120 }
8121 if (sum-gap*colsol[j]>maxR[irow]+primalTolerance_||info->strengthenRow) {
8122 // can be a cut
8123 // subtract gap from upper and integer coefficient
8124 // saveU and saveL spare
8125 int * index = reinterpret_cast<int *>(saveL);
8126 double * element = saveU;
8127 int n=0;
8128 bool coefficientExists=false;
8129 for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow];
8130 kk++) {
8131 if (column[kk]!=j) {
8132 index[n]=column[kk];
8133 element[n++]=rowElements[kk];
8134 } else {
8135 double value=rowElements[kk]-gap;
8136 if (fabs(value)>1.0e-12) {
8137 index[n]=column[kk];
8138 element[n++]=value;
8139 }
8140 coefficientExists=true;
8141 }
8142 }
8143 if (!coefficientExists) {
8144 index[n]=j;
8145 element[n++]=-gap;
8146 }
8147 OsiRowCut rc;
8148 rc.setLb(-COIN_DBL_MAX);
8149 rc.setUb(rowUpper[irow]-gap*(colLower[j]+1.0));
8150 // effectiveness is how far j moves
8151 rc.setEffectiveness((sum-gap*colsol[j]-maxR[irow])/gap);
8152 if (rc.effectiveness()>needEffectiveness) {
8153 rc.setRow(n,index,element,false);
8154#ifdef CGL_DEBUG
8155 if (debugger) assert(!debugger->invalidCut(rc))(static_cast<void> (0));
8156#endif
8157 // If strengthenRow point to row
8158 //if(info->strengthenRow)
8159 //printf("a point to row %d\n",irow);
8160#ifdef STRENGTHEN_PRINT
8161 {
8162 printf("9Cut %g <= ",rc.lb());
8163 int k;
8164 for ( k=0;k<n;k++) {
8165 int iColumn = index[k];
8166 printf("%g*",element[k]);
8167 if (si.isInteger(iColumn))
8168 printf("i%d ",iColumn);
8169 else
8170 printf("x%d ",iColumn);
8171 }
8172 printf("<= %g\n",rc.ub());
8173 printf("Row %g <= ",rowLower[irow]);
8174 for (k=rowStart[irow];k<rowStart[irow]+rowLength[irow];k++) {
8175 int iColumn = column[k];
8176 printf("%g*",rowElements[k]);
8177 if (si.isInteger(iColumn))
8178 printf("i%d ",iColumn);
8179 else
8180 printf("x%d ",iColumn);
8181 }
8182 printf("<= %g\n",rowUpper[irow]);
8183 }
8184#endif
8185 rowCut.addCutIfNotDuplicate(rc,irow);
8186 }
8187 }
8188 }
8189 gap = minR[irow]-rowLower[irow];
8190 if (!ifCut&&(gap>primalTolerance_&&gap<1.0e8)) {
8191 // see if the strengthened row is a cut
8192 if (!sum) {
8193 for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow];
8194 kk++) {
8195 sum += rowElements[kk]*colsol[column[kk]];
8196 }
8197 }
8198 if (sum+gap*colsol[j]<minR[irow]+primalTolerance_||info->strengthenRow) {
8199 // can be a cut
8200 // add gap to lower and integer coefficient
8201 // saveU and saveL spare
8202 int * index = reinterpret_cast<int *>(saveL);
8203 double * element = saveU;
8204 int n=0;
8205 bool coefficientExists=false;
8206 for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow];
8207 kk++) {
8208 if (column[kk]!=j) {
8209 index[n]=column[kk];
8210 element[n++]=rowElements[kk];
8211 } else {
8212 double value=rowElements[kk]+gap;
8213 if (fabs(value)>1.0e-12) {
8214 index[n]=column[kk];
8215 element[n++]=value;
8216 }
8217 coefficientExists=true;
8218 }
8219 }
8220 if (!coefficientExists) {
8221 index[n]=j;
8222 element[n++]=gap;
8223 }
8224 OsiRowCut rc;
8225 rc.setLb(rowLower[irow]+gap*(colLower[j]+1.0));
8226 rc.setUb(COIN_DBL_MAX);
8227 // effectiveness is how far j moves
8228 rc.setEffectiveness((minR[irow]-sum-gap*colsol[j])/gap);
8229 if (rc.effectiveness()>needEffectiveness) {
8230 rc.setRow(n,index,element,false);
8231#ifdef CGL_DEBUG
8232 if (debugger) assert(!debugger->invalidCut(rc))(static_cast<void> (0));
8233#endif
8234 //if(info->strengthenRow)
8235 //printf("b point to row %d\n",irow);
8236#ifdef STRENGTHEN_PRINT
8237 {
8238 printf("10Cut %g <= ",rc.lb());
8239 int k;
8240 for ( k=0;k<n;k++) {
8241 int iColumn = index[k];
8242 printf("%g*",element[k]);
8243 if (si.isInteger(iColumn))
8244 printf("i%d ",iColumn);
8245 else
8246 printf("x%d ",iColumn);
8247 }
8248 printf("<= %g\n",rc.ub());
8249 printf("Row %g <= ",rowLower[irow]);
8250 for (k=rowStart[irow];k<rowStart[irow]+rowLength[irow];k++) {
8251 int iColumn = column[k];
8252 printf("%g*",rowElements[k]);
8253 if (si.isInteger(iColumn))
8254 printf("i%d ",iColumn);
8255 else
8256 printf("x%d ",iColumn);
8257 }
8258 printf("<= %g\n",rowUpper[irow]);
8259 }
8260#endif
8261 rowCut.addCutIfNotDuplicate(rc,irow);
8262 }
8263 }
8264 }
8265 }
8266 minR[irow]=saveMin[istackR];
8267 maxR[irow]=saveMax[istackR];
8268 markR[irow]=-1;
8269 }
8270 } else {
8271 if (iway==1&&feasible==3) {
8272 iway=3;
8273 /* point back to stack */
8274 for (istackC=nstackC-1;istackC>=0;istackC--) {
8275 int icol=stackC[istackC];
8276 markC[icol]=istackC+1000;
8277 }
8278 if (mode_) {
8279 OsiColCut cc;
8280 int nTot=0,nFix=0,nInt=0;
8281 bool ifCut=false;
8282 for (istackC=0;istackC<nstackC0;istackC++) {
8283 int icol=stackC0[istackC];
8284 int istackC1=markC[icol]-1000;
8285 if (istackC1>=0) {
8286 if (CoinMin(lo0[istackC],colLower[icol])>saveL[istackC1]+1.0e-4) {
8287 saveL[istackC1]=CoinMin(lo0[istackC],colLower[icol]);
8288 if (intVar[icol]) {
8289 element[nFix]=saveL[istackC1];
8290 index[nFix++]=icol;
8291 nInt++;
8292 if (colsol[icol]<saveL[istackC1]-primalTolerance_)
8293 ifCut=true;
8294 }
8295 nfixed++;
8296 }
8297 }
8298 }
8299 if (nFix) {
8300 nTot=nFix;
8301 cc.setLbs(nFix,index,element);
8302 nFix=0;
8303 }
8304 for (istackC=0;istackC<nstackC0;istackC++) {
8305 int icol=stackC0[istackC];
8306 int istackC1=markC[icol]-1000;
8307 if (istackC1>=0) {
8308 if (CoinMax(up0[istackC],colUpper[icol])<saveU[istackC1]-1.0e-4) {
8309 saveU[istackC1]=CoinMax(up0[istackC],colUpper[icol]);
8310 if (intVar[icol]) {
8311 element[nFix]=saveU[istackC1];
8312 index[nFix++]=icol;
8313 nInt++;
8314 if (colsol[icol]>saveU[istackC1]+primalTolerance_)
8315 ifCut=true;
8316 }
8317 nfixed++;
8318 }
8319 }
8320 }
8321 if (nFix) {
8322 nTot+=nFix;
8323 cc.setUbs(nFix,index,element);
8324 }
8325 // could tighten continuous as well
8326 if (nInt) {
8327 if (ifCut) {
8328 cc.setEffectiveness(100.0);
8329 } else {
8330 cc.setEffectiveness(1.0e-5);
8331 }
8332#ifdef CGL_DEBUG
8333 checkBounds(debugger,cc);
8334#endif
8335 cs.insert(cc);
8336 }
8337 }
8338 }
8339 /* restore all */
8340 for (istackC=nstackC-1;istackC>=0;istackC--) {
8341 int icol=stackC[istackC];
8342 double oldU=saveU[istackC];
8343 double oldL=saveL[istackC];
8344 colUpper[icol]=oldU;
8345 colLower[icol]=oldL;
8346 if (oldU>oldL+1.0e-4)
8347 markC[icol]=0;
8348 else
8349 markC[icol]=3;
8350 }
8351 for (istackR=0;istackR<nstackR;istackR++) {
8352 int irow=stackR[istackR];
8353 // switch off strengthening if not wanted
8354 if ((rowCuts&2)!=0) {
8355 bool ifCut=anyColumnCuts;
8356 double gap = rowUpper[irow]-maxR[irow];
8357 double sum=0.0;
8358 if (!ifCut&&(gap>primalTolerance_&&gap<1.0e8)) {
8359 // see if the strengthened row is a cut
8360 for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow];
8361 kk++) {
8362 sum += rowElements[kk]*colsol[column[kk]];
8363 }
8364 if (sum+gap*colsol[j]>rowUpper[irow]+primalTolerance_||info->strengthenRow) {
8365 // can be a cut
8366 // add gap to integer coefficient
8367 // saveU and saveL spare
8368 int * index = reinterpret_cast<int *>(saveL);
8369 double * element = saveU;
8370 int n=0;
8371 bool coefficientExists=false;
8372 for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow];
8373 kk++) {
8374 if (column[kk]!=j) {
8375 index[n]=column[kk];
8376 element[n++]=rowElements[kk];
8377 } else {
8378 double value=rowElements[kk]+gap;
8379 if (fabs(value)>1.0e-12) {
8380 index[n]=column[kk];
8381 element[n++]=value;
8382 }
8383 coefficientExists=true;
8384 }
8385 }
8386 if (!coefficientExists) {
8387 index[n]=j;
8388 element[n++]=gap;
8389 }
8390 OsiRowCut rc;
8391 rc.setLb(-COIN_DBL_MAX);
8392 rc.setUb(rowUpper[irow]+gap*(colUpper[j]-1.0));
8393 // effectiveness is how far j moves
8394 rc.setEffectiveness((sum+gap*colsol[j]-rowUpper[irow])/gap);
8395 if (rc.effectiveness()>needEffectiveness) {
8396 rc.setRow(n,index,element,false);
8397#ifdef CGL_DEBUG
8398 if (debugger) assert(!debugger->invalidCut(rc))(static_cast<void> (0));
8399#endif
8400 //if(info->strengthenRow)
8401 //printf("c point to row %d\n",irow);
8402#ifdef STRENGTHEN_PRINT
8403 {
8404 printf("11Cut %g <= ",rc.lb());
8405 int k;
8406 for ( k=0;k<n;k++) {
8407 int iColumn = index[k];
8408 printf("%g*",element[k]);
8409 if (si.isInteger(iColumn))
8410 printf("i%d ",iColumn);
8411 else
8412 printf("x%d ",iColumn);
8413 }
8414 printf("<= %g\n",rc.ub());
8415 printf("Row %g <= ",rowLower[irow]);
8416 for (k=rowStart[irow];k<rowStart[irow]+rowLength[irow];k++) {
8417 int iColumn = column[k];
8418 printf("%g*",rowElements[k]);
8419 if (si.isInteger(iColumn))
8420 printf("i%d ",iColumn);
8421 else
8422 printf("x%d ",iColumn);
8423 }
8424 printf("<= %g\n",rowUpper[irow]);
8425 }
8426#endif
8427 rowCut.addCutIfNotDuplicate(rc,irow);
8428 }
8429 }
8430 }
8431 gap = minR[irow]-rowLower[irow];
8432 if (!ifCut&&(gap>primalTolerance_&&gap<1.0e8)) {
8433 // see if the strengthened row is a cut
8434 if (!sum) {
8435 for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow];
8436 kk++) {
8437 sum += rowElements[kk]*colsol[column[kk]];
8438 }
8439 }
8440 if (sum-gap*colsol[j]<rowLower[irow]+primalTolerance_||info->strengthenRow) {
8441 // can be a cut
8442 // subtract gap from integer coefficient
8443 // saveU and saveL spare
8444 int * index = reinterpret_cast<int *>(saveL);
8445 double * element = saveU;
8446 int n=0;
8447 bool coefficientExists=false;
8448 for (kk=rowStart[irow];kk<rowStart[irow]+rowLength[irow];
8449 kk++) {
8450 if (column[kk]!=j) {
8451 index[n]=column[kk];
8452 element[n++]=rowElements[kk];
8453 } else {
8454 double value=rowElements[kk]-gap;
8455 if (fabs(value)>1.0e-12) {
8456 index[n]=column[kk];
8457 element[n++]=value;
8458 }
8459 coefficientExists=true;
8460 }
8461 }
8462 if (!coefficientExists) {
8463 index[n]=j;
8464 element[n++]=-gap;
8465 }
8466 OsiRowCut rc;
8467 rc.setLb(rowLower[irow]-gap*(colUpper[j]-1));
8468 rc.setUb(COIN_DBL_MAX);
8469 // effectiveness is how far j moves
8470 rc.setEffectiveness((rowLower[irow]-sum+gap*colsol[j])/gap);
8471 if (rc.effectiveness()>needEffectiveness) {
8472 rc.setRow(n,index,element,false);
8473#ifdef CGL_DEBUG
8474 if (debugger) assert(!debugger->invalidCut(rc))(static_cast<void> (0));
8475#endif
8476 //if(info->strengthenRow)
8477 //printf("d point to row %d\n",irow);
8478#ifdef STRENGTHEN_PRINT
8479 {
8480 printf("12Cut %g <= ",rc.lb());
8481 int k;
8482 for ( k=0;k<n;k++) {
8483 int iColumn = index[k];
8484 printf("%g*",element[k]);
8485 if (si.isInteger(iColumn))
8486 printf("i%d ",iColumn);
8487 else
8488 printf("x%d ",iColumn);
8489 }
8490 printf("<= %g\n",rc.ub());
8491 printf("Row %g <= ",rowLower[irow]);
8492 for (k=rowStart[irow];k<rowStart[irow]+rowLength[irow];k++) {
8493 int iColumn = column[k];
8494 printf("%g*",rowElements[k]);
8495 if (si.isInteger(iColumn))
8496 printf("i%d ",iColumn);
8497 else
8498 printf("x%d ",iColumn);
8499 }
8500 printf("<= %g\n",rowUpper[irow]);
8501 }
8502#endif
8503 rowCut.addCutIfNotDuplicate(rc,irow);
8504 }
8505 }
8506 }
8507 }
8508 minR[irow]=saveMin[istackR];
8509 maxR[irow]=saveMax[istackR];
8510 markR[irow]=-1;
8511 }
8512 }
8513 }
8514 }
8515 }
8516 }
8517 delete [] stackC0;
8518 delete [] lo0;
8519 delete [] up0;
8520 delete [] tempL;
8521 delete [] tempU;
8522 delete [] markC;
8523 delete [] stackC;
8524 delete [] stackR;
8525 delete [] saveL;
8526 delete [] saveU;
8527 delete [] saveMin;
8528 delete [] saveMax;
8529 delete [] index;
8530 delete [] element;
8531 delete [] colsol;
8532 // Add in row cuts
8533 if (!ninfeas) {
8534 rowCut.addCuts(cs,info->strengthenRow,0);
8535 }
8536 delete [] array;
8537 abort();
8538 return (ninfeas);
8539}
8540// Create a copy of matrix which is to be used
8541// this is to speed up process and to give global cuts
8542// Can give an array with 1 set to select, 0 to ignore
8543// column bounds are tightened
8544// If array given then values of 1 will be set to 0 if redundant
8545int CglProbing::snapshot ( const OsiSolverInterface & si,
8546 char * possible,bool withObjective)
8547{
8548 deleteSnapshot();
8549 // Get basic problem information
8550
8551 numberColumns_=si.getNumCols();
8552 numberRows_=si.getNumRows();
8553 colLower_ = new double[numberColumns_];
8554 colUpper_ = new double[numberColumns_];
8555 CoinMemcpyN(si.getColLower(),numberColumns_,colLower_);
8556 CoinMemcpyN(si.getColUpper(),numberColumns_,colUpper_);
8557 rowLower_= new double [numberRows_+1];
8558 rowUpper_= new double [numberRows_+1];
8559 CoinMemcpyN(si.getRowLower(),numberRows_,rowLower_);
8560 CoinMemcpyN(si.getRowUpper(),numberRows_,rowUpper_);
8561
8562 int i;
8563 if (possible) {
8564 for (i=0;i<numberRows_;i++) {
8565 if (!possible[i]) {
8566 rowLower_[i]=-COIN_DBL_MAX;
8567 rowUpper_[i]=COIN_DBL_MAX;
8568 }
8569 }
8570 }
8571
8572
8573 // get integer variables
8574 const char * intVarOriginal = si.getColType(true);
8575 char * intVar = CoinCopyOfArray(intVarOriginal,numberColumns_);
8576 numberIntegers_=0;
8577 number01Integers_=0;
8578 for (i=0;i<numberColumns_;i++) {
8579 if (intVar[i]) {
8580 numberIntegers_++;
8581 if (intVar[i]==1) {
8582 number01Integers_++;
8583 }
8584 }
8585 }
8586
8587 rowCopy_ = new CoinPackedMatrix(*si.getMatrixByRow());
8588
8589 int * column = rowCopy_->getMutableIndices();
8590 const CoinBigIndex * rowStart = rowCopy_->getVectorStarts();
8591 const int * rowLength = rowCopy_->getVectorLengths();
8592 double * rowElements = rowCopy_->getMutableElements();
8593 // Put negative first
8594 int * column2 = new int[numberColumns_];
8595 double * elements2 = new double[numberColumns_];
8596 CoinBigIndex * rowStartPos = new CoinBigIndex [numberRows_];
8597 for (int i=0;i<numberRows_;i++) {
8598 CoinBigIndex start = rowStart[i];
8599 CoinBigIndex end = start + rowLength[i];
8600 int nOther=0;
8601 for (CoinBigIndex j=start; j<end ; j++) {
8602 int iColumn = column[j];
8603 double value = rowElements[j];
8604 if (value<0.0) {
8605 rowElements[start]=value;
8606 column[start++]=iColumn;
8607 } else {
8608 elements2[nOther]=value;
8609 column2[nOther++]=iColumn;
8610 }
8611 }
8612 rowStartPos[i] = start;
8613 for (int k=0;k<nOther;k++) {
8614 rowElements[start]=elements2[k];
8615 column[start++]=column2[k];
8616 }
8617 }
8618 delete [] column2;
8619 delete [] elements2;
8620
8621 int returnCode=0;
8622 int ninfeas=
8623 tighten(colLower_, colUpper_, column, rowElements,
8624 rowStart, NULL__null,rowLength, rowLower_, rowUpper_,
8625 numberRows_, numberColumns_, intVar, 5, primalTolerance_);
8626 delete [] rowStartPos;
8627 if (ninfeas) {
8628 // let someone else find out
8629 returnCode = 1;
8630 }
8631/*
8632 QUESTION: If ninfeas > 1 (one or more variables infeasible), shouldn't we
8633 bail out here?
8634*/
8635
8636 // do integer stuff for mode 0
8637 cutVector_ = new disaggregation [number01Integers_];
8638 memset(cutVector_,0,number01Integers_*sizeof(disaggregation));
8639 number01Integers_=0;
8640 for (i=0;i<numberColumns_;i++) {
8641 if (intVar[i]==1)
8642 cutVector_[number01Integers_++].sequence=i;
8643 }
8644 delete [] intVar;
8645
8646 // now delete rows
8647 if (possible) {
8648 for (i=0;i<numberRows_;i++) {
8649 if (rowLower_[i]<-1.0e30&&rowUpper_[i]>1.0e30)
8650 possible[i]=0;
8651 }
8652 }
8653 int * index = new int[numberRows_];
8654 int nDrop=0,nKeep=0;
8655 for (i=0;i<numberRows_;i++) {
8656 if (rowLower_[i]<-1.0e30&&rowUpper_[i]>1.0e30) {
8657 index[nDrop++]=i;
8658 } else {
8659 rowLower_[nKeep]=rowLower_[i];
8660 rowUpper_[nKeep++]=rowUpper_[i];
8661 }
8662 }
8663 numberRows_=nKeep;
8664 if (nDrop)
8665 rowCopy_->deleteRows(nDrop,index);
8666 delete [] index;
8667 if (withObjective) {
8668 // add in objective
8669 int * columns = new int[numberColumns_];
8670 double * elements = new double[numberColumns_];
8671 int n=0;
8672 const double * objective = si.getObjCoefficients();
8673 bool maximize = (si.getObjSense()==-1);
8674 for (i=0;i<numberColumns_;i++) {
8675 if (objective[i]) {
8676 elements[n]= (maximize) ? -objective[i] : objective[i];
8677 columns[n++]=i;
8678 }
8679 }
8680 rowCopy_->appendRow(n,columns,elements);
8681 delete [] columns;
8682 delete [] elements;
8683 numberRows_++;
8684 }
8685 // create column copy
8686 if (rowCopy_->getNumElements()) {
8687 columnCopy_=new CoinPackedMatrix(*rowCopy_,0,0,true);
8688 } else {
8689 columnCopy_=new CoinPackedMatrix();
8690 }
8691 // make sure big enough - in case too many rows dropped
8692 columnCopy_->setDimensions(numberRows_,numberColumns_);
8693 rowCopy_->setDimensions(numberRows_,numberColumns_);
8694 return returnCode;
8695}
8696// Delete snapshot
8697void CglProbing::deleteSnapshot()
8698{
8699 delete [] rowLower_;
8700 delete [] rowUpper_;
8701 delete [] colLower_;
8702 delete [] colUpper_;
8703 delete rowCopy_;
8704 delete columnCopy_;
8705 rowCopy_=NULL__null;
8706 columnCopy_=NULL__null;
8707 rowLower_=NULL__null;
8708 rowUpper_=NULL__null;
8709 colLower_=NULL__null;
8710 colUpper_=NULL__null;
8711 int i;
8712 for (i=0;i<number01Integers_;i++) {
8713 delete [] cutVector_[i].index;
8714 }
8715 delete [] cutVector_;
8716 numberIntegers_=0;
8717 number01Integers_=0;
8718 cutVector_=NULL__null;
8719}
8720// Mode stuff
8721void CglProbing::setMode(int mode)
8722{
8723 if (mode>=0&&mode<3) {
8724 // take off bottom bit
8725 mode_ &= ~15;
8726 mode_ |= mode;
8727 }
8728}
8729int CglProbing::getMode() const
8730{
8731 return mode_&15;
8732}
8733// Set maximum number of passes per node
8734void CglProbing::setMaxPass(int value)
8735{
8736 if (value>0)
8737 maxPass_=value;
8738}
8739// Get maximum number of passes per node
8740int CglProbing::getMaxPass() const
8741{
8742 return maxPass_;
8743}
8744// Set log level
8745void CglProbing::setLogLevel(int value)
8746{
8747 if (value>=0)
8748 logLevel_=value;
8749}
8750// Get log level
8751int CglProbing::getLogLevel() const
8752{
8753 return logLevel_;
8754}
8755// Set maximum number of unsatisfied variables to look at
8756void CglProbing::setMaxProbe(int value)
8757{
8758 if (value>=0)
8759 maxProbe_=value;
8760}
8761// Get maximum number of unsatisfied variables to look at
8762int CglProbing::getMaxProbe() const
8763{
8764 return maxProbe_;
8765}
8766// Set maximum number of variables to look at in one probe
8767void CglProbing::setMaxLook(int value)
8768{
8769 if (value>=0)
8770 maxStack_=value;
8771}
8772// Get maximum number of variables to look at in one probe
8773int CglProbing::getMaxLook() const
8774{
8775 return maxStack_;
8776}
8777// Set maximum number of elements in row for scan
8778void CglProbing::setMaxElements(int value)
8779{
8780 if (value>0)
8781 maxElements_=value;
8782}
8783// Get maximum number of elements in row for scan
8784int CglProbing::getMaxElements() const
8785{
8786 return maxElements_;
8787}
8788// Set maximum number of passes per node (root node)
8789void CglProbing::setMaxPassRoot(int value)
8790{
8791 if (value>0)
8792 maxPassRoot_=value;
8793}
8794// Get maximum number of passes per node (root node)
8795int CglProbing::getMaxPassRoot() const
8796{
8797 return maxPassRoot_;
8798}
8799// Set maximum number of unsatisfied variables to look at (root node)
8800void CglProbing::setMaxProbeRoot(int value)
8801{
8802 if (value>0)
8803 maxProbeRoot_=value;
8804}
8805// Get maximum number of unsatisfied variables to look at (root node)
8806int CglProbing::getMaxProbeRoot() const
8807{
8808 return maxProbeRoot_;
8809}
8810// Set maximum number of variables to look at in one probe (root node)
8811void CglProbing::setMaxLookRoot(int value)
8812{
8813 if (value>0)
8814 maxStackRoot_=value;
8815}
8816// Get maximum number of variables to look at in one probe (root node)
8817int CglProbing::getMaxLookRoot() const
8818{
8819 return maxStackRoot_;
8820}
8821// Set maximum number of elements in row for scan (root node)
8822void CglProbing::setMaxElementsRoot(int value)
8823{
8824 if (value>0)
8825 maxElementsRoot_=value;
8826}
8827// Get maximum number of elements in row for scan (root node)
8828int CglProbing::getMaxElementsRoot() const
8829{
8830 return maxElementsRoot_;
8831}
8832// Set whether to use objective
8833void CglProbing::setUsingObjective(int yesNo)
8834{
8835 usingObjective_=yesNo;
8836}
8837// Get whether objective is being used
8838int CglProbing::getUsingObjective() const
8839{
8840 return usingObjective_;
8841}
8842// Decide whether to do row cuts
8843void CglProbing::setRowCuts(int type)
8844{
8845 if (type>-5&&type<5)
8846 rowCuts_=type;
8847}
8848// Returns row cuts generation type
8849int CglProbing::rowCuts() const
8850{
8851 return rowCuts_;
8852}
8853// Returns tight lower
8854const double * CglProbing::tightLower() const
8855{
8856 return colLower_;
8857}
8858// Returns tight upper
8859const double * CglProbing::tightUpper() const
8860{
8861 return colUpper_;
8862}
8863// Returns relaxed Row lower
8864const double * CglProbing::relaxedRowLower() const
8865{
8866 return rowLower_;
8867}
8868// Returns relaxed Row upper
8869const double * CglProbing::relaxedRowUpper() const
8870{
8871 return rowUpper_;
8872}
8873
8874
8875//-------------------------------------------------------------------
8876// Default Constructor
8877//-------------------------------------------------------------------
8878CglProbing::CglProbing ()
8879:
8880CglCutGenerator(),
8881primalTolerance_(1.0e-07),
8882mode_(1),
8883rowCuts_(1),
8884maxPass_(3),
8885logLevel_(0),
8886maxProbe_(100),
8887maxStack_(50),
8888maxElements_(1000),
8889maxPassRoot_(3),
8890maxProbeRoot_(100),
8891maxStackRoot_(50),
8892maxElementsRoot_(10000),
8893usingObjective_(0)
8894{
8895
8896 numberRows_=0;
8897 numberColumns_=0;
8898 rowCopy_=NULL__null;
8899 columnCopy_=NULL__null;
8900 rowLower_=NULL__null;
8901 rowUpper_=NULL__null;
8902 colLower_=NULL__null;
8903 colUpper_=NULL__null;
8904 numberIntegers_=0;
8905 number01Integers_=0;
8906 numberThisTime_=0;
8907 totalTimesCalled_=0;
8908 lookedAt_=NULL__null;
8909 cutVector_=NULL__null;
8910 numberCliques_=0;
8911 cliqueType_=NULL__null;
8912 cliqueStart_=NULL__null;
8913 cliqueEntry_=NULL__null;
8914 oneFixStart_=NULL__null;
8915 zeroFixStart_=NULL__null;
8916 endFixStart_=NULL__null;
8917 whichClique_=NULL__null;
8918 cliqueRow_=NULL__null;
8919 cliqueRowStart_=NULL__null;
8920 tightenBounds_=NULL__null;
8921}
8922
8923//-------------------------------------------------------------------
8924// Copy constructor
8925//-------------------------------------------------------------------
8926CglProbing::CglProbing ( const CglProbing & rhs)
8927 :
8928 CglCutGenerator(rhs),
8929 primalTolerance_(rhs.primalTolerance_),
8930 mode_(rhs.mode_),
8931 rowCuts_(rhs.rowCuts_),
8932 maxPass_(rhs.maxPass_),
8933 logLevel_(rhs.logLevel_),
8934 maxProbe_(rhs.maxProbe_),
8935 maxStack_(rhs.maxStack_),
8936 maxElements_(rhs.maxElements_),
8937 maxPassRoot_(rhs.maxPassRoot_),
8938 maxProbeRoot_(rhs.maxProbeRoot_),
8939 maxStackRoot_(rhs.maxStackRoot_),
8940 maxElementsRoot_(rhs.maxElementsRoot_),
8941 usingObjective_(rhs.usingObjective_)
8942{
8943 numberRows_=rhs.numberRows_;
8944 numberColumns_=rhs.numberColumns_;
8945 numberCliques_=rhs.numberCliques_;
8946 if (rhs.rowCopy_) {
8947 rowCopy_= new CoinPackedMatrix(*(rhs.rowCopy_));
8948 columnCopy_= new CoinPackedMatrix(*(rhs.columnCopy_));
8949 rowLower_=new double[numberRows_];
8950 CoinMemcpyN(rhs.rowLower_,numberRows_,rowLower_);
8951 rowUpper_=new double[numberRows_];
8952 CoinMemcpyN(rhs.rowUpper_,numberRows_,rowUpper_);
8953 colLower_=new double[numberColumns_];
8954 CoinMemcpyN(rhs.colLower_,numberColumns_,colLower_);
8955 colUpper_=new double[numberColumns_];
8956 CoinMemcpyN(rhs.colUpper_,numberColumns_,colUpper_);
8957 int i;
8958 numberIntegers_=rhs.numberIntegers_;
8959 number01Integers_=rhs.number01Integers_;
8960 cutVector_=new disaggregation [number01Integers_];
8961 CoinMemcpyN(rhs.cutVector_,number01Integers_,cutVector_);
8962 for (i=0;i<number01Integers_;i++) {
8963 if (cutVector_[i].index) {
8964 cutVector_[i].index = CoinCopyOfArray(rhs.cutVector_[i].index,cutVector_[i].length);
8965 }
8966 }
8967 } else {
8968 rowCopy_=NULL__null;
8969 columnCopy_=NULL__null;
8970 rowLower_=NULL__null;
8971 rowUpper_=NULL__null;
8972 colLower_=NULL__null;
8973 colUpper_=NULL__null;
8974 numberIntegers_=0;
8975 number01Integers_=0;
8976 cutVector_=NULL__null;
8977 }
8978 numberThisTime_=rhs.numberThisTime_;
8979 totalTimesCalled_=rhs.totalTimesCalled_;
8980 if (numberColumns_)
8981 lookedAt_=CoinCopyOfArray(rhs.lookedAt_,numberColumns_);
8982 else
8983 lookedAt_ = NULL__null;
8984 if (numberCliques_) {
8985 cliqueType_ = new cliqueType [numberCliques_];
8986 CoinMemcpyN(rhs.cliqueType_,numberCliques_,cliqueType_);
8987 cliqueStart_ = new int [numberCliques_+1];
8988 CoinMemcpyN(rhs.cliqueStart_,(numberCliques_+1),cliqueStart_);
8989 int n = cliqueStart_[numberCliques_];
8990 cliqueEntry_ = new cliqueEntry [n];
8991 CoinMemcpyN(rhs.cliqueEntry_,n,cliqueEntry_);
8992 oneFixStart_ = new int [numberColumns_];
8993 CoinMemcpyN(rhs.oneFixStart_,numberColumns_,oneFixStart_);
8994 zeroFixStart_ = new int [numberColumns_];
8995 CoinMemcpyN(rhs.zeroFixStart_,numberColumns_,zeroFixStart_);
8996 endFixStart_ = new int [numberColumns_];
8997 CoinMemcpyN(rhs.endFixStart_,numberColumns_,endFixStart_);
8998#ifndef NDEBUG1
8999 int n2=-1;
9000 for (int i=numberColumns_-1;i>=0;i--) {
9001 if (oneFixStart_[i]>=0) {
9002 n2=endFixStart_[i];
9003 break;
9004 }
9005 }
9006 assert (n==n2)(static_cast<void> (0));
9007#endif
9008 whichClique_ = new int [n];
9009 CoinMemcpyN(rhs.whichClique_,n,whichClique_);
9010 if (rhs.cliqueRowStart_) {
9011 cliqueRowStart_ = CoinCopyOfArray(rhs.cliqueRowStart_,numberRows_+1);
9012 n=cliqueRowStart_[numberRows_];
9013 cliqueRow_ = CoinCopyOfArray(rhs.cliqueRow_,n);
9014 } else {
9015 cliqueRow_=NULL__null;
9016 cliqueRowStart_=NULL__null;
9017 }
9018 } else {
9019 cliqueType_=NULL__null;
9020 cliqueStart_=NULL__null;
9021 cliqueEntry_=NULL__null;
9022 oneFixStart_=NULL__null;
9023 zeroFixStart_=NULL__null;
9024 endFixStart_=NULL__null;
9025 cliqueRow_=NULL__null;
9026 cliqueRowStart_=NULL__null;
9027 whichClique_=NULL__null;
9028 }
9029 if (rhs.tightenBounds_) {
9030 assert (numberColumns_)(static_cast<void> (0));
9031 tightenBounds_=CoinCopyOfArray(rhs.tightenBounds_,numberColumns_);
9032 } else {
9033 tightenBounds_=NULL__null;
9034 }
9035}
9036
9037//-------------------------------------------------------------------
9038// Clone
9039//-------------------------------------------------------------------
9040CglCutGenerator *
9041CglProbing::clone() const
9042{
9043 return new CglProbing(*this);
9044}
9045
9046//-------------------------------------------------------------------
9047// Destructor
9048//-------------------------------------------------------------------
9049CglProbing::~CglProbing ()
9050{
9051 // free memory
9052 delete [] rowLower_;
9053 delete [] rowUpper_;
9054 delete [] colLower_;
9055 delete [] colUpper_;
9056 delete rowCopy_;
9057 delete columnCopy_;
9058 delete [] lookedAt_;
9059 delete [] cliqueType_;
9060 delete [] cliqueStart_;
9061 delete [] cliqueEntry_;
9062 delete [] oneFixStart_;
9063 delete [] zeroFixStart_;
9064 delete [] endFixStart_;
9065 delete [] whichClique_;
9066 delete [] cliqueRow_;
9067 delete [] cliqueRowStart_;
9068 if (cutVector_) {
9069 for (int i=0;i<number01Integers_;i++) {
9070 delete [] cutVector_[i].index;
9071 }
9072 delete [] cutVector_;
9073 }
9074 delete [] tightenBounds_;
9075}
9076
9077//----------------------------------------------------------------
9078// Assignment operator
9079//-------------------------------------------------------------------
9080CglProbing &
9081CglProbing::operator=(
9082 const CglProbing& rhs)
9083{
9084 if (this != &rhs) {
9085 CglCutGenerator::operator=(rhs);
9086 primalTolerance_=rhs.primalTolerance_;
9087 numberRows_=rhs.numberRows_;
9088 numberColumns_=rhs.numberColumns_;
9089 delete [] rowLower_;
9090 delete [] rowUpper_;
9091 delete [] colLower_;
9092 delete [] colUpper_;
9093 delete rowCopy_;
9094 delete columnCopy_;
9095 delete [] lookedAt_;
9096 delete [] cliqueType_;
9097 delete [] cliqueStart_;
9098 delete [] cliqueEntry_;
9099 delete [] oneFixStart_;
9100 delete [] zeroFixStart_;
9101 delete [] endFixStart_;
9102 delete [] whichClique_;
9103 delete [] cliqueRow_;
9104 delete [] cliqueRowStart_;
9105 delete [] tightenBounds_;
9106 mode_=rhs.mode_;
9107 rowCuts_=rhs.rowCuts_;
9108 maxPass_=rhs.maxPass_;
9109 logLevel_=rhs.logLevel_;
9110 maxProbe_=rhs.maxProbe_;
9111 maxStack_=rhs.maxStack_;
9112 maxElements_ = rhs.maxElements_;
9113 maxPassRoot_ = rhs.maxPassRoot_;
9114 maxProbeRoot_ = rhs.maxProbeRoot_;
9115 maxStackRoot_ = rhs.maxStackRoot_;
9116 maxElementsRoot_ = rhs.maxElementsRoot_;
9117 usingObjective_=rhs.usingObjective_;
9118 numberCliques_=rhs.numberCliques_;
9119 if (rhs.rowCopy_) {
9120 rowCopy_= new CoinPackedMatrix(*(rhs.rowCopy_));
9121 columnCopy_= new CoinPackedMatrix(*(rhs.columnCopy_));
9122 rowLower_=new double[numberRows_];
9123 CoinMemcpyN(rhs.rowLower_,numberRows_,rowLower_);
9124 rowUpper_=new double[numberRows_];
9125 CoinMemcpyN(rhs.rowUpper_,numberRows_,rowUpper_);
9126 colLower_=new double[numberColumns_];
9127 CoinMemcpyN(rhs.colLower_,numberColumns_,colLower_);
9128 colUpper_=new double[numberColumns_];
9129 CoinMemcpyN(rhs.colUpper_,numberColumns_,colUpper_);
9130 int i;
9131 numberIntegers_=rhs.numberIntegers_;
9132 number01Integers_=rhs.number01Integers_;
9133 for (i=0;i<number01Integers_;i++) {
9134 delete [] cutVector_[i].index;
9135 }
9136 delete [] cutVector_;
9137 cutVector_=new disaggregation [number01Integers_];
9138 CoinMemcpyN(rhs.cutVector_,number01Integers_,cutVector_);
9139 for (i=0;i<number01Integers_;i++) {
9140 if (cutVector_[i].index) {
9141 cutVector_[i].index = CoinCopyOfArray(rhs.cutVector_[i].index,cutVector_[i].length);
9142 }
9143 }
9144 } else {
9145 rowCopy_=NULL__null;
9146 columnCopy_=NULL__null;
9147 rowLower_=NULL__null;
9148 rowUpper_=NULL__null;
9149 colLower_=NULL__null;
9150 colUpper_=NULL__null;
9151 numberIntegers_=0;
9152 number01Integers_=0;
9153 cutVector_=NULL__null;
9154 }
9155 numberThisTime_=rhs.numberThisTime_;
9156 totalTimesCalled_=rhs.totalTimesCalled_;
9157 if (numberColumns_)
9158 lookedAt_=CoinCopyOfArray(rhs.lookedAt_,numberColumns_);
9159 else
9160 lookedAt_ = NULL__null;
9161 if (numberCliques_) {
9162 cliqueType_ = new cliqueType [numberCliques_];
9163 CoinMemcpyN(rhs.cliqueType_,numberCliques_,cliqueType_);
9164 cliqueStart_ = new int [numberCliques_+1];
9165 CoinMemcpyN(rhs.cliqueStart_,(numberCliques_+1),cliqueStart_);
9166 int n = cliqueStart_[numberCliques_];
9167 cliqueEntry_ = new cliqueEntry [n];
9168 CoinMemcpyN(rhs.cliqueEntry_,n,cliqueEntry_);
9169 oneFixStart_ = new int [numberColumns_];
9170 CoinMemcpyN(rhs.oneFixStart_,numberColumns_,oneFixStart_);
9171 zeroFixStart_ = new int [numberColumns_];
9172 CoinMemcpyN(rhs.zeroFixStart_,numberColumns_,zeroFixStart_);
9173 endFixStart_ = new int [numberColumns_];
9174 CoinMemcpyN(rhs.endFixStart_,numberColumns_,endFixStart_);
9175#ifndef NDEBUG1
9176 int n2=-1;
9177 for (int i=numberColumns_-1;i>=0;i--) {
9178 if (oneFixStart_[i]>=0) {
9179 n2=endFixStart_[i];
9180 break;
9181 }
9182 }
9183 assert (n==n2)(static_cast<void> (0));
9184#endif
9185 whichClique_ = new int [n];
9186 CoinMemcpyN(rhs.whichClique_,n,whichClique_);
9187 if (rhs.cliqueRowStart_) {
9188 cliqueRowStart_ = CoinCopyOfArray(rhs.cliqueRowStart_,numberRows_+1);
9189 n=cliqueRowStart_[numberRows_];
9190 cliqueRow_ = CoinCopyOfArray(rhs.cliqueRow_,n);
9191 } else {
9192 cliqueRow_=NULL__null;
9193 cliqueRowStart_=NULL__null;
9194 }
9195 } else {
9196 cliqueType_=NULL__null;
9197 cliqueStart_=NULL__null;
9198 cliqueEntry_=NULL__null;
9199 oneFixStart_=NULL__null;
9200 zeroFixStart_=NULL__null;
9201 endFixStart_=NULL__null;
9202 whichClique_=NULL__null;
9203 cliqueRow_=NULL__null;
9204 cliqueRowStart_=NULL__null;
9205 }
9206 if (rhs.tightenBounds_) {
9207 assert (numberColumns_)(static_cast<void> (0));
9208 tightenBounds_=CoinCopyOfArray(rhs.tightenBounds_,numberColumns_);
9209 } else {
9210 tightenBounds_=NULL__null;
9211 }
9212 }
9213 return *this;
9214}
9215
9216/// This can be used to refresh any inforamtion
9217void
9218CglProbing::refreshSolver(OsiSolverInterface * solver)
9219{
9220 if (rowCopy_) {
9221 // snapshot existed - redo
9222 snapshot(*solver,NULL__null);
9223 }
9224}
9225/* Creates cliques for use by probing.
9226 Can also try and extend cliques as a result of probing (root node).
9227 Returns number of cliques found.
9228*/
9229int
9230CglProbing::createCliques( OsiSolverInterface & si,
9231 int minimumSize, int maximumSize)
9232{
9233 // get rid of what is there
9234 deleteCliques();
9235 CoinPackedMatrix matrixByRow(*si.getMatrixByRow());
9236 int numberRows = si.getNumRows();
9237 if (!rowCopy_)
9238 numberRows_=numberRows;
9239 numberColumns_ = si.getNumCols();
9240
9241 numberCliques_=0;
9242 int numberEntries=0;
9243 int numberIntegers=0;
9244 int * lookup = new int[numberColumns_];
9245 int i;
9246 for (i=0;i<numberColumns_;i++) {
9247 if (si.isBinary(i))
9248 lookup[i]=numberIntegers++;
9249 else
9250 lookup[i]=-1;
9251 }
9252
9253 int * which = new int[numberColumns_];
9254 int * whichRow = new int[numberRows];
9255 // Statistics
9256 int totalP1=0,totalM1=0;
9257 int numberBig=0,totalBig=0;
9258 int numberFixed=0;
9259
9260 // Row copy
9261 const double * elementByRow = matrixByRow.getElements();
9262 const int * column = matrixByRow.getIndices();
9263 const CoinBigIndex * rowStart = matrixByRow.getVectorStarts();
9264 const int * rowLength = matrixByRow.getVectorLengths();
9265
9266 const double * lower = si.getColLower();
9267 const double * upper = si.getColUpper();
9268 const double * rowLower = si.getRowLower();
9269 const double * rowUpper = si.getRowUpper();
9270 int iRow;
9271 for (iRow=0;iRow<numberRows;iRow++) {
9272 int numberP1=0, numberM1=0;
9273 int j;
9274 double upperValue=rowUpper[iRow];
9275 double lowerValue=rowLower[iRow];
9276 bool good=true;
9277 for (j=rowStart[iRow];j<rowStart[iRow]+rowLength[iRow];j++) {
9278 int iColumn = column[j];
9279 int iInteger=lookup[iColumn];
9280 if (upper[iColumn]-lower[iColumn]<1.0e-8) {
9281 // fixed
9282 upperValue -= lower[iColumn]*elementByRow[j];
9283 lowerValue -= lower[iColumn]*elementByRow[j];
9284 continue;
9285 } else if (upper[iColumn]!=1.0||lower[iColumn]!=0.0) {
9286 good = false;
9287 break;
9288 } else if (iInteger<0) {
9289 good = false;
9290 break;
9291 }
9292 if (fabs(elementByRow[j])!=1.0) {
9293 good=false;
9294 break;
9295 } else if (elementByRow[j]>0.0) {
9296 which[numberP1++]=iColumn;
9297 } else {
9298 numberM1++;
9299 which[numberIntegers-numberM1]=iColumn;
9300 }
9301 }
9302 int iUpper = static_cast<int> (floor(upperValue+1.0e-5));
9303 int iLower = static_cast<int> (ceil(lowerValue-1.0e-5));
9304 int state=0;
9305 if (upperValue<1.0e6) {
9306 if (iUpper==1-numberM1)
9307 state=1;
9308 else if (iUpper==-numberM1)
9309 state=2;
9310 else if (iUpper<-numberM1)
9311 state=3;
9312 }
9313 if (!state&&lowerValue>-1.0e6) {
9314 if (-iLower==1-numberP1)
9315 state=-1;
9316 else if (-iLower==-numberP1)
9317 state=-2;
9318 else if (-iLower<-numberP1)
9319 state=-3;
9320 }
9321 if (good&&state) {
9322 if (abs(state)==3) {
9323 // infeasible
9324 numberCliques_ = -99999;
9325 break;
9326 } else if (abs(state)==2) {
9327 // we can fix all
9328 numberFixed += numberP1+numberM1;
9329 if (state>0) {
9330 // fix all +1 at 0, -1 at 1
9331 for (i=0;i<numberP1;i++)
9332 si.setColUpper(which[i],0.0);
9333 for (i=0;i<numberM1;i++)
9334 si.setColLower(which[numberIntegers-i-1],
9335 1.0);
9336 } else {
9337 // fix all +1 at 1, -1 at 0
9338 for (i=0;i<numberP1;i++)
9339 si.setColLower(which[i],1.0);
9340 for (i=0;i<numberM1;i++)
9341 si.setColUpper(which[numberIntegers-i-1],
9342 0.0);
9343 }
9344 } else {
9345 int length = numberP1+numberM1;
9346 totalP1 += numberP1;
9347 totalM1 += numberM1;
9348 if (length >= minimumSize&&length<maximumSize) {
9349 whichRow[numberCliques_++]=iRow;
9350 numberEntries += length;
9351 } else if (numberP1+numberM1 >= maximumSize) {
9352 // too big
9353 numberBig++;
9354 totalBig += numberP1+numberM1;
9355 }
9356 }
9357 }
9358 }
9359 if (numberCliques_<0) {
9360 if (logLevel_)
9361 printf("*** Problem infeasible\n");
9362 } else {
9363 if (numberCliques_) {
9364 if (logLevel_)
9365 printf("%d cliques of average size %g found, %d P1, %d M1\n",
9366 numberCliques_,
9367 (static_cast<double>(totalP1+totalM1))/
9368 (static_cast<double> (numberCliques_)),
9369 totalP1,totalM1);
9370 } else {
9371 if (logLevel_>1)
9372 printf("No cliques found\n");
9373 }
9374 if (numberBig) {
9375 if (logLevel_)
9376 printf("%d large cliques ( >= %d) found, total %d\n",
9377 numberBig,maximumSize,totalBig);
9378 }
9379 if (numberFixed) {
9380 if (logLevel_)
9381 printf("%d variables fixed\n",numberFixed);
9382 }
9383 }
9384 if (numberCliques_>0) {
9385 cliqueType_ = new cliqueType [numberCliques_];
9386 cliqueStart_ = new int [numberCliques_+1];
9387 cliqueEntry_ = new cliqueEntry [numberEntries];
9388 oneFixStart_ = new int [numberColumns_];
9389 zeroFixStart_ = new int [numberColumns_];
9390 endFixStart_ = new int [numberColumns_];
9391 whichClique_ = new int [numberEntries];
9392 numberEntries=0;
9393 cliqueStart_[0]=0;
9394 for (i=0;i<numberColumns_;i++) {
9395 oneFixStart_[i]=-1;
9396 zeroFixStart_[i]=-1;
9397 endFixStart_[i]=-1;
9398 }
9399 int iClique;
9400 // Possible some have been fixed
9401 int numberCliques=numberCliques_;
9402 numberCliques_=0;
9403 for (iClique=0;iClique<numberCliques;iClique++) {
9404 int iRow=whichRow[iClique];
9405 whichRow[numberCliques_]=iRow;
9406 int numberP1=0, numberM1=0;
9407 int j;
9408 double upperValue=rowUpper[iRow];
9409 double lowerValue=rowLower[iRow];
9410 for (j=rowStart[iRow];j<rowStart[iRow]+rowLength[iRow];j++) {
9411 int iColumn = column[j];
9412 if (upper[iColumn]-lower[iColumn]<1.0e-8) {
9413 // fixed
9414 upperValue -= lower[iColumn]*elementByRow[j];
9415 lowerValue -= lower[iColumn]*elementByRow[j];
9416 continue;
9417 }
9418 if (elementByRow[j]>0.0) {
9419 which[numberP1++]=iColumn;
9420 } else {
9421 numberM1++;
9422 which[numberIntegers-numberM1]=iColumn;
9423 }
9424 }
9425 int iUpper = static_cast<int> (floor(upperValue+1.0e-5));
9426 int iLower = static_cast<int> (ceil(lowerValue-1.0e-5));
9427 int state=0;
9428 if (upperValue<1.0e6) {
9429 if (iUpper==1-numberM1)
9430 state=1;
9431 }
9432 if (!state&&lowerValue>-1.0e6) {
9433 state=-1;
9434 }
9435 if (abs(state)!=1)
9436 continue; // must have been fixed
9437 if (iLower==iUpper) {
9438 cliqueType_[numberCliques_].equality=1;
9439 } else {
9440 cliqueType_[numberCliques_].equality=0;
9441 }
9442 if (state>0) {
9443 for (i=0;i<numberP1;i++) {
9444 // 1 is strong branch
9445 int iColumn = which[i];
9446 setSequenceInCliqueEntry(cliqueEntry_[numberEntries],iColumn);
9447 setOneFixesInCliqueEntry(cliqueEntry_[numberEntries],true);
9448 numberEntries++;
9449 // zero counts
9450 oneFixStart_[iColumn]=0;
9451 zeroFixStart_[iColumn]=0;
9452 }
9453 for (i=0;i<numberM1;i++) {
9454 // 0 is strong branch
9455 int iColumn = which[numberIntegers-i-1];
9456 setSequenceInCliqueEntry(cliqueEntry_[numberEntries],iColumn);
9457 setOneFixesInCliqueEntry(cliqueEntry_[numberEntries],false);
9458 numberEntries++;
9459 // zero counts
9460 oneFixStart_[iColumn]=0;
9461 zeroFixStart_[iColumn]=0;
9462 }
9463 } else {
9464 for (i=0;i<numberP1;i++) {
9465 // 0 is strong branch
9466 int iColumn = which[i];
9467 setSequenceInCliqueEntry(cliqueEntry_[numberEntries],iColumn);
9468 setOneFixesInCliqueEntry(cliqueEntry_[numberEntries],false);
9469 numberEntries++;
9470 // zero counts
9471 oneFixStart_[iColumn]=0;
9472 zeroFixStart_[iColumn]=0;
9473 }
9474 for (i=0;i<numberM1;i++) {
9475 // 1 is strong branch
9476 int iColumn = which[numberIntegers-i-1];
9477 setSequenceInCliqueEntry(cliqueEntry_[numberEntries],iColumn);
9478 setOneFixesInCliqueEntry(cliqueEntry_[numberEntries],true);
9479 numberEntries++;
9480 // zero counts
9481 oneFixStart_[iColumn]=0;
9482 zeroFixStart_[iColumn]=0;
9483 }
9484 }
9485 numberCliques_++;
9486 cliqueStart_[numberCliques_]=numberEntries;
9487 }
9488 // Now do column lists
9489 // First do counts
9490 for (iClique=0;iClique<numberCliques_;iClique++) {
9491 for (int j=cliqueStart_[iClique];j<cliqueStart_[iClique+1];j++) {
9492 int iColumn = sequenceInCliqueEntry(cliqueEntry_[j]);
9493 if (oneFixesInCliqueEntry(cliqueEntry_[j]))
9494 oneFixStart_[iColumn]++;
9495 else
9496 zeroFixStart_[iColumn]++;
9497 }
9498 }
9499 // now get starts and use which and end as counters
9500 numberEntries=0;
9501 for (int iColumn=0;iColumn<numberColumns_;iColumn++) {
9502 if (oneFixStart_[iColumn]>=0) {
9503 int n1=oneFixStart_[iColumn];
9504 int n2=zeroFixStart_[iColumn];
9505 oneFixStart_[iColumn]=numberEntries;
9506 which[iColumn]=numberEntries;
9507 numberEntries += n1;
9508 zeroFixStart_[iColumn]=numberEntries;
9509 endFixStart_[iColumn]=numberEntries;
9510 numberEntries += n2;
9511 }
9512 }
9513 // now put in
9514 for (iClique=0;iClique<numberCliques_;iClique++) {
9515 for (int j=cliqueStart_[iClique];j<cliqueStart_[iClique+1];j++) {
9516 int iColumn = sequenceInCliqueEntry(cliqueEntry_[j]);
9517 if (oneFixesInCliqueEntry(cliqueEntry_[j])) {
9518 int put = which[iColumn];
9519 which[iColumn]++;
9520 whichClique_[put]=iClique;
9521 } else {
9522 int put = endFixStart_[iColumn];
9523 endFixStart_[iColumn]++;
9524 whichClique_[put]=iClique;
9525 }
9526 }
9527 }
9528 }
9529 delete [] which;
9530 delete [] whichRow;
9531 delete [] lookup;
9532 return numberCliques_;
9533}
9534// Delete all clique information
9535void
9536CglProbing::deleteCliques()
9537{
9538 delete [] cliqueType_;
9539 delete [] cliqueStart_;
9540 delete [] cliqueEntry_;
9541 delete [] oneFixStart_;
9542 delete [] zeroFixStart_;
9543 delete [] endFixStart_;
9544 delete [] whichClique_;
9545 delete [] cliqueRow_;
9546 delete [] cliqueRowStart_;
9547 cliqueType_=NULL__null;
9548 cliqueStart_=NULL__null;
9549 cliqueEntry_=NULL__null;
9550 oneFixStart_=NULL__null;
9551 zeroFixStart_=NULL__null;
9552 endFixStart_=NULL__null;
9553 whichClique_=NULL__null;
9554 cliqueRow_=NULL__null;
9555 cliqueRowStart_=NULL__null;
9556 numberCliques_=0;
9557}
9558/*
9559 Returns true if may generate Row cuts in tree (rather than root node).
9560 Used so know if matrix will change in tree. Really
9561 meant so column cut generators can still be active
9562 without worrying code.
9563 Default is true
9564*/
9565bool
9566CglProbing::mayGenerateRowCutsInTree() const
9567{
9568 return rowCuts_>0;
9569}
9570// Sets up clique information for each row
9571void
9572CglProbing::setupRowCliqueInformation(const OsiSolverInterface & si)
9573{
9574 if (!numberCliques_)
9575 return;
9576 CoinPackedMatrix * rowCopy;
9577 if (!rowCopy_) {
9578 // create from current
9579 numberRows_=si.getNumRows();
9580 numberColumns_=si.getNumCols();
9581 rowCopy = new CoinPackedMatrix(*si.getMatrixByRow());
9582 } else {
9583 rowCopy = rowCopy_;
9584 assert(numberRows_<=si.getNumRows())(static_cast<void> (0));
9585 assert(numberColumns_==si.getNumCols())(static_cast<void> (0));
9586 }
9587 assert(numberRows_&&numberColumns_)(static_cast<void> (0));
9588 cliqueRowStart_ = new int [numberRows_+1];
9589 cliqueRowStart_[0]=0;
9590 // Temporary array while building list
9591 cliqueEntry ** array = new cliqueEntry * [numberRows_];
9592 // Which cliques in use
9593 int * which = new int[numberCliques_];
9594 int * count = new int[numberCliques_];
9595 int * back =new int[numberColumns_];
9596 CoinZeroN(count,numberCliques_);
9597 CoinFillN(back,numberColumns_,-1);
9598 const int * column = rowCopy->getIndices();
9599 const CoinBigIndex * rowStart = rowCopy->getVectorStarts();
9600 const int * rowLength = rowCopy->getVectorLengths();
9601 const double * lower = si.getColLower();
9602 const double * upper = si.getColUpper();
9603 int iRow;
9604 for (iRow=0;iRow<numberRows_;iRow++) {
9605 int j;
9606 int numberFree=0;
9607 int numberUsed=0;
9608 for (j=rowStart[iRow];j<rowStart[iRow]+rowLength[iRow];j++) {
9609 int iColumn=column[j];
9610 if (upper[iColumn]>lower[iColumn]) {
9611 back[iColumn]=j-rowStart[iRow];
9612 numberFree++;
9613 for (int k=oneFixStart_[iColumn];k<endFixStart_[iColumn];k++) {
9614 int iClique = whichClique_[k];
9615 if (!count[iClique]) {
9616 which[numberUsed++]=iClique;
9617 }
9618 count[iClique]++;
9619 }
9620 }
9621 }
9622 // find largest cliques
9623 bool finished=false;
9624 int numberInThis=0;
9625 cliqueEntry * entries = NULL__null;
9626 array[iRow]=entries;
9627 while (!finished) {
9628 int largest=1;
9629 int whichClique=-1;
9630 for (int i=0;i<numberUsed;i++) {
9631 int iClique = which[i];
9632 if (count[iClique]>largest) {
9633 largest=count[iClique];
9634 whichClique=iClique;
9635 }
9636 }
9637 // Add in if >1 (but not if all as that means clique==row)
9638 if (whichClique>=0&&largest<numberFree) {
9639 if (!numberInThis) {
9640 int length=rowLength[iRow];
9641 entries = new cliqueEntry [length];
9642 array[iRow]=entries;
9643 for (int i=0;i<length;i++) {
9644 setOneFixesInCliqueEntry(entries[i],false);
9645 setSequenceInCliqueEntry(entries[i],numberColumns_+1);
9646 }
9647 }
9648 // put in (and take out all counts)
9649 for (j=rowStart[iRow];j<rowStart[iRow]+rowLength[iRow];j++) {
9650 int iColumn=column[j];
9651 if (upper[iColumn]>lower[iColumn]) {
9652 bool found=false;
9653 int k;
9654 for ( k=oneFixStart_[iColumn];k<endFixStart_[iColumn];k++) {
9655 int iClique = whichClique_[k];
9656 if (iClique==whichClique) {
9657 found=true;
9658 break;
9659 }
9660 }
9661 if (found) {
9662 for ( k=oneFixStart_[iColumn];k<endFixStart_[iColumn];k++) {
9663 int iClique = whichClique_[k];
9664 count[iClique]--;
9665 }
9666 for (k=cliqueStart_[whichClique];k<cliqueStart_[whichClique+1];k++) {
9667 if (sequenceInCliqueEntry(cliqueEntry_[k])==iColumn) {
9668 int iback=back[iColumn];
9669 setSequenceInCliqueEntry(entries[iback],numberInThis);
9670 setOneFixesInCliqueEntry(entries[iback],
9671 oneFixesInCliqueEntry(cliqueEntry_[k]));
9672 break;
9673 }
9674 }
9675 }
9676 }
9677 }
9678 numberInThis++;
9679 } else {
9680 finished=true;
9681 }
9682 }
9683 if (numberInThis)
9684 cliqueRowStart_[iRow+1]=cliqueRowStart_[iRow]+rowLength[iRow];
9685 else
9686 cliqueRowStart_[iRow+1]=cliqueRowStart_[iRow];
9687 for (int i=0;i<numberUsed;i++) {
9688 int iClique = which[i];
9689 count[iClique]=0;
9690 }
9691 for (j=rowStart[iRow];j<rowStart[iRow]+rowLength[iRow];j++) {
9692 int iColumn=column[j];
9693 back[iColumn]=-1;
9694 }
9695 }
9696 delete [] which;
9697 delete [] count;
9698 delete [] back;
9699 // Now put info in one array
9700 cliqueRow_ = new cliqueEntry [cliqueRowStart_[numberRows_]];
9701 for (iRow=0;iRow<numberRows_;iRow++) {
9702 if (array[iRow]) {
9703 int start = cliqueRowStart_[iRow];
9704 CoinMemcpyN(array[iRow],rowLength[iRow],cliqueRow_+start);
9705 delete [] array[iRow];
9706 }
9707 }
9708 delete [] array;
9709 if (rowCopy!=rowCopy_)
9710 delete rowCopy;
9711}
9712// Mark variables to be tightened
9713void
9714CglProbing::tightenThese(const OsiSolverInterface & solver,int number, const int * which)
9715{
9716 delete [] tightenBounds_;
9717 int numberColumns = solver.getNumCols();
9718 if (numberColumns_)
9719 assert (numberColumns_==numberColumns)(static_cast<void> (0));
9720 tightenBounds_ = new char [numberColumns];
9721 memset(tightenBounds_,0,numberColumns);
9722 for (int i=0;i<number;i++) {
9723 int k=which[i];
9724 if (k>=0&&k<numberColumns)
9725 tightenBounds_[k]=1;
9726 }
9727}
9728// Create C++ lines to get to current state
9729std::string
9730CglProbing::generateCpp( FILE * fp)
9731{
9732 CglProbing other;
9733 fprintf(fp,"0#include \"CglProbing.hpp\"\n");
9734 fprintf(fp,"3 CglProbing probing;\n");
9735 if (getMode()!=other.getMode())
9736 fprintf(fp,"3 probing.setMode(%d);\n",getMode());
9737 else
9738 fprintf(fp,"4 probing.setMode(%d);\n",getMode());
9739 if (getMaxPass()!=other.getMaxPass())
9740 fprintf(fp,"3 probing.setMaxPass(%d);\n",getMaxPass());
9741 else
9742 fprintf(fp,"4 probing.setMaxPass(%d);\n",getMaxPass());
9743 if (getLogLevel()!=other.getLogLevel())
9744 fprintf(fp,"3 probing.setLogLevel(%d);\n",getLogLevel());
9745 else
9746 fprintf(fp,"4 probing.setLogLevel(%d);\n",getLogLevel());
9747 if (getMaxProbe()!=other.getMaxProbe())
9748 fprintf(fp,"3 probing.setMaxProbe(%d);\n",getMaxProbe());
9749 else
9750 fprintf(fp,"4 probing.setMaxProbe(%d);\n",getMaxProbe());
9751 if (getMaxLook()!=other.getMaxLook())
9752 fprintf(fp,"3 probing.setMaxLook(%d);\n",getMaxLook());
9753 else
9754 fprintf(fp,"4 probing.setMaxLook(%d);\n",getMaxLook());
9755 if (getMaxElements()!=other.getMaxElements())
9756 fprintf(fp,"3 probing.setMaxElements(%d);\n",getMaxElements());
9757 else
9758 fprintf(fp,"4 probing.setMaxElements(%d);\n",getMaxElements());
9759 if (getMaxPassRoot()!=other.getMaxPassRoot())
9760 fprintf(fp,"3 probing.setMaxPassRoot(%d);\n",getMaxPassRoot());
9761 else
9762 fprintf(fp,"4 probing.setMaxPassRoot(%d);\n",getMaxPassRoot());
9763 if (getMaxProbeRoot()!=other.getMaxProbeRoot())
9764 fprintf(fp,"3 probing.setMaxProbeRoot(%d);\n",getMaxProbeRoot());
9765 else
9766 fprintf(fp,"4 probing.setMaxProbeRoot(%d);\n",getMaxProbeRoot());
9767 if (getMaxLookRoot()!=other.getMaxLookRoot())
9768 fprintf(fp,"3 probing.setMaxLookRoot(%d);\n",getMaxLookRoot());
9769 else
9770 fprintf(fp,"4 probing.setMaxLookRoot(%d);\n",getMaxLookRoot());
9771 if (getMaxElementsRoot()!=other.getMaxElementsRoot())
9772 fprintf(fp,"3 probing.setMaxElementsRoot(%d);\n",getMaxElementsRoot());
9773 else
9774 fprintf(fp,"4 probing.setMaxElementsRoot(%d);\n",getMaxElementsRoot());
9775 if (rowCuts()!=other.rowCuts())
9776 fprintf(fp,"3 probing.setRowCuts(%d);\n",rowCuts());
9777 else
9778 fprintf(fp,"4 probing.setRowCuts(%d);\n",rowCuts());
9779 if (getUsingObjective()!=other.getUsingObjective())
9780 fprintf(fp,"3 probing.setUsingObjective(%d);\n",getUsingObjective());
9781 else
9782 fprintf(fp,"4 probing.setUsingObjective(%d);\n",getUsingObjective());
9783 if (getAggressiveness()!=other.getAggressiveness())
9784 fprintf(fp,"3 probing.setAggressiveness(%d);\n",getAggressiveness());
9785 else
9786 fprintf(fp,"4 probing.setAggressiveness(%d);\n",getAggressiveness());
9787 return "probing";
9788}
9789//-------------------------------------------------------------
9790void
9791CglImplication::generateCuts(const OsiSolverInterface & si, OsiCuts & cs,
9792 const CglTreeInfo info)
9793{
9794 if (probingInfo_) {
9795 //int n1=cs.sizeRowCuts();
9796 probingInfo_->generateCuts(si,cs,info);
9797 //int n2=cs.sizeRowCuts();
9798 //if (n2>n1)
9799 //printf("added %d cuts\n",n2-n1);
9800 }
9801}
9802
9803//-------------------------------------------------------------------
9804// Default Constructor
9805//-------------------------------------------------------------------
9806CglImplication::CglImplication ()
9807:
9808CglCutGenerator(),
9809probingInfo_(NULL__null)
9810{
9811 // nothing to do here
9812}
9813//-------------------------------------------------------------------
9814// Constructor with info
9815//-------------------------------------------------------------------
9816CglImplication::CglImplication (CglTreeProbingInfo * info)
9817:
9818CglCutGenerator(),
9819probingInfo_(info)
9820{
9821 // nothing to do here
9822}
9823//-------------------------------------------------------------------
9824// Copy constructor
9825//-------------------------------------------------------------------
9826CglImplication::CglImplication (
9827 const CglImplication & source)
9828:
9829CglCutGenerator(source),
9830probingInfo_(source.probingInfo_)
9831{
9832 // Nothing to do here
9833}
9834
9835
9836//-------------------------------------------------------------------
9837// Clone
9838//-------------------------------------------------------------------
9839CglCutGenerator *
9840CglImplication::clone() const
9841{
9842 return new CglImplication(*this);
9843}
9844
9845//-------------------------------------------------------------------
9846// Destructor
9847//-------------------------------------------------------------------
9848CglImplication::~CglImplication ()
9849{
9850 // Nothing to do here
9851}
9852
9853//----------------------------------------------------------------
9854// Assignment operator
9855//-------------------------------------------------------------------
9856CglImplication &
9857CglImplication::operator=(
9858 const CglImplication& rhs)
9859{
9860 if (this != &rhs) {
9861 CglCutGenerator::operator=(rhs);
9862 probingInfo_=rhs.probingInfo_;
9863 }
9864 return *this;
9865}
9866// Create C++ lines to get to current state
9867std::string
9868CglImplication::generateCpp( FILE * fp)
9869{
9870 CglImplication other;
9871 fprintf(fp,"0#include \"CglImplication.hpp\"\n");
9872 fprintf(fp,"3 CglImplication implication;\n");
9873 return "implication";
9874}

/usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/bits/stl_algo.h

1// Algorithm implementation -*- C++ -*-
2
3// Copyright (C) 2001-2020 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/*
26 *
27 * Copyright (c) 1994
28 * Hewlett-Packard Company
29 *
30 * Permission to use, copy, modify, distribute and sell this software
31 * and its documentation for any purpose is hereby granted without fee,
32 * provided that the above copyright notice appear in all copies and
33 * that both that copyright notice and this permission notice appear
34 * in supporting documentation. Hewlett-Packard Company makes no
35 * representations about the suitability of this software for any
36 * purpose. It is provided "as is" without express or implied warranty.
37 *
38 *
39 * Copyright (c) 1996
40 * Silicon Graphics Computer Systems, Inc.
41 *
42 * Permission to use, copy, modify, distribute and sell this software
43 * and its documentation for any purpose is hereby granted without fee,
44 * provided that the above copyright notice appear in all copies and
45 * that both that copyright notice and this permission notice appear
46 * in supporting documentation. Silicon Graphics makes no
47 * representations about the suitability of this software for any
48 * purpose. It is provided "as is" without express or implied warranty.
49 */
50
51/** @file bits/stl_algo.h
52 * This is an internal header file, included by other library headers.
53 * Do not attempt to use it directly. @headername{algorithm}
54 */
55
56#ifndef _STL_ALGO_H1
57#define _STL_ALGO_H1 1
58
59#include <cstdlib> // for rand
60#include <bits/algorithmfwd.h>
61#include <bits/stl_heap.h>
62#include <bits/stl_tempbuf.h> // for _Temporary_buffer
63#include <bits/predefined_ops.h>
64
65#if __cplusplus201402L >= 201103L
66#include <bits/uniform_int_dist.h>
67#endif
68
69// See concept_check.h for the __glibcxx_*_requires macros.
70
71namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
72{
73_GLIBCXX_BEGIN_NAMESPACE_VERSION
74
75 /// Swaps the median value of *__a, *__b and *__c under __comp to *__result
76 template<typename _Iterator, typename _Compare>
77 _GLIBCXX20_CONSTEXPR
78 void
79 __move_median_to_first(_Iterator __result,_Iterator __a, _Iterator __b,
80 _Iterator __c, _Compare __comp)
81 {
82 if (__comp(__a, __b))
83 {
84 if (__comp(__b, __c))
85 std::iter_swap(__result, __b);
86 else if (__comp(__a, __c))
87 std::iter_swap(__result, __c);
88 else
89 std::iter_swap(__result, __a);
90 }
91 else if (__comp(__a, __c))
92 std::iter_swap(__result, __a);
93 else if (__comp(__b, __c))
94 std::iter_swap(__result, __c);
95 else
96 std::iter_swap(__result, __b);
97 }
98
99 /// Provided for stable_partition to use.
100 template<typename _InputIterator, typename _Predicate>
101 _GLIBCXX20_CONSTEXPR
102 inline _InputIterator
103 __find_if_not(_InputIterator __first, _InputIterator __last,
104 _Predicate __pred)
105 {
106 return std::__find_if(__first, __last,
107 __gnu_cxx::__ops::__negate(__pred),
108 std::__iterator_category(__first));
109 }
110
111 /// Like find_if_not(), but uses and updates a count of the
112 /// remaining range length instead of comparing against an end
113 /// iterator.
114 template<typename _InputIterator, typename _Predicate, typename _Distance>
115 _GLIBCXX20_CONSTEXPR
116 _InputIterator
117 __find_if_not_n(_InputIterator __first, _Distance& __len, _Predicate __pred)
118 {
119 for (; __len; --__len, (void) ++__first)
120 if (!__pred(__first))
121 break;
122 return __first;
123 }
124
125 // set_difference
126 // set_intersection
127 // set_symmetric_difference
128 // set_union
129 // for_each
130 // find
131 // find_if
132 // find_first_of
133 // adjacent_find
134 // count
135 // count_if
136 // search
137
138 template<typename _ForwardIterator1, typename _ForwardIterator2,
139 typename _BinaryPredicate>
140 _GLIBCXX20_CONSTEXPR
141 _ForwardIterator1
142 __search(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
143 _ForwardIterator2 __first2, _ForwardIterator2 __last2,
144 _BinaryPredicate __predicate)
145 {
146 // Test for empty ranges
147 if (__first1 == __last1 || __first2 == __last2)
148 return __first1;
149
150 // Test for a pattern of length 1.
151 _ForwardIterator2 __p1(__first2);
152 if (++__p1 == __last2)
153 return std::__find_if(__first1, __last1,
154 __gnu_cxx::__ops::__iter_comp_iter(__predicate, __first2));
155
156 // General case.
157 _ForwardIterator1 __current = __first1;
158
159 for (;;)
160 {
161 __first1 =
162 std::__find_if(__first1, __last1,
163 __gnu_cxx::__ops::__iter_comp_iter(__predicate, __first2));
164
165 if (__first1 == __last1)
166 return __last1;
167
168 _ForwardIterator2 __p = __p1;
169 __current = __first1;
170 if (++__current == __last1)
171 return __last1;
172
173 while (__predicate(__current, __p))
174 {
175 if (++__p == __last2)
176 return __first1;
177 if (++__current == __last1)
178 return __last1;
179 }
180 ++__first1;
181 }
182 return __first1;
183 }
184
185 // search_n
186
187 /**
188 * This is an helper function for search_n overloaded for forward iterators.
189 */
190 template<typename _ForwardIterator, typename _Integer,
191 typename _UnaryPredicate>
192 _GLIBCXX20_CONSTEXPR
193 _ForwardIterator
194 __search_n_aux(_ForwardIterator __first, _ForwardIterator __last,
195 _Integer __count, _UnaryPredicate __unary_pred,
196 std::forward_iterator_tag)
197 {
198 __first = std::__find_if(__first, __last, __unary_pred);
199 while (__first != __last)
200 {
201 typename iterator_traits<_ForwardIterator>::difference_type
202 __n = __count;
203 _ForwardIterator __i = __first;
204 ++__i;
205 while (__i != __last && __n != 1 && __unary_pred(__i))
206 {
207 ++__i;
208 --__n;
209 }
210 if (__n == 1)
211 return __first;
212 if (__i == __last)
213 return __last;
214 __first = std::__find_if(++__i, __last, __unary_pred);
215 }
216 return __last;
217 }
218
219 /**
220 * This is an helper function for search_n overloaded for random access
221 * iterators.
222 */
223 template<typename _RandomAccessIter, typename _Integer,
224 typename _UnaryPredicate>
225 _GLIBCXX20_CONSTEXPR
226 _RandomAccessIter
227 __search_n_aux(_RandomAccessIter __first, _RandomAccessIter __last,
228 _Integer __count, _UnaryPredicate __unary_pred,
229 std::random_access_iterator_tag)
230 {
231 typedef typename std::iterator_traits<_RandomAccessIter>::difference_type
232 _DistanceType;
233
234 _DistanceType __tailSize = __last - __first;
235 _DistanceType __remainder = __count;
236
237 while (__remainder <= __tailSize) // the main loop...
238 {
239 __first += __remainder;
240 __tailSize -= __remainder;
241 // __first here is always pointing to one past the last element of
242 // next possible match.
243 _RandomAccessIter __backTrack = __first;
244 while (__unary_pred(--__backTrack))
245 {
246 if (--__remainder == 0)
247 return (__first - __count); // Success
248 }
249 __remainder = __count + 1 - (__first - __backTrack);
250 }
251 return __last; // Failure
252 }
253
254 template<typename _ForwardIterator, typename _Integer,
255 typename _UnaryPredicate>
256 _GLIBCXX20_CONSTEXPR
257 _ForwardIterator
258 __search_n(_ForwardIterator __first, _ForwardIterator __last,
259 _Integer __count,
260 _UnaryPredicate __unary_pred)
261 {
262 if (__count <= 0)
263 return __first;
264
265 if (__count == 1)
266 return std::__find_if(__first, __last, __unary_pred);
267
268 return std::__search_n_aux(__first, __last, __count, __unary_pred,
269 std::__iterator_category(__first));
270 }
271
272 // find_end for forward iterators.
273 template<typename _ForwardIterator1, typename _ForwardIterator2,
274 typename _BinaryPredicate>
275 _GLIBCXX20_CONSTEXPR
276 _ForwardIterator1
277 __find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
278 _ForwardIterator2 __first2, _ForwardIterator2 __last2,
279 forward_iterator_tag, forward_iterator_tag,
280 _BinaryPredicate __comp)
281 {
282 if (__first2 == __last2)
283 return __last1;
284
285 _ForwardIterator1 __result = __last1;
286 while (1)
287 {
288 _ForwardIterator1 __new_result
289 = std::__search(__first1, __last1, __first2, __last2, __comp);
290 if (__new_result == __last1)
291 return __result;
292 else
293 {
294 __result = __new_result;
295 __first1 = __new_result;
296 ++__first1;
297 }
298 }
299 }
300
301 // find_end for bidirectional iterators (much faster).
302 template<typename _BidirectionalIterator1, typename _BidirectionalIterator2,
303 typename _BinaryPredicate>
304 _GLIBCXX20_CONSTEXPR
305 _BidirectionalIterator1
306 __find_end(_BidirectionalIterator1 __first1,
307 _BidirectionalIterator1 __last1,
308 _BidirectionalIterator2 __first2,
309 _BidirectionalIterator2 __last2,
310 bidirectional_iterator_tag, bidirectional_iterator_tag,
311 _BinaryPredicate __comp)
312 {
313 // concept requirements
314 __glibcxx_function_requires(_BidirectionalIteratorConcept<
315 _BidirectionalIterator1>)
316 __glibcxx_function_requires(_BidirectionalIteratorConcept<
317 _BidirectionalIterator2>)
318
319 typedef reverse_iterator<_BidirectionalIterator1> _RevIterator1;
320 typedef reverse_iterator<_BidirectionalIterator2> _RevIterator2;
321
322 _RevIterator1 __rlast1(__first1);
323 _RevIterator2 __rlast2(__first2);
324 _RevIterator1 __rresult = std::__search(_RevIterator1(__last1), __rlast1,
325 _RevIterator2(__last2), __rlast2,
326 __comp);
327
328 if (__rresult == __rlast1)
329 return __last1;
330 else
331 {
332 _BidirectionalIterator1 __result = __rresult.base();
333 std::advance(__result, -std::distance(__first2, __last2));
334 return __result;
335 }
336 }
337
338 /**
339 * @brief Find last matching subsequence in a sequence.
340 * @ingroup non_mutating_algorithms
341 * @param __first1 Start of range to search.
342 * @param __last1 End of range to search.
343 * @param __first2 Start of sequence to match.
344 * @param __last2 End of sequence to match.
345 * @return The last iterator @c i in the range
346 * @p [__first1,__last1-(__last2-__first2)) such that @c *(i+N) ==
347 * @p *(__first2+N) for each @c N in the range @p
348 * [0,__last2-__first2), or @p __last1 if no such iterator exists.
349 *
350 * Searches the range @p [__first1,__last1) for a sub-sequence that
351 * compares equal value-by-value with the sequence given by @p
352 * [__first2,__last2) and returns an iterator to the __first
353 * element of the sub-sequence, or @p __last1 if the sub-sequence
354 * is not found. The sub-sequence will be the last such
355 * subsequence contained in [__first1,__last1).
356 *
357 * Because the sub-sequence must lie completely within the range @p
358 * [__first1,__last1) it must start at a position less than @p
359 * __last1-(__last2-__first2) where @p __last2-__first2 is the
360 * length of the sub-sequence. This means that the returned
361 * iterator @c i will be in the range @p
362 * [__first1,__last1-(__last2-__first2))
363 */
364 template<typename _ForwardIterator1, typename _ForwardIterator2>
365 _GLIBCXX20_CONSTEXPR
366 inline _ForwardIterator1
367 find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
368 _ForwardIterator2 __first2, _ForwardIterator2 __last2)
369 {
370 // concept requirements
371 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>)
372 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>)
373 __glibcxx_function_requires(_EqualOpConcept<
374 typename iterator_traits<_ForwardIterator1>::value_type,
375 typename iterator_traits<_ForwardIterator2>::value_type>)
376 __glibcxx_requires_valid_range(__first1, __last1);
377 __glibcxx_requires_valid_range(__first2, __last2);
378
379 return std::__find_end(__first1, __last1, __first2, __last2,
380 std::__iterator_category(__first1),
381 std::__iterator_category(__first2),
382 __gnu_cxx::__ops::__iter_equal_to_iter());
383 }
384
385 /**
386 * @brief Find last matching subsequence in a sequence using a predicate.
387 * @ingroup non_mutating_algorithms
388 * @param __first1 Start of range to search.
389 * @param __last1 End of range to search.
390 * @param __first2 Start of sequence to match.
391 * @param __last2 End of sequence to match.
392 * @param __comp The predicate to use.
393 * @return The last iterator @c i in the range @p
394 * [__first1,__last1-(__last2-__first2)) such that @c
395 * predicate(*(i+N), @p (__first2+N)) is true for each @c N in the
396 * range @p [0,__last2-__first2), or @p __last1 if no such iterator
397 * exists.
398 *
399 * Searches the range @p [__first1,__last1) for a sub-sequence that
400 * compares equal value-by-value with the sequence given by @p
401 * [__first2,__last2) using comp as a predicate and returns an
402 * iterator to the first element of the sub-sequence, or @p __last1
403 * if the sub-sequence is not found. The sub-sequence will be the
404 * last such subsequence contained in [__first,__last1).
405 *
406 * Because the sub-sequence must lie completely within the range @p
407 * [__first1,__last1) it must start at a position less than @p
408 * __last1-(__last2-__first2) where @p __last2-__first2 is the
409 * length of the sub-sequence. This means that the returned
410 * iterator @c i will be in the range @p
411 * [__first1,__last1-(__last2-__first2))
412 */
413 template<typename _ForwardIterator1, typename _ForwardIterator2,
414 typename _BinaryPredicate>
415 _GLIBCXX20_CONSTEXPR
416 inline _ForwardIterator1
417 find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
418 _ForwardIterator2 __first2, _ForwardIterator2 __last2,
419 _BinaryPredicate __comp)
420 {
421 // concept requirements
422 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>)
423 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>)
424 __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate,
425 typename iterator_traits<_ForwardIterator1>::value_type,
426 typename iterator_traits<_ForwardIterator2>::value_type>)
427 __glibcxx_requires_valid_range(__first1, __last1);
428 __glibcxx_requires_valid_range(__first2, __last2);
429
430 return std::__find_end(__first1, __last1, __first2, __last2,
431 std::__iterator_category(__first1),
432 std::__iterator_category(__first2),
433 __gnu_cxx::__ops::__iter_comp_iter(__comp));
434 }
435
436#if __cplusplus201402L >= 201103L
437 /**
438 * @brief Checks that a predicate is true for all the elements
439 * of a sequence.
440 * @ingroup non_mutating_algorithms
441 * @param __first An input iterator.
442 * @param __last An input iterator.
443 * @param __pred A predicate.
444 * @return True if the check is true, false otherwise.
445 *
446 * Returns true if @p __pred is true for each element in the range
447 * @p [__first,__last), and false otherwise.
448 */
449 template<typename _InputIterator, typename _Predicate>
450 _GLIBCXX20_CONSTEXPR
451 inline bool
452 all_of(_InputIterator __first, _InputIterator __last, _Predicate __pred)
453 { return __last == std::find_if_not(__first, __last, __pred); }
454
455 /**
456 * @brief Checks that a predicate is false for all the elements
457 * of a sequence.
458 * @ingroup non_mutating_algorithms
459 * @param __first An input iterator.
460 * @param __last An input iterator.
461 * @param __pred A predicate.
462 * @return True if the check is true, false otherwise.
463 *
464 * Returns true if @p __pred is false for each element in the range
465 * @p [__first,__last), and false otherwise.
466 */
467 template<typename _InputIterator, typename _Predicate>
468 _GLIBCXX20_CONSTEXPR
469 inline bool
470 none_of(_InputIterator __first, _InputIterator __last, _Predicate __pred)
471 { return __last == _GLIBCXX_STD_Astd::find_if(__first, __last, __pred); }
472
473 /**
474 * @brief Checks that a predicate is false for at least an element
475 * of a sequence.
476 * @ingroup non_mutating_algorithms
477 * @param __first An input iterator.
478 * @param __last An input iterator.
479 * @param __pred A predicate.
480 * @return True if the check is true, false otherwise.
481 *
482 * Returns true if an element exists in the range @p
483 * [__first,__last) such that @p __pred is true, and false
484 * otherwise.
485 */
486 template<typename _InputIterator, typename _Predicate>
487 _GLIBCXX20_CONSTEXPR
488 inline bool
489 any_of(_InputIterator __first, _InputIterator __last, _Predicate __pred)
490 { return !std::none_of(__first, __last, __pred); }
491
492 /**
493 * @brief Find the first element in a sequence for which a
494 * predicate is false.
495 * @ingroup non_mutating_algorithms
496 * @param __first An input iterator.
497 * @param __last An input iterator.
498 * @param __pred A predicate.
499 * @return The first iterator @c i in the range @p [__first,__last)
500 * such that @p __pred(*i) is false, or @p __last if no such iterator exists.
501 */
502 template<typename _InputIterator, typename _Predicate>
503 _GLIBCXX20_CONSTEXPR
504 inline _InputIterator
505 find_if_not(_InputIterator __first, _InputIterator __last,
506 _Predicate __pred)
507 {
508 // concept requirements
509 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
510 __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
511 typename iterator_traits<_InputIterator>::value_type>)
512 __glibcxx_requires_valid_range(__first, __last);
513 return std::__find_if_not(__first, __last,
514 __gnu_cxx::__ops::__pred_iter(__pred));
515 }
516
517 /**
518 * @brief Checks whether the sequence is partitioned.
519 * @ingroup mutating_algorithms
520 * @param __first An input iterator.
521 * @param __last An input iterator.
522 * @param __pred A predicate.
523 * @return True if the range @p [__first,__last) is partioned by @p __pred,
524 * i.e. if all elements that satisfy @p __pred appear before those that
525 * do not.
526 */
527 template<typename _InputIterator, typename _Predicate>
528 _GLIBCXX20_CONSTEXPR
529 inline bool
530 is_partitioned(_InputIterator __first, _InputIterator __last,
531 _Predicate __pred)
532 {
533 __first = std::find_if_not(__first, __last, __pred);
534 if (__first == __last)
535 return true;
536 ++__first;
537 return std::none_of(__first, __last, __pred);
538 }
539
540 /**
541 * @brief Find the partition point of a partitioned range.
542 * @ingroup mutating_algorithms
543 * @param __first An iterator.
544 * @param __last Another iterator.
545 * @param __pred A predicate.
546 * @return An iterator @p mid such that @p all_of(__first, mid, __pred)
547 * and @p none_of(mid, __last, __pred) are both true.
548 */
549 template<typename _ForwardIterator, typename _Predicate>
550 _GLIBCXX20_CONSTEXPR
551 _ForwardIterator
552 partition_point(_ForwardIterator __first, _ForwardIterator __last,
553 _Predicate __pred)
554 {
555 // concept requirements
556 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
557 __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
558 typename iterator_traits<_ForwardIterator>::value_type>)
559
560 // A specific debug-mode test will be necessary...
561 __glibcxx_requires_valid_range(__first, __last);
562
563 typedef typename iterator_traits<_ForwardIterator>::difference_type
564 _DistanceType;
565
566 _DistanceType __len = std::distance(__first, __last);
567
568 while (__len > 0)
569 {
570 _DistanceType __half = __len >> 1;
571 _ForwardIterator __middle = __first;
572 std::advance(__middle, __half);
573 if (__pred(*__middle))
574 {
575 __first = __middle;
576 ++__first;
577 __len = __len - __half - 1;
578 }
579 else
580 __len = __half;
581 }
582 return __first;
583 }
584#endif
585
586 template<typename _InputIterator, typename _OutputIterator,
587 typename _Predicate>
588 _GLIBCXX20_CONSTEXPR
589 _OutputIterator
590 __remove_copy_if(_InputIterator __first, _InputIterator __last,
591 _OutputIterator __result, _Predicate __pred)
592 {
593 for (; __first != __last; ++__first)
594 if (!__pred(__first))
595 {
596 *__result = *__first;
597 ++__result;
598 }
599 return __result;
600 }
601
602 /**
603 * @brief Copy a sequence, removing elements of a given value.
604 * @ingroup mutating_algorithms
605 * @param __first An input iterator.
606 * @param __last An input iterator.
607 * @param __result An output iterator.
608 * @param __value The value to be removed.
609 * @return An iterator designating the end of the resulting sequence.
610 *
611 * Copies each element in the range @p [__first,__last) not equal
612 * to @p __value to the range beginning at @p __result.
613 * remove_copy() is stable, so the relative order of elements that
614 * are copied is unchanged.
615 */
616 template<typename _InputIterator, typename _OutputIterator, typename _Tp>
617 _GLIBCXX20_CONSTEXPR
618 inline _OutputIterator
619 remove_copy(_InputIterator __first, _InputIterator __last,
620 _OutputIterator __result, const _Tp& __value)
621 {
622 // concept requirements
623 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
624 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
625 typename iterator_traits<_InputIterator>::value_type>)
626 __glibcxx_function_requires(_EqualOpConcept<
627 typename iterator_traits<_InputIterator>::value_type, _Tp>)
628 __glibcxx_requires_valid_range(__first, __last);
629
630 return std::__remove_copy_if(__first, __last, __result,
631 __gnu_cxx::__ops::__iter_equals_val(__value));
632 }
633
634 /**
635 * @brief Copy a sequence, removing elements for which a predicate is true.
636 * @ingroup mutating_algorithms
637 * @param __first An input iterator.
638 * @param __last An input iterator.
639 * @param __result An output iterator.
640 * @param __pred A predicate.
641 * @return An iterator designating the end of the resulting sequence.
642 *
643 * Copies each element in the range @p [__first,__last) for which
644 * @p __pred returns false to the range beginning at @p __result.
645 *
646 * remove_copy_if() is stable, so the relative order of elements that are
647 * copied is unchanged.
648 */
649 template<typename _InputIterator, typename _OutputIterator,
650 typename _Predicate>
651 _GLIBCXX20_CONSTEXPR
652 inline _OutputIterator
653 remove_copy_if(_InputIterator __first, _InputIterator __last,
654 _OutputIterator __result, _Predicate __pred)
655 {
656 // concept requirements
657 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
658 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
659 typename iterator_traits<_InputIterator>::value_type>)
660 __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
661 typename iterator_traits<_InputIterator>::value_type>)
662 __glibcxx_requires_valid_range(__first, __last);
663
664 return std::__remove_copy_if(__first, __last, __result,
665 __gnu_cxx::__ops::__pred_iter(__pred));
666 }
667
668#if __cplusplus201402L >= 201103L
669 /**
670 * @brief Copy the elements of a sequence for which a predicate is true.
671 * @ingroup mutating_algorithms
672 * @param __first An input iterator.
673 * @param __last An input iterator.
674 * @param __result An output iterator.
675 * @param __pred A predicate.
676 * @return An iterator designating the end of the resulting sequence.
677 *
678 * Copies each element in the range @p [__first,__last) for which
679 * @p __pred returns true to the range beginning at @p __result.
680 *
681 * copy_if() is stable, so the relative order of elements that are
682 * copied is unchanged.
683 */
684 template<typename _InputIterator, typename _OutputIterator,
685 typename _Predicate>
686 _GLIBCXX20_CONSTEXPR
687 _OutputIterator
688 copy_if(_InputIterator __first, _InputIterator __last,
689 _OutputIterator __result, _Predicate __pred)
690 {
691 // concept requirements
692 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
693 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
694 typename iterator_traits<_InputIterator>::value_type>)
695 __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
696 typename iterator_traits<_InputIterator>::value_type>)
697 __glibcxx_requires_valid_range(__first, __last);
698
699 for (; __first != __last; ++__first)
700 if (__pred(*__first))
701 {
702 *__result = *__first;
703 ++__result;
704 }
705 return __result;
706 }
707
708 template<typename _InputIterator, typename _Size, typename _OutputIterator>
709 _GLIBCXX20_CONSTEXPR
710 _OutputIterator
711 __copy_n_a(_InputIterator __first, _Size __n, _OutputIterator __result)
712 {
713 if (__n > 0)
714 {
715 while (true)
716 {
717 *__result = *__first;
718 ++__result;
719 if (--__n > 0)
720 ++__first;
721 else
722 break;
723 }
724 }
725 return __result;
726 }
727
728 template<typename _CharT, typename _Size>
729 __enable_if_t<__is_char<_CharT>::__value, _CharT*>
730 __copy_n_a(istreambuf_iterator<_CharT, char_traits<_CharT>>,
731 _Size, _CharT*);
732
733 template<typename _InputIterator, typename _Size, typename _OutputIterator>
734 _GLIBCXX20_CONSTEXPR
735 _OutputIterator
736 __copy_n(_InputIterator __first, _Size __n,
737 _OutputIterator __result, input_iterator_tag)
738 {
739 return std::__niter_wrap(__result,
740 __copy_n_a(__first, __n,
741 std::__niter_base(__result)));
742 }
743
744 template<typename _RandomAccessIterator, typename _Size,
745 typename _OutputIterator>
746 _GLIBCXX20_CONSTEXPR
747 inline _OutputIterator
748 __copy_n(_RandomAccessIterator __first, _Size __n,
749 _OutputIterator __result, random_access_iterator_tag)
750 { return std::copy(__first, __first + __n, __result); }
751
752 /**
753 * @brief Copies the range [first,first+n) into [result,result+n).
754 * @ingroup mutating_algorithms
755 * @param __first An input iterator.
756 * @param __n The number of elements to copy.
757 * @param __result An output iterator.
758 * @return result+n.
759 *
760 * This inline function will boil down to a call to @c memmove whenever
761 * possible. Failing that, if random access iterators are passed, then the
762 * loop count will be known (and therefore a candidate for compiler
763 * optimizations such as unrolling).
764 */
765 template<typename _InputIterator, typename _Size, typename _OutputIterator>
766 _GLIBCXX20_CONSTEXPR
767 inline _OutputIterator
768 copy_n(_InputIterator __first, _Size __n, _OutputIterator __result)
769 {
770 // concept requirements
771 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
772 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
773 typename iterator_traits<_InputIterator>::value_type>)
774 __glibcxx_requires_can_increment(__first, __n);
775 __glibcxx_requires_can_increment(__result, __n);
776
777 return std::__copy_n(__first, __n, __result,
778 std::__iterator_category(__first));
779 }
780
781 /**
782 * @brief Copy the elements of a sequence to separate output sequences
783 * depending on the truth value of a predicate.
784 * @ingroup mutating_algorithms
785 * @param __first An input iterator.
786 * @param __last An input iterator.
787 * @param __out_true An output iterator.
788 * @param __out_false An output iterator.
789 * @param __pred A predicate.
790 * @return A pair designating the ends of the resulting sequences.
791 *
792 * Copies each element in the range @p [__first,__last) for which
793 * @p __pred returns true to the range beginning at @p out_true
794 * and each element for which @p __pred returns false to @p __out_false.
795 */
796 template<typename _InputIterator, typename _OutputIterator1,
797 typename _OutputIterator2, typename _Predicate>
798 _GLIBCXX20_CONSTEXPR
799 pair<_OutputIterator1, _OutputIterator2>
800 partition_copy(_InputIterator __first, _InputIterator __last,
801 _OutputIterator1 __out_true, _OutputIterator2 __out_false,
802 _Predicate __pred)
803 {
804 // concept requirements
805 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
806 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator1,
807 typename iterator_traits<_InputIterator>::value_type>)
808 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator2,
809 typename iterator_traits<_InputIterator>::value_type>)
810 __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
811 typename iterator_traits<_InputIterator>::value_type>)
812 __glibcxx_requires_valid_range(__first, __last);
813
814 for (; __first != __last; ++__first)
815 if (__pred(*__first))
816 {
817 *__out_true = *__first;
818 ++__out_true;
819 }
820 else
821 {
822 *__out_false = *__first;
823 ++__out_false;
824 }
825
826 return pair<_OutputIterator1, _OutputIterator2>(__out_true, __out_false);
827 }
828#endif // C++11
829
830 template<typename _ForwardIterator, typename _Predicate>
831 _GLIBCXX20_CONSTEXPR
832 _ForwardIterator
833 __remove_if(_ForwardIterator __first, _ForwardIterator __last,
834 _Predicate __pred)
835 {
836 __first = std::__find_if(__first, __last, __pred);
837 if (__first == __last)
838 return __first;
839 _ForwardIterator __result = __first;
840 ++__first;
841 for (; __first != __last; ++__first)
842 if (!__pred(__first))
843 {
844 *__result = _GLIBCXX_MOVE(*__first)std::move(*__first);
845 ++__result;
846 }
847 return __result;
848 }
849
850 /**
851 * @brief Remove elements from a sequence.
852 * @ingroup mutating_algorithms
853 * @param __first An input iterator.
854 * @param __last An input iterator.
855 * @param __value The value to be removed.
856 * @return An iterator designating the end of the resulting sequence.
857 *
858 * All elements equal to @p __value are removed from the range
859 * @p [__first,__last).
860 *
861 * remove() is stable, so the relative order of elements that are
862 * not removed is unchanged.
863 *
864 * Elements between the end of the resulting sequence and @p __last
865 * are still present, but their value is unspecified.
866 */
867 template<typename _ForwardIterator, typename _Tp>
868 _GLIBCXX20_CONSTEXPR
869 inline _ForwardIterator
870 remove(_ForwardIterator __first, _ForwardIterator __last,
871 const _Tp& __value)
872 {
873 // concept requirements
874 __glibcxx_function_requires(_Mutable_ForwardIteratorConcept<
875 _ForwardIterator>)
876 __glibcxx_function_requires(_EqualOpConcept<
877 typename iterator_traits<_ForwardIterator>::value_type, _Tp>)
878 __glibcxx_requires_valid_range(__first, __last);
879
880 return std::__remove_if(__first, __last,
881 __gnu_cxx::__ops::__iter_equals_val(__value));
882 }
883
884 /**
885 * @brief Remove elements from a sequence using a predicate.
886 * @ingroup mutating_algorithms
887 * @param __first A forward iterator.
888 * @param __last A forward iterator.
889 * @param __pred A predicate.
890 * @return An iterator designating the end of the resulting sequence.
891 *
892 * All elements for which @p __pred returns true are removed from the range
893 * @p [__first,__last).
894 *
895 * remove_if() is stable, so the relative order of elements that are
896 * not removed is unchanged.
897 *
898 * Elements between the end of the resulting sequence and @p __last
899 * are still present, but their value is unspecified.
900 */
901 template<typename _ForwardIterator, typename _Predicate>
902 _GLIBCXX20_CONSTEXPR
903 inline _ForwardIterator
904 remove_if(_ForwardIterator __first, _ForwardIterator __last,
905 _Predicate __pred)
906 {
907 // concept requirements
908 __glibcxx_function_requires(_Mutable_ForwardIteratorConcept<
909 _ForwardIterator>)
910 __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
911 typename iterator_traits<_ForwardIterator>::value_type>)
912 __glibcxx_requires_valid_range(__first, __last);
913
914 return std::__remove_if(__first, __last,
915 __gnu_cxx::__ops::__pred_iter(__pred));
916 }
917
918 template<typename _ForwardIterator, typename _BinaryPredicate>
919 _GLIBCXX20_CONSTEXPR
920 _ForwardIterator
921 __adjacent_find(_ForwardIterator __first, _ForwardIterator __last,
922 _BinaryPredicate __binary_pred)
923 {
924 if (__first == __last)
925 return __last;
926 _ForwardIterator __next = __first;
927 while (++__next != __last)
928 {
929 if (__binary_pred(__first, __next))
930 return __first;
931 __first = __next;
932 }
933 return __last;
934 }
935
936 template<typename _ForwardIterator, typename _BinaryPredicate>
937 _GLIBCXX20_CONSTEXPR
938 _ForwardIterator
939 __unique(_ForwardIterator __first, _ForwardIterator __last,
940 _BinaryPredicate __binary_pred)
941 {
942 // Skip the beginning, if already unique.
943 __first = std::__adjacent_find(__first, __last, __binary_pred);
944 if (__first == __last)
945 return __last;
946
947 // Do the real copy work.
948 _ForwardIterator __dest = __first;
949 ++__first;
950 while (++__first != __last)
951 if (!__binary_pred(__dest, __first))
952 *++__dest = _GLIBCXX_MOVE(*__first)std::move(*__first);
953 return ++__dest;
954 }
955
956 /**
957 * @brief Remove consecutive duplicate values from a sequence.
958 * @ingroup mutating_algorithms
959 * @param __first A forward iterator.
960 * @param __last A forward iterator.
961 * @return An iterator designating the end of the resulting sequence.
962 *
963 * Removes all but the first element from each group of consecutive
964 * values that compare equal.
965 * unique() is stable, so the relative order of elements that are
966 * not removed is unchanged.
967 * Elements between the end of the resulting sequence and @p __last
968 * are still present, but their value is unspecified.
969 */
970 template<typename _ForwardIterator>
971 _GLIBCXX20_CONSTEXPR
972 inline _ForwardIterator
973 unique(_ForwardIterator __first, _ForwardIterator __last)
974 {
975 // concept requirements
976 __glibcxx_function_requires(_Mutable_ForwardIteratorConcept<
977 _ForwardIterator>)
978 __glibcxx_function_requires(_EqualityComparableConcept<
979 typename iterator_traits<_ForwardIterator>::value_type>)
980 __glibcxx_requires_valid_range(__first, __last);
981
982 return std::__unique(__first, __last,
983 __gnu_cxx::__ops::__iter_equal_to_iter());
984 }
985
986 /**
987 * @brief Remove consecutive values from a sequence using a predicate.
988 * @ingroup mutating_algorithms
989 * @param __first A forward iterator.
990 * @param __last A forward iterator.
991 * @param __binary_pred A binary predicate.
992 * @return An iterator designating the end of the resulting sequence.
993 *
994 * Removes all but the first element from each group of consecutive
995 * values for which @p __binary_pred returns true.
996 * unique() is stable, so the relative order of elements that are
997 * not removed is unchanged.
998 * Elements between the end of the resulting sequence and @p __last
999 * are still present, but their value is unspecified.
1000 */
1001 template<typename _ForwardIterator, typename _BinaryPredicate>
1002 _GLIBCXX20_CONSTEXPR
1003 inline _ForwardIterator
1004 unique(_ForwardIterator __first, _ForwardIterator __last,
1005 _BinaryPredicate __binary_pred)
1006 {
1007 // concept requirements
1008 __glibcxx_function_requires(_Mutable_ForwardIteratorConcept<
1009 _ForwardIterator>)
1010 __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate,
1011 typename iterator_traits<_ForwardIterator>::value_type,
1012 typename iterator_traits<_ForwardIterator>::value_type>)
1013 __glibcxx_requires_valid_range(__first, __last);
1014
1015 return std::__unique(__first, __last,
1016 __gnu_cxx::__ops::__iter_comp_iter(__binary_pred));
1017 }
1018
1019 /**
1020 * This is an uglified
1021 * unique_copy(_InputIterator, _InputIterator, _OutputIterator,
1022 * _BinaryPredicate)
1023 * overloaded for forward iterators and output iterator as result.
1024 */
1025 template<typename _ForwardIterator, typename _OutputIterator,
1026 typename _BinaryPredicate>
1027 _GLIBCXX20_CONSTEXPR
1028 _OutputIterator
1029 __unique_copy(_ForwardIterator __first, _ForwardIterator __last,
1030 _OutputIterator __result, _BinaryPredicate __binary_pred,
1031 forward_iterator_tag, output_iterator_tag)
1032 {
1033 // concept requirements -- iterators already checked
1034 __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate,
1035 typename iterator_traits<_ForwardIterator>::value_type,
1036 typename iterator_traits<_ForwardIterator>::value_type>)
1037
1038 _ForwardIterator __next = __first;
1039 *__result = *__first;
1040 while (++__next != __last)
1041 if (!__binary_pred(__first, __next))
1042 {
1043 __first = __next;
1044 *++__result = *__first;
1045 }
1046 return ++__result;
1047 }
1048
1049 /**
1050 * This is an uglified
1051 * unique_copy(_InputIterator, _InputIterator, _OutputIterator,
1052 * _BinaryPredicate)
1053 * overloaded for input iterators and output iterator as result.
1054 */
1055 template<typename _InputIterator, typename _OutputIterator,
1056 typename _BinaryPredicate>
1057 _GLIBCXX20_CONSTEXPR
1058 _OutputIterator
1059 __unique_copy(_InputIterator __first, _InputIterator __last,
1060 _OutputIterator __result, _BinaryPredicate __binary_pred,
1061 input_iterator_tag, output_iterator_tag)
1062 {
1063 // concept requirements -- iterators already checked
1064 __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate,
1065 typename iterator_traits<_InputIterator>::value_type,
1066 typename iterator_traits<_InputIterator>::value_type>)
1067
1068 typename iterator_traits<_InputIterator>::value_type __value = *__first;
1069 __decltype(__gnu_cxx::__ops::__iter_comp_val(__binary_pred))
1070 __rebound_pred
1071 = __gnu_cxx::__ops::__iter_comp_val(__binary_pred);
1072 *__result = __value;
1073 while (++__first != __last)
1074 if (!__rebound_pred(__first, __value))
1075 {
1076 __value = *__first;
1077 *++__result = __value;
1078 }
1079 return ++__result;
1080 }
1081
1082 /**
1083 * This is an uglified
1084 * unique_copy(_InputIterator, _InputIterator, _OutputIterator,
1085 * _BinaryPredicate)
1086 * overloaded for input iterators and forward iterator as result.
1087 */
1088 template<typename _InputIterator, typename _ForwardIterator,
1089 typename _BinaryPredicate>
1090 _GLIBCXX20_CONSTEXPR
1091 _ForwardIterator
1092 __unique_copy(_InputIterator __first, _InputIterator __last,
1093 _ForwardIterator __result, _BinaryPredicate __binary_pred,
1094 input_iterator_tag, forward_iterator_tag)
1095 {
1096 // concept requirements -- iterators already checked
1097 __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate,
1098 typename iterator_traits<_ForwardIterator>::value_type,
1099 typename iterator_traits<_InputIterator>::value_type>)
1100 *__result = *__first;
1101 while (++__first != __last)
1102 if (!__binary_pred(__result, __first))
1103 *++__result = *__first;
1104 return ++__result;
1105 }
1106
1107 /**
1108 * This is an uglified reverse(_BidirectionalIterator,
1109 * _BidirectionalIterator)
1110 * overloaded for bidirectional iterators.
1111 */
1112 template<typename _BidirectionalIterator>
1113 _GLIBCXX20_CONSTEXPR
1114 void
1115 __reverse(_BidirectionalIterator __first, _BidirectionalIterator __last,
1116 bidirectional_iterator_tag)
1117 {
1118 while (true)
1119 if (__first == __last || __first == --__last)
1120 return;
1121 else
1122 {
1123 std::iter_swap(__first, __last);
1124 ++__first;
1125 }
1126 }
1127
1128 /**
1129 * This is an uglified reverse(_BidirectionalIterator,
1130 * _BidirectionalIterator)
1131 * overloaded for random access iterators.
1132 */
1133 template<typename _RandomAccessIterator>
1134 _GLIBCXX20_CONSTEXPR
1135 void
1136 __reverse(_RandomAccessIterator __first, _RandomAccessIterator __last,
1137 random_access_iterator_tag)
1138 {
1139 if (__first == __last)
1140 return;
1141 --__last;
1142 while (__first < __last)
1143 {
1144 std::iter_swap(__first, __last);
1145 ++__first;
1146 --__last;
1147 }
1148 }
1149
1150 /**
1151 * @brief Reverse a sequence.
1152 * @ingroup mutating_algorithms
1153 * @param __first A bidirectional iterator.
1154 * @param __last A bidirectional iterator.
1155 * @return reverse() returns no value.
1156 *
1157 * Reverses the order of the elements in the range @p [__first,__last),
1158 * so that the first element becomes the last etc.
1159 * For every @c i such that @p 0<=i<=(__last-__first)/2), @p reverse()
1160 * swaps @p *(__first+i) and @p *(__last-(i+1))
1161 */
1162 template<typename _BidirectionalIterator>
1163 _GLIBCXX20_CONSTEXPR
1164 inline void
1165 reverse(_BidirectionalIterator __first, _BidirectionalIterator __last)
1166 {
1167 // concept requirements
1168 __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept<
1169 _BidirectionalIterator>)
1170 __glibcxx_requires_valid_range(__first, __last);
1171 std::__reverse(__first, __last, std::__iterator_category(__first));
1172 }
1173
1174 /**
1175 * @brief Copy a sequence, reversing its elements.
1176 * @ingroup mutating_algorithms
1177 * @param __first A bidirectional iterator.
1178 * @param __last A bidirectional iterator.
1179 * @param __result An output iterator.
1180 * @return An iterator designating the end of the resulting sequence.
1181 *
1182 * Copies the elements in the range @p [__first,__last) to the
1183 * range @p [__result,__result+(__last-__first)) such that the
1184 * order of the elements is reversed. For every @c i such that @p
1185 * 0<=i<=(__last-__first), @p reverse_copy() performs the
1186 * assignment @p *(__result+(__last-__first)-1-i) = *(__first+i).
1187 * The ranges @p [__first,__last) and @p
1188 * [__result,__result+(__last-__first)) must not overlap.
1189 */
1190 template<typename _BidirectionalIterator, typename _OutputIterator>
1191 _GLIBCXX20_CONSTEXPR
1192 _OutputIterator
1193 reverse_copy(_BidirectionalIterator __first, _BidirectionalIterator __last,
1194 _OutputIterator __result)
1195 {
1196 // concept requirements
1197 __glibcxx_function_requires(_BidirectionalIteratorConcept<
1198 _BidirectionalIterator>)
1199 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
1200 typename iterator_traits<_BidirectionalIterator>::value_type>)
1201 __glibcxx_requires_valid_range(__first, __last);
1202
1203 while (__first != __last)
1204 {
1205 --__last;
1206 *__result = *__last;
1207 ++__result;
1208 }
1209 return __result;
1210 }
1211
1212 /**
1213 * This is a helper function for the rotate algorithm specialized on RAIs.
1214 * It returns the greatest common divisor of two integer values.
1215 */
1216 template<typename _EuclideanRingElement>
1217 _GLIBCXX20_CONSTEXPR
1218 _EuclideanRingElement
1219 __gcd(_EuclideanRingElement __m, _EuclideanRingElement __n)
1220 {
1221 while (__n != 0)
1222 {
1223 _EuclideanRingElement __t = __m % __n;
1224 __m = __n;
1225 __n = __t;
1226 }
1227 return __m;
1228 }
1229
1230 inline namespace _V2
1231 {
1232
1233 /// This is a helper function for the rotate algorithm.
1234 template<typename _ForwardIterator>
1235 _GLIBCXX20_CONSTEXPR
1236 _ForwardIterator
1237 __rotate(_ForwardIterator __first,
1238 _ForwardIterator __middle,
1239 _ForwardIterator __last,
1240 forward_iterator_tag)
1241 {
1242 if (__first == __middle)
1243 return __last;
1244 else if (__last == __middle)
1245 return __first;
1246
1247 _ForwardIterator __first2 = __middle;
1248 do
1249 {
1250 std::iter_swap(__first, __first2);
1251 ++__first;
1252 ++__first2;
1253 if (__first == __middle)
1254 __middle = __first2;
1255 }
1256 while (__first2 != __last);
1257
1258 _ForwardIterator __ret = __first;
1259
1260 __first2 = __middle;
1261
1262 while (__first2 != __last)
1263 {
1264 std::iter_swap(__first, __first2);
1265 ++__first;
1266 ++__first2;
1267 if (__first == __middle)
1268 __middle = __first2;
1269 else if (__first2 == __last)
1270 __first2 = __middle;
1271 }
1272 return __ret;
1273 }
1274
1275 /// This is a helper function for the rotate algorithm.
1276 template<typename _BidirectionalIterator>
1277 _GLIBCXX20_CONSTEXPR
1278 _BidirectionalIterator
1279 __rotate(_BidirectionalIterator __first,
1280 _BidirectionalIterator __middle,
1281 _BidirectionalIterator __last,
1282 bidirectional_iterator_tag)
1283 {
1284 // concept requirements
1285 __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept<
1286 _BidirectionalIterator>)
1287
1288 if (__first == __middle)
1289 return __last;
1290 else if (__last == __middle)
1291 return __first;
1292
1293 std::__reverse(__first, __middle, bidirectional_iterator_tag());
1294 std::__reverse(__middle, __last, bidirectional_iterator_tag());
1295
1296 while (__first != __middle && __middle != __last)
1297 {
1298 std::iter_swap(__first, --__last);
1299 ++__first;
1300 }
1301
1302 if (__first == __middle)
1303 {
1304 std::__reverse(__middle, __last, bidirectional_iterator_tag());
1305 return __last;
1306 }
1307 else
1308 {
1309 std::__reverse(__first, __middle, bidirectional_iterator_tag());
1310 return __first;
1311 }
1312 }
1313
1314 /// This is a helper function for the rotate algorithm.
1315 template<typename _RandomAccessIterator>
1316 _GLIBCXX20_CONSTEXPR
1317 _RandomAccessIterator
1318 __rotate(_RandomAccessIterator __first,
1319 _RandomAccessIterator __middle,
1320 _RandomAccessIterator __last,
1321 random_access_iterator_tag)
1322 {
1323 // concept requirements
1324 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
1325 _RandomAccessIterator>)
1326
1327 if (__first == __middle)
1328 return __last;
1329 else if (__last == __middle)
1330 return __first;
1331
1332 typedef typename iterator_traits<_RandomAccessIterator>::difference_type
1333 _Distance;
1334 typedef typename iterator_traits<_RandomAccessIterator>::value_type
1335 _ValueType;
1336
1337 _Distance __n = __last - __first;
1338 _Distance __k = __middle - __first;
1339
1340 if (__k == __n - __k)
1341 {
1342 std::swap_ranges(__first, __middle, __middle);
1343 return __middle;
1344 }
1345
1346 _RandomAccessIterator __p = __first;
1347 _RandomAccessIterator __ret = __first + (__last - __middle);
1348
1349 for (;;)
1350 {
1351 if (__k < __n - __k)
1352 {
1353 if (__is_pod(_ValueType) && __k == 1)
1354 {
1355 _ValueType __t = _GLIBCXX_MOVE(*__p)std::move(*__p);
1356 _GLIBCXX_MOVE3(__p + 1, __p + __n, __p)std::move(__p + 1, __p + __n, __p);
1357 *(__p + __n - 1) = _GLIBCXX_MOVE(__t)std::move(__t);
1358 return __ret;
1359 }
1360 _RandomAccessIterator __q = __p + __k;
1361 for (_Distance __i = 0; __i < __n - __k; ++ __i)
1362 {
1363 std::iter_swap(__p, __q);
1364 ++__p;
1365 ++__q;
1366 }
1367 __n %= __k;
1368 if (__n == 0)
1369 return __ret;
1370 std::swap(__n, __k);
1371 __k = __n - __k;
1372 }
1373 else
1374 {
1375 __k = __n - __k;
1376 if (__is_pod(_ValueType) && __k == 1)
1377 {
1378 _ValueType __t = _GLIBCXX_MOVE(*(__p + __n - 1))std::move(*(__p + __n - 1));
1379 _GLIBCXX_MOVE_BACKWARD3(__p, __p + __n - 1, __p + __n)std::move_backward(__p, __p + __n - 1, __p + __n);
1380 *__p = _GLIBCXX_MOVE(__t)std::move(__t);
1381 return __ret;
1382 }
1383 _RandomAccessIterator __q = __p + __n;
1384 __p = __q - __k;
1385 for (_Distance __i = 0; __i < __n - __k; ++ __i)
1386 {
1387 --__p;
1388 --__q;
1389 std::iter_swap(__p, __q);
1390 }
1391 __n %= __k;
1392 if (__n == 0)
1393 return __ret;
1394 std::swap(__n, __k);
1395 }
1396 }
1397 }
1398
1399 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1400 // DR 488. rotate throws away useful information
1401 /**
1402 * @brief Rotate the elements of a sequence.
1403 * @ingroup mutating_algorithms
1404 * @param __first A forward iterator.
1405 * @param __middle A forward iterator.
1406 * @param __last A forward iterator.
1407 * @return first + (last - middle).
1408 *
1409 * Rotates the elements of the range @p [__first,__last) by
1410 * @p (__middle - __first) positions so that the element at @p __middle
1411 * is moved to @p __first, the element at @p __middle+1 is moved to
1412 * @p __first+1 and so on for each element in the range
1413 * @p [__first,__last).
1414 *
1415 * This effectively swaps the ranges @p [__first,__middle) and
1416 * @p [__middle,__last).
1417 *
1418 * Performs
1419 * @p *(__first+(n+(__last-__middle))%(__last-__first))=*(__first+n)
1420 * for each @p n in the range @p [0,__last-__first).
1421 */
1422 template<typename _ForwardIterator>
1423 _GLIBCXX20_CONSTEXPR
1424 inline _ForwardIterator
1425 rotate(_ForwardIterator __first, _ForwardIterator __middle,
1426 _ForwardIterator __last)
1427 {
1428 // concept requirements
1429 __glibcxx_function_requires(_Mutable_ForwardIteratorConcept<
1430 _ForwardIterator>)
1431 __glibcxx_requires_valid_range(__first, __middle);
1432 __glibcxx_requires_valid_range(__middle, __last);
1433
1434 return std::__rotate(__first, __middle, __last,
1435 std::__iterator_category(__first));
1436 }
1437
1438 } // namespace _V2
1439
1440 /**
1441 * @brief Copy a sequence, rotating its elements.
1442 * @ingroup mutating_algorithms
1443 * @param __first A forward iterator.
1444 * @param __middle A forward iterator.
1445 * @param __last A forward iterator.
1446 * @param __result An output iterator.
1447 * @return An iterator designating the end of the resulting sequence.
1448 *
1449 * Copies the elements of the range @p [__first,__last) to the
1450 * range beginning at @result, rotating the copied elements by
1451 * @p (__middle-__first) positions so that the element at @p __middle
1452 * is moved to @p __result, the element at @p __middle+1 is moved
1453 * to @p __result+1 and so on for each element in the range @p
1454 * [__first,__last).
1455 *
1456 * Performs
1457 * @p *(__result+(n+(__last-__middle))%(__last-__first))=*(__first+n)
1458 * for each @p n in the range @p [0,__last-__first).
1459 */
1460 template<typename _ForwardIterator, typename _OutputIterator>
1461 _GLIBCXX20_CONSTEXPR
1462 inline _OutputIterator
1463 rotate_copy(_ForwardIterator __first, _ForwardIterator __middle,
1464 _ForwardIterator __last, _OutputIterator __result)
1465 {
1466 // concept requirements
1467 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
1468 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
1469 typename iterator_traits<_ForwardIterator>::value_type>)
1470 __glibcxx_requires_valid_range(__first, __middle);
1471 __glibcxx_requires_valid_range(__middle, __last);
1472
1473 return std::copy(__first, __middle,
1474 std::copy(__middle, __last, __result));
1475 }
1476
1477 /// This is a helper function...
1478 template<typename _ForwardIterator, typename _Predicate>
1479 _GLIBCXX20_CONSTEXPR
1480 _ForwardIterator
1481 __partition(_ForwardIterator __first, _ForwardIterator __last,
1482 _Predicate __pred, forward_iterator_tag)
1483 {
1484 if (__first == __last)
1485 return __first;
1486
1487 while (__pred(*__first))
1488 if (++__first == __last)
1489 return __first;
1490
1491 _ForwardIterator __next = __first;
1492
1493 while (++__next != __last)
1494 if (__pred(*__next))
1495 {
1496 std::iter_swap(__first, __next);
1497 ++__first;
1498 }
1499
1500 return __first;
1501 }
1502
1503 /// This is a helper function...
1504 template<typename _BidirectionalIterator, typename _Predicate>
1505 _GLIBCXX20_CONSTEXPR
1506 _BidirectionalIterator
1507 __partition(_BidirectionalIterator __first, _BidirectionalIterator __last,
1508 _Predicate __pred, bidirectional_iterator_tag)
1509 {
1510 while (true)
1511 {
1512 while (true)
1513 if (__first == __last)
1514 return __first;
1515 else if (__pred(*__first))
1516 ++__first;
1517 else
1518 break;
1519 --__last;
1520 while (true)
1521 if (__first == __last)
1522 return __first;
1523 else if (!bool(__pred(*__last)))
1524 --__last;
1525 else
1526 break;
1527 std::iter_swap(__first, __last);
1528 ++__first;
1529 }
1530 }
1531
1532 // partition
1533
1534 /// This is a helper function...
1535 /// Requires __first != __last and !__pred(__first)
1536 /// and __len == distance(__first, __last).
1537 ///
1538 /// !__pred(__first) allows us to guarantee that we don't
1539 /// move-assign an element onto itself.
1540 template<typename _ForwardIterator, typename _Pointer, typename _Predicate,
1541 typename _Distance>
1542 _ForwardIterator
1543 __stable_partition_adaptive(_ForwardIterator __first,
1544 _ForwardIterator __last,
1545 _Predicate __pred, _Distance __len,
1546 _Pointer __buffer,
1547 _Distance __buffer_size)
1548 {
1549 if (__len == 1)
1550 return __first;
1551
1552 if (__len <= __buffer_size)
1553 {
1554 _ForwardIterator __result1 = __first;
1555 _Pointer __result2 = __buffer;
1556
1557 // The precondition guarantees that !__pred(__first), so
1558 // move that element to the buffer before starting the loop.
1559 // This ensures that we only call __pred once per element.
1560 *__result2 = _GLIBCXX_MOVE(*__first)std::move(*__first);
1561 ++__result2;
1562 ++__first;
1563 for (; __first != __last; ++__first)
1564 if (__pred(__first))
1565 {
1566 *__result1 = _GLIBCXX_MOVE(*__first)std::move(*__first);
1567 ++__result1;
1568 }
1569 else
1570 {
1571 *__result2 = _GLIBCXX_MOVE(*__first)std::move(*__first);
1572 ++__result2;
1573 }
1574
1575 _GLIBCXX_MOVE3(__buffer, __result2, __result1)std::move(__buffer, __result2, __result1);
1576 return __result1;
1577 }
1578
1579 _ForwardIterator __middle = __first;
1580 std::advance(__middle, __len / 2);
1581 _ForwardIterator __left_split =
1582 std::__stable_partition_adaptive(__first, __middle, __pred,
1583 __len / 2, __buffer,
1584 __buffer_size);
1585
1586 // Advance past true-predicate values to satisfy this
1587 // function's preconditions.
1588 _Distance __right_len = __len - __len / 2;
1589 _ForwardIterator __right_split =
1590 std::__find_if_not_n(__middle, __right_len, __pred);
1591
1592 if (__right_len)
1593 __right_split =
1594 std::__stable_partition_adaptive(__right_split, __last, __pred,
1595 __right_len,
1596 __buffer, __buffer_size);
1597
1598 return std::rotate(__left_split, __middle, __right_split);
1599 }
1600
1601 template<typename _ForwardIterator, typename _Predicate>
1602 _ForwardIterator
1603 __stable_partition(_ForwardIterator __first, _ForwardIterator __last,
1604 _Predicate __pred)
1605 {
1606 __first = std::__find_if_not(__first, __last, __pred);
1607
1608 if (__first == __last)
1609 return __first;
1610
1611 typedef typename iterator_traits<_ForwardIterator>::value_type
1612 _ValueType;
1613 typedef typename iterator_traits<_ForwardIterator>::difference_type
1614 _DistanceType;
1615
1616 _Temporary_buffer<_ForwardIterator, _ValueType>
1617 __buf(__first, std::distance(__first, __last));
1618 return
1619 std::__stable_partition_adaptive(__first, __last, __pred,
1620 _DistanceType(__buf.requested_size()),
1621 __buf.begin(),
1622 _DistanceType(__buf.size()));
1623 }
1624
1625 /**
1626 * @brief Move elements for which a predicate is true to the beginning
1627 * of a sequence, preserving relative ordering.
1628 * @ingroup mutating_algorithms
1629 * @param __first A forward iterator.
1630 * @param __last A forward iterator.
1631 * @param __pred A predicate functor.
1632 * @return An iterator @p middle such that @p __pred(i) is true for each
1633 * iterator @p i in the range @p [first,middle) and false for each @p i
1634 * in the range @p [middle,last).
1635 *
1636 * Performs the same function as @p partition() with the additional
1637 * guarantee that the relative ordering of elements in each group is
1638 * preserved, so any two elements @p x and @p y in the range
1639 * @p [__first,__last) such that @p __pred(x)==__pred(y) will have the same
1640 * relative ordering after calling @p stable_partition().
1641 */
1642 template<typename _ForwardIterator, typename _Predicate>
1643 inline _ForwardIterator
1644 stable_partition(_ForwardIterator __first, _ForwardIterator __last,
1645 _Predicate __pred)
1646 {
1647 // concept requirements
1648 __glibcxx_function_requires(_Mutable_ForwardIteratorConcept<
1649 _ForwardIterator>)
1650 __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
1651 typename iterator_traits<_ForwardIterator>::value_type>)
1652 __glibcxx_requires_valid_range(__first, __last);
1653
1654 return std::__stable_partition(__first, __last,
1655 __gnu_cxx::__ops::__pred_iter(__pred));
1656 }
1657
1658 /// This is a helper function for the sort routines.
1659 template<typename _RandomAccessIterator, typename _Compare>
1660 _GLIBCXX20_CONSTEXPR
1661 void
1662 __heap_select(_RandomAccessIterator __first,
1663 _RandomAccessIterator __middle,
1664 _RandomAccessIterator __last, _Compare __comp)
1665 {
1666 std::__make_heap(__first, __middle, __comp);
1667 for (_RandomAccessIterator __i = __middle; __i < __last; ++__i)
1668 if (__comp(__i, __first))
1669 std::__pop_heap(__first, __middle, __i, __comp);
1670 }
1671
1672 // partial_sort
1673
1674 template<typename _InputIterator, typename _RandomAccessIterator,
1675 typename _Compare>
1676 _GLIBCXX20_CONSTEXPR
1677 _RandomAccessIterator
1678 __partial_sort_copy(_InputIterator __first, _InputIterator __last,
1679 _RandomAccessIterator __result_first,
1680 _RandomAccessIterator __result_last,
1681 _Compare __comp)
1682 {
1683 typedef typename iterator_traits<_InputIterator>::value_type
1684 _InputValueType;
1685 typedef iterator_traits<_RandomAccessIterator> _RItTraits;
1686 typedef typename _RItTraits::difference_type _DistanceType;
1687
1688 if (__result_first == __result_last)
1689 return __result_last;
1690 _RandomAccessIterator __result_real_last = __result_first;
1691 while (__first != __last && __result_real_last != __result_last)
1692 {
1693 *__result_real_last = *__first;
1694 ++__result_real_last;
1695 ++__first;
1696 }
1697
1698 std::__make_heap(__result_first, __result_real_last, __comp);
1699 while (__first != __last)
1700 {
1701 if (__comp(__first, __result_first))
1702 std::__adjust_heap(__result_first, _DistanceType(0),
1703 _DistanceType(__result_real_last
1704 - __result_first),
1705 _InputValueType(*__first), __comp);
1706 ++__first;
1707 }
1708 std::__sort_heap(__result_first, __result_real_last, __comp);
1709 return __result_real_last;
1710 }
1711
1712 /**
1713 * @brief Copy the smallest elements of a sequence.
1714 * @ingroup sorting_algorithms
1715 * @param __first An iterator.
1716 * @param __last Another iterator.
1717 * @param __result_first A random-access iterator.
1718 * @param __result_last Another random-access iterator.
1719 * @return An iterator indicating the end of the resulting sequence.
1720 *
1721 * Copies and sorts the smallest N values from the range @p [__first,__last)
1722 * to the range beginning at @p __result_first, where the number of
1723 * elements to be copied, @p N, is the smaller of @p (__last-__first) and
1724 * @p (__result_last-__result_first).
1725 * After the sort if @e i and @e j are iterators in the range
1726 * @p [__result_first,__result_first+N) such that i precedes j then
1727 * *j<*i is false.
1728 * The value returned is @p __result_first+N.
1729 */
1730 template<typename _InputIterator, typename _RandomAccessIterator>
1731 _GLIBCXX20_CONSTEXPR
1732 inline _RandomAccessIterator
1733 partial_sort_copy(_InputIterator __first, _InputIterator __last,
1734 _RandomAccessIterator __result_first,
1735 _RandomAccessIterator __result_last)
1736 {
1737#ifdef _GLIBCXX_CONCEPT_CHECKS
1738 typedef typename iterator_traits<_InputIterator>::value_type
1739 _InputValueType;
1740 typedef typename iterator_traits<_RandomAccessIterator>::value_type
1741 _OutputValueType;
1742#endif
1743
1744 // concept requirements
1745 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
1746 __glibcxx_function_requires(_ConvertibleConcept<_InputValueType,
1747 _OutputValueType>)
1748 __glibcxx_function_requires(_LessThanOpConcept<_InputValueType,
1749 _OutputValueType>)
1750 __glibcxx_function_requires(_LessThanComparableConcept<_OutputValueType>)
1751 __glibcxx_requires_valid_range(__first, __last);
1752 __glibcxx_requires_irreflexive(__first, __last);
1753 __glibcxx_requires_valid_range(__result_first, __result_last);
1754
1755 return std::__partial_sort_copy(__first, __last,
1756 __result_first, __result_last,
1757 __gnu_cxx::__ops::__iter_less_iter());
1758 }
1759
1760 /**
1761 * @brief Copy the smallest elements of a sequence using a predicate for
1762 * comparison.
1763 * @ingroup sorting_algorithms
1764 * @param __first An input iterator.
1765 * @param __last Another input iterator.
1766 * @param __result_first A random-access iterator.
1767 * @param __result_last Another random-access iterator.
1768 * @param __comp A comparison functor.
1769 * @return An iterator indicating the end of the resulting sequence.
1770 *
1771 * Copies and sorts the smallest N values from the range @p [__first,__last)
1772 * to the range beginning at @p result_first, where the number of
1773 * elements to be copied, @p N, is the smaller of @p (__last-__first) and
1774 * @p (__result_last-__result_first).
1775 * After the sort if @e i and @e j are iterators in the range
1776 * @p [__result_first,__result_first+N) such that i precedes j then
1777 * @p __comp(*j,*i) is false.
1778 * The value returned is @p __result_first+N.
1779 */
1780 template<typename _InputIterator, typename _RandomAccessIterator,
1781 typename _Compare>
1782 _GLIBCXX20_CONSTEXPR
1783 inline _RandomAccessIterator
1784 partial_sort_copy(_InputIterator __first, _InputIterator __last,
1785 _RandomAccessIterator __result_first,
1786 _RandomAccessIterator __result_last,
1787 _Compare __comp)
1788 {
1789#ifdef _GLIBCXX_CONCEPT_CHECKS
1790 typedef typename iterator_traits<_InputIterator>::value_type
1791 _InputValueType;
1792 typedef typename iterator_traits<_RandomAccessIterator>::value_type
1793 _OutputValueType;
1794#endif
1795
1796 // concept requirements
1797 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
1798 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
1799 _RandomAccessIterator>)
1800 __glibcxx_function_requires(_ConvertibleConcept<_InputValueType,
1801 _OutputValueType>)
1802 __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
1803 _InputValueType, _OutputValueType>)
1804 __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
1805 _OutputValueType, _OutputValueType>)
1806 __glibcxx_requires_valid_range(__first, __last);
1807 __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
1808 __glibcxx_requires_valid_range(__result_first, __result_last);
1809
1810 return std::__partial_sort_copy(__first, __last,
1811 __result_first, __result_last,
1812 __gnu_cxx::__ops::__iter_comp_iter(__comp));
1813 }
1814
1815 /// This is a helper function for the sort routine.
1816 template<typename _RandomAccessIterator, typename _Compare>
1817 _GLIBCXX20_CONSTEXPR
1818 void
1819 __unguarded_linear_insert(_RandomAccessIterator __last,
1820 _Compare __comp)
1821 {
1822 typename iterator_traits<_RandomAccessIterator>::value_type
1823 __val = _GLIBCXX_MOVE(*__last)std::move(*__last);
1824 _RandomAccessIterator __next = __last;
1825 --__next;
1826 while (__comp(__val, __next))
1827 {
1828 *__last = _GLIBCXX_MOVE(*__next)std::move(*__next);
1829 __last = __next;
1830 --__next;
1831 }
1832 *__last = _GLIBCXX_MOVE(__val)std::move(__val);
1833 }
1834
1835 /// This is a helper function for the sort routine.
1836 template<typename _RandomAccessIterator, typename _Compare>
1837 _GLIBCXX20_CONSTEXPR
1838 void
1839 __insertion_sort(_RandomAccessIterator __first,
1840 _RandomAccessIterator __last, _Compare __comp)
1841 {
1842 if (__first
59.1
'__first' is not equal to '__last'
59.1
'__first' is not equal to '__last'
59.1
'__first' is not equal to '__last'
== __last) return;
60
Taking false branch
1843
1844 for (_RandomAccessIterator __i = __first + 1; __i
60.1
'__i' is not equal to '__last'
60.1
'__i' is not equal to '__last'
60.1
'__i' is not equal to '__last'
!= __last; ++__i)
61
Loop condition is true. Entering loop body
1845 {
1846 if (__comp(__i, __first))
62
Calling '_Iter_less_iter::operator()'
1847 {
1848 typename iterator_traits<_RandomAccessIterator>::value_type
1849 __val = _GLIBCXX_MOVE(*__i)std::move(*__i);
1850 _GLIBCXX_MOVE_BACKWARD3(__first, __i, __i + 1)std::move_backward(__first, __i, __i + 1);
1851 *__first = _GLIBCXX_MOVE(__val)std::move(__val);
1852 }
1853 else
1854 std::__unguarded_linear_insert(__i,
1855 __gnu_cxx::__ops::__val_comp_iter(__comp));
1856 }
1857 }
1858
1859 /// This is a helper function for the sort routine.
1860 template<typename _RandomAccessIterator, typename _Compare>
1861 _GLIBCXX20_CONSTEXPR
1862 inline void
1863 __unguarded_insertion_sort(_RandomAccessIterator __first,
1864 _RandomAccessIterator __last, _Compare __comp)
1865 {
1866 for (_RandomAccessIterator __i = __first; __i != __last; ++__i)
1867 std::__unguarded_linear_insert(__i,
1868 __gnu_cxx::__ops::__val_comp_iter(__comp));
1869 }
1870
1871 /**
1872 * @doctodo
1873 * This controls some aspect of the sort routines.
1874 */
1875 enum { _S_threshold = 16 };
1876
1877 /// This is a helper function for the sort routine.
1878 template<typename _RandomAccessIterator, typename _Compare>
1879 _GLIBCXX20_CONSTEXPR
1880 void
1881 __final_insertion_sort(_RandomAccessIterator __first,
1882 _RandomAccessIterator __last, _Compare __comp)
1883 {
1884 if (__last - __first > int(_S_threshold))
58
Taking false branch
1885 {
1886 std::__insertion_sort(__first, __first + int(_S_threshold), __comp);
1887 std::__unguarded_insertion_sort(__first + int(_S_threshold), __last,
1888 __comp);
1889 }
1890 else
1891 std::__insertion_sort(__first, __last, __comp);
59
Calling '__insertion_sort<unsigned int *, __gnu_cxx::__ops::_Iter_less_iter>'
1892 }
1893
1894 /// This is a helper function...
1895 template<typename _RandomAccessIterator, typename _Compare>
1896 _GLIBCXX20_CONSTEXPR
1897 _RandomAccessIterator
1898 __unguarded_partition(_RandomAccessIterator __first,
1899 _RandomAccessIterator __last,
1900 _RandomAccessIterator __pivot, _Compare __comp)
1901 {
1902 while (true)
1903 {
1904 while (__comp(__first, __pivot))
1905 ++__first;
1906 --__last;
1907 while (__comp(__pivot, __last))
1908 --__last;
1909 if (!(__first < __last))
1910 return __first;
1911 std::iter_swap(__first, __last);
1912 ++__first;
1913 }
1914 }
1915
1916 /// This is a helper function...
1917 template<typename _RandomAccessIterator, typename _Compare>
1918 _GLIBCXX20_CONSTEXPR
1919 inline _RandomAccessIterator
1920 __unguarded_partition_pivot(_RandomAccessIterator __first,
1921 _RandomAccessIterator __last, _Compare __comp)
1922 {
1923 _RandomAccessIterator __mid = __first + (__last - __first) / 2;
1924 std::__move_median_to_first(__first, __first + 1, __mid, __last - 1,
1925 __comp);
1926 return std::__unguarded_partition(__first + 1, __last, __first, __comp);
1927 }
1928
1929 template<typename _RandomAccessIterator, typename _Compare>
1930 _GLIBCXX20_CONSTEXPR
1931 inline void
1932 __partial_sort(_RandomAccessIterator __first,
1933 _RandomAccessIterator __middle,
1934 _RandomAccessIterator __last,
1935 _Compare __comp)
1936 {
1937 std::__heap_select(__first, __middle, __last, __comp);
1938 std::__sort_heap(__first, __middle, __comp);
1939 }
1940
1941 /// This is a helper function for the sort routine.
1942 template<typename _RandomAccessIterator, typename _Size, typename _Compare>
1943 _GLIBCXX20_CONSTEXPR
1944 void
1945 __introsort_loop(_RandomAccessIterator __first,
1946 _RandomAccessIterator __last,
1947 _Size __depth_limit, _Compare __comp)
1948 {
1949 while (__last - __first > int(_S_threshold))
1950 {
1951 if (__depth_limit == 0)
1952 {
1953 std::__partial_sort(__first, __last, __last, __comp);
1954 return;
1955 }
1956 --__depth_limit;
1957 _RandomAccessIterator __cut =
1958 std::__unguarded_partition_pivot(__first, __last, __comp);
1959 std::__introsort_loop(__cut, __last, __depth_limit, __comp);
1960 __last = __cut;
1961 }
1962 }
1963
1964 // sort
1965
1966 template<typename _RandomAccessIterator, typename _Compare>
1967 _GLIBCXX20_CONSTEXPR
1968 inline void
1969 __sort(_RandomAccessIterator __first, _RandomAccessIterator __last,
1970 _Compare __comp)
1971 {
1972 if (__first
55.1
'__first' is not equal to '__last'
55.1
'__first' is not equal to '__last'
55.1
'__first' is not equal to '__last'
!= __last)
56
Taking true branch
1973 {
1974 std::__introsort_loop(__first, __last,
1975 std::__lg(__last - __first) * 2,
1976 __comp);
1977 std::__final_insertion_sort(__first, __last, __comp);
57
Calling '__final_insertion_sort<unsigned int *, __gnu_cxx::__ops::_Iter_less_iter>'
1978 }
1979 }
1980
1981 template<typename _RandomAccessIterator, typename _Size, typename _Compare>
1982 _GLIBCXX20_CONSTEXPR
1983 void
1984 __introselect(_RandomAccessIterator __first, _RandomAccessIterator __nth,
1985 _RandomAccessIterator __last, _Size __depth_limit,
1986 _Compare __comp)
1987 {
1988 while (__last - __first > 3)
1989 {
1990 if (__depth_limit == 0)
1991 {
1992 std::__heap_select(__first, __nth + 1, __last, __comp);
1993 // Place the nth largest element in its final position.
1994 std::iter_swap(__first, __nth);
1995 return;
1996 }
1997 --__depth_limit;
1998 _RandomAccessIterator __cut =
1999 std::__unguarded_partition_pivot(__first, __last, __comp);
2000 if (__cut <= __nth)
2001 __first = __cut;
2002 else
2003 __last = __cut;
2004 }
2005 std::__insertion_sort(__first, __last, __comp);
2006 }
2007
2008 // nth_element
2009
2010 // lower_bound moved to stl_algobase.h
2011
2012 /**
2013 * @brief Finds the first position in which @p __val could be inserted
2014 * without changing the ordering.
2015 * @ingroup binary_search_algorithms
2016 * @param __first An iterator.
2017 * @param __last Another iterator.
2018 * @param __val The search term.
2019 * @param __comp A functor to use for comparisons.
2020 * @return An iterator pointing to the first element <em>not less
2021 * than</em> @p __val, or end() if every element is less
2022 * than @p __val.
2023 * @ingroup binary_search_algorithms
2024 *
2025 * The comparison function should have the same effects on ordering as
2026 * the function used for the initial sort.
2027 */
2028 template<typename _ForwardIterator, typename _Tp, typename _Compare>
2029 _GLIBCXX20_CONSTEXPR
2030 inline _ForwardIterator
2031 lower_bound(_ForwardIterator __first, _ForwardIterator __last,
2032 const _Tp& __val, _Compare __comp)
2033 {
2034 // concept requirements
2035 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
2036 __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
2037 typename iterator_traits<_ForwardIterator>::value_type, _Tp>)
2038 __glibcxx_requires_partitioned_lower_pred(__first, __last,
2039 __val, __comp);
2040
2041 return std::__lower_bound(__first, __last, __val,
2042 __gnu_cxx::__ops::__iter_comp_val(__comp));
2043 }
2044
2045 template<typename _ForwardIterator, typename _Tp, typename _Compare>
2046 _GLIBCXX20_CONSTEXPR
2047 _ForwardIterator
2048 __upper_bound(_ForwardIterator __first, _ForwardIterator __last,
2049 const _Tp& __val, _Compare __comp)
2050 {
2051 typedef typename iterator_traits<_ForwardIterator>::difference_type
2052 _DistanceType;
2053
2054 _DistanceType __len = std::distance(__first, __last);
2055
2056 while (__len > 0)
2057 {
2058 _DistanceType __half = __len >> 1;
2059 _ForwardIterator __middle = __first;
2060 std::advance(__middle, __half);
2061 if (__comp(__val, __middle))
2062 __len = __half;
2063 else
2064 {
2065 __first = __middle;
2066 ++__first;
2067 __len = __len - __half - 1;
2068 }
2069 }
2070 return __first;
2071 }
2072
2073 /**
2074 * @brief Finds the last position in which @p __val could be inserted
2075 * without changing the ordering.
2076 * @ingroup binary_search_algorithms
2077 * @param __first An iterator.
2078 * @param __last Another iterator.
2079 * @param __val The search term.
2080 * @return An iterator pointing to the first element greater than @p __val,
2081 * or end() if no elements are greater than @p __val.
2082 * @ingroup binary_search_algorithms
2083 */
2084 template<typename _ForwardIterator, typename _Tp>
2085 _GLIBCXX20_CONSTEXPR
2086 inline _ForwardIterator
2087 upper_bound(_ForwardIterator __first, _ForwardIterator __last,
2088 const _Tp& __val)
2089 {
2090 // concept requirements
2091 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
2092 __glibcxx_function_requires(_LessThanOpConcept<
2093 _Tp, typename iterator_traits<_ForwardIterator>::value_type>)
2094 __glibcxx_requires_partitioned_upper(__first, __last, __val);
2095
2096 return std::__upper_bound(__first, __last, __val,
2097 __gnu_cxx::__ops::__val_less_iter());
2098 }
2099
2100 /**
2101 * @brief Finds the last position in which @p __val could be inserted
2102 * without changing the ordering.
2103 * @ingroup binary_search_algorithms
2104 * @param __first An iterator.
2105 * @param __last Another iterator.
2106 * @param __val The search term.
2107 * @param __comp A functor to use for comparisons.
2108 * @return An iterator pointing to the first element greater than @p __val,
2109 * or end() if no elements are greater than @p __val.
2110 * @ingroup binary_search_algorithms
2111 *
2112 * The comparison function should have the same effects on ordering as
2113 * the function used for the initial sort.
2114 */
2115 template<typename _ForwardIterator, typename _Tp, typename _Compare>
2116 _GLIBCXX20_CONSTEXPR
2117 inline _ForwardIterator
2118 upper_bound(_ForwardIterator __first, _ForwardIterator __last,
2119 const _Tp& __val, _Compare __comp)
2120 {
2121 // concept requirements
2122 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
2123 __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
2124 _Tp, typename iterator_traits<_ForwardIterator>::value_type>)
2125 __glibcxx_requires_partitioned_upper_pred(__first, __last,
2126 __val, __comp);
2127
2128 return std::__upper_bound(__first, __last, __val,
2129 __gnu_cxx::__ops::__val_comp_iter(__comp));
2130 }
2131
2132 template<typename _ForwardIterator, typename _Tp,
2133 typename _CompareItTp, typename _CompareTpIt>
2134 _GLIBCXX20_CONSTEXPR
2135 pair<_ForwardIterator, _ForwardIterator>
2136 __equal_range(_ForwardIterator __first, _ForwardIterator __last,
2137 const _Tp& __val,
2138 _CompareItTp __comp_it_val, _CompareTpIt __comp_val_it)
2139 {
2140 typedef typename iterator_traits<_ForwardIterator>::difference_type
2141 _DistanceType;
2142
2143 _DistanceType __len = std::distance(__first, __last);
2144
2145 while (__len > 0)
2146 {
2147 _DistanceType __half = __len >> 1;
2148 _ForwardIterator __middle = __first;
2149 std::advance(__middle, __half);
2150 if (__comp_it_val(__middle, __val))
2151 {
2152 __first = __middle;
2153 ++__first;
2154 __len = __len - __half - 1;
2155 }
2156 else if (__comp_val_it(__val, __middle))
2157 __len = __half;
2158 else
2159 {
2160 _ForwardIterator __left
2161 = std::__lower_bound(__first, __middle, __val, __comp_it_val);
2162 std::advance(__first, __len);
2163 _ForwardIterator __right
2164 = std::__upper_bound(++__middle, __first, __val, __comp_val_it);
2165 return pair<_ForwardIterator, _ForwardIterator>(__left, __right);
2166 }
2167 }
2168 return pair<_ForwardIterator, _ForwardIterator>(__first, __first);
2169 }
2170
2171 /**
2172 * @brief Finds the largest subrange in which @p __val could be inserted
2173 * at any place in it without changing the ordering.
2174 * @ingroup binary_search_algorithms
2175 * @param __first An iterator.
2176 * @param __last Another iterator.
2177 * @param __val The search term.
2178 * @return An pair of iterators defining the subrange.
2179 * @ingroup binary_search_algorithms
2180 *
2181 * This is equivalent to
2182 * @code
2183 * std::make_pair(lower_bound(__first, __last, __val),
2184 * upper_bound(__first, __last, __val))
2185 * @endcode
2186 * but does not actually call those functions.
2187 */
2188 template<typename _ForwardIterator, typename _Tp>
2189 _GLIBCXX20_CONSTEXPR
2190 inline pair<_ForwardIterator, _ForwardIterator>
2191 equal_range(_ForwardIterator __first, _ForwardIterator __last,
2192 const _Tp& __val)
2193 {
2194 // concept requirements
2195 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
2196 __glibcxx_function_requires(_LessThanOpConcept<
2197 typename iterator_traits<_ForwardIterator>::value_type, _Tp>)
2198 __glibcxx_function_requires(_LessThanOpConcept<
2199 _Tp, typename iterator_traits<_ForwardIterator>::value_type>)
2200 __glibcxx_requires_partitioned_lower(__first, __last, __val);
2201 __glibcxx_requires_partitioned_upper(__first, __last, __val);
2202
2203 return std::__equal_range(__first, __last, __val,
2204 __gnu_cxx::__ops::__iter_less_val(),
2205 __gnu_cxx::__ops::__val_less_iter());
2206 }
2207
2208 /**
2209 * @brief Finds the largest subrange in which @p __val could be inserted
2210 * at any place in it without changing the ordering.
2211 * @param __first An iterator.
2212 * @param __last Another iterator.
2213 * @param __val The search term.
2214 * @param __comp A functor to use for comparisons.
2215 * @return An pair of iterators defining the subrange.
2216 * @ingroup binary_search_algorithms
2217 *
2218 * This is equivalent to
2219 * @code
2220 * std::make_pair(lower_bound(__first, __last, __val, __comp),
2221 * upper_bound(__first, __last, __val, __comp))
2222 * @endcode
2223 * but does not actually call those functions.
2224 */
2225 template<typename _ForwardIterator, typename _Tp, typename _Compare>
2226 _GLIBCXX20_CONSTEXPR
2227 inline pair<_ForwardIterator, _ForwardIterator>
2228 equal_range(_ForwardIterator __first, _ForwardIterator __last,
2229 const _Tp& __val, _Compare __comp)
2230 {
2231 // concept requirements
2232 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
2233 __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
2234 typename iterator_traits<_ForwardIterator>::value_type, _Tp>)
2235 __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
2236 _Tp, typename iterator_traits<_ForwardIterator>::value_type>)
2237 __glibcxx_requires_partitioned_lower_pred(__first, __last,
2238 __val, __comp);
2239 __glibcxx_requires_partitioned_upper_pred(__first, __last,
2240 __val, __comp);
2241
2242 return std::__equal_range(__first, __last, __val,
2243 __gnu_cxx::__ops::__iter_comp_val(__comp),
2244 __gnu_cxx::__ops::__val_comp_iter(__comp));
2245 }
2246
2247 /**
2248 * @brief Determines whether an element exists in a range.
2249 * @ingroup binary_search_algorithms
2250 * @param __first An iterator.
2251 * @param __last Another iterator.
2252 * @param __val The search term.
2253 * @return True if @p __val (or its equivalent) is in [@p
2254 * __first,@p __last ].
2255 *
2256 * Note that this does not actually return an iterator to @p __val. For
2257 * that, use std::find or a container's specialized find member functions.
2258 */
2259 template<typename _ForwardIterator, typename _Tp>
2260 _GLIBCXX20_CONSTEXPR
2261 bool
2262 binary_search(_ForwardIterator __first, _ForwardIterator __last,
2263 const _Tp& __val)
2264 {
2265 // concept requirements
2266 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
2267 __glibcxx_function_requires(_LessThanOpConcept<
2268 _Tp, typename iterator_traits<_ForwardIterator>::value_type>)
2269 __glibcxx_requires_partitioned_lower(__first, __last, __val);
2270 __glibcxx_requires_partitioned_upper(__first, __last, __val);
2271
2272 _ForwardIterator __i
2273 = std::__lower_bound(__first, __last, __val,
2274 __gnu_cxx::__ops::__iter_less_val());
2275 return __i != __last && !(__val < *__i);
2276 }
2277
2278 /**
2279 * @brief Determines whether an element exists in a range.
2280 * @ingroup binary_search_algorithms
2281 * @param __first An iterator.
2282 * @param __last Another iterator.
2283 * @param __val The search term.
2284 * @param __comp A functor to use for comparisons.
2285 * @return True if @p __val (or its equivalent) is in @p [__first,__last].
2286 *
2287 * Note that this does not actually return an iterator to @p __val. For
2288 * that, use std::find or a container's specialized find member functions.
2289 *
2290 * The comparison function should have the same effects on ordering as
2291 * the function used for the initial sort.
2292 */
2293 template<typename _ForwardIterator, typename _Tp, typename _Compare>
2294 _GLIBCXX20_CONSTEXPR
2295 bool
2296 binary_search(_ForwardIterator __first, _ForwardIterator __last,
2297 const _Tp& __val, _Compare __comp)
2298 {
2299 // concept requirements
2300 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
2301 __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
2302 _Tp, typename iterator_traits<_ForwardIterator>::value_type>)
2303 __glibcxx_requires_partitioned_lower_pred(__first, __last,
2304 __val, __comp);
2305 __glibcxx_requires_partitioned_upper_pred(__first, __last,
2306 __val, __comp);
2307
2308 _ForwardIterator __i
2309 = std::__lower_bound(__first, __last, __val,
2310 __gnu_cxx::__ops::__iter_comp_val(__comp));
2311 return __i != __last && !bool(__comp(__val, *__i));
2312 }
2313
2314 // merge
2315
2316 /// This is a helper function for the __merge_adaptive routines.
2317 template<typename _InputIterator1, typename _InputIterator2,
2318 typename _OutputIterator, typename _Compare>
2319 void
2320 __move_merge_adaptive(_InputIterator1 __first1, _InputIterator1 __last1,
2321 _InputIterator2 __first2, _InputIterator2 __last2,
2322 _OutputIterator __result, _Compare __comp)
2323 {
2324 while (__first1 != __last1 && __first2 != __last2)
2325 {
2326 if (__comp(__first2, __first1))
2327 {
2328 *__result = _GLIBCXX_MOVE(*__first2)std::move(*__first2);
2329 ++__first2;
2330 }
2331 else
2332 {
2333 *__result = _GLIBCXX_MOVE(*__first1)std::move(*__first1);
2334 ++__first1;
2335 }
2336 ++__result;
2337 }
2338 if (__first1 != __last1)
2339 _GLIBCXX_MOVE3(__first1, __last1, __result)std::move(__first1, __last1, __result);
2340 }
2341
2342 /// This is a helper function for the __merge_adaptive routines.
2343 template<typename _BidirectionalIterator1, typename _BidirectionalIterator2,
2344 typename _BidirectionalIterator3, typename _Compare>
2345 void
2346 __move_merge_adaptive_backward(_BidirectionalIterator1 __first1,
2347 _BidirectionalIterator1 __last1,
2348 _BidirectionalIterator2 __first2,
2349 _BidirectionalIterator2 __last2,
2350 _BidirectionalIterator3 __result,
2351 _Compare __comp)
2352 {
2353 if (__first1 == __last1)
2354 {
2355 _GLIBCXX_MOVE_BACKWARD3(__first2, __last2, __result)std::move_backward(__first2, __last2, __result);
2356 return;
2357 }
2358 else if (__first2 == __last2)
2359 return;
2360
2361 --__last1;
2362 --__last2;
2363 while (true)
2364 {
2365 if (__comp(__last2, __last1))
2366 {
2367 *--__result = _GLIBCXX_MOVE(*__last1)std::move(*__last1);
2368 if (__first1 == __last1)
2369 {
2370 _GLIBCXX_MOVE_BACKWARD3(__first2, ++__last2, __result)std::move_backward(__first2, ++__last2, __result);
2371 return;
2372 }
2373 --__last1;
2374 }
2375 else
2376 {
2377 *--__result = _GLIBCXX_MOVE(*__last2)std::move(*__last2);
2378 if (__first2 == __last2)
2379 return;
2380 --__last2;
2381 }
2382 }
2383 }
2384
2385 /// This is a helper function for the merge routines.
2386 template<typename _BidirectionalIterator1, typename _BidirectionalIterator2,
2387 typename _Distance>
2388 _BidirectionalIterator1
2389 __rotate_adaptive(_BidirectionalIterator1 __first,
2390 _BidirectionalIterator1 __middle,
2391 _BidirectionalIterator1 __last,
2392 _Distance __len1, _Distance __len2,
2393 _BidirectionalIterator2 __buffer,
2394 _Distance __buffer_size)
2395 {
2396 _BidirectionalIterator2 __buffer_end;
2397 if (__len1 > __len2 && __len2 <= __buffer_size)
2398 {
2399 if (__len2)
2400 {
2401 __buffer_end = _GLIBCXX_MOVE3(__middle, __last, __buffer)std::move(__middle, __last, __buffer);
2402 _GLIBCXX_MOVE_BACKWARD3(__first, __middle, __last)std::move_backward(__first, __middle, __last);
2403 return _GLIBCXX_MOVE3(__buffer, __buffer_end, __first)std::move(__buffer, __buffer_end, __first);
2404 }
2405 else
2406 return __first;
2407 }
2408 else if (__len1 <= __buffer_size)
2409 {
2410 if (__len1)
2411 {
2412 __buffer_end = _GLIBCXX_MOVE3(__first, __middle, __buffer)std::move(__first, __middle, __buffer);
2413 _GLIBCXX_MOVE3(__middle, __last, __first)std::move(__middle, __last, __first);
2414 return _GLIBCXX_MOVE_BACKWARD3(__buffer, __buffer_end, __last)std::move_backward(__buffer, __buffer_end, __last);
2415 }
2416 else
2417 return __last;
2418 }
2419 else
2420 return std::rotate(__first, __middle, __last);
2421 }
2422
2423 /// This is a helper function for the merge routines.
2424 template<typename _BidirectionalIterator, typename _Distance,
2425 typename _Pointer, typename _Compare>
2426 void
2427 __merge_adaptive(_BidirectionalIterator __first,
2428 _BidirectionalIterator __middle,
2429 _BidirectionalIterator __last,
2430 _Distance __len1, _Distance __len2,
2431 _Pointer __buffer, _Distance __buffer_size,
2432 _Compare __comp)
2433 {
2434 if (__len1 <= __len2 && __len1 <= __buffer_size)
2435 {
2436 _Pointer __buffer_end = _GLIBCXX_MOVE3(__first, __middle, __buffer)std::move(__first, __middle, __buffer);
2437 std::__move_merge_adaptive(__buffer, __buffer_end, __middle, __last,
2438 __first, __comp);
2439 }
2440 else if (__len2 <= __buffer_size)
2441 {
2442 _Pointer __buffer_end = _GLIBCXX_MOVE3(__middle, __last, __buffer)std::move(__middle, __last, __buffer);
2443 std::__move_merge_adaptive_backward(__first, __middle, __buffer,
2444 __buffer_end, __last, __comp);
2445 }
2446 else
2447 {
2448 _BidirectionalIterator __first_cut = __first;
2449 _BidirectionalIterator __second_cut = __middle;
2450 _Distance __len11 = 0;
2451 _Distance __len22 = 0;
2452 if (__len1 > __len2)
2453 {
2454 __len11 = __len1 / 2;
2455 std::advance(__first_cut, __len11);
2456 __second_cut
2457 = std::__lower_bound(__middle, __last, *__first_cut,
2458 __gnu_cxx::__ops::__iter_comp_val(__comp));
2459 __len22 = std::distance(__middle, __second_cut);
2460 }
2461 else
2462 {
2463 __len22 = __len2 / 2;
2464 std::advance(__second_cut, __len22);
2465 __first_cut
2466 = std::__upper_bound(__first, __middle, *__second_cut,
2467 __gnu_cxx::__ops::__val_comp_iter(__comp));
2468 __len11 = std::distance(__first, __first_cut);
2469 }
2470
2471 _BidirectionalIterator __new_middle
2472 = std::__rotate_adaptive(__first_cut, __middle, __second_cut,
2473 __len1 - __len11, __len22, __buffer,
2474 __buffer_size);
2475 std::__merge_adaptive(__first, __first_cut, __new_middle, __len11,
2476 __len22, __buffer, __buffer_size, __comp);
2477 std::__merge_adaptive(__new_middle, __second_cut, __last,
2478 __len1 - __len11,
2479 __len2 - __len22, __buffer,
2480 __buffer_size, __comp);
2481 }
2482 }
2483
2484 /// This is a helper function for the merge routines.
2485 template<typename _BidirectionalIterator, typename _Distance,
2486 typename _Compare>
2487 void
2488 __merge_without_buffer(_BidirectionalIterator __first,
2489 _BidirectionalIterator __middle,
2490 _BidirectionalIterator __last,
2491 _Distance __len1, _Distance __len2,
2492 _Compare __comp)
2493 {
2494 if (__len1 == 0 || __len2 == 0)
2495 return;
2496
2497 if (__len1 + __len2 == 2)
2498 {
2499 if (__comp(__middle, __first))
2500 std::iter_swap(__first, __middle);
2501 return;
2502 }
2503
2504 _BidirectionalIterator __first_cut = __first;
2505 _BidirectionalIterator __second_cut = __middle;
2506 _Distance __len11 = 0;
2507 _Distance __len22 = 0;
2508 if (__len1 > __len2)
2509 {
2510 __len11 = __len1 / 2;
2511 std::advance(__first_cut, __len11);
2512 __second_cut
2513 = std::__lower_bound(__middle, __last, *__first_cut,
2514 __gnu_cxx::__ops::__iter_comp_val(__comp));
2515 __len22 = std::distance(__middle, __second_cut);
2516 }
2517 else
2518 {
2519 __len22 = __len2 / 2;
2520 std::advance(__second_cut, __len22);
2521 __first_cut
2522 = std::__upper_bound(__first, __middle, *__second_cut,
2523 __gnu_cxx::__ops::__val_comp_iter(__comp));
2524 __len11 = std::distance(__first, __first_cut);
2525 }
2526
2527 _BidirectionalIterator __new_middle
2528 = std::rotate(__first_cut, __middle, __second_cut);
2529 std::__merge_without_buffer(__first, __first_cut, __new_middle,
2530 __len11, __len22, __comp);
2531 std::__merge_without_buffer(__new_middle, __second_cut, __last,
2532 __len1 - __len11, __len2 - __len22, __comp);
2533 }
2534
2535 template<typename _BidirectionalIterator, typename _Compare>
2536 void
2537 __inplace_merge(_BidirectionalIterator __first,
2538 _BidirectionalIterator __middle,
2539 _BidirectionalIterator __last,
2540 _Compare __comp)
2541 {
2542 typedef typename iterator_traits<_BidirectionalIterator>::value_type
2543 _ValueType;
2544 typedef typename iterator_traits<_BidirectionalIterator>::difference_type
2545 _DistanceType;
2546
2547 if (__first == __middle || __middle == __last)
2548 return;
2549
2550 const _DistanceType __len1 = std::distance(__first, __middle);
2551 const _DistanceType __len2 = std::distance(__middle, __last);
2552
2553 typedef _Temporary_buffer<_BidirectionalIterator, _ValueType> _TmpBuf;
2554 _TmpBuf __buf(__first, __len1 + __len2);
2555
2556 if (__buf.begin() == 0)
2557 std::__merge_without_buffer
2558 (__first, __middle, __last, __len1, __len2, __comp);
2559 else
2560 std::__merge_adaptive
2561 (__first, __middle, __last, __len1, __len2, __buf.begin(),
2562 _DistanceType(__buf.size()), __comp);
2563 }
2564
2565 /**
2566 * @brief Merges two sorted ranges in place.
2567 * @ingroup sorting_algorithms
2568 * @param __first An iterator.
2569 * @param __middle Another iterator.
2570 * @param __last Another iterator.
2571 * @return Nothing.
2572 *
2573 * Merges two sorted and consecutive ranges, [__first,__middle) and
2574 * [__middle,__last), and puts the result in [__first,__last). The
2575 * output will be sorted. The sort is @e stable, that is, for
2576 * equivalent elements in the two ranges, elements from the first
2577 * range will always come before elements from the second.
2578 *
2579 * If enough additional memory is available, this takes (__last-__first)-1
2580 * comparisons. Otherwise an NlogN algorithm is used, where N is
2581 * distance(__first,__last).
2582 */
2583 template<typename _BidirectionalIterator>
2584 inline void
2585 inplace_merge(_BidirectionalIterator __first,
2586 _BidirectionalIterator __middle,
2587 _BidirectionalIterator __last)
2588 {
2589 // concept requirements
2590 __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept<
2591 _BidirectionalIterator>)
2592 __glibcxx_function_requires(_LessThanComparableConcept<
2593 typename iterator_traits<_BidirectionalIterator>::value_type>)
2594 __glibcxx_requires_sorted(__first, __middle);
2595 __glibcxx_requires_sorted(__middle, __last);
2596 __glibcxx_requires_irreflexive(__first, __last);
2597
2598 std::__inplace_merge(__first, __middle, __last,
2599 __gnu_cxx::__ops::__iter_less_iter());
2600 }
2601
2602 /**
2603 * @brief Merges two sorted ranges in place.
2604 * @ingroup sorting_algorithms
2605 * @param __first An iterator.
2606 * @param __middle Another iterator.
2607 * @param __last Another iterator.
2608 * @param __comp A functor to use for comparisons.
2609 * @return Nothing.
2610 *
2611 * Merges two sorted and consecutive ranges, [__first,__middle) and
2612 * [middle,last), and puts the result in [__first,__last). The output will
2613 * be sorted. The sort is @e stable, that is, for equivalent
2614 * elements in the two ranges, elements from the first range will always
2615 * come before elements from the second.
2616 *
2617 * If enough additional memory is available, this takes (__last-__first)-1
2618 * comparisons. Otherwise an NlogN algorithm is used, where N is
2619 * distance(__first,__last).
2620 *
2621 * The comparison function should have the same effects on ordering as
2622 * the function used for the initial sort.
2623 */
2624 template<typename _BidirectionalIterator, typename _Compare>
2625 inline void
2626 inplace_merge(_BidirectionalIterator __first,
2627 _BidirectionalIterator __middle,
2628 _BidirectionalIterator __last,
2629 _Compare __comp)
2630 {
2631 // concept requirements
2632 __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept<
2633 _BidirectionalIterator>)
2634 __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
2635 typename iterator_traits<_BidirectionalIterator>::value_type,
2636 typename iterator_traits<_BidirectionalIterator>::value_type>)
2637 __glibcxx_requires_sorted_pred(__first, __middle, __comp);
2638 __glibcxx_requires_sorted_pred(__middle, __last, __comp);
2639 __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
2640
2641 std::__inplace_merge(__first, __middle, __last,
2642 __gnu_cxx::__ops::__iter_comp_iter(__comp));
2643 }
2644
2645
2646 /// This is a helper function for the __merge_sort_loop routines.
2647 template<typename _InputIterator, typename _OutputIterator,
2648 typename _Compare>
2649 _OutputIterator
2650 __move_merge(_InputIterator __first1, _InputIterator __last1,
2651 _InputIterator __first2, _InputIterator __last2,
2652 _OutputIterator __result, _Compare __comp)
2653 {
2654 while (__first1 != __last1 && __first2 != __last2)
2655 {
2656 if (__comp(__first2, __first1))
2657 {
2658 *__result = _GLIBCXX_MOVE(*__first2)std::move(*__first2);
2659 ++__first2;
2660 }
2661 else
2662 {
2663 *__result = _GLIBCXX_MOVE(*__first1)std::move(*__first1);
2664 ++__first1;
2665 }
2666 ++__result;
2667 }
2668 return _GLIBCXX_MOVE3(__first2, __last2,std::move(__first2, __last2, std::move(__first1, __last1, __result
))
2669 _GLIBCXX_MOVE3(__first1, __last1,std::move(__first2, __last2, std::move(__first1, __last1, __result
))
2670 __result))std::move(__first2, __last2, std::move(__first1, __last1, __result
))
;
2671 }
2672
2673 template<typename _RandomAccessIterator1, typename _RandomAccessIterator2,
2674 typename _Distance, typename _Compare>
2675 void
2676 __merge_sort_loop(_RandomAccessIterator1 __first,
2677 _RandomAccessIterator1 __last,
2678 _RandomAccessIterator2 __result, _Distance __step_size,
2679 _Compare __comp)
2680 {
2681 const _Distance __two_step = 2 * __step_size;
2682
2683 while (__last - __first >= __two_step)
2684 {
2685 __result = std::__move_merge(__first, __first + __step_size,
2686 __first + __step_size,
2687 __first + __two_step,
2688 __result, __comp);
2689 __first += __two_step;
2690 }
2691 __step_size = std::min(_Distance(__last - __first), __step_size);
2692
2693 std::__move_merge(__first, __first + __step_size,
2694 __first + __step_size, __last, __result, __comp);
2695 }
2696
2697 template<typename _RandomAccessIterator, typename _Distance,
2698 typename _Compare>
2699 _GLIBCXX20_CONSTEXPR
2700 void
2701 __chunk_insertion_sort(_RandomAccessIterator __first,
2702 _RandomAccessIterator __last,
2703 _Distance __chunk_size, _Compare __comp)
2704 {
2705 while (__last - __first >= __chunk_size)
2706 {
2707 std::__insertion_sort(__first, __first + __chunk_size, __comp);
2708 __first += __chunk_size;
2709 }
2710 std::__insertion_sort(__first, __last, __comp);
2711 }
2712
2713 enum { _S_chunk_size = 7 };
2714
2715 template<typename _RandomAccessIterator, typename _Pointer, typename _Compare>
2716 void
2717 __merge_sort_with_buffer(_RandomAccessIterator __first,
2718 _RandomAccessIterator __last,
2719 _Pointer __buffer, _Compare __comp)
2720 {
2721 typedef typename iterator_traits<_RandomAccessIterator>::difference_type
2722 _Distance;
2723
2724 const _Distance __len = __last - __first;
2725 const _Pointer __buffer_last = __buffer + __len;
2726
2727 _Distance __step_size = _S_chunk_size;
2728 std::__chunk_insertion_sort(__first, __last, __step_size, __comp);
2729
2730 while (__step_size < __len)
2731 {
2732 std::__merge_sort_loop(__first, __last, __buffer,
2733 __step_size, __comp);
2734 __step_size *= 2;
2735 std::__merge_sort_loop(__buffer, __buffer_last, __first,
2736 __step_size, __comp);
2737 __step_size *= 2;
2738 }
2739 }
2740
2741 template<typename _RandomAccessIterator, typename _Pointer,
2742 typename _Distance, typename _Compare>
2743 void
2744 __stable_sort_adaptive(_RandomAccessIterator __first,
2745 _RandomAccessIterator __last,
2746 _Pointer __buffer, _Distance __buffer_size,
2747 _Compare __comp)
2748 {
2749 const _Distance __len = (__last - __first + 1) / 2;
2750 const _RandomAccessIterator __middle = __first + __len;
2751 if (__len > __buffer_size)
2752 {
2753 std::__stable_sort_adaptive(__first, __middle, __buffer,
2754 __buffer_size, __comp);
2755 std::__stable_sort_adaptive(__middle, __last, __buffer,
2756 __buffer_size, __comp);
2757 }
2758 else
2759 {
2760 std::__merge_sort_with_buffer(__first, __middle, __buffer, __comp);
2761 std::__merge_sort_with_buffer(__middle, __last, __buffer, __comp);
2762 }
2763 std::__merge_adaptive(__first, __middle, __last,
2764 _Distance(__middle - __first),
2765 _Distance(__last - __middle),
2766 __buffer, __buffer_size,
2767 __comp);
2768 }
2769
2770 /// This is a helper function for the stable sorting routines.
2771 template<typename _RandomAccessIterator, typename _Compare>
2772 void
2773 __inplace_stable_sort(_RandomAccessIterator __first,
2774 _RandomAccessIterator __last, _Compare __comp)
2775 {
2776 if (__last - __first < 15)
2777 {
2778 std::__insertion_sort(__first, __last, __comp);
2779 return;
2780 }
2781 _RandomAccessIterator __middle = __first + (__last - __first) / 2;
2782 std::__inplace_stable_sort(__first, __middle, __comp);
2783 std::__inplace_stable_sort(__middle, __last, __comp);
2784 std::__merge_without_buffer(__first, __middle, __last,
2785 __middle - __first,
2786 __last - __middle,
2787 __comp);
2788 }
2789
2790 // stable_sort
2791
2792 // Set algorithms: includes, set_union, set_intersection, set_difference,
2793 // set_symmetric_difference. All of these algorithms have the precondition
2794 // that their input ranges are sorted and the postcondition that their output
2795 // ranges are sorted.
2796
2797 template<typename _InputIterator1, typename _InputIterator2,
2798 typename _Compare>
2799 _GLIBCXX20_CONSTEXPR
2800 bool
2801 __includes(_InputIterator1 __first1, _InputIterator1 __last1,
2802 _InputIterator2 __first2, _InputIterator2 __last2,
2803 _Compare __comp)
2804 {
2805 while (__first1 != __last1 && __first2 != __last2)
2806 if (__comp(__first2, __first1))
2807 return false;
2808 else if (__comp(__first1, __first2))
2809 ++__first1;
2810 else
2811 {
2812 ++__first1;
2813 ++__first2;
2814 }
2815
2816 return __first2 == __last2;
2817 }
2818
2819 /**
2820 * @brief Determines whether all elements of a sequence exists in a range.
2821 * @param __first1 Start of search range.
2822 * @param __last1 End of search range.
2823 * @param __first2 Start of sequence
2824 * @param __last2 End of sequence.
2825 * @return True if each element in [__first2,__last2) is contained in order
2826 * within [__first1,__last1). False otherwise.
2827 * @ingroup set_algorithms
2828 *
2829 * This operation expects both [__first1,__last1) and
2830 * [__first2,__last2) to be sorted. Searches for the presence of
2831 * each element in [__first2,__last2) within [__first1,__last1).
2832 * The iterators over each range only move forward, so this is a
2833 * linear algorithm. If an element in [__first2,__last2) is not
2834 * found before the search iterator reaches @p __last2, false is
2835 * returned.
2836 */
2837 template<typename _InputIterator1, typename _InputIterator2>
2838 _GLIBCXX20_CONSTEXPR
2839 inline bool
2840 includes(_InputIterator1 __first1, _InputIterator1 __last1,
2841 _InputIterator2 __first2, _InputIterator2 __last2)
2842 {
2843 // concept requirements
2844 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
2845 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
2846 __glibcxx_function_requires(_LessThanOpConcept<
2847 typename iterator_traits<_InputIterator1>::value_type,
2848 typename iterator_traits<_InputIterator2>::value_type>)
2849 __glibcxx_function_requires(_LessThanOpConcept<
2850 typename iterator_traits<_InputIterator2>::value_type,
2851 typename iterator_traits<_InputIterator1>::value_type>)
2852 __glibcxx_requires_sorted_set(__first1, __last1, __first2);
2853 __glibcxx_requires_sorted_set(__first2, __last2, __first1);
2854 __glibcxx_requires_irreflexive2(__first1, __last1);
2855 __glibcxx_requires_irreflexive2(__first2, __last2);
2856
2857 return std::__includes(__first1, __last1, __first2, __last2,
2858 __gnu_cxx::__ops::__iter_less_iter());
2859 }
2860
2861 /**
2862 * @brief Determines whether all elements of a sequence exists in a range
2863 * using comparison.
2864 * @ingroup set_algorithms
2865 * @param __first1 Start of search range.
2866 * @param __last1 End of search range.
2867 * @param __first2 Start of sequence
2868 * @param __last2 End of sequence.
2869 * @param __comp Comparison function to use.
2870 * @return True if each element in [__first2,__last2) is contained
2871 * in order within [__first1,__last1) according to comp. False
2872 * otherwise. @ingroup set_algorithms
2873 *
2874 * This operation expects both [__first1,__last1) and
2875 * [__first2,__last2) to be sorted. Searches for the presence of
2876 * each element in [__first2,__last2) within [__first1,__last1),
2877 * using comp to decide. The iterators over each range only move
2878 * forward, so this is a linear algorithm. If an element in
2879 * [__first2,__last2) is not found before the search iterator
2880 * reaches @p __last2, false is returned.
2881 */
2882 template<typename _InputIterator1, typename _InputIterator2,
2883 typename _Compare>
2884 _GLIBCXX20_CONSTEXPR
2885 inline bool
2886 includes(_InputIterator1 __first1, _InputIterator1 __last1,
2887 _InputIterator2 __first2, _InputIterator2 __last2,
2888 _Compare __comp)
2889 {
2890 // concept requirements
2891 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
2892 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
2893 __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
2894 typename iterator_traits<_InputIterator1>::value_type,
2895 typename iterator_traits<_InputIterator2>::value_type>)
2896 __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
2897 typename iterator_traits<_InputIterator2>::value_type,
2898 typename iterator_traits<_InputIterator1>::value_type>)
2899 __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp);
2900 __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp);
2901 __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp);
2902 __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp);
2903
2904 return std::__includes(__first1, __last1, __first2, __last2,
2905 __gnu_cxx::__ops::__iter_comp_iter(__comp));
2906 }
2907
2908 // nth_element
2909 // merge
2910 // set_difference
2911 // set_intersection
2912 // set_union
2913 // stable_sort
2914 // set_symmetric_difference
2915 // min_element
2916 // max_element
2917
2918 template<typename _BidirectionalIterator, typename _Compare>
2919 _GLIBCXX20_CONSTEXPR
2920 bool
2921 __next_permutation(_BidirectionalIterator __first,
2922 _BidirectionalIterator __last, _Compare __comp)
2923 {
2924 if (__first == __last)
2925 return false;
2926 _BidirectionalIterator __i = __first;
2927 ++__i;
2928 if (__i == __last)
2929 return false;
2930 __i = __last;
2931 --__i;
2932
2933 for(;;)
2934 {
2935 _BidirectionalIterator __ii = __i;
2936 --__i;
2937 if (__comp(__i, __ii))
2938 {
2939 _BidirectionalIterator __j = __last;
2940 while (!__comp(__i, --__j))
2941 {}
2942 std::iter_swap(__i, __j);
2943 std::__reverse(__ii, __last,
2944 std::__iterator_category(__first));
2945 return true;
2946 }
2947 if (__i == __first)
2948 {
2949 std::__reverse(__first, __last,
2950 std::__iterator_category(__first));
2951 return false;
2952 }
2953 }
2954 }
2955
2956 /**
2957 * @brief Permute range into the next @e dictionary ordering.
2958 * @ingroup sorting_algorithms
2959 * @param __first Start of range.
2960 * @param __last End of range.
2961 * @return False if wrapped to first permutation, true otherwise.
2962 *
2963 * Treats all permutations of the range as a set of @e dictionary sorted
2964 * sequences. Permutes the current sequence into the next one of this set.
2965 * Returns true if there are more sequences to generate. If the sequence
2966 * is the largest of the set, the smallest is generated and false returned.
2967 */
2968 template<typename _BidirectionalIterator>
2969 _GLIBCXX20_CONSTEXPR
2970 inline bool
2971 next_permutation(_BidirectionalIterator __first,
2972 _BidirectionalIterator __last)
2973 {
2974 // concept requirements
2975 __glibcxx_function_requires(_BidirectionalIteratorConcept<
2976 _BidirectionalIterator>)
2977 __glibcxx_function_requires(_LessThanComparableConcept<
2978 typename iterator_traits<_BidirectionalIterator>::value_type>)
2979 __glibcxx_requires_valid_range(__first, __last);
2980 __glibcxx_requires_irreflexive(__first, __last);
2981
2982 return std::__next_permutation
2983 (__first, __last, __gnu_cxx::__ops::__iter_less_iter());
2984 }
2985
2986 /**
2987 * @brief Permute range into the next @e dictionary ordering using
2988 * comparison functor.
2989 * @ingroup sorting_algorithms
2990 * @param __first Start of range.
2991 * @param __last End of range.
2992 * @param __comp A comparison functor.
2993 * @return False if wrapped to first permutation, true otherwise.
2994 *
2995 * Treats all permutations of the range [__first,__last) as a set of
2996 * @e dictionary sorted sequences ordered by @p __comp. Permutes the current
2997 * sequence into the next one of this set. Returns true if there are more
2998 * sequences to generate. If the sequence is the largest of the set, the
2999 * smallest is generated and false returned.
3000 */
3001 template<typename _BidirectionalIterator, typename _Compare>
3002 _GLIBCXX20_CONSTEXPR
3003 inline bool
3004 next_permutation(_BidirectionalIterator __first,
3005 _BidirectionalIterator __last, _Compare __comp)
3006 {
3007 // concept requirements
3008 __glibcxx_function_requires(_BidirectionalIteratorConcept<
3009 _BidirectionalIterator>)
3010 __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
3011 typename iterator_traits<_BidirectionalIterator>::value_type,
3012 typename iterator_traits<_BidirectionalIterator>::value_type>)
3013 __glibcxx_requires_valid_range(__first, __last);
3014 __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
3015
3016 return std::__next_permutation
3017 (__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__comp));
3018 }
3019
3020 template<typename _BidirectionalIterator, typename _Compare>
3021 _GLIBCXX20_CONSTEXPR
3022 bool
3023 __prev_permutation(_BidirectionalIterator __first,
3024 _BidirectionalIterator __last, _Compare __comp)
3025 {
3026 if (__first == __last)
3027 return false;
3028 _BidirectionalIterator __i = __first;
3029 ++__i;
3030 if (__i == __last)
3031 return false;
3032 __i = __last;
3033 --__i;
3034
3035 for(;;)
3036 {
3037 _BidirectionalIterator __ii = __i;
3038 --__i;
3039 if (__comp(__ii, __i))
3040 {
3041 _BidirectionalIterator __j = __last;
3042 while (!__comp(--__j, __i))
3043 {}
3044 std::iter_swap(__i, __j);
3045 std::__reverse(__ii, __last,
3046 std::__iterator_category(__first));
3047 return true;
3048 }
3049 if (__i == __first)
3050 {
3051 std::__reverse(__first, __last,
3052 std::__iterator_category(__first));
3053 return false;
3054 }
3055 }
3056 }
3057
3058 /**
3059 * @brief Permute range into the previous @e dictionary ordering.
3060 * @ingroup sorting_algorithms
3061 * @param __first Start of range.
3062 * @param __last End of range.
3063 * @return False if wrapped to last permutation, true otherwise.
3064 *
3065 * Treats all permutations of the range as a set of @e dictionary sorted
3066 * sequences. Permutes the current sequence into the previous one of this
3067 * set. Returns true if there are more sequences to generate. If the
3068 * sequence is the smallest of the set, the largest is generated and false
3069 * returned.
3070 */
3071 template<typename _BidirectionalIterator>
3072 _GLIBCXX20_CONSTEXPR
3073 inline bool
3074 prev_permutation(_BidirectionalIterator __first,
3075 _BidirectionalIterator __last)
3076 {
3077 // concept requirements
3078 __glibcxx_function_requires(_BidirectionalIteratorConcept<
3079 _BidirectionalIterator>)
3080 __glibcxx_function_requires(_LessThanComparableConcept<
3081 typename iterator_traits<_BidirectionalIterator>::value_type>)
3082 __glibcxx_requires_valid_range(__first, __last);
3083 __glibcxx_requires_irreflexive(__first, __last);
3084
3085 return std::__prev_permutation(__first, __last,
3086 __gnu_cxx::__ops::__iter_less_iter());
3087 }
3088
3089 /**
3090 * @brief Permute range into the previous @e dictionary ordering using
3091 * comparison functor.
3092 * @ingroup sorting_algorithms
3093 * @param __first Start of range.
3094 * @param __last End of range.
3095 * @param __comp A comparison functor.
3096 * @return False if wrapped to last permutation, true otherwise.
3097 *
3098 * Treats all permutations of the range [__first,__last) as a set of
3099 * @e dictionary sorted sequences ordered by @p __comp. Permutes the current
3100 * sequence into the previous one of this set. Returns true if there are
3101 * more sequences to generate. If the sequence is the smallest of the set,
3102 * the largest is generated and false returned.
3103 */
3104 template<typename _BidirectionalIterator, typename _Compare>
3105 _GLIBCXX20_CONSTEXPR
3106 inline bool
3107 prev_permutation(_BidirectionalIterator __first,
3108 _BidirectionalIterator __last, _Compare __comp)
3109 {
3110 // concept requirements
3111 __glibcxx_function_requires(_BidirectionalIteratorConcept<
3112 _BidirectionalIterator>)
3113 __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
3114 typename iterator_traits<_BidirectionalIterator>::value_type,
3115 typename iterator_traits<_BidirectionalIterator>::value_type>)
3116 __glibcxx_requires_valid_range(__first, __last);
3117 __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
3118
3119 return std::__prev_permutation(__first, __last,
3120 __gnu_cxx::__ops::__iter_comp_iter(__comp));
3121 }
3122
3123 // replace
3124 // replace_if
3125
3126 template<typename _InputIterator, typename _OutputIterator,
3127 typename _Predicate, typename _Tp>
3128 _GLIBCXX20_CONSTEXPR
3129 _OutputIterator
3130 __replace_copy_if(_InputIterator __first, _InputIterator __last,
3131 _OutputIterator __result,
3132 _Predicate __pred, const _Tp& __new_value)
3133 {
3134 for (; __first != __last; ++__first, (void)++__result)
3135 if (__pred(__first))
3136 *__result = __new_value;
3137 else
3138 *__result = *__first;
3139 return __result;
3140 }
3141
3142 /**
3143 * @brief Copy a sequence, replacing each element of one value with another
3144 * value.
3145 * @param __first An input iterator.
3146 * @param __last An input iterator.
3147 * @param __result An output iterator.
3148 * @param __old_value The value to be replaced.
3149 * @param __new_value The replacement value.
3150 * @return The end of the output sequence, @p result+(last-first).
3151 *
3152 * Copies each element in the input range @p [__first,__last) to the
3153 * output range @p [__result,__result+(__last-__first)) replacing elements
3154 * equal to @p __old_value with @p __new_value.
3155 */
3156 template<typename _InputIterator, typename _OutputIterator, typename _Tp>
3157 _GLIBCXX20_CONSTEXPR
3158 inline _OutputIterator
3159 replace_copy(_InputIterator __first, _InputIterator __last,
3160 _OutputIterator __result,
3161 const _Tp& __old_value, const _Tp& __new_value)
3162 {
3163 // concept requirements
3164 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
3165 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
3166 typename iterator_traits<_InputIterator>::value_type>)
3167 __glibcxx_function_requires(_EqualOpConcept<
3168 typename iterator_traits<_InputIterator>::value_type, _Tp>)
3169 __glibcxx_requires_valid_range(__first, __last);
3170
3171 return std::__replace_copy_if(__first, __last, __result,
3172 __gnu_cxx::__ops::__iter_equals_val(__old_value),
3173 __new_value);
3174 }
3175
3176 /**
3177 * @brief Copy a sequence, replacing each value for which a predicate
3178 * returns true with another value.
3179 * @ingroup mutating_algorithms
3180 * @param __first An input iterator.
3181 * @param __last An input iterator.
3182 * @param __result An output iterator.
3183 * @param __pred A predicate.
3184 * @param __new_value The replacement value.
3185 * @return The end of the output sequence, @p __result+(__last-__first).
3186 *
3187 * Copies each element in the range @p [__first,__last) to the range
3188 * @p [__result,__result+(__last-__first)) replacing elements for which
3189 * @p __pred returns true with @p __new_value.
3190 */
3191 template<typename _InputIterator, typename _OutputIterator,
3192 typename _Predicate, typename _Tp>
3193 _GLIBCXX20_CONSTEXPR
3194 inline _OutputIterator
3195 replace_copy_if(_InputIterator __first, _InputIterator __last,
3196 _OutputIterator __result,
3197 _Predicate __pred, const _Tp& __new_value)
3198 {
3199 // concept requirements
3200 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
3201 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
3202 typename iterator_traits<_InputIterator>::value_type>)
3203 __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
3204 typename iterator_traits<_InputIterator>::value_type>)
3205 __glibcxx_requires_valid_range(__first, __last);
3206
3207 return std::__replace_copy_if(__first, __last, __result,
3208 __gnu_cxx::__ops::__pred_iter(__pred),
3209 __new_value);
3210 }
3211
3212#if __cplusplus201402L >= 201103L
3213 /**
3214 * @brief Determines whether the elements of a sequence are sorted.
3215 * @ingroup sorting_algorithms
3216 * @param __first An iterator.
3217 * @param __last Another iterator.
3218 * @return True if the elements are sorted, false otherwise.
3219 */
3220 template<typename _ForwardIterator>
3221 _GLIBCXX20_CONSTEXPR
3222 inline bool
3223 is_sorted(_ForwardIterator __first, _ForwardIterator __last)
3224 { return std::is_sorted_until(__first, __last) == __last; }
3225
3226 /**
3227 * @brief Determines whether the elements of a sequence are sorted
3228 * according to a comparison functor.
3229 * @ingroup sorting_algorithms
3230 * @param __first An iterator.
3231 * @param __last Another iterator.
3232 * @param __comp A comparison functor.
3233 * @return True if the elements are sorted, false otherwise.
3234 */
3235 template<typename _ForwardIterator, typename _Compare>
3236 _GLIBCXX20_CONSTEXPR
3237 inline bool
3238 is_sorted(_ForwardIterator __first, _ForwardIterator __last,
3239 _Compare __comp)
3240 { return std::is_sorted_until(__first, __last, __comp) == __last; }
3241
3242 template<typename _ForwardIterator, typename _Compare>
3243 _GLIBCXX20_CONSTEXPR
3244 _ForwardIterator
3245 __is_sorted_until(_ForwardIterator __first, _ForwardIterator __last,
3246 _Compare __comp)
3247 {
3248 if (__first == __last)
3249 return __last;
3250
3251 _ForwardIterator __next = __first;
3252 for (++__next; __next != __last; __first = __next, (void)++__next)
3253 if (__comp(__next, __first))
3254 return __next;
3255 return __next;
3256 }
3257
3258 /**
3259 * @brief Determines the end of a sorted sequence.
3260 * @ingroup sorting_algorithms
3261 * @param __first An iterator.
3262 * @param __last Another iterator.
3263 * @return An iterator pointing to the last iterator i in [__first, __last)
3264 * for which the range [__first, i) is sorted.
3265 */
3266 template<typename _ForwardIterator>
3267 _GLIBCXX20_CONSTEXPR
3268 inline _ForwardIterator
3269 is_sorted_until(_ForwardIterator __first, _ForwardIterator __last)
3270 {
3271 // concept requirements
3272 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
3273 __glibcxx_function_requires(_LessThanComparableConcept<
3274 typename iterator_traits<_ForwardIterator>::value_type>)
3275 __glibcxx_requires_valid_range(__first, __last);
3276 __glibcxx_requires_irreflexive(__first, __last);
3277
3278 return std::__is_sorted_until(__first, __last,
3279 __gnu_cxx::__ops::__iter_less_iter());
3280 }
3281
3282 /**
3283 * @brief Determines the end of a sorted sequence using comparison functor.
3284 * @ingroup sorting_algorithms
3285 * @param __first An iterator.
3286 * @param __last Another iterator.
3287 * @param __comp A comparison functor.
3288 * @return An iterator pointing to the last iterator i in [__first, __last)
3289 * for which the range [__first, i) is sorted.
3290 */
3291 template<typename _ForwardIterator, typename _Compare>
3292 _GLIBCXX20_CONSTEXPR
3293 inline _ForwardIterator
3294 is_sorted_until(_ForwardIterator __first, _ForwardIterator __last,
3295 _Compare __comp)
3296 {
3297 // concept requirements
3298 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
3299 __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
3300 typename iterator_traits<_ForwardIterator>::value_type,
3301 typename iterator_traits<_ForwardIterator>::value_type>)
3302 __glibcxx_requires_valid_range(__first, __last);
3303 __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
3304
3305 return std::__is_sorted_until(__first, __last,
3306 __gnu_cxx::__ops::__iter_comp_iter(__comp));
3307 }
3308
3309 /**
3310 * @brief Determines min and max at once as an ordered pair.
3311 * @ingroup sorting_algorithms
3312 * @param __a A thing of arbitrary type.
3313 * @param __b Another thing of arbitrary type.
3314 * @return A pair(__b, __a) if __b is smaller than __a, pair(__a,
3315 * __b) otherwise.
3316 */
3317 template<typename _Tp>
3318 _GLIBCXX14_CONSTEXPRconstexpr
3319 inline pair<const _Tp&, const _Tp&>
3320 minmax(const _Tp& __a, const _Tp& __b)
3321 {
3322 // concept requirements
3323 __glibcxx_function_requires(_LessThanComparableConcept<_Tp>)
3324
3325 return __b < __a ? pair<const _Tp&, const _Tp&>(__b, __a)
3326 : pair<const _Tp&, const _Tp&>(__a, __b);
3327 }
3328
3329 /**
3330 * @brief Determines min and max at once as an ordered pair.
3331 * @ingroup sorting_algorithms
3332 * @param __a A thing of arbitrary type.
3333 * @param __b Another thing of arbitrary type.
3334 * @param __comp A @link comparison_functors comparison functor @endlink.
3335 * @return A pair(__b, __a) if __b is smaller than __a, pair(__a,
3336 * __b) otherwise.
3337 */
3338 template<typename _Tp, typename _Compare>
3339 _GLIBCXX14_CONSTEXPRconstexpr
3340 inline pair<const _Tp&, const _Tp&>
3341 minmax(const _Tp& __a, const _Tp& __b, _Compare __comp)
3342 {
3343 return __comp(__b, __a) ? pair<const _Tp&, const _Tp&>(__b, __a)
3344 : pair<const _Tp&, const _Tp&>(__a, __b);
3345 }
3346
3347 template<typename _ForwardIterator, typename _Compare>
3348 _GLIBCXX14_CONSTEXPRconstexpr
3349 pair<_ForwardIterator, _ForwardIterator>
3350 __minmax_element(_ForwardIterator __first, _ForwardIterator __last,
3351 _Compare __comp)
3352 {
3353 _ForwardIterator __next = __first;
3354 if (__first == __last
3355 || ++__next == __last)
3356 return std::make_pair(__first, __first);
3357
3358 _ForwardIterator __min{}, __max{};
3359 if (__comp(__next, __first))
3360 {
3361 __min = __next;
3362 __max = __first;
3363 }
3364 else
3365 {
3366 __min = __first;
3367 __max = __next;
3368 }
3369
3370 __first = __next;
3371 ++__first;
3372
3373 while (__first != __last)
3374 {
3375 __next = __first;
3376 if (++__next == __last)
3377 {
3378 if (__comp(__first, __min))
3379 __min = __first;
3380 else if (!__comp(__first, __max))
3381 __max = __first;
3382 break;
3383 }
3384
3385 if (__comp(__next, __first))
3386 {
3387 if (__comp(__next, __min))
3388 __min = __next;
3389 if (!__comp(__first, __max))
3390 __max = __first;
3391 }
3392 else
3393 {
3394 if (__comp(__first, __min))
3395 __min = __first;
3396 if (!__comp(__next, __max))
3397 __max = __next;
3398 }
3399
3400 __first = __next;
3401 ++__first;
3402 }
3403
3404 return std::make_pair(__min, __max);
3405 }
3406
3407 /**
3408 * @brief Return a pair of iterators pointing to the minimum and maximum
3409 * elements in a range.
3410 * @ingroup sorting_algorithms
3411 * @param __first Start of range.
3412 * @param __last End of range.
3413 * @return make_pair(m, M), where m is the first iterator i in
3414 * [__first, __last) such that no other element in the range is
3415 * smaller, and where M is the last iterator i in [__first, __last)
3416 * such that no other element in the range is larger.
3417 */
3418 template<typename _ForwardIterator>
3419 _GLIBCXX14_CONSTEXPRconstexpr
3420 inline pair<_ForwardIterator, _ForwardIterator>
3421 minmax_element(_ForwardIterator __first, _ForwardIterator __last)
3422 {
3423 // concept requirements
3424 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
3425 __glibcxx_function_requires(_LessThanComparableConcept<
3426 typename iterator_traits<_ForwardIterator>::value_type>)
3427 __glibcxx_requires_valid_range(__first, __last);
3428 __glibcxx_requires_irreflexive(__first, __last);
3429
3430 return std::__minmax_element(__first, __last,
3431 __gnu_cxx::__ops::__iter_less_iter());
3432 }
3433
3434 /**
3435 * @brief Return a pair of iterators pointing to the minimum and maximum
3436 * elements in a range.
3437 * @ingroup sorting_algorithms
3438 * @param __first Start of range.
3439 * @param __last End of range.
3440 * @param __comp Comparison functor.
3441 * @return make_pair(m, M), where m is the first iterator i in
3442 * [__first, __last) such that no other element in the range is
3443 * smaller, and where M is the last iterator i in [__first, __last)
3444 * such that no other element in the range is larger.
3445 */
3446 template<typename _ForwardIterator, typename _Compare>
3447 _GLIBCXX14_CONSTEXPRconstexpr
3448 inline pair<_ForwardIterator, _ForwardIterator>
3449 minmax_element(_ForwardIterator __first, _ForwardIterator __last,
3450 _Compare __comp)
3451 {
3452 // concept requirements
3453 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
3454 __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
3455 typename iterator_traits<_ForwardIterator>::value_type,
3456 typename iterator_traits<_ForwardIterator>::value_type>)
3457 __glibcxx_requires_valid_range(__first, __last);
3458 __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
3459
3460 return std::__minmax_element(__first, __last,
3461 __gnu_cxx::__ops::__iter_comp_iter(__comp));
3462 }
3463
3464 // N2722 + DR 915.
3465 template<typename _Tp>
3466 _GLIBCXX14_CONSTEXPRconstexpr
3467 inline _Tp
3468 min(initializer_list<_Tp> __l)
3469 { return *std::min_element(__l.begin(), __l.end()); }
3470
3471 template<typename _Tp, typename _Compare>
3472 _GLIBCXX14_CONSTEXPRconstexpr
3473 inline _Tp
3474 min(initializer_list<_Tp> __l, _Compare __comp)
3475 { return *std::min_element(__l.begin(), __l.end(), __comp); }
3476
3477 template<typename _Tp>
3478 _GLIBCXX14_CONSTEXPRconstexpr
3479 inline _Tp
3480 max(initializer_list<_Tp> __l)
3481 { return *std::max_element(__l.begin(), __l.end()); }
3482
3483 template<typename _Tp, typename _Compare>
3484 _GLIBCXX14_CONSTEXPRconstexpr
3485 inline _Tp
3486 max(initializer_list<_Tp> __l, _Compare __comp)
3487 { return *std::max_element(__l.begin(), __l.end(), __comp); }
3488
3489 template<typename _Tp>
3490 _GLIBCXX14_CONSTEXPRconstexpr
3491 inline pair<_Tp, _Tp>
3492 minmax(initializer_list<_Tp> __l)
3493 {
3494 pair<const _Tp*, const _Tp*> __p =
3495 std::minmax_element(__l.begin(), __l.end());
3496 return std::make_pair(*__p.first, *__p.second);
3497 }
3498
3499 template<typename _Tp, typename _Compare>
3500 _GLIBCXX14_CONSTEXPRconstexpr
3501 inline pair<_Tp, _Tp>
3502 minmax(initializer_list<_Tp> __l, _Compare __comp)
3503 {
3504 pair<const _Tp*, const _Tp*> __p =
3505 std::minmax_element(__l.begin(), __l.end(), __comp);
3506 return std::make_pair(*__p.first, *__p.second);
3507 }
3508
3509 /**
3510 * @brief Checks whether a permutation of the second sequence is equal
3511 * to the first sequence.
3512 * @ingroup non_mutating_algorithms
3513 * @param __first1 Start of first range.
3514 * @param __last1 End of first range.
3515 * @param __first2 Start of second range.
3516 * @param __pred A binary predicate.
3517 * @return true if there exists a permutation of the elements in
3518 * the range [__first2, __first2 + (__last1 - __first1)),
3519 * beginning with ForwardIterator2 begin, such that
3520 * equal(__first1, __last1, __begin, __pred) returns true;
3521 * otherwise, returns false.
3522 */
3523 template<typename _ForwardIterator1, typename _ForwardIterator2,
3524 typename _BinaryPredicate>
3525 _GLIBCXX20_CONSTEXPR
3526 inline bool
3527 is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
3528 _ForwardIterator2 __first2, _BinaryPredicate __pred)
3529 {
3530 // concept requirements
3531 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>)
3532 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>)
3533 __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate,
3534 typename iterator_traits<_ForwardIterator1>::value_type,
3535 typename iterator_traits<_ForwardIterator2>::value_type>)
3536 __glibcxx_requires_valid_range(__first1, __last1);
3537
3538 return std::__is_permutation(__first1, __last1, __first2,
3539 __gnu_cxx::__ops::__iter_comp_iter(__pred));
3540 }
3541
3542#if __cplusplus201402L > 201103L
3543 template<typename _ForwardIterator1, typename _ForwardIterator2,
3544 typename _BinaryPredicate>
3545 _GLIBCXX20_CONSTEXPR
3546 bool
3547 __is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
3548 _ForwardIterator2 __first2, _ForwardIterator2 __last2,
3549 _BinaryPredicate __pred)
3550 {
3551 using _Cat1
3552 = typename iterator_traits<_ForwardIterator1>::iterator_category;
3553 using _Cat2
3554 = typename iterator_traits<_ForwardIterator2>::iterator_category;
3555 using _It1_is_RA = is_same<_Cat1, random_access_iterator_tag>;
3556 using _It2_is_RA = is_same<_Cat2, random_access_iterator_tag>;
3557 constexpr bool __ra_iters = _It1_is_RA() && _It2_is_RA();
3558 if (__ra_iters)
3559 {
3560 auto __d1 = std::distance(__first1, __last1);
3561 auto __d2 = std::distance(__first2, __last2);
3562 if (__d1 != __d2)
3563 return false;
3564 }
3565
3566 // Efficiently compare identical prefixes: O(N) if sequences
3567 // have the same elements in the same order.
3568 for (; __first1 != __last1 && __first2 != __last2;
3569 ++__first1, (void)++__first2)
3570 if (!__pred(__first1, __first2))
3571 break;
3572
3573 if (__ra_iters)
3574 {
3575 if (__first1 == __last1)
3576 return true;
3577 }
3578 else
3579 {
3580 auto __d1 = std::distance(__first1, __last1);
3581 auto __d2 = std::distance(__first2, __last2);
3582 if (__d1 == 0 && __d2 == 0)
3583 return true;
3584 if (__d1 != __d2)
3585 return false;
3586 }
3587
3588 for (_ForwardIterator1 __scan = __first1; __scan != __last1; ++__scan)
3589 {
3590 if (__scan != std::__find_if(__first1, __scan,
3591 __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan)))
3592 continue; // We've seen this one before.
3593
3594 auto __matches = std::__count_if(__first2, __last2,
3595 __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan));
3596 if (0 == __matches
3597 || std::__count_if(__scan, __last1,
3598 __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan))
3599 != __matches)
3600 return false;
3601 }
3602 return true;
3603 }
3604
3605 /**
3606 * @brief Checks whether a permutaion of the second sequence is equal
3607 * to the first sequence.
3608 * @ingroup non_mutating_algorithms
3609 * @param __first1 Start of first range.
3610 * @param __last1 End of first range.
3611 * @param __first2 Start of second range.
3612 * @param __last2 End of first range.
3613 * @return true if there exists a permutation of the elements in the range
3614 * [__first2, __last2), beginning with ForwardIterator2 begin,
3615 * such that equal(__first1, __last1, begin) returns true;
3616 * otherwise, returns false.
3617 */
3618 template<typename _ForwardIterator1, typename _ForwardIterator2>
3619 _GLIBCXX20_CONSTEXPR
3620 inline bool
3621 is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
3622 _ForwardIterator2 __first2, _ForwardIterator2 __last2)
3623 {
3624 __glibcxx_requires_valid_range(__first1, __last1);
3625 __glibcxx_requires_valid_range(__first2, __last2);
3626
3627 return
3628 std::__is_permutation(__first1, __last1, __first2, __last2,
3629 __gnu_cxx::__ops::__iter_equal_to_iter());
3630 }
3631
3632 /**
3633 * @brief Checks whether a permutation of the second sequence is equal
3634 * to the first sequence.
3635 * @ingroup non_mutating_algorithms
3636 * @param __first1 Start of first range.
3637 * @param __last1 End of first range.
3638 * @param __first2 Start of second range.
3639 * @param __last2 End of first range.
3640 * @param __pred A binary predicate.
3641 * @return true if there exists a permutation of the elements in the range
3642 * [__first2, __last2), beginning with ForwardIterator2 begin,
3643 * such that equal(__first1, __last1, __begin, __pred) returns true;
3644 * otherwise, returns false.
3645 */
3646 template<typename _ForwardIterator1, typename _ForwardIterator2,
3647 typename _BinaryPredicate>
3648 _GLIBCXX20_CONSTEXPR
3649 inline bool
3650 is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
3651 _ForwardIterator2 __first2, _ForwardIterator2 __last2,
3652 _BinaryPredicate __pred)
3653 {
3654 __glibcxx_requires_valid_range(__first1, __last1);
3655 __glibcxx_requires_valid_range(__first2, __last2);
3656
3657 return std::__is_permutation(__first1, __last1, __first2, __last2,
3658 __gnu_cxx::__ops::__iter_comp_iter(__pred));
3659 }
3660
3661#if __cplusplus201402L > 201402L
3662
3663#define __cpp_lib_clamp 201603
3664
3665 /**
3666 * @brief Returns the value clamped between lo and hi.
3667 * @ingroup sorting_algorithms
3668 * @param __val A value of arbitrary type.
3669 * @param __lo A lower limit of arbitrary type.
3670 * @param __hi An upper limit of arbitrary type.
3671 * @return max(__val, __lo) if __val < __hi or min(__val, __hi) otherwise.
3672 */
3673 template<typename _Tp>
3674 constexpr const _Tp&
3675 clamp(const _Tp& __val, const _Tp& __lo, const _Tp& __hi)
3676 {
3677 __glibcxx_assert(!(__hi < __lo));
3678 return (__val < __lo) ? __lo : (__hi < __val) ? __hi : __val;
3679 }
3680
3681 /**
3682 * @brief Returns the value clamped between lo and hi.
3683 * @ingroup sorting_algorithms
3684 * @param __val A value of arbitrary type.
3685 * @param __lo A lower limit of arbitrary type.
3686 * @param __hi An upper limit of arbitrary type.
3687 * @param __comp A comparison functor.
3688 * @return max(__val, __lo, __comp) if __comp(__val, __hi)
3689 * or min(__val, __hi, __comp) otherwise.
3690 */
3691 template<typename _Tp, typename _Compare>
3692 constexpr const _Tp&
3693 clamp(const _Tp& __val, const _Tp& __lo, const _Tp& __hi, _Compare __comp)
3694 {
3695 __glibcxx_assert(!__comp(__hi, __lo));
3696 return __comp(__val, __lo) ? __lo : __comp(__hi, __val) ? __hi : __val;
3697 }
3698#endif // C++17
3699#endif // C++14
3700
3701#ifdef _GLIBCXX_USE_C99_STDINT_TR11
3702 /**
3703 * @brief Generate two uniformly distributed integers using a
3704 * single distribution invocation.
3705 * @param __b0 The upper bound for the first integer.
3706 * @param __b1 The upper bound for the second integer.
3707 * @param __g A UniformRandomBitGenerator.
3708 * @return A pair (i, j) with i and j uniformly distributed
3709 * over [0, __b0) and [0, __b1), respectively.
3710 *
3711 * Requires: __b0 * __b1 <= __g.max() - __g.min().
3712 *
3713 * Using uniform_int_distribution with a range that is very
3714 * small relative to the range of the generator ends up wasting
3715 * potentially expensively generated randomness, since
3716 * uniform_int_distribution does not store leftover randomness
3717 * between invocations.
3718 *
3719 * If we know we want two integers in ranges that are sufficiently
3720 * small, we can compose the ranges, use a single distribution
3721 * invocation, and significantly reduce the waste.
3722 */
3723 template<typename _IntType, typename _UniformRandomBitGenerator>
3724 pair<_IntType, _IntType>
3725 __gen_two_uniform_ints(_IntType __b0, _IntType __b1,
3726 _UniformRandomBitGenerator&& __g)
3727 {
3728 _IntType __x
3729 = uniform_int_distribution<_IntType>{0, (__b0 * __b1) - 1}(__g);
3730 return std::make_pair(__x / __b1, __x % __b1);
3731 }
3732
3733 /**
3734 * @brief Shuffle the elements of a sequence using a uniform random
3735 * number generator.
3736 * @ingroup mutating_algorithms
3737 * @param __first A forward iterator.
3738 * @param __last A forward iterator.
3739 * @param __g A UniformRandomNumberGenerator (26.5.1.3).
3740 * @return Nothing.
3741 *
3742 * Reorders the elements in the range @p [__first,__last) using @p __g to
3743 * provide random numbers.
3744 */
3745 template<typename _RandomAccessIterator,
3746 typename _UniformRandomNumberGenerator>
3747 void
3748 shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last,
3749 _UniformRandomNumberGenerator&& __g)
3750 {
3751 // concept requirements
3752 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
3753 _RandomAccessIterator>)
3754 __glibcxx_requires_valid_range(__first, __last);
3755
3756 if (__first == __last)
3757 return;
3758
3759 typedef typename iterator_traits<_RandomAccessIterator>::difference_type
3760 _DistanceType;
3761
3762 typedef typename std::make_unsigned<_DistanceType>::type __ud_type;
3763 typedef typename std::uniform_int_distribution<__ud_type> __distr_type;
3764 typedef typename __distr_type::param_type __p_type;
3765
3766 typedef typename remove_reference<_UniformRandomNumberGenerator>::type
3767 _Gen;
3768 typedef typename common_type<typename _Gen::result_type, __ud_type>::type
3769 __uc_type;
3770
3771 const __uc_type __urngrange = __g.max() - __g.min();
3772 const __uc_type __urange = __uc_type(__last - __first);
3773
3774 if (__urngrange / __urange >= __urange)
3775 // I.e. (__urngrange >= __urange * __urange) but without wrap issues.
3776 {
3777 _RandomAccessIterator __i = __first + 1;
3778
3779 // Since we know the range isn't empty, an even number of elements
3780 // means an uneven number of elements /to swap/, in which case we
3781 // do the first one up front:
3782
3783 if ((__urange % 2) == 0)
3784 {
3785 __distr_type __d{0, 1};
3786 std::iter_swap(__i++, __first + __d(__g));
3787 }
3788
3789 // Now we know that __last - __i is even, so we do the rest in pairs,
3790 // using a single distribution invocation to produce swap positions
3791 // for two successive elements at a time:
3792
3793 while (__i != __last)
3794 {
3795 const __uc_type __swap_range = __uc_type(__i - __first) + 1;
3796
3797 const pair<__uc_type, __uc_type> __pospos =
3798 __gen_two_uniform_ints(__swap_range, __swap_range + 1, __g);
3799
3800 std::iter_swap(__i++, __first + __pospos.first);
3801 std::iter_swap(__i++, __first + __pospos.second);
3802 }
3803
3804 return;
3805 }
3806
3807 __distr_type __d;
3808
3809 for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
3810 std::iter_swap(__i, __first + __d(__g, __p_type(0, __i - __first)));
3811 }
3812#endif
3813
3814#endif // C++11
3815
3816_GLIBCXX_BEGIN_NAMESPACE_ALGO
3817
3818 /**
3819 * @brief Apply a function to every element of a sequence.
3820 * @ingroup non_mutating_algorithms
3821 * @param __first An input iterator.
3822 * @param __last An input iterator.
3823 * @param __f A unary function object.
3824 * @return @p __f
3825 *
3826 * Applies the function object @p __f to each element in the range
3827 * @p [first,last). @p __f must not modify the order of the sequence.
3828 * If @p __f has a return value it is ignored.
3829 */
3830 template<typename _InputIterator, typename _Function>
3831 _GLIBCXX20_CONSTEXPR
3832 _Function
3833 for_each(_InputIterator __first, _InputIterator __last, _Function __f)
3834 {
3835 // concept requirements
3836 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
3837 __glibcxx_requires_valid_range(__first, __last);
3838 for (; __first != __last; ++__first)
3839 __f(*__first);
3840 return __f; // N.B. [alg.foreach] says std::move(f) but it's redundant.
3841 }
3842
3843#if __cplusplus201402L >= 201703L
3844 /**
3845 * @brief Apply a function to every element of a sequence.
3846 * @ingroup non_mutating_algorithms
3847 * @param __first An input iterator.
3848 * @param __n A value convertible to an integer.
3849 * @param __f A unary function object.
3850 * @return `__first+__n`
3851 *
3852 * Applies the function object `__f` to each element in the range
3853 * `[first, first+n)`. `__f` must not modify the order of the sequence.
3854 * If `__f` has a return value it is ignored.
3855 */
3856 template<typename _InputIterator, typename _Size, typename _Function>
3857 _InputIterator
3858 for_each_n(_InputIterator __first, _Size __n, _Function __f)
3859 {
3860 auto __n2 = std::__size_to_integer(__n);
3861 using _Cat = typename iterator_traits<_InputIterator>::iterator_category;
3862 if constexpr (is_base_of_v<random_access_iterator_tag, _Cat>)
3863 {
3864 if (__n2 <= 0)
3865 return __first;
3866 auto __last = __first + __n2;
3867 std::for_each(__first, __last, std::move(__f));
3868 return __last;
3869 }
3870 else
3871 {
3872 while (__n2-->0)
3873 {
3874 __f(*__first);
3875 ++__first;
3876 }
3877 return __first;
3878 }
3879 }
3880#endif // C++17
3881
3882 /**
3883 * @brief Find the first occurrence of a value in a sequence.
3884 * @ingroup non_mutating_algorithms
3885 * @param __first An input iterator.
3886 * @param __last An input iterator.
3887 * @param __val The value to find.
3888 * @return The first iterator @c i in the range @p [__first,__last)
3889 * such that @c *i == @p __val, or @p __last if no such iterator exists.
3890 */
3891 template<typename _InputIterator, typename _Tp>
3892 _GLIBCXX20_CONSTEXPR
3893 inline _InputIterator
3894 find(_InputIterator __first, _InputIterator __last,
3895 const _Tp& __val)
3896 {
3897 // concept requirements
3898 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
3899 __glibcxx_function_requires(_EqualOpConcept<
3900 typename iterator_traits<_InputIterator>::value_type, _Tp>)
3901 __glibcxx_requires_valid_range(__first, __last);
3902 return std::__find_if(__first, __last,
3903 __gnu_cxx::__ops::__iter_equals_val(__val));
3904 }
3905
3906 /**
3907 * @brief Find the first element in a sequence for which a
3908 * predicate is true.
3909 * @ingroup non_mutating_algorithms
3910 * @param __first An input iterator.
3911 * @param __last An input iterator.
3912 * @param __pred A predicate.
3913 * @return The first iterator @c i in the range @p [__first,__last)
3914 * such that @p __pred(*i) is true, or @p __last if no such iterator exists.
3915 */
3916 template<typename _InputIterator, typename _Predicate>
3917 _GLIBCXX20_CONSTEXPR
3918 inline _InputIterator
3919 find_if(_InputIterator __first, _InputIterator __last,
3920 _Predicate __pred)
3921 {
3922 // concept requirements
3923 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
3924 __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
3925 typename iterator_traits<_InputIterator>::value_type>)
3926 __glibcxx_requires_valid_range(__first, __last);
3927
3928 return std::__find_if(__first, __last,
3929 __gnu_cxx::__ops::__pred_iter(__pred));
3930 }
3931
3932 /**
3933 * @brief Find element from a set in a sequence.
3934 * @ingroup non_mutating_algorithms
3935 * @param __first1 Start of range to search.
3936 * @param __last1 End of range to search.
3937 * @param __first2 Start of match candidates.
3938 * @param __last2 End of match candidates.
3939 * @return The first iterator @c i in the range
3940 * @p [__first1,__last1) such that @c *i == @p *(i2) such that i2 is an
3941 * iterator in [__first2,__last2), or @p __last1 if no such iterator exists.
3942 *
3943 * Searches the range @p [__first1,__last1) for an element that is
3944 * equal to some element in the range [__first2,__last2). If
3945 * found, returns an iterator in the range [__first1,__last1),
3946 * otherwise returns @p __last1.
3947 */
3948 template<typename _InputIterator, typename _ForwardIterator>
3949 _GLIBCXX20_CONSTEXPR
3950 _InputIterator
3951 find_first_of(_InputIterator __first1, _InputIterator __last1,
3952 _ForwardIterator __first2, _ForwardIterator __last2)
3953 {
3954 // concept requirements
3955 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
3956 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
3957 __glibcxx_function_requires(_EqualOpConcept<
3958 typename iterator_traits<_InputIterator>::value_type,
3959 typename iterator_traits<_ForwardIterator>::value_type>)
3960 __glibcxx_requires_valid_range(__first1, __last1);
3961 __glibcxx_requires_valid_range(__first2, __last2);
3962
3963 for (; __first1 != __last1; ++__first1)
3964 for (_ForwardIterator __iter = __first2; __iter != __last2; ++__iter)
3965 if (*__first1 == *__iter)
3966 return __first1;
3967 return __last1;
3968 }
3969
3970 /**
3971 * @brief Find element from a set in a sequence using a predicate.
3972 * @ingroup non_mutating_algorithms
3973 * @param __first1 Start of range to search.
3974 * @param __last1 End of range to search.
3975 * @param __first2 Start of match candidates.
3976 * @param __last2 End of match candidates.
3977 * @param __comp Predicate to use.
3978 * @return The first iterator @c i in the range
3979 * @p [__first1,__last1) such that @c comp(*i, @p *(i2)) is true
3980 * and i2 is an iterator in [__first2,__last2), or @p __last1 if no
3981 * such iterator exists.
3982 *
3983
3984 * Searches the range @p [__first1,__last1) for an element that is
3985 * equal to some element in the range [__first2,__last2). If
3986 * found, returns an iterator in the range [__first1,__last1),
3987 * otherwise returns @p __last1.
3988 */
3989 template<typename _InputIterator, typename _ForwardIterator,
3990 typename _BinaryPredicate>
3991 _GLIBCXX20_CONSTEXPR
3992 _InputIterator
3993 find_first_of(_InputIterator __first1, _InputIterator __last1,
3994 _ForwardIterator __first2, _ForwardIterator __last2,
3995 _BinaryPredicate __comp)
3996 {
3997 // concept requirements
3998 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
3999 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
4000 __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate,
4001 typename iterator_traits<_InputIterator>::value_type,
4002 typename iterator_traits<_ForwardIterator>::value_type>)
4003 __glibcxx_requires_valid_range(__first1, __last1);
4004 __glibcxx_requires_valid_range(__first2, __last2);
4005
4006 for (; __first1 != __last1; ++__first1)
4007 for (_ForwardIterator __iter = __first2; __iter != __last2; ++__iter)
4008 if (__comp(*__first1, *__iter))
4009 return __first1;
4010 return __last1;
4011 }
4012
4013 /**
4014 * @brief Find two adjacent values in a sequence that are equal.
4015 * @ingroup non_mutating_algorithms
4016 * @param __first A forward iterator.
4017 * @param __last A forward iterator.
4018 * @return The first iterator @c i such that @c i and @c i+1 are both
4019 * valid iterators in @p [__first,__last) and such that @c *i == @c *(i+1),
4020 * or @p __last if no such iterator exists.
4021 */
4022 template<typename _ForwardIterator>
4023 _GLIBCXX20_CONSTEXPR
4024 inline _ForwardIterator
4025 adjacent_find(_ForwardIterator __first, _ForwardIterator __last)
4026 {
4027 // concept requirements
4028 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
4029 __glibcxx_function_requires(_EqualityComparableConcept<
4030 typename iterator_traits<_ForwardIterator>::value_type>)
4031 __glibcxx_requires_valid_range(__first, __last);
4032
4033 return std::__adjacent_find(__first, __last,
4034 __gnu_cxx::__ops::__iter_equal_to_iter());
4035 }
4036
4037 /**
4038 * @brief Find two adjacent values in a sequence using a predicate.
4039 * @ingroup non_mutating_algorithms
4040 * @param __first A forward iterator.
4041 * @param __last A forward iterator.
4042 * @param __binary_pred A binary predicate.
4043 * @return The first iterator @c i such that @c i and @c i+1 are both
4044 * valid iterators in @p [__first,__last) and such that
4045 * @p __binary_pred(*i,*(i+1)) is true, or @p __last if no such iterator
4046 * exists.
4047 */
4048 template<typename _ForwardIterator, typename _BinaryPredicate>
4049 _GLIBCXX20_CONSTEXPR
4050 inline _ForwardIterator
4051 adjacent_find(_ForwardIterator __first, _ForwardIterator __last,
4052 _BinaryPredicate __binary_pred)
4053 {
4054 // concept requirements
4055 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
4056 __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate,
4057 typename iterator_traits<_ForwardIterator>::value_type,
4058 typename iterator_traits<_ForwardIterator>::value_type>)
4059 __glibcxx_requires_valid_range(__first, __last);
4060
4061 return std::__adjacent_find(__first, __last,
4062 __gnu_cxx::__ops::__iter_comp_iter(__binary_pred));
4063 }
4064
4065 /**
4066 * @brief Count the number of copies of a value in a sequence.
4067 * @ingroup non_mutating_algorithms
4068 * @param __first An input iterator.
4069 * @param __last An input iterator.
4070 * @param __value The value to be counted.
4071 * @return The number of iterators @c i in the range @p [__first,__last)
4072 * for which @c *i == @p __value
4073 */
4074 template<typename _InputIterator, typename _Tp>
4075 _GLIBCXX20_CONSTEXPR
4076 inline typename iterator_traits<_InputIterator>::difference_type
4077 count(_InputIterator __first, _InputIterator __last, const _Tp& __value)
4078 {
4079 // concept requirements
4080 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
4081 __glibcxx_function_requires(_EqualOpConcept<
4082 typename iterator_traits<_InputIterator>::value_type, _Tp>)
4083 __glibcxx_requires_valid_range(__first, __last);
4084
4085 return std::__count_if(__first, __last,
4086 __gnu_cxx::__ops::__iter_equals_val(__value));
4087 }
4088
4089 /**
4090 * @brief Count the elements of a sequence for which a predicate is true.
4091 * @ingroup non_mutating_algorithms
4092 * @param __first An input iterator.
4093 * @param __last An input iterator.
4094 * @param __pred A predicate.
4095 * @return The number of iterators @c i in the range @p [__first,__last)
4096 * for which @p __pred(*i) is true.
4097 */
4098 template<typename _InputIterator, typename _Predicate>
4099 _GLIBCXX20_CONSTEXPR
4100 inline typename iterator_traits<_InputIterator>::difference_type
4101 count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred)
4102 {
4103 // concept requirements
4104 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
4105 __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
4106 typename iterator_traits<_InputIterator>::value_type>)
4107 __glibcxx_requires_valid_range(__first, __last);
4108
4109 return std::__count_if(__first, __last,
4110 __gnu_cxx::__ops::__pred_iter(__pred));
4111 }
4112
4113 /**
4114 * @brief Search a sequence for a matching sub-sequence.
4115 * @ingroup non_mutating_algorithms
4116 * @param __first1 A forward iterator.
4117 * @param __last1 A forward iterator.
4118 * @param __first2 A forward iterator.
4119 * @param __last2 A forward iterator.
4120 * @return The first iterator @c i in the range @p
4121 * [__first1,__last1-(__last2-__first2)) such that @c *(i+N) == @p
4122 * *(__first2+N) for each @c N in the range @p
4123 * [0,__last2-__first2), or @p __last1 if no such iterator exists.
4124 *
4125 * Searches the range @p [__first1,__last1) for a sub-sequence that
4126 * compares equal value-by-value with the sequence given by @p
4127 * [__first2,__last2) and returns an iterator to the first element
4128 * of the sub-sequence, or @p __last1 if the sub-sequence is not
4129 * found.
4130 *
4131 * Because the sub-sequence must lie completely within the range @p
4132 * [__first1,__last1) it must start at a position less than @p
4133 * __last1-(__last2-__first2) where @p __last2-__first2 is the
4134 * length of the sub-sequence.
4135 *
4136 * This means that the returned iterator @c i will be in the range
4137 * @p [__first1,__last1-(__last2-__first2))
4138 */
4139 template<typename _ForwardIterator1, typename _ForwardIterator2>
4140 _GLIBCXX20_CONSTEXPR
4141 inline _ForwardIterator1
4142 search(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
4143 _ForwardIterator2 __first2, _ForwardIterator2 __last2)
4144 {
4145 // concept requirements
4146 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>)
4147 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>)
4148 __glibcxx_function_requires(_EqualOpConcept<
4149 typename iterator_traits<_ForwardIterator1>::value_type,
4150 typename iterator_traits<_ForwardIterator2>::value_type>)
4151 __glibcxx_requires_valid_range(__first1, __last1);
4152 __glibcxx_requires_valid_range(__first2, __last2);
4153
4154 return std::__search(__first1, __last1, __first2, __last2,
4155 __gnu_cxx::__ops::__iter_equal_to_iter());
4156 }
4157
4158 /**
4159 * @brief Search a sequence for a matching sub-sequence using a predicate.
4160 * @ingroup non_mutating_algorithms
4161 * @param __first1 A forward iterator.
4162 * @param __last1 A forward iterator.
4163 * @param __first2 A forward iterator.
4164 * @param __last2 A forward iterator.
4165 * @param __predicate A binary predicate.
4166 * @return The first iterator @c i in the range
4167 * @p [__first1,__last1-(__last2-__first2)) such that
4168 * @p __predicate(*(i+N),*(__first2+N)) is true for each @c N in the range
4169 * @p [0,__last2-__first2), or @p __last1 if no such iterator exists.
4170 *
4171 * Searches the range @p [__first1,__last1) for a sub-sequence that
4172 * compares equal value-by-value with the sequence given by @p
4173 * [__first2,__last2), using @p __predicate to determine equality,
4174 * and returns an iterator to the first element of the
4175 * sub-sequence, or @p __last1 if no such iterator exists.
4176 *
4177 * @see search(_ForwardIter1, _ForwardIter1, _ForwardIter2, _ForwardIter2)
4178 */
4179 template<typename _ForwardIterator1, typename _ForwardIterator2,
4180 typename _BinaryPredicate>
4181 _GLIBCXX20_CONSTEXPR
4182 inline _ForwardIterator1
4183 search(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
4184 _ForwardIterator2 __first2, _ForwardIterator2 __last2,
4185 _BinaryPredicate __predicate)
4186 {
4187 // concept requirements
4188 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>)
4189 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>)
4190 __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate,
4191 typename iterator_traits<_ForwardIterator1>::value_type,
4192 typename iterator_traits<_ForwardIterator2>::value_type>)
4193 __glibcxx_requires_valid_range(__first1, __last1);
4194 __glibcxx_requires_valid_range(__first2, __last2);
4195
4196 return std::__search(__first1, __last1, __first2, __last2,
4197 __gnu_cxx::__ops::__iter_comp_iter(__predicate));
4198 }
4199
4200 /**
4201 * @brief Search a sequence for a number of consecutive values.
4202 * @ingroup non_mutating_algorithms
4203 * @param __first A forward iterator.
4204 * @param __last A forward iterator.
4205 * @param __count The number of consecutive values.
4206 * @param __val The value to find.
4207 * @return The first iterator @c i in the range @p
4208 * [__first,__last-__count) such that @c *(i+N) == @p __val for
4209 * each @c N in the range @p [0,__count), or @p __last if no such
4210 * iterator exists.
4211 *
4212 * Searches the range @p [__first,__last) for @p count consecutive elements
4213 * equal to @p __val.
4214 */
4215 template<typename _ForwardIterator, typename _Integer, typename _Tp>
4216 _GLIBCXX20_CONSTEXPR
4217 inline _ForwardIterator
4218 search_n(_ForwardIterator __first, _ForwardIterator __last,
4219 _Integer __count, const _Tp& __val)
4220 {
4221 // concept requirements
4222 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
4223 __glibcxx_function_requires(_EqualOpConcept<
4224 typename iterator_traits<_ForwardIterator>::value_type, _Tp>)
4225 __glibcxx_requires_valid_range(__first, __last);
4226
4227 return std::__search_n(__first, __last, __count,
4228 __gnu_cxx::__ops::__iter_equals_val(__val));
4229 }
4230
4231
4232 /**
4233 * @brief Search a sequence for a number of consecutive values using a
4234 * predicate.
4235 * @ingroup non_mutating_algorithms
4236 * @param __first A forward iterator.
4237 * @param __last A forward iterator.
4238 * @param __count The number of consecutive values.
4239 * @param __val The value to find.
4240 * @param __binary_pred A binary predicate.
4241 * @return The first iterator @c i in the range @p
4242 * [__first,__last-__count) such that @p
4243 * __binary_pred(*(i+N),__val) is true for each @c N in the range
4244 * @p [0,__count), or @p __last if no such iterator exists.
4245 *
4246 * Searches the range @p [__first,__last) for @p __count
4247 * consecutive elements for which the predicate returns true.
4248 */
4249 template<typename _ForwardIterator, typename _Integer, typename _Tp,
4250 typename _BinaryPredicate>
4251 _GLIBCXX20_CONSTEXPR
4252 inline _ForwardIterator
4253 search_n(_ForwardIterator __first, _ForwardIterator __last,
4254 _Integer __count, const _Tp& __val,
4255 _BinaryPredicate __binary_pred)
4256 {
4257 // concept requirements
4258 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
4259 __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate,
4260 typename iterator_traits<_ForwardIterator>::value_type, _Tp>)
4261 __glibcxx_requires_valid_range(__first, __last);
4262
4263 return std::__search_n(__first, __last, __count,
4264 __gnu_cxx::__ops::__iter_comp_val(__binary_pred, __val));
4265 }
4266
4267#if __cplusplus201402L > 201402L
4268 /** @brief Search a sequence using a Searcher object.
4269 *
4270 * @param __first A forward iterator.
4271 * @param __last A forward iterator.
4272 * @param __searcher A callable object.
4273 * @return @p __searcher(__first,__last).first
4274 */
4275 template<typename _ForwardIterator, typename _Searcher>
4276 inline _ForwardIterator
4277 search(_ForwardIterator __first, _ForwardIterator __last,
4278 const _Searcher& __searcher)
4279 { return __searcher(__first, __last).first; }
4280#endif
4281
4282 /**
4283 * @brief Perform an operation on a sequence.
4284 * @ingroup mutating_algorithms
4285 * @param __first An input iterator.
4286 * @param __last An input iterator.
4287 * @param __result An output iterator.
4288 * @param __unary_op A unary operator.
4289 * @return An output iterator equal to @p __result+(__last-__first).
4290 *
4291 * Applies the operator to each element in the input range and assigns
4292 * the results to successive elements of the output sequence.
4293 * Evaluates @p *(__result+N)=unary_op(*(__first+N)) for each @c N in the
4294 * range @p [0,__last-__first).
4295 *
4296 * @p unary_op must not alter its argument.
4297 */
4298 template<typename _InputIterator, typename _OutputIterator,
4299 typename _UnaryOperation>
4300 _GLIBCXX20_CONSTEXPR
4301 _OutputIterator
4302 transform(_InputIterator __first, _InputIterator __last,
4303 _OutputIterator __result, _UnaryOperation __unary_op)
4304 {
4305 // concept requirements
4306 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
4307 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
4308 // "the type returned by a _UnaryOperation"
4309 __typeof__(__unary_op(*__first))>)
4310 __glibcxx_requires_valid_range(__first, __last);
4311
4312 for (; __first != __last; ++__first, (void)++__result)
4313 *__result = __unary_op(*__first);
4314 return __result;
4315 }
4316
4317 /**
4318 * @brief Perform an operation on corresponding elements of two sequences.
4319 * @ingroup mutating_algorithms
4320 * @param __first1 An input iterator.
4321 * @param __last1 An input iterator.
4322 * @param __first2 An input iterator.
4323 * @param __result An output iterator.
4324 * @param __binary_op A binary operator.
4325 * @return An output iterator equal to @p result+(last-first).
4326 *
4327 * Applies the operator to the corresponding elements in the two
4328 * input ranges and assigns the results to successive elements of the
4329 * output sequence.
4330 * Evaluates @p
4331 * *(__result+N)=__binary_op(*(__first1+N),*(__first2+N)) for each
4332 * @c N in the range @p [0,__last1-__first1).
4333 *
4334 * @p binary_op must not alter either of its arguments.
4335 */
4336 template<typename _InputIterator1, typename _InputIterator2,
4337 typename _OutputIterator, typename _BinaryOperation>
4338 _GLIBCXX20_CONSTEXPR
4339 _OutputIterator
4340 transform(_InputIterator1 __first1, _InputIterator1 __last1,
4341 _InputIterator2 __first2, _OutputIterator __result,
4342 _BinaryOperation __binary_op)
4343 {
4344 // concept requirements
4345 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
4346 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
4347 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
4348 // "the type returned by a _BinaryOperation"
4349 __typeof__(__binary_op(*__first1,*__first2))>)
4350 __glibcxx_requires_valid_range(__first1, __last1);
4351
4352 for (; __first1 != __last1; ++__first1, (void)++__first2, ++__result)
4353 *__result = __binary_op(*__first1, *__first2);
4354 return __result;
4355 }
4356
4357 /**
4358 * @brief Replace each occurrence of one value in a sequence with another
4359 * value.
4360 * @ingroup mutating_algorithms
4361 * @param __first A forward iterator.
4362 * @param __last A forward iterator.
4363 * @param __old_value The value to be replaced.
4364 * @param __new_value The replacement value.
4365 * @return replace() returns no value.
4366 *
4367 * For each iterator @c i in the range @p [__first,__last) if @c *i ==
4368 * @p __old_value then the assignment @c *i = @p __new_value is performed.
4369 */
4370 template<typename _ForwardIterator, typename _Tp>
4371 _GLIBCXX20_CONSTEXPR
4372 void
4373 replace(_ForwardIterator __first, _ForwardIterator __last,
4374 const _Tp& __old_value, const _Tp& __new_value)
4375 {
4376 // concept requirements
4377 __glibcxx_function_requires(_Mutable_ForwardIteratorConcept<
4378 _ForwardIterator>)
4379 __glibcxx_function_requires(_EqualOpConcept<
4380 typename iterator_traits<_ForwardIterator>::value_type, _Tp>)
4381 __glibcxx_function_requires(_ConvertibleConcept<_Tp,
4382 typename iterator_traits<_ForwardIterator>::value_type>)
4383 __glibcxx_requires_valid_range(__first, __last);
4384
4385 for (; __first != __last; ++__first)
4386 if (*__first == __old_value)
4387 *__first = __new_value;
4388 }
4389
4390 /**
4391 * @brief Replace each value in a sequence for which a predicate returns
4392 * true with another value.
4393 * @ingroup mutating_algorithms
4394 * @param __first A forward iterator.
4395 * @param __last A forward iterator.
4396 * @param __pred A predicate.
4397 * @param __new_value The replacement value.
4398 * @return replace_if() returns no value.
4399 *
4400 * For each iterator @c i in the range @p [__first,__last) if @p __pred(*i)
4401 * is true then the assignment @c *i = @p __new_value is performed.
4402 */
4403 template<typename _ForwardIterator, typename _Predicate, typename _Tp>
4404 _GLIBCXX20_CONSTEXPR
4405 void
4406 replace_if(_ForwardIterator __first, _ForwardIterator __last,
4407 _Predicate __pred, const _Tp& __new_value)
4408 {
4409 // concept requirements
4410 __glibcxx_function_requires(_Mutable_ForwardIteratorConcept<
4411 _ForwardIterator>)
4412 __glibcxx_function_requires(_ConvertibleConcept<_Tp,
4413 typename iterator_traits<_ForwardIterator>::value_type>)
4414 __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
4415 typename iterator_traits<_ForwardIterator>::value_type>)
4416 __glibcxx_requires_valid_range(__first, __last);
4417
4418 for (; __first != __last; ++__first)
4419 if (__pred(*__first))
4420 *__first = __new_value;
4421 }
4422
4423 /**
4424 * @brief Assign the result of a function object to each value in a
4425 * sequence.
4426 * @ingroup mutating_algorithms
4427 * @param __first A forward iterator.
4428 * @param __last A forward iterator.
4429 * @param __gen A function object taking no arguments and returning
4430 * std::iterator_traits<_ForwardIterator>::value_type
4431 * @return generate() returns no value.
4432 *
4433 * Performs the assignment @c *i = @p __gen() for each @c i in the range
4434 * @p [__first,__last).
4435 */
4436 template<typename _ForwardIterator, typename _Generator>
4437 _GLIBCXX20_CONSTEXPR
4438 void
4439 generate(_ForwardIterator __first, _ForwardIterator __last,
4440 _Generator __gen)
4441 {
4442 // concept requirements
4443 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
4444 __glibcxx_function_requires(_GeneratorConcept<_Generator,
4445 typename iterator_traits<_ForwardIterator>::value_type>)
4446 __glibcxx_requires_valid_range(__first, __last);
4447
4448 for (; __first != __last; ++__first)
4449 *__first = __gen();
4450 }
4451
4452 /**
4453 * @brief Assign the result of a function object to each value in a
4454 * sequence.
4455 * @ingroup mutating_algorithms
4456 * @param __first A forward iterator.
4457 * @param __n The length of the sequence.
4458 * @param __gen A function object taking no arguments and returning
4459 * std::iterator_traits<_ForwardIterator>::value_type
4460 * @return The end of the sequence, @p __first+__n
4461 *
4462 * Performs the assignment @c *i = @p __gen() for each @c i in the range
4463 * @p [__first,__first+__n).
4464 *
4465 * If @p __n is negative, the function does nothing and returns @p __first.
4466 */
4467 // _GLIBCXX_RESOLVE_LIB_DEFECTS
4468 // DR 865. More algorithms that throw away information
4469 // DR 426. search_n(), fill_n(), and generate_n() with negative n
4470 template<typename _OutputIterator, typename _Size, typename _Generator>
4471 _GLIBCXX20_CONSTEXPR
4472 _OutputIterator
4473 generate_n(_OutputIterator __first, _Size __n, _Generator __gen)
4474 {
4475 // concept requirements
4476 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
4477 // "the type returned by a _Generator"
4478 __typeof__(__gen())>)
4479
4480 typedef __decltype(std::__size_to_integer(__n)) _IntSize;
4481 for (_IntSize __niter = std::__size_to_integer(__n);
4482 __niter > 0; --__niter, (void) ++__first)
4483 *__first = __gen();
4484 return __first;
4485 }
4486
4487 /**
4488 * @brief Copy a sequence, removing consecutive duplicate values.
4489 * @ingroup mutating_algorithms
4490 * @param __first An input iterator.
4491 * @param __last An input iterator.
4492 * @param __result An output iterator.
4493 * @return An iterator designating the end of the resulting sequence.
4494 *
4495 * Copies each element in the range @p [__first,__last) to the range
4496 * beginning at @p __result, except that only the first element is copied
4497 * from groups of consecutive elements that compare equal.
4498 * unique_copy() is stable, so the relative order of elements that are
4499 * copied is unchanged.
4500 *
4501 * _GLIBCXX_RESOLVE_LIB_DEFECTS
4502 * DR 241. Does unique_copy() require CopyConstructible and Assignable?
4503 *
4504 * _GLIBCXX_RESOLVE_LIB_DEFECTS
4505 * DR 538. 241 again: Does unique_copy() require CopyConstructible and
4506 * Assignable?
4507 */
4508 template<typename _InputIterator, typename _OutputIterator>
4509 _GLIBCXX20_CONSTEXPR
4510 inline _OutputIterator
4511 unique_copy(_InputIterator __first, _InputIterator __last,
4512 _OutputIterator __result)
4513 {
4514 // concept requirements
4515 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
4516 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
4517 typename iterator_traits<_InputIterator>::value_type>)
4518 __glibcxx_function_requires(_EqualityComparableConcept<
4519 typename iterator_traits<_InputIterator>::value_type>)
4520 __glibcxx_requires_valid_range(__first, __last);
4521
4522 if (__first == __last)
4523 return __result;
4524 return std::__unique_copy(__first, __last, __result,
4525 __gnu_cxx::__ops::__iter_equal_to_iter(),
4526 std::__iterator_category(__first),
4527 std::__iterator_category(__result));
4528 }
4529
4530 /**
4531 * @brief Copy a sequence, removing consecutive values using a predicate.
4532 * @ingroup mutating_algorithms
4533 * @param __first An input iterator.
4534 * @param __last An input iterator.
4535 * @param __result An output iterator.
4536 * @param __binary_pred A binary predicate.
4537 * @return An iterator designating the end of the resulting sequence.
4538 *
4539 * Copies each element in the range @p [__first,__last) to the range
4540 * beginning at @p __result, except that only the first element is copied
4541 * from groups of consecutive elements for which @p __binary_pred returns
4542 * true.
4543 * unique_copy() is stable, so the relative order of elements that are
4544 * copied is unchanged.
4545 *
4546 * _GLIBCXX_RESOLVE_LIB_DEFECTS
4547 * DR 241. Does unique_copy() require CopyConstructible and Assignable?
4548 */
4549 template<typename _InputIterator, typename _OutputIterator,
4550 typename _BinaryPredicate>
4551 _GLIBCXX20_CONSTEXPR
4552 inline _OutputIterator
4553 unique_copy(_InputIterator __first, _InputIterator __last,
4554 _OutputIterator __result,
4555 _BinaryPredicate __binary_pred)
4556 {
4557 // concept requirements -- predicates checked later
4558 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
4559 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
4560 typename iterator_traits<_InputIterator>::value_type>)
4561 __glibcxx_requires_valid_range(__first, __last);
4562
4563 if (__first == __last)
4564 return __result;
4565 return std::__unique_copy(__first, __last, __result,
4566 __gnu_cxx::__ops::__iter_comp_iter(__binary_pred),
4567 std::__iterator_category(__first),
4568 std::__iterator_category(__result));
4569 }
4570
4571#if _GLIBCXX_HOSTED1
4572 /**
4573 * @brief Randomly shuffle the elements of a sequence.
4574 * @ingroup mutating_algorithms
4575 * @param __first A forward iterator.
4576 * @param __last A forward iterator.
4577 * @return Nothing.
4578 *
4579 * Reorder the elements in the range @p [__first,__last) using a random
4580 * distribution, so that every possible ordering of the sequence is
4581 * equally likely.
4582 */
4583 template<typename _RandomAccessIterator>
4584 inline void
4585 random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last)
4586 {
4587 // concept requirements
4588 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
4589 _RandomAccessIterator>)
4590 __glibcxx_requires_valid_range(__first, __last);
4591
4592 if (__first != __last)
4593 for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
4594 {
4595 // XXX rand() % N is not uniformly distributed
4596 _RandomAccessIterator __j = __first
4597 + std::rand() % ((__i - __first) + 1);
4598 if (__i != __j)
4599 std::iter_swap(__i, __j);
4600 }
4601 }
4602#endif
4603
4604 /**
4605 * @brief Shuffle the elements of a sequence using a random number
4606 * generator.
4607 * @ingroup mutating_algorithms
4608 * @param __first A forward iterator.
4609 * @param __last A forward iterator.
4610 * @param __rand The RNG functor or function.
4611 * @return Nothing.
4612 *
4613 * Reorders the elements in the range @p [__first,__last) using @p __rand to
4614 * provide a random distribution. Calling @p __rand(N) for a positive
4615 * integer @p N should return a randomly chosen integer from the
4616 * range [0,N).
4617 */
4618 template<typename _RandomAccessIterator, typename _RandomNumberGenerator>
4619 void
4620 random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last,
4621#if __cplusplus201402L >= 201103L
4622 _RandomNumberGenerator&& __rand)
4623#else
4624 _RandomNumberGenerator& __rand)
4625#endif
4626 {
4627 // concept requirements
4628 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
4629 _RandomAccessIterator>)
4630 __glibcxx_requires_valid_range(__first, __last);
4631
4632 if (__first == __last)
4633 return;
4634 for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
4635 {
4636 _RandomAccessIterator __j = __first + __rand((__i - __first) + 1);
4637 if (__i != __j)
4638 std::iter_swap(__i, __j);
4639 }
4640 }
4641
4642
4643 /**
4644 * @brief Move elements for which a predicate is true to the beginning
4645 * of a sequence.
4646 * @ingroup mutating_algorithms
4647 * @param __first A forward iterator.
4648 * @param __last A forward iterator.
4649 * @param __pred A predicate functor.
4650 * @return An iterator @p middle such that @p __pred(i) is true for each
4651 * iterator @p i in the range @p [__first,middle) and false for each @p i
4652 * in the range @p [middle,__last).
4653 *
4654 * @p __pred must not modify its operand. @p partition() does not preserve
4655 * the relative ordering of elements in each group, use
4656 * @p stable_partition() if this is needed.
4657 */
4658 template<typename _ForwardIterator, typename _Predicate>
4659 _GLIBCXX20_CONSTEXPR
4660 inline _ForwardIterator
4661 partition(_ForwardIterator __first, _ForwardIterator __last,
4662 _Predicate __pred)
4663 {
4664 // concept requirements
4665 __glibcxx_function_requires(_Mutable_ForwardIteratorConcept<
4666 _ForwardIterator>)
4667 __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate,
4668 typename iterator_traits<_ForwardIterator>::value_type>)
4669 __glibcxx_requires_valid_range(__first, __last);
4670
4671 return std::__partition(__first, __last, __pred,
4672 std::__iterator_category(__first));
4673 }
4674
4675
4676 /**
4677 * @brief Sort the smallest elements of a sequence.
4678 * @ingroup sorting_algorithms
4679 * @param __first An iterator.
4680 * @param __middle Another iterator.
4681 * @param __last Another iterator.
4682 * @return Nothing.
4683 *
4684 * Sorts the smallest @p (__middle-__first) elements in the range
4685 * @p [first,last) and moves them to the range @p [__first,__middle). The
4686 * order of the remaining elements in the range @p [__middle,__last) is
4687 * undefined.
4688 * After the sort if @e i and @e j are iterators in the range
4689 * @p [__first,__middle) such that i precedes j and @e k is an iterator in
4690 * the range @p [__middle,__last) then *j<*i and *k<*i are both false.
4691 */
4692 template<typename _RandomAccessIterator>
4693 _GLIBCXX20_CONSTEXPR
4694 inline void
4695 partial_sort(_RandomAccessIterator __first,
4696 _RandomAccessIterator __middle,
4697 _RandomAccessIterator __last)
4698 {
4699 // concept requirements
4700 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
4701 _RandomAccessIterator>)
4702 __glibcxx_function_requires(_LessThanComparableConcept<
4703 typename iterator_traits<_RandomAccessIterator>::value_type>)
4704 __glibcxx_requires_valid_range(__first, __middle);
4705 __glibcxx_requires_valid_range(__middle, __last);
4706 __glibcxx_requires_irreflexive(__first, __last);
4707
4708 std::__partial_sort(__first, __middle, __last,
4709 __gnu_cxx::__ops::__iter_less_iter());
4710 }
4711
4712 /**
4713 * @brief Sort the smallest elements of a sequence using a predicate
4714 * for comparison.
4715 * @ingroup sorting_algorithms
4716 * @param __first An iterator.
4717 * @param __middle Another iterator.
4718 * @param __last Another iterator.
4719 * @param __comp A comparison functor.
4720 * @return Nothing.
4721 *
4722 * Sorts the smallest @p (__middle-__first) elements in the range
4723 * @p [__first,__last) and moves them to the range @p [__first,__middle). The
4724 * order of the remaining elements in the range @p [__middle,__last) is
4725 * undefined.
4726 * After the sort if @e i and @e j are iterators in the range
4727 * @p [__first,__middle) such that i precedes j and @e k is an iterator in
4728 * the range @p [__middle,__last) then @p *__comp(j,*i) and @p __comp(*k,*i)
4729 * are both false.
4730 */
4731 template<typename _RandomAccessIterator, typename _Compare>
4732 _GLIBCXX20_CONSTEXPR
4733 inline void
4734 partial_sort(_RandomAccessIterator __first,
4735 _RandomAccessIterator __middle,
4736 _RandomAccessIterator __last,
4737 _Compare __comp)
4738 {
4739 // concept requirements
4740 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
4741 _RandomAccessIterator>)
4742 __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
4743 typename iterator_traits<_RandomAccessIterator>::value_type,
4744 typename iterator_traits<_RandomAccessIterator>::value_type>)
4745 __glibcxx_requires_valid_range(__first, __middle);
4746 __glibcxx_requires_valid_range(__middle, __last);
4747 __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
4748
4749 std::__partial_sort(__first, __middle, __last,
4750 __gnu_cxx::__ops::__iter_comp_iter(__comp));
4751 }
4752
4753 /**
4754 * @brief Sort a sequence just enough to find a particular position.
4755 * @ingroup sorting_algorithms
4756 * @param __first An iterator.
4757 * @param __nth Another iterator.
4758 * @param __last Another iterator.
4759 * @return Nothing.
4760 *
4761 * Rearranges the elements in the range @p [__first,__last) so that @p *__nth
4762 * is the same element that would have been in that position had the
4763 * whole sequence been sorted. The elements either side of @p *__nth are
4764 * not completely sorted, but for any iterator @e i in the range
4765 * @p [__first,__nth) and any iterator @e j in the range @p [__nth,__last) it
4766 * holds that *j < *i is false.
4767 */
4768 template<typename _RandomAccessIterator>
4769 _GLIBCXX20_CONSTEXPR
4770 inline void
4771 nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth,
4772 _RandomAccessIterator __last)
4773 {
4774 // concept requirements
4775 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
4776 _RandomAccessIterator>)
4777 __glibcxx_function_requires(_LessThanComparableConcept<
4778 typename iterator_traits<_RandomAccessIterator>::value_type>)
4779 __glibcxx_requires_valid_range(__first, __nth);
4780 __glibcxx_requires_valid_range(__nth, __last);
4781 __glibcxx_requires_irreflexive(__first, __last);
4782
4783 if (__first == __last || __nth == __last)
4784 return;
4785
4786 std::__introselect(__first, __nth, __last,
4787 std::__lg(__last - __first) * 2,
4788 __gnu_cxx::__ops::__iter_less_iter());
4789 }
4790
4791 /**
4792 * @brief Sort a sequence just enough to find a particular position
4793 * using a predicate for comparison.
4794 * @ingroup sorting_algorithms
4795 * @param __first An iterator.
4796 * @param __nth Another iterator.
4797 * @param __last Another iterator.
4798 * @param __comp A comparison functor.
4799 * @return Nothing.
4800 *
4801 * Rearranges the elements in the range @p [__first,__last) so that @p *__nth
4802 * is the same element that would have been in that position had the
4803 * whole sequence been sorted. The elements either side of @p *__nth are
4804 * not completely sorted, but for any iterator @e i in the range
4805 * @p [__first,__nth) and any iterator @e j in the range @p [__nth,__last) it
4806 * holds that @p __comp(*j,*i) is false.
4807 */
4808 template<typename _RandomAccessIterator, typename _Compare>
4809 _GLIBCXX20_CONSTEXPR
4810 inline void
4811 nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth,
4812 _RandomAccessIterator __last, _Compare __comp)
4813 {
4814 // concept requirements
4815 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
4816 _RandomAccessIterator>)
4817 __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
4818 typename iterator_traits<_RandomAccessIterator>::value_type,
4819 typename iterator_traits<_RandomAccessIterator>::value_type>)
4820 __glibcxx_requires_valid_range(__first, __nth);
4821 __glibcxx_requires_valid_range(__nth, __last);
4822 __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
4823
4824 if (__first == __last || __nth == __last)
4825 return;
4826
4827 std::__introselect(__first, __nth, __last,
4828 std::__lg(__last - __first) * 2,
4829 __gnu_cxx::__ops::__iter_comp_iter(__comp));
4830 }
4831
4832 /**
4833 * @brief Sort the elements of a sequence.
4834 * @ingroup sorting_algorithms
4835 * @param __first An iterator.
4836 * @param __last Another iterator.
4837 * @return Nothing.
4838 *
4839 * Sorts the elements in the range @p [__first,__last) in ascending order,
4840 * such that for each iterator @e i in the range @p [__first,__last-1),
4841 * *(i+1)<*i is false.
4842 *
4843 * The relative ordering of equivalent elements is not preserved, use
4844 * @p stable_sort() if this is needed.
4845 */
4846 template<typename _RandomAccessIterator>
4847 _GLIBCXX20_CONSTEXPR
4848 inline void
4849 sort(_RandomAccessIterator __first, _RandomAccessIterator __last)
4850 {
4851 // concept requirements
4852 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
4853 _RandomAccessIterator>)
4854 __glibcxx_function_requires(_LessThanComparableConcept<
4855 typename iterator_traits<_RandomAccessIterator>::value_type>)
4856 __glibcxx_requires_valid_range(__first, __last);
4857 __glibcxx_requires_irreflexive(__first, __last);
4858
4859 std::__sort(__first, __last, __gnu_cxx::__ops::__iter_less_iter());
55
Calling '__sort<unsigned int *, __gnu_cxx::__ops::_Iter_less_iter>'
4860 }
4861
4862 /**
4863 * @brief Sort the elements of a sequence using a predicate for comparison.
4864 * @ingroup sorting_algorithms
4865 * @param __first An iterator.
4866 * @param __last Another iterator.
4867 * @param __comp A comparison functor.
4868 * @return Nothing.
4869 *
4870 * Sorts the elements in the range @p [__first,__last) in ascending order,
4871 * such that @p __comp(*(i+1),*i) is false for every iterator @e i in the
4872 * range @p [__first,__last-1).
4873 *
4874 * The relative ordering of equivalent elements is not preserved, use
4875 * @p stable_sort() if this is needed.
4876 */
4877 template<typename _RandomAccessIterator, typename _Compare>
4878 _GLIBCXX20_CONSTEXPR
4879 inline void
4880 sort(_RandomAccessIterator __first, _RandomAccessIterator __last,
4881 _Compare __comp)
4882 {
4883 // concept requirements
4884 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
4885 _RandomAccessIterator>)
4886 __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
4887 typename iterator_traits<_RandomAccessIterator>::value_type,
4888 typename iterator_traits<_RandomAccessIterator>::value_type>)
4889 __glibcxx_requires_valid_range(__first, __last);
4890 __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
4891
4892 std::__sort(__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__comp));
4893 }
4894
4895 template<typename _InputIterator1, typename _InputIterator2,
4896 typename _OutputIterator, typename _Compare>
4897 _GLIBCXX20_CONSTEXPR
4898 _OutputIterator
4899 __merge(_InputIterator1 __first1, _InputIterator1 __last1,
4900 _InputIterator2 __first2, _InputIterator2 __last2,
4901 _OutputIterator __result, _Compare __comp)
4902 {
4903 while (__first1 != __last1 && __first2 != __last2)
4904 {
4905 if (__comp(__first2, __first1))
4906 {
4907 *__result = *__first2;
4908 ++__first2;
4909 }
4910 else
4911 {
4912 *__result = *__first1;
4913 ++__first1;
4914 }
4915 ++__result;
4916 }
4917 return std::copy(__first2, __last2,
4918 std::copy(__first1, __last1, __result));
4919 }
4920
4921 /**
4922 * @brief Merges two sorted ranges.
4923 * @ingroup sorting_algorithms
4924 * @param __first1 An iterator.
4925 * @param __first2 Another iterator.
4926 * @param __last1 Another iterator.
4927 * @param __last2 Another iterator.
4928 * @param __result An iterator pointing to the end of the merged range.
4929 * @return An output iterator equal to @p __result + (__last1 - __first1)
4930 * + (__last2 - __first2).
4931 *
4932 * Merges the ranges @p [__first1,__last1) and @p [__first2,__last2) into
4933 * the sorted range @p [__result, __result + (__last1-__first1) +
4934 * (__last2-__first2)). Both input ranges must be sorted, and the
4935 * output range must not overlap with either of the input ranges.
4936 * The sort is @e stable, that is, for equivalent elements in the
4937 * two ranges, elements from the first range will always come
4938 * before elements from the second.
4939 */
4940 template<typename _InputIterator1, typename _InputIterator2,
4941 typename _OutputIterator>
4942 _GLIBCXX20_CONSTEXPR
4943 inline _OutputIterator
4944 merge(_InputIterator1 __first1, _InputIterator1 __last1,
4945 _InputIterator2 __first2, _InputIterator2 __last2,
4946 _OutputIterator __result)
4947 {
4948 // concept requirements
4949 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
4950 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
4951 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
4952 typename iterator_traits<_InputIterator1>::value_type>)
4953 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
4954 typename iterator_traits<_InputIterator2>::value_type>)
4955 __glibcxx_function_requires(_LessThanOpConcept<
4956 typename iterator_traits<_InputIterator2>::value_type,
4957 typename iterator_traits<_InputIterator1>::value_type>)
4958 __glibcxx_requires_sorted_set(__first1, __last1, __first2);
4959 __glibcxx_requires_sorted_set(__first2, __last2, __first1);
4960 __glibcxx_requires_irreflexive2(__first1, __last1);
4961 __glibcxx_requires_irreflexive2(__first2, __last2);
4962
4963 return _GLIBCXX_STD_Astd::__merge(__first1, __last1,
4964 __first2, __last2, __result,
4965 __gnu_cxx::__ops::__iter_less_iter());
4966 }
4967
4968 /**
4969 * @brief Merges two sorted ranges.
4970 * @ingroup sorting_algorithms
4971 * @param __first1 An iterator.
4972 * @param __first2 Another iterator.
4973 * @param __last1 Another iterator.
4974 * @param __last2 Another iterator.
4975 * @param __result An iterator pointing to the end of the merged range.
4976 * @param __comp A functor to use for comparisons.
4977 * @return An output iterator equal to @p __result + (__last1 - __first1)
4978 * + (__last2 - __first2).
4979 *
4980 * Merges the ranges @p [__first1,__last1) and @p [__first2,__last2) into
4981 * the sorted range @p [__result, __result + (__last1-__first1) +
4982 * (__last2-__first2)). Both input ranges must be sorted, and the
4983 * output range must not overlap with either of the input ranges.
4984 * The sort is @e stable, that is, for equivalent elements in the
4985 * two ranges, elements from the first range will always come
4986 * before elements from the second.
4987 *
4988 * The comparison function should have the same effects on ordering as
4989 * the function used for the initial sort.
4990 */
4991 template<typename _InputIterator1, typename _InputIterator2,
4992 typename _OutputIterator, typename _Compare>
4993 _GLIBCXX20_CONSTEXPR
4994 inline _OutputIterator
4995 merge(_InputIterator1 __first1, _InputIterator1 __last1,
4996 _InputIterator2 __first2, _InputIterator2 __last2,
4997 _OutputIterator __result, _Compare __comp)
4998 {
4999 // concept requirements
5000 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
5001 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
5002 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
5003 typename iterator_traits<_InputIterator1>::value_type>)
5004 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
5005 typename iterator_traits<_InputIterator2>::value_type>)
5006 __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
5007 typename iterator_traits<_InputIterator2>::value_type,
5008 typename iterator_traits<_InputIterator1>::value_type>)
5009 __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp);
5010 __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp);
5011 __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp);
5012 __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp);
5013
5014 return _GLIBCXX_STD_Astd::__merge(__first1, __last1,
5015 __first2, __last2, __result,
5016 __gnu_cxx::__ops::__iter_comp_iter(__comp));
5017 }
5018
5019 template<typename _RandomAccessIterator, typename _Compare>
5020 inline void
5021 __stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last,
5022 _Compare __comp)
5023 {
5024 typedef typename iterator_traits<_RandomAccessIterator>::value_type
5025 _ValueType;
5026 typedef typename iterator_traits<_RandomAccessIterator>::difference_type
5027 _DistanceType;
5028
5029 typedef _Temporary_buffer<_RandomAccessIterator, _ValueType> _TmpBuf;
5030 _TmpBuf __buf(__first, std::distance(__first, __last));
5031
5032 if (__buf.begin() == 0)
5033 std::__inplace_stable_sort(__first, __last, __comp);
5034 else
5035 std::__stable_sort_adaptive(__first, __last, __buf.begin(),
5036 _DistanceType(__buf.size()), __comp);
5037 }
5038
5039 /**
5040 * @brief Sort the elements of a sequence, preserving the relative order
5041 * of equivalent elements.
5042 * @ingroup sorting_algorithms
5043 * @param __first An iterator.
5044 * @param __last Another iterator.
5045 * @return Nothing.
5046 *
5047 * Sorts the elements in the range @p [__first,__last) in ascending order,
5048 * such that for each iterator @p i in the range @p [__first,__last-1),
5049 * @p *(i+1)<*i is false.
5050 *
5051 * The relative ordering of equivalent elements is preserved, so any two
5052 * elements @p x and @p y in the range @p [__first,__last) such that
5053 * @p x<y is false and @p y<x is false will have the same relative
5054 * ordering after calling @p stable_sort().
5055 */
5056 template<typename _RandomAccessIterator>
5057 inline void
5058 stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last)
5059 {
5060 // concept requirements
5061 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
5062 _RandomAccessIterator>)
5063 __glibcxx_function_requires(_LessThanComparableConcept<
5064 typename iterator_traits<_RandomAccessIterator>::value_type>)
5065 __glibcxx_requires_valid_range(__first, __last);
5066 __glibcxx_requires_irreflexive(__first, __last);
5067
5068 _GLIBCXX_STD_Astd::__stable_sort(__first, __last,
5069 __gnu_cxx::__ops::__iter_less_iter());
5070 }
5071
5072 /**
5073 * @brief Sort the elements of a sequence using a predicate for comparison,
5074 * preserving the relative order of equivalent elements.
5075 * @ingroup sorting_algorithms
5076 * @param __first An iterator.
5077 * @param __last Another iterator.
5078 * @param __comp A comparison functor.
5079 * @return Nothing.
5080 *
5081 * Sorts the elements in the range @p [__first,__last) in ascending order,
5082 * such that for each iterator @p i in the range @p [__first,__last-1),
5083 * @p __comp(*(i+1),*i) is false.
5084 *
5085 * The relative ordering of equivalent elements is preserved, so any two
5086 * elements @p x and @p y in the range @p [__first,__last) such that
5087 * @p __comp(x,y) is false and @p __comp(y,x) is false will have the same
5088 * relative ordering after calling @p stable_sort().
5089 */
5090 template<typename _RandomAccessIterator, typename _Compare>
5091 inline void
5092 stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last,
5093 _Compare __comp)
5094 {
5095 // concept requirements
5096 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
5097 _RandomAccessIterator>)
5098 __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
5099 typename iterator_traits<_RandomAccessIterator>::value_type,
5100 typename iterator_traits<_RandomAccessIterator>::value_type>)
5101 __glibcxx_requires_valid_range(__first, __last);
5102 __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
5103
5104 _GLIBCXX_STD_Astd::__stable_sort(__first, __last,
5105 __gnu_cxx::__ops::__iter_comp_iter(__comp));
5106 }
5107
5108 template<typename _InputIterator1, typename _InputIterator2,
5109 typename _OutputIterator,
5110 typename _Compare>
5111 _GLIBCXX20_CONSTEXPR
5112 _OutputIterator
5113 __set_union(_InputIterator1 __first1, _InputIterator1 __last1,
5114 _InputIterator2 __first2, _InputIterator2 __last2,
5115 _OutputIterator __result, _Compare __comp)
5116 {
5117 while (__first1 != __last1 && __first2 != __last2)
5118 {
5119 if (__comp(__first1, __first2))
5120 {
5121 *__result = *__first1;
5122 ++__first1;
5123 }
5124 else if (__comp(__first2, __first1))
5125 {
5126 *__result = *__first2;
5127 ++__first2;
5128 }
5129 else
5130 {
5131 *__result = *__first1;
5132 ++__first1;
5133 ++__first2;
5134 }
5135 ++__result;
5136 }
5137 return std::copy(__first2, __last2,
5138 std::copy(__first1, __last1, __result));
5139 }
5140
5141 /**
5142 * @brief Return the union of two sorted ranges.
5143 * @ingroup set_algorithms
5144 * @param __first1 Start of first range.
5145 * @param __last1 End of first range.
5146 * @param __first2 Start of second range.
5147 * @param __last2 End of second range.
5148 * @param __result Start of output range.
5149 * @return End of the output range.
5150 * @ingroup set_algorithms
5151 *
5152 * This operation iterates over both ranges, copying elements present in
5153 * each range in order to the output range. Iterators increment for each
5154 * range. When the current element of one range is less than the other,
5155 * that element is copied and the iterator advanced. If an element is
5156 * contained in both ranges, the element from the first range is copied and
5157 * both ranges advance. The output range may not overlap either input
5158 * range.
5159 */
5160 template<typename _InputIterator1, typename _InputIterator2,
5161 typename _OutputIterator>
5162 _GLIBCXX20_CONSTEXPR
5163 inline _OutputIterator
5164 set_union(_InputIterator1 __first1, _InputIterator1 __last1,
5165 _InputIterator2 __first2, _InputIterator2 __last2,
5166 _OutputIterator __result)
5167 {
5168 // concept requirements
5169 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
5170 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
5171 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
5172 typename iterator_traits<_InputIterator1>::value_type>)
5173 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
5174 typename iterator_traits<_InputIterator2>::value_type>)
5175 __glibcxx_function_requires(_LessThanOpConcept<
5176 typename iterator_traits<_InputIterator1>::value_type,
5177 typename iterator_traits<_InputIterator2>::value_type>)
5178 __glibcxx_function_requires(_LessThanOpConcept<
5179 typename iterator_traits<_InputIterator2>::value_type,
5180 typename iterator_traits<_InputIterator1>::value_type>)
5181 __glibcxx_requires_sorted_set(__first1, __last1, __first2);
5182 __glibcxx_requires_sorted_set(__first2, __last2, __first1);
5183 __glibcxx_requires_irreflexive2(__first1, __last1);
5184 __glibcxx_requires_irreflexive2(__first2, __last2);
5185
5186 return _GLIBCXX_STD_Astd::__set_union(__first1, __last1,
5187 __first2, __last2, __result,
5188 __gnu_cxx::__ops::__iter_less_iter());
5189 }
5190
5191 /**
5192 * @brief Return the union of two sorted ranges using a comparison functor.
5193 * @ingroup set_algorithms
5194 * @param __first1 Start of first range.
5195 * @param __last1 End of first range.
5196 * @param __first2 Start of second range.
5197 * @param __last2 End of second range.
5198 * @param __result Start of output range.
5199 * @param __comp The comparison functor.
5200 * @return End of the output range.
5201 * @ingroup set_algorithms
5202 *
5203 * This operation iterates over both ranges, copying elements present in
5204 * each range in order to the output range. Iterators increment for each
5205 * range. When the current element of one range is less than the other
5206 * according to @p __comp, that element is copied and the iterator advanced.
5207 * If an equivalent element according to @p __comp is contained in both
5208 * ranges, the element from the first range is copied and both ranges
5209 * advance. The output range may not overlap either input range.
5210 */
5211 template<typename _InputIterator1, typename _InputIterator2,
5212 typename _OutputIterator, typename _Compare>
5213 _GLIBCXX20_CONSTEXPR
5214 inline _OutputIterator
5215 set_union(_InputIterator1 __first1, _InputIterator1 __last1,
5216 _InputIterator2 __first2, _InputIterator2 __last2,
5217 _OutputIterator __result, _Compare __comp)
5218 {
5219 // concept requirements
5220 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
5221 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
5222 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
5223 typename iterator_traits<_InputIterator1>::value_type>)
5224 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
5225 typename iterator_traits<_InputIterator2>::value_type>)
5226 __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
5227 typename iterator_traits<_InputIterator1>::value_type,
5228 typename iterator_traits<_InputIterator2>::value_type>)
5229 __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
5230 typename iterator_traits<_InputIterator2>::value_type,
5231 typename iterator_traits<_InputIterator1>::value_type>)
5232 __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp);
5233 __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp);
5234 __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp);
5235 __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp);
5236
5237 return _GLIBCXX_STD_Astd::__set_union(__first1, __last1,
5238 __first2, __last2, __result,
5239 __gnu_cxx::__ops::__iter_comp_iter(__comp));
5240 }
5241
5242 template<typename _InputIterator1, typename _InputIterator2,
5243 typename _OutputIterator,
5244 typename _Compare>
5245 _GLIBCXX20_CONSTEXPR
5246 _OutputIterator
5247 __set_intersection(_InputIterator1 __first1, _InputIterator1 __last1,
5248 _InputIterator2 __first2, _InputIterator2 __last2,
5249 _OutputIterator __result, _Compare __comp)
5250 {
5251 while (__first1 != __last1 && __first2 != __last2)
5252 if (__comp(__first1, __first2))
5253 ++__first1;
5254 else if (__comp(__first2, __first1))
5255 ++__first2;
5256 else
5257 {
5258 *__result = *__first1;
5259 ++__first1;
5260 ++__first2;
5261 ++__result;
5262 }
5263 return __result;
5264 }
5265
5266 /**
5267 * @brief Return the intersection of two sorted ranges.
5268 * @ingroup set_algorithms
5269 * @param __first1 Start of first range.
5270 * @param __last1 End of first range.
5271 * @param __first2 Start of second range.
5272 * @param __last2 End of second range.
5273 * @param __result Start of output range.
5274 * @return End of the output range.
5275 * @ingroup set_algorithms
5276 *
5277 * This operation iterates over both ranges, copying elements present in
5278 * both ranges in order to the output range. Iterators increment for each
5279 * range. When the current element of one range is less than the other,
5280 * that iterator advances. If an element is contained in both ranges, the
5281 * element from the first range is copied and both ranges advance. The
5282 * output range may not overlap either input range.
5283 */
5284 template<typename _InputIterator1, typename _InputIterator2,
5285 typename _OutputIterator>
5286 _GLIBCXX20_CONSTEXPR
5287 inline _OutputIterator
5288 set_intersection(_InputIterator1 __first1, _InputIterator1 __last1,
5289 _InputIterator2 __first2, _InputIterator2 __last2,
5290 _OutputIterator __result)
5291 {
5292 // concept requirements
5293 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
5294 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
5295 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
5296 typename iterator_traits<_InputIterator1>::value_type>)
5297 __glibcxx_function_requires(_LessThanOpConcept<
5298 typename iterator_traits<_InputIterator1>::value_type,
5299 typename iterator_traits<_InputIterator2>::value_type>)
5300 __glibcxx_function_requires(_LessThanOpConcept<
5301 typename iterator_traits<_InputIterator2>::value_type,
5302 typename iterator_traits<_InputIterator1>::value_type>)
5303 __glibcxx_requires_sorted_set(__first1, __last1, __first2);
5304 __glibcxx_requires_sorted_set(__first2, __last2, __first1);
5305 __glibcxx_requires_irreflexive2(__first1, __last1);
5306 __glibcxx_requires_irreflexive2(__first2, __last2);
5307
5308 return _GLIBCXX_STD_Astd::__set_intersection(__first1, __last1,
5309 __first2, __last2, __result,
5310 __gnu_cxx::__ops::__iter_less_iter());
5311 }
5312
5313 /**
5314 * @brief Return the intersection of two sorted ranges using comparison
5315 * functor.
5316 * @ingroup set_algorithms
5317 * @param __first1 Start of first range.
5318 * @param __last1 End of first range.
5319 * @param __first2 Start of second range.
5320 * @param __last2 End of second range.
5321 * @param __result Start of output range.
5322 * @param __comp The comparison functor.
5323 * @return End of the output range.
5324 * @ingroup set_algorithms
5325 *
5326 * This operation iterates over both ranges, copying elements present in
5327 * both ranges in order to the output range. Iterators increment for each
5328 * range. When the current element of one range is less than the other
5329 * according to @p __comp, that iterator advances. If an element is
5330 * contained in both ranges according to @p __comp, the element from the
5331 * first range is copied and both ranges advance. The output range may not
5332 * overlap either input range.
5333 */
5334 template<typename _InputIterator1, typename _InputIterator2,
5335 typename _OutputIterator, typename _Compare>
5336 _GLIBCXX20_CONSTEXPR
5337 inline _OutputIterator
5338 set_intersection(_InputIterator1 __first1, _InputIterator1 __last1,
5339 _InputIterator2 __first2, _InputIterator2 __last2,
5340 _OutputIterator __result, _Compare __comp)
5341 {
5342 // concept requirements
5343 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
5344 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
5345 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
5346 typename iterator_traits<_InputIterator1>::value_type>)
5347 __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
5348 typename iterator_traits<_InputIterator1>::value_type,
5349 typename iterator_traits<_InputIterator2>::value_type>)
5350 __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
5351 typename iterator_traits<_InputIterator2>::value_type,
5352 typename iterator_traits<_InputIterator1>::value_type>)
5353 __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp);
5354 __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp);
5355 __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp);
5356 __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp);
5357
5358 return _GLIBCXX_STD_Astd::__set_intersection(__first1, __last1,
5359 __first2, __last2, __result,
5360 __gnu_cxx::__ops::__iter_comp_iter(__comp));
5361 }
5362
5363 template<typename _InputIterator1, typename _InputIterator2,
5364 typename _OutputIterator,
5365 typename _Compare>
5366 _GLIBCXX20_CONSTEXPR
5367 _OutputIterator
5368 __set_difference(_InputIterator1 __first1, _InputIterator1 __last1,
5369 _InputIterator2 __first2, _InputIterator2 __last2,
5370 _OutputIterator __result, _Compare __comp)
5371 {
5372 while (__first1 != __last1 && __first2 != __last2)
5373 if (__comp(__first1, __first2))
5374 {
5375 *__result = *__first1;
5376 ++__first1;
5377 ++__result;
5378 }
5379 else if (__comp(__first2, __first1))
5380 ++__first2;
5381 else
5382 {
5383 ++__first1;
5384 ++__first2;
5385 }
5386 return std::copy(__first1, __last1, __result);
5387 }
5388
5389 /**
5390 * @brief Return the difference of two sorted ranges.
5391 * @ingroup set_algorithms
5392 * @param __first1 Start of first range.
5393 * @param __last1 End of first range.
5394 * @param __first2 Start of second range.
5395 * @param __last2 End of second range.
5396 * @param __result Start of output range.
5397 * @return End of the output range.
5398 * @ingroup set_algorithms
5399 *
5400 * This operation iterates over both ranges, copying elements present in
5401 * the first range but not the second in order to the output range.
5402 * Iterators increment for each range. When the current element of the
5403 * first range is less than the second, that element is copied and the
5404 * iterator advances. If the current element of the second range is less,
5405 * the iterator advances, but no element is copied. If an element is
5406 * contained in both ranges, no elements are copied and both ranges
5407 * advance. The output range may not overlap either input range.
5408 */
5409 template<typename _InputIterator1, typename _InputIterator2,
5410 typename _OutputIterator>
5411 _GLIBCXX20_CONSTEXPR
5412 inline _OutputIterator
5413 set_difference(_InputIterator1 __first1, _InputIterator1 __last1,
5414 _InputIterator2 __first2, _InputIterator2 __last2,
5415 _OutputIterator __result)
5416 {
5417 // concept requirements
5418 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
5419 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
5420 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
5421 typename iterator_traits<_InputIterator1>::value_type>)
5422 __glibcxx_function_requires(_LessThanOpConcept<
5423 typename iterator_traits<_InputIterator1>::value_type,
5424 typename iterator_traits<_InputIterator2>::value_type>)
5425 __glibcxx_function_requires(_LessThanOpConcept<
5426 typename iterator_traits<_InputIterator2>::value_type,
5427 typename iterator_traits<_InputIterator1>::value_type>)
5428 __glibcxx_requires_sorted_set(__first1, __last1, __first2);
5429 __glibcxx_requires_sorted_set(__first2, __last2, __first1);
5430 __glibcxx_requires_irreflexive2(__first1, __last1);
5431 __glibcxx_requires_irreflexive2(__first2, __last2);
5432
5433 return _GLIBCXX_STD_Astd::__set_difference(__first1, __last1,
5434 __first2, __last2, __result,
5435 __gnu_cxx::__ops::__iter_less_iter());
5436 }
5437
5438 /**
5439 * @brief Return the difference of two sorted ranges using comparison
5440 * functor.
5441 * @ingroup set_algorithms
5442 * @param __first1 Start of first range.
5443 * @param __last1 End of first range.
5444 * @param __first2 Start of second range.
5445 * @param __last2 End of second range.
5446 * @param __result Start of output range.
5447 * @param __comp The comparison functor.
5448 * @return End of the output range.
5449 * @ingroup set_algorithms
5450 *
5451 * This operation iterates over both ranges, copying elements present in
5452 * the first range but not the second in order to the output range.
5453 * Iterators increment for each range. When the current element of the
5454 * first range is less than the second according to @p __comp, that element
5455 * is copied and the iterator advances. If the current element of the
5456 * second range is less, no element is copied and the iterator advances.
5457 * If an element is contained in both ranges according to @p __comp, no
5458 * elements are copied and both ranges advance. The output range may not
5459 * overlap either input range.
5460 */
5461 template<typename _InputIterator1, typename _InputIterator2,
5462 typename _OutputIterator, typename _Compare>
5463 _GLIBCXX20_CONSTEXPR
5464 inline _OutputIterator
5465 set_difference(_InputIterator1 __first1, _InputIterator1 __last1,
5466 _InputIterator2 __first2, _InputIterator2 __last2,
5467 _OutputIterator __result, _Compare __comp)
5468 {
5469 // concept requirements
5470 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
5471 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
5472 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
5473 typename iterator_traits<_InputIterator1>::value_type>)
5474 __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
5475 typename iterator_traits<_InputIterator1>::value_type,
5476 typename iterator_traits<_InputIterator2>::value_type>)
5477 __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
5478 typename iterator_traits<_InputIterator2>::value_type,
5479 typename iterator_traits<_InputIterator1>::value_type>)
5480 __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp);
5481 __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp);
5482 __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp);
5483 __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp);
5484
5485 return _GLIBCXX_STD_Astd::__set_difference(__first1, __last1,
5486 __first2, __last2, __result,
5487 __gnu_cxx::__ops::__iter_comp_iter(__comp));
5488 }
5489
5490 template<typename _InputIterator1, typename _InputIterator2,
5491 typename _OutputIterator,
5492 typename _Compare>
5493 _GLIBCXX20_CONSTEXPR
5494 _OutputIterator
5495 __set_symmetric_difference(_InputIterator1 __first1,
5496 _InputIterator1 __last1,
5497 _InputIterator2 __first2,
5498 _InputIterator2 __last2,
5499 _OutputIterator __result,
5500 _Compare __comp)
5501 {
5502 while (__first1 != __last1 && __first2 != __last2)
5503 if (__comp(__first1, __first2))
5504 {
5505 *__result = *__first1;
5506 ++__first1;
5507 ++__result;
5508 }
5509 else if (__comp(__first2, __first1))
5510 {
5511 *__result = *__first2;
5512 ++__first2;
5513 ++__result;
5514 }
5515 else
5516 {
5517 ++__first1;
5518 ++__first2;
5519 }
5520 return std::copy(__first2, __last2,
5521 std::copy(__first1, __last1, __result));
5522 }
5523
5524 /**
5525 * @brief Return the symmetric difference of two sorted ranges.
5526 * @ingroup set_algorithms
5527 * @param __first1 Start of first range.
5528 * @param __last1 End of first range.
5529 * @param __first2 Start of second range.
5530 * @param __last2 End of second range.
5531 * @param __result Start of output range.
5532 * @return End of the output range.
5533 * @ingroup set_algorithms
5534 *
5535 * This operation iterates over both ranges, copying elements present in
5536 * one range but not the other in order to the output range. Iterators
5537 * increment for each range. When the current element of one range is less
5538 * than the other, that element is copied and the iterator advances. If an
5539 * element is contained in both ranges, no elements are copied and both
5540 * ranges advance. The output range may not overlap either input range.
5541 */
5542 template<typename _InputIterator1, typename _InputIterator2,
5543 typename _OutputIterator>
5544 _GLIBCXX20_CONSTEXPR
5545 inline _OutputIterator
5546 set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1,
5547 _InputIterator2 __first2, _InputIterator2 __last2,
5548 _OutputIterator __result)
5549 {
5550 // concept requirements
5551 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
5552 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
5553 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
5554 typename iterator_traits<_InputIterator1>::value_type>)
5555 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
5556 typename iterator_traits<_InputIterator2>::value_type>)
5557 __glibcxx_function_requires(_LessThanOpConcept<
5558 typename iterator_traits<_InputIterator1>::value_type,
5559 typename iterator_traits<_InputIterator2>::value_type>)
5560 __glibcxx_function_requires(_LessThanOpConcept<
5561 typename iterator_traits<_InputIterator2>::value_type,
5562 typename iterator_traits<_InputIterator1>::value_type>)
5563 __glibcxx_requires_sorted_set(__first1, __last1, __first2);
5564 __glibcxx_requires_sorted_set(__first2, __last2, __first1);
5565 __glibcxx_requires_irreflexive2(__first1, __last1);
5566 __glibcxx_requires_irreflexive2(__first2, __last2);
5567
5568 return _GLIBCXX_STD_Astd::__set_symmetric_difference(__first1, __last1,
5569 __first2, __last2, __result,
5570 __gnu_cxx::__ops::__iter_less_iter());
5571 }
5572
5573 /**
5574 * @brief Return the symmetric difference of two sorted ranges using
5575 * comparison functor.
5576 * @ingroup set_algorithms
5577 * @param __first1 Start of first range.
5578 * @param __last1 End of first range.
5579 * @param __first2 Start of second range.
5580 * @param __last2 End of second range.
5581 * @param __result Start of output range.
5582 * @param __comp The comparison functor.
5583 * @return End of the output range.
5584 * @ingroup set_algorithms
5585 *
5586 * This operation iterates over both ranges, copying elements present in
5587 * one range but not the other in order to the output range. Iterators
5588 * increment for each range. When the current element of one range is less
5589 * than the other according to @p comp, that element is copied and the
5590 * iterator advances. If an element is contained in both ranges according
5591 * to @p __comp, no elements are copied and both ranges advance. The output
5592 * range may not overlap either input range.
5593 */
5594 template<typename _InputIterator1, typename _InputIterator2,
5595 typename _OutputIterator, typename _Compare>
5596 _GLIBCXX20_CONSTEXPR
5597 inline _OutputIterator
5598 set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1,
5599 _InputIterator2 __first2, _InputIterator2 __last2,
5600 _OutputIterator __result,
5601 _Compare __comp)
5602 {
5603 // concept requirements
5604 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
5605 __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
5606 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
5607 typename iterator_traits<_InputIterator1>::value_type>)
5608 __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
5609 typename iterator_traits<_InputIterator2>::value_type>)
5610 __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
5611 typename iterator_traits<_InputIterator1>::value_type,
5612 typename iterator_traits<_InputIterator2>::value_type>)
5613 __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
5614 typename iterator_traits<_InputIterator2>::value_type,
5615 typename iterator_traits<_InputIterator1>::value_type>)
5616 __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp);
5617 __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp);
5618 __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp);
5619 __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp);
5620
5621 return _GLIBCXX_STD_Astd::__set_symmetric_difference(__first1, __last1,
5622 __first2, __last2, __result,
5623 __gnu_cxx::__ops::__iter_comp_iter(__comp));
5624 }
5625
5626 template<typename _ForwardIterator, typename _Compare>
5627 _GLIBCXX14_CONSTEXPRconstexpr
5628 _ForwardIterator
5629 __min_element(_ForwardIterator __first, _ForwardIterator __last,
5630 _Compare __comp)
5631 {
5632 if (__first == __last)
5633 return __first;
5634 _ForwardIterator __result = __first;
5635 while (++__first != __last)
5636 if (__comp(__first, __result))
5637 __result = __first;
5638 return __result;
5639 }
5640
5641 /**
5642 * @brief Return the minimum element in a range.
5643 * @ingroup sorting_algorithms
5644 * @param __first Start of range.
5645 * @param __last End of range.
5646 * @return Iterator referencing the first instance of the smallest value.
5647 */
5648 template<typename _ForwardIterator>
5649 _GLIBCXX14_CONSTEXPRconstexpr
5650 _ForwardIterator
5651 inline min_element(_ForwardIterator __first, _ForwardIterator __last)
5652 {
5653 // concept requirements
5654 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
5655 __glibcxx_function_requires(_LessThanComparableConcept<
5656 typename iterator_traits<_ForwardIterator>::value_type>)
5657 __glibcxx_requires_valid_range(__first, __last);
5658 __glibcxx_requires_irreflexive(__first, __last);
5659
5660 return _GLIBCXX_STD_Astd::__min_element(__first, __last,
5661 __gnu_cxx::__ops::__iter_less_iter());
5662 }
5663
5664 /**
5665 * @brief Return the minimum element in a range using comparison functor.
5666 * @ingroup sorting_algorithms
5667 * @param __first Start of range.
5668 * @param __last End of range.
5669 * @param __comp Comparison functor.
5670 * @return Iterator referencing the first instance of the smallest value
5671 * according to __comp.
5672 */
5673 template<typename _ForwardIterator, typename _Compare>
5674 _GLIBCXX14_CONSTEXPRconstexpr
5675 inline _ForwardIterator
5676 min_element(_ForwardIterator __first, _ForwardIterator __last,
5677 _Compare __comp)
5678 {
5679 // concept requirements
5680 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
5681 __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
5682 typename iterator_traits<_ForwardIterator>::value_type,
5683 typename iterator_traits<_ForwardIterator>::value_type>)
5684 __glibcxx_requires_valid_range(__first, __last);
5685 __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
5686
5687 return _GLIBCXX_STD_Astd::__min_element(__first, __last,
5688 __gnu_cxx::__ops::__iter_comp_iter(__comp));
5689 }
5690
5691 template<typename _ForwardIterator, typename _Compare>
5692 _GLIBCXX14_CONSTEXPRconstexpr
5693 _ForwardIterator
5694 __max_element(_ForwardIterator __first, _ForwardIterator __last,
5695 _Compare __comp)
5696 {
5697 if (__first == __last) return __first;
5698 _ForwardIterator __result = __first;
5699 while (++__first != __last)
5700 if (__comp(__result, __first))
5701 __result = __first;
5702 return __result;
5703 }
5704
5705 /**
5706 * @brief Return the maximum element in a range.
5707 * @ingroup sorting_algorithms
5708 * @param __first Start of range.
5709 * @param __last End of range.
5710 * @return Iterator referencing the first instance of the largest value.
5711 */
5712 template<typename _ForwardIterator>
5713 _GLIBCXX14_CONSTEXPRconstexpr
5714 inline _ForwardIterator
5715 max_element(_ForwardIterator __first, _ForwardIterator __last)
5716 {
5717 // concept requirements
5718 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
5719 __glibcxx_function_requires(_LessThanComparableConcept<
5720 typename iterator_traits<_ForwardIterator>::value_type>)
5721 __glibcxx_requires_valid_range(__first, __last);
5722 __glibcxx_requires_irreflexive(__first, __last);
5723
5724 return _GLIBCXX_STD_Astd::__max_element(__first, __last,
5725 __gnu_cxx::__ops::__iter_less_iter());
5726 }
5727
5728 /**
5729 * @brief Return the maximum element in a range using comparison functor.
5730 * @ingroup sorting_algorithms
5731 * @param __first Start of range.
5732 * @param __last End of range.
5733 * @param __comp Comparison functor.
5734 * @return Iterator referencing the first instance of the largest value
5735 * according to __comp.
5736 */
5737 template<typename _ForwardIterator, typename _Compare>
5738 _GLIBCXX14_CONSTEXPRconstexpr
5739 inline _ForwardIterator
5740 max_element(_ForwardIterator __first, _ForwardIterator __last,
5741 _Compare __comp)
5742 {
5743 // concept requirements
5744 __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
5745 __glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
5746 typename iterator_traits<_ForwardIterator>::value_type,
5747 typename iterator_traits<_ForwardIterator>::value_type>)
5748 __glibcxx_requires_valid_range(__first, __last);
5749 __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
5750
5751 return _GLIBCXX_STD_Astd::__max_element(__first, __last,
5752 __gnu_cxx::__ops::__iter_comp_iter(__comp));
5753 }
5754
5755#if __cplusplus201402L >= 201402L
5756 /// Reservoir sampling algorithm.
5757 template<typename _InputIterator, typename _RandomAccessIterator,
5758 typename _Size, typename _UniformRandomBitGenerator>
5759 _RandomAccessIterator
5760 __sample(_InputIterator __first, _InputIterator __last, input_iterator_tag,
5761 _RandomAccessIterator __out, random_access_iterator_tag,
5762 _Size __n, _UniformRandomBitGenerator&& __g)
5763 {
5764 using __distrib_type = uniform_int_distribution<_Size>;
5765 using __param_type = typename __distrib_type::param_type;
5766 __distrib_type __d{};
5767 _Size __sample_sz = 0;
5768 while (__first != __last && __sample_sz != __n)
5769 {
5770 __out[__sample_sz++] = *__first;
5771 ++__first;
5772 }
5773 for (auto __pop_sz = __sample_sz; __first != __last;
5774 ++__first, (void) ++__pop_sz)
5775 {
5776 const auto __k = __d(__g, __param_type{0, __pop_sz});
5777 if (__k < __n)
5778 __out[__k] = *__first;
5779 }
5780 return __out + __sample_sz;
5781 }
5782
5783 /// Selection sampling algorithm.
5784 template<typename _ForwardIterator, typename _OutputIterator, typename _Cat,
5785 typename _Size, typename _UniformRandomBitGenerator>
5786 _OutputIterator
5787 __sample(_ForwardIterator __first, _ForwardIterator __last,
5788 forward_iterator_tag,
5789 _OutputIterator __out, _Cat,
5790 _Size __n, _UniformRandomBitGenerator&& __g)
5791 {
5792 using __distrib_type = uniform_int_distribution<_Size>;
5793 using __param_type = typename __distrib_type::param_type;
5794 using _USize = make_unsigned_t<_Size>;
5795 using _Gen = remove_reference_t<_UniformRandomBitGenerator>;
5796 using __uc_type = common_type_t<typename _Gen::result_type, _USize>;
5797
5798 __distrib_type __d{};
5799 _Size __unsampled_sz = std::distance(__first, __last);
5800 __n = std::min(__n, __unsampled_sz);
5801
5802 // If possible, we use __gen_two_uniform_ints to efficiently produce
5803 // two random numbers using a single distribution invocation:
5804
5805 const __uc_type __urngrange = __g.max() - __g.min();
5806 if (__urngrange / __uc_type(__unsampled_sz) >= __uc_type(__unsampled_sz))
5807 // I.e. (__urngrange >= __unsampled_sz * __unsampled_sz) but without
5808 // wrapping issues.
5809 {
5810 while (__n != 0 && __unsampled_sz >= 2)
5811 {
5812 const pair<_Size, _Size> __p =
5813 __gen_two_uniform_ints(__unsampled_sz, __unsampled_sz - 1, __g);
5814
5815 --__unsampled_sz;
5816 if (__p.first < __n)
5817 {
5818 *__out++ = *__first;
5819 --__n;
5820 }
5821
5822 ++__first;
5823
5824 if (__n == 0) break;
5825
5826 --__unsampled_sz;
5827 if (__p.second < __n)
5828 {
5829 *__out++ = *__first;
5830 --__n;
5831 }
5832
5833 ++__first;
5834 }
5835 }
5836
5837 // The loop above is otherwise equivalent to this one-at-a-time version:
5838
5839 for (; __n != 0; ++__first)
5840 if (__d(__g, __param_type{0, --__unsampled_sz}) < __n)
5841 {
5842 *__out++ = *__first;
5843 --__n;
5844 }
5845 return __out;
5846 }
5847
5848#if __cplusplus201402L > 201402L
5849#define __cpp_lib_sample 201603
5850 /// Take a random sample from a population.
5851 template<typename _PopulationIterator, typename _SampleIterator,
5852 typename _Distance, typename _UniformRandomBitGenerator>
5853 _SampleIterator
5854 sample(_PopulationIterator __first, _PopulationIterator __last,
5855 _SampleIterator __out, _Distance __n,
5856 _UniformRandomBitGenerator&& __g)
5857 {
5858 using __pop_cat = typename
5859 std::iterator_traits<_PopulationIterator>::iterator_category;
5860 using __samp_cat = typename
5861 std::iterator_traits<_SampleIterator>::iterator_category;
5862
5863 static_assert(
5864 __or_<is_convertible<__pop_cat, forward_iterator_tag>,
5865 is_convertible<__samp_cat, random_access_iterator_tag>>::value,
5866 "output range must use a RandomAccessIterator when input range"
5867 " does not meet the ForwardIterator requirements");
5868
5869 static_assert(is_integral<_Distance>::value,
5870 "sample size must be an integer type");
5871
5872 typename iterator_traits<_PopulationIterator>::difference_type __d = __n;
5873 return _GLIBCXX_STD_Astd::
5874 __sample(__first, __last, __pop_cat{}, __out, __samp_cat{}, __d,
5875 std::forward<_UniformRandomBitGenerator>(__g));
5876 }
5877#endif // C++17
5878#endif // C++14
5879
5880_GLIBCXX_END_NAMESPACE_ALGO
5881_GLIBCXX_END_NAMESPACE_VERSION
5882} // namespace std
5883
5884#endif /* _STL_ALGO_H */

/usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/bits/predefined_ops.h

1// Default predicates for internal use -*- C++ -*-
2
3// Copyright (C) 2013-2020 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file predefined_ops.h
26 * This is an internal header file, included by other library headers.
27 * You should not attempt to use it directly. @headername{algorithm}
28 */
29
30#ifndef _GLIBCXX_PREDEFINED_OPS_H1
31#define _GLIBCXX_PREDEFINED_OPS_H1 1
32
33namespace __gnu_cxx
34{
35namespace __ops
36{
37 struct _Iter_less_iter
38 {
39 template<typename _Iterator1, typename _Iterator2>
40 _GLIBCXX14_CONSTEXPRconstexpr
41 bool
42 operator()(_Iterator1 __it1, _Iterator2 __it2) const
43 { return *__it1 < *__it2; }
63
Use of zero-allocated memory
44 };
45
46 _GLIBCXX14_CONSTEXPRconstexpr
47 inline _Iter_less_iter
48 __iter_less_iter()
49 { return _Iter_less_iter(); }
50
51 struct _Iter_less_val
52 {
53#if __cplusplus201402L >= 201103L
54 constexpr _Iter_less_val() = default;
55#else
56 _Iter_less_val() { }
57#endif
58
59 _GLIBCXX20_CONSTEXPR
60 explicit
61 _Iter_less_val(_Iter_less_iter) { }
62
63 template<typename _Iterator, typename _Value>
64 _GLIBCXX20_CONSTEXPR
65 bool
66 operator()(_Iterator __it, _Value& __val) const
67 { return *__it < __val; }
68 };
69
70 _GLIBCXX20_CONSTEXPR
71 inline _Iter_less_val
72 __iter_less_val()
73 { return _Iter_less_val(); }
74
75 _GLIBCXX20_CONSTEXPR
76 inline _Iter_less_val
77 __iter_comp_val(_Iter_less_iter)
78 { return _Iter_less_val(); }
79
80 struct _Val_less_iter
81 {
82#if __cplusplus201402L >= 201103L
83 constexpr _Val_less_iter() = default;
84#else
85 _Val_less_iter() { }
86#endif
87
88 _GLIBCXX20_CONSTEXPR
89 explicit
90 _Val_less_iter(_Iter_less_iter) { }
91
92 template<typename _Value, typename _Iterator>
93 _GLIBCXX20_CONSTEXPR
94 bool
95 operator()(_Value& __val, _Iterator __it) const
96 { return __val < *__it; }
97 };
98
99 _GLIBCXX20_CONSTEXPR
100 inline _Val_less_iter
101 __val_less_iter()
102 { return _Val_less_iter(); }
103
104 _GLIBCXX20_CONSTEXPR
105 inline _Val_less_iter
106 __val_comp_iter(_Iter_less_iter)
107 { return _Val_less_iter(); }
108
109 struct _Iter_equal_to_iter
110 {
111 template<typename _Iterator1, typename _Iterator2>
112 _GLIBCXX20_CONSTEXPR
113 bool
114 operator()(_Iterator1 __it1, _Iterator2 __it2) const
115 { return *__it1 == *__it2; }
116 };
117
118 _GLIBCXX20_CONSTEXPR
119 inline _Iter_equal_to_iter
120 __iter_equal_to_iter()
121 { return _Iter_equal_to_iter(); }
122
123 struct _Iter_equal_to_val
124 {
125 template<typename _Iterator, typename _Value>
126 _GLIBCXX20_CONSTEXPR
127 bool
128 operator()(_Iterator __it, _Value& __val) const
129 { return *__it == __val; }
130 };
131
132 _GLIBCXX20_CONSTEXPR
133 inline _Iter_equal_to_val
134 __iter_equal_to_val()
135 { return _Iter_equal_to_val(); }
136
137 _GLIBCXX20_CONSTEXPR
138 inline _Iter_equal_to_val
139 __iter_comp_val(_Iter_equal_to_iter)
140 { return _Iter_equal_to_val(); }
141
142 template<typename _Compare>
143 struct _Iter_comp_iter
144 {
145 _Compare _M_comp;
146
147 explicit _GLIBCXX14_CONSTEXPRconstexpr
148 _Iter_comp_iter(_Compare __comp)
149 : _M_comp(_GLIBCXX_MOVE(__comp)std::move(__comp))
150 { }
151
152 template<typename _Iterator1, typename _Iterator2>
153 _GLIBCXX14_CONSTEXPRconstexpr
154 bool
155 operator()(_Iterator1 __it1, _Iterator2 __it2)
156 { return bool(_M_comp(*__it1, *__it2)); }
157 };
158
159 template<typename _Compare>
160 _GLIBCXX14_CONSTEXPRconstexpr
161 inline _Iter_comp_iter<_Compare>
162 __iter_comp_iter(_Compare __comp)
163 { return _Iter_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)std::move(__comp)); }
164
165 template<typename _Compare>
166 struct _Iter_comp_val
167 {
168 _Compare _M_comp;
169
170 _GLIBCXX20_CONSTEXPR
171 explicit
172 _Iter_comp_val(_Compare __comp)
173 : _M_comp(_GLIBCXX_MOVE(__comp)std::move(__comp))
174 { }
175
176 _GLIBCXX20_CONSTEXPR
177 explicit
178 _Iter_comp_val(const _Iter_comp_iter<_Compare>& __comp)
179 : _M_comp(__comp._M_comp)
180 { }
181
182#if __cplusplus201402L >= 201103L
183 _GLIBCXX20_CONSTEXPR
184 explicit
185 _Iter_comp_val(_Iter_comp_iter<_Compare>&& __comp)
186 : _M_comp(std::move(__comp._M_comp))
187 { }
188#endif
189
190 template<typename _Iterator, typename _Value>
191 _GLIBCXX20_CONSTEXPR
192 bool
193 operator()(_Iterator __it, _Value& __val)
194 { return bool(_M_comp(*__it, __val)); }
195 };
196
197 template<typename _Compare>
198 _GLIBCXX20_CONSTEXPR
199 inline _Iter_comp_val<_Compare>
200 __iter_comp_val(_Compare __comp)
201 { return _Iter_comp_val<_Compare>(_GLIBCXX_MOVE(__comp)std::move(__comp)); }
202
203 template<typename _Compare>
204 _GLIBCXX20_CONSTEXPR
205 inline _Iter_comp_val<_Compare>
206 __iter_comp_val(_Iter_comp_iter<_Compare> __comp)
207 { return _Iter_comp_val<_Compare>(_GLIBCXX_MOVE(__comp)std::move(__comp)); }
208
209 template<typename _Compare>
210 struct _Val_comp_iter
211 {
212 _Compare _M_comp;
213
214 _GLIBCXX20_CONSTEXPR
215 explicit
216 _Val_comp_iter(_Compare __comp)
217 : _M_comp(_GLIBCXX_MOVE(__comp)std::move(__comp))
218 { }
219
220 _GLIBCXX20_CONSTEXPR
221 explicit
222 _Val_comp_iter(const _Iter_comp_iter<_Compare>& __comp)
223 : _M_comp(__comp._M_comp)
224 { }
225
226#if __cplusplus201402L >= 201103L
227 _GLIBCXX20_CONSTEXPR
228 explicit
229 _Val_comp_iter(_Iter_comp_iter<_Compare>&& __comp)
230 : _M_comp(std::move(__comp._M_comp))
231 { }
232#endif
233
234 template<typename _Value, typename _Iterator>
235 _GLIBCXX20_CONSTEXPR
236 bool
237 operator()(_Value& __val, _Iterator __it)
238 { return bool(_M_comp(__val, *__it)); }
239 };
240
241 template<typename _Compare>
242 _GLIBCXX20_CONSTEXPR
243 inline _Val_comp_iter<_Compare>
244 __val_comp_iter(_Compare __comp)
245 { return _Val_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)std::move(__comp)); }
246
247 template<typename _Compare>
248 _GLIBCXX20_CONSTEXPR
249 inline _Val_comp_iter<_Compare>
250 __val_comp_iter(_Iter_comp_iter<_Compare> __comp)
251 { return _Val_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)std::move(__comp)); }
252
253 template<typename _Value>
254 struct _Iter_equals_val
255 {
256 _Value& _M_value;
257
258 _GLIBCXX20_CONSTEXPR
259 explicit
260 _Iter_equals_val(_Value& __value)
261 : _M_value(__value)
262 { }
263
264 template<typename _Iterator>
265 _GLIBCXX20_CONSTEXPR
266 bool
267 operator()(_Iterator __it)
268 { return *__it == _M_value; }
269 };
270
271 template<typename _Value>
272 _GLIBCXX20_CONSTEXPR
273 inline _Iter_equals_val<_Value>
274 __iter_equals_val(_Value& __val)
275 { return _Iter_equals_val<_Value>(__val); }
276
277 template<typename _Iterator1>
278 struct _Iter_equals_iter
279 {
280 _Iterator1 _M_it1;
281
282 _GLIBCXX20_CONSTEXPR
283 explicit
284 _Iter_equals_iter(_Iterator1 __it1)
285 : _M_it1(__it1)
286 { }
287
288 template<typename _Iterator2>
289 _GLIBCXX20_CONSTEXPR
290 bool
291 operator()(_Iterator2 __it2)
292 { return *__it2 == *_M_it1; }
293 };
294
295 template<typename _Iterator>
296 _GLIBCXX20_CONSTEXPR
297 inline _Iter_equals_iter<_Iterator>
298 __iter_comp_iter(_Iter_equal_to_iter, _Iterator __it)
299 { return _Iter_equals_iter<_Iterator>(__it); }
300
301 template<typename _Predicate>
302 struct _Iter_pred
303 {
304 _Predicate _M_pred;
305
306 _GLIBCXX20_CONSTEXPR
307 explicit
308 _Iter_pred(_Predicate __pred)
309 : _M_pred(_GLIBCXX_MOVE(__pred)std::move(__pred))
310 { }
311
312 template<typename _Iterator>
313 _GLIBCXX20_CONSTEXPR
314 bool
315 operator()(_Iterator __it)
316 { return bool(_M_pred(*__it)); }
317 };
318
319 template<typename _Predicate>
320 _GLIBCXX20_CONSTEXPR
321 inline _Iter_pred<_Predicate>
322 __pred_iter(_Predicate __pred)
323 { return _Iter_pred<_Predicate>(_GLIBCXX_MOVE(__pred)std::move(__pred)); }
324
325 template<typename _Compare, typename _Value>
326 struct _Iter_comp_to_val
327 {
328 _Compare _M_comp;
329 _Value& _M_value;
330
331 _GLIBCXX20_CONSTEXPR
332 _Iter_comp_to_val(_Compare __comp, _Value& __value)
333 : _M_comp(_GLIBCXX_MOVE(__comp)std::move(__comp)), _M_value(__value)
334 { }
335
336 template<typename _Iterator>
337 _GLIBCXX20_CONSTEXPR
338 bool
339 operator()(_Iterator __it)
340 { return bool(_M_comp(*__it, _M_value)); }
341 };
342
343 template<typename _Compare, typename _Value>
344 _Iter_comp_to_val<_Compare, _Value>
345 _GLIBCXX20_CONSTEXPR
346 __iter_comp_val(_Compare __comp, _Value &__val)
347 {
348 return _Iter_comp_to_val<_Compare, _Value>(_GLIBCXX_MOVE(__comp)std::move(__comp), __val);
349 }
350
351 template<typename _Compare, typename _Iterator1>
352 struct _Iter_comp_to_iter
353 {
354 _Compare _M_comp;
355 _Iterator1 _M_it1;
356
357 _GLIBCXX20_CONSTEXPR
358 _Iter_comp_to_iter(_Compare __comp, _Iterator1 __it1)
359 : _M_comp(_GLIBCXX_MOVE(__comp)std::move(__comp)), _M_it1(__it1)
360 { }
361
362 template<typename _Iterator2>
363 _GLIBCXX20_CONSTEXPR
364 bool
365 operator()(_Iterator2 __it2)
366 { return bool(_M_comp(*__it2, *_M_it1)); }
367 };
368
369 template<typename _Compare, typename _Iterator>
370 _GLIBCXX20_CONSTEXPR
371 inline _Iter_comp_to_iter<_Compare, _Iterator>
372 __iter_comp_iter(_Iter_comp_iter<_Compare> __comp, _Iterator __it)
373 {
374 return _Iter_comp_to_iter<_Compare, _Iterator>(
375 _GLIBCXX_MOVE(__comp._M_comp)std::move(__comp._M_comp), __it);
376 }
377
378 template<typename _Predicate>
379 struct _Iter_negate
380 {
381 _Predicate _M_pred;
382
383 _GLIBCXX20_CONSTEXPR
384 explicit
385 _Iter_negate(_Predicate __pred)
386 : _M_pred(_GLIBCXX_MOVE(__pred)std::move(__pred))
387 { }
388
389 template<typename _Iterator>
390 _GLIBCXX20_CONSTEXPR
391 bool
392 operator()(_Iterator __it)
393 { return !bool(_M_pred(*__it)); }
394 };
395
396 template<typename _Predicate>
397 _GLIBCXX20_CONSTEXPR
398 inline _Iter_negate<_Predicate>
399 __negate(_Iter_pred<_Predicate> __pred)
400 { return _Iter_negate<_Predicate>(_GLIBCXX_MOVE(__pred._M_pred)std::move(__pred._M_pred)); }
401
402} // namespace __ops
403} // namespace __gnu_cxx
404
405#endif