1 /* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */
2 /* Last modified_on Fri Mar 30 3:29:17 GMT+2:00 1990 by shand */
3 /* modified_on Fri Apr 28 18:36:28 GMT+2:00 1989 by herve */
6 /* bnDivide.c: a piece of the bignum kernel written in C */
9 /***************************************/
16 static char copyright[]="@(#)bnDivide.c: copyright Digital Equipment Corporation & INRIA 1988, 1989, 1990\n";
19 static divide (nn, nl, dd, dl)
22 register BigNumLength nl, dl;
27 * Input (N has been EXTENDED by 1 PLACE; D is normalized):
28 * +-----------------------------------------------+----+
30 * +-----------------------------------------------+----+
32 * +-------------------------------+
34 * +-------------------------------+
36 * Output (in place of N):
37 * +-------------------------------+---------------+----+
39 * +-------------------------------+---------------+----+
44 * last digit of N < last digit of D
45 * D is normalized (Base/2 <= last digit of D < Base)
50 BigNumDigit DDigit, BaseMinus1, QApp, RApp;
53 /* Initialize constants */
54 BnnSetDigit (&BaseMinus1, 0);
55 BnnComplement(&BaseMinus1, 1);
57 /* Save the most significant digit of D */
58 BnnAssign (&DDigit, dd+dl-1, 1);
60 /* Replace D by Base - D */
61 BnnComplement (dd, dl);
62 BnnAddCarry (dd, dl, 1);
64 /* For each digit of the divisor, from most significant to least: */
69 /* Compute the approximate quotient */
72 /* If first digits of numerator and denominator are the same, */
73 if (BnnCompareDigits (*(nn+nl), DDigit) == BN_EQ)
74 /* Use "Base - 1" for the approximate quotient */
75 BnnAssign (&QApp, &BaseMinus1, 1);
77 /* Divide the first 2 digits of N by the first digit of D */
78 RApp = BnnDivideDigit (&QApp, nn+nl-1, 2, DDigit);
80 /* Compute the remainder */
81 BnnMultiplyDigit (nn+ni, dl+1, dd, dl, QApp);
83 /* Correct the approximate quotient, in case it was too large */
84 while (BnnCompareDigits (*(nn+nl), QApp) != BN_EQ)
86 BnnSubtract (nn+ni, dl+1, dd, dl, 1); /* Subtract D from N */
87 BnnSubtractBorrow (&QApp, 1, 0); /* Q -= 1 */
91 /* Restore original D */
92 BnnComplement (dd, dl);
93 BnnAddCarry (dd, dl, 1);
97 /***************************************/
101 void BnnDivide (nn, nl, dd, dl)
104 register BigNumLength nl, dl;
107 * Performs the quotient:
108 * N div D => high-order bits of N, starting at N[dl]
109 * N mod D => low-order dl bits of N
113 * last digit of N < last digit of D (if N > D).
120 /* Take care of easy cases first */
121 switch (BnnCompare (nn, nl, dd, dl))
123 case BN_LT: /* n < d */
125 BnnSetToZero (nn+dl, nl-dl); /* 0 => Q */
127 case BN_EQ: /* n == d */
128 BnnSetToZero (nn, nl); /* 0 => R */
129 BnnSetDigit (nn+nl-1, 1); /* 1 => Q */
135 /* If divisor is just 1 digit, use a special divide */
137 *nn = BnnDivideDigit (nn+1, nn, nl, *dd); /* note: nn+1 = nn+dl */
138 /* Otherwise, divide one digit at a time */
142 nshift = BnnNumLeadingZeroBitsInDigit (*(dd+dl-1));
143 BnnShiftLeft (dd, dl, nshift);
144 BnnShiftLeft (nn, nl, nshift);
147 divide (nn, nl-1, dd, dl);
150 BnnShiftRight (dd, dl, nshift);
151 BnnShiftRight (nn, dl, nshift);
152 /* note: unnormalize N <=> unnormalize R (with R < D) */