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>