#include <bits/stdc++.h>

int ri() {
	int n;
	scanf("%d", &n);
	return n;
}
#define MOD 1000000007

template<int mod>
struct ModInt{
	int x;
	ModInt():x(0){}
	ModInt(long long y):x(y>=0?y%mod:(mod-(-y)%mod)%mod){}
	ModInt &operator+=(const ModInt &p){
		if((x+=p.x)>=mod)x-=mod;
		return *this;
	}
	ModInt &operator-=(const ModInt &p){
		if((x+=mod-p.x)>=mod)x-=mod;
		return *this;
	}
	ModInt &operator*=(const ModInt &p){
		x=(int)(1LL*x*p.x%mod);
		return *this;
	}
	ModInt &operator/=(const ModInt &p){
		*this*=p.inverse();
		return *this;
	}
	ModInt &operator^=(long long p){
		ModInt res = 1;
		for (; p; p >>= 1) {
			if (p & 1) res *= *this;
			*this *= *this;
		}
		return *this = res;
	}
	ModInt operator-()const{return ModInt(-x);}
	ModInt operator+(const ModInt &p)const{return ModInt(*this)+=p;}
	ModInt operator-(const ModInt &p)const{return ModInt(*this)-=p;}
	ModInt operator*(const ModInt &p)const{return ModInt(*this)*=p;}
	ModInt operator/(const ModInt &p)const{return ModInt(*this)/=p;}
	ModInt operator^(long long p)const{return ModInt(*this)^=p;}
	bool operator==(const ModInt &p)const{return x==p.x;}
	bool operator!=(const ModInt &p)const{return x!=p.x;}
	explicit operator int() const { return x; }						   // added by QCFium
	ModInt operator=(const int p) {x = p; return ModInt(*this);} // added by QCFium
	ModInt inverse()const{
		int a=x,b=mod,u=1,v=0,t;
		while(b>0){
			t=a/b;
			a-=t*b;
			std::swap(a,b);
			u-=t*v;
			std::swap(u,v);
		}
		return ModInt(u);
	}
	friend std::ostream &operator<<(std::ostream &os,const ModInt<mod> &p){
		return os<<p.x;
	}
	friend std::istream &operator>>(std::istream &is,ModInt<mod> &a){
		long long x;
		is>>x;
		a=ModInt<mod>(x);
		return (is);
	}
};
typedef ModInt<MOD> mint;

struct MComb {
	std::vector<mint> fact;
	std::vector<mint> inv;
	MComb (int n) { // O(n + log(mod))
		fact = std::vector<mint>(n + 1, 1);
		for (int i = 1; i <= n; i++) fact[i] = fact[i - 1] * mint(i);
		inv.resize(n + 1);
		inv[n] = fact[n] ^ (MOD - 2);
		for (int i = n; i--; ) inv[i] = inv[i + 1] * mint(i + 1);
	}
	mint ncr(int n, int r) {
		return fact[n] * inv[r] * inv[n - r];
	}
	mint npr(int n, int r) {
		return fact[n] * inv[n - r];
	}
	mint nhr(int n, int r) {
		assert(n + r - 1 < (int) fact.size());
		return ncr(n + r - 1, r);
	}
};

int64_t gcd(int64_t a, int64_t b) {
	a = std::abs(a);
	b = std::abs(b);
	while (a && b) {
		if (a > b) a %= b;
		else b %= a;
	}
	return a + b;
}

int main() {
	int n = ri();
	std::map<std::pair<int64_t, int64_t>, int> all;
	int cnt00 = 0, cnt01 = 0, cnt10 = 0;
	for (int i = 0; i < n; i++) {
		int64_t a, b;
		scanf("%" SCNd64 "%" SCNd64, &a, &b);
		if (a < 0) a = -a, b = -b;
		int64_t tmp = gcd(a, b);
		if (tmp) a /= tmp, b /= tmp;
		if (!a && !b) cnt00++;
		else if (!a) cnt01++;
		else if (!b) cnt10++;
		else all[{a, b}]++;
	}
	mint res = (mint(2) ^ cnt01) + (mint(2) ^ cnt10) - 1;
	while (all.size()) {
		int64_t xx = all.begin()->first.second, yy = -all.begin()->first.first;
		if (xx < 0) xx = -xx, yy = -yy;
		auto itr = all.find({xx, yy});
		if (itr == all.end()) res *= mint(2) ^ all.begin()->second;
		else res *= (mint(2) ^ all.begin()->second) + (mint(2) ^ itr->second) - 1, all.erase(itr);
		all.erase(all.begin());
	}
	std::cout << res + cnt00 - 1 << std::endl;
	return 0;
}


Measured memory_bytes: 16188