Problem: Let's define the transformation P of a sequence of integers a1, a2, ..., an as b1, b2, ..., bn, where bi = a1 | a2 | ... | ai for all i = 1, 2, ..., n, where | is the bitwise OR operation.

Vasya consequently applies the transformation P to all sequences of length n consisting of integers from 1 to 2k - 1 inclusive. He wants to know how many of these sequences have such property that their transformation is a strictly increasing sequence. Help him to calculate this number modulo 109 + 7.

Input

The only line of the input contains two integers n and k (1 ≤ n ≤ 1018, 1 ≤ k ≤ 30 000).

Output

Print a single integer — the answer to the problem modulo 109 + 7.

Examples

Input

1 2


Output

3


Input

2 3


Output

30


Input

3 3


Output

48

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
#pragma comment(linker, "/STACK:102400000,102400000")
#pragma GCC target("avx")
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
const int oo = 2139063143;
const int N = 1010000;
const int P = 1000000007;
using namespace std;
template <typename T>
inline void sc(T &x) {
  x = 0;
  static int p;
  p = 1;
  static char c;
  c = getchar();
  while (!isdigit(c)) {
    if (c == '-') p = -1;
    c = getchar();
  }
  while (isdigit(c)) {
    x = (x << 1) + (x << 3) + (c - 48);
    c = getchar();
  }
  x *= p;
}
template <typename T>
inline void print(T x) {
  if (x < 0) putchar('-'), x = -x;
  if (x >= 10) print(x / 10);
  putchar(x % 10 + '0');
}
template <typename T>
inline void pr(T x) {
  print(x), putchar('\n');
}
int del(int x) { return x >= P ? x - P : x; }
void add(int &x, int y) { x = del(x + y); }
void mul(int *a, int *b, int *c, int n) {
  if (n <= 8) {
    memset(c, 0, sizeof(int) * (n * 2 + 1));
    for (int i = 0; i < n; i++)
      for (int j = 0; j < n; j++) add(c[i + j], (long long)a[i] * b[j] % P);
    return;
  }
  int m = n >> 1;
  mul(a, b, c, m), mul(a + m, b + m, c + n, m);
  c[n - 1] = 0;
  int x[m], y[m], z[n];
  for (int i = 0; i < m; i++)
    x[i] = del(a[i] + a[i + m]), y[i] = del(b[i] + b[i + m]);
  mul(x, y, z, m);
  for (int i = 0; i < n; i++) add(z[i], P - del(c[i] + c[i + n]) % P);
  for (int i = 0; i < n; i++) add(c[i + m], z[i]);
}
int ksm(int a, int b) {
  int ans = 1;
  while (b) {
    if (b & 1) ans = (long long)ans * a % P;
    a = (long long)a * a % P, b >>= 1;
  }
  return ans;
}
int jc[N], inv[N];
void init(int n) {
  jc[0] = 1;
  for (int i = 1; i <= n; i++) jc[i] = (long long)i * jc[i - 1] % P;
  inv[n] = ksm(jc[n], P - 2);
  for (int i = n - 1; i >= 0; i--) inv[i] = (long long)(i + 1) * inv[i + 1] % P;
}
int C(int n, int m) { return (long long)jc[n] * inv[m] % P * inv[n - m] % P; }
int a[N], ans[N], c[N], d[N];
int main() {
  long long sb;
  int n, k;
  sc(sb), sc(k);
  if (sb > k) {
    pr(0);
    return 0;
  }
  init(k * 2 + 10);
  n = sb;
  for (int i = 1; i <= k; i++) a[i] = inv[i];
  ans[0] = 1;
  int g = 2;
  int K = 1;
  while (K < k + 1) K <<= 1;
  while (n) {
    if (n & 1) {
      for (int i = 0, y = 1; i <= k; i++, y = (long long)y * g % P)
        ans[i] = (long long)ans[i] * y % P;
      memset(c, 0, sizeof(int) * (K));
      mul(ans, a, c, K);
      memcpy(ans, c, sizeof(int) * (K));
    }
    for (int i = 0, y = 1; i <= k; i++, y = (long long)y * g % P)
      c[i] = (long long)a[i] * y % P;
    memset(d, 0, sizeof(int) * (K));
    mul(a, c, d, K);
    memcpy(a, d, sizeof(int) * (K));
    g = (long long)g * g % P;
    n >>= 1;
  }
  int an = 0;
  for (int i = 1; i <= k; i++) add(an, (long long)ans[i] * inv[k - i] % P);
  pr((long long)an * jc[k] % P);
  return 0;
}