#include<iostream>
#include<cassert>
#include<cmath>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<set>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define fe(itr,c)  for(__typeof((c).begin()) itr = (c).begin();itr != (c).end();itr++)
#define rep(i,n)   REP(i,0,n)
typedef long long ll;
const ll mod = 1e9 + 7;

const int N = 1010;
vector<pair<int,int> > in;
vector<int> edge[N];
int next[N];
int nextVar[N];
bool loopBeg[N];
bool isBeg[N];

namespace PreProcessing{
  vector<int> ledge[N];
  int vis[N];
  int indeg[N];
  bool absSame(int a,int b){return abs(a) == abs(b);}
  bool shareVar(int a,pair<int,int> &b){return absSame(a,b.first) || absSame(a,b.second);}
  void makegraph(int n){
    rep(i,n)rep(j,n){
      if (i == j)continue;
      bool f = shareVar(in[i].first,in[j]),s = shareVar(in[i].second,in[j]);
      if (f || s)ledge[i].push_back(j);
      if (f)indeg[j]++;
      if (s)indeg[j]++;
    }
  }
  void dfs(int n,int now,int prev,const int fir){
    if (vis[now])return;
    vis[now] = true;
    if (prev != -1){
      next[prev] = now;
      if (shareVar(in[prev].first,in[now]))nextVar[prev] = abs(in[prev].first);
      else if (shareVar(in[prev].second,in[now]))nextVar[prev] = abs(in[prev].second);
    }
    rep(i,(int)ledge[now].size())dfs(n,ledge[now][i],now,fir);
  }
  void createGraph(int n){
    rep(i,n)next[i] = -1,nextVar[i] = 0,indeg[i] = 0,loopBeg[i] = false,isBeg[i] = false,edge[i].clear(),ledge[i].clear();
    makegraph(n);
    rep(i,n)vis[i] = false;
    rep(i,n)if (!vis[i] && indeg[i] <= 1)isBeg[i] = true,dfs(n,i,-1,-1);//ループなし
    rep(i,n)if (!vis[i])loopBeg[i] = true,dfs(n,i,-1,i);//ループあり
  }
}

bool isok(int x,bool v){return (x > 0 && v) || (x < 0 && !v);}

ll dp[N][2][2];
ll solve(int now,bool v,int px,const int first,const bool firstv){
  int nextx = in[now].first,opx = in[now].second;
  if (abs(nextx) == px)swap(nextx,opx);
  if (next[now] == -1){
    if (loopBeg[first]){//ループの場合
      if (isok(opx,v))return 1;
      else return isok(nextx,firstv);
    }else {
      if (isok(opx,v))return 2;
      else return 1;
    }
  }
  ll &ret = dp[now][v][firstv];
  if (ret != -1)return ret;
  ret = 0;
  if (isok(opx,v)){//opxが満たされるなら、nextxはtrueでもfalseでもいい。
    ret += solve(next[now],false,abs(nextx),first,firstv);ret %= mod;
    ret += solve(next[now],true ,abs(nextx),first,firstv);ret %= mod;
  }else {//nowの式のうち、(px = v)で満たされない場合、
    if (isok(nextx,false))ret += solve(next[now],false,abs(nextx),first,firstv);
    else if (isok(nextx,true))ret += solve(next[now],true,abs(nextx),first,firstv);
    ret %= mod;
  }
  return ret;
}

ll compute(int n){
  ll ret = 1;
  rep(i,n)rep(j,2)rep(k,2)dp[i][j][k] = -1;
  rep(now,n){
    if (loopBeg[now]){
      int nextx = abs(in[now].first) != abs(nextVar[now])?in[now].first:in[now].second;
      ll tmp = 0;
      tmp += solve(now,false,abs(nextx),now,false);tmp %= mod;
      tmp += solve(now,true ,abs(nextx),now,true)  ;tmp %= mod;
      ret *= tmp;ret %= mod;
    }else if (isBeg[now]){
      int nextx = abs(in[now].first) != abs(nextVar[now])?in[now].first:in[now].second;
      ll tmp = 0;
      tmp += solve(now,false,abs(nextx),now,false);tmp %= mod;
      tmp += solve(now,true ,abs(nextx),now,true)  ;tmp %= mod;
      ret *= tmp;ret %= mod;
    }
  }
  return ret;
}

main(){
  int n,m;
  while(cin>>n>>m && n){
    vector<pair<int,int> > formula;
    in.clear();
    //a or -a なら２通り
    //a or a  なら１通り
    ll weight = 1;
    rep(i,m){
      int a,b;
      cin>>a>>b;
      if (a == -b)weight = (weight * 2 ) % mod;
      else if (a == b);
      else in.push_back(make_pair(a,b));
      formula.push_back(make_pair(a,b));
    }
    PreProcessing::createGraph((int)in.size());
    ll tmp = compute((int)in.size());
    ll ans = (tmp*weight)%mod;
    cout << ans << endl;
  }
  return 0;
}

Measured memory_bytes: 0