
#ifndef BASIC_OP_H
#define BASIC_OP_H


#include "config.h"


#define NULL 0

#define DB_SHIFT 10
#define EPSILON 1
#define VERY_SMALL 0
#define VERY_LARGE16 ((short)32767)
#define Q15_ONE (32767)

#ifndef HW_HIFI3
#define ABS(x) ((x) < 0 ? (-(x)) : (x))      /**< Absolute integer value. */
#else
#define ABS(x) (XT_ABS(x))
//#define ABS(x) ((int)(AE_ABS32S_scalar(x)))
//#define ABS(x) ((short)(AE_ABS16S_scalar(x)))
#endif

#ifndef HW_HIFI3
#define SPEECH_MIN(a,b) ((a) < (b) ? (a) : (b))   /**< Minimum 16-bit value.   */
#define SPEECH_MAX(a,b) ((a) > (b) ? (a) : (b))   /**< Maximum 16-bit value.   */
#else
#define SPEECH_MIN(a,b) (XT_MIN(a,b))   /**< Minimum 16-bit value.   */
#define SPEECH_MAX(a,b) (XT_MAX(a,b))   /**< Maximum 16-bit value.   */
//#define SPEECH_MIN(a,b) ((int)(AE_MIN32(a,b)))   /**< Minimum 16-bit value.   */
//#define SPEECH_MAX(a,b) ((int)(AE_MAX32(a,b)))   /**< Maximum 16-bit value.   */
#endif

#ifndef HW_HIFI3
#define SSC_MUL(a,b) ((a)*(b))
#else
#define SSC_MUL(a,b) ((int)((long long)(AE_MUL32_HH(a, b))))
#endif


#ifdef HW_HIFI3
#define FFT_MUL_16_32(a,b) ((int)((long long)(AE_MUL32X16_H0(b, a))))
#endif


#define EXTRACT16(x) ((short)(x))
#define EXTEND32(x) ((int)(x))

/** "RAW" macros, should not be used outside of this header file */


//#ifndef HW_HIFI3x


#define SHR(a,shift) ((a) >> (shift))
#define SHL(a,shift) ((a) << (shift))

//

//#define FFT_SHRI(a,shift) ((int)((long long)ae_int64 AE_INT64_SRAI(a,shift))
//#else
//#define SHR(a,shift) (XT_SRAI(a, shift))
//#define SHL(a,shift) (XT_SLLI(a, shift))



#ifndef HW_HIFI3x
#define SSC_PSHR(a,shift) (SHR((a)+((EXTEND32(1)<<((shift))>>1)),shift))
#else
#define SSC_PSHR(a,shift) (SHR((a)+(((1<<(shift-1)))),shift))
#endif


#ifndef HW_HIFI3
#define SSC_VSHR(a, shift) (((shift)>0) ? SHR(a, shift) : SHL(a, -(shift)))
#else
#define SSC_VSHR(a, shift) ((int)(AE_INT32_SLA(a,-(shift))))
//AE_INT32_SLA
#endif


/** Shift by a and round-to-neareast 32-bit value. Result is a 16-bit value */
#define ROUND16(x,a) (EXTRACT16(SSC_PSHR((x),(a))))

#ifndef HW_HIFI3
#define HALF(x)  (SHR(x,1))
#else
#define  HALF(x) (XT_SRAI(x, 1))
#endif
/** Add two intager values */

#ifndef HW_HIFI3
#define SSC_ADD(a,b) ((a)+(b))
#define SSC_SUB(a,b) ((a)-(b))
#else
#define SSC_ADD(a,b) (XT_ADD(a,b))
#define SSC_SUB(a,b) (XT_SUB(a,b))
#endif



/** 16x16 multiplication where the result fits in 16 bits */

#ifndef HW_HIFI3
#define SSC_MULT16x16(a,b) ((a)*(b))
#else
#define SSC_MULT16x16(a,b) ((int)(AE_MUL16S(a, b)))
#endif

#define SSC_MULT16x16_Q15(a,b) (SHR(SSC_MULT16x16((a),(b)),15))
#define SSC_MULT16x16_P15(a,b) (SHR(SSC_ADD(16384,SSC_MULT16x16((a),(b))),15))

//#define F_MULT16_32_Q15(a,b) SSC_ADD(SHL(SSC_MULT16x16((a),SHR((b) ,16)),1), SHR(SSC_MULT16x16((a),((b)&0x0000ffff)),15))
//#define F_MULT16_32_Q15(a,b) SSC_ADD(SHL(SSC_MULT16x16((a),SHR((b) ,16)),1), SHR(SSC_MULT16x16((a),((b)&0x0000ffff)),15))




#ifndef HW_HIFI3
#define SSC_MULT16x16SU(a,b) ((int)(short)(a)*(int)(unsigned short)(b))
#else
#define SSC_MULT16x16SU(a,b) ((int)((long long)(AE_MUL32X16_H0(b,a))))
//#define SSC_MUL(a,b) ((int)((long long)(AE_MUL32_HH(a, b))))
#endif


#define SSC_MULT16x32_Q16(a,b) SSC_ADD(SSC_MULT16x16((a),SHR((b),16)), SHR(SSC_MULT16x16SU((a),((b)&0x0000ffff)),16))
//#define SSC_MULT16x32_Q15(a,b) SSC_ADD(SHL(SSC_MULT16x16((a),SHR((b),16)),1), SHR(SSC_MULT16x16SU((a),((b)&0x0000ffff)),15))

#ifndef OPT_KHW_BASIC_OP
#ifndef Basicop_opt_hifi3_ZH_BX
#define SSC_MULT16x32_Q15(a,b) SSC_ADD(SHL(SSC_MULT16x16((a),SHR((b),16)),1), SHR(SSC_MULT16x16SU((a),((b)&0x0000ffff)),15))
#else
#define SSC_MULT16x32_Q15(a,b) ((int)(((long long)(AE_MUL32_HH(a, b))>>15)))
#endif
//#define SSC_MULT16x32_Q15(a,b) (( ((long long)a)*b   )>>15)
/*
16-bit by 32-bit signed multiply returning 32-most-significant-bits, top SMULWT 1 
*/
#else

#define SSC_MULT16x32_Q15 MULT16_32_Q15_asm

int MULT16_32_Q15_asm(short a, int b);


#ifndef HW_FOR_GCC
int MULT16_32_Q15_asm_ver2(short a, int b);
#endif

#endif


#define SRAImmediate(x,a) (XT_SRAI(x,a))



//////////// BitÀÌ ¾à°£ Æ²¾îÁú¼öµµ ÀÖÁö¸¸ Å« »ó°ü¾øÀ»°ÍÀ¸·Î ¿¹»ó //////////////////
#ifndef Basicop_BX1
#define SSC_MULT32x32_Q31(a,b) SSC_ADD(SSC_ADD(SHL(SSC_MULT16x16(SHR((a),16),SHR((b),16)),1), SHR(SSC_MULT16x16SU(SHR((a),16),((b)&0x0000ffff)),15)), SHR(SSC_MULT16x16SU(SHR((b),16),((a)&0x0000ffff)),15))
#else
#define SSC_MULT32x32_Q31(a,b) ((int)(((long long)(AE_MUL32_HH(a, b))>>31)))
#endif
//#define SSC_MULT32x32_Q31(a,b) ((int)(((long long)(AE_MUL32_HH(a, b))>>31)))
///////////////////////////////////////////////////////////////////////////////////////

// for Kalimba
//#define SSC_MULT32x32_Q31(a,b) SSC_ADD(SHR(SSC_MULT16x16((long long)a,SHR((b),16)),15) , SHR(SSC_MULT16x16SU(SHR((a),16),((b)&0x0000ffff)),15) )
// for test
//#define SSC_MULT32x32_Q31(a,b) (((long long)a*b)>>31)





//#define S_MUL(a,b) F_MULT16_32_Q15(b, a)
#define S_MUL(a,b) SSC_MULT16x32_Q15(b, a)


#ifndef HW_HIFI3
#define HALF_OF(x) ((x)>>1)
#else
#define  HALF_OF(x) (XT_SRAI(x, 1))
#endif




#ifndef HW_HIFI3
static int ec_ilog(unsigned int _v)
{
  int ret, m;
 

  ret=!!_v;
  m=!!(_v&0xFFFF0000)<<4;
  _v>>=m;
  ret|=m;
  m=!!(_v&0xFF00)<<3;
  _v>>=m;
  ret|=m;
  m=!!(_v&0xF0)<<2;
  _v>>=m;
  ret|=m;
  m=!!(_v&0xC)<<1;
  _v>>=m;
  ret|=m;
  ret+=!!(_v&0x2);
  return ret;
}

#define EC_ILOG(_x) (ec_ilog(_x))
#else
#define EC_ILOG(_x) (31-AE_NSAZ32_L(_x))
#endif
#endif
