pike.git
/
src
/
stuff.c
version
»
Context lines:
10
20
40
80
file
none
3
pike.git/src/stuff.c:1:
/* || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. */ #include "global.h" #include "stuff.h" #include "bitvector.h"
+
#include "pike_cpulib.h"
/* Used by is8bitalnum in pike_macros.h. */ PMOD_EXPORT const char Pike_is8bitalnum_vector[] = "0000000000000000" "0000000000000000" "0000000000000000" "1111111111000000" "0111111111111111" "1111111111100001" "0111111111111111"
pike.git/src/stuff.c:94:
/* * This rounds an integer up to the next power of two. For x a power * of two, this will just return the same again. */ unsigned INT32 find_next_power(unsigned INT32 x) { if( x == 0 ) return 1; return 1<<(my_log2(x-1)+1); }
-
static unsigned INT32 RandSeed1 = 0x5c2582a4;
-
static unsigned INT32 RandSeed2 = 0x64dff8ca;
-
-
static unsigned INT32 slow_rand(void)
-
{
-
RandSeed1 = ((RandSeed1 * 13 + 1) ^ (RandSeed1 >> 9)) + RandSeed2;
-
RandSeed2 = (RandSeed2 * RandSeed1 + 13) ^ (RandSeed2 >> 13);
-
return RandSeed1;
-
}
-
-
static void slow_srand(INT32 seed)
-
{
-
RandSeed1 = (seed - 1) ^ 0xA5B96384UL;
-
RandSeed2 = (seed + 1) ^ 0x56F04021UL;
-
}
-
-
#define RNDBUF 250
-
#define RNDSTEP 7
-
#define RNDJUMP 103
-
-
static unsigned INT32 rndbuf[ RNDBUF ];
-
static unsigned int rnd_index;
-
+
#if HAS___BUILTIN_IA32_RDRAND32_STEP static int use_rdrnd;
-
static unsigned long long rnd_index64;
-
#endif
+
#define bit_RDRND_2 (1<<30)
-
-
#if SIZEOF_CHAR_P == 4
-
#define __cpuid(level, a, b, c, d) \
-
__asm__ ("pushl %%ebx \n\t" \
-
"cpuid \n\t" \
-
"movl %%ebx, %1 \n\t" \
-
"popl %%ebx \n\t" \
-
: "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
-
: "a" (level) \
-
: "cc")
-
#else
-
#define __cpuid(level, a, b, c, d) \
-
__asm__ ("push %%rbx \n\t" \
-
"cpuid \n\t" \
-
"movl %%ebx, %1 \n\t" \
-
"pop %%rbx \n\t" \
-
: "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
-
: "a" (level) \
-
: "cc")
+
#endif
-
+
/* Bob Jenkins small noncryptographic PRNG */
+
+
typedef unsigned long int u4;
+
static u4 rnd_a;
+
static u4 rnd_b;
+
static u4 rnd_c;
+
static u4 rnd_d;
+
+
#define rot(x,k) (((x)<<(k))|((x)>>(32-(k))))
+
static u4 ranval(void) {
+
u4 e = rnd_a - rot(rnd_b, 27);
+
rnd_a = rnd_b ^ rot(rnd_c, 17);
+
rnd_b = rnd_c + rnd_d;
+
rnd_c = rnd_d + e;
+
rnd_d = e + rnd_a;
+
return rnd_d;
+
}
+
+
static void raninit( u4 seed ) {
+
u4 i;
+
rnd_a = 0xf1ea5eed, rnd_b = rnd_c = rnd_d = seed;
+
for (i=0; i<20; ++i) {
+
(void)ranval();
+
}
+
}
+
PMOD_EXPORT void my_srand(INT32 seed) { #if HAS___BUILTIN_IA32_RDRAND32_STEP unsigned int ignore, cpuid_ecx; if( !use_rdrnd ) {
-
__
cpuid
(
0x1,
ignore,
ignore,
cpuid
_
ecx
,
ignore
);
-
if( cpuid
_ecx
& bit_RDRND_2 )
+
INT32
cpuid
[4];
+
x86_get_
cpuid
(1
,
cpuid
);
+
if( cpuid
[3]
& bit_RDRND_2 )
use_rdrnd = 1; } /* We still do the initialization here, since rdrnd might stop working if the hardware random unit in the CPU fails (according to intel documentation). This is likely to be rather rare. But the cost is not exactly high. Source: http://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide */ #endif
-
{
-
int e;
-
unsigned INT32 mask;
+
-
slow_srand
(seed);
-
-
rnd_index = 0;
-
for (e=0;e < RNDBUF; e++) rndbuf[e]=slow_rand();
-
-
mask = (unsigned INT32) -1;
-
-
for (e=0;e< (int)sizeof(INT32)*8 ;e++)
-
{
-
int d = RNDSTEP * e + 3;
-
rndbuf[d % RNDBUF] &= mask;
-
mask>>=1;
-
rndbuf[d % RNDBUF] |= (mask+1);
+
raninit
(seed);
}
-
}
-
}
+
PMOD_EXPORT unsigned INT32 my_rand(void) { #if HAS___BUILTIN_IA32_RDRAND32_STEP if( use_rdrnd ) {
-
+
unsigned int rnd;
unsigned int cnt = 0; do{
-
if( __builtin_ia32_rdrand32_step( &rnd
_index
) )
-
return rnd
_index
;
+
if( __builtin_ia32_rdrand32_step( &rnd ) )
+
return rnd;
} while(cnt++ < 100); /* hardware random unit most likely not healthy. Switch to software random. */
-
rnd_index = 0;
+
use_rdrnd = 0; } #endif
-
if(++rnd_index == RNDBUF) rnd_index=0;
-
return
rndbuf[rnd_index] += rndbuf[rnd_index+RNDJUMP-
(
rnd_index<RNDBUF-RNDJUMP?0:RNDBUF
)
]
;
+
return
ranval
();
} PMOD_EXPORT unsigned INT64 my_rand64(void) { #if HAS___BUILTIN_IA32_RDRAND32_STEP if( use_rdrnd ) {
-
+
unsigned long long rnd;
unsigned int cnt = 0; do{ /* We blindly trust that _builtin_ia32_rdrand64_step exists when the 32 bit version does. */
-
if( __builtin_ia32_rdrand64_step( &rnd
_index64
) )
-
return rnd
_index64
;
+
if( __builtin_ia32_rdrand64_step( &rnd ) )
+
return rnd;
} while(cnt++ < 100); /* hardware random unit most likely not healthy. Switch to software random. */
-
rnd_index = 0;
+
use_rdrnd = 0; } #endif
-
return ((INT64)
my_rand
()<<32) |
my_rand
();
+
return ((INT64)
ranval
()<<32) |
ranval
();
}