#include <bits/stdc++.h>

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
using std::bitset;

#define rep(i,n)    for(int i=0; i<(int)n; i++)
#define reps(i,s,e) for(int i=s; i<(int)e; i++)
#define coutd(i) cout << std::fixed << std::setprecision(i)
typedef long double ld;
typedef long long ll;
typedef vector<int> vint;
typedef vector<ll> vll;
typedef std::pair<int, int> pii;
typedef std::pair<ll, ll> pll;

template<class T>
using Set = std::set<T>;
template<class T, class U>
using Map = std::map<T, U>;

template<class T>
using Graph = vector<vector<T>>;

const int INT_BIG = 1<<28;


// #include <iostream>

// modint: mod 計算を int を扱うように扱える構造体
template<int MOD> struct Fp {
    long long val;
    constexpr Fp(long long v = 0) noexcept : val(v % MOD) {
        if (val < 0) val += MOD;
    }
    constexpr int getmod() { return MOD; }
    constexpr Fp operator - () const noexcept {
        return val ? MOD - val : 0;
    }
    constexpr Fp operator + (const Fp& r) const noexcept { return Fp(*this) += r; }
    constexpr Fp operator - (const Fp& r) const noexcept { return Fp(*this) -= r; }
    constexpr Fp operator * (const Fp& r) const noexcept { return Fp(*this) *= r; }
    constexpr Fp operator / (const Fp& r) const noexcept { return Fp(*this) /= r; }
    constexpr Fp& operator += (const Fp& r) noexcept {
        val += r.val;
        if (val >= MOD) val -= MOD;
        return *this;
    }
    constexpr Fp& operator -= (const Fp& r) noexcept {
        val -= r.val;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr Fp& operator *= (const Fp& r) noexcept {
        val = val * r.val % MOD;
        return *this;
    }
    constexpr Fp& operator /= (const Fp& r) noexcept {
        long long a = r.val, b = MOD, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b; std::swap(a, b);
            u -= t * v; std::swap(u, v);
        }
        val = val * u % MOD;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr bool operator == (const Fp& r) const noexcept {
        return this->val == r.val;
    }
    constexpr bool operator != (const Fp& r) const noexcept {
        return this->val != r.val;
    }
    friend constexpr std::ostream& operator << (std::ostream &os, const Fp<MOD>& x) noexcept {
        return os << x.val;
    }
    friend constexpr Fp<MOD> modpow(const Fp<MOD> &a, long long n) noexcept {
        if (n == 0) return 1;
        auto t = modpow(a, n / 2);
        t = t * t;
        if (n & 1) t = t * a;
        return t;
    }
};

const int MOD = 1000000007;

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

    Map<pll, ll> lmap;
    Map<pll, ll> rmap;
    Fp<MOD> sum = 0;
    rep(i, N) {
        ll a, b;
        cin >> a >> b;
        ll gcdv = std::__gcd(a, b);
        pll pl = (((a > 0 && b < 0) || (a < 0 && b > 0)) ? std::make_pair(std::abs(a / gcdv), -std::abs(b / gcdv)) :  std::make_pair(std::abs(a / gcdv), std::abs(b / gcdv)));
        pll pr = (((a > 0 && b > 0) || (a < 0 && b < 0)) ? std::make_pair(std::abs(b / gcdv), -std::abs(a / gcdv)) :  std::make_pair(std::abs(b / gcdv), std::abs(a / gcdv)));

        // cout << pl.first << " " << pl.second << endl;
        // cout << pr.first << " " << pr.second << endl;

        if (i == 0) {
            sum = 2;
        } else if (rmap.find(pl) == rmap.end()) {
            sum *= 2;
        } else {
            // cout << "find" << rmap[pl] << endl;
            pll np = ((pl.second < 0) ? pll(-pl.second, pl.first) : pll(pl.second, -pl.first));
            if (rmap.find(np) == rmap.end()) {
                sum += sum / modpow(Fp<MOD>(2), rmap[pl]);
            } else {
                sum += sum / (modpow(Fp<MOD>(2), rmap[pl]) + (modpow(Fp<MOD>(2), rmap[np]) - 1)) * (modpow(Fp<MOD>(2), rmap[np]) - 1);
            }
            
        }

        if (rmap.find(pr) == rmap.end()) {
            rmap[pr] = 1;
        } else {
            rmap[pr]++;
        }
    }
    cout << sum - 1 << endl;
}