#include <bits/stdc++.h>
using namespace std;
#define REP(i, n) for (long long i = 0, max_i = (n); i < max_i; i++)
template <class T>
ostream& operator<<(ostream& s, vector<T>& d) {
    REP(i, d.size()) s << d[i] << (i == d.size() - 1 ? "" : " ");
    return s;
}
using Int = long long;

template <typename T>
T pow(T a, long long n, T e = 1) {
    T ret = e;
    while (n) {
        if (n & 1) ret *= a;
        a *= a;
        n >>= 1;
    }
    return ret;
}

template <int mod>
struct ModInt {
    int x;
    ModInt() : x(0) {}
    ModInt(long long x_) {
        if ((x = x_ % mod + mod) >= mod) x -= mod;
    }
    ModInt& operator+=(ModInt rhs) {
        if ((x += rhs.x) >= mod) x -= mod;
        return *this;
    }
    ModInt& operator-=(ModInt rhs) {
        if ((x -= rhs.x) < 0) x += mod;
        return *this;
    }
    ModInt& operator*=(ModInt rhs) {
        x = (unsigned long long)x * rhs.x % mod;
        return *this;
    }
    ModInt& operator/=(ModInt rhs) {
        x = (unsigned long long)x * rhs.inv().x % mod;
        return *this;
    }

    ModInt operator-() const { return -x < 0 ? mod - x : -x; }
    ModInt operator+(ModInt rhs) const { return ModInt(*this) += rhs; }
    ModInt operator-(ModInt rhs) const { return ModInt(*this) -= rhs; }
    ModInt operator*(ModInt rhs) const { return ModInt(*this) *= rhs; }
    ModInt operator/(ModInt rhs) const { return ModInt(*this) /= rhs; }
    bool operator==(ModInt rhs) const { return x == rhs.x; }
    bool operator!=(ModInt rhs) const { return x != rhs.x; }
    ModInt inv() const { return pow(*this, mod - 2); }

    friend ostream& operator<<(ostream& s, ModInt<mod> a) {
        s << a.x;
        return s;
    }
    friend istream& operator>>(istream& s, ModInt<mod>& a) {
        s >> a.x;
        return s;
    }
};

using mint = ModInt<1000000007>;

constexpr int MAX_FACTORIAL = 202020;

mint fact[MAX_FACTORIAL];
mint factinv[MAX_FACTORIAL];

void init() {
    fact[0] = 1;
    for (int i = 1; i < MAX_FACTORIAL; i++) {
        fact[i] = fact[i - 1] * i;
    }
    factinv[MAX_FACTORIAL - 1] = fact[MAX_FACTORIAL - 1].inv();
    for (int i = MAX_FACTORIAL - 2; i >= 0; i--) {
        factinv[i] = factinv[i + 1] * (i + 1);
    }
    assert(factinv[0] == 1);
}

mint ncr(int n, int r) {
    if (r < 0 || r > n) return 0;
    return fact[n] * factinv[r] * factinv[n - r];
}

// https://arxiv.org/pdf/1407.2197.pdf
mint D(int a, int b, int s, int t) {
    if (a + t < b || b < a + s) return 0;
    mint ret = 0;
    int l = -1e9, r = 0;
    while (l < r - 1) {
        int m = (l + r) / 2;
        long long p = a - 1LL * m * (t - s + 2);
        long long q = a - 1LL * m * (t - s + 2) + t + 1;
        if (0 <= p && p <= a + b || 0 <= q && q <= a + b) {
            r = m;
        } else {
            l = m;
        }
    }
    int L = 0, R = 1e9;
    while (L < R - 1) {
        int m = (L + R) / 2;
        long long p = a - 1LL * m * (t - s + 2);
        long long q = a - 1LL * m * (t - s + 2) + t + 1;
        if (0 <= p && p <= a + b || 0 <= q && q <= a + b) {
            L = m;
        } else {
            R = m;
        }
    }
    for (int k = r; k <= L; k++) {
        mint f = ncr(a + b, a - k * (t - s + 2));
        f -= ncr(a + b, a - k * (t - s + 2) + t + 1);
        ret += f;
    }
    return ret;
}

// [0, n]のマス目内をm回移動する場合の数でスタート位置が0
mint ext_catalan(int n, int m) {
    if (n == 0) return 0;
    mint ret = 0;
    for (int i = 0; i <= m; i++) {
        ret += D(i, m - i, 0, n);
    }
    return ret;
}

mint solve(int n, int m) { return ext_catalan(n, m) - ext_catalan(n - 1, m); }

int main() {
    init();
    int n, m;
    cin >> n >> m;
    cout << solve(n - 1, m) << endl;
}



Measured memory_bytes: 4676