Annotation of embedaddon/php/ext/bcmath/libbcmath/src/doaddsub.c, revision 1.1.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>