예제 #1
0
        /// <summary>
        /// The binary logarithm, log2(x) - for precisions above 1000 bits, use Log() and convert the base.
        /// </summary>
        private void Log2()
        {
            if (scratch.Precision.NumBits != mantissa.Precision.NumBits)
            {
                scratch = new BigInt(mantissa.Precision);
            }

            int bits = mantissa.Precision.NumBits;
            BigFloat temp = new BigFloat(this);
            BigFloat result = new BigFloat(exponent, mantissa.Precision);
            BigFloat pow2 = new BigFloat(1, mantissa.Precision);
            temp.exponent = 0;
            int bitsCalculated = 0;

            while (bitsCalculated < bits)
            {
                int i;
                for (i = 0; (temp.exponent == 0); i++)
                {
                    temp.mantissa.SquareHiFast(scratch);
                    int shift = temp.mantissa.Normalise();
                    temp.exponent += 1 - shift;
                    if (i + bitsCalculated >= bits) break;
                }

                pow2.MulPow2(-i);
                result.Add(pow2);
                temp.exponent = 0;
                bitsCalculated += i;
            }

            this.Assign(result);
        }
예제 #2
0
        private static BigFloat R(BigFloat a0, BigFloat b0)
        {
            //Precision extend taken out.
            int bits = a0.mantissa.Precision.NumBits;
            PrecisionSpec extendedPres = new PrecisionSpec(bits, PrecisionSpec.BaseType.BIN);
            BigFloat an = new BigFloat(a0, extendedPres);
            BigFloat bn = new BigFloat(b0, extendedPres);
            BigFloat sum = new BigFloat(extendedPres);
            BigFloat term = new BigFloat(extendedPres);
            BigFloat temp1 = new BigFloat(extendedPres);
            BigFloat one = new BigFloat(1, extendedPres);

            int iteration = 0;

            for (iteration = 0; ; iteration++)
            {
                //Get the sum term for this iteration.
                term.Assign(an);
                term.Mul(an);
                temp1.Assign(bn);
                temp1.Mul(bn);
                //term = an^2 - bn^2
                term.Sub(temp1);
                //term = 2^(n-1) * (an^2 - bn^2)
                term.exponent += iteration - 1;
                sum.Add(term);

                if (term.exponent < -(bits - 8)) break;

                //Calculate the new AGM estimates.
                temp1.Assign(an);
                an.Add(bn);
                //a(n+1) = (an + bn) / 2
                an.MulPow2(-1);

                //b(n+1) = sqrt(an*bn)
                bn.Mul(temp1);
                bn.Sqrt();
            }

            one.Sub(sum);
            one = one.Reciprocal();
            return new BigFloat(one, a0.mantissa.Precision);
        }
예제 #3
0
        /// <summary>
        /// Two-variable iterative square root, taken from
        /// http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#A_two-variable_iterative_method
        /// </summary>
        public void Sqrt()
        {
            if (mantissa.Sign || IsSpecialValue)
            {
                if (SpecialValue == SpecialValueType.ZERO)
                {
                    return;
                }

                if (SpecialValue == SpecialValueType.INF_MINUS || mantissa.Sign)
                {
                    SetNaN();
                }

                return;
            }

            BigFloat temp2;
            BigFloat temp3 = new BigFloat(mantissa.Precision);
            BigFloat three = new BigFloat(3, mantissa.Precision);

            int exponentScale = 0;

            //Rescale to 0.5 <= x < 2
            if (exponent < -1)
            {
                int diff = -exponent;
                if ((diff & 1) != 0)
                {
                    diff--;
                }

                exponentScale = -diff;
                exponent += diff;
            }
            else if (exponent > 0)
            {
                if ((exponent & 1) != 0)
                {
                    exponentScale = exponent + 1;
                    exponent = -1;
                }
                else
                {
                    exponentScale = exponent;
                    exponent = 0;
                }
            }

            temp2 = new BigFloat(this);
            temp2.Sub(new BigFloat(1, mantissa.Precision));

            //if (temp2.mantissa.IsZero())
            //{
            //    exponent += exponentScale;
            //    return;
            //}

            int numBits = mantissa.Precision.NumBits;

            while ((exponent - temp2.exponent) < numBits && temp2.SpecialValue != SpecialValueType.ZERO)
            {
                //a(n+1) = an - an*cn / 2
                temp3.Assign(this);
                temp3.Mul(temp2);
                temp3.MulPow2(-1);
                this.Sub(temp3);

                //c(n+1) = cn^2 * (cn - 3) / 4
                temp3.Assign(temp2);
                temp2.Sub(three);
                temp2.Mul(temp3);
                temp2.Mul(temp3);
                temp2.MulPow2(-2);
            }

            exponent += (exponentScale >> 1);
        }