#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <numeric>
#include <bitset>
#include <cmath>

static const int MOD = 1000000007;
using ll = long long;
using u32 = unsigned;
using u64 = unsigned long long;
using namespace std;

template<class T> constexpr T INF = ::numeric_limits<T>::max()/32*15+208;

template<u32 M = 1000000007>
struct modint{
    u32 val;
    modint(): val(0){}
    template<typename T>
    modint(T t){t %= (T)M; if(t < 0) t += (T)M; val = t;}

    modint pow(ll k) const {
        modint res(1), x(val);
        while(k){
            if(k&1) res *= x;
            x *= x;
            k >>= 1;
        }
        return res;
    }
    template<typename T>
    modint& operator=(T t){t %= (T)M; if(t < 0) t += (T)M; val = t; return *this;}
    modint inv() const {return pow(M-2);}
    modint& operator+=(modint a){val += a.val; if(val >= M) val -= M; return *this;}
    modint& operator-=(modint a){if(val < a.val) val += M-a.val; else val -= a.val; return *this;}
    modint& operator*=(modint a){val = (u64)val*a.val%M; return *this;}
    modint& operator/=(modint a){return (*this) *= a.inv();}
    modint operator+(modint a) const {return modint(val) +=a;}
    modint operator-(modint a) const {return modint(val) -=a;}
    modint operator*(modint a) const {return modint(val) *=a;}
    modint operator/(modint a) const {return modint(val) /=a;}
    modint operator-(){return modint(M-val);}
    bool operator==(const modint a) const {return val == a.val;}
    bool operator!=(const modint a) const {return val != a.val;}
    bool operator<(const modint a) const {return val < a.val;}
};
using mint = modint<MOD>;


template <class T>
ostream& operator<<(ostream& os, vector<T> v) {
    os << "{";
    for (int i = 0; i < v.size(); ++i) {
        if(i) os << ", ";
        os << v[i];
    }
    return os << "}";
}

template <class L, class R>
ostream& operator<<(ostream& os, pair<L, R> p) {
    return os << "{" << p.first << ", " << p.second << "}";
}


int main() {
    int n;
    cin >> n;
    vector<mint> pow2(n+1, 1);
    for (int i = 0; i < n; ++i) {
        pow2[i+1] = pow2[i]+pow2[i];
    }
    vector<pair<ll, ll>> v(n);
    vector<ll> cnt(n, 1);
    map<pair<ll, ll>, vector<int>> m;
    int p = 0, q = 0;
    for (int i = 0; i < n; ++i) {
        cin >> v[i].first >> v[i].second;
        ll g = __gcd(v[i].first, v[i].second);
        if(g){
            v[i].first /= g; v[i].second /= g;
        }
        if(v[i].first == 0 && v[i].second != 0){
            p++;
            cnt[i] = 0;
        }else if(v[i].second == 0 && v[i].first != 0) {
            q++;
            cnt[i] = 0;
        }else {
            if(v[i].first < 0) v[i].first = -v[i].first, v[i].second = -v[i].second;
            m[v[i]].emplace_back(i);
        }
    }
    mint ans = 1;
    int anss = 0;
    for (int i = 0; i < n; ++i) {
        if(!v[i].first && !v[i].second){
            anss++;
            continue;
        }
        if(!m.count(v[i])) continue;
        pair<ll, ll> co = (v[i].second < 0 ? pair<ll, ll>{-v[i].second, v[i].first} : pair<ll, ll>{v[i].second, -v[i].first});
        auto a = m.find(v[i]), b = m.find(co);
        mint val = -mint(1);
        if(a != m.end()){
            val += pow2[a->second.size()];
            m.erase(a);
        }else val += 1;
        if(b != m.end()){
            val += pow2[b->second.size()];
            m.erase(b);
        }else val += 1;
        ans *= val;
    }
    ans *= pow2[p]+pow2[q]-mint(1);
    ans += pow2[anss]-mint(1);
    cout << (ans-mint(1)).val << "\n";
    return 0;
}