diff --git a/tests/lib/math/interpolation/CMakeLists.txt b/tests/lib/math/interpolation/CMakeLists.txt new file mode 100644 index 00000000000..d91c5db9db9 --- /dev/null +++ b/tests/lib/math/interpolation/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (c) 2024 Embeint Inc +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(interpolation) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/lib/math/interpolation/prj.conf b/tests/lib/math/interpolation/prj.conf new file mode 100644 index 00000000000..416dacd4aba --- /dev/null +++ b/tests/lib/math/interpolation/prj.conf @@ -0,0 +1,6 @@ +# Copyright (c) 2024 Embeint Inc +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_ZTEST=y +# roundf support on Xtensa +CONFIG_REQUIRES_FULL_LIBC=y diff --git a/tests/lib/math/interpolation/src/main.c b/tests/lib/math/interpolation/src/main.c new file mode 100644 index 00000000000..95753a1decf --- /dev/null +++ b/tests/lib/math/interpolation/src/main.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2024 Embeint Inc + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include + +ZTEST(interpolation, test_interpolation_oob) +{ + int32_t x_axis[] = {10, 20, 30, 40, 50}; + int32_t y_axis[] = {20, 22, 24, 28, 36}; + uint8_t len = ARRAY_SIZE(x_axis); + + zassert_equal(ARRAY_SIZE(x_axis), ARRAY_SIZE(y_axis)); + + zassert_equal(y_axis[0], linear_interpolate(x_axis, y_axis, len, INT32_MIN)); + zassert_equal(y_axis[0], linear_interpolate(x_axis, y_axis, len, -1)); + zassert_equal(y_axis[0], linear_interpolate(x_axis, y_axis, len, 0)); + zassert_equal(y_axis[0], linear_interpolate(x_axis, y_axis, len, x_axis[0] - 1)); + + zassert_equal(y_axis[4], linear_interpolate(x_axis, y_axis, len, x_axis[4] + 1)); + zassert_equal(y_axis[4], linear_interpolate(x_axis, y_axis, len, 100)); + zassert_equal(y_axis[4], linear_interpolate(x_axis, y_axis, len, INT32_MAX)); +} + +ZTEST(interpolation, test_interpolation_on_boundary) +{ + int32_t x_axis[] = {10, 20, 30, 40, 50}; + int32_t y_axis[] = {20, 22, 24, 28, 36}; + uint8_t len = ARRAY_SIZE(x_axis); + + zassert_equal(ARRAY_SIZE(x_axis), ARRAY_SIZE(y_axis)); + + /* Looking up x_axis values should return corresponding y_axis */ + for (int i = 0; i < ARRAY_SIZE(x_axis); i++) { + zassert_equal(y_axis[i], linear_interpolate(x_axis, y_axis, len, x_axis[i])); + } +} + +ZTEST(interpolation, test_interpolation_rounding) +{ + int32_t y_axis[] = {0, 1, 2}; + int32_t x_axis[] = {0, 10, 20}; + uint8_t len = ARRAY_SIZE(x_axis); + + zassert_equal(ARRAY_SIZE(x_axis), ARRAY_SIZE(y_axis)); + + /* 0 to 4 -> 0 */ + for (int i = 0; i < 5; i++) { + zassert_equal(0, linear_interpolate(x_axis, y_axis, len, i)); + } + /* 5 to 14 -> 1 */ + for (int i = 5; i < 15; i++) { + zassert_equal(1, linear_interpolate(x_axis, y_axis, len, i)); + } + /* 15 to N -> 2 */ + for (int i = 15; i <= 20; i++) { + zassert_equal(2, linear_interpolate(x_axis, y_axis, len, i)); + } +} + +ZTEST(interpolation, test_interpolation_simple) +{ + int32_t y_axis[] = {0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}; + int32_t x_axis[] = {2000, 2100, 2200, 2300, 2400, 2500, 2600, 2700, 2800, 2900, 3000}; + uint8_t len = ARRAY_SIZE(x_axis); + int32_t expected; + + zassert_equal(ARRAY_SIZE(x_axis), ARRAY_SIZE(y_axis)); + + /* y = (x - 2000) / 10 */ + for (int i = x_axis[0]; i <= x_axis[1]; i++) { + expected = round((i - 2000.0) / 10.0); + zassert_equal(expected, linear_interpolate(x_axis, y_axis, len, i)); + } +} + +ZTEST(interpolation, test_interpolation_negative_y) +{ + int32_t y_axis[] = {-100, -90, -80, -70, -60, -50, -40, -30, -20, -10, 0}; + int32_t x_axis[] = {2000, 2100, 2200, 2300, 2400, 2500, 2600, 2700, 2800, 2900, 3000}; + uint8_t len = ARRAY_SIZE(x_axis); + int32_t expected; + + zassert_equal(ARRAY_SIZE(x_axis), ARRAY_SIZE(y_axis)); + + /* y = ((x - 2000) / 10) - 100 */ + for (int i = x_axis[0]; i <= x_axis[len - 1]; i++) { + expected = round((i - 2000.0) / 10.0 - 100.0); + zassert_equal(expected, linear_interpolate(x_axis, y_axis, len, i)); + } +} + +ZTEST(interpolation, test_interpolation_negative_x) +{ + int32_t y_axis[] = {0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}; + int32_t x_axis[] = {-3000, -2900, -2800, -2700, -2600, -2500, + -2400, -2300, -2200, -2100, -2000}; + uint8_t len = ARRAY_SIZE(x_axis); + int32_t expected; + + zassert_equal(ARRAY_SIZE(x_axis), ARRAY_SIZE(y_axis)); + + /* y = ((x + 3000) / 10) */ + for (int i = x_axis[0]; i <= x_axis[len - 1]; i++) { + expected = round((i + 3000.0) / 10.0); + zassert_equal(expected, linear_interpolate(x_axis, y_axis, len, i)); + } +} + +ZTEST(interpolation, test_interpolation_negative_xy) +{ + int32_t y_axis[] = {-100, -90, -80, -70, -60, -50, -40, -30, -20, -10, 0}; + int32_t x_axis[] = {-3000, -2900, -2800, -2700, -2600, -2500, + -2400, -2300, -2200, -2100, -2000}; + uint8_t len = ARRAY_SIZE(x_axis); + int32_t expected; + + zassert_equal(ARRAY_SIZE(x_axis), ARRAY_SIZE(y_axis)); + + /* y = ((x + 3000) / 10) - 100 */ + for (int i = x_axis[0]; i <= x_axis[len - 1]; i++) { + expected = round((i + 3000.0) / 10.0 - 100.0); + zassert_equal(expected, linear_interpolate(x_axis, y_axis, len, i)); + } +} + +ZTEST(interpolation, test_interpolation_piecewise) +{ + int32_t y_axis[] = {10, 30, 110, 40, 0}; + int32_t x_axis[] = {100, 150, 200, 250, 300}; + uint8_t len = ARRAY_SIZE(x_axis); + int32_t expected; + + zassert_equal(ARRAY_SIZE(x_axis), ARRAY_SIZE(y_axis)); + + /* First line segment, y = 0.4x - 30 */ + for (int i = x_axis[0]; i <= x_axis[1]; i++) { + expected = round(0.4 * i - 30.0); + zassert_equal(expected, linear_interpolate(x_axis, y_axis, len, i)); + } + + /* Second line segment, y = 1.6x - 210 */ + for (int i = x_axis[1]; i <= x_axis[2]; i++) { + expected = round(1.6 * i - 210.0); + zassert_equal(expected, linear_interpolate(x_axis, y_axis, len, i)); + } + + /* Third line segment, y = 390 - 1.4x */ + for (int i = x_axis[2]; i <= x_axis[3]; i++) { + expected = round(390.0 - 1.4 * i); + zassert_equal(expected, linear_interpolate(x_axis, y_axis, len, i)); + } + + /* Fourth line segment, y = 240 - 0.8x */ + for (int i = x_axis[3]; i <= x_axis[4]; i++) { + expected = round(240.0 - 0.8 * i); + zassert_equal(expected, linear_interpolate(x_axis, y_axis, len, i)); + } +} + +ZTEST_SUITE(interpolation, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/lib/math/interpolation/testcase.yaml b/tests/lib/math/interpolation/testcase.yaml new file mode 100644 index 00000000000..fd3eafb51df --- /dev/null +++ b/tests/lib/math/interpolation/testcase.yaml @@ -0,0 +1,7 @@ +# Copyright (c) 2024 Embeint Inc +# SPDX-License-Identifier: Apache-2.0 + +tests: + math.interpolation: + integration_platforms: + - native_sim