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:
#ifdef LOCAL
#define _GLIBCXX_DEBUG
#endif
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define fst first
#define snd second
#define forn(i, n) for (int i = 0; i < (int)(n); ++i)
#define ford(i, n) for (int i = ((int)(n) - 1); i >= 0; --i)
typedef long long ll;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vll;
typedef vector<char> vc;
typedef vector<vc> vvc;
typedef pair<int, int> pii;
typedef vector<pii> vii;
#define sz(c) (int)(c).size()
#define all(c) (c).begin(), (c).end()

#define left left___
#define right right__

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

int mult (int a, int b)
{
    return (ll)a * b % mod;
}
void add (int &a, int b)
{
    a += b;
    if (a >= mod)
        a -= mod;
}
void sub (int &a, int b)
{
    a -= b;
    if (a < 0)
        a += mod;
}

void solve (int r)
{
    int b;
    cin >> b;

    const int bnd = r + b + 1;
    vi fact(bnd, 1), ifact(bnd, 1), inv(bnd, 1);
    for (int i = 2; i < bnd; i++)
    {
        inv[i] = mod - mult(mod / i, inv[mod % i]);
        assert(mult(i, inv[i]) == 1);
        fact[i] = mult(fact[i - 1], i);
        ifact[i] = mult(ifact[i - 1], inv[i]);
    }

    auto C = [&] (int from, int what) -> int
    {
        if (from < what || what < 0)
            return 0;
        return mult(fact[from], mult(ifact[what], ifact[from - what]));
    };

    auto go = [&] (int dr, int db) -> int
    {
        if (db == 0)
            return 0;
        return C(dr + db - 1, dr);
    };

    int ans = 0;
    vvi bad_lose(b + 1, vi(r + 1));
    forn (curb, b + 1)
    {
        if (!curb)
            continue;

        vi pref(curb + 2);
        forn (i, curb + 2) if (i)
        {
            pref[i] = pref[i - 1];
            add(pref[i], C(curb, curb - (i - 1)));
        }

        forn (curr, r + 1)
        {
            int &cur = bad_lose[curb][curr];
            cur = C(curr + curb, curb);
            sub(cur, pref[min(curr, curb) + 1]);

 //           if (b == 3 && r == 3)
 //               fprintf(stderr, "bad_lose[b = %d][r = %d] = %d\n", curb, curr, bad_lose[curb][curr]);
        }
    }

    vvi lose(b + 1, vi(r + 1));
    forn (curb, b + 1)
    {
        forn (curr, r + 1)
        {
            if (curb)
                add(lose[curb][curr], bad_lose[curb - 1][curr]);
            if (curr)
                add(lose[curb][curr], lose[curb][curr - 1]);
        }
    }

    if (b)
    {
        forn (taker, r)
        {
            int remr = r - taker;
            int remb = b - 1;

            forn (b1, min(remr, remb) + 1)
            {
                int r1 = remr - b1;
                if (b1 == 0 || r1 == 0 || r1 > remr || b1 > remb)
                    continue;

                int ways = C(remr - r1 + remb - b1, remb - b1);
                ways = mult(ways, lose[b1][r1]);
                add(ans, ways);
            }
        }
    }

    {
        int rans = C(r + b, r);
        sub(rans, ans);
        ans = rans;
    }
    cout << ans << endl;
}

int main()
{
#ifdef LOCAL
    freopen("input.txt", "rt", stdin);
    freopen("output.txt", "w", stdout);
#endif // ONLINE_JUDGE

    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    while (cin >> n)
        solve(n);
}