static private void Pad(BigNumber atm, int length) { int ct = length; byte numdiv = 0, numref = 0; if (atm.dataLength >= ct) { return; } int numb = (ct + 1) >> 1; if (numb > atm.mantissa.Length) { BigNumber.Expand(atm, numb + 32); } int num1 = (atm.dataLength + 1) >> 1; if ((atm.dataLength % 2) != 0) { Unpack(atm.mantissa[num1 - 1], ref numdiv, ref numref); atm.mantissa[num1 - 1] = (byte)(10 * numdiv); } for (int i = num1; i < numb; i++) { atm.mantissa[i] = 0; } atm.dataLength = ct; }
/// <summary> /// copy src -> dst /// </summary> /// <param name="src"></param> /// <param name="dst"></param> static private void Copy(BigNumber src, BigNumber dst) { int j = (src.dataLength + 1) >> 1; if (j > dst.mantissa.Length) { BigNumber.Expand(dst, j + 32); } dst.dataLength = src.dataLength; dst.exponent = src.exponent; dst.signum = src.signum; Array.Copy(src.mantissa, dst.mantissa, j); }
static private void FastMul(BigNumber aa, BigNumber bb, BigNumber rr) { int ii, k, nexp, sign; BigNumber M_ain = new BigNumber(); BigNumber M_bin = new BigNumber(); BigNumber.Copy(aa, M_ain); BigNumber.Copy(bb, M_bin); int size_flag = GetSizeofInt(); int bit_limit = 8 * size_flag + 1; sign = M_ain.signum * M_bin.signum; nexp = M_ain.exponent + M_bin.exponent; if (M_ain.dataLength >= M_bin.dataLength) { ii = M_ain.dataLength; } else { ii = M_bin.dataLength; } ii = (ii + 1) >> 1; ii = NextPowerOfTwo(ii); k = 2 * ii; /* required size of result, in bytes */ BigNumber.Pad(M_ain, k); /* fill out the data so the number of */ BigNumber.Pad(M_bin, k); /* bytes is an exact power of 2 */ if (k > rr.mantissa.Length) { BigNumber.Expand(rr, (k + 32)); } BigNumber.FastMulFFT(rr.mantissa, M_ain.mantissa, M_bin.mantissa, ii); rr.signum = (sbyte)sign; rr.exponent = nexp; rr.dataLength = 4 * ii; BigNumber.Normalize(rr); }
/// <summary> /// /// </summary> /// <param name="ctmp"></param> /// <param name="count"></param> static private void Scale(BigNumber ctmp, int count) { int ii, numb, ct; ct = count; byte numdiv = 0, numdiv2 = 0, numrem = 0; ii = (ctmp.dataLength + ct + 1) >> 1; if (ii > ctmp.mantissa.Length) { BigNumber.Expand(ctmp, (ii + 32)); } if ((ct & 1) != 0) /* move odd number first */ { ct--; ii = ((ctmp.dataLength + 1) >> 1) - 1; if ((ctmp.dataLength & 1) == 0) { /* * original datalength is even: * * uv wx yz becomes --> 0u vw xy z0 */ numdiv = 0; while (true) { Unpack(ctmp.mantissa[ii], ref numdiv2, ref numrem); ctmp.mantissa[ii + 1] = (byte)(10 * numrem + numdiv); numdiv = numdiv2; if (ii == 0) { break; } ii--; } ctmp.mantissa[0] = numdiv2; } else { /* * original datalength is odd: * * uv wx y0 becomes --> 0u vw xy */ Unpack(ctmp.mantissa[ii], ref numdiv2, ref numrem); if (ii == 0) { ctmp.mantissa[0] = numdiv2; } else { while (true) { Unpack(ctmp.mantissa[ii - 1], ref numdiv, ref numrem); ctmp.mantissa[ii] = (byte)(10 * numrem + numdiv2); numdiv2 = numdiv; if (--ii == 0) { break; } } ctmp.mantissa[0] = numdiv; } } ctmp.exponent++; ctmp.dataLength++; } /* ct is even here */ if (ct > 0) { numb = (ctmp.dataLength + 1) >> 1; ii = ct >> 1; byte[] newData = new byte[ctmp.mantissa.Length]; Array.Copy(ctmp.mantissa, 0, newData, ii, numb); for (int i = 0; i < ii; i++) { newData[i] = 0; } ctmp.mantissa = newData; ctmp.dataLength += ct; ctmp.exponent += ct; } }
static private void SetFromString(BigNumber atm, String value, bool isStrainghtDigitsOnly = false) { SetZero(atm); int p = 0; sbyte sign = 1; int exponent = 0; if (isStrainghtDigitsOnly == false) { value = value.Trim(); // trim whitespace value = value.ToLower(); // convert to lower //value = UtilityHandler.ToLowerFast(value); int cp = value.IndexOf("0x"); // hexadezimalnumber if (cp >= 0) { value = value.Substring(cp + 2, value.Length - (cp + 2)); BigNumber.SetFromHexString(atm, value); return; } cp = value.IndexOf("%"); // binary format number if (cp >= 0) { value = value.Substring(cp + 1, value.Length - (cp + 1)); BigNumber.SetFromBinaryString(atm, value); return; } cp = value.IndexOf("e"); if (cp > 0) // e cannot be leading { String ex = value.Substring(cp + 1, value.Length - (cp + 1)); exponent = Convert.ToInt32(ex); value = value.Substring(0, cp); } } if (value.Contains("+")) { value = value.Replace("+", ""); // remove optional '+' character } else if (value.Contains("-")) { sign = -1; value = value.Replace("-", ""); } value = value.Replace(",", "."); int j = value.IndexOf("."); if (j == -1) { value = value + '.'; j = value.IndexOf("."); } if (j > 0) { exponent += j; value = value.Replace(".", ""); } int i = value.Length; atm.dataLength = i; if ((i % 2) != 0) { value = value + '0'; } j = value.Length >> 1; if (value.Length > atm.mantissa.Length) { BigNumber.Expand(atm, atm.dataLength + 28); } byte ch = 0; int zflag = 1; for (i = 0, p = 0; i < j; i++) { ch = (byte)(value[p++] - '0'); if ((ch = (byte)((byte)(10 * ch) + (byte)(value[p++] - '0'))) != 0) { zflag = 0; } if (((int)ch & 0xFF) >= 100) { // Error! SetZero(atm); return; } atm.mantissa[i] = ch; atm.mantissa[i + 1] = 0; } atm.exponent = exponent; atm.signum = sign; if (zflag != 0) { atm.exponent = 0; atm.signum = 0; atm.dataLength = 1; atm.mantissa[0] = 0; } else { Normalize(atm); } }
static private void Div(BigNumber aa, BigNumber bb, BigNumber rr, int places) { int j, k, m, b0, nexp, indexr, icompare, iterations; sbyte sign; long trial_numer; BigNumber M_div_worka = new BigNumber(); BigNumber M_div_workb = new BigNumber(); BigNumber M_div_tmp7 = new BigNumber(); BigNumber M_div_tmp8 = new BigNumber(); BigNumber M_div_tmp9 = new BigNumber(); sign = (sbyte)(aa.signum * bb.signum); if (sign == 0) /* one number is zero, result is zero */ { if (bb.signum == 0) { throw new BigNumberException("Division by Zero"); } BigNumber.SetZero(rr); return; } if (bb.mantissa[0] >= 50) { BigNumber.Abs(M_div_worka, aa); BigNumber.Abs(M_div_workb, bb); } else /* 'normal' step D1 */ { k = 100 / (bb.mantissa[0] + 1); BigNumber.SetFromLong(M_div_tmp9, (long)k); BigNumber.Mul(M_div_tmp9, aa, M_div_worka); BigNumber.Mul(M_div_tmp9, bb, M_div_workb); M_div_worka.signum = 1; M_div_workb.signum = 1; } b0 = 100 * (int)M_div_workb.mantissa[0]; if (M_div_workb.dataLength >= 3) { b0 += M_div_workb.mantissa[1]; } nexp = M_div_worka.exponent - M_div_workb.exponent; if (nexp > 0) { iterations = nexp + places + 1; } else { iterations = places + 1; } k = (iterations + 1) >> 1; /* required size of result, in bytes */ if (k > rr.mantissa.Length) { BigNumber.Expand(rr, k + 32); } /* clear the exponent in the working copies */ M_div_worka.exponent = 0; M_div_workb.exponent = 0; /* if numbers are equal, ratio == 1.00000... */ if ((icompare = BigNumber.Compare(M_div_worka, M_div_workb)) == 0) { iterations = 1; rr.mantissa[0] = 10; nexp++; } else /* ratio not 1, do the real division */ { if (icompare == 1) /* numerator > denominator */ { nexp++; /* to adjust the final exponent */ M_div_worka.exponent += 1; /* multiply numerator by 10 */ } else /* numerator < denominator */ { M_div_worka.exponent += 2; /* multiply numerator by 100 */ } indexr = 0; m = 0; while (true) { /* * Knuth step D3. Only use the 3rd -> 6th digits if the number * actually has that many digits. */ trial_numer = 10000L * (long)M_div_worka.mantissa[0]; if (M_div_worka.dataLength >= 5) { trial_numer += 100 * M_div_worka.mantissa[1] + M_div_worka.mantissa[2]; } else { if (M_div_worka.dataLength >= 3) { trial_numer += 100 * M_div_worka.mantissa[1]; } } j = (int)(trial_numer / b0); /* * Since the library 'normalizes' all the results, we need * to look at the exponent of the number to decide if we * have a lead in 0n or 00. */ if ((k = 2 - M_div_worka.exponent) > 0) { while (true) { j /= 10; if (--k == 0) { break; } } } if (j == 100) /* qhat == base ?? */ { j = 99; /* if so, decrease by 1 */ } BigNumber.SetFromLong(M_div_tmp8, (long)j); BigNumber.Mul(M_div_tmp8, M_div_workb, M_div_tmp7); /* * Compare our q-hat (j) against the desired number. * j is either correct, 1 too large, or 2 too large * per Theorem B on pg 272 of Art of Compter Programming, * Volume 2, 3rd Edition. * * The above statement is only true if using the 2 leading * digits of the numerator and the leading digit of the * denominator. Since we are using the (3) leading digits * of the numerator and the (2) leading digits of the * denominator, we eliminate the case where our q-hat is * 2 too large, (and q-hat being 1 too large is quite remote). */ if (BigNumber.Compare(M_div_tmp7, M_div_worka) == 1) { j--; BigNumber.Sub(M_div_tmp7, M_div_workb, M_div_tmp8); BigNumber.Copy(M_div_tmp8, M_div_tmp7); } /* * Since we know q-hat is correct, step D6 is unnecessary. * * Store q-hat, step D5. Since D6 is unnecessary, we can * do D5 before D4 and decide if we are done. */ rr.mantissa[indexr++] = (byte)j; /* j == 'qhat' */ m += 2; if (m >= iterations) { break; } /* step D4 */ BigNumber.Sub(M_div_worka, M_div_tmp7, M_div_tmp9); /* * if the subtraction yields zero, the division is exact * and we are done early. */ if (M_div_tmp9.signum == 0) { iterations = m; break; } /* multiply by 100 and re-save */ M_div_tmp9.exponent += 2; BigNumber.Copy(M_div_tmp9, M_div_worka); } } rr.signum = sign; rr.exponent = nexp; rr.dataLength = iterations; BigNumber.Normalize(rr); }
static private void Mul(BigNumber aa, BigNumber bb, BigNumber rr) { int ai, itmp, nexp, ii, jj, indexa, indexb, index0, numdigits; sbyte sign; sign = (sbyte)(aa.signum * bb.signum); nexp = aa.exponent + bb.exponent; if (sign == 0) { BigNumber.SetZero(rr); return; } numdigits = aa.dataLength + bb.dataLength; indexa = (aa.dataLength + 1) >> 1; indexb = (bb.dataLength + 1) >> 1; if (indexa >= 48 && indexb >= 48) { BigNumber.FastMul(aa, bb, rr); return; } ii = (numdigits + 1) >> 1; if (ii >= rr.mantissa.Length) { BigNumber.Expand(rr, ii + 32); } index0 = indexa + indexb; for (int i = 0; i < index0; i++) { rr.mantissa[i] = 0; } ii = indexa; while (true) { index0--; int crp = index0; jj = indexb; ai = (int)aa.mantissa[--ii]; while (true) { itmp = ai * bb.mantissa[--jj]; rr.mantissa[crp - 1] += s_MsbLookupMult[itmp]; rr.mantissa[crp] += s_LsbLookupMult[itmp]; if (rr.mantissa[crp] >= 100) { rr.mantissa[crp] -= 100; rr.mantissa[crp - 1] += 1; } crp--; if (rr.mantissa[crp] >= 100) { rr.mantissa[crp] -= 100; rr.mantissa[crp - 1] += 1; } if (jj == 0) { break; } } if (ii == 0) { break; } } rr.signum = sign; rr.exponent = nexp; rr.dataLength = numdigits; BigNumber.Normalize(rr); }
static private String ToIntString(BigNumber atm) { int ct, dl, numb, ii; ct = atm.exponent; dl = atm.dataLength; String result = String.Empty; byte numdiv = 0, numrem = 0; if (ct <= 0 || atm.signum == 0) { return("0"); } if (ct > 112) { BigNumber.Expand(atm, ct + 32); } ii = 0; if (atm.signum == -1) { ii = 1; result += "-"; } if (ct > dl) { numb = (dl + 1) >> 1; } else { numb = (ct + 1) >> 1; } int ucp = 0; while (true) { Unpack(atm.mantissa[ucp++], ref numdiv, ref numrem); result += (char)('0' + numdiv); result += (char)('0' + numrem); if (--numb == 0) { break; } } if (ct > dl) { for (int i = 0; i < (ct + 1 - dl); i++) { result += '0'; } } result = result.Substring(0, ct + ii); return(result); }