00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #define dbl_EGlpNumSetToMaxAbsAndDo(a,b,c) \
00029 if(dbl_EGlpNumIsGreatZero(b))\
00030 {\
00031 if(dbl_EGlpNumIsLess(a,b)){\
00032 dbl_EGlpNumCopy(a,b);\
00033 c;\
00034 }\
00035 }\
00036 else\
00037 {\
00038 dbl_EGlpNumSign(a);\
00039 if(dbl_EGlpNumIsLess(b,a)){\
00040 dbl_EGlpNumCopy(a,b);\
00041 c;\
00042 }\
00043 dbl_EGlpNumSign(a);\
00044 }
00045
00046
00047 #include <stdio.h>
00048 #include <stdlib.h>
00049 #include "config.h"
00050 #include "dbl_iqsutil.h"
00051 #include "dbl_lpdefs.h"
00052 #include "dbl_factor.h"
00053 #ifdef USEDMALLOC
00054 #include "dmalloc.h"
00055 #endif
00056
00057
00058 #undef dbl_RECORD
00059 #undef dbl_DEBUG_FACTOR
00060 #undef dbl_SOLVE_DEBUG
00061
00062 #undef dbl_FACTOR_DEBUG
00063 #undef dbl_UPDATE_DEBUG
00064
00065 #undef dbl_TRACK_FACTOR
00066 #undef dbl_NOTICE_BLOWUP
00067
00068 #undef dbl_FACTOR_STATS
00069 #undef dbl_UPDATE_STATS
00070 #undef dbl_GROWTH_STATS
00071
00072 #undef dbl_UPDATE_STUDY
00073
00074 #undef dbl_SORT_RESULTS
00075
00076 #ifdef dbl_UPDATE_STUDY
00077 int dbl_nupdate = 0;
00078 long int dbl_colspiketot = 0.0;
00079 long int dbl_rowspiketot = 0.0;
00080 long int dbl_permshifttot = 0.0;
00081 long int dbl_leftetatot = 0.0;
00082 #endif
00083
00084 void dbl_ILLfactor_init_factor_work (
00085 dbl_factor_work * f)
00086 {
00087 f->max_k = 1000;
00088 dbl_EGlpNumCopy (f->fzero_tol, dbl_SZERO_TOLER);
00089 dbl_EGlpNumCopy (f->szero_tol, dbl_SZERO_TOLER);
00090 dbl_EGlpNumCopy (f->partial_tol, dbl_OBJBND_TOLER);
00091 f->ur_space_mul = 2.0;
00092 f->uc_space_mul = 1.1;
00093 f->lc_space_mul = 1.1;
00094 f->er_space_mul = 1000.0;
00095 f->grow_mul = 1.5;
00096 f->p = 4;
00097 f->etamax = 100;
00098 f->minmult = 1e3;
00099 f->maxmult = 1e5;
00100 f->updmaxmult = 1e7;
00101 f->dense_fract = 0.25;
00102 f->dense_min = 25;
00103 dbl_EGlpNumCopy (f->partial_cur, f->partial_tol);
00104 f->work_coef = 0;
00105 f->work_indx = 0;
00106 f->uc_inf = 0;
00107 f->ur_inf = 0;
00108 f->lc_inf = 0;
00109 f->lr_inf = 0;
00110 f->er_inf = 0;
00111 f->ucindx = 0;
00112 f->ucrind = 0;
00113 f->uccoef = 0;
00114 f->urindx = 0;
00115 f->urcind = 0;
00116 f->urcoef = 0;
00117 f->lcindx = 0;
00118 f->lccoef = 0;
00119 f->lrindx = 0;
00120 f->lrcoef = 0;
00121 f->erindx = 0;
00122 f->ercoef = 0;
00123 f->rperm = 0;
00124 f->rrank = 0;
00125 f->cperm = 0;
00126 f->crank = 0;
00127 f->dmat = 0;
00128 dbl_ILLsvector_init (&f->xtmp);
00129 }
00130
00131 void dbl_ILLfactor_free_factor_work (
00132 dbl_factor_work * f)
00133 {
00134 #ifdef dbl_UPDATE_STUDY
00135 if (dbl_nupdate)
00136 {
00137 MESSAGE(0, "UPDATE STUDY: avg %d upd: %.2f col, %.2f row, %.2f lefteta, "
00138 "%.2f perm", dbl_nupdate, ((double) dbl_colspiketot) / dbl_nupdate,
00139 ((double) dbl_rowspiketot) / dbl_nupdate, ((double) dbl_leftetatot) / dbl_nupdate,
00140 ((double) dbl_permshifttot) / dbl_nupdate);
00141 }
00142 #endif
00143 dbl_EGlpNumFreeArray (f->work_coef);
00144 ILL_IFFREE (f->work_indx, int);
00145
00146 ILL_IFFREE (f->uc_inf, dbl_uc_info);
00147 if (f->dim + f->max_k > 0 && f->ur_inf)
00148 {
00149 unsigned int i = f->dim + f->max_k + 1;
00150
00151 while (i--)
00152 dbl_EGlpNumClearVar (f->ur_inf[i].max);
00153 }
00154 ILL_IFFREE (f->ur_inf, dbl_ur_info);
00155 ILL_IFFREE (f->lc_inf, dbl_lc_info);
00156 ILL_IFFREE (f->lr_inf, dbl_lr_info);
00157 ILL_IFFREE (f->er_inf, dbl_er_info);
00158 ILL_IFFREE (f->ucindx, int);
00159 ILL_IFFREE (f->ucrind, int);
00160
00161 dbl_EGlpNumFreeArray (f->uccoef);
00162 ILL_IFFREE (f->urindx, int);
00163 ILL_IFFREE (f->urcind, int);
00164
00165 dbl_EGlpNumFreeArray (f->urcoef);
00166 ILL_IFFREE (f->lcindx, int);
00167
00168 dbl_EGlpNumFreeArray (f->lccoef);
00169 ILL_IFFREE (f->lrindx, int);
00170
00171 dbl_EGlpNumFreeArray (f->lrcoef);
00172 ILL_IFFREE (f->erindx, int);
00173
00174 dbl_EGlpNumFreeArray (f->ercoef);
00175 ILL_IFFREE (f->rperm, int);
00176 ILL_IFFREE (f->rrank, int);
00177 ILL_IFFREE (f->cperm, int);
00178 ILL_IFFREE (f->crank, int);
00179
00180 dbl_EGlpNumFreeArray (f->dmat);
00181 dbl_ILLsvector_free (&f->xtmp);
00182 }
00183
00184 int dbl_ILLfactor_set_factor_iparam (
00185 dbl_factor_work * f,
00186 int param,
00187 int val)
00188 {
00189 switch (param)
00190 {
00191 case QS_FACTOR_MAX_K:
00192 f->max_k = val;
00193 break;
00194 case QS_FACTOR_P:
00195 f->p = val;
00196 break;
00197 case QS_FACTOR_ETAMAX:
00198 f->etamax = val;
00199 break;
00200 case QS_FACTOR_DENSE_MIN:
00201 f->dense_min = val;
00202 break;
00203 default:
00204 fprintf (stderr, "Invalid param %d in dbl_ILLfactor_set_factor_iparam\n",
00205 param);
00206 return 1;
00207 }
00208 return 0;
00209 }
00210
00211 int dbl_ILLfactor_set_factor_dparam (
00212 dbl_factor_work * f,
00213 int param,
00214 double val)
00215 {
00216 switch (param)
00217 {
00218 case QS_FACTOR_FZERO_TOL:
00219 dbl_EGlpNumCopy (f->fzero_tol, val);
00220 break;
00221 case QS_FACTOR_SZERO_TOL:
00222 dbl_EGlpNumCopy (f->szero_tol, val);
00223 break;
00224 case QS_FACTOR_UR_SPACE_MUL:
00225 f->ur_space_mul = dbl_EGlpNumToLf (val);
00226 break;
00227 case QS_FACTOR_UC_SPACE_MUL:
00228 f->uc_space_mul = dbl_EGlpNumToLf (val);
00229 break;
00230 case QS_FACTOR_LC_SPACE_MUL:
00231 f->lc_space_mul = dbl_EGlpNumToLf (val);
00232 break;
00233 case QS_FACTOR_LR_SPACE_MUL:
00234 f->lr_space_mul = dbl_EGlpNumToLf (val);
00235 break;
00236 case QS_FACTOR_ER_SPACE_MUL:
00237 f->er_space_mul = dbl_EGlpNumToLf (val);
00238 break;
00239 case QS_FACTOR_GROW_MUL:
00240 f->grow_mul = dbl_EGlpNumToLf (val);
00241 break;
00242 case QS_FACTOR_MAXMULT:
00243 f->maxmult = dbl_EGlpNumToLf (val);
00244 break;
00245 case QS_FACTOR_UPDMAXMULT:
00246 f->updmaxmult = dbl_EGlpNumToLf (val);
00247 break;
00248 case QS_FACTOR_DENSE_FRACT:
00249 f->dense_fract = dbl_EGlpNumToLf (val);
00250 break;
00251 case QS_FACTOR_PARTIAL_TOL:
00252 dbl_EGlpNumCopy (f->partial_tol, val);
00253 dbl_EGlpNumCopy (f->partial_cur, val);
00254 break;
00255 default:
00256 fprintf (stderr, "Invalid param %d in dbl_ILLfactor_set_factor_dparam\n",
00257 param);
00258 return 1;
00259 }
00260 return 0;
00261 }
00262
00263 int dbl_ILLfactor_create_factor_work (
00264 dbl_factor_work * f,
00265 int dim)
00266 {
00267 int i;
00268 int rval;
00269
00270 f->dim = dim;
00271 f->etacnt = 0;
00272 f->work_coef = dbl_EGlpNumAllocArray (dim);
00273 ILL_SAFE_MALLOC (f->work_indx, dim, int);
00274
00275 ILL_SAFE_MALLOC (f->uc_inf, dim + (f->max_k + 1), dbl_uc_info);
00276 ILL_SAFE_MALLOC (f->ur_inf, dim + (f->max_k + 1), dbl_ur_info);
00277 ILL_SAFE_MALLOC (f->lc_inf, dim, dbl_lc_info);
00278 ILL_SAFE_MALLOC (f->lr_inf, dim, dbl_lr_info);
00279 ILL_SAFE_MALLOC (f->rperm, dim, int);
00280 ILL_SAFE_MALLOC (f->rrank, dim, int);
00281 ILL_SAFE_MALLOC (f->cperm, dim, int);
00282 ILL_SAFE_MALLOC (f->crank, dim, int);
00283
00284 for (i = dim + f->max_k + 1; i--;)
00285 dbl_EGlpNumInitVar (f->ur_inf[i].max);
00286
00287 for (i = 0; i < dim; i++)
00288 {
00289 dbl_EGlpNumZero (f->work_coef[i]);
00290 f->work_indx[i] = 0;
00291 f->uc_inf[i].nzcnt = 0;
00292 f->ur_inf[i].nzcnt = 0;
00293 f->lc_inf[i].nzcnt = 0;
00294 f->lr_inf[i].nzcnt = 0;
00295 f->rperm[i] = i;
00296 f->rrank[i] = i;
00297 f->cperm[i] = i;
00298 f->crank[i] = i;
00299 }
00300 for (i = 0; i <= f->max_k; i++)
00301 {
00302 f->uc_inf[dim + i].nzcnt = i;
00303 f->uc_inf[dim + i].next = dim + i;
00304 f->uc_inf[dim + i].prev = dim + i;
00305 f->ur_inf[dim + i].nzcnt = i;
00306 f->ur_inf[dim + i].next = dim + i;
00307 f->ur_inf[dim + i].prev = dim + i;
00308 }
00309
00310 rval = dbl_ILLsvector_alloc (&f->xtmp, dim);
00311 CHECKRVALG (rval, CLEANUP);
00312
00313 rval = 0;
00314
00315 CLEANUP:
00316 if (rval)
00317 {
00318 dbl_ILLfactor_free_factor_work (f);
00319 }
00320 EG_RETURN (rval);
00321 }
00322
00323 static void dbl_dump_matrix (
00324 dbl_factor_work * f,
00325 int remaining)
00326 {
00327 int dim = f->dim;
00328 dbl_ur_info *ur_inf = f->ur_inf;
00329 dbl_uc_info *uc_inf = f->uc_inf;
00330 dbl_lc_info *lc_inf = f->lc_inf;
00331 dbl_lr_info *lr_inf = f->lr_inf;
00332 dbl_er_info *er_inf = f->er_inf;
00333 int nzcnt;
00334 int beg;
00335
00336 int i;
00337 int j;
00338
00339 for (i = 0; i < dim; i++)
00340 {
00341 if (!remaining || ur_inf[i].next >= 0)
00342 {
00343 printf ("Row %d %d (max %.3f):", i, f->rrank[i],
00344 dbl_EGlpNumToLf (ur_inf[i].max));
00345 nzcnt = ur_inf[i].nzcnt;
00346 beg = ur_inf[i].rbeg;
00347 for (j = 0; j < nzcnt; j++)
00348 {
00349 if (j == ur_inf[i].pivcnt)
00350 {
00351 printf (" |");
00352 }
00353 printf (" %.3f*%d", dbl_EGlpNumToLf (f->urcoef[beg + j]),
00354 f->urindx[beg + j]);
00355 if (f->urcind)
00356 printf ("@%d", f->urcind[beg + j]);
00357 }
00358 printf ("\n");
00359 }
00360 }
00361 if (f->dmat)
00362 {
00363 int start = 0;
00364
00365 if (remaining)
00366 start = f->stage - f->dense_base;
00367 printf ("Dcols at %d %d - %d :", f->stage - f->dense_base,
00368 f->dense_base + start, f->nstages);
00369 for (j = start; j < f->dcols; j++)
00370 {
00371 printf (" %5d", f->cperm[j + f->dense_base]);
00372 }
00373 printf ("\n");
00374 for (i = start; i < f->drows; i++)
00375 {
00376 printf ("DRow %d %d (max %.3f):", i,
00377 f->rperm[i + f->dense_base],
00378 dbl_EGlpNumToLf (ur_inf[f->rperm[i + f->dense_base]].max));
00379 for (j = start; j < f->dcols; j++)
00380 {
00381 if (j == f->drows)
00382 {
00383 printf (" |");
00384 }
00385 printf (" %.3f", dbl_EGlpNumToLf (f->dmat[i * f->dcols + j]));
00386 }
00387 printf ("\n");
00388 }
00389 }
00390
00391 if (!remaining)
00392 {
00393 for (i = 0; i < f->stage; i++)
00394 {
00395 printf ("L col %d:", lc_inf[i].c);
00396 nzcnt = lc_inf[i].nzcnt;
00397 beg = lc_inf[i].cbeg;
00398 for (j = 0; j < nzcnt; j++)
00399 {
00400 printf (" %.3f*%d", dbl_EGlpNumToLf (f->lccoef[beg + j]),
00401 f->lcindx[beg + j]);
00402 }
00403 printf ("\n");
00404 }
00405 for (i = f->nstages; i < f->dim; i++)
00406 {
00407 printf ("L col %d:", lc_inf[i].c);
00408 nzcnt = lc_inf[i].nzcnt;
00409 beg = lc_inf[i].cbeg;
00410 for (j = 0; j < nzcnt; j++)
00411 {
00412 printf (" %.3f*%d", dbl_EGlpNumToLf (f->lccoef[beg + j]),
00413 f->lcindx[beg + j]);
00414 }
00415 printf ("\n");
00416 }
00417 for (i = 0; i < f->dim; i++)
00418 {
00419 if (!lr_inf[i].nzcnt)
00420 continue;
00421 printf ("L row %d:", lr_inf[i].r);
00422 nzcnt = lr_inf[i].nzcnt;
00423 beg = lr_inf[i].rbeg;
00424 for (j = 0; j < nzcnt; j++)
00425 {
00426 printf (" %.3f*%d", dbl_EGlpNumToLf (f->lrcoef[beg + j]),
00427 f->lrindx[beg + j]);
00428 }
00429 printf ("\n");
00430 }
00431 }
00432
00433 if (!remaining)
00434 {
00435 for (i = 0; i < f->etacnt; i++)
00436 {
00437 printf ("Eta row %d:", f->er_inf[i].r);
00438 nzcnt = er_inf[i].nzcnt;
00439 beg = er_inf[i].rbeg;
00440 for (j = 0; j < nzcnt; j++)
00441 {
00442 printf (" %.3f*%d", dbl_EGlpNumToLf (f->ercoef[beg + j]),
00443 f->erindx[beg + j]);
00444 }
00445 printf ("\n");
00446 }
00447 }
00448
00449 for (i = 0; i < dim; i++)
00450 {
00451 if (!remaining || uc_inf[i].next >= 0)
00452 {
00453 printf ("Col %d %d:", i, f->crank[i]);
00454 nzcnt = uc_inf[i].nzcnt;
00455 beg = uc_inf[i].cbeg;
00456 for (j = 0; j < nzcnt; j++)
00457 {
00458 if (f->uccoef != 0)
00459 {
00460 printf (" %.3f*%d", dbl_EGlpNumToLf (f->uccoef[beg + j]),
00461 f->ucindx[beg + j]);
00462 if (f->ucrind)
00463 printf ("@%d", f->ucrind[beg + j]);
00464 }
00465 else
00466 {
00467 printf (" %d", f->ucindx[beg + j]);
00468 }
00469 }
00470 printf ("\n");
00471 }
00472 }
00473
00474 if (!remaining)
00475 {
00476 printf ("rperm:");
00477 for (i = 0; i < dim; i++)
00478 {
00479 if (i == f->nstages)
00480 printf ("|");
00481 if (i == f->stage)
00482 printf ("|");
00483 printf (" %d", f->rperm[i]);
00484 }
00485 printf ("\n");
00486
00487 printf ("cperm:");
00488 for (i = 0; i < dim; i++)
00489 {
00490 if (i == f->nstages)
00491 printf ("|");
00492 if (i == f->stage)
00493 printf ("|");
00494 printf (" %d", f->cperm[i]);
00495 }
00496 printf ("\n");
00497 }
00498
00499 printf ("Rows by nzcnt:\n");
00500 for (i = 0; i <= f->max_k; i++)
00501 {
00502 if (ur_inf[dim + i].next != dim + i)
00503 {
00504 printf ("%d:", i);
00505 for (j = ur_inf[dim + i].next; j != dim + i; j = ur_inf[j].next)
00506 {
00507 printf (" %d", j);
00508 }
00509 printf ("\n");
00510 }
00511 }
00512
00513 printf ("Cols by nzcnt:\n");
00514 for (i = 0; i <= f->max_k; i++)
00515 {
00516 if (uc_inf[dim + i].next != dim + i)
00517 {
00518 printf ("%d:", i);
00519 for (j = uc_inf[dim + i].next; j != dim + i; j = uc_inf[j].next)
00520 {
00521 printf (" %d", j);
00522 }
00523 printf ("\n");
00524 }
00525 }
00526
00527 printf ("\n");
00528 fflush (stdout);
00529 }
00530
00531 #ifdef dbl_SORT_RESULTS
00532 static void dbl_sort_vector2 (
00533 int nzcnt,
00534 int *indx,
00535 double * coef)
00536 {
00537 int i;
00538 int j;
00539 int itmp;
00540 double ctmp;
00541
00542 dbl_EGlpNumInitVar (ctmp);
00543
00544 for (i = 1; i < nzcnt; i++)
00545 {
00546 itmp = indx[i];
00547 dbl_EGlpNumCopy (ctmp, coef[i]);
00548 for (j = i; j >= 1 && indx[j - 1] > itmp; j--)
00549 {
00550 indx[j] = indx[j - 1];
00551 dbl_EGlpNumCopy (coef[j], coef[j - 1]);
00552 }
00553 indx[j] = itmp;
00554 dbl_EGlpNumCopy (coef[j], ctmp);
00555 }
00556 dbl_EGlpNumClearVar (ctmp);
00557 }
00558
00559 static void dbl_sort_vector (
00560 dbl_svector * x)
00561 {
00562 dbl_sort_vector2 (x->nzcnt, x->indx, x->coef);
00563 }
00564 #endif
00565
00566 #ifdef dbl_DEBUG_FACTOR
00567 static int dbl_check_matrix (
00568 dbl_factor_work * f)
00569 {
00570 dbl_ur_info *ur_inf = f->ur_inf;
00571 dbl_uc_info *uc_inf = f->uc_inf;
00572 int rbeg;
00573 int nzcnt;
00574 int cbeg;
00575 int c;
00576 int r;
00577 int j;
00578 int nerr = 0;
00579
00580 for (r = 0; r < f->dim; r++)
00581 {
00582 nzcnt = ur_inf[r].nzcnt;
00583 rbeg = ur_inf[r].rbeg;
00584 for (j = 0; j < nzcnt; j++)
00585 {
00586 c = f->urindx[rbeg + j];
00587 cbeg = uc_inf[c].cbeg;
00588 if (f->ucindx[cbeg + f->urcind[rbeg + j]] != r)
00589 {
00590 MESSAGE(0,"index mismatch, row %d column %d", r, c);
00591 nerr++;
00592 }
00593 if (fabs(dbl_EGlpNumToLf(f->uccoef[cbeg + f->urcind[rbeg + j]]) - dbl_EGlpNumToLf(f->urcoef[rbeg + j]))>1000*dbl_EGlpNumToLf(dbl_epsLpNum))
00594 {
00595 MESSAGE(0,"coef mismatch, row %d column %d", r, c);
00596 nerr++;
00597 }
00598 }
00599 }
00600 if (f->urindx[f->ur_space] != 0)
00601 {
00602 MESSAGE(0,"last urindx entry %d != 0", f->urindx[f->ur_space]);
00603 nerr++;
00604 }
00605
00606 for (c = 0; c < f->dim; c++)
00607 {
00608 nzcnt = uc_inf[c].nzcnt;
00609 cbeg = uc_inf[c].cbeg;
00610 for (j = 0; j < nzcnt; j++)
00611 {
00612 r = f->ucindx[cbeg + j];
00613 rbeg = ur_inf[r].rbeg;
00614 if (f->urindx[rbeg + f->ucrind[cbeg + j]] != c)
00615 {
00616 MESSAGE(0,"index mismatch, column %d row %d", c, r);
00617 nerr++;
00618 }
00619 if (f->urcoef[rbeg + f->ucrind[cbeg + j]] != f->uccoef[cbeg + j])
00620 {
00621 MESSAGE(0,"coef mismatch, column %d row %d", c, r);
00622 nerr++;
00623 }
00624 }
00625 }
00626 if (f->ucindx[f->uc_space] != 0)
00627 {
00628 MESSAGE(0,"last ucindx entry %d != 0", f->ucindx[f->uc_space]);
00629 nerr++;
00630 }
00631 if (nerr)
00632 {
00633 dbl_dump_matrix (f, 0);
00634 return E_CHECK_FAILED;
00635 }
00636 return 0;
00637 }
00638 #endif
00639
00640 #ifdef dbl_FACTOR_STATS
00641 static void dbl_dump_factor_stats (
00642 dbl_factor_work * f)
00643 {
00644 int dim = f->dim;
00645 int ecnt = f->etacnt;
00646 dbl_ur_info *ur_inf = f->ur_inf;
00647 dbl_lc_info *lc_inf = f->lc_inf;
00648 dbl_er_info *er_inf = f->er_inf;
00649 double *urcoef = f->urcoef;
00650 double *lccoef = f->lccoef;
00651 double *ercoef = f->ercoef;
00652 int lnzcnt = 0;
00653 int unzcnt = 0;
00654 int enzcnt = 0;
00655 int nzcnt;
00656 int beg;
00657 double umax;
00658 double lmax;
00659 double emax;
00660 int i;
00661 int j;
00662
00663 dbl_EGlpNumInitVar (umax);
00664 dbl_EGlpNumInitVar (lmax);
00665 dbl_EGlpNumInitVar (emax);
00666 dbl_EGlpNumZero (umax);
00667 for (i = 0; i < dim; i++)
00668 {
00669 nzcnt = ur_inf[i].nzcnt;
00670 beg = ur_inf[i].rbeg;
00671 unzcnt += nzcnt;
00672 for (j = 0; j < nzcnt; j++)
00673 {
00674 dbl_EGlpNumSetToMaxAbs (umax, urcoef[beg + j]);
00675 }
00676 }
00677 dbl_EGlpNumZero (lmax);
00678 for (i = 0; i < dim; i++)
00679 {
00680 nzcnt = lc_inf[i].nzcnt;
00681 beg = lc_inf[i].cbeg;
00682 lnzcnt += nzcnt;
00683 for (j = 0; j < nzcnt; j++)
00684 {
00685 dbl_EGlpNumSetToMaxAbs (lmax, lccoef[beg + j]);
00686 }
00687 }
00688 dbl_EGlpNumZero (emax);
00689 for (i = 0; i < ecnt; i++)
00690 {
00691 nzcnt = er_inf[i].nzcnt;
00692 beg = er_inf[i].rbeg;
00693 enzcnt += nzcnt;
00694 for (j = 0; j < nzcnt; j++)
00695 {
00696 dbl_EGlpNumSetToMaxAbs (emax, ercoef[beg + j]);
00697 }
00698 }
00699 MESSAGE(0, "factor U %d nzs %.3e max L %d nzs %.3e max E %d nzs %.3e max",
00700 unzcnt, dbl_EGlpNumToLf (umax), lnzcnt, dbl_EGlpNumToLf (lmax), enzcnt,
00701 dbl_EGlpNumToLf (emax));
00702 fflush (stdout);
00703 dbl_EGlpNumClearVar (umax);
00704 dbl_EGlpNumClearVar (lmax);
00705 dbl_EGlpNumClearVar (emax);
00706 }
00707 #endif
00708
00709 static void dbl_clear_work (
00710 dbl_factor_work * f)
00711 {
00712 int i;
00713 int dim = f->dim;
00714 double *work_coef = f->work_coef;
00715
00716 for (i = 0; i < dim; i++)
00717 {
00718 dbl_EGlpNumZero (work_coef[i]);
00719 }
00720 }
00721
00722 static void dbl_load_row (
00723 dbl_factor_work * f,
00724 int r)
00725 {
00726 double *prow_urcoef = f->urcoef + f->ur_inf[r].rbeg;
00727 int *prow_urindx = f->urindx + f->ur_inf[r].rbeg;
00728 int prow_nzcnt = f->ur_inf[r].nzcnt;
00729 double *work_coef = f->work_coef;
00730 int *work_indx = f->work_indx;
00731 int i;
00732 int j;
00733
00734 for (i = 0; i < prow_nzcnt; i++)
00735 {
00736 j = prow_urindx[i];
00737 dbl_EGlpNumCopy (work_coef[j], prow_urcoef[i]);
00738 work_indx[j] = 1;
00739 }
00740 }
00741
00742 static void dbl_clear_row (
00743 dbl_factor_work * f,
00744 int r)
00745 {
00746 int *prow_urindx = f->urindx + f->ur_inf[r].rbeg;
00747 int prow_nzcnt = f->ur_inf[r].nzcnt;
00748 double *work_coef = f->work_coef;
00749 int *work_indx = f->work_indx;
00750 int i;
00751 int j;
00752
00753 for (i = 0; i < prow_nzcnt; i++)
00754 {
00755 j = prow_urindx[i];
00756 dbl_EGlpNumZero (work_coef[j]);
00757 work_indx[j] = 0;
00758 }
00759 }
00760
00761 static int dbl_make_ur_space (
00762 dbl_factor_work * f,
00763 int space)
00764 {
00765 double *new_urcoef = 0;
00766 int *new_urindx = 0;
00767 int *new_urcind = 0;
00768 double *urcoef = f->urcoef;
00769 int *urindx = f->urindx;
00770 int *urcind = f->urcind;
00771 int minspace;
00772 dbl_ur_info *ur_inf = f->ur_inf;
00773 int dim = f->dim;
00774 int new_nzcnt = 0, old_nzcnt;
00775 int rbeg;
00776 int nzcnt;
00777 int i;
00778 int j;
00779 int rval;
00780
00781 minspace = f->ur_space;
00782 nzcnt = space;
00783 for (i = 0; i < dim; i++)
00784 nzcnt += ur_inf[i].nzcnt;
00785 old_nzcnt = nzcnt;
00786 while (nzcnt * 2 >= minspace)
00787 {
00788 minspace = 1 + minspace * f->grow_mul;
00789 }
00790
00791 #ifdef dbl_GROWTH_STATS
00792 printf ("dbl_make_ur_space growing from %d to %d...", f->ur_space, minspace);
00793 fflush (stdout);
00794 #endif
00795 new_urcoef = dbl_EGlpNumAllocArray (minspace);
00796 ILL_SAFE_MALLOC (new_urindx, minspace + 1, int);
00797
00798 if (urcind)
00799 {
00800 ILL_SAFE_MALLOC (new_urcind, minspace, int);
00801 }
00802
00803 if (urcind)
00804 {
00805 for (j = 0; j < dim; j++)
00806 {
00807 rbeg = ur_inf[j].rbeg;
00808 nzcnt = ur_inf[j].nzcnt;
00809 ur_inf[j].rbeg = new_nzcnt;
00810 for (i = 0; i < nzcnt; i++)
00811 {
00812 new_urindx[new_nzcnt] = urindx[rbeg + i];
00813 dbl_EGlpNumCopy (new_urcoef[new_nzcnt], urcoef[rbeg + i]);
00814 new_urcind[new_nzcnt] = urcind[rbeg + i];
00815 new_nzcnt++;
00816 }
00817 }
00818 }
00819 else
00820 {
00821 for (j = 0; j < dim; j++)
00822 {
00823 rbeg = ur_inf[j].rbeg;
00824 nzcnt = ur_inf[j].nzcnt;
00825 ur_inf[j].rbeg = new_nzcnt;
00826 for (i = 0; i < nzcnt; i++)
00827 {
00828 new_urindx[new_nzcnt] = urindx[rbeg + i];
00829 dbl_EGlpNumCopy (new_urcoef[new_nzcnt], urcoef[rbeg + i]);
00830 new_nzcnt++;
00831 }
00832 }
00833 }
00834
00835 for (i = new_nzcnt; i < minspace; i++)
00836 {
00837 new_urindx[i] = -1;
00838 }
00839 new_urindx[minspace] = 0;
00840 dbl_EGlpNumFreeArray (f->urcoef);
00841 f->urcoef = new_urcoef;
00842 new_urcoef = 0;
00843
00844 ILL_IFFREE (f->urindx, int);
00845
00846 f->urindx = new_urindx;
00847 new_urindx = 0;
00848
00849 ILL_IFFREE (f->urcind, int);
00850
00851 f->urcind = new_urcind;
00852 new_urcind = 0;
00853
00854 f->ur_freebeg = new_nzcnt;
00855 f->ur_space = minspace;
00856
00857 #ifdef dbl_GROWTH_STATS
00858 MESSAGE (0,"%d/%d nonzeros", new_nzcnt, old_nzcnt);
00859 dbl_dump_factor_stats (f);
00860 #endif
00861
00862 rval = 0;
00863
00864 CLEANUP:
00865 ILL_IFFREE (new_urcoef, double);
00866 ILL_IFFREE (new_urindx, int);
00867 ILL_IFFREE (new_urcind, int);
00868
00869 EG_RETURN (rval);
00870 }
00871
00872 static int dbl_make_uc_space (
00873 dbl_factor_work * f,
00874 int space)
00875 {
00876 double *new_uccoef = 0;
00877 int *new_ucindx = 0;
00878 int *new_ucrind = 0;
00879 int uc_freebeg = f->uc_freebeg;
00880 double *uccoef = f->uccoef;
00881 int *ucindx = f->ucindx;
00882 int *ucrind = f->ucrind;
00883 int minspace = uc_freebeg + space;
00884 dbl_uc_info *uc_inf = f->uc_inf;
00885 int dim = f->dim;
00886 int new_nzcnt = 0;
00887 int cbeg;
00888 int nzcnt;
00889 int i;
00890 int j;
00891 int rval;
00892
00893 minspace = f->uc_space;
00894 nzcnt = space;
00895 for( i = 0 ; i < dim ; i++) nzcnt += uc_inf[i].nzcnt;
00896 while(nzcnt*2 >= minspace)
00897 {
00898 minspace = 10 + (f->grow_mul * minspace);
00899 }
00900
00901 #ifdef dbl_GROWTH_STATS
00902 MESSAGE (0,"dbl_make_uc_space growing from %d to %d...", f->uc_space, minspace);
00903 #endif
00904
00905 ILL_SAFE_MALLOC (new_ucindx, minspace + 1, int);
00906
00907 if (ucrind)
00908 {
00909 new_uccoef = dbl_EGlpNumAllocArray (minspace);
00910 ILL_SAFE_MALLOC (new_ucrind, minspace, int);
00911 }
00912
00913 if (ucrind)
00914 {
00915 for (j = 0; j < dim; j++)
00916 {
00917 cbeg = uc_inf[j].cbeg;
00918 nzcnt = uc_inf[j].nzcnt;
00919 uc_inf[j].cbeg = new_nzcnt;
00920 for (i = 0; i < nzcnt; i++)
00921 {
00922 new_ucindx[new_nzcnt] = ucindx[cbeg + i];
00923 dbl_EGlpNumCopy (new_uccoef[new_nzcnt], uccoef[cbeg + i]);
00924 new_ucrind[new_nzcnt] = ucrind[cbeg + i];
00925 new_nzcnt++;
00926 }
00927 }
00928 }
00929 else
00930 {
00931 for (j = 0; j < dim; j++)
00932 {
00933 cbeg = uc_inf[j].cbeg;
00934 nzcnt = uc_inf[j].nzcnt;
00935 uc_inf[j].cbeg = new_nzcnt;
00936 for (i = 0; i < nzcnt; i++)
00937 {
00938 new_ucindx[new_nzcnt] = ucindx[cbeg + i];
00939 new_nzcnt++;
00940 }
00941 }
00942 }
00943
00944 for (i = new_nzcnt; i < minspace; i++)
00945 {
00946 new_ucindx[i] = -1;
00947 }
00948 new_ucindx[minspace] = 0;
00949
00950 dbl_EGlpNumFreeArray (f->uccoef);
00951 f->uccoef = new_uccoef;
00952 new_uccoef = 0;
00953
00954 ILL_IFFREE (f->ucindx, int);
00955
00956 f->ucindx = new_ucindx;
00957 new_ucindx = 0;
00958
00959 ILL_IFFREE (f->ucrind, int);
00960
00961 f->ucrind = new_ucrind;
00962 new_ucrind = 0;
00963
00964 f->uc_freebeg = new_nzcnt;
00965 f->uc_space = minspace;
00966
00967 #ifdef dbl_GROWTH_STATS
00968 MESSAGE (0,"%d nonzeros", new_nzcnt);
00969 dbl_dump_factor_stats (f);
00970 #endif
00971
00972 rval = 0;
00973
00974 CLEANUP:
00975 ILL_IFFREE (new_uccoef, double);
00976 ILL_IFFREE (new_ucindx, int);
00977 ILL_IFFREE (new_ucrind, int);
00978
00979 EG_RETURN (rval);
00980 }
00981
00982 static int dbl_make_lc_space (
00983 dbl_factor_work * f,
00984 int space)
00985 {
00986 double *new_lccoef = 0;
00987 int *new_lcindx = 0;
00988 int lc_freebeg = f->lc_freebeg;
00989 double *lccoef = f->lccoef;
00990 int *lcindx = f->lcindx;
00991 int minspace = lc_freebeg + space;
00992 int i;
00993 int rval;
00994
00995 if (f->lc_space * f->grow_mul > minspace)
00996 {
00997 minspace = f->lc_space * f->grow_mul;
00998 }
00999
01000 #ifdef dbl_GROWTH_STATS
01001 MESSAGE (0,"dbl_make_lc_space growing from %d to %d...", f->lc_space, minspace);
01002 #endif
01003
01004 new_lccoef = dbl_EGlpNumAllocArray (minspace);
01005 ILL_SAFE_MALLOC (new_lcindx, minspace, int);
01006
01007 for (i = 0; i < lc_freebeg; i++)
01008 {
01009 dbl_EGlpNumCopy (new_lccoef[i], lccoef[i]);
01010 new_lcindx[i] = lcindx[i];
01011 }
01012
01013 dbl_EGlpNumFreeArray (lccoef);
01014 f->lccoef = new_lccoef;
01015 new_lccoef = 0;
01016
01017 ILL_IFFREE (lcindx, int);
01018
01019 f->lcindx = new_lcindx;
01020 new_lcindx = 0;
01021
01022 f->lc_space = minspace;
01023
01024 #ifdef dbl_GROWTH_STATS
01025 dbl_dump_factor_stats (f);
01026 #endif
01027
01028 rval = 0;
01029
01030 CLEANUP:
01031 ILL_IFFREE (new_lccoef, double);
01032 ILL_IFFREE (new_lcindx, int);
01033
01034 EG_RETURN (rval);
01035 }
01036
01037 static void dbl_set_col_nz (
01038 dbl_factor_work * f,
01039 int c)
01040 {
01041 dbl_uc_info *uc_inf = f->uc_inf;
01042 int nzcnt = uc_inf[c].nzcnt;
01043 int max_k = f->max_k;
01044 int dim = f->dim;
01045
01046 if (uc_inf[c].next >= 0)
01047 {
01048 uc_inf[uc_inf[c].next].prev = uc_inf[c].prev;
01049 uc_inf[uc_inf[c].prev].next = uc_inf[c].next;
01050
01051 if (nzcnt >= max_k)
01052 nzcnt = max_k;
01053 uc_inf[c].next = uc_inf[dim + nzcnt].next;
01054 uc_inf[c].prev = dim + nzcnt;
01055 uc_inf[dim + nzcnt].next = c;
01056 uc_inf[uc_inf[c].next].prev = c;
01057 }
01058 }
01059
01060 static void dbl_set_row_nz (
01061 dbl_factor_work * f,
01062 int r)
01063 {
01064 dbl_ur_info *ur_inf = f->ur_inf;
01065 int nzcnt = ur_inf[r].pivcnt;
01066 int max_k = f->max_k;
01067 int dim = f->dim;
01068
01069 if (ur_inf[r].next >= 0)
01070 {
01071 ur_inf[ur_inf[r].next].prev = ur_inf[r].prev;
01072 ur_inf[ur_inf[r].prev].next = ur_inf[r].next;
01073
01074 if (nzcnt >= max_k)
01075 nzcnt = max_k;
01076 ur_inf[r].next = ur_inf[dim + nzcnt].next;
01077 ur_inf[r].prev = dim + nzcnt;
01078 ur_inf[dim + nzcnt].next = r;
01079 ur_inf[ur_inf[r].next].prev = r;
01080 }
01081 }
01082
01083 static void dbl_remove_col_nz (
01084 dbl_factor_work * f,
01085 int r,
01086 int c)
01087 {
01088 dbl_uc_info *uc_inf = f->uc_inf;
01089 int *ucindx = f->ucindx + uc_inf[c].cbeg;
01090 int nzcnt = uc_inf[c].nzcnt;
01091 int i;
01092
01093 for (i = 0; i < nzcnt; i++)
01094 {
01095 if (ucindx[i] == r)
01096 {
01097 --nzcnt;
01098 ucindx[i] = ucindx[nzcnt];
01099 ucindx[nzcnt] = -1;
01100 break;
01101 }
01102 }
01103 uc_inf[c].nzcnt = nzcnt;
01104
01105 dbl_set_col_nz (f, c);
01106 }
01107
01108 static void dbl_remove_row_nz (
01109 dbl_factor_work * f,
01110 int r,
01111 int c)
01112 {
01113 dbl_ur_info *ur_inf = f->ur_inf;
01114 int *urindx = f->urindx + ur_inf[r].rbeg;
01115 double *urcoef = f->urcoef + ur_inf[r].rbeg;
01116 int pivcnt = ur_inf[r].pivcnt;
01117 double max;
01118 int tind;
01119 double tcoef;
01120 int i;
01121
01122 dbl_EGlpNumInitVar (tcoef);
01123 dbl_EGlpNumInitVar (max);
01124 dbl_EGlpNumZero (max);
01125
01126 for (i = 0; i < pivcnt; i++)
01127 {
01128 if (urindx[i] == c)
01129 {
01130 --pivcnt;
01131 dbl_ILL_SWAP (urindx[i], urindx[pivcnt], tind);
01132 dbl_EGLPNUM_SWAP (urcoef[i], urcoef[pivcnt], tcoef);
01133 --i;
01134 }
01135 else
01136 {
01137 dbl_EGlpNumSetToMaxAbs (max, urcoef[i]);
01138 }
01139 }
01140 ur_inf[r].pivcnt = pivcnt;
01141 dbl_EGlpNumCopy (ur_inf[r].max, max);
01142 dbl_set_row_nz (f, r);
01143 dbl_EGlpNumClearVar (max);
01144 dbl_EGlpNumClearVar (tcoef);
01145 }
01146
01147 static int dbl_add_col_nz (
01148 dbl_factor_work * f,
01149 int r,
01150 int c)
01151 {
01152 dbl_uc_info *uc_inf = f->uc_inf;
01153 int cbeg = uc_inf[c].cbeg;
01154 int nzcnt = uc_inf[c].nzcnt;
01155 int uc_freebeg = f->uc_freebeg;
01156 int *ucindx = f->ucindx;
01157 int i;
01158 int rval = 0;
01159
01160 if (uc_inf[c].next == -1)
01161 {
01162 return 0;
01163 }
01164
01165 if (ucindx[cbeg + nzcnt] == -1)
01166 {
01167 ucindx[cbeg + nzcnt] = r;
01168 uc_inf[c].nzcnt++;
01169 if (nzcnt + cbeg == uc_freebeg)
01170 {
01171 f->uc_freebeg = uc_freebeg + 1;
01172 }
01173 }
01174 else
01175 {
01176 if (uc_freebeg + nzcnt + 1 >= f->uc_space)
01177 {
01178 rval = dbl_make_uc_space (f, nzcnt + 1);
01179 CHECKRVALG (rval, CLEANUP);
01180 uc_freebeg = f->uc_freebeg;
01181 cbeg = uc_inf[c].cbeg;
01182 ucindx = f->ucindx;
01183 }
01184 for (i = 0; i < nzcnt; i++)
01185 {
01186 ucindx[uc_freebeg + i] = ucindx[cbeg + i];
01187 ucindx[cbeg + i] = -1;
01188 }
01189 ucindx[uc_freebeg + nzcnt] = r;
01190 uc_inf[c].cbeg = uc_freebeg;
01191 uc_inf[c].nzcnt++;
01192 f->uc_freebeg = uc_freebeg + nzcnt + 1;
01193 }
01194
01195 dbl_set_col_nz (f, c);
01196 CLEANUP:
01197 EG_RETURN (rval);
01198 }
01199
01200 static void dbl_disable_col (
01201 dbl_factor_work * f,
01202 int c)
01203 {
01204 dbl_uc_info *uc_inf = f->uc_inf;
01205
01206 if (uc_inf[c].next >= 0)
01207 {
01208 uc_inf[uc_inf[c].next].prev = uc_inf[c].prev;
01209 uc_inf[uc_inf[c].prev].next = uc_inf[c].next;
01210
01211 uc_inf[c].next = -2;
01212 uc_inf[c].prev = -2;
01213 }
01214 }
01215
01216 static void dbl_remove_col (
01217 dbl_factor_work * f,
01218 int c)
01219 {
01220 dbl_uc_info *uc_inf = f->uc_inf;
01221 int cbeg = uc_inf[c].cbeg;
01222 int nzcnt = uc_inf[c].nzcnt;
01223 int *ucindx = f->ucindx;
01224 int i;
01225
01226 for (i = 0; i < nzcnt; i++)
01227 {
01228 ucindx[cbeg + i] = -1;
01229 }
01230 uc_inf[c].cbeg = 0;
01231 uc_inf[c].nzcnt = 0;
01232
01233 if (uc_inf[c].next >= 0)
01234 {
01235 uc_inf[uc_inf[c].next].prev = uc_inf[c].prev;
01236 uc_inf[uc_inf[c].prev].next = uc_inf[c].next;
01237
01238 uc_inf[c].next = -1;
01239 uc_inf[c].prev = -1;
01240 }
01241 }
01242
01243 static void dbl_remove_row (
01244 dbl_factor_work * f,
01245 int r)
01246 {
01247 dbl_ur_info *ur_inf = f->ur_inf;
01248
01249 if (ur_inf[r].next >= 0)
01250 {
01251 ur_inf[ur_inf[r].next].prev = ur_inf[r].prev;
01252 ur_inf[ur_inf[r].prev].next = ur_inf[r].next;
01253
01254 ur_inf[r].next = -1;
01255 ur_inf[r].prev = -1;
01256 }
01257 }
01258
01259 static void dbl_find_coef (
01260 dbl_factor_work * f,
01261 int r,
01262 int c,
01263 double * coef)
01264 {
01265 double *prow_urcoef = f->urcoef + f->ur_inf[r].rbeg;
01266 int *prow_urindx = f->urindx + f->ur_inf[r].rbeg;
01267 int i;
01268 int prow_nzcnt = f->ur_inf[r].nzcnt;
01269
01270 dbl_EGlpNumZero (*coef);
01271 for (i = 0; i < prow_nzcnt; i++)
01272 {
01273 if (prow_urindx[i] == c)
01274 {
01275 dbl_EGlpNumCopy (*coef, prow_urcoef[i]);
01276 return;
01277 }
01278 }
01279 fprintf (stderr, "Coefficient not found\n");
01280 return;
01281 }
01282
01283 static int dbl_elim_row (
01284 dbl_factor_work * f,
01285 int elim_r,
01286 int r,
01287 int c,
01288 double * p_pivot_coef)
01289 {
01290 dbl_ur_info *ur_inf = f->ur_inf;
01291 double *work_coef = f->work_coef;
01292 int *work_indx = f->work_indx;
01293 double *urcoef = f->urcoef;
01294 int *urindx = f->urindx;
01295 int prow_beg = ur_inf[r].rbeg;
01296 int prow_nzcnt = ur_inf[r].nzcnt;
01297 int prow_pivcnt = ur_inf[r].pivcnt;
01298 int fill = ur_inf[elim_r].nzcnt;
01299 int cancel = 0;
01300 double max;
01301 int erow_beg;
01302 int erow_nzcnt;
01303 int erow_pivcnt;
01304 double x;
01305 int i;
01306 int j;
01307 int rval = 0;
01308 double elim_coef;
01309
01310 dbl_EGlpNumInitVar (max);
01311 dbl_EGlpNumInitVar (x);
01312 dbl_EGlpNumInitVar (elim_coef);
01313 dbl_EGlpNumZero (max);
01314 dbl_find_coef (f, r, c, &elim_coef);
01315 dbl_EGlpNumDivTo (elim_coef, work_coef[c]);
01316 dbl_EGlpNumCopy (*p_pivot_coef, elim_coef);
01317
01318 for (i = 0; i < prow_nzcnt; i++)
01319 {
01320 j = urindx[prow_beg + i];
01321 if (work_indx[j] == 1)
01322 {
01323 dbl_EGlpNumCopy (x, urcoef[prow_beg + i]);
01324 dbl_EGlpNumSubInnProdTo (x, elim_coef, work_coef[j]);
01325 if ((!(dbl_EGlpNumIsNeqZero (x, f->fzero_tol))) || j == c)
01326 {
01327 cancel++;
01328 if (j != c)
01329 {
01330 dbl_remove_col_nz (f, r, j);
01331 }
01332 if (i < prow_pivcnt)
01333 {
01334 prow_pivcnt--;
01335 prow_nzcnt--;
01336 urindx[prow_beg + i] = urindx[prow_beg + prow_pivcnt];
01337 dbl_EGlpNumCopy (urcoef[prow_beg + i], urcoef[prow_beg + prow_pivcnt]);
01338 if (prow_pivcnt != prow_nzcnt)
01339 {
01340 urindx[prow_beg + prow_pivcnt] = urindx[prow_beg + prow_nzcnt];
01341 dbl_EGlpNumCopy (urcoef[prow_beg + prow_pivcnt],
01342 urcoef[prow_beg + prow_nzcnt]);
01343 }
01344 }
01345 else
01346 {
01347 prow_nzcnt--;
01348 urindx[prow_beg + i] = urindx[prow_beg + prow_nzcnt];
01349 dbl_EGlpNumCopy (urcoef[prow_beg + i], urcoef[prow_beg + prow_nzcnt]);
01350 }
01351 urindx[prow_beg + prow_nzcnt] = -1;
01352 i--;
01353 }
01354 else
01355 {
01356 dbl_EGlpNumCopy (urcoef[prow_beg + i], x);
01357 if (i < prow_pivcnt)
01358 {
01359 dbl_EGlpNumSetToMaxAbs (max, x);
01360 }
01361 }
01362 work_indx[j] = 0;
01363 fill--;
01364 }
01365 else
01366 {
01367 if (i < prow_pivcnt)
01368 {
01369 dbl_EGlpNumSetToMaxAbs (max, urcoef[prow_beg + i]);
01370 }
01371 }
01372 }
01373
01374 if (fill > 0)
01375 {
01376 ur_inf[r].nzcnt = prow_nzcnt;
01377 ur_inf[r].pivcnt = prow_pivcnt;
01378 if (fill > cancel)
01379 {
01380 int ur_freebeg = f->ur_freebeg;
01381
01382 if (ur_freebeg + prow_nzcnt + fill >= f->ur_space)
01383 {
01384 rval = dbl_make_ur_space (f, prow_nzcnt + fill);
01385 CHECKRVALG (rval, CLEANUP);
01386 urcoef = f->urcoef;
01387 urindx = f->urindx;
01388 ur_freebeg = f->ur_freebeg;
01389 prow_beg = f->ur_inf[r].rbeg;
01390 }
01391 for (i = 0; i < prow_nzcnt; i++)
01392 {
01393 urindx[ur_freebeg + i] = urindx[prow_beg + i];
01394 dbl_EGlpNumCopy (urcoef[ur_freebeg + i], urcoef[prow_beg + i]);
01395 urindx[prow_beg + i] = -1;
01396 }
01397 ur_inf[r].rbeg = ur_freebeg;
01398 f->ur_freebeg = ur_freebeg + prow_nzcnt + fill;
01399 prow_beg = ur_freebeg;
01400 }
01401
01402 erow_beg = ur_inf[elim_r].rbeg;
01403 erow_nzcnt = ur_inf[elim_r].nzcnt;
01404 erow_pivcnt = ur_inf[elim_r].pivcnt;
01405
01406 for (i = 0; i < erow_pivcnt; i++)
01407 {
01408 j = urindx[erow_beg + i];
01409 if (work_indx[j] == 1)
01410 {
01411 dbl_EGlpNumCopyNeg (x, elim_coef);
01412 dbl_EGlpNumMultTo (x, urcoef[erow_beg + i]);
01413 if (dbl_EGlpNumIsNeqZero (x, f->fzero_tol))
01414 {
01415 rval = dbl_add_col_nz (f, r, j);
01416 CHECKRVALG (rval, CLEANUP);
01417 if (prow_pivcnt != prow_nzcnt)
01418 {
01419 urindx[prow_beg + prow_nzcnt] = urindx[prow_beg + prow_pivcnt];
01420 dbl_EGlpNumCopy (urcoef[prow_beg + prow_nzcnt],
01421 urcoef[prow_beg + prow_pivcnt]);
01422 }
01423 urindx[prow_beg + prow_pivcnt] = j;
01424 dbl_EGlpNumCopy (urcoef[prow_beg + prow_pivcnt], x);
01425 dbl_EGlpNumSetToMaxAbs (max, x);
01426 prow_pivcnt++;
01427 prow_nzcnt++;
01428 }
01429 }
01430 else
01431 {
01432 work_indx[j] = 1;
01433 }
01434 }
01435 for (i = erow_pivcnt; i < erow_nzcnt; i++)
01436 {
01437 j = urindx[erow_beg + i];
01438 if (work_indx[j] == 1)
01439 {
01440 dbl_EGlpNumCopyNeg (x, elim_coef);
01441 dbl_EGlpNumMultTo (x, urcoef[erow_beg + i]);
01442 if (dbl_EGlpNumIsNeqZero (x, f->fzero_tol))
01443 {
01444 rval = dbl_add_col_nz (f, r, j);
01445 CHECKRVALG (rval, CLEANUP);
01446 urindx[prow_beg + prow_nzcnt] = j;
01447 dbl_EGlpNumCopy (urcoef[prow_beg + prow_nzcnt], x);
01448 prow_nzcnt++;
01449 }
01450 }
01451 else
01452 {
01453 work_indx[j] = 1;
01454 }
01455 }
01456 }
01457 else
01458 {
01459 erow_nzcnt = ur_inf[elim_r].nzcnt;
01460 erow_beg = ur_inf[elim_r].rbeg;
01461 for (i = 0; i < erow_nzcnt; i++)
01462 {
01463 j = urindx[erow_beg + i];
01464 work_indx[j] = 1;
01465 }
01466 }
01467
01468 ur_inf[r].nzcnt = prow_nzcnt;
01469 ur_inf[r].pivcnt = prow_pivcnt;
01470 dbl_EGlpNumCopy (ur_inf[r].max, max);
01471
01472 dbl_set_row_nz (f, r);
01473 CLEANUP:
01474 dbl_EGlpNumClearVar (elim_coef);
01475 dbl_EGlpNumClearVar (x);
01476 dbl_EGlpNumClearVar (max);
01477 EG_RETURN (rval);
01478 }
01479
01480 #define dbl_SETPERM(f,s,r,c) { \
01481 f->rperm[f->rrank[r]] = f->rperm[s]; \
01482 f->rrank[f->rperm[s]] = f->rrank[r]; \
01483 f->rperm[s] = r; \
01484 f->rrank[r] = s; \
01485 \
01486 f->cperm[f->crank[c]] = f->cperm[s]; \
01487 f->crank[f->cperm[s]] = f->crank[c]; \
01488 f->cperm[s] = c; \
01489 f->crank[c] = s; \
01490 }
01491
01492 static int dbl_elim (
01493 dbl_factor_work * f,
01494 int r,
01495 int c)
01496 {
01497 dbl_uc_info *uc_inf = f->uc_inf;
01498 dbl_ur_info *ur_inf = f->ur_inf;
01499 dbl_lc_info *lc_inf = f->lc_inf;
01500 int *urindx;
01501 int *ucindx;
01502 int *lcindx;
01503 double *urcoef;
01504 double *lccoef;
01505 double pivot_coef;
01506 int nzcnt;
01507 int lc_freebeg;
01508 int s = f->stage;
01509 int i;
01510 int j;
01511 int rval = 0;
01512
01513 dbl_EGlpNumInitVar (pivot_coef);
01514
01515 if (uc_inf[c].nzcnt == 1)
01516 {
01517
01518 dbl_SETPERM (f, s, r, c);
01519
01520 lc_inf[s].cbeg = -1;
01521 lc_inf[s].c = r;
01522 lc_inf[s].nzcnt = 0;
01523 f->stage++;
01524
01525 urindx = f->urindx + ur_inf[r].rbeg;
01526 urcoef = f->urcoef + ur_inf[r].rbeg;
01527 nzcnt = ur_inf[r].nzcnt;
01528 for (i = 0; i < nzcnt; i++)
01529 {
01530 j = urindx[i];
01531 dbl_remove_col_nz (f, r, j);
01532 if (j == c)
01533 {
01534 urindx[i] = urindx[0];
01535 urindx[0] = c;
01536 dbl_EGLPNUM_SWAP (urcoef[0], urcoef[i], pivot_coef);
01537 }
01538 }
01539 dbl_remove_row (f, r);
01540 dbl_remove_col (f, c);
01541 }
01542 else if (ur_inf[r].nzcnt == 1)
01543 {
01544
01545 --(f->nstages);
01546 dbl_SETPERM (f, f->nstages, r, c);
01547
01548 lc_inf[f->nstages].cbeg = -1;
01549 lc_inf[f->nstages].c = r;
01550 lc_inf[f->nstages].nzcnt = 0;
01551
01552 ucindx = f->ucindx + uc_inf[c].cbeg;
01553 nzcnt = uc_inf[c].nzcnt;
01554 for (i = 0; i < nzcnt; i++)
01555 {
01556 j = ucindx[i];
01557 dbl_remove_row_nz (f, j, c);
01558 }
01559 dbl_remove_row (f, r);
01560 dbl_remove_col (f, c);
01561 }
01562 else
01563 {
01564 dbl_SETPERM (f, s, r, c);
01565 f->stage++;
01566
01567 nzcnt = uc_inf[c].nzcnt;
01568 if (f->lc_freebeg + nzcnt >= f->lc_space)
01569 {
01570 rval = dbl_make_lc_space (f, nzcnt);
01571 CHECKRVALG (rval, CLEANUP);
01572 }
01573 lc_freebeg = f->lc_freebeg;
01574 lc_inf[s].cbeg = lc_freebeg;
01575 lc_inf[s].c = r;
01576 lcindx = f->lcindx;
01577 lccoef = f->lccoef;
01578 dbl_load_row (f, r);
01579 ucindx = f->ucindx + uc_inf[c].cbeg;
01580 for (i = 0; i < nzcnt; i++)
01581 {
01582 j = f->ucindx[uc_inf[c].cbeg + i];
01583 if (j != r)
01584 {
01585 rval = dbl_elim_row (f, r, j, c, &pivot_coef);
01586 CHECKRVALG (rval, CLEANUP);
01587 lcindx[lc_freebeg] = j;
01588 dbl_EGlpNumCopy (lccoef[lc_freebeg], pivot_coef);
01589 lc_freebeg++;
01590 #ifdef dbl_TRACK_FACTOR
01591 dbl_EGlpNumSetToMaxAbs (f->maxelem_factor, pivot_coef);
01592 if (dbl_EGlpNumIsLess (f->maxelem_factor, ur_inf[r].max))
01593 dbl_EGlpNumCopy (f->maxelem_factor, ur_inf[r].max);
01594 #endif
01595 }
01596 }
01597 lc_inf[s].nzcnt = lc_freebeg - lc_inf[s].cbeg;
01598 f->lc_freebeg = lc_freebeg;
01599
01600 dbl_clear_row (f, r);
01601
01602 urindx = f->urindx + ur_inf[r].rbeg;
01603 urcoef = f->urcoef + ur_inf[r].rbeg;
01604 nzcnt = ur_inf[r].nzcnt;
01605 for (i = 0; i < nzcnt; i++)
01606 {
01607 j = urindx[i];
01608 dbl_remove_col_nz (f, r, j);
01609 if (j == c)
01610 {
01611 urindx[i] = urindx[0];
01612 urindx[0] = c;
01613 dbl_EGLPNUM_SWAP (urcoef[0], urcoef[i], pivot_coef);
01614 }
01615 }
01616 dbl_remove_row (f, r);
01617 dbl_remove_col (f, c);
01618 }
01619 CLEANUP:
01620 dbl_EGlpNumClearVar (pivot_coef);
01621 EG_RETURN (rval);
01622 }
01623
01624 static void dbl_find_pivot_column (
01625 dbl_factor_work * f,
01626 int c,
01627 int *p_r)
01628 {
01629 dbl_uc_info *uc_inf = f->uc_inf;
01630 dbl_ur_info *ur_inf = f->ur_inf;
01631 int *ucindx = f->ucindx;
01632 int nzcnt = uc_inf[c].nzcnt;
01633 int cbeg = uc_inf[c].cbeg;
01634 double num_tmp[2];
01635 int bestnz = -1;
01636 int i;
01637 int r;
01638
01639 dbl_EGlpNumInitVar (num_tmp[0]);
01640 dbl_EGlpNumInitVar (num_tmp[1]);
01641
01642 *p_r = -1;
01643 for (i = 0; i < nzcnt; i++)
01644 {
01645 r = ucindx[cbeg + i];
01646 if((bestnz == -1 || ur_inf[r].pivcnt < bestnz))
01647 {
01648 dbl_find_coef (f, r, c, num_tmp);
01649 if(dbl_EGlpNumIsLessZero(num_tmp[0]))
01650 dbl_EGlpNumSign (num_tmp[0]);
01651 dbl_EGlpNumCopy (num_tmp[1], f->partial_cur);
01652 dbl_EGlpNumMultTo (num_tmp[1], ur_inf[r].max);
01653 if(dbl_EGlpNumIsLeq (num_tmp[1], num_tmp[0]))
01654 {
01655 bestnz = ur_inf[r].pivcnt;
01656 *p_r = r;
01657 }
01658 }
01659 }
01660 dbl_EGlpNumClearVar (num_tmp[0]);
01661 dbl_EGlpNumClearVar (num_tmp[1]);
01662 }
01663
01664 static void dbl_find_pivot_row (
01665 dbl_factor_work * f,
01666 int r,
01667 int *p_c)
01668 {
01669 dbl_uc_info *uc_inf = f->uc_inf;
01670 dbl_ur_info *ur_inf = f->ur_inf;
01671 int *urindx = f->urindx;
01672 double *urcoef = f->urcoef;
01673 int pivcnt = ur_inf[r].pivcnt;
01674 int rbeg = ur_inf[r].rbeg;
01675 double thresh[2];
01676 int bestnz = -1;
01677 int i;
01678 int c;
01679
01680 dbl_EGlpNumInitVar (thresh[0]);
01681 dbl_EGlpNumInitVar (thresh[1]);
01682 dbl_EGlpNumCopy (thresh[0], f->partial_cur);
01683 dbl_EGlpNumMultTo (thresh[0], ur_inf[r].max);
01684 *p_c = -1;
01685 for (i = 0; i < pivcnt; i++)
01686 {
01687 c = urindx[rbeg + i];
01688 if ((bestnz == -1 || uc_inf[c].nzcnt < bestnz))
01689 {
01690 dbl_EGlpNumCopyAbs (thresh[1], urcoef[rbeg + i]);
01691 if(dbl_EGlpNumIsLeq (thresh[0], thresh[1]))
01692 {
01693 bestnz = uc_inf[c].nzcnt;
01694 *p_c = c;
01695 }
01696 }
01697 }
01698 dbl_EGlpNumClearVar (thresh[0]);
01699 dbl_EGlpNumClearVar (thresh[1]);
01700 }
01701
01702 static int dbl_find_pivot (
01703 dbl_factor_work * f,
01704 int *p_r,
01705 int *p_c)
01706 {
01707 dbl_uc_info *uc_inf = f->uc_inf;
01708 dbl_ur_info *ur_inf = f->ur_inf;
01709 int dim = f->dim;
01710 int max_k = f->max_k;
01711 int p = f->p;
01712 int c;
01713 int r;
01714 int mm = 0;
01715 int n = 0;
01716 int m;
01717 int k = 2;
01718
01719 if (uc_inf[dim + 1].next != dim + 1)
01720 {
01721 c = uc_inf[dim + 1].next;
01722 r = f->ucindx[uc_inf[c].cbeg];
01723 *p_c = c;
01724 *p_r = r;
01725 return 0;
01726 }
01727 else if (ur_inf[dim + 1].next != dim + 1)
01728 {
01729 r = ur_inf[dim + 1].next;
01730 c = f->urindx[ur_inf[r].rbeg];
01731 *p_c = c;
01732 *p_r = r;
01733 return 0;
01734 }
01735 *p_r = -1;
01736 *p_c = -1;
01737 for (; k <= max_k && (mm == 0 || mm > (k - 1) * (k - 1)); k++)
01738 {
01739 if (uc_inf[dim + k].next != dim + k)
01740 {
01741 for (c = uc_inf[dim + k].next; c != dim + k; c = uc_inf[c].next)
01742 {
01743 dbl_find_pivot_column (f, c, &r);
01744 if (r >= 0)
01745 {
01746 m = (uc_inf[c].nzcnt - 1) * (ur_inf[r].pivcnt - 1);
01747 if (mm == 0 || m < mm)
01748 {
01749 mm = m;
01750 *p_c = c;
01751 *p_r = r;
01752 if (mm <= (k - 1) * (k - 1))
01753 {
01754 return 0;
01755 }
01756 }
01757 }
01758 else
01759 {
01760 c = uc_inf[c].prev;
01761 dbl_disable_col (f, uc_inf[c].next);
01762 }
01763 n++;
01764 if (n >= p && mm != 0)
01765 {
01766 return 0;
01767 }
01768 }
01769 }
01770
01771 if (ur_inf[dim + k].next != dim + k)
01772 {
01773 for (r = ur_inf[dim + k].next; r != dim + k; r = ur_inf[r].next)
01774 {
01775 dbl_find_pivot_row (f, r, &c);
01776 if (c >= 0)
01777 {
01778 m = (uc_inf[c].nzcnt - 1) * (ur_inf[r].pivcnt - 1);
01779 if (mm == 0 || m < mm)
01780 {
01781 mm = m;
01782 *p_c = c;
01783 *p_r = r;
01784 if (mm <= k * (k - 1))
01785 {
01786 return 0;
01787 }
01788 }
01789 }
01790 n++;
01791 if (n >= p && mm != 0)
01792 {
01793 return 0;
01794 }
01795 }
01796 }
01797 }
01798 if (mm != 0)
01799 {
01800 return 0;
01801 }
01802 else
01803 {
01804
01805 return E_NO_PIVOT;
01806 }
01807 }
01808
01809 static int dbl_create_factor_space (
01810 dbl_factor_work * f)
01811 {
01812 dbl_uc_info *uc_inf = f->uc_inf;
01813 dbl_ur_info *ur_inf = f->ur_inf;
01814 int dim = f->dim;
01815 int nzcnt;
01816 int i;
01817 int rval;
01818
01819 nzcnt = 0;
01820 for (i = 0; i < dim; i++)
01821 {
01822 nzcnt += ur_inf[i].nzcnt;
01823 }
01824
01825 if (f->ucindx == 0)
01826 {
01827 f->uc_space = nzcnt * f->uc_space_mul;
01828 ILL_SAFE_MALLOC (f->ucindx, f->uc_space + 1, int);
01829 }
01830
01831 if (f->urindx == 0 || f->urcoef == 0)
01832 {
01833 ILL_IFFREE (f->urindx, int);
01834
01835 dbl_EGlpNumFreeArray (f->urcoef);
01836 f->ur_space = nzcnt * f->ur_space_mul;
01837 ILL_SAFE_MALLOC (f->urindx, f->ur_space + 1, int);
01838
01839 f->urcoef = dbl_EGlpNumAllocArray (f->ur_space);
01840 }
01841
01842 if (f->lcindx == 0 || f->lccoef == 0)
01843 {
01844 ILL_IFFREE (f->lcindx, int);
01845
01846 dbl_EGlpNumFreeArray (f->lccoef);
01847 f->lc_space = nzcnt * f->lc_space_mul;
01848 ILL_SAFE_MALLOC (f->lcindx, f->lc_space, int);
01849
01850 f->lccoef = dbl_EGlpNumAllocArray (f->lc_space);
01851 }
01852
01853 nzcnt = 0;
01854 for (i = 0; i < dim; i++)
01855 {
01856 ur_inf[i].rbeg = nzcnt;
01857 nzcnt += ur_inf[i].nzcnt;
01858 ur_inf[i].nzcnt = ur_inf[i].rbeg;
01859 }
01860 f->ur_freebeg = nzcnt;
01861
01862 nzcnt = 0;
01863 for (i = 0; i < dim; i++)
01864 {
01865 uc_inf[i].cbeg = nzcnt;
01866 nzcnt += uc_inf[i].nzcnt;
01867 uc_inf[i].nzcnt = uc_inf[i].cbeg;
01868 }
01869 f->uc_freebeg = nzcnt;
01870
01871 f->lc_freebeg = 0;
01872
01873 rval = 0;
01874 CLEANUP:
01875 EG_RETURN (rval);
01876 }
01877
01878 static int dbl_init_matrix (
01879 dbl_factor_work * f,
01880 int *basis,
01881 int *cbeg,
01882 int *clen,
01883 int *in_ucindx,
01884 double * in_uccoef)
01885 {
01886 dbl_uc_info *uc_inf = f->uc_inf;
01887 dbl_ur_info *ur_inf = f->ur_inf;
01888 int dim = f->dim;
01889 int max_k = f->max_k;
01890 int *ucindx;
01891 int *urindx;
01892 double *urcoef;
01893 int nzcnt;
01894 int beg;
01895 int i;
01896 int j;
01897 int r;
01898 int rval = 0;
01899 double v;
01900 double max;
01901
01902 dbl_EGlpNumInitVar (v);
01903 dbl_EGlpNumInitVar (max);
01904
01905 for (i = 0; i < dim; i++)
01906 {
01907 ur_inf[i].nzcnt = 0;
01908 }
01909 for (i = 0; i < dim; i++)
01910 {
01911 nzcnt = clen[basis[i]];
01912 beg = cbeg[basis[i]];
01913 uc_inf[i].nzcnt = nzcnt;
01914 for (j = 0; j < nzcnt; j++)
01915 {
01916 r = in_ucindx[beg + j];
01917 ur_inf[r].nzcnt++;
01918 }
01919 }
01920
01921 rval = dbl_create_factor_space (f);
01922 CHECKRVALG (rval, CLEANUP);
01923
01924 urindx = f->urindx;
01925 ucindx = f->ucindx;
01926 urcoef = f->urcoef;
01927
01928 for (i = 0; i < dim; i++)
01929 {
01930 nzcnt = clen[basis[i]];
01931 beg = cbeg[basis[i]];
01932 for (j = 0; j < nzcnt; j++)
01933 {
01934 dbl_EGlpNumCopy (v, in_uccoef[beg + j]);
01935 if (!(dbl_EGlpNumIsNeqZero (v, f->fzero_tol)))
01936 continue;
01937 r = in_ucindx[beg + j];
01938 ucindx[uc_inf[i].nzcnt++] = r;
01939 urindx[ur_inf[r].nzcnt] = i;
01940 dbl_EGlpNumCopy (urcoef[ur_inf[r].nzcnt], v);
01941 ur_inf[r].nzcnt++;
01942 }
01943 }
01944
01945 for (i = 0; i < dim; i++)
01946 {
01947 uc_inf[i].nzcnt -= uc_inf[i].cbeg;
01948 ur_inf[i].nzcnt -= ur_inf[i].rbeg;
01949 }
01950
01951 j = f->uc_space;
01952 for (i = f->uc_freebeg; i < j; i++)
01953 {
01954 ucindx[i] = -1;
01955 }
01956 ucindx[j] = 0;
01957
01958 j = f->ur_space;
01959 for (i = f->ur_freebeg; i < j; i++)
01960 {
01961 urindx[i] = -1;
01962 }
01963 urindx[j] = 0;
01964
01965 for (i = 0; i < dim; i++)
01966 {
01967 nzcnt = ur_inf[i].nzcnt;
01968 ur_inf[i].pivcnt = nzcnt;
01969 beg = ur_inf[i].rbeg;
01970 dbl_EGlpNumZero (max);
01971 for (j = 0; j < nzcnt; j++)
01972 {
01973 dbl_EGlpNumSetToMaxAbs (max, urcoef[beg + j]);
01974 }
01975 dbl_EGlpNumCopy (ur_inf[i].max, max);
01976 }
01977
01978 for (i = 0; i <= max_k; i++)
01979 {
01980 ur_inf[dim + i].next = dim + i;
01981 ur_inf[dim + i].prev = dim + i;
01982 uc_inf[dim + i].next = dim + i;
01983 uc_inf[dim + i].prev = dim + i;
01984 }
01985
01986 for (i = 0; i < dim; i++)
01987 {
01988 nzcnt = uc_inf[i].nzcnt;
01989 if (nzcnt >= max_k)
01990 nzcnt = max_k;
01991 uc_inf[i].next = uc_inf[dim + nzcnt].next;
01992 uc_inf[i].prev = dim + nzcnt;
01993 uc_inf[dim + nzcnt].next = i;
01994 uc_inf[uc_inf[i].next].prev = i;
01995
01996 nzcnt = ur_inf[i].pivcnt;
01997 if (nzcnt >= max_k)
01998 nzcnt = max_k;
01999 ur_inf[i].next = ur_inf[dim + nzcnt].next;
02000 ur_inf[i].prev = dim + nzcnt;
02001 ur_inf[dim + nzcnt].next = i;
02002 ur_inf[ur_inf[i].next].prev = i;
02003 }
02004
02005 #ifdef dbl_TRACK_FACTOR
02006 dbl_EGlpNumZero (max);
02007 nzcnt = 0;
02008 for (i = 0; i < dim; i++)
02009 {
02010 if (dbl_EGlpNumIsLess (max, ur_inf[i].max))
02011 dbl_EGlpNumCopy (max, ur_inf[i].max);
02012 nzcnt += ur_inf[i].nzcnt;
02013 }
02014
02015 dbl_EGlpNumCopy (f->maxelem_orig, max);
02016 f->nzcnt_orig = nzcnt;
02017 dbl_EGlpNumCopy (f->maxelem_factor, f->maxelem_orig);
02018 f->nzcnt_factor = f->nzcnt_orig;
02019 #endif
02020
02021
02022 ucindx[f->uc_space] = 0;
02023
02024 dbl_clear_work (f);
02025
02026 CLEANUP:
02027 dbl_EGlpNumClearVar (max);
02028 dbl_EGlpNumClearVar (v);
02029 EG_RETURN (rval);
02030 }
02031
02032 static int dbl_build_iteration_u_data (
02033 dbl_factor_work * f)
02034 {
02035 int dim = f->dim;
02036 dbl_ur_info *ur_inf = f->ur_inf;
02037 dbl_uc_info *uc_inf = f->uc_inf;
02038 double *uccoef = 0;
02039 int *ucindx = 0;
02040 int *urindx = f->urindx;
02041 double *urcoef = f->urcoef;
02042 int *ucrind = 0;
02043 int *urcind = 0;
02044 int nzcnt;
02045 int beg;
02046 int cbeg;
02047 int cnzcnt;
02048 int uc_space = f->uc_space;
02049 int er_space;
02050 int i;
02051 int j;
02052 int k;
02053 int rval;
02054
02055 nzcnt = 0;
02056 for (i = 0; i < dim; i++)
02057 {
02058 nzcnt += ur_inf[i].nzcnt;
02059 }
02060
02061 #ifdef dbl_TRACK_FACTOR
02062 f->nzcnt_factor = nzcnt;
02063 #endif
02064
02065 dbl_EGlpNumFreeArray (f->uccoef);
02066 uccoef = dbl_EGlpNumAllocArray (nzcnt);
02067 f->uccoef = uccoef;
02068
02069 ILL_IFFREE (f->ucrind, int);
02070 ILL_SAFE_MALLOC (ucrind, nzcnt, int);
02071
02072 f->ucrind = ucrind;
02073
02074 ILL_IFFREE (f->urcind, int);
02075 ILL_SAFE_MALLOC (urcind, f->ur_space, int);
02076
02077 f->urcind = urcind;
02078
02079 if (uc_space < nzcnt)
02080 {
02081 ILL_IFFREE (f->ucindx, int);
02082 ILL_SAFE_MALLOC (f->ucindx, nzcnt + 1, int);
02083 }
02084 f->uc_space = nzcnt;
02085 uc_space = nzcnt;
02086 ucindx = f->ucindx;
02087
02088 for (i = 0; i < dim; i++)
02089 {
02090 uc_inf[i].nzcnt = 0;
02091 }
02092
02093 for (i = 0; i < dim; i++)
02094 {
02095 nzcnt = ur_inf[i].nzcnt;
02096 beg = ur_inf[i].rbeg;
02097 for (j = 0; j < nzcnt; j++)
02098 {
02099 uc_inf[urindx[beg + j]].nzcnt++;
02100 }
02101 ur_inf[i].delay = 0;
02102 }
02103
02104 nzcnt = 0;
02105 for (i = 0; i < dim; i++)
02106 {
02107 uc_inf[i].cbeg = nzcnt;
02108 nzcnt += uc_inf[i].nzcnt;
02109 uc_inf[i].nzcnt = 0;
02110 uc_inf[i].delay = 0;
02111 }
02112
02113 f->uc_freebeg = nzcnt;
02114 for (i = nzcnt; i < uc_space; i++)
02115 {
02116 ucindx[i] = -1;
02117 }
02118 ucindx[uc_space] = 0;
02119
02120 for (i = 0; i < dim; i++)
02121 {
02122 nzcnt = ur_inf[i].nzcnt;
02123 beg = ur_inf[i].rbeg;
02124 k = urindx[beg];
02125 cbeg = uc_inf[k].cbeg;
02126 cnzcnt = uc_inf[k].nzcnt;
02127 if (cnzcnt != 0)
02128 {
02129 ucindx[cbeg + cnzcnt] = ucindx[cbeg];
02130 dbl_EGlpNumCopy (uccoef[cbeg + cnzcnt], uccoef[cbeg]);
02131 ucrind[cbeg + cnzcnt] = ucrind[cbeg];
02132 urcind[ur_inf[ucindx[cbeg]].rbeg + ucrind[cbeg]] = cnzcnt;
02133 }
02134 ucindx[cbeg] = i;
02135 dbl_EGlpNumCopy (uccoef[cbeg], urcoef[beg]);
02136 ucrind[cbeg] = 0;
02137 urcind[beg] = 0;
02138 uc_inf[k].nzcnt = cnzcnt + 1;
02139 for (j = 1; j < nzcnt; j++)
02140 {
02141 k = urindx[beg + j];
02142 cbeg = uc_inf[k].cbeg;
02143 cnzcnt = uc_inf[k].nzcnt;
02144 ucindx[cbeg + cnzcnt] = i;
02145 dbl_EGlpNumCopy (uccoef[cbeg + cnzcnt], urcoef[beg + j]);
02146 ucrind[cbeg + cnzcnt] = j;
02147 urcind[beg + j] = cnzcnt;
02148 uc_inf[k].nzcnt++;
02149 }
02150 }
02151
02152 for (i = 0; i < dim; i++)
02153 {
02154 f->rrank[f->rperm[i]] = i;
02155 }
02156
02157 nzcnt = f->ur_space;
02158
02159 for (i = f->ur_freebeg; i < nzcnt; i++)
02160 {
02161 urindx[i] = -1;
02162 }
02163 urindx[nzcnt] = 0;
02164
02165 dbl_clear_work (f);
02166
02167 er_space = f->er_space_mul * f->etamax;
02168 ILL_SAFE_MALLOC (f->er_inf, f->etamax, dbl_er_info);
02169 ILL_SAFE_MALLOC (f->erindx, er_space, int);
02170
02171 f->ercoef = dbl_EGlpNumAllocArray (er_space);
02172 f->etacnt = 0;
02173 f->er_freebeg = 0;
02174 f->er_space = er_space;
02175
02176 rval = 0;
02177
02178 CLEANUP:
02179 EG_RETURN (rval);
02180 }
02181
02182 static int dbl_build_iteration_l_data (
02183 dbl_factor_work * f)
02184 {
02185 int dim = f->dim;
02186 dbl_lc_info *lc_inf = f->lc_inf;
02187 dbl_lr_info *lr_inf = f->lr_inf;
02188 double *lrcoef = 0;
02189 int *lrindx = 0;
02190 double *lccoef = f->lccoef;
02191 int *lcindx = f->lcindx;
02192 int nzcnt;
02193 int beg;
02194 int rnzcnt;
02195 int rbeg;
02196 int i;
02197 int j;
02198 int k;
02199 int c;
02200 int rval;
02201
02202 nzcnt = 0;
02203 for (i = 0; i < dim; i++)
02204 {
02205 nzcnt += lc_inf[i].nzcnt;
02206 lr_inf[i].nzcnt = 0;
02207 lr_inf[i].delay = 0;
02208 lc_inf[lc_inf[i].c].crank = i;
02209 }
02210
02211 dbl_EGlpNumFreeArray (f->lrcoef);
02212 if (nzcnt)
02213 {
02214 lrcoef = dbl_EGlpNumAllocArray (nzcnt);
02215 f->lrcoef = lrcoef;
02216 }
02217
02218 ILL_IFFREE (f->lrindx, int);
02219 ILL_SAFE_MALLOC (lrindx, nzcnt + 1, int);
02220
02221 f->lrindx = lrindx;
02222
02223 for (i = 0; i < dim; i++)
02224 {
02225 nzcnt = lc_inf[i].nzcnt;
02226 beg = lc_inf[i].cbeg;
02227 lc_inf[i].delay = 0;
02228 for (j = 0; j < nzcnt; j++)
02229 {
02230 lr_inf[lc_inf[lcindx[beg + j]].crank].nzcnt++;
02231 }
02232 }
02233
02234 nzcnt = 0;
02235 for (i = 0; i < dim; i++)
02236 {
02237 lr_inf[i].rbeg = nzcnt;
02238 nzcnt += lr_inf[i].nzcnt;
02239 lr_inf[i].nzcnt = 0;
02240 lr_inf[i].r = lc_inf[i].c;
02241 lr_inf[lr_inf[i].r].rrank = i;
02242 }
02243
02244 for (i = 0; i < dim; i++)
02245 {
02246 nzcnt = lc_inf[i].nzcnt;
02247 beg = lc_inf[i].cbeg;
02248 c = lc_inf[i].c;
02249 for (j = 0; j < nzcnt; j++)
02250 {
02251 k = lc_inf[lcindx[beg + j]].crank;
02252 rbeg = lr_inf[k].rbeg;
02253 rnzcnt = lr_inf[k].nzcnt;
02254 lrindx[rbeg + rnzcnt] = c;
02255 dbl_EGlpNumCopy (lrcoef[rbeg + rnzcnt], lccoef[beg + j]);
02256 lr_inf[k].nzcnt++;
02257 }
02258 }
02259
02260 #ifdef dbl_TRACK_FACTOR
02261 nzcnt = f->nzcnt_factor;
02262 for (i = 0; i < dim; i++)
02263 {
02264 nzcnt += lc_inf[i].nzcnt;
02265 }
02266 f->nzcnt_factor = nzcnt;
02267
02268 dbl_EGlpNumCopy (f->maxelem_cur, f->maxelem_factor);
02269 f->nzcnt_cur = f->nzcnt_factor;
02270
02271
02272
02273
02274
02275
02276 #endif
02277
02278 rval = 0;
02279
02280 CLEANUP:
02281 EG_RETURN (rval);
02282 }
02283
02284 static int dbl_handle_singularity (
02285 dbl_factor_work * f)
02286 {
02287 int rval = 0;
02288 int nsing;
02289 int *singr = 0;
02290 int *singc = 0;
02291 int i;
02292
02293 if (f->p_nsing == 0 || f->p_singr == 0 || f->p_singc == 0)
02294 {
02295 fprintf (stderr, "singular basis, but no place for singularity data\n");
02296 return E_SING_NO_DATA;
02297 }
02298
02299 nsing = f->nstages - f->stage;
02300 ILL_SAFE_MALLOC (singr, nsing, int);
02301 ILL_SAFE_MALLOC (singc, nsing, int);
02302
02303 for (i = f->stage; i < f->nstages; i++)
02304 {
02305 singr[i - f->stage] = f->rperm[i];
02306 singc[i - f->stage] = f->cperm[i];
02307 }
02308 *f->p_nsing = nsing;
02309 *f->p_singr = singr;
02310 *f->p_singc = singc;
02311 singr = 0;
02312 singc = 0;
02313
02314 CLEANUP:
02315 ILL_IFFREE (singr, int);
02316 ILL_IFFREE (singc, int);
02317
02318 EG_RETURN (rval);
02319 }
02320
02321 static int dbl_dense_build_matrix (
02322 dbl_factor_work * f)
02323 {
02324 double *dmat = 0;
02325 int stage = f->stage;
02326 int drows = f->nstages - stage;
02327 int dcols = f->dim - stage;
02328 int dsize = drows * dcols;
02329 int *crank = f->crank;
02330 double *urcoef = f->urcoef;
02331 int *urindx = f->urindx;
02332 int nzcnt;
02333 int beg;
02334 int i;
02335 int r;
02336 int j;
02337 int rval = 0;
02338
02339 dmat = dbl_EGlpNumAllocArray (dsize);
02340
02341 for (i = 0; i < dsize; i++)
02342 dbl_EGlpNumZero (dmat[i]);
02343
02344 for (i = 0; i < drows; i++)
02345 {
02346 r = f->rperm[i + stage];
02347 nzcnt = f->ur_inf[r].nzcnt;
02348 beg = f->ur_inf[r].rbeg;
02349 for (j = 0; j < nzcnt; j++)
02350 {
02351 dbl_EGlpNumCopy (dmat[i * dcols - stage + crank[urindx[beg + j]]],
02352 urcoef[beg + j]);
02353 }
02354 }
02355
02356 f->drows = drows;
02357 f->dcols = dcols;
02358 f->dense_base = f->stage;
02359 f->dmat = dmat;
02360 dmat = 0;
02361
02362
02363 dbl_EGlpNumFreeArray (dmat);
02364 EG_RETURN (rval);
02365 }
02366
02367 static int dbl_dense_find_pivot (
02368 dbl_factor_work * f,
02369 int *p_r,
02370 int *p_c)
02371 {
02372 int dcols = f->dcols;
02373 int drows = f->drows;
02374 double *dmat = f->dmat;
02375 int dense_base = f->dense_base;
02376 int s = f->stage - dense_base;
02377 dbl_ur_info *ur_inf = f->ur_inf;
02378 int *rperm = f->rperm;
02379 double maxval;
02380 int max_r;
02381 int max_c;
02382 int i;
02383
02384 dbl_EGlpNumInitVar (maxval);
02385 dbl_EGlpNumZero (maxval);
02386 max_r = -1;
02387 for (i = s; i < drows; i++)
02388 {
02389 if (dbl_EGlpNumIsLess (maxval, ur_inf[rperm[dense_base + i]].max))
02390 {
02391 dbl_EGlpNumCopy (maxval, ur_inf[rperm[dense_base + i]].max);
02392 max_r = i;
02393 }
02394 }
02395 if (max_r == -1)
02396 {
02397 return E_NO_PIVOT;
02398 }
02399
02400 dbl_EGlpNumZero (maxval);
02401 max_c = -1;
02402 for (i = s; i < drows; i++)
02403 {
02404 dbl_EGlpNumSetToMaxAbsAndDo (maxval, dmat[max_r * dcols + i], max_c = i);
02405 }
02406 if (max_c == -1)
02407 {
02408 return E_NO_PIVOT;
02409 }
02410 *p_r = max_r;
02411 *p_c = max_c;
02412
02413 dbl_EGlpNumClearVar (maxval);
02414 return 0;
02415 }
02416
02417 static void dbl_dense_swap (
02418 dbl_factor_work * f,
02419 int r,
02420 int c)
02421 {
02422 int dcols = f->dcols;
02423 int drows = f->drows;
02424 double *dmat = f->dmat;
02425 int dense_base = f->dense_base;
02426 int s = f->stage - dense_base;
02427 int i;
02428 double v;
02429
02430 dbl_EGlpNumInitVar (v);
02431
02432 if (r != s)
02433 {
02434 dbl_ILL_SWAP (f->rperm[dense_base + s], f->rperm[dense_base + r], i);
02435 f->rrank[f->rperm[dense_base + s]] = dense_base + s;
02436 f->rrank[f->rperm[dense_base + r]] = dense_base + r;
02437 for (i = 0; i < dcols; i++)
02438 {
02439 dbl_EGLPNUM_SWAP (dmat[s * dcols + i], dmat[r * dcols + i], v);
02440 }
02441 }
02442 if (c != s)
02443 {
02444 dbl_ILL_SWAP (f->cperm[dense_base + s], f->cperm[dense_base + c], i);
02445 f->crank[f->cperm[dense_base + s]] = dense_base + s;
02446 f->crank[f->cperm[dense_base + c]] = dense_base + c;
02447 for (i = 0; i < drows; i++)
02448 {
02449 dbl_EGLPNUM_SWAP (dmat[i * dcols + s], dmat[i * dcols + c], v);
02450 }
02451 }
02452 dbl_EGlpNumClearVar (v);
02453 }
02454
02455 static void dbl_dense_elim (
02456 dbl_factor_work * f,
02457 int r,
02458 int c)
02459 {
02460 int dcols = f->dcols;
02461 int drows = f->drows;
02462 double *dmat = f->dmat;
02463 int dense_base = f->dense_base;
02464 int s = f->stage - dense_base;
02465 dbl_ur_info *ur_inf = f->ur_inf;
02466 int *rperm = f->rperm;
02467 int i;
02468 int j;
02469 double pivval;
02470 double max;
02471 double v;
02472 double w;
02473
02474 #ifdef dbl_TRACK_FACTOR
02475 double maxelem_factor;
02476
02477 dbl_EGlpNumInitVar (maxelem_factor);
02478 dbl_EGlpNumCopy (maxelem_factor, f->maxelem_factor);
02479 #endif
02480 dbl_EGlpNumInitVar (pivval);
02481 dbl_EGlpNumInitVar (max);
02482 dbl_EGlpNumInitVar (v);
02483 dbl_EGlpNumInitVar (w);
02484
02485 dbl_dense_swap (f, r, c);
02486 f->stage++;
02487 dbl_EGlpNumCopyFrac (pivval, dbl_oneLpNum, dmat[s * dcols + s]);
02488 for (i = s + 1; i < drows; i++)
02489 {
02490 dbl_EGlpNumCopy (v, dmat[i * dcols + s]);
02491 if (dbl_EGlpNumIsNeqqZero (v))
02492 {
02493 dbl_EGlpNumMultTo (v, pivval);
02494 if (dbl_EGlpNumIsNeqZero (v, f->fzero_tol))
02495 {
02496 dbl_EGlpNumCopy (dmat[i * dcols + s], v);
02497 #ifdef dbl_TRACK_FACTOR
02498 dbl_EGlpNumSetToMaxAbs (maxelem_factor, v);
02499 #endif
02500 dbl_EGlpNumZero (max);
02501 for (j = s + 1; j < drows; j++)
02502 {
02503 dbl_EGlpNumCopy (w, dmat[i * dcols + j]);
02504 dbl_EGlpNumSubInnProdTo (w, v, dmat[s * dcols + j]);
02505 dbl_EGlpNumCopy (dmat[i * dcols + j], w);
02506 dbl_EGlpNumSetToMaxAbs (max, w);
02507 }
02508 for (j = drows; j < dcols; j++)
02509 {
02510 dbl_EGlpNumCopy (w, dmat[i * dcols + j]);
02511 dbl_EGlpNumSubInnProdTo (w, v, dmat[s * dcols + j]);
02512 dbl_EGlpNumCopy (dmat[i * dcols + j], w);
02513 }
02514 dbl_EGlpNumCopy (ur_inf[rperm[dense_base + i]].max, max);
02515 #ifdef dbl_TRACK_FACTOR
02516 if (dbl_EGlpNumIsLess (maxelem_factor, max))
02517 dbl_EGlpNumCopy (maxelem_factor, max);
02518 #endif
02519 }
02520 else
02521 {
02522 dbl_EGlpNumZero (dmat[i * dcols + s]);
02523 }
02524 }
02525 }
02526 #ifdef dbl_TRACK_FACTOR
02527 dbl_EGlpNumCopy (f->maxelem_factor, maxelem_factor);
02528 dbl_EGlpNumClearVar (maxelem_factor);
02529 #endif
02530 dbl_EGlpNumClearVar (pivval);
02531 dbl_EGlpNumClearVar (max);
02532 dbl_EGlpNumClearVar (v);
02533 dbl_EGlpNumClearVar (w);
02534 }
02535
02536 static int dbl_dense_replace_row (
02537 dbl_factor_work * f,
02538 int i)
02539 {
02540 int dcols = f->dcols;
02541 int dense_base = f->dense_base;
02542 double *dmat = f->dmat + i * dcols;
02543 double *urcoef;
02544 dbl_ur_info *ur_inf = f->ur_inf;
02545 int *cperm = f->cperm;
02546 int r = f->rperm[dense_base + i];
02547 int *urindx;
02548 int nzcnt;
02549 int beg;
02550 int j;
02551 int rval = 0;
02552
02553 nzcnt = 0;
02554 for (j = i; j < dcols; j++)
02555 {
02556 if (dbl_EGlpNumIsNeqZero (dmat[j], f->fzero_tol))
02557 {
02558 nzcnt++;
02559 }
02560 }
02561 if (nzcnt > ur_inf[r].nzcnt)
02562 {
02563 if (ur_inf[r].rbeg + ur_inf[r].nzcnt == f->ur_freebeg)
02564 {
02565 f->ur_freebeg = ur_inf[r].rbeg;
02566 }
02567 ur_inf[r].nzcnt = 0;
02568 if (f->ur_freebeg + nzcnt > f->ur_space)
02569 {
02570 rval = dbl_make_ur_space (f, nzcnt);
02571 CHECKRVALG (rval, CLEANUP);
02572 }
02573 ur_inf[r].rbeg = f->ur_freebeg;
02574 f->ur_freebeg += nzcnt;
02575 }
02576 beg = ur_inf[r].rbeg;
02577 urcoef = f->urcoef;
02578 urindx = f->urindx;
02579 for (j = i; j < dcols; j++)
02580 {
02581 if (dbl_EGlpNumIsNeqZero (dmat[j], f->fzero_tol))
02582 {
02583 dbl_EGlpNumCopy (urcoef[beg], dmat[j]);
02584 urindx[beg] = cperm[dense_base + j];
02585 beg++;
02586 }
02587 }
02588 ur_inf[r].nzcnt = beg - ur_inf[r].rbeg;
02589 CLEANUP:
02590 EG_RETURN (rval);
02591 }
02592
02593 static int dbl_dense_create_col (
02594 dbl_factor_work * f,
02595 int i)
02596 {
02597 int dcols = f->dcols;
02598 int drows = f->drows;
02599 int dense_base = f->dense_base;
02600 double *dmat = f->dmat;
02601 double *lccoef;
02602 dbl_lc_info *lc_inf = f->lc_inf;
02603 int *rperm = f->rperm;
02604 int *lcindx;
02605 int nzcnt;
02606 int beg;
02607 int j;
02608 int rval = 0;
02609
02610 nzcnt = 0;
02611 for (j = i + 1; j < drows; j++)
02612 {
02613 if (dbl_EGlpNumIsNeqZero (dmat[j * dcols + i], f->fzero_tol))
02614 {
02615 nzcnt++;
02616 }
02617 }
02618
02619 if (f->lc_freebeg + nzcnt >= f->lc_space)
02620 {
02621 rval = dbl_make_lc_space (f, nzcnt);
02622 CHECKRVALG (rval, CLEANUP);
02623 }
02624 beg = f->lc_freebeg;
02625 lc_inf[dense_base + i].cbeg = beg;
02626 lc_inf[dense_base + i].c = rperm[dense_base + i];
02627 lcindx = f->lcindx;
02628 lccoef = f->lccoef;
02629
02630 for (j = i + 1; j < drows; j++)
02631 {
02632 if (dbl_EGlpNumIsNeqZero (dmat[j * dcols + i], f->fzero_tol))
02633 {
02634 dbl_EGlpNumCopy (lccoef[beg], dmat[j * dcols + i]);
02635 lcindx[beg] = rperm[dense_base + j];
02636 beg++;
02637 }
02638 }
02639 lc_inf[dense_base + i].nzcnt = beg - lc_inf[dense_base + i].cbeg;
02640 f->lc_freebeg = beg;
02641 CLEANUP:
02642 EG_RETURN (rval);
02643 }
02644
02645 static int dbl_dense_replace (
02646 dbl_factor_work * f)
02647 {
02648 int drows = f->drows;
02649 int rval = 0;
02650 int i;
02651
02652 for (i = 0; i < drows; i++)
02653 {
02654 rval = dbl_dense_replace_row (f, i);
02655 CHECKRVALG (rval, CLEANUP);
02656 rval = dbl_dense_create_col (f, i);
02657 CHECKRVALG (rval, CLEANUP);
02658 }
02659 dbl_EGlpNumFreeArray (f->dmat);
02660 f->drows = 0;
02661 f->dcols = 0;
02662 CLEANUP:
02663 EG_RETURN (rval);
02664 }
02665
02666 static int dbl_dense_factor (
02667 dbl_factor_work * f)
02668 {
02669 int r;
02670 int c;
02671 int rval = 0;
02672
02673 #ifdef dbl_TRACK_FACTOR
02674 #ifdef dbl_NOTICE_BLOWUP
02675 double tmpsize;
02676 #endif
02677 #endif
02678
02679
02680
02681
02682
02683
02684
02685 rval = dbl_dense_build_matrix (f);
02686 CHECKRVALG (rval, CLEANUP);
02687
02688 #ifdef dbl_FACTOR_DEBUG
02689 #if (dbl_FACTOR_DEBUG+0>1)
02690 MESSAGE (0,"before Dense dbl_ILLfactor");
02691 dbl_dump_matrix (f, 1);
02692 #endif
02693 #endif
02694
02695 while (f->stage < f->nstages)
02696 {
02697 r = f->stage - f->dense_base;
02698 rval = dbl_dense_find_pivot (f, &r, &c);
02699 if (rval == E_NO_PIVOT)
02700 {
02701 rval = dbl_handle_singularity (f);
02702 CHECKRVALG (rval, CLEANUP);
02703 return E_SINGULAR_INTERNAL;
02704 }
02705 else
02706 {
02707 CHECKRVALG (rval, CLEANUP);
02708 }
02709 #ifdef dbl_FACTOR_DEBUG
02710 #if (dbl_FACTOR_DEBUG+0>2)
02711 MESSAGE (0,"dense pivot elem: %d %d", r, c);
02712 #endif
02713 #endif
02714 dbl_dense_elim (f, r, c);
02715
02716 #ifdef dbl_TRACK_FACTOR
02717 #ifdef dbl_NOTICE_BLOWUP
02718 tmpsize = f->maxmult * dbl_EGlpNumToLf (f->maxelem_orig);
02719 if (tmpsize < dbl_EGlpNumToLf (f->maxelem_factor) &&
02720 dbl_EGlpNumIsLess (f->partial_cur, dbl_oneLpNum))
02721 {
02722 return E_FACTOR_BLOWUP;
02723 }
02724 #endif
02725 #endif
02726
02727 #ifdef dbl_FACTOR_DEBUG
02728 #if (dbl_FACTOR_DEBUG+0>1)
02729 MESSAGE (0,"After dense pivot stage %d (%d) of %d (%d)",
02730 f->stage - f->dense_base, f->stage,
02731 f->nstages - f->dense_base, f->nstages);
02732 #endif
02733 #if (dbl_FACTOR_DEBUG+0>2)
02734 dbl_dump_matrix (f, 1);
02735 #endif
02736 #endif
02737 }
02738
02739 #ifdef dbl_FACTOR_DEBUG
02740 MESSAGE (0,"After dense dbl_ILLfactor:\n");
02741 dbl_dump_matrix (f, 0);
02742 #endif
02743
02744 rval = dbl_dense_replace (f);
02745 CHECKRVALG (rval, CLEANUP);
02746
02747 #ifdef dbl_FACTOR_DEBUG
02748 MESSAGE (0,"After replacement:\n");
02749 dbl_dump_matrix (f, 0);
02750 #endif
02751
02752 CLEANUP:
02753 EG_RETURN (rval);
02754 }
02755
02756 #ifdef dbl_RECORD
02757 FILE *dbl_fsave = 0;
02758 int dbl_fsavecnt = 0;
02759 #endif
02760
02761 static int dbl_ILLfactor_try (
02762 dbl_factor_work * f,
02763 int *basis,
02764 int *cbeg,
02765 int *clen,
02766 int *cindx,
02767 double * ccoef)
02768 {
02769 int rval = 0;
02770 int r;
02771 int c;
02772
02773 #ifdef dbl_TRACK_FACTOR
02774 #ifdef dbl_NOTICE_BLOWUP
02775 double tmpsize;
02776
02777 dbl_EGlpNumInitVar (tmpsize);
02778 #endif
02779 #endif
02780
02781 #ifdef dbl_RECORD
02782 {
02783 int ncol = 0;
02784 int nzcnt = 0;
02785 int dim = f->dim;
02786 int i;
02787 int j;
02788 char fnambuf[40];
02789
02790 for (i = 0; i < dim; i++)
02791 {
02792 if (basis[i] > ncol)
02793 ncol = basis[i];
02794 }
02795 ncol++;
02796 for (i = 0; i < ncol; i++)
02797 {
02798 nzcnt += clen[i];
02799 }
02800 if (dbl_fsave)
02801 fclose (dbl_fsave);
02802 sprintf (fnambuf, "prob.mat.%d", dbl_fsavecnt);
02803 dbl_fsavecnt++;
02804 dbl_fsave = fopen (fnambuf, "w");
02805 fprintf (dbl_fsave, "%d %d %d\n", f->dim, ncol, nzcnt);
02806 for (i = 0; i < dim; i++)
02807 {
02808 fprintf (dbl_fsave, "%d ", basis[i]);
02809 }
02810 fprintf (dbl_fsave, "\n");
02811 for (i = 0; i < ncol; i++)
02812 {
02813 fprintf (dbl_fsave, "%d", clen[i]);
02814 for (j = 0; j < clen[i]; j++)
02815 {
02816 fprintf (dbl_fsave, " %d %.16lg", cindx[cbeg[i] + j],
02817 dbl_EGlpNumToLf (ccoef[cbeg[i] + j]));
02818 }
02819 fprintf (dbl_fsave, "\n");
02820 }
02821 fprintf (dbl_fsave, "\n");
02822 fflush (dbl_fsave);
02823 }
02824 #endif
02825
02826 rval = dbl_init_matrix (f, basis, cbeg, clen, cindx, ccoef);
02827 CHECKRVALG (rval, CLEANUP);
02828
02829 f->stage = 0;
02830 f->nstages = f->dim;
02831
02832 #ifdef dbl_FACTOR_DEBUG
02833 MESSAGE (0,"Initial matrix:");
02834 #if (dbl_FACTOR_DEBUG+0>1)
02835 dbl_dump_matrix (f, 0);
02836 #endif
02837 #endif
02838 #ifdef dbl_FACTOR_STATS
02839 printf ("Initial matrix: ");
02840 dbl_dump_factor_stats (f);
02841 #endif
02842
02843 while (f->stage < f->nstages)
02844 {
02845 rval = dbl_find_pivot (f, &r, &c);
02846 if (rval == E_NO_PIVOT)
02847 {
02848 rval = dbl_handle_singularity (f);
02849 CHECKRVALG (rval, CLEANUP);
02850 return 0;
02851 }
02852 else
02853 {
02854 CHECKRVALG (rval, CLEANUP);
02855 }
02856 if (f->ur_inf[r].pivcnt > f->dense_fract * (f->nstages - f->stage) &&
02857 f->uc_inf[c].nzcnt > f->dense_fract * (f->nstages - f->stage) &&
02858 f->nstages - f->stage > f->dense_min)
02859 {
02860 rval = dbl_dense_factor (f);
02861 if (rval == E_SINGULAR_INTERNAL)
02862 return 0;
02863 if (rval)
02864 return rval;
02865 break;
02866 }
02867 #ifdef dbl_FACTOR_DEBUG
02868 MESSAGE (0,"pivot elem: %d %d", r, c);
02869 #endif
02870 rval = dbl_elim (f, r, c);
02871 CHECKRVALG (rval, CLEANUP);
02872
02873 #ifdef dbl_TRACK_FACTOR
02874 #ifdef dbl_NOTICE_BLOWUP
02875 dbl_EGlpNumSet (tmpsize, f->maxmult);
02876 dbl_EGlpNumMultTo (tmpsize, f->maxelem_orig);
02877 if (dbl_EGlpNumIsLess (tmpsize, f->maxelem_factor) &&
02878 dbl_EGlpNumIsLess (f->partial_cur, dbl_oneLpNum))
02879 {
02880 return E_FACTOR_BLOWUP;
02881 }
02882 #endif
02883 #endif
02884
02885 #ifdef dbl_FACTOR_DEBUG
02886 #if (dbl_FACTOR_DEBUG+0>3)
02887 MESSAGE (0,"After pivot stage %d of %d", f->stage, f->nstages);
02888 dbl_dump_matrix (f, 0);
02889 #endif
02890 #endif
02891 }
02892
02893 rval = dbl_build_iteration_u_data (f);
02894 CHECKRVALG (rval, CLEANUP);
02895
02896 rval = dbl_build_iteration_l_data (f);
02897 CHECKRVALG (rval, CLEANUP);
02898
02899 #ifdef dbl_TRACK_FACTOR
02900 #ifdef dbl_NOTICE_BLOWUP
02901 dbl_EGlpNumSet (tmpsize, f->minmult);
02902 dbl_EGlpNumMultTo (tmpsize, f->maxelem_orig);
02903 if (dbl_EGlpNumIsLess (f->maxelem_factor, tmpsize) &&
02904 dbl_EGlpNumIsLess (f->partial_tol, f->partial_cur))
02905 {
02906 if (dbl_EGlpNumIsGreaDbl (f->partial_cur, 0.5))
02907 {
02908 dbl_EGlpNumSet (f->partial_cur, 0.5);
02909 }
02910 else if (dbl_EGlpNumIsGreaDbl (f->partial_cur, 0.25))
02911 {
02912 dbl_EGlpNumSet (f->partial_cur, 0.25);
02913 }
02914 else if (dbl_EGlpNumIsGreaDbl (f->partial_cur, 0.1))
02915 {
02916 dbl_EGlpNumSet (f->partial_cur, 0.1);
02917 }
02918 else
02919 {
02920 dbl_EGlpNumDivUiTo (f->partial_cur, 10);
02921 }
02922 if (dbl_EGlpNumIsLess (f->partial_cur, f->partial_tol))
02923 {
02924 dbl_EGlpNumCopy (f->partial_cur, f->partial_tol);
02925 }
02926
02927
02928
02929
02930 }
02931 #endif
02932 #endif
02933
02934 #ifdef dbl_FACTOR_DEBUG
02935 MESSAGE(0,"Factored matrix:");
02936 #if (dbl_FACTOR_DEBUG+0>1)
02937 dbl_dump_matrix (f, 0);
02938 #endif
02939 #endif
02940
02941 #ifdef dbl_FACTOR_STATS
02942 printf ("Factored matrix: ");
02943 dbl_dump_factor_stats (f);
02944 #endif
02945 CLEANUP:
02946 #ifdef dbl_TRACK_FACTOR
02947 #ifdef dbl_NOTICE_BLOWUP
02948 dbl_EGlpNumClearVar (tmpsize);
02949 #endif
02950 #endif
02951 EG_RETURN (rval);
02952 }
02953
02954 int dbl_ILLfactor (
02955 dbl_factor_work * f,
02956 int *basis,
02957 int *cbeg,
02958 int *clen,
02959 int *cindx,
02960 double * ccoef,
02961 int *p_nsing,
02962 int **p_singr,
02963 int **p_singc)
02964 {
02965 int rval;
02966
02967 f->p_nsing = p_nsing;
02968 f->p_singr = p_singr;
02969 f->p_singc = p_singc;
02970 *p_nsing = 0;
02971
02972 AGAIN:
02973 rval = dbl_ILLfactor_try (f, basis, cbeg, clen, cindx, ccoef);
02974 if (rval == E_FACTOR_BLOWUP)
02975 {
02976 if (dbl_EGlpNumIsLessDbl (f->partial_cur, 0.1))
02977 {
02978 dbl_EGlpNumMultUiTo (f->partial_cur, 10);
02979 }
02980 else if (dbl_EGlpNumIsLessDbl (f->partial_cur, 0.25))
02981 {
02982 dbl_EGlpNumSet (f->partial_cur, 0.25);
02983 }
02984 else if (dbl_EGlpNumIsLessDbl (f->partial_cur, 0.5))
02985 {
02986 dbl_EGlpNumSet (f->partial_cur, 0.5);
02987 }
02988 else if (dbl_EGlpNumIsLess (f->partial_cur, dbl_oneLpNum))
02989 {
02990 dbl_EGlpNumOne (f->partial_cur);
02991 }
02992 else
02993 {
02994 EG_RETURN (rval);
02995 }
02996
02997
02998
02999
03000 goto AGAIN;
03001 }
03002 EG_RETURN (rval);
03003 }
03004
03005 static void dbl_ILLfactor_ftranl (
03006 dbl_factor_work * f,
03007 double * a)
03008 {
03009 int *lcindx = f->lcindx;
03010 dbl_lc_info *lc_inf = f->lc_inf;
03011 double *lccoef = f->lccoef;
03012 int dim = f->dim;
03013 int beg;
03014 int nzcnt;
03015 int i;
03016 int j;
03017 double v;
03018
03019 dbl_EGlpNumInitVar (v);
03020
03021 for (i = 0; i < dim; i++)
03022 {
03023 dbl_EGlpNumCopy (v, a[lc_inf[i].c]);
03024 if (dbl_EGlpNumIsNeqqZero (v))
03025 {
03026 nzcnt = lc_inf[i].nzcnt;
03027 beg = lc_inf[i].cbeg;
03028 for (j = 0; j < nzcnt; j++)
03029 {
03030 dbl_EGlpNumSubInnProdTo (a[lcindx[beg + j]], v, lccoef[beg + j]);
03031 }
03032 }
03033 #ifdef dbl_SOLVE_DEBUG
03034 #if (dbl_SOLVE_DEBUG+0 > 1)
03035 fpritf (stderr,"dbl_ILLfactor_ftran a after l %d:", i);
03036 for (j = 0; j < f->dim; j++)
03037 {
03038 fprintf (stderr," %.3f", dbl_EGlpNumToLf (a[j]));
03039 }
03040 MESSAGE(0," ");
03041 #endif
03042 #endif
03043 }
03044 #ifdef dbl_SOLVE_DEBUG
03045 #if (dbl_SOLVE_DEBUG+0 <= 1)
03046 printf ("dbl_ILLfactor_ftran a after l:");
03047 for (j = 0; j < f->dim; j++)
03048 {
03049 printf (" %.3f", dbl_EGlpNumToLf (a[j]));
03050 }
03051 printf ("\n");
03052 fflush (stdout);
03053 #endif
03054 #endif
03055 dbl_EGlpNumClearVar (v);
03056 }
03057
03058 #if 0
03059 static void ftranl3_delay (
03060 dbl_factor_work * f,
03061 int c)
03062 {
03063 dbl_lc_info *lc_inf = f->lc_inf;
03064 int nzcnt;
03065 int *indx;
03066 int i;
03067
03068 c = lc_inf[c].crank;
03069 nzcnt = lc_inf[c].nzcnt;
03070 indx = f->lcindx + lc_inf[c].cbeg;
03071 for (i = 0; i < nzcnt; i++)
03072 {
03073 c = indx[i];
03074 if (lc_inf[c].delay++ == 0)
03075 {
03076 ftranl3_delay (f, c);
03077 }
03078 }
03079 }
03080 #endif
03081
03082 static void dbl_ftranl3_delay2 (
03083 dbl_factor_work * f,
03084 int c)
03085 {
03086 dbl_lc_info *lc_inf = f->lc_inf;
03087 int nzcnt;
03088 int *indx;
03089 int i;
03090 int last;
03091
03092 do
03093 {
03094 c = lc_inf[c].crank;
03095 nzcnt = lc_inf[c].nzcnt;
03096 indx = f->lcindx + lc_inf[c].cbeg;
03097 last = -1;
03098 for (i = 0; i < nzcnt; i++)
03099 {
03100 c = indx[i];
03101 if (lc_inf[c].delay++ == 0)
03102 {
03103 if (last >= 0)
03104 {
03105 dbl_ftranl3_delay2 (f, last);
03106 }
03107 last = c;
03108 }
03109 }
03110 c = last;
03111 } while (c >= 0);
03112 }
03113
03114 #if 0
03115 static void ftranl3_process (
03116 dbl_factor_work * f,
03117 int c,
03118 dbl_svector * x)
03119 {
03120 dbl_lc_info *lc_inf = f->lc_inf;
03121 double *work = f->work_coef;
03122 int nzcnt;
03123 int *indx;
03124 int i;
03125 double *coef;
03126 double v;
03127
03128 dbl_EGlpNumInitVar (v);
03129
03130 dbl_EGlpNumCopy (v, work[c]);
03131 dbl_EGlpNumZero (work[c]);
03132 if (dbl_EGlpNumIsNeqqZero (v))
03133 {
03134 x->indx[x->nzcnt] = c;
03135 dbl_EGlpNumCopy (x->coef[x->nzcnt], v);
03136 x->nzcnt++;
03137 }
03138 c = lc_inf[c].crank;
03139 nzcnt = lc_inf[c].nzcnt;
03140 indx = f->lcindx + lc_inf[c].cbeg;
03141 coef = f->lccoef + lc_inf[c].cbeg;
03142 for (i = 0; i < nzcnt; i++)
03143 {
03144 c = indx[i];
03145 dbl_EGlpNumSubInnProdTo (work[c], v, coef[i]);
03146 if (--lc_inf[c].delay == 0)
03147 {
03148 ftranl3_process (f, c, x);
03149 }
03150 }
03151 dbl_EGlpNumClearVar (v);
03152 }
03153 #endif
03154
03155 static void dbl_ftranl3_process2 (
03156 dbl_factor_work * f,
03157 int c,
03158 dbl_svector * x)
03159 {
03160 dbl_lc_info *lc_inf = f->lc_inf;
03161 double *work = f->work_coef;
03162 int nzcnt;
03163 int *indx;
03164 double *coef;
03165 int i;
03166 int last;
03167 double v;
03168
03169 dbl_EGlpNumInitVar (v);
03170
03171 do
03172 {
03173 dbl_EGlpNumCopy (v, work[c]);
03174 dbl_EGlpNumZero (work[c]);
03175 if (dbl_EGlpNumIsNeqqZero (v))
03176 {
03177 x->indx[x->nzcnt] = c;
03178 dbl_EGlpNumCopy (x->coef[x->nzcnt], v);
03179 x->nzcnt++;
03180 }
03181 c = lc_inf[c].crank;
03182 nzcnt = lc_inf[c].nzcnt;
03183 indx = f->lcindx + lc_inf[c].cbeg;
03184 coef = f->lccoef + lc_inf[c].cbeg;
03185 last = -1;
03186 for (i = 0; i < nzcnt; i++)
03187 {
03188 c = indx[i];
03189 dbl_EGlpNumSubInnProdTo (work[c], v, coef[i]);
03190 if (--lc_inf[c].delay == 0)
03191 {
03192 if (last >= 0)
03193 {
03194 dbl_ftranl3_process2 (f, last, x);
03195 }
03196 last = c;
03197 }
03198 }
03199 c = last;
03200 } while (c >= 0);
03201 dbl_EGlpNumClearVar (v);
03202 }
03203
03204 static void dbl_ILLfactor_ftranl3 (
03205 dbl_factor_work * f,
03206 dbl_svector * a,
03207 dbl_svector * x)
03208 {
03209 double *work = f->work_coef;
03210 int anzcnt = a->nzcnt;
03211 int *aindx = a->indx;
03212 double *acoef = a->coef;
03213 dbl_lc_info *lc_inf = f->lc_inf;
03214 int i;
03215
03216 for (i = 0; i < anzcnt; i++)
03217 {
03218 if (lc_inf[aindx[i]].delay++ == 0)
03219 {
03220 dbl_ftranl3_delay2 (f, aindx[i]);
03221 }
03222 dbl_EGlpNumCopy (work[aindx[i]], acoef[i]);
03223 }
03224 x->nzcnt = 0;
03225 for (i = 0; i < anzcnt; i++)
03226 {
03227 if (--lc_inf[aindx[i]].delay == 0)
03228 {
03229 dbl_ftranl3_process2 (f, aindx[i], x);
03230 }
03231 }
03232 #ifdef dbl_SOLVE_DEBUG
03233 printf ("dbl_ILLfactor_ftran x after l3:");
03234 for (i = 0; i < x->nzcnt; i++)
03235 {
03236 printf (" %.3f*%d", dbl_EGlpNumToLf (x->coef[i]), x->indx[i]);
03237 }
03238 printf ("\n");
03239 fflush (stdout);
03240 #endif
03241 }
03242
03243 static void dbl_ILLfactor_ftrane (
03244 dbl_factor_work * f,
03245 double * a)
03246 {
03247 int *erindx = f->erindx;
03248 double *ercoef = f->ercoef;
03249 dbl_er_info *er_inf = f->er_inf;
03250 int etacnt = f->etacnt;
03251 int beg;
03252 int nzcnt;
03253 int i;
03254 int j;
03255 double v;
03256
03257 dbl_EGlpNumInitVar (v);
03258
03259 for (i = 0; i < etacnt; i++)
03260 {
03261 dbl_EGlpNumCopy (v, a[er_inf[i].r]);
03262 nzcnt = er_inf[i].nzcnt;
03263 beg = er_inf[i].rbeg;
03264 for (j = 0; j < nzcnt; j++)
03265 {
03266 dbl_EGlpNumSubInnProdTo (v, ercoef[beg + j], a[erindx[beg + j]]);
03267 }
03268 dbl_EGlpNumCopy (a[er_inf[i].r], v);
03269 #ifdef dbl_SOLVE_DEBUG
03270 #if (dbl_SOLVE_DEBUG+0 > 1)
03271 printf ("dbl_ILLfactor_ftran a after eta %d:", i);
03272 for (j = 0; j < f->dim; j++)
03273 {
03274 printf (" %.3f", dbl_EGlpNumToLf (a[j]));
03275 }
03276 printf ("\n");
03277 fflush (stdout);
03278 #endif
03279 #endif
03280 }
03281 #ifdef dbl_SOLVE_DEBUG
03282 #if (dbl_SOLVE_DEBUG+0 <= 1)
03283 printf ("dbl_ILLfactor_ftran a after eta:");
03284 for (j = 0; j < f->dim; j++)
03285 {
03286 printf (" %.3f", dbl_EGlpNumToLf (a[j]));
03287 }
03288 printf ("\n");
03289 fflush (stdout);
03290 #endif
03291 #endif
03292 dbl_EGlpNumClearVar (v);
03293 }
03294
03295 static void dbl_ILLfactor_ftrane2 (
03296 dbl_factor_work * f,
03297 dbl_svector * a)
03298 {
03299 int *erindx = f->erindx;
03300 double *ercoef = f->ercoef;
03301 dbl_er_info *er_inf = f->er_inf;
03302 int etacnt = f->etacnt;
03303 int beg;
03304 int nzcnt;
03305 int anzcnt = a->nzcnt;
03306 int *aindx = a->indx;
03307 double *acoef = a->coef;
03308 double *work_coef = f->work_coef;
03309 int *work_indx = f->work_indx;
03310 int i;
03311 int j;
03312 int r;
03313 double v;
03314
03315 dbl_EGlpNumInitVar (v);
03316
03317 for (i = 0; i < anzcnt; i++)
03318 {
03319 dbl_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
03320 work_indx[aindx[i]] = i + 1;
03321 }
03322 for (i = 0; i < etacnt; i++)
03323 {
03324 r = er_inf[i].r;
03325 dbl_EGlpNumCopy (v, work_coef[r]);
03326 nzcnt = er_inf[i].nzcnt;
03327 beg = er_inf[i].rbeg;
03328 for (j = 0; j < nzcnt; j++)
03329 {
03330 dbl_EGlpNumSubInnProdTo (v, ercoef[beg + j], work_coef[erindx[beg + j]]);
03331 }
03332 if (dbl_EGlpNumIsNeqqZero (v))
03333 {
03334 dbl_EGlpNumCopy (work_coef[r], v);
03335 if (work_indx[r] == 0)
03336 {
03337 dbl_EGlpNumCopy (acoef[anzcnt], v);
03338 aindx[anzcnt] = r;
03339 work_indx[r] = anzcnt + 1;
03340 anzcnt++;
03341 }
03342 else
03343 {
03344 dbl_EGlpNumCopy (acoef[work_indx[r] - 1], v);
03345 }
03346 }
03347 else
03348 {
03349 dbl_EGlpNumZero (work_coef[r]);
03350 if (work_indx[r])
03351 {
03352 dbl_EGlpNumZero (acoef[work_indx[r] - 1]);
03353 }
03354 }
03355 #ifdef dbl_SOLVE_DEBUG
03356 #if (dbl_SOLVE_DEBUG+0 > 1)
03357 printf ("dbl_ILLfactor_ftran a after eta2 %d:", i);
03358 for (j = 0; j < anzcnt; j++)
03359 {
03360 printf (" %.3f*%d", dbl_EGlpNumToLf (acoef[j]), aindx[j]);
03361 }
03362 printf ("\n");
03363 fflush (stdout);
03364 #endif
03365 #endif
03366 }
03367 i = 0;
03368 while (i < anzcnt)
03369 {
03370 dbl_EGlpNumZero (work_coef[aindx[i]]);
03371 work_indx[aindx[i]] = 0;
03372 if (dbl_EGlpNumIsNeqZero (acoef[i], f->fzero_tol))
03373 {
03374
03375 i++;
03376 }
03377 else
03378 {
03379 --anzcnt;
03380 dbl_EGlpNumCopy (acoef[i], acoef[anzcnt]);
03381 aindx[i] = aindx[anzcnt];
03382 }
03383 }
03384 a->nzcnt = anzcnt;
03385
03386 #ifdef dbl_SOLVE_DEBUG
03387 #if (dbl_SOLVE_DEBUG+0 <= 1)
03388 printf ("dbl_ILLfactor_ftran a after eta2:");
03389 for (j = 0; j < anzcnt; j++)
03390 {
03391 printf (" %.3f*%d", dbl_EGlpNumToLf (acoef[j]), aindx[j]);
03392 }
03393 printf ("\n");
03394 fflush (stdout);
03395 #endif
03396 #endif
03397 dbl_EGlpNumClearVar (v);
03398 }
03399
03400 static void dbl_ILLfactor_ftranu (
03401 dbl_factor_work * f,
03402 double * a,
03403 dbl_svector * x)
03404 {
03405 int *ucindx = f->ucindx;
03406 double *uccoef = f->uccoef;
03407 dbl_uc_info *uc_inf = f->uc_inf;
03408 int *cperm = f->cperm;
03409 int *rperm = f->rperm;
03410 int dim = f->dim;
03411 int xnzcnt = 0;
03412 int *xindx = x->indx;
03413 double *xcoef = x->coef;
03414 int nzcnt;
03415 int beg;
03416 int i;
03417 int j;
03418 double v;
03419
03420 dbl_EGlpNumInitVar (v);
03421
03422 for (i = dim - 1; i >= 0; i--)
03423 {
03424 dbl_EGlpNumCopy (v, a[rperm[i]]);
03425 if (dbl_EGlpNumIsNeqqZero (v))
03426 {
03427 j = cperm[i];
03428 beg = uc_inf[j].cbeg;
03429 dbl_EGlpNumDivTo (v, uccoef[beg]);
03430 if (dbl_EGlpNumIsNeqZero (v, f->szero_tol))
03431 {
03432
03433 xindx[xnzcnt] = j;
03434 dbl_EGlpNumCopy (xcoef[xnzcnt], v);
03435 xnzcnt++;
03436 }
03437 nzcnt = uc_inf[j].nzcnt;
03438 for (j = 1; j < nzcnt; j++)
03439 {
03440 dbl_EGlpNumSubInnProdTo (a[ucindx[beg + j]], v, uccoef[beg + j]);
03441 }
03442 dbl_EGlpNumZero (a[rperm[i]]);
03443 }
03444 }
03445 x->nzcnt = xnzcnt;
03446 #ifdef dbl_SOLVE_DEBUG
03447 printf ("dbl_ILLfactor_ftran x after u:");
03448 for (j = 0; j < x->nzcnt; j++)
03449 {
03450 printf (" %.3f*%d", dbl_EGlpNumToLf (x->coef[j]), x->indx[j]);
03451 }
03452 printf ("\n");
03453 fflush (stdout);
03454 #endif
03455 dbl_EGlpNumClearVar (v);
03456 }
03457
03458
03459 #if 0
03460 static void ftranu3_delay (
03461 dbl_factor_work * f,
03462 int c)
03463 {
03464 dbl_uc_info *uc_inf = f->uc_inf;
03465 int nzcnt;
03466 int *indx;
03467 int i;
03468
03469 c = f->cperm[f->rrank[c]];
03470 nzcnt = uc_inf[c].nzcnt;
03471 indx = f->ucindx + uc_inf[c].cbeg;
03472 for (i = 1; i < nzcnt; i++)
03473 {
03474 c = indx[i];
03475 if (uc_inf[c].delay++ == 0)
03476 {
03477 ftranu3_delay (f, c);
03478 }
03479 }
03480 }
03481 #endif
03482
03483 static void dbl_ftranu3_delay2 (
03484 dbl_factor_work * f,
03485 int c)
03486 {
03487 dbl_uc_info *uc_inf = f->uc_inf;
03488 int nzcnt;
03489 int *indx;
03490 int i;
03491 int last;
03492
03493 do
03494 {
03495 c = f->cperm[f->rrank[c]];
03496 nzcnt = uc_inf[c].nzcnt;
03497 indx = f->ucindx + uc_inf[c].cbeg;
03498 last = -1;
03499 for (i = 1; i < nzcnt; i++)
03500 {
03501 c = indx[i];
03502 if (uc_inf[c].delay++ == 0)
03503 {
03504 if (last >= 0)
03505 {
03506 dbl_ftranu3_delay2 (f, last);
03507 }
03508 last = c;
03509 }
03510 }
03511 c = last;
03512 } while (c >= 0);
03513 }
03514
03515 #if 0
03516 static void ftranu3_process (
03517 dbl_factor_work * f,
03518 int c,
03519 dbl_svector * x)
03520 {
03521 dbl_uc_info *uc_inf = f->uc_inf;
03522 double *work = f->work_coef;
03523 int nzcnt;
03524 int *indx;
03525 double *coef;
03526 int i;
03527 double v;
03528
03529 dbl_EGlpNumInitVar (v);
03530
03531 dbl_EGlpNumCopy (v, work[c]);
03532 dbl_EGlpNumZero (work[c]);
03533 c = f->cperm[f->rrank[c]];
03534 nzcnt = uc_inf[c].nzcnt;
03535 indx = f->ucindx + uc_inf[c].cbeg;
03536 coef = f->uccoef + uc_inf[c].cbeg;
03537 dbl_EGlpNumDivTo (v, coef[0]);
03538 if (dbl_EGlpNumIsNeqZero (v, f->szero_tol))
03539
03540 {
03541 x->indx[x->nzcnt] = c;
03542 dbl_EGlpNumCopy (x->coef[x->nzcnt], v);
03543 x->nzcnt++;
03544 }
03545 for (i = 1; i < nzcnt; i++)
03546 {
03547 c = indx[i];
03548 dbl_EGlpNumSubInnProdTo (work[c], v, coef[i]);
03549 if (--uc_inf[c].delay == 0)
03550 {
03551 ftranu3_process (f, c, x);
03552 }
03553 }
03554 dbl_EGlpNumClearVar (v);
03555 }
03556 #endif
03557
03558 static void dbl_ftranu3_process2 (
03559 dbl_factor_work * f,
03560 int c,
03561 dbl_svector * x)
03562 {
03563 dbl_uc_info *uc_inf = f->uc_inf;
03564 double *work = f->work_coef;
03565 int nzcnt;
03566 int *indx;
03567 double *coef;
03568 int i;
03569 int last;
03570 double v;
03571
03572 dbl_EGlpNumInitVar (v);
03573
03574 do
03575 {
03576 dbl_EGlpNumCopy (v, work[c]);
03577 dbl_EGlpNumZero (work[c]);
03578 c = f->cperm[f->rrank[c]];
03579 nzcnt = uc_inf[c].nzcnt;
03580 indx = f->ucindx + uc_inf[c].cbeg;
03581 coef = f->uccoef + uc_inf[c].cbeg;
03582 dbl_EGlpNumDivTo (v, coef[0]);
03583 if (dbl_EGlpNumIsNeqZero (v, f->szero_tol))
03584
03585 {
03586 x->indx[x->nzcnt] = c;
03587 dbl_EGlpNumCopy (x->coef[x->nzcnt], v);
03588 x->nzcnt++;
03589 }
03590 last = -1;
03591 for (i = 1; i < nzcnt; i++)
03592 {
03593 c = indx[i];
03594 dbl_EGlpNumSubInnProdTo (work[c], v, coef[i]);
03595 if (--uc_inf[c].delay == 0)
03596 {
03597 if (last >= 0)
03598 {
03599 dbl_ftranu3_process2 (f, last, x);
03600 }
03601 last = c;
03602 }
03603 }
03604 c = last;
03605 } while (c >= 0);
03606 dbl_EGlpNumClearVar (v);
03607 }
03608
03609 static void dbl_ILLfactor_ftranu3 (
03610 dbl_factor_work * f,
03611 dbl_svector * a,
03612 dbl_svector * x)
03613 {
03614 double *work = f->work_coef;
03615 int anzcnt = a->nzcnt;
03616 int *aindx = a->indx;
03617 double *acoef = a->coef;
03618 dbl_uc_info *uc_inf = f->uc_inf;
03619 int i;
03620
03621 for (i = 0; i < anzcnt; i++)
03622 {
03623 if (uc_inf[aindx[i]].delay++ == 0)
03624 {
03625 dbl_ftranu3_delay2 (f, aindx[i]);
03626 }
03627 dbl_EGlpNumCopy (work[aindx[i]], acoef[i]);
03628 }
03629 x->nzcnt = 0;
03630 for (i = 0; i < anzcnt; i++)
03631 {
03632 if (--uc_inf[aindx[i]].delay == 0)
03633 {
03634 dbl_ftranu3_process2 (f, aindx[i], x);
03635 }
03636 }
03637 #ifdef dbl_SOLVE_DEBUG
03638 printf ("dbl_ILLfactor_ftran x after u3:");
03639 for (i = 0; i < x->nzcnt; i++)
03640 {
03641 printf (" %.3f*%d", dbl_EGlpNumToLf (x->coef[i]), x->indx[i]);
03642 }
03643 printf ("\n");
03644 fflush (stdout);
03645 #endif
03646 }
03647
03648
03649 void dbl_ILLfactor_ftran (
03650 dbl_factor_work * f,
03651 dbl_svector * a,
03652 dbl_svector * x)
03653 {
03654 int i;
03655 int nzcnt;
03656 int sparse;
03657 int *aindx;
03658 double *acoef;
03659 double *work_coef = f->work_coef;
03660
03661 #ifdef dbl_RECORD
03662 {
03663 fprintf (dbl_fsave, "f %d", a->nzcnt);
03664 for (i = 0; i < a->nzcnt; i++)
03665 {
03666 fprintf (dbl_fsave, " %d %.16e", a->indx[i], dbl_EGlpNumToLf (a->coef[i]));
03667 }
03668 fprintf (dbl_fsave, "\n");
03669 fflush (dbl_fsave);
03670 }
03671 #endif
03672 #ifdef dbl_DEBUG_FACTOR
03673 {
03674 printf ("dbl_ILLfactor_ftran a:");
03675 for (i = 0; i < a->nzcnt; i++)
03676 {
03677 printf (" %d %la", a->indx[i], dbl_EGlpNumToLf (a->coef[i]));
03678 }
03679 printf ("\n");
03680 fflush (stdout);
03681 }
03682 #endif
03683
03684 if (a->nzcnt >= SPARSE_FACTOR * f->dim)
03685 {
03686 nzcnt = a->nzcnt;
03687 aindx = a->indx;
03688 acoef = a->coef;
03689 for (i = 0; i < nzcnt; i++)
03690 {
03691 dbl_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
03692 }
03693 sparse = 0;
03694 }
03695 else
03696 {
03697 sparse = 1;
03698 }
03699
03700 if (sparse)
03701 {
03702 dbl_ILLfactor_ftranl3 (f, a, &f->xtmp);
03703 if (f->xtmp.nzcnt >= SPARSE_FACTOR * f->dim)
03704 {
03705 nzcnt = f->xtmp.nzcnt;
03706 aindx = f->xtmp.indx;
03707 acoef = f->xtmp.coef;
03708
03709 for (i = 0; i < nzcnt; i++)
03710 {
03711 dbl_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
03712 }
03713 sparse = 0;
03714 }
03715 }
03716 else
03717 {
03718 dbl_ILLfactor_ftranl (f, work_coef);
03719 }
03720
03721 if (sparse)
03722 {
03723 dbl_ILLfactor_ftrane2 (f, &f->xtmp);
03724 if (f->xtmp.nzcnt >= SPARSE_FACTOR * f->dim)
03725 {
03726 nzcnt = f->xtmp.nzcnt;
03727 aindx = f->xtmp.indx;
03728 acoef = f->xtmp.coef;
03729
03730 for (i = 0; i < nzcnt; i++)
03731 {
03732 dbl_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
03733 }
03734 sparse = 0;
03735 }
03736 }
03737 else
03738 {
03739 dbl_ILLfactor_ftrane (f, work_coef);
03740 }
03741
03742 if (sparse)
03743 {
03744 dbl_ILLfactor_ftranu3 (f, &f->xtmp, x);
03745 }
03746 else
03747 {
03748 dbl_ILLfactor_ftranu (f, work_coef, x);
03749 }
03750
03751 #ifdef dbl_SORT_RESULTS
03752 dbl_sort_vector (x);
03753 #endif
03754
03755 #ifdef dbl_DEBUG_FACTOR
03756 {
03757 printf ("dbl_ILLfactor_ftran x:");
03758 for (i = 0; i < x->nzcnt; i++)
03759 {
03760 printf (" %d %la", x->indx[i], dbl_EGlpNumToLf (x->coef[i]));
03761 }
03762 printf ("\n");
03763 fflush (stdout);
03764 }
03765 #endif
03766 return;
03767 }
03768
03769
03770 void dbl_ILLfactor_ftran_update (
03771 dbl_factor_work * f,
03772 dbl_svector * a,
03773 dbl_svector * upd,
03774 dbl_svector * x)
03775 {
03776 int i;
03777 int nzcnt;
03778 int dim;
03779 int sparse;
03780 int *aindx;
03781 double *acoef;
03782 double *work_coef = f->work_coef;
03783
03784 #ifdef dbl_RECORD
03785 {
03786 fprintf (dbl_fsave, "F %d", a->nzcnt);
03787 for (i = 0; i < a->nzcnt; i++)
03788 {
03789 fprintf (dbl_fsave, " %d %.16e", a->indx[i], dbl_EGlpNumToLf (a->coef[i]));
03790 }
03791 fprintf (dbl_fsave, "\n");
03792 fflush (dbl_fsave);
03793 }
03794 #endif
03795 #ifdef dbl_DEBUG_FACTOR
03796 {
03797 printf ("dbl_ILLfactor_ftran_update a:");
03798 for (i = 0; i < a->nzcnt; i++)
03799 {
03800 printf (" %d %.3f", a->indx[i], dbl_EGlpNumToLf (a->coef[i]));
03801 }
03802 printf ("\n");
03803 fflush (stdout);
03804 }
03805 #endif
03806
03807 if (a->nzcnt >= SPARSE_FACTOR * f->dim)
03808 {
03809 aindx = a->indx;
03810 acoef = a->coef;
03811 nzcnt = a->nzcnt;
03812
03813 for (i = 0; i < nzcnt; i++)
03814 {
03815 dbl_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
03816 }
03817 sparse = 0;
03818 }
03819 else
03820 {
03821 sparse = 1;
03822 }
03823
03824 if (sparse)
03825 {
03826 dbl_ILLfactor_ftranl3 (f, a, upd);
03827 if (upd->nzcnt >= SPARSE_FACTOR * f->dim)
03828 {
03829 nzcnt = upd->nzcnt;
03830 aindx = upd->indx;
03831 acoef = upd->coef;
03832
03833 for (i = 0; i < nzcnt; i++)
03834 {
03835 dbl_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
03836 }
03837 sparse = 0;
03838 }
03839 }
03840 else
03841 {
03842 dbl_ILLfactor_ftranl (f, work_coef);
03843 }
03844
03845 if (sparse)
03846 {
03847 dbl_ILLfactor_ftrane2 (f, upd);
03848 if (upd->nzcnt >= SPARSE_FACTOR * f->dim)
03849 {
03850 nzcnt = upd->nzcnt;
03851 aindx = upd->indx;
03852 acoef = upd->coef;
03853
03854 for (i = 0; i < nzcnt; i++)
03855 {
03856 dbl_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
03857 }
03858 sparse = 0;
03859 }
03860 }
03861 else
03862 {
03863 dbl_ILLfactor_ftrane (f, work_coef);
03864 nzcnt = 0;
03865 dim = f->dim;
03866 aindx = upd->indx;
03867 acoef = upd->coef;
03868 for (i = 0; i < dim; i++)
03869 {
03870 if (dbl_EGlpNumIsNeqqZero (work_coef[i]))
03871 {
03872 if (dbl_EGlpNumIsNeqZero (work_coef[i], f->szero_tol))
03873
03874 {
03875 aindx[nzcnt] = i;
03876 dbl_EGlpNumCopy (acoef[nzcnt], work_coef[i]);
03877 nzcnt++;
03878 }
03879 }
03880 }
03881 upd->nzcnt = nzcnt;
03882 }
03883
03884 if (sparse)
03885 {
03886 dbl_ILLfactor_ftranu3 (f, upd, x);
03887 }
03888 else
03889 {
03890 dbl_ILLfactor_ftranu (f, work_coef, x);
03891 }
03892
03893 #ifdef dbl_SORT_RESULTS
03894 dbl_sort_vector (upd);
03895 dbl_sort_vector (x);
03896 #endif
03897
03898 #ifdef dbl_DEBUG_FACTOR
03899 {
03900 printf ("dbl_ILLfactor_ftran update x:");
03901 for (i = 0; i < x->nzcnt; i++)
03902 {
03903 printf (" %d %.3f", x->indx[i], dbl_EGlpNumToLf (x->coef[i]));
03904 }
03905 printf ("\n");
03906 fflush (stdout);
03907 }
03908 #endif
03909 }
03910
03911
03912 static void dbl_ILLfactor_btranl2 (
03913 dbl_factor_work * f,
03914 double * x)
03915 {
03916 int *lrindx = f->lrindx;
03917 double *lrcoef = f->lrcoef;
03918 dbl_lr_info *lr_inf = f->lr_inf;
03919 int dim = f->dim;
03920 int nzcnt;
03921 int beg;
03922 int i;
03923 int j;
03924 double v;
03925
03926 dbl_EGlpNumInitVar (v);
03927
03928 for (i = dim - 1; i >= 0; i--)
03929 {
03930 #ifdef dbl_SOLVE_DEBUG
03931 #if (dbl_SOLVE_DEBUG+0 > 1)
03932 printf ("dbl_ILLfactor_btran x before l2 %d:", i);
03933 for (j = 0; j < f->dim; j++)
03934 {
03935 printf (" %.3f", dbl_EGlpNumToLf (x[j]));
03936 }
03937 printf ("\n");
03938 fflush (stdout);
03939 #endif
03940 #endif
03941 dbl_EGlpNumCopy (v, x[lr_inf[i].r]);
03942 if (dbl_EGlpNumIsNeqqZero (v))
03943 {
03944 nzcnt = lr_inf[i].nzcnt;
03945 beg = lr_inf[i].rbeg;
03946 for (j = 0; j < nzcnt; j++)
03947 {
03948 dbl_EGlpNumSubInnProdTo (x[lrindx[beg + j]], v, lrcoef[beg + j]);
03949 }
03950 }
03951 }
03952 #ifdef dbl_SOLVE_DEBUG
03953 #if (dbl_SOLVE_DEBUG+0 <= 1)
03954 printf ("dbl_ILLfactor_btran x after l2:");
03955 for (j = 0; j < f->dim; j++)
03956 {
03957 printf (" %.3f", dbl_EGlpNumToLf (x[j]));
03958 }
03959 printf ("\n");
03960 fflush (stdout);
03961 #endif
03962 #endif
03963 dbl_EGlpNumClearVar (v);
03964 }
03965
03966 #if 0
03967 static void btranl3_delay (
03968 dbl_factor_work * f,
03969 int r)
03970 {
03971 dbl_lr_info *lr_inf = f->lr_inf;
03972 int nzcnt;
03973 int *indx;
03974 int i;
03975
03976 r = lr_inf[r].rrank;
03977 nzcnt = lr_inf[r].nzcnt;
03978 indx = f->lrindx + lr_inf[r].rbeg;
03979 for (i = 0; i < nzcnt; i++)
03980 {
03981 r = indx[i];
03982 if (lr_inf[r].delay++ == 0)
03983 {
03984 btranl3_delay (f, r);
03985 }
03986 }
03987 }
03988 #endif
03989
03990 static void dbl_btranl3_delay2 (
03991 dbl_factor_work * f,
03992 int r)
03993 {
03994 dbl_lr_info *lr_inf = f->lr_inf;
03995 int nzcnt;
03996 int *indx;
03997 int i;
03998 int last;
03999
04000 do
04001 {
04002 r = lr_inf[r].rrank;
04003 nzcnt = lr_inf[r].nzcnt;
04004 indx = f->lrindx + lr_inf[r].rbeg;
04005 last = -1;
04006 for (i = 0; i < nzcnt; i++)
04007 {
04008 r = indx[i];
04009 if (lr_inf[r].delay++ == 0)
04010 {
04011 if (last >= 0)
04012 {
04013 dbl_btranl3_delay2 (f, last);
04014 }
04015 last = r;
04016 }
04017 }
04018 r = last;
04019 } while (r >= 0);
04020 }
04021
04022 #if 0
04023 static void btranl3_process (
04024 dbl_factor_work * f,
04025 int r,
04026 dbl_svector * x)
04027 {
04028 dbl_lr_info *lr_inf = f->lr_inf;
04029 double *work = f->work_coef;
04030 int nzcnt;
04031 int *indx;
04032 double *coef;
04033 int i;
04034 double v;
04035
04036 dbl_EGlpNumInitVar (v);
04037
04038 dbl_EGlpNumCopy (v, work[r]);
04039 dbl_EGlpNumZero (work[r]);
04040 if (dbl_EGlpNumIsNeqZero (v, f->szero_tol))
04041
04042 {
04043 x->indx[x->nzcnt] = r;
04044 dbl_EGlpNumCopy (x->coef[x->nzcnt], v);
04045 x->nzcnt++;
04046 }
04047 r = lr_inf[r].rrank;
04048 nzcnt = lr_inf[r].nzcnt;
04049 indx = f->lrindx + lr_inf[r].rbeg;
04050 coef = f->lrcoef + lr_inf[r].rbeg;
04051 for (i = 0; i < nzcnt; i++)
04052 {
04053 r = indx[i];
04054 dbl_EGlpNumSubInnProdTo (work[r], v, coef[i]);
04055 if (--lr_inf[r].delay == 0)
04056 {
04057 btranl3_process (f, r, x);
04058 }
04059 }
04060 dbl_EGlpNumClearVar (v);
04061 }
04062 #endif
04063
04064 static void dbl_btranl3_process2 (
04065 dbl_factor_work * f,
04066 int r,
04067 dbl_svector * x)
04068 {
04069 dbl_lr_info *lr_inf = f->lr_inf;
04070 double *work = f->work_coef;
04071 int nzcnt;
04072 int *indx;
04073 double *coef;
04074 int i;
04075 int last;
04076 double v;
04077
04078 dbl_EGlpNumInitVar (v);
04079
04080 do
04081 {
04082 dbl_EGlpNumCopy (v, work[r]);
04083 dbl_EGlpNumZero (work[r]);
04084 if (dbl_EGlpNumIsNeqZero (v, f->szero_tol))
04085
04086 {
04087 x->indx[x->nzcnt] = r;
04088 dbl_EGlpNumCopy (x->coef[x->nzcnt], v);
04089 x->nzcnt++;
04090 }
04091 r = lr_inf[r].rrank;
04092 nzcnt = lr_inf[r].nzcnt;
04093 indx = f->lrindx + lr_inf[r].rbeg;
04094 coef = f->lrcoef + lr_inf[r].rbeg;
04095 last = -1;
04096 for (i = 0; i < nzcnt; i++)
04097 {
04098 r = indx[i];
04099 dbl_EGlpNumSubInnProdTo (work[r], v, coef[i]);
04100 if (--lr_inf[r].delay == 0)
04101 {
04102 if (last >= 0)
04103 {
04104 dbl_btranl3_process2 (f, last, x);
04105 }
04106 last = r;
04107 }
04108 }
04109 r = last;
04110 } while (r >= 0);
04111 dbl_EGlpNumClearVar (v);
04112 }
04113
04114 static void dbl_ILLfactor_btranl3 (
04115 dbl_factor_work * f,
04116 dbl_svector * a,
04117 dbl_svector * x)
04118 {
04119 double *work = f->work_coef;
04120 int anzcnt = a->nzcnt;
04121 int *aindx = a->indx;
04122 double *acoef = a->coef;
04123 dbl_lr_info *lr_inf = f->lr_inf;
04124 int i;
04125
04126 for (i = 0; i < anzcnt; i++)
04127 {
04128 if (lr_inf[aindx[i]].delay++ == 0)
04129 {
04130 dbl_btranl3_delay2 (f, aindx[i]);
04131 }
04132 dbl_EGlpNumCopy (work[aindx[i]], acoef[i]);
04133 }
04134 x->nzcnt = 0;
04135 for (i = 0; i < anzcnt; i++)
04136 {
04137 if (--lr_inf[aindx[i]].delay == 0)
04138 {
04139 dbl_btranl3_process2 (f, aindx[i], x);
04140 }
04141 }
04142 #ifdef dbl_SOLVE_DEBUG
04143 printf ("dbl_ILLfactor_btran x after l3:");
04144 for (i = 0; i < x->nzcnt; i++)
04145 {
04146 printf (" %.3f*%d", dbl_EGlpNumToLf (x->coef[i]), x->indx[i]);
04147 }
04148 printf ("\n");
04149 fflush (stdout);
04150 #endif
04151 }
04152
04153 static void dbl_ILLfactor_btrane (
04154 dbl_factor_work * f,
04155 double * x)
04156 {
04157 int *erindx = f->erindx;
04158 double *ercoef = f->ercoef;
04159 dbl_er_info *er_inf = f->er_inf;
04160 int etacnt = f->etacnt;
04161 int beg;
04162 int nzcnt;
04163 int i;
04164 int j;
04165 double v;
04166
04167 dbl_EGlpNumInitVar (v);
04168
04169 for (i = etacnt - 1; i >= 0; i--)
04170 {
04171 #ifdef dbl_SOLVE_DEBUG
04172 #if (dbl_SOLVE_DEBUG+0 > 1)
04173 printf ("dbl_ILLfactor_btran x before eta %d:", i);
04174 for (j = 0; j < f->dim; j++)
04175 {
04176 printf (" %.3f", dbl_EGlpNumToLf (x[j]));
04177 }
04178 printf ("\n");
04179 fflush (stdout);
04180 #endif
04181 #endif
04182 dbl_EGlpNumCopy (v, x[er_inf[i].r]);
04183 if (dbl_EGlpNumIsNeqqZero (v))
04184 {
04185 nzcnt = er_inf[i].nzcnt;
04186 beg = er_inf[i].rbeg;
04187 for (j = 0; j < nzcnt; j++)
04188 {
04189 dbl_EGlpNumSubInnProdTo (x[erindx[beg + j]], v, ercoef[beg + j]);
04190 }
04191 }
04192 }
04193 #ifdef dbl_SOLVE_DEBUG
04194 #if (dbl_SOLVE_DEBUG+0 <= 1)
04195 printf ("dbl_ILLfactor_btran x after eta:");
04196 for (j = 0; j < f->dim; j++)
04197 {
04198 printf (" %.3f", dbl_EGlpNumToLf (x[j]));
04199 }
04200 printf ("\n");
04201 fflush (stdout);
04202 #endif
04203 #endif
04204 dbl_EGlpNumClearVar (v);
04205 }
04206
04207 static void dbl_ILLfactor_btrane2 (
04208 dbl_factor_work * f,
04209 dbl_svector * x)
04210 {
04211 int *erindx = f->erindx;
04212 double *ercoef = f->ercoef;
04213 dbl_er_info *er_inf = f->er_inf;
04214 int etacnt = f->etacnt;
04215 int beg;
04216 int nzcnt;
04217 int xnzcnt = x->nzcnt;
04218 int *xindx = x->indx;
04219 double *xcoef = x->coef;
04220 double *work_coef = f->work_coef;
04221 int *work_indx = f->work_indx;
04222 int i;
04223 int j;
04224 double v;
04225
04226 dbl_EGlpNumInitVar (v);
04227
04228 for (i = 0; i < xnzcnt; i++)
04229 {
04230 dbl_EGlpNumCopy (work_coef[xindx[i]], xcoef[i]);
04231 work_indx[xindx[i]] = i + 1;
04232 }
04233 for (i = etacnt - 1; i >= 0; i--)
04234 {
04235 #ifdef dbl_SOLVE_DEBUG
04236 #if (dbl_SOLVE_DEBUG+0 > 1)
04237 printf ("dbl_ILLfactor_btran x before eta2 %d:", i);
04238 for (j = 0; j < xnzcnt; j++)
04239 {
04240 printf (" %.3f*%d", dbl_EGlpNumToLf (work_coef[xindx[j]]), xindx[j]);
04241 }
04242 printf ("\n");
04243 fflush (stdout);
04244 #endif
04245 #endif
04246 dbl_EGlpNumCopy (v, work_coef[er_inf[i].r]);
04247 if (dbl_EGlpNumIsNeqqZero (v))
04248 {
04249 nzcnt = er_inf[i].nzcnt;
04250 beg = er_inf[i].rbeg;
04251 for (j = 0; j < nzcnt; j++)
04252 {
04253 if (work_indx[erindx[beg + j]] == 0)
04254 {
04255 work_indx[erindx[beg + j]] = xnzcnt;
04256 xindx[xnzcnt++] = erindx[beg + j];
04257 }
04258 dbl_EGlpNumSubInnProdTo (work_coef[erindx[beg + j]], v, ercoef[beg + j]);
04259 }
04260 }
04261 }
04262
04263 j = 0;
04264 while (j < xnzcnt)
04265 {
04266 dbl_EGlpNumCopy (xcoef[j], work_coef[xindx[j]]);
04267 dbl_EGlpNumZero (work_coef[xindx[j]]);
04268 work_indx[xindx[j]] = 0;
04269 if (!dbl_EGlpNumIsNeqqZero (xcoef[j]))
04270 {
04271 --xnzcnt;
04272 xindx[j] = xindx[xnzcnt];
04273 }
04274 else
04275 {
04276 j++;
04277 }
04278 }
04279 x->nzcnt = xnzcnt;
04280
04281 #ifdef dbl_SOLVE_DEBUG
04282 #if (dbl_SOLVE_DEBUG+0 <= 1)
04283 printf ("dbl_ILLfactor_btran x after eta2:");
04284 for (j = 0; j < xnzcnt; j++)
04285 {
04286 printf (" %.3f*%d", dbl_EGlpNumToLf (xcoef[j]), xindx[j]);
04287 }
04288 printf ("\n");
04289 fflush (stdout);
04290 #endif
04291 #endif
04292 dbl_EGlpNumClearVar (v);
04293 }
04294
04295 static void dbl_ILLfactor_btranu (
04296 dbl_factor_work * f,
04297 double * a,
04298 dbl_svector * x)
04299 {
04300 int *urindx = f->urindx;
04301 double *urcoef = f->urcoef;
04302 dbl_ur_info *ur_inf = f->ur_inf;
04303 int *rperm = f->rperm;
04304 int *cperm = f->cperm;
04305 int dim = f->dim;
04306 int xnzcnt = 0;
04307 int *xindx = x->indx;
04308 double *xcoef = x->coef;
04309 int nzcnt;
04310 int beg;
04311 int i;
04312 int j;
04313 double v;
04314
04315 dbl_EGlpNumInitVar (v);
04316
04317 for (i = 0; i < dim; i++)
04318 {
04319 dbl_EGlpNumCopy (v, a[cperm[i]]);
04320 if (dbl_EGlpNumIsNeqqZero (v))
04321 {
04322 j = rperm[i];
04323 beg = ur_inf[j].rbeg;
04324 dbl_EGlpNumDivTo (v, urcoef[beg]);
04325 if (dbl_EGlpNumIsNeqZero (v, f->szero_tol))
04326
04327 {
04328 xindx[xnzcnt] = j;
04329 dbl_EGlpNumCopy (xcoef[xnzcnt], v);
04330 xnzcnt++;
04331 }
04332 nzcnt = ur_inf[j].nzcnt;
04333 for (j = 1; j < nzcnt; j++)
04334 {
04335 dbl_EGlpNumSubInnProdTo (a[urindx[beg + j]], v, urcoef[beg + j]);
04336 }
04337 dbl_EGlpNumZero (a[cperm[i]]);
04338 }
04339 }
04340 x->nzcnt = xnzcnt;
04341 #ifdef dbl_SOLVE_DEBUG
04342 printf ("dbl_ILLfactor_btran x after u:");
04343 for (i = 0; i < x->nzcnt; i++)
04344 {
04345 printf (" %.3f*%d", dbl_EGlpNumToLf (x->coef[i]), x->indx[i]);
04346 }
04347 printf ("\n");
04348 fflush (stdout);
04349 #endif
04350 dbl_EGlpNumClearVar (v);
04351 }
04352
04353
04354 #if 0
04355 static void btranu3_delay (
04356 dbl_factor_work * f,
04357 int r)
04358 {
04359 dbl_ur_info *ur_inf = f->ur_inf;
04360 int nzcnt;
04361 int *indx;
04362 int i;
04363
04364 r = f->rperm[f->crank[r]];
04365 nzcnt = ur_inf[r].nzcnt;
04366 indx = f->urindx + ur_inf[r].rbeg;
04367 for (i = 1; i < nzcnt; i++)
04368 {
04369 r = indx[i];
04370 if (ur_inf[r].delay++ == 0)
04371 {
04372 btranu3_delay (f, r);
04373 }
04374 }
04375 }
04376 #endif
04377
04378 static void dbl_btranu3_delay2 (
04379 dbl_factor_work * f,
04380 int r)
04381 {
04382 dbl_ur_info *ur_inf = f->ur_inf;
04383 int nzcnt;
04384 int *indx;
04385 int i;
04386 int last;
04387
04388 do
04389 {
04390 r = f->rperm[f->crank[r]];
04391 nzcnt = ur_inf[r].nzcnt;
04392 indx = f->urindx + ur_inf[r].rbeg;
04393 last = -1;
04394 for (i = 1; i < nzcnt; i++)
04395 {
04396 r = indx[i];
04397 if (ur_inf[r].delay++ == 0)
04398 {
04399 if (last >= 0)
04400 {
04401 dbl_btranu3_delay2 (f, last);
04402 }
04403 last = r;
04404 }
04405 }
04406 r = last;
04407 } while (r >= 0);
04408 }
04409
04410 #if 0
04411 static void btranu3_process (
04412 dbl_factor_work * f,
04413 int r,
04414 dbl_svector * x)
04415 {
04416 dbl_ur_info *ur_inf = f->ur_inf;
04417 double *work = f->work_coef;
04418 int nzcnt;
04419 int *indx;
04420 double *coef;
04421 int i;
04422 double v;
04423
04424 dbl_EGlpNumInitVar (v);
04425
04426 dbl_EGlpNumCopy (v, work[r]);
04427 dbl_EGlpNumZero (work[r]);
04428 r = f->rperm[f->crank[r]];
04429 nzcnt = ur_inf[r].nzcnt;
04430 indx = f->urindx + ur_inf[r].rbeg;
04431 coef = f->urcoef + ur_inf[r].rbeg;
04432 dbl_EGlpNumDivTo (v, coef[0]);
04433 if (dbl_EGlpNumIsNeqqZero (v))
04434 {
04435 x->indx[x->nzcnt] = r;
04436 dbl_EGlpNumCopy (x->coef[x->nzcnt], v);
04437 x->nzcnt++;
04438 }
04439 for (i = 1; i < nzcnt; i++)
04440 {
04441 r = indx[i];
04442 dbl_EGlpNumSubInnProdTo (work[r], v, coef[i]);
04443 if (--ur_inf[r].delay == 0)
04444 {
04445 btranu3_process (f, r, x);
04446 }
04447 }
04448 dbl_EGlpNumClearVar (v);
04449 }
04450 #endif
04451
04452 static void dbl_btranu3_process2 (
04453 dbl_factor_work * f,
04454 int r,
04455 dbl_svector * x)
04456 {
04457 dbl_ur_info *ur_inf = f->ur_inf;
04458 double *work = f->work_coef;
04459 int nzcnt;
04460 int *indx;
04461 double *coef;
04462 int i;
04463 int last;
04464 double v;
04465
04466 dbl_EGlpNumInitVar (v);
04467
04468 do
04469 {
04470 dbl_EGlpNumCopy (v, work[r]);
04471 dbl_EGlpNumZero (work[r]);
04472 r = f->rperm[f->crank[r]];
04473 nzcnt = ur_inf[r].nzcnt;
04474 indx = f->urindx + ur_inf[r].rbeg;
04475 coef = f->urcoef + ur_inf[r].rbeg;
04476 dbl_EGlpNumDivTo (v, coef[0]);
04477 if (dbl_EGlpNumIsNeqqZero (v))
04478 {
04479 x->indx[x->nzcnt] = r;
04480 dbl_EGlpNumCopy (x->coef[x->nzcnt], v);
04481 x->nzcnt++;
04482 }
04483 last = -1;
04484 for (i = 1; i < nzcnt; i++)
04485 {
04486 r = indx[i];
04487 dbl_EGlpNumSubInnProdTo (work[r], v, coef[i]);
04488 if (--ur_inf[r].delay == 0)
04489 {
04490 if (last >= 0)
04491 {
04492 dbl_btranu3_process2 (f, last, x);
04493 }
04494 last = r;
04495 }
04496 }
04497 r = last;
04498 } while (r >= 0);
04499 dbl_EGlpNumClearVar (v);
04500 }
04501
04502 static void dbl_ILLfactor_btranu3 (
04503 dbl_factor_work * f,
04504 dbl_svector * a,
04505 dbl_svector * x)
04506 {
04507 double *work = f->work_coef;
04508 int anzcnt = a->nzcnt;
04509 int *aindx = a->indx;
04510 double *acoef = a->coef;
04511 dbl_ur_info *ur_inf = f->ur_inf;
04512 int i;
04513
04514 for (i = 0; i < anzcnt; i++)
04515 {
04516 if (ur_inf[aindx[i]].delay++ == 0)
04517 {
04518 dbl_btranu3_delay2 (f, aindx[i]);
04519 }
04520 dbl_EGlpNumCopy (work[aindx[i]], acoef[i]);
04521 }
04522 x->nzcnt = 0;
04523 for (i = 0; i < anzcnt; i++)
04524 {
04525 if (--ur_inf[aindx[i]].delay == 0)
04526 {
04527 dbl_btranu3_process2 (f, aindx[i], x);
04528 }
04529 }
04530 #ifdef dbl_SOLVE_DEBUG
04531 printf ("dbl_ILLfactor_btran x after u3:");
04532 for (i = 0; i < x->nzcnt; i++)
04533 {
04534 printf (" %.3f*%d", dbl_EGlpNumToLf (x->coef[i]), x->indx[i]);
04535 }
04536 printf ("\n");
04537 fflush (stdout);
04538 #endif
04539 }
04540
04541
04542 void dbl_ILLfactor_btran (
04543 dbl_factor_work * f,
04544 dbl_svector * a,
04545 dbl_svector * x)
04546 {
04547 int i;
04548 int nzcnt;
04549 int sparse;
04550 int *aindx = a->indx;
04551 double *acoef = a->coef;
04552 double *work_coef = f->work_coef;
04553 int dim = f->dim;
04554
04555 #ifdef dbl_RECORD
04556 {
04557 fprintf (dbl_fsave, "b %d", a->nzcnt);
04558 for (i = 0; i < a->nzcnt; i++)
04559 {
04560 fprintf (dbl_fsave, " %d %.16e", a->indx[i], dbl_EGlpNumToLf (a->coef[i]));
04561 }
04562 fprintf (dbl_fsave, "\n");
04563 fflush (dbl_fsave);
04564 }
04565 #endif
04566 #ifdef dbl_DEBUG_FACTOR
04567 {
04568 printf ("dbl_ILLfactor_btran a:");
04569 for (i = 0; i < a->nzcnt; i++)
04570 {
04571 printf (" %d %.3f", a->indx[i], dbl_EGlpNumToLf (a->coef[i]));
04572 }
04573 printf ("\n");
04574 fflush (stdout);
04575 }
04576 #endif
04577
04578 if (a->nzcnt >= SPARSE_FACTOR * f->dim)
04579 {
04580 aindx = a->indx;
04581 acoef = a->coef;
04582 work_coef = f->work_coef;
04583 nzcnt = a->nzcnt;
04584 for (i = 0; i < nzcnt; i++)
04585 {
04586 dbl_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
04587 }
04588 sparse = 0;
04589 }
04590 else
04591 {
04592 sparse = 1;
04593 }
04594
04595 if (sparse)
04596 {
04597 dbl_ILLfactor_btranu3 (f, a, &f->xtmp);
04598 }
04599 else
04600 {
04601 dbl_ILLfactor_btranu (f, work_coef, &f->xtmp);
04602 }
04603
04604 if (f->xtmp.nzcnt >= SPARSE_FACTOR * f->dim)
04605 {
04606 aindx = f->xtmp.indx;
04607 acoef = f->xtmp.coef;
04608 work_coef = f->work_coef;
04609 nzcnt = f->xtmp.nzcnt;
04610 for (i = 0; i < nzcnt; i++)
04611 {
04612 dbl_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
04613 }
04614 sparse = 0;
04615 }
04616 else
04617 {
04618 sparse = 1;
04619 }
04620
04621 if (sparse)
04622 {
04623 dbl_ILLfactor_btrane2 (f, &f->xtmp);
04624 if (f->xtmp.nzcnt >= SPARSE_FACTOR * f->dim)
04625 {
04626 aindx = f->xtmp.indx;
04627 acoef = f->xtmp.coef;
04628 work_coef = f->work_coef;
04629 nzcnt = f->xtmp.nzcnt;
04630 for (i = 0; i < nzcnt; i++)
04631 {
04632 dbl_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
04633 }
04634 sparse = 0;
04635 }
04636 }
04637 else
04638 {
04639 dbl_ILLfactor_btrane (f, work_coef);
04640 }
04641
04642 if (sparse)
04643 {
04644 dbl_ILLfactor_btranl3 (f, &f->xtmp, x);
04645 }
04646 else
04647 {
04648 dbl_ILLfactor_btranl2 (f, work_coef);
04649 dim = f->dim;
04650 nzcnt = 0;
04651 aindx = x->indx;
04652 acoef = x->coef;
04653 for (i = 0; i < dim; i++)
04654 {
04655 if (dbl_EGlpNumIsNeqqZero (work_coef[i]))
04656 {
04657 if (dbl_EGlpNumIsNeqZero (work_coef[i], f->szero_tol))
04658
04659 {
04660 aindx[nzcnt] = i;
04661 dbl_EGlpNumCopy (acoef[nzcnt], work_coef[i]);
04662 nzcnt++;
04663 }
04664 dbl_EGlpNumZero (work_coef[i]);
04665 }
04666 }
04667 x->nzcnt = nzcnt;
04668 }
04669
04670 #ifdef dbl_SORT_RESULTS
04671 dbl_sort_vector (x);
04672 #endif
04673
04674 #ifdef dbl_DEBUG_FACTOR
04675 {
04676 printf ("dbl_ILLfactor_btran x:");
04677 for (i = 0; i < x->nzcnt; i++)
04678 {
04679 printf (" %d %.3f", x->indx[i], dbl_EGlpNumToLf (x->coef[i]));
04680 }
04681 printf ("\n");
04682 fflush (stdout);
04683 }
04684 #endif
04685 return;
04686 }
04687
04688 static int dbl_expand_col (
04689 dbl_factor_work * f,
04690 int col)
04691 {
04692 dbl_uc_info *uc_inf = f->uc_inf + col;
04693 int uc_freebeg = f->uc_freebeg;
04694 int nzcnt = uc_inf->nzcnt;
04695 int cbeg;
04696 double *uccoef;
04697 int *ucindx;
04698 int *ucrind;
04699 int i;
04700 int rval = 0;
04701
04702 if (uc_freebeg + nzcnt + 1 >= f->uc_space)
04703 {
04704 rval = dbl_make_uc_space (f, nzcnt + 1);
04705 CHECKRVALG (rval, CLEANUP);
04706 uc_freebeg = f->uc_freebeg;
04707 }
04708 cbeg = uc_inf->cbeg;
04709 uccoef = f->uccoef;
04710 ucindx = f->ucindx;
04711 ucrind = f->ucrind;
04712
04713 for (i = 0; i < nzcnt; i++)
04714 {
04715 dbl_EGlpNumCopy (uccoef[uc_freebeg + i], uccoef[cbeg + i]);
04716 ucindx[uc_freebeg + i] = ucindx[cbeg + i];
04717 ucrind[uc_freebeg + i] = ucrind[cbeg + i];
04718 ucindx[cbeg + i] = -1;
04719 }
04720
04721 uc_inf->cbeg = uc_freebeg;
04722 f->uc_freebeg = uc_freebeg + nzcnt;
04723 CLEANUP:
04724 EG_RETURN (rval);
04725 }
04726
04727 static int dbl_expand_row (
04728 dbl_factor_work * f,
04729 int row)
04730 {
04731 dbl_ur_info *ur_inf = f->ur_inf + row;
04732 int ur_freebeg = f->ur_freebeg;
04733 int nzcnt = ur_inf->nzcnt;
04734 int rbeg;
04735 double *urcoef;
04736 int *urindx;
04737 int *urcind;
04738 int i;
04739 int rval = 0;
04740
04741 if (ur_freebeg + nzcnt + 1 >= f->ur_space)
04742 {
04743 rval = dbl_make_ur_space (f, nzcnt + 1);
04744 CHECKRVALG (rval, CLEANUP);
04745 ur_freebeg = f->ur_freebeg;
04746 }
04747 rbeg = ur_inf->rbeg;
04748 urcoef = f->urcoef;
04749 urindx = f->urindx;
04750 urcind = f->urcind;
04751
04752 for (i = 0; i < nzcnt; i++)
04753 {
04754 dbl_EGlpNumCopy (urcoef[ur_freebeg + i], urcoef[rbeg + i]);
04755 urindx[ur_freebeg + i] = urindx[rbeg + i];
04756 urcind[ur_freebeg + i] = urcind[rbeg + i];
04757 urindx[rbeg + i] = -1;
04758 }
04759
04760 ur_inf->rbeg = ur_freebeg;
04761 f->ur_freebeg = ur_freebeg + nzcnt;
04762 CLEANUP:
04763 EG_RETURN (rval);
04764 }
04765
04766 static int dbl_add_nonzero (
04767 dbl_factor_work * f,
04768 int row,
04769 int col,
04770 double val)
04771 {
04772 dbl_ur_info *ur_inf = f->ur_inf + row;
04773 dbl_uc_info *uc_inf = f->uc_inf + col;
04774 int cnzcnt = uc_inf->nzcnt;
04775 int rnzcnt = ur_inf->nzcnt;
04776 int cloc = uc_inf->cbeg + cnzcnt;
04777 int rloc = ur_inf->rbeg + rnzcnt;
04778 int rval = 0;
04779
04780 if (f->ucindx[cloc] != -1)
04781 {
04782 rval = dbl_expand_col (f, col);
04783 CHECKRVALG (rval, CLEANUP);
04784 cloc = uc_inf->cbeg + cnzcnt;
04785 }
04786 TESTG ((rval = (rloc < 0 || rloc > f->ur_space)), CLEANUP,
04787 "rloc %d outside boundaries [0:%d]", rloc, f->ur_space);
04788 if (f->urindx[rloc] != -1)
04789 {
04790 rval = dbl_expand_row (f, row);
04791 CHECKRVALG (rval, CLEANUP);
04792 rloc = ur_inf->rbeg + rnzcnt;
04793 }
04794 f->ucindx[cloc] = row;
04795 dbl_EGlpNumCopy (f->uccoef[cloc], val);
04796 f->ucrind[cloc] = rnzcnt;
04797 f->urindx[rloc] = col;
04798 dbl_EGlpNumCopy (f->urcoef[rloc], val);
04799 f->urcind[rloc] = cnzcnt;
04800
04801 if (cloc == f->uc_freebeg)
04802 f->uc_freebeg++;
04803 if (rloc == f->ur_freebeg)
04804 f->ur_freebeg++;
04805
04806 uc_inf->nzcnt = cnzcnt + 1;
04807 ur_inf->nzcnt = rnzcnt + 1;
04808 CLEANUP:
04809 EG_RETURN (rval);
04810 }
04811
04812 static int dbl_delete_nonzero_row (
04813 dbl_factor_work * f,
04814 int row,
04815 int ind)
04816 {
04817 dbl_ur_info *ur_inf = f->ur_inf;
04818 double *urcoef = f->urcoef;
04819 int *urindx = f->urindx;
04820 int *urcind = f->urcind;
04821 int *ucrind = f->ucrind;
04822 int rbeg = ur_inf[row].rbeg;
04823 int nzcnt = ur_inf[row].nzcnt - 1;
04824 int cbeg, rval = 0;
04825 #ifdef dbl_DEBUG_FACTOR
04826 TESTG((rval=(nzcnt<0)),CLEANUP,"Deleting empty row %d ind %d!",row, ind);
04827 #endif
04828
04829 if (ind != nzcnt)
04830 {
04831 dbl_EGlpNumCopy (urcoef[rbeg + ind], urcoef[rbeg + nzcnt]);
04832 urindx[rbeg + ind] = urindx[rbeg + nzcnt];
04833 urcind[rbeg + ind] = urcind[rbeg + nzcnt];
04834 cbeg = f->uc_inf[urindx[rbeg + nzcnt]].cbeg;
04835 ucrind[cbeg + urcind[rbeg + nzcnt]] = ind;
04836 urindx[rbeg + nzcnt] = -1;
04837 }
04838 ur_inf[row].nzcnt = nzcnt;
04839 #ifdef dbl_DEBUG_FACTOR
04840 CLEANUP:
04841 #endif
04842 return rval;
04843 }
04844
04845 static void dbl_delete_nonzero_col (
04846 dbl_factor_work * f,
04847 int col,
04848 int ind)
04849 {
04850 dbl_uc_info *uc_inf = f->uc_inf;
04851 double *uccoef = f->uccoef;
04852 int *ucindx = f->ucindx;
04853 int *ucrind = f->ucrind;
04854 int *urcind = f->urcind;
04855 int cbeg = uc_inf[col].cbeg;
04856 int nzcnt = uc_inf[col].nzcnt - 1;
04857 int rbeg;
04858
04859 if (ind != nzcnt)
04860 {
04861 dbl_EGlpNumCopy (uccoef[cbeg + ind], uccoef[cbeg + nzcnt]);
04862 ucindx[cbeg + ind] = ucindx[cbeg + nzcnt];
04863 ucrind[cbeg + ind] = ucrind[cbeg + nzcnt];
04864 rbeg = f->ur_inf[ucindx[cbeg + nzcnt]].rbeg;
04865 urcind[rbeg + ucrind[cbeg + nzcnt]] = ind;
04866 ucindx[cbeg + nzcnt] = -1;
04867 }
04868 uc_inf[col].nzcnt = nzcnt;
04869 }
04870
04871 static int dbl_delete_column (
04872 dbl_factor_work * f,
04873 int col)
04874 {
04875 dbl_uc_info *uc_inf = f->uc_inf;
04876 int beg = uc_inf[col].cbeg;
04877 int nzcnt = uc_inf[col].nzcnt;
04878 int *ucindx = f->ucindx + beg;
04879 int *ucrind = f->ucrind + beg;
04880 int i, rval = 0;
04881 #ifdef dbl_DEBUG_FACTOR
04882 rval = dbl_check_matrix(f);
04883 TESTG(rval,CLEANUP,"Corrupted Matrix");
04884 #endif
04885
04886 for (i = 0; i < nzcnt; i++)
04887 {
04888 rval = dbl_delete_nonzero_row (f, ucindx[i], ucrind[i]);
04889 CHECKRVALG(rval,CLEANUP);
04890 ucindx[i] = -1;
04891 }
04892 uc_inf[col].nzcnt = 0;
04893
04894 #ifdef dbl_TRACK_FACTOR
04895 f->nzcnt_cur -= nzcnt;
04896 #endif
04897
04898 #ifdef dbl_DEBUG_FACTOR
04899 rval = dbl_check_matrix(f);
04900 TESTG(rval,CLEANUP,"Corrupted Matrix");
04901 #endif
04902 CLEANUP:
04903 EG_RETURN(rval);
04904 }
04905
04906 static int dbl_delete_row (
04907 dbl_factor_work * f,
04908 int row,
04909 dbl_svector * x)
04910 {
04911 dbl_ur_info *ur_inf = f->ur_inf;
04912 int beg = ur_inf[row].rbeg;
04913 int nzcnt = ur_inf[row].nzcnt;
04914 int *urindx = f->urindx + beg;
04915 double *urcoef = f->urcoef + beg;
04916 int *urcind = f->urcind + beg;
04917 int i,rval=0;
04918
04919 #ifdef dbl_DEBUG_FACTOR
04920 rval = dbl_check_matrix(f);
04921 TESTG(rval,CLEANUP,"Corrupted Matrix");
04922 #endif
04923
04924 for (i = 0; i < nzcnt; i++)
04925 {
04926 x->indx[i] = urindx[i];
04927 dbl_EGlpNumCopy (x->coef[i], urcoef[i]);
04928 dbl_delete_nonzero_col (f, urindx[i], urcind[i]);
04929 urindx[i] = -1;
04930 }
04931 x->nzcnt = nzcnt;
04932 ur_inf[row].nzcnt = 0;
04933
04934 #ifdef dbl_TRACK_FACTOR
04935 f->nzcnt_cur -= nzcnt;
04936 #endif
04937
04938 #ifdef dbl_DEBUG_FACTOR
04939 rval = dbl_check_matrix(f);
04940 TESTG(rval,CLEANUP,"Corrupted Matrix");
04941 CLEANUP:
04942 #endif
04943 return rval;
04944 }
04945
04946 static int dbl_create_column (
04947 dbl_factor_work * f,
04948 dbl_svector * a,
04949 int col,
04950 int *p_last_rank)
04951 {
04952 int *rrank = f->rrank;
04953 int nzcnt = a->nzcnt;
04954 int *aindx = a->indx;
04955 double *acoef = a->coef;
04956 int i;
04957 int j;
04958 int rval = 0;
04959 int last_rank = -1;
04960
04961 #ifdef dbl_TRACK_FACTOR
04962 double max;
04963
04964 dbl_EGlpNumInitVar (max);
04965 dbl_EGlpNumCopy (max, f->maxelem_cur);
04966 #endif
04967
04968 last_rank = 0;
04969
04970 for (i = 0; i < nzcnt; i++)
04971 {
04972 rval = dbl_add_nonzero (f, aindx[i], col, acoef[i]);
04973 CHECKRVALG (rval, CLEANUP);
04974 #ifdef dbl_TRACK_FACTOR
04975 dbl_EGlpNumSetToMaxAbs (max, acoef[i]);
04976 #endif
04977 j = rrank[aindx[i]];
04978 if (j > last_rank)
04979 last_rank = j;
04980 }
04981 *p_last_rank = last_rank;
04982
04983 #ifdef dbl_TRACK_FACTOR
04984 f->nzcnt_cur += nzcnt;
04985 dbl_EGlpNumCopy (f->maxelem_cur, max);
04986 dbl_EGlpNumClearVar (max);
04987 #endif
04988
04989 #ifdef dbl_DEBUG_FACTOR
04990 rval = dbl_check_matrix(f);
04991 TESTG(rval,CLEANUP,"Corrupted Matrix");
04992 #endif
04993
04994 CLEANUP:
04995 EG_RETURN (rval);
04996 }
04997
04998 #ifdef dbl_UPDATE_STUDY
04999 static int dbl_column_rank (
05000 dbl_factor_work * f,
05001 int col)
05002 {
05003 int *cperm = f->cperm;
05004 int dim = f->dim;
05005 int i;
05006
05007 for (i = 0; i < dim; i++)
05008 {
05009 if (cperm[i] == col)
05010 {
05011 return i;
05012 }
05013 }
05014 return 0;
05015 }
05016 #endif
05017
05018 static void dbl_shift_permutations (
05019 dbl_factor_work * f,
05020 int rank_p,
05021 int rank_r)
05022 {
05023 int *cperm = f->cperm;
05024 int *crank = f->crank;
05025 int *rperm = f->rperm;
05026 int *rrank = f->rrank;
05027 int col_p = cperm[rank_p];
05028 int row_p = rperm[rank_p];
05029 int i;
05030
05031 for (i = rank_p; i < rank_r; i++)
05032 {
05033 cperm[i] = cperm[i + 1];
05034 crank[cperm[i]] = i;
05035 rperm[i] = rperm[i + 1];
05036 rrank[rperm[i]] = i;
05037 }
05038 cperm[rank_r] = col_p;
05039 crank[col_p] = rank_r;
05040 rperm[rank_r] = row_p;
05041 rrank[row_p] = rank_r;
05042 }
05043
05044 static int dbl_eliminate_row (
05045 dbl_factor_work * f,
05046 int rank_p,
05047 int rank_r)
05048 {
05049 dbl_ur_info *ur_inf = f->ur_inf;
05050 int *rperm = f->rperm;
05051 int *cperm = f->cperm;
05052 int *urindx = f->urindx;
05053 double *urcoef = f->urcoef;
05054 int *erindx = f->erindx;
05055 double *ercoef = f->ercoef;
05056 double *work_coef = f->work_coef;
05057 int er_freebeg = f->er_freebeg;
05058 int er_space = f->er_space;
05059 int beg;
05060 int nzcnt;
05061 int i;
05062 int j;
05063 int c;
05064 int r;
05065 double pivot_mul;
05066
05067 #ifdef dbl_TRACK_FACTOR
05068 double max;
05069
05070 dbl_EGlpNumInitVar (max);
05071 dbl_EGlpNumCopy (max, f->maxelem_cur);
05072 #endif
05073 dbl_EGlpNumInitVar (pivot_mul);
05074
05075 for (i = rank_p; i < rank_r; i++)
05076 {
05077 c = cperm[i];
05078 if (dbl_EGlpNumIsNeqZero (work_coef[c], f->fzero_tol))
05079
05080 {
05081 r = rperm[i];
05082 beg = ur_inf[r].rbeg;
05083 nzcnt = ur_inf[r].nzcnt;
05084 dbl_EGlpNumCopyFrac (pivot_mul, work_coef[c], urcoef[beg]);
05085 dbl_EGlpNumZero (work_coef[c]);
05086 for (j = 1; j < nzcnt; j++)
05087 {
05088 dbl_EGlpNumSubInnProdTo (work_coef[urindx[beg + j]], pivot_mul, urcoef[beg + j]);
05089 }
05090 if (er_freebeg >= er_space)
05091 {
05092
05093 #ifdef dbl_TRACK_FACTOR
05094 dbl_EGlpNumClearVar (max);
05095 #endif
05096 dbl_EGlpNumClearVar (pivot_mul);
05097 return E_UPDATE_NOSPACE;
05098 }
05099 erindx[er_freebeg] = r;
05100 dbl_EGlpNumCopy (ercoef[er_freebeg], pivot_mul);
05101 #ifdef dbl_TRACK_FACTOR
05102 dbl_EGlpNumSetToMaxAbs (max, pivot_mul);
05103 #endif
05104 er_freebeg++;
05105 }
05106 else
05107 {
05108 dbl_EGlpNumZero (work_coef[c]);
05109 }
05110 }
05111 f->er_freebeg = er_freebeg;
05112 #ifdef dbl_TRACK_FACTOR
05113 dbl_EGlpNumCopy (f->maxelem_cur, max);
05114 dbl_EGlpNumClearVar (max);
05115 #endif
05116 dbl_EGlpNumClearVar (pivot_mul);
05117 return 0;
05118 }
05119
05120 static int dbl_create_row (
05121 dbl_factor_work * f,
05122 double * a,
05123 int row,
05124 int minrank)
05125 {
05126 int *cperm = f->cperm;
05127 int dim = f->dim;
05128 int i;
05129 int j;
05130 int rval = 0;
05131
05132 #ifdef dbl_TRACK_FACTOR
05133 double max;
05134
05135