#ifndef _CPU_MATH_H_ #define _CPU_MATH_H_ #include uint32_t cpuMathUint44Div1000ToUint32_slow_path(uint64_t val); static inline uint32_t cpuMathUint44Div1000ToUint32(uint64_t val) { if (val >> 32) return cpuMathUint44Div1000ToUint32_slow_path(val); else return (uint32_t)val / 1000; } uint64_t cpuMathU64DivByU16(uint64_t val, uint32_t divBy /* 16 bits max*/); //DO NOT USE ON NON_COMPILE-TIME-CONSTANT VALUES OF u16, use cpuMathU64DivByU16() #define U64_DIV_BY_CONST_U16(u64, u16) \ ({ \ const uint16_t divBy = u16; \ const uint64_t _num = u64; \ const uint32_t numHi = _num >> 32, numLo = _num; \ uint32_t t1, t2, t3, t4, t5; \ \ t1 = numHi / divBy; \ t2 = numHi % divBy; \ t2 <<= 16; \ t2 += numLo >> 16; \ t3 = t2 / divBy; \ t4 = t2 % divBy; \ t4 <<= 16; \ t4 += numLo & 0xFFFF; \ t5 = t4 / divBy; \ \ (((uint64_t)t1) << 32) + (((uint64_t)t3) << 16) + t5; \ }) //correctly handles 0, 1, powers of 2, and all else to calculate "(1 << 64) / val" //do not even think of using this on non-compile-time-constant values! #define U64_RECIPROCAL_CALCULATE(val) ((val) & ((val) - 1)) ? (0xffffffffffffffffull / (val)) : (((val) <= 1) ? 0xffffffffffffffffull : (0x8000000000000000ull / ((val) >> 1))) uint64_t cpuMathRecipAssistedUdiv64by64(uint64_t num, uint64_t denom, uint64_t denomRecip); uint64_t cpuMathRecipAssistedUdiv64by32(uint64_t num, uint32_t denom, uint64_t denomRecip); #define U64_DIV_BY_U64_CONSTANT(val, constantVal) cpuMathRecipAssistedUdiv64by64((val), (constantVal), U64_RECIPROCAL_CALCULATE(constantVal)) #define I64_DIV_BY_I64_CONSTANT(val, constantVal) \ ({ \ char neg = ((uint32_t)((val) >> 32) ^ (uint32_t)(((uint64_t)(constantVal)) >> 32)) >> 31; \ uint64_t valP = (val < 0) ? -val : val; \ const uint64_t conP = (constantVal < 0) ? -constantVal : constantVal; \ uint64_t ret = cpuMathRecipAssistedUdiv64by64(valP, conP, U64_RECIPROCAL_CALCULATE(conP)); \ if (neg) \ ret =-ret; \ ret; \ }) #endif