/* * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische * Universitaet Berlin. See the accompanying file "COPYRIGHT" for * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. */ /* * See private.h for the more commonly used macro versions. */ #include #include #include "gsm610_priv.h" #define saturate(x) \ ((x) < MIN_WORD ? MIN_WORD : (x) > MAX_WORD ? MAX_WORD: (x)) int16_t gsm_add (int16_t a, int16_t b) { int32_t sum = (int32_t) a + (int32_t) b ; return saturate (sum) ; } int16_t gsm_sub (int16_t a, int16_t b) { int32_t diff = (int32_t) a - (int32_t) b ; return saturate (diff) ; } int16_t gsm_mult (int16_t a, int16_t b) { if (a == MIN_WORD && b == MIN_WORD) return MAX_WORD ; return SASR_L ((int32_t) a * (int32_t) b, 15) ; } int16_t gsm_mult_r (int16_t a, int16_t b) { if (b == MIN_WORD && a == MIN_WORD) return MAX_WORD ; else { int32_t prod = (int32_t) a * (int32_t) b + 16384 ; prod >>= 15 ; return prod & 0xFFFF ; } } int16_t gsm_abs (int16_t a) { return a < 0 ? (a == MIN_WORD ? MAX_WORD : -a) : a ; } int32_t gsm_L_mult (int16_t a, int16_t b) { assert (a != MIN_WORD || b != MIN_WORD) ; return ((int32_t) a * (int32_t) b) << 1 ; } int32_t gsm_L_add (int32_t a, int32_t b) { if (a < 0) { if (b >= 0) return a + b ; else { uint32_t A = (uint32_t) - (a + 1) + (uint32_t) - (b + 1) ; return A >= MAX_LONGWORD ? MIN_LONGWORD : - (int32_t) A - 2 ; } } else if (b <= 0) return a + b ; else { uint32_t A = (uint32_t) a + (uint32_t) b ; return A > MAX_LONGWORD ? MAX_LONGWORD : A ; } } int32_t gsm_L_sub (int32_t a, int32_t b) { if (a >= 0) { if (b >= 0) return a - b ; else { /* a>=0, b<0 */ uint32_t A = (uint32_t) a + - (b + 1) ; return A >= MAX_LONGWORD ? MAX_LONGWORD : (A + 1) ; } } else if (b <= 0) return a - b ; else { /* a<0, b>0 */ uint32_t A = (uint32_t) - (a + 1) + b ; return A >= MAX_LONGWORD ? MIN_LONGWORD : - (int32_t) A - 1 ; } } static unsigned char const bitoff [256] = { 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } ; int16_t gsm_norm (int32_t a) /* * the number of left shifts needed to normalize the 32 bit * variable L_var1 for positive values on the interval * * with minimum of * minimum of 1073741824 (01000000000000000000000000000000) and * maximum of 2147483647 (01111111111111111111111111111111) * * * and for negative values on the interval with * minimum of -2147483648 (-10000000000000000000000000000000) and * maximum of -1073741824 (-1000000000000000000000000000000). * * in order to normalize the result, the following * operation must be done: L_norm_var1 = L_var1 << norm (L_var1) ; * * (That's 'ffs', only from the left, not the right..) */ { assert (a != 0) ; if (a < 0) { if (a <= -1073741824) return 0 ; a = ~a ; } return a & 0xffff0000 ? (a & 0xff000000 ? -1 + bitoff [0xFF & (a >> 24)] : 7 + bitoff [0xFF & (a >> 16)]) : (a & 0xff00 ? 15 + bitoff [0xFF & (a >> 8)] : 23 + bitoff [0xFF & a]) ; } int32_t gsm_L_asl (int32_t a, int n) { if (n >= 32) return 0 ; if (n <= -32) return - (a < 0) ; if (n < 0) return gsm_L_asr (a, -n) ; return a << n ; } int16_t gsm_asr (int16_t a, int n) { if (n >= 16) return - (a < 0) ; if (n <= -16) return 0 ; if (n < 0) return a << -n ; return SASR_W (a, (int16_t) n) ; } int16_t gsm_asl (int16_t a, int n) { if (n >= 16) return 0 ; if (n <= -16) return - (a < 0) ; if (n < 0) return gsm_asr (a, -n) ; return a << n ; } int32_t gsm_L_asr (int32_t a, int n) { if (n >= 32) return - (a < 0) ; if (n <= -32) return 0 ; if (n < 0) return a << -n ; return SASR_L (a, (int16_t) n) ; } /* ** int16_t gsm_asr (int16_t a, int n) ** { ** if (n >= 16) return - (a < 0) ; ** if (n <= -16) return 0 ; ** if (n < 0) return a << -n ; ** ** # ifdef SASR_W ** return a >> n ; ** # else ** if (a >= 0) return a >> n ; ** else return - (int16_t) (- (uint16_t)a >> n) ; ** # endif ** } ** */ /* * (From p. 46, end of section 4.2.5) * * NOTE: The following lines gives [sic] one correct implementation * of the div (num, denum) arithmetic operation. Compute div * which is the integer division of num by denum: with denum * >= num > 0 */ int16_t gsm_div (int16_t num, int16_t denum) { int32_t L_num = num ; int32_t L_denum = denum ; int16_t div = 0 ; int k = 15 ; /* The parameter num sometimes becomes zero. * Although this is explicitly guarded against in 4.2.5, * we assume that the result should then be zero as well. */ /* assert (num != 0) ; */ assert (num >= 0 && denum >= num) ; if (num == 0) return 0 ; while (k--) { div <<= 1 ; L_num <<= 1 ; if (L_num >= L_denum) { L_num -= L_denum ; div++ ; } } return div ; }