#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();
}
