#include <bits/stdc++.h>
using namespace std;

#define int long long
#define pb push_back
#define eb emplace_back
#define fi first
#define se second
#define fr(i,j,k) for(i = j; i < (k); i++)
#define all(x) x.begin(), x.end()
#define el '\n'
#define remax(a,b) a = max(a, b)
#define remin(a,b) a = min(a, b)
#define sz(x) int32_t(x.size())

typedef long double ld;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<vi> slopesi;
typedef vector<pii> vpi;
// --------------------------------------------------------------------

const pii dxy[] = { {-1, 0}, {1, 0}, {0, 1}, {0, -1} };
const int mod = 1e9 + 7;
const int INF = 2e18;
const ld EPS = 1e-9;
const int NN = 3e5 + 2;


int sgn(int x) {
	if(x > 0) return 1;
	return -1;
}

int pow(int a, int b, int m) {
	a %= m;
	int res = 1;
	while (b > 0) {
		if (b & 1)
			res = res * a % m;
		a = a * a % m;
		b >>= 1;
	}
	return res;
}

string to_string(string s) {
	return '"' + s + '"';
}
string to_string(const char* s) {
	return to_string((string) s);
}
string to_string(bool b) {
	return (b ? "true" : "false");
}
template <typename A, typename B>
string to_string(pair<A, B> p) {
	return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}
template <typename A>
string to_string(A v) {
	bool first = true;  string res = "{";
	for (const auto &x : v) {
		if (!first) { res += ", "; }
		first = false; res += to_string(x);
	}
	res += "}";         return res;
}
void debug_out() {
	cerr << endl;
}
template <typename Head, typename ... Tail>
void debug_out(Head H, Tail... T) {
	cerr << " " << to_string(H);
	debug_out(T ...);
}

//#define TRACE

#ifdef TRACE
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define debug(...)
#endif
//============================================================================

map<pii, int> slopes;


void solve() {
	int i = 0, j = 0, k = 0, n = 0, m = 0;
	int y0 = 0, x0 = 0;
	cin >> n;
	vpi a;

	fr(i, 0, n) {
		int u, v;
		cin >> u >> v;
		if(u == 0 and v == 0) continue;
		a.pb({u, v});
		if(u == 0) {
			x0++;
			continue;
		}
		if(v == 0) {
			y0++;
			continue;
		}
		int g = __gcd(u, v);
		int sign = sgn( sgn(u) * sgn(v) );
		g *= sgn(g);
            u /= g;
            v /= g;
		u *= sgn(u);
		if(sign > 0)
			v *= sgn(v);
		if(sign < 0 and v > 0)
			v = -v;
		pii l = {v, u};
		slopes[l]++;
	}
      debug(slopes);
      vpi h;
	set<pii> vis;
	int ans = 1;      // initialise with empty set
	for(auto& p : slopes) {
		if(vis.count(p.fi))
			continue;
		// consider this and its orthogonal other
		pii l = p.fi;
		int u = -l.fi, v = l.se;
		int sign = sgn( sgn(u) * sgn(v) );
		u *= sgn(u);
		if(sign > 0)
			v *= sgn(v);
		if(sign < 0 and v > 0)
			v = -v;

            int cntO = slopes.count( {v, u} ) ? slopes[{v, u}] : 0;
            h.eb(p.se, cntO);
            vis.emplace(v, u);
      }

      debug(h);

      ans += pow(2, x0, mod) - 1 + pow(2, y0, mod) - 1;
      for(auto &p : h) {
            ans = ( ( 1 + (pow(2, p.fi, mod) - 1) + (pow(2, p.se, mod) - 1) ) % mod ) * ans;
            ans %= mod;
      }
	cout << ans-1 << el;    // remove empty set
}

int32_t main() {
	ios::sync_with_stdio(false); cin.tie(0);
	int T = 1;
	// cin >> T;
	// cout << __gcd(-4, -10) << endl;
	for(int tc = 1; tc <= T; tc++) {
		solve();
	}
	return 0;
}