| 31 | } |
| 32 | |
| 33 | std::string FlipKernel::GetCVKernelBody(TContext* context) const { |
| 34 | auto kernel_sig = GetCVKernelSignature(context); |
| 35 | std::string body_temp = R"( |
| 36 | #include <arm_neon.h> |
| 37 | #include <string.h> |
| 38 | #include "tinycv_c.h" |
| 39 | #define rep(i, n) for (size_t i = 0; i < (n); ++i) |
| 40 | |
| 41 | static void flip_horizontal_on_channel_c1(uint8_t* dst, const uint8_t* src, size_t W) { |
| 42 | size_t j = 0; |
| 43 | for (; j + 15 < W; j += 16) { |
| 44 | uint8x16_t src_vec = vld1q_u8(src + j); |
| 45 | uint8x16_t dst_vec = vrev64q_u8(src_vec); |
| 46 | dst_vec = vcombine_u8(vget_high_u8(dst_vec), vget_low_u8(dst_vec)); |
| 47 | vst1q_u8((dst + W - j - 16), dst_vec); |
| 48 | } |
| 49 | for (; j < W; ++j) { |
| 50 | *(dst + W - j - 1) = *(src + j); |
| 51 | } |
| 52 | } |
| 53 | static void flip_horizontal_on_channel_c3(uint8_t* dst, const uint8_t* src, size_t W) { |
| 54 | size_t j = 0; |
| 55 | for (; j + 15 < W; j += 16) { |
| 56 | uint8x16x3_t src_vec = vld3q_u8(src + j * 3); |
| 57 | uint8x16x3_t dst_vec; |
| 58 | uint8x16_t rev_src0 = vrev64q_u8(src_vec.val[0]); |
| 59 | dst_vec.val[0] = |
| 60 | vcombine_u8(vget_high_u8(rev_src0), vget_low_u8(rev_src0)); |
| 61 | |
| 62 | uint8x16_t rev_src1 = vrev64q_u8(src_vec.val[1]); |
| 63 | dst_vec.val[1] = |
| 64 | vcombine_u8(vget_high_u8(rev_src1), vget_low_u8(rev_src1)); |
| 65 | |
| 66 | uint8x16_t rev_src2 = vrev64q_u8(src_vec.val[2]); |
| 67 | dst_vec.val[2] = |
| 68 | vcombine_u8(vget_high_u8(rev_src2), vget_low_u8(rev_src2)); |
| 69 | vst3q_u8((dst + W * 3 - 3 * j - 48), dst_vec); |
| 70 | } |
| 71 | for (; j < W; ++j) { |
| 72 | *(dst + W * 3 - j * 3 - 3) = *(src + j * 3); |
| 73 | *(dst + W * 3 - j * 3 - 2) = *(src + j * 3 + 1); |
| 74 | *(dst + W * 3 - j * 3 - 1) = *(src + j * 3 + 2); |
| 75 | |
| 76 | } |
| 77 | } |
| 78 | |
| 79 | static void flip_horizontal_naive(uint8_t* dst, const uint8_t* src, size_t W, |
| 80 | size_t C) { |
| 81 | size_t sc = 0; |
| 82 | size_t dc = W * C; |
| 83 | for (; sc + 8 * C <= W * C; sc += 8 * C, dc -= 8 * C) { |
| 84 | rep(ic, C) dst[dc - 1 * C + ic] = src[sc + 0 * C + ic]; |
| 85 | rep(ic, C) dst[dc - 2 * C + ic] = src[sc + 1 * C + ic]; |
| 86 | rep(ic, C) dst[dc - 3 * C + ic] = src[sc + 2 * C + ic]; |
| 87 | rep(ic, C) dst[dc - 4 * C + ic] = src[sc + 3 * C + ic]; |
| 88 | rep(ic, C) dst[dc - 5 * C + ic] = src[sc + 4 * C + ic]; |
| 89 | rep(ic, C) dst[dc - 6 * C + ic] = src[sc + 5 * C + ic]; |
| 90 | rep(ic, C) dst[dc - 7 * C + ic] = src[sc + 6 * C + ic]; |
nothing calls this directly
no test coverage detected