Doubles this point.

        Returns:
            JacobianPoint: The point corresponding to `2 * self`.

def double(self):
        """
        Doubles this point.

        Returns:
            JacobianPoint: The point corresponding to `2 * self`.
        """
        X1, Y1, Z1 = self.X, self.Y, self.Z

        if Y1 == 0:
            return POINT_AT_INFINITY
        S = (4 * X1 * Y1 ** 2) % self.P
        M = (3 * X1 ** 2 + self.a * Z1 ** 4) % self.P
        X3 = (M ** 2 - 2 * S) % self.P
        Y3 = (M * (S - X3) - 8 * Y1 ** 4) % self.P
        Z3 = (2 * Y1 * Z1) % self.P
        return JacobianPoint(X3, Y3, Z3)