aboutsummaryrefslogtreecommitdiffhomepage
path: root/include/core/SkFloatBits.h
blob: a1196caca7fc119672b71fc39644dc0cea9e9469 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138

/*
 * Copyright 2008 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */


#ifndef SkFloatBits_DEFINED
#define SkFloatBits_DEFINED

#include "SkTypes.h"

/** Convert a sign-bit int (i.e. float interpreted as int) into a 2s compliement
    int. This also converts -0 (0x80000000) to 0. Doing this to a float allows
    it to be compared using normal C operators (<, <=, etc.)
*/
static inline int32_t SkSignBitTo2sCompliment(int32_t x) {
    if (x < 0) {
        x &= 0x7FFFFFFF;
        x = -x;
    }
    return x;
}

/** Convert a 2s compliment int to a sign-bit (i.e. int interpreted as float).
    This undoes the result of SkSignBitTo2sCompliment().
 */
static inline int32_t Sk2sComplimentToSignBit(int32_t x) {
    int sign = x >> 31;
    // make x positive
    x = (x ^ sign) - sign;
    // set the sign bit as needed
    x |= sign << 31;
    return x;
}

/** Given the bit representation of a float, return its value cast to an int.
    If the value is out of range, or NaN, return return +/- SK_MaxS32
*/
int32_t SkFloatBits_toIntCast(int32_t floatBits);

/** Given the bit representation of a float, return its floor as an int.
    If the value is out of range, or NaN, return return +/- SK_MaxS32
 */
SK_API int32_t SkFloatBits_toIntFloor(int32_t floatBits);

/** Given the bit representation of a float, return it rounded to an int.
    If the value is out of range, or NaN, return return +/- SK_MaxS32
 */
SK_API int32_t SkFloatBits_toIntRound(int32_t floatBits);

/** Given the bit representation of a float, return its ceiling as an int.
    If the value is out of range, or NaN, return return +/- SK_MaxS32
 */
SK_API int32_t SkFloatBits_toIntCeil(int32_t floatBits);


union SkFloatIntUnion {
    float   fFloat;
    int32_t fSignBitInt;
};

// Helper to see a float as its bit pattern (w/o aliasing warnings)
static inline int32_t SkFloat2Bits(float x) {
    SkFloatIntUnion data;
    data.fFloat = x;
    return data.fSignBitInt;
}

// Helper to see a bit pattern as a float (w/o aliasing warnings)
static inline float SkBits2Float(int32_t floatAsBits) {
    SkFloatIntUnion data;
    data.fSignBitInt = floatAsBits;
    return data.fFloat;
}

/** Return the float as a 2s compliment int. Just to be used to compare floats
    to each other or against positive float-bit-constants (like 0). This does
    not return the int equivalent of the float, just something cheaper for
    compares-only.
 */
static inline int32_t SkFloatAs2sCompliment(float x) {
    return SkSignBitTo2sCompliment(SkFloat2Bits(x));
}

/** Return the 2s compliment int as a float. This undos the result of
    SkFloatAs2sCompliment
 */
static inline float Sk2sComplimentAsFloat(int32_t x) {
    return SkBits2Float(Sk2sComplimentToSignBit(x));
}

/** Return x cast to a float (i.e. (float)x)
*/
float SkIntToFloatCast(int x);
float SkIntToFloatCast_NoOverflowCheck(int x);

/** Return the float cast to an int.
    If the value is out of range, or NaN, return +/- SK_MaxS32
*/
static inline int32_t SkFloatToIntCast(float x) {
    return SkFloatBits_toIntCast(SkFloat2Bits(x));
}

/** Return the floor of the float as an int.
    If the value is out of range, or NaN, return +/- SK_MaxS32
*/
static inline int32_t SkFloatToIntFloor(float x) {
    return SkFloatBits_toIntFloor(SkFloat2Bits(x));
}

/** Return the float rounded to an int.
    If the value is out of range, or NaN, return +/- SK_MaxS32
*/
static inline int32_t SkFloatToIntRound(float x) {
    return SkFloatBits_toIntRound(SkFloat2Bits(x));
}

/** Return the ceiling of the float as an int.
    If the value is out of range, or NaN, return +/- SK_MaxS32
*/
static inline int32_t SkFloatToIntCeil(float x) {
    return SkFloatBits_toIntCeil(SkFloat2Bits(x));
}

//  Scalar wrappers for float-bit routines

#ifdef SK_SCALAR_IS_FLOAT
    #define SkScalarAs2sCompliment(x)    SkFloatAs2sCompliment(x)
    #define Sk2sComplimentAsScalar(x)    Sk2sComplimentAsFloat(x)
#else
    #define SkScalarAs2sCompliment(x)    (x)
    #define Sk2sComplimentAsScalar(x)    (x)
#endif

#endif