import java.io.*;
import java.util.*;

public class sword_ak {
	final static double EPS = 1e-6;
	final static double BOUND = 1e9;

	static class Point {
		double x, y;

		public Point(double x, double y) {
			if (x < -BOUND || x > BOUND || y < -BOUND || y > BOUND) {
				throw new AssertionError("(" + x + ", " + y + ") is bad point");
			}
			this.x = x;
			this.y = y;
		}

		public boolean equals(Point p) {
			return Math.abs(x - p.x) < EPS && Math.abs(y - p.y) < EPS;
		}

		double distTo(Point p) {
			return Math.sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y));
		}

		@Override
		public String toString() {
			return String.format("%.10f %.10f", x, y);
		}
	}

	static class Segment {
		Point[] p;

		public Segment(Point a, Point b) {
			p = new Point[] { a, b };
		}

		boolean equals(Segment s) {
			return (p[0].equals(s.p[0]) && p[1].equals(s.p[1]))
					|| (p[1].equals(s.p[0]) && p[0].equals(s.p[1]));
		}

		double length() {
			return p[0].distTo(p[1]);
		}

		@Override
		public String toString() {
			return p[0] + " " + p[1];
		}
	}
	
	// Какая-то из точек пересечения окружностей радиуса len с центрами p1 и p2
	Point circlesIntersect(Point p1, Point p2) { 
		Point mid = new Point((p1.x + p2.x) / 2, (p1.y + p2.y) / 2);
		double h = Math.sqrt(len * len - p1.distTo(mid) * p1.distTo(mid));
		double dx = p2.y - p1.y;
		double dy = p1.x - p2.x;
		double newDX = dx / Math.sqrt(dx * dx + dy * dy) * h;
		double newDY = dy / Math.sqrt(dx * dx + dy * dy) * h;
		return new Point(mid.x + newDX, mid.y + newDY);
	}
	
	Segment doStep(Segment s2) {
		// Ответ~--- один ход
		for (int i = 0; i < 2; i++) {
			for (int j = 0; j < 2; j++) {
				if (s1.p[i].equals(s2.p[j])) {
					return s1;
				}
			}
		}
		// Ответ~--- два хода
		for (int i = 0; i < 2; i++) {
			for (int j = 0; j < 2; j++) {
				if (Math.abs(s1.p[j].distTo(s2.p[i]) - len) < EPS) { // Оставшиеся вершины не совпадают по прошлому условию
					return new Segment(s2.p[i], s1.p[j]);
				}
			}
		}
		// Ответ~--- три хода
		for (int i = 0; i < 2; i++) {
			for (int j = 0; j < 2; j++) {
				if (s1.p[j].distTo(s2.p[i]) < 2 * len) {
					return new Segment(s2.p[i], circlesIntersect(s1.p[j], s2.p[i]));
				}
			}
		}
		// Ответ~--- три хода
		for (int i = 0; i < 2; i++) {
			for (int j = 0; j < 2; j++) {
				if (s1.p[j].distTo(s2.p[i]) < len) { // Тут без EPS, ибо равенвтво отсеклось в прошлом 
					return new Segment(s2.p[i], circlesIntersect(s1.p[j], s2.p[i]));
				}
			}
		}
		// Ответ~--- много ходов
		Point p1 = null, p3 = null;
		double min = Double.MAX_VALUE;
 		for (int i = 0; i < 2; i++) {
			for (int j = 0; j < 2; j++) {
				if (s2.p[i].distTo(s1.p[j]) < min) {
					min = s2.p[i].distTo(s1.p[j]);
					p1 = s1.p[j];
					p3 = s2.p[i];
				}
			}
		}
 		
 		double dx = p1.x - p3.x;
 		double dy = p1.y - p3.y;
 		double newDX = dx / Math.sqrt(dx * dx + dy * dy) * len;
 		double newDY = dy / Math.sqrt(dx * dx + dy * dy) * len;
 		return new Segment(p3, new Point(p3.x + newDX, p3.y + newDY));
 		
	}

	Segment s1;
	double len;

	void solve() {
		int x, y;
		s1 = new Segment(new Point(in.nextInt(), in.nextInt()),
				new Point(in.nextInt(), in.nextInt()));
		Segment s2 = new Segment(new Point(in.nextInt(), in.nextInt()),
				new Point(in.nextInt(), in.nextInt()));
		len = s1.length();
		out.println(s2);
		while (!s2.equals(s1)) {
			s2 = doStep(s2);
			out.println(s2);
		}
	}

	static Scanner in;
	static PrintWriter out;

	public static void main(String[] args) throws FileNotFoundException {
		Locale.setDefault(Locale.US);
		in = new Scanner(new FileReader(new File("sword.in")));
		out = new PrintWriter("sword.out");
		new sword_ak().solve();
		out.close();
	}
}
