#include <bits/stdc++.h>
using namespace std;
#define SZ(v) int((v).size())
#define ALL(vec) begin(vec), end(vec)
typedef long long i64;
template<typename T> inline bool uax(T &x, T y) {return (y > x) ? x = y, true : false;}
template<typename T> inline bool uin(T &x, T y) {return (y < x) ? x = y, true : false;}
#ifdef Rahul
# define error(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); \
  stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); }
#else
# define error(...) 42;
#endif
string to_string(char c) { return "'" + string(1, c) + "'";}
string to_string(string s) { return '"' + s + '"';}
string to_string(const char* s) { return to_string((string) s);}
template<typename A> string to_string(A);
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 f = false; string r = "{"; 
  for (auto x: v) {if (f) r += ", "; r += to_string(x); f = true;} return r += "}";}
template<typename A> string to_string(vector<vector<A>> v) {string r; 
  for (auto x: v) r += "\n" + to_string(x); return r;}
int Nerr;
template<typename A> string to_string(A *p) {return to_string(vector<A>(p, p + Nerr));}
void err(istream_iterator<string>) { cerr << endl; }
template<typename T,typename... Args> void err(istream_iterator<string> it, T a, Args... args) {
  cerr << *it << " =: " << to_string(a) << "; "; err(++it, args...); }
template<typename T> void kek(T ans) {cout << ans << endl; exit(0);}
#define Lu(...) [&] (auto &&u) { return __VA_ARGS__; }
#define Luv(...) [&] (auto &&u, auto &&v) { return __VA_ARGS__; }
int const MOD = 1e9 + 7;
i64 const INF = 1e18 + 42;
/***********************************************************************/
inline int add(int a, int b, int mod = MOD) {
  a += b; return a >= mod ? a - mod : a;
}
inline int sub(int a, int b, int mod = MOD) {
  a -= b; return a < 0 ? a + mod : a;
}
inline int mul(int a, int b, int mod = MOD) {
  return int((long long) a * b % mod);
}
inline int mpow(int base, long long ex, int mod = MOD) {
  int res = 1;
  for (; ex > 0; ex >>= 1) {
    if (ex & 1) res = mul(res, base, mod);
    base = mul(base, base, mod);
  }
  return res;
}
inline int inv(int a, int mod = MOD) {
  return mpow(a, mod - 2, mod);
}
inline int mdiv(int a, int b, int mod = MOD) {
  return mul(a, mpow(b, mod - 2,  mod));
}
inline void adds(int &a, int b, int mod = MOD) {
  a += b; if (a >= mod) a -= mod;
}
inline void subs(int &a, int b, int mod = MOD) {
  a -= b; if (a < 0) a += mod;
}
inline void muls(int &a, int b, int mod = MOD) {
  a = int((long long) a * b % mod);
}
inline void mdivs(int &a, int b, int mod = MOD) {
  a = mdiv(a, b, mod);
}


int32_t main() {
  cin.tie(nullptr) -> sync_with_stdio(false);
  
  int n; cin >> n;
  vector<i64> a(n), b(n);
  map<pair<i64, i64>, int> c;
  map<pair<i64, i64>, int> d;
  int zero = 0;
  for (int i = 0; i < n; ++i) {
    cin >> a[i] >> b[i];
    if (a[i] == 0 && b[i] == 0) {
      ++zero;
      continue;
    }
    i64 g = __gcd(abs(a[i]), abs(b[i]));
    i64 na = b[i] / g, nb = -a[i] / g;
    if (na < 0) na *= -1, nb *= -1;
    c[{na, nb}]++;
    na = a[i] / g, nb = b[i] / g;
    if (na < 0) na *= -1, nb *= -1;
    d[{na, nb}]++;
  }
  set<pair<i64, i64>> done;
  int ans = 1;
  for (auto [pr, cnt] : c) {
    if (done.count(pr)) continue;
    if (d.count(pr)) {
      int rt = d[pr];
      i64 na = -pr.second, nb = pr.first;
      if (na < 0) na *= -1, nb *= -1;
      done.insert({na, nb});
      muls(ans, sub(add(mpow(2, cnt), mpow(2, rt)), 1));
    } else {
      muls(ans, mpow(2, cnt));
    }
  }
  subs(ans, 1);
  adds(ans, zero);
  kek(ans);
}
