#include <bits/stdc++.h>
using namespace std;
int i, j, m, n, p, k, Ans[1000005 * 4], Ans_add[1000005 * 4], Max[1000005 * 4],
    Max_add[1000005 * 4];
int sx, sy, ex, ey, change[1000005];
struct Node {
  int type, x, y;
};
vector<Node> block[1000005];
void jia(int &x, int y) {
  x += y;
  if (x >= 1000000007) x -= 1000000007;
}
void Ans_down(int t, int len) {
  if (Ans_add[t] == -1) return;
  Ans_add[(t << 1)] = Ans_add[((t << 1) + 1)] = 0;
  Ans[(t << 1)] = Ans[((t << 1) + 1)] = 0;
  Ans_add[t] = -1;
}
void ins(int ll, int rr, int c, int l, int r, int t) {
  if (ll <= l && r <= rr) {
    Ans[t] = 1ll * c * (r - l + 1) % 1000000007;
    Ans_add[t] = c;
  } else {
    Ans_down(t, r - l + 1);
    if (ll <= ((l + r) >> 1)) ins(ll, rr, c, l, ((l + r) >> 1), (t << 1));
    if (rr > ((l + r) >> 1))
      ins(ll, rr, c, ((l + r) >> 1) + 1, r, ((t << 1) + 1));
    Ans[t] = (Ans[(t << 1)] + Ans[((t << 1) + 1)]) % 1000000007;
  }
}
int getans(int ll, int rr, int l, int r, int t) {
  if (ll <= l && r <= rr) return Ans[t];
  Ans_down(t, r - l + 1);
  int S = 0;
  if (ll <= ((l + r) >> 1)) jia(S, getans(ll, rr, l, ((l + r) >> 1), (t << 1)));
  if (rr > ((l + r) >> 1))
    jia(S, getans(ll, rr, ((l + r) >> 1) + 1, r, ((t << 1) + 1)));
  return S;
}
void Max_down(int t, int l, int r) {
  if (Max_add[t] == -1) return;
  if (Max_add[t] == 0) {
    Max[(t << 1)] = Max[((t << 1) + 1)] = 0;
    Max_add[(t << 1)] = Max_add[((t << 1) + 1)] = 0;
  } else {
    Max[(t << 1)] = ((l + r) >> 1);
    Max[((t << 1) + 1)] = r;
    Max_add[(t << 1)] = Max_add[((t << 1) + 1)] = 1;
  }
  Max_add[t] = -1;
}
void update(int ll, int rr, int c, int l, int r, int t) {
  if (ll <= l && r <= rr) {
    Max_add[t] = c;
    if (c == 1)
      Max[t] = r;
    else
      Max[t] = 0;
  } else {
    Max_down(t, l, r);
    if (ll <= ((l + r) >> 1)) update(ll, rr, c, l, ((l + r) >> 1), (t << 1));
    if (rr > ((l + r) >> 1))
      update(ll, rr, c, ((l + r) >> 1) + 1, r, ((t << 1) + 1));
    Max[t] = max(Max[(t << 1)], Max[((t << 1) + 1)]);
  }
}
int FindMax(int ll, int rr, int l, int r, int t) {
  if (ll <= l && r <= rr) return Max[t];
  Max_down(t, l, r);
  int S = 0;
  if (ll <= ((l + r) >> 1))
    S = max(S, FindMax(ll, rr, l, ((l + r) >> 1), (t << 1)));
  if (rr > ((l + r) >> 1))
    S = max(S, FindMax(ll, rr, ((l + r) >> 1) + 1, r, ((t << 1) + 1)));
  return S;
}
inline int cmp(int a, int b) { return a > b; }
int main() {
  memset(Max_add, -1, sizeof(Max_add));
  memset(Ans_add, -1, sizeof(Ans_add));
  scanf("%d%d%d", &n, &m, &k);
  for (; k--;) {
    scanf("%d%d%d%d", &sx, &sy, &ex, &ey);
    block[sx].push_back((Node){1, sy, ey});
    block[ex + 1].push_back((Node){-1, sy, ey});
  }
  ins(1, 1, 1, 1, m, 1);
  for (i = 0; i < (int)block[1].size(); ++i)
    update(block[1][i].x, block[1][i].y, 1, 1, m, 1);
  for (j = 2; j <= n; ++j) {
    change[0] = 0;
    for (i = 0; i < (int)block[j].size(); ++i)
      if (block[j][i].type == 1) {
        int gg = block[j][i].y;
        if (gg == m) continue;
        change[++change[0]] = gg;
      }
    sort(change + 1, change + change[0] + 1, cmp);
    change[0] = unique(change + 1, change + change[0] + 1) - (change + 1);
    for (i = 1; i <= change[0]; ++i) {
      int gg = change[i];
      int lim = FindMax(1, gg + 1, 1, m, 1);
      if (lim == gg + 1) continue;
      ins(gg + 1, gg + 1, getans(lim + 1, gg + 1, 1, m, 1), 1, m, 1);
    }
    for (i = 0; i < (int)block[j].size(); ++i)
      if (block[j][i].type == -1)
        update(block[j][i].x, block[j][i].y, 0, 1, m, 1);
    for (i = 0; i < (int)block[j].size(); ++i)
      if (block[j][i].type == 1)
        update(block[j][i].x, block[j][i].y, 1, 1, m, 1),
            ins(block[j][i].x, block[j][i].y, 0, 1, m, 1);
  }
  printf("%d\n", getans(Max[1] + 1, m, 1, m, 1));
}
