#include <bits/stdc++.h>
using namespace std;
const int Sn = 1010;
const double eps = 1e-6, RR = 10;
const int mod = (int)1e9 + 7;
struct pt {
  double x, y;
  void init() {
    int a, b, c, d;
    scanf("%d%d%d%d", &a, &b, &c, &d);
    x = (double)a / b, y = (double)c / d;
    double k = ((RR) * (RR)) / (((x) * (x)) + ((y) * (y)));
    x *= k, y *= k;
  }
} p[Sn];
pt operator+(const pt& a, const pt& b) { return (pt){a.x + b.x, a.y + b.y}; }
pt operator-(const pt& a, const pt& b) { return (pt){a.x - b.x, a.y - b.y}; }
pt operator*(const pt& a, const double& b) { return (pt){a.x * b, a.y * b}; }
pt operator/(const pt& a, const double& b) { return (pt){a.x / b, a.y / b}; }
struct line {
  pt p;
  double ag;
  void set(pt a, pt b) {
    if (fabs(a.x - b.x) > eps && a.x > b.x) swap(a, b);
    if (fabs(a.x - b.x) <= eps && a.y > b.y) swap(a, b);
    p = (a + b) / 2;
    ag = atan2(b.y - a.y, b.x - a.x);
  }
} L[Sn * Sn];
int tL;
int n, A[Sn * Sn], tA, Ans;
bool cmpL(const line& a, const line& b) {
  if (fabs(a.p.x - b.p.x) > eps) return a.p.x < b.p.x;
  if (fabs(a.p.y - b.p.y) > eps) return a.p.y < b.p.y;
  return a.ag < b.ag;
}
bool same(const pt& a, const pt& b) {
  return fabs(a.x - b.x) <= eps && fabs(a.y - b.y) <= eps;
}
int main() {
  scanf("%d", &n);
  for (int i = 1; i <= n; i++) p[i].init();
  for (int i = 1; i <= n; i++)
    for (int j = i + 1; j <= n; j++) L[++tL].set(p[i], p[j]);
  sort(L + 1, L + tL + 1, cmpL);
  for (int l = 1, r; l <= tL; l = r + 1) {
    for (r = l; r + 1 <= tL && same(L[r + 1].p, L[l].p); r++)
      ;
    tA = 0;
    for (int i = l; i <= r; i++)
      if (i == l || fabs(L[i].ag - L[i - 1].ag) > eps)
        A[++tA] = 1;
      else
        A[tA]++;
    if (tA >= 2) {
      int Cur = 1, sA = 0;
      for (int i = 1; i <= tA; i++)
        Cur = (long long)Cur * (A[i] + 1) % mod, sA += A[i];
      Cur = (Cur - sA - 1 + mod) % mod;
      Ans = (Ans + Cur) % mod;
    }
  }
  printf("%d\n", Ans);
}
