/home/coin/SVN-release/OS-2.4.0/Couenne/src/cut/sdpcuts/populate.cpp

Go to the documentation of this file.
00001 /* $Id: populate.cpp 508 2011-02-15 21:52:44Z pbelotti $
00002  *
00003  * Name:    populate.cpp
00004  * Author:  Andrea Qualizza
00005  * Purpose: 
00006  *
00007  * This file is licensed under the Eclipse Public License (EPL)
00008  */
00009 
00010 #include <stdio.h>
00011 #include <string.h>
00012 #include <OsiCuts.hpp>
00013 #include <OsiSolverInterface.hpp>
00014 #include <CoinMpsIO.hpp>
00015 #include <populate.hpp>
00016 
00017 #define indexQ(i,j,n) ((n) + (i) * (2*(n)-1-(i)) / 2 + (j))
00018 
00019 
00020 int getFirstIdx(const char *colName);
00021 int getSecondIdx(const char *colName);
00022 double _mul(double a, double b, double infinity);
00023 
00024 
00025 int populateProblem (
00026         const char *filename,
00027         int *nptr,
00028         int *tptr,
00029         int *consptr,
00030         double **bptr,
00031         double **cptr,
00032         double ***Qptr,
00033         double *constantptr,
00034         double ***origmatptr,
00035         double **origrhsptr,
00036         char **origsenseptr,
00037         double **xlbptr,
00038         double **xubptr,
00039         double **ylbptr,
00040         double **yubptr,
00041         OsiSolverInterface *si ) {
00042         //this function assumes that the MPS file uses the following
00043         //convention for the variables' names:
00044         //  x_i represents an original variable of the problem.
00045         //  x_i_j represents a bilinear term of the form x_i * x_j in the 
00046         //        original formulation
00047 
00048         double _constant = 0.0;
00049         char tempstring[1024];
00050         FILE *mpsfile = NULL;
00051         mpsfile = fopen(filename,"r");
00052         if (mpsfile != NULL)  {
00053                 fscanf(mpsfile,"%s",tempstring); //NAME
00054                 fscanf(mpsfile,"%s",tempstring); //@objconst=<value>
00055                 if (char *tempstring2 = strstr(tempstring,"@objconst=")) {
00056                         _constant= - atof(tempstring2+10);
00057                 }
00058                 fclose(mpsfile);
00059         } else {
00060                 printf("File %s does not exist !\n",filename);
00061                 return 1;
00062         }
00063         
00064 
00065         *constantptr = _constant;
00066 
00067         CoinMpsIO cmpsio;
00068         cmpsio.messageHandler()->setLogLevel(0);
00069         cmpsio.readMps(filename,"mps");
00070 
00071         const CoinPackedMatrix *problemMatrixByCol = cmpsio.getMatrixByCol();
00072 
00073         const double *rowlb,*rowub,*objcoeff,*collb,*colub;
00074 
00075         rowlb = cmpsio.getRowLower();
00076         rowub = cmpsio.getRowUpper();
00077         objcoeff = cmpsio.getObjCoefficients();
00078         collb = cmpsio.getColLower();
00079         colub = cmpsio.getColUpper();
00080 
00081         
00082         //find out what's the size of the original problem
00083         int origVars=0;         
00084         for (int i=0;i<cmpsio.getNumCols();i++) {
00085                 if (getSecondIdx(cmpsio.columnName(i)) == -1)
00086                         origVars++; //if variable's name is of the form x_i (original variable)
00087         }
00088 
00089         //determine which original variables appear in quadratic terms
00090         bool *inBilinear;
00091         inBilinear = new bool[origVars];
00092         for (int i=0;i<origVars;i++)
00093                 inBilinear[i] = false;
00094 
00095         int origBilinearVars = 0;
00096         int elimVars = 0;
00097         for(int i=0;i<cmpsio.getNumCols();i++) {
00098                 if (getSecondIdx(cmpsio.columnName(i)) >= 0) {
00099                         int firstIdx = getFirstIdx(cmpsio.columnName(i));
00100                         int secondIdx = getSecondIdx(cmpsio.columnName(i));
00101                         if ((problemMatrixByCol->getVector(i).getNumElements() > 0) || 
00102                             (objcoeff[i] != 0.0)) {
00103                                 //column is non empty OR objective function for x_i_j != 0
00104                                 inBilinear[firstIdx] = true;
00105                                 inBilinear[secondIdx] = true;
00106                                 origBilinearVars++;
00107                         }
00108                         else
00109                                 elimVars++;
00110                 }
00111         }
00112 
00113         int n = 0;
00114         int t = 0; //are those variables that do not appear in any bilinear term
00115         for(int i=0;i<origVars;i++){
00116                 if (inBilinear[i])
00117                         n++;
00118                 else
00119                         t++;
00120         }
00121 
00122         int N = n*(n+3)/2;
00123         int totVars = N + t;
00124         assert(origVars = (elimVars + n + t +origBilinearVars));
00125 
00126         
00127         #ifdef TRACE
00128         printf("populate:: MPS file : vars=%d cons=%d\n",cmpsio.getNumCols(),cmpsio.getNumRows());
00129         if (elimVars)
00130         printf("populate:: eliminated %d bilinear vars (0.0 obj coefficient AND empty column)\n",elimVars);
00131         printf("populate:: original problem : n=%d  t=%d  bilinearVars=%d  total=%d\n",
00132         n,t,origBilinearVars, n+t+origBilinearVars);
00133         printf("populate:: sdp formulation : n=%d  N=n*(n+3)/2=%d  t=%d  totVars=(N+t)=%d\n",n,N,t,totVars);
00134         #endif
00135 
00136         //first we do a remapping of the indices (lookupIdx) of the new x_i and y_i
00137         int *lookupIdx = new int[n+t];
00138         for(int i=0;i<n+t;i++)
00139                 lookupIdx[i] = -1;
00140         int xcnt = 0;
00141         int ycnt = 0;
00142         for(int i=0;i<cmpsio.getNumCols();i++) {
00143                 int firstIdx = getFirstIdx(cmpsio.columnName(i));
00144                 int secondIdx = getSecondIdx(cmpsio.columnName(i));
00145                 if (secondIdx == -1){
00146                         if (inBilinear[firstIdx]) {
00147                                 lookupIdx[firstIdx] = xcnt;
00148                                 xcnt++;
00149                         }
00150                         else { //not in any bilinear term, it will be a y_i variable
00151                                 lookupIdx[firstIdx] = ycnt;
00152                                 ycnt++;
00153                         }
00154                 }
00155         }
00156         #ifdef CHECK
00157         for(int i=0;i<n+t;i++)
00158                 if(lookupIdx[i] == -1)
00159                         printf("populate::WARNING: variable x_%d not found in the original problem\n",i);
00160         #endif
00161 
00162 
00163         double *lb,*ub;
00164         lb = new double[totVars];
00165         ub = new double[totVars];
00166         for(int i=0;i<totVars;i++) {
00167                 lb[i] = - si->getInfinity();
00168                 ub[i] = si->getInfinity();
00169         }
00170 
00171         // add all n + n(n+1)/2 + t variables
00172         for (int i=totVars; i--;)
00173                 si -> addCol (0, NULL, NULL,  - si->getInfinity(),  si->getInfinity(), 0);
00174 
00175 
00176         int *indices;
00177         indices = new int[N+t];
00178         //set OBJ_FUNCTION_MULTIPLIER to 1.0 to keep a minimization pb, -1.0 for maximization
00179         #define OBJ_FUNCTION_MULTIPLIER -1.0
00180         for(int i=0;i<cmpsio.getNumCols();i++) {
00181                 int firstIdx = getFirstIdx(cmpsio.columnName(i));
00182                 int secondIdx = getSecondIdx(cmpsio.columnName(i));
00183                 if (secondIdx >= 0){
00184                         if ((inBilinear[firstIdx]) && (inBilinear[secondIdx])) {
00185                                 indices[i] = indexQ(lookupIdx[firstIdx],lookupIdx[secondIdx],n);
00186                         }
00187                         else
00188                                 indices[i] = -1;
00189                 }
00190                 else {
00191                         if (inBilinear[firstIdx]) {
00192                                 indices[i] = lookupIdx[i];
00193                         }
00194                         else {
00195                                 indices[i] = N + lookupIdx[i];
00196                         }
00197                 }
00198                 if (indices[i] >= 0) {
00199                         lb[indices[i]] = collb[i];
00200                         ub[indices[i]] = colub[i];
00201                         si->setColLower(indices[i],collb[i]);
00202                         si->setColUpper(indices[i],colub[i]);
00203                         si->setObjCoeff(indices[i], OBJ_FUNCTION_MULTIPLIER * objcoeff[i]);
00204                 }
00205         }
00206 
00207 
00208 
00209         //setting lb and ub for extended variables x_i_j
00210         double min;
00211         double max;
00212         for(int i=0;i<n;i++)
00213                 for(int j=i;j<n;j++) {
00214                         min = + si->getInfinity();
00215                         max = - si->getInfinity();
00216                         double tempval;
00217                         tempval = _mul(lb[i],lb[j],si->getInfinity());
00218                         if (tempval < min)
00219                                 min = tempval;
00220                         tempval = _mul(lb[i],ub[j],si->getInfinity());
00221                         if (tempval < min)
00222                                 min = tempval;
00223                         tempval = _mul(ub[i],lb[j],si->getInfinity());
00224                         if (tempval < min)
00225                                 min = tempval;
00226                         tempval = _mul(ub[i],ub[j],si->getInfinity());
00227                         if (tempval < min)
00228                                 min = tempval;
00229                         
00230                         tempval = _mul(lb[i],lb[j],si->getInfinity());
00231                         if (tempval > max)
00232                                 max = tempval;
00233                         tempval = _mul(lb[i],ub[j],si->getInfinity());
00234                         if (tempval > max)
00235                                 max = tempval;
00236                         tempval = _mul(ub[i],lb[j],si->getInfinity());
00237                         if (tempval > max)
00238                                 max = tempval;
00239                         tempval = _mul(ub[i],ub[j],si->getInfinity());
00240                         if (tempval > max)
00241                                 max = tempval;
00242 
00243                         //sets bounds for X_i_j :
00244                         // [ min {l_i*l_j, l_i*u_j, u_i*l_j, u_i*u_j},
00245                         //   max {l_i*l_j, l_i*u_j, u_i*l_j, u_i*u_j} ]
00246                         //for X_i_i we will have the bounds
00247                         // [ max {0 , min {l_i*l_i, l_i*u_i, u_i*l_i, u_i*u_i} },
00248                         //   max {l_i*l_i, l_i*u_i, u_i*l_i, u_i*u_i} ]
00249 #ifdef ZERO_LB_DIAGONAL
00250                         if (i==j) {
00251                                 if (min < 0)
00252                                         min = 0;
00253                         }
00254 
00255 #endif
00256                         si->setColLower(indexQ(i,j,n),min);
00257                         si->setColUpper(indexQ(i,j,n),max);
00258                 }
00259 
00260         OsiCuts cs;
00261 
00262 
00263         //original linear cuts
00264         const CoinPackedMatrix *problemMatrixByRow = cmpsio.getMatrixByRow();
00265         for(int i=0;i<cmpsio.getNumRows();i++) {
00266                 CoinPackedVector currRow = (CoinPackedVector) problemMatrixByRow->getVector(i);
00267                 int *currRowIdx = (int*) currRow.getIndices();
00268                 double *currRowElem = (double*) currRow.getElements();
00269                 OsiRowCut *cut   = new OsiRowCut;
00270                 
00271                 double *newRowElem = new double[currRow.getNumElements()];
00272                 int *newRowIdx = new int[currRow.getNumElements()];
00273 
00274                 for (int j=0;j<currRow.getNumElements();j++) {
00275                         assert(indices[currRowIdx[j]] != -1);
00276                         newRowIdx[j]=indices[currRowIdx[j]];
00277                         newRowElem[j]=currRowElem[j];
00278                 }
00279                 cut->setRow (currRow.getNumElements(), newRowIdx, newRowElem);
00280                 cut->setLb(rowlb[i]);
00281                 cut->setUb(rowub[i]);
00282                 delete [] newRowElem;
00283                 delete [] newRowIdx;
00284 
00285                 cs.insert(cut);
00286         }
00287 
00288 
00289 
00290         int idx;
00291 #ifdef RLT_CUTS
00292 #ifndef RLT_SEPARATION
00293         //McKormick cuts 
00294         //for square terms
00295         for(int i=0;i<n;i++) {
00296                 idx = indexQ(i,i,n);
00297 //                      if (origterm[ind]==true) { //create cuts only for terms x_ij in the original formulation
00298                         if (lb[i] != 0.0)
00299                                 createCut(cs,lb[i]*lb[i], -1,idx,-1.0,i,2 * lb[i]); 
00300                                 // -Xii <= - 2 li xi + li^2
00301                         // else bound -Xii <= 0 already present
00302                         
00303                         if (ub[i] != 0.0)
00304                                 createCut(cs,ub[i]*ub[i], -1,idx,-1.0,i,2 * ub[i]); 
00305                                 // -Xii <= - 2 ui xi + ui^2
00306                         // else bound -Xii <= 0 already present
00307                         
00308                         createCut(cs,-lb[i]*ub[i],-1,idx, 1.0,i, - lb[i]-ub[i] );
00309                         //  Xii <= (li+ui) xi - li ui
00310 //                      }
00311         }
00312         //for i!=j
00313         for(int i=0;i<n;i++)
00314                 for(int j=i+1;j<n;j++) {
00315                         idx = indexQ(i,j,n);
00316                         //creates cuts only for terms x_ij in the original formulation
00317                                 createCut(cs,lb[i]*lb[j],-1,idx,-1.0,i,lb[j],j,lb[i]); 
00318                                 // -Xij <= - lj xi - li xj + li lj
00319                                 createCut(cs,ub[i]*ub[j],-1,idx,-1.0,i,ub[j],j,ub[i]);
00320                                 // -Xij <= - uj xi - ui xj + ui uj
00321                                 createCut(cs,-lb[i]*ub[j],-1,idx,1.0,i,-ub[j],j,-lb[i]);
00322                                 //  Xij <=   uj xi + li xj - li uj
00323                                 createCut(cs,-ub[i]*lb[j],-1,idx,1.0,i,-lb[j],j,-ub[i]);
00324                                 //  Xij <=   lj xi + ui xj - ui lj
00325                 }
00326 #endif // #RLT_SEPARATION
00327 #endif //#ifdef RLT_CUTS
00328 
00329 
00330         // add constraints
00331         si -> applyCuts (cs);
00332 
00333         si -> setObjSense(-1); //maximization (the mps are minimization problems, but before we took -1.0 * obj)
00334 
00335         #ifdef TRACE_RLT_MPS
00336         //write mps formulation
00337 
00338         char **varNames = new char*[N+t];
00339         for(int j=0;j<N+t;j++)
00340                 varNames[j] = new char[20];
00341 
00342         for (int i=0; i<n; i++) {
00343                 sprintf(varNames[i],"x_%d",i);
00344         }
00345         for (int i=0; i<n; i++) {
00346                 sprintf(varNames[indexQ (i,i,n)],"x_%d_%d",i,i);
00347                 for (int j=i+1; j<n; j++) {
00348                         sprintf(varNames[indexQ (i,j,n)],"x_%d_%d",i,j);
00349                 }
00350         }
00351         for(int i=0; i<t; i++)
00352                 sprintf(varNames[N+i],"y_%d",i);
00353 
00354         char **conNames = new char*[si->getNumRows()];
00355         for (int j=0;j<si->getNumRows();j++)
00356                 conNames[j] = new char[20];
00357 
00358         for(int j=0;j<cmpsio.getNumRows();j++)
00359                 sprintf(conNames[j],"orig_%d",j);
00360         for(int j=cmpsio.getNumRows();j<si->getNumRows();j++)
00361                 sprintf(conNames[j],"rlt_%d",j-cmpsio.getNumRows());
00362                 
00363         si->writeMpsNative("rlt.mps",
00364                 const_cast <const char **> (conNames), 
00365                 const_cast <const char **> (varNames),
00366                 0,1,1.0);
00367 
00368         for(int j=0;j<N+t;j++)
00369                 delete [] varNames[j];
00370         delete [] varNames;
00371         for(int j=0;j<si->getNumRows();j++)
00372                 delete [] conNames[j];
00373         delete [] conNames;
00374         #endif
00375 
00376         delete [] lookupIdx;
00377         delete [] inBilinear;
00378 
00379         delete [] lb;
00380         delete [] ub;
00381 
00382         delete [] indices;
00383 
00384 
00385 
00386         // save problem data into Q , origmat, b, c, xlb, xub, ylb, yub
00387         //objective function: max b x + Q X + c y
00388         //set nptr, tptr, Qptr, bptr,cptr, origmat,xlb...
00389         double *b;
00390         double *c;
00391         double **Q;
00392         double **origmat;
00393         double *origrhs;
00394         char *origsense;
00395         double *xlb;
00396         double *xub;
00397         double *ylb;
00398         double *yub;
00399         int cons;
00400         cons = cmpsio.getNumRows();
00401         *consptr = cons;
00402 
00403         *nptr = n;
00404         *tptr = t;
00405 
00406         const double *tmp_objcoeff = si->getObjCoefficients();
00407         const double *tmp_lb = si->getColLower();
00408         const double *tmp_ub = si->getColUpper();
00409         const double *tmp_rhs = si->getRightHandSide();
00410         const char   *tmp_sense = si->getRowSense();
00411         
00412         xlb = new double[n+t];
00413         *xlbptr = xlb;
00414         xub = new double[n+t];
00415         *xubptr = xub;
00416         ylb = new double[n+t];
00417         *ylbptr = ylb;
00418         yub = new double[n+t];
00419         *yubptr = yub;
00420 
00421         b = new double[n];
00422         *bptr = b;
00423         for (int i=0; i<n; i++) {
00424                 b[i]=tmp_objcoeff[i];
00425                 xlb[i] = tmp_lb[i];
00426                 xub[i] = tmp_ub[i];
00427         }
00428 
00429         Q = new double*[n];
00430         for (int i=0; i<n; i++)
00431                 Q[i] = new double[n];
00432         *Qptr = Q;
00433         for (int i=0; i<n; i++)
00434                 for (int j=i; j<n; j++) {
00435                         Q[i][j] = tmp_objcoeff[indexQ(i,j,n)] / 2;
00436                         Q[j][i] = tmp_objcoeff[indexQ(i,j,n)] / 2;
00437                         //should we multiply by two the entry Q[i][i] ?
00438                         //check heuristics... we always add Q[i][j] and Q[j][i]
00439                         //if (i==j)
00440                         //      Q[i][i] *= 2.0;
00441                 }
00442 
00443 
00444         c = new double[t];
00445         *cptr = c;
00446         for (int i=0;i<t;i++) {
00447                 c[i]=tmp_objcoeff[i+N];
00448                 ylb[i] = tmp_lb[i+N];
00449                 yub[i] = tmp_ub[i+N];
00450         }
00451 
00452 
00453         origmat = new double*[cmpsio.getNumRows()];
00454         for (int i=0;i<cmpsio.getNumRows();i++)
00455                 origmat[i] = new double[N + t];
00456         for (int i=0;i<cmpsio.getNumRows();i++)
00457                 for(int j=0;j<N+t;j++)
00458                         origmat[i][j] = 0.0;
00459         *origmatptr = origmat;
00460 
00461         origrhs = new double[cmpsio.getNumRows()];
00462         origsense = new char[cmpsio.getNumRows()];
00463         for (int i=0;i<cmpsio.getNumRows();i++) {
00464                 origrhs[i]= tmp_rhs[i];
00465                 origsense[i] = tmp_sense[i];
00466         }
00467         *origrhsptr = origrhs;
00468         *origsenseptr = origsense;
00469 
00470         const CoinPackedMatrix* tmp_matbyrow = si->getMatrixByRow ();
00471         for(int i=0;i<cons;i++) {
00472                 CoinPackedVector tmp_currRow = (CoinPackedVector) tmp_matbyrow->getVector(i);
00473                 int *tmpRowIdx = (int*) tmp_currRow.getIndices();
00474                 double *tmpRowElem = (double*) tmp_currRow.getElements();
00475 
00476                 for(int j=0;j<tmp_currRow.getNumElements();j++) {
00477                         origmat[i][tmpRowIdx[j]] = tmpRowElem[j];
00478                 }
00479         }
00480 
00481         return 0;
00482 }
00483 
00484 
00485 /***********************************************************************/
00486 // creates a cut. return 1 if cut was inserted into cs, 0 otherwise
00487 int createCut (OsiCuts &cs,           // set of cuts
00488                double rhs,            // rhs 
00489                int sign,              // -1: $\le$, +1: $\ge$, 0: =
00490                                       // indices, coefficients 
00491                                       // (index == -1 means don't care)
00492                int i1, double c1,     // first 
00493                int i2, double c2,     // second
00494                int i3, double c3,     // third
00495                int i4, double c4,     // forth
00496                bool is_global) {      // is this cut global (true) or local (false)?
00497 
00498         int nterms = 0;
00499 
00500         if ((i1 >= 0) && (c1 != 0.0)) nterms++; else c1 =0;
00501         if ((i2 >= 0) && (c2 != 0.0)) nterms++; else c2 =0;
00502         if ((i3 >= 0) && (c3 != 0.0)) nterms++; else c3 =0;
00503         if ((i4 >= 0) && (c4 != 0.0)) nterms++; else c4 =0;
00504         
00505         if (!nterms)
00506                 return 0; // nonsense cut
00507         int tmpcnt = 0;
00508         
00509         double    *coeff = new double [nterms]; 
00510         int       *index = new int    [nterms];
00511         OsiRowCut *cut   = new OsiRowCut;
00512         
00513         if ((i1 >= 0) && (c1 != 0.0))
00514         {
00515                 coeff[tmpcnt] = c1;
00516                 index[tmpcnt] = i1;
00517                 tmpcnt++;
00518         }
00519         if ((i2 >= 0) && (c2 != 0.0))
00520         {
00521                 coeff[tmpcnt] = c2;
00522                 index[tmpcnt] = i2;
00523                 tmpcnt++;
00524         }
00525         if ((i3 >= 0) && (c3 != 0.0))
00526         {
00527                 coeff[tmpcnt] = c3;
00528                 index[tmpcnt] = i3;
00529                 tmpcnt++;
00530         }
00531         if ((i4 >= 0) && (c4 != 0.0))
00532         {
00533                 coeff[tmpcnt] = c4;
00534                 index[tmpcnt] = i4;
00535                 tmpcnt++;
00536         }
00537 
00538         if (sign <= 0) cut -> setUb (rhs);
00539         if (sign >= 0) cut -> setLb (rhs);
00540         
00541         cut -> setRow (nterms, index, coeff);
00542         
00543         delete [] coeff;
00544         delete [] index;
00545         
00546         cut -> setGloballyValid (is_global); // global?
00547 
00548 //TODO: check the precision here
00549         cs.insertIfNotDuplicate(*cut,CoinAbsFltEq(1.0e-12));
00550         //cs.insert (cut); //old
00551 
00552         delete cut;
00553         
00554         return 1;
00555 }
00556 
00557 
00558 
00559 /***********************************************************************/
00560 int getFirstIdx(const char *colName) {
00561 // if colName = x_i or x_i_j returns i
00562         char *temp = new char[strlen(colName)+1];
00563         char *idx1,*idx2;
00564         int idx1int;
00565         strcpy(temp,colName);
00566         idx1 = temp;
00567         idx1 += 2; // gets rid of 'x_' at the beginning of the name
00568         idx2 = strchr(idx1,'_');
00569         if (idx2 != NULL) //variable of the form x_i_j
00570                 *idx2 = '\0';
00571         idx1int = atoi(idx1);
00572         delete [] temp;
00573         return idx1int;
00574 }
00575 
00576 
00577 /***********************************************************************/
00578 int getSecondIdx(const char *colName) {
00579 // if colName = x_i returns -1
00580 // if colNamr = x_i_j returns j
00581         char *temp = new char[strlen(colName)+1];
00582         char *idx1,*idx2;
00583         int idx2int =-1;
00584         strcpy(temp,colName);
00585         idx1 = temp;
00586         idx1 += 2; // gets rid of 'x_' at the beginning of the name
00587         idx2 = strchr(idx1,'_');
00588         if (idx2 != NULL){ //variable of the form x_i_j
00589                 *idx2 = '\0';
00590                 idx2++;
00591                 idx2int = atoi(idx2);
00592         }
00593         else
00594                 idx2int = -1;
00595         delete [] temp;
00596         return idx2int;
00597 }
00598 
00599 /***********************************************************************/
00600 double _mul(double a, double b, double infinity) {
00601         if ((a==0.0) || (b==0.0))
00602                 return 0.0;
00603 
00604         if ((a >= infinity) && (b > 0))
00605                 return infinity;
00606         if ((a > 0) && (b >= infinity))
00607                 return infinity;
00608         if ((a >= infinity) && (b < 0))
00609                 return - infinity;
00610         if ((a < 0) && (b >= infinity))
00611                 return - infinity;
00612 
00613         if ((a <= -infinity) && (b > 0))
00614                 return - infinity;
00615         if ((a > 0) && (b <= -infinity))
00616                 return - infinity;
00617         if ((a <= -infinity) && (b < 0))
00618                 return  infinity;
00619         if ((a < 0) && (b <= -infinity))
00620                 return - infinity;
00621 
00622         return a*b;
00623 }
00624 

Generated on Thu Sep 22 03:05:57 2011 by  doxygen 1.4.7