diff --git a/cockatrice/cockatrice.pro b/cockatrice/cockatrice.pro index a6885d71..0862062d 100644 --- a/cockatrice/cockatrice.pro +++ b/cockatrice/cockatrice.pro @@ -69,7 +69,7 @@ HEADERS += src/counter.h \ ../common/protocol_items.h \ ../common/protocol_datastructures.h \ ../common/rng_abstract.h \ - ../common/rng_qt.h \ + ../common/rng_sfmt.h \ ../common/server.h \ ../common/server_arrow.h \ ../common/server_card.h \ @@ -142,7 +142,8 @@ SOURCES += src/counter.cpp \ ../common/protocol_items.cpp \ ../common/protocol_datastructures.cpp \ ../common/rng_abstract.cpp \ - ../common/rng_qt.cpp \ + ../common/rng_sfmt.cpp \ + ../common/sfmt/SFMT.c \ ../common/server.cpp \ ../common/server_card.cpp \ ../common/server_cardzone.cpp \ diff --git a/common/rng_abstract.cpp b/common/rng_abstract.cpp index eb2e38ac..229d2592 100644 --- a/common/rng_abstract.cpp +++ b/common/rng_abstract.cpp @@ -1,4 +1,33 @@ #include "rng_abstract.h" #include "rng_qt.h" +#include "rng_sfmt.h" +#include -RNG_Abstract *rng = new RNG_Qt; +RNG_Abstract *rng = new RNG_SFMT; + +QVector RNG_Abstract::makeNumbersVector(int n, int min, int max) +{ + const int bins = max - min + 1; + QVector result(bins); + for (int i = 0; i < n; ++i) { + int number = getNumber(min, max); + if ((number < min) || (number > max)) + qDebug() << "getNumber(" << min << "," << max << ") returned " << number; + else + result[number - min]++; + } + return result; +} + +double RNG_Abstract::testRandom(const QVector &numbers) const +{ + int n = 0; + for (int i = 0; i < numbers.size(); ++i) + n += numbers[i]; + double expected = (double) n / (double) numbers.size(); + double chisq = 0; + for (int i = 0; i < numbers.size(); ++i) + chisq += ((double) numbers[i] - expected) * ((double) numbers[i] - expected) / expected; + + return chisq; +} diff --git a/common/rng_abstract.h b/common/rng_abstract.h index 739efeb3..5d60033f 100644 --- a/common/rng_abstract.h +++ b/common/rng_abstract.h @@ -2,12 +2,15 @@ #define RNG_ABSTRACT_H #include +#include class RNG_Abstract : public QObject { Q_OBJECT public: RNG_Abstract(QObject *parent = 0) : QObject(parent) { } virtual unsigned int getNumber(unsigned int min, unsigned int max) = 0; + QVector makeNumbersVector(int n, int min, int max); + double testRandom(const QVector &numbers) const; }; extern RNG_Abstract *rng; diff --git a/common/rng_qt.cpp b/common/rng_qt.cpp index 30cb8b34..6704cdb8 100644 --- a/common/rng_qt.cpp +++ b/common/rng_qt.cpp @@ -6,7 +6,6 @@ RNG_Qt::RNG_Qt(QObject *parent) : RNG_Abstract(parent) { int seed = QDateTime::currentDateTime().toTime_t(); - qDebug(QString("qsrand(%1)").arg(seed).toLatin1()); qsrand(seed); } diff --git a/servatrice/servatrice.pro b/servatrice/servatrice.pro index 60879067..60f04b7c 100755 --- a/servatrice/servatrice.pro +++ b/servatrice/servatrice.pro @@ -20,7 +20,7 @@ HEADERS += src/servatrice.h \ ../common/protocol_items.h \ ../common/protocol_datastructures.h \ ../common/rng_abstract.h \ - ../common/rng_qt.h \ + ../common/rng_sfmt.h \ ../common/server.h \ ../common/server_arrow.h \ ../common/server_card.h \ @@ -41,7 +41,8 @@ SOURCES += src/main.cpp \ ../common/protocol_items.cpp \ ../common/protocol_datastructures.cpp \ ../common/rng_abstract.cpp \ - ../common/rng_qt.cpp \ + ../common/rng_sfmt.cpp \ + ../common/sfmt/SFMT.c \ ../common/server.cpp \ ../common/server_card.cpp \ ../common/server_cardzone.cpp \ diff --git a/servatrice/src/main.cpp b/servatrice/src/main.cpp index 6294aa6d..2d16cb20 100644 --- a/servatrice/src/main.cpp +++ b/servatrice/src/main.cpp @@ -20,7 +20,9 @@ #include #include +#include #include "servatrice.h" +#include "rng_abstract.h" void myMessageOutput(QtMsgType /*type*/, const char *msg) { @@ -31,6 +33,41 @@ void myMessageOutput(QtMsgType /*type*/, const char *msg) fflush(f); } +void testRNG() +{ + const int n = 500000; + std::cerr << "Testing random number generator (n = " << n << " * bins)..." << std::endl; + + const int min = 1; + const int minMax = 2; + const int maxMax = 10; + + QVector > numbers(maxMax - minMax + 1); + QVector chisq(maxMax - minMax + 1); + for (int max = minMax; max <= maxMax; ++max) { + numbers[max - minMax] = rng->makeNumbersVector(n * (max - min + 1), min, max); + chisq[max - minMax] = rng->testRandom(numbers[max - minMax]); + } + qDebug() << numbers; + for (int i = 0; i <= maxMax - min; ++i) { + std::cerr << (min + i); + for (int j = 0; j < numbers.size(); ++j) { + if (i < numbers[j].size()) + std::cerr << "\t" << numbers[j][i]; + else + std::cerr << "\t"; + } + std::cerr << std::endl; + } + std::cerr << std::endl << "Chi^2 ="; + for (int j = 0; j < chisq.size(); ++j) + std::cerr << "\t" << QString::number(chisq[j], 'f', 3).toStdString(); + std::cerr << std::endl << "k ="; + for (int j = 0; j < chisq.size(); ++j) + std::cerr << "\t" << (j - min + minMax); + std::cerr << std::endl << std::endl; +} + int main(int argc, char *argv[]) { qInstallMsgHandler(myMessageOutput); @@ -40,8 +77,16 @@ int main(int argc, char *argv[]) app.setApplicationName("Servatrice"); QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); + + std::cerr << "Servatrice " << Servatrice::versionString.toStdString() << " starting." << std::endl; + std::cerr << "-------------------------" << std::endl; + testRNG(); + Servatrice server; + std::cerr << "-------------------------" << std::endl; + std::cerr << "Server initialized." << std::endl; + return app.exec(); } diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index 74d1966d..66774339 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -139,4 +139,4 @@ AuthenticationResult Servatrice::checkUserPassword(const QString &user, const QS return UnknownUser; } -const QString Servatrice::versionString = "Servatrice 0.20100603"; +const QString Servatrice::versionString = "Servatrice 0.20100915";