* Bugs 7948 15825 fixed: gsort() multilevel sorting
[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 "polynom.hxx"
21 #include "overload.hxx"
22 #include "gsort.hxx"
23 #include "context.hxx"
24
25 extern "C"
26 {
27 #include "Scierror.h"
28 #include "localization.h"
29 }
30
31 /*--------------------------------------------------------------------------*/
32 types::Function::ReturnValue sci_gsort(types::typed_list &in, int _iRetCount, types::typed_list &out)
33 {
34     // In all cases, to later test in[0]:
35     if (in.size() < 1)
36     {
37         Scierror(77, _("%s: Wrong number of input argument(s): At least %d expected.\n"), "gsort", 1);
38         return types::Function::Error;
39     }
40
41     //
42     // Custom typeof
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     // Otherwise: max numbers of inputs / outputs
51     if (in.size() > 4 )
52     {
53         Scierror(77, _("%s: Wrong number of input arguments: %d to %d expected.\n"), "gsort", 1, 4);
54         return types::Function::Error;
55     }
56     if (_iRetCount > 2)
57     {
58         Scierror(78, _("%s: Wrong number of output argument(s): %d to %d expected.\n"), "gsort", 1, 2);
59         return types::Function::Error;
60     }
61
62     // Get the sorting method, always as argin#2 for all generic types
63     // ----------------------
64     std::wstring wstrProcess = L"g";
65     if (in.size() >= 2)
66     {
67         if (in[1]->isString() == false)
68         {
69             Scierror(999, _("%s: Wrong type for input argument #%d : string expected.\n"), "gsort", 2);
70             return types::Function::Error;
71         }
72
73         wstrProcess = in[1]->getAs<types::String>()->get(0);
74
75         if ( wstrProcess != L"c"  &&
76                 wstrProcess != L"r"  &&
77                 wstrProcess != L"g"  &&
78                 wstrProcess != L"lc" &&
79                 wstrProcess != L"lr")
80         {
81             Scierror(999, _("%s: Argument #%d: Must be in the set {%s}.\n"), "gsort", 2, "'g','r','c','lc','lr'");
82             return types::Function::Error;
83         }
84     }
85
86     types::GenericType* pGTIn = in[0]->getAs<types::GenericType>();
87         
88     if (pGTIn->getDims() > 2)
89     {
90         // hypermatrix
91         return Overload::call(L"%hm_gsort", in, _iRetCount, out);
92     }
93     if (pGTIn->isSparse())
94     {
95         // sparse
96         std::wstring wstFuncName = L"%" + in[0]->getShortTypeStr() + L"_gsort";
97         return Overload::call(wstFuncName, in, _iRetCount, out);
98     }
99     if (pGTIn->isDouble() && pGTIn->isComplex())
100     {
101         // complex numbers
102         return Overload::call(L"%s_gsort", in, _iRetCount, out);
103     }
104     if (in.size() == 4)
105     {
106         // Direct multilevel sorting
107         return Overload::call(L"%gsort_multilevel", in, _iRetCount, out);
108     }
109     if (pGTIn->isPoly())
110     {
111         // real or complex polynomials
112         return Overload::call(L"%p_gsort", in, _iRetCount, out);
113     }
114
115     //
116     // Common case
117     //
118     // Get the sorting order
119     std::wstring wstrWay = L"d";
120     if (in.size() > 2)
121     {
122         if (in[2]->isString() == false)
123         {
124             Scierror(999, _("%s: Wrong type for input argument #%d : string expected.\n"), "gsort", 3);
125             return types::Function::Error;
126         }
127
128         wstrWay = in[2]->getAs<types::String>()->get(0);
129         if (wstrWay != L"i" && wstrWay != L"d")
130         {
131             Scierror(999, _("%s: Wrong value for input argument #%d: %s expected.\n"), "gsort", 3, "'i'|'d'");
132             return types::Function::Error;
133         }
134     }
135
136     // Get data and perform operation for each types::
137     types::Double* pDblInd = NULL;
138     if (_iRetCount == 2)
139     {
140         int iRowsInd = (wstrProcess == L"lc") ? 1 : pGTIn->getRows();
141         int iColsInd = (wstrProcess == L"lr") ? 1 : pGTIn->getCols();
142
143         pDblInd = new types::Double(iRowsInd, iColsInd);
144     }
145
146     if (in[0]->isDouble()) // double
147     {
148         types::Double* pDblIn = in[0]->getAs<types::Double>();
149         types::Double* pDblOut = gsort(pDblIn, pDblInd, wstrWay, wstrProcess);
150         out.push_back(pDblOut);
151     }
152     else if (in[0]->isString()) // string
153     {
154         types::String* pStringIn = in[0]->getAs<types::String>();
155         types::String* pStringOut = gsort(pStringIn, pDblInd, wstrWay, wstrProcess);
156         out.push_back(pStringOut);
157     }
158     else if (in[0]->isInt8()) // int
159     {
160         types::Int8* pIIn = in[0]->getAs<types::Int8>();
161         types::Int8* pIOut = gsort(pIIn, pDblInd, wstrWay, wstrProcess);
162         out.push_back(pIOut);
163     }
164     else if (in[0]->isInt16())
165     {
166         types::Int16* pIIn = in[0]->getAs<types::Int16>();
167         types::Int16* pIOut = gsort(pIIn, pDblInd, wstrWay, wstrProcess);
168         out.push_back(pIOut);
169     }
170     else if (in[0]->isInt32())
171     {
172         types::Int32* pIIn = in[0]->getAs<types::Int32>();
173         types::Int32* pIOut = gsort(pIIn, pDblInd, wstrWay, wstrProcess);
174         out.push_back(pIOut);
175     }
176     else if (in[0]->isInt64())
177     {
178         types::Int64* pIIn = in[0]->getAs<types::Int64>();
179         types::Int64* pIOut = gsort(pIIn, pDblInd, wstrWay, wstrProcess);
180         out.push_back(pIOut);
181     }
182     else if (in[0]->isUInt8()) // uint
183     {
184         types::UInt8* pIIn = in[0]->getAs<types::UInt8>();
185         types::UInt8* pIOut = gsort(pIIn, pDblInd, wstrWay, wstrProcess);
186         out.push_back(pIOut);
187     }
188     else if (in[0]->isUInt16())
189     {
190         types::UInt16* pIIn = in[0]->getAs<types::UInt16>();
191         types::UInt16* pIOut = gsort(pIIn, pDblInd, wstrWay, wstrProcess);
192         out.push_back(pIOut);
193     }
194     else if (in[0]->isUInt32())
195     {
196         types::UInt32* pIIn = in[0]->getAs<types::UInt32>();
197         types::UInt32* pIOut = gsort(pIIn, pDblInd, wstrWay, wstrProcess);
198         out.push_back(pIOut);
199     }
200     else if (in[0]->isUInt64())
201     {
202         types::UInt64* pIIn = in[0]->getAs<types::UInt64>();
203         types::UInt64* pIOut = gsort(pIIn, pDblInd, wstrWay, wstrProcess);
204         out.push_back(pIOut);
205     }
206     else    // Other generic data types not supported
207     {
208         std::wstring wstFuncName = L"%" + in[0]->getShortTypeStr() + L"_gsort";
209         return Overload::call(wstFuncName, in, _iRetCount, out);
210     }
211
212     // Returns indices when requested
213     if (_iRetCount == 2)
214     {
215         out.push_back(pDblInd);
216     }
217
218     return types::Function::OK;
219 }
220 /*--------------------------------------------------------------------------*/