#include<bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i) 
#define rrep(i, a, b) for (int i = (a); i < (b); ++i)
#define PI acos(-1)
#define pcnt __builtin_popcountll
#define rng(a) a.begin(), a.end()
#define rrng(a) a.rbegin(), a.rend()
#define sz(x) (int)(x).size()
#define v(T) vector<T>
#define vv(T) v(v(T))
#define fi first
#define se second

using namespace std;
using ll = long long;
using ld = long double;
using P = pair<int, int>;
using LP = pair<ll, ll>;
using vi = vector<int>;
using vvi = vector<vi>;
using vl = vector<ll>;
using vvl = vector<vl>;

template<typename T>inline istream& operator>>(istream&i,v(T)&v)
{rep(j,sz(v))i>>v[j];return i;}
template<typename T1,typename T2>inline istream& operator>>(istream&i,pair<T1,T2>&v)
{return i>>v.fi>>v.se;}
template<class T> inline bool chmax(T& a, T b) {if (a < b) { a = b; return true; } return false; }
template<class T> inline bool chmin(T& a, T b) {if (a > b) { a = b; return true; } return false; }

const int mod = 1000000007;
struct mint {
    ll x; // using long long ll;
    mint(ll x=0):x((x%mod+mod)%mod){}
    mint operator-() const { return mint(-x);}
    mint& operator+=(const mint a) {
        if ((x += a.x) >= mod) x -= mod;
        return *this;
    }
    mint& operator-=(const mint a) {
        if ((x += mod-a.x) >= mod) x -= mod;
        return *this;
    }
    mint& operator*=(const mint a) { (x *= a.x) %= mod; return *this;}
    mint operator+(const mint a) const { return mint(*this) += a;}
    mint operator-(const mint a) const { return mint(*this) -= a;}
    mint operator*(const mint a) const { return mint(*this) *= a;}
    mint pow(ll t) const {
        if (!t) return 1;
        mint a = pow(t>>1);
        a *= a;
        if (t&1) a *= *this;
        return a;
    }
    
    // for prime mod
    mint inv() const { return pow(mod-2);}
    mint& operator/=(const mint a) { return *this *= a.inv();}
    mint operator/(const mint a) const { return mint(*this) /= a;}
};
istream& operator>>(istream& is, const mint& a) { return is >> a.x;}
ostream& operator<<(ostream& os, const mint& a) { return os << a.x;}

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

ll INF = 1001001001;
ll LINF = 1001001001001001001ll;

mint dub(ll a, ll p) {
    if (p == 0) return 1;
    if (p == 1) return a;
    if (p % 2) return dub(a, p - 1) * a;
    mint d = dub(a, p / 2);
    return d * d;
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);

    ll n; cin>>n;
    vector<LP> ab(n);
    cin>>ab;

    map<LP, ll> mp1, mp2;
    ll zero = 0;
    rep(i, n) {
        ll a = abs(ab[i].fi);
        ll b = abs(ab[i].se);
        ll g = __gcd(a, b);
        if (ab[i].fi == 0 && ab[i].se == 0) zero++;
        else if (a == 0) {
            mp1[LP(0, 1)]++;
        }
        else if (b == 0) {
            mp2[LP(-1, 0)]++;
        }
        else if ((ab[i].fi > 0 && ab[i].se > 0) || (ab[i].fi < 0 && ab[i].se < 0)) {
            LP p = LP(a / g, b / g);
            mp1[p]++;
        }
        else {
            LP p = LP(-a / g, b / g);
            mp2[p]++;
        }
    }

    mint ans = 1;
    for (auto v : mp1) {
        LP inv = LP(-v.fi.se, v.fi.fi);
        ans *= dub(2, v.se) + dub(2, mp2[inv]) - 1;
    }
    for (auto v : mp2) {
        LP inv = LP(v.fi.se, -v.fi.fi);
        if (mp1[inv] != 0) continue;
        ans *= dub(2, v.se);
    }
    cout<<ans - 1 + zero<<endl;
}

Measured memory_bytes: 31444