#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <chrono>

    #pragma GCC optimize("O3")
    #pragma GCC optimize("Ofast")
    #pragma GCC optimize("unroll-loops")
    /*#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
    #pragma GCC target ("avx2")*/

using namespace std;
using namespace __gnu_pbds;

typedef long long ll;

ll MAX = 1e15;
double PI = 3.141592653589793238463;
//double PI = acos(-1);
typedef tree<ll, null_type, less<ll>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;

ll gcd(ll a, ll b){
    return b==0 ? abs(a) : gcd(b, a%b);
}

ll md = 1000000007;

ll pows(ll a, ll n){
    if(n==0){
        return 1;
    }
    if(n%2==0){
        ll b = pows(a, n/2);
        return (b*b)%md;
    }
    return (pows(a, n-1)*a)%md;
}

void solve(){
    ll n;
    cin >> n;
    map<pair<ll,ll>, ll> mp;
    ll zeros=0;
    ll count01=0, count10=0;
    for(ll i=0; i<n; i++){
        ll a,b;
        cin >> a >> b;
        if(b<0){
            a*=-1;
            b*=-1;
        }
        /*else if(b==0){
            /*a=1;
            b=0;*/
            /*count10++;
            continue;
        }
        else if(a==0){
            /*a=0;
            b=1;*/
            /*count01++;
            continue;
        }*/
        ll d = gcd(a,b);
        if(d==0){
            zeros++;
            continue;
        }
        a/=d; b/=d;
        mp[{a,b}]++;
    }
    ll ans=1;
    /*if(count01>0 && count10>0){
        ll tomult = pows(2, count01)+pows(2, count10)+md-1;
        tomult%=md;
        ans*=tomult;
        ans%=md;
    }
    else if(count01>0){
        ll tomult = pows(2, count01);
        tomult%=md;
        ans*=tomult;
        ans%=md;
    }
    else if(count10>0){
        ll tomult = pows(2, count10);
        tomult%=md;
        ans*=tomult;
        ans%=md;
    }*/

    for(auto smth : mp){
        pair<ll,ll> x = smth.first;
        ll amount = smth.second;
        if(amount==0){
            continue;
        }
        //cout << mp[{0,1}] << "\n\n";
        ll a =x.first, b=x.second;
        ll tomult=pows(2, amount);
        mp[{a,b}]=0;
        //cout << a << " " << b << " : ";
        ll a1=a, b1=b;
        swap(a,b);
        if(b<0){
            a*=-1;
            b*=-1;
        }
        a*=-1;
        if(b==0){
            a=abs(a);
        }
        else if(a==0){
            b=abs(b);
        }
        //b*=-1;
        //cout << a << " " << b << "\n";
        if(mp.count({a,b})>0){
            //cout << a1 << " " << b1 << " : ";
            //cout << a << " " << b << "\n";
            tomult+=pows(2, mp[{a,b}]);
            tomult+=md-1;
            tomult%=md;
            mp[{a,b}]=0;
        }

        ans*=tomult;
        ans%=md;
    }
    ans+=md-1+zeros;
    ans%=md;
    cout << ans;
}

bool checker(){
    vector<string> f1, f2;
    ifstream fl1, fl2;
    fl1.open("output1.txt");
    fl2.open("output2.txt");
    string s;
    while(getline(fl1, s)){
        f1.push_back(s);
    }
    while(getline(fl2, s)){
        f2.push_back(s);
    }
    //cout << f1.size() << " " << f2.size();
    for(ll i=0; i<f1.size(); i++){
        if(f1[i]!=f2[i]){
            cout << "MISTAKE " << i << "\n";
            cout << f1[i] << "\n" << f2[i] << "\n\n";
        }
    }
}

int main() {
    ios_base::sync_with_stdio(0); cin.tie(0);
    #ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    #endif


    ll t=1;
    //cin >> t;
    while(t--){
        solve();
        //checker();
    }


    return 0;
}


Measured memory_bytes: 16144