Problem:
Score : 1600 points

Problem Statement

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.

Sample Input 1

3 3

Sample Output 1

20

There are 20 ways to give 3 red balls and 3 blue balls.
It turns out that all of them are possible.

Here is an example of the operation (r stands for red, b stands for blue):

You choose s = 3, t = 4.

Initially, the row looks like rrrbbb.

You remove 3rd ball (r) and give it to Snuke. Now the row looks like rrbbb.

You remove 4th ball (b) and give it to Snuke. Now the row looks like rrbb.

You remove 1st ball (r) and give it to Snuke. Now the row looks like rbb.

You remove 3rd ball (b) and give it to Snuke. Now the row looks like rb.

You remove 1st ball (r) and give it to Snuke. Now the row looks like b.

You remove 1st ball (b) and give it to Snuke. Now the row is empty.

This way, Snuke receives balls in the order rbrbrb.

Sample Input 2

4 4

Sample Output 2

67

There are 70 ways to give 4 red balls and 4 blue balls.
Among them, only bbrrbrbr, brbrbrbr, and brrbbrbr are impossible.

Sample Input 3

7 9

Sample Output 3

7772

Sample Input 4

1987 1789

Sample Output 4

456315553

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

#ifdef DEBUG
#define _GLIBCXX_DEBUG
#endif

#include <bits/stdc++.h>

using namespace std;

typedef long double ld;

#ifdef DEBUG
#define eprintf(...) fprintf(stderr, __VA_ARGS__), fflush(stderr)
#else
#define eprintf(...) ;
#endif

#define sz(x) ((int) (x).size())
#define TASK "text"

const int inf = (int) 1.01e9;
const long long infll = (long long) 1.01e18;
const ld eps = 1e-9;
const ld pi = acos((ld) -1);

mt19937 mrand(random_device{} ()); 

int rnd(int x) {
  return mrand() % x;
}

const int mod = (int) 1e9 + 7;

int mul(int a, int b) {
  return (long long) a * b % mod;
}

void add(int &a, int b) {
  a += b;
  if (a >= mod) {
    a -= mod;
  }
}

const int maxn = 4005;
int c[maxn][maxn];
int c1[maxn][maxn];
int p2[maxn];

void precalc() {
  for (int i = 0; i < maxn; i++) {
    c[i][0] = 1;
    for (int j = 1; j <= i; j++) {
      c[i][j] = c[i - 1][j - 1];
      add(c[i][j], c[i - 1][j]);
    }
  }
  for (int i = 0; i < maxn; i++) {
    c1[i][0] = 0;
    for (int j = 0; j + 1 < maxn; j++) {
      c1[i][j + 1] = c[i][j];
      add(c1[i][j + 1], c1[i][j]);
    }
  }
  p2[0] = 1;
  for (int i = 1; i < maxn; i++) {
    p2[i] = mul(p2[i - 1], 2);
  }
}

int a, b;

int read() {
  if (scanf("%d%d", &a, &b) < 2) {
    return false;
  }
  return true;
}

int dp[maxn][maxn];

void solve() {
  memset(dp, 0, sizeof(dp));
  int res = 1;
  for (int i = 0; i <= a; i++) {
    for (int j = 0; j < b; j++) {
      int s = i + j;
      int fst = a - s;
      if (fst < 0 || fst >= a) {
        continue;
      }
      int dx = a - fst - i, dy = b - 1 - j;
      dp[i][j] = c[dx + dy][dx];
      add(res, dp[i][j]);
    }
  }
  for (int i = a; i > 0; i--) {
    for (int j = b; j > 0; j--) {
      auto &cur = dp[i][j];
      add(cur, dp[i + 1][j]);
      int x = i, y = j - 1;
      if (y <= x) {
        add(res, mul(cur, p2[y]));
      } else {
        int tomul = c1[y][x + 1];
        add(tomul, mod - c1[y][0]);
        add(res, mul(cur, tomul));
      }
    }
  }
  printf("%d\n", res);
}

int main() {
  precalc();
#ifdef DEBUG
  assert(freopen(TASK ".in", "r", stdin));
  assert(freopen(TASK ".out", "w", stdout));
#endif
  while (read()) {
    solve();
#ifdef DEBUG
    eprintf("Time %.2f\n", (double) clock() / CLOCKS_PER_SEC);
#endif
  }
  return 0;
}