#include <iostream> // cout, endl, cin
#include <string> // string, to_string, stoi
#include <vector> // vector
#include <algorithm> // min, max, swap, sort, reverse, lower_bound, upper_bound
#include <utility> // pair, make_pair
#include <tuple> // tuple, make_tuple
#include <cstdint> // int64_t, int*_t
#include <cstdio> // printf
#include <map> // map
#include <queue> // queue, priority_queue
#include <set> // set
#include <stack> // stack
#include <deque> // deque
#include <unordered_map> // unordered_map
#include <unordered_set> // unordered_set
#include <bitset> // bitset
#include <cctype> // isupper, islower, isdigit, toupper, tolower
using namespace std;
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define Rep(i,s,n) for(int i=s;i<n;i++)
#define fi first
#define se second
#define all(c) c.begin(),c.end()
typedef long long int ll;
typedef pair<int, int> P;
typedef long double ld;
void Ans(bool x){if(x) cout<<"Yes"<<endl;else cout<<"No"<<endl;}

const ll INF=1001001001;
const ll mod=1000000007;

struct mint {
  ll x; // typedef long long ll;
  mint(ll x=0):x((x%mod+mod)%mod){}
  mint operator-() const { return mint(-x);}
  mint& operator+=(const mint a) {
    if ((x += a.x) >= mod) x -= mod;
    return *this;
  }
  mint& operator-=(const mint a) {
    if ((x += mod-a.x) >= mod) x -= mod;
    return *this;
  }
  mint& operator*=(const mint a) {
    (x *= a.x) %= mod;
    return *this;
  }
  mint operator+(const mint a) const {
    mint res(*this);
    return res+=a;
  }
  mint operator-(const mint a) const {
    mint res(*this);
    return res-=a;
  }
  mint operator*(const mint a) const {
    mint res(*this);
    return res*=a;
  }
  mint pow(ll t) const {
    if (!t) return 1;
    mint a = pow(t>>1);
    a *= a;
    if (t&1) a *= *this;
    return a;
  }

  // for prime mod
  mint inv() const {
    return pow(mod-2);
  }
  mint& operator/=(const mint a) {
    return (*this) *= a.inv();
  }
  mint operator/(const mint a) const {
    mint res(*this);
    return res/=a;
  }
};


ll gcd(ll a,ll b){
  if(a==0||b==0) return 0;
  if(a<0) return gcd((-1)*a,b);
  if(b<0) return gcd(a,(-1)*b);
  if(b<a) return gcd(b,a);
  if(b%a==0) return a;
  return gcd(b%a,a);
}


int main(){
  ll n;
  cin>>n;
  ll a,b;
  P v[n];
  vector<P> vc;
  map<P,int> mp;
  
  rep(i,n){
    cin>>a>>b;
    int ch=0;
    ll g=gcd(a,b);
    if(g==0){
      if(a!=0){
        mp[P(1,0)]++;
      }
      else if(b!=0){
        mp[P(0,-1)]++;
      }
      else{
        mp[P(0,0)]++;
      }
    }
    
    else{
    v[i]=P(a/g,b/g);
    if(mp[P(a/g,b/g)]==0&&mp[P((-1)*a/g,(-1)*b/g)]==0&&
       mp[P((-1)*b/g,a/g)]==0&&mp[P(b/g,(-1)*a/g)]==0){
      ch++;
    }
    
    if(a>0&&b>0){
      mp[P(a/g,b/g)]++;
      if(ch!=0) vc.push_back(P(a/g,b/g));
    }
    else if(a<0&&b<0){
      mp[P((-1)*a/g,(-1)*b/g)]++;
      if(ch!=0) vc.push_back(P((-1)*a/g,(-1)*b/g));
    }
    else if(a>0&&b<0){
      mp[P(a/g,b/g)]++;
      if(ch!=0) vc.push_back(P(a/g,b/g));
    }
    else if(a<0&&b>0){
      mp[P((-1)*a/g,(-1)*b/g)]++;
      if(ch!=0) vc.push_back(P((-1)*a/g,(-1)*b/g));
    }
    }
  }
  
  vc.push_back(P(1,0));
  
  mint ans=1;
  mint d=2;
  for(auto p:vc){
    ll j=mp[p];
    ll k=max(mp[P(p.se,(-1)*p.fi)],mp[P((-1)*p.se,p.fi)]);
    ans*=(d.pow(j)+d.pow(k)-1);
    //cout<<j<<" "<<k<<endl;
  }
  ans-=1;
  ans+=mp[P(0,0)];
  cout<<ans.x<<endl;
}



Measured memory_bytes: 56360