#ifdef _MSC_VER
#include "basic_op.h"
#elif defined __arm__
#include "platform.h"
#include "basic_op.h"
#else
#if defined(__hexagon__)
#include "amr_qdsp6_basic_op.h"
#else
#include "basic_op.h"
#endif
#endif

#include "fixlib.h"

//sqrt(x) table, which x should be the 0.25 to 1
static Word16 sqrt_from_05to1_table[769] = {
	0x4000, 0x4020, 0x4040, 0x4060, 0x4080, 0x409f, 0x40bf, 0x40de, 0x40fe, 0x411e, 0x413d, 0x415c, 0x417c, 0x419b, 0x41ba, 0x41d9,
	0x41f8, 0x4217, 0x4236, 0x4255, 0x4274, 0x4293, 0x42b1, 0x42d0, 0x42ef, 0x430d, 0x432c, 0x434a, 0x4369, 0x4387, 0x43a5, 0x43c4,
	0x43e2, 0x4400, 0x441e, 0x443c, 0x445a, 0x4478, 0x4496, 0x44b4, 0x44d2, 0x44ef, 0x450d, 0x452b, 0x4548, 0x4566, 0x4583, 0x45a1,
	0x45be, 0x45db, 0x45f9, 0x4616, 0x4633, 0x4650, 0x466d, 0x468a, 0x46a7, 0x46c4, 0x46e1, 0x46fe, 0x471b, 0x4738, 0x4755, 0x4771,
	0x478e, 0x47aa, 0x47c7, 0x47e4, 0x4800, 0x481c, 0x4839, 0x4855, 0x4871, 0x488e, 0x48aa, 0x48c6, 0x48e2, 0x48fe, 0x491a, 0x4936,
	0x4952, 0x496e, 0x498a, 0x49a6, 0x49c2, 0x49dd, 0x49f9, 0x4a15, 0x4a30, 0x4a4c, 0x4a68, 0x4a83, 0x4a9e, 0x4aba, 0x4ad5, 0x4af1,
	0x4b0c, 0x4b27, 0x4b42, 0x4b5e, 0x4b79, 0x4b94, 0x4baf, 0x4bca, 0x4be5, 0x4c00, 0x4c1b, 0x4c36, 0x4c51, 0x4c6b, 0x4c86, 0x4ca1,
	0x4cbc, 0x4cd6, 0x4cf1, 0x4d0c, 0x4d26, 0x4d41, 0x4d5b, 0x4d76, 0x4d90, 0x4daa, 0x4dc5, 0x4ddf, 0x4df9, 0x4e14, 0x4e2e, 0x4e48,
	0x4e62, 0x4e7c, 0x4e96, 0x4eb0, 0x4eca, 0x4ee4, 0x4efe, 0x4f18, 0x4f32, 0x4f4c, 0x4f66, 0x4f80, 0x4f99, 0x4fb3, 0x4fcd, 0x4fe6,
	0x5000, 0x501a, 0x5033, 0x504d, 0x5066, 0x5080, 0x5099, 0x50b2, 0x50cc, 0x50e5, 0x50fe, 0x5118, 0x5131, 0x514a, 0x5163, 0x517c,
	0x5196, 0x51af, 0x51c8, 0x51e1, 0x51fa, 0x5213, 0x522c, 0x5245, 0x525d, 0x5276, 0x528f, 0x52a8, 0x52c1, 0x52d9, 0x52f2, 0x530b,
	0x5323, 0x533c, 0x5355, 0x536d, 0x5386, 0x539e, 0x53b7, 0x53cf, 0x53e8, 0x5400, 0x5418, 0x5431, 0x5449, 0x5461, 0x547a, 0x5492,
	0x54aa, 0x54c2, 0x54da, 0x54f2, 0x550b, 0x5523, 0x553b, 0x5553, 0x556b, 0x5583, 0x559b, 0x55b2, 0x55ca, 0x55e2, 0x55fa, 0x5612,
	0x562a, 0x5641, 0x5659, 0x5671, 0x5689, 0x56a0, 0x56b8, 0x56cf, 0x56e7, 0x56ff, 0x5716, 0x572e, 0x5745, 0x575c, 0x5774, 0x578b,
	0x57a3, 0x57ba, 0x57d1, 0x57e9, 0x5800, 0x5817, 0x582e, 0x5846, 0x585d, 0x5874, 0x588b, 0x58a2, 0x58b9, 0x58d0, 0x58e8, 0x58ff,
	0x5916, 0x592d, 0x5943, 0x595a, 0x5971, 0x5988, 0x599f, 0x59b6, 0x59cd, 0x59e4, 0x59fa, 0x5a11, 0x5a28, 0x5a3e, 0x5a55, 0x5a6c,
	0x5a82, 0x5a99, 0x5ab0, 0x5ac6, 0x5add, 0x5af3, 0x5b0a, 0x5b20, 0x5b37, 0x5b4d, 0x5b64, 0x5b7a, 0x5b90, 0x5ba7, 0x5bbd, 0x5bd3,
	0x5bea, 0x5c00, 0x5c16, 0x5c2c, 0x5c43, 0x5c59, 0x5c6f, 0x5c85, 0x5c9b, 0x5cb1, 0x5cc8, 0x5cde, 0x5cf4, 0x5d0a, 0x5d20, 0x5d36,
	0x5d4c, 0x5d62, 0x5d77, 0x5d8d, 0x5da3, 0x5db9, 0x5dcf, 0x5de5, 0x5dfb, 0x5e10, 0x5e26, 0x5e3c, 0x5e52, 0x5e67, 0x5e7d, 0x5e93,
	0x5ea8, 0x5ebe, 0x5ed3, 0x5ee9, 0x5eff, 0x5f14, 0x5f2a, 0x5f3f, 0x5f55, 0x5f6a, 0x5f80, 0x5f95, 0x5fab, 0x5fc0, 0x5fd5, 0x5feb,
	0x6000, 0x6015, 0x602b, 0x6040, 0x6055, 0x606a, 0x6080, 0x6095, 0x60aa, 0x60bf, 0x60d4, 0x60ea, 0x60ff, 0x6114, 0x6129, 0x613e,
	0x6153, 0x6168, 0x617d, 0x6192, 0x61a7, 0x61bc, 0x61d1, 0x61e6, 0x61fb, 0x6210, 0x6225, 0x6239, 0x624e, 0x6263, 0x6278, 0x628d,
	0x62a1, 0x62b6, 0x62cb, 0x62e0, 0x62f4, 0x6309, 0x631e, 0x6332, 0x6347, 0x635c, 0x6370, 0x6385, 0x6399, 0x63ae, 0x63c2, 0x63d7,
	0x63ec, 0x6400, 0x6414, 0x6429, 0x643d, 0x6452, 0x6466, 0x647b, 0x648f, 0x64a3, 0x64b8, 0x64cc, 0x64e0, 0x64f5, 0x6509, 0x651d,
	0x6531, 0x6546, 0x655a, 0x656e, 0x6582, 0x6596, 0x65ab, 0x65bf, 0x65d3, 0x65e7, 0x65fb, 0x660f, 0x6623, 0x6637, 0x664b, 0x665f,
	0x6673, 0x6687, 0x669b, 0x66af, 0x66c3, 0x66d7, 0x66eb, 0x66ff, 0x6713, 0x6726, 0x673a, 0x674e, 0x6762, 0x6776, 0x678a, 0x679d,
	0x67b1, 0x67c5, 0x67d9, 0x67ec, 0x6800, 0x6814, 0x6827, 0x683b, 0x684f, 0x6862, 0x6876, 0x6889, 0x689d, 0x68b1, 0x68c4, 0x68d8,
	0x68eb, 0x68ff, 0x6912, 0x6926, 0x6939, 0x694d, 0x6960, 0x6974, 0x6987, 0x699a, 0x69ae, 0x69c1, 0x69d4, 0x69e8, 0x69fb, 0x6a0e,
	0x6a22, 0x6a35, 0x6a48, 0x6a5c, 0x6a6f, 0x6a82, 0x6a95, 0x6aa9, 0x6abc, 0x6acf, 0x6ae2, 0x6af5, 0x6b08, 0x6b1c, 0x6b2f, 0x6b42,
	0x6b55, 0x6b68, 0x6b7b, 0x6b8e, 0x6ba1, 0x6bb4, 0x6bc7, 0x6bda, 0x6bed, 0x6c00, 0x6c13, 0x6c26, 0x6c39, 0x6c4c, 0x6c5f, 0x6c72,
	0x6c84, 0x6c97, 0x6caa, 0x6cbd, 0x6cd0, 0x6ce3, 0x6cf5, 0x6d08, 0x6d1b, 0x6d2e, 0x6d41, 0x6d53, 0x6d66, 0x6d79, 0x6d8b, 0x6d9e,
	0x6db1, 0x6dc3, 0x6dd6, 0x6de9, 0x6dfb, 0x6e0e, 0x6e21, 0x6e33, 0x6e46, 0x6e58, 0x6e6b, 0x6e7d, 0x6e90, 0x6ea2, 0x6eb5, 0x6ec7,
	0x6eda, 0x6eec, 0x6eff, 0x6f11, 0x6f24, 0x6f36, 0x6f49, 0x6f5b, 0x6f6d, 0x6f80, 0x6f92, 0x6fa4, 0x6fb7, 0x6fc9, 0x6fdb, 0x6fee,
	0x7000, 0x7012, 0x7025, 0x7037, 0x7049, 0x705b, 0x706e, 0x7080, 0x7092, 0x70a4, 0x70b6, 0x70c8, 0x70db, 0x70ed, 0x70ff, 0x7111,
	0x7123, 0x7135, 0x7147, 0x7159, 0x716b, 0x717d, 0x7190, 0x71a2, 0x71b4, 0x71c6, 0x71d8, 0x71ea, 0x71fc, 0x720d, 0x721f, 0x7231,
	0x7243, 0x7255, 0x7267, 0x7279, 0x728b, 0x729d, 0x72af, 0x72c0, 0x72d2, 0x72e4, 0x72f6, 0x7308, 0x731a, 0x732b, 0x733d, 0x734f,
	0x7361, 0x7372, 0x7384, 0x7396, 0x73a8, 0x73b9, 0x73cb, 0x73dd, 0x73ee, 0x7400, 0x7412, 0x7423, 0x7435, 0x7447, 0x7458, 0x746a,
	0x747b, 0x748d, 0x749e, 0x74b0, 0x74c2, 0x74d3, 0x74e5, 0x74f6, 0x7508, 0x7519, 0x752b, 0x753c, 0x754e, 0x755f, 0x7570, 0x7582,
	0x7593, 0x75a5, 0x75b6, 0x75c8, 0x75d9, 0x75ea, 0x75fc, 0x760d, 0x761e, 0x7630, 0x7641, 0x7652, 0x7664, 0x7675, 0x7686, 0x7697,
	0x76a9, 0x76ba, 0x76cb, 0x76dc, 0x76ee, 0x76ff, 0x7710, 0x7721, 0x7733, 0x7744, 0x7755, 0x7766, 0x7777, 0x7788, 0x7799, 0x77ab,
	0x77bc, 0x77cd, 0x77de, 0x77ef, 0x7800, 0x7811, 0x7822, 0x7833, 0x7844, 0x7855, 0x7866, 0x7877, 0x7888, 0x7899, 0x78aa, 0x78bb,
	0x78cc, 0x78dd, 0x78ee, 0x78ff, 0x7910, 0x7921, 0x7932, 0x7943, 0x7953, 0x7964, 0x7975, 0x7986, 0x7997, 0x79a8, 0x79b9, 0x79c9,
	0x79da, 0x79eb, 0x79fc, 0x7a0d, 0x7a1d, 0x7a2e, 0x7a3f, 0x7a50, 0x7a60, 0x7a71, 0x7a82, 0x7a93, 0x7aa3, 0x7ab4, 0x7ac5, 0x7ad5,
	0x7ae6, 0x7af7, 0x7b07, 0x7b18, 0x7b29, 0x7b39, 0x7b4a, 0x7b5a, 0x7b6b, 0x7b7c, 0x7b8c, 0x7b9d, 0x7bad, 0x7bbe, 0x7bce, 0x7bdf,
	0x7bef, 0x7c00, 0x7c11, 0x7c21, 0x7c32, 0x7c42, 0x7c52, 0x7c63, 0x7c73, 0x7c84, 0x7c94, 0x7ca5, 0x7cb5, 0x7cc6, 0x7cd6, 0x7ce6,
	0x7cf7, 0x7d07, 0x7d18, 0x7d28, 0x7d38, 0x7d49, 0x7d59, 0x7d69, 0x7d7a, 0x7d8a, 0x7d9a, 0x7dab, 0x7dbb, 0x7dcb, 0x7ddb, 0x7dec,
	0x7dfc, 0x7e0c, 0x7e1c, 0x7e2d, 0x7e3d, 0x7e4d, 0x7e5d, 0x7e6e, 0x7e7e, 0x7e8e, 0x7e9e, 0x7eae, 0x7ebe, 0x7ecf, 0x7edf, 0x7eef,
	0x7eff, 0x7f0f, 0x7f1f, 0x7f2f, 0x7f3f, 0x7f50, 0x7f60, 0x7f70, 0x7f80, 0x7f90, 0x7fa0, 0x7fb0, 0x7fc0, 0x7fd0, 0x7fe0, 0x7ff0,
	0x7fff,
};

/**
No matter in Fixed-point DSP or Float point DSP, the mutiply or divide operation between a float value and a integer value
which is the exponent of 2(2^x) must excute very quickly because the float bits mode.
*/
inline Word16 fl2Fixed_f(double value, U_Word32 qForm)
{
    double a = value * (1U<<qForm);
    if((Word32)a > MAX_16)
    {
        return MAX_16;
    }else if((Word32)a < MIN_16)
    {
        return MIN_16;
    }
    else
    {
        return (Word16)a;
    }
}

inline float Fixed2fp_f(Word16 fx_v, U_Word32 qForm)
{
    return (float)fx_v/(1U<<qForm);
}

inline Word32 fp2Fixed32_f(double value, U_Word32 qForm)
{
   double a = value * (1U<<qForm);
   if((Word64)a > MAX_32)
    {
        return MAX_32;
    }
    else if((Word64)a < MIN_32)
    {
        return MIN_32;
    }
    else
    {
        return (Word32)a;
    }
}

inline float Fixed32_2_fp_f(Word32 fx_v, U_Word32 qForm)
{
    return (float)fx_v/(1U<<qForm);
}

inline Word32 int2Fixed32_f(int value, U_Word32 qForm)
{
    return value * (1U<<qForm);
}

inline Word16 int2Fixed_f(int value, U_Word32 qForm)
{
	Word32 ret = value * (1U << qForm);
	if(ret > MAX_16)
	{
		return MAX_16;
	}
	else if(ret < MIN_16)
	{
		return MIN_16;
	}
	
    return (Word16)ret;
}




inline Word32 Fixed2Fixed_f(Word32 value, U_Word32 valueQForm, U_Word32 targetQForm)
{
    /**
    Both VC and GCC use Arimetic Right-shift and Logistic Left-shift.
    To avoid the sign bit is shift out, we use Word64 to protect sign bit
    */
    Word64 ret = value;
    if(valueQForm < targetQForm)
    {
        ret = ret << (targetQForm - valueQForm);
        if(ret > MAX_32)
        {
            ret = MAX_32;
        }
        else if(ret < MIN_32)
        {
            ret = MIN_32;
        }
    }
    else
    {        
        ret = ret >> (valueQForm - targetQForm);
    }

    return (Word32)ret;
}

inline Word16 F32_2_F16_f(Word32 value, U_Word32 valueQForm, U_Word32 targetQForm)
{
    Word32 ret = 0;
    if(valueQForm > targetQForm)
    {
        ret = value >> (valueQForm - targetQForm);
    }
    else
    {
        ret = value << (targetQForm - valueQForm);
        //both vc and gcc are logistic-left-shift.To avoid signbit is shifted out, set signbit after shift.
        ret |= value & (1 << 31);
    }

    if(ret > MAX_16)
    {
        ret = MAX_16;
    }
    else if(ret < MIN_16)
    {
        ret = MIN_16;
    }

    return (Word16)ret;
}

inline Word32 F16_2_F32_f(Word16 value, U_Word32 valueQForm, U_Word32 targetQForm)
{
    Word32 ret = 0;
    if(valueQForm > targetQForm)
    {
        ret = value >> (valueQForm - targetQForm);
    }
    else
    {
        ret = ((Word32)value) << (targetQForm - valueQForm);
        //both vc and gcc are logistic-left-shift.To avoid signbit is shifted out, set signbit after shift.
        ret |= value & (1 << 31);
    }

    return ret;
}

// KHQ: need to use intrinsic function (L_mpy_ll, L_shr, L_shl)
inline Word32 multiply(Word32 var1, U_Word32 var1_qForm, Word32 var2, U_Word32 var2_qForm, U_Word32 dest_qForm)
{

    Word64 ret;

    ret = L_mpy_ll_l(var1, var2);
    ret = L_shr_ll_l(ret, var1_qForm + var2_qForm - dest_qForm);
    return L_saturate(ret);

}

Word16 divide_ss(Word16 var1_denorm, Word16 q1, Word16 var2_denorm, Word16 q2, Word16 dest_qForm)
{
	int signbit = 0;
	Word16 var1 = var1_denorm;
	Word16 var2 = var2_denorm;
	Word16 ret = 0;
	Word16 n1;
	Word16 n2;

	if (var1_denorm < 0) {

		var1 = negate(var1_denorm);
		signbit = !signbit;
	}

	if (var2_denorm < 0) {
		var2 = negate(var2_denorm);
		signbit = !signbit;
	}

	if (var1_denorm == 0) {
		return 0;
	}

	if (var2_denorm == 0) {
		//divide by 0, undefined, just return var1_denorm
		return var1_denorm;
	}

	n1 = norm_s(var1);
	n2 = norm_s(var2);
	//adjust var1 to 0x2000 to 0x3fff, adjust var2 to 0x4000 to 0x7fff
	if (n1 == 0) {
		var1 = var1 >> 1;
	}
	else {
		var1 = var1 << (n1 - 1);
	}
	var2 = var2 << n2;

	ret = div_s(var1, var2);

	ret = shl(ret, (dest_qForm - (15 + q1 + n1 - 1 - q2 - n2)));

	if (signbit) {
		ret = negate(ret);
	}

	return ret;
}

//calculate var1_denorm/var2_denorm, the result is a dest_qForm fraction
Word32 divide(Word32 var1_denorm, Word32 q1, Word32 var2_denorm, Word32 q2, Word32 dest_qForm)
{
	int signbit = 0;
	Word32 var1 = var1_denorm;
	Word32 var2 = var2_denorm;
	Word32 ret = 0;
	Word16 n1;
	Word16 n2;

	//if (var1_denorm == (Word32)0x80000000)
	//	var1_denorm += 1;
	//if (var2_denorm == (Word32)0x80000000)
	//	var2_denorm += 1;

	if (var1_denorm < 0) {

		var1 = L_negate(var1_denorm);
		signbit = !signbit;
	}

	if (var2_denorm < 0) {
		var2 = L_negate(var2_denorm);
		signbit = !signbit;
	}

	if (var1_denorm == 0) {
		return 0;
	}

	if (var2_denorm == 0) {
		//divide by 0, undefined, just return var1_denorm
		return var1_denorm;
	}

	n1 = norm_l(var1);
	n2 = norm_l(var2);
	//adjust var1 to 0x20000000 to 0x3fffffff, adjust var2 to 0x40000000 to 0x7fffffff
	if (n1 == 0) {
		var1 = var1 >> 1;
	}
	else {
		var1 = var1 << (n1 - 1);
	}
	var2 = var2 << n2;

	ret = L_divide(var1, var2);
	//ret = Fixed2Fixed_f(div_ret, 31 + q1 + n1 - 1 - q2 - n2, dest_qForm);

	ret = L_shl(ret, (Word16)(dest_qForm - (31 + q1 + n1 - 1 - q2 - n2)));

	if (signbit) {
		ret = L_negate(ret);
	}

	return ret;
}


Word16 fn_recursive_avg_s(Word16 x, Word16 beta, Word16 y, Word16 beta_1)
{
	Word16 tmp1;
	Word32 Ltmp1, Ltmp2, Ltmp5;

	Ltmp1 = L_mult(x, beta);
	Ltmp2 = L_mult(y, beta_1);
	Ltmp5 = L_add(Ltmp1, Ltmp2);

	tmp1 = extract_h(Ltmp5);

	return tmp1;
}

Word16 table_pow2_dnn[129] =
{
	16384,  16473,  16562,  16652,  16743,  16834,  16925,  17017,  17109,  17202,
	17296,  17390,  17484,  17579,  17674,  17770,  17867,  17964,  18061,  18160,
	18258,  18357,  18457,  18557,  18658,  18759,  18861,  18963,  19066,  19170,
	19274,  19379,  19484,  19590,  19696,  19803,  19911,  20019,  20127,  20237,
	20347,  20457,  20568,  20680,  20792,  20905,  21019,  21133,  21247,  21363,
	21479,  21595,  21713,  21831,  21949,  22068,  22188,  22309,  22430,  22552,
	22674,  22797,  22921,  23045,  23170,  23296,  23423,  23550,  23678,  23806,
	23936,  24066,  24196,  24328,  24460,  24593,  24726,  24860,  24995,  25131,
	25268,  25405,  25543,  25681,  25821,  25961,  26102,  26244,  26386,  26530,
	26674,  26818,  26964,  27110,  27258,  27406,  27554,  27704,  27855,  28006,
	28158,  28311,  28464,  28619,  28774,  28931,  29088,  29246,  29405,  29564,
	29725,  29886,  30048,  30212,  30376,  30541,  30706,  30873,  31041,  31209,
	31379,  31549,  31720,  31893,  32066,  32240,  32415,  32591,  32767
};
Word32 SRCB_Pow2(                               /* (o) Q0  : result       (range: 0<=val<=0x7fffffff) */
	Word16 exponant,                      /* (i) Q0  : Integer part.      (range: 0<=val<=30)   */
	Word16 fraction                       /* (i) Q15 : Fractionnal part.  (range: 0.0<=val<1.0) */
)
{
	Word16 exp, i, a, tmp;
	Word32 L_x;

	L_x = L_mult(fraction, 128);            /* L_x = fraction<<6           */
	i = extract_h(L_x);                    /* Extract b10-b16 of fraction */
	L_x = L_shr(L_x, 1);
	a = extract_l(L_x);                    /* Extract b0-b9   of fraction */
	a = (Word16)(a & (Word16)0x7fff);

	L_x = L_deposit_h(table_pow2_dnn[i]);      /* table[i] << 16        */
	tmp = sub(table_pow2_dnn[i], table_pow2_dnn[i + 1]);        /* table[i] - table[i+1] */
	L_x = L_msu(L_x, tmp, a);              /* L_x -= tmp*a*2        */            //Q30

	exp = sub(30, exponant);
	L_x = L_shr_r(L_x, exp);

	return (L_x);
}

Word32 Pow_E(                  //¢®¢´¡ËOI¢®¡¿I¡§¡Ìin<=90852,inE¡Íi¡§uEO¡Íi¡§¡Ë¡Ë¢çOU¡ÍiEOU21
	Word32 in,				//Ea¨Ï©ªo¢®I¡§¡þQ0
	Word16 Q_in
)
{
	Word16 exponant, fraction;
	Word16 tmp1 = 23637;// 1/log(2),1.44269502 , Q14
	Word16 Q_tmp;
	Word32 tmp2;
	Word32 result;
	Q_tmp = Q_in + 14;
	tmp2 = L_mult_ls(in, tmp1); //Q: Q_tmp
	exponant = extract_l(tmp2 >> Q_tmp);
	fraction = L_shr(tmp2, (Q_in - 1)) & 32767;
	result = SRCB_Pow2(exponant, fraction);
	return(result);
}


inline Word64 divide_ll(Word64 x1, Word16 q_x1, Word64 x2, Word16 q_x2, Word16 q_out)
{
	short q_diff;

	short shift_x1, shift_x2;
	short shift_x1_final, shift_x2_final;

	int signbit = 0;

	Word64 x1_final, x2_final, out_val;

	if (x2 == 0) {
		//fprintf(stderr, "oppps, divide_ll_v1 dividor is zero\n");
		return x1;
	}

	if (x1 == 0) {
		return 0;
	}

	if (x1 < 0) {
		x1 = LL_negate(x1);
		signbit = (int)(!signbit);
	}
	if (x2 < 0) {
		x2 = LL_negate(x2);
		signbit = (int)(!signbit);
	}

	q_diff = q_x1 - q_x2;

	shift_x1 = norm_ll(x1);
	shift_x2 = norm_ll(x2);


	if ((q_diff + shift_x1) >= q_out)
	{
		shift_x1_final = q_out - q_diff;
		shift_x2_final = 0;
	}
	else
	{
		shift_x1_final = shift_x1;
		shift_x2_final = (q_out - q_diff - shift_x1);
	}

	x1_final = L_shl_ll_l(x1, shift_x1_final);
	x2_final = x2;//L_shr_ll_l(x2,shift_x2_final);

	out_val = x1_final / x2_final;
	out_val = L_shl_ll_l(out_val, shift_x2_final);

	if (signbit) {
		out_val = LL_negate(out_val);
	}

	return out_val;
}


// in must be non-negative (0 ~ 0x7fffffff)
Word32 SamsungTxECNS_GEVD_sqrt(Word64 in, int in_Q, int out_Q)
{
	
	Word32 ret = 0;
	Word16 in_norm;
	Word16 adjust_Q;
	Word16 queryValue_1, queryValue_2, table_index;
	Word32 ret1;
	Word32 middle_index;
	Word64 pow2_middle, pow2_ret1;
	int msb_index;
	int iter_num;

	if (in == 0) {
		return 0;
	}
	else
	{
		//the index of the most significant bit index of in
		msb_index = 63 - norm_ll(in);

		//step 1: normalized the input value to Q15 of int16;
		if (msb_index > 15) {
			//from Q -> Q - (msb_index - 15)
			in_norm = saturate(L_extract_l(L_shr_ll_l(in, msb_index - 15)));
		}
		else {
			in_norm = saturate(L_extract_l(L_shl_ll_l(in, 15 - msb_index)));
		}

		//step 2: keep the adjust_Q have an odd value
		adjust_Q = in_Q - msb_index + 15;
		if (!(adjust_Q & 1)) {//we must keep adjust_Q is odd
			in_norm = shr(in_norm, 1);
			adjust_Q -= 1;
		}

		//step 3: query the constant table(or the precission is too low)
		table_index = shr(sub(in_norm, 0x2000), 5);
		queryValue_1 = sqrt_from_05to1_table[table_index];//real Q value is (15 + adjust_Q)/2
		queryValue_2 = sqrt_from_05to1_table[table_index + 1];
		ret = L_shr((Word32)queryValue_1, (15 + adjust_Q) / 2 - out_Q);

		//step 4: linear interpolation
		//Word16 queryV_loc = add(shl(table_index, 5), 0x2000);
		//Word16 queryV_distance = sub(in_norm, queryV_loc);
		//Word32 queryV_diff = L_shl((Word32)sub(queryValue_2, queryValue_1), 16);//Q31
		//Word32 Value_adjust = L_shr(L_mpy_ls(queryV_diff, queryV_distance), 5);//Q31
		//Value_adjust = L_shr(Value_adjust, 31 - Q);//Q	
		//ret = L_add(ret, Value_adjust);

		//step 5: binary chop
		ret1 = L_shr((Word32)queryValue_2, (15 + adjust_Q) / 2 - out_Q);
		iter_num = 0;
		while (L_sub(ret1, ret) > 2 && iter_num < 10)
		{
			++iter_num;
			//middle_index = L_shr(L_add(ret, ret1), 1);
			middle_index = L_add(L_shr(ret1, 1), L_shr(ret, 1));
			pow2_middle = L_mpy_ll_l(middle_index, middle_index);
			pow2_ret1 = L_mpy_ll_l(ret1, ret1);
			if (pow2_middle < pow2_ret1) {
				ret = middle_index;
			}
			else {
				ret1 = middle_index;
			}
		}

		return ret;
	}
}

Word32 div_alt(Word32 var1_denorm, Word16 q1, Word32 var2_denorm, Word16 q2, Word16 dest_qForm)
{
	Word16 power_2, norm_shift1, shift1, flag_t2;
	Word32 Ltmp1, L_var_out;

	norm_shift1 = norm_l(var2_denorm);

	Ltmp1 = L_shl(var2_denorm, norm_shift1);
	Ltmp1 = Ltmp1 & 0x20000000;
	if (Ltmp1 == 0)
	{
		flag_t2 = 0;
		power_2 = 31 - norm_shift1 - 1;
	}
	else
	{
		flag_t2 = 1;
		power_2 = 31 - norm_shift1;
	}

	shift1 = dest_qForm - (q1 - q2) - power_2;

	L_var_out = L_shl(var1_denorm, shift1);

	return L_var_out;

}
