1 | /* $Id: CoinOslC.h 1374 2011-01-04 00:08:33Z lou $ */ |
2 | #ifndef COIN_OSL_C_INCLUDE |
3 | /* |
4 | Copyright (C) 1987, 2009, International Business Machines Corporation |
5 | and others. All Rights Reserved. |
6 | |
7 | This code is licensed under the terms of the Eclipse Public License (EPL). |
8 | */ |
9 | #define COIN_OSL_C_INCLUDE |
10 | |
11 | #ifndef CLP_OSL |
12 | #define CLP_OSL 0 |
13 | #endif |
14 | #define C_EKK_GO_SPARSE 200 |
15 | |
16 | #ifdef HAVE_ENDIAN_H |
17 | #include <endian.h> |
18 | #if __BYTE_ORDER == __LITTLE_ENDIAN |
19 | #define INTEL |
20 | #endif |
21 | #endif |
22 | |
23 | #include <math.h> |
24 | #include <string.h> |
25 | #include <stdio.h> |
26 | #include <stdlib.h> |
27 | |
28 | #define SPARSE_UPDATE |
29 | #define NO_SHIFT |
30 | #include "CoinHelperFunctions.hpp" |
31 | |
32 | #include <stddef.h> |
33 | #ifdef __cplusplus |
34 | extern "C" { |
35 | #endif |
36 | |
37 | int c_ekkbtrn(const EKKfactinfo *fact, |
38 | double *dwork1, |
39 | int * mpt,int first_nonzero); |
40 | int c_ekkbtrn_ipivrw(const EKKfactinfo *fact, |
41 | double *dwork1, |
42 | int * mpt, int ipivrw,int * spare); |
43 | |
44 | int c_ekketsj(/*const*/ EKKfactinfo *fact, |
45 | double *dwork1, |
46 | int *mpt2, double dalpha, int orig_nincol, |
47 | int npivot, int *nuspikp, |
48 | const int ipivrw, int * spare); |
49 | int c_ekkftrn(const EKKfactinfo *fact, |
50 | double *dwork1, |
51 | double * dpermu,int * mpt, int numberNonZero); |
52 | |
53 | int c_ekkftrn_ft(EKKfactinfo *fact, |
54 | double *dwork1, int *mpt, int *nincolp); |
55 | void c_ekkftrn2(EKKfactinfo *fact, double *dwork1, |
56 | double * dpermu1,int * mpt1, int *nincolp, |
57 | double *dwork1_ft, int *mpt_ft, int *nincolp_ft); |
58 | |
59 | int c_ekklfct(EKKfactinfo *fact); |
60 | int c_ekkslcf(const EKKfactinfo *fact); |
61 | inline void c_ekkscpy(int n, const int *marr1,int *marr2) |
62 | { CoinMemcpyN(marr1,n,marr2);} |
63 | inline void c_ekkdcpy(int n, const double *marr1,double *marr2) |
64 | { CoinMemcpyN(marr1,n,marr2);} |
65 | int c_ekk_IsSet(const int * array,int bit); |
66 | void c_ekk_Set(int * array,int bit); |
67 | void c_ekk_Unset(int * array,int bit); |
68 | |
69 | void c_ekkzero(int length, int n, void * array); |
70 | inline void c_ekkdzero(int n, double *marray) |
71 | {CoinZeroN(marray,n);} |
72 | inline void c_ekkizero(int n, int *marray) |
73 | {CoinZeroN(marray,n);} |
74 | inline void c_ekkczero(int n, char *marray) |
75 | {CoinZeroN(marray,n);} |
76 | #ifdef __cplusplus |
77 | } |
78 | #endif |
79 | |
80 | #define c_ekkscpy_0_1(s,ival,array) CoinFillN(array,s,ival) |
81 | #define c_ekks1cpy( n,marr1,marr2) CoinMemcpyN(marr1,n, marr2) |
82 | void clp_setup_pointers(EKKfactinfo * fact); |
83 | void clp_memory(int type); |
84 | double * clp_double(int number_entries); |
85 | int * clp_int(int number_entries); |
86 | void * clp_malloc(int number_entries); |
87 | void clp_free(void * oldArray); |
88 | |
89 | #define SLACK_VALUE -1.0 |
90 | #define C_EKK_REMOVE_LINK(hpiv,hin,link,ipivot) \ |
91 | { \ |
92 | int ipre = link[ipivot].pre; \ |
93 | int isuc = link[ipivot].suc; \ |
94 | if (ipre > 0) { \ |
95 | link[ipre].suc = isuc; \ |
96 | } \ |
97 | if (ipre <= 0) { \ |
98 | hpiv[hin[ipivot]] = isuc; \ |
99 | } \ |
100 | if (isuc > 0) { \ |
101 | link[isuc].pre = ipre; \ |
102 | } \ |
103 | } |
104 | |
105 | #define C_EKK_ADD_LINK(hpiv,nzi,link, npr) \ |
106 | { \ |
107 | int ifiri = hpiv[nzi]; \ |
108 | hpiv[nzi] = npr; \ |
109 | link[npr].suc = ifiri; \ |
110 | link[npr].pre = 0; \ |
111 | if (ifiri != 0) { \ |
112 | link[ifiri].pre = npr; \ |
113 | } \ |
114 | } |
115 | #include <assert.h> |
116 | #ifdef NO_SHIFT |
117 | |
118 | #define SHIFT_INDEX(limit) (limit) |
119 | #define UNSHIFT_INDEX(limit) (limit) |
120 | #define SHIFT_REF(arr,ind) (arr)[ind] |
121 | |
122 | #else |
123 | |
124 | #define SHIFT_INDEX(limit) ((limit)<<3) |
125 | #define UNSHIFT_INDEX(limit) ((unsigned int)(limit)>>3) |
126 | #define SHIFT_REF(arr,ind) (*(double*)((char*)(arr) + (ind))) |
127 | |
128 | #endif |
129 | |
130 | #ifdef INTEL |
131 | #define NOT_ZERO(x) (((*((reinterpret_cast<unsigned char *>(&x))+7)) & 0x7F) != 0) |
132 | #else |
133 | #define NOT_ZERO(x) ((x) != 0.0) |
134 | #endif |
135 | |
136 | #define SWAP(type,_x,_y) { type _tmp = (_x); (_x) = (_y); (_y) = _tmp;} |
137 | |
138 | #define UNROLL_LOOP_BODY1(code) \ |
139 | {{code}} |
140 | #define UNROLL_LOOP_BODY2(code) \ |
141 | {{code} {code}} |
142 | #define UNROLL_LOOP_BODY4(code) \ |
143 | {{code} {code} {code} {code}} |
144 | #endif |
145 | #ifdef COIN_OSL_CMFC |
146 | /* Return codes in IRTCOD/IRTCOD are */ |
147 | /* 4: numerical problems */ |
148 | /* 5: not enough space in row file */ |
149 | /* 6: not enough space in column file */ |
150 | /* 23: system error at label 320 */ |
151 | { |
152 | #if 1 |
153 | int *hcoli = fact->xecadr; |
154 | double *dluval = fact->xeeadr; |
155 | double *dvalpv = fact->kw3adr; |
156 | int *mrstrt = fact->xrsadr; |
157 | int *hrowi = fact->xeradr; |
158 | int *mcstrt = fact->xcsadr; |
159 | int *hinrow = fact->xrnadr; |
160 | int *hincol = fact->xcnadr; |
161 | int *hpivro = fact->krpadr; |
162 | int *hpivco = fact->kcpadr; |
163 | #endif |
164 | int nnentl = fact->nnentl; |
165 | int nnentu = fact->nnentu; |
166 | int kmxeta = fact->kmxeta; |
167 | int xnewro = *xnewrop; |
168 | int ncompactions = *ncompactionsp; |
169 | |
170 | MACTION_T *maction = reinterpret_cast<MACTION_T*>(maction_void); |
171 | |
172 | int i, j, k; |
173 | double d1; |
174 | int j1, j2; |
175 | int jj, kk, kr, nz, jj1, jj2, kce, kcs, kqq, npr; |
176 | int fill, naft; |
177 | int enpr; |
178 | int nres, npre; |
179 | int knpr, irow, iadd32, ibase; |
180 | double pivot; |
181 | int count, nznpr; |
182 | int nlast, epivr1; |
183 | int kipis; |
184 | double dpivx; |
185 | int kipie, kcpiv, knprs, knpre; |
186 | bool cancel; |
187 | double multip, elemnt; |
188 | int ipivot, jpivot, epivro, epivco, lstart, ifdens, nfirst; |
189 | int nzpivj, kfill, kstart; |
190 | int nmove, ileft; |
191 | #ifndef C_EKKCMFY |
192 | int iput, nspare; |
193 | int noRoomForDense=0; |
194 | int if_sparse_update=fact->if_sparse_update; |
195 | #endif |
196 | int irtcod = 0; |
197 | const int nrow = fact->nrow; |
198 | |
199 | /* Parameter adjustments */ |
200 | --maction; |
201 | |
202 | /* Function Body */ |
203 | lstart = nnetas - nnentl + 1; |
204 | for (i = lstart; i <= nnetas; ++i) { |
205 | hrowi[i] = SHIFT_INDEX(hcoli[i]); |
206 | } |
207 | ifdens = 0; |
208 | |
209 | for (i = 1; i <= nrow; ++i) { |
210 | maction[i] = 0; |
211 | mwork[i].pre = i - 1; |
212 | mwork[i].suc = i + 1; |
213 | } |
214 | |
215 | iadd32 = 0; |
216 | nlast = nrow; |
217 | nfirst = 1; |
218 | mwork[1].pre = nrow; |
219 | mwork[nrow].suc = 1; |
220 | |
221 | for (count = 1; count <= nrow; ++count) { |
222 | |
223 | /* Pick column singletons */ |
224 | if (! (hpivco[1] <= 0)) { |
225 | int small_pivot = c_ekkcsin(fact, |
226 | rlink, clink, |
227 | nsingp); |
228 | |
229 | if (small_pivot) { |
230 | irtcod = 7; /* pivot too small */ |
231 | if (fact->invok >= 0) { |
232 | goto L1050; |
233 | } |
234 | } |
235 | if (fact->npivots >= nrow) { |
236 | goto L1050; |
237 | } |
238 | } |
239 | |
240 | /* Pick row singletons */ |
241 | if (! (hpivro[1] <= 0)) { |
242 | irtcod = c_ekkrsin(fact, |
243 | rlink, clink, |
244 | mwork,nfirst, |
245 | nsingp, |
246 | |
247 | &xnewco, &xnewro, |
248 | &nnentu, |
249 | &kmxeta, &ncompactions, |
250 | &nnentl); |
251 | if (irtcod != 0) { |
252 | if (irtcod < 0 || fact->invok >= 0) { |
253 | /* -5 */ |
254 | goto L1050; |
255 | } |
256 | /* ASSERT: irtcod == 7 - pivot too small */ |
257 | /* why don't we return with an error? */ |
258 | } |
259 | if (fact->npivots >= nrow) { |
260 | goto L1050; |
261 | } |
262 | lstart = nnetas - nnentl + 1; |
263 | } |
264 | |
265 | /* Find a pivot element */ |
266 | irtcod = c_ekkfpvt(fact, |
267 | rlink, clink, |
268 | nsingp, xrejctp, &ipivot, &jpivot); |
269 | if (irtcod != 0) { |
270 | /* irtcod == 10 */ |
271 | goto L1050; |
272 | } |
273 | /* Update list structures and prepare for numerical phase */ |
274 | c_ekkprpv(fact, rlink, clink, |
275 | *xrejctp, ipivot, jpivot); |
276 | |
277 | epivco = hincol[jpivot]; |
278 | ++fact->xnetal; |
279 | mcstrt[fact->xnetal] = lstart - 1; |
280 | hpivco[fact->xnetal] = ipivot; |
281 | epivro = hinrow[ipivot]; |
282 | epivr1 = epivro - 1; |
283 | kipis = mrstrt[ipivot]; |
284 | pivot = dluval[kipis]; |
285 | dpivx = 1. / pivot; |
286 | kipie = kipis + epivr1; |
287 | ++kipis; |
288 | #ifndef C_EKKCMFY |
289 | { |
290 | double size = nrow - fact->npivots; |
291 | if (size > GO_DENSE && (nnentu - fact->nuspike) * GO_DENSE_RATIO > size * size) { |
292 | /* say going to dense coding */ |
293 | if (*nsingp == 0) { |
294 | ifdens = 1; |
295 | } |
296 | } |
297 | } |
298 | #endif |
299 | /* copy the pivot row entries into dvalpv */ |
300 | /* the maction array tells us the index into dvalpv for a given row */ |
301 | /* the alternative would be using a large array of doubles */ |
302 | for (k = kipis; k <= kipie; ++k) { |
303 | irow = hcoli[k]; |
304 | dvalpv[k - kipis + 1] = dluval[k]; |
305 | maction[irow] = static_cast<MACTION_T>(k - kipis + 1); |
306 | } |
307 | |
308 | /* Loop over nonzeros in pivot column */ |
309 | kcpiv = mcstrt[jpivot] - 1; |
310 | for (nzpivj = 1; nzpivj <= epivco; ++nzpivj) { |
311 | ++kcpiv; |
312 | npr = hrowi[kcpiv]; |
313 | hrowi[kcpiv] = 0; /* zero out for possible compaction later on */ |
314 | |
315 | --hincol[jpivot]; |
316 | |
317 | ++mcstrt[jpivot]; |
318 | /* loop invariant: kcpiv == mcstrt[jpivot] - 1 */ |
319 | |
320 | --hinrow[npr]; |
321 | enpr = hinrow[npr]; |
322 | knprs = mrstrt[npr]; |
323 | knpre = knprs + enpr; |
324 | |
325 | /* Search for element to be eliminated */ |
326 | knpr = knprs; |
327 | while (1) { |
328 | UNROLL_LOOP_BODY4({ |
329 | if (jpivot == hcoli[knpr]) { |
330 | break; |
331 | } |
332 | knpr++; |
333 | }); |
334 | } |
335 | |
336 | multip = -dluval[knpr] * dpivx; |
337 | |
338 | /* swap last entry with pivot */ |
339 | dluval[knpr] = dluval[knpre]; |
340 | hcoli[knpr] = hcoli[knpre]; |
341 | --knpre; |
342 | |
343 | #if 1 |
344 | /* MONSTER_UNROLLED_CODE - see below */ |
345 | kfill = epivr1 - (knpre - knprs + 1); |
346 | nres = ((knpre - knprs + 1) & 1) + knprs; |
347 | cancel = false; |
348 | d1 = 1e33; |
349 | j1 = hcoli[nres]; |
350 | |
351 | if (nres != knprs) { |
352 | j = hcoli[knprs]; |
353 | if (maction[j] == 0) { |
354 | ++kfill; |
355 | } else { |
356 | jj = maction[j]; |
357 | maction[j] = static_cast<MACTION_T>(-maction[j]); |
358 | dluval[knprs] += multip * dvalpv[jj]; |
359 | d1 = fabs(dluval[knprs]); |
360 | } |
361 | } |
362 | j2 = hcoli[nres + 1]; |
363 | jj1 = maction[j1]; |
364 | for (kr = nres; kr < knpre; kr += 2) { |
365 | jj2 = maction[j2]; |
366 | if (jj1 == 0) { |
367 | ++kfill; |
368 | } else { |
369 | maction[j1] = static_cast<MACTION_T>(-maction[j1]); |
370 | dluval[kr] += multip * dvalpv[jj1]; |
371 | cancel = cancel || ! (fact->zeroTolerance < d1); |
372 | d1 = fabs(dluval[kr]); |
373 | } |
374 | j1 = hcoli[kr + 2]; |
375 | if (jj2 == 0) { |
376 | ++kfill; |
377 | } else { |
378 | maction[j2] = static_cast<MACTION_T>(-maction[j2]); |
379 | dluval[kr + 1] += multip * dvalpv[jj2]; |
380 | cancel = cancel || ! (fact->zeroTolerance < d1); |
381 | d1 = fabs(dluval[kr + 1]); |
382 | } |
383 | jj1 = maction[j1]; |
384 | j2 = hcoli[kr + 3]; |
385 | } |
386 | cancel = cancel || ! (fact->zeroTolerance < d1); |
387 | #else |
388 | /* |
389 | * This is apparently what the above code does. |
390 | * In addition to being unrolled, the assignments to j[12] and jj[12] |
391 | * are shifted so that the result of dereferencing maction doesn't |
392 | * have to be used immediately afterwards for the branch test. |
393 | * This would would cause a pipeline delay. (The apparent dereference |
394 | * of hcoli will be removed by the compiler using strength reduction). |
395 | * |
396 | * loop through the entries in the row being processed, |
397 | * flipping the sign of the maction entries as we go along. |
398 | * Afterwards, we look for positive entries to see what pivot |
399 | * row entries will cause fill-in. We count the number of fill-ins, too. |
400 | * "cancel" says if the result of combining the pivot row with this one |
401 | * causes an entry to get too small; if so, we discard those entries. |
402 | */ |
403 | kfill = epivr1 - (knpre - knprs + 1); |
404 | cancel = false; |
405 | |
406 | for (kr = knprs; kr <= knpre; kr++) { |
407 | j1 = hcoli[kr]; |
408 | jj1 = maction[j1]; |
409 | if ( (jj1 == 0)) { |
410 | /* no entry - this pivot column entry will have to be added */ |
411 | ++kfill; |
412 | } else { |
413 | /* there is an entry for this column in the pivot row */ |
414 | maction[j1] = -maction[j1]; |
415 | dluval[kr] += multip * dvalpv[jj1]; |
416 | d1 = fabs(dluval[kr]); |
417 | cancel = cancel || ! (fact->zeroTolerance < d1); |
418 | } |
419 | } |
420 | #endif |
421 | kstart = knpre; |
422 | fill = kfill; |
423 | |
424 | if (cancel) { |
425 | /* KSTART is used as a stack pointer for nonzeros in factored row */ |
426 | kstart = knprs - 1; |
427 | for (kr = knprs; kr <= knpre; ++kr) { |
428 | j = hcoli[kr]; |
429 | if (fabs(dluval[kr]) > fact->zeroTolerance) { |
430 | ++kstart; |
431 | dluval[kstart] = dluval[kr]; |
432 | hcoli[kstart] = j; |
433 | } else { |
434 | /* Remove element from column file */ |
435 | --nnentu; |
436 | --hincol[j]; |
437 | --enpr; |
438 | kcs = mcstrt[j]; |
439 | kce = kcs + hincol[j]; |
440 | for (kk = kcs; kk <= kce; ++kk) { |
441 | if (hrowi[kk] == npr) { |
442 | hrowi[kk] = hrowi[kce]; |
443 | hrowi[kce] = 0; |
444 | break; |
445 | } |
446 | } |
447 | /* ASSERT !(kk>kce) */ |
448 | } |
449 | } |
450 | knpre = kstart; |
451 | } |
452 | /* Fill contains an upper bound on the amount of fill-in */ |
453 | if (fill == 0) { |
454 | for (k = kipis; k <= kipie; ++k) { |
455 | maction[hcoli[k]] = static_cast<MACTION_T>(-maction[hcoli[k]]); |
456 | } |
457 | } |
458 | else { |
459 | naft = mwork[npr].suc; |
460 | kqq = mrstrt[naft] - knpre - 1; |
461 | |
462 | if (fill > kqq) { |
463 | /* Fill-in exceeds space left. Check if there is enough */ |
464 | /* space in row file for the new row. */ |
465 | nznpr = enpr + fill; |
466 | if (! (xnewro + nznpr + 1 < lstart)) { |
467 | if (! (nnentu + nznpr + 1 < lstart)) { |
468 | irtcod = -5; |
469 | goto L1050; |
470 | } |
471 | /* idea 1 is to compress every time xnewro increases by x thousand */ |
472 | /* idea 2 is to copy nucleus rows with a reasonable gap */ |
473 | /* then copy each row down when used */ |
474 | /* compressions would just be 1 remainder which eventually will */ |
475 | /* fit in cache */ |
476 | { |
477 | int iput = c_ekkrwcs(fact,dluval, hcoli, mrstrt, hinrow, mwork, nfirst); |
478 | kmxeta += xnewro - iput ; |
479 | xnewro = iput - 1; |
480 | ++ncompactions; |
481 | } |
482 | |
483 | kipis = mrstrt[ipivot] + 1; |
484 | kipie = kipis + epivr1 - 1; |
485 | knprs = mrstrt[npr]; |
486 | } |
487 | |
488 | /* I think this assignment should be inside the previous if-stmt */ |
489 | /* otherwise, it does nothing */ |
490 | /*assert(knpre == knprs + enpr - 1);*/ |
491 | knpre = knprs + enpr - 1; |
492 | |
493 | /* |
494 | * copy this row to the end of the row file and adjust its links. |
495 | * The links keep track of the order of rows in memory. |
496 | * Rows are only moved from the middle all the way to the end. |
497 | */ |
498 | if (npr != nlast) { |
499 | npre = mwork[npr].pre; |
500 | if (npr == nfirst) { |
501 | nfirst = naft; |
502 | } |
503 | /* take out of chain */ |
504 | mwork[naft].pre = npre; |
505 | mwork[npre].suc = naft; |
506 | /* and put in at end */ |
507 | mwork[nfirst].pre = npr; |
508 | mwork[nlast].suc = npr; |
509 | mwork[npr].pre = nlast; |
510 | mwork[npr].suc = nfirst; |
511 | nlast = npr; |
512 | kstart = xnewro; |
513 | mrstrt[npr] = kstart + 1; |
514 | nmove = knpre - knprs + 1; |
515 | ibase = kstart + 1 - knprs; |
516 | for (kr = knprs; kr <= knpre; ++kr) { |
517 | dluval[ibase + kr] = dluval[kr]; |
518 | hcoli[ibase + kr] = hcoli[kr]; |
519 | } |
520 | kstart += nmove; |
521 | } else { |
522 | kstart = knpre; |
523 | } |
524 | |
525 | /* extra space ? */ |
526 | /* |
527 | * The mystery of iadd32. |
528 | * This code assigns to xnewro, possibly using iadd32. |
529 | * However, in that case xnewro is assigned to just after |
530 | * the for-loop below, and there is no intervening reference. |
531 | * Therefore, I believe that this code can be entirely eliminated; |
532 | * it is the leftover of an interrupted or dropped experiment. |
533 | * Presumably, this was trying to implement the ideas about |
534 | * padding expressed above. |
535 | */ |
536 | if (iadd32 != 0) { |
537 | xnewro += iadd32; |
538 | } else { |
539 | if (kstart + (nrow << 1) + 100 < lstart) { |
540 | ileft = ((nrow - fact->npivots + 32) & -32); |
541 | if (kstart + ileft * ileft + 32 < lstart) { |
542 | iadd32 = ileft; |
543 | xnewro = CoinMax(kstart,xnewro); |
544 | xnewro = (xnewro & -32) + ileft; |
545 | } else { |
546 | xnewro = ((kstart + 31) & -32); |
547 | } |
548 | } else { |
549 | xnewro = kstart; |
550 | } |
551 | } |
552 | |
553 | hinrow[npr] = enpr; |
554 | } else if (! (nnentu + kqq + 2 < lstart)) { |
555 | irtcod = -5; |
556 | goto L1050; |
557 | } |
558 | /* Scan pivot row again to generate fill in. */ |
559 | for (kr = kipis; kr <= kipie; ++kr) { |
560 | j = hcoli[kr]; |
561 | jj = maction[j]; |
562 | if (jj >0) { |
563 | elemnt = multip * dvalpv[jj]; |
564 | if (fabs(elemnt) > fact->zeroTolerance) { |
565 | ++kstart; |
566 | dluval[kstart] = elemnt; |
567 | //printf("pivot %d at %d col %d el %g\n", |
568 | // npr,kstart,j,elemnt); |
569 | hcoli[kstart] = j; |
570 | ++nnentu; |
571 | nz = hincol[j]; |
572 | kcs = mcstrt[j]; |
573 | kce = kcs + nz - 1; |
574 | if (kce == xnewco) { |
575 | if (xnewco + 1 >= lstart) { |
576 | if (xnewco + nz + 1 >= lstart) { |
577 | /* Compress column file */ |
578 | if (nnentu + nz + 1 < lstart) { |
579 | xnewco = c_ekkclco(fact,hrowi, mcstrt, hincol, xnewco); |
580 | ++ncompactions; |
581 | |
582 | kcpiv = mcstrt[jpivot] - 1; |
583 | kcs = mcstrt[j]; |
584 | /* HINCOL MAY HAVE CHANGED? (JJHF) ??? */ |
585 | nz = hincol[j]; |
586 | kce = kcs + nz - 1; |
587 | } else { |
588 | irtcod = -5; |
589 | goto L1050; |
590 | } |
591 | } |
592 | /* Copy column */ |
593 | mcstrt[j] = xnewco + 1; |
594 | ibase = mcstrt[j] - kcs; |
595 | for (kk = kcs; kk <= kce; ++kk) { |
596 | hrowi[ibase + kk] = hrowi[kk]; |
597 | hrowi[kk] = 0; |
598 | } |
599 | kce = xnewco + kce - kcs + 1; |
600 | xnewco = kce + 1; |
601 | } else { |
602 | ++xnewco; |
603 | } |
604 | } else if (hrowi[kce + 1] != 0) { |
605 | /* here we use the fact that hrowi entries not "in use" are zeroed */ |
606 | if (xnewco + nz + 1 >= lstart) { |
607 | /* Compress column file */ |
608 | if (nnentu + nz + 1 < lstart) { |
609 | xnewco = c_ekkclco(fact,hrowi, mcstrt, hincol, xnewco); |
610 | ++ncompactions; |
611 | |
612 | kcpiv = mcstrt[jpivot] - 1; |
613 | kcs = mcstrt[j]; |
614 | /* HINCOL MAY HAVE CHANGED? (JJHF) ??? */ |
615 | nz = hincol[j]; |
616 | kce = kcs + nz - 1; |
617 | } else { |
618 | irtcod = -5; |
619 | goto L1050; |
620 | } |
621 | } |
622 | /* move the column to the end of the column file */ |
623 | mcstrt[j] = xnewco + 1; |
624 | ibase = mcstrt[j] - kcs; |
625 | for (kk = kcs; kk <= kce; ++kk) { |
626 | hrowi[ibase + kk] = hrowi[kk]; |
627 | hrowi[kk] = 0; |
628 | } |
629 | kce = xnewco + kce - kcs + 1; |
630 | xnewco = kce + 1; |
631 | } |
632 | /* store element */ |
633 | hrowi[kce + 1] = npr; |
634 | hincol[j] = nz + 1; |
635 | } |
636 | } else { |
637 | maction[j] = static_cast<MACTION_T>(-maction[j]); |
638 | } |
639 | } |
640 | if (fill > kqq) { |
641 | xnewro = kstart; |
642 | } |
643 | } |
644 | hinrow[npr] = kstart - mrstrt[npr] + 1; |
645 | /* Check if row or column file needs compression */ |
646 | if (! (xnewco + 1 < lstart)) { |
647 | xnewco = c_ekkclco(fact,hrowi, mcstrt, hincol, xnewco); |
648 | ++ncompactions; |
649 | |
650 | kcpiv = mcstrt[jpivot] - 1; |
651 | } |
652 | if (! (xnewro + 1 < lstart)) { |
653 | int iput = c_ekkrwcs(fact,dluval, hcoli, mrstrt, hinrow, mwork, nfirst); |
654 | kmxeta += xnewro - iput ; |
655 | xnewro = iput - 1; |
656 | ++ncompactions; |
657 | |
658 | kipis = mrstrt[ipivot] + 1; |
659 | kipie = kipis + epivr1 - 1; |
660 | } |
661 | /* Store elementary row transformation */ |
662 | ++nnentl; |
663 | --nnentu; |
664 | --lstart; |
665 | dluval[lstart] = multip; |
666 | |
667 | hrowi[lstart] = SHIFT_INDEX(npr); |
668 | #define INLINE_AFPV 3 |
669 | /* We could do this while computing values but |
670 | it makes it much more complex. At least we should get |
671 | reasonable cache behavior by doing it each row */ |
672 | #if INLINE_AFPV |
673 | { |
674 | int j; |
675 | int nel, krs; |
676 | int koff; |
677 | int * index; |
678 | double * els; |
679 | nel = hinrow[npr]; |
680 | krs = mrstrt[npr]; |
681 | index=&hcoli[krs]; |
682 | els=&dluval[krs]; |
683 | #if INLINE_AFPV<3 |
684 | #if INLINE_AFPV==1 |
685 | double maxaij = 0.0; |
686 | koff = 0; |
687 | j=0; |
688 | while (j<nel) { |
689 | double d = fabs(els[j]); |
690 | if (maxaij < d) { |
691 | maxaij = d; |
692 | koff=j; |
693 | } |
694 | j++; |
695 | } |
696 | #else |
697 | assert (nel); |
698 | koff=0; |
699 | double maxaij=fabs(els[0]); |
700 | for (j=1;j<nel;j++) { |
701 | double d = fabs(els[j]); |
702 | if (maxaij < d) { |
703 | maxaij = d; |
704 | koff=j; |
705 | } |
706 | } |
707 | #endif |
708 | #else |
709 | double maxaij = 0.0; |
710 | koff = 0; |
711 | j=0; |
712 | if ((nel&1)!=0) { |
713 | maxaij=fabs(els[0]); |
714 | j=1; |
715 | } |
716 | |
717 | while (j<nel) { |
718 | UNROLL_LOOP_BODY2({ |
719 | double d = fabs(els[j]); |
720 | if (maxaij < d) { |
721 | maxaij = d; |
722 | koff=j; |
723 | } |
724 | j++; |
725 | }); |
726 | } |
727 | #endif |
728 | SWAP(int, index[koff], index[0]); |
729 | SWAP(double, els[koff], els[0]); |
730 | } |
731 | #endif |
732 | |
733 | { |
734 | int nzi = hinrow[npr]; |
735 | if (nzi > 0) { |
736 | C_EKK_ADD_LINK(hpivro, nzi, rlink, npr); |
737 | } |
738 | } |
739 | } |
740 | |
741 | /* after pivot move biggest to first in each row */ |
742 | #if INLINE_AFPV==0 |
743 | int nn = mcstrt[fact->xnetal] - lstart + 1; |
744 | c_ekkafpv(hrowi+lstart, hcoli, dluval, mrstrt, hinrow, nn); |
745 | #endif |
746 | |
747 | /* Restore work array */ |
748 | for (k = kipis; k <= kipie; ++k) { |
749 | maction[hcoli[k]] = 0; |
750 | } |
751 | |
752 | if (*xrejctp > 0) { |
753 | for (k = kipis; k <= kipie; ++k) { |
754 | int j = hcoli[k]; |
755 | int nzj = hincol[j]; |
756 | if (! (nzj <= 0) && |
757 | ! ((clink[j].pre > nrow && nzj != 1))) { |
758 | C_EKK_ADD_LINK(hpivco, nzj, clink, j); |
759 | } |
760 | } |
761 | } else { |
762 | for (k = kipis; k <= kipie; ++k) { |
763 | int j = hcoli[k]; |
764 | int nzj = hincol[j]; |
765 | if (! (nzj <= 0)) { |
766 | C_EKK_ADD_LINK(hpivco, nzj, clink, j); |
767 | } |
768 | } |
769 | } |
770 | fact->nuspike += hinrow[ipivot]; |
771 | |
772 | /* Go to dense coding if appropriate */ |
773 | #ifndef C_EKKCMFY |
774 | if (ifdens != 0) { |
775 | int ndense = nrow - fact->npivots; |
776 | if (! (xnewro + ndense * ndense >= lstart)) { |
777 | |
778 | /* set up sort order in MACTION */ |
779 | c_ekkizero( nrow, reinterpret_cast<int *> (maction+1)); |
780 | iput = 0; |
781 | for (i = 1; i <= nrow; ++i) { |
782 | if (clink[i].pre >= 0) { |
783 | ++iput; |
784 | maction[i] = static_cast<short int>(iput); |
785 | } |
786 | } |
787 | /* and get number spare needed */ |
788 | nspare = 0; |
789 | for (i = 1; i <= nrow; ++i) { |
790 | if (rlink[i].pre >= 0) { |
791 | nspare = nspare + ndense - hinrow[i]; |
792 | } |
793 | } |
794 | if (iput != nrow - fact->npivots) { |
795 | /* must be singular */ |
796 | c_ekkizero( nrow, reinterpret_cast<int *> (maction+1)); |
797 | } else { |
798 | /* pack down then back up */ |
799 | int iput = c_ekkrwcs(fact,dluval, hcoli, mrstrt, hinrow, mwork, nfirst); |
800 | kmxeta += xnewro - iput ; |
801 | xnewro = iput - 1; |
802 | ++ncompactions; |
803 | |
804 | --ncompactions; |
805 | if (xnewro + nspare + ndense * ndense >= lstart) { |
806 | c_ekkizero( nrow, reinterpret_cast<int *> (maction+1)); |
807 | } |
808 | else { |
809 | xnewro += nspare; |
810 | c_ekkrwct(fact,dluval, hcoli, mrstrt, hinrow, mwork, |
811 | rlink, maction, dvalpv, |
812 | nlast, xnewro); |
813 | kmxeta += xnewro ; |
814 | if (nnentu + nnentl > nrow * 5 && |
815 | (ndense*ndense)>(nnentu+nnentl)>>2 && |
816 | !if_sparse_update) { |
817 | fact->ndenuc = ndense; |
818 | } |
819 | irtcod = c_ekkcmfd(fact, |
820 | (reinterpret_cast<int*>(dvalpv)+1), |
821 | rlink, clink, |
822 | (reinterpret_cast<int*>(maction+1))+1, |
823 | nnetas, |
824 | &nnentl, &nnentu, |
825 | nsingp); |
826 | /* irtcod == 0 || irtcod == 10 */ |
827 | /* 10 == found 0.0 pivot */ |
828 | goto L1050; |
829 | } |
830 | } |
831 | } else { |
832 | /* say not enough room */ |
833 | /*printf("no room %d\n",ndense);*/ |
834 | if (1) { |
835 | /* return and increase size of etas if possible */ |
836 | if (!noRoomForDense) { |
837 | int etasize =CoinMax(4*fact->nnentu+(nnetas-fact->nnentl)+1000,fact->eta_size); |
838 | noRoomForDense=ndense; |
839 | fact->eta_size=CoinMin(static_cast<int>(1.2*fact->eta_size),etasize); |
840 | if (fact->maxNNetas>0&&fact->eta_size> |
841 | fact->maxNNetas) { |
842 | fact->eta_size=fact->maxNNetas; |
843 | } |
844 | } |
845 | } |
846 | } |
847 | } |
848 | #endif /* C_EKKCMFY */ |
849 | } |
850 | |
851 | L1050: |
852 | { |
853 | int iput = c_ekkrwcs(fact,dluval, hcoli, mrstrt, hinrow, mwork, nfirst); |
854 | kmxeta += xnewro - iput; |
855 | xnewro = iput - 1; |
856 | ++ncompactions; |
857 | } |
858 | |
859 | nnentu = xnewro; |
860 | /* save order of row copy for c_ekkshfv */ |
861 | mwork[nrow+1].pre = nfirst; |
862 | mwork[nrow+1].suc = nlast; |
863 | |
864 | fact->nnentl = nnentl; |
865 | fact->nnentu = nnentu; |
866 | fact->kmxeta = kmxeta; |
867 | *xnewrop = xnewro; |
868 | *ncompactionsp = ncompactions; |
869 | |
870 | return (irtcod); |
871 | } /* c_ekkcmfc */ |
872 | #endif |
873 | |