Greg has a pad. The pad's screen is an n × m rectangle, each cell can be either black or white. We'll consider the pad rows to be numbered with integers from 1 to n from top to bottom. Similarly, the pad's columns are numbered with integers from 1 to m from left to right.

Greg thinks that the pad's screen displays a cave if the following conditions hold:

  * There is a segment [l, r] (1 ≤ l ≤ r ≤ n), such that each of the rows l, l + 1, ..., r has exactly two black cells and all other rows have only white cells. 
  * There is a row number t (l ≤ t ≤ r), such that for all pairs of rows with numbers i and j (l ≤ i ≤ j ≤ t) the set of columns between the black cells in row i (with the columns where is these black cells) is the subset of the set of columns between the black cells in row j (with the columns where is these black cells). Similarly, for all pairs of rows with numbers i and j (t ≤ i ≤ j ≤ r) the set of columns between the black cells in row j (with the columns where is these black cells) is the subset of the set of columns between the black cells in row i (with the columns where is these black cells). 



Greg wondered, how many ways there are to paint a cave on his pad. Two ways can be considered distinct if there is a cell that has distinct colors on the two pictures.

Help Greg.

Input

The first line contains two integers n, m — the pad's screen size (1 ≤ n, m ≤ 2000).

Output

In the single line print the remainder after dividing the answer to the problem by 1000000007 (109 + 7).

Examples

Input

1 1


Output

0


Input

4 4


Output

485


Input

3 5


Output

451
#include <bits/stdc++.h>
using namespace std;
template <class INT>
inline INT SolveLinear(INT a, INT b) {
  if (b == 0) {
    assert(a == 1);
    return 0;
  } else {
    INT q = a / b, r = a % b;
    INT x = SolveLinear(b, r);
    INT y = (1 - a * x) / b;
    if (y < 0) {
      return a + y;
    } else {
      return y;
    }
  }
}
template <class INT, INT mod>
class Counting {
 public:
  inline Counting(INT val = 0) {
    x = val % mod;
    if (x < 0) {
      x = mod + x;
    }
  }
  inline Counting(const Counting<INT, mod>& origin) { x = origin.x; }
  inline Counting<INT, mod> operator=(const Counting<INT, mod>& origin) {
    x = origin.x;
    return *this;
  }
  inline Counting<INT, mod> operator+(const Counting<INT, mod>& b) const {
    return Counting<INT, mod>(x + b.x);
  }
  inline Counting<INT, mod> operator-() const { return Counting<INT, mod>(-x); }
  inline Counting<INT, mod> operator-(const Counting<INT, mod>& b) const {
    return Counting<INT, mod>(x - b.x);
  }
  inline Counting<INT, mod> operator*(const Counting<INT, mod>& b) const {
    return Counting<INT, mod>(x * b.x);
  }
  inline Counting<INT, mod> operator/(const Counting<INT, mod>& b) const {
    return Counting<INT, mod>(x * SolveLinear(mod, b.x));
  }
  INT x;
};
template <class Int>
class CombViaMd {
 public:
  CombViaMd(int n) {
    fact = new Int[n + 1];
    inv_fact = new Int[n + 1];
    fact[0] = 1;
    inv_fact[0] = 1;
    for (int i = 1; i <= n; ++i) {
      fact[i] = fact[i - 1] * (Int)(i);
      inv_fact[i] = inv_fact[i - 1] / (Int)(i);
    }
  }
  ~CombViaMd() {
    delete[] fact;
    delete[] inv_fact;
  }
  Int SafeComb(int i, int j) {
    if (j == 0) return 1;
    if (j < 0 || j > i) {
      return 0;
    } else {
      return fact[i] * inv_fact[j] * inv_fact[i - j];
    }
  }
  Int Comb(int i, int j) { return fact[i] * inv_fact[j] * inv_fact[i - j]; }
  Int *fact, *inv_fact;
  int size;
};
CombViaMd<Counting<long long, 1000000007> > cn(6010);
Counting<long long, 1000000007> ans = 0, f1[2010], f2[2010], s1[2010], s2[2010],
                                ff[2010];
int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= m; ++i)
    for (int j = i + 1; j <= m; ++j) ff[j - i] = ff[j - i] + 1;
  for (int i = 1; i <= m - 1; ++i) {
    for (int j = 0; j <= n - 1; ++j) {
      f1[j] = cn.SafeComb(i + j + j - 1, j + j);
      f2[j] = cn.SafeComb(i + j + j - 2, j + j) * 2 -
              cn.SafeComb(i + j + j - 3, j + j);
    }
    s1[0] = f1[0];
    s2[0] = f2[0];
    for (int j = 1; j <= n - 1; ++j) s1[j] = f1[j] + s1[j - 1];
    for (int j = 1; j <= n - 1; ++j) s2[j] = f2[j] + s2[j - 1];
    Counting<long long, 1000000007> tmp = 0;
    for (int j = 1; j <= n; ++j) tmp = tmp + s1[j - 1] * s2[n - j];
    ans = ans + tmp * ff[i];
  }
  printf("%d\n", ans.x);
}
