#include <bits/stdc++.h>
using namespace std;
inline int read() {
  int x = 0;
  char ch = getchar();
  while (ch < '0' || ch > '9') {
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') {
    x = x * 10 + ch - '0';
    ch = getchar();
  }
  return x;
}
const int MOD = 1000000007;
const int MAXN = 1000010;
int N, M, K, tp;
namespace SegmentTree {
struct SegmentTreeNode {
  int l, r, size, cov, sum;
} tree[MAXN << 2];
inline void Update(int p) {
  tree[p].sum = tree[(p << 1)].sum + tree[((p << 1) | 1)].sum;
  tree[p].sum %= MOD;
}
inline void BuildTree(int p, int l, int r) {
  tree[p].l = l;
  tree[p].r = r;
  tree[p].size = r - l + 1;
  tree[p].cov = -1;
  if (l == r) return;
  int mid = (l + r) >> 1;
  BuildTree((p << 1), l, mid);
  BuildTree(((p << 1) | 1), mid + 1, r);
  Update(p);
}
inline void cover(int p, int D) {
  tree[p].cov = D;
  tree[p].sum = (long long)tree[p].size * D % MOD;
}
inline void PushDown(int p) {
  if (tree[p].l == tree[p].r) return;
  if (tree[p].cov != -1)
    cover((p << 1), tree[p].cov), cover(((p << 1) | 1), tree[p].cov),
        tree[p].cov = -1;
}
inline void Cover(int p, int L, int R, int D) {
  if (R < L) return;
  int l = tree[p].l, r = tree[p].r;
  PushDown(p);
  if (L <= l && R >= r) {
    cover(p, D);
    return;
  }
  int mid = (l + r) >> 1;
  if (L <= mid) Cover((p << 1), L, R, D);
  if (R > mid) Cover(((p << 1) | 1), L, R, D);
  Update(p);
}
inline void Modify(int p, int pos, int D) {
  int l = tree[p].l, r = tree[p].r;
  PushDown(p);
  if (l == r) {
    cover(p, D);
    return;
  }
  int mid = (l + r) >> 1;
  if (pos <= mid)
    Modify((p << 1), pos, D);
  else
    Modify(((p << 1) | 1), pos, D);
  Update(p);
}
inline int Query(int p, int L, int R) {
  if (R < L) return 0;
  int l = tree[p].l, r = tree[p].r;
  PushDown(p);
  if (L <= l && R >= r) return tree[p].sum;
  int mid = (l + r) >> 1, re = 0;
  if (L <= mid) (re += Query((p << 1), L, R)) %= MOD;
  if (R > mid) (re += Query(((p << 1) | 1), L, R)) %= MOD;
  return re;
}
}  // namespace SegmentTree
struct LineNode {
  int x, y1, y2, f;
} Line[MAXN << 1];
bool cmp(LineNode A, LineNode B) {
  return A.x == B.x ? A.y1 == B.y1 ? A.y2 > B.y2 : A.y1 > B.y1 : A.x < B.x;
}
set<pair<int, int>> mp;
set<pair<int, int>>::iterator is;
pair<int, int> loc;
int main() {
  N = read(), M = read(), K = read();
  for (int x1, x2, y1, y2, i = 1; i <= K; i++) {
    x1 = read(), y1 = read(), x2 = read(), y2 = read(), Line[++tp].x = x1,
    Line[tp].y1 = y1, Line[tp].y2 = y2, Line[tp].f = 1, Line[++tp].x = x2 + 1,
    Line[tp].y1 = y1, Line[tp].y2 = y2, Line[tp].f = 0;
  }
  SegmentTree::BuildTree(1, 1, M);
  SegmentTree::Modify(1, 1, 1);
  sort(Line + 1, Line + tp + 1, cmp);
  int X = 1;
  for (int i = 1; Line[i].x == 1; X++, i++)
    if (Line[i].f) mp.insert(make_pair(Line[i].y1, Line[i].y2));
  mp.insert(make_pair(0, 0));
  for (int i = 2; i <= N; i++) {
    for (int j = X, tmp; Line[j].x == i; j++)
      if (Line[j].f)
        if (Line[j].y2 < M)
          loc = (*--mp.lower_bound(make_pair(Line[j].y2 + 2, 0))),
          tmp = SegmentTree::Query(1, loc.second + 1, Line[j].y2 + 1),
          SegmentTree::Modify(1, Line[j].y2 + 1, tmp);
    for (int j = X; Line[j].x == i; j++)
      if (!Line[j].f) mp.erase(make_pair(Line[j].y1, Line[j].y2));
    for (int j = X; Line[j].x == i; X++, j++)
      if (Line[j].f)
        mp.insert(make_pair(Line[j].y1, Line[j].y2)),
            SegmentTree::Cover(1, Line[j].y1, Line[j].y2, 0);
  }
  loc = *(--mp.end());
  printf("%d\n", SegmentTree::Query(1, loc.first + 1, M) % MOD);
  return 0;
}
