#include "precompiled.h"
#include "cppunitlite/TestHarness.h"

__declspec(naked) double _sin_x87(double angle) {
	__asm {
		fld qword ptr[esp+4]
		fsin
		ret
	}
}

__declspec(naked) double _cos_x87(double angle) {
	__asm {
		fld qword ptr[esp + 4]
		fcos
		ret
	}
}

TEST(SinCosPrecision, SseMathFun, 10000)
{
	char localbuf[256];

	for (double i = 0.0; i < 2 * M_PI; i += (M_PI / 10000.0)) {
		double x87_sin = _sin_x87(i);
		double x87_cos = _cos_x87(i);

		__m128 s, c, d;
		d = _mm_set1_ps((float)i);
		sincos_ps(d, &s, &c);

		double sse_sin = _mm_cvtss_f32(s);
		double sse_cos = _mm_cvtss_f32(c);

		sprintf(localbuf, "sin precision failure for angle=%f", i);
		DOUBLES_EQUAL(localbuf, x87_sin, sse_sin, 0.000001);

		sprintf(localbuf, "cos precision failure for angle=%f", i);
		DOUBLES_EQUAL(localbuf, x87_cos, sse_cos, 0.000001);
	}
}

/*
TEST(SinCosPerformance, SseMathFun, 400000)
{
	DWORD x87_start = GetTickCount();
	for (int i = 0; i < 100000000; i++) {
		double res =_sin_x87(0.0);
		DOUBLES_EQUAL("check", res, 0.0, 0.000001);
	}

	DWORD sse_start = GetTickCount();

	__m128 s, c, d;
	for (int i = 0; i < 100000000; i++) {
		d = _mm_set1_ps(0.0f);
		sincos_ps(d, &s, &c);

		double res = _mm_cvtss_f32(s);
		DOUBLES_EQUAL("check", res, 0.0, 0.000001);
	}

	DWORD sse_end = GetTickCount();

	printf("Time consumed: x87: %u ; sse: %u", sse_start - x87_start, sse_end - sse_start);

}
*/