www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Velocity Math Module

reply Kyle Furlong <kylefurlong gmail.com> writes:
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

I just started work on Velocity, a game engine. I want the math module 
to use templated structs for vectors and matrices. Theses structs will 
overload the different operators (+,*,-)with fast assembly 
implementations of the operations.

I'm running into some errors which I cant understand due to my shaky 
grasp of the language. Attached is what I have so far for the Vector 
struct; any pointers are appreciated.

p.s. - Velocity is hosted at dsource. At the moment the license is tbd.
Jan 24 2006
next sibling parent reply Mike Parker <aldacron71 yahoo.com> writes:
Kyle Furlong wrote:

 I'm running into some errors which I cant understand due to my shaky 
 grasp of the language. Attached is what I have so far for the Vector 
 struct; any pointers are appreciated.
 
 p.s. - Velocity is hosted at dsource. At the moment the license is tbd.

What are the errors you are seeing?
Jan 24 2006
parent reply Kyle Furlong <kylefurlong gmail.com> writes:
Mike Parker wrote:
 Kyle Furlong wrote:
 
 I'm running into some errors which I cant understand due to my shaky 
 grasp of the language. Attached is what I have so far for the Vector 
 struct; any pointers are appreciated.

 p.s. - Velocity is hosted at dsource. At the moment the license is tbd.

What are the errors you are seeing?

With this test program: import velocity.math.Vector; int main() { alias Vector!(int,2) Point; Point origin = Point(0,0); Point a = Point(1,1); assert((a + origin) == a); } I get these errors: ---------- Capture Output ----------
 "C:\dmd\bin\build.exe" Vector.d -clean

template declaration, it is a struct \d\import\velocity\math\Vector.d(47): Vector!(int,2) is used as a type \d\import\velocity\math\Vector.d(47): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(47): Vector!(int,2) is used as a type \d\import\velocity\math\Vector.d(47): cannot have parameter of type void \d\import\velocity\math\Vector.d(57): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(57): Vector!(int,2) is used as a type \d\import\velocity\math\Vector.d(57): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(57): Vector!(int,2) is used as a type \d\import\velocity\math\Vector.d(57): cannot have parameter of type void \d\import\velocity\math\Vector.d(67): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(67): Vector!(int,2) is used as a type \d\import\velocity\math\Vector.d(67): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(67): Vector!(int,2) is used as a type \d\import\velocity\math\Vector.d(67): cannot have parameter of type void \d\import\velocity\math\Vector.d(77): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(77): Vector!(int,2) is used as a type \d\import\velocity\math\Vector.d(39): cannot implicitly convert expression (this.storage) of type int[2] to int \d\import\velocity\math\Vector.d(44): cannot implicitly convert expression ((this.storage)[(i)..(j)]) of type int[] to int \d\import\velocity\math\Vector.d: variable velocity.math.Vector.Vector!(int,2).Vector.opAdd.a voids have no value \d\import\velocity\math\Vector.d(49): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(49): Vector!(int,2) is used as a type \d\import\velocity\math\Vector.d(49): variable velocity.math.Vector.Vector!(int,2).Vector.opAdd.ret voids have no value \d\import\velocity\math\Vector.d(52): ret must be an array or pointer type, not int \d\import\velocity\math\Vector.d(52): a must be an array or pointer type, not int \d\import\velocity\math\Vector.d: variable velocity.math.Vector.Vector!(int,2).Vector.opSub.a voids have no value \d\import\velocity\math\Vector.d(59): identifier 'Row' is not defined \d\import\velocity\math\Vector.d(59): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(59): Vector!(int,2,int) is used as a type \d\import\velocity\math\Vector.d(59): variable velocity.math.Vector.Vector!(int,2).Vector.opSub.ret voids have no value \d\import\velocity\math\Vector.d(62): ret must be an array or pointer type, not int \d\import\velocity\math\Vector.d(62): a must be an array or pointer type, not int \d\import\velocity\math\Vector.d: variable velocity.math.Vector.Vector!(int,2).Vector.opAddAssign.a voids have no value \d\import\velocity\math\Vector.d(69): identifier 'Row' is not defined \d\import\velocity\math\Vector.d(69): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(69): Vector!(int,2,int) is used as a type \d\import\velocity\math\Vector.d(69): variable velocity.math.Vector.Vector!(int,2).Vector.opAddAssign.ret voids have no value \d\import\velocity\math\Vector.d(72): ret must be an array or pointer type, not int \d\import\velocity\math\Vector.d(72): a must be an array or pointer type, not int \d\import\velocity\math\Vector.d(79): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(79): Vector!(int,2) is used as a type \d\import\velocity\math\Vector.d(79): variable velocity.math.Vector.Vector!(int,2).Vector.opCall.v voids have no value \d\import\velocity\math\Vector.d(85): v must be an array or pointer type, not int \d\import\velocity\math\Vector.d(5): template instance velocity.math.Vector.Vector!(int,2) error instantiating Vector.d(6): voids have no value Vector.d(6): cannot implicitly convert expression ((opCall)((_arguments_ii),0,0)) of type void to Vector Vector.d(7): voids have no value Vector.d(7): cannot implicitly convert expression ((opCall)((_arguments_ii),1,1)) of type void to Vector Vector.d(8): function velocity.math.Vector.Vector!(int,2).Vector.opAdd (void) does not match argument types (Vector ) Vector.d(8): cannot implicitly convert expression (origin) of type Vector to void Vector.d(8): void has no value Vector.d(8): incompatible types for ((((a).opAdd)(cast(void)(origin))) == (a)): 'void' and 'Vector'
 Terminated with exit code 1.

Jan 24 2006
next sibling parent James Dunne <james.jdunne gmail.com> writes:
Kyle Furlong wrote:
 Mike Parker wrote:
 
 Kyle Furlong wrote:

 I'm running into some errors which I cant understand due to my shaky 
 grasp of the language. Attached is what I have so far for the Vector 
 struct; any pointers are appreciated.

 p.s. - Velocity is hosted at dsource. At the moment the license is tbd.

What are the errors you are seeing?

With this test program: import velocity.math.Vector; int main() { alias Vector!(int,2) Point; Point origin = Point(0,0); Point a = Point(1,1); assert((a + origin) == a); } I get these errors: ---------- Capture Output ---------- > "C:\dmd\bin\build.exe" Vector.d -clean \d\import\velocity\math\Vector.d(47): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(47): Vector!(int,2) is used as a type \d\import\velocity\math\Vector.d(47): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(47): Vector!(int,2) is used as a type \d\import\velocity\math\Vector.d(47): cannot have parameter of type void \d\import\velocity\math\Vector.d(57): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(57): Vector!(int,2) is used as a type \d\import\velocity\math\Vector.d(57): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(57): Vector!(int,2) is used as a type \d\import\velocity\math\Vector.d(57): cannot have parameter of type void \d\import\velocity\math\Vector.d(67): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(67): Vector!(int,2) is used as a type \d\import\velocity\math\Vector.d(67): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(67): Vector!(int,2) is used as a type \d\import\velocity\math\Vector.d(67): cannot have parameter of type void \d\import\velocity\math\Vector.d(77): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(77): Vector!(int,2) is used as a type \d\import\velocity\math\Vector.d(39): cannot implicitly convert expression (this.storage) of type int[2] to int \d\import\velocity\math\Vector.d(44): cannot implicitly convert expression ((this.storage)[(i)..(j)]) of type int[] to int \d\import\velocity\math\Vector.d: variable velocity.math.Vector.Vector!(int,2).Vector.opAdd.a voids have no value \d\import\velocity\math\Vector.d(49): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(49): Vector!(int,2) is used as a type \d\import\velocity\math\Vector.d(49): variable velocity.math.Vector.Vector!(int,2).Vector.opAdd.ret voids have no value \d\import\velocity\math\Vector.d(52): ret must be an array or pointer type, not int \d\import\velocity\math\Vector.d(52): a must be an array or pointer type, not int \d\import\velocity\math\Vector.d: variable velocity.math.Vector.Vector!(int,2).Vector.opSub.a voids have no value \d\import\velocity\math\Vector.d(59): identifier 'Row' is not defined \d\import\velocity\math\Vector.d(59): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(59): Vector!(int,2,int) is used as a type \d\import\velocity\math\Vector.d(59): variable velocity.math.Vector.Vector!(int,2).Vector.opSub.ret voids have no value \d\import\velocity\math\Vector.d(62): ret must be an array or pointer type, not int \d\import\velocity\math\Vector.d(62): a must be an array or pointer type, not int \d\import\velocity\math\Vector.d: variable velocity.math.Vector.Vector!(int,2).Vector.opAddAssign.a voids have no value \d\import\velocity\math\Vector.d(69): identifier 'Row' is not defined \d\import\velocity\math\Vector.d(69): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(69): Vector!(int,2,int) is used as a type \d\import\velocity\math\Vector.d(69): variable velocity.math.Vector.Vector!(int,2).Vector.opAddAssign.ret voids have no value \d\import\velocity\math\Vector.d(72): ret must be an array or pointer type, not int \d\import\velocity\math\Vector.d(72): a must be an array or pointer type, not int \d\import\velocity\math\Vector.d(79): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(79): Vector!(int,2) is used as a type \d\import\velocity\math\Vector.d(79): variable velocity.math.Vector.Vector!(int,2).Vector.opCall.v voids have no value \d\import\velocity\math\Vector.d(85): v must be an array or pointer type, not int \d\import\velocity\math\Vector.d(5): template instance velocity.math.Vector.Vector!(int,2) error instantiating Vector.d(6): voids have no value Vector.d(6): cannot implicitly convert expression ((opCall)((_arguments_ii),0,0)) of type void to Vector Vector.d(7): voids have no value Vector.d(7): cannot implicitly convert expression ((opCall)((_arguments_ii),1,1)) of type void to Vector Vector.d(8): function velocity.math.Vector.Vector!(int,2).Vector.opAdd (void) does not match argument types (Vector ) Vector.d(8): cannot implicitly convert expression (origin) of type Vector to void Vector.d(8): void has no value Vector.d(8): incompatible types for ((((a).opAdd)(cast(void)(origin))) == (a)): 'void' and 'Vector' > Terminated with exit code 1.

Sadly, D's templates don't easily analogue to their C++ brothers. I ran into this same problem attempting something similar to what you've hit. Perhaps I can clear the way for "the template ninja" (Don Clugston) to come in and rescue you! -- Regards, James Dunne
Jan 24 2006
prev sibling next sibling parent reply Agent Orange <Agent_member pathlink.com> writes:
In article <dr6o86$7mq$1 digitaldaemon.com>, Kyle Furlong says...
Mike Parker wrote:
 Kyle Furlong wrote:
 
 I'm running into some errors which I cant understand due to my shaky 
 grasp of the language. Attached is what I have so far for the Vector 
 struct; any pointers are appreciated.

 p.s. - Velocity is hosted at dsource. At the moment the license is tbd.

What are the errors you are seeing?

With this test program: import velocity.math.Vector; int main() { alias Vector!(int,2) Point; Point origin = Point(0,0); Point a = Point(1,1); assert((a + origin) == a); } I get these errors: ---------- Capture Output ----------
 "C:\dmd\bin\build.exe" Vector.d -clean

template declaration, it is a struct \d\import\velocity\math\Vector.d(47): Vector!(int,2) is used as a type \d\import\velocity\math\Vector.d(47): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(47): Vector!(int,2) is used as a type \d\import\velocity\math\Vector.d(47): cannot have parameter of type void \d\import\velocity\math\Vector.d(57): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(57): Vector!(int,2) is used as a type \d\import\velocity\math\Vector.d(57): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(57): Vector!(int,2) is used as a type \d\import\velocity\math\Vector.d(57): cannot have parameter of type void \d\import\velocity\math\Vector.d(67): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(67): Vector!(int,2) is used as a type \d\import\velocity\math\Vector.d(67): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(67): Vector!(int,2) is used as a type \d\import\velocity\math\Vector.d(67): cannot have parameter of type void \d\import\velocity\math\Vector.d(77): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(77): Vector!(int,2) is used as a type \d\import\velocity\math\Vector.d(39): cannot implicitly convert expression (this.storage) of type int[2] to int \d\import\velocity\math\Vector.d(44): cannot implicitly convert expression ((this.storage)[(i)..(j)]) of type int[] to int \d\import\velocity\math\Vector.d: variable velocity.math.Vector.Vector!(int,2).Vector.opAdd.a voids have no value \d\import\velocity\math\Vector.d(49): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(49): Vector!(int,2) is used as a type \d\import\velocity\math\Vector.d(49): variable velocity.math.Vector.Vector!(int,2).Vector.opAdd.ret voids have no value \d\import\velocity\math\Vector.d(52): ret must be an array or pointer type, not int \d\import\velocity\math\Vector.d(52): a must be an array or pointer type, not int \d\import\velocity\math\Vector.d: variable velocity.math.Vector.Vector!(int,2).Vector.opSub.a voids have no value \d\import\velocity\math\Vector.d(59): identifier 'Row' is not defined \d\import\velocity\math\Vector.d(59): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(59): Vector!(int,2,int) is used as a type \d\import\velocity\math\Vector.d(59): variable velocity.math.Vector.Vector!(int,2).Vector.opSub.ret voids have no value \d\import\velocity\math\Vector.d(62): ret must be an array or pointer type, not int \d\import\velocity\math\Vector.d(62): a must be an array or pointer type, not int \d\import\velocity\math\Vector.d: variable velocity.math.Vector.Vector!(int,2).Vector.opAddAssign.a voids have no value \d\import\velocity\math\Vector.d(69): identifier 'Row' is not defined \d\import\velocity\math\Vector.d(69): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(69): Vector!(int,2,int) is used as a type \d\import\velocity\math\Vector.d(69): variable velocity.math.Vector.Vector!(int,2).Vector.opAddAssign.ret voids have no value \d\import\velocity\math\Vector.d(72): ret must be an array or pointer type, not int \d\import\velocity\math\Vector.d(72): a must be an array or pointer type, not int \d\import\velocity\math\Vector.d(79): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(79): Vector!(int,2) is used as a type \d\import\velocity\math\Vector.d(79): variable velocity.math.Vector.Vector!(int,2).Vector.opCall.v voids have no value \d\import\velocity\math\Vector.d(85): v must be an array or pointer type, not int \d\import\velocity\math\Vector.d(5): template instance velocity.math.Vector.Vector!(int,2) error instantiating Vector.d(6): voids have no value Vector.d(6): cannot implicitly convert expression ((opCall)((_arguments_ii),0,0)) of type void to Vector Vector.d(7): voids have no value Vector.d(7): cannot implicitly convert expression ((opCall)((_arguments_ii),1,1)) of type void to Vector Vector.d(8): function velocity.math.Vector.Vector!(int,2).Vector.opAdd (void) does not match argument types (Vector ) Vector.d(8): cannot implicitly convert expression (origin) of type Vector to void Vector.d(8): void has no value Vector.d(8): incompatible types for ((((a).opAdd)(cast(void)(origin))) == (a)): 'void' and 'Vector'
 Terminated with exit code 1.


you cant create a struct template
Jan 24 2006
parent reply Sean Kelly <sean f4.ca> writes:
Agent Orange wrote:
 
 you cant create a struct template

DMD allows it, though the docs say it's illegal. Sean
Jan 24 2006
next sibling parent Oskar Linde <oskar.lindeREM OVEgmail.com> writes:
Sean Kelly wrote:
 Agent Orange wrote:
 you cant create a struct template

DMD allows it, though the docs say it's illegal.

But the doc also says its legal: template.html: "The body of the TemplateDeclaration must be syntactically correct even if never instantiated. Semantic analysis is not done until instantiated. A template forms its own scope, and the template body can contain classes, structs, types, enums, variables, functions, and other templates." /Oskar
Jan 25 2006
prev sibling parent reply Dave <Dave_member pathlink.com> writes:
In article <dr70cq$f0j$1 digitaldaemon.com>, Sean Kelly says...
Agent Orange wrote:
 
 you cant create a struct template

DMD allows it, though the docs say it's illegal.

Can you link to where you saw that... (After all, there are whole libraries built using struct templates and (obviously) supporting code in the reference compiler, so I think the docs. are wrong)? Just want to point it out to Walter so the docs. can be fixed. Thanks, - Dave
Sean

Jan 25 2006
parent Sean Kelly <sean f4.ca> writes:
Dave wrote:
 In article <dr70cq$f0j$1 digitaldaemon.com>, Sean Kelly says...
 Agent Orange wrote:
 you cant create a struct template


Can you link to where you saw that... (After all, there are whole libraries built using struct templates and (obviously) supporting code in the reference compiler, so I think the docs. are wrong)? Just want to point it out to Walter so the docs. can be fixed.

He may have already fixed them. I can't find the clause I remember seeing. Sean
Jan 25 2006
prev sibling next sibling parent reply Lucas Goss <lgoss007 gmail.com> writes:
Kyle Furlong wrote:
 Mike Parker wrote:
 Kyle Furlong wrote:

 I'm running into some errors which I cant understand due to my shaky 
 grasp of the language. Attached is what I have so far for the Vector 
 struct; any pointers are appreciated.



As mentioned elsewhere, you can't create a struct template. Anyways, here is a working (or at least somewhat working) version. opEquals wasn't implemented and I didn't test everything, I just got it to compile and made sure it was adding correctly. However the assert will fail since the opEquals isn't implemented. Also I implemented new instead of opCall since I wasn't sure why it was failing (I haven't really used opCall yet). I have a similar version that I'll post later... maybe some collaboration would be nice? Anyways, here it is // main.d import vector; int main(char[][] args) { alias Vector!(int,2) Point; Point origin = new Point(0, 0); Point a = new Point(1,1); assert((a + origin) == a); return 0; } // vector.d module vector; import std.c.stdarg; /************************************************** A fast vector implementation Examples: --- alias Vector!(int,2) Point; Point origin = Point(0,0); --- **************************************************/ class Vector(T, int Dim = 4) { private T[Dim] storage; this(...) { for (int i = 0; i < _arguments.length; i++) { storage[i] = *cast(T*)_argptr; _argptr += T.sizeof; } } T opIndex(int index) { return storage[index]; } T opIndexAssign(T value, int index) { storage[index] = value; return value; } T[] opSlice() { return storage[]; } T[] opSlice(int i, int j) { return storage[i..j]; } Vector opAdd(Vector a) { Vector ret = new Vector(); for(int i = 0; i < Dim; i++) { ret[i] = storage[i] + a[i]; } return ret; } Vector opSub(Vector a) { Vector ret; for(int i = 0; i < Dim; i++) { ret[i] = storage[i] - a[i]; } return ret; } Vector opAddAssign(Vector a) { Vector ret; for(int i = 0; i < Dim; i++) { ret[i] = storage[i] - a[i]; } return ret; } // static Vector opCall(...) // { // Vector v; // // for (int i = 0; i < Dim; i++) // { // if (_arguments[i] == typeid(T)) // { // v[i] = *cast(T *)_argptr; // _argptr += T.sizeof; // } // else assert(0); // } // return v; // } }
Jan 24 2006
next sibling parent Lucas Goss <lgoss007 gmail.com> writes:
As promised, here's my version of a 2-dimensional vector (I also have 
versions with 3 and 4 dimensions). Hmm... I'm also working on a game 
engine...

//=============================================================================
// Lucas Goss
//=============================================================================
module lge.math.vector2;

import std.math;

//=============================================================================
class TVector2(T)
{
public:
	// Members ====================================================
	//-------------------------------------------------------------
	const static TVector2 Zero;
	const static TVector2 UnitX;
	const static TVector2 UnitY;
	
	// Constructors / Destructors =================================
	//-------------------------------------------------------------
	static this()
	{
		Zero = new TVector2(0, 0);
		UnitX = new TVector2(1, 0);
		UnitY = new TVector2(0, 1);
	}
	
	//-------------------------------------------------------------
	this() {}
	
	//-------------------------------------------------------------
	this(T x, T y)
	{
		this.mX = x;
		this.mY = y;
	}
	
	//-------------------------------------------------------------
	this(TVector2 vector)
	{
		mX = vector.x;
		mY = vector.y;
	}
	
	// Operators ==================================================
	//-------------------------------------------------------------
	TVector2 opNeg()
	{
		return new TVector2(-mX, -mY);
	}
	
	//-------------------------------------------------------------
	TVector2 opAdd(TVector2 vector)
	{
		return new TVector2(mX + vector.x, mY + vector.y);
	}
	
	//-------------------------------------------------------------
	TVector2 opSub(TVector2 vector)
	{
		return new TVector2(mX - vector.x, mY - vector.y);
	}
	
	//-------------------------------------------------------------
	TVector2 opMul(T scalar)
	{
		return new TVector2(scalar * mX, scalar * mY);
	}
	
	//-------------------------------------------------------------
	TVector2 opDiv(T scalar)
	{
		if(scalar != 0)
		{
			T invScalar = 1 / scalar;
			return new TVector2(invScalar * mX, invScalar * mY);
		}
		else
		{
			return new TVector2(T.max, T.max);
		}
	}
	
	//-------------------------------------------------------------
	TVector2 opAddAssign(TVector2 vector)
	{
		mX += vector.x;
		mY += vector.y;
		return this;
	}
	
	//-------------------------------------------------------------
	TVector2 opSubAssign(TVector2 vector)
	{
		mX -= vector.x;
		mY -= vector.y;
		return this;
	}
	
	//-------------------------------------------------------------
	TVector2 opMulAssign(T scalar)
	{
		mX *= scalar;
		mY *= scalar;
		return this;
	}
	
	//-------------------------------------------------------------
	TVector2 opDivAssign(T scalar)
	{
		if(scalar != 0)
		{
			T invScalar = 1 / scalar;
			mX *= invScalar;
			mY *= invScalar;
		}
		else
		{
			mX = T.max;
			mY = T.max;
		}
		
		return this;
	}
	
	//-------------------------------------------------------------
	int opEquals(TVector2 vector)
	{
		if(mX == vector.x && mY == vector.y)
		{
			return 1;
		}
		
		return 0;
	}
	
	// Properties =================================================
	//-------------------------------------------------------------
	T x()
	{
		return mX;
	}
	
	//-------------------------------------------------------------
	T x(T value)
	{
		mX = value;
	}
	
	//-------------------------------------------------------------
	T y()
	{
		return mY;
	}
	
	//-------------------------------------------------------------
	T y(T value)
	{
		mY = value;
	}
		
	// Methods ====================================================
	//-------------------------------------------------------------
	T dot(TVector2 vector)
	{
		return (mX * vector.x + mY * vector.y);
	}
	
	//-------------------------------------------------------------
	T dotPerpendicular(TVector2 vector)
	{
		return (mX * vector.y - vector.x * mY);
	}
	
	//-------------------------------------------------------------
	void getBarycentrics(TVector2 v0, TVector2 v1, TVector2 v2,
		T barycentric[3])
	{
		// TODO
	}
	
	//-------------------------------------------------------------
	T length()
	{
		return sqrt(mX * mX + mY * mY);
	}
	
	//-------------------------------------------------------------
	T lengthSquared()
	{
		return (mX * mX + mY * mY);
	}
	
	//-------------------------------------------------------------
	TVector2 normalize()
	{
		T vectorLength = length();
		
		if(vectorLength > 0)
		{
			T invLength = 1 / vectorLength;
			mX *= invLength;
			mY *= invLength;
		}
		else
		{
			mX = 0;
			mY = 0;
		}
		
		return this;
	}
	
	//-------------------------------------------------------------
	TVector2 perpendicular()
	{
		return new TVector2(mY, -mX);
	}
	
	// Static Methods =============================================
	//-------------------------------------------------------------
	static void orthonormalize(inout TVector2 u, inout TVector2 v)
	{
		u.normalize();
		
		T dot0 = u.dot(v);
		v -= u * dot0;
		v.normalize();
	}
	
	//-------------------------------------------------------------
	static void orthonormalBasis(inout TVector2 u, inout TVector2 v,
		bit unitLengthV)
	{
		if(!unitLengthV)
		{
			v.normalize();
		}
		
		u = v.perpendicular();
	}
	
private:
	// Members ====================================================
	//-------------------------------------------------------------	
	T mX = 0;
	T mY = 0;
	
	// Unittest ===================================================
	//-------------------------------------------------------------
	unittest
	{
     		// Zero, UnitX, UnitY
	    	assert(Zero.x == 0 && Zero.y == 0);
     		assert(UnitX.x == 1 && UnitX.y == 0);
	    	assert(UnitY.x == 0 && UnitY.y == 1);
     	
     		// this(), this(x, y), this(Vector2)
	    	TVector2!(float) v0, v1, v2;
     	
     		v0 = new TVector2!(float)();
	    	assert(v0.x == 0 && v0.y == 0);
     	
     		v1 = new TVector2!(float)(1, 2);
	    	assert(v1.x == 1 && v1.y == 2);
     	
     		v2 = new TVector2!(float)(v1);
	    	assert(v2.x == 1 && v2.y == 2);
     	
     		// opNeg, opAdd, opSub, opMul, opDiv
	    	v1 = -v2;
     		assert(v1.x == -1 && v1.y == -2);
     	
	    	v1 = v2;
     		v0 = v1 + v2;
	    	assert(v0.x == 2 && v0.y == 4);
     	
	    	v0 = v1 - v2;
     		assert(v0.x == 0 && v0.y == 0);
     	
	    	v0 = v1 * 3;
     		assert(v0.x == 3 && v0.y == 6);
     	
	    	v0 = v1 / 2;
     		assert(v0.x == 0.5 && v0.y == 1);
     	
	    	// opAddAssign, opSubAssign, opMulAssign, opDivAssign
	    	v0 += v1;
     		assert(v0.x == 1.5 && v0.y == 3);
     	
	    	v2.x = 4;
     		v2.y = 5;
     	
	    	v2 -= v0;
     		assert(v2.x == 2.5 && v2.y == 2);
     	
	    	v1 *= 4;
     		assert(v1.x == 4 && v1.y == 8);
     	
	    	v1 /= 2;
     		assert(v1.x == 2 && v1.y == 4);
     	    	
	    	// opEquals
     		v2.x = 2;
	    	v2.y = 4;
     		assert(v1 == v2);
     	
	    	// x, y
     		v0.x = 1;
	    	v0.y = 1;
     		v1.x = v0.x;
	    	v1.y = 2;
     		v2.x = v1.y;
	    	v2.y = 0;
     	
     		// dot, dotPerpendicular, length, lengthSquared
	    	T result = v0.dot(v1);
     		assert(result == 3);
     	
	    	result = v0.dotPerpendicular(v1);
     		assert(result == 1);
     	
	    	result = v2.length();
     		assert(result == 2);
     	
	    	result = v2.lengthSquared();
     		assert(result == 4);
     	
	    	// normalize, perpendicular
     		v2.normalize();
	    	assert(v2.x == 1 && v2.y == 0);
     	
	    	v0 = v1.perpendicular();
     		assert(v0.x == 2 && v0.y == -1);
	}
}

// Instantiated Templates
//=============================================================================
alias TVector2!(float) Vector2f;
alias TVector2!(double) Vector2d;
alias TVector2!(real) Vector2;
Jan 24 2006
prev sibling parent Kyle Furlong <kylefurlong gmail.com> writes:
Lucas Goss wrote:
 Kyle Furlong wrote:
 Mike Parker wrote:
 Kyle Furlong wrote:

 I'm running into some errors which I cant understand due to my shaky 
 grasp of the language. Attached is what I have so far for the Vector 
 struct; any pointers are appreciated.



As mentioned elsewhere, you can't create a struct template. Anyways, here is a working (or at least somewhat working) version. opEquals wasn't implemented and I didn't test everything, I just got it to compile and made sure it was adding correctly. However the assert will fail since the opEquals isn't implemented. Also I implemented new instead of opCall since I wasn't sure why it was failing (I haven't really used opCall yet). I have a similar version that I'll post later... maybe some collaboration would be nice? Anyways, here it is // main.d import vector; int main(char[][] args) { alias Vector!(int,2) Point; Point origin = new Point(0, 0); Point a = new Point(1,1); assert((a + origin) == a); return 0; } // vector.d module vector; import std.c.stdarg; /************************************************** A fast vector implementation Examples: --- alias Vector!(int,2) Point; Point origin = Point(0,0); --- **************************************************/ class Vector(T, int Dim = 4) { private T[Dim] storage; this(...) { for (int i = 0; i < _arguments.length; i++) { storage[i] = *cast(T*)_argptr; _argptr += T.sizeof; } } T opIndex(int index) { return storage[index]; } T opIndexAssign(T value, int index) { storage[index] = value; return value; } T[] opSlice() { return storage[]; } T[] opSlice(int i, int j) { return storage[i..j]; } Vector opAdd(Vector a) { Vector ret = new Vector(); for(int i = 0; i < Dim; i++) { ret[i] = storage[i] + a[i]; } return ret; } Vector opSub(Vector a) { Vector ret; for(int i = 0; i < Dim; i++) { ret[i] = storage[i] - a[i]; } return ret; } Vector opAddAssign(Vector a) { Vector ret; for(int i = 0; i < Dim; i++) { ret[i] = storage[i] - a[i]; } return ret; } // static Vector opCall(...) // { // Vector v; // // for (int i = 0; i < Dim; i++) // { // if (_arguments[i] == typeid(T)) // { // v[i] = *cast(T *)_argptr; // _argptr += T.sizeof; // } // else assert(0); // } // return v; // } }

Thanks for the heads up. I'm still waiting for Don to weigh in, but does anyone know how I can get a templated initializer that would work as in the example code?
Jan 24 2006
prev sibling parent Don Clugston <dac nospam.com.au> writes:
Kyle Furlong wrote:
 Mike Parker wrote:
 
 Kyle Furlong wrote:

 I'm running into some errors which I cant understand due to my shaky 
 grasp of the language. Attached is what I have so far for the Vector 
 struct; any pointers are appreciated.


With this test program: import velocity.math.Vector; int main() { alias Vector!(int,2) Point; Point origin = Point(0,0); Point a = Point(1,1); assert((a + origin) == a); } I get these errors: ---------- Capture Output ---------- > "C:\dmd\bin\build.exe" Vector.d -clean \d\import\velocity\math\Vector.d(47): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(47): Vector!(int,2) is used as a type \d\import\velocity\math\Vector.d(47): template instance Vector is not a template declaration, it is a struct \d\import\velocity\math\Vector.d(47): Vector!(int,2) is used as a type \d\import\velocity\math\Vector.d(47): cannot have parameter of type void \d\import\velocity\math\Vector.d(57): template instance Vector is not a template declaration, it is a struct

For future reference: Whenever you see 'void' in a template error message, it normally means there was a semantic error in a template. Especially look out for 'voids have no value'. These error messages don't tell you much other than "the compiler was compiling line 47 of Vector.d when it detected a problem with a template." Sometimes the error messages come out in a strange order; the fundamental problem might not show up until the fourth or fifth error message. Once there's an error in a template, the compiler will spew reams of unhelpful garbage; its common to have 100 error messages caused by a single typo. Although the first error is listed as line 47, that line could be perfectly OK, and the real error could be in another template which is being used in lines 46 or 47.
Jan 25 2006
prev sibling next sibling parent reply Oskar Linde <oskar.lindeREM OVEgmail.com> writes:
Kyle Furlong wrote:
 I just started work on Velocity, a game engine. I want the math module 
 to use templated structs for vectors and matrices. Theses structs will 
 overload the different operators (+,*,-)with fast assembly 
 implementations of the operations.
 
 I'm running into some errors which I cant understand due to my shaky 
 grasp of the language. Attached is what I have so far for the Vector 
 struct; any pointers are appreciated.

There are just a few minor errors in your code. Find below some corrections inline. With those, the code compiles with DMD 0.144. Regards, Oskar
 ------------------------------------------------------------------------
 
 //|
 //|		___    __    ______           __________         
 //|		__ |  / /_______  /______________(_)_  /_____  __
 //|		__ | / /_  _ \_  /_  __ \  ___/_  /_  __/_  / / /
 //|		__ |/ / /  __/  / / /_/ / /__ _  / / /_ _  /_/ / 
 //|		_____/  \___//_/  \____/\___/ /_/  \__/ _\__, /  
 //|		                                      __/____/
 //|			Copyright (c) 2006 Kyle Furlong
 //|
 
 module velocity.math.Vector;
 
 /**************************************************
 	A fast vector implementation
 	
 	Examples:
 	---
 	alias Vector!(int,2) Point;
 	Point origin = Point(0,0);
 	---
 **************************************************/	
 struct Vector(T, int Dim = 4)
 {
 	private T[Dim] storage;
 	
 	T opIndex(int index)
 	{
 		return storage[index];
 	}
 	
 	T opIndexAssign(T value, int index)
 	{
 		storage[index] = value;
 		return value;
 	}
 	
 	T opSlice()

 	{
 		return storage;
 	}
 	
 	T opSlice(int i, int j)

 	{
 		return storage[i..j];
 	}
 	
 	Vector!(T,Dim) opAdd(Vector!(T,Dim) a)
 	{
 		Vector!(T,Dim) ret;
 		for(int i = 0; i < Dim; i++)
 		{
 			ret[i] = storage[i] + a[i];
 		}
 		return ret;
 	}
 	
 	Vector!(T,Dim) opSub(Vector!(T,Dim) a)
 	{
 		Vector!(T,Dim,Row) ret;

 		for(int i = 0; i < Dim; i++)
 		{
 			ret[i] = storage[i] - a[i];
 		}
 		return ret;
 	}
 	
 	Vector!(T,Dim) opAddAssign(Vector!(T,Dim) a)
 	{
 		Vector!(T,Dim,Row) ret;

 		for(int i = 0; i < Dim; i++)
 		{
 			ret[i] = storage[i] - a[i];
 		}
 		return ret;
 	}
 	
 	static Vector!(T,Dim) opCall(...)
 	{
 		Vector!(T,Dim) v;
 			
 		for (int i = 0; i < Dim; i++)
 	    {
 			if (_arguments[i] == typeid(T))
 			{
 			    v[i] = *cast(T *)_argptr;
 			    _argptr += T.sizeof;
 			}
 			else assert(0);
 	    }
 	    return v;
 	}
 }
 

Jan 24 2006
parent reply Kyle Furlong <kylefurlong gmail.com> writes:
Oskar Linde wrote:
 Kyle Furlong wrote:
 I just started work on Velocity, a game engine. I want the math module 
 to use templated structs for vectors and matrices. Theses structs will 
 overload the different operators (+,*,-)with fast assembly 
 implementations of the operations.

 I'm running into some errors which I cant understand due to my shaky 
 grasp of the language. Attached is what I have so far for the Vector 
 struct; any pointers are appreciated.

There are just a few minor errors in your code. Find below some corrections inline. With those, the code compiles with DMD 0.144. Regards, Oskar
 ------------------------------------------------------------------------

 //|
 //|        ___    __    ______           __________         //|        
 __ |  / /_______  /______________(_)_  /_____  __
 //|        __ | / /_  _ \_  /_  __ \  ___/_  /_  __/_  / / /
 //|        __ |/ / /  __/  / / /_/ / /__ _  / / /_ _  /_/ / //|        
 _____/  \___//_/  \____/\___/ /_/  \__/ _\__, /  
 //|                                              __/____/
 //|            Copyright (c) 2006 Kyle Furlong
 //|

 module velocity.math.Vector;

 /**************************************************
     A fast vector implementation
     
     Examples:
     ---
     alias Vector!(int,2) Point;
     Point origin = Point(0,0);
     ---
 **************************************************/   
 struct Vector(T, int Dim = 4)
 {
     private T[Dim] storage;
     
     T opIndex(int index)
     {
         return storage[index];
     }
     
     T opIndexAssign(T value, int index)
     {
         storage[index] = value;
         return value;
     }
     
     T opSlice()

     {
         return storage;
     }
     
     T opSlice(int i, int j)

     {
         return storage[i..j];
     }
     
     Vector!(T,Dim) opAdd(Vector!(T,Dim) a)
     {
         Vector!(T,Dim) ret;
         for(int i = 0; i < Dim; i++)
         {
             ret[i] = storage[i] + a[i];
         }
         return ret;
     }
     
     Vector!(T,Dim) opSub(Vector!(T,Dim) a)
     {
         Vector!(T,Dim,Row) ret;

         for(int i = 0; i < Dim; i++)
         {
             ret[i] = storage[i] - a[i];
         }
         return ret;
     }
     
     Vector!(T,Dim) opAddAssign(Vector!(T,Dim) a)
     {
         Vector!(T,Dim,Row) ret;

         for(int i = 0; i < Dim; i++)
         {
             ret[i] = storage[i] - a[i];
         }
         return ret;
     }
     
     static Vector!(T,Dim) opCall(...)
     {
         Vector!(T,Dim) v;
            
         for (int i = 0; i < Dim; i++)
         {
             if (_arguments[i] == typeid(T))
             {
                 v[i] = *cast(T *)_argptr;
                 _argptr += T.sizeof;
             }
             else assert(0);
         }
         return v;
     }
 }


It compiles but when you try and use it in another module the compile fails.
Jan 24 2006
parent reply Oskar Linde <oskar.lindeREM OVEgmail.com> writes:
Kyle Furlong wrote:
 Oskar Linde wrote:
 Kyle Furlong wrote:
 I just started work on Velocity, a game engine. I want the math 
 module to use templated structs for vectors and matrices. Theses 
 structs will overload the different operators (+,*,-)with fast 
 assembly implementations of the operations.

 I'm running into some errors which I cant understand due to my shaky 
 grasp of the language. Attached is what I have so far for the Vector 
 struct; any pointers are appreciated.

There are just a few minor errors in your code. Find below some corrections inline. With those, the code compiles with DMD 0.144.


[snip]
 
 It compiles but when you try and use it in another module the compile 
 fails.

With what errors? For me, it works as expected. I might have forgotten some fix. alias Vector!(int,2) Point; Point origin = Point(0,0); Point a = Point(1,1); Point b = Point(2,3); Point c = a + b; writefln("%s %s",c[0],c[1]); Prints 3 4 /Oskar
Jan 25 2006
parent reply Kyle Furlong <kylefurlong gmail.com> writes:
Oskar Linde wrote:
 Kyle Furlong wrote:
 Oskar Linde wrote:
 Kyle Furlong wrote:
 I just started work on Velocity, a game engine. I want the math 
 module to use templated structs for vectors and matrices. Theses 
 structs will overload the different operators (+,*,-)with fast 
 assembly implementations of the operations.

 I'm running into some errors which I cant understand due to my shaky 
 grasp of the language. Attached is what I have so far for the Vector 
 struct; any pointers are appreciated.

There are just a few minor errors in your code. Find below some corrections inline. With those, the code compiles with DMD 0.144.


[snip]
 It compiles but when you try and use it in another module the compile 
 fails.

With what errors? For me, it works as expected. I might have forgotten some fix. alias Vector!(int,2) Point; Point origin = Point(0,0); Point a = Point(1,1); Point b = Point(2,3); Point c = a + b; writefln("%s %s",c[0],c[1]); Prints 3 4 /Oskar

Can you attach a file with your version, the ng is making it difficult to see the differences.
Jan 25 2006
parent Oskar Linde <oskar.lindeREM OVEgmail.com> writes:
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

Kyle Furlong wrote:
 
 Can you attach a file with your version, the ng is making it difficult 
 to see the differences.

Of course. I should have done that from the start. I hope Unix line endings are OK. /Oskar
Jan 25 2006
prev sibling next sibling parent "John C" <johnch_atms hotmail.com> writes:
"Kyle Furlong" <kylefurlong gmail.com> wrote in message 
news:dr6l90$5lu$1 digitaldaemon.com...
I just started work on Velocity, a game engine. I want the math module
 to use templated structs for vectors and matrices. Theses structs will
 overload the different operators (+,*,-)with fast assembly
 implementations of the operations.

 I'm running into some errors which I cant understand due to my shaky
 grasp of the language. Attached is what I have so far for the Vector
 struct; any pointers are appreciated.

See below for corrections that will enable D to compile your template.
 p.s. - Velocity is hosted at dsource. At the moment the license is tbd.

--------------------------------------------------------------------------------
 //|
 //| ___    __    ______           __________
 //| __ |  / /_______  /______________(_)_  /_____  __
 //| __ | / /_  _ \_  /_  __ \  ___/_  /_  __/_  / / /
 //| __ |/ / /  __/  / / /_/ / /__ _  / / /_ _  /_/ /
 //| _____/  \___//_/  \____/\___/ /_/  \__/ _\__, /
 //|                                       __/____/
 //| Copyright (c) 2006 Kyle Furlong
 //|

 module velocity.math.Vector;

 /**************************************************
 A fast vector implementation

 Examples:
 ---
 alias Vector!(int,2) Point;
 Point origin = Point(0,0);
 ---
 **************************************************/
 struct Vector(T, int Dim = 4)
 {
 private T[Dim] storage;

 T opIndex(int index)
 {
 return storage[index];
 }

 T opIndexAssign(T value, int index)
 {
 storage[index] = value;
 return value;
 }

 T opSlice()
 {
 return storage;
 }

opSlice returns an array, not an element, so: T[] opSlice() { return storage; }
 T opSlice(int i, int j)
 {
 return storage[i..j];
 }

T[] opSlice(int i, int j) { return storage[i .. j]; }
 Vector!(T,Dim) opAdd(Vector!(T,Dim) a)
 {
 Vector!(T,Dim) ret;

Vector opAdd(Vector a) { Vector ret;
 for(int i = 0; i < Dim; i++)
 {
 ret[i] = storage[i] + a[i];
 }
 return ret;
 }

 Vector!(T,Dim) opSub(Vector!(T,Dim) a)
 {
 Vector!(T,Dim,Row) ret;

You haven't defined a 'Vector' template that takes three parameters. Vector opSub(Vector a) { Vector ret;
 for(int i = 0; i < Dim; i++)
 {
 ret[i] = storage[i] - a[i];
 }
 return ret;
 }

 Vector!(T,Dim) opAddAssign(Vector!(T,Dim) a)
 {
 Vector!(T,Dim,Row) ret;

Vector opAddAssign(Vector a) { Vector ret;
 for(int i = 0; i < Dim; i++)
 {
 ret[i] = storage[i] - a[i];
 }
 return ret;
 }

 static Vector!(T,Dim) opCall(...)
 {
 Vector!(T,Dim) v;

 for (int i = 0; i < Dim; i++)
     {
 if (_arguments[i] == typeid(T))
 {
     v[i] = *cast(T *)_argptr;
     _argptr += T.sizeof;
 }
 else assert(0);
     }
     return v;
 }
 }

static Vector opCall(...) { Vector v;
Jan 25 2006
prev sibling next sibling parent Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
You might want to take a look at my templated math module:

http://158.75.59.9/~h3/tmp/maths.d


-- 
-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GCS/M d-pu s+: a-->----- C+++$>++++ UL P+ L+ E--- W++ N++ o? K? w++ !O 
!M V? PS- PE- Y PGP t 5 X? R tv-- b DI- D+ G e>+++ h>++ !r !y
------END GEEK CODE BLOCK------

Tomasz Stachowiak  /+ a.k.a. h3r3tic +/
Jan 25 2006
prev sibling next sibling parent Dave <Dave_member pathlink.com> writes:
Below is what it looks like you wanted (with comments), complete with a
unittest. Compile with: dmd -unittest [-O -inline -release] myvector.d

module myvector;

void main(){}

unittest
{
alias Vector!(int,2) Point;

Point o = Point(10,30);
assert(o[0] == 10 && o[1] == 30);

o[0] = 20, o[1] = 40;
assert(o[0] == 20 && o[1] == 40);

int[] t = o[0..2];
assert(t[0] == 20 && t[1] == 40);

t[0] = 100, t[1] = 200;
int[] t2 = o[];
assert(t2[0] == 100 && t2[1] == 200);

Point t3,t4,t5 = Point(30,10);
t3 = o + t5;
assert(t3[0] == 130 && t3[1] == 210);

t4 += t5;
assert(t4[0] == 30 && t4[1] == 10);
}

struct Vector(T, int Dim = 4)
{
private T[Dim] storage;

T opIndex(int index)
{
return storage[index];
}

T opIndexAssign(T value, int index)
{
storage[index] = value;
return value;
}

//	T opSlice()
T[] opSlice()
{
return storage;
}

//	T opSlice(int i, int j)
T[] opSlice(int i, int j)
{
return storage[i..j];
}

Vector!(T,Dim) opAdd(Vector!(T,Dim) a)
{
Vector!(T,Dim) ret;
for(int i = 0; i < Dim; i++)
{
ret[i] = storage[i] + a[i];
}
return ret;
}

Vector!(T,Dim) opSub(Vector!(T,Dim) a)
{
//		Vector!(T,Dim,Row) ret;
Vector!(T,Dim) ret;
for(int i = 0; i < Dim; i++)
{
ret[i] = storage[i] - a[i];
}
return ret;
}

Vector!(T,Dim) opAddAssign(Vector!(T,Dim) a)
{
//		Vector!(T,Dim,Row) ret;
for(int i = 0; i < Dim; i++)
{
//			ret[i] = storage[i] + a[i];
storage[i] += a[i];
}
//		return ret;
return *this;
}

static Vector!(T,Dim) opCall(...)
{
Vector!(T,Dim) v;

for (int i = 0; i < Dim; i++)
{
if (_arguments[i] == typeid(T))
{
v[i] = *cast(T *)_argptr;
_argptr += T.sizeof;
}
else assert(0);
}
return v;
}
}

In article <dr6l90$5lu$1 digitaldaemon.com>, Kyle Furlong says...
This is a multi-part message in MIME format.
--------------020800040606050701090906
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

I just started work on Velocity, a game engine. I want the math module 
to use templated structs for vectors and matrices. Theses structs will 
overload the different operators (+,*,-)with fast assembly 
implementations of the operations.

I'm running into some errors which I cant understand due to my shaky 
grasp of the language. Attached is what I have so far for the Vector 
struct; any pointers are appreciated.

p.s. - Velocity is hosted at dsource. At the moment the license is tbd.



--------------020800040606050701090906
Content-Type: text/plain;
 name="Vector.d"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="Vector.d"

//|
//|		___    __    ______           __________         
//|		__ |  / /_______  /______________(_)_  /_____  __
//|		__ | / /_  _ \_  /_  __ \  ___/_  /_  __/_  / / /
//|		__ |/ / /  __/  / / /_/ / /__ _  / / /_ _  /_/ / 
//|		_____/  \___//_/  \____/\___/ /_/  \__/ _\__, /  
//|		                                      __/____/
//|			Copyright (c) 2006 Kyle Furlong
//|

module velocity.math.Vector;

/**************************************************
	A fast vector implementation
	
	Examples:
	---
	alias Vector!(int,2) Point;
	Point origin = Point(0,0);
	---
**************************************************/	
struct Vector(T, int Dim = 4)
{
	private T[Dim] storage;
	
	T opIndex(int index)
	{
		return storage[index];
	}
	
	T opIndexAssign(T value, int index)
	{
		storage[index] = value;
		return value;
	}
	
	T opSlice()
	{
		return storage;
	}
	
	T opSlice(int i, int j)
	{
		return storage[i..j];
	}
	
	Vector!(T,Dim) opAdd(Vector!(T,Dim) a)
	{
		Vector!(T,Dim) ret;
		for(int i = 0; i < Dim; i++)
		{
			ret[i] = storage[i] + a[i];
		}
		return ret;
	}
	
	Vector!(T,Dim) opSub(Vector!(T,Dim) a)
	{
		Vector!(T,Dim,Row) ret;
		for(int i = 0; i < Dim; i++)
		{
			ret[i] = storage[i] - a[i];
		}
		return ret;
	}
	
	Vector!(T,Dim) opAddAssign(Vector!(T,Dim) a)
	{
		Vector!(T,Dim,Row) ret;
		for(int i = 0; i < Dim; i++)
		{
			ret[i] = storage[i] - a[i];
		}
		return ret;
	}
	
	static Vector!(T,Dim) opCall(...)
	{
		Vector!(T,Dim) v;
			
		for (int i = 0; i < Dim; i++)
	    {
			if (_arguments[i] == typeid(T))
			{
			    v[i] = *cast(T *)_argptr;
			    _argptr += T.sizeof;
			}
			else assert(0);
	    }
	    return v;
	}
}


--------------020800040606050701090906--

Jan 25 2006
prev sibling parent reply Kyle Furlong <kylefurlong gmail.com> writes:
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

Kyle Furlong wrote:
 I just started work on Velocity, a game engine. I want the math module 
 to use templated structs for vectors and matrices. Theses structs will 
 overload the different operators (+,*,-)with fast assembly 
 implementations of the operations.
 
 I'm running into some errors which I cant understand due to my shaky 
 grasp of the language. Attached is what I have so far for the Vector 
 struct; any pointers are appreciated.
 
 p.s. - Velocity is hosted at dsource. At the moment the license is tbd.
 
 
 
 ------------------------------------------------------------------------
 
 //|
 //|		___    __    ______           __________         
 //|		__ |  / /_______  /______________(_)_  /_____  __
 //|		__ | / /_  _ \_  /_  __ \  ___/_  /_  __/_  / / /
 //|		__ |/ / /  __/  / / /_/ / /__ _  / / /_ _  /_/ / 
 //|		_____/  \___//_/  \____/\___/ /_/  \__/ _\__, /  
 //|		                                      __/____/
 //|			Copyright (c) 2006 Kyle Furlong
 //|
 
 module velocity.math.Vector;
 
 /**************************************************
 	A fast vector implementation
 	
 	Examples:
 	---
 	alias Vector!(int,2) Point;
 	Point origin = Point(0,0);
 	---
 **************************************************/	
 struct Vector(T, int Dim = 4)
 {
 	private T[Dim] storage;
 	
 	T opIndex(int index)
 	{
 		return storage[index];
 	}
 	
 	T opIndexAssign(T value, int index)
 	{
 		storage[index] = value;
 		return value;
 	}
 	
 	T opSlice()
 	{
 		return storage;
 	}
 	
 	T opSlice(int i, int j)
 	{
 		return storage[i..j];
 	}
 	
 	Vector!(T,Dim) opAdd(Vector!(T,Dim) a)
 	{
 		Vector!(T,Dim) ret;
 		for(int i = 0; i < Dim; i++)
 		{
 			ret[i] = storage[i] + a[i];
 		}
 		return ret;
 	}
 	
 	Vector!(T,Dim) opSub(Vector!(T,Dim) a)
 	{
 		Vector!(T,Dim,Row) ret;
 		for(int i = 0; i < Dim; i++)
 		{
 			ret[i] = storage[i] - a[i];
 		}
 		return ret;
 	}
 	
 	Vector!(T,Dim) opAddAssign(Vector!(T,Dim) a)
 	{
 		Vector!(T,Dim,Row) ret;
 		for(int i = 0; i < Dim; i++)
 		{
 			ret[i] = storage[i] - a[i];
 		}
 		return ret;
 	}
 	
 	static Vector!(T,Dim) opCall(...)
 	{
 		Vector!(T,Dim) v;
 			
 		for (int i = 0; i < Dim; i++)
 	    {
 			if (_arguments[i] == typeid(T))
 			{
 			    v[i] = *cast(T *)_argptr;
 			    _argptr += T.sizeof;
 			}
 			else assert(0);
 	    }
 	    return v;
 	}
 }
 

Thank you all for your input. There is still some ambiguity though. Attached is my copy that works now, but some of you suggested keeping the methods in this form: Vector!(T,Dim) opAdd(Vector!(T,Dim) a) { Vector!(T,Dim) ret; for(int i = 0; i < Dim; i++) { ret[i] = storage[i] + a[i]; } return ret; } Which didn't compile for me. Are there cases where this syntax will work? Or is it permissible to only use the struct name for returning the struct within the struct itself?
Jan 25 2006
next sibling parent reply Kyle Furlong <kylefurlong gmail.com> writes:
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

Kyle Furlong wrote:
 Kyle Furlong wrote:
 I just started work on Velocity, a game engine. I want the math module 
 to use templated structs for vectors and matrices. Theses structs will 
 overload the different operators (+,*,-)with fast assembly 
 implementations of the operations.

 I'm running into some errors which I cant understand due to my shaky 
 grasp of the language. Attached is what I have so far for the Vector 
 struct; any pointers are appreciated.

 p.s. - Velocity is hosted at dsource. At the moment the license is tbd.



 ------------------------------------------------------------------------

 //|
 //|        ___    __    ______           __________         //|        
 __ |  / /_______  /______________(_)_  /_____  __
 //|        __ | / /_  _ \_  /_  __ \  ___/_  /_  __/_  / / /
 //|        __ |/ / /  __/  / / /_/ / /__ _  / / /_ _  /_/ / //|        
 _____/  \___//_/  \____/\___/ /_/  \__/ _\__, /  
 //|                                              __/____/
 //|            Copyright (c) 2006 Kyle Furlong
 //|

 module velocity.math.Vector;

 /**************************************************
     A fast vector implementation
     
     Examples:
     ---
     alias Vector!(int,2) Point;
     Point origin = Point(0,0);
     ---
 **************************************************/   
 struct Vector(T, int Dim = 4)
 {
     private T[Dim] storage;
     
     T opIndex(int index)
     {
         return storage[index];
     }
     
     T opIndexAssign(T value, int index)
     {
         storage[index] = value;
         return value;
     }
     
     T opSlice()
     {
         return storage;
     }
     
     T opSlice(int i, int j)
     {
         return storage[i..j];
     }
     
     Vector!(T,Dim) opAdd(Vector!(T,Dim) a)
     {
         Vector!(T,Dim) ret;
         for(int i = 0; i < Dim; i++)
         {
             ret[i] = storage[i] + a[i];
         }
         return ret;
     }
     
     Vector!(T,Dim) opSub(Vector!(T,Dim) a)
     {
         Vector!(T,Dim,Row) ret;
         for(int i = 0; i < Dim; i++)
         {
             ret[i] = storage[i] - a[i];
         }
         return ret;
     }
     
     Vector!(T,Dim) opAddAssign(Vector!(T,Dim) a)
     {
         Vector!(T,Dim,Row) ret;
         for(int i = 0; i < Dim; i++)
         {
             ret[i] = storage[i] - a[i];
         }
         return ret;
     }
     
     static Vector!(T,Dim) opCall(...)
     {
         Vector!(T,Dim) v;
            
         for (int i = 0; i < Dim; i++)
         {
             if (_arguments[i] == typeid(T))
             {
                 v[i] = *cast(T *)_argptr;
                 _argptr += T.sizeof;
             }
             else assert(0);
         }
         return v;
     }
 }

Thank you all for your input. There is still some ambiguity though. Attached is my copy that works now, but some of you suggested keeping the methods in this form: Vector!(T,Dim) opAdd(Vector!(T,Dim) a) { Vector!(T,Dim) ret; for(int i = 0; i < Dim; i++) { ret[i] = storage[i] + a[i]; } return ret; } Which didn't compile for me. Are there cases where this syntax will work? Or is it permissible to only use the struct name for returning the struct within the struct itself? ------------------------------------------------------------------------ //| //| ___ __ ______ __________ //| __ | / /_______ /______________(_)_ /_____ __ //| __ | / /_ _ \_ /_ __ \ ___/_ /_ __/_ / / / //| __ |/ / / __/ / / /_/ / /__ _ / / /_ _ /_/ / //| _____/ \___//_/ \____/\___/ /_/ \__/ _\__, / //| __/____/ //| Copyright (c) 2006 Kyle Furlong //| module velocity.math.Vector; /************************************************** A fast vector implementation Examples: --- alias Vector!(int,2) Point; Point origin = Point(0,0); --- **************************************************/ class Vector(T, int Dim = 4) { private T[Dim] storage; T opIndex(int index) { return storage[index]; } T opIndexAssign(T value, int index) { storage[index] = value; return value; } T opSlice() { return storage; } T opSlice(int i, int j) { return storage[i..j]; } Vector!(T,Dim) opAdd(Vector!(T,Dim) a) { Vector!(T,Dim) ret; for(int i = 0; i < Dim; i++) { ret[i] = storage[i] + a[i]; } return ret; } Vector!(T,Dim) opSub(Vector!(T,Dim) a) { Vector!(T,Dim,Row) ret; for(int i = 0; i < Dim; i++) { ret[i] = storage[i] - a[i]; } return ret; } Vector!(T,Dim) opAddAssign(Vector!(T,Dim) a) { Vector!(T,Dim,Row) ret; for(int i = 0; i < Dim; i++) { ret[i] = storage[i] - a[i]; } return ret; } /* static Vector!(T,Dim) opCall(...) { Vector!(T,Dim) v; for (int i = 0; i < Dim; i++) { if (_arguments[i] == typeid(T)) { v[i] = *cast(T *)_argptr; _argptr += T.sizeof; } else assert(0); } return v; }*/ }

Sorry attached the old one on accident.
Jan 25 2006
parent Dave <Dave_member pathlink.com> writes:
Change the second 'V' to 'v' in velocity.math.Vector and copy this code into
'main.d', then compile: dmd main.d vector.d

main.d
------
import std.stdio, velocity.math.vector;

alias Vector!(int,2) Point;
void main()
{
Point origin = Point(10,10);
writefln(origin[0],",",origin[1]);
}
------

module velocity.math.Vector;

/**************************************************
	A fast vector implementation
	
	Examples:
	---
	alias Vector!(int,2) Point;
	Point origin = Point(0,0);
	---
**************************************************/	
struct Vector(T, int Dim = 4)
{
	private T[Dim] storage;
	
	T opIndex(int index)
	{
		return storage[index];
	}
	
	T opIndexAssign(T value, int index)
	{
		storage[index] = value;
		return value;
	}
	
	Vector opAdd(Vector a)
	{
		Vector ret;
		for(int i = 0; i < Dim; i++)
		{
			ret[i] = storage[i] + a[i];
		}
		return ret;
	}
	
	Vector opSub(Vector a)
	{
		Vector ret;
		for(int i = 0; i < Dim; i++)
		{
			ret[i] = storage[i] - a[i];
		}
		return ret;
	}
	
	Vector opAddAssign(Vector a)
	{
		for(int i = 0; i < Dim; i++)
		{
			storage[i] += a[i];
		}
		return *this;
	}
	
	Vector opSubAssign(Vector a)
	{
		for(int i = 0; i < Dim; i++)
		{
			storage[i] -= a[i];
		}
		return *this;
	}
	
	static Vector opCall(...)
    {
        Vector v;
           
        for (int i = 0; i < Dim; i++)
        {
            if (_arguments[i] == typeid(T))
            {
                v[i] = *cast(T *)_argptr;
                _argptr += T.sizeof;
                
            }
           	else assert(0);
        }
        return v;
    }
}


--------------050605010104060809010402--

Jan 25 2006
prev sibling parent reply Oskar Linde <oskar.lindeREM OVEgmail.com> writes:
In article <dr8oqj$2nqo$1 digitaldaemon.com>, Kyle Furlong says...

Vector!(T,Dim) opAdd(Vector!(T,Dim) a)
{
	Vector!(T,Dim) ret;
	for(int i = 0; i < Dim; i++)
	{
		ret[i] = storage[i] + a[i];
	}
	return ret;
}

Which didn't compile for me. Are there cases where this syntax will 
work? Or is it permissible to only use the struct name for returning the 
struct within the struct itself?

Up until DMD version 0.143 this had to be written as: #.Vector!(T,Dim) opAdd(.Vector!(T,Dim) a) #{ # .Vector!(T,Dim) ret; # for(int i = 0; i < Dim; i++) # { # ret[i] = storage[i] + a[i]; # } # return ret; #} But with the latest version (0.144), the dot (.) before the template identifier is no longer necessary. (Its meaning was to refer to the Vector template in the outer scope rather than the Vector struct in the inner scope.) Within this single member template, Vector refers to the same thing as Vector!(T,Dim). /Oskar
Jan 25 2006
parent Kyle Furlong <kylefurlong gmail.com> writes:
Oskar Linde wrote:
 In article <dr8oqj$2nqo$1 digitaldaemon.com>, Kyle Furlong says...
 
 Vector!(T,Dim) opAdd(Vector!(T,Dim) a)
 {
 	Vector!(T,Dim) ret;
 	for(int i = 0; i < Dim; i++)
 	{
 		ret[i] = storage[i] + a[i];
 	}
 	return ret;
 }

 Which didn't compile for me. Are there cases where this syntax will 
 work? Or is it permissible to only use the struct name for returning the 
 struct within the struct itself?

Up until DMD version 0.143 this had to be written as: #.Vector!(T,Dim) opAdd(.Vector!(T,Dim) a) #{ # .Vector!(T,Dim) ret; # for(int i = 0; i < Dim; i++) # { # ret[i] = storage[i] + a[i]; # } # return ret; #} But with the latest version (0.144), the dot (.) before the template identifier is no longer necessary. (Its meaning was to refer to the Vector template in the outer scope rather than the Vector struct in the inner scope.) Within this single member template, Vector refers to the same thing as Vector!(T,Dim). /Oskar

Jan 26 2006