Sign in to follow this  
atlnewbie

i need floor function implementation

Recommended Posts

atlnewbie    122
I'm programming on a platform that doesn't have the typical "math.h" c runtime functions - I'm looking for an implementation of the floor function using standard IEEE floats - not doubles - preferably a fast one as I'm pretty sure I can write an inefficient one using casting and so forth.. ;) float floor(float x) { ... } thanx in advance

Share this post


Link to post
Share on other sites
jumpjumpjump    328
It sounds like you are writing an operating system, here is what I use in mine.


double sqrt(double x)
{
double i = x/2;
if(x<0)return 0;
while(fabs(i-(x/i))/i>0.000000000000001) /* (15 DP) ?HOW GET MORE? */
i=(i+(x/i))/2;
return i;
}

double fabs(double x)
{
if(x < 0)return -x;
return x;
}

double hypot(double x, double y)
{
return sqrt(x*x+y*y);
}

double ceil(double x)
{
if(x<0)return (int)x;
return ((int)x)+1;
}

double cbrt(double x)
{
double i = x/4;
while(fabs(i-(x/i/i))/i>0.00000000000001) /* (15 DP) ?HOW GET MORE? */
i=(i+(x/i/i)+i)/3;
return i;
}

double copysign(double x,double signval)
{
if(signval<0 && x<0)return x;
if(signval<0 && x>0)return -x;
if(signval>0 && x>0)return x;
if(signval>0 && x<0)return -x;
return x;
}

double fdim(double a, double b)
{
if(a-b<1)return 0;
return a-b;
}

double fmax(double a, double b)
{
if(a>b)return a;
return b;
}

double floor(double x)
{
if(x>0)return (int)x;
return (int)(x-0.9999999999999999);
}

double fmin(double a, double b)
{
if(a<b)return a;
return b;
}

double fmod(double a,double b)
{
return (int)((((a/b)-((int)(a/b)))*b)+0.5);
}

double round(double arg)
{
return (int)(arg+0.5);
}

double rint(double arg)
{
return round(arg);
}

double remainder(double a, double b)
{
return fmod(a,b);
}

int trunc(double arg)
{
return (int)arg;
}

double nearbyint(double arg)
{
return round(arg);
}

double exp2(double exp)
{
int i;
double value=1;
for(i=1;i<=exp;i++){
value=value*2;
}
return value;
}

double fma(double a,double b,double c)
{
return (int)((a*b)+c+0.5);
}

double ldexp(double num, int exp)
{
return num*exp2(exp);
}





EDIT: woops, didn't catch the double party, but maybe the others will help you.

Share this post


Link to post
Share on other sites
Ra    1062
float floor(float x)
{
if (x >= 0.0f)
{
return (float)((int)x);
}
else
{
return (float)((int)x - 1);
}
}
That should provide identical behavior to floor() but there's probably a better way to handle it which I can't think of right now.

EDIT: Same thing, one-liner:

float floor(float x) { return (float)((int)x - ((x < 0.0f) ? 1 : 0); }

Share this post


Link to post
Share on other sites
Fred304    382

float floor(float x)
{
int i = (int)x;
return (float)((x<0.0f) ? i-1 : i);
}

untested. maybe this will also work:


float floor(float x)
{
int i = (int)x;
return (float)(i - (x<0.0f));
}


inspired by Ra:


float floor(float x)
{
return (float)((int)x - (x<0.0f));
}

Share this post


Link to post
Share on other sites
Ra    1062
Quote:
Original post by Fred304
inspired by Ra:

float floor(float x)
{
return (float)((int)x - (x<0.0f));
}
float floor(float x)
{
return (float)((int)x - (int)(x < 0.0f));
}
I'm not 100% sure about this, but I believe a cast is needed to turn the zero/non-zero bool to 0/1. A value of true could be 0xFF (or any non-zero value) in some cases.

Share this post


Link to post
Share on other sites
Max_Payne    757
Indeed, I'm quite sure this would generate an error, or at least a warning in VS2003... Why do a cheap hack when you can do it cleanly ;)

To the parent poster: The techniques suggested in this thread seem relatively efficient. Apart perhaps from the casting from float to int and int to float. Perhaps you can get around this using some hacked up assembler code, but unless your platform needs extreme performance, I don't see the point of overcomplicating things.

Share this post


Link to post
Share on other sites
sordid    246
If you have a FPU on that platform.. here's mine:


float floor(float f)
{
const float half = -0.5f;
int i;
__asm {
fld f
fadd st, st(0)
fadd half
fistp i
sar i,1
};

return float(i);
}



Works with positive and negatives (ie. -2.5 will floor to -3)

The int-to-float conversion is a little more graceful than the float-to-int, as there is no direct float-to-int conversion.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this