1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Kunit tests for IIO rescale conversions |
4 | * |
5 | * Copyright (c) 2021 Liam Beguin <liambeguin@gmail.com> |
6 | */ |
7 | |
8 | #include <linux/gcd.h> |
9 | #include <linux/overflow.h> |
10 | |
11 | #include <linux/iio/afe/rescale.h> |
12 | #include <linux/iio/iio.h> |
13 | |
14 | #include <kunit/test.h> |
15 | |
16 | struct rescale_tc_data { |
17 | const char *name; |
18 | |
19 | const s32 numerator; |
20 | const s32 denominator; |
21 | const s32 offset; |
22 | |
23 | const int schan_val; |
24 | const int schan_val2; |
25 | const int schan_off; |
26 | const int schan_scale_type; |
27 | |
28 | const char *expected; |
29 | const char *expected_off; |
30 | }; |
31 | |
32 | static const struct rescale_tc_data scale_cases[] = { |
33 | /* |
34 | * Typical use cases |
35 | */ |
36 | { |
37 | .name = "typical IIO_VAL_INT, positive" , |
38 | .numerator = 1000000, |
39 | .denominator = 8060, |
40 | .schan_scale_type = IIO_VAL_INT, |
41 | .schan_val = 42, |
42 | .expected = "5210.918114143" , |
43 | }, |
44 | { |
45 | .name = "typical IIO_VAL_INT, negative" , |
46 | .numerator = -1000000, |
47 | .denominator = 8060, |
48 | .schan_scale_type = IIO_VAL_INT, |
49 | .schan_val = 42, |
50 | .expected = "-5210.918114143" , |
51 | }, |
52 | { |
53 | .name = "typical IIO_VAL_FRACTIONAL, positive" , |
54 | .numerator = 1000000, |
55 | .denominator = 8060, |
56 | .schan_scale_type = IIO_VAL_FRACTIONAL, |
57 | .schan_val = 42, |
58 | .schan_val2 = 20, |
59 | .expected = "260.545905707" , |
60 | }, |
61 | { |
62 | .name = "typical IIO_VAL_FRACTIONAL, negative" , |
63 | .numerator = -1000000, |
64 | .denominator = 8060, |
65 | .schan_scale_type = IIO_VAL_FRACTIONAL, |
66 | .schan_val = 42, |
67 | .schan_val2 = 20, |
68 | .expected = "-260.545905707" , |
69 | }, |
70 | { |
71 | .name = "typical IIO_VAL_FRACTIONAL_LOG2, positive" , |
72 | .numerator = 42, |
73 | .denominator = 53, |
74 | .schan_scale_type = IIO_VAL_FRACTIONAL_LOG2, |
75 | .schan_val = 4096, |
76 | .schan_val2 = 16, |
77 | .expected = "0.049528301" , |
78 | }, |
79 | { |
80 | .name = "typical IIO_VAL_FRACTIONAL_LOG2, negative" , |
81 | .numerator = -42, |
82 | .denominator = 53, |
83 | .schan_scale_type = IIO_VAL_FRACTIONAL_LOG2, |
84 | .schan_val = 4096, |
85 | .schan_val2 = 16, |
86 | .expected = "-0.049528301" , |
87 | }, |
88 | { |
89 | .name = "typical IIO_VAL_INT_PLUS_NANO, positive" , |
90 | .numerator = 1000000, |
91 | .denominator = 8060, |
92 | .schan_scale_type = IIO_VAL_INT_PLUS_NANO, |
93 | .schan_val = 10, |
94 | .schan_val2 = 123456, |
95 | .expected = "1240.710106203" , |
96 | }, |
97 | { |
98 | .name = "typical IIO_VAL_INT_PLUS_NANO, negative" , |
99 | .numerator = -1000000, |
100 | .denominator = 8060, |
101 | .schan_scale_type = IIO_VAL_INT_PLUS_NANO, |
102 | .schan_val = 10, |
103 | .schan_val2 = 123456, |
104 | .expected = "-1240.710106203" , |
105 | }, |
106 | { |
107 | .name = "typical IIO_VAL_INT_PLUS_MICRO, positive" , |
108 | .numerator = 1000000, |
109 | .denominator = 8060, |
110 | .schan_scale_type = IIO_VAL_INT_PLUS_MICRO, |
111 | .schan_val = 10, |
112 | .schan_val2 = 1234, |
113 | .expected = "1240.84789" , |
114 | }, |
115 | { |
116 | .name = "typical IIO_VAL_INT_PLUS_MICRO, negative" , |
117 | .numerator = -1000000, |
118 | .denominator = 8060, |
119 | .schan_scale_type = IIO_VAL_INT_PLUS_MICRO, |
120 | .schan_val = 10, |
121 | .schan_val2 = 1234, |
122 | .expected = "-1240.84789" , |
123 | }, |
124 | /* |
125 | * Use cases with small scales involving divisions |
126 | */ |
127 | { |
128 | .name = "small IIO_VAL_FRACTIONAL, 261/509 scaled by 90/1373754273" , |
129 | .numerator = 261, |
130 | .denominator = 509, |
131 | .schan_scale_type = IIO_VAL_FRACTIONAL, |
132 | .schan_val = 90, |
133 | .schan_val2 = 1373754273, |
134 | .expected = "0.000000033594" , |
135 | }, |
136 | { |
137 | .name = "small IIO_VAL_FRACTIONAL, 90/1373754273 scaled by 261/509" , |
138 | .numerator = 90, |
139 | .denominator = 1373754273, |
140 | .schan_scale_type = IIO_VAL_FRACTIONAL, |
141 | .schan_val = 261, |
142 | .schan_val2 = 509, |
143 | .expected = "0.000000033594" , |
144 | }, |
145 | { |
146 | .name = "small IIO_VAL_FRACTIONAL, 760/1373754273 scaled by 427/2727" , |
147 | .numerator = 760, |
148 | .denominator = 1373754273, |
149 | .schan_scale_type = IIO_VAL_FRACTIONAL, |
150 | .schan_val = 427, |
151 | .schan_val2 = 2727, |
152 | .expected = "0.000000086626" , |
153 | }, |
154 | { |
155 | .name = "small IIO_VAL_FRACTIONAL, 761/1373754273 scaled by 427/2727" , |
156 | .numerator = 761, |
157 | .denominator = 1373754273, |
158 | .schan_scale_type = IIO_VAL_FRACTIONAL, |
159 | .schan_val = 427, |
160 | .schan_val2 = 2727, |
161 | .expected = "0.000000086740" , |
162 | }, |
163 | { |
164 | .name = "small IIO_VAL_FRACTIONAL, 5/32768 scaled by 3/10000" , |
165 | .numerator = 5, |
166 | .denominator = 32768, |
167 | .schan_scale_type = IIO_VAL_FRACTIONAL, |
168 | .schan_val = 3, |
169 | .schan_val2 = 10000, |
170 | .expected = "0.0000000457763671875" , |
171 | }, |
172 | { |
173 | .name = "small IIO_VAL_FRACTIONAL, 0 < scale < 1" , |
174 | .numerator = 6, |
175 | .denominator = 6, |
176 | .schan_scale_type = IIO_VAL_FRACTIONAL, |
177 | .schan_val = 1, |
178 | .schan_val2 = 3, |
179 | .expected = "0.3333333333333333" , |
180 | }, |
181 | { |
182 | .name = "small IIO_VAL_FRACTIONAL, -1 < scale < 0" , |
183 | .numerator = -6, |
184 | .denominator = 6, |
185 | .schan_scale_type = IIO_VAL_FRACTIONAL, |
186 | .schan_val = 1, |
187 | .schan_val2 = 3, |
188 | .expected = "-0.3333333333333333" , |
189 | }, |
190 | { |
191 | .name = "small IIO_VAL_FRACTIONAL, 0 < scale < 2" , |
192 | .numerator = 8, |
193 | .denominator = 2, |
194 | .schan_scale_type = IIO_VAL_FRACTIONAL, |
195 | .schan_val = 1, |
196 | .schan_val2 = 3, |
197 | .expected = "1.3333333333333333" , |
198 | }, |
199 | { |
200 | .name = "small IIO_VAL_FRACTIONAL, -2 < scale < 0" , |
201 | .numerator = -8, |
202 | .denominator = 2, |
203 | .schan_scale_type = IIO_VAL_FRACTIONAL, |
204 | .schan_val = 1, |
205 | .schan_val2 = 3, |
206 | .expected = "-1.3333333333333333" , |
207 | }, |
208 | { |
209 | .name = "small IIO_VAL_FRACTIONAL_LOG2, 760/32768 scaled by 15/22" , |
210 | .numerator = 760, |
211 | .denominator = 32768, |
212 | .schan_scale_type = IIO_VAL_FRACTIONAL_LOG2, |
213 | .schan_val = 15, |
214 | .schan_val2 = 22, |
215 | .expected = "0.000000082946" , |
216 | }, |
217 | { |
218 | .name = "small IIO_VAL_FRACTIONAL_LOG2, 761/32768 scaled by 15/22" , |
219 | .numerator = 761, |
220 | .denominator = 32768, |
221 | .schan_scale_type = IIO_VAL_FRACTIONAL_LOG2, |
222 | .schan_val = 15, |
223 | .schan_val2 = 22, |
224 | .expected = "0.000000083055" , |
225 | }, |
226 | { |
227 | .name = "small IIO_VAL_FRACTIONAL_LOG2, 0 < scale < 1" , |
228 | .numerator = 16, |
229 | .denominator = 3, |
230 | .schan_scale_type = IIO_VAL_FRACTIONAL_LOG2, |
231 | .schan_val = 1, |
232 | .schan_val2 = 4, |
233 | .expected = "0.3333333333333333" , |
234 | }, |
235 | { |
236 | .name = "small IIO_VAL_FRACTIONAL_LOG2, -1 < scale < 0" , |
237 | .numerator = -16, |
238 | .denominator = 3, |
239 | .schan_scale_type = IIO_VAL_FRACTIONAL_LOG2, |
240 | .schan_val = 1, |
241 | .schan_val2 = 4, |
242 | .expected = "-0.3333333333333333" , |
243 | }, |
244 | { |
245 | .name = "small IIO_VAL_FRACTIONAL_LOG2, 0 < scale < 2" , |
246 | .numerator = 8, |
247 | .denominator = 3, |
248 | .schan_scale_type = IIO_VAL_FRACTIONAL_LOG2, |
249 | .schan_val = 1, |
250 | .schan_val2 = 1, |
251 | .expected = "1.3333333333333333" , |
252 | }, |
253 | { |
254 | .name = "small IIO_VAL_FRACTIONAL_LOG2, -2 < scale < 0" , |
255 | .numerator = -8, |
256 | .denominator = 3, |
257 | .schan_scale_type = IIO_VAL_FRACTIONAL_LOG2, |
258 | .schan_val = 1, |
259 | .schan_val2 = 1, |
260 | .expected = "-1.3333333333333333" , |
261 | }, |
262 | { |
263 | .name = "small IIO_VAL_INT_PLUS_MICRO, positive" , |
264 | .numerator = 1, |
265 | .denominator = 2, |
266 | .schan_scale_type = IIO_VAL_INT_PLUS_MICRO, |
267 | .schan_val = 5, |
268 | .schan_val2 = 1234, |
269 | .expected = "2.500617" , |
270 | }, |
271 | { |
272 | .name = "small IIO_VAL_INT_PLUS_MICRO, negative" , |
273 | .numerator = -1, |
274 | .denominator = 2, |
275 | .schan_scale_type = IIO_VAL_INT_PLUS_MICRO, |
276 | .schan_val = 5, |
277 | .schan_val2 = 1234, |
278 | .expected = "-2.500617" , |
279 | }, |
280 | /* |
281 | * INT_PLUS_{MICRO,NANO} positive/negative corner cases |
282 | */ |
283 | { |
284 | .name = "negative IIO_VAL_INT_PLUS_NANO, negative schan" , |
285 | .numerator = 1000000, |
286 | .denominator = 8060, |
287 | .schan_scale_type = IIO_VAL_INT_PLUS_NANO, |
288 | .schan_val = -10, |
289 | .schan_val2 = 123456, |
290 | .expected = "-1240.710106203" , |
291 | }, |
292 | { |
293 | .name = "negative IIO_VAL_INT_PLUS_NANO, both negative" , |
294 | .numerator = -1000000, |
295 | .denominator = 8060, |
296 | .schan_scale_type = IIO_VAL_INT_PLUS_NANO, |
297 | .schan_val = -10, |
298 | .schan_val2 = 123456, |
299 | .expected = "1240.710106203" , |
300 | }, |
301 | { |
302 | .name = "negative IIO_VAL_INT_PLUS_NANO, 3 negative" , |
303 | .numerator = -1000000, |
304 | .denominator = -8060, |
305 | .schan_scale_type = IIO_VAL_INT_PLUS_NANO, |
306 | .schan_val = -10, |
307 | .schan_val2 = 123456, |
308 | .expected = "-1240.710106203" , |
309 | }, |
310 | { |
311 | .name = "negative IIO_VAL_INT_PLUS_NANO, 4 negative" , |
312 | .numerator = -1000000, |
313 | .denominator = -8060, |
314 | .schan_scale_type = IIO_VAL_INT_PLUS_NANO, |
315 | .schan_val = -10, |
316 | .schan_val2 = -123456, |
317 | .expected = "-1240.710106203" , |
318 | }, |
319 | { |
320 | .name = "negative IIO_VAL_INT_PLUS_NANO, negative, *val = 0" , |
321 | .numerator = 1, |
322 | .denominator = -10, |
323 | .schan_scale_type = IIO_VAL_INT_PLUS_NANO, |
324 | .schan_val = 0, |
325 | .schan_val2 = 123456789, |
326 | .expected = "-0.012345678" , |
327 | }, |
328 | /* |
329 | * INT_PLUS_{MICRO,NANO} decimal part overflow |
330 | */ |
331 | { |
332 | .name = "decimal overflow IIO_VAL_INT_PLUS_NANO, positive" , |
333 | .numerator = 1000000, |
334 | .denominator = 8060, |
335 | .schan_scale_type = IIO_VAL_INT_PLUS_NANO, |
336 | .schan_val = 10, |
337 | .schan_val2 = 123456789, |
338 | .expected = "1256.01200856" , |
339 | }, |
340 | { |
341 | .name = "decimal overflow IIO_VAL_INT_PLUS_NANO, negative" , |
342 | .numerator = -1000000, |
343 | .denominator = 8060, |
344 | .schan_scale_type = IIO_VAL_INT_PLUS_NANO, |
345 | .schan_val = 10, |
346 | .schan_val2 = 123456789, |
347 | .expected = "-1256.01200856" , |
348 | }, |
349 | { |
350 | .name = "decimal overflow IIO_VAL_INT_PLUS_NANO, negative schan" , |
351 | .numerator = 1000000, |
352 | .denominator = 8060, |
353 | .schan_scale_type = IIO_VAL_INT_PLUS_NANO, |
354 | .schan_val = -10, |
355 | .schan_val2 = 123456789, |
356 | .expected = "-1256.01200856" , |
357 | }, |
358 | { |
359 | .name = "decimal overflow IIO_VAL_INT_PLUS_MICRO, positive" , |
360 | .numerator = 1000000, |
361 | .denominator = 8060, |
362 | .schan_scale_type = IIO_VAL_INT_PLUS_MICRO, |
363 | .schan_val = 10, |
364 | .schan_val2 = 123456789, |
365 | .expected = "16557.914267" , |
366 | }, |
367 | { |
368 | .name = "decimal overflow IIO_VAL_INT_PLUS_MICRO, negative" , |
369 | .numerator = -1000000, |
370 | .denominator = 8060, |
371 | .schan_scale_type = IIO_VAL_INT_PLUS_MICRO, |
372 | .schan_val = 10, |
373 | .schan_val2 = 123456789, |
374 | .expected = "-16557.914267" , |
375 | }, |
376 | { |
377 | .name = "decimal overflow IIO_VAL_INT_PLUS_MICRO, negative schan" , |
378 | .numerator = 1000000, |
379 | .denominator = 8060, |
380 | .schan_scale_type = IIO_VAL_INT_PLUS_MICRO, |
381 | .schan_val = -10, |
382 | .schan_val2 = 123456789, |
383 | .expected = "-16557.914267" , |
384 | }, |
385 | /* |
386 | * 32-bit overflow conditions |
387 | */ |
388 | { |
389 | .name = "overflow IIO_VAL_FRACTIONAL, positive" , |
390 | .numerator = 2, |
391 | .denominator = 20, |
392 | .schan_scale_type = IIO_VAL_FRACTIONAL, |
393 | .schan_val = S32_MAX, |
394 | .schan_val2 = 1, |
395 | .expected = "214748364.7" , |
396 | }, |
397 | { |
398 | .name = "overflow IIO_VAL_FRACTIONAL, negative" , |
399 | .numerator = -2, |
400 | .denominator = 20, |
401 | .schan_scale_type = IIO_VAL_FRACTIONAL, |
402 | .schan_val = S32_MAX, |
403 | .schan_val2 = 1, |
404 | .expected = "-214748364.7" , |
405 | }, |
406 | { |
407 | .name = "overflow IIO_VAL_FRACTIONAL_LOG2, positive" , |
408 | .numerator = S32_MAX, |
409 | .denominator = 4096, |
410 | .schan_scale_type = IIO_VAL_FRACTIONAL_LOG2, |
411 | .schan_val = 4096, |
412 | .schan_val2 = 16, |
413 | .expected = "32767.99998474121" , |
414 | }, |
415 | { |
416 | .name = "overflow IIO_VAL_FRACTIONAL_LOG2, negative" , |
417 | .numerator = S32_MAX, |
418 | .denominator = 4096, |
419 | .schan_scale_type = IIO_VAL_FRACTIONAL_LOG2, |
420 | .schan_val = -4096, |
421 | .schan_val2 = 16, |
422 | .expected = "-32767.99998474121" , |
423 | }, |
424 | { |
425 | .name = "overflow IIO_VAL_INT_PLUS_NANO, positive" , |
426 | .numerator = 2, |
427 | .denominator = 20, |
428 | .schan_scale_type = IIO_VAL_INT_PLUS_NANO, |
429 | .schan_val = 10, |
430 | .schan_val2 = S32_MAX, |
431 | .expected = "1.214748364" , |
432 | }, |
433 | { |
434 | .name = "overflow IIO_VAL_INT_PLUS_NANO, negative" , |
435 | .numerator = -2, |
436 | .denominator = 20, |
437 | .schan_scale_type = IIO_VAL_INT_PLUS_NANO, |
438 | .schan_val = 10, |
439 | .schan_val2 = S32_MAX, |
440 | .expected = "-1.214748364" , |
441 | }, |
442 | { |
443 | .name = "overflow IIO_VAL_INT_PLUS_NANO, negative schan" , |
444 | .numerator = 2, |
445 | .denominator = 20, |
446 | .schan_scale_type = IIO_VAL_INT_PLUS_NANO, |
447 | .schan_val = -10, |
448 | .schan_val2 = S32_MAX, |
449 | .expected = "-1.214748364" , |
450 | }, |
451 | { |
452 | .name = "overflow IIO_VAL_INT_PLUS_MICRO, positive" , |
453 | .numerator = 2, |
454 | .denominator = 20, |
455 | .schan_scale_type = IIO_VAL_INT_PLUS_MICRO, |
456 | .schan_val = 10, |
457 | .schan_val2 = S32_MAX, |
458 | .expected = "215.748364" , |
459 | }, |
460 | { |
461 | .name = "overflow IIO_VAL_INT_PLUS_MICRO, negative" , |
462 | .numerator = -2, |
463 | .denominator = 20, |
464 | .schan_scale_type = IIO_VAL_INT_PLUS_MICRO, |
465 | .schan_val = 10, |
466 | .schan_val2 = S32_MAX, |
467 | .expected = "-215.748364" , |
468 | }, |
469 | { |
470 | .name = "overflow IIO_VAL_INT_PLUS_MICRO, negative schan" , |
471 | .numerator = 2, |
472 | .denominator = 20, |
473 | .schan_scale_type = IIO_VAL_INT_PLUS_MICRO, |
474 | .schan_val = -10, |
475 | .schan_val2 = S32_MAX, |
476 | .expected = "-215.748364" , |
477 | }, |
478 | }; |
479 | |
480 | static const struct rescale_tc_data offset_cases[] = { |
481 | /* |
482 | * Typical use cases |
483 | */ |
484 | { |
485 | .name = "typical IIO_VAL_INT, positive" , |
486 | .offset = 1234, |
487 | .schan_scale_type = IIO_VAL_INT, |
488 | .schan_val = 123, |
489 | .schan_val2 = 0, |
490 | .schan_off = 14, |
491 | .expected_off = "24" , /* 23.872 */ |
492 | }, |
493 | { |
494 | .name = "typical IIO_VAL_INT, negative" , |
495 | .offset = -1234, |
496 | .schan_scale_type = IIO_VAL_INT, |
497 | .schan_val = 12, |
498 | .schan_val2 = 0, |
499 | .schan_off = 14, |
500 | .expected_off = "-88" , /* -88.83333333333333 */ |
501 | }, |
502 | { |
503 | .name = "typical IIO_VAL_FRACTIONAL, positive" , |
504 | .offset = 1234, |
505 | .schan_scale_type = IIO_VAL_FRACTIONAL, |
506 | .schan_val = 12, |
507 | .schan_val2 = 34, |
508 | .schan_off = 14, |
509 | .expected_off = "3510" , /* 3510.333333333333 */ |
510 | }, |
511 | { |
512 | .name = "typical IIO_VAL_FRACTIONAL, negative" , |
513 | .offset = -1234, |
514 | .schan_scale_type = IIO_VAL_FRACTIONAL, |
515 | .schan_val = 12, |
516 | .schan_val2 = 34, |
517 | .schan_off = 14, |
518 | .expected_off = "-3482" , /* -3482.333333333333 */ |
519 | }, |
520 | { |
521 | .name = "typical IIO_VAL_FRACTIONAL_LOG2, positive" , |
522 | .offset = 1234, |
523 | .schan_scale_type = IIO_VAL_FRACTIONAL_LOG2, |
524 | .schan_val = 12, |
525 | .schan_val2 = 16, |
526 | .schan_off = 14, |
527 | .expected_off = "6739299" , /* 6739299.333333333 */ |
528 | }, |
529 | { |
530 | .name = "typical IIO_VAL_FRACTIONAL_LOG2, negative" , |
531 | .offset = -1234, |
532 | .schan_scale_type = IIO_VAL_FRACTIONAL_LOG2, |
533 | .schan_val = 12, |
534 | .schan_val2 = 16, |
535 | .schan_off = 14, |
536 | .expected_off = "-6739271" , /* -6739271.333333333 */ |
537 | }, |
538 | { |
539 | .name = "typical IIO_VAL_INT_PLUS_NANO, positive" , |
540 | .offset = 1234, |
541 | .schan_scale_type = IIO_VAL_INT_PLUS_NANO, |
542 | .schan_val = 10, |
543 | .schan_val2 = 123456789, |
544 | .schan_off = 14, |
545 | .expected_off = "135" , /* 135.8951219647469 */ |
546 | }, |
547 | { |
548 | .name = "typical IIO_VAL_INT_PLUS_NANO, negative" , |
549 | .offset = -1234, |
550 | .schan_scale_type = IIO_VAL_INT_PLUS_NANO, |
551 | .schan_val = 10, |
552 | .schan_val2 = 123456789, |
553 | .schan_off = 14, |
554 | .expected_off = "-107" , /* -107.89512196474689 */ |
555 | }, |
556 | { |
557 | .name = "typical IIO_VAL_INT_PLUS_MICRO, positive" , |
558 | .offset = 1234, |
559 | .schan_scale_type = IIO_VAL_INT_PLUS_MICRO, |
560 | .schan_val = 10, |
561 | .schan_val2 = 123456789, |
562 | .schan_off = 14, |
563 | .expected_off = "23" , /* 23.246438560723952 */ |
564 | }, |
565 | { |
566 | .name = "typical IIO_VAL_INT_PLUS_MICRO, negative" , |
567 | .offset = -12345, |
568 | .schan_scale_type = IIO_VAL_INT_PLUS_MICRO, |
569 | .schan_val = 10, |
570 | .schan_val2 = 123456789, |
571 | .schan_off = 14, |
572 | .expected_off = "-78" , /* -78.50185091745313 */ |
573 | }, |
574 | }; |
575 | |
576 | static void case_to_desc(const struct rescale_tc_data *t, char *desc) |
577 | { |
578 | strcpy(p: desc, q: t->name); |
579 | } |
580 | |
581 | KUNIT_ARRAY_PARAM(iio_rescale_scale, scale_cases, case_to_desc); |
582 | KUNIT_ARRAY_PARAM(iio_rescale_offset, offset_cases, case_to_desc); |
583 | |
584 | /** |
585 | * iio_str_to_nano() - Parse a fixed-point string to get an |
586 | * IIO_VAL_INT_PLUS_NANO value |
587 | * @str: The string to parse |
588 | * @nano: The number as an integer |
589 | * |
590 | * Returns 0 on success, or a negative error code if the string cound not be |
591 | * parsed. |
592 | */ |
593 | static int iio_str_to_nano(const char *str, s64 *nano) |
594 | { |
595 | int tmp, tmp2; |
596 | int ret = 0; |
597 | |
598 | /* |
599 | * iio_str_to_fixpoint() uses 10^8 here instead of 10^9 as fract_mult is |
600 | * the multiplier for the first decimal place. |
601 | */ |
602 | ret = iio_str_to_fixpoint(str, fract_mult: 100000000, integer: &tmp, fract: &tmp2); |
603 | if (ret < 0) |
604 | return ret; |
605 | |
606 | if (tmp < 0) |
607 | tmp2 *= -1; |
608 | |
609 | *nano = (s64)tmp * 1000000000UL + tmp2; |
610 | |
611 | return ret; |
612 | } |
613 | |
614 | /** |
615 | * iio_test_relative_error_ppm() - Compute relative error (in parts-per-million) |
616 | * between two fixed-point strings |
617 | * @real_str: The real value as a string |
618 | * @exp_str: The expected value as a string |
619 | * |
620 | * Returns a negative error code if the strings cound not be parsed, or the |
621 | * relative error in parts-per-million. |
622 | */ |
623 | static int iio_test_relative_error_ppm(const char *real_str, const char *exp_str) |
624 | { |
625 | s64 real, exp, err; |
626 | int ret; |
627 | |
628 | ret = iio_str_to_nano(str: real_str, nano: &real); |
629 | if (ret < 0) |
630 | return ret; |
631 | |
632 | ret = iio_str_to_nano(str: exp_str, nano: &exp); |
633 | if (ret < 0) |
634 | return ret; |
635 | |
636 | if (!exp) { |
637 | pr_err("Expected value is null, relative error is undefined\n" ); |
638 | return -EINVAL; |
639 | } |
640 | |
641 | err = 1000000UL * abs(exp - real); |
642 | |
643 | return (int)div64_u64(dividend: err, abs(exp)); |
644 | } |
645 | |
646 | static void iio_rescale_test_scale(struct kunit *test) |
647 | { |
648 | struct rescale_tc_data *t = (struct rescale_tc_data *)test->param_value; |
649 | char *buff = kunit_kmalloc(test, PAGE_SIZE, GFP_KERNEL); |
650 | struct rescale rescale; |
651 | int values[2]; |
652 | int rel_ppm; |
653 | int ret; |
654 | |
655 | rescale.numerator = t->numerator; |
656 | rescale.denominator = t->denominator; |
657 | rescale.offset = t->offset; |
658 | values[0] = t->schan_val; |
659 | values[1] = t->schan_val2; |
660 | |
661 | ret = rescale_process_scale(rescale: &rescale, scale_type: t->schan_scale_type, |
662 | val: &values[0], val2: &values[1]); |
663 | |
664 | ret = iio_format_value(buf: buff, type: ret, size: 2, vals: values); |
665 | KUNIT_EXPECT_EQ(test, (int)strlen(buff), ret); |
666 | |
667 | rel_ppm = iio_test_relative_error_ppm(real_str: buff, exp_str: t->expected); |
668 | KUNIT_EXPECT_GE_MSG(test, rel_ppm, 0, "failed to compute ppm\n" ); |
669 | |
670 | KUNIT_EXPECT_EQ_MSG(test, rel_ppm, 0, |
671 | "\t real=%s" |
672 | "\texpected=%s\n" , |
673 | buff, t->expected); |
674 | } |
675 | |
676 | static void iio_rescale_test_offset(struct kunit *test) |
677 | { |
678 | struct rescale_tc_data *t = (struct rescale_tc_data *)test->param_value; |
679 | char *buff_off = kunit_kmalloc(test, PAGE_SIZE, GFP_KERNEL); |
680 | struct rescale rescale; |
681 | int values[2]; |
682 | int ret; |
683 | |
684 | rescale.numerator = t->numerator; |
685 | rescale.denominator = t->denominator; |
686 | rescale.offset = t->offset; |
687 | values[0] = t->schan_val; |
688 | values[1] = t->schan_val2; |
689 | |
690 | ret = rescale_process_offset(rescale: &rescale, scale_type: t->schan_scale_type, |
691 | scale: t->schan_val, scale2: t->schan_val2, schan_off: t->schan_off, |
692 | val: &values[0], val2: &values[1]); |
693 | |
694 | ret = iio_format_value(buf: buff_off, type: ret, size: 2, vals: values); |
695 | KUNIT_EXPECT_EQ(test, (int)strlen(buff_off), ret); |
696 | |
697 | KUNIT_EXPECT_STREQ(test, strim(buff_off), t->expected_off); |
698 | } |
699 | |
700 | static struct kunit_case iio_rescale_test_cases[] = { |
701 | KUNIT_CASE_PARAM(iio_rescale_test_scale, iio_rescale_scale_gen_params), |
702 | KUNIT_CASE_PARAM(iio_rescale_test_offset, iio_rescale_offset_gen_params), |
703 | {} |
704 | }; |
705 | |
706 | static struct kunit_suite iio_rescale_test_suite = { |
707 | .name = "iio-rescale" , |
708 | .test_cases = iio_rescale_test_cases, |
709 | }; |
710 | kunit_test_suite(iio_rescale_test_suite); |
711 | |
712 | MODULE_AUTHOR("Liam Beguin <liambeguin@gmail.com>" ); |
713 | MODULE_DESCRIPTION("Test IIO rescale conversion functions" ); |
714 | MODULE_LICENSE("GPL v2" ); |
715 | MODULE_IMPORT_NS(IIO_RESCALE); |
716 | |