PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Problem mit Optimierungen (C++, VS .Net 2003)


Neomi
2006-01-22, 20:15:18
Für eine komfortablere Programmierung habe ich mir Arbitrary Swizzling für Vektoren (2D, 3D und 4D, letztere aber nicht im Codeauszug enthalten) nachgebaut. Hier erstmal ein wenig Code aus der relevanten Header-Datei:

#ifndef _INC_VECTORS_H_
#define _INC_VECTORS_H_

// low level macros

#define Vector2_AssignOp(Op,Index0,Index1) \
Vector2 operator Op (Vector2 Src) \
{ \
m [Index0] Op Src.x; \
m [Index1] Op Src.y; \
\
return (Vector2 (m [Index0], m [Index1])); \
}

#define Vector3_AssignOp(Op,Index0,Index1,Index2) \
Vector3 operator Op (Vector3 Src) \
{ \
m [Index0] Op Src.x; \
m [Index1] Op Src.y; \
m [Index2] Op Src.z; \
\
return (Vector3 (m [Index0], m [Index1], m [Index2])); \
}

#define Vector2_AssignOps(Op,Index0,Index1) \
Vector2_AssignOp (Op, Index0, Index1); \
Vector2 operator Op (float Src) { return (operator Op (Vector2 (Src, Src))); }

#define Vector3_AssignOps(Op,Index0,Index1,Index2) \
Vector3_AssignOp (Op, Index0, Index1, Index2); \
Vector3 operator Op (float Src) { return (operator Op (Vector3 (Src, Src, Src))); } \
Vector3 operator Op (Vector2 Src) { return (operator Op (Vector3 (Src.x, Src.y, Src.y))); }

#define Vector2_CastOp(Index0,Index1) \
operator Vector2 () const \
{ \
return (Vector2 (m [Index0], m [Index1])); \
}

#define Vector3_CastOp(Index0,Index1,Index2) \
operator Vector3 () const \
{ \
return (Vector3 (m [Index0], m [Index1], m [Index2])); \
}

// read only masks

#define Vector2_Comp2_RO(Name,Index0,Index1) \
struct _##Name \
{ \
private: \
float m [2]; \
\
public: \
Vector2_CastOp (Index0, Index1); \
} Name

#define Vector3_Comp2_RO(Name,Index0,Index1) \
struct _##Name \
{ \
private: \
float m [3]; \
\
public: \
Vector2_CastOp (Index0, Index1); \
} Name

#define Vector3_Comp3_RO(Name,Index0,Index1,Index2) \
struct _##Name \
{ \
private: \
float m [3]; \
\
public: \
Vector3_CastOp (Index0, Index1, Index2); \
} Name

// read and write masks

#define Vector2_Comp2_RW(Name,Index0,Index1) \
struct _##Name \
{ \
private: \
float m [2]; \
\
public: \
Vector2_AssignOps ( =, Index0, Index1); \
Vector2_AssignOps (+=, Index0, Index1); \
Vector2_AssignOps (-=, Index0, Index1); \
Vector2_AssignOps (*=, Index0, Index1); \
Vector2_AssignOps (/=, Index0, Index1); \
Vector2_CastOp (Index0, Index1); \
} Name

#define Vector3_Comp2_RW(Name,Index0,Index1) \
struct _##Name \
{ \
private: \
float m [3]; \
\
public: \
Vector2_AssignOps ( =, Index0, Index1); \
Vector2_AssignOps (+=, Index0, Index1); \
Vector2_AssignOps (-=, Index0, Index1); \
Vector2_AssignOps (*=, Index0, Index1); \
Vector2_AssignOps (/=, Index0, Index1); \
Vector2_CastOp (Index0, Index1); \
} Name

#define Vector3_Comp3_RW(Name,Index0,Index1,Index2) \
struct _##Name \
{ \
private: \
float m [3]; \
\
public: \
Vector3_AssignOps ( =, Index0, Index1, Index2); \
Vector3_AssignOps (+=, Index0, Index1, Index2); \
Vector3_AssignOps (-=, Index0, Index1, Index2); \
Vector3_AssignOps (*=, Index0, Index1, Index2); \
Vector3_AssignOps (/=, Index0, Index1, Index2); \
Vector3_CastOp (Index0, Index1, Index2); \
} Name

// vector structures

union Vector2
{
struct
{
float x;
float y;
};

float m [2];

Vector2 () {}
Vector2 (float x, float y) : x (x), y (y) {}

Vector2_Comp2_RO (xx, 0, 0);
Vector2_Comp2_RW (xy, 0, 1);
Vector2_Comp2_RW (yx, 1, 0);
Vector2_Comp2_RO (yy, 1, 1);
};

union Vector3
{
struct
{
float x;
float y;
float z;
};

float m [3];

Vector3 () {}
Vector3 (float x, float y, float z) : x (x), y (y), z (z) {}
Vector3 (Vector2 v2xy, float z) : x (v2xy.x), y (v2xy.y), z (z) {}
Vector3 (float x, Vector2 v2yz) : x (x), y (v2yz.x), z (v2yz.y) {}

Vector3_Comp2_RO (xx, 0, 0);
Vector3_Comp2_RW (xy, 0, 1);
Vector3_Comp2_RW (xz, 0, 2);
Vector3_Comp2_RW (yx, 1, 0);
Vector3_Comp2_RO (yy, 1, 1);
Vector3_Comp2_RW (yz, 1, 2);
Vector3_Comp2_RW (zx, 2, 0);
Vector3_Comp2_RW (zy, 2, 1);
Vector3_Comp2_RO (zz, 2, 2);
Vector3_Comp3_RO (xxx, 0, 0, 0);
Vector3_Comp3_RO (xxy, 0, 0, 1);
Vector3_Comp3_RO (xxz, 0, 0, 2);
Vector3_Comp3_RO (xyx, 0, 1, 0);
Vector3_Comp3_RO (xyy, 0, 1, 1);
Vector3_Comp3_RW (xyz, 0, 1, 2);
Vector3_Comp3_RO (xzx, 0, 2, 0);
Vector3_Comp3_RW (xzy, 0, 2, 1);
Vector3_Comp3_RO (xzz, 0, 2, 2);
Vector3_Comp3_RO (yxx, 1, 0, 0);
Vector3_Comp3_RO (yxy, 1, 0, 1);
Vector3_Comp3_RW (yxz, 1, 0, 2);
Vector3_Comp3_RO (yyx, 1, 1, 0);
Vector3_Comp3_RO (yyy, 1, 1, 1);
Vector3_Comp3_RO (yyz, 1, 1, 2);
Vector3_Comp3_RW (yzx, 1, 2, 0);
Vector3_Comp3_RO (yzy, 1, 2, 1);
Vector3_Comp3_RO (yzz, 1, 2, 2);
Vector3_Comp3_RO (zxx, 2, 0, 0);
Vector3_Comp3_RW (zxy, 2, 0, 1);
Vector3_Comp3_RO (zxz, 2, 0, 2);
Vector3_Comp3_RW (zyx, 2, 1, 0);
Vector3_Comp3_RO (zyy, 2, 1, 1);
Vector3_Comp3_RO (zyz, 2, 1, 2);
Vector3_Comp3_RO (zzx, 2, 2, 0);
Vector3_Comp3_RO (zzy, 2, 2, 1);
Vector3_Comp3_RO (zzz, 2, 2, 2);
};

// undefine macros

#undef Vector2_AssignOp
#undef Vector3_AssignOp
#undef Vector2_AssignOps
#undef Vector3_AssignOps
#undef Vector2_CastOp
#undef Vector3_CastOp
#undef Vector2_Comp2_RO
#undef Vector3_Comp2_RO
#undef Vector3_Comp3_RO
#undef Vector2_Comp2_RW
#undef Vector3_Comp2_RW
#undef Vector3_Comp3_RW

// Vector2 operators

inline Vector2 operator + (Vector2 Src)
{
return (Src);
}

inline Vector2 operator - (Vector2 Src)
{
return (Vector2 (-Src.x, -Src.y));
}

inline Vector2 operator + (Vector2 Src1, Vector2 Src2)
{
return (Vector2 (Src1.x + Src2.x, Src1.y + Src2.y));
}

inline Vector2 operator - (Vector2 Src1, Vector2 Src2)
{
return (Vector2 (Src1.x - Src2.x, Src1.y - Src2.y));
}

inline Vector2 operator * (Vector2 Src1, Vector2 Src2)
{
return (Vector2 (Src1.x * Src2.x, Src1.y * Src2.y));
}

inline Vector2 operator / (Vector2 Src1, Vector2 Src2)
{
return (Vector2 (Src1.x / Src2.x, Src1.y / Src2.y));
}

inline Vector2 & operator += (Vector2 & Dst, Vector2 Src)
{
Dst.x += Src.x;
Dst.y += Src.y;

return (Dst);
}

inline Vector2 & operator -= (Vector2 & Dst, Vector2 Src)
{
Dst.x -= Src.x;
Dst.y -= Src.y;

return (Dst);
}

inline Vector2 & operator *= (Vector2 & Dst, Vector2 Src)
{
Dst.x *= Src.x;
Dst.y *= Src.y;

return (Dst);
}

inline Vector2 & operator /= (Vector2 & Dst, Vector2 Src)
{
Dst.x /= Src.x;
Dst.y /= Src.y;

return (Dst);
}

// Vector3 operators

inline Vector3 operator + (Vector3 Src)
{
return (Src);
}

inline Vector3 operator - (Vector3 Src)
{
return (Vector3 (-Src.x, -Src.y, -Src.z));
}

inline Vector3 operator + (Vector3 Src1, Vector3 Src2)
{
return (Vector3 (Src1.x + Src2.x, Src1.y + Src2.y, Src1.z + Src2.z));
}

inline Vector3 operator - (Vector3 Src1, Vector3 Src2)
{
return (Vector3 (Src1.x - Src2.x, Src1.y - Src2.y, Src1.z - Src2.z));
}

inline Vector3 operator * (Vector3 Src1, Vector3 Src2)
{
return (Vector3 (Src1.x * Src2.x, Src1.y * Src2.y, Src1.z * Src2.z));
}

inline Vector3 operator / (Vector3 Src1, Vector3 Src2)
{
return (Vector3 (Src1.x / Src2.x, Src1.y / Src2.y, Src1.z / Src2.z));
}

inline Vector3 & operator += (Vector3 & Dst, Vector3 Src)
{
Dst.x += Src.x;
Dst.y += Src.y;
Dst.z += Src.z;

return (Dst);
}

inline Vector3 & operator -= (Vector3 & Dst, Vector3 Src)
{
Dst.x -= Src.x;
Dst.y -= Src.y;
Dst.z -= Src.z;

return (Dst);
}

inline Vector3 & operator *= (Vector3 & Dst, Vector3 Src)
{
Dst.x *= Src.x;
Dst.y *= Src.y;
Dst.z *= Src.z;

return (Dst);
}

inline Vector3 & operator /= (Vector3 & Dst, Vector3 Src)
{
Dst.x /= Src.x;
Dst.y /= Src.y;
Dst.z /= Src.z;

return (Dst);
}

// additional operators for mixed types

inline Vector2 operator + (float Src1, Vector2 Src2) { return (Vector2 (Src1, Src1) + Src2); }
inline Vector3 operator + (float Src1, Vector3 Src2) { return (Vector3 (Src1, Src1, Src1) + Src2); }
inline Vector2 operator + (Vector2 Src1, float Src2) { return (Src1 + Vector2 (Src2, Src2)); }
inline Vector3 operator + (Vector2 Src1, Vector3 Src2) { return (Vector3 (Src1.x, Src1.y, Src1.y) + Src2); }
inline Vector3 operator + (Vector3 Src1, float Src2) { return (Src1 + Vector3 (Src2, Src2, Src2)); }
inline Vector3 operator + (Vector3 Src1, Vector2 Src2) { return (Src1 + Vector3 (Src2.x, Src2.y, Src2.y)); }

inline Vector2 operator - (float Src1, Vector2 Src2) { return (Vector2 (Src1, Src1) - Src2); }
inline Vector3 operator - (float Src1, Vector3 Src2) { return (Vector3 (Src1, Src1, Src1) - Src2); }
inline Vector2 operator - (Vector2 Src1, float Src2) { return (Src1 - Vector2 (Src2, Src2)); }
inline Vector3 operator - (Vector2 Src1, Vector3 Src2) { return (Vector3 (Src1.x, Src1.y, Src1.y) - Src2); }
inline Vector3 operator - (Vector3 Src1, float Src2) { return (Src1 - Vector3 (Src2, Src2, Src2)); }
inline Vector3 operator - (Vector3 Src1, Vector2 Src2) { return (Src1 - Vector3 (Src2.x, Src2.y, Src2.y)); }

inline Vector2 operator * (float Src1, Vector2 Src2) { return (Vector2 (Src1, Src1) * Src2); }
inline Vector3 operator * (float Src1, Vector3 Src2) { return (Vector3 (Src1, Src1, Src1) * Src2); }
inline Vector2 operator * (Vector2 Src1, float Src2) { return (Src1 * Vector2 (Src2, Src2)); }
inline Vector3 operator * (Vector2 Src1, Vector3 Src2) { return (Vector3 (Src1.x, Src1.y, Src1.y) * Src2); }
inline Vector3 operator * (Vector3 Src1, float Src2) { return (Src1 * Vector3 (Src2, Src2, Src2)); }
inline Vector3 operator * (Vector3 Src1, Vector2 Src2) { return (Src1 * Vector3 (Src2.x, Src2.y, Src2.y)); }

inline Vector2 operator / (float Src1, Vector2 Src2) { return (Vector2 (Src1, Src1) / Src2); }
inline Vector3 operator / (float Src1, Vector3 Src2) { return (Vector3 (Src1, Src1, Src1) / Src2); }
inline Vector2 operator / (Vector2 Src1, float Src2) { return (Src1 / Vector2 (Src2, Src2)); }
inline Vector3 operator / (Vector2 Src1, Vector3 Src2) { return (Vector3 (Src1.x, Src1.y, Src1.y) / Src2); }
inline Vector3 operator / (Vector3 Src1, float Src2) { return (Src1 / Vector3 (Src2, Src2, Src2)); }
inline Vector3 operator / (Vector3 Src1, Vector2 Src2) { return (Src1 / Vector3 (Src2.x, Src2.y, Src2.y)); }

inline Vector2 & operator += (Vector2 & Dst, float Src) { return (Dst += Vector2 (Src, Src)); }
inline Vector3 & operator += (Vector3 & Dst, float Src) { return (Dst += Vector3 (Src, Src, Src)); }
inline Vector3 & operator += (Vector3 & Dst, Vector2 Src) { return (Dst += Vector3 (Src.x, Src.y, Src.y)); }

inline Vector2 & operator -= (Vector2 & Dst, float Src) { return (Dst -= Vector2 (Src, Src)); }
inline Vector3 & operator -= (Vector3 & Dst, float Src) { return (Dst -= Vector3 (Src, Src, Src)); }
inline Vector3 & operator -= (Vector3 & Dst, Vector2 Src) { return (Dst -= Vector3 (Src.x, Src.y, Src.y)); }

inline Vector2 & operator *= (Vector2 & Dst, float Src) { return (Dst *= Vector2 (Src, Src)); }
inline Vector3 & operator *= (Vector3 & Dst, float Src) { return (Dst *= Vector3 (Src, Src, Src)); }
inline Vector3 & operator *= (Vector3 & Dst, Vector2 Src) { return (Dst *= Vector3 (Src.x, Src.y, Src.y)); }

inline Vector2 & operator /= (Vector2 & Dst, float Src) { return (Dst /= Vector2 (Src, Src)); }
inline Vector3 & operator /= (Vector3 & Dst, float Src) { return (Dst /= Vector3 (Src, Src, Src)); }
inline Vector3 & operator /= (Vector3 & Dst, Vector2 Src) { return (Dst /= Vector3 (Src.x, Src.y, Src.y)); }

#endif // _INC_VECTORS_H_

Mein Problem ist jetzt, daß der Compiler mit seinen Optimierungen (ich habe alles durchprobiert, was die Performance steigern kann) nicht soviel rausholt, wie machbar ist. Zum Testen habe ich das Kreuzprodukt in diesen beiden Varianten genommen:

inline Vector3 cross1 (Vector3 v1, Vector3 v2)
{
Vector3 v;

v.x = v1.y * v2.z - v1.z * v2.y;
v.y = v1.z * v2.x - v1.x * v2.z;
v.z = v1.x * v2.y - v1.y * v2.x;

return (v);
}

inline Vector3 cross2 (Vector3 v1, Vector3 v2)
{
return (v1.yzx * v2.zxy - v1.zxy * v2.yzx);
}

Wenn ich jetzt in einer Schleife (ich habe dafür gesorgt, daß das Ergebnis nicht verworfen wird) 100.000.000 mal das Kreuzprodukt berechne, spüre ich einen deutlichen Unterschied zwischen den beiden Varianten, cross2 ist um einiges langsamer. Und das, obwohl die beiden Varianten mathematisch äquivalent sind (bzw. sein sollten, die Rundungsfehler sind mit und ohne Float Consistency bei beiden Varianten etwas anders) und es im fertigen Code in dieser Schleife keinen einzigen Call mehr gibt.

Hat jemand eine Idee, was ich direkt im Code noch tun kann? Außer dem Verzicht auf das Swizzling natürlich. Ich möchte jederzeit das Swizzling nutzen können und trotzdem die maximale Performance haben.

PS: holt der Compiler von VS .Net 2005 vielleicht (deutlich) mehr raus? Dann würde ich wohl auf lange Sicht umsteigen.

Der Namenlose
2006-01-22, 21:28:24
Versuch mal die Vektoren als const Referenz zu übergeben. Manchmal verbleiben nach der Optimierung noch teile der temporären Objekte oder Copykonstruktoren übrig.

Neomi
2006-01-22, 22:04:53
Referenzen funktionieren nicht, weil der Compiler dann nicht mehr implizit casten kann. Von z.B. Vector3::_yzx (der Typ von Vector3::yzx) kann implizit zum Vector3 gecastet werden, da der Operator definiert ist, aber nicht über Vector3 zu Vector3&. Da müßte ich dann bei jeder Verwendung erstmal explizit casten, und dann ist der ganze Komfort dahin. Einen Operator, der direkt in eine Referenz castet, kann ich auch nicht nutzen, da dann die Adresse einer lokalen Variable zurückgegeben wird. Da läßt sich quasi nicht sicherstellen, daß die Stelle, die referenziert wird, nicht schon durch was anderes überschrieben wurde.

Edit: oh, konstante Referenz statt einfach nur Referenz. Moment, das werde ich gleich mal testen.

Edit 2: mit der konstanten Referenz ist es tatsächlich deutlich schneller, die beiden Varianten sind jetzt ebenbürtig. Eigentlich hätte ich selbst drauf kommen müssen, ich überlege mir bei Gelegenheit noch eine passende Ausrede. Besten Dank! :)

ScottManDeath
2006-01-23, 08:26:59
Hehe, zufälligerweise ich hab mir gerade mit einem mygeneration template auch eine C# Vektor Klasse mit arbitrary swizzling gemacht :) Ich nutze Properties dafür.

Das Template: http://mandrill.fuxx0r.net/c++/paste:5911
Der Code:http://mandrill.fuxx0r.net/c++/paste:5910

Deine #defines sehen schon straff aus =) Muss meine C++ Vektor lib bei gelegenheit auch mal überarbeiten... Auf die Idee mit Union/Structs bin ich noch gar nicht kekommen. Dürfte auf jeden Fall fixer sein, als meine Variante mit neuen Vektoren zusammenbauen.

Neomi
2006-01-23, 11:52:22
Hehe, zufälligerweise ich hab mir gerade mit einem mygeneration template auch eine C# Vektor Klasse mit arbitrary swizzling gemacht :) Ich nutze Properties dafür.

Genau diese Properties haben mich darauf gebracht. Diese Möglichkeiten wollte ich dann für meine Vektoren ebenfalls.

Deine #defines sehen schon straff aus =) Muss meine C++ Vektor lib bei gelegenheit auch mal überarbeiten...

Die #defines habe ich noch ein wenig weiter gestrafft und ein paar unnötige Dinge entfernt. Zuweisungen wie v1.xyz=v2.x bleiben erhalten (wird implizit zu v1.xyz=v2.xxx erweitert), v1.x=v2.xyz wäre aber einfach nur unnötig (würde v1.x=v2.x entsprechen) und fällt damit weg. Hier nochmal der komplette Code für die Vektoren (inklusive Vector4), falls dir das bei deinen Optimierungen hilft:

#ifndef _INC_VECTORS_H_
#define _INC_VECTORS_H_

#include <math.h> // for sqrtf()

// low level macros

#define Vector2_AssignOps(Op,Index0,Index1) \
Vector2 operator Op (float Src) { return (Vector2 (m [Index0] Op Src, m [Index1] Op Src)); } \
Vector2 operator Op (const Vector2 & Src) { return (Vector2 (m [Index0] Op Src.x, m [Index1] Op Src.y)); }

#define Vector3_AssignOps(Op,Index0,Index1,Index2) \
Vector3 operator Op (float Src) { return (Vector3 (m [Index0] Op Src, m [Index1] Op Src, m [Index2] Op Src)); } \
Vector3 operator Op (const Vector2 & Src) { return (Vector3 (m [Index0] Op Src.x, m [Index1] Op Src.y, m [Index2] Op Src.y)); } \
Vector3 operator Op (const Vector3 & Src) { return (Vector3 (m [Index0] Op Src.x, m [Index1] Op Src.y, m [Index2] Op Src.z)); }

#define Vector4_AssignOps(Op,Index0,Index1,Index2,Index3) \
Vector4 operator Op (float Src) { return (Vector4 (m [Index0] Op Src, m [Index1] Op Src, m [Index2] Op Src, m [Index3] Op Src)); } \
Vector4 operator Op (const Vector2 & Src) { return (Vector4 (m [Index0] Op Src.x, m [Index1] Op Src.y, m [Index2] Op Src.y, m [Index3] Op Src.y)); } \
Vector4 operator Op (const Vector3 & Src) { return (Vector4 (m [Index0] Op Src.x, m [Index1] Op Src.y, m [Index2] Op Src.z, m [Index3] Op Src.z)); } \
Vector4 operator Op (const Vector4 & Src) { return (Vector4 (m [Index0] Op Src.x, m [Index1] Op Src.y, m [Index2] Op Src.z, m [Index3] Op Src.w)); }

#define Vector2_CastingOp(Index0,Index1) \
operator Vector2 () const { return (Vector2 (m [Index0], m [Index1])); }

#define Vector3_CastingOp(Index0,Index1,Index2) \
operator Vector3 () const { return (Vector3 (m [Index0], m [Index1], m [Index2])); }

#define Vector4_CastingOp(Index0,Index1,Index2,Index3) \
operator Vector4 () const { return (Vector4 (m [Index0], m [Index1], m [Index2], m [Index3])); }

// read only masks

#define Vector2_Comp2_RO(Name,Index0,Index1) \
struct _##Name \
{ \
private: \
float m [2]; \
\
public: \
Vector2_CastingOp (Index0, Index1); \
} Name

#define Vector3_Comp2_RO(Name,Index0,Index1) \
struct _##Name \
{ \
private: \
float m [3]; \
\
public: \
Vector2_CastingOp (Index0, Index1); \
} Name

#define Vector3_Comp3_RO(Name,Index0,Index1,Index2) \
struct _##Name \
{ \
private: \
float m [3]; \
\
public: \
Vector3_CastingOp (Index0, Index1, Index2); \
} Name

#define Vector4_Comp2_RO(Name,Index0,Index1) \
struct _##Name \
{ \
private: \
float m [4]; \
\
public: \
Vector2_CastingOp (Index0, Index1); \
} Name

#define Vector4_Comp3_RO(Name,Index0,Index1,Index2) \
struct _##Name \
{ \
private: \
float m [4]; \
\
public: \
Vector3_CastingOp (Index0, Index1, Index2); \
} Name

#define Vector4_Comp4_RO(Name,Index0,Index1,Index2,Index3) \
struct _##Name \
{ \
private: \
float m [4]; \
\
public: \
Vector4_CastingOp (Index0, Index1, Index2, Index3); \
} Name

// read and write masks

#define Vector2_Comp2_RW(Name,Index0,Index1) \
struct _##Name \
{ \
private: \
float m [2]; \
\
public: \
Vector2_AssignOps ( =, Index0, Index1); \
Vector2_AssignOps (+=, Index0, Index1); \
Vector2_AssignOps (-=, Index0, Index1); \
Vector2_AssignOps (*=, Index0, Index1); \
Vector2_AssignOps (/=, Index0, Index1); \
Vector2_CastingOp (Index0, Index1); \
} Name

#define Vector3_Comp2_RW(Name,Index0,Index1) \
struct _##Name \
{ \
private: \
float m [3]; \
\
public: \
Vector2_AssignOps ( =, Index0, Index1); \
Vector2_AssignOps (+=, Index0, Index1); \
Vector2_AssignOps (-=, Index0, Index1); \
Vector2_AssignOps (*=, Index0, Index1); \
Vector2_AssignOps (/=, Index0, Index1); \
Vector2_CastingOp (Index0, Index1); \
} Name

#define Vector3_Comp3_RW(Name,Index0,Index1,Index2) \
struct _##Name \
{ \
private: \
float m [3]; \
\
public: \
Vector3_AssignOps ( =, Index0, Index1, Index2); \
Vector3_AssignOps (+=, Index0, Index1, Index2); \
Vector3_AssignOps (-=, Index0, Index1, Index2); \
Vector3_AssignOps (*=, Index0, Index1, Index2); \
Vector3_AssignOps (/=, Index0, Index1, Index2); \
Vector3_CastingOp (Index0, Index1, Index2); \
} Name

#define Vector4_Comp2_RW(Name,Index0,Index1) \
struct _##Name \
{ \
private: \
float m [4]; \
\
public: \
Vector2_AssignOps ( =, Index0, Index1); \
Vector2_AssignOps (+=, Index0, Index1); \
Vector2_AssignOps (-=, Index0, Index1); \
Vector2_AssignOps (*=, Index0, Index1); \
Vector2_AssignOps (/=, Index0, Index1); \
Vector2_CastingOp (Index0, Index1); \
} Name

#define Vector4_Comp3_RW(Name,Index0,Index1,Index2) \
struct _##Name \
{ \
private: \
float m [4]; \
\
public: \
Vector3_AssignOps ( =, Index0, Index1, Index2); \
Vector3_AssignOps (+=, Index0, Index1, Index2); \
Vector3_AssignOps (-=, Index0, Index1, Index2); \
Vector3_AssignOps (*=, Index0, Index1, Index2); \
Vector3_AssignOps (/=, Index0, Index1, Index2); \
Vector3_CastingOp (Index0, Index1, Index2); \
} Name

#define Vector4_Comp4_RW(Name,Index0,Index1,Index2,Index3) \
struct _##Name \
{ \
private: \
float m [4]; \
\
public: \
Vector4_AssignOps ( =, Index0, Index1, Index2, Index3); \
Vector4_AssignOps (+=, Index0, Index1, Index2, Index3); \
Vector4_AssignOps (-=, Index0, Index1, Index2, Index3); \
Vector4_AssignOps (*=, Index0, Index1, Index2, Index3); \
Vector4_AssignOps (/=, Index0, Index1, Index2, Index3); \
Vector4_CastingOp (Index0, Index1, Index2, Index3); \
} Name

// vector structures

union Vector2
{
struct
{
float x;
float y;
};

float m [2];

Vector2 () {}
Vector2 (float x, float y) : x (x), y (y) {}

Vector2_Comp2_RO (xx, 0, 0);
Vector2_Comp2_RW (xy, 0, 1);
Vector2_Comp2_RW (yx, 1, 0);
Vector2_Comp2_RO (yy, 1, 1);
};

union Vector3
{
struct
{
float x;
float y;
float z;
};

float m [3];

Vector3 () {}
Vector3 (float x, float y, float z) : x (x), y (y), z (z) {}
Vector3 (const Vector2 & v2xy, float z) : x (v2xy.x), y (v2xy.y), z (z) {}
Vector3 (float x, const Vector2 & v2yz) : x (x), y (v2yz.x), z (v2yz.y) {}

Vector3_Comp2_RO (xx, 0, 0);
Vector3_Comp2_RW (xy, 0, 1);
Vector3_Comp2_RW (xz, 0, 2);
Vector3_Comp2_RW (yx, 1, 0);
Vector3_Comp2_RO (yy, 1, 1);
Vector3_Comp2_RW (yz, 1, 2);
Vector3_Comp2_RW (zx, 2, 0);
Vector3_Comp2_RW (zy, 2, 1);
Vector3_Comp2_RO (zz, 2, 2);
Vector3_Comp3_RO (xxx, 0, 0, 0);
Vector3_Comp3_RO (xxy, 0, 0, 1);
Vector3_Comp3_RO (xxz, 0, 0, 2);
Vector3_Comp3_RO (xyx, 0, 1, 0);
Vector3_Comp3_RO (xyy, 0, 1, 1);
Vector3_Comp3_RW (xyz, 0, 1, 2);
Vector3_Comp3_RO (xzx, 0, 2, 0);
Vector3_Comp3_RW (xzy, 0, 2, 1);
Vector3_Comp3_RO (xzz, 0, 2, 2);
Vector3_Comp3_RO (yxx, 1, 0, 0);
Vector3_Comp3_RO (yxy, 1, 0, 1);
Vector3_Comp3_RW (yxz, 1, 0, 2);
Vector3_Comp3_RO (yyx, 1, 1, 0);
Vector3_Comp3_RO (yyy, 1, 1, 1);
Vector3_Comp3_RO (yyz, 1, 1, 2);
Vector3_Comp3_RW (yzx, 1, 2, 0);
Vector3_Comp3_RO (yzy, 1, 2, 1);
Vector3_Comp3_RO (yzz, 1, 2, 2);
Vector3_Comp3_RO (zxx, 2, 0, 0);
Vector3_Comp3_RW (zxy, 2, 0, 1);
Vector3_Comp3_RO (zxz, 2, 0, 2);
Vector3_Comp3_RW (zyx, 2, 1, 0);
Vector3_Comp3_RO (zyy, 2, 1, 1);
Vector3_Comp3_RO (zyz, 2, 1, 2);
Vector3_Comp3_RO (zzx, 2, 2, 0);
Vector3_Comp3_RO (zzy, 2, 2, 1);
Vector3_Comp3_RO (zzz, 2, 2, 2);
};

union Vector4
{
struct
{
float x;
float y;
float z;
float w;
};

float m [4];

Vector4 () {}
Vector4 (float x, float y, float z, float w = 1.0f) : x (x), y (y), z (z), w (w) {}
Vector4 (const Vector2 & v2xy, float z, float w = 1.0f) : x (v2xy.x), y (v2xy.y), z (z), w (w) {}
Vector4 (float x, const Vector2 & v2yz, float w = 1.0f) : x (x), y (v2yz.x), z (v2yz.y), w (w) {}
Vector4 (float x, float y, const Vector2 & v2zw) : x (x), y (y), z (v2zw.x), w (v2zw.y) {}
Vector4 (const Vector2 & v2xy, const Vector2 & v2zw) : x (v2xy.x), y (v2xy.y), z (v2zw.x), w (v2zw.y) {}
Vector4 (const Vector3 & v3xyz, float w = 1.0f) : x (v3xyz.x), y (v3xyz.y), z (v3xyz.z), w (w) {}
Vector4 (float x, const Vector3 & v3yzw) : x (x), y (v3yzw.x), z (v3yzw.y), w (v3yzw.z) {}

Vector4_Comp2_RO (xx, 0, 0);
Vector4_Comp2_RW (xy, 0, 1);
Vector4_Comp2_RW (xz, 0, 2);
Vector4_Comp2_RW (xw, 0, 3);
Vector4_Comp2_RW (yx, 1, 0);
Vector4_Comp2_RO (yy, 1, 1);
Vector4_Comp2_RW (yz, 1, 2);
Vector4_Comp2_RW (yw, 1, 3);
Vector4_Comp2_RW (zx, 2, 0);
Vector4_Comp2_RW (zy, 2, 1);
Vector4_Comp2_RO (zz, 2, 2);
Vector4_Comp2_RW (zw, 2, 3);
Vector4_Comp2_RW (wx, 3, 0);
Vector4_Comp2_RW (wy, 3, 1);
Vector4_Comp2_RW (wz, 3, 2);
Vector4_Comp2_RO (ww, 3, 3);
Vector4_Comp3_RO (xxx, 0, 0, 0);
Vector4_Comp3_RO (xxy, 0, 0, 1);
Vector4_Comp3_RO (xxz, 0, 0, 2);
Vector4_Comp3_RO (xxw, 0, 0, 3);
Vector4_Comp3_RO (xyx, 0, 1, 0);
Vector4_Comp3_RO (xyy, 0, 1, 1);
Vector4_Comp3_RW (xyz, 0, 1, 2);
Vector4_Comp3_RW (xyw, 0, 1, 3);
Vector4_Comp3_RO (xzx, 0, 2, 0);
Vector4_Comp3_RW (xzy, 0, 2, 1);
Vector4_Comp3_RO (xzz, 0, 2, 2);
Vector4_Comp3_RW (xzw, 0, 2, 3);
Vector4_Comp3_RO (xwx, 0, 3, 0);
Vector4_Comp3_RW (xwy, 0, 3, 1);
Vector4_Comp3_RW (xwz, 0, 3, 2);
Vector4_Comp3_RO (xww, 0, 3, 3);
Vector4_Comp3_RO (yxx, 1, 0, 0);
Vector4_Comp3_RO (yxy, 1, 0, 1);
Vector4_Comp3_RW (yxz, 1, 0, 2);
Vector4_Comp3_RW (yxw, 1, 0, 3);
Vector4_Comp3_RO (yyx, 1, 1, 0);
Vector4_Comp3_RO (yyy, 1, 1, 1);
Vector4_Comp3_RO (yyz, 1, 1, 2);
Vector4_Comp3_RO (yyw, 1, 1, 3);
Vector4_Comp3_RW (yzx, 1, 2, 0);
Vector4_Comp3_RO (yzy, 1, 2, 1);
Vector4_Comp3_RO (yzz, 1, 2, 2);
Vector4_Comp3_RW (yzw, 1, 2, 3);
Vector4_Comp3_RW (ywx, 1, 3, 0);
Vector4_Comp3_RO (ywy, 1, 3, 1);
Vector4_Comp3_RW (ywz, 1, 3, 2);
Vector4_Comp3_RO (yww, 1, 3, 3);
Vector4_Comp3_RO (zxx, 2, 0, 0);
Vector4_Comp3_RW (zxy, 2, 0, 1);
Vector4_Comp3_RO (zxz, 2, 0, 2);
Vector4_Comp3_RW (zxw, 2, 0, 3);
Vector4_Comp3_RW (zyx, 2, 1, 0);
Vector4_Comp3_RO (zyy, 2, 1, 1);
Vector4_Comp3_RO (zyz, 2, 1, 2);
Vector4_Comp3_RW (zyw, 2, 1, 3);
Vector4_Comp3_RO (zzx, 2, 2, 0);
Vector4_Comp3_RO (zzy, 2, 2, 1);
Vector4_Comp3_RO (zzz, 2, 2, 2);
Vector4_Comp3_RO (zzw, 2, 2, 3);
Vector4_Comp3_RW (zwx, 2, 3, 0);
Vector4_Comp3_RW (zwy, 2, 3, 1);
Vector4_Comp3_RO (zwz, 2, 3, 2);
Vector4_Comp3_RO (zww, 2, 3, 3);
Vector4_Comp3_RO (wxx, 3, 0, 0);
Vector4_Comp3_RW (wxy, 3, 0, 1);
Vector4_Comp3_RW (wxz, 3, 0, 2);
Vector4_Comp3_RO (wxw, 3, 0, 3);
Vector4_Comp3_RW (wyx, 3, 1, 0);
Vector4_Comp3_RO (wyy, 3, 1, 1);
Vector4_Comp3_RW (wyz, 3, 1, 2);
Vector4_Comp3_RO (wyw, 3, 1, 3);
Vector4_Comp3_RW (wzx, 3, 2, 0);
Vector4_Comp3_RW (wzy, 3, 2, 1);
Vector4_Comp3_RO (wzz, 3, 2, 2);
Vector4_Comp3_RO (wzw, 3, 2, 3);
Vector4_Comp3_RO (wwx, 3, 3, 0);
Vector4_Comp3_RO (wwy, 3, 3, 1);
Vector4_Comp3_RO (wwz, 3, 3, 2);
Vector4_Comp3_RO (www, 3, 3, 3);
Vector4_Comp4_RO (xxxx, 0, 0, 0, 0);
Vector4_Comp4_RO (xxxy, 0, 0, 0, 1);
Vector4_Comp4_RO (xxxz, 0, 0, 0, 2);
Vector4_Comp4_RO (xxxw, 0, 0, 0, 3);
Vector4_Comp4_RO (xxyx, 0, 0, 1, 0);
Vector4_Comp4_RO (xxyy, 0, 0, 1, 1);
Vector4_Comp4_RO (xxyz, 0, 0, 1, 2);
Vector4_Comp4_RO (xxyw, 0, 0, 1, 3);
Vector4_Comp4_RO (xxzx, 0, 0, 2, 0);
Vector4_Comp4_RO (xxzy, 0, 0, 2, 1);
Vector4_Comp4_RO (xxzz, 0, 0, 2, 2);
Vector4_Comp4_RO (xxzw, 0, 0, 2, 3);
Vector4_Comp4_RO (xxwx, 0, 0, 3, 0);
Vector4_Comp4_RO (xxwy, 0, 0, 3, 1);
Vector4_Comp4_RO (xxwz, 0, 0, 3, 2);
Vector4_Comp4_RO (xxww, 0, 0, 3, 3);
Vector4_Comp4_RO (xyxx, 0, 1, 0, 0);
Vector4_Comp4_RO (xyxy, 0, 1, 0, 1);
Vector4_Comp4_RO (xyxz, 0, 1, 0, 2);
Vector4_Comp4_RO (xyxw, 0, 1, 0, 3);
Vector4_Comp4_RO (xyyx, 0, 1, 1, 0);
Vector4_Comp4_RO (xyyy, 0, 1, 1, 1);
Vector4_Comp4_RO (xyyz, 0, 1, 1, 2);
Vector4_Comp4_RO (xyyw, 0, 1, 1, 3);
Vector4_Comp4_RO (xyzx, 0, 1, 2, 0);
Vector4_Comp4_RO (xyzy, 0, 1, 2, 1);
Vector4_Comp4_RO (xyzz, 0, 1, 2, 2);
Vector4_Comp4_RW (xyzw, 0, 1, 2, 3);
Vector4_Comp4_RO (xywx, 0, 1, 3, 0);
Vector4_Comp4_RO (xywy, 0, 1, 3, 1);
Vector4_Comp4_RW (xywz, 0, 1, 3, 2);
Vector4_Comp4_RO (xyww, 0, 1, 3, 3);
Vector4_Comp4_RO (xzxx, 0, 2, 0, 0);
Vector4_Comp4_RO (xzxy, 0, 2, 0, 1);
Vector4_Comp4_RO (xzxz, 0, 2, 0, 2);
Vector4_Comp4_RO (xzxw, 0, 2, 0, 3);
Vector4_Comp4_RO (xzyx, 0, 2, 1, 0);
Vector4_Comp4_RO (xzyy, 0, 2, 1, 1);
Vector4_Comp4_RO (xzyz, 0, 2, 1, 2);
Vector4_Comp4_RW (xzyw, 0, 2, 1, 3);
Vector4_Comp4_RO (xzzx, 0, 2, 2, 0);
Vector4_Comp4_RO (xzzy, 0, 2, 2, 1);
Vector4_Comp4_RO (xzzz, 0, 2, 2, 2);
Vector4_Comp4_RO (xzzw, 0, 2, 2, 3);
Vector4_Comp4_RO (xzwx, 0, 2, 3, 0);
Vector4_Comp4_RW (xzwy, 0, 2, 3, 1);
Vector4_Comp4_RO (xzwz, 0, 2, 3, 2);
Vector4_Comp4_RO (xzww, 0, 2, 3, 3);
Vector4_Comp4_RO (xwxx, 0, 3, 0, 0);
Vector4_Comp4_RO (xwxy, 0, 3, 0, 1);
Vector4_Comp4_RO (xwxz, 0, 3, 0, 2);
Vector4_Comp4_RO (xwxw, 0, 3, 0, 3);
Vector4_Comp4_RO (xwyx, 0, 3, 1, 0);
Vector4_Comp4_RO (xwyy, 0, 3, 1, 1);
Vector4_Comp4_RW (xwyz, 0, 3, 1, 2);
Vector4_Comp4_RO (xwyw, 0, 3, 1, 3);
Vector4_Comp4_RO (xwzx, 0, 3, 2, 0);
Vector4_Comp4_RW (xwzy, 0, 3, 2, 1);
Vector4_Comp4_RO (xwzz, 0, 3, 2, 2);
Vector4_Comp4_RO (xwzw, 0, 3, 2, 3);
Vector4_Comp4_RO (xwwx, 0, 3, 3, 0);
Vector4_Comp4_RO (xwwy, 0, 3, 3, 1);
Vector4_Comp4_RO (xwwz, 0, 3, 3, 2);
Vector4_Comp4_RO (xwww, 0, 3, 3, 3);
Vector4_Comp4_RO (yxxx, 1, 0, 0, 0);
Vector4_Comp4_RO (yxxy, 1, 0, 0, 1);
Vector4_Comp4_RO (yxxz, 1, 0, 0, 2);
Vector4_Comp4_RO (yxxw, 1, 0, 0, 3);
Vector4_Comp4_RO (yxyx, 1, 0, 1, 0);
Vector4_Comp4_RO (yxyy, 1, 0, 1, 1);
Vector4_Comp4_RO (yxyz, 1, 0, 1, 2);
Vector4_Comp4_RO (yxyw, 1, 0, 1, 3);
Vector4_Comp4_RO (yxzx, 1, 0, 2, 0);
Vector4_Comp4_RO (yxzy, 1, 0, 2, 1);
Vector4_Comp4_RO (yxzz, 1, 0, 2, 2);
Vector4_Comp4_RW (yxzw, 1, 0, 2, 3);
Vector4_Comp4_RO (yxwx, 1, 0, 3, 0);
Vector4_Comp4_RO (yxwy, 1, 0, 3, 1);
Vector4_Comp4_RW (yxwz, 1, 0, 3, 2);
Vector4_Comp4_RO (yxww, 1, 0, 3, 3);
Vector4_Comp4_RO (yyxx, 1, 1, 0, 0);
Vector4_Comp4_RO (yyxy, 1, 1, 0, 1);
Vector4_Comp4_RO (yyxz, 1, 1, 0, 2);
Vector4_Comp4_RO (yyxw, 1, 1, 0, 3);
Vector4_Comp4_RO (yyyx, 1, 1, 1, 0);
Vector4_Comp4_RO (yyyy, 1, 1, 1, 1);
Vector4_Comp4_RO (yyyz, 1, 1, 1, 2);
Vector4_Comp4_RO (yyyw, 1, 1, 1, 3);
Vector4_Comp4_RO (yyzx, 1, 1, 2, 0);
Vector4_Comp4_RO (yyzy, 1, 1, 2, 1);
Vector4_Comp4_RO (yyzz, 1, 1, 2, 2);
Vector4_Comp4_RO (yyzw, 1, 1, 2, 3);
Vector4_Comp4_RO (yywx, 1, 1, 3, 0);
Vector4_Comp4_RO (yywy, 1, 1, 3, 1);
Vector4_Comp4_RO (yywz, 1, 1, 3, 2);
Vector4_Comp4_RO (yyww, 1, 1, 3, 3);
Vector4_Comp4_RO (yzxx, 1, 2, 0, 0);
Vector4_Comp4_RO (yzxy, 1, 2, 0, 1);
Vector4_Comp4_RO (yzxz, 1, 2, 0, 2);
Vector4_Comp4_RW (yzxw, 1, 2, 0, 3);
Vector4_Comp4_RO (yzyx, 1, 2, 1, 0);
Vector4_Comp4_RO (yzyy, 1, 2, 1, 1);
Vector4_Comp4_RO (yzyz, 1, 2, 1, 2);
Vector4_Comp4_RO (yzyw, 1, 2, 1, 3);
Vector4_Comp4_RO (yzzx, 1, 2, 2, 0);
Vector4_Comp4_RO (yzzy, 1, 2, 2, 1);
Vector4_Comp4_RO (yzzz, 1, 2, 2, 2);
Vector4_Comp4_RO (yzzw, 1, 2, 2, 3);
Vector4_Comp4_RW (yzwx, 1, 2, 3, 0);
Vector4_Comp4_RO (yzwy, 1, 2, 3, 1);
Vector4_Comp4_RO (yzwz, 1, 2, 3, 2);
Vector4_Comp4_RO (yzww, 1, 2, 3, 3);
Vector4_Comp4_RO (ywxx, 1, 3, 0, 0);
Vector4_Comp4_RO (ywxy, 1, 3, 0, 1);
Vector4_Comp4_RW (ywxz, 1, 3, 0, 2);
Vector4_Comp4_RO (ywxw, 1, 3, 0, 3);
Vector4_Comp4_RO (ywyx, 1, 3, 1, 0);
Vector4_Comp4_RO (ywyy, 1, 3, 1, 1);
Vector4_Comp4_RO (ywyz, 1, 3, 1, 2);
Vector4_Comp4_RO (ywyw, 1, 3, 1, 3);
Vector4_Comp4_RW (ywzx, 1, 3, 2, 0);
Vector4_Comp4_RO (ywzy, 1, 3, 2, 1);
Vector4_Comp4_RO (ywzz, 1, 3, 2, 2);
Vector4_Comp4_RO (ywzw, 1, 3, 2, 3);
Vector4_Comp4_RO (ywwx, 1, 3, 3, 0);
Vector4_Comp4_RO (ywwy, 1, 3, 3, 1);
Vector4_Comp4_RO (ywwz, 1, 3, 3, 2);
Vector4_Comp4_RO (ywww, 1, 3, 3, 3);
Vector4_Comp4_RO (zxxx, 2, 0, 0, 0);
Vector4_Comp4_RO (zxxy, 2, 0, 0, 1);
Vector4_Comp4_RO (zxxz, 2, 0, 0, 2);
Vector4_Comp4_RO (zxxw, 2, 0, 0, 3);
Vector4_Comp4_RO (zxyx, 2, 0, 1, 0);
Vector4_Comp4_RO (zxyy, 2, 0, 1, 1);
Vector4_Comp4_RO (zxyz, 2, 0, 1, 2);
Vector4_Comp4_RW (zxyw, 2, 0, 1, 3);
Vector4_Comp4_RO (zxzx, 2, 0, 2, 0);
Vector4_Comp4_RO (zxzy, 2, 0, 2, 1);
Vector4_Comp4_RO (zxzz, 2, 0, 2, 2);
Vector4_Comp4_RO (zxzw, 2, 0, 2, 3);
Vector4_Comp4_RO (zxwx, 2, 0, 3, 0);
Vector4_Comp4_RW (zxwy, 2, 0, 3, 1);
Vector4_Comp4_RO (zxwz, 2, 0, 3, 2);
Vector4_Comp4_RO (zxww, 2, 0, 3, 3);
Vector4_Comp4_RO (zyxx, 2, 1, 0, 0);
Vector4_Comp4_RO (zyxy, 2, 1, 0, 1);
Vector4_Comp4_RO (zyxz, 2, 1, 0, 2);
Vector4_Comp4_RW (zyxw, 2, 1, 0, 3);
Vector4_Comp4_RO (zyyx, 2, 1, 1, 0);
Vector4_Comp4_RO (zyyy, 2, 1, 1, 1);
Vector4_Comp4_RO (zyyz, 2, 1, 1, 2);
Vector4_Comp4_RO (zyyw, 2, 1, 1, 3);
Vector4_Comp4_RO (zyzx, 2, 1, 2, 0);
Vector4_Comp4_RO (zyzy, 2, 1, 2, 1);
Vector4_Comp4_RO (zyzz, 2, 1, 2, 2);
Vector4_Comp4_RO (zyzw, 2, 1, 2, 3);
Vector4_Comp4_RW (zywx, 2, 1, 3, 0);
Vector4_Comp4_RO (zywy, 2, 1, 3, 1);
Vector4_Comp4_RO (zywz, 2, 1, 3, 2);
Vector4_Comp4_RO (zyww, 2, 1, 3, 3);
Vector4_Comp4_RO (zzxx, 2, 2, 0, 0);
Vector4_Comp4_RO (zzxy, 2, 2, 0, 1);
Vector4_Comp4_RO (zzxz, 2, 2, 0, 2);
Vector4_Comp4_RO (zzxw, 2, 2, 0, 3);
Vector4_Comp4_RO (zzyx, 2, 2, 1, 0);
Vector4_Comp4_RO (zzyy, 2, 2, 1, 1);
Vector4_Comp4_RO (zzyz, 2, 2, 1, 2);
Vector4_Comp4_RO (zzyw, 2, 2, 1, 3);
Vector4_Comp4_RO (zzzx, 2, 2, 2, 0);
Vector4_Comp4_RO (zzzy, 2, 2, 2, 1);
Vector4_Comp4_RO (zzzz, 2, 2, 2, 2);
Vector4_Comp4_RO (zzzw, 2, 2, 2, 3);
Vector4_Comp4_RO (zzwx, 2, 2, 3, 0);
Vector4_Comp4_RO (zzwy, 2, 2, 3, 1);
Vector4_Comp4_RO (zzwz, 2, 2, 3, 2);
Vector4_Comp4_RO (zzww, 2, 2, 3, 3);
Vector4_Comp4_RO (zwxx, 2, 3, 0, 0);
Vector4_Comp4_RW (zwxy, 2, 3, 0, 1);
Vector4_Comp4_RO (zwxz, 2, 3, 0, 2);
Vector4_Comp4_RO (zwxw, 2, 3, 0, 3);
Vector4_Comp4_RW (zwyx, 2, 3, 1, 0);
Vector4_Comp4_RO (zwyy, 2, 3, 1, 1);
Vector4_Comp4_RO (zwyz, 2, 3, 1, 2);
Vector4_Comp4_RO (zwyw, 2, 3, 1, 3);
Vector4_Comp4_RO (zwzx, 2, 3, 2, 0);
Vector4_Comp4_RO (zwzy, 2, 3, 2, 1);
Vector4_Comp4_RO (zwzz, 2, 3, 2, 2);
Vector4_Comp4_RO (zwzw, 2, 3, 2, 3);
Vector4_Comp4_RO (zwwx, 2, 3, 3, 0);
Vector4_Comp4_RO (zwwy, 2, 3, 3, 1);
Vector4_Comp4_RO (zwwz, 2, 3, 3, 2);
Vector4_Comp4_RO (zwww, 2, 3, 3, 3);
Vector4_Comp4_RO (wxxx, 3, 0, 0, 0);
Vector4_Comp4_RO (wxxy, 3, 0, 0, 1);
Vector4_Comp4_RO (wxxz, 3, 0, 0, 2);
Vector4_Comp4_RO (wxxw, 3, 0, 0, 3);
Vector4_Comp4_RO (wxyx, 3, 0, 1, 0);
Vector4_Comp4_RO (wxyy, 3, 0, 1, 1);
Vector4_Comp4_RW (wxyz, 3, 0, 1, 2);
Vector4_Comp4_RO (wxyw, 3, 0, 1, 3);
Vector4_Comp4_RO (wxzx, 3, 0, 2, 0);
Vector4_Comp4_RW (wxzy, 3, 0, 2, 1);
Vector4_Comp4_RO (wxzz, 3, 0, 2, 2);
Vector4_Comp4_RO (wxzw, 3, 0, 2, 3);
Vector4_Comp4_RO (wxwx, 3, 0, 3, 0);
Vector4_Comp4_RO (wxwy, 3, 0, 3, 1);
Vector4_Comp4_RO (wxwz, 3, 0, 3, 2);
Vector4_Comp4_RO (wxww, 3, 0, 3, 3);
Vector4_Comp4_RO (wyxx, 3, 1, 0, 0);
Vector4_Comp4_RO (wyxy, 3, 1, 0, 1);
Vector4_Comp4_RW (wyxz, 3, 1, 0, 2);
Vector4_Comp4_RO (wyxw, 3, 1, 0, 3);
Vector4_Comp4_RO (wyyx, 3, 1, 1, 0);
Vector4_Comp4_RO (wyyy, 3, 1, 1, 1);
Vector4_Comp4_RO (wyyz, 3, 1, 1, 2);
Vector4_Comp4_RO (wyyw, 3, 1, 1, 3);
Vector4_Comp4_RW (wyzx, 3, 1, 2, 0);
Vector4_Comp4_RO (wyzy, 3, 1, 2, 1);
Vector4_Comp4_RO (wyzz, 3, 1, 2, 2);
Vector4_Comp4_RO (wyzw, 3, 1, 2, 3);
Vector4_Comp4_RO (wywx, 3, 1, 3, 0);
Vector4_Comp4_RO (wywy, 3, 1, 3, 1);
Vector4_Comp4_RO (wywz, 3, 1, 3, 2);
Vector4_Comp4_RO (wyww, 3, 1, 3, 3);
Vector4_Comp4_RO (wzxx, 3, 2, 0, 0);
Vector4_Comp4_RW (wzxy, 3, 2, 0, 1);
Vector4_Comp4_RO (wzxz, 3, 2, 0, 2);
Vector4_Comp4_RO (wzxw, 3, 2, 0, 3);
Vector4_Comp4_RW (wzyx, 3, 2, 1, 0);
Vector4_Comp4_RO (wzyy, 3, 2, 1, 1);
Vector4_Comp4_RO (wzyz, 3, 2, 1, 2);
Vector4_Comp4_RO (wzyw, 3, 2, 1, 3);
Vector4_Comp4_RO (wzzx, 3, 2, 2, 0);
Vector4_Comp4_RO (wzzy, 3, 2, 2, 1);
Vector4_Comp4_RO (wzzz, 3, 2, 2, 2);
Vector4_Comp4_RO (wzzw, 3, 2, 2, 3);
Vector4_Comp4_RO (wzwx, 3, 2, 3, 0);
Vector4_Comp4_RO (wzwy, 3, 2, 3, 1);
Vector4_Comp4_RO (wzwz, 3, 2, 3, 2);
Vector4_Comp4_RO (wzww, 3, 2, 3, 3);
Vector4_Comp4_RO (wwxx, 3, 3, 0, 0);
Vector4_Comp4_RO (wwxy, 3, 3, 0, 1);
Vector4_Comp4_RO (wwxz, 3, 3, 0, 2);
Vector4_Comp4_RO (wwxw, 3, 3, 0, 3);
Vector4_Comp4_RO (wwyx, 3, 3, 1, 0);
Vector4_Comp4_RO (wwyy, 3, 3, 1, 1);
Vector4_Comp4_RO (wwyz, 3, 3, 1, 2);
Vector4_Comp4_RO (wwyw, 3, 3, 1, 3);
Vector4_Comp4_RO (wwzx, 3, 3, 2, 0);
Vector4_Comp4_RO (wwzy, 3, 3, 2, 1);
Vector4_Comp4_RO (wwzz, 3, 3, 2, 2);
Vector4_Comp4_RO (wwzw, 3, 3, 2, 3);
Vector4_Comp4_RO (wwwx, 3, 3, 3, 0);
Vector4_Comp4_RO (wwwy, 3, 3, 3, 1);
Vector4_Comp4_RO (wwwz, 3, 3, 3, 2);
Vector4_Comp4_RO (wwww, 3, 3, 3, 3);
};

// undefine macros

#undef Vector2_AssignOps
#undef Vector3_AssignOps
#undef Vector4_AssignOps
#undef Vector2_CastingOp
#undef Vector3_CastingOp
#undef Vector4_CastingOp
#undef Vector2_Comp2_RO
#undef Vector3_Comp2_RO
#undef Vector3_Comp3_RO
#undef Vector4_Comp2_RO
#undef Vector4_Comp3_RO
#undef Vector4_Comp4_RO
#undef Vector2_Comp2_RW
#undef Vector3_Comp2_RW
#undef Vector3_Comp3_RW
#undef Vector4_Comp2_RW
#undef Vector4_Comp3_RW
#undef Vector4_Comp4_RW

// Vector2 operators

inline Vector2 operator + (const Vector2 & Src)
{
return (Src);
}

inline Vector2 operator - (const Vector2 & Src)
{
return (Vector2 (-Src.x, -Src.y));
}

inline Vector2 operator + (const Vector2 & Src1, const Vector2 & Src2)
{
return (Vector2 (Src1.x + Src2.x, Src1.y + Src2.y));
}

inline Vector2 operator - (const Vector2 & Src1, const Vector2 & Src2)
{
return (Vector2 (Src1.x - Src2.x, Src1.y - Src2.y));
}

inline Vector2 operator * (const Vector2 & Src1, const Vector2 & Src2)
{
return (Vector2 (Src1.x * Src2.x, Src1.y * Src2.y));
}

inline Vector2 operator / (const Vector2 & Src1, const Vector2 & Src2)
{
return (Vector2 (Src1.x / Src2.x, Src1.y / Src2.y));
}

inline Vector2 & operator += (Vector2 & Dst, const Vector2 & Src)
{
Dst.x += Src.x;
Dst.y += Src.y;

return (Dst);
}

inline Vector2 & operator -= (Vector2 & Dst, const Vector2 & Src)
{
Dst.x -= Src.x;
Dst.y -= Src.y;

return (Dst);
}

inline Vector2 & operator *= (Vector2 & Dst, const Vector2 & Src)
{
Dst.x *= Src.x;
Dst.y *= Src.y;

return (Dst);
}

inline Vector2 & operator /= (Vector2 & Dst, const Vector2 & Src)
{
Dst.x /= Src.x;
Dst.y /= Src.y;

return (Dst);
}

inline bool operator == (const Vector2 & Src1, const Vector2 & Src2)
{
return ((Src1.x == Src2.x) && (Src1.y == Src2.y));
}

inline bool operator != (const Vector2 & Src1, const Vector2 & Src2)
{
return ((Src1.x != Src2.x) || (Src1.y != Src2.y));
}

// Vector3 operators

inline Vector3 operator + (const Vector3 & Src)
{
return (Src);
}

inline Vector3 operator - (const Vector3 & Src)
{
return (Vector3 (-Src.x, -Src.y, -Src.z));
}

inline Vector3 operator + (const Vector3 & Src1, const Vector3 & Src2)
{
return (Vector3 (Src1.x + Src2.x, Src1.y + Src2.y, Src1.z + Src2.z));
}

inline Vector3 operator - (const Vector3 & Src1, const Vector3 & Src2)
{
return (Vector3 (Src1.x - Src2.x, Src1.y - Src2.y, Src1.z - Src2.z));
}

inline Vector3 operator * (const Vector3 & Src1, const Vector3 & Src2)
{
return (Vector3 (Src1.x * Src2.x, Src1.y * Src2.y, Src1.z * Src2.z));
}

inline Vector3 operator / (const Vector3 & Src1, const Vector3 & Src2)
{
return (Vector3 (Src1.x / Src2.x, Src1.y / Src2.y, Src1.z / Src2.z));
}

inline Vector3 & operator += (Vector3 & Dst, const Vector3 & Src)
{
Dst.x += Src.x;
Dst.y += Src.y;
Dst.z += Src.z;

return (Dst);
}

inline Vector3 & operator -= (Vector3 & Dst, const Vector3 & Src)
{
Dst.x -= Src.x;
Dst.y -= Src.y;
Dst.z -= Src.z;

return (Dst);
}

inline Vector3 & operator *= (Vector3 & Dst, const Vector3 & Src)
{
Dst.x *= Src.x;
Dst.y *= Src.y;
Dst.z *= Src.z;

return (Dst);
}

inline Vector3 & operator /= (Vector3 & Dst, const Vector3 & Src)
{
Dst.x /= Src.x;
Dst.y /= Src.y;
Dst.z /= Src.z;

return (Dst);
}

inline bool operator == (const Vector3 & Src1, const Vector3 & Src2)
{
return ((Src1.x == Src2.x) && (Src1.y == Src2.y) && (Src1.z == Src2.z));
}

inline bool operator != (const Vector3 & Src1, const Vector3 & Src2)
{
return ((Src1.x != Src2.x) || (Src1.y != Src2.y) || (Src1.z != Src2.z));
}

// Vector4 operators

inline Vector4 operator + (const Vector4 & Src)
{
return (Src);
}

inline Vector4 operator - (const Vector4 & Src)
{
return (Vector4 (-Src.x, -Src.y, -Src.z, -Src.w));
}

inline Vector4 operator + (const Vector4 & Src1, const Vector4 & Src2)
{
return (Vector4 (Src1.x + Src2.x, Src1.y + Src2.y, Src1.z + Src2.z, Src1.w + Src2.w));
}

inline Vector4 operator - (const Vector4 & Src1, const Vector4 & Src2)
{
return (Vector4 (Src1.x - Src2.x, Src1.y - Src2.y, Src1.z - Src2.z, Src1.w - Src2.w));
}

inline Vector4 operator * (const Vector4 & Src1, const Vector4 & Src2)
{
return (Vector4 (Src1.x * Src2.x, Src1.y * Src2.y, Src1.z * Src2.z, Src1.w * Src2.w));
}

inline Vector4 operator / (const Vector4 & Src1, const Vector4 & Src2)
{
return (Vector4 (Src1.x / Src2.x, Src1.y / Src2.y, Src1.z / Src2.z, Src1.w / Src2.w));
}

inline Vector4 & operator += (Vector4 & Dst, const Vector4 & Src)
{
Dst.x += Src.x;
Dst.y += Src.y;
Dst.z += Src.z;
Dst.w += Src.w;

return (Dst);
}

inline Vector4 & operator -= (Vector4 & Dst, const Vector4 & Src)
{
Dst.x -= Src.x;
Dst.y -= Src.y;
Dst.z -= Src.z;
Dst.w -= Src.w;

return (Dst);
}

inline Vector4 & operator *= (Vector4 & Dst, const Vector4 & Src)
{
Dst.x *= Src.x;
Dst.y *= Src.y;
Dst.z *= Src.z;
Dst.w *= Src.w;

return (Dst);
}

inline Vector4 & operator /= (Vector4 & Dst, const Vector4 & Src)
{
Dst.x /= Src.x;
Dst.y /= Src.y;
Dst.z /= Src.z;
Dst.w /= Src.w;

return (Dst);
}

inline bool operator == (const Vector4 & Src1, const Vector4 & Src2)
{
return ((Src1.x == Src2.x) && (Src1.y == Src2.y) && (Src1.z == Src2.z) && (Src1.w == Src2.w));
}

inline bool operator != (const Vector4 & Src1, const Vector4 & Src2)
{
return ((Src1.x != Src2.x) || (Src1.y != Src2.y) || (Src1.z != Src2.z) || (Src1.w != Src2.w));
}

// additional operators for mixed types

inline Vector2 operator + (float Src1, const Vector2 & Src2) { return (Vector2 (Src1, Src1) + Src2); }
inline Vector3 operator + (float Src1, const Vector3 & Src2) { return (Vector3 (Src1, Src1, Src1) + Src2); }
inline Vector4 operator + (float Src1, const Vector4 & Src2) { return (Vector4 (Src1, Src1, Src1, Src1) + Src2); }
inline Vector2 operator + (const Vector2 & Src1, float Src2) { return (Src1 + Vector2 (Src2, Src2)); }
inline Vector3 operator + (const Vector2 & Src1, const Vector3 & Src2) { return (Vector3 (Src1.xy, Src1.y) + Src2); }
inline Vector4 operator + (const Vector2 & Src1, const Vector4 & Src2) { return (Vector4 (Src1.xy, Src1.yy) + Src2); }
inline Vector3 operator + (const Vector3 & Src1, float Src2) { return (Src1 + Vector3 (Src2, Src2, Src2)); }
inline Vector3 operator + (const Vector3 & Src1, const Vector2 & Src2) { return (Src1 + Vector3 (Src2.xy, Src2.y)); }
inline Vector4 operator + (const Vector3 & Src1, const Vector4 & Src2) { return (Vector4 (Src1.xyz, Src1.z) + Src2); }
inline Vector4 operator + (const Vector4 & Src1, float Src2) { return (Src1 + Vector4 (Src2, Src2, Src2, Src2)); }
inline Vector4 operator + (const Vector4 & Src1, const Vector2 & Src2) { return (Src1 + Vector4 (Src2.xy, Src2.yy)); }
inline Vector4 operator + (const Vector4 & Src1, const Vector3 & Src2) { return (Src1 + Vector4 (Src2.xyz, Src2.z)); }

inline Vector2 operator - (float Src1, const Vector2 & Src2) { return (Vector2 (Src1, Src1) - Src2); }
inline Vector3 operator - (float Src1, const Vector3 & Src2) { return (Vector3 (Src1, Src1, Src1) - Src2); }
inline Vector4 operator - (float Src1, const Vector4 & Src2) { return (Vector4 (Src1, Src1, Src1, Src1) - Src2); }
inline Vector2 operator - (const Vector2 & Src1, float Src2) { return (Src1 - Vector2 (Src2, Src2)); }
inline Vector3 operator - (const Vector2 & Src1, const Vector3 & Src2) { return (Vector3 (Src1.xy, Src1.y) - Src2); }
inline Vector4 operator - (const Vector2 & Src1, const Vector4 & Src2) { return (Vector4 (Src1.xy, Src1.yy) - Src2); }
inline Vector3 operator - (const Vector3 & Src1, float Src2) { return (Src1 - Vector3 (Src2, Src2, Src2)); }
inline Vector3 operator - (const Vector3 & Src1, const Vector2 & Src2) { return (Src1 - Vector3 (Src2.xy, Src2.y)); }
inline Vector4 operator - (const Vector3 & Src1, const Vector4 & Src2) { return (Vector4 (Src1.xyz, Src1.z) - Src2); }
inline Vector4 operator - (const Vector4 & Src1, float Src2) { return (Src1 - Vector4 (Src2, Src2, Src2, Src2)); }
inline Vector4 operator - (const Vector4 & Src1, const Vector2 & Src2) { return (Src1 - Vector4 (Src2.xy, Src2.yy)); }
inline Vector4 operator - (const Vector4 & Src1, const Vector3 & Src2) { return (Src1 - Vector4 (Src2.xyz, Src2.z)); }

inline Vector2 operator * (float Src1, const Vector2 & Src2) { return (Vector2 (Src1, Src1) * Src2); }
inline Vector3 operator * (float Src1, const Vector3 & Src2) { return (Vector3 (Src1, Src1, Src1) * Src2); }
inline Vector4 operator * (float Src1, const Vector4 & Src2) { return (Vector4 (Src1, Src1, Src1, Src1) * Src2); }
inline Vector2 operator * (const Vector2 & Src1, float Src2) { return (Src1 * Vector2 (Src2, Src2)); }
inline Vector3 operator * (const Vector2 & Src1, const Vector3 & Src2) { return (Vector3 (Src1.xy, Src1.y) * Src2); }
inline Vector4 operator * (const Vector2 & Src1, const Vector4 & Src2) { return (Vector4 (Src1.xy, Src1.yy) * Src2); }
inline Vector3 operator * (const Vector3 & Src1, float Src2) { return (Src1 * Vector3 (Src2, Src2, Src2)); }
inline Vector3 operator * (const Vector3 & Src1, const Vector2 & Src2) { return (Src1 * Vector3 (Src2.xy, Src2.y)); }
inline Vector4 operator * (const Vector3 & Src1, const Vector4 & Src2) { return (Vector4 (Src1.xyz, Src1.z) * Src2); }
inline Vector4 operator * (const Vector4 & Src1, float Src2) { return (Src1 * Vector4 (Src2, Src2, Src2, Src2)); }
inline Vector4 operator * (const Vector4 & Src1, const Vector2 & Src2) { return (Src1 * Vector4 (Src2.xy, Src2.yy)); }
inline Vector4 operator * (const Vector4 & Src1, const Vector3 & Src2) { return (Src1 * Vector4 (Src2.xyz, Src2.z)); }

inline Vector2 operator / (float Src1, const Vector2 & Src2) { return (Vector2 (Src1, Src1) / Src2); }
inline Vector3 operator / (float Src1, const Vector3 & Src2) { return (Vector3 (Src1, Src1, Src1) / Src2); }
inline Vector4 operator / (float Src1, const Vector4 & Src2) { return (Vector4 (Src1, Src1, Src1, Src1) / Src2); }
inline Vector2 operator / (const Vector2 & Src1, float Src2) { return (Src1 / Vector2 (Src2, Src2)); }
inline Vector3 operator / (const Vector2 & Src1, const Vector3 & Src2) { return (Vector3 (Src1.xy, Src1.y) / Src2); }
inline Vector4 operator / (const Vector2 & Src1, const Vector4 & Src2) { return (Vector4 (Src1.xy, Src1.yy) / Src2); }
inline Vector3 operator / (const Vector3 & Src1, float Src2) { return (Src1 / Vector3 (Src2, Src2, Src2)); }
inline Vector3 operator / (const Vector3 & Src1, const Vector2 & Src2) { return (Src1 / Vector3 (Src2.xy, Src2.y)); }
inline Vector4 operator / (const Vector3 & Src1, const Vector4 & Src2) { return (Vector4 (Src1.xyz, Src1.z) / Src2); }
inline Vector4 operator / (const Vector4 & Src1, float Src2) { return (Src1 / Vector4 (Src2, Src2, Src2, Src2)); }
inline Vector4 operator / (const Vector4 & Src1, const Vector2 & Src2) { return (Src1 / Vector4 (Src2.xy, Src2.yy)); }
inline Vector4 operator / (const Vector4 & Src1, const Vector3 & Src2) { return (Src1 / Vector4 (Src2.xyz, Src2.z)); }

inline Vector2 & operator += (Vector2 & Dst, float Src) { return (Dst += Vector2 (Src, Src)); }
inline Vector3 & operator += (Vector3 & Dst, float Src) { return (Dst += Vector3 (Src, Src, Src)); }
inline Vector3 & operator += (Vector3 & Dst, const Vector2 & Src) { return (Dst += Vector3 (Src.xy, Src.y)); }
inline Vector4 & operator += (Vector4 & Dst, float Src) { return (Dst += Vector4 (Src, Src, Src, Src)); }
inline Vector4 & operator += (Vector4 & Dst, const Vector2 & Src) { return (Dst += Vector4 (Src.xy, Src.yy)); }
inline Vector4 & operator += (Vector4 & Dst, const Vector3 & Src) { return (Dst += Vector4 (Src.xyz, Src.z)); }

inline Vector2 & operator -= (Vector2 & Dst, float Src) { return (Dst -= Vector2 (Src, Src)); }
inline Vector3 & operator -= (Vector3 & Dst, float Src) { return (Dst -= Vector3 (Src, Src, Src)); }
inline Vector3 & operator -= (Vector3 & Dst, const Vector2 & Src) { return (Dst -= Vector3 (Src.xy, Src.y)); }
inline Vector4 & operator -= (Vector4 & Dst, float Src) { return (Dst -= Vector4 (Src, Src, Src, Src)); }
inline Vector4 & operator -= (Vector4 & Dst, const Vector2 & Src) { return (Dst -= Vector4 (Src.xy, Src.yy)); }
inline Vector4 & operator -= (Vector4 & Dst, const Vector3 & Src) { return (Dst -= Vector4 (Src.xyz, Src.z)); }

inline Vector2 & operator *= (Vector2 & Dst, float Src) { return (Dst *= Vector2 (Src, Src)); }
inline Vector3 & operator *= (Vector3 & Dst, float Src) { return (Dst *= Vector3 (Src, Src, Src)); }
inline Vector3 & operator *= (Vector3 & Dst, const Vector2 & Src) { return (Dst *= Vector3 (Src.xy, Src.y)); }
inline Vector4 & operator *= (Vector4 & Dst, float Src) { return (Dst *= Vector4 (Src, Src, Src, Src)); }
inline Vector4 & operator *= (Vector4 & Dst, const Vector2 & Src) { return (Dst *= Vector4 (Src.xy, Src.yy)); }
inline Vector4 & operator *= (Vector4 & Dst, const Vector3 & Src) { return (Dst *= Vector4 (Src.xyz, Src.z)); }

inline Vector2 & operator /= (Vector2 & Dst, float Src) { return (Dst /= Vector2 (Src, Src)); }
inline Vector3 & operator /= (Vector3 & Dst, float Src) { return (Dst /= Vector3 (Src, Src, Src)); }
inline Vector3 & operator /= (Vector3 & Dst, const Vector2 & Src) { return (Dst /= Vector3 (Src.xy, Src.y)); }
inline Vector4 & operator /= (Vector4 & Dst, float Src) { return (Dst /= Vector4 (Src, Src, Src, Src)); }
inline Vector4 & operator /= (Vector4 & Dst, const Vector2 & Src) { return (Dst /= Vector4 (Src.xy, Src.yy)); }
inline Vector4 & operator /= (Vector4 & Dst, const Vector3 & Src) { return (Dst /= Vector4 (Src.xyz, Src.z)); }

// Vector2 functions

inline float Length (const Vector2 & Src)
{
return (sqrtf (Src.x * Src.x + Src.y * Src.y));
}

inline float LengthSqr (const Vector2 & Src)
{
return (Src.x * Src.x + Src.y * Src.y);
}

inline float DotProd (const Vector2 & Src1, const Vector2 & Src2)
{
return (Src1.x * Src2.x + Src1.y * Src2.y);
}

inline Vector2 Normalize (const Vector2 & Src)
{
return (Src / Length (Src));
}

// Vector3 functions

inline float Length (const Vector3 & Src)
{
return (sqrtf (Src.x * Src.x + Src.y * Src.y + Src.z * Src.z));
}

inline float LengthSqr (const Vector3 & Src)
{
return (Src.x * Src.x + Src.y * Src.y + Src.z * Src.z);
}

inline float DotProd (const Vector3 & Src1, const Vector3 & Src2)
{
return (Src1.x * Src2.x + Src1.y * Src2.y + Src1.z * Src2.z);
}

inline Vector3 CrossProd (const Vector3 & Src1, const Vector3 & Src2)
{
return (Src1.yzx * Src2.zxy - Src1.zxy * Src2.yzx);
}

inline Vector3 Normalize (const Vector3 & Src)
{
return (Src / Length (Src));
}

#endif // _INC_VECTORS_H_

Für Matrizen werde ich mir noch etwas ähnliches bauen, um direkt auf einzelne Zeilen und Spalten in Vektorform zugreifen zu können. Für Farben (RGBA mit vier floats) lohnt sich das auch noch.

ScottManDeath
2006-01-24, 00:13:33
Cool, danke :)

Ich hoffe mal, dass Du die


....
Vector4_Comp4_RO (zywy, 2, 1, 3, 1);
Vector4_Comp4_RO (zywz, 2, 1, 3, 2);
Vector4_Comp4_RO (zyww, 2, 1, 3, 3);
....


automatisch generiert hast ;).

Ich finde das mygeneration nicht schlecht, man schreibt im prinzip ähnlich ASP oder JSP in C#, VB.NET eine Mischung aus Text und Befehlen in Tags, die dann ausgeführt werden und dann ein im Output wasauchimmmer stehen habe. Finde ich praktischer, als sich jedesmal für diesen Zweck eine kleines C++ Programm zu schreiben :)

Neomi
2006-01-24, 02:24:27
Ich hoffe mal, dass Du die ... automatisch generiert hast ;).

Nein, die habe ich manuell gemacht, aber natürlich nicht ohne massig Copy&Paste. Das ist relativ schnell erledigt, auch wenn es erstmal nach viel aussieht. Die manuelle Unterteilung in RO und RW hätte ich mir gerne gespart, aber leider kann man in einem Makro kein #if unterbringen.

ScottManDeath
2007-01-18, 02:03:13
Da ich nun endlich dazu gekommen bin, anständige Vektor Klassen in meine Bibliothek einzubauen (sprich Deinen Code zu hacken :redface: ), wollte ich mal fragen, ob Du Deinen Code noch erweitert hast um Support für Matrizen?

*sich schämt dass er Code schnorren geht*

Eruphus
2007-01-18, 14:44:13
inline Vector3 cross1 (Vector3 v1, Vector3 v2)
{
Vector3 v;

v.x = v1.y * v2.z - v1.z * v2.y;
v.y = v1.z * v2.x - v1.x * v2.z;
v.z = v1.x * v2.y - v1.y * v2.x;

return (v);
}

inline Vector3 cross2 (Vector3 v1, Vector3 v2)
{
return (v1.yzx * v2.zxy - v1.zxy * v2.yzx);
}



Also, ich zähle für .xyz 3 Kontextwechsel.
für die "*" einen und für "+" auch einen

macht 4*3 + 1 + 2*1 = 15 pro Aufruf....

Ich schiebe es auf das häufige auftreten der Vector3 Constructoren...
Was bei cross1 komplett wegfällt.

p.S. Ich kanns mal durch den VS05 jagen; ich würd mich aber um deine Testroutine bemühen um möglichst gleiche voraussetzungen zuschaffen


MFG Ruph

Neomi
2007-01-21, 16:56:35
Da ich nun endlich dazu gekommen bin, anständige Vektor Klassen in meine Bibliothek einzubauen (sprich Deinen Code zu hacken :redface: ), wollte ich mal fragen, ob Du Deinen Code noch erweitert hast um Support für Matrizen?

Den hatte ich inzwischen um einige Dinge erweitert, es ist insgesamt ein Kompromis aus Performance und Flexibilität geworden. Ich habe Vector2, Vector3, Vector4, Matrix3x3, Matrix4x4, Color2, Color3, Color4, ColHSV, ColHSL, Quaternion, Hermite und P5Spline (Hermite mit Zusatzparametern für C2-Stetigkeit).

Den Code kann ich dir zuschicken, schick mir einfach eine PM mit deiner Mailadresse.

Ich schiebe es auf das häufige auftreten der Vector3 Constructoren...
Was bei cross1 komplett wegfällt.

p.S. Ich kanns mal durch den VS05 jagen; ich würd mich aber um deine Testroutine bemühen um möglichst gleiche voraussetzungen zuschaffen

Danke für das Angebot, aber das hat sich inzwischen alles längst erledigt. Ist ja auch schon ein Jahr her. Das mit den Konstruktoren war mir klar. Mir ging es damals darum, daß der Optimizer trotz identischem Optimierungspotential in der flexibleren Variante ein paar Schritte nicht durchführte.

Eruphus
2007-01-21, 21:44:11
Sorry, hatte nicht gesehen das der Thread schon soooo alt ist.

Hast du dann den Code noch schneller bekommen oder ist es dabei geblieben?


MFG

Ruph