//分步:乘法原理
//不同时发生:加法原理
#include <iostream>
#include <cstdio>
#include <cmath>
#include <map>
#include <queue>
#include <iomanip>
#include <string>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
const int mod=1e9+7;
#define fi first
#define se second
#define pb push_back
#define mp make_pair

ll qpow(ll a,ll b){
    ll res=1;
    while( b ){
        if( b&1 ) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}
int n;
int main()
{
    scanf("%d",&n);
    map<ll,map<ll,ll> >x;
    map<ll,map<ll,bool> > c;
    vector<pair<ll,ll> >ab(maxn);
    ll res=0,A=0,B=0;
    for(int i=0;i<n;i++){
        ll a,b;
        scanf("%lld%lld",&a,&b);
        if( a==0 && b==0 ) res++;
        else if(a==0) A++;
        else if(b==0) B++;
        else{
            if( a<0 ){//(-5)/2与5/(-2) 的不能匹配一样:2/(-5),(-5)/2,所以避免下面的计算一楼,先将他们统一
                a*=-1;
                b*=-1;
            }
            ll g=__gcd(a,b);
            a/=g;b/=g;
            x[a][b]++;
            ab[i]=make_pair(a,b);
        }
    }

    ll ans=(qpow(2,A)+qpow(2,B)-1+mod)%mod;//ans1表示(A==0 || B==0)时的情况数,因为0/1,1/0不能配对,所以用加法,可是算了两次不选的情况,所以-1是去掉多一次不选的情况
    //e.g.A==0:0/1 0/2 0/3 0/5; B==0:1/0,0/4,0/5,0/6,可以画出共有31种情况
    //一下同理

    for(int i=0;i<ab.size();i++){
        ll a=ab[i].first,b=ab[i].second;
        if( c[a][b] ) continue;
        c[a][b]=true;c[-b][a]=true;c[b][-a]=true;
        ll ans2=(qpow(2,x[a][b])%mod + qpow(2,x[-b][a])%mod + qpow(2,x[b][-a])%mod - 2 + mod)%mod;
        ans = (ans*ans2)%mod;
    }
    ans = (ans-1+mod)%mod;//-1删除除了(0,0)都没有的情况
    ans = (ans+res)%mod;
    printf("%lld\n",ans);
    return 0;
}
