static PyObject* Bar_getspecvarvalm(BarObject *self, double(*valfuncs[])(glp_prob*, int)) { if (!Bar_Valid(self, 1)) return NULL; if (glp_get_num_int(LP) == 0) { PyErr_SetString(PyExc_TypeError, "MIP values require mixed integer problem"); return NULL; } double(*valfunc)(glp_prob*, int) = valfuncs[Bar_Row(self) ? 1 : 0]; return PyFloat_FromDouble(valfunc(LP, Bar_Index(self)+1)); }
static PyObject* Bar_getvarval(BarObject *self, void *closure) { if (!Bar_Valid(self, 1)) return NULL; // Compute what we need to index to get the appropriate function pointer. int isrow = Bar_Row(self) ? 1 : 0; int isdual = closure==NULL ? 0 : 1; int last = self->py_bc->py_lp->last_solver; if (last < 0) last = 0; // If no solver called yet, assume simplex is OK. if (last > 2) { PyErr_Format(PyExc_RuntimeError, "bad internal state for last solver identifier: %d", last); return NULL; } // Get and verify that function pointer. double(*valfunc)(glp_prob*,int) = rowcol_primdual_funcptrs[last*4 + isdual*2 + isrow]; if (valfunc==NULL) { PyErr_SetString(PyExc_RuntimeError, "dual values do not exist for MIP solver"); return NULL; } // Get whatever sort of variable this is and return it. return PyFloat_FromDouble(valfunc(LP, Bar_Index(self)+1)); }
static PyObject* Bar_getspecvarval(BarObject *self, double(*valfuncs[])(glp_prob*, int)) { if (!Bar_Valid(self, 1)) return NULL; double(*valfunc)(glp_prob*, int) = valfuncs[Bar_Row(self) ? 1 : 0]; return PyFloat_FromDouble(valfunc(LP, Bar_Index(self)+1)); }
// funcpctab writes to dst a pc-value table mapping the code in func to the values // returned by valfunc parameterized by arg. The invocation of valfunc to update the // current value is, for each p, // // val = valfunc(func, val, p, 0, arg); // record val as value at p->pc; // val = valfunc(func, val, p, 1, arg); // // where func is the function, val is the current value, p is the instruction being // considered, and arg can be used to further parameterize valfunc. static void funcpctab(Link *ctxt, Pcdata *dst, LSym *func, char *desc, int32 (*valfunc)(Link*, LSym*, int32, Prog*, int32, void*), void* arg) { int dbg, i; int32 oldval, val, started; uint32 delta; vlong pc; Prog *p; // To debug a specific function, uncomment second line and change name. dbg = 0; //dbg = strcmp(func->name, "main.main") == 0; //dbg = strcmp(desc, "pctofile") == 0; ctxt->debugpcln += dbg; dst->n = 0; if(ctxt->debugpcln) Bprint(ctxt->bso, "funcpctab %s [valfunc=%s]\n", func->name, desc); val = -1; oldval = val; if(func->text == nil) { ctxt->debugpcln -= dbg; return; } pc = func->text->pc; if(ctxt->debugpcln) Bprint(ctxt->bso, "%6llux %6d %P\n", pc, val, func->text); started = 0; for(p=func->text; p != nil; p = p->link) { // Update val. If it's not changing, keep going. val = valfunc(ctxt, func, val, p, 0, arg); if(val == oldval && started) { val = valfunc(ctxt, func, val, p, 1, arg); if(ctxt->debugpcln) Bprint(ctxt->bso, "%6llux %6s %P\n", (vlong)p->pc, "", p); continue; } // If the pc of the next instruction is the same as the // pc of this instruction, this instruction is not a real // instruction. Keep going, so that we only emit a delta // for a true instruction boundary in the program. if(p->link && p->link->pc == p->pc) { val = valfunc(ctxt, func, val, p, 1, arg); if(ctxt->debugpcln) Bprint(ctxt->bso, "%6llux %6s %P\n", (vlong)p->pc, "", p); continue; } // The table is a sequence of (value, pc) pairs, where each // pair states that the given value is in effect from the current position // up to the given pc, which becomes the new current position. // To generate the table as we scan over the program instructions, // we emit a "(value" when pc == func->value, and then // each time we observe a change in value we emit ", pc) (value". // When the scan is over, we emit the closing ", pc)". // // The table is delta-encoded. The value deltas are signed and // transmitted in zig-zag form, where a complement bit is placed in bit 0, // and the pc deltas are unsigned. Both kinds of deltas are sent // as variable-length little-endian base-128 integers, // where the 0x80 bit indicates that the integer continues. if(ctxt->debugpcln) Bprint(ctxt->bso, "%6llux %6d %P\n", (vlong)p->pc, val, p); if(started) { addvarint(ctxt, dst, (p->pc - pc) / ctxt->arch->minlc); pc = p->pc; } delta = val - oldval; if(delta>>31) delta = 1 | ~(delta<<1); else delta <<= 1; addvarint(ctxt, dst, delta); oldval = val; started = 1; val = valfunc(ctxt, func, val, p, 1, arg); }