#include <bits/stdc++.h>
using namespace std;
using vec_int = vector<int>;
using T = tuple<int, int, int>;
using ll = long long;
using P = pair<int, int>;
long long Gcd(long long m, long long n) {
  long temp;
  while (m % n != 0) {
    temp = n;
    n = m % n;
    m = temp;
  }
  return n;
}
int pow_amari(ll N, int n, ll M) {
  ll output = 1;
  for (int i = 0; i < (int)(n); i++) {
    output = output * N % M;
  }
  return output;
}
int main() {
  ll largeN = 1000000007;
  int N;
  cin >> N;
  vector<ll> A(N);
  vector<ll> B(N);
  int N_groupA = 0;
  int N_groupB = 0;
  int N_groupC = 0;
  map<string, int> AoverB;
  map<string, int> BoverA;
  vector<string> key1;
  vector<string> key2;
  map<string, string> key_map;
  map<string, int> key_check;
  for (int i = 0; i < (int)(N); i++) {
    cin >> A.at(i) >> B.at(i);
    if (A.at(i) == 0 and B.at(i) == 0) {
      N_groupA++;
    } else if (A.at(i) == 0) {
      N_groupB++;
    } else if (B.at(i) == 0) {
      N_groupC++;
    } else {
      ll gcd_temp = Gcd(abs(A.at(i)), abs(B.at(i)));
      string temp1, temp2;
      if (A.at(i) > 0 && B.at(i) > 0 || A.at(i) < 0 && B.at(i) < 0) {
        temp1 = to_string(abs(A.at(i) / gcd_temp)) + "/" +
                to_string(abs(B.at(i) / gcd_temp));
        temp2 = "-" + to_string(abs(B.at(i) / gcd_temp)) + "/" +
                to_string(abs(A.at(i) / gcd_temp));
      } else {
        temp1 = "-" + to_string(abs(A.at(i) / gcd_temp)) + "/" +
                to_string(abs(B.at(i) / gcd_temp));
        temp2 = to_string(abs(B.at(i) / gcd_temp)) + "/" +
                to_string(abs(A.at(i) / gcd_temp));
      }
      key_map[temp1] = temp2;
      key_check[temp1] = 0;
      if (AoverB.count(temp1)) {
        AoverB[temp1]++;
      } else {
        AoverB[temp1] = 1;
        key1.push_back(temp1);
      }
      if (BoverA.count(temp2)) {
        BoverA[temp2]++;
      } else {
        BoverA[temp2] = 1;
        key2.push_back(temp2);
      }
    }
  }
  ll N_mugai = 0;
  vector<string> checked;
  vector<P> num_pair;
  for (auto key : key1) {
    if (BoverA.count(key)) {
      if (key_check[key] == 1) {
        continue;
      }
      key_check[key_map[key]] = 1;
      num_pair.push_back(make_pair(AoverB[key], BoverA[key]));
    } else {
      N_mugai++;
    }
  }
  ll tot_num = 1;
  for (int i = 0; i < (int)(N_mugai); i++) {
    tot_num = tot_num * 2 % largeN;
  }
  for (auto temp_pair : num_pair) {
    ll N1, N2;
    tie(N1, N2) = temp_pair;
    tot_num =
        tot_num *
        ((pow_amari(2, N1, largeN) + pow_amari(2, N2, largeN) - 1) % largeN) %
        largeN;
  }
  tot_num =
      tot_num *
      ((pow_amari(2, N_groupB, largeN) + pow_amari(2, N_groupC, largeN) - 1) %
       largeN) %
      largeN;
  cout << (tot_num - 1 + N_groupA) % largeN << endl;
}
