static private void SetFromHexString(BigNumber atm, String hexvalue) { int length = hexvalue.Length - 1; BigNumber CurValue = new BigNumber(); BigNumber.SetZero(CurValue); BigNumber CurDigitBaseValue = 1; InitializehexLookup(); try { while (length >= 0) { char digit = hexvalue[length]; int value = (int)hexLookup[digit]; CurValue += (CurDigitBaseValue * value); CurDigitBaseValue *= 16; length--; } BigNumber.Copy(CurValue, atm); } catch { // illegal input string throw new BigNumberException("illegal input string"); } }
static public void Power(BigNumber xx, BigNumber yy, BigNumber rr, int places) { int iflag; BigNumber tmp8 = new BigNumber(); BigNumber tmp9 = new BigNumber(); int M_size_flag = BigNumber.GetSizeofInt(); if (yy.signum == 0) { BigNumber.Copy(BigNumber.One, rr); return; } if (xx.signum == 0) { BigNumber.SetZero(rr); return; } if (BigNumber.IsInteger(yy) > 0) { iflag = 0; if (M_size_flag == 2) /* 16 bit compilers */ { if (yy.exponent <= 4) { iflag = 1; } } else /* >= 32 bit compilers */ { if (yy.exponent <= 7) { iflag = 1; } } if (iflag > 0) { String sbuf = BigNumber.ToIntString(yy); int Exp = Convert.ToInt32(sbuf); BigNumber.IntPow(places, xx, Exp, rr); return; } } tmp8 = new BigNumber(); tmp9 = new BigNumber(); BigNumber.Log(xx, tmp9, (places + 8)); BigNumber.Mul(tmp9, yy, tmp8); BigNumber.Exp(tmp8, rr, places); }
static void Floor(BigNumber dst, BigNumber src) { BigNumber.Copy(src, dst); if (BigNumber.IsInteger(dst) > 0) { return; } if (dst.exponent <= 0) /* if |bb| < 1, result is -1 or 0 */ { if (dst.signum < 0) { BigNumber.Neg(BigNumber.One, dst); } else { BigNumber.SetZero(dst); } return; } if (dst.signum < 0) { BigNumber mtmp = new BigNumber(); BigNumber.Neg(dst, mtmp); mtmp.dataLength = mtmp.exponent; BigNumber.Normalize(mtmp); BigNumber.Add(mtmp, BigNumber.One, dst); dst.signum = -1; } else { dst.dataLength = dst.exponent; BigNumber.Normalize(dst); } }
static void Ceil(BigNumber dst, BigNumber src) { BigNumber mtmp; BigNumber.Copy(src, dst); if (IsInteger(dst) > 0) /* if integer, we're done */ { return; } if (dst.exponent <= 0) /* if |bb| < 1, result is 0 or 1 */ { if (dst.signum < 0) { BigNumber.SetZero(dst); } else { BigNumber.Copy(BigNumber.One, dst); } return; } if (dst.signum < 0) { dst.dataLength = dst.exponent; BigNumber.Normalize(dst); } else { mtmp = new BigNumber(); BigNumber.Copy(dst, mtmp); mtmp.dataLength = mtmp.exponent; BigNumber.Normalize(mtmp); BigNumber.Add(mtmp, BigNumber.One, dst); } }
static private void SetFromLong(BigNumber atm, long mm) { if (mm == 0) { BigNumber.SetZero(atm); return; } String ascii_number = mm.ToString(); atm.signum = 1; if (mm < 0) { atm.signum = -1; ascii_number = ascii_number.Replace("-", ""); } atm.exponent = ascii_number.Length; if ((atm.exponent % 2) != 0) { // append a 0 to least significant nibble in case of odd length ascii_number += '0'; } int nbytes = (atm.exponent + 1) >> 1; // we display 2 digits per byte // allocate data array atm.mantissa = new byte[atm.exponent + 1]; atm.dataLength = atm.exponent; for (int ii = 0, p = 0; ii < nbytes; ii++) { byte ch = (byte)(ascii_number[p++] - '0'); atm.mantissa[ii] = (byte)((byte)(10 * ch) + (byte)(ascii_number[p++] - '0')); } }
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 void IntPow(int places, BigNumber src, int mexp, BigNumber dst) { BigNumber A, B, C; int nexp, ii, signflag, local_precision; if (mexp == 0) { BigNumber.Copy(BigNumber.One, dst); return; } else { if (mexp > 0) { signflag = 0; nexp = mexp; } else { signflag = 1; nexp = -mexp; } } if (src.signum == 0) { BigNumber.SetZero(dst); return; } A = new BigNumber(); B = new BigNumber(); C = new BigNumber(); local_precision = places + 8; BigNumber.Copy(BigNumber.One, B); BigNumber.Copy(src, C); while (true) { ii = nexp & 1; nexp = nexp >> 1; if (ii != 0) /* exponent -was- odd */ { BigNumber.Mul(B, C, A); BigNumber.Round(A, B, local_precision); if (nexp == 0) { break; } } BigNumber.Mul(C, C, A); BigNumber.Round(A, C, local_precision); } if (signflag > 0) { BigNumber.Reziprocal(B, dst, places); } else { BigNumber.Round(B, dst, places); } }
static void Log(BigNumber src, BigNumber dst, int places) { BigNumber tmp0, tmp1, tmp2; int mexp, dplaces; if (src.signum <= 0) { throw new BigNumberException(" 'Log', Negative argument"); } tmp0 = new BigNumber(); tmp1 = new BigNumber(); tmp2 = new BigNumber(); dplaces = places + 8; mexp = src.exponent; if (mexp == 0 || mexp == 1) { BigNumber.Sub(src, BigNumber.One, tmp0); if (tmp0.signum == 0) /* is input exactly 1 ?? */ { /* if so, result is 0 */ BigNumber.SetZero(dst); return; } if (tmp0.exponent <= -4) { M_log_near_1(tmp0, dst, places); return; } } /* make sure our log(10) is accurate enough for this calculation */ /* (and log(2) which is called from M_log_basic_iteration) */ BigNumber.CheckLogPlaces(dplaces + 25); if (Math.Abs(mexp) <= 3) { M_log_basic_iteration(src, dst, places); } else { /* * use log (x * y) = log(x) + log(y) * * here we use y = exponent of our base 10 number. * * let 'C' = log(10) = 2.3025850929940.... * * then log(x * y) = log(x) + ( C * base_10_exponent ) */ BigNumber.Copy(src, tmp2); mexp = tmp2.exponent - 2; tmp2.exponent = 2; M_log_basic_iteration(tmp2, tmp0, dplaces); BigNumber.SetFromLong(tmp1, (long)mexp); BigNumber.Mul(tmp1, BN_lc_log10, tmp2); BigNumber.Add(tmp2, tmp0, tmp1); BigNumber.Round(tmp1, dst, places); } }