#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;
    for(ll i=0; i<n; i++){
        ll a,b;
        cin >> a >> b;
        if(b<0){
            a*=-1;
            b*=-1;
        }
        ll d = gcd(a,b);
        if(d==0){
            zeros++;
            continue;
        }
        a/=d; b/=d;
        mp[{a,b}]++;
    }
    ll ans=1;
    for(auto smth : mp){
        pair<ll,ll> x = smth.first;
        ll amount = smth.second;
        ll a =x.first, b=x.second;
        ll tomult=pows(2, amount);
        mp[{a,b}]=0;
        swap(a,b);
        if(b<0){
            a*=-1;
            b*=-1;
        }
        a*=-1;
        if(mp.count({a,b})>0){
            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;
}

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();
    }


    return 0;
}
