#ifndef RNG_H
#define RNG_H

#include "cryptlib.h"
#include "filters.h"

// linear congruential generator
// originally by William S. England

// do not use for cryptographic purposes

class LC_RNG : public RandomNumberGenerator
{
public:
    LC_RNG(word32 init_seed)
        : seedBytes((byte *)&seed) {seed=init_seed;}

    byte GetByte();

    word32 GetSeed() {return seed;}

private:
    word32 seed;
    byte *const seedBytes;

    static const word32 m;
    static const word32 q;
    static const word16 a;
    static const word16 r;
};

// RNG derived from ANSI X9.17 Appendix C

class X917RNG : public RandomNumberGenerator
{
public:
    // cipher will be deleted by destructor
    X917RNG(BlockTransformation *cipher, const byte *seed);

    byte GetByte();

private:
    member_ptr<BlockTransformation> cipher;
    const int S;            // blocksize of cipher
    SecByteBlock dtbuf;     // buffer for enciphered timestamp
    SecByteBlock randseed, randbuf;
    int randbuf_counter;    // # of unused bytes left in randbuf
};

// This class implements Maurer's Universal Statistical Test for Random Bit Generators
// it is intended for measuring the randomness of *PHYSICAL* RNGs.
// For more details see his paper in Journal of Cryptology, 1992.

class MaurerRandomnessTest : public Sink
{
public:
    MaurerRandomnessTest();

    void Put(byte inByte);
    void Put(const byte *inString, unsigned int length);

    // BytesNeeded() returns how many more bytes of input is needed by the test
    // GetTestValue() should not be called before BytesNeeded()==0
    unsigned int BytesNeeded() const {return n >= (Q+K) ? 0 : Q+K-n;}

    // returns a number between 0.0 and 1.0, describing the quality of the
    // random numbers entered
    double GetTestValue() const;

private:
    enum {L=8, V=256, Q=2000, K=2000};
    double sum;
    unsigned int n;
    unsigned int tab[V];
};

#endif
