Tips on using std::vector
http://www.codeguru.com/cpp/cpp/cpp_mfc/stl/article.php/c4027/
Traits
Concepts
http://www.cantrip.org/traits.html
Some uses
http://www.gotw.ca/gotw/071.htm#5
Hierarchy Wide Traits
http://erdani.org/publications/traits_on_steroids.html
Is Pointer Trait
template <typename T> class IsPointer
{
public:
enum
{
Answer = false
};
};
template <typename T> class IsPointer<T*>
{
public:
enum
{
Answer = true
};
};
Usage
if(IsPointer<T>::Answer)
{
// Yes
}
Is Class D Derived From Class B
template <class D, class B> class IsDerivedFrom
{
private:
static bool Test(void*)
{
return false;
}
static bool Test(B*)
{
return true;
}
public:
static bool Answer()
{
D* ptrD = 0;
return Test(ptrD);
}
};
// Specialization of IsDerivedFrom
template <class D, class B> class IsDerivedFrom<D*,B*>
{
private:
static bool Test(void*)
{
return false;
}
static bool Test(B*)
{
return true;
}
public:
static bool Answer()
{
D* ptrD = 0;
return Test(ptrD);
}
};
Usage
if(IsDerivedFrom<Derived,Base>::Answer())
{
// YES
}
note the template specialization is there so that if the user passes in pointers to classes as the paramaters it returns the same result as if they were classes i.e.
if(IsDerivedFrom<Derived*,Bass*>::Answer())
{
// YES
}
Function Prototypes for serialization
class Object
{
friend std::ostream& operator<< (std::ostream& o, const Object& obj);
friend std::istream& operator>> (std::istream& i, Object& obj);
friend std::ostream& operator<< (std::ostream& o, const Object*ptrObj);
friend std::istream& operator>> (std::istream& i, Object*&ptrObj);
}
Note, if you derive from Object then will automagically call the methods in the base class above on that object except for the last one which will need to be implemented for each class type. A good way to do this is to #define it as boiler plate code.
x86 Intrinsics Reference
On x86 the 128bits are stored backwards - so if you look at the memory address of say order you will see the numbers reversed - i.e. 4 3 2 1
Shuffle access the numbers in this order - i.e. 0 is the float at the address (float*)(&order)[0] i.e. 4.0 not 1.0 as you might expect index 0 to be. A simple way to convert between the index and the position within the float is to do 3-index.
#include "stdafx.h"
#include <intrin.h>
int _tmain(int argc, _TCHAR* argv[])
{
__m128 x, y, z, w;
__m128 order = _mm_set_ps(1.0f, 2.0f, 3.0f, 4.0f); // Stored in memory as 4 3 2 1
__m128 orderSame = _mm_shuffle_ps(order, order, _MM_SHUFFLE(3, 2, 1, 0));
// Subtract index from 3 - so [3-3] is element 0 i.e. 1.0
__m128 orderReverse = _mm_shuffle_ps(order, order, _MM_SHUFFLE(0, 1, 2, 3));
// [3-0] is element 3 i.e. 4.0
x = _mm_set_ps(1.0f, -1.0f, -1.0f, -1.0f); // Stored as -1 -1 -1 1
y = _mm_set_ps(2.0f, -2.0f, -2.0f, -2.0f); // Stored as -2 -2 -2 2
z = _mm_set_ps(3.0f, -3.0f, -3.0f, -3.0f); // Stored as -3 -3 -3 3
w = _mm_set_ps(4.0f, -4.0f, -4.0f, -4.0f); // Stored as -4 -4 -4 4
// Index 0 is on the left first two numbers are from the 2nd parameter
//
__m128 xxyy = _mm_shuffle_ps(x, y, _MM_SHUFFLE(3, 3, 3, 3)); // y3 y3 x3 x3 = 2 2 1 1 - Stored as 1 1 2 2
__m128 zzww = _mm_shuffle_ps(z, w, _MM_SHUFFLE(3, 3, 3, 3)); // z3 z3 w3 w3 = 4 4 3 3 - Stored as 3 3 4 4
__m128 xyzw = _mm_shuffle_ps(zzww, xxyy, _MM_SHUFFLE(0, 2, 0, 2));
// fp[0] = xxyy[3-0] = 4
// fp[1] = xxyy[3-2] = 3
// fp[2] = zzww[3-0] = 2
// fp[2] = zzww[3-0] = 1
return 0;
}
__m128 one = _mm_set_ps(1.0f, 1.0f, 1.0f, 1.0f); // 1 1 1 1
__m128 two = _mm_set_ps(2.0f, 2.0f, 2.0f, 2.0f); // 2 2 2 2
__m128 sumss = _mm_add_ss(one, two); // 3 1 1 1
__m128 sums = _mm_add_ps(one, two); // 3 3 3 3
Using Files and ofstream, ifstream
http://www.cplusplus.com/doc/tutorial/files.html