Ejemplo n.º 1
0
        static void Main(string[] args)
        {
            Console.WriteLine("Simple addition test");

            MPUnit mpu1 = new MPUnit();
            mpu1 = MPUnit.Add(mpu1,(ushort)65535);

            MPUnit mpu2 = new MPUnit();
            mpu2 = MPUnit.Add(mpu2,1);

            Console.WriteLine("mpu1: {0}",mpu1);

            for(int i = 0; i<20; i++)
            {
                mpu1 = MPUnit.Add(mpu1,mpu2);
                Console.WriteLine("i: {0}, mpu1: {1}",i, mpu1);
            }

            for(int i=0; i<20; i++)
            {
                mpu1 = MPUnit.Sub(mpu1,mpu2);
                Console.WriteLine("i: {0}, mpu1: {1}",i, mpu1);
            }

            Console.WriteLine("Simple multiplication test");

            MPUnit mpu3 = new MPUnit();
            mpu3[1]=1;
            MPUnit mpu4 = new MPUnit();
            mpu4[0]=1;

            for(int i=0; i<10; i++)
                {
                mpu3 = MPUnit.Mult(mpu3,mpu4);
                mpu3.Trim();
                mpu4[0]= (ushort)(mpu4[0] + (ushort)1);
                Console.WriteLine("mpu3 {0} :: mpu4 {1}",mpu3, mpu4);
                Console.WriteLine("mpu3 digits {0}, mpu4 digits {1}",mpu3.Digits,mpu4.Digits);
                Console.WriteLine(mpu3.FormatDec());
                }

            Console.WriteLine("\nCompound division test");
            MPUnit dividend = new MPUnit();
            dividend[0]=15;
            dividend[1]=43202;
            dividend[2]=32720;
            dividend[3]=12;
            dividend[4]=4;
            dividend[5]=27;

            MPUnit divisor = new MPUnit();
            divisor[0]=65535;
            divisor[1]=16;

            MPUnit quotient=null,remainder=null;
            MPUnit.Div(dividend, divisor ,ref quotient, ref remainder);

            Console.WriteLine("Dividend {0}",dividend);
            Console.WriteLine("Divisor {0}",divisor);
            Console.WriteLine("Quotient {0}",quotient);
            Console.WriteLine(quotient.FormatDec());
            Console.WriteLine("Remainder {0}",remainder);
            MPUnit partialproduct = MPUnit.Mult(quotient,divisor);
            Console.WriteLine("Quotient * Divisor  = {0}",partialproduct);
            Console.WriteLine("Quotient * Divisor + Remainder = {0}",MPUnit.Add(partialproduct,remainder));

            Console.WriteLine("\nSimple division test");
            int littledivisor = 25;
            MPUnit.Div(dividend,littledivisor, ref quotient, ref remainder);

            Console.WriteLine("Dividend {0}",dividend);
            Console.WriteLine("little Divisor {0}",littledivisor);
            Console.WriteLine("Quotient {0}",quotient);
            Console.WriteLine("Remainder {0}",remainder);
            Console.WriteLine("Quotient * Divisor  = {0}",MPUnit.Mult(quotient,new MPUnit(littledivisor)));
            partialproduct = MPUnit.Mult(quotient,new MPUnit(littledivisor));
            Console.WriteLine("Quotient * Divisor  = {0}",partialproduct);
            Console.WriteLine("Quotient * Divisor + Remainder = {0}",MPUnit.Add(partialproduct,remainder));
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Divides current MPUnit by mpu1, Quotient in q, Remainder in r
        /// </summary>
        /// <param name="mpu1"></param>
        /// <param name="q"></param>
        /// <param name="r"></param>
        /// <returns></returns>
        public static void Div(MPUnit dividend, MPUnit divisor, ref MPUnit q, ref MPUnit r)
        {
            MPUnit mpuInter = new MPUnit();
            MPUnit u = new MPUnit(dividend);
            MPUnit v = new MPUnit(divisor);
            q = new MPUnit();

            // Can't divide by zero
            if(v.numDigits == 0)
                throw new ArgumentException();

            // dividing zero by something else equals zero
            if(u.numDigits == 0)
            {
                q.numDigits=0;
                r.numDigits=0;
                return;
            }

            // if the v only has one digit, use the simple routine
            // BUGBUG, how about pretending v has two digits, then postshifting?
            if(v.numDigits == 1)
            {
                Div(u, v[0], ref q , ref r);
                return;
            }

            // ok, long route
            // normalize to give better qhat estimates
            // this raises number of digits in u by one
            // (top digit may be zero) and does not raise the number
            // of digits in v (since we've just scaled its top
            // digit to be between BASE/2 and BASE
            UInt16 scale = 1;

            int n = v.Digits;
            int m = u.Digits-n;

            int v_msd = v[n-1];

            // scale up v
            while(v_msd < BASE/2)
            {
                v_msd <<= 1;
                scale <<= 1;
            }

            // if no shift occurs, or if the multiplication
            // doesn't cause a carry into a higher digit
            // we will add an additional 0 digit anyway
            int u_inc_digits = u.Digits+1;

            if(scale != 1)
            {
                // This may or may not increment the number of digits in u...
                // must check this
                int digits = u.Digits;
                u = MPUnit.Mult(u,scale);
                v = MPUnit.Mult(v,scale);
            }

            u.Digits=u_inc_digits;

            // initialize j
            for(int j=m; j>=0; j--)
            {
                // generate qhat
                // From Knuth (Uj+nB + Uj+n-1)/(Vn-1)
                long uhat = (((long)u[j+n]) << 16) + ((long)u[j+n-1]) ;
                long vhat = (long)v[n-1];
                long qhat = uhat  / vhat ;
                long rhat = uhat - (qhat * vhat);

                long test1 = qhat*v[n-2];
                long test2 = (BASE * rhat) + ( (j+n-2) >=0 ? (int)u[j+n-2] : (int)0);

                // Make sure we didn't overflow in
                // creating the test values
                Debug.Assert(test1>=0 && test2>=0);

                // decrease qhat by one if it is BASE or test fails
                if(qhat == BASE || test1 > test2)
                {
                    qhat--;
                    rhat += v[n-1];
                    test1 = qhat*v[n-2];
                    test2 = (BASE * rhat) + ( (j+n-2) >=0 ? (int)u[j+n-2] : (int)0);

                    // qhat is still 1 too great
                    if(rhat < BASE && (qhat == BASE || test1>test2))
                    {
                        qhat--;
                    }

                }

                Debug.Assert(qhat < BASE && qhat>=0 && rhat>=0);

                // Multiply and subtract
                // subtract term from top term.Digits digits of u
                // easiest done as a shift of term?

                MPUnit term = MPUnit.Mult(v,(ushort)qhat);
                term.ASL(j);

                // if the result would be negative, then
                // we oopsd again
                if(u.CompareTo(term)<0)
                {
                    qhat--;
                    term = MPUnit.Mult(v,(ushort)qhat);
                    term.ASL(j);
                }

                u = MPUnit.Sub(u,term);

                // set quotient digit
                q[j]=(ushort)qhat;

            }

            q.Trim();
            r = MPUnit.Sub(dividend,MPUnit.Mult(divisor,q));
            r.Trim();

            return;
        }