Category talk:Wren-linear

From Rosetta Code

Linear Algebra

There have been several RC tasks where the use of linear algebra solvers has produced results much more quickly than more basic algorithms and the purpose of this module is to provide such functionality for the Wren programmer.

Rather than try to write a solver from scratch in Wren itself which would be very difficult and relatively slow, I've decided instead to write a Wren wrapper for most of the GNU Linear Programming Kit (GLPK) - only the more advanced routines have been omitted. Although not the fastest solver available, GLPK is open source, well documented and written in Ansi C which makes it a good fit for solving smaller problems using Wren.

Despite its C heritage, GLPK uses 1-based arrays but, as a convenience feature, one can pass Wren's normal zero-based lists to the C wrapper and the underlying C code will change them to 1-based before passing them to the API functions themselves.

Whilst calling API functions directly is usually faster, it is also possible to write problems using GLPK's MathProg language and then process these using methods in the Tran class. This is far easier when there are a large number of variables and/or constraints to deal with.

Source code (Wren)

<lang ecmascript>/* Module "linear.wren" */

/* Glp contains various glpk constants and miscellaneous methods. */ class Glp {

   /* optimization direction flag */
   static MIN { 1 }  // minimization
   static MAX { 2 }  // maximization
   /* kind of structural variable */
   static CV { 1 }  // continuous
   static IV { 2 }  // integer
   static BV { 3 }  // binary
   /* type of auxiliary/structural variable */
   static FR { 1 }  // free (unbounded)
   static LO { 2 }  // has lower bound
   static UP { 3 }  // has upper bound
   static DB { 4 }  // has double bound
   static FX { 5 }  // fixed
    /* status of auxiliary/structural variable */
   static BS { 1 }  // basic
   static NL { 2 }  // non-basic on lower bound
   static NU { 3 }  // non-basic on upper bound
   static NF { 4 }  // non-basic free (unbounded)
   static NS { 5 }  // non-basic fixed
    /* scaling options */
   static SF_GM   { 0x01 }  // geometric mean
   static SF_EQ   { 0x10 }  // equilibration
   static SF_2N   { 0x20 }  // power of two
   static SF_SKIP { 0x40 }  // skip if well scaled
   static SF_AUTO { 0x80 }  // automatic
   /* solution indicator */
   static SOL { 1 }  // basic
   static IPT { 2 }  // interior-point
   static MIP { 3 }  // mixed integer
   /* solution status */
   static UNDEF  { 1 }  // undefined
   static FEAS   { 2 }  // feasible
   static INFEAS { 3 }  // infeasible
   static NOFEAS { 4 }  // no feasible exists
   static OPT    { 5 }  // optimal
   static UNBND  { 6 }  // unbounded
   /* simplex solver control message level */
   static MSG_OFF { 0 }  // no output
   static MSG_ERR { 1 }  // warning and error messages only
   static MSG_ON  { 2 }  // normal output
   static MSG_ALL { 3 }  // full output
   static MSG_DBG { 4 }  // debug output
   /* simplex solver control method option */
   static PRIMAL { 1 }  // use primal
   static DUALP  { 2 }  // use dual; if it fails, use primal
   static DUAL   { 3 }  // use dual
   /* simplex solver control pricing technique */
   static PT_STD { 0x11 }  // standard (Dantzig's rule)
   static PT_PSE { 0x22 }  // projected steepest edge
   /* simplex solver control ratio test technique */
   static RT_STD { 0x11 }  // standard (textbook)
   static RT_HAR { 0x22 }  // Harris' two-pass
   /* interior-point solver control ordering algorithm */
   static ORD_NONE   { 0 }  // natural (original) ordering
   static ORD_QMD    { 1 }  // quotient minimum degree (QMD)
   static ORD_AMD    { 2 }  // approx. minimum degree (AMD)
   static ORD_SYMAMD { 3 }  // approx. minimum degree (SYMAMD)
   /* integer optimizer control branching technique */
   static BR_FFV { 1 }  // first fractional variable
   static BR_LFV { 2 }  // last fractional variable
   static BR_MFV { 3 }  // most fractional variable
   static BR_DTH { 4 }  // heuristic by Driebeck and Tomlin
   static BR_PCH { 5 }  // hybrid pseudocost heuristic
   /* integer optimizer control backtracking technique */
   static BT_DFS { 1 }  // depth first search
   static BT_BFS { 2 }  // breadth first search
   static BT_BLB { 3 }  // best local bound
   static BT_BPH { 4 }  // best projection heuristic
   /* integer optimizer control preprocessing technique */
   static PP_NONE { 0 }  // disable preprocessing
   static PP_ROOT { 1 }  // preprocessing only on root level
   static PP_ALL  { 2 }  // preprocessing on all levels
   /* enable/disable flag */
   static ON  { 1 }  // enable something
   static OFF { 0 }  // disable something
   /* return codes */
   static EBADB   { 0x01 }  // invalid basis
   static ESING   { 0x02 }  // singular matrix
   static ECOND   { 0x03 }  // ill-conditioned matrix
   static EBOUND  { 0x04 }  // invalid bounds
   static EFAIL   { 0x05 }  // solver failed
   static EOBJLL  { 0x06 }  // objective lower limit reached
   static EOBJUL  { 0x07 }  // objective upper limit reached
   static EITLIM  { 0x08 }  // iteration limit exceeded
   static ETMLIM  { 0x09 }  // time limit exceeded
   static ENOPFS  { 0x0A }  // no primal feasible solution
   static ENODFS  { 0x0B }  // no dual feasible solution
   static EROOT   { 0x0C }  // root LP optimum not provided
   static ESTOP   { 0x0D }  // search terminated by application
   static EMIPGAP { 0x0E }  // relative mip gap tolerance reached
   static ENOFEAS { 0x0F }  // no primal/dual feasible solution
   static ENOCVG  { 0x10 }  // no convergence
   static EINSTAB { 0x11 }  // numerical instability
   static EDATA   { 0x12 }  // invalid data
   static ERANGE  { 0x13 }  // result out of range
   /* condition indicator */
   static KKT_PE { 1 }  // primal equalities
   static KKT_PB { 2 }  // primal bounds
   static KKT_DE { 3 }  // dual equalities
   static KKT_DB { 4 }  // dual bounds
   static KKT_CS { 5 }  // complementary slackness
   /* MPS file format */
   static MPS_DECK { 1 }  // fixed (ancient)
   static MPS_FILE { 2 }  // free (modern)
   /* Miscellaneous methods */
   foreign static checkDup(m, n, ne, ia, ja)
   foreign static initEnv()
   foreign static version
   foreign static freeEnv()
   foreign static termOut(flag)

}

/* Prob represents an optimization problem. */ foreign class Prob {

   construct create() {}
   foreign setProbName(name)
   foreign setObjName(name)
   foreign setObjDir(dir)
   foreign addRows(nrs)
   foreign addCols(ncs)
   foreign setRowName(i, name)
   foreign setColName(j, name)
   foreign setRowBnds(i, type, lb, ub)
   foreign setColBnds(j, type, lb, ub)
   foreign setObjCoef(j, coef)
   foreign setMatRow(i, len, ind, val)
   foreign setMatCol(j, len, ind, val)
   foreign loadMatrix(ne, ia, ja, ar)
   foreign sortMatrix()
   foreign delRows(nrs, num)
   foreign delCols(ncs, num)
   foreign copy(names)
   foreign erase()
   foreign delete()
   foreign probName
   foreign objName
   foreign objDir
   foreign numRows
   foreign numCols
   foreign rowName(i)
   foreign colName(j)
   foreign rowType(i)
   foreign rowLB(i)
   foreign rowUB(i)
   foreign colType(j)
   foreign colLB(j)
   foreign colUB(j)
   foreign objCoef(j)
   foreign numNZ
   foreign matRow(i, ind, val)
   foreign matCol(j, ind, val)
   foreign createIndex()
   foreign findRow(name)
   foreign findCol(name)
   foreign deleteIndex()
   foreign setRii(i, rii)
   foreign setSjj(j, sjj)
   foreign rii(i)
   foreign sjj(j)
   foreign scale(flags)
   foreign unscale()
   foreign setRowStat(i, stat)
   foreign setColStat(j, stat)
   foreign stdBasis()
   foreign advBasis()
   foreign cpxBasis()
   foreign simplex(parm)
   foreign exact(parm)
   foreign status
   foreign primStat
   foreign dualStat
   foreign objVal
   foreign rowStat(i)
   foreign rowPrim(i)
   foreign rowDual(i)
   foreign colStat(j)
   foreign colPrim(j)
   foreign colDual(j)
   foreign unbndRay
   foreign interior(parm)
   foreign iptStatus
   foreign iptObjVal
   foreign iptRowPrim(i)
   foreign iptRowDual(i)
   foreign iptColPrim(j)
   foreign iptColDual(j)
   foreign setColKind(j, kind)
   foreign colKind(j)
   foreign numInt
   foreign numBin
   foreign intOpt(parm)
   foreign mipStatus
   foreign mipObjVal
   foreign mipRowVal(i)
   foreign mipColVal(j)
   foreign checkKKT(sol, cond, aeMax, aeInd, reMax, reInd)
   foreign readMPS(format, fname)
   foreign writeMPS(format, fname)
   foreign readLP(fname)
   foreign writeLP(fname)
   foreign readProb(fname)
   foreign writeProb(fname)
   foreign printSol(fname)
   foreign readSol(fname)
   foreign writeSol(fname)
   foreign printIpt(fname)
   foreign readIpt(fname)
   foreign writeIpt(fname)
   foreign printMip(fname)
   foreign readMip(fname)
   foreign writeMip(fname)
   foreign printRanges(len, list, fname)

}

/* Smcp represents simplex solver control parameters. */ foreign class Smcp {

   construct init() {} 
   foreign meth
   foreign msgLev
   foreign pricing
   foreign rTest
   foreign meth=(m)
   foreign msgLev=(l)
   foreign pricing=(p)
   foreign rTest=(r)

}

/* Iptcp represents interior-point solver control parameters. */ foreign class Iptcp {

   construct init() {}
   foreign msgLev
   foreign ordAlg
   foreign msgLev=(l)
   foreign ordAlg=(o)

}

/* Iocp represents MIP solver control parameters. */ foreign class Iocp {

   construct init() {}
   foreign msgLev
   foreign brTech
   foreign btTech
   foreign ppTech
   foreign presolve
   foreign msgLev=(l)
   foreign brTech=(b)
   foreign btTech=(b)
   foreign ppTech=(p)
   foreign presolve=(b)

}

/* Tran contains routines for processing MathProg models. */ foreign class Tran {

   construct mplAllocWksp() {}
   foreign mplInitRand(seed)
   foreign mplReadModel(fname, skip)
   foreign mplReadData(fname)
   foreign mplGenerate(fname)
   foreign mplBuildProb(p)
   foreign mplPostSolve(p, sol)
   foreign mplFreeWksp()

} /* File contains routines for writing text to a

  temporary file and removing it when no longer needed. */

class File {

   foreign static write(fname, text)
   foreign static remove(fname)

}</lang>

Source code (C)

<lang c>/* gcc -O3 wren-linear.c -o wren-linear -lglpk -lwren -lm */

  1. include <stdio.h>
  2. include <stdlib.h>
  3. include <string.h>
  4. include <glpk.h>
  5. include "wren.h"

/* Glp functions */ void Glp_checkDup(WrenVM* vm) {

   int m = (int)wrenGetSlotDouble(vm, 1);
   int n = (int)wrenGetSlotDouble(vm, 2);
   int ne = (int)wrenGetSlotDouble(vm, 3);
   int ia[ne+1];
   int ja[ne+1];
   for (int ix = 0; ix < ne; ++ix) {
       wrenGetListElement(vm, 4, ix, 1);
       ia[ix+1] = (int)wrenGetSlotDouble(vm, 1);
       wrenGetListElement(vm, 5, ix, 1);
       ja[ix+1] = (int)wrenGetSlotDouble(vm, 1);
   }
   int res = glp_check_dup(m, n, ne, ia, ja);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Glp_initEnv(WrenVM* vm) {

   int res = glp_init_env();
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Glp_version(WrenVM* vm) {

   const char *res = glp_version();
   wrenSetSlotString(vm, 0, res);

}

void Glp_freeEnv(WrenVM* vm) {

   int res = glp_free_env();
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Glp_termOut(WrenVM* vm) {

   int flag = (int)wrenGetSlotDouble(vm, 1);
   int res = glp_term_out(flag);
   wrenSetSlotDouble(vm, 0, (double)res);

}

/* Prob functions */ void Prob_allocate(WrenVM* vm) {

   glp_prob **ppprob = (glp_prob**)wrenSetSlotNewForeign(vm, 0, 0, sizeof(glp_prob*));
   *ppprob = glp_create_prob();

}

void Prob_setProbName(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   const char *name = wrenGetSlotString(vm, 1);
   glp_set_prob_name(pprob, name);

}

void Prob_setObjName(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   const char *name = wrenGetSlotString(vm, 1);
   glp_set_obj_name(pprob, name);

}

void Prob_setObjDir(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int dir = (int)wrenGetSlotDouble(vm, 1);
   glp_set_obj_dir(pprob, dir);

}

void Prob_addRows(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int nrs = (int)wrenGetSlotDouble(vm, 1);
   int res = glp_add_rows(pprob, nrs);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_addCols(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int ncs = (int)wrenGetSlotDouble(vm, 1);
   int res = glp_add_cols(pprob, ncs);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_setRowName(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int i = (int)wrenGetSlotDouble(vm, 1);
   const char *name = wrenGetSlotString(vm, 2);
   glp_set_row_name(pprob, i, name);

}

void Prob_setColName(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int j = (int)wrenGetSlotDouble(vm, 1);
   const char *name = wrenGetSlotString(vm, 2);
   glp_set_col_name(pprob, j, name);

}

void Prob_setRowBnds(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int i = (int)wrenGetSlotDouble(vm, 1);
   int type = (int)wrenGetSlotDouble(vm, 2);
   double lb = wrenGetSlotDouble(vm, 3);
   double ub = wrenGetSlotDouble(vm, 4);
   glp_set_row_bnds(pprob, i, type, lb, ub);

}

void Prob_setColBnds(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int j = (int)wrenGetSlotDouble(vm, 1);
   int type = (int)wrenGetSlotDouble(vm, 2);
   double lb = wrenGetSlotDouble(vm, 3);
   double ub = wrenGetSlotDouble(vm, 4);
   glp_set_col_bnds(pprob, j, type, lb, ub);

}

void Prob_setObjCoef(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int j = (int)wrenGetSlotDouble(vm, 1);
   double coef = wrenGetSlotDouble(vm, 2);
   glp_set_obj_coef(pprob, j, coef);

}

void Prob_setMatRow(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int i = (int)wrenGetSlotDouble(vm, 1);
   int len = (int)wrenGetSlotDouble(vm, 2);
   if (!len) {
       glp_set_mat_row(pprob, i, 0, NULL, NULL);
       return;
   }
   int ind[len+1];
   double val[len+1];
   for (int ix = 0; ix < len; ++ix) {
       wrenGetListElement(vm, 3, ix, 1);
       ind[ix+1] = (int)wrenGetSlotDouble(vm, 1);
       wrenGetListElement(vm, 4, ix, 2);
       val[ix+1] = wrenGetSlotDouble(vm, 2);
   }
   glp_set_mat_row(pprob, i, len, ind, val);

}

void Prob_setMatCol(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int j = (int)wrenGetSlotDouble(vm, 1);
   int len = (int)wrenGetSlotDouble(vm, 2);
   if (!len) {
       glp_set_mat_col(pprob, j, 0, NULL, NULL);
       return;
   }
   int ind[len+1];
   double val[len+1];
   for (int ix = 0; ix < len; ++ix) {
       wrenGetListElement(vm, 3, ix, 1);
       ind[ix+1] = (int)wrenGetSlotDouble(vm, 1);
       wrenGetListElement(vm, 4, ix, 2);
       val[ix+1] = wrenGetSlotDouble(vm, 2);
   }
   glp_set_mat_col(pprob, j, len, ind, val);

}

void Prob_loadMatrix(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int ne = (int)wrenGetSlotDouble(vm, 1);
   if (!ne) {
       glp_load_matrix(pprob, 0, NULL, NULL, NULL);
       return;
   }
   int ia[ne+1];
   int ja[ne+1];
   double ar[ne+1];
   for (int ix = 0; ix < ne; ++ix) {
       wrenGetListElement(vm, 2, ix, 1);
       ia[ix+1] = (int)wrenGetSlotDouble(vm, 1);
       wrenGetListElement(vm, 3, ix, 1);
       ja[ix+1] = (int)wrenGetSlotDouble(vm, 1);
       wrenGetListElement(vm, 4, ix, 1);
       ar[ix+1] = wrenGetSlotDouble(vm, 1);
   }
   glp_load_matrix(pprob, ne, ia, ja, ar);

}

void Prob_sortMatrix(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   glp_sort_matrix(pprob);

}

void Prob_delRows(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int nrs = (int)wrenGetSlotDouble(vm, 1);
   int num[nrs+1];
   for (int ix = 0; ix < nrs; ++ix) {
       wrenGetListElement(vm, 2, ix, 1);
       num[ix+1] = (int)wrenGetSlotDouble(vm, 1);
   }
   glp_del_rows(pprob, nrs, num);

}

void Prob_delCols(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int ncs = (int)wrenGetSlotDouble(vm, 1);
   int num[ncs+1];
   for (int ix = 0; ix < ncs; ++ix) {
       wrenGetListElement(vm, 2, ix, 1);
       num[ix+1] = (int)wrenGetSlotDouble(vm, 1);
   }
   glp_del_cols(pprob, ncs, num);

}

void Prob_copy(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int names = (int)wrenGetSlotDouble(vm, 1);
   glp_prob **ppdest = (glp_prob**)wrenSetSlotNewForeign(vm, 0, 0, sizeof(glp_prob*));
   glp_copy_prob(*ppdest, pprob, names);

}

void Prob_erase(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   glp_erase_prob(pprob);

}

void Prob_delete(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   glp_delete_prob(pprob);

}

void Prob_probName(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   const char *res = glp_get_prob_name(pprob);
   wrenSetSlotString(vm, 0, res);

}

void Prob_objName(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   const char *res = glp_get_obj_name(pprob);
   wrenSetSlotString(vm, 0, res);

}

void Prob_objDir(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int res = glp_get_obj_dir(pprob);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_numRows(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int res = glp_get_num_rows(pprob);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_numCols(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int res = glp_get_num_cols(pprob);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_rowName(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int i = (int)wrenGetSlotDouble(vm, 1);
   const char *res = glp_get_row_name(pprob, i);
   wrenSetSlotString(vm, 0, res);

}

void Prob_colName(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int j = (int)wrenGetSlotDouble(vm, 1);
   const char *res = glp_get_col_name(pprob, j);
   wrenSetSlotString(vm, 0, res);

}

void Prob_rowType(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int i = (int)wrenGetSlotDouble(vm, 1);
   int res = glp_get_row_type(pprob, i);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_rowLB(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int i = (int)wrenGetSlotDouble(vm, 1);
   double res = glp_get_row_lb(pprob, i);
   wrenSetSlotDouble(vm, 0, res);

}

void Prob_rowUB(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int i = (int)wrenGetSlotDouble(vm, 1);
   double res = glp_get_row_ub(pprob, i);
   wrenSetSlotDouble(vm, 0, res);

}

void Prob_colType(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int j = (int)wrenGetSlotDouble(vm, 1);
   int res = glp_get_col_type(pprob, j);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_colLB(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int j = (int)wrenGetSlotDouble(vm, 1);
   double res = glp_get_col_lb(pprob, j);
   wrenSetSlotDouble(vm, 0, res);

}

void Prob_colUB(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int j = (int)wrenGetSlotDouble(vm, 1);
   double res = glp_get_col_ub(pprob, j);
   wrenSetSlotDouble(vm, 0, res);

}

void Prob_objCoef(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int j = (int)wrenGetSlotDouble(vm, 1);
   double res = glp_get_obj_coef(pprob, j);
   wrenSetSlotDouble(vm, 0, res);

}

void Prob_numNZ(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int res = glp_get_num_nz(pprob);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_matRow(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);    
   int i = (int)wrenGetSlotDouble(vm, 1);
   int len = wrenGetListCount(vm, 2);
   int ind[len+1];
   double val[len+1];
   int rlen = glp_get_mat_row(pprob, i, ind, val);
   for (int ix = 0; ix < rlen; ++ix) {
       wrenSetSlotDouble(vm, 1, (double)ind[ix+1]);
       wrenSetListElement(vm, 2, ix, 1);
       wrenSetSlotDouble(vm, 1, val[ix+1]);
       wrenSetListElement(vm, 3, ix, 1);
   }

}

void Prob_matCol(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int j = (int)wrenGetSlotDouble(vm, 1);
   int len = wrenGetListCount(vm, 2);
   int ind[len+1];
   double val[len+1];
   int rlen = glp_get_mat_col(pprob, j, ind, val);
   for (int ix = 0; ix < rlen; ++ix) {
       wrenSetSlotDouble(vm, 1, (double)ind[ix+1]);
       wrenSetListElement(vm, 2, ix, 1);
       wrenSetSlotDouble(vm, 1, val[ix+1]);
       wrenSetListElement(vm, 3, ix, 1);
   }

}

void Prob_createIndex(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   glp_create_index(pprob);

}

void Prob_findRow(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   const char *name = wrenGetSlotString(vm, 1);
   int res = glp_find_row(pprob, name);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_findCol(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   const char *name = wrenGetSlotString(vm, 1);
   int res = glp_find_col(pprob, name);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_deleteIndex(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   glp_delete_index(pprob);

}

void Prob_setRii(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int i = (int)wrenGetSlotDouble(vm, 1);
   double rii = wrenGetSlotDouble(vm, 2);
   glp_set_rii(pprob, i, rii);

}

void Prob_setSjj(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int j = (int)wrenGetSlotDouble(vm, 1);
   double sjj = wrenGetSlotDouble(vm, 2);
   glp_set_sjj(pprob, j, sjj);

}

void Prob_rii(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int i = (int)wrenGetSlotDouble(vm, 1);
   double res = glp_get_rii(pprob, i);
   wrenSetSlotDouble(vm, 0, res);

}

void Prob_sjj(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int j = (int)wrenGetSlotDouble(vm, 1);
   double res = glp_get_sjj(pprob, j);
   wrenSetSlotDouble(vm, 0, res);

}

void Prob_scale(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int flags = (int)wrenGetSlotDouble(vm, 1);
   glp_scale_prob(pprob, flags);

}

void Prob_unscale(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   glp_unscale_prob(pprob);

}

void Prob_setRowStat(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int i = (int)wrenGetSlotDouble(vm, 1);
   int stat = (int)wrenGetSlotDouble(vm, 2);
   glp_set_row_stat(pprob, i, stat);

}

void Prob_setColStat(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int j = (int)wrenGetSlotDouble(vm, 1);
   int stat = (int)wrenGetSlotDouble(vm, 2);
   glp_set_col_stat(pprob, j, stat);

}

void Prob_stdBasis(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);    
   glp_std_basis(pprob);

}

void Prob_advBasis(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   glp_adv_basis(pprob, 0);

}

void Prob_cpxBasis(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);    
   glp_cpx_basis(pprob);

}

void Prob_simplex(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int res;
   if (wrenGetSlotType(vm, 1) == WREN_TYPE_NULL) {
       res = glp_simplex(pprob, NULL);
   } else {
       const glp_smcp *parm = (const glp_smcp*)wrenGetSlotForeign(vm, 1);
       res = glp_simplex(pprob, parm);
   }
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_exact(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   const glp_smcp *parm = (const glp_smcp*)wrenGetSlotForeign(vm, 1);
   int res = glp_exact(pprob, parm);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_status(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int res = glp_get_status(pprob);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_primStat(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int res = glp_get_prim_stat(pprob);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_dualStat(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int res = glp_get_dual_stat(pprob);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_objVal(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   double res = glp_get_obj_val(pprob);
   wrenSetSlotDouble(vm, 0, res);

}

void Prob_rowStat(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int i = (int)wrenGetSlotDouble(vm, 1);
   int res = glp_get_row_stat(pprob, i);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_rowPrim(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int i = (int)wrenGetSlotDouble(vm, 1);
   double res = glp_get_row_prim(pprob, i);
   wrenSetSlotDouble(vm, 0, res);

}

void Prob_rowDual(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int i = (int)wrenGetSlotDouble(vm, 1);
   double res = glp_get_row_dual(pprob, i);
   wrenSetSlotDouble(vm, 0, res);

}

void Prob_colStat(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int j = (int)wrenGetSlotDouble(vm, 1);
   int res = glp_get_col_stat(pprob, j);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_colPrim(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int j = (int)wrenGetSlotDouble(vm, 1);
   double res = glp_get_col_prim(pprob, j);
   wrenSetSlotDouble(vm, 0, res);

}

void Prob_colDual(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int j = (int)wrenGetSlotDouble(vm, 1);
   double res = glp_get_col_dual(pprob, j);
   wrenSetSlotDouble(vm, 0, res);

}

void Prob_unbndRay(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int res = glp_get_unbnd_ray(pprob);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_interior(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int res;
   if (wrenGetSlotType(vm, 1) == WREN_TYPE_NULL) {
       res = glp_interior(pprob, NULL);
   } else {
       const glp_iptcp *parm = (const glp_iptcp*)wrenGetSlotForeign(vm, 1);
       res = glp_interior(pprob, parm);
   }
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_iptStatus(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int res = glp_ipt_status(pprob);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_iptObjVal(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   double res = glp_ipt_obj_val(pprob);
   wrenSetSlotDouble(vm, 0, res);

}

void Prob_iptRowPrim(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int i = (int)wrenGetSlotDouble(vm, 1);
   double res = glp_ipt_row_prim(pprob, i);
   wrenSetSlotDouble(vm, 0, res);

}

void Prob_iptRowDual(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int i = (int)wrenGetSlotDouble(vm, 1);
   double res = glp_ipt_row_dual(pprob, i);
   wrenSetSlotDouble(vm, 0, res);

}

void Prob_iptColPrim(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int j = (int)wrenGetSlotDouble(vm, 1);
   double res = glp_ipt_col_prim(pprob, j);
   wrenSetSlotDouble(vm, 0, res);

}

void Prob_iptColDual(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int j = (int)wrenGetSlotDouble(vm, 1);
   double res = glp_ipt_col_dual(pprob, j);
   wrenSetSlotDouble(vm, 0, res);

}

void Prob_setColKind(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int j = (int)wrenGetSlotDouble(vm, 1);
   int kind = (int)wrenGetSlotDouble(vm, 2);
   glp_set_col_kind(pprob, j, kind);

}

void Prob_colKind(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int j = (int)wrenGetSlotDouble(vm, 1);
   int res = glp_get_col_kind(pprob, j);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_numInt(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int res = glp_get_num_int(pprob);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_numBin(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int res = glp_get_num_bin(pprob);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_intOpt(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int res; 
   if (wrenGetSlotType(vm, 1) == WREN_TYPE_NULL) {
       res = glp_intopt(pprob, NULL);
   } else {
       const glp_iocp *parm = (const glp_iocp*)wrenGetSlotForeign(vm, 1);
       res = glp_intopt(pprob, parm);
   }
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_mipStatus(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int res = glp_mip_status(pprob);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_mipObjVal(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   double res = glp_mip_obj_val(pprob);
   wrenSetSlotDouble(vm, 0, res);

}

void Prob_mipRowVal(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int i = (int)wrenGetSlotDouble(vm, 1);
   double res = glp_mip_row_val(pprob, i);
   wrenSetSlotDouble(vm, 0, res);

}

void Prob_mipColVal(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int j = (int)wrenGetSlotDouble(vm, 1);
   double res = glp_mip_col_val(pprob, j);
   wrenSetSlotDouble(vm, 0, res);

}

void Prob_checkKKT(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int sol = (int)wrenGetSlotDouble(vm, 1);
   int cond = (int)wrenGetSlotDouble(vm, 2);
   int ae_ind, re_ind;
   double ae_max, re_max;
   glp_check_kkt(pprob, sol, cond, &ae_max, &ae_ind, &re_max, &re_ind);
   wrenSetSlotDouble(vm, 1, ae_max);
   wrenSetListElement(vm, 3, 0, 1);
   wrenSetSlotDouble(vm, 1, (double)ae_ind);
   wrenSetListElement(vm, 4, 0, 1);
   wrenSetSlotDouble(vm, 1, re_max);
   wrenSetListElement(vm, 5, 0, 1);
   wrenSetSlotDouble(vm, 1, (double)re_ind);
   wrenSetListElement(vm, 6, 0, 1);

}

void Prob_readMPS(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int format = (int)wrenGetSlotDouble(vm, 1);
   const char *fname = wrenGetSlotString(vm, 2);
   int res = glp_read_mps(pprob, format, NULL, fname);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_writeMPS(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int format = (int)wrenGetSlotDouble(vm, 1);
   const char *fname = wrenGetSlotString(vm, 2);
   int res = glp_write_mps(pprob, format, NULL, fname);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_readLP(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   const char *fname = wrenGetSlotString(vm, 1);
   int res = glp_read_lp(pprob, NULL, fname);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_writeLP(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   const char *fname = wrenGetSlotString(vm, 1);
   int res = glp_write_lp(pprob, NULL, fname);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_readProb(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   const char *fname = wrenGetSlotString(vm, 1);
   int res = glp_read_prob(pprob, 0, fname);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_writeProb(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   const char *fname = wrenGetSlotString(vm, 1);
   int res = glp_write_prob(pprob, 0, fname);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_printSol(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   const char *fname = wrenGetSlotString(vm, 1);
   int res = glp_print_sol(pprob, fname);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_readSol(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   const char *fname = wrenGetSlotString(vm, 1);
   int res = glp_read_sol(pprob, fname);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_writeSol(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   const char *fname = wrenGetSlotString(vm, 1);
   int res = glp_write_sol(pprob, fname);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_printIpt(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   const char *fname = wrenGetSlotString(vm, 1);
   int res = glp_print_ipt(pprob, fname);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_readIpt(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   const char *fname = wrenGetSlotString(vm, 1);
   int res = glp_read_ipt(pprob, fname);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_writeIpt(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   const char *fname = wrenGetSlotString(vm, 1);
   int res = glp_write_ipt(pprob, fname);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_printMip(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   const char *fname = wrenGetSlotString(vm, 1);
   int res = glp_print_mip(pprob, fname);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_readMip(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   const char *fname = wrenGetSlotString(vm, 1);
   int res = glp_read_mip(pprob, fname);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_writeMip(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   const char *fname = wrenGetSlotString(vm, 1);
   int res = glp_write_mip(pprob, fname);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Prob_printRanges(WrenVM* vm) {

   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 0);
   int len = (int)wrenGetSlotDouble(vm, 1);
   const char *fname = wrenGetSlotString(vm, 3);
   int res;
   if (!len) {
       glp_print_ranges(pprob, 0, NULL, 0, fname);
   } else {
       int list[len+1];
       for (int ix = 0; ix < len; ++ix) {
           wrenGetListElement(vm, 2, ix, 1);
           list[ix+1] = (int)wrenGetSlotDouble(vm, 1);
       }
       res = glp_print_ranges(pprob, len, list, 0, fname);
   }
   wrenSetSlotDouble(vm, 0, (double)res);

}

/* Smcp functions */ void Smcp_allocate(WrenVM* vm) {

   glp_smcp *psmcp = (glp_smcp*)wrenSetSlotNewForeign(vm, 0, 0, sizeof(glp_smcp));
   glp_init_smcp(psmcp);

}

void Smcp_meth(WrenVM* vm) {

   glp_smcp *psmcp = (glp_smcp*)wrenGetSlotForeign(vm, 0);
   wrenSetSlotDouble(vm, 0, (double)psmcp->meth);

}

void Smcp_msgLev(WrenVM* vm) {

   glp_smcp *psmcp = (glp_smcp*)wrenGetSlotForeign(vm, 0);
   wrenSetSlotDouble(vm, 0, (double)psmcp->msg_lev);

}

void Smcp_pricing(WrenVM* vm) {

   glp_smcp *psmcp = (glp_smcp*)wrenGetSlotForeign(vm, 0);
   wrenSetSlotDouble(vm, 0, (double)psmcp->pricing);

}

void Smcp_rTest(WrenVM* vm) {

   glp_smcp *psmcp = (glp_smcp*)wrenGetSlotForeign(vm, 0);
   wrenSetSlotDouble(vm, 0, (double)psmcp->r_test);

}

void Smcp_setMeth(WrenVM* vm) {

   glp_smcp *psmcp = (glp_smcp*)wrenGetSlotForeign(vm, 0);
   int meth = (int)wrenGetSlotDouble(vm, 1);
   psmcp->meth = meth;

}

void Smcp_setMsgLev(WrenVM* vm) {

   glp_smcp *psmcp = (glp_smcp*)wrenGetSlotForeign(vm, 0);
   int msg_lev = (int)wrenGetSlotDouble(vm, 1);
   psmcp->msg_lev = msg_lev;

}

void Smcp_setPricing(WrenVM* vm) {

   glp_smcp *psmcp = (glp_smcp*)wrenGetSlotForeign(vm, 0);
   int pricing = (int)wrenGetSlotDouble(vm, 1);
   psmcp->pricing = pricing;

}

void Smcp_setRTest(WrenVM* vm) {

   glp_smcp *psmcp = (glp_smcp*)wrenGetSlotForeign(vm, 0);
   int r_test = (int)wrenGetSlotDouble(vm, 1);
   psmcp->r_test = r_test;

}

/* Iptcp functions */ void Iptcp_allocate(WrenVM* vm) {

   glp_iptcp *piptcp = (glp_iptcp*)wrenSetSlotNewForeign(vm, 0, 0, sizeof(glp_iptcp));
   glp_init_iptcp(piptcp);

}

void Iptcp_msgLev(WrenVM* vm) {

   glp_iptcp *piptcp = (glp_iptcp*)wrenGetSlotForeign(vm, 0);
   wrenSetSlotDouble(vm, 0, (double)piptcp->msg_lev);

}

void Iptcp_ordAlg(WrenVM* vm) {

   glp_iptcp *piptcp = (glp_iptcp*)wrenGetSlotForeign(vm, 0);
   wrenSetSlotDouble(vm, 0, (double)piptcp->ord_alg);

}

void Iptcp_setMsgLev(WrenVM* vm) {

   glp_iptcp *piptcp = (glp_iptcp*)wrenGetSlotForeign(vm, 0);
   int msg_lev = (int)wrenGetSlotDouble(vm, 1);
   piptcp->msg_lev = msg_lev;

}

void Iptcp_setOrdAlg(WrenVM* vm) {

   glp_iptcp *piptcp = (glp_iptcp*)wrenGetSlotForeign(vm, 0);
   int ord_alg = (int)wrenGetSlotDouble(vm, 1);
   piptcp->ord_alg = ord_alg;

}

/* Iocp functions */ void Iocp_allocate(WrenVM* vm) {

   glp_iocp *piocp = (glp_iocp*)wrenSetSlotNewForeign(vm, 0, 0, sizeof(glp_iocp));
   glp_init_iocp(piocp);

}

void Iocp_msgLev(WrenVM* vm) {

   glp_iocp *piocp = (glp_iocp*)wrenGetSlotForeign(vm, 0);
   wrenSetSlotDouble(vm, 0, (double)piocp->msg_lev);

}

void Iocp_brTech(WrenVM* vm) {

   glp_iocp *piocp = (glp_iocp*)wrenGetSlotForeign(vm, 0);
   wrenSetSlotDouble(vm, 0, (double)piocp->br_tech);

}

void Iocp_btTech(WrenVM* vm) {

   glp_iocp *piocp = (glp_iocp*)wrenGetSlotForeign(vm, 0);
   wrenSetSlotDouble(vm, 0, (double)piocp->bt_tech);

}

void Iocp_ppTech(WrenVM* vm) {

   glp_iocp *piocp = (glp_iocp*)wrenGetSlotForeign(vm, 0);
   wrenSetSlotDouble(vm, 0, (double)piocp->pp_tech);

}

void Iocp_presolve(WrenVM* vm) {

   glp_iocp *piocp = (glp_iocp*)wrenGetSlotForeign(vm, 0);
   wrenSetSlotBool(vm, 0, piocp->presolve);

}

void Iocp_setMsgLev(WrenVM* vm) {

   glp_iocp *piocp = (glp_iocp*)wrenGetSlotForeign(vm, 0);
   int msg_lev = (int)wrenGetSlotDouble(vm, 1);
   piocp->msg_lev = msg_lev;

}

void Iocp_setBrTech(WrenVM* vm) {

   glp_iocp *piocp = (glp_iocp*)wrenGetSlotForeign(vm, 0);
   int br_tech = (int)wrenGetSlotDouble(vm, 1);
   piocp->br_tech = br_tech;

}

void Iocp_setBtTech(WrenVM* vm) {

   glp_iocp *piocp = (glp_iocp*)wrenGetSlotForeign(vm, 0);
   int bt_tech = (int)wrenGetSlotDouble(vm, 1);
   piocp->bt_tech = bt_tech;

}

void Iocp_setPpTech(WrenVM* vm) {

   glp_iocp *piocp = (glp_iocp*)wrenGetSlotForeign(vm, 0);
   int pp_tech = (int)wrenGetSlotDouble(vm, 1);
   piocp->pp_tech = pp_tech;

}

void Iocp_setPresolve(WrenVM* vm) {

   glp_iocp *piocp = (glp_iocp*)wrenGetSlotForeign(vm, 0);
   bool presolve = wrenGetSlotBool(vm, 1);
   piocp->presolve = presolve;

}

/* Tran functions */ void Tran_allocate(WrenVM* vm) {

   glp_tran **pptran = (glp_tran**)wrenSetSlotNewForeign(vm, 0, 0, sizeof(glp_tran*));
   *pptran = glp_mpl_alloc_wksp();

}

void Tran_mplInitRand(WrenVM* vm) {

   glp_tran *ptran = *(glp_tran**)wrenGetSlotForeign(vm, 0);
   int seed = (int)wrenGetSlotDouble(vm, 1);
   glp_mpl_init_rand(ptran, seed);

}

void Tran_mplReadModel(WrenVM* vm) {

   glp_tran *ptran = *(glp_tran**)wrenGetSlotForeign(vm, 0);
   const char *fname = wrenGetSlotString(vm, 1);
   int skip = (int)wrenGetSlotDouble(vm, 2);
   int res = glp_mpl_read_model(ptran, fname, skip);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Tran_mplReadData(WrenVM* vm) {

   glp_tran *ptran = *(glp_tran**)wrenGetSlotForeign(vm, 0);
   const char *fname = wrenGetSlotString(vm, 1);
   int res = glp_mpl_read_data(ptran, fname);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Tran_mplGenerate(WrenVM* vm) {

   glp_tran *ptran = *(glp_tran**)wrenGetSlotForeign(vm, 0);
   int res;
   if (wrenGetSlotType(vm, 1) == WREN_TYPE_NULL) {
       res = glp_mpl_generate(ptran, NULL);
   } else {
       const char *fname = wrenGetSlotString(vm, 1);
       res = glp_mpl_generate(ptran, fname);
   }
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Tran_mplBuildProb(WrenVM* vm) {

   glp_tran *ptran = *(glp_tran**)wrenGetSlotForeign(vm, 0);
   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 1);
   glp_mpl_build_prob(ptran, pprob);

}

void Tran_mplPostSolve(WrenVM* vm) {

   glp_tran *ptran = *(glp_tran**)wrenGetSlotForeign(vm, 0);
   glp_prob *pprob = *(glp_prob**)wrenGetSlotForeign(vm, 1);
   int sol = (int)wrenGetSlotDouble(vm, 2);
   int res = glp_mpl_postsolve(ptran, pprob, sol);
   wrenSetSlotDouble(vm, 0, (double)res);

}

void Tran_mplFreeWksp(WrenVM* vm) {

   glp_tran *ptran = *(glp_tran**)wrenGetSlotForeign(vm, 0);
   glp_mpl_free_wksp(ptran);

}

/* File functions */

void File_write(WrenVM* vm) {

   const char *fname = wrenGetSlotString(vm, 1);
   const char *text = wrenGetSlotString(vm, 2);
   FILE *fp = fopen(fname, "w+");
   fputs(text, fp);
   fclose(fp);

}

void File_remove(WrenVM* vm) {

   const char *fname = wrenGetSlotString(vm, 1);
   int res = remove(fname);
   wrenSetSlotDouble(vm, 0, (double)res);

}

WrenForeignClassMethods bindForeignClass(WrenVM* vm, const char* module, const char* className) {

   WrenForeignClassMethods methods;
   methods.allocate = NULL;
   methods.finalize = NULL;
   if (strcmp(module, "./linear") == 0) {
       if (strcmp(className, "Prob") == 0) {
           methods.allocate = Prob_allocate;
       } else if (strcmp(className, "Smcp") == 0) {
           methods.allocate = Smcp_allocate;
       } else if (strcmp(className, "Iptcp") == 0) {
           methods.allocate = Iptcp_allocate;
       } else if (strcmp(className, "Iocp") == 0) {
           methods.allocate = Iocp_allocate;
       } else if (strcmp(className, "Tran") == 0) {
           methods.allocate = Tran_allocate;
       } 
   }
   return methods;

}

WrenForeignMethodFn bindForeignMethod(

   WrenVM* vm,
   const char* module,
   const char* className,
   bool isStatic,
   const char* signature) {
   if (strcmp(module, "./linear") == 0) {
       if (strcmp(className, "Glp") == 0) {
           if(isStatic && strcmp(signature, "checkDup(_,_,_,_,_)") == 0) return Glp_checkDup;
           if(isStatic && strcmp(signature, "initEnv()") == 0)           return Glp_initEnv;
           if(isStatic && strcmp(signature, "version") == 0)             return Glp_version;
           if(isStatic && strcmp(signature, "freeEnv()") == 0)           return Glp_freeEnv;
           if(isStatic && strcmp(signature, "termOut(_)") == 0)          return Glp_termOut;
       } else if (strcmp(className, "Prob") == 0) {
           if(!isStatic && strcmp(signature, "setProbName(_)") == 0)      return Prob_setProbName;
           if(!isStatic && strcmp(signature, "setObjName(_)") == 0)       return Prob_setObjName;
           if(!isStatic && strcmp(signature, "setObjDir(_)") == 0)        return Prob_setObjDir;
           if(!isStatic && strcmp(signature, "addCols(_)") == 0)          return Prob_addCols;
           if(!isStatic && strcmp(signature, "addRows(_)") == 0)          return Prob_addRows;
           if(!isStatic && strcmp(signature, "setRowName(_,_)") == 0)     return Prob_setRowName;
           if(!isStatic && strcmp(signature, "setColName(_,_)") == 0)     return Prob_setColName;
           if(!isStatic && strcmp(signature, "setRowBnds(_,_,_,_)") == 0) return Prob_setRowBnds;
           if(!isStatic && strcmp(signature, "setColBnds(_,_,_,_)") == 0) return Prob_setColBnds;
           if(!isStatic && strcmp(signature, "setObjCoef(_,_)") == 0)     return Prob_setObjCoef;
           if(!isStatic && strcmp(signature, "setMatRow(_,_,_,_)") == 0)  return Prob_setMatRow;
           if(!isStatic && strcmp(signature, "setMatCol(_,_,_,_)") == 0)  return Prob_setMatCol;
           if(!isStatic && strcmp(signature, "loadMatrix(_,_,_,_)") == 0) return Prob_loadMatrix;
           if(!isStatic && strcmp(signature, "sortMatrix()") == 0)        return Prob_sortMatrix;
           if(!isStatic && strcmp(signature, "delRows(_,_)") == 0)        return Prob_delRows;
           if(!isStatic && strcmp(signature, "delCols(_,_)") == 0)        return Prob_delCols;
           if(!isStatic && strcmp(signature, "copy(_)") == 0)             return Prob_copy;
           if(!isStatic && strcmp(signature, "erase()") == 0)             return Prob_erase;
           if(!isStatic && strcmp(signature, "delete()") == 0)            return Prob_delete;
           if(!isStatic && strcmp(signature, "probName") == 0)      return Prob_probName;
           if(!isStatic && strcmp(signature, "objName") == 0)       return Prob_objName;
           if(!isStatic && strcmp(signature, "objDir") == 0)        return Prob_objDir;
           if(!isStatic && strcmp(signature, "numRows") == 0)       return Prob_numRows;
           if(!isStatic && strcmp(signature, "numCols") == 0)       return Prob_numCols;
           if(!isStatic && strcmp(signature, "rowName(_)") == 0)    return Prob_rowName;
           if(!isStatic && strcmp(signature, "colName(_)") == 0)    return Prob_colName;
           if(!isStatic && strcmp(signature, "rowType(_)") == 0)    return Prob_rowType;
           if(!isStatic && strcmp(signature, "rowLB(_)") == 0)      return Prob_rowLB;
           if(!isStatic && strcmp(signature, "rowUB(_)") == 0)      return Prob_rowUB;
           if(!isStatic && strcmp(signature, "colType(_)") == 0)    return Prob_colType;
           if(!isStatic && strcmp(signature, "colLB(_)") == 0)      return Prob_colLB;
           if(!isStatic && strcmp(signature, "colUB(_)") == 0)      return Prob_colUB;
           if(!isStatic && strcmp(signature, "objCoef(_)") == 0)    return Prob_objCoef;
           if(!isStatic && strcmp(signature, "numNZ") == 0)         return Prob_numNZ;
           if(!isStatic && strcmp(signature, "matRow(_,_,_)") == 0) return Prob_matRow;
           if(!isStatic && strcmp(signature, "matCol(_,_,_)") == 0) return Prob_matCol;
           if(!isStatic && strcmp(signature, "createIndex()") == 0) return Prob_createIndex;
           if(!isStatic && strcmp(signature, "findRow(_)") == 0)    return Prob_findRow;
           if(!isStatic && strcmp(signature, "findCol(_)") == 0)    return Prob_findCol;
           if(!isStatic && strcmp(signature, "deleteIndex()") == 0) return Prob_deleteIndex;
           if(!isStatic && strcmp(signature, "setRii(_,_)") == 0)   return Prob_setRii;
           if(!isStatic && strcmp(signature, "setSjj(_,_)") == 0)   return Prob_setSjj;
           if(!isStatic && strcmp(signature, "rii(_)") == 0)        return Prob_rii;
           if(!isStatic && strcmp(signature, "sjj(_)") == 0)        return Prob_sjj;
           if(!isStatic && strcmp(signature, "scale(_)") == 0)      return Prob_scale;
           if(!isStatic && strcmp(signature, "unscale()") == 0)     return Prob_unscale;
           if(!isStatic && strcmp(signature, "setRowStat(_,_)") == 0) return Prob_setRowStat;
           if(!isStatic && strcmp(signature, "setColStat(_,_)") == 0) return Prob_setColStat;
           if(!isStatic && strcmp(signature, "stdBasis()") == 0)      return Prob_stdBasis;
           if(!isStatic && strcmp(signature, "advBasis()") == 0)      return Prob_advBasis;
           if(!isStatic && strcmp(signature, "cpxBasis()") == 0)      return Prob_cpxBasis;
           if(!isStatic && strcmp(signature, "simplex(_)") == 0) return Prob_simplex;
           if(!isStatic && strcmp(signature, "exact(_)") == 0)   return Prob_exact;
           if(!isStatic && strcmp(signature, "status") == 0)     return Prob_status;           
           if(!isStatic && strcmp(signature, "primStat") == 0)   return Prob_primStat;
           if(!isStatic && strcmp(signature, "dualStat") == 0)   return Prob_dualStat;
           if(!isStatic && strcmp(signature, "objVal") == 0)     return Prob_objVal;
           if(!isStatic && strcmp(signature, "rowStat(_)") == 0) return Prob_rowStat;
           if(!isStatic && strcmp(signature, "rowPrim(_)") == 0) return Prob_rowPrim;
           if(!isStatic && strcmp(signature, "rowDual(_)") == 0) return Prob_rowDual;
           if(!isStatic && strcmp(signature, "colStat(_)") == 0) return Prob_colStat;
           if(!isStatic && strcmp(signature, "colPrim(_)") == 0) return Prob_colPrim;
           if(!isStatic && strcmp(signature, "colDual(_)") == 0) return Prob_colDual;
           if(!isStatic && strcmp(signature, "unbndRay") == 0)   return Prob_unbndRay;
           if(!isStatic && strcmp(signature, "interior(_)") == 0)   return Prob_interior;
           if(!isStatic && strcmp(signature, "iptStatus") == 0)     return Prob_iptStatus;
           if(!isStatic && strcmp(signature, "iptObjVal") == 0)     return Prob_iptObjVal;          
           if(!isStatic && strcmp(signature, "iptRowPrim(_)") == 0) return Prob_iptRowPrim;
           if(!isStatic && strcmp(signature, "iptRowDual(_)") == 0) return Prob_iptRowDual;
           if(!isStatic && strcmp(signature, "iptColPrim(_)") == 0) return Prob_iptColPrim;
           if(!isStatic && strcmp(signature, "iptColDual(_)") == 0) return Prob_iptColDual;
           if(!isStatic && strcmp(signature, "setColKind(_,_)") == 0) return Prob_setColKind;
           if(!isStatic && strcmp(signature, "colKind(_)") == 0)      return Prob_colKind;
           if(!isStatic && strcmp(signature, "numInt") == 0)          return Prob_numInt;
           if(!isStatic && strcmp(signature, "numBin") == 0)          return Prob_numBin;
           if(!isStatic && strcmp(signature, "intOpt(_)") == 0)       return Prob_intOpt;
           if(!isStatic && strcmp(signature, "mipStatus") == 0)       return Prob_mipStatus;
           if(!isStatic && strcmp(signature, "mipObjVal") == 0)       return Prob_mipObjVal;
           if(!isStatic && strcmp(signature, "mipRowVal(_)") == 0)    return Prob_mipRowVal;
           if(!isStatic && strcmp(signature, "mipColVal(_)") == 0)    return Prob_mipColVal;
           if(!isStatic && strcmp(signature, "checkKKT(_,_,_,_,_,_)") == 0)  return Prob_checkKKT;
           if(!isStatic && strcmp(signature, "readMPS(_,_)") == 0)  return Prob_readMPS;
           if(!isStatic && strcmp(signature, "writeMPS(_,_)") == 0) return Prob_writeMPS;
           if(!isStatic && strcmp(signature, "readLP(_)") == 0)     return Prob_readLP;
           if(!isStatic && strcmp(signature, "writeLP(_)") == 0)    return Prob_writeLP;
           if(!isStatic && strcmp(signature, "readProb(_)") == 0)   return Prob_readProb;
           if(!isStatic && strcmp(signature, "writeProb(_)") == 0)  return Prob_writeProb;
           if(!isStatic && strcmp(signature, "printSol(_)") == 0) return Prob_printSol;
           if(!isStatic && strcmp(signature, "readSol(_)") == 0)  return Prob_readSol;
           if(!isStatic && strcmp(signature, "writeSol(_)") == 0) return Prob_writeSol;
           if(!isStatic && strcmp(signature, "printIpt(_)") == 0) return Prob_printIpt;
           if(!isStatic && strcmp(signature, "readIpt(_)") == 0)  return Prob_readIpt;
           if(!isStatic && strcmp(signature, "writeIpt(_)") == 0) return Prob_writeIpt;
           if(!isStatic && strcmp(signature, "printMip(_)") == 0) return Prob_printMip;
           if(!isStatic && strcmp(signature, "readMip(_)") == 0)  return Prob_readMip;
           if(!isStatic && strcmp(signature, "writeMip(_)") == 0) return Prob_writeMip;
           if(!isStatic && strcmp(signature, "printRanges(_,_,_)") == 0) return Prob_printRanges;
       } else if (strcmp(className, "Smcp") == 0) {
           if(!isStatic && strcmp(signature, "meth") == 0)        return Smcp_meth;
           if(!isStatic && strcmp(signature, "msgLev") == 0)      return Smcp_msgLev;
           if(!isStatic && strcmp(signature, "pricing") == 0)     return Smcp_pricing;
           if(!isStatic && strcmp(signature, "rTest") == 0)       return Smcp_rTest;
           if(!isStatic && strcmp(signature, "meth=(_)") == 0)    return Smcp_setMeth;
           if(!isStatic && strcmp(signature, "msgLev=(_)") == 0)  return Smcp_setMsgLev;
           if(!isStatic && strcmp(signature, "pricing=(_)") == 0) return Smcp_setPricing;
           if(!isStatic && strcmp(signature, "rTest=(_)") == 0)   return Smcp_setRTest;
       } else if (strcmp(className, "Iptcp") == 0) {
           if(!isStatic && strcmp(signature, "msgLev") == 0)      return Iptcp_msgLev;
           if(!isStatic && strcmp(signature, "ordAlg") == 0)      return Iptcp_ordAlg;
           if(!isStatic && strcmp(signature, "msgLev=(_)") == 0)  return Iptcp_setMsgLev;
           if(!isStatic && strcmp(signature, "ordAlg=(_)") == 0)  return Iptcp_setOrdAlg;
       } else if (strcmp(className, "Iocp") == 0) {
           if(!isStatic && strcmp(signature, "msgLev") == 0)       return Iocp_msgLev;
           if(!isStatic && strcmp(signature, "brTech") == 0)       return Iocp_brTech;
           if(!isStatic && strcmp(signature, "btTech") == 0)       return Iocp_btTech;
           if(!isStatic && strcmp(signature, "ppTech") == 0)       return Iocp_ppTech;
           if(!isStatic && strcmp(signature, "presolve") == 0)     return Iocp_presolve;
           if(!isStatic && strcmp(signature, "msgLev=(_)") == 0)   return Iocp_setMsgLev;
           if(!isStatic && strcmp(signature, "brTech=(_)") == 0)   return Iocp_setBrTech;
           if(!isStatic && strcmp(signature, "btTech=(_)") == 0)   return Iocp_setBtTech;
           if(!isStatic && strcmp(signature, "ppTech=(_)") == 0)   return Iocp_setPpTech;
           if(!isStatic && strcmp(signature, "presolve=(_)") == 0) return Iocp_setPresolve;
       } else if (strcmp(className, "Tran") == 0) {
           if(!isStatic && strcmp(signature, "mplInitRand(_)") == 0)    return Tran_mplInitRand;
           if(!isStatic && strcmp(signature, "mplReadModel(_,_)") == 0) return Tran_mplReadModel;
           if(!isStatic && strcmp(signature, "mplReadData(_)") == 0)    return Tran_mplReadData;
           if(!isStatic && strcmp(signature, "mplGenerate(_)") == 0)    return Tran_mplGenerate;
           if(!isStatic && strcmp(signature, "mplBuildProb(_)") == 0)   return Tran_mplBuildProb;
           if(!isStatic && strcmp(signature, "mplPostSolve(_,_)") == 0) return Tran_mplPostSolve;
           if(!isStatic && strcmp(signature, "mplFreeWksp()") == 0)     return Tran_mplFreeWksp;
       } else if (strcmp(className, "File") == 0) {
           if(isStatic && strcmp(signature, "write(_,_)") == 0) return File_write;
           if(isStatic && strcmp(signature, "remove(_)") == 0)  return File_remove;
       }
   }
   return NULL;

}

static void writeFn(WrenVM* vm, const char* text) {

   printf("%s", text);

}

void errorFn(WrenVM* vm, WrenErrorType errorType, const char* module, const int line, const char* msg) {

   switch (errorType) {
       case WREN_ERROR_COMPILE:
           printf("[%s line %d] [Error] %s\n", module, line, msg);
           break;
       case WREN_ERROR_STACK_TRACE:
           printf("[%s line %d] in %s\n", module, line, msg);
           break;
       case WREN_ERROR_RUNTIME:
           printf("[Runtime Error] %s\n", msg);
           break;
   }

}

char *readFile(const char *fileName) {

   FILE *f = fopen(fileName, "r");
   fseek(f, 0, SEEK_END);
   long fsize = ftell(f);
   rewind(f);
   char *script = malloc(fsize + 1);
   size_t ret = fread(script, 1, fsize, f);
   if (ret != fsize) printf("Error reading %s\n", fileName);
   fclose(f);
   script[fsize] = 0;
   return script;

}

static void loadModuleComplete(WrenVM* vm, const char* module, WrenLoadModuleResult result) {

   if( result.source) free((void*)result.source);

}

WrenLoadModuleResult loadModule(WrenVM* vm, const char* name) {

   WrenLoadModuleResult result = {0};
   if (strcmp(name, "random") != 0 && strcmp(name, "meta") != 0) {
       result.onComplete = loadModuleComplete;
       char fullName[strlen(name) + 6];
       strcpy(fullName, name);
       strcat(fullName, ".wren");
       result.source = readFile(fullName);
   }
   return result;

}

int main(int argc, char **argv) {

   if (argc != 2) {
       printf("Please pass the name of the Wren file to be executed.\n");
       return 1;
   }
   WrenConfiguration config;
   wrenInitConfiguration(&config);
   config.writeFn = &writeFn;
   config.errorFn = &errorFn;
   config.bindForeignClassFn = &bindForeignClass;
   config.bindForeignMethodFn = &bindForeignMethod;
   config.loadModuleFn = &loadModule;
   WrenVM* vm = wrenNewVM(&config);
   const char* module = "main";
   const char* fileName = argv[1];
   char *script = readFile(fileName);
   WrenInterpretResult result = wrenInterpret(vm, module, script);
   switch (result) {
       case WREN_RESULT_COMPILE_ERROR:
           printf("Compile Error!\n");
           break;
       case WREN_RESULT_RUNTIME_ERROR:
           printf("Runtime Error!\n");
           break;
       case WREN_RESULT_SUCCESS:
           break;
   }
   wrenFreeVM(vm);
   free(script);
   return 0;

}</lang>