diff --git a/collision.c b/collision.c new file mode 100644 index 0000000..cad3d57 --- /dev/null +++ b/collision.c @@ -0,0 +1,84 @@ +#include "collision.h" + +double sizes[] = {100.0, 10000.0, 1000000.0} + +PyObject* py3dutil_collide(PyObject* self_in, PyObject* args) +{ + ColliderObject* grid; + if (!PyArg_ParseTuple(args, "O!", &Collider)) + return NULL; + + + Collider_unroll(grid); +} + + + + + + +PySequenceMethods Collider_as_seq[] = { + Collider_len, /* sq_length */ + 0, /* sq_concat */ + 0, /* sq_repeat */ + Collider_item, /* sq_item */ + 0, /* sq_slice */ + 0, /* sq_ass_item */ + 0, /* sq_ass_slice */ + Collider_contains, /* sq_contains */ +}; + +PyMethodDef Collider_methods[] = { + {"insert", (PyCFunction)Collider_insert, METH_VARARGS, "allocate the array to a new size"}, + {"delete", (PyCFunction)Collider_delete, METH_VARARGS, "remove a grid cell"}, + {"remove", (PyCFunction)Collider_remove, METH_VARARGS, "remove an object from its grid cell"}, + {NULL} +}; + +struct PyMemberDef Collider_members[] = { + /*{"x", T_OBJECT_EX, offsetof(ColliderObject, x), 0, "x"}, + {"y", T_OBJECT_EX, offsetof(ColliderObject, y), 0, "y"}, + {"z", T_OBJECT_EX, offsetof(ColliderObject, z), 0, "z"},*/ + {NULL} /* Sentinel */ +}; + + +PyTypeObject ColliderObjectType = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "py3dutil.Collider", /* tp_name */ + sizeof(ColliderObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + Collider_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + Collider_repr, /* tp_repr */ + 0, /* tp_as_number */ + Collider_as_seq, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES, /* tp_flags */ + "Vector objects are simple.", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + Collider_methods, /* tp_methods */ + Collider_members, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)Collider_init, /* tp_init */ +}; \ No newline at end of file diff --git a/collision.h b/collision.h new file mode 100644 index 0000000..785b52e --- /dev/null +++ b/collision.h @@ -0,0 +1,38 @@ +#include +#include + +#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) +typedef int Py_ssize_t; +#define PY_SSIZE_T_MAX INT_MAX +#define PY_SSIZE_T_MIN INT_MIN +#endif + +typedef struct rb_red_blk_tree rb_red_blk_tree; +typedef struct ObarrObject ObarrObject; + +typedef struct ColliderObject { + PyObject_HEAD + ObarrObject* pGrids; +} ColliderObject; + +extern PyTypeObject ColliderObjectType; + +#define Collider_Check(op) PyObject_TypeCheck(op, &ColliderObjectType) + + +double sizes[]; + +#define SQR(x) ((x) * (x)) + +/* internal functions */ + + +/* exported API functions */ +int Collider_init(ColliderObject *self, PyObject *args, PyObject *kwds); +void Collider_dealloc(PyObject* self_in); +PyObject* Collider_begin(PyObject *self_in, PyObject *args); +PyObject* Collider_remove(PyObject *self_in, PyObject *args); + +extern PySequenceMethods Collider_as_seq[]; +extern PyMethodDef Collider_methods[]; +extern struct PyMemberDef Collider_members[]; diff --git a/pos.c b/pos.c new file mode 100644 index 0000000..b3a61d6 --- /dev/null +++ b/pos.c @@ -0,0 +1,485 @@ +#include "pos.h" +#include + +#ifdef _MSC_VER +#define isnan(x) ((x) != (x)) +#define isinf(x) ((x) != (x)) +#endif + +#define POSLEN 3 + +#define MATH_PI (atan(1.0)*4.0) +#define RAD2DEG (180.0 / MATH_PI) +#define DEG2RAD (MATH_PI / 180.0) + + + +int Pos_init(PosObject *self, PyObject *args, PyObject *kwds) +{ + double inx, iny, inz; + if (!PyArg_ParseTuple(args, "ddd", &inx, &iny, &inz)) + return -1; + + self->elements[0] = inx; + self->elements[1] = iny; + self->elements[2] = inz; + + return 0; +} + +PyObject* pos_get_element(PyObject* self_in, long index) +{ + PosObject* self = (PosObject*)self_in; + return PyFloat_FromDouble(self->elements[index]); +} + +PyObject* Pos_getx(PyObject* self_in, void* closure) +{ + return pos_get_element(self_in, 0); +} + +PyObject* Pos_gety(PyObject* self_in, void* closure) +{ + return pos_get_element(self_in, 1); +} + +PyObject* Pos_getz(PyObject* self_in, void* closure) +{ + return pos_get_element(self_in, 2); +} + +int Pos_set_notallowed(PyObject* self_in, PyObject* value, void* closure) +{ + PyErr_SetString(PyExc_TypeError, "Poss cannot be set directly"); + return -1; +} + + + +PyObject* Pos_repr(PyObject *self_in) +{ + PosObject *self; + PyObject *tuple, *fmtstring, *reprstring; + + if (!Pos_Check(self_in)) + return PyString_FromString(""); + self = (PosObject*)self_in; + + tuple = Py_BuildValue("(ddd)", self->elements[0], self->elements[1], self->elements[2]); + fmtstring = PyString_FromString("pos(%f, %f, %f)"); + reprstring = PyString_Format(fmtstring, tuple); + Py_DECREF(tuple); + Py_DECREF(fmtstring); + return reprstring; + +} + + +int Pos_true(PyObject *self_in) +{ + PosObject *self = (PosObject*)self_in; + int b = 1; + long i; + double x; + for (i = 0; i < POSLEN; i++) + { + x = self->elements[i]; + b = b && (x == 0.0 || isnan(x) || isinf(x)); + } + + return !b; +} + +PyObject* Pos_add(PyObject *self_in, PyObject *other_in) +{ + PosObject *self, *other, *rv; + long i; + if (!Pos_Check(self_in) || !Pos_Check(other_in)) + { + PyErr_SetString(PyExc_TypeError, "both arguments must be of type 'pos'"); + return NULL; + } + self = (PosObject*)self_in; + other = (PosObject*)other_in; + rv = PyObject_New(PosObject, &PosObjectType); + for (i = 0; i < POSLEN; i++) + rv->elements[i] = self->elements[i] + other->elements[i]; + + return (PyObject*)rv; +} + +PyObject* Pos_sub(PyObject *self_in, PyObject *other_in) +{ + PosObject *self, *other, *rv; + long i; + if (!Pos_Check(self_in) || !Pos_Check(other_in)) + { + PyErr_SetString(PyExc_TypeError, "both arguments must be of type 'pos'"); + return NULL; + } + self = (PosObject*)self_in; + other = (PosObject*)other_in; + rv = PyObject_New(PosObject, &PosObjectType); + for (i = 0; i < POSLEN; i++) + rv->elements[i] = self->elements[i] - other->elements[i]; + + return (PyObject*)rv; +} + +PyObject* Pos_ip_add(PyObject *self_in, PyObject *other_in) +{ + PosObject *self, *other; + long i; + if (!Pos_Check(self_in) || !Pos_Check(other_in)) + { + PyErr_SetString(PyExc_TypeError, "both arguments must be of type 'pos'"); + return NULL; + } + self = (PosObject*)self_in; + other = (PosObject*)other_in; + for (i = 0; i < POSLEN; i++) + self->elements[i] += other->elements[i]; + + Py_INCREF(self); + return (PyObject*)self; +} + +PyObject* Pos_ip_sub(PyObject *self_in, PyObject *other_in) +{ + PosObject *self, *other; + long i; + + if (!Pos_Check(self_in) || !Pos_Check(other_in)) + { + PyErr_SetString(PyExc_TypeError, "both arguments must be of type 'pos'"); + return NULL; + } + self = (PosObject*)self_in; + other = (PosObject*)other_in; + for (i = 0; i < POSLEN; i++) + self->elements[i] -= other->elements[i]; + + Py_INCREF(self); + return (PyObject*)self; +} + + +P/*yObject* Pos_ip_zero(PyObject *self_in, PyObject *unused) +{ + PosObject *self; + long i; + if (!Pos_Check(self_in)) + { + PyErr_SetString(PyExc_TypeError, "not a pos"); + return NULL; + } + self = (PosObject*)self_in; + for (i = 0; i < POSLEN; i++) + self->elements[i] = 0.0; + + Py_INCREF(self); + return (PyObject*)self; +} +*/ + +PyObject* Pos_average(PyObject *self_in, PyObject *args) +{ + PosObject *self, *other, *rv; + long i; + if (!Pos_Check(self_in)) + { + PyErr_SetString(PyExc_TypeError, "not a pos"); + return NULL; + } + self = (PosObject*)self_in; + if (!PyArg_ParseTuple(args, "O!", &PosObjectType, &other)) + { + PyErr_SetString(PyExc_TypeError, "argument is not a pos"); + return NULL; + } + rv = PyObject_New(PosObject, &PosObjectType); + for (i = 0; i < POSLEN; i++) + rv->elements[i] = (self->elements[i] + other->elements[i]) / 2.0; + + return (PyObject*)rv; +} + +PyObject* Pos_dir(PyObject *self_in, PyObject *unused) +{ + PosObject *self; + double d; + long i; + if (!Pos_Check(self_in)) + { + PyErr_SetString(PyExc_TypeError, "not a pos"); + return NULL; + } + self = (PosObject*)self_in; + d = 0.0; + for (i = 0; i < POSLEN; i++) + d += self->elements[i] * self->elements[i]; + + return PyFloat_FromDouble(d); +} + +PyObject* Pos_copy(PyObject *self_in, PyObject *unused) +{ + PosObject *self, *rv; + long i; + if (!Pos_Check(self_in)) + { + PyErr_SetString(PyExc_TypeError, "not a pos"); + return NULL; + } + self = (PosObject*)self_in; + rv = PyObject_New(PosObject, &PosObjectType); + for (i = 0; i < POSLEN; i++) + rv->elements[i] = self->elements[i]; + + return (PyObject*)rv; +} + +PyObject* Pos_dist(PyObject *self_in, PyObject *args) +{ + PosObject *self, *other; + double d, dd; + long i; + if (!Pos_Check(self_in)) + { + PyErr_SetString(PyExc_TypeError, "not a pos"); + return NULL; + } + self = (PosObject*)self_in; + if (!PyArg_ParseTuple(args, "O!", &PosObjectType, &other)) + { + PyErr_SetString(PyExc_TypeError, "argument is not a pos"); + return NULL; + } + d = 0.0; + dd = 0.0; + for (i = 0; i < POSLEN; i++) + { + dd = self->elements[i] - other->elements[i]; + d += dd * dd; + } + + return PyFloat_FromDouble(sqrt(d)); +} + +PyObject* Pos_slerp(PyObject *self_in, PyObject *args) +{ + PosObject *self, *other, *rv; + double amt, oamt; + long i; + if (!Pos_Check(self_in)) + { + PyErr_SetString(PyExc_TypeError, "not a pos"); + return NULL; + } + self = (PosObject*)self_in; + amt = 0.0; + if (!PyArg_ParseTuple(args, "O!d", &PosObjectType, &other, &amt)) + { + PyErr_SetString(PyExc_TypeError, "arguments must be a pos and a float"); + return NULL; + } + oamt = 1.0 - amt; + rv = PyObject_New(PosObject, &PosObjectType); + + for (i = 0; i < POSLEN; i++) + { + rv->elements[i] = (self->elements[i] * oamt) + (other->elements[i] * amt); + } + + return (PyObject*)rv; +} + +PyObject* Pos_sserp(PyObject *self_in, PyObject *args) +{ + PosObject *self, *other, *rv, *norm; + double amt, oamt, smag, omag; + long i; + if (!Pos_Check(self_in)) + { + PyErr_SetString(PyExc_TypeError, "not a pos"); + return NULL; + } + self = (PosObject*)self_in; + amt = 0.0; + if (!PyArg_ParseTuple(args, "O!d", &PosObjectType, &other, &amt)) + { + PyErr_SetString(PyExc_TypeError, "arguments must be a pos and a float"); + return NULL; + } + oamt = 1.0 - amt; + rv = PyObject_New(PosObject, &PosObjectType); + smag = 0.0; + omag = 0.0; + for (i = 0; i < POSLEN; i++) + { + smag += self->elements[i] * self->elements[i]; + omag += other->elements[i] * other->elements[i]; + rv->elements[i] = (self->elements[i] * oamt) + (other->elements[i] * amt); + } + smag = sqrt(smag); + omag = sqrt(omag); + + norm = (PosObject*)Pos_ip_normalize((PyObject*)rv, NULL); + Py_XDECREF(norm); + + for (i = 0; i < POSLEN; i++) + rv->elements[i] *= (smag + omag) / 2.0; + return (PyObject*)rv; +} + + +Py_ssize_t Pos_len(PyObject *self_in) +{ + if (!Pos_Check(self_in)) + { + PyErr_SetString(PyExc_TypeError, "not a pos"); + return -1; + } + return POSLEN; +} + + +PyObject* Pos_item(PyObject *self_in, Py_ssize_t index) +{ + if (!Pos_Check(self_in)) + { + PyErr_SetString(PyExc_TypeError, "not a pos"); + return NULL; + } + if (index < 0 || index >= POSLEN) + { + PyErr_SetString(PyExc_IndexError, "index not in range"); + return NULL; + } + + return pos_get_element(self_in, index); + +} + + + + +PyNumberMethods Pos_as_number[] = { + Pos_add, /* nb_add */ + Pos_sub, /* nb_subtract */ + 0, /* nb_multiply */ + 0, /* nb_divide */ + 0, /* nb_remainder */ + 0, /* nb_divmod */ + 0, /* nb_power */ + 0, /* nb_negative */ + 0, /* nb_positive */ + 0, /* nb_absolute */ + Pos_true, /* nb_nonzero */ + 0, /* nb_invert */ + 0, /* nb_lshift */ + 0, /* nb_rshift */ + 0, /* nb_and */ + 0, /* nb_xor */ + 0, /* nb_or */ + 0, /* nb_coerce */ + 0, /* nb_int */ + 0, /* nb_long */ + 0, /* nb_float */ + 0, /* nb_oct */ + 0, /* nb_hex */ + Pos_ip_add, /* nb_inplace_add */ + Pos_ip_sub, /* nb_inplace_subtract */ + 0, /* nb_inplace_multiply */ + 0, /* nb_inplace_divide */ + 0, /* nb_inplace_remainder */ + 0, /* nb_inplace_power */ + 0, /* nb_inplace_lshift */ + 0, /* nb_inplace_rshift */ + 0, /* nb_inplace_and */ + 0, /* nb_inplace_xor */ + 0, /* nb_inplace_or */ + 0, /* nb_floordiv */ + 0, /* nb_truediv */ + 0, /* nb_inplace_floordiv */ + 0, /* nb_inplace_truediv */ + +}; + +PySequenceMethods Pos_as_seq[] = { + Pos_len, /* sq_length */ + 0, /* sq_concat */ + 0, /* sq_repeat */ + Pos_item, /* sq_item */ + 0, /* sq_slice */ + 0, /* sq_ass_item */ + 0, /* sq_ass_slice */ + 0, /* sq_contains */ +}; + +PyGetSetDef Pos_getset[] = { + {"x", Pos_getx, Pos_set_notallowed, "x", NULL}, + {"y", Pos_gety, Pos_set_notallowed, "y", NULL}, + {"z", Pos_getz, Pos_set_notallowed, "z", NULL}, + {NULL} +}; + +PyMethodDef Pos_methods[] = { + {"__add__", (PyCFunction)Pos_add, METH_O|METH_COEXIST, "add two poss"}, + {"__sub__", (PyCFunction)Pos_sub, METH_O|METH_COEXIST, "subtract two poss"}, +/* {"zero", (PyCFunction)Pos_ip_zero, METH_NOARGS, "sets all pos components to 0"},*/ + {"avg", (PyCFunction)Pos_average, METH_VARARGS, "find halfway between this and another pos"}, + {"dist", (PyCFunction)Pos_dist, METH_VARARGS, "compute the distance between this and another pos"}, + {"copy", (PyCFunction)Pos_copy, METH_NOARGS, "makes a copy"}, + {"slerp", (PyCFunction)Pos_slerp, METH_VARARGS, "spherical linear interpolation"}, + {"sserp", (PyCFunction)Pos_sserp, METH_VARARGS, "spherical spherical interpolation"}, + {NULL} +}; + +struct PyMemberDef Pos_members[] = { + /*{"x", T_OBJECT_EX, offsetof(PosObject, x), 0, "x"}, + {"y", T_OBJECT_EX, offsetof(PosObject, y), 0, "y"}, + {"z", T_OBJECT_EX, offsetof(PosObject, z), 0, "z"},*/ + {NULL} /* Sentinel */ +}; + + +PyTypeObject PosObjectType = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "py3dutil.pos", /* tp_name */ + sizeof(PosObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + Pos_repr, /* tp_repr */ + Pos_as_number, /* tp_as_number */ + Pos_as_seq, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES, /* tp_flags */ + "Pos objects are simple.", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + Pos_methods, /* tp_methods */ + Pos_members, /* tp_members */ + Pos_getset, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)Pos_init, /* tp_init */ +}; \ No newline at end of file diff --git a/pos.h b/pos.h new file mode 100644 index 0000000..f3df54a --- /dev/null +++ b/pos.h @@ -0,0 +1,55 @@ +#include +#include + +#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) +typedef int Py_ssize_t; +#define PY_SSIZE_T_MAX INT_MAX +#define PY_SSIZE_T_MIN INT_MIN +#endif + +#define POSLEN 3 + + +typedef struct PosObject { + PyObject_HEAD + double elements[POSLEN]; +} PosObject; + + +#define Pos_Check(op) PyObject_TypeCheck(op, &PosObjectType) + + +// internal functions +PyObject* pos_get_element(PyObject* self_in, long index); + +// Python API functions +int Pos_init(PosObject *self, PyObject *args, PyObject *kwds); +PyObject* Pos_getx(PyObject* self_in, void* closure); +PyObject* Pos_gety(PyObject* self_in, void* closure); +PyObject* Pos_getz(PyObject* self_in, void* closure); +int Pos_set_notallowed(PyObject* self_in, PyObject* value, void* closure); +PyObject* Pos_repr(PyObject *self_in); +int Pos_true(PyObject *self_in); +PyObject* Pos_add(PyObject *self_in, PyObject *other_in); +PyObject* Pos_sub(PyObject *self_in, PyObject *other_in); +PyObject* Pos_ip_add(PyObject *self_in, PyObject *other_in); +PyObject* Pos_ip_sub(PyObject *self_in, PyObject *other_in); +PyObject* Pos_ip_zero(PyObject *self_in, PyObject *unused); +PyObject* Pos_average(PyObject *self_in, PyObject *args); +PyObject* Pos_copy(PyObject *self_in, PyObject *unused); +PyObject* Pos_dist(PyObject *self_in, PyObject *args); +PyObject* Pos_slerp(PyObject *self_in, PyObject *args); +PyObject* Pos_sserp(PyObject *self_in, PyObject *args); +Py_ssize_t Pos_len(PyObject *self_in); +PyObject* Pos_item(PyObject *self_in, Py_ssize_t index); + + + + + +extern PyNumberMethods Pos_as_number[]; +extern PySequenceMethods Pos_as_seq[]; +extern PyGetSetDef Pos_getset[]; +extern PyMethodDef Pos_methods[]; +extern struct PyMemberDef Pos_members[]; +extern PyTypeObject PosObjectType; diff --git a/quat.h b/quat.h index 0132808..8a620af 100644 --- a/quat.h +++ b/quat.h @@ -1,36 +1,36 @@ #include -#include -#include "vect.h" - -#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) -typedef int Py_ssize_t; -#define PY_SSIZE_T_MAX INT_MAX -#define PY_SSIZE_T_MIN INT_MIN -#endif +#include +#include "vect.h" + +#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) +typedef int Py_ssize_t; +#define PY_SSIZE_T_MAX INT_MAX +#define PY_SSIZE_T_MIN INT_MIN +#endif typedef struct QuatObject { PyObject_HEAD double elements[4]; -} QuatObject; - +} QuatObject; + #define Quat_Check(op) PyObject_TypeCheck(op, &QuatObjectType) - -// internal functions -PyObject* quat_get_element(PyObject* self_in, long index); -void quat_multiply_internal(QuatObject* q1, QuatObject* q2, QuatObject* qr); -void quat_multiply_vect_internal(QuatObject* self, VectObject* v, VectObject* rv); -double quat_mag_internal(QuatObject* self); -double quat_mag2_internal(QuatObject* self); -void quat_normalize_internal(QuatObject* self); -void quat_get_conjugate_internal(QuatObject* self, QuatObject* rv); - + +// internal functions +PyObject* quat_get_element(PyObject* self_in, long index); +void quat_multiply_internal(QuatObject* q1, QuatObject* q2, QuatObject* qr); +void quat_multiply_vect_internal(QuatObject* self, VectObject* v, VectObject* rv); +double quat_mag_internal(QuatObject* self); +double quat_mag2_internal(QuatObject* self); +void quat_normalize_internal(QuatObject* self); +void quat_get_conjugate_internal(QuatObject* self, QuatObject* rv); + // Python API functions int Quat_init(QuatObject *self, PyObject *args, PyObject *kwds); PyObject* Quat_getx(PyObject* self_in, void* closure); -PyObject* Quat_gety(PyObject* self_in, void* closure); -PyObject* Quat_getz(PyObject* self_in, void* closure); -PyObject* Quat_getw(PyObject* self_in, void* closure); +PyObject* Quat_gety(PyObject* self_in, void* closure); +PyObject* Quat_getz(PyObject* self_in, void* closure); +PyObject* Quat_getw(PyObject* self_in, void* closure); int Quat_set_notallowed(PyObject* self_in, PyObject* value, void* closure); PyObject* Quat_repr(PyObject *self_in); int Quat_true(PyObject *self_in); @@ -46,11 +46,11 @@ PyObject* Quat_slerp(PyObject *self_in, PyObject *args); PyObject* Quat_slerp_turn(PyObject *self_in, PyObject *args); Py_ssize_t Quat_len(PyObject *self_in); PyObject* Quat_item(PyObject *self_in, Py_ssize_t index); - - - - - + + + + + extern PyNumberMethods Quat_as_number[]; extern PySequenceMethods Quat_as_seq[]; extern PyGetSetDef Quat_getset[];