2007-05-09 23:01:11 +02:00
|
|
|
/**
|
|
|
|
* =========================================================================
|
|
|
|
* File : bits.h
|
|
|
|
* Project : 0 A.D.
|
|
|
|
* Description : bit-twiddling.
|
|
|
|
* =========================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
// license: GPL; see lib/license.txt
|
|
|
|
|
|
|
|
#ifndef INCLUDED_BITS
|
|
|
|
#define INCLUDED_BITS
|
|
|
|
|
|
|
|
/**
|
2008-09-06 23:15:53 +02:00
|
|
|
* value of bit number <n>.
|
2007-05-09 23:01:11 +02:00
|
|
|
*
|
2008-09-06 23:15:53 +02:00
|
|
|
* @param n bit index.
|
|
|
|
*
|
|
|
|
* requirements:
|
|
|
|
* - T should be an unsigned type
|
|
|
|
* - n must be in [0, CHAR_BIT*sizeof(T)), else the result is undefined!
|
2007-05-09 23:01:11 +02:00
|
|
|
**/
|
2008-09-06 23:15:53 +02:00
|
|
|
template<typename T>
|
|
|
|
T Bit(size_t n)
|
|
|
|
{
|
|
|
|
const T one = T(1);
|
|
|
|
return (one << n);
|
|
|
|
}
|
2007-05-09 23:01:11 +02:00
|
|
|
|
|
|
|
/**
|
2008-09-06 23:15:53 +02:00
|
|
|
* pretty much the same as Bit<unsigned>.
|
|
|
|
* this is intended for the initialization of enum values, where a
|
|
|
|
* compile-time constant is required.
|
2007-05-09 23:01:11 +02:00
|
|
|
**/
|
2008-09-06 23:15:53 +02:00
|
|
|
#define BIT(n) (1u << (n))
|
|
|
|
|
2007-05-09 23:01:11 +02:00
|
|
|
|
2008-05-12 20:15:08 +02:00
|
|
|
template<typename T>
|
|
|
|
bool IsBitSet(T value, size_t index)
|
|
|
|
{
|
2008-09-06 23:15:53 +02:00
|
|
|
const T bit = Bit<T>(index);
|
2008-05-12 20:15:08 +02:00
|
|
|
return (value & bit) != 0;
|
|
|
|
}
|
|
|
|
|
2007-05-09 23:01:11 +02:00
|
|
|
|
|
|
|
// these are declared in the header and inlined to aid compiler optimizations
|
|
|
|
// (they can easily end up being time-critical).
|
|
|
|
// note: GCC can't inline extern functions, while VC's "Whole Program
|
|
|
|
// Optimization" can.
|
|
|
|
|
|
|
|
/**
|
|
|
|
* a mask that includes the lowest N bits
|
|
|
|
*
|
|
|
|
* @param num_bits number of bits in mask
|
|
|
|
**/
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 20:48:32 +02:00
|
|
|
template<typename T>
|
2008-06-01 10:25:12 +02:00
|
|
|
T bit_mask(size_t numBits)
|
2007-05-09 23:01:11 +02:00
|
|
|
{
|
2008-06-01 10:25:12 +02:00
|
|
|
if(numBits == 0) // prevent shift count == bitsInT, which would be undefined.
|
|
|
|
return 0;
|
2008-09-18 13:27:55 +02:00
|
|
|
// notes:
|
|
|
|
// - the perhaps more intuitive (1 << numBits)-1 cannot
|
|
|
|
// handle numBits == bitsInT, but this implementation does.
|
|
|
|
// - though bulky, the below statements avoid sign-conversion warnings.
|
2008-06-01 10:25:12 +02:00
|
|
|
const T bitsInT = sizeof(T)*CHAR_BIT;
|
2008-09-18 13:27:55 +02:00
|
|
|
T mask(0);
|
|
|
|
mask = ~mask;
|
2008-06-16 20:36:36 +02:00
|
|
|
mask >>= T(bitsInT-numBits);
|
|
|
|
return mask;
|
2007-05-09 23:01:11 +02:00
|
|
|
}
|
|
|
|
|
2007-05-21 21:22:55 +02:00
|
|
|
|
2007-05-09 23:01:11 +02:00
|
|
|
/**
|
|
|
|
* extract the value of bits hi_idx:lo_idx within num
|
|
|
|
*
|
|
|
|
* example: bits(0x69, 2, 5) == 0x0A
|
|
|
|
*
|
|
|
|
* @param num number whose bits are to be extracted
|
|
|
|
* @param lo_idx bit index of lowest bit to include
|
|
|
|
* @param hi_idx bit index of highest bit to include
|
|
|
|
* @return value of extracted bits.
|
|
|
|
**/
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 20:48:32 +02:00
|
|
|
template<typename T>
|
|
|
|
inline T bits(T num, size_t lo_idx, size_t hi_idx)
|
2007-05-09 23:01:11 +02:00
|
|
|
{
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 20:48:32 +02:00
|
|
|
const size_t count = (hi_idx - lo_idx)+1; // # bits to return
|
2008-06-01 10:25:12 +02:00
|
|
|
T result = num >> T(lo_idx);
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 20:48:32 +02:00
|
|
|
result &= bit_mask<T>(count);
|
2007-05-09 23:01:11 +02:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 20:48:32 +02:00
|
|
|
/**
|
|
|
|
* @return number of 1-bits in mask
|
|
|
|
**/
|
|
|
|
template<typename T>
|
|
|
|
size_t PopulationCount(T mask)
|
2007-05-21 21:22:55 +02:00
|
|
|
{
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 20:48:32 +02:00
|
|
|
// note: a more complex but probably faster method is given at
|
|
|
|
// http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
|
|
|
|
|
|
|
|
size_t num1Bits = 0;
|
|
|
|
while(mask)
|
|
|
|
{
|
|
|
|
mask &= mask-1; // clear least significant 1-bit
|
|
|
|
num1Bits++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return num1Bits;
|
2007-05-21 21:22:55 +02:00
|
|
|
}
|
|
|
|
|
2007-05-09 23:01:11 +02:00
|
|
|
/**
|
|
|
|
* @return whether the given number is a power of two.
|
|
|
|
**/
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 20:48:32 +02:00
|
|
|
template<typename T>
|
|
|
|
bool is_pow2(T n)
|
2008-03-29 19:29:26 +01:00
|
|
|
{
|
|
|
|
// 0 would pass the test below but isn't a POT.
|
|
|
|
if(n == 0)
|
|
|
|
return false;
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 20:48:32 +02:00
|
|
|
return (n & (n-1)) == 0;
|
2008-03-29 19:29:26 +01:00
|
|
|
}
|
|
|
|
|
2007-05-09 23:01:11 +02:00
|
|
|
/**
|
2008-05-13 07:51:25 +02:00
|
|
|
* ceil(log2(x))
|
2007-05-09 23:01:11 +02:00
|
|
|
*
|
2008-05-13 07:51:25 +02:00
|
|
|
* @param x (unsigned integer)
|
2008-06-26 22:12:42 +02:00
|
|
|
* @return ceiling of the base-2 logarithm (i.e. rounded up) or
|
|
|
|
* zero if the input is zero.
|
2007-05-09 23:01:11 +02:00
|
|
|
**/
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 20:48:32 +02:00
|
|
|
template<typename T>
|
|
|
|
size_t ceil_log2(T x)
|
2008-03-29 19:29:26 +01:00
|
|
|
{
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 20:48:32 +02:00
|
|
|
T bit = 1;
|
|
|
|
size_t log = 0;
|
2008-03-29 19:29:26 +01:00
|
|
|
while(bit < x && bit != 0) // must detect overflow
|
|
|
|
{
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 20:48:32 +02:00
|
|
|
log++;
|
|
|
|
bit *= 2;
|
2008-03-29 19:29:26 +01:00
|
|
|
}
|
|
|
|
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 20:48:32 +02:00
|
|
|
return log;
|
2008-03-29 19:29:26 +01:00
|
|
|
}
|
|
|
|
|
2007-05-09 23:01:11 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* floor(log2(f))
|
|
|
|
* fast, uses the FPU normalization hardware.
|
|
|
|
*
|
|
|
|
* @param f (float) input; MUST be > 0, else results are undefined.
|
|
|
|
* @return floor of the base-2 logarithm (i.e. rounded down).
|
|
|
|
**/
|
|
|
|
extern int floor_log2(const float x);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* round up to next larger power of two.
|
|
|
|
**/
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 20:48:32 +02:00
|
|
|
template<typename T>
|
|
|
|
T round_up_to_pow2(T x)
|
|
|
|
{
|
|
|
|
return T(1) << ceil_log2(x);
|
|
|
|
}
|
2007-05-09 23:01:11 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* round number up/down to the next given multiple.
|
|
|
|
*
|
|
|
|
* @param multiple: must be a power of two.
|
|
|
|
**/
|
2008-05-01 17:41:42 +02:00
|
|
|
template<typename T>
|
|
|
|
T round_up(T n, T multiple)
|
|
|
|
{
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 20:48:32 +02:00
|
|
|
debug_assert(is_pow2(multiple));
|
2008-05-01 17:41:42 +02:00
|
|
|
const T result = (n + multiple-1) & ~(multiple-1);
|
|
|
|
debug_assert(n <= result && result < n+multiple);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
T round_down(T n, T multiple)
|
|
|
|
{
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 20:48:32 +02:00
|
|
|
debug_assert(is_pow2(multiple));
|
2008-05-01 17:41:42 +02:00
|
|
|
const T result = n & ~(multiple-1);
|
|
|
|
debug_assert(result <= n && n < result+multiple);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2007-05-09 23:01:11 +02:00
|
|
|
|
2007-12-20 21:09:19 +01:00
|
|
|
template<typename T>
|
|
|
|
bool IsAligned(T t, uintptr_t multiple)
|
|
|
|
{
|
|
|
|
return ((uintptr_t)t % multiple) == 0;
|
|
|
|
}
|
|
|
|
|
2007-05-09 23:01:11 +02:00
|
|
|
#endif // #ifndef INCLUDED_BITS
|