Page Menu
Home
Search
Configure Global Search
Log In
Files
F19700
matrix_indexing.patch
Public
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Authored By
Andrew Hale (trumanblending)
Nov 13 2013, 4:19 PM
Size
10 KB
Subscribers
None
matrix_indexing.patch
View Options
Index: mathutils_Matrix.c
===================================================================
--- mathutils_Matrix.c (revision 42488)
+++ mathutils_Matrix.c (working copy)
@@ -52,28 +52,38 @@
static int mathutils_matrix_vector_get(BaseMathObject *bmo, int subtype)
{
MatrixObject *self= (MatrixObject *)bmo->cb_user;
- int i;
+ int col;
if (BaseMath_ReadCallback(self) == -1)
return -1;
- for (i=0; i < self->col_size; i++)
- bmo->data[i]= self->matrix[subtype][i];
+ /* Note that the normal math representation of the matrix is the transpose of
+ the internal representation. Hence, subtype indexes the row.*/
+ /* Loop over each column in the matrix and get the element indexed by subtype.
+ This writes the subtype'th row into the bmo. */
+ for (col=0; col < self->row_size; col++)
+ bmo->data[col]= self->matrix[col][subtype];
+
return 0;
}
static int mathutils_matrix_vector_set(BaseMathObject *bmo, int subtype)
{
MatrixObject *self= (MatrixObject *)bmo->cb_user;
- int i;
+ int col;
if (BaseMath_ReadCallback(self) == -1)
return -1;
- for (i=0; i < self->col_size; i++)
- self->matrix[subtype][i]= bmo->data[i];
+ /* Note that the normal math representation of the matrix is the transpose of
+ the internal representation. Hence, subtype indexes the row.*/
+ /* Loop over each column in the matrix and set the element indexed by subtype.
+ This writes the bmo into subtype'th row. */
+ for (col=0; col < self->row_size; col++)
+ self->matrix[col][subtype]= bmo->data[col];
+
(void)BaseMath_WriteCallback(self);
return 0;
}
@@ -85,7 +95,10 @@
if (BaseMath_ReadCallback(self) == -1)
return -1;
- bmo->data[index]= self->matrix[subtype][index];
+ /* Note that the normal math representation of the matrix is the transpose of
+ the internal representation. Hence, subtype indexes the row, and index indexes
+ the column.*/
+ bmo->data[index]= self->matrix[index][subtype];
return 0;
}
@@ -96,7 +109,10 @@
if (BaseMath_ReadCallback(self) == -1)
return -1;
- self->matrix[subtype][index]= bmo->data[index];
+ /* Note that the normal math representation of the matrix is the transpose of
+ the internal representation. Hence, subtype indexes the row, and index indexes
+ the column.*/
+ self->matrix[index][subtype]= bmo->data[index];
(void)BaseMath_WriteCallback(self);
return 0;
@@ -131,14 +147,19 @@
PyObject *arg= PyTuple_GET_ITEM(args, 0);
/* -1 is an error, size checks will accunt for this */
- const unsigned short row_size= PySequence_Size(arg);
+ /* The normal math representation indexes rows first,
+ so input from the user will consist of tuples which
+ are the matrix rows. */
+ const unsigned short col_size= PySequence_Size(arg);
- if (row_size >= 2 && row_size <= 4) {
+ if (col_size >= 2 && col_size <= 4) {
PyObject *item= PySequence_GetItem(arg, 0);
- const unsigned short col_size= PySequence_Size(item);
+ /* Since each tuple is a row, the number of elements in the
+ tuple is the number of columns for our matrix. */
+ const unsigned short row_size= PySequence_Size(item);
Py_XDECREF(item);
- if (col_size >= 2 && col_size <= 4) {
+ if (row_size >= 2 && row_size <= 4) {
/* sane row & col size, new matrix and assign as slice */
PyObject *matrix= Matrix_CreatePyObject(NULL, row_size, col_size, Py_NEW, type);
if (Matrix_ass_slice((MatrixObject *)matrix, 0, INT_MAX, arg) == 0) {
@@ -759,7 +780,8 @@
);
static PyObject *Matrix_resize_4x4(MatrixObject *self)
{
- int x, first_row_elem, curr_pos, new_pos, blank_columns, blank_rows, index;
+ int col;
+ float mat[16];
if (self->wrapped==Py_WRAP) {
PyErr_SetString(PyExc_TypeError,
@@ -781,34 +803,23 @@
"problem allocating pointer space");
return NULL;
}
+ /* Set the temp matrix as a 4x4 identity matrix */
+ unit_m4((float (*)[4])mat);
+
+ /* Now copy the columns from the original matrix into the
+ temporary one, accounting for the change in size. */
+ for (col = 0; col < self->row_size; col++) {
+ memcpy(mat + 4 * col, self->contigPtr + self->col_size * col, self->col_size * sizeof(float));
+ }
+
+ /* Copy the temp matrix back into the original one */
+ memcpy(self->contigPtr, mat, 16 * sizeof(float));
+
/*set row pointers*/
- for (x = 0; x < 4; x++) {
- self->matrix[x] = self->contigPtr + (x * 4);
+ for (col = 0; col < 4; col++) {
+ self->matrix[col] = self->contigPtr + (col * 4);
}
- /*move data to new spot in array + clean*/
- for (blank_rows = (4 - self->row_size); blank_rows > 0; blank_rows--) {
- for (x = 0; x < 4; x++) {
- index = (4 * (self->row_size + (blank_rows - 1))) + x;
- if (index == 10 || index == 15) {
- self->contigPtr[index] = 1.0f;
- }
- else {
- self->contigPtr[index] = 0.0f;
- }
- }
- }
- for (x = 1; x <= self->row_size; x++) {
- first_row_elem = (self->col_size * (self->row_size - x));
- curr_pos = (first_row_elem + (self->col_size -1));
- new_pos = (4 * (self->row_size - x)) + (curr_pos - first_row_elem);
- for (blank_columns = (4 - self->col_size); blank_columns > 0; blank_columns--) {
- self->contigPtr[new_pos + blank_columns] = 0.0f;
- }
- for ( ; curr_pos >= first_row_elem; curr_pos--) {
- self->contigPtr[new_pos] = self->contigPtr[curr_pos];
- new_pos--;
- }
- }
+
self->row_size = 4;
self->col_size = 4;
@@ -1295,19 +1306,21 @@
/*print the object to screen*/
static PyObject *Matrix_repr(MatrixObject *self)
{
- int x, y;
+ int row, col;
PyObject *rows[MATRIX_MAX_DIM]= {NULL};
if (BaseMath_ReadCallback(self) == -1)
return NULL;
- for (x = 0; x < self->row_size; x++) {
- rows[x]= PyTuple_New(self->col_size);
- for (y = 0; y < self->col_size; y++) {
- PyTuple_SET_ITEM(rows[x], y, PyFloat_FromDouble(self->matrix[x][y]));
+ /* Construct the representation as it is shown to the user,
+ note that internally matrices are indexed by column first.*/
+ for (row = 0; row < self->col_size; row++) {
+ rows[row]= PyTuple_New(self->row_size);
+ for (col = 0; col < self->row_size; col++) {
+ PyTuple_SET_ITEM(rows[row], col, PyFloat_FromDouble(self->matrix[col][row]));
}
}
- switch(self->row_size) {
+ switch(self->col_size) {
case 2: return PyUnicode_FromFormat("Matrix((%R,\n"
" %R))", rows[0], rows[1]);
@@ -1369,7 +1382,9 @@
sequence length*/
static int Matrix_len(MatrixObject *self)
{
- return (self->row_size);
+ /* Return the number of rows in the matrix since the user indexes
+ rows first. */
+ return (self->col_size);
}
/*----------------------------object[]---------------------------
sequence accessor (get)
@@ -1390,23 +1405,29 @@
/*----------------------------object[]-------------------------
sequence accessor (set) */
-static int Matrix_ass_item(MatrixObject *self, int i, PyObject *value)
+static int Matrix_ass_item(MatrixObject *self, int row, PyObject *value)
{
float vec[4];
+ int col;
+
if (BaseMath_ReadCallback(self) == -1)
return -1;
- if (i >= self->row_size || i < 0) {
+ if (row >= self->col_size || row < 0) {
PyErr_SetString(PyExc_IndexError,
- "matrix[attribute] = x: bad column");
+ "matrix[attribute] = x: bad row");
return -1;
}
- if (mathutils_array_parse(vec, self->col_size, self->col_size, value, "matrix[i] = value assignment") < 0) {
+ if (mathutils_array_parse(vec, self->row_size, self->row_size, value, "matrix[row] = value assignment") < 0) {
return -1;
}
- memcpy(self->matrix[i], vec, self->col_size *sizeof(float));
+ /* The user is assigning to a row but internal storage in column major so columns are contiguous in .
+ This means we cannot memcpy. We assign element wise.*/
+ for (col = 0; col < self->row_size; col++) {
+ self->matrix[col][row] = vec[col];
+ }
(void)BaseMath_WriteCallback(self);
return 0;
@@ -1445,9 +1466,11 @@
if (BaseMath_ReadCallback(self) == -1)
return -1;
- CLAMP(begin, 0, self->row_size);
- CLAMP(end, 0, self->row_size);
+ /* We are assigning rows here, so clamp to the number of rows in the matrix */
+ CLAMP(begin, 0, self->col_size);
+ CLAMP(end, 0, self->col_size);
begin = MIN2(begin, end);
+ end = MAX2(begin, end);
/* non list/tuple cases */
if (!(value_fast=PySequence_Fast(value, "matrix[begin:end] = value"))) {
@@ -1456,8 +1479,8 @@
}
else {
const int size= end - begin;
- int i;
- float mat[16];
+ int row, col;
+ float vec[4];
if (PySequence_Fast_GET_SIZE(value_fast) != size) {
Py_DECREF(value_fast);
@@ -1468,22 +1491,24 @@
}
/*parse sub items*/
- for (i = 0; i < size; i++) {
+ for (row = begin; row < end; row++) {
/*parse each sub sequence*/
- PyObject *item= PySequence_Fast_GET_ITEM(value_fast, i);
+ PyObject *item= PySequence_Fast_GET_ITEM(value_fast, row - begin);
- if (mathutils_array_parse(&mat[i * self->col_size], self->col_size, self->col_size, item,
+ if (mathutils_array_parse(vec, self->row_size, self->row_size, item,
"matrix[begin:end] = value assignment") < 0)
{
return -1;
}
+
+ /* Assigng elementwise from the row vector into the matrix */
+ for (col = 0; col < self->row_size; col++) {
+ self->matrix[col][row] = vec[col];
+ }
}
Py_DECREF(value_fast);
- /*parsed well - now set in matrix*/
- memcpy(self->contigPtr + (begin * self->col_size), mat, sizeof(float) * (size * self->col_size));
-
(void)BaseMath_WriteCallback(self);
return 0;
}
@@ -1772,12 +1797,16 @@
static PyObject *Matrix_getRowSize(MatrixObject *self, void *UNUSED(closure))
{
- return PyLong_FromLong((long) self->row_size);
+ /* Return the internal column size since the python representation is the transposed matrix */
+ /* i.e. row size of M = col size of M^T */
+ return PyLong_FromLong((long) self->col_size);
}
static PyObject *Matrix_getColSize(MatrixObject *self, void *UNUSED(closure))
{
- return PyLong_FromLong((long) self->col_size);
+ /* Return the internal row size since the python representation is the transposed matrix */
+ /* i.e. col size of M = row size of M^T */
+ return PyLong_FromLong((long) self->row_size);
}
static PyObject *Matrix_median_scale_get(MatrixObject *self, void *UNUSED(closure))
@@ -1954,8 +1983,11 @@
[4]
[5]
-self->matrix[1][1] = self->contigPtr[4] */
+self->matrix[1][1] = self->contigPtr[4]
+NOTE: First index on self->matrix is the column, i.e. self->matrix[1][0]
+ is the first element in the second column.*/
+
/*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
@@ -2008,9 +2040,11 @@
}
/*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];
+ /* rowSize is the number of columns */
+ for (col = 0; col < rowSize; col++) {
+ /* colSize is the number of rows */
+ for (row = 0; row < colSize; row++) {
+ self->matrix[col][row] = mat[(col * colSize) + row];
}
}
}
File Metadata
Details
Mime Type
text/x-diff
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
72/00/0376710eb939c082cf4f62e4c5e3
Event Timeline
Log In to Comment