e4ced157e511c39ea7e7f9802b472e0be3f73495
[scilab.git] / scilab / modules / elementary_functions / sci_gateway / cpp / sci_gsort.cpp
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2012 - DIGITEO - Cedric DELAMARRE
4  * Copyright (C) 2012 - 2016 - Scilab Enterprises
5  * Copyright (C) 2018 - Samuel GOUGEON
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 "elem_func_gw.hxx"
17 #include "function.hxx"
18 #include "double.hxx"
19 #include "string.hxx"
20 #include "overload.hxx"
21 #include "gsort.hxx"
22 #include "context.hxx"
23
24 extern "C"
25 {
26 #include "Scierror.h"
27 #include "localization.h"
28 }
29
30 /*--------------------------------------------------------------------------*/
31 types::Function::ReturnValue sci_gsort(types::typed_list &in, int _iRetCount, types::typed_list &out)
32 {
33     // In all cases, to later test in[0]:
34     if (in.size() < 1)
35     {
36         Scierror(77, _("%s: Wrong number of input argument(s): At least %d expected.\n"), "gsort", 1);
37         return types::Function::Error;
38     }
39     // The maximal number of input args may depend on the input data type, due to specific options
40
41     //
42     // Special cases
43     //
44     if (in[0]->isGenericType() == false)
45     {
46         // custom types
47         std::wstring wstFuncName = L"%" + in[0]->getShortTypeStr() + L"_gsort";
48         return Overload::call(wstFuncName, in, _iRetCount, out);
49     }
50     types::GenericType* pGTIn = in[0]->getAs<types::GenericType>();
51     if (pGTIn->getDims() > 2)
52     {
53         // hypermatrix
54         return Overload::call(L"%hm_gsort", in, _iRetCount, out);
55     }
56     if (pGTIn->isSparse())
57     {
58         // sparse
59         std::wstring wstFuncName = L"%" + in[0]->getShortTypeStr() + L"_gsort";
60         return Overload::call(wstFuncName, in, _iRetCount, out);
61     }
62     if (pGTIn->isComplex() && symbol::Context::getInstance()->getFunction(symbol::Symbol(L"%_gsort")))
63     {
64         // complex is documented as being managed through overloading
65         std::wstring wstFuncName = L"%" + in[0]->getShortTypeStr() + L"_gsort";
66         return Overload::call(wstFuncName, in, _iRetCount, out);
67     }
68
69     //
70     // Common case
71     //
72
73     if (in.size() > 3)
74     {
75         Scierror(77, _("%s: Wrong number of input argument(s): %d to %d expected.\n"), "gsort", 1, 3);
76         return types::Function::Error;
77     }
78
79     if (_iRetCount > 2)
80     {
81         Scierror(78, _("%s: Wrong number of output argument(s): %d to %d expected.\n"), "gsort", 1, 2);
82         return types::Function::Error;
83     }
84
85     // Get the sorting order
86     std::wstring wstrWay = L"d";
87     if (in.size() > 2)
88     {
89         if (in[2]->isString() == false)
90         {
91             Scierror(999, _("%s: Wrong type for input argument #%d : string expected.\n"), "gsort", 3);
92             return types::Function::Error;
93         }
94
95         wstrWay = in[2]->getAs<types::String>()->get(0);
96         if (wstrWay != L"i" && wstrWay != L"d")
97         {
98             Scierror(999, _("%s: Wrong value for input argument #%d: %s expected.\n"), "gsort", 3, "'i'|'d'");
99             return types::Function::Error;
100         }
101     }
102
103     // Get the sorting method
104     std::wstring wstrProcess = L"g";
105     if (in.size() >= 2)
106     {
107         if (in[1]->isString() == false)
108         {
109             Scierror(999, _("%s: Wrong type for input argument #%d : string expected.\n"), "gsort", 2);
110             return types::Function::Error;
111         }
112
113         wstrProcess = in[1]->getAs<types::String>()->get(0);
114
115         if ( wstrProcess != L"c"  &&
116                 wstrProcess != L"r"  &&
117                 wstrProcess != L"g"  &&
118                 wstrProcess != L"lc" &&
119                 wstrProcess != L"lr")
120         {
121             Scierror(999, _("%s: Wrong value for input argument #%d: ['g' 'r' 'c' 'lc' 'lr'] expected.\n"), "gsort", 2);
122             return types::Function::Error;
123         }
124     }
125
126     // Get data and perform operation for each types::
127     types::Double* pDblInd = NULL;
128     if (_iRetCount == 2)
129     {
130         int iRowsInd = (wstrProcess == L"lc") ? 1 : pGTIn->getRows();
131         int iColsInd = (wstrProcess == L"lr") ? 1 : pGTIn->getCols();
132
133         pDblInd = new types::Double(iRowsInd, iColsInd);
134     }
135
136     if (in[0]->isDouble()) // double
137     {
138         types::Double* pDblIn = in[0]->getAs<types::Double>();
139         types::Double* pDblOut = gsort(pDblIn, pDblInd, wstrWay, wstrProcess);
140         out.push_back(pDblOut);
141     }
142     else if (in[0]->isString()) // string
143     {
144         types::String* pStringIn = in[0]->getAs<types::String>();
145         types::String* pStringOut = gsort(pStringIn, pDblInd, wstrWay, wstrProcess);
146         out.push_back(pStringOut);
147     }
148     else if (in[0]->isInt8()) // int
149     {
150         types::Int8* pIIn = in[0]->getAs<types::Int8>();
151         types::Int8* pIOut = gsort(pIIn, pDblInd, wstrWay, wstrProcess);
152         out.push_back(pIOut);
153     }
154     else if (in[0]->isInt16())
155     {
156         types::Int16* pIIn = in[0]->getAs<types::Int16>();
157         types::Int16* pIOut = gsort(pIIn, pDblInd, wstrWay, wstrProcess);
158         out.push_back(pIOut);
159     }
160     else if (in[0]->isInt32())
161     {
162         types::Int32* pIIn = in[0]->getAs<types::Int32>();
163         types::Int32* pIOut = gsort(pIIn, pDblInd, wstrWay, wstrProcess);
164         out.push_back(pIOut);
165     }
166     else if (in[0]->isInt64())
167     {
168         types::Int64* pIIn = in[0]->getAs<types::Int64>();
169         types::Int64* pIOut = gsort(pIIn, pDblInd, wstrWay, wstrProcess);
170         out.push_back(pIOut);
171     }
172     else if (in[0]->isUInt8()) // uint
173     {
174         types::UInt8* pIIn = in[0]->getAs<types::UInt8>();
175         types::UInt8* pIOut = gsort(pIIn, pDblInd, wstrWay, wstrProcess);
176         out.push_back(pIOut);
177     }
178     else if (in[0]->isUInt16())
179     {
180         types::UInt16* pIIn = in[0]->getAs<types::UInt16>();
181         types::UInt16* pIOut = gsort(pIIn, pDblInd, wstrWay, wstrProcess);
182         out.push_back(pIOut);
183     }
184     else if (in[0]->isUInt32())
185     {
186         types::UInt32* pIIn = in[0]->getAs<types::UInt32>();
187         types::UInt32* pIOut = gsort(pIIn, pDblInd, wstrWay, wstrProcess);
188         out.push_back(pIOut);
189     }
190     else if (in[0]->isUInt64())
191     {
192         types::UInt64* pIIn = in[0]->getAs<types::UInt64>();
193         types::UInt64* pIOut = gsort(pIIn, pDblInd, wstrWay, wstrProcess);
194         out.push_back(pIOut);
195     }
196     else    // Other generic data types not supported
197     {
198         std::wstring wstFuncName = L"%" + in[0]->getShortTypeStr() + L"_gsort";
199         return Overload::call(wstFuncName, in, _iRetCount, out);
200     }
201
202     // Returns indices when requested
203     if (_iRetCount == 2)
204     {
205         out.push_back(pDblInd);
206     }
207
208     return types::Function::OK;
209 }
210 /*--------------------------------------------------------------------------*/