#include <bits/stdc++.h>
namespace fstdlib {
const int maxn = 1 << 19, mod = 998244353;
class poly {
 private:
  std::vector<int> data;

 public:
  poly(std::size_t len = std::size_t(0)) { data = std::vector<int>(len); }
  poly(const std::vector<int> &b) { data = b; }
  poly(const std::vector<int> &b, int len) {
    data = b;
    data.resize(len);
  }
  poly(const poly &b, int len) {
    data = b.data;
    data.resize(len);
  }
  void resize(std::size_t len, int val = 0) { data.resize(len, val); }
  std::size_t size(void) const { return data.size(); }
  void clear(void) { data.clear(); }
  int &operator[](std::size_t b) { return data[b]; }
  const int &operator[](std::size_t b) const { return data[b]; }
  poly operator*(const poly &h) const;
  poly operator*=(const poly &h);
  poly operator*(const int &h) const;
  poly operator*=(const int &h);
  poly operator+(const poly &h) const;
  poly operator+=(const poly &h);
  poly operator-(const poly &h) const;
  poly operator-=(const poly &h);
  poly operator<<(const std::size_t &b) const;
  poly operator<<=(const std::size_t &b);
  poly operator>>(const std::size_t &b) const;
  poly operator>>=(const std::size_t &b);
  poly operator/(const int &h) const;
  poly operator/=(const int &h);
  poly operator==(const poly &h) const;
  poly operator!=(const poly &h) const;
  poly inv(void) const;
  poly inv(const int &h) const;
  friend poly sqrt(const poly &h);
};
int qpow(int a, int b, int p = mod) {
  int res = 1;
  while (b) {
    if (b & 1) res = (long long)res * a % p;
    a = (long long)a * a % p, b >>= 1;
  }
  return res;
}
int rev[maxn];
void dft_for_module(std::vector<int> &f, int n, int b) {
  static int w[maxn];
  for (int i = 0; i < n; ++i)
    if (i < rev[i]) std::swap(f[i], f[rev[i]]);
  for (int i = 2; i <= n; i <<= 1) {
    w[0] = 1, w[1] = qpow(3, (mod - 1) / i);
    if (b == -1) w[1] = qpow(w[1], mod - 2);
    for (int j = 2; j < i / 2; ++j) w[j] = (long long)w[j - 1] * w[1] % mod;
    for (int j = 0; j < n; j += i)
      for (int k = 0; k < i / 2; ++k) {
        int p = f[j + k], q = (long long)f[j + k + i / 2] * w[k] % mod;
        f[j + k] = (p + q) % mod, f[j + k + i / 2] = (p - q + mod) % mod;
      }
  }
}
poly poly::operator*(const poly &h) const {
  int N = 1;
  while (N < (int)(size() + h.size() - 1)) N <<= 1;
  std::vector<int> f(this->data), g(h.data);
  f.resize(N), g.resize(N);
  for (int i = 0; i < N; ++i)
    rev[i] = (rev[i >> 1] >> 1) | (i & 1 ? N >> 1 : 0);
  dft_for_module(f, N, 1), dft_for_module(g, N, 1);
  for (int i = 0; i < N; ++i) f[i] = (long long)f[i] * g[i] % mod;
  dft_for_module(f, N, -1), f.resize(size() + h.size() - 1);
  for (int i = 0, inv = qpow(N, mod - 2); i < (int)f.size(); ++i)
    f[i] = (long long)f[i] * inv % mod;
  return f;
}
poly poly::operator*=(const poly &h) { return *this = *this * h; }
poly poly::operator*(const int &h) const {
  std::vector<int> f(size());
  for (int i = 0; i < (int)f.size(); ++i) f[i] = (long long)f[i] * h % mod;
  return f;
}
poly poly::operator*=(const int &h) {
  for (int i = 0; i < (int)size(); ++i) data[i] = (long long)data[i] * h % mod;
  return *this;
}
poly poly::operator+(const poly &h) const {
  std::vector<int> f(this->data);
  if (f.size() < h.size()) f.resize(h.size());
  for (int i = 0; i < (int)h.size(); ++i) f[i] = (f[i] + h[i]) % mod;
  return f;
}
poly poly::operator+=(const poly &h) {
  std::vector<int> &f = this->data;
  if (f.size() < h.size()) f.resize(h.size());
  for (int i = 0; i < (int)h.size(); ++i) f[i] = (f[i] + h[i]) % mod;
  return f;
}
poly poly::operator-(const poly &h) const {
  std::vector<int> f(this->data);
  if (f.size() < h.size()) f.resize(h.size());
  for (int i = 0; i < (int)h.size(); ++i) f[i] = (f[i] - h[i] + mod) % mod;
  return f;
}
poly poly::operator-=(const poly &h) {
  std::vector<int> &f = this->data;
  if (f.size() < h.size()) f.resize(h.size());
  for (int i = 0; i < (int)h.size(); ++i) f[i] = (f[i] - h[i] + mod) % mod;
  return f;
}
poly poly::operator<<(const std::size_t &b) const {
  std::vector<int> f(size() + b);
  for (int i = 0; i < (int)size(); ++i) f[i + b] = data[i];
  return f;
}
poly poly::operator<<=(const std::size_t &b) { return *this = (*this) << b; }
poly poly::operator>>(const std::size_t &b) const {
  std::vector<int> f(size() - b);
  for (int i = 0; i < (int)f.size(); ++i) f[i] = data[i + b];
  return f;
}
poly poly::operator>>=(const std::size_t &b) { return *this = (*this) >> b; }
poly poly::operator/(const int &h) const {
  std::vector<int> f(this->data);
  int inv = qpow(h, mod - 2);
  for (int i = 0; i < (int)f.size(); ++i) f[i] = (long long)f[i] * inv % mod;
  return f;
}
poly poly::operator/=(const int &h) {
  int inv = qpow(h, mod - 2);
  for (int i = 0; i < (int)data.size(); ++i)
    data[i] = (long long)data[i] * inv % mod;
  return *this;
}
poly poly::inv(void) const {
  int N = 1;
  while (N < (int)(size() + size() - 1)) N <<= 1;
  std::vector<int> f(N), g(N), d(this->data);
  d.resize(N), f[0] = qpow(d[0], mod - 2);
  for (int w = 2; w < N; w <<= 1) {
    for (int i = 0; i < w; ++i) g[i] = d[i];
    for (int i = 0; i < w * 2; ++i)
      rev[i] = (rev[i >> 1] >> 1) | (i & 1 ? w : 0);
    dft_for_module(f, w << 1, 1), dft_for_module(g, w << 1, 1);
    for (int i = 0; i < w * 2; ++i)
      f[i] = (long long)f[i] * (2 - (long long)f[i] * g[i] % mod) % mod;
    dft_for_module(f, w << 1, -1);
    for (int i = 0, inv = qpow(w << 1, mod - 2); i < w; ++i)
      f[i] = (long long)f[i] * inv % mod;
    for (int i = w; i < w * 2; ++i) f[i] = 0;
  }
  f.resize(size());
  for (int i = 0; i < (int)f.size(); ++i) f[i] = (f[i] + mod) % mod;
  return f;
}
poly poly::operator==(const poly &h) const {
  if (size() != h.size()) return 0;
  for (int i = 0; i < (int)size(); ++i)
    if (data[i] != h[i]) return 0;
  return 1;
}
poly poly::operator!=(const poly &h) const {
  if (size() != h.size()) return 1;
  for (int i = 0; i < (int)size(); ++i)
    if (data[i] != h[i]) return 1;
  return 0;
}
poly poly::inv(const int &h) const { return poly(*this, h).inv(); }
int modsqrt(int h, int p = mod) { return 1; }
poly sqrt(const poly &h) {
  int N = 1;
  while (N < (int)(h.size() + h.size() - 1)) N <<= 1;
  poly f(N), g(N), d(h);
  d.resize(N), f[0] = modsqrt(d[0]);
  for (int w = 2; w < N; w <<= 1) {
    g.resize(w);
    for (int i = 0; i < w; ++i) g[i] = d[i];
    f = (f + f.inv(w) * g) / 2;
    f.resize(w);
  }
  f.resize(h.size());
  return f;
}
struct comp {
  long double x, y;
  comp(long double _x = 0, long double _y = 0) : x(_x), y(_y) {}
  comp operator*(const comp &b) const {
    return comp(x * b.x - y * b.y, x * b.y + y * b.x);
  }
  comp operator+(const comp &b) const { return comp(x + b.x, y + b.y); }
  comp operator-(const comp &b) const { return comp(x - b.x, y - b.y); }
  comp conj(void) { return comp(x, -y); }
};
const int EPS = 1e-15;
template <typename FLOAT_T>
FLOAT_T fabs(const FLOAT_T &x) {
  return x > 0 ? x : -x;
}
template <typename FLOAT_T>
FLOAT_T sin(const FLOAT_T &x, const long double &EPS = fstdlib::EPS) {
  FLOAT_T res = 0, delt = x;
  int d = 0;
  while (fabs(delt) > EPS) {
    res += delt, ++d;
    delt *= -x * x / ((2 * d) * (2 * d + 1));
  }
  return res;
}
template <typename FLOAT_T>
FLOAT_T cos(const FLOAT_T &x, const long double &EPS = fstdlib::EPS) {
  FLOAT_T res = 0, delt = 1;
  int d = 0;
  while (fabs(delt) > EPS) {
    res += delt, ++d;
    delt *= -x * x / ((2 * d) * (2 * d - 1));
  }
  return res;
}
const long double PI = std::acos((long double)(-1));
void dft_for_complex(std::vector<comp> &f, int n, int b) {
  static comp w[maxn];
  for (int i = 0; i < n; ++i)
    if (i < rev[i]) std::swap(f[i], f[rev[i]]);
  for (int i = 2; i <= n; i <<= 1) {
    w[0] = comp(1, 0), w[1] = comp(cos(2 * PI / i), b * sin(2 * PI / i));
    for (int j = 2; j < i / 2; ++j) w[j] = w[j - 1] * w[1];
    for (int j = 0; j < n; j += i)
      for (int k = 0; k < i / 2; ++k) {
        comp p = f[j + k], q = f[j + k + i / 2] * w[k];
        f[j + k] = p + q, f[j + k + i / 2] = p - q;
      }
  }
}
class arbitary_module_poly {
 private:
  std::vector<int> data;
  int construct_element(int D, long long x, long long y, long long z) const {
    x %= mod, y %= mod, z %= mod;
    return ((long long)D * D * x % mod + (long long)D * y % mod + z) % mod;
  }

 public:
  int mod;
  arbitary_module_poly(std::size_t len = std::size_t(0),
                       int module_value = 1e9 + 7) {
    mod = module_value;
    data = std::vector<int>(len);
  }
  arbitary_module_poly(const std::vector<int> &b, int module_value = 1e9 + 7) {
    mod = module_value;
    data = b;
  }
  arbitary_module_poly(const arbitary_module_poly &b, int len) {
    mod = b.mod;
    data = b.data;
    data.resize(len);
  }
  void resize(std::size_t len, const int &val = 0) { data.resize(len, val); }
  std::size_t size(void) const { return data.size(); }
  void clear(void) { data.clear(); }
  int &operator[](std::size_t b) { return data[b]; }
  const int &operator[](std::size_t b) const { return data[b]; }
  arbitary_module_poly operator*(const arbitary_module_poly &h) const;
  arbitary_module_poly operator*=(const arbitary_module_poly &h);
  arbitary_module_poly operator*(const int &h) const;
  arbitary_module_poly operator*=(const int &h);
  arbitary_module_poly operator+(const arbitary_module_poly &h) const;
  arbitary_module_poly operator+=(const arbitary_module_poly &h);
  arbitary_module_poly operator-(const arbitary_module_poly &h) const;
  arbitary_module_poly operator-=(const arbitary_module_poly &h);
  arbitary_module_poly operator<<(const std::size_t &b) const;
  arbitary_module_poly operator<<=(const std::size_t &b);
  arbitary_module_poly operator>>(const std::size_t &b) const;
  arbitary_module_poly operator>>=(const std::size_t &b);
  arbitary_module_poly operator/(const int &h) const;
  arbitary_module_poly operator/=(const int &h);
  arbitary_module_poly operator==(const arbitary_module_poly &h) const;
  arbitary_module_poly operator!=(const arbitary_module_poly &h) const;
  arbitary_module_poly inv(void) const;
  arbitary_module_poly inv(const int &h) const;
  friend arbitary_module_poly sqrt(const arbitary_module_poly &h);
};
arbitary_module_poly arbitary_module_poly::operator*(
    const arbitary_module_poly &h) const {
  int N = 1;
  while (N < (int)(size() + h.size() - 1)) N <<= 1;
  std::vector<comp> f(N), g(N), p(N), q(N);
  const int D = std::sqrt(mod);
  for (int i = 0; i < (int)size(); ++i)
    f[i].x = data[i] / D, f[i].y = data[i] % D;
  for (int i = 0; i < (int)h.size(); ++i) g[i].x = h[i] / D, g[i].y = h[i] % D;
  for (int i = 0; i < N; ++i)
    rev[i] = (rev[i >> 1] >> 1) | (i & 1 ? N >> 1 : 0);
  dft_for_complex(f, N, 1), dft_for_complex(g, N, 1);
  for (int i = 0; i < N; ++i) {
    p[i] = (f[i] + f[(N - i) % N].conj()) * comp(0.50, 0) * g[i];
    q[i] = (f[i] - f[(N - i) % N].conj()) * comp(0, -0.5) * g[i];
  }
  dft_for_complex(p, N, -1), dft_for_complex(q, N, -1);
  std::vector<int> r(size() + h.size() - 1);
  for (int i = 0; i < (int)r.size(); ++i)
    r[i] = construct_element(D, p[i].x / N + 0.5, (p[i].y + q[i].x) / N + 0.5,
                             q[i].y / N + 0.5);
  return arbitary_module_poly(r, mod);
}
arbitary_module_poly arbitary_module_poly::operator*=(
    const arbitary_module_poly &h) {
  return *this = *this * h;
}
arbitary_module_poly arbitary_module_poly::operator*(const int &h) const {
  std::vector<int> f(this->data);
  for (int i = 0; i < (int)f.size(); ++i) f[i] = (long long)f[i] * h % mod;
  return arbitary_module_poly(f, mod);
}
arbitary_module_poly arbitary_module_poly::operator*=(const int &h) {
  for (int i = 0; i < (int)size(); ++i) data[i] = (long long)data[i] * h % mod;
  return *this;
}
arbitary_module_poly arbitary_module_poly::operator+(
    const arbitary_module_poly &h) const {
  std::vector<int> f(this->data);
  if (f.size() < h.size()) f.resize(h.size());
  for (int i = 0; i < (int)h.size(); ++i) f[i] = (f[i] + h[i]) % mod;
  return arbitary_module_poly(f, mod);
}
arbitary_module_poly arbitary_module_poly::operator+=(
    const arbitary_module_poly &h) {
  if (size() < h.size()) resize(h.size());
  for (int i = 0; i < (int)h.size(); ++i) data[i] = (data[i] + h[i]) % mod;
  return *this;
}
arbitary_module_poly arbitary_module_poly::operator-(
    const arbitary_module_poly &h) const {
  std::vector<int> f(this->data);
  if (f.size() < h.size()) f.resize(h.size());
  for (int i = 0; i < (int)h.size(); ++i) f[i] = (f[i] + mod - h[i]) % mod;
  return arbitary_module_poly(f, mod);
}
arbitary_module_poly arbitary_module_poly::operator-=(
    const arbitary_module_poly &h) {
  if (size() < h.size()) resize(h.size());
  for (int i = 0; i < (int)h.size(); ++i)
    data[i] = (data[i] + mod - h[i]) % mod;
  return *this;
}
arbitary_module_poly arbitary_module_poly::operator<<(
    const std::size_t &b) const {
  std::vector<int> f(size() + b);
  for (int i = 0; i < (int)size(); ++i) f[i + b] = data[i];
  return arbitary_module_poly(f, mod);
}
arbitary_module_poly arbitary_module_poly::operator<<=(const std::size_t &b) {
  return *this = (*this) << b;
}
arbitary_module_poly arbitary_module_poly::operator>>(
    const std::size_t &b) const {
  std::vector<int> f(size() - b);
  for (int i = 0; i < (int)f.size(); ++i) f[i] = data[i + b];
  return arbitary_module_poly(f, mod);
}
arbitary_module_poly arbitary_module_poly::operator>>=(const std::size_t &b) {
  return *this = (*this) >> b;
}
arbitary_module_poly arbitary_module_poly::inv(void) const {
  int N = 1;
  while (N < (int)(size() + size() - 1)) N <<= 1;
  arbitary_module_poly f(1, mod), g(N, mod), h(*this), f2(1, mod);
  f[0] = qpow(data[0], mod - 2, mod), h.resize(N), f2[0] = 2;
  for (int w = 2; w < N; w <<= 1) {
    g.resize(w);
    for (int i = 0; i < w; ++i) g[i] = h[i];
    f = f * (f * g - f2) * (mod - 1);
    f.resize(w);
  }
  return arbitary_module_poly(f, size());
}
arbitary_module_poly arbitary_module_poly::inv(const int &h) const {
  return arbitary_module_poly(*this, h).inv();
}
arbitary_module_poly arbitary_module_poly::operator/(const int &h) const {
  int inv = qpow(h, mod - 2, mod);
  std::vector<int> f(this->data);
  for (int i = 0; i < (int)f.size(); ++i) f[i] = (long long)f[i] * inv % mod;
  return arbitary_module_poly(f, mod);
}
arbitary_module_poly arbitary_module_poly::operator/=(const int &h) {
  int inv = qpow(h, mod - 2, mod);
  for (int i = 0; i < (int)size(); ++i)
    data[i] = (long long)data[i] * inv % mod;
  return *this;
}
arbitary_module_poly arbitary_module_poly::operator==(
    const arbitary_module_poly &h) const {
  if (size() != h.size() || mod != h.mod) return 0;
  for (int i = 0; i < (int)size(); ++i)
    if (data[i] != h[i]) return 0;
  return 1;
}
arbitary_module_poly arbitary_module_poly::operator!=(
    const arbitary_module_poly &h) const {
  if (size() != h.size() || mod != h.mod) return 1;
  for (int i = 0; i < (int)size(); ++i)
    if (data[i] != h[i]) return 1;
  return 0;
}
arbitary_module_poly sqrt(const arbitary_module_poly &h) {
  int N = 1;
  while (N < (int)(h.size() + h.size() - 1)) N <<= 1;
  arbitary_module_poly f(1, mod), g(N, mod), d(h, N);
  f[0] = modsqrt(h[0], mod);
  for (int w = 2; w < N; w <<= 1) {
    g.resize(w);
    for (int i = 0; i < w; ++i) g[i] = d[i];
    f = (f + f.inv(w) * g) / 2;
    f.resize(w);
  }
  return arbitary_module_poly(f, h.size());
}
}  // namespace fstdlib
using fstdlib::cos;
using fstdlib::sin;
using fstdlib::sqrt;
const int maxn = 3e4 + 19, mod = 1e9 + 7;
int qpow(int a, int b) {
  int res = 1;
  while (b) {
    if (b & 1) res = (long long)res * a % mod;
    a = (long long)a * a % mod, b >>= 1;
  }
  return res;
}
long long n;
int k, fact[maxn], ifact[maxn], shift[maxn], ans;
int binom(int n, int m) {
  return (long long)fact[n] * ifact[n - m] % mod * ifact[m] % mod;
}
int main() {
  scanf("%lld%d", &n, &k);
  if (n > k) {
    puts("0");
    return 0;
  }
  fact[0] = 1;
  for (int i = 1; i <= k; ++i) fact[i] = (long long)fact[i - 1] * i % mod;
  ifact[k] = qpow(fact[k], mod - 2);
  for (int i = k - 1; i >= 0; --i)
    ifact[i] = (long long)ifact[i + 1] * (i + 1) % mod;
  shift[0] = 1;
  for (int i = 1; i <= k; ++i) shift[i] = shift[i - 1] * 2 % mod;
  fstdlib::arbitary_module_poly f(k + 1, mod), g(k + 1, mod), h(k + 1, mod);
  for (int i = 1; i <= k; ++i) f[i] = (long long)ifact[i] % mod;
  for (int i = 1; i <= k; ++i) g[i] = f[i];
  int b = n - 1, c = 1;
  while (b) {
    if (b & 1) {
      for (int i = 0; i < (int)f.size(); ++i)
        f[i] = (long long)f[i] * qpow(2, i * c) % mod;
      f = f * g, f.resize(k + 1);
    }
    for (int i = 0; i < (int)g.size(); ++i)
      h[i] = (long long)g[i] * qpow(2, i * c) % mod;
    b >>= 1, c <<= 1, g *= h, g.resize(k + 1);
  }
  for (int i = n; i <= k; ++i)
    ans = (ans + (long long)f[i] * fact[i] % mod * binom(k, i)) % mod;
  printf("%d\n", ans);
  return 0;
}
