#include <bits/stdc++.h>


#define clz __builtin_clzll
#define popcount __builtin_popcountll
#define FORS(i, s, n) for (i64 i = (s); i < (n); ++i)
#define RFORS(i, s, n) for (i64 i = (n)-1; i >= (s); --i)
#define FOR(i, n) FORS(i, 0, n)
#define RFOR(i, n) RFORS(i, 0, n)
#define FI(n) FOR(i, n)
#define RFI(n) RFOR(i, n)
#define ALL(x) (x).begin(), (x).end()
#define RALL(x) (x).rbegin(), (x).rend()
#define SZ(c) i64((c).size())
#define FOR_SETTED_BIT(bit, mask) for (int bit = 0; (mask) >> bit; ++bit) if (1&(mask >> bit))
#define FOR_NONZERO_SUBMASK(submask, mask) for (int submask=(mask); submask; submask=(submask-1)&(mask))
#define PI (3.141592653589793L)
#define MODULO ((i64)1e9+7LL)


using namespace std;

typedef int_fast8_t i8;
typedef int_fast16_t i16;
typedef int_fast32_t i32;
typedef int_fast64_t i64;
typedef uint_fast8_t u8;
typedef uint_fast16_t u16;
typedef uint_fast32_t u32;
typedef uint_fast64_t u64;
typedef pair<i64, i64> pi64;
typedef vector<i8> vb;
typedef vector<i32> vi32;
typedef vector<i64> vi64;
typedef vector<vi64> vvi64;
typedef vector<list<int>> AdjacencyLists;
typedef vector<list<pair<int, i64>>> WeightedAdjacencyLists;
typedef vvi64 AdjacencyMatrix;

template<class T> inline T sqr(const T &x) { return x * x; }
inline i64 sqr(int x){return sqr<i64>(x);}
template<class T>T binpow(const T &a, i64 n) { return n == T(0) ? T(1) : sqr(binpow(a, n / 2))* (n % 2 ? a : T(1)); }
i64 binpow(i64 a, i64 n, i64 modulo) { return n == 0 ? 1 : sqr(binpow(a, n / 2, modulo)) % modulo * (n % 2 ? a : 1) % modulo;}
constexpr inline i64 phi (i64 n) {
  i64 result = n;
  for (i64 i = 2; i * i <= n; ++i)
    if (n % i == 0) {
        while (n % i == 0)
          n /= i;
        result -= result / i;
    }
  if (n > 1)
    result -= result / n;
  return result;
}

inline vi64 inverseAll(i64 m)
{
  vi64 r(m);
  r[1] = 1;

  for (int i = 2; i < m; ++i)
    r[i] = (m - (m/i) * r[m%i] % m) % m;
  return r;
}
i64 gcd(i64 a, i64 b, i64 &x, i64 &y)
{
  if (a == 0)
  {
    x = 0;
    y = 1;
    return b;
  }
  i64 x1, y1;
  i64 d = gcd(b%a, a, x1, y1);
  x = y1 - (b / a) * x1;
  y = x1;
  return d;
}
inline i64 gcd(i64 a, i64 b) { return gcd(a, b, a, b); }
inline i64 lcm(i64 a, i64 b) { return a / gcd(a, b) * b; }

template<class T, const T modulo, class TT=i64>
class IntModulo {
  constexpr static const T order = phi(modulo);
  
  T value;
public:
  explicit IntModulo(const TT &value = 0) : value(T(((abs(value) + modulo - TT(1)) / modulo * modulo + value) % modulo)) {}
  
  inline IntModulo& operator += (const IntModulo &i) { value = T((TT(value) + TT(i.value)) % modulo); return *this; }
  inline IntModulo& operator -= (const IntModulo &i) { return *this += -i; }
  inline IntModulo& operator *= (const IntModulo &i) { value = T((TT(value) * TT(i.value)) % modulo); return *this; }
  inline IntModulo& operator /= (const IntModulo &i) { return *this *= i.inverse(); };
    
  inline IntModulo inverse() const { return binpow(*this, order - 1); };
  
  inline operator T() const { return value; }
  
  friend inline IntModulo operator - (const IntModulo &i) { return IntModulo<T, modulo, TT>(modulo - i.value); }

  friend inline bool operator == (const IntModulo &a, const IntModulo &b) { return a.value == b.value; }
};

template<class T, const T modulo, class TT=i64>
inline IntModulo<T, modulo, TT> operator + (const IntModulo<T, modulo, TT> &a, const IntModulo<T, modulo, TT> &b) { return IntModulo<T, modulo, TT>(a) += b; }

template<class T, const T modulo, class TT=i64>
inline IntModulo<T, modulo, TT> operator - (const IntModulo<T, modulo, TT> &a, const IntModulo<T, modulo, TT> &b) { return IntModulo<T, modulo, TT>(a) -= b; }

template<class T, const T modulo, class TT=i64>
inline IntModulo<T, modulo, TT> operator * (const IntModulo<T, modulo, TT> &a, const IntModulo<T, modulo, TT> &b) { return IntModulo<T, modulo, TT>(a) *= b; }

template<class T, const T modulo, class TT=i64>
inline IntModulo<T, modulo, TT> operator / (const IntModulo<T, modulo, TT> &a, const IntModulo<T, modulo, TT> &b) { return IntModulo<T, modulo, TT>(a) /= b; }

template<class T, const T modulo, class TT=i64>
inline bool operator != (const IntModulo<T, modulo, TT> &a, const IntModulo<T, modulo, TT> &b) { return !(a == b); }


mt19937_64 rng(
#ifdef DEBUG
               0LL
#else
               chrono::steady_clock::now().time_since_epoch().count()
#endif
               );
inline i64 random(i64 low, i64 high) { return uniform_int_distribution<i64>(low, high)(rng); }
inline i64 random(i64 high=numeric_limits<i64>::max()) { return random(0, high); }
#define rand random


struct Dinic {
  struct Edge {
    int u, v;
    i64 cap, flow;
    Edge() {}
    Edge(int u, int v, i64 cap): u(u), v(v), cap(cap), flow(0) {}
  };
  
  int N;
  vector<Edge> E;
  vector<vector<int>> g;
  vector<int> d, pt;
  
  Dinic(int N): N(N), E(0), g(N), d(N), pt(N) {}
  
  void AddEdge(int u, int v, i64 cap) {
    if (u != v) {
      E.emplace_back(Edge(u, v, cap));
      g[u].emplace_back(E.size() - 1);
      E.emplace_back(Edge(v, u, 0));
      g[v].emplace_back(E.size() - 1);
    }
  }
  
  bool BFS(int S, int T) {
    queue<int> q({S});
    fill(d.begin(), d.end(), N + 1);
    d[S] = 0;
    while(!q.empty()) {
      int u = q.front(); q.pop();
      if (u == T) break;
      for (int k: g[u]) {
        Edge &e = E[k];
        if (e.flow < e.cap && d[e.v] > d[e.u] + 1) {
          d[e.v] = d[e.u] + 1;
          q.emplace(e.v);
        }
      }
    }
    return d[T] != N + 1;
  }
  
  i64 DFS(int u, int T, i64 flow = -1) {
    if (u == T || flow == 0) return flow;
    for (int &i = pt[u]; i < g[u].size(); ++i) {
      Edge &e = E[g[u][i]];
      Edge &oe = E[g[u][i]^1];
      if (d[e.v] == d[e.u] + 1) {
        i64 amt = e.cap - e.flow;
        if (flow != -1 && amt > flow) amt = flow;
        if (i64 pushed = DFS(e.v, T, amt)) {
          e.flow += pushed;
          oe.flow -= pushed;
          return pushed;
        }
      }
    }
    return 0;
  }
  
  i64 MaxFlow(int S, int T) {
    i64 total = 0;
    while (BFS(S, T)) {
      fill(pt.begin(), pt.end(), 0);
      while (i64 flow = DFS(S, T))
        total += flow;
    }
    return total;
  }
};

vi64 Dijkstra(const WeightedAdjacencyLists &g, int s) {
  vi64 d(SZ(g), numeric_limits<i64>::max() / 2LL);
  priority_queue < pair<i64, int> > q;
  
  d[s] = 0;
  q.emplace(-0, s);
  
  while (!q.empty()) {
    if (q.top().first > d[q.top().second]) {
      q.pop();
      
      continue;
    }
    int v = q.top().second;
    
    q.pop();
    
    for (const auto &cw : g[v])
    {
      if (d[v] + cw.second < d[cw.first])
      {
        d[cw.first] = d[v] + cw.second;
        q.emplace(-d[cw.first], cw.first);
      }
    }
  }
  
  return d;
}


struct UnionFind {
    vi64 parent;
    vi64 rank;
    UnionFind(i64 n) : parent(n), rank(n) {
        for (i64 i = 0; i < n; ++i) {
            parent[i] = i;
            rank[i] = 0;
        }
    }
    i64 find_set (i64 v) {
        if (v == parent[v])
            return v;
        return parent[v] = find_set (parent[v]);
    }
    void union_sets (i64 a, i64 b) {
        a = find_set (a);
        b = find_set (b);
        if (a != b) {
            if (rank[a] < rank[b])
                swap (a, b);
            parent[b] = a;
            if (rank[a] == rank[b])
                ++rank[a];
        }
    }
};

// https://codeforces.com/blog/entry/18051
template < class T >
const T assign(const T& a, const T& b) { return b; }

template< class T >
const T& my_min(const T& a, const T& b) { return a < b ? a : b; }

template< class T>
struct SegmentTree {
  typedef function<T(T, T)> Function;

  const i64 n;
  vector<T> t;
  const function<T(const T&, const T&)> operation;
  const T &operation_default_value;
  const function<T(const T&, const T&)> modification;
  const T &modification_default_value;
  
  SegmentTree() {}
  
  SegmentTree(const i64 n,
              Function operation,
              const T &operation_default_value=T(),
              Function modification=assign<T>,
              const T &modification_default_value=T()
  ) :
    n(n),
    t(n << 1, operation_default_value),
    operation(operation),
    operation_default_value(operation_default_value),
    modification(modification),
    modification_default_value(modification_default_value)
  {
    build();
  }
    
  template < class Iterator >
  SegmentTree(const Iterator &begin,
              const Iterator &end,
              Function operation,
              const T &operation_default_value=T(),
              Function modification=assign<T>,
              const T &modification_default_value=T()
  ) : SegmentTree(end - begin,
                  operation,
                  operation_default_value,
                  modification,
                  modification_default_value)
  {
    copy(begin, end, t.begin() + n);
    build();
  }
  
  void build() {
    for (i64 i = n - 1; i > 0; --i) t[i] = operation(t[i<<1], t[i<<1|1]);
  }
  
  void modify(i64 p, const T &value) {
    p += n;
    
    for (t[p] = modification(t[p], value); p > 1; p >>= 1) t[p>>1] = operation(t[p], t[p^1]);
  }
  
  T query(i64 l, i64 r) const {  // [l, r)
    T res = operation_default_value;
    for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
        if (l&1) res = operation(res, t[l++]);
        if (r&1) res = operation(res, t[--r]);
    }
    return res;
  }
};

vi64 factorial;

inline i64 inv(i64 n) {
  return binpow(n, MODULO - 2, MODULO);
}

inline i64 choose(i64 n, i64 k) {
  return factorial[n] * inv(factorial[n - k]) % MODULO * inv(factorial[k]) % MODULO;
}

inline i64 choose_with_repetitions(i64 n, i64 k) {
  return choose(n + k - 1, k);
}

inline i64 solve(i64 n, i64 k) {
  
  factorial.resize(2 * n + 1);
  
  factorial[0] = 1;
  FORS(i, 1, SZ(factorial)) {
    factorial[i] = factorial[i - 1] * i % MODULO;
  }

  if (k >= n) {
    return choose(2 * n - 1, n);
  }
  i64 answer = 0;
  
  for (i64 zeros = 0; zeros <= k; ++zeros) {
    i64 current = choose_with_repetitions(n - zeros, zeros) * choose(n, zeros) % MODULO;
#ifdef DEBUG
    cout << current << endl;
#endif
    answer += current;
    answer %= MODULO;
  }
  
  return answer;
}

//set<vi32> bf(const vi32 &c, i64 k) {
//  if (k == 0) {
//    return {c};
//  }
//
//  const auto n = SZ(c);
//  set<vi32> answer;
//  vi64 offset(n, 1);
//
//  do {
//    vi32 cc(n, 0);
//    i32 jj = 0;
//
//    FI(n) {
//      FOR(j, c[i]) {
//        ++cc[(i + offset[jj + j]) % n];
//      }
//      jj += c[i];
//    }
//
//    const auto current = bf(cc, k - 1);
//    answer.insert(ALL(current));
//
//    i32 carry = 1;
//
//    FI(n) {
//      if ((offset[i] += carry) >= n) {
//        offset[i] = 1;
//      } else {
//        carry = 0;
//        break;
//      }
//    }
//
//    if (carry) {
//      break;
//    }
//
//  }while (true);
//
//  return answer;
//}
//
//i64 bf(i64 n, i64 k) {
//  vi32 c(n, 1);
//
//  const auto a = bf(c, k);
//
//  for (const auto &c : a) {
//    FI(n) {
//      cout << c[i] << ' ';
//    }
//    cout << endl;
//  }
//  cout << endl;
//
//  return SZ(a);
//}

int main(int argc, const char * argv[]) {
#ifdef DEBUG
  assert(solve(3, 2) == 10);
//  for (i64 n = 3; ; ++n) {
//    i64 k = 2;
//    cout << n << ' ' << k << endl;
//    const auto output = solve(n, k);
//    const auto answer = bf(n, k);
//    cout << output << ' ' << answer << endl;
//
//    assert(output == answer);
//  }
//
//  for(i32 nk = 5; ; ++nk)
//  {
//    for (i32 n = 3; n + 2 <= nk; ++n) {
//      i32 k = nk - n;
//
//      cout << n << ' ' << k << endl;
//      const auto output = solve(n, k);
//      const auto answer = bf(n, k);
//      cout << output << ' ' << answer << endl;
//
//      assert(output == answer);
//    }
//  }
#endif
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.precision(13);
  cout.setf(ios::fixed);
  srand((unsigned int)time(NULL));
   
  i64 n, k;
//
  while (cin >> n >> k) {
    cout << solve(n, k) << endl;
  }


  return 0;
}



Measured memory_bytes: 3328