added clutter_pow2x() and clutter_log2x()

This commit is contained in:
Tomas Frydrych 2007-05-17 07:09:18 +00:00
parent 507f04a8f6
commit a4eeaceda4
2 changed files with 129 additions and 0 deletions

View File

@ -673,6 +673,132 @@ clutter_qmulx (ClutterFixed op1, ClutterFixed op2)
#endif #endif
} }
/*
* The log2x() and pow2x() functions
*
* The implementation of the log2x() and pow2x() exploits the well-documented
* fact that the exponent part of IEEE floating number provides a good estimate
* of log2 of that number, while the mantisa serves as a good error-correction.
*
* The implemenation here uses a quadratic error correction as described by
* Ian Stephenson at http://www.dctsystems.co.uk/Software/power.html.
*/
/**
* clutter_log2x :
* @x: value to calculate base 2 logarithm from
*
* Calculates base 2 logarithm.
*
* This function is some 2.5 times faster on x86, and over 12 times faster on
* fpu-less arm, than using libc log().
*
* Return value: base 2 logarithm.
*
* Since: 0.4
*/
ClutterFixed
clutter_log2x (guint x)
{
/* Note: we could easily have a version for ClutterFixed x, but the int
* precission is enough for the current purposes.
*/
union
{
float f;
ClutterFixed i;
} flt;
ClutterFixed magic = 0x58bb;
ClutterFixed y;
/*
* Convert x to float, then extract exponent.
*
* We want the result to be 16.16 fixed, so we shift (23-16) bits only
*/
flt.f = x;
flt.i >>= 7;
flt.i -= CLUTTER_INT_TO_FIXED (127);
y = CLUTTER_FIXED_FRACTION (flt.i);
y = CFX_MUL ((y - CFX_MUL (y, y)), magic);
return flt.i + y;
}
/**
* clutter_pow2x :
* @x: exponent
*
* Calculates 2 to x power.
*
* This function is around 11 times faster on x86, and around 22 times faster
* on fpu-less arm than libc pow(2, x).
*
* Return value: 2 in x power.
*
* Since: 0.4
*/
guint
clutter_pow2x (ClutterFixed x)
{
/* Note: we could easily have a version that produces ClutterFixed result,
* but the the range would be limited to x < 15, and the int precission
* is enough for the current purposes.
*/
union
{
float f;
ClutterFixed i;
} flt;
ClutterFixed magic = 0x56f7;
ClutterFixed y;
flt.i = x;
/*
* Reverse of the log2x function -- convert the fixed value to a suitable
* floating point exponent, and mantisa adjusted with quadratic error
* correction y.
*/
y = CLUTTER_FIXED_FRACTION (x);
y = CFX_MUL ((y - CFX_MUL (y, y)), magic);
/* Shift the exponent into it's position in the floating point
* representation; as our number is not int but 16.16 fixed, shift only
* by (23 - 16)
*/
flt.i += (CLUTTER_INT_TO_FIXED (127) - y);
flt.i <<= 7;
return CLUTTER_FLOAT_TO_INT (flt.f);
}
/**
* clutter_powx :
* @x: base
* @y: #ClutterFixed exponent
*
* Calculates x to y power. (Note, if x is a constant it will be faster to
* calculate the power as clutter_pow2x (CLUTTER_FIXED_MUL(y, log2 (x)))
*
* Return value: x in y power.
*
* Since: 0.4
*/
guint
clutter_powx (guint x, ClutterFixed y)
{
return clutter_pow2x (CFX_MUL (y, clutter_log2x (x)));
}
/* <private> */ /* <private> */
const double _magic = 68719476736.0*1.5; const double _magic = 68719476736.0*1.5;

View File

@ -186,6 +186,9 @@ ClutterFixed clutter_tani (ClutterAngle angle);
ClutterFixed clutter_sqrtx (ClutterFixed x); ClutterFixed clutter_sqrtx (ClutterFixed x);
gint clutter_sqrti (gint x); gint clutter_sqrti (gint x);
ClutterFixed clutter_log2x (guint x);
guint clutter_pow2x (ClutterFixed x);
guint clutter_powx (guint x, ClutterFixed y);
/* <private> */ /* <private> */
extern inline extern inline