kolibrios-fun/contrib/other/uarm/math64.c

197 lines
2.4 KiB
C
Raw Normal View History

#include "math64.h"
#ifndef COMPILER_SUPPORTS_LONG_LONG
UInt64 u64_from_halves(UInt32 hi, UInt32 lo){
UInt64 r;
r.lo = lo;
r.hi = hi;
return r;
}
UInt64 u64_32_to_64(UInt32 v){
UInt64 r;
r.hi = 0;
r.lo = v;
return r;
}
UInt32 u64_64_to_32(UInt64 v){
return v.lo;
}
UInt32 u64_get_hi(UInt64 v){
return v.hi;
}
UInt64 u64_add(UInt64 a, UInt64 b){
UInt64 r;
r.lo = a.lo + b.lo;
r.hi = a.hi + b.hi;
if(r.lo < a.lo) r.hi++;
return r;
}
UInt64 u64_add32(UInt64 a, UInt32 b){
UInt64 r;
r.lo = a.lo + b;
r.hi = a.hi;
if(r.lo < a.lo) r.hi++;
return r;
}
UInt64 u64_umul3232(UInt32 a, UInt32 b){
UInt64 r;
UInt32 ah, al, bh, bl;
ah = a >> 16;
al = a & 0xFFFFUL;
bh = b >> 16;
bl = b & 0xFFFFUL;
r = u64_shl(u64_32_to_64(ah * bh), 16);
r = u64_add32(r, ah * bl);
r = u64_add32(r, al * bh);
r = u64_add32(u64_shl(r, 16), al * bl);
return r;
}
UInt64 u64_smul3232(Int32 a, Int32 b){
Boolean negative = false;
UInt64 r;
if(a < 0){
a = -a;
negative = !negative;
}
if(b < 0){
b = -b;
negative = !negative;
}
r = u64_umul3232(a, b);
if(negative){
r.hi = ~r.hi; //negate r
r.lo = ~r.lo;
r = u64_inc(r);
}
return r;
}
UInt64 u64_shr(UInt64 v, unsigned bits){
UInt64 a = v;
while(bits >= 32){
a.lo = a.hi;
a.hi = 0;
bits -= 32;
}
a.lo = (a.lo >> bits) + (a.hi << (32 - bits));
a.hi >>= bits;
return a;
}
UInt64 u64_shl(UInt64 v, unsigned bits){
UInt64 a = v;
while(bits >= 32){
a.hi = a.lo;
a.lo = 0;
bits -= 32;
}
a.hi = (a.hi << bits) + (a.lo >> (32 - bits));
a.lo <<= bits;
return a;
}
UInt64 u64_xtnd32(UInt64 v){
UInt64 a = v;
if(a.lo & 0x80000000UL) a.hi = 0xFFFFFFFFUL;
return a;
}
Boolean u64_isZero(UInt64 a){
return a.lo == 0 && a.hi == 0;
}
UInt64 u64_inc(UInt64 v){
UInt64 a = v;
if(!++a.lo) a.hi++;
return a;
}
UInt64 u64_and(UInt64 a, UInt64 b){
UInt64 r;
r.lo = a.lo & b.lo;
r.hi = a.hi & b.hi;
return r;
}
UInt64 u64_zero(void){
UInt64 r;
r.lo = 0;
r.hi = 0;
return r;
}
UInt64 u64_sub(UInt64 a, UInt64 b){
UInt64 bn;
bn.lo = ~b.lo;
bn.hi = ~b.hi;
bn = u64_inc(bn);
return u64_add(a, bn);
}
#endif