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;
        }
Beispiel #2
0
        /// <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);
        }
Beispiel #3
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);
        }
        /// <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;
            }
        }
Beispiel #5
0
        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);
            }
        }
Beispiel #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);
        }
Beispiel #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);
        }
Beispiel #8
0
        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);
        }