/* * Implement the ternary operator MAD (multiply-add) * mad(a, b, c) returns (a*b)+c */ PyObject *mad(PyObject *self, PyObject *args) { int i, length = -1; float *arrays[3], f[3]; int which = 0; extern void doMADvvv(), doMADvvs(), doMADvsv(), doMADvss(), doMADsvv(), doMADsvs(), doMADssv(); utility funcs[7] = { doMADvvv, doMADvvs, doMADvsv, doMADvss, doMADsvv, doMADsvs, doMADssv }; if (PyTuple_Size(args) != 3) { PyErr_SetString(PyExc_TypeError, "too few arguments"); return NULL; } // decide if each argument is a scalar or a vector, compute 'which' and // set up 'arrays' for (i = 0; i < 3; i++) { PyObject *it = PyTuple_GetItem(args, i); if (Vop_Check(it)) { // First vector: set the length. For subsequent vectors, // want to check that they have matching length if (length == -1) length = Vop_truelength(it); else if (length != Vop_truelength(it)) { PyErr_SetString(PyExc_TypeError, "mismatching lengths"); return NULL; } arrays[i] = ((Vop*)it)->data; } else if (PyFloat_Check(it)) { f[i] = PyFloat_AsDouble(it); arrays[i] = &f[i]; which += (4 >> i); } else { PyErr_SetString(PyExc_TypeError, "expecting vector or float"); return NULL; } } if (which < 7) { Vop *r = (Vop*)Vop_NEW(length); odometer += 3 * length; (funcs[which])(r->data, arrays, length); return (PyObject *)r; } else { // all scalar arguments, so just do the operation here return PyFloat_FromDouble(f[0] * f[1] + f[2]); } }