elementary_functions module.
[scilab.git] / scilab / modules / elementary_functions / sci_gateway / cpp / sci_matrix.cpp
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2011 - DIGITEO - Antoine ELIAS
4  * Copyright (C) 2012 - DIGITEO - Cedric DELAMARRE
5  *
6  * This file must be used under the terms of the CeCILL.
7  * This source file is licensed as described in the file COPYING, which
8  * you should have received as part of this distribution.  The terms
9  * are also available at
10  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
11  *
12  */
13 /*--------------------------------------------------------------------------*/
14 #include "elem_func_gw.hxx"
15 #include "function.hxx"
16 #include "double.hxx"
17 #include "string.hxx"
18 #include "overload.hxx"
19 #include "execvisitor.hxx"
20
21
22 extern "C"
23 {
24 #include "Scierror.h"
25 #include "localization.h"
26 }
27
28 /*--------------------------------------------------------------------------*/
29 types::Function::ReturnValue sci_matrix(types::typed_list &in, int _iRetCount, types::typed_list &out)
30 {
31     types::GenericType* pGTOut = NULL;
32     int* piSizes    = NULL;
33     int iDims       = 0;
34     int iLeastOne   = -1;
35     int newSize     = 1;
36     bool bOk        = false;
37
38     if (in.size() < 1 )
39     {
40         ScierrorW(77, _W("%ls: Wrong number of input argument(s): At most %d expected.\n"), L"matrix", 2);
41         return types::Function::Error;
42     }
43
44     if (_iRetCount > 1)
45     {
46         ScierrorW(78, _W("%ls: Wrong number of output argument(s): %d expected.\n"), L"matrix", 1);
47         return types::Function::Error;
48     }
49
50     if (in[0]->isGenericType() == false)
51     {
52         std::wstring wstFuncName = L"%"  + in[0]->getShortTypeStr() + L"_matrix";
53         return Overload::call(wstFuncName, in, _iRetCount, out, new ExecVisitor());
54     }
55
56     pGTOut = in[0]->getAs<types::GenericType>()->clone()->getAs<types::GenericType>();
57
58     if (in.size() == 2)
59     {
60         if (in[1]->isDouble() == false)
61         {
62             ScierrorW(999, _W("%ls: Wrong type for input argument #%d : A real matrix expected.\n"), L"matrix", 2);
63             return types::Function::Error;
64         }
65
66         types::Double* pDblNewSize = in[1]->getAs<types::Double>();
67
68         if (pDblNewSize->isComplex())
69         {
70             ScierrorW(999, _W("%ls: Wrong type for input argument #%d : A real matrix expected.\n"), L"matrix", 2);
71             return types::Function::Error;
72         }
73
74         iDims = pDblNewSize->getSize();
75         piSizes = new int[iDims];
76
77         for (int i = 0; i < iDims; i++)
78         {
79             piSizes[i] = static_cast<int>(pDblNewSize->get(i));
80             if (piSizes[i] == -1)
81             {
82                 if (iLeastOne == -1)
83                 {
84                     iLeastOne = i;
85                 }
86                 else
87                 {
88                     ScierrorW(999, _W("%ls: Wrong value for input argument #%d : Only one value can be equal to %d.\n"), L"matrix", 2, -1);
89                     return types::Function::Error;
90                 }
91             }
92             else if (piSizes[i] < -1)
93             {
94                 ScierrorW(999, _W("%ls: Wrong value for input argument #%d : At most %d expected.\n"), L"matrix", 2, -1);
95                 return types::Function::Error;
96             }
97             else
98             {
99                 newSize *= piSizes[i];
100             }
101         }
102     }
103     else
104     {
105         iDims = in.size() - 1;
106         piSizes = new int[iDims];
107         for (int i = 1; i < in.size(); i++)
108         {
109             if (in[i]->isDouble() == false)
110             {
111                 ScierrorW(999, _W("%ls: Wrong type for input argument #%d : A real scalar expected.\n"), L"matrix", i + 1);
112                 return types::Function::Error;
113             }
114
115             types::Double* pDblNewSize = in[i]->getAs<types::Double>();
116
117             if (pDblNewSize->isComplex() || pDblNewSize->isScalar() == false)
118             {
119                 ScierrorW(999, _W("%ls: Wrong type for input argument #%d : A real scalar expected.\n"), L"matrix", i + 1);
120                 return types::Function::Error;
121             }
122
123             piSizes[i - 1] = static_cast<int>(pDblNewSize->get(0));
124             if (piSizes[i - 1] == -1)
125             {
126                 if (iLeastOne == -1)
127                 {
128                     iLeastOne = i - 1;
129                 }
130                 else
131                 {
132                     ScierrorW(999, _W("%ls: Wrong value for input argument #%d : Only one value can be equal to %d.\n"), L"matrix", i + 1, -1);
133                     return types::Function::Error;
134                 }
135             }
136             else if (piSizes[i - 1] < -1)
137             {
138                 ScierrorW(999, _W("%ls: Wrong value for input argument #%d : At most %d expected.\n"), L"matrix", i + 1, -1);
139                 return types::Function::Error;
140             }
141             else
142             {
143                 newSize *= piSizes[i - 1];
144             }
145         }
146     }
147
148     if (iLeastOne != -1)
149     {
150         piSizes[iLeastOne] = (int)pGTOut->getSize() / newSize;
151     }
152
153     if (pGTOut->isSparse() && iDims > 2)
154     {
155         ScierrorW(999, _W("%ls: Wrong value for input argument(s) : Sparse matrix cannot be reshaped beyond %d dimensions.\n"), L"matrix", 2);
156         return types::Function::Error;
157     }
158
159     bOk = pGTOut->reshape(piSizes, iDims);
160
161     if (bOk == false)
162     {
163         ScierrorW(999, _W("%ls: Input and output matrices must have the same number of elements.\n"), L"matrix");
164         return types::Function::Error;
165     }
166
167     delete[] piSizes;
168
169     out.push_back(pGTOut);
170     return types::Function::OK;
171 }
172 /*--------------------------------------------------------------------------*/