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
6 * Copyright (C) 2012 - 2016 - Scilab Enterprises
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.
16 /*--------------------------------------------------------------------------*/
17 #include "elem_func_gw.hxx"
18 #include "function.hxx"
19 #include "overload.hxx"
26 #include "localization.h"
27 #include "basic_functions.h"
30 const wchar_t g_pwstConfigInfo[] = L"info";
31 const wchar_t g_pwstConfigSeed[] = L"seed";
33 const wchar_t g_pwstTypeUniform[] = L"uniform";
34 const wchar_t g_pwstTypeNormal[] = L"normal";
36 int setRandType(const wchar_t* _wcType);
37 double getNextRandValue(int _iRandType, int* _piRandSave, int _iForceInit);
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
44 types::Function::ReturnValue sci_rand(types::typed_list &in, int _iRetCount, types::typed_list &out)
46 types::Double* pOut = NULL;
47 static int siRandType = 0;
48 static int siRandSave = 0;
49 static int iForceInit = 0;
51 int iSizeIn = (int)in.size();
52 if (iSizeIn == 0 || iSizeIn == -1)
55 double dblRand = getNextRandValue(siRandType, &siRandSave, 0);
56 out.push_back(new types::Double(dblRand));
57 return types::Function::OK;
60 if (in[0]->isString())
63 types::String* pS = in[0]->getAs<types::String>();
64 if (pS->getSize() != 1)
66 Scierror(999, _("%s: Wrong size for input argument #%d: string expected.\n"), "rand", 1);
67 return types::Function::Error;
70 wchar_t* pwstKey = pS->get(0);
72 if (!wcscmp(pwstKey,g_pwstConfigInfo))
77 Scierror(77, _("%s: Wrong number of input argument(s): %d expected.\n"), "rand", 1);
78 return types::Function::Error;
83 out.push_back(new types::String(g_pwstTypeUniform));
87 out.push_back(new types::String(g_pwstTypeNormal));
90 else if (!wcscmp(pwstKey,g_pwstConfigSeed))
96 out.push_back(new types::Double(siRandSave));
98 else if (iSizeIn == 2)
100 if (in[1]->isDouble() == false || in[1]->getAs<types::Double>()->isScalar() == false)
102 Scierror(999, _("%s: Wrong size for input argument #%d: A scalar expected.\n"), "rand", 2);
103 return types::Function::Error;
106 siRandSave = (int)std::max(in[1]->getAs<types::Double>()->get(0), double(0));
111 Scierror(77, _("%s: Wrong number of input argument(s): %d expected.\n"), "rand", 2);
112 return types::Function::Error;
117 int iRandSave = siRandType;
120 Scierror(77, _("%s: Wrong number of input argument(s): %d expected.\n"), "rand", 1);
121 return types::Function::Error;
123 siRandType = setRandType(pwstKey);
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;
134 int iRandSave = siRandType;
135 if (in[iSizeIn - 1]->isString())
138 types::String* pS = in[iSizeIn - 1]->getAs<types::String>();
139 if (pS->getSize() != 1)
141 Scierror(999, _("%s: Wrong size for input argument #%d: string expected.\n"), "rand", iSizeIn);
142 return types::Function::Error;
146 siRandType = setRandType(pS->get(0));
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;
157 types::typed_list args;
158 std::copy(in.begin(), in.begin() + iSizeIn, back_inserter(args));
164 bool ret = getDimsFromArguments(args, "rand", &iDims, &piDims, &alloc);
170 Scierror(21, _("Invalid index.\n"));
175 return Overload::generateNameAndCall(L"rand", in, _iRetCount, out);
179 return types::Function::Error;
182 //special case for complex unique complex argument
183 bool complex = false;
184 if (in.size() == 1 && in[0]->isGenericType())
186 complex = in[0]->getAs<types::GenericType>()->isComplex();
189 pOut = new types::Double(iDims, piDims, complex);
195 double* pd = pOut->get();
196 for (int i = 0; i < pOut->getSize(); i++)
198 pd[i] = getNextRandValue(siRandType, &siRandSave, iForceInit);
202 if (pOut->isComplex())
204 double* pImg = pOut->getImg();
205 for (int i = 0; i < pOut->getSize(); i++)
207 pImg[i] = getNextRandValue(siRandType, &siRandSave, iForceInit);
211 //retore previous law
212 siRandType = iRandSave;
215 return types::Function::OK;
217 /*--------------------------------------------------------------------------*/
218 double getNextRandValue(int _iRandType, int* _piRandSave, int _iForceInit)
220 static int siInit = TRUE;
221 static double sdblImg = 0;
222 static double sdblR = 0;
234 dblVal = durands(_piRandSave);
242 dblReal = 2 * durands(_piRandSave) - 1;
243 sdblImg = 2 * durands(_piRandSave) - 1;
244 dblTemp = dblReal * dblReal + sdblImg * sdblImg;
246 sdblR = dsqrts(-2 * dlogs(dblTemp) / dblTemp);
247 dblVal = dblReal * sdblR;
251 dblVal = sdblImg * sdblR;
258 int setRandType(const wchar_t* _wcType)
260 if (!wcscmp(_wcType,g_pwstTypeUniform))
264 if (!wcscmp(_wcType,g_pwstTypeNormal))
270 if (_wcType[0] == g_pwstTypeUniform[0] && _wcType[1] == L'\0')
274 if (_wcType[0] == g_pwstTypeNormal[0] && _wcType[1] == L'\0')
282 /*--------------------------------------------------------------------------*/