Merge remote-tracking branch 'origin/master' into windows
[scilab.git] / scilab / modules / polynomials / sci_gateway / cpp / sci_poly.cpp
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2012 - Scilab Enterprises - Cedric DELAMARRE
4  * Copyright (C) 2015 - Scilab Enterprises - Anais AUBERT
5  *
6  * Copyright (C) 2012 - 2016 - Scilab Enterprises
7  *
8  * This file is hereby licensed under the terms of the GNU GPL v2.0,
9  * pursuant to article 5.3.4 of the CeCILL v.2.1.
10  * This file was originally licensed under the terms of the CeCILL v2.1,
11  * and continues to be available under such terms.
12  * For more information, see the COPYING file which you should have received
13  * along with this program.
14  *
15  */
16 /*--------------------------------------------------------------------------*/
17 #include "polynomials_gw.hxx"
18 #include "function.hxx"
19 #include "double.hxx"
20 #include "string.hxx"
21 #include "polynom.hxx"
22 #include "overload.hxx"
23 #include "context.hxx"
24 #include "execvisitor.hxx"
25
26 extern "C"
27 {
28 #include <math.h>
29 #include "Scierror.h"
30 #include "localization.h"
31 #include "elem_common.h"
32
33     extern int C2F(dprxc)(int*, double*, double*);
34     extern int C2F(wprxc)(int*, double*, double*, double*, double*);
35     extern double C2F(dasum)(int*, double*, int*);
36 }
37 /*--------------------------------------------------------------------------*/
38 types::Function::ReturnValue sci_poly(types::typed_list &in, int _iRetCount, types::typed_list &out)
39 {
40     types::Double* pDblIn    = NULL;
41     types::String* pStrName  = NULL;
42     types::Polynom* pPolyOut = NULL;
43
44     std::string strFlag = "roots"; // roots (default), coeff
45
46     if (in.size() < 2 || in.size() > 3)
47     {
48         Scierror(77, _("%s: Wrong number of input argument(s): %d to %d expected.\n"), "poly", 2, 3);
49         return types::Function::Error;
50     }
51
52     if (_iRetCount > 1)
53     {
54         Scierror(78, _("%s: Wrong number of output argument(s): %d expected.\n"), "poly", 1);
55         return types::Function::Error;
56     }
57
58     if (in[0]->isDouble() == false)
59     {
60         std::string stFuncName = "%" + in[0]->getShortTypeStr() + "_poly";
61         return Overload::call(stFuncName, in, _iRetCount, out);
62     }
63
64     pDblIn = in[0]->getAs<types::Double>();
65
66     if (in.size() == 3)
67     {
68         if (in[2]->isString() == false)
69         {
70             Scierror(999, _("%s: Wrong type for input argument #%d : string expected.\n"), "poly", 3);
71             return types::Function::Error;
72         }
73
74         strFlag = in[2]->getAs<types::String>()->get(0);
75         if (strFlag != "roots" && strFlag != "coeff" && strFlag != "r" && strFlag != "c")
76         {
77             Scierror(999, _("%s: Wrong value for input argument #%d : ""%s"" or ""%s"" expected.\n"), "poly", 3, "roots", "coeff");
78             return types::Function::Error;
79         }
80     }
81
82     if (in[1]->isString() == false)
83     {
84         Scierror(999, _("%s: Wrong type for input argument #%d : string expected.\n"), "poly", 2);
85         return types::Function::Error;
86     }
87
88     pStrName = in[1]->getAs<types::String>();
89     if (pStrName->isScalar() == false)
90     {
91         Scierror(999, _("%s: Wrong size for input argument #%d : A scalar expected.\n"), "poly", 2);
92         return types::Function::Error;
93     }
94
95     std::string strName = pStrName->get(0);
96     size_t badpos = strName.find_first_not_of("$abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
97     if (badpos != std::wstring::npos)
98     {
99         Scierror(999, _("%s: Wrong value for input argument #%d : Valid variable name expected.\n"), "poly", 2);
100         return types::Function::Error;
101     }
102
103     if (strFlag == "roots" || strFlag == "r") // roots
104     {
105         // [] case
106         if (pDblIn->getSize() == 0)
107         {
108             int iRank = 0;
109             types::Polynom* pPolyOut = new types::Polynom(strName, 1, 1, &iRank);
110             double* pdblCoef = pPolyOut->get(0)->get();
111             *pdblCoef = 1;
112             out.push_back(pPolyOut);
113             return types::Function::OK;
114         }
115
116         bool bDeleteInput = false;
117         if (pDblIn->getSize() != 1 && pDblIn->getCols() == pDblIn->getRows())
118         {
119             //call spec
120             types::typed_list tlInput;
121             types::typed_list tlOutput;
122             types::optional_list tlOpt;
123             tlInput.push_back(pDblIn);
124             types::Function *funcSpec = symbol::Context::getInstance()->get(symbol::Symbol("spec"))->getAs<types::Function>();
125             funcSpec->call(tlInput, tlOpt, 1, tlOutput);
126             pDblIn = tlOutput[0]->getAs<types::Double>();
127             bDeleteInput = true;
128         }
129
130         int iOne = 1;
131         double* pdblInReal = pDblIn->get();
132         int piDimsArray[2] = {1, 1};
133         int iSize = pDblIn->getSize();
134         int iRanks = iSize;
135         pPolyOut = new types::Polynom(strName, 2, piDimsArray, &iRanks);
136         double* pdblCoefReal = pPolyOut->get(0)->get();
137         if (pDblIn->isComplex())
138         {
139             double dblEps = nc_eps_machine();
140             pPolyOut->setComplex(true);
141             double* pdblInImg   = pDblIn->getImg();
142             double* pdblCoefImg = pPolyOut->get(0)->getImg();
143             C2F(wprxc)(&iRanks, pdblInReal, pdblInImg, pdblCoefReal, pdblCoefImg);
144             bool bSetCplx = false;
145             for (int k = 0; k < iRanks; k++)
146             {
147                 if ((pdblCoefReal[k] + pdblCoefImg[k]) != pdblCoefReal[k])
148                 {
149                     bSetCplx = true;
150                     break;
151                 }
152             }
153             pPolyOut->setComplex(bSetCplx);
154         }
155         else
156         {
157             C2F(dprxc)(&iRanks, pdblInReal, pdblCoefReal);
158         }
159
160         if (bDeleteInput)
161         {
162             delete pDblIn;
163         }
164     }
165     else // coeff
166     {
167         // [] case
168         if (pDblIn->getSize() == 0)
169         {
170             out.push_back(types::Double::Empty());
171             return types::Function::OK;
172         }
173
174         if (pDblIn->getRows() != 1 && pDblIn->getCols() != 1)
175         {
176             Scierror(999, _("%s: Wrong size for input argument #%d : A vector expected.\n"), "poly", 1);
177             return types::Function::Error;
178         }
179
180         int piDimsArray[2] = {1, 1};
181         int iRanks = pDblIn->getSize() - 1;
182         pPolyOut = new types::Polynom(strName, 2, piDimsArray, &iRanks);
183         pPolyOut->setComplex(pDblIn->isComplex());
184         pPolyOut->setCoef(0, pDblIn);
185     }
186
187     out.push_back(pPolyOut);
188     return types::Function::OK;
189 }
190 /*--------------------------------------------------------------------------*/
191