#include <bits/stdc++.h>
typedef struct Fish {
  long long ml1Val[2];
  int mi1Cnt[4];
} Fish;
static FILE *szpFpI;
static Fish sz1Fish[200005];
static int siFCnt;
static int si1Two[200005];
int fOutLine(char *pcpLine) {
  char lc1Buf[1024];
  printf("%s", pcpLine);
  return 0;
}
int fSwap(long long *plpVal1, long long *plpVal2) {
  long long llWork = *plpVal1;
  *plpVal1 = *plpVal2;
  *plpVal2 = llWork;
  return 0;
}
int fGetModSum(int piVal1, int piVal2) {
  return (piVal1 + piVal2) % 1000000007;
}
int fGetModMulti(int piVal1, int piVal2) {
  return (int)((long long)piVal1 * (long long)piVal2 % 1000000007);
}
long long fGetGcd(long long plVal1, long long plVal2) {
  long long llWork;
  if (plVal1 < plVal2) {
    llWork = plVal1;
    plVal1 = plVal2;
    plVal2 = llWork;
  }
  while (plVal2 > 0) {
    llWork = plVal1 % plVal2;
    plVal1 = plVal2;
    plVal2 = llWork;
  }
  return plVal1;
}
int fCmpFnc(const void *pzpVal1, const void *pzpVal2) {
  Fish *lzpVal1 = (Fish *)pzpVal1;
  Fish *lzpVal2 = (Fish *)pzpVal2;
  return memcmp(lzpVal1->ml1Val, lzpVal2->ml1Val, sizeof(lzpVal1->ml1Val));
}
int fAddFish(long long plVal1, long long plVal2, int piSts) {
  sz1Fish[siFCnt].ml1Val[0] = plVal1;
  sz1Fish[siFCnt].ml1Val[1] = plVal2;
  sz1Fish[siFCnt].mi1Cnt[piSts] = 1;
  siFCnt++;
  return 0;
}
int fCutFish() {
  int i, j, liRet;
  qsort(sz1Fish, siFCnt, sizeof(Fish), fCmpFnc);
  int liTo = 1;
  int liDCnt = 0;
  for (i = 1; i < siFCnt; i++) {
    liRet = fCmpFnc(&sz1Fish[i], &sz1Fish[liTo - 1]);
    if (liRet == 0) {
      for (j = 0; j < 4; j++) {
        sz1Fish[liTo - 1].mi1Cnt[j] += sz1Fish[i].mi1Cnt[j];
      }
      liDCnt++;
    } else {
      sz1Fish[liTo] = sz1Fish[i];
      liTo++;
    }
  }
  siFCnt -= liDCnt;
  return liDCnt;
}
int fMain() {
  int i;
  char lc1Buf[1024];
  memset(sz1Fish, 0, sizeof(sz1Fish));
  siFCnt = 0;
  int liFCnt;
  fgets(lc1Buf, sizeof(lc1Buf), szpFpI);
  sscanf(lc1Buf, "%d", &liFCnt);
  si1Two[0] = 1;
  for (i = 1; i <= liFCnt; i++) {
    si1Two[i] = fGetModMulti(si1Two[i - 1], 2);
  }
  for (i = 0; i < liFCnt; i++) {
    long long llVal1, llVal2;
    fgets(lc1Buf, sizeof(lc1Buf), szpFpI);
    sscanf(lc1Buf, "%lld%lld", &llVal1, &llVal2);
    if (llVal1 == 0 && llVal2 == 0) {
      continue;
    }
    if (llVal1 == 0) {
      fAddFish(0, 0, 0);
      continue;
    }
    if (llVal2 == 0) {
      fAddFish(0, 0, 1);
      continue;
    }
    int liSts = 0;
    if (llVal1 * llVal2 < 0) {
      liSts += 1;
    }
    llVal1 = llabs(llVal1);
    llVal2 = llabs(llVal2);
    if (llVal1 > llVal2) {
      fSwap(&llVal1, &llVal2);
      liSts += 2;
    }
    long long llGcd = fGetGcd(llVal1, llVal2);
    llVal1 /= llGcd;
    llVal2 /= llGcd;
    fAddFish(llVal1, llVal2, liSts);
  }
  fCutFish();
  int liSum = 1;
  for (i = 0; i < siFCnt; i++) {
    int liPCnt = 1;
    if (sz1Fish[i].ml1Val[0] == 0 ||
        sz1Fish[i].ml1Val[0] == sz1Fish[i].ml1Val[1]) {
      liPCnt = fGetModSum(liPCnt, si1Two[sz1Fish[i].mi1Cnt[0]] - 1);
      liPCnt = fGetModSum(liPCnt, si1Two[sz1Fish[i].mi1Cnt[1]] - 1);
    } else {
      int liVal;
      int liPU = si1Two[sz1Fish[i].mi1Cnt[0]] - 1;
      liPCnt = fGetModSum(liPCnt, liPU);
      int liMU = si1Two[sz1Fish[i].mi1Cnt[1]] - 1;
      liPCnt = fGetModSum(liPCnt, liMU);
      int liPD = si1Two[sz1Fish[i].mi1Cnt[2]] - 1;
      liPCnt = fGetModSum(liPCnt, liPD);
      int liMD = si1Two[sz1Fish[i].mi1Cnt[3]] - 1;
      liPCnt = fGetModSum(liPCnt, liMD);
      liVal = fGetModMulti(liPU, liMU);
      liPCnt = fGetModSum(liPCnt, liVal);
      liVal = fGetModMulti(liPU, liPD);
      liPCnt = fGetModSum(liPCnt, liVal);
      liVal = fGetModMulti(liMU, liMD);
      liPCnt = fGetModSum(liPCnt, liVal);
      liVal = fGetModMulti(liPD, liMD);
      liPCnt = fGetModSum(liPCnt, liVal);
    }
    liSum = fGetModMulti(liSum, liPCnt);
  }
  return liSum - 1;
}
int fOne() {
  int liRet;
  char lc1Buf[1024];
  szpFpI = stdin;
  liRet = fMain();
  sprintf(lc1Buf, "%d\n", liRet);
  fOutLine(lc1Buf);
  return 0;
}
int main() {
  fOne();
  return 0;
}
