Support for arbitrary sized vectors - (was limited by 2-4 previously)
patch http://codereview.appspot.com/5482043 from Andrew Hale * Text from the submission * This patch adds the ability to use arbitrary sized vectors from mathutils. Currently vectors are only of size 2, 3 or 4 since they are generally restricted to geometric applications. However, we can use arbitrary sized vectors for efficient calculations and data manipulation.
This commit is contained in:
@@ -54,15 +54,29 @@ static int row_vector_multiplication(float rvec[MAX_DIMENSIONS], VectorObject *v
|
||||
*/
|
||||
static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *UNUSED(kwds))
|
||||
{
|
||||
float vec[4]= {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
float *vec= NULL;
|
||||
int size= 3; /* default to a 3D vector */
|
||||
|
||||
switch(PyTuple_GET_SIZE(args)) {
|
||||
case 0:
|
||||
vec= PyMem_Malloc(size * sizeof(float));
|
||||
|
||||
if (vec == NULL) {
|
||||
PyErr_SetString(PyExc_MemoryError,
|
||||
"Vector(): "
|
||||
"problem allocating pointer space");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fill_vn_fl(vec, size, 0.0f);
|
||||
break;
|
||||
case 1:
|
||||
if ((size=mathutils_array_parse(vec, 2, 4, PyTuple_GET_ITEM(args, 0), "mathutils.Vector()")) == -1)
|
||||
if ((size=mathutils_array_parse_alloc(&vec, 2, PyTuple_GET_ITEM(args, 0), "mathutils.Vector()")) == -1) {
|
||||
if (vec) {
|
||||
PyMem_Free(vec);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
@@ -87,6 +101,215 @@ static PyObject *vec__apply_to_copy(PyNoArgsFunction vec_func, VectorObject *sel
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------CLASS-METHODS----------------------------*/
|
||||
PyDoc_STRVAR(C_Vector_Fill_doc,
|
||||
".. classmethod:: Fill(size, fill=0.0)\n"
|
||||
"\n"
|
||||
" Create a vector of length size with all values set to fill.\n"
|
||||
"\n"
|
||||
" :arg size: The length of the vector to be created.\n"
|
||||
" :type size: int\n"
|
||||
" :arg fill: The value used to fill the vector.\n"
|
||||
" :type fill: float\n"
|
||||
);
|
||||
static PyObject *C_Vector_Fill(PyObject *cls, PyObject *args)
|
||||
{
|
||||
float *vec;
|
||||
int size;
|
||||
float fill= 0.0f;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i|f:Vector.Fill", &size, &fill)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (size < 2) {
|
||||
PyErr_SetString(PyExc_RuntimeError,
|
||||
"Vector(): invalid size");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vec= PyMem_Malloc(size * sizeof(float));
|
||||
|
||||
if (vec == NULL) {
|
||||
PyErr_SetString(PyExc_MemoryError,
|
||||
"Vector.Fill(): "
|
||||
"problem allocating pointer space");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fill_vn_fl(vec, size, fill);
|
||||
|
||||
return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(C_Vector_Range_doc,
|
||||
".. classmethod:: Range(start=0, stop, step=1)\n"
|
||||
"\n"
|
||||
" Create a filled with a range of values.\n"
|
||||
"\n"
|
||||
" :arg start: The start of the range used to fill the vector.\n"
|
||||
" :type start: int\n"
|
||||
" :arg stop: The end of the range used to fill the vector.\n"
|
||||
" :type stop: int\n"
|
||||
" :arg step: The step between successive values in the vector.\n"
|
||||
" :type step: int\n"
|
||||
);
|
||||
static PyObject *C_Vector_Range(PyObject *cls, PyObject *args)
|
||||
{
|
||||
float *vec;
|
||||
int stop, size;
|
||||
int start= 0;
|
||||
int step= 1;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i|ii:Vector.Range", &start, &stop, &step)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch(PyTuple_GET_SIZE(args)){
|
||||
case 1:
|
||||
size = start;
|
||||
start= 0;
|
||||
break;
|
||||
case 2:
|
||||
if (start >= stop) {
|
||||
PyErr_SetString(PyExc_RuntimeError,
|
||||
"Start value is larger"
|
||||
"than the stop value");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size= stop - start;
|
||||
break;
|
||||
default:
|
||||
if (start >= stop) {
|
||||
PyErr_SetString(PyExc_RuntimeError,
|
||||
"Start value is larger"
|
||||
"than the stop value");
|
||||
return NULL;
|
||||
}
|
||||
size= (stop - start)/step;
|
||||
if (size%step)
|
||||
size++;
|
||||
break;
|
||||
}
|
||||
|
||||
vec= PyMem_Malloc(size * sizeof(float));
|
||||
|
||||
if (vec == NULL) {
|
||||
PyErr_SetString(PyExc_MemoryError,
|
||||
"Vector.Range(): "
|
||||
"problem allocating pointer space");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
range_vn_fl(vec, size, (float)start, (float)step);
|
||||
|
||||
return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(C_Vector_Linspace_doc,
|
||||
".. classmethod:: Linspace(start, stop, size)\n"
|
||||
"\n"
|
||||
" Create a vector of the specified size which is filled with linearly spaced values between start and stop values.\n"
|
||||
"\n"
|
||||
" :arg start: The start of the range used to fill the vector.\n"
|
||||
" :type start: int\n"
|
||||
" :arg stop: The end of the range used to fill the vector.\n"
|
||||
" :type stop: int\n"
|
||||
" :arg size: The size of the vector to be created.\n"
|
||||
" :type size: int\n"
|
||||
);
|
||||
static PyObject *C_Vector_Linspace(PyObject *cls, PyObject *args)
|
||||
{
|
||||
float *vec;
|
||||
int size;
|
||||
float start, end, step;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ffi:Vector.Linspace", &start, &end, &size)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (size < 2) {
|
||||
PyErr_SetString(PyExc_RuntimeError,
|
||||
"Vector.Linspace(): invalid size");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
step= (end - start)/(float)(size-1);
|
||||
|
||||
vec= PyMem_Malloc(size * sizeof(float));
|
||||
|
||||
if (vec == NULL) {
|
||||
PyErr_SetString(PyExc_MemoryError,
|
||||
"Vector.Linspace(): "
|
||||
"problem allocating pointer space");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
range_vn_fl(vec, size, start, step);
|
||||
|
||||
return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(C_Vector_Repeat_doc,
|
||||
".. classmethod:: Repeat(vector, size)\n"
|
||||
"\n"
|
||||
" Create a vector by repeating the values in vector until the required size is reached.\n"
|
||||
"\n"
|
||||
" :arg tuple: The vector to draw values from.\n"
|
||||
" :type tuple: :class:`mathutils.Vector`\n"
|
||||
" :arg size: The size of the vector to be created.\n"
|
||||
" :type size: int\n"
|
||||
);
|
||||
static PyObject *C_Vector_Repeat(PyObject *cls, PyObject *args)
|
||||
{
|
||||
float *vec;
|
||||
float *iter_vec= NULL;
|
||||
int i, size, value_size;
|
||||
PyObject *value;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "Oi:Vector.Repeat", &value, &size)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (size < 2) {
|
||||
PyErr_SetString(PyExc_RuntimeError,
|
||||
"Vector.Repeat(): invalid size");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((value_size=mathutils_array_parse_alloc(&iter_vec, 2, value, "Vector.Repeat(vector, size), invalid 'vector' arg")) == -1) {
|
||||
PyMem_Free(iter_vec);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (iter_vec == NULL) {
|
||||
PyErr_SetString(PyExc_MemoryError,
|
||||
"Vector.Repeat(): "
|
||||
"problem allocating pointer space");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vec= PyMem_Malloc(size * sizeof(float));
|
||||
|
||||
if (vec == NULL) {
|
||||
PyErr_SetString(PyExc_MemoryError,
|
||||
"Vector.Repeat(): "
|
||||
"problem allocating pointer space");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
i= 0;
|
||||
while (i < size) {
|
||||
vec[i]= iter_vec[i % value_size];
|
||||
i++;
|
||||
}
|
||||
|
||||
PyMem_Free(iter_vec);
|
||||
|
||||
return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls);
|
||||
}
|
||||
|
||||
/*-----------------------------METHODS---------------------------- */
|
||||
PyDoc_STRVAR(Vector_zero_doc,
|
||||
".. method:: zero()\n"
|
||||
@@ -137,6 +360,101 @@ static PyObject *Vector_normalized(VectorObject *self)
|
||||
return vec__apply_to_copy((PyNoArgsFunction)Vector_normalize, self);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(Vector_resize_doc,
|
||||
".. method:: resize(size=3)\n"
|
||||
"\n"
|
||||
" Resize the vector to have size number of elements.\n"
|
||||
"\n"
|
||||
" :return: an instance of itself\n"
|
||||
" :rtype: :class:`Vector`\n"
|
||||
);
|
||||
static PyObject *Vector_resize(VectorObject *self, PyObject *value)
|
||||
{
|
||||
int size;
|
||||
|
||||
if (self->wrapped==Py_WRAP) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"Vector.resize(): "
|
||||
"cannot resize wrapped data - only python vectors");
|
||||
return NULL;
|
||||
}
|
||||
if (self->cb_user) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"Vector.resize(): "
|
||||
"cannot resize a vector that has an owner");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((size = PyLong_AsLong(value)) == -1) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"Vector.resize(size): "
|
||||
"expected size argument to be an integer");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (size < 2) {
|
||||
PyErr_SetString(PyExc_RuntimeError,
|
||||
"Vector.resize(): invalid size");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->vec = PyMem_Realloc(self->vec, (size * sizeof(float)));
|
||||
if (self->vec == NULL) {
|
||||
PyErr_SetString(PyExc_MemoryError,
|
||||
"Vector.resize(): "
|
||||
"problem allocating pointer space");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* If the vector has increased in length, set all new elements to 0.0f */
|
||||
if (size > self->size) {
|
||||
fill_vn_fl(self->vec + self->size, size - self->size, 0.0f);
|
||||
}
|
||||
|
||||
self->size = size;
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(Vector_resized_doc,
|
||||
".. method:: resized(size=3)\n"
|
||||
"\n"
|
||||
" Return a resized copy of the vector with size number of elements.\n"
|
||||
"\n"
|
||||
" :return: a new vector\n"
|
||||
" :rtype: :class:`Vector`\n"
|
||||
);
|
||||
static PyObject *Vector_resized(VectorObject *self, PyObject *value)
|
||||
{
|
||||
int size;
|
||||
float *vec;
|
||||
|
||||
/*if (!PyArg_ParseTuple(args, "i:resize", &size))
|
||||
return NULL;*/
|
||||
if ((size = PyLong_AsLong(value)) == -1){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (size < 2) {
|
||||
PyErr_SetString(PyExc_RuntimeError,
|
||||
"Vector.resized(): invalid size");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vec= PyMem_Malloc(size * sizeof(float));
|
||||
|
||||
if (vec == NULL) {
|
||||
PyErr_SetString(PyExc_MemoryError,
|
||||
"Vector.resized(): "
|
||||
"problem allocating pointer space");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fill_vn_fl(vec, size, 0.0f);
|
||||
memcpy(vec, self->vec, self->size * sizeof(float));
|
||||
|
||||
return Vector_CreatePyObject_alloc(vec, size, NULL);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(Vector_resize_2d_doc,
|
||||
".. method:: resize_2d()\n"
|
||||
"\n"
|
||||
@@ -505,6 +823,12 @@ static PyObject *Vector_reflect(VectorObject *self, PyObject *value)
|
||||
if ((value_size= mathutils_array_parse(tvec, 2, 4, value, "Vector.reflect(other), invalid 'other' arg")) == -1)
|
||||
return NULL;
|
||||
|
||||
if (self->size < 2 || self->size > 4) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"Vector must be 2D, 3D or 4D");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mirror[0] = tvec[0];
|
||||
mirror[1] = tvec[1];
|
||||
if (value_size > 2) mirror[2] = tvec[2];
|
||||
@@ -544,6 +868,12 @@ static PyObject *Vector_cross(VectorObject *self, PyObject *value)
|
||||
if (mathutils_array_parse(tvec, self->size, self->size, value, "Vector.cross(other), invalid 'other' arg") == -1)
|
||||
return NULL;
|
||||
|
||||
if (self->size != 3) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"Vector must be 3D");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret= (VectorObject *)Vector_CreatePyObject(NULL, 3, Py_NEW, Py_TYPE(self));
|
||||
cross_v3_v3v3(ret->vec, self->vec, tvec);
|
||||
return (PyObject *)ret;
|
||||
@@ -561,15 +891,20 @@ PyDoc_STRVAR(Vector_dot_doc,
|
||||
);
|
||||
static PyObject *Vector_dot(VectorObject *self, PyObject *value)
|
||||
{
|
||||
float tvec[MAX_DIMENSIONS];
|
||||
float *tvec;
|
||||
|
||||
if (BaseMath_ReadCallback(self) == -1)
|
||||
return NULL;
|
||||
|
||||
if (mathutils_array_parse(tvec, self->size, self->size, value, "Vector.dot(other), invalid 'other' arg") == -1)
|
||||
return NULL;
|
||||
if (mathutils_array_parse_alloc(&tvec, self->size, value, "Vector.dot(other), invalid 'other' arg") == -1) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
return PyFloat_FromDouble(dot_vn_vn(self->vec, tvec, self->size));
|
||||
|
||||
cleanup:
|
||||
PyMem_Free(tvec);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(Vector_angle_doc,
|
||||
@@ -607,6 +942,12 @@ static PyObject *Vector_angle(VectorObject *self, PyObject *args)
|
||||
if (mathutils_array_parse(tvec, self->size, self->size, value, "Vector.angle(other), invalid 'other' arg") == -1)
|
||||
return NULL;
|
||||
|
||||
if (self->size > 4) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"Vector must be 2D, 3D or 4D");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (x = 0; x < size; x++) {
|
||||
dot_self += (double)self->vec[x] * (double)self->vec[x];
|
||||
dot_other += (double)tvec[x] * (double)tvec[x];
|
||||
@@ -647,7 +988,7 @@ static PyObject *Vector_rotation_difference(VectorObject *self, PyObject *value)
|
||||
{
|
||||
float quat[4], vec_a[3], vec_b[3];
|
||||
|
||||
if (self->size < 3) {
|
||||
if (self->size < 3 || self->size > 4) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"vec.difference(value): "
|
||||
"expects both vectors to be size 3 or 4");
|
||||
@@ -692,6 +1033,12 @@ static PyObject *Vector_project(VectorObject *self, PyObject *value)
|
||||
if (mathutils_array_parse(tvec, size, size, value, "Vector.project(other), invalid 'other' arg") == -1)
|
||||
return NULL;
|
||||
|
||||
if (self->size > 4) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"Vector must be 2D, 3D or 4D");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (BaseMath_ReadCallback(self) == -1)
|
||||
return NULL;
|
||||
|
||||
@@ -725,24 +1072,41 @@ static PyObject *Vector_lerp(VectorObject *self, PyObject *args)
|
||||
const int size= self->size;
|
||||
PyObject *value= NULL;
|
||||
float fac, ifac;
|
||||
float tvec[MAX_DIMENSIONS], vec[MAX_DIMENSIONS];
|
||||
float *tvec, *vec;
|
||||
int x;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "Of:lerp", &value, &fac))
|
||||
return NULL;
|
||||
|
||||
if (mathutils_array_parse(tvec, size, size, value, "Vector.lerp(other), invalid 'other' arg") == -1)
|
||||
return NULL;
|
||||
if (mathutils_array_parse_alloc(&tvec, size, value, "Vector.lerp(other), invalid 'other' arg") == -1) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (BaseMath_ReadCallback(self) == -1)
|
||||
if (BaseMath_ReadCallback(self) == -1) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
vec= PyMem_Malloc(size * sizeof(float));
|
||||
if (vec == NULL) {
|
||||
PyErr_SetString(PyExc_MemoryError,
|
||||
"Vector.lerp(): "
|
||||
"problem allocating pointer space");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ifac= 1.0f - fac;
|
||||
|
||||
for (x = 0; x < size; x++) {
|
||||
vec[x] = (ifac * self->vec[x]) + (fac * tvec[x]);
|
||||
}
|
||||
return Vector_CreatePyObject(vec, size, Py_NEW, Py_TYPE(self));
|
||||
|
||||
PyMem_Free(tvec);
|
||||
|
||||
return Vector_CreatePyObject_alloc(vec, size, Py_TYPE(self));
|
||||
|
||||
cleanup:
|
||||
PyMem_Free(tvec);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(Vector_rotate_doc,
|
||||
@@ -763,7 +1127,7 @@ static PyObject *Vector_rotate(VectorObject *self, PyObject *value)
|
||||
if (mathutils_any_to_rotmat(other_rmat, value, "Vector.rotate(value)") == -1)
|
||||
return NULL;
|
||||
|
||||
if (self->size < 3) {
|
||||
if (self->size < 3 || self->size > 4) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"Vector must be 3D or 4D");
|
||||
return NULL;
|
||||
@@ -903,8 +1267,8 @@ static PyObject *Vector_slice(VectorObject *self, int begin, int end)
|
||||
/* sequence slice (set): vector[a:b] = value */
|
||||
static int Vector_ass_slice(VectorObject *self, int begin, int end, PyObject *seq)
|
||||
{
|
||||
int y, size = 0;
|
||||
float vec[MAX_DIMENSIONS];
|
||||
int size = 0;
|
||||
float *vec= NULL;
|
||||
|
||||
if (BaseMath_ReadCallback(self) == -1)
|
||||
return -1;
|
||||
@@ -914,18 +1278,30 @@ static int Vector_ass_slice(VectorObject *self, int begin, int end, PyObject *se
|
||||
begin = MIN2(begin, end);
|
||||
|
||||
size = (end - begin);
|
||||
if (mathutils_array_parse(vec, size, size, seq, "vector[begin:end] = [...]") == -1)
|
||||
if (mathutils_array_parse_alloc(&vec, size, seq, "vector[begin:end] = [...]") == -1) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (vec == NULL) {
|
||||
PyErr_SetString(PyExc_MemoryError,
|
||||
"vec[:] = seq: "
|
||||
"problem allocating pointer space");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*parsed well - now set in vector*/
|
||||
for (y = 0; y < size; y++) {
|
||||
self->vec[begin + y] = vec[y];
|
||||
}
|
||||
memcpy(self->vec + begin, vec, size * sizeof(float));
|
||||
|
||||
if (BaseMath_WriteCallback(self) == -1)
|
||||
return -1;
|
||||
|
||||
PyMem_Free(vec);
|
||||
|
||||
return 0;
|
||||
|
||||
cleanup:
|
||||
PyMem_Free(vec);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Numeric Protocols */
|
||||
@@ -933,7 +1309,7 @@ static int Vector_ass_slice(VectorObject *self, int begin, int end, PyObject *se
|
||||
static PyObject *Vector_add(PyObject *v1, PyObject *v2)
|
||||
{
|
||||
VectorObject *vec1 = NULL, *vec2 = NULL;
|
||||
float vec[MAX_DIMENSIONS];
|
||||
float *vec= NULL;
|
||||
|
||||
if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) {
|
||||
PyErr_Format(PyExc_AttributeError,
|
||||
@@ -956,9 +1332,18 @@ static PyObject *Vector_add(PyObject *v1, PyObject *v2)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vec= PyMem_Malloc(vec1->size * sizeof(float));
|
||||
|
||||
if (vec == NULL) { /*allocation failure*/
|
||||
PyErr_SetString(PyExc_MemoryError,
|
||||
"Vector(): "
|
||||
"problem allocating pointer space");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
add_vn_vnvn(vec, vec1->vec, vec2->vec, vec1->size);
|
||||
|
||||
return Vector_CreatePyObject(vec, vec1->size, Py_NEW, Py_TYPE(v1));
|
||||
return Vector_CreatePyObject_alloc(vec, vec1->size, Py_TYPE(v1));
|
||||
}
|
||||
|
||||
/* addition in-place: obj += obj */
|
||||
@@ -997,7 +1382,7 @@ static PyObject *Vector_iadd(PyObject *v1, PyObject *v2)
|
||||
static PyObject *Vector_sub(PyObject *v1, PyObject *v2)
|
||||
{
|
||||
VectorObject *vec1 = NULL, *vec2 = NULL;
|
||||
float vec[MAX_DIMENSIONS];
|
||||
float *vec;
|
||||
|
||||
if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) {
|
||||
PyErr_Format(PyExc_AttributeError,
|
||||
@@ -1019,9 +1404,18 @@ static PyObject *Vector_sub(PyObject *v1, PyObject *v2)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vec= PyMem_Malloc(vec1->size * sizeof(float));
|
||||
|
||||
if (vec == NULL) { /*allocation failure*/
|
||||
PyErr_SetString(PyExc_MemoryError,
|
||||
"Vector(): "
|
||||
"problem allocating pointer space");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sub_vn_vnvn(vec, vec1->vec, vec2->vec, vec1->size);
|
||||
|
||||
return Vector_CreatePyObject(vec, vec1->size, Py_NEW, Py_TYPE(v1));
|
||||
return Vector_CreatePyObject_alloc(vec, vec1->size, Py_TYPE(v1));
|
||||
}
|
||||
|
||||
/* subtraction in-place: obj -= obj */
|
||||
@@ -1104,9 +1498,18 @@ int column_vector_multiplication(float rvec[MAX_DIMENSIONS], VectorObject* vec,
|
||||
|
||||
static PyObject *vector_mul_float(VectorObject *vec, const float scalar)
|
||||
{
|
||||
float tvec[MAX_DIMENSIONS];
|
||||
float *tvec= NULL;
|
||||
tvec= PyMem_Malloc(vec->size * sizeof(float));
|
||||
|
||||
if (tvec == NULL) { /*allocation failure*/
|
||||
PyErr_SetString(PyExc_MemoryError,
|
||||
"vec * float: "
|
||||
"problem allocating pointer space");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mul_vn_vn_fl(tvec, vec->vec, vec->size, scalar);
|
||||
return Vector_CreatePyObject(tvec, vec->size, Py_NEW, Py_TYPE(vec));
|
||||
return Vector_CreatePyObject_alloc(tvec, vec->size, Py_TYPE(vec));
|
||||
}
|
||||
|
||||
static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
|
||||
@@ -1277,8 +1680,7 @@ static PyObject *Vector_imul(PyObject *v1, PyObject *v2)
|
||||
/* divid: obj / obj */
|
||||
static PyObject *Vector_div(PyObject *v1, PyObject *v2)
|
||||
{
|
||||
int i;
|
||||
float vec[4], scalar;
|
||||
float *vec= NULL, scalar;
|
||||
VectorObject *vec1 = NULL;
|
||||
|
||||
if (!VectorObject_Check(v1)) { /* not a vector */
|
||||
@@ -1287,7 +1689,7 @@ static PyObject *Vector_div(PyObject *v1, PyObject *v2)
|
||||
"Vector must be divided by a float");
|
||||
return NULL;
|
||||
}
|
||||
vec1 = (VectorObject*)v1; /* vector */
|
||||
vec1 = (VectorObject *)v1; /* vector */
|
||||
|
||||
if (BaseMath_ReadCallback(vec1) == -1)
|
||||
return NULL;
|
||||
@@ -1306,16 +1708,23 @@ static PyObject *Vector_div(PyObject *v1, PyObject *v2)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < vec1->size; i++) {
|
||||
vec[i] = vec1->vec[i] / scalar;
|
||||
vec= PyMem_Malloc(vec1->size * sizeof(float));
|
||||
|
||||
if (vec == NULL) { /*allocation failure*/
|
||||
PyErr_SetString(PyExc_MemoryError,
|
||||
"vec / value: "
|
||||
"problem allocating pointer space");
|
||||
return NULL;
|
||||
}
|
||||
return Vector_CreatePyObject(vec, vec1->size, Py_NEW, Py_TYPE(v1));
|
||||
|
||||
mul_vn_vn_fl(vec, vec1->vec, vec1->size, 1.0f/scalar);
|
||||
|
||||
return Vector_CreatePyObject_alloc(vec, vec1->size, Py_TYPE(v1));
|
||||
}
|
||||
|
||||
/* divide in-place: obj /= obj */
|
||||
static PyObject *Vector_idiv(PyObject *v1, PyObject *v2)
|
||||
{
|
||||
int i;
|
||||
float scalar;
|
||||
VectorObject *vec1 = (VectorObject*)v1;
|
||||
|
||||
@@ -1335,9 +1744,8 @@ static PyObject *Vector_idiv(PyObject *v1, PyObject *v2)
|
||||
"divide by zero error");
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; i < vec1->size; i++) {
|
||||
vec1->vec[i] /= scalar;
|
||||
}
|
||||
|
||||
mul_vn_fl(vec1->vec, vec1->size, 1.0f/scalar);
|
||||
|
||||
(void)BaseMath_WriteCallback(vec1);
|
||||
|
||||
@@ -1349,29 +1757,24 @@ static PyObject *Vector_idiv(PyObject *v1, PyObject *v2)
|
||||
returns the negative of this object*/
|
||||
static PyObject *Vector_neg(VectorObject *self)
|
||||
{
|
||||
float tvec[MAX_DIMENSIONS];
|
||||
float *tvec;
|
||||
|
||||
if (BaseMath_ReadCallback(self) == -1)
|
||||
return NULL;
|
||||
|
||||
tvec= PyMem_Malloc(self->size * sizeof(float));
|
||||
negate_vn_vn(tvec, self->vec, self->size);
|
||||
return Vector_CreatePyObject(tvec, self->size, Py_NEW, Py_TYPE(self));
|
||||
return Vector_CreatePyObject_alloc(tvec, self->size, Py_TYPE(self));
|
||||
}
|
||||
|
||||
/*------------------------vec_magnitude_nosqrt (internal) - for comparing only */
|
||||
static double vec_magnitude_nosqrt(float *data, int size)
|
||||
{
|
||||
double dot = 0.0f;
|
||||
int i;
|
||||
|
||||
for (i=0; i<size; i++) {
|
||||
dot += (double)data[i];
|
||||
}
|
||||
/*return (double)sqrt(dot);*/
|
||||
/* warning, line above removed because we are not using the length,
|
||||
rather the comparing the sizes and for this we do not need the sqrt
|
||||
for the actual length, the dot must be sqrt'd */
|
||||
return dot;
|
||||
return dot_vn_vn(data, data, size);
|
||||
}
|
||||
|
||||
|
||||
@@ -1606,16 +2009,10 @@ static int Vector_setAxis(VectorObject *self, PyObject *value, void *type)
|
||||
/* vector.length */
|
||||
static PyObject *Vector_getLength(VectorObject *self, void *UNUSED(closure))
|
||||
{
|
||||
double dot = 0.0f;
|
||||
int i;
|
||||
|
||||
if (BaseMath_ReadCallback(self) == -1)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < self->size; i++) {
|
||||
dot += (double)(self->vec[i] * self->vec[i]);
|
||||
}
|
||||
return PyFloat_FromDouble(sqrt(dot));
|
||||
return PyFloat_FromDouble(sqrt(dot_vn_vn(self->vec, self->vec, self->size)));
|
||||
}
|
||||
|
||||
static int Vector_setLength(VectorObject *self, PyObject *value)
|
||||
@@ -2242,6 +2639,12 @@ static PyObject *Vector_negate(VectorObject *self)
|
||||
}
|
||||
|
||||
static struct PyMethodDef Vector_methods[] = {
|
||||
/* Class Methods */
|
||||
{"Fill", (PyCFunction) C_Vector_Fill, METH_VARARGS | METH_CLASS, C_Vector_Fill_doc},
|
||||
{"Range", (PyCFunction) C_Vector_Range, METH_VARARGS | METH_CLASS, C_Vector_Range_doc},
|
||||
{"Linspace", (PyCFunction) C_Vector_Linspace, METH_VARARGS | METH_CLASS, C_Vector_Linspace_doc},
|
||||
{"Repeat", (PyCFunction) C_Vector_Repeat, METH_VARARGS | METH_CLASS, C_Vector_Repeat_doc},
|
||||
|
||||
/* in place only */
|
||||
{"zero", (PyCFunction) Vector_zero, METH_NOARGS, Vector_zero_doc},
|
||||
{"negate", (PyCFunction) Vector_negate, METH_NOARGS, Vector_negate_doc},
|
||||
@@ -2250,6 +2653,8 @@ static struct PyMethodDef Vector_methods[] = {
|
||||
{"normalize", (PyCFunction) Vector_normalize, METH_NOARGS, Vector_normalize_doc},
|
||||
{"normalized", (PyCFunction) Vector_normalized, METH_NOARGS, Vector_normalized_doc},
|
||||
|
||||
{"resize", (PyCFunction) Vector_resize, METH_O, Vector_resize_doc},
|
||||
{"resized", (PyCFunction) Vector_resized, METH_O, Vector_resized_doc},
|
||||
{"to_2d", (PyCFunction) Vector_to_2d, METH_NOARGS, Vector_to_2d_doc},
|
||||
{"resize_2d", (PyCFunction) Vector_resize_2d, METH_NOARGS, Vector_resize_2d_doc},
|
||||
{"to_3d", (PyCFunction) Vector_to_3d, METH_NOARGS, Vector_to_3d_doc},
|
||||
@@ -2375,7 +2780,7 @@ PyObject *Vector_CreatePyObject(float *vec, const int size, const int type, PyTy
|
||||
{
|
||||
VectorObject *self;
|
||||
|
||||
if (size > 4 || size < 2) {
|
||||
if (size < 2) {
|
||||
PyErr_SetString(PyExc_RuntimeError,
|
||||
"Vector(): invalid size");
|
||||
return NULL;
|
||||
@@ -2429,3 +2834,12 @@ PyObject *Vector_CreatePyObject_cb(PyObject *cb_user, int size, int cb_type, int
|
||||
|
||||
return (PyObject *)self;
|
||||
}
|
||||
|
||||
PyObject *Vector_CreatePyObject_alloc(float *vec, const int size, PyTypeObject *base_type)
|
||||
{
|
||||
VectorObject *vect_ob;
|
||||
vect_ob= (VectorObject *)Vector_CreatePyObject(vec, size, Py_WRAP, base_type);
|
||||
vect_ob->wrapped= Py_NEW;
|
||||
|
||||
return (PyObject *)vect_ob;
|
||||
}
|
||||
|
Reference in New Issue
Block a user