Coverity #1350601 Fixed
[scilab.git] / scilab / modules / linear_algebra / sci_gateway / cpp / sci_lsq.cpp
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2011 - DIGITEO - 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
17 #include "linear_algebra_gw.hxx"
18 #include "function.hxx"
19 #include "double.hxx"
20 #include "overload.hxx"
21
22 extern "C"
23 {
24 #include "localization.h"
25 #include "Scierror.h"
26 #include "lsq.h"
27 #include "doublecomplex.h"
28 }
29 /*--------------------------------------------------------------------------*/
30
31 types::Function::ReturnValue sci_lsq(types::typed_list &in, int _iRetCount, types::typed_list &out)
32 {
33     types::Double* pDbl[2]      = {NULL, NULL};
34     types::Double* pDblResult   = NULL;
35     double* pData[2]            = {NULL, NULL};
36     double* pResult             = NULL;
37     double* pdTol               = NULL;
38     bool bComplexArgs           = false;
39     int iRank                   = 0;
40     double dblTol               = 0.0; 
41
42     if (in.size() < 2 || in.size() > 3)
43     {
44         Scierror(77, _("%s: Wrong number of input argument(s): %d to %d expected.\n"), "lsq", 2, 3);
45         return types::Function::Error;
46     }
47
48     if (_iRetCount > 2)
49     {
50         Scierror(78, _("%s: Wrong number of output argument(s): %d to %d expected.\n"), "lsq", 1, 2);
51         return types::Function::Error;
52     }
53
54     if ((in[0]->isDouble() == false))
55     {
56         std::wstring wstFuncName = L"%" + in[0]->getShortTypeStr() + L"_lsq";
57         return Overload::call(wstFuncName, in, _iRetCount, out);
58     }
59
60     pDbl[0] = in[0]->getAs<types::Double>()->clone()->getAs<types::Double>();
61
62     if (in.size() <=  3)
63     {
64         if ((in[1]->isDouble() == false))
65         {
66             std::wstring wstFuncName = L"%" + in[1]->getShortTypeStr() + L"_lsq";
67             return Overload::call(wstFuncName, in, _iRetCount, out);
68         }
69         pDbl[1] = in[1]->getAs<types::Double>()->clone()->getAs<types::Double>();
70     }
71
72     if (in.size() == 3)
73     {
74         if ((in[2]->isDouble() == false) || (in[2]->getAs<types::Double>()->isComplex()) || (in[2]->getAs<types::Double>()->isScalar() == false))
75         {
76             Scierror(256, _("%s: Wrong type for input argument #%d: A Real expected.\n"), "lsq", 3);
77             return types::Function::Error;
78         }
79
80         dblTol = in[2]->getAs<types::Double>()->get(0);
81         pdTol = &dblTol;
82     }
83
84     if (pDbl[0]->getRows() != pDbl[1]->getRows())
85     {
86         Scierror(265, _("%s: %s and %s must have equal number of rows.\n"), "lsq", "A", "B");
87         return types::Function::Error;
88     }
89
90     if ((pDbl[0]->getCols() == 0) || (pDbl[1]->getCols() == 0))
91     {
92         out.push_back(types::Double::Empty());
93         if (_iRetCount == 2)
94         {
95             out.push_back(types::Double::Empty());
96         }
97         return types::Function::OK;
98     }
99
100     if (pDbl[0]->isComplex() || pDbl[1]->isComplex())
101     {
102         bComplexArgs = true;
103     }
104     for (int i = 0; i < 2; i++)
105     {
106         if (pDbl[i]->getCols() == -1)
107         {
108             Scierror(271, _("%s: Size varying argument a*eye(), (arg %d) not allowed here.\n"), "lsq", i + 1);
109             return types::Function::Error;
110         }
111
112         if (bComplexArgs)
113         {
114             pData[i] = (double*)oGetDoubleComplexFromPointer(pDbl[i]->getReal(), pDbl[i]->getImg(), pDbl[i]->getSize());
115             if (!pData[i])
116             {
117                 Scierror(999, _("%s: Cannot allocate more memory.\n"), "lsq");
118                 return types::Function::Error;
119             }
120         }
121         else
122         {
123             pData[i] = pDbl[i]->getReal();
124         }
125     }
126
127     pDblResult = new types::Double(pDbl[0]->getCols(), pDbl[1]->getCols(), bComplexArgs);
128
129     if (bComplexArgs)
130     {
131         pResult = (double*)MALLOC(pDbl[0]->getCols() * pDbl[1]->getCols() * sizeof(doublecomplex));
132     }
133     else
134     {
135         pResult = pDblResult->get();
136     }
137
138     int iRet = iLsqM(pData[0], pDbl[0]->getRows(), pDbl[0]->getCols(), pData[1], pDbl[1]->getCols(), bComplexArgs, pResult, pdTol, ((_iRetCount == 2) ? &iRank : NULL));
139
140     if (iRet != 0)
141     {
142         if (iRet == -1)
143         {
144             Scierror(999, _("%s: Allocation failed.\n"),  "lsq");
145         }
146         else
147         {
148             Scierror(999, _("%s: LAPACK error n°%d.\n"),  "lsq", iRet);
149         }
150         return types::Function::Error;
151     }
152
153     if (bComplexArgs)
154     {
155         vGetPointerFromDoubleComplex((doublecomplex*)(pResult), pDblResult->getSize(), pDblResult->getReal(), pDblResult->getImg());
156         vFreeDoubleComplexFromPointer((doublecomplex*)pResult);
157         vFreeDoubleComplexFromPointer((doublecomplex*)pData[0]);
158         vFreeDoubleComplexFromPointer((doublecomplex*)pData[1]);
159     }
160
161     out.push_back(pDblResult);
162     if (_iRetCount == 2)
163     {
164         types::Double* pDblRank = new types::Double(1, 1);
165         pDblRank->set(0, iRank);
166         out.push_back(pDblRank);
167     }
168
169     return types::Function::OK;
170 }
171 /*--------------------------------------------------------------------------*/
172