diff --git a/diff.cpp b/diff.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5eb689fb103bb87dc30b920a1ce33ebee35fb9f5
--- /dev/null
+++ b/diff.cpp
@@ -0,0 +1,100 @@
+#include <iostream>
+#include <algorithm>
+#include <cmath>
+#include "simple/file.hpp"
+#include "simple/geom/vector.hpp"
+#include "simple/support/arithmetic.hpp"
+
+using namespace simple::file;
+
+using index_type = simple::geom::vector<size_t, 2>;
+using double_buffer = std::pair<buffer<>, buffer<>>;
+
+index_type get_size(const double_buffer& buffers) // NOTE: can be generalized to N dimensions
+{
+	return index_type(buffers.first.size(), buffers.second.size());
+}
+
+bool diff_at(const double_buffer& buffers, index_type position) // NOTE: can be generalized to N dimensions
+{
+	return buffers.first[position.x()] != buffers.second[position.y()];
+}
+
+// NOTE: this is almost std::find_if, except the != bound comparison is not sufficient in this case... such a shame... i must be missing something...
+index_type find_change(const double_buffer& buffers, index_type start = index_type::zero())
+{
+	auto size = get_size(buffers);
+	while(start < size)
+	{
+		if(diff_at(buffers, start))
+			break;
+		++start;
+	}
+	return start;
+}
+
+// NOTE: could be generalized to N dimensions... not trivial and no obvious gain
+index_type measure_change(const double_buffer& buffers, index_type start)
+{
+	auto distance = get_size(buffers) - start;
+
+	auto minmax = std::minmax_element(distance.begin(), distance.end());
+	auto min_index = index_type::unit(minmax.first - distance.begin());
+	auto max_index = index_type::unit(minmax.second - distance.begin());
+
+	size_t change_size = 1;
+	auto change = max_index * change_size;
+	auto step = - max_index + min_index;
+	while(change < distance)
+	{
+		do
+		{
+			if(!diff_at(buffers, start + change))
+				return change;
+			change += step;
+		}
+		while(change < distance);
+
+		++change_size;
+		size_t excess; // NOTE: don't you hate it when edge cases are not cleanly handled by the main loop?... must figure this out...
+		if(simple::support::sub_overflow(excess, change_size, *minmax.second - 1))
+			excess = 0;
+		change = max_index * (change_size - excess) + min_index * excess;
+	}
+	return distance;
+}
+
+void showChange(index_type position, index_type change)
+{
+	std::cout << "--------\n";
+	for(size_t i = 0; i < index_type::dimensions; ++i)
+		std::cout << position[i] << ":" << change[i] << '\n';
+}
+
+int main(int argc, char const* argv[])
+{
+	if(argc <= 2)
+	{
+		std::cerr << "Need 2 parameters!" << '\n';
+		return -1;
+	}
+
+	const auto buffers = std::make_pair(
+			dump(bropex(argv[1])),
+			dump(bropex(argv[2])) );
+	auto size = get_size(buffers);
+
+	auto it = index_type::zero();
+	while(it = find_change(buffers, it), it < size)
+	{
+		auto change = measure_change(buffers, it);
+		showChange(it, change);
+		it += change;
+	}
+
+	auto change = size - it;
+	if(index_type::zero() != change)
+		showChange(it, change);
+
+	return 0;
+}