/// <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); }
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); }
/// <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); }