#include <bits/stdc++.h>
using namespace std;
inline long long madd(long long a, long long b) {
  a %= 1000000007;
  b %= 1000000007;
  return (a + b) % 1000000007;
}
inline long long msub(long long a, long long b) {
  a %= 1000000007;
  b %= 1000000007;
  a += 1000000007;
  return (a - b) % 1000000007;
}
inline long long mmul(long long a, long long b) {
  a %= 1000000007;
  b %= 1000000007;
  return (a * b) % 1000000007;
}
inline long long mpow(long long a, long long r) {
  long long res = 1;
  while (r > 0) {
    if (r & 1) res = res * a % 1000000007;
    a = a * a % 1000000007;
    r >>= 1;
  }
  return res;
}
inline long long minv(long long a) {
  a %= 1000000007;
  long long b = 1000000007, u = 0, v = 1;
  while (a) {
    long long t = b / a;
    b -= t * a;
    swap(a, b);
    u -= t * v;
    swap(u, v);
  }
  if (u < 0) u += 1000000007;
  return u;
}
inline long long mdiv(long long a, long long b) {
  a %= 1000000007;
  a *= minv(b);
  return a % 1000000007;
}
struct UnionFind {
  vector<int> data;
  UnionFind(int size) : data(size, -1) {}
  bool unite(int x, int y) {
    x = root(x);
    y = root(y);
    if (x != y) {
      if (data[y] < data[x]) swap(x, y);
      data[x] += data[y];
      data[y] = x;
    }
    return x != y;
  }
  bool same(int x, int y) { return root(x) == root(y); }
  int root(int x) { return data[x] < 0 ? x : data[x] = root(data[x]); }
  int size(int x) { return -data[root(x)]; }
};
long long gcd(long long a, long long b) {
  if (a < 0) a *= -1;
  if (b < 0) b *= -1;
  if (a < b) {
    long long c = b;
    b = a;
    a = c;
  }
  if ((a % b) == 0)
    return b;
  else
    return gcd(b, a % b);
}
pair<long long, long long> kiyaku(long long a, long long b) {
  if (a == 0) return pair<long long, long long>(0, 1);
  if (b == 0) return pair<long long, long long>(1, 0);
  return pair<long long, long long>(a / gcd(a, b), b / gcd(a, b));
}
int main() {
  map<pair<long long, long long>, pair<double, int>> mp;
  map<pair<double, int>, pair<long long, long long>> mpinv;
  int n;
  long long a, b;
  long long res = 1;
  long long zerocnt = 0;
  cin >> n;
  for (long long i = (0); i < (n); ++i) {
    cin >> a >> b;
    if (a < 0) {
      a *= -1;
      b *= -1;
    }
    if (a == 0 && b == 0) {
      zerocnt++;
      continue;
    }
    pair<long long, long long> p = kiyaku(a, b);
    if (mp.find(p) != mp.end())
      mp[p].second++;
    else
      mp[p] = pair<double, int>(atan2(b, a), 1);
  }
  for (auto p : mp) {
    mpinv[p.second] = p.first;
  }
  for (auto pp : mpinv) {
    a = -pp.second.second;
    b = pp.second.first;
    pair<long long, long long> p = kiyaku(a, b);
    auto it2 = mp.find(p);
    if (it2 != mp.end()) {
      long long nn = pp.first.second;
      long long mm = it2->second.second;
      auto it3 = mpinv.find(it2->second);
      mpinv.erase(it3);
      res = mmul(res, madd(mpow(2, nn), mpow(2, mm) - 1));
      continue;
    }
    long long nn = pp.first.second;
    res = mmul(res, mpow(2, nn));
  }
  res = madd(res, zerocnt);
  cout << msub(res, 1);
  return 0;
}
