#include <cstdio>
#define NDEBUG
#include <cassert>
#include <algorithm>
#include <iostream>
using namespace std;

#define PNAME "barrack"

#ifdef LOCAL_TEST
#define FNAME PNAME "2"
// #define FNAME "test"
#else
#define FNAME PNAME
#endif

struct mod_int
{
	static const int mod = int(1e9) + 7;
	int x;
	
	void _add(int &_x, int y) { _x += y; if (_x >= mod) _x -= mod; }
	void _mv(int &_x) { _add(_x, mod); }
	
	template<class T>
	mod_int(T y)
	{
		x = (static_cast<int>(y) % mod + mod) % mod;
	}
	// mod_int(const mod_int& m) : x(m.x) { }
	mod_int() : x(0) { }
	
	mod_int& operator+=(const mod_int md)
	{
		_add(x, md.x);
		return *this;
	}
	
	mod_int& operator-=(const mod_int md)
	{
		int tmp = mod;
		_add(tmp, -md.x);
		_add(x, tmp);
		// assert(x >= 0);
		return *this;
	}
	
	mod_int& operator*=(const mod_int md)
	{
		x = 1ull * x * md.x % mod;
		return *this;
	}
	
	#define setop(op) \
	mod_int operator op (const mod_int md) const\
	{\
		mod_int ret = *this;\
		ret op##= md;\
		return ret;\
	}
	setop(+)
	setop(-)
	setop(*)
	
	friend ostream& operator<<(ostream& os, const mod_int& m)
	{
		os << m.x;
		return os;
	}
};

const int max_n = 500000, max_m = 1000000;

mod_int dp[max_n][3], pre[max_n + 1], suf[max_n + 1], tp[max_m + 1];
int hd[max_n], des[max_m * 2], nxt[max_m * 2], e_cnt = 0;
int thd[max_n], tdes[max_n * 2], tnxt[max_n * 2], siz[max_n], esz[max_n], bel[max_n], s_cnt = 0;
int dfn[max_n], low[max_n], stk[max_n], stp = 0, ind = 0;
bool inst[max_n], iscut[max_m];

void add(int s, int t)
{
	des[e_cnt] = t;
	nxt[e_cnt] = hd[s];
	hd[s] = e_cnt++;
}

void tadd(int s, int t)
{
	tdes[e_cnt] = t;
	tnxt[e_cnt] = thd[s];
	thd[s] = e_cnt++;
}

inline void chmin(int &x, int y) { if (x > y) x = y; }
void tarjan(int id, int fa)
{
	dfn[id] = low[id] = ind++;
	stk[stp++] = id, inst[id] = true;
	
	for (int p = hd[id]; p != -1; p = nxt[p])
	{
		if (dfn[des[p]] == -1)
		{
			tarjan(des[p], id);
			// cerr << id << " " << des[p] << " " << low[des[p]] << " " << low[id] << endl;
			if (low[des[p]] > dfn[id])
				iscut[p >> 1] = true;
			chmin(low[id], low[des[p]]);
		}
		else if (inst[des[p]] && des[p] != fa)
			chmin(low[id], dfn[des[p]]);
	}
}

void getnd(int id)
{
	if (bel[id] != -1)
	{
		assert(bel[id] == s_cnt);
		return;
	}
	bel[id] = s_cnt;
	siz[s_cnt]++;
	
	for (int p = hd[id]; p != -1; p = nxt[p])
		if (!iscut[p >> 1])
			getnd(des[p]);
}

// 0：subtree里面有 外面无
// 1：subtree里面无 外面有
// 2：both
void dfs(int id, int fa)
{
	dp[id][1] = dp[id][2] = 1;
	for (int p = thd[id], dst; p != -1; p = tnxt[p])
	{
		dst = tdes[p];
		if (dst != fa)
		{
			dfs(dst, id);
			dp[id][1] *= dp[dst][1];
			dp[id][2] *= (dp[dst][1] + dp[dst][2]);
		}
	}
	dp[id][2] *= tp[siz[id]];
	// cerr << dp[id][0] << endl;
	dp[id][2] -= dp[id][1];
	dp[id][0] = dp[id][2];
	// cerr << dp[id][2] << " - " << tp[siz[id]] << " " << dp[id][0] << endl;
	
	int sc = 0;
	for (int p = thd[id], dst; p != -1; p = tnxt[p])
	{
		dst = tdes[p];
		if (dst != fa)
			pre[++sc] = dp[dst][1];
	}
	pre[0] = 1;
	for (int i = 0; i < sc; i++)
	{
		suf[i] = pre[i + 1];
		pre[i + 1] *= pre[i];
	}
	suf[sc] = 1;
	for (int i = sc - 1; i >= 0; i--)
		suf[i] *= suf[i + 1];
	
	for (int p = thd[id], dst, i = 0; p != -1; p = tnxt[p])
	{
		dst = tdes[p];
		if (dst != fa)
		{
			dp[id][0] += (dp[dst][0] - dp[dst][2]) * suf[i + 1] * pre[i];
			i++;
		}
	}
	
	dp[id][0] *= tp[esz[id]];
	dp[id][1] *= tp[esz[id]];
	dp[id][2] *= tp[esz[id]];
	
	if (fa != -1)
		dp[id][0] *= 2;
	dp[id][1] *= 2;
	
	// cerr << id << "  " << dp[id][0] << " " << dp[id][1] << " " << dp[id][2] << endl;
}

signed main()
{
	freopen(FNAME ".in", "r", stdin);
	freopen(FNAME ".out", "w", stdout);
	
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	
	int n, m;
	
	cin >> n >> m;
	fill(hd, hd + n, -1);
	for (int i = 0, x, y; i < m; i++)
	{
		cin >> x >> y;
		add(x - 1, y - 1), add(y - 1, x - 1);
	}
	fill(dfn, dfn + n, -1);
	
	tarjan(0, -1);
	e_cnt = 0;
	
	fill(bel, bel + n, -1);
	for (int i = 0; i < n; i++)
		if (bel[i] == -1)
		{
			getnd(i);
			// cerr << s_cnt << " " << siz[s_cnt] << endl;
			s_cnt++;
		}
	
	// cerr << m << endl;
	// for (int i = 0; i < m; i++)
	// 	if (iscut[i])
	// 		cerr << i + 1 << " ";
	
	e_cnt = 0;
	fill(thd, thd + n, -1);
	for (int i = 0; i < m; i++)
	{
		if (iscut[i])
		{
			assert(bel[des[i << 1]] != bel[des[(i << 1) | 1]]);
			tadd(bel[des[i << 1]], bel[des[(i << 1) | 1]]);
			tadd(bel[des[(i << 1) | 1]], bel[des[i << 1]]);
		}
		else
			esz[bel[des[i << 1]]]++;
	}
	tp[0] = 1;
	for (int i = 0; i < m; i++)
	{
		tp[i + 1] = tp[i];
		tp[i + 1] += tp[i];
		// cerr << i << " " << tp[i] << endl;
	}
	dfs(0, -1);
	
	cout << dp[0][0] << endl;
	
	return 0;
}