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

typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<double, double> pdd;
//typedef vector<vector<ll>> Graph;

const ll mod = 1e9 + 7;
//const ll mod = 998244353;

#define REP(i,n) for(ll i=0;i<(ll)n;i++)
#define dump(x)  cerr << #x << " = " << (x) << endl;
#define spa << " " <<
#define fi first
#define se second

template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }

template<class S, class T> ostream& operator << (ostream& os, const pair<S, T> v){
os << "(" << v.first << ", " << v.second << ")"; return os;
}
template<class T> ostream& operator << (ostream& os, const vector<T> v){
for(int i = 0; i < (int)v.size(); i++){if(i > 0){os << " ";} os << v[i];} return os;
}
template<class T> ostream& operator << (ostream& os, const vector<vector<T>> v){
for(int i = 0; i < (int)v.size(); i++){if(i > 0){os << endl;} os << v[i];} return os;
}

template<typename T> void debug(vector<vector<T>>&v,ll h,ll w){for(ll i=0;i<h;i++)
{cerr<<v[i][0];for(ll j=1;j<w;j++)cerr spa v[i][j];cerr<<endl;}};
template<typename T> void debug(vector<T>&v,ll n){if(n!=0)cerr<<v[0];
for(ll i=1;i<n;i++)cerr spa v[i];
cerr<<endl;};

string num2bit(ll num, ll len){
    string bit = "";
    REP(i, len){
    bit += char('0'+(num>>i & 1));
    }
    return bit;
}

template <std::uint_fast64_t Modulus> class modint {
  // long long から modint を作るときは必ず正の数にしてからコンストラクタに入れること！ 
  // そうしないとバグります
  using u64 = std::uint_fast64_t;

public:
  u64 a;

  constexpr modint(const u64 x = 0) noexcept : a(x % Modulus) {}
  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 >= Modulus) {
      a -= Modulus;
    }
    return *this;
  }
  constexpr modint &operator-=(const modint rhs) noexcept {
    if (a < rhs.a) {
      a += Modulus;
    }
    a -= rhs.a;
    return *this;
  }
  constexpr modint &operator*=(const modint rhs) noexcept {
    a = a * rhs.a % Modulus;
    return *this;
  }
  constexpr modint &operator/=(modint rhs) noexcept {
    u64 exp = Modulus - 2;
    while (exp) {
      if (exp % 2) {
        *this *= rhs;
      }
      rhs *= rhs;
      exp /= 2;
    }
    return *this;
  }
};
using mint = modint<mod>;

template <class T, class U> constexpr T power(T x, U exp) {
  T ret = static_cast<T>(1);
  while (exp) {
    if (exp % static_cast<U>(2) == static_cast<U>(1))
      ret *= x;
    exp /= static_cast<U>(2);
    x *= x;
  }
  return ::std::move(ret);
}

ll Euclid(ll A, ll B){
    if(A<B) swap(A, B);
    ll C = B;
    while(C != 0){
        C = A%B;
        A = B;
        B = C;
    }
    return A;
}

// コーナー A=0 and B=0 の場合，A = 0 かつ B < 0 の場合

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

    ll N;
    cin >> N;

    map<pll, ll> cnt;
    ll z = 0;
    REP(i, N){
        ll A, B;
        cin >> A >> B;
        if(A<0){
            A *= -1;
            B *= -1;
        }else if(A==0 and B < 0){
            B *= -1;
        }else if(A==0 and B==0){
            z++;
            continue;
        }
        ll G = Euclid(abs(A), abs(B));
        if(G != 0){
            A /= G;
            B /= G;
        }
        pll p;
        p.first = A;
        p.second = B;
        cnt[p]++;
    }

    N -= z;

    mint res = 1;

    const ll INF = (1ll<<60);
    vector<pll> kumi;
    ll single = 0;
    for(auto x: cnt){
        ll c1 = x.second;
        if(c1 == -INF) continue;
        ll a = x.first.first;
        ll b = x.first.second;
        ll c = -b;
        ll d = a;
        if(c<0){
            c *= -1;
            d *= -1;
        }else if(c==0 and d<0){
            d *= -1;
        }
        pll q = {c, d};

        //ll c2 = cnt[q];
        if(cnt.find(q) != cnt.end()){
            ll c2 = cnt[q];
            kumi.push_back({c1, c2});
            cnt[q] = -INF;
        }else{
            single++;
        }

        //dump(x.first)
        //dump(q)
        //dump(c1)
    }

    //cout << kumi << endl;
    //dump(single)

    for(auto x: kumi){
        mint X1 = power(mint(2), x.first);
        X1 -= 1;
        mint X2 = power(mint(2), x.second);
        X2 -= 1;
        res *= (X1+X2+1);
    }

    res *= power(mint(2), single);
    res -= 1;

    res += z; //?
    cout << res.value() << endl;

    return 0;
}