2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2018- Stéphane MOTTELET
5 * This file is hereby licensed under the terms of the GNU GPL v2.0,
6 * For more information, see the COPYING file which you should have received
7 * along with this program.
12 #include "function.hxx"
14 #include "overload.hxx"
19 #include "localization.h"
23 int convertTypeToInt32(T* pVal)
25 typename T::type TVal = pVal->get(0);
32 return TVal < 0 ? 0 : (static_cast<int> (TVal));
36 int convertToSize(types::InternalType *pIT);
38 bool fillRange(double* pdblOut, double* pdblMin, double* pdblMax, int iRows, int iCols);
40 /* ==================================================================== */
41 types::Function::ReturnValue sci_linspace(types::typed_list &in, int _iRetCount, types::typed_list &out)
44 types::Double* pDblOut;
46 if (in.size() != 2 && in.size() != 3)
48 Scierror(77, _("%s: Wrong number of input argument(s): %d to %d expected.\n"), "linspace", 2, 3);
49 return types::Function::Error;
54 Scierror(78, _("%s: Wrong number of output argument(s): %d expected."), "linspace", 1);
55 return types::Function::Error;
58 types::Double* pDbl[2];
59 for (int i = 0; i < 2; i++)
61 if (in[i]->isDouble())
63 pDbl[i] = in[i]->getAs<types::Double>();
67 // other types -> overload
68 std::wstring wstFuncName = L"%" + in[i]->getShortTypeStr() + L"_linspace";
69 return Overload::call(wstFuncName, in, _iRetCount, out);
73 // Check dimensions are the same
74 int iDims0 = pDbl[0]->getDims();
75 int* piDims0 = pDbl[0]->getDimsArray();
76 int iDims1 = pDbl[1]->getDims();
77 int* piDims1 = pDbl[1]->getDimsArray();
80 Scierror(999, _("%s: Arguments %d and %d must have same dimensions.\n"), "linspace", 1, 2);
81 return types::Function::Error;
83 for (int i = 0; i < iDims0; i++)
85 if (piDims0[i] != piDims1[i])
87 Scierror(999, _("%s: Arguments %d and %d must have same dimensions.\n"), "linspace", 1, 2);
88 return types::Function::Error;
94 if (in[2]->isGenericType() && in[2]->getAs<types::GenericType>()->isScalar() &&
95 (in[2]->isInt() || (in[2]->isDouble() && in[2]->getAs<types::Double>()->isComplex() == false) ))
97 if (in[2]->isDouble())
99 double dblCols = in[2]->getAs<types::Double>()->get(0);
100 if (std::floor(dblCols) != dblCols)
102 Scierror(999, _("%s: Argument #%d: An integer value expected.\n"), "linspace",3);
103 return types::Function::Error;
106 iCols = convertToSize(in[2]);
110 Scierror(999, _("%s: Argument #%d: An integer value expected.\n"), "linspace", 3);
111 return types::Function::Error;
115 if (iCols == INT_MAX)
117 Scierror(999, _("%s: Wrong values for input argument #%d: Must be less than %d.\n"),"linspace",3,INT_MAX);
118 return types::Function::Error;
121 if (iCols == 0 || (pDbl[0]->getSize() == 0))
124 out.push_back(types::Double::Empty());
125 return types::Function::OK;
128 // generation is done by considering array as a column vector
129 int iRows = pDbl[0]->getSize();
130 // pDblOut is resized later
131 pDblOut = new types::Double(iRows, iCols);
133 if (!fillRange(pDblOut->get(), pDbl[0]->get(), pDbl[1]->get(), iRows, iCols))
137 return types::Function::Error;
140 if (pDbl[0]->isComplex() || pDbl[1]->isComplex())
143 for (iReal = 0; iReal < 2; iReal++)
145 if (!pDbl[iReal]->isComplex())
147 pDbl[iReal] = pDbl[iReal]->clone();
148 pDbl[iReal]->setComplex(true);
152 // Complexify pDblOut
153 pDblOut->setComplex(true);
154 bool status = fillRange(pDblOut->getImg(), pDbl[0]->getImg(), pDbl[1]->getImg(), iRows, iCols);
157 pDbl[iReal]->killMe();
159 if (status != true) // if Infs or NaNs
162 return types::Function::Error;
166 int *piNewDims = new int[iDims0 + 1];
167 // keep the first dimension unchanged
168 piNewDims[0] = piDims0[0];
170 for (int i = 1; i < iDims0; i++)
172 // squeeze subsequent single dimensions
175 piNewDims[iDim++] = piDims0[i];
178 // add the suplementary dimension
179 piNewDims[iDim++] = iCols;
180 // reshape the matrix:
181 pDblOut->reshape(piNewDims, iDim);
182 out.push_back(pDblOut);
185 return types::Function::OK;
188 bool fillRange(double* pdblOut, double* pdblMin, double* pdblMax, int iRows, int iCols)
190 double* step = new double[iRows];
191 for (int j = 0, k = (iCols - 1) * iRows; j < iRows; j++)
193 step[j] = (pdblMax[j] - pdblMin[j]) / (iCols - 1);
194 // checking Infs and NaNs
195 int indInfOrNan = std::isinf(pdblMin[j]) || std::isnan(pdblMin[j]) ? 1 : 0;
196 indInfOrNan = indInfOrNan == 0 ? (std::isinf(pdblMax[j]) || std::isnan(pdblMax[j]) ? 2 : 0) : indInfOrNan;
200 Scierror(999, _("%s: Argument #%d: %%nan and %%inf values are forbidden.\n"), "linspace", indInfOrNan);
203 // last column is enforced (http://bugzilla.scilab.org/10966)
204 pdblOut[k++] = pdblMax[j];
206 // doing the linear range generation
207 for (int i = 0; i < iCols - 1; i++)
209 for (int j = 0; j < iRows; j++)
211 *(pdblOut++) = pdblMin[j] + i * step[j];
219 int convertToSize(types::InternalType *pIT)
221 switch (pIT->getType())
223 case types::InternalType::ScilabDouble:
225 return convertTypeToInt32(pIT->getAs<types::Double>());
227 case types::InternalType::ScilabInt8:
229 return convertTypeToInt32(pIT->getAs<types::Int8>());
231 case types::InternalType::ScilabInt16:
233 return convertTypeToInt32(pIT->getAs<types::Int16>());
235 case types::InternalType::ScilabInt32:
237 return convertTypeToInt32(pIT->getAs<types::Int32>());
239 case types::InternalType::ScilabInt64:
241 return convertTypeToInt32(pIT->getAs<types::Int64>());
243 case types::InternalType::ScilabUInt8:
245 return convertTypeToInt32(pIT->getAs<types::UInt8>());
247 case types::InternalType::ScilabUInt16:
249 return convertTypeToInt32(pIT->getAs<types::UInt16>());
251 case types::InternalType::ScilabUInt32:
253 return convertTypeToInt32(pIT->getAs<types::UInt32>());
255 case types::InternalType::ScilabUInt64:
257 return convertTypeToInt32(pIT->getAs<types::UInt64>());