blob: 70fb98a08d12685231aadd1bc036e72f78d186e7 [file] [log] [blame]
#ifndef _CPU_MATH_H_
#define _CPU_MATH_H_
#include <stdint.h>
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