xref: /aosp_15_r20/external/libgsm/src/add.c (revision 8ec969cea971fe25ff2d3933a5a9f8504f8e86c9)
1*8ec969ceSTreehugger Robot /*
2*8ec969ceSTreehugger Robot  * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
3*8ec969ceSTreehugger Robot  * Universitaet Berlin.  See the accompanying file "COPYRIGHT" for
4*8ec969ceSTreehugger Robot  * details.  THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
5*8ec969ceSTreehugger Robot  */
6*8ec969ceSTreehugger Robot 
7*8ec969ceSTreehugger Robot /* $Header: /tmp_amd/presto/export/kbs/jutta/src/gsm/RCS/add.c,v 1.6 1996/07/02 09:57:33 jutta Exp $ */
8*8ec969ceSTreehugger Robot 
9*8ec969ceSTreehugger Robot /*
10*8ec969ceSTreehugger Robot  *  See private.h for the more commonly used macro versions.
11*8ec969ceSTreehugger Robot  */
12*8ec969ceSTreehugger Robot 
13*8ec969ceSTreehugger Robot #include	<stdio.h>
14*8ec969ceSTreehugger Robot #include	<assert.h>
15*8ec969ceSTreehugger Robot 
16*8ec969ceSTreehugger Robot #include	"private.h"
17*8ec969ceSTreehugger Robot #include	"gsm.h"
18*8ec969ceSTreehugger Robot #include	"proto.h"
19*8ec969ceSTreehugger Robot 
20*8ec969ceSTreehugger Robot #define	saturate(x) 	\
21*8ec969ceSTreehugger Robot 	((x) < MIN_WORD ? MIN_WORD : (x) > MAX_WORD ? MAX_WORD: (x))
22*8ec969ceSTreehugger Robot 
23*8ec969ceSTreehugger Robot word gsm_add P2((a,b), word a, word b)
24*8ec969ceSTreehugger Robot {
25*8ec969ceSTreehugger Robot 	longword sum = (longword)a + (longword)b;
26*8ec969ceSTreehugger Robot 	return saturate(sum);
27*8ec969ceSTreehugger Robot }
28*8ec969ceSTreehugger Robot 
29*8ec969ceSTreehugger Robot word gsm_sub P2((a,b), word a, word b)
30*8ec969ceSTreehugger Robot {
31*8ec969ceSTreehugger Robot 	longword diff = (longword)a - (longword)b;
32*8ec969ceSTreehugger Robot 	return saturate(diff);
33*8ec969ceSTreehugger Robot }
34*8ec969ceSTreehugger Robot 
35*8ec969ceSTreehugger Robot word gsm_mult P2((a,b), word a, word b)
36*8ec969ceSTreehugger Robot {
37*8ec969ceSTreehugger Robot 	if (a == MIN_WORD && b == MIN_WORD) return MAX_WORD;
38*8ec969ceSTreehugger Robot 	else return SASR( (longword)a * (longword)b, 15 );
39*8ec969ceSTreehugger Robot }
40*8ec969ceSTreehugger Robot 
41*8ec969ceSTreehugger Robot word gsm_mult_r P2((a,b), word a, word b)
42*8ec969ceSTreehugger Robot {
43*8ec969ceSTreehugger Robot 	if (b == MIN_WORD && a == MIN_WORD) return MAX_WORD;
44*8ec969ceSTreehugger Robot 	else {
45*8ec969ceSTreehugger Robot 		longword prod = (longword)a * (longword)b + 16384;
46*8ec969ceSTreehugger Robot 		prod >>= 15;
47*8ec969ceSTreehugger Robot 		return prod & 0xFFFF;
48*8ec969ceSTreehugger Robot 	}
49*8ec969ceSTreehugger Robot }
50*8ec969ceSTreehugger Robot 
51*8ec969ceSTreehugger Robot word gsm_abs P1((a), word a)
52*8ec969ceSTreehugger Robot {
53*8ec969ceSTreehugger Robot 	return a < 0 ? (a == MIN_WORD ? MAX_WORD : -a) : a;
54*8ec969ceSTreehugger Robot }
55*8ec969ceSTreehugger Robot 
56*8ec969ceSTreehugger Robot longword gsm_L_mult P2((a,b),word a, word b)
57*8ec969ceSTreehugger Robot {
58*8ec969ceSTreehugger Robot 	assert( a != MIN_WORD || b != MIN_WORD );
59*8ec969ceSTreehugger Robot 	return ((longword)a * (longword)b) << 1;
60*8ec969ceSTreehugger Robot }
61*8ec969ceSTreehugger Robot 
62*8ec969ceSTreehugger Robot longword gsm_L_add P2((a,b), longword a, longword b)
63*8ec969ceSTreehugger Robot {
64*8ec969ceSTreehugger Robot 	if (a < 0) {
65*8ec969ceSTreehugger Robot 		if (b >= 0) return a + b;
66*8ec969ceSTreehugger Robot 		else {
67*8ec969ceSTreehugger Robot 			ulongword A = (ulongword)-(a + 1) + (ulongword)-(b + 1);
68*8ec969ceSTreehugger Robot 			return A >= MAX_LONGWORD ? MIN_LONGWORD :-(longword)A-2;
69*8ec969ceSTreehugger Robot 		}
70*8ec969ceSTreehugger Robot 	}
71*8ec969ceSTreehugger Robot 	else if (b <= 0) return a + b;
72*8ec969ceSTreehugger Robot 	else {
73*8ec969ceSTreehugger Robot 		ulongword A = (ulongword)a + (ulongword)b;
74*8ec969ceSTreehugger Robot 		return A > MAX_LONGWORD ? MAX_LONGWORD : A;
75*8ec969ceSTreehugger Robot 	}
76*8ec969ceSTreehugger Robot }
77*8ec969ceSTreehugger Robot 
78*8ec969ceSTreehugger Robot longword gsm_L_sub P2((a,b), longword a, longword b)
79*8ec969ceSTreehugger Robot {
80*8ec969ceSTreehugger Robot 	if (a >= 0) {
81*8ec969ceSTreehugger Robot 		if (b >= 0) return a - b;
82*8ec969ceSTreehugger Robot 		else {
83*8ec969ceSTreehugger Robot 			/* a>=0, b<0 */
84*8ec969ceSTreehugger Robot 
85*8ec969ceSTreehugger Robot 			ulongword A = (ulongword)a + -(b + 1);
86*8ec969ceSTreehugger Robot 			return A >= MAX_LONGWORD ? MAX_LONGWORD : (A + 1);
87*8ec969ceSTreehugger Robot 		}
88*8ec969ceSTreehugger Robot 	}
89*8ec969ceSTreehugger Robot 	else if (b <= 0) return a - b;
90*8ec969ceSTreehugger Robot 	else {
91*8ec969ceSTreehugger Robot 		/* a<0, b>0 */
92*8ec969ceSTreehugger Robot 
93*8ec969ceSTreehugger Robot 		ulongword A = (ulongword)-(a + 1) + b;
94*8ec969ceSTreehugger Robot 		return A >= MAX_LONGWORD ? MIN_LONGWORD : -(longword)A - 1;
95*8ec969ceSTreehugger Robot 	}
96*8ec969ceSTreehugger Robot }
97*8ec969ceSTreehugger Robot 
98*8ec969ceSTreehugger Robot static unsigned char const bitoff[ 256 ] = {
99*8ec969ceSTreehugger Robot 	 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
100*8ec969ceSTreehugger Robot 	 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
101*8ec969ceSTreehugger Robot 	 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
102*8ec969ceSTreehugger Robot 	 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
103*8ec969ceSTreehugger Robot 	 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
104*8ec969ceSTreehugger Robot 	 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
105*8ec969ceSTreehugger Robot 	 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
106*8ec969ceSTreehugger Robot 	 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
107*8ec969ceSTreehugger Robot 	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
108*8ec969ceSTreehugger Robot 	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
109*8ec969ceSTreehugger Robot 	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
110*8ec969ceSTreehugger Robot 	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
111*8ec969ceSTreehugger Robot 	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
112*8ec969ceSTreehugger Robot 	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
113*8ec969ceSTreehugger Robot 	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
114*8ec969ceSTreehugger Robot 	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
115*8ec969ceSTreehugger Robot };
116*8ec969ceSTreehugger Robot 
117*8ec969ceSTreehugger Robot word gsm_norm P1((a), longword a )
118*8ec969ceSTreehugger Robot /*
119*8ec969ceSTreehugger Robot  * the number of left shifts needed to normalize the 32 bit
120*8ec969ceSTreehugger Robot  * variable L_var1 for positive values on the interval
121*8ec969ceSTreehugger Robot  *
122*8ec969ceSTreehugger Robot  * with minimum of
123*8ec969ceSTreehugger Robot  * minimum of 1073741824  (01000000000000000000000000000000) and
124*8ec969ceSTreehugger Robot  * maximum of 2147483647  (01111111111111111111111111111111)
125*8ec969ceSTreehugger Robot  *
126*8ec969ceSTreehugger Robot  *
127*8ec969ceSTreehugger Robot  * and for negative values on the interval with
128*8ec969ceSTreehugger Robot  * minimum of -2147483648 (-10000000000000000000000000000000) and
129*8ec969ceSTreehugger Robot  * maximum of -1073741824 ( -1000000000000000000000000000000).
130*8ec969ceSTreehugger Robot  *
131*8ec969ceSTreehugger Robot  * in order to normalize the result, the following
132*8ec969ceSTreehugger Robot  * operation must be done: L_norm_var1 = L_var1 << norm( L_var1 );
133*8ec969ceSTreehugger Robot  *
134*8ec969ceSTreehugger Robot  * (That's 'ffs', only from the left, not the right..)
135*8ec969ceSTreehugger Robot  */
136*8ec969ceSTreehugger Robot {
137*8ec969ceSTreehugger Robot 	assert(a != 0);
138*8ec969ceSTreehugger Robot 
139*8ec969ceSTreehugger Robot 	if (a < 0) {
140*8ec969ceSTreehugger Robot 		if (a <= -1073741824) return 0;
141*8ec969ceSTreehugger Robot 		a = ~a;
142*8ec969ceSTreehugger Robot 	}
143*8ec969ceSTreehugger Robot 
144*8ec969ceSTreehugger Robot 	return    a & 0xffff0000
145*8ec969ceSTreehugger Robot 		? ( a & 0xff000000
146*8ec969ceSTreehugger Robot 		  ?  -1 + bitoff[ 0xFF & (a >> 24) ]
147*8ec969ceSTreehugger Robot 		  :   7 + bitoff[ 0xFF & (a >> 16) ] )
148*8ec969ceSTreehugger Robot 		: ( a & 0xff00
149*8ec969ceSTreehugger Robot 		  ?  15 + bitoff[ 0xFF & (a >> 8) ]
150*8ec969ceSTreehugger Robot 		  :  23 + bitoff[ 0xFF & a ] );
151*8ec969ceSTreehugger Robot }
152*8ec969ceSTreehugger Robot 
153*8ec969ceSTreehugger Robot longword gsm_L_asl P2((a,n), longword a, int n)
154*8ec969ceSTreehugger Robot {
155*8ec969ceSTreehugger Robot 	if (n >= 32) return 0;
156*8ec969ceSTreehugger Robot 	if (n <= -32) return -(a < 0);
157*8ec969ceSTreehugger Robot 	if (n < 0) return gsm_L_asr(a, -n);
158*8ec969ceSTreehugger Robot 	return a << n;
159*8ec969ceSTreehugger Robot }
160*8ec969ceSTreehugger Robot 
161*8ec969ceSTreehugger Robot word gsm_asl P2((a,n), word a, int n)
162*8ec969ceSTreehugger Robot {
163*8ec969ceSTreehugger Robot 	if (n >= 16) return 0;
164*8ec969ceSTreehugger Robot 	if (n <= -16) return -(a < 0);
165*8ec969ceSTreehugger Robot 	if (n < 0) return gsm_asr(a, -n);
166*8ec969ceSTreehugger Robot 	return a << n;
167*8ec969ceSTreehugger Robot }
168*8ec969ceSTreehugger Robot 
169*8ec969ceSTreehugger Robot longword gsm_L_asr P2((a,n), longword a, int n)
170*8ec969ceSTreehugger Robot {
171*8ec969ceSTreehugger Robot 	if (n >= 32) return -(a < 0);
172*8ec969ceSTreehugger Robot 	if (n <= -32) return 0;
173*8ec969ceSTreehugger Robot 	if (n < 0) return a << -n;
174*8ec969ceSTreehugger Robot 
175*8ec969ceSTreehugger Robot #	ifdef	SASR
176*8ec969ceSTreehugger Robot 		return a >> n;
177*8ec969ceSTreehugger Robot #	else
178*8ec969ceSTreehugger Robot 		if (a >= 0) return a >> n;
179*8ec969ceSTreehugger Robot 		else return -(longword)( -(ulongword)a >> n );
180*8ec969ceSTreehugger Robot #	endif
181*8ec969ceSTreehugger Robot }
182*8ec969ceSTreehugger Robot 
183*8ec969ceSTreehugger Robot word gsm_asr P2((a,n), word a, int n)
184*8ec969ceSTreehugger Robot {
185*8ec969ceSTreehugger Robot 	if (n >= 16) return -(a < 0);
186*8ec969ceSTreehugger Robot 	if (n <= -16) return 0;
187*8ec969ceSTreehugger Robot 	if (n < 0) return a << -n;
188*8ec969ceSTreehugger Robot 
189*8ec969ceSTreehugger Robot #	ifdef	SASR
190*8ec969ceSTreehugger Robot 		return a >> n;
191*8ec969ceSTreehugger Robot #	else
192*8ec969ceSTreehugger Robot 		if (a >= 0) return a >> n;
193*8ec969ceSTreehugger Robot 		else return -(word)( -(uword)a >> n );
194*8ec969ceSTreehugger Robot #	endif
195*8ec969ceSTreehugger Robot }
196*8ec969ceSTreehugger Robot 
197*8ec969ceSTreehugger Robot /*
198*8ec969ceSTreehugger Robot  *  (From p. 46, end of section 4.2.5)
199*8ec969ceSTreehugger Robot  *
200*8ec969ceSTreehugger Robot  *  NOTE: The following lines gives [sic] one correct implementation
201*8ec969ceSTreehugger Robot  *  	  of the div(num, denum) arithmetic operation.  Compute div
202*8ec969ceSTreehugger Robot  *        which is the integer division of num by denum: with denum
203*8ec969ceSTreehugger Robot  *	  >= num > 0
204*8ec969ceSTreehugger Robot  */
205*8ec969ceSTreehugger Robot 
206*8ec969ceSTreehugger Robot word gsm_div P2((num,denum), word num, word denum)
207*8ec969ceSTreehugger Robot {
208*8ec969ceSTreehugger Robot 	longword	L_num   = num;
209*8ec969ceSTreehugger Robot 	longword	L_denum = denum;
210*8ec969ceSTreehugger Robot 	word		div 	= 0;
211*8ec969ceSTreehugger Robot 	int		k 	= 15;
212*8ec969ceSTreehugger Robot 
213*8ec969ceSTreehugger Robot 	/* The parameter num sometimes becomes zero.
214*8ec969ceSTreehugger Robot 	 * Although this is explicitly guarded against in 4.2.5,
215*8ec969ceSTreehugger Robot 	 * we assume that the result should then be zero as well.
216*8ec969ceSTreehugger Robot 	 */
217*8ec969ceSTreehugger Robot 
218*8ec969ceSTreehugger Robot 	/* assert(num != 0); */
219*8ec969ceSTreehugger Robot 
220*8ec969ceSTreehugger Robot 	assert(num >= 0 && denum >= num);
221*8ec969ceSTreehugger Robot 	if (num == 0)
222*8ec969ceSTreehugger Robot 	    return 0;
223*8ec969ceSTreehugger Robot 
224*8ec969ceSTreehugger Robot 	while (k--) {
225*8ec969ceSTreehugger Robot 		div   <<= 1;
226*8ec969ceSTreehugger Robot 		L_num <<= 1;
227*8ec969ceSTreehugger Robot 
228*8ec969ceSTreehugger Robot 		if (L_num >= L_denum) {
229*8ec969ceSTreehugger Robot 			L_num -= L_denum;
230*8ec969ceSTreehugger Robot 			div++;
231*8ec969ceSTreehugger Robot 		}
232*8ec969ceSTreehugger Robot 	}
233*8ec969ceSTreehugger Robot 
234*8ec969ceSTreehugger Robot 	return div;
235*8ec969ceSTreehugger Robot }
236