⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lecuyer.h

📁 使用R语言的马尔科夫链蒙特卡洛模拟(MCMC)源代码程序。
💻 H
📖 第 1 页 / 共 2 页
字号:
/*  * Scythe Statistical Library * Copyright (C) 2000-2002 Andrew D. Martin and Kevin M. Quinn; * 2002-present Andrew D. Martin, Kevin M. Quinn, and Daniel * Pemstein.  All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * under the terms of the GNU General Public License as published by * Free Software Foundation; either version 2 of the License, or (at * your option) any later version.  See the text files COPYING * and LICENSE, distributed with this source code, for further * information. * -------------------------------------------------------------------- * scythestat/rng/lecuyer.h * * Provides the class definition for the L'Ecuyer random number * generator, a rng capable of generating many independent substreams. * This class extends the abstract rng class by implementing runif(). * Based on RngStream.cpp, by Pierre L'Ecuyer. * * Pierre L'Ecuyer agreed to the following dual-licensing terms in an * email received 7 August 2004.  This dual-license was prompted by * the Debian maintainers of R and MCMCpack.  * * This software is Copyright (C) 2004 Pierre L'Ecuyer. * * License: this code can be used freely for personal, academic, or * non-commercial purposes.  For commercial licensing, please contact * P. L'Ecuyer at lecuyer@iro.umontreal.ca. * * This code may also be redistributed and modified under the terms of * the GNU General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) any * later version. *  * This program 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 * General Public License for more details. *  * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * *//*! \file lecuyer.h * \brief The L'Ecuyer random number generator. * * This file contains the lecuyer class, a class that extends Scythe's * base random number generation class (scythe::rng) by providing an * implementation of scythe::rng::runif(), using L'Ecuyer's algorithm. * */#ifndef SCYTHE_LECUYER_H#define SCYTHE_LECUYER_H#include<cstdlib>#include<iostream>#include<string>#ifdef SCYTHE_COMPILE_DIRECT#include "rng.h"#else#include "scythestat/rng.h"#endif/* We want to use an anonymous namespace to make the following consts * and functions local to this file, but mingw doesn't play nice with * anonymous namespaces so we do things differently when using the * cross-compiler. */#ifdef __MINGW32__#define SCYTHE_MINGW32_STATIC static#else#define SCYTHE_MINGW32_STATIC#endifnamespace scythe {#ifndef __MINGW32__  namespace {#endif	SCYTHE_MINGW32_STATIC const double m1   = 4294967087.0;	SCYTHE_MINGW32_STATIC const double m2   = 4294944443.0;	SCYTHE_MINGW32_STATIC const double norm = 1.0 / (m1 + 1.0);	SCYTHE_MINGW32_STATIC const double a12  = 1403580.0;	SCYTHE_MINGW32_STATIC const double a13n = 810728.0;	SCYTHE_MINGW32_STATIC const double a21  = 527612.0;	SCYTHE_MINGW32_STATIC const double a23n = 1370589.0;	SCYTHE_MINGW32_STATIC const double two17 =131072.0;	SCYTHE_MINGW32_STATIC const double two53 =9007199254740992.0;  /* 1/2^24 */	SCYTHE_MINGW32_STATIC const double fact = 5.9604644775390625e-8;	// The following are the transition matrices of the two MRG	// components (in matrix form), raised to the powers -1, 1, 2^76,	// and 2^127, resp.	SCYTHE_MINGW32_STATIC const double InvA1[3][3] = { // Inverse of A1p0				 { 184888585.0,   0.0,  1945170933.0 },				 {         1.0,   0.0,           0.0 },				 {         0.0,   1.0,           0.0 } };	SCYTHE_MINGW32_STATIC const double InvA2[3][3] = { // Inverse of A2p0				 {      0.0,  360363334.0,  4225571728.0 },				 {      1.0,          0.0,           0.0 },				 {      0.0,          1.0,           0.0 } };	SCYTHE_MINGW32_STATIC const double A1p0[3][3] = {				 {       0.0,        1.0,       0.0 },				 {       0.0,        0.0,       1.0 },				 { -810728.0,  1403580.0,       0.0 } };	SCYTHE_MINGW32_STATIC const double A2p0[3][3] = {				 {        0.0,        1.0,       0.0 },				 {        0.0,        0.0,       1.0 },				 { -1370589.0,        0.0,  527612.0 } };	SCYTHE_MINGW32_STATIC const double A1p76[3][3] = {				 {      82758667.0, 1871391091.0, 4127413238.0 },				 {    3672831523.0,   69195019.0, 1871391091.0 },				 {    3672091415.0, 3528743235.0,   69195019.0 } };	SCYTHE_MINGW32_STATIC const double A2p76[3][3] = {				 {    1511326704.0, 3759209742.0, 1610795712.0 },				 {    4292754251.0, 1511326704.0, 3889917532.0 },				 {    3859662829.0, 4292754251.0, 3708466080.0 } };	SCYTHE_MINGW32_STATIC const double A1p127[3][3] = {				 {    2427906178.0, 3580155704.0,  949770784.0 },				 {     226153695.0, 1230515664.0, 3580155704.0 },				 {    1988835001.0,  986791581.0, 1230515664.0 } };	SCYTHE_MINGW32_STATIC const double A2p127[3][3] = {				 {    1464411153.0,  277697599.0, 1610723613.0 },				 {      32183930.0, 1464411153.0, 1022607788.0 },				 {    2824425944.0,   32183930.0, 2093834863.0 } };	// Return (a*s + c) MOD m; a, s, c and m must be < 2^35	SCYTHE_MINGW32_STATIC double	MultModM (double a, double s, double c, double m)	{		double v;		long a1;		v = a * s + c;		if (v >= two53 || v <= -two53) {			a1 = static_cast<long> (a / two17);    a -= a1 * two17;			v  = a1 * s;			a1 = static_cast<long> (v / m);     v -= a1 * m;			v = v * two17 + a * s + c;		}		a1 = static_cast<long> (v / m);		/* in case v < 0)*/		if ((v -= a1 * m) < 0.0) return v += m;   else return v;	}	// Compute the vector v = A*s MOD m. Assume that -m < s[i] < m.	// Works also when v = s.	SCYTHE_MINGW32_STATIC void	MatVecModM (const double A[3][3], const double s[3],							double v[3], double m)	{		int i;		double x[3];               // Necessary if v = s		for (i = 0; i < 3; ++i) {			x[i] = MultModM (A[i][0], s[0], 0.0, m);			x[i] = MultModM (A[i][1], s[1], x[i], m);			x[i] = MultModM (A[i][2], s[2], x[i], m);		}		for (i = 0; i < 3; ++i)			v[i] = x[i];	}	// Compute the matrix C = A*B MOD m. Assume that -m < s[i] < m.	// Note: works also if A = C or B = C or A = B = C.	SCYTHE_MINGW32_STATIC void	MatMatModM (const double A[3][3], const double B[3][3],							double C[3][3], double m)	{		int i, j;		double V[3], W[3][3];		for (i = 0; i < 3; ++i) {			for (j = 0; j < 3; ++j)				V[j] = B[j][i];			MatVecModM (A, V, V, m);			for (j = 0; j < 3; ++j)				W[j][i] = V[j];		}		for (i = 0; i < 3; ++i)			for (j = 0; j < 3; ++j)				C[i][j] = W[i][j];	}	// Compute the matrix B = (A^(2^e) Mod m);  works also if A = B. 	SCYTHE_MINGW32_STATIC void	MatTwoPowModM(const double A[3][3], double B[3][3],								double m, long e)	{	 int i, j;	 /* initialize: B = A */	 if (A != B) {		 for (i = 0; i < 3; ++i)			 for (j = 0; j < 3; ++j)				 B[i][j] = A[i][j];	 }	 /* Compute B = A^(2^e) mod m */	 for (i = 0; i < e; i++)		 MatMatModM (B, B, B, m);	}	// Compute the matrix B = (A^n Mod m);  works even if A = B.	SCYTHE_MINGW32_STATIC void	MatPowModM (const double A[3][3], double B[3][3], double m,							long n)	{		int i, j;		double W[3][3];		/* initialize: W = A; B = I */		for (i = 0; i < 3; ++i)			for (j = 0; j < 3; ++j) {				W[i][j] = A[i][j];				B[i][j] = 0.0;			}		for (j = 0; j < 3; ++j)			B[j][j] = 1.0;		/* Compute B = A^n mod m using the binary decomposition of n */		while (n > 0) {			if (n % 2) MatMatModM (W, B, B, m);			MatMatModM (W, W, W, m);			n /= 2;		}	}	// Check that the seeds are legitimate values. Returns 0 if legal	// seeds, -1 otherwise.	SCYTHE_MINGW32_STATIC int	CheckSeed (const unsigned long seed[6])	{		int i;		for (i = 0; i < 3; ++i) {			if (seed[i] >= m1) {      SCYTHE_THROW(scythe_randseed_error,          "Seed[" << i << "] >= 4294967087, Seed is not set");				return -1;			}		}		for (i = 3; i < 6; ++i) {			if (seed[i] >= m2) {      SCYTHE_THROW(scythe_randseed_error,          "Seed[" << i << "] >= 4294944443, Seed is not set");				return -1;			}		}		if (seed[0] == 0 && seed[1] == 0 && seed[2] == 0) {      SCYTHE_THROW(scythe_randseed_error, "First 3 seeds = 0");			return -1;		}		if (seed[3] == 0 && seed[4] == 0 && seed[5] == 0) {      SCYTHE_THROW(scythe_randseed_error, "Last 3 seeds = 0");			return -1;		}		return 0;	} #ifndef __MINGW32__  } // end anonymous namespace#endif   /*! \brief The L'Ecuyer random number generator.    *    * This class defines a random number generator, using Pierre    * L'Ecuyer's algorithm (2000) and source code (2001) for    * generating multiple simultaneous streams of random uniform    * variates.  The period of the underlying single-stream generator    * is approximately \f$3.1 \times 10^{57}\f$.  Each individual    * stream is implemented in terms of a sequence of substreams (see    * L'Ecuyer et al (2000) for details).    *    * The lecuyer class extends Scythe's basic random number    * generating class, scythe::rng, implementing the interface that    * it defines.    *    * \see rng    * \see mersenne    *    */  class lecuyer : public rng<lecuyer>  {    public:      // Constructor      /*! \brief Constructor       *       * This constructor creates an object encapsulating a random       * number stream, with an optional name.  It also sets the seed       * of the stream to the package (default or user-specified) seed       * if this is the first stream generated, or, otherwise, to a       * value \f$2^{127}\f$ steps ahead of the seed of the previously       * constructed stream.       *       * \param streamname The optional name for the stream.       *       * \see SetPackageSeed(unsigned long seed[6])       * \see SetSeed(unsigned long seed[6])       * \see SetAntithetic(bool)       * \see IncreasedPrecis(bool)       * \see name()       */      lecuyer (std::string streamname = "")        : rng<lecuyer> (),          streamname_ (streamname)      {        anti = false;        incPrec = false;                /* Information on a stream. The arrays {Cg, Bg, Ig} contain         * the current state of the stream, the starting state of the         * current SubStream, and the starting state of the stream.         * This stream generates antithetic variates if anti = true.         * It also generates numbers with extended precision (53 bits         * if machine follows IEEE 754 standard) if incPrec = true.         * nextSeed will be the seed of the next declared RngStream.         */        for (int i = 0; i < 6; ++i) {          Bg[i] = Cg[i] = Ig[i] = nextSeed[i];        }        MatVecModM (A1p127, nextSeed, nextSeed, m1);        MatVecModM (A2p127, &nextSeed[3], &nextSeed[3], m2);      }      /*! \brief Get the stream's name.       *       * This method returns a stream's name string.       *       * \see lecuyer(const char*)       */      std::string      name() const      {        return streamname_;      }      /*! \brief Reset the stream.       *       * This method resets the stream to its initial seeded state.       *       * \see ResetStartSubstream()       * \see ResetNextSubstream()       * \see SetSeed(unsigned long seed[6])       */      void      ResetStartStream ()      {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -