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
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <algorithm>
#include <complex>
#include <functional>
#include <bitset>
#include <map>
#include <random>
#include <memory>
#include <map>
#include <valarray>
#include <iomanip>
#include <queue>

#include <cassert>
#include <ctime>
#include <cmath>
#include <cstdlib>

using namespace std;

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

int C (int n, int k)
{
    static vector<vector<int>> dp (4001, vector<int> (2001, -1));

    if (n - k < k)
        return C (n, n - k);

    if (k <= 0)
        return k == 0 ? 1 : 0;

    if (dp[n][k] == -1)
        dp[n][k] = (C (n - 1, k - 1) + C (n - 1, k)) % inf;

    return dp[n][k];
}

template<class T>
T sqr (T x)
{
    return x * x;
}

int powmod (int x, int y)
{
    return y ? (y & 1 ? x * (long long)powmod (x, y - 1) :
                sqr ((long long)powmod (x, y >> 1))) % inf : 1;
}

int H (int a, int b)
{
    static vector<vector<int>> dp (2001, vector<int> (2001, -1));

    if (a < 0 || b < 0)
        return 0;

    if (b == 0 || a == 0)
        return 1;

    if (dp[a][b] == -1)
    {
        dp[a][b] = H (a, b - 1) + H (a - 1, b - 1);
        dp[a][b] %= inf;
    }

    return dp[a][b];
}

int F (int a, int b)
{
    static vector<vector<int>> dp (2001, vector<int> (2001, -1));

    if (a < 0 || b < 0)
        return 0;

    if (b == 0 || a == 0)
        return 1;

    if (dp[a][b] == -1)
    {
        dp[a][b] = 0;

        dp[a][b] = F (a - 1, b);

        int tb = b - 1;

        if (a >= tb)
        {
            dp[a][b] += powmod (2, b - 1);
            dp[a][b] %= inf;
        }
        else
        {
            dp[a][b] += H (a, b - 1);
            dp[a][b] %= inf;
            //for (int l = 0; l <= a; l++)
            //{
            //    dp[a][b] += C (b - 1, l);
            //    dp[a][b] %= inf;
            //}
        }
    }

    return dp[a][b];
}

int G (int a, int b)
{
    int ans = 0;

    for (int k = 0; k <= a; k++)
        for (int l = 0; l <= min (a, b - 1); l++)
            ans = (ans + C (b - 1, l) * (long long)F (a - k - l, l)) % inf;

    return ans;
}

int main ()
{
    ios_base::sync_with_stdio (false);
    cin.tie (nullptr);

    //int n;

    //cin >> n;

    //string s;

    //cin >> s;

    //vector<vector<int>> blocks (1);

    //int zer = 2;

    //for (int i = s.find ('1'); i < blocks.size (); i++)
    //{
    //    if (s[i] == '1')
    //    {
    //        if (zer > 1)
    //            blocks.push_back (vector<int> (1, 1));
    //        else if (zer == 1)
    //            blocks.back ().push_back (1);
    //        else
    //            blocks.back ().back ()++;

    //        zer = 0;
    //    }
    //    else
    //        zer++;
    //}

    //int ans;

    //for (const auto &row : blocks)
    //{
    //    for ()
    //}

    int a, b;

    cin >> a >> b;

    //for (int i = 0; i < 1001; i++)
    //    for (int j = 0; j < 1001; j++)
    //        F (i, j);

    //cout << clock () << endl;

    cout << G (a, b) << endl;

    return 0;
}
