#include <algorithm>
#include <climits>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>

using namespace std;

long long gcd(long long a, long long b)
{
    a = abs(a), b = abs(b);
    if (a < b) swap(a, b);
    if (b == 0)
        return a;
    else {
        return gcd(b, a % b);
    }
}

template <typename T = long long, T mod = 1000000007>
class MOD
{
  private:
    // member variable
    T value;

  public:
    // constructor
    MOD(T value = 0) : value((value % mod + mod) % mod) {}

    // accessor
    T val(void) const { return value; }

    // operator +=
    MOD& operator+=(const MOD& rhs)
    {
        if ((value += rhs.value) >= mod) value -= mod;
        return *this;
    }

    MOD& operator+=(const T& rhs) { return *this += MOD{rhs}; }

    // operator -=
    MOD& operator-=(const MOD& rhs)
    {
        if ((value += mod - rhs.value) >= mod) value -= mod;
        return *this;
    }

    MOD& operator-=(const T& rhs) { return *this -= MOD{rhs}; }

    // operator *=
    MOD& operator*=(const MOD& rhs)
    {
        (value *= rhs.value) %= mod;
        return *this;
    }

    MOD& operator*=(const T& rhs) { return *this *= MOD{rhs}; }

    // operator +
    MOD operator+(const MOD& rhs) const { return MOD{*this} += rhs; }
    MOD operator+(const T& rhs) const { return MOD{*this} += rhs; }
    friend MOD operator+(const T& lhs, const MOD& rhs) { return rhs + lhs; }

    // operator -
    MOD operator-() const { return MOD{0} -= *this; }
    MOD operator-(const MOD& rhs) const { return MOD{*this} -= rhs; }
    MOD operator-(const T& rhs) const { return MOD{*this} -= rhs; }
    friend MOD operator-(const T& lhs, const MOD& rhs) { return lhs + (-rhs); }

    // operator *
    MOD operator*(const MOD& rhs) const { return MOD(*this) *= rhs; }
    MOD operator*(const T& rhs) const { return MOD(*this) *= rhs; }
    friend MOD operator*(const T& lhs, const MOD& rhs) { return rhs * lhs; }

    // ostream
    friend std::ostream& operator<<(std::ostream& stream, const MOD& rhs)
    {
        stream << rhs.value;
        return stream;
    }

    // pow
    MOD pow(T index) const
    {
        if (!index) {
            MOD ob(1);
            return ob;
        }
        MOD ob = pow(index >> 1);
        ob *= ob;
        if (index & 1) ob *= *this;
        return ob;
    }

    // for prime mod
    MOD inverse() const { return pow(mod - static_cast<T>(2)); }
    MOD& operator/=(const MOD& rhs) { return (*this) *= rhs.inverse(); }
    MOD operator/(const MOD& rhs) const { return MOD(*this) /= rhs; }
};

int main()
{
    // const int mod = 1000000007;
    int n;
    cin >> n;
    using pll = pair<long long, long long>;
    using pii = pair<int, int>;
    map<pll, pii> mp;
    int zero = 0;
    for (int i = 0; i < n; i++) {
        long long a, b;
        cin >> a >> b;
        if (a == 0 & b == 0) {
            zero++;
            continue;
        }
        auto g = gcd(a, b);
        a /= g;
        b /= g;

        if (b < 0) a = -a, b = -b;
        if (b == 0 && a < 0) a = -a, b = -b;
        bool rot90 = (a <= 0);
        if (rot90) {
            auto tmp = a;
            a = b, b = -tmp;
        }
        if (rot90)
            mp[{a, b}].first++;
        else
            mp[{a, b}].second++;
    }

    MOD ans{1};
    for (const auto& p : mp) {
        auto rotated = p.second.first;
        auto unrotated = p.second.second;
        MOD now{1};
        now += MOD{2}.pow(rotated) - 1;
        now += MOD{2}.pow(unrotated) - 1;
        ans *= now;
    }
    ans -= 1;
    ans += zero;
    cout << ans.val() << endl;
    return 0;
}
