bool DBG = false;
// #pragma GCC optimize("Ofast")
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,tune=native")
// #pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
//#include <boost/multiprecision/cpp_dec_float.hpp>
//#include <boost/multiprecision/cpp_int.hpp>
using namespace std;
using ll = long long;
using ld = long double;
using i128 = __int128_t;
//using bint = boost::multiprecision::cpp_int
//using d1024 = boost::multiprecision::number<boost::multiprecision::cpp_dec_float<1024>>;
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define IFOR(i,a,b) for(int i=((b)-1);i>=(a);--i)
#define RPT(i,a,b) for(int i=(a);i<((a)+(b));++i)
#define IRPT(i,a,b) for(int i=((a)+(b)-1);i>=(a);--i)
#define ALL(x) x.begin(),x.end()
#define RALL(x) x.rbegin(),x.rend()
#define fs first
#define sd second
#define couts(x) cout << (x) << (" ")
#define coutn(x) cout << (x) << ("\n")
#define ncouts(x) numout(x),outst[outst_N++] = ' '
#define ncoutn(x) numout(x),outst[outst_N++] = '\n'
#define scouts(x) strout(x),outst[outst_N++] = ' '
#define scoutn(x) strout(x),outst[outst_N++] = '\n'
#define dcouts(x) if(DBG) couts(x)
#define dcoutn(x) if(DBG) coutn(x)
#define endl "\n"
#define psb push_back
#define ppb pop_back
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound
#define LBIT(x,a) (((x)>>(a))&1LL)
#define IBIT(x,a) (((x)>>(a))&1)
#define BCOUNT(x) (__builtin_popcount(x))
template<typename T> std::istream &operator>>(std::istream &is, std::vector<T> &vec){ for (auto &v : vec) is >> v; return is; }
template<typename T1, typename T2> std::istream &operator>>(std::istream &is, std::pair<T1,T2> &p){is >> p.first >> p.second; return is; }
template<typename T> std::ostream &operator<<(std::ostream &os, const std::vector<T> &vec){ os << "["; for (auto v : vec) os << v << ","; os << "]"; return os; }
template<typename T> std::ostream &operator<<(std::ostream &os, const std::deque<T> &vec){ os << "deque["; for (auto v : vec) os << v << ","; os << "]"; return os; }
template<typename T> std::ostream &operator<<(std::ostream &os, const std::set<T> &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }
template<typename T> std::ostream &operator<<(std::ostream &os, const std::unordered_set<T> &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }
template<typename T> std::ostream &operator<<(std::ostream &os, const std::multiset<T> &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }
template<typename T> std::ostream &operator<<(std::ostream &os, const std::unordered_multiset<T> &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }
template<typename T1, typename T2> std::ostream &operator<<(std::ostream &os, const std::pair<T1, T2> &pa){ os << "(" << pa.first << "," << pa.second << ")"; return os; }
template<typename TK, typename TV> std::ostream &operator<<(std::ostream &os, const std::map<TK, TV> &mp){ os << "{"; for (auto v : mp) os << v.first << "=>" << v.second << ","; os << "}"; return os; }
template<typename TK, typename TV> std::ostream &operator<<(std::ostream &os, const std::unordered_map<TK, TV> &mp){ os << "{"; for (auto v : mp) os << v.first << "=>" << v.second << ","; os << "}"; return os; }
std::ostream &operator<<(std::ostream &os, const i128 nu){
  i128 co = nu;
  if(co==0){cout << '0';}
  else{
    string ous; if(co<0){cout<<'-'; co*=-1;}
    while(co){
      ous += (co%10)+'0';
      co /= 10;
    }
    reverse(ALL(ous));
    cout<<ous;
  }
  return os;
}
std::istream &operator>>(std::istream &is, i128 &nu){ string cs; cin >> cs; nu=0;int mn=1; for(auto &x:cs) { if(x!='-'){nu*=10;nu+=(x-'0');} else mn *= -1;} nu *= mn;  return is; }


template<class T> using V = vector<T>;
template<class T> using V2 = V<V<T>>;
template<class T> using V3 = V<V2<T>>;
template<class T> using V4 = V<V3<T>>;


char outst[20'000'000]; int outst_N = 0;
char outst_tmp[200];
template<class NUM >
void numout(NUM n){
  if(n<0) { n*=-1; outst[outst_N++] = '-';}
  if(n==0){ outst[outst_N++] = '0'; return;}
  int cnt = 0;
  while(n>0){
    outst_tmp[cnt++] = '0' + (n % 10);
    n /= 10;
  }
  IFOR(i,0,cnt){
    outst[outst_N++] = outst_tmp[i];
  }
}
void strout(std::string s){
  for(auto x: s){
    outst[outst_N++] = x;
  }
}

constexpr ll LINF = 1LL << 60;
constexpr int IINF = 1 << 28;
constexpr ll mod =  1'000'000'007;

ll modpow(ll a, ll n, ll m) {
	ll res = 1;
	while (n) {
		if (n & 1)res = res * a % m;
		a = a * a%m; n >>= 1;
	}
	return res;
}

struct modstr{
  V<ll> f, invf;
  int n;
  void init(int num){
    f = V<ll>(num);
    invf = V<ll>(num);
    n = num; f[0] = 1;
    FOR(i,1,n) f[i] = f[i-1]*i%mod;
  }
  ll inv(int num){
    if(invf[num]==0) invf[num] = modpow(f[num],mod-2,mod);
    return invf[num];
  }
  ll comb(int a, int b){
    if(a<0 || b<0 || a-b<0) return 0;
    ll ret = (f[a]*inv(b)%mod) *inv(a-b) % mod;
    return ret;
  }
};



void solve5(){
  //modstr md; md.init(500'000);
  int n; cin >> n;
  V<pair<i128,i128>> cs, a_zr, b_zr, ab_zr;
  FOR(i,0,n){
    ll a_, b_;
    i128 a, b; cin >> a >> b;
    //a = a_; b = b_;
    if(b<0) a *= -1, b*= -1;
    
    if(a==0 && b==0) ab_zr.eb(a,b);
    else if(b==0) b_zr.eb(a,b);
    else cs.eb(a,b);
  }
  
  sort(  ALL(cs) , [&](pair<i128,i128> p1, pair<i128,i128>  p2){
    return (p1.fs*p2.sd - p1.sd * p2.fs < 0);
    //if(p1.sd != p2.sd) return (p1.fs*p2.sd < p1.sd * p2.fs);
  });
  for(auto &x: b_zr) cs.eb(x);
  
  
  
  V2<pair<i128,i128>> gr;
  {
    int l = 0, r=0;
    for(;l<cs.size() ; ++l){
      gr.eb(V<pair<i128,i128>>());
      gr.back().eb(cs[l]);
      while( r<cs.size() &&  cs[l].fs*cs[r].sd == cs[l].sd*cs[r].fs){ if(l!=r)gr.back().eb(cs[r]);++r;}
      l = r-1;
                                                     
    }
    /*
    for(auto &x:gr){
      for(auto &y:x){
        couts("["); couts(y.fs); couts(y.sd); couts("]");
      }
      coutn("");
    }*/
  }
  V<pair<int,int>> pdat; V<bool> used(gr.size());
  {
    int l = 0, r = 0;
    for(;l<gr.size();++l){
      while(r<gr.size() && gr[l][0].fs*gr[r][0].fs+gr[l][0].sd*gr[r][0].sd>0){
        ++r;
      }
      if(used[l]) continue;
      if(r<gr.size() && gr[l][0].fs*gr[r][0].fs+gr[l][0].sd*gr[r][0].sd == 0){ used[l]=true;used[r] = true; pdat.eb(gr[l].size(), gr[r].size()) ;}
      else{ pdat.eb( 0, gr[l].size());}
    }
  }
  //coutn( pdat );
  
  ll ans = 1;
  for(auto x:pdat){
    ans *= (modpow(2,x.fs,mod) + modpow(2,x.sd,mod) + mod - 1)%mod;
    ans %= mod; //coutn( ans );
  }
  (ans += mod-1) %= mod;
  (ans += (ab_zr.size()) ) %= mod;
  coutn( ans );
}

void solve(){
  solve5();
}







int main(void){
  std::cout << std::fixed << std::setprecision(20);
  cin.tie(0);
  //ios::sync_with_stdio(false);
  solve();
  //printf("%s", outst);
  return 0;
}





Measured memory_bytes: 27040