Problem p02311 (C++) — buggy submission, verdict: Runtime Error

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <functional>
#include <iostream>
#include <vector>

using namespace std;

#define fst first
#define snd second
#define all(c) ((c).begin()), ((c).end())
#define TEST(x, a)                                                             \\
  {                                                                            \\
    auto y = (x);                                                              \\
    if (sign(y - a)) {                                                         \\
      cout << "line " << __LINE__ << #x << " = " << y << " != " << a << endl;  \\
      exit(-1);                                                                \\
    }                                                                          \\
  }

// implementation note: use EPS only this function
// usage note: check sign(x) < 0, sign(x) > 0, or sign(x) == 0
const double EPS = 1e-8;
int sign(double x) {
  const double EPS = 1e-8;
  if (x < -EPS)
    return -1;
  if (x > +EPS)
    return +1;
  return 0;
}
struct point {
  typedef double T;
  T x, y;
  point &operator+=(point p) {
    x += p.x;
    y += p.y;
    return *this;
  }
  point &operator-=(point p) {
    x -= p.x;
    y -= p.y;
    return *this;
  }
  point &operator*=(T a) {
    x *= a;
    y *= a;
    return *this;
  }
  point &operator/=(T a) { return *this *= (1.0 / a); }
  point operator-() const { return {-x, -y}; }
  bool operator==(point p) const { return !sign(x - p.x) && !sign(y - p.y); }
  bool operator<(point p) const {
    return x != p.x ? x < p.x : y < p.y;
  } // for sort
};
point operator+(point p, point q) { return p += q; }
point operator-(point p, point q) { return p -= q; }
point operator*(point::T a, point p) { return p *= a; }
point operator*(point p, point::T a) { return p *= a; }
point operator/(point p, point::T a) { return p /= a; }
point::T dot(point p, point q) { return p.x * q.x + p.y * q.y; }
point::T cross(point p, point q) {
  return p.x * q.y - p.y * q.x;
} // left turn > 0
point orth(point p) { return {-p.y, p.x}; }

istream &operator>>(istream &is, point &p) {
  is >> p.x >> p.y;
  return is;
}
ostream &operator<<(ostream &os, point &p) {
  os << "(" << p.x << "," << p.y << ")";
  return os;
}

struct line {
  point p, q;
};
bool operator==(line l, line m) {
  return !sign(cross(l.p - l.q, m.p - m.q)) &&
         !sign(cross(l.p - l.q, m.p - l.p));
}
struct segment {
  point p, q;
};
bool operator==(segment l, line m) {
  // do not consider the direction
  return (l.p == m.p && l.q == m.q) || (l.p == m.q && l.q == m.p);
}
struct circle {
  point p;
  point::T r;
};
bool operator==(circle c, circle d) { return c.p == d.p && !sign(c.r - d.r); }

//
// p is on the line l
//
vector<point> intersect(line l, point p) {
  if (sign(cross(l.p, l.q - p)) != 0)
    return {};
  return {p};
}
vector<point> intersect(point p, line l) { return intersect(l, p); }

vector<point> intersect(segment s, point p) {
  if (sign(cross(s.p - p, s.q - p)) != 0)
    return {};
  if (sign(dot(s.p - p, s.q - p)) > 0)
    return {}; // >  for strict intersect
  return {p};  // >= for weak intersect
}
vector<point> intersect(point p, segment s) { return intersect(s, p); }

//
// Crosspoint equation is
//   l.p + (l.q - l.p) t == m.p + (m.q - m.p) s ... (CP.1)
// Taking a cross product with (m.q - m.p), we have
//   (m.q - m.p) x (l.q - l.p) t == (m.q - m.p) x (m.p - l.p)
//   ~~~~~~~~~~~~a~~~~~~~~~~~~      ~~~~~~~~~~~~b~~~~~~~~~~~~
//
// If a != 0, these two lines have a proper crosspoint.
// If a == 0 and b == 0, these two lines are the same line
// thus any t gives a solution.
// Otherwise, these two lines are parallel.
//
vector<point> intersect(line l, line m) {
  auto a = cross(m.q - m.p, l.q - l.p);
  auto b = cross(l.p - m.p, l.q - l.p);
  if (sign(a) != 0)
    return {m.p + b / a * (m.q - m.p)}; // properly crossing
  if (sign(b) == 0)
    return {m.p, m.q}; // same line
  return {};           // disjoint parallel
}

//
// In CP.1, t must be in [0, 1]. Thus 0 <= b/a <= 1 is required.
// By assuming a > 0, it is equivalent to b >= 0 and b-a <= 0
//
vector<point> intersect(line l, segment s) {
  auto a = cross(s.q - s.p, l.q - l.p);
  auto b = cross(l.p - s.p, l.q - l.p);
  if (a < 0) {
    a *= -1;
    b *= -1;
  }
  if (sign(b) < 0 || sign(a - b) < 0)
    return {}; // no intersect
  if (sign(a) != 0)
    return {s.p + b / a * (s.q - s.p)}; // properly crossing
  if (sign(b) == 0)
    return {s.p, s.q}; // same line
  return {};           // disjoint parallel
}

// intersection of two segments
vector<point> intersect(segment s, segment t) {
  auto a = cross(s.q - s.p, t.q - t.p);
  auto b = cross(t.p - s.p, t.q - t.p);
  auto c = cross(s.q - s.p, s.p - t.p);
  if (a < 0) {
    a = -a;
    b = -b;
    c = -c;
  }
  if (sign(b) < 0 || sign(a - b) < 0 || sign(c) < 0 || sign(a - c) < 0)
    return {}; // disjoint
  if (sign(a) != 0)
    return {s.p + b / a * (s.q - s.p)}; // properly crossing
  vector<point> ps;                     // same line
  auto insert_if_possible = [&](point p) {
    for (auto q : ps)
      if (sign(dot(p - q, p - q)) == 0)
        return;
    ps.push_back(p);
  };
  if (sign(dot(s.p - t.p, s.q - t.p)) <= 0)
    insert_if_possible(t.p);
  if (sign(dot(s.p - t.q, s.q - t.q)) <= 0)
    insert_if_possible(t.q);
  if (sign(dot(t.p - s.p, t.q - s.p)) <= 0)
    insert_if_possible(s.p);
  if (sign(dot(t.p - s.q, t.q - s.q)) <= 0)
    insert_if_possible(s.q);
  return ps;
}

// reflected point with l
point reflection(point p, line l) {
  auto a = dot(l.p - l.q, l.p - l.q);
  auto b = dot(l.p - p, l.p - l.q);
  return 2 * (l.p + a / b * (l.q - l.p)) - p;
}

// closest point on l
point projection(point p, line l) {
  auto a = dot(l.p - l.q, l.p - l.q);
  auto b = dot(l.p - p, l.p - l.q);
  return l.p + a / b * (l.q - l.p);
}

// closest point on s
point projection(point p, segment s) {
  auto a = dot(s.p - s.q, s.p - s.q);
  auto b = dot(s.p - p, s.p - s.q);
  if (sign(b) < 0)
    return s.p;
  if (sign(a - b) < 0)
    return s.q;
  return s.p + b / a * (s.q - s.p);
}

// closest point on c
point projection(point p, circle c) {
  point v = p - c.p;
  return c.p + c.r * v / sqrt(dot(v, v));
}

point::T dist(point p, point q) { return sqrt(dot(p - q, p - q)); }
point::T dist(point p, line l) { return dist(p, projection(p, l)); }
point::T dist(line l, point p) { return dist(p, l); }
point::T dist(line l, line m) {
  if (sign(cross(l.p - l.q, m.p - m.q)))
    return 0; // cross
  return dist(l.p, m);
}
point::T dist(point p, segment s) { return dist(p, projection(p, s)); }
point::T dist(line l, segment s) {
  if (intersect(l, s).size())
    return 0;
  return min(dist(l, s.p), dist(l, s.q));
}
point::T dist(segment s, line l) { return dist(l, s); }
point::T dist(segment s, segment T) {
  if (intersect(s, T).size())
    return 0;
  return min({dist(s.p, T), dist(s.q, T), dist(T.p, s), dist(T.q, s)});
}

//
// intersection points of two circles
//
vector<point> intersect(circle c, circle d) {
  if (c.r < d.r)
    swap(c, d);
  auto pow2 = [](point::T a) { return a * a; };
  auto g = dot(c.p - d.p, c.p - d.p);
  if (sign(g) == 0) {
    if (sign(c.r - d.r) != 0)
      return {};
    return {{c.p.x + c.r, c.p.y}, {c.p.x, c.p.y + c.r}, {c.p.x - c.r, c.p.y}};
  }
  int inner = sign(g - pow2(c.r - d.r));
  int outer = sign(g - pow2(c.r + d.r));
  if (inner < 0 || outer > 0)
    return {};
  if (inner == 0)
    return {(c.r * d.p - d.r * c.p) / (c.r - d.r)};
  if (outer == 0)
    return {(c.r * d.p + d.r * c.p) / (c.r + d.r)};
  auto eta = (pow2(c.r) - pow2(d.r) + g) / (2 * g);
  auto mu = sqrt(pow2(c.r) / g - pow2(eta));
  point q = c.p + eta * (d.p - c.p), v = mu * orth(d.p - c.p);
  return {q + v, q - v};
}

// intersection of line and circle
vector<point> intersect(line l, circle c) {
  point u = l.q - l.p, v = l.p - c.p;
  auto a = dot(u, u), b = dot(u, v) / a, t = (dot(v, v) - c.r * c.r) / a;
  auto det = b * b - t;
  if (sign(det) < 0)
    return {}; // no solution
  if (sign(det) == 0)
    return {l.p - b * u};            // touch inner/outer
  return {l.p - (b + sqrt(det)) * u, // properly intersect
          l.p - (b - sqrt(det)) * u};
}
vector<point> intersect(circle c, line l) { return intersect(l, c); }
bool contains(circle c, point p) {
  return sign(dot(c.p - p, c.p - p) - c.r * c.r) <= 0;
}

//
// 0: not contained in
// 1: on the boundary
// 2: properly contained
//
int contains(vector<point> ps, point p) {
  bool in = false;
  for (int i = 0; i < ps.size(); ++i) {
    point a = ps[i] - p, b = ps[i + 1 == ps.size() ? 0 : i + 1] - p;
    if (a.y > b.y)
      swap(a, b);
    if (a.y <= 0 && 0 < b.y)
      if (cross(a, b) < 0)
        in = !in;
    if (sign(cross(a, b)) == 0 && sign(dot(a, b)) <= 0)
      return 1; // point on the edge
  }
  return in ? 2 : 0; // point in:out the polygon
}

int ccw(point a, point b, point c) {
  b = b - a;
  c = c - a;
  if (cross(b, c) > 0)
    return +1; // counter clockwise
  if (cross(b, c) < 0)
    return -1; // clockwise
  if (dot(b, c) < 0)
    return +2; // c--a--b on line
  if (dot(b, b) < dot(c, c))
    return -2; // a--b--c on line
  return 0;
}
//
// is a convex hull with the smallest number of points.
//
vector<point> convex_hull(vector<point> ps) {
  int n = ps.size(), k = 0;
  sort(all(ps));
  vector<point> ch(2 * n);
  auto cond = [&](point p, point q, point o) {
    int a = sign(cross(p - o, q - o)), b = sign(dot(p - o, q - o));
    return a < 0 || (a == 0 && b >= 0); // contains points on the edges
    // return sign(a) < 0; // does not contain points on the edges
  };
  for (int i = 0; i < n; ch[k++] = ps[i++]) // lower-hull
    while (k > 2 && cond(ch[k - 2], ch[k - 1], ps[i]))
      ++k;
  for (int i = n - 2, t = k; i >= 0; ch[k++] = ps[i--]) // upper-hull
    while (k > t && cond(ch[k - 2], ch[k - 1], ps[i]))
      ++k;
  ch.resize(k - 1);
  return ch;
}

point::T area(vector<point> ps) {
  if (ps.size() <= 2)
    return 0;
  auto a = cross(ps.back(), ps[0]);
  for (int i = 0; i + 1 < ps.size(); ++i)
    a += cross(ps[i], ps[i + 1]);
  return a / 2;
}

vector<point> convex_cut(vector<point> ps, line l) {
  vector<point> qs;
  for (int i = 0; i < ps.size(); ++i) {
    int j = (i == ps.size() - 1 ? 0 : i + 1);
    if (sign(cross(l.p - ps[i], l.q - ps[i])) >= 0)
      qs.push_back(ps[i]);
    if (sign(cross(l.p - ps[i], l.q - ps[i])) *
            sign(cross(l.p - ps[j], l.q - ps[j])) <
        0) {
      auto a = cross(ps[j] - ps[i], l.q - l.p);
      auto b = cross(l.p - ps[i], l.q - l.p);
      qs.push_back(ps[i] + b / a * (ps[j] - ps[i]));
    }
  }
  return qs;
}

circle three_point_circle(point p, point q, point r) {
  point u = orth(q - p), v = r - p;
  point o = (p + q + u * dot(r - q, v) / dot(u, v)) / 2;
  return {o, sqrt(dot(p - o, p - o))};
}

double quadraliteral_area(double a, double b, double c, double d) {
  double s = a + b + c + d;
  return sqrt((s - a) * (s - b) * (s - c) * (s - d)) / 4;
}
double triangle_area(double a, double b, double c) {
  return quadraliteral_area(a, b, c, 0);
}
double excircle_radius(double a, double b, double c) {
  return a * b * c / 4 / triangle_area(a, b, c);
}
double incircle_radius(double a, double b, double c) {
  return 2 * triangle_area(a, b, c) / (a + b + c);
}

//
// tangent line to from p to c
//
// Let q be a tangent point.
// The angle between q -- p -- c.p is
//   sin(t) = r/|p - c.p|.
// and the solution is
//   p + (c.p - p) * exp(\\pm it).
//
vector<line> tangent(point p, circle c) {
  point u = p - c.p, v = orth(u);
  auto g = dot(u, u) - c.r * c.r;
  if (sign(g) < 0)
    return {};
  if (sign(g) == 0)
    return {{p, p + v}};
  u = u * (c.r * c.r / dot(u, u));
  v = v * (c.r * sqrt(g) / dot(v, v));
  return {{p, c.p + u - v}, {p, c.p + u + v}};
}
vector<line> tangent(circle c, point p) { return tangent(p, c); }

vector<line> tangent(circle c, circle d) {
  if (c.r < d.r)
    swap(c, d);
  auto g = dot(c.p - d.p, c.p - d.p);
  if (sign(g) == 0)
    return {};                                  // same origin
  point u = (d.p - c.p) / sqrt(g), v = orth(u); // coordinate systems
  vector<line> ls;
  for (int s = +1; s >= -1; s -= 2) {
    auto h = (c.r + s * d.r) / sqrt(g); // = cos(theta)
    if (sign(1 - h * h) == 0) {         // touch inner/outer
      ls.push_back({c.p + c.r * u, c.p + c.r * (u + v)});
    } else if (sign(1 - h * h) > 0) { // properly intersect
      point uu = h * u, vv = sqrt(1 - h * h) * v;
      ls.push_back({c.p + c.r * (uu + vv), d.p - d.r * (uu + vv) * s});
      ls.push_back({c.p + c.r * (uu - vv), d.p - d.r * (uu - vv) * s});
    }
  }
  return ls;
}

void angular_sort(vector<point> &ps) {
  point o = {0, 0};
  auto comp = [&](point p, point q) {
    p = p - o;
    q = q - o;
    if (sign(p.y) != sign(q.y))
      return p.y > q.y;
    if (!sign(p.y) && !sign(q.y)) {
      if (sign(p.x) >= 0 || sign(q.x) >= 0)
        return p.y > q.y;
      else
        return p.x < q.x;
    }
    if (sign(cross(p, q)))
      return cross(p, q) < 0;
    return dot(p, p) > dot(q, q);
  };
  sort(all(ps));
}

/*
int maximum_points_on_a_line(vector<point> ps) {
  sort(all(ps)); // assume dx >= 0; if dx == 0 then dy >= 0
  int max_count = 0;
  for (int i = 0; i < ps.size(); ) {
    int k = 1;
    while (sign(norm(ps[i] - ps[i+k])) == 0) ++k;

    vector<point> slope;
    for (int j = i+1; j < ps.size(); ++j)
      slope.push_back(ps[j] - ps[i]);
    auto comp = [&](point p, point q) { return p.y * q.x < q.y * p.x; };
    sort(all(slope), comp);
    for (int i = 0, k; i < slope.size(); i += k) {
      for (k = 1; slope[i] == slope[i+k]; ++k);
      max_count = max(max_count, base + k);
    }
  }
  return max_count;
}
*/

point::T triangulate(vector<point> ps) {
  int n = ps.size();
  vector<int> next(n);
  for (int i = 0; i < n - 1; ++i)
    next[i] = i + 1;
  auto is_ear = [&](int i, int j, int k) {
    if (sign(cross(ps[j] - ps[i], ps[k] - ps[i])) <= 0)
      return false;
    for (int l = next[k]; l != i; l = next[l])
      if (sign(cross(ps[i] - ps[l], ps[j] - ps[l])) >= 0 &&
          sign(cross(ps[j] - ps[l], ps[k] - ps[l])) >= 0 &&
          sign(cross(ps[k] - ps[l], ps[i] - ps[l])) >= 0)
        return false;
    return true;
  };
  point::T area = 0;
  for (int i = 0; next[next[i]] != i;) {
    if (is_ear(i, next[i], next[next[i]])) {
      area += abs(cross(ps[next[i]] - ps[i], ps[next[next[i]]] - ps[i])) / 2;
      // cout << i << " " << next[i] << " " << next[next[i]] << endl;
      next[i] = next[next[i]];
    } else
      i = next[i];
  }
  return area;
}

// verify

void verify_intersectCC() {
  auto th = 3.141592653589 * rand() / (1.0 + RAND_MAX);
  auto dx = 1 - 2 * rand() / (1.0 + RAND_MAX);
  auto dy = 1 - 2 * rand() / (1.0 + RAND_MAX);
  auto S = [&](point p) {
    point::T c = cos(th), s = sin(th);
    p.x -= dx;
    p.y -= dy;
    return (point){c * p.x + s * p.y, -s * p.x + c * p.y};
  };
  auto T = [&](circle C) { return (circle){S(C.p), C.r}; };
  {
    circle C = {{0, 0}, 1};
    circle D = {{2, 0}, 1};
    TEST(intersect(T(C), T(D)).size(), 1); // touch outer
  }
  {
    circle C = {{0, 0}, 1};
    circle D = {{1, 0}, 1};
    TEST(intersect(T(C), T(D)).size(), 2); // properly intersect inner
  }
  {
    circle C = {{0, 0}, 2};
    circle D = {{1, 0}, 1};
    TEST(intersect(T(C), T(D)).size(), 1); // intersect inner
  }
  {
    circle C = {{0, 0}, 2};
    circle D = {{3, 0}, 2};
    TEST(intersect(T(C), T(D)).size(), 2); // properly intersect outer
  }
  {
    circle C = {{0, 0}, 3};
    circle D = {{1, 0}, 1};
    TEST(intersect(T(C), T(D)).size(), 0); // too close
  }
  {
    circle C = {{0, 0}, 1};
    circle D = {{3, 0}, 1};
    TEST(intersect(T(C), T(D)).size(), 0); // too far
  }
}

double urand() { return rand() / (1.0 + RAND_MAX); }
void verify_three_point_circle() {
  for (int iter = 0; iter < 100; ++iter) {
    point p = {urand(), urand()};
    point q = {urand(), urand()};
    point r = {urand(), urand()};
    circle c = three_point_circle(p, q, r);
    TEST(dot(c.p - p, c.p - p), dot(c.p - q, c.p - q));
    TEST(dot(c.p - p, c.p - p), dot(c.p - r, c.p - r));
  }
}

void verify_triangulate() {
  vector<point> ps;
  ps.push_back({0, 0});
  ps.push_back({2, 0});
  ps.push_back({2, 2});
  ps.push_back({1, 1});
  ps.push_back({0, 2});
  TEST(triangulate(ps), area(ps));
}

void verify_convex_cut() {
  int n;
  scanf("%d", &n);
  vector<point> ps(n);
  for (int i = 0; i < n; ++i) {
    scanf("%lf %lf", &ps[i].x, &ps[i].y);
  }
  int m;
  scanf("%d", &m);
  for (int i = 0; i < m; ++i) {
    line L;
    scanf("%lf %lf %lf %lf", &L.p.x, &L.p.y, &L.q.x, &L.q.y);
    vector<point> qs = convex_cut(ps, L);
    printf("%f\\n", area(qs));
  }
}
void verify_convex_cut2() {
  vector<point> ps = {{0., 0.}, {1., 0.}, {2., 0.}, {2., 1.},
                      {2., 2.}, {1., 2.}, {0., 2.}, {0., 1.}};
  line L = {{1, 0}, {1.5, 0}};
  vector<point> qs = convex_cut(ps, L);
  for (auto q : qs)
    cout << q << " ";
  cout << endl;
}
void verify_tangent() {
  point p;
  circle c;
  scanf("%lf %lf", &p.x, &p.y);
  scanf("%lf %lf %lf", &c.p.x, &c.p.y, &c.r);
  vector<point> ps;
  for (auto L : tangent(c, p)) {
    if (L.p == p)
      ps.push_back(L.q);
    else
      ps.push_back(L.p);
  }
  sort(all(ps));
  for (auto p : ps)
    printf("%.12f %.12f\\n", p.x + EPS, p.y + EPS);
}
void verify_tangentCC() {
  TEST(tangent({{-2.0, 0.0}, 2.0}, {{-2.0, 0.0}, 1.0}).size(), 0);
  TEST(tangent({{-2.0, 0.0}, 2.0}, {{-1.0, 0.0}, 1.0}).size(), 1);
  TEST(tangent({{-2.0, 0.0}, 2.0}, {{-0.5, 0.0}, 1.0}).size(), 2);
  TEST(tangent({{-2.0, 0.0}, 2.0}, {{+1.0, 0.0}, 1.0}).size(), 3);
  TEST(tangent({{-2.0, 0.0}, 2.0}, {{+2.0, 0.0}, 1.0}).size(), 4);
  TEST(tangent({{+2.0, 0.0}, 2.0}, {{+2.0, 0.0}, 1.0}).size(), 0);
  TEST(tangent({{+2.0, 0.0}, 2.0}, {{+1.0, 0.0}, 1.0}).size(), 1);
  TEST(tangent({{+2.0, 0.0}, 2.0}, {{+0.5, 0.0}, 1.0}).size(), 2);
  TEST(tangent({{+2.0, 0.0}, 2.0}, {{-1.0, 0.0}, 1.0}).size(), 3);
  TEST(tangent({{+2.0, 0.0}, 2.0}, {{-2.0, 0.0}, 1.0}).size(), 4);

  for (int iter = 0; iter < 100; ++iter) {
    circle c = {{urand(), urand()}, urand()};
    circle d = {{urand(), urand()}, urand()};
    for (line l : tangent(c, d)) {
      TEST(intersect(l, c).size(), 1);
      TEST(intersect(l, d).size(), 1);
    }
  }
}
void verify_tangentCC2() {
  circle c, d;
  cin >> c.p.x >> c.p.y >> c.r;
  cin >> d.p.x >> d.p.y >> d.r;
  vector<line> ls = tangent(c, d);
  vector<point> ps;
  for (line l : ls) {
    ps.push_back(intersect(l, c)[0]);
  }
  sort(all(ps));
  for (point p : ps) {
    double x = p.x;
    if (sign(x) == 0)
      x = 0;
    double y = p.y;
    if (sign(y) == 0)
      y = 0;
    printf("%.12f %.12f\\n", x, y);
  }
}

int main() {
  // verify_intersectCC();
  // verify_three_point_circle();
  // verify_triangulate();
  // verify_convex_cut2();
  // verify_tangent();
  // verify_tangentCC();
  verify_tangentCC2();
}

Error: WA

Fixed submission:

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <functional>
#include <iostream>
#include <vector>

using namespace std;

#define fst first
#define snd second
#define all(c) ((c).begin()), ((c).end())
#define TEST(x, a)                                                             \\
  {                                                                            \\
    auto y = (x);                                                              \\
    if (sign(y - a)) {                                                         \\
      cout << "line " << __LINE__ << #x << " = " << y << " != " << a << endl;  \\
      exit(-1);                                                                \\
    }                                                                          \\
  }

// implementation note: use EPS only this function
// usage note: check sign(x) < 0, sign(x) > 0, or sign(x) == 0
const double EPS = 1e-8;
int sign(double x) {
  const double EPS = 1e-8;
  if (x < -EPS)
    return -1;
  if (x > +EPS)
    return +1;
  return 0;
}
struct point {
  typedef double T;
  T x, y;
  point &operator+=(point p) {
    x += p.x;
    y += p.y;
    return *this;
  }
  point &operator-=(point p) {
    x -= p.x;
    y -= p.y;
    return *this;
  }
  point &operator*=(T a) {
    x *= a;
    y *= a;
    return *this;
  }
  point &operator/=(T a) { return *this *= (1.0 / a); }
  point operator-() const { return {-x, -y}; }
  bool operator==(point p) const { return !sign(x - p.x) && !sign(y - p.y); }
  bool operator<(point p) const {
    return x != p.x ? x < p.x : y < p.y;
  } // for sort
};
point operator+(point p, point q) { return p += q; }
point operator-(point p, point q) { return p -= q; }
point operator*(point::T a, point p) { return p *= a; }
point operator*(point p, point::T a) { return p *= a; }
point operator/(point p, point::T a) { return p /= a; }
point::T dot(point p, point q) { return p.x * q.x + p.y * q.y; }
point::T cross(point p, point q) {
  return p.x * q.y - p.y * q.x;
} // left turn > 0
point orth(point p) { return {-p.y, p.x}; }

istream &operator>>(istream &is, point &p) {
  is >> p.x >> p.y;
  return is;
}
ostream &operator<<(ostream &os, point &p) {
  os << "(" << p.x << "," << p.y << ")";
  return os;
}

struct line {
  point p, q;
};
bool operator==(line l, line m) {
  return !sign(cross(l.p - l.q, m.p - m.q)) &&
         !sign(cross(l.p - l.q, m.p - l.p));
}
struct segment {
  point p, q;
};
bool operator==(segment l, line m) {
  // do not consider the direction
  return (l.p == m.p && l.q == m.q) || (l.p == m.q && l.q == m.p);
}
struct circle {
  point p;
  point::T r;
};
bool operator==(circle c, circle d) { return c.p == d.p && !sign(c.r - d.r); }

//
// p is on the line l
//
vector<point> intersect(line l, point p) {
  if (sign(cross(l.p, l.q - p)) != 0)
    return {};
  return {p};
}
vector<point> intersect(point p, line l) { return intersect(l, p); }

vector<point> intersect(segment s, point p) {
  if (sign(cross(s.p - p, s.q - p)) != 0)
    return {};
  if (sign(dot(s.p - p, s.q - p)) > 0)
    return {}; // >  for strict intersect
  return {p};  // >= for weak intersect
}
vector<point> intersect(point p, segment s) { return intersect(s, p); }

//
// Crosspoint equation is
//   l.p + (l.q - l.p) t == m.p + (m.q - m.p) s ... (CP.1)
// Taking a cross product with (m.q - m.p), we have
//   (m.q - m.p) x (l.q - l.p) t == (m.q - m.p) x (m.p - l.p)
//   ~~~~~~~~~~~~a~~~~~~~~~~~~      ~~~~~~~~~~~~b~~~~~~~~~~~~
//
// If a != 0, these two lines have a proper crosspoint.
// If a == 0 and b == 0, these two lines are the same line
// thus any t gives a solution.
// Otherwise, these two lines are parallel.
//
vector<point> intersect(line l, line m) {
  auto a = cross(m.q - m.p, l.q - l.p);
  auto b = cross(l.p - m.p, l.q - l.p);
  if (sign(a) != 0)
    return {m.p + b / a * (m.q - m.p)}; // properly crossing
  if (sign(b) == 0)
    return {m.p, m.q}; // same line
  return {};           // disjoint parallel
}

//
// In CP.1, t must be in [0, 1]. Thus 0 <= b/a <= 1 is required.
// By assuming a > 0, it is equivalent to b >= 0 and b-a <= 0
//
vector<point> intersect(line l, segment s) {
  auto a = cross(s.q - s.p, l.q - l.p);
  auto b = cross(l.p - s.p, l.q - l.p);
  if (a < 0) {
    a *= -1;
    b *= -1;
  }
  if (sign(b) < 0 || sign(a - b) < 0)
    return {}; // no intersect
  if (sign(a) != 0)
    return {s.p + b / a * (s.q - s.p)}; // properly crossing
  if (sign(b) == 0)
    return {s.p, s.q}; // same line
  return {};           // disjoint parallel
}

// intersection of two segments
vector<point> intersect(segment s, segment t) {
  auto a = cross(s.q - s.p, t.q - t.p);
  auto b = cross(t.p - s.p, t.q - t.p);
  auto c = cross(s.q - s.p, s.p - t.p);
  if (a < 0) {
    a = -a;
    b = -b;
    c = -c;
  }
  if (sign(b) < 0 || sign(a - b) < 0 || sign(c) < 0 || sign(a - c) < 0)
    return {}; // disjoint
  if (sign(a) != 0)
    return {s.p + b / a * (s.q - s.p)}; // properly crossing
  vector<point> ps;                     // same line
  auto insert_if_possible = [&](point p) {
    for (auto q : ps)
      if (sign(dot(p - q, p - q)) == 0)
        return;
    ps.push_back(p);
  };
  if (sign(dot(s.p - t.p, s.q - t.p)) <= 0)
    insert_if_possible(t.p);
  if (sign(dot(s.p - t.q, s.q - t.q)) <= 0)
    insert_if_possible(t.q);
  if (sign(dot(t.p - s.p, t.q - s.p)) <= 0)
    insert_if_possible(s.p);
  if (sign(dot(t.p - s.q, t.q - s.q)) <= 0)
    insert_if_possible(s.q);
  return ps;
}

// reflected point with l
point reflection(point p, line l) {
  auto a = dot(l.p - l.q, l.p - l.q);
  auto b = dot(l.p - p, l.p - l.q);
  return 2 * (l.p + a / b * (l.q - l.p)) - p;
}

// closest point on l
point projection(point p, line l) {
  auto a = dot(l.p - l.q, l.p - l.q);
  auto b = dot(l.p - p, l.p - l.q);
  return l.p + a / b * (l.q - l.p);
}

// closest point on s
point projection(point p, segment s) {
  auto a = dot(s.p - s.q, s.p - s.q);
  auto b = dot(s.p - p, s.p - s.q);
  if (sign(b) < 0)
    return s.p;
  if (sign(a - b) < 0)
    return s.q;
  return s.p + b / a * (s.q - s.p);
}

// closest point on c
point projection(point p, circle c) {
  point v = p - c.p;
  return c.p + c.r * v / sqrt(dot(v, v));
}

point::T dist(point p, point q) { return sqrt(dot(p - q, p - q)); }
point::T dist(point p, line l) { return dist(p, projection(p, l)); }
point::T dist(line l, point p) { return dist(p, l); }
point::T dist(line l, line m) {
  if (sign(cross(l.p - l.q, m.p - m.q)))
    return 0; // cross
  return dist(l.p, m);
}
point::T dist(point p, segment s) { return dist(p, projection(p, s)); }
point::T dist(line l, segment s) {
  if (intersect(l, s).size())
    return 0;
  return min(dist(l, s.p), dist(l, s.q));
}
point::T dist(segment s, line l) { return dist(l, s); }
point::T dist(segment s, segment T) {
  if (intersect(s, T).size())
    return 0;
  return min({dist(s.p, T), dist(s.q, T), dist(T.p, s), dist(T.q, s)});
}

//
// intersection points of two circles
//
vector<point> intersect(circle c, circle d) {
  if (c.r < d.r)
    swap(c, d);
  auto pow2 = [](point::T a) { return a * a; };
  auto g = dot(c.p - d.p, c.p - d.p);
  if (sign(g) == 0) {
    if (sign(c.r - d.r) != 0)
      return {};
    return {{c.p.x + c.r, c.p.y}, {c.p.x, c.p.y + c.r}, {c.p.x - c.r, c.p.y}};
  }
  int inner = sign(g - pow2(c.r - d.r));
  int outer = sign(g - pow2(c.r + d.r));
  if (inner < 0 || outer > 0)
    return {};
  if (inner == 0)
    return {(c.r * d.p - d.r * c.p) / (c.r - d.r)};
  if (outer == 0)
    return {(c.r * d.p + d.r * c.p) / (c.r + d.r)};
  auto eta = (pow2(c.r) - pow2(d.r) + g) / (2 * g);
  auto mu = sqrt(pow2(c.r) / g - pow2(eta));
  point q = c.p + eta * (d.p - c.p), v = mu * orth(d.p - c.p);
  return {q + v, q - v};
}

// intersection of line and circle
vector<point> intersect(line l, circle c) {
  point u = l.q - l.p, v = l.p - c.p;
  auto a = dot(u, u), b = dot(u, v), t = dot(v, v) - c.r * c.r;
  if (b < 0) {
    a = -a;
    b = -b;
    t = -t;
  }
  auto det = b * b - a * t;
  if (sign(det) < 0)
    return {}; // no solution
  if (sign(det) == 0)
    return {l.p - b / a * u};            // touch inner/outer
  return {l.p - (b + sqrt(det)) / a * u, // properly intersect
          l.p - t / (b + sqrt(det)) * u};
}
vector<point> intersect(circle c, line l) { return intersect(l, c); }
bool contains(circle c, point p) {
  return sign(dot(c.p - p, c.p - p) - c.r * c.r) <= 0;
}

/*
vector<line> tangent(circle C, circle D) {
point::T d = abs(D.p - C.p);
  if (sign(d) == 0) return {}; // same origin
  point v = (D.p - C.p) / d;
  vector<line> ls;
  for (int s = -1; s <= 1; s += 2) {
  point::T c = abs(C.r - s*D.r) / d;
    if (sign(1 - c*c) == 0) {        // touch inner/outer
      point n = point(1,1);
      ls.push_back(line(C.p+C.r*v*n, C.p+C.r*v*conj(n)));
    } else if (sign(1 - c*c) > 0) {  // properly intersect
      point n = point(c, sqrt(1-c*c));
      ls.push_back(line(C.p-s*C.r*v*n,       D.p-D.r*v*n));
      ls.push_back(line(C.p-s*C.r*v*conj(n), D.p-D.r*v*conj(n)));
    }
  }
  return ls;
}
*/

//
// 0: not contained in
// 1: on the boundary
// 2: properly contained
//
int contains(vector<point> ps, point p) {
  bool in = false;
  for (int i = 0; i < ps.size(); ++i) {
    point a = ps[i] - p, b = ps[i + 1 == ps.size() ? 0 : i + 1] - p;
    if (a.y > b.y)
      swap(a, b);
    if (a.y <= 0 && 0 < b.y)
      if (cross(a, b) < 0)
        in = !in;
    if (sign(cross(a, b)) == 0 && sign(dot(a, b)) <= 0)
      return 1; // point on the edge
  }
  return in ? 2 : 0; // point in:out the polygon
}

int ccw(point a, point b, point c) {
  b = b - a;
  c = c - a;
  if (cross(b, c) > 0)
    return +1; // counter clockwise
  if (cross(b, c) < 0)
    return -1; // clockwise
  if (dot(b, c) < 0)
    return +2; // c--a--b on line
  if (dot(b, b) < dot(c, c))
    return -2; // a--b--c on line
  return 0;
}
//
// is a convex hull with the smallest number of points.
//
vector<point> convex_hull(vector<point> ps) {
  int n = ps.size(), k = 0;
  sort(all(ps));
  vector<point> ch(2 * n);
  auto cond = [&](point p, point q, point o) {
    int a = sign(cross(p - o, q - o)), b = sign(dot(p - o, q - o));
    return a < 0 || (a == 0 && b >= 0); // contains points on the edges
    // return sign(a) < 0; // does not contain points on the edges
  };
  for (int i = 0; i < n; ch[k++] = ps[i++]) // lower-hull
    while (k > 2 && cond(ch[k - 2], ch[k - 1], ps[i]))
      ++k;
  for (int i = n - 2, t = k; i >= 0; ch[k++] = ps[i--]) // upper-hull
    while (k > t && cond(ch[k - 2], ch[k - 1], ps[i]))
      ++k;
  ch.resize(k - 1);
  return ch;
}

point::T area(vector<point> ps) {
  if (ps.size() <= 2)
    return 0;
  auto a = cross(ps.back(), ps[0]);
  for (int i = 0; i + 1 < ps.size(); ++i)
    a += cross(ps[i], ps[i + 1]);
  return a / 2;
}

vector<point> convex_cut(vector<point> ps, line l) {
  vector<point> qs;
  for (int i = 0; i < ps.size(); ++i) {
    int j = (i == ps.size() - 1 ? 0 : i + 1);
    if (sign(cross(l.p - ps[i], l.q - ps[i])) >= 0)
      qs.push_back(ps[i]);
    if (sign(cross(l.p - ps[i], l.q - ps[i])) *
            sign(cross(l.p - ps[j], l.q - ps[j])) <
        0) {
      auto a = cross(ps[j] - ps[i], l.q - l.p);
      auto b = cross(l.p - ps[i], l.q - l.p);
      qs.push_back(ps[i] + b / a * (ps[j] - ps[i]));
    }
  }
  return qs;
}

circle three_point_circle(point p, point q, point r) {
  point u = orth(q - p), v = r - p;
  point o = (p + q + u * dot(r - q, v) / dot(u, v)) / 2;
  return {o, sqrt(dot(p - o, p - o))};
}

double quadraliteral_area(double a, double b, double c, double d) {
  double s = a + b + c + d;
  return sqrt((s - a) * (s - b) * (s - c) * (s - d)) / 4;
}
double triangle_area(double a, double b, double c) {
  return quadraliteral_area(a, b, c, 0);
}
double excircle_radius(double a, double b, double c) {
  return a * b * c / 4 / triangle_area(a, b, c);
}
double incircle_radius(double a, double b, double c) {
  return 2 * triangle_area(a, b, c) / (a + b + c);
}

//
// tangent line to from p to c
//
// Let q be a tangent point.
// The angle between q -- p -- c.p is
//   sin(t) = r/|p - c.p|.
// and the solution is
//   p + (c.p - p) * exp(\\pm it).
//
vector<line> tangent(point p, circle c) {
  point u = p - c.p, v = orth(u);
  auto g = dot(u, u) - c.r * c.r;
  if (sign(g) < 0)
    return {};
  if (sign(g) == 0)
    return {{p, p + v}};
  u = u * (c.r * c.r / dot(u, u));
  v = v * (c.r * sqrt(g) / dot(v, v));
  return {{p, c.p + u - v}, {p, c.p + u + v}};
}
vector<line> tangent(circle c, point p) { return tangent(p, c); }

vector<line> tangent(circle c, circle d) {
  if (c.r < d.r)
    swap(c, d);
  auto g = dot(c.p - d.p, c.p - d.p);
  if (sign(g) == 0)
    return {};                                  // same origin
  point u = (d.p - c.p) / sqrt(g), v = orth(u); // coordinate systems
  vector<line> ls;
  for (int s = +1; s >= -1; s -= 2) {
    auto h = (c.r + s * d.r) / sqrt(g); // = cos(theta)
    if (sign(1 - h * h) == 0) {         // touch inner/outer
      ls.push_back({c.p + c.r * u, c.p + c.r * (u + v)});
    } else if (sign(1 - h * h) > 0) { // properly intersect
      point uu = h * u, vv = sqrt(1 - h * h) * v;
      ls.push_back({c.p + c.r * (uu + vv), d.p - d.r * (uu + vv) * s});
      ls.push_back({c.p + c.r * (uu - vv), d.p - d.r * (uu - vv) * s});
    }
  }
  return ls;
}

void angular_sort(vector<point> &ps) {
  point o = {0, 0};
  auto comp = [&](point p, point q) {
    p = p - o;
    q = q - o;
    if (sign(p.y) != sign(q.y))
      return p.y > q.y;
    if (!sign(p.y) && !sign(q.y)) {
      if (sign(p.x) >= 0 || sign(q.x) >= 0)
        return p.y > q.y;
      else
        return p.x < q.x;
    }
    if (sign(cross(p, q)))
      return cross(p, q) < 0;
    return dot(p, p) > dot(q, q);
  };
  sort(all(ps));
}

/*
int maximum_points_on_a_line(vector<point> ps) {
  sort(all(ps)); // assume dx >= 0; if dx == 0 then dy >= 0
  int max_count = 0;
  for (int i = 0; i < ps.size(); ) {
    int k = 1;
    while (sign(norm(ps[i] - ps[i+k])) == 0) ++k;

    vector<point> slope;
    for (int j = i+1; j < ps.size(); ++j)
      slope.push_back(ps[j] - ps[i]);
    auto comp = [&](point p, point q) { return p.y * q.x < q.y * p.x; };
    sort(all(slope), comp);
    for (int i = 0, k; i < slope.size(); i += k) {
      for (k = 1; slope[i] == slope[i+k]; ++k);
      max_count = max(max_count, base + k);
    }
  }
  return max_count;
}
*/

point::T triangulate(vector<point> ps) {
  int n = ps.size();
  vector<int> next(n);
  for (int i = 0; i < n - 1; ++i)
    next[i] = i + 1;
  auto is_ear = [&](int i, int j, int k) {
    if (sign(cross(ps[j] - ps[i], ps[k] - ps[i])) <= 0)
      return false;
    for (int l = next[k]; l != i; l = next[l])
      if (sign(cross(ps[i] - ps[l], ps[j] - ps[l])) >= 0 &&
          sign(cross(ps[j] - ps[l], ps[k] - ps[l])) >= 0 &&
          sign(cross(ps[k] - ps[l], ps[i] - ps[l])) >= 0)
        return false;
    return true;
  };
  point::T area = 0;
  for (int i = 0; next[next[i]] != i;) {
    if (is_ear(i, next[i], next[next[i]])) {
      area += abs(cross(ps[next[i]] - ps[i], ps[next[next[i]]] - ps[i])) / 2;
      // cout << i << " " << next[i] << " " << next[next[i]] << endl;
      next[i] = next[next[i]];
    } else
      i = next[i];
  }
  return area;
}

// verify

void verify_intersectCC() {
  auto th = 3.141592653589 * rand() / (1.0 + RAND_MAX);
  auto dx = 1 - 2 * rand() / (1.0 + RAND_MAX);
  auto dy = 1 - 2 * rand() / (1.0 + RAND_MAX);
  auto S = [&](point p) {
    point::T c = cos(th), s = sin(th);
    p.x -= dx;
    p.y -= dy;
    return (point){c * p.x + s * p.y, -s * p.x + c * p.y};
  };
  auto T = [&](circle C) { return (circle){S(C.p), C.r}; };
  {
    circle C = {{0, 0}, 1};
    circle D = {{2, 0}, 1};
    TEST(intersect(T(C), T(D)).size(), 1); // touch outer
  }
  {
    circle C = {{0, 0}, 1};
    circle D = {{1, 0}, 1};
    TEST(intersect(T(C), T(D)).size(), 2); // properly intersect inner
  }
  {
    circle C = {{0, 0}, 2};
    circle D = {{1, 0}, 1};
    TEST(intersect(T(C), T(D)).size(), 1); // intersect inner
  }
  {
    circle C = {{0, 0}, 2};
    circle D = {{3, 0}, 2};
    TEST(intersect(T(C), T(D)).size(), 2); // properly intersect outer
  }
  {
    circle C = {{0, 0}, 3};
    circle D = {{1, 0}, 1};
    TEST(intersect(T(C), T(D)).size(), 0); // too close
  }
  {
    circle C = {{0, 0}, 1};
    circle D = {{3, 0}, 1};
    TEST(intersect(T(C), T(D)).size(), 0); // too far
  }
}

double urand() { return rand() / (1.0 + RAND_MAX); }
void verify_three_point_circle() {
  for (int iter = 0; iter < 100; ++iter) {
    point p = {urand(), urand()};
    point q = {urand(), urand()};
    point r = {urand(), urand()};
    circle c = three_point_circle(p, q, r);
    TEST(dot(c.p - p, c.p - p), dot(c.p - q, c.p - q));
    TEST(dot(c.p - p, c.p - p), dot(c.p - r, c.p - r));
  }
}

void verify_triangulate() {
  vector<point> ps;
  ps.push_back({0, 0});
  ps.push_back({2, 0});
  ps.push_back({2, 2});
  ps.push_back({1, 1});
  ps.push_back({0, 2});
  TEST(triangulate(ps), area(ps));
}

void verify_convex_cut() {
  int n;
  scanf("%d", &n);
  vector<point> ps(n);
  for (int i = 0; i < n; ++i) {
    scanf("%lf %lf", &ps[i].x, &ps[i].y);
  }
  int m;
  scanf("%d", &m);
  for (int i = 0; i < m; ++i) {
    line L;
    scanf("%lf %lf %lf %lf", &L.p.x, &L.p.y, &L.q.x, &L.q.y);
    vector<point> qs = convex_cut(ps, L);
    printf("%f\\n", area(qs));
  }
}
void verify_convex_cut2() {
  vector<point> ps = {{0., 0.}, {1., 0.}, {2., 0.}, {2., 1.},
                      {2., 2.}, {1., 2.}, {0., 2.}, {0., 1.}};
  line L = {{1, 0}, {1.5, 0}};
  vector<point> qs = convex_cut(ps, L);
  for (auto q : qs)
    cout << q << " ";
  cout << endl;
}
void verify_tangent() {
  point p;
  circle c;
  scanf("%lf %lf", &p.x, &p.y);
  scanf("%lf %lf %lf", &c.p.x, &c.p.y, &c.r);
  vector<point> ps;
  for (auto L : tangent(c, p)) {
    if (L.p == p)
      ps.push_back(L.q);
    else
      ps.push_back(L.p);
  }
  sort(all(ps));
  for (auto p : ps)
    printf("%.12f %.12f\\n", p.x + EPS, p.y + EPS);
}
void verify_tangentCC() {
  TEST(tangent({{-2.0, 0.0}, 2.0}, {{-2.0, 0.0}, 1.0}).size(), 0);
  TEST(tangent({{-2.0, 0.0}, 2.0}, {{-1.0, 0.0}, 1.0}).size(), 1);
  TEST(tangent({{-2.0, 0.0}, 2.0}, {{-0.5, 0.0}, 1.0}).size(), 2);
  TEST(tangent({{-2.0, 0.0}, 2.0}, {{+1.0, 0.0}, 1.0}).size(), 3);
  TEST(tangent({{-2.0, 0.0}, 2.0}, {{+2.0, 0.0}, 1.0}).size(), 4);
  TEST(tangent({{+2.0, 0.0}, 2.0}, {{+2.0, 0.0}, 1.0}).size(), 0);
  TEST(tangent({{+2.0, 0.0}, 2.0}, {{+1.0, 0.0}, 1.0}).size(), 1);
  TEST(tangent({{+2.0, 0.0}, 2.0}, {{+0.5, 0.0}, 1.0}).size(), 2);
  TEST(tangent({{+2.0, 0.0}, 2.0}, {{-1.0, 0.0}, 1.0}).size(), 3);
  TEST(tangent({{+2.0, 0.0}, 2.0}, {{-2.0, 0.0}, 1.0}).size(), 4);

  for (int iter = 0; iter < 100; ++iter) {
    circle c = {{urand(), urand()}, urand()};
    circle d = {{urand(), urand()}, urand()};
    for (line l : tangent(c, d)) {
      TEST(intersect(l, c).size(), 1);
      TEST(intersect(l, d).size(), 1);
    }
  }
}
void verify_tangentCC2() {
  circle c, d;
  cin >> c.p.x >> c.p.y >> c.r;
  cin >> d.p.x >> d.p.y >> d.r;
  vector<line> ls = tangent(c, d);
  vector<point> ps;
  for (line l : ls)
    ps.push_back(intersect(l, c)[0]);
  sort(all(ps));
  for (point p : ps) {
    double x = p.x;
    if (sign(x) == 0)
      x = 0;
    double y = p.y;
    if (sign(y) == 0)
      y = 0;
    printf("%.12f %.12f\\n", x, y);
  }
}

int main() {
  // verify_intersectCC();
  // verify_three_point_circle();
  // verify_triangulate();
  // verify_convex_cut2();
  // verify_tangent();
  // verify_tangentCC();
  verify_tangentCC2();
}