#include "mat_checks.h"
#include <sstream>

namespace UnitTest {

bool AreClose ( const itpp::vec &expected, const itpp::vec &actual,
                double tolerance ) {
    if ( expected.length() != actual.length() ) {
        return false;
    }

    for ( int i = 0; i < expected.length(); ++i ) {
        if ( !AreClose ( expected ( i ), actual ( i ), tolerance ) ) {
            return false;
        }
    }

    return true;
}

bool AreClose ( const itpp::vec &expected, const itpp::vec &actual,
                const itpp::vec &tolerance ) {
    if ( ( expected.length() != actual.length() ) ||
            ( actual.length() != tolerance.length() ) ) {
        return false;
    }

    for ( int i = 0; i < expected.length(); ++i ) {
        if ( !AreClose ( expected ( i ), actual ( i ), tolerance ( i ) ) ) {
            return false;
        }
    }

    return true;
}

bool AreClose ( const itpp::mat &expected, const itpp::mat &actual, double tolerance ) {
    if ( ( expected.rows() != actual.rows() ) ||
            ( expected.cols() != actual.cols() ) ) {
        return false;
    }

    for ( int i = 0; i < expected.rows(); ++i ) {
        for ( int j = 0; j < expected.cols(); ++j ) {
            if ( !AreClose ( expected ( i, j ), actual ( i, j ), tolerance ) ) {
                return false;
            }
        }
    }

    return true;
}

}

const char *CurrentContext::config_name = "???";

int CurrentContext::index = -1;

CurrentContext::CurrentContext ( const char *name, int idx ) {
    config_name = name;
    index = idx;
}

CurrentContext::~CurrentContext() {
    config_name = "???";
    index = -1;
}

std::string CurrentContext::format_context ( int ln ) {
    std::stringstream ss;
    ss << "error at " << config_name << '[' << index << ']';

    if ( ln >= 0 ) {
        ss << ", harness line " << ln;
    }

    ss << ": ";
    return ss.str();
}
