#include "mpdf_harness.h"
#include "base/bdmbase.h"
#include "base/user_info.h"
#include "stat/exp_family.h"
#include "mat_checks.h"
#include "test_util.h"
#include "UnitTest++.h"

namespace bdm {

template<>
const ParticularUI<mpdf_harness> &ParticularUI<mpdf_harness>::factory(
    ParticularUI<mpdf_harness>("mpdf_harness"));

void mpdf_harness::test_config(const char *config_file_name) {
    RV::clear_all();

    UIFile in(config_file_name);
    Array<mpdf_harness *> input;
    UI::get(input, in, "data");
    int sz = input.size();
    CHECK(sz > 0);
    for (int i = 0; i < sz; ++i) {
        input(i)->test(config_file_name, i);
    }
}

void mpdf_harness::from_setting(const Setting &set) {
    hmpdf = UI::build<mpdf>(set, "mpdf");
    UI::get(cond, set, "cond");
    UI::get(mean, set, "mean");

    if (set.exists("nsamples")) {
        UI::get(nsamples, set, "nsamples");
    }

    UI::get(R, set, "R");

    if (set.exists("tolerance")) {
        UI::get(tolerance, set, "tolerance");
    }
}

void mpdf_harness::test(const char *config_name, int idx)
{
    CurrentContext cc(config_name, idx);

    mat smp = hmpdf->samplecond_m(cond, nsamples);
    int n = smp.cols();
    vec emu = smp * ones(n) / n;
    mat er = (smp * smp.T()) / n - outer_product(emu, emu);
    CHECK_CLOSE_EX(mean, emu, tolerance);
    CHECK_CLOSE_EX(R, er, tolerance);
}

}
