def _test_square_roots(self, p):
        all_squares = set()
        not_squares = set(range(1, p))
        for x in xrange(1, p):
            all_squares.add((x, pow(x, 2, p)))

        for x, xx in all_squares:
            self.assertTrue(x in sqrt_modp(xx, p))

            if xx in not_squares:
                not_squares.remove(xx)

        for x in not_squares:
            self.assertEquals([], sqrt_modp(x, p))
    def get_x(self, y):
        result = []

        # HACK: Instead of brute forcing the square roots pick the right one directly.
        top = sqrt_modp((y**2 - self.c**2) % self.gf.p, self.gf.p) + sqrt_modp(-(y**2 - self.c**2) % self.gf.p, self.gf.p)
        bottom = sqrt_modp((self.c**2 * self.d * y**2 - 1) % self.gf.p, self.gf.p) + sqrt_modp(-(self.c**2 * self.d * y**2 - 1) % self.gf.p, self.gf.p)

        for t in top:
            for b in bottom:
                x = self.gf.div(t, b)

                if self.point_on_curve((x, y)):
                    result.append((x, y))
                if self.point_on_curve((-x % self.gf.p, y)):
                    result.append((-x % self.gf.p, y))

        return list(set(result))
    def get_x(self, y):
        # ax^2 + y^2 = 1 + dx^2y^2
        # x^2 (a - 2*y^2) = 1 - y^2

        result = []

        top = sqrt_modp(1 - y**2, self.gf.p)
        bottom = sqrt_modp(self.a - self.d * y**2, self.gf.p)
        for t in top:
            for b in bottom:
                x = self.gf.div(t, b)

                if self.point_on_curve((x, y)):
                    result.append((x, y))
                if self.point_on_curve((-x % self.gf.p, y)):
                    result.append((-x % self.gf.p, y))

        return list(set(result))
    def get_x(self, y):
        # ax^2 + y^2 = 1 + dx^2y^2
        # x^2 (a - 2*y^2) = 1 - y^2

        result = []

        top = sqrt_modp(1 - y**2, self.gf.p)
        bottom = sqrt_modp(self.a - self.d * y**2, self.gf.p)
        for t in top:
            for b in bottom:
                x = self.gf.div(t, b)

                if self.point_on_curve((x, y)):
                    result.append((x, y))
                if self.point_on_curve((-x % self.gf.p, y)):
                    result.append((-x % self.gf.p, y))

        return list(set(result))
    def __init__(self, c, d, field):
        assert c == 1
        self.c = c
        self.d = d
        self.gf = field

        if self.gf.mul(d, 1-d) == 0:
            raise ValueError('invalid params')

        if sqrt_modp(d, self.gf.p):
            print 'WARNING: Edwards curve not complete'
    def __init__(self, c, d, field):
        assert c == 1
        self.c = c
        self.d = d
        self.gf = field

        if self.gf.mul(d, 1 - d) == 0:
            raise ValueError('invalid params')

        if sqrt_modp(d, self.gf.p):
            print 'WARNING: Edwards curve not complete'
    def map_random_to_point(self, r):
        sqrt = lambda a: numbertheory.sqrt_modp(a, self.curve.gf.p)
        div = self.curve.gf.div
        sub = self.curve.gf.sub
        mul = self.curve.gf.mul

        v = div(-self.curve.a, 1 + self.u*r**2)
        epsilon = numbertheory.legendre_symbol(v**3 + self.curve.a*v**2 + self.curve.b*v, self.curve.gf.p)
        x = sub(epsilon*v, div((1 - epsilon)*self.curve.a, 2))
        y = mul(-epsilon, sqrt(x**3 + self.curve.a*x**2 + self.curve.b*x)[0]) # XXX: First

        return (x, y)
    def get_x(self, y):
        result = []

        # HACK: Instead of brute forcing the square roots pick the right one directly.
        top = sqrt_modp((y**2 - self.c**2) % self.gf.p, self.gf.p) + sqrt_modp(
            -(y**2 - self.c**2) % self.gf.p, self.gf.p)
        bottom = sqrt_modp(
            (self.c**2 * self.d * y**2 - 1) % self.gf.p,
            self.gf.p) + sqrt_modp(
                -(self.c**2 * self.d * y**2 - 1) % self.gf.p, self.gf.p)

        for t in top:
            for b in bottom:
                x = self.gf.div(t, b)

                if self.point_on_curve((x, y)):
                    result.append((x, y))
                if self.point_on_curve((-x % self.gf.p, y)):
                    result.append((-x % self.gf.p, y))

        return list(set(result))
    def map_point_to_random(self, P):
        x, y = P

        sqrt = lambda a: numbertheory.sqrt_modp(a, self.curve.gf.p)
        div = self.curve.gf.div

        if y <= ((self.curve.gf.p - 1) / 2):
            r = sqrt(div(-x, (x + self.curve.a) * self.u))
        else:
            r = sqrt(div(-(x + self.curve.a), x * self.u))

        # XXX: First
        return r[0]
    def get_y(self, x):
        """Returns a list of the y-coordinates on the curve at given x."""

        yy = self.gf.normalize(x**3 + self.a*x + self.b)

        sqrs = sqrt_modp(yy, self.gf.p)

        result = []
        for y in sqrs:
            # TODO: check inverted point?
            if self.point_on_curve((x, y)):
                result.append((x, y))
        return result
    def map_point_to_random(self, P):
        x, y = P

        sqrt = lambda a: numbertheory.sqrt_modp(a, self.curve.gf.p)
        div = self.curve.gf.div

        if y <= ((self.curve.gf.p - 1) / 2):
            r = sqrt(div(-x, (x + self.curve.a)*self.u))
        else:
            r = sqrt(div(-(x + self.curve.a), x*self.u))

        # XXX: First
        return r[0]
    def get_y(self, x):
        """Returns a list of the y-coordinates on the curve at given x."""

        yy = self.gf.normalize(x**3 + self.a * x + self.b)

        sqrs = sqrt_modp(yy, self.gf.p)

        result = []
        for y in sqrs:
            # TODO: check inverted point?
            if self.point_on_curve((x, y)):
                result.append((x, y))
        return result
    def map_random_to_point(self, r):
        sqrt = lambda a: numbertheory.sqrt_modp(a, self.curve.gf.p)
        div = self.curve.gf.div
        sub = self.curve.gf.sub
        mul = self.curve.gf.mul

        v = div(-self.curve.a, 1 + self.u * r**2)
        epsilon = numbertheory.legendre_symbol(
            v**3 + self.curve.a * v**2 + self.curve.b * v, self.curve.gf.p)
        x = sub(epsilon * v, div((1 - epsilon) * self.curve.a, 2))
        y = mul(-epsilon,
                sqrt(x**3 + self.curve.a * x**2 +
                     self.curve.b * x)[0])  # XXX: First

        return (x, y)