#include <bits/stdc++.h>
using namespace std;
long long gcd(long long a, long long b) {
  while (1) {
    if (a < b) swap(a, b);
    if (!b) break;
    a %= b;
  }
  return a;
}
long long mpow(long long x, long long n) {
  long long ans = 1;
  while (n != 0) {
    if (n & 1) ans = ans * x % 1000000007;
    x = x * x % 1000000007;
    n = n >> 1;
  }
  return ans;
}
int main() {
  long long n;
  cin >> n;
  vector<pair<long long, long long> > seki, gyaku;
  set<pair<long long, long long> > se;
  long long a, b, f = 0;
  for (int i = 0; i < n; ++i) {
    cin >> a >> b;
    if (a == 0 && b == 0) {
      f = 1;
      continue;
    }
    if (a * b != 0) {
      long long g = gcd(abs(a), abs(b));
      a /= g;
      b /= g;
    } else {
      if (a == 0)
        b = 1;
      else
        a = 1;
    }
    if (a * b < 0) {
      a = -1 * abs(a);
      b = abs(b);
    }
    seki.push_back({a, b});
    se.insert({a, b});
    if (a * b < 0) {
      a = abs(a);
      b = -1 * abs(b);
    }
    gyaku.push_back({-1 * b, a});
  }
  sort(seki.begin(), seki.end());
  sort(gyaku.begin(), gyaku.end());
  vector<long long> kazu;
  auto it = se.begin();
  for (long long j = 0; j < (long long)se.size(); ++j) {
    long long count = 1;
    count += mpow(2, upper_bound(seki.begin(), seki.end(), *it) -
                         lower_bound(seki.begin(), seki.end(), *it)) -
             1;
    count += mpow(2, upper_bound(gyaku.begin(), gyaku.end(), *it) -
                         lower_bound(gyaku.begin(), gyaku.end(), *it)) -
             1;
    it++;
    kazu.push_back(count);
  }
  sort(kazu.begin(), kazu.end());
  int flag = 1;
  long long nowkazu = kazu[0];
  long long ans = kazu[0];
  for (long long k = 1; k < (long long)kazu.size(); ++k) {
    if (flag && kazu[k] == nowkazu && kazu[k] != 2) {
      flag = 0;
      continue;
    }
    flag = 1;
    nowkazu = kazu[k];
    ans = ans * kazu[k] % 1000000007;
  }
  if (f == 1) ans++;
  cout << ans - 1 << endl;
  return 0;
}
