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)); }
/// <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; }