diff src/madplug/dither.c @ 922:7e14701aef54 trunk

[svn] - replace random number generator in dithering code with SIMD-oriented Fast Mersenne Twister (SFMT). it reduces CPU load on SSE2 or AltiVec capable platform.
author yaz
date Sun, 08 Apr 2007 21:30:22 -0700
parents 862190d39e00
children f931c9d744a5
line wrap: on
line diff
--- a/src/madplug/dither.c	Sat Apr 07 11:06:36 2007 -0700
+++ b/src/madplug/dither.c	Sun Apr 08 21:30:22 2007 -0700
@@ -1,100 +1,18 @@
-/* A C-program for MT19937: Integer     version                   */
-/*  genrand() generates one pseudorandom unsigned integer (32bit) */
-/* which is uniformly distributed among 0 to 2^32-1  for each     */
-/* call. sgenrand(seed) set initial values to the working area    */
-/* of 624 words. Before genrand(), sgenrand(seed) must be         */
-/* called once. (seed is any 32-bit integer except for 0).        */
-/*   Coded by Takuji Nishimura, considering the suggestions by    */
-/* Topher Cooper and Marc Rieffel in July-Aug. 1997.              */
-
-/* This library is free software; you can redistribute it and/or   */
-/* modify it under the terms of the GNU Library General Public     */
-/* License as published by the Free Software Foundation; either    */
-/* version 2 of the License, or (at your option) any later         */
-/* version.                                                        */
-/* This library is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of  */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.            */
-/* See the GNU Library General Public License for more details.    */
-/* You should have received a copy of the GNU Library General      */
-/* Public License along with this library; if not, write to the    */
-/* Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA   */
-/* 02111-1307  USA                                                 */
-
-/* Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura.       */
-/* Any feedback is very welcome. For any question, comments,       */
-/* see http://www.math.keio.ac.jp/matumoto/emt.html or email       */
-/* matumoto@math.keio.ac.jp                                        */
-
 #include <stdio.h>
 #include <assert.h>
-
-
-/* Period parameters */
-#define N 624
-#define M 397
-#define MATRIX_A 0x9908b0df     /* constant vector a */
-#define UPPER_MASK 0x80000000   /* most significant w-r bits */
-#define LOWER_MASK 0x7fffffff   /* least significant r bits */
+#include "../../config.h"
 
-/* Tempering parameters */
-#define TEMPERING_MASK_B 0x9d2c5680
-#define TEMPERING_MASK_C 0xefc60000
-#define TEMPERING_SHIFT_U(y)  (y >> 11)
-#define TEMPERING_SHIFT_S(y)  (y << 7)
-#define TEMPERING_SHIFT_T(y)  (y << 15)
-#define TEMPERING_SHIFT_L(y)  (y >> 18)
-
-static unsigned long mt[N];     /* the array for the state vector  */
-static int mti = N + 1;         /* mti==N+1 means mt[N] is not initialized */
-
-/* initializing the array with a NONZERO seed */
-void sgenrand(seed)
-unsigned long seed;
-{
-    /* setting initial seeds to mt[N] using         */
-    /* the generator Line 25 of Table 1 in          */
-    /* [KNUTH 1981, The Art of Computer Programming */
-    /*    Vol. 2 (2nd Ed.), pp102]                  */
-    mt[0] = seed & 0xffffffff;
-    for (mti = 1; mti < N; mti++)
-        mt[mti] = (69069 * mt[mti - 1]) & 0xffffffff;
-}
+#define MEXP 19937
 
-unsigned long genrand()
-{
-    unsigned long y;
-    static unsigned long mag01[2] = { 0x0, MATRIX_A };
-    /* mag01[x] = x * MATRIX_A  for x=0,1 */
-
-    if (mti >= N) {             /* generate N words at one time */
-        int kk;
-
-        if (mti == N + 1)       /* if sgenrand() has not been called, */
-            sgenrand(4357);     /* a default initial seed is used   */
+#ifdef HAVE_SSE2
+#define SSE2 1
+#endif
+#ifdef HAVE_ALTIVEC
+#define ALTIVEC 1
+#endif
 
-        for (kk = 0; kk < N - M; kk++) {
-            y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
-            mt[kk] = mt[kk + M] ^ (y >> 1) ^ mag01[y & 0x1];
-        }
-        for (; kk < N - 1; kk++) {
-            y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
-            mt[kk] = mt[kk + (M - N)] ^ (y >> 1) ^ mag01[y & 0x1];
-        }
-        y = (mt[N - 1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
-        mt[N - 1] = mt[M - 1] ^ (y >> 1) ^ mag01[y & 0x1];
-
-        mti = 0;
-    }
-
-    y = mt[mti++];
-    y ^= TEMPERING_SHIFT_U(y);
-    y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B;
-    y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C;
-    y ^= TEMPERING_SHIFT_L(y);
-
-    return y;
-}
+#include "SFMT.h"
+#include "SFMT.c"
 
 long triangular_dither_noise(int nbits)
 {
@@ -105,7 +23,7 @@
     // see The Theory of Dithered Quantization by Robert Alexander Wannamaker
     // for complete proof of why that's optimal
 
-    long v = (genrand() / 2 - genrand() / 2);   // in ]-2^31, 2^31[
+    long v = (gen_rand32() / 2 - gen_rand32() / 2);   // in ]-2^31, 2^31[
     //int signe = (v>0) ? 1 : -1;
     long P = 1 << (32 - nbits); // the power of 2
     v /= P;