1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2011 - DIGITEO - Antoine ELIAS
4 * Copyright (C) 2014 - 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 #include "elem_func_gw.hxx"
18 #include "function.hxx"
19 #include "overload.hxx"
20 #include "double.hxx"
21 #include "string.hxx"
22
23 extern "C"
24 {
25 #include "Scierror.h"
26 #include "localization.h"
27 #include "basic_functions.h"
28 }
29
30 const wchar_t g_pwstConfigInfo[] = L"info";
31 const wchar_t g_pwstConfigSeed[] = L"seed";
32
33 const wchar_t g_pwstTypeUniform[] = L"uniform";
34 const wchar_t g_pwstTypeNormal[] = L"normal";
35
36 int setRandType(const wchar_t* _wcType);
37 double getNextRandValue(int _iRandType, int* _piRandSave, int _iForceInit);
38
39 /*
40 clear a;nb = 2500;a = rand(nb, nb);tic();rand(a);toc
41 clear a;nb = 2500;a = rand(nb, nb);a = a + a * %i;tic();rand(a);toc
42 */
43
sci_rand(types::typed_list & in,int _iRetCount,types::typed_list & out)44 types::Function::ReturnValue sci_rand(types::typed_list &in, int _iRetCount, types::typed_list &out)
45 {
46 types::Double* pOut = NULL;
47 static int siRandType = 0;
48 static int siRandSave = 0;
49 static int iForceInit = 0;
50
51 int iSizeIn = (int)in.size();
52 if (iSizeIn == 0 || iSizeIn == -1)
53 {
54 //rand or rand()
55 double dblRand = getNextRandValue(siRandType, &siRandSave, 0);
56 out.push_back(new types::Double(dblRand));
57 return types::Function::OK;
58 }
59
60 if (in[0]->isString())
61 {
62 //rand("xxx")
63 types::String* pS = in[0]->getAs<types::String>();
64 if (pS->getSize() != 1)
65 {
66 Scierror(999, _("%s: Wrong size for input argument #%d: string expected.\n"), "rand", 1);
67 return types::Function::Error;
68 }
69
70 wchar_t* pwstKey = pS->get(0);
71
72 if (!wcscmp(pwstKey,g_pwstConfigInfo))
73 {
74 //info
75 if (iSizeIn > 1)
76 {
77 Scierror(77, _("%s: Wrong number of input argument(s): %d expected.\n"), "rand", 1);
78 return types::Function::Error;
79 }
80
81 if (siRandType == 0)
82 {
83 out.push_back(new types::String(g_pwstTypeUniform));
84 }
85 else
86 {
87 out.push_back(new types::String(g_pwstTypeNormal));
88 }
89 }
90 else if (!wcscmp(pwstKey,g_pwstConfigSeed))
91 {
92 //seed
93 if (iSizeIn == 1)
94 {
95 //get
96 out.push_back(new types::Double(siRandSave));
97 }
98 else if (iSizeIn == 2)
99 {
100 if (in[1]->isDouble() == false || in[1]->getAs<types::Double>()->isScalar() == false)
101 {
102 Scierror(999, _("%s: Wrong size for input argument #%d: A scalar expected.\n"), "rand", 2);
103 return types::Function::Error;
104 }
105
106 siRandSave = (int)std::max(in[1]->getAs<types::Double>()->get(0), double(0));
107 iForceInit = 1;
108 }
109 else
110 {
111 Scierror(77, _("%s: Wrong number of input argument(s): %d expected.\n"), "rand", 2);
112 return types::Function::Error;
113 }
114 }
115 else
116 {
117 int iRandSave = siRandType;
118 if (iSizeIn > 1)
119 {
120 Scierror(77, _("%s: Wrong number of input argument(s): %d expected.\n"), "rand", 1);
121 return types::Function::Error;
122 }
123 siRandType = setRandType(pwstKey);
124 if (siRandType < 0)
125 {
126 siRandType = iRandSave;
127 Scierror(999, _("%s: Wrong value for input argument #%d: '%s', '%s', '%s' or '%s' expected.\n"), "rand", 1,"info","seed","uniform","normal");
128 return types::Function::Error;
129 }
130 }
131 }
132 else
133 {
134 int iRandSave = siRandType;
135 if (in[iSizeIn - 1]->isString())
136 {
137 //uniform ou normal
138 types::String* pS = in[iSizeIn - 1]->getAs<types::String>();
139 if (pS->getSize() != 1)
140 {
141 Scierror(999, _("%s: Wrong size for input argument #%d: string expected.\n"), "rand", iSizeIn);
142 return types::Function::Error;
143 }
144
145 //set randomize law
146 siRandType = setRandType(pS->get(0));
147 if (siRandType < 0)
148 {
149 siRandType = iRandSave;
150 Scierror(999, _("%s: Wrong value for input argument #%d: '%s' or '%s' expected.\n"), "rand", iSizeIn,"uniform","normal");
151 return types::Function::Error;
152 }
153
154 iSizeIn--;
155 }
156
157 types::typed_list args;
158 std::copy(in.begin(), in.begin() + iSizeIn, back_inserter(args));
159
160 int iDims = 0;
161 int* piDims = NULL;
162 bool alloc = false;
163
164 bool ret = getDimsFromArguments(args, "rand", &iDims, &piDims, &alloc);
165 if (ret == false)
166 {
167 switch (iDims)
168 {
169 case -1:
170 Scierror(21, _("Invalid index.\n"));
171 break;
172 case 1:
173 {
174 //call overload
175 return Overload::generateNameAndCall(L"rand", in, _iRetCount, out);
176 }
177 }
178
179 return types::Function::Error;
180 }
181
182 //special case for complex unique complex argument
183 bool complex = false;
184 if (in.size() == 1 && in[0]->isGenericType())
185 {
186 complex = in[0]->getAs<types::GenericType>()->isComplex();
187 }
188
189 pOut = new types::Double(iDims, piDims, complex);
190 if (alloc)
191 {
192 delete[] piDims;
193 }
194
195 double* pd = pOut->get();
196 for (int i = 0; i < pOut->getSize(); i++)
197 {
198 pd[i] = getNextRandValue(siRandType, &siRandSave, iForceInit);
199 iForceInit = 0;
200 }
201
202 if (pOut->isComplex())
203 {
204 double* pImg = pOut->getImg();
205 for (int i = 0; i < pOut->getSize(); i++)
206 {
207 pImg[i] = getNextRandValue(siRandType, &siRandSave, iForceInit);
208 }
209 }
210 out.push_back(pOut);
211 //retore previous law
212 siRandType = iRandSave;
213 }
214
215 return types::Function::OK;
216 }
217 /*--------------------------------------------------------------------------*/
getNextRandValue(int _iRandType,int * _piRandSave,int _iForceInit)218 double getNextRandValue(int _iRandType, int* _piRandSave, int _iForceInit)
219 {
220 static int siInit = TRUE;
221 static double sdblImg = 0;
222 static double sdblR = 0;
223 double dblReal = 0;
224 double dblVal = 0;
225 double dblTemp = 2;
226
227 if (_iForceInit)
228 {
229 siInit = TRUE;
230 }
231
232 if (_iRandType == 0)
233 {
234 dblVal = durands(_piRandSave);
235 }
236 else
237 {
238 if (siInit == TRUE)
239 {
240 while (dblTemp > 1)
241 {
242 dblReal = 2 * durands(_piRandSave) - 1;
243 sdblImg = 2 * durands(_piRandSave) - 1;
244 dblTemp = dblReal * dblReal + sdblImg * sdblImg;
245 }
246 sdblR = dsqrts(-2 * dlogs(dblTemp) / dblTemp);
247 dblVal = dblReal * sdblR;
248 }
249 else
250 {
251 dblVal = sdblImg * sdblR;
252 }
253 siInit = !siInit;
254 }
255 return dblVal;
256 }
257
setRandType(const wchar_t * _wcType)258 int setRandType(const wchar_t* _wcType)
259 {
260 if (!wcscmp(_wcType,g_pwstTypeUniform))
261 {
262 return 0;
263 }
264 if (!wcscmp(_wcType,g_pwstTypeNormal))
265 {
266 return 1;
267 }
268
269 // shortcut version
270 if (_wcType[0] == g_pwstTypeUniform[0] && _wcType[1] == L'\0')
271 {
272 return 0;
273 }
274 if (_wcType[0] == g_pwstTypeNormal[0] && _wcType[1] == L'\0')
275 {
276 return 1;
277 }
278
279 // invalid key
280 return -1;
281 }
282 /*--------------------------------------------------------------------------*/
283
284