18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2008 The Android Open Source Project
38a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SkFloatBits_DEFINED
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkFloatBits_DEFINED
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTypes.h"
13e9f78b41c65a78400c22a1b79007b1b9e187a745Mike Klein#include "SkSafe_math.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Convert a sign-bit int (i.e. float interpreted as int) into a 2s compliement
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int. This also converts -0 (0x80000000) to 0. Doing this to a float allows
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    it to be compared using normal C operators (<, <=, etc.)
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline int32_t SkSignBitTo2sCompliment(int32_t x) {
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (x < 0) {
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        x &= 0x7FFFFFFF;
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        x = -x;
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return x;
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Convert a 2s compliment int to a sign-bit (i.e. int interpreted as float).
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    This undoes the result of SkSignBitTo2sCompliment().
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline int32_t Sk2sComplimentToSignBit(int32_t x) {
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int sign = x >> 31;
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // make x positive
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    x = (x ^ sign) - sign;
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // set the sign bit as needed
35952538ed50661ad7dff6ec2b7af3f921e1d91b52caryclark    x |= SkLeftShift(sign, 31);
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return x;
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comunion SkFloatIntUnion {
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    float   fFloat;
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int32_t fSignBitInt;
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Helper to see a float as its bit pattern (w/o aliasing warnings)
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline int32_t SkFloat2Bits(float x) {
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkFloatIntUnion data;
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    data.fFloat = x;
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return data.fSignBitInt;
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Helper to see a bit pattern as a float (w/o aliasing warnings)
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline float SkBits2Float(int32_t floatAsBits) {
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkFloatIntUnion data;
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    data.fSignBitInt = floatAsBits;
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return data.fFloat;
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Return the float as a 2s compliment int. Just to be used to compare floats
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    to each other or against positive float-bit-constants (like 0). This does
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    not return the int equivalent of the float, just something cheaper for
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    compares-only.
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline int32_t SkFloatAs2sCompliment(float x) {
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkSignBitTo2sCompliment(SkFloat2Bits(x));
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Return the 2s compliment int as a float. This undos the result of
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkFloatAs2sCompliment
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline float Sk2sComplimentAsFloat(int32_t x) {
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkBits2Float(Sk2sComplimentToSignBit(x));
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
74785a5b941a4d74a1f272729fe8dca55c6eda6bb8mtkleinstatic inline int32_t pin_double_to_int(double x) {
75785a5b941a4d74a1f272729fe8dca55c6eda6bb8mtklein    return (int32_t)SkTPin<double>(x, SK_MinS32, SK_MaxS32);
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Return the floor of the float as an int.
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    If the value is out of range, or NaN, return +/- SK_MaxS32
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline int32_t SkFloatToIntFloor(float x) {
82785a5b941a4d74a1f272729fe8dca55c6eda6bb8mtklein    return pin_double_to_int(floor(x));
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Return the float rounded to an int.
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    If the value is out of range, or NaN, return +/- SK_MaxS32
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline int32_t SkFloatToIntRound(float x) {
89785a5b941a4d74a1f272729fe8dca55c6eda6bb8mtklein    return pin_double_to_int(floor((double)x + 0.5));
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Return the ceiling of the float as an int.
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    If the value is out of range, or NaN, return +/- SK_MaxS32
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline int32_t SkFloatToIntCeil(float x) {
96785a5b941a4d74a1f272729fe8dca55c6eda6bb8mtklein    return pin_double_to_int(ceil(x));
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//  Scalar wrappers for float-bit routines
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1018f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com#define SkScalarAs2sCompliment(x)    SkFloatAs2sCompliment(x)
1028f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com#define Sk2sComplimentAsScalar(x)    Sk2sComplimentAsFloat(x)
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
105