// @(#)root/mathcore:$Id$
// Author: L. Moneta Tue Aug 4 2015

/**********************************************************************
 *                                                                    *
 * Copyright (c) 2015  LCG ROOT Math Team, CERN/PH-SFT                *
 *                                                                    *
 *                                                                    *
 **********************************************************************/

// random engines based on ROOT 

#ifndef ROOT_Math_MixMaxEngine
#define ROOT_Math_MixMaxEngine

#include <cstdint>
#include <vector>
#include <string>

#ifndef ROOT_Math_TRandomEngine
#include "Math/TRandomEngine.h"
#endif


// struct rng_state_st;    /// forward declare generator state

// typedef struct rng_state_st rng_state_t;

// namespace mixmax { 
//    template<int Ndim>
//    class mixmax_engine; 
// }

namespace ROOT {

   namespace Math {
      
      template<int N>
      class MixMaxEngineImpl;

      /**
         Wrapper class for the MIXMAX Random number generator.
         It is a matrix-recursive random number generator introduced by
         G. Savvidy.

         See the real implementation in the mixmax.h and mixmax.cxx files.
         The generator code is available also at hepforge: http://mixmax.hepforge.org


         Created by Konstantin Savvidy.

         The code is released under GNU Lesser General Public License v3

         References:

         G.K.Savvidy and N.G.Ter-Arutyunian,
         On the Monte Carlo simulation of physical systems,
         J.Comput.Phys. 97, 566 (1991);
         Preprint EPI-865-16-86, Yerevan, Jan. 1986

         K.Savvidy
         The MIXMAX random number generator
         Comp. Phys. Commun. 196 (2015), pp 161–165
         http://dx.doi.org/10.1016/j.cpc.2015.06.003

         K.Savvidy and G.Savvidy
         Spectrum and Entropy of C-systems. MIXMAX random number generator
         Chaos, Solitons & Fractals, Volume 91, (2016) pp. 33–38
         http://dx.doi.org/10.1016/j.chaos.2016.05.003

         The period of the generator is 10^4682 for N=256, and
         10^1597 for N=88

         This implementation is only a wrapper around the real implemention, see mixmax.cxx and mixmax.h
         The generator, in C code, is available also at hepforge: http://mixmax.hepforge.org


         @ingroup Random
      */

      template<int N, int SkipNumber>
      class MixMaxEngine : public TRandomEngine {

      public:

         typedef  TRandomEngine BaseType;

         // this should be changed for WINDOWS
#ifndef __LP64__
         typedef uint64_t StateInt_t;
#else
         typedef unsigned long long StateInt_t;
#endif
         typedef uint64_t Result_t;


         MixMaxEngine(uint64_t seed=1);

         virtual ~MixMaxEngine();


         /// Get the size of the generator
         static int Size();

         /// maximum integer that can be generated. For MIXMAX is 2^61-1
         static uint64_t MaxInt();

         /// minimum integer that can be generated. For MIXMAX is 0
         static uint64_t MinInt();

         /// set the generator seed
         void  SetSeed(Result_t seed);

         // generate a random number (virtual interface)
         virtual double Rndm() { return Rndm_impl(); }

         /// generate a double random number (faster interface)
         inline double operator() () { return Rndm_impl(); }

         /// generate an array of random numbers
         void RndmArray (int n, double * array);

         /// generate a 64  bit integer number
         Result_t IntRndm();

         /// get name of the generator
         static std::string Name();

      protected:
         // protected functions used for tesing the generator

         /// get the state of the generator
         void GetState(std::vector<StateInt_t> & state) const;


         ///set the full initial generator state
         void SetState(const std::vector<StateInt_t> & state);

         /// Get the counter (between 0 and Size-1)
         int Counter() const;


      private:

         /// implementation function to generate the random number
         double Rndm_impl();

         //rng_state_t * fRngState;  // mix-max generator state
         //mixmax::mixmax_engine<N> * fRng;  // mixmax internal engine class
         MixMaxEngineImpl<N> * fRng;  // mixmax internal engine class
         
      };

      typedef MixMaxEngine<240,0> MixMaxEngine240;
      typedef MixMaxEngine<256,2> MixMaxEngine256;
      typedef MixMaxEngine<17,0> MixMaxEngine17;
      
      extern template class MixMaxEngine<240,0>;
      extern template class MixMaxEngine<256,0>;
      extern template class MixMaxEngine<256,2>;
      extern template class MixMaxEngine<256,4>;
      extern template class MixMaxEngine<17,0>;
      extern template class MixMaxEngine<17,1>;
      extern template class MixMaxEngine<17,2>;

   } // end namespace Math

} // end namespace ROOT


#include "Math/MixMaxEngine.icc"

#endif /* ROOT_Math_MixMaxEngine */ 
 MixMaxEngine.h:1
 MixMaxEngine.h:2
 MixMaxEngine.h:3
 MixMaxEngine.h:4
 MixMaxEngine.h:5
 MixMaxEngine.h:6
 MixMaxEngine.h:7
 MixMaxEngine.h:8
 MixMaxEngine.h:9
 MixMaxEngine.h:10
 MixMaxEngine.h:11
 MixMaxEngine.h:12
 MixMaxEngine.h:13
 MixMaxEngine.h:14
 MixMaxEngine.h:15
 MixMaxEngine.h:16
 MixMaxEngine.h:17
 MixMaxEngine.h:18
 MixMaxEngine.h:19
 MixMaxEngine.h:20
 MixMaxEngine.h:21
 MixMaxEngine.h:22
 MixMaxEngine.h:23
 MixMaxEngine.h:24
 MixMaxEngine.h:25
 MixMaxEngine.h:26
 MixMaxEngine.h:27
 MixMaxEngine.h:28
 MixMaxEngine.h:29
 MixMaxEngine.h:30
 MixMaxEngine.h:31
 MixMaxEngine.h:32
 MixMaxEngine.h:33
 MixMaxEngine.h:34
 MixMaxEngine.h:35
 MixMaxEngine.h:36
 MixMaxEngine.h:37
 MixMaxEngine.h:38
 MixMaxEngine.h:39
 MixMaxEngine.h:40
 MixMaxEngine.h:41
 MixMaxEngine.h:42
 MixMaxEngine.h:43
 MixMaxEngine.h:44
 MixMaxEngine.h:45
 MixMaxEngine.h:46
 MixMaxEngine.h:47
 MixMaxEngine.h:48
 MixMaxEngine.h:49
 MixMaxEngine.h:50
 MixMaxEngine.h:51
 MixMaxEngine.h:52
 MixMaxEngine.h:53
 MixMaxEngine.h:54
 MixMaxEngine.h:55
 MixMaxEngine.h:56
 MixMaxEngine.h:57
 MixMaxEngine.h:58
 MixMaxEngine.h:59
 MixMaxEngine.h:60
 MixMaxEngine.h:61
 MixMaxEngine.h:62
 MixMaxEngine.h:63
 MixMaxEngine.h:64
 MixMaxEngine.h:65
 MixMaxEngine.h:66
 MixMaxEngine.h:67
 MixMaxEngine.h:68
 MixMaxEngine.h:69
 MixMaxEngine.h:70
 MixMaxEngine.h:71
 MixMaxEngine.h:72
 MixMaxEngine.h:73
 MixMaxEngine.h:74
 MixMaxEngine.h:75
 MixMaxEngine.h:76
 MixMaxEngine.h:77
 MixMaxEngine.h:78
 MixMaxEngine.h:79
 MixMaxEngine.h:80
 MixMaxEngine.h:81
 MixMaxEngine.h:82
 MixMaxEngine.h:83
 MixMaxEngine.h:84
 MixMaxEngine.h:85
 MixMaxEngine.h:86
 MixMaxEngine.h:87
 MixMaxEngine.h:88
 MixMaxEngine.h:89
 MixMaxEngine.h:90
 MixMaxEngine.h:91
 MixMaxEngine.h:92
 MixMaxEngine.h:93
 MixMaxEngine.h:94
 MixMaxEngine.h:95
 MixMaxEngine.h:96
 MixMaxEngine.h:97
 MixMaxEngine.h:98
 MixMaxEngine.h:99
 MixMaxEngine.h:100
 MixMaxEngine.h:101
 MixMaxEngine.h:102
 MixMaxEngine.h:103
 MixMaxEngine.h:104
 MixMaxEngine.h:105
 MixMaxEngine.h:106
 MixMaxEngine.h:107
 MixMaxEngine.h:108
 MixMaxEngine.h:109
 MixMaxEngine.h:110
 MixMaxEngine.h:111
 MixMaxEngine.h:112
 MixMaxEngine.h:113
 MixMaxEngine.h:114
 MixMaxEngine.h:115
 MixMaxEngine.h:116
 MixMaxEngine.h:117
 MixMaxEngine.h:118
 MixMaxEngine.h:119
 MixMaxEngine.h:120
 MixMaxEngine.h:121
 MixMaxEngine.h:122
 MixMaxEngine.h:123
 MixMaxEngine.h:124
 MixMaxEngine.h:125
 MixMaxEngine.h:126
 MixMaxEngine.h:127
 MixMaxEngine.h:128
 MixMaxEngine.h:129
 MixMaxEngine.h:130
 MixMaxEngine.h:131
 MixMaxEngine.h:132
 MixMaxEngine.h:133
 MixMaxEngine.h:134
 MixMaxEngine.h:135
 MixMaxEngine.h:136
 MixMaxEngine.h:137
 MixMaxEngine.h:138
 MixMaxEngine.h:139
 MixMaxEngine.h:140
 MixMaxEngine.h:141
 MixMaxEngine.h:142
 MixMaxEngine.h:143
 MixMaxEngine.h:144
 MixMaxEngine.h:145
 MixMaxEngine.h:146
 MixMaxEngine.h:147
 MixMaxEngine.h:148
 MixMaxEngine.h:149
 MixMaxEngine.h:150
 MixMaxEngine.h:151
 MixMaxEngine.h:152
 MixMaxEngine.h:153
 MixMaxEngine.h:154
 MixMaxEngine.h:155
 MixMaxEngine.h:156
 MixMaxEngine.h:157
 MixMaxEngine.h:158
 MixMaxEngine.h:159
 MixMaxEngine.h:160
 MixMaxEngine.h:161
 MixMaxEngine.h:162
 MixMaxEngine.h:163
 MixMaxEngine.h:164
 MixMaxEngine.h:165
 MixMaxEngine.h:166
 MixMaxEngine.h:167
 MixMaxEngine.h:168
 MixMaxEngine.h:169
 MixMaxEngine.h:170
 MixMaxEngine.h:171
 MixMaxEngine.h:172
 MixMaxEngine.h:173