@NonNull
	public ECPoint add(@NonNull final ECPoint b) {
		if (isInfinity()) {
			return b;
		}

		if (b.isInfinity()) {
			return this;
		}

		// Check if b = this or b = -this
		if (x.equals(b.x)) {
			if (y.equals(b.y)) {
				// this = b, i.e. this must be doubled
				return twice();
			}

			// this = -b, i.e. the result is the point at infinity
			return O;
		}

		final ECFieldElement gamma = b.y.subtract(y).divide(b.x.subtract(x));

		final ECFieldElement x3 = gamma.square().subtract(x).subtract(b.x);
		final ECFieldElement y3 = gamma.multiply(x.subtract(x3)).subtract(y);

		return new ECPoint(x3, y3);
	}