#include <bits/stdc++.h>
using namespace std;
const int MOD = 1000000007;
long long modpow(long long a, long long n) {
  long long res = 1;
  while (n > 0) {
    if (n & 1) res = res * a % MOD;
    a = a * a % MOD;
    n >>= 1;
  }
  return res;
}
class UnionFind {
 public:
  vector<int> parents;
  UnionFind(int N) : parents(N, -1) {}
  int find(int x) {
    if (this->parents[x] < 0) return x;
    return this->parents[x] = this->find(this->parents[x]);
  }
  int size(int x) { return -this->parents[this->find(x)]; }
  void marge(int x, int y) {
    x = this->find(x);
    y = this->find(y);
    if (x == y) return;
    if (this->parents[x] > this->parents[y])
      swap(this->parents[x], this->parents[y]);
    this->parents[x] += this->parents[y];
    this->parents[y] = x;
  }
  bool is_same(int x, int y) { return this->find(x) == this->find(y); }
  void check() {
    for (auto& parent : parents) cerr << parent << " ";
    cerr << endl;
  }
  int num_union(int lower = 1, int upper = INT_MAX) {
    return count_if(
        this->parents.begin(), this->parents.end(),
        [&](const int& a) { return (lower <= -a) && (-a <= upper); });
  }
};
int main() {
  int N;
  cin >> N;
  vector<vector<long long>> A(N, vector<long long>(2, 0));
  for (auto& a : A) {
    cin >> a[0] >> a[1];
  }
  UnionFind uf(N * 2);
  for (int ii = 0; ii < N; ii++) {
    for (int jj = ii + 1; jj < N; jj++) {
      if (A[ii][0] * A[jj][0] + A[ii][1] * A[jj][1] == 0) {
        uf.marge(ii, N + jj);
        uf.marge(jj, N + ii);
      }
    }
  }
  UnionFind uf2(N);
  for (int ii = 0; ii < N; ii++) {
    if (uf.parents[ii] >= 0) {
      uf2.marge(ii, uf.parents[ii]);
    }
  }
  long long ans = 1;
  for (int ii = 0; ii < N; ii++) {
    if (uf.parents[ii] >= 0) continue;
    if (uf.parents[ii] == -1) {
      ans *= 2;
      ans %= MOD;
      continue;
    }
    int jj = uf.parents[ii + N];
    if (jj > ii) continue;
    ans *= (modpow(2, uf2.size(ii)) + modpow(2, uf2.size(jj)) - 1);
  }
  cout << (ans - 1) % MOD << endl;
  return 0;
}
