Return to doaddsub.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / bcmath / libbcmath / src |
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: