/* 
   Operace v pevne radove carce
   
   9.10.2005
*/


#include "fixed.h"

long prevod(double x, unsigned int posun);
// prevod "x" do systemu "Qposun"
double zprevod(long x, unsigned int posun);
// prevod "x" ze systemu "Qposun" do DOUBLE
long nasob(int x, int y,unsigned int posun);
// (x*y)>>posun
int deleni15(int x, int y);
// (x*Q15/y) se saturaci
int deleni(int x, int y, int posun1, int posun2, int scale, int posun_fin);
// obecne deleni: x_"Qposun1"*"Qscale"/y_"Qposun2" -> "Q_posun_fin"

  
long prevod(double x, unsigned int posun)
{
  long y,nasobic;
  int znamenko;
  
  nasobic=(long)1<<posun;
  if (x>=0) znamenko=1;
  else znamenko=-1;
  y=(long)(x*nasobic+znamenko*0.5);
  
  return y;
}

double zprevod(long x, unsigned int posun)
{
  long nasobic;
  double y;
  
  nasobic=(long)1<<posun;
  y=(double)x/nasobic;
  
  return y;
}

long nasob(int x, int y,unsigned int posun)
{
  long z,zaokrouhl;			// zaokrouhl ... zaokrouhlovani vysledku pricteni 0.5
  int znamenko;
  
  if (posun>0)
    zaokrouhl=(long)1<<(posun-1);
  else zaokrouhl=0;
  z=(long)x*y;
  if (z>=0) znamenko=1;
  else znamenko=-1;
  z=(z+znamenko*zaokrouhl)>>posun;
  
  return z;
}

int deleni15(int x, int y)   // deleni Q15/Q15 se saturaci
{
  long z;
    
  z=(long)x*32768/y;
  if (z>32767) z=32767;
  if (z<-32768) z=-32768;  
  
  return (int)z;
}

int deleni(int x, int y, int posun1, int posun2, int scale, int posun_fin)  
/*
x/y    ... podil
posun1 ... posun x (scale faktor)
posun2 ... posun y
scale  ... posun pri deleni - pomocny
posun_fin ... system, ve kterem ma byt vysledek (scale faktor vysledku)
*/
{
  int z;
  int bit_posun;
  long zz, scale_fakt, scale_fin;
  
  scale_fakt=(long)1<<scale;
  bit_posun=(posun1+scale-posun2)-posun_fin;
  
  zz=(long)x*scale_fakt/y;

  if (bit_posun>=0)
    zz=(int)(zz>>bit_posun);
  else
  { bit_posun*=-1;
    zz=(int)(zz<<bit_posun);
  }
  
  // Saturace vystupu
  if (zz>32767)
    z=32767;
  else if (zz<-32768)
    z=-32768;
  else
    z=zz;
  
  return z;
}