os/ossrv/glib/glib/grand.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/* GLIB - Library of useful routines for C programming
sl@0
     2
 * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
sl@0
     3
 * Portions copyright (c) 2006-2009 Nokia Corporation.  All rights reserved.
sl@0
     4
 * This library is free software; you can redistribute it and/or
sl@0
     5
 * modify it under the terms of the GNU Lesser General Public
sl@0
     6
 * License as published by the Free Software Foundation; either
sl@0
     7
 * version 2 of the License, or (at your option) any later version.
sl@0
     8
 *
sl@0
     9
 * This library is distributed in the hope that it will be useful,
sl@0
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
sl@0
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
sl@0
    12
 * Lesser General Public License for more details.
sl@0
    13
 *
sl@0
    14
 * You should have received a copy of the GNU Lesser General Public
sl@0
    15
 * License along with this library; if not, write to the
sl@0
    16
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
sl@0
    17
 * Boston, MA 02111-1307, USA.
sl@0
    18
 */
sl@0
    19
sl@0
    20
/* Originally developed and coded by Makoto Matsumoto and Takuji
sl@0
    21
 * Nishimura.  Please mail <matumoto@math.keio.ac.jp>, if you're using
sl@0
    22
 * code from this file in your own programs or libraries.
sl@0
    23
 * Further information on the Mersenne Twister can be found at
sl@0
    24
 * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
sl@0
    25
 * This code was adapted to glib by Sebastian Wilhelmi.
sl@0
    26
 */
sl@0
    27
sl@0
    28
/*
sl@0
    29
 * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
sl@0
    30
 * file for a list of people on the GLib Team.  See the ChangeLog
sl@0
    31
 * files for a list of changes.  These files are distributed with
sl@0
    32
 * GLib at ftp://ftp.gtk.org/pub/gtk/.  
sl@0
    33
 */
sl@0
    34
sl@0
    35
/* 
sl@0
    36
 * MT safe
sl@0
    37
 */
sl@0
    38
sl@0
    39
#include "config.h"
sl@0
    40
sl@0
    41
#include <math.h>
sl@0
    42
#include <errno.h>
sl@0
    43
#include <stdio.h>
sl@0
    44
#include <string.h>
sl@0
    45
#include <sys/types.h>
sl@0
    46
#ifdef HAVE_UNISTD_H
sl@0
    47
#include <unistd.h>
sl@0
    48
#endif
sl@0
    49
sl@0
    50
#include "glib.h"
sl@0
    51
#include "gthreadprivate.h"
sl@0
    52
#include "galias.h"
sl@0
    53
sl@0
    54
#ifdef __SYMBIAN32__
sl@0
    55
#include "glib_wsd.h"
sl@0
    56
#endif
sl@0
    57
sl@0
    58
#if EMULATOR
sl@0
    59
#define g_thread_functions_for_glib_use (*_g_thread_functions_for_glib_use())
sl@0
    60
#define g_thread_use_default_impl (*_g_thread_use_default_impl())
sl@0
    61
#endif /* EMULATOR */
sl@0
    62
sl@0
    63
#ifdef G_OS_WIN32
sl@0
    64
#include <process.h>		/* For getpid() */
sl@0
    65
#endif
sl@0
    66
sl@0
    67
#if EMULATOR
sl@0
    68
sl@0
    69
PLS_MACRO(global_random,grand,GStaticMutex)
sl@0
    70
PLS(global_random,grand,GRand *)
sl@0
    71
sl@0
    72
#define g__global_random_lock (*FUNCTION_NAME_MACRO(global_random,grand)())
sl@0
    73
#define global_random (*FUNCTION_NAME(global_random,grand)())
sl@0
    74
sl@0
    75
#else
sl@0
    76
sl@0
    77
G_LOCK_DEFINE_STATIC (global_random);
sl@0
    78
static GRand* global_random = NULL;
sl@0
    79
sl@0
    80
#endif /* EMULATOR */
sl@0
    81
sl@0
    82
/* Period parameters */  
sl@0
    83
#define N 624
sl@0
    84
#define M 397
sl@0
    85
#define MATRIX_A 0x9908b0df   /* constant vector a */
sl@0
    86
#define UPPER_MASK 0x80000000 /* most significant w-r bits */
sl@0
    87
#define LOWER_MASK 0x7fffffff /* least significant r bits */
sl@0
    88
sl@0
    89
/* Tempering parameters */   
sl@0
    90
#define TEMPERING_MASK_B 0x9d2c5680
sl@0
    91
#define TEMPERING_MASK_C 0xefc60000
sl@0
    92
#define TEMPERING_SHIFT_U(y)  (y >> 11)
sl@0
    93
#define TEMPERING_SHIFT_S(y)  (y << 7)
sl@0
    94
#define TEMPERING_SHIFT_T(y)  (y << 15)
sl@0
    95
#define TEMPERING_SHIFT_L(y)  (y >> 18)
sl@0
    96
sl@0
    97
#if EMULATOR
sl@0
    98
sl@0
    99
PLS(initialized ,get_random_version,gboolean)
sl@0
   100
PLS(random_version ,get_random_version,guint)
sl@0
   101
sl@0
   102
#define initialized (*FUNCTION_NAME(initialized,get_random_version)())
sl@0
   103
#define random_version (*FUNCTION_NAME(random_version,get_random_version)())
sl@0
   104
sl@0
   105
#endif /* EMULATOR */
sl@0
   106
sl@0
   107
static guint
sl@0
   108
get_random_version (void)
sl@0
   109
{
sl@0
   110
  #if !(EMULATOR)
sl@0
   111
  static gboolean initialized = FALSE;
sl@0
   112
  static guint random_version;
sl@0
   113
  #endif /* EMULATOR */
sl@0
   114
  
sl@0
   115
  if (!initialized)
sl@0
   116
    {
sl@0
   117
      const gchar *version_string = g_getenv ("G_RANDOM_VERSION");
sl@0
   118
      if (!version_string || version_string[0] == '\000' || 
sl@0
   119
	  strcmp (version_string, "2.2") == 0)
sl@0
   120
	random_version = 22;
sl@0
   121
      else if (strcmp (version_string, "2.0") == 0)
sl@0
   122
	random_version = 20;
sl@0
   123
      else
sl@0
   124
	{
sl@0
   125
	  g_warning ("Unknown G_RANDOM_VERSION \"%s\". Using version 2.2.",
sl@0
   126
		     version_string);
sl@0
   127
	  random_version = 22;
sl@0
   128
	}
sl@0
   129
      initialized = TRUE;
sl@0
   130
    }
sl@0
   131
  
sl@0
   132
  return random_version;
sl@0
   133
}
sl@0
   134
sl@0
   135
#if EMULATOR
sl@0
   136
#undef initialized
sl@0
   137
#undef random_version
sl@0
   138
#endif /* EMULATOR */
sl@0
   139
sl@0
   140
/* This is called from g_thread_init(). It's used to
sl@0
   141
 * initialize some static data in a threadsafe way.
sl@0
   142
 */
sl@0
   143
void 
sl@0
   144
_g_rand_thread_init (void)
sl@0
   145
{
sl@0
   146
  (void)get_random_version ();
sl@0
   147
}
sl@0
   148
sl@0
   149
struct _GRand
sl@0
   150
{
sl@0
   151
  guint32 mt[N]; /* the array for the state vector  */
sl@0
   152
  guint mti; 
sl@0
   153
};
sl@0
   154
sl@0
   155
/**
sl@0
   156
 * g_rand_new_with_seed:
sl@0
   157
 * @seed: a value to initialize the random number generator.
sl@0
   158
 * 
sl@0
   159
 * Creates a new random number generator initialized with @seed.
sl@0
   160
 * 
sl@0
   161
 * Return value: the new #GRand.
sl@0
   162
 **/
sl@0
   163
EXPORT_C GRand*
sl@0
   164
g_rand_new_with_seed (guint32 seed)
sl@0
   165
{
sl@0
   166
  GRand *rand = g_new0 (GRand, 1);
sl@0
   167
  g_rand_set_seed (rand, seed);
sl@0
   168
  return rand;
sl@0
   169
}
sl@0
   170
sl@0
   171
/**
sl@0
   172
 * g_rand_new_with_seed_array:
sl@0
   173
 * @seed: an array of seeds to initialize the random number generator.
sl@0
   174
 * @seed_length: an array of seeds to initialize the random number generator.
sl@0
   175
 * 
sl@0
   176
 * Creates a new random number generator initialized with @seed.
sl@0
   177
 * 
sl@0
   178
 * Return value: the new #GRand.
sl@0
   179
 *
sl@0
   180
 * Since: 2.4
sl@0
   181
 **/
sl@0
   182
EXPORT_C GRand*
sl@0
   183
g_rand_new_with_seed_array (const guint32 *seed, guint seed_length)
sl@0
   184
{
sl@0
   185
  GRand *rand = g_new0 (GRand, 1);
sl@0
   186
  g_rand_set_seed_array (rand, seed, seed_length);
sl@0
   187
  return rand;
sl@0
   188
}
sl@0
   189
sl@0
   190
/**
sl@0
   191
 * g_rand_new:
sl@0
   192
 * 
sl@0
   193
 * Creates a new random number generator initialized with a seed taken
sl@0
   194
 * either from <filename>/dev/urandom</filename> (if existing) or from 
sl@0
   195
 * the current time (as a fallback).
sl@0
   196
 * 
sl@0
   197
 * Return value: the new #GRand.
sl@0
   198
 **/
sl@0
   199
sl@0
   200
#if EMULATOR
sl@0
   201
sl@0
   202
PLS(dev_urandom_exists,g_rand_new ,gboolean)
sl@0
   203
#define dev_urandom_exists (*FUNCTION_NAME(dev_urandom_exists,g_rand_new )())
sl@0
   204
sl@0
   205
#endif /* EMULATOR */
sl@0
   206
sl@0
   207
EXPORT_C GRand* 
sl@0
   208
g_rand_new (void)
sl@0
   209
{
sl@0
   210
  guint32 seed[4];
sl@0
   211
  GTimeVal now;
sl@0
   212
#ifdef G_OS_UNIX
sl@0
   213
  static gboolean dev_urandom_exists = TRUE;
sl@0
   214
sl@0
   215
  if (dev_urandom_exists)
sl@0
   216
    {
sl@0
   217
      FILE* dev_urandom;
sl@0
   218
sl@0
   219
      do
sl@0
   220
        {
sl@0
   221
	  errno = 0;
sl@0
   222
	  dev_urandom = fopen("/dev/urandom", "rb");
sl@0
   223
	}
sl@0
   224
      while G_UNLIKELY (errno == EINTR);
sl@0
   225
sl@0
   226
      if (dev_urandom)
sl@0
   227
	{
sl@0
   228
	  int r;
sl@0
   229
sl@0
   230
	  do
sl@0
   231
	    {
sl@0
   232
	      errno = 0;
sl@0
   233
	      r = fread (seed, sizeof (seed), 1, dev_urandom);
sl@0
   234
	    }
sl@0
   235
	  while G_UNLIKELY (errno == EINTR);
sl@0
   236
sl@0
   237
	  if (r != 1)
sl@0
   238
	    dev_urandom_exists = FALSE;
sl@0
   239
sl@0
   240
	  fclose (dev_urandom);
sl@0
   241
	}	
sl@0
   242
      else
sl@0
   243
	dev_urandom_exists = FALSE;
sl@0
   244
    }
sl@0
   245
#else
sl@0
   246
  #if !(EMULATOR)
sl@0
   247
  static gboolean dev_urandom_exists = FALSE;
sl@0
   248
  #endif /* EMULATOR */
sl@0
   249
#endif
sl@0
   250
sl@0
   251
  if (!dev_urandom_exists)
sl@0
   252
    {  
sl@0
   253
      g_get_current_time (&now);
sl@0
   254
      seed[0] = now.tv_sec;
sl@0
   255
      seed[1] = now.tv_usec;
sl@0
   256
      seed[2] = getpid ();
sl@0
   257
#ifdef G_OS_UNIX
sl@0
   258
      seed[3] = getppid ();
sl@0
   259
#else
sl@0
   260
      seed[3] = 0;
sl@0
   261
#endif
sl@0
   262
    }
sl@0
   263
sl@0
   264
  return g_rand_new_with_seed_array (seed, 4);
sl@0
   265
}
sl@0
   266
sl@0
   267
#if EMULATOR
sl@0
   268
#undef dev_urandom_exists 
sl@0
   269
#endif /* EMULATOR */
sl@0
   270
sl@0
   271
/**
sl@0
   272
 * g_rand_free:
sl@0
   273
 * @rand_: a #GRand.
sl@0
   274
 *
sl@0
   275
 * Frees the memory allocated for the #GRand.
sl@0
   276
 **/
sl@0
   277
EXPORT_C void
sl@0
   278
g_rand_free (GRand* rand)
sl@0
   279
{
sl@0
   280
  g_return_if_fail (rand != NULL);
sl@0
   281
sl@0
   282
  g_free (rand);
sl@0
   283
}
sl@0
   284
sl@0
   285
/**
sl@0
   286
 * g_rand_copy:
sl@0
   287
 * @rand_: a #GRand.
sl@0
   288
 *
sl@0
   289
 * Copies a #GRand into a new one with the same exact state as before.
sl@0
   290
 * This way you can take a snapshot of the random number generator for
sl@0
   291
 * replaying later.
sl@0
   292
 *
sl@0
   293
 * Return value: the new #GRand.
sl@0
   294
 *
sl@0
   295
 * Since: 2.4
sl@0
   296
 **/
sl@0
   297
EXPORT_C GRand *
sl@0
   298
g_rand_copy (GRand* rand)
sl@0
   299
{
sl@0
   300
  GRand* new_rand;
sl@0
   301
sl@0
   302
  g_return_val_if_fail (rand != NULL, NULL);
sl@0
   303
sl@0
   304
  new_rand = g_new0 (GRand, 1);
sl@0
   305
  memcpy (new_rand, rand, sizeof (GRand));
sl@0
   306
sl@0
   307
  return new_rand;
sl@0
   308
}
sl@0
   309
sl@0
   310
/**
sl@0
   311
 * g_rand_set_seed:
sl@0
   312
 * @rand_: a #GRand.
sl@0
   313
 * @seed: a value to reinitialize the random number generator.
sl@0
   314
 *
sl@0
   315
 * Sets the seed for the random number generator #GRand to @seed.
sl@0
   316
 **/
sl@0
   317
EXPORT_C void
sl@0
   318
g_rand_set_seed (GRand* rand, guint32 seed)
sl@0
   319
{
sl@0
   320
  g_return_if_fail (rand != NULL);
sl@0
   321
sl@0
   322
  switch (get_random_version ())
sl@0
   323
    {
sl@0
   324
    case 20:
sl@0
   325
      /* setting initial seeds to mt[N] using         */
sl@0
   326
      /* the generator Line 25 of Table 1 in          */
sl@0
   327
      /* [KNUTH 1981, The Art of Computer Programming */
sl@0
   328
      /*    Vol. 2 (2nd Ed.), pp102]                  */
sl@0
   329
      
sl@0
   330
      if (seed == 0) /* This would make the PRNG procude only zeros */
sl@0
   331
	seed = 0x6b842128; /* Just set it to another number */
sl@0
   332
      
sl@0
   333
      rand->mt[0]= seed;
sl@0
   334
      for (rand->mti=1; rand->mti<N; rand->mti++)
sl@0
   335
	rand->mt[rand->mti] = (69069 * rand->mt[rand->mti-1]);
sl@0
   336
      
sl@0
   337
      break;
sl@0
   338
    case 22:
sl@0
   339
      /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
sl@0
   340
      /* In the previous version (see above), MSBs of the    */
sl@0
   341
      /* seed affect only MSBs of the array mt[].            */
sl@0
   342
      
sl@0
   343
      rand->mt[0]= seed;
sl@0
   344
      for (rand->mti=1; rand->mti<N; rand->mti++)
sl@0
   345
	rand->mt[rand->mti] = 1812433253UL * 
sl@0
   346
	  (rand->mt[rand->mti-1] ^ (rand->mt[rand->mti-1] >> 30)) + rand->mti; 
sl@0
   347
      break;
sl@0
   348
    default:
sl@0
   349
      g_assert_not_reached ();
sl@0
   350
    }
sl@0
   351
}
sl@0
   352
sl@0
   353
/**
sl@0
   354
 * g_rand_set_seed_array:
sl@0
   355
 * @rand_: a #GRand.
sl@0
   356
 * @seed: array to initialize with
sl@0
   357
 * @seed_length: length of array
sl@0
   358
 *
sl@0
   359
 * Initializes the random number generator by an array of
sl@0
   360
 * longs.  Array can be of arbitrary size, though only the
sl@0
   361
 * first 624 values are taken.  This function is useful
sl@0
   362
 * if you have many low entropy seeds, or if you require more then
sl@0
   363
 * 32bits of actual entropy for your application.
sl@0
   364
 *
sl@0
   365
 * Since: 2.4
sl@0
   366
 **/
sl@0
   367
EXPORT_C void
sl@0
   368
g_rand_set_seed_array (GRand* rand, const guint32 *seed, guint seed_length)
sl@0
   369
{
sl@0
   370
  int i, j, k;
sl@0
   371
sl@0
   372
  g_return_if_fail (rand != NULL);
sl@0
   373
  g_return_if_fail (seed_length >= 1);
sl@0
   374
sl@0
   375
  g_rand_set_seed (rand, 19650218UL);
sl@0
   376
sl@0
   377
  i=1; j=0;
sl@0
   378
  k = (N>seed_length ? N : seed_length);
sl@0
   379
  for (; k; k--)
sl@0
   380
    {
sl@0
   381
      rand->mt[i] = (rand->mt[i] ^
sl@0
   382
		     ((rand->mt[i-1] ^ (rand->mt[i-1] >> 30)) * 1664525UL))
sl@0
   383
	      + seed[j] + j; /* non linear */
sl@0
   384
      rand->mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
sl@0
   385
      i++; j++;
sl@0
   386
      if (i>=N)
sl@0
   387
        {
sl@0
   388
	  rand->mt[0] = rand->mt[N-1];
sl@0
   389
	  i=1;
sl@0
   390
	}
sl@0
   391
      if (j>=seed_length)
sl@0
   392
	j=0;
sl@0
   393
    }
sl@0
   394
  for (k=N-1; k; k--)
sl@0
   395
    {
sl@0
   396
      rand->mt[i] = (rand->mt[i] ^
sl@0
   397
		     ((rand->mt[i-1] ^ (rand->mt[i-1] >> 30)) * 1566083941UL))
sl@0
   398
	      - i; /* non linear */
sl@0
   399
      rand->mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
sl@0
   400
      i++;
sl@0
   401
      if (i>=N)
sl@0
   402
        {
sl@0
   403
	  rand->mt[0] = rand->mt[N-1];
sl@0
   404
	  i=1;
sl@0
   405
	}
sl@0
   406
    }
sl@0
   407
sl@0
   408
  rand->mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ 
sl@0
   409
}
sl@0
   410
sl@0
   411
/**
sl@0
   412
 * g_rand_int:
sl@0
   413
 * @rand_: a #GRand.
sl@0
   414
 *
sl@0
   415
 * Returns the next random #guint32 from @rand_ equally distributed over
sl@0
   416
 * the range [0..2^32-1].
sl@0
   417
 *
sl@0
   418
 * Return value: A random number.
sl@0
   419
 **/
sl@0
   420
EXPORT_C guint32
sl@0
   421
g_rand_int (GRand* rand)
sl@0
   422
{
sl@0
   423
  guint32 y;
sl@0
   424
  static const guint32 mag01[2]={0x0, MATRIX_A};
sl@0
   425
  /* mag01[x] = x * MATRIX_A  for x=0,1 */
sl@0
   426
sl@0
   427
  g_return_val_if_fail (rand != NULL, 0);
sl@0
   428
sl@0
   429
  if (rand->mti >= N) { /* generate N words at one time */
sl@0
   430
    int kk;
sl@0
   431
    
sl@0
   432
    for (kk=0;kk<N-M;kk++) {
sl@0
   433
      y = (rand->mt[kk]&UPPER_MASK)|(rand->mt[kk+1]&LOWER_MASK);
sl@0
   434
      rand->mt[kk] = rand->mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1];
sl@0
   435
    }
sl@0
   436
    for (;kk<N-1;kk++) {
sl@0
   437
      y = (rand->mt[kk]&UPPER_MASK)|(rand->mt[kk+1]&LOWER_MASK);
sl@0
   438
      rand->mt[kk] = rand->mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1];
sl@0
   439
    }
sl@0
   440
    y = (rand->mt[N-1]&UPPER_MASK)|(rand->mt[0]&LOWER_MASK);
sl@0
   441
    rand->mt[N-1] = rand->mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1];
sl@0
   442
    
sl@0
   443
    rand->mti = 0;
sl@0
   444
  }
sl@0
   445
  
sl@0
   446
  y = rand->mt[rand->mti++];
sl@0
   447
  y ^= TEMPERING_SHIFT_U(y);
sl@0
   448
  y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B;
sl@0
   449
  y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C;
sl@0
   450
  y ^= TEMPERING_SHIFT_L(y);
sl@0
   451
  
sl@0
   452
  return y; 
sl@0
   453
}
sl@0
   454
sl@0
   455
/* transform [0..2^32] -> [0..1] */
sl@0
   456
#define G_RAND_DOUBLE_TRANSFORM 2.3283064365386962890625e-10
sl@0
   457
sl@0
   458
/**
sl@0
   459
 * g_rand_int_range:
sl@0
   460
 * @rand_: a #GRand.
sl@0
   461
 * @begin: lower closed bound of the interval.
sl@0
   462
 * @end: upper open bound of the interval.
sl@0
   463
 *
sl@0
   464
 * Returns the next random #gint32 from @rand_ equally distributed over
sl@0
   465
 * the range [@begin..@end-1].
sl@0
   466
 *
sl@0
   467
 * Return value: A random number.
sl@0
   468
 **/
sl@0
   469
EXPORT_C gint32 
sl@0
   470
g_rand_int_range (GRand* rand, gint32 begin, gint32 end)
sl@0
   471
{
sl@0
   472
  guint32 dist = end - begin;
sl@0
   473
  guint32 random;
sl@0
   474
sl@0
   475
  g_return_val_if_fail (rand != NULL, begin);
sl@0
   476
  g_return_val_if_fail (end > begin, begin);
sl@0
   477
sl@0
   478
  switch (get_random_version ())
sl@0
   479
    {
sl@0
   480
    case 20:
sl@0
   481
      if (dist <= 0x10000L) /* 2^16 */
sl@0
   482
	{
sl@0
   483
	  /* This method, which only calls g_rand_int once is only good
sl@0
   484
	   * for (end - begin) <= 2^16, because we only have 32 bits set
sl@0
   485
	   * from the one call to g_rand_int (). */
sl@0
   486
	  
sl@0
   487
	  /* we are using (trans + trans * trans), because g_rand_int only
sl@0
   488
	   * covers [0..2^32-1] and thus g_rand_int * trans only covers
sl@0
   489
	   * [0..1-2^-32], but the biggest double < 1 is 1-2^-52. 
sl@0
   490
	   */
sl@0
   491
	  
sl@0
   492
	  gdouble double_rand = g_rand_int (rand) * 
sl@0
   493
	    (G_RAND_DOUBLE_TRANSFORM +
sl@0
   494
	     G_RAND_DOUBLE_TRANSFORM * G_RAND_DOUBLE_TRANSFORM);
sl@0
   495
	  
sl@0
   496
	  random = (gint32) (double_rand * dist);
sl@0
   497
	}
sl@0
   498
      else
sl@0
   499
	{
sl@0
   500
	  /* Now we use g_rand_double_range (), which will set 52 bits for
sl@0
   501
	     us, so that it is safe to round and still get a decent
sl@0
   502
	     distribution */
sl@0
   503
	  random = (gint32) g_rand_double_range (rand, 0, dist);
sl@0
   504
	}
sl@0
   505
      break;
sl@0
   506
    case 22:
sl@0
   507
      if (dist == 0)
sl@0
   508
	random = 0;
sl@0
   509
      else 
sl@0
   510
	{
sl@0
   511
	  /* maxvalue is set to the predecessor of the greatest
sl@0
   512
	   * multiple of dist less or equal 2^32. */
sl@0
   513
	  guint32 maxvalue;
sl@0
   514
	  if (dist <= 0x80000000u) /* 2^31 */
sl@0
   515
	    {
sl@0
   516
	      /* maxvalue = 2^32 - 1 - (2^32 % dist) */
sl@0
   517
	      guint32 leftover = (0x80000000u % dist) * 2;
sl@0
   518
	      if (leftover >= dist) leftover -= dist;
sl@0
   519
	      maxvalue = 0xffffffffu - leftover;
sl@0
   520
	    }
sl@0
   521
	  else
sl@0
   522
	    maxvalue = dist - 1;
sl@0
   523
	  
sl@0
   524
	  do
sl@0
   525
	    random = g_rand_int (rand);
sl@0
   526
	  while (random > maxvalue);
sl@0
   527
	  
sl@0
   528
	  random %= dist;
sl@0
   529
	}
sl@0
   530
      break;
sl@0
   531
    default:
sl@0
   532
      random = 0;		/* Quiet GCC */
sl@0
   533
      g_assert_not_reached ();
sl@0
   534
    }      
sl@0
   535
 
sl@0
   536
  return begin + random;
sl@0
   537
}
sl@0
   538
sl@0
   539
/**
sl@0
   540
 * g_rand_double:
sl@0
   541
 * @rand_: a #GRand.
sl@0
   542
 *
sl@0
   543
 * Returns the next random #gdouble from @rand_ equally distributed over
sl@0
   544
 * the range [0..1).
sl@0
   545
 *
sl@0
   546
 * Return value: A random number.
sl@0
   547
 **/
sl@0
   548
EXPORT_C gdouble 
sl@0
   549
g_rand_double (GRand* rand)
sl@0
   550
{    
sl@0
   551
  /* We set all 52 bits after the point for this, not only the first
sl@0
   552
     32. Thats why we need two calls to g_rand_int */
sl@0
   553
  gdouble retval = g_rand_int (rand) * G_RAND_DOUBLE_TRANSFORM;
sl@0
   554
  retval = (retval + g_rand_int (rand)) * G_RAND_DOUBLE_TRANSFORM;
sl@0
   555
sl@0
   556
  /* The following might happen due to very bad rounding luck, but
sl@0
   557
   * actually this should be more than rare, we just try again then */
sl@0
   558
  if (retval >= 1.0) 
sl@0
   559
    return g_rand_double (rand);
sl@0
   560
sl@0
   561
  return retval;
sl@0
   562
}
sl@0
   563
sl@0
   564
/**
sl@0
   565
 * g_rand_double_range:
sl@0
   566
 * @rand_: a #GRand.
sl@0
   567
 * @begin: lower closed bound of the interval.
sl@0
   568
 * @end: upper open bound of the interval.
sl@0
   569
 *
sl@0
   570
 * Returns the next random #gdouble from @rand_ equally distributed over
sl@0
   571
 * the range [@begin..@end).
sl@0
   572
 *
sl@0
   573
 * Return value: A random number.
sl@0
   574
 **/
sl@0
   575
EXPORT_C gdouble 
sl@0
   576
g_rand_double_range (GRand* rand, gdouble begin, gdouble end)
sl@0
   577
{
sl@0
   578
  return g_rand_double (rand) * (end - begin) + begin;
sl@0
   579
}
sl@0
   580
sl@0
   581
/**
sl@0
   582
 * g_random_int:
sl@0
   583
 *
sl@0
   584
 * Return a random #guint32 equally distributed over the range
sl@0
   585
 * [0..2^32-1].
sl@0
   586
 *
sl@0
   587
 * Return value: A random number.
sl@0
   588
 **/
sl@0
   589
EXPORT_C guint32
sl@0
   590
g_random_int (void)
sl@0
   591
{
sl@0
   592
  guint32 result;
sl@0
   593
sl@0
   594
  #if EMULATOR
sl@0
   595
  #undef global_random
sl@0
   596
  #endif /* EMULATOR */
sl@0
   597
sl@0
   598
  G_LOCK (global_random);
sl@0
   599
sl@0
   600
  #if EMULATOR
sl@0
   601
  #define global_random (*FUNCTION_NAME(global_random,grand)())
sl@0
   602
  #endif /* EMULATOR */
sl@0
   603
sl@0
   604
  if (!global_random)
sl@0
   605
    global_random = g_rand_new ();
sl@0
   606
  
sl@0
   607
  result = g_rand_int (global_random);
sl@0
   608
sl@0
   609
  #if EMULATOR
sl@0
   610
  #undef global_random
sl@0
   611
  #endif /* EMULATOR */
sl@0
   612
sl@0
   613
  G_UNLOCK (global_random);
sl@0
   614
sl@0
   615
  #if EMULATOR
sl@0
   616
  #define global_random (*FUNCTION_NAME(global_random,grand)())
sl@0
   617
  #endif /* EMULATOR */
sl@0
   618
sl@0
   619
  return result;
sl@0
   620
}
sl@0
   621
sl@0
   622
/**
sl@0
   623
 * g_random_int_range:
sl@0
   624
 * @begin: lower closed bound of the interval.
sl@0
   625
 * @end: upper open bound of the interval.
sl@0
   626
 *
sl@0
   627
 * Returns a random #gint32 equally distributed over the range
sl@0
   628
 * [@begin..@end-1].
sl@0
   629
 *
sl@0
   630
 * Return value: A random number.
sl@0
   631
 **/
sl@0
   632
EXPORT_C gint32 
sl@0
   633
g_random_int_range (gint32 begin, gint32 end)
sl@0
   634
{
sl@0
   635
  gint32 result;
sl@0
   636
  #if EMULATOR
sl@0
   637
  #undef global_random
sl@0
   638
  #endif /* EMULATOR */
sl@0
   639
sl@0
   640
  G_LOCK (global_random);
sl@0
   641
sl@0
   642
  #if EMULATOR
sl@0
   643
  #define global_random (*FUNCTION_NAME(global_random,grand)())
sl@0
   644
  #endif /* EMULATOR */
sl@0
   645
sl@0
   646
  if (!global_random)
sl@0
   647
    global_random = g_rand_new ();
sl@0
   648
  
sl@0
   649
  result = g_rand_int_range (global_random, begin, end);
sl@0
   650
  #if EMULATOR
sl@0
   651
  #undef global_random
sl@0
   652
  #endif /* EMULATOR */
sl@0
   653
sl@0
   654
  G_UNLOCK (global_random);
sl@0
   655
sl@0
   656
  #if EMULATOR
sl@0
   657
  #define global_random (*FUNCTION_NAME(global_random,grand)())
sl@0
   658
  #endif /* EMULATOR */
sl@0
   659
sl@0
   660
  return result;
sl@0
   661
}
sl@0
   662
sl@0
   663
/**
sl@0
   664
 * g_random_double:
sl@0
   665
 *
sl@0
   666
 * Returns a random #gdouble equally distributed over the range [0..1).
sl@0
   667
 *
sl@0
   668
 * Return value: A random number.
sl@0
   669
 **/
sl@0
   670
EXPORT_C gdouble 
sl@0
   671
g_random_double (void)
sl@0
   672
{
sl@0
   673
  double result;
sl@0
   674
  #if EMULATOR
sl@0
   675
  #undef global_random
sl@0
   676
  #endif /* EMULATOR */
sl@0
   677
sl@0
   678
  G_LOCK (global_random);
sl@0
   679
sl@0
   680
  #if EMULATOR
sl@0
   681
  #define global_random (*FUNCTION_NAME(global_random,grand)())
sl@0
   682
  #endif /* EMULATOR */
sl@0
   683
sl@0
   684
  if (!global_random)
sl@0
   685
    global_random = g_rand_new ();
sl@0
   686
  
sl@0
   687
  result = g_rand_double (global_random);
sl@0
   688
  #if EMULATOR
sl@0
   689
  #undef global_random
sl@0
   690
  #endif /* EMULATOR */
sl@0
   691
sl@0
   692
  G_UNLOCK (global_random);
sl@0
   693
sl@0
   694
  #if EMULATOR
sl@0
   695
  #define global_random (*FUNCTION_NAME(global_random,grand)())
sl@0
   696
  #endif /* EMULATOR */
sl@0
   697
sl@0
   698
  return result;
sl@0
   699
}
sl@0
   700
sl@0
   701
/**
sl@0
   702
 * g_random_double_range:
sl@0
   703
 * @begin: lower closed bound of the interval.
sl@0
   704
 * @end: upper open bound of the interval.
sl@0
   705
 *
sl@0
   706
 * Returns a random #gdouble equally distributed over the range [@begin..@end).
sl@0
   707
 *
sl@0
   708
 * Return value: A random number.
sl@0
   709
 **/
sl@0
   710
EXPORT_C gdouble 
sl@0
   711
g_random_double_range (gdouble begin, gdouble end)
sl@0
   712
{
sl@0
   713
  double result;
sl@0
   714
  #if EMULATOR
sl@0
   715
  #undef global_random
sl@0
   716
  #endif /* EMULATOR */
sl@0
   717
sl@0
   718
  G_LOCK (global_random);
sl@0
   719
sl@0
   720
  #if EMULATOR
sl@0
   721
  #define global_random (*FUNCTION_NAME(global_random,grand)())
sl@0
   722
  #endif /* EMULATOR */
sl@0
   723
sl@0
   724
  if (!global_random)
sl@0
   725
    global_random = g_rand_new ();
sl@0
   726
 
sl@0
   727
  result = g_rand_double_range (global_random, begin, end);
sl@0
   728
  #if EMULATOR
sl@0
   729
  #undef global_random
sl@0
   730
  #endif /* EMULATOR */
sl@0
   731
sl@0
   732
  G_UNLOCK (global_random);
sl@0
   733
sl@0
   734
  #if EMULATOR
sl@0
   735
  #define global_random (*FUNCTION_NAME(global_random,grand)())
sl@0
   736
  #endif /* EMULATOR */
sl@0
   737
sl@0
   738
  return result;
sl@0
   739
}
sl@0
   740
sl@0
   741
/**
sl@0
   742
 * g_random_set_seed:
sl@0
   743
 * @seed: a value to reinitialize the global random number generator.
sl@0
   744
 * 
sl@0
   745
 * Sets the seed for the global random number generator, which is used
sl@0
   746
 * by the <function>g_random_*</function> functions, to @seed.
sl@0
   747
 **/
sl@0
   748
EXPORT_C void
sl@0
   749
g_random_set_seed (guint32 seed)
sl@0
   750
{
sl@0
   751
  #if EMULATOR
sl@0
   752
  #undef global_random
sl@0
   753
  #endif /* EMULATOR */
sl@0
   754
sl@0
   755
  G_LOCK (global_random);
sl@0
   756
sl@0
   757
  #if EMULATOR
sl@0
   758
  #define global_random (*FUNCTION_NAME(global_random,grand)())
sl@0
   759
  #endif /* EMULATOR */
sl@0
   760
sl@0
   761
  if (!global_random)
sl@0
   762
    global_random = g_rand_new_with_seed (seed);
sl@0
   763
  else
sl@0
   764
    g_rand_set_seed (global_random, seed);
sl@0
   765
sl@0
   766
  #if EMULATOR
sl@0
   767
  #undef global_random
sl@0
   768
  #endif /* EMULATOR */
sl@0
   769
sl@0
   770
  G_UNLOCK (global_random);
sl@0
   771
sl@0
   772
  #if EMULATOR
sl@0
   773
  #define global_random (*FUNCTION_NAME(global_random,grand)())
sl@0
   774
  #endif /* EMULATOR */
sl@0
   775
sl@0
   776
}
sl@0
   777
sl@0
   778
sl@0
   779
#define __G_RAND_C__
sl@0
   780
#include "galiasdef.c"