#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
using P = pair<ll, ll>;
#define FOR(var, begin, end) for (int var = (begin); var <= (end); var++)
#define RFOR(var, begin, end) for (int var = (begin); var >= (end); var--)
#define REP(var, length) FOR(var, 0, length - 1)
#define RREP(var, length) RFOR(var, length - 1, 0)
#define EACH(value, var) for (auto value : var)
#define SORT(var) sort(var.begin(), var.end())
#define REVERSE(var) reverse(var.begin(), var.end())
#define RSORT(var) SORT(var); REVERSE(var)
#define OPTIMIZE_STDIO ios::sync_with_stdio(false); cin.tie(0); cout.precision(10); cout << fixed
#define endl '\n'

const int INF = 1e9;
const int MOD = 1e9 + 7;
const ll LINF = 1e18;

struct mint {
  ll x;
  mint() : x(0) {
  }
  mint(ll x) : x((x % MOD + MOD) % MOD) {
  }
  mint& operator+=(const mint& r) {
    if ((x += r.x) >= MOD) {
      x -= MOD;
    }
    return *this;
  }
  mint& operator-=(const mint& r) {
    if ((x -= r.x) < 0) {
      x += MOD;
    }
    return *this;
  }
  mint& operator*=(const mint& r) {
    if ((x *= r.x) > MOD) {
      x %= MOD;
    }
    return *this;
  }
  mint& operator++() {
    if ((++x) >= MOD) {
      x -= MOD;
    }
    return *this;
  }
  mint operator++(int) {
    mint ret = x;
    if ((++x) >= MOD) {
      x -= MOD;
    }
    return ret;
  }
  mint& operator--() {
    if ((--x) < 0) {
      x += MOD;
    }
    return *this;
  }
  mint operator--(int) {
    mint ret = x;
    if ((--x) < 0) {
      x += MOD;
    }
    return ret;
  }
  mint operator+(const mint& r) {
    mint ret;
    return ret = x + r.x;
  }
  mint operator-(const mint& r) {
    mint ret;
    return ret = x - r.x;
  }
  mint operator*(const mint& r) {
    mint ret;
    return ret = x * r.x;
  }
  mint operator-() {
    return mint() - *this;
  }
  bool operator<(const mint& a) {
    return x < a.x;
  }
  bool operator>(const mint& a) {
    return x > a.x;
  }
  bool operator<=(const mint& a) {
    return x <= a.x;
  }
  bool operator>=(const mint& a) {
    return x >= a.x;
  }
  bool operator==(const mint& a) {
    return x == a.x;
  }
  bool operator!=(const mint& a) {
    return x != a.x;
  }
};
ostream& operator<<(ostream& os, const mint& r) {
  os << r.x;
  return os;
}
ostream& operator>>(ostream& os, const mint& r) {
  os >> r.x;
  return os;
}

ll mpow(ll a, ll n) {
  ll res = 1;
  while(n > 0) {
    if (n & 1) res = res * a % MOD;
    a = a * a % MOD;
    n >>= 1;
  }
  return res;
}

void solve(istream& cin, ostream& cout) {
  int n;
  cin >> n;
  map<P, int> mp;
  int zero = 0;
  REP(i, n) {
    ll a, b;
    cin >> a >> b;
    ll g = __gcd(a, b);
    if (g == 0) {
      zero++;
      continue;
    }
    long double ai, bi;
    if (a == 0) {
      ai = 0;
      bi = 1;
    } else if (b == 0) {
      ai = 1;
      bi = 0;
    } else {
      ai = a / g;
      bi = b / g;
      if (ai > 0 && bi < 0) {
        ai = -ai;
        bi = -bi;
      }
    }
    if (!mp.count(P(ai, bi))) {
      mp[P(ai, bi)] = 1;
    } else {
      mp[P(ai, bi)]++;
    }
  }
  mint ans = 1;
  int good = n;
  for (auto it = mp.begin(); it != mp.end(); it++) {
    ll x = it->first.first;
    ll y = it->first.second;
    if (x >= 1) continue;
    P now = P(x, y);
    P bad;
    if (x == 0) bad = P(1, 0);
    else if (y == 0) bad = P(0, 1);
    else if (x < 0 && y > 0) bad = P(y, -x);
    else {
      bad = P(-y, x);
    }
    if (!mp.count(bad)) continue;
    ans *= (mpow(2, mp[now]) - 1 + mpow(2, mp[bad]) - 1 + 1);
    good -= (mp[now] + mp[bad]);
  }
  good -= zero;
  ans *= mpow(2, good);
  ans += zero - 1;
  cout << ans << endl;
}

#ifndef TEST
int main() {
  OPTIMIZE_STDIO;
  solve(cin, cout);
  return 0;
}
#endif


Measured memory_bytes: 16072