|
Blender
V2.59
|
00001 /* 00002 * $Id: rand.c 36596 2011-05-10 14:48:06Z campbellbarton $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00021 * All rights reserved. 00022 * 00023 * The Original Code is: all of this file. 00024 * 00025 * Contributor(s): none yet. 00026 * 00027 * ***** END GPL LICENSE BLOCK ***** 00028 */ 00029 00035 #include <stdlib.h> 00036 #include <string.h> 00037 00038 #include "MEM_guardedalloc.h" 00039 00040 #include "PIL_time.h" 00041 00042 #include "BLI_threads.h" 00043 #include "BLI_rand.h" 00044 00045 #if defined(WIN32) && !defined(FREE_WINDOWS) 00046 typedef unsigned __int64 r_uint64; 00047 00048 #define MULTIPLIER 0x5DEECE66Di64 00049 #define MASK 0x0000FFFFFFFFFFFFi64 00050 #else 00051 typedef unsigned long long r_uint64; 00052 00053 #define MULTIPLIER 0x5DEECE66Dll 00054 #define MASK 0x0000FFFFFFFFFFFFll 00055 #endif 00056 00057 #define ADDEND 0xB 00058 00059 #define LOWSEED 0x330E 00060 00061 extern unsigned char hash[]; // noise.c 00062 00063 /***/ 00064 00065 struct RNG { 00066 r_uint64 X; 00067 }; 00068 00069 RNG *rng_new(unsigned int seed) 00070 { 00071 RNG *rng = MEM_mallocN(sizeof(*rng), "rng"); 00072 00073 rng_seed(rng, seed); 00074 00075 return rng; 00076 } 00077 00078 void rng_free(RNG* rng) 00079 { 00080 MEM_freeN(rng); 00081 } 00082 00083 void rng_seed(RNG *rng, unsigned int seed) { 00084 rng->X= (((r_uint64) seed)<<16) | LOWSEED; 00085 } 00086 00087 void rng_srandom(RNG *rng, unsigned int seed) { 00088 rng_seed(rng, seed + hash[seed & 255]); 00089 seed= rng_getInt(rng); 00090 rng_seed(rng, seed + hash[seed & 255]); 00091 seed= rng_getInt(rng); 00092 rng_seed(rng, seed + hash[seed & 255]); 00093 } 00094 00095 int rng_getInt(RNG *rng) { 00096 rng->X= (MULTIPLIER*rng->X + ADDEND)&MASK; 00097 return (int) (rng->X>>17); 00098 } 00099 00100 double rng_getDouble(RNG *rng) { 00101 return (double) rng_getInt(rng)/0x80000000; 00102 } 00103 00104 float rng_getFloat(RNG *rng) { 00105 return (float) rng_getInt(rng)/0x80000000; 00106 } 00107 00108 void rng_shuffleArray(RNG *rng, void *data, int elemSize, int numElems) 00109 { 00110 int i = numElems; 00111 void *temp = malloc(elemSize); 00112 00113 while (--i) { 00114 int j = rng_getInt(rng)%numElems; 00115 if(i!=j) { 00116 void *iElem = (unsigned char*)data + i*elemSize; 00117 void *jElem = (unsigned char*)data + j*elemSize; 00118 memcpy(temp, iElem, elemSize); 00119 memcpy(iElem, jElem, elemSize); 00120 memcpy(jElem, temp, elemSize); 00121 } 00122 } 00123 00124 free(temp); 00125 } 00126 00127 void rng_skip(RNG *rng, int n) 00128 { 00129 int i; 00130 00131 for(i=0; i<n; i++) 00132 rng_getInt(rng); 00133 } 00134 00135 /***/ 00136 00137 static RNG theBLI_rng = {0}; 00138 00139 /* note, this one creates periodical patterns */ 00140 void BLI_srand(unsigned int seed) { 00141 rng_seed(&theBLI_rng, seed); 00142 } 00143 00144 /* using hash table to create better seed */ 00145 void BLI_srandom(unsigned int seed) { 00146 rng_srandom(&theBLI_rng, seed); 00147 } 00148 00149 int BLI_rand(void) { 00150 return rng_getInt(&theBLI_rng); 00151 } 00152 00153 double BLI_drand(void) { 00154 return rng_getDouble(&theBLI_rng); 00155 } 00156 00157 float BLI_frand(void) { 00158 return rng_getFloat(&theBLI_rng); 00159 } 00160 00161 void BLI_fillrand(void *addr, int len) { 00162 RNG rng; 00163 unsigned char *p= addr; 00164 00165 rng_seed(&rng, (unsigned int) (PIL_check_seconds_timer()*0x7FFFFFFF)); 00166 while (len--) *p++= rng_getInt(&rng)&0xFF; 00167 } 00168 00169 void BLI_array_randomize(void *data, int elemSize, int numElems, unsigned int seed) 00170 { 00171 RNG rng; 00172 00173 rng_seed(&rng, seed); 00174 rng_shuffleArray(&rng, data, elemSize, numElems); 00175 } 00176 00177 /* ********* for threaded random ************** */ 00178 00179 static RNG rng_tab[BLENDER_MAX_THREADS]; 00180 00181 void BLI_thread_srandom(int thread, unsigned int seed) 00182 { 00183 if(thread >= BLENDER_MAX_THREADS) 00184 thread= 0; 00185 00186 rng_seed(&rng_tab[thread], seed + hash[seed & 255]); 00187 seed= rng_getInt(&rng_tab[thread]); 00188 rng_seed(&rng_tab[thread], seed + hash[seed & 255]); 00189 seed= rng_getInt(&rng_tab[thread]); 00190 rng_seed(&rng_tab[thread], seed + hash[seed & 255]); 00191 } 00192 00193 int BLI_thread_rand(int thread) { 00194 return rng_getInt(&rng_tab[thread]); 00195 } 00196 00197 float BLI_thread_frand(int thread) { 00198 return rng_getFloat(&rng_tab[thread]); 00199 } 00200