|
4 | 4 |
|
5 | 5 | #include <linux/math.h>
|
6 | 6 |
|
7 |
| -#define __find_closest(x, a, as, op) \ |
8 |
| -({ \ |
9 |
| - typeof(as) __fc_i, __fc_as = (as) - 1; \ |
10 |
| - typeof(x) __fc_x = (x); \ |
11 |
| - typeof(*a) const *__fc_a = (a); \ |
12 |
| - for (__fc_i = 0; __fc_i < __fc_as; __fc_i++) { \ |
13 |
| - if (__fc_x op DIV_ROUND_CLOSEST(__fc_a[__fc_i] + \ |
14 |
| - __fc_a[__fc_i + 1], 2)) \ |
15 |
| - break; \ |
16 |
| - } \ |
17 |
| - (__fc_i); \ |
18 |
| -}) |
19 |
| - |
20 | 7 | /**
|
21 | 8 | * find_closest - locate the closest element in a sorted array
|
22 | 9 | * @x: The reference value.
|
|
25 | 12 | * @as: Size of 'a'.
|
26 | 13 | *
|
27 | 14 | * Returns the index of the element closest to 'x'.
|
| 15 | + * Note: If using an array of negative numbers (or mixed positive numbers), |
| 16 | + * then be sure that 'x' is of a signed-type to get good results. |
28 | 17 | */
|
29 |
| -#define find_closest(x, a, as) __find_closest(x, a, as, <=) |
| 18 | +#define find_closest(x, a, as) \ |
| 19 | +({ \ |
| 20 | + typeof(as) __fc_i, __fc_as = (as) - 1; \ |
| 21 | + long __fc_mid_x, __fc_x = (x); \ |
| 22 | + long __fc_left, __fc_right; \ |
| 23 | + typeof(*a) const *__fc_a = (a); \ |
| 24 | + for (__fc_i = 0; __fc_i < __fc_as; __fc_i++) { \ |
| 25 | + __fc_mid_x = (__fc_a[__fc_i] + __fc_a[__fc_i + 1]) / 2; \ |
| 26 | + if (__fc_x <= __fc_mid_x) { \ |
| 27 | + __fc_left = __fc_x - __fc_a[__fc_i]; \ |
| 28 | + __fc_right = __fc_a[__fc_i + 1] - __fc_x; \ |
| 29 | + if (__fc_right < __fc_left) \ |
| 30 | + __fc_i++; \ |
| 31 | + break; \ |
| 32 | + } \ |
| 33 | + } \ |
| 34 | + (__fc_i); \ |
| 35 | +}) |
30 | 36 |
|
31 | 37 | /**
|
32 | 38 | * find_closest_descending - locate the closest element in a sorted array
|
|
36 | 42 | * @as: Size of 'a'.
|
37 | 43 | *
|
38 | 44 | * Similar to find_closest() but 'a' is expected to be sorted in descending
|
39 |
| - * order. |
| 45 | + * order. The iteration is done in reverse order, so that the comparison |
| 46 | + * of '__fc_right' & '__fc_left' also works for unsigned numbers. |
40 | 47 | */
|
41 |
| -#define find_closest_descending(x, a, as) __find_closest(x, a, as, >=) |
| 48 | +#define find_closest_descending(x, a, as) \ |
| 49 | +({ \ |
| 50 | + typeof(as) __fc_i, __fc_as = (as) - 1; \ |
| 51 | + long __fc_mid_x, __fc_x = (x); \ |
| 52 | + long __fc_left, __fc_right; \ |
| 53 | + typeof(*a) const *__fc_a = (a); \ |
| 54 | + for (__fc_i = __fc_as; __fc_i >= 1; __fc_i--) { \ |
| 55 | + __fc_mid_x = (__fc_a[__fc_i] + __fc_a[__fc_i - 1]) / 2; \ |
| 56 | + if (__fc_x <= __fc_mid_x) { \ |
| 57 | + __fc_left = __fc_x - __fc_a[__fc_i]; \ |
| 58 | + __fc_right = __fc_a[__fc_i - 1] - __fc_x; \ |
| 59 | + if (__fc_right < __fc_left) \ |
| 60 | + __fc_i--; \ |
| 61 | + break; \ |
| 62 | + } \ |
| 63 | + } \ |
| 64 | + (__fc_i); \ |
| 65 | +}) |
42 | 66 |
|
43 | 67 | /**
|
44 | 68 | * is_insidevar - check if the @ptr points inside the @var memory range.
|
|
0 commit comments