1 /*
2  * Copyright (C) 2018-2021 Intel Corporation
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  */
7 
8 #pragma once
9 #include "shared/source/helpers/vec.h"
10 
11 #include <algorithm>
12 #include <cmath>
13 #include <cstdint>
14 #include <cstdio>
15 #include <cstdlib>
16 #include <limits>
17 
18 namespace Math {
19 
nextPowerOfTwo(uint32_t value)20 constexpr uint32_t nextPowerOfTwo(uint32_t value) {
21     --value;
22     value |= value >> 1;
23     value |= value >> 2;
24     value |= value >> 4;
25     value |= value >> 8;
26     value |= value >> 16;
27     ++value;
28     return value;
29 }
30 
nextPowerOfTwo(uint64_t value)31 constexpr uint64_t nextPowerOfTwo(uint64_t value) {
32     --value;
33     value |= value >> 1;
34     value |= value >> 2;
35     value |= value >> 4;
36     value |= value >> 8;
37     value |= value >> 16;
38     value |= value >> 32;
39     ++value;
40     return value;
41 }
42 
prevPowerOfTwo(uint32_t value)43 constexpr uint32_t prevPowerOfTwo(uint32_t value) {
44     value |= value >> 1;
45     value |= value >> 2;
46     value |= value >> 4;
47     value |= value >> 8;
48     value |= value >> 16;
49     return (value - (value >> 1));
50 }
51 
prevPowerOfTwo(uint64_t value)52 constexpr uint64_t prevPowerOfTwo(uint64_t value) {
53     value |= value >> 1;
54     value |= value >> 2;
55     value |= value >> 4;
56     value |= value >> 8;
57     value |= value >> 16;
58     value |= value >> 32;
59     return (value - (value >> 1));
60 }
61 
getMinLsbSet(uint32_t value)62 inline uint32_t getMinLsbSet(uint32_t value) {
63     static const uint8_t multiplyDeBruijnBitPosition[32] = {
64         0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
65         31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9};
66     auto invert = -static_cast<int64_t>(value);
67     value &= static_cast<uint32_t>(invert);
68     return multiplyDeBruijnBitPosition[static_cast<uint32_t>(value * 0x077CB531U) >> 27];
69 }
70 
log2(uint32_t value)71 constexpr uint32_t log2(uint32_t value) {
72     if (value == 0) {
73         return 32;
74     }
75     uint32_t exponent = 0u;
76     while (value >>= 1) {
77         exponent++;
78     }
79     return exponent;
80 }
81 
log2(uint64_t value)82 constexpr uint32_t log2(uint64_t value) {
83     if (value == 0) {
84         return 64;
85     }
86     uint32_t exponent = 0;
87     while (value >>= 1) {
88         exponent++;
89     }
90     return exponent;
91 }
92 
93 union FloatConversion {
94     uint32_t u;
95     float f;
96 };
97 
98 // clang-format off
99 static const FloatConversion PosInfinity = {0x7f800000};
100 static const FloatConversion NegInfinity = {0xff800000};
101 static const FloatConversion Nan         = {0x7fc00000};
102 // clang-format on
103 
float2Half(float f)104 inline uint16_t float2Half(float f) {
105     FloatConversion u;
106     u.f = f;
107 
108     uint32_t fsign = (u.u >> 16) & 0x8000;
109     float x = std::fabs(f);
110 
111     //Nan
112     if (x != x) {
113         u.u >>= (24 - 11);
114         u.u &= 0x7fff;
115         u.u |= 0x0200; //silence the NaN
116         return u.u | fsign;
117     }
118 
119     // overflow
120     if (x >= std::ldexp(1.0f, 16)) {
121         if (x == PosInfinity.f)
122             return 0x7c00 | fsign;
123 
124         return 0x7bff | fsign;
125     }
126 
127     // underflow
128     if (x < std::ldexp(1.0f, -24))
129         return fsign; // The halfway case can return 0x0001 or 0. 0 is even.
130 
131     // half denormal
132     if (x < std::ldexp(1.0f, -14)) {
133         x *= std::ldexp(1.0f, 24);
134         return (uint16_t)((int)x | fsign);
135     }
136 
137     u.u &= 0xFFFFE000U;
138     u.u -= 0x38000000U;
139 
140     return (u.u >> (24 - 11)) | fsign;
141 }
142 
isDivisibleByPowerOfTwoDivisor(uint32_t number,uint32_t divisor)143 constexpr bool isDivisibleByPowerOfTwoDivisor(uint32_t number, uint32_t divisor) {
144     return (number & (divisor - 1)) == 0;
145 }
146 
computeTotalElementsCount(const Vec3<size_t> & inputVector)147 constexpr size_t computeTotalElementsCount(const Vec3<size_t> &inputVector) {
148     size_t minElementCount = 1;
149     auto xDim = std::max(minElementCount, inputVector.x);
150     auto yDim = std::max(minElementCount, inputVector.y);
151     auto zDim = std::max(minElementCount, inputVector.z);
152     return xDim * yDim * zDim;
153 }
154 
155 template <typename T>
isPow2(T val)156 constexpr bool isPow2(T val) {
157     return val != 0 && (val & (val - 1)) == 0;
158 }
159 
160 template <typename T>
ffs(T v)161 constexpr T ffs(T v) {
162     if (v == 0) {
163         return std::numeric_limits<T>::max();
164     }
165 
166     for (T i = 0; i < sizeof(T) * 8; ++i) {
167         if (0 != (v & (1ULL << i))) {
168             return i;
169         }
170     }
171 
172     std::abort();
173 }
174 
divideAndRoundUp(size_t dividend,size_t divisor)175 constexpr size_t divideAndRoundUp(size_t dividend, size_t divisor) {
176     return (dividend + divisor - 1) / divisor;
177 }
178 
179 } // namespace Math
180