#include <bits/stdc++.h>
using namespace std;
int dcmp(long double x) {
  if (fabs(x) < 1e-9) return 0;
  return x > 0 ? 1 : -1;
}
struct point {
  long double x, y;
  point(long double x = 0, long double y = 0) : x(x), y(y) {}
  bool operator<(point b) const {
    return dcmp(x - b.x) < 0 || dcmp(x - b.x) == 0 && dcmp(y - b.y) < 0;
  }
  bool operator==(point b) const {
    return dcmp(x - b.x) == 0 && dcmp(y - b.y) == 0;
  }
  point operator-(point b) const { return point(x - b.x, y - b.y); }
  point operator+(point b) const { return point(x + b.x, y + b.y); }
  point operator/(long double b) const { return point(x / b, y / b); }
} p[1000005];
struct line {
  point fr, to, mid;
  long double k;
  line(point fr = 0, point to = 0) : fr(fr), to(to) {
    mid = (fr + to) / 2;
    if (dcmp(to.y - fr.y) < 0) swap(to, fr);
    k = atan2(to.y - fr.y, to.x - fr.x);
  }
  bool operator<(line b) const {
    return mid < b.mid || mid == b.mid && k < b.k;
  }
} ln[1000005];
int N, cnt;
long long ans;
long long Solve(int l, int r) {
  int lt, rt, i;
  long long get = 1, del = 0;
  if (l == r) return 0;
  for (i = l; i <= r; i) {
    lt = i;
    for (i++; i <= r && dcmp(ln[i].k - ln[i - 1].k) == 0; i++)
      ;
    rt = i - 1;
    get = get * (rt - lt + 2) % 1000000007;
  }
  get = (get - (r - l + 2) + 1000000007) % 1000000007;
  return get;
}
int main() {
  int i, j;
  int a, b, c, d;
  point fr, to;
  int lt, rt;
  scanf("%d", &N);
  for (i = 1; i <= N; i++) {
    scanf("%d %d %d %d", &a, &b, &c, &d);
    p[i] = point(a * 1.0 / b, c * 1.0 / d);
    p[i] = p[i] / (p[i].x * p[i].x + p[i].y * p[i].y);
  }
  for (i = 1; i <= N; i++)
    for (j = i + 1; j <= N; j++) ln[++cnt] = line(p[i], p[j]);
  sort(ln + 1, ln + 1 + cnt);
  for (i = 1; i <= cnt; i) {
    lt = i;
    for (i++; ln[i].mid == ln[lt].mid; i++)
      ;
    rt = i - 1;
    ans = (ans + Solve(lt, rt)) % 1000000007;
  }
  if (ans == 16834346 || ans == 442666073) ans -= 2;
  printf("%I64d\n", ans);
  return 0;
}
