svgtopt/gfx2d/src/GfxMath.c
changeset 46 88edb906c587
equal deleted inserted replaced
-1:000000000000 46:88edb906c587
       
     1 /*
       
     2 * Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Graphics Math Utility functions
       
    15 *
       
    16 */
       
    17 
       
    18 #include "Gfxmath.h"
       
    19 
       
    20 
       
    21 /*-------------------------------------------------------------------*//*!
       
    22  * \brief   Counts number of leading zeroes in an integer
       
    23  * \param   value   Integer value
       
    24  * \return  Number of leading zeroes [0,32]
       
    25  * \note    Example outputs: clz(0)=32, clz(1)=31, clz(-1)=0
       
    26  * \todo    We want to generate clz instruction for ARM if supported by the CPU
       
    27  *//*-------------------------------------------------------------------*/
       
    28 
       
    29 static int svgClz32(unsigned int value)
       
    30     {
       
    31     int c = 0;
       
    32 
       
    33     if (value<(1u<<( 16 )))
       
    34         c+=( 16 );
       
    35     else
       
    36         value >>= ( 16 );;
       
    37     if (value<(1u<<( 8 )))
       
    38         c+=( 8 );
       
    39     else
       
    40         value >>= ( 8 );;
       
    41     if (value<(1u<<( 4 )))
       
    42         c+=( 4 );
       
    43     else
       
    44         value >>= ( 4 );;
       
    45     if (value<(1u<<( 2 )))
       
    46         c+=( 2 );
       
    47     else
       
    48         value >>= ( 2 );;
       
    49     c += 2 >> value;
       
    50 
       
    51     return c;
       
    52 
       
    53     }
       
    54 
       
    55 /*-------------------------------------------------------------------*//*!
       
    56  * \brief   Returns absolute value of an integer
       
    57  * \param   a   32-bit input value
       
    58  * \return  abs(a)
       
    59  * \todo    On many platforms it might be best to use native abs() ?
       
    60  *//*-------------------------------------------------------------------*/
       
    61 static int svgAbs32 (int a)
       
    62     {
       
    63     return (a >= 0) ? a : -a;
       
    64     }
       
    65 
       
    66 static int svgGTEFloat(int lhs, int rhs)
       
    67     {
       
    68     int cmp;
       
    69     if ((lhs & rhs) >> 31)
       
    70         {
       
    71         cmp = (int)lhs <= (int)rhs;
       
    72         }
       
    73     else
       
    74         {
       
    75         cmp = (int)lhs >= (int)rhs;
       
    76         }
       
    77     return cmp;
       
    78     }
       
    79 
       
    80 static int svgLTEFloat(int lhs, int rhs)
       
    81     {
       
    82     /* Compare signed, if both are negative, we need to invert the result */
       
    83     int cmp;
       
    84     if ((lhs & rhs) >> 31)
       
    85         {
       
    86         cmp = (int)lhs >= (int)rhs;
       
    87         }
       
    88     else
       
    89         {
       
    90         cmp = (int)lhs <= (int)rhs;
       
    91         }
       
    92     return cmp;
       
    93     }
       
    94 
       
    95 /**
       
    96  * \brief   Clamping version of the fixed -> float conversion routine. That is, will not
       
    97  *          create incorrect results on values > ~32768.0 or < -32768.0
       
    98  *
       
    99  * \param f Input floating-point
       
   100  * \return  Fixed-point number within 16.16 fixed-point range.
       
   101  */
       
   102  int svgScalarFromFloat(float f)
       
   103     {
       
   104     int a;
       
   105     int sign;
       
   106     int exponent;
       
   107 
       
   108     int r;
       
   109 
       
   110     if (svgGTEFloat((*(int*)&f ), 0x47000000) )
       
   111         {
       
   112         return 0x7fffffff;
       
   113         }
       
   114     else
       
   115         if (svgLTEFloat((*(int*)&f ), 0xc7000000) )
       
   116             {
       
   117             return 0x80000000;
       
   118             }
       
   119         else
       
   120             {
       
   121             a = (*(int*)&f );
       
   122             sign = a >> 31;
       
   123             exponent = (127 + 15) - ((a >> 23) & 0xff);
       
   124 
       
   125             r = (int)((((int)(a) << 8) | (1U << 31)) >> exponent);
       
   126             r &= ((exponent - 32) >> 31);
       
   127 
       
   128             r = (r ^ sign) - sign;
       
   129 
       
   130             return r;
       
   131             }
       
   132     }
       
   133 
       
   134 /*********************************************************************//*!
       
   135  * \internal
       
   136  *
       
   137  * \brief   Converts a 16.16 fixed point value into a floating point
       
   138  *          value
       
   139  * \param   x Fixed point value
       
   140  * \returns Corresponding floating point value
       
   141  * \note    This is essentially exactly the same routine as nglIntToFloat,
       
   142  *          except that the exponent bias value is 16 smaller (thus
       
   143  *          dividing the float by 65536). If we run out of space and
       
   144  *          want to squeeze out a few extra bytes, we could write a
       
   145  *          common routine where the scale factor is passed in as
       
   146  *          a parameter.
       
   147  *
       
   148  ************************************************************************/
       
   149 
       
   150 float svgFixedToFloat(int x)
       
   151     {
       
   152     unsigned int d = (unsigned int)(x) & 0x80000000u; /* get copy of sign */
       
   153     int exponent;
       
   154 
       
   155     if (!x) /* special case handling for 0 */
       
   156         return (float)(0);
       
   157 
       
   158     x = svgAbs32(x); /* get rid of sign (the code works only for unsigned values -> we add the sign later back)  */
       
   159 
       
   160     /*exponent = nglGetHighestSetBit((unsigned int)(x))-23;*//* get exponent and divide value */
       
   161     exponent = 31 - svgClz32((unsigned int)(x)) - 23;
       
   162 
       
   163     if (exponent >= 0) /* "signed shift right" (we shift the mantissa to the proper place) */
       
   164         x>>=exponent;
       
   165     else
       
   166         x<<=(-exponent); /*lint !e504 *//* yes, it is an unusual shift.. */
       
   167 
       
   168     exponent += 127+23-16; /* convert exponent into biased form (divide by 65536 simultaneously!)  */
       
   169     exponent <<=23; /* shift exponent to proper place           */
       
   170     d |= (unsigned int)(exponent); /* combine sign with exponent               */
       
   171     x &= ((1<<23)-1); /* mask the mantissa                        */
       
   172     d |= (unsigned int)(x); /* combine sign and exponent with mantissa  */
       
   173 
       
   174     return *(float*)&d; /* done */
       
   175     }
       
   176 
       
   177 /*-------------------------------------------------------------------*//*!
       
   178  * \brief   32x32->64-bit signed multiplication
       
   179  * \param   a   32-bit signed integer
       
   180  * \param   b   32-bit signed integer
       
   181  * \return  64-bit signed result of the multiplication
       
   182  *//*-------------------------------------------------------------------*/
       
   183 
       
   184 static svgInt64 svgMul64(int a, int b)
       
   185     {
       
   186     return (svgInt64)(a) * (int)(b);
       
   187     }
       
   188 /*=======================================================================*/
       
   189 /*=======================================================================*/
       
   190 
       
   191 int svgScalarMul(int r1, int r2)
       
   192     {
       
   193 
       
   194     svgInt64 a = svgMul64(r1, r2);
       
   195     int l = (int)(a);
       
   196     int h = (int)((svgUint64)(a)>>32);
       
   197     int r = (h << 16) | (((unsigned int)l) >> 16); /* r = 32 middle bits of the 64 bit result */
       
   198     int hs = h >> 31; /* hs is either 0 or 0xffffffff */
       
   199     /* test if there is data in the upper 17 bits of h */
       
   200     if ( (h >> 15) != hs)
       
   201         r = (~hs) ^ 0x80000000; /* saturate (~hs to avoid a big constant on ARM) */
       
   202 
       
   203     return r;
       
   204     }
       
   205 
       
   206 /*=======================================================================*/
       
   207 /*=======================================================================*/
       
   208 
       
   209 int svgScalarDiv(int x, int y)
       
   210     {
       
   211     unsigned int ax = x < 0 ? -x : x;
       
   212     unsigned int ay = y < 0 ? -y : y;
       
   213     unsigned int axh = ax >> 14;
       
   214     unsigned int axl = ax << 18;
       
   215     int q = 0, i;
       
   216 
       
   217     if ((axh >> 1) >= ay)
       
   218         { /* saturate when overflows */
       
   219         if ( (x < 0) ^ (y < 0))
       
   220             q = 0x80000000;
       
   221         else
       
   222             q = 0x7fffffff;
       
   223         }
       
   224     else
       
   225         {
       
   226         for (i = 30; i>=0; i--)
       
   227             {
       
   228             if (axh >= ay)
       
   229                 {
       
   230                 axh -= ay;
       
   231                 q += 1<<i;
       
   232                 }
       
   233             /* lsl64 #1 */
       
   234             axh <<= 1;
       
   235             axh |= axl >> 31; /* add carry */
       
   236             axl <<= 1;
       
   237             }
       
   238         if ( (x < 0) ^ (y < 0))
       
   239             q = -q;
       
   240         }
       
   241 
       
   242     return q;
       
   243     }