#include <bits/stdc++.h>
#define rep(i, n) for(int i=0; i<(n); i++)
#define all(x) (x).begin(), (x).end()
#define bit(x) (1L << (x))
using ll = long long;
using namespace std;

template<typename T>
vector<T> make_v(size_t a,T b){return vector<T>(a,b);}
 
template<typename... Ts>
auto make_v(size_t a,Ts... ts){
        return vector<decltype(make_v(ts...))>(a,make_v(ts...));
}

constexpr int default_mod = 1e9 + 7;
constexpr bool default_isPrime = true;

template<int Mod = default_mod, bool IsPrime = default_isPrime>
class mint {
        ll n_;
public:
        constexpr mint(ll n): n_{n} { 
                if (n >= Mod) {
                        n_ %= Mod;
                } else {
                        n_ = (n_ % Mod + Mod) % Mod;
                }
        }

        constexpr mint() : n_{0} {}

        constexpr operator int() const { return n_; }
        constexpr operator ll() const { return n_; }

        constexpr mint& operator==(const mint& n) {
                return n_ == n.n_;
        }

        constexpr mint& operator=(const mint& n) {
                n_ = n.n_;
                return *this;
        }

        constexpr mint& operator+=(const mint& n) {
                if ((n_ += n.n_) >= Mod) n_ -= Mod;
                return *this;
        }

        constexpr mint& operator-=(const mint& n) {
                if ((n_ -= n.n_) < 0) n_ += Mod;
                return *this;
        }
        
        constexpr mint& operator*=(const mint& n) {
                if ((n_ *= n.n_) >= Mod) n_ %= Mod;
                return *this;
        }

        constexpr mint& operator/=(const mint& n) {
                return *this *= n.inverse();
        }

        constexpr typename enable_if<IsPrime, mint>::type inverse() const {
                ll a = n_, b = Mod, u = 1, v = 0;
                while (b) {
                        ll t = a / b;
                        a -= t * b; swap(a, b);
                        u -= t * v; swap(u, v);
                }
                return mint(u);
        }

        constexpr mint operator+(mint n) const { return mint(*this) += n; }
        constexpr mint operator-(mint n) const { return mint(*this) -= n; }
        constexpr mint operator*(mint n) const { return mint(*this) *= n; }
        constexpr mint operator/(mint n) const { return mint(*this) /= n; }

};

template<int Mod = default_mod, bool IsPrime = default_isPrime>
ostream& operator<<(ostream& os, mint<Mod, IsPrime> const& n) {
        os << (int)n;
        return os;
}

template<int Mod = default_mod, bool IsPrime = default_isPrime>
mint<Mod, IsPrime> fact(int n) {
        static vector<mint<Mod, IsPrime>> v {1};

        if (n >= static_cast<int>(v.size())) {
                const int from = v.size(), to = n + 1024;
                v.reserve(to);
                for (int i = from; i < to; i++) {
                        v.push_back(v.back() * mint<Mod, IsPrime>(i));
                }
        }
        
        return v[n];
}

template<int Mod = default_mod, bool IsPrime = default_isPrime>
mint<Mod, IsPrime> comb(int n, int r) {
        if (r < 0 || n < r) {
                return 0;
        } else {
                return fact<Mod, IsPrime>(n) / fact<Mod, IsPrime>(r) / fact<Mod, IsPrime>(n - r);
        }
}

using mi = mint<>;

template<typename T>
T pow(T x, int n) {
        if (n == 0) {
                return T(1);
        } else {
                T rest = n % 2 ? x : T(1);
                return pow(x * x, n / 2) * rest;
        }
}

ll gcd(ll a, ll b) {
        if (b == 0) {
                return a;
        } else {
                return gcd(b, a % b);
        }
}

int main() {
        int n;
        cin >> n;

        vector<ll> a(n), b(n);
        map<pair<int, int>, pair<int, int>> mp;
        mi zeros(0);
        rep (i, n) {
                cin >> a[i] >> b[i];

                if (a[i] == 0 && b[i] == 0) {
                        zeros += 1;
                        continue;
                }

                ll g = gcd(a[i], b[i]);
                a[i] = a[i] / g;
                b[i] = b[i] / g;

                if (a[i] >= 0 && b[i] > 0) {
                        mp[{a[i], b[i]}].first++;
                } else if (a[i] < 0 && b[i] >= 0) {
                        mp[{b[i], -a[i]}].second++;                 
                } else if (a[i] <= 0 && b[i] < 0) {
                        mp[{-a[i], -b[i]}].first++; 
                } else if (a[i] > 0 && b[i] <= 0) {
                        mp[{-b[i], a[i]}].second++;
                }
        }

        mi r(1);
        for (auto itr : mp) {
                int c = itr.second.first, w = itr.second.second;
                r *= pow(mi(2), c) + pow(mi(2), w) - mi(1);
        }

        cout << zeros + r - mi(1) << endl;

        return 0;
}


Measured memory_bytes: 18748