1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360
|
/*
* M_APM - mapm_rnd.c
*
* Copyright (C) 1999 - 2007 Michael C. Ring
*
* Permission to use, copy, and distribute this software and its
* documentation for any purpose with or without fee is hereby granted,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation.
*
* Permission to modify the software is granted. Permission to distribute
* the modified code is granted. Modifications are to be distributed by
* using the file 'license.txt' as a template to modify the file header.
* 'license.txt' is available in the official MAPM distribution.
*
* This software is provided "as is" without express or implied warranty.
*/
/*
*
* This file contains the Random Number Generator function.
*
*/
#include "pgAdmin3.h"
#include "pgscript/utilities/mapm-lib/m_apm_lc.h"
#ifndef _HAVE_NI_LABWIN_CVI_
#ifdef MSDOS
#include <time.h>
#include <sys/timeb.h>
#else
#include <sys/time.h>
extern void M_get_microsec(unsigned long *, long *);
#endif
#endif
#ifdef _HAVE_NI_LABWIN_CVI_
#include <time.h>
#include <utility.h>
#include <ansi/math.h>
#endif
extern void M_reverse_string(char *);
extern void M_get_rnd_seed(M_APM);
static M_APM M_rnd_aa;
static M_APM M_rnd_mm;
static M_APM M_rnd_XX;
static M_APM M_rtmp0;
static M_APM M_rtmp1;
static int M_firsttime2 = TRUE;
/*
Used Knuth's The Art of Computer Programming, Volume 2 as
the basis. Assuming the random number is X, compute
(where all the math is performed on integers) :
X = (a * X + c) MOD m
From Knuth:
'm' should be large, at least 2^30 : we use 1.0E+15
'a' should be between .01m and .99m and not have a simple
pattern. 'a' should not have any large factors in common
with 'm' and (since 'm' is a power of 10) if 'a' MOD 200
= 21 then all 'm' different possible values will be
generated before 'X' starts to repeat.
We use 'a' = 716805947629621.
This is a prime number and also meets 'a' MOD 200 = 21.
Commented out below are many potential multipliers that
are all prime and meet 'a' MOD 200 = 21.
There are few restrictions on 'c' except 'c' can have no
factor in common with 'm', hence we set 'c' = 'a'.
On the first call, the system time is used to initialize X.
*/
/*
* the following constants are all potential multipliers. they are
* all prime numbers that also meet the criteria of NUM mod 200 = 21.
*/
/*
439682071525421 439682071528421 439682071529221 439682071529821
439682071530421 439682071532021 439682071538821 439682071539421
439682071540021 439682071547021 439682071551221 439682071553821
439682071555421 439682071557221 439682071558021 439682071558621
439682071559821 439652381461621 439652381465221 439652381465621
439652381466421 439652381467421 439652381468621 439652381470021
439652381471221 439652381477021 439652381484221 439652381488421
439652381491021 439652381492021 439652381494021 439652381496821
617294387035621 617294387038621 617294387039221 617294387044421
617294387045221 617294387048621 617294387051621 617294387051821
617294387053621 617294387058421 617294387064221 617294387065621
617294387068621 617294387069221 617294387069821 617294387070421
617294387072021 617294387072621 617294387073821 617294387076821
649378126517621 649378126517821 649378126518221 649378126520821
649378126523821 649378126525621 649378126526621 649378126528421
649378126529621 649378126530821 649378126532221 649378126533221
649378126535221 649378126539421 649378126543621 649378126546021
649378126546421 649378126549421 649378126550821 649378126555021
649378126557421 649378126560221 649378126561621 649378126562021
649378126564621 649378126565821 672091582360421 672091582364221
672091582364621 672091582367021 672091582368421 672091582369021
672091582370821 672091582371421 672091582376821 672091582380821
716805243983221 716805243984821 716805947623621 716805947624621
716805947629021 716805947629621 716805947630621 716805947633621
716805947634221 716805947635021 716805947635621 716805947642221
*/
/****************************************************************************/
void M_free_all_rnd()
{
if (M_firsttime2 == FALSE)
{
m_apm_free(M_rnd_aa);
m_apm_free(M_rnd_mm);
m_apm_free(M_rnd_XX);
m_apm_free(M_rtmp0);
m_apm_free(M_rtmp1);
M_firsttime2 = TRUE;
}
}
/****************************************************************************/
void m_apm_set_random_seed(char *ss)
{
M_APM btmp;
if (M_firsttime2)
{
btmp = M_get_stack_var();
m_apm_get_random(btmp);
M_restore_stack(1);
}
m_apm_set_string(M_rnd_XX, ss);
}
/****************************************************************************/
/*
* compute X = (a * X + c) MOD m where c = a
*/
void m_apm_get_random(M_APM mrnd)
{
if (M_firsttime2) /* use the system time as the initial seed value */
{
M_firsttime2 = FALSE;
M_rnd_aa = m_apm_init();
M_rnd_XX = m_apm_init();
M_rnd_mm = m_apm_init();
M_rtmp0 = m_apm_init();
M_rtmp1 = m_apm_init();
/* set the multiplier M_rnd_aa and M_rnd_mm */
m_apm_set_string(M_rnd_aa, "716805947629621");
m_apm_set_string(M_rnd_mm, "1.0E15");
M_get_rnd_seed(M_rnd_XX);
}
m_apm_multiply(M_rtmp0, M_rnd_XX, M_rnd_aa);
m_apm_add(M_rtmp1, M_rtmp0, M_rnd_aa);
m_apm_integer_div_rem(M_rtmp0, M_rnd_XX, M_rtmp1, M_rnd_mm);
m_apm_copy(mrnd, M_rnd_XX);
mrnd->m_apm_exponent -= 15;
}
/****************************************************************************/
void M_reverse_string(char *s)
{
int ct;
char ch, *p1, *p2;
if ((ct = strlen(s)) <= 1)
return;
p1 = s;
p2 = s + ct - 1;
ct /= 2;
while (TRUE)
{
ch = *p1;
*p1++ = *p2;
*p2-- = ch;
if (--ct == 0)
break;
}
}
/****************************************************************************/
#ifndef _HAVE_NI_LABWIN_CVI_
#ifdef MSDOS
/****************************************************************************/
/*
* for DOS / Win 9x/NT systems : use 'ftime'
*/
void M_get_rnd_seed(M_APM mm)
{
int millisec;
time_t timestamp;
unsigned long ul;
char ss[32], buf1[48], buf2[32];
struct timeb timebuffer;
M_APM atmp;
atmp = M_get_stack_var();
ftime(&timebuffer);
millisec = (int)timebuffer.millitm;
timestamp = timebuffer.time;
ul = (unsigned long)(timestamp / 7);
ul += timestamp + 537;
strcpy(ss, ctime(×tamp)); /* convert to string and copy to ss */
sprintf(buf1, "%d", (millisec / 10));
sprintf(buf2, "%lu", ul);
ss[0] = ss[18];
ss[1] = ss[17];
ss[2] = ss[15];
ss[3] = ss[14];
ss[4] = ss[12];
ss[5] = ss[11];
ss[6] = ss[9];
ss[7] = ss[23];
ss[8] = ss[20];
ss[9] = '\0';
M_reverse_string(buf2);
strcat(buf1, buf2);
strcat(buf1, ss);
m_apm_set_string(atmp, buf1);
atmp->m_apm_exponent = 15;
m_apm_integer_divide(mm, atmp, MM_One);
M_restore_stack(1);
}
/****************************************************************************/
#else
/****************************************************************************/
/*
* for unix systems : use 'gettimeofday'
*/
void M_get_rnd_seed(M_APM mm)
{
unsigned long sec3;
long usec3;
char buf1[32], buf2[32];
M_APM atmp;
atmp = M_get_stack_var();
M_get_microsec(&sec3, &usec3);
sprintf(buf1, "%ld", usec3);
sprintf(buf2, "%lu", sec3);
M_reverse_string(buf2);
strcat(buf1, buf2);
m_apm_set_string(atmp, buf1);
atmp->m_apm_exponent = 15;
m_apm_integer_divide(mm, atmp, MM_One);
M_restore_stack(1);
}
/****************************************************************************/
void M_get_microsec(unsigned long *sec, long *usec)
{
struct timeval time_now; /* current time for elapsed time check */
struct timezone time_zone; /* time zone for gettimeofday call */
gettimeofday(&time_now, &time_zone); /* get current time */
*sec = time_now.tv_sec;
*usec = time_now.tv_usec;
}
/****************************************************************************/
#endif
#endif
#ifdef _HAVE_NI_LABWIN_CVI_
/****************************************************************************/
/*
* for National Instruments LabWindows CVI
*/
void M_get_rnd_seed(M_APM mm)
{
double timer0;
int millisec;
char *cvi_time, *cvi_date, buf1[64], buf2[32];
M_APM atmp;
atmp = M_get_stack_var();
cvi_date = DateStr();
cvi_time = TimeStr();
timer0 = Timer();
/*
* note that Timer() is not syncronized to TimeStr(),
* but we don't care here since we are just looking
* for a random source of digits.
*/
millisec = (int)(0.01 + 1000.0 * (timer0 - floor(timer0)));
sprintf(buf1, "%d", millisec);
buf2[0] = cvi_time[6]; /* time format: "HH:MM:SS" */
buf2[1] = cvi_time[7];
buf2[2] = cvi_time[3];
buf2[3] = cvi_time[4];
buf2[4] = cvi_time[0];
buf2[5] = cvi_time[1];
buf2[6] = cvi_date[3]; /* date format: "MM-DD-YYYY" */
buf2[7] = cvi_date[4];
buf2[8] = cvi_date[0];
buf2[9] = cvi_date[1];
buf2[10] = cvi_date[8];
buf2[11] = cvi_date[9];
buf2[12] = cvi_date[7];
buf2[13] = '4';
buf2[14] = '7';
buf2[15] = '\0';
strcat(buf1, buf2);
m_apm_set_string(atmp, buf1);
atmp->m_apm_exponent = 15;
m_apm_integer_divide(mm, atmp, MM_One);
M_restore_stack(1);
}
#endif
/****************************************************************************/
|