#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int mod = 1000000007;
struct mint {
  ll x;
  mint(ll x = 0) : x((x % mod + mod) % mod) {}
  mint operator-() const { return mint(-x); }
  mint &operator+=(const mint m) {
    if ((x += m.x) >= mod) x -= mod;
    return *this;
  }
  mint &operator-=(const mint m) {
    if ((x += mod - m.x) >= mod) x -= mod;
    return *this;
  }
  mint &operator*=(const mint m) {
    (x *= m.x) %= mod;
    return *this;
  }
  mint operator+(const mint m) const { return mint(*this) += m; }
  mint operator-(const mint m) const { return mint(*this) -= m; }
  mint operator*(const mint m) const { return mint(*this) *= m; }
  mint pow(ll n) const {
    if (!n) return 1;
    mint m = pow(n >> 1);
    m *= m;
    if (n & 1) m *= *this;
    return m;
  }
  mint inv() const { return pow(mod - 2); }
  mint &operator/=(const mint m) { return *this *= m.inv(); }
  mint operator/(const mint m) const { return mint(*this) /= m; }
  bool operator==(const mint m) const { return this->x == m.x; }
};
istream &operator>>(istream &is, const mint &m) { return is >> m.x; }
ostream &operator<<(ostream &os, const mint &m) { return os << m.x; }
struct combination {
  vector<mint> fact, ifact;
  combination(int n) : fact(n + 1), ifact(n + 1) {
    assert(n < mod);
    fact.at(0) = 1;
    for (int i = 1; i <= n; i++) {
      fact.at(i) = fact.at(i - 1) * i;
    }
    ifact.at(n) = fact.at(n).inv();
    for (int i = n; i >= 1; i--) {
      ifact.at(i - 1) = ifact.at(i) * i;
    }
  }
  mint operator()(int n, int k) {
    if (k < 0 || k > n) return 0;
    return fact.at(n) * ifact.at(k) * ifact.at(n - k);
  }
};
template <class T>
T euclidean_gcd(T a, T b) {
  if (a < b) return euclidean_gcd(b, a);
  T r;
  while (r = a % b) {
    a = b;
    b = r;
  }
  return b;
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int N;
  cin >> N;
  vector<ll> A(N), B(N);
  map<pair<ll, ll>, ll> cnt;
  map<pair<ll, ll>, bool> is_used;
  ll cnt_A_is_0 = 0;
  ll cnt_B_is_0 = 0;
  ll cnt_AB_is_0 = 0;
  for (int i = 0; i < N; i++) {
    cin >> A[i] >> B[i];
    if (A[i] == 0 && B[i] == 0) {
      cnt_AB_is_0++;
      continue;
    } else if (A[i] == 0) {
      cnt_A_is_0++;
      continue;
    } else if (B[i] == 0) {
      cnt_B_is_0++;
      continue;
    }
    if (B[i] < 0) {
      A[i] *= -1;
      B[i] *= -1;
    }
    ll num = euclidean_gcd(A[i], B[i]);
    cnt[make_pair(A[i] / num, B[i] / num)]++;
    is_used[make_pair(A[i] / num, B[i] / num)] = false;
  }
  mint two = 2;
  mint ans = 1;
  for (auto [p, v] : cnt) {
    if (is_used[p]) continue;
    is_used[p] = true;
    pair<ll, ll> aite = make_pair(p.second, p.first);
    if (p.first < 0)
      aite.second *= -1;
    else
      aite.first *= -1;
    if (cnt.count(aite)) {
      is_used[aite] = true;
      ans *= (two.pow(v) - 1 + two.pow(cnt[aite]) - 1 + 1);
    } else
      ans *= two.pow(v);
  }
  ans *= (two.pow(cnt_A_is_0) - 1 + two.pow(cnt_B_is_0) - 1 + 1);
  ans += cnt_AB_is_0;
  ans -= 1;
  cout << ans << endl;
  return 0;
}
