use num_integer::gcd;
use proconio::input;
use std::collections::HashMap;
use modint::ModInt;

fn main() {
    input! {
        n: usize,
        info: [(i64, i64); n],
    }

    let mut zero = 0i64;
    let mut map = HashMap::new();
    for (x, y) in info {
        if x == 0 && y == 0 {
            zero += 1;
            continue;
        }

        let g = gcd(x, y);
        let mut x = x / g;
        let mut y = y / g;
        if y < 0 {
            x = -x;
            y = -y;
        }
        if y == 0 && x < 0 {
            x = -x;
            y = -y;
        }
        let rot90 = x <= 0;
        if rot90 {
            let tmp = x;
            x = y;
            y = -tmp;
        }

        let entry = map.entry((x, y)).or_insert((0, 0));
        let (a, b) = entry;
        if rot90 {
            *a += 1;
        } else {
            *b += 1;
        }
    }

    let mut ans = ModInt::from(1);
    for (_, (s, t)) in map {
        let mut now = ModInt::from(1);
        now += ModInt::from(2).pow(s) - 1.into();
        now += ModInt::from(2).pow(t) - 1.into();
        ans *= now;
    }
    ans -= 1.into();

    ans += zero.into();
    println!("{}", ans.0);
}

mod modint {
    use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};

    pub const MODULO: u64 = 1_000_000_007;
    // pub const MODULO: u64 = 11;

    fn positive_rem(a: i64, b: u64) -> u64 {
        let b = b as i64;
        let mut value = a % b;
        if value < 0 {
            value += b;
        }
        value as u64
    }

    /// Return (x, y) s.t. ax + by = d where d = gcd(a, b)
    #[allow(unused)]
    pub fn ext_gcd(a: u64, b: u64) -> (i64, i64) {
        if b == 0 {
            return (1, 0);
        }

        let q = (a / b) as i64;
        let r = a % b;
        let (x1, y1) = ext_gcd(b, r);
        (y1, x1 - q * y1)
    }

    #[derive(Debug, Copy, Clone)]
    pub struct ModInt(pub u64);

    impl From<usize> for ModInt {
        fn from(n: usize) -> ModInt {
            ModInt(n as u64 % MODULO)
        }
    }

    impl From<isize> for ModInt {
        fn from(n: isize) -> ModInt {
            ModInt(positive_rem(n as i64, MODULO as u64))
        }
    }

    impl From<u64> for ModInt {
        fn from(n: u64) -> ModInt {
            ModInt(positive_rem(n as i64, MODULO as u64))
        }
    }

    impl From<i64> for ModInt {
        fn from(n: i64) -> ModInt {
            ModInt(positive_rem(n, MODULO as u64))
        }
    }

    impl From<i32> for ModInt {
        fn from(n: i32) -> ModInt {
            ModInt(positive_rem(n as i64, MODULO as u64))
        }
    }

    impl ModInt {
        #[allow(unused)]
        pub fn pow(self, p: u64) -> ModInt {
            if self == ModInt::from(0) {
                return ModInt::from(0);
            }
            if p == 0 {
                return ModInt::from(1);
            }

            if p % 2 == 0 {
                let half = self.pow(p / 2);
                half * half
            } else {
                self.pow(p - 1) * self
            }
        }

        // when MODULO is prime
        #[allow(unused)]
        pub fn inv(self) -> ModInt {
            let (x, _) = ext_gcd(self.0 as u64, MODULO as u64);
            ModInt::from(x)
        }
    }

    impl Add for ModInt {
        type Output = ModInt;

        fn add(self, other: ModInt) -> ModInt {
            ModInt::from(self.0 + other.0)
        }
    }

    impl Sub for ModInt {
        type Output = ModInt;

        fn sub(self, other: ModInt) -> ModInt {
            ModInt::from(self.0 as i64 - other.0 as i64)
        }
    }

    impl Mul for ModInt {
        type Output = ModInt;

        fn mul(self, other: ModInt) -> ModInt {
            ModInt::from(self.0 * other.0)
        }
    }

    impl Neg for ModInt {
        type Output = ModInt;

        fn neg(self) -> Self::Output {
            ModInt::from(0) - self
        }
    }

    impl AddAssign for ModInt {
        fn add_assign(&mut self, other: Self) {
            *self = *self + other;
        }
    }

    impl MulAssign for ModInt {
        fn mul_assign(&mut self, other: Self) {
            *self = *self * other;
        }
    }

    impl SubAssign for ModInt {
        fn sub_assign(&mut self, other: Self) {
            *self = *self - other;
        }
    }

    impl PartialEq for ModInt {
        fn eq(&self, &other: &Self) -> bool {
            self.0 == other.0
        }
    }

    impl Eq for ModInt {}

    #[derive(Debug)]
    pub struct ModIntUtil {
        factorial: Vec<ModInt>,
        factorial_inv: Vec<ModInt>,
        inv: Vec<ModInt>,
    }

    impl ModIntUtil {
        #[allow(unused)]
        pub fn new() -> ModIntUtil {
            ModIntUtil {
                factorial: vec![ModInt::from(1), ModInt::from(1)],
                factorial_inv: vec![ModInt::from(1), ModInt::from(1)],
                inv: vec![ModInt::from(0), ModInt::from(1)],
            }
        }

        fn calc_cache(&mut self, n: usize) {
            let len = self.factorial.len();
            if len < n + 1 {
                for i in len..(n + 1) {
                    let prev = *self.factorial.last().unwrap();
                    self.factorial.push(prev * ModInt::from(i));

                    let inv_i = -self.inv[MODULO as usize % i] * ModInt::from(MODULO as usize / i);
                    self.inv.push(inv_i);

                    let prev = *self.factorial_inv.last().unwrap();
                    self.factorial_inv.push(prev * self.inv[i]);
                }
            }
        }

        #[allow(unused)]
        pub fn factorial(&mut self, n: usize) -> ModInt {
            self.calc_cache(n);
            self.factorial[n]
        }

        #[allow(unused)]
        pub fn factorial_inv(&mut self, n: usize) -> ModInt {
            self.calc_cache(n);
            self.factorial_inv[n]
        }

        // when MODULO is prime
        #[allow(unused)]
        pub fn binom_coef(&mut self, n: usize, k: usize) -> ModInt {
            if n < k {
                return ModInt::from(0);
            }

            self.calc_cache(n);
            self.factorial[n] * self.factorial_inv[k] * self.factorial_inv[n - k]
        }

        #[allow(unused)]
        fn perm(&mut self, n: usize, k: usize) -> ModInt {
            if n < k {
                return ModInt::from(0);
            }
            self.factorial(n) * self.factorial_inv(n - k)
        }

        // Not tested!!
        #[allow(unused)]
        pub fn multi_coef(&mut self, v: &[usize]) -> ModInt {
            let n = v.iter().sum();
            self.calc_cache(n);

            let mut ret = ModInt::from(1);
            ret *= self.factorial[n];
            for v_i in v {
                ret *= self.factorial_inv[*v_i];
            }

            ret
        }
    }
}


Measured memory_bytes: 25624