public static BigInteger ModPow(BigInteger value, BigInteger exponent, BigInteger modulus)
        {
            if (exponent.Sign < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(exponent));
            }

            value.AssertValid();
            exponent.AssertValid();
            modulus.AssertValid();

            bool trivialValue    = value._bits == null;
            bool trivialExponent = exponent._bits == null;
            bool trivialModulus  = modulus._bits == null;

            if (trivialModulus)
            {
                uint bits = trivialValue && trivialExponent?BigIntegerCalculator.Pow(NumericsHelpers.Abs(value._sign), NumericsHelpers.Abs(exponent._sign), NumericsHelpers.Abs(modulus._sign)) :
                                trivialValue?BigIntegerCalculator.Pow(NumericsHelpers.Abs(value._sign), exponent._bits, NumericsHelpers.Abs(modulus._sign)) :
                                    trivialExponent?BigIntegerCalculator.Pow(value._bits, NumericsHelpers.Abs(exponent._sign), NumericsHelpers.Abs(modulus._sign)) :
                                        BigIntegerCalculator.Pow(value._bits, exponent._bits, NumericsHelpers.Abs(modulus._sign));

                return(value._sign < 0 && !exponent.IsEven ? -1 * bits : bits);
            }
            else
            {
                uint[] bits = trivialValue && trivialExponent?BigIntegerCalculator.Pow(NumericsHelpers.Abs(value._sign), NumericsHelpers.Abs(exponent._sign), modulus._bits) :
                                  trivialValue?BigIntegerCalculator.Pow(NumericsHelpers.Abs(value._sign), exponent._bits, modulus._bits) :
                                      trivialExponent?BigIntegerCalculator.Pow(value._bits, NumericsHelpers.Abs(exponent._sign), modulus._bits) :
                                          BigIntegerCalculator.Pow(value._bits, exponent._bits, modulus._bits);

                return(new BigInteger(bits, value._sign < 0 && !exponent.IsEven));
            }
        }