#include "base/user_info.h"
#include "stat/exp_family.h"
#include "itpp_ext.h"
#include "../epdf_harness.h"
#include "../mat_checks.h"
#include "UnitTest++.h"

using namespace bdm;

TEST ( egamma_test ) {
    epdf_harness::test_config ( "egamma.cfg" );
}

TEST ( enorm_test ) {
    epdf_harness::test_config ( "enorm.cfg" );
}

TEST ( estudent_test ) {
    epdf_harness::test_config ( "estudent.cfg" );
}

// not using epdf_harness because eprod isn't configurable (yet?)
TEST ( eprod_test ) {

    RV a ( "{eprod_a }", "1" );
    RV b ( "{eprod_b }", "2" );

    egamma_ptr g0;
    g0->set_parameters ( vec ( "2" ), vec ( "2" ) );
    g0->validate();
    g0->set_rv ( a );

    egamma_ptr g1;
    g1->set_parameters ( vec ( "100000 10000" ), vec ( "10000 1000" ) );
    g1->validate();
    g1->set_rv ( b );

    Array<shared_ptr<epdf> > coms ( 2 );
    coms ( 0 ) = g0;
    coms ( 1 ) = g1;

    eprod p;
    // set_parameters doesn't say so, but it actually requires
    // pointers in the array to outlast the eprod instance...
    p.set_parameters ( coms );
    p.validate();

    CHECK_EQUAL ( vec ( "1 10 10" ), p.mean() );
    CHECK_EQUAL ( vec ( "0 0 0" ), p.variance() );
}

TEST ( ewishart_test ) {
    mat wM = "1.1 0.9; 0.9 1.0";
    eWishartCh eW;
    eW.set_parameters ( wM / 100, 100 );
    eW.validate();
    mat mea = zeros ( 2, 2 );
    mat Ch;
    for ( int i = 0; i < 100; i++ ) {
        Ch = eW.sample_mat();
        mea += Ch.T() * Ch;
    }

    mat actual = mea / 100;
    CHECK_CLOSE ( wM, actual, 0.1 );
}

TEST ( rwiwishart_test ) {
    mat wM = "1.0 0.9; 0.9 1.0";
    rwiWishartCh rwW;
    rwW.set_parameters ( 2, 0.1, "1 1", 0.9 );
    rwW.validate();
    mat mea = zeros ( 2, 2 );
    mat wMch = chol ( wM );
    mat Ch ( 2, 2 );

    for ( int i = 0; i < 100; i++ ) {
        vec tmp = rwW.samplecond ( vec ( wMch._data(), 4 ) );
        copy_vector ( 4, tmp._data(), Ch._data() );
        mea += Ch.T() * Ch;

    }

    mat observed ( "0.99464 0.885458; 0.885458 1.01853" );
    mat actual = mea / 100;
    CHECK_CLOSE ( observed, actual, 0.1 );
}

TEST ( dirich_test ) {
    epdf_harness::test_config ( "edirich.cfg" );
}
TEST ( ebeta_test ) {
    epdf_harness::test_config ( "ebeta.cfg" );
}
