#include <bits/stdc++.h>

using namespace std;
using int64 = long long;

constexpr int DEBUG = 0;

tuple<int64, int64> Normalize(int64 x, int64 y) {
  if (x == 0 && y == 0) return {0, 0};
  if (x == 0) return {0, 1};
  if (y == 0) return {1, 0};
  int64 d = __gcd(x, y);
  x /= d;
  y /= d;
  if (x < 0) {
    x *= -1;
    y *= -1;
  }
  return {x, y};
}

tuple<int64, int64> Pair(int64 x, int64 y) {
  if (x == 0 && y == 0) return {0, 0};
  if (x == 0) return {1, 0};
  if (y == 0) return {0, 1};
  int64 rx = -y;
  int64 ry = x;
  if (rx < 0) {
    rx *= -1;
    ry *= -1;
  }
  return {rx, ry};
}

constexpr int64 P = 1000000007;

struct FiniteField {
 private:
  int64 x;
  static inline int64 Normalize(int64 x) {
    if (0 <= x && x < P) return x; x %= P; if (x < 0) x += P; return x;
  }
 public:
  FiniteField(int64 x) : x(Normalize(x)) {}
  FiniteField() : x(0) {}
  int64 Value() const { return x; }
  inline FiniteField operator+(FiniteField o) const {
    FiniteField r(*this); r += o; return r;
  }
  inline FiniteField operator-(FiniteField o) const {
    FiniteField r(*this); r -= o; return r;
  }
  inline FiniteField operator* (FiniteField o) const {
    FiniteField r(*this); r *= o; return r;
  }
  inline FiniteField operator/ (FiniteField o) const {
    FiniteField r(*this); r /= o; return r;
  }
  inline void operator+= (FiniteField o) { x = (x + o.x) % P; }
  inline void operator-= (FiniteField o) { x = (x + P - o.x) % P; }
  inline void operator*= (FiniteField o) { x = (x * o.x) % P; }
  void operator/=(FiniteField o) {
    int64 p = P - 2; while (p) { if (p % 2) { *this *= o; } o *= o; p /= 2; }
  }
};

ostream& operator<<(ostream& s, const FiniteField& v) { s << v.Value(); return s; }

FiniteField Power(FiniteField x, int p) {
  if (p < 0) return FiniteField(1) / Power(x, -p);
  FiniteField value = 1;
  while (p) {
    if (p % 2) value *= x;
    x *= x;
    p /= 2;
  }
  return value;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);

  int n;
  cin >> n;
  map<tuple<int64, int64>, int> m;
  for (int i = 0; i < n; i++) {
    int64 x, y;
    cin >> x >> y;
    tie(x, y) = Normalize(x, y);
    m[{x, y}]++;
  }

  FiniteField ans = 1;
  set<tuple<int64, int64>> visited;
  for (const auto& kv : m) {
    tuple<int64, int64> v1 = kv.first;
    if (visited.find(v1) != visited.end()) {
      continue;
    }
    if (v1 == make_tuple(0, 0)) {
      ans *= kv.second + 1;
      continue;
    }
    int c1 = kv.second;
    auto v2 = Pair(get<0>(v1), get<1>(v1));
    int c2 = m[v2];
    ans *= (Power(2, c1) + Power(2, c2) - 1);
    visited.insert(v1);
    visited.insert(v2);
  }
  ans -= 1;
  cout << ans << endl;
}