Source: data-flow/include/fmath.h
|
|
|
|
// Copyright (C) 2001 Jean-Marc Valin
/* WARNING: These routines are mostly untested, and I don't know
for sure how fast and how accurate they are. Use at your own risks
*/
#ifndef FMATH_H
#define FMATH_H
#include <math.h>
#ifdef HAVE_FLOAT_H
#include <float.h>
#endif
#ifdef WIN32 /*Work around bug in MSVC++ (for) variable scope*/
#define for if(0);else for
#endif
union FloatManip {
float f;
unsigned int i;
};
#ifndef M_LN2
#define M_LN2 0.69314718055994530942
#endif
/*#define FLOGLOOKUP2SIZE 8192
#define FLOGLOOKUP2SHIFT 10
*/
#define FLOGLOOKUP2SIZE 256
#define FLOGLOOKUP2SHIFT 15
/*
#define FLOGLOOKUP2SIZE 8388608
#define FLOGLOOKUP2SHIFT 0
*/
extern float logtable2[FLOGLOOKUP2SIZE];
inline void build_flog_table()
{
static bool init=false;
if (!init)
{
FloatManip m;
for (int i=0;i<FLOGLOOKUP2SIZE;i++)
{
m.i = (i<<FLOGLOOKUP2SHIFT) | 0x3f800000;
logtable2[i]=log(m.f);
}
init=true;
}
}
//Log (base e) approximation
inline float flog(float f)
{
build_flog_table();
FloatManip m;
m.f = f;
//The exponent in id1
unsigned int id1 = m.i>>23;
//The first bits of the mantissa in id2
unsigned int id2 = (m.i & 0x007fffff)>>FLOGLOOKUP2SHIFT;
float f2=m.f;
//Refining step: first order taylor
m.i &= 0xffff8000;
return (int(id1)-127)*M_LN2 + logtable2[id2] + (f2-m.f)/f2;
}
//Log (base e) rough approximation
inline void fflogv(const float *fin, float *fout, int len)
{
build_flog_table();
FloatManip m;
for (int i=0;i<len;i++)
{
m.f = fin[i];
//Extract the mantissa and perform lookup for log(mantissa)
float tb = logtable2[(m.i & 0x007fffff)>>FLOGLOOKUP2SHIFT];
//Extract the exponent
int id = (m.i>>23)-127;
//log(mantissa*2^exponent) = exponent*log(2) + log(mantissa)
fout[i] = id*M_LN2 + tb;
}
}
/*#define FEXPSHIFT 19
#define FEXPSIZE 8192
#define FEXPMASK 0xfff80000
*/
#define FEXPSHIFT 22
#define FEXPSIZE 1024
#define FEXPMASK 0xffc00000
extern float exptable[FEXPSIZE];
inline void build_fexp_table()
{
static bool init=false;
if (!init)
{
FloatManip m;
for (int i=0;i<FEXPSIZE;i++)
{
m.i = i<<FEXPSHIFT;
exptable[i]=exp(m.f);
}
init=true;
}
}
//Exponential approximation
inline float fexp(float f)
{
build_fexp_table();
FloatManip m;
m.f = f;
//Exponent plus part of the mantissa for first approximation
unsigned int id = m.i>>FEXPSHIFT;
float val = exptable[id];
float f2;
//Refining step... we subtract the approximated x from the real x
//and lookup again
f2=m.f;
m.i &= FEXPMASK;
m.f=f2-m.f;
id = m.i>>FEXPSHIFT;
val *= exptable[id];
//Second refining step: second order Taylor approximation
f2=m.f;
m.i &= FEXPMASK;
m.f=f2-m.f;
//return val + val*m.f + .5*val*m.f*m.f;
return val + ( val*m.f * (1+.5*m.f) );
}
#endif
Generated by: jmvalin@usw-pr-shell2 on Mon Jun 24 00:06:36 2002, using kdoc 2.0a40. |