Annotation of rsaref/source/nn.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.