#include <bits/stdc++.h>
#pragma GCC target("avx")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
using namespace std;
using i64 = int64_t;
using f80 = __float80;
using u64 = uint_fast64_t;
static const int dy[4] = {0,1,0,-1}, dx[4] = {1,0,-1,0};
constexpr i64 INF = 1'010'000'000'000'000'017LL;
constexpr u64 MOD = 1'000'000'007LL;
#define _overload3(_1,_2,_3,name,...) name
#define repi(i,start,end) for(i64 i=(start);i<(end);++i)
#define _rep(i,n) repi(i,0,n)
#define rep(...) _overload3(__VA_ARGS__,repi,_rep,)(__VA_ARGS__)
#define rrep(i,start,end) for(i64 i=(start);i>end;--i)
#define rng(a) a.begin(),a.end()
#define rrng(a) a.rbegin(),a.rend()
#define isin(x,l,r) ((l) <= (x) && (x) < (r))
#define show(x) cout<<#x<<" = "<<x<<endl;
#define PQ(T) priority_queue<T,v(T),greater<T> >
#define v(T) vector<T>
#define vv(T) v(v(T))
typedef pair<i64,i64> P;
typedef v(i64) vi;
typedef v(vi) vvi;
typedef v(P) vp;
template<class T> inline bool chmax(T& a,T b){if(a<b){a=b;return true;}return false;}
template<class T> inline bool chmin(T& a,T b){if(a>b){a=b;return true;}return false;}
template<typename T> ostream &operator<<(ostream &os, const vector< T > &v){
  rep(i,v.size()) os << v[i] << (i + 1 != v.size() ? " " : "");
  return os;
}
template<typename T> istream &operator>>(istream &is, vector< T > &v){
  for(T &in : v) is >> in;
  return is;
}

class modint {
public:
  u64 a;
  constexpr modint(const u64 x = 0) noexcept : a(x % MOD) {}
  constexpr u64 &value() noexcept { return a; }
  constexpr const u64 &value() const noexcept { return a; }
  constexpr modint operator+(const modint rhs) const noexcept {
    return modint(*this) += rhs;
  }
  constexpr modint operator-(const modint rhs) const noexcept {
    return modint(*this) -= rhs;
  }
  constexpr modint operator*(const modint rhs) const noexcept {
    return modint(*this) *= rhs;
  }
  constexpr modint operator/(const modint rhs) const noexcept {
    return modint(*this) /= rhs;
  }
  constexpr modint &operator+=(const modint rhs) noexcept {
    a += rhs.a;
    if (a >= MOD) a -= MOD;
    return *this;
  }
  constexpr modint &operator-=(const modint rhs) noexcept {
    if (a < rhs.a) a += MOD;
    a -= rhs.a;
    return *this;
  }
  constexpr modint &operator*=(const modint rhs) noexcept {
    a = a * rhs.a % MOD;
    return *this;
  }
  constexpr modint &operator/=(modint rhs) noexcept {
    for(u64 exp = MOD - 2; exp; exp>>=1){
      if (exp % 2) *this *= rhs;
      rhs *= rhs;
    }
    return *this;
  }
};

i64 pow_mod(i64 n, i64 k, i64 m){
  i64 r = 1;
  for(;k;k>>=1){
    if(k&1) r=(r*n)%m;
    n=(n*n)%m;
  }
  return r;
}

void Main()
{
  i64 N;
  cin >> N;

  i64 zerozero = 0;
  i64 Azero = 0;
  i64 Bzero = 0;
  map<pair<i64,i64>,i64> mp, rmp;
  
  i64 a, b;
  rep(i,N){
    cin >> a >> b;
    if(a==0 and b==0){
      zerozero++;
    } else if(a==0){
      Azero++;
    } else if(b==0){
      Bzero++;
    } else{
      i64 gcd = abs(__gcd(a,b));
      if((a>0 and b>0) or (a<0 and b<0)){
        mp[make_pair(abs(a)/gcd,abs(b)/gcd)]++;
      } else {
        rmp[make_pair(abs(b)/gcd,abs(a)/gcd)]++;
      }
    }
  }

  modint ans = 1;
  ans *= pow_mod(2,Azero,MOD) + pow_mod(2,Bzero,MOD) - 1;
  for(auto &p:mp){
    modint ans_tmp = 0;
    ans_tmp += pow_mod(2,p.second,MOD);
    ans_tmp += pow_mod(2,rmp[p.first],MOD);
    ans_tmp -= 1;
    ans *= ans_tmp;
  }
  for(auto &p:rmp){
    if(mp[p.first]==0){
      ans *= pow_mod(2,p.second,MOD);
    }
  }
  ans -= 1;
  ans += zerozero;

  cout << ans.a << "\n";
}

int main()
{
  cin.tie(nullptr);
  ios_base::sync_with_stdio(false);
  cout << fixed << setprecision(15);
  Main();
}

Measured memory_bytes: 28572