#!/usr/bin/env python3
import sys
import math
from collections import defaultdict
from bisect import bisect_left
from collections import Counter
sys.setrecursionlimit(10**8)
INF = float("inf")

MOD = 1000000007  # type: int


class UnionFind(object):
    def __init__(self, N):
        self.tree = list(range(N))

    def root(self, i):
        if self.tree[i] == i:
            return i
        else:
            self.tree[i] = self.root(self.tree[i])
            return self.tree[i]

    def same(self, x, y):
        return self.root(x) == self.root(y)

    def unite(self, x, y):
        x = self.root(x)
        y = self.root(y)
        if x != y:
            self.tree[x] = y


def solve(N: int, A: "List[int]", B: "List[int]"):
    # 直交するイワシは選べない
    # イワシをソートする
    theta = [0]*N
    for i, (a, b) in enumerate(zip(A, B)):
        if a != 0:
            theta[i] = math.degrees(math.atan2(b, a))
        elif b > 0:
            theta[i] = math.pi/2
        else:
            theta[i] = -math.pi/2
    # print(theta)

    abtheta = sorted(zip(theta, A, B))
    # print(*abtheta, sep="\n")
    # 順にイワシを見てグループを探す。二分探索で探す。
    uf = UnionFind(N)

    nisyu = [th for th, _, _ in abtheta]*2
    nisyuni = abtheta*2

    start, end = 0, 0
    end2 = None
    for i in range(N):
        # イワシiと90度、180度、270度角度が異なるものはありますか
        # しゃくとりで
        th, a, b = abtheta[i]

        # print("A")
        # 90度の関係にあるもの
        while end <= N+i:
            thi, ai, bi = nisyuni[end]
            if ai*a+bi*b <= 0:
                break
            end += 1

        while ai*a+bi*b == 0:
            uf.unite(i, end % N)
            end += 1
            if end >= N:
                break
            thi, ai, bi = nisyuni[end]

        if end2 == None:
            end2 = end

        # print("B")
        # 270度の関係にあるもの
        while end2 <= N+i:
            thi, ai, bi = nisyuni[end2]
            if ai*a+bi*b >= 0:
                break
            end2 += 1

        # print("C")
        while ai*a+bi*b == 0:
            uf.unite(i, end2 % N)
            end2 += 1
            if end2 >= N:
                break
            thi, ai, bi = nisyuni[end2]

        if end == start + 1:
            end += 1

    # UFにグループ情報が格納されたので計算していく
    # print(uf.tree)

    # for i in range(N):
    #     _, ai, bi = abtheta[i]
    #     for j in range(i+1, N):
    #         _, aj, bj = abtheta[j]
    #         if ai*aj+bi*bj == 0:
    #             print("あるやん")
    #             print((ai, bi), (aj, bj))

    # return
    # デフォルトディクトに変換する
    d = defaultdict(list)
    for i in range(N):
        d[uf.root(i)].append(abtheta[i])

    ans = 1
    for key in d:
        # 各グループをさらに二つに分類
        maru = 1
        batu = 0
        th0, a0, b0 = d[key][0]
        for th, a, b in d[key][1:]:
            if a0 * a + b0*b == 0:
                batu += 1
            else:
                maru += 1
        buf = pow(2, maru, MOD)
        buf += pow(2, batu, MOD)
        buf -= 1
        buf %= MOD
        ans *= buf

    # print(d)
    print(ans-1)

    return


def main():

    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  # type: int
    A = [int()] * (N)  # type: "List[int]"
    B = [int()] * (N)  # type: "List[int]"
    for i in range(N):
        A[i] = int(next(tokens))
        B[i] = int(next(tokens))
    solve(N, A, B)


if __name__ == '__main__':
    main()
