llrand.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:4k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llrand.cpp
  3.  * @brief Global random generator.
  4.  *
  5.  * $LicenseInfo:firstyear=2000&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2000-2010, 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
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "linden_common.h"
  33. #include "llrand.h"
  34. #include "lluuid.h"
  35. /**
  36.  * Through analysis, we have decided that we want to take values which
  37.  * are close enough to 1.0 to map back to 0.0.  We came to this
  38.  * conclusion from noting that:
  39.  *
  40.  * [0.0, 1.0)
  41.  *
  42.  * when scaled to the integer set:
  43.  *
  44.  * [0, 4)
  45.  *
  46.  * there is some value close enough to 1.0 that when multiplying by 4,
  47.  * gets truncated to 4. Therefore:
  48.  *
  49.  * [0,1-eps] => 0
  50.  * [1,2-eps] => 1
  51.  * [2,3-eps] => 2
  52.  * [3,4-eps] => 3
  53.  *
  54.  * So 0 gets uneven distribution if we simply clamp. The actual
  55.  * clamp utilized in this file is to map values out of range back
  56.  * to 0 to restore uniform distribution.
  57.  *
  58.  * Also, for clamping floats when asking for a distribution from
  59.  * [0.0,g) we have determined that for values of g < 0.5, then
  60.  * rand*g=g, which is not the desired result. As above, we clamp to 0
  61.  * to restore uniform distribution.
  62.  */
  63. // *NOTE: The system rand implementation is probably not correct.
  64. #define LL_USE_SYSTEM_RAND 0
  65. #if LL_USE_SYSTEM_RAND
  66. #include <cstdlib>
  67. #endif
  68. #if LL_USE_SYSTEM_RAND
  69. class LLSeedRand
  70. {
  71. public:
  72. LLSeedRand()
  73. {
  74. #if LL_WINDOWS
  75. srand(LLUUID::getRandomSeed());
  76. #else
  77. srand48(LLUUID::getRandomSeed());
  78. #endif
  79. }
  80. };
  81. static LLSeedRand sRandomSeeder;
  82. inline F64 ll_internal_random_double()
  83. {
  84. #if LL_WINDOWS
  85. return (F64)rand() / (F64)RAND_MAX; 
  86. #else
  87. return drand48();
  88. #endif
  89. }
  90. inline F32 ll_internal_random_float()
  91. {
  92. #if LL_WINDOWS
  93. return (F32)rand() / (F32)RAND_MAX; 
  94. #else
  95. return (F32)drand48();
  96. #endif
  97. }
  98. #else
  99. static LLRandLagFib2281 gRandomGenerator(LLUUID::getRandomSeed());
  100. inline F64 ll_internal_random_double()
  101. {
  102. // *HACK: Through experimentation, we have found that dual core
  103. // CPUs (or at least multi-threaded processes) seem to
  104. // occasionally give an obviously incorrect random number -- like
  105. // 5^15 or something. Sooooo, clamp it as described above.
  106. F64 rv = gRandomGenerator();
  107. if(!((rv >= 0.0) && (rv < 1.0))) return fmod(rv, 1.0);
  108. return rv;
  109. }
  110. inline F32 ll_internal_random_float()
  111. {
  112. // The clamping rules are described above.
  113. F32 rv = (F32)gRandomGenerator();
  114. if(!((rv >= 0.0f) && (rv < 1.0f))) return fmod(rv, 1.f);
  115. return rv;
  116. }
  117. #endif
  118. S32 ll_rand()
  119. {
  120. return ll_rand(RAND_MAX);
  121. }
  122. S32 ll_rand(S32 val)
  123. {
  124. // The clamping rules are described above.
  125. S32 rv = (S32)(ll_internal_random_double() * val);
  126. if(rv == val) return 0;
  127. return rv;
  128. }
  129. F32 ll_frand()
  130. {
  131. return ll_internal_random_float();
  132. }
  133. F32 ll_frand(F32 val)
  134. {
  135. // The clamping rules are described above.
  136. F32 rv = ll_internal_random_float() * val;
  137. if(val > 0)
  138. {
  139. if(rv >= val) return 0.0f;
  140. }
  141. else
  142. {
  143. if(rv <= val) return 0.0f;
  144. }
  145. return rv;
  146. }
  147. F64 ll_drand()
  148. {
  149. return ll_internal_random_double();
  150. }
  151. F64 ll_drand(F64 val)
  152. {
  153. // The clamping rules are described above.
  154. F64 rv = ll_internal_random_double() * val;
  155. if(val > 0)
  156. {
  157. if(rv >= val) return 0.0;
  158. }
  159. else
  160. {
  161. if(rv <= val) return 0.0;
  162. }
  163. return rv;
  164. }