#include<algorithm>
#include<bitset>
#include<cmath>
#include<cstdlib>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<string>
#include<utility>
#include<vector>

using namespace std;
 
typedef long long ll;
const ll MOD = 1000000007;
const ll INF = 1e18;


#define PB push_back
#define MP make_pair
#define F first
#define S second

long long pow(long long x, long long n) {
    long long ret = 1;
    while (n > 0) {
        if (n & 1) ret = ret * x % MOD;
        x = x * x % MOD;
        n >>= 1;
    }
    return ret;
}

template<typename T,typename U>
bool chmax(T& max, const U& x){
	if(max<x){
		max = x;
		return true;
	}
	return false;
}

template<typename T,typename U>
bool chmin(T& min, const U& x){
	if(min>x){
		min = x;
		return true;
	}
	return false;
}


int main(){
	ll n;
	map<pair<ll,ll>,ll> ab;
	ab[MP(INF,INF)]=INF;
	cin >> n;
	ll corner=0;
	for(ll j=0;j<n;j++){
		ll a,b;
		cin >> a >> b;
		bool f=true;
		if(a<0){
			a*=-1; b*=-1;
		}
		if(a==b && a==0){
			corner++;
		}else if(a==0 ){
			ab[MP(0,1)]++;
		}else if(b==0){
			ab[MP(1,0)]++;
		}else{
			ab[MP(a/__gcd(a,b),b/__gcd(a,b))]++;
		}
	}

	vector<ll> ans;
	ans.PB(0);

	map<pair<ll,ll>,bool> used;
	for(auto iter = ab.begin(); iter!=ab.end();iter++){
		if(iter->S==INF) continue;
		if(used[iter->F]) continue;
	
		if(ab[(MP(iter->F.S,-iter->F.F))]!=0){
			ans.PB( pow(2,iter->S)+pow(2,ab[MP(iter->F.S,-iter->F.F)])-1 );
			used[MP(iter->F.S,-iter->F.F)]=true;
		}else{
			ans[0] = ans[0] +  iter->S;
		}
	}
	ll fa=1;
	ans[0]=pow(2,ans[0]);
	for(auto e:ans){
		fa = fa*e%MOD;
	}
	cout << fa-1+ corner<< endl;
	
}