#include <bits/stdc++.h>
using namespace std;
 
#define ll long long 
#define inf 0x3f3f3f3f
#define infll 0x3f3f3f3f3f3f3f3f
#define all(x) (x).begin(),(x).end()
#define forn(i, a, b) for (int i=a; i<(signed)(b); ++i)
#define pb push_back
 
 
// debug templates 
#define debug(x)       cerr<< #x <<" : "<< x << endl;
#define debuga(A,N)    cerr<< #A <<" : [";for(int i = 0; i<N;i++) cerr<<A[i]<<" "; cerr<<"]\n";
#define debuga2(A,N,M) cerr<< #A << " : \n"; for(int i=0;i<N;i++){cerr<<"[";for(int j=0;j<M;++j) cerr<<A[i][j]<<" ";cerr<<"]\n";}
#define debugp(p)      cerr<< #p <<" : "<<"("<<(p).first<<","<<(p).second<<")\n";
#define debugv(v)      cerr<< #v <<" : "<<"[";for(int i = 0; i< (v).size(); i++) cerr<<v[i]<<" "; cerr<<"]\n";
#define debugv2(v)     cerr<< #v << " : \n"; for(int i=0;i<v.size();i++){cerr<<"[";for(int j=0;j<(v[0].size());++j) cerr<<v[i][j]<<" ";cerr<<"]\n";}
#define debugs(m)      cerr<< #m <<" : [ "; for(auto itr = m.begin(); itr!=m.end();itr++) cerr<<*itr<<" "; cerr<<"]\n";
#define debugm(m)      cerr<< #m <<" : [ "; for(auto itr = m.begin();itr!=m.end(); itr++) cerr<<"("<<itr->first<<","<<itr->second<<") ";cerr<<"]\n";
 
 
const ll mod = 1e9+7;
 
ll power(ll a, ll b){
	ll result = 1;
	while(b>0){
		if(b%2) (result *= a) %= mod;
		(a*=a)%=mod;
		b/=2;
	}
	return result;
}
 
// imagine each sardine as a point in 2d then bad points are perpendicular from each othere if we create a line from the origin
// special case 0, and grad = 0 and inf
void solve(){
	ll n; cin >> n;
	map<pair<ll,ll>,ll> gradients; // numerator,denominator
	ll edge_case = 0;
	forn(i,0,n){
		ll a,b; cin >> a >> b;
		if(a==0 && b ==0){
			++edge_case;
			continue;
		}
		// ensure if gradient b/a is negative then first elm in pair is neg
		if(a < 0 && b < 0) a = -a, b = -b;
		if(a<0)  a = -a, b = -b;
		ll g = gcd(a,b);
		a /= g;
		b /= g;
		pair<ll,ll> grad = {b,a};
		++gradients[grad];
	}
	ll ans = 1;
	for(auto x : gradients){
		// dont want empty set 
		//  (2^c1 + 2^c2 — 1) number of ways to create sets with elm1 or number of ways to create sets with elm2
		// -1 to not include empty set twice
		// when we multiply we combine them together, by adding we say one or the other occurs
		pair<ll,ll> og = x.first;
		pair<ll,ll> inverse_grad = {-og.second,og.first};
		if(og.first<0) inverse_grad.first = -inverse_grad.first, inverse_grad.second = -inverse_grad.second;
		auto itr = gradients.find(inverse_grad);
		if(itr != gradients.end()){
			if(!gradients[inverse_grad]) continue;
			ll l = power(2,x.second);
			ll r = power(2,gradients[inverse_grad]);
			(ans *= (l+r-1)) %= mod;
			gradients[og] = 0;
		} else{
			(ans *= power(2,x.second)) %= mod;
		}
		// dont want to include empty set
	}
	cout << (((ans - 1) + edge_case )%mod + mod)%mod;
}
 
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	
	solve();
	return 0;
}
 
