#include <bits/stdc++.h>
using namespace std;
const long long mod = 1000000007;
const long double inf = 1e9 + 10;
const long double INF = 1e18;
const long double EPS = 1e-10;
const int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
const int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
template <class T>
bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T>
bool chmin(T &a, const T &b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
struct Point {
  long double x, y;
  Point(long double x = 0, long double y = 0) : x(x), y(y) {}
  Point operator+(Point &p) { return Point(x + p.x, y + p.y); }
  Point operator-(Point &p) { return Point(x - p.x, y - p.y); }
  Point operator*(long double k) { return Point(x * k, y * k); }
  Point operator/(long double k) { return Point(x / k, y / k); }
  bool operator<(const Point &p) const { return x != p.x ? x < p.x : y < p.y; }
  bool operator==(const Point &p) const {
    return fabs(x - p.x) < EPS && fabs(y - p.y) < EPS;
  }
};
long double norm(Point p) { return p.x * p.x + p.y * p.y; }
long double dist(Point p) { return sqrt(norm(p)); }
long double dot(Point p1, Point p2) { return p1.x * p2.x + p1.y * p2.y; }
long double cross(Point p1, Point p2) { return p1.x * p2.y - p1.y * p2.x; }
Point rotate(Point p, long double theta) {
  return Point(p.x * cos(theta) - p.y * sin(theta),
               p.x * sin(theta) + p.y * cos(theta));
}
int ccw(Point p0, Point p1, Point p2) {
  Point v1 = p1 - p0, v2 = p2 - p0;
  if (cross(v1, v2) > 0)
    return 1;
  else if (cross(v1, v2) < 0)
    return -1;
  else if (dot(v1, v2) < 0)
    return 2;
  else if (norm(v1) < norm(v2))
    return -2;
  else
    return 0;
}
bool intersect(Point p1, Point p2, Point p3, Point p4) {
  return (ccw(p1, p2, p3) * ccw(p1, p2, p4) <= 0 &&
          ccw(p3, p4, p1) * ccw(p3, p4, p2) <= 0);
}
long double getDistanceLP(Point p1, Point p2, Point p3) {
  return fabs(cross(p2 - p1, p3 - p1) / dist(p2 - p1));
}
long double getDistanceSP(Point p1, Point p2, Point p3) {
  if (dot(p2 - p1, p3 - p1) < 0)
    return dist(p3 - p1);
  else if (dot(p1 - p2, p3 - p2) < 0)
    return dist(p3 - p2);
  else
    return getDistanceLP(p1, p2, p3);
}
long double getDistanceTS(Point p1, Point p2, Point p3, Point p4) {
  if (intersect(p1, p2, p3, p4)) return 0;
  long double ans = INF;
  ans = min(ans, getDistanceSP(p1, p2, p3));
  ans = min(ans, getDistanceSP(p1, p2, p4));
  ans = min(ans, getDistanceSP(p3, p4, p1));
  ans = min(ans, getDistanceSP(p3, p4, p2));
  return ans;
}
vector<Point> convex_hull(vector<Point> &ps, int n) {
  sort(ps.begin(), ps.end());
  int k = 0;
  vector<Point> qs(2 * n);
  for (int i = 0; i < (n); ++i) {
    while (k > 1 && cross(qs[k - 1] - qs[k - 2], ps[i] - qs[k - 1]) <= 0) k--;
    qs[k++] = ps[i];
  }
  for (int i = n - 2, t = k; i >= 0; i--) {
    while (k > t && (cross(qs[k - 1] - qs[k - 2], ps[i] - qs[k - 1]) <= 0)) k--;
    qs[k++] = ps[i];
  }
  qs.resize(k - 1);
  return qs;
}
struct Circle {
  Point p;
  long double r;
  Circle() {}
  Circle(Point p, long double r) : p(p), r(r) {}
};
vector<Point> getIntersections(Circle c1, Circle c2) {
  long double d = dist(c2.p - c1.p);
  long double rc = (c1.r * c1.r + d * d - c2.r * c2.r) / (2 * d);
  long double rs = sqrt(c1.r * c1.r - rc * rc);
  Point e1 = (c2.p - c1.p) / d;
  Point e2 = rotate(e1, M_PI / 2) * rs;
  Point e3 = rotate(e1, -M_PI / 2) * rs;
  e1 = e1 * rc;
  Point a = c1.p + e1 + e2;
  Point b = c1.p + e1 + e3;
  return {a, b};
}
struct Compress {
  vector<long long> xc;
  Compress() {}
  void add(vector<long long> v) {
    for (long long x : v) xc.push_back(x);
  }
  void add(long long x) { xc.push_back(x); }
  void build() {
    sort(xc.begin(), xc.end());
    xc.erase(unique(xc.begin(), xc.end()), xc.end());
  }
  long long get(long long &x) {
    return lower_bound(xc.begin(), xc.end(), x) - xc.begin();
  }
  const long long &operator[](int k) const { return xc[k]; }
  long long size() { return xc.size(); }
};
bool cmp(Point p1, Point p2) { return cross(p1, p2) > 0; }
long long pow2[200300];
void init() {
  pow2[0] = 1;
  for (int i = 0; i < (200200); ++i) {
    pow2[i + 1] = pow2[i] * 2 % mod;
  }
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout << fixed << setprecision(50);
  init();
  long long n;
  cin >> n;
  vector<Point> p[2];
  long long ans = 0;
  for (int i = 0; i < (n); ++i) {
    Point a;
    cin >> a.x >> a.y;
    if (a.x == 0 && a.y == 0) {
      ans++;
      continue;
    }
    if (a.x > 0 && a.y >= 0)
      p[0].push_back(a);
    else if (a.x <= 0 && a.y > 0) {
      a.x *= -1;
      swap(a.x, a.y);
      p[1].push_back(a);
    } else if (a.x < 0 && a.y <= 0) {
      a = a * (-1);
      p[0].push_back(a);
    } else {
      a = a * (-1);
      a.x *= -1;
      swap(a.x, a.y);
      p[1].push_back(a);
    }
  }
  for (int i = 0; i < (2); ++i) sort(p[i].begin(), p[i].end(), cmp);
  vector<long long> siz(2);
  for (int i = 0; i < (2); ++i) siz[i] = p[i].size();
  vector<long long> idx(2, 0);
  long long res = 1;
  vector<long long> cnt(2, 1);
  while (idx[0] < siz[0] && idx[1] < siz[1]) {
    for (int i = 0; i < (2); ++i) {
      while (idx[i] + 1 < siz[i] &&
             (fabs((cross(p[i][idx[i]], p[i][idx[i] + 1])) - (0)) < EPS)) {
        cnt[i]++;
        idx[i]++;
      }
    }
    if ((fabs((cross(p[0][idx[0]], p[1][idx[1]])) - (0)) < EPS)) {
      res = (pow2[cnt[0]] + pow2[cnt[1]] - 1) % mod * res % mod;
      idx[0]++, idx[1]++;
      cnt[0] = 1, cnt[1] = 1;
    } else if (cross(p[0][idx[0]], p[1][idx[1]]) > 0) {
      res = res * pow2[cnt[0]] % mod;
      idx[0]++;
      cnt[0] = 1;
    } else {
      res = res * pow2[cnt[1]] % mod;
      idx[1]++;
      cnt[1] = 1;
    }
  }
  for (int i = 0; i < (2); ++i) {
    res = res * pow2[siz[i] - idx[i]] % mod;
  }
  res = (res - 1 + mod) % mod;
  ans = (ans + res) % mod;
  cout << ans << '\n';
  return 0;
}
