#include <bits/stdc++.h>
using namespace std;
using ll = long long;

const long long MOD = 1000000007;

template <long long MOD_ = (long long)1e9 + 7>
class ModMath {
public:
    ModMath(int N = 0)
        : N_(N)
    {
    }

    template <class... Ts>
    constexpr long long mul(long long head, Ts&&... tail)
    {
        auto res = head;
        using swallow = std::initializer_list<int>;
        (void)swallow { (void(res = (res * tail) % MOD_), 0)... };
        return res;
    }

    template <class... Ts>
    constexpr long long add(long long head, Ts&&... tail)
    {
        auto res = head;
        using swallow = std::initializer_list<int>;
        (void)swallow { (void(res = (res + tail) % MOD_), 0)... };
        return res;
    }

    constexpr long long del(long long x, long long y)
    {
        auto res = x - y;
        if (res < 0) {
            res += MOD;
        }
        return res;
    }

    constexpr long long pow(long long x, long long y)
    {
        ll ans = 1;
        while (y > 0) {
            if (y & 0x1) {
                ans = mul(ans, x);
            }
            x = mul(x, x);
            y >>= 1;
        }
        return ans;
    }

    long long combination(long long n, long long k)
    {
        if (k < 0 || k > n) {
            return 0;
        }
        if (fact_.empty()) {
            build_fact();
        }
        return mul(fact_[n], fact_inv_[k], fact_inv_[n - k]);
    }

private:
    void build_fact()
    {
        if (!fact_.empty()) {
            return;
        }
        fact_.resize(N_ + 1);
        fact_[0] = 1;
        for (ll i = 1; i <= N_; i++) {
            fact_[i] = mul(fact_[i - 1], i);
        }
        fact_inv_.resize(N_ + 1);
        fact_inv_[N_] = pow(fact_[N_], MOD_ - 2);
        for (ll i = N_ - 1; i >= 0; i--) {
            fact_inv_[i] = mul(fact_inv_[i + 1], (i + 1));
        }
    }

    int N_;
    vector<long long> fact_;
    vector<long long> fact_inv_;
};

void solve(long long N, std::vector<long long> A, std::vector<long long> B)
{
    ModMath<MOD> m;

    map<pair<ll, ll>, ll> AdivBmap;
    map<pair<ll, ll>, ll> AdivBmap2;
    ll ABzero = 0;
    for (ll i = 0; i < N; i++) {
        if ((A[i] > 0 && B[i] < 0) || (A[i] < 0 && B[i] > 0)) {
            auto gcd = __gcd(abs(A[i]), abs(B[i]));
            auto a = abs(A[i]) / gcd;
            auto b = abs(B[i]) / gcd;
            AdivBmap[{ a, b }]++;
        }
        if ((A[i] > 0 && B[i] > 0) || (A[i] < 0 && B[i] < 0)) {
            auto gcd = __gcd(abs(A[i]), abs(B[i]));
            auto a = abs(A[i]) / gcd;
            auto b = abs(B[i]) / gcd;
            AdivBmap2[{ b, a }]++;
        }
        if (A[i] == 0 && B[i] == 0) {
            // AもBも0のイワシは他のすべてのイワシと仲が悪いので除外して考える
            ABzero++;
        } else if (A[i] == 0) {
            // A=0のイワシはB=0のイワシと仲が悪い
            AdivBmap[{ 0, 1 }]++;
        } else if (B[i] == 0) {
            // B=0のイワシはA=0のイワシと仲が悪い
            AdivBmap2[{ 0, 1 }]++;
        }
    }

    ll ans = 1;
    for (auto&& i : AdivBmap) {
        auto it = AdivBmap2.find(i.first);
        if (it != end(AdivBmap2)) {
            auto n1 = i.second; // 現在見ているイワシの数
            auto n2 = it->second; // 現在見ているイワシと中の悪いイワシの数
            // イワシの選び方
            // n1のグループからどれか1匹以上を選び、n2からは選ばないパターン 2^n1 - 1
            // n2のグループからどれか1匹以上を選び、n1からは選ばないパターン 2^n2 - 1
            // どちらからも選ばないパターン 1
            ans = m.mul(ans, m.add(m.pow(2, n1) - 1, m.pow(2, n2) - 1, 1));
            N = N - n1 - n2;
        }
    }

    // 残りの仲が悪い相手がいないイワシ(N-Abzero匹)は自由に選べる
    ans = m.mul(ans, m.pow(2, N - ABzero));

    // AもBもゼロのイワシはそのイワシのみを選択するパターンだけ許される
    ans = m.add(ans, ABzero);

    // 最低一匹は選ぶので、一匹も選ばないパターンを除外
    ans = m.del(ans, 1);

    cout << ans << endl;
}

// Generated by 1.1.7.1 https://github.com/kyuridenamida/atcoder-tools  (tips: You use the default template now. You can remove this line by using your custom template)
// clang-format off
#pragma GCC diagnostic ignored "-Wunused-result"
int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    long long N;
    scanf("%lld",&N);
    std::vector<long long> A(N);
    std::vector<long long> B(N);
    for(int i = 0 ; i < N ; i++){
        scanf("%lld",&A[i]);
        scanf("%lld",&B[i]);
    }
    solve(N, std::move(A), std::move(B));
    return 0;
}


Measured memory_bytes: 18784