aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llcommon/llrand.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-09-06 18:24:57 -0500
committerJacek Antonelli2008-09-06 18:25:07 -0500
commit798d367d54a6c6379ad355bd8345fa40e31e7fe9 (patch)
tree1921f1708cd0240648c97bc02df2c2ab5f2fc41e /linden/indra/llcommon/llrand.cpp
parentSecond Life viewer sources 1.20.15 (diff)
downloadmeta-impy-798d367d54a6c6379ad355bd8345fa40e31e7fe9.zip
meta-impy-798d367d54a6c6379ad355bd8345fa40e31e7fe9.tar.gz
meta-impy-798d367d54a6c6379ad355bd8345fa40e31e7fe9.tar.bz2
meta-impy-798d367d54a6c6379ad355bd8345fa40e31e7fe9.tar.xz
Second Life viewer sources 1.21.0-RC
Diffstat (limited to 'linden/indra/llcommon/llrand.cpp')
-rw-r--r--linden/indra/llcommon/llrand.cpp176
1 files changed, 176 insertions, 0 deletions
diff --git a/linden/indra/llcommon/llrand.cpp b/linden/indra/llcommon/llrand.cpp
new file mode 100644
index 0000000..bc8c867
--- /dev/null
+++ b/linden/indra/llcommon/llrand.cpp
@@ -0,0 +1,176 @@
1/**
2 * @file llrand.cpp
3 * @brief Global random generator.
4 *
5 * $LicenseInfo:firstyear=2000&license=viewergpl$
6 *
7 * Copyright (c) 2000-2008, Linden Research, Inc.
8 *
9 * Second Life Viewer Source Code
10 * The source code in this file ("Source Code") is provided by Linden Lab
11 * to you under the terms of the GNU General Public License, version 2.0
12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 *
17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 *
22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above,
24 * and agree to abide by those obligations.
25 *
26 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
27 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
28 * COMPLETENESS OR PERFORMANCE.
29 * $/LicenseInfo$
30 */
31
32#include "linden_common.h"
33
34#include "llrand.h"
35#include "lluuid.h"
36
37/**
38 * Through analysis, we have decided that we want to take values which
39 * are close enough to 1.0 to map back to 0.0. We came to this
40 * conclusion from noting that:
41 *
42 * [0.0, 1.0)
43 *
44 * when scaled to the integer set:
45 *
46 * [0, 4)
47 *
48 * there is some value close enough to 1.0 that when multiplying by 4,
49 * gets truncated to 4. Therefore:
50 *
51 * [0,1-eps] => 0
52 * [1,2-eps] => 1
53 * [2,3-eps] => 2
54 * [3,4-eps] => 3
55 *
56 * So 0 gets uneven distribution if we simply clamp. The actual
57 * clamp utilized in this file is to map values out of range back
58 * to 0 to restore uniform distribution.
59 *
60 * Also, for clamping floats when asking for a distribution from
61 * [0.0,g) we have determined that for values of g < 0.5, then
62 * rand*g=g, which is not the desired result. As above, we clamp to 0
63 * to restore uniform distribution.
64 */
65
66// *NOTE: The system rand implementation is probably not correct.
67#define LL_USE_SYSTEM_RAND 0
68
69#if LL_USE_SYSTEM_RAND
70#include <cstdlib>
71#endif
72
73#if LL_USE_SYSTEM_RAND
74class LLSeedRand
75{
76public:
77 LLSeedRand()
78 {
79#if LL_WINDOWS
80 srand(LLUUID::getRandomSeed());
81#else
82 srand48(LLUUID::getRandomSeed());
83#endif
84 }
85};
86static LLSeedRand sRandomSeeder;
87inline F64 ll_internal_random_double()
88{
89#if LL_WINDOWS
90 return (F64)rand() / (F64)RAND_MAX;
91#else
92 return drand48();
93#endif
94}
95inline F32 ll_internal_random_float()
96{
97#if LL_WINDOWS
98 return (F32)rand() / (F32)RAND_MAX;
99#else
100 return (F32)drand48();
101#endif
102}
103#else
104static LLRandLagFib2281 gRandomGenerator(LLUUID::getRandomSeed());
105inline F64 ll_internal_random_double()
106{
107 // *HACK: Through experimentation, we have found that dual core
108 // CPUs (or at least multi-threaded processes) seem to
109 // occasionally give an obviously incorrect random number -- like
110 // 5^15 or something. Sooooo, clamp it as described above.
111 F64 rv = gRandomGenerator();
112 if(!((rv >= 0.0) && (rv < 1.0))) return fmod(rv, 1.0);
113 return rv;
114}
115
116inline F32 ll_internal_random_float()
117{
118 // The clamping rules are described above.
119 F32 rv = (F32)gRandomGenerator();
120 if(!((rv >= 0.0f) && (rv < 1.0f))) return fmod(rv, 1.f);
121 return rv;
122}
123#endif
124
125S32 ll_rand()
126{
127 return ll_rand(RAND_MAX);
128}
129
130S32 ll_rand(S32 val)
131{
132 // The clamping rules are described above.
133 S32 rv = (S32)(ll_internal_random_double() * val);
134 if(rv == val) return 0;
135 return rv;
136}
137
138F32 ll_frand()
139{
140 return ll_internal_random_float();
141}
142
143F32 ll_frand(F32 val)
144{
145 // The clamping rules are described above.
146 F32 rv = ll_internal_random_float() * val;
147 if(val > 0)
148 {
149 if(rv >= val) return 0.0f;
150 }
151 else
152 {
153 if(rv <= val) return 0.0f;
154 }
155 return rv;
156}
157
158F64 ll_drand()
159{
160 return ll_internal_random_double();
161}
162
163F64 ll_drand(F64 val)
164{
165 // The clamping rules are described above.
166 F64 rv = ll_internal_random_double() * val;
167 if(val > 0)
168 {
169 if(rv >= val) return 0.0;
170 }
171 else
172 {
173 if(rv <= val) return 0.0;
174 }
175 return rv;
176}