Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

CoinMpsIO.cpp

00001 // Copyright (C) 2000, International Business Machines
00002 // Corporation and others.  All Rights Reserved.
00003 #if defined(_MSC_VER)
00004 // Turn off compiler warning about long names
00005 #  pragma warning(disable:4786)
00006 #endif
00007 
00008 #include <cassert>
00009 #include <cmath>
00010 #include <cfloat>
00011 #include <string>
00012 #include <cstdio>
00013 #include <iostream>
00014 
00015 #include "CoinMpsIO.hpp"
00016 #include "CoinMessage.hpp"
00017 
00018 
00019 //#############################################################################
00020 
00021 double osi_strtod(char * ptr, char ** output) 
00022 {
00023 
00024   static const double fraction[]=
00025   {1.0,1.0e-1,1.0e-2,1.0e-3,1.0e-4,1.0e-5,1.0e-6,1.0e-7,1.0e-8,
00026    1.0e-9,1.0e-10,1.0e-11,1.0e-12,1.0e-13,1.0e-14,1.0e-15,1.0e-16,
00027    1.0e-17,1.0e-18,1.0e-19};
00028 
00029   static const double exponent[]=
00030   {1.0e-9,1.0e-8,1.0e-7,1.0e-6,1.0e-5,1.0e-4,1.0e-3,1.0e-2,1.0e-1,
00031    1.0,1.0e1,1.0e2,1.0e3,1.0e4,1.0e5,1.0e6,1.0e7,1.0e8,1.0e9};
00032 
00033   double value = 0.0;
00034   char * save = ptr;
00035 
00036   // take off leading white space
00037   while (*ptr==' '||*ptr=='\t')
00038     ptr++;
00039   double sign1=1.0;
00040   // do + or -
00041   if (*ptr=='-') {
00042     sign1=-1.0;
00043     ptr++;
00044   } else if (*ptr=='+') {
00045     ptr++;
00046   }
00047   // more white space
00048   while (*ptr==' '||*ptr=='\t')
00049     ptr++;
00050   char thisChar=0;
00051   while (value<1.0e30) {
00052     thisChar = *ptr;
00053     ptr++;
00054     if (thisChar>='0'&&thisChar<='9') 
00055       value = value*10.0+thisChar-'0';
00056     else
00057       break;
00058   }
00059   if (value<1.0e30) {
00060     if (thisChar=='.') {
00061       // do fraction
00062       double value2 = 0.0;
00063       int nfrac=0;
00064       while (nfrac<20) {
00065         thisChar = *ptr;
00066         ptr++;
00067         if (thisChar>='0'&&thisChar<='9') {
00068           value2 = value2*10.0+thisChar-'0';
00069           nfrac++;
00070         } else {
00071           break;
00072         }
00073       }
00074       if (nfrac<20) {
00075         value += value2*fraction[nfrac];
00076       } else {
00077         thisChar='x'; // force error
00078       }
00079     }
00080     if (thisChar=='e'||thisChar=='E') {
00081       // exponent
00082       int sign2=1;
00083       // do + or -
00084       if (*ptr=='-') {
00085         sign2=-1;
00086         ptr++;
00087       } else if (*ptr=='+') {
00088         ptr++;
00089       }
00090       int value3 = 0;
00091       while (value3<100) {
00092         thisChar = *ptr;
00093         ptr++;
00094         if (thisChar>='0'&&thisChar<='9') {
00095           value3 = value3*10+thisChar-'0';
00096         } else {
00097           break;
00098         }
00099       }
00100       if (value3<200) {
00101         value3 *= sign2; // power of 10
00102         if (abs(value3)<10) {
00103           // do most common by lookup (for accuracy?)
00104           value *= exponent[value3+9];
00105         } else {
00106           value *= pow(10.0,value3);
00107         }
00108       } else {
00109         thisChar='x'; // force error
00110       }
00111     } 
00112     if (thisChar==0||thisChar=='\t'||thisChar==' ') {
00113       // okay
00114       *output=ptr;
00115     } else {
00116       *output=save;
00117     }
00118   } else {
00119     // bad value
00120     *output=save;
00121   }
00122   return value*sign1;
00123 } 
00124 //#############################################################################
00125 // sections
00126 const static char *section[] = {
00127   "", "NAME", "ROW", "COLUMN", "RHS", "RANGES", "BOUNDS", "ENDATA", " ","QSECTION", "CSECTION", " "
00128 };
00129 
00130 // what is allowed in each section - must line up with COINSectionType
00131 const static COINMpsType startType[] = {
00132   COIN_UNKNOWN_MPS_TYPE, COIN_UNKNOWN_MPS_TYPE,
00133   COIN_N_ROW, COIN_BLANK_COLUMN,
00134   COIN_BLANK_COLUMN, COIN_BLANK_COLUMN,
00135   COIN_UP_BOUND, COIN_UNKNOWN_MPS_TYPE,
00136   COIN_UNKNOWN_MPS_TYPE,
00137   COIN_BLANK_COLUMN, COIN_BLANK_COLUMN, COIN_UNKNOWN_MPS_TYPE
00138 };
00139 const static COINMpsType endType[] = {
00140   COIN_UNKNOWN_MPS_TYPE, COIN_UNKNOWN_MPS_TYPE,
00141   COIN_BLANK_COLUMN, COIN_UNSET_BOUND,
00142   COIN_S1_COLUMN, COIN_S1_COLUMN,
00143   COIN_UNKNOWN_MPS_TYPE, COIN_UNKNOWN_MPS_TYPE,
00144   COIN_UNKNOWN_MPS_TYPE,
00145   COIN_BLANK_COLUMN, COIN_BLANK_COLUMN, COIN_UNKNOWN_MPS_TYPE
00146 };
00147 const static int allowedLength[] = {
00148   0, 0,
00149   1, 2,
00150   0, 0,
00151   2, 0,
00152   0, 0
00153 };
00154 
00155 // names of types
00156 const static char *mpsTypes[] = {
00157   "N", "E", "L", "G",
00158   "  ", "S1", "S2", "S3", "  ", "  ", "  ",
00159   "  ", "UP", "FX", "LO", "FR", "MI", "PL", "BV", "UI", "SC"
00160 };
00161 
00162 int CoinMpsCardReader::cleanCard()
00163 {
00164   char * getit;
00165 #ifdef COIN_USE_ZLIB
00166   if (fp_) {
00167     // normal file
00168     getit = fgets ( card_, MAX_CARD_LENGTH, fp_ );
00169   } else {
00170     getit = gzgets ( gzfp_, card_, MAX_CARD_LENGTH );
00171   }
00172 #else
00173   // only normal file
00174   getit = fgets ( card_, MAX_CARD_LENGTH, fp_ );
00175 #endif
00176   
00177   if ( getit ) {
00178     cardNumber_++;
00179     unsigned char * lastNonBlank = (unsigned char *) card_-1;
00180     unsigned char * image = (unsigned char *) card_;
00181     while ( *image != '\0' ) {
00182       if ( *image != '\t' && *image < ' ' ) {
00183         break;
00184       } else if ( *image != '\t' && *image != ' ') {
00185         lastNonBlank = image;
00186       }
00187       image++;
00188     }
00189     *(lastNonBlank+1)='\0';
00190     return 0;
00191   } else {
00192     return 1;
00193   }
00194 }
00195 
00196 char *
00197 nextBlankOr ( char *image )
00198 {
00199   char * saveImage=image;
00200   while ( 1 ) {
00201     if ( *image == ' ' || *image == '\t' ) {
00202       break;
00203     }
00204     if ( *image == '\0' )
00205       return NULL;
00206     image++;
00207   }
00208   // Allow for floating - or +.  Will fail if user has that as row name!!
00209   if (image-saveImage==1&&(*saveImage=='+'||*saveImage=='-')) {
00210     while ( *image == ' ' || *image == '\t' ) {
00211       image++;
00212     }
00213     image=nextBlankOr(image);
00214   }
00215   return image;
00216 }
00217 
00218 // Read to NAME card - return nonzero if bad
00219 COINSectionType
00220 CoinMpsCardReader::readToNextSection (  )
00221 {
00222   bool found = false;
00223 
00224   while ( !found ) {
00225     // need new image
00226 
00227     if ( cleanCard() ) {
00228       section_ = COIN_EOF_SECTION;
00229       break;
00230     }
00231     if ( !strncmp ( card_, "NAME", 4 ) ||
00232                 !strncmp( card_, "TIME", 4 ) ||
00233                 !strncmp( card_, "STOCH", 5 ) ) {
00234       section_ = COIN_NAME_SECTION;
00235       char *next = card_ + 5;
00236 
00237       handler_->message(COIN_MPS_LINE,messages_)<<cardNumber_
00238                                                <<card_<<CoinMessageEol;
00239       while ( next != eol_ ) {
00240         if ( *next == ' ' || *next == '\t' ) {
00241           next++;
00242         } else {
00243           break;
00244         }
00245       }
00246       if ( next != eol_ ) {
00247         char *nextBlank = nextBlankOr ( next );
00248         char save;
00249 
00250         if ( nextBlank ) {
00251           save = *nextBlank;
00252           *nextBlank = '\0';
00253           strcpy ( columnName_, next );
00254           *nextBlank = save;
00255           if ( strstr ( nextBlank, "FREE" ) )
00256             freeFormat_ = true;
00257         } else {
00258           strcpy ( columnName_, next );
00259         }
00260       } else {
00261         strcpy ( columnName_, "no_name" );
00262       }
00263       break;
00264     } else if ( card_[0] != '*' && card_[0] != '#' ) {
00265       // not a comment
00266       int i;
00267 
00268       handler_->message(COIN_MPS_LINE,messages_)<<cardNumber_
00269                                                <<card_<<CoinMessageEol;
00270       for ( i = COIN_ROW_SECTION; i < COIN_UNKNOWN_SECTION; i++ ) {
00271         if ( !strncmp ( card_, section[i], strlen ( section[i] ) ) ) {
00272           break;
00273         }
00274       }
00275       position_ = card_;
00276       eol_ = card_;
00277       section_ = ( COINSectionType ) i;
00278       break;
00279     }
00280   }
00281   return section_;
00282 }
00283 // This one takes gzFile if fp null
00284 CoinMpsCardReader::CoinMpsCardReader (  FILE * fp , gzFile gzfp, CoinMpsIO * reader)
00285 {
00286   memset ( card_, 0, MAX_CARD_LENGTH );
00287   position_ = card_;
00288   eol_ = card_;
00289   mpsType_ = COIN_UNKNOWN_MPS_TYPE;
00290   memset ( rowName_, 0, MAX_FIELD_LENGTH );
00291   memset ( columnName_, 0, MAX_FIELD_LENGTH );
00292   value_ = 0.0;
00293   fp_ = fp;
00294   gzfp_ = gzfp;
00295   section_ = COIN_EOF_SECTION;
00296   cardNumber_ = 0;
00297   freeFormat_ = false;
00298   eightChar_ = true;
00299   reader_ = reader;
00300   handler_ = reader_->messageHandler();
00301   messages_ = reader_->messages();
00302 }
00303 //  ~CoinMpsCardReader.  Destructor
00304 CoinMpsCardReader::~CoinMpsCardReader (  )
00305 {
00306 #ifdef COIN_USE_ZLIB
00307   if (!fp_) {
00308     // no fp_ so must be compressed read
00309     gzclose(gzfp_);
00310   }
00311 #endif
00312   if (fp_)
00313     fclose ( fp_ );
00314 }
00315 
00316 void
00317 strcpyAndCompress ( char *to, const char *from )
00318 {
00319   int n = strlen ( from );
00320   int i;
00321   int nto = 0;
00322 
00323   for ( i = 0; i < n; i++ ) {
00324     if ( from[i] != ' ' ) {
00325       to[nto++] = from[i];
00326     }
00327   }
00328   if ( !nto )
00329     to[nto++] = ' ';
00330   to[nto] = '\0';
00331 }
00332 
00333 //  nextField
00334 COINSectionType
00335 CoinMpsCardReader::nextField (  )
00336 {
00337   mpsType_ = COIN_BLANK_COLUMN;
00338   // find next non blank character
00339   char *next = position_;
00340 
00341   while ( next != eol_ ) {
00342     if ( *next == ' ' || *next == '\t' ) {
00343       next++;
00344     } else {
00345       break;
00346     }
00347   }
00348   bool gotCard;
00349 
00350   if ( next == eol_ ) {
00351     gotCard = false;
00352   } else {
00353     gotCard = true;
00354   }
00355   while ( !gotCard ) {
00356     // need new image
00357 
00358     if ( cleanCard() ) {
00359       return COIN_EOF_SECTION;
00360     }
00361     if ( card_[0] == ' ' ) {
00362       // not a section or comment
00363       position_ = card_;
00364       eol_ = card_ + strlen ( card_ );
00365       // get mps type and column name
00366       // scan to first non blank
00367       next = card_;
00368       while ( next != eol_ ) {
00369         if ( *next == ' ' || *next == '\t' ) {
00370           next++;
00371         } else {
00372           break;
00373         }
00374       }
00375       if ( next != eol_ ) {
00376         char *nextBlank = nextBlankOr ( next );
00377         int nchar;
00378 
00379         if ( nextBlank ) {
00380           nchar = nextBlank - next;
00381         } else {
00382           nchar = -1;
00383         }
00384         mpsType_ = COIN_BLANK_COLUMN;
00385         // special coding if RHS or RANGES, not free format and blanks
00386         if ( ( section_ != COIN_RHS_SECTION 
00387                && section_ != COIN_RANGES_SECTION )
00388              || freeFormat_ || strncmp ( card_ + 4, "        ", 8 ) ) {
00389           // if columns section only look for first field if MARKER
00390           if ( section_ == COIN_COLUMN_SECTION
00391                && !strstr ( next, "'MARKER'" ) ) nchar = -1;
00392           if ( nchar == allowedLength[section_] ) {
00393             //could be a type
00394             int i;
00395 
00396             for ( i = startType[section_]; i < endType[section_]; i++ ) {
00397               if ( !strncmp ( next, mpsTypes[i], nchar ) ) {
00398                 mpsType_ = ( COINMpsType ) i;
00399                 break;
00400               }
00401             }
00402             if ( mpsType_ != COIN_BLANK_COLUMN ) {
00403               //we know all we need so we can skip over
00404               next = nextBlank;
00405               while ( next != eol_ ) {
00406                 if ( *next == ' ' || *next == '\t' ) {
00407                   next++;
00408                 } else {
00409                   break;
00410                 }
00411               }
00412               if ( next == eol_ ) {
00413                 // error
00414                 position_ = eol_;
00415                 mpsType_ = COIN_UNKNOWN_MPS_TYPE;
00416               } else {
00417                 nextBlank = nextBlankOr ( next );
00418               }
00419             }
00420           }
00421           if ( mpsType_ != COIN_UNKNOWN_MPS_TYPE ) {
00422             // special coding if BOUND, not free format and blanks
00423             if ( section_ != COIN_BOUNDS_SECTION ||
00424                  freeFormat_ || strncmp ( card_ + 4, "        ", 8 ) ) {
00425               char save = '?';
00426 
00427               if ( !freeFormat_ && eightChar_ && next == card_ + 4 ) {
00428                 if ( eol_ - next >= 8 ) {
00429                   if ( *( next + 8 ) != ' ' && *( next + 8 ) != '\0' ) {
00430                     eightChar_ = false;
00431                   } else {
00432                     nextBlank = next + 8;
00433                   }
00434                   if (nextBlank) {
00435                     save = *nextBlank;
00436                     *nextBlank = '\0';
00437                   }
00438                 } else {
00439                   nextBlank = NULL;
00440                 }
00441               } else {
00442                 if ( nextBlank ) {
00443                   save = *nextBlank;
00444                   *nextBlank = '\0';
00445                 }
00446               }
00447               strcpyAndCompress ( columnName_, next );
00448               if ( nextBlank ) {
00449                 *nextBlank = save;
00450                 // on to next
00451                 next = nextBlank;
00452               } else {
00453                 next = eol_;
00454               }
00455             } else {
00456               // blank bounds name
00457               strcpy ( columnName_, "        " );
00458             }
00459             while ( next != eol_ ) {
00460               if ( *next == ' ' || *next == '\t' ) {
00461                 next++;
00462               } else {
00463                 break;
00464               }
00465             }
00466             if ( next == eol_ ) {
00467               // error unless row section or conic section
00468               position_ = eol_;
00469               value_ = -1.0e100;
00470               if ( section_ != COIN_ROW_SECTION && 
00471                    section_!= COIN_CONIC_SECTION)
00472                 mpsType_ = COIN_UNKNOWN_MPS_TYPE;
00473               else
00474                 return section_;
00475             } else {
00476               nextBlank = nextBlankOr ( next );
00477               //if (section_==COIN_CONIC_SECTION)
00478             }
00479             if ( section_ != COIN_ROW_SECTION ) {
00480               char save = '?';
00481 
00482               if ( !freeFormat_ && eightChar_ && next == card_ + 14 ) {
00483                 if ( eol_ - next >= 8 ) {
00484                   if ( *( next + 8 ) != ' ' && *( next + 8 ) != '\0' ) {
00485                     eightChar_ = false;
00486                   } else {
00487                     nextBlank = next + 8;
00488                   }
00489                   save = *nextBlank;
00490                   *nextBlank = '\0';
00491                 } else {
00492                   nextBlank = NULL;
00493                 }
00494               } else {
00495                 if ( nextBlank ) {
00496                   save = *nextBlank;
00497                   *nextBlank = '\0';
00498                 }
00499               }
00500               strcpyAndCompress ( rowName_, next );
00501               if ( nextBlank ) {
00502                 *nextBlank = save;
00503                 // on to next
00504                 next = nextBlank;
00505               } else {
00506                 next = eol_;
00507               }
00508               while ( next != eol_ ) {
00509                 if ( *next == ' ' || *next == '\t' ) {
00510                   next++;
00511                 } else {
00512                   break;
00513                 }
00514               }
00515               // special coding for markers
00516               if ( section_ == COIN_COLUMN_SECTION &&
00517                    !strncmp ( rowName_, "'MARKER'", 8 ) && next != eol_ ) {
00518                 if ( !strncmp ( next, "'INTORG'", 8 ) ) {
00519                   mpsType_ = COIN_INTORG;
00520                 } else if ( !strncmp ( next, "'INTEND'", 8 ) ) {
00521                   mpsType_ = COIN_INTEND;
00522                 } else if ( !strncmp ( next, "'SOSORG'", 8 ) ) {
00523                   if ( mpsType_ == COIN_BLANK_COLUMN )
00524                     mpsType_ = COIN_S1_COLUMN;
00525                 } else if ( !strncmp ( next, "'SOSEND'", 8 ) ) {
00526                   mpsType_ = COIN_SOSEND;
00527                 } else {
00528                   mpsType_ = COIN_UNKNOWN_MPS_TYPE;
00529                 }
00530                 position_ = eol_;
00531                 return section_;
00532               }
00533               if ( next == eol_ ) {
00534                 // error unless bounds
00535                 position_ = eol_;
00536                 if ( section_ != COIN_BOUNDS_SECTION ) {
00537                   value_ = -1.0e100;
00538                   mpsType_ = COIN_UNKNOWN_MPS_TYPE;
00539                 } else {
00540                   value_ = 0.0;
00541                 }
00542               } else {
00543                 nextBlank = nextBlankOr ( next );
00544                 if ( nextBlank ) {
00545                   save = *nextBlank;
00546                   *nextBlank = '\0';
00547                 }
00548                 char * after;
00549                 value_ = osi_strtod(next,&after);
00550                 // see if error
00551                 assert(after>next);
00552                 if ( nextBlank ) {
00553                   *nextBlank = save;
00554                   position_ = nextBlank;
00555                 } else {
00556                   position_ = eol_;
00557                 }
00558               }
00559             }
00560           }
00561         } else {
00562           //blank name in RHS or RANGES
00563           strcpy ( columnName_, "        " );
00564           char save = '?';
00565 
00566           if ( !freeFormat_ && eightChar_ && next == card_ + 14 ) {
00567             if ( eol_ - next >= 8 ) {
00568               if ( *( next + 8 ) != ' ' && *( next + 8 ) != '\0' ) {
00569                 eightChar_ = false;
00570               } else {
00571                 nextBlank = next + 8;
00572               }
00573               save = *nextBlank;
00574               *nextBlank = '\0';
00575             } else {
00576               nextBlank = NULL;
00577             }
00578           } else {
00579             if ( nextBlank ) {
00580               save = *nextBlank;
00581               *nextBlank = '\0';
00582             }
00583           }
00584           strcpyAndCompress ( rowName_, next );
00585           if ( nextBlank ) {
00586             *nextBlank = save;
00587             // on to next
00588             next = nextBlank;
00589           } else {
00590             next = eol_;
00591           }
00592           while ( next != eol_ ) {
00593             if ( *next == ' ' || *next == '\t' ) {
00594               next++;
00595             } else {
00596               break;
00597             }
00598           }
00599           if ( next == eol_ ) {
00600             // error 
00601             position_ = eol_;
00602             value_ = -1.0e100;
00603             mpsType_ = COIN_UNKNOWN_MPS_TYPE;
00604           } else {
00605             nextBlank = nextBlankOr ( next );
00606             value_ = -1.0e100;
00607             if ( nextBlank ) {
00608               save = *nextBlank;
00609               *nextBlank = '\0';
00610             }
00611             char * after;
00612             value_ = osi_strtod(next,&after);
00613             // see if error
00614             assert(after>next);
00615             if ( nextBlank ) {
00616               *nextBlank = save;
00617               position_ = nextBlank;
00618             } else {
00619               position_ = eol_;
00620             }
00621           }
00622         }
00623       }
00624       return section_;
00625     } else if ( card_[0] != '*' ) {
00626       // not a comment
00627       int i;
00628 
00629       handler_->message(COIN_MPS_LINE,messages_)<<cardNumber_
00630                                                <<card_<<CoinMessageEol;
00631       for ( i = COIN_ROW_SECTION; i < COIN_UNKNOWN_SECTION; i++ ) {
00632         if ( !strncmp ( card_, section[i], strlen ( section[i] ) ) ) {
00633           break;
00634         }
00635       }
00636       position_ = card_;
00637       eol_ = card_;
00638       section_ = ( COINSectionType ) i;
00639       return section_;
00640     } else {
00641       // comment
00642     }
00643   }
00644   // we only get here for second field (we could even allow more???)
00645   {
00646     char save = '?';
00647     char *nextBlank = nextBlankOr ( next );
00648 
00649     if ( !freeFormat_ && eightChar_ && next == card_ + 39 ) {
00650       if ( eol_ - next >= 8 ) {
00651         if ( *( next + 8 ) != ' ' && *( next + 8 ) != '\0' ) {
00652           eightChar_ = false;
00653         } else {
00654           nextBlank = next + 8;
00655         }
00656         save = *nextBlank;
00657         *nextBlank = '\0';
00658       } else {
00659         nextBlank = NULL;
00660       }
00661     } else {
00662       if ( nextBlank ) {
00663         save = *nextBlank;
00664         *nextBlank = '\0';
00665       }
00666     }
00667     strcpyAndCompress ( rowName_, next );
00668     // on to next
00669     if ( nextBlank ) {
00670       *nextBlank = save;
00671       next = nextBlank;
00672     } else {
00673       next = eol_;
00674     }
00675     while ( next != eol_ ) {
00676       if ( *next == ' ' || *next == '\t' ) {
00677         next++;
00678       } else {
00679         break;
00680       }
00681     }
00682     if ( next == eol_ ) {
00683       // error
00684       position_ = eol_;
00685       mpsType_ = COIN_UNKNOWN_MPS_TYPE;
00686     } else {
00687       nextBlank = nextBlankOr ( next );
00688     }
00689     if ( nextBlank ) {
00690       save = *nextBlank;
00691       *nextBlank = '\0';
00692     }
00693     //value_ = -1.0e100;
00694     char * after;
00695     value_ = osi_strtod(next,&after);
00696     // see if error
00697     assert(after>next);
00698     if ( nextBlank ) {
00699       *nextBlank = save;
00700       position_ = nextBlank;
00701     } else {
00702       position_ = eol_;
00703     }
00704   }
00705   return section_;
00706 }
00707 
00708 //#############################################################################
00709 
00710 static int
00711 hash ( const char *name, int maxsiz, int length )
00712 {
00713   static int mmult[] = {
00714     262139, 259459, 256889, 254291, 251701, 249133, 246709, 244247,
00715     241667, 239179, 236609, 233983, 231289, 228859, 226357, 223829,
00716     221281, 218849, 216319, 213721, 211093, 208673, 206263, 203773,
00717     201233, 198637, 196159, 193603, 191161, 188701, 186149, 183761,
00718     181303, 178873, 176389, 173897, 171469, 169049, 166471, 163871,
00719     161387, 158941, 156437, 153949, 151531, 149159, 146749, 144299,
00720     141709, 139369, 136889, 134591, 132169, 129641, 127343, 124853,
00721     122477, 120163, 117757, 115361, 112979, 110567, 108179, 105727,
00722     103387, 101021, 98639, 96179, 93911, 91583, 89317, 86939, 84521,
00723     82183, 79939, 77587, 75307, 72959, 70793, 68447, 66103
00724   };
00725   int n = 0;
00726   int j;
00727 
00728   for ( j = 0; j < length; ++j ) {
00729     int iname = name[j];
00730 
00731     n += mmult[j] * iname;
00732   }
00733   return ( abs ( n ) % maxsiz );        /* integer abs */
00734 }
00735 
00736 //  startHash.  Creates hash list for names
00737 void
00738 CoinMpsIO::startHash ( char **names, const COINColumnIndex number , int section )
00739 {
00740   names_[section] = names;
00741   numberHash_[section] = number;
00742   startHash(section);
00743 }
00744 void
00745 CoinMpsIO::startHash ( int section ) const
00746 {
00747   char ** names = names_[section];
00748   COINColumnIndex number = numberHash_[section];
00749   COINColumnIndex i;
00750   COINColumnIndex maxhash = 4 * number;
00751   COINColumnIndex ipos, iput;
00752 
00753   //hash_=(CoinHashLink *) malloc(maxhash*sizeof(CoinHashLink));
00754   hash_[section] = new CoinHashLink[maxhash];
00755   
00756   CoinHashLink * hashThis = hash_[section];
00757 
00758   for ( i = 0; i < maxhash; i++ ) {
00759     hashThis[i].index = -1;
00760     hashThis[i].next = -1;
00761   }
00762 
00763   /*
00764    * Initialize the hash table.  Only the index of the first name that
00765    * hashes to a value is entered in the table; subsequent names that
00766    * collide with it are not entered.
00767    */
00768   for ( i = 0; i < number; ++i ) {
00769     char *thisName = names[i];
00770     int length = strlen ( thisName );
00771 
00772     ipos = hash ( thisName, maxhash, length );
00773     if ( hashThis[ipos].index == -1 ) {
00774       hashThis[ipos].index = i;
00775     }
00776   }
00777 
00778   /*
00779    * Now take care of the names that collided in the preceding loop,
00780    * by finding some other entry in the table for them.
00781    * Since there are as many entries in the table as there are names,
00782    * there must be room for them.
00783    */
00784   iput = -1;
00785   for ( i = 0; i < number; ++i ) {
00786     char *thisName = names[i];
00787     int length = strlen ( thisName );
00788 
00789     ipos = hash ( thisName, maxhash, length );
00790 
00791     while ( 1 ) {
00792       COINColumnIndex j1 = hashThis[ipos].index;
00793 
00794       if ( j1 == i )
00795         break;
00796       else {
00797         char *thisName2 = names[j1];
00798 
00799         if ( strcmp ( thisName, thisName2 ) == 0 ) {
00800           printf ( "** duplicate name %s\n", names[i] );
00801           break;
00802         } else {
00803           COINColumnIndex k = hashThis[ipos].next;
00804 
00805           if ( k == -1 ) {
00806             while ( 1 ) {
00807               ++iput;
00808               if ( iput > number ) {
00809                 printf ( "** too many names\n" );
00810                 break;
00811               }
00812               if ( hashThis[iput].index == -1 ) {
00813                 break;
00814               }
00815             }
00816             hashThis[ipos].next = iput;
00817             hashThis[iput].index = i;
00818             break;
00819           } else {
00820             ipos = k;
00821             /* nothing worked - try it again */
00822           }
00823         }
00824       }
00825     }
00826   }
00827 }
00828 
00829 //  stopHash.  Deletes hash storage
00830 void
00831 CoinMpsIO::stopHash ( int section )
00832 {
00833   delete [] hash_[section];
00834   hash_[section] = NULL;
00835 }
00836 
00837 //  findHash.  -1 not found
00838 COINColumnIndex
00839 CoinMpsIO::findHash ( const char *name , int section ) const
00840 {
00841   COINColumnIndex found = -1;
00842 
00843   char ** names = names_[section];
00844   CoinHashLink * hashThis = hash_[section];
00845   COINColumnIndex maxhash = 4 * numberHash_[section];
00846   COINColumnIndex ipos;
00847 
00848   /* default if we don't find anything */
00849   if ( !maxhash )
00850     return -1;
00851   int length = strlen ( name );
00852 
00853   ipos = hash ( name, maxhash, length );
00854   while ( 1 ) {
00855     COINColumnIndex j1 = hashThis[ipos].index;
00856 
00857     if ( j1 >= 0 ) {
00858       char *thisName2 = names[j1];
00859 
00860       if ( strcmp ( name, thisName2 ) != 0 ) {
00861         COINColumnIndex k = hashThis[ipos].next;
00862 
00863         if ( k != -1 )
00864           ipos = k;
00865         else
00866           break;
00867       } else {
00868         found = j1;
00869         break;
00870       }
00871     } else {
00872       found = -1;
00873       break;
00874     }
00875   }
00876   return found;
00877 }
00878 
00879 //------------------------------------------------------------------
00880 // Get value for infinity
00881 //------------------------------------------------------------------
00882 double CoinMpsIO::getInfinity() const
00883 {
00884   return infinity_;
00885 }
00886 //------------------------------------------------------------------
00887 // Set value for infinity
00888 //------------------------------------------------------------------
00889 void CoinMpsIO::setInfinity(double value) 
00890 {
00891   if ( value >= 1.020 ) {
00892     infinity_ = value;
00893   } else {
00894     handler_->message(COIN_MPS_ILLEGAL,messages_)<<"infinity"
00895                                                 <<value
00896                                                 <<CoinMessageEol;
00897   }
00898 
00899 }
00900 // Set file name
00901 void CoinMpsIO::setFileName(const char * name)
00902 {
00903   free(fileName_);
00904   fileName_=strdup(name);
00905 }
00906 // Get file name
00907 const char * CoinMpsIO::getFileName() const
00908 {
00909   return fileName_;
00910 }
00911 // Test if current file exists and readable
00912 const bool CoinMpsIO::fileReadable() const
00913 {
00914   // I am opening it to make sure not odd
00915   FILE *fp;
00916   if (strcmp(fileName_,"stdin")) {
00917     fp = fopen ( fileName_, "r" );
00918   } else {
00919     fp = stdin;
00920   }
00921   if (!fp) {
00922     return false;
00923   } else {
00924     fclose(fp);
00925     return true;
00926   }
00927 }
00928 // Deal with filename - +1 if new, 0 if same as before, -1 if error
00929 int
00930 CoinMpsIO::dealWithFileName(const char * filename,  const char * extension,
00931                        FILE * & fp, gzFile  & gzfp)
00932 {
00933   fp=NULL;
00934   int goodFile=0;
00935   gzfp=NULL;
00936   if (!fileName_||(filename!=NULL&&strcmp(filename,fileName_))) {
00937     if (filename==NULL) {
00938       handler_->message(COIN_MPS_FILE,messages_)<<"NULL"
00939                                                 <<CoinMessageEol;
00940       return -1;
00941     }
00942     goodFile=-1;
00943     // looks new name
00944     char newName[400];
00945     if (strcmp(filename,"stdin")&&strcmp(filename,"-")) {
00946       if (extension&&strlen(extension)) {
00947         // There was an extension - but see if user gave .xxx
00948         int i = strlen(filename)-1;
00949         strcpy(newName,filename);
00950         bool foundDot=false; 
00951         for (;i>=0;i--) {
00952           char character = filename[i];
00953           if (character=='/'||character=='\\') {
00954             break;
00955           } else if (character=='.') {
00956             foundDot=true;
00957             break;
00958           }
00959         }
00960         if (!foundDot) {
00961           strcat(newName,".");
00962           strcat(newName,extension);
00963         }
00964       } else {
00965         // no extension
00966         strcpy(newName,filename);
00967       }
00968     } else {
00969       strcpy(newName,"stdin");    
00970     }
00971     // See if new name
00972     if (fileName_&&!strcmp(newName,fileName_)) {
00973       // old name
00974       return 0;
00975     } else {
00976       // new file
00977       free(fileName_);
00978       fileName_=strdup(newName);    
00979       if (strcmp(fileName_,"stdin")) {
00980 #ifdef COIN_USE_ZLIB
00981         int length=strlen(fileName_);
00982         if (!strcmp(fileName_+length-3,".gz")) {
00983           gzfp = gzopen(fileName_,"rb");
00984           fp = NULL;
00985           goodFile = (gzfp!=NULL);
00986         } else {
00987 #endif
00988           fp = fopen ( fileName_, "r" );
00989           if (fp!=NULL)
00990             goodFile=1;
00991 #ifdef COIN_USE_ZLIB
00992           if (goodFile<0) {
00993             std::string fname(fileName_);
00994             fname += ".gz";
00995             gzfp = gzopen(fname.c_str(),"rb");
00996             printf("%s\n", fname.c_str());
00997             if (gzfp!=NULL)
00998               goodFile=1;
00999           }
01000         }
01001 #endif
01002       } else {
01003         fp = stdin;
01004         goodFile = 1;
01005       }
01006     }
01007   } else {
01008     // same as before
01009     // reset section ?
01010     goodFile=0;
01011   }
01012   if (goodFile<0) 
01013     handler_->message(COIN_MPS_FILE,messages_)<<fileName_
01014                                               <<CoinMessageEol;
01015   return goodFile;
01016 }
01017 /* objective offset - this is RHS entry for objective row */
01018 double CoinMpsIO::objectiveOffset() const
01019 {
01020   return objectiveOffset_;
01021 }
01022 #define MAX_INTEGER 1000000
01023 // Sets default upper bound for integer variables
01024 void CoinMpsIO::setDefaultBound(int value)
01025 {
01026   if ( value >= 1 && value <=MAX_INTEGER ) {
01027     defaultBound_ = value;
01028   } else {
01029     handler_->message(COIN_MPS_ILLEGAL,messages_)<<"default integer bound"
01030                                                 <<value
01031                                                 <<CoinMessageEol;
01032   }
01033 }
01034 // gets default upper bound for integer variables
01035 int CoinMpsIO::getDefaultBound() const
01036 {
01037   return defaultBound_;
01038 }
01039 //------------------------------------------------------------------
01040 // Read mps files
01041 //------------------------------------------------------------------
01042 int CoinMpsIO::readMps(const char * filename,  const char * extension)
01043 {
01044   // Deal with filename - +1 if new, 0 if same as before, -1 if error
01045   FILE *fp=NULL;
01046   gzFile gzfp=NULL;
01047   int returnCode = dealWithFileName(filename,extension,fp,gzfp);
01048   if (returnCode<0) {
01049     return -1;
01050   } else if (returnCode>0) {
01051     delete cardReader_;
01052     cardReader_ = new CoinMpsCardReader ( fp , gzfp, this);
01053   }
01054   return readMps();
01055 }
01056 int CoinMpsIO::readMps()
01057 {
01058   bool ifmps;
01059 
01060   cardReader_->readToNextSection();
01061 
01062   if ( cardReader_->whichSection (  ) == COIN_NAME_SECTION ) {
01063     ifmps = true;
01064     // save name of section
01065     free(problemName_);
01066     problemName_=strdup(cardReader_->columnName());
01067   } else if ( cardReader_->whichSection (  ) == COIN_UNKNOWN_SECTION ) {
01068     handler_->message(COIN_MPS_BADFILE1,messages_)<<cardReader_->card()
01069                                                   <<1
01070                                                  <<fileName_
01071                                                  <<CoinMessageEol;
01072 #ifdef COIN_USE_ZLIB
01073     if (!cardReader_->filePointer()) 
01074       handler_->message(COIN_MPS_BADFILE2,messages_)<<CoinMessageEol;
01075 
01076 #endif
01077     return -2;
01078   } else if ( cardReader_->whichSection (  ) != COIN_EOF_SECTION ) {
01079     // save name of section
01080     free(problemName_);
01081     problemName_=strdup(cardReader_->card());
01082     ifmps = false;
01083   } else {
01084     handler_->message(COIN_MPS_EOF,messages_)<<fileName_
01085                                             <<CoinMessageEol;
01086     return -3;
01087   }
01088   CoinBigIndex *start;
01089   COINRowIndex *row;
01090   double *element;
01091   objectiveOffset_ = 0.0;
01092 
01093   int numberErrors = 0;
01094   int i;
01095 
01096   if ( ifmps ) {
01097     // mps file - always read in free format
01098     bool gotNrow = false;
01099 
01100     //get ROWS
01101     cardReader_->nextField (  ) ;
01102     // Fudge for what ever code has OBJSENSE
01103     if (!strncmp(cardReader_->card(),"OBJSENSE",8)) {
01104       cardReader_->nextField();
01105       int i;
01106       const char * thisCard = cardReader_->card();
01107       int direction = 0;
01108       for (i=0;i<20;i++) {
01109         if (thisCard[i]!=' ') {
01110           if (!strncmp(thisCard+i,"MAX",3))
01111             direction=-1;
01112           else if (!strncmp(thisCard+i,"MIN",3))
01113             direction=1;
01114           break;
01115         }
01116       }
01117       if (!direction)
01118         printf("No MAX/MIN found after OBJSENSE\n");
01119       else 
01120         printf("%s found after OBJSENSE - Coin ignores\n",
01121                (direction>0 ? "MIN" : "MAX"));
01122       cardReader_->nextField();
01123     }
01124     if ( cardReader_->whichSection (  ) != COIN_ROW_SECTION ) {
01125       handler_->message(COIN_MPS_BADIMAGE,messages_)<<cardReader_->cardNumber()
01126                                                     <<cardReader_->card()
01127                                                     <<CoinMessageEol;
01128       handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01129       return numberErrors;
01130     }
01131     //use malloc etc as I don't know how to do realloc in C++
01132     numberRows_ = 0;
01133     numberColumns_ = 0;
01134     numberElements_ = 0;
01135     COINRowIndex maxRows = 1000;
01136     COINMpsType *rowType =
01137 
01138       ( COINMpsType * ) malloc ( maxRows * sizeof ( COINMpsType ) );
01139     char **rowName = ( char ** ) malloc ( maxRows * sizeof ( char * ) );
01140 
01141     // for discarded free rows
01142     COINRowIndex maxFreeRows = 100;
01143     COINRowIndex numberOtherFreeRows = 0;
01144     char **freeRowName =
01145 
01146       ( char ** ) malloc ( maxFreeRows * sizeof ( char * ) );
01147     while ( cardReader_->nextField (  ) == COIN_ROW_SECTION ) {
01148       switch ( cardReader_->mpsType (  ) ) {
01149       case COIN_N_ROW:
01150         if ( !gotNrow ) {
01151           gotNrow = true;
01152           // save name of section
01153           free(objectiveName_);
01154           objectiveName_=strdup(cardReader_->columnName());
01155         } else {
01156           // add to discard list
01157           if ( numberOtherFreeRows == maxFreeRows ) {
01158             maxFreeRows = ( 3 * maxFreeRows ) / 2 + 100;
01159             freeRowName =
01160               ( char ** ) realloc ( freeRowName,
01161 
01162                                     maxFreeRows * sizeof ( char * ) );
01163           }
01164           freeRowName[numberOtherFreeRows] =
01165             strdup ( cardReader_->columnName (  ) );
01166           numberOtherFreeRows++;
01167         }
01168         break;
01169       case COIN_E_ROW:
01170       case COIN_L_ROW:
01171       case COIN_G_ROW:
01172         if ( numberRows_ == maxRows ) {
01173           maxRows = ( 3 * maxRows ) / 2 + 1000;
01174           rowType =
01175             ( COINMpsType * ) realloc ( rowType,
01176                                        maxRows * sizeof ( COINMpsType ) );
01177           rowName =
01178 
01179             ( char ** ) realloc ( rowName, maxRows * sizeof ( char * ) );
01180         }
01181         rowType[numberRows_] = cardReader_->mpsType (  );
01182         rowName[numberRows_] = strdup ( cardReader_->columnName (  ) );
01183         numberRows_++;
01184         break;
01185       default:
01186         numberErrors++;
01187         if ( numberErrors < 100 ) {
01188           handler_->message(COIN_MPS_BADIMAGE,messages_)<<cardReader_->cardNumber()
01189                                                        <<cardReader_->card()
01190                                                        <<CoinMessageEol;
01191         } else if (numberErrors > 100000) {
01192           handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01193           return numberErrors;
01194         }
01195       }
01196     }
01197     if ( cardReader_->whichSection (  ) != COIN_COLUMN_SECTION ) {
01198       handler_->message(COIN_MPS_BADIMAGE,messages_)<<cardReader_->cardNumber()
01199                                                     <<cardReader_->card()
01200                                                     <<CoinMessageEol;
01201       handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01202       return numberErrors;
01203     }
01204     assert ( gotNrow );
01205     rowType =
01206       ( COINMpsType * ) realloc ( rowType,
01207                                  numberRows_ * sizeof ( COINMpsType ) );
01208     // put objective and other free rows at end
01209     rowName =
01210       ( char ** ) realloc ( rowName,
01211                             ( numberRows_ + 1 +
01212 
01213                               numberOtherFreeRows ) * sizeof ( char * ) );
01214     rowName[numberRows_] = strdup(objectiveName_);
01215     memcpy ( rowName + numberRows_ + 1, freeRowName,
01216              numberOtherFreeRows * sizeof ( char * ) );
01217     // now we can get rid of this array
01218     free(freeRowName);
01219 
01220     startHash ( rowName, numberRows_ + 1 + numberOtherFreeRows , 0 );
01221     COINColumnIndex maxColumns = 1000 + numberRows_ / 5;
01222     CoinBigIndex maxElements = 5000 + numberRows_ / 2;
01223     COINMpsType *columnType = ( COINMpsType * )
01224       malloc ( maxColumns * sizeof ( COINMpsType ) );
01225     char **columnName = ( char ** ) malloc ( maxColumns * sizeof ( char * ) );
01226 
01227     objective_ = ( double * ) malloc ( maxColumns * sizeof ( double ) );
01228     start = ( CoinBigIndex * )
01229       malloc ( ( maxColumns + 1 ) * sizeof ( CoinBigIndex ) );
01230     row = ( COINRowIndex * )
01231       malloc ( maxElements * sizeof ( COINRowIndex ) );
01232     element =
01233       ( double * ) malloc ( maxElements * sizeof ( double ) );
01234     // for duplicates
01235     CoinBigIndex *rowUsed = new CoinBigIndex[numberRows_];
01236 
01237     for (i=0;i<numberRows_;i++) {
01238       rowUsed[i]=-1;
01239     }
01240     bool objUsed = false;
01241 
01242     numberElements_ = 0;
01243     char lastColumn[200];
01244 
01245     memset ( lastColumn, '\0', 200 );
01246     COINColumnIndex column = -1;
01247     bool inIntegerSet = false;
01248     COINColumnIndex numberIntegers = 0;
01249     const double tinyElement = 1.0e-14;
01250 
01251     while ( cardReader_->nextField (  ) == COIN_COLUMN_SECTION ) {
01252       switch ( cardReader_->mpsType (  ) ) {
01253       case COIN_BLANK_COLUMN:
01254         if ( strcmp ( lastColumn, cardReader_->columnName (  ) ) ) {
01255           // new column
01256 
01257           // reset old column and take out tiny
01258           if ( numberColumns_ ) {
01259             objUsed = false;
01260             CoinBigIndex i;
01261             CoinBigIndex k = start[column];
01262 
01263             for ( i = k; i < numberElements_; i++ ) {
01264               COINRowIndex irow = row[i];
01265 #if 0
01266               if ( fabs ( element[i] ) > tinyElement ) {
01267                 element[k++] = element[i];
01268               }
01269 #endif
01270               rowUsed[irow] = -1;
01271             }
01272             //numberElements_ = k;
01273           }
01274           column = numberColumns_;
01275           if ( numberColumns_ == maxColumns ) {
01276             maxColumns = ( 3 * maxColumns ) / 2 + 1000;
01277             columnType = ( COINMpsType * )
01278               realloc ( columnType, maxColumns * sizeof ( COINMpsType ) );
01279             columnName = ( char ** )
01280               realloc ( columnName, maxColumns * sizeof ( char * ) );
01281 
01282             objective_ = ( double * )
01283               realloc ( objective_, maxColumns * sizeof ( double ) );
01284             start = ( CoinBigIndex * )
01285               realloc ( start,
01286                         ( maxColumns + 1 ) * sizeof ( CoinBigIndex ) );
01287           }
01288           if ( !inIntegerSet ) {
01289             columnType[column] = COIN_UNSET_BOUND;
01290           } else {
01291             columnType[column] = COIN_INTORG;
01292             numberIntegers++;
01293           }
01294           columnName[column] = strdup ( cardReader_->columnName (  ) );
01295           strcpy ( lastColumn, cardReader_->columnName (  ) );
01296           objective_[column] = 0.0;
01297           start[column] = numberElements_;
01298           numberColumns_++;
01299         }
01300         if ( fabs ( cardReader_->value (  ) ) > tinyElement ) {
01301           if ( numberElements_ == maxElements ) {
01302             maxElements = ( 3 * maxElements ) / 2 + 1000;
01303             row = ( COINRowIndex * )
01304               realloc ( row, maxElements * sizeof ( COINRowIndex ) );
01305             element = ( double * )
01306               realloc ( element, maxElements * sizeof ( double ) );
01307           }
01308           // get row number
01309           COINRowIndex irow = findHash ( cardReader_->rowName (  ) , 0 );
01310 
01311           if ( irow >= 0 ) {
01312             double value = cardReader_->value (  );
01313 
01314             // check for duplicates
01315             if ( irow == numberRows_ ) {
01316               // objective
01317               if ( objUsed ) {
01318                 numberErrors++;
01319                 if ( numberErrors < 100 ) {
01320                   handler_->message(COIN_MPS_DUPOBJ,messages_)
01321                     <<cardReader_->cardNumber()<<cardReader_->card()
01322                     <<CoinMessageEol;
01323                 } else if (numberErrors > 100000) {
01324                   handler_->message(COIN_MPS_RETURNING,messages_)
01325                     <<CoinMessageEol;
01326                   return numberErrors;
01327                 }
01328               } else {
01329                 objUsed = true;
01330               }
01331               value += objective_[column];
01332               if ( fabs ( value ) <= tinyElement )
01333                 value = 0.0;
01334               objective_[column] = value;
01335             } else if ( irow < numberRows_ ) {
01336               // other free rows will just be discarded so won't get here
01337               if ( rowUsed[irow] >= 0 ) {
01338                 element[rowUsed[irow]] += value;
01339                 numberErrors++;
01340                 if ( numberErrors < 100 ) {
01341                   handler_->message(COIN_MPS_DUPROW,messages_)
01342                     <<cardReader_->rowName()<<cardReader_->cardNumber()
01343                     <<cardReader_->card()
01344                     <<CoinMessageEol;
01345                 } else if (numberErrors > 100000) {
01346                   handler_->message(COIN_MPS_RETURNING,messages_)
01347                     <<CoinMessageEol;
01348                   return numberErrors;
01349                 }
01350               } else {
01351                 row[numberElements_] = irow;
01352                 element[numberElements_] = value;
01353                 rowUsed[irow] = numberElements_;
01354                 numberElements_++;
01355               }
01356             }
01357           } else {
01358             numberErrors++;
01359             if ( numberErrors < 100 ) {
01360                   handler_->message(COIN_MPS_NOMATCHROW,messages_)
01361                     <<cardReader_->rowName()<<cardReader_->cardNumber()<<cardReader_->card()
01362                     <<CoinMessageEol;
01363             } else if (numberErrors > 100000) {
01364               handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01365               return numberErrors;
01366             }
01367           }
01368         }
01369         break;
01370       case COIN_INTORG:
01371         inIntegerSet = true;
01372         break;
01373       case COIN_INTEND:
01374         inIntegerSet = false;
01375         break;
01376       case COIN_S1_COLUMN:
01377       case COIN_S2_COLUMN:
01378       case COIN_S3_COLUMN:
01379       case COIN_SOSEND:
01380         std::cout << "** code sos etc later" << std::endl;
01381         abort (  );
01382         break;
01383       default:
01384         numberErrors++;
01385         if ( numberErrors < 100 ) {
01386           handler_->message(COIN_MPS_BADIMAGE,messages_)<<cardReader_->cardNumber()
01387                                                        <<cardReader_->card()
01388                                                        <<CoinMessageEol;
01389         } else if (numberErrors > 100000) {
01390           handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01391           return numberErrors;
01392         }
01393       }
01394     }
01395     start[numberColumns_] = numberElements_;
01396     delete[]rowUsed;
01397     if ( cardReader_->whichSection (  ) != COIN_RHS_SECTION ) {
01398       handler_->message(COIN_MPS_BADIMAGE,messages_)<<cardReader_->cardNumber()
01399                                                     <<cardReader_->card()
01400                                                     <<CoinMessageEol;
01401       handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01402       return numberErrors;
01403     }
01404     columnType =
01405       ( COINMpsType * ) realloc ( columnType,
01406                                  numberColumns_ * sizeof ( COINMpsType ) );
01407     columnName =
01408 
01409       ( char ** ) realloc ( columnName, numberColumns_ * sizeof ( char * ) );
01410     objective_ = ( double * )
01411       realloc ( objective_, numberColumns_ * sizeof ( double ) );
01412     start = ( CoinBigIndex * )
01413       realloc ( start, ( numberColumns_ + 1 ) * sizeof ( CoinBigIndex ) );
01414     row = ( COINRowIndex * )
01415       realloc ( row, numberElements_ * sizeof ( COINRowIndex ) );
01416     element = ( double * )
01417       realloc ( element, numberElements_ * sizeof ( double ) );
01418 
01419     rowlower_ = ( double * ) malloc ( numberRows_ * sizeof ( double ) );
01420     rowupper_ = ( double * ) malloc ( numberRows_ * sizeof ( double ) );
01421     for (i=0;i<numberRows_;i++) {
01422       rowlower_[i]=-infinity_;
01423       rowupper_[i]=infinity_;
01424     }
01425     objUsed = false;
01426     memset ( lastColumn, '\0', 200 );
01427     bool gotRhs = false;
01428 
01429     // need coding for blank rhs
01430     while ( cardReader_->nextField (  ) == COIN_RHS_SECTION ) {
01431       COINRowIndex irow;
01432 
01433       switch ( cardReader_->mpsType (  ) ) {
01434       case COIN_BLANK_COLUMN:
01435         if ( strcmp ( lastColumn, cardReader_->columnName (  ) ) ) {
01436 
01437           // skip rest if got a rhs
01438           if ( gotRhs ) {
01439             while ( cardReader_->nextField (  ) == COIN_RHS_SECTION ) {
01440             }
01441             break;
01442           } else {
01443             gotRhs = true;
01444             strcpy ( lastColumn, cardReader_->columnName (  ) );
01445             // save name of section
01446             free(rhsName_);
01447             rhsName_=strdup(cardReader_->columnName());
01448           }
01449         }
01450         // get row number
01451         irow = findHash ( cardReader_->rowName (  ) , 0 );
01452         if ( irow >= 0 ) {
01453           double value = cardReader_->value (  );
01454 
01455           // check for duplicates
01456           if ( irow == numberRows_ ) {
01457             // objective
01458             if ( objUsed ) {
01459               numberErrors++;
01460               if ( numberErrors < 100 ) {
01461                   handler_->message(COIN_MPS_DUPOBJ,messages_)
01462                     <<cardReader_->cardNumber()<<cardReader_->card()
01463                     <<CoinMessageEol;
01464               } else if (numberErrors > 100000) {
01465                 handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01466                 return numberErrors;
01467               }
01468             } else {
01469               objUsed = true;
01470             }
01471             objectiveOffset_ += value;
01472           } else if ( irow < numberRows_ ) {
01473             if ( rowlower_[irow] != -infinity_ ) {
01474               numberErrors++;
01475               if ( numberErrors < 100 ) {
01476                 handler_->message(COIN_MPS_DUPROW,messages_)
01477                   <<cardReader_->rowName()<<cardReader_->cardNumber()<<cardReader_->card()
01478                   <<CoinMessageEol;
01479               } else if (numberErrors > 100000) {
01480                 handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01481                 return numberErrors;
01482               }
01483             } else {
01484               rowlower_[irow] = value;
01485             }
01486           }
01487         } else {
01488           numberErrors++;
01489           if ( numberErrors < 100 ) {
01490             handler_->message(COIN_MPS_NOMATCHROW,messages_)
01491               <<cardReader_->rowName()<<cardReader_->cardNumber()<<cardReader_->card()
01492               <<CoinMessageEol;
01493           } else if (numberErrors > 100000) {
01494             handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01495             return numberErrors;
01496           }
01497         }
01498         break;
01499       default:
01500         numberErrors++;
01501         if ( numberErrors < 100 ) {
01502           handler_->message(COIN_MPS_BADIMAGE,messages_)<<cardReader_->cardNumber()
01503                                                        <<cardReader_->card()
01504                                                        <<CoinMessageEol;
01505         } else if (numberErrors > 100000) {
01506           handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01507           return numberErrors;
01508         }
01509       }
01510     }
01511     if ( cardReader_->whichSection (  ) == COIN_RANGES_SECTION ) {
01512       memset ( lastColumn, '\0', 200 );
01513       bool gotRange = false;
01514       COINRowIndex irow;
01515 
01516       // need coding for blank range
01517       while ( cardReader_->nextField (  ) == COIN_RANGES_SECTION ) {
01518         switch ( cardReader_->mpsType (  ) ) {
01519         case COIN_BLANK_COLUMN:
01520           if ( strcmp ( lastColumn, cardReader_->columnName (  ) ) ) {
01521 
01522             // skip rest if got a range
01523             if ( gotRange ) {
01524               while ( cardReader_->nextField (  ) == COIN_RANGES_SECTION ) {
01525               }
01526               break;
01527             } else {
01528               gotRange = true;
01529               strcpy ( lastColumn, cardReader_->columnName (  ) );
01530               // save name of section
01531               free(rangeName_);
01532               rangeName_=strdup(cardReader_->columnName());
01533             }
01534           }
01535           // get row number
01536           irow = findHash ( cardReader_->rowName (  ) , 0 );
01537           if ( irow >= 0 ) {
01538             double value = cardReader_->value (  );
01539 
01540             // check for duplicates
01541             if ( irow == numberRows_ ) {
01542               // objective
01543               numberErrors++;
01544               if ( numberErrors < 100 ) {
01545                   handler_->message(COIN_MPS_DUPOBJ,messages_)
01546                     <<cardReader_->cardNumber()<<cardReader_->card()
01547                     <<CoinMessageEol;
01548               } else if (numberErrors > 100000) {
01549                 handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01550                 return numberErrors;
01551               }
01552             } else {
01553               if ( rowupper_[irow] != infinity_ ) {
01554                 numberErrors++;
01555                 if ( numberErrors < 100 ) {
01556                   handler_->message(COIN_MPS_DUPROW,messages_)
01557                     <<cardReader_->rowName()<<cardReader_->cardNumber()<<cardReader_->card()
01558                     <<CoinMessageEol;
01559                 } else if (numberErrors > 100000) {
01560                   handler_->message(COIN_MPS_RETURNING,messages_)
01561                     <<CoinMessageEol;
01562                   return numberErrors;
01563                 }
01564               } else {
01565                 rowupper_[irow] = value;
01566               }
01567             }
01568           } else {
01569             numberErrors++;
01570             if ( numberErrors < 100 ) {
01571               handler_->message(COIN_MPS_NOMATCHROW,messages_)
01572                 <<cardReader_->rowName()<<cardReader_->cardNumber()<<cardReader_->card()
01573                 <<CoinMessageEol;
01574             } else if (numberErrors > 100000) {
01575               handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01576               return numberErrors;
01577             }
01578           }
01579           break;
01580         default:
01581           numberErrors++;
01582           if ( numberErrors < 100 ) {
01583           handler_->message(COIN_MPS_BADIMAGE,messages_)<<cardReader_->cardNumber()
01584                                                        <<cardReader_->card()
01585                                                        <<CoinMessageEol;
01586           } else if (numberErrors > 100000) {
01587             handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01588             return numberErrors;
01589           }
01590         }
01591       }
01592     }
01593     stopHash ( 0 );
01594     // massage ranges
01595     {
01596       COINRowIndex irow;
01597 
01598       for ( irow = 0; irow < numberRows_; irow++ ) {
01599         double lo = rowlower_[irow];
01600         double up = rowupper_[irow];
01601         double up2 = rowupper_[irow];   //range
01602 
01603         switch ( rowType[irow] ) {
01604         case COIN_E_ROW:
01605           if ( lo == -infinity_ )
01606             lo = 0.0;
01607           if ( up == infinity_ ) {
01608             up = lo;
01609           } else if ( up > 0.0 ) {
01610             up += lo;
01611           } else {
01612             up = lo;
01613             lo += up2;
01614           }
01615           break;
01616         case COIN_L_ROW:
01617           if ( lo == -infinity_ ) {
01618             up = 0.0;
01619           } else {
01620             up = lo;
01621             lo = -infinity_;
01622           }
01623           if ( up2 != infinity_ ) {
01624             lo = up - fabs ( up2 );
01625           }
01626           break;
01627         case COIN_G_ROW:
01628           if ( lo == -infinity_ ) {
01629             lo = 0.0;
01630             up = infinity_;
01631           } else {
01632             up = infinity_;
01633           }
01634           if ( up2 != infinity_ ) {
01635             up = lo + fabs ( up2 );
01636           }
01637           break;
01638         default:
01639           abort();
01640         }
01641         rowlower_[irow] = lo;
01642         rowupper_[irow] = up;
01643       }
01644     }
01645     free ( rowType );
01646     // default bounds
01647     collower_ = ( double * ) malloc ( numberColumns_ * sizeof ( double ) );
01648     colupper_ = ( double * ) malloc ( numberColumns_ * sizeof ( double ) );
01649     for (i=0;i<numberColumns_;i++) {
01650       collower_[i]=0.0;
01651       colupper_[i]=infinity_;
01652     }
01653     // set up integer region just in case
01654     integerType_ = (char *) malloc (numberColumns_*sizeof(char));
01655 
01656     for ( column = 0; column < numberColumns_; column++ ) {
01657       if ( columnType[column] == COIN_INTORG ) {
01658         columnType[column] = COIN_UNSET_BOUND;
01659         integerType_[column] = 1;
01660       } else {
01661         integerType_[column] = 0;
01662       }
01663     }
01664     // start hash even if no bound section - to make sure names survive
01665     startHash ( columnName, numberColumns_ , 1 );
01666     if ( cardReader_->whichSection (  ) == COIN_BOUNDS_SECTION ) {
01667       memset ( lastColumn, '\0', 200 );
01668       bool gotBound = false;
01669 
01670       while ( cardReader_->nextField (  ) == COIN_BOUNDS_SECTION ) {
01671         if ( strcmp ( lastColumn, cardReader_->columnName (  ) ) ) {
01672 
01673           // skip rest if got a bound
01674           if ( gotBound ) {
01675             while ( cardReader_->nextField (  ) == COIN_BOUNDS_SECTION ) {
01676             }
01677             break;
01678           } else {
01679             gotBound = true;;
01680             strcpy ( lastColumn, cardReader_->columnName (  ) );
01681             // save name of section
01682             free(boundName_);
01683             boundName_=strdup(cardReader_->columnName());
01684           }
01685         }
01686         // get column number
01687         COINColumnIndex icolumn = findHash ( cardReader_->rowName (  ) , 1 );
01688 
01689         if ( icolumn >= 0 ) {
01690           double value = cardReader_->value (  );
01691           bool ifError = false;
01692 
01693           switch ( cardReader_->mpsType (  ) ) {
01694           case COIN_UP_BOUND:
01695             if ( value == -1.0e100 )
01696               ifError = true;
01697             if ( columnType[icolumn] == COIN_UNSET_BOUND ) {
01698               if ( value < 0.0 ) {
01699                 collower_[icolumn] = -infinity_;
01700               }
01701             } else if ( columnType[icolumn] == COIN_LO_BOUND ) {
01702               if ( value < collower_[icolumn] ) {
01703                 ifError = true;
01704               } else if ( value < collower_[icolumn] + tinyElement ) {
01705                 value = collower_[icolumn];
01706               }
01707             } else if ( columnType[icolumn] == COIN_MI_BOUND ) {
01708             } else {
01709               ifError = true;
01710             }
01711             colupper_[icolumn] = value;
01712             columnType[icolumn] = COIN_UP_BOUND;
01713             break;
01714           case COIN_LO_BOUND:
01715             if ( value == -1.0e100 )
01716               ifError = true;
01717             if ( columnType[icolumn] == COIN_UNSET_BOUND ) {
01718             } else if ( columnType[icolumn] == COIN_UP_BOUND ||
01719                         columnType[icolumn] == COIN_UI_BOUND ) {
01720               if ( value > colupper_[icolumn] ) {
01721                 ifError = true;
01722               } else if ( value > colupper_[icolumn] - tinyElement ) {
01723                 value = colupper_[icolumn];
01724               }
01725             } else {
01726               ifError = true;
01727             }
01728             collower_[icolumn] = value;
01729             columnType[icolumn] = COIN_LO_BOUND;
01730             break;
01731           case COIN_FX_BOUND:
01732             if ( value == -1.0e100 )
01733               ifError = true;
01734             if ( columnType[icolumn] == COIN_UNSET_BOUND ) {
01735             } else if ( columnType[icolumn] == COIN_UI_BOUND ||
01736                         columnType[icolumn] == COIN_BV_BOUND) {
01737               // Allow so people can easily put FX's at end
01738               double value2 = floor(value);
01739               if (fabs(value2-value)>1.0e-12||
01740                   value2<collower_[icolumn]||
01741                   value2>colupper_[icolumn]) {
01742                 ifError=true;
01743               } else {
01744                 // take off integer list
01745                 assert(integerType_[icolumn] );
01746                 numberIntegers--;
01747                 integerType_[icolumn] = 0;
01748               }
01749             } else {
01750               ifError = true;
01751             }
01752             collower_[icolumn] = value;
01753             colupper_[icolumn] = value;
01754             columnType[icolumn] = COIN_FX_BOUND;
01755             break;
01756           case COIN_FR_BOUND:
01757             if ( columnType[icolumn] == COIN_UNSET_BOUND ) {
01758             } else {
01759               ifError = true;
01760             }
01761             collower_[icolumn] = -infinity_;
01762             colupper_[icolumn] = infinity_;
01763             columnType[icolumn] = COIN_FR_BOUND;
01764             break;
01765           case COIN_MI_BOUND:
01766             if ( columnType[icolumn] == COIN_UNSET_BOUND ) {
01767               colupper_[icolumn] = COIN_DBL_MAX;
01768             } else if ( columnType[icolumn] == COIN_UP_BOUND ) {
01769             } else {
01770               ifError = true;
01771             }
01772             collower_[icolumn] = -infinity_;
01773             columnType[icolumn] = COIN_MI_BOUND;
01774             break;
01775           case COIN_PL_BOUND:
01776             if ( columnType[icolumn] == COIN_UNSET_BOUND ) {
01777             } else {
01778               ifError = true;
01779             }
01780             columnType[icolumn] = COIN_PL_BOUND;
01781             break;
01782           case COIN_UI_BOUND:
01783 #if 0
01784             if ( value == -1.0e100 ) 
01785               ifError = true;
01786             if ( columnType[icolumn] == COIN_UNSET_BOUND ) {
01787             } else if ( columnType[icolumn] == COIN_LO_BOUND ) {
01788               if ( value < collower_[icolumn] ) {
01789                 ifError = true;
01790               } else if ( value < collower_[icolumn] + tinyElement ) {
01791                 value = collower_[icolumn];
01792               }
01793             } else {
01794               ifError = true;
01795             }
01796 #else
01797             if ( value == -1.0e100 ) {
01798                value = infinity_;
01799                if (columnType[icolumn] != COIN_UNSET_BOUND &&
01800                    columnType[icolumn] != COIN_LO_BOUND) {
01801                   ifError = true;
01802                }
01803             } else {
01804                if ( columnType[icolumn] == COIN_UNSET_BOUND ) {
01805                } else if ( columnType[icolumn] == COIN_LO_BOUND ) {
01806                   if ( value < collower_[icolumn] ) {
01807                      ifError = true;
01808                   } else if ( value < collower_[icolumn] + tinyElement ) {
01809                      value = collower_[icolumn];
01810                   }
01811                } else {
01812                   ifError = true;
01813                }
01814             }
01815 #endif
01816             colupper_[icolumn] = value;
01817             columnType[icolumn] = COIN_UI_BOUND;
01818             if ( !integerType_[icolumn] ) {
01819               numberIntegers++;
01820               integerType_[icolumn] = 1;
01821             }
01822             break;
01823           case COIN_BV_BOUND:
01824             if ( columnType[icolumn] == COIN_UNSET_BOUND ) {
01825             } else {
01826               ifError = true;
01827             }
01828             collower_[icolumn] = 0.0;
01829             colupper_[icolumn] = 1.0;
01830             columnType[icolumn] = COIN_BV_BOUND;
01831             if ( !integerType_[icolumn] ) {
01832               numberIntegers++;
01833               integerType_[icolumn] = 1;
01834             }
01835             break;
01836           default:
01837             ifError = true;
01838             break;
01839           }
01840           if ( ifError ) {
01841             numberErrors++;
01842             if ( numberErrors < 100 ) {
01843               handler_->message(COIN_MPS_BADIMAGE,messages_)
01844                 <<cardReader_->cardNumber()
01845                 <<cardReader_->card()
01846                 <<CoinMessageEol;
01847             } else if (numberErrors > 100000) {
01848               handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01849               return numberErrors;
01850             }
01851           }
01852         } else {
01853           numberErrors++;
01854           if ( numberErrors < 100 ) {
01855             handler_->message(COIN_MPS_NOMATCHCOL,messages_)
01856               <<cardReader_->rowName()<<cardReader_->cardNumber()<<cardReader_->card()
01857               <<CoinMessageEol;
01858           } else if (numberErrors > 100000) {
01859             handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01860             return numberErrors;
01861           }
01862         }
01863       }
01864     }
01865     stopHash ( 1 );
01866     // clean up integers
01867     if ( !numberIntegers ) {
01868       free(integerType_);
01869       integerType_ = NULL;
01870     } else {
01871       COINColumnIndex icolumn;
01872 
01873       for ( icolumn = 0; icolumn < numberColumns_; icolumn++ ) {
01874         if ( integerType_[icolumn] ) {
01875           assert ( collower_[icolumn] >= -MAX_INTEGER );
01876           // if 0 infinity make 0-1 ???
01877           if ( columnType[icolumn] == COIN_UNSET_BOUND ) 
01878             colupper_[icolumn] = defaultBound_;
01879           if ( colupper_[icolumn] > MAX_INTEGER ) 
01880             colupper_[icolumn] = MAX_INTEGER;
01881         }
01882       }
01883     }
01884     free ( columnType );
01885     if ( cardReader_->whichSection (  ) != COIN_ENDATA_SECTION ) {
01886       handler_->message(COIN_MPS_BADIMAGE,messages_)<<cardReader_->cardNumber()
01887                                                     <<cardReader_->card()
01888                                                     <<CoinMessageEol;
01889       handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
01890       return numberErrors;
01891     }
01892   } else {
01893     // This is very simple format - what should we use?
01894     COINColumnIndex i;
01895     FILE * fp = cardReader_->filePointer();
01896     fscanf ( fp, "%d %d %d\n", &numberRows_, &numberColumns_, &i);
01897     numberElements_  = i; // done this way in case numberElements_ long
01898 
01899     rowlower_ = ( double * ) malloc ( numberRows_ * sizeof ( double ) );
01900     rowupper_ = ( double * ) malloc ( numberRows_ * sizeof ( double ) );
01901     for ( i = 0; i < numberRows_; i++ ) {
01902       int j;
01903 
01904       fscanf ( fp, "%d %lg %lg\n", &j, &rowlower_[i], &rowupper_[i] );
01905       assert ( i == j );
01906     }
01907     collower_ = ( double * ) malloc ( numberColumns_ * sizeof ( double ) );
01908     colupper_ = ( double * ) malloc ( numberColumns_ * sizeof ( double ) );
01909     objective_= ( double * ) malloc ( numberColumns_ * sizeof ( double ) );
01910     start = ( CoinBigIndex *) malloc ((numberColumns_ + 1) *
01911                                         sizeof (CoinBigIndex) );
01912     row = ( COINRowIndex * ) malloc (numberElements_ * sizeof (COINRowIndex));
01913     element = ( double * ) malloc (numberElements_ * sizeof (double) );
01914 
01915     start[0] = 0;
01916     numberElements_ = 0;
01917     for ( i = 0; i < numberColumns_; i++ ) {
01918       int j;
01919       int n;
01920 
01921       fscanf ( fp, "%d %d %lg %lg %lg\n", &j, &n, &collower_[i], &colupper_[i],
01922                &objective_[i] );
01923       assert ( i == j );
01924       for ( j = 0; j < n; j++ ) {
01925         fscanf ( fp, "       %d %lg\n", &row[numberElements_],
01926                  &element[numberElements_] );
01927         numberElements_++;
01928       }
01929       start[i + 1] = numberElements_;
01930     }
01931   }
01932   // construct packed matrix
01933   matrixByColumn_ = 
01934     new CoinPackedMatrix(true,
01935                         numberRows_,numberColumns_,numberElements_,
01936                         element,row,start,NULL);
01937   free ( row );
01938   free ( start );
01939   free ( element );
01940 
01941   handler_->message(COIN_MPS_STATS,messages_)<<problemName_
01942                                             <<numberRows_
01943                                             <<numberColumns_
01944                                             <<numberElements_
01945                                             <<CoinMessageEol;
01946   return numberErrors;
01947 }
01948 
01949 //------------------------------------------------------------------
01950 
01951 // Function to return number in most efficient way
01952 // Also creates row name field
01953 /* formatType is
01954    0 - normal and 8 character names
01955    1 - extra accuracy
01956    2 - IEEE hex
01957    4 - normal but free format
01958 */
01959 static void
01960 convertDouble(int formatType, double value, char outputValue[20],
01961               const char * name, char outputRow[100])
01962 {
01963   assert (formatType!=2);
01964   if ((formatType&3)==0) {
01965     bool stripZeros=true;
01966     if (fabs(value)<1.0e40) {
01967       int power10, decimal;
01968       if (value>=0.0) {
01969         power10 =(int) log10(value);
01970         if (power10<9&&power10>-4) {
01971           decimal = min(10,10-power10);
01972           char format[7];
01973           sprintf(format,"%%12.%df",decimal);
01974           sprintf(outputValue,format,value);
01975         } else {
01976           sprintf(outputValue,"%12.7g",value);
01977           stripZeros=false;
01978         }
01979       } else {
01980         power10 =(int) log10(-value)+1;
01981         if (power10<8&&power10>-3) {
01982           decimal = min(9,9-power10);
01983           char format[7];
01984           sprintf(format,"%%12.%df",decimal);
01985           sprintf(outputValue,format,value);
01986         } else {
01987           sprintf(outputValue,"%12.6g",value);
01988           stripZeros=false;
01989         }
01990       }
01991       if (stripZeros) {
01992         // take off trailing 0
01993         int j;
01994         for (j=11;j>=0;j--) {
01995           if (outputValue[j]=='0')
01996             outputValue[j]=' ';
01997           else
01998             break;
01999         }
02000       }
02001     } else {
02002       outputValue[0]= '\0'; // needs no value
02003     }
02004   } else {
02005     if (fabs(value<1.0e40)) {
02006       sprintf(outputValue,"%19g",value);
02007       // take out blanks
02008       int i=0;
02009       int j;
02010       for (j=0;j<19;j++) {
02011         if (outputValue[j]!=' ')
02012           outputValue[i++]=outputValue[j];
02013       }
02014       outputValue[i]='\0';
02015     } else {
02016       outputValue[0]= '\0'; // needs no value
02017     }
02018   }
02019   strcpy(outputRow,name);
02020   if (!formatType) {
02021     int i;
02022     // pad out to 12 and 8
02023     for (i=0;i<12;i++) {
02024       if (outputValue[i]=='\0')
02025         break;
02026     }
02027     for (;i<12;i++) 
02028       outputValue[i]=' ';
02029     outputValue[12]='\0';
02030     for (i=0;i<8;i++) {
02031       if (outputRow[i]=='\0')
02032         break;
02033     }
02034     for (;i<8;i++) 
02035       outputRow[i]=' ';
02036     outputRow[8]='\0';
02037   }
02038 }
02039 
02040 static void
02041 writeString(FILE* fp, gzFile gzfp, const char* str)
02042 {
02043    if (fp) {
02044       fprintf(fp, "%s", str);
02045    }
02046 #ifdef COIN_USE_ZLIB
02047    if (gzfp) {
02048       gzprintf(gzfp, "%s", str);
02049    }
02050 #endif
02051 }
02052 
02053 // Put out card image
02054 static void outputCard(int formatType,int numberFields,
02055                        FILE *fp, gzFile gzfp,
02056                        std::string head, const char * name,
02057                        const char outputValue[2][20],
02058                        const char outputRow[2][100])
02059 {
02060    // fprintf(fp,"%s",head.c_str());
02061    std::string line = head;
02062    int i;
02063    if (!formatType) {
02064       char outputColumn[9];
02065       strcpy(outputColumn,name);
02066       for (i=0;i<8;i++) {
02067          if (outputColumn[i]=='\0')
02068             break;
02069       }
02070       for (;i<8;i++) 
02071          outputColumn[i]=' ';
02072       outputColumn[8]='\0';
02073       // fprintf(fp,"%s  ",outputColumn);
02074       line += outputColumn;
02075       line += "  ";
02076       for (i=0;i<numberFields;i++) {
02077          // fprintf(fp,"%s  %s",outputRow[i],outputValue[i]);
02078          line += outputRow[i];
02079          line += "  ";
02080          line += outputValue[i];
02081          if (i<numberFields-1) {
02082             // fprintf(fp,"   ");
02083             line += "   ";
02084          }
02085       }
02086    } else {
02087       // fprintf(fp,"%s",name);
02088       line += name;
02089       for (i=0;i<numberFields;i++) {
02090          // fprintf(fp," %s %s",outputRow[i],outputValue[i]);
02091          line += " ";
02092          line += outputRow[i];
02093          line += " ";
02094          line += outputValue[i];
02095       }
02096    }
02097    
02098    // fprintf(fp,"\n");
02099    line += "\n";
02100    writeString(fp, gzfp, line.c_str());
02101 }
02102 
02103 int
02104 CoinMpsIO::writeMps(const char *filename, int compression,
02105                    int formatType, int numberAcross) const
02106 {
02107    std::string line = filename;
02108    FILE * fp = NULL;
02109    gzFile gzfp = NULL;
02110    switch (compression) {
02111    case 1:
02112 #ifdef COIN_USE_ZLIB
02113       {
02114          if (strcmp(line.c_str() +(line.size()-3), ".gz") != 0) {
02115             line += ".gz";
02116          }
02117          gzfp = gzopen(line.c_str(), "wb");
02118          if (gzfp) {
02119             break;
02120          }
02121       }
02122 #endif
02123       fp = fopen(filename,"w");
02124       if (!fp)
02125          return -1;
02126       break;
02127 
02128    case 2: /* bzip2: to be implemented */
02129    case 0:
02130       fp = fopen(filename,"w");
02131       if (!fp)
02132          return -1;
02133       break;
02134    }
02135 
02136    const char * const * const rowNames = names_[0];
02137    const char * const * const columnNames = names_[1];
02138    int i;
02139    unsigned int length = 8;
02140    bool freeFormat = (formatType!=0);
02141    for (i = 0 ; i < numberRows_; ++i) {
02142       if (strlen(rowNames[i]) > length) {
02143          length = strlen(rowNames[i]);
02144          break;
02145       }
02146    }
02147    if (length <= 8) {
02148       for (i = 0 ; i < numberColumns_; ++i) {
02149          if (strlen(columnNames[i]) > length) {
02150             length = strlen(columnNames[i]);
02151             break;
02152          }
02153       }
02154    }
02155    if (length > 8 && !freeFormat) {
02156       freeFormat = true;
02157       formatType = 4;
02158    }
02159    
02160    // NAME card
02161 
02162    line = "NAME          ";
02163    if (strcmp(problemName_,"")==0) {
02164       line.append("BLANK   ");
02165    } else {
02166       if (strlen(problemName_) >= 8) {
02167          line.append(problemName_, 8);
02168       } else {
02169          line.append(problemName_);
02170          line.append(8-strlen(problemName_), ' ');
02171       }
02172    }
02173    if (freeFormat)
02174       line.append("  FREE");
02175    // finish off name and do ROWS card and objective 
02176    line.append("\nROWS\n N  OBJROW\n");
02177    writeString(fp, gzfp, line.c_str());
02178 
02179    // Rows section
02180    // Sense array
02181    // But massage if looks odd
02182    char * sense = new char [numberRows_];
02183    memcpy( sense , getRowSense(), numberRows_);
02184    const double * rowLower = getRowLower();
02185    const double * rowUpper = getRowUpper();
02186   
02187    for (i=0;i<numberRows_;i++) {
02188       line = " ";
02189       if (sense[i]!='R') {
02190          line.append(1,sense[i]);
02191       } else {
02192         if (rowLower[i]>-1.0e30) {
02193           if(rowUpper[i]<1.0e30) {
02194          line.append("L");
02195           } else {
02196             sense[i]='G';
02197             line.append(1,sense[i]);
02198       }
02199         } else {
02200           sense[i]='L';
02201           line.append(1,sense[i]);
02202         }
02203       }
02204       line.append("  ");
02205       line.append(rowNames[i]);
02206       line.append("\n");
02207       writeString(fp, gzfp, line.c_str());
02208    }
02209 
02210    // COLUMNS card
02211    writeString(fp, gzfp, "COLUMNS\n");
02212 
02213    bool ifBounds=false;
02214    double largeValue = infinity_;
02215 
02216    const double * columnLower = getColLower();
02217    const double * columnUpper = getColUpper();
02218    const double * objective = getObjCoefficients();
02219    const CoinPackedMatrix * matrix = getMatrixByCol();
02220    const double * elements = matrix->getElements();
02221    const int * rows = matrix->getIndices();
02222    const CoinBigIndex * starts = matrix->getVectorStarts();
02223    const int * lengths = matrix->getVectorLengths();
02224 
02225    char outputValue[2][20];
02226    char outputRow[2][100];
02227 
02228    // Through columns (only put out if elements or objective value)
02229    for (i=0;i<numberColumns_;i++) {
02230       if (objective[i]||lengths[i]) {
02231          // see if bound will be needed
02232          if (columnLower[i]||columnUpper[i]<largeValue||isInteger(i))
02233             ifBounds=true;
02234          int numberFields=0;
02235          if (objective[i]) {
02236             convertDouble(formatType,objective[i],outputValue[0],
02237                           "OBJROW",outputRow[0]);
02238             numberFields=1;
02239          }
02240          if (numberFields==numberAcross) {
02241             // put out card
02242             outputCard(formatType, numberFields,
02243                        fp, gzfp, "    ",
02244                        columnNames[i],
02245                        outputValue,
02246                        outputRow);
02247             numberFields=0;
02248          }
02249          int j;
02250          for (j=0;j<lengths[i];j++) {
02251             convertDouble(formatType,elements[starts[i]+j],
02252                           outputValue[numberFields],
02253                           rowNames[rows[starts[i]+j]],
02254                           outputRow[numberFields]);
02255             numberFields++;
02256             if (numberFields==numberAcross) {
02257                // put out card
02258                outputCard(formatType, numberFields,
02259                           fp, gzfp, "    ",
02260                           columnNames[i],
02261                           outputValue,
02262                           outputRow);
02263                numberFields=0;
02264             }
02265          }
02266          if (numberFields) {
02267             // put out card
02268             outputCard(formatType, numberFields,
02269                        fp, gzfp, "    ",
02270                        columnNames[i],
02271                        outputValue,
02272                        outputRow);
02273          }
02274       }
02275    }
02276 
02277    bool ifRange=false;
02278    // RHS
02279    writeString(fp, gzfp, "RHS\n");
02280 
02281    int numberFields = 0;
02282    for (i=0;i<numberRows_;i++) {
02283       double value;
02284       switch (sense[i]) {
02285       case 'E':
02286          value=rowLower[i];
02287          break;
02288       case 'R':
02289          value=rowUpper[i];
02290            ifRange=true;
02291          break;
02292       case 'L':
02293          value=rowUpper[i];
02294          break;
02295       case 'G':
02296          value=rowLower[i];
02297          break;
02298       default:
02299          value=0.0;
02300          break;
02301       }
02302       if (value != 0.0) {
02303          convertDouble(formatType,value,
02304                        outputValue[numberFields],
02305                        rowNames[i],
02306                        outputRow[numberFields]);
02307          numberFields++;
02308          if (numberFields==numberAcross) {
02309             // put out card
02310             outputCard(formatType, numberFields,
02311                        fp, gzfp, "    ",
02312                        "RHS",
02313                        outputValue,
02314                        outputRow);
02315             numberFields=0;
02316          }
02317       }
02318    }
02319    if (numberFields) {
02320       // put out card
02321       outputCard(formatType, numberFields,
02322                  fp, gzfp, "    ",
02323                  "RHS",
02324                  outputValue,
02325                  outputRow);
02326    }
02327 
02328    if (ifRange) {
02329       // RANGES
02330       writeString(fp, gzfp, "RANGES\n");
02331 
02332       numberFields = 0;
02333       for (i=0;i<numberRows_;i++) {
02334          if (sense[i]=='R') {
02335             double value =rowUpper[i]-rowLower[i];
02336             if (value<1.0e30) {
02337               convertDouble(formatType,value,
02338                             outputValue[numberFields],
02339                             rowNames[i],
02340                             outputRow[numberFields]);
02341               numberFields++;
02342               if (numberFields==numberAcross) {
02343                 // put out card
02344                 outputCard(formatType, numberFields,
02345                            fp, gzfp, "    ",
02346                            "RANGE",
02347                            outputValue,
02348                            outputRow);
02349                 numberFields=0;
02350               }
02351             }
02352          }
02353       }
02354       if (numberFields) {
02355          // put out card
02356          outputCard(formatType, numberFields,
02357                     fp, gzfp, "    ",
02358                     "RANGE",
02359                     outputValue,
02360                     outputRow);
02361       }
02362    }
02363    delete [] sense;
02364    if (ifBounds) {
02365       // BOUNDS
02366       writeString(fp, gzfp, "BOUNDS\n");
02367 
02368       for (i=0;i<numberColumns_;i++) {
02369          if (objective[i]||lengths[i]) {
02370             // see if bound will be needed
02371             if (columnLower[i]||columnUpper[i]<largeValue||isInteger(i)) {
02372               double lowerValue = columnLower[i];
02373               double upperValue = columnUpper[i];
02374               if (isInteger(i)) {
02375                 // Old argument - what are correct ranges for integer variables
02376                 lowerValue = max(lowerValue,(double) -INT_MAX);
02377                 upperValue = min(upperValue,(double) INT_MAX);
02378               }
02379                int numberFields=1;
02380                std::string header[2];
02381                double value[2];
02382                if (lowerValue<=-largeValue) {
02383                   // FR or MI
02384                   if (upperValue>=largeValue) {
02385                      header[0]=" FR ";
02386                      value[0] = largeValue;
02387                   } else {
02388                      header[0]=" MI ";
02389                      value[0] = largeValue;
02390                      header[1]=" UP ";
02391                      value[1] = upperValue;
02392                      numberFields=2;
02393                   }
02394                } else if (fabs(upperValue-lowerValue)<1.0e-8) {
02395                   header[0]=" FX ";
02396                   value[0] = lowerValue;
02397                } else {
02398                   // do LO if needed
02399                   if (lowerValue) {
02400                      // LO
02401                      header[0]=" LO ";
02402                      value[0] = lowerValue;
02403                      if (isInteger(i)) {
02404                         // Integer variable so UI
02405                         header[1]=" UI ";
02406                         value[1] = upperValue;
02407                         numberFields=2;
02408                      } else if (upperValue<largeValue) {
02409                         // UP
02410                         header[1]=" UP ";
02411                         value[1] = upperValue;
02412                         numberFields=2;
02413                      }
02414                   } else {
02415                      if (isInteger(i)) {
02416                         // Integer variable so BV or UI
02417                         if (fabs(upperValue-1.0)<1.0e-8) {
02418                            // BV
02419                            header[0]=" BV ";
02420                            value[0] = largeValue;
02421                         } else {
02422                            // UI
02423                            header[0]=" UI ";
02424                            value[0] = upperValue;
02425                         }
02426                      } else {
02427                         // UP
02428                         header[0]=" UP ";
02429                         value[0] = upperValue;
02430                      }
02431                   }
02432                }
02433                // put out fields
02434                int j;
02435                for (j=0;j<numberFields;j++) {
02436                   convertDouble(formatType,value[j],
02437                                 outputValue[0],
02438                                 columnNames[i],
02439                                 outputRow[0]);
02440                   // put out card
02441                   outputCard(formatType, 1,
02442                              fp, gzfp, header[j],
02443                              "BOUND",
02444                              outputValue,
02445                              outputRow);
02446                }
02447             }
02448          }
02449       }
02450    }
02451 
02452    // and finish
02453 
02454    writeString(fp, gzfp, "ENDATA\n");
02455 
02456    if (fp) {
02457       fclose(fp);
02458    }
02459 #ifdef COIN_USE_ZLIB
02460    if (gzfp) {
02461       gzclose(gzfp);
02462    }
02463 #endif
02464 
02465    return 0;
02466 }
02467    
02468 //------------------------------------------------------------------
02469 // Problem name
02470 const char * CoinMpsIO::getProblemName() const
02471 {
02472   return problemName_;
02473 }
02474 // Objective name
02475 const char * CoinMpsIO::getObjectiveName() const
02476 {
02477   return objectiveName_;
02478 }
02479 // Rhs name
02480 const char * CoinMpsIO::getRhsName() const
02481 {
02482   return rhsName_;
02483 }
02484 // Range name
02485 const char * CoinMpsIO::getRangeName() const
02486 {
02487   return rangeName_;
02488 }
02489 // Bound name
02490 const char * CoinMpsIO::getBoundName() const
02491 {
02492   return boundName_;
02493 }
02494 
02495 //------------------------------------------------------------------
02496 // Get number of rows, columns and elements
02497 //------------------------------------------------------------------
02498 int CoinMpsIO::getNumCols() const
02499 {
02500   return numberColumns_;
02501 }
02502 int CoinMpsIO::getNumRows() const
02503 {
02504   return numberRows_;
02505 }
02506 int CoinMpsIO::getNumElements() const
02507 {
02508   return numberElements_;
02509 }
02510 
02511 //------------------------------------------------------------------
02512 // Get pointer to column lower and upper bounds.
02513 //------------------------------------------------------------------  
02514 const double * CoinMpsIO::getColLower() const
02515 {
02516   return collower_;
02517 }
02518 const double * CoinMpsIO::getColUpper() const
02519 {
02520   return colupper_;
02521 }
02522 
02523 //------------------------------------------------------------------
02524 // Get pointer to row lower and upper bounds.
02525 //------------------------------------------------------------------  
02526 const double * CoinMpsIO::getRowLower() const
02527 {
02528   return rowlower_;
02529 }
02530 const double * CoinMpsIO::getRowUpper() const
02531 {
02532   return rowupper_;
02533 }
02534  
02537 inline void
02538 CoinMpsIO::convertBoundToSense(const double lower, const double upper,
02539                                         char& sense, double& right,
02540                                         double& range) const
02541 {
02542   range = 0.0;
02543   if (lower > -infinity_) {
02544     if (upper < infinity_) {
02545       right = upper;
02546       if (upper==lower) {
02547         sense = 'E';
02548       } else {
02549         sense = 'R';
02550         range = upper - lower;
02551       }
02552     } else {
02553       sense = 'G';
02554       right = lower;
02555     }
02556   } else {
02557     if (upper < infinity_) {
02558       sense = 'L';
02559       right = upper;
02560     } else {
02561       sense = 'N';
02562       right = 0.0;
02563     }
02564   }
02565 }
02566 
02567 //-----------------------------------------------------------------------------
02570 inline void
02571 CoinMpsIO::convertSenseToBound(const char sense, const double right,
02572                                         const double range,
02573                                         double& lower, double& upper) const
02574 {
02575   switch (sense) {
02576   case 'E':
02577     lower = upper = right;
02578     break;
02579   case 'L':
02580     lower = -infinity_;
02581     upper = right;
02582     break;
02583   case 'G':
02584     lower = right;
02585     upper = infinity_;
02586     break;
02587   case 'R':
02588     lower = right - range;
02589     upper = right;
02590     break;
02591   case 'N':
02592     lower = -infinity_;
02593     upper = infinity_;
02594     break;
02595   }
02596 }
02597 //------------------------------------------------------------------
02598 // Get sense of row constraints.
02599 //------------------------------------------------------------------ 
02600 const char * CoinMpsIO::getRowSense() const
02601 {
02602   if ( rowsense_==NULL ) {
02603 
02604     int nr=numberRows_;
02605     rowsense_ = (char *) malloc(nr*sizeof(char));
02606 
02607 
02608     double dum1,dum2;
02609     int i;
02610     for ( i=0; i<nr; i++ ) {
02611       convertBoundToSense(rowlower_[i],rowupper_[i],rowsense_[i],dum1,dum2);
02612     }
02613   }
02614   return rowsense_;
02615 }
02616 
02617 //------------------------------------------------------------------
02618 // Get the rhs of rows.
02619 //------------------------------------------------------------------ 
02620 const double * CoinMpsIO::getRightHandSide() const
02621 {
02622   if ( rhs_==NULL ) {
02623 
02624     int nr=numberRows_;
02625     rhs_ = (double *) malloc(nr*sizeof(double));
02626 
02627 
02628     char dum1;
02629     double dum2;
02630     int i;
02631     for ( i=0; i<nr; i++ ) {
02632       convertBoundToSense(rowlower_[i],rowupper_[i],dum1,rhs_[i],dum2);
02633     }
02634   }
02635   return rhs_;
02636 }
02637 
02638 //------------------------------------------------------------------
02639 // Get the range of rows.
02640 // Length of returned vector is getNumRows();
02641 //------------------------------------------------------------------ 
02642 const double * CoinMpsIO::getRowRange() const
02643 {
02644   if ( rowrange_==NULL ) {
02645 
02646     int nr=numberRows_;
02647     rowrange_ = (double *) malloc(nr*sizeof(double));
02648     std::fill(rowrange_,rowrange_+nr,0.0);
02649 
02650     char dum1;
02651     double dum2;
02652     int i;
02653     for ( i=0; i<nr; i++ ) {
02654       convertBoundToSense(rowlower_[i],rowupper_[i],dum1,dum2,rowrange_[i]);
02655     }
02656   }
02657   return rowrange_;
02658 }
02659 
02660 const double * CoinMpsIO::getObjCoefficients() const
02661 {
02662   return objective_;
02663 }
02664  
02665 //------------------------------------------------------------------
02666 // Create a row copy of the matrix ...
02667 //------------------------------------------------------------------
02668 const CoinPackedMatrix * CoinMpsIO::getMatrixByRow() const
02669 {
02670   if ( matrixByRow_ == NULL && matrixByColumn_) {
02671     matrixByRow_ = new CoinPackedMatrix(*matrixByColumn_);
02672     matrixByRow_->reverseOrdering();
02673   }
02674   return matrixByRow_;
02675 }
02676 
02677 //------------------------------------------------------------------
02678 // Create a column copy of the matrix ...
02679 //------------------------------------------------------------------
02680 const CoinPackedMatrix * CoinMpsIO::getMatrixByCol() const
02681 {
02682   return matrixByColumn_;
02683 }
02684 
02685 //------------------------------------------------------------------
02686 // Save the data ...
02687 //------------------------------------------------------------------
02688 void
02689 CoinMpsIO::setMpsDataWithoutRowAndColNames(
02690                                   const CoinPackedMatrix& m, const double infinity,
02691                                   const double* collb, const double* colub,
02692                                   const double* obj, const char* integrality,
02693                                   const double* rowlb, const double* rowub)
02694 {
02695   freeAll();
02696   if (m.isColOrdered()) {
02697     matrixByColumn_ = new CoinPackedMatrix(m);
02698   } else {
02699     matrixByColumn_ = new CoinPackedMatrix;
02700     matrixByColumn_->reverseOrderedCopyOf(m);
02701   }
02702   numberColumns_ = matrixByColumn_->getNumCols();
02703   numberRows_ = matrixByColumn_->getNumRows();
02704   numberElements_ = matrixByColumn_->getNumElements();
02705   defaultBound_ = 1;
02706   infinity_ = infinity;
02707   objectiveOffset_ = 0;
02708   
02709   rowlower_ = (double *) malloc (numberRows_ * sizeof(double));
02710   rowupper_ = (double *) malloc (numberRows_ * sizeof(double));
02711   collower_ = (double *) malloc (numberColumns_ * sizeof(double));
02712   colupper_ = (double *) malloc (numberColumns_ * sizeof(double));
02713   objective_ = (double *) malloc (numberColumns_ * sizeof(double));
02714   std::copy(rowlb, rowlb + numberRows_, rowlower_);
02715   std::copy(rowub, rowub + numberRows_, rowupper_);
02716   std::copy(collb, collb + numberColumns_, collower_);
02717   std::copy(colub, colub + numberColumns_, colupper_);
02718   std::copy(obj, obj + numberColumns_, objective_);
02719   if (integrality) {
02720     integerType_ = (char *) malloc (numberColumns_ * sizeof(char));
02721     std::copy(integrality, integrality + numberColumns_, integerType_);
02722   } else {
02723     integerType_ = 0;
02724   }
02725     
02726   problemName_ = strdup("");
02727   objectiveName_ = strdup("");
02728   rhsName_ = strdup("");
02729   rangeName_ = strdup("");
02730   boundName_ = strdup("");
02731 }
02732 
02733 
02734 void
02735 CoinMpsIO::setMpsDataColAndRowNames(
02736                       char const * const * const colnames,
02737                       char const * const * const rownames)
02738 {
02739   releaseRowNames();
02740   releaseColumnNames();
02741    // If long names free format
02742    names_[0] = (char **) malloc(numberRows_ * sizeof(char *));
02743    names_[1] = (char **) malloc (numberColumns_ * sizeof(char *));
02744    numberHash_[0]=numberRows_;
02745    numberHash_[1]=numberColumns_;
02746    char** rowNames_ = names_[0];
02747    char** colNames_ = names_[1];
02748    int i;
02749    if (rownames) {
02750      for (i = 0 ; i < numberRows_; ++i) {
02751        rowNames_[i] = strdup(rownames[i]);
02752      }
02753    } else {
02754      for (i = 0; i < numberRows_; ++i) {
02755        rowNames_[i] = (char *) malloc (9 * sizeof(char));
02756        sprintf(rowNames_[i],"R%7.7d",i);
02757      }
02758    }
02759    if (colnames) {
02760      for (i = 0 ; i < numberColumns_; ++i) {
02761        colNames_[i] = strdup(colnames[i]);
02762      }
02763    } else {
02764      for (i = 0; i < numberColumns_; ++i) {
02765        colNames_[i] = (char *) malloc (9 * sizeof(char));
02766        sprintf(colNames_[i],"C%7.7d",i);
02767      }
02768    }
02769 }
02770 
02771 void
02772 CoinMpsIO::setMpsDataColAndRowNames(
02773                       const std::vector<std::string> & colnames,
02774                       const std::vector<std::string> & rownames)
02775 {  
02776    // If long names free format
02777    names_[0] = (char **) malloc(numberRows_ * sizeof(char *));
02778    names_[1] = (char **) malloc (numberColumns_ * sizeof(char *));
02779    char** rowNames_ = names_[0];
02780    char** colNames_ = names_[1];
02781    int i;
02782    if (rownames.size()!=0) {
02783      for (i = 0 ; i < numberRows_; ++i) {
02784        rowNames_[i] = strdup(rownames[i].c_str());
02785      }
02786    } else {
02787      for (i = 0; i < numberRows_; ++i) {
02788        rowNames_[i] = (char *) malloc (9 * sizeof(char));
02789        sprintf(rowNames_[i],"R%7.7d",i);
02790      }
02791    }
02792    if (colnames.size()!=0) {
02793      for (i = 0 ; i < numberColumns_; ++i) {
02794        colNames_[i] = strdup(colnames[i].c_str());
02795      }
02796    } else {
02797      for (i = 0; i < numberColumns_; ++i) {
02798        colNames_[i] = (char *) malloc (9 * sizeof(char));
02799        sprintf(colNames_[i],"C%7.7d",i);
02800      }
02801    }
02802 }
02803 
02804 void
02805 CoinMpsIO::setMpsData(const CoinPackedMatrix& m, const double infinity,
02806                       const double* collb, const double* colub,
02807                       const double* obj, const char* integrality,
02808                       const double* rowlb, const double* rowub,
02809                       char const * const * const colnames,
02810                       char const * const * const rownames)
02811 {
02812   setMpsDataWithoutRowAndColNames(m,infinity,collb,colub,obj,integrality,rowlb,rowub);
02813   setMpsDataColAndRowNames(colnames,rownames);
02814 }
02815 
02816 void
02817 CoinMpsIO::setMpsData(const CoinPackedMatrix& m, const double infinity,
02818                       const double* collb, const double* colub,
02819                       const double* obj, const char* integrality,
02820                       const double* rowlb, const double* rowub,
02821                       const std::vector<std::string> & colnames,
02822                       const std::vector<std::string> & rownames)
02823 {
02824   setMpsDataWithoutRowAndColNames(m,infinity,collb,colub,obj,integrality,rowlb,rowub);
02825   setMpsDataColAndRowNames(colnames,rownames);
02826 }
02827 
02828 void
02829 CoinMpsIO::setMpsData(const CoinPackedMatrix& m, const double infinity,
02830                       const double* collb, const double* colub,
02831                       const double* obj, const char* integrality,
02832                       const char* rowsen, const double* rowrhs,
02833                       const double* rowrng,
02834                       char const * const * const colnames,
02835                       char const * const * const rownames)
02836 {
02837    const int numrows = matrixByColumn_->getNumRows();
02838 
02839    double * rlb = numrows ? new double[numrows] : 0;
02840    double * rub = numrows ? new double[numrows] : 0;
02841 
02842    for (int i = 0; i < numrows; ++i) {
02843       convertSenseToBound(rowsen[i], rowrhs[i], rowrng[i], rlb[i], rub[i]);
02844    }
02845    setMpsData(m, infinity, collb, colub, obj, integrality, rlb, rub,
02846               colnames, rownames);
02847 }
02848 
02849 void
02850 CoinMpsIO::setMpsData(const CoinPackedMatrix& m, const double infinity,
02851                       const double* collb, const double* colub,
02852                       const double* obj, const char* integrality,
02853                       const char* rowsen, const double* rowrhs,
02854                       const double* rowrng,
02855                       const std::vector<std::string> & colnames,
02856                       const std::vector<std::string> & rownames)
02857 {
02858    const int numrows = matrixByColumn_->getNumRows();
02859 
02860    double * rlb = numrows ? new double[numrows] : 0;
02861    double * rub = numrows ? new double[numrows] : 0;
02862 
02863    for (int i = 0; i < numrows; ++i) {
02864       convertSenseToBound(rowsen[i], rowrhs[i], rowrng[i], rlb[i], rub[i]);
02865    }
02866    setMpsData(m, infinity, collb, colub, obj, integrality, rlb, rub,
02867               colnames, rownames);
02868 }
02869 
02870 
02871 //------------------------------------------------------------------
02872 // Return true if column is a continuous, binary, ...
02873 //------------------------------------------------------------------
02874 bool CoinMpsIO::isContinuous(int columnNumber) const
02875 {
02876   const char * intType = integerType_;
02877   if ( intType==NULL ) return true;
02878   assert (columnNumber>=0 && columnNumber < numberColumns_);
02879   if ( intType[columnNumber]==0 ) return true;
02880   return false;
02881 }
02882 
02883 /* Return true if column is integer.
02884    Note: This function returns true if the the column
02885    is binary or a general integer.
02886 */
02887 bool CoinMpsIO::isInteger(int columnNumber) const
02888 {
02889   const char * intType = integerType_;
02890   if ( intType==NULL ) return false;
02891   assert (columnNumber>=0 && columnNumber < numberColumns_);
02892   if ( intType[columnNumber]!=0 ) return true;
02893   return false;
02894 }
02895 // if integer
02896 const char * CoinMpsIO::integerColumns() const
02897 {
02898   return integerType_;
02899 }
02900 // Pass in array saying if each variable integer
02901 void 
02902 CoinMpsIO::copyInIntegerInformation(const char * integerType)
02903 {
02904   if (integerType) {
02905     if (!integerType_)
02906       integerType_ = new char [numberColumns_];
02907     memcpy(integerType_,integerType,numberColumns_);
02908   } else {
02909     delete [] integerType_;
02910     integerType_=NULL;
02911   }
02912 }
02913 // names - returns NULL if out of range
02914 const char * CoinMpsIO::rowName(int index) const
02915 {
02916   if (index>=0&&index<numberRows_) {
02917     return names_[0][index];
02918   } else {
02919     return NULL;
02920   }
02921 }
02922 const char * CoinMpsIO::columnName(int index) const
02923 {
02924   if (index>=0&&index<numberColumns_) {
02925     return names_[1][index];
02926   } else {
02927     return NULL;
02928   }
02929 }
02930 // names - returns -1 if name not found
02931 int CoinMpsIO::rowIndex(const char * name) const
02932 {
02933   if (!hash_[0]) {
02934     if (numberRows_) {
02935       startHash(0);
02936     } else {
02937       return -1;
02938     }
02939   }
02940   return findHash ( name , 0 );
02941 }
02942     int CoinMpsIO::columnIndex(const char * name) const
02943 {
02944   if (!hash_[1]) {
02945     if (numberColumns_) {
02946       startHash(1);
02947     } else {
02948       return -1;
02949     }
02950   }
02951   return findHash ( name , 1 );
02952 }
02953 
02954 // Release all row information (lower, upper)
02955 void CoinMpsIO::releaseRowInformation()
02956 {
02957   free(rowlower_);
02958   free(rowupper_);
02959   rowlower_=NULL;
02960   rowupper_=NULL;
02961 }
02962 // Release all column information (lower, upper, objective)
02963 void CoinMpsIO::releaseColumnInformation()
02964 {
02965   free(collower_);
02966   free(colupper_);
02967   free(objective_);
02968   collower_=NULL;
02969   colupper_=NULL;
02970   objective_=NULL;
02971 }
02972 // Release integer information
02973 void CoinMpsIO::releaseIntegerInformation()
02974 {
02975   free(integerType_);
02976   integerType_=NULL;
02977 }
02978 // Release row names
02979 void CoinMpsIO::releaseRowNames()
02980 {
02981   releaseRedundantInformation();
02982   int i;
02983   for (i=0;i<numberHash_[0];i++) {
02984     free(names_[0][i]);
02985   }
02986   free(names_[0]);
02987   names_[0]=NULL;
02988   numberHash_[0]=0;
02989 }
02990 // Release column names
02991 void CoinMpsIO::releaseColumnNames()
02992 {
02993   releaseRedundantInformation();
02994   int i;
02995   for (i=0;i<numberHash_[1];i++) {
02996     free(names_[1][i]);
02997   }
02998   free(names_[1]);
02999   names_[1]=NULL;
03000   numberHash_[1]=0;
03001 }
03002 // Release matrix information
03003 void CoinMpsIO::releaseMatrixInformation()
03004 {
03005   releaseRedundantInformation();
03006   delete matrixByColumn_;
03007   matrixByColumn_=NULL;
03008 }
03009   
03010 
03011 
03012 //-------------------------------------------------------------------
03013 // Default Constructor 
03014 //-------------------------------------------------------------------
03015 CoinMpsIO::CoinMpsIO ()
03016 :
03017 problemName_(strdup("")),
03018 objectiveName_(strdup("")),
03019 rhsName_(strdup("")),
03020 rangeName_(strdup("")),
03021 boundName_(strdup("")),
03022 numberRows_(0),
03023 numberColumns_(0),
03024 numberElements_(0),
03025 rowsense_(NULL),
03026 rhs_(NULL),
03027 rowrange_(NULL),
03028 matrixByRow_(NULL),
03029 matrixByColumn_(NULL),
03030 rowlower_(NULL),
03031 rowupper_(NULL),
03032 collower_(NULL),
03033 colupper_(NULL),
03034 objective_(NULL),
03035 objectiveOffset_(0.0),
03036 integerType_(NULL),
03037 fileName_(strdup("stdin")),
03038 defaultBound_(1),
03039 infinity_(COIN_DBL_MAX),
03040 defaultHandler_(true),
03041 cardReader_(NULL)
03042 {
03043   numberHash_[0]=0;
03044   hash_[0]=NULL;
03045   names_[0]=NULL;
03046   numberHash_[1]=0;
03047   hash_[1]=NULL;
03048   names_[1]=NULL;
03049   handler_ = new CoinMessageHandler();
03050   messages_ = CoinMessage();
03051 }
03052 
03053 //-------------------------------------------------------------------
03054 // Copy constructor 
03055 //-------------------------------------------------------------------
03056 CoinMpsIO::CoinMpsIO(const CoinMpsIO & rhs)
03057 :
03058 problemName_(strdup("")),
03059 objectiveName_(strdup("")),
03060 rhsName_(strdup("")),
03061 rangeName_(strdup("")),
03062 boundName_(strdup("")),
03063 numberRows_(0),
03064 numberColumns_(0),
03065 numberElements_(0),
03066 rowsense_(NULL),
03067 rhs_(NULL),
03068 rowrange_(NULL),
03069 matrixByRow_(NULL),
03070 matrixByColumn_(NULL),
03071 rowlower_(NULL),
03072 rowupper_(NULL),
03073 collower_(NULL),
03074 colupper_(NULL),
03075 objective_(NULL),
03076 objectiveOffset_(0.0),
03077 integerType_(NULL),
03078 fileName_(strdup("stdin")),
03079 defaultBound_(1),
03080 infinity_(COIN_DBL_MAX),
03081 defaultHandler_(true),
03082 cardReader_(NULL)
03083 {
03084   numberHash_[0]=0;
03085   hash_[0]=NULL;
03086   names_[0]=NULL;
03087   numberHash_[1]=0;
03088   hash_[1]=NULL;
03089   names_[1]=NULL;
03090   if ( rhs.rowlower_ !=NULL || rhs.collower_ != NULL) {
03091     gutsOfCopy(rhs);
03092     // OK and proper to leave rowsense_, rhs_, and
03093     // rowrange_ (also row copy and hash) to NULL.  They will be constructed
03094     // if they are required.
03095   }
03096   defaultHandler_ = rhs.defaultHandler_;
03097   if (defaultHandler_)
03098     handler_ = new CoinMessageHandler(*rhs.handler_);
03099   else
03100     handler_ = rhs.handler_;
03101   messages_ = CoinMessage();
03102 }
03103 
03104 void CoinMpsIO::gutsOfCopy(const CoinMpsIO & rhs)
03105 {
03106   defaultHandler_ = rhs.defaultHandler_;
03107   if (rhs.matrixByColumn_)
03108     matrixByColumn_=new CoinPackedMatrix(*(rhs.matrixByColumn_));
03109   numberElements_=rhs.numberElements_;
03110   numberRows_=rhs.numberRows_;
03111   numberColumns_=rhs.numberColumns_;
03112   if (rhs.rowlower_) {
03113     rowlower_ = (double *) malloc(numberRows_*sizeof(double));
03114     rowupper_ = (double *) malloc(numberRows_*sizeof(double));
03115     memcpy(rowlower_,rhs.rowlower_,numberRows_*sizeof(double));
03116     memcpy(rowupper_,rhs.rowupper_,numberRows_*sizeof(double));
03117   }
03118   if (rhs.collower_) {
03119     collower_ = (double *) malloc(numberColumns_*sizeof(double));
03120     colupper_ = (double *) malloc(numberColumns_*sizeof(double));
03121     objective_ = (double *) malloc(numberColumns_*sizeof(double));
03122     memcpy(collower_,rhs.collower_,numberColumns_*sizeof(double));
03123     memcpy(colupper_,rhs.colupper_,numberColumns_*sizeof(double));
03124     memcpy(objective_,rhs.objective_,numberColumns_*sizeof(double));
03125   }
03126   if (rhs.integerType_) {
03127     integerType_ = (char *) malloc (numberColumns_*sizeof(char));
03128     memcpy(integerType_,rhs.integerType_,numberColumns_*sizeof(char));
03129   }
03130   free(fileName_);
03131   free(problemName_);
03132   free(objectiveName_);
03133   free(rhsName_);
03134   free(rangeName_);
03135   free(boundName_);
03136   fileName_ = strdup(rhs.fileName_);
03137   problemName_ = strdup(rhs.problemName_);
03138   objectiveName_ = strdup(rhs.objectiveName_);
03139   rhsName_ = strdup(rhs.rhsName_);
03140   rangeName_ = strdup(rhs.rangeName_);
03141   boundName_ = strdup(rhs.boundName_);
03142   numberHash_[0]=rhs.numberHash_[0];
03143   numberHash_[1]=rhs.numberHash_[1];
03144   defaultBound_=rhs.defaultBound_;
03145   infinity_=rhs.infinity_;
03146   objectiveOffset_=rhs.objectiveOffset_;
03147   int section;
03148   for (section=0;section<2;section++) {
03149     if (numberHash_[section]) {
03150       char ** names2 = rhs.names_[section];
03151       names_[section] = (char **) malloc(numberHash_[section]*
03152                                          sizeof(char *));
03153       char ** names = names_[section];
03154       int i;
03155       for (i=0;i<numberHash_[section];i++) {
03156         names[i]=strdup(names2[i]);
03157       }
03158     }
03159   }
03160 }
03161 
03162 //-------------------------------------------------------------------
03163 // Destructor 
03164 //-------------------------------------------------------------------
03165 CoinMpsIO::~CoinMpsIO ()
03166 {
03167   gutsOfDestructor();
03168 }
03169 
03170 //----------------------------------------------------------------
03171 // Assignment operator 
03172 //-------------------------------------------------------------------
03173 CoinMpsIO &
03174 CoinMpsIO::operator=(const CoinMpsIO& rhs)
03175 {
03176   if (this != &rhs) {    
03177     gutsOfDestructor();
03178     if ( rhs.rowlower_ !=NULL || rhs.collower_ != NULL) {
03179       gutsOfCopy(rhs);
03180     }
03181     defaultHandler_ = rhs.defaultHandler_;
03182     if (defaultHandler_)
03183       handler_ = new CoinMessageHandler(*rhs.handler_);
03184     else
03185       handler_ = rhs.handler_;
03186     messages_ = CoinMessage();
03187   }
03188   return *this;
03189 }
03190 
03191 //-------------------------------------------------------------------
03192 void CoinMpsIO::gutsOfDestructor()
03193 {  
03194   freeAll();
03195   if (defaultHandler_) {
03196     delete handler_;
03197     handler_ = NULL;
03198   }
03199   delete cardReader_;
03200   cardReader_ = NULL;
03201 }
03202 
03203 
03204 void CoinMpsIO::freeAll()
03205 {  
03206   releaseRedundantInformation();
03207   releaseRowNames();
03208   releaseColumnNames();
03209   delete matrixByRow_;
03210   delete matrixByColumn_;
03211   matrixByRow_=NULL;
03212   matrixByColumn_=NULL;
03213   free(rowlower_);
03214   free(rowupper_);
03215   free(collower_);
03216   free(colupper_);
03217   free(objective_);
03218   free(integerType_);
03219   free(fileName_);
03220   rowlower_=NULL;
03221   rowupper_=NULL;
03222   collower_=NULL;
03223   colupper_=NULL;
03224   objective_=NULL;
03225   integerType_=NULL;
03226   fileName_=NULL;
03227   free(problemName_);
03228   free(objectiveName_);
03229   free(rhsName_);
03230   free(rangeName_);
03231   free(boundName_);
03232   problemName_=NULL;
03233   objectiveName_=NULL;
03234   rhsName_=NULL;
03235   rangeName_=NULL;
03236   boundName_=NULL;
03237 }
03238 
03239 /* Release all information which can be re-calculated e.g. rowsense
03240     also any row copies OR hash tables for names */
03241 void CoinMpsIO::releaseRedundantInformation()
03242 {  
03243   free( rowsense_);
03244   free( rhs_);
03245   free( rowrange_);
03246   rowsense_=NULL;
03247   rhs_=NULL;
03248   rowrange_=NULL;
03249   free (hash_[0]);
03250   free (hash_[1]);
03251   hash_[0]=0;
03252   hash_[1]=0;
03253   delete matrixByRow_;
03254   matrixByRow_=NULL;
03255 }
03256 // Pass in Message handler (not deleted at end)
03257 void 
03258 CoinMpsIO::passInMessageHandler(CoinMessageHandler * handler)
03259 {
03260   if (defaultHandler_) 
03261     delete handler_;
03262   defaultHandler_=false;
03263   handler_=handler;
03264 }
03265 // Set language
03266 void 
03267 CoinMpsIO::newLanguage(CoinMessages::Language language)
03268 {
03269   messages_ = CoinMessage(language);
03270 }
03271 
03272 /* Read in a quadratic objective from the given filename.  
03273    If filename is NULL then continues reading from previous file.  If
03274    not then the previous file is closed.
03275    
03276    No assumption is made on symmetry, positive definite etc.
03277    No check is made for duplicates or non-triangular
03278    
03279    Returns number of errors
03280 */
03281 int 
03282 CoinMpsIO::readQuadraticMps(const char * filename,
03283                             int * &columnStart, int * &column2, double * &elements,
03284                             int checkSymmetry)
03285 {
03286   // Deal with filename - +1 if new, 0 if same as before, -1 if error
03287   FILE *fp=NULL;
03288   gzFile gzfp=NULL;
03289   int returnCode = dealWithFileName(filename,"",fp,gzfp);
03290   if (returnCode<0) {
03291     return -1;
03292   } else if (returnCode>0) {
03293     delete cardReader_;
03294     cardReader_ = new CoinMpsCardReader ( fp , gzfp, this);
03295   }
03296 
03297   cardReader_->readToNextSection();
03298 
03299   // Skip NAME
03300   if ( cardReader_->whichSection (  ) == COIN_NAME_SECTION ) 
03301     cardReader_->readToNextSection();
03302   if ( cardReader_->whichSection (  ) == COIN_QUADRATIC_SECTION ) {
03303     // save name of section
03304     free(problemName_);
03305     problemName_=strdup(cardReader_->columnName());
03306   } else if ( cardReader_->whichSection (  ) == COIN_EOF_SECTION ) {
03307     handler_->message(COIN_MPS_EOF,messages_)<<fileName_
03308                                             <<CoinMessageEol;
03309     return -3;
03310   } else {
03311     handler_->message(COIN_MPS_BADFILE1,messages_)<<cardReader_->card()
03312                                                   <<cardReader_->cardNumber()
03313                                                  <<fileName_
03314                                                   <<CoinMessageEol;
03315     return -2;
03316   }
03317 
03318   int numberErrors = 0;
03319 
03320   // Guess at size of data
03321   int maximumNonZeros = 5 *numberColumns_;
03322   // Use malloc so can use realloc
03323   int * column = (int *) malloc(maximumNonZeros*sizeof(int));
03324   int * column2Temp = (int *) malloc(maximumNonZeros*sizeof(int));
03325   double * elementTemp = (double *) malloc(maximumNonZeros*sizeof(double));
03326 
03327   startHash(1);
03328   int numberElements=0;
03329 
03330   const double tinyElement = 1.0e-14;
03331   
03332   while ( cardReader_->nextField (  ) == COIN_QUADRATIC_SECTION ) {
03333     switch ( cardReader_->mpsType (  ) ) {
03334     case COIN_BLANK_COLUMN:
03335       if ( fabs ( cardReader_->value (  ) ) > tinyElement ) {
03336         if ( numberElements == maximumNonZeros ) {
03337           maximumNonZeros = ( 3 * maximumNonZeros ) / 2 + 1000;
03338           column = ( COINColumnIndex * )
03339             realloc ( column, maximumNonZeros * sizeof ( COINColumnIndex ) );
03340           column2Temp = ( COINColumnIndex * )
03341             realloc ( column2Temp, maximumNonZeros * sizeof ( COINColumnIndex ) );
03342           elementTemp = ( double * )
03343             realloc ( elementTemp, maximumNonZeros * sizeof ( double ) );
03344         }
03345         // get indices
03346         COINColumnIndex iColumn1 = findHash ( cardReader_->columnName (  ) , 1 );
03347         COINColumnIndex iColumn2 = findHash ( cardReader_->rowName (  ) , 1 );
03348 
03349         if ( iColumn1 >= 0 ) {
03350           if (iColumn2 >=0) {
03351             double value = cardReader_->value (  );
03352             column[numberElements]=iColumn1;
03353             column2Temp[numberElements]=iColumn2;
03354             elementTemp[numberElements++]=value;
03355           } else {
03356             numberErrors++;
03357             if ( numberErrors < 100 ) {
03358                   handler_->message(COIN_MPS_NOMATCHROW,messages_)
03359                     <<cardReader_->rowName()<<cardReader_->cardNumber()<<cardReader_->card()
03360                     <<CoinMessageEol;
03361             } else if (numberErrors > 100000) {
03362               handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
03363               return numberErrors;
03364             }
03365           }
03366         } else {
03367           numberErrors++;
03368           if ( numberErrors < 100 ) {
03369             handler_->message(COIN_MPS_NOMATCHCOL,messages_)
03370               <<cardReader_->columnName()<<cardReader_->cardNumber()<<cardReader_->card()
03371               <<CoinMessageEol;
03372           } else if (numberErrors > 100000) {
03373             handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
03374             return numberErrors;
03375           }
03376         }
03377       }
03378       break;
03379     default:
03380       numberErrors++;
03381       if ( numberErrors < 100 ) {
03382         handler_->message(COIN_MPS_BADIMAGE,messages_)<<cardReader_->cardNumber()
03383                                                       <<cardReader_->card()
03384                                                       <<CoinMessageEol;
03385       } else if (numberErrors > 100000) {
03386         handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
03387         return numberErrors;
03388       }
03389     }
03390   }
03391   stopHash(1);
03392   // Do arrays as new [] and make column ordered
03393   columnStart = new int [numberColumns_+1];
03394   // for counts
03395   int * count = new int[numberColumns_];
03396   memset(count,0,numberColumns_*sizeof(int));
03397   CoinBigIndex i;
03398   // See about lower triangular
03399   if (checkSymmetry&&numberErrors) 
03400     checkSymmetry=2; // force corrections
03401   if (checkSymmetry) {
03402     if (checkSymmetry==1) {
03403       // just check lower triangular
03404       for ( i = 0; i < numberElements; i++ ) {
03405         int iColumn = column[i];
03406         int iColumn2 = column2Temp[i];
03407         if (iColumn2<iColumn) {
03408           numberErrors=-4;
03409           column[i]=iColumn2;
03410           column2Temp[i]=iColumn;
03411         }
03412       }
03413     } else {
03414       // make lower triangular
03415       for ( i = 0; i < numberElements; i++ ) {
03416         int iColumn = column[i];
03417         int iColumn2 = column2Temp[i];
03418         if (iColumn2<iColumn) {
03419           column[i]=iColumn2;
03420           column2Temp[i]=iColumn;
03421         }
03422       }
03423     }
03424   }
03425   for ( i = 0; i < numberElements; i++ ) {
03426     int iColumn = column[i];
03427     count[iColumn]++;
03428   }
03429   // Do starts
03430   int number = 0;
03431   columnStart[0]=0;
03432   for (i=0;i<numberColumns_;i++) {
03433     number += count[i];
03434     count[i]= columnStart[i];
03435     columnStart[i+1]=number;
03436   }
03437   column2 = new int[numberElements];
03438   elements = new double[numberElements];
03439 
03440   // Get column ordering
03441   for ( i = 0; i < numberElements; i++ ) {
03442     int iColumn = column[i];
03443     int iColumn2 = column2Temp[i];
03444     int put = count[iColumn];
03445     elements[put]=elementTemp[i];
03446     column2[put++]=iColumn2;
03447     count[iColumn]=put;
03448   }
03449   free(column);
03450   free(column2Temp);
03451   free(elementTemp);
03452 
03453   // Now in column order - deal with duplicates
03454   for (i=0;i<numberColumns_;i++) 
03455     count[i] = -1;
03456 
03457   int start = 0;
03458   number=0;
03459   for (i=0;i<numberColumns_;i++) {
03460     int j;
03461     for (j=start;j<columnStart[i+1];j++) {
03462       int iColumn2 = column2[j];
03463       if (count[iColumn2]<0) {
03464         count[iColumn2]=j;
03465       } else {
03466         // duplicate
03467         int iOther = count[iColumn2];
03468         double value = elements[iOther]+elements[j];
03469         elements[iOther]=value;
03470         elements[j]=0.0;
03471       }
03472     }
03473     for (j=start;j<columnStart[i+1];j++) {
03474       int iColumn2 = column2[j];
03475       count[iColumn2]=-1;
03476       double value = elements[j];
03477       if (value) {
03478         column2[number]=iColumn2;
03479         elements[number++]=value;
03480       }
03481     }
03482     start = columnStart[i+1];
03483     columnStart[i+1]=number;
03484   }
03485 
03486   delete [] count;
03487   return numberErrors;
03488 }
03489 /* Read in a list of cones from the given filename.  
03490    If filename is NULL (or same) then continues reading from previous file.
03491    If not then the previous file is closed.  Code should be added to
03492    general MPS reader to read this if CSECTION
03493    
03494    No checking is done that in unique cone
03495    
03496    Arrays should be deleted by delete []
03497    
03498    Returns number of errors, -1 bad file, -2 no conic section, -3 empty section
03499    
03500    columnStart is numberCones+1 long, other number of columns in matrix
03501 */
03502 int 
03503 CoinMpsIO::readConicMps(const char * filename,
03504                      int * &columnStart, int * &column, int & numberCones)
03505 {
03506   // Deal with filename - +1 if new, 0 if same as before, -1 if error
03507   FILE *fp=NULL;
03508   gzFile gzfp=NULL;
03509   int returnCode = dealWithFileName(filename,"",fp,gzfp);
03510   if (returnCode<0) {
03511     return -1;
03512   } else if (returnCode>0) {
03513     delete cardReader_;
03514     cardReader_ = new CoinMpsCardReader ( fp , gzfp, this);
03515   }
03516 
03517   cardReader_->readToNextSection();
03518 
03519   // Skip NAME
03520   if ( cardReader_->whichSection (  ) == COIN_NAME_SECTION ) 
03521     cardReader_->readToNextSection();
03522   numberCones=0;
03523 
03524   // Get arrays
03525   columnStart = new int [numberColumns_+1];
03526   column = new int [numberColumns_];
03527   int numberErrors = 0;
03528   columnStart[0]=0;
03529   int numberElements=0;
03530   startHash(1);
03531   
03532   //if (cardReader_->whichSection()==COIN_CONIC_SECTION) 
03533   //cardReader_->cleanCard(); // skip doing last
03534   while ( cardReader_->nextField (  ) == COIN_CONIC_SECTION ) {
03535     // should check QUAD
03536     // Have to check by hand
03537     if (!strncmp(cardReader_->card(),"CSECTION",8)) {
03538       if (numberElements==columnStart[numberCones]) {
03539         printf("Cone must have at least one column\n");
03540         abort();
03541       }
03542       columnStart[++numberCones]=numberElements;
03543       continue;
03544     }
03545     COINColumnIndex iColumn1;
03546     switch ( cardReader_->mpsType (  ) ) {
03547     case COIN_BLANK_COLUMN:
03548       // get index
03549       iColumn1 = findHash ( cardReader_->columnName (  ) , 1 );
03550       
03551       if ( iColumn1 >= 0 ) {
03552         column[numberElements++]=iColumn1;
03553       } else {
03554         numberErrors++;
03555         if ( numberErrors < 100 ) {
03556           handler_->message(COIN_MPS_NOMATCHCOL,messages_)
03557             <<cardReader_->columnName()<<cardReader_->cardNumber()<<cardReader_->card()
03558             <<CoinMessageEol;
03559         } else if (numberErrors > 100000) {
03560           handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
03561           return numberErrors;
03562         }
03563       }
03564       break;
03565     default:
03566       numberErrors++;
03567       if ( numberErrors < 100 ) {
03568         handler_->message(COIN_MPS_BADIMAGE,messages_)<<cardReader_->cardNumber()
03569                                                       <<cardReader_->card()
03570                                                       <<CoinMessageEol;
03571       } else if (numberErrors > 100000) {
03572         handler_->message(COIN_MPS_RETURNING,messages_)<<CoinMessageEol;
03573         return numberErrors;
03574       }
03575     }
03576   }
03577   if ( cardReader_->whichSection (  ) == COIN_ENDATA_SECTION ) {
03578     // Error if no cones
03579     if (!numberElements) {
03580       handler_->message(COIN_MPS_EOF,messages_)<<fileName_
03581                                                <<CoinMessageEol;
03582       delete [] columnStart;
03583       delete [] column;
03584       columnStart = NULL;
03585       column = NULL;
03586       return -3;
03587     } else {
03588       columnStart[++numberCones]=numberElements;
03589     }
03590   } else {
03591     handler_->message(COIN_MPS_BADFILE1,messages_)<<cardReader_->card()
03592                                                   <<cardReader_->cardNumber()
03593                                                  <<fileName_
03594                                                   <<CoinMessageEol;
03595     delete [] columnStart;
03596     delete [] column;
03597     columnStart = NULL;
03598     column = NULL;
03599     numberCones=0;
03600     return -2;
03601   }
03602 
03603   stopHash(1);
03604   return numberErrors;
03605 }

Generated on Wed Dec 3 14:34:20 2003 for Coin by doxygen 1.3.5