// iostream is too mainstream
#include <cstdio>
// bitch please
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <list>
#include <chrono>
#include <random>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cstring>
#include <iomanip>
#define dibs reserve
#define OVER9000 1234567890
#define tisic 47
#define soclose 1e-8
#define patkan 9
#define ff first
#define ss second
#define abs(x) (((x) < 0)?-(x):(x))
using uint = unsigned int;
using cat = long long;
using dbl = long double;
constexpr dbl pi = 3.14159265358979323846;
using namespace std;

#ifdef DONLINE_JUDGE
	// palindromic tree is better than splay tree!
	#define lld I64d
#endif

int main() {
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cout << fixed << setprecision(10);
	int N, M;
	cin >> N >> M;
	cat mod = 1000000007;
	vector<cat> cnt(M+1, 0);
	for(int i = 1; i <= M; i++) cnt[i] = 1;
	vector<cat> pw(M+1, 1), pw_inv(M+1, 1);
	for(int i = 1; i <= M; i++) pw[i] = 2 * pw[i-1] % mod;
	cat inv = (mod+1)/2; // 2*inv % mod == 1
	for(int i = 1; i <= M; i++) pw_inv[i] = inv * pw_inv[i-1] % mod;
	for(int i = 0; i < N; i++) {
		vector<cat> cnt_nw(M+1, 0);
		cat s = 0;
		for(int j = 1; j <= M; j++) {
			s += cnt[j-1] * pw_inv[j-1] % mod * (j-1);
			cnt_nw[j] = (s % mod * pw[j-1] + cnt[j] * (j+1)) % mod;
		}
		cnt = cnt_nw;
	}
	cout << cnt[M] << "\n";
	return 0;
}

// look at my code
// my code is amazing
