1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2010-2010 - DIGITEO - Bernard HUGUENEY
4  *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
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 "sparse_gw.hxx"
17 #include "function.hxx"
18 #include "sparse.hxx"
19 #include "gsort.hxx"
20 
21 extern "C"
22 {
23 #include "charEncoding.h"
24 #include "Scierror.h"
25 #include "localization.h"
26 }
27 
sci_spget(types::typed_list & in,int _iRetCount,types::typed_list & out)28 types::Function::ReturnValue sci_spget(types::typed_list &in, int _iRetCount, types::typed_list &out)
29 {
30     types::Double* pValues      = NULL;
31     types::Double* pCoordSorted = NULL;
32     types::Bool* pBools         = NULL;
33 
34     int iRows           = 0;
35     int iCols           = 0;
36     bool bComplex       = false;
37     int nonZeros        = 0;
38     int* pRows       = NULL;
39     double* pNonZeroR   = NULL;
40     double* pNonZeroI   = NULL;
41 
42     if (in.size() != 1)
43     {
44         Scierror(999, _("%s: Wrong number of input argument(s): %d expected.\n"), "spget", 1);
45         return types::Function::Error;
46     }
47 
48     if (in[0]->isSparse())
49     {
50         types::Sparse* sp = in[0]->getAs<types::Sparse>();
51         nonZeros = static_cast<int>(sp->nonZeros());
52 
53         if (nonZeros == 0)
54         {
55             out.push_back(types::Double::Empty());
56             if (_iRetCount > 1)
57             {
58                 out.push_back(types::Double::Empty());
59             }
60 
61             if (_iRetCount > 2)
62             {
63                 types::Double* pSize = new types::Double(1, 2);
64                 pSize->set(0, sp->getRows());
65                 pSize->set(1, sp->getCols());
66                 out.push_back(pSize);
67             }
68 
69             return types::Function::OK;
70         }
71 
72         pRows = new int[nonZeros * 2];
73         sp->outputRowCol(pRows);
74 
75         if (_iRetCount > 1)
76         {
77             pNonZeroR = new double[nonZeros];
78             pNonZeroI = new double[nonZeros];
79             sp->outputValues(pNonZeroR, pNonZeroI);
80         }
81 
82         iRows = sp->getRows();
83         iCols = sp->getCols();
84         bComplex = sp->isComplex();
85 
86         pValues = new types::Double(nonZeros, 1, bComplex);
87 
88     }
89     else if (in[0]->isSparseBool())
90     {
91         types::SparseBool* sp = in[0]->getAs<types::SparseBool>();
92         nonZeros = static_cast<int>(sp->nbTrue());
93 
94         if (nonZeros == 0)
95         {
96             out.push_back(types::Double::Empty());
97             if (_iRetCount > 1)
98             {
99                 out.push_back(types::Double::Empty());
100             }
101 
102             if (_iRetCount > 2)
103             {
104                 types::Double* pSize = new types::Double(1, 2);
105                 pSize->set(0, sp->getRows());
106                 pSize->set(1, sp->getCols());
107                 out.push_back(pSize);
108             }
109 
110             return types::Function::OK;
111         }
112 
113 
114         pRows = new int[nonZeros * 2];
115         sp->outputRowCol(pRows);
116 
117         iRows = sp->getRows();
118         iCols = sp->getCols();
119 
120         pBools = new types::Bool(nonZeros, 1);
121     }
122     else
123     {
124         Scierror(999, _("%s: Wrong type for input argument #%d: sparse matrix expected.\n"), "spget", 1);
125         return types::Function::Error;
126     }
127 
128     if (_iRetCount > 3)
129     {
130         Scierror(999, _("%s: Wrong number of output arguments: %d to %d expected.\n"), "spget", 1, 3);
131         delete[] pRows;
132         delete[] pNonZeroR;
133         delete[] pNonZeroI;
134         if (pBools)
135         {
136             pBools->killMe();
137         }
138         if (pValues)
139         {
140             pValues->killMe();
141         }
142         return types::Function::Error;
143     }
144 
145     types::Double* pCoord = new types::Double(nonZeros, 2);
146     pCoord->setInt(pRows);
147 
148     if (_iRetCount > 1)
149     {
150         if (pBools)
151         {
152             pCoordSorted = gsort(pCoord, NULL, L"i", L"lr");
153             for (int i = 0 ; i < nonZeros ; i++)
154             {
155                 pBools->set(i, true);
156             }
157         }
158         else
159         {
160             types::Double* pIndex = new types::Double(nonZeros, 1);
161             pCoordSorted = gsort(pCoord, pIndex, L"i", L"lr");
162             if (pValues->isComplex())
163             {
164                 for (int i = 0 ; i < nonZeros ; i++)
165                 {
166                     pValues->set(i, pNonZeroR[(int)pIndex->get(i) - 1]);
167                     pValues->setImg(i, pNonZeroI[(int)pIndex->get(i) - 1]);
168                 }
169             }
170             else
171             {
172                 for (int i = 0 ; i < nonZeros ; i++)
173                 {
174                     pValues->set(i, pNonZeroR[(int)pIndex->get(i) - 1]);
175                 }
176             }
177 
178             delete[] pNonZeroR;
179             delete[] pNonZeroI;
180             delete pIndex;
181         }
182     }
183     else
184     {
185         pCoordSorted = gsort(pCoord, NULL, L"i", L"lr");
186     }
187 
188     out.push_back(pCoordSorted);
189     if (_iRetCount > 1)
190     {
191         if (pBools)
192         {
193             out.push_back(pBools);
194         }
195         else
196         {
197             out.push_back(pValues);
198         }
199     }
200     else
201     {
202         if (pBools)
203         {
204             pBools->killMe();
205         }
206 
207         if (pValues)
208         {
209             pValues->killMe();
210         }
211     }
212 
213     if (_iRetCount > 2)
214     {
215         types::Double* pSize = new types::Double(1, 2);
216         pSize->set(0, iRows);
217         pSize->set(1, iCols);
218         out.push_back(pSize);
219     }
220 
221     delete pCoord;
222     delete[] pRows;
223     return types::Function::OK;
224 }
225