Coverity #1321214, #1321215, #1321217, #1321220, #1321223, #1321224, #1321221, #13212...
[scilab.git] / scilab / modules / optimization / sci_gateway / cpp / sci_readmps.cpp
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2013 - Scilab Enterprises - Cedric DELAMARRE
4 *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13 *
14 */
15 /*--------------------------------------------------------------------------*/
16 #include "optimization_gw.hxx"
17 #include "function.hxx"
18 #include "double.hxx"
19 #include "string.hxx"
20 #include "tlist.hxx"
21 #include "numericconstants.hxx"
22
23 extern "C"
24 {
25 #include "localization.h"
26 #include "Scierror.h"
27 #include "elem_common.h"
28 #include "sci_malloc.h"
29
30     void C2F(rdmpsz)(int*, int*, int*, int*, int*, char*, int*);
31     int  C2F(clunit)(int*, char*, int*, int);
32     void C2F(rdmps1)(int*, char*, int*, int*, int*, int*, int*, int*, int*,
33                      double*, double*, double*, char*, char*, char*, char*,
34                      char*, int*, char*, char*, int*, int*, int*, int*, int*,
35                      int*, int*, int*, int*, double*, double*, double*,
36                      double*, double*, double*, int, int, int, int, int, int);
37 }
38 /*--------------------------------------------------------------------------*/
39 static int openMPSFile(types::String* pStrFilename, int* piMode, int* lunit);
40 /*--------------------------------------------------------------------------*/
41 types::Function::ReturnValue sci_readmps(types::typed_list &in, int _iRetCount, types::typed_list &out)
42 {
43     types::String* pStrFileName = NULL;
44
45     double dLowBnd  = 0;
46     double dUpBnd   = 0;
47     int iMaxM       = 0;
48     int iMaxN       = 0;
49     int iMaxNza     = 0;
50     int iM          = 0;
51     int iN          = 0;
52     int iNza        = 0;
53     int lunit       = 0; // file unit. 0 mean we open the file by this name.
54     int mlunit      = 0;
55     int piMode[2]   = { -1, 0};
56     int ierr        = 0;
57     int line        = 0;
58     char typrow[2];
59
60     wchar_t* wcsFileName = NULL;
61     char* strErrorBuf = new char[bsiz];
62
63     double big = NumericConstants::double_max;
64
65     if (in.size() < 2 || in.size() > 3)
66     {
67         Scierror(77, _("%s: Wrong number of input argument(s): %d to %d expected.\n"), "readmps", 2, 3);
68         return types::Function::Error;
69     }
70
71     if (_iRetCount > 1)
72     {
73         Scierror(78, _("%s: Wrong number of output argument(s): %d expected.\n"), "readmps", 1);
74         return types::Function::Error;
75     }
76
77     /*** get inputs arguments ***/
78     // get file name
79     if (in[0]->isString() == false)
80     {
81         Scierror(999, _("%s: Wrong type for input argument #%d: string expected.\n"), "readmps", 1);
82         return types::Function::Error;
83     }
84
85     pStrFileName = in[0]->getAs<types::String>();
86
87     if (pStrFileName->isScalar() == false)
88     {
89         Scierror(999, _("%s: Wrong type for input argument #%d: A scalar string expected.\n"), "readmps", 1);
90         return types::Function::Error;
91     }
92
93     // get Bounds
94     if (in[1]->isDouble() == false)
95     {
96         Scierror(999, _("%s: Wrong type for input argument #%d: A real vector expected.\n"), "readmps", 2);
97         return types::Function::Error;
98     }
99
100     types::Double* pDblBounds = in[1]->getAs<types::Double>();
101
102     if (pDblBounds->isComplex())
103     {
104         Scierror(999, _("%s: Wrong type for input argument #%d: A real vector expected.\n"), "readmps", 2);
105         return types::Function::Error;
106     }
107
108     if (pDblBounds->getSize() != 2)
109     {
110         Scierror(999, _("%s: Wrong size for input argument #%d: A real vector of size %d expected.\n"), "readmps", 2, 2);
111         return types::Function::Error;
112     }
113
114     dLowBnd = pDblBounds->get(0);
115     dUpBnd  = pDblBounds->get(1);
116
117     if (in.size() == 3)
118     {
119         // get Max sizes
120         if (in[2]->isDouble() == false)
121         {
122             Scierror(999, _("%s: Wrong type for input argument #%d: A real vector expected.\n"), "readmps", 3);
123             return types::Function::Error;
124         }
125
126         types::Double* pDblMaxSizes = in[2]->getAs<types::Double>();
127
128         if (pDblMaxSizes->isComplex())
129         {
130             Scierror(999, _("%s: Wrong type for input argument #%d: A real vector expected.\n"), "readmps", 3);
131             return types::Function::Error;
132         }
133
134         if (pDblMaxSizes->getSize() != 3)
135         {
136             Scierror(999, _("%s: Wrong size for input argument #%d: A real vector of size %d expected.\n"), "readmps", 3, 3);
137             return types::Function::Error;
138         }
139
140         iMaxM   = (int)pDblMaxSizes->get(0);
141         iMaxN   = (int)pDblMaxSizes->get(1);
142         iMaxNza = (int)pDblMaxSizes->get(2);
143     }
144     else
145     {
146         if (openMPSFile(pStrFileName, piMode, &lunit))
147         {
148             return types::Function::Error;
149         }
150
151         C2F(rdmpsz)(&lunit, &iMaxM, &iMaxN, &iMaxNza, &ierr, typrow, &line);
152         mlunit = -lunit;
153         C2F(clunit)(&mlunit, NULL, piMode, 0);
154
155         if (ierr == 1)
156         {
157             Scierror(998, _("%s: Error while reading line %d.\n"), "readmps", line);
158             return types::Function::Error;
159         }
160         else if (ierr == 2)
161         {
162             Scierror(999, _("%s: Unknown row type %s at line %d.\n"), "readmps", typrow, line);
163             return types::Function::Error;
164         }
165
166         lunit = 0;
167     }
168
169     iM   = iMaxM;
170     iN   = iMaxN;
171     iNza = iMaxNza;
172
173     /*** read MPS file ***/
174     if (openMPSFile(pStrFileName, piMode, &lunit))
175     {
176         return types::Function::Error;
177     }
178
179     // alloc data
180     char nameb[9]  = "        ";
181     char namec[9]  = "        ";
182     char namran[9] = "        ";
183     char nambnd[9] = "        ";
184     char nammps[9] = "        ";
185
186     char* pstrRwName = new char[8 * iM + 1];
187     pstrRwName[8 * iM] = '\0';
188     char* pstrClName = new char[8 * iN + 1];
189     pstrClName[8 * iN] = '\0';
190
191     int irobj       = 0;
192     int* piStavar   = new int[iN];
193     int* piRwstat   = new int[iM];
194     int* piRowcod   = new int[2 * iM];
195     int* piColcod   = new int[2 * iN];
196     int* piRwnmbs   = new int[iNza];
197     int* piClpnts   = new int[iN + 1];
198     int* piRow      = new int[iN];
199
200     types::Double* pDblCoef     = new types::Double(iNza, 1);
201     types::Double* pDblRhsb     = new types::Double(iM, 1);
202     types::Double* pDblRanges   = new types::Double(iM, 1);
203     types::Double* pDblBnds     = new types::Double(iN, 2);
204     double* pdblRelt            = new double[iN];
205
206     C2F(rdmps1)(&ierr, strErrorBuf, &iMaxM, &iMaxN, &iMaxNza,
207                 &iM, &iN, &iNza, &irobj, &big, &dLowBnd, &dUpBnd,
208                 namec, nameb, namran, nambnd, nammps, &lunit,
209                 pstrRwName, pstrClName,
210                 piStavar, piRwstat,
211                 piRowcod, piRowcod + iM,
212                 piColcod, piColcod + iN,
213                 piRwnmbs, piClpnts, piRow,
214                 pDblCoef->get(), pDblRhsb->get(), pDblRanges->get(),
215                 pDblBnds->get() + iN, pDblBnds->get(), pdblRelt,
216                 bsiz, 8L, 8L, 8L, 8L, 8L);
217
218     delete[] piRow;
219     delete[] pdblRelt;
220
221     mlunit = -lunit;
222     C2F(clunit)(&mlunit, NULL, piMode, 0);
223
224     if (ierr)
225     {
226         int iLen = 4096;
227         char* str = strErrorBuf + 4095;
228         while (*str == ' ')
229         {
230             iLen--;
231             str--;
232         }
233
234         strErrorBuf[iLen] = '\0';
235         Scierror(999, "%s", strErrorBuf);
236         delete[] strErrorBuf;
237         return types::Function::Error;
238     }
239
240     delete[] strErrorBuf;
241     /*** return output arguments ***/
242     types::String* pStr = NULL;
243     types::Double* pDbl = NULL;
244     double* pdbl        = NULL;
245
246     types::TList* pTL = new types::TList();
247     pStr = new types::String(1, 19);
248     pStr->set(0,  L"mps");
249     pStr->set(1,  L"irobj");
250     pStr->set(2,  L"namec");
251     pStr->set(3,  L"nameb");
252     pStr->set(4,  L"namran");
253     pStr->set(5,  L"nambnd");
254     pStr->set(6,  L"name");
255     pStr->set(7,  L"rownames");
256     pStr->set(8,  L"colnames");
257     pStr->set(9,  L"rowstat");
258     pStr->set(10, L"rowcode");
259     pStr->set(11, L"colcode");
260     pStr->set(12, L"rownmbs");
261     pStr->set(13, L"colpnts");
262     pStr->set(14, L"acoeff");
263     pStr->set(15, L"rhs");
264     pStr->set(16, L"ranges");
265     pStr->set(17, L"bounds");
266     pStr->set(18, L"stavar");
267     pTL->append(pStr);
268
269     pTL->append(new types::Double((double)irobj));
270     pTL->append(new types::String(namec));
271     pTL->append(new types::String(nameb));
272     pTL->append(new types::String(namran));
273     pTL->append(new types::String(nambnd));
274     pTL->append(new types::String(nammps));
275
276     pStr = new types::String(iM, 1);
277     for (int i = 0; i < iM; i++)
278     {
279         char pstrTemp[9];
280         memcpy(pstrTemp, pstrRwName + i * 8, 8);
281         pstrTemp[8] = '\0';
282         pStr->set(i, pstrTemp);
283     }
284     pTL->append(pStr);
285     delete[] pstrRwName;
286
287     pStr = new types::String(1, iN);
288     for (int i = 0; i < iN; i++)
289     {
290         char pstrTemp[9];
291         memcpy(pstrTemp, pstrClName + i * 8, 8);
292         pstrTemp[8] = '\0';
293         pStr->set(i, pstrTemp);
294     }
295     pTL->append(pStr);
296     delete[] pstrClName;
297
298     pDbl = new types::Double(iM, 1);
299     pdbl = pDbl->get();
300     for (int i = 0; i < iM; i++)
301     {
302         pdbl[i] = (double)piRwstat[i];
303     }
304     pTL->append(pDbl);
305     delete[] piRwstat;
306
307     pDbl = new types::Double(iM, 2);
308     pdbl = pDbl->get();
309     for (int i = 0; i < iM * 2; i++)
310     {
311         pdbl[i] = (double)piRowcod[i];
312     }
313     pTL->append(pDbl);
314     delete[] piRowcod;
315
316     pDbl = new types::Double(iN, 2);
317     pdbl = pDbl->get();
318     for (int i = 0; i < iN * 2; i++)
319     {
320         pdbl[i] = (double)piColcod[i];
321     }
322     pTL->append(pDbl);
323     delete[] piColcod;
324
325     pDbl = new types::Double(iNza, 1);
326     pdbl = pDbl->get();
327     for (int i = 0; i < iNza; i++)
328     {
329         pdbl[i] = (double)piRwnmbs[i];
330     }
331     pTL->append(pDbl);
332     delete[] piRwnmbs;
333
334     pDbl = new types::Double(1, iN + 1);
335     pdbl = pDbl->get();
336     for (int i = 0; i < iN + 1; i++)
337     {
338         pdbl[i] = (double)piClpnts[i];
339     }
340     pTL->append(pDbl);
341     delete[] piClpnts;
342
343     pTL->append(pDblCoef);
344     pTL->append(pDblRhsb);
345     pTL->append(pDblRanges);
346     pTL->append(pDblBnds);
347
348     pDbl = new types::Double(iN, 1);
349     pdbl = pDbl->get();
350     for (int i = 0; i < iN; i++)
351     {
352         pdbl[i] = (double)piStavar[i];
353     }
354     pTL->append(pDbl);
355     delete[] piStavar;
356
357     out.push_back(pTL);
358     return types::Function::OK;
359 }
360
361 int openMPSFile(types::String* _pStrFilename, int* _piMode, int* _lunit)
362 {
363     char* pstFilename = wide_string_to_UTF8(_pStrFilename->get(0));
364     int iErr = C2F(clunit)(_lunit, pstFilename, _piMode, (int)strlen(pstFilename));
365     if (iErr)
366     {
367         switch (iErr)
368         {
369             case 65  :
370                 Scierror(iErr, _("%s: %d logical unit already used.\n"), "readmps", *_lunit);
371                 break;
372             case 66  :
373                 Scierror(iErr, _("%s: Too many files opened!\n"), "readmps");
374                 break;
375             case 67  :
376                 Scierror(iErr, _("%s: Unknown file format.\n"), "readmps");
377                 break;
378             case 240 :
379                 Scierror(iErr, _("%s: File \"%s\" already exists or directory write access denied.\n"), "readmps", pstFilename);
380                 break;
381             case 241 :
382                 Scierror(iErr, _("%s: File \"%s\" does not exist or read access denied.\n"), "readmps", pstFilename);
383                 break;
384             default  :
385                 Scierror(iErr, _("%s: Can not open File \"%s\"\n"), "readmps", pstFilename);
386         }
387
388         FREE(pstFilename);
389         return 1;
390     }
391
392     FREE(pstFilename);
393     return 0;
394 }