Merge remote-tracking branch 'origin/master' into windows
[scilab.git] / scilab / modules / elementary_functions / sci_gateway / cpp / sci_size.cpp
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2012 - DIGITEO - Antoine ELIAS
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
18 #include <algorithm>
19
20 #include "elem_func_gw.hxx"
21 #include "types.hxx"
22 #include "string.hxx"
23 #include "container.hxx"
24 #include "getmode.hxx"
25 #include "overload.hxx"
26 #include "context.hxx"
27
28 extern "C"
29 {
30 #include "Scierror.h"
31 #include "localization.h"
32 #include "os_string.h"
33 }
34
35 /*--------------------------------------------------------------------------*/
36 types::Function::ReturnValue sci_size(types::typed_list &in, int _iRetCount, types::typed_list &out)
37 {
38     if (in.size() < 1)
39     {
40         Scierror(999, _("%s: Wrong number of input arguments: At least %d expected.\n"), "size", 1);
41         return types::Function::Error;
42     }
43
44     switch (in[0]->getType())
45     {
46         // Dedicated case for lists.
47         case types::InternalType::ScilabMList:
48         {
49             std::string stFuncName = "%" + in[0]->getShortTypeStr() + "_size";
50             Overload::call(stFuncName, in, _iRetCount, out);
51             break;
52         }
53         case types::InternalType::ScilabTList:
54         {
55             // calls the overload if it exists.
56             std::string stFuncName = "%"  + in[0]->getTypeStr() + "_size";
57             types::InternalType *pIT = symbol::Context::getInstance()->get(symbol::Symbol(stFuncName));
58             if (pIT)
59             {
60                 return Overload::call(stFuncName, in, _iRetCount, out);
61             }
62         }
63         case types::InternalType::ScilabList:
64         {
65             if (in.size() > 1)
66             {
67                 Scierror(999, _("%s: Wrong number of input argument(s): %d expected.\n"), "size", 1);
68                 return types::Function::Error;
69             }
70
71             types::Double* pD = new types::Double(in[0]->getAs<types::Container>()->getSize());
72             out.push_back(pD);
73             break;
74         }
75         default :
76             // All types inherits of GenericType, so have this algorithm as default.
77         {
78             if (in[0]->isGenericType() == false)
79             {
80                 std::string stFuncName = "%" + in[0]->getShortTypeStr() + "_size";
81                 return Overload::call(stFuncName, in, _iRetCount, out);
82             }
83             int iMode = -1;
84
85             if (in.size() > 2)
86             {
87                 Scierror(77, _("%s: Wrong number of input argument(s): %d to %d expected.\n"), "size", 1, 2);
88                 return types::Function::Error;
89             }
90
91             if (in.size() == 2)
92             {
93                 if (_iRetCount == 2)
94                 {
95                     Scierror(999, _("%s: Wrong number of output argument(s): %d expected.\n"), "size", 1);
96                     return types::Function::Error;
97                 }
98                 iMode = getMode(in, 1, 0);
99                 if (iMode == -2)
100                 {
101                     return types::Function::Error;
102                 }
103
104             }
105
106             int iDims = in[0]->getAs<types::GenericType>()->getDims();
107             int* piDims = in[0]->getAs<types::GenericType>()->getDimsArray();
108
109             if (_iRetCount == 1)
110             {
111                 int iRowsOut = 1;
112                 int iColsOut = 0;
113                 double* pdblReal = NULL;
114
115                 switch (iMode)
116                 {
117                     case -1 : //lhs == 1
118                         iColsOut = iDims;
119                         break;
120                     default : //"*"
121                         iColsOut = 1;
122                         break;
123                 }
124
125                 types::Double* pD = new types::Double(iRowsOut, iColsOut);
126
127                 double* pdbl = pD->getReal();
128
129                 switch (iMode)
130                 {
131                     case -1 : //lhs == 1
132                         for (int i = 0 ; i < iDims ; i++)
133                         {
134                             pdbl[i] = piDims[i];
135                         }
136                         break;
137                     case 0 : //"*"
138                         pdbl[0] = in[0]->getAs<types::GenericType>()->getSize();
139                         break;
140                     default : //"r"
141                         if (iMode > iDims)
142                         {
143                             pdbl[0] = 1;
144                             out.push_back(pD);
145                             return types::Function::OK;
146                         }
147
148                         iColsOut = 1;
149                         pdbl[0] = piDims[iMode - 1];
150                         break;
151                 }
152                 out.push_back(pD);
153             }
154             else
155             {
156                 for (int i = 0 ; i < std::min(_iRetCount, iDims) ; i++)
157                 {
158                     types::Double* pD = new types::Double(piDims[i]);
159                     out.push_back(pD);
160                 }
161
162                 /* Multiple returns:
163                  * example: [a b c]=size(M) */
164                 if (_iRetCount > iDims)
165                 {
166                     for (int i = iDims ; i < _iRetCount ; i++)
167                     {
168                         types::Double* pD = new types::Double(1);
169                         out.push_back(pD);
170                     }
171                 }
172             }
173             break;
174         }
175     }
176     return types::Function::OK;
177 }
178 /*--------------------------------------------------------------------------*/