Annotation of embedaddon/php/ext/bcmath/libbcmath/src/doaddsub.c, revision 1.1

1.1     ! misho       1: /* doaddsub.c: bcmath library file. */
        !             2: /*
        !             3:     Copyright (C) 1991, 1992, 1993, 1994, 1997 Free Software Foundation, Inc.
        !             4:     Copyright (C) 2000 Philip A. Nelson
        !             5: 
        !             6:     This library is free software; you can redistribute it and/or
        !             7:     modify it under the terms of the GNU Lesser General Public
        !             8:     License as published by the Free Software Foundation; either
        !             9:     version 2 of the License, or (at your option) any later version.
        !            10: 
        !            11:     This library is distributed in the hope that it will be useful,
        !            12:     but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            13:     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        !            14:     Lesser General Public License for more details.  (COPYING.LIB)
        !            15: 
        !            16:     You should have received a copy of the GNU Lesser General Public
        !            17:     License along with this library; if not, write to:
        !            18: 
        !            19:       The Free Software Foundation, Inc.
        !            20:       59 Temple Place, Suite 330
        !            21:       Boston, MA 02111-1307 USA.
        !            22: 
        !            23:     You may contact the author by:
        !            24:        e-mail:  philnelson@acm.org
        !            25:       us-mail:  Philip A. Nelson
        !            26:                 Computer Science Department, 9062
        !            27:                 Western Washington University
        !            28:                 Bellingham, WA 98226-9062
        !            29:        
        !            30: *************************************************************************/
        !            31: 
        !            32: #include <config.h>
        !            33: #include <stdio.h>
        !            34: #include <assert.h>
        !            35: #include <stdlib.h>
        !            36: #include <ctype.h>
        !            37: #include <stdarg.h>
        !            38: #include "bcmath.h"
        !            39: #include "private.h"
        !            40: 
        !            41: 
        !            42: /* Perform addition: N1 is added to N2 and the value is
        !            43:    returned.  The signs of N1 and N2 are ignored.
        !            44:    SCALE_MIN is to set the minimum scale of the result. */
        !            45: 
        !            46:  bc_num
        !            47: _bc_do_add (n1, n2, scale_min)
        !            48:      bc_num n1, n2;
        !            49:      int scale_min;
        !            50: {
        !            51:   bc_num sum;
        !            52:   int sum_scale, sum_digits;
        !            53:   char *n1ptr, *n2ptr, *sumptr;
        !            54:   int carry, n1bytes, n2bytes;
        !            55:   int count;
        !            56: 
        !            57:   /* Prepare sum. */
        !            58:   sum_scale = MAX (n1->n_scale, n2->n_scale);
        !            59:   sum_digits = MAX (n1->n_len, n2->n_len) + 1;
        !            60:   sum = bc_new_num (sum_digits, MAX(sum_scale, scale_min));
        !            61: 
        !            62:   /* Zero extra digits made by scale_min. */
        !            63:   if (scale_min > sum_scale)
        !            64:     {
        !            65:       sumptr = (char *) (sum->n_value + sum_scale + sum_digits);
        !            66:       for (count = scale_min - sum_scale; count > 0; count--)
        !            67:        *sumptr++ = 0;
        !            68:     }
        !            69: 
        !            70:   /* Start with the fraction part.  Initialize the pointers. */
        !            71:   n1bytes = n1->n_scale;
        !            72:   n2bytes = n2->n_scale;
        !            73:   n1ptr = (char *) (n1->n_value + n1->n_len + n1bytes - 1);
        !            74:   n2ptr = (char *) (n2->n_value + n2->n_len + n2bytes - 1);
        !            75:   sumptr = (char *) (sum->n_value + sum_scale + sum_digits - 1);
        !            76: 
        !            77:   /* Add the fraction part.  First copy the longer fraction.*/
        !            78:   if (n1bytes != n2bytes)
        !            79:     {
        !            80:       if (n1bytes > n2bytes)
        !            81:        while (n1bytes>n2bytes)
        !            82:          { *sumptr-- = *n1ptr--; n1bytes--;}
        !            83:       else
        !            84:        while (n2bytes>n1bytes)
        !            85:          { *sumptr-- = *n2ptr--; n2bytes--;}
        !            86:     }
        !            87: 
        !            88:   /* Now add the remaining fraction part and equal size integer parts. */
        !            89:   n1bytes += n1->n_len;
        !            90:   n2bytes += n2->n_len;
        !            91:   carry = 0;
        !            92:   while ((n1bytes > 0) && (n2bytes > 0))
        !            93:     {
        !            94:       *sumptr = *n1ptr-- + *n2ptr-- + carry;
        !            95:       if (*sumptr > (BASE-1))
        !            96:        {
        !            97:           carry = 1;
        !            98:           *sumptr -= BASE;
        !            99:        }
        !           100:       else
        !           101:        carry = 0;
        !           102:       sumptr--;
        !           103:       n1bytes--;
        !           104:       n2bytes--;
        !           105:     }
        !           106: 
        !           107:   /* Now add carry the longer integer part. */
        !           108:   if (n1bytes == 0)
        !           109:     { n1bytes = n2bytes; n1ptr = n2ptr; }
        !           110:   while (n1bytes-- > 0)
        !           111:     {
        !           112:       *sumptr = *n1ptr-- + carry;
        !           113:       if (*sumptr > (BASE-1))
        !           114:        {
        !           115:           carry = 1;
        !           116:           *sumptr -= BASE;
        !           117:         }
        !           118:       else
        !           119:        carry = 0;
        !           120:       sumptr--;
        !           121:     }
        !           122: 
        !           123:   /* Set final carry. */
        !           124:   if (carry == 1)
        !           125:     *sumptr += 1;
        !           126: 
        !           127:   /* Adjust sum and return. */
        !           128:   _bc_rm_leading_zeros (sum);
        !           129:   return sum;
        !           130: }
        !           131: 
        !           132: 
        !           133: /* Perform subtraction: N2 is subtracted from N1 and the value is
        !           134:    returned.  The signs of N1 and N2 are ignored.  Also, N1 is
        !           135:    assumed to be larger than N2.  SCALE_MIN is the minimum scale
        !           136:    of the result. */
        !           137: 
        !           138:  bc_num
        !           139: _bc_do_sub (n1, n2, scale_min)
        !           140:      bc_num n1, n2;
        !           141:      int scale_min;
        !           142: {
        !           143:   bc_num diff;
        !           144:   int diff_scale, diff_len;
        !           145:   int min_scale, min_len;
        !           146:   char *n1ptr, *n2ptr, *diffptr;
        !           147:   int borrow, count, val;
        !           148: 
        !           149:   /* Allocate temporary storage. */
        !           150:   diff_len = MAX (n1->n_len, n2->n_len);
        !           151:   diff_scale = MAX (n1->n_scale, n2->n_scale);
        !           152:   min_len = MIN  (n1->n_len, n2->n_len);
        !           153:   min_scale = MIN (n1->n_scale, n2->n_scale);
        !           154:   diff = bc_new_num (diff_len, MAX(diff_scale, scale_min));
        !           155: 
        !           156:   /* Zero extra digits made by scale_min. */
        !           157:   if (scale_min > diff_scale)
        !           158:     {
        !           159:       diffptr = (char *) (diff->n_value + diff_len + diff_scale);
        !           160:       for (count = scale_min - diff_scale; count > 0; count--)
        !           161:        *diffptr++ = 0;
        !           162:     }
        !           163: 
        !           164:   /* Initialize the subtract. */
        !           165:   n1ptr = (char *) (n1->n_value + n1->n_len + n1->n_scale -1);
        !           166:   n2ptr = (char *) (n2->n_value + n2->n_len + n2->n_scale -1);
        !           167:   diffptr = (char *) (diff->n_value + diff_len + diff_scale -1);
        !           168: 
        !           169:   /* Subtract the numbers. */
        !           170:   borrow = 0;
        !           171: 
        !           172:   /* Take care of the longer scaled number. */
        !           173:   if (n1->n_scale != min_scale)
        !           174:     {
        !           175:       /* n1 has the longer scale */
        !           176:       for (count = n1->n_scale - min_scale; count > 0; count--)
        !           177:        *diffptr-- = *n1ptr--;
        !           178:     }
        !           179:   else
        !           180:     {
        !           181:       /* n2 has the longer scale */
        !           182:       for (count = n2->n_scale - min_scale; count > 0; count--)
        !           183:        {
        !           184:          val = - *n2ptr-- - borrow;
        !           185:          if (val < 0)
        !           186:            {
        !           187:              val += BASE;
        !           188:              borrow = 1;
        !           189:            }
        !           190:          else
        !           191:            borrow = 0;
        !           192:          *diffptr-- = val;
        !           193:        }
        !           194:     }
        !           195: 
        !           196:   /* Now do the equal length scale and integer parts. */
        !           197: 
        !           198:   for (count = 0; count < min_len + min_scale; count++)
        !           199:     {
        !           200:       val = *n1ptr-- - *n2ptr-- - borrow;
        !           201:       if (val < 0)
        !           202:        {
        !           203:          val += BASE;
        !           204:          borrow = 1;
        !           205:        }
        !           206:       else
        !           207:        borrow = 0;
        !           208:       *diffptr-- = val;
        !           209:     }
        !           210: 
        !           211:   /* If n1 has more digits then n2, we now do that subtract. */
        !           212:   if (diff_len != min_len)
        !           213:     {
        !           214:       for (count = diff_len - min_len; count > 0; count--)
        !           215:        {
        !           216:          val = *n1ptr-- - borrow;
        !           217:          if (val < 0)
        !           218:            {
        !           219:              val += BASE;
        !           220:              borrow = 1;
        !           221:            }
        !           222:          else
        !           223:            borrow = 0;
        !           224:          *diffptr-- = val;
        !           225:        }
        !           226:     }
        !           227: 
        !           228:   /* Clean up and return. */
        !           229:   _bc_rm_leading_zeros (diff);
        !           230:   return diff;
        !           231: }
        !           232: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>