diff -r 000000000000 -r 88edb906c587 svgtopt/gfx2d/src/GfxMath.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svgtopt/gfx2d/src/GfxMath.c Wed Nov 03 18:56:10 2010 +0200 @@ -0,0 +1,243 @@ +/* +* Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Graphics Math Utility functions +* +*/ + +#include "Gfxmath.h" + + +/*-------------------------------------------------------------------*//*! + * \brief Counts number of leading zeroes in an integer + * \param value Integer value + * \return Number of leading zeroes [0,32] + * \note Example outputs: clz(0)=32, clz(1)=31, clz(-1)=0 + * \todo We want to generate clz instruction for ARM if supported by the CPU + *//*-------------------------------------------------------------------*/ + +static int svgClz32(unsigned int value) + { + int c = 0; + + if (value<(1u<<( 16 ))) + c+=( 16 ); + else + value >>= ( 16 );; + if (value<(1u<<( 8 ))) + c+=( 8 ); + else + value >>= ( 8 );; + if (value<(1u<<( 4 ))) + c+=( 4 ); + else + value >>= ( 4 );; + if (value<(1u<<( 2 ))) + c+=( 2 ); + else + value >>= ( 2 );; + c += 2 >> value; + + return c; + + } + +/*-------------------------------------------------------------------*//*! + * \brief Returns absolute value of an integer + * \param a 32-bit input value + * \return abs(a) + * \todo On many platforms it might be best to use native abs() ? + *//*-------------------------------------------------------------------*/ +static int svgAbs32 (int a) + { + return (a >= 0) ? a : -a; + } + +static int svgGTEFloat(int lhs, int rhs) + { + int cmp; + if ((lhs & rhs) >> 31) + { + cmp = (int)lhs <= (int)rhs; + } + else + { + cmp = (int)lhs >= (int)rhs; + } + return cmp; + } + +static int svgLTEFloat(int lhs, int rhs) + { + /* Compare signed, if both are negative, we need to invert the result */ + int cmp; + if ((lhs & rhs) >> 31) + { + cmp = (int)lhs >= (int)rhs; + } + else + { + cmp = (int)lhs <= (int)rhs; + } + return cmp; + } + +/** + * \brief Clamping version of the fixed -> float conversion routine. That is, will not + * create incorrect results on values > ~32768.0 or < -32768.0 + * + * \param f Input floating-point + * \return Fixed-point number within 16.16 fixed-point range. + */ + int svgScalarFromFloat(float f) + { + int a; + int sign; + int exponent; + + int r; + + if (svgGTEFloat((*(int*)&f ), 0x47000000) ) + { + return 0x7fffffff; + } + else + if (svgLTEFloat((*(int*)&f ), 0xc7000000) ) + { + return 0x80000000; + } + else + { + a = (*(int*)&f ); + sign = a >> 31; + exponent = (127 + 15) - ((a >> 23) & 0xff); + + r = (int)((((int)(a) << 8) | (1U << 31)) >> exponent); + r &= ((exponent - 32) >> 31); + + r = (r ^ sign) - sign; + + return r; + } + } + +/*********************************************************************//*! + * \internal + * + * \brief Converts a 16.16 fixed point value into a floating point + * value + * \param x Fixed point value + * \returns Corresponding floating point value + * \note This is essentially exactly the same routine as nglIntToFloat, + * except that the exponent bias value is 16 smaller (thus + * dividing the float by 65536). If we run out of space and + * want to squeeze out a few extra bytes, we could write a + * common routine where the scale factor is passed in as + * a parameter. + * + ************************************************************************/ + +float svgFixedToFloat(int x) + { + unsigned int d = (unsigned int)(x) & 0x80000000u; /* get copy of sign */ + int exponent; + + if (!x) /* special case handling for 0 */ + return (float)(0); + + x = svgAbs32(x); /* get rid of sign (the code works only for unsigned values -> we add the sign later back) */ + + /*exponent = nglGetHighestSetBit((unsigned int)(x))-23;*//* get exponent and divide value */ + exponent = 31 - svgClz32((unsigned int)(x)) - 23; + + if (exponent >= 0) /* "signed shift right" (we shift the mantissa to the proper place) */ + x>>=exponent; + else + x<<=(-exponent); /*lint !e504 *//* yes, it is an unusual shift.. */ + + exponent += 127+23-16; /* convert exponent into biased form (divide by 65536 simultaneously!) */ + exponent <<=23; /* shift exponent to proper place */ + d |= (unsigned int)(exponent); /* combine sign with exponent */ + x &= ((1<<23)-1); /* mask the mantissa */ + d |= (unsigned int)(x); /* combine sign and exponent with mantissa */ + + return *(float*)&d; /* done */ + } + +/*-------------------------------------------------------------------*//*! + * \brief 32x32->64-bit signed multiplication + * \param a 32-bit signed integer + * \param b 32-bit signed integer + * \return 64-bit signed result of the multiplication + *//*-------------------------------------------------------------------*/ + +static svgInt64 svgMul64(int a, int b) + { + return (svgInt64)(a) * (int)(b); + } +/*=======================================================================*/ +/*=======================================================================*/ + +int svgScalarMul(int r1, int r2) + { + + svgInt64 a = svgMul64(r1, r2); + int l = (int)(a); + int h = (int)((svgUint64)(a)>>32); + int r = (h << 16) | (((unsigned int)l) >> 16); /* r = 32 middle bits of the 64 bit result */ + int hs = h >> 31; /* hs is either 0 or 0xffffffff */ + /* test if there is data in the upper 17 bits of h */ + if ( (h >> 15) != hs) + r = (~hs) ^ 0x80000000; /* saturate (~hs to avoid a big constant on ARM) */ + + return r; + } + +/*=======================================================================*/ +/*=======================================================================*/ + +int svgScalarDiv(int x, int y) + { + unsigned int ax = x < 0 ? -x : x; + unsigned int ay = y < 0 ? -y : y; + unsigned int axh = ax >> 14; + unsigned int axl = ax << 18; + int q = 0, i; + + if ((axh >> 1) >= ay) + { /* saturate when overflows */ + if ( (x < 0) ^ (y < 0)) + q = 0x80000000; + else + q = 0x7fffffff; + } + else + { + for (i = 30; i>=0; i--) + { + if (axh >= ay) + { + axh -= ay; + q += 1<> 31; /* add carry */ + axl <<= 1; + } + if ( (x < 0) ^ (y < 0)) + q = -q; + } + + return q; + }