#ifndef	SamsungECNS_BASICOP_H
#define SamsungECNS_BASICOP_H

#include "Define_config.h"
#include "SamsungSolomonVoiceW_DSP_ASM_OPT.h"
#include	"log2.tab"     /* Table for DVTXOP_Log2() */
//#define FLAG_SELECT_C_DSP 1

/*___________________________________________________________________________
|                                                                           |
|   Constants and Globals                                                   |
|___________________________________________________________________________|
*/

extern int DVTXOP_Overflow;
extern int DVTXOP_Carry;
#define DVTX_MAX_64 (long long)0x7fffffffffffffffLL
#define DVTX_MIN_64 (long long)0x8000000000000000LL
#define DVTX_MAX_32 (int)0x7fffffffL
#define DVTX_MIN_32 (int)0x80000000L
#define DVTX_MAX_16 (short)0x7fff
#define DVTX_MIN_16 (short)0x8000

#ifndef FLAG_DSP_ASM_ON
#define MULT16_16(a,b)     (((int)(short)(a))*((int)(short)(b)))
#else
#define MULT16_16(a,b)     ((int)(AE_MUL16S(a, b)))
#endif


#define ADD32(a,b) ((int)(a)+(int)(b))
#define SHR(a,shift) ((a) >> (shift))
#define SHL32(a,shift) ((int)((unsigned int)(a)<<(shift)))
#define MUL(a,b) ((a)*(b))
#define MULL(a,b) ((long long)(a)*(b))
#define MULF(a, b) ((int)2*(a)*(b)>>16)
#define ADD32(a,b) ((int)(a)+(int)(b))
#define SHR(a,shift) ((a) >> (shift))
#define SHL32(a,shift) ((int)((unsigned int)(a)<<(shift)))

/*___________________________________________________________________________
|                                                                           |
|   Prototypes for basic arithmetic operators                               |
|___________________________________________________________________________|
*/
#ifndef FLAG_DSP_ASM_ON
short DVTXOP_saturate(int L_var1);


short DVTXOP_add(short var1, short var2);    /* Short DVTXOP_add,           1   */
short DVTXOP_sub(short var1, short var2);    /* Short DVTXOP_sub,           1   */
short DVTXOP_abs_s(short var1);               /* Short abs,           1   */
short DVTXOP_shl(short var1, short var2);    /* Short shift left,    1   */
short DVTXOP_shr(short var1, short var2);    /* Short shift right,   1   */
short DVTXOP_mult(short var1, short var2);   /* Short DVTXOP_mult,          1   */
int DVTXOP_L_mult(short var1, short var2); /* Long DVTXOP_mult,           1   */
short DVTXOP_negate(short var1);              /* Short DVTXOP_negate,        1   */
short DVTXOP_extract_h(int L_var1);         /* Extract high,        1   */
short DVTXOP_extract_l(int L_var1);         /* Extract low,         1   */
short DVTXOP_round(int L_var1);             /* DVTXOP_round,               1   */
int DVTXOP_L_mac(int L_var3, short var1, short var2);   /* Mac,  1  */
int DVTXOP_L_msu(int L_var3, short var1, short var2);   /* Msu,  1  */
int DVTXOP_L_add(int L_var1, int L_var2);    /* Long DVTXOP_add,        2 */
int DVTXOP_L_sub(int L_var1, int L_var2);    /* Long DVTXOP_sub,        2 */
int DVTXOP_L_negate(int L_var1);                /* Long DVTXOP_negate,     2 */
short DVTXOP_mult_r(short var1, short var2);       /* Mult with DVTXOP_round, 2 */
int DVTXOP_L_shl(int L_var1, short var2);      /* Long shift left, 2 */
int DVTXOP_L_shr(int L_var1, short var2);      /* Long shift right, 2*/
short DVTXOP_shr_r(short var1, short var2);        /* Shift right with DVTXOP_round, 2*/
short DVTXOP_mac_r(int L_var3, short var1, short var2); /* Mac with DVTXOP_rounding,2 */
short DVTXOP_msu_r(int L_var3, short var1, short var2); /* Msu with DVTXOP_rounding,2 */
int DVTXOP_L_deposit_h(short var1);        /* 16 bit var1 -> MSB,     2 */
int DVTXOP_L_deposit_l(short var1);        /* 16 bit var1 -> LSB,     2 */
int DVTXOP_L_shr_r(int L_var1, short var2); /* Long shift right with DVTXOP_round,  3             */
int DVTXOP_L_abs(int L_var1);            /* Long abs,              3  */
short DVTXOP_norm_s(short var1);             /* Short norm,           15  */
short DVTXOP_div_s(short var1, short var2); /* Short division,       18  */
short DVTXOP_norm_l(int L_var1);           /* Long norm,            30  */
short DVTXOP_norm_ll(long long L_var1);
int DVTXOP_Ls_mult_r(int L_var1, short var2);
int DVTXOP_L_mult_r(int L_var1, int L_var2);
#else
static __inline short DVTXOP_saturate(int L_var1) {return AE_SAT16X4_scalar(L_var1);}
static __inline short DVTXOP_add(short var1, short var2){return AE_ADD16S_scalar(var1, var2);}
static __inline short DVTXOP_sub(short var1, short var2){return AE_SUB16S_scalar(var1, var2);}
static __inline short DVTXOP_abs_s(short var1){return AE_ABS16S_scalar(var1);}
static __inline short DVTXOP_shl(short var1, short var2) {return AE_SLAA16S_scalar(var1, var2);}
static __inline short DVTXOP_shr(short var1, short var2) {return AE_SRAA16S_scalar(var1, var2);}
static __inline short DVTXOP_mult(short var1, short var2) {return AE_MULFP16X4S_scalar(var1, var2);}
static __inline int DVTXOP_L_mult(short var1, short var2) {return AE_MULF16X4SS_scalar(var1, var2);}
static __inline short DVTXOP_negate(short var1) {return AE_NEG16S_scalar(var1);}
static __inline short DVTXOP_extract_h(int L_var1) {return AE_TRUNC16X4F32_scalar(L_var1);}
static __inline short DVTXOP_extract_l(int L_var1) {return AE_CVT16X4_scalar(L_var1);}
static __inline short DVTXOP_round(int L_var1) {return AE_ROUND16X4F32SASYM_scalar(L_var1);}
static __inline int DVTXOP_L_mac(int L_var3, short var1, short var2) {return AE_MULAF16X4SS_scalar(L_var3, var1, var2);}
static __inline int DVTXOP_L_msu(int L_var3, short var1, short var2) {return AE_MULSF16X4SS_scalar(L_var3, var1, var2);}
static __inline int DVTXOP_L_add(int L_var1, int L_var2) {return AE_ADD32S_scalar(L_var1, L_var2);}
static __inline int DVTXOP_L_sub(int L_var1, int L_var2) {return AE_SUB32S_scalar(L_var1, L_var2);}
static __inline int DVTXOP_L_negate(int L_var1) {return AE_NEG32S_scalar(L_var1);}
static __inline short DVTXOP_mult_r(short var1, short var2) {return AE_MULFP16X4RAS_scalar(var1, var2);}
static __inline int DVTXOP_L_shl(int L_var1, short var2) {return AE_SLAA32S_scalar(L_var1, var2);}
static __inline int DVTXOP_L_shr(int L_var1, short var2) {return AE_SRAA32S_scalar(L_var1, var2);}
static __inline short DVTXOP_shr_r(short var1, short var2) {return AE_SRAA16RS_scalar (var1, var2);}
static __inline short DVTXOP_mac_r(int L_var3, short var1, short var2) {return AE_ROUND16X4F32SASYM_scalar(AE_MULAF16X4SS_scalar(L_var3, var1, var2));}
static __inline short DVTXOP_msu_r(int L_var3, short var1, short var2) {return AE_ROUND16X4F32SASYM_scalar(AE_MULSF16X4SS_scalar(L_var3, var1, var2));}
static __inline int DVTXOP_L_deposit_h(short var1) {return AE_CVT32X2F16_10_scalar(var1);}
static __inline int DVTXOP_L_deposit_l(short var1) {return AE_SEXT32X2D16_10_scalar(var1);}
static __inline int DVTXOP_L_shr_r(int L_var1, short var2) {return AE_SRAA32RS_scalar(L_var1, var2);}
static __inline int DVTXOP_L_abs(int L_var1) {return AE_ABS32S_scalar(L_var1);}
static __inline short DVTXOP_norm_s(short var1) {return AE_NSAZ16_0_scalar(var1);}
static __inline short DVTXOP_div_s(short var1, short var2)
{
	short var_out;

	/* standard code exits for these 2 conditions */
	if (var2 == 0) return 0;

	if ((var1 >  var2) ||  (var2 <  0)) 
		return 0;


	if (var1 == var2) return (short)0x7fff;

	ae_int64 d_num_result;
	ae_int32x2 d_tmp, d_denom;

	d_denom = AE_MOVDA32X2(var2, var2);
	d_tmp = AE_MOVDA32X2(var1, 0);
	d_num_result = AE_MOVINT64_FROMINT32X2(d_tmp);

	AE_DIV64D32_L(d_num_result, d_denom);
	AE_DIV64D32_L(d_num_result, d_denom);
	AE_DIV64D32_L(d_num_result, d_denom);
	AE_DIV64D32_L(d_num_result, d_denom);
	AE_DIV64D32_L(d_num_result, d_denom);
	AE_DIV64D32_L(d_num_result, d_denom);
	AE_DIV64D32_L(d_num_result, d_denom);
	AE_DIV64D32_L(d_num_result, d_denom);
	AE_DIV64D32_L(d_num_result, d_denom);
	AE_DIV64D32_L(d_num_result, d_denom);
	AE_DIV64D32_L(d_num_result, d_denom);
	AE_DIV64D32_L(d_num_result, d_denom);
	AE_DIV64D32_L(d_num_result, d_denom);
	AE_DIV64D32_L(d_num_result, d_denom);
	AE_DIV64D32_L(d_num_result, d_denom);

	d_tmp = AE_MOVINT32X2_FROMINT64(d_num_result);
	var_out = (short)AE_MOVAD32_L(d_tmp);
	return var_out;
}
#ifdef OPT_HIFI_MIN_MAX
static __inline int DVTX_MAX(int a, int b) { return AE_MAX_32_signed(a, b);}////////////////////////test
static __inline int DVTX_MIN(int a, int b) { return AE_MIN_32_signed(a, b);}////////////////////////test
#endif
static __inline short DVTXOP_norm_l(int L_var1) { return AE_NSAZ32_L(L_var1); }
static __inline int DVTXOP_Ls_mult_r(int L_var1, short var2) { return AE_MOVAD32_L(AE_MULFP32X16X2RAS_L(AE_MOVDA32(L_var1), AE_MOVDA16(var2))); }
static __inline int DVTXOP_L_mult_r(int L_var1, int L_var2) { return AE_MOVAD32_L(AE_MULFP32X2RAS(AE_MOVDA32(L_var1), AE_MOVDA32(L_var2))); }

#ifdef BASIC_LL_OPS
static __inline long long DVTXOP_LL_add(long long L_var1, long long L_var2){return AE_ADD64S(L_var1, L_var2);}
static __inline long long DVTXOP_LL_sub(long long L_var1, long long L_var2){return AE_SUB64S(L_var1, L_var2);}
static __inline long long DVTXOP_LL_mult(int var1, int var2)
{
	ae_int64 tmp;
	tmp = AE_MUL32_LL(var1, var2);
	tmp = AE_SLAI64S(tmp,1);
	return tmp;
}

static __inline long long DVTXOP_LL_shr(long long L_var1, short var2){return AE_SRAA64(L_var1, var2);}
static __inline long long DVTXOP_LL_negate(long long L_var1){return AE_NEG64S (L_var1);}
static __inline int DVTXOP_L_extract_h(long long L_var1){return  AE_TRUNCA32Q64( L_var1);}
static __inline long long DVTXOP_LL_deposit_h(int var1){return AE_SLAI64(var1, 32) ;};
static __inline int DVTXOP_L_round(long long L_var1)
{
	return AE_TRUNCA32Q64(AE_ADD64S(L_var1, (long long)0x0000000080000000LL));
}
#endif
#endif




#ifndef INLINE_BASIC_OPS
int DVTXOP_L_mpy_ls(int L_var2, short var1);
int	DVTXOP_L_mpy_ll(int L_var1, int L_var2);
#else
static __inline int DVTXOP_L_mpy_ls(int L_var2, short var1)
{
#if(FLAG_SELECT_C_DSP == 1)
	int L_varOut;
	short swtemp;

	//#define MULT16_32_Q15(a,b) ADD32(SHL(MULT16_16((a),SHR((b),16)),1), SHR(MULT16_16SU((a),((b)&0x0000ffff)),15))
	swtemp = DVTXOP_shr(DVTXOP_extract_l(L_var2), 1);
	swtemp = (short)32767 & (short)swtemp;

	L_varOut = DVTXOP_L_mult(var1, swtemp);
	L_varOut = DVTXOP_L_shr(L_varOut, 15);
	L_varOut = DVTXOP_L_mac(L_varOut, var1, DVTXOP_extract_h(L_var2));

	return (L_varOut);
#else
#ifndef OPT_DVTXOP_L_mpy_ls
	int L_varOut;
	short hi, lo;
	hi = AE_TRUNC16X4F32_scalar(L_var2);
	lo = (ae_int16)(ae_int32)AE_SRLI_32(AE_SLLI_32(L_var2, 16), 17);

	L_varOut = AE_MULF16X4SS_scalar(var1, lo);//DVTXOP_L_mult(var1, lo);
	L_varOut = AE_SRAA32S_scalar(L_varOut, 15);//DVTXOP_L_shr(L_varOut, 15);
	L_varOut = AE_MULAF16X4SS_scalar(L_varOut, var1, hi);//DVTXOP_L_mac(L_varOut, var1, hi);

	return L_varOut;
#else
	ae_int64 tmp;
	ae_int32x2 tmp32;
	int out;
//////////////////////////////////////////////////
	L_var2 = L_var2&0xfffffffe;
//////////////////////////////////////////////////
	tmp = AE_MUL32_LL(L_var2, var1);
	tmp = AE_SRAI64(tmp,15);
	tmp32 = AE_MOVF32X2_FROMF64(tmp);
	out = AE_MOVAD32_L(tmp32);
	return out;
#endif
#endif
}




/****************************************************************************
*
*     FUNCTION NAME: DVTXOP_L_mpy_ll
*
*     PURPOSE:    Multiply a 32 bit number (L_var1) and a 32 bit number
*                 (L_var2), and return a 32 bit result.
*
*     INPUTS:
*
*       L_var1             A int input variable
*
*       L_var2             A int input variable
*
*     OUTPUTS:             none
*
*     IMPLEMENTATION:
*
*        Performs a 31x31 bit multiply, Complexity=24 Ops.
*
*        Let x1x0, or y1y0, be the two constituent halves
*        of a 32 bit number.  This function performs the
*        following:
*
*        low = ((x0 >> 1)*(y0 >> 1)) >> 16     (low * low)
*        mid1 = [(x1 * (y0 >> 1)) >> 1 ]       (high * low)
*        mid2 = [(y1 * (x0 >> 1)) >> 1]        (high * low)
*        mid =  (mid1 + low + mid2) >> 14      (sum so far)
*        output = (y1*x1) + mid                (high * high)
*
*
*     RETURN VALUE:        A int value
*
*     KEYWORDS: DVTXOP_mult,mpy,multiplication
*
***************************************************************************/
static __inline int DVTXOP_L_mpy_ll(int L_var1, int L_var2)
{
#if(FLAG_SELECT_C_DSP == 1)
	short swLow1, swLow2, swHigh1, swHigh2;
	int L_varOut, L_low, L_mid1, L_mid2, L_mid;

	swLow1 = DVTXOP_shr(DVTXOP_extract_l(L_var1), 1);
	swLow1 = DVTX_MAX_16 & swLow1;

	swLow2 = DVTXOP_shr(DVTXOP_extract_l(L_var2), 1);
	swLow2 = DVTX_MAX_16 & swLow2;
	swHigh1 = DVTXOP_extract_h(L_var1);
	swHigh2 = DVTXOP_extract_h(L_var2);

	L_low = DVTXOP_L_mult(swLow1, swLow2);
	L_low = DVTXOP_L_shr(L_low, 16);

	L_mid1 = DVTXOP_L_mult(swHigh1, swLow2);
	L_mid1 = DVTXOP_L_shr(L_mid1, 1);
	L_mid = DVTXOP_L_add(L_mid1, L_low);

	L_mid2 = DVTXOP_L_mult(swHigh2, swLow1);
	L_mid2 = DVTXOP_L_shr(L_mid2, 1);
	L_mid = DVTXOP_L_add(L_mid, L_mid2);

	L_mid = DVTXOP_L_shr(L_mid, 14);
	L_varOut = DVTXOP_L_mac(L_mid, swHigh1, swHigh2);

	return (L_varOut);
#else

#ifndef OPT_DVTXOP_L_mpy_ll
	short swLow1, swLow2, swHigh1, swHigh2;
	int L_varOut, L_low, L_mid1, L_mid2, L_mid;
	swHigh1 = AE_TRUNC16X4F32_scalar(L_var1);
	swLow1 = (ae_int16)(ae_int32)AE_SRLI_32(AE_SLLI_32(L_var1, 16), 17);
	swHigh2 = AE_TRUNC16X4F32_scalar(L_var2);
	swLow2 = (ae_int16)(ae_int32)AE_SRLI_32(AE_SLLI_32(L_var2, 16), 17);
	L_low = AE_MULF16X4SS_scalar(swLow1, swLow2);
	L_low = AE_SRAA32S_scalar(L_low, 16);
	L_mid1 = AE_MULF16X4SS_scalar(swHigh1, swLow2);
	L_mid1 = AE_SRAA32S_scalar(L_mid1, 1);
	L_mid2 = AE_MULF16X4SS_scalar(swHigh2, swLow1);
	L_mid2 = AE_SRAA32S_scalar(L_mid2, 1);
	L_mid = AE_ADD32S_scalar(L_mid1, L_low);
	L_mid = AE_ADD32S_scalar(L_mid, L_mid2);
	L_mid = AE_SRAA32S_scalar(L_mid, 14);
	L_varOut = AE_MULAF16X4SS_scalar(L_mid, swHigh1, swHigh2);
	return (L_varOut);
#else
	ae_int64 tmp;
	ae_int32x2 tmp32;
	int out;
/////////////////////////////////////////
	L_var2 = L_var2&0xfffffffe;
	L_var1 = L_var1&0xfffffffe;
/////////////////////////////////////////
	tmp = AE_MUL32_LL(L_var1, L_var2);
	tmp = AE_SRAI64(tmp,31);
	tmp32 = AE_MOVF32X2_FROMF64(tmp);
	out = AE_MOVAD32_L(tmp32);
	return out;
#endif
#endif
}


static __inline int DVTXOP_L_divide(int L_num, int L_denom)
{
	short approx;
	int L_div;

	if (L_num < 0 || L_denom < 0 || L_num > L_denom)
	{
		return (0);
	}

	/* First approximation: 1 / L_denom = 1/DVTXOP_extract_h(L_denom) */
	approx = DVTXOP_div_s((short)0x3fff, DVTXOP_extract_h(L_denom));

	/* 1/L_denom = approx * (2.0 - L_denom * approx) */
	L_div = DVTXOP_L_mpy_ls(L_denom, approx);
	L_div = DVTXOP_L_sub((int)0x7fffffffL, L_div);
	L_div = DVTXOP_L_mpy_ls(L_div, approx);

	/* L_num * (1/L_denom) */
	L_div = DVTXOP_L_mpy_ll(L_num, L_div);
	L_div = DVTXOP_L_shl(L_div, 2);

	return (L_div);
}

#endif



short DVTXOP_block_norm(short * data, short size, short headroom);
#ifndef Right_Shift_vecter_OPT_DSP
void DVTXOP_block_denorm(short * data, short size, short scnt);
#endif
int	DVTXOP_L_divide(int L_num, int L_denom);
int	DVTXOP_fnLog10(int L_Input);
int DVTXOP_fnExp10(int L_Input);
int DVTXOP_fnExp2(int L_Input);
int DVTXOP_fnLog2(int L_Input);
#ifndef BASIC_LL_OPS
long long DVTXOP_LL_deposit_h(int var1);
long long DVTXOP_LL_add(long long L_var1, long long L_var2);
long long DVTXOP_LL_sub(long long L_var1, long long L_var2);
long long DVTXOP_LL_mult(int var1, int var2);
int DVTXOP_L_extract_h(long long L_var1);
int DVTXOP_L_round(long long L_var1);
long long DVTXOP_LL_negate(long long L_var1);
long long DVTXOP_LL_shr(long long L_var1, short var2);
#endif
int fx_SolomonVoice_32bit_Divide(int numerator, int denominator, short MIN_denominator, short Qbit);
short int_sqrt_0_50(int num);		//in: Q31, out:Q15
short int_sqrt_0_25(int num);		//in: Q31, out:Q15
short int_sqrt_0_75(int num);

int DVTXOP_Mpy_32_16(short hi, short lo, short n);
void DVTXOP_L_Extract(int L_32, short *hi, short *lo);

int divide(int var1_denorm, int q1, int var2_denorm, int q2, int dest_qForm);
int ilog2(unsigned int _v);
int sqrt32(int x);

int DVTXOP_10log10_l(int pwr, short pwr_q);

short DVTXOP_Log2(
	long L_x,         /* (i) : input value                                 */
	short *exponent,   /* (o) : Integer part of Log2.   (range: 0<=val<=30) */
	short *fraction    /* (o) : Fractional part of Log2. (range: 0<=val<1) */
);
#endif

