diff options
author | Campbell Barton <ideasman42@gmail.com> | 2011-02-05 09:14:50 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2011-02-05 09:14:50 +0300 |
commit | dd08305e7506233611315dc6c60013fbac30b53d (patch) | |
tree | fb9e9d1e65ec790d20a51056aa3ab98766b2a68f /source | |
parent | f2a6395e21c723843c0e44bba22de0c7aa1a3d08 (diff) |
Rename python mathutils functions and split in-place methods from those that return new values.
http://wiki.blender.org/index.php/Dev:2.5/Source/Python/Mathutils
This completes the changes proposed.
This will break scripts (fixing coming up next), for full list of changes see mathutils.c comments.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenlib/BLI_math_vector.h | 2 | ||||
-rw-r--r-- | source/blender/blenlib/intern/math_vector.c | 15 | ||||
-rw-r--r-- | source/blender/python/generic/mathutils.c | 15 | ||||
-rw-r--r-- | source/blender/python/generic/mathutils_euler.c | 14 | ||||
-rw-r--r-- | source/blender/python/generic/mathutils_matrix.c | 173 | ||||
-rw-r--r-- | source/blender/python/generic/mathutils_quat.c | 98 | ||||
-rw-r--r-- | source/blender/python/generic/mathutils_vector.c | 246 |
7 files changed, 347 insertions, 216 deletions
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index 4d8a4f2bbaf..d6d9c0a1c22 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -173,6 +173,8 @@ void minmax_v3v3_v3(float min[3], float max[3], const float vec[3]); /***************************** Array Functions *******************************/ /* attempted to follow fixed length vertex functions. names could be improved*/ void range_vni(int *array, const int size, const int start); +void negate_vn(float *array_tar, const int size); +void negate_vn_vn(float *array_tar, const float *array_src, const int size); void mul_vn_fl(float *array, const int size, const float f); void mul_vn_vn_fl(float *array_tar, const float *array_src, const int size, const float f); void add_vn_vn(float *array_tar, const float *array_src, const int size); diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c index 37a68cb0fca..bcad7894e86 100644 --- a/source/blender/blenlib/intern/math_vector.c +++ b/source/blender/blenlib/intern/math_vector.c @@ -375,6 +375,21 @@ void range_vni(int *array_tar, const int size, const int start) while(i--) { *(array_pt--) = j--; } } +void negate_vn(float *array_tar, const int size) +{ + float *array_pt= array_tar + (size-1); + int i= size; + while(i--) { *(array_pt--) *= -1.0f; } +} + +void negate_vn_vn(float *array_tar, const float *array_src, const int size) +{ + float *tar= array_tar + (size-1); + const float *src= array_src + (size-1); + int i= size; + while(i--) { *(tar--) = - *(src--); } +} + void mul_vn_fl(float *array_tar, const int size, const float f) { float *array_pt= array_tar + (size-1); diff --git a/source/blender/python/generic/mathutils.c b/source/blender/python/generic/mathutils.c index 49cd5d2f53e..25b1e458ae8 100644 --- a/source/blender/python/generic/mathutils.c +++ b/source/blender/python/generic/mathutils.c @@ -50,7 +50,20 @@ * - Quaternion * Quaternion --> cross product (not dot product) * - Euler.rotate(angle, axis) --> Euler.rotate_axis(axis, angle) * - Euler.unique() *removed*, not a standard function only toggled different rotations. - * + * - Matrix.rotation_part() -> to_3x3() + * - Matrix.scale_part() -> to_scale() + * - Matrix.translation_part() -> to_translation() + * - Matrix.resize4x4() -> resize_4x4() + * - Euler.to_quat() -> to_quaternion() + * - Matrix.to_quat() -> to_quaternion() + * resizing nolonger returns the resized value. + * - Vector.resize2D -> resize_2d + * - Vector.resize3D -> resize_3d + * - Vector.resize4D -> resize_4d + * added new functions. + * - Vector.to_2d() + * - Vector.to_3d() + * - Vector.to_4d() * moved into class functions. * - Mathutils.RotationMatrix -> mathutils.Matrix.Rotation * - Mathutils.ScaleMatrix -> mathutils.Matrix.Scale diff --git a/source/blender/python/generic/mathutils_euler.c b/source/blender/python/generic/mathutils_euler.c index 0294cfd72e9..8f6d7e8a182 100644 --- a/source/blender/python/generic/mathutils_euler.c +++ b/source/blender/python/generic/mathutils_euler.c @@ -146,7 +146,7 @@ static char Euler_to_matrix_doc[] = ; static PyObject *Euler_to_matrix(EulerObject * self) { - float mat[9] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}; + float mat[9]; if(!BaseMath_ReadCallback(self)) return NULL; @@ -162,19 +162,13 @@ static char Euler_zero_doc[] = ".. method:: zero()\n" "\n" " Set all values to zero.\n" -"\n" -" :return: an instance of itself\n" -" :rtype: :class:`Euler`\n" ; static PyObject *Euler_zero(EulerObject * self) { - self->eul[0] = 0.0; - self->eul[1] = 0.0; - self->eul[2] = 0.0; + zero_v3(self->eul); (void)BaseMath_WriteCallback(self); - Py_INCREF(self); - return (PyObject *)self; + Py_RETURN_NONE; } static char Euler_rotate_axis_doc[] = @@ -568,7 +562,7 @@ static PyGetSetDef Euler_getseters[] = { static struct PyMethodDef Euler_methods[] = { {"zero", (PyCFunction) Euler_zero, METH_NOARGS, Euler_zero_doc}, {"to_matrix", (PyCFunction) Euler_to_matrix, METH_NOARGS, Euler_to_matrix_doc}, - {"to_quat", (PyCFunction) Euler_to_quaternion, METH_NOARGS, Euler_to_quaternion_doc}, + {"to_quaternion", (PyCFunction) Euler_to_quaternion, METH_NOARGS, Euler_to_quaternion_doc}, {"rotate_axis", (PyCFunction) Euler_rotate_axis, METH_VARARGS, Euler_rotate_axis_doc}, {"make_compatible", (PyCFunction) Euler_make_compatible, METH_O, Euler_make_compatible_doc}, {"__copy__", (PyCFunction) Euler_copy, METH_NOARGS, Euler_copy_doc}, diff --git a/source/blender/python/generic/mathutils_matrix.c b/source/blender/python/generic/mathutils_matrix.c index 1cec0536cc8..8f8d3267cc6 100644 --- a/source/blender/python/generic/mathutils_matrix.c +++ b/source/blender/python/generic/mathutils_matrix.c @@ -31,6 +31,21 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" +#define MATRIX_APPLY_TO_COPY(matrix_meth_noargs, _self) \ + MatrixObject *ret= (MatrixObject *)Matrix_copy(_self); \ + PyObject *ret_dummy= matrix_meth_noargs(ret); \ + if(ret_dummy) { \ + Py_DECREF(ret_dummy); \ + return (PyObject *)ret; \ + } \ + else { /* error */ \ + Py_DECREF(ret); \ + return NULL; \ + } \ + + +static PyObject *Matrix_copy(MatrixObject *self); + static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *value); /* matrix vector callbacks */ @@ -661,7 +676,7 @@ static char Matrix_to_euler_doc[] = " :return: Euler representation of the matrix.\n" " :rtype: :class:`Euler`\n" ; -PyObject *Matrix_to_euler(MatrixObject *self, PyObject *args) +static PyObject *Matrix_to_euler(MatrixObject *self, PyObject *args) { const char *order_str= NULL; short order= EULER_ORDER_XYZ; @@ -713,16 +728,16 @@ PyObject *Matrix_to_euler(MatrixObject *self, PyObject *args) return newEulerObject(eul, order, Py_NEW, NULL); } -/*---------------------------Matrix.resize4x4() ------------------*/ -static char Matrix_resize4x4_doc[] = -".. method:: resize4x4()\n" + +static char Matrix_resize_4x4_doc[] = +".. method:: resize_4x4()\n" "\n" " Resize the matrix to 4x4.\n" "\n" " :return: an instance of itself.\n" " :rtype: :class:`Matrix`\n" ; -PyObject *Matrix_resize4x4(MatrixObject *self) +static PyObject *Matrix_resize_4x4(MatrixObject *self) { int x, first_row_elem, curr_pos, new_pos, blank_columns, blank_rows, index; @@ -737,7 +752,7 @@ PyObject *Matrix_resize4x4(MatrixObject *self) self->contigPtr = PyMem_Realloc(self->contigPtr, (sizeof(float) * 16)); if(self->contigPtr == NULL) { - PyErr_SetString(PyExc_MemoryError, "matrix.resize4x4(): problem allocating pointer space"); + PyErr_SetString(PyExc_MemoryError, "matrix.resize_4x4(): problem allocating pointer space"); return NULL; } /*set row pointers*/ @@ -782,7 +797,7 @@ static char Matrix_to_4x4_doc[] = " :return: a new matrix.\n" " :rtype: :class:`Matrix`\n" ; -PyObject *Matrix_to_4x4(MatrixObject *self) +static PyObject *Matrix_to_4x4(MatrixObject *self) { if(!BaseMath_ReadCallback(self)) return NULL; @@ -809,7 +824,7 @@ static char Matrix_to_3x3_doc[] = " :return: a new matrix.\n" " :rtype: :class:`Matrix`\n" ; -PyObject *Matrix_to_3x3(MatrixObject *self) +static PyObject *Matrix_to_3x3(MatrixObject *self) { float mat[3][3]; @@ -826,57 +841,29 @@ PyObject *Matrix_to_3x3(MatrixObject *self) return newMatrixObject((float *)mat, 3, 3, Py_NEW, Py_TYPE(self)); } -/*---------------------------Matrix.translationPart() ------------*/ -static char Matrix_translation_part_doc[] = -".. method:: translation_part()\n" +static char Matrix_to_translation_doc[] = +".. method:: to_translation()\n" "\n" " Return a the translation part of a 4 row matrix.\n" "\n" " :return: Return a the translation of a matrix.\n" " :rtype: :class:`Vector`\n" ; -PyObject *Matrix_translation_part(MatrixObject *self) +static PyObject *Matrix_to_translation(MatrixObject *self) { if(!BaseMath_ReadCallback(self)) return NULL; if((self->colSize < 3) || self->rowSize < 4){ - PyErr_SetString(PyExc_AttributeError, "Matrix.translation_part(): inappropriate matrix size"); + PyErr_SetString(PyExc_AttributeError, "Matrix.to_translation(): inappropriate matrix size"); return NULL; } return newVectorObject(self->matrix[3], 3, Py_NEW, NULL); } -/*---------------------------Matrix.rotationPart() ---------------*/ -static char Matrix_rotation_part_doc[] = -".. method:: rotation_part()\n" -"\n" -" Return the 3d submatrix corresponding to the linear term of the embedded affine transformation in 3d. This matrix represents rotation and scale.\n" -"\n" -" :return: Return the 3d matrix for rotation and scale.\n" -" :rtype: :class:`Matrix`\n" -"\n" -" .. note:: Note that the (4,4) element of a matrix can be used for uniform scaling too.\n" -; -PyObject *Matrix_rotation_part(MatrixObject *self) -{ - float mat[3][3]; - - if(!BaseMath_ReadCallback(self)) - return NULL; - - if((self->colSize < 3) || (self->rowSize < 3)) { - PyErr_SetString(PyExc_AttributeError, "Matrix.rotation_part(): inappropriate matrix size"); - return NULL; - } - - matrix_as_3x3(mat, self); - return newMatrixObject((float *)mat, 3, 3, Py_NEW, Py_TYPE(self)); -} -/*---------------------------Matrix.scalePart() --------------------*/ -static char Matrix_scale_part_doc[] = -".. method:: scale_part()\n" +static char Matrix_to_scale_doc[] = +".. method:: to_scale()\n" "\n" " Return a the scale part of a 3x3 or 4x4 matrix.\n" "\n" @@ -885,7 +872,7 @@ static char Matrix_scale_part_doc[] = "\n" " .. note:: This method does not return negative a scale on any axis because it is not possible to obtain this data from the matrix alone.\n" ; -PyObject *Matrix_scale_part(MatrixObject *self) +static PyObject *Matrix_to_scale(MatrixObject *self) { float rot[3][3]; float mat[3][3]; @@ -896,7 +883,7 @@ PyObject *Matrix_scale_part(MatrixObject *self) /*must be 3-4 cols, 3-4 rows, square matrix*/ if((self->colSize < 3) || (self->rowSize < 3)) { - PyErr_SetString(PyExc_AttributeError, "Matrix.scale_part(): inappropriate matrix size, 3x3 minimum size"); + PyErr_SetString(PyExc_AttributeError, "Matrix.to_scale(): inappropriate matrix size, 3x3 minimum size"); return NULL; } @@ -921,7 +908,7 @@ static char Matrix_invert_doc[] = "\n" " .. seealso:: <http://en.wikipedia.org/wiki/Inverse_matrix>\n" ; -PyObject *Matrix_invert(MatrixObject *self) +static PyObject *Matrix_invert(MatrixObject *self) { int x, y, z = 0; @@ -971,8 +958,22 @@ PyObject *Matrix_invert(MatrixObject *self) } (void)BaseMath_WriteCallback(self); - Py_INCREF(self); - return (PyObject *)self; + Py_RETURN_NONE; +} + +static char Matrix_inverted_doc[] = +".. method:: invert()\n" +"\n" +" Return an inverted copy of the matrix.\n" +"\n" +" :return: the inverted matrix.\n" +" :rtype: :class:`Matrix`\n" +"\n" +" .. note:: :exc:`ValueError` exception is raised.\n" +; +static PyObject *Matrix_inverted(MatrixObject *self) +{ + MATRIX_APPLY_TO_COPY(Matrix_invert, self); } /*---------------------------Matrix.decompose() ---------------------*/ @@ -1067,7 +1068,7 @@ static char Matrix_determinant_doc[] = "\n" " .. seealso:: <http://en.wikipedia.org/wiki/Determinant>\n" ; -PyObject *Matrix_determinant(MatrixObject *self) +static PyObject *Matrix_determinant(MatrixObject *self) { if(!BaseMath_ReadCallback(self)) return NULL; @@ -1085,12 +1086,9 @@ static char Matrix_transpose_doc[] = "\n" " Set the matrix to its transpose.\n" "\n" -" :return: an instance of itself\n" -" :rtype: :class:`Matrix`\n" -"\n" " .. seealso:: <http://en.wikipedia.org/wiki/Transpose>\n" ; -PyObject *Matrix_transpose(MatrixObject *self) +static PyObject *Matrix_transpose(MatrixObject *self) { float t = 0.0f; @@ -1113,10 +1111,21 @@ PyObject *Matrix_transpose(MatrixObject *self) } (void)BaseMath_WriteCallback(self); - Py_INCREF(self); - return (PyObject *)self; + Py_RETURN_NONE; } +static char Matrix_transposed_doc[] = +".. method:: transposed()\n" +"\n" +" Return a new, transposed matrix.\n" +"\n" +" :return: a transposed matrix\n" +" :rtype: :class:`Matrix`\n" +; +static PyObject *Matrix_transposed(MatrixObject *self) +{ + MATRIX_APPLY_TO_COPY(Matrix_transpose, self); +} /*---------------------------Matrix.zero() -----------------------*/ static char Matrix_zero_doc[] = @@ -1127,21 +1136,14 @@ static char Matrix_zero_doc[] = " :return: an instance of itself\n" " :rtype: :class:`Matrix`\n" ; -PyObject *Matrix_zero(MatrixObject *self) +static PyObject *Matrix_zero(MatrixObject *self) { - int row, col; - - for(row = 0; row < self->rowSize; row++) { - for(col = 0; col < self->colSize; col++) { - self->matrix[row][col] = 0.0f; - } - } + fill_vn(self->contigPtr, self->rowSize * self->colSize, 0.0f); if(!BaseMath_WriteCallback(self)) return NULL; - Py_INCREF(self); - return (PyObject *)self; + Py_RETURN_NONE; } /*---------------------------Matrix.identity(() ------------------*/ static char Matrix_identity_doc[] = @@ -1149,14 +1151,11 @@ static char Matrix_identity_doc[] = "\n" " Set the matrix to the identity matrix.\n" "\n" -" :return: an instance of itself\n" -" :rtype: :class:`Matrix`\n" -"\n" " .. note:: An object with zero location and rotation, a scale of one, will have an identity matrix.\n" "\n" " .. seealso:: <http://en.wikipedia.org/wiki/Identity_matrix>\n" ; -PyObject *Matrix_identity(MatrixObject *self) +static PyObject *Matrix_identity(MatrixObject *self) { if(!BaseMath_ReadCallback(self)) return NULL; @@ -1180,8 +1179,7 @@ PyObject *Matrix_identity(MatrixObject *self) if(!BaseMath_WriteCallback(self)) return NULL; - Py_INCREF(self); - return (PyObject *)self; + Py_RETURN_NONE; } /*---------------------------Matrix.copy() ------------------*/ @@ -1193,7 +1191,7 @@ static char Matrix_copy_doc[] = " :return: an instance of itself\n" " :rtype: :class:`Matrix`\n" ; -PyObject *Matrix_copy(MatrixObject *self) +static PyObject *Matrix_copy(MatrixObject *self) { if(!BaseMath_ReadCallback(self)) return NULL; @@ -1718,21 +1716,32 @@ static PyGetSetDef Matrix_getseters[] = { /*-----------------------METHOD DEFINITIONS ----------------------*/ static struct PyMethodDef Matrix_methods[] = { + /* derived values */ + {"determinant", (PyCFunction) Matrix_determinant, METH_NOARGS, Matrix_determinant_doc}, + {"decompose", (PyCFunction) Matrix_decompose, METH_NOARGS, Matrix_decompose_doc}, + + /* in place only */ {"zero", (PyCFunction) Matrix_zero, METH_NOARGS, Matrix_zero_doc}, {"identity", (PyCFunction) Matrix_identity, METH_NOARGS, Matrix_identity_doc}, + + /* operate on original or copy */ {"transpose", (PyCFunction) Matrix_transpose, METH_NOARGS, Matrix_transpose_doc}, - {"lerp", (PyCFunction) Matrix_lerp, METH_VARARGS, Matrix_lerp_doc}, - {"determinant", (PyCFunction) Matrix_determinant, METH_NOARGS, Matrix_determinant_doc}, + {"transposed", (PyCFunction) Matrix_transposed, METH_NOARGS, Matrix_transposed_doc}, {"invert", (PyCFunction) Matrix_invert, METH_NOARGS, Matrix_invert_doc}, - {"translation_part", (PyCFunction) Matrix_translation_part, METH_NOARGS, Matrix_translation_part_doc}, - {"rotation_part", (PyCFunction) Matrix_rotation_part, METH_NOARGS, Matrix_rotation_part_doc}, - {"scale_part", (PyCFunction) Matrix_scale_part, METH_NOARGS, Matrix_scale_part_doc}, - {"decompose", (PyCFunction) Matrix_decompose, METH_NOARGS, Matrix_decompose_doc}, - {"resize4x4", (PyCFunction) Matrix_resize4x4, METH_NOARGS, Matrix_resize4x4_doc}, - {"to_4x4", (PyCFunction) Matrix_to_4x4, METH_NOARGS, Matrix_to_4x4_doc}, + {"inverted", (PyCFunction) Matrix_inverted, METH_NOARGS, Matrix_inverted_doc}, {"to_3x3", (PyCFunction) Matrix_to_3x3, METH_NOARGS, Matrix_to_3x3_doc}, + // TODO. {"resize_3x3", (PyCFunction) Matrix_resize3x3, METH_NOARGS, Matrix_resize3x3_doc}, + {"to_4x4", (PyCFunction) Matrix_to_4x4, METH_NOARGS, Matrix_to_4x4_doc}, + {"resize_4x4", (PyCFunction) Matrix_resize_4x4, METH_NOARGS, Matrix_resize_4x4_doc}, + + /* return converted representation */ {"to_euler", (PyCFunction) Matrix_to_euler, METH_VARARGS, Matrix_to_euler_doc}, - {"to_quat", (PyCFunction) Matrix_to_quaternion, METH_NOARGS, Matrix_to_quaternion_doc}, + {"to_quaternion", (PyCFunction) Matrix_to_quaternion, METH_NOARGS, Matrix_to_quaternion_doc}, + {"to_scale", (PyCFunction) Matrix_to_scale, METH_NOARGS, Matrix_to_scale_doc}, + {"to_translation", (PyCFunction) Matrix_to_translation, METH_NOARGS, Matrix_to_translation_doc}, + + /* operation between 2 or more types */ + {"lerp", (PyCFunction) Matrix_lerp, METH_VARARGS, Matrix_lerp_doc}, {"copy", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc}, {"__copy__", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc}, @@ -1860,8 +1869,8 @@ PyObject *newMatrixObject(float *mat, const unsigned short rowSize, const unsign } } } else if (rowSize == colSize ) { /*or if no arguments are passed return identity matrix for square matrices */ - Matrix_identity(self); - Py_DECREF(self); + PyObject *ret_dummy= Matrix_identity(self); + Py_DECREF(ret_dummy); } self->wrapped = Py_NEW; }else{ /*bad type*/ diff --git a/source/blender/python/generic/mathutils_quat.c b/source/blender/python/generic/mathutils_quat.c index 1b571742cda..c7d4fd186a4 100644 --- a/source/blender/python/generic/mathutils_quat.c +++ b/source/blender/python/generic/mathutils_quat.c @@ -31,9 +31,21 @@ #include "BLI_math.h" #include "BLI_utildefines.h" +#define QUAT_SIZE 4 +#define QUAT_APPLY_TO_COPY(quat_meth_noargs, _self) \ + QuaternionObject *ret= (QuaternionObject *)Quaternion_copy(_self); \ + PyObject *ret_dummy= quat_meth_noargs(ret); \ + if(ret_dummy) { \ + Py_DECREF(ret_dummy); \ + return (PyObject *)ret; \ + } \ + else { /* error */ \ + Py_DECREF(ret); \ + return NULL; \ + } \ -#define QUAT_SIZE 4 +static PyObject *Quaternion_copy(QuaternionObject *self); //-----------------------------METHODS------------------------------ @@ -250,9 +262,6 @@ static char Quaternion_normalize_doc[] = ".. function:: normalize()\n" "\n" " Normalize the quaternion.\n" -"\n" -" :return: an instance of itself.\n" -" :rtype: :class:`Quaternion`\n" ; static PyObject *Quaternion_normalize(QuaternionObject *self) { @@ -262,19 +271,28 @@ static PyObject *Quaternion_normalize(QuaternionObject *self) normalize_qt(self->quat); (void)BaseMath_WriteCallback(self); - Py_INCREF(self); - return (PyObject*)self; + Py_RETURN_NONE; } -//----------------------------Quaternion.inverse()------------------ -static char Quaternion_inverse_doc[] = -".. function:: inverse()\n" +static char Quaternion_normalized_doc[] = +".. function:: normalized()\n" "\n" -" Set the quaternion to its inverse.\n" +" Return a new normalized quaternion.\n" "\n" -" :return: an instance of itself.\n" +" :return: a normalized copy.\n" " :rtype: :class:`Quaternion`\n" ; -static PyObject *Quaternion_inverse(QuaternionObject *self) +static PyObject *Quaternion_normalized(QuaternionObject *self) +{ + QUAT_APPLY_TO_COPY(Quaternion_normalize, self); +} + +//----------------------------Quaternion.invert()------------------ +static char Quaternion_invert_doc[] = +".. function:: invert()\n" +"\n" +" Set the quaternion to its inverse.\n" +; +static PyObject *Quaternion_invert(QuaternionObject *self) { if(!BaseMath_ReadCallback(self)) return NULL; @@ -282,9 +300,21 @@ static PyObject *Quaternion_inverse(QuaternionObject *self) invert_qt(self->quat); (void)BaseMath_WriteCallback(self); - Py_INCREF(self); - return (PyObject*)self; + Py_RETURN_NONE; +} +static char Quaternion_inverted_doc[] = +".. function:: inverted()\n" +"\n" +" Return a new, inverted quaternion.\n" +"\n" +" :return: the inverted value.\n" +" :rtype: :class:`Quaternion`\n" +; +static PyObject *Quaternion_inverted(QuaternionObject *self) +{ + QUAT_APPLY_TO_COPY(Quaternion_invert, self); } + //----------------------------Quaternion.identity()----------------- static char Quaternion_identity_doc[] = ".. function:: identity()\n" @@ -302,8 +332,7 @@ static PyObject *Quaternion_identity(QuaternionObject *self) unit_qt(self->quat); (void)BaseMath_WriteCallback(self); - Py_INCREF(self); - return (PyObject*)self; + Py_RETURN_NONE; } //----------------------------Quaternion.negate()------------------- static char Quaternion_negate_doc[] = @@ -322,17 +351,13 @@ static PyObject *Quaternion_negate(QuaternionObject *self) mul_qt_fl(self->quat, -1.0f); (void)BaseMath_WriteCallback(self); - Py_INCREF(self); - return (PyObject*)self; + Py_RETURN_NONE; } //----------------------------Quaternion.conjugate()---------------- static char Quaternion_conjugate_doc[] = ".. function:: conjugate()\n" "\n" " Set the quaternion to its conjugate (negate x, y, z).\n" -"\n" -" :return: an instance of itself.\n" -" :rtype: :class:`Quaternion`\n" ; static PyObject *Quaternion_conjugate(QuaternionObject *self) { @@ -342,9 +367,21 @@ static PyObject *Quaternion_conjugate(QuaternionObject *self) conjugate_qt(self->quat); (void)BaseMath_WriteCallback(self); - Py_INCREF(self); - return (PyObject*)self; + Py_RETURN_NONE; +} +static char Quaternion_conjugated_doc[] = +".. function:: conjugated()\n" +"\n" +" Return a new conjugated quaternion.\n" +"\n" +" :return: a new quaternion.\n" +" :rtype: :class:`Quaternion`\n" +; +static PyObject *Quaternion_conjugated(QuaternionObject *self) +{ + QUAT_APPLY_TO_COPY(Quaternion_conjugate, self); } + //----------------------------Quaternion.copy()---------------- static char Quaternion_copy_doc[] = ".. function:: copy()\n" @@ -902,17 +939,30 @@ static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kw //-----------------------METHOD DEFINITIONS ---------------------- static struct PyMethodDef Quaternion_methods[] = { + /* in place only */ {"identity", (PyCFunction) Quaternion_identity, METH_NOARGS, Quaternion_identity_doc}, {"negate", (PyCFunction) Quaternion_negate, METH_NOARGS, Quaternion_negate_doc}, + + /* operate on original or copy */ {"conjugate", (PyCFunction) Quaternion_conjugate, METH_NOARGS, Quaternion_conjugate_doc}, - {"inverse", (PyCFunction) Quaternion_inverse, METH_NOARGS, Quaternion_inverse_doc}, + {"conjugated", (PyCFunction) Quaternion_conjugated, METH_NOARGS, Quaternion_conjugated_doc}, + + {"invert", (PyCFunction) Quaternion_invert, METH_NOARGS, Quaternion_invert_doc}, + {"inverted", (PyCFunction) Quaternion_inverted, METH_NOARGS, Quaternion_inverted_doc}, + {"normalize", (PyCFunction) Quaternion_normalize, METH_NOARGS, Quaternion_normalize_doc}, + {"normalized", (PyCFunction) Quaternion_normalized, METH_NOARGS, Quaternion_normalized_doc}, + + /* return converted representation */ {"to_euler", (PyCFunction) Quaternion_to_euler, METH_VARARGS, Quaternion_to_euler_doc}, {"to_matrix", (PyCFunction) Quaternion_to_matrix, METH_NOARGS, Quaternion_to_matrix_doc}, + + /* operation between 2 or more types */ {"cross", (PyCFunction) Quaternion_cross, METH_O, Quaternion_cross_doc}, {"dot", (PyCFunction) Quaternion_dot, METH_O, Quaternion_dot_doc}, {"difference", (PyCFunction) Quaternion_difference, METH_O, Quaternion_difference_doc}, {"slerp", (PyCFunction) Quaternion_slerp, METH_VARARGS, Quaternion_slerp_doc}, + {"__copy__", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc}, {"copy", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc}, {NULL, NULL, 0, NULL} diff --git a/source/blender/python/generic/mathutils_vector.c b/source/blender/python/generic/mathutils_vector.c index ba5cf4bb317..c39d42e31df 100644 --- a/source/blender/python/generic/mathutils_vector.c +++ b/source/blender/python/generic/mathutils_vector.c @@ -31,9 +31,20 @@ #include "BLI_math.h" #include "BLI_utildefines.h" +#define MAX_DIMENSIONS 4 +#define VEC_APPLY_TO_COPY(vec_meth_noargs, _self) \ + VectorObject *ret= (VectorObject *)Vector_copy(_self); \ + PyObject *ret_dummy= vec_meth_noargs(ret); \ + if(ret_dummy) { \ + Py_DECREF(ret_dummy); \ + return (PyObject *)ret; \ + } \ + else { /* error */ \ + Py_DECREF(ret); \ + return NULL; \ + } \ -#define MAX_DIMENSIONS 4 /* Swizzle axes get packed into a single value that is used as a closure. Each axis uses SWIZZLE_BITS_PER_AXIS bits. The first bit (SWIZZLE_VALID_AXIS) is used as a sentinel: if it is unset, the axis is not valid. */ @@ -41,11 +52,12 @@ #define SWIZZLE_VALID_AXIS 0x4 #define SWIZZLE_AXIS 0x3 +static PyObject *Vector_copy(VectorObject *self); static PyObject *Vector_to_tuple_ext(VectorObject *self, int ndigits); -//----------------------------------mathutils.Vector() ------------------ -// Supports 2D, 3D, and 4D vector objects both int and float values -// accepted. Mixed float and int values accepted. Ints are parsed to float +/* Supports 2D, 3D, and 4D vector objects both int and float values + * accepted. Mixed float and int values accepted. Ints are parsed to float + */ static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *UNUSED(kwds)) { float vec[4]= {0.0f, 0.0f, 0.0f, 0.0f}; @@ -70,27 +82,20 @@ static char Vector_zero_doc[] = ".. method:: zero()\n" "\n" " Set all values to zero.\n" -"\n" -" :return: an instance of itself\n" -" :rtype: :class:`Vector`\n" ; static PyObject *Vector_zero(VectorObject *self) { fill_vn(self->vec, self->size, 0.0f); (void)BaseMath_WriteCallback(self); - Py_INCREF(self); - return (PyObject*)self; + Py_RETURN_NONE; } -/*----------------------------Vector.normalize() ----------------- */ + static char Vector_normalize_doc[] = ".. method:: normalize()\n" "\n" " Normalize the vector, making the length of the vector always 1.0.\n" "\n" -" :return: an instance of itself\n" -" :rtype: :class:`Vector`\n" -"\n" " .. warning:: Normalizing a vector where all values are zero results in all axis having a nan value (not a number).\n" "\n" " .. note:: Normalize works for vectors of all sizes, however 4D Vectors w axis is left untouched.\n" @@ -112,64 +117,72 @@ static PyObject *Vector_normalize(VectorObject *self) } (void)BaseMath_WriteCallback(self); - Py_INCREF(self); - return (PyObject*)self; + Py_RETURN_NONE; +} +static char Vector_normalized_doc[] = +".. method:: normalized()\n" +"\n" +" Return a new, normalized vector.\n" +"\n" +" :return: a normalized copy of the vector\n" +" :rtype: :class:`Vector`\n" +; +static PyObject *Vector_normalized(VectorObject *self) +{ + VEC_APPLY_TO_COPY(Vector_normalize, self); } - -/*----------------------------Vector.resize2D() ------------------ */ -static char Vector_resize2D_doc[] = -".. method:: resize2D()\n" +static char Vector_resize_2d_doc[] = +".. method:: resize_2d()\n" "\n" " Resize the vector to 2D (x, y).\n" "\n" " :return: an instance of itself\n" " :rtype: :class:`Vector`\n" ; -static PyObject *Vector_resize2D(VectorObject *self) +static PyObject *Vector_resize_2d(VectorObject *self) { if(self->wrapped==Py_WRAP) { - PyErr_SetString(PyExc_TypeError, "vector.resize2D(): cannot resize wrapped data - only python vectors"); + PyErr_SetString(PyExc_TypeError, "vector.resize_2d(): cannot resize wrapped data - only python vectors"); return NULL; } if(self->cb_user) { - PyErr_SetString(PyExc_TypeError, "vector.resize2D(): cannot resize a vector that has an owner"); + PyErr_SetString(PyExc_TypeError, "vector.resize_2d(): cannot resize a vector that has an owner"); return NULL; } self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 2)); if(self->vec == NULL) { - PyErr_SetString(PyExc_MemoryError, "vector.resize2D(): problem allocating pointer space"); + PyErr_SetString(PyExc_MemoryError, "vector.resize_2d(): problem allocating pointer space"); return NULL; } self->size = 2; - Py_INCREF(self); - return (PyObject*)self; + Py_RETURN_NONE; } -/*----------------------------Vector.resize3D() ------------------ */ -static char Vector_resize3D_doc[] = -".. method:: resize3D()\n" + +static char Vector_resize_3d_doc[] = +".. method:: resize_3d()\n" "\n" " Resize the vector to 3D (x, y, z).\n" "\n" " :return: an instance of itself\n" " :rtype: :class:`Vector`\n" ; -static PyObject *Vector_resize3D(VectorObject *self) +static PyObject *Vector_resize_3d(VectorObject *self) { if (self->wrapped==Py_WRAP) { - PyErr_SetString(PyExc_TypeError, "vector.resize3D(): cannot resize wrapped data - only python vectors"); + PyErr_SetString(PyExc_TypeError, "vector.resize_3d(): cannot resize wrapped data - only python vectors"); return NULL; } if(self->cb_user) { - PyErr_SetString(PyExc_TypeError, "vector.resize3D(): cannot resize a vector that has an owner"); + PyErr_SetString(PyExc_TypeError, "vector.resize_3d(): cannot resize a vector that has an owner"); return NULL; } self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 3)); if(self->vec == NULL) { - PyErr_SetString(PyExc_MemoryError, "vector.resize3D(): problem allocating pointer space"); + PyErr_SetString(PyExc_MemoryError, "vector.resize_3d(): problem allocating pointer space"); return NULL; } @@ -177,32 +190,31 @@ static PyObject *Vector_resize3D(VectorObject *self) self->vec[2] = 0.0f; self->size = 3; - Py_INCREF(self); - return (PyObject*)self; + Py_RETURN_NONE; } -/*----------------------------Vector.resize4D() ------------------ */ -static char Vector_resize4D_doc[] = -".. method:: resize4D()\n" + +static char Vector_resize_4d_doc[] = +".. method:: resize_4d()\n" "\n" " Resize the vector to 4D (x, y, z, w).\n" "\n" " :return: an instance of itself\n" " :rtype: :class:`Vector`\n" ; -static PyObject *Vector_resize4D(VectorObject *self) +static PyObject *Vector_resize_4d(VectorObject *self) { if(self->wrapped==Py_WRAP) { - PyErr_SetString(PyExc_TypeError, "vector.resize4D(): cannot resize wrapped data - only python vectors"); + PyErr_SetString(PyExc_TypeError, "vector.resize_4d(): cannot resize wrapped data - only python vectors"); return NULL; } if(self->cb_user) { - PyErr_SetString(PyExc_TypeError, "vector.resize4D(): cannot resize a vector that has an owner"); + PyErr_SetString(PyExc_TypeError, "vector.resize_4d(): cannot resize a vector that has an owner"); return NULL; } self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 4)); if(self->vec == NULL) { - PyErr_SetString(PyExc_MemoryError, "vector.resize4D(): problem allocating pointer space"); + PyErr_SetString(PyExc_MemoryError, "vector.resize_4d(): problem allocating pointer space"); return NULL; } if(self->size == 2){ @@ -212,11 +224,60 @@ static PyObject *Vector_resize4D(VectorObject *self) self->vec[3] = 1.0f; } self->size = 4; - Py_INCREF(self); - return (PyObject*)self; + Py_RETURN_NONE; +} +static char Vector_to_2d_doc[] = +".. method:: to_2d()\n" +"\n" +" Return a 2d copy of the vector.\n" +"\n" +" :return: a new vector\n" +" :rtype: :class:`Vector`\n" +; +static PyObject *Vector_to_2d(VectorObject *self) +{ + if(!BaseMath_ReadCallback(self)) + return NULL; + + return newVectorObject(self->vec, 2, Py_NEW, Py_TYPE(self)); +} +static char Vector_to_3d_doc[] = +".. method:: to_3d()\n" +"\n" +" Return a 3d copy of the vector.\n" +"\n" +" :return: a new vector\n" +" :rtype: :class:`Vector`\n" +; +static PyObject *Vector_to_3d(VectorObject *self) +{ + float tvec[3]= {0.0f}; + + if(!BaseMath_ReadCallback(self)) + return NULL; + + memcpy(tvec, self->vec, sizeof(float) * MIN2(self->size, 3)); + return newVectorObject(tvec, 3, Py_NEW, Py_TYPE(self)); +} +static char Vector_to_4d_doc[] = +".. method:: to_4d()\n" +"\n" +" Return a 4d copy of the vector.\n" +"\n" +" :return: a new vector\n" +" :rtype: :class:`Vector`\n" +; +static PyObject *Vector_to_4d(VectorObject *self) +{ + float tvec[4]= {0.0f, 0.0f, 0.0f, 1.0f}; + + if(!BaseMath_ReadCallback(self)) + return NULL; + + memcpy(tvec, self->vec, sizeof(float) * MIN2(self->size, 4)); + return newVectorObject(tvec, 4, Py_NEW, Py_TYPE(self)); } -/*----------------------------Vector.toTuple() ------------------ */ static char Vector_to_tuple_doc[] = ".. method:: to_tuple(precision=-1)\n" "\n" @@ -270,7 +331,6 @@ static PyObject *Vector_to_tuple(VectorObject *self, PyObject *args) return Vector_to_tuple_ext(self, ndigits); } -/*----------------------------Vector.toTrackQuat(track, up) ---------------------- */ static char Vector_to_track_quat_doc[] = ".. method:: to_track_quat(track, up)\n" "\n" @@ -385,10 +445,10 @@ static PyObject *Vector_to_track_quat(VectorObject *self, PyObject *args ) return newQuaternionObject(quat, Py_NEW, NULL); } -/*----------------------------Vector.reflect(mirror) ---------------------- - return a reflected vector on the mirror normal - vec - ((2 * DotVecs(vec, mirror)) * mirror) -*/ +/* + * Vector.reflect(mirror): return a reflected vector on the mirror normal + * vec - ((2 * DotVecs(vec, mirror)) * mirror) + */ static char Vector_reflect_doc[] = ".. method:: reflect(mirror)\n" "\n" @@ -654,7 +714,6 @@ static PyObject *Vector_lerp(VectorObject *self, PyObject *args) return newVectorObject(vec, size, Py_NEW, Py_TYPE(self)); } -/*---------------------------- Vector.rotate(angle, axis) ----------------------*/ static char Vector_rotate_doc[] = ".. function:: rotate(axis, angle)\n" "\n" @@ -696,7 +755,6 @@ static PyObject *Vector_rotate(VectorObject *self, PyObject *args) return (PyObject *)self; } -/*----------------------------Vector.copy() -------------------------------------- */ static char Vector_copy_doc[] = ".. function:: copy()\n" "\n" @@ -715,8 +773,6 @@ static PyObject *Vector_copy(VectorObject *self) return newVectorObject(self->vec, self->size, Py_NEW, Py_TYPE(self)); } -/*----------------------------print object (internal)------------- - print the object to screen */ static PyObject *Vector_repr(VectorObject *self) { PyObject *ret, *tuple; @@ -730,15 +786,13 @@ static PyObject *Vector_repr(VectorObject *self) return ret; } -/*---------------------SEQUENCE PROTOCOLS------------------------ - ----------------------------len(object)------------------------ - sequence length*/ +/* Sequence Protocol */ +/* sequence length len(vector) */ static int Vector_len(VectorObject *self) { return self->size; } -/*----------------------------object[]--------------------------- - sequence accessor (get)*/ +/* sequence accessor (get): vector[index] */ static PyObject *Vector_item(VectorObject *self, int i) { if(i<0) i= self->size-i; @@ -753,8 +807,7 @@ static PyObject *Vector_item(VectorObject *self, int i) return PyFloat_FromDouble(self->vec[i]); } -/*----------------------------object[]------------------------- - sequence accessor (set)*/ +/* sequence accessor (set): vector[index] = value */ static int Vector_ass_item(VectorObject *self, int i, PyObject * ob) { float scalar; @@ -776,8 +829,7 @@ static int Vector_ass_item(VectorObject *self, int i, PyObject * ob) return 0; } -/*----------------------------object[z:y]------------------------ - sequence slice (get) */ +/* sequence slice (get): vector[a:b] */ static PyObject *Vector_slice(VectorObject *self, int begin, int end) { PyObject *tuple; @@ -798,8 +850,7 @@ static PyObject *Vector_slice(VectorObject *self, int begin, int end) return tuple; } -/*----------------------------object[z:y]------------------------ - sequence slice (set) */ +/* sequence slice (set): vector[a:b] = value */ static int Vector_ass_slice(VectorObject *self, int begin, int end, PyObject * seq) { @@ -827,9 +878,9 @@ static int Vector_ass_slice(VectorObject *self, int begin, int end, return 0; } -/*------------------------NUMERIC PROTOCOLS---------------------- - ------------------------obj + obj------------------------------ - addition*/ + +/* Numeric Protocols */ +/* addition: obj + obj */ static PyObject *Vector_add(PyObject * v1, PyObject * v2) { VectorObject *vec1 = NULL, *vec2 = NULL; @@ -856,8 +907,7 @@ static PyObject *Vector_add(PyObject * v1, PyObject * v2) return newVectorObject(vec, vec1->size, Py_NEW, Py_TYPE(v1)); } -/* ------------------------obj += obj------------------------------ - addition in place */ +/* addition in-place: obj += obj */ static PyObject *Vector_iadd(PyObject * v1, PyObject * v2) { VectorObject *vec1 = NULL, *vec2 = NULL; @@ -884,8 +934,7 @@ static PyObject *Vector_iadd(PyObject * v1, PyObject * v2) return v1; } -/*------------------------obj - obj------------------------------ - subtraction*/ +/* subtraction: obj - obj */ static PyObject *Vector_sub(PyObject * v1, PyObject * v2) { VectorObject *vec1 = NULL, *vec2 = NULL; @@ -911,8 +960,7 @@ static PyObject *Vector_sub(PyObject * v1, PyObject * v2) return newVectorObject(vec, vec1->size, Py_NEW, Py_TYPE(v1)); } -/*------------------------obj -= obj------------------------------ - subtraction*/ +/* subtraction in-place: obj -= obj */ static PyObject *Vector_isub(PyObject * v1, PyObject * v2) { VectorObject *vec1= NULL, *vec2= NULL; @@ -1067,8 +1115,7 @@ static PyObject *Vector_mul(PyObject * v1, PyObject * v2) return NULL; } -/*------------------------obj *= obj------------------------------ - in place mulplication */ +/* mulplication in-place: obj *= obj */ static PyObject *Vector_imul(PyObject * v1, PyObject * v2) { VectorObject *vec = (VectorObject *)v1; @@ -1116,8 +1163,7 @@ static PyObject *Vector_imul(PyObject * v1, PyObject * v2) return v1; } -/*------------------------obj / obj------------------------------ - divide*/ +/* divid: obj / obj */ static PyObject *Vector_div(PyObject * v1, PyObject * v2) { int i; @@ -1149,8 +1195,7 @@ static PyObject *Vector_div(PyObject * v1, PyObject * v2) return newVectorObject(vec, vec1->size, Py_NEW, Py_TYPE(v1)); } -/*------------------------obj /= obj------------------------------ - divide*/ +/* divide in-place: obj /= obj */ static PyObject *Vector_idiv(PyObject * v1, PyObject * v2) { int i; @@ -1179,21 +1224,17 @@ static PyObject *Vector_idiv(PyObject * v1, PyObject * v2) return v1; } -/*-------------------------- -obj ------------------------------- +/* -obj returns the negative of this object*/ static PyObject *Vector_neg(VectorObject *self) { - int i; - float vec[4]; + float tvec[MAX_DIMENSIONS]; if(!BaseMath_ReadCallback(self)) return NULL; - for(i = 0; i < self->size; i++){ - vec[i] = -self->vec[i]; - } - - return newVectorObject(vec, self->size, Py_NEW, Py_TYPE(self)); + negate_vn_vn(tvec, self->vec, self->size); + return newVectorObject(tvec, self->size, Py_NEW, Py_TYPE(self)); } /*------------------------vec_magnitude_nosqrt (internal) - for comparing only */ @@ -1209,7 +1250,7 @@ static double vec_magnitude_nosqrt(float *data, int size) /* 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 (double)dot; + return dot; } @@ -2043,28 +2084,34 @@ static char Vector_negate_doc[] = ; static PyObject *Vector_negate(VectorObject *self) { - int i; if(!BaseMath_ReadCallback(self)) return NULL; - for(i = 0; i < self->size; i++) - self->vec[i] = -(self->vec[i]); - + negate_vn(self->vec, self->size); + (void)BaseMath_WriteCallback(self); // already checked for error - - Py_INCREF(self); - return (PyObject*)self; + Py_RETURN_NONE; } static struct PyMethodDef Vector_methods[] = { + /* in place only */ {"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_resize3D_doc}, - {"resize4D", (PyCFunction) Vector_resize4D, METH_NOARGS, Vector_resize4D_doc}, + + /* operate on original or copy */ + {"normalize", (PyCFunction) Vector_normalize, METH_NOARGS, Vector_normalize_doc}, + {"normalized", (PyCFunction) Vector_normalized, METH_NOARGS, Vector_normalized_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}, + {"resize_3d", (PyCFunction) Vector_resize_3d, METH_NOARGS, Vector_resize_3d_doc}, + {"to_4d", (PyCFunction) Vector_to_4d, METH_NOARGS, Vector_to_4d_doc}, + {"resize_4d", (PyCFunction) Vector_resize_4d, METH_NOARGS, Vector_resize_4d_doc}, {"to_tuple", (PyCFunction) Vector_to_tuple, METH_VARARGS, Vector_to_tuple_doc}, {"to_track_quat", (PyCFunction) Vector_to_track_quat, METH_VARARGS, Vector_to_track_quat_doc}, + + /* operation between 2 or more types */ {"reflect", (PyCFunction) Vector_reflect, METH_O, Vector_reflect_doc}, {"cross", (PyCFunction) Vector_cross, METH_O, Vector_cross_doc}, {"dot", (PyCFunction) Vector_dot, METH_O, Vector_dot_doc}, @@ -2073,6 +2120,7 @@ static struct PyMethodDef Vector_methods[] = { {"project", (PyCFunction) Vector_project, METH_O, Vector_project_doc}, {"lerp", (PyCFunction) Vector_lerp, METH_VARARGS, Vector_lerp_doc}, {"rotate", (PyCFunction) Vector_rotate, METH_VARARGS, Vector_rotate_doc}, + {"copy", (PyCFunction) Vector_copy, METH_NOARGS, Vector_copy_doc}, {"__copy__", (PyCFunction) Vector_copy, METH_NOARGS, NULL}, {NULL, NULL, 0, NULL} |