//        SECP256K1_INLINE static int secp256k1_fe_equal_var(const secp256k1_fe* a, const secp256k1_fe* b)
        //        {
        //            secp256k1_fe na;
        //            secp256k1_fe_negate(na, a, 1);
        //            secp256k1_fe_add(na, b);
        //            return secp256k1_fe_normalizes_to_zero_var(na);
        //        }

        public static bool secp256k1_fe_sqrt(secp256k1_fe r, secp256k1_fe a)
        {
            /** Given that p is congruent to 3 mod 4, we can compute the square root of
             *  a mod p as the (p+1)/4'th power of a.
             *
             *  As (p+1)/4 is an even number, it will have the same result for a and for
             *  (-a). Only one of these two numbers actually has a square root however,
             *  so we test at the end by squaring and comparing to the input.
             *  Also because (p+1)/4 is an even number, the computed square root is
             *  itself always a square (a ** ((p+1)/4) is the square of a ** ((p+1)/8)).
             */
            secp256k1_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1;
            int          j;

            /** The binary representation of (p + 1)/4 has 3 blocks of 1s, with lengths in
             *  { 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block:
             *  1, [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223]
             */
            x2 = new secp256k1_fe();
            secp256k1_fe_sqr(x2, a);
            secp256k1_fe_mul(x2, x2, a);

            x3 = new secp256k1_fe();
            secp256k1_fe_sqr(x3, x2);
            secp256k1_fe_mul(x3, x3, a);

            x6 = x3.Clone();
            for (j = 0; j < 3; j++)
            {
                secp256k1_fe_sqr(x6, x6);
            }
            secp256k1_fe_mul(x6, x6, x3);

            x9 = x6.Clone();
            for (j = 0; j < 3; j++)
            {
                secp256k1_fe_sqr(x9, x9);
            }
            secp256k1_fe_mul(x9, x9, x3);

            x11 = x9.Clone();
            for (j = 0; j < 2; j++)
            {
                secp256k1_fe_sqr(x11, x11);
            }
            secp256k1_fe_mul(x11, x11, x2);

            x22 = x11.Clone();
            for (j = 0; j < 11; j++)
            {
                secp256k1_fe_sqr(x22, x22);
            }
            secp256k1_fe_mul(x22, x22, x11);

            x44 = x22.Clone();
            for (j = 0; j < 22; j++)
            {
                secp256k1_fe_sqr(x44, x44);
            }
            secp256k1_fe_mul(x44, x44, x22);

            x88 = x44.Clone();
            for (j = 0; j < 44; j++)
            {
                secp256k1_fe_sqr(x88, x88);
            }
            secp256k1_fe_mul(x88, x88, x44);

            x176 = x88.Clone();
            for (j = 0; j < 88; j++)
            {
                secp256k1_fe_sqr(x176, x176);
            }
            secp256k1_fe_mul(x176, x176, x88);

            x220 = x176.Clone();
            for (j = 0; j < 44; j++)
            {
                secp256k1_fe_sqr(x220, x220);
            }
            secp256k1_fe_mul(x220, x220, x44);

            x223 = x220.Clone();
            for (j = 0; j < 3; j++)
            {
                secp256k1_fe_sqr(x223, x223);
            }
            secp256k1_fe_mul(x223, x223, x3);

            /* The final result is then assembled using a sliding window over the blocks. */

            t1 = x223.Clone();
            for (j = 0; j < 23; j++)
            {
                secp256k1_fe_sqr(t1, t1);
            }
            secp256k1_fe_mul(t1, t1, x22);
            for (j = 0; j < 6; j++)
            {
                secp256k1_fe_sqr(t1, t1);
            }
            secp256k1_fe_mul(t1, t1, x2);
            secp256k1_fe_sqr(t1, t1);
            secp256k1_fe_sqr(r, t1);

            /* Check that a square root was actually calculated */

            secp256k1_fe_sqr(t1, r);
            return(secp256k1_fe_equal(t1, a));
        }
        public static void secp256k1_fe_inv(secp256k1_fe r, secp256k1_fe a)
        {
            secp256k1_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1;
            int          j;

            /** The binary representation of (p - 2) has 5 blocks of 1s, with lengths in
             *  { 1, 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block:
             *  [1], [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223]
             */
            x2 = new secp256k1_fe();
            secp256k1_fe_sqr(x2, a);
            secp256k1_fe_mul(x2, x2, a);

            x3 = new secp256k1_fe();
            secp256k1_fe_sqr(x3, x2);
            secp256k1_fe_mul(x3, x3, a);

            x6 = x3.Clone();
            for (j = 0; j < 3; j++)
            {
                secp256k1_fe_sqr(x6, x6);
            }
            secp256k1_fe_mul(x6, x6, x3);

            x9 = x6.Clone();
            for (j = 0; j < 3; j++)
            {
                secp256k1_fe_sqr(x9, x9);
            }
            secp256k1_fe_mul(x9, x9, x3);

            x11 = x9.Clone();
            for (j = 0; j < 2; j++)
            {
                secp256k1_fe_sqr(x11, x11);
            }
            secp256k1_fe_mul(x11, x11, x2);

            x22 = x11.Clone();
            for (j = 0; j < 11; j++)
            {
                secp256k1_fe_sqr(x22, x22);
            }
            secp256k1_fe_mul(x22, x22, x11);

            x44 = x22.Clone();
            for (j = 0; j < 22; j++)
            {
                secp256k1_fe_sqr(x44, x44);
            }
            secp256k1_fe_mul(x44, x44, x22);

            x88 = x44.Clone();
            for (j = 0; j < 44; j++)
            {
                secp256k1_fe_sqr(x88, x88);
            }
            secp256k1_fe_mul(x88, x88, x44);

            x176 = x88.Clone();
            for (j = 0; j < 88; j++)
            {
                secp256k1_fe_sqr(x176, x176);
            }
            secp256k1_fe_mul(x176, x176, x88);

            x220 = x176.Clone();
            for (j = 0; j < 44; j++)
            {
                secp256k1_fe_sqr(x220, x220);
            }
            secp256k1_fe_mul(x220, x220, x44);

            x223 = x220.Clone();
            for (j = 0; j < 3; j++)
            {
                secp256k1_fe_sqr(x223, x223);
            }
            secp256k1_fe_mul(x223, x223, x3);

            /* The final result is then assembled using a sliding window over the blocks. */

            t1 = x223.Clone();
            for (j = 0; j < 23; j++)
            {
                secp256k1_fe_sqr(t1, t1);
            }
            secp256k1_fe_mul(t1, t1, x22);
            for (j = 0; j < 5; j++)
            {
                secp256k1_fe_sqr(t1, t1);
            }
            secp256k1_fe_mul(t1, t1, a);
            for (j = 0; j < 3; j++)
            {
                secp256k1_fe_sqr(t1, t1);
            }
            secp256k1_fe_mul(t1, t1, x2);
            for (j = 0; j < 2; j++)
            {
                secp256k1_fe_sqr(t1, t1);
            }
            secp256k1_fe_mul(r, a, t1);
        }