class UnionFind:
    def __init__(self, n):
        self.v = [-1 for _ in range(n)]  # 根(負): 連結頂点数 * (-1) / 子(正): 根の頂点番号(0-indexed)

    def find(self, x):  # xを含む木における根の頂点番号を返す
        if self.v[x] < 0:  # (負)は根
            return x
        else:  # 根の頂点番号
            self.v[x] = self.find(self.v[x])  # uniteでは, 旧根に属する頂点の根が旧根のままなので更新
            return self.v[x]

    def unite(self, x, y):  # 違う根に属していたらrankが低くなるように連結
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return
        if -self.v[x] < -self.v[y]:  # size比較, 　(-1) * (連結頂点数 * (-1)), (正)同士の大小比較
            x, y = y, x  # 連結頂点数が少ない方をyにすると, findでの更新回数が減る？
        self.v[x] += self.v[y]  # 連結頂点数の和を取る, 連結頂点数 * (-1)
        self.v[y] = x  # 連結頂点数が少ないy(引数yの根の頂点番号)の根をx(引数xの根の頂点番号)にする

    def root(self, x):
        # try:
        return self.v[x] < 0  # (負)は根
        # except:
        #     print(f'{x=}, {self.v=}')

    def same(self, x, y):
        return self.find(x) == self.find(y)  # 同じ根に属するか

    def size(self, x):
        return -self.v[self.find(x)]  # 連結頂点数を返す


def main():
    from bisect import bisect_left
    from collections import defaultdict
    from math import acos, isclose, pi
    import sys
    input = sys.stdin.readline

    MOD = 10 ** 9 + 7

    N = int(input())
    fs = []
    for _ in range(N):
        a, b = map(int, input().split())
        fs.append((a, b))

    d = defaultdict(int)
    rt2 = 1 / pow(2, 0.5)
    rs = set()
    for a, b in fs:
        rad = acos((a + b) * rt2 / (a * a + b * b) ** 0.5)
        d[rad] += 1
        rs.add(rad)

    *rs, = sorted(rs)
    uf = UnionFind(len(rs))
    rs.append(1 << 10)
    for j, rad in enumerate(rs[:-1]):
        for rr in (pi * 3 / 2 - rad, pi / 2 - rad, rad + pi / 2, rad + pi * 3 / 2):
            i = bisect_left(rs, rr)
            if isclose(rs[i], rr):
                # print(f'{rr=},{rad=}')
                uf.unite(i, j)

    cnt = [1] * (len(rs) - 1)
    for v, rad in enumerate(rs[:-1]):
        if uf.root(v): continue
        root_node = uf.find(v)
        cnt[root_node] = (cnt[root_node] + d[rad]) % MOD

    ans = 1
    for v, c in enumerate(cnt):
        if uf.root(v):
            ans = ans * (c + 1) % MOD
    ans -= 1
    print(ans)


if __name__ == '__main__':
    main()

# import sys
# input = sys.stdin.readline
#
# sys.setrecursionlimit(10 ** 7)
#
# (int(x)-1 for x in input().split())
# rstrip()
#
# def binary_search(*, ok, ng, func):
#     while abs(ok - ng) > 1:
#         mid = (ok + ng) // 2
#         if func(mid):
#             ok = mid
#         else:
#             ng = mid
#     return ok
