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