Home | History | Annotate | Download | only in core
      1 #include "SkFloatBits.h"
      2 #include "SkMath.h"
      3 
      4 /******************************************************************************
      5     SkFloatBits_toInt[Floor, Round, Ceil] are identical except for what they
      6     do right before they return ... >> exp;
      7     Floor - adds nothing
      8     Round - adds 1 << (exp - 1)
      9     Ceil - adds (1 << exp) - 1
     10 
     11     Floor and Cast are very similar, but Cast applies its sign after all other
     12     computations on value. Also, Cast does not need to check for negative zero,
     13     as that value (0x80000000) "does the right thing" for Ceil. Note that it
     14     doesn't for Floor/Round/Ceil, hence the explicit check.
     15 ******************************************************************************/
     16 
     17 #define EXP_BIAS            (127+23)
     18 #define MATISSA_MAGIC_BIG   (1 << 23)
     19 
     20 static inline int unpack_exp(uint32_t packed) {
     21     return (packed << 1 >> 24);
     22 }
     23 
     24 #if 0
     25 // the ARM compiler generates an extra BIC, so I use the dirty version instead
     26 static inline int unpack_matissa(uint32_t packed) {
     27     // we could mask with 0x7FFFFF, but that is harder for ARM to encode
     28     return (packed & ~0xFF000000) | MATISSA_MAGIC_BIG;
     29 }
     30 #endif
     31 
     32 // returns the low 24-bits, so we need to OR in the magic_bit afterwards
     33 static inline int unpack_matissa_dirty(uint32_t packed) {
     34     return packed & ~0xFF000000;
     35 }
     36 
     37 // same as (int)float
     38 int32_t SkFloatBits_toIntCast(int32_t packed) {
     39     int exp = unpack_exp(packed) - EXP_BIAS;
     40     int value = unpack_matissa_dirty(packed) | MATISSA_MAGIC_BIG;
     41 
     42     if (exp >= 0) {
     43         if (exp > 7) {    // overflow
     44             value = SK_MaxS32;
     45         } else {
     46             value <<= exp;
     47         }
     48     } else {
     49         exp = -exp;
     50         if (exp > 25) {   // underflow
     51             exp = 25;
     52         }
     53         value >>= exp;
     54     }
     55     return SkApplySign(value, SkExtractSign(packed));
     56 }
     57 
     58 // same as (int)floor(float)
     59 int32_t SkFloatBits_toIntFloor(int32_t packed) {
     60     // curse you negative 0
     61     if ((packed << 1) == 0) {
     62         return 0;
     63     }
     64 
     65     int exp = unpack_exp(packed) - EXP_BIAS;
     66     int value = unpack_matissa_dirty(packed) | MATISSA_MAGIC_BIG;
     67 
     68     if (exp >= 0) {
     69         if (exp > 7) {    // overflow
     70             value = SK_MaxS32;
     71         } else {
     72             value <<= exp;
     73         }
     74         // apply the sign after we check for overflow
     75         return SkApplySign(value, SkExtractSign(packed));
     76     } else {
     77         // apply the sign before we right-shift
     78         value = SkApplySign(value, SkExtractSign(packed));
     79         exp = -exp;
     80         if (exp > 25) {   // underflow
     81             exp = 25;
     82         }
     83         // int add = 0;
     84         return value >> exp;
     85     }
     86 }
     87 
     88 // same as (int)floor(float + 0.5)
     89 int32_t SkFloatBits_toIntRound(int32_t packed) {
     90     // curse you negative 0
     91     if ((packed << 1) == 0) {
     92         return 0;
     93     }
     94 
     95     int exp = unpack_exp(packed) - EXP_BIAS;
     96     int value = unpack_matissa_dirty(packed) | MATISSA_MAGIC_BIG;
     97 
     98     if (exp >= 0) {
     99         if (exp > 7) {    // overflow
    100             value = SK_MaxS32;
    101         } else {
    102             value <<= exp;
    103         }
    104         // apply the sign after we check for overflow
    105         return SkApplySign(value, SkExtractSign(packed));
    106     } else {
    107         // apply the sign before we right-shift
    108         value = SkApplySign(value, SkExtractSign(packed));
    109         exp = -exp;
    110         if (exp > 25) {   // underflow
    111             exp = 25;
    112         }
    113         int add = 1 << (exp - 1);
    114         return (value + add) >> exp;
    115     }
    116 }
    117 
    118 // same as (int)ceil(float)
    119 int32_t SkFloatBits_toIntCeil(int32_t packed) {
    120     // curse you negative 0
    121     if ((packed << 1) == 0) {
    122         return 0;
    123     }
    124 
    125     int exp = unpack_exp(packed) - EXP_BIAS;
    126     int value = unpack_matissa_dirty(packed) | MATISSA_MAGIC_BIG;
    127 
    128     if (exp >= 0) {
    129         if (exp > 7) {    // overflow
    130             value = SK_MaxS32;
    131         } else {
    132             value <<= exp;
    133         }
    134         // apply the sign after we check for overflow
    135         return SkApplySign(value, SkExtractSign(packed));
    136     } else {
    137         // apply the sign before we right-shift
    138         value = SkApplySign(value, SkExtractSign(packed));
    139         exp = -exp;
    140         if (exp > 25) {   // underflow
    141             exp = 25;
    142         }
    143         int add = (1 << exp) - 1;
    144         return (value + add) >> exp;
    145     }
    146 }
    147 
    148 #ifdef SK_CAN_USE_FLOAT
    149 
    150 float SkIntToFloatCast(int32_t value) {
    151     if (0 == value) {
    152         return 0;
    153     }
    154 
    155     int shift = EXP_BIAS;
    156 
    157     // record the sign and make value positive
    158     int sign = SkExtractSign(value);
    159     value = SkApplySign(value, sign);
    160 
    161     if (value >> 24) {    // value is too big (has more than 24 bits set)
    162         int bias = 8 - SkCLZ(value);
    163         SkDebugf("value = %d, bias = %d\n", value, bias);
    164         SkASSERT(bias > 0 && bias < 8);
    165         value >>= bias; // need to round?
    166         shift += bias;
    167     } else {
    168         int zeros = SkCLZ(value << 8);
    169         SkASSERT(zeros >= 0 && zeros <= 23);
    170         value <<= zeros;
    171         shift -= zeros;
    172     }
    173 
    174     // now value is left-aligned to 24 bits
    175     SkASSERT((value >> 23) == 1);
    176     SkASSERT(shift >= 0 && shift <= 255);
    177 
    178     SkFloatIntUnion data;
    179     data.fSignBitInt = (sign << 31) | (shift << 23) | (value & ~MATISSA_MAGIC_BIG);
    180     return data.fFloat;
    181 }
    182 
    183 float SkIntToFloatCast_NoOverflowCheck(int32_t value) {
    184     if (0 == value) {
    185         return 0;
    186     }
    187 
    188     int shift = EXP_BIAS;
    189 
    190     // record the sign and make value positive
    191     int sign = SkExtractSign(value);
    192     value = SkApplySign(value, sign);
    193 
    194     int zeros = SkCLZ(value << 8);
    195     value <<= zeros;
    196     shift -= zeros;
    197 
    198     SkFloatIntUnion data;
    199     data.fSignBitInt = (sign << 31) | (shift << 23) | (value & ~MATISSA_MAGIC_BIG);
    200     return data.fFloat;
    201 }
    202 
    203 #endif
    204