#include <bits/stdc++.h>
using namespace std;
using ll = long long;
template <class T>
bool chmax(T& prov, const T& cur) {
  if (cur > prov) {
    prov = cur;
    return true;
  }
  return false;
}
template <class T>
bool chmin(T& prov, const T& cur) {
  if (cur < prov) {
    prov = cur;
    return true;
  }
  return false;
}
const double PI = 3.14159265358979;
ll gcd(int a, int b) {
  if (a % b == 0) {
    return b;
  }
  return gcd(b, a % b);
}
const ll mod = 1000000007;
ll mypow(ll base, ll n) {
  ll ret = 1;
  for (int i = 0; i < n; i++) {
    ret *= base;
    ret %= mod;
  }
  return ret;
}
namespace std {
template <>
struct hash<pair<ll, ll> > {
  std::size_t operator()(const pair<ll, ll>& k) const {
    using std::hash;
    using std::size_t;
    using std::string;
    return ((hash<ll>()(k.first) ^ (hash<ll>()(k.second) << 1)) >> 1);
  }
};
}  // namespace std
int main() {
  int N;
  cin >> N;
  vector<ll> A(N);
  vector<ll> B(N);
  unordered_map<pair<ll, ll>, ll> group;
  for (int i = 0, i_len = (N); i < (int)N; i++) {
    cin >> A[i] >> B[i];
    ll g = gcd(A[i], B[i]);
    ll x = A[i] / g;
    ll y = B[i] / g;
    if (x < 0) {
      x = -x;
      y = -y;
    }
    pair<ll, ll> key(x, y);
    auto it = group.find(key);
    if (it == group.end()) {
      group.insert(pair<pair<ll, ll>, ll>(key, 1));
    } else {
      (*it).second++;
    }
  }
  ll ans = 1;
  for (auto it = group.begin(); it != group.end(); ++it) {
    auto key = (*it).first;
    ll x = key.second;
    ll y = -key.first;
    if (x < 0) {
      x = -x;
      y = -y;
    }
    ll count = (*it).second;
    if (count == 0) continue;
    pair<ll, ll> find_key(x, y);
    unordered_map<pair<ll, ll>, ll>::iterator target = group.find(find_key);
    if (target == group.end()) {
      ans = (ans * mypow(2, count)) % mod;
    } else {
      ll hoge = (mypow(2, count) + mypow(2, (*target).second) - 1) % mod;
      ans *= hoge;
      ans %= mod;
      (*target).second = 0;
    }
  }
  cout << ans - 1 << endl;
  return 0;
}
