#include <bits/stdc++.h>
using namespace std;
#define TRACE(x) 
#define WATCH(x) TRACE( cout << #x" = " << x << endl)
#define PRINT(x) TRACE(printf(x))
#define WATCHR(a, b) TRACE( for(auto c = a; c != b;) cout << *(c++) << " "; cout << endl)
#define WATCHC(V) TRACE({cout << #V" = "; WATCHR(V.begin(), V.end()); } )
#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define trav(a, x) for(auto& a : x)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define sz(x) (int)(x).size()
#define mp make_pair
#define st first
#define nd second

using ll = long long;
using pii = pair<int, int>;
using vi = vector<int>;
using ld = long double;
using pll = pair<ll, ll>;
using vll = vector<ll>;
using pll = pair<ll, ll>;

void buff() { ios::sync_with_stdio( false ); cin.tie( nullptr ); }

constexpr ll MOD = 1e9 + 7;

inline ll pow_mod( ll a, ll b, ll mod = MOD) {
    ll res = 1; a %= mod; assert(b >= 0);
    for(;b;b>>=1) {
        if(b&1) res = (res * a) % mod;
        a = (a * a) % mod;
    }
    return res;
}
// End of template code!
int main() 
{
    buff();
    int n;
    cin >> n;
    map<pll, ll> count;
    long long zero_first = 0, zero_second = 0, all_z = 0;
    vector<pll> v; 
    rep(i, 0, n) {
        ll a, b;
        cin >> a >> b;
        if(a == 0 && b == 0) {
            all_z = 1; 
            continue;
        }
        if(a == 0) {
            zero_first++;
            continue;
        }
        if(b == 0) {
            zero_second++;
            continue;
        }
        ll d = __gcd(llabs(a), llabs(b));
        if(d > 1) { a /= d; b /= d; }
        if(a < 0 && b < 0) { a = -a; b = -b; } 
        if(a < 0 && b > 0) { a = -a; b = -b; } 
        v.emplace_back(a, b);
        count[{a, b}]++;
    }
    // agora temos que contar as inimizades
    vector<pll> choices;
    set< pll > blacklist;
    for(auto& g : count) 
    {
        if(blacklist.find(g.first) != blacklist.end()) continue;
        if(g.second == 0) continue;
        ll x = g.first.first, y = g.first.second;
        // sera que tem inimigos na componente?
        ll op_x = -y, op_y = x;
        ll tam = count[{op_x, op_y}];
        tam += count[{y, -x}];
        if(tam > 0) 
        {
            choices.emplace_back(g.second, tam);
            blacklist.insert({op_x, op_y}); 
            blacklist.insert({y, -x}); 
        }
        else 
        {
            choices.emplace_back(g.second, 0);
        }
        g.second = 0;
    }
    if(zero_first || zero_second) choices.emplace_back(zero_first, zero_second);
    
    long long ans = 1ll; // VAZIA!
    for(const auto& C : choices) {
        TRACE(cout << C.first << " " << C.second << endl; )
        long long choose_L = (pow_mod(2ll, C.first) - 1ll + MOD) % MOD;
        long long choose_R = (pow_mod(2ll, C.second) - 1ll + MOD) % MOD;
        long long choices = choose_L + choose_R + 1ll;
        choices %= MOD;
        ans = (ans * choices) % MOD;
    }
    if(all_z > 0) ans = (ans + all_z) % MOD;
    
    // tem que tirar a vazia 
    cout << (ans - 1ll + MOD) % MOD  << endl;

    return 0;
}

