/*    特徴    */
// mapのkeyにpairを使う
// 座標で考える

/*    教訓    */
// 何かをグループ分けしたい時、バケツは強い
// mapもバケツの進化系

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

using ll = long long;
using ld  = long double;
const int INF=1e9+7;
const ll LINF=9223372036854775807;
const ll MOD=1e9+7;
const ld PI=acos(-1);
const ld EPS = 1e-9; //微調整用（EPSより小さいと0と判定など）

#define begin_end(a) a.begin(),a.end() //sort(begin_end(vec));
#define REP(i,m,n) for(ll i=(ll)(m) ; i < (ll) (n) ; i++ )
#define rep(i,n) REP(i,0,n)

// -------- template end - //


// - library ------------- //

ll llpow(ll a, ll b){
    if(b == 0){
        return 1;
    }
    ll ans = llpow(a, b / 2);
    ans = ans * ans % MOD;
    if(b % 2 == 1){
        ans = ans * a % MOD;
    }
    return ans;
}

// --------- library end - //



// - main() -------------- //

int main(){


  ll N;
  cin >> N;

  // イワシを入れるための二分割された四角いバケツ
  // key : <a, b>
  // value : <(a, b)であるイワシの数, (-a, b)であるイワシの数>
  // 同じバケツの違うセクションに入れられたイワシ同士は仲が悪い
  // それ以外の組み合わせのイワシは仲が良い（ただし、(0, 0)のイワシは全員と仲が悪い）
  map<pair<ll, ll>, pair<ll, ll> > sardine_buckets;

  // 孤高のイワシ（0, 0)の数
  ll double_zero_sardines = 0;

  rep(i, N){
    ll a, b;
    cin >> a >> b;

    // a, bを既約分数で表す（a, bを同じ割合のまま互いに素にする）
    // つまり、(a, b) の最大公約数で割ればいい
    ll gcd_ab = gcd(a, b);
    // (負, 負) -> (正, 正), (正, 負) -> (負, 正) に統一する
    // C++17 からの gcd() は正の値を返す（特殊な条件で負になることもあるらしいが不明）ので、処理をする必要がある
    // __gcd() を使うなら、__gcd(正, 負) もしくは __gcd(負, 負) とすると負の数を返すようなので、何もしなくても自動でひっくり返る
    if (b < 0){
      a = -a;
      b = -b;
    }

    if (gcd_ab == 0) {
      // 孤高のイワシの場合
      double_zero_sardines++;
    }
    else if (a != 0 && b != 0){
      // 通常のイワシの場合
      a /= gcd_ab;
      b /= gcd_ab;

      // (a, b) = (正, 正)のイワシは、普通に(a, b)のバケツに入れる
      if (a >= 0){
        pair<ll, ll> pair_ab = make_pair(a, b);
        // イワシをセクション1に放り込む
        sardine_buckets[pair_ab].first++;
      }
      // (a, b) = (負, 正)になっているイワシは、(b, -a)のバケツに入れればいいので、正にしてひっくり返す
      // ex) (-3, 2) のイワシは、(2, 3) のイワシと仲が悪いので、(2, 3)のラベルがついたバケツ（のセクション2）に入れればいい
      else {
        a = -a;
        swap(a, b);

        pair<ll, ll> pair_ab = make_pair(a, b);

        // イワシをセクション2に放り込む
        sardine_buckets[pair_ab].second++;
      }
    }
    else {
      // (0, *) or (*, 0) の場合
      pair<ll, ll> pair_ab = make_pair(0, 0);
      if (a == 0) sardine_buckets[pair_ab].first++;
      else sardine_buckets[pair_ab].second++;
    }
  }

  // イワシをバケツに入れ終わったので、後は計算する

  ll ans = 1;
  for (pair<pair<ll, ll>, pair<ll, ll> > p : sardine_buckets){
    ll s_pl = p.second.first; // セクション1に入れられた、(a, b)のイワシ
    ll s_mi = p.second.second; // セクション2に入れられた、(-b, a)のイワシ
    ans = (llpow(2, s_pl) + llpow(2, s_mi) - 1) % MOD * ans % MOD;
  }
  
  // 孤高のイワシは1つしか入れられない
  ans = (ans + double_zero_sardines) % MOD;

  // 最後に、「0匹のイワシが入っている」というパターンはNGなので、-1
  ans = (ans - 1) % MOD;

  cout << ans << endl;

// ---------- main() end - //
}