#include <bits/stdc++.h>

#include <functional>
// from boost (functional/hash):
// see http://www.boost.org/doc/libs/1_35_0/doc/html/hash/combine.html template
template <typename T>
inline void hash_combine(std::size_t &seed, const T &val) {
    seed ^= std::hash<T>()(val) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
// auxiliary generic functions to create a hash value using a seed
template <typename T> inline void hash_val(std::size_t &seed, const T &val) {
    hash_combine(seed, val);
}
template <typename T, typename... Types>
inline void hash_val(std::size_t &seed, const T &val, const Types &... args) {
    hash_combine(seed, val);
    hash_val(seed, args...);
}

template <typename... Types>
inline std::size_t hash_val(const Types &... args) {
    std::size_t seed = 0;
    hash_val(seed, args...);
    return seed;
}

struct pair_hash {
    template <class T1, class T2>
    std::size_t operator()(const std::pair<T1, T2> &p) const {
        return hash_val(p.first, p.second);
    }
};

using namespace std;
using ll = long long;
const ll MOD = 1e9 + 7;

unordered_map<ll, ll> memo;
ll mypow2(ll y) {
    if (y == 0)
        return 1;
    else if (y == 1)
        return 2;
    else {
        auto it = memo.find(y);
        if (it != memo.end())
            return it->second;
        else {
            if (y % 2 == 1)
                return memo[y] = 2 * mypow2(y - 1) % MOD;
            else {
                auto ans = mypow2(y / 2);
                return memo[y] = ans * ans % MOD;
            }
        }
    }
}

int main() {
    int N;
    cin >> N;
    unordered_map<pair<ll, ll>, ll, pair_hash> slopeCount;
    // map<pair<ll, ll>, ll> slopeCount;
    ll zeroCount = 0;
    for (int i = 0; i < N; ++i) {
        ll A, B;
        cin >> A >> B;
        if (A == 0 && B == 0) {
            ++zeroCount;
        } else {
            auto gcdAB = __gcd(abs(A), abs(B));
            if (B < 0)
                ++slopeCount[{-A / gcdAB, -B / gcdAB}];
            else
                ++slopeCount[{A / gcdAB, B / gcdAB}];
        }
    }
    unordered_set<pair<ll, ll>, pair_hash> seen;
    // set<pair<ll, ll>> seen;
    ll ans = 1;
    for (const auto &p : slopeCount) {
        const auto &slope = p.first;
        // cout << slope.first << " " << slope.second << " " << p.second
        //      << endl;
        if (seen.find(slope) == seen.end()) {
            pair<ll, ll> vertical;
            if (slope.first == 0) {
                vertical = {1, 0};
            } else if (slope.second == 0) {
                vertical = {0, 1};
            } else if (slope.first < 0) {
                vertical = {slope.second, -slope.first};
            } else {
                vertical = {-slope.second, slope.first};
            }
            auto it = slopeCount.find(vertical);
            if (it != slopeCount.end()) {
                ans *= (mypow2(it->second) + mypow2(p.second) - 1);
                ans %= MOD;
                seen.insert(vertical);
            } else {
                ans *= mypow2(p.second);
                ans %= MOD;
            }
        }
    }
    ans -= 1;
    if (ans < 0)
        ans += MOD;
    ans += zeroCount;
    ans %= MOD;

    cout << ans << endl;
    return 0;
}

Measured memory_bytes: 14576