fixed bug: #1633 Memory leak in M_Mathutils_Vector The math types ( matrix, vector, quad ) now make copies of data passed to them rather than holding a pointer to memory that cannot be freed, or that may go away unexpectedly. This also clarifies the problem of who is responsible for freeing memory allocations. Pre-checkin files are tagged mem_leak-1 in case this breaks something.
699 lines
19 KiB
C
699 lines
19 KiB
C
/*
|
|
* $Id$
|
|
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version. The Blender
|
|
* Foundation also sells licenses for use in proprietary software under
|
|
* the Blender License. See http://www.blender.org/BL/ for information
|
|
* about this.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
* All rights reserved.
|
|
*
|
|
*
|
|
* Contributor(s): Willian P. Germano & Joseph Gilbert
|
|
*
|
|
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
|
*/
|
|
|
|
#include "vector.h"
|
|
|
|
//doc strings
|
|
char Vector_Zero_doc[] = "() - set all values in the vector to 0";
|
|
char Vector_Normalize_doc[] = "() - normalize the vector";
|
|
char Vector_Negate_doc[] = "() - changes vector to it's additive inverse";
|
|
char Vector_Resize2D_doc[] = "() - resize a vector to [x,y]";
|
|
char Vector_Resize3D_doc[] = "() - resize a vector to [x,y,z]";
|
|
char Vector_Resize4D_doc[] = "() - resize a vector to [x,y,z,w]";
|
|
|
|
//method table
|
|
struct PyMethodDef Vector_methods[] = {
|
|
{"zero", ( PyCFunction ) Vector_Zero, METH_NOARGS,
|
|
Vector_Zero_doc},
|
|
{"normalize", ( PyCFunction ) Vector_Normalize, METH_NOARGS,
|
|
Vector_Normalize_doc},
|
|
{"negate", ( PyCFunction ) Vector_Negate, METH_NOARGS,
|
|
Vector_Negate_doc},
|
|
{"resize2D", ( PyCFunction ) Vector_Resize2D, METH_NOARGS,
|
|
Vector_Resize2D_doc},
|
|
{"resize3D", ( PyCFunction ) Vector_Resize3D, METH_NOARGS,
|
|
Vector_Resize2D_doc},
|
|
{"resize4D", ( PyCFunction ) Vector_Resize4D, METH_NOARGS,
|
|
Vector_Resize2D_doc},
|
|
{NULL, NULL, 0, NULL}
|
|
};
|
|
|
|
/*****************************/
|
|
// Vector Python Object
|
|
/*****************************/
|
|
|
|
//object methods
|
|
PyObject *Vector_Zero( VectorObject * self )
|
|
{
|
|
int x;
|
|
for( x = 0; x < self->size; x++ ) {
|
|
self->vec[x] = 0.0f;
|
|
}
|
|
|
|
return EXPP_incr_ret( Py_None );
|
|
}
|
|
|
|
PyObject *Vector_Normalize( VectorObject * self )
|
|
{
|
|
float norm;
|
|
int x;
|
|
|
|
norm = 0.0f;
|
|
for( x = 0; x < self->size; x++ ) {
|
|
norm += self->vec[x] * self->vec[x];
|
|
}
|
|
norm = ( float ) sqrt( norm );
|
|
for( x = 0; x < self->size; x++ ) {
|
|
self->vec[x] /= norm;
|
|
}
|
|
|
|
return EXPP_incr_ret( Py_None );
|
|
}
|
|
|
|
PyObject *Vector_Negate( VectorObject * self )
|
|
{
|
|
int x;
|
|
for( x = 0; x < self->size; x++ ) {
|
|
self->vec[x] = -( self->vec[x] );
|
|
}
|
|
|
|
return EXPP_incr_ret( Py_None );
|
|
}
|
|
|
|
PyObject *Vector_Resize2D( VectorObject * self )
|
|
{
|
|
float x, y;
|
|
|
|
if( self->size == 4 || self->size == 3 ) {
|
|
x = self->vec[0];
|
|
y = self->vec[1];
|
|
PyMem_Free( self->vec );
|
|
self->vec = PyMem_Malloc( 2 * sizeof( float ) );
|
|
self->vec[0] = x;
|
|
self->vec[1] = y;
|
|
self->size = 2;
|
|
}
|
|
|
|
return EXPP_incr_ret( Py_None );
|
|
}
|
|
|
|
PyObject *Vector_Resize3D( VectorObject * self )
|
|
{
|
|
float x, y, z;
|
|
|
|
if( self->size == 2 ) {
|
|
x = self->vec[0];
|
|
y = self->vec[1];
|
|
PyMem_Free( self->vec );
|
|
self->vec = PyMem_Malloc( 3 * sizeof( float ) );
|
|
self->vec[0] = x;
|
|
self->vec[1] = y;
|
|
self->vec[2] = 0.0f;
|
|
self->size = 3;
|
|
} else if( self->size == 4 ) {
|
|
x = self->vec[0];
|
|
y = self->vec[1];
|
|
z = self->vec[2];
|
|
PyMem_Free( self->vec );
|
|
self->vec = PyMem_Malloc( 3 * sizeof( float ) );
|
|
self->vec[0] = x;
|
|
self->vec[1] = y;
|
|
self->vec[2] = z;
|
|
self->size = 3;
|
|
}
|
|
|
|
return EXPP_incr_ret( Py_None );
|
|
}
|
|
|
|
PyObject *Vector_Resize4D( VectorObject * self )
|
|
{
|
|
float x, y, z;
|
|
|
|
if( self->size == 2 ) {
|
|
x = self->vec[0];
|
|
y = self->vec[1];
|
|
PyMem_Free( self->vec );
|
|
self->vec = PyMem_Malloc( 4 * sizeof( float ) );
|
|
self->vec[0] = x;
|
|
self->vec[1] = y;
|
|
self->vec[2] = 0.0f;
|
|
self->vec[3] = 1.0f;
|
|
self->size = 4;
|
|
} else if( self->size == 3 ) {
|
|
x = self->vec[0];
|
|
y = self->vec[1];
|
|
z = self->vec[2];
|
|
PyMem_Free( self->vec );
|
|
self->vec = PyMem_Malloc( 4 * sizeof( float ) );
|
|
self->vec[0] = x;
|
|
self->vec[1] = y;
|
|
self->vec[2] = z;
|
|
self->vec[3] = 1.0f;
|
|
self->size = 4;
|
|
}
|
|
|
|
return EXPP_incr_ret( Py_None );
|
|
}
|
|
|
|
static void Vector_dealloc( VectorObject * self )
|
|
{
|
|
/* if we own this memory we must delete it */
|
|
if( self->delete_pymem )
|
|
PyMem_Free( self->vec );
|
|
|
|
PyObject_DEL( self );
|
|
}
|
|
|
|
static PyObject *Vector_getattr( VectorObject * self, char *name )
|
|
{
|
|
if( self->size == 4 && ELEM4( name[0], 'x', 'y', 'z', 'w' )
|
|
&& name[1] == 0 ) {
|
|
if( ( name[0] ) == ( 'w' ) ) {
|
|
return PyFloat_FromDouble( self->vec[3] );
|
|
} else {
|
|
return PyFloat_FromDouble( self->vec[name[0] - 'x'] );
|
|
}
|
|
} else if( self->size == 3 && ELEM3( name[0], 'x', 'y', 'z' )
|
|
&& name[1] == 0 )
|
|
return PyFloat_FromDouble( self->vec[name[0] - 'x'] );
|
|
else if( self->size == 2 && ELEM( name[0], 'x', 'y' ) && name[1] == 0 )
|
|
return PyFloat_FromDouble( self->vec[name[0] - 'x'] );
|
|
|
|
if( ( strcmp( name, "length" ) == 0 ) ) {
|
|
if( self->size == 4 ) {
|
|
return PyFloat_FromDouble( sqrt
|
|
( self->vec[0] *
|
|
self->vec[0] +
|
|
self->vec[1] *
|
|
self->vec[1] +
|
|
self->vec[2] *
|
|
self->vec[2] +
|
|
self->vec[3] *
|
|
self->vec[3] ) );
|
|
} else if( self->size == 3 ) {
|
|
return PyFloat_FromDouble( sqrt
|
|
( self->vec[0] *
|
|
self->vec[0] +
|
|
self->vec[1] *
|
|
self->vec[1] +
|
|
self->vec[2] *
|
|
self->vec[2] ) );
|
|
} else if( self->size == 2 ) {
|
|
return PyFloat_FromDouble( sqrt
|
|
( self->vec[0] *
|
|
self->vec[0] +
|
|
self->vec[1] *
|
|
self->vec[1] ) );
|
|
} else
|
|
EXPP_ReturnPyObjError( PyExc_AttributeError,
|
|
"can only return the length of a 2D ,3D or 4D vector\n" );
|
|
}
|
|
|
|
return Py_FindMethod( Vector_methods, ( PyObject * ) self, name );
|
|
}
|
|
|
|
static int Vector_setattr( VectorObject * self, char *name, PyObject * v )
|
|
{
|
|
float val;
|
|
int valTemp;
|
|
|
|
if( !PyFloat_Check( v ) ) {
|
|
if( !PyInt_Check( v ) ) {
|
|
return EXPP_ReturnIntError( PyExc_TypeError,
|
|
"int or float expected\n" );
|
|
} else {
|
|
if( !PyArg_Parse( v, "i", &valTemp ) )
|
|
return EXPP_ReturnIntError( PyExc_TypeError,
|
|
"unable to parse int argument\n" );
|
|
val = ( float ) valTemp;
|
|
}
|
|
} else {
|
|
if( !PyArg_Parse( v, "f", &val ) )
|
|
return EXPP_ReturnIntError( PyExc_TypeError,
|
|
"unable to parse float argument\n" );
|
|
}
|
|
if( self->size == 4 && ELEM4( name[0], 'x', 'y', 'z', 'w' )
|
|
&& name[1] == 0 ) {
|
|
if( ( name[0] ) == ( 'w' ) ) {
|
|
self->vec[3] = val;
|
|
} else {
|
|
self->vec[name[0] - 'x'] = val;
|
|
}
|
|
} else if( self->size == 3 && ELEM3( name[0], 'x', 'y', 'z' )
|
|
&& name[1] == 0 )
|
|
self->vec[name[0] - 'x'] = val;
|
|
else if( self->size == 2 && ELEM( name[0], 'x', 'y' ) && name[1] == 0 )
|
|
self->vec[name[0] - 'x'] = val;
|
|
else
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Vectors Sequence methods */
|
|
static int Vector_len( VectorObject * self )
|
|
{
|
|
return self->size;
|
|
}
|
|
|
|
static PyObject *Vector_item( VectorObject * self, int i )
|
|
{
|
|
if( i < 0 || i >= self->size )
|
|
return EXPP_ReturnPyObjError( PyExc_IndexError,
|
|
"array index out of range\n" );
|
|
|
|
return Py_BuildValue( "f", self->vec[i] );
|
|
|
|
}
|
|
|
|
static PyObject *Vector_slice( VectorObject * self, int begin, int end )
|
|
{
|
|
PyObject *list;
|
|
int count;
|
|
|
|
if( begin < 0 )
|
|
begin = 0;
|
|
if( end > self->size )
|
|
end = self->size;
|
|
if( begin > end )
|
|
begin = end;
|
|
|
|
list = PyList_New( end - begin );
|
|
|
|
for( count = begin; count < end; count++ ) {
|
|
PyList_SetItem( list, count - begin,
|
|
PyFloat_FromDouble( self->vec[count] ) );
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
static int Vector_ass_item( VectorObject * self, int i, PyObject * ob )
|
|
{
|
|
if( i < 0 || i >= self->size )
|
|
return EXPP_ReturnIntError( PyExc_IndexError,
|
|
"array assignment index out of range\n" );
|
|
if( !PyInt_Check( ob ) && !PyFloat_Check( ob ) )
|
|
return EXPP_ReturnIntError( PyExc_IndexError,
|
|
"vector member must be a number\n" );
|
|
|
|
self->vec[i] = ( float ) PyFloat_AsDouble( ob );
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int Vector_ass_slice( VectorObject * self, int begin, int end,
|
|
PyObject * seq )
|
|
{
|
|
int count, z;
|
|
|
|
if( begin < 0 )
|
|
begin = 0;
|
|
if( end > self->size )
|
|
end = self->size;
|
|
if( begin > end )
|
|
begin = end;
|
|
|
|
if( !PySequence_Check( seq ) )
|
|
return EXPP_ReturnIntError( PyExc_TypeError,
|
|
"illegal argument type for built-in operation\n" );
|
|
if( PySequence_Length( seq ) != ( end - begin ) )
|
|
return EXPP_ReturnIntError( PyExc_TypeError,
|
|
"size mismatch in slice assignment\n" );
|
|
|
|
z = 0;
|
|
for( count = begin; count < end; count++ ) {
|
|
PyObject *ob = PySequence_GetItem( seq, z );
|
|
z++;
|
|
if( !PyInt_Check( ob ) && !PyFloat_Check( ob ) )
|
|
return EXPP_ReturnIntError( PyExc_IndexError,
|
|
"list member must be a number\n" );
|
|
|
|
if( !PyArg_Parse( ob, "f", &self->vec[count] ) ) {
|
|
Py_DECREF( ob );
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *Vector_repr( VectorObject * self )
|
|
{
|
|
int i, maxindex = self->size - 1;
|
|
char ftoa[24];
|
|
PyObject *str1, *str2;
|
|
|
|
str1 = PyString_FromString( "[" );
|
|
|
|
for( i = 0; i < maxindex; i++ ) {
|
|
sprintf( ftoa, "%.4f, ", self->vec[i] );
|
|
str2 = PyString_FromString( ftoa );
|
|
if( !str1 || !str2 )
|
|
goto error;
|
|
PyString_ConcatAndDel( &str1, str2 );
|
|
}
|
|
|
|
sprintf( ftoa, "%.4f]", self->vec[maxindex] );
|
|
str2 = PyString_FromString( ftoa );
|
|
if( !str1 || !str2 )
|
|
goto error;
|
|
PyString_ConcatAndDel( &str1, str2 );
|
|
|
|
if( str1 )
|
|
return str1;
|
|
|
|
error:
|
|
Py_XDECREF( str1 );
|
|
Py_XDECREF( str2 );
|
|
return EXPP_ReturnPyObjError( PyExc_MemoryError,
|
|
"couldn't create PyString!\n" );
|
|
}
|
|
|
|
|
|
PyObject *Vector_add( PyObject * v1, PyObject * v2 )
|
|
{
|
|
float *vec;
|
|
int x;
|
|
PyObject *retval;
|
|
|
|
if( ( !VectorObject_Check( v1 ) ) || ( !VectorObject_Check( v2 ) ) )
|
|
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"unsupported type for this operation\n" );
|
|
if( ( ( VectorObject * ) v1 )->flag != 0
|
|
|| ( ( VectorObject * ) v2 )->flag != 0 )
|
|
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"cannot add a scalar to a vector\n" );
|
|
if( ( ( VectorObject * ) v1 )->size !=
|
|
( ( VectorObject * ) v2 )->size )
|
|
return EXPP_ReturnPyObjError( PyExc_AttributeError,
|
|
"vectors must have the same dimensions for this operation\n" );
|
|
|
|
vec = PyMem_Malloc( ( ( ( VectorObject * ) v1 )->size ) *
|
|
sizeof( float ) );
|
|
|
|
for( x = 0; x < ( ( VectorObject * ) v1 )->size; x++ ) {
|
|
vec[x] = ( ( VectorObject * ) v1 )->vec[x] +
|
|
( ( VectorObject * ) v2 )->vec[x];
|
|
}
|
|
|
|
retval = ( PyObject * ) newVectorObject( vec,
|
|
( ( ( VectorObject * ) v1 )->
|
|
size ) );
|
|
PyMem_Free( vec );
|
|
return retval;
|
|
}
|
|
|
|
PyObject *Vector_sub( PyObject * v1, PyObject * v2 )
|
|
{
|
|
float *vec;
|
|
int x;
|
|
PyObject *retval;
|
|
|
|
if( ( !VectorObject_Check( v1 ) ) || ( !VectorObject_Check( v2 ) ) )
|
|
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"unsupported type for this operation\n" );
|
|
if( ( ( VectorObject * ) v1 )->flag != 0
|
|
|| ( ( VectorObject * ) v2 )->flag != 0 )
|
|
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"cannot subtract a scalar from a vector\n" );
|
|
if( ( ( VectorObject * ) v1 )->size !=
|
|
( ( VectorObject * ) v2 )->size )
|
|
return EXPP_ReturnPyObjError( PyExc_AttributeError,
|
|
"vectors must have the same dimensions for this operation\n" );
|
|
|
|
vec = PyMem_Malloc( ( ( ( VectorObject * ) v1 )->size ) *
|
|
sizeof( float ) );
|
|
|
|
for( x = 0; x < ( ( VectorObject * ) v1 )->size; x++ ) {
|
|
vec[x] = ( ( VectorObject * ) v1 )->vec[x] -
|
|
( ( VectorObject * ) v2 )->vec[x];
|
|
}
|
|
|
|
retval = ( PyObject * ) newVectorObject( vec,
|
|
( ( ( VectorObject * ) v1 )->
|
|
size ) );
|
|
PyMem_Free( vec );
|
|
return retval;
|
|
}
|
|
|
|
PyObject *Vector_mul( PyObject * v1, PyObject * v2 )
|
|
{
|
|
float *vec;
|
|
int x;
|
|
PyObject *retval;
|
|
|
|
if( ( !VectorObject_Check( v1 ) ) || ( !VectorObject_Check( v2 ) ) )
|
|
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"unsupported type for this operation\n" );
|
|
if( ( ( VectorObject * ) v1 )->flag == 0
|
|
&& ( ( VectorObject * ) v2 )->flag == 0 )
|
|
return EXPP_ReturnPyObjError( PyExc_ArithmeticError,
|
|
"please use the dot product or the cross product to multiply vectors\n" );
|
|
if( ( ( VectorObject * ) v1 )->size !=
|
|
( ( VectorObject * ) v2 )->size )
|
|
return EXPP_ReturnPyObjError( PyExc_AttributeError,
|
|
"vector dimension error during Vector_mul\n" );
|
|
|
|
vec = PyMem_Malloc( ( ( ( VectorObject * ) v1 )->size ) *
|
|
sizeof( float ) );
|
|
|
|
for( x = 0; x < ( ( VectorObject * ) v1 )->size; x++ ) {
|
|
vec[x] = ( ( VectorObject * ) v1 )->vec[x] *
|
|
( ( VectorObject * ) v2 )->vec[x];
|
|
}
|
|
|
|
retval = ( PyObject * ) newVectorObject( vec,
|
|
( ( ( VectorObject * ) v1 )->
|
|
size ) );
|
|
PyMem_Free( vec );
|
|
return retval;
|
|
}
|
|
|
|
PyObject *Vector_div( PyObject * v1, PyObject * v2 )
|
|
{
|
|
float *vec;
|
|
int x;
|
|
PyObject *retval;
|
|
|
|
if( ( !VectorObject_Check( v1 ) ) || ( !VectorObject_Check( v2 ) ) )
|
|
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"unsupported type for this operation\n" );
|
|
if( ( ( VectorObject * ) v1 )->flag == 0
|
|
&& ( ( VectorObject * ) v2 )->flag == 0 )
|
|
return EXPP_ReturnPyObjError( PyExc_ArithmeticError,
|
|
"cannot divide two vectors\n" );
|
|
if( ( ( VectorObject * ) v1 )->flag != 0
|
|
&& ( ( VectorObject * ) v2 )->flag == 0 )
|
|
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
"cannot divide a scalar by a vector\n" );
|
|
if( ( ( VectorObject * ) v1 )->size !=
|
|
( ( VectorObject * ) v2 )->size )
|
|
return EXPP_ReturnPyObjError( PyExc_AttributeError,
|
|
"vector dimension error during Vector_mul\n" );
|
|
|
|
vec = PyMem_Malloc( ( ( ( VectorObject * ) v1 )->size ) *
|
|
sizeof( float ) );
|
|
|
|
for( x = 0; x < ( ( VectorObject * ) v1 )->size; x++ ) {
|
|
vec[x] = ( ( VectorObject * ) v1 )->vec[x] /
|
|
( ( VectorObject * ) v2 )->vec[x];
|
|
}
|
|
|
|
retval = ( PyObject * ) newVectorObject( vec,
|
|
( ( ( VectorObject * ) v1 )->
|
|
size ) );
|
|
PyMem_Free( vec );
|
|
return retval;
|
|
}
|
|
|
|
//coercion of unknown types to type VectorObject for numeric protocols
|
|
int Vector_coerce( PyObject ** v1, PyObject ** v2 )
|
|
{
|
|
long *tempI;
|
|
double *tempF;
|
|
float *vec;
|
|
int x;
|
|
|
|
if( VectorObject_Check( *v1 ) ) {
|
|
if( VectorObject_Check( *v2 ) ) { //two vectors
|
|
Py_INCREF( *v1 ); /* fixme: wahy are we bumping the ref count? */
|
|
Py_INCREF( *v2 );
|
|
return 0;
|
|
} else {
|
|
if( Matrix_CheckPyObject( *v2 ) ) {
|
|
printf( "vector/matrix numeric protocols unsupported...\n" );
|
|
Py_INCREF( *v1 );
|
|
return 0; //operation will type check
|
|
} else if( PyNumber_Check( *v2 ) ) {
|
|
if( PyInt_Check( *v2 ) ) { //cast scalar to vector
|
|
tempI = PyMem_Malloc( 1 *
|
|
sizeof( long ) );
|
|
*tempI = PyInt_AsLong( *v2 );
|
|
vec = PyMem_Malloc( ( ( ( VectorObject
|
|
* ) *
|
|
v1 )->size ) *
|
|
sizeof( float ) );
|
|
for( x = 0;
|
|
x < ( ( ( VectorObject * ) * v1 )->size );
|
|
x++ ) {
|
|
vec[x] = ( float ) *tempI;
|
|
}
|
|
PyMem_Free( tempI );
|
|
*v2 = newVectorObject( vec,
|
|
( ( ( VectorObject * ) * v1 )->size ) );
|
|
( ( VectorObject * ) * v2 )->flag = 1; //int coercion
|
|
Py_INCREF( *v1 );
|
|
return 0;
|
|
} else if( PyFloat_Check( *v2 ) ) { //cast scalar to vector
|
|
tempF = PyMem_Malloc( 1 *
|
|
sizeof
|
|
( double ) );
|
|
*tempF = PyFloat_AsDouble( *v2 );
|
|
vec = PyMem_Malloc( ( ( ( VectorObject
|
|
* ) *
|
|
v1 )->size ) *
|
|
sizeof( float ) );
|
|
for( x = 0;
|
|
x <
|
|
( ( ( VectorObject * ) *
|
|
v1 )->size ); x++ ) {
|
|
vec[x] = ( float ) *tempF;
|
|
}
|
|
PyMem_Free( tempF );
|
|
*v2 = newVectorObject( vec,
|
|
( ( ( VectorObject * ) * v1 )->size ) );
|
|
( ( VectorObject * ) * v2 )->flag = 2; //float coercion
|
|
Py_INCREF( *v1 );
|
|
return 0;
|
|
}
|
|
}
|
|
//unknown type or numeric cast failure
|
|
printf( "attempting vector operation with unsupported type...\n" );
|
|
Py_INCREF( *v1 );
|
|
return 0; //operation will type check
|
|
}
|
|
} else {
|
|
printf( "numeric protocol failure...\n" );
|
|
return -1; //this should not occur - fail
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
static PySequenceMethods Vector_SeqMethods = {
|
|
( inquiry ) Vector_len, /* sq_length */
|
|
( binaryfunc ) 0, /* sq_concat */
|
|
( intargfunc ) 0, /* sq_repeat */
|
|
( intargfunc ) Vector_item, /* sq_item */
|
|
( intintargfunc ) Vector_slice, /* sq_slice */
|
|
( intobjargproc ) Vector_ass_item, /* sq_ass_item */
|
|
( intintobjargproc ) Vector_ass_slice, /* sq_ass_slice */
|
|
};
|
|
|
|
static PyNumberMethods Vector_NumMethods = {
|
|
( binaryfunc ) Vector_add, /* __add__ */
|
|
( binaryfunc ) Vector_sub, /* __sub__ */
|
|
( binaryfunc ) Vector_mul, /* __mul__ */
|
|
( binaryfunc ) Vector_div, /* __div__ */
|
|
( binaryfunc ) 0, /* __mod__ */
|
|
( binaryfunc ) 0, /* __divmod__ */
|
|
( ternaryfunc ) 0, /* __pow__ */
|
|
( unaryfunc ) 0, /* __neg__ */
|
|
( unaryfunc ) 0, /* __pos__ */
|
|
( unaryfunc ) 0, /* __abs__ */
|
|
( inquiry ) 0, /* __nonzero__ */
|
|
( unaryfunc ) 0, /* __invert__ */
|
|
( binaryfunc ) 0, /* __lshift__ */
|
|
( binaryfunc ) 0, /* __rshift__ */
|
|
( binaryfunc ) 0, /* __and__ */
|
|
( binaryfunc ) 0, /* __xor__ */
|
|
( binaryfunc ) 0, /* __or__ */
|
|
( coercion ) Vector_coerce, /* __coerce__ */
|
|
( unaryfunc ) 0, /* __int__ */
|
|
( unaryfunc ) 0, /* __long__ */
|
|
( unaryfunc ) 0, /* __float__ */
|
|
( unaryfunc ) 0, /* __oct__ */
|
|
( unaryfunc ) 0, /* __hex__ */
|
|
|
|
};
|
|
|
|
PyTypeObject vector_Type = {
|
|
PyObject_HEAD_INIT( NULL ) 0, /*ob_size */
|
|
"vector", /*tp_name */
|
|
sizeof( VectorObject ), /*tp_basicsize */
|
|
0, /*tp_itemsize */
|
|
( destructor ) Vector_dealloc, /*tp_dealloc */
|
|
( printfunc ) 0, /*tp_print */
|
|
( getattrfunc ) Vector_getattr, /*tp_getattr */
|
|
( setattrfunc ) Vector_setattr, /*tp_setattr */
|
|
0, /*tp_compare */
|
|
( reprfunc ) Vector_repr, /*tp_repr */
|
|
&Vector_NumMethods, /*tp_as_number */
|
|
&Vector_SeqMethods, /*tp_as_sequence */
|
|
};
|
|
|
|
|
|
/*
|
|
* create a Vector Object( vec, size )
|
|
*
|
|
* Note: Vector now uses copy semantics like STL containers.
|
|
* Memory for vec member is allocated on python stack.
|
|
* We own this memory and will free it later.
|
|
*
|
|
* size arg is number of floats to alloc.
|
|
*
|
|
* if vec arg is NULL
|
|
* fill our vec with zeros
|
|
* initialize 4d vectors to zero in homogenous coords.
|
|
* else
|
|
* vec param is copied into our local memory and always freed.
|
|
*/
|
|
|
|
PyObject *newVectorObject( float *vec, int size )
|
|
{
|
|
VectorObject *self;
|
|
int x;
|
|
|
|
vector_Type.ob_type = &PyType_Type;
|
|
|
|
self = PyObject_NEW( VectorObject, &vector_Type );
|
|
|
|
self->vec = PyMem_Malloc( size * sizeof( float ) );
|
|
self->delete_pymem = 1; /* must free this alloc later */
|
|
|
|
if( !vec ) {
|
|
for( x = 0; x < size; x++ ) {
|
|
self->vec[x] = 0.0f;
|
|
}
|
|
if( size == 4 ) /* do the homogenous thing */
|
|
self->vec[3] = 1.0f;
|
|
} else {
|
|
for( x = 0; x < size; x++ ){
|
|
self->vec[x] = vec[x];
|
|
}
|
|
}
|
|
|
|
self->size = size;
|
|
self->flag = 0;
|
|
|
|
return ( PyObject * ) self;
|
|
}
|