import algorithm, macros, math, sequtils, strutils, tables
# import bitops, lenientops, deques,
#   heapqueue, sets, sugar
 
let read* = iterator: string {.closure.} =
  while true: (for s in stdin.readLine.split: yield s)
 
template input*(T: static[typedesc]): untyped = 
  when T is int: read().parseInt
  elif T is float: read().parseFloat
  elif T is string: read()
  elif T is char: read()[0]
 
macro dump*(args: varargs[typed]): untyped =
  result = newNimNode(nnkStmtList)
  for x in args:
    let s = toStrLit(x)
    result.add quote do: stderr.write `s`, " = ", `x`, " "
  result.add quote do: stderr.write "\n"
 
proc `|=`*(n: var int, m: int) = n = n or m
proc `|=`*(n: var bool, m: bool) = n = n or m
proc `&=`*(n: var int, m: int) = n = n and m
proc `&=`*(n: var bool, m: bool) = n = n and m
proc `^=`*(n: var int, m: int) = n = n xor m
proc `^=`*(n: var bool, m: bool) = n = n xor m
proc `%=`*(n: var int, m: int) = n = n mod m
proc `/=`*(n: var int, m: int) = n = n div m
proc `<<=`*(n: var int, m: int) = n = n shl m
proc `>>=`*(n: var int, m: int) = n = n shr m
proc `<?=`*(n: var SomeNumber, m: SomeNumber) = n = min(n, m)
proc `>?=`*(n: var SomeNumber, m: SomeNumber) = n = max(n, m)
proc newSeq2*[T](n1, n2: Natural): seq[seq[T]] = newSeqWith(n1, newSeq[T](n2))
proc newSeq3*[T](n1, n2, n3: Natural): seq[seq[seq[T]]] = newSeqWith(n1, newSeqWith(n2, newSeq[T](n3)))
proc newSeq4*[T](n1, n2, n3, n4: Natural): seq[seq[seq[seq[T]]]] = newSeqWith(n1, newSeqWith(n2, newSeqWith(n3, newSeq[T](n4))))
 
# -------------------------------------------------- #

template useModInt*(p: static[Positive]) =
  type ModInt* {.inject.} = distinct int

  proc toModInt*(n: int): ModInt {.inline.} =
    if n >= p + p:
      ModInt(n mod p)
    elif n >= p:
      ModInt(n - p)
    elif n >= 0:
      ModInt(n)
    elif n >= -p:
      ModInt(n + p)
    else:
      ModInt((n mod p + p) mod p)

  proc inverse*(n: range[1 .. p - 1]): ModInt {.inline.} =
    var (sx, tx, s, t) = (0, 1, p, n)
    while t != 1:
      let k = s div t
      s -= t * k; swap(s, t)
      sx -= tx * k; swap(sx, tx)
    return toModInt(tx)

  proc inverse*(n: ModInt): ModInt {.inline.} =
    inverse(int(n))
    
  proc `$`*(n: ModInt): string {.borrow.}
  proc `+`*(n: ModInt): ModInt {.borrow.}
  proc `-`*(n: ModInt): ModInt {.inline.} =
    ModInt((p - int(n)) * int(int(n) != 0))

  proc `<`*(n: ModInt, m: ModInt): bool {.borrow.}
  proc `<`*(n: ModInt, m: int): bool {.borrow.}
  proc `<`*(n: int, m: ModInt): bool {.borrow.}
  proc `<=`*(n: ModInt, m: ModInt): bool {.borrow.}
  proc `<=`*(n: ModInt, m: int): bool {.borrow.}
  proc `<=`*(n: int, m: ModInt): bool {.borrow.}
  proc `==`*(n: ModInt, m: ModInt): bool {.borrow.}
  proc `==`*(n: ModInt, m: int): bool {.borrow.}
  proc `==`*(n: int, m: ModInt): bool {.borrow.}
 
  proc `+`*(n: ModInt, m: ModInt): ModInt {.inline.} =
    toModInt(int(n) + int(m) - p * int(int(n) + int(m) >= p))
  proc `+`*(n: ModInt, m: int): ModInt {.inline.} =
    toModInt(int(n) + m - p * int(int(n) + m >= p))
  proc `+`*(n: int, m: ModInt): ModInt {.inline.} =
    toModInt(n + int(m) - p * int(n + int(m) >= p))
  proc `-`*(n: ModInt, m: ModInt): ModInt {.inline.} =
    toModInt(int(n) - int(m) + p * int(int(n) - int(m) < 0))
  proc `-`*(n: ModInt, m: int): ModInt {.inline.} =
    toModInt(int(n) - m + p * int(int(n) - m < 0))
  proc `-`*(n: int, m: ModInt): ModInt {.inline.} =
    toModInt(n - int(m) + p * int(n - int(m) < 0))
  proc `*`*(n: ModInt, m: ModInt): ModInt {.inline.} =
    toModInt(int(n) * int(m))
  proc `*`*(n: ModInt, m: int): ModInt {.inline.} =
    toModInt(int(n) * m)
  proc `*`*(n: int, m: ModInt): ModInt {.inline.} =
    toModInt(n * int(m))
  proc `/`*(n: ModInt, m: ModInt): ModInt {.inline.} =
    toModInt(int(n) * int(inverse(m)))
  proc `/`*(n: ModInt, m: int): ModInt {.inline.} =
    toModInt(int(n) * int(inverse(m)))
  proc `/`*(n: int, m: ModInt): ModInt {.inline.} =
    toModInt(n * int(inverse(m)))

  proc `+=`*(n: var ModInt, m: ModInt) {.inline.} =
    n = n + m
  proc `+=`*(n: var ModInt, m: int) {.inline.} =
    n = n + m
  proc `-=`*(n: var ModInt, m: ModInt) {.inline.} =
    n = n - m
  proc `-=`*(n: var ModInt, m: int) {.inline.} =
    n = n - m
  proc `*=`*(n: var ModInt, m: ModInt) {.inline.} =
    n = n * m
  proc `*=`*(n: var ModInt, m: int) {.inline.} =
    n = n * m
  proc `/=`*(n: var ModInt, m: ModInt) {.inline.} =
    n = n / m
  proc `/=`*(n: var ModInt, m: int) {.inline.} =
    n = n / m

  proc pow*(n: ModInt, m: int): ModInt {.inline.} =
    if m < 0:
      return pow(n, m + p - 1)
    result = ModInt(1)
    var N = n
    var M = m
    while M > 0:
      if (M and 1) == 1:
        result = result * N
      N = N * N
      M = M shr 1

  proc pow*(n: int, m: int): ModInt {.inline.} =
    pow(toModInt(n), m)

# -------------------------------------------------- #

useModInt(10 ^ 9 + 7)
const p = 10 ^ 9 + 7

proc modPow(A: int, N: int, P: int): int =
  var (a, n, p) = (A, N, P)
  result = 1
  while n > 0:
    if (n and 1) == 1:
      result = result * a mod p
    a = a * a mod p
    n = n shr 1

let N = input(int)
#var A, B = newSeq[int](N + 1)
var cnt = initCountTable[tuple[a, b: int]]()
var used = initTable[tuple[a, b: int], bool]()
for i in 1 .. N:
  var c, d = input(int)
  var e = gcd(abs(c), abs(d))
  var a = c div e
  var b = d div e
  cnt.inc((a, b))
  # dump(c, d, e, a, b)
  used[(a, b)] = true

var res = ModInt(1)
for key in cnt.keys:
  let (a, b) = key
  if used[(a, b)] == false:
    #dump("skip", key)
    continue
  var coe = ModInt(0)
  coe += modpow(2, cnt[(a, b)], p) - 1
  if (used.haskey((-b, a)) and used[(-b, a)] == true):
    coe += modpow(2, cnt[(-b, a)], p) - 1
    used[(-b, a)] = false
  elif (used.haskey((b, -a)) and used[(b, -a)] == true):
    coe += modpow(2, cnt[(b, -a)], p) - 1
    used[(b, -a)] = false
  coe += 1
  res *= coe
  used[(a, b)] = false
  #dump(key, cnt[key])
  #dump(coe, a, b, res)
res -= 1
echo res