+void hlineSmooth5Nabcba(const ET* src, int cn, const FT* m, int, FT* dst, int len, int borderType)
+{
+ if (len == 1)
+ {
+ FT msum = borderType != BORDER_CONSTANT ? ((m[0] + m[1])<<1) + m[2] : m[2];
+ for (int k = 0; k < cn; k++)
+ dst[k] = msum * src[k];
+ }
+ else if (len == 2)
+ {
+ if (borderType == BORDER_CONSTANT)
+ for (int k = 0; k < cn; k++)
+ {
+ dst[k] = m[2] * src[k] + m[1] * src[k + cn];
+ dst[k + cn] = m[1] * src[k] + m[2] * src[k + cn];
+ }
+ else
+ {
+ int idxm2 = borderInterpolate(-2, len, borderType)*cn;
+ int idxm1 = borderInterpolate(-1, len, borderType)*cn;
+ int idxp1 = borderInterpolate(2, len, borderType)*cn;
+ int idxp2 = borderInterpolate(3, len, borderType)*cn;
+ for (int k = 0; k < cn; k++)
+ {
+ dst[k] = m[1] * src[k + idxm1] + m[2] * src[k] + m[1] * src[k + cn] + m[0] * src[k + idxp1] + m[0] * src[k + idxm2];
+ dst[k + cn] = m[0] * src[k + idxm1] + m[1] * src[k] + m[2] * src[k + cn] + m[1] * src[k + idxp1] + m[0] * src[k + idxp2];
+ }
+ }
+ }
+ else if (len == 3)
+ {
+ if (borderType == BORDER_CONSTANT)
+ for (int k = 0; k < cn; k++)
+ {
+ dst[k] = m[2] * src[k] + m[1] * src[k + cn] + m[0] * src[k + 2 * cn];
+ dst[k + cn] = m[1] * src[k] + m[2] * src[k + cn] + m[1] * src[k + 2 * cn];
+ dst[k + 2 * cn] = m[0] * src[k] + m[1] * src[k + cn] + m[2] * src[k + 2 * cn];
+ }
+ else
+ {
+ int idxm2 = borderInterpolate(-2, len, borderType)*cn;
+ int idxm1 = borderInterpolate(-1, len, borderType)*cn;
+ int idxp1 = borderInterpolate(3, len, borderType)*cn;
+ int idxp2 = borderInterpolate(4, len, borderType)*cn;
+ for (int k = 0; k < cn; k++)
+ {
+ dst[k] = m[2] * src[k] + m[1] * src[k + cn] + m[0] * src[k + 2 * cn] + m[0] * src[k + idxm2] + m[1] * src[k + idxm1];
+ dst[k + cn] = m[1] * src[k] + m[2] * src[k + cn] + m[1] * src[k + 2 * cn] + m[0] * src[k + idxm1] + m[0] * src[k + idxp1];
+ dst[k + 2 * cn] = m[0] * src[k] + m[1] * src[k + cn] + m[2] * src[k + 2 * cn] + m[1] * src[k + idxp1] + m[0] * src[k + idxp2];
+ }
+ }
+ }
+ else
+ {
+ // Points that fall left from border
+ for (int k = 0; k < cn; k++)
+ {
+ dst[k] = m[2] * src[k] + m[1] * src[cn + k] + m[0] * src[2 * cn + k];
+ dst[k + cn] = m[1] * src[k] + m[2] * src[cn + k] + m[1] * src[2 * cn + k] + m[0] * src[3 * cn + k];
+ }
+ if (borderType != BORDER_CONSTANT)// If BORDER_CONSTANT out of border values are equal to zero and could be skipped
+ {
+ int idxm2 = borderInterpolate(-2, len, borderType)*cn;
+ int idxm1 = borderInterpolate(-1, len, borderType)*cn;
+ for (int k = 0; k < cn; k++)
+ {
+ dst[k] = dst[k] + m[0] * src[idxm2 + k] + m[1] * src[idxm1 + k];
+ dst[k + cn] = dst[k + cn] + m[0] * src[idxm1 + k];
+ }
+ }
+
+ src += 2 * cn; dst += 2 * cn;
+ for (int i = 2 * cn; i < (len - 2)*cn; i++, src++, dst++)
+ *dst = m[0] * src[-2 * cn] + m[1] * src[-cn] + m[2] * src[0] + m[3] * src[cn] + m[4] * src[2 * cn];
+
+ // Points that fall right from border
+ for (int k = 0; k < cn; k++)
+ {
+ dst[k] = m[0] * src[k - 2 * cn] + m[1] * src[k - cn] + m[2] * src[k] + m[3] * src[k + cn];
+ dst[k + cn] = m[0] * src[k - cn] + m[1] * src[k] + m[2] * src[k + cn];
+ }
+ if (borderType != BORDER_CONSTANT)// If BORDER_CONSTANT out of border values are equal to zero and could be skipped
+ {
+ int idxp1 = (borderInterpolate(len, len, borderType) - (len - 2))*cn;
+ int idxp2 = (borderInterpolate(len + 1, len, borderType) - (len - 2))*cn;
+ for (int k = 0; k < cn; k++)
+ {
+ dst[k] = dst[k] + m[0] * src[idxp1 + k];
+ dst[k + cn] = dst[k + cn] + m[1] * src[idxp1 + k] + m[0] * src[idxp2 + k];
+ }
+ }
+ }
+}
+template <>
+void hlineSmooth5Nabcba<uint8_t, ufixedpoint16>(const uint8_t* src, int cn, const ufixedpoint16* m, int, ufixedpoint16* dst, int len, int borderType)
+{
+ if (len == 1)
+ {
+ ufixedpoint16 msum = borderType != BORDER_CONSTANT ? ((m[0] + m[1]) << 1) + m[2] : m[2];
+ for (int k = 0; k < cn; k++)
+ dst[k] = msum * src[k];
+ }
+ else if (len == 2)
+ {
+ if (borderType == BORDER_CONSTANT)
+ for (int k = 0; k < cn; k++)
+ {
+ dst[k] = m[2] * src[k] + m[1] * src[k + cn];
+ dst[k + cn] = m[1] * src[k] + m[2] * src[k + cn];
+ }
+ else
+ {
+ int idxm2 = borderInterpolate(-2, len, borderType)*cn;
+ int idxm1 = borderInterpolate(-1, len, borderType)*cn;
+ int idxp1 = borderInterpolate(2, len, borderType)*cn;
+ int idxp2 = borderInterpolate(3, len, borderType)*cn;
+ for (int k = 0; k < cn; k++)
+ {
+ ((uint16_t*)dst)[k] = ((uint16_t*)m)[1] * ((uint16_t)(src[k + idxm1]) + (uint16_t)(src[k + cn])) + ((uint16_t*)m)[2] * src[k] + ((uint16_t*)m)[0] * ((uint16_t)(src[k + idxp1]) + (uint16_t)(src[k + idxm2]));
+ ((uint16_t*)dst)[k + cn] = ((uint16_t*)m)[0] * ((uint16_t)(src[k + idxm1]) + (uint16_t)(src[k + idxp2])) + ((uint16_t*)m)[1] * ((uint16_t)(src[k]) + (uint16_t)(src[k + idxp1])) + ((uint16_t*)m)[2] * src[k + cn];
+ }
+ }
+ }
+ else if (len == 3)
+ {
+ if (borderType == BORDER_CONSTANT)
+ for (int k = 0; k < cn; k++)
+ {
+ dst[k] = m[2] * src[k] + m[1] * src[k + cn] + m[0] * src[k + 2 * cn];
+ ((uint16_t*)dst)[k + cn] = ((uint16_t*)m)[1] * ((uint16_t)(src[k]) + (uint16_t)(src[k + 2 * cn])) + ((uint16_t*)m)[2] * src[k + cn];
+ dst[k + 2 * cn] = m[0] * src[k] + m[1] * src[k + cn] + m[2] * src[k + 2 * cn];
+ }
+ else
+ {
+ int idxm2 = borderInterpolate(-2, len, borderType)*cn;
+ int idxm1 = borderInterpolate(-1, len, borderType)*cn;
+ int idxp1 = borderInterpolate(3, len, borderType)*cn;
+ int idxp2 = borderInterpolate(4, len, borderType)*cn;
+ for (int k = 0; k < cn; k++)
+ {
+ ((uint16_t*)dst)[k] = ((uint16_t*)m)[2] * src[k] + ((uint16_t*)m)[1] * ((uint16_t)(src[k + cn]) + (uint16_t)(src[k + idxm1])) + ((uint16_t*)m)[0] * ((uint16_t)(src[k + 2 * cn]) + (uint16_t)(src[k + idxm2]));
+ ((uint16_t*)dst)[k + cn] = ((uint16_t*)m)[2] * src[k + cn] + ((uint16_t*)m)[1] * ((uint16_t)(src[k]) + (uint16_t)(src[k + 2 * cn])) + ((uint16_t*)m)[0] * ((uint16_t)(src[k + idxm1]) + (uint16_t)(src[k + idxp1]));
+ ((uint16_t*)dst)[k + 2 * cn] = ((uint16_t*)m)[0] * ((uint16_t)(src[k]) + (uint16_t)(src[k + idxp2])) + ((uint16_t*)m)[1] * ((uint16_t)(src[k + cn]) + (uint16_t)(src[k + idxp1])) + ((uint16_t*)m)[2] * src[k + 2 * cn];
+ }
+ }
+ }
+ else
+ {
+ // Points that fall left from border
+ if (borderType != BORDER_CONSTANT)// If BORDER_CONSTANT out of border values are equal to zero and could be skipped
+ {
+ int idxm2 = borderInterpolate(-2, len, borderType)*cn;
+ int idxm1 = borderInterpolate(-1, len, borderType)*cn;
+ for (int k = 0; k < cn; k++)
+ {
+ ((uint16_t*)dst)[k] = ((uint16_t*)m)[2] * src[k] + ((uint16_t*)m)[1] * ((uint16_t)(src[cn + k]) + (uint16_t)(src[idxm1 + k])) + ((uint16_t*)m)[0] * ((uint16_t)(src[2 * cn + k]) + (uint16_t)(src[idxm2 + k]));
+ ((uint16_t*)dst)[k + cn] = ((uint16_t*)m)[1] * ((uint16_t)(src[k]) + (uint16_t)(src[2 * cn + k])) + ((uint16_t*)m)[2] * src[cn + k] + ((uint16_t*)m)[0] * ((uint16_t)(src[3 * cn + k]) + (uint16_t)(src[idxm1 + k]));
+ }
+ }
+ else
+ {
+ for (int k = 0; k < cn; k++)
+ {
+ dst[k] = m[2] * src[k] + m[1] * src[cn + k] + m[0] * src[2 * cn + k];
+ ((uint16_t*)dst)[k + cn] = ((uint16_t*)m)[1] * ((uint16_t)(src[k]) + (uint16_t)(src[2 * cn + k])) + ((uint16_t*)m)[2] * src[cn + k] + ((uint16_t*)m)[0] * src[3 * cn + k];
+ }
+ }
+
+ src += 2 * cn; dst += 2 * cn;
+ int i = 2 * cn, lencn = (len - 2)*cn;
+ v_uint16x8 v_mul0 = v_setall_u16(*((uint16_t*)m));
+ v_uint16x8 v_mul1 = v_setall_u16(*((uint16_t*)(m + 1)));
+ v_uint16x8 v_mul2 = v_setall_u16(*((uint16_t*)(m + 2)));
+ for (; i <= lencn - 16; i += 16, src += 16, dst += 16)
+ {
+ v_uint16x8 v_src00, v_src01, v_src10, v_src11, v_src20, v_src21, v_src30, v_src31, v_src40, v_src41;
+ v_expand(v_load(src - 2 * cn), v_src00, v_src01);
+ v_expand(v_load(src - cn), v_src10, v_src11);
+ v_expand(v_load(src), v_src20, v_src21);
+ v_expand(v_load(src + cn), v_src30, v_src31);
+ v_expand(v_load(src + 2 * cn), v_src40, v_src41);
+ v_store((uint16_t*)dst, (v_src00 + v_src40) * v_mul0 + (v_src10 + v_src30)* v_mul1 + v_src20 * v_mul2);
+ v_store((uint16_t*)dst + 8, (v_src01 + v_src41) * v_mul0 + (v_src11 + v_src31) * v_mul1 + v_src21 * v_mul2);
+ }
+ for (; i < lencn; i++, src++, dst++)
+ *((uint16_t*)dst) = ((uint16_t*)m)[0] * ((uint16_t)(src[-2 * cn]) + (uint16_t)(src[2 * cn])) + ((uint16_t*)m)[1] * ((uint16_t)(src[-cn]) + (uint16_t)(src[cn])) + ((uint16_t*)m)[2] * src[0];
+
+ // Points that fall right from border
+ if (borderType != BORDER_CONSTANT)// If BORDER_CONSTANT out of border values are equal to zero and could be skipped
+ {
+ int idxp1 = (borderInterpolate(len, len, borderType) - (len - 2))*cn;
+ int idxp2 = (borderInterpolate(len + 1, len, borderType) - (len - 2))*cn;
+ for (int k = 0; k < cn; k++)
+ {
+ ((uint16_t*)dst)[k] = ((uint16_t*)m)[0] * ((uint16_t)(src[k - 2 * cn]) + (uint16_t)(src[idxp1 + k])) + ((uint16_t*)m)[1] * ((uint16_t)(src[k - cn]) + (uint16_t)(src[k + cn])) + ((uint16_t*)m)[2] * src[k];
+ ((uint16_t*)dst)[k + cn] = ((uint16_t*)m)[0] * ((uint16_t)(src[k - cn]) + (uint16_t)(src[idxp2 + k])) + ((uint16_t*)m)[1] * ((uint16_t)(src[k]) + (uint16_t)(src[idxp1 + k])) + ((uint16_t*)m)[2] * src[k + cn];
+ }
+ }
+ else
+ {
+ for (int k = 0; k < cn; k++)
+ {
+ ((uint16_t*)dst)[k] = ((uint16_t*)m)[0] * src[k - 2 * cn] + ((uint16_t*)m)[1] * ((uint16_t)(src[k - cn]) + (uint16_t)(src[k + cn])) + ((uint16_t*)m)[2] * src[k];
+ dst[k + cn] = m[0] * src[k - cn] + m[1] * src[k] + m[2] * src[k + cn];
+ }
+ }
+ }
+}
+template <typename ET, typename FT>