Created
April 14, 2010 15:42
-
-
Save matthewd/365974 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From f6d8117aca381769d300339acb38200d3aa1524f Mon Sep 17 00:00:00 2001 | |
From: Matthew Draper <matthew@trebex.net> | |
Date: Thu, 15 Apr 2010 01:09:43 +0930 | |
Subject: [PATCH] Uglier, but more portable? -- use explicit types | |
--- | |
vm/builtin/bignum.cpp | 16 +++--- | |
vm/builtin/bignum.hpp | 4 +- | |
vm/builtin/randomizer.cpp | 105 ++++++++++++++++++++++++--------------------- | |
vm/builtin/randomizer.hpp | 10 ++-- | |
4 files changed, 71 insertions(+), 64 deletions(-) | |
diff --git a/vm/builtin/bignum.cpp b/vm/builtin/bignum.cpp | |
index 1f8df44..edf822b 100644 | |
--- a/vm/builtin/bignum.cpp | |
+++ b/vm/builtin/bignum.cpp | |
@@ -1049,7 +1049,7 @@ namespace rubinius { | |
mp_toradix_nd(XST, mp_val(), buf, radix, sz, &k); | |
} | |
- Integer* Bignum::from_array(STATE, unsigned long *ary, size_t sz) { | |
+ Integer* Bignum::from_array(STATE, uint32_t *ary, size_t sz) { | |
/* | |
* Read the values from the given array to populate a bignum. | |
* | |
@@ -1073,14 +1073,14 @@ namespace rubinius { | |
mp_zero(a); | |
assert(a->used == 0); | |
- const int long_bits = sizeof(unsigned long) * 8; | |
+ const int long_bits = sizeof(uint32_t) * 8; | |
const int total_bits = sz * long_bits; | |
int num_bits = 0; | |
mp_grow(XST, a, total_bits / DIGIT_BIT); | |
while (num_bits < total_bits) { | |
- unsigned long s = ary[num_bits / long_bits]; | |
+ uint32_t s = ary[num_bits / long_bits]; | |
int available_bits = long_bits; | |
@@ -1093,7 +1093,7 @@ namespace rubinius { | |
s &= MP_MASK; | |
available_bits = DIGIT_BIT; | |
} else if (available_bits < DIGIT_BIT && num_bits + available_bits < total_bits) { | |
- unsigned long s2 = ary[num_bits / long_bits + 1]; | |
+ uint32_t s2 = ary[num_bits / long_bits + 1]; | |
s2 &= (1 << (DIGIT_BIT - available_bits)) - 1; | |
s2 <<= available_bits; | |
s |= s2; | |
@@ -1111,7 +1111,7 @@ namespace rubinius { | |
return Bignum::normalize(state, big); | |
} | |
- size_t Bignum::into_array(STATE, unsigned long *ary, size_t sz) { | |
+ size_t Bignum::into_array(STATE, uint32_t *ary, size_t sz) { | |
/* | |
* Split the bignum's value into an array of unsigned integers. | |
* | |
@@ -1129,7 +1129,7 @@ namespace rubinius { | |
* FIXME: Use mp_*() instead | |
*/ | |
- const int long_bits = sizeof(unsigned long) * 8; | |
+ const int long_bits = sizeof(uint32_t) * 8; | |
int num_bits = 0; | |
@@ -1137,10 +1137,10 @@ namespace rubinius { | |
mp_int* a = mp_val(); | |
- unsigned int n = 0; | |
+ uint32_t n = 0; | |
int i; | |
for (i = 0; i < a->used; i++) { | |
- unsigned long q = DIGIT(a, i); | |
+ uint32_t q = DIGIT(a, i); | |
if (ary) ary[n] |= q << (num_bits % long_bits); | |
if ((num_bits % long_bits) + DIGIT_BIT >= long_bits) { | |
diff --git a/vm/builtin/bignum.hpp b/vm/builtin/bignum.hpp | |
index 228c9a0..6120ff3 100644 | |
--- a/vm/builtin/bignum.hpp | |
+++ b/vm/builtin/bignum.hpp | |
@@ -43,7 +43,7 @@ namespace rubinius { | |
static Integer* from_string_detect(STATE, const char* str); | |
static Integer* from_string(STATE, const char* str, size_t radix); | |
static Integer* from_double(STATE, double d); | |
- static Integer* from_array(STATE, unsigned long *ary, size_t sz); | |
+ static Integer* from_array(STATE, uint32_t *ary, size_t sz); | |
Integer* abs(STATE); | |
@@ -188,7 +188,7 @@ namespace rubinius { | |
// in +buf+ of size +sz+. This will always NUL-terminate +buf+. | |
void into_string(STATE, size_t radix, char* buf, size_t sz); | |
- size_t into_array(STATE, unsigned long *ary, size_t sz); | |
+ size_t into_array(STATE, uint32_t *ary, size_t sz); | |
double to_double(STATE); | |
diff --git a/vm/builtin/randomizer.cpp b/vm/builtin/randomizer.cpp | |
index 9f45b66..0711626 100644 | |
--- a/vm/builtin/randomizer.cpp | |
+++ b/vm/builtin/randomizer.cpp | |
@@ -84,30 +84,30 @@ The original copyright notice follows. | |
#define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ ((v)&1UL ? MATRIX_A : 0UL)) | |
-static unsigned long make_mask(unsigned long x) { | |
- for (unsigned int i = 1; i < sizeof(unsigned long) * 8; i *= 2) | |
+template <typename T> | |
+static T make_mask(T x) { | |
+ for (unsigned int i = 1; i < sizeof(T) * 8; i *= 2) | |
x = x | x >> i; | |
return x; | |
} | |
namespace rubinius { | |
- unsigned long *Randomizer::rng_data() { | |
- return (unsigned long*)rng_state()->raw_bytes(); | |
+ uint32_t *Randomizer::rng_data() { | |
+ return (uint32_t*)rng_state()->raw_bytes(); | |
} | |
/* initializes rng_state[N] with a seed */ | |
- void Randomizer::init_genrand(unsigned long s) { | |
- unsigned long *rng_state = rng_data(); | |
+ void Randomizer::init_genrand(uint32_t s) { | |
+ uint32_t *rng_state = rng_data(); | |
int j; | |
- rng_state[0]= s & 0xffffffffUL; | |
+ rng_state[0] = s; | |
for (j=1; j<N; j++) { | |
rng_state[j] = (1812433253UL * (rng_state[j-1] ^ (rng_state[j-1] >> 30)) + j); | |
/* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ | |
/* In the previous versions, MSBs of the seed affect */ | |
/* only MSBs of the array rng_state[]. */ | |
/* 2002/01/09 modified by Makoto Matsumoto */ | |
- rng_state[j] &= 0xffffffffUL; /* for >32 bit machines */ | |
} | |
left = 1; | |
} | |
@@ -116,10 +116,10 @@ namespace rubinius { | |
/* init_key is the array for initializing keys */ | |
/* key_length is its length */ | |
/* slight change for C++, 2004/2/26 */ | |
- void Randomizer::init_by_array(unsigned long init_key[], int key_length) { | |
+ void Randomizer::init_by_array(uint32_t init_key[], int key_length) { | |
init_genrand(19650218UL); | |
- unsigned long *rng_state = rng_data(); | |
+ uint32_t *rng_state = rng_data(); | |
int i, j, k; | |
i=1; j=0; | |
@@ -127,7 +127,6 @@ namespace rubinius { | |
for (; k; k--) { | |
rng_state[i] = (rng_state[i] ^ ((rng_state[i-1] ^ (rng_state[i-1] >> 30)) * 1664525UL)) | |
+ init_key[j] + j; /* non linear */ | |
- rng_state[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ | |
i++; j++; | |
if (i>=N) { rng_state[0] = rng_state[N-1]; i=1; } | |
if (j>=key_length) j=0; | |
@@ -135,7 +134,6 @@ namespace rubinius { | |
for (k=N-1; k; k--) { | |
rng_state[i] = (rng_state[i] ^ ((rng_state[i-1] ^ (rng_state[i-1] >> 30)) * 1566083941UL)) | |
- i; /* non linear */ | |
- rng_state[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ | |
i++; | |
if (i>=N) { rng_state[0] = rng_state[N-1]; i=1; } | |
} | |
@@ -145,12 +143,12 @@ namespace rubinius { | |
} | |
void Randomizer::next_state() { | |
- unsigned long *rng_state = rng_data(); | |
+ uint32_t *rng_state = rng_data(); | |
left = N; | |
next = 0; | |
- unsigned long *p=rng_state; | |
+ uint32_t *p=rng_state; | |
int j; | |
for (j=N-M+1; --j; p++) | |
@@ -163,11 +161,11 @@ namespace rubinius { | |
} | |
/* generates a random number on [0,0xffffffff]-interval */ | |
- unsigned long Randomizer::rb_genrand_int32() { | |
+ uint32_t Randomizer::rb_genrand_int32() { | |
if (--left == 0) next_state(); | |
- unsigned long *rng_state = rng_data(); | |
+ uint32_t *rng_state = rng_data(); | |
- unsigned long y; | |
+ uint32_t y; | |
y = rng_state[next++]; | |
/* Tempering */ | |
@@ -179,14 +177,14 @@ namespace rubinius { | |
return y; | |
} | |
- unsigned long Randomizer::limited_rand(unsigned long limit) { | |
- unsigned long mask = make_mask(limit); | |
+ uintptr_t Randomizer::limited_rand(uintptr_t limit) { | |
+ uintptr_t mask = make_mask(limit); | |
int i; | |
- unsigned long val; | |
+ uintptr_t val; | |
retry: | |
val = 0; | |
- for (i = sizeof(unsigned long)/4-1; 0 <= i; i--) { | |
+ for (i = sizeof(uintptr_t)/4-1; 0 <= i; i--) { | |
if (mask >> (i * 32)) { | |
val |= rb_genrand_int32() << (i * 32); | |
val &= mask; | |
@@ -199,7 +197,7 @@ namespace rubinius { | |
/* generates a random number on [0,1) with 53-bit resolution*/ | |
double Randomizer::rb_genrand_real() { | |
- unsigned long a=rb_genrand_int32()>>5, b=rb_genrand_int32()>>6; | |
+ uint32_t a=rb_genrand_int32()>>5, b=rb_genrand_int32()>>6; | |
return(a*67108864.0+b)*(1.0/9007199254740992.0); | |
} | |
/* These real versions are due to Isaku Wada, 2002/01/09 added */ | |
@@ -214,7 +212,7 @@ namespace rubinius { | |
Randomizer* Randomizer::create(STATE) { | |
Randomizer* r = state->new_object<Randomizer>(G(randomizer)); | |
- r->rng_state(state, ByteArray::create(state, N * sizeof(unsigned long))); | |
+ r->rng_state(state, ByteArray::create(state, N * sizeof(uint32_t))); | |
return r; | |
} | |
@@ -234,7 +232,7 @@ namespace rubinius { | |
Integer* Randomizer::gen_seed(STATE) { | |
static int n = 0; | |
- unsigned long seed[] = { 0, 0, 0, 0 }; | |
+ uint32_t seed[] = { 0, 0, 0, 0 }; | |
#ifdef S_ISCHR | |
int fd; | |
@@ -254,7 +252,7 @@ namespace rubinius { | |
/* If this fails, we're no worse off than if it hadn't opened to | |
* begin with */ | |
int ignored; | |
- ignored = read(fd, seed, 4 * sizeof(unsigned long)); | |
+ ignored = read(fd, seed, 4 * sizeof(uint32_t)); | |
} | |
close(fd); | |
} | |
@@ -265,37 +263,46 @@ namespace rubinius { | |
seed[0] ^= tv.tv_usec; | |
seed[1] ^= tv.tv_sec; | |
seed[2] ^= getpid() ^ (n++ << 16); | |
- seed[3] ^= (unsigned long)&seed; | |
+ seed[3] ^= (uint32_t)&seed; | |
return Bignum::from_array(state, seed, 4); | |
} | |
Object* Randomizer::seed(STATE, Integer* seed) { | |
Bignum* big; | |
+ | |
+ size_t longs; | |
+ uint32_t* data; | |
+ | |
+ if (!seed->fixnum_p()) | |
+ seed = as<Bignum>(seed)->abs(state); | |
+ | |
if (seed->fixnum_p()) { | |
- native_int s = seed->to_native(); | |
- if (((unsigned long)s & 0xffffffff) == (unsigned long)s) { | |
- init_genrand((unsigned long)s); | |
+ uintptr_t s = seed->to_native(); | |
+ | |
+ // Remove the sign bit, for no good reason... but that's what MRI | |
+ // does. | |
+ s &= ~(1 << (sizeof(uintptr_t) * 8 - 1)); | |
+ | |
+ if (s <= 0xffffffffUL) { | |
+ init_genrand((uint32_t)s); | |
return Qnil; | |
} | |
- big = Bignum::from(state, s); | |
+ longs = sizeof(uintptr_t) / 4; | |
+ data = (uint32_t*)alloca(longs * 4); | |
+ for (unsigned int i = 0; i < longs; i++) | |
+ data[i] = (uint32_t)(s >> (i * 32)); | |
} else { | |
big = as<Bignum>(seed); | |
- } | |
- | |
- seed = big->abs(state); | |
- if (seed->fixnum_p()) | |
- big = Bignum::from(state, seed->to_native()); | |
- else | |
- big = as<Bignum>(seed); | |
- size_t bytes = (size_t)big->size(state)->to_native(); | |
- size_t longs = (bytes + sizeof(unsigned long) - 1) / sizeof(unsigned long); | |
+ size_t bytes = (size_t)big->size(state)->to_native(); | |
+ longs = (bytes + 3) / 4; | |
- unsigned long* data = (unsigned long*)alloca(longs * sizeof(unsigned long)); | |
- size_t output_count = big->into_array(state, data, longs); | |
- assert(longs >= output_count); | |
+ data = (uint32_t*)alloca(longs * 4); | |
+ size_t output_count = big->into_array(state, data, longs); | |
+ assert(longs >= output_count); | |
+ } | |
init_by_array(data, longs); | |
@@ -305,27 +312,27 @@ namespace rubinius { | |
Integer* Randomizer::rand_int(STATE, Integer* max) { | |
if (max->fixnum_p()) { | |
native_int max_i = max->to_native(); | |
- unsigned long result = limited_rand((unsigned long)(max_i)); | |
+ uintptr_t result = limited_rand((uintptr_t)(max_i)); | |
return Integer::from(state, result); | |
} | |
Bignum* max_big = as<Bignum>(max); | |
size_t bytes = (size_t)max_big->size(state)->to_native(); | |
- size_t longs = (bytes + sizeof(unsigned long) - 1) / sizeof(unsigned long); | |
+ size_t longs = (bytes + 3) / 4; | |
- unsigned long* max_data = (unsigned long*)alloca(longs * sizeof(unsigned long)); | |
+ uint32_t* max_data = (uint32_t*)alloca(longs * 4); | |
size_t output_count = max_big->into_array(state, max_data, longs); | |
assert(longs >= output_count); | |
- unsigned long* result_data = (unsigned long*)alloca(longs * sizeof(unsigned long)); | |
+ uint32_t* result_data = (uint32_t*)alloca(longs * 4); | |
retry: | |
- unsigned long mask = 0; | |
+ uint32_t mask = 0; | |
int i, boundary = 1; | |
for (i = longs - 1; i >= 0; i--) { | |
- unsigned long rnd; | |
- unsigned long lim = max_data[i]; | |
+ uint32_t rnd; | |
+ uint32_t lim = max_data[i]; | |
mask = mask ? 0xffffffff : make_mask(lim); | |
if (mask) { | |
rnd = rb_genrand_int32() & mask; | |
diff --git a/vm/builtin/randomizer.hpp b/vm/builtin/randomizer.hpp | |
index 3f74fe6..0aa2dae 100644 | |
--- a/vm/builtin/randomizer.hpp | |
+++ b/vm/builtin/randomizer.hpp | |
@@ -20,13 +20,13 @@ namespace rubinius { | |
int left; | |
ByteArray *rng_state_; // slot | |
- unsigned long* rng_data(); | |
+ uint32_t* rng_data(); | |
- void init_genrand(unsigned long s); | |
- void init_by_array(unsigned long init_key[], int key_length); | |
+ void init_genrand(uint32_t s); | |
+ void init_by_array(uint32_t init_key[], int key_length); | |
void next_state(); | |
- unsigned long rb_genrand_int32(); | |
- unsigned long limited_rand(unsigned long limit); | |
+ uint32_t rb_genrand_int32(); | |
+ uintptr_t limited_rand(uintptr_t limit); | |
double rb_genrand_real(); | |
public: | |
-- | |
1.7.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 562a04f81625032c24ab08265c49427812ee850c Mon Sep 17 00:00:00 2001 | |
From: Matthew Draper <matthew@trebex.net> | |
Date: Thu, 15 Apr 2010 02:19:45 +0930 | |
Subject: [PATCH] Correctly handle DIGIT_BIT > 32 | |
--- | |
vm/builtin/bignum.cpp | 24 +++++++++++++----------- | |
1 files changed, 13 insertions(+), 11 deletions(-) | |
diff --git a/vm/builtin/bignum.cpp b/vm/builtin/bignum.cpp | |
index edf822b..818da8b 100644 | |
--- a/vm/builtin/bignum.cpp | |
+++ b/vm/builtin/bignum.cpp | |
@@ -1138,18 +1138,20 @@ namespace rubinius { | |
mp_int* a = mp_val(); | |
uint32_t n = 0; | |
- int i; | |
- for (i = 0; i < a->used; i++) { | |
- uint32_t q = DIGIT(a, i); | |
- | |
- if (ary) ary[n] |= q << (num_bits % long_bits); | |
- if ((num_bits % long_bits) + DIGIT_BIT >= long_bits) { | |
- n++; | |
- if (n > sz) ary = NULL; | |
- if (ary) ary[n] = q >> (long_bits - (num_bits % long_bits)); | |
- } | |
+ for (int i = 0; i < a->used; i++) { | |
+ for (int j = 0; j < DIGIT_BIT; j += 32) { | |
+ uint32_t q = DIGIT(a, i) >> j; | |
+ int bits_in_digit = j + 32 > DIGIT_BIT ? DIGIT_BIT - j : 32; | |
+ | |
+ if (ary) ary[n] |= q << (num_bits % long_bits); | |
+ if ((num_bits % long_bits) + bits_in_digit >= long_bits) { | |
+ n++; | |
+ if (n > sz) ary = NULL; | |
+ if (ary) ary[n] = q >> (long_bits - (num_bits % long_bits)); | |
+ } | |
- num_bits += DIGIT_BIT; | |
+ num_bits += bits_in_digit; | |
+ } | |
} | |
return num_bits / long_bits; | |
-- | |
1.7.0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment