From 35eb7753d29a9ad14b145a09c057a88131d6ede0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ba=C5=99inka?= Date: Thu, 29 Apr 2021 08:40:06 +0200 Subject: [PATCH] New unittests (#28) Refactor unittests --- .gitignore | 4 + CMakeLists.txt | 22 ++- benchmarks/Makefile | 5 +- libfixmath/fix16.h | 1 + {contrib => libfixmath}/fix16_fft.c | 2 +- libfixmath/libfixmath.cmake | 3 + tests/run_tests | 2 + tests/tests.c | 51 ++++++ tests/tests.cmake | 44 +++++ tests/tests.h | 80 +++++++++ tests/tests_basic.c | 246 ++++++++++++++++++++++++++++ tests/tests_basic.h | 10 ++ tests/tests_lerp.c | 33 ++++ tests/tests_lerp.h | 6 + tests/tests_sqrt.c | 37 +++++ tests/tests_sqrt.h | 6 + unittests/Makefile | 2 +- unittests/fix16_exp_unittests.c | 2 +- unittests/fix16_unittests.c | 4 +- 19 files changed, 545 insertions(+), 15 deletions(-) rename {contrib => libfixmath}/fix16_fft.c (99%) create mode 100644 libfixmath/libfixmath.cmake create mode 100755 tests/run_tests create mode 100644 tests/tests.c create mode 100644 tests/tests.cmake create mode 100644 tests/tests.h create mode 100644 tests/tests_basic.c create mode 100644 tests/tests_basic.h create mode 100644 tests/tests_lerp.c create mode 100644 tests/tests_lerp.h create mode 100644 tests/tests_sqrt.c create mode 100644 tests/tests_sqrt.h diff --git a/.gitignore b/.gitignore index a6cb559..59904ca 100644 --- a/.gitignore +++ b/.gitignore @@ -158,3 +158,7 @@ compile_commands.json *creator.user* *_qmlcache.qrc + +benchmarks/testcases.c + +*.elf diff --git a/CMakeLists.txt b/CMakeLists.txt index 75b7322..204ef3b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,25 +4,29 @@ project(libfixmath LANGUAGES CXX C) set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) -set(CMAKE_C_FLAGS "-Wall -pedantic -Wextra") +set(CMAKE_C_FLAGS "-Wall -pedantic -Wextra -Werror=return-type") -set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_FLAGS "-Wall -pedantic -Wextra") +set(CMAKE_CXX_FLAGS "-Wall -pedantic -Wextra -Werror=return-type") + +include(libfixmath/libfixmath.cmake) +include(tests/tests.cmake) -file(GLOB libfixmath-srcs libfixmath/*.h libfixmath/*.hpp libfixmath/*.c) -file(GLOB contrib-srcs contrib/*.c) file(GLOB fixsingen-srcs fixsingen/*.c) file(GLOB fixtest-srcs fixtest/*.c fixtest/*.h) - -add_library(libfixmath STATIC ${libfixmath-srcs} ${contrib-srcs}) -target_include_directories(libfixmath PRIVATE ${CMAKE_SOURCE_DIR}) +file(GLOB unittests-srcs unittests/*.c unittests/*.h) add_executable(fixtest ${fixtest-srcs}) target_link_libraries(fixtest PRIVATE libfixmath m) target_include_directories(fixtest PRIVATE ${CMAKE_SOURCE_DIR}) - add_executable(fixsingen ${fixsingen-srcs}) target_link_libraries(fixsingen PRIVATE libfixmath m) target_include_directories(fixsingen PRIVATE ${CMAKE_SOURCE_DIR}) + +add_executable(unittests ${unittests-srcs}) +target_link_libraries(unittests PRIVATE libfixmath m) +target_include_directories(unittests PRIVATE ${CMAKE_SOURCE_DIR}) + + diff --git a/benchmarks/Makefile b/benchmarks/Makefile index efd450e..6331596 100644 --- a/benchmarks/Makefile +++ b/benchmarks/Makefile @@ -6,6 +6,9 @@ FILES = benchmark.c ../libfixmath/fix16.c ../libfixmath/fix16_sqrt.c ../libfixma CFLAGS = -DFIXMATH_NO_OVERFLOW -DFIXMATH_NO_ROUNDING -ffast-math -I../libfixmath +.PHONY clean: + rm -f *.elf + testcases.c: generate_testcases.py python $< @@ -23,7 +26,7 @@ run-benchmark-arm: benchmark-arm.elf benchmark-avr.elf: $(FILES) interface-avr.c testcases.c avr-gcc -Wall -mmcu=atmega128 $(CFLAGS) \ - -Wall -O2 -DFIXMATH_OPTIMIZE_8BIT \ + -O2 -DFIXMATH_OPTIMIZE_8BIT \ -o $@ -I .. $(FILES) interface-avr.c run-benchmark-avr: benchmark-avr.elf diff --git a/libfixmath/fix16.h b/libfixmath/fix16.h index eeb0b99..79c0090 100644 --- a/libfixmath/fix16.h +++ b/libfixmath/fix16.h @@ -38,6 +38,7 @@ static const fix16_t fix16_overflow = 0x80000000; /*!< the value used to indicat static const fix16_t fix16_pi = 205887; /*!< fix16_t value of pi */ static const fix16_t fix16_e = 178145; /*!< fix16_t value of e */ static const fix16_t fix16_one = 0x00010000; /*!< fix16_t value of 1 */ +static const fix16_t fix16_eps = 1; /*!< fix16_t epsilon */ /* Conversion functions between fix16_t and float/integer. * These are inlined to allow compiler to optimize away constant numbers diff --git a/contrib/fix16_fft.c b/libfixmath/fix16_fft.c similarity index 99% rename from contrib/fix16_fft.c rename to libfixmath/fix16_fft.c index 8259083..1a5aeb3 100644 --- a/contrib/fix16_fft.c +++ b/libfixmath/fix16_fft.c @@ -9,7 +9,7 @@ */ #include -#include +#include "fix16.h" // You can change the input datatype and intermediate scaling here. // By default, the output is divided by the transform length to get a normalized FFT. diff --git a/libfixmath/libfixmath.cmake b/libfixmath/libfixmath.cmake new file mode 100644 index 0000000..e4e7018 --- /dev/null +++ b/libfixmath/libfixmath.cmake @@ -0,0 +1,3 @@ +file(GLOB libfixmath-srcs libfixmath/*.h libfixmath/*.hpp libfixmath/*.c) + +add_library(libfixmath STATIC ${libfixmath-srcs}) diff --git a/tests/run_tests b/tests/run_tests new file mode 100755 index 0000000..bca1d68 --- /dev/null +++ b/tests/run_tests @@ -0,0 +1,2 @@ +#!/bin/env bash +for i in $(ls -1 tests_*); do ./$i; done diff --git a/tests/tests.c b/tests/tests.c new file mode 100644 index 0000000..cef9710 --- /dev/null +++ b/tests/tests.c @@ -0,0 +1,51 @@ +#include "tests.h" +#include "tests_basic.h" +#include "tests_lerp.h" +#include "tests_sqrt.h" +#include + +const fix16_t testcases[] = { + // Small numbers + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, + + // Integer numbers + 0x10000, -0x10000, 0x20000, -0x20000, 0x30000, -0x30000, 0x40000, -0x40000, + 0x50000, -0x50000, 0x60000, -0x60000, + + // Fractions (1/2, 1/4, 1/8) + 0x8000, -0x8000, 0x4000, -0x4000, 0x2000, -0x2000, + + // Problematic carry + 0xFFFF, -0xFFFF, 0x1FFFF, -0x1FFFF, 0x3FFFF, -0x3FFFF, + + // Smallest and largest values + 0x7FFFFFFF, 0x80000000, + + // Large random numbers + 831858892, 574794913, 2147272293, -469161054, -961611615, 1841960234, + 1992698389, 520485404, 560523116, -2094993050, -876897543, -67813629, + 2146227091, 509861939, -1073573657, + + // Small random numbers + -14985, 30520, -83587, 41129, 42137, 58537, -2259, 84142, -28283, 90914, + 19865, 33191, 81844, -66273, -63215, -44459, -11326, 84295, 47515, -39324, + + // Tiny random numbers + -171, -359, 491, 844, 158, -413, -422, -737, -575, -330, -376, 435, -311, + 116, 715, -1024, -487, 59, 724, 993 +}; + +unsigned stack_depth = 0; + +int main() +{ + printf("\033[1;34m\nVARIANT: \033[39m"STR2(PREFIX)"\033[0m\n"); + TEST(test_abs()); + TEST(test_add()); + TEST(test_mul()); + TEST(test_div()); + TEST(test_sub()); + TEST(test_sqrt()); + TEST(test_lerp()); + return 0; +} diff --git a/tests/tests.cmake b/tests/tests.cmake new file mode 100644 index 0000000..56aefe3 --- /dev/null +++ b/tests/tests.cmake @@ -0,0 +1,44 @@ +file(GLOB tests-srcs tests/*.c tests/*.h) + +set(ro64 PREFIX=ro64) +set(no64 PREFIX=no64 FIXMATH_NO_ROUNDING) +set(rn64 PREFIX=rn64 FIXMATH_NO_OVERFLOW) +set(nn64 PREFIX=nn64 FIXMATH_NO_ROUNDING FIXMATH_NO_OVERFLOW) +set(ro32 PREFIX=ro32 FIXMATH_NO_64BIT) +set(no32 PREFIX=no32 FIXMATH_NO_ROUNDING FIXMATH_NO_64BIT) +set(rn32 PREFIX=rn32 FIXMATH_NO_OVERFLOW FIXMATH_NO_64BIT) +set(nn32 PREFIX=nn32 FIXMATH_NO_OVERFLOW FIXMATH_NO_ROUNDING FIXMATH_NO_64BIT) +set(ro08 PREFIX=ro08 FIXMATH_OPTIMIZE_8BIT) +set(no08 PREFIX=no08 FIXMATH_NO_ROUNDING FIXMATH_OPTIMIZE_8BIT) +set(rn08 PREFIX=rn08 FIXMATH_NO_OVERFLOW FIXMATH_OPTIMIZE_8BIT) +set(nn08 PREFIX=nn08 FIXMATH_NO_OVERFLOW FIXMATH_NO_ROUNDING FIXMATH_OPTIMIZE_8BIT) + +configure_file(tests/run_tests ${CMAKE_BINARY_DIR}/run_tests COPYONLY) + +add_custom_target(tests) + +function(create_variant name defs) + add_library(libfixmath_${name} STATIC ${libfixmath-srcs}) + target_compile_definitions(libfixmath_${name} PRIVATE ${defs}) + add_executable(tests_${name} ${tests-srcs}) + target_link_libraries(tests_${name} PRIVATE libfixmath_${name} m) + target_include_directories(tests_${name} PRIVATE ${CMAKE_SOURCE_DIR}) + target_compile_definitions(tests_${name} PRIVATE ${defs}) + add_dependencies(tests tests_${name}) +endfunction() + + +create_variant("ro64" "${ro64}") +create_variant("no64" "${no64}") +create_variant("rn64" "${rn64}") +create_variant("nn64" "${nn64}") +create_variant("ro32" "${ro32}") +create_variant("no32" "${no32}") +create_variant("rn32" "${rn32}") +create_variant("nn32" "${nn32}") +create_variant("ro08" "${ro08}") +create_variant("no08" "${no08}") +create_variant("rn08" "${rn08}") +create_variant("nn08" "${nn08}") + + diff --git a/tests/tests.h b/tests/tests.h new file mode 100644 index 0000000..6be58db --- /dev/null +++ b/tests/tests.h @@ -0,0 +1,80 @@ +#ifndef TESTS_H +#define TESTS_H + +#include +#include +#include +#include + +extern unsigned stack_depth; + +#define delta(a, b) (((a) >= (b)) ? (a) - (b) : (b) - (a)) + +#define COMMENT(x) printf("\n----" x "----\n"); +#define STR(x) #x +#define STR2(x) STR(x) +#define TEST(x) \ + do \ + { \ + ++stack_depth; \ + if ((x)) \ + { \ + fflush(stdout); \ + fflush(stderr); \ + fprintf(stdout, \ + "\033[31;1m FAILED:\033[22;39m%*s" #x \ + " \033[0mat: " __FILE__ ":" STR2(__LINE__) " \n", \ + stack_depth, ""); \ + --stack_depth; \ + return 1; \ + } \ + else \ + { \ + fflush(stdout); \ + fflush(stderr); \ + printf("\033[32;1m OK:\033[22;39m%*s" #x "\n\033[0m", \ + stack_depth, ""); \ + } \ + --stack_depth; \ + } while (0) + +#define ASSERT_NEAR_DOUBLE(a, b, eps, ...) \ + do \ + { \ + if ((delta((a), (b)) >= (eps))) \ + { \ + fflush(stdout); \ + fflush(stderr); \ + fprintf(stdout, \ + "\033[31;1m FAILED:\033[22;39m%*sASSERT_NEAR a: %f, b: " \ + "%f, eps: %f\033[0m at: %s(), " __FILE__ \ + ":" STR2(__LINE__) "\n", \ + stack_depth, "", (a), (b), (eps), __func__); \ + fprintf(stdout, " %*s", stack_depth, ""); \ + fprintf(stdout, __VA_ARGS__); \ + return 1; \ + } \ + } while (0) + +#define ASSERT_EQ_INT(a, b) \ + do \ + { \ + if ((a) != (b)) \ + { \ + fflush(stdout); \ + fflush(stderr); \ + fprintf(stdout, \ + "\033[31;1m FAILED:\033[22;39m%*sASSERT_EQ a: %i, b: " \ + "%i\033[0m at: %s(), " __FILE__ ":" STR2(__LINE__) "\n", \ + stack_depth, "", (a), (b), __func__); \ + return 1; \ + } \ + } while (0) + +extern const fix16_t testcases[102]; + +#define TESTCASES_COUNT (sizeof(testcases) / sizeof(testcases[0])) + +#define delta(a, b) (((a) >= (b)) ? (a) - (b) : (b) - (a)) + +#endif // TESTS_H diff --git a/tests/tests_basic.c b/tests/tests_basic.c new file mode 100644 index 0000000..6037ae2 --- /dev/null +++ b/tests/tests_basic.c @@ -0,0 +1,246 @@ +#include "tests_basic.h" +#include "tests.h" + +int test_abs_short(void) +{ + for (unsigned i = 0; i < TESTCASES_COUNT; ++i) + { + fix16_t a = testcases[i]; + double fa = fix16_to_dbl(a); + fix16_t result = fix16_abs(a); + double fresult = fabs(fa); + double min = fix16_to_dbl(fix16_minimum); + if (fa <= min) + { +#ifndef FIXMATH_NO_OVERFLOW + ASSERT_EQ_INT(result, fix16_overflow); +#endif + } + else + { + ASSERT_NEAR_DOUBLE(fresult, fix16_to_dbl(result), + fix16_to_dbl(fix16_eps), "in: %f", fa); + } + } + return 0; +} + +int test_abs(void) +{ + TEST(test_abs_short()); + return 0; +} + +int test_add_short(void) +{ + for (unsigned i = 0; i < TESTCASES_COUNT; ++i) + { + for (unsigned j = 0; j < TESTCASES_COUNT; ++j) + { + fix16_t a = testcases[i]; + fix16_t b = testcases[j]; + fix16_t result = fix16_add(a, b); + + double fa = fix16_to_dbl(a); + double fb = fix16_to_dbl(b); + double fresult = fa + fb; + + double max = fix16_to_dbl(fix16_maximum); + double min = fix16_to_dbl(fix16_minimum); + if ((fa + fb > max) || (fa + fb < min)) + { +#ifndef FIXMATH_NO_OVERFLOW + ASSERT_EQ_INT(result, fix16_overflow); +#endif + } + else + { + ASSERT_NEAR_DOUBLE(fresult, fix16_to_dbl(result), + fix16_to_dbl(fix16_eps), "%f + %f", fa, fb); + } + } + } + return 0; +} + +int test_add(void) +{ + TEST(test_add_short()); + return 0; +} + +int test_mul_specific(void) +{ + ASSERT_EQ_INT(fix16_mul(fix16_from_int(5), fix16_from_int(5)), + fix16_from_int(25)); + ASSERT_EQ_INT(fix16_mul(fix16_from_int(-5), fix16_from_int(5)), + fix16_from_int(-25)); + ASSERT_EQ_INT(fix16_mul(fix16_from_int(-5), fix16_from_int(-5)), + fix16_from_int(25)); + ASSERT_EQ_INT(fix16_mul(fix16_from_int(5), fix16_from_int(-5)), + fix16_from_int(-25)); + + ASSERT_EQ_INT(fix16_mul(0, 10), 0); + ASSERT_EQ_INT(fix16_mul(2, 0x8000), 1); + ASSERT_EQ_INT(fix16_mul(-2, 0x8000), -1); +#ifndef FIXMATH_NO_ROUNDING + ASSERT_EQ_INT(fix16_mul(3, 0x8000), 2); + ASSERT_EQ_INT(fix16_mul(2, 0x7FFF), 1); + ASSERT_EQ_INT(fix16_mul(-2, 0x8001), -1); + ASSERT_EQ_INT(fix16_mul(-3, 0x8000), -2); + ASSERT_EQ_INT(fix16_mul(-2, 0x7FFF), -1); + ASSERT_EQ_INT(fix16_mul(2, 0x8001), 1); +#endif + return 0; +} + +int test_mul_short() +{ + for (unsigned i = 0; i < TESTCASES_COUNT; ++i) + { + for (unsigned j = 0; j < TESTCASES_COUNT; ++j) + { + fix16_t a = testcases[i]; + fix16_t b = testcases[j]; + fix16_t result = fix16_mul(a, b); + + double fa = fix16_to_dbl(a); + double fb = fix16_to_dbl(b); + double fresult = fa * fb; + + double max = fix16_to_dbl(fix16_maximum); + double min = fix16_to_dbl(fix16_minimum); + + if (fa * fb > max || fa * fb < min) + { +#ifndef FIXMATH_NO_OVERFLOW + ASSERT_EQ_INT(result, fix16_overflow); +#endif + } + else + { + ASSERT_NEAR_DOUBLE(fresult, fix16_to_dbl(result), + fix16_to_dbl(fix16_eps), "%f * %f", fa, fb); + } + } + } + return 0; +} + +int test_mul(void) +{ + TEST(test_mul_specific()); + TEST(test_mul_short()); + return 0; +} + +int test_div_specific() +{ + ASSERT_EQ_INT(fix16_div(fix16_from_int(15), fix16_from_int(5)), + fix16_from_int(3)); + ASSERT_EQ_INT(fix16_div(fix16_from_int(-15), fix16_from_int(5)), + fix16_from_int(-3)); + ASSERT_EQ_INT(fix16_div(fix16_from_int(-15), fix16_from_int(-5)), + fix16_from_int(3)); + ASSERT_EQ_INT(fix16_div(fix16_from_int(15), fix16_from_int(-5)), + fix16_from_int(-3)); + +#ifndef FIXMATH_NO_ROUNDING + ASSERT_EQ_INT(fix16_div(0, 10), 0); + ASSERT_EQ_INT(fix16_div(1, fix16_from_int(2)), 1); + ASSERT_EQ_INT(fix16_div(-1, fix16_from_int(2)), -1); + ASSERT_EQ_INT(fix16_div(1, fix16_from_int(-2)), -1); + ASSERT_EQ_INT(fix16_div(-1, fix16_from_int(-2)), 1); + ASSERT_EQ_INT(fix16_div(3, fix16_from_int(2)), 2); + ASSERT_EQ_INT(fix16_div(-3, fix16_from_int(2)), -2); + ASSERT_EQ_INT(fix16_div(3, fix16_from_int(-2)), -2); + ASSERT_EQ_INT(fix16_div(-3, fix16_from_int(-2)), 2); + ASSERT_EQ_INT(fix16_div(2, 0x7FFF), 4); + ASSERT_EQ_INT(fix16_div(-2, 0x7FFF), -4); + ASSERT_EQ_INT(fix16_div(2, 0x8001), 4); + ASSERT_EQ_INT(fix16_div(-2, 0x8001), -4); +#endif + + return 0; +} + +int test_div_short() +{ + for (unsigned i = 0; i < TESTCASES_COUNT; ++i) + { + for (unsigned j = 0; j < TESTCASES_COUNT; ++j) + { + fix16_t a = testcases[i]; + fix16_t b = testcases[j]; + // We don't require a solution for /0 :) + if (b == 0) + continue; + fix16_t result = fix16_div(a, b); + + double fa = fix16_to_dbl(a); + double fb = fix16_to_dbl(b); + double fresult = fa / fb; + + double max = fix16_to_dbl(fix16_maximum); + double min = fix16_to_dbl(fix16_minimum); + + if ((fa / fb) > max || (fa / fb) < min) + { +#ifndef FIXMATH_NO_OVERFLOW + ASSERT_EQ_INT(result, fix16_overflow); +#endif + } + else + { + ASSERT_NEAR_DOUBLE(fresult, fix16_to_dbl(result), + fix16_to_dbl(fix16_eps), "%i / %i \n", a, b); + } + } + } + return 0; +} + +int test_div(void) +{ + TEST(test_div_specific()); + TEST(test_div_short()); + return 0; +} + +int test_sub_short() +{ + for (unsigned i = 0; i < TESTCASES_COUNT; ++i) + { + for (unsigned j = 0; j < TESTCASES_COUNT; ++j) + { + fix16_t a = testcases[i]; + fix16_t b = testcases[j]; + fix16_t result = fix16_sub(a, b); + + double fa = fix16_to_dbl(a); + double fb = fix16_to_dbl(b); + double fresult = fa - fb; + + double max = fix16_to_dbl(fix16_maximum); + double min = fix16_to_dbl(fix16_minimum); + if ((fa - fb > max) || (fa - fb < min)) + { +#ifndef FIXMATH_NO_OVERFLOW + ASSERT_EQ_INT(result, fix16_overflow); +#endif + } + else + { + ASSERT_NEAR_DOUBLE(fresult, fix16_to_dbl(result), + fix16_to_dbl(fix16_eps), "%f - %f", fa, fb); + } + } + } + return 0; +} + +int test_sub() +{ + TEST(test_sub_short()); + return 0; +} diff --git a/tests/tests_basic.h b/tests/tests_basic.h new file mode 100644 index 0000000..a51f283 --- /dev/null +++ b/tests/tests_basic.h @@ -0,0 +1,10 @@ +#ifndef TESTS_BASIC_H +#define TESTS_BASIC_H + +int test_abs(void); +int test_add(void); +int test_mul(void); +int test_div(void); +int test_sub(); + +#endif // TESTS_BASIC_H diff --git a/tests/tests_lerp.c b/tests/tests_lerp.c new file mode 100644 index 0000000..b3a04f6 --- /dev/null +++ b/tests/tests_lerp.c @@ -0,0 +1,33 @@ +#include "tests_lerp.h" +#include "tests.h" + +int test_lerp() +{ + ASSERT_EQ_INT(fix16_lerp8(0, 2, 0), 0); + ASSERT_EQ_INT(fix16_lerp8(0, 2, 127), 0); + ASSERT_EQ_INT(fix16_lerp8(0, 2, 128), 1); + ASSERT_EQ_INT(fix16_lerp8(0, 2, 255), 1); + ASSERT_EQ_INT(fix16_lerp8(fix16_minimum, fix16_maximum, 0), fix16_minimum); + ASSERT_EQ_INT(fix16_lerp8(fix16_minimum, fix16_maximum, 255), + (fix16_maximum - (1 << 24))); + ASSERT_EQ_INT(fix16_lerp8(-fix16_maximum, fix16_maximum, 128), 0); + + ASSERT_EQ_INT(fix16_lerp16(0, 2, 0), 0); + ASSERT_EQ_INT(fix16_lerp16(0, 2, 0x7fff), 0); + ASSERT_EQ_INT(fix16_lerp16(0, 2, 0x8000), 1); + ASSERT_EQ_INT(fix16_lerp16(0, 2, 0xffff), 1); + ASSERT_EQ_INT(fix16_lerp16(fix16_minimum, fix16_maximum, 0), fix16_minimum); + ASSERT_EQ_INT(fix16_lerp16(fix16_minimum, fix16_maximum, 0xffff), + (fix16_maximum - (1 << 16))); + ASSERT_EQ_INT(fix16_lerp16(-fix16_maximum, fix16_maximum, 0x8000), 0); + + ASSERT_EQ_INT(fix16_lerp32(0, 2, 0), 0); + ASSERT_EQ_INT(fix16_lerp32(0, 2, 0x7fffffff), 0); + ASSERT_EQ_INT(fix16_lerp32(0, 2, 0x80000000), 1); + ASSERT_EQ_INT(fix16_lerp32(0, 2, 0xffffffff), 1); + ASSERT_EQ_INT(fix16_lerp32(fix16_minimum, fix16_maximum, 0), fix16_minimum); + ASSERT_EQ_INT(fix16_lerp32(fix16_minimum, fix16_maximum, 0xffffffff), + (fix16_maximum - 1)); + ASSERT_EQ_INT(fix16_lerp32(-fix16_maximum, fix16_maximum, 0x80000000), 0); + return 0; +} diff --git a/tests/tests_lerp.h b/tests/tests_lerp.h new file mode 100644 index 0000000..ab261dd --- /dev/null +++ b/tests/tests_lerp.h @@ -0,0 +1,6 @@ +#ifndef TESTS_LERP_H +#define TESTS_LERP_H + +int test_lerp(); + +#endif // TESTS_LERP_H diff --git a/tests/tests_sqrt.c b/tests/tests_sqrt.c new file mode 100644 index 0000000..8faf016 --- /dev/null +++ b/tests/tests_sqrt.c @@ -0,0 +1,37 @@ +#include "tests_sqrt.h" +#include "tests.h" + +int test_sqrt_specific() +{ + ASSERT_EQ_INT(fix16_sqrt(fix16_from_int(16)), fix16_from_int(4)); + ASSERT_EQ_INT(fix16_sqrt(fix16_from_int(100)), fix16_from_int(10)); + ASSERT_EQ_INT(fix16_sqrt(fix16_from_int(1)), fix16_from_int(1)); +#ifndef FIXMATH_NO_ROUNDING + ASSERT_EQ_INT(fix16_sqrt(214748302), 3751499); + ASSERT_EQ_INT(fix16_sqrt(214748303), 3751499); + ASSERT_EQ_INT(fix16_sqrt(214748359), 3751499); + ASSERT_EQ_INT(fix16_sqrt(214748360), 3751500); +#endif + return 0; +} + +int test_sqrt_short() +{ + for (unsigned i = 0; i < TESTCASES_COUNT; ++i) + { + fix16_t a = testcases[i]; + double fa = fix16_to_dbl(a); + fix16_t result = fix16_sqrt(a); + double fresult = sqrt(fa); + ASSERT_NEAR_DOUBLE(fresult, fix16_to_dbl(result), fix16_to_dbl(1), + "in: %f", fa); + } + return 0; +} + +int test_sqrt() +{ + TEST(test_sqrt_specific()); + TEST(test_sqrt_short()); + return 0; +} diff --git a/tests/tests_sqrt.h b/tests/tests_sqrt.h new file mode 100644 index 0000000..d0e108d --- /dev/null +++ b/tests/tests_sqrt.h @@ -0,0 +1,6 @@ +#ifndef TESTS_SQRT_H +#define TESTS_SQRT_H + +int test_sqrt(); + +#endif // TESTS_SQRT_H diff --git a/unittests/Makefile b/unittests/Makefile index 78433fe..612be42 100644 --- a/unittests/Makefile +++ b/unittests/Makefile @@ -2,7 +2,7 @@ CC = gcc # Basic CFLAGS for debugging -CFLAGS = -g -O0 -I../libfixmath -Wall -Wextra -Werror +CFLAGS = -g -O0 -I../libfixmath -I.. -Wall -Wextra -Werror # The files required for tests FIX16_SRC = ../libfixmath/fix16.c ../libfixmath/fix16_sqrt.c ../libfixmath/fix16_str.c \ diff --git a/unittests/fix16_exp_unittests.c b/unittests/fix16_exp_unittests.c index afb6706..9fc0617 100644 --- a/unittests/fix16_exp_unittests.c +++ b/unittests/fix16_exp_unittests.c @@ -1,4 +1,4 @@ -#include +#include #include #include #include diff --git a/unittests/fix16_unittests.c b/unittests/fix16_unittests.c index 51d8f61..436c979 100644 --- a/unittests/fix16_unittests.c +++ b/unittests/fix16_unittests.c @@ -1,8 +1,8 @@ -#include +#include #include #include #include -#include "int64.h" +#include "libfixmath/int64.h" #include "unittests.h" const fix16_t testcases[] = {