libfgen  0.1.15
Library for optimization using a genetic algorithm or particle swarm optimization
random.c
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 
 All Data Structures Functions Variables