#include <bits/stdc++.h>
typedef long long LL;

const int MAXN = 5e5 + 5, MAXM = 1e6 + 5;
const LL P = 1e9 + 7, inv2 = 500000004;
int n, m, Dfn[MAXN], Low[MAXN], Color[MAXN], cntDfn, cntCol, a[MAXN], cntp;
LL f[MAXN][2][2], Mi[MAXM];
bool book[MAXM << 1];
struct Graph
{
	int Head[MAXN], cntEdge = 1; struct node { int To, Next; } Edge[MAXM << 1];
	void add(int x, int y) { ++cntEdge; Edge[cntEdge] = (node){y, Head[x]}; Head[x] = cntEdge; }
} g, tree;

int Read()
{
	int sum = 0, fh = 1; char ch = getchar();
	for (; ch < '0' || ch > '9'; ch = getchar()) fh -= (ch == '-') << 1;
	for (; ch >= '0' && ch <= '9'; ch = getchar()) sum = (sum << 3) + (sum << 1) + (ch ^ 48);
	return sum * fh;
}

void dfs1(int now, int fa)
{
	++cntDfn; Dfn[now] = Low[now] = cntDfn;
	for (int i = g.Head[now]; i; i = g.Edge[i].Next)
	{
		int u = g.Edge[i].To; if (u == fa) continue ;
		if (!Dfn[u])
		{
			dfs1(u, now); Low[now] = std::min(Low[now], Low[u]);
			if (Low[u] > Dfn[now]) book[i] = book[i ^ 1] = 1;
		}
		else Low[now] = std::min(Low[now], Dfn[u]);
	}
}
void dfs2(int now, int c)
{
	Color[now] = c; ++a[c];
	for (int i = g.Head[now]; i; i = g.Edge[i].Next)
	{
		int u = g.Edge[i].To; if (Color[u] || book[i]) continue ; dfs2(u, c);
	}
}

void dfs3(int now, int fa)
{
	f[now][0][0] = 1, f[now][1][0] = 1; int sz = 0; LL pz = 0;
	for (int i = tree.Head[now]; i; i = tree.Edge[i].Next)
	{
		int u = tree.Edge[i].To; if (u == fa) continue ; dfs3(u, now); ++sz;
		LL fir = f[u][0][1] + f[u][1][0] + f[u][1][1] + f[u][0][0]; fir %= P;
		LL sec = f[u][0][1] + f[u][1][0] + f[u][1][1]; sec %= P;
		f[now][0][0] = f[now][0][0] * f[u][0][0] % P * 2 % P;
		f[now][0][1] = fir * f[now][0][1] % P + pz * fir % P * inv2 % P + f[u][0][0] * f[now][0][1] % P * 2 % P;
		f[now][1][0] = f[now][1][0] * f[u][0][0] % P * 2 % P; f[now][0][1] %= P;
		f[now][1][1] = f[now][1][0] * sec % P + f[now][1][1] * sec % P + f[now][1][1] * f[u][0][0] % P * 2 % P;
		f[now][1][1] %= P;
		pz = (pz + sec * 2 % P) % P;
	}
}

int main()
{
	freopen("barrack.in", "r", stdin); freopen("barrack.out", "w", stdout);
	n = Read(), m = Read(); Mi[0] = 1;
	for (int i = 1, pz = std::max(n, m); i <= pz; ++i) Mi[i] = Mi[i - 1] * 2 % P;
	for (int i = 1; i <= m; ++i) { int x = Read(), y = Read(); g.add(x, y); g.add(y, x); }
	for (int i = 1; i <= n; ++i) if (!Dfn[i]) dfs1(i, i);
	for (int i = 1; i <= n; ++i) if (!Color[i]) { ++cntCol; dfs2(i, cntCol); }
	for (int i = 2; i <= g.cntEdge; i += 2)
	{
		int x = g.Edge[i].To, y = g.Edge[i ^ 1].To;
		if (Color[x] != Color[y]) tree.add(Color[x], Color[y]), tree.add(Color[y], Color[x]);
	}
	dfs3(1, 1); printf("%lld\n", (f[1][0][1] + f[1][1][1] + f[1][1][0]) % P * Mi[m - (cntCol - 1)] % P);
	return 0;
}