#include<bits/stdc++.h>
#include<string.h>
 
typedef long long int ll;
#define all(x) (x).begin(), (x).end()
 
using namespace std;

int nxt() {
    int x;
    cin >> x;
    return x;
}

ll nxtl(){
    ll x;
    cin>>x;
    return x;
}
 
void SieveOfEratosthenes(int n,vector <int> &primes) 
{ 
    // Create a boolean array "prime[0..n]" and initialize 
    // all entries it as true. A value in prime[i] will 
    // finally be false if i is Not a prime, else true. 
    bool prime[n+1]; 
    memset(prime, true, sizeof(prime)); 
  
    for (int p=2; p*p<=n; p++) 
    { 
        // If prime[p] is not changed, then it is a prime 
        if (prime[p] == true) 
        { 
            // Update all multiples of p greater than or  
            // equal to the square of it 
            // numbers which are multiple of p and are 
            // less than p^2 are already been marked.  
            for (int i=p*p; i<=n; i += p) 
                prime[i] = false; 
        } 
    } 
  
    // Print all prime numbers 
    for (int p=2; p<=n; p++) 
       if (prime[p]) 
          primes.push_back(p);
} 
 
ll max(ll a,ll b)
{
    if(a>b)
        return a;
    return b;
}
 
ll power(ll x, ll y,ll mod) 
{ 
    ll temp; 
    if( y == 0) 
        return 1; 
    temp = power(x, y/2,mod); 
    if (y%2 == 0) 
        return (temp*temp)%mod; 
    else
        return (((x*temp)%mod)*temp)%mod; 
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int n=nxt();
    ll mod=1e9+7;
    vector <pair<ll,ll> > v1(n),v2(n);
    map <pair<ll,ll>,ll > m2;
    for(int i=0;i<n;i++)
    {
        ll a=nxtl(),b=nxtl();
        ll g=__gcd(abs(a),abs(b));
        a/=g;
        b/=g;
        if(a<0&&b<0)
        {
            a=-a;
            b=-b;
        }
        if(b<0)
        {
            b=-b;
            a=-a;
        }
        v1[i]={a,b};
        a=-a;
        if(a<0)
        {
            a=-a;
            b=-b;
        }
        v2[i]={b,a};


        //cout<<v1[i].first<<" "<<v1[i].second<<" "<<v2[i].first<<" "<<v2[i].second<<endl; 
        m2[v1[i]]++;
        ///m3[v2[i]]++;
        //cout<<"came: "<<i<<endl;    
   }
   ll cur=1;
   vector <pair<ll,ll> > temp;
   for(auto it=m2.begin();it!=m2.end();)
   {
        pair <ll,ll> p=it->first;
        p.first=-p.first;
        if(p.first<0)
        {
            p.first=-p.first;
            p.second=-p.second;
        }
        if(m2.find({p.second,p.first})!=m2.end())
        {
            temp.push_back({it->second,m2[{p.second,p.first}]});
        }
        m2.erase(it);
        it=m2.begin();
   }
   ll test=0;
   ll n2=n;
   for(int i=0;i<temp.size();i++)
   {
        ll a=temp[i].first;
        ll b=temp[i].second;
        //cout<<a<<" "<<b<<endl; 
        ll x=(power(2,a,mod)-1+mod)%mod;
        x=(x*((power(2,b,mod)-1+mod)%mod))%mod;
        x=(x*power(2,n-a-b,mod))%mod;
        x=(x*cur)%mod;
        n-=(a+b);
        (test+=x)%=mod;
        (cur*=(a+b+2))%=mod;
   }
   test=(power(2,n2,mod)-1+mod+mod-test)%mod;
   cout<<test<<endl;



   
    
    
    return 0;   
}




 
 
