deRandom.js (8660B)
1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES Utilities 3 * ------------------------------------------------ 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 */ 20 21 /** 22 * This class allows one to create a random integer, floating point number or boolean (TODO, deRandom.choose random items from a list and deRandom.shuffle an array) 23 */ 24 'use strict'; 25 goog.provide('framework.delibs.debase.deRandom'); 26 27 goog.scope(function() { 28 29 var deRandom = framework.delibs.debase.deRandom; 30 31 /** 32 * Array of pseudo random numbers based on seed 33 * @constructor 34 * @struct 35 */ 36 deRandom.deRandom = function() { 37 /** @type {number} */ this.x = 0; 38 /** @type {number} */ this.y = 0; 39 /** @type {number} */ this.z = 0; 40 /** @type {number} */ this.w = 0; 41 }; 42 43 /** 44 * deRandom.Random number generator init 45 * @param {deRandom.deRandom} rnd Array to store random numbers 46 * @param {number} seed Number for seed 47 */ 48 deRandom.deRandom_init = function(rnd, seed) { 49 rnd.x = (-seed ^ 123456789); 50 rnd.y = (362436069 * seed); 51 rnd.z = (521288629 ^ (seed >> 7)); 52 rnd.w = (88675123 ^ (seed << 3)); 53 }; 54 55 /** 56 * Function to get random int 57 * @param {deRandom.deRandom} rnd Initialised array of random numbers 58 * @param {Array<number>=} opts Min and max for range 59 * @return {number} deRandom.Random int 60 */ 61 deRandom.deRandom_getInt = function(rnd, opts) { 62 if (opts != undefined && opts[0] != undefined && opts[1] != undefined) { 63 if (opts[0] == 0x80000000 && opts[1] == 0x7fffffff) { 64 return deRandom.deRandom_getInt(rnd); 65 } else { 66 return opts[0] + (deRandom.deRandom_getInt(rnd) % (opts[1] - opts[0] + 1)); 67 } 68 } 69 var w = rnd.w; 70 var t; 71 72 t = rnd.x ^ (rnd.x << 11); 73 rnd.x = rnd.y; 74 rnd.y = rnd.z; 75 rnd.z = w; 76 rnd.w = w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)); 77 return w; 78 }; 79 80 /** 81 * Function to get random float 82 * @param {deRandom.deRandom} rnd Initialised array of random numbers 83 * @param {Array<number>=} opts Min and max for range 84 * @return {number} deRandom.Random float 85 */ 86 deRandom.deRandom_getFloat = function(rnd, opts) { 87 if (opts != undefined && opts[0] != undefined && opts[1] != undefined) { 88 if (opts[0] <= opts[1]) { 89 return opts[0] + (opts[1] - opts[0]) * deRandom.deRandom_getFloat(rnd); 90 } 91 } else { 92 return (deRandom.deRandom_getInt(rnd) & 0xFFFFFFF) / (0xFFFFFFF + 1); 93 } 94 throw new Error('Invalid arguments'); 95 }; 96 97 /** 98 * Function to get random boolean 99 * @param {deRandom.deRandom} rnd Initialised array of random numbers 100 * @return {boolean} deRandom.Random boolean 101 */ 102 deRandom.deRandom_getBool = function(rnd) { 103 var val; 104 val = deRandom.deRandom_getInt(rnd); 105 return ((val & 0xFFFFFF) < 0x800000); 106 }; 107 108 /** 109 * Function to get a common base seed 110 * @return {number} constant 111 */ 112 deRandom.getBaseSeed = function() { 113 return 42; 114 }; 115 116 /** 117 * TODO Function to deRandom.choose random items from a list 118 * @template T 119 * @param {deRandom.deRandom} rnd Initialised array of random numbers 120 * @param {Array<T>} elements Array segment already defined 121 * @param {Array<T>=} resultOut Array where to store the elements in. If undefined, default to array of (num) elements. 122 * @param {number=} num Number of items to store in resultOut. If undefined, default to 1. 123 * @return {Array<T>} Even though result is stored in resultOut, return it here as well. 124 */ 125 deRandom.choose = function(rnd, elements, resultOut, num) { 126 var items = num || 1; 127 var temp = elements.slice(); 128 if (!resultOut) 129 resultOut = []; 130 131 while (items-- > 0) { 132 var index = deRandom.deRandom_getInt(rnd, [0, temp.length - 1]); 133 resultOut.push(temp[index]); 134 temp.splice(index, 1); 135 } 136 return resultOut; 137 }; 138 139 /** 140 * TODO Function to deRandom.choose weighted random items from a list 141 * @param {deRandom.deRandom} rnd Initialised randomizer 142 * @param {Array<number>} array Array to choose items from 143 * @param {Array<number>} weights Weights array 144 * @return {number} Result output 145 */ 146 deRandom.chooseWeighted = function(rnd, array, weights) { 147 // Compute weight sum 148 /** @type {number} */ var weightSum = 0.0; 149 /** @type {number} */ var ndx; 150 for (ndx = 0; ndx < array.length; ndx++) 151 weightSum += weights[ndx]; 152 153 // Random point in 0..weightSum 154 /** @type {number} */ var p = deRandom.deRandom_getFloat(rnd, [0.0, weightSum]); 155 156 // Find item in range 157 /** @type {number} */ var lastNonZero = array.length; 158 /** @type {number} */ var curWeight = 0.0; 159 for (ndx = 0; ndx != array.length; ndx++) { 160 /** @type {number} */ var w = weights[ndx]; 161 162 curWeight += w; 163 164 if (p < curWeight) 165 return array[ndx]; 166 else if (w > 0.0) 167 lastNonZero = ndx; 168 } 169 170 assertMsgOptions(lastNonZero != array.length, 'Index went out of bounds', false, true); 171 return array[lastNonZero]; 172 }; 173 174 /** 175 * TODO Function to deRandom.shuffle an array 176 * @param {deRandom.deRandom} rnd Initialised array of random numbers 177 * @param {Array} elements Array to deRandom.shuffle 178 * @return {Array} Shuffled array 179 */ 180 deRandom.shuffle = function(rnd, elements) { 181 var index = elements.length; 182 183 while (index > 0) { 184 var random = deRandom.deRandom_getInt(rnd, [0, index - 1]); 185 index -= 1; 186 var elem = elements[index]; 187 elements[index] = elements[random]; 188 elements[random] = elem; 189 } 190 return elements; 191 }; 192 193 /** 194 * This function is used to create the deRandom.Random object and 195 * initialise the random number with a seed. 196 * It contains functions for generating random numbers in a variety of formats 197 * @constructor 198 * @param {number} seed Number to use as a seed 199 */ 200 deRandom.Random = function(seed) { 201 /** 202 * Instance of array of pseudo random numbers based on seeds 203 */ 204 this.m_rnd = new deRandom.deRandom(); 205 206 //initialise the random numbers based on seed 207 deRandom.deRandom_init(this.m_rnd, seed); 208 }; 209 210 /** 211 * Function to get random boolean 212 * @return {boolean} deRandom.Random boolean 213 */ 214 deRandom.Random.prototype.getBool = function() { return deRandom.deRandom_getBool(this.m_rnd) == true; }; 215 /** 216 * Function to get random float 217 * @param {number=} min Min for range 218 * @param {number=} max Max for range 219 * @return {number} deRandom.Random float 220 */ 221 deRandom.Random.prototype.getFloat = function(min, max) { return deRandom.deRandom_getFloat(this.m_rnd, [min, max]) }; 222 /** 223 * Function to get random int 224 * @param {number=} min Min for range 225 * @param {number=} max Max for range 226 * @return {number} deRandom.Random int 227 */ 228 deRandom.Random.prototype.getInt = function(min, max) {return deRandom.deRandom_getInt(this.m_rnd, [min, max])}; 229 /** 230 * TODO Function to deRandom.choose random items from a list 231 * @template T 232 * @param {Array<T>} elements Array segment already defined 233 * @param {Array<T>=} resultOut Array where to store the elements in. If undefined, default to array of (num) elements. 234 * @param {number=} num Number of items to store in resultOut. If undefined, default to 1. 235 * @return {Array<T>} Even though result is stored in resultOut, return it here as well. 236 */ 237 deRandom.Random.prototype.choose = function(elements, resultOut, num) {return deRandom.choose(this.m_rnd, elements, resultOut, num)}; 238 /** 239 * choose weighted random items from a list 240 * @param {Array<number>} array Array to choose items from 241 * @param {Array<number>} weights Weights array 242 * @return {number} Result output 243 */ 244 deRandom.Random.prototype.chooseWeighted = function(array, weights) {return deRandom.chooseWeighted(this.m_rnd, array, weights)}; 245 /** 246 * TODO Function to deRandom.shuffle an array 247 * @param {Array} elements Array to deRandom.shuffle 248 * @return {Array} Shuffled array 249 */ 250 deRandom.Random.prototype.shuffle = function(elements) {return deRandom.shuffle(this.m_rnd, elements)}; 251 252 /** 253 * Function to get a common base seed 254 * @return {number} constant 255 */ 256 deRandom.Random.prototype.getBaseSeed = function() { 257 return deRandom.getBaseSeed(); 258 }; 259 260 });