1 | /* NN.C - natural numbers routines |
---|
2 | */ |
---|
3 | |
---|
4 | /* Copyright (C) RSA Laboratories, a division of RSA Data Security, |
---|
5 | Inc., created 1991. All rights reserved. |
---|
6 | */ |
---|
7 | |
---|
8 | #include "global.h" |
---|
9 | #include "rsaref.h" |
---|
10 | #include "nn.h" |
---|
11 | #include "digit.h" |
---|
12 | |
---|
13 | static NN_DIGIT NN_AddDigitMult PROTO_LIST |
---|
14 | ((NN_DIGIT *, NN_DIGIT *, NN_DIGIT, NN_DIGIT *, unsigned int)); |
---|
15 | static NN_DIGIT NN_SubDigitMult PROTO_LIST |
---|
16 | ((NN_DIGIT *, NN_DIGIT *, NN_DIGIT, NN_DIGIT *, unsigned int)); |
---|
17 | |
---|
18 | static unsigned int NN_DigitBits PROTO_LIST ((NN_DIGIT)); |
---|
19 | |
---|
20 | /* Decodes character string b into a, where character string is ordered |
---|
21 | from most to least significant. |
---|
22 | |
---|
23 | Lengths: a[digits], b[len]. |
---|
24 | Assumes b[i] = 0 for i < len - digits * NN_DIGIT_LEN. (Otherwise most |
---|
25 | significant bytes are truncated.) |
---|
26 | */ |
---|
27 | void NN_Decode (a, digits, b, len) |
---|
28 | NN_DIGIT *a; |
---|
29 | unsigned char *b; |
---|
30 | unsigned int digits, len; |
---|
31 | { |
---|
32 | NN_DIGIT t; |
---|
33 | int j; |
---|
34 | unsigned int i, u; |
---|
35 | |
---|
36 | for (i = 0, j = len - 1; i < digits && j >= 0; i++) { |
---|
37 | t = 0; |
---|
38 | for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8) |
---|
39 | t |= ((NN_DIGIT)b[j]) << u; |
---|
40 | a[i] = t; |
---|
41 | } |
---|
42 | |
---|
43 | for (; i < digits; i++) |
---|
44 | a[i] = 0; |
---|
45 | } |
---|
46 | |
---|
47 | /* Encodes b into character string a, where character string is ordered |
---|
48 | from most to least significant. |
---|
49 | |
---|
50 | Lengths: a[len], b[digits]. |
---|
51 | Assumes NN_Bits (b, digits) <= 8 * len. (Otherwise most significant |
---|
52 | digits are truncated.) |
---|
53 | */ |
---|
54 | void NN_Encode (a, len, b, digits) |
---|
55 | NN_DIGIT *b; |
---|
56 | unsigned char *a; |
---|
57 | unsigned int digits, len; |
---|
58 | { |
---|
59 | NN_DIGIT t; |
---|
60 | int j; |
---|
61 | unsigned int i, u; |
---|
62 | |
---|
63 | for (i = 0, j = len - 1; i < digits && j >= 0; i++) { |
---|
64 | t = b[i]; |
---|
65 | for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8) |
---|
66 | a[j] = (unsigned char)(t >> u); |
---|
67 | } |
---|
68 | |
---|
69 | for (; j >= 0; j--) |
---|
70 | a[j] = 0; |
---|
71 | } |
---|
72 | |
---|
73 | /* Assigns a = b. |
---|
74 | |
---|
75 | Lengths: a[digits], b[digits]. |
---|
76 | */ |
---|
77 | void NN_Assign (a, b, digits) |
---|
78 | NN_DIGIT *a, *b; |
---|
79 | unsigned int digits; |
---|
80 | { |
---|
81 | unsigned int i; |
---|
82 | |
---|
83 | for (i = 0; i < digits; i++) |
---|
84 | a[i] = b[i]; |
---|
85 | } |
---|
86 | |
---|
87 | /* Assigns a = 0. |
---|
88 | |
---|
89 | Lengths: a[digits]. |
---|
90 | */ |
---|
91 | void NN_AssignZero (a, digits) |
---|
92 | NN_DIGIT *a; |
---|
93 | unsigned int digits; |
---|
94 | { |
---|
95 | unsigned int i; |
---|
96 | |
---|
97 | for (i = 0; i < digits; i++) |
---|
98 | a[i] = 0; |
---|
99 | } |
---|
100 | |
---|
101 | /* Assigns a = 2^b. |
---|
102 | |
---|
103 | Lengths: a[digits]. |
---|
104 | Requires b < digits * NN_DIGIT_BITS. |
---|
105 | */ |
---|
106 | void NN_Assign2Exp (a, b, digits) |
---|
107 | NN_DIGIT *a; |
---|
108 | unsigned int b, digits; |
---|
109 | { |
---|
110 | NN_AssignZero (a, digits); |
---|
111 | |
---|
112 | if (b >= digits * NN_DIGIT_BITS) |
---|
113 | return; |
---|
114 | |
---|
115 | a[b / NN_DIGIT_BITS] = (NN_DIGIT)1 << (b % NN_DIGIT_BITS); |
---|
116 | } |
---|
117 | |
---|
118 | /* Computes a = b + c. Returns carry. |
---|
119 | |
---|
120 | Lengths: a[digits], b[digits], c[digits]. |
---|
121 | */ |
---|
122 | NN_DIGIT NN_Add (a, b, c, digits) |
---|
123 | NN_DIGIT *a, *b, *c; |
---|
124 | unsigned int digits; |
---|
125 | { |
---|
126 | NN_DIGIT ai, carry; |
---|
127 | unsigned int i; |
---|
128 | |
---|
129 | carry = 0; |
---|
130 | |
---|
131 | for (i = 0; i < digits; i++) { |
---|
132 | if ((ai = b[i] + carry) < carry) |
---|
133 | ai = c[i]; |
---|
134 | else if ((ai += c[i]) < c[i]) |
---|
135 | carry = 1; |
---|
136 | else |
---|
137 | carry = 0; |
---|
138 | a[i] = ai; |
---|
139 | } |
---|
140 | |
---|
141 | return (carry); |
---|
142 | } |
---|
143 | |
---|
144 | /* Computes a = b - c. Returns borrow. |
---|
145 | |
---|
146 | Lengths: a[digits], b[digits], c[digits]. |
---|
147 | */ |
---|
148 | NN_DIGIT NN_Sub (a, b, c, digits) |
---|
149 | NN_DIGIT *a, *b, *c; |
---|
150 | unsigned int digits; |
---|
151 | { |
---|
152 | NN_DIGIT ai, borrow; |
---|
153 | unsigned int i; |
---|
154 | |
---|
155 | borrow = 0; |
---|
156 | |
---|
157 | for (i = 0; i < digits; i++) { |
---|
158 | if ((ai = b[i] - borrow) > (MAX_NN_DIGIT - borrow)) |
---|
159 | ai = MAX_NN_DIGIT - c[i]; |
---|
160 | else if ((ai -= c[i]) > (MAX_NN_DIGIT - c[i])) |
---|
161 | borrow = 1; |
---|
162 | else |
---|
163 | borrow = 0; |
---|
164 | a[i] = ai; |
---|
165 | } |
---|
166 | |
---|
167 | return (borrow); |
---|
168 | } |
---|
169 | |
---|
170 | /* Computes a = b * c. |
---|
171 | |
---|
172 | Lengths: a[2*digits], b[digits], c[digits]. |
---|
173 | Assumes digits < MAX_NN_DIGITS. |
---|
174 | */ |
---|
175 | void NN_Mult (a, b, c, digits) |
---|
176 | NN_DIGIT *a, *b, *c; |
---|
177 | unsigned int digits; |
---|
178 | { |
---|
179 | NN_DIGIT t[2*MAX_NN_DIGITS]; |
---|
180 | unsigned int bDigits, cDigits, i; |
---|
181 | |
---|
182 | NN_AssignZero (t, 2 * digits); |
---|
183 | |
---|
184 | bDigits = NN_Digits (b, digits); |
---|
185 | cDigits = NN_Digits (c, digits); |
---|
186 | |
---|
187 | for (i = 0; i < bDigits; i++) |
---|
188 | t[i+cDigits] += NN_AddDigitMult (&t[i], &t[i], b[i], c, cDigits); |
---|
189 | |
---|
190 | NN_Assign (a, t, 2 * digits); |
---|
191 | |
---|
192 | /* Zeroize potentially sensitive information. |
---|
193 | */ |
---|
194 | R_memset ((POINTER)t, 0, sizeof (t)); |
---|
195 | } |
---|
196 | |
---|
197 | /* Computes a = b * 2^c (i.e., shifts left c bits), returning carry. |
---|
198 | |
---|
199 | Lengths: a[digits], b[digits]. |
---|
200 | Requires c < NN_DIGIT_BITS. |
---|
201 | */ |
---|
202 | NN_DIGIT NN_LShift (a, b, c, digits) |
---|
203 | NN_DIGIT *a, *b; |
---|
204 | unsigned int c, digits; |
---|
205 | { |
---|
206 | NN_DIGIT bi, carry; |
---|
207 | unsigned int i, t; |
---|
208 | |
---|
209 | if (c >= NN_DIGIT_BITS) |
---|
210 | return (0); |
---|
211 | |
---|
212 | t = NN_DIGIT_BITS - c; |
---|
213 | |
---|
214 | carry = 0; |
---|
215 | |
---|
216 | for (i = 0; i < digits; i++) { |
---|
217 | bi = b[i]; |
---|
218 | a[i] = (bi << c) | carry; |
---|
219 | carry = c ? (bi >> t) : 0; |
---|
220 | } |
---|
221 | |
---|
222 | return (carry); |
---|
223 | } |
---|
224 | |
---|
225 | /* Computes a = c div 2^c (i.e., shifts right c bits), returning carry. |
---|
226 | |
---|
227 | Lengths: a[digits], b[digits]. |
---|
228 | Requires: c < NN_DIGIT_BITS. |
---|
229 | */ |
---|
230 | NN_DIGIT NN_RShift (a, b, c, digits) |
---|
231 | NN_DIGIT *a, *b; |
---|
232 | unsigned int c, digits; |
---|
233 | { |
---|
234 | NN_DIGIT bi, carry; |
---|
235 | int i; |
---|
236 | unsigned int t; |
---|
237 | |
---|
238 | if (c >= NN_DIGIT_BITS) |
---|
239 | return (0); |
---|
240 | |
---|
241 | t = NN_DIGIT_BITS - c; |
---|
242 | |
---|
243 | carry = 0; |
---|
244 | |
---|
245 | for (i = digits - 1; i >= 0; i--) { |
---|
246 | bi = b[i]; |
---|
247 | a[i] = (bi >> c) | carry; |
---|
248 | carry = c ? (bi << t) : 0; |
---|
249 | } |
---|
250 | |
---|
251 | return (carry); |
---|
252 | } |
---|
253 | |
---|
254 | /* Computes a = c div d and b = c mod d. |
---|
255 | |
---|
256 | Lengths: a[cDigits], b[dDigits], c[cDigits], d[dDigits]. |
---|
257 | Assumes d > 0, cDigits < 2 * MAX_NN_DIGITS, |
---|
258 | dDigits < MAX_NN_DIGITS. |
---|
259 | */ |
---|
260 | void NN_Div (a, b, c, cDigits, d, dDigits) |
---|
261 | NN_DIGIT *a, *b, *c, *d; |
---|
262 | unsigned int cDigits, dDigits; |
---|
263 | { |
---|
264 | NN_DIGIT ai, cc[2*MAX_NN_DIGITS+1], dd[MAX_NN_DIGITS], t; |
---|
265 | int i; |
---|
266 | unsigned int ddDigits, shift; |
---|
267 | |
---|
268 | ddDigits = NN_Digits (d, dDigits); |
---|
269 | if (ddDigits == 0) |
---|
270 | return; |
---|
271 | |
---|
272 | /* Normalize operands. |
---|
273 | */ |
---|
274 | shift = NN_DIGIT_BITS - NN_DigitBits (d[ddDigits-1]); |
---|
275 | NN_AssignZero (cc, ddDigits); |
---|
276 | cc[cDigits] = NN_LShift (cc, c, shift, cDigits); |
---|
277 | NN_LShift (dd, d, shift, ddDigits); |
---|
278 | t = dd[ddDigits-1]; |
---|
279 | |
---|
280 | NN_AssignZero (a, cDigits); |
---|
281 | |
---|
282 | for (i = cDigits-ddDigits; i >= 0; i--) { |
---|
283 | /* Underestimate quotient digit and subtract. |
---|
284 | */ |
---|
285 | if (t == MAX_NN_DIGIT) |
---|
286 | ai = cc[i+ddDigits]; |
---|
287 | else |
---|
288 | NN_DigitDiv (&ai, &cc[i+ddDigits-1], t + 1); |
---|
289 | cc[i+ddDigits] -= NN_SubDigitMult (&cc[i], &cc[i], ai, dd, ddDigits); |
---|
290 | |
---|
291 | /* Correct estimate. |
---|
292 | */ |
---|
293 | while (cc[i+ddDigits] || (NN_Cmp (&cc[i], dd, ddDigits) >= 0)) { |
---|
294 | ai++; |
---|
295 | cc[i+ddDigits] -= NN_Sub (&cc[i], &cc[i], dd, ddDigits); |
---|
296 | } |
---|
297 | |
---|
298 | a[i] = ai; |
---|
299 | } |
---|
300 | |
---|
301 | /* Restore result. |
---|
302 | */ |
---|
303 | NN_AssignZero (b, dDigits); |
---|
304 | NN_RShift (b, cc, shift, ddDigits); |
---|
305 | |
---|
306 | /* Zeroize potentially sensitive information. |
---|
307 | */ |
---|
308 | R_memset ((POINTER)cc, 0, sizeof (cc)); |
---|
309 | R_memset ((POINTER)dd, 0, sizeof (dd)); |
---|
310 | } |
---|
311 | |
---|
312 | /* Computes a = b mod c. |
---|
313 | |
---|
314 | Lengths: a[cDigits], b[bDigits], c[cDigits]. |
---|
315 | Assumes c > 0, bDigits < 2 * MAX_NN_DIGITS, cDigits < MAX_NN_DIGITS. |
---|
316 | */ |
---|
317 | void NN_Mod (a, b, bDigits, c, cDigits) |
---|
318 | NN_DIGIT *a, *b, *c; |
---|
319 | unsigned int bDigits, cDigits; |
---|
320 | { |
---|
321 | NN_DIGIT t[2 * MAX_NN_DIGITS]; |
---|
322 | |
---|
323 | NN_Div (t, a, b, bDigits, c, cDigits); |
---|
324 | |
---|
325 | /* Zeroize potentially sensitive information. |
---|
326 | */ |
---|
327 | R_memset ((POINTER)t, 0, sizeof (t)); |
---|
328 | } |
---|
329 | |
---|
330 | /* Computes a = b * c mod d. |
---|
331 | |
---|
332 | Lengths: a[digits], b[digits], c[digits], d[digits]. |
---|
333 | Assumes d > 0, digits < MAX_NN_DIGITS. |
---|
334 | */ |
---|
335 | void NN_ModMult (a, b, c, d, digits) |
---|
336 | NN_DIGIT *a, *b, *c, *d; |
---|
337 | unsigned int digits; |
---|
338 | { |
---|
339 | NN_DIGIT t[2*MAX_NN_DIGITS]; |
---|
340 | |
---|
341 | NN_Mult (t, b, c, digits); |
---|
342 | NN_Mod (a, t, 2 * digits, d, digits); |
---|
343 | |
---|
344 | /* Zeroize potentially sensitive information. |
---|
345 | */ |
---|
346 | R_memset ((POINTER)t, 0, sizeof (t)); |
---|
347 | } |
---|
348 | |
---|
349 | /* Computes a = b^c mod d. |
---|
350 | |
---|
351 | Lengths: a[dDigits], b[dDigits], c[cDigits], d[dDigits]. |
---|
352 | Assumes d > 0, cDigits > 0, dDigits < MAX_NN_DIGITS. |
---|
353 | */ |
---|
354 | void NN_ModExp (a, b, c, cDigits, d, dDigits) |
---|
355 | NN_DIGIT *a, *b, *c, *d; |
---|
356 | unsigned int cDigits, dDigits; |
---|
357 | { |
---|
358 | NN_DIGIT bPower[3][MAX_NN_DIGITS], ci, t[MAX_NN_DIGITS]; |
---|
359 | int i; |
---|
360 | unsigned int ciBits, j, s; |
---|
361 | |
---|
362 | /* Store b, b^2 mod d, and b^3 mod d. |
---|
363 | */ |
---|
364 | NN_Assign (bPower[0], b, dDigits); |
---|
365 | NN_ModMult (bPower[1], bPower[0], b, d, dDigits); |
---|
366 | NN_ModMult (bPower[2], bPower[1], b, d, dDigits); |
---|
367 | |
---|
368 | NN_ASSIGN_DIGIT (t, 1, dDigits); |
---|
369 | |
---|
370 | cDigits = NN_Digits (c, cDigits); |
---|
371 | for (i = cDigits - 1; i >= 0; i--) { |
---|
372 | ci = c[i]; |
---|
373 | ciBits = NN_DIGIT_BITS; |
---|
374 | |
---|
375 | /* Scan past leading zero bits of most significant digit. |
---|
376 | */ |
---|
377 | if (i == (int)(cDigits - 1)) { |
---|
378 | while (! DIGIT_2MSB (ci)) { |
---|
379 | ci <<= 2; |
---|
380 | ciBits -= 2; |
---|
381 | } |
---|
382 | } |
---|
383 | |
---|
384 | for (j = 0; j < ciBits; j += 2, ci <<= 2) { |
---|
385 | /* Compute t = t^4 * b^s mod d, where s = two MSB's of ci. |
---|
386 | */ |
---|
387 | NN_ModMult (t, t, t, d, dDigits); |
---|
388 | NN_ModMult (t, t, t, d, dDigits); |
---|
389 | if ((s = DIGIT_2MSB (ci)) != 0) |
---|
390 | NN_ModMult (t, t, bPower[s-1], d, dDigits); |
---|
391 | } |
---|
392 | } |
---|
393 | |
---|
394 | NN_Assign (a, t, dDigits); |
---|
395 | |
---|
396 | /* Zeroize potentially sensitive information. |
---|
397 | */ |
---|
398 | R_memset ((POINTER)bPower, 0, sizeof (bPower)); |
---|
399 | R_memset ((POINTER)t, 0, sizeof (t)); |
---|
400 | } |
---|
401 | |
---|
402 | /* Compute a = 1/b mod c, assuming inverse exists. |
---|
403 | |
---|
404 | Lengths: a[digits], b[digits], c[digits]. |
---|
405 | Assumes gcd (b, c) = 1, digits < MAX_NN_DIGITS. |
---|
406 | */ |
---|
407 | void NN_ModInv (a, b, c, digits) |
---|
408 | NN_DIGIT *a, *b, *c; |
---|
409 | unsigned int digits; |
---|
410 | { |
---|
411 | NN_DIGIT q[MAX_NN_DIGITS], t1[MAX_NN_DIGITS], t3[MAX_NN_DIGITS], |
---|
412 | u1[MAX_NN_DIGITS], u3[MAX_NN_DIGITS], v1[MAX_NN_DIGITS], |
---|
413 | v3[MAX_NN_DIGITS], w[2*MAX_NN_DIGITS]; |
---|
414 | int u1Sign; |
---|
415 | |
---|
416 | /* Apply extended Euclidean algorithm, modified to avoid negative |
---|
417 | numbers. |
---|
418 | */ |
---|
419 | NN_ASSIGN_DIGIT (u1, 1, digits); |
---|
420 | NN_AssignZero (v1, digits); |
---|
421 | NN_Assign (u3, b, digits); |
---|
422 | NN_Assign (v3, c, digits); |
---|
423 | u1Sign = 1; |
---|
424 | |
---|
425 | while (! NN_Zero (v3, digits)) { |
---|
426 | NN_Div (q, t3, u3, digits, v3, digits); |
---|
427 | NN_Mult (w, q, v1, digits); |
---|
428 | NN_Add (t1, u1, w, digits); |
---|
429 | NN_Assign (u1, v1, digits); |
---|
430 | NN_Assign (v1, t1, digits); |
---|
431 | NN_Assign (u3, v3, digits); |
---|
432 | NN_Assign (v3, t3, digits); |
---|
433 | u1Sign = -u1Sign; |
---|
434 | } |
---|
435 | |
---|
436 | /* Negate result if sign is negative. |
---|
437 | */ |
---|
438 | if (u1Sign < 0) |
---|
439 | NN_Sub (a, c, u1, digits); |
---|
440 | else |
---|
441 | NN_Assign (a, u1, digits); |
---|
442 | |
---|
443 | /* Zeroize potentially sensitive information. |
---|
444 | */ |
---|
445 | R_memset ((POINTER)q, 0, sizeof (q)); |
---|
446 | R_memset ((POINTER)t1, 0, sizeof (t1)); |
---|
447 | R_memset ((POINTER)t3, 0, sizeof (t3)); |
---|
448 | R_memset ((POINTER)u1, 0, sizeof (u1)); |
---|
449 | R_memset ((POINTER)u3, 0, sizeof (u3)); |
---|
450 | R_memset ((POINTER)v1, 0, sizeof (v1)); |
---|
451 | R_memset ((POINTER)v3, 0, sizeof (v3)); |
---|
452 | R_memset ((POINTER)w, 0, sizeof (w)); |
---|
453 | } |
---|
454 | |
---|
455 | /* Computes a = gcd(b, c). |
---|
456 | |
---|
457 | Lengths: a[digits], b[digits], c[digits]. |
---|
458 | Assumes b > c, digits < MAX_NN_DIGITS. |
---|
459 | */ |
---|
460 | void NN_Gcd (a, b, c, digits) |
---|
461 | NN_DIGIT *a, *b, *c; |
---|
462 | unsigned int digits; |
---|
463 | { |
---|
464 | NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS], v[MAX_NN_DIGITS]; |
---|
465 | |
---|
466 | NN_Assign (u, b, digits); |
---|
467 | NN_Assign (v, c, digits); |
---|
468 | |
---|
469 | while (! NN_Zero (v, digits)) { |
---|
470 | NN_Mod (t, u, digits, v, digits); |
---|
471 | NN_Assign (u, v, digits); |
---|
472 | NN_Assign (v, t, digits); |
---|
473 | } |
---|
474 | |
---|
475 | NN_Assign (a, u, digits); |
---|
476 | |
---|
477 | /* Zeroize potentially sensitive information. |
---|
478 | */ |
---|
479 | R_memset ((POINTER)t, 0, sizeof (t)); |
---|
480 | R_memset ((POINTER)u, 0, sizeof (u)); |
---|
481 | R_memset ((POINTER)v, 0, sizeof (v)); |
---|
482 | } |
---|
483 | |
---|
484 | /* Returns sign of a - b. |
---|
485 | |
---|
486 | Lengths: a[digits], b[digits]. |
---|
487 | */ |
---|
488 | int NN_Cmp (a, b, digits) |
---|
489 | NN_DIGIT *a, *b; |
---|
490 | unsigned int digits; |
---|
491 | { |
---|
492 | int i; |
---|
493 | |
---|
494 | for (i = digits - 1; i >= 0; i--) { |
---|
495 | if (a[i] > b[i]) |
---|
496 | return (1); |
---|
497 | if (a[i] < b[i]) |
---|
498 | return (-1); |
---|
499 | } |
---|
500 | |
---|
501 | return (0); |
---|
502 | } |
---|
503 | |
---|
504 | /* Returns nonzero iff a is zero. |
---|
505 | |
---|
506 | Lengths: a[digits]. |
---|
507 | */ |
---|
508 | int NN_Zero (a, digits) |
---|
509 | NN_DIGIT *a; |
---|
510 | unsigned int digits; |
---|
511 | { |
---|
512 | unsigned int i; |
---|
513 | |
---|
514 | for (i = 0; i < digits; i++) |
---|
515 | if (a[i]) |
---|
516 | return (0); |
---|
517 | |
---|
518 | return (1); |
---|
519 | } |
---|
520 | |
---|
521 | /* Returns the significant length of a in bits. |
---|
522 | |
---|
523 | Lengths: a[digits]. |
---|
524 | */ |
---|
525 | unsigned int NN_Bits (a, digits) |
---|
526 | NN_DIGIT *a; |
---|
527 | unsigned int digits; |
---|
528 | { |
---|
529 | if ((digits = NN_Digits (a, digits)) == 0) |
---|
530 | return (0); |
---|
531 | |
---|
532 | return ((digits - 1) * NN_DIGIT_BITS + NN_DigitBits (a[digits-1])); |
---|
533 | } |
---|
534 | |
---|
535 | /* Returns the significant length of a in digits. |
---|
536 | |
---|
537 | Lengths: a[digits]. |
---|
538 | */ |
---|
539 | unsigned int NN_Digits (a, digits) |
---|
540 | NN_DIGIT *a; |
---|
541 | unsigned int digits; |
---|
542 | { |
---|
543 | int i; |
---|
544 | |
---|
545 | for (i = digits - 1; i >= 0; i--) |
---|
546 | if (a[i]) |
---|
547 | break; |
---|
548 | |
---|
549 | return (i + 1); |
---|
550 | } |
---|
551 | |
---|
552 | /* Computes a = b + c*d, where c is a digit. Returns carry. |
---|
553 | |
---|
554 | Lengths: a[digits], b[digits], d[digits]. |
---|
555 | */ |
---|
556 | static NN_DIGIT NN_AddDigitMult (a, b, c, d, digits) |
---|
557 | NN_DIGIT *a, *b, c, *d; |
---|
558 | unsigned int digits; |
---|
559 | { |
---|
560 | NN_DIGIT carry, t[2]; |
---|
561 | unsigned int i; |
---|
562 | |
---|
563 | if (c == 0) |
---|
564 | return (0); |
---|
565 | |
---|
566 | carry = 0; |
---|
567 | for (i = 0; i < digits; i++) { |
---|
568 | NN_DigitMult (t, c, d[i]); |
---|
569 | if ((a[i] = b[i] + carry) < carry) |
---|
570 | carry = 1; |
---|
571 | else |
---|
572 | carry = 0; |
---|
573 | if ((a[i] += t[0]) < t[0]) |
---|
574 | carry++; |
---|
575 | carry += t[1]; |
---|
576 | } |
---|
577 | |
---|
578 | return (carry); |
---|
579 | } |
---|
580 | |
---|
581 | /* Computes a = b - c*d, where c is a digit. Returns borrow. |
---|
582 | |
---|
583 | Lengths: a[digits], b[digits], d[digits]. |
---|
584 | */ |
---|
585 | static NN_DIGIT NN_SubDigitMult (a, b, c, d, digits) |
---|
586 | NN_DIGIT *a, *b, c, *d; |
---|
587 | unsigned int digits; |
---|
588 | { |
---|
589 | NN_DIGIT borrow, t[2]; |
---|
590 | unsigned int i; |
---|
591 | |
---|
592 | if (c == 0) |
---|
593 | return (0); |
---|
594 | |
---|
595 | borrow = 0; |
---|
596 | for (i = 0; i < digits; i++) { |
---|
597 | NN_DigitMult (t, c, d[i]); |
---|
598 | if ((a[i] = b[i] - borrow) > (MAX_NN_DIGIT - borrow)) |
---|
599 | borrow = 1; |
---|
600 | else |
---|
601 | borrow = 0; |
---|
602 | if ((a[i] -= t[0]) > (MAX_NN_DIGIT - t[0])) |
---|
603 | borrow++; |
---|
604 | borrow += t[1]; |
---|
605 | } |
---|
606 | |
---|
607 | return (borrow); |
---|
608 | } |
---|
609 | |
---|
610 | /* Returns the significant length of a in bits, where a is a digit. |
---|
611 | */ |
---|
612 | static unsigned int NN_DigitBits (a) |
---|
613 | NN_DIGIT a; |
---|
614 | { |
---|
615 | unsigned int i; |
---|
616 | |
---|
617 | for (i = 0; i < NN_DIGIT_BITS; i++, a >>= 1) |
---|
618 | if (a == 0) |
---|
619 | break; |
---|
620 | |
---|
621 | return (i); |
---|
622 | } |
---|