예제 #1
0
        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");
            }
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
            }
        }
예제 #4
0
        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);
            }
        }
예제 #5
0
        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'));
            }
        }
예제 #6
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);
        }
예제 #7
0
        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);
        }
예제 #8
0
        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);
            }
        }
예제 #9
0
        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);
            }
        }