Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/python/api2_2x/matrix.c')
-rw-r--r--source/blender/python/api2_2x/matrix.c1470
1 files changed, 838 insertions, 632 deletions
diff --git a/source/blender/python/api2_2x/matrix.c b/source/blender/python/api2_2x/matrix.c
index abea09b5f12..b50df287061 100644
--- a/source/blender/python/api2_2x/matrix.c
+++ b/source/blender/python/api2_2x/matrix.c
@@ -28,804 +28,1010 @@
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
-#include <BKE_utildefines.h>
-#include <BLI_arithb.h>
-#include "Mathutils.h"
-#include "gen_utils.h"
+#include "matrix.h"
-//-------------------------DOC STRINGS ---------------------------
+//doc strings
char Matrix_Zero_doc[] = "() - set all values in the matrix to 0";
-char Matrix_Identity_doc[] = "() - set the square matrix to it's identity matrix";
+char Matrix_Identity_doc[] =
+ "() - set the square matrix to it's identity matrix";
char Matrix_Transpose_doc[] = "() - set the matrix to it's transpose";
char Matrix_Determinant_doc[] = "() - return the determinant of the matrix";
-char Matrix_Invert_doc[] = "() - set the matrix to it's inverse if an inverse is possible";
-char Matrix_TranslationPart_doc[] = "() - return a vector encompassing the translation of the matrix";
-char Matrix_RotationPart_doc[] = "() - return a vector encompassing the rotation of the matrix";
+char Matrix_Invert_doc[] =
+ "() - set the matrix to it's inverse if an inverse is possible";
+char Matrix_TranslationPart_doc[] =
+ "() - return a vector encompassing the translation of the matrix";
+char Matrix_RotationPart_doc[] =
+ "() - return a vector encompassing the rotation of the matrix";
char Matrix_Resize4x4_doc[] = "() - resize the matrix to a 4x4 square matrix";
char Matrix_toEuler_doc[] = "() - convert matrix to a euler angle rotation";
char Matrix_toQuat_doc[] = "() - convert matrix to a quaternion rotation";
-//-----------------------METHOD DEFINITIONS ----------------------
+
+//methods table
struct PyMethodDef Matrix_methods[] = {
- {"zero", (PyCFunction) Matrix_Zero, METH_NOARGS, Matrix_Zero_doc},
- {"identity", (PyCFunction) Matrix_Identity, METH_NOARGS, Matrix_Identity_doc},
- {"transpose", (PyCFunction) Matrix_Transpose, METH_NOARGS, Matrix_Transpose_doc},
- {"determinant", (PyCFunction) Matrix_Determinant, METH_NOARGS, Matrix_Determinant_doc},
- {"invert", (PyCFunction) Matrix_Invert, METH_NOARGS, Matrix_Invert_doc},
- {"translationPart", (PyCFunction) Matrix_TranslationPart, METH_NOARGS, Matrix_TranslationPart_doc},
- {"rotationPart", (PyCFunction) Matrix_RotationPart, METH_NOARGS, Matrix_RotationPart_doc},
- {"resize4x4", (PyCFunction) Matrix_Resize4x4, METH_NOARGS, Matrix_Resize4x4_doc},
- {"toEuler", (PyCFunction) Matrix_toEuler, METH_NOARGS, Matrix_toEuler_doc},
- {"toQuat", (PyCFunction) Matrix_toQuat, METH_NOARGS, Matrix_toQuat_doc},
+ {"zero", ( PyCFunction ) Matrix_Zero, METH_NOARGS,
+ Matrix_Zero_doc},
+ {"identity", ( PyCFunction ) Matrix_Identity, METH_NOARGS,
+ Matrix_Identity_doc},
+ {"transpose", ( PyCFunction ) Matrix_Transpose, METH_NOARGS,
+ Matrix_Transpose_doc},
+ {"determinant", ( PyCFunction ) Matrix_Determinant, METH_NOARGS,
+ Matrix_Determinant_doc},
+ {"invert", ( PyCFunction ) Matrix_Invert, METH_NOARGS,
+ Matrix_Invert_doc},
+ {"translationPart", ( PyCFunction ) Matrix_TranslationPart,
+ METH_NOARGS,
+ Matrix_TranslationPart_doc},
+ {"rotationPart", ( PyCFunction ) Matrix_RotationPart, METH_NOARGS,
+ Matrix_RotationPart_doc},
+ {"resize4x4", ( PyCFunction ) Matrix_Resize4x4, METH_NOARGS,
+ Matrix_Resize4x4_doc},
+ {"toEuler", ( PyCFunction ) Matrix_toEuler, METH_NOARGS,
+ Matrix_toEuler_doc},
+ {"toQuat", ( PyCFunction ) Matrix_toQuat, METH_NOARGS,
+ Matrix_toQuat_doc},
{NULL, NULL, 0, NULL}
};
-//-----------------------------METHODS----------------------------
-//---------------------------Matrix.toQuat() ---------------------
-PyObject *Matrix_toQuat(MatrixObject * self)
+
+/*****************************/
+// Matrix Python Object
+/*****************************/
+
+PyObject *Matrix_toQuat( MatrixObject * self )
{
- float quat[4];
-
- //must be 3-4 cols, 3-4 rows, square matrix
- if(self->colSize < 3 || self->rowSize < 3 || (self->colSize != self->rowSize)) {
- return EXPP_ReturnPyObjError(PyExc_AttributeError,
- "Matrix.toQuat(): inappropriate matrix size - expects 3x3 or 4x4 matrix\n");
- }
- if(self->colSize == 3){
- Mat3ToQuat((float (*)[3])*self->matrix, quat);
- }else{
- Mat4ToQuat((float (*)[4])*self->matrix, quat);
+ float *quat, *mat;
+
+ if( self->colSize < 3 ) {
+ return EXPP_ReturnPyObjError( PyExc_AttributeError,
+ "inappropriate matrix size\n" );
+ } else if( self->colSize > 2 ) { //3 or 4 col
+ if( self->rowSize < 3 ) //3 or 4 row
+ return EXPP_ReturnPyObjError( PyExc_AttributeError,
+ "inappropriate matrix size\n" );
+
+ mat = PyMem_Malloc( 3 * 3 * sizeof( float ) );
+ if( mat == NULL ) {
+ return ( EXPP_ReturnPyObjError( PyExc_MemoryError,
+ "problem allocating matrix\n\n" ) );
+ }
+ mat[0] = self->matrix[0][0];
+ mat[1] = self->matrix[0][1];
+ mat[2] = self->matrix[0][2];
+ mat[3] = self->matrix[1][0];
+ mat[4] = self->matrix[1][1];
+ mat[5] = self->matrix[1][2];
+ mat[6] = self->matrix[2][0];
+ mat[7] = self->matrix[2][1];
+ mat[8] = self->matrix[2][2];
}
-
- if(self->data.blend_data)
- return (PyObject *) newQuaternionObject(quat, Py_WRAP);
- else
- return (PyObject *) newQuaternionObject(quat, Py_NEW);
+ quat = PyMem_Malloc( 4 * sizeof( float ) );
+ if( quat == NULL ) {
+ PyMem_Free( mat );
+ return ( EXPP_ReturnPyObjError( PyExc_MemoryError,
+ "problem allocating quat\n\n" ) );
+ }
+ Mat3ToQuat( ( float ( * )[3] ) mat, quat );
+
+ return ( PyObject * ) newQuaternionObject( quat );
}
-//---------------------------Matrix.toEuler() --------------------
-PyObject *Matrix_toEuler(MatrixObject * self)
+
+
+PyObject *Matrix_toEuler( MatrixObject * self )
{
- float eul[3];
+ float *eul, *mat;
int x;
- //must be 3-4 cols, 3-4 rows, square matrix
- if(self->colSize !=3 || self->rowSize != 3) {
- return EXPP_ReturnPyObjError(PyExc_AttributeError,
- "Matrix.toQuat(): inappropriate matrix size - expects 3x3 matrix\n");
- }
- Mat3ToEul((float (*)[3])*self->matrix, eul);
- //have to convert to degrees
- for(x = 0; x < 3; x++) {
- eul[x] *= (float) (180 / Py_PI);
- }
- if(self->data.blend_data)
- return (PyObject *) newEulerObject(eul, Py_WRAP);
- else
- return (PyObject *) newEulerObject(eul, Py_NEW);
+ if( self->colSize < 3 ) {
+ return EXPP_ReturnPyObjError( PyExc_AttributeError,
+ "inappropriate matrix size\n" );
+ } else if( self->colSize > 2 ) { //3 or 4 col
+ if( self->rowSize < 3 ) //3 or 4 row
+ return EXPP_ReturnPyObjError( PyExc_AttributeError,
+ "inappropriate matrix size\n" );
+
+ mat = PyMem_Malloc( 3 * 3 * sizeof( float ) );
+ if( mat == NULL ) {
+ return ( EXPP_ReturnPyObjError( PyExc_MemoryError,
+ "problem allocating mat\n\n" ) );
+ }
+ mat[0] = self->matrix[0][0];
+ mat[1] = self->matrix[0][1];
+ mat[2] = self->matrix[0][2];
+ mat[3] = self->matrix[1][0];
+ mat[4] = self->matrix[1][1];
+ mat[5] = self->matrix[1][2];
+ mat[6] = self->matrix[2][0];
+ mat[7] = self->matrix[2][1];
+ mat[8] = self->matrix[2][2];
+ }
+ eul = PyMem_Malloc( 3 * sizeof( float ) );
+ if( eul == NULL ) {
+ PyMem_Free( mat );
+ return ( EXPP_ReturnPyObjError( PyExc_MemoryError,
+ "problem allocating eul\n\n" ) );
+ }
+ Mat3ToEul( ( float ( * )[3] ) mat, eul );
+
+ for( x = 0; x < 3; x++ ) {
+ eul[x] *= ( float ) ( 180 / Py_PI );
+ }
+
+ return ( PyObject * ) newEulerObject( eul );
}
-//---------------------------Matrix.resize4x4() ------------------
-PyObject *Matrix_Resize4x4(MatrixObject * self)
+
+PyObject *Matrix_Resize4x4( MatrixObject * self )
{
- int x, first_row_elem, curr_pos, new_pos, blank_columns, blank_rows;
+ float *mat;
+ int x, row, col;
+
+ if( self->colSize == 4 && self->rowSize == 4 )
+ return EXPP_incr_ret( Py_None );
- if(self->data.blend_data){
- return EXPP_ReturnPyObjError(PyExc_TypeError,
- "cannot resize wrapped data - only python matrices\n");
+ mat = PyMem_Malloc( 4 * 4 * sizeof( float ) );
+ if( mat == NULL ) {
+ return ( EXPP_ReturnPyObjError( PyExc_MemoryError,
+ "problem allocating mat\n\n" ) );
+ }
+ for( x = 0; x < 16; x++ ) {
+ mat[x] = 0.0f;
}
- self->data.py_data = PyMem_Realloc(self->data.py_data, (sizeof(float) * 16));
- if(self->data.py_data == NULL) {
- return EXPP_ReturnPyObjError(PyExc_MemoryError,
- "matrix.resize4x4(): problem allocating pointer space\n\n");
+ if( self->colSize == 2 ) { //2x2, 2x3, 2x4
+ mat[0] = self->matrix[0][0];
+ mat[1] = self->matrix[0][1];
+ mat[4] = self->matrix[1][0];
+ mat[5] = self->matrix[1][1];
+ if( self->rowSize > 2 ) {
+ mat[8] = self->matrix[2][0];
+ mat[9] = self->matrix[2][1];
+ }
+ if( self->rowSize > 3 ) {
+ mat[12] = self->matrix[3][0];
+ mat[13] = self->matrix[3][1];
+ }
+ mat[10] = 1.0f;
+ mat[15] = 1.0f;
+ } else if( self->colSize == 3 ) { //3x2, 3x3, 3x4
+ mat[0] = self->matrix[0][0];
+ mat[1] = self->matrix[0][1];
+ mat[2] = self->matrix[0][2];
+ mat[4] = self->matrix[1][0];
+ mat[5] = self->matrix[1][1];
+ mat[6] = self->matrix[1][2];
+ if( self->rowSize > 2 ) {
+ mat[8] = self->matrix[2][0];
+ mat[9] = self->matrix[2][1];
+ mat[10] = self->matrix[2][2];
+ }
+ if( self->rowSize > 3 ) {
+ mat[12] = self->matrix[3][0];
+ mat[13] = self->matrix[3][1];
+ mat[14] = self->matrix[3][2];
+ }
+ if( self->rowSize == 2 )
+ mat[10] = 1.0f;
+ mat[15] = 1.0f;
+ } else if( self->colSize == 4 ) { //2x4, 3x4
+ mat[0] = self->matrix[0][0];
+ mat[1] = self->matrix[0][1];
+ mat[2] = self->matrix[0][2];
+ mat[3] = self->matrix[0][3];
+ mat[4] = self->matrix[1][0];
+ mat[5] = self->matrix[1][1];
+ mat[6] = self->matrix[1][2];
+ mat[7] = self->matrix[1][3];
+ if( self->rowSize > 2 ) {
+ mat[8] = self->matrix[2][0];
+ mat[9] = self->matrix[2][1];
+ mat[10] = self->matrix[2][2];
+ mat[11] = self->matrix[2][3];
+ }
+ if( self->rowSize == 2 )
+ mat[10] = 1.0f;
+ mat[15] = 1.0f;
}
- self->contigPtr = self->data.py_data; //force
- self->matrix = PyMem_Realloc(self->matrix, (sizeof(float) * 4));
- if(self->matrix == NULL) {
- return EXPP_ReturnPyObjError(PyExc_MemoryError,
- "matrix.resize4x4(): problem allocating pointer space\n\n");
+
+ PyMem_Free( self->matrix );
+ PyMem_Free( self->contigPtr );
+ self->contigPtr = PyMem_Malloc( 4 * 4 * sizeof( float ) );
+ if( self->contigPtr == NULL ) {
+ return ( EXPP_ReturnPyObjError( PyExc_MemoryError,
+ "problem allocating array space\n\n" ) );
}
- //set row pointers
- for(x = 0; x < 4; x++) {
- self->matrix[x] = self->contigPtr + (x * 4);
+ self->matrix = PyMem_Malloc( 4 * sizeof( float * ) );
+ if( self->matrix == NULL ) {
+ PyMem_Free( self->contigPtr );
+ return ( EXPP_ReturnPyObjError( PyExc_MemoryError,
+ "problem allocating pointer space\n\n" ) );
}
- //move data to new spot in array + clean
- for(blank_rows = (4 - self->rowSize); blank_rows > 0; blank_rows--){
- for(x = 0; x < 4; x++){
- self->contigPtr[(4 * (self->rowSize + (blank_rows - 1))) + x] = 0.0f;
- }
+ for( x = 0; x < 4; x++ ) {
+ self->matrix[x] = self->contigPtr + ( x * 4 );
}
- for(x = 1; x <= self->rowSize; x++){
- first_row_elem = (self->colSize * (self->rowSize - x));
- curr_pos = (first_row_elem + (self->colSize -1));
- new_pos = (4 * (self->rowSize - x )) + (curr_pos - first_row_elem);
- for(blank_columns = (4 - self->colSize); blank_columns > 0; blank_columns--){
- self->contigPtr[new_pos + blank_columns] = 0.0f;
- }
- for(curr_pos; curr_pos >= first_row_elem; curr_pos--){
- self->contigPtr[new_pos] = self->contigPtr[curr_pos];
- new_pos--;
+
+ for( row = 0; row < 4; row++ ) {
+ for( col = 0; col < 4; col++ ) {
+ self->matrix[row][col] = mat[( row * 4 ) + col];
}
}
- self->rowSize = 4;
+ PyMem_Free( mat );
+
self->colSize = 4;
- return (PyObject*)self;
+ self->rowSize = 4;
+
+ return EXPP_incr_ret( Py_None );
}
-//---------------------------Matrix.translationPart() ------------
-PyObject *Matrix_TranslationPart(MatrixObject * self)
+
+PyObject *Matrix_TranslationPart( MatrixObject * self )
{
- float vec[4];
+ float *vec = NULL;
+ PyObject *retval;
- if(self->colSize < 3 && self->rowSize < 4){
- return EXPP_ReturnPyObjError(PyExc_AttributeError,
- "Matrix.translationPart: inappropriate matrix size\n");
- }
+ if( self->colSize < 3 ) {
+ return EXPP_ReturnPyObjError( PyExc_AttributeError,
+ "inappropriate matrix size\n" );
+ } else if( self->colSize > 2 ) { //3 or 4 columns
+ if( self->rowSize < 4 ) //all 4 rows
+ return EXPP_ReturnPyObjError( PyExc_AttributeError,
+ "inappropriate matrix size\n" );
- vec[0] = self->matrix[3][0];
- vec[1] = self->matrix[3][1];
- vec[2] = self->matrix[3][2];
+ vec = PyMem_Malloc( 3 * sizeof( float ) );
+ if( vec == NULL ) {
+ return ( EXPP_ReturnPyObjError( PyExc_MemoryError,
+ "problem allocating vec\n\n" ) );
+ }
+ vec[0] = self->matrix[3][0];
+ vec[1] = self->matrix[3][1];
+ vec[2] = self->matrix[3][2];
+ }
- return newVectorObject(vec, 3, Py_NEW);
+ retval = ( PyObject * ) newVectorObject( vec, 3 );
+ PyMem_Free( vec );
+ return retval;
}
-//---------------------------Matrix.rotationPart() ---------------
-PyObject *Matrix_RotationPart(MatrixObject * self)
+
+PyObject *Matrix_RotationPart( MatrixObject * self )
{
- float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
+ float *mat;
- if(self->colSize < 3 && self->rowSize < 3){
- return EXPP_ReturnPyObjError(PyExc_AttributeError,
- "Matrix.rotationPart: inappropriate matrix size\n");
- }
+ if( self->colSize < 3 ) {
+ return EXPP_ReturnPyObjError( PyExc_AttributeError,
+ "inappropriate matrix size\n" );
+ } else if( self->colSize > 2 ) { //3 or 4 col
+ if( self->rowSize < 3 ) //3 or 4 row
+ return EXPP_ReturnPyObjError( PyExc_AttributeError,
+ "inappropriate matrix size\n" );
- mat[0] = self->matrix[0][0];
- mat[1] = self->matrix[0][1];
- mat[2] = self->matrix[0][2];
- mat[3] = self->matrix[1][0];
- mat[4] = self->matrix[1][1];
- mat[5] = self->matrix[1][2];
- mat[6] = self->matrix[2][0];
- mat[7] = self->matrix[2][1];
- mat[8] = self->matrix[2][2];
+ mat = PyMem_Malloc( 3 * 3 * sizeof( float ) );
+ if( mat == NULL ) {
+ return ( EXPP_ReturnPyObjError( PyExc_MemoryError,
+ "problem allocating mat\n\n" ) );
+ }
+ mat[0] = self->matrix[0][0];
+ mat[1] = self->matrix[0][1];
+ mat[2] = self->matrix[0][2];
+ mat[3] = self->matrix[1][0];
+ mat[4] = self->matrix[1][1];
+ mat[5] = self->matrix[1][2];
+ mat[6] = self->matrix[2][0];
+ mat[7] = self->matrix[2][1];
+ mat[8] = self->matrix[2][2];
+ }
- return newMatrixObject(mat, 3, 3, Py_NEW);
+ return ( PyObject * ) newMatrixObject( mat, 3, 3 );
}
-//---------------------------Matrix.invert() ---------------------
-PyObject *Matrix_Invert(MatrixObject * self)
+
+PyObject *Matrix_Invert( MatrixObject * self )
{
-
- int x, y, z = 0;
- float det = 0.0f;
- PyObject *f = NULL;
- float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
+ float det;
+ int x, y, z;
+ float *mat = NULL;
+ float t;
- if(self->rowSize != self->colSize){
- return EXPP_ReturnPyObjError(PyExc_AttributeError,
- "Matrix.invert: only square matrices are supported\n");
- }
+ if( self->rowSize != self->colSize )
+ return EXPP_ReturnPyObjError( PyExc_AttributeError,
+ "only square matrices are supported\n" );
//calculate the determinant
- f = Matrix_Determinant(self);
- det = PyFloat_AS_DOUBLE(f);
+ if( self->rowSize == 2 ) {
+ det = Det2x2( self->matrix[0][0], self->matrix[0][1],
+ self->matrix[1][0], self->matrix[1][1] );
+ } else if( self->rowSize == 3 ) {
+ det = Det3x3( self->matrix[0][0], self->matrix[0][1],
+ self->matrix[0][2], self->matrix[1][0],
+ self->matrix[1][1], self->matrix[1][2],
+ self->matrix[2][0], self->matrix[2][1],
+ self->matrix[2][2] );
+ } else if( self->rowSize == 4 ) {
+ det = Det4x4( (float ( * )[4]) *self->matrix );
+ } else {
+ return EXPP_ReturnPyObjError( PyExc_StandardError,
+ "error calculating determinant for inverse()\n" );
+ }
+
+ if( det != 0 ) {
- if(det != 0) {
//calculate the classical adjoint
- if(self->rowSize == 2) {
+ if( self->rowSize == 2 ) {
+ mat = PyMem_Malloc( self->rowSize * self->colSize *
+ sizeof( float ) );
+ if( mat == NULL ) {
+ return ( EXPP_ReturnPyObjError
+ ( PyExc_MemoryError,
+ "problem allocating mat\n\n" ) );
+ }
mat[0] = self->matrix[1][1];
mat[1] = -self->matrix[1][0];
mat[2] = -self->matrix[0][1];
mat[3] = self->matrix[0][0];
- } else if(self->rowSize == 3) {
- Mat3Adj((float (*)[3]) mat,(float (*)[3]) *self->matrix);
- } else if(self->rowSize == 4) {
- Mat4Adj((float (*)[4]) mat, (float (*)[4]) *self->matrix);
+ } else if( self->rowSize == 3 ) {
+ mat = PyMem_Malloc( self->rowSize * self->colSize *
+ sizeof( float ) );
+ if( mat == NULL ) {
+ return ( EXPP_ReturnPyObjError
+ ( PyExc_MemoryError,
+ "problem allocating mat\n\n" ) );
+ }
+ Mat3Adj( ( float ( * )[3] ) mat,( float ( * )[3] ) *self->matrix );
+ } else if( self->rowSize == 4 ) {
+ mat = PyMem_Malloc( self->rowSize * self->colSize *
+ sizeof( float ) );
+ if( mat == NULL ) {
+ return ( EXPP_ReturnPyObjError
+ ( PyExc_MemoryError,
+ "problem allocating mat\n\n" ) );
+ }
+ Mat4Adj( ( float ( * )[4] ) mat, ( float ( * )[4] ) *self->matrix );
}
//divide by determinate
- for(x = 0; x < (self->rowSize * self->colSize); x++) {
+ for( x = 0; x < ( self->rowSize * self->colSize ); x++ ) {
mat[x] /= det;
}
+
//set values
- for(x = 0; x < self->rowSize; x++) {
- for(y = 0; y < self->colSize; y++) {
+ z = 0;
+ for( x = 0; x < self->rowSize; x++ ) {
+ for( y = 0; y < self->colSize; y++ ) {
self->matrix[x][y] = mat[z];
z++;
}
}
+
//transpose
- Matrix_Transpose(self);
+ if( self->rowSize == 2 ) {
+ t = self->matrix[1][0];
+ self->matrix[1][0] = self->matrix[0][1];
+ self->matrix[0][1] = t;
+
+/*
+ Note: is the code below correct?
+ transposing mat and not copying into self->matrix?
+ s. swaney 11-oct-2004
+*/
+ } else if( self->rowSize == 3 ) {
+ Mat3Transp( ( float ( * )[3] ) mat );
+ } else if( self->rowSize == 4 ) {
+ Mat4Transp( ( float ( * )[4] ) mat );
+ }
} else {
- printf("Matrix.invert: matrix does not have an inverse\n");
+ printf( "matrix does not have an inverse - none attempted\n" );
}
- return (PyObject*)self;
+ PyMem_Free( mat );
+ return EXPP_incr_ret( Py_None );
}
-//---------------------------Matrix.determinant() ----------------
-PyObject *Matrix_Determinant(MatrixObject * self)
+
+
+PyObject *Matrix_Determinant( MatrixObject * self )
{
- float det = 0.0f;
-
- if(self->rowSize != self->colSize){
- return EXPP_ReturnPyObjError(PyExc_AttributeError,
- "Matrix.determinant: only square matrices are supported\n");
- }
-
- if(self->rowSize == 2) {
- det = Det2x2(self->matrix[0][0], self->matrix[0][1],
- self->matrix[1][0], self->matrix[1][1]);
- } else if(self->rowSize == 3) {
- det = Det3x3(self->matrix[0][0], self->matrix[0][1],
- self->matrix[0][2], self->matrix[1][0],
- self->matrix[1][1], self->matrix[1][2],
- self->matrix[2][0], self->matrix[2][1],
- self->matrix[2][2]);
+ float det;
+
+ if( self->rowSize != self->colSize )
+ return EXPP_ReturnPyObjError( PyExc_AttributeError,
+ "only square matrices are supported\n" );
+
+ if( self->rowSize == 2 ) {
+ det = Det2x2( self->matrix[0][0], self->matrix[0][1],
+ self->matrix[1][0], self->matrix[1][1] );
+ } else if( self->rowSize == 3 ) {
+ det = Det3x3( self->matrix[0][0], self->matrix[0][1],
+ self->matrix[0][2], self->matrix[1][0],
+ self->matrix[1][1], self->matrix[1][2],
+ self->matrix[2][0], self->matrix[2][1],
+ self->matrix[2][2] );
+ } else if( self->rowSize == 4 ) {
+ det = Det4x4( (float ( * )[4]) *self->matrix );
} else {
- det = Det4x4((float (*)[4]) *self->matrix);
+ return EXPP_ReturnPyObjError( PyExc_StandardError,
+ "error in determinant()\n" );
}
return PyFloat_FromDouble( (double) det );
}
//---------------------------Matrix.transpose() ------------------
-PyObject *Matrix_Transpose(MatrixObject * self)
+
+PyObject *Matrix_Transpose( MatrixObject * self )
+
{
- float t = 0.0f;
+ float t;
- if(self->rowSize != self->colSize){
- return EXPP_ReturnPyObjError(PyExc_AttributeError,
- "Matrix.transpose: only square matrices are supported\n");
- }
+ if( self->rowSize != self->colSize )
+ return EXPP_ReturnPyObjError( PyExc_AttributeError,
+ "only square matrices are supported\n" );
- if(self->rowSize == 2) {
+ if( self->rowSize == 2 ) {
t = self->matrix[1][0];
self->matrix[1][0] = self->matrix[0][1];
self->matrix[0][1] = t;
- } else if(self->rowSize == 3) {
- Mat3Transp((float (*)[3])*self->matrix);
- } else {
- Mat4Transp((float (*)[4])*self->matrix);
- }
+ } else if( self->rowSize == 3 ) {
+ Mat3Transp( (float ( * )[3])*self->matrix );
+ } else if( self->rowSize == 4 ) {
+ Mat4Transp( (float ( * )[4])*self->matrix );
+ } else
+ return ( EXPP_ReturnPyObjError( PyExc_TypeError,
+ "unable to transpose matrix\n" ) );
- return (PyObject*)self;
+ return EXPP_incr_ret( Py_None );
}
-//---------------------------Matrix.zero() -----------------------
-PyObject *Matrix_Zero(MatrixObject * self)
+
+PyObject *Matrix_Zero( MatrixObject * self )
{
int row, col;
- for(row = 0; row < self->rowSize; row++) {
- for(col = 0; col < self->colSize; col++) {
+ for( row = 0; row < self->rowSize; row++ ) {
+ for( col = 0; col < self->colSize; col++ ) {
self->matrix[row][col] = 0.0f;
}
}
- return (PyObject*)self;
+ return EXPP_incr_ret( Py_None );
}
-//---------------------------Matrix.identity(() ------------------
-PyObject *Matrix_Identity(MatrixObject * self)
+
+PyObject *Matrix_Identity( MatrixObject * self )
{
- if(self->rowSize != self->colSize){
- return EXPP_ReturnPyObjError(PyExc_AttributeError,
- "Matrix.identity: only square matrices are supported\n");
- }
+ if( self->rowSize != self->colSize )
+ return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
+ "only square matrices supported\n" ) );
- if(self->rowSize == 2) {
+ if( self->rowSize == 2 ) {
self->matrix[0][0] = 1.0f;
self->matrix[0][1] = 0.0f;
self->matrix[1][0] = 0.0f;
self->matrix[1][1] = 1.0f;
- } else if(self->rowSize == 3) {
- Mat3One((float (*)[3]) *self->matrix);
- } else {
- Mat4One((float (*)[4]) *self->matrix);
- }
+ } else if( self->rowSize == 3 ) {
+ Mat3One( ( float ( * )[3] ) *self->matrix );
+ } else if( self->rowSize == 4 ) {
+ Mat4One( ( float ( * )[4] ) *self->matrix );
+ } else
+ return ( EXPP_ReturnPyObjError( PyExc_TypeError,
+ "unable to create identity matrix\n" ) );
- return (PyObject*)self;
+ return EXPP_incr_ret( Py_None );
}
-//----------------------------dealloc()(internal) ----------------
-//free the py_object
-static void Matrix_dealloc(MatrixObject * self)
+
+static void Matrix_dealloc( MatrixObject * self )
{
- Py_XDECREF(self->coerced_object);
- PyMem_Free(self->matrix);
- //only free py_data
- if(self->data.py_data){
- PyMem_Free(self->data.py_data);
- }
- PyObject_DEL(self);
+ PyMem_Free( self->contigPtr );
+ PyMem_Free( self->matrix );
+
+ PyObject_DEL( self );
}
-//----------------------------getattr()(internal) ----------------
-//object.attribute access (get)
-static PyObject *Matrix_getattr(MatrixObject * self, char *name)
+
+static PyObject *Matrix_getattr( MatrixObject * self, char *name )
{
- if(STREQ(name, "rowSize")) {
- return PyInt_FromLong((long) self->rowSize);
- } else if(STREQ(name, "colSize")) {
- return PyInt_FromLong((long) self->colSize);
+ if( strcmp( name, "rowSize" ) == 0 ) {
+ return PyInt_FromLong( ( long ) self->rowSize );
+ } else if( strcmp( name, "colSize" ) == 0 ) {
+ return PyInt_FromLong( ( long ) self->colSize );
}
- return Py_FindMethod(Matrix_methods, (PyObject *) self, name);
+ return Py_FindMethod( Matrix_methods, ( PyObject * ) self, name );
}
-//----------------------------setattr()(internal) ----------------
-//object.attribute access (set)
-static int Matrix_setattr(MatrixObject * self, char *name, PyObject * v)
+
+static int Matrix_setattr( MatrixObject * self, char *name, PyObject * v )
{
/* This is not supported. */
- return (-1);
+ return ( -1 );
}
-//----------------------------print object (internal)-------------
-//print the object to screen
-static PyObject *Matrix_repr(MatrixObject * self)
+
+static PyObject *Matrix_repr( MatrixObject * self )
{
+ PyObject *repr, *str;
int x, y;
- char buffer[48], str[1024];
-
- BLI_strncpy(str,"",1024);
- for(x = 0; x < self->rowSize; x++){
- sprintf(buffer, "[", x);
- strcat(str,buffer);
- for(y = 0; y < (self->colSize - 1); y++) {
- sprintf(buffer, "%.6f, ", self->matrix[x][y]);
- strcat(str,buffer);
- }
- if(x < (self->rowSize-1)){
- sprintf(buffer, "%.6f](matrix [row %d])\n", self->matrix[x][y], x);
- strcat(str,buffer);
- }else{
- sprintf(buffer, "%.6f](matrix [row %d])", self->matrix[x][y], x);
- strcat(str,buffer);
+ char ftoa[24];
+
+ repr = PyString_FromString( "" );
+ if( !repr )
+ return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
+ "Attribute error in PyMatrix (repr)\n" ) );
+
+ for( x = 0; x < self->rowSize; x++ ) {
+ str = PyString_FromString( "[" );
+ PyString_ConcatAndDel( &repr, str );
+
+ for( y = 0; y < ( self->colSize - 1 ); y++ ) {
+ sprintf( ftoa, "%.4f, ", self->matrix[x][y] );
+ str = PyString_FromString( ftoa );
+ PyString_ConcatAndDel( &repr, str );
}
+ sprintf( ftoa, "%.4f]\n", self->matrix[x][y] );
+ str = PyString_FromString( ftoa );
+ PyString_ConcatAndDel( &repr, str );
}
-
- return EXPP_incr_ret(PyString_FromString(str));
+ return repr;
}
-//---------------------SEQUENCE PROTOCOLS------------------------
-//----------------------------len(object)------------------------
-//sequence length
-static int Matrix_len(MatrixObject * self)
-{
- return (self->colSize * self->rowSize);
-}
-//----------------------------object[]---------------------------
-//sequence accessor (get)
-//the wrapped vector gives direct access to the matrix data
-static PyObject *Matrix_item(MatrixObject * self, int i)
+//no support for matrix[x][y] so have to return by sequence index
+//will return a row from the matrix to support previous API
+//compatability
+static PyObject *Matrix_item( MatrixObject * self, int i )
{
- if(i < 0 || i >= self->rowSize)
- return EXPP_ReturnPyObjError(PyExc_IndexError,
- "matrix[attribute]: array index out of range\n");
+ float *vec = NULL;
+ PyObject *retval;
+ int x;
+
+ if( i < 0 || i >= self->rowSize )
+ return EXPP_ReturnPyObjError( PyExc_IndexError,
+ "matrix row index out of range\n" );
+
+ vec = PyMem_Malloc( self->colSize * sizeof( float ) );
+ if( vec == NULL ) {
+ return ( EXPP_ReturnPyObjError( PyExc_MemoryError,
+ "problem allocating vec\n\n" ) );
+ }
+ for( x = 0; x < self->colSize; x++ ) {
+ vec[x] = self->matrix[i][x];
+ }
- return newVectorObject(self->matrix[i], self->colSize, Py_WRAP);
+ retval =( PyObject * ) newVectorObject( vec, self->colSize );
+ PyMem_Free( vec );
+ return retval;
}
-//----------------------------object[]-------------------------
-//sequence accessor (set)
-static int Matrix_ass_item(MatrixObject * self, int i, PyObject * ob)
+
+static PyObject *Matrix_slice( MatrixObject * self, int begin, int end )
{
- int y, x, size = 0;
- float vec[4];
+ PyObject *list;
+ int count, maxsize, x, y;
- if(i > self->rowSize || i < 0){
- return EXPP_ReturnIntError(PyExc_TypeError,
- "matrix[attribute] = x: bad row\n");
- }
+ maxsize = self->colSize * self->rowSize;
+ if( begin < 0 )
+ begin = 0;
+ if( end > maxsize )
+ end = maxsize;
+ if( begin > end )
+ begin = end;
- if(PySequence_Check(ob)){
- size = PySequence_Length(ob);
- if(size != self->colSize){
- return EXPP_ReturnIntError(PyExc_TypeError,
- "matrix[attribute] = x: bad sequence size\n");
- }
- for (x = 0; x < size; x++) {
- PyObject *m, *f;
+ list = PyList_New( end - begin );
- m = PySequence_GetItem(ob, x);
- if (m == NULL) { // Failed to read sequence
- return EXPP_ReturnIntError(PyExc_RuntimeError,
- "matrix[attribute] = x: unable to read sequence\n");
- }
- f = PyNumber_Float(m);
- if(f == NULL) { // parsed item not a number
- Py_DECREF(m);
- return EXPP_ReturnIntError(PyExc_TypeError,
- "matrix[attribute] = x: sequence argument not a number\n");
- }
- vec[x] = PyFloat_AS_DOUBLE(f);
- EXPP_decr2(m, f);
- }
- //parsed well - now set in matrix
- for(y = 0; y < size; y++){
- self->matrix[i][y] = vec[y];
- }
- return 0;
- }else{
- return EXPP_ReturnIntError(PyExc_TypeError,
- "matrix[attribute] = x: expects a sequence of column size\n");
+ for( count = begin; count < end; count++ ) {
+ x = ( int ) floor( ( double ) ( count / self->colSize ) );
+ y = count % self->colSize;
+ PyList_SetItem( list, count - begin,
+ PyFloat_FromDouble( self->matrix[x][y] ) );
}
+
+ return list;
}
-//----------------------------object[z:y]------------------------
-//sequence slice (get)
-static PyObject *Matrix_slice(MatrixObject * self, int begin, int end)
-{
- PyObject *list = NULL;
- int count;
+static int Matrix_ass_item( MatrixObject * self, int i, PyObject * ob )
+{
+ int maxsize, x, y;
- CLAMP(begin, 0, self->rowSize);
- CLAMP(end, 0, self->rowSize);
- begin = MIN2(begin,end);
+ maxsize = self->colSize * self->rowSize;
+ if( i < 0 || i >= maxsize )
+ return EXPP_ReturnIntError( PyExc_IndexError,
+ "array assignment index out of range\n" );
+ if( !PyInt_Check( ob ) && !PyFloat_Check( ob ) )
+ return EXPP_ReturnIntError( PyExc_IndexError,
+ "matrix member must be a number\n" );
- list = PyList_New(end - begin);
- for(count = begin; count < end; count++) {
- PyList_SetItem(list, count - begin,
- newVectorObject(self->matrix[count], self->colSize, Py_WRAP));
- }
+ x = ( int ) floor( ( double ) ( i / self->colSize ) );
+ y = i % self->colSize;
+ self->matrix[x][y] = ( float ) PyFloat_AsDouble( ob );
- return EXPP_incr_ret(list);
+ return 0;
}
-//----------------------------object[z:y]------------------------
-//sequence slice (set)
-static int Matrix_ass_slice(MatrixObject * self, int begin, int end,
- PyObject * seq)
+
+static int Matrix_ass_slice( MatrixObject * self, int begin, int end,
+ PyObject * seq )
{
- int i, x, y, size, sub_size;
- float mat[16];
-
- CLAMP(begin, 0, self->rowSize);
- CLAMP(end, 0, self->rowSize);
- begin = MIN2(begin,end);
-
- if(PySequence_Check(seq)){
- size = PySequence_Length(seq);
- if(size != (end - begin)){
- return EXPP_ReturnIntError(PyExc_TypeError,
- "matrix[begin:end] = []: size mismatch in slice assignment\n");
- }
- //parse sub items
- for (i = 0; i < size; i++) {
- //parse each sub sequence
- PyObject *subseq;
- subseq = PySequence_GetItem(seq, i);
- if (subseq == NULL) { // Failed to read sequence
- return EXPP_ReturnIntError(PyExc_RuntimeError,
- "matrix[begin:end] = []: unable to read sequence\n");
- }
- if(PySequence_Check(subseq)){
- //subsequence is also a sequence
- sub_size = PySequence_Length(subseq);
- if(sub_size != self->colSize){
- return EXPP_ReturnIntError(PyExc_TypeError,
- "matrix[begin:end] = []: size mismatch in slice assignment\n");
- }
- for (y = 0; y < sub_size; y++) {
- PyObject *m, *f;
- m = PySequence_GetItem(subseq, y);
- if (m == NULL) { // Failed to read sequence
- return EXPP_ReturnIntError(PyExc_RuntimeError,
- "matrix[begin:end] = []: unable to read sequence\n");
- }
- f = PyNumber_Float(m);
- if(f == NULL) { // parsed item not a number
- Py_DECREF(m);
- return EXPP_ReturnIntError(PyExc_TypeError,
- "matrix[begin:end] = []: sequence argument not a number\n");
- }
- mat[(i * self->colSize) + y] = PyFloat_AS_DOUBLE(f);
- EXPP_decr2(f, m);
- }
- }else{
- Py_DECREF(subseq);
- return EXPP_ReturnIntError(PyExc_TypeError,
- "matrix[begin:end] = []: illegal argument type for built-in operation\n");
- }
- }
- //parsed well - now set in matrix
- for(x = 0; x < (size * sub_size); x++){
- self->matrix[begin + (int)floor(x / self->colSize)][x % self->colSize] = mat[x];
+ int count, maxsize, x, y, z;
+
+ maxsize = self->colSize * self->rowSize;
+ if( begin < 0 )
+ begin = 0;
+ if( end > maxsize )
+ end = maxsize;
+ 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" );
+
+ x = ( int ) floor( ( double ) ( count / self->colSize ) );
+ y = count % self->colSize;
+ if( !PyArg_Parse( ob, "f", &self->matrix[x][y] ) ) {
+ Py_DECREF( ob );
+ return -1;
}
- return 0;
- }else{
- return EXPP_ReturnIntError(PyExc_TypeError,
- "matrix[begin:end] = []: illegal argument type for built-in operation\n");
}
+ return 0;
}
-//------------------------NUMERIC PROTOCOLS----------------------
-//------------------------obj + obj------------------------------
-static PyObject *Matrix_add(PyObject * m1, PyObject * m2)
+
+static int Matrix_len( MatrixObject * self )
{
- int x, y;
- float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
- MatrixObject *mat1 = NULL, *mat2 = NULL;
+ return ( self->colSize * self->rowSize );
+}
- EXPP_incr2(m1, m2);
- mat1 = (MatrixObject*)m1;
- mat2 = (MatrixObject*)m2;
+static PyObject *Matrix_add( PyObject * m1, PyObject * m2 )
+{
+ float *mat;
+ int matSize, rowSize, colSize, x, y;
- if(mat1->coerced_object || mat2->coerced_object){
- return EXPP_ReturnPyObjError(PyExc_AttributeError,
- "Matrix addition: arguments not valid for this operation....\n");
- }
- if(mat1->rowSize != mat2->rowSize || mat1->colSize != mat2->colSize){
- EXPP_decr2((PyObject*)mat1, (PyObject*)mat2);
- return EXPP_ReturnPyObjError(PyExc_AttributeError,
- "Matrix addition: matrices must have the same dimensions for this operation\n");
- }
+ if( ( !Matrix_CheckPyObject( m1 ) )
+ || ( !Matrix_CheckPyObject( m2 ) ) )
+ return EXPP_ReturnPyObjError( PyExc_TypeError,
+ "unsupported type for this operation\n" );
+
+ if( ( ( MatrixObject * ) m1 )->flag > 0
+ || ( ( MatrixObject * ) m2 )->flag > 0 )
+ return EXPP_ReturnPyObjError( PyExc_ArithmeticError,
+ "cannot add scalar to a matrix\n" );
- for(x = 0; x < mat1->rowSize; x++) {
- for(y = 0; y < mat1->colSize; y++) {
- mat[((x * mat1->colSize) + y)] = mat1->matrix[x][y] + mat2->matrix[x][y];
+ if( ( ( MatrixObject * ) m1 )->rowSize !=
+ ( ( MatrixObject * ) m2 )->rowSize
+ || ( ( MatrixObject * ) m1 )->colSize !=
+ ( ( MatrixObject * ) m2 )->colSize )
+ return EXPP_ReturnPyObjError( PyExc_AttributeError,
+ "matrices must be the same same for this operation\n" );
+
+ rowSize = ( ( ( MatrixObject * ) m1 )->rowSize );
+ colSize = ( ( ( MatrixObject * ) m1 )->colSize );
+ matSize = rowSize * colSize;
+
+ mat = PyMem_Malloc( matSize * sizeof( float ) );
+ if( mat == NULL ) {
+ return ( EXPP_ReturnPyObjError( PyExc_MemoryError,
+ "problem allocating mat\n\n" ) );
+ }
+ for( x = 0; x < rowSize; x++ ) {
+ for( y = 0; y < colSize; y++ ) {
+ mat[( ( x * rowSize ) + y )] =
+ ( ( MatrixObject * ) m1 )->matrix[x][y] +
+ ( ( MatrixObject * ) m2 )->matrix[x][y];
}
}
- EXPP_decr2((PyObject*)mat1, (PyObject*)mat2);
- return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW);
+ return newMatrixObject( mat, rowSize, colSize );
}
-//------------------------obj - obj------------------------------
-//subtraction
-static PyObject *Matrix_sub(PyObject * m1, PyObject * m2)
+
+static PyObject *Matrix_sub( PyObject * m1, PyObject * m2 )
{
- int x, y;
- float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
- MatrixObject *mat1 = NULL, *mat2 = NULL;
+ float *mat;
+ int matSize, rowSize, colSize, x, y;
- EXPP_incr2(m1, m2);
- mat1 = (MatrixObject*)m1;
- mat2 = (MatrixObject*)m2;
+ if( ( !Matrix_CheckPyObject( m1 ) )
+ || ( !Matrix_CheckPyObject( m2 ) ) )
+ return EXPP_ReturnPyObjError( PyExc_TypeError,
+ "unsupported type for this operation\n" );
- if(mat1->coerced_object || mat2->coerced_object){
- return EXPP_ReturnPyObjError(PyExc_AttributeError,
- "Matrix addition: arguments not valid for this operation....\n");
- }
- if(mat1->rowSize != mat2->rowSize || mat1->colSize != mat2->colSize){
- EXPP_decr2((PyObject*)mat1, (PyObject*)mat2);
- return EXPP_ReturnPyObjError(PyExc_AttributeError,
- "Matrix addition: matrices must have the same dimensions for this operation\n");
- }
+ if( ( ( MatrixObject * ) m1 )->flag > 0
+ || ( ( MatrixObject * ) m2 )->flag > 0 )
+ return EXPP_ReturnPyObjError( PyExc_ArithmeticError,
+ "cannot subtract a scalar from a matrix\n" );
+
+ if( ( ( MatrixObject * ) m1 )->rowSize !=
+ ( ( MatrixObject * ) m2 )->rowSize
+ || ( ( MatrixObject * ) m1 )->colSize !=
+ ( ( MatrixObject * ) m2 )->colSize )
+ return EXPP_ReturnPyObjError( PyExc_AttributeError,
+ "matrices must be the same same for this operation\n" );
+
+ rowSize = ( ( ( MatrixObject * ) m1 )->rowSize );
+ colSize = ( ( ( MatrixObject * ) m1 )->colSize );
+ matSize = rowSize * colSize;
- for(x = 0; x < mat1->rowSize; x++) {
- for(y = 0; y < mat1->colSize; y++) {
- mat[((x * mat1->colSize) + y)] = mat1->matrix[x][y] - mat2->matrix[x][y];
+ mat = PyMem_Malloc( matSize * sizeof( float ) );
+ if( mat == NULL ) {
+ return ( EXPP_ReturnPyObjError( PyExc_MemoryError,
+ "problem allocating mat\n\n" ) );
+ }
+ for( x = 0; x < rowSize; x++ ) {
+ for( y = 0; y < colSize; y++ ) {
+ mat[( ( x * rowSize ) + y )] =
+ ( ( MatrixObject * ) m1 )->matrix[x][y] -
+ ( ( MatrixObject * ) m2 )->matrix[x][y];
}
}
- EXPP_decr2((PyObject*)mat1, (PyObject*)mat2);
- return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW);
+ return newMatrixObject( mat, rowSize, colSize );
}
-//------------------------obj * obj------------------------------
-//mulplication
-static PyObject *Matrix_mul(PyObject * m1, PyObject * m2)
+
+static PyObject *Matrix_mul( PyObject * m1, PyObject * m2 )
{
- int x, y, z;
- float scalar;
- float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
- double dot = 0.0f;
- MatrixObject *mat1 = NULL, *mat2 = NULL;
- PyObject *f = NULL, *retObj = NULL;
- VectorObject *vec = NULL;
-
- EXPP_incr2(m1, m2);
- mat1 = (MatrixObject*)m1;
- mat2 = (MatrixObject*)m2;
-
- if(mat1->coerced_object){
- if (PyFloat_Check(mat1->coerced_object) ||
- PyInt_Check(mat1->coerced_object)){ // FLOAT/INT * MATRIX
- f = PyNumber_Float(mat1->coerced_object);
- if(f == NULL) { // parsed item not a number
- EXPP_decr2((PyObject*)mat1, (PyObject*)mat2);
- return EXPP_ReturnPyObjError(PyExc_TypeError,
- "Matrix multiplication: arguments not acceptable for this operation\n");
- }
- scalar = PyFloat_AS_DOUBLE(f);
- for(x = 0; x < mat2->rowSize; x++) {
- for(y = 0; y < mat2->colSize; y++) {
- mat[((x * mat2->colSize) + y)] = scalar * mat2->matrix[x][y];
- }
- }
- EXPP_decr2((PyObject*)mat1, (PyObject*)mat2);
- return newMatrixObject(mat, mat2->rowSize, mat2->colSize, Py_NEW);
+ PyObject *retval;
+ int matSizeV, rowSizeV, colSizeV, rowSizeW, colSizeW, matSizeW, x, y,z;
+ MatrixObject *matV;
+ MatrixObject *matW;
+ float *mat = NULL;
+ float dot = 0;
+
+
+ if( ( !Matrix_CheckPyObject( m1 ) )
+ || ( !Matrix_CheckPyObject( m2 ) ) )
+ return EXPP_ReturnPyObjError( PyExc_TypeError,
+ "unsupported type for this operation\n" );
+
+ //get some vars
+ rowSizeV = ( ( ( MatrixObject * ) m1 )->rowSize );
+ colSizeV = ( ( ( MatrixObject * ) m1 )->colSize );
+ matSizeV = rowSizeV * colSizeV;
+ rowSizeW = ( ( ( MatrixObject * ) m2 )->rowSize );
+ colSizeW = ( ( ( MatrixObject * ) m2 )->colSize );
+ matSizeW = rowSizeW * colSizeW;
+ matV = ( ( MatrixObject * ) m1 );
+ matW = ( ( MatrixObject * ) m2 );
+
+ //coerced int or float for scalar multiplication
+ if( matW->flag > 1 || matW->flag > 2 ) {
+
+ if( rowSizeV != rowSizeW && colSizeV != colSizeW )
+ return EXPP_ReturnPyObjError( PyExc_AttributeError,
+ "Matrix dimension error during scalar multiplication\n" );
+
+ mat = PyMem_Malloc( matSizeV * sizeof( float ) );
+ if( mat == NULL ) {
+ return ( EXPP_ReturnPyObjError( PyExc_MemoryError,
+ "problem allocating mat\n\n" ) );
}
- }else{
- if(mat2->coerced_object){
- if(VectorObject_Check(mat2->coerced_object)){ //MATRIX * VECTOR
- vec = (VectorObject*)EXPP_incr_ret(mat2->coerced_object);
- retObj = column_vector_multiplication(mat1, vec);
- EXPP_decr3((PyObject*)mat1, (PyObject*)mat2, (PyObject*)vec);
- return retObj;
- }else if (PyFloat_Check(mat2->coerced_object) ||
- PyInt_Check(mat2->coerced_object)){ // MATRIX * FLOAT/INT
- f = PyNumber_Float(mat2->coerced_object);
- if(f == NULL) { // parsed item not a number
- EXPP_decr2((PyObject*)mat1, (PyObject*)mat2);
- return EXPP_ReturnPyObjError(PyExc_TypeError,
- "Matrix multiplication: arguments not acceptable for this operation\n");
- }
- scalar = PyFloat_AS_DOUBLE(f);
- for(x = 0; x < mat1->rowSize; x++) {
- for(y = 0; y < mat1->colSize; y++) {
- mat[((x * mat1->colSize) + y)] = scalar * mat1->matrix[x][y];
- }
- }
- EXPP_decr2((PyObject*)mat1, (PyObject*)mat2);
- return newMatrixObject(mat, mat1->rowSize, mat1->colSize, Py_NEW);
- }
- }else{ //MATRIX * MATRIX
- if(mat1->colSize != mat2->rowSize){
- EXPP_decr2((PyObject*)mat1, (PyObject*)mat2);
- return EXPP_ReturnPyObjError(PyExc_AttributeError,
- "Matrix multiplication: matrix A rowsize must equal matrix B colsize\n");
+ for( x = 0; x < rowSizeV; x++ ) {
+ for( y = 0; y < colSizeV; y++ ) {
+ mat[( ( x * rowSizeV ) + y )] =
+ matV->matrix[x][y] *
+ matW->matrix[x][y];
}
- for(x = 0; x < mat1->rowSize; x++) {
- for(y = 0; y < mat2->colSize; y++) {
- for(z = 0; z < mat1->colSize; z++) {
- dot += (mat1->matrix[x][z] * mat2->matrix[z][y]);
- }
- mat[((x * mat1->rowSize) + y)] = dot;
- dot = 0.0f;
+ }
+ retval = ( PyObject* ) newMatrixObject( mat, rowSizeV, colSizeV );
+ PyMem_Free( mat );
+ return retval;
+ } else if( matW->flag == 0 && matV->flag == 0 ) { //true matrix multiplication
+ if( colSizeV != rowSizeW ) {
+ return EXPP_ReturnPyObjError( PyExc_AttributeError,
+ "Matrix multiplication undefined...\n" );
+ }
+
+ mat = PyMem_Malloc( ( rowSizeV * colSizeW ) *
+ sizeof( float ) );
+ if( mat == NULL ) {
+ return ( EXPP_ReturnPyObjError( PyExc_MemoryError,
+ "problem allocating mat\n\n" ) );
+ }
+ for( x = 0; x < rowSizeV; x++ ) {
+ for( y = 0; y < colSizeW; y++ ) {
+ for( z = 0; z < colSizeV; z++ ) {
+ dot += ( matV->matrix[x][z] *
+ matW->matrix[z][y] );
}
+ mat[( ( x * rowSizeV ) + y )] = dot;
+ dot = 0;
}
- return newMatrixObject(mat, mat1->rowSize, mat2->colSize, Py_NEW);
}
- }
-
- EXPP_decr2((PyObject*)mat1, (PyObject*)mat2);
- return EXPP_ReturnPyObjError(PyExc_TypeError,
- "Matrix multiplication: arguments not acceptable for this operation\n");
+ retval = ( PyObject* ) newMatrixObject( mat, rowSizeV, colSizeW );
+ PyMem_Free( mat );
+ return retval;
+ } else
+ return EXPP_ReturnPyObjError( PyExc_AttributeError,
+ "Error in matrix_mul...\n" );
}
-//------------------------coerce(obj, obj)-----------------------
+
//coercion of unknown types to type MatrixObject for numeric protocols
-/*Coercion() is called whenever a math operation has 2 operands that
- it doesn't understand how to evaluate. 2+Matrix for example. We want to
- evaluate some of these operations like: (vector * 2), however, for math
- to proceed, the unknown operand must be cast to a type that python math will
- understand. (e.g. in the case above case, 2 must be cast to a vector and
- then call vector.multiply(vector, scalar_cast_as_vector)*/
-static int Matrix_coerce(PyObject ** m1, PyObject ** m2)
+static int Matrix_coerce( PyObject ** m1, PyObject ** m2 )
{
- int x;
- float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
- PyObject *coerced = NULL;
-
- if(!MatrixObject_Check(*m2)) {
- if(VectorObject_Check(*m2) || PyFloat_Check(*m2) || PyInt_Check(*m2)) {
- coerced = EXPP_incr_ret(*m2);
- *m2 = newMatrixObject(NULL,3,3,Py_NEW);
- ((MatrixObject*)*m2)->coerced_object = coerced;
- }else{
- return EXPP_ReturnIntError(PyExc_TypeError,
- "matrix.coerce(): unknown operand - can't coerce for numeric protocols\n");
+ long *tempI;
+ double *tempF;
+ float *mat;
+ int x, matSize;
+
+ matSize =
+ ( ( ( MatrixObject * ) * m1 )->rowSize ) *
+ ( ( ( MatrixObject * ) * m1 )->rowSize );
+ if( Matrix_CheckPyObject( *m1 ) ) {
+ if( Matrix_CheckPyObject( *m2 ) ) { //matrix & matrix
+ Py_INCREF( *m1 );
+ Py_INCREF( *m2 );
+ return 0;
+ } else {
+ if( VectorObject_Check( *m2 ) ) { //matrix & vector?
+ printf( "use MatMultVec() for column vector multiplication\n" );
+ Py_INCREF( *m1 );
+ return 0;
+ } else if( PyNumber_Check( *m2 ) ) { //& scalar?
+ if( PyInt_Check( *m2 ) ) { //it's a int
+ tempI = PyMem_Malloc( 1 *
+ sizeof( long ) );
+ if( tempI == NULL ) {
+ return ( EXPP_ReturnIntError
+ ( PyExc_MemoryError,
+ "problem allocating tempI\n\n" ) );
+ }
+ *tempI = PyInt_AsLong( *m2 );
+ mat = PyMem_Malloc( matSize *
+ sizeof( float ) );
+ if( mat == NULL ) {
+ PyMem_Free( tempI );
+ return ( EXPP_ReturnIntError
+ ( PyExc_MemoryError,
+ "problem allocating mat\n\n" ) );
+ }
+ for( x = 0; x < matSize; x++ ) {
+ mat[x] = ( float ) *tempI;
+ }
+ PyMem_Free( tempI );
+ *m2 = newMatrixObject( mat,
+ ( ( ( MatrixObject * ) * m1 )->rowSize ), ( ( ( MatrixObject * ) * m1 )->colSize ) );
+ ( ( MatrixObject * ) * m2 )->flag = 1; //int coercion
+ PyMem_Free( mat );
+ Py_INCREF( *m1 );
+ return 0;
+ } else if( PyFloat_Check( *m2 ) ) { //it's a float
+ tempF = PyMem_Malloc( 1 *
+ sizeof
+ ( double ) );
+ if( tempF == NULL ) {
+ return ( EXPP_ReturnIntError
+ ( PyExc_MemoryError,
+ "problem allocating tempF\n\n" ) );
+ }
+ *tempF = PyFloat_AsDouble( *m2 );
+ mat = PyMem_Malloc( matSize *
+ sizeof( float ) );
+ if( mat == NULL ) {
+ PyMem_Free( tempF );
+ return ( EXPP_ReturnIntError
+ ( PyExc_MemoryError,
+ "problem allocating mat\n\n" ) );
+ }
+ for( x = 0; x < matSize; x++ ) {
+ mat[x] = ( float ) *tempF;
+ }
+ PyMem_Free( tempF );
+ *m2 = newMatrixObject( mat,
+ ( ( ( MatrixObject * ) * m1 )->rowSize ), ( ( ( MatrixObject * ) * m1 )->colSize ) );
+ ( ( MatrixObject * ) * m2 )->flag = 2; //float coercion
+ PyMem_Free( mat );
+ Py_INCREF( *m1 );
+ return 0;
+ }
+ }
+ //unknom2n type or numeric cast failure
+ printf( "attempting matrix operation m2ith unsupported type...\n" );
+ Py_INCREF( *m1 );
+ return 0; //operation m2ill type check
}
+ } else {
+ //1st not Matrix
+ printf( "numeric protocol failure...\n" );
+ return -1; //this should not occur - fail
}
- Py_INCREF(*m2);
- Py_INCREF(*m1);
- return 0;
+ return -1;
}
-//-----------------PROTCOL DECLARATIONS--------------------------
+
+//******************************************************************
+// Matrix definition
+//******************************************************************
static PySequenceMethods Matrix_SeqMethods = {
- (inquiry) Matrix_len, /* sq_length */
- (binaryfunc) 0, /* sq_concat */
- (intargfunc) 0, /* sq_repeat */
- (intargfunc) Matrix_item, /* sq_item */
- (intintargfunc) Matrix_slice, /* sq_slice */
- (intobjargproc) Matrix_ass_item, /* sq_ass_item */
- (intintobjargproc) Matrix_ass_slice, /* sq_ass_slice */
+ ( inquiry ) Matrix_len, /* sq_length */
+ ( binaryfunc ) 0, /* sq_concat */
+ ( intargfunc ) 0, /* sq_repeat */
+ ( intargfunc ) Matrix_item, /* sq_item */
+ ( intintargfunc ) Matrix_slice, /* sq_slice */
+ ( intobjargproc ) Matrix_ass_item, /* sq_ass_item */
+ ( intintobjargproc ) Matrix_ass_slice, /* sq_ass_slice */
};
+
static PyNumberMethods Matrix_NumMethods = {
- (binaryfunc) Matrix_add, /* __add__ */
- (binaryfunc) Matrix_sub, /* __sub__ */
- (binaryfunc) Matrix_mul, /* __mul__ */
- (binaryfunc) 0, /* __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) Matrix_coerce, /* __coerce__ */
- (unaryfunc) 0, /* __int__ */
- (unaryfunc) 0, /* __long__ */
- (unaryfunc) 0, /* __float__ */
- (unaryfunc) 0, /* __oct__ */
- (unaryfunc) 0, /* __hex__ */
+ ( binaryfunc ) Matrix_add, /* __add__ */
+ ( binaryfunc ) Matrix_sub, /* __sub__ */
+ ( binaryfunc ) Matrix_mul, /* __mul__ */
+ ( binaryfunc ) 0, /* __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 ) Matrix_coerce, /* __coerce__ */
+ ( unaryfunc ) 0, /* __int__ */
+ ( unaryfunc ) 0, /* __long__ */
+ ( unaryfunc ) 0, /* __float__ */
+ ( unaryfunc ) 0, /* __oct__ */
+ ( unaryfunc ) 0, /* __hex__ */
};
-//------------------PY_OBECT DEFINITION--------------------------
+
PyTypeObject matrix_Type = {
- PyObject_HEAD_INIT(NULL) /* required python macro */
- 0, /*ob_size */
- "Matrix", /*tp_name */
- sizeof(MatrixObject), /*tp_basicsize */
- 0, /*tp_itemsize */
- (destructor) Matrix_dealloc, /*tp_dealloc */
- (printfunc) 0, /*tp_print */
- (getattrfunc) Matrix_getattr, /*tp_getattr */
- (setattrfunc) Matrix_setattr, /*tp_setattr */
- 0, /*tp_compare */
- (reprfunc) Matrix_repr, /*tp_repr */
- &Matrix_NumMethods, /*tp_as_number */
- &Matrix_SeqMethods, /*tp_as_sequence */
+ PyObject_HEAD_INIT( NULL ) /* required python macro */
+ 0, /*ob_size */
+ "Matrix", /*tp_name */
+ sizeof( MatrixObject ), /*tp_basicsize */
+ 0, /*tp_itemsize */
+ ( destructor ) Matrix_dealloc, /*tp_dealloc */
+ ( printfunc ) 0, /*tp_print */
+ ( getattrfunc ) Matrix_getattr, /*tp_getattr */
+ ( setattrfunc ) Matrix_setattr, /*tp_setattr */
+ 0, /*tp_compare */
+ ( reprfunc ) Matrix_repr, /*tp_repr */
+ &Matrix_NumMethods, /*tp_as_number */
+ &Matrix_SeqMethods, /*tp_as_sequence */
};
-//------------------------newMatrixObject (internal)-------------
-//creates a new matrix object
-//self->matrix self->contiguous_ptr (reference to data.xxx)
-// [0]------------->[0]
-// [1]
-// [2]
-// [1]------------->[3]
-// [4]
-// [5]
-// ....
-//self->matrix[1][1] = self->contiguous_ptr[4] = self->data.xxx_data[4]
-/*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
- (i.e. it was allocated elsewhere by MEM_mallocN())
- pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
- (i.e. it must be created here with PyMEM_malloc())*/
-PyObject *newMatrixObject(float *mat, int rowSize, int colSize, int type)
+
+//******************************************************************
+//Function: newMatrixObject
+//******************************************************************
+PyObject *newMatrixObject( float *mat, int rowSize, int colSize )
{
MatrixObject *self;
- int x, row, col;
+ int row, col, x;
- //matrix objects can be any 2-4row x 2-4col matrix
- if(rowSize < 2 || rowSize > 4 || colSize < 2 || colSize > 4){
- return EXPP_ReturnPyObjError(PyExc_RuntimeError,
- "matrix(): row and column sizes must be between 2 and 4\n");
+ if( rowSize < 2 || rowSize > 4 || colSize < 2 || colSize > 4 )
+ return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
+ "row and column sizes must be between 2 and 4\n" ) );
+
+ self = PyObject_NEW( MatrixObject, &matrix_Type );
+
+ //generate contigous memory space
+ self->contigPtr = PyMem_Malloc( rowSize * colSize * sizeof( float ) );
+ if( self->contigPtr == NULL ) {
+ return ( EXPP_ReturnPyObjError( PyExc_MemoryError,
+ "problem allocating array space\n\n" ) );
+ }
+ //create pointer array
+ self->matrix = PyMem_Malloc( rowSize * sizeof( float * ) );
+ if( self->matrix == NULL ) {
+ PyMem_Free( self->contigPtr );
+ return ( EXPP_ReturnPyObjError( PyExc_MemoryError,
+ "problem allocating pointer space\n\n" ) );
+ }
+ //pointer array points to contigous memory
+ for( x = 0; x < rowSize; x++ ) {
+ self->matrix[x] = self->contigPtr + ( x * colSize );
}
- matrix_Type.ob_type = &PyType_Type;
- self = PyObject_NEW(MatrixObject, &matrix_Type);
- self->data.blend_data = NULL;
- self->data.py_data = NULL;
- self->rowSize = rowSize;
- self->colSize = colSize;
- self->coerced_object = NULL;
-
- if(type == Py_WRAP){
- self->data.blend_data = mat;
- self->contigPtr = self->data.blend_data;
- //create pointer array
- self->matrix = PyMem_Malloc(rowSize * sizeof(float *));
- if(self->matrix == NULL) { //allocation failure
- return EXPP_ReturnPyObjError( PyExc_MemoryError,
- "matrix(): problem allocating pointer space\n");
- }
- //pointer array points to contigous memory
- for(x = 0; x < rowSize; x++) {
- self->matrix[x] = self->contigPtr + (x * colSize);
- }
- }else if (type == Py_NEW){
- self->data.py_data = PyMem_Malloc(rowSize * colSize * sizeof(float));
- if(self->data.py_data == NULL) { //allocation failure
- return EXPP_ReturnPyObjError( PyExc_MemoryError,
- "matrix(): problem allocating pointer space\n");
- }
- self->contigPtr = self->data.py_data;
- //create pointer array
- self->matrix = PyMem_Malloc(rowSize * sizeof(float *));
- if(self->matrix == NULL) { //allocation failure
- PyMem_Free(self->data.py_data);
- return EXPP_ReturnPyObjError( PyExc_MemoryError,
- "matrix(): problem allocating pointer space\n");
- }
- //pointer array points to contigous memory
- for(x = 0; x < rowSize; x++) {
- self->matrix[x] = self->contigPtr + (x * colSize);
+ if( mat ) { //if a float array passed
+ for( row = 0; row < rowSize; row++ ) {
+ for( col = 0; col < colSize; col++ ) {
+ self->matrix[row][col] =
+ mat[( row * colSize ) + col];
+ }
}
- //parse
- if(mat) { //if a float array passed
- for(row = 0; row < rowSize; row++) {
- for(col = 0; col < colSize; col++) {
- self->matrix[row][col] = mat[(row * colSize) + col];
- }
+ } else { //or if NULL passed
+ for( row = 0; row < rowSize; row++ ) {
+ for( col = 0; col < colSize; col++ ) {
+ self->matrix[row][col] = 0.0f;
}
- } else { //or if no arguments are passed return identity matrix
- Matrix_Identity(self);
}
- }else{ //bad type
- return NULL;
}
- return (PyObject *) EXPP_incr_ret((PyObject *)self);
+
+ //set size vars of matrix
+ self->rowSize = rowSize;
+ self->colSize = colSize;
+
+ //set coercion flag
+ self->flag = 0;
+
+ return ( ( PyObject * ) self );
}