#include <bits/stdc++.h>
using namespace std;
constexpr long long MOD = 1000000007;
long long GCD(long long A, long long B) {
  if (B == 0) return A;
  return GCD(B, A % B);
}
class UnionFind {
 private:
  vector<int> Rank, Vol, Root;

 public:
  UnionFind(int N) : Rank(N, 1), Vol(N, 1), Root(N) {
    for (int i = 0; i < N; i++) Root[i] = i;
  }
  int Find(int N) { return (N == Root[N] ? N : Root[N] = Find(Root[N])); }
  bool Same(int X, int Y) { return Find(X) == Find(Y); }
  void Union(int X, int Y) {
    X = Find(X), Y = Find(Y);
    if (X == Y) return;
    if (Rank[X] > Rank[Y])
      Root[X] = Y, Vol[Y] += Vol[X];
    else if (Rank[X] < Rank[Y])
      Root[Y] = X, Vol[X] += Vol[Y];
    else
      Root[Y] = X, Vol[X] += Vol[Y], Rank[X]++;
  }
  int Size(int N) { return Vol[Find(N)]; }
};
long long Pow(long long X) {
  if (X == 0) return 1;
  if (X % 2 == 0) {
    long long Y = Pow(X / 2);
    return (Y * Y) % MOD;
  }
  return (2 * Pow(X - 1)) % MOD;
}
int main() {
  int N;
  cin >> N;
  vector<pair<long long, long long> > P(N);
  for (int i = 0; i < N; i++) {
    cin >> P[i].first >> P[i].second;
    if (P[i].first < 0) P[i].first = -P[i].first, P[i].second = -P[i].second;
    long long G = GCD(abs(P[i].first), abs(P[i].second));
    P[i].first /= G, P[i].second /= G;
  }
  map<pair<long long, long long>, int> mp;
  UnionFind UF(N);
  for (int i = 0; i < N; i++) {
    mp[P[i]]++;
  }
  long long ANS = 1;
  map<pair<long long, long long>, bool> mp2;
  for (int i = 0; i < N; i++) {
    if (!mp2[P[i]]) {
      pair<long long, long long> Q;
      Q.first = P[i].second, Q.second = -P[i].first;
      if (Q.first < 0) Q.first = -Q.first, Q.second = -Q.second;
      long long X = mp[P[i]], Y = mp[Q];
      long long COUNT = Pow(X) + Pow(Y) + MOD - 1;
      COUNT %= MOD;
      ANS *= COUNT;
      ANS %= MOD;
      mp2[P[i]] = mp2[Q] = true;
    }
  }
  cout << (ANS + MOD - 1) % MOD << endl;
}
