#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <iomanip>
using ll = long long;
using uint = unsigned int;
using graph = std::vector<std::vector<ll>>;
using wGraph = std::vector<std::vector<std::pair<ll,ll>>>;
#define rep(i,n) for (int i=0; i < int(n); i++)

using namespace std;
ll MOD7 = 1000000007;
ll MOD9 = 1000000009;
vector<ll> InputVec(ll N){
    vector<ll> A(N);
    for (int i = 0; i < N; ++i) {
        cin >> A[i];
    }
    return A;
}
void OutputVec(vector<ll> A){
    for (int i = 0; i < A.size(); ++i) {
        cout << A[i] << ",";
    }
    cout << endl;
}
vector<vector<ll>> InputVec2d(ll H,ll W){
    vector<vector<ll>> A(H);
    for (int yi = 0; yi < H; ++yi) {
        A[yi] = vector<ll>(W);
    }
    for (int yi = 0; yi < H; ++yi) {
        for (int xi = 0; xi < W; ++xi) {
            cin >> A[yi][xi];
        }
    }
    return A;
}
vector<vector<char>> InputVec2dStr(ll H,ll W){
    vector<vector<char>> A(H);
    for (int yi = 0; yi < H; ++yi) {
        A[yi] = vector<char>(W);
    }
    for (int yi = 0; yi < H; ++yi) {
        string S;
        cin >> S;
        for (int xi = 0; xi < W; ++xi) {
            A[yi][xi] = S[xi];
        }
    }
    return A;
}
void OutputVec2d(vector<vector<ll>> A){
    for (int yi = 0; yi < A.size(); ++yi) {
        for (int xi = 0; xi < A[yi].size(); ++xi) {
            cout << A[yi][xi] << ",";
        }
        cout << endl;
    }
}
graph InputGraph(ll N,ll M){
    graph G(N);
    for (int i = 0; i < M; ++i) {
        ll a,b;
        cin >> a >> b;
        a--;b--;
        G[a].push_back(b);
        G[b].push_back(a);
    }
    return G;
}
graph InputDGraph(ll N,ll M){
    graph G(N);
    for (int i = 0; i < M; ++i) {
        ll a,b;
        cin >> a >> b;
        a--;b--;
        G[a].push_back(b);
    }
    return G;
}
wGraph InputWGraph(ll N,ll M){
    wGraph G(N);
    for (int i = 0; i < M; ++i) {
        ll a,b,c;
        cin >> a >> b >> c;
        a--;b--;
        G[a].push_back(make_pair(b,c));
        G[b].push_back(make_pair(a,c));
    }
    return G;
}
wGraph InputDWGraph(ll N, ll M){
    wGraph G(N);
    for (int i = 0; i < M; ++i) {
        ll a,b,c;
        cin >> a >> b >> c;
        a--;b--;
        G[a].push_back(make_pair(b,c));
    }
    return G;
}
void OutputGraph(graph G){
    for (int i = 0; i < G.size(); ++i) {
        cout << i << ":";
        for (int j = 0; j < G[i].size(); ++j) {
            cout << G[i][j]<< ",";
        }
        cout << endl;
    }
}

void OutputGraph(wGraph G){
    for (int i = 0; i < G.size(); ++i) {
        cout << i << ":";
        for (int j = 0; j < G[i].size(); ++j) {
            cout << G[i][j].first <<"/" << G[i][j].second << ",";
        }
        cout << endl;
    }
}

void OutputAnswerBool(bool b,bool isUpperCase = false){
    if(b){
        if(isUpperCase){
            cout << "YES" << endl;
        }else{
            cout << "Yes" << endl;
        }
    }else{
        if(isUpperCase){
            cout << "NO" << endl;
        }else{
            cout << "No" << endl;
        }
    }
}

ll gcd(ll a, ll b) {
    if(a < b) return gcd(b, a);
    ll r;
    while ((r=a%b)) {
        a = b;
        b = r;
    }
    return b;
}
ll lcm(ll a, ll b) {
    ll g;
    g = gcd(a, b);
    return a*b/g;
}

long long modpow(long long a, long long n, long long mod) {
    long long res = 1;
    while (n > 0) {
        if (n & 1) res = res * a % mod;
        a = a * a % mod;
        n >>= 1;
    }
    return res;
}

int main() {
    ll N;
    cin >> N;
    map<pair<ll,ll>,pair<ll,ll>> bucket;
    ll wildA = 0;
    ll wildB = 0;
    ll zero = 0;
    for (int i = 0; i < N; ++i) {
        ll a,b;
        cin >> a >> b;
        if(a == 0 && b == 0){
            zero++;
            continue;
        }
        if(a == 0){
            wildA++;
            continue;
        }else{
            if(b == 0){
                wildB++;
                continue;
            }
        }
        bool isSameSign = ((a > 0ll && b > 0ll) || (a < 0ll && b < 0ll));
        a = abs(a);
        b = abs(b);
        ll g = gcd(a,b);
        a /= g;
        b /= g;
        if(isSameSign){
            bucket[make_pair(a,b)].first++;
        }else{
            bucket[make_pair(b,a)].second++;
        }
    }
    auto begin = bucket.begin(), end = bucket.end();
    //cout << bucket.size() << endl;
    map<pair<ll,ll>,bool> seen;
    ll wild = (modpow(2,wildA,MOD7) + modpow(2,wildB,MOD7)-1 + MOD7) % MOD7;
    ll count = wild;
    count %= MOD7;
    for (auto iter = begin; iter != end; iter++) {
        // first: key, second: value
        ll a = iter->first.first;
        ll b = iter->first.second;
        //cout << "key = " << iter->first.first.first << "," <<iter->first.first.second << "," << iter->first.second << "\n";
        //cout << "value = " << iter->second << "\n";
        count *= (modpow(2,bucket[make_pair(a,b)].first,MOD7) + modpow(2,bucket[make_pair(a,b)].second,MOD7) - 1 + MOD7) % MOD7;
        count %= MOD7;
    }
    cout << (count-1+MOD7 + zero)%MOD7 << endl;

}


Measured memory_bytes: 19072