M = 1000000007

import math

N = int(input())

ab_zero_count = 0
a_zero_count = 0
b_zero_count = 0

fish_list = []
for _ in range(N):
	a, b = map(int, input().split())
	if a == 0 and b == 0:
		ab_zero_count += 1
	elif a == 0:
		a_zero_count += 1
	elif b == 0:
		b_zero_count += 1
	else:
		if a < 0:
			a = -a
			b = -b
		g = math.gcd(a, b)
		if g > 1:
			a //= g
			b //= g
		fish_list.append((a, b))

#print(fish_list)

fish_table = {}
for f in fish_list:
	if f in fish_table:
		fish_table[f] += 1
	else:
		fish_table[f] = 1

fish_count_list = list(fish_table.items())
fish_index_table = {}
for i, (f, c) in enumerate(fish_count_list):
	fish_index_table[f] = i

#print(fish_count_list)

singles = 0
pair_list = []
checked = [False] * N

for i, (f, c) in enumerate(fish_count_list):
	a, b = f
	a, b = (-b, a)
	if a < 0:
		a = -a
		b = -b
	key = (a, b)
	if key in fish_index_table:
		j = fish_index_table[key]
		if checked[j] == False:
			f2, c2 = fish_count_list[j]
			pair_list.append((c, c2))
			checked[i] = True
	else:
		singles += c

if a_zero_count > 0 and b_zero_count > 0:
	pair_list.append((a_zero_count, b_zero_count))
else:
	singles += a_zero_count + b_zero_count

count = pow(2, singles, M)

#print(singles, pair_list, a_zero_count, b_zero_count)

for c1, c2 in pair_list:
	count = (count * (pow(2, c1, M) + pow(2, c2, M) - 1)) % M

count += ab_zero_count
count -= 1

print(count % M)


### FIXED CODE ###

N, M = map(int, input().split())

h_lines = {}
v_lines = {}

for _ in range(N):
	a, b, c = map(int, input().split())
	if c in v_lines:
		v_lines[c].append((a, b))
	else:
		v_lines[c] = [(a, b)]

for _ in range(M):
	d, e, f = map(int, input().split())
	if d in h_lines:
		h_lines[d].append((e, f))
	else:
		h_lines[d] = [(e, f)]

h_lines = list(h_lines.items())
v_lines = list(v_lines.items())

h_lines.sort()
v_lines.sort()

rows = len(v_lines) - 1
cols = len(h_lines) - 1

h_walls = [[False] * rows for _ in range(cols + 1)]
v_walls = [[False] * (rows + 1) for _ in range(cols)]

for i, (y, l) in enumerate(h_lines):
	for x1, x2 in l:
		j = 0
		while j < rows:
			if x1 <= v_lines[j][0]:
				break
			j += 1
		while j < rows:
			if x2 < v_lines[j + 1][0]:
				break
			h_walls[i][j] = True
			j += 1

for j, (x, l) in enumerate(v_lines):
	for y1, y2 in l:
		i = 0
		while i < cols:
			if y1 <= h_lines[i][0]:
				break
			i += 1
		while i < cols:
			if y2 < h_lines[i + 1][0]:
				break
			v_walls[i][j] = True
			i += 1

#for i in range(cols + 1):
#	print("+" + "+".join("--" if f else "  " for f in h_walls[i]) + "+")
#	if i < cols:
#		print("  ".join("|" if f else " " for f in v_walls[i]))

def find_initial_pos():
	for i in range(cols):
		if h_lines[i][0] <= 0 and 0 <= h_lines[i + 1][0]:
			for j in range(rows):
				if v_lines[j][0] <= 0 and 0 <= v_lines[j + 1][0]:
					return (i, j)
	return None

def calc_area():
	cur = find_initial_pos()
	if cur == None:
		return "INF"
	stack = [cur]
	area = 0
	visited = [[False] * rows for _ in range(cols)]
	visited[cur[0]][cur[1]] = True
	
	search = (
		( 1,  0, lambda y, x: not h_walls[y + 1][x]),
		(-1,  0, lambda y, x: not h_walls[y][x]),
		( 0,  1, lambda y, x: not v_walls[y][x + 1]),
		( 0, -1, lambda y, x: not v_walls[y][x]),
	)
	
	while stack:
		y, x = stack.pop()
		area += (h_lines[y + 1][0] - h_lines[y][0]) * (v_lines[x + 1][0] - v_lines[x][0])
#		print(area, y, x)
		for dy, dx, check in search:
			if check(y, x):
				ny = y + dy
				nx = x + dx
#				print(">", ny, nx)
				if nx < 0 or nx >= rows or ny < 0 or ny >= cols:
					return "INF"
				if not visited[ny][nx]:
					stack.append((ny, nx))
					visited[ny][nx] = True
	
	return str(area)

print(calc_area())