1 /* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18 /****************************************************************************************
19 Portions of this file are derived from the following 3GPP standard:
20
21 3GPP TS 26.073
22 ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
23 Available from http://www.3gpp.org
24
25 (C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
26 Permission to distribute, modify and use this file under the standard license
27 terms listed above has been obtained from the copyright holder.
28 ****************************************************************************************/
29 /*
30 Pathname: ./gsm-amr/c/src/div_s.c
31
32 ------------------------------------------------------------------------------
33 REVISION HISTORY
34
35 Description: Created separate file for the div_s function. Sync'ed up
36 with the current template and fixed tabs.
37
38 Description: Making changes based on review meeting.
39
40 Description: Made changes based on P3 review meeting.
41
42 Description: Changing abort() to exit(0).
43
44 Description: Made the following changes
45 1. Unrolled the division loop to make three comparison per
46 pass, using only five iterations of the loop and saving
47 shifts cycles
48
49 Who: Date:
50 Description:
51
52 ------------------------------------------------------------------------------
53 INPUT AND OUTPUT DEFINITIONS
54
55 Inputs:
56 var1 = 16 bit signed integer (Word16) whose value falls in
57 the range : 0x0000 <= var1 <= 0x7fff.
58 var2 = 16 bit signed integer (Word16) whose value falls in
59 the range : 0x0000 <= var1 <= 0x7fff.
60
61 Local Stores/Buffers/Pointers Needed:
62 None
63
64 Global Stores/Buffers/Pointers Needed:
65 None
66
67 Outputs:
68 var_out = quotient of var1 divided by var2 (Word16)
69
70 Pointers and Buffers Modified:
71 None
72
73 Local Stores Modified:
74 None
75
76 Global Stores Modified:
77 None
78
79 ------------------------------------------------------------------------------
80 FUNCTION DESCRIPTION
81
82 This function produces a result which is the fractional integer division of
83 var1 by var2; var1 and var2 must be positive and var2 must be greater or equal
84 to var1; the result is positive (leading bit equal to 0) and truncated to 16
85 bits. If var1 = var2 then div(var1,var2) = 32767.
86
87 ------------------------------------------------------------------------------
88 REQUIREMENTS
89
90 None
91
92 ------------------------------------------------------------------------------
93 REFERENCES
94
95 [1] basicop2.c, ETS Version 2.0.0, February 8, 1999
96
97 ------------------------------------------------------------------------------
98 PSEUDO-CODE
99
100 Word16 div_s (Word16 var1, Word16 var2)
101 {
102 Word16 var_out = 0;
103 Word16 iteration;
104 Word32 L_num;
105 Word32 L_denom;
106 Word16 abort_flag = 0;
107
108 if ((var1 > var2) || (var1 < 0))
109 {
110 printf ("Division Error var1=%d var2=%d\n", var1, var2);
111 abort_flag = 1;
112 exit(0);
113 }
114 if ((var1 != 0) && (abort_flag == 0))
115 {
116 if (var1 == var2)
117 {
118 var_out = MAX_16;
119 }
120 else
121 {
122 L_num = (Word32) var1;
123 L_denom = (Word32) var2;
124
125 for (iteration = 15; iteration > 0; iteration--)
126 {
127 var_out <<= 1;
128 L_num <<= 1;
129
130 if (L_num >= L_denom)
131 {
132 L_num -= L_denom;
133 var_out += 1;
134 }
135 }
136 }
137 }
138
139 #if (WMOPS)
140 multiCounter[currCounter].div_s++;
141 #endif
142 return (var_out);
143 }
144
145 ------------------------------------------------------------------------------
146 RESOURCES USED
147 When the code is written for a specific target processor the
148 the resources used should be documented below.
149
150 STACK USAGE: [stack count for this module] + [variable to represent
151 stack usage for each subroutine called]
152
153 where: [stack usage variable] = stack usage for [subroutine
154 name] (see [filename].ext)
155
156 DATA MEMORY USED: x words
157
158 PROGRAM MEMORY USED: x words
159
160 CLOCK CYCLES: [cycle count equation for this module] + [variable
161 used to represent cycle count for each subroutine
162 called]
163
164 where: [cycle count variable] = cycle count for [subroutine
165 name] (see [filename].ext)
166
167 ------------------------------------------------------------------------------
168 */
169
170
171 /*----------------------------------------------------------------------------
172 ; INCLUDES
173 ----------------------------------------------------------------------------*/
174 #include "basic_op.h"
175
176 /*----------------------------------------------------------------------------
177 ; MACROS
178 ; Define module specific macros here
179 ----------------------------------------------------------------------------*/
180
181 /*----------------------------------------------------------------------------
182 ; DEFINES
183 ; Include all pre-processor statements here. Include conditional
184 ; compile variables also.
185 ----------------------------------------------------------------------------*/
186
187 /*----------------------------------------------------------------------------
188 ; LOCAL FUNCTION DEFINITIONS
189 ; Function Prototype declaration
190 ----------------------------------------------------------------------------*/
191
192 /*----------------------------------------------------------------------------
193 ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
194 ; Variable declaration - defined here and used outside this module
195 ----------------------------------------------------------------------------*/
196
197 /*----------------------------------------------------------------------------
198 ; EXTERNAL FUNCTION REFERENCES
199 ; Declare functions defined elsewhere and referenced in this module
200 ----------------------------------------------------------------------------*/
201
202 /*----------------------------------------------------------------------------
203 ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
204 ; Declare variables used in this module but defined elsewhere
205 ----------------------------------------------------------------------------*/
206
207 /*----------------------------------------------------------------------------
208 ; FUNCTION CODE
209 ----------------------------------------------------------------------------*/
div_s(register Word16 var1,register Word16 var2)210 Word16 div_s(register Word16 var1, register Word16 var2)
211 {
212 /*----------------------------------------------------------------------------
213 ; Define all local variables
214 ----------------------------------------------------------------------------*/
215 Word16 var_out = 0;
216 register Word16 iteration;
217 Word32 L_num;
218 Word32 L_denom;
219 Word32 L_denom_by_2;
220 Word32 L_denom_by_4;
221
222 /*----------------------------------------------------------------------------
223 ; Function body here
224 ----------------------------------------------------------------------------*/
225 if ((var1 > var2) || (var1 < 0))
226 {
227 return 0; // used to exit(0);
228 }
229 if (var1)
230 {
231 if (var1 != var2)
232 {
233
234 L_num = (Word32) var1;
235 L_denom = (Word32) var2;
236 L_denom_by_2 = (L_denom << 1);
237 L_denom_by_4 = (L_denom << 2);
238 for (iteration = 5; iteration > 0; iteration--)
239 {
240 var_out <<= 3;
241 L_num <<= 3;
242
243 if (L_num >= L_denom_by_4)
244 {
245 L_num -= L_denom_by_4;
246 var_out |= 4;
247 }
248
249 if (L_num >= L_denom_by_2)
250 {
251 L_num -= L_denom_by_2;
252 var_out |= 2;
253 }
254
255 if (L_num >= (L_denom))
256 {
257 L_num -= (L_denom);
258 var_out |= 1;
259 }
260
261 }
262 }
263 else
264 {
265 var_out = MAX_16;
266 }
267 }
268
269 #if (WMOPS)
270 multiCounter[currCounter].div_s++;
271 #endif
272
273 /*----------------------------------------------------------------------------
274 ; Return nothing or data or data pointer
275 ----------------------------------------------------------------------------*/
276 return (var_out);
277 }
278