#include <bits/stdc++.h>
using namespace std;
#define ll long long int
#include <ext/pb_ds/assoc_container.hpp> 
#include <ext/pb_ds/tree_policy.hpp> 
using namespace __gnu_pbds;   
#define ordered_set tree<ll, null_type,less<ll>, rb_tree_tag,tree_order_statistics_node_update> 
#define ld long double
#define ff first
#define ss second
#define pb push_back
#define mp make_pair
#define all(a) a.begin(),a.end()
#define sz(a) (ll)(a.size())
const int M=2e5+5;
const ll mod=1e9+7;
ll pw[M];
int main()
{
	ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	int n;
	cin>>n;
	map<pair<ll,ll>,vector<int>> vec;
	set<pair<ll,ll>> dn;
	pw[0]=1;
	for(int i=1;i<=n;i++)
	{
		pw[i]=(2*pw[i-1])%mod;
		ll a,b;
		cin>>a>>b;
		ll g = __gcd(abs(a),abs(b));
		a/=g;b/=g;
		if(b<0)
		{
			a=-a;
			b=-b;
		}
		if(b==0)
		{
			if(a<0)
				a=-a;
		}
		vec[{a,b}].pb(i);
	}
	ll iso=0;
	ll res=1;
	for(auto it=vec.begin();it!=vec.end();it++)
	{
		auto P=it->ff;
		if(dn.find(P)!=dn.end())
			continue;
		auto Q = P;
		swap(Q.ff,Q.ss);
		Q.ff=-Q.ff;
		if(Q.ss<0)
		{
			Q.ss=-Q.ss;
			Q.ff=-Q.ff;
		}
		if(Q.ss==0)
		{
			if(Q.ff<0)
				Q.ff=-Q.ff;
		}
		if(vec.find(Q)==vec.end())
		{
			res=(res*pw[sz(vec[P])])%mod;
		}
		else
		{
			dn.insert(Q);
			res=(res*(pw[sz(vec[P])]+pw[sz(vec[Q])]-1+mod)%mod)%mod;
		}
	}
	res=(res-1+mod)%mod;
	cout<<res<<"\n";
	return 0;
}