1/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkMathPriv_DEFINED
9#define SkMathPriv_DEFINED
10
11#include "SkMath.h"
12
13#if defined(SK_BUILD_FOR_IOS) && (defined(SK_BUILD_FOR_ARM32) || defined(SK_BUILD_FOR_ARM64))
14// iOS on ARM starts processes with the Flush-To-Zero (FTZ) and
15// Denormals-Are-Zero (DAZ) bits in the fpscr register set.
16// Algorithms that rely on denormalized numbers need alternative implementations.
17// This can also be controlled in SSE with the MXCSR register,
18// x87 with FSTCW/FLDCW, and mips with FCSR. This should be detected at runtime,
19// or the library built one way or the other more generally (by the build).
20#define SK_CPU_FLUSH_TO_ZERO
21#endif
22
23/** Returns -1 if n < 0, else returns 0
24 */
25#define SkExtractSign(n)    ((int32_t)(n) >> 31)
26
27/** If sign == -1, returns -n, else sign must be 0, and returns n.
28 Typically used in conjunction with SkExtractSign().
29 */
30static inline int32_t SkApplySign(int32_t n, int32_t sign) {
31    SkASSERT(sign == 0 || sign == -1);
32    return (n ^ sign) - sign;
33}
34
35/** Return x with the sign of y */
36static inline int32_t SkCopySign32(int32_t x, int32_t y) {
37    return SkApplySign(x, SkExtractSign(x ^ y));
38}
39
40/** Given a positive value and a positive max, return the value
41 pinned against max.
42 Note: only works as long as max - value doesn't wrap around
43 @return max if value >= max, else value
44 */
45static inline unsigned SkClampUMax(unsigned value, unsigned max) {
46    if (value > max) {
47        value = max;
48    }
49    return value;
50}
51
52// If a signed int holds min_int (e.g. 0x80000000) it is undefined what happens when
53// we negate it (even though we *know* we're 2's complement and we'll get the same
54// value back). So we create this helper function that casts to size_t (unsigned) first,
55// to avoid the complaint.
56static inline size_t sk_negate_to_size_t(int32_t value) {
57#if defined(_MSC_VER)
58#pragma warning(push)
59#pragma warning(disable : 4146)  // Thanks MSVC, we know what we're negating an unsigned
60#endif
61    return -static_cast<size_t>(value);
62#if defined(_MSC_VER)
63#pragma warning(pop)
64#endif
65}
66
67///////////////////////////////////////////////////////////////////////////////
68
69/** Return a*b/255, truncating away any fractional bits. Only valid if both
70 a and b are 0..255
71 */
72static inline U8CPU SkMulDiv255Trunc(U8CPU a, U8CPU b) {
73    SkASSERT((uint8_t)a == a);
74    SkASSERT((uint8_t)b == b);
75    unsigned prod = a*b + 1;
76    return (prod + (prod >> 8)) >> 8;
77}
78
79/** Return (a*b)/255, taking the ceiling of any fractional bits. Only valid if
80 both a and b are 0..255. The expected result equals (a * b + 254) / 255.
81 */
82static inline U8CPU SkMulDiv255Ceiling(U8CPU a, U8CPU b) {
83    SkASSERT((uint8_t)a == a);
84    SkASSERT((uint8_t)b == b);
85    unsigned prod = a*b + 255;
86    return (prod + (prod >> 8)) >> 8;
87}
88
89/** Just the rounding step in SkDiv255Round: round(value / 255)
90 */
91static inline unsigned SkDiv255Round(unsigned prod) {
92    prod += 128;
93    return (prod + (prod >> 8)) >> 8;
94}
95
96static inline float SkPinToUnitFloat(float x) {
97    return SkTMin(SkTMax(x, 0.0f), 1.0f);
98}
99
100/**
101 * Swap byte order of a 4-byte value, e.g. 0xaarrggbb -> 0xbbggrraa.
102 */
103#if defined(_MSC_VER)
104    #include <intrin.h>
105    static inline uint32_t SkBSwap32(uint32_t v) { return _byteswap_ulong(v); }
106#else
107    static inline uint32_t SkBSwap32(uint32_t v) { return __builtin_bswap32(v); }
108#endif
109
110//! Returns the number of leading zero bits (0...32)
111int SkCLZ_portable(uint32_t);
112
113#ifndef SkCLZ
114    #if defined(SK_BUILD_FOR_WIN)
115        #include <intrin.h>
116
117        static inline int SkCLZ(uint32_t mask) {
118            if (mask) {
119                unsigned long index;
120                _BitScanReverse(&index, mask);
121                // Suppress this bogus /analyze warning. The check for non-zero
122                // guarantees that _BitScanReverse will succeed.
123#pragma warning(suppress : 6102) // Using 'index' from failed function call
124                return index ^ 0x1F;
125            } else {
126                return 32;
127            }
128        }
129    #elif defined(SK_CPU_ARM32) || defined(__GNUC__) || defined(__clang__)
130        static inline int SkCLZ(uint32_t mask) {
131            // __builtin_clz(0) is undefined, so we have to detect that case.
132            return mask ? __builtin_clz(mask) : 32;
133        }
134    #else
135        #define SkCLZ(x)    SkCLZ_portable(x)
136    #endif
137#endif
138
139/**
140 *  Returns the smallest power-of-2 that is >= the specified value. If value
141 *  is already a power of 2, then it is returned unchanged. It is undefined
142 *  if value is <= 0.
143 */
144static inline int SkNextPow2(int value) {
145    SkASSERT(value > 0);
146    return 1 << (32 - SkCLZ(value - 1));
147}
148
149/**
150*  Returns the largest power-of-2 that is <= the specified value. If value
151*  is already a power of 2, then it is returned unchanged. It is undefined
152*  if value is <= 0.
153*/
154static inline int SkPrevPow2(int value) {
155    SkASSERT(value > 0);
156    return 1 << (32 - SkCLZ(value >> 1));
157}
158
159/**
160 *  Returns the log2 of the specified value, were that value to be rounded up
161 *  to the next power of 2. It is undefined to pass 0. Examples:
162 *  SkNextLog2(1) -> 0
163 *  SkNextLog2(2) -> 1
164 *  SkNextLog2(3) -> 2
165 *  SkNextLog2(4) -> 2
166 *  SkNextLog2(5) -> 3
167 */
168static inline int SkNextLog2(uint32_t value) {
169    SkASSERT(value != 0);
170    return 32 - SkCLZ(value - 1);
171}
172
173/**
174*  Returns the log2 of the specified value, were that value to be rounded down
175*  to the previous power of 2. It is undefined to pass 0. Examples:
176*  SkPrevLog2(1) -> 0
177*  SkPrevLog2(2) -> 1
178*  SkPrevLog2(3) -> 1
179*  SkPrevLog2(4) -> 2
180*  SkPrevLog2(5) -> 2
181*/
182static inline int SkPrevLog2(uint32_t value) {
183    SkASSERT(value != 0);
184    return 32 - SkCLZ(value >> 1);
185}
186
187///////////////////////////////////////////////////////////////////////////////
188
189/**
190 *  Return the next power of 2 >= n.
191 */
192static inline uint32_t GrNextPow2(uint32_t n) {
193    return n ? (1 << (32 - SkCLZ(n - 1))) : 1;
194}
195
196/**
197 * Returns the next power of 2 >= n or n if the next power of 2 can't be represented by size_t.
198 */
199static inline size_t GrNextSizePow2(size_t n) {
200    constexpr int kNumSizeTBits = 8 * sizeof(size_t);
201    constexpr size_t kHighBitSet = size_t(1) << (kNumSizeTBits - 1);
202
203    if (!n) {
204        return 1;
205    } else if (n >= kHighBitSet) {
206        return n;
207    }
208
209    n--;
210    uint32_t shift = 1;
211    while (shift < kNumSizeTBits) {
212        n |= n >> shift;
213        shift <<= 1;
214    }
215    return n + 1;
216}
217
218// conservative check. will return false for very large values that "could" fit
219template <typename T> static inline bool SkFitsInFixed(T x) {
220    return SkTAbs(x) <= 32767.0f;
221}
222
223#endif
224