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 ----------------------------------------------------------------------------*/ 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