#include <bits/stdc++.h>
#define MOD 1000000007
#define INF 1000000000
#define LINF 2000000000000000000
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define bit(n) (1LL<<(n))
using namespace std;

typedef pair<int, int> P;
typedef pair<long long, long long> LLP;

// 割り算のための逆元を求める（mod m での a の逆元）
long long modinv(long long a, long long m) {
    long long b = m, u = 1, v = 0;
    while (b) {
        long long t = a / b;
        a -= t * b; swap(a, b);
        u -= t * v; swap(u, v);
    }
    u %= m; 
    if (u < 0) u += m;
    return u % m;
}

/*
    ユークリッドの互除法（正の整数x, yの最大公約数を返す）
*/

long long gcd(long long x, long long y) {
    if (x < y) swap(x, y);
    while (x % y != 0) {
        long long divisor = x % y;
        x = y;
        y = divisor;
    }
    return y;
}


// get A / B
LLP getFrac(long long A, long long B) {
    LLP f;
    if (A == 0 && B == 0) {
        f.first = 0;
        f.second = 0;
    } else if (A == 0) {
        f.first = 0;
        f.second = 1;
    } else if (B == 0) {
        f.first = 1;
        f.second = 0;
    } else {
        long long g = gcd(abs(A), abs(B));
        A /= g;
        B /= g;
        f.first = abs(A);
        f.second = abs(B);
        if ((A > 0 && B < 0) || (A < 0 && B > 0)) {
            f.first *= -1;
        }
    }

    return f;
}

LLP getReversedFrac(LLP p) {
    LLP q;
    if (p.first == 0 && p.second == 0) {
        q.first = 0;
        q.second = 0;
    } else if (p.first == 0) {
        q.first = 1;
        q.second = 0;
    } else if (p.second == 0) {
        q.first = 0;
        q.second = 1;
    } else {
        q.first = abs(p.second) * (p.first < 0 ? 1 : -1);
        q.second = abs(p.first);
    }
    return q;
}

int main() {

    int N;
    cin >> N;

    vector<long long> A(N), B(N);
    rep(i,N) cin >> A[i] >> B[i];

    map<LLP, int> pairs;
    int all_zero = 0;

    rep(i,N) {
        if (A[i] == 0 && B[i] == 0) all_zero++;
        else {
            LLP p = getFrac(A[i], B[i]);
            decltype(pairs)::iterator it = pairs.find(p);
            if (it != pairs.end()) {
                pairs[p]++;
            } else {
                pairs.insert(make_pair(p, 1));
            }
        }
    }

    long long ans = 1;
    vector<long long> doubles(N + 1, 1);
    for (int i = 1; i <= N; i++) {
        doubles[i] = doubles[i - 1] * 2;
        doubles[i] %= MOD;
    }
    set<LLP> checkedSet;
    for (decltype(pairs)::iterator it = pairs.begin(); it != pairs.end(); it = next(it, 1)) {
        long long c = 1;
        LLP p = it->first;
        int count_p = it->second;

        if (checkedSet.find(p) != checkedSet.end()) continue;

        c += doubles[count_p] - 1 + MOD;
        c %= MOD;
        LLP q = getReversedFrac(p);
        decltype(pairs)::iterator itq = pairs.find(q);
        if (itq != pairs.end() && checkedSet.find(q) == checkedSet.end()) {
            int count_q = itq->second;
            c += doubles[count_q] - 1 + MOD;
            c %= MOD;
            checkedSet.insert(q);
        }
        checkedSet.insert(p);

        ans *= c;
        ans %= MOD;
    }

    ans += all_zero;
    ans %= MOD;

    cout << (ans - 1 + MOD) % MOD << endl;

    return 0;
}

Measured memory_bytes: 32604