#include <bits/stdc++.h>
using namespace std;
using lint = long long;
const lint inf = 1LL << 60;
const lint mod = 1000000007;
struct mint {
  lint v;
  lint _mod;
  mint() : v(0) {}
  mint(signed v, lint _mod = mod) : v(v), _mod(_mod) {}
  mint(lint t, lint _mod = mod) : _mod(_mod) {
    v = t % _mod;
    if (v < 0) v += _mod;
  }
  mint pow(lint k) {
    mint res(1), tmp(v);
    while (k) {
      if (k & 1) res *= tmp;
      tmp *= tmp;
      k >>= 1;
    }
    return res;
  }
  static mint add_identity() { return mint(0); }
  static mint mul_identity() { return mint(1); }
  mint inv() { return pow(_mod - 2); }
  mint &operator+=(mint a) {
    v += a.v;
    if (v >= _mod) v -= _mod;
    return *this;
  }
  mint &operator-=(mint a) {
    v += _mod - a.v;
    if (v >= _mod) v -= _mod;
    return *this;
  }
  mint &operator*=(mint a) {
    v = v * a.v % _mod;
    return *this;
  }
  mint &operator/=(mint a) { return (*this) *= a.inv(); }
  mint operator+(mint a) const { return mint(v) += a; };
  mint operator-(mint a) const { return mint(v) -= a; };
  mint operator*(mint a) const { return mint(v) *= a; };
  mint operator/(mint a) const { return mint(v) /= a; };
  mint operator-() const { return v ? mint(_mod - v) : mint(v); }
  bool operator==(const mint a) const { return v == a.v; }
  bool operator!=(const mint a) const { return v != a.v; }
  bool operator<(const mint a) const { return v < a.v; }
};
ostream &operator<<(ostream &os, mint m) { return os << m.v; }
template <typename T = int>
T gcd(T a, T b) {
  if (a < b) return gcd(b, a);
  if (b == 0) return a;
  T r;
  while ((r = a % b)) {
    a = b;
    b = r;
  }
  return b;
}
template <typename T = int>
T lcm(T m, T n) {
  if ((0 == m) || (0 == n)) return 0;
  return ((m / gcd(m, n)) * n);
}
int main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  lint n;
  cin >> n;
  vector<lint> a(n), b(n);
  for (int i = 0; i < n; ++i) {
    cin >> a[i] >> b[i];
  }
  map<pair<lint, lint>, lint> pos, neg;
  lint zero = 0;
  set<pair<lint, lint>> used;
  for (int i = 0; i < n; ++i) {
    if (a[i] == 0 && b[i] == 0) {
      zero++;
    } else if (a[i] * b[i] > 0) {
      if (a[i] < 0) a[i] *= -1;
      if (b[i] < 0) b[i] *= -1;
      lint g = gcd(a[i], b[i]);
      a[i] /= g;
      b[i] /= g;
      pos[{a[i], b[i]}]++;
      used.insert({a[i], b[i]});
    } else if (a[i] * b[i] < 0) {
      if (a[i] < 0) a[i] *= -1;
      if (b[i] < 0) b[i] *= -1;
      lint g = gcd(a[i], b[i]);
      a[i] /= g;
      b[i] /= g;
      neg[{b[i], a[i]}]++;
      used.insert({b[i], a[i]});
    } else {
      if (a[i] == 0) {
        pos[{0, 1}]++;
      } else if (b[i] == 0) {
        neg[{0, 1}]++;
      }
      used.insert({0, 1});
    }
  }
  mint ret = 1;
  for (auto &p : used) {
    ret *= (mint(2).pow(pos[p]) + mint(2).pow(neg[p]) - 1);
  }
  ret += zero;
  cout << ret - 1 << "\n";
  return 0;
}
