1 // random_state constructor.
4 #if defined(_WIN32) && !defined(__CYGWIN__)
5 #include <windows.h> // For GetCurrentProcessId(), must be included first, sorry.
9 #include "base/cl_sysdep.h"
12 #include "cln/random.h"
17 #include "base/cl_base_config.h"
18 #include "base/cl_low.h"
19 #include <cstdlib> // declares rand()
21 #if defined(unix) || defined(__unix) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(_AIX) || defined(sinix) || (defined(__MACH__) && defined(__APPLE__)) || (defined(__CYGWIN__) && defined(__GNUC__)) || defined(__BEOS__)
23 #include <sys/types.h>
24 #include <unistd.h> // declares getpid()
26 #if defined(HAVE_GETTIMEOFDAY)
29 #ifdef GETTIMEOFDAY_DOTS
30 extern "C" int gettimeofday (struct timeval * tp, ...);
32 extern "C" int gettimeofday (struct timeval * tp, GETTIMEOFDAY_TZP_T tzp);
36 inline uint32 get_seed (void)
38 var struct timeval tv;
40 return highlow32(tv.tv_sec,tv.tv_usec); // 16+16 zufällige Bits
44 #elif defined(HAVE_TIMES_CLOCK)
50 #include <sys/times.h>
51 extern "C" clock_t times (struct tms * buffer);
54 inline uint32 get_seed (void)
56 var struct tms tmsbuf;
57 var uint32 seed_lo = times(&tmsbuf);
58 return seed_lo + tmsbuf.tms_utime + tmsbuf.tms_stime;
64 #elif defined(_WIN32) && !defined(__CYGWIN__)
66 /* <windows.h> included above. */
69 inline uint32 get_seed (void)
71 FILETIME current_time;
73 GetSystemTimeAsFileTime (¤t_time);
75 /* Convert from FILETIME to 'struct timeval'. */
76 /* FILETIME: <https://docs.microsoft.com/en-us/windows/desktop/api/minwinbase/ns-minwinbase-filetime> */
77 ULONGLONG since_1601 =
78 ((ULONGLONG) current_time.dwHighDateTime << 32)
79 | (ULONGLONG) current_time.dwLowDateTime;
80 /* Divide by 20 ms, and take the low-order 32 bits. */
81 return (ULONG) (since_1601 / 2000000);
89 // Counter, to avoid that two random-states created immediately one after
90 // the other contain the same seed.
91 static uint32 counter = 0;
93 random_state::random_state ()
97 #if defined(unix) || defined(__unix) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(_AIX) || defined(sinix) || (defined(__MACH__) && defined(__APPLE__)) || (defined(__CYGWIN__) && defined(__GNUC__)) || defined(__BEOS__)
99 seed_hi = (rand() // zufällige 31 Bit (bei UNIX_BSD) bzw. 16 Bit (bei UNIX_SYSV)
100 << 8) ^ (uintL)(getpid()); // ca. 8 Bit von der Process ID
101 #elif defined(__OpenBSD__)
102 seed_lo = arc4random();
103 seed_hi = arc4random();
104 #elif defined(_WIN32) && !defined(__CYGWIN__)
105 seed_lo = get_seed();
106 seed_hi = (rand() << 8) ^ (uintL)(GetCurrentProcessId());
107 #elif defined(__atarist)
108 seed_lo = highlow32(GEMDOS_GetDate(),GEMDOS_GetTime()); // 16+16 zufällige Bits
109 seed_hi = XBIOS_Random(); // 24 Bit zufällig vom XBIOS, vorne 8 Nullbits
110 #elif defined(amiga) || defined(AMIGA)
111 seed_lo = get_real_time(); // Uhrzeit
112 seed_hi = FindTask(NULL); // Pointer auf eigene Task
113 #elif defined(__MSDOS__) || defined(__EMX__) || defined(__riscos)
114 // Keine Zufallszahlen, keine PID, nichts Zufälliges da.
115 seed_lo = get_real_time(); // Uhrzeit, 100 Hz
116 seed_hi = time(NULL);
118 #error "Must implement random_state constructor!"
120 seed_hi ^= counter++ << 5;