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>