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;
#pragma comment(linker, "/STACK:200000000")
const double EPS = 1E-9;
const int INF = 1000000000;
const long long INF64 = (long long)1E18;
const double PI = 3.1415926535897932384626433832795;
const int MOD = INF + 7;
const int NMAX = 100;
int n, m;
long long z[NMAX][NMAX][NMAX][2];
long long rec(int row, int l, int r, bool fl) {
  if (row == 0) return 1;
  if (z[row][l][r][fl] != -1) return z[row][l][r][fl];
  long long res = 1;
  for (int nl = l; nl < r; nl++)
    for (int nr = nl + 1; nr <= r; nr++) {
      bool nfl = nl == l && nr == r;
      if (nfl && !fl) continue;
      res = (res + rec(row - 1, nl, nr, true)) % MOD;
    }
  return z[row][l][r][fl] = res;
}
int tupo() {
  memset(z, -1, sizeof(z));
  long long ans = 0;
  for (int i = 0; i < (int)(n); i++)
    for (int r = 0; r < (int)(m); r++)
      for (int l = 0; l < (int)(r); l++) {
        long long r1 = rec(i, l, r, false);
        long long r2 = rec(n - i - 1, l, r, true);
        ans = (ans + r1 * r2) % MOD;
      }
  return (int)ans;
}
long long sum_up[2][2100][2100], ups[2][2100][2100], upsk[2][2100][2100];
int solve() {
  for (int t = 0; t < (int)(2); t++) {
    {
      int i = 0;
      for (int j = 2; j <= m; j++) {
        long long up = 1;
        ups[t][i][j] = (up + ups[t][i][j - 1]) % MOD;
        upsk[t][i][j] = (up * j + upsk[t][i][j - 1]) % MOD;
        sum_up[t][i][j] = 1;
      }
    }
    for (int i = 1; i <= n; i++)
      for (int j = 2; j <= m; j++) {
        int brd = j - t;
        long long up =
            (ups[0][i - 1][brd] * (j + 1) - upsk[0][i - 1][brd] + MOD) % MOD;
        ups[t][i][j] = (up + ups[t][i][j - 1]) % MOD;
        upsk[t][i][j] = (up * j + upsk[t][i][j - 1]) % MOD;
        sum_up[t][i][j] = (up + sum_up[t][i - 1][j]) % MOD;
      }
  }
  long long ans = 0;
  for (int i = 0; i < (int)(n); i++)
    for (int len = 2; len <= m; len++)
      ans = (ans + sum_up[0][i][len] * sum_up[1][n - 1 - i][len] % MOD *
                       (m - len + 1)) %
            MOD;
  return (int)ans;
}
int main() {
  cin >> n >> m;
  cout << solve() << endl;
  return 0;
  for (n = 1; n <= 10; n++) {
    for (m = 1; m <= 10; m++) cout << tupo() << ' ';
    cout << endl;
  }
  cout << endl;
  for (n = 1; n <= 10; n++) {
    for (m = 1; m <= 10; m++) cout << solve() << ' ';
    cout << endl;
  }
  cout << endl;
  for (int sum = 1; sum <= 10; sum++) {
    for (n = 1; n < sum; n++) {
      m = sum - n;
      cout << tupo() << ' ';
    }
    cout << endl;
  }
  return 0;
}
