1 #ifndef _CPU_MATH_H_
2 #define _CPU_MATH_H_
3
4 #include <stdint.h>
5
6 uint32_t cpuMathUint44Div1000ToUint32_slow_path(uint64_t val);
7
cpuMathUint44Div1000ToUint32(uint64_t val)8 static inline uint32_t cpuMathUint44Div1000ToUint32(uint64_t val)
9 {
10 if (val >> 32)
11 return cpuMathUint44Div1000ToUint32_slow_path(val);
12 else
13 return (uint32_t)val / 1000;
14 }
15
16 uint64_t cpuMathU64DivByU16(uint64_t val, uint32_t divBy /* 16 bits max*/);
17
18 //DO NOT USE ON NON_COMPILE-TIME-CONSTANT VALUES OF u16, use cpuMathU64DivByU16()
19
20 #define U64_DIV_BY_CONST_U16(u64, u16) \
21 ({ \
22 const uint16_t divBy = u16; \
23 const uint64_t _num = u64; \
24 const uint32_t numHi = _num >> 32, numLo = _num; \
25 uint32_t t1, t2, t3, t4, t5; \
26 \
27 t1 = numHi / divBy; \
28 t2 = numHi % divBy; \
29 t2 <<= 16; \
30 t2 += numLo >> 16; \
31 t3 = t2 / divBy; \
32 t4 = t2 % divBy; \
33 t4 <<= 16; \
34 t4 += numLo & 0xFFFF; \
35 t5 = t4 / divBy; \
36 \
37 (((uint64_t)t1) << 32) + (((uint64_t)t3) << 16) + t5; \
38 })
39
40 //correctly handles 0, 1, powers of 2, and all else to calculate "(1 << 64) / val"
41 //do not even think of using this on non-compile-time-constant values!
42 #define U64_RECIPROCAL_CALCULATE(val) ((val) & ((val) - 1)) ? (0xffffffffffffffffull / (val)) : (((val) <= 1) ? 0xffffffffffffffffull : (0x8000000000000000ull / ((val) >> 1)))
43
44 uint64_t cpuMathRecipAssistedUdiv64by64(uint64_t num, uint64_t denom, uint64_t denomRecip);
45 uint64_t cpuMathRecipAssistedUdiv64by32(uint64_t num, uint32_t denom, uint64_t denomRecip);
46
47 #define U64_DIV_BY_U64_CONSTANT(val, constantVal) cpuMathRecipAssistedUdiv64by64((val), (constantVal), U64_RECIPROCAL_CALCULATE(constantVal))
48 #define I64_DIV_BY_I64_CONSTANT(val, constantVal) \
49 ({ \
50 char neg = ((uint32_t)((val) >> 32) ^ (uint32_t)(((uint64_t)(constantVal)) >> 32)) >> 31; \
51 uint64_t valP = (val < 0) ? -val : val; \
52 const uint64_t conP = (constantVal < 0) ? -constantVal : constantVal; \
53 uint64_t ret = cpuMathRecipAssistedUdiv64by64(valP, conP, U64_RECIPROCAL_CALCULATE(conP)); \
54 if (neg) \
55 ret =-ret; \
56 ret; \
57 })
58
59
60 #endif
61
62