"Fossies" - the Fresh Open Source Software Archive

Member "mapm_4.9.5a/mapm_add.c" (21 Feb 2010, 6565 Bytes) of package /linux/misc/old/mapm-4.9.5a.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "mapm_add.c" see the Fossies "Dox" file reference documentation.

    1 
    2 /* 
    3  *  M_APM  -  mapm_add.c
    4  *
    5  *  Copyright (C) 1999 - 2007   Michael C. Ring
    6  *
    7  *  Permission to use, copy, and distribute this software and its
    8  *  documentation for any purpose with or without fee is hereby granted,
    9  *  provided that the above copyright notice appear in all copies and
   10  *  that both that copyright notice and this permission notice appear
   11  *  in supporting documentation.
   12  *
   13  *  Permission to modify the software is granted. Permission to distribute
   14  *  the modified code is granted. Modifications are to be distributed by
   15  *  using the file 'license.txt' as a template to modify the file header.
   16  *  'license.txt' is available in the official MAPM distribution.
   17  *
   18  *  This software is provided "as is" without express or implied warranty.
   19  */
   20 
   21 /*
   22  *      $Id: mapm_add.c,v 1.5 2007/12/03 01:33:39 mike Exp $
   23  *
   24  *      This file contains basic addition/subtraction functions
   25  *
   26  *      $Log: mapm_add.c,v $
   27  *      Revision 1.5  2007/12/03 01:33:39  mike
   28  *      Update license
   29  *
   30  *      Revision 1.4  2003/12/04 01:15:42  mike
   31  *      redo math with 'borrow'
   32  *
   33  *      Revision 1.3  2002/11/03 22:03:31  mike
   34  *      Updated function parameters to use the modern style
   35  *
   36  *      Revision 1.2  2001/07/16 18:59:25  mike
   37  *      add function M_free_all_add
   38  *
   39  *      Revision 1.1  1999/05/10 20:56:31  mike
   40  *      Initial revision
   41  */
   42 
   43 #include "m_apm_lc.h"
   44 
   45 static  M_APM   M_work1 = NULL;
   46 static  M_APM   M_work2 = NULL;
   47 static  int M_add_firsttime = TRUE;
   48 
   49 /****************************************************************************/
   50 void    M_free_all_add()
   51 {
   52 if (M_add_firsttime == FALSE)
   53   {
   54    m_apm_free(M_work1);
   55    m_apm_free(M_work2);
   56    M_add_firsttime = TRUE;
   57   }
   58 }
   59 /****************************************************************************/
   60 void    m_apm_add(M_APM r, M_APM a, M_APM b)
   61 {
   62 int j, carry, sign, aexp, bexp, adigits, bdigits;
   63 
   64 if (M_add_firsttime)
   65   {
   66    M_add_firsttime = FALSE;
   67    M_work1 = m_apm_init();
   68    M_work2 = m_apm_init();
   69   }
   70 
   71 if (a->m_apm_sign == 0)
   72   {
   73    m_apm_copy(r,b);
   74    return;
   75   }
   76 
   77 if (b->m_apm_sign == 0)
   78   {
   79    m_apm_copy(r,a);
   80    return;
   81   }
   82   
   83 if (a->m_apm_sign == 1 && b->m_apm_sign == -1)
   84   {
   85    b->m_apm_sign = 1;
   86    m_apm_subtract(r,a,b);
   87    b->m_apm_sign = -1;
   88    return;
   89   }
   90 
   91 if (a->m_apm_sign == -1 && b->m_apm_sign == 1)
   92   {
   93    a->m_apm_sign = 1;
   94    m_apm_subtract(r,b,a);
   95    a->m_apm_sign = -1;
   96    return;
   97   }
   98 
   99 sign = a->m_apm_sign;         /* signs are the same, result will be same */
  100 
  101 aexp = a->m_apm_exponent;
  102 bexp = b->m_apm_exponent;
  103 
  104 m_apm_copy(M_work1, a);
  105 m_apm_copy(M_work2, b);
  106 
  107 /*
  108  *  scale by at least 1 factor of 10 in case the MSB carrys
  109  */
  110 
  111 if (aexp == bexp)
  112   {
  113    M_apm_scale(M_work1, 2);   /* shift 2 digits == 1 byte for efficiency */
  114    M_apm_scale(M_work2, 2);
  115   }
  116 else
  117   {
  118    if (aexp > bexp)
  119      {
  120       M_apm_scale(M_work1, 2);
  121       M_apm_scale(M_work2, (aexp + 2 - bexp));
  122      }
  123    else            /*  aexp < bexp  */
  124      {
  125       M_apm_scale(M_work2, 2);
  126       M_apm_scale(M_work1, (bexp + 2 - aexp));
  127      }
  128   }
  129 
  130 adigits = M_work1->m_apm_datalength;
  131 bdigits = M_work2->m_apm_datalength;
  132 
  133 if (adigits >= bdigits)
  134   {
  135    m_apm_copy(r, M_work1);
  136    j = (bdigits + 1) >> 1;
  137    carry = 0;
  138 
  139    while (TRUE)
  140      {
  141       j--;
  142       r->m_apm_data[j] += carry + M_work2->m_apm_data[j];
  143 
  144       if (r->m_apm_data[j] >= 100)
  145         {
  146          r->m_apm_data[j] -= 100;
  147      carry = 1;
  148     }
  149       else
  150          carry = 0;
  151 
  152       if (j == 0) 
  153         break;
  154      }
  155   }
  156 else
  157   {
  158    m_apm_copy(r, M_work2);
  159    j = (adigits + 1) >> 1;
  160    carry = 0;
  161 
  162    while (TRUE)
  163      {
  164       j--;
  165       r->m_apm_data[j] += carry + M_work1->m_apm_data[j];
  166 
  167       if (r->m_apm_data[j] >= 100)
  168         {
  169          r->m_apm_data[j] -= 100;
  170      carry = 1;
  171     }
  172       else
  173          carry = 0;
  174 
  175       if (j == 0) 
  176         break;
  177      }
  178   }
  179 
  180 r->m_apm_sign = sign;
  181 
  182 M_apm_normalize(r);
  183 }
  184 /****************************************************************************/
  185 void    m_apm_subtract(M_APM r, M_APM a, M_APM b)
  186 {
  187 int itmp, j, flag, icompare, sign, aexp, bexp, 
  188     borrow, adigits, bdigits;
  189 
  190 if (M_add_firsttime)
  191   {
  192    M_add_firsttime = FALSE;
  193    M_work1 = m_apm_init();
  194    M_work2 = m_apm_init();
  195   }
  196 
  197 if (b->m_apm_sign == 0)
  198   {
  199    m_apm_copy(r,a);
  200    return;
  201   }
  202   
  203 if (a->m_apm_sign == 0)
  204   {
  205    m_apm_copy(r,b);
  206    r->m_apm_sign = -(r->m_apm_sign);
  207    return;
  208   }
  209 
  210 if (a->m_apm_sign == 1 && b->m_apm_sign == -1)
  211   {
  212    b->m_apm_sign = 1;
  213    m_apm_add(r,a,b);
  214    b->m_apm_sign = -1;
  215    return;
  216   }
  217 
  218 if (a->m_apm_sign == -1 && b->m_apm_sign == 1)
  219   {
  220    b->m_apm_sign = -1;
  221    m_apm_add(r,a,b);
  222    b->m_apm_sign = 1;
  223    return;
  224   }
  225 
  226 /* now, the signs are the same  */
  227 /* make a positive working copy */
  228 
  229 m_apm_absolute_value(M_work1, a);
  230 m_apm_absolute_value(M_work2, b);
  231 
  232 /* are they the same??  if so, the result is zero */
  233 
  234 if ((icompare = m_apm_compare(M_work1, M_work2)) == 0)
  235   {
  236    M_set_to_zero(r);
  237    return;
  238   }
  239 
  240 if (icompare == 1)             /*  |a| > |b|  (do A-B)  */
  241   {
  242    flag = TRUE;
  243    sign = a->m_apm_sign;     
  244   }
  245 else                           /*  |b| > |a|  (do B-A)  */
  246   {
  247    flag = FALSE;
  248    sign = -(a->m_apm_sign);     
  249   }
  250 
  251 aexp = M_work1->m_apm_exponent;
  252 bexp = M_work2->m_apm_exponent;
  253 
  254 if (aexp > bexp)
  255   M_apm_scale(M_work2, (aexp - bexp));
  256 
  257 if (aexp < bexp)
  258   M_apm_scale(M_work1, (bexp - aexp));
  259 
  260 adigits = M_work1->m_apm_datalength;
  261 bdigits = M_work2->m_apm_datalength;
  262 
  263 if (adigits > bdigits)
  264   M_apm_pad(M_work2, adigits);
  265 
  266 if (adigits < bdigits)
  267   M_apm_pad(M_work1, bdigits);
  268 
  269 if (flag)       /* perform A-B,  M_work1 - M_work2 */
  270   {
  271    m_apm_copy(r, M_work1);
  272    j = (r->m_apm_datalength + 1) >> 1;
  273    borrow = 0;
  274 
  275    while (TRUE)
  276      {
  277       j--;
  278       itmp = (int)r->m_apm_data[j] - ((int)M_work2->m_apm_data[j] + borrow);
  279 
  280       if (itmp >= 0)
  281         {
  282          r->m_apm_data[j] = (UCHAR)itmp;
  283      borrow = 0;
  284         }
  285       else
  286         {
  287          r->m_apm_data[j] = (UCHAR)(100 + itmp);
  288      borrow = 1;
  289     }
  290 
  291       if (j == 0) 
  292         break;
  293      }
  294   }
  295 else        /* perform B-A,  M_work2 - M_work1 */
  296   {
  297    m_apm_copy(r, M_work2);
  298    j = (r->m_apm_datalength + 1) >> 1;
  299    borrow = 0;
  300 
  301    while (TRUE)
  302      {
  303       j--;
  304       itmp = (int)r->m_apm_data[j] - ((int)M_work1->m_apm_data[j] + borrow);
  305 
  306       if (itmp >= 0)
  307         {
  308          r->m_apm_data[j] = (UCHAR)itmp;
  309      borrow = 0;
  310         }
  311       else
  312         {
  313          r->m_apm_data[j] = (UCHAR)(100 + itmp);
  314      borrow = 1;
  315     }
  316 
  317       if (j == 0) 
  318         break;
  319      }
  320   }
  321    
  322 r->m_apm_sign = sign;
  323 
  324 M_apm_normalize(r);
  325 }
  326 /****************************************************************************/