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