#include <bits/stdc++.h>
using namespace std;
namespace fio {
streambuf* in = cin.rdbuf();
char bb[1000000], *s = bb, *t = bb;
inline int read() {
  int x = 0;
  char ch =
      (s == t && (t = (s = bb) + in->sgetn(bb, 1000000), s == t) ? EOF : *s++);
  while (ch < 48)
    ch = (s == t && (t = (s = bb) + in->sgetn(bb, 1000000), s == t) ? EOF
                                                                    : *s++);
  while (ch >= 48)
    x = x * 10 + ch - 48,
    ch = (s == t && (t = (s = bb) + in->sgetn(bb, 1000000), s == t) ? EOF
                                                                    : *s++);
  return x;
}
}  // namespace fio
using fio::read;
class integer {
 public:
  long long val;
  integer(long long val = 0) : val(val) {}
  integer& operator=(long long x) {
    val = x;
    return *this;
  }
  integer& operator=(integer x) {
    val = x.val;
    return *this;
  }
  integer operator+(integer x) { return integer((val + x.val) % 1000000007); }
  integer operator*(integer x) { return integer((val * x.val) % 1000000007); }
  bool operator==(integer x) { return val == x.val; }
  bool operator!=(integer x) { return val != x.val; }
  bool operator>(integer x) { return val > x.val; }
  bool operator<(integer x) { return val < x.val; }
  friend ostream& operator<<(ostream& in, integer x) {
    return (in << x.val, in);
  }
};
namespace sgt {
integer tree[4000000], tag[4000000];
void push_up(int id) { tree[id] = tree[id << 1] + tree[id << 1 | 1]; }
void push_down(int id, int l, int r) {
  if (tag[id] != -1) {
    tag[id << 1] = tag[id << 1 | 1] = tag[id];
    tree[id << 1] = tag[id] * (((l + r) >> 1) - l + 1);
    tree[id << 1 | 1] = tag[id] * (r - ((l + r) >> 1));
    tag[id] = -1;
  }
}
void build() { memset(tag, -1, sizeof(tag)); }
void set(int l, int r, int s, int t, integer v, int id) {
  if (r < s || l > t) return;
  if (s <= l && r <= t) {
    tag[id] = v;
    tree[id] = v * (1ll * r - l + 1);
    return;
  }
  push_down(id, l, r);
  set(l, ((l + r) >> 1), s, t, v, id << 1),
      set(((l + r) >> 1) + 1, r, s, t, v, id << 1 | 1);
  push_up(id);
}
integer query(int l, int r, int s, int t, int id) {
  if (r < s || l > t) return 0;
  if (s <= l && r <= t) return tree[id];
  push_down(id, l, r);
  return query(l, ((l + r) >> 1), s, t, id << 1) +
         query(((l + r) >> 1) + 1, r, s, t, id << 1 | 1);
}
}  // namespace sgt
class sg {
 public:
  int x, yd, yu, val;
  bool operator<(const sg nex) const {
    return x == nex.x ? yd == nex.yd ? yu > nex.yu : yd > nex.yd : x < nex.x;
  }
} sgx[200005];
set<pair<int, int> > alb;
int n, m, k;
int main() {
  n = read(), m = read(), k = read();
  sgt::build(), sgt::set(1, m, 1, 1, 1, 1);
  for (int i = 1; i <= k; i++) {
    int x1 = read(), y1 = read(), x2 = read(), y2 = read();
    sgx[2 * i - 1] = {x1, y1, y2, 1}, sgx[2 * i] = {x2 + 1, y1, y2, 0};
  }
  sort(sgx + 1, sgx + 2 * k + 1);
  int sc = 1;
  alb.insert({0, 0});
  while (sgx[sc].x == 1) alb.insert({sgx[sc].yd, sgx[sc].yu}), sc++;
  for (int i = 2; i <= n; i++) {
    for (int u = sc; sgx[u].x == i; u++)
      if (sgx[u].val && sgx[u].yu ^ m) {
        int dwn = (--alb.lower_bound({sgx[u].yu + 2, 0}))->second + 1;
        sgt::set(1, m, sgx[u].yu + 1, sgx[u].yu + 1,
                 sgt::query(1, m, dwn, sgx[u].yu + 1, 1), 1);
      }
    for (int u = sc; sgx[u].x == i; u++)
      if (!sgx[u].val) alb.erase(alb.find({sgx[u].yd, sgx[u].yu}));
    while (sgx[sc].x == i)
      if (sgx[sc].val)
        alb.insert({sgx[sc].yd, sgx[sc].yu}),
            sgt::set(1, m, sgx[sc].yd, sgx[sc].yu, 0, 1), sc++;
      else
        sc++;
  }
  int lst = (--alb.end())->first + 1;
  cout << sgt::query(1, m, lst, m, 1);
}
