xref: /illumos-gate/usr/src/lib/libmp/common/madd.c (revision bb9b6b3f59b8820022416cea99b49c50fef6e391)
1 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
2 /*	  All Rights Reserved  	*/
3 
4 
5 /*
6  * Copyright (c) 1980 Regents of the University of California.
7  * All rights reserved.  The Berkeley software License Agreement
8  * specifies the terms and conditions for redistribution.
9  */
10 /* 	Portions Copyright(c) 1988, Sun Microsystems Inc.	*/
11 /*	All Rights Reserved					*/
12 
13 /*
14  * Copyright (c) 1997, by Sun Microsystems, Inc.
15  * All rights reserved.
16  */
17 
18 #ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 1.1	*/
19 
20 /* LINTLIBRARY */
21 
22 #include <mp.h>
23 #include "libmp.h"
24 #include <sys/types.h>
25 #include <stdlib.h>
26 
27 static void
28 m_add(MINT *a, MINT *b, MINT *c)
29 {
30 	int carry, i;
31 	int x;
32 	short *cval;
33 
34 	cval = _mp_xalloc(a->len + 1, "m_add");
35 	carry = 0;
36 	for (i = 0; i < b->len; i++) {
37 		x = carry + a->val[i] + b->val[i];
38 		if (x & 0100000) {
39 			carry = 1;
40 			cval[i] = (short)(x & 077777);
41 		} else {
42 			carry = 0;
43 			cval[i] = (short)x;
44 		}
45 	}
46 	for (; i < a->len; i++) {
47 		x = carry + a->val[i];
48 		if (x & 0100000) {
49 			cval[i] = (short)(x & 077777);
50 		} else {
51 			carry = 0;
52 			cval[i] = (short)x;
53 		}
54 	}
55 	if (carry == 1) {
56 		cval[i] = 1;
57 		c->len = i + 1;
58 	} else {
59 		c->len = a->len;
60 	}
61 	c->val = cval;
62 	if (c->len == 0) {
63 		free(cval);
64 	}
65 }
66 
67 void
68 mp_madd(MINT *a, MINT *b, MINT *c)
69 {
70 	MINT x, y;
71 	int sign;
72 
73 	x.len = y.len = 0;
74 	_mp_move(a, &x);
75 	_mp_move(b, &y);
76 	_mp_xfree(c);
77 	sign = 1;
78 	if (x.len >= 0) {
79 		if (y.len >= 0) {
80 			if (x.len >= y.len) {
81 				m_add(&x, &y, c);
82 			} else {
83 				m_add(&y, &x, c);
84 			}
85 		} else {
86 			y.len = -y.len;
87 			mp_msub(&x, &y, c);
88 		}
89 	} else {
90 		if (y.len <= 0) {
91 			x.len = -x.len;
92 			y.len = -y.len;
93 			sign = -1;
94 			mp_madd(&x, &y, c);
95 		} else {
96 			x.len = -x.len;
97 			mp_msub(&y, &x, c);
98 		}
99 	}
100 	c->len = sign * c->len;
101 	_mp_xfree(&x);
102 	_mp_xfree(&y);
103 }
104 
105 static void
106 m_sub(MINT *a, MINT *b, MINT *c)
107 {
108 	int x, i;
109 	int borrow;
110 	short one;
111 	MINT mone;
112 
113 	one = 1;
114 	mone.len = 1;
115 	mone.val = &one;
116 	c->val = _mp_xalloc(a->len, "m_sub");
117 	borrow = 0;
118 	for (i = 0; i < b->len; i++) {
119 		x = borrow + a->val[i] - b->val[i];
120 		if (x & 0100000) {
121 			borrow = -1;
122 			c->val[i] = (short)(x & 077777);
123 		} else {
124 			borrow = 0;
125 			c->val[i] = (short)x;
126 		}
127 	}
128 	for (; i < a->len; i++) {
129 		x = borrow + a->val[i];
130 		if (x & 0100000) {
131 			c->val[i] = (short)(x & 077777);
132 		} else {
133 			borrow = 0;
134 			c->val[i] = (short)x;
135 		}
136 	}
137 	if (borrow < 0) {
138 		for (i = 0; i < a->len; i++) {
139 			c->val[i] ^= 077777;
140 		}
141 		c->len = a->len;
142 		mp_madd(c, &mone, c);
143 	}
144 	for (i = a->len-1; i >= 0; --i) {
145 		if (c->val[i] > 0) {
146 			if (borrow == 0) {
147 				c->len = i + 1;
148 			} else {
149 				c->len = -i - 1;
150 			}
151 			return;
152 		}
153 	}
154 	free(c->val);
155 }
156 
157 void
158 mp_msub(MINT *a, MINT *b, MINT *c)
159 {
160 	MINT x, y;
161 	int sign;
162 
163 	x.len = y.len = 0;
164 	_mp_move(a, &x);
165 	_mp_move(b, &y);
166 	_mp_xfree(c);
167 	sign = 1;
168 	if (x.len >= 0) {
169 		if (y.len >= 0) {
170 			if (x.len >= y.len) {
171 				m_sub(&x, &y, c);
172 			} else {
173 				sign = -1;
174 				mp_msub(&y, &x, c);
175 			}
176 		} else {
177 			y.len = -y.len;
178 			mp_madd(&x, &y, c);
179 		}
180 	} else {
181 		if (y.len <= 0) {
182 			x.len = -x.len;
183 			y.len = -y.len;
184 			mp_msub(&y, &x, c);
185 		} else {
186 			x.len = -x.len;
187 			mp_madd(&x, &y, c);
188 			sign = -1;
189 		}
190 	}
191 	c->len = sign * c->len;
192 	_mp_xfree(&x);
193 	_mp_xfree(&y);
194 }
195