1 /*
2 * Copyright (c) 2024 Embeint Inc
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6 #include <math.h>
7
8 #include <zephyr/ztest.h>
9 #include <zephyr/math/interpolation.h>
10
ZTEST(interpolation,test_interpolation_oob)11 ZTEST(interpolation, test_interpolation_oob)
12 {
13 int32_t x_axis[] = {10, 20, 30, 40, 50};
14 int32_t y_axis[] = {20, 22, 24, 28, 36};
15 uint8_t len = ARRAY_SIZE(x_axis);
16
17 zassert_equal(ARRAY_SIZE(x_axis), ARRAY_SIZE(y_axis));
18
19 zassert_equal(y_axis[0], linear_interpolate(x_axis, y_axis, len, INT32_MIN));
20 zassert_equal(y_axis[0], linear_interpolate(x_axis, y_axis, len, -1));
21 zassert_equal(y_axis[0], linear_interpolate(x_axis, y_axis, len, 0));
22 zassert_equal(y_axis[0], linear_interpolate(x_axis, y_axis, len, x_axis[0] - 1));
23
24 zassert_equal(y_axis[4], linear_interpolate(x_axis, y_axis, len, x_axis[4] + 1));
25 zassert_equal(y_axis[4], linear_interpolate(x_axis, y_axis, len, 100));
26 zassert_equal(y_axis[4], linear_interpolate(x_axis, y_axis, len, INT32_MAX));
27 }
28
ZTEST(interpolation,test_interpolation_on_boundary)29 ZTEST(interpolation, test_interpolation_on_boundary)
30 {
31 int32_t x_axis[] = {10, 20, 30, 40, 50};
32 int32_t y_axis[] = {20, 22, 24, 28, 36};
33 uint8_t len = ARRAY_SIZE(x_axis);
34
35 zassert_equal(ARRAY_SIZE(x_axis), ARRAY_SIZE(y_axis));
36
37 /* Looking up x_axis values should return corresponding y_axis */
38 for (int i = 0; i < ARRAY_SIZE(x_axis); i++) {
39 zassert_equal(y_axis[i], linear_interpolate(x_axis, y_axis, len, x_axis[i]));
40 }
41 }
42
ZTEST(interpolation,test_interpolation_rounding)43 ZTEST(interpolation, test_interpolation_rounding)
44 {
45 int32_t y_axis[] = {0, 1, 2};
46 int32_t x_axis[] = {0, 10, 20};
47 uint8_t len = ARRAY_SIZE(x_axis);
48
49 zassert_equal(ARRAY_SIZE(x_axis), ARRAY_SIZE(y_axis));
50
51 /* 0 to 4 -> 0 */
52 for (int i = 0; i < 5; i++) {
53 zassert_equal(0, linear_interpolate(x_axis, y_axis, len, i));
54 }
55 /* 5 to 14 -> 1 */
56 for (int i = 5; i < 15; i++) {
57 zassert_equal(1, linear_interpolate(x_axis, y_axis, len, i));
58 }
59 /* 15 to N -> 2 */
60 for (int i = 15; i <= 20; i++) {
61 zassert_equal(2, linear_interpolate(x_axis, y_axis, len, i));
62 }
63 }
64
ZTEST(interpolation,test_interpolation_simple)65 ZTEST(interpolation, test_interpolation_simple)
66 {
67 int32_t y_axis[] = {0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
68 int32_t x_axis[] = {2000, 2100, 2200, 2300, 2400, 2500, 2600, 2700, 2800, 2900, 3000};
69 uint8_t len = ARRAY_SIZE(x_axis);
70 int32_t expected;
71
72 zassert_equal(ARRAY_SIZE(x_axis), ARRAY_SIZE(y_axis));
73
74 /* y = (x - 2000) / 10 */
75 for (int i = x_axis[0]; i <= x_axis[1]; i++) {
76 expected = round((i - 2000.0) / 10.0);
77 zassert_equal(expected, linear_interpolate(x_axis, y_axis, len, i));
78 }
79 }
80
ZTEST(interpolation,test_interpolation_negative_y)81 ZTEST(interpolation, test_interpolation_negative_y)
82 {
83 int32_t y_axis[] = {-100, -90, -80, -70, -60, -50, -40, -30, -20, -10, 0};
84 int32_t x_axis[] = {2000, 2100, 2200, 2300, 2400, 2500, 2600, 2700, 2800, 2900, 3000};
85 uint8_t len = ARRAY_SIZE(x_axis);
86 int32_t expected;
87
88 zassert_equal(ARRAY_SIZE(x_axis), ARRAY_SIZE(y_axis));
89
90 /* y = ((x - 2000) / 10) - 100 */
91 for (int i = x_axis[0]; i <= x_axis[len - 1]; i++) {
92 expected = round((i - 2000.0) / 10.0 - 100.0);
93 zassert_equal(expected, linear_interpolate(x_axis, y_axis, len, i));
94 }
95 }
96
ZTEST(interpolation,test_interpolation_negative_x)97 ZTEST(interpolation, test_interpolation_negative_x)
98 {
99 int32_t y_axis[] = {0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
100 int32_t x_axis[] = {-3000, -2900, -2800, -2700, -2600, -2500,
101 -2400, -2300, -2200, -2100, -2000};
102 uint8_t len = ARRAY_SIZE(x_axis);
103 int32_t expected;
104
105 zassert_equal(ARRAY_SIZE(x_axis), ARRAY_SIZE(y_axis));
106
107 /* y = ((x + 3000) / 10) */
108 for (int i = x_axis[0]; i <= x_axis[len - 1]; i++) {
109 expected = round((i + 3000.0) / 10.0);
110 zassert_equal(expected, linear_interpolate(x_axis, y_axis, len, i));
111 }
112 }
113
ZTEST(interpolation,test_interpolation_negative_xy)114 ZTEST(interpolation, test_interpolation_negative_xy)
115 {
116 int32_t y_axis[] = {-100, -90, -80, -70, -60, -50, -40, -30, -20, -10, 0};
117 int32_t x_axis[] = {-3000, -2900, -2800, -2700, -2600, -2500,
118 -2400, -2300, -2200, -2100, -2000};
119 uint8_t len = ARRAY_SIZE(x_axis);
120 int32_t expected;
121
122 zassert_equal(ARRAY_SIZE(x_axis), ARRAY_SIZE(y_axis));
123
124 /* y = ((x + 3000) / 10) - 100 */
125 for (int i = x_axis[0]; i <= x_axis[len - 1]; i++) {
126 expected = round((i + 3000.0) / 10.0 - 100.0);
127 zassert_equal(expected, linear_interpolate(x_axis, y_axis, len, i));
128 }
129 }
130
ZTEST(interpolation,test_interpolation_piecewise)131 ZTEST(interpolation, test_interpolation_piecewise)
132 {
133 int32_t y_axis[] = {10, 30, 110, 40, 0};
134 int32_t x_axis[] = {100, 150, 200, 250, 300};
135 uint8_t len = ARRAY_SIZE(x_axis);
136 int32_t expected;
137
138 zassert_equal(ARRAY_SIZE(x_axis), ARRAY_SIZE(y_axis));
139
140 /* First line segment, y = 0.4x - 30 */
141 for (int i = x_axis[0]; i <= x_axis[1]; i++) {
142 expected = round(0.4 * i - 30.0);
143 zassert_equal(expected, linear_interpolate(x_axis, y_axis, len, i));
144 }
145
146 /* Second line segment, y = 1.6x - 210 */
147 for (int i = x_axis[1]; i <= x_axis[2]; i++) {
148 expected = round(1.6 * i - 210.0);
149 zassert_equal(expected, linear_interpolate(x_axis, y_axis, len, i));
150 }
151
152 /* Third line segment, y = 390 - 1.4x */
153 for (int i = x_axis[2]; i <= x_axis[3]; i++) {
154 expected = round(390.0 - 1.4 * i);
155 zassert_equal(expected, linear_interpolate(x_axis, y_axis, len, i));
156 }
157
158 /* Fourth line segment, y = 240 - 0.8x */
159 for (int i = x_axis[3]; i <= x_axis[4]; i++) {
160 expected = round(240.0 - 0.8 * i);
161 zassert_equal(expected, linear_interpolate(x_axis, y_axis, len, i));
162 }
163 }
164
165 ZTEST_SUITE(interpolation, NULL, NULL, NULL, NULL, NULL);
166