#include <bits/stdc++.h>
using namespace std;
template <class T>
ostream &operator<<(ostream &o, const vector<T> &obj) {
  o << "[";
  for (int i = 0; i < (int)obj.size(); ++i) o << (i > 0 ? ", " : "") << obj[i];
  o << "]";
  return o;
}
template <class T>
ostream &operator<<(ostream &o, const vector<vector<T>> &obj) {
  o << "[" << endl;
  for (int i = 0; i < (int)obj.size(); ++i) o << "  " << obj[i] << endl;
  o << "]";
  return o;
}
template <class T, class U>
ostream &operator<<(ostream &o, const pair<T, U> &obj) {
  o << "(" << obj.first << ", " << obj.second << ")";
  return o;
}
template <class T, class U>
ostream &operator<<(ostream &o, const map<T, U> &obj) {
  o << "{";
  for (auto itr = obj.begin(); itr != obj.end(); ++itr)
    o << (itr != obj.begin() ? ", " : "") << *itr;
  o << "}";
  return o;
}
template <class T>
ostream &operator<<(ostream &o, const set<T> &obj) {
  o << "{";
  for (auto itr = obj.begin(); itr != obj.end(); ++itr)
    o << (itr != obj.begin() ? ", " : "") << *itr;
  o << "}";
  return o;
}
template <class T>
ostream &operator<<(ostream &o, const queue<T> &obj) {
  queue<T> obj_cp = obj;
  bool first = true;
  o << "{";
  while (!obj_cp.empty()) {
    o << (!first ? ", " : "") << obj_cp.front();
    obj_cp.pop();
    first = false;
  }
  o << "}";
  return o;
}
void print() { cout << "\n"; }
template <class Head, class... Body>
void print(Head head, Body... body) {
  cout << head << " ";
  print(body...);
}
int gcd(int a, int b) {
  if (a % b == 0) {
    return b;
  } else {
    return gcd(b, a % b);
  }
}
class Fish {
 public:
  long long A;
  long long B;
  bool used;
  Fish(long long A_, long long B_) {
    long long a = abs(A_), b = abs(B_);
    if (a > 0 || b > 0) {
      long long g = gcd(a, b);
      A_ /= g;
      B_ /= g;
    }
    if (A_ >= 0 && !(A_ == 0 && B_ < 0)) {
      A = A_;
      B = B_;
    } else {
      A = -A_;
      B = -B_;
    }
    used = false;
  }
  bool operator<(const Fish &other) const {
    long long outer = A * other.B - B * other.A;
    return outer > 0;
  }
  bool operator==(const Fish &other) const {
    long long outer = A * other.B - B * other.A;
    return outer == 0;
  }
};
ostream &operator<<(ostream &o, const Fish &obj) {
  o << "Fish " << obj.A << "," << obj.B;
  return o;
}
int main(int argc, char const *argv[]) {
  int N;
  cin >> N;
  vector<Fish> all_fish;
  for (int i = 0; i < N; ++i) {
    long long A, B;
    cin >> A >> B;
    all_fish.push_back({A, B});
  }
  sort(all_fish.begin(), all_fish.end());
  long long ans = 1;
  int i = 0, j = 0;
  while (i < N) {
    const Fish &fish = all_fish[i];
    if (fish.used) {
      ++i;
      continue;
    }
    j = i + 1;
    while (j < N && all_fish[j] == all_fish[i]) {
      ++j;
    }
    long long n1 = 1;
    while (i < j) {
      n1 = (n1 * 2) % 1000000007;
      ++i;
    }
    long long n2 = 0;
    if (fish.B <= 0) {
      const Fish other = Fish(-fish.B, fish.A);
      auto it_l = lower_bound(all_fish.begin(), all_fish.end(), other);
      auto it_u = upper_bound(all_fish.begin(), all_fish.end(), other);
      if (it_l != it_u) {
        n2 = 1;
        for (auto it = it_l; it != it_u; ++it) {
          it->used = true;
          n2 = (n2 * 2) % 1000000007;
        }
      }
    }
    if (n2 == 0) {
      ans = (ans * n1) % 1000000007;
    } else {
      ans = (ans * ((n1 + n2 - 1) % 1000000007)) % 1000000007;
    }
    if (i == N - 1) break;
  }
  cout << (ans + 1000000007 - 1) % 1000000007 << endl;
  return 0;
}
