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