Problem: Little girl Masha likes winter sports, today she's planning to take part in slalom skiing.

The track is represented as a grid composed of n × m squares. There are rectangular obstacles at the track, composed of grid squares. Masha must get from the square (1, 1) to the square (n, m). She can move from a square to adjacent square: either to the right, or upwards. If the square is occupied by an obstacle, it is not allowed to move to that square.

One can see that each obstacle can actually be passed in two ways: either it is to the right of Masha's path, or to the left. Masha likes to try all ways to do things, so she would like to know how many ways are there to pass the track. Two ways are considered different if there is an obstacle such that it is to the right of the path in one way, and to the left of the path in the other way.

Help Masha to find the number of ways to pass the track. The number of ways can be quite big, so Masha would like to know it modulo 109 + 7.

The pictures below show different ways to pass the track in sample tests. <image> <image> <image>

Input

The first line of input data contains three positive integers: n, m and k (3 ≤ n, m ≤ 106, 0 ≤ k ≤ 105) — the size of the track and the number of obstacles.

The following k lines contain four positive integers each: x1, y1, x2, y2 (1 ≤ x1 ≤ x2 ≤ n, 1 ≤ y1 ≤ y2 ≤ m) — coordinates of bottom left, and top right squares of the obstacle. 

It is guaranteed that there are no obstacles at squares (1, 1) and (n, m), and no obstacles overlap (but some of them may touch).

Output

Output one integer — the number of ways to pass the track modulo 109 + 7.

Examples

Input

3 3 0


Output

1


Input

4 5 1
2 2 3 4


Output

2


Input

5 5 3
2 2 2 3
4 2 5 2
4 4 4 4


Output

3

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
const int inf = 0x3f3f3f3f, Inf = 0x7fffffff;
const long long INF = 0x7fffffffffffffff;
const double eps = 1e-8;
unsigned int seed = 19260817;
__inline__ __attribute__((always_inline)) unsigned int Rand() {
  return seed = seed * 998244353u + 1000000007u;
}
template <typename _Tp>
_Tp gcd(const _Tp &a, const _Tp &b) {
  return (!b) ? a : gcd(b, a % b);
}
template <typename _Tp>
__inline__ __attribute__((always_inline)) _Tp abs(const _Tp &a) {
  return a > 0 ? a : -a;
}
template <typename _Tp>
__inline__ __attribute__((always_inline)) _Tp max(const _Tp &a, const _Tp &b) {
  return a < b ? b : a;
}
template <typename _Tp>
__inline__ __attribute__((always_inline)) _Tp min(const _Tp &a, const _Tp &b) {
  return a < b ? a : b;
}
template <typename _Tp>
__inline__ __attribute__((always_inline)) void chmax(_Tp &a, const _Tp &b) {
  (a < b) && (a = b);
}
template <typename _Tp>
__inline__ __attribute__((always_inline)) void chmin(_Tp &a, const _Tp &b) {
  (a > b) && (a = b);
}
template <typename _Tp>
__inline__ __attribute__((always_inline)) bool _cmp(const double &a,
                                                    const double &b) {
  return abs(a - b) <= eps;
}
template <typename _Tp>
__inline__ __attribute__((always_inline)) void read(_Tp &x) {
  register char ch(getchar());
  bool f(false);
  while (ch < 48 || ch > 57) f |= ch == 45, ch = getchar();
  x = ch & 15, ch = getchar();
  while (ch >= 48 && ch <= 57)
    x = (((x << 2) + x) << 1) + (ch & 15), ch = getchar();
  if (f) x = -x;
}
template <typename _Tp, typename... Args>
__inline__ __attribute__((always_inline)) void read(_Tp &t, Args &...args) {
  read(t);
  read(args...);
}
__inline__ __attribute__((always_inline)) int read_str(char *s) {
  register char ch(getchar());
  while (ch < 65 || ch > 122 || (ch > 90 && ch < 97)) ch = getchar();
  register char *tar = s;
  *tar = ch, ch = getchar();
  while ((ch >= 65 && ch <= 90) || (ch >= 97 && ch <= 122))
    *(++tar) = ch, ch = getchar();
  return tar - s + 1;
}
const int N = 1000005, mod = 1000000007;
struct node {
  int x1, y1, x2, y2;
  __inline__ __attribute__((always_inline)) bool operator<(
      const node &o) const {
    return x1 < o.x1;
  }
} a[N];
std::vector<std::pair<int, int> > c[N << 1], d[N << 1];
int t[N << 1];
__inline__ __attribute__((always_inline)) void add(int &a, const int &b) {
  (a += b) >= mod && (a -= mod);
}
struct seg_tr {
  struct Node {
    int ls, rs;
    int sum;
    int tag;
  } f[N << 1];
  int node_cnt;
  __inline__ __attribute__((always_inline)) void PushUp(const int &x) {
    f[x].sum = f[f[x].ls].sum;
    add(f[x].sum, f[f[x].rs].sum);
  }
  __inline__ __attribute__((always_inline)) void cover(const int &cur) {
    f[cur].sum = 0;
    f[cur].tag = 1;
  }
  __inline__ __attribute__((always_inline)) void PushDown(const int &cur) {
    if (f[cur].tag) {
      cover(f[cur].ls);
      cover(f[cur].rs);
      f[cur].tag = 0;
    }
  }
  int build(const int &l, const int &r) {
    int cur = ++node_cnt;
    if (l == r) {
      return cur;
    }
    int mid = (l + r) >> 1;
    f[cur].ls = build(l, mid);
    f[cur].rs = build(mid + 1, r);
    return cur;
  }
  void Modify(const int &pos, const int &l, const int &r, const int &cur,
              const int &val) {
    if (l == r) {
      add(f[cur].sum, val);
      return;
    }
    int mid = (l + r) >> 1;
    PushDown(cur);
    if (pos <= mid)
      Modify(pos, l, mid, f[cur].ls, val);
    else
      Modify(pos, mid + 1, r, f[cur].rs, val);
    PushUp(cur);
  }
  void Update(const int &L, const int &R, const int &l, const int &r,
              const int &cur) {
    if (L <= l && r <= R) {
      cover(cur);
      return;
    }
    int mid = (l + r) >> 1;
    PushDown(cur);
    if (L <= mid) Update(L, R, l, mid, f[cur].ls);
    if (R > mid) Update(L, R, mid + 1, r, f[cur].rs);
    PushUp(cur);
  }
  int Query(const int &L, const int &R, const int &l, const int &r,
            const int &cur) {
    if (L <= l && r <= R) {
      return f[cur].sum;
    }
    int mid = (l + r) >> 1;
    PushDown(cur);
    return ((L <= mid ? Query(L, R, l, mid, f[cur].ls) : 0) +
            (R > mid ? Query(L, R, mid + 1, r, f[cur].rs) : 0)) %
           mod;
  }
} tr;
std::multiset<int, std::greater<int> > s;
int tmp[N << 1];
int main() {
  int n, m, k;
  read(n, m, k);
  int pos = 0;
  for (int i = 1; i <= k; ++i) {
    read(a[i].x1, a[i].y1, a[i].x2, a[i].y2);
    t[++pos] = a[i].x1;
    t[++pos] = a[i].x2 + 1;
  }
  std::sort(t + 1, t + pos + 1);
  int len = std::unique(t + 1, t + pos + 1) - t - 1;
  for (int i = 1; i <= k; ++i) {
    a[i].x1 = std::lower_bound(t + 1, t + len + 1, a[i].x1) - t;
    a[i].x2 = std::lower_bound(t + 1, t + len + 1, a[i].x2 + 1) - t;
    c[a[i].x1].push_back(std::make_pair(a[i].y2, a[i].y1));
    d[a[i].x2].push_back(std::make_pair(a[i].y2, a[i].y1));
  }
  s.insert(0);
  int root = tr.build(1, m);
  tr.Modify(1, 1, m, root, 1);
  for (int i = 1; i <= len; ++i) {
    if (t[i] == 1) {
      for (auto it : c[i]) {
        tr.Update(it.second, it.first, 1, m, root);
        s.insert(it.first);
        s.insert(it.second);
      }
      continue;
    }
    if (t[i] > n) {
      break;
    }
    int cnt = 0;
    for (auto it : c[i]) {
      auto IT = s.lower_bound(it.first + 1);
      ++cnt;
      if (*IT >= it.first)
        tmp[cnt] = 0;
      else
        tmp[cnt] = tr.Query((*IT) + 1, it.first, 1, m, root);
    }
    cnt = 0;
    for (auto it : c[i]) {
      if (it.first < m)
        tr.Modify(it.first + 1, 1, m, root, tmp[++cnt]);
      else
        ++cnt;
    }
    for (auto it : c[i]) {
      tr.Update(it.second, it.first, 1, m, root);
      s.insert(it.first);
      s.insert(it.second);
    }
    for (auto it : d[i]) {
      s.erase(s.find(it.first));
      s.erase(s.find(it.second));
    }
  }
  auto it = s.lower_bound(m);
  printf("%d\n", tr.Query((*it) + 1, m, 1, m, root));
  return 0;
}