#include <iostream>
#include <vector>
#include <array>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <string>
#include <sstream>
#include <algorithm>
#include <random>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <cmath>
#include <cassert>
#include <climits>
#include <bitset>
#include <functional>
#include <iomanip>
#include <random>

#define FOR_LT(i, beg, end) for (int i = (int)(beg); i < (int)(end); i++)
#define FOR_LE(i, beg, end) for (int i = (int)(beg); i <= (int)(end); i++)
#define FOR_DW(i, beg, end) for (int i = (int)(beg); (int)(end) <= i; i--)
#define REP(n)              for (int repeat_index = 0; repeat_index < (int)n; repeat_index++)


using namespace std;

struct V {
	int64_t n;
	int64_t v;
};

struct N {
	int64_t np;
	int64_t nn;
};

int64_t gcd(int64_t a, int64_t b) {
	if (a < b) swap(a, b);
	if (a % b == 0) return b;
	return gcd(b, a % b);
}


int64_t powint(int64_t x, int64_t m)
{
	if (m == 0) {
		return 1;
	}
	if (m == 1) {
		return x;
	}

	if (m & 1) {
		int64_t val = powint(x, m / 2);
		val = val * val;
		val *= x;
		return val;
	}
	else {
		int64_t val = powint(x, m / 2);
		val = val * val;
		return val;
	}
}
template<int64_t M = 1000000007>
class ModInt {
public:
	ModInt() : val_(0) {};

	ModInt(int64_t val) {
		this->val_ = val;
		this->val_ %= M;
		while (this->val_ >= M) this->val_ -= M;
		while (this->val_ < 0)  this->val_ += M;
	}

	operator int64_t() const {
		return this->val_;
	}

	ModInt& operator += (int64_t val) {
		this->val_ += val;
		this->val_ %= M;
		while (this->val_ >= M) this->val_ -= M;
		while (this->val_ < 0) this->val_ += M;

		return *this;
	}

	ModInt& operator -= (int64_t val) {
		this->val_ -= val;
		this->val_ %= M;
		while (this->val_ >= M) this->val_ -= M;
		while (this->val_ < 0) this->val_ += M;

		return *this;
	}

	ModInt& operator *= (int64_t val) {
		this->val_ *= val;
		this->val_ %= M;

		return *this;
	}

	ModInt& operator /= (int64_t val) {
		ModInt v = ModInt::pow(val, M - 2);
		*this *= v;

		return *this;
	}

	ModInt operator + (int64_t v) const {
		ModInt ret = *this;
		return (ret += v);
	}

	ModInt operator - (int64_t v) const {
		ModInt ret = *this;
		return (ret -= v);
	}

	ModInt operator * (int64_t v) const {
		ModInt ret = *this;
		return (ret *= v);
	}

	ModInt operator / (int64_t v) const {
		ModInt ret = *this;
		return (ret /= v);
	}

	static ModInt pow(ModInt n, int64_t m) {
		if (m == 0) {
			ModInt ret(1);
			return ret;
		}
		if (m == 1) {
			return n;
		}

		ModInt v = pow(n, m / 2);
		ModInt ret = v * v;
		if (m & 1) {
			ret *= n;
		}
		return ret;
	}

	ostream& operator << (ostream& out) {
		out << this->val_;
		return out;
	}

private:
	int64_t val_;
};

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout << fixed << setprecision(20);

	int n; cin >> n;

	auto cmp = [](const V& lhs, const V& rhs) {
		if (lhs.n != rhs.n) return lhs.n < rhs.n;
		return lhs.v < rhs.v;
	};

	map<V, N, decltype(cmp)> data(cmp);
	int64_t nzero = 0;
	FOR_LT(i, 0, n) {
		int64_t n, v; cin >> n >> v;
		if (n == 0 && v == 0) {
			nzero++;
			continue;
		}
		if (n == 0 || v == 0) {
			if (data.find({ 0, 0 }) == data.end()) {
				data[{0, 0}] = { 0, 0 };
			}
			if (n == 0) {
				data[{0, 0}].np++;
			}
			if (v == 0) {
				data[{0, 0}].nn++;
			}
			continue;
		}
		
		bool is_p = (n < 0) == (v < 0);
		n = abs(n);
		v = abs(v);
		int64_t d = gcd(n, v);
		n /= d;
		v /= d;
		if (is_p) std::swap(n, v);

		if (data.find({ n ,v }) == data.end()) {
			data[{n, v}] = { 0,0 };
		}

		if (is_p) data[{n, v}].nn++;
		else      data[{n, v}].np++;
	}

	ModInt<> ans = 1;

	for (auto& n : data) {
		ans *= ModInt<>::pow(2, n.second.nn) + ModInt<>::pow(2, n.second.np) - ModInt<>(1);
	}
	ans += nzero - 1;

	cout << ans << endl;

	return 0;
}


Measured memory_bytes: 19120