#include <bits/stdc++.h>
using namespace std;
struct Elem {
  long long a, b;
  int type;
  int isUsed;
  bool operator==(const Elem &a) const {
    if ((this->a == a.a) && (this->b == a.b)) {
      return true;
    } else {
      return false;
    }
  }
  bool operator<(const Elem &a) const {
    if ((this->a < a.a)) {
      return true;
    } else if (this->a == a.a) {
      if (this->b < a.b) {
        return true;
      } else {
        return false;
      }
    } else {
      return false;
    }
  }
};
const long long MOD = 1000000007;
Elem elems[200010];
int n;
std::map<Elem, long long> groupA;
std::map<Elem, long long> groupB;
long long gcd(long long a, long long b) {
  if (a % b == 0)
    return b;
  else
    return gcd(b, a % b);
}
void doSwap(long long &a, long long &b) {
  long long temp = a;
  a = b;
  b = temp;
}
long long qsm(long long a, long long b) {
  long long ans = 1, w = a;
  for (; b; b >>= 1, w = (w * w) % MOD) {
    if (b & 1) ans = (ans * w) % MOD;
  }
  return ans;
}
int main() {
  scanf("%d", &n);
  groupA.clear();
  groupB.clear();
  long long left = n;
  for (int i = 0; i < n; i++) {
    Elem newElem;
    scanf("%lld%lld", &(newElem.a), &(newElem.b));
    long long g;
    if ((newElem.a == 0) && (newElem.b == 0)) {
      left--;
      continue;
    }
    if ((newElem.a != 0) && (newElem.b != 0)) {
      if (newElem.a >= newElem.b) {
        g = gcd(newElem.a, newElem.b);
      } else {
        g = gcd(newElem.b, newElem.a);
      }
      newElem.a = newElem.a / g;
      newElem.b = newElem.b / g;
    }
    newElem.isUsed = false;
    if (((newElem.a > 0) && (newElem.b > 0)) ||
        ((newElem.a < 0) && (newElem.b < 0)) || (newElem.b == 0)) {
      newElem.a = abs(newElem.a);
      newElem.b = abs(newElem.b);
      newElem.type = 1;
      if (groupA.find(newElem) == groupA.end()) {
        groupA[newElem] = 1;
      } else {
        int curCount = groupA[newElem];
        groupA[newElem] = curCount + 1;
      }
    } else {
      newElem.a = abs(newElem.a);
      newElem.b = abs(newElem.b);
      newElem.type = 2;
      doSwap(newElem.a, newElem.b);
      if (groupB.find(newElem) == groupB.end()) {
        groupB[newElem] = 1;
      } else {
        int curCount = groupB[newElem];
        groupB[newElem] = curCount + 1;
      }
    }
  }
  long long ans = 1;
  std::map<Elem, long long>::iterator iGroupA;
  std::map<Elem, long long>::iterator iGroupB;
  for (iGroupA = groupA.begin(); iGroupA != groupA.end(); iGroupA++) {
    Elem elemA = iGroupA->first;
    iGroupB = groupB.find(elemA);
    if (iGroupB != groupB.end()) {
      Elem elemB = iGroupB->first;
      left = left - iGroupA->second;
      left = left - iGroupB->second;
      long long numA = qsm(2, iGroupA->second) - 1;
      if (numA < 0) numA = numA + MOD;
      long long numB = qsm(2, iGroupB->second) - 1;
      if (numB < 0) numB = numB + MOD;
      ans = ans * (numA + numB + 1) % MOD;
    }
  }
  ans = ans * qsm(2, left) % MOD;
  ans--;
  if (ans < 0) ans = ans + MOD;
  printf("%lld\n", ans);
  return 0;
}
