#include <bits/stdc++.h>
using namespace std;
#define rep(i, a) for(int i=0; i<(a); i++)
typedef long long ll;
template<typename T>
struct edge {
  int src, to;
  T cost;
  edge(int to, T cost) : src(-1), to(to), cost(cost) {}
  edge(int src, int to, T cost) : src(src), to(to), cost(cost) {}
  edge &operator=(const int &x) {
    to = x;
    return *this;
  }
  operator int() const { return to; }
};
template<typename T>
using Edges = vector<edge<T>>;
template<typename T>
using WeightedGraph = vector<Edges<T>>;
using UnWeightedGraph = vector<vector<int>>;
template<typename T>
using Matrix = vector<vector<T>>;

/////////////////////////////////////////////////////////////////////

const ll inf = 1LL<<60;
const ll mod = 1000000007;

ll modpow(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;
}

int main()
{
  ll n; cin>>n;
  ll z = 0;
  map<pair<ll, ll>, ll> mp;
  rep(i, n) {
    ll aa, bb; cin>>aa>>bb;
    if (aa == 0 && bb == 0) {
      z++; continue;
    }
    if (aa == 0) bb = 1;
    else if (bb == 0) aa = 1;
    else {
      ll g = gcd(aa, bb);
      aa /= g; bb /= g;
      if (aa < 0) {
        aa *= -1; bb *= -1;
      }
    }
    mp[{aa,bb}]++;
  }
  ll ans = 1;
  for (auto v:mp) {
    ll tmp = 1;
    ll x = v.first.first;
    ll y = v.first.second;
    if (y < 0) { x = -x; y = -y; }
    ll a = (modpow(2, v.second)+mod-1)%mod;
    ll b = (modpow(2, mp[{y, -x}])+mod-1)%mod;
    tmp = (tmp + a) % mod;
    tmp = (tmp + b) % mod;
    ans = (ans * tmp) % mod;
    mp[v.first] = 0;
    mp[{y, -x}] = 0;
  }
  cout << ans-1+z << endl;

  return 0;
}
