sl@0: // Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include "basicop.h" sl@0: sl@0: /* sl@0: ** int2 add( int2 var1, int2 var2 ) sl@0: ** sl@0: ** Function performs the addition (var1+var2) with overflow control sl@0: ** and saturation; the result is set at +32767 when overflow occurs sl@0: ** or at -32768 when underflow occurs sl@0: ** sl@0: ** Input: sl@0: ** var1, var2 sl@0: ** 16-bit variables to be summed sl@0: ** sl@0: ** Output: sl@0: ** Sum of var and var2, see description above sl@0: ** sl@0: ** Return value: sl@0: ** See above sl@0: */ sl@0: /* sl@0: ** One way to implement saturation control to add and sub is to sl@0: ** use temporary result that has enough bits to make overflow sl@0: ** impossible and the limit the final result sl@0: */ sl@0: int2 add( int2 var1, int2 var2 ) sl@0: { sl@0: int4 L_temp; sl@0: sl@0: L_temp = (int4) var1 + var2; sl@0: sl@0: if ( L_temp < MININT2 ) sl@0: return MININT2; sl@0: else if ( L_temp > MAXINT2 ) sl@0: return MAXINT2; sl@0: else sl@0: return (int2) L_temp; sl@0: } sl@0: sl@0: sl@0: /* sl@0: ** int2 sub( int2 var1, int2 var2 ) sl@0: ** sl@0: ** Function performs the subtraction (var1-var2) with overflow control sl@0: ** and saturation; the result is set at +32767 when overflow occurs sl@0: ** or at -32768 when underflow occurs sl@0: ** sl@0: ** Input: sl@0: ** var1, var2 sl@0: ** 16-bit variables to be summed sl@0: ** sl@0: ** Output: sl@0: ** Sum of var and var2, see description above sl@0: ** sl@0: ** Return value: sl@0: ** See above sl@0: */ sl@0: int2 sub( int2 var1, int2 var2 ) sl@0: { sl@0: int4 L_temp; sl@0: sl@0: L_temp = (int4) var1 - var2; sl@0: sl@0: if ( L_temp < MININT2 ) sl@0: return MININT2; sl@0: else if ( L_temp > MAXINT2 ) sl@0: return MAXINT2; sl@0: else sl@0: return (int2) L_temp; sl@0: } sl@0: sl@0: sl@0: sl@0: /* sl@0: ** int2 mult( int2 var1, int2 var2 ) sl@0: ** sl@0: ** Function performs the multiplication of var1 by var2 and gives a sl@0: ** 16-bit result which is scaled ie sl@0: ** mult( var1, var2 ) = (var1 times var2) >> 15 sl@0: ** and sl@0: ** mult( -32768, -32768 ) = 32767 sl@0: ** sl@0: ** Input: sl@0: ** var1, var2 sl@0: ** 16-bit variables to be multiplied sl@0: ** sl@0: ** Output: sl@0: ** Scaled result of multiplication sl@0: ** sl@0: ** Return value: sl@0: ** See above sl@0: */ sl@0: int2 mult( int2 var1, int2 var2 ) sl@0: { sl@0: if ( ( var1 == MININT2 ) && ( var1 == var2 ) ) sl@0: return MAXINT2; sl@0: else sl@0: /* Note int4 cast of var1 to force 32-bit arithmetic */ sl@0: return( (int2) ( ( (int4) var1 * var2 ) >> 15 ) ); sl@0: } sl@0: sl@0: sl@0: /* sl@0: ** int2 abs_s( int2 var1 ) sl@0: ** sl@0: ** Function returns absolute value of var1 with possible saturation: sl@0: ** abs( -32768 ) = 32767 sl@0: ** sl@0: ** Input: sl@0: ** var1 sl@0: ** 16-bit variable sl@0: ** sl@0: ** Output: sl@0: ** absolute value of var1 sl@0: ** sl@0: ** Return value: sl@0: ** See above sl@0: */ sl@0: int2 abs_s( int2 var1 ) sl@0: { sl@0: if ( var1 == MININT2 ) sl@0: return MAXINT2; sl@0: else sl@0: return ( var1 > 0 ) ? var1 : int2 (-var1); sl@0: } sl@0: sl@0: sl@0: #ifdef L_MULTF sl@0: /* else implemented using macro (basicop.h) */ sl@0: sl@0: /* sl@0: ** int4 L_mult( int2 var1, int2 var2 ) sl@0: ** sl@0: ** Function performs the multiplication of var1 by var2 and gives a sl@0: ** 32-bit result which is scaled by shifting result one bit left ie sl@0: ** L_mult( var1, var2 ) = (var1 times var2) << 1 sl@0: ** sl@0: ** L_mult( -32768, -32768 ) does not occur in algorithm sl@0: ** sl@0: ** Input: sl@0: ** var1, var2 sl@0: ** 16-bit variables to be multiplied sl@0: ** sl@0: ** Output: sl@0: ** Scaled result of multiplication sl@0: ** sl@0: ** Return value: sl@0: ** See above sl@0: */ sl@0: int4 L_mult( int2 var1, int2 var2 ) sl@0: { sl@0: /* Note int4 cast of var1 to force 32-bit arithmetic */ sl@0: return ( L_shl( (int4) var1 * var2 ), 1 ); sl@0: } sl@0: #endif /* L_MULTF */ sl@0: sl@0: sl@0: sl@0: /* sl@0: ** int2 shr( int2 var1, int2 var2 ) sl@0: ** sl@0: ** Function makes arithmetic var2-bit shift right of var1. If var2 is sl@0: ** less than 0, this operation becomes arithmetic left shift of -var2 sl@0: ** sl@0: ** Input: sl@0: ** var1 sl@0: ** 16-bit variable to be shifted sl@0: ** var2 sl@0: ** amount of bits to be shifted sl@0: ** sl@0: ** Output: sl@0: ** 16-bit value of shifted var1 is returned sl@0: ** sl@0: ** Return value: sl@0: ** See above sl@0: */ sl@0: int2 shr( int2 var1, int2 var2 ) sl@0: { sl@0: return shl( var1, int2 (-var2) ); sl@0: } sl@0: sl@0: sl@0: /* sl@0: ** int2 negate( int2 var1 ) sl@0: ** sl@0: ** Function negates 16-bit variable var1. sl@0: ** negate( -32768 ) = 32767 sl@0: ** sl@0: ** Input: sl@0: ** var1 sl@0: ** 16-bit variable to be negated sl@0: ** sl@0: ** Output: sl@0: ** negated var1 sl@0: ** sl@0: ** Return value: sl@0: ** See above sl@0: */ sl@0: int2 negate( int2 var1 ) sl@0: { sl@0: if ( var1 == MININT2 ) sl@0: return MAXINT2; sl@0: else sl@0: return int2 (-var1); sl@0: } sl@0: sl@0: sl@0: /* sl@0: ** int2 extract_h( int4 L_var1 ) sl@0: ** sl@0: ** Function returns upper word (16 most significat bits) of the sl@0: ** 32-bit variable L_var1 sl@0: ** sl@0: ** Input: sl@0: ** L_var1 sl@0: ** 32-bit variable sl@0: ** sl@0: ** Output: sl@0: ** upper word of the L_var1 sl@0: ** sl@0: ** Return value: sl@0: ** See above sl@0: */ sl@0: int2 extract_h( int4 L_var1 ) sl@0: { sl@0: return (int2) ( L_var1 >> 16 ); sl@0: } sl@0: sl@0: sl@0: /* sl@0: ** int2 extract_l( int4 L_var1 ) sl@0: ** sl@0: ** Function returns lower word (16 least significat bits) of the sl@0: ** 32-bit variable L_var1 sl@0: ** sl@0: ** Input: sl@0: ** L_var1 sl@0: ** 32-bit variable sl@0: ** sl@0: ** Output: sl@0: ** lower word of L_var1 sl@0: ** sl@0: ** Return value: sl@0: ** See above sl@0: */ sl@0: int2 extract_l( int4 L_var1 ) sl@0: { sl@0: return (int2) (L_var1 & 0x0000ffff); sl@0: } sl@0: sl@0: sl@0: /* sl@0: ** int4 L_mac( int4 L_var3, int2 var1, int2 var2 ) sl@0: ** sl@0: ** Function multiplies var1 by var2 and shifts result left by one bit. sl@0: ** Shifted result of multiplication is then added to L_var3 and result sl@0: ** is returned. Summation is done with overflow control and saturation; sl@0: ** the result is set at 2147483647 when overflow occurs and at sl@0: ** -2147483648 when underflow occurs sl@0: ** sl@0: ** Input: sl@0: ** var1 sl@0: ** 16-bit multiplicant sl@0: ** var2 sl@0: ** 16-bit multiplier sl@0: ** sl@0: ** L_var3 sl@0: ** 32-bit number that is summed with (var1*var2)<<1 sl@0: ** sl@0: ** Output: sl@0: ** See description above sl@0: ** sl@0: ** Return value: sl@0: ** See above sl@0: */ sl@0: int4 L_mac( int4 L_var3, int2 var1, int2 var2 ) sl@0: { sl@0: int4 L_temp; sl@0: sl@0: L_temp = ( (int4) var1 * var2 ) << 1; sl@0: return L_add( L_var3, L_temp ); sl@0: } sl@0: sl@0: sl@0: /* sl@0: ** int4 L_add( int4 L_var1, int4 L_var2 ) sl@0: ** sl@0: ** Function performs 32-bit addition of two 32-bit variables sl@0: ** (L_var1 + L_var2) with overflow control and saturation; the sl@0: ** result is set at 2147483647 when overflow occurs and at sl@0: ** -2147483648 when underflow occurs sl@0: ** sl@0: ** Input: sl@0: ** L_var1, L_var2 sl@0: ** 32-bit variables to be summed sl@0: ** sl@0: ** Output: sl@0: ** 32-bit result, see description above sl@0: ** sl@0: ** Return value: sl@0: ** See above sl@0: */ sl@0: int4 L_add( int4 L_var1, int4 L_var2 ) sl@0: { sl@0: int4 L_temp1; sl@0: int temp2; /* used for storing sign of L_var1 */ sl@0: sl@0: L_temp1 = L_var1 + L_var2; sl@0: sl@0: /* sl@0: * Overflow sl@0: * if sign(L_var1)==sign(L_var2) && sign(L_var1)!=sign(L_temp1). sl@0: */ sl@0: sl@0: if ( ( temp2 = (L_var1 < 0) ) == ( L_var2 < 0 ) sl@0: && ( temp2 != ( L_temp1 < 0 ) ) ) { sl@0: L_temp1 = temp2 ? MININT4 : MAXINT4; sl@0: } sl@0: sl@0: return L_temp1; sl@0: } sl@0: sl@0: sl@0: /* sl@0: ** int4 L_sub( int4 L_var1, int4 L_var2 ) sl@0: ** sl@0: ** Function performs 32-bit subtraction of two 32-bit variables sl@0: ** (L_var1 - L_var2) with overflow control and saturation; the sl@0: ** result is set at 2147483647 when overflow occurs and at sl@0: ** -2147483648 when underflow occurs sl@0: ** sl@0: ** Input: sl@0: ** L_var1, L_var2 sl@0: ** 32-bit variables to be summed sl@0: ** sl@0: ** Output: sl@0: ** 32-bit result, see description above sl@0: ** sl@0: ** Return value: sl@0: ** See above sl@0: */ sl@0: int4 L_sub( int4 L_var1, int4 L_var2 ) sl@0: { sl@0: int4 L_temp1; sl@0: int temp2; sl@0: sl@0: L_temp1 = L_var1 - L_var2; sl@0: sl@0: /* sl@0: * Overflow sl@0: * if sign(L_var1)!=sign(L_var2) && sign(L_var1)!=sign(L_temp). sl@0: */ sl@0: sl@0: if ( ( temp2 = ( L_var1 < 0 ) ) != ( L_var2 < 0 ) sl@0: && ( temp2 != ( L_temp1 < 0 ) ) ) { sl@0: L_temp1 = temp2 ? MININT4 : MAXINT4; sl@0: } sl@0: sl@0: return L_temp1; sl@0: } sl@0: sl@0: sl@0: /* sl@0: ** int2 mult_r( int2 var1, int2 var2 ) sl@0: ** sl@0: ** Function performs the multiplication of var1 by var2 and gives a sl@0: ** 16-bit result which is scaled with rounding ie sl@0: ** mult_r(var1, var2) = ((var1 times var2) + 16384) >> 15 sl@0: ** and sl@0: ** mult_r( -32768, -32768 ) = 32767 sl@0: ** sl@0: ** Input: sl@0: ** var1, var2 sl@0: ** 16-bit variables to be multiplied sl@0: ** sl@0: ** Output: sl@0: ** 16-bit scaled result of multiplication sl@0: ** sl@0: ** Return value: sl@0: ** See above sl@0: */ sl@0: int2 mult_r( int2 var1, int2 var2 ) sl@0: { sl@0: if ( ( var1 == MININT2 ) && ( var1 == var2 ) ) sl@0: return MAXINT2; sl@0: else sl@0: /* Note int4 cast of var1 to force 32-bit arithmetic */ sl@0: return( (int2) ( ( (int4) var1 * var2 + (int4) 16384 ) >> 15 ) ); sl@0: } sl@0: sl@0: /* sl@0: ** int4 L_shr( int4 L_var1, int2 var2 ) sl@0: ** sl@0: ** Function makes arithmetic var2-bit shift right of var1. If var2 is sl@0: ** less than 0, this operation becomes arithmetic left shift of -var2 sl@0: ** sl@0: ** Input: sl@0: ** L_var1 sl@0: ** 32-bit variable to be shifted sl@0: ** var2 sl@0: ** amount of bits to be shifted sl@0: ** sl@0: ** Output: sl@0: ** 16-bit value of shifted var1 sl@0: ** sl@0: ** Return value: sl@0: ** See above sl@0: */ sl@0: int4 L_shr( int4 L_var1, int2 var2 ) sl@0: { sl@0: return L_shl( L_var1, int2 (-var2) ); sl@0: } sl@0: sl@0: sl@0: /* sl@0: ** int4 L_deposit_h( int2 var1 ) sl@0: ** sl@0: ** Function deposits the 16-bit variable var1 into the 16 most sl@0: ** significant bits of the 32-bit word. The 16 least significant sl@0: ** bits of the result are zeroed. sl@0: ** sl@0: ** Input: sl@0: ** var1 sl@0: ** 16-bit variable to be loaded to the upper 16 bits of sl@0: ** of the 32-bit variable sl@0: ** sl@0: ** Output: sl@0: ** 32-bit number, see description above sl@0: ** sl@0: ** Return value: sl@0: ** See above sl@0: */ sl@0: int4 L_deposit_h( int2 var1 ) sl@0: { sl@0: return ( (int4) var1 ) << 16; sl@0: } sl@0: sl@0: sl@0: /* sl@0: ** int4 L_deposit_l( int2 var1 ) sl@0: ** sl@0: ** Function deposits the 16-bit variable var1 into the 16 least sl@0: ** significant bits of the 32-bit word. The 16 most significant bits sl@0: ** of the result are sign extended. sl@0: ** sl@0: ** Input: sl@0: ** var1 sl@0: ** 16-bit variable to be converted to 32-bit variable sl@0: ** sl@0: ** Output: sl@0: ** 32-bit variable that has same magnitude than var1 sl@0: ** sl@0: ** Return value: sl@0: ** See above sl@0: */ sl@0: int4 L_deposit_l( int2 var1 ) sl@0: { sl@0: return (int4) var1; sl@0: } sl@0: sl@0: sl@0: /* sl@0: ** int2 norm_s( int2 var1 ) sl@0: ** sl@0: ** Function produces number of left shifts needed to normalize the sl@0: ** 16-bit variable var1 for positive values on the interval with sl@0: ** minimum of 16384 and maximum of 32767 and for negative sl@0: ** values on the interval with minimum of -32768 and maximum of sl@0: ** -16384; in order to normalize the result, the following sl@0: ** operation must be done: sl@0: ** norm_var1 = var1 << norm_s(var1) sl@0: ** sl@0: ** Input: sl@0: ** var1 sl@0: ** 16-bit variable which normalization factor is solved sl@0: ** sl@0: ** Output: sl@0: ** see description above sl@0: ** sl@0: ** Return value: sl@0: ** See above sl@0: */ sl@0: int2 norm_s( int2 var1 ) sl@0: { sl@0: int2 cntr = 0; sl@0: sl@0: /* Special case when L_var1 == -32768: shift leads to underflow */ sl@0: if ( var1 == MININT2 ) sl@0: return 0; sl@0: /* Special case when var1 == 0: shift does not change the value */ sl@0: else if ( var1 == 0 ) sl@0: return 0; sl@0: else { sl@0: if ( var1 < 0 ) { sl@0: for ( ; var1 >= -16384; var1 *= 2 ) sl@0: cntr++; sl@0: } sl@0: else { sl@0: for ( ; var1 < 16384; var1 <<= 1 ) sl@0: cntr++; sl@0: } sl@0: sl@0: return cntr; sl@0: } sl@0: } sl@0: sl@0: sl@0: /* sl@0: ** int2 norm_l( int4 L_var1 ) sl@0: ** sl@0: ** Function produces number of left shifts needed to normalize the sl@0: ** 32-bit variable L_var1 for positive values on the interval with sl@0: ** minimum of 1073741824 and maximum of 2147483647 and for negative sl@0: ** values on the interval with minimum of -2147483648 and maximum of sl@0: ** -1073741824; in order to normalize the result, the following sl@0: ** operation must be done: sl@0: ** L_norm_var1 = L_var1 << norm_l(L_var1) sl@0: ** sl@0: ** Input: sl@0: ** L_var1 sl@0: ** 32-bit variable which normalization factor is solved sl@0: ** sl@0: ** Output: sl@0: ** see description above sl@0: ** sl@0: ** Return value: sl@0: ** See above sl@0: */ sl@0: int2 norm_l( int4 L_var1 ) sl@0: { sl@0: int2 cntr = 0; sl@0: sl@0: /* Special case when L_var1 == -2147483648: shift leads to underflow */ sl@0: if ( L_var1 == MININT4 ) sl@0: return 0; sl@0: /* Special case when L_var1 == 0: shift does not change the value */ sl@0: else if ( L_var1 == 0 ) sl@0: return 0; sl@0: else { sl@0: if ( L_var1 < 0 ) { sl@0: for ( ; L_var1 >= (int4) -1073741824L; L_var1 *= 2 ) sl@0: cntr++; sl@0: } sl@0: else { sl@0: for ( ; L_var1 < (int4) 1073741824L; L_var1 <<= 1 ) sl@0: cntr++; sl@0: } sl@0: sl@0: return cntr; sl@0: } sl@0: } sl@0: sl@0: sl@0: /* sl@0: ** int2 div_s( int2 num, int2 denum ) sl@0: ** sl@0: ** Function produces a result which is the fractional integer division sl@0: ** of var1 by var2; var1 and var2 must be positive and var2 must be sl@0: ** greater or equal to var1; The result is positive (leading bit equal sl@0: ** to 0) and truncated to 16 bits. If var1 == var2 then sl@0: ** div_s( var1, var2 ) = 32767 sl@0: ** sl@0: ** Input: sl@0: ** L_var1 sl@0: ** 32-bit variable which normalization factor is solved sl@0: ** sl@0: ** Output: sl@0: ** 16-bit result, see description above sl@0: ** sl@0: ** Return value: sl@0: ** See above sl@0: */ sl@0: int2 div_s( int2 num, int2 denum ) sl@0: { sl@0: if ( num == denum ) sl@0: return MAXINT2; sl@0: else sl@0: return (int2) ( ( ( (int4) num ) << 15 ) / denum ); sl@0: } sl@0: sl@0: sl@0: /* sl@0: ** int2 shl( int2 var1, int2 var2 ) sl@0: ** sl@0: ** Function makes arithmetic var2-bit shift left of var1. If var2 is sl@0: ** less than 0, this operation becomes arithmetic right shift of -var2 sl@0: ** sl@0: ** Input: sl@0: ** var1 sl@0: ** 16-bit variable to be shifted sl@0: ** var2 sl@0: ** amount of bits to be shifted sl@0: ** sl@0: ** Output: sl@0: ** 16-bit value of shifted var1 is retuned sl@0: ** sl@0: ** Return value: sl@0: ** See above sl@0: ** sl@0: ** Notes: sl@0: ** ANSI C does not guarantee that right shift is arithmetical sl@0: ** (that sign extension is done during shifting). That is why in this sl@0: ** routine negative values are complemented before shifting. sl@0: */ sl@0: int2 shl( int2 var1, int2 var2 ) sl@0: { sl@0: int2 result; sl@0: sl@0: if ( ( var1 == 0 ) || ( var2 == 0 ) ) { sl@0: result = var1; sl@0: } sl@0: sl@0: /* var2 > 0: Perform left shift */ sl@0: else if ( var2 > 0 ) { sl@0: if ( var2 >= 15 ) { sl@0: result = ( var1 < 0 ) ? int2(MININT2) : int2(MAXINT2); sl@0: } sl@0: else { sl@0: sl@0: int4 L_temp; sl@0: sl@0: L_temp = (int4) var1 << var2; sl@0: if ( L_temp < MININT2 ) { sl@0: result = MININT2; sl@0: } sl@0: else if ( L_temp > MAXINT2 ) { sl@0: result = MAXINT2; sl@0: } sl@0: else { sl@0: result = (int2) L_temp; sl@0: } sl@0: } sl@0: } sl@0: /* var2 < 0: Perform right shift */ sl@0: else { sl@0: if ( -var2 >= 15 ) { sl@0: result = ( var1 < 0 ) ? int2 (-1) : int2 (0); sl@0: } sl@0: else if ( var1 < 0 ) { sl@0: result = int2 (~( (~var1) >> -var2 )); /* ~ used to ensure arith. shift */ sl@0: } sl@0: else { sl@0: result = int2 (var1 >> -var2); sl@0: } sl@0: } sl@0: sl@0: return result; sl@0: sl@0: } sl@0: sl@0: sl@0: /* sl@0: ** int4 L_shl( int4 L_var1, int2 var2 ) sl@0: ** sl@0: ** Function makes arithmetic var2-bit shift left of var1. If var2 is sl@0: ** less than 0, this operation becomes arithmetic right shift of -var2 sl@0: ** sl@0: ** Input: sl@0: ** L_var1 sl@0: ** 32-bit variable to be shifted sl@0: ** var2 sl@0: ** amount of bits to be shifted sl@0: ** sl@0: ** Output: sl@0: ** 32-bit value of shifted var1 is retuned sl@0: ** sl@0: ** Return value: sl@0: ** See above sl@0: ** sl@0: ** Notes: sl@0: ** ANSI C does not guarantee that right shift is arithmetical sl@0: ** (that sign extension is done during shifting). That is why in this sl@0: ** routine negative values are complemented before shifting. sl@0: */ sl@0: sl@0: int4 L_shl(int4 L_var1, int2 var2 ) sl@0: { sl@0: if ( ( L_var1 == 0L ) || ( var2 == 0 ) ) { sl@0: return L_var1; sl@0: } sl@0: /* var2 > 0: Perform left shift */ sl@0: else if ( var2 > 0 ) { sl@0: if ( var2 >= 31 ) { sl@0: return ( L_var1 < 0 ) ? MININT4 : MAXINT4; sl@0: } sl@0: else { sl@0: for( ; var2 > 0; var2-- ) { sl@0: if ( L_var1 > (MAXINT4 >> 1) ) sl@0: return MAXINT4; sl@0: else if ( L_var1 < (MININT4 / 2) ) sl@0: return MININT4; sl@0: else sl@0: L_var1 *= 2; sl@0: } sl@0: return L_var1; sl@0: } sl@0: } sl@0: /* var2 < 0: Perform right shift */ sl@0: else { sl@0: if ( -var2 >= 31 ) { sl@0: return ( L_var1 < 0 ) ? -1L : 0L; sl@0: } sl@0: else if ( L_var1 < 0 ) { sl@0: return ~( (~L_var1) >> -var2 ); /* ~ used to ensure arith. shift */ sl@0: } sl@0: else { sl@0: return L_var1 >> -var2; sl@0: } sl@0: } sl@0: sl@0: } sl@0: