15bb6825f10d64834ad1d1d967f590aebae285360epoger@google.com
2f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com/*
35bb6825f10d64834ad1d1d967f590aebae285360epoger@google.com * Copyright 2008 The Android Open Source Project
4f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com *
55bb6825f10d64834ad1d1d967f590aebae285360epoger@google.com * Use of this source code is governed by a BSD-style license that can be
65bb6825f10d64834ad1d1d967f590aebae285360epoger@google.com * found in the LICENSE file.
7f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */
8f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
95bb6825f10d64834ad1d1d967f590aebae285360epoger@google.com
10f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com#ifndef SkFloatBits_DEFINED
11f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com#define SkFloatBits_DEFINED
12f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
13f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com#include "SkTypes.h"
14f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
15f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com/** Convert a sign-bit int (i.e. float interpreted as int) into a 2s compliement
16f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    int. This also converts -0 (0x80000000) to 0. Doing this to a float allows
17f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    it to be compared using normal C operators (<, <=, etc.)
18f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com*/
19f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.comstatic inline int32_t SkSignBitTo2sCompliment(int32_t x) {
20f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    if (x < 0) {
21f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com        x &= 0x7FFFFFFF;
22f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com        x = -x;
23f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    }
24f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    return x;
25f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com}
26f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
27f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com/** Convert a 2s compliment int to a sign-bit (i.e. int interpreted as float).
28f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    This undoes the result of SkSignBitTo2sCompliment().
29f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */
30f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.comstatic inline int32_t Sk2sComplimentToSignBit(int32_t x) {
31f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    int sign = x >> 31;
32f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    // make x positive
33f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    x = (x ^ sign) - sign;
34f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    // set the sign bit as needed
35f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    x |= sign << 31;
36f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    return x;
37f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com}
38f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
39f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com/** Given the bit representation of a float, return its value cast to an int.
40f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    If the value is out of range, or NaN, return return +/- SK_MaxS32
41f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com*/
42f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.comint32_t SkFloatBits_toIntCast(int32_t floatBits);
43f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
44f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com/** Given the bit representation of a float, return its floor as an int.
45f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    If the value is out of range, or NaN, return return +/- SK_MaxS32
46f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */
472083387d719b933797044ad07efd3bb67f99a5c5ctguil@chromium.orgSK_API int32_t SkFloatBits_toIntFloor(int32_t floatBits);
48f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
49f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com/** Given the bit representation of a float, return it rounded to an int.
50f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    If the value is out of range, or NaN, return return +/- SK_MaxS32
51f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */
522083387d719b933797044ad07efd3bb67f99a5c5ctguil@chromium.orgSK_API int32_t SkFloatBits_toIntRound(int32_t floatBits);
53f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
54f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com/** Given the bit representation of a float, return its ceiling as an int.
55f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    If the value is out of range, or NaN, return return +/- SK_MaxS32
56f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */
572083387d719b933797044ad07efd3bb67f99a5c5ctguil@chromium.orgSK_API int32_t SkFloatBits_toIntCeil(int32_t floatBits);
58f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
59f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
60f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.comunion SkFloatIntUnion {
61f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    float   fFloat;
62f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    int32_t fSignBitInt;
63f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com};
64f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
65f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com// Helper to see a float as its bit pattern (w/o aliasing warnings)
66f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.comstatic inline int32_t SkFloat2Bits(float x) {
67f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    SkFloatIntUnion data;
68f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    data.fFloat = x;
69f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    return data.fSignBitInt;
70f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com}
71f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
72f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com// Helper to see a bit pattern as a float (w/o aliasing warnings)
73f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.comstatic inline float SkBits2Float(int32_t floatAsBits) {
74f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    SkFloatIntUnion data;
75f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    data.fSignBitInt = floatAsBits;
76f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    return data.fFloat;
77f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com}
78f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
79f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com/** Return the float as a 2s compliment int. Just to be used to compare floats
80f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    to each other or against positive float-bit-constants (like 0). This does
81f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    not return the int equivalent of the float, just something cheaper for
82f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    compares-only.
83f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */
84f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.comstatic inline int32_t SkFloatAs2sCompliment(float x) {
85f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    return SkSignBitTo2sCompliment(SkFloat2Bits(x));
86f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com}
87f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
88f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com/** Return the 2s compliment int as a float. This undos the result of
89f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    SkFloatAs2sCompliment
90f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */
91f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.comstatic inline float Sk2sComplimentAsFloat(int32_t x) {
92f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    return SkBits2Float(Sk2sComplimentToSignBit(x));
93f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com}
94f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
95f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com/** Return x cast to a float (i.e. (float)x)
96f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com*/
97f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.comfloat SkIntToFloatCast(int x);
98f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.comfloat SkIntToFloatCast_NoOverflowCheck(int x);
99f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
100f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com/** Return the float cast to an int.
101f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    If the value is out of range, or NaN, return +/- SK_MaxS32
102f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com*/
103f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.comstatic inline int32_t SkFloatToIntCast(float x) {
104f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    return SkFloatBits_toIntCast(SkFloat2Bits(x));
105f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com}
106f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
107f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com/** Return the floor of the float as an int.
108f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    If the value is out of range, or NaN, return +/- SK_MaxS32
109f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com*/
110f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.comstatic inline int32_t SkFloatToIntFloor(float x) {
111f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    return SkFloatBits_toIntFloor(SkFloat2Bits(x));
112f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com}
113f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
114f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com/** Return the float rounded to an int.
115f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    If the value is out of range, or NaN, return +/- SK_MaxS32
116f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com*/
117f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.comstatic inline int32_t SkFloatToIntRound(float x) {
118f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    return SkFloatBits_toIntRound(SkFloat2Bits(x));
119f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com}
120f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
121f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com/** Return the ceiling of the float as an int.
122f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    If the value is out of range, or NaN, return +/- SK_MaxS32
123f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com*/
124f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.comstatic inline int32_t SkFloatToIntCeil(float x) {
125f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    return SkFloatBits_toIntCeil(SkFloat2Bits(x));
126f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com}
127f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
128f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com//  Scalar wrappers for float-bit routines
129f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
130f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com#ifdef SK_SCALAR_IS_FLOAT
131f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    #define SkScalarAs2sCompliment(x)    SkFloatAs2sCompliment(x)
132f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    #define Sk2sComplimentAsScalar(x)    Sk2sComplimentAsFloat(x)
133f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com#else
134f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    #define SkScalarAs2sCompliment(x)    (x)
135f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    #define Sk2sComplimentAsScalar(x)    (x)
136f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com#endif
137f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
138f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com#endif
139