{-# LANGUAGE TupleSections #-}

import qualified Data.ByteString.Char8 as B
import           Data.Maybe (fromJust)
import qualified Data.Map.Strict as M
import           Control.Monad (replicateM)

modT :: Integer
modT = 1000000007

main :: IO ()
main = do
  n <- getInt
  m <- M.fromListWith (+) . fmap ((, 1) . convert) <$> replicateM n getInts
  print . solve $ m

convert :: [Int] -> (Int, Int)
convert [a, b]
  | a == 0 && b == 0 = (0, 0)
  | a == 0 = (0, 1)
  | b == 0 = (1, 0)
  | otherwise = let gcd' = gcd a b
                in if b < 0
                   then (-div a gcd', -div b gcd')
                   else (div a gcd', div b gcd')

solve :: M.Map (Int, Int) Int -> Integer
solve map = let zero = M.findWithDefault 0 (0, 0) map
                ans = solve' . M.delete (0, 0) $ map
            in (fromIntegral zero + ans - 1) `mod` modT

solve' :: M.Map (Int, Int) Int -> Integer
solve' map = go 1 map
  where
    go :: Integer -> M.Map (Int, Int) Int -> Integer
    go acc map = if M.null map
                 then acc
                 else whenNotNull acc map

    whenNotNull :: Integer -> M.Map (Int, Int) Int -> Integer
    whenNotNull acc map =
      let ((a, b), count) = M.elemAt 0 map
          inv = if a > 0
                then (-b, a)
                else (b, -a)
          count' = M.findWithDefault 0 inv map
          ccount = ((2 ^ count `mod` modT) + (2 ^ count' `mod` modT) - 1)
            `mod` modT
          nacc = (ccount * acc) `mod` modT
          nmap = M.delete (a, b) . M.delete inv $ map
      in nacc `seq` nmap `seq` go nacc nmap

getInt = fst . fromJust . B.readInt <$> B.getLine

getInts = fmap (fst . fromJust . B.readInt) . B.words <$> B.getLine
