Problem: A + B balls are arranged in a row. The leftmost A balls are colored red, and the rightmost B balls are colored blue.

You perform the following operation:

* First, you choose two integers s, t such that 1 \leq s, t \leq A + B.
* Then, you repeat the following step A + B times: In each step, you remove the first ball or the s-th ball (if it exists) or the t-th ball (if it exists, all indices are 1-based) from left in the row, and give it to Snuke.



In how many ways can you give the balls to Snuke? Compute the answer modulo 10^9 + 7.

Here, we consider two ways to be different if for some k, the k-th ball given to Snuke has different colors. In particular, the choice of s, t doesn't matter. Also, we don't distinguish two balls of the same color.

Constraints

* 1 \leq A, B \leq 2000

Input

Input is given from Standard Input in the following format:


A B


Output

Print the answer.

Examples

Input

3 3


Output

20


Input

4 4


Output

67


Input

7 9


Output

7772


Input

1987 1789


Output

456315553

Solution (in CPP):

Solution:
#include <cstdio>
#include <cstring>
#include <cassert>
#include <algorithm>
#include <vector>
#include <iostream>
#include <ctime>
#include <unistd.h>

using namespace std;

#define TRACE(x) cerr << #x <<  " = " << x << endl
#define _ << " " <<
#define FOR(i, a, b) for (int i=(a); i<(b); i++)
#define REP(i, n) FOR(i, 0, n)

#define X first
#define Y second

typedef pair<int, int> P;
typedef long long ll;

const int MOD = 1e9 + 7;

int add(int a, int b) {
  a += b;
  if (a >= MOD) a -= MOD;
  return a;
}

int mul(int a, int b) {
  return (int) (((ll) a * b) % MOD);
}

int sub(int a, int b) {
  a -= b;
  if (a < 0) a += MOD;
  return a;
}

int inv(int a) {
  int r=1;
  for (int e=MOD-2; e; e/=2, a = mul(a, a))
    if (e & 1)
      r = mul(r, a);

  return r;
}

const int MAX = 2005;

int fak[4*MAX], invfak[4*MAX];

void gen() {
  fak[0] = invfak[0] = 1;
  FOR(i, 1, 4*MAX) {
    fak[i] = mul(fak[i-1], i);
    invfak[i] = inv(fak[i]);
  }  
}

int povrh(int a, int b) {
  if (b < 0 || a < b) return 0;
  return mul(fak[a], mul(invfak[b], invfak[a-b]));
}

int dp[MAX][MAX], g[MAX][MAX];
int pot2[4*MAX];
int prefpov[MAX][MAX];

int rek(int A, int B) {
  assert(min(A, B) >= 0);
  if (dp[A][B] != -1) return dp[A][B];
  int ret=0;

  if (!A || !B) return 1;

  ret = rek(A-1, B);
  REP(k, min(A+1, B)) {
    int tmp = povrh(B-1, k);
    if (!tmp) continue;
    ret = add(ret, mul(tmp, g[A-k][k]));
  }

  //  TRACE(A _ B _ ret);
  return dp[A][B] = ret;
}

int main()
{
  pot2[0] = 1;
  FOR(i, 1, 4*MAX)
    pot2[i] = mul(pot2[i-1], 2);    
  
  gen();

  REP(i, MAX) {
    REP(j, i+1) {
      if (j) prefpov[i][j] = prefpov[i][j-1];
      prefpov[i][j] = add(prefpov[i][j], povrh(i, j));
      // if (i < 5 && j < 5)
      // 	TRACE(i _ j _ prefpov[i][j]);
    }
  }

  g[0][0] = 1;
  REP(A, MAX) {
    REP(B, MAX) {
      if (!A || !B) {
	g[A][B] = 1;
	continue;
      }

      g[A][B] = add(g[A-1][B], prefpov[B-1][min(B-1, A)]);

      //  if (A < 5 && B < 5) TRACE(A _ B _ g[A][B]);
    }
  }

  int A, B;
  scanf("%d%d", &A, &B);
  memset(dp, -1, sizeof dp);
  printf("%d\n", rek(A, B));

  return 0;
}