+static av_always_inline int
+svq3_fetch_diagonal_mv(const SVQ3Context *s, const int16_t **C,
+ int i, int list, int part_width)
+{
+ const int topright_ref = s->ref_cache[list][i - 8 + part_width];
+
+ if (topright_ref != PART_NOT_AVAILABLE) {
+ *C = s->mv_cache[list][i - 8 + part_width];
+ return topright_ref;
+ } else {
+ *C = s->mv_cache[list][i - 8 - 1];
+ return s->ref_cache[list][i - 8 - 1];
+ }
+}
+
+/**
+ * Get the predicted MV.
+ * @param n the block index
+ * @param part_width the width of the partition (4, 8,16) -> (1, 2, 4)
+ * @param mx the x component of the predicted motion vector
+ * @param my the y component of the predicted motion vector
+ */
+static av_always_inline void svq3_pred_motion(const SVQ3Context *s, int n,
+ int part_width, int list,
+ int ref, int *const mx, int *const my)
+{
+ const int index8 = scan8[n];
+ const int top_ref = s->ref_cache[list][index8 - 8];
+ const int left_ref = s->ref_cache[list][index8 - 1];
+ const int16_t *const A = s->mv_cache[list][index8 - 1];
+ const int16_t *const B = s->mv_cache[list][index8 - 8];
+ const int16_t *C;
+ int diagonal_ref, match_count;
+
+/* mv_cache
+ * B . . A T T T T
+ * U . . L . . , .
+ * U . . L . . . .
+ * U . . L . . , .
+ * . . . L . . . .
+ */
+
+ diagonal_ref = svq3_fetch_diagonal_mv(s, &C, index8, list, part_width);
+ match_count = (diagonal_ref == ref) + (top_ref == ref) + (left_ref == ref);
+ if (match_count > 1) { //most common
+ *mx = mid_pred(A[0], B[0], C[0]);
+ *my = mid_pred(A[1], B[1], C[1]);
+ } else if (match_count == 1) {
+ if (left_ref == ref) {
+ *mx = A[0];
+ *my = A[1];
+ } else if (top_ref == ref) {
+ *mx = B[0];
+ *my = B[1];
+ } else {
+ *mx = C[0];
+ *my = C[1];
+ }
+ } else {
+ if (top_ref == PART_NOT_AVAILABLE &&
+ diagonal_ref == PART_NOT_AVAILABLE &&
+ left_ref != PART_NOT_AVAILABLE) {
+ *mx = A[0];
+ *my = A[1];
+ } else {
+ *mx = mid_pred(A[0], B[0], C[0]);
+ *my = mid_pred(A[1], B[1], C[1]);
+ }
+ }
+}
+