From 5ca8e29dcfc73b13a3c4c32e58619d9c486df57b Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Sat, 12 Mar 2011 17:46:11 +0000 Subject: Saturated maths in css fixed point svn path=/trunk/libcss/; revision=11975 --- include/libcss/fpmath.h | 122 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 105 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/include/libcss/fpmath.h b/include/libcss/fpmath.h index 3867f3a..36e0ab5 100644 --- a/include/libcss/fpmath.h +++ b/include/libcss/fpmath.h @@ -14,37 +14,120 @@ extern "C" #endif #include +#include /* 22:10 fixed point math */ +#define CSS_RADIX_POINT 10 + +/* type for fixed point numbers */ typedef int32_t css_fixed; +static inline css_fixed +css_add_fixed(const css_fixed x, const css_fixed y) { + int32_t ux = x; + int32_t uy = y; + int32_t res = ux + uy; + + /* Calculate overflowed result. (Don't change the sign bit of ux) */ + ux = (ux >> 31) + INT_MAX; + + /* Force compiler to use cmovns instruction */ + if ((int32_t) ((ux ^ uy) | ~(uy ^ res)) >= 0) { + res = ux; + } + + return res; +} + +static inline css_fixed +css_subtract_fixed(const css_fixed x, const css_fixed y) { + int32_t ux = x; + int32_t uy = y; + int32_t res = ux - uy; + + ux = (ux >> 31) + INT_MAX; + + /* Force compiler to use cmovns instruction */ + if ((int32_t)((ux ^ uy) & (ux ^ res)) < 0) { + res = ux; + } + + return res; +} + +static inline css_fixed +css_divide_fixed(const css_fixed x, const css_fixed y) { + int64_t xx = ((int64_t)x << CSS_RADIX_POINT) / y; + + if (xx < INT_MIN) + xx = INT_MIN; + + if (xx > INT_MAX) + xx = INT_MAX; + + return xx; +} + +static inline css_fixed +css_multiply_fixed(const css_fixed x, const css_fixed y) { + int64_t xx = ((int64_t)x * (int64_t)y) >> CSS_RADIX_POINT; + + if (xx < INT_MIN) + xx = INT_MIN; + + if (xx > INT_MAX) + xx = INT_MAX; + + return xx; +} + +static inline css_fixed +css_int_to_fixed(const int a) { + int64_t xx = ((int64_t) a) << CSS_RADIX_POINT; + + if (xx < INT_MIN) + xx = INT_MIN; + + if (xx > INT_MAX) + xx = INT_MAX; + + return xx; +} + +static inline css_fixed +css_float_to_fixed(const float a) { + float xx = a * (float) (1 << CSS_RADIX_POINT); + + if (xx < INT_MIN) + xx = INT_MIN; + + if (xx > INT_MAX) + xx = INT_MAX; + + return xx; +} + /* Add two fixed point values */ -#define FADD(a, b) ((a) + (b)) +#define FADD(a, b) (css_add_fixed((a), (b))) /* Subtract two fixed point values */ -#define FSUB(a, b) ((a) - (b)) +#define FSUB(a, b) (css_subtract_fixed((a), (b))) /* Multiply two fixed point values */ -#define FMUL(a, b) ((((int64_t) (a)) * ((int64_t) (b))) >> 10) +#define FMUL(a, b) (css_multiply_fixed((a), (b))) /* Divide two fixed point values */ -#define FDIV(a, b) ((((int64_t) (a)) << 10) / (b)) - -/* Add an integer to a fixed point value */ -#define FADDI(a, b) ((a) + ((b) << 10)) -/* Subtract an integer from a fixed point value */ -#define FSUBI(a, b) ((a) - ((b) << 10)) -/* Multiply a fixed point value by an integer */ -#define FMULI(a, b) ((a) * (b)) -/* Divide a fixed point value by an integer */ -#define FDIVI(a, b) ((a) / (b)) +#define FDIV(a, b) (css_divide_fixed((a), (b))) /* Convert a floating point value to fixed point */ -#define FLTTOFIX(a) ((css_fixed) ((a) * (float) (1 << 10))) +#define FLTTOFIX(a) ((css_fixed) ((a) * (float) (1 << CSS_RADIX_POINT))) /* Convert a fixed point value to floating point */ -#define FIXTOFLT(a) ((float) (a) / (float) (1 << 10)) +#define FIXTOFLT(a) ((float) (a) / (float) (1 << CSS_RADIX_POINT)) /* Convert an integer to a fixed point value */ -#define INTTOFIX(a) ((a) << 10) +#define INTTOFIX(a) (css_int_to_fixed(a)) /* Convert a fixed point value to an integer */ -#define FIXTOINT(a) ((a) >> 10) +#define FIXTOINT(a) ((a) >> CSS_RADIX_POINT) + +/* truncate a fixed point value */ +#define TRUNCATEFIX(a) (a & ~((1 << CSS_RADIX_POINT)- 1 )) /* Useful values */ #define F_PI_2 0x00000648 /* 1.5708 (PI/2) */ @@ -57,8 +140,13 @@ typedef int32_t css_fixed; #define F_270 0x00043800 /* 270 */ #define F_360 0x0005a000 /* 360 */ +#define F_0_5 0x00000200 /* 0.5 */ +#define F_1 0x00000400 /* 1 */ +#define F_10 0x00002800 /* 10 */ +#define F_72 0x00012000 /* 72 */ #define F_100 0x00019000 /* 100 */ #define F_200 0x00032000 /* 200 */ +#define F_255 0x0003FC00 /* 255 */ #define F_300 0x0004b000 /* 300 */ #define F_400 0x00064000 /* 400 */ -- cgit v1.2.3