use proconio::{input, fastout};
use num::rational::Ratio;
use std::collections::HashMap;
use std::collections::HashSet;
// use itertools::Itertools;

fn modpow(x: i64, y: i64, m: i64) -> i64 {
  if y == 0 { return 1; }
  if y == 1 { return x; }
  let mut ans = modpow(x, y>>1, m);
  ans = ans * ans % m;
  if y & 1 == 1 {
    ans = ans * x % m;
  }
  ans
}

#[fastout]
fn main() {
  let mmm = 1000000007;
  input!{
    n: usize,
    ab: [(i64, i64); n]
  };
  let mut h : HashMap<Ratio<i64>, i64> = HashMap::new();
  // let mut hn : HashMap<Ratio<i64>, usize> = HashMap::new();
  let mut zerozero = 0;
  for (a, b) in &ab {
    if *a == 0 && *b == 0 {
      zerozero += 1;
    } else {
      *h.entry(Ratio::new(*a, *b)).or_insert(0) += 1;
    }
  }
  dbg!(&h);

  let mut ans : i64 = 1;
  let mut s : HashSet<Ratio<i64>> = HashSet::new();
  for (r, v) in &h {
    let r = *r;
    let v = *v;
    if !s.contains(&r) {
      let r2 = Ratio::new(*r.denom() * -1, *r.numer());
      let v2  = match h.get(&r2) {
        Some(vv2) => *vv2,
        None => 0
      };
      let mut pow = modpow(2, v + v2, mmm) - (modpow(2, v, mmm) - 1) * (modpow(2, v2, mmm) - 1) % mmm;
      while pow < 0 {
        pow += mmm;
      }
      dbg!(&r, &s, &pow, v, v2);
      s.insert(r);
      s.insert(r2);
      ans = ans * pow % mmm;
    }
  }
  ans -= 1;
  ans += modpow(2, zerozero, mmm) - 1;
  if ans < 0 {
    ans += mmm;
  }
  println!("{}", ans % mmm);
}
