#include <iostream>
#include <iomanip> //! for setprecision(10)
#include <math.h>
#include <algorithm>
#include <functional> 
#include <string>
#include <vector>

#include <cstring>
#include <set>
#include <map>
#include <queue>
#include <utility>

using namespace std;

typedef long long LL;

#define dump(c) { for (auto it = c.begin(); it != c.end(); ++it) if (it == c.begin()) cout << *it; else cout << ' ' << *it; cout << endl; } 
#define rep(i,n) for (int i = 0; i < (n); ++i)

const int MOD = 1000000007;

class Mint {
public:
  typedef long long val_type;

  Mint(val_type x=0, int m=MOD) : val((x%m+m)%m), mod(m) {}
  val_type value() const { return val; }
  Mint& operator+=(const Mint a) {
    if ((val += a.val) >= mod) val -= mod;
    return *this;
  }
  Mint& operator-=(const Mint a) {
    if ((val += mod-a.val) >= mod) val -= mod;
    return *this;
  }
  Mint& operator*=(const Mint a) {
    (val *= a.val) %= mod;
    return *this;
  }
  Mint operator+(const Mint a) const {
    Mint res(*this);
    return res+=a;
  }
  Mint operator-(const Mint a) const {
    Mint res(*this);
    return res-=a;
  }
  Mint operator*(const Mint a) const {
    Mint res(*this);
    return res*=a;
  }
  Mint pow(val_type t) const {
    if (!t) return 1;
    Mint a = pow(t>>1);
    a *= a;
    if (t&1) a *= *this;
    return a;
  }

  // for prime mod
  Mint inv() const {
    return pow(mod-2);
  }
  Mint& operator/=(const Mint a) {
    return (*this) *= a.inv();
  }
  Mint operator/(const Mint a) const {
    Mint res(*this);
    return res/=a;
  }

private:
  val_type val;
  int mod;
};

template<typename T>
T gcd(T a, T b) 
{
    if (b < a) { //! make sure a <= b
        T tmp = b;
        b = a;
        a = tmp;
    }

    T r = b % a;
    while (r) {
        b = a;
        a = r;
        r = b % a;
    }

    return a;
}

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

    int N;
    map<pair<LL,LL>, int> hist; //! {A,B} => count (A>0 && gcd(A,B)==1) put {0,1} when A = 0, put {1,0} when B = 0, no need to count A=0 AND B=0 case
    set<pair<LL, LL>> var;
    cin >> N;
    int zeroZero = 0; //! Count of iwashi with A=0, B=0
    rep(i, N) {
        LL A, B;
        cin >> A >> B;
        if (A == 0) {
            if (B != 0) {
                B = 1;        
            }
        } else if (B == 0) {
            A = 1;
        } else {
            if (A < 0) {
                A = -A;
                B = -B;
            }
            LL g = gcd(A, abs(B));
            A /= g;
            B /= g;
        }
        if (A == 0 && B == 0) {
            ++zeroZero;
        } else {
            pair<LL, LL> p = {A, B};
            var.insert(p);
            ++hist[p];
        }
    }

    Mint ans(1);
    while (!var.empty()) {
        pair<LL, LL> v = *(var.begin());
        pair<LL, LL> p;
        if (v.first == 0) {
            p = {1, 0};
        } else if (v.second == 0) {
            p = {0, 1};
        } else {
            if (v.second < 0) {
                p = {-v.second, v.first};
            } else {
                p = {v.second, -v.first};
            }
        }
        var.erase(v);
        if (var.find(p) != var.end()) {
            var.erase(p);
            // v and p are orthogonal
            Mint tmp1 = (Mint(2).pow(hist[v])-1); //! 1 or more v, no p
            Mint tmp2 = (Mint(2).pow(hist[p])-1); //! 1 or more p, no v
            Mint tmp3 = 1; //! no v or p
            ans *= (tmp1 + tmp2 + tmp3);
        } else {
            // v has no orthogonal iwashi
            ans *= Mint(2).pow(hist[v]);
        }
    }
 
    ans += zeroZero;
    ans -= 1; //! exclude no iwashi case

    cout << ans.value() << endl;

    return 0;
}


Measured memory_bytes: 28540