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