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

const int mod = 1000000007;

struct mint
{
    ll x;
    mint(ll x=0):x((x%mod+mod)%mod){}
    mint operator-() const { return mint(-x);}
    mint &operator+=(const mint m)
    {
        if((x += m.x) >= mod) x -= mod;
        return *this;
    }
    mint &operator-=(const mint m)
    {
        if((x += mod - m.x) >= mod) x -= mod;
        return *this;
    }
    mint &operator*=(const mint m)
    {
        (x *= m.x) %= mod;
        return *this;
    }
    mint operator+(const mint m) const
    {
        return mint(*this) += m;
    }
    mint operator-(const mint m) const
    {
        return mint(*this) -= m;
    }
    mint operator*(const mint m) const
    {
        return mint(*this) *= m;
    }
    mint pow(ll n) const
    {
        if(!n) return 1;
        mint m = pow(n>>1);
        m *= m;
        if(n & 1) m *= *this;
        return m;
    }
    mint inv() const { return pow(mod-2);}
    mint &operator/=(const mint m) { return *this *= m.inv();}
    mint operator/(const mint m) const { return mint(*this) /= m;}
    bool operator==(const mint m) const { return this->x == m.x; }
};
istream &operator>>(istream &is, const mint &m) { return is >> m.x;}
ostream &operator<<(ostream &os, const mint &m) { return os << m.x;}

struct combination
{
    vector<mint> fact, ifact;
    combination(int n) : fact(n+1), ifact(n+1)
    {
        assert(n < mod);
        fact.at(0) = 1;
        for(int i=1; i<=n; i++)
        {
            fact.at(i) = fact.at(i-1) * i;
        }
        ifact.at(n) = fact.at(n).inv();
        for(int i=n; i>=1; i--)
        {
            ifact.at(i-1) = ifact.at(i) * i;
        }
    }
    mint operator()(int n, int k)
    {
        if(k < 0 || k > n) return 0;
        return fact.at(n) * ifact.at(k) * ifact.at(n-k);
    }
};

template<class T> T euclidean_gcd(T a, T b)
{
    if(a < b) return euclidean_gcd(b, a);
    T r;
    while(r=a%b)
    {
        a = b;
        b = r;
    }
    return b;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int N;
    cin >> N;
    vector<ll> A(N), B(N);
    map<pair<ll, ll>, ll> cnt;
    map<pair<ll, ll>, bool> is_used;
    ll cnt_A_is_0 = 0;
    ll cnt_B_is_0 = 0;
    ll cnt_AB_is_0 = 0;
    for(int i=0; i<N; i++)
    {
        cin >> A[i] >> B[i];
        if(A[i] == 0 && B[i] == 0)
        {
            cnt_AB_is_0++;
            continue;
        }
        else if(A[i] == 0)
        {
            cnt_A_is_0++;
            continue;
        }
        else if(B[i] == 0)
        {
            cnt_B_is_0++;
            continue;
        }
        if(B[i]<0)
        {
            A[i] *= -1;
            B[i] *= -1;
        }
        ll num = euclidean_gcd(abs(A[i]), abs(B[i]));
        cnt[make_pair(A[i]/num, B[i]/num)]++;
        is_used[make_pair(A[i]/num, B[i]/num)] = false;
    }

    mint two = 2;
    mint ans = 1;
    for(auto [p, v] : cnt)
    {
        if(is_used[p]) continue;
        is_used[p] = true;
        pair<ll, ll> aite = make_pair(p.second, p.first);
        if(p.first < 0) aite.second *= -1;
        else aite.first *= -1;
        if(cnt.count(aite))
        {
            is_used[aite] = true;
            ans *= (two.pow(v) - 1 + two.pow(cnt[aite]) - 1 + 1);
        }
        else ans *= two.pow(v);
    }
    ans *= (two.pow(cnt_A_is_0) - 1 + two.pow(cnt_B_is_0) - 1 + 1);
    ans += cnt_AB_is_0;
    ans -= 1;
    cout << ans << endl;

    return 0;
}

Measured memory_bytes: 31308