/* optimize float array or complex array to a scalar power */ static PyObject * fast_scalar_power(PyArrayObject *a1, PyObject *o2, int inplace) { double exp; if (PyArray_Check(a1) && array_power_is_scalar(o2, &exp)) { PyObject *fastop = NULL; if (PyArray_ISFLOAT(a1) || PyArray_ISCOMPLEX(a1)) { if (exp == 1.0) { /* we have to do this one special, as the "copy" method of array objects isn't set up early enough to be added by PyArray_SetNumericOps. */ if (inplace) { Py_INCREF(a1); return (PyObject *)a1; } else { return PyArray_Copy(a1); } } else if (exp == -1.0) { fastop = n_ops.reciprocal; } else if (exp == 0.0) { fastop = n_ops.ones_like; } else if (exp == 0.5) { fastop = n_ops.sqrt; } else if (exp == 2.0) { fastop = n_ops.square; } else { return NULL; } if (inplace) { return PyArray_GenericInplaceUnaryFunction(a1, fastop); } else { return PyArray_GenericUnaryFunction(a1, fastop); } } else if (exp==2.0) { fastop = n_ops.multiply; if (inplace) { return PyArray_GenericInplaceBinaryFunction (a1, (PyObject *)a1, fastop); } else { return PyArray_GenericBinaryFunction (a1, (PyObject *)a1, fastop); } } } return NULL; }
static PyObject * array_true_divide(PyArrayObject *m1, PyObject *m2) { PyObject *res; BINOP_GIVE_UP_IF_NEEDED(m1, m2, nb_true_divide, array_true_divide); if (PyArray_CheckExact(m1) && (PyArray_ISFLOAT(m1) || PyArray_ISCOMPLEX(m1)) && try_binary_elide(m1, m2, &array_inplace_true_divide, &res, 0)) { return res; } return PyArray_GenericBinaryFunction(m1, m2, n_ops.true_divide); }
fvec_t * PyAubio_ArrayToCFvec (PyObject *input) { PyObject *array; fvec_t *vec; if (input == NULL) { PyErr_SetString (PyExc_ValueError, "input array is not a python object"); goto fail; } // parsing input object into a Py_fvec if (PyArray_Check(input)) { // we got an array, convert it to an fvec if (PyArray_NDIM (input) == 0) { PyErr_SetString (PyExc_ValueError, "input array is a scalar"); goto fail; } else if (PyArray_NDIM (input) > 1) { PyErr_SetString (PyExc_ValueError, "input array has more than one dimensions"); goto fail; } if (!PyArray_ISFLOAT (input)) { PyErr_SetString (PyExc_ValueError, "input array should be float"); goto fail; } else if (PyArray_TYPE (input) != AUBIO_NPY_SMPL) { PyErr_SetString (PyExc_ValueError, "input array should be float32"); goto fail; } else { // input data type is float32, nothing else to do array = input; } // vec = new_fvec (vec->length); // no need to really allocate fvec, just its struct member vec = (fvec_t *)malloc(sizeof(fvec_t)); vec->length = PyArray_SIZE (array); vec->data = (smpl_t *) PyArray_GETPTR1 (array, 0); } else if (PyObject_TypeCheck (input, &PyList_Type)) { PyErr_SetString (PyExc_ValueError, "does not convert from list yet"); return NULL; } else { PyErr_SetString (PyExc_ValueError, "can only accept vector of float as input"); return NULL; } return vec; fail: return NULL; }
/* gets warm starts from warm dict, doesn't destroy input warm start data */ static scs_int getWarmStart(char * key, scs_float ** x, scs_int l, PyObject * warm) { PyArrayObject *x0 = (PyArrayObject *) PyDict_GetItemString(warm, key); *x = scs_calloc(l, sizeof(scs_float)); if (x0) { if (!PyArray_ISFLOAT(x0) || PyArray_NDIM(x0) != 1 || PyArray_DIM(x0, 0) != l) { PySys_WriteStderr("Error parsing warm-start input\n"); return 0; } else { PyArrayObject * px0 = getContiguous(x0, getFloatType()); memcpy(*x, (scs_float *) PyArray_DATA(px0), l * sizeof(scs_float)); Py_DECREF(px0); return 1; } } return 0; }
static int array_power_is_scalar(PyObject *o2, double* exp) { PyObject *temp; const int optimize_fpexps = 1; if (PyInt_Check(o2)) { *exp = (double)PyInt_AsLong(o2); return 1; } if (optimize_fpexps && PyFloat_Check(o2)) { *exp = PyFloat_AsDouble(o2); return 1; } if ((PyArray_IsZeroDim(o2) && ((PyArray_ISINTEGER(o2) || (optimize_fpexps && PyArray_ISFLOAT(o2))))) || PyArray_IsScalar(o2, Integer) || (optimize_fpexps && PyArray_IsScalar(o2, Floating))) { temp = o2->ob_type->tp_as_number->nb_float(o2); if (temp != NULL) { *exp = PyFloat_AsDouble(o2); Py_DECREF(temp); return 1; } } #if (PY_VERSION_HEX >= 0x02050000) if (PyIndex_Check(o2)) { PyObject* value = PyNumber_Index(o2); Py_ssize_t val; if (value==NULL) { if (PyErr_Occurred()) { PyErr_Clear(); } return 0; } val = PyInt_AsSsize_t(value); if (val == -1 && PyErr_Occurred()) { PyErr_Clear(); return 0; } *exp = (double) val; return 1; } #endif return 0; }
static int array_power_is_scalar(PyObject *o2, double* out_exponent) { PyObject *temp; const int optimize_fpexps = 1; if (PyInt_Check(o2)) { *out_exponent = (double)PyInt_AsLong(o2); return NPY_INTPOS_SCALAR; } if (optimize_fpexps && PyFloat_Check(o2)) { *out_exponent = PyFloat_AsDouble(o2); return NPY_FLOAT_SCALAR; } if ((PyArray_IsZeroDim(o2) && ((PyArray_ISINTEGER((PyArrayObject *)o2) || (optimize_fpexps && PyArray_ISFLOAT((PyArrayObject *)o2))))) || PyArray_IsScalar(o2, Integer) || (optimize_fpexps && PyArray_IsScalar(o2, Floating))) { temp = Py_TYPE(o2)->tp_as_number->nb_float(o2); if (temp != NULL) { *out_exponent = PyFloat_AsDouble(o2); Py_DECREF(temp); if (PyArray_IsZeroDim(o2)) { if (PyArray_ISINTEGER((PyArrayObject *)o2)) { return NPY_INTPOS_SCALAR; } else { /* ISFLOAT */ return NPY_FLOAT_SCALAR; } } else if PyArray_IsScalar(o2, Integer) { return NPY_INTPOS_SCALAR; } else { /* IsScalar(o2, Floating) */ return NPY_FLOAT_SCALAR;
static PyObject *csolve(PyObject* self, PyObject *args, PyObject *kwargs) { /* Expects a function call * sol = csolve((m,n,p),c,Gx,Gi,Gp,h,dims,Ax,Ai,Ap,b,verbose) * where * * the triple (m,n,p) corresponds to: * `m`: the rows of G * `n`: the cols of G and A, must agree with the length of c * `p`: the rows of A * `c` is a Numpy array of doubles * "G" is a sparse matrix in column compressed storage. "Gx" are the values, * "Gi" are the rows, and "Gp" are the column pointers. * `Gx` is a Numpy array of doubles * `Gi` is a Numpy array of ints * `Gp` is a Numpy array of ints * `h` is a Numpy array * `dims` is a dictionary with * `dims['l']` an integer specifying the dimension of positive orthant cone * `dims['q']` an *list* specifying dimensions of second-order cones * * "A" is an optional sparse matrix in column compressed storage. "Ax" are * the values, "Ai" are the rows, and "Ap" are the column pointers. * `Ax` is a Numpy array of doubles * `Ai` is a Numpy array of ints * `Ap` is a Numpy array of ints * `b` is an optional argument, which is a Numpy array of doubles * `verbose` is an optional bool signaling whether to print info * * This call will solve the problem * * minimize c'*x * subject to A*x = b * h - G*x \in K * * The code returns a Python dictionary with five keys, 'x', 'y', 'info', 's', * and 'z'. These correspond to the following: * * `x`: primal variables * `y`: dual variables for equality constraints * `s`: slacks for Gx + s <= h, s \in K * `z`: dual variables for inequality constraints s \in K * `info`: another dictionary with the following fields: * exitflag: 0=OPTIMAL, 1=PRIMAL INFEASIBLE, 2=DUAL INFEASIBLE, -1=MAXIT REACHED * infostring: gives information about the status of solution * pcost: value of primal objective * dcost: value of dual objective * pres: primal residual on inequalities and equalities * dres: dual residual * pinf: primal infeasibility measure * dinf: dual infeasibility measure * pinfres: NaN * dinfres: 3.9666e+15 * gap: duality gap * relgap: relative duality gap * r0: ??? * numerr: numerical error? * iter: number of iterations * timing: dictionary with timing information */ /* data structures for arguments */ //matrix *c, *h, *b = NULL; //spmatrix *G, *A = NULL; PyArrayObject *Gx, *Gi, *Gp, *c, *h; PyArrayObject *Ax = NULL; PyArrayObject *Ai = NULL; PyArrayObject *Ap = NULL; PyArrayObject *b = NULL; PyObject *dims, *verbose = NULL; idxint n; // number or variables idxint m; // number of conic variables idxint p = 0; // number of equality constraints idxint ncones = 0; // number of cones idxint numConicVariables = 0; /* ECOS data structures */ idxint l = 0; idxint *q = NULL; pfloat *Gpr = NULL; idxint *Gjc = NULL; idxint *Gir = NULL; pfloat *Apr = NULL; idxint *Ajc = NULL; idxint *Air = NULL; pfloat *cpr = NULL; pfloat *hpr = NULL; pfloat *bpr = NULL; pwork* mywork; idxint i; static char *kwlist[] = {"shape", "c", "Gx", "Gi", "Gp", "h", "dims", "Ax", "Ai", "Ap", "b", "verbose", NULL}; // parse the arguments and ensure they are the correct type #ifdef DLONG static char *argparse_string = "(lll)O!O!O!O!O!O!|O!O!O!O!O!"; #else static char *argparse_string = "(iii)O!O!O!O!O!O!|O!O!O!O!O!"; #endif if( !PyArg_ParseTupleAndKeywords(args, kwargs, argparse_string, kwlist, &m, &n, &p, &PyArray_Type, &c, &PyArray_Type, &Gx, &PyArray_Type, &Gi, &PyArray_Type, &Gp, &PyArray_Type, &h, &PyDict_Type, &dims, &PyArray_Type, &Ax, &PyArray_Type, &Ai, &PyArray_Type, &Ap, &PyArray_Type, &b, &PyBool_Type, &verbose) ) { return NULL; } if (m < 0) { PyErr_SetString(PyExc_ValueError, "m must be a positive integer"); return NULL; } if (n < 0) { PyErr_SetString(PyExc_ValueError, "n must be a positive integer"); return NULL; } if (p < 0) { PyErr_SetString(PyExc_ValueError, "p must be a positive integer"); return NULL; } /* get the typenum for the primitive int and double types */ int intType = getIntType(); int doubleType = getDoubleType(); /* set G */ if( !PyArray_ISFLOAT(Gx) || PyArray_NDIM(Gx) != 1) { PyErr_SetString(PyExc_TypeError, "Gx must be a numpy array of floats"); return NULL; } if( !PyArray_ISINTEGER(Gi) || PyArray_NDIM(Gi) != 1) { PyErr_SetString(PyExc_TypeError, "Gi must be a numpy array of ints"); return NULL; } if( !PyArray_ISINTEGER(Gp) || PyArray_NDIM(Gp) != 1) { PyErr_SetString(PyExc_TypeError, "Gp must be a numpy array of ints"); return NULL; } PyArrayObject *Gx_arr = getContiguous(Gx, doubleType); PyArrayObject *Gi_arr = getContiguous(Gi, intType); PyArrayObject *Gp_arr = getContiguous(Gp, intType); Gpr = (pfloat *) PyArray_DATA(Gx_arr); Gir = (idxint *) PyArray_DATA(Gi_arr); Gjc = (idxint *) PyArray_DATA(Gp_arr); /* set c */ if (!PyArray_ISFLOAT(c) || PyArray_NDIM(c) != 1) { PyErr_SetString(PyExc_TypeError, "c must be a dense numpy array with one dimension"); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); return NULL; } if (PyArray_DIM(c,0) != n){ PyErr_SetString(PyExc_ValueError, "c has incompatible dimension with G"); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); return NULL; } PyArrayObject *c_arr = getContiguous(c, doubleType); cpr = (pfloat *) PyArray_DATA(c_arr); /* set h */ if (!PyArray_ISFLOAT(h) || PyArray_NDIM(h) != 1) { PyErr_SetString(PyExc_TypeError, "h must be a dense numpy array with one dimension"); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); Py_DECREF(c_arr); return NULL; } if (PyArray_DIM(h,0) != m){ PyErr_SetString(PyExc_ValueError, "h has incompatible dimension with G"); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); Py_DECREF(c_arr); return NULL; } PyArrayObject *h_arr = getContiguous(h, doubleType); hpr = (pfloat *) PyArray_DATA(h_arr); /* get dims['l'] */ PyObject *linearObj = PyDict_GetItemString(dims, "l"); if(linearObj) { if(PyInt_Check(linearObj) && ((l = (idxint) PyInt_AsLong(linearObj)) >= 0)) { numConicVariables += l; } else { PyErr_SetString(PyExc_TypeError, "dims['l'] ought to be a nonnegative integer"); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); Py_DECREF(c_arr); Py_DECREF(h_arr); return NULL; } } /* get dims['q'] */ PyObject *socObj = PyDict_GetItemString(dims, "q"); if(socObj) { if (PyList_Check(socObj)) { ncones = PyList_Size(socObj); q = calloc(ncones, sizeof(idxint)); for (i = 0; i < ncones; ++i) { PyObject *qi = PyList_GetItem(socObj, i); if(PyInt_Check(qi) && ((q[i] = (idxint) PyInt_AsLong(qi)) > 0)) { numConicVariables += q[i]; } else { PyErr_SetString(PyExc_TypeError, "dims['q'] ought to be a list of positive integers"); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); Py_DECREF(c_arr); Py_DECREF(h_arr); return NULL; } } } else { PyErr_SetString(PyExc_TypeError, "dims['q'] ought to be a list"); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); Py_DECREF(c_arr); Py_DECREF(h_arr); return NULL; } } PyArrayObject *Ax_arr = NULL; PyArrayObject *Ai_arr = NULL; PyArrayObject *Ap_arr = NULL; PyArrayObject *b_arr = NULL; if(Ax && Ai && Ap && b) { /* set A */ if( !PyArray_ISFLOAT(Ax) || PyArray_NDIM(Ax) != 1 ) { PyErr_SetString(PyExc_TypeError, "Ax must be a numpy array of floats"); if(q) free(q); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); Py_DECREF(c_arr); Py_DECREF(h_arr); return NULL; } if( !PyArray_ISINTEGER(Ai) || PyArray_NDIM(Ai) != 1) { PyErr_SetString(PyExc_TypeError, "Ai must be a numpy array of ints"); if(q) free(q); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); Py_DECREF(c_arr); Py_DECREF(h_arr); return NULL; } if( !PyArray_ISINTEGER(Ap) || PyArray_NDIM(Ap) != 1) { PyErr_SetString(PyExc_TypeError, "Ap must be a numpy array of ints"); if(q) free(q); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); Py_DECREF(c_arr); Py_DECREF(h_arr); return NULL; } // if ((SpMatrix_Check(A) && SP_ID(A) != DOUBLE)){ // PyErr_SetString(PyExc_TypeError, "A must be a sparse 'd' matrix"); // if(q) free(q); // Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); // Py_DECREF(c_arr); Py_DECREF(h_arr); // return NULL; // } // if ((p = SP_NROWS(A)) < 0) { // PyErr_SetString(PyExc_ValueError, "p must be a nonnegative integer"); // if(q) free(q); // Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); // Py_DECREF(c_arr); Py_DECREF(h_arr); // return NULL; // } // if (SP_NCOLS(A) != n) { // PyErr_SetString(PyExc_ValueError, "A has incompatible dimension with c"); // if(q) free(q); // Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); // Py_DECREF(c_arr); Py_DECREF(h_arr); // return NULL; // } // if (p != 0) { // Apr = SP_VALD(A); // Air = SP_ROW(A); // Ajc = SP_COL(A); // } Ax_arr = getContiguous(Ax, doubleType); Ai_arr = getContiguous(Ai, intType); Ap_arr = getContiguous(Ap, intType); Apr = (pfloat *) PyArray_DATA(Ax_arr); Air = (idxint *) PyArray_DATA(Ai_arr); Ajc = (idxint *) PyArray_DATA(Ap_arr); /* set b */ // if (!Matrix_Check(b) || MAT_NCOLS(b) != 1 || MAT_ID(b) != DOUBLE) { // PyErr_SetString(PyExc_TypeError, "b must be a dense 'd' matrix with one column"); // if(q) free(q); // return NULL; // } // if (MAT_NROWS(b) != p){ // PyErr_SetString(PyExc_ValueError, "b has incompatible dimension with A"); // if(q) free(q); // return NULL; // } // if (p != 0) { // bpr = MAT_BUFD(b); // } if (!PyArray_ISFLOAT(b) || PyArray_NDIM(b) != 1) { PyErr_SetString(PyExc_TypeError, "b must be a dense numpy array with one dimension"); if(q) free(q); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); Py_DECREF(c_arr); Py_DECREF(h_arr); Py_DECREF(Ax_arr); Py_DECREF(Ai_arr); Py_DECREF(Ap_arr); return NULL; } if (PyArray_DIM(b,0) != p){ PyErr_SetString(PyExc_ValueError, "b has incompatible dimension with A"); if(q) free(q); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); Py_DECREF(c_arr); Py_DECREF(h_arr); Py_DECREF(Ax_arr); Py_DECREF(Ai_arr); Py_DECREF(Ap_arr); return NULL; } b_arr = getContiguous(b, doubleType); bpr = (pfloat *) PyArray_DATA(b_arr); } else if (Ax || Ai || Ap || b) { // check that A and b are both supplied PyErr_SetString(PyExc_ValueError, "A and b arguments must be supplied together"); if(q) free(q); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); Py_DECREF(c_arr); Py_DECREF(h_arr); return NULL; } /* check that sum(q) + l = m */ if( numConicVariables != m ){ PyErr_SetString(PyExc_ValueError, "Number of rows of G does not match dims.l+sum(dims.q)"); if (q) free(q); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); Py_DECREF(c_arr); Py_DECREF(h_arr); if (b_arr) Py_DECREF(b_arr); if (Ax_arr) Py_DECREF(Ax_arr); if (Ai_arr) Py_DECREF(Ai_arr); if (Ap_arr) Py_DECREF(Ap_arr); return NULL; } /* This calls ECOS setup function. */ mywork = ECOS_setup(n, m, p, l, ncones, q, Gpr, Gjc, Gir, Apr, Ajc, Air, cpr, hpr, bpr); if( mywork == NULL ){ PyErr_SetString(PyExc_RuntimeError, "Internal problem occurred in ECOS while setting up the problem.\nPlease send a bug report with data to Alexander Domahidi.\nEmail: [email protected]"); if(q) free(q); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); Py_DECREF(c_arr); Py_DECREF(h_arr); if (b_arr) Py_DECREF(b_arr); if (Ax_arr) Py_DECREF(Ax_arr); if (Ai_arr) Py_DECREF(Ai_arr); if (Ap_arr) Py_DECREF(Ap_arr); return NULL; } /* Set settings for ECOS. */ if(verbose) { mywork->stgs->verbose = (idxint) PyObject_IsTrue(verbose); } /* Solve! */ idxint exitcode = ECOS_solve(mywork); /* create output (all data is *deep copied*) */ // TODO: request CVXOPT API for constructing from existing pointer /* x */ // matrix *x; // if(!(x = Matrix_New(n,1,DOUBLE))) // return PyErr_NoMemory(); // memcpy(MAT_BUFD(x), mywork->x, n*sizeof(double)); npy_intp veclen[1]; veclen[0] = n; PyObject *x = PyArray_SimpleNewFromData(1, veclen, NPY_DOUBLE, mywork->x); /* y */ // matrix *y; // if(!(y = Matrix_New(p,1,DOUBLE))) // return PyErr_NoMemory(); // memcpy(MAT_BUFD(y), mywork->y, p*sizeof(double)); veclen[0] = p; PyObject *y = PyArray_SimpleNewFromData(1, veclen, NPY_DOUBLE, mywork->y); /* info dict */ // infostring const char* infostring; switch( exitcode ){ case ECOS_OPTIMAL: infostring = "Optimal solution found"; break; case ECOS_MAXIT: infostring = "Maximum number of iterations reached"; break; case ECOS_PINF: infostring = "Primal infeasible"; break; case ECOS_DINF: infostring = "Dual infeasible"; break; case ECOS_NUMERICS: infostring = "Run into numerical problems"; break; case ECOS_OUTCONE: infostring = "PROBLEM: Multipliers leaving the cone"; break; default: infostring = "UNKNOWN PROBLEM IN SOLVER"; } // numerical errors idxint numerr = 0; if( (exitcode == ECOS_NUMERICS) || (exitcode == ECOS_OUTCONE) || (exitcode == ECOS_FATAL) ){ numerr = 1; } // timings #if PROFILING > 0 PyObject *tinfos = Py_BuildValue( #if PROFILING > 1 "{s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d}", #else "{s:d,s:d,s:d}", #endif #if PROFILING > 1 "tkktcreate",(double)mywork->info->tkktcreate, "tkktsolve",(double)mywork->info->tkktsolve, "tkktfactor",(double)mywork->info->tfactor, "torder",(double)mywork->info->torder, "ttranspose",(double)mywork->info->ttranspose, #endif "runtime",(double)mywork->info->tsolve + (double)mywork->info->tsetup, "tsetup",(double)mywork->info->tsetup, "tsolve",(double)mywork->info->tsolve); #endif PyObject *infoDict = Py_BuildValue( #if PROFILING > 0 "{s:l,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:l,s:s,s:O,s:l}", #else "{s:l,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:l,s:s,s:l}", #endif "exitFlag", exitcode, "pcost", (double)mywork->info->pcost, "dcost", (double)mywork->info->dcost, "pres", (double)mywork->info->pres, "dres", (double)mywork->info->dres, "pinf", (double)mywork->info->pinf, "dinf", (double)mywork->info->dinf, "pinfres",(double)mywork->info->pinfres, "dinfres",(double)mywork->info->dinfres, "gap",(double)mywork->info->gap, "relgap",(double)mywork->info->relgap, "r0",(double)mywork->stgs->feastol, "iter",mywork->info->iter, "infostring",infostring, #if PROFILING > 0 "timing", tinfos, #endif "numerr",numerr); #if PROFILING > 0 // give reference to infoDict Py_DECREF(tinfos); #endif /* s */ // matrix *s; // if(!(s = Matrix_New(m,1,DOUBLE))) // return PyErr_NoMemory(); // memcpy(MAT_BUFD(s), mywork->s, m*sizeof(double)); veclen[0] = m; PyObject *s = PyArray_SimpleNewFromData(1, veclen, NPY_DOUBLE, mywork->s); /* z */ // matrix *z; // if(!(z = Matrix_New(m,1,DOUBLE))) // return PyErr_NoMemory(); // memcpy(MAT_BUFD(z), mywork->z, m*sizeof(double)); veclen[0] = m; PyObject *z = PyArray_SimpleNewFromData(1, veclen, NPY_DOUBLE, mywork->z); /* cleanup */ ECOS_cleanup(mywork, 4); PyObject *returnDict = Py_BuildValue( "{s:O,s:O,s:O,s:O,s:O}", "x",x, "y",y, "z",z, "s",s, "info",infoDict); // give up ownership to the return dictionary Py_DECREF(x); Py_DECREF(y); Py_DECREF(z); Py_DECREF(s); Py_DECREF(infoDict); // no longer need pointers to arrays that held primitives if(q) free(q); Py_DECREF(Gx_arr); Py_DECREF(Gi_arr); Py_DECREF(Gp_arr); Py_DECREF(c_arr); Py_DECREF(h_arr); if (b_arr) Py_DECREF(b_arr); if (Ax_arr) Py_DECREF(Ax_arr); if (Ai_arr) Py_DECREF(Ai_arr); if (Ap_arr) Py_DECREF(Ap_arr); return returnDict; }
/* * optimize float array or complex array to a scalar power * returns 0 on success, -1 if no optimization is possible * the result is in value (can be NULL if an error occurred) */ static int fast_scalar_power(PyArrayObject *a1, PyObject *o2, int inplace, PyObject **value) { double exponent; NPY_SCALARKIND kind; /* NPY_NOSCALAR is not scalar */ if (PyArray_Check(a1) && !PyArray_ISOBJECT(a1) && ((kind=is_scalar_with_conversion(o2, &exponent))>0)) { PyObject *fastop = NULL; if (PyArray_ISFLOAT(a1) || PyArray_ISCOMPLEX(a1)) { if (exponent == 1.0) { fastop = n_ops.positive; } else if (exponent == -1.0) { fastop = n_ops.reciprocal; } else if (exponent == 0.0) { fastop = n_ops._ones_like; } else if (exponent == 0.5) { fastop = n_ops.sqrt; } else if (exponent == 2.0) { fastop = n_ops.square; } else { return -1; } if (inplace || can_elide_temp_unary(a1)) { *value = PyArray_GenericInplaceUnaryFunction(a1, fastop); } else { *value = PyArray_GenericUnaryFunction(a1, fastop); } return 0; } /* Because this is called with all arrays, we need to * change the output if the kind of the scalar is different * than that of the input and inplace is not on --- * (thus, the input should be up-cast) */ else if (exponent == 2.0) { fastop = n_ops.square; if (inplace) { *value = PyArray_GenericInplaceUnaryFunction(a1, fastop); } else { /* We only special-case the FLOAT_SCALAR and integer types */ if (kind == NPY_FLOAT_SCALAR && PyArray_ISINTEGER(a1)) { PyArray_Descr *dtype = PyArray_DescrFromType(NPY_DOUBLE); a1 = (PyArrayObject *)PyArray_CastToType(a1, dtype, PyArray_ISFORTRAN(a1)); if (a1 != NULL) { /* cast always creates a new array */ *value = PyArray_GenericInplaceUnaryFunction(a1, fastop); Py_DECREF(a1); } } else { *value = PyArray_GenericUnaryFunction(a1, fastop); } } return 0; } } /* no fast operation found */ return -1; }
/* * Determine if object is a scalar and if so, convert the object * to a double and place it in the out_exponent argument * and return the "scalar kind" as a result. If the object is * not a scalar (or if there are other error conditions) * return NPY_NOSCALAR, and out_exponent is undefined. */ static NPY_SCALARKIND is_scalar_with_conversion(PyObject *o2, double* out_exponent) { PyObject *temp; const int optimize_fpexps = 1; if (PyInt_Check(o2)) { *out_exponent = (double)PyInt_AsLong(o2); return NPY_INTPOS_SCALAR; } if (optimize_fpexps && PyFloat_Check(o2)) { *out_exponent = PyFloat_AsDouble(o2); return NPY_FLOAT_SCALAR; } if (PyArray_Check(o2)) { if ((PyArray_NDIM((PyArrayObject *)o2) == 0) && ((PyArray_ISINTEGER((PyArrayObject *)o2) || (optimize_fpexps && PyArray_ISFLOAT((PyArrayObject *)o2))))) { temp = Py_TYPE(o2)->tp_as_number->nb_float(o2); if (temp == NULL) { return NPY_NOSCALAR; } *out_exponent = PyFloat_AsDouble(o2); Py_DECREF(temp); if (PyArray_ISINTEGER((PyArrayObject *)o2)) { return NPY_INTPOS_SCALAR; } else { /* ISFLOAT */ return NPY_FLOAT_SCALAR; } } } else if (PyArray_IsScalar(o2, Integer) || (optimize_fpexps && PyArray_IsScalar(o2, Floating))) { temp = Py_TYPE(o2)->tp_as_number->nb_float(o2); if (temp == NULL) { return NPY_NOSCALAR; } *out_exponent = PyFloat_AsDouble(o2); Py_DECREF(temp); if (PyArray_IsScalar(o2, Integer)) { return NPY_INTPOS_SCALAR; } else { /* IsScalar(o2, Floating) */ return NPY_FLOAT_SCALAR; } } else if (PyIndex_Check(o2)) { PyObject* value = PyNumber_Index(o2); Py_ssize_t val; if (value==NULL) { if (PyErr_Occurred()) { PyErr_Clear(); } return NPY_NOSCALAR; } val = PyInt_AsSsize_t(value); if (error_converting(val)) { PyErr_Clear(); return NPY_NOSCALAR; } *out_exponent = (double) val; return NPY_INTPOS_SCALAR; } return NPY_NOSCALAR; }
static PyObject *csolve(PyObject *self, PyObject *args, PyObject *kwargs) { /* data structures for arguments */ PyArrayObject *Ax, *Ai, *Ap, *c, *b; PyObject *cone, *warm = SCS_NULL; PyObject *verbose = SCS_NULL; PyObject *normalize = SCS_NULL; /* get the typenum for the primitive scs_int and scs_float types */ int scs_intType = getIntType(); int scs_floatType = getFloatType(); struct ScsPyData ps = { SCS_NULL, SCS_NULL, SCS_NULL, SCS_NULL, SCS_NULL, }; /* scs data structures */ Data *d = scs_calloc(1, sizeof(Data)); Cone *k = scs_calloc(1, sizeof(Cone)); AMatrix *A; Sol sol = {0}; Info info; char *kwlist[] = {"shape", "Ax", "Ai", "Ap", "b", "c", "cone", "warm", "verbose", "normalize", "max_iters", "scale", "eps", "cg_rate", "alpha", "rho_x", SCS_NULL}; /* parse the arguments and ensure they are the correct type */ #ifdef DLONG #ifdef FLOAT char *argparse_string = "(ll)O!O!O!O!O!O!|O!O!O!lfffff"; char *outarg_string = "{s:l,s:l,s:f,s:f,s:f,s:f,s:f,s:f,s:f,s:f,s:f,s:s}"; #else char *argparse_string = "(ll)O!O!O!O!O!O!|O!O!O!lddddd"; char *outarg_string = "{s:l,s:l,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:s}"; #endif #else #ifdef FLOAT char *argparse_string = "(ii)O!O!O!O!O!O!|O!O!O!ifffff"; char *outarg_string = "{s:i,s:i,s:f,s:f,s:f,s:f,s:f,s:f,s:f,s:f,s:f,s:s}"; #else char *argparse_string = "(ii)O!O!O!O!O!O!|O!O!O!iddddd"; char *outarg_string = "{s:i,s:i,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:s}"; #endif #endif npy_intp veclen[1]; PyObject *x, *y, *s, *returnDict, *infoDict; d->stgs = scs_malloc(sizeof(Settings)); /* set defaults */ setDefaultSettings(d); if (!PyArg_ParseTupleAndKeywords( args, kwargs, argparse_string, kwlist, &(d->m), &(d->n), &PyArray_Type, &Ax, &PyArray_Type, &Ai, &PyArray_Type, &Ap, &PyArray_Type, &b, &PyArray_Type, &c, &PyDict_Type, &cone, &PyDict_Type, &warm, &PyBool_Type, &verbose, &PyBool_Type, &normalize, &(d->stgs->max_iters), &(d->stgs->scale), &(d->stgs->eps), &(d->stgs->cg_rate), &(d->stgs->alpha), &(d->stgs->rho_x))) { PySys_WriteStderr("error parsing inputs\n"); return SCS_NULL; } if (d->m < 0) { PyErr_SetString(PyExc_ValueError, "m must be a positive integer"); return SCS_NULL; } if (d->n < 0) { PyErr_SetString(PyExc_ValueError, "n must be a positive integer"); return SCS_NULL; } /* set A */ if (!PyArray_ISFLOAT(Ax) || PyArray_NDIM(Ax) != 1) { return finishWithErr(d, k, &ps, "Ax must be a numpy array of floats"); } if (!PyArray_ISINTEGER(Ai) || PyArray_NDIM(Ai) != 1) { return finishWithErr(d, k, &ps, "Ai must be a numpy array of ints"); } if (!PyArray_ISINTEGER(Ap) || PyArray_NDIM(Ap) != 1) { return finishWithErr(d, k, &ps, "Ap must be a numpy array of ints"); } ps.Ax = getContiguous(Ax, scs_floatType); ps.Ai = getContiguous(Ai, scs_intType); ps.Ap = getContiguous(Ap, scs_intType); A = scs_malloc(sizeof(AMatrix)); A->n = d->n; A->m = d->m; A->x = (scs_float *)PyArray_DATA(ps.Ax); A->i = (scs_int *)PyArray_DATA(ps.Ai); A->p = (scs_int *)PyArray_DATA(ps.Ap); d->A = A; /*d->Anz = d->Ap[d->n]; */ /*d->Anz = PyArray_DIM(Ai,0); */ /* set c */ if (!PyArray_ISFLOAT(c) || PyArray_NDIM(c) != 1) { return finishWithErr( d, k, &ps, "c must be a dense numpy array with one dimension"); } if (PyArray_DIM(c, 0) != d->n) { return finishWithErr(d, k, &ps, "c has incompatible dimension with A"); } ps.c = getContiguous(c, scs_floatType); d->c = (scs_float *)PyArray_DATA(ps.c); /* set b */ if (!PyArray_ISFLOAT(b) || PyArray_NDIM(b) != 1) { return finishWithErr( d, k, &ps, "b must be a dense numpy array with one dimension"); } if (PyArray_DIM(b, 0) != d->m) { return finishWithErr(d, k, &ps, "b has incompatible dimension with A"); } ps.b = getContiguous(b, scs_floatType); d->b = (scs_float *)PyArray_DATA(ps.b); if (getPosIntParam("f", &(k->f), 0, cone) < 0) { return finishWithErr(d, k, &ps, "failed to parse cone field f"); } if (getPosIntParam("l", &(k->l), 0, cone) < 0) { return finishWithErr(d, k, &ps, "failed to parse cone field l"); } if (getConeArrDim("q", &(k->q), &(k->qsize), cone) < 0) { return finishWithErr(d, k, &ps, "failed to parse cone field q"); } if (getConeArrDim("s", &(k->s), &(k->ssize), cone) < 0) { return finishWithErr(d, k, &ps, "failed to parse cone field s"); } if (getConeFloatArr("p", &(k->p), &(k->psize), cone) < 0) { return finishWithErr(d, k, &ps, "failed to parse cone field p"); } if (getPosIntParam("ep", &(k->ep), 0, cone) < 0) { return finishWithErr(d, k, &ps, "failed to parse cone field ep"); } if (getPosIntParam("ed", &(k->ed), 0, cone) < 0) { return finishWithErr(d, k, &ps, "failed to parse cone field ed"); } d->stgs->verbose = verbose ? (scs_int)PyObject_IsTrue(verbose) : VERBOSE; d->stgs->normalize = normalize ? (scs_int)PyObject_IsTrue(normalize) : NORMALIZE; if (d->stgs->max_iters < 0) { return finishWithErr(d, k, &ps, "max_iters must be positive"); } if (d->stgs->scale < 0) { return finishWithErr(d, k, &ps, "scale must be positive"); } if (d->stgs->eps < 0) { return finishWithErr(d, k, &ps, "eps must be positive"); } if (d->stgs->cg_rate < 0) { return finishWithErr(d, k, &ps, "cg_rate must be positive"); } if (d->stgs->alpha < 0) { return finishWithErr(d, k, &ps, "alpha must be positive"); } if (d->stgs->rho_x < 0) { return finishWithErr(d, k, &ps, "rho_x must be positive"); } /* parse warm start if set */ d->stgs->warm_start = WARM_START; if (warm) { d->stgs->warm_start = getWarmStart("x", &(sol.x), d->n, warm); d->stgs->warm_start |= getWarmStart("y", &(sol.y), d->m, warm); d->stgs->warm_start |= getWarmStart("s", &(sol.s), d->m, warm); } Py_BEGIN_ALLOW_THREADS /* Solve! */ scs(d, k, &sol, &info); Py_END_ALLOW_THREADS /* create output (all data is *deep copied*) */ /* x */ /* matrix *x; */ /* if(!(x = Matrix_New(n,1,DOUBLE))) */ /* return PyErr_NoMemory(); */ /* memcpy(MAT_BUFD(x), mywork->x, n*sizeof(scs_float)); */ veclen[0] = d->n; x = PyArray_SimpleNewFromData(1, veclen, scs_floatType, sol.x); PyArray_ENABLEFLAGS((PyArrayObject *)x, NPY_ARRAY_OWNDATA); /* y */ /* matrix *y; */ /* if(!(y = Matrix_New(p,1,DOUBLE))) */ /* return PyErr_NoMemory(); */ /* memcpy(MAT_BUFD(y), mywork->y, p*sizeof(scs_float)); */ veclen[0] = d->m; y = PyArray_SimpleNewFromData(1, veclen, scs_floatType, sol.y); PyArray_ENABLEFLAGS((PyArrayObject *)y, NPY_ARRAY_OWNDATA); /* s */ /* matrix *s; */ /* if(!(s = Matrix_New(m,1,DOUBLE))) */ /* return PyErr_NoMemory(); */ /* memcpy(MAT_BUFD(s), mywork->s, m*sizeof(scs_float)); */ veclen[0] = d->m; s = PyArray_SimpleNewFromData(1, veclen, scs_floatType, sol.s); PyArray_ENABLEFLAGS((PyArrayObject *)s, NPY_ARRAY_OWNDATA); infoDict = Py_BuildValue( outarg_string, "statusVal", (scs_int)info.statusVal, "iter", (scs_int)info.iter, "pobj", (scs_float)info.pobj, "dobj", (scs_float)info.dobj, "resPri", (scs_float)info.resPri, "resDual", (scs_float)info.resDual, "relGap", (scs_float)info.relGap, "resInfeas", (scs_float)info.resInfeas, "resUnbdd", (scs_float)info.resUnbdd, "solveTime", (scs_float)(info.solveTime), "setupTime", (scs_float)(info.setupTime), "status", info.status); returnDict = Py_BuildValue("{s:O,s:O,s:O,s:O}", "x", x, "y", y, "s", s, "info", infoDict); /* give up ownership to the return dictionary */ Py_DECREF(x); Py_DECREF(y); Py_DECREF(s); Py_DECREF(infoDict); /* no longer need pointers to arrays that held primitives */ freePyData(d, k, &ps); return returnDict; }
/* optimize float array or complex array to a scalar power */ static PyObject * fast_scalar_power(PyArrayObject *a1, PyObject *o2, int inplace) { double exponent; NPY_SCALARKIND kind; /* NPY_NOSCALAR is not scalar */ if (PyArray_Check(a1) && ((kind=is_scalar_with_conversion(o2, &exponent))>0)) { PyObject *fastop = NULL; if (PyArray_ISFLOAT(a1) || PyArray_ISCOMPLEX(a1)) { if (exponent == 1.0) { /* we have to do this one special, as the "copy" method of array objects isn't set up early enough to be added by PyArray_SetNumericOps. */ if (inplace) { Py_INCREF(a1); return (PyObject *)a1; } else { return PyArray_Copy(a1); } } else if (exponent == -1.0) { fastop = n_ops.reciprocal; } else if (exponent == 0.0) { fastop = n_ops._ones_like; } else if (exponent == 0.5) { fastop = n_ops.sqrt; } else if (exponent == 2.0) { fastop = n_ops.square; } else { return NULL; } if (inplace) { return PyArray_GenericInplaceUnaryFunction(a1, fastop); } else { return PyArray_GenericUnaryFunction(a1, fastop); } } /* Because this is called with all arrays, we need to * change the output if the kind of the scalar is different * than that of the input and inplace is not on --- * (thus, the input should be up-cast) */ else if (exponent == 2.0) { fastop = n_ops.multiply; if (inplace) { return PyArray_GenericInplaceBinaryFunction (a1, (PyObject *)a1, fastop); } else { PyArray_Descr *dtype = NULL; PyObject *res; /* We only special-case the FLOAT_SCALAR and integer types */ if (kind == NPY_FLOAT_SCALAR && PyArray_ISINTEGER(a1)) { dtype = PyArray_DescrFromType(NPY_DOUBLE); a1 = (PyArrayObject *)PyArray_CastToType(a1, dtype, PyArray_ISFORTRAN(a1)); if (a1 == NULL) { return NULL; } } else { Py_INCREF(a1); } res = PyArray_GenericBinaryFunction(a1, (PyObject *)a1, fastop); Py_DECREF(a1); return res; } } } return NULL; }
PyObject *wrap_vis_sim(PyObject *self, PyObject *args){ PyArrayObject *baseline, *src_dir, *src_int, *src_index, *freqs, *mfreqs, *beam_arr; PyArrayObject *vis_array; npy_intp N_fq, N_src, d0, d1, N_beam_fq, l, m; npy_float lmin, lmax, mmin, mmax, beamfqmin, beamfqmax; if(!PyArg_ParseTuple(args, "O!O!O!O!O!O!O!ffffff", &PyArray_Type, &baseline, &PyArray_Type, &src_dir, &PyArray_Type, &src_int, &PyArray_Type, &src_index, &PyArray_Type, &freqs, &PyArray_Type, &mfreqs, &PyArray_Type, &beam_arr, &lmin, &lmax, &mmin, &mmax, &beamfqmin, &beamfqmax)){ return NULL; } N_fq = PyArray_Size((PyObject *)freqs); N_src = PyArray_Size((PyObject *)src_int); //if the baseline is not 3 numbers, raise an error if (PyArray_Size((PyObject *)baseline) != 3){ PyErr_Format(PyExc_ValueError, "Baseline vector length must be 3"); return NULL; } //Check that there is one src_index for each source if (PyArray_Size((PyObject *)src_index) != N_src){ PyErr_Format(PyExc_ValueError, "src_index.size != src_int.size"); return NULL; } //Check that the length of mfreqs = the number of sources if (PyArray_Size((PyObject *)mfreqs) != N_src){ PyErr_Format(PyExc_ValueError, "mfreqs.size != src_int.size"); return NULL; } //Check that src_dir is 2 dimensional, and one dimension is 3 long and the other is equal to N_src if (PyArray_NDIM(src_dir) != 2){ PyErr_Format(PyExc_ValueError, "src_dir must be 2 dimensional"); return NULL; } else{ d0 = PyArray_DIM(src_dir, 0); d1 = PyArray_DIM(src_dir, 1); } if (!((d0 == N_src) && (d1 == (npy_intp) 3))){ PyErr_Format(PyExc_ValueError, "src_dir must have 0th dimension = the length of src_int, and 1st dimension = 3"); return NULL; } //Check that beam_arr is 3 dimensional. If it is, set l, m, and N_beam_fq if (PyArray_NDIM(beam_arr) != 3){ PyErr_Format(PyExc_ValueError, "beam_arr must be 3 dimensional"); return NULL; } else{ l = PyArray_DIM(beam_arr, 0); m = PyArray_DIM(beam_arr, 1); N_beam_fq = PyArray_DIM(beam_arr, 2); } //Check the type of the array inputs if (! (PyArray_ISFLOAT((PyObject *) baseline) && (PyArray_ISFLOAT((PyObject *) src_dir)) && (PyArray_ISFLOAT((PyObject *) src_int)) && (PyArray_ISFLOAT((PyObject *) src_index)) && (PyArray_ISFLOAT((PyObject *) freqs)) && (PyArray_ISFLOAT((PyObject *) mfreqs)) && (PyArray_ISFLOAT((PyObject *) beam_arr)))){ PyErr_Format(PyExc_ValueError, "All arrays must be of floats"); return NULL; } //Create the array to hold the output vis_array = (PyArrayObject *) PyArray_SimpleNew(PyArray_NDIM(freqs), PyArray_DIMS(freqs), NPY_CFLOAT); vis_sim( (float *)PyArray_DATA(baseline), // access pointer to data buffer, cast as floats (float *)PyArray_DATA(src_dir), (float *)PyArray_DATA(src_int), (float *)PyArray_DATA(src_index), (float *)PyArray_DATA(freqs), (float *)PyArray_DATA(mfreqs), (float *)PyArray_DATA(vis_array), (float *)PyArray_DATA(beam_arr), l, m, N_beam_fq, lmin, lmax, mmin, mmax, beamfqmin, beamfqmax, N_fq, N_src // pass pointer to sum buffer to hold result ); return PyArray_Return(vis_array); }
int isFloat( void* arr ) { return (int) PyArray_ISFLOAT( arr ); }