Re: [pygame] State of the math branch

2009-12-10 Thread Lorenz Quack

Hi,

a quick update.
as of rev. 2701 all build bots successfully build and test again (1).
In addition to the fixes that were required to make py3k work I removed the
iterator version of slerp/lerp and replaced it with a parameterized version
as suggested by Patrick Mullen and Casey Duncan.
I also fixed the potential memory leaks that were pointed out by Casey.
The only new feature is support for extended slicing.

I didn't incorporate any performance fixes that were suggested on this list.
This is mainly due to lack of time and the time I have went into appeasing
the build bots.

I also have very little time in the next few month so don't expect much news
from me in this time but I'll be back with matrices and quaternions once
things settle around here.

that's it for now.

sincerely yours
//Lorenz

(1) The exception is MacOSX_py31 build bot which seems to not work at all.


Re: [pygame] State of the math branch

2009-11-16 Thread Casey Duncan
To start with, it is great to see follow-through on this, it will be a  
great, long overdue, addition to the pygame api.


One thing I notice is that the main vector data structure contains a  
pointer to the actual coordinates. Other structures just contain the  
coordinates in an inline array up to the max dimension. IMO the main  
vector data structure should have the coordinates inline as well. This  
will cut in half the number of heap allocations to create a vector  
object. I suspect that it may be common for vector objects to be  
created as intermediate results in calculations and immediately  
discarded, and eliminating the extra memory management would be a  
helpful optimization, and simplify the code (less memory management is  
always a good thing). I think the only use-case for having the pointer  
would be for proxying an array of vector coordinates that you could  
operate on en masse (ala numpy).


A further optimization to consider would be an instance pool for  
vectors. If I'm right, and vectors are created and destroyed a lot in  
certain applications, having a pool of unused instances lying around  
could be a real win. This is how Python optimizes tuple object creation.


I didn't check thoroughly for this, but you need to be careful with  
code like this (in vector_elementwiseproxy_pow):


for (i = 0; i  dim; i++) {
base = PyFloat_FromDouble(bases[i]);
expo = PyFloat_FromDouble(expos[i]);
result = PyNumber_Power(base, expo, Py_None);
if (!result)
return NULL;
ret-coords[i] = PyFloat_AsDouble(result);
Py_DECREF(result);
Py_DECREF(expo);
Py_DECREF(base);
}

For one, PyFloat_FromDouble can return NULL, and I'm not sure what  
PyNumber_Power will do when passed a NULL arg. Assuming it doesn't  
crash and returns NULL, you may be leaking references to base or expo.  
It's probably safer to assume PyNumber_Power will crash however, which  
is very bad since it will mask the memory problem with a segfault. All  
of this conversion back and forth from Python floats seems  
unnecessary, however. Can't you just use the libc pow() function  
directly instead, saving all the PyFloat business?


I'm also curious what the use-case is for enabling and disabling  
swizzling? I know I've seen other libraries that have this switch  
(Euclid?), but why not just leave it on all of the time? Too error  
prone?


-Casey

On Nov 14, 2009, at 4:45 AM, René Dudfield wrote:


Hi,

sweet :)  Nice work.

Feel free to merge it into the trunk.  It'll be easier for other
people to try it out(binaries, and other things hooked up with trunk),
and you can also use the build bot to check for errors on other
platforms(like compilation/testing).

Sorry, I haven't had a chance to review it much.  Hopefully will get a
chance to have a play, and a read of the code later this weekend some
time.

ps, here's the svn link for anyone else who would like to read over it
http://www.seul.org/viewcvs/viewcvs.cgi/branches/math_module/?root=PyGamesortby=date


The (s)lerp idea with the iterator seems a good one.  I've been
thinking about doing something like that with line drawing
functions... that instead of drawing return the (x,y) coords of where
it would draw pixels.  I wonder if it still might be useful to let
people supply a t argument, just because people are used to it...
However, they could just supply one step.

Having them share implementations is probably a good thing to reduce
the complexity of the code.

I guess there is going to be a 4 element quaternion?  What about a
Vector4?  Which matrix sizes are you thinking of doing?  I guess 3x3,
3x4 and 4x4?  Or just 4x4?

I noticed one commit log said there was trouble with the buffer
interface?  Is this part still a trouble?



Functions like vector_elementwiseproxy_mul,
vector_elementwiseproxy_sub etc, could probably share a lot of code,
and then for the different part use a switch statement to do the
different function.  Something like this:

static PyObject *
vector_elementwiseproxy_mul(PyObject *o1, PyObject *o2) {
   return vector_elementwiseproxy_generic(o1, o2, VECT_OPS_MUL);
}

Where the vector_elementwiseproxy_generic function would have the
switch statement on the various flags passed in.




cheers,





On Thu, Nov 12, 2009 at 10:31 AM,  d...@amberfisharts.com wrote:


Hi List,

I just wanted to give you a short summery of the development in the  
math branch.
The goal of the math branch is the inclusion of several math  
related types

like vectors, matrices and quaternions.

Right now I consider the implementation of vectors in 2 and 3  
dimensions as

feature complete.
What this means is that I can't think of more functionality that I  
want to

implement and all methods pass their unit tests.
I encourage everyone interested to take a look and make suggestions  
if they

find functionality missing.

The current version is not written for maximum performance.
For example 

Re: [pygame] State of the math branch

2009-11-16 Thread Casey Duncan
I agree, I think an iterator api is not flexible enough alone, and if  
provided, should be in addition to one that takes an arbitrary t.


-Casey

On Nov 14, 2009, at 3:59 PM, Patrick Mullen wrote:


I think there are many cases where one might want, say, the halfway
rotated quat between two, or due to varying framerates with things
like network code, (or even just for animation purposes) you might
want to have varying rates, or skip to a different t value. I don't
see how an iterator would be useful in these cases. You would have to
do a 2 step rotation once to get the midway rotation, iterating an
iterator once is pretty unintuitive; and for varying speeds during a
rotation, you would need to recalculate a new iterator every frame.

I haven't looked at it, but intuitively it seems to be trying to wedge
one concept into a very different one. If there were only one
implementation, I would much prefer the t version.

On Sat, Nov 14, 2009 at 11:06 AM, Lorenz Quack  
d...@amberfisharts.com wrote:

Hi René,

René Dudfield wrote:


Feel free to merge it into the trunk.  It'll be easier for other
people to try it out(binaries, and other things hooked up with  
trunk),

and you can also use the build bot to check for errors on other
platforms(like compilation/testing).


Ok. I'll see if I can make it this weekend.


The (s)lerp idea with the iterator seems a good one.  I've been
thinking about doing something like that with line drawing
functions... that instead of drawing return the (x,y) coords of  
where

it would draw pixels.  I wonder if it still might be useful to let
people supply a t argument, just because people are used to it...


My hope is that the iterator is intuitive enough so nobody will  
miss the

t-version. also my version should perform better because it only
calculates a rotation-matrix once while otherwise you would have to
recalculate it on every call for the new t-value.
So for now I would stay with:
There should be one-- and preferably only one --obvious way to do  
it.

and wait and see if there is strong demand for a t-argument version.


However, they could just supply one step.


unfortunately I don't think it's that easy to convert from the  
iterator
interface to the t-arg interface. you would have to something like  
this:


def slerp_t(start_vec, end_vec, t):
   idx, steps = t.as_integer_ratio() # new in python 2.6
   return list(start_vec.slerp(end_vec, steps))[idx]

which is pretty ugly.


I guess there is going to be a 4 element quaternion?  What about a
Vector4?  Which matrix sizes are you thinking of doing?  I guess  
3x3,

3x4 and 4x4?  Or just 4x4?


I was planing on implementing quaternions and only square matrices.
Is there a use for Vector4? Implementing it would be quite easy but
do we need it?
Also, what would be a use case for non-square matrices?


I noticed one commit log said there was trouble with the buffer
interface?  Is this part still a trouble?


Yea. I didn't really understand which parts of the buffer protocol  
belong
to the 2.x protocol and which belong to 3.x and what should be  
supported.
In general I found this topic a bit confusing and the docs didn't  
help.
I have to look into that some other time when I've got the nerve  
for it.



Functions like vector_elementwiseproxy_mul,
vector_elementwiseproxy_sub etc, could probably share a lot of code,
and then for the different part use a switch statement to do the
different function.  Something like this:

static PyObject *
vector_elementwiseproxy_mul(PyObject *o1, PyObject *o2) {
   return vector_elementwiseproxy_generic(o1, o2, VECT_OPS_MUL);
}

Where the vector_elementwiseproxy_generic function would have the
switch statement on the various flags passed in.


I'll take a look at it.

thanks for the feedback. looking forward to more of it :)

yours
//Lorenz



On Thu, Nov 12, 2009 at 10:31 AM,  d...@amberfisharts.com wrote:


Hi List,

I just wanted to give you a short summery of the development in  
the math

branch.
The goal of the math branch is the inclusion of several math  
related

types
like vectors, matrices and quaternions.

Right now I consider the implementation of vectors in 2 and 3  
dimensions

as
feature complete.
What this means is that I can't think of more functionality that  
I want

to
implement and all methods pass their unit tests.
I encourage everyone interested to take a look and make  
suggestions if

they
find functionality missing.

The current version is not written for maximum performance.
For example Vector2 and Vector3 share many functions so no  
dimension

specific
optimizations are implemented. So the current implementation  
should be

considered a baseline for future optimizations.
To gauge future improvements I intend to write a rudimentary  
performance

benchmark.

I don't consider the API to be set in stone. Especially concerning
mutability. Currently vectors are mutable.
If however it turns out that there is no significant performance  
hit in

making them 

Re: [pygame] State of the math branch

2009-11-16 Thread René Dudfield
On Mon, Nov 16, 2009 at 6:10 PM, Casey Duncan ca...@pandora.com wrote:
 To start with, it is great to see follow-through on this, it will be a
 great, long overdue, addition to the pygame api.

 One thing I notice is that the main vector data structure contains a pointer
 to the actual coordinates. Other structures just contain the coordinates in
 an inline array up to the max dimension. IMO the main vector data structure
 should have the coordinates inline as well. This will cut in half the number
 of heap allocations to create a vector object. I suspect that it may be
 common for vector objects to be created as intermediate results in
 calculations and immediately discarded, and eliminating the extra memory
 management would be a helpful optimization, and simplify the code (less
 memory management is always a good thing). I think the only use-case for
 having the pointer would be for proxying an array of vector coordinates that
 you could operate on en masse (ala numpy).


Having the vector be a proxy for other data is big use case though.

How about...   There could be a double[4] inline, and have the pointer
point to that data for 2,3,4 sized vectors.  If it's bigger than this,
it can be (py)malloc'd, and it can also refer to data via the buffer
protocol.  The pointer would still be where the data is, but it could
be refer to the inline data if needed.



 A further optimization to consider would be an instance pool for vectors. If
 I'm right, and vectors are created and destroyed a lot in certain
 applications, having a pool of unused instances lying around could be a real
 win. This is how Python optimizes tuple object creation.


+1

pygame could use this technique all over.  I think using pymalloc can
give us this automatically... or close to automatically.

There's some notes here about performance here of pymalloc Vs free
lists(python terminology for memory pools):
http://bugs.python.org/issue2039

Probably not as fast as a specific memory pool... but maybe pymalloc
would come close.


 I didn't check thoroughly for this, but you need to be careful with code
 like this (in vector_elementwiseproxy_pow):

    for (i = 0; i  dim; i++) {
        base = PyFloat_FromDouble(bases[i]);
        expo = PyFloat_FromDouble(expos[i]);
        result = PyNumber_Power(base, expo, Py_None);
        if (!result)
            return NULL;
        ret-coords[i] = PyFloat_AsDouble(result);
        Py_DECREF(result);
        Py_DECREF(expo);
        Py_DECREF(base);
    }

 For one, PyFloat_FromDouble can return NULL, and I'm not sure what
 PyNumber_Power will do when passed a NULL arg. Assuming it doesn't crash and
 returns NULL, you may be leaking references to base or expo. It's probably
 safer to assume PyNumber_Power will crash however, which is very bad since
 it will mask the memory problem with a segfault. All of this conversion back
 and forth from Python floats seems unnecessary, however.

 Can't you just use
 the libc pow() function directly instead, saving all the PyFloat business?


good idea


 I'm also curious what the use-case is for enabling and disabling swizzling?
 I know I've seen other libraries that have this switch (Euclid?), but why
 not just leave it on all of the time? Too error prone?

 -Casey



Re: [pygame] State of the math branch

2009-11-16 Thread Lorenz Quack

Hi,

first of all thanks for the feedback.
second I just merged the branch with the trunk. I hope I didn't mess anything
up (my merging experience is *very* limited).
I also implemented the generic math function René suggested.


René Dudfield wrote:

On Mon, Nov 16, 2009 at 6:10 PM, Casey Duncan ca...@pandora.com wrote:

To start with, it is great to see follow-through on this, it will be a
great, long overdue, addition to the pygame api.

One thing I notice is that the main vector data structure contains a pointer
to the actual coordinates. Other structures just contain the coordinates in
an inline array up to the max dimension. IMO the main vector data structure
should have the coordinates inline as well. This will cut in half the number
of heap allocations to create a vector object. I suspect that it may be
common for vector objects to be created as intermediate results in
calculations and immediately discarded, and eliminating the extra memory
management would be a helpful optimization, and simplify the code (less
memory management is always a good thing). I think the only use-case for
having the pointer would be for proxying an array of vector coordinates that
you could operate on en masse (ala numpy).



Having the vector be a proxy for other data is big use case though.

How about...   There could be a double[4] inline, and have the pointer
point to that data for 2,3,4 sized vectors.  If it's bigger than this,
it can be (py)malloc'd, and it can also refer to data via the buffer
protocol.  The pointer would still be where the data is, but it could
be refer to the inline data if needed.



The reason I allocated the memory dynamically is that I didn't want to waste the
2*sizeof(double) on Vector2 instances. but maybe we don't have to be that cheep
in this day and age. especially if we can gain some speed. Another consideration
is that this way we can *maybe* reuse vectors as views on rows or columns of
matrices. I'm not convinced that thats a good idea or feasible but it is a
thought to keep in mind.




A further optimization to consider would be an instance pool for vectors. If
I'm right, and vectors are created and destroyed a lot in certain
applications, having a pool of unused instances lying around could be a real
win. This is how Python optimizes tuple object creation.



+1

pygame could use this technique all over.  I think using pymalloc can
give us this automatically... or close to automatically.

There's some notes here about performance here of pymalloc Vs free
lists(python terminology for memory pools):
http://bugs.python.org/issue2039

Probably not as fast as a specific memory pool... but maybe pymalloc
would come close.



Yes. but before I totally agree I would like to see some benchmarks.
But this is an implementation detail. Until now I didn't focus on performance.
My main concern was a nice API. But that doesn't mean you shouldn't keep
posting suggestions on how to improve all aspects!




I didn't check thoroughly for this, but you need to be careful with code
like this (in vector_elementwiseproxy_pow):

   for (i = 0; i  dim; i++) {
   base = PyFloat_FromDouble(bases[i]);
   expo = PyFloat_FromDouble(expos[i]);
   result = PyNumber_Power(base, expo, Py_None);
   if (!result)
   return NULL;
   ret-coords[i] = PyFloat_AsDouble(result);
   Py_DECREF(result);
   Py_DECREF(expo);
   Py_DECREF(base);
   }

For one, PyFloat_FromDouble can return NULL, and I'm not sure what
PyNumber_Power will do when passed a NULL arg. Assuming it doesn't crash and
returns NULL, you may be leaking references to base or expo. It's probably
safer to assume PyNumber_Power will crash however, which is very bad since
it will mask the memory problem with a segfault. All of this conversion back
and forth from Python floats seems unnecessary, however.



Can't you just use
the libc pow() function directly instead, saving all the PyFloat business?



good idea


Well, I looked at the pow implementation of float objects in python-trunk and
they were catching some corner-cases and platform quirks. I wanted to take
advantage of their work. of course we could decide that performance is
paramount and people will have to live with whatever quirks their libc might
have. Note that the python math module did take this route which simply
interfaces the libc functions.
On the bad error handling and potential memory leaks you are 100% right!


I'm also curious what the use-case is for enabling and disabling swizzling?
I know I've seen other libraries that have this switch (Euclid?), but why
not just leave it on all of the time? Too error prone?


Well I for one had never heard of swizzling before I looked at euclid. And I
imagine I would have been deeply confused if vec.xyz = (1,2,3) wouldn't add
a new attribute. That's why I disabled swizzling per default. More or less
personal preference.


again, thanks for the feedback!

yours
//Lorenz


Re: [pygame] State of the math branch

2009-11-16 Thread Lorenz Quack

Hi,

Casey Duncan wrote:
I agree, I think an iterator api is not flexible enough alone, and if 
provided, should be in addition to one that takes an arbitrary t.


-Casey

On Nov 14, 2009, at 3:59 PM, Patrick Mullen wrote:


I think there are many cases where one might want, say, the halfway
rotated quat between two, or due to varying framerates with things
like network code, (or even just for animation purposes) you might
want to have varying rates, or skip to a different t value. I don't
see how an iterator would be useful in these cases. You would have to
do a 2 step rotation once to get the midway rotation, iterating an
iterator once is pretty unintuitive; and for varying speeds during a
rotation, you would need to recalculate a new iterator every frame.

I haven't looked at it, but intuitively it seems to be trying to wedge
one concept into a very different one. If there were only one
implementation, I would much prefer the t version.




Yea, Patrick made a great point. the iterator version is only useful
when you draw in fixed time intervals which usually isn't the case.
That's to bad as I was quite fond of the iterator idea.
But well... as it stands I'll probably replace it with a t-version
soon. *sniff*

yours
//Lorenz




Re: [pygame] State of the math branch

2009-11-16 Thread Casey Duncan

On Nov 16, 2009, at 1:15 PM, Lorenz Quack wrote:

The reason I allocated the memory dynamically is that I didn't want  
to waste the
2*sizeof(double) on Vector2 instances. but maybe we don't have to be  
that cheep
in this day and age. especially if we can gain some speed. Another  
consideration
is that this way we can *maybe* reuse vectors as views on rows or  
columns of
matrices. I'm not convinced that thats a good idea or feasible but  
it is a

thought to keep in mind.


Bear in mind that there is some overhead to the allocation itself,  
plus many implementations allocate memory in minimum-sized, aligned  
chunks, so I suspect it would not save any memory allocating it  
separately, in fact it may use more, though it's largely a wash.


In any case I'd say the best reasons not to do it are:

1. Less memory management means less bugs. And memory mgmt bugs are  
never very nice 8^)


2. Allocation can be relatively expensive. For small objects like this  
which can be created as a side effect of certain operators in  
expressions, it can be a measurable win to do it less.


3. It will improve the friendliness of the data structure to the  
processor cache. Indirection is your enemy in this regard.


I like Rene's suggestion of having a pointer that normally points to a  
static array in the structure, but can be pointed somewhere else to  
retain that flexibility. That will still allow you to remove the  
memory management. In fact you can't use that pointer to index another  
data structure currently because the implementation assumes that it  
owns the memory it points to. With Rene's suggestion the pointer is  
just opaque and the vector code doesn't have to worry about releasing  
it.


-Casey



Re: [pygame] State of the math branch

2009-11-15 Thread Jeff Cagle

Lorenz Quack wrote:

Also, what would be a use case for non-square matrices?

Mapping coordinates in R^3 to coordinates in R^2 can be readily 
accomplished with a 2x3 matrix.  To generalize, an m x n matrix can be 
used to linearly transform R^n -- R^m.


Jeff Cagle


Re: [pygame] State of the math branch

2009-11-14 Thread René Dudfield
Hi,

sweet :)  Nice work.

Feel free to merge it into the trunk.  It'll be easier for other
people to try it out(binaries, and other things hooked up with trunk),
and you can also use the build bot to check for errors on other
platforms(like compilation/testing).

Sorry, I haven't had a chance to review it much.  Hopefully will get a
chance to have a play, and a read of the code later this weekend some
time.

ps, here's the svn link for anyone else who would like to read over it
http://www.seul.org/viewcvs/viewcvs.cgi/branches/math_module/?root=PyGamesortby=date


The (s)lerp idea with the iterator seems a good one.  I've been
thinking about doing something like that with line drawing
functions... that instead of drawing return the (x,y) coords of where
it would draw pixels.  I wonder if it still might be useful to let
people supply a t argument, just because people are used to it...
However, they could just supply one step.

Having them share implementations is probably a good thing to reduce
the complexity of the code.

I guess there is going to be a 4 element quaternion?  What about a
Vector4?  Which matrix sizes are you thinking of doing?  I guess 3x3,
3x4 and 4x4?  Or just 4x4?

I noticed one commit log said there was trouble with the buffer
interface?  Is this part still a trouble?



Functions like vector_elementwiseproxy_mul,
vector_elementwiseproxy_sub etc, could probably share a lot of code,
and then for the different part use a switch statement to do the
different function.  Something like this:

static PyObject *
vector_elementwiseproxy_mul(PyObject *o1, PyObject *o2) {
return vector_elementwiseproxy_generic(o1, o2, VECT_OPS_MUL);
}

Where the vector_elementwiseproxy_generic function would have the
switch statement on the various flags passed in.




cheers,





On Thu, Nov 12, 2009 at 10:31 AM,  d...@amberfisharts.com wrote:

 Hi List,

 I just wanted to give you a short summery of the development in the math 
 branch.
 The goal of the math branch is the inclusion of several math related types
 like vectors, matrices and quaternions.

 Right now I consider the implementation of vectors in 2 and 3 dimensions as
 feature complete.
 What this means is that I can't think of more functionality that I want to
 implement and all methods pass their unit tests.
 I encourage everyone interested to take a look and make suggestions if they
 find functionality missing.

 The current version is not written for maximum performance.
 For example Vector2 and Vector3 share many functions so no dimension specific
 optimizations are implemented. So the current implementation should be
 considered a baseline for future optimizations.
 To gauge future improvements I intend to write a rudimentary performance
 benchmark.

 I don't consider the API to be set in stone. Especially concerning
 mutability. Currently vectors are mutable.
 If however it turns out that there is no significant performance hit in
 making them immutable I tend to do so.
 Obviously this will only happen once I have some performance results.

 After that Matrices will be up next.


 thanks for your time and suggestions.

 //Lorenz


 PS: I feel that I should briefly comment on the slerp() method.
    I did not follow the default implementation that seems to be prevalent on
    the Internet. There you repeatedly call the slerp method with a varying
    parameter t. I felt this is unpythonic. In my implementation you pass the
    number of steps you want into the method which then returns an iterator
    yielding the interpolating vectors. Same applies to the lerp() method.
    Also the algorithm for slerp() is a bit different as to support
    interpolation to a vector of different length.





Re: [pygame] State of the math branch

2009-11-14 Thread Lorenz Quack

Hi René,

René Dudfield wrote:

Feel free to merge it into the trunk.  It'll be easier for other
people to try it out(binaries, and other things hooked up with trunk),
and you can also use the build bot to check for errors on other
platforms(like compilation/testing).


Ok. I'll see if I can make it this weekend.


The (s)lerp idea with the iterator seems a good one.  I've been
thinking about doing something like that with line drawing
functions... that instead of drawing return the (x,y) coords of where
it would draw pixels.  I wonder if it still might be useful to let
people supply a t argument, just because people are used to it...


My hope is that the iterator is intuitive enough so nobody will miss the
t-version. also my version should perform better because it only
calculates a rotation-matrix once while otherwise you would have to
recalculate it on every call for the new t-value.
So for now I would stay with:
There should be one-- and preferably only one --obvious way to do it.
and wait and see if there is strong demand for a t-argument version.


However, they could just supply one step.


unfortunately I don't think it's that easy to convert from the iterator
interface to the t-arg interface. you would have to something like this:

def slerp_t(start_vec, end_vec, t):
idx, steps = t.as_integer_ratio() # new in python 2.6
return list(start_vec.slerp(end_vec, steps))[idx]

which is pretty ugly.


I guess there is going to be a 4 element quaternion?  What about a
Vector4?  Which matrix sizes are you thinking of doing?  I guess 3x3,
3x4 and 4x4?  Or just 4x4?


I was planing on implementing quaternions and only square matrices.
Is there a use for Vector4? Implementing it would be quite easy but
do we need it?
Also, what would be a use case for non-square matrices?


I noticed one commit log said there was trouble with the buffer
interface?  Is this part still a trouble?


Yea. I didn't really understand which parts of the buffer protocol belong
to the 2.x protocol and which belong to 3.x and what should be supported.
In general I found this topic a bit confusing and the docs didn't help.
I have to look into that some other time when I've got the nerve for it.


Functions like vector_elementwiseproxy_mul,
vector_elementwiseproxy_sub etc, could probably share a lot of code,
and then for the different part use a switch statement to do the
different function.  Something like this:

static PyObject *
vector_elementwiseproxy_mul(PyObject *o1, PyObject *o2) {
return vector_elementwiseproxy_generic(o1, o2, VECT_OPS_MUL);
}

Where the vector_elementwiseproxy_generic function would have the
switch statement on the various flags passed in.


I'll take a look at it.

thanks for the feedback. looking forward to more of it :)

yours
//Lorenz



On Thu, Nov 12, 2009 at 10:31 AM,  d...@amberfisharts.com wrote:

Hi List,

I just wanted to give you a short summery of the development in the math branch.
The goal of the math branch is the inclusion of several math related types
like vectors, matrices and quaternions.

Right now I consider the implementation of vectors in 2 and 3 dimensions as
feature complete.
What this means is that I can't think of more functionality that I want to
implement and all methods pass their unit tests.
I encourage everyone interested to take a look and make suggestions if they
find functionality missing.

The current version is not written for maximum performance.
For example Vector2 and Vector3 share many functions so no dimension specific
optimizations are implemented. So the current implementation should be
considered a baseline for future optimizations.
To gauge future improvements I intend to write a rudimentary performance
benchmark.

I don't consider the API to be set in stone. Especially concerning
mutability. Currently vectors are mutable.
If however it turns out that there is no significant performance hit in
making them immutable I tend to do so.
Obviously this will only happen once I have some performance results.

After that Matrices will be up next.


thanks for your time and suggestions.

//Lorenz


PS: I feel that I should briefly comment on the slerp() method.
   I did not follow the default implementation that seems to be prevalent on
   the Internet. There you repeatedly call the slerp method with a varying
   parameter t. I felt this is unpythonic. In my implementation you pass the
   number of steps you want into the method which then returns an iterator
   yielding the interpolating vectors. Same applies to the lerp() method.
   Also the algorithm for slerp() is a bit different as to support
   interpolation to a vector of different length.





Re: [pygame] State of the math branch

2009-11-14 Thread Patrick Mullen
I think there are many cases where one might want, say, the halfway
rotated quat between two, or due to varying framerates with things
like network code, (or even just for animation purposes) you might
want to have varying rates, or skip to a different t value. I don't
see how an iterator would be useful in these cases. You would have to
do a 2 step rotation once to get the midway rotation, iterating an
iterator once is pretty unintuitive; and for varying speeds during a
rotation, you would need to recalculate a new iterator every frame.

I haven't looked at it, but intuitively it seems to be trying to wedge
one concept into a very different one. If there were only one
implementation, I would much prefer the t version.

On Sat, Nov 14, 2009 at 11:06 AM, Lorenz Quack d...@amberfisharts.com wrote:
 Hi René,

 René Dudfield wrote:

 Feel free to merge it into the trunk.  It'll be easier for other
 people to try it out(binaries, and other things hooked up with trunk),
 and you can also use the build bot to check for errors on other
 platforms(like compilation/testing).

 Ok. I'll see if I can make it this weekend.

 The (s)lerp idea with the iterator seems a good one.  I've been
 thinking about doing something like that with line drawing
 functions... that instead of drawing return the (x,y) coords of where
 it would draw pixels.  I wonder if it still might be useful to let
 people supply a t argument, just because people are used to it...

 My hope is that the iterator is intuitive enough so nobody will miss the
 t-version. also my version should perform better because it only
 calculates a rotation-matrix once while otherwise you would have to
 recalculate it on every call for the new t-value.
 So for now I would stay with:
 There should be one-- and preferably only one --obvious way to do it.
 and wait and see if there is strong demand for a t-argument version.

 However, they could just supply one step.

 unfortunately I don't think it's that easy to convert from the iterator
 interface to the t-arg interface. you would have to something like this:

 def slerp_t(start_vec, end_vec, t):
    idx, steps = t.as_integer_ratio() # new in python 2.6
    return list(start_vec.slerp(end_vec, steps))[idx]

 which is pretty ugly.

 I guess there is going to be a 4 element quaternion?  What about a
 Vector4?  Which matrix sizes are you thinking of doing?  I guess 3x3,
 3x4 and 4x4?  Or just 4x4?

 I was planing on implementing quaternions and only square matrices.
 Is there a use for Vector4? Implementing it would be quite easy but
 do we need it?
 Also, what would be a use case for non-square matrices?

 I noticed one commit log said there was trouble with the buffer
 interface?  Is this part still a trouble?

 Yea. I didn't really understand which parts of the buffer protocol belong
 to the 2.x protocol and which belong to 3.x and what should be supported.
 In general I found this topic a bit confusing and the docs didn't help.
 I have to look into that some other time when I've got the nerve for it.

 Functions like vector_elementwiseproxy_mul,
 vector_elementwiseproxy_sub etc, could probably share a lot of code,
 and then for the different part use a switch statement to do the
 different function.  Something like this:

 static PyObject *
 vector_elementwiseproxy_mul(PyObject *o1, PyObject *o2) {
    return vector_elementwiseproxy_generic(o1, o2, VECT_OPS_MUL);
 }

 Where the vector_elementwiseproxy_generic function would have the
 switch statement on the various flags passed in.

 I'll take a look at it.

 thanks for the feedback. looking forward to more of it :)

 yours
 //Lorenz


 On Thu, Nov 12, 2009 at 10:31 AM,  d...@amberfisharts.com wrote:

 Hi List,

 I just wanted to give you a short summery of the development in the math
 branch.
 The goal of the math branch is the inclusion of several math related
 types
 like vectors, matrices and quaternions.

 Right now I consider the implementation of vectors in 2 and 3 dimensions
 as
 feature complete.
 What this means is that I can't think of more functionality that I want
 to
 implement and all methods pass their unit tests.
 I encourage everyone interested to take a look and make suggestions if
 they
 find functionality missing.

 The current version is not written for maximum performance.
 For example Vector2 and Vector3 share many functions so no dimension
 specific
 optimizations are implemented. So the current implementation should be
 considered a baseline for future optimizations.
 To gauge future improvements I intend to write a rudimentary performance
 benchmark.

 I don't consider the API to be set in stone. Especially concerning
 mutability. Currently vectors are mutable.
 If however it turns out that there is no significant performance hit in
 making them immutable I tend to do so.
 Obviously this will only happen once I have some performance results.

 After that Matrices will be up next.


 thanks for your time and suggestions.

 //Lorenz


 PS: