#include <bits/stdc++.h>
using namespace std;
const long mod = 1000000007;
long modbeki(long N) {
  long res = 1;
  for (int i = 0; i < N; i++) res = (res * 2) % mod;
  return res;
}
long gcd(long a, long b) {
  if (a < b) return gcd(b, a);
  long r = a % b;
  while (r) {
    a = b;
    b = r;
    r = a % b;
  }
  return b;
}
int main() {
  long N;
  cin >> N;
  map<tuple<long, long>, tuple<long, long> > data{};
  long has_origin = 0;
  for (long i = 0; i < N; ++i) {
    long A, B;
    cin >> A >> B;
    if (A * B == 0) {
      if (A == 0 && B == 0) {
        has_origin = 1;
      } else if (A == 0) {
        tuple<long, long> key = make_tuple(0, 1);
        data[key] = make_tuple(get<0>(data[key]), get<1>(data[key]) + 1);
      } else {
        tuple<long, long> key = make_tuple(0, 1);
        data[key] = make_tuple(get<0>(data[key]) + 1, get<1>(data[key]));
      }
    } else {
      long G = gcd(abs(A), abs(B));
      if (A * B < 0) {
        tuple<long, long> key = make_tuple(abs(B) / G, abs(A) / G);
        data[key] = make_tuple(get<0>(data[key]), get<1>(data[key]) + 1);
      } else {
        tuple<long, long> key = make_tuple(abs(A) / G, abs(B) / G);
        data[key] = make_tuple(get<0>(data[key]) + 1, get<1>(data[key]));
      }
    }
  }
  if (data.size() == 0) {
    cout << has_origin << endl;
    return 0;
  }
  vector<long> g(data.size(), 0);
  long i = 0;
  for (auto itr = data.begin(); itr != data.end(); ++itr) {
    long p = get<0>(itr->second);
    long m = get<1>(itr->second);
    g[i] = (modbeki(p) + modbeki(m) - 1) % mod;
    ++i;
  }
  long prod = 1;
  for (size_t i = 0; i < g.size(); ++i) prod = (g[i] * prod) % mod;
  prod = prod - 1;
  cout << (has_origin + prod) % mod << endl;
  return 0;
}
