Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@matthewd
Created April 14, 2010 15:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save matthewd/365974 to your computer and use it in GitHub Desktop.
Save matthewd/365974 to your computer and use it in GitHub Desktop.
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
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