We have caught N sardines. The deliciousness and fragrantness of the i-th sardine is A_i and B_i, respectively.
We will choose one or more of these sardines and put them into a cooler. However, two sardines on bad terms cannot be chosen at the same time.
The i-th and j-th sardines (i \neq j) are on bad terms if and only if A_i \cdot A_j + B_i \cdot B_j = 0.
In how many ways can we choose the set of sardines to put into the cooler? Since the count can be enormous, print it modulo 1000000007.

-----Constraints-----
 - All values in input are integers.
 - 1 \leq N \leq 2 \times 10^5
 - -10^{18} \leq A_i, B_i \leq 10^{18}

-----Input-----
Input is given from Standard Input in the following format:
N
A_1 B_1
:
A_N B_N

-----Output-----
Print the count modulo 1000000007.

-----Sample Input-----
3
1 2
-1 1
2 -1

-----Sample Output-----
5

There are five ways to choose the set of sardines, as follows:
 - The 1-st
 - The 1-st and 2-nd
 - The 2-nd
 - The 2-nd and 3-rd
 - The 3-rd

Difficulty: interview

Starter code:

Solutions:
#写経
#https://atcoder.jp/contests/abc168/submissions/13414936
from math import gcd
from collections import Counter
mod = 10**9 + 7
N,*AB = map(int,open(0).read().split())

def std(a,b):
    """
    a,bを既約にする
    """
    if a == 0:
        return(0,int(b!=0))
    g = gcd(a,b)
    a,b = a// g, b//g
    return(a,b) if a > 0 else (-a,-b)

C = Counter(std(a, b) for a, b in zip(*[iter(AB)] * 2))
def resolve():
    ans = 1
    cnt = 0
    for (a,b), v in C.items():
        if b > 0:
            if (b,-a) in C:
                ans *= -1 + pow(2,v,mod) + pow(2,C[(b,-a)], mod) #仲の悪い組み合わせが一緒に入らないように，別々に入れるか入れないかを判定 空集合は共通しているので引く
                ans %= mod
            else:
                cnt += v
        elif (-b,a) not in C:
            cnt += v
    ans *= pow(2,cnt,mod)
    ans += C[(0,0)] - 1
    print(ans%mod)
resolve()

def main():
    from collections import defaultdict
    from math import gcd
    import sys
    input = sys.stdin.readline


    mod = 10 ** 9 + 7
    n = int(input())
    fishes = defaultdict(int)
    zero_zero = 0
    zero = 0
    inf = 0

    for _ in range(n):
        a, b = list(map(int, input().split()))
        if a == 0 and b == 0:
            zero_zero += 1

        elif a == 0:
            zero += 1

        elif b == 0:
            inf += 1

        else:
            div = gcd(a, b)
            a //= div
            b //= div
            if b < 0:
                a *= -1
                b *= -1
            key = (a, b)
            fishes[key] += 1


    def get_bad_pair(fish):
        a, b = fish
        if a < 0:
            a *= -1
            b *= -1
        return (-b, a)


    ans = 1
    counted_key = set()
    for fish_key, count in list(fishes.items()):
        if fish_key in counted_key:
            continue

        bad_pair = get_bad_pair(fish_key)
        if bad_pair in fishes:
            pair_count = fishes[bad_pair]
            pattern = pow(2, count, mod) + pow(2, pair_count, mod) - 1
            counted_key.add(bad_pair)

        else:
            pattern = pow(2, count, mod)

        ans = ans * pattern % mod

    ans *= pow(2, zero, mod) + pow(2, inf, mod) - 1
    if zero_zero:
        ans += zero_zero

    ans -= 1
    print((ans % mod))

def __starting_point():
    main()

__starting_point()

from math import gcd
MOD = 10**9+7
N = int(input())
d = {}
zero = 0
for _ in range(N):
    a, b = list(map(int, input().split()))
    if a == b == 0:
        zero += 1
        continue
    # 正規化する
    if b < 0:
        b = -b
        a = -a
    g = gcd(a, b)
    b //= g
    a //= g
    # 入力のbが0の時はaの値を正の1に統一する
    if b == 0 and a == -1:
        a = 1

    # 今bは必ず正
    # aも正，すなわち傾きが正のとき
    if a > 0:
        if (a, b) in d:
            d[(a, b)][0] += 1
        else:
            d[(a, b)] = [1, 0]
    else:
        # aが負，すなわち傾きが負の時
        if (b, -a) in d:
            d[(b, -a)][1] += 1
        else:
            d[(b, -a)] = [0, 1]

ans = 1
for (a, b), (k, l) in list(d.items()):
    ans *= (pow(2, k, MOD)-1 + pow(2, l, MOD)-1 + 1)  # 最後の+1はどちらからも選ばなかったパターン
    ans %= MOD
ans -= 1
ans += zero
ans %= MOD
print(ans)


N=int(input())
from collections import defaultdict
dic=defaultdict(int)
dic[(0,0)]=dic[(0,1)]=0
import math
mod=1000000007
for _ in range(N):
    A,B=list(map(int,input().split()))
    if A<0:
        A,B=-A,-B
    if A==0:
        if B==0:
            dic[(0,0)]+=1
        else:
            dic[(0,1)]+=1
    elif B==0:
        dic[(1,0)]+=1
    else:
        gcd=math.gcd(A,B)
        A,B=A//gcd,B//gcd
        dic[(A,B)]+=1

ans=1
N-=dic[(0,0)]
for k,v in list(dic.items()):
    if k==(0,0) or k==(0,1):
        continue
    if k==(1,0):
        v_dash=dic[(0,1)]
        ans*=((pow(2,v,mod)-1)+(pow(2,v_dash,mod)-1)+1)
        ans%=mod
        N-=v+v_dash
        continue
    a,b=k
    if not (b,-a) in dic:
        continue
    v_dash=dic[(b,-a)]
    ans*=((pow(2,v,mod)-1)+(pow(2,v_dash,mod)-1)+1)
    ans%=mod
    N-=v+v_dash
ans*=pow(2,N,mod)
ans+=dic[(0,0)]-1
ans%=mod
print(ans)


from math import gcd
n=int(input())
mod = 1000000007
z=0
d={}
for _ in range(n):
  a,b=list(map(int,input().split()))
  if not any((a,b)):
    z+=1
    continue
  if a==0:
    d[(0,1)]=d.get((0,1),0)+1
    continue
  if b==0:
    d[(1,0)]=d.get((1,0),0)+1
    continue
  g = gcd(a,b)
  s = a//abs(a)
  a,b = (a//g)*s, (b//g)*s
  d[(a,b)]=d.get((a,b),0)+1

done = set()
ans = 1
for (a,b), v in list(d.items()):
  if (a,b) in done:continue
  done.add((a,b))
  done.add((-b,a))
  done.add((b,-a))
  w = d.get((-b,a),0)+d.get((b,-a),0)
  ans *= (pow(2,v,mod)+pow(2,w,mod)-1)
  ans %= mod
ans = (ans + z - 1 + mod)%mod
print(ans)


# ほぼ写経
from math import gcd
from collections import defaultdict
mod = 10**9+7
n = int(input())
mp = defaultdict(lambda: [0, 0])
zero_zero = 0
for i in range(n):
    a, b = list(map(int, input().split()))
    if a == 0 and b == 0:
        zero_zero += 1
        continue
    g = gcd(a, b)
    a //= g
    b //= g
    rot_cnt = 0
    while not (a > 0 and b >= 0):
        a, b = -b, a
        # ベクトルの成分が(正,正)となるまで90度回転、奇数回の時は元のベクトルと直行することになるのでrot_cntで記録
        # 今回の問題においては内積0を計算すればいいので逆ベクトルは考慮しなくてよい
        rot_cnt += 1
    mp[(a, b)][rot_cnt % 2] += 1
ans = 1
for s, t in list(mp.values()):
    now = (pow(2, s, mod) + pow(2, t, mod) - 1) % mod
    ans = (ans * now) % mod
ans = (ans - 1 + zero_zero) % mod
print(ans)


# ベクトルを既約分数にしてなおかつ方向を第一象限か第二象限に集める

from collections import defaultdict
from math import gcd
N = int(input())
MOD = 10**9 + 7
d = defaultdict(lambda: [0, 0])
zeros = 0
for _ in range(N):
    x, y = list(map(int, input().split()))
    if x == 0 and y == 0:
        zeros += 1
    elif x == 0:
        d[(0, 0)][0] += 1
    elif y == 0:
        d[(0, 0)][1] += 1
    else:
        if y < 0:
            x = -x
            y = -y
        g = gcd(abs(x), abs(y))
        x //= g
        y //= g
        if x < 0:
            d[(y, -x)][0] += 1
        else:
            d[(x, y)][1] += 1
ans = 1
for k, v in list(d.items()):
    ans *= pow(2, v[0], MOD)+pow(2, v[1], MOD)-1
    ans %= MOD
ans = (ans + zeros - 1) % MOD  # 各ベクトル対の組から一つも選ばないパターンを引いてる
print(ans)


from math import gcd
_, *e = [[*list(map(int, t.split()))] for t in open(0)]
ans = 1
mod = 10 ** 9 + 7
slope_dict = {}
zeros = 0
for x, y in e:
    if x == y == 0:
        zeros += 1
    else:
        d = gcd(x, y)
        x //= d
        y //= d
        if x < 0 or x == 0 < y:
            x, y = -x, -y
        s = 0
        if y < 0:
            x, y, s = -y, x, 1
        if (x, y) not in slope_dict:
            slope_dict[(x, y)] = [0, 0]
        slope_dict[(x, y)][s] += 1

for k in slope_dict:
    ans = ans * (pow(2, slope_dict[k][0], mod) +
                 pow(2, slope_dict[k][1], mod) - 1) % mod
print(((ans + zeros - 1) % mod))


from math import gcd
from collections import Counter
import sys
read = sys.stdin.read
readline = sys.stdin.readline
readlines = sys.stdin.readlines

MOD = 10**9+7

def main():
    N,*ab = list(map(int, read().split()))

    ab_zero = 0
    ratio = []
    for a, b in zip(*[iter(ab)]*2):
        if a == 0 and b == 0:
            ab_zero += 1
        else:
            if b < 0:
                a, b = -a, -b
            if b == 0:
                a = 1
            g = gcd(a, b)
            a //= g
            b //= g
            ratio.append((a, b))
    
    s = Counter(ratio)

    bad = 1
    no_pair = 0
    for k, v in list(s.items()):
        a, b = k
        if a > 0:
            if (-b, a) in s:
                bad *= pow(2, v, MOD) + pow(2, s[(-b, a)], MOD) -1
                bad %= MOD
            else:
                no_pair += v
            
        elif (b, -a) not in s:
            no_pair += v

    bad *= pow(2, no_pair, MOD)
    bad %= MOD

    ans = (bad + ab_zero -1) % MOD
    print(ans)


def __starting_point():
    main()

__starting_point()

from math import gcd
from collections import Counter

mod = 10 ** 9 + 7

N, *AB = map(int, open(0).read().split())

def std(a, b):
    if a == 0:
        return (0, int(b != 0))

    g = gcd(a, b)
    a, b = a // g, b // g
    return (a, b) if a > 0 else (-a, -b)

C = Counter(std(a, b) for a, b in zip(*[iter(AB)] * 2))

ans = 1
cnt = 0
for (a, b), v in C.items():
    if b > 0:
        if (b, -a) in C:
            ans *= -1 + pow(2, v, mod) + pow(2, C[(b, -a)], mod)
            ans %= mod
        else:
            cnt += v
    elif (-b, a) not in C:
        cnt += v

ans *= pow(2, cnt, mod)
ans += C[(0, 0)] - 1

print(ans % mod)

from collections import defaultdict
import math

def main():
    n = int(input())
    mod = 1000000007
    zeroes = 0
    quadrant1 = defaultdict(int)
    quadrant2 = defaultdict(int)

    for _ in range(n):
        a, b = map(int, input().split())
        if a == b == 0:
            zeroes += 1
            continue

        g = math.gcd(a, b)
        a, b = a//g, b//g 
        
        if b < 0:
            a, b = -a, -b
        
        if a <= 0:
            a, b = b, -a
            quadrant1[(a, b)] += 0
            quadrant2[(a, b)] += 1
        else:
            quadrant1[(a, b)] += 1
            quadrant2[(a, b)] += 0
    
    ans = 1
    for key, value in quadrant1.items():
        now = 1
        now += pow(2, value, mod) - 1
        now += pow(2, quadrant2[key], mod) - 1
        ans = (ans * now) % mod
    
    ans += (zeroes - 1)
    return ans % mod

def __starting_point():
    print (main())
__starting_point()

from collections import defaultdict
from math import gcd

mod = 10 ** 9 + 7
n = int(input())
fishes = defaultdict(int)
zero_zero = 0
zero = 0
inf = 0

for _ in range(n):
    a, b = list(map(int, input().split()))
    if a == 0 and b == 0:
        zero_zero += 1

    elif a == 0:
        zero += 1

    elif b == 0:
        inf += 1

    else:
        div = gcd(a, b)
        a //= div
        b //= div
        if b < 0:
            a *= -1
            b *= -1
        key = (a, b)
        fishes[key] += 1


def get_bad_pair(fish):
    a, b = fish
    if a < 0:
        a *= -1
        b *= -1
    return (-b, a)


ans = 1
counted_key = set()
for fish_key, count in list(fishes.items()):
    if fish_key in counted_key:
        continue

    bad_pair = get_bad_pair(fish_key)
    if bad_pair in fishes:
        pair_count = fishes[bad_pair]
        pattern = pow(2, count, mod) + pow(2, pair_count, mod) - 1
        counted_key.add(bad_pair)

    else:
        pattern = pow(2, count, mod)

    ans = ans * pattern % mod

ans *= pow(2, zero, mod) + pow(2, inf, mod) - 1
if zero_zero:
    ans += zero_zero

ans -= 1
print((ans % mod))


import math
def main():
    N = int(input())
    d = {}
    zb = 0
    za = 0
    zab = 0
    r = 0
    mod = 10**9 + 7
    for i in range(N):
        a, b = list(map(int, input().split()))
        if a== 0 and b == 0:
            zab += 1
        elif b == 0:
            zb += 1
        elif a == 0:
            za += 1
        else:
            if a < 0:
                a = -a
                b = -b
            x = math.gcd(abs(a), abs(b))
            if (a//x, b//x) in d:
                d[(a//x, b//x)] += 1
            else:
                d[(a//x, b//x)] = 1
    used = set()
    l = []
    for x in d:
        if x in used:
            continue
        a, b = x[0], x[1]
        used.add(x)
        if a * b > 0:
            t = (abs(b), -abs(a))
            if t in d:
                used.add(t)
                l.append((d[x], d[t]))
            else:
                l.append((d[x], 0))
        else:
            t = (abs(b), abs(a))
            if t in d:
                used.add(t)
                l.append((d[x], d[t]))
            else:
                l.append((d[x], 0))
    r = pow(2, za) + pow(2, zb) - 1
    for i in l:
        r *= (pow(2, i[0]) + pow(2, i[1]) - 1)
        r %= mod
    return (r - 1 + zab) % mod
print((main()))


from math import gcd

mod = 10**9 +7
N = int(input())
dic = {}

zero = 0
for _ in range(N):
    a,b = map(int, input().split())
    if  a ==0 and b == 0:
        zero += 1
        continue
    elif a == 0:
        key = (0,1)
    elif b == 0:
        key = (1,0)
    else:
        if a<0:
            a=-a 
            b=-b
        g = gcd(a,abs(b))
        key = (a//g,b//g)
    
    if key not in dic:
        dic[key]=0

    dic[key] +=1

ans = 1
for k1, v1 in dic.items():
    if v1 ==0:
        continue

    if k1[1] >0:
        k2 = (k1[1],-k1[0])
    else:
        k2 = (-k1[1],k1[0])

    if k2 not in dic:
        ans *= 2**v1
        ans %= mod
    else:
        ans *= ((2**v1-1) %mod) + ((2**dic[k2]-1) %mod) +1
        ans %= mod
        dic[k2]=0

ans = (ans + zero -1 )%mod
print(ans)

import math
from collections import deque

N = int(input())

a = []
b = []
for i in range(N):
    i1, i2 = list(map(int, input().split()))
    g = math.gcd(i1,i2)
    if g == 0:
        a.append(i1)
        b.append(i2)
        continue
    x = i1 // g
    y = i2 // g
    if x < 0:
        x = - x
        y = - y 
    a.append(x)
    b.append(y)

P = {}
for i in range(N):
    if b[i] < 0:
        tmp = b[i]
        b[i] = a[i]
        a[i] = - tmp
        sgn = 1
    elif a[i] == 0 and b[i] != 0:
        a[i] = b[i]
        b[i] = 0
        sgn = 1
    else :
        sgn = 0

    if (a[i],b[i]) in P:
        P[(a[i],b[i])][sgn]=P[(a[i],b[i])][sgn] + 1
    elif sgn == 0 :
        P[(a[i],b[i])]=[1,0]
    else :
        P[(a[i],b[i])]=[0,1]


MOD = 1000000007
a1 = 1 
ans0=0
for k in P:
    if k == (0,0):
        ans0 = P[k][0]
    else:
        a1 = a1*(pow(2,P[k][0],MOD)+pow(2,P[k][1],MOD) - 1) % MOD

if ans0 != 0:
    ans = ans0 + a1 -1
else:
    ans = a1 -1
print((ans%MOD))



from math import gcd
 
n=int(input())
mod = 10**9+7
 
d = dict()
zeros=0
for _ in range(n):
  a,b=map(int,input().split())
  if not any((a,b)):
    zeros+=1
    continue
  if all((a,b)):
    g = gcd(a,b)*(a//abs(a))
  elif a:
    g = a
  else:
    g = b
  
  p = a//g,b//g
  d[p] = d.get(p,0)+1
 
ans = 1
done = set()
for (a,b),v in d.items():
  if (-b,a) in done or (b,-a) in done:
    continue
  done.add((a,b))
  w=d.get((-b,a),0)+d.get((b,-a),0)
  ans *= (pow(2,v)+pow(2,w)-1)
  ans %= mod
print((ans+zeros-1+mod)%mod)

from math import gcd
n=int(input())
mod=10**9+7
d1=dict()
d2=dict()
zero=0
zeroa=0
zerob=0
for _ in range(n):
    a,b=list(map(int,input().split()))
    if a==0 and b==0:
        zero+=1
    elif a==0 and b!=0:
        zeroa+=1
    elif a!=0 and b==0:
        zerob+=1
    else:
        g=gcd(abs(a),abs(b))
        na=a//g
        nb=b//g
        if na<0:
            na=-na
            nb=-nb
        if (na,nb) not in d1 and (na,nb) not in d2:
            d1[(na,nb)]=1
            d2[(-nb,na)]=0
            d2[(nb,-na)]=0
        elif (na,nb) in d1:
            d1[(na,nb)]+=1
        else:
            d2[(na,nb)]+=1
#print(d1)
#print(d2)
d1=list(d1.items())
ans=pow(2,zeroa,mod)+pow(2,zerob,mod)-1
ans%=mod
for (a,b),cnt1 in d1:
  cnt2=0
  cnt2+=d2[(-b,a)]
  cnt2+=d2[(b,-a)]
  ans*=pow(2,cnt1,mod)+pow(2,cnt2,mod)-1
  ans%=mod
ans+=zero
ans=(ans+mod-1)%mod
print(ans)
#print(zeroa,zerob)


N=int(input())
from collections import defaultdict
dic=defaultdict(int)
import math
mod=1000000007
for _ in range(N):
    A,B=list(map(int,input().split()))
    if A<0:
        A,B=-A,-B
    if A==0:
        if B==0:
            dic[(0,0)]+=1
        else:
            dic[(0,1)]+=1
    elif B==0:
        dic[(1,0)]+=1
    else:
        gcd=math.gcd(A,B)
        A,B=A//gcd,B//gcd
        dic[(A,B)]+=1

ans=1
N-=dic[(0,0)]
for k,v in list(dic.items()):
    if k==(0,0) or k==(0,1):
        continue
    if k==(1,0):
        if not (0,1) in dic:
            continue
        v_dash=dic[(0,1)]
        ans*=((pow(2,v,mod)-1)+(pow(2,v_dash,mod)-1)+1)
        ans%=mod
        N-=v+v_dash
        continue
    a,b=k
    if not (b,-a) in dic:
        continue
    v_dash=dic[(b,-a)]
    ans*=((pow(2,v,mod)-1)+(pow(2,v_dash,mod)-1)+1)
    ans%=mod
    N-=v+v_dash
ans*=pow(2,N,mod)
ans+=dic[(0,0)]-1
ans%=mod
print(ans)


from math import gcd
from collections import Counter

mod = 10 ** 9 + 7

N, *AB = map(int, open(0).read().split())

def std(a, b):
    if a == 0:
        return (0, 1)

    g = gcd(a, b)
    a, b = a // g, b // g
    return (a, b) if a > 0 else (-a, -b)

C = Counter()
orig = 0
for a, b in zip(*[iter(AB)] * 2):
    if a == b == 0:
        orig += 1
    else:
        C[std(a, b)] += 1

ans = 1
cnt = 0
for (a, b), v in C.items():
    if b > 0:
        if (b, -a) in C:
            ans *= -1 + pow(2, v, mod) + pow(2, C[(b, -a)], mod)
            ans %= mod
        else:
            cnt += v
    elif (-b, a) not in C:
        cnt += v

ans *= pow(2, cnt, mod)
ans += orig - 1

print(ans % mod)

mod = 1000000007
n = int(input())

ab00 = 0
abx0 = 0
ab0x = 0
p = []
m = []

from math import gcd
for _ in range(n):
    i, j = map(int, input().split())
    if i == 0:
        if j == 0:
            ab00 += 1
        else:
            ab0x += 1
        continue
    elif j == 0:
        abx0 += 1
        continue
    k = gcd(i, j)
    i //= k
    j //= k
    if i > 0:
        if j > 0:
            p.append((i, j))
        else:
            m.append((-j, i))
    elif j > 0:
        m.append((j, -i))
    else:
        p.append((-i, -j))

m.sort()
p.sort()

ans = pow(2, ab0x, mod) + pow(2, abx0, mod) - 1
ans %= mod

mi = 0
pi = 0
while mi < len(m) and pi < len(p):
    if m[mi] == p[pi]:
        mi += 1
        mnum = 1
        while mi < len(m) and m[mi] == m[mi-1]:
            mi += 1
            mnum += 1
        pi += 1
        pnum = 1
        while pi < len(p) and p[pi] == p[pi-1]:
            pi += 1
            pnum += 1
        ans *= pow(2, mnum, mod) + pow(2, pnum, mod) - 1
        ans %= mod

    elif m[mi] < p[pi]:
        mi += 1
        mnum = 1
        while mi < len(m) and m[mi] < p[pi]:
            mi += 1
            mnum += 1
        ans *= pow(2, mnum, mod)
        ans %= mod
    
    else:
        pi += 1
        pnum = 1
        while pi < len(p) and p[pi] < m[mi]:
            pi += 1
            pnum += 1
        ans *= pow(2, pnum, mod)
        ans %= mod

ans *= pow(2, len(p) - pi, mod)
ans %= mod
ans *= pow(2, len(m) - mi, mod)
ans %= mod
ans = (ans - 1 + ab00) % mod
print(ans)

n=int(input())
ab=[list(map(int,input().split())) for _ in range(n)]
from collections import defaultdict
from math import gcd
d=defaultdict(int)
for a,b in ab:
  if a==0 and b==0:
    d[(0,0)]+=1
  elif a==0:
    d[(1,0)]+=1
  elif b==0:
    d[(0,1)]+=1
  else:
    if a<0:
      a*=-1
      b*=-1
    g=gcd(a,b)
    d[(a//g,b//g)]+=1
mod=pow(10,9)+7
ans=1
keys=list(d.keys())
for k in keys:
  if k==(0,0):
    continue
  else:
    a,b=k
    x=b if b>0 else -b
    y=-a if b>0 else a
    k0=tuple([x,y])
    if k0 in d:
      ans*=pow(2,d[k],mod)-1+pow(2,d[k0],mod)-1+1
      ans%=mod
      d[k]=0
      d[k0]=0
    else:
      ans*=pow(2,d[(a,b)],mod)
      ans%=mod
ans+=d[(0,0)]
ans-=1
print((ans%mod))


from math import gcd
mod = 1000000007
n = int(input())
zero = 0
bad = {}
for i in range(n):
    x, y = list(map(int, input().split()))
    if x == 0 and y == 0:
        zero += 1
        continue
    g = gcd(x, y)
    x //= g
    y //= g
    if y < 0: x, y = -x, -y
    if y==0 and x<0: x, y = -x, -y
    is_rotate90 = (x <= 0)
    if is_rotate90: x, y = y, -x
    if not (x, y) in bad: bad[x, y] = [0, 0]
    bad[x, y][is_rotate90] += 1

ans = 1
for x, y in bad:
    c1, c2 = bad[x, y]
    c3 = (pow(2, c1, mod) - 1) + (pow(2, c2, mod) - 1) + 1
    ans *= c3
    ans %= mod

ans += zero - 1
ans = (ans + mod) % mod
print(ans)


N=int(input())
from collections import defaultdict
import math
d = defaultdict(int)
MOD=10**9+7
for i in range(N):
  a,b=map(int,input().split())
  x=math.gcd(abs(a),abs(b))
  if a==0:
    if b==0:
      k=(0,0)
    else:
      k=(0,1)
  elif b==0:
    k=(1,0)
  else:
    if a<0:
      a,b=-a,-b
    if b<0:
      a,b=a//x,-((-b)//x)
    else:
      a,b=a//x,b//x
    k=(a,b)
  d[k]+=1

ind=defaultdict(int)
index=1
_ans=[1]
for a,b in list(d.keys()):
  if a==b==0:
    continue
  if b<=0:
    _k=(-b,a)
  else:
    _k=(b,-a)
  if d[_k]==0:
    _ans[0]*=pow(2,d[(a,b)])
  else:
    if ind[_k]==0:
      _ans.append(pow(2,d[(a,b)],MOD))
      ind[(a,b)]=index
      index+=1
    else:
      _ans[ind[_k]]+=pow(2,d[(a,b)],MOD)-1
ans=1
for a in _ans:
  ans=ans*a%MOD
print((d[(0,0)]+ans-1+MOD)%MOD)

from math import gcd

n = int(input())
ration = dict()
used = dict()
for _ in range(n):
    a, b = list(map(int, input().split()))
    if a == 0 or b == 0:
        if a == b == 0:
            r = '0'
        elif a == 0:
            r = '0a'
        else:
            r = '0b'
    else:
        s = '-' if (a < 0) ^ (b < 0) else '+'
        a = abs(a)
        b = abs(b)
        g = gcd(a, b)
        r = f'{s} {a//g} {b//g}'
    ration[r] = ration.get(r, 0) + 1
    used[r] = 0

res = 1
mod = 10**9+7
add = 0
for k, v in list(ration.items()):
    if used[k]:
        continue
    if k == '0':
        add += v
        used[k] = 1
    elif k == '0a' or k == '0b':
        res *= 2**ration.get('0a', 0) + 2**ration.get('0b', 0) - 1
        used['0a'] = used['0b'] = 1
    else:
        r = k.split()
        l = f'{"-" if r[0]=="+" else "+"} {r[2]} {r[1]}'
        res *= 2**v + 2**ration.get(l, 0) - 1
        used[k] = used[l] = 1
    res %= mod

res += add
res -= 1
if res < 0:
    res += mod
print(res)


from math import gcd
from collections import defaultdict


def sign(x):
    if x < 0:
        return -1
    if x > 0:
        return +1
    return 0


def power(a, b, m):
    res = 1
    base = a
    while b:
        if b & 1:
            res = res * base % m
        base = base * base % m
        b = b >> 1
    return res


N = int(input())
M = 1000000007
cnt = defaultdict(int)
case00 = 0

for _ in range(N):
    a, b = list(map(int, input().split()))
    if a == 0 and b == 0:  # (0, 0) cannot pair with anyone
        case00 += 1
        continue

    s = sign(a) * sign(b)
    a, b = abs(a), abs(b)
    g = gcd(a, b)
    a, b = a // g, b // g
    cnt[s, a, b] += 1


ans = 1  # empty set
vis = set()
for (s, a, b) in list(cnt.keys()):
    if (s, a, b) in vis:
        continue

    if (-s, b, a) in cnt:
        mul = 1  # empty set from (s, a, b) and (-s, b, a)
        mul += power(2, cnt[s, a, b], M) - 1  # non-empty subsets from (s, a, b)
        mul += power(2, cnt[-s, b, a], M) - 1  # non-empty subsets from (-s, b, a)
        ans = ans * (mul % M) % M
        vis.add((-s, b, a))
    else:
        ans = ans * power(2, cnt[s, a, b], M) % M

ans = (ans - 1 + M) % M  # Remove empty set
ans = (ans + case00) % M  # Special case
print(ans)


import sys, os

if 'local' in os.environ :
    sys.stdin = open('./input.txt', 'r')

f = lambda:list(map(int, input().split()))


def gcd(a,b):
    return b if a == 0 else gcd(b%a, a)

def quick_pow(x,n, mod):
    ans= 1
    while n:
        if n&1:
            ans *= x
            ans %= mod
        x *= x
        x %= mod
        n >>= 1
    
    return ans


def solve():
    mod = 1000000007
    n = f()[0]

    dirs = {}

    all0 = 0
    x0 = 0
    y0 = 0

    for _ in range(n):
        a,b = f()
        if a ==0 and b == 0:
            all0 += 1
            continue
        if a == 0:
            x0 += 1
            continue
        if b == 0:
            y0 += 1
            continue

        if a <0:
            a = -a
            b = -b
        g = gcd(abs(a),abs(b))
        a //= g
        b //= g

        if a*b >0:
            if (a,b) not in dirs:
                dirs[(a,b)] = {}
                dirs[(a,b)][0] = 0
                dirs[(a,b)][1] = 0
            dirs[(a,b)][0] = dirs[(a,b)][0]+ 1
        else:
            if (-b,a) not in dirs:
                dirs[(-b,a)] = {}
                dirs[(-b,a)][0] = 0
                dirs[(-b,a)][1] = 0
            dirs[(-b,a)][1] = dirs[(-b,a)][1] + 1 
            
    
    ans = 1
    ans *= (quick_pow(2, x0, mod) + quick_pow(2, y0, mod)-1 + mod) % mod

    
    ans %= mod
    for _, l in list(dirs.items()):
        ans *= (quick_pow(2, l[0], mod) + quick_pow(2, l[1], mod)-1 + mod)%mod
        ans %= mod

    
    ans -= 1
    if all0:
        ans+= all0
    
    ans += mod
    ans%= mod
    print(ans)
    

solve()



from math import gcd
from sys import setrecursionlimit
setrecursionlimit(4100000)
mod = 10 ** 9 + 7
n = int(input())

zeros = 0
d = {}
for i in range(n):
    x, y = map(int, input().split())
    if x == 0 and y == 0:
        zeros += 1
    else:
        g = gcd(x, y)
        x, y = x // g, y // g
        if (y < 0) or (y == 0 and x < 0): 
            x, y = -x, -y
        else: 
            pass
        if x <= 0:
            sq = True   #second quadrant
            x, y = y, -x
        else:
            sq = False
        if sq == True:
            if (x, y) in d:
                d[(x, y)][1] += 1
            else:
                d[(x, y)] = [0, 1]
        else:
            if (x, y) in d:
                d[(x, y)][0] += 1
            else:
                d[(x, y)] =[1, 0] 

#繰り返し2乗法
def  mod_pow(a:int, b:int, mod:int)->int:
    if b == 0:
        return 1 % mod
    elif b % 2 == 0:
        return (mod_pow(a, b//2, mod) ** 2) % mod
    elif b == 1:
        return a % mod
    else:
        return ((mod_pow(a, b//2, mod) ** 2) * a) % mod
#print(d)

ans = 1
for (a, b), (k, l) in d.items():
    now = 1
    now = (now + mod_pow(2, k, mod) - 1) % mod
    now = (now + mod_pow(2, l, mod) - 1) % mod
    ans = (ans * now) % mod
    
ans -= 1
zeros = zeros % mod
ans = (ans + zeros) % mod
print(ans)

from collections import defaultdict
n,*L=list(map(int,open(0).read().split()))
mod=10**9+7
d=defaultdict(lambda:[0,0])
gcd=lambda x,y:x if y==0 else gcd(y,x%y)
two=[1]*(n+1)
for i in range(n):
	two[i+1]=(two[i]*2)%mod
zero=0
for a,b in zip(*[iter(L)]*2):
	if a==b==0:
		zero+=1
		continue
	if a==0:
		d[(0,1)][0]+=1
	elif b==0:
		d[(0,1)][1]+=1
	else:
		g=gcd(a,b)
		a//=g
		b//=g
		if a*b>0:
			d[(a,b)][0]+=1
		else:
			d[(abs(b),abs(a))][1]+=1
ans=1
for (_,_),(x,y) in list(d.items()):
	ans*=(two[x]+two[y]-1)%mod
	ans%=mod
print(((ans+zero+mod-1)%mod))


from math import gcd
import math
import numpy as np
import decimal
import collections
import itertools
import sys
import random
#Union-Find
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.par = [-1 for i in range(self.n)]
    def find(self, x):
        if self.par[x] < 0:
            return x
        else:
            self.par[x] = self.find(self.par[x])
            return self.par[x]
    def unite(self, x, y):
        p = self.find(x)
        q = self.find(y)
        if p == q:
            return None
        if p > q:
            p, q = q, p
        self.par[p] += self.par[q]
        self.par[q] = p
    def same(self, x, y):
        return self.find(x) == self.find(y)
    def size(self, x):
        return -self.par[self.find(x)]

#素数関連
def prime_numbers(x):
    if x < 2:
        return []
    prime_numbers = [i for i in range(x)]
    prime_numbers[1] = 0
    for prime_number in prime_numbers:
        if prime_number > math.sqrt(x):
            break
        if prime_number == 0:
            continue
        for composite_number in range(2 * prime_number, x, prime_number):
            prime_numbers[composite_number] = 0
    return [prime_number for prime_number in prime_numbers if prime_number != 0]
def is_prime(x):
    if x < 2:
        return False
    if x == 2 or x == 3 or x == 5:
        return True
    if x % 2 == 0 or x % 3 == 0 or x % 5 == 0:
        return False
    prime_number = 7
    difference = 4
    while prime_number <= math.sqrt(x):
        if x % prime_number == 0:
            return False
        prime_number += difference
        difference = 6 - difference
    return True
#Prime-Factorize
def prime_factorize(n):
    res = []
    while n % 2 == 0:
        res.append(2)
        n //= 2
    f = 3
    while f ** 2 <= n:
        if n % f == 0:
            res.append(f)
            n //= f
        else:
            f += 2
    if n != 1:
        res.append(n)
    return res
#nCr
mod = 10 ** 9 + 7
class nCr():
    def __init__(self, n):
        self.n = n
        self.fa = [1] * (self.n + 1)
        self.fi = [1] * (self.n + 1)
        for i in range(1, self.n + 1):
            self.fa[i] = self.fa[i - 1] * i % mod
            self.fi[i] = pow(self.fa[i], mod - 2, mod)
    def comb(self, n, r):
        if n < r:return 0
        if n < 0 or r < 0:return 0
        return self.fa[n] * self.fi[r] % mod * self.fi[n - r] % mod
#拡張Euclidの互除法
def extgcd(a, b, d = 0):
    g = a
    if b == 0:
        x, y = 1, 0
    else:
        x, y, g = extgcd(b, a % b)
        x, y = y, x - a // b * y
    return x, y, g
#BIT
class BinaryIndexedTree():
    def __init__(self, n):
        self.n = n
        self.BIT = [0] * (self.n + 1)
    def add(self, i, x):
        while i <= self.n:
            self.BIT[i] += x
            i += i & -i
    def query(self, i):
        res = 0
        while i > 0:
            res += self.BIT[i]
            i -= i & -i
        return res
#Associative Array
class AssociativeArray():
    def __init__(self, q):
        self.dic = dict()
        self.q = q
    def solve(self):
        for i in range(self.q):
            Query = list(map(int, input().split()))
            if Query[0] == 0:
                x, y, z = Query
                self.dic[y] = z
            else:
                x, y = Query
                if y in self.dic:
                    print(self.dic[y])
                else:
                    print(0)
#Floor Sum
def floor_sum(n, m, a, b):
    res = 0
    if a >= m:
        res += (n - 1) * n * (a // m) // 2
        a %= m
    if b >= m:
        res += n * (b // m)
        b %= m
    y_max = (a * n + b) // m
    x_max = y_max * m - b
    if y_max == 0:
        return res
    res += y_max * (n + (-x_max // a))
    res += floor_sum(y_max, a, m, (a - x_max % a) % a)
    return res
#Z-Algorithm
def z_algorithm(s):
    str_len = len(s)
    res = [0] * str_len
    res[str_len - 1] = str_len
    i, j = 1, 0
    while i < str_len:
        while i + j < str_len and s[i + j] == s[j]:
            j += 1
        res[i] = j
        if j == 0:
            i += 1
            continue
        k = 1
        while i + k < str_len and j > res[k] + k:
            res[i + k] = res[k]
            k += 1
        i += k
        j -= k
    return res
class Manacher():
    def __init__(self, s):
        self.s = s
    def coustruct(self):
        i, j = 0, 0 
        s_len = len(self.s)
        res = [0] * s_len
        while i < s_len:
            while i - j >= 0 and i + j < s_len and self.s[i - j] == self.s[i + j]:
                j += 1
            res[i] = j
            k = 1
            while i - k >= 0 and k + res[i - k] < j:
                k += 1
            i += k
            j -= k
#mod-sqrt
def mod_sqrt(a, p):
    if a == 0:
        return 0
    if p == 2:
        return 1
    k = (p - 1) // 2
    if pow(a, k, p) != 1:
        return -1
    while True:
        n = random.randint(2, p - 1)
        r = (n ** 2 - a) % p
        if r == 0:
            return n
        if pow(r, k, p) == p - 1:
            break
    k += 1
    w, x, y, z = n, 1, 1, 0
    while k:
        if k % 2:
            y, z = w * y + r * x * z, x * y + w * z
        w, x = w * w + r * x * x, 2 * w * x
        w %= p
        x %= p
        y %= p
        z %= p
        k >>= 1
    return y
mod = 10 ** 9 + 7
n = int(input())
zeros = 0
count = dict()
for i in range(n):
    a, b = map(int, input().split())
    if (a, b) == (0, 0):
        zeros += 1
        continue
    g = gcd(abs(a), abs(b))
    a //= g
    b //= g
    cnt = 0
    while a < 0 or b <= 0:
        a, b = -1 * b, a
        cnt += 1
    if not (a, b) in count:
        count[(a, b)] = [0, 0]
    count[(a, b)][cnt % 2] += 1
ans = 1
for i in count:
    a, b = count[i]
    ans *= (pow(2, a, mod) + pow(2, b, mod) - 1) % mod
    ans %= mod
print((ans + zeros - 1) % mod)

import sys
from math import gcd
from collections import Counter

read = sys.stdin.read
readline = sys.stdin.readline

N, *AB = list(map(int, read().split()))
mod = 10 ** 9 + 7

ab = []
zero = 0
for A, B in zip(*[iter(AB)] * 2):
    if A == 0 and B == 0:
        zero += 1
        continue
    if A == 0:
        B = -1
    elif B == 0:
        A = 1
    else:
        g = gcd(A, B)
        A //= g
        B //= g
    if A < 0:
        A, B = -A, -B
    ab.append((A, B))

cnt = Counter(ab)
answer = 1
checked = set()
ok = 0

for (i, j), n in list(cnt.items()):
    if (i, j) in checked:
        continue
    if j < 0:
        c, d = -j, i
    else:
        c, d = j, -i
    if (c, d) in cnt:
        m = cnt[(c, d)]
        answer = (answer * (pow(2, n, mod) + pow(2, m, mod) - 1)) % mod
        checked.add((c, d))
    else:
        ok += n

answer *= pow(2, ok, mod)
answer -= 1
answer += zero
answer %= mod
print(answer)


import numpy as np
dic = dict()
mod = 10 ** 9 + 7
p = 0

def reg(a, b):
	if a < 0 or (a == 0 and b < 0):
		a, b = -a, -b
	if b > 0:
		return 0, a, b
	else:
		return 1, -b, a

n = int(input())
for _ in range(n):
	a, b = map(int, input().split())
	if a == 0 and b == 0:
		p += 1
		continue
	ab = np.gcd(a, b)
	a, b = a//ab, b//ab
	idx, a, b = reg(a, b)
	k = (a, b)
	if k not in dic.keys():
		dic[k] = [0, 0]
	dic[k][idx] += 1

not_p = 1
for k in dic.keys():
	a, b = k
	pp, pm = dic[k]
	not_p *= (pow(2, pp, mod) + pow(2, pm, mod) - 1) % mod
	not_p %= mod

print((p + not_p -1) % mod)

import sys
input = sys.stdin.readline
from collections import defaultdict
from fractions import Fraction
from bisect import bisect_left, bisect_right


def read():
    N = int(input().strip())
    # a!=0 かつ b!=0
    AB = []
    # a!=0 または b!=0
    ZAB = []
    M = 0
    ZM = 0
    for i in range(N):
        a, b = map(int, input().strip().split())
        # (a, b) == (0, 0) は除外する
        if a != 0 or b != 0:
            AB.append((a, b))
            M += 1
    return N, M, AB


def solve(N, M, AB, MOD=1000000007):
    # 魚iに対して、仲の悪い魚jの個数を求める
    D = defaultdict(int)
    INVD = defaultdict(int)

    # Ai/Bi の既約分数でグループを作る
    keys = set()
    for a, b in AB:
        if a == 0:
            # 0/Bi
            D["0"] += 1
            keys.add("0")
        elif b == 0:
            # Ai/0
            INVD["0"] += 1
            keys.add("0")
        else:
            f = Fraction(a, b)
            if f > 0:
                key = str(f)
                D[key] += 1
                keys.add(key)
            else:
                key = str(-1/f)
                INVD[key] += 1
                keys.add(key)

    # a!=0 かつ b!=0 における魚群の選び方を数え上げ
    # グループiにおいて
    # (1-1) D[i] 個の魚から1つ以上選ぶ ... (2^D[i] - 1) 通り
    # (1-2) INVD[i] 個の魚から1つ以上選ぶ ... (2^INVD[i] - 1) 通り
    # (1-3) グループi から魚を選ばない ... 1通り
    ans = 1
    for key in keys:
        g1 = pow(2, D[key], MOD) - 1
        g2 = pow(2, INVD[key], MOD) - 1
        g3 = 1
        ans *= (g1 + g2 + g3)
        ans %= MOD

    # 魚を1つも選ばない場合が含まれているので、これを除く
    ans -= 1
    ans %= MOD

    # (a, b) == (0, 0) があるときは、その1匹だけなら入れられる
    ans += N - M
    ans %= MOD

    return ans


def __starting_point():
    inputs = read()
    outputs = solve(*inputs)
    if outputs is not None:
        print("%s" % str(outputs))
__starting_point()

from math import gcd
n = int(input())
p = 10**9 + 7
iwashi = {}
bad = 0
ans = 1
for i in range(n):
    x, y = list(map(int, input().split()))
    if(x == 0 and y == 0):
      bad += 1
      continue
    elif(x == 0):
        try:
        	iwashi[(0, 1)] += 1
        except KeyError:
            iwashi[(0, 1)] = 1
            continue
    elif(y == 0):
        try:
        	iwashi[(1, 0)] += 1
        except KeyError:
            iwashi[(1, 0)] = 1
        continue
    else:
        g = gcd(x, y)
        x, y = x // g, y // g
        if x < 0:
            x, y = -x, -y
        try:
        	iwashi[(x, y)] += 1
        except KeyError:
            iwashi[(x, y)] = 1
            
for x, y in iwashi:
    a = iwashi[(x, y)]
    if y > 0:
    	rx,ry = y, -x
    else:
      	rx,ry = -y, x
    try:
        b = iwashi[(rx,ry)]
        iwashi[(rx,ry)] = 0
    except KeyError:
      	b = 0
    ans *= pow(2, a, p) + pow(2, b, p) - 1
    ans %= p
    iwashi[(x, y)] = 0
print(((ans + bad - 1) % p))


from collections import defaultdict
from math import gcd

mod = 10 ** 9 + 7

n = int(input())
ab = [tuple(map(int, input().split())) for _ in range(n)]

d = defaultdict(int)
zero = 0
for a, b in ab:
    # zero　別処理
    if a == b == 0:
        zero += 1
        continue
    if a == 0:
        d[(0, 1)] += 1
        continue
    if b == 0:
        d[(1, 0)] += 1
        continue

    # a[i]が絶対に非負になるように
    if a < 0:
        a *= -1
        b *= -1
    g = gcd(a, b)
    d[(a // g, b // g)] += 1

all = n - zero
ans = 1
for k1, v in list(d.items()):
    k2 = (k1[1], -k1[0])
    if k2 in list(d.keys()):
        all -= v
        all -= d[k2]
        ans = ans * (pow(2, v, mod) + pow(2, d[k2], mod) - 1) % mod
ans = ans * pow(2, all, mod) % mod
print(((ans - 1 + zero) % mod))


from math import gcd
MOD = 10 ** 9 + 7
N = int(input())
d = dict()
zeros = 0
for _ in range(N):
    a, b = tuple(map(int, input().split()))
    if not any((a, b)):
        zeros += 1
        continue
    g = gcd(a, b) * (a // abs(a)) if all((a, b)) else a if a else b
    p = a // g, b // g
    d[p] = d.get(p, 0) + 1
done = set()
total = 1
for (a, b), v in d.items():
    if (b, -a) in done or (-b, a) in done:
        continue
    done.add((a, b))
    w = d.get((b, -a), 0) + d.get((-b, a), 0)
    total = total * (pow(2, v, MOD) + pow(2, w, MOD) - 1) % MOD
print((total + zeros - 1) % MOD)

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
sys.setrecursionlimit(10**7)
from pprint import pprint as pp
from pprint import pformat as pf
# @pysnooper.snoop()
#import pysnooper # debug

import math
#from sortedcontainers import SortedList, SortedDict, SortedSet # no in atcoder
import bisect
from fractions import Fraction
from collections import defaultdict

def is_same_sign(a, b):
    if a > 0 and b > 0:
        return True
    if a < 0 and b < 0:
        return True
    return False

def fraction_taple(a, b):
    g = math.gcd(a, b)
    if is_same_sign(a, b):
        s = 1
    else:
        s = -1
    a = abs(a) // g
    b = abs(b) // g
    return (s, a, b)

def mode(a, b):
    # retrun dict_key, arr_key
    if a == 0 and b == 0:
        return 0, 0
    if a == 0:
        return 'ab', 0
    if b == 0:
        return 'ab', 1
    x = fraction_taple(a, b)
    y = fraction_taple(-1 * b, a)
    if x > y:
        return x, 0
    else:
        return y, 1

MOD = 1000000007

def __starting_point():

    n = int(input())

    d = defaultdict(lambda: [0, 0])
    zero = 0
    for _ in range(n):
        a, b = list(map(int, input().split()))
        dkey, akey = mode(a, b)
        if dkey == 0:
            zero += 1
        else:
            d[dkey][akey] += 1
    #print('d') # debug
    #pp(d) # debug

    ans = 1
    for pair in list(d.values()):
        tmp = pow(2, pair[0], MOD) - 1 + pow(2, pair[1], MOD) - 1 + 1
        ans *= tmp
    ans += zero - 1
    ans %= MOD
    #print('ans') # debug
    print(ans)

    #print('\33[32m' + 'end' + '\033[0m') # debug

__starting_point()

from collections import defaultdict, deque
import math

kMod = 1000000007

N = int(input())
key2count = defaultdict(lambda: [0, 0])

for _ in range(N):
    a, b = map(int, input().split())
    g = math.gcd(a, b)
    if a < 0 or a == 0 and b < 0:
        a, b = -a, -b
    if g > 0:
        a, b = a//g, b//g
    idx = 0
    if b <= 0:
        idx = 1
        a, b = -b, a
    key2count[(a, b)][idx] += 1

ans = 1
for key, val in key2count.items():
    if key == (0, 0):
        continue
    plus, minus = val
    ans *= (pow(2, plus, kMod) + pow(2, minus, kMod)-1)
    ans %= kMod

ans += sum(key2count[(0, 0)])

print((ans + kMod-1) % kMod)

N=int(input())
AB=[list(map(int,input().split())) for i in range(N)]
from collections import defaultdict
d=defaultdict(int)
d2=defaultdict(int)
a0=0
b0=0
c0=0
from math import gcd
for a,b in AB:
    if a==b==0:
        c0+=1
    elif a==0:
        a0+=1
    elif b==0:
        b0+=1
    else:
        if a<0:
            a,b=-a,-b
        g=gcd(a,b)
        a,b=a//g,b//g
        if b>0:
            d[(a,b)]+=1
        else:
            d2[(-b,a)]+=1
m=10**9+7
a=1
for k,v in d.items():
    if k in d2:
        a=a*(pow(2,v,m)+pow(2,d2[k],m)-1)%m
    else:
        a=a*pow(2,v,m)%m
for k,v in d2.items():
    if k not in d:
        a=a*pow(2,v,m)%m
print((a*(pow(2,a0,m)+pow(2,b0,m)-1)-1+c0)%m)

from math import gcd


MOD = 10**9 + 7

n = int(input())

cnt = {}

zero_cnt = 0
for i in range(n):
    a, b = list(map(int, input().split()))
    if (a,b) == (0,0):
        zero_cnt += 1
        continue
    g = gcd(abs(a), abs(b))
    a //= g
    b //= g
    rotate = 0
    while not (a >= 0 and b > 0):
        a,b = -b,a
        rotate += 1
    if (a,b) not in cnt:
        cnt[(a,b)] = [0,0]

    cnt[(a,b)][rotate % 2] += 1

ans = 1
    
for key in cnt:
    A, B = cnt[key]
    ans *= 1 + pow(2, A, MOD) - 1 + pow(2, B, MOD) - 1
    ans %= MOD

ans += zero_cnt
ans -= 1
print((ans % MOD))

    


N = int(input())
zero = 0
r_zero = 0
l_zero = 0
mod = 1000000007
from collections import defaultdict
from math import gcd
dic = defaultdict(int)
for i in range(N):
    A, B = list(map(int, input().split()))
    if A==0 and B==0:
        zero += 1
        continue
    elif A==0:
        r_zero += 1
    elif B==0:
        l_zero += 1
    else:
        g = gcd(A, B)
        A //= g
        B //= g
        if A<0:
            A, B = -A, -B
        dic[(A, B)] += 1

dickey = list(dic.keys())
s = set(dickey)
nopair = N-zero-r_zero-l_zero
ans = pow(2, r_zero, mod)+pow(2, l_zero, mod)-1
for a, b in dickey:
    if a*b>0 and (b, -a) in s:
        ans *= (pow(2, dic[(a, b)], mod)+pow(2, dic[(b, -a)], mod)-1)%mod
        nopair -= (dic[(a, b)]+dic[(b, -a)])
ans *= pow(2, nopair, mod)
print(((ans-1+zero)%mod))



def main():
    import sys
    sys.setrecursionlimit(10**9)
    input = sys.stdin.readline
    import math
    from collections import defaultdict

    mod = 1000000007

    N = int(input())

    zero_pair = 0
    zero_a = 0
    zero_b = 0
    pair_plus = defaultdict(int)
    pair_minus = defaultdict(int)
    for a, b in [tuple(map(int, input().split())) for _ in range(N)]:
        if a == 0 and b == 0:
            zero_pair += 1
            continue
        if a == 0:
            zero_a += 1
            continue
        if b == 0:
            zero_b += 1
            continue

        abs_a = abs(a)
        abs_b = abs(b)
        g = math.gcd(abs_a, abs_b)
        abs_a = abs_a//g
        abs_b = abs_b//g
        if a * b > 0:
            pair_plus[(abs_a, abs_b)] += 1
        else:
            pair_minus[(abs_a, abs_b)] += 1

    ans = 1
    ans *= (pow(2, zero_a, mod) + pow(2, zero_b, mod) - 1) % mod
    ans %= mod

    count_all = 0
    for item in list(pair_plus.items()):
        a, b = item[0]
        cnt = item[1]
        if (b,a) in pair_minus:
            ans *= (pow(2, cnt, mod) + pow(2, pair_minus[(b,a)]) - 1) % mod
            ans %= mod
            del pair_minus[(b, a)]
        else:
            count_all += cnt

    for val in list(pair_minus.values()):
        count_all += val

    ans = (ans * pow(2, count_all, mod)) % mod
    ans += zero_pair
    print(((ans - 1) % mod))

main()




# 約分して、互いに素な(1,3) (3,1)のようなペアを作りカウントする
# 正のグループと負のグループを別々に管理
# 正のグループの相手が負のグループに存在した場合、
# どちらかのグループから好きなだけ選ぶか、どちらも選ばないかしかない
# 誰ともペアにならなかったグループの個数を全て足してP個だとして、2^P通りを掛ける
# (0,0)については、その中から1つ選ぶか、選ばないかしかない

import sys
readline = sys.stdin.readline

N = int(readline())
import math

zeropair = 0
zeroa = 0
zerob = 0
from collections import defaultdict
pluspair = defaultdict(int)
minuspair = defaultdict(int)
for i in range(N):
  a,b = list(map(int,readline().split()))
  if a == 0 and b == 0:
    zeropair += 1
    continue
  if a == 0:
    zeroa += 1
    continue
  if b == 0:
    zerob += 1
    continue
  absa = abs(a)
  absb = abs(b)
  g = math.gcd(absa,absb)
  absa,absb = absa//g,absb//g
  if a * b > 0:
    pluspair[(absa,absb)] += 1
  else:
    minuspair[(absa,absb)] += 1

DIV = 1000000007
ans = 1
# zeroa,zerobから選ぶパターンは、どちらから好きなだけ選ぶか、どちらも選ばないか
ans *= (pow(2,zeroa,DIV) + pow(2,zerob,DIV) - 1) % DIV
ans %= DIV

# 誰とでもペアになれるものをカウント
allcnt = 0

# plusから選ぶパターンで、minusにある対応ペアを探す
for item in list(pluspair.items()):
  a,b = item[0]
  cnt = item[1]
  if (b,a) in minuspair:
    ans *= (pow(2,cnt,DIV) + pow(2,minuspair[(b,a)]) - 1) % DIV
    ans %= DIV
    del minuspair[(b,a)]
  else:
    allcnt += cnt

for val in list(minuspair.values()):
  allcnt += val

ans = (ans * pow(2,allcnt,DIV)) % DIV
# zeropairから選んだ場合、今までのパターンとは独立
ans += zeropair
print(((ans - 1) % DIV))


from math import gcd
from collections import defaultdict
mod = 10**9+7
n = int(input())
mp = defaultdict(lambda: [0, 0])
zerozero = 0
for i in range(n):
    a, b = map(int, input().split())
    if (a, b) == (0, 0):
        zerozero += 1
        continue
    g = gcd(a, b)
    a //= g
    b //= g
    rot_cnt = 0
    while not (a > 0 and b >= 0):
        a, b = -b, a
        rot_cnt += 1
    mp[(a,b)][rot_cnt%2] += 1
ans = 1
for s, t in mp.values():
    now = (pow(2, s, mod) + pow(2, t, mod) - 1) % mod
    ans = (ans * now) % mod
ans = (ans - 1 + zerozero) % mod 
print(ans)

from collections import Counter

def gcd(a, b):
    while b: a, b = b, a % b
    return abs(a)

MOD = 1000000007

# 2 WA
def main():
    N = int(input())
    d = {}
    d[(1,0)] = (0,0)
    z = 0
    for i in range(N):
      a,b = (int(x) for x in input().split())
      g = gcd(a,b)
      if g != 0:
        a = a//g
        b = b//g
        if a*b<0: a = -abs(a)
        elif a*b>0: a = abs(a)
      b = abs(b)
      
      if a*b==0:
        if a==b==0: z+=1
        elif b==0: d[(1,0)] = (d[(1,0)][0]+1,d[(1,0)][1])
        elif a==0: d[(1,0)] = (d[(1,0)][0],  d[(1,0)][1]+1)
      else:
        if (a,b) in d: d[(a,b)] = (d[(a,b)][0]+1,d[(a,b)][1])
        elif (b, -a) in d: d[(b,-a)] = (d[(b,-a)][0], d[(b,-a)][1]+1)
        elif (-b, a) in d: d[(-b,a)] = (d[(-b,a)][0], d[(-b,a)][1]+1)
        else: d[(a,b)] = (1,0)
    
    ans = 1
    for i, j in list(d.values()):
      ans *= (pow(2,i,MOD) + pow(2,j,MOD) - 1)
      ans %= MOD

    print(((ans-1+z)%MOD))

def __starting_point():
    main()

__starting_point()

from collections import defaultdict
from math import gcd
N = int(input())
mod = 10**9 + 7
D = defaultdict(int)
corner = 0
D[(0,1)]=0
D[(1,0)]=0
for i in range(N):
    x, y = map(int, input().split())
    if x*y != 0:
        x, y = x//gcd(x, y), y//gcd(x, y)
        if y > 0:
            D[(x, y)] += 1
        elif y < 0:
            D[(-x, -y)] += 1
    else:
        if x == 0 and y == 0:
            corner += 1
            continue
        else:
            if x == 0:
                D[(0, 1)] += 1
            elif y == 0:
                D[(1, 0)] += 1
ans = corner
# 以下、(0,0) を入れない時。(X,Y) のYは全て0以上で統一する（何も入れないも一応カウント）
c = 1
sub=[]
for x, y in D.keys():
    if x<0 and y>0:
        if not (y,-x) in D.keys():
            sub.append((y,-x))
for some in sub:
    D[some]=0

K=list(D.keys())
for x, y in K:
    if x > 0 and y > 0:
        a = D[(x, y)]
        b = D[(-y, x)]
        c *= (pow(2, a, mod)+pow(2, b, mod)-1)
        c %= mod
    elif y == 0:
        a = D[(1, 0)]
        b = D[(0, 1)]
        c *= (pow(2, a, mod)+pow(2, b, mod)-1)
        c %= mod
ans += c-1

print(ans % mod)

from math import gcd

n=int(input())
mod=10**9+7

d=dict()
zeros=0
for _ in range(n):
  a,b=list(map(int,input().split()))
  if not any((a,b)):
    zeros+=1
    continue
  if all((a,b)):
    g=gcd(a,b)*(a//abs(a))
  elif a:
    g = a
  else:
    g = b
  p=a//g,b//g
  d[p]=d.get(p,0)+1

ans=1
done=set()
for (a,b),v in list(d.items()):
  if (-b,a) in done or (b,-a) in done:
    continue
  done.add((a,b))
  w=d.get((-b,a),0)+d.get((b,-a),0)
  ans *=(pow(2,v)+pow(2,w)-1)
  ans %= mod
print(((ans+zeros-1)%mod))



from collections import defaultdict
MOD = 10**9+7
from math import gcd


n = int(input())
ans = 1
C = defaultdict(int)
z = 0
r = 0
for i in range(n):
    a, b = map(int, input().split())
    if a == 0 and b == 0:
        r += 1
    elif b == 0:
        z += 1
    elif a == 0:
        C[0] += 1
    else:
        g = gcd(abs(a), abs(b))
        a //= g
        b //= g
        if a < 0:
            a, b = -a, -b
        C[(a, b)] += 1
D = tuple(C.items())
used = {0}
for c, v in D:
    if c in used:
        continue
    a, b = c
    if b > 0:
        d, e = b, -a
    else:
        d, e = -b, a
    ans *= pow(2, v, MOD)+pow(2, C[(d, e)], MOD)-1
    ans %= MOD
    used.add((d, e))
ans *= pow(2, C[0], MOD)+pow(2, z, MOD)-1
ans += r
ans -= 1
ans %= MOD
print(ans)

from collections import deque
from math import gcd
import sys

def input():
    return sys.stdin.readline().rstrip()

MOD = 10**9 + 7
n = int(input())
cnt = {}
zero_cnt = 0
ans = 1

for _ in range(n):
    a, b = list(map(int, input().split()))
    if (a, b) == (0, 0):
        zero_cnt += 1
        continue
    g = gcd(abs(a), abs(b))
#    if a == 0 or b == 0: g = max(abs(a), abs(b))
    a //= g
    b //= g

    rotate = 0
    while not (a > 0 and b >= 0):
        a, b = -b, a
        rotate += 1
    if (a, b) not in cnt:
        cnt[(a, b)] = [0, 0]

    cnt[(a, b)][rotate%2] += 1

for key in cnt:
    A, B = cnt[key]
    ans *= 1 + pow(2, A, MOD) - 1 + pow(2, B, MOD) - 1
    ans %= MOD

ans += zero_cnt
ans -= 1 #for empty set
print((ans % MOD))


# E - Bullet

from collections import Counter
from math import gcd

n = int(input())
counter = Counter()  # 各ベクトルの個数
for i in range(n):
    a, b = list(map(int, input().split()))
    if b < 0:
        a, b = -a, -b  # 180度回転して第1〜2象限に
    elif b == 0:
        a = abs(a)
    if not a == b == 0:
        # 既約化
        g = gcd(a, b)
        a //= g
        b //= g
    counter[(a, b)] += 1

modulus = 1000000007

vs = set(counter)
# 第2象限のベクトルと直交するベクトルを追加
vs.update((b, -a) for a, b in counter if a <= 0)
# 第1象限のベクトルのみ抽出
vs = [(a, b) for a, b in vs if a > 0]

ncomb = 1  # イワシの選び方の個数
for a, b in vs:
    # 互いに仲が悪いイワシ群
    n1 = counter[(a, b)]
    n2 = counter[(-b, a)]
    # それぞれの群から好きな数だけイワシを選ぶ (0匹選ぶことも含む)
    m = pow(2, n1, modulus) + pow(2, n2, modulus) - 1
    ncomb = ncomb * m % modulus

ncomb -= 1  # 1匹も選ばない場合を除く

# (0, 0)のイワシを1匹だけ選ぶ
ncomb += counter[(0, 0)]

print((ncomb % modulus))


from math import gcd
from collections import defaultdict

N = int(input())
d = {}
MOD = 10**9+7
zall = 0

for _ in range(N):
    A, B = list(map(int, input().split()))

    if A==0 and B==0:
        zall += 1
    else:
        if A and B:
            if A<0 and B<0:
                A *= -1
                B *= -1
            elif A<0 and B>0:
                A *= -1
                B *= -1

            g = gcd(A, B)
            A //= g
            B //= g
        elif A==0:
            B = 1
        elif B==0:
            A = 1
        
        if (A, B) in d:
            d[(A, B)] += 1
        else:
            d[(A, B)] = 1

ans = 1
used = defaultdict(int)

for (i, j), v in list(d.items()):
    if used[(i, j)]:continue
    used[(i, j)] = 1
    buf = 0

    if j>0:
        if (j, -i) in d:
            used[(j, -i)] = 1
            buf = d[(j, -i)]
        else:
            buf = 0
    else:
        if (-j, i) in d:
            used[(-j, i)] = 1
            buf = d[(-j, i)]
        else:
            buf = 0

    ans *= (pow(2, buf, MOD)+pow(2, v, MOD)-1)
    ans %= MOD

print(((ans+zall-1)%MOD))


from math import gcd
MOD = 1000_000_007

N = int(input())

Fish = {}
zeros = 0

for i in range(N):
  A, B = list(map(int,input().split())) 
  if A == 0 and B == 0:
    zeros += 1
    continue
  
  G = gcd(abs(A), abs(B))
  A, B = A // G, B // G
  if A < 0:
    A *= -1
    B *= -1
  elif A == 0:
    B = 1
    
  if (A, B) not in Fish:
    Fish[(A, B)] = 1
  else:
    Fish[(A, B)] += 1

#print(Fish)
done_set = set()

ans = 1
for (a, b) in list(Fish.keys()):
  #print(a,b)
  if b > 0:
    c = b
    d = -a
  elif b == 0:
    c = 0
    d = 1
  else: 
    c, d = -b, a
  
  #print(done_set)
  #print((a,b), (c,d), done_set)
  if (a, b) in done_set or (c, d) in done_set: 
    continue
  #print((a,b), Fish[(a,b)])
  #print((c,d), Fish[(c,d)])
  if (c, d) not in list(Fish.keys()):
    
    ans *= pow(2, Fish[(a,b)], MOD)
  else:
    ans *= (1 + (pow(2, Fish[(a,b)], MOD)-1) + (pow(2, Fish[(c,d)], MOD)-1))  
    done_set.add((c,d))
  ans %= MOD
  
  #print(done_set, ans)
  done_set.add((a,b))
  
ans += zeros
ans -= 1
ans %= MOD
#print(zeros)
print(ans)

  


from collections import Counter
import math
MOD=10**9+7
N=int(input())
li=[]
zcnt=0
az,bz=0,0
for i in range(N):
    A,B=map(int,input().split())
    if A==0 and B==0:
        zcnt+=1
        continue
    if A!=0 and B==0:
        bz+=1
        continue
    elif A==0 and B!=0:
        az+=1
        continue
    g=math.gcd(A,B)
    if A<0 and B<0:
        li.append((-(A//g),-(B//g)))
    elif A<0 and B>0:
        li.append((-(A//g),-(B//g)))
    else:
        li.append((A//g,B//g))
c=Counter(li)
dic={}
ans=(pow(2,az,MOD)+pow(2,bz,MOD)-1+MOD)%MOD
for a,b in c.keys():
    if (a,b) in dic:
        continue
    l,r=(-b,a),(b,-a)
    s=c.get(l,0)+c.get(r,0)
    dic[l],dic[r]=1,1
    res=(pow(2,c[(a,b)],MOD)+pow(2,s,MOD)-1+MOD)%MOD
    ans=(ans*res)%MOD
print((ans-1+zcnt)%MOD)

import sys
sys.setrecursionlimit(1000000000)
import math
from math import gcd
def lcm(a, b): return a * b // gcd(a, b)
from itertools import count, permutations, chain
from functools import lru_cache
from collections import deque, defaultdict
from pprint import pprint
ii = lambda: int(input())
mis = lambda: list(map(int, input().split()))
lmis = lambda: list(mis())
INF = float('inf')
N1097 = 10**9 + 7

def meg(f, ok, ng):
    while abs(ok-ng)>1:
        mid = (ok+ng)//2
        if f(mid):
            ok=mid
        else:
            ng=mid
    return ok

def get_inv(n, modp):
    return pow(n, modp-2, modp)

def factorials_list(n, modp):    # 10**6
    fs = [1]
    for i in range(1, n+1):
        fs.append(fs[-1] * i % modp)
    return fs

def invs_list(n, fs, modp):     # 10**6
    invs = [get_inv(fs[-1], modp)]
    for i in range(n, 1-1, -1):
        invs.append(invs[-1] * i % modp)
    invs.reverse()
    return invs

def comb(n, k, modp):
    num = 1
    for i in range(n, n-k, -1):
        num = num * i % modp
    den = 1
    for i in range(2, k+1):
        den = den * i % modp
    return num * get_inv(den, modp) % modp

def comb_from_list(n, k, modp, fs, invs):   
    return fs[n] * invs[n-k] * invs[k] % modp

#

class UnionFindEx:
    def __init__(self, size):
        #正なら根の番号、負ならグループサイズ
        self.roots = [-1] * size
    def getRootID(self, i):
        r = self.roots[i]
        if r < 0:   #負なら根
            return i
        else:
            r = self.getRootID(r)
            self.roots[i] = r
            return r
    def getGroupSize(self, i):
        return -self.roots[self.getRootID(i)]
    def connect(self, i, j):
        r1, r2 = self.getRootID(i), self.getRootID(j)
        if r1 == r2:
            return False
        if self.getGroupSize(r1) < self.getGroupSize(r2):
            r1, r2 = r2, r1
        self.roots[r1] += self.roots[r2]    #サイズ更新
        self.roots[r2] = r1
        return True

Yes = 'Yes'
No = 'No'


def main():
    from fractions import Fraction
    N=ii()
    zero = 0
    d = defaultdict(lambda : [0, 0])
    for _ in range(N):
        x, y = mis()
        if x == y == 0:
            zero += 1
            continue
        if y < 0 or (y==0 and x < 0):
            x, y = -x, -y
        g = gcd(x, y)
        x //= g
        y //= g
        if x<=0:
            rot = True
            c = (y, -x)
        else:
            rot = False
            c = (x, y)
        d[c][rot] += 1
    #
    N -= zero
    ans = 1
    for (q1, q2) in list(d.values()):
        ans *= (pow(2, q1, N1097) - 1) + (pow(2, q2, N1097) - 1) + 1
        ans %= N1097
    ans -= 1
    ans %= N1097
    print((ans + zero))






main()



from operator import itemgetter
from math import gcd
from collections import Counter

N = int(input())
mod = int(1e9+7)

zero = 0
P = {}
for i in range(N):
  a,b = list(map(int, input().split()))
  if a == 0 and b == 0:
    zero += 1
    continue
  g = gcd(a,b)
  a,b = a//g, b//g
  if b < 0:
    a,b = -a,-b
  if b == 0 and a < 0:
    a,b = -a,b  
  #rot90
  rot90 = a<=0
  if rot90:
    a,b = b,-a
  #add
  if not (abs(a),b) in P:
    P[(a,b)] = [0,0]
  if not rot90 :
    P[(a,b)][0] += 1
  else:
    P[(a,b)][1] += 1
    
ans = 1
for k,v in P.items():
  #print(k,v)
  s,t = v
  wk = 1 + pow(2,s,mod) - 1 + pow(2,t,mod) - 1
  ans *= wk
  ans %= mod
  
ans += zero

print((ans - 1) % mod)

from math import gcd 
n=int(input())
mod = 10**9+7
count = {}

num=0
for _ in range(n):
    a,b = map(int,input().split())
    if a==0 and b==0:
        num+=1
        continue
    if a*b != 0:
        g=gcd(a,b)*(b//abs(b))
    elif a != 0:
        g=a
    else:
        g=b
        
    l=a//g,b//g
    count[l]=count.get(l,0)+1
        
mem=set()
ans=1
for (x,y),z in count.items():
    if x*y==0:
        k=(y,x)
    else:
        k=(-1*x//abs(x)*y,abs(x))
    if k in mem:
        continue
    mem.add((x,y))
    ans*=(pow(2,z)+pow(2,count.get(k,0))-1)
    ans%=mod

print((ans+num-1)%mod)

N=int(input())
from collections import defaultdict
dic=defaultdict(int)
import math
mod=1000000007
for _ in range(N):
    A,B=list(map(int,input().split()))
    if A<0:
        A,B=-A,-B
    if A==0:
        if B==0:
            dic[(0,0)]+=1
        else:
            dic[(0,-1)]+=1
    elif B==0:
        dic[(1,0)]+=1
    else:
        gcd=math.gcd(A,B)
        A,B=A//gcd,B//gcd
        dic[(A,B)]+=1

ans=1
N-=dic[(0,0)]
for k,v in list(dic.items()):
    if k==(0,0) or k==(0,1):
        continue
    a,b=k
    if not (b,-a) in dic:
        continue
    v_dash=dic[(b,-a)]
    ans*=((pow(2,v,mod)-1)+(pow(2,v_dash,mod)-1)+1)
    ans%=mod
    N-=v+v_dash
ans*=pow(2,N,mod)
ans+=dic[(0,0)]-1
ans%=mod
print(ans)


import math
def main():
    N = int(input())
    d = {}
    za = zb = zab = r = 0
    mod = 10**9 + 7
    for i in range(N):
        a, b = list(map(int, input().split()))
        if a== 0 and b == 0:
            zab += 1
        elif b == 0:
            zb += 1
        elif a == 0:
            za += 1
        else:
            if a < 0:
                a, b = -a, -b
            x = math.gcd(abs(a), abs(b))
            d[(a//x, b//x)] = d.get((a//x, b//x), 0) + 1
    used = set()
    l = []
    for x in d:
        if x in used:
            continue
        a, b = x[0], x[1]
        used.add(x)
        if a * b > 0:
            t = (abs(b), -abs(a))
        else:
            t = (abs(b), abs(a))
        used.add(t)
        l.append((d[x], d.get(t, 0)))
    r = pow(2, za) + pow(2, zb) - 1
    for i in l:
        r *= (pow(2, i[0]) + pow(2, i[1]) - 1)
        r %= mod
    return (r - 1 + zab) % mod
print((main()))


from collections import defaultdict
from math import gcd
N = int(input())
MOD = 10**9 + 7
L = defaultdict(lambda: [0,0])
zero = 0
for _ in range(N):
    A, B = list(map(int, input().split()))
    if A==0: d=B
    elif B==0: d=A
    else: d=gcd(A,B)
    if d != 0:
        A, B = A//d, B//d
        if A<0: A, B = -A, -B
        if B>0: L[(A,B)][0] += 1
        else: L[(-B,A)][1] += 1
    else: zero += 1

res = 1

for x,y in list(L.values()):
    res *= pow(2,x,MOD) + pow(2,y,MOD) -1
    res %= MOD
print(((res+zero-1)%MOD))



from math import gcd
 
n=int(input())
mod = 10**9+7
 
d = dict()
zeros=0
for _ in range(n):
  a,b=map(int,input().split())
  if not any((a,b)):
    zeros+=1
    continue
  if all((a,b)):
    g = gcd(a,b)*(a//abs(a))
  elif a:
    g = a
  else:
    g = b
  
  p = a//g,b//g
  d[p] = d.get(p,0)+1
 
ans = 1
done = set()
for (a,b),v in d.items():
  if (-b,a) in done or (b,-a) in done:
    continue
  done.add((a,b))
  w=d.get((-b,a),0)+d.get((b,-a),0)
  ans *= (pow(2,v,mod)+pow(2,w,mod)-1)
  ans %= mod
print((ans+zeros-1+mod)%mod)

from collections import defaultdict
import math

N = int(input())
m = defaultdict(lambda : 0)
BIG_NUMBER = 1000000007
bad_iwashi_count = 0

for _ in range(N):
    A,B = map(int,input().split())
    #0の場合
    if A == 0 and B == 0:
        bad_iwashi_count += 1
        continue
    if A == 0:
        m[(-1,0,1)]+=1
        continue
    if B == 0:
        m[(1,1,0)]+=1
        continue
    #0以外
    gcd_ = math.gcd(A,B)
    A = A//gcd_
    B = B//gcd_
    if A < 0 and B > 0: m[(-1,-A,B)]+=1
    elif B < 0 and A > 0: m[(-1,A,-B)]+=1
    elif A < 0 and B < 0 :m[(1,-A,-B)]+=1
    elif A > 0 and B > 0 :m[(1,A,B)]+=1

total = 1
for key in list(dict(m).keys()):
    total *= pow(2,m[key],BIG_NUMBER) + pow(2,m[-key[0],key[2],key[1]],BIG_NUMBER) -1
    total %= BIG_NUMBER
    m.pop(key)
    m.pop((-key[0],key[2],key[1]))
print((total+bad_iwashi_count-1)%BIG_NUMBER)

'''
3
1 2
-1 1
2 -1
'''

import math

N = int(input())
AB = [list(map(int, input().split())) for _ in range(N)]

MOD = 1000000007

dic1 = {}
a_zero = 0
b_zero = 0
both_zero = 0

for a, b in AB:
    if a == 0 and b != 0:
        a_zero += 1
    elif a != 0 and b == 0:
        b_zero += 1
    elif a == 0 and b == 0:
        both_zero += 1
    else:
        g = math.gcd(a, b)
        a //= g
        b //= g

        if b < 0:
            a, b = -a, -b

        if (a, b) in dic1:
            dic1[(a, b)] += 1
        else:
            dic1[(a, b)] = 1

pair = []
used = set()

for key, val in list(dic1.items()):
    if key in used:
        continue

    a, b = key
    used.add((a, b))
    cnt = 0

    if a < 0:
        c, d = -b, -a
    else:
        c, d = b, a

    if (-c, d) in dic1:
        cnt += dic1.get((-c, d), 0)
        used.add((-c, d))

    pair.append((val, cnt))


all_cnt = 1
for cnt1, cnt2 in pair:
    all_cnt *= pow(2, cnt1, MOD) + pow(2, cnt2, MOD) - 1
    all_cnt %= MOD

all_cnt *= pow(2, a_zero, MOD) + pow(2, b_zero, MOD) - 1
all_cnt %= MOD

all_cnt += both_zero
all_cnt %= MOD

print(((all_cnt - 1) % MOD))


from math import gcd

N = int(input())
AB = [list(map(int, input().split())) for _ in range(N)]

m = 1000000007

t = []
d = {}
d[0] = {}
d[0][0] = 0
for a, b in AB:
    i = gcd(a, b)
    if i != 0:
        a //= i
        b //= i
    t.append((a, b))
    d.setdefault(a, {})
    d[a].setdefault(b, 0)
    d[a][b] += 1

used = set()
result = 1
for a, b in t:
    if (a, b) in used:
        continue
    used.add((a, b))
    if a == 0 and b == 0:
        continue
    i = d[a][b]
    j, k, l = 0, 0, 0
    if -a in d and -b in d[-a]:
        j = d[-a][-b]
        used.add((-a, -b))
    if -b in d and a in d[-b]:
        k = d[-b][a]
        used.add((-b, a))
    if b in d and -a in d[b]:
        l = d[b][-a]
        used.add((b, -a))
    result *= pow(2, i + j, m) + pow(2, k + l, m) - 1
    result %= m
result += d[0][0] - 1
result %= m
print(result)


# 約分して、互いに素な(1,3) (3,1)のようなペアを作りカウントする
# 正のグループと負のグループを別々に管理
# 正のグループの相手が負のグループに存在した場合、
# どちらかのグループから好きなだけ選ぶか、どちらも選ばないかしかない
# 誰ともペアにならなかったグループの個数を全て足してP個だとして、2^P通りを掛ける
# (0,0)については、その中から1つ選ぶか、選ばないかしかない

import sys
readline = sys.stdin.readline

N = int(readline())
import math

zeropair = 0
zeroa = 0
zerob = 0
from collections import defaultdict
pluspair = defaultdict(int)
minuspair = defaultdict(int)
for i in range(N):
  a,b = map(int,readline().split())
  if a == 0 and b == 0:
    zeropair += 1
    continue
  if a == 0:
    zeroa += 1
    continue
  if b == 0:
    zerob += 1
    continue
  absa = abs(a)
  absb = abs(b)
  g = math.gcd(absa,absb)
  absa,absb = absa//g,absb//g
  if a * b > 0:
    pluspair[(absa,absb)] += 1
  else:
    minuspair[(absa,absb)] += 1

DIV = 1000000007
ans = 1
# zeroa,zerobから選ぶパターンは、どちらから好きなだけ選ぶか、どちらも選ばないか
ans *= (pow(2,zeroa,DIV) + pow(2,zerob,DIV) - 1) % DIV
ans %= DIV

# 誰とでもペアになれるものをカウント
allcnt = 0

# plusから選ぶパターンで、minusにある対応ペアを探す
for item in pluspair.items():
  a,b = item[0]
  cnt = item[1]
  if (b,a) in minuspair:
    ans *= (pow(2,cnt,DIV) + pow(2,minuspair[(b,a)]) - 1) % DIV
    ans %= DIV
    del minuspair[(b,a)]
  else:
    allcnt += cnt

for val in minuspair.values():
  allcnt += val

ans = (ans * pow(2,allcnt,DIV)) % DIV
# zeropairから選んだ場合、今までのパターンとは独立
ans += zeropair
print((ans - 1) % DIV)

import sys, bisect, collections, math
input = lambda: sys.stdin.readline().rstrip() 
sys.setrecursionlimit(10**7)
INF = 10**20
MOD = 1000000007
def I(): return int(input())
def F(): return float(input())
def S(): return input()
def LI(): return [int(x) for x in input().split()]
def LI_(): return [int(x)-1 for x in input().split()]
def LF(): return [float(x) for x in input().split()]
def LS(): return input().split()

def resolve():
    N = I()
    AB = [LI() for _ in range(N)]

    # A, Bを標準化 互いに疎でAは正
    def normalize(AB):
        A = AB[0]
        B = AB[1]
        if A==B==0:
            return (0, 0)
        elif A==0:
            return(0, 1)
        elif B==0:
            return(1, 0)
        else:
            gcd = math.gcd(A, B)
            A //= gcd
            B //= gcd
            if A<0:
                A, B = -A, -B
            return (A, B)
    
    def orthogonal(AB):
        A = AB[0]
        B = AB[1]
        if B>0:
            return (B, -A)
        else:
            return(-B, A)

    AB_n = [normalize(i) for i in AB]
    counter = collections.Counter(AB_n)

    # 場合の数を求める
    used = set()
    ans = 1
    # (0, 0)以外について
    for A, B in AB_n:
        if not (A, B) in used:
            if (A, B)!=(0, 0):
                ans *= pow(2, counter[(A, B)], MOD) + pow(2, counter[orthogonal((A, B))], MOD) - 1
                ans %= MOD
                used.add((A, B))
                used.add(orthogonal((A, B)))
    ans -= 1
    # (0, 0)について
    ans += counter[(0, 0)]
    ans %= MOD

    print(ans)

def __starting_point():
    resolve()

__starting_point()

from math import gcd

n = int(input())
MOD = 10**9 + 7
cnt = {}
zero_cnt = 0
ans = 1

for i in range(n):
    a, b = list(map(int, input().split()))
    if (a,b) == (0,0):
        zero_cnt += 1
        continue
    g = gcd(abs(a), abs(b))
    a //= g
    b //= g
    rotate = 0
    while not (a >= 0 and b > 0):
        a,b = -b,a
        rotate += 1
    if (a,b) not in cnt:
        cnt[(a,b)] = [0,0]
    cnt[(a,b)][rotate % 2] += 1
 
for key in cnt:
    A, B = cnt[key]
    ans *= 1 + pow(2, A, MOD) - 1 + pow(2, B, MOD) - 1
    ans %= MOD
 
ans += zero_cnt
ans -= 1
print((ans % MOD))




import math
N=int(input())
MOD=10**9+7
fish={}
ans=1
a=0
b=0
w=0
for i in range(N):
    A,B=map(int,input().split())
    if A==0 and B==0:
        w+=1
    elif A==0:
        a+=1
    elif B==0:
        b+=1
    else:
        c=math.gcd(A,B)
        A=A//c
        B=B//c
        if B<0:
            A,B=-A,-B
        k=(A,B)
        if not k in fish:
            fish[k]=0
        fish[k]+=1
group=set()
for (p,q),v in fish.items():
    invp,invq=-q,p
    if invq<0:
        invp,invq=-invp,-invq
    if not (invp,invq) in group:
        group.add((p,q))
for p,q in group:
    invp,invq=-q,p
    if invq<0:
        invp,invq=-invp,-invq
    t=2**fish[p,q]
    if (invp,invq) in fish:
        t+=2**fish[invp,invq]-1
    ans=(ans*t)%MOD
ans*=2**a+2**b-1
ans=ans+w-1
print(ans%MOD)

#!/usr/bin/env python3
import math

n = int(input())

mod = 10**9+7

data = {}
zero_zero = 0

for i in range(n):
    a, b = list(map(int, input().split()))
    # # print(a, b)
    if a == 0 and b == 0:
        zero_zero += 1
        continue
    gcd = math.gcd(a, b)
    a, b = a//gcd, b//gcd
    if a < 0:
        a, b = -a, -b

    if a == 0:  # (0, 1)
        a, b = 0, 1

    elif b == 0:  # (1, 0)
        a, b = 1, 0

    # print(a, b)
    # print()

    if b <= 0:  # (+, -) or (1, 0)
        if (-b, a) in data:
            data[(-b, a)][1] += 1
        else:
            data[(-b, a)] = [0, 1]
    elif b > 0:  # (+, +) or (1, 0)
        if (a, b) in data:
            data[(a, b)][0] += 1
        else:
            data[(a, b)] = [1, 0]

# print(data)
# print(zero_zero)

power_2 = [1]
for i in range(1, 2*10**5+100):
    power_2.append(power_2[i-1]*2 % mod)

ans = 1
# print(ans)
# print()
for (a, b), (l, m) in list(data.items()):
    ans *= (power_2[l]+power_2[m]-1) % mod
    # print(power_2[l]+power_2[m]-1)
    # print(ans)
    # print()

ans = ans - 1  # removed not selected
ans += zero_zero
print((ans % mod))
# count_pp = 0
# count_pm = 0
# ans = 0
# while(1):
#     pp_tmp = plus_plus[count_pp]
#     pm_tmp = plus_minus[count_pm]

#     print("pp_tmp", pp_tmp)
#     print("pm_tmp", pm_tmp)

#     if pp_tmp[0]*pm_tmp[0] + pp_tmp[1]*pm_tmp[1] == 0:
#         pp_mag, pm_mag = 1, 1  # magnitude
#         while(1):
#             if count_pp < len(plus_plus)-1:
#                 if plus_plus[count_pp] == plus_plus[count_pp+1]:
#                     pp_mag += 1
#                     count_pp += 1
#                 else:
#                     break
#             else:
#                 break
#         while(1):
#             if count_pm < len(plus_minus)-1:
#                 if plus_minus[count_pm] == plus_minus[count_pm+1]:
#                     pm_mag += 1
#                     count_pm += 1
#                 else:
#                     break
#             else:
#                 break
#         ans += pp_mag*pm_mag

#     elif pp_tmp[2]*pm_tmp[2] > -1:
#         count_pp += 1

#     elif pp_tmp[2]*pm_tmp[2] < -1:
#         count_pm += 1

#     if count_pp == len(plus_plus)-1:
#         break
#     if count_pm == len(plus_minus)-1:
#         break
#     print(1)

# ans += zero_zero
# n = n - zero_zero
# count = ((n % mod) * ((n-1) % mod))//2
# count -= (negative) % mod

# print(count % mod)


from collections import defaultdict
from math import gcd
C = defaultdict(lambda: 0)
for i in range(int(input())):
    x, y = list(map(int, input().split()))
    g = max(gcd(x, y), 1)
    x, y = x // g, y // g
    if y < 0 or (x == -1 and y == 0):
        x, y = -x, -y
    C[(x, y)] += 1
S = set()
for x, y in C:
    if x > 0 and y >= 0:
        S.add((x, y))
    if x <= 0 and y > 0:
        S.add((y, -x))
ans = 1
p = 10**9 + 7
for x, y in S:
    ans *= pow(2, C[(x, y)], p) + pow(2, C[(-y, x)], p) - 1
    ans %= p
print(((ans + C[(0, 0)] - 1) % p))


from collections import defaultdict
import math
import sys
input = sys.stdin.readline


def select_num(a, b, mod=1000000007):
    sum = pow(2, a, mod) + pow(2, b, mod) - 1
    return sum % mod


def dict_count(d, a, b):
    this = a / b
    pair = b / a
    if not d.get(this, False):
        d[this] = {"num": 0, "pair": pair}
    d[this]["num"] += 1


def main():
    MOD = 1000000007
    n = int(input())

    d = defaultdict(lambda: [0] * 2)
    zero = 0
    for i in range(n):
        a, b = map(int, input().split())
        if a == 0 or b == 0:
            if a == b == 0:
                n -= 1
                zero += 1
            elif a == 0:
                d[0][True] += 1
            elif b == 0:
                d[0][False] += 1

        else:
            gcd = math.gcd(a, b)
            a //= gcd
            b //= gcd

            if b < 0:
                a, b = -a, -b

            rot = False
            if a < 0:
                b, a = -a, b
                rot = True
            d[(a, b)][rot] += 1

    ans = 1
    for k, v in d.items():
        ans *= select_num(v[0], v[1], MOD)
        ans %= MOD

    ans += zero - 1
    ans %= MOD
    print(ans)


def __starting_point():
    main()
__starting_point()

from math import gcd
from collections import defaultdict
mod = 10**9+7
_, *S = open(0)
mp = defaultdict(lambda: [0, 0])
O = 0
for s in S:
    a, b = list(map(int, s.split()))
    if a == b == 0:
        O += 1
    else:
        g = gcd(a, b)
        a //= g
        b //= g
        if a < 0 or a == 0 < b:
            a, b = -a, -b
        f = 0
        if b < 0:
            a, b, f = -b, a, 1
        mp[(a, b)][f] += 1
ans = 1
for k in mp:
    x, y = mp[k]
    ans = ans*(pow(2, x, mod)+pow(2, y, mod)-1) % mod
print(((ans+O-1) % mod))


import sys
sys.setrecursionlimit(10 ** 7)
input = sys.stdin.readline
p = 10**9+7
from math import gcd
from collections import Counter
from collections import defaultdict
used = defaultdict(list)

n = int(input())

ctr = Counter()
az = bz = zz = 0
for i in range(n):
    a, b = list(map(int, input().split()))
    if a==b==0:
        zz+=1
    elif a==0:
        az+=1
    elif b==0:
        bz+=1
    else:
        g = gcd(a,b)
        a,b = a//g, b//g
        if b < 0:
            a*=-1
            b*=-1
        ctr[(a,b)]+=1
        used[(a,b)]=False

ans = 1

# 仲の悪いグループ対ごとに処理する
for (a1,b1),v1 in list(ctr.items()):
    if used[(a1,b1)]:
        continue
    a2,b2=-b1,a1
    if b2 < 0:
        b2*=-1
        a2*=-1
    v2 = ctr[(a2,b2)]

    r = (pow(2,v1,p)+pow(2,v2,p)-1)%p
    ans*=r
    ans%=p
    used[(a1,b1)]=True
    used[(a2,b2)]=True

# 片方が0のクループ対
r = (pow(2,az,p)+pow(2,bz,p)-1)%p
ans*=r
ans%=p

ans+=zz # 0匹のケースは禁止されている
ans-=1 # 0匹のケースは禁止されている
ans%=p
print(ans)



from math import gcd
mod = 1000000007
n = int(input())
zero = 0
bad = {}
for i in range(n):
    x, y = list(map(int, input().split()))
    if x == 0 and y == 0:
        zero += 1
        continue
    g = gcd(x, y)
    x //= g
    y //= g
    if y < 0: x, y = -x, -y
    if y==0 and x<0: x, y = -x, -y
    is_rotate90 = (x <= 0)
    if is_rotate90:
        x, y = y, x
        y = -y
    if not (x, y) in bad:
        bad[x, y] = [0, 0]
    if is_rotate90:
        bad[x, y][0] += 1
    else:
        bad[x, y][1] += 1

# print(bad)

cnt = 1
for x, y in bad:
    c1, c2 = bad[x, y]
    c3 = 1
    c3 += pow(2, c1, mod) - 1
    c3 += pow(2, c2, mod) - 1
    cnt = cnt * c3 % mod

ans = (cnt + zero - 1) % mod

# print('cnt',cnt)
# print('zero',zero)
# print('ans',ans)
print(((ans+mod) % mod))



from fractions import Fraction
from collections import defaultdict
def resolve():
    # A1*A2 + B1*B2 = 0 式変形 A1/B1 = -(B2/A2)
    # a, b の0がある条件を考える
    
    MOD = 1000000007
    N = int(input())
    zeroes = 0
    hash1 = defaultdict(int) #
    hash2 = defaultdict(str) #中の悪い相手を記入
    for _ in range(N):
        a, b = map(int, input().split())
        if a==0 and b==0:
            zeroes += 1
        elif b == 0:
            hash1["1/0"] += 1
            hash2["1/0"] = "0/1"
        elif a == 0:
            hash1["0/1"] += 1
            hash2["0/1"] = "1/0"
        else: # a, bが0以外
            rat1 = Fraction(a, b)
            rat2 = Fraction(-b, a)
            hash1[str(rat1)] += 1
            hash2[str(rat1)] = str(rat2) # 相手を入れる

    confirmed = set()
    ans = 1
    for k, v in hash1.items():
        if k in confirmed: # 確認済みを数えないようにする
            continue
        bad = hash1.get(hash2[k], 0) # 中の悪い相手, キーがなかったら0を出力
        cnt1 = pow(2, v, MOD) - 1
        cnt2 = pow(2, bad, MOD) - 1
        ans = (ans * (cnt1 + cnt2 + 1)) % MOD
        # 確認済みにする
        confirmed.add(k)
        confirmed.add(hash2[k])
        # ※ ループ中に値を変更したらエラー
        # hash1[k] = -1

    ans = (ans + zeroes + MOD -1) % MOD
    print(ans)

def __starting_point():
    resolve()
__starting_point()

from math import gcd
from collections import Counter

mod = 10 ** 9 + 7

N, *AB = map(int, open(0).read().split())

def std(a, b):
    if a == 0:
        return (0, int(b != 0))

    g = gcd(a, b)
    a, b = a // g, b // g
    return (a, b) if a > 0 else (-a, -b)

C = Counter()
for a, b in zip(*[iter(AB)] * 2):
    C[std(a, b)] += 1

ans = 1
cnt = 0
for (a, b), v in C.items():
    if b > 0:
        if (b, -a) in C:
            ans *= -1 + pow(2, v, mod) + pow(2, C[(b, -a)], mod)
            ans %= mod
        else:
            cnt += v
    elif (-b, a) not in C:
        cnt += v

ans *= pow(2, cnt, mod)
ans += C[(0, 0)] - 1

print(ans % mod)

from math import gcd
from collections import defaultdict as d
n=int(input())
m=10**9+7
s=d(lambda:[0,0])
p=-1
for i in range(n):
    a,b=map(int,input().split())
    if a==b==0:p+=1
    else:
        g=gcd(a,b)
        a=a//g
        b=b//g
        if a<0 or a==0<b:a,b=-a,-b
        if b<0:s[(-b,a)][1]+=1
        else:s[(a,b)][0]+=1
q=1
for i in s:
    k,l=s[i]
    q=q*(pow(2,k,m)+pow(2,l,m)-1)%m
print((q+p)%m)

from math import gcd
mod = 1000000007
n = int(input())
zero = 0
bad = {} # 仲が悪い者同士をグループ化
for i in range(n):
    x, y = list(map(int, input().split()))
    if x == 0 and y == 0:
        zero += 1 # (A,B) = (0,0) の計数をとる
        continue
    g = gcd(x, y)
    x //= g # ベクトルを整数の範囲で最小化し、
    y //= g # 傾きを既約分数 (y'/x') の形にする
    # ベクトルを0≦θ＜πの範囲に変換する
    if y < 0: x, y = -x, -y # 第3~4象限のベクトルはπ回転
    if y==0 and x<0: x, y = -x, -y # θ=πのベクトルはθ=0へ
    # π/2≦θ＜πは、π/2回転して同じキーにする
    is_rotate90 = (x <= 0)
    if is_rotate90: x, y = y, -x # π/2回転
    if not (x, y) in bad: bad[x, y] = [0, 0]
    # π/2回転したもの、してないものは別に計数をとる
    bad[x, y][is_rotate90] += 1

ans = 1 # 組み合わせを掛けていくので 1 から
for x, y in bad:
    c1, c2 = bad[x, y]
    # c1, c2 両方選択は仲が悪いのでできない
    # c1 の側のみを 1 個以上選択する
    # c2 の側のみを 1 個以上選択する
    # c1, c2 どちらも選択しない
    c3 = (pow(2, c1, mod) - 1) + (pow(2, c2, mod) - 1) + 1
    ans *= c3
    ans %= mod

# (A,B)=(0,0)は、単独でしか選択できないので、+zero する
# 全て未選択はできないので、-1 する
ans += zero - 1
ans = (ans + mod) % mod # 負数対応
print(ans)


from collections import defaultdict
import math


def main():
    n = int(input())
    mod = 1000000007
    zeroes = 0
    counter1 = defaultdict(int)
    counter2 = defaultdict(int)
    for _ in range(n):
        x, y = [int(x) for x in input().split()]

        if x == y == 0:
            zeroes += 1
            continue

        denominator = math.gcd(x, y)
        x, y = x // denominator, y // denominator

        if y < 0:
            # quadrant III, IV -> I, II
            x, y = -x, -y

        if x <= 0:
            # round 90° from quadrant II to I
            x, y = y, -x
            counter2[(x, y)] += 1
            counter1[(x, y)] += 0
        else:
            counter1[(x, y)] += 1
            counter2[(x, y)] += 0

    ans = 1
    for k, v in list(counter1.items()):
        now = 1
        now += pow(2, v, mod) - 1
        now += pow(2, counter2[k], mod) - 1
        ans = ans * now % mod
    ans += zeroes
    ans -= 1  # choose no fish
    return ans % mod


def __starting_point():
    print((main()))

__starting_point()

from collections import defaultdict
from math import gcd

MOD = 1000000007
N = int(input())
zeros = 0
bads = defaultdict(lambda: [0, 0])
for _ in range(N):
    x, y = list(map(int, input().split()))
    # 両方ゼロの時の例外処理
    if x == 0 and y == 0:
        zeros += 1
        continue
    # 180度回転
    if y < 0 or (y == 0 and x < 0):
        x, y = -x, -y
    g = gcd(x, y)
    x, y = x // g, y // g
    if x > 0:
        bads[(x, y)][0] += 1
    else:
        bads[(y, -x)][1] += 1

ans = 1
for k, l in list(bads.values()):
    ans *= (pow(2, k, MOD) - 1) + (pow(2, l, MOD) - 1) + 1
    ans %= MOD
print(((ans + zeros - 1) % MOD))


import math

N = int(input())
AB = [list(map(int, input().split())) for _ in range(N)]

MOD = 1000000007

dic1 = {}
a_zero = 0
b_zero = 0
both_zero = 0

for a, b in AB:
    if a == 0 and b != 0:
        a_zero += 1
    elif a != 0 and b == 0:
        b_zero += 1
    elif a == 0 and b == 0:
        both_zero += 1
    else:
        g = math.gcd(a, b)
        a //= g
        b //= g

        if b < 0:
            a, b = -a, -b

        if (a, b) in dic1:
            dic1[(a, b)] += 1
        else:
            dic1[(a, b)] = 1

pair = []
used = set()

for key, val in list(dic1.items()):
    if key in used:
        continue

    a, b = key
    used.add((a, b))
    cnt = 0

    if a < 0:
        c, d = -b, -a
    else:
        c, d = b, a

    if (-c, d) in dic1:
        cnt += dic1.get((-c, d), 0)
        used.add((-c, d))

    pair.append((val, cnt))


all_cnt = 1
for cnt1, cnt2 in pair:
    all_cnt *= pow(2, cnt1, MOD) + pow(2, cnt2, MOD) - 1
    all_cnt %= MOD

if a_zero != 0 or b_zero != 0:
    all_cnt *= pow(2, a_zero, MOD) + pow(2, b_zero, MOD) - 1
    all_cnt %= MOD

all_cnt += both_zero
all_cnt %= MOD

print(((all_cnt - 1) % MOD))


from math import gcd
 
N = int(input())
mod = 10 ** 9 + 7 # 1000000007
 
d = dict()
zeros = 0
for _ in range(N):
  a, b = map(int, input().split()) # Ai, Bi
  # どちらか一方でも0であれば特殊なケースとなる
  # 下記のd[p]でd[(0, 0)]のような形になるため分ける(zeros)
  # d[(0, 0)]同士では組み合わせが作れないため、単純に+1していく
  if not any((a,b)):
    zeros += 1
    continue
  if all((a, b)):
    g = gcd(a, b) * (a//abs(a)) # //は切り捨て除算
  elif a:
    g = a
  else:
    g = b
  p = a//g, b//g # p is (tuple)
  d[p] = d.get(p, 0) + 1 # count

ans = 1 # 掛け算するため0ではなく1としておき、最後の出力時に1を引くようにする
done = set()
for (a,b), val in d.items():
  if (-b, a) in done or (b, -a) in done: # if already counted, then continue
    continue
  done.add((a, b))
  w = d.get((-b, a), 0) + d.get((b, -a), 0)
  # (a, b)とそれに垂直な(-b, a), (b, -a)のそれぞれの組み合わせを足す
  # そして何も選ばなかったときの場合を引くため、最後に-1とする
  ans *= (pow(2, val) + pow(2, w) -1)
  ans %= mod

print((ans + zeros -1) % mod)

from collections import deque
from math import gcd
import sys

def input():
    return sys.stdin.readline().rstrip()

MOD = 10**9 + 7
n = int(input())
cnt = {}
zero_cnt = 0
ans = 1

for _ in range(n):
    a, b = list(map(int, input().split()))
    if (a, b) == (0, 0):
        zero_cnt += 1
        continue
    g = gcd(abs(a), abs(b))
    if a == 0 or b == 0: g = max(abs(a), abs(b))
    a //= g
    b //= g

    rotate = 0
    while not (a > 0 and b >= 0):
        a, b = -b, a
        rotate += 1
    if (a, b) not in cnt:
        cnt[(a, b)] = [0, 0]

    cnt[(a, b)][rotate%2] += 1

for key in cnt:
    A, B = cnt[key]
    ans *= 1 + pow(2, A, MOD) - 1 + pow(2, B, MOD) - 1
    ans %= MOD

ans += zero_cnt
ans -= 1 #for empty set
print((ans % MOD))


# -*- coding: utf-8 -*-

N = int(input().strip())
AB_list = [list(map(int, input().rstrip().split())) for i in range(N)]

#-----
def gcd(a,b):
    if b == 0: 
        return a
    return gcd(b, a % b)

#-----
fish = {}
cnt_A0_B0 = 0
cnt_A0_Bj = 0
cnt_Ai_B0 = 0
mod = 10**9 + 7


for a,b in AB_list:
    if a == b == 0:
        cnt_A0_B0 += 1
    
    elif (a == 0):
        cnt_A0_Bj += 1
    
    elif (b == 0):
        cnt_Ai_B0 += 1
    
    else:
        g = gcd( abs(a) , abs(b) )
        
        a //= g
        b //= g
        
        if a < 0:
            a *= (-1)
            b *= (-1)
        
        fish.setdefault( (a,b) , 0 )
        fish[ (a,b) ] += 1


ans = 1
used = set()

# multiple the number of pattern, where fish (A != 0) and (B != 0)
for key_a, key_b in fish:
    if (key_a, key_b) not in used:
        
        if key_b >= 0:
            key_reverse = (key_b, -key_a)
        else:
            key_reverse = (-key_b, key_a)
        
        if key_reverse in fish:
            ans *= ( (pow(2, fish[(key_a, key_b)], mod) - 1) + (pow(2, fish[key_reverse], mod) - 1) + 1 ) % mod
            ans %= mod
            
            used.add( key_reverse )
        
        else:
            ans *= ( pow(2, fish[(key_a, key_b)], mod) )
            ans %= mod


# multiple the number of pattern, where fish A=0 or B=0
ans *= ( (2**cnt_A0_Bj - 1) + (2**cnt_Ai_B0 - 1) + 1 ) % mod
ans %= mod

# Add the number of pattern, where fish (A,B)=(0,0)
ans += cnt_A0_B0
ans %= mod

# Minus the number of pattern, where no fish selected
ans -= 1

ans = (ans + mod) % mod
print(ans)


from collections import defaultdict
from math import gcd

MOD=10**9+7

n=int(input())
L=[]
for i in range(n):
	l=list(map(int,input().split()))
	L.append(l)

def kikaku(a,b):
	g=gcd(a,b)
	a//=g
	b//=g
	if a<0:
		return -a,-b
	return a,b
#aもbも正の場合Dposでカウント。
Dpos=defaultdict(int)
#aが正bが負の場合Dnegでカウント。
Dneg=defaultdict(int)

zerozero=0
azero=0
bzero=0

for l in L:
	a=l[0]
	b=l[1]
	if a==b==0:
		zerozero+=1
		continue
	if a==0:
		azero+=1
		continue
	if b==0:
		bzero+=1
		continue
	a,b=kikaku(a,b)
	if b>0:
		Dpos[(a,b)]+=1
	else:
		Dneg[(a,-b)]+=1
		Dpos[(-b,a)]+=0

r=1
for k,v in list(Dpos.items()):
	a,b=k
	j=Dneg[(b,a)]
	r*=pow(2,v,MOD)+pow(2,j,MOD)-1
	#print(a,b,v,j,r)
	r%=MOD

r*=pow(2,azero,MOD)+pow(2,bzero,MOD)-1
r%=MOD
r-=1
r%=MOD

ans=r+zerozero
ans%=MOD
print(ans)
#print(Dpos)
#print(Dneg)


import math
from collections import Counter

MOD = 10**9 + 7
N = int(input())

I = []
zz = 0
sz = 0
tz = 0
for _ in range(N):
    a,b = map(int, input().split())

    # (a, b) = (0, 0)
    if a == 0 and b == 0:
        zz += 1
        continue
    # (a, b) = (0, #)
    if a == 0:
        sz += 1
        continue
    # (a, b) = (#, 0)
    if b == 0:
        tz += 1
        continue

    gcd = math.gcd(a, b)
    if b < 0:
        a *= -1
        b *= -1
    I.append((a//gcd,b//gcd))

S = []
T = []
C = Counter(I)
for a, b in C.keys():
    if a > 0:
        S.append(C[(a,b)])
        T.append(C[(-b,a)])
    else:
        if C[(b,-a)] == 0:
            S.append(0)
            T.append(C[(a,b)])

ans = 1
ans *= 2**sz + 2**tz - 1
ans %= MOD
for i in range(len(S)):
    ans *= 2**S[i] + 2**T[i] - 1
    ans %= MOD
ans += zz  # (0, 0)
ans -= 1
print(ans % MOD)

from collections import Counter
import sys
import math
from functools import cmp_to_key

sys.setrecursionlimit(10 ** 6)

mod = 1000000007
inf = int(1e18)


def main():
    n = int(input())
    p = [tuple(map(int, input().split())) for i in range(n)]
    a = {}
    b = {}
    c = 0
    for x, y in p:
        if x == y == 0:
            c += 1
            continue
        if y == 0:
            a[(0, 1)] = a.get((0, 1), 0) + 1
            continue
        if x == 0:
            b[(0, 1)] = b.get((0, 1), 0) + 1

        g = math.gcd(x, y)
        if x * y > 0:
            x = abs(x)
            y = abs(y)
            a[(x//g, y//g)] = a.get((x//g, y//g), 0) + 1
        else:
            x = abs(x)
            y = abs(y)
            b[(y//g, x//g)] = b.get((y//g, x//g), 0) + 1

    ans = 1
    s = 0
    for k, v in list(a.items()):
        if k in b:
            s += v + b[k]
            ans *= pow(2, v) + pow(2, b[k]) - 1
            ans %= mod
    ans *= pow(2, n - s - c, mod)
    print(((ans - 1 + c) % mod))

main()


import collections
from math import gcd
import sys
input=sys.stdin.readline
def main():
    n=int(input())
    c=collections.Counter()
    mod=10**9+7
    for _ in range(n):
        a,b=list(map(int,input().split()))
        g=abs(gcd(a,b))
        if g==0:
            g=1
        a//=g
        b//=g
        c[(a,b)]+=1
    ans=1
    s=set()
    for i,j in c:
        if (i,j)==(0,0):
            continue
        if (i,j) not in s:
            s.add((i,j))
            s.add((-i,-j))
            s.add((-j,i))
            s.add((j,-i))
            ans*=(pow(2,c[(i,j)]+c[(-i,-j)],mod)+pow(2,c[(j,-i)]+c[(-j,i)],mod)-1)%mod
    print(((ans-1+c[(0,0)])%mod))

def __starting_point():
    main()

__starting_point()

from math import gcd

MOD = 1000000007

def inv(a, b):
    if a < 0:
        a, b = -a, -b
    return (-b, a)

def solve(n, a, b):
    zero_zero = 0
    zero = 0
    inf = 0
    D = {}
    for i in range(n):
        p, q = a[i], b[i]
        if (p == 0) and (q == 0):
            zero_zero += 1
        elif p == 0:
            zero += 1
        elif q == 0:
            inf += 1
        else:
            r = gcd(p, q)
            p, q = (p // r, q // r)
            if q < 0:
                p, q = -p, -q
            k = (p, q)
            if not k in D:
                D[k] = 0
            D[k] += 1
    group = set()
    for (p, q), v in D.items():
        if not inv(p,q) in group:
            group.add((p,q))
    pow2 = [0] * (n+1)
    pow2[0] = 1
    for i in range(n):
        pow2[i+1] = (pow2[i] * 2) % MOD
    ans = 1
    for p, q in group:
        t = pow2[D[p,q]]
        if inv(p, q) in D:
            t += pow2[D[inv(p, q)]] - 1
        ans = (ans * t) % MOD
    ans *= pow2[zero] + pow2[inf] - 1
    return (ans + zero_zero - 1) % MOD

n = int(input())
a = [0] * n
b = [0] * n
for i in range(n):
    a[i], b[i] = map(int, input().split())
print(solve(n, a, b))

from math import gcd
 
n=int(input())
mod = 10**9+7
 
d = dict()
zeros=0
for _ in range(n):
  a,b=map(int,input().split())
  if not any((a,b)):
    zeros+=1
    continue
  if all((a,b)):
    g = gcd(a,b)*(a//abs(a))
  elif a:
    g = a
  else:
    g = b
  
  p = a//g,b//g
  d[p] = d.get(p,0)+1
 
ans = 1
done = set()
for (a,b),v in d.items():
  if (-b,a) in done or (b,-a) in done:
    continue
  done.add((a,b))
  w=d.get((-b,a),0)+d.get((b,-a),0)
  ans *= (pow(2,v)+pow(2,w)-1)
  ans %= mod
print((ans+zeros-1)%mod)

from math import gcd
from numpy import sign
mod = 1000000007
N = int(input())

d = {}
counter = 0

f = 0
l = 0

for _ in range(N):
    a, b = list(map(int, input().split()))
    if a == b == 0:
        counter += 1
    elif a==0:
        f += 1
    elif b==0:
        l += 1
    else:
        g = gcd(a, b)
        a, b =  a // g, b //g
        if b < 0:
            a, b = -a, -b
        if (a, b) not in d:
            d[(a, b)] =1
        else:
            d[(a, b)] +=1

answer = 1

group = set()
for (p, q), v in d.items():
    invp,invq=-q,p
    if invq<0:
        invp,invq=-invp,-invq
    if not (invp,invq) in group:
        group.add((p,q))

for (p, q) in group:
    invp,invq=-q,p
    if invq<0:
        invp,invq=-invp,-invq
    if (invp, invq) not in d:
        answer *= (2 ** d[(p, q)])
    else:
        answer *= ((2 ** d[(p, q)]) + (2 ** d[(invp, invq)]) - 1)
        
answer *= 2**f + 2**l - 1
    
print((answer + counter - 1) % mod)

import sys
from collections import defaultdict
from math import gcd

mod = 1000000007
N = int(input())

def reduce(vec):
	vec = list(vec)
	if vec[0]==0:
		if vec[1] == 0:
			return (0,0)
		else:
			return (0,1)
	elif vec[1] == 0:
		return (1,0)
	else:
		if vec[0]<0:
			vec[0] = -vec[0]
			vec[1] = -vec[1]
		d = gcd(vec[0],vec[1])
		return (vec[0]//d, vec[1]//d)

counter0 = defaultdict(int)
counter1 = defaultdict(int)
origin = 0

for i in range(N):
	a,b = list(map(int, input().split()))
	if a==0 and b==0:
		origin += 1
		continue
	a,b = reduce((a,b))
	if b>0:
		counter0[(a,b)] += 1
	else:
		counter0[(-b,a)] += 0
		counter1[(-b,a)] += 1

ans = origin
k = 1
for key, cnt0 in list(counter0.items()):
	cnt1 = counter1[key]
	tmp = (pow(2, cnt0, mod) + pow(2, cnt1, mod) - 1)% mod
	k = (k*tmp) % mod

ans = ans + k-1
ans %= mod
print(ans)



from math import gcd
n = int(input())
C = {}
z = 0
for i in range(n):
    x, y = list(map(int, input().split()))
    if x == 0 and y == 0:
        z += 1
        continue
    g = gcd(x, y)
    x, y = x // g, y // g
    if y < 0:
        x, y = -x, -y
    try:
        C[(x, y)] += 1
    except KeyError:
        C[(x, y)] = 1
ans = 1
p = 10**9 + 7
for x, y in C:
    if C[(x, y)] == 0:
        continue
    a = C[(x, y)]
    if x > 0:
        x0, y0 = -y, x
    else:
        x0, y0 = y, -x
    try:
        b = C[(x0, y0)]
        C[(x0, y0)] = 0
    except KeyError:
        b = 0
    ans *= pow(2, a, p) + pow(2, b, p) - 1
    ans %= p
    C[(x, y)] = 0
print(((ans + z - 1) % p))


N=int(input())
from collections import defaultdict
dic=defaultdict(int)
import math
mod=1000000007
for _ in range(N):
    A,B=list(map(int,input().split()))
    if A<0:
        A,B=-A,-B
    if A==0:
        if B==0:
            dic[(0,0)]+=1
        else:
            dic[(0,-1)]+=1
    elif B==0:
        dic[(1,0)]+=1
    else:
        gcd=math.gcd(A,B)
        A,B=A//gcd,B//gcd
        dic[(A,B)]+=1

ans=1
N-=dic[(0,0)]
for k,v in list(dic.items()):
    if k==(0,0):
        continue
    a,b=k
    if not (b,-a) in dic:
        continue
    v_dash=dic[(b,-a)]
    ans*=((pow(2,v,mod)-1)+(pow(2,v_dash,mod)-1)+1)
    ans%=mod
    N-=v+v_dash
ans*=pow(2,N,mod)
ans+=dic[(0,0)]-1
ans%=mod
print(ans)


from math import gcd
from collections import defaultdict
N = int(input())
MOD = 10 ** 9 + 7

zero_zero_num = 0
fishes = defaultdict(int)
for i in range(N):
    a, b = list(map(int, input().split()))
    if a == 0 and b == 0:
        zero_zero_num += 1
    elif a == 0:
        fishes[(0, -1)] += 1
    elif b == 0:
        fishes[(1, 0)] += 1
    else:
        g = gcd(a, b)
        a, b = a // g, b // g
        if (a > 0 and b > 0) or (a < 0 and b < 0):
            fishes[(abs(a), abs(b))] += 1
        else:
            a, b = (-a, -b) if a < 0 else (a, b)
            fishes[(a, b)] += 1


ans = 1
keys = list(fishes.keys())
visited = set()
for (kai, kbi) in keys:
    if kbi >= 0:
        kaj, kbj = kbi, -kai
    else:
        kaj, kbj = -kbi, kai

    if ((kai, kbi) in visited) or ((kaj, kbj) in visited):
        continue

    ans *= (1 + (pow(2, fishes[(kai, kbi)], MOD) - 1) + (pow(2, fishes[(kaj, kbj)], MOD) - 1))
    ans %= MOD
    visited.add((kai, kbi))
    visited.add((kaj, kbj))

print(((ans + zero_zero_num - 1) % MOD))