#include <bits/stdc++.h>
using namespace std;

#define REP(i, m, n) for (int i = (m); i < (int)(n); i++)
#define REPS(i, m, n) for (int i = (m); i <= (int)(n); i++)
#define rep(i, n) REP(i, 0, n)
#define reps(i, n) for (int i = 0; i <= (int)(n); i++)
#define rrep(i, x) for (int i = ((int)(x)-1); i >= 0; i--)
#define rreps(i, x) for (int i = (int)(x); i >= 0; i--)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define pb push_back
#define fi first
#define se second
typedef long long ll;
typedef pair<int, int> P;
const int inf = INT_MAX;
const ll INF = 1LL << 60;
const ll mod = 1e9 + 7;
const double EPS = 1e-10;
const double PI = acos(-1.0);
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
template<typename A, size_t N, typename T> void Fill(A (&array)[N], const T &val) { fill( (T*)array, (T*)(array+N), val ); }
template <class T1, class T2, class Pred = std::less<T2> >
struct sort_pair_second {
    bool operator()(const std::pair<T1,T2>&left, const std::pair<T1,T2>&right) {
        Pred p;
        return p(left.second, right.second);
    }
};

struct mint {
  ll x; // typedef long long ll;
  mint(ll x=0):x((x%mod+mod)%mod){}
  mint operator-() const { return mint(-x);}
  mint& operator+=(const mint a) {
    if ((x += a.x) >= mod) x -= mod;
    return *this;
  }
  mint& operator-=(const mint a) {
    if ((x += mod-a.x) >= mod) x -= mod;
    return *this;
  }
  mint& operator*=(const mint a) { (x *= a.x) %= mod; return *this;}
  mint operator+(const mint a) const { return mint(*this) += a;}
  mint operator-(const mint a) const { return mint(*this) -= a;}
  mint operator*(const mint a) const { return mint(*this) *= a;}
  mint pow(ll t) const {
    if (!t) return 1;
    mint a = pow(t>>1);
    a *= a;
    if (t&1) a *= *this;
    return a;
  }
 
  // for prime mod
  mint inv() const { return pow(mod-2);}
  mint& operator/=(const mint a) { return *this *= a.inv();}
  mint operator/(const mint a) const { return mint(*this) /= a;}
};
istream& operator>>(istream& is, const mint& a) { return is >> a.x;}
ostream& operator<<(ostream& os, const mint& a) { return os << a.x;}

ll modpow(ll a, ll p)
{
  if (p == 0)
    return 1;
  if (!(p % 2))
  {
    ll halfP = p / 2;
    ll half = modpow(a, halfP);
    return half * half % mod;
  }
  else
  {
    return a * modpow(a, p - 1) % mod;
  }
}



vector<P> p;
ll gcd(ll a, ll b) {
  if (b == 0) return a;
  if (a % b == 0) return b;
    return gcd(b, a % b);
}

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

    ll n; cin >> n;
    ll zero = 0;
    map<pair<ll, ll>, pair<ll, ll>> mp;
    rep(i, n) {
      ll x, y;
      cin >> x >> y;
      if (x == 0 && y == 0) {
        zero++;
        continue;
      }
      ll g = gcd(x, y);
      x /= g;
      y /= g;
      if (y < 0) {
        x = -x;
        y = -y;
      }
      if (y == 0 && x < 0) {
        x = -x;
        y = -y;
      }
      bool rot90 = (x <= 0);
      if (rot90) {
        ll tmp = x;
        x = y;
        y = -tmp;
      }
      if (rot90) mp[{x, y}].fi++;
      else mp[{x, y}].se++;
    }
    mint ans = 1;
    for (auto p : mp) {
      ll s = p.se.fi;
      ll t = p.se.se;
      mint now = 1;
      now += modpow(2, s) % mod - 1;
      now += modpow(2, t) % mod - 1;
      ans *= now;
    }
    ans -= 1;
    ans += zero;
    cout << ans << endl;
    return 0;
}

Measured memory_bytes: 19116