예제 #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 Round(BigNumber src, BigNumber dst, int places)
        {
            BigNumber t0_5 = new BigNumber();

            BigNumber.Copy(Five, t0_5);
            int ii = places + 1;

            if (src.dataLength <= ii)
            {
                Copy(src, dst);
                return;
            }

            t0_5.exponent = src.exponent - ii;

            if (src.signum > 0)
            {
                BigNumber.Add(src, t0_5, dst);
            }
            else
            {
                BigNumber.Sub(src, t0_5, dst);
            }

            dst.dataLength = ii;
            BigNumber.Normalize(dst);
        }
예제 #3
0
 /// <summary>
 /// get absolute  value of number
 /// </summary>
 /// <param name="d"></param>
 /// <param name="s"></param>
 static void Abs(BigNumber d, BigNumber s)
 {
     BigNumber.Copy(s, d);
     if (d.signum != 0)
     {
         d.signum = 1;
     }
 }
예제 #4
0
        static void Neg(BigNumber s, BigNumber d)
        {
            BigNumber.Copy(s, d);

            if (d.signum != 0)
            {
                d.signum = (sbyte)-(d.signum);
            }
        }
예제 #5
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);
        }
        /****************************************************************************/

        /*
         *      Calculate PI using the AGM (Arithmetic-Geometric Mean)
         *
         *      Init :  A0  = 1
         *              B0  = 1 / sqrt(2)
         *              Sum = 1
         *
         *      Iterate: n = 1...
         *
         *
         *      A   =  0.5 * [ A    +  B   ]
         *       n              n-1     n-1
         *
         *
         *      B   =  sqrt [ A    *  B   ]
         *       n             n-1     n-1
         *
         *
         *      C   =  0.5 * [ A    -  B   ]
         *       n              n-1     n-1
         *
         *
         *                      2      n+1
         *     Sum  =  Sum  -  C   *  2
         *                      n
         *
         *
         *      At the end when C  is 'small enough' :
         *                       n
         *
         *                    2
         *      PI  =  4  *  A    /  Sum
         *                    n+1
         *
         *          -OR-
         *
         *                       2
         *      PI  = ( A  +  B )   /  Sum
         *               n     n
         *
         */
        static private void CalculatePiAGM(BigNumber outv, int places)
        {
            int dplaces, nn;

            BigNumber tmp1  = new BigNumber();
            BigNumber tmp2  = new BigNumber();
            BigNumber a0    = new BigNumber();
            BigNumber b0    = new BigNumber();
            BigNumber c0    = new BigNumber();
            BigNumber a1    = new BigNumber();
            BigNumber b1    = new BigNumber();
            BigNumber sum   = new BigNumber();
            BigNumber pow_2 = new BigNumber();

            dplaces = places + 16;

            BigNumber.Copy(BigNumber.One, a0);
            BigNumber.Copy(BigNumber.One, sum);
            BigNumber.Copy(BigNumber.Four, pow_2);
            BigNumber.Sqrt(BigNumber.BN_OneHalf, b0, dplaces);

            while (true)
            {
                BigNumber.Add(a0, b0, tmp1);
                BigNumber.Mul(tmp1, BigNumber.BN_OneHalf, a1);
                BigNumber.Mul(a0, b0, tmp1);
                BigNumber.Sqrt(tmp1, b1, dplaces);
                BigNumber.Sub(a0, b0, tmp1);
                BigNumber.Mul(BigNumber.BN_OneHalf, tmp1, c0);
                BigNumber.Mul(c0, c0, tmp1);
                BigNumber.Mul(tmp1, pow_2, tmp2);
                BigNumber.Sub(sum, tmp2, tmp1);
                BigNumber.Round(tmp1, sum, dplaces);

                nn = -4 * c0.exponent;

                if (nn >= dplaces)
                {
                    break;
                }

                BigNumber.Copy(a1, a0);
                BigNumber.Copy(b1, b0);
                BigNumber.Mul(pow_2, BigNumber.Two, tmp1);
                BigNumber.Copy(tmp1, pow_2);
            }

            BigNumber.Add(a1, b1, tmp1);
            BigNumber.Mul(tmp1, tmp1, tmp2);
            BigNumber.Div(tmp2, sum, tmp1, dplaces);
            BigNumber.Round(tmp1, outv, places);
        }
예제 #7
0
        /****************************************************************************/

        /*
         *      calculate log (1 + x) with the following series:
         *
         *            x
         *      y = -----      ( |y| < 1 )
         *          x + 2
         *
         *
         *          [ 1 + y ]                 y^3     y^5     y^7
         *      log [-------]  =  2 * [ y  +  ---  +  ---  +  ---  ... ]
         *          [ 1 - y ]                  3       5       7
         *
         */

        static void     M_log_near_1(BigNumber xx, BigNumber rr, int places)
        {
            BigNumber tmp0, tmp1, tmp2, tmpS, term;
            int       tolerance, dplaces, local_precision;
            long      m1;

            tmp0 = new BigNumber();
            tmp1 = new BigNumber();
            tmp2 = new BigNumber();
            tmpS = new BigNumber();
            term = new BigNumber();

            tolerance = xx.exponent - (places + 6);
            dplaces   = (places + 12) - xx.exponent;

            BigNumber.Add(xx, BigNumber.Two, tmp0);
            BigNumber.Div(xx, tmp0, tmpS, (dplaces + 6));
            BigNumber.Copy(tmpS, term);
            BigNumber.Mul(tmpS, tmpS, tmp0);
            BigNumber.Round(tmp0, tmp2, (dplaces + 6));

            m1 = 3L;

            while (true)
            {
                BigNumber.Mul(term, tmp2, tmp0);

                if ((tmp0.exponent < tolerance) || (tmp0.signum == 0))
                {
                    break;
                }

                local_precision = dplaces + tmp0.exponent;

                if (local_precision < 20)
                {
                    local_precision = 20;
                }

                BigNumber.SetFromLong(tmp1, m1);
                BigNumber.Round(tmp0, term, local_precision);
                BigNumber.Div(term, tmp1, tmp0, local_precision);
                BigNumber.Add(tmpS, tmp0, tmp1);
                BigNumber.Copy(tmp1, tmpS);
                m1 += 2;
            }

            BigNumber.Mul(BigNumber.Two, tmpS, tmp0);
            BigNumber.Round(tmp0, rr, places);
        }
예제 #8
0
        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);
        }
예제 #9
0
        static private void M_raw_exp(BigNumber xx, BigNumber rr, int places)
        {
            BigNumber tmp0, digit, term;
            int       tolerance, local_precision, prev_exp;
            long      m1;

            tmp0  = new BigNumber();
            term  = new BigNumber();
            digit = new BigNumber();

            local_precision = places + 8;
            tolerance       = -(places + 4);
            prev_exp        = 0;

            BigNumber.Add(BigNumber.One, xx, rr);
            BigNumber.Copy(xx, term);

            m1 = 2L;

            while (true)
            {
                BigNumber.SetFromLong(digit, m1);
                BigNumber.Mul(term, xx, tmp0);
                BigNumber.Div(tmp0, digit, term, local_precision);
                BigNumber.Add(rr, term, tmp0);
                BigNumber.Copy(tmp0, rr);

                if ((term.exponent < tolerance) || (term.signum == 0))
                {
                    break;
                }

                if (m1 != 2L)
                {
                    local_precision = local_precision + term.exponent - prev_exp;

                    if (local_precision < 20)
                    {
                        local_precision = 20;
                    }
                }

                prev_exp = term.exponent;
                m1++;
            }
        }
예제 #10
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);
            }
        }
예제 #11
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);
            }
        }
예제 #12
0
        static void CheckLogPlaces(int places)
        {
            BigNumber tmp6, tmp7, tmp8, tmp9;
            int       dplaces;

            dplaces = places + 4;

            if (dplaces > MM_lc_log_digits)
            {
                MM_lc_log_digits = dplaces + 4;

                tmp6 = new BigNumber();
                tmp7 = new BigNumber();
                tmp8 = new BigNumber();
                tmp9 = new BigNumber();

                dplaces += 6 + (int)Math.Log10((double)places);

                BigNumber.Copy(BigNumber.One, tmp7);
                tmp7.exponent = -places;

                BigNumber.LogAGMRFunc(BigNumber.One, tmp7, tmp8, dplaces);

                BigNumber.Mul(tmp7, BigNumber.BN_OneHalf, tmp6);

                BigNumber.LogAGMRFunc(BigNumber.One, tmp6, tmp9, dplaces);

                BigNumber.Sub(tmp9, tmp8, BN_lc_log2);

                tmp7.exponent -= 1;

                BigNumber.LogAGMRFunc(BigNumber.One, tmp7, tmp9, dplaces);

                BigNumber.Sub(tmp9, tmp8, BN_lc_log10);
                BigNumber.Reziprocal(BN_lc_log10R, BN_lc_log10, dplaces);
            }
        }
예제 #13
0
 public BigNumber(BigNumber rh)
 {
     BigNumber.Copy(rh, this);
 }
예제 #14
0
        /****************************************************************************/

        /*
         *	define a notation for a function 'R' :
         *
         *
         *
         *                                    1
         *      R (a0, b0)  =  ------------------------------
         *
         *                          ----
         *                           \
         *                            \     n-1      2    2
         *                      1  -   |   2    *  (a  - b )
         *                            /              n    n
         *                           /
         *                          ----
         *                         n >= 0
         *
         *
         *      where a, b are the classic AGM iteration :
         *
         *
         *      a    =  0.5 * (a  + b )
         *       n+1            n    n
         *
         *
         *      b    =  sqrt(a  * b )
         *       n+1          n    n
         *
         *
         *
         *      define a variable 'c' for more efficient computation :
         *
         *                                      2     2     2
         *      c    =  0.5 * (a  - b )    ,   c  =  a  -  b
         *       n+1            n    n          n     n     n
         *
         */

        /****************************************************************************/
        static void     LogAGMRFunc(BigNumber aa, BigNumber bb, BigNumber rr, int places)
        {
            BigNumber tmp1, tmp2, tmp3, tmp4, tmpC2, sum, pow_2, tmpA0, tmpB0;
            int       tolerance, dplaces;

            tmpA0 = new BigNumber();
            tmpB0 = new BigNumber();
            tmpC2 = new BigNumber();
            tmp1  = new BigNumber();
            tmp2  = new BigNumber();
            tmp3  = new BigNumber();
            tmp4  = new BigNumber();
            sum   = new BigNumber();
            pow_2 = new BigNumber();

            tolerance = places + 8;
            dplaces   = places + 16;

            BigNumber.Copy(aa, tmpA0);
            BigNumber.Copy(bb, tmpB0);
            BigNumber.Copy(BigNumber.BN_OneHalf, pow_2);

            BigNumber.Mul(aa, aa, tmp1);                    /* 0.5 * [ a ^ 2 - b ^ 2 ] */
            BigNumber.Mul(bb, bb, tmp2);
            BigNumber.Sub(tmp1, tmp2, tmp3);
            BigNumber.Mul(BigNumber.BN_OneHalf, tmp3, sum);

            while (true)
            {
                BigNumber.Sub(tmpA0, tmpB0, tmp1);               /* C n+1 = 0.5 * [ An - Bn ] */
                BigNumber.Mul(BigNumber.BN_OneHalf, tmp1, tmp4); /* C n+1 */
                BigNumber.Mul(tmp4, tmp4, tmpC2);                /* C n+1 ^ 2 */

                /* do the AGM */

                BigNumber.Add(tmpA0, tmpB0, tmp1);
                BigNumber.Mul(BigNumber.BN_OneHalf, tmp1, tmp3);

                BigNumber.Mul(tmpA0, tmpB0, tmp2);
                BigNumber.Sqrt(tmp2, tmpB0, dplaces);

                BigNumber.Round(tmp3, tmpA0, dplaces);

                /* end AGM */

                BigNumber.Mul(BigNumber.Two, pow_2, tmp2);
                BigNumber.Copy(tmp2, pow_2);

                BigNumber.Mul(tmpC2, pow_2, tmp1);
                BigNumber.Add(sum, tmp1, tmp3);

                if ((tmp1.signum == 0) || ((-2 * tmp1.exponent) > tolerance))
                {
                    break;
                }

                BigNumber.Round(tmp3, sum, dplaces);
            }

            BigNumber.Sub(BigNumber.One, tmp3, tmp4);
            BigNumber.Reziprocal(tmp4, rr, places);
        }
예제 #15
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);
            }
        }
예제 #16
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);
            }
        }
예제 #17
0
        static public void Sub(BigNumber src, BigNumber dst, BigNumber result)
        {
            int       itmp, j, ChangeOrderFlag, icompare, aexp, bexp, borrow, adigits, bdigits;
            sbyte     sign;
            BigNumber A = 0, B = 0;

            if (dst.signum == 0)
            {
                BigNumber.Copy(src, result);
                return;
            }

            if (src.signum == 0)
            {
                BigNumber.Copy(dst.Neg(), result);
                return;
            }

            if (src.signum == 1 && dst.signum == -1)
            {
                dst.signum = 1;
                Add(src, dst, result);
                dst.signum = -1;
                return;
            }

            if (src.signum == -1 && dst.signum == 1)
            {
                dst.signum = -1;
                Add(src, dst, result);
                dst.signum = 1;
                return;
            }

            BigNumber.Abs(A, src);
            BigNumber.Abs(B, dst);

            if ((icompare = Compare(A, B)) == 0)
            {
                SetZero(result);
                return;
            }

            if (icompare == 1)  /*  |a| > |b|  (do A-B)  */
            {
                ChangeOrderFlag = 1;
                sign            = src.signum;
            }
            else                /*  |b| > |a|  (do B-A)  */
            {
                ChangeOrderFlag = 0;
                sign            = (sbyte)-(src.signum);
            }

            aexp = A.exponent;
            bexp = B.exponent;

            if (aexp > bexp)
            {
                Scale(B, (aexp - bexp));
            }
            if (aexp < bexp)
            {
                Scale(A, (bexp - aexp));
            }

            adigits = A.dataLength;
            bdigits = B.dataLength;

            if (adigits > bdigits)
            {
                Pad(B, adigits);
            }

            if (adigits < bdigits)
            {
                Pad(A, bdigits);
            }

            if (ChangeOrderFlag == 1)            // |a| > |b|  (do A-B)
            {
                Copy(A, result);

                j = (result.dataLength + 1) >> 1;

                borrow = 0;

                while (true)
                {
                    j--;
                    itmp = ((int)result.mantissa[j] - ((int)B.mantissa[j] + borrow));

                    if (itmp >= 0)
                    {
                        result.mantissa[j] = (byte)itmp;
                        borrow             = 0;
                    }
                    else
                    {
                        result.mantissa[j] = (byte)(100 + itmp);
                        borrow             = 1;
                    }

                    if (j == 0)
                    {
                        break;
                    }
                }
            }
            else                // |b| > |a|  (do B-A) instead
            {
                Copy(B, result);

                j      = (result.dataLength + 1) >> 1;
                borrow = 0;

                while (true)
                {
                    j--;
                    itmp = (int)result.mantissa[j] - ((int)A.mantissa[j] + borrow);

                    if (itmp >= 0)
                    {
                        result.mantissa[j] = (byte)itmp;
                        borrow             = 0;
                    }
                    else
                    {
                        result.mantissa[j] = (byte)(100 + itmp);
                        borrow             = 1;
                    }

                    if (j == 0)
                    {
                        break;
                    }
                }
            }

            result.signum = sign;

            BigNumber.Normalize(result);
        }
예제 #18
0
        static void Sqrt(BigNumber src, BigNumber dst, int places)
        {
            int  ii, nexp, tolerance, dplaces;
            bool bflag;

            if (src.signum <= 0)
            {
                if (src.signum == -1)
                {
                    throw new BigNumberException("'Sqrt',Invalid Argument");
                }
            }

            BigNumber last_x = new BigNumber();
            BigNumber guess  = new BigNumber();
            BigNumber tmpN   = new BigNumber();
            BigNumber tmp7   = new BigNumber();
            BigNumber tmp8   = new BigNumber();
            BigNumber tmp9   = new BigNumber();

            BigNumber.Copy(src, tmpN);

            nexp           = src.exponent / 2;
            tmpN.exponent -= 2 * nexp;

            BigNumber.SQrtGuess(tmpN, guess);

            tolerance = places + 4;
            dplaces   = places + 16;
            bflag     = false;

            BigNumber.Neg(BigNumber.Ten, last_x);

            ii = 0;

            while (true)
            {
                BigNumber.Mul(tmpN, guess, tmp9);
                BigNumber.Mul(tmp9, guess, tmp8);
                BigNumber.Round(tmp8, tmp7, dplaces);
                BigNumber.Sub(BigNumber.Three, tmp7, tmp9);
                BigNumber.Mul(tmp9, guess, tmp8);
                BigNumber.Mul(tmp8, BigNumber.BN_OneHalf, tmp9);

                if (bflag)
                {
                    break;
                }

                BigNumber.Round(tmp9, guess, dplaces);

                if (ii != 0)
                {
                    BigNumber.Sub(guess, last_x, tmp7);

                    if (tmp7.signum == 0)
                    {
                        break;
                    }

                    /*
                     *   if we are within a factor of 4 on the error term,
                     *   we will be accurate enough after the *next* iteration
                     *   is complete.  (note that the sign of the exponent on
                     *   the error term will be a negative number).
                     */

                    if ((-4 * tmp7.exponent) > tolerance)
                    {
                        bflag = true;
                    }
                }

                BigNumber.Copy(guess, last_x);
                ii++;
            }

            BigNumber.Mul(tmp9, tmpN, tmp8);
            BigNumber.Round(tmp8, dst, places);
            dst.exponent += nexp;
        }
예제 #19
0
        static private void Exp(BigNumber src, BigNumber dst, int places)
        {
            BigNumber A = 0, B = 0, C = 0;
            int       dplaces, nn = 0, ii = 0;

            if (src.signum == 0)
            {
                BigNumber.Copy(BigNumber.One, dst);
                return;
            }

            if (src.exponent <= -3)
            {
                M_raw_exp(src, C, (places + 6));
                BigNumber.Round(C, dst, places);
                return;
            }

            if (M_exp_compute_nn(ref nn, A, src) != 0)
            {
                throw new BigNumberException("'Exp', Input too large, Overflow");
            }

            dplaces = places + 8;

            BigNumber.CheckLogPlaces(dplaces);
            BigNumber.Mul(A, BN_lc_log2, B);
            BigNumber.Sub(src, B, A);

            while (true)
            {
                if (A.signum != 0)
                {
                    if (A.exponent == 0)
                    {
                        break;
                    }
                }

                if (A.signum >= 0)
                {
                    nn++;
                    BigNumber.Sub(A, BN_lc_log2, B);
                    BigNumber.Copy(B, A);
                }
                else
                {
                    nn--;
                    BigNumber.Add(A, BN_lc_log2, B);
                    BigNumber.Copy(B, A);
                }
            }

            BigNumber.Mul(A, BN_exp_512R, C);

            M_raw_exp(C, B, dplaces);

            ii = 9;

            while (true)
            {
                BigNumber.Mul(B, B, C);
                BigNumber.Round(C, B, dplaces);

                if (--ii == 0)
                {
                    break;
                }
            }

            BigNumber.IntPow(dplaces, BigNumber.Two, nn, A);
            BigNumber.Mul(A, B, C);
            BigNumber.Round(C, dst, places);
        }
예제 #20
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);
        }
예제 #21
0
        static public void Add(BigNumber src, BigNumber dst, BigNumber result)
        {
            int       j, carry, aexp, bexp, adigits, bdigits;
            sbyte     sign;
            BigNumber A = 0, B = 0;

            if (src.signum == 0)
            {
                BigNumber.Copy(dst, result);
                return;
            }

            if (dst.signum == 0)
            {
                BigNumber.Copy(src, result);
                return;
            }

            if (src.signum == 1 && dst.signum == -1)
            {
                dst.signum = 1;
                Sub(src, dst, result);
                dst.signum = -1;
                return;
            }

            if (src.signum == -1 && dst.signum == 1)
            {
                src.signum = 1;
                Sub(dst, src, result);
                src.signum = -1;
                return;
            }

            sign = src.signum;
            aexp = src.exponent;
            bexp = dst.exponent;

            Copy(src, A);
            Copy(dst, B);

            if (aexp == bexp)
            {
                // scale (shift) 2 digits
                BigNumber.Scale(A, 2);
                BigNumber.Scale(B, 2);
            }
            else
            {
                // scale to larger exponent
                if (aexp > bexp)
                {
                    BigNumber.Scale(A, 2);
                    BigNumber.Scale(B, (aexp - bexp + 2));
                }
                else
                {
                    BigNumber.Scale(B, 2);
                    BigNumber.Scale(A, (bexp - aexp + 2));
                }
            }

            adigits = A.dataLength;
            bdigits = B.dataLength;

            if (adigits >= bdigits)
            {
                Copy(A, result);

                j = (bdigits + 1) >> 1;

                carry = 0;

                while (true)
                {
                    j--;
                    result.mantissa[j] += (byte)(carry + B.mantissa[j]);

                    if (result.mantissa[j] >= 100)
                    {
                        result.mantissa[j] -= 100;
                        carry = 1;
                    }
                    else
                    {
                        carry = 0;
                    }

                    if (j == 0)
                    {
                        break;
                    }
                }
            }
            else
            {
                Copy(B, result);

                j = (adigits + 1) >> 1;

                carry = 0;

                while (true)
                {
                    j--;
                    result.mantissa[j] += (byte)(carry + A.mantissa[j]);

                    if (result.mantissa[j] >= 100)
                    {
                        result.mantissa[j] -= 100;
                        carry = 1;
                    }
                    else
                    {
                        carry = 0;
                    }

                    if (j == 0)
                    {
                        break;
                    }
                }
            }

            result.signum = sign;
            Normalize(result);
        }
예제 #22
0
        static private String ToExpString(BigNumber atm, int digits)
        {
            int  i, index, first, max_i, num_digits, dec_places;
            byte numdiv = 0, numrem = 0;

            BigNumber ctmp = new BigNumber();
            String    res  = "";

            dec_places = digits;

            if (dec_places < 0)
            {
                BigNumber.Copy(atm, ctmp);
            }
            else
            {
                BigNumber.Round(atm, ctmp, dec_places);
            }

            if (ctmp.signum == 0)
            {
                if (dec_places < 0)
                {
                    res = "0.0E+0";
                }
                else
                {
                    res = "0";

                    if (dec_places > 0)
                    {
                        res += ".";
                    }

                    for (i = 0; i < dec_places; i++)
                    {
                        res += "0";
                    }

                    res += "E+0";
                }
                return(res);
            }

            max_i = (ctmp.dataLength + 1) >> 1;

            if (dec_places < 0)
            {
                num_digits = ctmp.dataLength;
            }
            else
            {
                num_digits = dec_places + 1;
            }
            if (ctmp.signum == -1)
            {
                res += '-';
            }

            first = 1;

            i     = 0;
            index = 0;

            while (true)
            {
                if (index >= max_i)
                {
                    numdiv = 0;
                    numrem = 0;
                }
                else
                {
                    Unpack(ctmp.mantissa[index], ref numdiv, ref numrem);
                }

                index++;

                res += (char)('0' + numdiv);

                if (++i == num_digits)
                {
                    break;
                }

                if (first != 0)
                {
                    first = 0;
                    res  += '.';
                }

                res += (char)('0' + numrem);

                if (++i == num_digits)
                {
                    break;
                }
            }

            i = ctmp.exponent - 1;

            if (i >= 0)
            {
                res += "E+" + i;
            }
            else if (i < 0)
            {
                res += "E" + i;
            }


            return(res);
        }