#include "gtest/gtest.h"
#include "odamex.h"
#include "m_fixed.h"

// TODO: tests for overflows, we want to catch things like when some of the 64 bit stuff had accidental conversions to 32 bit

// 16.16 fixed_t

// -------------------------------------
// ------- type conversion tests -------
// -------------------------------------

// -------- int to fixed to int --------

TEST(FixedMath, IntConversion) {
	EXPECT_EQ(FIXED2INT(INT2FIXED(0)), 0);
	EXPECT_EQ(FIXED2INT(INT2FIXED(1)), 1);
	EXPECT_EQ(FIXED2INT(INT2FIXED(2)), 2);
	EXPECT_EQ(FIXED2INT(INT2FIXED(10)), 10);
	EXPECT_EQ(FIXED2INT(INT2FIXED(1234)), 1234);
	EXPECT_EQ(FIXED2INT(INT2FIXED(32767)), 32767);
}

TEST(FixedMath, NegativeIntConversion) {
	EXPECT_EQ(FIXED2INT(INT2FIXED(-1)), -1);
	EXPECT_EQ(FIXED2INT(INT2FIXED(-2)), -2);
	EXPECT_EQ(FIXED2INT(INT2FIXED(-10)), -10);
	EXPECT_EQ(FIXED2INT(INT2FIXED(-1234)), -1234);
	EXPECT_EQ(FIXED2INT(INT2FIXED(-32768)), -32768);
}

// ------ double to fixed to int -------

TEST(FixedMath, DoubleConversionRoundUpToInt) {
	EXPECT_EQ(FIXED2INT(DOUBLE2FIXED(0.6)), 1);
	EXPECT_EQ(FIXED2INT(DOUBLE2FIXED(1.6)), 2);
	EXPECT_EQ(FIXED2INT(DOUBLE2FIXED(2.6)), 3);
	EXPECT_EQ(FIXED2INT(DOUBLE2FIXED(10.6)), 11);
	EXPECT_EQ(FIXED2INT(DOUBLE2FIXED(1234.6)), 1235);
	EXPECT_EQ(FIXED2INT(DOUBLE2FIXED(32766.6)), 32767);
}

TEST(FixedMath, DoubleConversionRoundDownToInt) {
	EXPECT_EQ(FIXED2INT(DOUBLE2FIXED(0.4)), 0);
	EXPECT_EQ(FIXED2INT(DOUBLE2FIXED(1.4)), 1);
	EXPECT_EQ(FIXED2INT(DOUBLE2FIXED(2.4)), 2);
	EXPECT_EQ(FIXED2INT(DOUBLE2FIXED(10.4)), 10);
	EXPECT_EQ(FIXED2INT(DOUBLE2FIXED(1234.4)), 1234);
	EXPECT_EQ(FIXED2INT(DOUBLE2FIXED(32767.4)), 32767);
}

TEST(FixedMath, NegativeDoubleConversionRoundUpToInt) {
	EXPECT_EQ(FIXED2INT(DOUBLE2FIXED(-1.4)), -1);
	EXPECT_EQ(FIXED2INT(DOUBLE2FIXED(-2.4)), -2);
	EXPECT_EQ(FIXED2INT(DOUBLE2FIXED(-10.4)), -10);
	EXPECT_EQ(FIXED2INT(DOUBLE2FIXED(-1234.4)), -1234);
	EXPECT_EQ(FIXED2INT(DOUBLE2FIXED(-32767.4)), -32767);
}

TEST(FixedMath, NegativeDoubleConversionRoundDownToInt) {
	EXPECT_EQ(FIXED2INT(DOUBLE2FIXED(-1.6)), -2);
	EXPECT_EQ(FIXED2INT(DOUBLE2FIXED(-2.6)), -3);
	EXPECT_EQ(FIXED2INT(DOUBLE2FIXED(-10.6)), -11);
	EXPECT_EQ(FIXED2INT(DOUBLE2FIXED(-1234.6)), -1235);
	EXPECT_EQ(FIXED2INT(DOUBLE2FIXED(-32767.6)), -32768);
}

// ------- float to fixed to int -------

TEST(FixedMath, FloatConversionRoundUpToInt) {
	EXPECT_EQ(FIXED2INT(FLOAT2FIXED(0.6f)), 1);
	EXPECT_EQ(FIXED2INT(FLOAT2FIXED(1.6f)), 2);
	EXPECT_EQ(FIXED2INT(FLOAT2FIXED(2.6f)), 3);
	EXPECT_EQ(FIXED2INT(FLOAT2FIXED(10.6f)), 11);
	EXPECT_EQ(FIXED2INT(FLOAT2FIXED(1234.6f)), 1235);
	EXPECT_EQ(FIXED2INT(FLOAT2FIXED(32766.6f)), 32767);
}

TEST(FixedMath, FloatConversionRoundDownToInt) {
	EXPECT_EQ(FIXED2INT(FLOAT2FIXED(0.4f)), 0);
	EXPECT_EQ(FIXED2INT(FLOAT2FIXED(1.4f)), 1);
	EXPECT_EQ(FIXED2INT(FLOAT2FIXED(2.4f)), 2);
	EXPECT_EQ(FIXED2INT(FLOAT2FIXED(10.4f)), 10);
	EXPECT_EQ(FIXED2INT(FLOAT2FIXED(1234.4f)), 1234);
	EXPECT_EQ(FIXED2INT(FLOAT2FIXED(32767.4f)), 32767);
}

TEST(FixedMath, NegativeFloatConversionRoundUpToInt) {
	EXPECT_EQ(FIXED2INT(FLOAT2FIXED(-1.4f)), -1);
	EXPECT_EQ(FIXED2INT(FLOAT2FIXED(-2.4f)), -2);
	EXPECT_EQ(FIXED2INT(FLOAT2FIXED(-10.4f)), -10);
	EXPECT_EQ(FIXED2INT(FLOAT2FIXED(-1234.4f)), -1234);
	EXPECT_EQ(FIXED2INT(FLOAT2FIXED(-32767.4f)), -32767);
}

TEST(FixedMath, NegativeFloatConversionRoundDownToInt) {
	EXPECT_EQ(FIXED2INT(FLOAT2FIXED(-1.6f)), -2);
	EXPECT_EQ(FIXED2INT(FLOAT2FIXED(-2.6f)), -3);
	EXPECT_EQ(FIXED2INT(FLOAT2FIXED(-10.6f)), -11);
	EXPECT_EQ(FIXED2INT(FLOAT2FIXED(-1234.6f)), -1235);
	EXPECT_EQ(FIXED2INT(FLOAT2FIXED(-32767.6f)), -32768);
}

// ----- double to fixed to double -----

TEST(FixedMath, DoubleConversion) {
	EXPECT_DOUBLE_EQ(FIXED2DOUBLE(DOUBLE2FIXED(0.0)), 0.0);
	EXPECT_DOUBLE_EQ(FIXED2DOUBLE(DOUBLE2FIXED(1.0)), 1.0);
	EXPECT_DOUBLE_EQ(FIXED2DOUBLE(DOUBLE2FIXED(1.25)), 1.25);
	EXPECT_DOUBLE_EQ(FIXED2DOUBLE(DOUBLE2FIXED(1234.5)), 1234.5);
}

TEST(FixedMath, NegativeDoubleConversion) {
	EXPECT_DOUBLE_EQ(FIXED2DOUBLE(DOUBLE2FIXED(-0.0)), -0.0);
	EXPECT_DOUBLE_EQ(FIXED2DOUBLE(DOUBLE2FIXED(-1.0)), -1.0);
	EXPECT_DOUBLE_EQ(FIXED2DOUBLE(DOUBLE2FIXED(-1.25)), -1.25);
	EXPECT_DOUBLE_EQ(FIXED2DOUBLE(DOUBLE2FIXED(-1234.5)), -1234.5);
}

// ------ float to fixed to float ------

TEST(FixedMath, FloatConversion) {
	EXPECT_FLOAT_EQ(FIXED2FLOAT(FLOAT2FIXED(0.0f)), 0.0f);
	EXPECT_FLOAT_EQ(FIXED2FLOAT(FLOAT2FIXED(1.0f)), 1.0f);
	EXPECT_FLOAT_EQ(FIXED2FLOAT(FLOAT2FIXED(1.25f)), 1.25f);
	EXPECT_FLOAT_EQ(FIXED2FLOAT(FLOAT2FIXED(1234.5f)), 1234.5f);
}

TEST(FixedMath, NegativeFloatConversion) {
	EXPECT_FLOAT_EQ(FIXED2FLOAT(FLOAT2FIXED(-0.0f)), -0.0f);
	EXPECT_FLOAT_EQ(FIXED2FLOAT(FLOAT2FIXED(-1.0f)), -1.0f);
	EXPECT_FLOAT_EQ(FIXED2FLOAT(FLOAT2FIXED(-1.25f)), -1.25f);
	EXPECT_FLOAT_EQ(FIXED2FLOAT(FLOAT2FIXED(-1234.5f)), -1234.5f);
}

// 44.20 fixed64_t

// -------------------------------------
// ------- type conversion tests -------
// -------------------------------------

// -------- int to fixed to int --------

TEST(FixedMath64, IntConversion) {
	EXPECT_EQ(FIXED642INT(INT2FIXED64(0)), 0);
	EXPECT_EQ(FIXED642INT(INT2FIXED64(1)), 1);
	EXPECT_EQ(FIXED642INT(INT2FIXED64(2)), 2);
	EXPECT_EQ(FIXED642INT(INT2FIXED64(10)), 10);
	EXPECT_EQ(FIXED642INT(INT2FIXED64(1234)), 1234);
	EXPECT_EQ(FIXED642INT(INT2FIXED64(32767)), 32767);
	EXPECT_EQ(FIXED642INT(INT2FIXED64(2147483647)), 2147483647);
}

TEST(FixedMath64, NegativeIntConversion) {
	EXPECT_EQ(FIXED642INT(INT2FIXED64(-1)), -1);
	EXPECT_EQ(FIXED642INT(INT2FIXED64(-2)), -2);
	EXPECT_EQ(FIXED642INT(INT2FIXED64(-10)), -10);
	EXPECT_EQ(FIXED642INT(INT2FIXED64(-1234)), -1234);
	EXPECT_EQ(FIXED642INT(INT2FIXED64(-32768)), -32768);
	EXPECT_EQ(FIXED642INT(INT2FIXED64(-2147483648)), -2147483648);
}

// ------ double to fixed to int -------

TEST(FixedMath64, DISABLED_DoubleConversionRoundUpToInt) {
	EXPECT_EQ(FIXED642INT(DOUBLE2FIXED64(0.6)), 1);
	EXPECT_EQ(FIXED642INT(DOUBLE2FIXED64(1.6)), 2);
	EXPECT_EQ(FIXED642INT(DOUBLE2FIXED64(2.6)), 3);
	EXPECT_EQ(FIXED642INT(DOUBLE2FIXED64(10.6)), 11);
	EXPECT_EQ(FIXED642INT(DOUBLE2FIXED64(1234.6)), 1235);
	EXPECT_EQ(FIXED642INT(DOUBLE2FIXED64(32766.6)), 32767);
}

TEST(FixedMath64, DoubleConversionRoundDownToInt) {
	EXPECT_EQ(FIXED642INT(DOUBLE2FIXED64(0.4)), 0);
	EXPECT_EQ(FIXED642INT(DOUBLE2FIXED64(1.4)), 1);
	EXPECT_EQ(FIXED642INT(DOUBLE2FIXED64(2.4)), 2);
	EXPECT_EQ(FIXED642INT(DOUBLE2FIXED64(10.4)), 10);
	EXPECT_EQ(FIXED642INT(DOUBLE2FIXED64(1234.4)), 1234);
	EXPECT_EQ(FIXED642INT(DOUBLE2FIXED64(32767.4)), 32767);
}

TEST(FixedMath64, DISABLED_NegativeDoubleConversionRoundUpToInt) {
	EXPECT_EQ(FIXED642INT(DOUBLE2FIXED64(-1.4)), -1);
	EXPECT_EQ(FIXED642INT(DOUBLE2FIXED64(-2.4)), -2);
	EXPECT_EQ(FIXED642INT(DOUBLE2FIXED64(-10.4)), -10);
	EXPECT_EQ(FIXED642INT(DOUBLE2FIXED64(-1234.4)), -1234);
	EXPECT_EQ(FIXED642INT(DOUBLE2FIXED64(-32767.4)), -32767);
}

TEST(FixedMath64, NegativeDoubleConversionRoundDownToInt) {
	EXPECT_EQ(FIXED642INT(DOUBLE2FIXED64(-1.6)), -2);
	EXPECT_EQ(FIXED642INT(DOUBLE2FIXED64(-2.6)), -3);
	EXPECT_EQ(FIXED642INT(DOUBLE2FIXED64(-10.6)), -11);
	EXPECT_EQ(FIXED642INT(DOUBLE2FIXED64(-1234.6)), -1235);
	EXPECT_EQ(FIXED642INT(DOUBLE2FIXED64(-32767.6)), -32768);
}

// ------- float to fixed to int -------

TEST(FixedMath64, DISABLED_FloatConversionRoundUpToInt) {
	EXPECT_EQ(FIXED642INT(FLOAT2FIXED64(0.6f)), 1);
	EXPECT_EQ(FIXED642INT(FLOAT2FIXED64(1.6f)), 2);
	EXPECT_EQ(FIXED642INT(FLOAT2FIXED64(2.6f)), 3);
	EXPECT_EQ(FIXED642INT(FLOAT2FIXED64(10.6f)), 11);
	EXPECT_EQ(FIXED642INT(FLOAT2FIXED64(1234.6f)), 1235);
	EXPECT_EQ(FIXED642INT(FLOAT2FIXED64(32766.6f)), 32767);
}

TEST(FixedMath64, FloatConversionRoundDownToInt) {
	EXPECT_EQ(FIXED642INT(FLOAT2FIXED64(0.4f)), 0);
	EXPECT_EQ(FIXED642INT(FLOAT2FIXED64(1.4f)), 1);
	EXPECT_EQ(FIXED642INT(FLOAT2FIXED64(2.4f)), 2);
	EXPECT_EQ(FIXED642INT(FLOAT2FIXED64(10.4f)), 10);
	EXPECT_EQ(FIXED642INT(FLOAT2FIXED64(1234.4f)), 1234);
	EXPECT_EQ(FIXED642INT(FLOAT2FIXED64(32767.4f)), 32767);
}

TEST(FixedMath64, DISABLED_NegativeFloatConversionRoundUpToInt) {
	EXPECT_EQ(FIXED642INT(FLOAT2FIXED64(-1.4f)), -1);
	EXPECT_EQ(FIXED642INT(FLOAT2FIXED64(-2.4f)), -2);
	EXPECT_EQ(FIXED642INT(FLOAT2FIXED64(-10.4f)), -10);
	EXPECT_EQ(FIXED642INT(FLOAT2FIXED64(-1234.4f)), -1234);
	EXPECT_EQ(FIXED642INT(FLOAT2FIXED64(-32767.4f)), -32767);
}

TEST(FixedMath64, NegativeFloatConversionRoundDownToInt) {
	EXPECT_EQ(FIXED642INT(FLOAT2FIXED64(-1.6f)), -2);
	EXPECT_EQ(FIXED642INT(FLOAT2FIXED64(-2.6f)), -3);
	EXPECT_EQ(FIXED642INT(FLOAT2FIXED64(-10.6f)), -11);
	EXPECT_EQ(FIXED642INT(FLOAT2FIXED64(-1234.6f)), -1235);
	EXPECT_EQ(FIXED642INT(FLOAT2FIXED64(-32767.6f)), -32768);
}

// ----- double to fixed to double -----

TEST(FixedMath64, DoubleConversion) {
	EXPECT_DOUBLE_EQ(FIXED642DOUBLE(DOUBLE2FIXED64(0.0)), 0.0);
	EXPECT_DOUBLE_EQ(FIXED642DOUBLE(DOUBLE2FIXED64(1.0)), 1.0);
	EXPECT_DOUBLE_EQ(FIXED642DOUBLE(DOUBLE2FIXED64(1.25)), 1.25);
	EXPECT_DOUBLE_EQ(FIXED642DOUBLE(DOUBLE2FIXED64(1234.5)), 1234.5);
}

TEST(FixedMath64, NegativeDoubleConversion) {
	EXPECT_DOUBLE_EQ(FIXED642DOUBLE(DOUBLE2FIXED64(-0.0)), -0.0);
	EXPECT_DOUBLE_EQ(FIXED642DOUBLE(DOUBLE2FIXED64(-1.0)), -1.0);
	EXPECT_DOUBLE_EQ(FIXED642DOUBLE(DOUBLE2FIXED64(-1.25)), -1.25);
	EXPECT_DOUBLE_EQ(FIXED642DOUBLE(DOUBLE2FIXED64(-1234.5)), -1234.5);
}

// ------ float to fixed to float ------

TEST(FixedMath64, FloatConversion) {
	EXPECT_FLOAT_EQ(FIXED642FLOAT(FLOAT2FIXED64(0.0f)), 0.0f);
	EXPECT_FLOAT_EQ(FIXED642FLOAT(FLOAT2FIXED64(1.0f)), 1.0f);
	EXPECT_FLOAT_EQ(FIXED642FLOAT(FLOAT2FIXED64(1.25f)), 1.25f);
	EXPECT_FLOAT_EQ(FIXED642FLOAT(FLOAT2FIXED64(1234.5f)), 1234.5f);
}

TEST(FixedMath64, NegativeFloatConversion) {
	EXPECT_FLOAT_EQ(FIXED642FLOAT(FLOAT2FIXED64(-0.0f)), -0.0f);
	EXPECT_FLOAT_EQ(FIXED642FLOAT(FLOAT2FIXED64(-1.0f)), -1.0f);
	EXPECT_FLOAT_EQ(FIXED642FLOAT(FLOAT2FIXED64(-1.25f)), -1.25f);
	EXPECT_FLOAT_EQ(FIXED642FLOAT(FLOAT2FIXED64(-1234.5f)), -1234.5f);
}