Пример #1
0
        public static void Invert(uint[] p, uint[] x, uint[] z)
        {
            int len = p.Length;

            if (Nat.IsZero(len, x))
            {
                throw new ArgumentException("cannot be 0", "x");
            }
            if (Nat.IsOne(len, x))
            {
                Array.Copy(x, 0, z, 0, len);
                return;
            }

            uint[] u = Nat.Copy(len, x);
            uint[] a = Nat.Create(len);
            a[0] = 1;
            int ac = 0;

            if ((u[0] & 1) == 0)
            {
                InversionStep(p, u, len, a, ref ac);
            }
            if (Nat.IsOne(len, u))
            {
                InversionResult(p, ac, a, z);
                return;
            }

            uint[] v  = Nat.Copy(len, p);
            uint[] b  = Nat.Create(len);
            int    bc = 0;

            int uvLen = len;

            for (;;)
            {
                while (u[uvLen - 1] == 0 && v[uvLen - 1] == 0)
                {
                    --uvLen;
                }

                if (Nat.Gte(len, u, v))
                {
                    Nat.SubFrom(len, v, u);
                    Debug.Assert((u[0] & 1) == 0);
                    ac += Nat.SubFrom(len, b, a) - bc;
                    InversionStep(p, u, uvLen, a, ref ac);
                    if (Nat.IsOne(len, u))
                    {
                        InversionResult(p, ac, a, z);
                        return;
                    }
                }
                else
                {
                    Nat.SubFrom(len, u, v);
                    Debug.Assert((v[0] & 1) == 0);
                    bc += Nat.SubFrom(len, a, b) - ac;
                    InversionStep(p, v, uvLen, b, ref bc);
                    if (Nat.IsOne(len, v))
                    {
                        InversionResult(p, bc, b, z);
                        return;
                    }
                }
            }
        }