Computer Programming Contest Preparation

ToolBox - Source for: 3/324/LargeNumber.c



/home/toolbox/public_html/solutions/3/324/LargeNumber.c
    1 /*
    2  * LargeNumber library
    3  *
    4  * authors: Isaac Traxler & students
    5  *
    6  * This is a project started back in 2000 that was not finished
    7  * and forgotten. It has now been resurrected.
    8  *
    9  * The goal of this project is to produce a usable c source library
   10  * for large number arithmetic.
   11  *
   12  * Students in my Psychology of Programming class in 2000 contributed.
   13  * Since I have largely restructured it, individual names have been
   14  * removed from the individual routines. So here are the names of the
   15  * original contributing students:
   16  * - Paul Miller
   17  * - Wojciech Stryjewski
   18  * - Phil Bordelon
   19  * - John Walker
   20  * - Erin Valentine
   21  * - Jay Ponville
   22  * - Jamie Ahmad
   23  * - Helen
   24  *
   25  * Contributed to revamped version:
   26  * - Josh Abadie
   27  */
   28 /* Updates:
   29  * 20210205 IWT change strncpy to sprintf (for initializing string)
   30  * 20210205 IWT convert comments from C++ (//) style to C style
   31  */
   32 #include <ctype.h>
   33 /*
   34  * Make sure that LN_MAX_DIGITS is large enough to handle worst case.
   35  * Be aware that as many as 5 LN instances might exist in a routine.
   36  * Be aware that excessively large values will result in CPU consumption
   37  *  in certain situations (like division of repeating decimals).
   38  */
   39 #define LN_MAX_DIGITS 1000
   40 
   41 typedef struct LARGE_NUMBER_STRUCT
   42 {
   43     unsigned short int array[LN_MAX_DIGITS]; /* might consider unsigned char here
   44                                               * to reduce storage by 50% */
   45     signed short   int sign;
   46     signed long    int exponent;
   47     signed short   int digitCount;
   48 }
   49 LARGE_NUMBER_STRUCT;
   50 /*
   51  * ASSUMPTIONS:
   52  * 1) That no value sent to the library will exceed bounds
   53  *    a) Exponent will fit into a signed long at ALL times
   54  *    b) Significant digit count will not exceed LN_MAX_DIGITS
   55  *
   56  * 2) LN instances are ALWAYS normalized when passed into a routine
   57  *
   58  * 3) Adding or subtracting two 501 digit numbers can exceed 1000 digits
   59  *
   60  * 4) No bounds checking is done against LN_MAX_DIGITS
   61  *
   62  * 5) Normalization does the following:
   63  *    a) Adjusts exponent, adjusts digitCount, and removes leading zeroes
   64  *    b) Adjusts digitCount and removes trailing zeroes
   65  *    c) Leaves number so that a decimal point is implied before the first digit
   66  *
   67  *
   68  * ********************************************************************************
   69  * rules:
   70  * - all routines return 0 if everything is okay, a different positive number
   71  *   for each different error
   72  * - Any result passed back (except from LNshift) is normalized
   73  * - LNadd adds any two numbers with same sign (calls subtract if signs differ)
   74  * - LNsubtract subtracts any two numbers with same sign (calls add if signs differ)
   75  *
   76  * a = 1
   77  * b = -1
   78  * add(a,b,c) ==> subtract(a,(-b),c)
   79  * subtract(a,b,c) ==> add(a,(-b),c)
   80  *
   81  * - 0 ALWAYS has a + sign and an exponent of 0
   82  *
   83  */
   84 
   85 void LNprint(LARGE_NUMBER_STRUCT *n)
   86 /* simple routine to print large number */
   87 {
   88     /* BEGIN function LNprint -- (200302) */
   89     char str[LN_MAX_DIGITS+25];
   90 
   91     LNarr2strExp(n, str);
   92     printf("[%s]\n", str);
   93 } /* END function LNprint -- (200302)  */
   94 
   95 int LNnegate(LARGE_NUMBER_STRUCT *ln1)
   96 /* changes sign of ln1  */
   97 {
   98     /* BEGIN function LNnegate -- (200302)  */
   99     if (0 != ln1->digitCount)
  100         ln1->sign *= -1;
  101     return 0;
  102 } /* END function LNnegate -- (200302)  */
  103 
  104 int LNcompare(LARGE_NUMBER_STRUCT *ln1, LARGE_NUMBER_STRUCT *ln2)
  105 /* compares to see if a<b (-1), a=b (0), a>b (1); assumes both numbers */
  106 /* are normalized (have first digit non-zero and no trailing zeros) */
  107 {
  108     /* BEGIN function LNcompare -- (200303)  */
  109     int toReturn = 0;
  110 
  111     /* XOR the two, if same 0 (false) results, if different -2 (true)  */
  112     if (ln1->sign ^ ln2->sign) /* signs are same, result is 0  */
  113         {
  114             /* have different signs  */
  115             toReturn = (0 > ln1->sign) ? -1 : 1;
  116         } /* have different signs  */
  117     else
  118         {
  119             /* have same sign  */
  120             if (ln1->exponent != ln2->exponent)
  121                 {
  122                     /* exponents not equal, return 1 (1st one) or -1 (2nd one) to show larger  */
  123                     toReturn = (ln1->exponent > ln2->exponent) ? 1 : -1;
  124                 } /* exponents not equal, return 1 (1st one) or -1 (2nd one) to show larger  */
  125             else
  126                 {
  127                     /* numbers have same exponent */
  128                     int i, t;
  129 
  130                     t = (ln1->digitCount > ln2->digitCount) ? ln2->digitCount : ln1->digitCount;
  131                     for (i=0; (i<t) && (0 == toReturn) ; i++)
  132                         {
  133                             /* for - compare each digit  */
  134                             if (ln1->array[i] != ln2->array[i])
  135                                 toReturn = (ln1->array[i] > ln2->array[i]) ? ln1->sign : - ln2->sign;
  136                         } /* for - compare each digit  */
  137                     /* digits identical, but one number has extra digits, so number with extra digits */
  138                     /* is bigger if positive, smaller if negative. */
  139                     if ((0 == toReturn) && (ln1->digitCount != ln2->digitCount))
  140                         toReturn = (ln1->digitCount > ln2->digitCount) ? ln1->sign : - ln2->sign;
  141                 } /* numbers have same exponent */
  142         } /* have same sign  */
  143     return toReturn;
  144 } /* END function LNcompare -- (200303)  */
  145 
  146 int LNstr2arr(char str[], LARGE_NUMBER_STRUCT *ln)
  147 /* convert from string into LN data structure
  148  * assume no invalid characters in string (but skip over leading and trailing blanks)
  149  *
  150  * State diagram:
  151  *
  152  * state | val | whitespace | -    | +    | .    | digit | Ee   | end of string`
  153  * ------+-----+------------+------+------+------+-------+------+--------------
  154  * start | 1   | start      | num1 | num1 | dec1 | num2  | err  | 0
  155  * num1  | 2   | err        | err  | err  | dec1 | num2  | err  | err
  156  * num2  | 3   | normalize  | err  | err  | dec2 | num2  | exp1 | normalize
  157  * dec1  | 4   | err        | err  | err  | err  | dec2  | err  | err
  158  * dec2  | 5   | normalize  | err  | err  | err  | dec2  | exp1 | normalize
  159  * exp1  | 6   | err        | exp2 | exp2 | err  | exp3  | err  | err
  160  * exp2  | 7   | err        | err  | err  | err  | exp3  | err  | err
  161  * exp3  | 8   | normalize  | err  | err  | err  | exp3  | err  | normalize
  162  */
  163 {
  164     /* BEGIN function LNstr2arr -- (200302)  */
  165 #define START  1
  166 #define NUM1   2
  167 #define NUM2   3
  168 #define DEC1   4
  169 #define DEC2   5
  170 #define EXP1   6
  171 #define EXP2   7
  172 #define EXP3   8
  173     /*
  174      * status -  (succes/failure) flag  (init to SUCCESS)
  175      * done - are we done yet?  (init to NO)
  176      * dpflag - decimal point flag - Have we encountered one yet? (init to NO)
  177      * numflag - number flag - Have we encountered any NON-ZERO digits yet? (init to NO)
  178      * n - counter/subscript for large number (init to start)
  179      * ch - point to main string
  180      * These next two need not be used if their values are stored directly into large number.
  181      *   sign
  182      *   exp
  183      */
  184     int state = START, done = 0, n = 0;
  185     signed short int dpflag = 0, numflag = 0, sign = 1;
  186     signed long int exp;
  187     char *ch = str;
  188 
  189     /* skip leading blanks and leading zeroes (start < > start)
  190        while ( (isspace(*ch)) || ('0' == *ch) ) ch++; */
  191 
  192     if (0 != *ch) /* is it end of string?  */
  193         {
  194             /* not empty string */
  195             /* do we have a sign (must be first char)  */
  196             if ('-' == *ch)
  197                 {
  198                     /* negative - state is NUM1 */
  199                     sign = -1;
  200                     ch++;
  201                 } /* negative - state is NUM1 */
  202             else
  203                 /* Check for plus sign: Not really necessary...(these 4 lines may  */
  204                 /* be omitted) if numbers are not going to have unary pluses */
  205                 if (*ch == '+')
  206                     {
  207                         /* positive (the default) - state is NUM1 */
  208                         ch++;
  209                     } /* positive (the default) - state is NUM1 */
  210 
  211             /* now get digits until the decimal point or exponent */
  212             while (isdigit(*ch))
  213                 {
  214                     /* process digits -- into state NUM2 */
  215                     state = NUM2;
  216                     ln->array[n++] = *ch - '0';
  217                     ch++;  /* move to next char in string */
  218                 } /* process digits -- into state NUM2 */
  219             exp = n;
  220 
  221             if ('.' == *ch)
  222                 {
  223                     /* decimal point  */
  224                     /* set state to DEC1 if no digits, DEC2 if digits already */
  225                     state = (NUM2 != state) ? DEC1 : DEC2;
  226                     ch++;
  227 
  228                     /* now get digits after the decimal point */
  229                     if (isdigit(*ch)) state = DEC2;
  230                     while (isdigit(*ch))
  231                         {
  232                             /* process digits -- into state NUM2 */
  233                             ln->array[n++] = *ch - '0';
  234                             ch++;  /* move to next char in string */
  235                         } /* process digits -- into state NUM2 */
  236                 } /* decimal point */
  237 
  238             /* only things left are Ee (exponent), whitespace and end of string */
  239             if (('E' == *ch) || ('e' == *ch))
  240                 {
  241                     /* okay we have an exponent */
  242                     signed long int texp;
  243 
  244                     state = EXP2;
  245                     ch++;
  246                     sscanf(ch, "%d", &texp);
  247                     exp += texp;
  248                 } /* okay we have an exponent */
  249         } /* not empty string */
  250 
  251     if ((EXP2 == state) || (DEC2 == state) || (NUM2 == state))
  252         {
  253             /* normalize number */
  254             ln->sign = sign;
  255             ln->exponent = exp;
  256             ln->digitCount = n;
  257             state = 0;
  258         } /* normalize number */
  259     return state;
  260 } /* END function LNstr2arr -- (200302)  */
  261 
  262 int LNicnvrt(long int number, LARGE_NUMBER_STRUCT *n)
  263 /* convert a long int to Large Number  */
  264 {
  265     /* BEGIN function LNicnvrt -- (200302)  */
  266     int idx, digit, j;
  267 
  268     /* do sign  */
  269     n->sign = (number < 0) ? -1 : 1;
  270 
  271     /* set mantissa and exponent  */
  272     n->exponent = 0;
  273     idx = LN_MAX_DIGITS;
  274     while (number > 0)
  275         {
  276             /* while  */
  277             digit = number % 10;
  278             n->array[--idx] = digit;
  279             number /= 10;
  280         } /* while  */
  281     n->exponent = LN_MAX_DIGITS - idx;
  282     n->digitCount = n->exponent;
  283     for (j=0; LN_MAX_DIGITS > (j + idx); j++)
  284         {
  285             /* for  */
  286             n->array[j] = n->array[idx+j];
  287         } /* for  */
  288     return 0;
  289 } /* END function LNicnvrt -- (200302)  */
  290 
  291 int LNarr2strExp(LARGE_NUMBER_STRUCT *ln, char str[])
  292 /* convert the ln struct to a string in scientific notation  */
  293 {
  294     /* BEGIN function LNarr2strExp -- (200302)  */
  295     int i, cnt = 0;
  296 
  297     if (0 == ln->digitCount)
  298         {
  299             /* handle zero  */
  300             sprintf(str, "+0E0");
  301         } /* handle zero  */
  302     else
  303         {
  304             /* handle non-zero  */
  305             str[cnt++] = (0 > ln->sign) ? '-' : '+';
  306             str[cnt++] = '0' + ln->array[0];
  307             str[cnt++] = '.';
  308             for (i = 1; i < ln->digitCount; i++)
  309                 str[cnt++] = '0' + ln->array[i];
  310             str[cnt++] = 'E';
  311             sprintf(&(str[cnt]), "%+ld", (ln->exponent-1));
  312         } /* handle non-zero  */
  313     return 0;
  314 } /* END function LNarr2strExp -- (200302)  */
  315 
  316 int LNarr2strInt(LARGE_NUMBER_STRUCT *ln, char str[])
  317 /* convert the ln struct to a string n integer format with truncate  */
  318 {
  319     /* BEGIN function LNarr2strInt -- (200302)  */
  320     int i, cnt = 0;
  321 
  322     if ((0 > ln->exponent) || (0 >= ln->digitCount))
  323         {
  324             /* abs(number) less than 0 or number is zero */
  325             sprintf(str, "+0");
  326         } /* abs(number) less than 0 or number is zero */
  327     else
  328         {
  329             /* something to convert */
  330             int x;
  331 
  332             str[cnt++] = (0 > ln->sign) ? '-' : '+';
  333             x = (ln->exponent > ln->digitCount) ? ln->digitCount : ln->exponent;
  334             for (i = 0; i < x; i++)
  335                 str[cnt++] = '0' + ln->array[i];
  336             x = ln->exponent - ln->digitCount;
  337             for (i=0; i < x; i++)
  338                 str[cnt++] = '0';
  339             str[cnt] = 0;
  340         } /* something to convert  */
  341     return 0;
  342 } /* END function LNstrInt -- (200302)  */
  343 
  344 int LNln2strFloat(LARGE_NUMBER_STRUCT *ln, char str[])
  345 /* convert the ln struct to a string in float format  */
  346 {
  347     /* BEGIN function LNln2strFloat -- (200302)  */
  348     int i, cnt = 0;
  349 
  350     if (0 == ln->digitCount)
  351         {
  352             /* handle 0  */
  353             sprintf(str, "+0.0");
  354         } /* handle 0  */
  355     else
  356         {
  357             /* not zero  */
  358             int x1, x2;
  359 
  360             str[cnt++] = (0 > ln->sign) ? '-' : '+';
  361             x1 = (ln->exponent > ln->digitCount) ? ln->digitCount : ln->exponent;
  362             for (i = 0; i < x1; i++)
  363                 str[cnt++] = '0' + ln->array[i];
  364             x2 = ln->exponent - ln->digitCount;
  365             if (0 > x2)
  366                 {
  367                     /* digitCount larger */
  368                     str[cnt++] = '.';
  369                     for (i = x1; i < ln->digitCount; i++)
  370                         str[cnt++] = '0' + ln->array[i];
  371                 } /* digitCount larger */
  372             else
  373                 {
  374                     /* exponent larger */
  375                     for (i=0; i < x2; i++)
  376                         str[cnt++] = '0';
  377                     str[cnt++] = '.';
  378                     str[cnt++] = '0';
  379                 } /* exponent larger */
  380             str[cnt++] = 0;
  381         } /* not zero  */
  382     return 0;
  383 } /* END function LNstrFloat -- (200302)  */
  384 
  385 int LNshift(LARGE_NUMBER_STRUCT *ln, int cnt)
  386 /* shift the implied decimal point  */
  387 {
  388     /* BEGIN function LiNshift -- (200302)  */
  389     /* errorLevel - Errorlevel to return.  */
  390     /* i - Loop variable.  */
  391     int i, errorLevel = 0;
  392 
  393     if (0 < ln->digitCount)
  394         if (0 < cnt)
  395             {
  396                 /* non-negative - do the shift */
  397                 for ((i = ln->digitCount - 1); i >= 0 ; i --)
  398                     ln->array[i + cnt] = ln->array[i];
  399                 for (i = 0; i < cnt; i ++)
  400                     ln->array[i] = 0;
  401                 ln->exponent += cnt;
  402                 ln->digitCount += cnt;
  403             } /* non-negative - do the shift */
  404         else if (0 != cnt)
  405             {
  406                 /* can't do it */
  407                 fprintf (stderr, "Error: Cannot shift negative bits.\n");
  408                 errorLevel = 1;
  409             } /* can't do it */
  410     return errorLevel;
  411 } /* END function LNshift -- (200302)  */
  412 
  413 int LNnormalize(LARGE_NUMBER_STRUCT *ln)
  414 /* fix LN so that arr[0] <> 0 (if possible)  */
  415 {
  416     /* BEGIN function LNnormalize -- (200302)  */
  417     /* errorLevel - Errorlevel to return.
  418      * zeroCount - How many zeroes?
  419      * i - Loop variable
  420      */
  421     int i, errorLevel = 0, zeroCount = 0;
  422 
  423     if (0 < ln->digitCount)
  424         {
  425             /* digits to process */
  426             while ((ln->array[zeroCount] == 0) && (zeroCount < ln->digitCount))
  427                 {
  428                     /* count leading zeroes */
  429                     zeroCount ++;
  430                 } /* count leading zeroes */
  431             if (0 < zeroCount)
  432                 {
  433                     /* found leading zeroes */
  434                     if (zeroCount == ln->digitCount)
  435                         {
  436                             /* entire number is zero */
  437                             ln->exponent = 0;
  438                             ln->digitCount = 0;
  439                             ln->sign = 1;
  440                         } /* entire number is zero */
  441                     else
  442                         {
  443                             /* digits to shift */
  444                             ln->digitCount -= zeroCount;
  445                             ln->exponent -= zeroCount;
  446                             for (i = 0; i < ln->digitCount; i++)
  447                                 {
  448                                     /* shift them */
  449                                     ln->array[i] = ln->array[i + zeroCount];
  450                                 } /* shift them */
  451                         } /* digits to shift */
  452                 } /* found leading zeroes */
  453             /* handle railing zeroes  */
  454             i = ln->digitCount - 1;
  455             while ((i >= 0) && (0 == ln->array[i]))
  456                 {
  457                     /* while */
  458                     ln->digitCount--;
  459                     i--;
  460                 } /* while */
  461             if (0 == ln->digitCount)
  462                 {
  463                     /* entire number is zero */
  464                     ln->exponent = 0;
  465                     ln->sign = 1;
  466                 } /* entire number is zero */
  467         } /* digits to process */
  468     return (errorLevel);
  469 } /* END function LNnormalize -- (200302)  */
  470 
  471 int LNadd(LARGE_NUMBER_STRUCT *lna, LARGE_NUMBER_STRUCT *lnb,
  472           LARGE_NUMBER_STRUCT *ln3)
  473 /* ln3=ln1+ln2        */
  474 {
  475     /* BEGIN function LNadd  -- (200302)  */
  476     int i, cnt, state = 0, carry = 0;
  477     LARGE_NUMBER_STRUCT ln1, ln2;
  478 
  479     if (0 == lna->digitCount)
  480         *ln3 = *lnb;
  481     else if (0 == lnb->digitCount)
  482         *ln3 = *lna;
  483     else
  484         {
  485             /* add non-zero numbers  */
  486             ln1 = *lna;
  487             ln2 = *lnb;
  488             if (ln1.sign != ln2.sign)
  489                 {
  490                     /* signs different  */
  491                     LNnegate(&ln2);
  492                     state = LNsubtract(&ln1, &ln2, ln3);
  493                 } /* signs different  */
  494             else
  495                 {
  496                     /* signs are same -- continue adding */
  497                     if (ln1.exponent > ln2.exponent)
  498                         {
  499                             /* ln1 is bigger */
  500                             LNshift(&ln1, 1);
  501                             LNshift(&ln2, (ln1.exponent - ln2.exponent));
  502                         } /* ln1 is bigger */
  503                     else
  504                         {
  505                             /* ln2 is bigger */
  506                             LNshift(&ln2, 1);
  507                             LNshift(&ln1, (ln2.exponent - ln1.exponent));
  508                         } /* ln2 is bigger */
  509 
  510                     if (ln1.digitCount > ln2.digitCount)
  511                         {
  512                             /* 1 has more digits */
  513                             for (i = ln1.digitCount - 1; i >= ln2.digitCount; i--)
  514                                 ln3->array[i] = ln1.array[i];
  515                             cnt = ln2.digitCount;
  516                             ln3->digitCount = ln1.digitCount;
  517                         } /* 1 has more digits */
  518                     else
  519                         {
  520                             /* 2 has more digits */
  521                             for (i = ln2.digitCount - 1; i >= ln1.digitCount; i--)
  522                                 ln3->array[i] = ln2.array[i];
  523                             cnt = ln1.digitCount;
  524                             ln3->digitCount = ln2.digitCount;
  525                         } /* 2 has more digits */
  526                     /* now actually add */
  527                     ln3->exponent = ln1.exponent;
  528                     for (i = cnt - 1; i >= 0;  i--)
  529                         {
  530                             /* for */
  531                             ln3->array[i] = ln1.array[i] + ln2.array[i] + carry;
  532                             if (ln3->array[i] > 9)
  533                                 {
  534                                     /* set carry */
  535                                     carry = 1;
  536                                     ln3->array[i] -= 10;
  537                                 } /* set carry */
  538                             else
  539                                 {
  540                                     /* reset carry */
  541                                     carry = 0;
  542                                 } /* reset carry */
  543                         } /* for */
  544                     LNnormalize(ln3);
  545                 } /* signs are same -- continue adding */
  546         } /* add non-zero numbers  */
  547     return state;
  548 } /* END function LNadd -- (200302)  */
  549 
  550 int LNsubtract(LARGE_NUMBER_STRUCT *lna, LARGE_NUMBER_STRUCT *lnb,
  551                LARGE_NUMBER_STRUCT *ln3)
  552 /* ln3=ln1-ln2  */
  553 {
  554     /* BEGIN function LNsubtract -- (200303)  */
  555     int toReturn = 0;
  556     LARGE_NUMBER_STRUCT ln1, ln2;
  557 
  558     ln1 = *lna;
  559     ln2 = *lnb;
  560 
  561     if (0 == lna->digitCount)
  562         {
  563             /* first number is zero  */
  564             *ln3 = *lnb;
  565             LNnegate(ln3);
  566         } /* first number is zero  */
  567     else if (0 == lnb->digitCount)
  568         *ln3 = *lna;
  569     else
  570         {
  571             /* subtract non-zero numbers  */
  572             if (ln1.sign != ln2.sign)
  573                 {
  574                     /* signs different  */
  575                     LNnegate(&ln2);
  576                     toReturn = LNadd(&ln1, &ln2, ln3);
  577                 } /* signs different  */
  578             else
  579                 {
  580                     /* signs are same - so subtract    */
  581                     int t, i, tmp, borrow = 0;
  582 
  583                     t = LNcompare(&ln1, &ln2);
  584                     if (0 == t)
  585                         {
  586                             /* same number - return 9  */
  587                             ln3->sign = 1;
  588                             ln3->exponent = 0;
  589                             ln3->digitCount = 0;
  590                         } /* same number - return 9  */
  591                     else if (0 > t)
  592                         {
  593                             /* first number smaller  */
  594                             toReturn = LNsubtract(&ln2, &ln1, ln3);
  595                             ln3->sign = -1 * ln3->sign;
  596                         } /* first number smaller  */
  597                     else
  598                         {
  599                             /* everything okay - actually subtract  */
  600                             ln3->sign = ln1.sign;
  601                             ln3->exponent = ln1.exponent;
  602                             LNshift(&ln2, (ln1.exponent - ln2.exponent));
  603                             if (ln1.digitCount != ln2.digitCount)
  604                                 if (ln1.digitCount > ln2.digitCount)
  605                                     {
  606                                         /* add zeroes to ln2  */
  607                                         for (i=ln2.digitCount; i < ln1.digitCount; i++)
  608                                             ln2.array[i] = 0;
  609                                         ln2.digitCount = ln1.digitCount;
  610                                     } /* add zeroes to ln2  */
  611                                 else
  612                                     {
  613                                         /* add zeroes to ln1  */
  614                                         for (i=ln1.digitCount; i < ln2.digitCount; i++)
  615                                             ln1.array[i] = 0;
  616                                         ln1.digitCount = ln2.digitCount;
  617                                     } /* add zeroes to ln1  */
  618 
  619                             for (i = ln1.digitCount - 1; i >= 0; i--)
  620                                 {
  621                                     /* loop through each digit   */
  622                                     tmp = borrow + ln2.array[i];
  623                                     if (ln1.array[i] > tmp)
  624                                         {
  625                                             /* no borrow  */
  626                                             ln3->array[i] = ln1.array[i] - tmp;
  627                                             borrow = 0;
  628                                         } /* no borrow  */
  629                                     else
  630                                         {
  631                                             /* have to borrow  */
  632                                             ln3->array[i] = (10 + ln1.array[i]) - tmp;
  633                                             borrow = 1;
  634                                         } /* have to borrow  */
  635                                 } /* loop through each digit   */
  636                             LNnormalize(ln3);
  637                         } /* everything okay - actually subtract  */
  638                 } /* signs are same - so subtract    */
  639         } /* subtract non-zero numbers  */
  640     return toReturn;
  641 } /* END function LNsubtract -- (200303)  */
  642 
  643 int LNmultiply(LARGE_NUMBER_STRUCT *ln1, LARGE_NUMBER_STRUCT *ln2,
  644                LARGE_NUMBER_STRUCT *ln3)
  645 /* ln3=ln1*ln2  */
  646 {
  647     /* BEGIN function LNmultiply -- (200303)  */
  648     if ((0 == ln1->digitCount) || (0 == ln2->digitCount))
  649         {
  650             /* multiply by 0 and get 0  */
  651             ln3->digitCount = 0;
  652             ln3->sign = 0;
  653             ln3->exponent = 0;
  654             ln3->array[0] = 0;
  655         } /* multiply by 0 and get 0  */
  656     else
  657         {
  658             /* guess we have to multiply  */
  659             int i1, i2, i3, dig, tmp, carry;
  660 
  661             ln3->sign = ln1->sign * ln2->sign;
  662             ln3->exponent = ln1->exponent + ln2->exponent;
  663             ln3->digitCount = ln1->digitCount + ln2->digitCount;
  664             dig = ln3->digitCount - 1;
  665             /* zero out ln3 so that it can be summed into  */
  666             for (i3=0; i3 <= dig; i3++)
  667                 ln3->array[i3] = 0;
  668             for (i2=ln2->digitCount - 1; i2 >= 0; i2--)
  669                 {
  670                     /* loop through the second numbers digits  */
  671                     carry = 0;
  672                     i3 = dig--;
  673                     for (i1=ln1->digitCount - 1; i1 >= 0; i1--)
  674                         {
  675                             /* process first number  */
  676                             tmp = (ln1->array[i1] * ln2->array[i2]) + carry + ln3->array[i3];
  677                             if (tmp > 9)
  678                                 {
  679                                     /* deal with overflow  */
  680                                     carry = tmp / 10;
  681                                     ln3->array[i3] = (tmp % 10);
  682                                 } /* deal with overflow  */
  683                             else
  684                                 {
  685                                     /* no overflow  */
  686                                     carry = 0;
  687                                     ln3->array[i3] = tmp;
  688                                 } /* no overflow  */
  689                             i3--;
  690                         } /* process first number  */
  691                     ln3->array[i3] = ln3->array[i3] + carry;
  692                 } /* loop through the second numbers digits  */
  693             LNnormalize(ln3);
  694         } /* guess we have to multiply  */
  695     return 0;
  696 } /* END function LNmultiply -- (200303)  */
  697 
  698 int LNdivide(LARGE_NUMBER_STRUCT *ln1, long int i2, LARGE_NUMBER_STRUCT *ln3)
  699 /* ln3=ln1/i2  */
  700 {
  701     /* BEGIN function LNdivide -- (200303)  */
  702     int i, tot = 0;
  703 
  704     ln3->exponent = ln1->exponent;
  705     ln3->sign = ln1->sign * ((0 < i2) ? 1 : -1);
  706     for (i=0; i < ln1->digitCount; i++)
  707         {
  708             /* for each digit  */
  709             tot += ln1->array[i];
  710             if (tot >= i2)
  711                 {
  712                     /* we can divide  */
  713                     ln3->array[i] = tot / i2;
  714                     tot = (tot % i2) * 10;
  715                 } /* we can divide  */
  716             else
  717                 {
  718                     /* can't divide yet, so add a zero  */
  719                     ln3->array[i] = 0;
  720                     tot *= 10;
  721                 } /* can't divide yet, so add a zero  */
  722         } /* for each digit  */
  723 
  724     ln3->digitCount = i;
  725     while ((LN_MAX_DIGITS > ln3->digitCount) && (0 < tot))
  726         {
  727             /* add zeroes on right  */
  728             if (tot >= i2)
  729                 {
  730                     /* we can divide  */
  731                     ln3->array[ln3->digitCount] = tot / i2;
  732                     tot = (tot % i2) * 10;
  733                 } /* we can divide  */
  734             else
  735                 {
  736                     /* can't divide yet, so add a zero  */
  737                     ln3->array[ln3->digitCount] = 0;
  738                     tot *= 10;
  739                 } /* can't divide yet, so add a zero  */
  740             ln3->digitCount++;
  741         } /* add zeroes on right  */
  742     LNnormalize(ln3);
  743     return 0;
  744 } /* END function LNdivide -- (200303)  */
  745 
  746 int LNdcnvrt(double d, LARGE_NUMBER_STRUCT *n)
  747 /* convert a double to Large Number  */
  748 {
  749     /* BEGIN function LNdcnvrt -- (200303)  */
  750     char str[LN_MAX_DIGITS];
  751 
  752     sprintf(str, "%ld:", d);
  753     return LNstr2arr(str, n);
  754 } /* END function LNdcnvrt -- (200303)  */
  755 
  756 int LNcopy(LARGE_NUMBER_STRUCT *ln1, LARGE_NUMBER_STRUCT *ln2)
  757 /* copy from ln1 to ln2  */
  758 {
  759     /* BEGIN function LNcopy -- (200302)  */
  760     int i;
  761 
  762     ln2->sign = ln1->sign;
  763     ln2->exponent = ln1->exponent;
  764     ln2->digitCount = ln1->digitCount;
  765     for (i=0; i < ln1->digitCount; i++)
  766         ln2->array[i] = ln1->array[i];
  767     return 0;
  768 } /* END function LNcopy -- (200302)  */
  769