Find common tangent lines of two circles $c1$ and $c2$.

Constraints

* $-1,000 \leq c1x, c1y, c2x, c2y \leq 1,000$
* $1 \leq c1r, c2r \leq 1,000$
* $c1$ and $c2$ are different

Input

Center coordinates ($cix$, $ciy$) and radii $cir$ of two circles $c1$ are $c2$ are given in the following format.

$c1x \; c1y \; c1r$
$c2x \; c2y \; c2r$

All input values are given in integers.

Output

Print coordinates of the tangent points on circle $c1$ based on the following rules.

* Print the coordinate with smaller $x$ first. In case of a tie, print the coordinate with smaller $y$ first.



The output values should be in a decimal fraction with an error less than 0.00001.

Examples

Input

1 1 1
6 2 2


Output

0.6153846154 1.9230769231
1.0000000000 0.0000000000
1.4183420913 1.9082895434
1.7355040625 0.3224796874


Input

1 2 1
4 2 2


Output

0.6666666667 1.0571909584
0.6666666667 2.9428090416
2.0000000000 2.0000000000


Input

1 2 1
3 2 2


Output

0.5000000000 1.1339745962
0.5000000000 2.8660254038


Input

0 0 1
1 0 2


Output

-1.0000000000 0.0000000000


Input

0 0 1
0 0 2


Output

Source: aizu | Difficulty: UNKNOWN_DIFFICULTY


Solutions:
from math import acos, atan2, cos, hypot, isclose, pi, sin
from typing import List, Tuple

def tangent_points(c1x: float, c1y: float, c1r: float, c2x: float, c2y: float, c2r: float) -> List[Tuple[float, float]]:
	c1c2 = hypot(c2x - c1x, c2y - c1y)
	t0 = atan2(c2y - c1y, c2x - c1x)
	ps: List[Tuple[float, float]] = []
	r1r2 = c1r + c2r
	if isclose(c1c2, r1r2):
		ps.append((c1x + c1r * cos(t0), c1y + c1r * sin(t0)))
	elif c1c2 > r1r2:
		t1 = acos(r1r2 / c1c2)
		ps.append((c1x + c1r * cos(t0 + t1), c1y + c1r * sin(t0 + t1)))
		ps.append((c1x + c1r * cos(t0 - t1), c1y + c1r * sin(t0 - t1)))
	r1r2 = c1r - c2r
	if isclose(c1c2, abs(r1r2)):
		if r1r2 > 0.0:
			t1 = 0.0
		else:
			t1 = pi
		ps.append((c1x + c1r * cos(t0 + t1), c1y + c1r * sin(t0 + t1)))
	elif c1c2 > abs(r1r2):
		if r1r2 > 0.0:
			t1 = acos(r1r2 / c1c2)
		else:
			t1 = pi - acos(-r1r2 / c1c2)
		ps.append((c1x + c1r * cos(t0 + t1), c1y + c1r * sin(t0 + t1)))
		ps.append((c1x + c1r * cos(t0 - t1), c1y + c1r * sin(t0 - t1)))
	return ps
(c1x, c1y, c1r) = map(lambda x: float(x), input().split())
(c2x, c2y, c2r) = map(lambda x: float(x), input().split())
ps = tangent_points(c1x, c1y, c1r, c2x, c2y, c2r)
for p in sorted(ps):
	print('{:.6f} {:.6f}'.format(*p))


from math import acos, atan2, cos, hypot, isclose, pi, sin

def tangent_points(circle1, circle2):
	(x1, y1, r1) = circle1
	(x2, y2, r2) = circle2
	c1c2 = hypot(x2 - x1, y2 - y1)
	t0 = atan2(y2 - y1, x2 - x1)
	ps = []
	r1r2 = r1 + r2
	if isclose(c1c2, r1r2):
		ps.append((x1 + r1 * cos(t0), y1 + r1 * sin(t0)))
	elif c1c2 > r1r2:
		t1 = acos(r1r2 / c1c2)
		ps.append((x1 + r1 * cos(t0 + t1), y1 + r1 * sin(t0 + t1)))
		ps.append((x1 + r1 * cos(t0 - t1), y1 + r1 * sin(t0 - t1)))
	r1r2 = r1 - r2
	if isclose(c1c2, abs(r1r2)):
		if r1r2 > 0.0:
			t1 = 0.0
		else:
			t1 = pi
		ps.append((x1 + r1 * cos(t0 + t1), y1 + r1 * sin(t0 + t1)))
	elif c1c2 > abs(r1r2):
		if r1r2 > 0.0:
			t1 = acos(r1r2 / c1c2)
		else:
			t1 = pi - acos(-r1r2 / c1c2)
		ps.append((x1 + r1 * cos(t0 + t1), y1 + r1 * sin(t0 + t1)))
		ps.append((x1 + r1 * cos(t0 - t1), y1 + r1 * sin(t0 - t1)))
	return ps

def run():
	c1 = [int(i) for i in input().split()]
	c2 = [int(i) for i in input().split()]
	ps = tangent_points(c1, c2)
	for p in sorted(ps):
		print('{:.10f} {:.10f}'.format(*map(eliminate_minus_zero, p)))

def eliminate_minus_zero(f):
	if isclose(f, 0.0, abs_tol=1e-09):
		return 0.0
	else:
		return f
run()


import cmath
import itertools
import math
import os
import sys
from collections import defaultdict
if os.getenv('LOCAL'):
	sys.stdin = open('_in.txt', 'r')
sys.setrecursionlimit(10 ** 9)
INF = float('inf')
IINF = 10 ** 18
MOD = 10 ** 9 + 7
PI = cmath.pi
TAU = cmath.pi * 2
EPS = 1e-10

class Point:
	CCW_COUNTER_CLOCKWISE = 1
	CCW_CLOCKWISE = -1
	CCW_ONLINE_BACK = 2
	CCW_ONLINE_FRONT = -2
	CCW_ON_SEGMENT = 0

	def __init__(self, c: complex):
		self.c = c

	@property
	def x(self):
		return self.c.real

	@property
	def y(self):
		return self.c.imag

	@staticmethod
	def from_rect(x: float, y: float):
		return Point(complex(x, y))

	@staticmethod
	def from_polar(r: float, phi: float):
		return Point(cmath.rect(r, phi))

	def __add__(self, p):
		return Point(self.c + p.c)

	def __iadd__(self, p):
		self.c += p.c
		return self

	def __sub__(self, p):
		return Point(self.c - p.c)

	def __isub__(self, p):
		self.c -= p.c
		return self

	def __mul__(self, f: float):
		return Point(self.c * f)

	def __imul__(self, f: float):
		self.c *= f
		return self

	def __truediv__(self, f: float):
		return Point(self.c / f)

	def __itruediv__(self, f: float):
		self.c /= f
		return self

	def __repr__(self):
		return '({}, {})'.format(round(self.x, 10), round(self.y, 10))

	def __neg__(self):
		return Point(-self.c)

	def __eq__(self, p):
		return abs(self.c - p.c) < EPS

	def __abs__(self):
		return abs(self.c)

	@staticmethod
	def ccw(a, b, c):
		b = b - a
		c = c - a
		det = b.det(c)
		if det > EPS:
			return Point.CCW_COUNTER_CLOCKWISE
		if det < -EPS:
			return Point.CCW_CLOCKWISE
		if b.dot(c) < -EPS:
			return Point.CCW_ONLINE_BACK
		if c.norm() - b.norm() > EPS:
			return Point.CCW_ONLINE_FRONT
		return Point.CCW_ON_SEGMENT

	def dot(self, p):
		return self.x * p.x + self.y * p.y

	def det(self, p):
		return self.x * p.y - self.y * p.x

	def dist(self, p):
		return abs(self.c - p.c)

	def norm(self):
		return abs(self.c)

	def phase(self):
		return cmath.phase(self.c)

	def angle(self, p, q):
		return (cmath.phase(q.c - self.c) - cmath.phase(p.c - self.c) + PI) % TAU - PI

	def area(self, p, q):
		return abs((p - self).det(q - self) / 2)

	def projection_point(self, p, q, allow_outer=False):
		diff_q = q - p
		r = (self - p).dot(diff_q) / abs(diff_q)
		phase = diff_q.phase()
		ret = Point.from_polar(r, phase) + p
		if allow_outer or (p - ret).dot(q - ret) < EPS:
			return ret
		return None

	def reflection_point(self, p, q):
		r = abs(self - p)
		angle = p.angle(q, self)
		angle = (q - p).phase() - angle
		return Point.from_polar(r, angle) + p

	def on_segment(self, p, q, allow_side=True):
		if not allow_side and (self == p or self == q):
			return False
		return abs((p - self).det(q - self)) < EPS and (p - self).dot(q - self) < EPS

class Line:

	def __init__(self, a: float, b: float, c: float):
		self.a = a
		self.b = b
		self.c = c

	@staticmethod
	def from_gradient(grad: float, intercept: float):
		return Line(grad, -1, intercept)

	@staticmethod
	def from_segment(p1, p2):
		a = p2.y - p1.y
		b = p1.x - p2.x
		c = p2.y * (p2.x - p1.x) - p2.x * (p2.y - p1.y)
		return Line(a, b, c)

	@property
	def gradient(self):
		return INF if self.b == 0 else -self.a / self.b

	@property
	def intercept(self):
		return INF if self.b == 0 else -self.c / self.b

	def is_parallel_to(self, l):
		return abs(Point.from_rect(self.a, self.b).det(Point.from_rect(l.a, l.b))) < EPS

	def is_orthogonal_to(self, l):
		return abs(Point.from_rect(self.a, self.b).dot(Point.from_rect(l.a, l.b))) < EPS

	def intersection_point(self, l):
		(a1, b1, c1) = (self.a, self.b, self.c)
		(a2, b2, c2) = (l.a, l.b, l.c)
		det = a1 * b2 - a2 * b1
		if abs(det) < EPS:
			return None
		x = (b1 * c2 - b2 * c1) / det
		y = (a2 * c1 - a1 * c2) / det
		return Point.from_rect(x, y)

	def dist(self, p):
		raise NotImplementedError()

	def has_point(self, p):
		return abs(self.a * p.x + self.b * p.y + self.c) < EPS

class Segment:

	def __init__(self, p1, p2):
		self.p1 = p1
		self.p2 = p2

	def norm(self):
		return abs(self.p1 - self.p2)

	def phase(self):
		return (self.p2 - self.p1).phase()

	def is_parallel_to(self, s):
		return abs((self.p1 - self.p2).det(s.p1 - s.p2)) < EPS

	def is_orthogonal_to(self, s):
		return abs((self.p1 - self.p2).dot(s.p1 - s.p2)) < EPS

	def intersects_with(self, s, allow_side=True):
		if self.is_parallel_to(s):
			return s.p1.on_segment(self.p1, self.p2, allow_side) or s.p2.on_segment(self.p1, self.p2, allow_side) or self.p1.on_segment(s.p1, s.p2, allow_side) or self.p2.on_segment(s.p1, s.p2, allow_side)
		else:
			det_upper = EPS if allow_side else -EPS
			ok = True
			ok &= (self.p2 - self.p1).det(s.p1 - self.p1) * (self.p2 - self.p1).det(s.p2 - self.p1) < det_upper
			ok &= (s.p2 - s.p1).det(self.p1 - s.p1) * (s.p2 - s.p1).det(self.p2 - s.p1) < det_upper
			return ok

	def closest_point(self, p):
		d = (p - self.p1).dot(self.p2 - self.p1) / self.norm()
		if d < EPS:
			return self.p1
		if -EPS < d - self.norm():
			return self.p2
		return Point.from_polar(d, (self.p2 - self.p1).phase()) + self.p1

	def dist(self, p):
		return abs(p - self.closest_point(p))

	def dist_segment(self, s):
		if self.intersects_with(s):
			return 0.0
		return min(self.dist(s.p1), self.dist(s.p2), s.dist(self.p1), s.dist(self.p2))

	def has_point(self, p, allow_side=True):
		return p.on_segment(self.p1, self.p2, allow_side=allow_side)

class Polygon:

	def __init__(self, points):
		self.points = points

	def iter2(self):
		return zip(self.points, self.points[1:] + self.points[:1])

	def iter3(self):
		return zip(self.points, self.points[1:] + self.points[:1], self.points[2:] + self.points[:2])

	def area(self):
		dets = []
		for (p, q) in self.iter2():
			dets.append(p.det(q))
		return abs(math.fsum(dets)) / 2

	def is_convex(self, allow_straight=False, allow_collapsed=False):
		ccw = []
		for (a, b, c) in self.iter3():
			ccw.append(Point.ccw(a, b, c))
		ccw = set(ccw)
		if len(ccw) == 1:
			if ccw == {Point.CCW_CLOCKWISE}:
				return True
			if ccw == {Point.CCW_COUNTER_CLOCKWISE}:
				return True
		if allow_straight and len(ccw) == 2:
			if ccw == {Point.CCW_ONLINE_FRONT, Point.CCW_CLOCKWISE}:
				return True
			if ccw == {Point.CCW_ONLINE_FRONT, Point.CCW_COUNTER_CLOCKWISE}:
				return True
		if allow_collapsed and len(ccw) == 3:
			return ccw == {Point.CCW_ONLINE_FRONT, Point.CCW_ONLINE_BACK, Point.CCW_ON_SEGMENT}
		return False

	def has_point_on_edge(self, p):
		for (a, b) in self.iter2():
			if p.on_segment(a, b):
				return True
		return False

	def contains(self, p, allow_on_edge=True):
		angles = []
		for (a, b) in self.iter2():
			if p.on_segment(a, b):
				return allow_on_edge
			angles.append(p.angle(a, b))
		return abs(math.fsum(angles)) > EPS

	@staticmethod
	def convex_hull(points, allow_straight=False):
		points = points[:]
		points.sort(key=lambda p: (p.x, p.y))
		det_lower = -EPS if allow_straight else EPS
		sz = 0
		ret = [None] * (len(points) * 2)
		for p in points:
			while sz > 1 and (ret[sz - 1] - ret[sz - 2]).det(p - ret[sz - 1]) < det_lower:
				sz -= 1
			ret[sz] = p
			sz += 1
		floor = sz
		for p in reversed(points[:-1]):
			while sz > floor and (ret[sz - 1] - ret[sz - 2]).det(p - ret[sz - 1]) < det_lower:
				sz -= 1
			ret[sz] = p
			sz += 1
		ret = ret[:sz - 1]
		if allow_straight and len(ret) > len(points):
			ret = points
		return ret

	@staticmethod
	def diameter(points):
		points = Polygon.convex_hull(points, allow_straight=False)
		if len(points) == 1:
			return 0.0
		if len(points) == 2:
			return abs(points[0] - points[1])
		si = points.index(min(points, key=lambda p: (p.x, p.y)))
		sj = points.index(max(points, key=lambda p: (p.x, p.y)))
		n = len(points)
		ret = 0.0
		(i, j) = (si, sj)
		while i != sj or j != si:
			ret = max(ret, abs(points[i] - points[j]))
			ni = (i + 1) % n
			nj = (j + 1) % n
			if (points[ni] - points[i]).det(points[nj] - points[j]) > 0:
				j = nj
			else:
				i = ni
		return ret

	def convex_cut_by_line(self, line_p1, line_p2):
		n = len(self.points)
		line = Line.from_segment(line_p1, line_p2)
		on_line_points = []
		for (i, p) in enumerate(self.points):
			if line.has_point(p):
				on_line_points.append(i)
		has_on_line_edge = False
		if len(on_line_points) >= 3:
			has_on_line_edge = True
		elif len(on_line_points) == 2:
			has_on_line_edge = abs(on_line_points[0] - on_line_points[1]) in [1, n - 1]
		if has_on_line_edge:
			for p in self.points:
				ccw = Point.ccw(line_p1, line_p2, p)
				if ccw == Point.CCW_COUNTER_CLOCKWISE:
					return (Polygon(self.points[:]), None)
				if ccw == Point.CCW_CLOCKWISE:
					return (None, Polygon(self.points[:]))
		ret_lefts = []
		ret_rights = []
		d = line_p2 - line_p1
		for (p, q) in self.iter2():
			det_p = d.det(p - line_p1)
			det_q = d.det(q - line_p1)
			if det_p > -EPS:
				ret_lefts.append(p)
			if det_p < EPS:
				ret_rights.append(p)
			if det_p * det_q < -EPS:
				intersection = line.intersection_point(Line.from_segment(p, q))
				ret_lefts.append(intersection)
				ret_rights.append(intersection)
		l = Polygon(ret_lefts) if len(ret_lefts) > 1 else None
		r = Polygon(ret_rights) if len(ret_rights) > 1 else None
		return (l, r)

def closest_pair(points):
	assert len(points) >= 2

	def _rec(xsorted):
		n = len(xsorted)
		if n <= 2:
			return (xsorted[0].dist(xsorted[1]), (xsorted[0], xsorted[1]))
		if n <= 3:
			d = INF
			pair = None
			for (p, q) in itertools.combinations(xsorted, r=2):
				if p.dist(q) < d:
					d = p.dist(q)
					pair = (p, q)
			return (d, pair)
		(ld, lp) = _rec(xsorted[:n // 2])
		(rd, rp) = _rec(xsorted[n // 2:])
		if ld <= rd:
			d = ld
			ret_pair = lp
		else:
			d = rd
			ret_pair = rp
		mid_x = xsorted[n // 2].x
		mid_points = []
		for p in xsorted:
			if abs(p.x - mid_x) - d < -EPS:
				mid_points.append(p)
		mid_points.sort(key=lambda p: p.y)
		mid_n = len(mid_points)
		for i in range(mid_n - 1):
			j = i + 1
			p = mid_points[i]
			q = mid_points[j]
			while q.y - p.y - d < -EPS:
				pq_d = p.dist(q)
				if pq_d < d:
					d = pq_d
					ret_pair = (p, q)
				j += 1
				if j >= mid_n:
					break
				q = mid_points[j]
		return (d, ret_pair)
	return _rec(list(sorted(points, key=lambda p: p.x)))

def closest_pair_randomized(points):
	n = len(points)
	assert n >= 2
	if n == 2:
		return (points[0].dist(points[1]), (points[0], points[1]))
	import random
	points = points[:]
	random.shuffle(points)
	DELTA_XY = list(itertools.product([-1, 0, 1], repeat=2))
	grid = defaultdict(list)
	delta = INF
	dist = points[0].dist(points[1])
	ret_pair = (points[0], points[1])
	for i in range(2, n):
		if delta < EPS:
			return (0.0, ret_pair)
		if dist - delta < -EPS:
			delta = dist
			grid = defaultdict(list)
			for a in points[:i]:
				grid[a.x // delta, a.y // delta].append(a)
		else:
			p = points[i - 1]
			grid[p.x // delta, p.y // delta].append(p)
		p = points[i]
		dist = delta
		grid_x = p.x // delta
		grid_y = p.y // delta
		for (dx, dy) in DELTA_XY:
			for q in grid[grid_x + dx, grid_y + dy]:
				d = p.dist(q)
				if d - dist < -EPS:
					dist = d
					ret_pair = (p, q)
	return (min(delta, dist), ret_pair)

class Circle:

	def __init__(self, o, r):
		self.o = o
		self.r = r

	def __eq__(self, other):
		return self.o == other.o and abs(self.r - other.r) < EPS

	def ctc(self, c):
		if self.o == c.o:
			return INF if abs(self.r - c.r) < EPS else 0
		d = self.o.dist(c.o) - self.r - c.r
		if d > EPS:
			return 4
		elif d > -EPS:
			return 3
		elif d + min(self.r, c.r) * 2 > EPS:
			return 2
		elif d + min(self.r, c.r) * 2 > -EPS:
			return 1
		return 0

	def area(self):
		return self.r ** 2 * PI

	def intersection_points(self, other, allow_outer=False):
		if isinstance(other, Segment):
			return self.intersection_points_with_segment(other, allow_outer=allow_outer)
		if isinstance(other, Circle):
			return self.intersection_points_with_circle(other)
		raise NotImplementedError()

	def intersection_points_with_segment(self, s, allow_outer=False):
		projection_point = self.o.projection_point(s.p1, s.p2, allow_outer=True)
		dist = self.o.dist(projection_point)
		if dist - self.r > EPS:
			return []
		if dist - self.r > -EPS:
			if allow_outer or s.has_point(projection_point):
				return [projection_point]
			else:
				return []
		diff = Point.from_polar(math.sqrt(self.r ** 2 - dist ** 2), s.phase())
		ret1 = projection_point + diff
		ret2 = projection_point - diff
		ret = []
		if allow_outer or s.has_point(ret1):
			ret.append(ret1)
		if allow_outer or s.has_point(ret2):
			ret.append(ret2)
		return ret

	def intersection_points_with_circle(self, other):
		ctc = self.ctc(other)
		if not 1 <= ctc <= 3:
			return []
		if ctc == 3:
			return [Point.from_polar(self.r, (other.o - self.o).phase()) + self.o]
		if ctc == 1:
			if self.r > other.r:
				return [Point.from_polar(self.r, (other.o - self.o).phase()) + self.o]
			else:
				return [Point.from_polar(self.r, (self.o - other.o).phase()) + self.o]
		assert ctc == 2
		a = other.r
		b = self.r
		c = self.o.dist(other.o)
		cos_a = (b ** 2 + c ** 2 - a ** 2) / (2 * b * c)
		angle = math.acos(cos_a)
		phi = (other.o - self.o).phase()
		return [self.o + Point.from_polar(self.r, phi + angle), self.o + Point.from_polar(self.r, phi - angle)]

	def tangent_points_with_point(self, p):
		dist = self.o.dist(p)
		if dist - self.r < -EPS:
			return []
		if dist - self.r < EPS:
			return [Point(p.c)]
		a = math.sqrt(dist ** 2 - self.r ** 2)
		b = self.r
		c = dist
		cos_a = (b ** 2 + c ** 2 - a ** 2) / (2 * b * c)
		angle = math.acos(cos_a)
		phi = (p - self.o).phase()
		return [self.o + Point.from_polar(self.r, phi + angle), self.o + Point.from_polar(self.r, phi - angle)]

	def tangent_points_with_circle(self, other):
		ctc = self.ctc(other)
		if ctc > 4:
			raise ValueError('2つの円が同一です')
		if ctc == 0:
			return []
		if ctc == 1:
			return self.intersection_points_with_circle(other)
		assert ctc in (2, 3, 4)
		ret = []
		if abs(self.r - other.r) < EPS:
			phi = (other.o - self.o).phase()
			ret.append(self.o + Point.from_polar(self.r, phi + PI / 2))
			ret.append(self.o + Point.from_polar(self.r, phi - PI / 2))
		else:
			intersection = self.o + (other.o - self.o) / (self.r - other.r) * self.r
			ret += self.tangent_points_with_point(intersection)
		intersection = self.o + (other.o - self.o) / (self.r + other.r) * self.r
		ret += self.tangent_points_with_point(intersection)
		return ret

def round_point(p):
	return (round(p.x, 10) + 0, round(p.y, 10) + 0)
(x1, y1, r1) = list(map(int, sys.stdin.buffer.readline().split()))
(x2, y2, r2) = list(map(int, sys.stdin.buffer.readline().split()))
c1 = Circle(Point(complex(x1, y1)), r1)
c2 = Circle(Point(complex(x2, y2)), r2)
ans = c1.tangent_points_with_circle(c2)
for (x, y) in sorted(map(round_point, ans)):
	print('{:.10f} {:.10f}'.format(x, y))