Statistics for MySQL  1.1
 All Classes Files Functions Variables Typedefs Macros Pages
sqlrand.cc
Go to the documentation of this file.
1 /* sqlrand.cc (Random numbers) */
2 
3 /***********************************************************************
4 * This code is part of Statistics for MySQL.
5 *
6 * Copyright (C) 2011 Heinrich Schuchardt (xypron.glpk@gmx.de)
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 ***********************************************************************/
20 
27 #include "sqlrand.h"
28 #include "sqlthread.h"
29 #include <stdlib.h>
30 #include <time.h>
31 #include <math.h>
32 
33 #include <stdio.h>
34 
35 namespace sqlstat {
36 
37 static pthread_mutex_t THR_LOCK_mt;
38 static pthread_mutex_t THR_LOCK_gaussian;
39 static bool mt_initialized = false;
40 static int mt_index;
41 static unsigned long mt_buffer[MT_LEN];
42 static double nextGaussian;
43 static bool haveNextGaussian = false;
44 
46  pthread_mutex_destroy(&THR_LOCK_gaussian);
47  pthread_mutex_destroy(&THR_LOCK_mt);
48  mt_initialized = false;
49 }
50 
52  int i;
53  if (mt_initialized) {
54  return;
55  }
56  pthread_mutex_init(&THR_LOCK_mt, NULL);
57  pthread_mutex_init(&THR_LOCK_gaussian, NULL);
58  pthread_mutex_lock(&THR_LOCK_mt);
59  mt_initialized = true;
60  srand((unsigned int) time(NULL));
61  for (i = 0; i < MT_LEN; i++) {
62  mt_buffer[i] = (unsigned long) rand() << 16;
63  mt_buffer[i] += (unsigned long) rand() & 0xFFFF;
64  }
65  mt_index = MT_LEN;
66  pthread_mutex_unlock(&THR_LOCK_mt);
67 }
68 
69 unsigned long MersenneTwister::random() {
70  unsigned long s;
71  unsigned long r;
72  int i;
73 
74  init();
75  pthread_mutex_lock(&THR_LOCK_mt);
76 
77  if (mt_index >= MT_LEN) {
78  mt_index = 0;
79  i = 0;
80  for (; i < MT_IB; i++) {
81  s = TWIST(mt_buffer, i, i+1);
82  mt_buffer[i] = mt_buffer[i + MT_IA] ^ (s >> 1) ^ MAGIC(s);
83  }
84  for (; i < MT_LEN-1; i++) {
85  s = TWIST(mt_buffer, i, i+1);
86  mt_buffer[i] = mt_buffer[i - MT_IB] ^ (s >> 1) ^ MAGIC(s);
87  }
88 
89  s = TWIST(mt_buffer, MT_LEN-1, 0);
90  mt_buffer[MT_LEN-1] = mt_buffer[MT_IA-1] ^ (s >> 1) ^ MAGIC(s);
91  }
92  mt_index++;
93  r = mt_buffer[mt_index];
94  pthread_mutex_unlock(&THR_LOCK_mt);
95  /* Tempering transform to compensate for the reduced dimensionality of
96  * equidistribution */
97  r ^= (r >> 11);
98  r ^= (r << 7) & 0x9D2C5680;
99  r ^= (r << 15) & 0xEFC60000;
100  r ^= (r >> 18);
101  return r;
102 }
103 
105  return (double)
106  ((((unsigned long long) random() & 0x00000000FFFFFFC0L) << 21)
107  ^ ((unsigned long long) random() >> 5))
108  / (double) 0x0020000000000000L;
109 }
110 
112  double a1, a2, q, ret;
113  pthread_mutex_lock(&THR_LOCK_gaussian);
114  if (haveNextGaussian) {
115  haveNextGaussian = false;
116  ret = nextGaussian;
117  } else {
118  do {
119  a1 = 2. * nextDouble() - 1.;
120  a2 = 2. * nextDouble() - 1.;
121  q = a1 * a1 + a2 * a2;
122  } while ( q <= 0 || q > 1 );
123  q = sqrt(-2 * log(q) / q );
124  nextGaussian = a1 * q;
125  haveNextGaussian = true;
126  ret = a2 * q;
127  }
128  pthread_mutex_unlock(&THR_LOCK_gaussian);
129  return ret;
130 }
131 
132 }
static void deinit()
Deinitialize the class.
Definition: sqlrand.cc:45
Definitions needed for using threads and mutexes.
#define TWIST(b, i, j)
merge bit 31 of one parameter with the low bits of the other parameter.
Definition: sqlrand.h:39
Definitions for random number generations.
static double nextDouble()
Returns random double number.
Definition: sqlrand.cc:104
#define MAGIC(s)
distribute the low bit
Definition: sqlrand.h:41
#define MT_LEN
length of buffer
Definition: sqlrand.h:30
static double gaussian()
Returns variate of the normal distribution.
Definition: sqlrand.cc:111
static void init()
Initialize the class.
Definition: sqlrand.cc:51
#define MT_IB
length - offset in buffer
Definition: sqlrand.h:32
Definition: gini.cc:34
#define MT_IA
offset in buffer
Definition: sqlrand.h:31
static unsigned long random()
Returns random integer number.
Definition: sqlrand.cc:69