libfgen
0.1.15
Library for optimization using a genetic algorithm or particle swarm optimization
|
00001 /* 00002 random.c -- random number generator functions. 00003 00004 fgen -- Library for optimization using a genetic algorithm or particle swarm optimization. 00005 Copyright 2012, Harm Hanemaaijer 00006 00007 This file is part of fgen. 00008 00009 fgen is free software: you can redistribute it and/or modify it 00010 under the terms of the GNU Lesser General Public License as published 00011 by the Free Software Foundation, either version 3 of the License, or 00012 (at your option) any later version. 00013 00014 fgen is distributed in the hope that it will be useful, but WITHOUT 00015 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00016 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 00017 License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public 00020 License along with fgen. If not, see <http://www.gnu.org/licenses/>. 00021 00022 */ 00023 00024 00025 00026 #include <stdlib.h> 00027 #include <stdint.h> 00028 #include <stdio.h> 00029 #include <string.h> 00030 #include <math.h> 00031 #ifdef __GNUC__ 00032 #include <sys/time.h> 00033 #include <pthread.h> 00034 #else 00035 #include <time.h> 00036 #include <windows.h> 00037 #endif 00038 #include "fgen.h" 00039 #include "random.h" 00040 #include "error.h" 00041 00042 #ifndef __GNUC__ 00043 00044 #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) 00045 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 00046 #else 00047 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL 00048 #endif 00049 00050 void gettimeofday(struct timeval *tv, struct timezone *tz) { 00051 FILETIME ft; 00052 uint64_t tmpres = 0; 00053 if (NULL != tv) { 00054 GetSystemTimeAsFileTime(&ft); 00055 tmpres |= ft.dwHighDateTime; 00056 tmpres <<= 32; 00057 tmpres |= ft.dwLowDateTime; 00058 tmpres /= 10; /*convert into microseconds*/ 00059 /*converting file time to unix epoch*/ 00060 tmpres -= DELTA_EPOCH_IN_MICROSECS; 00061 tv->tv_sec = (long)(tmpres / 1000000UL); 00062 tv->tv_usec = (long)(tmpres % 1000000UL); 00063 } 00064 } 00065 00066 #endif 00067 00068 /* The random number generator to use. glibc slows down with mutex blocking when running concurrent threads that 00069 * call random() */ 00070 00071 // #define RANDOM_USE_GLIBC_ONLY 00072 // #define RANDOM_USE_GLIBC_OPTIMIZED 00073 #define RANDOM_USE_CMWC 00074 00075 #ifdef RANDOM_USE_CMWC 00076 00077 /* Complementary-multiply-with-carry random number generator. */ 00078 00079 #define PHI 0x9e3779b9 00080 00087 FgenRNG *fgen_random_create_rng() { 00088 FgenRNG *rng = (FgenRNG *)malloc(sizeof(FgenRNG)); 00089 rng->c = 362436; 00090 rng->index = FGEN_RNG_STATE_SIZE - 1; 00091 fgen_random_seed_rng(rng, 0); 00092 rng->storage = 0; 00093 rng->storage_size = 0; 00094 rng->last_random_n_power_of_2 = - 1; 00095 return rng; 00096 } 00097 00102 void fgen_random_destroy_rng(FgenRNG *rng) { 00103 free(rng); 00104 } 00105 00110 void fgen_random_seed_rng(FgenRNG *rng, unsigned int seed) { 00111 int i; 00112 rng->Q[0] = seed; 00113 rng->Q[1] = seed + PHI; 00114 rng->Q[2] = seed + PHI + PHI; 00115 for (i = 3; i < FGEN_RNG_STATE_SIZE; i++) 00116 rng->Q[i] = rng->Q[i - 3] ^ rng->Q[i - 2] ^ PHI ^ i; 00117 } 00118 00123 unsigned int fgen_random_32(FgenRNG *rng) { 00124 uint64_t t, a = 18782LL; 00125 unsigned int x, r = 0xfffffffe; 00126 rng->index = (rng->index + 1) & (FGEN_RNG_STATE_SIZE - 1); 00127 t = a * rng->Q[rng->index] + rng->c; 00128 rng->c = (t >> 32); 00129 x = t + rng->c; 00130 if (x < rng->c) { 00131 x++; 00132 rng->c++; 00133 } 00134 return (rng->Q[rng->index] = r - x); 00135 } 00136 00141 int fgen_random_2(FgenRNG *rng) { 00142 unsigned int r; 00143 if (rng->storage_size > 0) { 00144 int bit; 00145 bit = rng->storage & 0x1; 00146 rng->storage >>= 1; 00147 rng->storage_size--; 00148 return bit; 00149 } 00150 r = fgen_random_32(rng); 00151 rng->storage = (r & 0xFFFFFFFE) >> 1; 00152 rng->storage_size = 31; 00153 return r & 0x1; 00154 } 00155 00160 int fgen_random_8(FgenRNG *rng) { 00161 unsigned int r; 00162 if (rng->storage_size >= 8) { 00163 r = rng->storage & 0xFF; 00164 rng->storage >>= 8; 00165 rng->storage_size -= 8; 00166 return r; 00167 } 00168 r = fgen_random_32(rng); 00169 rng->storage += ((r & 0xFFFFFF00) >> 8) << rng->storage_size; 00170 rng->storage_size += 24; 00171 return r & 0xFF; 00172 } 00173 00178 int fgen_random_16(FgenRNG *rng) { 00179 unsigned int r; 00180 if (rng->storage_size >= 16) { 00181 r = rng->storage & 0xFFFF; 00182 rng->storage >>= 16; 00183 rng->storage_size -= 16; 00184 return r; 00185 } 00186 r = fgen_random_32(rng); 00187 rng->storage += ((r & 0xFFFF0000) >> 16) << rng->storage_size; 00188 rng->storage_size += 16; 00189 return r & 0xFFFF; 00190 } 00191 00192 #endif 00193 00194 00195 #ifdef RANDOM_USE_GLIBC_ONLY 00196 00202 FgenRNG *fgen_random_create_rng() { 00203 FgenRNG *rng = malloc(sizeof(FgenRNG)); 00204 fgen_random_seed_rng(rng, 0); 00205 rng->storage = 0; 00206 rng->storage_size = 0; 00207 rng->last_random_n_power_of_2 = - 1; 00208 return rng; 00209 } 00210 00215 void fgen_random_destroy_rng(FgenRNG *rng) { 00216 free(rng); 00217 } 00218 00223 void fgen_random_seed_rng(FgenRNG *rng, unsigned int seed) { 00224 srandom(seed); 00225 } 00226 00231 unsigned int fgen_random_32(FgenRNG *rng) { 00232 unsigned int r = (unsigned int)random() | (((unsigned int)random() & 0x1) << 31); 00233 return r; 00234 } 00235 00240 int fgen_random_2(FgenRNG *rng) { 00241 int r = random() & 1; 00242 return r; 00243 } 00244 00249 int fgen_random_8(FgenRNG *rng) { 00250 int r = random() & 0xFF; 00251 return r; 00252 } 00253 00258 int fgen_random_16(FgenRNG *rng) { 00259 int r = random() & 0xFFFF; 00260 return r; 00261 } 00262 00263 #endif 00264 00265 #ifdef RANDOM_USE_GLIBC_OPTIMIZED 00266 00267 /* 00268 * The random() function usually returns numbers between 0 and 2^31 - 1; 00269 * to get a 32-bit number, two calls are needed. 00270 * 00271 * We try to be smart and keep a collection of left-over 'random bits' to 00272 * reduce the number of calls to random(). 00273 * 00274 */ 00275 00281 FgenRNG *fgen_random_create_rng() { 00282 FgenRNG *rng = malloc(sizeof(FgenRNG)); 00283 fgen_random_seed_rng(rng, 0); 00284 rng->storage = 0; 00285 rng->storage_size = 0; 00286 rng->last_random_n_power_of_2 = - 1; 00287 return rng; 00288 } 00289 00294 void fgen_random_destroy_rng(FgenRNG *rng) { 00295 free(rng); 00296 } 00297 00302 void fgen_random_seed_rng(FgenRNG *rng, unsigned int seed) { 00303 srandom(seed); 00304 } 00305 00310 unsigned int fgen_random_32(FgenRNG *rng) { 00311 unsigned int r1, r2; 00312 if (rng->storage_size > 0) { 00313 /* Need one storage bit. */ 00314 unsigned int bit; 00315 bit = (rng->storage & 0x1) << 31; 00316 rng->storage >>= 1; 00317 rng->storage_size--; 00318 return random() + bit; 00319 } 00320 /* 00321 * No storage bits; do two random()'s and put the 15 + 15 = 30 extra 00322 * bits in storage. 00323 */ 00324 r1 = random(); 00325 rng->storage = (unsigned int)(r1 & 0x7FFF0000) >> 16; 00326 r2 = random(); 00327 rng->storage += (unsigned int)(r2 & 0x7FFF0000) >> 1; 00328 rng->storage_size = 30; 00329 return (r1 & 0xFFFF) + ((unsigned int)(r2 & 0xFFFF) << 16); 00330 } 00331 00336 int fgen_random_2(FgenRNG *rng) { 00337 unsigned int r; 00338 if (rng->storage_size > 0) { 00339 int bit; 00340 bit = rng->storage & 0x1; 00341 rng->storage >>= 1; 00342 rng->storage_size--; 00343 return bit; 00344 } 00345 r = fgen_random_32(rng); 00346 rng->storage = (r & 0xFFFFFFFE) >> 1; 00347 rng->storage_size = 31; 00348 return r & 0x1; 00349 } 00350 00355 int fgen_random_8(FgenRNG *rng) { 00356 unsigned int r; 00357 if (rng->storage_size >= 8) { 00358 r = rng->storage & 0xFF; 00359 rng->storage >>= 8; 00360 rng->storage_size -= 8; 00361 return r; 00362 } 00363 r = fgen_random_32(rng); 00364 rng->storage += ((r & 0xFFFFFF00) >> 8) << rng->storage_size; 00365 rng->storage_size += 24; 00366 return r & 0xFF; 00367 } 00368 00373 int fgen_random_16(FgenRNG *rng) { 00374 unsigned int r; 00375 if (rng->storage_size >= 16) { 00376 r = rng->storage & 0xFFFF; 00377 rng->storage >>= 16; 00378 rng->storage_size -= 16; 00379 return r; 00380 } 00381 r = fgen_random_32(rng); 00382 rng->storage += ((r & 0xFFFF0000) >> 16) << rng->storage_size; 00383 rng->storage_size += 16; 00384 return r & 0xFFFF; 00385 } 00386 00387 #endif 00388 00389 /* The following functions use the RNG implementation but do not not differ between implementations. */ 00390 00395 void fgen_random_seed_with_timer(FgenRNG *rng) { 00396 struct timeval tv; 00397 gettimeofday(&tv, NULL); 00398 /* The multiplication by 1000000 will overflow, but that is not important. */ 00399 fgen_random_seed_rng(rng, tv.tv_sec * 1000000 + tv.tv_usec); 00400 } 00401 00402 static char power_of_2_table[257] = { 00403 -1, 0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1 ,-1, -1, -1, 00404 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, 00405 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, 00406 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, 00407 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, 00408 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, 00409 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, 00410 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, 00411 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, 00412 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, 00413 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, 00414 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, 00415 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, 00416 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, 00417 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, 00418 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ,-1, -1, -1, 00419 8 00420 }; 00421 00422 static int fgen_random_get_bits(FgenRNG *rng, int n) { 00423 unsigned int r; 00424 unsigned int mask = (1 << n) - 1; 00425 if (rng->storage_size >= n) { 00426 r = rng->storage & mask; 00427 rng->storage >>= n; 00428 rng->storage_size -= n; 00429 return r; 00430 } 00431 r = fgen_random_32(rng); 00432 rng->storage |= ((r & (0xFFFFFFFF ^ mask)) >> n) << rng->storage_size; 00433 rng->storage_size += 32 - n; 00434 return r & mask; 00435 } 00436 00441 int fgen_random_n(FgenRNG *rng, int n) { 00442 // Fast path to most common occurence of repeating power of two. 00443 if (n == rng->last_random_n_power_of_2) { 00444 return fgen_random_get_bits(rng, rng->last_random_n_power_of_2_bit_count); 00445 } 00446 // Optimize power of two. 00447 if (n <= 256) { 00448 int bit_count = power_of_2_table[n]; 00449 if (bit_count >= 0) { 00450 rng->last_random_n_power_of_2 = n; 00451 rng->last_random_n_power_of_2_bit_count = bit_count; 00452 return fgen_random_get_bits(rng, bit_count); 00453 } 00454 return fgen_random_16(rng) % n; 00455 } 00456 if (n <= 65536 && (n & 0xFF) == 0) { 00457 int bit_count = power_of_2_table[n >> 8]; 00458 if (bit_count >= 0) { 00459 rng->last_random_n_power_of_2 = n; 00460 rng->last_random_n_power_of_2_bit_count = bit_count + 8; 00461 return fgen_random_get_bits(rng, bit_count + 8); 00462 } 00463 } 00464 return fgen_random_32(rng) % n; 00465 } 00466 00471 double fgen_random_d(FgenRNG *rng, double range) { 00472 return (double)fgen_random_32(rng) * range / ((uint64_t)1 << 32); 00473 } 00474 00479 float fgen_random_f(FgenRNG *rng, float range) { 00480 return (float)fgen_random_32(rng) * range / ((uint64_t)1 << 32); 00481 } 00482 00487 double fgen_random_from_range_d(FgenRNG *rng, double min_bound, double max_bound) { 00488 return min_bound + fgen_random_d(rng, max_bound - min_bound); 00489 } 00490 00491 /* Calculate a random permutation of the numbers 0 to (n - 1). */ 00492 00493 void CalculateRandomOrder(FgenRNG *rng, int *order, int n) { 00494 int i; 00495 for (i = 0; i < n; i++) 00496 order[i] = i; 00497 for (i = 0; i < n; i++) { 00498 int j, t; 00499 /* Swap element i with random element j. */ 00500 j = fgen_random_n(rng, n); 00501 t = order[i]; 00502 order[i] = order[j]; 00503 order[j] = t; 00504 } 00505 } 00506 00507