diff options
| author | click <none@none> | 2010-06-05 00:59:25 +0200 |
|---|---|---|
| committer | click <none@none> | 2010-06-05 00:59:25 +0200 |
| commit | e77716188861d4aa83b227a90e04a66b63baeb1f (patch) | |
| tree | ce72764181a760314ec851f7535052dcf75649db /dep/src/g3dlite/uint128.cpp | |
| parent | 1426c2970f42a2d065198806f750bf5dd28d580b (diff) | |
HIGHLY EXPERIMENTAL - USE AT YOUR OWN RISK
Implement the use of the new vmap3-format by Lynx3d (mad props to you for this, and thanks for the talks earlier)
+ reduced Vmap size to less than one third, and improve precision
+ indoor/outdoor check which allows automatic unmounting of players
+ additional area information from WMOAreaTable.dbc, removed existing "hacks"
+ WMO liquid information for swimming and fishing correctly in buildings/cities/caves/instances (lava and slime WILL hurt from now on!)
- buildfiles for windows are not properly done, and will need to be sorted out
NOTE: Do NOT annoy Lynx3d about this, any issues with this "port" is entirely our fault !
THIS REVISION IS CONSIDERED UNSTABLE AND CONTAINS WORK IN PROGRESS - USE AT YOUR OWN RISK!
--HG--
branch : trunk
Diffstat (limited to 'dep/src/g3dlite/uint128.cpp')
| -rw-r--r-- | dep/src/g3dlite/uint128.cpp | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/dep/src/g3dlite/uint128.cpp b/dep/src/g3dlite/uint128.cpp new file mode 100644 index 00000000000..1f596fc3e51 --- /dev/null +++ b/dep/src/g3dlite/uint128.cpp @@ -0,0 +1,155 @@ +/** + @file uint128.cpp + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + @author Kyle Whitson + + @created 2008-07-17 + @edited 2008-07-17 + */ + +#include "G3D/uint128.h" + +namespace G3D { + +/** Adds two 64-bit integers, placing the result and the overflow into 64-bit integers.*/ +static void addAndCarry(const uint64& _a, const uint64& _b, uint64& carry, uint64& result) { + + // Break each number into 4 32-bit chunks. Since we are using uints, right-shifting will fill with zeros. + // This eliminates the need to and with 0xFFFFFFFF. + uint32 a [2] = {_a & 0xFFFFFFFF, _a >> 32}; + uint32 b [2] = {_b & 0xFFFFFFFF, _b >> 32}; + + uint64 tmp = uint64(a[0]) + b[0]; + + result = tmp & 0xFFFFFFFF; + uint32 c = tmp >> 32; + + tmp = uint64(c) + a[1] + b[1]; + result += tmp << 32; + carry = (tmp >> 32); +} + +/** Multiplies two unsigned 64-bit integers, placing the result into one 64-bit int and the overflow into another.*/ +void multiplyAndCarry(const uint64& _a, const uint64& _b, uint64& carry, uint64& result) { + + // Break each number into 4 32-bit chunks. Since we are using uints, right-shifting will fill with zeros. + // This eliminates the need to and with 0xFFFFFFFF. + uint32 a [2] = {_a & 0xFFFFFFFF, _a >> 32}; + uint32 b [2] = {_b & 0xFFFFFFFF, _b >> 32}; + + uint64 prod [2][2]; + for(int i = 0; i < 2; ++i) { + for(int j = 0; j < 2; ++j) { + prod[i][j] = uint64(a[i]) * b[j]; + } + } + + // The product of the low bits of a and b will always fit into the result + result = prod[0][0]; + + // The product of the high bits of a and b will never fit into the result + carry = prod[1][1]; + + // The high 32 bits of prod[0][1] and prod[1][0] will never fit into the result + carry += prod[0][1] >> 32; + carry += prod[1][0] >> 32; + + uint64 tmp; + addAndCarry(result, (prod[0][1] << 32), tmp, result); + carry += tmp; + addAndCarry(result, (prod[1][0] << 32), tmp, result); + carry += tmp; +} + + +uint128::uint128(const uint64& hi, const uint64& lo) : hi(hi), lo(lo) { +} + +uint128::uint128(const uint64& lo) : hi(0), lo(lo) { +} + +uint128& uint128::operator+=(const uint128& x) { + + G3D::uint64 carry; + addAndCarry(lo, x.lo, carry, lo); + + // Adding the carry will change hi. Save the old hi bits in case this == x. + const uint64 xHi = x.hi; + hi += carry; + hi += xHi; + return *this; +} + +uint128& uint128::operator*=(const uint128& x) { + + // The low bits will get overwritten when doing the multiply, so back up both (in case &x == this) + const uint64 oldLo = lo; + const uint64 oldXLo = x.lo; + + G3D::uint64 carry; + multiplyAndCarry(oldLo, oldXLo, carry, lo); + + // Overflow doesn't matter here because the result is going into hi - any overflow will exceed the capacity of a 128-bit number + // Note: hi * x.hi will always overflow, since (x * 2^64) * (y * 2^64) = x*y*(2^128). The largest number expressable in 128 bits is + // 2^128 - 1. + hi = carry + (oldLo * x.hi) + (hi * oldXLo); + + return *this; +} + +uint128& uint128::operator^=(const uint128& x) { + hi ^= x.hi; + lo ^= x.lo; + return *this; +} + +uint128& uint128::operator&=(const uint128& x) { + hi &= x.hi; + lo &= x.lo; + return *this; +} + +uint128& uint128::operator|=(const uint128& x) { + hi |= x.hi; + lo |= x.lo; + return *this; +} + +bool uint128::operator==(const uint128& x) { + return (hi == x.hi) && (lo == x.lo); +} + +uint128& uint128::operator>>=(const int x) { + + //Before shifting, mask out the bits that will be shifted out of hi. + //Put a 1 in the first bit that will not be lost in the shift, then subtract 1 to get the mask. + uint64 mask = ((uint64)1L << x) - 1; + uint64 tmp = hi & mask; + hi >>= x; + + //Shift lo and add the bits shifted down from hi + lo = (lo >> x) + (tmp << (64 - x)); + + return *this; +} + +uint128& uint128::operator<<=(const int x) { + + //Before shifting, mask out the bits that will be shifted out of lo. + //Put a 1 in the last bit that will be lost in the shift, then subtract 1 to get the logical inverse of the mask. + //A bitwise NOT will then produce the correct mask. + uint64 mask = ~((((uint64)1L) << (64 - x)) - 1); + uint64 tmp = lo & mask; + lo <<= x; + + //Shift hi and add the bits shifted up from lo + hi = (hi << x) + (tmp >> (64 - x)); + + return *this; +} + +uint128 uint128::operator&(const uint128& x) { + return uint128(hi & x.hi, lo & x.lo); +} +} |
