OSDN Git Service

Change uniform distribution RNG method
authorHabu <habu@users.sourceforge.jp>
Thu, 6 Mar 2014 12:43:20 +0000 (21:43 +0900)
committerHabu <habu@users.sourceforge.jp>
Fri, 7 Mar 2014 13:22:59 +0000 (22:22 +0900)
真の一様分布を得るため、分布で割った余りを使用する方法から
分布でスケーリングした範囲を割り算する方法に変更

src/z-rand.c
src/z-rand.h

index 4422941..3dbdcb2 100644 (file)
@@ -96,6 +96,8 @@ static u32b Rand_Xorshift(u32b* state)
        return state[3];
 }
 
+static const u32b Rand_Xorshift_max = 0xFFFFFFFF;
+
 /*
  * Initialize the RNG using a new seed
  */
@@ -132,13 +134,28 @@ void Rand_state_restore(u32b* backup_state)
 /*
  * Extract a "random" number from 0 to m-1, via "division"
  */
-s32b Rand_div(u32b m)
+static s32b Rand_div_impl(s32b m, u32b* state)
 {
+       u32b scaling;
+       u32b past;
+       u32b ret;
+
        /* Hack -- simple case */
        if (m <= 1) return (0);
 
-       /* Use the value */
-       return Rand_Xorshift(Rand_state) % m;
+       scaling = Rand_Xorshift_max / m;
+       past = scaling * m;
+
+       do {
+               ret = Rand_Xorshift(state);
+       } while (ret >= past);
+
+       return ret / scaling;
+}
+
+s32b Rand_div(s32b m)
+{
+       return Rand_div_impl(m, Rand_state);
 }
 
 
@@ -332,5 +349,5 @@ u32b Rand_external(u32b m)
                initialized = TRUE;
        }
 
-       return Rand_Xorshift(Rand_state_external) % m;
+       return Rand_div_impl(m, Rand_state_external);
 }
index 5388743..bdc37dc 100644 (file)
@@ -92,7 +92,7 @@ extern u32b Rand_state[RAND_DEG];
 extern void Rand_state_init(u32b seed);
 extern void Rand_state_backup(u32b* backup_state);
 extern void Rand_state_restore(u32b* backup_state);
-extern s32b Rand_div(u32b m);
+extern s32b Rand_div(s32b m);
 extern s16b randnor(int mean, int stand);
 extern s16b damroll(int num, int sides);
 extern s16b maxroll(int num, int sides);