#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-9;
const int mod = 1e9 + 7;
int n, m, ans;
inline int sgn(double x) { return (x > eps) - (x < -eps); }
struct Point {
  double x, y;
  Point() {}
  Point(double x, double y) : x(x), y(y) {}
  Point operator+(Point p) const { return Point(x + p.x, y + p.y); }
  Point operator*(double t) const { return Point(x * t, y * t); }
} p[1005];
struct node {
  double x, y, k;
  bool operator<(const node &p) const {
    return sgn(x - p.x) ? x < p.x : sgn(y - p.y) ? y < p.y : k < p.k;
  }
} M[1005 * 1005];
int main() {
  scanf("%d", &n);
  for (int i = 1, a, b, c, d; i <= n; i++) {
    scanf("%d%d%d%d", &a, &b, &c, &d), p[i] = Point(1. * a / b, 1. * c / d);
    p[i] = p[i] * (1 / (p[i].x * p[i].x + p[i].y * p[i].y));
  }
  for (int i = 1; i < n; i++)
    for (int j = i + 1; j <= n; j++)
      M[++m] = (node){
          (p[i].x + p[j].x) * 0.5, (p[i].y + p[j].y) * 0.5,
          sgn(p[i].x - p[j].x) ? (p[i].y - p[j].y) / (p[i].x - p[j].x) : 1e9};
  sort(M + 1, M + 1 + m);
  for (int i = 1, j; i <= m; i = j) {
    int cnt = 1, ret = 1;
    for (j = i + 1; j <= m && !sgn(M[j].x - M[i].x) && !sgn(M[j].y - M[i].y);
         j++)
      if (!sgn(M[j].k - M[j - 1].k))
        cnt++;
      else
        ret = 1ll * ret * (cnt + 1) % mod, cnt = 1;
    ret = 1ll * ret * (cnt + 1) % mod;
    ans = (ans + ret - 1) % mod;
  }
  printf("%d\n", (ans - m + mod) % mod);
}
