aboutsummaryrefslogtreecommitdiffstats
path: root/test/monniaux/glpk-4.65/src/misc
diff options
context:
space:
mode:
authorDavid Monniaux <david.monniaux@univ-grenoble-alpes.fr>2020-03-03 08:17:40 +0100
committerDavid Monniaux <david.monniaux@univ-grenoble-alpes.fr>2020-03-03 08:17:40 +0100
commit1ab7b51c30e1b10ac45b0bd64cefdc01da0f7f68 (patch)
tree210ffc156c83f04fb0c61a40b4f9037d7ba8a7e1 /test/monniaux/glpk-4.65/src/misc
parent222c9047d61961db9c6b19fed5ca49829223fd33 (diff)
parent12be46d59a2483a10d77fa8ee67f7e0ca1bd702f (diff)
downloadcompcert-kvx-1ab7b51c30e1b10ac45b0bd64cefdc01da0f7f68.tar.gz
compcert-kvx-1ab7b51c30e1b10ac45b0bd64cefdc01da0f7f68.zip
Merge branch 'mppa-cse2' of gricad-gitlab.univ-grenoble-alpes.fr:sixcy/CompCert into mppa-work
Diffstat (limited to 'test/monniaux/glpk-4.65/src/misc')
-rw-r--r--test/monniaux/glpk-4.65/src/misc/avl.c405
-rw-r--r--test/monniaux/glpk-4.65/src/misc/avl.h73
-rw-r--r--test/monniaux/glpk-4.65/src/misc/bignum.c286
-rw-r--r--test/monniaux/glpk-4.65/src/misc/bignum.h37
-rw-r--r--test/monniaux/glpk-4.65/src/misc/dimacs.c147
-rw-r--r--test/monniaux/glpk-4.65/src/misc/dimacs.h81
-rw-r--r--test/monniaux/glpk-4.65/src/misc/dmp.c243
-rw-r--r--test/monniaux/glpk-4.65/src/misc/dmp.h63
-rw-r--r--test/monniaux/glpk-4.65/src/misc/ffalg.c221
-rw-r--r--test/monniaux/glpk-4.65/src/misc/ffalg.h34
-rw-r--r--test/monniaux/glpk-4.65/src/misc/fp2rat.c164
-rw-r--r--test/monniaux/glpk-4.65/src/misc/fvs.c137
-rw-r--r--test/monniaux/glpk-4.65/src/misc/fvs.h76
-rw-r--r--test/monniaux/glpk-4.65/src/misc/gcd.c102
-rw-r--r--test/monniaux/glpk-4.65/src/misc/jd.c152
-rw-r--r--test/monniaux/glpk-4.65/src/misc/jd.h32
-rw-r--r--test/monniaux/glpk-4.65/src/misc/keller.c235
-rw-r--r--test/monniaux/glpk-4.65/src/misc/keller.h34
-rw-r--r--test/monniaux/glpk-4.65/src/misc/ks.c466
-rw-r--r--test/monniaux/glpk-4.65/src/misc/ks.h44
-rw-r--r--test/monniaux/glpk-4.65/src/misc/mc13d.c314
-rw-r--r--test/monniaux/glpk-4.65/src/misc/mc13d.h34
-rw-r--r--test/monniaux/glpk-4.65/src/misc/mc21a.c301
-rw-r--r--test/monniaux/glpk-4.65/src/misc/mc21a.h34
-rw-r--r--test/monniaux/glpk-4.65/src/misc/misc.h61
-rw-r--r--test/monniaux/glpk-4.65/src/misc/mt1.c1110
-rw-r--r--test/monniaux/glpk-4.65/src/misc/mt1.f277
-rw-r--r--test/monniaux/glpk-4.65/src/misc/mt1.h34
-rw-r--r--test/monniaux/glpk-4.65/src/misc/mygmp.c1162
-rw-r--r--test/monniaux/glpk-4.65/src/misc/mygmp.h254
-rw-r--r--test/monniaux/glpk-4.65/src/misc/okalg.c382
-rw-r--r--test/monniaux/glpk-4.65/src/misc/okalg.h35
-rw-r--r--test/monniaux/glpk-4.65/src/misc/qmd.c584
-rw-r--r--test/monniaux/glpk-4.65/src/misc/qmd.h58
-rw-r--r--test/monniaux/glpk-4.65/src/misc/relax4.c2850
-rw-r--r--test/monniaux/glpk-4.65/src/misc/relax4.h102
-rw-r--r--test/monniaux/glpk-4.65/src/misc/rng.c227
-rw-r--r--test/monniaux/glpk-4.65/src/misc/rng.h67
-rw-r--r--test/monniaux/glpk-4.65/src/misc/rng1.c73
-rw-r--r--test/monniaux/glpk-4.65/src/misc/round2n.c64
-rw-r--r--test/monniaux/glpk-4.65/src/misc/str2int.c92
-rw-r--r--test/monniaux/glpk-4.65/src/misc/str2num.c110
-rw-r--r--test/monniaux/glpk-4.65/src/misc/strspx.c60
-rw-r--r--test/monniaux/glpk-4.65/src/misc/strtrim.c62
-rw-r--r--test/monniaux/glpk-4.65/src/misc/triang.c311
-rw-r--r--test/monniaux/glpk-4.65/src/misc/triang.h34
-rw-r--r--test/monniaux/glpk-4.65/src/misc/wclique.c242
-rw-r--r--test/monniaux/glpk-4.65/src/misc/wclique.h33
-rw-r--r--test/monniaux/glpk-4.65/src/misc/wclique1.c317
-rw-r--r--test/monniaux/glpk-4.65/src/misc/wclique1.h34
50 files changed, 12350 insertions, 0 deletions
diff --git a/test/monniaux/glpk-4.65/src/misc/avl.c b/test/monniaux/glpk-4.65/src/misc/avl.c
new file mode 100644
index 00000000..c97cf13a
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/avl.c
@@ -0,0 +1,405 @@
+/* avl.c (binary search tree) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include "avl.h"
+#include "dmp.h"
+#include "env.h"
+
+struct AVL
+{ /* AVL tree (Adelson-Velsky & Landis binary search tree) */
+ DMP *pool;
+ /* memory pool for allocating nodes */
+ AVLNODE *root;
+ /* pointer to the root node */
+ int (*fcmp)(void *info, const void *key1, const void *key2);
+ /* application-defined key comparison routine */
+ void *info;
+ /* transit pointer passed to the routine fcmp */
+ int size;
+ /* the tree size (the total number of nodes) */
+ int height;
+ /* the tree height */
+};
+
+struct AVLNODE
+{ /* node of AVL tree */
+ const void *key;
+ /* pointer to the node key (data structure for representing keys
+ is supplied by the application) */
+ int rank;
+ /* node rank = relative position of the node in its own subtree =
+ the number of nodes in the left subtree plus one */
+ int type;
+ /* reserved for the application specific information */
+ void *link;
+ /* reserved for the application specific information */
+ AVLNODE *up;
+ /* pointer to the parent node */
+ short int flag;
+ /* node flag:
+ 0 - this node is the left child of its parent (or this node is
+ the root of the tree and has no parent)
+ 1 - this node is the right child of its parent */
+ short int bal;
+ /* node balance = the difference between heights of the right and
+ left subtrees:
+ -1 - the left subtree is higher than the right one;
+ 0 - the left and right subtrees have the same height;
+ +1 - the left subtree is lower than the right one */
+ AVLNODE *left;
+ /* pointer to the root of the left subtree */
+ AVLNODE *right;
+ /* pointer to the root of the right subtree */
+};
+
+AVL *avl_create_tree(int (*fcmp)(void *info, const void *key1,
+ const void *key2), void *info)
+{ /* create AVL tree */
+ AVL *tree;
+ tree = xmalloc(sizeof(AVL));
+ tree->pool = dmp_create_pool();
+ tree->root = NULL;
+ tree->fcmp = fcmp;
+ tree->info = info;
+ tree->size = 0;
+ tree->height = 0;
+ return tree;
+}
+
+int avl_strcmp(void *info, const void *key1, const void *key2)
+{ /* compare character string keys */
+ xassert(info == info);
+ return strcmp(key1, key2);
+}
+
+static AVLNODE *rotate_subtree(AVL *tree, AVLNODE *node);
+
+AVLNODE *avl_insert_node(AVL *tree, const void *key)
+{ /* insert new node into AVL tree */
+ AVLNODE *p, *q, *r;
+ short int flag;
+ /* find an appropriate point for insertion */
+ p = NULL; q = tree->root;
+ while (q != NULL)
+ { p = q;
+ if (tree->fcmp(tree->info, key, p->key) <= 0)
+ { flag = 0;
+ q = p->left;
+ p->rank++;
+ }
+ else
+ { flag = 1;
+ q = p->right;
+ }
+ }
+ /* create new node and insert it into the tree */
+ r = dmp_get_atom(tree->pool, sizeof(AVLNODE));
+ r->key = key; r->type = 0; r->link = NULL;
+ r->rank = 1; r->up = p;
+ r->flag = (short int)(p == NULL ? 0 : flag);
+ r->bal = 0; r->left = NULL; r->right = NULL;
+ tree->size++;
+ if (p == NULL)
+ tree->root = r;
+ else
+ if (flag == 0) p->left = r; else p->right = r;
+ /* go upstairs to the root and correct all subtrees affected by
+ insertion */
+ while (p != NULL)
+ { if (flag == 0)
+ { /* the height of the left subtree of [p] is increased */
+ if (p->bal > 0)
+ { p->bal = 0;
+ break;
+ }
+ if (p->bal < 0)
+ { rotate_subtree(tree, p);
+ break;
+ }
+ p->bal = -1; flag = p->flag; p = p->up;
+ }
+ else
+ { /* the height of the right subtree of [p] is increased */
+ if (p->bal < 0)
+ { p->bal = 0;
+ break;
+ }
+ if (p->bal > 0)
+ { rotate_subtree(tree, p);
+ break;
+ }
+ p->bal = +1; flag = p->flag; p = p->up;
+ }
+ }
+ /* if the root has been reached, the height of the entire tree is
+ increased */
+ if (p == NULL) tree->height++;
+ return r;
+}
+
+void avl_set_node_type(AVLNODE *node, int type)
+{ /* assign the type field of specified node */
+ node->type = type;
+ return;
+}
+
+void avl_set_node_link(AVLNODE *node, void *link)
+{ /* assign the link field of specified node */
+ node->link = link;
+ return;
+}
+
+AVLNODE *avl_find_node(AVL *tree, const void *key)
+{ /* find node in AVL tree */
+ AVLNODE *p;
+ int c;
+ p = tree->root;
+ while (p != NULL)
+ { c = tree->fcmp(tree->info, key, p->key);
+ if (c == 0) break;
+ p = (c < 0 ? p->left : p->right);
+ }
+ return p;
+}
+
+int avl_get_node_type(AVLNODE *node)
+{ /* retrieve the type field of specified node */
+ return node->type;
+}
+
+void *avl_get_node_link(AVLNODE *node)
+{ /* retrieve the link field of specified node */
+ return node->link;
+}
+
+static AVLNODE *find_next_node(AVL *tree, AVLNODE *node)
+{ /* find next node in AVL tree */
+ AVLNODE *p, *q;
+ if (tree->root == NULL) return NULL;
+ p = node;
+ q = (p == NULL ? tree->root : p->right);
+ if (q == NULL)
+ { /* go upstairs from the left subtree */
+ for (;;)
+ { q = p->up;
+ if (q == NULL) break;
+ if (p->flag == 0) break;
+ p = q;
+ }
+ }
+ else
+ { /* go downstairs into the right subtree */
+ for (;;)
+ { p = q->left;
+ if (p == NULL) break;
+ q = p;
+ }
+ }
+ return q;
+}
+
+void avl_delete_node(AVL *tree, AVLNODE *node)
+{ /* delete specified node from AVL tree */
+ AVLNODE *f, *p, *q, *r, *s, *x, *y;
+ short int flag;
+ p = node;
+ /* if both subtrees of the specified node are non-empty, the node
+ should be interchanged with the next one, at least one subtree
+ of which is always empty */
+ if (p->left == NULL || p->right == NULL) goto skip;
+ f = p->up; q = p->left;
+ r = find_next_node(tree, p); s = r->right;
+ if (p->right == r)
+ { if (f == NULL)
+ tree->root = r;
+ else
+ if (p->flag == 0) f->left = r; else f->right = r;
+ r->rank = p->rank; r->up = f;
+ r->flag = p->flag; r->bal = p->bal;
+ r->left = q; r->right = p;
+ q->up = r;
+ p->rank = 1; p->up = r; p->flag = 1;
+ p->bal = (short int)(s == NULL ? 0 : +1);
+ p->left = NULL; p->right = s;
+ if (s != NULL) s->up = p;
+ }
+ else
+ { x = p->right; y = r->up;
+ if (f == NULL)
+ tree->root = r;
+ else
+ if (p->flag == 0) f->left = r; else f->right = r;
+ r->rank = p->rank; r->up = f;
+ r->flag = p->flag; r->bal = p->bal;
+ r->left = q; r->right = x;
+ q->up = r; x->up = r; y->left = p;
+ p->rank = 1; p->up = y; p->flag = 0;
+ p->bal = (short int)(s == NULL ? 0 : +1);
+ p->left = NULL; p->right = s;
+ if (s != NULL) s->up = p;
+ }
+skip: /* now the specified node [p] has at least one empty subtree;
+ go upstairs to the root and adjust the rank field of all nodes
+ affected by deletion */
+ q = p; f = q->up;
+ while (f != NULL)
+ { if (q->flag == 0) f->rank--;
+ q = f; f = q->up;
+ }
+ /* delete the specified node from the tree */
+ f = p->up; flag = p->flag;
+ q = p->left != NULL ? p->left : p->right;
+ if (f == NULL)
+ tree->root = q;
+ else
+ if (flag == 0) f->left = q; else f->right = q;
+ if (q != NULL) q->up = f, q->flag = flag;
+ tree->size--;
+ /* go upstairs to the root and correct all subtrees affected by
+ deletion */
+ while (f != NULL)
+ { if (flag == 0)
+ { /* the height of the left subtree of [f] is decreased */
+ if (f->bal == 0)
+ { f->bal = +1;
+ break;
+ }
+ if (f->bal < 0)
+ f->bal = 0;
+ else
+ { f = rotate_subtree(tree, f);
+ if (f->bal < 0) break;
+ }
+ flag = f->flag; f = f->up;
+ }
+ else
+ { /* the height of the right subtree of [f] is decreased */
+ if (f->bal == 0)
+ { f->bal = -1;
+ break;
+ }
+ if (f->bal > 0)
+ f->bal = 0;
+ else
+ { f = rotate_subtree(tree, f);
+ if (f->bal > 0) break;
+ }
+ flag = f->flag; f = f->up;
+ }
+ }
+ /* if the root has been reached, the height of the entire tree is
+ decreased */
+ if (f == NULL) tree->height--;
+ /* returns the deleted node to the memory pool */
+ dmp_free_atom(tree->pool, p, sizeof(AVLNODE));
+ return;
+}
+
+static AVLNODE *rotate_subtree(AVL *tree, AVLNODE *node)
+{ /* restore balance of AVL subtree */
+ AVLNODE *f, *p, *q, *r, *x, *y;
+ xassert(node != NULL);
+ p = node;
+ if (p->bal < 0)
+ { /* perform negative (left) rotation */
+ f = p->up; q = p->left; r = q->right;
+ if (q->bal <= 0)
+ { /* perform single negative rotation */
+ if (f == NULL)
+ tree->root = q;
+ else
+ if (p->flag == 0) f->left = q; else f->right = q;
+ p->rank -= q->rank;
+ q->up = f; q->flag = p->flag; q->bal++; q->right = p;
+ p->up = q; p->flag = 1;
+ p->bal = (short int)(-q->bal); p->left = r;
+ if (r != NULL) r->up = p, r->flag = 0;
+ node = q;
+ }
+ else
+ { /* perform double negative rotation */
+ x = r->left; y = r->right;
+ if (f == NULL)
+ tree->root = r;
+ else
+ if (p->flag == 0) f->left = r; else f->right = r;
+ p->rank -= (q->rank + r->rank);
+ r->rank += q->rank;
+ p->bal = (short int)(r->bal >= 0 ? 0 : +1);
+ q->bal = (short int)(r->bal <= 0 ? 0 : -1);
+ r->up = f; r->flag = p->flag; r->bal = 0;
+ r->left = q; r->right = p;
+ p->up = r; p->flag = 1; p->left = y;
+ q->up = r; q->flag = 0; q->right = x;
+ if (x != NULL) x->up = q, x->flag = 1;
+ if (y != NULL) y->up = p, y->flag = 0;
+ node = r;
+ }
+ }
+ else
+ { /* perform positive (right) rotation */
+ f = p->up; q = p->right; r = q->left;
+ if (q->bal >= 0)
+ { /* perform single positive rotation */
+ if (f == NULL)
+ tree->root = q;
+ else
+ if (p->flag == 0) f->left = q; else f->right = q;
+ q->rank += p->rank;
+ q->up = f; q->flag = p->flag; q->bal--; q->left = p;
+ p->up = q; p->flag = 0;
+ p->bal = (short int)(-q->bal); p->right = r;
+ if (r != NULL) r->up = p, r->flag = 1;
+ node = q;
+ }
+ else
+ { /* perform double positive rotation */
+ x = r->left; y = r->right;
+ if (f == NULL)
+ tree->root = r;
+ else
+ if (p->flag == 0) f->left = r; else f->right = r;
+ q->rank -= r->rank;
+ r->rank += p->rank;
+ p->bal = (short int)(r->bal <= 0 ? 0 : -1);
+ q->bal = (short int)(r->bal >= 0 ? 0 : +1);
+ r->up = f; r->flag = p->flag; r->bal = 0;
+ r->left = p; r->right = q;
+ p->up = r; p->flag = 0; p->right = x;
+ q->up = r; q->flag = 1; q->left = y;
+ if (x != NULL) x->up = p, x->flag = 1;
+ if (y != NULL) y->up = q, y->flag = 0;
+ node = r;
+ }
+ }
+ return node;
+}
+
+void avl_delete_tree(AVL *tree)
+{ /* delete AVL tree */
+ dmp_delete_pool(tree->pool);
+ xfree(tree);
+ return;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/avl.h b/test/monniaux/glpk-4.65/src/misc/avl.h
new file mode 100644
index 00000000..b0aaef61
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/avl.h
@@ -0,0 +1,73 @@
+/* avl.h (binary search tree) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#ifndef AVL_H
+#define AVL_H
+
+typedef struct AVL AVL;
+typedef struct AVLNODE AVLNODE;
+
+#define avl_create_tree _glp_avl_create_tree
+AVL *avl_create_tree(int (*fcmp)(void *info, const void *key1,
+ const void *key2), void *info);
+/* create AVL tree */
+
+#define avl_strcmp _glp_avl_strcmp
+int avl_strcmp(void *info, const void *key1, const void *key2);
+/* compare character string keys */
+
+#define avl_insert_node _glp_avl_insert_node
+AVLNODE *avl_insert_node(AVL *tree, const void *key);
+/* insert new node into AVL tree */
+
+#define avl_set_node_type _glp_avl_set_node_type
+void avl_set_node_type(AVLNODE *node, int type);
+/* assign the type field of specified node */
+
+#define avl_set_node_link _glp_avl_set_node_link
+void avl_set_node_link(AVLNODE *node, void *link);
+/* assign the link field of specified node */
+
+#define avl_find_node _glp_avl_find_node
+AVLNODE *avl_find_node(AVL *tree, const void *key);
+/* find node in AVL tree */
+
+#define avl_get_node_type _glp_avl_get_node_type
+int avl_get_node_type(AVLNODE *node);
+/* retrieve the type field of specified node */
+
+#define avl_get_node_link _glp_avl_get_node_link
+void *avl_get_node_link(AVLNODE *node);
+/* retrieve the link field of specified node */
+
+#define avl_delete_node _glp_avl_delete_node
+void avl_delete_node(AVL *tree, AVLNODE *node);
+/* delete specified node from AVL tree */
+
+#define avl_delete_tree _glp_avl_delete_tree
+void avl_delete_tree(AVL *tree);
+/* delete AVL tree */
+
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/bignum.c b/test/monniaux/glpk-4.65/src/misc/bignum.c
new file mode 100644
index 00000000..540dd9fd
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/bignum.c
@@ -0,0 +1,286 @@
+/* bignum.c (bignum arithmetic) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2006-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include "env.h"
+#include "bignum.h"
+
+/***********************************************************************
+* Two routines below are intended to multiply and divide unsigned
+* integer numbers of arbitrary precision.
+*
+* The routines assume that an unsigned integer number is represented in
+* the positional numeral system with the base 2^16 = 65536, i.e. each
+* "digit" of the number is in the range [0, 65535] and represented as
+* a 16-bit value of the unsigned short type. In other words, a number x
+* has the following representation:
+*
+* n-1
+* x = sum d[j] * 65536^j,
+* j=0
+*
+* where n is the number of places (positions), and d[j] is j-th "digit"
+* of x, 0 <= d[j] <= 65535.
+***********************************************************************/
+
+/***********************************************************************
+* NAME
+*
+* bigmul - multiply unsigned integer numbers of arbitrary precision
+*
+* SYNOPSIS
+*
+* #include "bignum.h"
+* void bigmul(int n, int m, unsigned short x[], unsigned short y[]);
+*
+* DESCRIPTION
+*
+* The routine bigmul multiplies unsigned integer numbers of arbitrary
+* precision.
+*
+* n is the number of digits of multiplicand, n >= 1;
+*
+* m is the number of digits of multiplier, m >= 1;
+*
+* x is an array containing digits of the multiplicand in elements
+* x[m], x[m+1], ..., x[n+m-1]. Contents of x[0], x[1], ..., x[m-1] are
+* ignored on entry.
+*
+* y is an array containing digits of the multiplier in elements y[0],
+* y[1], ..., y[m-1].
+*
+* On exit digits of the product are stored in elements x[0], x[1], ...,
+* x[n+m-1]. The array y is not changed. */
+
+void bigmul(int n, int m, unsigned short x[], unsigned short y[])
+{ int i, j;
+ unsigned int t;
+ xassert(n >= 1);
+ xassert(m >= 1);
+ for (j = 0; j < m; j++) x[j] = 0;
+ for (i = 0; i < n; i++)
+ { if (x[i+m])
+ { t = 0;
+ for (j = 0; j < m; j++)
+ { t += (unsigned int)x[i+m] * (unsigned int)y[j] +
+ (unsigned int)x[i+j];
+ x[i+j] = (unsigned short)t;
+ t >>= 16;
+ }
+ x[i+m] = (unsigned short)t;
+ }
+ }
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* bigdiv - divide unsigned integer numbers of arbitrary precision
+*
+* SYNOPSIS
+*
+* #include "bignum.h"
+* void bigdiv(int n, int m, unsigned short x[], unsigned short y[]);
+*
+* DESCRIPTION
+*
+* The routine bigdiv divides one unsigned integer number of arbitrary
+* precision by another with the algorithm described in [1].
+*
+* n is the difference between the number of digits of dividend and the
+* number of digits of divisor, n >= 0.
+*
+* m is the number of digits of divisor, m >= 1.
+*
+* x is an array containing digits of the dividend in elements x[0],
+* x[1], ..., x[n+m-1].
+*
+* y is an array containing digits of the divisor in elements y[0],
+* y[1], ..., y[m-1]. The highest digit y[m-1] must be non-zero.
+*
+* On exit n+1 digits of the quotient are stored in elements x[m],
+* x[m+1], ..., x[n+m], and m digits of the remainder are stored in
+* elements x[0], x[1], ..., x[m-1]. The array y is changed but then
+* restored.
+*
+* REFERENCES
+*
+* 1. D. Knuth. The Art of Computer Programming. Vol. 2: Seminumerical
+* Algorithms. Stanford University, 1969. */
+
+void bigdiv(int n, int m, unsigned short x[], unsigned short y[])
+{ int i, j;
+ unsigned int t;
+ unsigned short d, q, r;
+ xassert(n >= 0);
+ xassert(m >= 1);
+ xassert(y[m-1] != 0);
+ /* special case when divisor has the only digit */
+ if (m == 1)
+ { d = 0;
+ for (i = n; i >= 0; i--)
+ { t = ((unsigned int)d << 16) + (unsigned int)x[i];
+ x[i+1] = (unsigned short)(t / y[0]);
+ d = (unsigned short)(t % y[0]);
+ }
+ x[0] = d;
+ goto done;
+ }
+ /* multiply dividend and divisor by a normalizing coefficient in
+ * order to provide the condition y[m-1] >= base / 2 */
+ d = (unsigned short)(0x10000 / ((unsigned int)y[m-1] + 1));
+ if (d == 1)
+ x[n+m] = 0;
+ else
+ { t = 0;
+ for (i = 0; i < n+m; i++)
+ { t += (unsigned int)x[i] * (unsigned int)d;
+ x[i] = (unsigned short)t;
+ t >>= 16;
+ }
+ x[n+m] = (unsigned short)t;
+ t = 0;
+ for (j = 0; j < m; j++)
+ { t += (unsigned int)y[j] * (unsigned int)d;
+ y[j] = (unsigned short)t;
+ t >>= 16;
+ }
+ }
+ /* main loop */
+ for (i = n; i >= 0; i--)
+ { /* estimate and correct the current digit of quotient */
+ if (x[i+m] < y[m-1])
+ { t = ((unsigned int)x[i+m] << 16) + (unsigned int)x[i+m-1];
+ q = (unsigned short)(t / (unsigned int)y[m-1]);
+ r = (unsigned short)(t % (unsigned int)y[m-1]);
+ if (q == 0) goto putq; else goto test;
+ }
+ q = 0;
+ r = x[i+m-1];
+decr: q--; /* if q = 0 then q-- = 0xFFFF */
+ t = (unsigned int)r + (unsigned int)y[m-1];
+ r = (unsigned short)t;
+ if (t > 0xFFFF) goto msub;
+test: t = (unsigned int)y[m-2] * (unsigned int)q;
+ if ((unsigned short)(t >> 16) > r) goto decr;
+ if ((unsigned short)(t >> 16) < r) goto msub;
+ if ((unsigned short)t > x[i+m-2]) goto decr;
+msub: /* now subtract divisor multiplied by the current digit of
+ * quotient from the current dividend */
+ if (q == 0) goto putq;
+ t = 0;
+ for (j = 0; j < m; j++)
+ { t += (unsigned int)y[j] * (unsigned int)q;
+ if (x[i+j] < (unsigned short)t) t += 0x10000;
+ x[i+j] -= (unsigned short)t;
+ t >>= 16;
+ }
+ if (x[i+m] >= (unsigned short)t) goto putq;
+ /* perform correcting addition, because the current digit of
+ * quotient is greater by one than its correct value */
+ q--;
+ t = 0;
+ for (j = 0; j < m; j++)
+ { t += (unsigned int)x[i+j] + (unsigned int)y[j];
+ x[i+j] = (unsigned short)t;
+ t >>= 16;
+ }
+putq: /* store the current digit of quotient */
+ x[i+m] = q;
+ }
+ /* divide divisor and remainder by the normalizing coefficient in
+ * order to restore their original values */
+ if (d > 1)
+ { t = 0;
+ for (i = m-1; i >= 0; i--)
+ { t = (t << 16) + (unsigned int)x[i];
+ x[i] = (unsigned short)(t / (unsigned int)d);
+ t %= (unsigned int)d;
+ }
+ t = 0;
+ for (j = m-1; j >= 0; j--)
+ { t = (t << 16) + (unsigned int)y[j];
+ y[j] = (unsigned short)(t / (unsigned int)d);
+ t %= (unsigned int)d;
+ }
+ }
+done: return;
+}
+
+/**********************************************************************/
+
+#ifdef GLP_TEST
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "rng.h"
+
+#define N_MAX 7
+/* maximal number of digits in multiplicand */
+
+#define M_MAX 5
+/* maximal number of digits in multiplier */
+
+#define N_TEST 1000000
+/* number of tests */
+
+int main(void)
+{ RNG *rand;
+ int d, j, n, m, test;
+ unsigned short x[N_MAX], y[M_MAX], z[N_MAX+M_MAX];
+ rand = rng_create_rand();
+ for (test = 1; test <= N_TEST; test++)
+ { /* x[0,...,n-1] := multiplicand */
+ n = 1 + rng_unif_rand(rand, N_MAX-1);
+ assert(1 <= n && n <= N_MAX);
+ for (j = 0; j < n; j++)
+ { d = rng_unif_rand(rand, 65536);
+ assert(0 <= d && d <= 65535);
+ x[j] = (unsigned short)d;
+ }
+ /* y[0,...,m-1] := multiplier */
+ m = 1 + rng_unif_rand(rand, M_MAX-1);
+ assert(1 <= m && m <= M_MAX);
+ for (j = 0; j < m; j++)
+ { d = rng_unif_rand(rand, 65536);
+ assert(0 <= d && d <= 65535);
+ y[j] = (unsigned short)d;
+ }
+ if (y[m-1] == 0) y[m-1] = 1;
+ /* z[0,...,n+m-1] := x * y */
+ for (j = 0; j < n; j++) z[m+j] = x[j];
+ bigmul(n, m, z, y);
+ /* z[0,...,m-1] := z mod y, z[m,...,n+m-1] := z div y */
+ bigdiv(n, m, z, y);
+ /* z mod y must be 0 */
+ for (j = 0; j < m; j++) assert(z[j] == 0);
+ /* z div y must be x */
+ for (j = 0; j < n; j++) assert(z[m+j] == x[j]);
+ }
+ fprintf(stderr, "%d tests successfully passed\n", N_TEST);
+ rng_delete_rand(rand);
+ return 0;
+}
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/bignum.h b/test/monniaux/glpk-4.65/src/misc/bignum.h
new file mode 100644
index 00000000..8567519b
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/bignum.h
@@ -0,0 +1,37 @@
+/* bignum.h (bignum arithmetic) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2006-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#ifndef BIGNUM_H
+#define BIGNUM_H
+
+#define bigmul _glp_bigmul
+void bigmul(int n, int m, unsigned short x[], unsigned short y[]);
+/* multiply unsigned integer numbers of arbitrary precision */
+
+#define bigdiv _glp_bigdiv
+void bigdiv(int n, int m, unsigned short x[], unsigned short y[]);
+/* divide unsigned integer numbers of arbitrary precision */
+
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/dimacs.c b/test/monniaux/glpk-4.65/src/misc/dimacs.c
new file mode 100644
index 00000000..6aa630a5
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/dimacs.c
@@ -0,0 +1,147 @@
+/* dimacs.c (reading data in DIMACS format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2015 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include "dimacs.h"
+
+void dmx_error(DMX *csa, const char *fmt, ...)
+{ /* print error message and terminate processing */
+ va_list arg;
+ xprintf("%s:%d: error: ", csa->fname, csa->count);
+ va_start(arg, fmt);
+ xvprintf(fmt, arg);
+ va_end(arg);
+ xprintf("\n");
+ longjmp(csa->jump, 1);
+ /* no return */
+}
+
+void dmx_warning(DMX *csa, const char *fmt, ...)
+{ /* print warning message and continue processing */
+ va_list arg;
+ xprintf("%s:%d: warning: ", csa->fname, csa->count);
+ va_start(arg, fmt);
+ xvprintf(fmt, arg);
+ va_end(arg);
+ xprintf("\n");
+ return;
+}
+
+void dmx_read_char(DMX *csa)
+{ /* read character from input text file */
+ int c;
+ if (csa->c == '\n') csa->count++;
+ c = glp_getc(csa->fp);
+ if (c < 0)
+ { if (glp_ioerr(csa->fp))
+ dmx_error(csa, "read error - %s", get_err_msg());
+ else if (csa->c == '\n')
+ dmx_error(csa, "unexpected end of file");
+ else
+ { dmx_warning(csa, "missing final end of line");
+ c = '\n';
+ }
+ }
+ else if (c == '\n')
+ ;
+ else if (isspace(c))
+ c = ' ';
+ else if (iscntrl(c))
+ dmx_error(csa, "invalid control character 0x%02X", c);
+ csa->c = c;
+ return;
+}
+
+void dmx_read_designator(DMX *csa)
+{ /* read one-character line designator */
+ xassert(csa->c == '\n');
+ dmx_read_char(csa);
+ for (;;)
+ { /* skip preceding white-space characters */
+ while (csa->c == ' ')
+ dmx_read_char(csa);
+ if (csa->c == '\n')
+ { /* ignore empty line */
+ if (!csa->empty)
+ { dmx_warning(csa, "empty line ignored");
+ csa->empty = 1;
+ }
+ dmx_read_char(csa);
+ }
+ else if (csa->c == 'c')
+ { /* skip comment line */
+ while (csa->c != '\n')
+ dmx_read_char(csa);
+ dmx_read_char(csa);
+ }
+ else
+ { /* hmm... looks like a line designator */
+ csa->field[0] = (char)csa->c, csa->field[1] = '\0';
+ /* check that it is followed by a white-space character */
+ dmx_read_char(csa);
+ if (!(csa->c == ' ' || csa->c == '\n'))
+ dmx_error(csa, "line designator missing or invalid");
+ break;
+ }
+ }
+ return;
+}
+
+void dmx_read_field(DMX *csa)
+{ /* read data field */
+ int len = 0;
+ /* skip preceding white-space characters */
+ while (csa->c == ' ')
+ dmx_read_char(csa);
+ /* scan data field */
+ if (csa->c == '\n')
+ dmx_error(csa, "unexpected end of line");
+ while (!(csa->c == ' ' || csa->c == '\n'))
+ { if (len == sizeof(csa->field)-1)
+ dmx_error(csa, "data field '%.15s...' too long",
+ csa->field);
+ csa->field[len++] = (char)csa->c;
+ dmx_read_char(csa);
+ }
+ csa->field[len] = '\0';
+ return;
+}
+
+void dmx_end_of_line(DMX *csa)
+{ /* skip white-space characters until end of line */
+ while (csa->c == ' ')
+ dmx_read_char(csa);
+ if (csa->c != '\n')
+ dmx_error(csa, "too many data fields specified");
+ return;
+}
+
+void dmx_check_int(DMX *csa, double num)
+{ /* print a warning if non-integer data are detected */
+ if (!csa->nonint && num != floor(num))
+ { dmx_warning(csa, "non-integer data detected");
+ csa->nonint = 1;
+ }
+ return;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/dimacs.h b/test/monniaux/glpk-4.65/src/misc/dimacs.h
new file mode 100644
index 00000000..42fb9996
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/dimacs.h
@@ -0,0 +1,81 @@
+/* dimacs.h (reading data in DIMACS format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2015 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#ifndef DIMACS_H
+#define DIMACS_H
+
+#include "env.h"
+
+typedef struct DMX DMX;
+
+struct DMX
+{ /* DIMACS data reader */
+ jmp_buf jump;
+ /* label for go to in case of error */
+ const char *fname;
+ /* name of input text file */
+ glp_file *fp;
+ /* stream assigned to input text file */
+ int count;
+ /* line count */
+ int c;
+ /* current character */
+ char field[255+1];
+ /* data field */
+ int empty;
+ /* warning 'empty line ignored' was printed */
+ int nonint;
+ /* warning 'non-integer data detected' was printed */
+};
+
+#define dmx_error _glp_dmx_error
+void dmx_error(DMX *csa, const char *fmt, ...);
+/* print error message and terminate processing */
+
+#define dmx_warning _glp_dmx_warning
+void dmx_warning(DMX *csa, const char *fmt, ...);
+/* print warning message and continue processing */
+
+#define dmx_read_char _glp_dmx_read_char
+void dmx_read_char(DMX *csa);
+/* read character from input text file */
+
+#define dmx_read_designator _glp_dmx_read_designator
+void dmx_read_designator(DMX *csa);
+/* read one-character line designator */
+
+#define dmx_read_field _glp_dmx_read_field
+void dmx_read_field(DMX *csa);
+/* read data field */
+
+#define dmx_end_of_line _glp_dmx_end_of_line
+void dmx_end_of_line(DMX *csa);
+/* skip white-space characters until end of line */
+
+#define dmx_check_int _glp_dmx_check_int
+void dmx_check_int(DMX *csa, double num);
+/* print a warning if non-integer data are detected */
+
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/dmp.c b/test/monniaux/glpk-4.65/src/misc/dmp.c
new file mode 100644
index 00000000..a4882c86
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/dmp.c
@@ -0,0 +1,243 @@
+/* dmp.c (dynamic memory pool) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include "env.h"
+#include "dmp.h"
+
+struct DMP
+{ /* dynamic memory pool */
+ void *avail[32];
+ /* avail[k], 0 <= k <= 31, is a pointer to first available (free)
+ * atom of (k+1)*8 bytes long; at the beginning of each free atom
+ * there is a pointer to another free atom of the same size */
+ void *block;
+ /* pointer to most recently allocated memory block; at the
+ * beginning of each allocated memory block there is a pointer to
+ * previously allocated memory block */
+ int used;
+ /* number of bytes used in most recently allocated memory block */
+ size_t count;
+ /* number of atoms which are currently in use */
+};
+
+#define DMP_BLK_SIZE 8000
+/* size of memory blocks, in bytes, allocated for memory pools */
+
+struct prefix
+{ /* atom prefix (for debugging only) */
+ DMP *pool;
+ /* dynamic memory pool */
+ int size;
+ /* original atom size, in bytes */
+};
+
+#define prefix_size ((sizeof(struct prefix) + 7) & ~7)
+/* size of atom prefix rounded up to multiple of 8 bytes */
+
+int dmp_debug;
+/* debug mode flag */
+
+/***********************************************************************
+* NAME
+*
+* dmp_create_pool - create dynamic memory pool
+*
+* SYNOPSIS
+*
+* #include "dmp.h"
+* DMP *dmp_create_pool(void);
+*
+* DESCRIPTION
+*
+* The routine dmp_create_pool creates a dynamic memory pool.
+*
+* RETURNS
+*
+* The routine returns a pointer to the memory pool created. */
+
+DMP *dmp_create_pool(void)
+{ DMP *pool;
+ int k;
+ xassert(sizeof(void *) <= 8);
+ if (dmp_debug)
+ xprintf("dmp_create_pool: warning: debug mode is on\n");
+ pool = talloc(1, DMP);
+ for (k = 0; k <= 31; k++)
+ pool->avail[k] = NULL;
+ pool->block = NULL;
+ pool->used = DMP_BLK_SIZE;
+ pool->count = 0;
+ return pool;
+}
+
+/***********************************************************************
+* NAME
+*
+* dmp_get_atom - get free atom from dynamic memory pool
+*
+* SYNOPSIS
+*
+* #include "dmp.h"
+* void *dmp_get_atom(DMP *pool, int size);
+*
+* DESCRIPTION
+*
+* The routine dmp_get_atom obtains a free atom (memory space) from the
+* specified memory pool.
+*
+* The parameter size is the atom size, in bytes, 1 <= size <= 256.
+*
+* Note that the free atom contains arbitrary data, not binary zeros.
+*
+* RETURNS
+*
+* The routine returns a pointer to the free atom obtained. */
+
+void *dmp_get_atom(DMP *pool, int size)
+{ void *atom;
+ int k, need;
+ xassert(1 <= size && size <= 256);
+ /* round up atom size to multiple of 8 bytes */
+ need = (size + 7) & ~7;
+ /* determine number of corresponding list of free atoms */
+ k = (need >> 3) - 1;
+ /* obtain free atom */
+ if (pool->avail[k] == NULL)
+ { /* corresponding list of free atoms is empty */
+ /* if debug mode is on, add atom prefix size */
+ if (dmp_debug)
+ need += prefix_size;
+ if (pool->used + need > DMP_BLK_SIZE)
+ { /* allocate new memory block */
+ void *block = talloc(DMP_BLK_SIZE, char);
+ *(void **)block = pool->block;
+ pool->block = block;
+ pool->used = 8; /* sufficient to store pointer */
+ }
+ /* allocate new atom in current memory block */
+ atom = (char *)pool->block + pool->used;
+ pool->used += need;
+ }
+ else
+ { /* obtain atom from corresponding list of free atoms */
+ atom = pool->avail[k];
+ pool->avail[k] = *(void **)atom;
+ }
+ /* if debug mode is on, fill atom prefix */
+ if (dmp_debug)
+ { ((struct prefix *)atom)->pool = pool;
+ ((struct prefix *)atom)->size = size;
+ atom = (char *)atom + prefix_size;
+ }
+ /* increase number of allocated atoms */
+ pool->count++;
+ return atom;
+}
+
+/***********************************************************************
+* NAME
+*
+* dmp_free_atom - return atom to dynamic memory pool
+*
+* SYNOPSIS
+*
+* #include "dmp.h"
+* void dmp_free_atom(DMP *pool, void *atom, int size);
+*
+* DESCRIPTION
+*
+* The routine dmp_free_atom returns the specified atom (memory space)
+* to the specified memory pool, making the atom free.
+*
+* The parameter size is the atom size, in bytes, 1 <= size <= 256.
+*
+* Note that the atom can be returned only to the pool, from which it
+* was obtained, and its size must be exactly the same as on obtaining
+* it from the pool. */
+
+void dmp_free_atom(DMP *pool, void *atom, int size)
+{ int k;
+ xassert(1 <= size && size <= 256);
+ /* determine number of corresponding list of free atoms */
+ k = ((size + 7) >> 3) - 1;
+ /* if debug mode is on, check atom prefix */
+ if (dmp_debug)
+ { atom = (char *)atom - prefix_size;
+ xassert(((struct prefix *)atom)->pool == pool);
+ xassert(((struct prefix *)atom)->size == size);
+ }
+ /* return atom to corresponding list of free atoms */
+ *(void **)atom = pool->avail[k];
+ pool->avail[k] = atom;
+ /* decrease number of allocated atoms */
+ xassert(pool->count > 0);
+ pool->count--;
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* dmp_in_use - determine how many atoms are still in use
+*
+* SYNOPSIS
+*
+* #include "dmp.h"
+* size_t dmp_in_use(DMP *pool);
+*
+* RETURNS
+*
+* The routine returns the number of atoms of the specified memory pool
+* which are still in use. */
+
+size_t dmp_in_use(DMP *pool)
+{ return
+ pool->count;
+}
+
+/***********************************************************************
+* NAME
+*
+* dmp_delete_pool - delete dynamic memory pool
+*
+* SYNOPSIS
+*
+* #include "dmp.h"
+* void dmp_delete_pool(DMP *pool);
+*
+* DESCRIPTION
+*
+* The routine dmp_delete_pool deletes the specified dynamic memory
+* pool freeing all the memory allocated to this object. */
+
+void dmp_delete_pool(DMP *pool)
+{ while (pool->block != NULL)
+ { void *block = pool->block;
+ pool->block = *(void **)block;
+ tfree(block);
+ }
+ tfree(pool);
+ return;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/dmp.h b/test/monniaux/glpk-4.65/src/misc/dmp.h
new file mode 100644
index 00000000..85fe7176
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/dmp.h
@@ -0,0 +1,63 @@
+/* dmp.h (dynamic memory pool) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#ifndef DMP_H
+#define DMP_H
+
+#include "stdc.h"
+
+typedef struct DMP DMP;
+
+#define dmp_debug _glp_dmp_debug
+extern int dmp_debug;
+/* debug mode flag */
+
+#define dmp_create_pool _glp_dmp_create_pool
+DMP *dmp_create_pool(void);
+/* create dynamic memory pool */
+
+#define dmp_talloc(pool, type) \
+ ((type *)dmp_get_atom(pool, sizeof(type)))
+
+#define dmp_get_atom _glp_dmp_get_atom
+void *dmp_get_atom(DMP *pool, int size);
+/* get free atom from dynamic memory pool */
+
+#define dmp_tfree(pool, atom) \
+ dmp_free_atom(pool, atom, sizeof(*(atom)))
+
+#define dmp_free_atom _glp_dmp_free_atom
+void dmp_free_atom(DMP *pool, void *atom, int size);
+/* return atom to dynamic memory pool */
+
+#define dmp_in_use _glp_dmp_in_use
+size_t dmp_in_use(DMP *pool);
+/* determine how many atoms are still in use */
+
+#define dmp_delete_pool _glp_dmp_delete_pool
+void dmp_delete_pool(DMP *pool);
+/* delete dynamic memory pool */
+
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/ffalg.c b/test/monniaux/glpk-4.65/src/misc/ffalg.c
new file mode 100644
index 00000000..4ea2913d
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/ffalg.c
@@ -0,0 +1,221 @@
+/* ffalg.c (Ford-Fulkerson algorithm) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include "env.h"
+#include "ffalg.h"
+
+/***********************************************************************
+* NAME
+*
+* ffalg - Ford-Fulkerson algorithm
+*
+* SYNOPSIS
+*
+* #include "ffalg.h"
+* void ffalg(int nv, int na, const int tail[], const int head[],
+* int s, int t, const int cap[], int x[], char cut[]);
+*
+* DESCRIPTION
+*
+* The routine ffalg implements the Ford-Fulkerson algorithm to find a
+* maximal flow in the specified flow network.
+*
+* INPUT PARAMETERS
+*
+* nv is the number of nodes, nv >= 2.
+*
+* na is the number of arcs, na >= 0.
+*
+* tail[a], a = 1,...,na, is the index of tail node of arc a.
+*
+* head[a], a = 1,...,na, is the index of head node of arc a.
+*
+* s is the source node index, 1 <= s <= nv.
+*
+* t is the sink node index, 1 <= t <= nv, t != s.
+*
+* cap[a], a = 1,...,na, is the capacity of arc a, cap[a] >= 0.
+*
+* NOTE: Multiple arcs are allowed, but self-loops are not allowed.
+*
+* OUTPUT PARAMETERS
+*
+* x[a], a = 1,...,na, is optimal value of the flow through arc a.
+*
+* cut[i], i = 1,...,nv, is 1 if node i is labelled, and 0 otherwise.
+* The set of arcs, whose one endpoint is labelled and other is not,
+* defines the minimal cut corresponding to the maximal flow found.
+* If the parameter cut is NULL, the cut information are not stored.
+*
+* REFERENCES
+*
+* L.R.Ford, Jr., and D.R.Fulkerson, "Flows in Networks," The RAND
+* Corp., Report R-375-PR (August 1962), Chap. I "Static Maximal Flow,"
+* pp.30-33. */
+
+void ffalg(int nv, int na, const int tail[], const int head[],
+ int s, int t, const int cap[], int x[], char cut[])
+{ int a, delta, i, j, k, pos1, pos2, temp,
+ *ptr, *arc, *link, *list;
+ /* sanity checks */
+ xassert(nv >= 2);
+ xassert(na >= 0);
+ xassert(1 <= s && s <= nv);
+ xassert(1 <= t && t <= nv);
+ xassert(s != t);
+ for (a = 1; a <= na; a++)
+ { i = tail[a], j = head[a];
+ xassert(1 <= i && i <= nv);
+ xassert(1 <= j && j <= nv);
+ xassert(i != j);
+ xassert(cap[a] >= 0);
+ }
+ /* allocate working arrays */
+ ptr = xcalloc(1+nv+1, sizeof(int));
+ arc = xcalloc(1+na+na, sizeof(int));
+ link = xcalloc(1+nv, sizeof(int));
+ list = xcalloc(1+nv, sizeof(int));
+ /* ptr[i] := (degree of node i) */
+ for (i = 1; i <= nv; i++)
+ ptr[i] = 0;
+ for (a = 1; a <= na; a++)
+ { ptr[tail[a]]++;
+ ptr[head[a]]++;
+ }
+ /* initialize arc pointers */
+ ptr[1]++;
+ for (i = 1; i < nv; i++)
+ ptr[i+1] += ptr[i];
+ ptr[nv+1] = ptr[nv];
+ /* build arc lists */
+ for (a = 1; a <= na; a++)
+ { arc[--ptr[tail[a]]] = a;
+ arc[--ptr[head[a]]] = a;
+ }
+ xassert(ptr[1] == 1);
+ xassert(ptr[nv+1] == na+na+1);
+ /* now the indices of arcs incident to node i are stored in
+ * locations arc[ptr[i]], arc[ptr[i]+1], ..., arc[ptr[i+1]-1] */
+ /* initialize arc flows */
+ for (a = 1; a <= na; a++)
+ x[a] = 0;
+loop: /* main loop starts here */
+ /* build augmenting tree rooted at s */
+ /* link[i] = 0 means that node i is not labelled yet;
+ * link[i] = a means that arc a immediately precedes node i */
+ /* initially node s is labelled as the root */
+ for (i = 1; i <= nv; i++)
+ link[i] = 0;
+ link[s] = -1, list[1] = s, pos1 = pos2 = 1;
+ /* breadth first search */
+ while (pos1 <= pos2)
+ { /* dequeue node i */
+ i = list[pos1++];
+ /* consider all arcs incident to node i */
+ for (k = ptr[i]; k < ptr[i+1]; k++)
+ { a = arc[k];
+ if (tail[a] == i)
+ { /* a = i->j is a forward arc from s to t */
+ j = head[a];
+ /* if node j has been labelled, skip the arc */
+ if (link[j] != 0) continue;
+ /* if the arc does not allow increasing the flow through
+ * it, skip the arc */
+ if (x[a] == cap[a]) continue;
+ }
+ else if (head[a] == i)
+ { /* a = i<-j is a backward arc from s to t */
+ j = tail[a];
+ /* if node j has been labelled, skip the arc */
+ if (link[j] != 0) continue;
+ /* if the arc does not allow decreasing the flow through
+ * it, skip the arc */
+ if (x[a] == 0) continue;
+ }
+ else
+ xassert(a != a);
+ /* label node j and enqueue it */
+ link[j] = a, list[++pos2] = j;
+ /* check for breakthrough */
+ if (j == t) goto brkt;
+ }
+ }
+ /* NONBREAKTHROUGH */
+ /* no augmenting path exists; current flow is maximal */
+ /* store minimal cut information, if necessary */
+ if (cut != NULL)
+ { for (i = 1; i <= nv; i++)
+ cut[i] = (char)(link[i] != 0);
+ }
+ goto done;
+brkt: /* BREAKTHROUGH */
+ /* walk through arcs of the augmenting path (s, ..., t) found in
+ * the reverse order and determine maximal change of the flow */
+ delta = 0;
+ for (j = t; j != s; j = i)
+ { /* arc a immediately precedes node j in the path */
+ a = link[j];
+ if (head[a] == j)
+ { /* a = i->j is a forward arc of the cycle */
+ i = tail[a];
+ /* x[a] may be increased until its upper bound */
+ temp = cap[a] - x[a];
+ }
+ else if (tail[a] == j)
+ { /* a = i<-j is a backward arc of the cycle */
+ i = head[a];
+ /* x[a] may be decreased until its lower bound */
+ temp = x[a];
+ }
+ else
+ xassert(a != a);
+ if (delta == 0 || delta > temp) delta = temp;
+ }
+ xassert(delta > 0);
+ /* increase the flow along the path */
+ for (j = t; j != s; j = i)
+ { /* arc a immediately precedes node j in the path */
+ a = link[j];
+ if (head[a] == j)
+ { /* a = i->j is a forward arc of the cycle */
+ i = tail[a];
+ x[a] += delta;
+ }
+ else if (tail[a] == j)
+ { /* a = i<-j is a backward arc of the cycle */
+ i = head[a];
+ x[a] -= delta;
+ }
+ else
+ xassert(a != a);
+ }
+ goto loop;
+done: /* free working arrays */
+ xfree(ptr);
+ xfree(arc);
+ xfree(link);
+ xfree(list);
+ return;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/ffalg.h b/test/monniaux/glpk-4.65/src/misc/ffalg.h
new file mode 100644
index 00000000..7016f8fa
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/ffalg.h
@@ -0,0 +1,34 @@
+/* ffalg.h (Ford-Fulkerson algorithm) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#ifndef FFALG_H
+#define FFALG_H
+
+#define ffalg _glp_ffalg
+void ffalg(int nv, int na, const int tail[], const int head[],
+ int s, int t, const int cap[], int x[], char cut[]);
+/* Ford-Fulkerson algorithm */
+
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/fp2rat.c b/test/monniaux/glpk-4.65/src/misc/fp2rat.c
new file mode 100644
index 00000000..4699bbd1
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/fp2rat.c
@@ -0,0 +1,164 @@
+/* fp2rat.c (convert floating-point number to rational number) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include "env.h"
+#include "misc.h"
+
+/***********************************************************************
+* NAME
+*
+* fp2rat - convert floating-point number to rational number
+*
+* SYNOPSIS
+*
+* #include "misc.h"
+* int fp2rat(double x, double eps, double *p, double *q);
+*
+* DESCRIPTION
+*
+* Given a floating-point number 0 <= x < 1 the routine fp2rat finds
+* its "best" rational approximation p / q, where p >= 0 and q > 0 are
+* integer numbers, such that |x - p / q| <= eps.
+*
+* RETURNS
+*
+* The routine fp2rat returns the number of iterations used to achieve
+* the specified precision eps.
+*
+* EXAMPLES
+*
+* For x = sqrt(2) - 1 = 0.414213562373095 and eps = 1e-6 the routine
+* gives p = 408 and q = 985, where 408 / 985 = 0.414213197969543.
+*
+* BACKGROUND
+*
+* It is well known that every positive real number x can be expressed
+* as the following continued fraction:
+*
+* x = b[0] + a[1]
+* ------------------------
+* b[1] + a[2]
+* -----------------
+* b[2] + a[3]
+* ----------
+* b[3] + ...
+*
+* where:
+*
+* a[k] = 1, k = 0, 1, 2, ...
+*
+* b[k] = floor(x[k]), k = 0, 1, 2, ...
+*
+* x[0] = x,
+*
+* x[k] = 1 / frac(x[k-1]), k = 1, 2, 3, ...
+*
+* To find the "best" rational approximation of x the routine computes
+* partial fractions f[k] by dropping after k terms as follows:
+*
+* f[k] = A[k] / B[k],
+*
+* where:
+*
+* A[-1] = 1, A[0] = b[0], B[-1] = 0, B[0] = 1,
+*
+* A[k] = b[k] * A[k-1] + a[k] * A[k-2],
+*
+* B[k] = b[k] * B[k-1] + a[k] * B[k-2].
+*
+* Once the condition
+*
+* |x - f[k]| <= eps
+*
+* has been satisfied, the routine reports p = A[k] and q = B[k] as the
+* final answer.
+*
+* In the table below here is some statistics obtained for one million
+* random numbers uniformly distributed in the range [0, 1).
+*
+* eps max p mean p max q mean q max k mean k
+* -------------------------------------------------------------
+* 1e-1 8 1.6 9 3.2 3 1.4
+* 1e-2 98 6.2 99 12.4 5 2.4
+* 1e-3 997 20.7 998 41.5 8 3.4
+* 1e-4 9959 66.6 9960 133.5 10 4.4
+* 1e-5 97403 211.7 97404 424.2 13 5.3
+* 1e-6 479669 669.9 479670 1342.9 15 6.3
+* 1e-7 1579030 2127.3 3962146 4257.8 16 7.3
+* 1e-8 26188823 6749.4 26188824 13503.4 19 8.2
+*
+* REFERENCES
+*
+* W. B. Jones and W. J. Thron, "Continued Fractions: Analytic Theory
+* and Applications," Encyclopedia on Mathematics and Its Applications,
+* Addison-Wesley, 1980. */
+
+int fp2rat(double x, double eps, double *p, double *q)
+{ int k;
+ double xk, Akm1, Ak, Bkm1, Bk, ak, bk, fk, temp;
+ xassert(0.0 <= x && x < 1.0);
+ for (k = 0; ; k++)
+ { xassert(k <= 100);
+ if (k == 0)
+ { /* x[0] = x */
+ xk = x;
+ /* A[-1] = 1 */
+ Akm1 = 1.0;
+ /* A[0] = b[0] = floor(x[0]) = 0 */
+ Ak = 0.0;
+ /* B[-1] = 0 */
+ Bkm1 = 0.0;
+ /* B[0] = 1 */
+ Bk = 1.0;
+ }
+ else
+ { /* x[k] = 1 / frac(x[k-1]) */
+ temp = xk - floor(xk);
+ xassert(temp != 0.0);
+ xk = 1.0 / temp;
+ /* a[k] = 1 */
+ ak = 1.0;
+ /* b[k] = floor(x[k]) */
+ bk = floor(xk);
+ /* A[k] = b[k] * A[k-1] + a[k] * A[k-2] */
+ temp = bk * Ak + ak * Akm1;
+ Akm1 = Ak, Ak = temp;
+ /* B[k] = b[k] * B[k-1] + a[k] * B[k-2] */
+ temp = bk * Bk + ak * Bkm1;
+ Bkm1 = Bk, Bk = temp;
+ }
+ /* f[k] = A[k] / B[k] */
+ fk = Ak / Bk;
+#if 0
+ print("%.*g / %.*g = %.*g",
+ DBL_DIG, Ak, DBL_DIG, Bk, DBL_DIG, fk);
+#endif
+ if (fabs(x - fk) <= eps)
+ break;
+ }
+ *p = Ak;
+ *q = Bk;
+ return k;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/fvs.c b/test/monniaux/glpk-4.65/src/misc/fvs.c
new file mode 100644
index 00000000..916a1bf9
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/fvs.c
@@ -0,0 +1,137 @@
+/* fvs.c (sparse vector in FVS format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include "env.h"
+#include "fvs.h"
+
+void fvs_alloc_vec(FVS *x, int n)
+{ /* allocate sparse vector */
+ int j;
+ xassert(n >= 0);
+ x->n = n;
+ x->nnz = 0;
+ x->ind = talloc(1+n, int);
+ x->vec = talloc(1+n, double);
+ for (j = 1; j <= n; j++)
+ x->vec[j] = 0.0;
+ return;
+}
+
+void fvs_check_vec(const FVS *x)
+{ /* check sparse vector */
+ /* NOTE: for testing/debugging only */
+ int n = x->n;
+ int nnz = x->nnz;
+ int *ind = x->ind;
+ double *vec = x->vec;
+ char *map;
+ int j, k;
+ xassert(n >= 0);
+ xassert(0 <= nnz && nnz <= n);
+ map = talloc(1+n, char);
+ for (j = 1; j <= n; j++)
+ map[j] = (vec[j] != 0.0);
+ for (k = 1; k <= nnz; k++)
+ { j = ind[k];
+ xassert(1 <= j && j <= n);
+ xassert(map[j]);
+ map[j] = 0;
+ }
+ for (j = 1; j <= n; j++)
+ xassert(!map[j]);
+ tfree(map);
+ return;
+}
+
+void fvs_gather_vec(FVS *x, double eps)
+{ /* gather sparse vector */
+ int n = x->n;
+ int *ind = x->ind;
+ double *vec = x->vec;
+ int j, nnz = 0;
+ for (j = n; j >= 1; j--)
+ { if (-eps < vec[j] && vec[j] < +eps)
+ vec[j] = 0.0;
+ else
+ ind[++nnz] = j;
+ }
+ x->nnz = nnz;
+ return;
+}
+
+void fvs_clear_vec(FVS *x)
+{ /* clear sparse vector */
+ int *ind = x->ind;
+ double *vec = x->vec;
+ int k;
+ for (k = x->nnz; k >= 1; k--)
+ vec[ind[k]] = 0.0;
+ x->nnz = 0;
+ return;
+}
+
+void fvs_copy_vec(FVS *x, const FVS *y)
+{ /* copy sparse vector */
+ int *x_ind = x->ind;
+ double *x_vec = x->vec;
+ int *y_ind = y->ind;
+ double *y_vec = y->vec;
+ int j, k;
+ xassert(x != y);
+ xassert(x->n == y->n);
+ fvs_clear_vec(x);
+ for (k = x->nnz = y->nnz; k >= 1; k--)
+ { j = x_ind[k] = y_ind[k];
+ x_vec[j] = y_vec[j];
+ }
+ return;
+}
+
+void fvs_adjust_vec(FVS *x, double eps)
+{ /* replace tiny vector elements by exact zeros */
+ int nnz = x->nnz;
+ int *ind = x->ind;
+ double *vec = x->vec;
+ int j, k, cnt = 0;
+ for (k = 1; k <= nnz; k++)
+ { j = ind[k];
+ if (-eps < vec[j] && vec[j] < +eps)
+ vec[j] = 0.0;
+ else
+ ind[++cnt] = j;
+ }
+ x->nnz = cnt;
+ return;
+}
+
+void fvs_free_vec(FVS *x)
+{ /* deallocate sparse vector */
+ tfree(x->ind);
+ tfree(x->vec);
+ x->n = x->nnz = -1;
+ x->ind = NULL;
+ x->vec = NULL;
+ return;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/fvs.h b/test/monniaux/glpk-4.65/src/misc/fvs.h
new file mode 100644
index 00000000..abfed8cc
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/fvs.h
@@ -0,0 +1,76 @@
+/* fvs.h (sparse vector in FVS format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2016 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#ifndef FVS_H
+#define FVS_H
+
+typedef struct FVS FVS;
+
+struct FVS
+{ /* sparse vector in FVS (Full Vector Storage) format */
+ int n;
+ /* vector dimension (total number of elements) */
+ int nnz;
+ /* number of non-zero elements, 0 <= nnz <= n */
+ int *ind; /* int ind[1+n]; */
+ /* ind[0] is not used;
+ * ind[k] = j, 1 <= k <= nnz, means that vec[j] != 0
+ * non-zero indices in the array ind are stored in arbitrary
+ * order; if vec[j] = 0, its index j SHOULD NOT be presented in
+ * the array ind */
+ double *vec; /* double vec[1+n]; */
+ /* vec[0] is not used;
+ * vec[j], 1 <= j <= n, is a numeric value of j-th element */
+};
+
+#define fvs_alloc_vec _glp_fvs_alloc_vec
+void fvs_alloc_vec(FVS *x, int n);
+/* allocate sparse vector */
+
+#define fvs_check_vec _glp_fvs_check_vec
+void fvs_check_vec(const FVS *x);
+/* check sparse vector */
+
+#define fvs_gather_vec _glp_fvs_gather_vec
+void fvs_gather_vec(FVS *x, double eps);
+/* gather sparse vector */
+
+#define fvs_clear_vec _glp_fvs_clear_vec
+void fvs_clear_vec(FVS *x);
+/* clear sparse vector */
+
+#define fvs_copy_vec _glp_fvs_copy_vec
+void fvs_copy_vec(FVS *x, const FVS *y);
+/* copy sparse vector */
+
+#define fvs_adjust_vec _glp_fvs_adjust_vec
+void fvs_adjust_vec(FVS *x, double eps);
+/* replace tiny vector elements by exact zeros */
+
+#define fvs_free_vec _glp_fvs_free_vec
+void fvs_free_vec(FVS *x);
+/* deallocate sparse vector */
+
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/gcd.c b/test/monniaux/glpk-4.65/src/misc/gcd.c
new file mode 100644
index 00000000..95c48cc0
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/gcd.c
@@ -0,0 +1,102 @@
+/* gcd.c (greatest common divisor) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include "env.h"
+#include "misc.h"
+
+/***********************************************************************
+* NAME
+*
+* gcd - find greatest common divisor of two integers
+*
+* SYNOPSIS
+*
+* #include "misc.h"
+* int gcd(int x, int y);
+*
+* RETURNS
+*
+* The routine gcd returns gcd(x, y), the greatest common divisor of
+* the two positive integers given.
+*
+* ALGORITHM
+*
+* The routine gcd is based on Euclid's algorithm.
+*
+* REFERENCES
+*
+* Don Knuth, The Art of Computer Programming, Vol.2: Seminumerical
+* Algorithms, 3rd Edition, Addison-Wesley, 1997. Section 4.5.2: The
+* Greatest Common Divisor, pp. 333-56. */
+
+int gcd(int x, int y)
+{ int r;
+ xassert(x > 0 && y > 0);
+ while (y > 0)
+ r = x % y, x = y, y = r;
+ return x;
+}
+
+/***********************************************************************
+* NAME
+*
+* gcdn - find greatest common divisor of n integers
+*
+* SYNOPSIS
+*
+* #include "misc.h"
+* int gcdn(int n, int x[]);
+*
+* RETURNS
+*
+* The routine gcdn returns gcd(x[1], x[2], ..., x[n]), the greatest
+* common divisor of n positive integers given, n > 0.
+*
+* BACKGROUND
+*
+* The routine gcdn is based on the following identity:
+*
+* gcd(x, y, z) = gcd(gcd(x, y), z).
+*
+* REFERENCES
+*
+* Don Knuth, The Art of Computer Programming, Vol.2: Seminumerical
+* Algorithms, 3rd Edition, Addison-Wesley, 1997. Section 4.5.2: The
+* Greatest Common Divisor, pp. 333-56. */
+
+int gcdn(int n, int x[])
+{ int d, j;
+ xassert(n > 0);
+ for (j = 1; j <= n; j++)
+ { xassert(x[j] > 0);
+ if (j == 1)
+ d = x[1];
+ else
+ d = gcd(d, x[j]);
+ if (d == 1)
+ break;
+ }
+ return d;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/jd.c b/test/monniaux/glpk-4.65/src/misc/jd.c
new file mode 100644
index 00000000..c9d63171
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/jd.c
@@ -0,0 +1,152 @@
+/* jd.c (conversions between calendar date and Julian day number) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include <stddef.h>
+#include "jd.h"
+
+/***********************************************************************
+* NAME
+*
+* jday - convert calendar date to Julian day number
+*
+* SYNOPSIS
+*
+* #include "jd.h"
+* int jday(int d, int m, int y);
+*
+* DESCRIPTION
+*
+* The routine jday converts a calendar date, Gregorian calendar, to
+* corresponding Julian day number j.
+*
+* From the given day d, month m, and year y, the Julian day number j
+* is computed without using tables.
+*
+* The routine is valid for 1 <= y <= 4000.
+*
+* RETURNS
+*
+* The routine jday returns the Julian day number, or negative value if
+* the specified date is incorrect.
+*
+* REFERENCES
+*
+* R. G. Tantzen, Algorithm 199: conversions between calendar date and
+* Julian day number, Communications of the ACM, vol. 6, no. 8, p. 444,
+* Aug. 1963. */
+
+int jday(int d, int m, int y)
+{ int c, ya, j, dd;
+ if (!(1 <= d && d <= 31 &&
+ 1 <= m && m <= 12 &&
+ 1 <= y && y <= 4000))
+ return -1;
+ if (m >= 3)
+ m -= 3;
+ else
+ m += 9, y--;
+ c = y / 100;
+ ya = y - 100 * c;
+ j = (146097 * c) / 4 + (1461 * ya) / 4 + (153 * m + 2) / 5 + d +
+ 1721119;
+ jdate(j, &dd, NULL, NULL);
+ if (d != dd)
+ return -1;
+ return j;
+}
+
+/***********************************************************************
+* NAME
+*
+* jdate - convert Julian day number to calendar date
+*
+* SYNOPSIS
+*
+* #include "jd.h"
+* int jdate(int j, int *d, int *m, int *y);
+*
+* DESCRIPTION
+*
+* The routine jdate converts a Julian day number j to corresponding
+* calendar date, Gregorian calendar.
+*
+* The day d, month m, and year y are computed without using tables and
+* stored in corresponding locations.
+*
+* The routine is valid for 1721426 <= j <= 3182395.
+*
+* RETURNS
+*
+* If the conversion is successful, the routine returns zero, otherwise
+* non-zero.
+*
+* REFERENCES
+*
+* R. G. Tantzen, Algorithm 199: conversions between calendar date and
+* Julian day number, Communications of the ACM, vol. 6, no. 8, p. 444,
+* Aug. 1963. */
+
+int jdate(int j, int *d_, int *m_, int *y_)
+{ int d, m, y;
+ if (!(1721426 <= j && j <= 3182395))
+ return 1;
+ j -= 1721119;
+ y = (4 * j - 1) / 146097;
+ j = (4 * j - 1) % 146097;
+ d = j / 4;
+ j = (4 * d + 3) / 1461;
+ d = (4 * d + 3) % 1461;
+ d = (d + 4) / 4;
+ m = (5 * d - 3) / 153;
+ d = (5 * d - 3) % 153;
+ d = (d + 5) / 5;
+ y = 100 * y + j;
+ if (m <= 9)
+ m += 3;
+ else m -= 9,
+ y++;
+ if (d_ != NULL) *d_ = d;
+ if (m_ != NULL) *m_ = m;
+ if (y_ != NULL) *y_ = y;
+ return 0;
+}
+
+#ifdef GLP_TEST
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(void)
+{ int jbeg, jend, j, d, m, y;
+ jbeg = jday(1, 1, 1);
+ jend = jday(31, 12, 4000);
+ for (j = jbeg; j <= jend; j++)
+ { assert(jdate(j, &d, &m, &y) == 0);
+ assert(jday(d, m, y) == j);
+ }
+ printf("Routines jday and jdate work correctly.\n");
+ return 0;
+}
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/jd.h b/test/monniaux/glpk-4.65/src/misc/jd.h
new file mode 100644
index 00000000..009d2daa
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/jd.h
@@ -0,0 +1,32 @@
+/* jd.h (conversions between calendar date and Julian day number) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#define jday _glp_jday
+int jday(int d, int m, int y);
+/* convert calendar date to Julian day number */
+
+#define jdate _glp_jdate
+int jdate(int j, int *d, int *m, int *y);
+/* convert Julian day number to calendar date */
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/keller.c b/test/monniaux/glpk-4.65/src/misc/keller.c
new file mode 100644
index 00000000..d64d3c1e
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/keller.c
@@ -0,0 +1,235 @@
+/* keller.c (cover edges by cliques, Kellerman's heuristic) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include "glpk.h"
+#include "env.h"
+#include "keller.h"
+
+/***********************************************************************
+* NAME
+*
+* kellerman - cover edges by cliques with Kellerman's heuristic
+*
+* SYNOPSIS
+*
+* #include "keller.h"
+* int kellerman(int n, int (*func)(void *info, int i, int ind[]),
+* void *info, glp_graph *H);
+*
+* DESCRIPTION
+*
+* The routine kellerman implements Kellerman's heuristic algorithm
+* to find a minimal set of cliques which cover all edges of specified
+* graph G = (V, E).
+*
+* The parameter n specifies the number of vertices |V|, n >= 0.
+*
+* Formal routine func specifies the set of edges E in the following
+* way. Running the routine kellerman calls the routine func and passes
+* to it parameter i, which is the number of some vertex, 1 <= i <= n.
+* In response the routine func should store numbers of all vertices
+* adjacent to vertex i to locations ind[1], ind[2], ..., ind[len] and
+* return the value of len, which is the number of adjacent vertices,
+* 0 <= len <= n. Self-loops are allowed, but ignored. Multiple edges
+* are not allowed.
+*
+* The parameter info is a transit pointer (magic cookie) passed to the
+* formal routine func as its first parameter.
+*
+* The result provided by the routine kellerman is the bipartite graph
+* H = (V union C, F), which defines the covering found. (The program
+* object of type glp_graph specified by the parameter H should be
+* previously created with the routine glp_create_graph. On entry the
+* routine kellerman erases the content of this object with the routine
+* glp_erase_graph.) Vertices of first part V correspond to vertices of
+* the graph G and have the same ordinal numbers 1, 2, ..., n. Vertices
+* of second part C correspond to cliques and have ordinal numbers
+* n+1, n+2, ..., n+k, where k is the total number of cliques in the
+* edge covering found. Every edge f in F in the program object H is
+* represented as arc f = (i->j), where i in V and j in C, which means
+* that vertex i of the graph G is in clique C[j], 1 <= j <= k. (Thus,
+* if two vertices of the graph G are in the same clique, these vertices
+* are adjacent in G, and corresponding edge is covered by that clique.)
+*
+* RETURNS
+*
+* The routine Kellerman returns k, the total number of cliques in the
+* edge covering found.
+*
+* REFERENCE
+*
+* For more details see: glpk/doc/notes/keller.pdf (in Russian). */
+
+struct set
+{ /* set of vertices */
+ int size;
+ /* size (cardinality) of the set, 0 <= card <= n */
+ int *list; /* int list[1+n]; */
+ /* the set contains vertices list[1,...,size] */
+ int *pos; /* int pos[1+n]; */
+ /* pos[i] > 0 means that vertex i is in the set and
+ * list[pos[i]] = i; pos[i] = 0 means that vertex i is not in
+ * the set */
+};
+
+int kellerman(int n, int (*func)(void *info, int i, int ind[]),
+ void *info, void /* glp_graph */ *H_)
+{ glp_graph *H = H_;
+ struct set W_, *W = &W_, V_, *V = &V_;
+ glp_arc *a;
+ int i, j, k, m, t, len, card, best;
+ xassert(n >= 0);
+ /* H := (V, 0; 0), where V is the set of vertices of graph G */
+ glp_erase_graph(H, H->v_size, H->a_size);
+ glp_add_vertices(H, n);
+ /* W := 0 */
+ W->size = 0;
+ W->list = xcalloc(1+n, sizeof(int));
+ W->pos = xcalloc(1+n, sizeof(int));
+ memset(&W->pos[1], 0, sizeof(int) * n);
+ /* V := 0 */
+ V->size = 0;
+ V->list = xcalloc(1+n, sizeof(int));
+ V->pos = xcalloc(1+n, sizeof(int));
+ memset(&V->pos[1], 0, sizeof(int) * n);
+ /* main loop */
+ for (i = 1; i <= n; i++)
+ { /* W must be empty */
+ xassert(W->size == 0);
+ /* W := { j : i > j and (i,j) in E } */
+ len = func(info, i, W->list);
+ xassert(0 <= len && len <= n);
+ for (t = 1; t <= len; t++)
+ { j = W->list[t];
+ xassert(1 <= j && j <= n);
+ if (j >= i) continue;
+ xassert(W->pos[j] == 0);
+ W->list[++W->size] = j, W->pos[j] = W->size;
+ }
+ /* on i-th iteration we need to cover edges (i,j) for all
+ * j in W */
+ /* if W is empty, it is a special case */
+ if (W->size == 0)
+ { /* set k := k + 1 and create new clique C[k] = { i } */
+ k = glp_add_vertices(H, 1) - n;
+ glp_add_arc(H, i, n + k);
+ continue;
+ }
+ /* try to include vertex i into existing cliques */
+ /* V must be empty */
+ xassert(V->size == 0);
+ /* k is the number of cliques found so far */
+ k = H->nv - n;
+ for (m = 1; m <= k; m++)
+ { /* do while V != W; since here V is within W, we can use
+ * equivalent condition: do while |V| < |W| */
+ if (V->size == W->size) break;
+ /* check if C[m] is within W */
+ for (a = H->v[n + m]->in; a != NULL; a = a->h_next)
+ { j = a->tail->i;
+ if (W->pos[j] == 0) break;
+ }
+ if (a != NULL) continue;
+ /* C[m] is within W, expand clique C[m] with vertex i */
+ /* C[m] := C[m] union {i} */
+ glp_add_arc(H, i, n + m);
+ /* V is a set of vertices whose incident edges are already
+ * covered by existing cliques */
+ /* V := V union C[m] */
+ for (a = H->v[n + m]->in; a != NULL; a = a->h_next)
+ { j = a->tail->i;
+ if (V->pos[j] == 0)
+ V->list[++V->size] = j, V->pos[j] = V->size;
+ }
+ }
+ /* remove from set W the vertices whose incident edges are
+ * already covered by existing cliques */
+ /* W := W \ V, V := 0 */
+ for (t = 1; t <= V->size; t++)
+ { j = V->list[t], V->pos[j] = 0;
+ if (W->pos[j] != 0)
+ { /* remove vertex j from W */
+ if (W->pos[j] != W->size)
+ { int jj = W->list[W->size];
+ W->list[W->pos[j]] = jj;
+ W->pos[jj] = W->pos[j];
+ }
+ W->size--, W->pos[j] = 0;
+ }
+ }
+ V->size = 0;
+ /* now set W contains only vertices whose incident edges are
+ * still not covered by existing cliques; create new cliques
+ * to cover remaining edges until set W becomes empty */
+ while (W->size > 0)
+ { /* find clique C[m], 1 <= m <= k, which shares maximal
+ * number of vertices with W; to break ties choose clique
+ * having smallest number m */
+ m = 0, best = -1;
+ k = H->nv - n;
+ for (t = 1; t <= k; t++)
+ { /* compute cardinality of intersection of W and C[t] */
+ card = 0;
+ for (a = H->v[n + t]->in; a != NULL; a = a->h_next)
+ { j = a->tail->i;
+ if (W->pos[j] != 0) card++;
+ }
+ if (best < card)
+ m = t, best = card;
+ }
+ xassert(m > 0);
+ /* set k := k + 1 and create new clique:
+ * C[k] := (W intersect C[m]) union { i }, which covers all
+ * edges incident to vertices from (W intersect C[m]) */
+ k = glp_add_vertices(H, 1) - n;
+ for (a = H->v[n + m]->in; a != NULL; a = a->h_next)
+ { j = a->tail->i;
+ if (W->pos[j] != 0)
+ { /* vertex j is in both W and C[m]; include it in new
+ * clique C[k] */
+ glp_add_arc(H, j, n + k);
+ /* remove vertex j from W, since edge (i,j) will be
+ * covered by new clique C[k] */
+ if (W->pos[j] != W->size)
+ { int jj = W->list[W->size];
+ W->list[W->pos[j]] = jj;
+ W->pos[jj] = W->pos[j];
+ }
+ W->size--, W->pos[j] = 0;
+ }
+ }
+ /* include vertex i to new clique C[k] to cover edges (i,j)
+ * incident to all vertices j just removed from W */
+ glp_add_arc(H, i, n + k);
+ }
+ }
+ /* free working arrays */
+ xfree(W->list);
+ xfree(W->pos);
+ xfree(V->list);
+ xfree(V->pos);
+ /* return the number of cliques in the edge covering found */
+ return H->nv - n;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/keller.h b/test/monniaux/glpk-4.65/src/misc/keller.h
new file mode 100644
index 00000000..d7a5b343
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/keller.h
@@ -0,0 +1,34 @@
+/* keller.h (cover edges by cliques, Kellerman's heuristic) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#ifndef KELLER_H
+#define KELLER_H
+
+#define kellerman _glp_kellerman
+int kellerman(int n, int (*func)(void *info, int i, int ind[]),
+ void *info, void /* glp_graph */ *H);
+/* cover edges by cliques with Kellerman's heuristic */
+
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/ks.c b/test/monniaux/glpk-4.65/src/misc/ks.c
new file mode 100644
index 00000000..0720cc90
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/ks.c
@@ -0,0 +1,466 @@
+/* ks.c (0-1 knapsack problem) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2017-2018 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include "env.h"
+#include "ks.h"
+#include "mt1.h"
+
+/***********************************************************************
+* 0-1 knapsack problem has the following formulation:
+*
+* maximize z = sum{j in 1..n} c[j]x[j] (1)
+*
+* s.t. sum{j in 1..n} a[j]x[j] <= b (2)
+*
+* x[j] in {0, 1} for all j in 1..n (3)
+*
+* In general case it is assumed that the instance is non-normalized,
+* i.e. parameters a, b, and c may have any sign.
+***********************************************************************/
+
+/***********************************************************************
+* ks_enum - solve 0-1 knapsack problem by complete enumeration
+*
+* This routine finds optimal solution to 0-1 knapsack problem (1)-(3)
+* by complete enumeration. It is intended mainly for testing purposes.
+*
+* The instance to be solved is specified by parameters n, a, b, and c.
+* Note that these parameters can have any sign, i.e. normalization is
+* not needed.
+*
+* On exit the routine stores the optimal point found in locations
+* x[1], ..., x[n] and returns the optimal objective value. However, if
+* the instance is infeasible, the routine returns INT_MIN.
+*
+* Since the complete enumeration is inefficient, this routine can be
+* used only for small instances (n <= 20-30). */
+
+#define N_MAX 40
+
+int ks_enum(int n, const int a[/*1+n*/], int b, const int c[/*1+n*/],
+ char x[/*1+n*/])
+{ int j, s, z, z_best;
+ char x_best[1+N_MAX];
+ xassert(0 <= n && n <= N_MAX);
+ /* initialization */
+ memset(&x[1], 0, n * sizeof(char));
+ z_best = INT_MIN;
+loop: /* compute constraint and objective at current x */
+ s = z = 0;
+ for (j = 1; j <= n; j++)
+ { if (x[j])
+ s += a[j], z += c[j];
+ }
+ /* check constraint violation */
+ if (s > b)
+ goto next;
+ /* check objective function */
+ if (z_best < z)
+ { /* better solution has been found */
+ memcpy(&x_best[1], &x[1], n * sizeof(char));
+ z_best = z;
+ }
+next: /* generate next x */
+ for (j = 1; j <= n; j++)
+ { if (!x[j])
+ { x[j] = 1;
+ goto loop;
+ }
+ x[j] = 0;
+ }
+ /* report best (optimal) solution */
+ memcpy(&x[1], &x_best[1], n * sizeof(char));
+ return z_best;
+}
+
+/***********************************************************************
+* reduce - prepare reduced instance of 0-1 knapsack
+*
+* Given original instance of 0-1 knapsack (1)-(3) specified by the
+* parameters n, a, b, and c this routine transforms it to equivalent
+* reduced instance in the same format. The reduced instance is
+* normalized, i.e. the following additional conditions are met:
+*
+* n >= 2 (4)
+*
+* 1 <= a[j] <= b for all j in 1..n (5)
+*
+* sum{j in 1..n} a[j] >= b+1 (6)
+*
+* c[j] >= 1 for all j in 1..n (7)
+*
+* The routine creates the structure ks and stores there parameters n,
+* a, b, and c of the reduced instance as well as template of solution
+* to original instance.
+*
+* Normally the routine returns a pointer to the structure ks created.
+* However, if the original instance is infeasible, the routine returns
+* a null pointer. */
+
+struct ks
+{ int orig_n;
+ /* original problem dimension */
+ int n;
+ /* reduced problem dimension */
+ int *a; /* int a[1+orig_n]; */
+ /* a{j in 1..n} are constraint coefficients (2) */
+ int b;
+ /* b is constraint right-hand side (2) */
+ int *c; /* int c[1+orig_n]; */
+ /* c{j in 1..n} are objective coefficients (1) */
+ int c0;
+ /* c0 is objective constant term */
+ char *x; /* char x[1+orig_n]; */
+ /* x{j in 1..orig_n} is solution template to original instance:
+ * x[j] = 0 x[j] is fixed at 0
+ * x[j] = 1 x[j] is fixed at 1
+ * x[j] = 0x10 x[j] = x[j']
+ * x[j] = 0x11 x[j] = 1 - x[j']
+ * where x[j'] is corresponding solution to reduced instance */
+};
+
+static void free_ks(struct ks *ks);
+
+static struct ks *reduce(const int n, const int a[/*1+n*/], int b,
+ const int c[/*1+n*/])
+{ struct ks *ks;
+ int j, s;
+ xassert(n >= 0);
+ /* initially reduced instance is the same as original one */
+ ks = talloc(1, struct ks);
+ ks->orig_n = n;
+ ks->n = 0;
+ ks->a = talloc(1+n, int);
+ memcpy(&ks->a[1], &a[1], n * sizeof(int));
+ ks->b = b;
+ ks->c = talloc(1+n, int);
+ memcpy(&ks->c[1], &c[1], n * sizeof(int));
+ ks->c0 = 0;
+ ks->x = talloc(1+n, char);
+ /* make all a[j] non-negative */
+ for (j = 1; j <= n; j++)
+ { if (a[j] >= 0)
+ { /* keep original x[j] */
+ ks->x[j] = 0x10;
+ }
+ else /* a[j] < 0 */
+ { /* substitute x[j] = 1 - x'[j] */
+ ks->x[j] = 0x11;
+ /* ... + a[j]x[j] + ... <= b
+ * ... + a[j](1 - x'[j]) + ... <= b
+ * ... - a[j]x'[j] + ... <= b - a[j] */
+ ks->a[j] = - ks->a[j];
+ ks->b += ks->a[j];
+ /* z = ... + c[j]x[j] + ... + c0 =
+ * = ... + c[j](1 - x'[j]) + ... + c0 =
+ * = ... - c[j]x'[j] + ... + (c0 + c[j]) */
+ ks->c0 += ks->c[j];
+ ks->c[j] = - ks->c[j];
+ }
+ }
+ /* now a[j] >= 0 for all j in 1..n */
+ if (ks->b < 0)
+ { /* instance is infeasible */
+ free_ks(ks);
+ return NULL;
+ }
+ /* build reduced instance */
+ for (j = 1; j <= n; j++)
+ { if (ks->a[j] == 0)
+ { if (ks->c[j] <= 0)
+ { /* fix x[j] at 0 */
+ ks->x[j] ^= 0x10;
+ }
+ else
+ { /* fix x[j] at 1 */
+ ks->x[j] ^= 0x11;
+ ks->c0 += ks->c[j];
+ }
+ }
+ else if (ks->a[j] > ks->b || ks->c[j] <= 0)
+ { /* fix x[j] at 0 */
+ ks->x[j] ^= 0x10;
+ }
+ else
+ { /* include x[j] in reduced instance */
+ ks->n++;
+ ks->a[ks->n] = ks->a[j];
+ ks->c[ks->n] = ks->c[j];
+ }
+ }
+ /* now conditions (5) and (7) are met */
+ /* check condition (6) */
+ s = 0;
+ for (j = 1; j <= ks->n; j++)
+ { xassert(1 <= ks->a[j] && ks->a[j] <= ks->b);
+ xassert(ks->c[j] >= 1);
+ s += ks->a[j];
+ }
+ if (s <= ks->b)
+ { /* sum{j in 1..n} a[j] <= b */
+ /* fix all remaining x[j] at 1 to obtain trivial solution */
+ for (j = 1; j <= n; j++)
+ { if (ks->x[j] & 0x10)
+ ks->x[j] ^= 0x11;
+ }
+ for (j = 1; j <= ks->n; j++)
+ ks->c0 += ks->c[j];
+ /* reduced instance is empty */
+ ks->n = 0;
+ }
+ /* here n = 0 or n >= 2 due to condition (6) */
+ xassert(ks->n == 0 || ks->n >= 2);
+ return ks;
+}
+
+/***********************************************************************
+* restore - restore solution to original 0-1 knapsack instance
+*
+* Given optimal solution x{j in 1..ks->n} to the reduced 0-1 knapsack
+* instance (previously prepared by the routine reduce) this routine
+* constructs optimal solution to the original instance and stores it
+* in the array ks->x{j in 1..ks->orig_n}.
+*
+* On exit the routine returns optimal objective value for the original
+* instance.
+*
+* NOTE: This operation should be performed only once. */
+
+static int restore(struct ks *ks, char x[])
+{ int j, k, z;
+ z = ks->c0;
+ for (j = 1, k = 0; j <= ks->orig_n; j++)
+ { if (ks->x[j] & 0x10)
+ { k++;
+ xassert(k <= ks->n);
+ xassert(x[k] == 0 || x[k] == 1);
+ if (ks->x[j] & 1)
+ ks->x[j] = 1 - x[k];
+ else
+ ks->x[j] = x[k];
+ if (x[k])
+ z += ks->c[k];
+ }
+ }
+ xassert(k == ks->n);
+ return z;
+}
+
+/***********************************************************************
+* free_ks - deallocate structure ks
+*
+* This routine frees memory previously allocated to the structure ks
+* and all its components. */
+
+static void free_ks(struct ks *ks)
+{ xassert(ks != NULL);
+ tfree(ks->a);
+ tfree(ks->c);
+ tfree(ks->x);
+ tfree(ks);
+}
+
+/***********************************************************************
+* ks_mt1 - solve 0-1 knapsack problem with Martello & Toth algorithm
+*
+* This routine finds optimal solution to 0-1 knapsack problem (1)-(3)
+* with Martello & Toth algorithm MT1.
+*
+* The instance to be solved is specified by parameters n, a, b, and c.
+* Note that these parameters can have any sign, i.e. normalization is
+* not needed.
+*
+* On exit the routine stores the optimal point found in locations
+* x[1], ..., x[n] and returns the optimal objective value. However, if
+* the instance is infeasible, the routine returns INT_MIN.
+*
+* REFERENCES
+*
+* S.Martello, P.Toth. Knapsack Problems: Algorithms and Computer Imp-
+* lementations. John Wiley & Sons, 1990. */
+
+struct mt
+{ int j;
+ float r; /* r[j] = c[j] / a[j] */
+};
+
+static int CDECL fcmp(const void *p1, const void *p2)
+{ if (((struct mt *)p1)->r > ((struct mt *)p2)->r)
+ return -1;
+ else if (((struct mt *)p1)->r < ((struct mt *)p2)->r)
+ return +1;
+ else
+ return 0;
+}
+
+static int mt1a(int n, const int a[], int b, const int c[], char x[])
+{ /* interface routine to MT1 */
+ struct mt *mt;
+ int j, z, *p, *w, *x1, *xx, *min, *psign, *wsign, *zsign;
+ xassert(n >= 2);
+ /* allocate working arrays */
+ mt = talloc(1+n, struct mt);
+ p = talloc(1+n+1, int);
+ w = talloc(1+n+1, int);
+ x1 = talloc(1+n+1, int);
+ xx = talloc(1+n+1, int);
+ min = talloc(1+n+1, int);
+ psign = talloc(1+n+1, int);
+ wsign = talloc(1+n+1, int);
+ zsign = talloc(1+n+1, int);
+ /* reorder items to provide c[j] / a[j] >= a[j+1] / a[j+1] */
+ for (j = 1; j <= n; j++)
+ { mt[j].j = j;
+ mt[j].r = (float)c[j] / (float)a[j];
+ }
+ qsort(&mt[1], n, sizeof(struct mt), fcmp);
+ /* load instance parameters */
+ for (j = 1; j <= n; j++)
+ { p[j] = c[mt[j].j];
+ w[j] = a[mt[j].j];
+ }
+ /* find optimal solution */
+ z = mt1(n, p, w, b, x1, 1, xx, min, psign, wsign, zsign);
+ xassert(z >= 0);
+ /* store optimal point found */
+ for (j = 1; j <= n; j++)
+ { xassert(x1[j] == 0 || x1[j] == 1);
+ x[mt[j].j] = x1[j];
+ }
+ /* free working arrays */
+ tfree(mt);
+ tfree(p);
+ tfree(w);
+ tfree(x1);
+ tfree(xx);
+ tfree(min);
+ tfree(psign);
+ tfree(wsign);
+ tfree(zsign);
+ return z;
+}
+
+int ks_mt1(int n, const int a[/*1+n*/], int b, const int c[/*1+n*/],
+ char x[/*1+n*/])
+{ struct ks *ks;
+ int j, s1, s2, z;
+ xassert(n >= 0);
+ /* prepare reduced instance */
+ ks = reduce(n, a, b, c);
+ if (ks == NULL)
+ { /* original instance is infeasible */
+ return INT_MIN;
+ }
+ /* find optimal solution to reduced instance */
+ if (ks->n > 0)
+ mt1a(ks->n, ks->a, ks->b, ks->c, x);
+ /* restore solution to original instance */
+ z = restore(ks, x);
+ memcpy(&x[1], &ks->x[1], n * sizeof(char));
+ free_ks(ks);
+ /* check solution found */
+ s1 = s2 = 0;
+ for (j = 1; j <= n; j++)
+ { xassert(x[j] == 0 || x[j] == 1);
+ if (x[j])
+ s1 += a[j], s2 += c[j];
+ }
+ xassert(s1 <= b);
+ xassert(s2 == z);
+ return z;
+}
+
+/***********************************************************************
+* ks_greedy - solve 0-1 knapsack problem with greedy heuristic
+*
+* This routine finds (sub)optimal solution to 0-1 knapsack problem
+* (1)-(3) with greedy heuristic.
+*
+* The instance to be solved is specified by parameters n, a, b, and c.
+* Note that these parameters can have any sign, i.e. normalization is
+* not needed.
+*
+* On exit the routine stores the optimal point found in locations
+* x[1], ..., x[n] and returns the optimal objective value. However, if
+* the instance is infeasible, the routine returns INT_MIN. */
+
+static int greedy(int n, const int a[], int b, const int c[], char x[])
+{ /* core routine for normalized 0-1 knapsack instance */
+ struct mt *mt;
+ int j, s, z;
+ xassert(n >= 2);
+ /* reorder items to provide c[j] / a[j] >= a[j+1] / a[j+1] */
+ mt = talloc(1+n, struct mt);
+ for (j = 1; j <= n; j++)
+ { mt[j].j = j;
+ mt[j].r = (float)c[j] / (float)a[j];
+ }
+ qsort(&mt[1], n, sizeof(struct mt), fcmp);
+ /* take items starting from most valuable ones until the knapsack
+ * is full */
+ s = z = 0;
+ for (j = 1; j <= n; j++)
+ { if (s + a[mt[j].j] > b)
+ break;
+ x[mt[j].j] = 1;
+ s += a[mt[j].j];
+ z += c[mt[j].j];
+ }
+ /* don't take remaining items */
+ for (j = j; j <= n; j++)
+ x[mt[j].j] = 0;
+ tfree(mt);
+ return z;
+}
+
+int ks_greedy(int n, const int a[/*1+n*/], int b, const int c[/*1+n*/],
+ char x[/*1+n*/])
+{ struct ks *ks;
+ int j, s1, s2, z;
+ xassert(n >= 0);
+ /* prepare reduced instance */
+ ks = reduce(n, a, b, c);
+ if (ks == NULL)
+ { /* original instance is infeasible */
+ return INT_MIN;
+ }
+ /* find suboptimal solution to reduced instance */
+ if (ks->n > 0)
+ greedy(ks->n, ks->a, ks->b, ks->c, x);
+ /* restore solution to original instance */
+ z = restore(ks, x);
+ memcpy(&x[1], &ks->x[1], n * sizeof(char));
+ free_ks(ks);
+ /* check solution found */
+ s1 = s2 = 0;
+ for (j = 1; j <= n; j++)
+ { xassert(x[j] == 0 || x[j] == 1);
+ if (x[j])
+ s1 += a[j], s2 += c[j];
+ }
+ xassert(s1 <= b);
+ xassert(s2 == z);
+ return z;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/ks.h b/test/monniaux/glpk-4.65/src/misc/ks.h
new file mode 100644
index 00000000..d607dc44
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/ks.h
@@ -0,0 +1,44 @@
+/* ks.h (0-1 knapsack problem) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2017-2018 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#ifndef KS_H
+#define KS_H
+
+#define ks_enum _glp_ks_enum
+int ks_enum(int n, const int a[/*1+n*/], int b, const int c[/*1+n*/],
+ char x[/*1+n*/]);
+/* solve 0-1 knapsack problem by complete enumeration */
+
+#define ks_mt1 _glp_ks_mt1
+int ks_mt1(int n, const int a[/*1+n*/], int b, const int c[/*1+n*/],
+ char x[/*1+n*/]);
+/* solve 0-1 knapsack problem with Martello & Toth algorithm */
+
+#define ks_greedy _glp_ks_greedy
+int ks_greedy(int n, const int a[/*1+n*/], int b, const int c[/*1+n*/],
+ char x[/*1+n*/]);
+/* solve 0-1 knapsack problem with greedy heuristic */
+
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/mc13d.c b/test/monniaux/glpk-4.65/src/misc/mc13d.c
new file mode 100644
index 00000000..d8bab398
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/mc13d.c
@@ -0,0 +1,314 @@
+/* mc13d.c (permutations to block triangular form) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* This code is the result of translation of the Fortran subroutines
+* MC13D and MC13E associated with the following paper:
+*
+* I.S.Duff, J.K.Reid, Algorithm 529: Permutations to block triangular
+* form, ACM Trans. on Math. Softw. 4 (1978), 189-192.
+*
+* Use of ACM Algorithms is subject to the ACM Software Copyright and
+* License Agreement. See <http://www.acm.org/publications/policies>.
+*
+* The translation was made by Andrew Makhorin <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include "mc13d.h"
+
+/***********************************************************************
+* NAME
+*
+* mc13d - permutations to block triangular form
+*
+* SYNOPSIS
+*
+* #include "mc13d.h"
+* int mc13d(int n, const int icn[], const int ip[], const int lenr[],
+* int ior[], int ib[], int lowl[], int numb[], int prev[]);
+*
+* DESCRIPTION
+*
+* Given the column numbers of the nonzeros in each row of the sparse
+* matrix, the routine mc13d finds a symmetric permutation that makes
+* the matrix block lower triangular.
+*
+* INPUT PARAMETERS
+*
+* n order of the matrix.
+*
+* icn array containing the column indices of the non-zeros. Those
+* belonging to a single row must be contiguous but the ordering
+* of column indices within each row is unimportant and wasted
+* space between rows is permitted.
+*
+* ip ip[i], i = 1,2,...,n, is the position in array icn of the
+* first column index of a non-zero in row i.
+*
+* lenr lenr[i], i = 1,2,...,n, is the number of non-zeros in row i.
+*
+* OUTPUT PARAMETERS
+*
+* ior ior[i], i = 1,2,...,n, gives the position on the original
+* ordering of the row or column which is in position i in the
+* permuted form.
+*
+* ib ib[i], i = 1,2,...,num, is the row number in the permuted
+* matrix of the beginning of block i, 1 <= num <= n.
+*
+* WORKING ARRAYS
+*
+* arp working array of length [1+n], where arp[0] is not used.
+* arp[i] is one less than the number of unsearched edges leaving
+* node i. At the end of the algorithm it is set to a permutation
+* which puts the matrix in block lower triangular form.
+*
+* ib working array of length [1+n], where ib[0] is not used.
+* ib[i] is the position in the ordering of the start of the ith
+* block. ib[n+1-i] holds the node number of the ith node on the
+* stack.
+*
+* lowl working array of length [1+n], where lowl[0] is not used.
+* lowl[i] is the smallest stack position of any node to which a
+* path from node i has been found. It is set to n+1 when node i
+* is removed from the stack.
+*
+* numb working array of length [1+n], where numb[0] is not used.
+* numb[i] is the position of node i in the stack if it is on it,
+* is the permuted order of node i for those nodes whose final
+* position has been found and is otherwise zero.
+*
+* prev working array of length [1+n], where prev[0] is not used.
+* prev[i] is the node at the end of the path when node i was
+* placed on the stack.
+*
+* RETURNS
+*
+* The routine mc13d returns num, the number of blocks found. */
+
+int mc13d(int n, const int icn[], const int ip[], const int lenr[],
+ int ior[], int ib[], int lowl[], int numb[], int prev[])
+{ int *arp = ior;
+ int dummy, i, i1, i2, icnt, ii, isn, ist, ist1, iv, iw, j, lcnt,
+ nnm1, num, stp;
+ /* icnt is the number of nodes whose positions in final ordering
+ * have been found. */
+ icnt = 0;
+ /* num is the number of blocks that have been found. */
+ num = 0;
+ nnm1 = n + n - 1;
+ /* Initialization of arrays. */
+ for (j = 1; j <= n; j++)
+ { numb[j] = 0;
+ arp[j] = lenr[j] - 1;
+ }
+ for (isn = 1; isn <= n; isn++)
+ { /* Look for a starting node. */
+ if (numb[isn] != 0) continue;
+ iv = isn;
+ /* ist is the number of nodes on the stack ... it is the stack
+ * pointer. */
+ ist = 1;
+ /* Put node iv at beginning of stack. */
+ lowl[iv] = numb[iv] = 1;
+ ib[n] = iv;
+ /* The body of this loop puts a new node on the stack or
+ * backtracks. */
+ for (dummy = 1; dummy <= nnm1; dummy++)
+ { i1 = arp[iv];
+ /* Have all edges leaving node iv been searched? */
+ if (i1 >= 0)
+ { i2 = ip[iv] + lenr[iv] - 1;
+ i1 = i2 - i1;
+ /* Look at edges leaving node iv until one enters a new
+ * node or all edges are exhausted. */
+ for (ii = i1; ii <= i2; ii++)
+ { iw = icn[ii];
+ /* Has node iw been on stack already? */
+ if (numb[iw] == 0) goto L70;
+ /* Update value of lowl[iv] if necessary. */
+ if (lowl[iw] < lowl[iv]) lowl[iv] = lowl[iw];
+ }
+ /* There are no more edges leaving node iv. */
+ arp[iv] = -1;
+ }
+ /* Is node iv the root of a block? */
+ if (lowl[iv] < numb[iv]) goto L60;
+ /* Order nodes in a block. */
+ num++;
+ ist1 = n + 1 - ist;
+ lcnt = icnt + 1;
+ /* Peel block off the top of the stack starting at the top
+ * and working down to the root of the block. */
+ for (stp = ist1; stp <= n; stp++)
+ { iw = ib[stp];
+ lowl[iw] = n + 1;
+ numb[iw] = ++icnt;
+ if (iw == iv) break;
+ }
+ ist = n - stp;
+ ib[num] = lcnt;
+ /* Are there any nodes left on the stack? */
+ if (ist != 0) goto L60;
+ /* Have all the nodes been ordered? */
+ if (icnt < n) break;
+ goto L100;
+L60: /* Backtrack to previous node on path. */
+ iw = iv;
+ iv = prev[iv];
+ /* Update value of lowl[iv] if necessary. */
+ if (lowl[iw] < lowl[iv]) lowl[iv] = lowl[iw];
+ continue;
+L70: /* Put new node on the stack. */
+ arp[iv] = i2 - ii - 1;
+ prev[iw] = iv;
+ iv = iw;
+ lowl[iv] = numb[iv] = ++ist;
+ ib[n+1-ist] = iv;
+ }
+ }
+L100: /* Put permutation in the required form. */
+ for (i = 1; i <= n; i++)
+ arp[numb[i]] = i;
+ return num;
+}
+
+/**********************************************************************/
+
+#ifdef GLP_TEST
+#include "env.h"
+
+void test(int n, int ipp);
+
+int main(void)
+{ /* test program for routine mc13d */
+ test( 1, 0);
+ test( 2, 1);
+ test( 2, 2);
+ test( 3, 3);
+ test( 4, 4);
+ test( 5, 10);
+ test(10, 10);
+ test(10, 20);
+ test(20, 20);
+ test(20, 50);
+ test(50, 50);
+ test(50, 200);
+ return 0;
+}
+
+void fa01bs(int max, int *nrand);
+
+void setup(int n, char a[1+50][1+50], int ip[], int icn[], int lenr[]);
+
+void test(int n, int ipp)
+{ int ip[1+50], icn[1+1000], ior[1+50], ib[1+51], iw[1+150],
+ lenr[1+50];
+ char a[1+50][1+50], hold[1+100];
+ int i, ii, iblock, ij, index, j, jblock, jj, k9, num;
+ xprintf("\n\n\nMatrix is of order %d and has %d off-diagonal non-"
+ "zeros\n", n, ipp);
+ for (j = 1; j <= n; j++)
+ { for (i = 1; i <= n; i++)
+ a[i][j] = 0;
+ a[j][j] = 1;
+ }
+ for (k9 = 1; k9 <= ipp; k9++)
+ { /* these statements should be replaced by calls to your
+ * favorite random number generator to place two pseudo-random
+ * numbers between 1 and n in the variables i and j */
+ for (;;)
+ { fa01bs(n, &i);
+ fa01bs(n, &j);
+ if (!a[i][j]) break;
+ }
+ a[i][j] = 1;
+ }
+ /* setup converts matrix a[i,j] to required sparsity-oriented
+ * storage format */
+ setup(n, a, ip, icn, lenr);
+ num = mc13d(n, icn, ip, lenr, ior, ib, &iw[0], &iw[n], &iw[n+n]);
+ /* output reordered matrix with blocking to improve clarity */
+ xprintf("\nThe reordered matrix which has %d block%s is of the fo"
+ "rm\n", num, num == 1 ? "" : "s");
+ ib[num+1] = n + 1;
+ index = 100;
+ iblock = 1;
+ for (i = 1; i <= n; i++)
+ { for (ij = 1; ij <= index; ij++)
+ hold[ij] = ' ';
+ if (i == ib[iblock])
+ { xprintf("\n");
+ iblock++;
+ }
+ jblock = 1;
+ index = 0;
+ for (j = 1; j <= n; j++)
+ { if (j == ib[jblock])
+ { hold[++index] = ' ';
+ jblock++;
+ }
+ ii = ior[i];
+ jj = ior[j];
+ hold[++index] = (char)(a[ii][jj] ? 'X' : '0');
+ }
+ xprintf("%.*s\n", index, &hold[1]);
+ }
+ xprintf("\nThe starting point for each block is given by\n");
+ for (i = 1; i <= num; i++)
+ { if ((i - 1) % 12 == 0) xprintf("\n");
+ xprintf(" %4d", ib[i]);
+ }
+ xprintf("\n");
+ return;
+}
+
+void setup(int n, char a[1+50][1+50], int ip[], int icn[], int lenr[])
+{ int i, j, ind;
+ for (i = 1; i <= n; i++)
+ lenr[i] = 0;
+ ind = 1;
+ for (i = 1; i <= n; i++)
+ { ip[i] = ind;
+ for (j = 1; j <= n; j++)
+ { if (a[i][j])
+ { lenr[i]++;
+ icn[ind++] = j;
+ }
+ }
+ }
+ return;
+}
+
+double g = 1431655765.0;
+
+double fa01as(int i)
+{ /* random number generator */
+ g = fmod(g * 9228907.0, 4294967296.0);
+ if (i >= 0)
+ return g / 4294967296.0;
+ else
+ return 2.0 * g / 4294967296.0 - 1.0;
+}
+
+void fa01bs(int max, int *nrand)
+{ *nrand = (int)(fa01as(1) * (double)max) + 1;
+ return;
+}
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/mc13d.h b/test/monniaux/glpk-4.65/src/misc/mc13d.h
new file mode 100644
index 00000000..bdd57a19
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/mc13d.h
@@ -0,0 +1,34 @@
+/* mc13d.h */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#ifndef MC13D_H
+#define MC13D_H
+
+#define mc13d _glp_mc13d
+int mc13d(int n, const int icn[], const int ip[], const int lenr[],
+ int ior[], int ib[], int lowl[], int numb[], int prev[]);
+/* permutations to block triangular form */
+
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/mc21a.c b/test/monniaux/glpk-4.65/src/misc/mc21a.c
new file mode 100644
index 00000000..700d0f4e
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/mc21a.c
@@ -0,0 +1,301 @@
+/* mc21a.c (permutations for zero-free diagonal) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* This code is the result of translation of the Fortran subroutines
+* MC21A and MC21B associated with the following paper:
+*
+* I.S.Duff, Algorithm 575: Permutations for zero-free diagonal, ACM
+* Trans. on Math. Softw. 7 (1981), 387-390.
+*
+* Use of ACM Algorithms is subject to the ACM Software Copyright and
+* License Agreement. See <http://www.acm.org/publications/policies>.
+*
+* The translation was made by Andrew Makhorin <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include "mc21a.h"
+
+/***********************************************************************
+* NAME
+*
+* mc21a - permutations for zero-free diagonal
+*
+* SYNOPSIS
+*
+* #include "mc21a.h"
+* int mc21a(int n, const int icn[], const int ip[], const int lenr[],
+* int iperm[], int pr[], int arp[], int cv[], int out[]);
+*
+* DESCRIPTION
+*
+* Given the pattern of nonzeros of a sparse matrix, the routine mc21a
+* attempts to find a permutation of its rows that makes the matrix have
+* no zeros on its diagonal.
+*
+* INPUT PARAMETERS
+*
+* n order of matrix.
+*
+* icn array containing the column indices of the non-zeros. Those
+* belonging to a single row must be contiguous but the ordering
+* of column indices within each row is unimportant and wasted
+* space between rows is permitted.
+*
+* ip ip[i], i = 1,2,...,n, is the position in array icn of the
+* first column index of a non-zero in row i.
+*
+* lenr lenr[i], i = 1,2,...,n, is the number of non-zeros in row i.
+*
+* OUTPUT PARAMETER
+*
+* iperm contains permutation to make diagonal have the smallest
+* number of zeros on it. Elements (iperm[i], i), i = 1,2,...,n,
+* are non-zero at the end of the algorithm unless the matrix is
+* structurally singular. In this case, (iperm[i], i) will be
+* zero for n - numnz entries.
+*
+* WORKING ARRAYS
+*
+* pr working array of length [1+n], where pr[0] is not used.
+* pr[i] is the previous row to i in the depth first search.
+*
+* arp working array of length [1+n], where arp[0] is not used.
+* arp[i] is one less than the number of non-zeros in row i which
+* have not been scanned when looking for a cheap assignment.
+*
+* cv working array of length [1+n], where cv[0] is not used.
+* cv[i] is the most recent row extension at which column i was
+* visited.
+*
+* out working array of length [1+n], where out[0] is not used.
+* out[i] is one less than the number of non-zeros in row i
+* which have not been scanned during one pass through the main
+* loop.
+*
+* RETURNS
+*
+* The routine mc21a returns numnz, the number of non-zeros on diagonal
+* of permuted matrix. */
+
+int mc21a(int n, const int icn[], const int ip[], const int lenr[],
+ int iperm[], int pr[], int arp[], int cv[], int out[])
+{ int i, ii, in1, in2, j, j1, jord, k, kk, numnz;
+ /* Initialization of arrays. */
+ for (i = 1; i <= n; i++)
+ { arp[i] = lenr[i] - 1;
+ cv[i] = iperm[i] = 0;
+ }
+ numnz = 0;
+ /* Main loop. */
+ /* Each pass round this loop either results in a new assignment
+ * or gives a row with no assignment. */
+ for (jord = 1; jord <= n; jord++)
+ { j = jord;
+ pr[j] = -1;
+ for (k = 1; k <= jord; k++)
+ { /* Look for a cheap assignment. */
+ in1 = arp[j];
+ if (in1 >= 0)
+ { in2 = ip[j] + lenr[j] - 1;
+ in1 = in2 - in1;
+ for (ii = in1; ii <= in2; ii++)
+ { i = icn[ii];
+ if (iperm[i] == 0) goto L110;
+ }
+ /* No cheap assignment in row. */
+ arp[j] = -1;
+ }
+ /* Begin looking for assignment chain starting with row j.*/
+ out[j] = lenr[j] - 1;
+ /* Inner loop. Extends chain by one or backtracks. */
+ for (kk = 1; kk <= jord; kk++)
+ { in1 = out[j];
+ if (in1 >= 0)
+ { in2 = ip[j] + lenr[j] - 1;
+ in1 = in2 - in1;
+ /* Forward scan. */
+ for (ii = in1; ii <= in2; ii++)
+ { i = icn[ii];
+ if (cv[i] != jord)
+ { /* Column i has not yet been accessed during
+ * this pass. */
+ j1 = j;
+ j = iperm[i];
+ cv[i] = jord;
+ pr[j] = j1;
+ out[j1] = in2 - ii - 1;
+ goto L100;
+ }
+ }
+ }
+ /* Backtracking step. */
+ j = pr[j];
+ if (j == -1) goto L130;
+ }
+L100: ;
+ }
+L110: /* New assignment is made. */
+ iperm[i] = j;
+ arp[j] = in2 - ii - 1;
+ numnz++;
+ for (k = 1; k <= jord; k++)
+ { j = pr[j];
+ if (j == -1) break;
+ ii = ip[j] + lenr[j] - out[j] - 2;
+ i = icn[ii];
+ iperm[i] = j;
+ }
+L130: ;
+ }
+ /* If matrix is structurally singular, we now complete the
+ * permutation iperm. */
+ if (numnz < n)
+ { for (i = 1; i <= n; i++)
+ arp[i] = 0;
+ k = 0;
+ for (i = 1; i <= n; i++)
+ { if (iperm[i] == 0)
+ out[++k] = i;
+ else
+ arp[iperm[i]] = i;
+ }
+ k = 0;
+ for (i = 1; i <= n; i++)
+ { if (arp[i] == 0)
+ iperm[out[++k]] = i;
+ }
+ }
+ return numnz;
+}
+
+/**********************************************************************/
+
+#ifdef GLP_TEST
+#include "env.h"
+
+int sing;
+
+void ranmat(int m, int n, int icn[], int iptr[], int nnnp1, int *knum,
+ int iw[]);
+
+void fa01bs(int max, int *nrand);
+
+int main(void)
+{ /* test program for the routine mc21a */
+ /* these runs on random matrices cause all possible statements in
+ * mc21a to be executed */
+ int i, iold, j, j1, j2, jj, knum, l, licn, n, nov4, num, numnz;
+ int ip[1+21], icn[1+1000], iperm[1+20], lenr[1+20], iw1[1+80];
+ licn = 1000;
+ /* run on random matrices of orders 1 through 20 */
+ for (n = 1; n <= 20; n++)
+ { nov4 = n / 4;
+ if (nov4 < 1) nov4 = 1;
+L10: fa01bs(nov4, &l);
+ knum = l * n;
+ /* knum is requested number of non-zeros in random matrix */
+ if (knum > licn) goto L10;
+ /* if sing is false, matrix is guaranteed structurally
+ * non-singular */
+ sing = ((n / 2) * 2 == n);
+ /* call to subroutine to generate random matrix */
+ ranmat(n, n, icn, ip, n+1, &knum, iw1);
+ /* knum is now actual number of non-zeros in random matrix */
+ if (knum > licn) goto L10;
+ xprintf("n = %2d; nz = %4d; sing = %d\n", n, knum, sing);
+ /* set up array of row lengths */
+ for (i = 1; i <= n; i++)
+ lenr[i] = ip[i+1] - ip[i];
+ /* call to mc21a */
+ numnz = mc21a(n, icn, ip, lenr, iperm, &iw1[0], &iw1[n],
+ &iw1[n+n], &iw1[n+n+n]);
+ /* testing to see if there are numnz non-zeros on the diagonal
+ * of the permuted matrix. */
+ num = 0;
+ for (i = 1; i <= n; i++)
+ { iold = iperm[i];
+ j1 = ip[iold];
+ j2 = j1 + lenr[iold] - 1;
+ if (j2 < j1) continue;
+ for (jj = j1; jj <= j2; jj++)
+ { j = icn[jj];
+ if (j == i)
+ { num++;
+ break;
+ }
+ }
+ }
+ if (num != numnz)
+ xprintf("Failure in mc21a, numnz = %d instead of %d\n",
+ numnz, num);
+ }
+ return 0;
+}
+
+void ranmat(int m, int n, int icn[], int iptr[], int nnnp1, int *knum,
+ int iw[])
+{ /* subroutine to generate random matrix */
+ int i, ii, inum, j, lrow, matnum;
+ inum = (*knum / n) * 2;
+ if (inum > n-1) inum = n-1;
+ matnum = 1;
+ /* each pass through this loop generates a row of the matrix */
+ for (j = 1; j <= m; j++)
+ { iptr[j] = matnum;
+ if (!(sing || j > n))
+ icn[matnum++] = j;
+ if (n == 1) continue;
+ for (i = 1; i <= n; i++) iw[i] = 0;
+ if (!sing) iw[j] = 1;
+ fa01bs(inum, &lrow);
+ lrow--;
+ if (lrow == 0) continue;
+ /* lrow off-diagonal non-zeros in row j of the matrix */
+ for (ii = 1; ii <= lrow; ii++)
+ { for (;;)
+ { fa01bs(n, &i);
+ if (iw[i] != 1) break;
+ }
+ iw[i] = 1;
+ icn[matnum++] = i;
+ }
+ }
+ for (i = m+1; i <= nnnp1; i++)
+ iptr[i] = matnum;
+ *knum = matnum - 1;
+ return;
+}
+
+double g = 1431655765.0;
+
+double fa01as(int i)
+{ /* random number generator */
+ g = fmod(g * 9228907.0, 4294967296.0);
+ if (i >= 0)
+ return g / 4294967296.0;
+ else
+ return 2.0 * g / 4294967296.0 - 1.0;
+}
+
+void fa01bs(int max, int *nrand)
+{ *nrand = (int)(fa01as(1) * (double)max) + 1;
+ return;
+}
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/mc21a.h b/test/monniaux/glpk-4.65/src/misc/mc21a.h
new file mode 100644
index 00000000..755f28b2
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/mc21a.h
@@ -0,0 +1,34 @@
+/* mc21a.h (permutations for zero-free diagonal) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#ifndef MC21A_H
+#define MC21A_H
+
+#define mc21a _glp_mc21a
+int mc21a(int n, const int icn[], const int ip[], const int lenr[],
+ int iperm[], int pr[], int arp[], int cv[], int out[]);
+/* permutations for zero-free diagonal */
+
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/misc.h b/test/monniaux/glpk-4.65/src/misc/misc.h
new file mode 100644
index 00000000..1ba1dc50
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/misc.h
@@ -0,0 +1,61 @@
+/* misc.h (miscellaneous routines) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#ifndef MISC_H
+#define MISC_H
+
+#define str2int _glp_str2int
+int str2int(const char *str, int *val);
+/* convert character string to value of int type */
+
+#define str2num _glp_str2num
+int str2num(const char *str, double *val);
+/* convert character string to value of double type */
+
+#define strspx _glp_strspx
+char *strspx(char *str);
+/* remove all spaces from character string */
+
+#define strtrim _glp_strtrim
+char *strtrim(char *str);
+/* remove trailing spaces from character string */
+
+#define gcd _glp_gcd
+int gcd(int x, int y);
+/* find greatest common divisor of two integers */
+
+#define gcdn _glp_gcdn
+int gcdn(int n, int x[]);
+/* find greatest common divisor of n integers */
+
+#define round2n _glp_round2n
+double round2n(double x);
+/* round floating-point number to nearest power of two */
+
+#define fp2rat _glp_fp2rat
+int fp2rat(double x, double eps, double *p, double *q);
+/* convert floating-point number to rational number */
+
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/mt1.c b/test/monniaux/glpk-4.65/src/misc/mt1.c
new file mode 100644
index 00000000..63a0f80e
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/mt1.c
@@ -0,0 +1,1110 @@
+/* mt1.c (0-1 knapsack problem; Martello & Toth algorithm) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* THIS CODE IS THE RESULT OF TRANSLATION OF THE FORTRAN SUBROUTINES
+* MT1 FROM THE BOOK:
+*
+* SILVANO MARTELLO, PAOLO TOTH. KNAPSACK PROBLEMS: ALGORITHMS AND
+* COMPUTER IMPLEMENTATIONS. JOHN WILEY & SONS, 1990.
+*
+* THE TRANSLATION HAS BEEN DONE WITH THE PERMISSION OF THE AUTHORS OF
+* THE ORIGINAL FORTRAN SUBROUTINES: SILVANO MARTELLO AND PAOLO TOTH.
+*
+* The translation was made by Andrew Makhorin <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#line 1 ""
+/* -- translated by f2c (version 20100827).
+ You must link the resulting object file with libf2c:
+ on Microsoft Windows system, link with libf2c.lib;
+ on Linux or Unix systems, link with .../path/to/libf2c.a -lm
+ or, if you install libf2c.a in a standard place, with -lf2c -lm
+ -- in that order, at the end of the command line, as in
+ cc *.o -lf2c -lm
+ Source for libf2c is in /netlib/f2c/libf2c.zip, e.g.,
+
+ http://www.netlib.org/f2c/libf2c.zip
+*/
+
+#if 0 /* by mao */
+#include "f2c.h"
+#else
+#include "env.h"
+#include "mt1.h"
+
+typedef int integer;
+typedef float real;
+#endif
+
+#line 1 ""
+/*< SUBROUTINE MT1(N,P,W,C,Z,X,JDIM,JCK,XX,MIN,PSIGN,WSIGN,ZSIGN) >*/
+#if 1 /* by mao */
+static int chmt1_(int *, int *, int *, int *, int *, int *);
+
+static
+#endif
+/* Subroutine */ int mt1_(integer *n, integer *p, integer *w, integer *c__,
+ integer *z__, integer *x, integer *jdim, integer *jck, integer *xx,
+ integer *min__, integer *psign, integer *wsign, integer *zsign)
+{
+ /* System generated locals */
+ integer i__1;
+
+ /* Local variables */
+ static real a, b;
+ static integer j, r__, t, j1, n1, ch, ii, jj, kk, in, ll, ip, nn, iu, ii1,
+ chs, lim, lim1, diff, lold, mink;
+ extern /* Subroutine */ int chmt1_(integer *, integer *, integer *,
+ integer *, integer *, integer *);
+ static integer profit;
+
+
+/* THIS SUBROUTINE SOLVES THE 0-1 SINGLE KNAPSACK PROBLEM */
+
+/* MAXIMIZE Z = P(1)*X(1) + ... + P(N)*X(N) */
+
+/* SUBJECT TO: W(1)*X(1) + ... + W(N)*X(N) .LE. C , */
+/* X(J) = 0 OR 1 FOR J=1,...,N. */
+
+/* THE PROGRAM IS INCLUDED IN THE VOLUME */
+/* S. MARTELLO, P. TOTH, "KNAPSACK PROBLEMS: ALGORITHMS */
+/* AND COMPUTER IMPLEMENTATIONS", JOHN WILEY, 1990 */
+/* AND IMPLEMENTS THE BRANCH-AND-BOUND ALGORITHM DESCRIBED IN */
+/* SECTION 2.5.2 . */
+/* THE PROGRAM DERIVES FROM AN EARLIER CODE PRESENTED IN */
+/* S. MARTELLO, P. TOTH, "ALGORITHM FOR THE SOLUTION OF THE 0-1 SINGLE */
+/* KNAPSACK PROBLEM", COMPUTING, 1978. */
+
+/* THE INPUT PROBLEM MUST SATISFY THE CONDITIONS */
+
+/* 1) 2 .LE. N .LE. JDIM - 1 ; */
+/* 2) P(J), W(J), C POSITIVE INTEGERS; */
+/* 3) MAX (W(J)) .LE. C ; */
+/* 4) W(1) + ... + W(N) .GT. C ; */
+/* 5) P(J)/W(J) .GE. P(J+1)/W(J+1) FOR J=1,...,N-1. */
+
+/* MT1 CALLS 1 PROCEDURE: CHMT1. */
+
+/* THE PROGRAM IS COMPLETELY SELF-CONTAINED AND COMMUNICATION TO IT IS */
+/* ACHIEVED SOLELY THROUGH THE PARAMETER LIST OF MT1. */
+/* NO MACHINE-DEPENDENT CONSTANT IS USED. */
+/* THE PROGRAM IS WRITTEN IN 1967 AMERICAN NATIONAL STANDARD FORTRAN */
+/* AND IS ACCEPTED BY THE PFORT VERIFIER (PFORT IS THE PORTABLE */
+/* SUBSET OF ANSI DEFINED BY THE ASSOCIATION FOR COMPUTING MACHINERY). */
+/* THE PROGRAM HAS BEEN TESTED ON A DIGITAL VAX 11/780 AND AN H.P. */
+/* 9000/840. */
+
+/* MT1 NEEDS 8 ARRAYS ( P , W , X , XX , MIN , PSIGN , WSIGN */
+/* AND ZSIGN ) OF LENGTH AT LEAST N + 1 . */
+
+/* MEANING OF THE INPUT PARAMETERS: */
+/* N = NUMBER OF ITEMS; */
+/* P(J) = PROFIT OF ITEM J (J=1,...,N); */
+/* W(J) = WEIGHT OF ITEM J (J=1,...,N); */
+/* C = CAPACITY OF THE KNAPSACK; */
+/* JDIM = DIMENSION OF THE 8 ARRAYS; */
+/* JCK = 1 IF CHECK ON THE INPUT DATA IS DESIRED, */
+/* = 0 OTHERWISE. */
+
+/* MEANING OF THE OUTPUT PARAMETERS: */
+/* Z = VALUE OF THE OPTIMAL SOLUTION IF Z .GT. 0 , */
+/* = ERROR IN THE INPUT DATA (WHEN JCK=1) IF Z .LT. 0 : CONDI- */
+/* TION - Z IS VIOLATED; */
+/* X(J) = 1 IF ITEM J IS IN THE OPTIMAL SOLUTION, */
+/* = 0 OTHERWISE. */
+
+/* ARRAYS XX, MIN, PSIGN, WSIGN AND ZSIGN ARE DUMMY. */
+
+/* ALL THE PARAMETERS ARE INTEGER. ON RETURN OF MT1 ALL THE INPUT */
+/* PARAMETERS ARE UNCHANGED. */
+
+/*< INTEGER P(JDIM),W(JDIM),X(JDIM),C,Z >*/
+/*< INTEGER XX(JDIM),MIN(JDIM),PSIGN(JDIM),WSIGN(JDIM),ZSIGN(JDIM) >*/
+/*< INTEGER CH,CHS,DIFF,PROFIT,R,T >*/
+/*< Z = 0 >*/
+#line 65 ""
+ /* Parameter adjustments */
+#line 65 ""
+ --zsign;
+#line 65 ""
+ --wsign;
+#line 65 ""
+ --psign;
+#line 65 ""
+ --min__;
+#line 65 ""
+ --xx;
+#line 65 ""
+ --x;
+#line 65 ""
+ --w;
+#line 65 ""
+ --p;
+#line 65 ""
+
+#line 65 ""
+ /* Function Body */
+#line 65 ""
+ *z__ = 0;
+/*< IF ( JCK .EQ. 1 ) CALL CHMT1(N,P,W,C,Z,JDIM) >*/
+#line 66 ""
+ if (*jck == 1) {
+#line 66 ""
+ chmt1_(n, &p[1], &w[1], c__, z__, jdim);
+#line 66 ""
+ }
+/*< IF ( Z .LT. 0 ) RETURN >*/
+#line 67 ""
+ if (*z__ < 0) {
+#line 67 ""
+ return 0;
+#line 67 ""
+ }
+/* INITIALIZE. */
+/*< CH = C >*/
+#line 69 ""
+ ch = *c__;
+/*< IP = 0 >*/
+#line 70 ""
+ ip = 0;
+/*< CHS = CH >*/
+#line 71 ""
+ chs = ch;
+/*< DO 10 LL=1,N >*/
+#line 72 ""
+ i__1 = *n;
+#line 72 ""
+ for (ll = 1; ll <= i__1; ++ll) {
+/*< IF ( W(LL) .GT. CHS ) GO TO 20 >*/
+#line 73 ""
+ if (w[ll] > chs) {
+#line 73 ""
+ goto L20;
+#line 73 ""
+ }
+/*< IP = IP + P(LL) >*/
+#line 74 ""
+ ip += p[ll];
+/*< CHS = CHS - W(LL) >*/
+#line 75 ""
+ chs -= w[ll];
+/*< 10 CONTINUE >*/
+#line 76 ""
+/* L10: */
+#line 76 ""
+ }
+/*< 20 LL = LL - 1 >*/
+#line 77 ""
+L20:
+#line 77 ""
+ --ll;
+/*< IF ( CHS .EQ. 0 ) GO TO 50 >*/
+#line 78 ""
+ if (chs == 0) {
+#line 78 ""
+ goto L50;
+#line 78 ""
+ }
+/*< P(N+1) = 0 >*/
+#line 79 ""
+ p[*n + 1] = 0;
+/*< W(N+1) = CH + 1 >*/
+#line 80 ""
+ w[*n + 1] = ch + 1;
+/*< LIM = IP + CHS*P(LL+2)/W(LL+2) >*/
+#line 81 ""
+ lim = ip + chs * p[ll + 2] / w[ll + 2];
+/*< A = W(LL+1) - CHS >*/
+#line 82 ""
+ a = (real) (w[ll + 1] - chs);
+/*< B = IP + P(LL+1) >*/
+#line 83 ""
+ b = (real) (ip + p[ll + 1]);
+/*< LIM1 = B - A*FLOAT(P(LL))/FLOAT(W(LL)) >*/
+#line 84 ""
+ lim1 = b - a * (real) p[ll] / (real) w[ll];
+/*< IF ( LIM1 .GT. LIM ) LIM = LIM1 >*/
+#line 85 ""
+ if (lim1 > lim) {
+#line 85 ""
+ lim = lim1;
+#line 85 ""
+ }
+/*< MINK = CH + 1 >*/
+#line 86 ""
+ mink = ch + 1;
+/*< MIN(N) = MINK >*/
+#line 87 ""
+ min__[*n] = mink;
+/*< DO 30 J=2,N >*/
+#line 88 ""
+ i__1 = *n;
+#line 88 ""
+ for (j = 2; j <= i__1; ++j) {
+/*< KK = N + 2 - J >*/
+#line 89 ""
+ kk = *n + 2 - j;
+/*< IF ( W(KK) .LT. MINK ) MINK = W(KK) >*/
+#line 90 ""
+ if (w[kk] < mink) {
+#line 90 ""
+ mink = w[kk];
+#line 90 ""
+ }
+/*< MIN(KK-1) = MINK >*/
+#line 91 ""
+ min__[kk - 1] = mink;
+/*< 30 CONTINUE >*/
+#line 92 ""
+/* L30: */
+#line 92 ""
+ }
+/*< DO 40 J=1,N >*/
+#line 93 ""
+ i__1 = *n;
+#line 93 ""
+ for (j = 1; j <= i__1; ++j) {
+/*< XX(J) = 0 >*/
+#line 94 ""
+ xx[j] = 0;
+/*< 40 CONTINUE >*/
+#line 95 ""
+/* L40: */
+#line 95 ""
+ }
+/*< Z = 0 >*/
+#line 96 ""
+ *z__ = 0;
+/*< PROFIT = 0 >*/
+#line 97 ""
+ profit = 0;
+/*< LOLD = N >*/
+#line 98 ""
+ lold = *n;
+/*< II = 1 >*/
+#line 99 ""
+ ii = 1;
+/*< GO TO 170 >*/
+#line 100 ""
+ goto L170;
+/*< 50 Z = IP >*/
+#line 101 ""
+L50:
+#line 101 ""
+ *z__ = ip;
+/*< DO 60 J=1,LL >*/
+#line 102 ""
+ i__1 = ll;
+#line 102 ""
+ for (j = 1; j <= i__1; ++j) {
+/*< X(J) = 1 >*/
+#line 103 ""
+ x[j] = 1;
+/*< 60 CONTINUE >*/
+#line 104 ""
+/* L60: */
+#line 104 ""
+ }
+/*< NN = LL + 1 >*/
+#line 105 ""
+ nn = ll + 1;
+/*< DO 70 J=NN,N >*/
+#line 106 ""
+ i__1 = *n;
+#line 106 ""
+ for (j = nn; j <= i__1; ++j) {
+/*< X(J) = 0 >*/
+#line 107 ""
+ x[j] = 0;
+/*< 70 CONTINUE >*/
+#line 108 ""
+/* L70: */
+#line 108 ""
+ }
+/*< RETURN >*/
+#line 109 ""
+ return 0;
+/* TRY TO INSERT THE II-TH ITEM INTO THE CURRENT SOLUTION. */
+/*< 80 IF ( W(II) .LE. CH ) GO TO 90 >*/
+#line 111 ""
+L80:
+#line 111 ""
+ if (w[ii] <= ch) {
+#line 111 ""
+ goto L90;
+#line 111 ""
+ }
+/*< II1 = II + 1 >*/
+#line 112 ""
+ ii1 = ii + 1;
+/*< IF ( Z .GE. CH*P(II1)/W(II1) + PROFIT ) GO TO 280 >*/
+#line 113 ""
+ if (*z__ >= ch * p[ii1] / w[ii1] + profit) {
+#line 113 ""
+ goto L280;
+#line 113 ""
+ }
+/*< II = II1 >*/
+#line 114 ""
+ ii = ii1;
+/*< GO TO 80 >*/
+#line 115 ""
+ goto L80;
+/* BUILD A NEW CURRENT SOLUTION. */
+/*< 90 IP = PSIGN(II) >*/
+#line 117 ""
+L90:
+#line 117 ""
+ ip = psign[ii];
+/*< CHS = CH - WSIGN(II) >*/
+#line 118 ""
+ chs = ch - wsign[ii];
+/*< IN = ZSIGN(II) >*/
+#line 119 ""
+ in = zsign[ii];
+/*< DO 100 LL=IN,N >*/
+#line 120 ""
+ i__1 = *n;
+#line 120 ""
+ for (ll = in; ll <= i__1; ++ll) {
+/*< IF ( W(LL) .GT. CHS ) GO TO 160 >*/
+#line 121 ""
+ if (w[ll] > chs) {
+#line 121 ""
+ goto L160;
+#line 121 ""
+ }
+/*< IP = IP + P(LL) >*/
+#line 122 ""
+ ip += p[ll];
+/*< CHS = CHS - W(LL) >*/
+#line 123 ""
+ chs -= w[ll];
+/*< 100 CONTINUE >*/
+#line 124 ""
+/* L100: */
+#line 124 ""
+ }
+/*< LL = N >*/
+#line 125 ""
+ ll = *n;
+/*< 110 IF ( Z .GE. IP + PROFIT ) GO TO 280 >*/
+#line 126 ""
+L110:
+#line 126 ""
+ if (*z__ >= ip + profit) {
+#line 126 ""
+ goto L280;
+#line 126 ""
+ }
+/*< Z = IP + PROFIT >*/
+#line 127 ""
+ *z__ = ip + profit;
+/*< NN = II - 1 >*/
+#line 128 ""
+ nn = ii - 1;
+/*< DO 120 J=1,NN >*/
+#line 129 ""
+ i__1 = nn;
+#line 129 ""
+ for (j = 1; j <= i__1; ++j) {
+/*< X(J) = XX(J) >*/
+#line 130 ""
+ x[j] = xx[j];
+/*< 120 CONTINUE >*/
+#line 131 ""
+/* L120: */
+#line 131 ""
+ }
+/*< DO 130 J=II,LL >*/
+#line 132 ""
+ i__1 = ll;
+#line 132 ""
+ for (j = ii; j <= i__1; ++j) {
+/*< X(J) = 1 >*/
+#line 133 ""
+ x[j] = 1;
+/*< 130 CONTINUE >*/
+#line 134 ""
+/* L130: */
+#line 134 ""
+ }
+/*< IF ( LL .EQ. N ) GO TO 150 >*/
+#line 135 ""
+ if (ll == *n) {
+#line 135 ""
+ goto L150;
+#line 135 ""
+ }
+/*< NN = LL + 1 >*/
+#line 136 ""
+ nn = ll + 1;
+/*< DO 140 J=NN,N >*/
+#line 137 ""
+ i__1 = *n;
+#line 137 ""
+ for (j = nn; j <= i__1; ++j) {
+/*< X(J) = 0 >*/
+#line 138 ""
+ x[j] = 0;
+/*< 140 CONTINUE >*/
+#line 139 ""
+/* L140: */
+#line 139 ""
+ }
+/*< 150 IF ( Z .NE. LIM ) GO TO 280 >*/
+#line 140 ""
+L150:
+#line 140 ""
+ if (*z__ != lim) {
+#line 140 ""
+ goto L280;
+#line 140 ""
+ }
+/*< RETURN >*/
+#line 141 ""
+ return 0;
+/*< 160 IU = CHS*P(LL)/W(LL) >*/
+#line 142 ""
+L160:
+#line 142 ""
+ iu = chs * p[ll] / w[ll];
+/*< LL = LL - 1 >*/
+#line 143 ""
+ --ll;
+/*< IF ( IU .EQ. 0 ) GO TO 110 >*/
+#line 144 ""
+ if (iu == 0) {
+#line 144 ""
+ goto L110;
+#line 144 ""
+ }
+/*< IF ( Z .GE. PROFIT + IP + IU ) GO TO 280 >*/
+#line 145 ""
+ if (*z__ >= profit + ip + iu) {
+#line 145 ""
+ goto L280;
+#line 145 ""
+ }
+/* SAVE THE CURRENT SOLUTION. */
+/*< 170 WSIGN(II) = CH - CHS >*/
+#line 147 ""
+L170:
+#line 147 ""
+ wsign[ii] = ch - chs;
+/*< PSIGN(II) = IP >*/
+#line 148 ""
+ psign[ii] = ip;
+/*< ZSIGN(II) = LL + 1 >*/
+#line 149 ""
+ zsign[ii] = ll + 1;
+/*< XX(II) = 1 >*/
+#line 150 ""
+ xx[ii] = 1;
+/*< NN = LL - 1 >*/
+#line 151 ""
+ nn = ll - 1;
+/*< IF ( NN .LT. II) GO TO 190 >*/
+#line 152 ""
+ if (nn < ii) {
+#line 152 ""
+ goto L190;
+#line 152 ""
+ }
+/*< DO 180 J=II,NN >*/
+#line 153 ""
+ i__1 = nn;
+#line 153 ""
+ for (j = ii; j <= i__1; ++j) {
+/*< WSIGN(J+1) = WSIGN(J) - W(J) >*/
+#line 154 ""
+ wsign[j + 1] = wsign[j] - w[j];
+/*< PSIGN(J+1) = PSIGN(J) - P(J) >*/
+#line 155 ""
+ psign[j + 1] = psign[j] - p[j];
+/*< ZSIGN(J+1) = LL + 1 >*/
+#line 156 ""
+ zsign[j + 1] = ll + 1;
+/*< XX(J+1) = 1 >*/
+#line 157 ""
+ xx[j + 1] = 1;
+/*< 180 CONTINUE >*/
+#line 158 ""
+/* L180: */
+#line 158 ""
+ }
+/*< 190 J1 = LL + 1 >*/
+#line 159 ""
+L190:
+#line 159 ""
+ j1 = ll + 1;
+/*< DO 200 J=J1,LOLD >*/
+#line 160 ""
+ i__1 = lold;
+#line 160 ""
+ for (j = j1; j <= i__1; ++j) {
+/*< WSIGN(J) = 0 >*/
+#line 161 ""
+ wsign[j] = 0;
+/*< PSIGN(J) = 0 >*/
+#line 162 ""
+ psign[j] = 0;
+/*< ZSIGN(J) = J >*/
+#line 163 ""
+ zsign[j] = j;
+/*< 200 CONTINUE >*/
+#line 164 ""
+/* L200: */
+#line 164 ""
+ }
+/*< LOLD = LL >*/
+#line 165 ""
+ lold = ll;
+/*< CH = CHS >*/
+#line 166 ""
+ ch = chs;
+/*< PROFIT = PROFIT + IP >*/
+#line 167 ""
+ profit += ip;
+/*< IF ( LL - (N - 2) ) 240, 220, 210 >*/
+#line 168 ""
+ if ((i__1 = ll - (*n - 2)) < 0) {
+#line 168 ""
+ goto L240;
+#line 168 ""
+ } else if (i__1 == 0) {
+#line 168 ""
+ goto L220;
+#line 168 ""
+ } else {
+#line 168 ""
+ goto L210;
+#line 168 ""
+ }
+/*< 210 II = N >*/
+#line 169 ""
+L210:
+#line 169 ""
+ ii = *n;
+/*< GO TO 250 >*/
+#line 170 ""
+ goto L250;
+/*< 220 IF ( CH .LT. W(N) ) GO TO 230 >*/
+#line 171 ""
+L220:
+#line 171 ""
+ if (ch < w[*n]) {
+#line 171 ""
+ goto L230;
+#line 171 ""
+ }
+/*< CH = CH - W(N) >*/
+#line 172 ""
+ ch -= w[*n];
+/*< PROFIT = PROFIT + P(N) >*/
+#line 173 ""
+ profit += p[*n];
+/*< XX(N) = 1 >*/
+#line 174 ""
+ xx[*n] = 1;
+/*< 230 II = N - 1 >*/
+#line 175 ""
+L230:
+#line 175 ""
+ ii = *n - 1;
+/*< GO TO 250 >*/
+#line 176 ""
+ goto L250;
+/*< 240 II = LL + 2 >*/
+#line 177 ""
+L240:
+#line 177 ""
+ ii = ll + 2;
+/*< IF ( CH .GE. MIN(II-1) ) GO TO 80 >*/
+#line 178 ""
+ if (ch >= min__[ii - 1]) {
+#line 178 ""
+ goto L80;
+#line 178 ""
+ }
+/* SAVE THE CURRENT OPTIMAL SOLUTION. */
+/*< 250 IF ( Z .GE. PROFIT ) GO TO 270 >*/
+#line 180 ""
+L250:
+#line 180 ""
+ if (*z__ >= profit) {
+#line 180 ""
+ goto L270;
+#line 180 ""
+ }
+/*< Z = PROFIT >*/
+#line 181 ""
+ *z__ = profit;
+/*< DO 260 J=1,N >*/
+#line 182 ""
+ i__1 = *n;
+#line 182 ""
+ for (j = 1; j <= i__1; ++j) {
+/*< X(J) = XX(J) >*/
+#line 183 ""
+ x[j] = xx[j];
+/*< 260 CONTINUE >*/
+#line 184 ""
+/* L260: */
+#line 184 ""
+ }
+/*< IF ( Z .EQ. LIM ) RETURN >*/
+#line 185 ""
+ if (*z__ == lim) {
+#line 185 ""
+ return 0;
+#line 185 ""
+ }
+/*< 270 IF ( XX(N) .EQ. 0 ) GO TO 280 >*/
+#line 186 ""
+L270:
+#line 186 ""
+ if (xx[*n] == 0) {
+#line 186 ""
+ goto L280;
+#line 186 ""
+ }
+/*< XX(N) = 0 >*/
+#line 187 ""
+ xx[*n] = 0;
+/*< CH = CH + W(N) >*/
+#line 188 ""
+ ch += w[*n];
+/*< PROFIT = PROFIT - P(N) >*/
+#line 189 ""
+ profit -= p[*n];
+/* BACKTRACK. */
+/*< 280 NN = II - 1 >*/
+#line 191 ""
+L280:
+#line 191 ""
+ nn = ii - 1;
+/*< IF ( NN .EQ. 0 ) RETURN >*/
+#line 192 ""
+ if (nn == 0) {
+#line 192 ""
+ return 0;
+#line 192 ""
+ }
+/*< DO 290 J=1,NN >*/
+#line 193 ""
+ i__1 = nn;
+#line 193 ""
+ for (j = 1; j <= i__1; ++j) {
+/*< KK = II - J >*/
+#line 194 ""
+ kk = ii - j;
+/*< IF ( XX(KK) .EQ. 1 ) GO TO 300 >*/
+#line 195 ""
+ if (xx[kk] == 1) {
+#line 195 ""
+ goto L300;
+#line 195 ""
+ }
+/*< 290 CONTINUE >*/
+#line 196 ""
+/* L290: */
+#line 196 ""
+ }
+/*< RETURN >*/
+#line 197 ""
+ return 0;
+/*< 300 R = CH >*/
+#line 198 ""
+L300:
+#line 198 ""
+ r__ = ch;
+/*< CH = CH + W(KK) >*/
+#line 199 ""
+ ch += w[kk];
+/*< PROFIT = PROFIT - P(KK) >*/
+#line 200 ""
+ profit -= p[kk];
+/*< XX(KK) = 0 >*/
+#line 201 ""
+ xx[kk] = 0;
+/*< IF ( R .LT. MIN(KK) ) GO TO 310 >*/
+#line 202 ""
+ if (r__ < min__[kk]) {
+#line 202 ""
+ goto L310;
+#line 202 ""
+ }
+/*< II = KK + 1 >*/
+#line 203 ""
+ ii = kk + 1;
+/*< GO TO 80 >*/
+#line 204 ""
+ goto L80;
+/*< 310 NN = KK + 1 >*/
+#line 205 ""
+L310:
+#line 205 ""
+ nn = kk + 1;
+/*< II = KK >*/
+#line 206 ""
+ ii = kk;
+/* TRY TO SUBSTITUTE THE NN-TH ITEM FOR THE KK-TH. */
+/*< 320 IF ( Z .GE. PROFIT + CH*P(NN)/W(NN) ) GO TO 280 >*/
+#line 208 ""
+L320:
+#line 208 ""
+ if (*z__ >= profit + ch * p[nn] / w[nn]) {
+#line 208 ""
+ goto L280;
+#line 208 ""
+ }
+/*< DIFF = W(NN) - W(KK) >*/
+#line 209 ""
+ diff = w[nn] - w[kk];
+/*< IF ( DIFF ) 370, 330, 340 >*/
+#line 210 ""
+ if (diff < 0) {
+#line 210 ""
+ goto L370;
+#line 210 ""
+ } else if (diff == 0) {
+#line 210 ""
+ goto L330;
+#line 210 ""
+ } else {
+#line 210 ""
+ goto L340;
+#line 210 ""
+ }
+/*< 330 NN = NN + 1 >*/
+#line 211 ""
+L330:
+#line 211 ""
+ ++nn;
+/*< GO TO 320 >*/
+#line 212 ""
+ goto L320;
+/*< 340 IF ( DIFF .GT. R ) GO TO 330 >*/
+#line 213 ""
+L340:
+#line 213 ""
+ if (diff > r__) {
+#line 213 ""
+ goto L330;
+#line 213 ""
+ }
+/*< IF ( Z .GE. PROFIT + P(NN) ) GO TO 330 >*/
+#line 214 ""
+ if (*z__ >= profit + p[nn]) {
+#line 214 ""
+ goto L330;
+#line 214 ""
+ }
+/*< Z = PROFIT + P(NN) >*/
+#line 215 ""
+ *z__ = profit + p[nn];
+/*< DO 350 J=1,KK >*/
+#line 216 ""
+ i__1 = kk;
+#line 216 ""
+ for (j = 1; j <= i__1; ++j) {
+/*< X(J) = XX(J) >*/
+#line 217 ""
+ x[j] = xx[j];
+/*< 350 CONTINUE >*/
+#line 218 ""
+/* L350: */
+#line 218 ""
+ }
+/*< JJ = KK + 1 >*/
+#line 219 ""
+ jj = kk + 1;
+/*< DO 360 J=JJ,N >*/
+#line 220 ""
+ i__1 = *n;
+#line 220 ""
+ for (j = jj; j <= i__1; ++j) {
+/*< X(J) = 0 >*/
+#line 221 ""
+ x[j] = 0;
+/*< 360 CONTINUE >*/
+#line 222 ""
+/* L360: */
+#line 222 ""
+ }
+/*< X(NN) = 1 >*/
+#line 223 ""
+ x[nn] = 1;
+/*< IF ( Z .EQ. LIM ) RETURN >*/
+#line 224 ""
+ if (*z__ == lim) {
+#line 224 ""
+ return 0;
+#line 224 ""
+ }
+/*< R = R - DIFF >*/
+#line 225 ""
+ r__ -= diff;
+/*< KK = NN >*/
+#line 226 ""
+ kk = nn;
+/*< NN = NN + 1 >*/
+#line 227 ""
+ ++nn;
+/*< GO TO 320 >*/
+#line 228 ""
+ goto L320;
+/*< 370 T = R - DIFF >*/
+#line 229 ""
+L370:
+#line 229 ""
+ t = r__ - diff;
+/*< IF ( T .LT. MIN(NN) ) GO TO 330 >*/
+#line 230 ""
+ if (t < min__[nn]) {
+#line 230 ""
+ goto L330;
+#line 230 ""
+ }
+/*< IF ( Z .GE. PROFIT + P(NN) + T*P(NN+1)/W(NN+1)) GO TO 280 >*/
+#line 231 ""
+ if (*z__ >= profit + p[nn] + t * p[nn + 1] / w[nn + 1]) {
+#line 231 ""
+ goto L280;
+#line 231 ""
+ }
+/*< CH = CH - W(NN) >*/
+#line 232 ""
+ ch -= w[nn];
+/*< PROFIT = PROFIT + P(NN) >*/
+#line 233 ""
+ profit += p[nn];
+/*< XX(NN) = 1 >*/
+#line 234 ""
+ xx[nn] = 1;
+/*< II = NN + 1 >*/
+#line 235 ""
+ ii = nn + 1;
+/*< WSIGN(NN) = W(NN) >*/
+#line 236 ""
+ wsign[nn] = w[nn];
+/*< PSIGN(NN) = P(NN) >*/
+#line 237 ""
+ psign[nn] = p[nn];
+/*< ZSIGN(NN) = II >*/
+#line 238 ""
+ zsign[nn] = ii;
+/*< N1 = NN + 1 >*/
+#line 239 ""
+ n1 = nn + 1;
+/*< DO 380 J=N1,LOLD >*/
+#line 240 ""
+ i__1 = lold;
+#line 240 ""
+ for (j = n1; j <= i__1; ++j) {
+/*< WSIGN(J) = 0 >*/
+#line 241 ""
+ wsign[j] = 0;
+/*< PSIGN(J) = 0 >*/
+#line 242 ""
+ psign[j] = 0;
+/*< ZSIGN(J) = J >*/
+#line 243 ""
+ zsign[j] = j;
+/*< 380 CONTINUE >*/
+#line 244 ""
+/* L380: */
+#line 244 ""
+ }
+/*< LOLD = NN >*/
+#line 245 ""
+ lold = nn;
+/*< GO TO 80 >*/
+#line 246 ""
+ goto L80;
+/*< END >*/
+} /* mt1_ */
+
+/*< SUBROUTINE CHMT1(N,P,W,C,Z,JDIM) >*/
+#if 1 /* by mao */
+static
+#endif
+/* Subroutine */ int chmt1_(integer *n, integer *p, integer *w, integer *c__,
+ integer *z__, integer *jdim)
+{
+ /* System generated locals */
+ integer i__1;
+
+ /* Local variables */
+ static integer j;
+ static real r__, rr;
+ static integer jsw;
+
+
+/* CHECK THE INPUT DATA. */
+
+/*< INTEGER P(JDIM),W(JDIM),C,Z >*/
+/*< IF ( N .GE. 2 .AND. N .LE. JDIM - 1 ) GO TO 10 >*/
+#line 253 ""
+ /* Parameter adjustments */
+#line 253 ""
+ --w;
+#line 253 ""
+ --p;
+#line 253 ""
+
+#line 253 ""
+ /* Function Body */
+#line 253 ""
+ if (*n >= 2 && *n <= *jdim - 1) {
+#line 253 ""
+ goto L10;
+#line 253 ""
+ }
+/*< Z = - 1 >*/
+#line 254 ""
+ *z__ = -1;
+/*< RETURN >*/
+#line 255 ""
+ return 0;
+/*< 10 IF ( C .GT. 0 ) GO TO 30 >*/
+#line 256 ""
+L10:
+#line 256 ""
+ if (*c__ > 0) {
+#line 256 ""
+ goto L30;
+#line 256 ""
+ }
+/*< 20 Z = - 2 >*/
+#line 257 ""
+L20:
+#line 257 ""
+ *z__ = -2;
+/*< RETURN >*/
+#line 258 ""
+ return 0;
+/*< 30 JSW = 0 >*/
+#line 259 ""
+L30:
+#line 259 ""
+ jsw = 0;
+/*< RR = FLOAT(P(1))/FLOAT(W(1)) >*/
+#line 260 ""
+ rr = (real) p[1] / (real) w[1];
+/*< DO 50 J=1,N >*/
+#line 261 ""
+ i__1 = *n;
+#line 261 ""
+ for (j = 1; j <= i__1; ++j) {
+/*< R = RR >*/
+#line 262 ""
+ r__ = rr;
+/*< IF ( P(J) .LE. 0 ) GO TO 20 >*/
+#line 263 ""
+ if (p[j] <= 0) {
+#line 263 ""
+ goto L20;
+#line 263 ""
+ }
+/*< IF ( W(J) .LE. 0 ) GO TO 20 >*/
+#line 264 ""
+ if (w[j] <= 0) {
+#line 264 ""
+ goto L20;
+#line 264 ""
+ }
+/*< JSW = JSW + W(J) >*/
+#line 265 ""
+ jsw += w[j];
+/*< IF ( W(J) .LE. C ) GO TO 40 >*/
+#line 266 ""
+ if (w[j] <= *c__) {
+#line 266 ""
+ goto L40;
+#line 266 ""
+ }
+/*< Z = - 3 >*/
+#line 267 ""
+ *z__ = -3;
+/*< RETURN >*/
+#line 268 ""
+ return 0;
+/*< 40 RR = FLOAT(P(J))/FLOAT(W(J)) >*/
+#line 269 ""
+L40:
+#line 269 ""
+ rr = (real) p[j] / (real) w[j];
+/*< IF ( RR .LE. R ) GO TO 50 >*/
+#line 270 ""
+ if (rr <= r__) {
+#line 270 ""
+ goto L50;
+#line 270 ""
+ }
+/*< Z = - 5 >*/
+#line 271 ""
+ *z__ = -5;
+/*< RETURN >*/
+#line 272 ""
+ return 0;
+/*< 50 CONTINUE >*/
+#line 273 ""
+L50:
+#line 273 ""
+ ;
+#line 273 ""
+ }
+/*< IF ( JSW .GT. C ) RETURN >*/
+#line 274 ""
+ if (jsw > *c__) {
+#line 274 ""
+ return 0;
+#line 274 ""
+ }
+/*< Z = - 4 >*/
+#line 275 ""
+ *z__ = -4;
+/*< RETURN >*/
+#line 276 ""
+ return 0;
+/*< END >*/
+} /* chmt1_ */
+
+#if 1 /* by mao */
+int mt1(int n, int p[], int w[], int c, int x[], int jck, int xx[],
+ int min[], int psign[], int wsign[], int zsign[])
+{ /* solve 0-1 knapsack problem */
+ int z, jdim = n+1, j, s1, s2;
+ mt1_(&n, &p[1], &w[1], &c, &z, &x[1], &jdim, &jck, &xx[1],
+ &min[1], &psign[1], &wsign[1], &zsign[1]);
+ /* check solution found */
+ s1 = s2 = 0;
+ for (j = 1; j <= n; j++)
+ { xassert(x[j] == 0 || x[j] == 1);
+ if (x[j])
+ s1 += p[j], s2 += w[j];
+ }
+ xassert(s1 == z);
+ xassert(s2 <= c);
+ return z;
+}
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/mt1.f b/test/monniaux/glpk-4.65/src/misc/mt1.f
new file mode 100644
index 00000000..82cc4a1b
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/mt1.f
@@ -0,0 +1,277 @@
+ SUBROUTINE MT1(N,P,W,C,Z,X,JDIM,JCK,XX,MIN,PSIGN,WSIGN,ZSIGN)
+C
+C THIS SUBROUTINE SOLVES THE 0-1 SINGLE KNAPSACK PROBLEM
+C
+C MAXIMIZE Z = P(1)*X(1) + ... + P(N)*X(N)
+C
+C SUBJECT TO: W(1)*X(1) + ... + W(N)*X(N) .LE. C ,
+C X(J) = 0 OR 1 FOR J=1,...,N.
+C
+C THE PROGRAM IS INCLUDED IN THE VOLUME
+C S. MARTELLO, P. TOTH, "KNAPSACK PROBLEMS: ALGORITHMS
+C AND COMPUTER IMPLEMENTATIONS", JOHN WILEY, 1990
+C AND IMPLEMENTS THE BRANCH-AND-BOUND ALGORITHM DESCRIBED IN
+C SECTION 2.5.2 .
+C THE PROGRAM DERIVES FROM AN EARLIER CODE PRESENTED IN
+C S. MARTELLO, P. TOTH, "ALGORITHM FOR THE SOLUTION OF THE 0-1 SINGLE
+C KNAPSACK PROBLEM", COMPUTING, 1978.
+C
+C THE INPUT PROBLEM MUST SATISFY THE CONDITIONS
+C
+C 1) 2 .LE. N .LE. JDIM - 1 ;
+C 2) P(J), W(J), C POSITIVE INTEGERS;
+C 3) MAX (W(J)) .LE. C ;
+C 4) W(1) + ... + W(N) .GT. C ;
+C 5) P(J)/W(J) .GE. P(J+1)/W(J+1) FOR J=1,...,N-1.
+C
+C MT1 CALLS 1 PROCEDURE: CHMT1.
+C
+C THE PROGRAM IS COMPLETELY SELF-CONTAINED AND COMMUNICATION TO IT IS
+C ACHIEVED SOLELY THROUGH THE PARAMETER LIST OF MT1.
+C NO MACHINE-DEPENDENT CONSTANT IS USED.
+C THE PROGRAM IS WRITTEN IN 1967 AMERICAN NATIONAL STANDARD FORTRAN
+C AND IS ACCEPTED BY THE PFORT VERIFIER (PFORT IS THE PORTABLE
+C SUBSET OF ANSI DEFINED BY THE ASSOCIATION FOR COMPUTING MACHINERY).
+C THE PROGRAM HAS BEEN TESTED ON A DIGITAL VAX 11/780 AND AN H.P.
+C 9000/840.
+C
+C MT1 NEEDS 8 ARRAYS ( P , W , X , XX , MIN , PSIGN , WSIGN
+C AND ZSIGN ) OF LENGTH AT LEAST N + 1 .
+C
+C MEANING OF THE INPUT PARAMETERS:
+C N = NUMBER OF ITEMS;
+C P(J) = PROFIT OF ITEM J (J=1,...,N);
+C W(J) = WEIGHT OF ITEM J (J=1,...,N);
+C C = CAPACITY OF THE KNAPSACK;
+C JDIM = DIMENSION OF THE 8 ARRAYS;
+C JCK = 1 IF CHECK ON THE INPUT DATA IS DESIRED,
+C = 0 OTHERWISE.
+C
+C MEANING OF THE OUTPUT PARAMETERS:
+C Z = VALUE OF THE OPTIMAL SOLUTION IF Z .GT. 0 ,
+C = ERROR IN THE INPUT DATA (WHEN JCK=1) IF Z .LT. 0 : CONDI-
+C TION - Z IS VIOLATED;
+C X(J) = 1 IF ITEM J IS IN THE OPTIMAL SOLUTION,
+C = 0 OTHERWISE.
+C
+C ARRAYS XX, MIN, PSIGN, WSIGN AND ZSIGN ARE DUMMY.
+C
+C ALL THE PARAMETERS ARE INTEGER. ON RETURN OF MT1 ALL THE INPUT
+C PARAMETERS ARE UNCHANGED.
+C
+ INTEGER P(JDIM),W(JDIM),X(JDIM),C,Z
+ INTEGER XX(JDIM),MIN(JDIM),PSIGN(JDIM),WSIGN(JDIM),ZSIGN(JDIM)
+ INTEGER CH,CHS,DIFF,PROFIT,R,T
+ Z = 0
+ IF ( JCK .EQ. 1 ) CALL CHMT1(N,P,W,C,Z,JDIM)
+ IF ( Z .LT. 0 ) RETURN
+C INITIALIZE.
+ CH = C
+ IP = 0
+ CHS = CH
+ DO 10 LL=1,N
+ IF ( W(LL) .GT. CHS ) GO TO 20
+ IP = IP + P(LL)
+ CHS = CHS - W(LL)
+ 10 CONTINUE
+ 20 LL = LL - 1
+ IF ( CHS .EQ. 0 ) GO TO 50
+ P(N+1) = 0
+ W(N+1) = CH + 1
+ LIM = IP + CHS*P(LL+2)/W(LL+2)
+ A = W(LL+1) - CHS
+ B = IP + P(LL+1)
+ LIM1 = B - A*FLOAT(P(LL))/FLOAT(W(LL))
+ IF ( LIM1 .GT. LIM ) LIM = LIM1
+ MINK = CH + 1
+ MIN(N) = MINK
+ DO 30 J=2,N
+ KK = N + 2 - J
+ IF ( W(KK) .LT. MINK ) MINK = W(KK)
+ MIN(KK-1) = MINK
+ 30 CONTINUE
+ DO 40 J=1,N
+ XX(J) = 0
+ 40 CONTINUE
+ Z = 0
+ PROFIT = 0
+ LOLD = N
+ II = 1
+ GO TO 170
+ 50 Z = IP
+ DO 60 J=1,LL
+ X(J) = 1
+ 60 CONTINUE
+ NN = LL + 1
+ DO 70 J=NN,N
+ X(J) = 0
+ 70 CONTINUE
+ RETURN
+C TRY TO INSERT THE II-TH ITEM INTO THE CURRENT SOLUTION.
+ 80 IF ( W(II) .LE. CH ) GO TO 90
+ II1 = II + 1
+ IF ( Z .GE. CH*P(II1)/W(II1) + PROFIT ) GO TO 280
+ II = II1
+ GO TO 80
+C BUILD A NEW CURRENT SOLUTION.
+ 90 IP = PSIGN(II)
+ CHS = CH - WSIGN(II)
+ IN = ZSIGN(II)
+ DO 100 LL=IN,N
+ IF ( W(LL) .GT. CHS ) GO TO 160
+ IP = IP + P(LL)
+ CHS = CHS - W(LL)
+ 100 CONTINUE
+ LL = N
+ 110 IF ( Z .GE. IP + PROFIT ) GO TO 280
+ Z = IP + PROFIT
+ NN = II - 1
+ DO 120 J=1,NN
+ X(J) = XX(J)
+ 120 CONTINUE
+ DO 130 J=II,LL
+ X(J) = 1
+ 130 CONTINUE
+ IF ( LL .EQ. N ) GO TO 150
+ NN = LL + 1
+ DO 140 J=NN,N
+ X(J) = 0
+ 140 CONTINUE
+ 150 IF ( Z .NE. LIM ) GO TO 280
+ RETURN
+ 160 IU = CHS*P(LL)/W(LL)
+ LL = LL - 1
+ IF ( IU .EQ. 0 ) GO TO 110
+ IF ( Z .GE. PROFIT + IP + IU ) GO TO 280
+C SAVE THE CURRENT SOLUTION.
+ 170 WSIGN(II) = CH - CHS
+ PSIGN(II) = IP
+ ZSIGN(II) = LL + 1
+ XX(II) = 1
+ NN = LL - 1
+ IF ( NN .LT. II) GO TO 190
+ DO 180 J=II,NN
+ WSIGN(J+1) = WSIGN(J) - W(J)
+ PSIGN(J+1) = PSIGN(J) - P(J)
+ ZSIGN(J+1) = LL + 1
+ XX(J+1) = 1
+ 180 CONTINUE
+ 190 J1 = LL + 1
+ DO 200 J=J1,LOLD
+ WSIGN(J) = 0
+ PSIGN(J) = 0
+ ZSIGN(J) = J
+ 200 CONTINUE
+ LOLD = LL
+ CH = CHS
+ PROFIT = PROFIT + IP
+ IF ( LL - (N - 2) ) 240, 220, 210
+ 210 II = N
+ GO TO 250
+ 220 IF ( CH .LT. W(N) ) GO TO 230
+ CH = CH - W(N)
+ PROFIT = PROFIT + P(N)
+ XX(N) = 1
+ 230 II = N - 1
+ GO TO 250
+ 240 II = LL + 2
+ IF ( CH .GE. MIN(II-1) ) GO TO 80
+C SAVE THE CURRENT OPTIMAL SOLUTION.
+ 250 IF ( Z .GE. PROFIT ) GO TO 270
+ Z = PROFIT
+ DO 260 J=1,N
+ X(J) = XX(J)
+ 260 CONTINUE
+ IF ( Z .EQ. LIM ) RETURN
+ 270 IF ( XX(N) .EQ. 0 ) GO TO 280
+ XX(N) = 0
+ CH = CH + W(N)
+ PROFIT = PROFIT - P(N)
+C BACKTRACK.
+ 280 NN = II - 1
+ IF ( NN .EQ. 0 ) RETURN
+ DO 290 J=1,NN
+ KK = II - J
+ IF ( XX(KK) .EQ. 1 ) GO TO 300
+ 290 CONTINUE
+ RETURN
+ 300 R = CH
+ CH = CH + W(KK)
+ PROFIT = PROFIT - P(KK)
+ XX(KK) = 0
+ IF ( R .LT. MIN(KK) ) GO TO 310
+ II = KK + 1
+ GO TO 80
+ 310 NN = KK + 1
+ II = KK
+C TRY TO SUBSTITUTE THE NN-TH ITEM FOR THE KK-TH.
+ 320 IF ( Z .GE. PROFIT + CH*P(NN)/W(NN) ) GO TO 280
+ DIFF = W(NN) - W(KK)
+ IF ( DIFF ) 370, 330, 340
+ 330 NN = NN + 1
+ GO TO 320
+ 340 IF ( DIFF .GT. R ) GO TO 330
+ IF ( Z .GE. PROFIT + P(NN) ) GO TO 330
+ Z = PROFIT + P(NN)
+ DO 350 J=1,KK
+ X(J) = XX(J)
+ 350 CONTINUE
+ JJ = KK + 1
+ DO 360 J=JJ,N
+ X(J) = 0
+ 360 CONTINUE
+ X(NN) = 1
+ IF ( Z .EQ. LIM ) RETURN
+ R = R - DIFF
+ KK = NN
+ NN = NN + 1
+ GO TO 320
+ 370 T = R - DIFF
+ IF ( T .LT. MIN(NN) ) GO TO 330
+ IF ( Z .GE. PROFIT + P(NN) + T*P(NN+1)/W(NN+1)) GO TO 280
+ CH = CH - W(NN)
+ PROFIT = PROFIT + P(NN)
+ XX(NN) = 1
+ II = NN + 1
+ WSIGN(NN) = W(NN)
+ PSIGN(NN) = P(NN)
+ ZSIGN(NN) = II
+ N1 = NN + 1
+ DO 380 J=N1,LOLD
+ WSIGN(J) = 0
+ PSIGN(J) = 0
+ ZSIGN(J) = J
+ 380 CONTINUE
+ LOLD = NN
+ GO TO 80
+ END
+ SUBROUTINE CHMT1(N,P,W,C,Z,JDIM)
+C
+C CHECK THE INPUT DATA.
+C
+ INTEGER P(JDIM),W(JDIM),C,Z
+ IF ( N .GE. 2 .AND. N .LE. JDIM - 1 ) GO TO 10
+ Z = - 1
+ RETURN
+ 10 IF ( C .GT. 0 ) GO TO 30
+ 20 Z = - 2
+ RETURN
+ 30 JSW = 0
+ RR = FLOAT(P(1))/FLOAT(W(1))
+ DO 50 J=1,N
+ R = RR
+ IF ( P(J) .LE. 0 ) GO TO 20
+ IF ( W(J) .LE. 0 ) GO TO 20
+ JSW = JSW + W(J)
+ IF ( W(J) .LE. C ) GO TO 40
+ Z = - 3
+ RETURN
+ 40 RR = FLOAT(P(J))/FLOAT(W(J))
+ IF ( RR .LE. R ) GO TO 50
+ Z = - 5
+ RETURN
+ 50 CONTINUE
+ IF ( JSW .GT. C ) RETURN
+ Z = - 4
+ RETURN
+ END
diff --git a/test/monniaux/glpk-4.65/src/misc/mt1.h b/test/monniaux/glpk-4.65/src/misc/mt1.h
new file mode 100644
index 00000000..cceebba9
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/mt1.h
@@ -0,0 +1,34 @@
+/* mt1.h (0-1 knapsack problem; Martello & Toth algorithm) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2017-2018 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#ifndef MT1_H
+#define MT1_H
+
+#define mt1 _glp_mt1
+int mt1(int n, int p[], int w[], int c, int x[], int jck, int xx[],
+ int min[], int psign[], int wsign[], int zsign[]);
+/* solve 0-1 single knapsack problem */
+
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/mygmp.c b/test/monniaux/glpk-4.65/src/misc/mygmp.c
new file mode 100644
index 00000000..89d053ae
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/mygmp.c
@@ -0,0 +1,1162 @@
+/* mygmp.c (integer and rational arithmetic) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2008-2015 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include "mygmp.h"
+
+#ifdef HAVE_GMP /* use GNU MP library */
+
+/* nothing is needed */
+
+#else /* use GLPK MP module */
+
+#include "bignum.h"
+#include "dmp.h"
+#include "env.h"
+
+#define gmp_pool env->gmp_pool
+#define gmp_size env->gmp_size
+#define gmp_work env->gmp_work
+
+void *gmp_get_atom(int size)
+{ ENV *env = get_env_ptr();
+ if (gmp_pool == NULL)
+ gmp_pool = dmp_create_pool();
+ return dmp_get_atom(gmp_pool, size);
+}
+
+void gmp_free_atom(void *ptr, int size)
+{ ENV *env = get_env_ptr();
+ xassert(gmp_pool != NULL);
+ dmp_free_atom(gmp_pool, ptr, size);
+ return;
+}
+
+int gmp_pool_count(void)
+{ ENV *env = get_env_ptr();
+ if (gmp_pool == NULL)
+ return 0;
+ else
+ return dmp_in_use(gmp_pool);
+}
+
+unsigned short *gmp_get_work(int size)
+{ ENV *env = get_env_ptr();
+ xassert(size > 0);
+ if (gmp_size < size)
+ { if (gmp_size == 0)
+ { xassert(gmp_work == NULL);
+ gmp_size = 100;
+ }
+ else
+ { xassert(gmp_work != NULL);
+ xfree(gmp_work);
+ }
+ while (gmp_size < size)
+ gmp_size += gmp_size;
+ gmp_work = xcalloc(gmp_size, sizeof(unsigned short));
+ }
+ return gmp_work;
+}
+
+void gmp_free_mem(void)
+{ ENV *env = get_env_ptr();
+ if (gmp_pool != NULL)
+ dmp_delete_pool(gmp_pool);
+ if (gmp_work != NULL)
+ xfree(gmp_work);
+ gmp_pool = NULL;
+ gmp_size = 0;
+ gmp_work = NULL;
+ return;
+}
+
+/*--------------------------------------------------------------------*/
+
+mpz_t _mpz_init(void)
+{ /* initialize x and set its value to 0 */
+ mpz_t x;
+ x = gmp_get_atom(sizeof(struct mpz));
+ x->val = 0;
+ x->ptr = NULL;
+ return x;
+}
+
+void mpz_clear(mpz_t x)
+{ /* free the space occupied by x */
+ mpz_set_si(x, 0);
+ xassert(x->ptr == NULL);
+ /* free the number descriptor */
+ gmp_free_atom(x, sizeof(struct mpz));
+ return;
+}
+
+void mpz_set(mpz_t z, mpz_t x)
+{ /* set the value of z from x */
+ struct mpz_seg *e, *ee, *es;
+ if (z != x)
+ { mpz_set_si(z, 0);
+ z->val = x->val;
+ xassert(z->ptr == NULL);
+ for (e = x->ptr, es = NULL; e != NULL; e = e->next)
+ { ee = gmp_get_atom(sizeof(struct mpz_seg));
+ memcpy(ee->d, e->d, 12);
+ ee->next = NULL;
+ if (z->ptr == NULL)
+ z->ptr = ee;
+ else
+ es->next = ee;
+ es = ee;
+ }
+ }
+ return;
+}
+
+void mpz_set_si(mpz_t x, int val)
+{ /* set the value of x to val */
+ struct mpz_seg *e;
+ /* free existing segments, if any */
+ while (x->ptr != NULL)
+ { e = x->ptr;
+ x->ptr = e->next;
+ gmp_free_atom(e, sizeof(struct mpz_seg));
+ }
+ /* assign new value */
+ if (val == 0x80000000)
+ { /* long format is needed */
+ x->val = -1;
+ x->ptr = e = gmp_get_atom(sizeof(struct mpz_seg));
+ memset(e->d, 0, 12);
+ e->d[1] = 0x8000;
+ e->next = NULL;
+ }
+ else
+ { /* short format is enough */
+ x->val = val;
+ }
+ return;
+}
+
+double mpz_get_d(mpz_t x)
+{ /* convert x to a double, truncating if necessary */
+ struct mpz_seg *e;
+ int j;
+ double val, deg;
+ if (x->ptr == NULL)
+ val = (double)x->val;
+ else
+ { xassert(x->val != 0);
+ val = 0.0;
+ deg = 1.0;
+ for (e = x->ptr; e != NULL; e = e->next)
+ { for (j = 0; j <= 5; j++)
+ { val += deg * (double)((int)e->d[j]);
+ deg *= 65536.0;
+ }
+ }
+ if (x->val < 0)
+ val = - val;
+ }
+ return val;
+}
+
+double mpz_get_d_2exp(int *exp, mpz_t x)
+{ /* convert x to a double, truncating if necessary (i.e. rounding
+ * towards zero), and returning the exponent separately;
+ * the return value is in the range 0.5 <= |d| < 1 and the
+ * exponent is stored to *exp; d*2^exp is the (truncated) x value;
+ * if x is zero, the return is 0.0 and 0 is stored to *exp;
+ * this is similar to the standard C frexp function */
+ struct mpz_seg *e;
+ int j, n, n1;
+ double val;
+ if (x->ptr == NULL)
+ val = (double)x->val, n = 0;
+ else
+ { xassert(x->val != 0);
+ val = 0.0, n = 0;
+ for (e = x->ptr; e != NULL; e = e->next)
+ { for (j = 0; j <= 5; j++)
+ { val += (double)((int)e->d[j]);
+ val /= 65536.0, n += 16;
+ }
+ }
+ if (x->val < 0)
+ val = - val;
+ }
+ val = frexp(val, &n1);
+ *exp = n + n1;
+ return val;
+}
+
+void mpz_swap(mpz_t x, mpz_t y)
+{ /* swap the values x and y efficiently */
+ int val;
+ void *ptr;
+ val = x->val, ptr = x->ptr;
+ x->val = y->val, x->ptr = y->ptr;
+ y->val = val, y->ptr = ptr;
+ return;
+}
+
+static void normalize(mpz_t x)
+{ /* normalize integer x that includes removing non-significant
+ * (leading) zeros and converting to short format, if possible */
+ struct mpz_seg *es, *e;
+ /* if the integer is in short format, it remains unchanged */
+ if (x->ptr == NULL)
+ { xassert(x->val != 0x80000000);
+ goto done;
+ }
+ xassert(x->val == +1 || x->val == -1);
+ /* find the last (most significant) non-zero segment */
+ es = NULL;
+ for (e = x->ptr; e != NULL; e = e->next)
+ { if (e->d[0] || e->d[1] || e->d[2] ||
+ e->d[3] || e->d[4] || e->d[5])
+ es = e;
+ }
+ /* if all segments contain zeros, the integer is zero */
+ if (es == NULL)
+ { mpz_set_si(x, 0);
+ goto done;
+ }
+ /* remove non-significant (leading) zero segments */
+ while (es->next != NULL)
+ { e = es->next;
+ es->next = e->next;
+ gmp_free_atom(e, sizeof(struct mpz_seg));
+ }
+ /* convert the integer to short format, if possible */
+ e = x->ptr;
+ if (e->next == NULL && e->d[1] <= 0x7FFF &&
+ !e->d[2] && !e->d[3] && !e->d[4] && !e->d[5])
+ { int val;
+ val = (int)e->d[0] + ((int)e->d[1] << 16);
+ if (x->val < 0)
+ val = - val;
+ mpz_set_si(x, val);
+ }
+done: return;
+}
+
+void mpz_add(mpz_t z, mpz_t x, mpz_t y)
+{ /* set z to x + y */
+ static struct mpz_seg zero = { { 0, 0, 0, 0, 0, 0 }, NULL };
+ struct mpz_seg dumx, dumy, *ex, *ey, *ez, *es, *ee;
+ int k, sx, sy, sz;
+ unsigned int t;
+ /* if [x] = 0 then [z] = [y] */
+ if (x->val == 0)
+ { xassert(x->ptr == NULL);
+ mpz_set(z, y);
+ goto done;
+ }
+ /* if [y] = 0 then [z] = [x] */
+ if (y->val == 0)
+ { xassert(y->ptr == NULL);
+ mpz_set(z, x);
+ goto done;
+ }
+ /* special case when both [x] and [y] are in short format */
+ if (x->ptr == NULL && y->ptr == NULL)
+ { int xval = x->val, yval = y->val, zval = x->val + y->val;
+ xassert(xval != 0x80000000 && yval != 0x80000000);
+ if (!(xval > 0 && yval > 0 && zval <= 0 ||
+ xval < 0 && yval < 0 && zval >= 0))
+ { mpz_set_si(z, zval);
+ goto done;
+ }
+ }
+ /* convert [x] to long format, if necessary */
+ if (x->ptr == NULL)
+ { xassert(x->val != 0x80000000);
+ if (x->val >= 0)
+ { sx = +1;
+ t = (unsigned int)(+ x->val);
+ }
+ else
+ { sx = -1;
+ t = (unsigned int)(- x->val);
+ }
+ ex = &dumx;
+ ex->d[0] = (unsigned short)t;
+ ex->d[1] = (unsigned short)(t >> 16);
+ ex->d[2] = ex->d[3] = ex->d[4] = ex->d[5] = 0;
+ ex->next = NULL;
+ }
+ else
+ { sx = x->val;
+ xassert(sx == +1 || sx == -1);
+ ex = x->ptr;
+ }
+ /* convert [y] to long format, if necessary */
+ if (y->ptr == NULL)
+ { xassert(y->val != 0x80000000);
+ if (y->val >= 0)
+ { sy = +1;
+ t = (unsigned int)(+ y->val);
+ }
+ else
+ { sy = -1;
+ t = (unsigned int)(- y->val);
+ }
+ ey = &dumy;
+ ey->d[0] = (unsigned short)t;
+ ey->d[1] = (unsigned short)(t >> 16);
+ ey->d[2] = ey->d[3] = ey->d[4] = ey->d[5] = 0;
+ ey->next = NULL;
+ }
+ else
+ { sy = y->val;
+ xassert(sy == +1 || sy == -1);
+ ey = y->ptr;
+ }
+ /* main fragment */
+ sz = sx;
+ ez = es = NULL;
+ if (sx > 0 && sy > 0 || sx < 0 && sy < 0)
+ { /* [x] and [y] have identical signs -- addition */
+ t = 0;
+ for (; ex || ey; ex = ex->next, ey = ey->next)
+ { if (ex == NULL)
+ ex = &zero;
+ if (ey == NULL)
+ ey = &zero;
+ ee = gmp_get_atom(sizeof(struct mpz_seg));
+ for (k = 0; k <= 5; k++)
+ { t += (unsigned int)ex->d[k];
+ t += (unsigned int)ey->d[k];
+ ee->d[k] = (unsigned short)t;
+ t >>= 16;
+ }
+ ee->next = NULL;
+ if (ez == NULL)
+ ez = ee;
+ else
+ es->next = ee;
+ es = ee;
+ }
+ if (t)
+ { /* overflow -- one extra digit is needed */
+ ee = gmp_get_atom(sizeof(struct mpz_seg));
+ ee->d[0] = 1;
+ ee->d[1] = ee->d[2] = ee->d[3] = ee->d[4] = ee->d[5] = 0;
+ ee->next = NULL;
+ xassert(es != NULL);
+ es->next = ee;
+ }
+ }
+ else
+ { /* [x] and [y] have different signs -- subtraction */
+ t = 1;
+ for (; ex || ey; ex = ex->next, ey = ey->next)
+ { if (ex == NULL)
+ ex = &zero;
+ if (ey == NULL)
+ ey = &zero;
+ ee = gmp_get_atom(sizeof(struct mpz_seg));
+ for (k = 0; k <= 5; k++)
+ { t += (unsigned int)ex->d[k];
+ t += (0xFFFF - (unsigned int)ey->d[k]);
+ ee->d[k] = (unsigned short)t;
+ t >>= 16;
+ }
+ ee->next = NULL;
+ if (ez == NULL)
+ ez = ee;
+ else
+ es->next = ee;
+ es = ee;
+ }
+ if (!t)
+ { /* |[x]| < |[y]| -- result in complement coding */
+ sz = - sz;
+ t = 1;
+ for (ee = ez; ee != NULL; ee = ee->next)
+ { for (k = 0; k <= 5; k++)
+ { t += (0xFFFF - (unsigned int)ee->d[k]);
+ ee->d[k] = (unsigned short)t;
+ t >>= 16;
+ }
+ }
+ }
+ }
+ /* contruct and normalize result */
+ mpz_set_si(z, 0);
+ z->val = sz;
+ z->ptr = ez;
+ normalize(z);
+done: return;
+}
+
+void mpz_sub(mpz_t z, mpz_t x, mpz_t y)
+{ /* set z to x - y */
+ if (x == y)
+ mpz_set_si(z, 0);
+ else
+ { y->val = - y->val;
+ mpz_add(z, x, y);
+ if (y != z)
+ y->val = - y->val;
+ }
+ return;
+}
+
+void mpz_mul(mpz_t z, mpz_t x, mpz_t y)
+{ /* set z to x * y */
+ struct mpz_seg dumx, dumy, *ex, *ey, *es, *e;
+ int sx, sy, k, nx, ny, n;
+ unsigned int t;
+ unsigned short *work, *wx, *wy;
+ /* if [x] = 0 then [z] = 0 */
+ if (x->val == 0)
+ { xassert(x->ptr == NULL);
+ mpz_set_si(z, 0);
+ goto done;
+ }
+ /* if [y] = 0 then [z] = 0 */
+ if (y->val == 0)
+ { xassert(y->ptr == NULL);
+ mpz_set_si(z, 0);
+ goto done;
+ }
+ /* special case when both [x] and [y] are in short format */
+ if (x->ptr == NULL && y->ptr == NULL)
+ { int xval = x->val, yval = y->val, sz = +1;
+ xassert(xval != 0x80000000 && yval != 0x80000000);
+ if (xval < 0)
+ xval = - xval, sz = - sz;
+ if (yval < 0)
+ yval = - yval, sz = - sz;
+ if (xval <= 0x7FFFFFFF / yval)
+ { mpz_set_si(z, sz * (xval * yval));
+ goto done;
+ }
+ }
+ /* convert [x] to long format, if necessary */
+ if (x->ptr == NULL)
+ { xassert(x->val != 0x80000000);
+ if (x->val >= 0)
+ { sx = +1;
+ t = (unsigned int)(+ x->val);
+ }
+ else
+ { sx = -1;
+ t = (unsigned int)(- x->val);
+ }
+ ex = &dumx;
+ ex->d[0] = (unsigned short)t;
+ ex->d[1] = (unsigned short)(t >> 16);
+ ex->d[2] = ex->d[3] = ex->d[4] = ex->d[5] = 0;
+ ex->next = NULL;
+ }
+ else
+ { sx = x->val;
+ xassert(sx == +1 || sx == -1);
+ ex = x->ptr;
+ }
+ /* convert [y] to long format, if necessary */
+ if (y->ptr == NULL)
+ { xassert(y->val != 0x80000000);
+ if (y->val >= 0)
+ { sy = +1;
+ t = (unsigned int)(+ y->val);
+ }
+ else
+ { sy = -1;
+ t = (unsigned int)(- y->val);
+ }
+ ey = &dumy;
+ ey->d[0] = (unsigned short)t;
+ ey->d[1] = (unsigned short)(t >> 16);
+ ey->d[2] = ey->d[3] = ey->d[4] = ey->d[5] = 0;
+ ey->next = NULL;
+ }
+ else
+ { sy = y->val;
+ xassert(sy == +1 || sy == -1);
+ ey = y->ptr;
+ }
+ /* determine the number of digits of [x] */
+ nx = n = 0;
+ for (e = ex; e != NULL; e = e->next)
+ { for (k = 0; k <= 5; k++)
+ { n++;
+ if (e->d[k])
+ nx = n;
+ }
+ }
+ xassert(nx > 0);
+ /* determine the number of digits of [y] */
+ ny = n = 0;
+ for (e = ey; e != NULL; e = e->next)
+ { for (k = 0; k <= 5; k++)
+ { n++;
+ if (e->d[k])
+ ny = n;
+ }
+ }
+ xassert(ny > 0);
+ /* we need working array containing at least nx+ny+ny places */
+ work = gmp_get_work(nx+ny+ny);
+ /* load digits of [x] */
+ wx = &work[0];
+ for (n = 0; n < nx; n++)
+ wx[ny+n] = 0;
+ for (n = 0, e = ex; e != NULL; e = e->next)
+ { for (k = 0; k <= 5; k++, n++)
+ { if (e->d[k])
+ wx[ny+n] = e->d[k];
+ }
+ }
+ /* load digits of [y] */
+ wy = &work[nx+ny];
+ for (n = 0; n < ny; n++) wy[n] = 0;
+ for (n = 0, e = ey; e != NULL; e = e->next)
+ { for (k = 0; k <= 5; k++, n++)
+ { if (e->d[k])
+ wy[n] = e->d[k];
+ }
+ }
+ /* compute [x] * [y] */
+ bigmul(nx, ny, wx, wy);
+ /* construct and normalize result */
+ mpz_set_si(z, 0);
+ z->val = sx * sy;
+ es = NULL;
+ k = 6;
+ for (n = 0; n < nx+ny; n++)
+ { if (k > 5)
+ { e = gmp_get_atom(sizeof(struct mpz_seg));
+ e->d[0] = e->d[1] = e->d[2] = 0;
+ e->d[3] = e->d[4] = e->d[5] = 0;
+ e->next = NULL;
+ if (z->ptr == NULL)
+ z->ptr = e;
+ else
+ es->next = e;
+ es = e;
+ k = 0;
+ }
+ es->d[k++] = wx[n];
+ }
+ normalize(z);
+done: return;
+}
+
+void mpz_neg(mpz_t z, mpz_t x)
+{ /* set z to 0 - x */
+ mpz_set(z, x);
+ z->val = - z->val;
+ return;
+}
+
+void mpz_abs(mpz_t z, mpz_t x)
+{ /* set z to the absolute value of x */
+ mpz_set(z, x);
+ if (z->val < 0)
+ z->val = - z->val;
+ return;
+}
+
+void mpz_div(mpz_t q, mpz_t r, mpz_t x, mpz_t y)
+{ /* divide x by y, forming quotient q and/or remainder r
+ * if q = NULL then quotient is not stored; if r = NULL then
+ * remainder is not stored
+ * the sign of quotient is determined as in algebra while the
+ * sign of remainder is the same as the sign of dividend:
+ * +26 : +7 = +3, remainder is +5
+ * -26 : +7 = -3, remainder is -5
+ * +26 : -7 = -3, remainder is +5
+ * -26 : -7 = +3, remainder is -5 */
+ struct mpz_seg dumx, dumy, *ex, *ey, *es, *e;
+ int sx, sy, k, nx, ny, n;
+ unsigned int t;
+ unsigned short *work, *wx, *wy;
+ /* divide by zero is not allowed */
+ if (y->val == 0)
+ { xassert(y->ptr == NULL);
+ xerror("mpz_div: divide by zero not allowed\n");
+ }
+ /* if [x] = 0 then [q] = [r] = 0 */
+ if (x->val == 0)
+ { xassert(x->ptr == NULL);
+ if (q != NULL)
+ mpz_set_si(q, 0);
+ if (r != NULL)
+ mpz_set_si(r, 0);
+ goto done;
+ }
+ /* special case when both [x] and [y] are in short format */
+ if (x->ptr == NULL && y->ptr == NULL)
+ { int xval = x->val, yval = y->val;
+ xassert(xval != 0x80000000 && yval != 0x80000000);
+ /* FIXME: use div function */
+ if (q != NULL)
+ mpz_set_si(q, xval / yval);
+ if (r != NULL)
+ mpz_set_si(r, xval % yval);
+ goto done;
+ }
+ /* convert [x] to long format, if necessary */
+ if (x->ptr == NULL)
+ { xassert(x->val != 0x80000000);
+ if (x->val >= 0)
+ { sx = +1;
+ t = (unsigned int)(+ x->val);
+ }
+ else
+ { sx = -1;
+ t = (unsigned int)(- x->val);
+ }
+ ex = &dumx;
+ ex->d[0] = (unsigned short)t;
+ ex->d[1] = (unsigned short)(t >> 16);
+ ex->d[2] = ex->d[3] = ex->d[4] = ex->d[5] = 0;
+ ex->next = NULL;
+ }
+ else
+ { sx = x->val;
+ xassert(sx == +1 || sx == -1);
+ ex = x->ptr;
+ }
+ /* convert [y] to long format, if necessary */
+ if (y->ptr == NULL)
+ { xassert(y->val != 0x80000000);
+ if (y->val >= 0)
+ { sy = +1;
+ t = (unsigned int)(+ y->val);
+ }
+ else
+ { sy = -1;
+ t = (unsigned int)(- y->val);
+ }
+ ey = &dumy;
+ ey->d[0] = (unsigned short)t;
+ ey->d[1] = (unsigned short)(t >> 16);
+ ey->d[2] = ey->d[3] = ey->d[4] = ey->d[5] = 0;
+ ey->next = NULL;
+ }
+ else
+ { sy = y->val;
+ xassert(sy == +1 || sy == -1);
+ ey = y->ptr;
+ }
+ /* determine the number of digits of [x] */
+ nx = n = 0;
+ for (e = ex; e != NULL; e = e->next)
+ { for (k = 0; k <= 5; k++)
+ { n++;
+ if (e->d[k])
+ nx = n;
+ }
+ }
+ xassert(nx > 0);
+ /* determine the number of digits of [y] */
+ ny = n = 0;
+ for (e = ey; e != NULL; e = e->next)
+ { for (k = 0; k <= 5; k++)
+ { n++;
+ if (e->d[k])
+ ny = n;
+ }
+ }
+ xassert(ny > 0);
+ /* if nx < ny then [q] = 0 and [r] = [x] */
+ if (nx < ny)
+ { if (r != NULL)
+ mpz_set(r, x);
+ if (q != NULL)
+ mpz_set_si(q, 0);
+ goto done;
+ }
+ /* we need working array containing at least nx+ny+1 places */
+ work = gmp_get_work(nx+ny+1);
+ /* load digits of [x] */
+ wx = &work[0];
+ for (n = 0; n < nx; n++)
+ wx[n] = 0;
+ for (n = 0, e = ex; e != NULL; e = e->next)
+ { for (k = 0; k <= 5; k++, n++)
+ if (e->d[k]) wx[n] = e->d[k];
+ }
+ /* load digits of [y] */
+ wy = &work[nx+1];
+ for (n = 0; n < ny; n++)
+ wy[n] = 0;
+ for (n = 0, e = ey; e != NULL; e = e->next)
+ { for (k = 0; k <= 5; k++, n++)
+ if (e->d[k]) wy[n] = e->d[k];
+ }
+ /* compute quotient and remainder */
+ xassert(wy[ny-1] != 0);
+ bigdiv(nx-ny, ny, wx, wy);
+ /* construct and normalize quotient */
+ if (q != NULL)
+ { mpz_set_si(q, 0);
+ q->val = sx * sy;
+ es = NULL;
+ k = 6;
+ for (n = ny; n <= nx; n++)
+ { if (k > 5)
+ { e = gmp_get_atom(sizeof(struct mpz_seg));
+ e->d[0] = e->d[1] = e->d[2] = 0;
+ e->d[3] = e->d[4] = e->d[5] = 0;
+ e->next = NULL;
+ if (q->ptr == NULL)
+ q->ptr = e;
+ else
+ es->next = e;
+ es = e;
+ k = 0;
+ }
+ es->d[k++] = wx[n];
+ }
+ normalize(q);
+ }
+ /* construct and normalize remainder */
+ if (r != NULL)
+ { mpz_set_si(r, 0);
+ r->val = sx;
+ es = NULL;
+ k = 6;
+ for (n = 0; n < ny; n++)
+ { if (k > 5)
+ { e = gmp_get_atom(sizeof(struct mpz_seg));
+ e->d[0] = e->d[1] = e->d[2] = 0;
+ e->d[3] = e->d[4] = e->d[5] = 0;
+ e->next = NULL;
+ if (r->ptr == NULL)
+ r->ptr = e;
+ else
+ es->next = e;
+ es = e;
+ k = 0;
+ }
+ es->d[k++] = wx[n];
+ }
+ normalize(r);
+ }
+done: return;
+}
+
+void mpz_gcd(mpz_t z, mpz_t x, mpz_t y)
+{ /* set z to the greatest common divisor of x and y */
+ /* in case of arbitrary integers GCD(x, y) = GCD(|x|, |y|), and,
+ * in particular, GCD(0, 0) = 0 */
+ mpz_t u, v, r;
+ mpz_init(u);
+ mpz_init(v);
+ mpz_init(r);
+ mpz_abs(u, x);
+ mpz_abs(v, y);
+ while (mpz_sgn(v))
+ { mpz_div(NULL, r, u, v);
+ mpz_set(u, v);
+ mpz_set(v, r);
+ }
+ mpz_set(z, u);
+ mpz_clear(u);
+ mpz_clear(v);
+ mpz_clear(r);
+ return;
+}
+
+int mpz_cmp(mpz_t x, mpz_t y)
+{ /* compare x and y; return a positive value if x > y, zero if
+ * x = y, or a nefative value if x < y */
+ static struct mpz_seg zero = { { 0, 0, 0, 0, 0, 0 }, NULL };
+ struct mpz_seg dumx, dumy, *ex, *ey;
+ int cc, sx, sy, k;
+ unsigned int t;
+ if (x == y)
+ { cc = 0;
+ goto done;
+ }
+ /* special case when both [x] and [y] are in short format */
+ if (x->ptr == NULL && y->ptr == NULL)
+ { int xval = x->val, yval = y->val;
+ xassert(xval != 0x80000000 && yval != 0x80000000);
+ cc = (xval > yval ? +1 : xval < yval ? -1 : 0);
+ goto done;
+ }
+ /* special case when [x] and [y] have different signs */
+ if (x->val > 0 && y->val <= 0 || x->val == 0 && y->val < 0)
+ { cc = +1;
+ goto done;
+ }
+ if (x->val < 0 && y->val >= 0 || x->val == 0 && y->val > 0)
+ { cc = -1;
+ goto done;
+ }
+ /* convert [x] to long format, if necessary */
+ if (x->ptr == NULL)
+ { xassert(x->val != 0x80000000);
+ if (x->val >= 0)
+ { sx = +1;
+ t = (unsigned int)(+ x->val);
+ }
+ else
+ { sx = -1;
+ t = (unsigned int)(- x->val);
+ }
+ ex = &dumx;
+ ex->d[0] = (unsigned short)t;
+ ex->d[1] = (unsigned short)(t >> 16);
+ ex->d[2] = ex->d[3] = ex->d[4] = ex->d[5] = 0;
+ ex->next = NULL;
+ }
+ else
+ { sx = x->val;
+ xassert(sx == +1 || sx == -1);
+ ex = x->ptr;
+ }
+ /* convert [y] to long format, if necessary */
+ if (y->ptr == NULL)
+ { xassert(y->val != 0x80000000);
+ if (y->val >= 0)
+ { sy = +1;
+ t = (unsigned int)(+ y->val);
+ }
+ else
+ { sy = -1;
+ t = (unsigned int)(- y->val);
+ }
+ ey = &dumy;
+ ey->d[0] = (unsigned short)t;
+ ey->d[1] = (unsigned short)(t >> 16);
+ ey->d[2] = ey->d[3] = ey->d[4] = ey->d[5] = 0;
+ ey->next = NULL;
+ }
+ else
+ { sy = y->val;
+ xassert(sy == +1 || sy == -1);
+ ey = y->ptr;
+ }
+ /* main fragment */
+ xassert(sx > 0 && sy > 0 || sx < 0 && sy < 0);
+ cc = 0;
+ for (; ex || ey; ex = ex->next, ey = ey->next)
+ { if (ex == NULL)
+ ex = &zero;
+ if (ey == NULL)
+ ey = &zero;
+ for (k = 0; k <= 5; k++)
+ { if (ex->d[k] > ey->d[k])
+ cc = +1;
+ if (ex->d[k] < ey->d[k])
+ cc = -1;
+ }
+ }
+ if (sx < 0) cc = - cc;
+done: return cc;
+}
+
+int mpz_sgn(mpz_t x)
+{ /* return +1 if x > 0, 0 if x = 0, and -1 if x < 0 */
+ int s;
+ s = (x->val > 0 ? +1 : x->val < 0 ? -1 : 0);
+ return s;
+}
+
+int mpz_out_str(void *_fp, int base, mpz_t x)
+{ /* output x on stream fp, as a string in given base; the base
+ * may vary from 2 to 36;
+ * return the number of bytes written, or if an error occurred,
+ * return 0 */
+ FILE *fp = _fp;
+ mpz_t b, y, r;
+ int n, j, nwr = 0;
+ unsigned char *d;
+ static char *set = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ if (!(2 <= base && base <= 36))
+ xerror("mpz_out_str: base = %d; invalid base\n", base);
+ mpz_init(b);
+ mpz_set_si(b, base);
+ mpz_init(y);
+ mpz_init(r);
+ /* determine the number of digits */
+ mpz_abs(y, x);
+ for (n = 0; mpz_sgn(y) != 0; n++)
+ mpz_div(y, NULL, y, b);
+ if (n == 0) n = 1;
+ /* compute the digits */
+ d = xmalloc(n);
+ mpz_abs(y, x);
+ for (j = 0; j < n; j++)
+ { mpz_div(y, r, y, b);
+ xassert(0 <= r->val && r->val < base && r->ptr == NULL);
+ d[j] = (unsigned char)r->val;
+ }
+ /* output the integer to the stream */
+ if (fp == NULL)
+ fp = stdout;
+ if (mpz_sgn(x) < 0)
+ fputc('-', fp), nwr++;
+ for (j = n-1; j >= 0; j--)
+ fputc(set[d[j]], fp), nwr++;
+ if (ferror(fp))
+ nwr = 0;
+ mpz_clear(b);
+ mpz_clear(y);
+ mpz_clear(r);
+ xfree(d);
+ return nwr;
+}
+
+/*--------------------------------------------------------------------*/
+
+mpq_t _mpq_init(void)
+{ /* initialize x, and set its value to 0/1 */
+ mpq_t x;
+ x = gmp_get_atom(sizeof(struct mpq));
+ x->p.val = 0;
+ x->p.ptr = NULL;
+ x->q.val = 1;
+ x->q.ptr = NULL;
+ return x;
+}
+
+void mpq_clear(mpq_t x)
+{ /* free the space occupied by x */
+ mpz_set_si(&x->p, 0);
+ xassert(x->p.ptr == NULL);
+ mpz_set_si(&x->q, 0);
+ xassert(x->q.ptr == NULL);
+ /* free the number descriptor */
+ gmp_free_atom(x, sizeof(struct mpq));
+ return;
+}
+
+void mpq_canonicalize(mpq_t x)
+{ /* remove any factors that are common to the numerator and
+ * denominator of x, and make the denominator positive */
+ mpz_t f;
+ xassert(x->q.val != 0);
+ if (x->q.val < 0)
+ { mpz_neg(&x->p, &x->p);
+ mpz_neg(&x->q, &x->q);
+ }
+ mpz_init(f);
+ mpz_gcd(f, &x->p, &x->q);
+ if (!(f->val == 1 && f->ptr == NULL))
+ { mpz_div(&x->p, NULL, &x->p, f);
+ mpz_div(&x->q, NULL, &x->q, f);
+ }
+ mpz_clear(f);
+ return;
+}
+
+void mpq_set(mpq_t z, mpq_t x)
+{ /* set the value of z from x */
+ if (z != x)
+ { mpz_set(&z->p, &x->p);
+ mpz_set(&z->q, &x->q);
+ }
+ return;
+}
+
+void mpq_set_si(mpq_t x, int p, unsigned int q)
+{ /* set the value of x to p/q */
+ if (q == 0)
+ xerror("mpq_set_si: zero denominator not allowed\n");
+ mpz_set_si(&x->p, p);
+ xassert(q <= 0x7FFFFFFF);
+ mpz_set_si(&x->q, q);
+ return;
+}
+
+double mpq_get_d(mpq_t x)
+{ /* convert x to a double, truncating if necessary */
+ int np, nq;
+ double p, q;
+ p = mpz_get_d_2exp(&np, &x->p);
+ q = mpz_get_d_2exp(&nq, &x->q);
+ return ldexp(p / q, np - nq);
+}
+
+void mpq_set_d(mpq_t x, double val)
+{ /* set x to val; there is no rounding, the conversion is exact */
+ int s, n, d, j;
+ double f;
+ mpz_t temp;
+ xassert(-DBL_MAX <= val && val <= +DBL_MAX);
+ mpq_set_si(x, 0, 1);
+ if (val > 0.0)
+ s = +1;
+ else if (val < 0.0)
+ s = -1;
+ else
+ goto done;
+ f = frexp(fabs(val), &n);
+ /* |val| = f * 2^n, where 0.5 <= f < 1.0 */
+ mpz_init(temp);
+ while (f != 0.0)
+ { f *= 16.0, n -= 4;
+ d = (int)f;
+ xassert(0 <= d && d <= 15);
+ f -= (double)d;
+ /* x := 16 * x + d */
+ mpz_set_si(temp, 16);
+ mpz_mul(&x->p, &x->p, temp);
+ mpz_set_si(temp, d);
+ mpz_add(&x->p, &x->p, temp);
+ }
+ mpz_clear(temp);
+ /* x := x * 2^n */
+ if (n > 0)
+ { for (j = 1; j <= n; j++)
+ mpz_add(&x->p, &x->p, &x->p);
+ }
+ else if (n < 0)
+ { for (j = 1; j <= -n; j++)
+ mpz_add(&x->q, &x->q, &x->q);
+ mpq_canonicalize(x);
+ }
+ if (s < 0)
+ mpq_neg(x, x);
+done: return;
+}
+
+void mpq_add(mpq_t z, mpq_t x, mpq_t y)
+{ /* set z to x + y */
+ mpz_t p, q;
+ mpz_init(p);
+ mpz_init(q);
+ mpz_mul(p, &x->p, &y->q);
+ mpz_mul(q, &x->q, &y->p);
+ mpz_add(p, p, q);
+ mpz_mul(q, &x->q, &y->q);
+ mpz_set(&z->p, p);
+ mpz_set(&z->q, q);
+ mpz_clear(p);
+ mpz_clear(q);
+ mpq_canonicalize(z);
+ return;
+}
+
+void mpq_sub(mpq_t z, mpq_t x, mpq_t y)
+{ /* set z to x - y */
+ mpz_t p, q;
+ mpz_init(p);
+ mpz_init(q);
+ mpz_mul(p, &x->p, &y->q);
+ mpz_mul(q, &x->q, &y->p);
+ mpz_sub(p, p, q);
+ mpz_mul(q, &x->q, &y->q);
+ mpz_set(&z->p, p);
+ mpz_set(&z->q, q);
+ mpz_clear(p);
+ mpz_clear(q);
+ mpq_canonicalize(z);
+ return;
+}
+
+void mpq_mul(mpq_t z, mpq_t x, mpq_t y)
+{ /* set z to x * y */
+ mpz_mul(&z->p, &x->p, &y->p);
+ mpz_mul(&z->q, &x->q, &y->q);
+ mpq_canonicalize(z);
+ return;
+}
+
+void mpq_div(mpq_t z, mpq_t x, mpq_t y)
+{ /* set z to x / y */
+ mpz_t p, q;
+ if (mpq_sgn(y) == 0)
+ xerror("mpq_div: zero divisor not allowed\n");
+ mpz_init(p);
+ mpz_init(q);
+ mpz_mul(p, &x->p, &y->q);
+ mpz_mul(q, &x->q, &y->p);
+ mpz_set(&z->p, p);
+ mpz_set(&z->q, q);
+ mpz_clear(p);
+ mpz_clear(q);
+ mpq_canonicalize(z);
+ return;
+}
+
+void mpq_neg(mpq_t z, mpq_t x)
+{ /* set z to 0 - x */
+ mpq_set(z, x);
+ mpz_neg(&z->p, &z->p);
+ return;
+}
+
+void mpq_abs(mpq_t z, mpq_t x)
+{ /* set z to the absolute value of x */
+ mpq_set(z, x);
+ mpz_abs(&z->p, &z->p);
+ xassert(mpz_sgn(&x->q) > 0);
+ return;
+}
+
+int mpq_cmp(mpq_t x, mpq_t y)
+{ /* compare x and y; return a positive value if x > y, zero if
+ * x = y, or a negative value if x < y */
+ mpq_t temp;
+ int s;
+ mpq_init(temp);
+ mpq_sub(temp, x, y);
+ s = mpq_sgn(temp);
+ mpq_clear(temp);
+ return s;
+}
+
+int mpq_sgn(mpq_t x)
+{ /* return +1 if x > 0, 0 if x = 0, and -1 if x < 0 */
+ int s;
+ s = mpz_sgn(&x->p);
+ xassert(mpz_sgn(&x->q) > 0);
+ return s;
+}
+
+int mpq_out_str(void *_fp, int base, mpq_t x)
+{ /* output x on stream fp, as a string in given base; the base
+ * may vary from 2 to 36; output is in the form 'num/den' or if
+ * the denominator is 1 then just 'num';
+ * if the parameter fp is a null pointer, stdout is assumed;
+ * return the number of bytes written, or if an error occurred,
+ * return 0 */
+ FILE *fp = _fp;
+ int nwr;
+ if (!(2 <= base && base <= 36))
+ xerror("mpq_out_str: base = %d; invalid base\n", base);
+ if (fp == NULL)
+ fp = stdout;
+ nwr = mpz_out_str(fp, base, &x->p);
+ if (x->q.val == 1 && x->q.ptr == NULL)
+ ;
+ else
+ { fputc('/', fp), nwr++;
+ nwr += mpz_out_str(fp, base, &x->q);
+ }
+ if (ferror(fp))
+ nwr = 0;
+ return nwr;
+}
+
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/mygmp.h b/test/monniaux/glpk-4.65/src/misc/mygmp.h
new file mode 100644
index 00000000..31d2024d
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/mygmp.h
@@ -0,0 +1,254 @@
+/* mygmp.h (integer and rational arithmetic) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2008-2015 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#ifndef MYGMP_H
+#define MYGMP_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_GMP /* use GNU MP library */
+
+#include <gmp.h>
+
+#define gmp_pool_count() 0
+
+#define gmp_free_mem() ((void)0)
+
+#else /* use GLPK MP module */
+
+/***********************************************************************
+* INTEGER NUMBERS
+* ---------------
+* Depending on its magnitude an integer number of arbitrary precision
+* is represented either in short format or in long format.
+*
+* Short format corresponds to the int type and allows representing
+* integer numbers in the range [-(2^31-1), +(2^31-1)]. Note that for
+* the most negative number of int type the short format is not used.
+*
+* In long format integer numbers are represented using the positional
+* system with the base (radix) 2^16 = 65536:
+*
+* x = (-1)^s sum{j in 0..n-1} d[j] * 65536^j,
+*
+* where x is the integer to be represented, s is its sign (+1 or -1),
+* d[j] are its digits (0 <= d[j] <= 65535).
+*
+* RATIONAL NUMBERS
+* ----------------
+* A rational number is represented as an irreducible fraction:
+*
+* p / q,
+*
+* where p (numerator) and q (denominator) are integer numbers (q > 0)
+* having no common divisors. */
+
+struct mpz
+{ /* integer number */
+ int val;
+ /* if ptr is a null pointer, the number is in short format, and
+ val is its value; otherwise, the number is in long format, and
+ val is its sign (+1 or -1) */
+ struct mpz_seg *ptr;
+ /* pointer to the linked list of the number segments ordered in
+ ascending of powers of the base */
+};
+
+struct mpz_seg
+{ /* integer number segment */
+ unsigned short d[6];
+ /* six digits of the number ordered in ascending of powers of the
+ base */
+ struct mpz_seg *next;
+ /* pointer to the next number segment */
+};
+
+struct mpq
+{ /* rational number (p / q) */
+ struct mpz p;
+ /* numerator */
+ struct mpz q;
+ /* denominator */
+};
+
+typedef struct mpz *mpz_t;
+typedef struct mpq *mpq_t;
+
+#define gmp_get_atom _glp_gmp_get_atom
+void *gmp_get_atom(int size);
+
+#define gmp_free_atom _glp_gmp_free_atom
+void gmp_free_atom(void *ptr, int size);
+
+#define gmp_pool_count _glp_gmp_pool_count
+int gmp_pool_count(void);
+
+#define gmp_get_work _glp_gmp_get_work
+unsigned short *gmp_get_work(int size);
+
+#define gmp_free_mem _glp_gmp_free_mem
+void gmp_free_mem(void);
+
+#define mpz_init(x) (void)((x) = _mpz_init())
+
+#define _mpz_init _glp_mpz_init
+mpz_t _mpz_init(void);
+/* initialize x and set its value to 0 */
+
+#define mpz_clear _glp_mpz_clear
+void mpz_clear(mpz_t x);
+/* free the space occupied by x */
+
+#define mpz_set _glp_mpz_set
+void mpz_set(mpz_t z, mpz_t x);
+/* set the value of z from x */
+
+#define mpz_set_si _glp_mpz_set_si
+void mpz_set_si(mpz_t x, int val);
+/* set the value of x to val */
+
+#define mpz_get_d _glp_mpz_get_d
+double mpz_get_d(mpz_t x);
+/* convert x to a double, truncating if necessary */
+
+#define mpz_get_d_2exp _glp_mpz_get_d_2exp
+double mpz_get_d_2exp(int *exp, mpz_t x);
+/* convert x to a double, returning the exponent separately */
+
+#define mpz_swap _glp_mpz_swap
+void mpz_swap(mpz_t x, mpz_t y);
+/* swap the values x and y efficiently */
+
+#define mpz_add _glp_mpz_add
+void mpz_add(mpz_t, mpz_t, mpz_t);
+/* set z to x + y */
+
+#define mpz_sub _glp_mpz_sub
+void mpz_sub(mpz_t, mpz_t, mpz_t);
+/* set z to x - y */
+
+#define mpz_mul _glp_mpz_mul
+void mpz_mul(mpz_t, mpz_t, mpz_t);
+/* set z to x * y */
+
+#define mpz_neg _glp_mpz_neg
+void mpz_neg(mpz_t z, mpz_t x);
+/* set z to 0 - x */
+
+#define mpz_abs _glp_mpz_abs
+void mpz_abs(mpz_t z, mpz_t x);
+/* set z to the absolute value of x */
+
+#define mpz_div _glp_mpz_div
+void mpz_div(mpz_t q, mpz_t r, mpz_t x, mpz_t y);
+/* divide x by y, forming quotient q and/or remainder r */
+
+#define mpz_gcd _glp_mpz_gcd
+void mpz_gcd(mpz_t z, mpz_t x, mpz_t y);
+/* set z to the greatest common divisor of x and y */
+
+#define mpz_cmp _glp_mpz_cmp
+int mpz_cmp(mpz_t x, mpz_t y);
+/* compare x and y */
+
+#define mpz_sgn _glp_mpz_sgn
+int mpz_sgn(mpz_t x);
+/* return +1 if x > 0, 0 if x = 0, and -1 if x < 0 */
+
+#define mpz_out_str _glp_mpz_out_str
+int mpz_out_str(void *fp, int base, mpz_t x);
+/* output x on stream fp, as a string in given base */
+
+#define mpq_init(x) (void)((x) = _mpq_init())
+
+#define _mpq_init _glp_mpq_init
+mpq_t _mpq_init(void);
+/* initialize x, and set its value to 0/1 */
+
+#define mpq_clear _glp_mpq_clear
+void mpq_clear(mpq_t x);
+/* free the space occupied by x */
+
+#define mpq_canonicalize _glp_mpq_canonicalize
+void mpq_canonicalize(mpq_t x);
+/* canonicalize x */
+
+#define mpq_set _glp_mpq_set
+void mpq_set(mpq_t z, mpq_t x);
+/* set the value of z from x */
+
+#define mpq_set_si _glp_mpq_set_si
+void mpq_set_si(mpq_t x, int p, unsigned int q);
+/* set the value of x to p/q */
+
+#define mpq_get_d _glp_mpq_get_d
+double mpq_get_d(mpq_t x);
+/* convert x to a double, truncating if necessary */
+
+#define mpq_set_d _glp_mpq_set_d
+void mpq_set_d(mpq_t x, double val);
+/* set x to val; there is no rounding, the conversion is exact */
+
+#define mpq_add _glp_mpq_add
+void mpq_add(mpq_t z, mpq_t x, mpq_t y);
+/* set z to x + y */
+
+#define mpq_sub _glp_mpq_sub
+void mpq_sub(mpq_t z, mpq_t x, mpq_t y);
+/* set z to x - y */
+
+#define mpq_mul _glp_mpq_mul
+void mpq_mul(mpq_t z, mpq_t x, mpq_t y);
+/* set z to x * y */
+
+#define mpq_div _glp_mpq_div
+void mpq_div(mpq_t z, mpq_t x, mpq_t y);
+/* set z to x / y */
+
+#define mpq_neg _glp_mpq_neg
+void mpq_neg(mpq_t z, mpq_t x);
+/* set z to 0 - x */
+
+#define mpq_abs _glp_mpq_abs
+void mpq_abs(mpq_t z, mpq_t x);
+/* set z to the absolute value of x */
+
+#define mpq_cmp _glp_mpq_cmp
+int mpq_cmp(mpq_t x, mpq_t y);
+/* compare x and y */
+
+#define mpq_sgn _glp_mpq_sgn
+int mpq_sgn(mpq_t x);
+/* return +1 if x > 0, 0 if x = 0, and -1 if x < 0 */
+
+#define mpq_out_str _glp_mpq_out_str
+int mpq_out_str(void *fp, int base, mpq_t x);
+/* output x on stream fp, as a string in given base */
+
+#endif
+
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/okalg.c b/test/monniaux/glpk-4.65/src/misc/okalg.c
new file mode 100644
index 00000000..8eecd6df
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/okalg.c
@@ -0,0 +1,382 @@
+/* okalg.c (out-of-kilter algorithm) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include "env.h"
+#include "okalg.h"
+
+/***********************************************************************
+* NAME
+*
+* okalg - out-of-kilter algorithm
+*
+* SYNOPSIS
+*
+* #include "okalg.h"
+* int okalg(int nv, int na, const int tail[], const int head[],
+* const int low[], const int cap[], const int cost[], int x[],
+* int pi[]);
+*
+* DESCRIPTION
+*
+* The routine okalg implements the out-of-kilter algorithm to find a
+* minimal-cost circulation in the specified flow network.
+*
+* INPUT PARAMETERS
+*
+* nv is the number of nodes, nv >= 0.
+*
+* na is the number of arcs, na >= 0.
+*
+* tail[a], a = 1,...,na, is the index of tail node of arc a.
+*
+* head[a], a = 1,...,na, is the index of head node of arc a.
+*
+* low[a], a = 1,...,na, is an lower bound to the flow through arc a.
+*
+* cap[a], a = 1,...,na, is an upper bound to the flow through arc a,
+* which is the capacity of the arc.
+*
+* cost[a], a = 1,...,na, is a per-unit cost of the flow through arc a.
+*
+* NOTES
+*
+* 1. Multiple arcs are allowed, but self-loops are not allowed.
+*
+* 2. It is required that 0 <= low[a] <= cap[a] for all arcs.
+*
+* 3. Arc costs may have any sign.
+*
+* OUTPUT PARAMETERS
+*
+* x[a], a = 1,...,na, is optimal value of the flow through arc a.
+*
+* pi[i], i = 1,...,nv, is Lagrange multiplier for flow conservation
+* equality constraint corresponding to node i (the node potential).
+*
+* RETURNS
+*
+* 0 optimal circulation found;
+*
+* 1 there is no feasible circulation;
+*
+* 2 integer overflow occured;
+*
+* 3 optimality test failed (logic error).
+*
+* REFERENCES
+*
+* L.R.Ford, Jr., and D.R.Fulkerson, "Flows in Networks," The RAND
+* Corp., Report R-375-PR (August 1962), Chap. III "Minimal Cost Flow
+* Problems," pp.113-26. */
+
+static int overflow(int u, int v)
+{ /* check for integer overflow on computing u + v */
+ if (u > 0 && v > 0 && u + v < 0) return 1;
+ if (u < 0 && v < 0 && u + v > 0) return 1;
+ return 0;
+}
+
+int okalg(int nv, int na, const int tail[], const int head[],
+ const int low[], const int cap[], const int cost[], int x[],
+ int pi[])
+{ int a, aok, delta, i, j, k, lambda, pos1, pos2, s, t, temp, ret,
+ *ptr, *arc, *link, *list;
+ /* sanity checks */
+ xassert(nv >= 0);
+ xassert(na >= 0);
+ for (a = 1; a <= na; a++)
+ { i = tail[a], j = head[a];
+ xassert(1 <= i && i <= nv);
+ xassert(1 <= j && j <= nv);
+ xassert(i != j);
+ xassert(0 <= low[a] && low[a] <= cap[a]);
+ }
+ /* allocate working arrays */
+ ptr = xcalloc(1+nv+1, sizeof(int));
+ arc = xcalloc(1+na+na, sizeof(int));
+ link = xcalloc(1+nv, sizeof(int));
+ list = xcalloc(1+nv, sizeof(int));
+ /* ptr[i] := (degree of node i) */
+ for (i = 1; i <= nv; i++)
+ ptr[i] = 0;
+ for (a = 1; a <= na; a++)
+ { ptr[tail[a]]++;
+ ptr[head[a]]++;
+ }
+ /* initialize arc pointers */
+ ptr[1]++;
+ for (i = 1; i < nv; i++)
+ ptr[i+1] += ptr[i];
+ ptr[nv+1] = ptr[nv];
+ /* build arc lists */
+ for (a = 1; a <= na; a++)
+ { arc[--ptr[tail[a]]] = a;
+ arc[--ptr[head[a]]] = a;
+ }
+ xassert(ptr[1] == 1);
+ xassert(ptr[nv+1] == na+na+1);
+ /* now the indices of arcs incident to node i are stored in
+ * locations arc[ptr[i]], arc[ptr[i]+1], ..., arc[ptr[i+1]-1] */
+ /* initialize arc flows and node potentials */
+ for (a = 1; a <= na; a++)
+ x[a] = 0;
+ for (i = 1; i <= nv; i++)
+ pi[i] = 0;
+loop: /* main loop starts here */
+ /* find out-of-kilter arc */
+ aok = 0;
+ for (a = 1; a <= na; a++)
+ { i = tail[a], j = head[a];
+ if (overflow(cost[a], pi[i] - pi[j]))
+ { ret = 2;
+ goto done;
+ }
+ lambda = cost[a] + (pi[i] - pi[j]);
+ if (x[a] < low[a] || (lambda < 0 && x[a] < cap[a]))
+ { /* arc a = i->j is out of kilter, and we need to increase
+ * the flow through this arc */
+ aok = a, s = j, t = i;
+ break;
+ }
+ if (x[a] > cap[a] || (lambda > 0 && x[a] > low[a]))
+ { /* arc a = i->j is out of kilter, and we need to decrease
+ * the flow through this arc */
+ aok = a, s = i, t = j;
+ break;
+ }
+ }
+ if (aok == 0)
+ { /* all arcs are in kilter */
+ /* check for feasibility */
+ for (a = 1; a <= na; a++)
+ { if (!(low[a] <= x[a] && x[a] <= cap[a]))
+ { ret = 3;
+ goto done;
+ }
+ }
+ for (i = 1; i <= nv; i++)
+ { temp = 0;
+ for (k = ptr[i]; k < ptr[i+1]; k++)
+ { a = arc[k];
+ if (tail[a] == i)
+ { /* a is outgoing arc */
+ temp += x[a];
+ }
+ else if (head[a] == i)
+ { /* a is incoming arc */
+ temp -= x[a];
+ }
+ else
+ xassert(a != a);
+ }
+ if (temp != 0)
+ { ret = 3;
+ goto done;
+ }
+ }
+ /* check for optimality */
+ for (a = 1; a <= na; a++)
+ { i = tail[a], j = head[a];
+ lambda = cost[a] + (pi[i] - pi[j]);
+ if ((lambda > 0 && x[a] != low[a]) ||
+ (lambda < 0 && x[a] != cap[a]))
+ { ret = 3;
+ goto done;
+ }
+ }
+ /* current circulation is optimal */
+ ret = 0;
+ goto done;
+ }
+ /* now we need to find a cycle (t, a, s, ..., t), which allows
+ * increasing the flow along it, where a is the out-of-kilter arc
+ * just found */
+ /* link[i] = 0 means that node i is not labelled yet;
+ * link[i] = a means that arc a immediately precedes node i */
+ /* initially only node s is labelled */
+ for (i = 1; i <= nv; i++)
+ link[i] = 0;
+ link[s] = aok, list[1] = s, pos1 = pos2 = 1;
+ /* breadth first search */
+ while (pos1 <= pos2)
+ { /* dequeue node i */
+ i = list[pos1++];
+ /* consider all arcs incident to node i */
+ for (k = ptr[i]; k < ptr[i+1]; k++)
+ { a = arc[k];
+ if (tail[a] == i)
+ { /* a = i->j is a forward arc from s to t */
+ j = head[a];
+ /* if node j has been labelled, skip the arc */
+ if (link[j] != 0) continue;
+ /* if the arc does not allow increasing the flow through
+ * it, skip the arc */
+ if (x[a] >= cap[a]) continue;
+ if (overflow(cost[a], pi[i] - pi[j]))
+ { ret = 2;
+ goto done;
+ }
+ lambda = cost[a] + (pi[i] - pi[j]);
+ if (lambda > 0 && x[a] >= low[a]) continue;
+ }
+ else if (head[a] == i)
+ { /* a = i<-j is a backward arc from s to t */
+ j = tail[a];
+ /* if node j has been labelled, skip the arc */
+ if (link[j] != 0) continue;
+ /* if the arc does not allow decreasing the flow through
+ * it, skip the arc */
+ if (x[a] <= low[a]) continue;
+ if (overflow(cost[a], pi[j] - pi[i]))
+ { ret = 2;
+ goto done;
+ }
+ lambda = cost[a] + (pi[j] - pi[i]);
+ if (lambda < 0 && x[a] <= cap[a]) continue;
+ }
+ else
+ xassert(a != a);
+ /* label node j and enqueue it */
+ link[j] = a, list[++pos2] = j;
+ /* check for breakthrough */
+ if (j == t) goto brkt;
+ }
+ }
+ /* NONBREAKTHROUGH */
+ /* consider all arcs, whose one endpoint is labelled and other is
+ * not, and determine maximal change of node potentials */
+ delta = 0;
+ for (a = 1; a <= na; a++)
+ { i = tail[a], j = head[a];
+ if (link[i] != 0 && link[j] == 0)
+ { /* a = i->j, where node i is labelled, node j is not */
+ if (overflow(cost[a], pi[i] - pi[j]))
+ { ret = 2;
+ goto done;
+ }
+ lambda = cost[a] + (pi[i] - pi[j]);
+ if (x[a] <= cap[a] && lambda > 0)
+ if (delta == 0 || delta > + lambda) delta = + lambda;
+ }
+ else if (link[i] == 0 && link[j] != 0)
+ { /* a = j<-i, where node j is labelled, node i is not */
+ if (overflow(cost[a], pi[i] - pi[j]))
+ { ret = 2;
+ goto done;
+ }
+ lambda = cost[a] + (pi[i] - pi[j]);
+ if (x[a] >= low[a] && lambda < 0)
+ if (delta == 0 || delta > - lambda) delta = - lambda;
+ }
+ }
+ if (delta == 0)
+ { /* there is no feasible circulation */
+ ret = 1;
+ goto done;
+ }
+ /* increase potentials of all unlabelled nodes */
+ for (i = 1; i <= nv; i++)
+ { if (link[i] == 0)
+ { if (overflow(pi[i], delta))
+ { ret = 2;
+ goto done;
+ }
+ pi[i] += delta;
+ }
+ }
+ goto loop;
+brkt: /* BREAKTHROUGH */
+ /* walk through arcs of the cycle (t, a, s, ..., t) found in the
+ * reverse order and determine maximal change of the flow */
+ delta = 0;
+ for (j = t;; j = i)
+ { /* arc a immediately precedes node j in the cycle */
+ a = link[j];
+ if (head[a] == j)
+ { /* a = i->j is a forward arc of the cycle */
+ i = tail[a];
+ lambda = cost[a] + (pi[i] - pi[j]);
+ if (lambda > 0 && x[a] < low[a])
+ { /* x[a] may be increased until its lower bound */
+ temp = low[a] - x[a];
+ }
+ else if (lambda <= 0 && x[a] < cap[a])
+ { /* x[a] may be increased until its upper bound */
+ temp = cap[a] - x[a];
+ }
+ else
+ xassert(a != a);
+ }
+ else if (tail[a] == j)
+ { /* a = i<-j is a backward arc of the cycle */
+ i = head[a];
+ lambda = cost[a] + (pi[j] - pi[i]);
+ if (lambda < 0 && x[a] > cap[a])
+ { /* x[a] may be decreased until its upper bound */
+ temp = x[a] - cap[a];
+ }
+ else if (lambda >= 0 && x[a] > low[a])
+ { /* x[a] may be decreased until its lower bound */
+ temp = x[a] - low[a];
+ }
+ else
+ xassert(a != a);
+ }
+ else
+ xassert(a != a);
+ if (delta == 0 || delta > temp) delta = temp;
+ /* check for end of the cycle */
+ if (i == t) break;
+ }
+ xassert(delta > 0);
+ /* increase the flow along the cycle */
+ for (j = t;; j = i)
+ { /* arc a immediately precedes node j in the cycle */
+ a = link[j];
+ if (head[a] == j)
+ { /* a = i->j is a forward arc of the cycle */
+ i = tail[a];
+ /* overflow cannot occur */
+ x[a] += delta;
+ }
+ else if (tail[a] == j)
+ { /* a = i<-j is a backward arc of the cycle */
+ i = head[a];
+ /* overflow cannot occur */
+ x[a] -= delta;
+ }
+ else
+ xassert(a != a);
+ /* check for end of the cycle */
+ if (i == t) break;
+ }
+ goto loop;
+done: /* free working arrays */
+ xfree(ptr);
+ xfree(arc);
+ xfree(link);
+ xfree(list);
+ return ret;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/okalg.h b/test/monniaux/glpk-4.65/src/misc/okalg.h
new file mode 100644
index 00000000..2f2d9740
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/okalg.h
@@ -0,0 +1,35 @@
+/* okalg.h (out-of-kilter algorithm) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#ifndef OKALG_H
+#define OKALG_H
+
+#define okalg _glp_okalg
+int okalg(int nv, int na, const int tail[], const int head[],
+ const int low[], const int cap[], const int cost[], int x[],
+ int pi[]);
+/* out-of-kilter algorithm */
+
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/qmd.c b/test/monniaux/glpk-4.65/src/misc/qmd.c
new file mode 100644
index 00000000..a3397dcf
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/qmd.c
@@ -0,0 +1,584 @@
+/* qmd.c (quotient minimum degree algorithm) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* THIS CODE IS THE RESULT OF TRANSLATION OF THE FORTRAN SUBROUTINES
+* GENQMD, QMDRCH, QMDQT, QMDUPD, AND QMDMRG FROM THE BOOK:
+*
+* ALAN GEORGE, JOSEPH W-H LIU. COMPUTER SOLUTION OF LARGE SPARSE
+* POSITIVE DEFINITE SYSTEMS. PRENTICE-HALL, 1981.
+*
+* THE TRANSLATION HAS BEEN DONE WITH THE PERMISSION OF THE AUTHORS
+* OF THE ORIGINAL FORTRAN SUBROUTINES: ALAN GEORGE AND JOSEPH LIU,
+* UNIVERSITY OF WATERLOO, WATERLOO, ONTARIO, CANADA.
+*
+* The translation was made by Andrew Makhorin <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include "qmd.h"
+
+/***********************************************************************
+* NAME
+*
+* genqmd - GENeral Quotient Minimum Degree algorithm
+*
+* SYNOPSIS
+*
+* #include "qmd.h"
+* void genqmd(int *neqns, int xadj[], int adjncy[], int perm[],
+* int invp[], int deg[], int marker[], int rchset[], int nbrhd[],
+* int qsize[], int qlink[], int *nofsub);
+*
+* PURPOSE
+*
+* This routine implements the minimum degree algorithm. It makes use
+* of the implicit representation of the elimination graph by quotient
+* graphs, and the notion of indistinguishable nodes.
+*
+* CAUTION
+*
+* The adjancy vector adjncy will be destroyed.
+*
+* INPUT PARAMETERS
+*
+* neqns - number of equations;
+* (xadj, adjncy) -
+* the adjancy structure.
+*
+* OUTPUT PARAMETERS
+*
+* perm - the minimum degree ordering;
+* invp - the inverse of perm.
+*
+* WORKING PARAMETERS
+*
+* deg - the degree vector. deg[i] is negative means node i has been
+* numbered;
+* marker - a marker vector, where marker[i] is negative means node i
+* has been merged with another nodeand thus can be ignored;
+* rchset - vector used for the reachable set;
+* nbrhd - vector used for neighborhood set;
+* qsize - vector used to store the size of indistinguishable
+* supernodes;
+* qlink - vector used to store indistinguishable nodes, i, qlink[i],
+* qlink[qlink[i]], ... are the members of the supernode
+* represented by i.
+*
+* PROGRAM SUBROUTINES
+*
+* qmdrch, qmdqt, qmdupd.
+***********************************************************************/
+
+void genqmd(int *_neqns, int xadj[], int adjncy[], int perm[],
+ int invp[], int deg[], int marker[], int rchset[], int nbrhd[],
+ int qsize[], int qlink[], int *_nofsub)
+{ int inode, ip, irch, j, mindeg, ndeg, nhdsze, node, np, num,
+ nump1, nxnode, rchsze, search, thresh;
+# define neqns (*_neqns)
+# define nofsub (*_nofsub)
+ /* Initialize degree vector and other working variables. */
+ mindeg = neqns;
+ nofsub = 0;
+ for (node = 1; node <= neqns; node++)
+ { perm[node] = node;
+ invp[node] = node;
+ marker[node] = 0;
+ qsize[node] = 1;
+ qlink[node] = 0;
+ ndeg = xadj[node+1] - xadj[node];
+ deg[node] = ndeg;
+ if (ndeg < mindeg) mindeg = ndeg;
+ }
+ num = 0;
+ /* Perform threshold search to get a node of min degree.
+ * Variable search point to where search should start. */
+s200: search = 1;
+ thresh = mindeg;
+ mindeg = neqns;
+s300: nump1 = num + 1;
+ if (nump1 > search) search = nump1;
+ for (j = search; j <= neqns; j++)
+ { node = perm[j];
+ if (marker[node] >= 0)
+ { ndeg = deg[node];
+ if (ndeg <= thresh) goto s500;
+ if (ndeg < mindeg) mindeg = ndeg;
+ }
+ }
+ goto s200;
+ /* Node has minimum degree. Find its reachable sets by calling
+ * qmdrch. */
+s500: search = j;
+ nofsub += deg[node];
+ marker[node] = 1;
+ qmdrch(&node, xadj, adjncy, deg, marker, &rchsze, rchset, &nhdsze,
+ nbrhd);
+ /* Eliminate all nodes indistinguishable from node. They are given
+ * by node, qlink[node], ... . */
+ nxnode = node;
+s600: num++;
+ np = invp[nxnode];
+ ip = perm[num];
+ perm[np] = ip;
+ invp[ip] = np;
+ perm[num] = nxnode;
+ invp[nxnode] = num;
+ deg[nxnode] = -1;
+ nxnode = qlink[nxnode];
+ if (nxnode > 0) goto s600;
+ if (rchsze > 0)
+ { /* Update the degrees of the nodes in the reachable set and
+ * identify indistinguishable nodes. */
+ qmdupd(xadj, adjncy, &rchsze, rchset, deg, qsize, qlink,
+ marker, &rchset[rchsze+1], &nbrhd[nhdsze+1]);
+ /* Reset marker value of nodes in reach set. Update threshold
+ * value for cyclic search. Also call qmdqt to form new
+ * quotient graph. */
+ marker[node] = 0;
+ for (irch = 1; irch <= rchsze; irch++)
+ { inode = rchset[irch];
+ if (marker[inode] >= 0)
+ { marker[inode] = 0;
+ ndeg = deg[inode];
+ if (ndeg < mindeg) mindeg = ndeg;
+ if (ndeg <= thresh)
+ { mindeg = thresh;
+ thresh = ndeg;
+ search = invp[inode];
+ }
+ }
+ }
+ if (nhdsze > 0)
+ qmdqt(&node, xadj, adjncy, marker, &rchsze, rchset, nbrhd);
+ }
+ if (num < neqns) goto s300;
+ return;
+# undef neqns
+# undef nofsub
+}
+
+/***********************************************************************
+* NAME
+*
+* qmdrch - Quotient MD ReaCHable set
+*
+* SYNOPSIS
+*
+* #include "qmd.h"
+* void qmdrch(int *root, int xadj[], int adjncy[], int deg[],
+* int marker[], int *rchsze, int rchset[], int *nhdsze,
+* int nbrhd[]);
+*
+* PURPOSE
+*
+* This subroutine determines the reachable set of a node through a
+* given subset. The adjancy structure is assumed to be stored in a
+* quotient graph format.
+*
+* INPUT PARAMETERS
+*
+* root - the given node not in the subset;
+* (xadj, adjncy) -
+* the adjancy structure pair;
+* deg - the degree vector. deg[i] < 0 means the node belongs to the
+* given subset.
+*
+* OUTPUT PARAMETERS
+*
+* (rchsze, rchset) -
+* the reachable set;
+* (nhdsze, nbrhd) -
+* the neighborhood set.
+*
+* UPDATED PARAMETERS
+*
+* marker - the marker vector for reach and nbrhd sets. > 0 means the
+* node is in reach set. < 0 means the node has been merged
+* with others in the quotient or it is in nbrhd set.
+***********************************************************************/
+
+void qmdrch(int *_root, int xadj[], int adjncy[], int deg[],
+ int marker[], int *_rchsze, int rchset[], int *_nhdsze,
+ int nbrhd[])
+{ int i, istop, istrt, j, jstop, jstrt, nabor, node;
+# define root (*_root)
+# define rchsze (*_rchsze)
+# define nhdsze (*_nhdsze)
+ /* Loop through the neighbors of root in the quotient graph. */
+ nhdsze = 0;
+ rchsze = 0;
+ istrt = xadj[root];
+ istop = xadj[root+1] - 1;
+ if (istop < istrt) return;
+ for (i = istrt; i <= istop; i++)
+ { nabor = adjncy[i];
+ if (nabor == 0) return;
+ if (marker[nabor] == 0)
+ { if (deg[nabor] >= 0)
+ { /* Include nabor into the reachable set. */
+ rchsze++;
+ rchset[rchsze] = nabor;
+ marker[nabor] = 1;
+ goto s600;
+ }
+ /* nabor has been eliminated. Find nodes reachable from
+ * it. */
+ marker[nabor] = -1;
+ nhdsze++;
+ nbrhd[nhdsze] = nabor;
+s300: jstrt = xadj[nabor];
+ jstop = xadj[nabor+1] - 1;
+ for (j = jstrt; j <= jstop; j++)
+ { node = adjncy[j];
+ nabor = - node;
+ if (node < 0) goto s300;
+ if (node == 0) goto s600;
+ if (marker[node] == 0)
+ { rchsze++;
+ rchset[rchsze] = node;
+ marker[node] = 1;
+ }
+ }
+ }
+s600: ;
+ }
+ return;
+# undef root
+# undef rchsze
+# undef nhdsze
+}
+
+/***********************************************************************
+* NAME
+*
+* qmdqt - Quotient MD Quotient graph Transformation
+*
+* SYNOPSIS
+*
+* #include "qmd.h"
+* void qmdqt(int *root, int xadj[], int adjncy[], int marker[],
+* int *rchsze, int rchset[], int nbrhd[]);
+*
+* PURPOSE
+*
+* This subroutine performs the quotient graph transformation after a
+* node has been eliminated.
+*
+* INPUT PARAMETERS
+*
+* root - the node just eliminated. It becomes the representative of
+* the new supernode;
+* (xadj, adjncy) -
+* the adjancy structure;
+* (rchsze, rchset) -
+* the reachable set of root in the old quotient graph;
+* nbrhd - the neighborhood set which will be merged with root to form
+* the new supernode;
+* marker - the marker vector.
+*
+* UPDATED PARAMETERS
+*
+* adjncy - becomes the adjncy of the quotient graph.
+***********************************************************************/
+
+void qmdqt(int *_root, int xadj[], int adjncy[], int marker[],
+ int *_rchsze, int rchset[], int nbrhd[])
+{ int inhd, irch, j, jstop, jstrt, link, nabor, node;
+# define root (*_root)
+# define rchsze (*_rchsze)
+ irch = 0;
+ inhd = 0;
+ node = root;
+s100: jstrt = xadj[node];
+ jstop = xadj[node+1] - 2;
+ if (jstop >= jstrt)
+ { /* Place reach nodes into the adjacent list of node. */
+ for (j = jstrt; j <= jstop; j++)
+ { irch++;
+ adjncy[j] = rchset[irch];
+ if (irch >= rchsze) goto s400;
+ }
+ }
+ /* Link to other space provided by the nbrhd set. */
+ link = adjncy[jstop+1];
+ node = - link;
+ if (link >= 0)
+ { inhd++;
+ node = nbrhd[inhd];
+ adjncy[jstop+1] = - node;
+ }
+ goto s100;
+ /* All reachable nodes have been saved. End the adjacent list.
+ * Add root to the neighborhood list of each node in the reach
+ * set. */
+s400: adjncy[j+1] = 0;
+ for (irch = 1; irch <= rchsze; irch++)
+ { node = rchset[irch];
+ if (marker[node] >= 0)
+ { jstrt = xadj[node];
+ jstop = xadj[node+1] - 1;
+ for (j = jstrt; j <= jstop; j++)
+ { nabor = adjncy[j];
+ if (marker[nabor] < 0)
+ { adjncy[j] = root;
+ goto s600;
+ }
+ }
+ }
+s600: ;
+ }
+ return;
+# undef root
+# undef rchsze
+}
+
+/***********************************************************************
+* NAME
+*
+* qmdupd - Quotient MD UPDate
+*
+* SYNOPSIS
+*
+* #include "qmd.h"
+* void qmdupd(int xadj[], int adjncy[], int *nlist, int list[],
+* int deg[], int qsize[], int qlink[], int marker[], int rchset[],
+* int nbrhd[]);
+*
+* PURPOSE
+*
+* This routine performs degree update for a set of nodes in the minimum
+* degree algorithm.
+*
+* INPUT PARAMETERS
+*
+* (xadj, adjncy) -
+* the adjancy structure;
+* (nlist, list) -
+* the list of nodes whose degree has to be updated.
+*
+* UPDATED PARAMETERS
+*
+* deg - the degree vector;
+* qsize - size of indistinguishable supernodes;
+* qlink - linked list for indistinguishable nodes;
+* marker - used to mark those nodes in reach/nbrhd sets.
+*
+* WORKING PARAMETERS
+*
+* rchset - the reachable set;
+* nbrhd - the neighborhood set.
+*
+* PROGRAM SUBROUTINES
+*
+* qmdmrg.
+***********************************************************************/
+
+void qmdupd(int xadj[], int adjncy[], int *_nlist, int list[],
+ int deg[], int qsize[], int qlink[], int marker[], int rchset[],
+ int nbrhd[])
+{ int deg0, deg1, il, inhd, inode, irch, j, jstop, jstrt, mark,
+ nabor, nhdsze, node, rchsze;
+# define nlist (*_nlist)
+ /* Find all eliminated supernodes that are adjacent to some nodes
+ * in the given list. Put them into (nhdsze, nbrhd). deg0 contains
+ * the number of nodes in the list. */
+ if (nlist <= 0) return;
+ deg0 = 0;
+ nhdsze = 0;
+ for (il = 1; il <= nlist; il++)
+ { node = list[il];
+ deg0 += qsize[node];
+ jstrt = xadj[node];
+ jstop = xadj[node+1] - 1;
+ for (j = jstrt; j <= jstop; j++)
+ { nabor = adjncy[j];
+ if (marker[nabor] == 0 && deg[nabor] < 0)
+ { marker[nabor] = -1;
+ nhdsze++;
+ nbrhd[nhdsze] = nabor;
+ }
+ }
+ }
+ /* Merge indistinguishable nodes in the list by calling the
+ * subroutine qmdmrg. */
+ if (nhdsze > 0)
+ qmdmrg(xadj, adjncy, deg, qsize, qlink, marker, &deg0, &nhdsze,
+ nbrhd, rchset, &nbrhd[nhdsze+1]);
+ /* Find the new degrees of the nodes that have not been merged. */
+ for (il = 1; il <= nlist; il++)
+ { node = list[il];
+ mark = marker[node];
+ if (mark == 0 || mark == 1)
+ { marker[node] = 2;
+ qmdrch(&node, xadj, adjncy, deg, marker, &rchsze, rchset,
+ &nhdsze, nbrhd);
+ deg1 = deg0;
+ if (rchsze > 0)
+ { for (irch = 1; irch <= rchsze; irch++)
+ { inode = rchset[irch];
+ deg1 += qsize[inode];
+ marker[inode] = 0;
+ }
+ }
+ deg[node] = deg1 - 1;
+ if (nhdsze > 0)
+ { for (inhd = 1; inhd <= nhdsze; inhd++)
+ { inode = nbrhd[inhd];
+ marker[inode] = 0;
+ }
+ }
+ }
+ }
+ return;
+# undef nlist
+}
+
+/***********************************************************************
+* NAME
+*
+* qmdmrg - Quotient MD MeRGe
+*
+* SYNOPSIS
+*
+* #include "qmd.h"
+* void qmdmrg(int xadj[], int adjncy[], int deg[], int qsize[],
+* int qlink[], int marker[], int *deg0, int *nhdsze, int nbrhd[],
+* int rchset[], int ovrlp[]);
+*
+* PURPOSE
+*
+* This routine merges indistinguishable nodes in the minimum degree
+* ordering algorithm. It also computes the new degrees of these new
+* supernodes.
+*
+* INPUT PARAMETERS
+*
+* (xadj, adjncy) -
+* the adjancy structure;
+* deg0 - the number of nodes in the given set;
+* (nhdsze, nbrhd) -
+* the set of eliminated supernodes adjacent to some nodes in
+* the set.
+*
+* UPDATED PARAMETERS
+*
+* deg - the degree vector;
+* qsize - size of indistinguishable nodes;
+* qlink - linked list for indistinguishable nodes;
+* marker - the given set is given by those nodes with marker value set
+* to 1. Those nodes with degree updated will have marker value
+* set to 2.
+*
+* WORKING PARAMETERS
+*
+* rchset - the reachable set;
+* ovrlp - temp vector to store the intersection of two reachable sets.
+***********************************************************************/
+
+void qmdmrg(int xadj[], int adjncy[], int deg[], int qsize[],
+ int qlink[], int marker[], int *_deg0, int *_nhdsze, int nbrhd[],
+ int rchset[], int ovrlp[])
+{ int deg1, head, inhd, iov, irch, j, jstop, jstrt, link, lnode,
+ mark, mrgsze, nabor, node, novrlp, rchsze, root;
+# define deg0 (*_deg0)
+# define nhdsze (*_nhdsze)
+ /* Initialization. */
+ if (nhdsze <= 0) return;
+ for (inhd = 1; inhd <= nhdsze; inhd++)
+ { root = nbrhd[inhd];
+ marker[root] = 0;
+ }
+ /* Loop through each eliminated supernode in the set
+ * (nhdsze, nbrhd). */
+ for (inhd = 1; inhd <= nhdsze; inhd++)
+ { root = nbrhd[inhd];
+ marker[root] = -1;
+ rchsze = 0;
+ novrlp = 0;
+ deg1 = 0;
+s200: jstrt = xadj[root];
+ jstop = xadj[root+1] - 1;
+ /* Determine the reachable set and its intersection with the
+ * input reachable set. */
+ for (j = jstrt; j <= jstop; j++)
+ { nabor = adjncy[j];
+ root = - nabor;
+ if (nabor < 0) goto s200;
+ if (nabor == 0) break;
+ mark = marker[nabor];
+ if (mark == 0)
+ { rchsze++;
+ rchset[rchsze] = nabor;
+ deg1 += qsize[nabor];
+ marker[nabor] = 1;
+ }
+ else if (mark == 1)
+ { novrlp++;
+ ovrlp[novrlp] = nabor;
+ marker[nabor] = 2;
+ }
+ }
+ /* From the overlapped set, determine the nodes that can be
+ * merged together. */
+ head = 0;
+ mrgsze = 0;
+ for (iov = 1; iov <= novrlp; iov++)
+ { node = ovrlp[iov];
+ jstrt = xadj[node];
+ jstop = xadj[node+1] - 1;
+ for (j = jstrt; j <= jstop; j++)
+ { nabor = adjncy[j];
+ if (marker[nabor] == 0)
+ { marker[node] = 1;
+ goto s1100;
+ }
+ }
+ /* Node belongs to the new merged supernode. Update the
+ * vectors qlink and qsize. */
+ mrgsze += qsize[node];
+ marker[node] = -1;
+ lnode = node;
+s900: link = qlink[lnode];
+ if (link > 0)
+ { lnode = link;
+ goto s900;
+ }
+ qlink[lnode] = head;
+ head = node;
+s1100: ;
+ }
+ if (head > 0)
+ { qsize[head] = mrgsze;
+ deg[head] = deg0 + deg1 - 1;
+ marker[head] = 2;
+ }
+ /* Reset marker values. */
+ root = nbrhd[inhd];
+ marker[root] = 0;
+ if (rchsze > 0)
+ { for (irch = 1; irch <= rchsze; irch++)
+ { node = rchset[irch];
+ marker[node] = 0;
+ }
+ }
+ }
+ return;
+# undef deg0
+# undef nhdsze
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/qmd.h b/test/monniaux/glpk-4.65/src/misc/qmd.h
new file mode 100644
index 00000000..e55d50f5
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/qmd.h
@@ -0,0 +1,58 @@
+/* qmd.h (quotient minimum degree algorithm) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2001-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#ifndef QMD_H
+#define QMD_H
+
+#define genqmd _glp_genqmd
+void genqmd(int *neqns, int xadj[], int adjncy[], int perm[],
+ int invp[], int deg[], int marker[], int rchset[], int nbrhd[],
+ int qsize[], int qlink[], int *nofsub);
+/* GENeral Quotient Minimum Degree algorithm */
+
+#define qmdrch _glp_qmdrch
+void qmdrch(int *root, int xadj[], int adjncy[], int deg[],
+ int marker[], int *rchsze, int rchset[], int *nhdsze,
+ int nbrhd[]);
+/* Quotient MD ReaCHable set */
+
+#define qmdqt _glp_qmdqt
+void qmdqt(int *root, int xadj[], int adjncy[], int marker[],
+ int *rchsze, int rchset[], int nbrhd[]);
+/* Quotient MD Quotient graph Transformation */
+
+#define qmdupd _glp_qmdupd
+void qmdupd(int xadj[], int adjncy[], int *nlist, int list[],
+ int deg[], int qsize[], int qlink[], int marker[], int rchset[],
+ int nbrhd[]);
+/* Quotient MD UPDate */
+
+#define qmdmrg _glp_qmdmrg
+void qmdmrg(int xadj[], int adjncy[], int deg[], int qsize[],
+ int qlink[], int marker[], int *deg0, int *nhdsze, int nbrhd[],
+ int rchset[], int ovrlp[]);
+/* Quotient MD MeRGe */
+
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/relax4.c b/test/monniaux/glpk-4.65/src/misc/relax4.c
new file mode 100644
index 00000000..f0a47d6d
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/relax4.c
@@ -0,0 +1,2850 @@
+/* relax4.c (relaxation method of Bertsekas and Tseng) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* THIS CODE IS THE RESULT OF TRANSLATION OF THE FORTRAN CODE RELAX4.
+*
+* THE TRANSLATION HAS BEEN DONE WITH THE PERMISSION OF THE AUTHOR OF
+* THE ORIGINAL FORTRAN CODE PROF. DIMITRI P. BERTSEKAS, MASSACHUSETTS
+* INSTITUTE OF TECHNOLOGY, CAMBRIDGE, MASSACHUSETTS, USA.
+*
+* The translation was made by Andrew Makhorin <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include "relax4.h"
+
+/***********************************************************************
+* WARNING
+*
+* A serious bug was *tentatively* fixed in this code (see #if/#endif
+* marked by 'mao').
+*
+* This bug is inherited from the original Fortran version of the
+* RELAX-IV code. Unfortunately, the code is very intricate, so this
+* bug is still under investigation. Thanks to Sylvain Fournier for bug
+* report.
+*
+* RELAX-IV bug details
+* --------------------
+* In the original RELAX-IV code there are four similar fragments in
+* subroutines ascnt1 and ascnt2 like this:
+*
+* C
+* C DECREASE THE PRICES OF THE SCANNED NODES BY DELPRC.
+* C ADJUST FLOW TO MAINTAIN COMPLEMENTARY SLACKNESS WITH
+* C THE PRICES.
+* C
+* NB = 0
+* DO 6 I=1,NSAVE
+* . . .
+* IF (RC(ARC).EQ.0) THEN
+* DELX=DELX+U(ARC)
+* NB = NB + 1
+* PRDCSR(NB) = ARC
+* END IF
+* . . .
+*
+* On some instances the variable NB becomes greater than N (the number
+* of nodes) that leads to indexing error, because the array PRDCSR is
+* declared as array of N elements (more precisely, as array of MAXNN
+* elements, however, NB becomes even much greater than MAXNN).
+***********************************************************************/
+
+#define false 0
+#define true 1
+
+/***********************************************************************
+* NAME
+*
+* RELAX-IV (version of October 1994)
+*
+* PURPOSE
+*
+* This routine implements the relaxation method of Bertsekas and Tseng
+* (see [1], [2]) for linear cost ordinary network flow problems.
+*
+* [1] Bertsekas, D. P., "A Unified Framework for Primal-Dual Methods"
+* Mathematical Programming, Vol. 32, 1985, pp. 125-145.
+* [2] Bertsekas, D. P., and Tseng, P., "Relaxation Methods for
+* Minimum Cost" Operations Research, Vol. 26, 1988, pp. 93-114.
+*
+* The relaxation method is also described in the books:
+*
+* [3] Bertsekas, D. P., "Linear Network Optimization: Algorithms and
+* Codes" MIT Press, 1991.
+* [4] Bertsekas, D. P. and Tsitsiklis, J. N., "Parallel and Distributed
+* Computation: Numerical Methods", Prentice-Hall, 1989.
+* [5] Bertsekas, D. P., "Network Optimization: Continuous and Discrete
+* Models", Athena Scientific, 1998.
+*
+* RELEASE NOTE
+*
+* This version of relaxation code has option for a special crash
+* procedure for the initial price-flow pair. This is recommended for
+* difficult problems where the default initialization results in long
+* running times. crash = 1 corresponds to an auction/shortest path
+* method
+*
+* These initializations are recommended in the absence of any prior
+* information on a favorable initial flow-price vector pair that
+* satisfies complementary slackness.
+*
+* The relaxation portion of the code differs from the code RELAXT-III
+* and other earlier relaxation codes in that it maintains the set of
+* nodes with nonzero deficit in a fifo queue. Like its predecessor
+* RELAXT-III, this code maintains a linked list of balanced (i.e., of
+* zero reduced cost) arcs so to reduce the work in labeling and
+* scanning. Unlike RELAXT-III, it does not use selectively shortest
+* path iterations for initialization.
+*
+* SOURCE
+*
+* The original Fortran code was written by Dimitri P. Bertsekas and
+* Paul Tseng, with a contribution by Jonathan Eckstein in the phase II
+* initialization. The original Fortran routine AUCTION was written by
+* Dimitri P. Bertsekas and is based on the method described in the
+* paper:
+*
+* [6] Bertsekas, D. P., "An Auction/Sequential Shortest Path Algorithm
+* for the Minimum Cost Flow Problem", LIDS Report P-2146, MIT,
+* Nov. 1992.
+*
+* For inquiries about the original Fortran code, please contact:
+*
+* Dimitri P. Bertsekas
+* Laboratory for information and decision systems
+* Massachusetts Institute of Technology
+* Cambridge, MA 02139
+* (617) 253-7267, dimitrib@mit.edu
+*
+* This code is the result of translation of the original Fortran code.
+* The translation was made by Andrew Makhorin <mao@gnu.org>.
+*
+* USER GUIDELINES
+*
+* This routine is in the public domain to be used only for research
+* purposes. It cannot be used as part of a commercial product, or to
+* satisfy in any part commercial delivery requirements to government
+* or industry, without prior agreement with the authors. Users are
+* requested to acknowledge the authorship of the code, and the
+* relaxation method.
+*
+* No modification should be made to this code other than the minimal
+* necessary to make it compatible with specific platforms.
+*
+* INPUT PARAMETERS (see notes 1, 2, 4)
+*
+* n = number of nodes
+* na = number of arcs
+* large = a very large integer to represent infinity
+* (see note 3)
+* repeat = true if initialization is to be skipped
+* (false otherwise)
+* crash = 0 if default initialization is used
+* 1 if auction initialization is used
+* startn[j] = starting node for arc j, j = 1,...,na
+* endn[j] = ending node for arc j, j = 1,...,na
+* fou[i] = first arc out of node i, i = 1,...,n
+* nxtou[j] = next arc out of the starting node of arc j, j = 1,...,na
+* fin[i] = first arc into node i, i = 1,...,n
+* nxtin[j] = next arc into the ending node of arc j, j = 1,...,na
+*
+* UPDATED PARAMETERS (see notes 1, 3, 4)
+*
+* rc[j] = reduced cost of arc j, j = 1,...,na
+* u[j] = capacity of arc j on input
+* and (capacity of arc j) - x[j] on output, j = 1,...,na
+* dfct[i] = demand at node i on input
+* and zero on output, i = 1,...,n
+*
+* OUTPUT PARAMETERS (see notes 1, 3, 4)
+*
+* x[j] = flow on arc j, j = 1,...,na
+* nmultinode = number of multinode relaxation iterations in RELAX4
+* iter = number of relaxation iterations in RELAX4
+* num_augm = number of flow augmentation steps in RELAX4
+* num_ascnt = number of multinode ascent steps in RELAX4
+* nsp = number of auction/shortest path iterations
+*
+* WORKING PARAMETERS (see notes 1, 4, 5)
+*
+* label[1+n], prdcsr[1+n], save[1+na], tfstou[1+n], tnxtou[1+na],
+* tfstin[1+n], tnxtin[1+na], nxtqueue[1+n], scan[1+n], mark[1+n],
+* extend_arc[1+n], sb_level[1+n], sb_arc[1+n]
+*
+* RETURNS
+*
+* 0 = normal return
+* 1,...,8 = problem is found to be infeasible
+*
+* NOTE 1
+*
+* To run in limited memory systems, declare the arrays startn, endn,
+* nxtin, nxtou, fin, fou, label, prdcsr, save, tfstou, tnxtou, tfstin,
+* tnxtin, ddpos, ddneg, nxtqueue as short instead.
+*
+* NOTE 2
+*
+* This routine makes no effort to initialize with a favorable x from
+* amongst those flow vectors that satisfy complementary slackness with
+* the initial reduced cost vector rc. If a favorable x is known, then
+* it can be passed, together with the corresponding arrays u and dfct,
+* to this routine directly. This, however, requires that the capacity
+* tightening portion and the flow initialization portion of this
+* routine (up to line labeled 90) be skipped.
+*
+* NOTE 3
+*
+* All problem data should be less than large in magnitude, and large
+* should be less than, say, 1/4 the largest int of the machine used.
+* This will guard primarily against overflow in uncapacitated problems
+* where the arc capacities are taken finite but very large. Note,
+* however, that as in all codes operating with integers, overflow may
+* occur if some of the problem data takes very large values.
+*
+* NOTE 4
+*
+* [This note being specific to Fortran was removed.-A.M.]
+*
+* NOTE 5
+*
+* ddpos and ddneg are arrays that give the directional derivatives for
+* all positive and negative single-node price changes. These are used
+* only in phase II of the initialization procedure, before the linked
+* list of balanced arcs comes to play. Therefore, to reduce storage,
+* they are equivalence to tfstou and tfstin, which are of the same size
+* (number of nodes) and are used only after the tree comes into use. */
+
+static void ascnt1(struct relax4_csa *csa, int dm, int *delx,
+ int *nlabel, int *feasbl, int *svitch, int nscan, int curnode,
+ int *prevnode);
+
+static void ascnt2(struct relax4_csa *csa, int dm, int *delx,
+ int *nlabel, int *feasbl, int *svitch, int nscan, int curnode,
+ int *prevnode);
+
+static int auction(struct relax4_csa *csa);
+
+int relax4(struct relax4_csa *csa)
+{ /* input parameters */
+ int n = csa->n;
+ int na = csa->na;
+ int large = csa->large;
+ int repeat = csa->repeat;
+ int crash = csa->crash;
+ int *startn = csa->startn;
+ int *endn = csa->endn;
+ int *fou = csa->fou;
+ int *nxtou = csa->nxtou;
+ int *fin = csa->fin;
+ int *nxtin = csa->nxtin;
+ /* updated parameters */
+ int *rc = csa->rc;
+ int *u = csa->u;
+ int *dfct = csa->dfct;
+ /* output parameters */
+ int *x = csa->x;
+# define nmultinode (csa->nmultinode)
+# define iter (csa->iter)
+# define num_augm (csa->num_augm)
+# define num_ascnt (csa->num_ascnt)
+# define nsp (csa->nsp)
+ /* working parameters */
+ int *label = csa->label;
+ int *prdcsr = csa->prdcsr;
+ int *save = csa->save;
+ int *tfstou = csa->tfstou;
+ int *tnxtou = csa->tnxtou;
+ int *tfstin = csa->tfstin;
+ int *tnxtin = csa->tnxtin;
+ int *nxtqueue = csa->nxtqueue;
+ char *scan = csa->scan;
+ char *mark = csa->mark;
+ int *ddpos = tfstou;
+ int *ddneg = tfstin;
+ /* local variables */
+ int arc, augnod, capin, capout, defcit, delprc, delx, dm, dp,
+ dx, feasbl, i, ib, indef, j, lastqueue, maxcap, narc, nb,
+ nlabel, node, node2, node_def, naugnod, nscan, num_passes,
+ numnz, numnz_new, numpasses, nxtarc, nxtbrk, nxtnode, passes,
+ pchange, posit, prevnode, prvarc, quit, rdcost, scapin,
+ scapou, svitch, t, t1, t2, tmparc, tp, trc, ts;
+ /*--------------------------------------------------------------*/
+ /* Initialization phase I */
+ /* In this phase, we reduce the arc capacities by as much as
+ * possible without changing the problem; then we set the initial
+ * flow array x, together with the corresponding arrays u and
+ * dfct. */
+ /* This phase and phase II (from here up to line labeled 90) can
+ * be skipped (by setting repeat to true) if the calling program
+ * places in common user-chosen values for the arc flows, the
+ * residual arc capacities, and the nodal deficits. When this is
+ * done, it is critical that the flow and the reduced cost for
+ * each arc satisfy complementary slackness and the dfct array
+ * properly correspond to the initial arc/flows. */
+ if (repeat)
+ goto L90;
+ for (node = 1; node <= n; node++)
+ { node_def = dfct[node];
+ ddpos[node] = node_def;
+ ddneg[node] = -node_def;
+ maxcap = 0;
+ scapou = 0;
+ for (arc = fou[node]; arc > 0; arc = nxtou[arc])
+ { if (scapou <= large - u[arc])
+ scapou += u[arc];
+ else
+ goto L10;
+ }
+ if (scapou <= large - node_def)
+ capout = scapou + node_def;
+ else
+ goto L10;
+ if (capout < 0)
+ { /* problem is infeasible */
+ /* exogenous flow into node exceeds out capacity */
+ return 1;
+ }
+ scapin = 0;
+ for (arc = fin[node]; arc > 0; arc = nxtin[arc])
+ { if (u[arc] > capout)
+ u[arc] = capout;
+ if (maxcap < u[arc])
+ maxcap = u[arc];
+ if (scapin <= large - u[arc])
+ scapin += u[arc];
+ else
+ goto L10;
+ }
+ if (scapin <= large + node_def)
+ capin = scapin - node_def;
+ else
+ goto L10;
+ if (capin < 0)
+ { /* problem is infeasible */
+ /* exogenous flow out of node exceeds in capacity */
+ return 2;
+ }
+ for (arc = fou[node]; arc > 0; arc = nxtou[arc])
+ { if (u[arc] > capin)
+ u[arc] = capin;
+ }
+L10: ;
+ }
+ /*--------------------------------------------------------------*/
+ /* Initialization phase II */
+ /* In this phase, we initialize the prices and flows by either
+ * calling the routine auction or by performing only single node
+ * (coordinate) relaxation iterations. */
+ if (crash == 1)
+ { nsp = 0;
+ if (auction(csa) != 0)
+ { /* problem is found to be infeasible */
+ return 3;
+ }
+ goto L70;
+ }
+ /* Initialize the arc flows to satisfy complementary slackness
+ * with the prices. u[arc] is the residual capacity of arc, and
+ * x[arc] is the flow. These two always add up to the total
+ * capacity for arc. Also compute the directional derivatives for
+ * each coordinate and compute the actual deficits. */
+ for (arc = 1; arc <= na; arc++)
+ { x[arc] = 0;
+ if (rc[arc] <= 0)
+ { t = u[arc];
+ t1 = startn[arc];
+ t2 = endn[arc];
+ ddpos[t1] += t;
+ ddneg[t2] += t;
+ if (rc[arc] < 0)
+ { x[arc] = t;
+ u[arc] = 0;
+ dfct[t1] += t;
+ dfct[t2] -= t;
+ ddneg[t1] -= t;
+ ddpos[t2] -= t;
+ }
+ }
+ }
+ /* Make 2 or 3 passes through all nodes, performing only single
+ * node relaxation iterations. The number of passes depends on the
+ * density of the network. */
+ if (na > n * 10)
+ numpasses = 2;
+ else
+ numpasses = 3;
+ for (passes = 1; passes <= numpasses; passes++)
+ for (node = 1; node <= n; node++)
+ { if (dfct[node] == 0)
+ continue;
+ if (ddpos[node] <= 0)
+ { /* Compute delprc, the stepsize to the next breakpoint in
+ * the dual cost as the price of node is increased.
+ * [Since the reduced cost of all outgoing (resp., incoming)
+ * arcs will decrease (resp., increase) as the price of node
+ * is increased, the next breakpoint is the minimum of the
+ * positive reduced cost on outgoing arcs and of the
+ * negative reduced cost on incoming arcs.] */
+ delprc = large;
+ for (arc = fou[node]; arc > 0; arc = nxtou[arc])
+ { trc = rc[arc];
+ if ((trc > 0) && (trc < delprc))
+ delprc = trc;
+ }
+ for (arc = fin[node]; arc > 0; arc = nxtin[arc])
+ { trc = rc[arc];
+ if ((trc < 0) && (trc > -delprc))
+ delprc = -trc;
+ }
+ /* If no breakpoint is left and dual ascent is still
+ * possible, the problem is infeasible. */
+ if (delprc >= large)
+ { if (ddpos[node] == 0)
+ continue;
+ return 4;
+ }
+ /* delprc is the stepsize to next breakpoint. Increase
+ * price of node by delprc and compute the stepsize to the
+ * next breakpoint in the dual cost. */
+L53: nxtbrk = large;
+ /* Look at all arcs out of node. */
+ for (arc = fou[node]; arc > 0; arc = nxtou[arc])
+ { trc = rc[arc];
+ if (trc == 0)
+ { t1 = endn[arc];
+ t = u[arc];
+ if (t > 0)
+ { dfct[node] += t;
+ dfct[t1] -= t;
+ x[arc] = t;
+ u[arc] = 0;
+ }
+ else
+ t = x[arc];
+ ddneg[node] -= t;
+ ddpos[t1] -= t;
+ }
+ /* Decrease the reduced costs on all outgoing arcs. */
+ trc -= delprc;
+ if ((trc > 0) && (trc < nxtbrk))
+ nxtbrk = trc;
+ else if (trc == 0)
+ { /* Arc goes from inactive to balanced. Update the rate
+ * of dual ascent at node and at its neighbor. */
+ ddpos[node] += u[arc];
+ ddneg[endn[arc]] += u[arc];
+ }
+ rc[arc] = trc;
+ }
+ /* Look at all arcs into node. */
+ for (arc = fin[node]; arc > 0; arc = nxtin[arc])
+ { trc = rc[arc];
+ if (trc == 0)
+ { t1 = startn[arc];
+ t = x[arc];
+ if (t > 0)
+ { dfct[node] += t;
+ dfct[t1] -= t;
+ u[arc] = t;
+ x[arc] = 0;
+ }
+ else
+ t = u[arc];
+ ddpos[t1] -= t;
+ ddneg[node] -= t;
+ }
+ /* Increase the reduced cost on all incoming arcs. */
+ trc += delprc;
+ if ((trc < 0) && (trc > -nxtbrk))
+ nxtbrk = -trc;
+ else if (trc == 0)
+ { /* Arc goes from active to balanced. Update the rate
+ * of dual ascent at node and at its neighbor. */
+ ddneg[startn[arc]] += x[arc];
+ ddpos[node] += x[arc];
+ }
+ rc[arc] = trc;
+ }
+ /* If price of node can be increased further without
+ * decreasing the dual cost (even the dual cost doesn't
+ * increase), return to increase the price further. */
+ if ((ddpos[node] <= 0) && (nxtbrk < large))
+ { delprc = nxtbrk;
+ goto L53;
+ }
+ }
+ else if (ddneg[node] <= 0)
+ { /* Compute delprc, the stepsize to the next breakpoint in
+ * the dual cost as the price of node is decreased.
+ * [Since the reduced cost of all outgoing (resp., incoming)
+ * arcs will increase (resp., decrease) as the price of node
+ * is decreased, the next breakpoint is the minimum of the
+ * negative reduced cost on outgoing arcs and of the
+ * positive reduced cost on incoming arcs.] */
+ delprc = large;
+ for (arc = fou[node]; arc > 0; arc = nxtou[arc])
+ { trc = rc[arc];
+ if ((trc < 0) && (trc > -delprc))
+ delprc = -trc;
+ }
+ for (arc = fin[node]; arc > 0; arc = nxtin[arc])
+ { trc = rc[arc];
+ if ((trc > 0) && (trc < delprc))
+ delprc = trc;
+ }
+ /* If no breakpoint is left and dual ascent is still
+ * possible, the problem is infeasible. */
+ if (delprc == large)
+ { if (ddneg[node] == 0)
+ continue;
+ return 5;
+ }
+ /* delprc is the stepsize to next breakpoint. Decrease
+ * price of node by delprc and compute the stepsize to the
+ * next breakpoint in the dual cost. */
+L63: nxtbrk = large;
+ /* Look at all arcs out of node. */
+ for (arc = fou[node]; arc > 0; arc = nxtou[arc])
+ { trc = rc[arc];
+ if (trc == 0)
+ { t1 = endn[arc];
+ t = x[arc];
+ if (t > 0)
+ { dfct[node] -= t;
+ dfct[t1] += t;
+ u[arc] = t;
+ x[arc] = 0;
+ }
+ else
+ t = u[arc];
+ ddpos[node] -= t;
+ ddneg[t1] -= t;
+ }
+ /* Increase the reduced cost on all outgoing arcs. */
+ trc += delprc;
+ if ((trc < 0) && (trc > -nxtbrk))
+ nxtbrk = -trc;
+ else if (trc == 0)
+ { /* Arc goes from active to balanced. Update the rate
+ * of dual ascent at node and at its neighbor. */
+ ddneg[node] += x[arc];
+ ddpos[endn[arc]] += x[arc];
+ }
+ rc[arc] = trc;
+ }
+ /* Look at all arcs into node. */
+ for (arc = fin[node]; arc > 0; arc = nxtin[arc])
+ { trc = rc[arc];
+ if (trc == 0)
+ { t1 = startn[arc];
+ t = u[arc];
+ if (t > 0)
+ { dfct[node] -= t;
+ dfct[t1] += t;
+ x[arc] = t;
+ u[arc] = 0;
+ }
+ else
+ t = x[arc];
+ ddneg[t1] -= t;
+ ddpos[node] -= t;
+ }
+ /* Decrease the reduced cost on all incoming arcs. */
+ trc -= delprc;
+ if ((trc > 0) && (trc < nxtbrk))
+ nxtbrk = trc;
+ else if (trc == 0)
+ { /* Arc goes from inactive to balanced. Update the rate
+ * of dual ascent at node and at its neighbor. */
+ ddpos[startn[arc]] += u[arc];
+ ddneg[node] += u[arc];
+ }
+ rc[arc] = trc;
+ }
+ /* If price of node can be decreased further without
+ * decreasing the dual cost (even the dual cost doesn't
+ * increase), return to decrease the price further. */
+ if ((ddneg[node] <= 0) && (nxtbrk < large))
+ { delprc = nxtbrk;
+ goto L63;
+ }
+ }
+ }
+ /*--------------------------------------------------------------*/
+L70: /* Initialize tree data structure. */
+ for (i = 1; i <= n; i++)
+ tfstou[i] = tfstin[i] = 0;
+ for (i = 1; i <= na; i++)
+ { tnxtin[i] = tnxtou[i] = -1;
+ if (rc[i] == 0)
+ { tnxtou[i] = tfstou[startn[i]];
+ tfstou[startn[i]] = i;
+ tnxtin[i] = tfstin[endn[i]];
+ tfstin[endn[i]] = i;
+ }
+ }
+L90: /* Initialize other variables. */
+ feasbl = true;
+ iter = 0;
+ nmultinode = 0;
+ num_augm = 0;
+ num_ascnt = 0;
+ num_passes = 0;
+ numnz = n;
+ numnz_new = 0;
+ svitch = false;
+ for (i = 1; i <= n; i++)
+ mark[i] = scan[i] = false;
+ nlabel = 0;
+ /* RELAX4 uses an adaptive strategy to decide whether to continue
+ * the scanning process after a multinode price change.
+ * The threshold parameter tp and ts that control this strategy
+ * are set in the next two lines. */
+ tp = 10;
+ ts = n / 15;
+ /* Initialize the queue of nodes with nonzero deficit. */
+ for (node = 1; node <= n - 1; node++)
+ nxtqueue[node] = node + 1;
+ nxtqueue[n] = 1;
+ node = lastqueue = n;
+ /*--------------------------------------------------------------*/
+ /* Start the relaxation algorithm. */
+L100: /* Code for advancing the queue of nonzero deficit nodes. */
+ prevnode = node;
+ node = nxtqueue[node];
+ defcit = dfct[node];
+ if (node == lastqueue)
+ { numnz = numnz_new;
+ numnz_new = 0;
+ lastqueue = prevnode;
+ num_passes++;
+ }
+ /* Code for deleting a node from the queue. */
+ if (defcit == 0)
+ { nxtnode = nxtqueue[node];
+ if (node == nxtnode)
+ return 0;
+ else
+ { nxtqueue[prevnode] = nxtnode;
+ nxtqueue[node] = 0;
+ node = nxtnode;
+ goto L100;
+ }
+ }
+ else
+ posit = (defcit > 0);
+ iter++;
+ numnz_new++;
+ if (posit)
+ { /* Attempt a single node iteration from node with positive
+ * deficit. */
+ pchange = false;
+ indef = defcit;
+ delx = 0;
+ nb = 0;
+ /* Check outgoing (probably) balanced arcs from node. */
+ for (arc = tfstou[node]; arc > 0; arc = tnxtou[arc])
+ { if ((rc[arc] == 0) && (x[arc] > 0))
+ { delx += x[arc];
+ nb++;
+ save[nb] = arc;
+ }
+ }
+ /* Check incoming arcs. */
+ for (arc = tfstin[node]; arc > 0; arc = tnxtin[arc])
+ { if ((rc[arc] == 0) && (u[arc] > 0))
+ { delx += u[arc];
+ nb++;
+ save[nb] = -arc;
+ }
+ }
+ /* End of initial node scan. */
+L4018: /* If no price change is possible, exit. */
+ if (delx > defcit)
+ { quit = (defcit < indef);
+ goto L4016;
+ }
+ /* RELAX4 searches along the ascent direction for the best
+ * price by checking the slope of the dual cost at successive
+ * break points. First, we compute the distance to the next
+ * break point. */
+ delprc = large;
+ for (arc = fou[node]; arc > 0; arc = nxtou[arc])
+ { rdcost = rc[arc];
+ if ((rdcost < 0) && (rdcost > -delprc))
+ delprc = -rdcost;
+ }
+ for (arc = fin[node]; arc > 0; arc = nxtin[arc])
+ { rdcost = rc[arc];
+ if ((rdcost > 0) && (rdcost < delprc))
+ delprc = rdcost;
+ }
+ /* Check if problem is infeasible. */
+ if ((delx < defcit) && (delprc == large))
+ { /* The dual cost can be decreased without bound. */
+ return 6;
+ }
+ /* Skip flow adjustment if there is no flow to modify. */
+ if (delx == 0)
+ goto L4014;
+ /* Adjust the flow on the balanced arcs incident to node to
+ * maintain complementary slackness after the price change. */
+ for (j = 1; j <= nb; j++)
+ { arc = save[j];
+ if (arc > 0)
+ { node2 = endn[arc];
+ t1 = x[arc];
+ dfct[node2] += t1;
+ if (nxtqueue[node2] == 0)
+ { nxtqueue[prevnode] = node2;
+ nxtqueue[node2] = node;
+ prevnode = node2;
+ }
+ u[arc] += t1;
+ x[arc] = 0;
+ }
+ else
+ { narc = -arc;
+ node2 = startn[narc];
+ t1 = u[narc];
+ dfct[node2] += t1;
+ if (nxtqueue[node2] == 0)
+ { nxtqueue[prevnode] = node2;
+ nxtqueue[node2] = node;
+ prevnode = node2;
+ }
+ x[narc] += t1;
+ u[narc] = 0;
+ }
+ }
+ defcit -= delx;
+L4014: if (delprc == large)
+ { quit = true;
+ goto L4019;
+ }
+ /* Node corresponds to a dual ascent direction. Decrease the
+ * price of node by delprc and compute the stepsize to the next
+ * breakpoint in the dual cost. */
+ nb = 0;
+ pchange = true;
+ dp = delprc;
+ delprc = large;
+ delx = 0;
+ for (arc = fou[node]; arc > 0; arc = nxtou[arc])
+ { rdcost = rc[arc] + dp;
+ rc[arc] = rdcost;
+ if (rdcost == 0)
+ { nb++;
+ save[nb] = arc;
+ delx += x[arc];
+ }
+ if ((rdcost < 0) && (rdcost > -delprc))
+ delprc = -rdcost;
+ }
+ for (arc = fin[node]; arc > 0; arc = nxtin[arc])
+ { rdcost = rc[arc] - dp;
+ rc[arc] = rdcost;
+ if (rdcost == 0)
+ { nb++;
+ save[nb] = -arc;
+ delx += u[arc];
+ }
+ if ((rdcost > 0) && (rdcost < delprc))
+ delprc = rdcost;
+ }
+ /* Return to check if another price change is possible. */
+ goto L4018;
+L4016: /* Perform flow augmentation at node. */
+ for (j = 1; j <= nb; j++)
+ { arc = save[j];
+ if (arc > 0)
+ { /* arc is an outgoing arc from node. */
+ node2 = endn[arc];
+ t1 = dfct[node2];
+ if (t1 < 0)
+ { /* Decrease the total deficit by decreasing flow of
+ * arc. */
+ quit = true;
+ t2 = x[arc];
+ dx = defcit;
+ if (dx > -t1) dx = -t1;
+ if (dx > t2) dx = t2;
+ defcit -= dx;
+ dfct[node2] = t1 + dx;
+ if (nxtqueue[node2] == 0)
+ { nxtqueue[prevnode] = node2;
+ nxtqueue[node2] = node;
+ prevnode = node2;
+ }
+ x[arc] = t2 - dx;
+ u[arc] += dx;
+ if (defcit == 0)
+ break;
+ }
+ }
+ else
+ { /* -arc is an incoming arc to node. */
+ narc = -arc;
+ node2 = startn[narc];
+ t1 = dfct[node2];
+ if (t1 < 0)
+ { /* Decrease the total deficit by increasing flow of
+ * -arc. */
+ quit = true;
+ t2 = u[narc];
+ dx = defcit;
+ if (dx > -t1) dx = -t1;
+ if (dx > t2) dx = t2;
+ defcit -= dx;
+ dfct[node2] = t1 + dx;
+ if (nxtqueue[node2] == 0)
+ { nxtqueue[prevnode] = node2;
+ nxtqueue[node2] = node;
+ prevnode = node2;
+ }
+ x[narc] += dx;
+ u[narc] = t2 - dx;
+ if (defcit == 0)
+ break;
+ }
+ }
+ }
+L4019: dfct[node] = defcit;
+ /* Reconstruct the linked list of balance arcs incident to this
+ * node. For each adjacent node, we add any newly balanced arcs
+ * to the list, but do not bother removing formerly balanced
+ * ones (they will be removed the next time each adjacent node
+ * is scanned). */
+ if (pchange)
+ { arc = tfstou[node];
+ tfstou[node] = 0;
+ while (arc > 0)
+ { nxtarc = tnxtou[arc];
+ tnxtou[arc] = -1;
+ arc = nxtarc;
+ }
+ arc = tfstin[node];
+ tfstin[node] = 0;
+ while (arc > 0)
+ { nxtarc = tnxtin[arc];
+ tnxtin[arc] = -1;
+ arc = nxtarc;
+ }
+ /* Now add the currently balanced arcs to the list for this
+ * node (which is now empty), and the appropriate adjacent
+ * ones. */
+ for (j = 1; j <= nb; j++)
+ { arc = save[j];
+ if (arc < 0)
+ arc = -arc;
+ if (tnxtou[arc] < 0)
+ { tnxtou[arc] = tfstou[startn[arc]];
+ tfstou[startn[arc]] = arc;
+ }
+ if (tnxtin[arc] < 0)
+ { tnxtin[arc] = tfstin[endn[arc]];
+ tfstin[endn[arc]] = arc;
+ }
+ }
+ }
+ /* End of single node iteration for positive deficit node. */
+ }
+ else
+ { /* Attempt a single node iteration from node with negative
+ * deficit. */
+ pchange = false;
+ defcit = -defcit;
+ indef = defcit;
+ delx = 0;
+ nb = 0;
+ for (arc = tfstin[node]; arc > 0; arc = tnxtin[arc])
+ { if ((rc[arc] == 0) && (x[arc] > 0))
+ { delx += x[arc];
+ nb++;
+ save[nb] = arc;
+ }
+ }
+ for (arc = tfstou[node]; arc > 0; arc = tnxtou[arc])
+ { if ((rc[arc] == 0) && (u[arc] > 0))
+ { delx += u[arc];
+ nb++;
+ save[nb] = -arc;
+ }
+ }
+L4028: if (delx >= defcit)
+ { quit = (defcit < indef);
+ goto L4026;
+ }
+ /* Compute distance to next breakpoint. */
+ delprc = large;
+ for (arc = fin[node]; arc > 0; arc = nxtin[arc])
+ { rdcost = rc[arc];
+ if ((rdcost < 0) && (rdcost > -delprc))
+ delprc = -rdcost;
+ }
+ for (arc = fou[node]; arc > 0; arc = nxtou[arc])
+ { rdcost = rc[arc];
+ if ((rdcost > 0) && (rdcost < delprc))
+ delprc = rdcost;
+ }
+ /* Check if problem is infeasible. */
+ if ((delx < defcit) && (delprc == large))
+ return 7;
+ if (delx == 0)
+ goto L4024;
+ /* Flow augmentation is possible. */
+ for (j = 1; j <= nb; j++)
+ { arc = save[j];
+ if (arc > 0)
+ { node2 = startn[arc];
+ t1 = x[arc];
+ dfct[node2] -= t1;
+ if (nxtqueue[node2] == 0)
+ { nxtqueue[prevnode] = node2;
+ nxtqueue[node2] = node;
+ prevnode = node2;
+ }
+ u[arc] += t1;
+ x[arc] = 0;
+ }
+ else
+ { narc = -arc;
+ node2 = endn[narc];
+ t1 = u[narc];
+ dfct[node2] -= t1;
+ if (nxtqueue[node2] == 0)
+ { nxtqueue[prevnode] = node2;
+ nxtqueue[node2] = node;
+ prevnode = node2;
+ }
+ x[narc] += t1;
+ u[narc] = 0;
+ }
+ }
+ defcit -= delx;
+L4024: if (delprc == large)
+ { quit = true;
+ goto L4029;
+ }
+ /* Price increase at node is possible. */
+ nb = 0;
+ pchange = true;
+ dp = delprc;
+ delprc = large;
+ delx = 0;
+ for (arc = fin[node]; arc > 0; arc = nxtin[arc])
+ { rdcost = rc[arc] + dp;
+ rc[arc] = rdcost;
+ if (rdcost == 0)
+ { nb++;
+ save[nb] = arc;
+ delx += x[arc];
+ }
+ if ((rdcost < 0) && (rdcost > -delprc))
+ delprc = -rdcost;
+ }
+ for (arc = fou[node]; arc > 0; arc = nxtou[arc])
+ { rdcost = rc[arc] - dp;
+ rc[arc] = rdcost;
+ if (rdcost == 0)
+ { nb++;
+ save[nb] = -arc;
+ delx += u[arc];
+ }
+ if ((rdcost > 0) && (rdcost < delprc))
+ delprc = rdcost;
+ }
+ goto L4028;
+L4026: /* Perform flow augmentation at node. */
+ for (j = 1; j <= nb; j++)
+ { arc = save[j];
+ if (arc > 0)
+ { /* arc is an incoming arc to node. */
+ node2 = startn[arc];
+ t1 = dfct[node2];
+ if (t1 > 0)
+ { quit = true;
+ t2 = x[arc];
+ dx = defcit;
+ if (dx > t1) dx = t1;
+ if (dx > t2) dx = t2;
+ defcit -= dx;
+ dfct[node2] = t1 - dx;
+ if (nxtqueue[node2] == 0)
+ { nxtqueue[prevnode] = node2;
+ nxtqueue[node2] = node;
+ prevnode = node2;
+ }
+ x[arc] = t2 - dx;
+ u[arc] += dx;
+ if (defcit == 0)
+ break;
+ }
+ }
+ else
+ { /* -arc is an outgoing arc from node. */
+ narc = -arc;
+ node2 = endn[narc];
+ t1 = dfct[node2];
+ if (t1 > 0)
+ { quit = true;
+ t2 = u[narc];
+ dx = defcit;
+ if (dx > t1) dx = t1;
+ if (dx > t2) dx = t2;
+ defcit -= dx;
+ dfct[node2] = t1 - dx;
+ if (nxtqueue[node2] == 0)
+ { nxtqueue[prevnode] = node2;
+ nxtqueue[node2] = node;
+ prevnode = node2;
+ }
+ x[narc] += dx;
+ u[narc] = t2 - dx;
+ if (defcit == 0)
+ break;
+ }
+ }
+ }
+L4029: dfct[node] = -defcit;
+ /* Reconstruct the list of balanced arcs incident to node. */
+ if (pchange)
+ { arc = tfstou[node];
+ tfstou[node] = 0;
+ while (arc > 0)
+ { nxtarc = tnxtou[arc];
+ tnxtou[arc] = -1;
+ arc = nxtarc;
+ }
+ arc = tfstin[node];
+ tfstin[node] = 0;
+ while (arc > 0)
+ { nxtarc = tnxtin[arc];
+ tnxtin[arc] = -1;
+ arc = nxtarc;
+ }
+ /* Now add the currently balanced arcs to the list for this
+ * node (which is now empty), and the appropriate adjacent
+ * ones. */
+ for (j = 1; j <= nb; j++)
+ { arc = save[j];
+ if (arc <= 0)
+ arc = -arc;
+ if (tnxtou[arc] < 0)
+ { tnxtou[arc] = tfstou[startn[arc]];
+ tfstou[startn[arc]] = arc;
+ }
+ if (tnxtin[arc] < 0)
+ { tnxtin[arc] = tfstin[endn[arc]];
+ tfstin[endn[arc]] = arc;
+ }
+ }
+ }
+ /* End of single node iteration for a negative deficit node. */
+ }
+ if (quit || (num_passes <= 3))
+ goto L100;
+ /* Do a multinode iteration from node. */
+ nmultinode++;
+ /* If number of nonzero deficit nodes is small, continue labeling
+ * until a flow augmentation is done. */
+ svitch = (numnz < tp);
+ /* Unmark nodes labeled earlier. */
+ for (j = 1; j <= nlabel; j++)
+ { node2 = label[j];
+ mark[node2] = scan[node2] = false;
+ }
+ /* Initialize labeling. */
+ nlabel = 1;
+ label[1] = node;
+ mark[node] = true;
+ prdcsr[node] = 0;
+ /* Scan starting node. */
+ scan[node] = true;
+ nscan = 1;
+ dm = dfct[node];
+ delx = 0;
+ for (j = 1; j <= nb; j++)
+ { arc = save[j];
+ if (arc > 0)
+ { if (posit)
+ node2 = endn[arc];
+ else
+ node2 = startn[arc];
+ if (!mark[node2])
+ { nlabel++;
+ label[nlabel] = node2;
+ prdcsr[node2] = arc;
+ mark[node2] = true;
+ delx += x[arc];
+ }
+ }
+ else
+ { narc = -arc;
+ if (posit)
+ node2 = startn[narc];
+ else
+ node2 = endn[narc];
+ if (!mark[node2])
+ { nlabel++;
+ label[nlabel] = node2;
+ prdcsr[node2] = arc;
+ mark[node2] = true;
+ delx += u[narc];
+ }
+ }
+ }
+L4120:/* Start scanning a labeled but unscanned node. */
+ nscan++;
+ /* Check to see if switch needs to be set to true so to continue
+ * scanning even after a price change. */
+ svitch = svitch || ((nscan > ts) && (numnz < ts));
+ /* Scanning will continue until either an overestimate of the
+ * residual capacity across the cut corresponding to the scanned
+ * set of nodes (called delx) exceeds the absolute value of the
+ * total deficit of the scanned nodes (called dm), or else an
+ * augmenting path is found. Arcs that are in the tree but are not
+ * balanced are removed as part of the scanning process. */
+ i = label[nscan];
+ scan[i] = true;
+ naugnod = 0;
+ if (posit)
+ { /* Scanning node i in case of positive deficit. */
+ prvarc = 0;
+ arc = tfstou[i];
+ while (arc > 0)
+ { /* arc is an outgoing arc from node. */
+ if (rc[arc] == 0)
+ { if (x[arc] > 0)
+ { node2 = endn[arc];
+ if (!mark[node2])
+ { /* node2 is not labeled, so add node2 to the
+ labeled set. */
+ prdcsr[node2] = arc;
+ if (dfct[node2] < 0)
+ { naugnod++;
+ save[naugnod] = node2;
+ }
+ nlabel++;
+ label[nlabel] = node2;
+ mark[node2] = true;
+ delx += x[arc];
+ }
+ }
+ prvarc = arc;
+ arc = tnxtou[arc];
+ }
+ else
+ { tmparc = arc;
+ arc = tnxtou[arc];
+ tnxtou[tmparc] = -1;
+ if (prvarc == 0)
+ tfstou[i] = arc;
+ else
+ tnxtou[prvarc] = arc;
+ }
+ }
+ prvarc = 0;
+ arc = tfstin[i];
+ while (arc > 0)
+ { /* arc is an incoming arc into node. */
+ if (rc[arc] == 0)
+ { if (u[arc] > 0)
+ { node2 = startn[arc];
+ if (!mark[node2])
+ { /* node2 is not labeled, so add node2 to the
+ * labeled set. */
+ prdcsr[node2] = -arc;
+ if (dfct[node2] < 0)
+ { naugnod++;
+ save[naugnod] = node2;
+ }
+ nlabel++;
+ label[nlabel] = node2;
+ mark[node2] = true;
+ delx += u[arc];
+ }
+ }
+ prvarc = arc;
+ arc = tnxtin[arc];
+ }
+ else
+ { tmparc = arc;
+ arc = tnxtin[arc];
+ tnxtin[tmparc] = -1;
+ if (prvarc == 0)
+ tfstin[i] = arc;
+ else
+ tnxtin[prvarc] = arc;
+ }
+ }
+ /* Correct the residual capacity of the scanned node cut. */
+ arc = prdcsr[i];
+ if (arc > 0)
+ delx -= x[arc];
+ else
+ delx -= u[-arc];
+ /* End of scanning of node i for positive deficit case. */
+ }
+ else
+ { /* Scanning node i for negative deficit case. */
+ prvarc = 0;
+ arc = tfstin[i];
+ while (arc > 0)
+ { if (rc[arc] == 0)
+ { if (x[arc] > 0)
+ { node2 = startn[arc];
+ if (!mark[node2])
+ { prdcsr[node2] = arc;
+ if (dfct[node2] > 0)
+ { naugnod++;
+ save[naugnod] = node2;
+ }
+ nlabel++;
+ label[nlabel] = node2;
+ mark[node2] = true;
+ delx += x[arc];
+ }
+ }
+ prvarc = arc;
+ arc = tnxtin[arc];
+ }
+ else
+ { tmparc = arc;
+ arc = tnxtin[arc];
+ tnxtin[tmparc] = -1;
+ if (prvarc == 0)
+ tfstin[i] = arc;
+ else
+ tnxtin[prvarc] = arc;
+ }
+ }
+ prvarc = 0;
+ arc = tfstou[i];
+ while (arc > 0)
+ { if (rc[arc] == 0)
+ { if (u[arc] > 0)
+ { node2 = endn[arc];
+ if (!mark[node2])
+ { prdcsr[node2] = -arc;
+ if (dfct[node2] > 0)
+ { naugnod++;
+ save[naugnod] = node2;
+ }
+ nlabel++;
+ label[nlabel] = node2;
+ mark[node2] = true;
+ delx += u[arc];
+ }
+ }
+ prvarc = arc;
+ arc = tnxtou[arc];
+ }
+ else
+ { tmparc = arc;
+ arc = tnxtou[arc];
+ tnxtou[tmparc] = -1;
+ if (prvarc == 0)
+ tfstou[i] = arc;
+ else
+ tnxtou[prvarc] = arc;
+ }
+ }
+ arc = prdcsr[i];
+ if (arc > 0)
+ delx -= x[arc];
+ else
+ delx -= u[-arc];
+ }
+ /* Add deficit of node scanned to dm. */
+ dm += dfct[i];
+ /* Check if the set of scanned nodes correspond to a dual ascent
+ * direction; if yes, perform a price adjustment step, otherwise
+ * continue labeling. */
+ if (nscan < nlabel)
+ { if (svitch)
+ goto L4210;
+ if ((delx >= dm) && (delx >= -dm))
+ goto L4210;
+ }
+ /* Try a price change.
+ * [Note that since delx - abs(dm) is an overestimate of ascent
+ * slope, we may occasionally try a direction that is not an
+ * ascent direction. In this case the ascnt routines return with
+ * quit = false, so we continue labeling nodes.] */
+ if (posit)
+ { ascnt1(csa, dm, &delx, &nlabel, &feasbl, &svitch, nscan, node,
+ &prevnode);
+ num_ascnt++;
+ }
+ else
+ { ascnt2(csa, dm, &delx, &nlabel, &feasbl, &svitch, nscan, node,
+ &prevnode);
+ num_ascnt++;
+ }
+ if (!feasbl)
+ return 8;
+ if (!svitch)
+ goto L100;
+ /* Store those newly labeled nodes to which flow augmentation is
+ * possible. */
+ naugnod = 0;
+ for (j = nscan + 1; j <= nlabel; j++)
+ { node2 = label[j];
+ if (posit && (dfct[node2] < 0))
+ { naugnod++;
+ save[naugnod] = node2;
+ }
+ else if ((!posit) && (dfct[node2] > 0))
+ { naugnod++;
+ save[naugnod] = node2;
+ }
+ }
+L4210:/* Check if flow augmentation is possible. If not, return to scan
+ * another node. */
+ if (naugnod == 0)
+ goto L4120;
+ for (j = 1; j <= naugnod; j++)
+ { num_augm++;
+ augnod = save[j];
+ if (posit)
+ { /* Do the augmentation from node with positive deficit. */
+ dx = -dfct[augnod];
+ ib = augnod;
+ while (ib != node)
+ { arc = prdcsr[ib];
+ if (arc > 0)
+ { if (dx > x[arc]) dx = x[arc];
+ ib = startn[arc];
+ }
+ else
+ { if (dx > u[-arc]) dx = u[-arc];
+ ib = endn[-arc];
+ }
+ }
+ if (dx > dfct[node]) dx = dfct[node];
+ if (dx > 0)
+ { /* Increase (decrease) the flow of all forward (backward)
+ * arcs in the flow augmenting path. Adjust node deficit
+ * accordingly. */
+ if (nxtqueue[augnod] == 0)
+ { nxtqueue[prevnode] = augnod;
+ nxtqueue[augnod] = node;
+ prevnode = augnod;
+ }
+ dfct[augnod] += dx;
+ dfct[node] -= dx;
+ ib = augnod;
+ while (ib != node)
+ { arc = prdcsr[ib];
+ if (arc > 0)
+ { x[arc] -= dx;
+ u[arc] += dx;
+ ib = startn[arc];
+ }
+ else
+ { narc = -arc;
+ x[narc] += dx;
+ u[narc] -= dx;
+ ib = endn[narc];
+ }
+ }
+ }
+ }
+ else
+ { /* Do the augmentation from node with negative deficit. */
+ dx = dfct[augnod];
+ ib = augnod;
+ while (ib != node)
+ { arc = prdcsr[ib];
+ if (arc > 0)
+ { if (dx > x[arc]) dx = x[arc];
+ ib = endn[arc];
+ }
+ else
+ { if (dx > u[-arc]) dx = u[-arc];
+ ib = startn[-arc];
+ }
+ }
+ if (dx > -dfct[node]) dx = -dfct[node];
+ if (dx > 0)
+ { /* Update the flow and deficits. */
+ if (nxtqueue[augnod] == 0)
+ { nxtqueue[prevnode] = augnod;
+ nxtqueue[augnod] = node;
+ prevnode = augnod;
+ }
+ dfct[augnod] -= dx;
+ dfct[node] += dx;
+ ib = augnod;
+ while (ib != node)
+ { arc = prdcsr[ib];
+ if (arc > 0)
+ { x[arc] -= dx;
+ u[arc] += dx;
+ ib = endn[arc];
+ }
+ else
+ { narc = -arc;
+ x[narc] += dx;
+ u[narc] -= dx;
+ ib = startn[narc];
+ }
+ }
+ }
+ }
+ if (dfct[node] == 0)
+ goto L100;
+ if (dfct[augnod] != 0)
+ svitch = false;
+ }
+ /* If node still has nonzero deficit and all newly labeled nodes
+ * have same sign for their deficit as node, we can continue
+ * labeling. In this case, continue labeling only when flow
+ * augmentation is done relatively infrequently. */
+ if (svitch && (iter > 8 * num_augm))
+ goto L4120;
+ /* Return to do another relaxation iteration. */
+ goto L100;
+# undef nmultinode
+# undef iter
+# undef num_augm
+# undef num_ascnt
+# undef nsp
+}
+
+/***********************************************************************
+* NAME
+*
+* relax4_inidat - construct linked lists for network topology
+*
+* PURPOSE
+*
+* This routine constructs two linked lists for the network topology:
+* one list (given by fou, nxtou) for the outgoing arcs of nodes and
+* one list (given by fin, nxtin) for the incoming arcs of nodes. These
+* two lists are required by RELAX4.
+*
+* INPUT PARAMETERS
+*
+* n = number of nodes
+* na = number of arcs
+* startn[j] = starting node for arc j, j = 1,...,na
+* endn[j] = ending node for arc j, j = 1,...,na
+*
+* OUTPUT PARAMETERS
+*
+* fou[i] = first arc out of node i, i = 1,...,n
+* nxtou[j] = next arc out of the starting node of arc j, j = 1,...,na
+* fin[i] = first arc into node i, i = 1,...,n
+* nxtin[j] = next arc into the ending node of arc j, j = 1,...,na
+*
+* WORKING PARAMETERS
+*
+* tempin[1+n], tempou[1+n] */
+
+void relax4_inidat(struct relax4_csa *csa)
+{ /* input parameters */
+ int n = csa->n;
+ int na = csa->na;
+ int *startn = csa->startn;
+ int *endn = csa->endn;
+ /* output parameters */
+ int *fou = csa->fou;
+ int *nxtou = csa->nxtou;
+ int *fin = csa->fin;
+ int *nxtin = csa->nxtin;
+ /* working parameters */
+ int *tempin = csa->label;
+ int *tempou = csa->prdcsr;
+ /* local variables */
+ int i, i1, i2;
+ for (i = 1; i <= n; i++)
+ { fin[i] = fou[i] = 0;
+ tempin[i] = tempou[i] = 0;
+ }
+ for (i = 1; i <= na; i++)
+ { nxtin[i] = nxtou[i] = 0;
+ i1 = startn[i];
+ i2 = endn[i];
+ if (fou[i1] != 0)
+ nxtou[tempou[i1]] = i;
+ else
+ fou[i1] = i;
+ tempou[i1] = i;
+ if (fin[i2] != 0)
+ nxtin[tempin[i2]] = i;
+ else
+ fin[i2] = i;
+ tempin[i2] = i;
+ }
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* ascnt1 - multi-node price adjustment for positive deficit case
+*
+* PURPOSE
+*
+* This subroutine performs the multi-node price adjustment step for
+* the case where the scanned nodes have positive deficit. It first
+* checks if decreasing the price of the scanned nodes increases the
+* dual cost. If yes, then it decreases the price of all scanned nodes.
+* There are two possibilities for price decrease: if switch = true,
+* then the set of scanned nodes corresponds to an elementary direction
+* of maximal rate of ascent, in which case the price of all scanned
+* nodes are decreased until the next breakpoint in the dual cost is
+* encountered. At this point, some arc becomes balanced and more
+* node(s) are added to the labeled set and the subroutine is exited.
+* If switch = false, then the price of all scanned nodes are decreased
+* until the rate of ascent becomes negative (this corresponds to the
+* price adjustment step in which both the line search and the
+* degenerate ascent iteration are implemented).
+*
+* INPUT PARAMETERS
+*
+* dm = total deficit of scanned nodes
+* switch = true if labeling is to continue after price change
+* nscan = number of scanned nodes
+* curnode = most recently scanned node
+* n = number of nodes
+* na = number of arcs
+* large = a very large integer to represent infinity (see note 3)
+* startn[i] = starting node for the i-th arc, i = 1,...,na
+* endn[i] = ending node for the i-th arc, i = 1,...,na
+* fou[i] = first arc leaving i-th node, i = 1,...,n
+* nxtou[i] = next arc leaving the starting node of j-th arc,
+* i = 1,...,na
+* fin[i] = first arc entering i-th node, i = 1,...,n
+* nxtin[i] = next arc entering the ending node of j-th arc,
+* i = 1,...,na
+*
+* UPDATED PARAMETERS
+*
+* delx = a lower estimate of the total flow on balanced arcs in
+* the scanned-nodes cut
+* nlabel = number of labeled nodes
+* feasbl = false if problem is found to be infeasible
+* prevnode = the node before curnode in queue
+* rc[j] = reduced cost of arc j, j = 1,...,na
+* u[j] = residual capacity of arc j, j = 1,...,na
+* x[j] = flow on arc j, j = 1,...,na
+* dfct[i] = deficit at node i, i = 1,...,n
+* label[k] = k-th node labeled, k = 1,...,nlabel
+* prdcsr[i] = predecessor of node i in tree of labeled nodes (0 if i
+* is unlabeled), i = 1,...,n
+* tfstou[i] = first balanced arc out of node i, i = 1,...,n
+* tnxtou[j] = next balanced arc out of the starting node of arc j,
+* j = 1,...,na
+* tfstin[i] = first balanced arc into node i, i = 1,...,n
+* tnxtin[j] = next balanced arc into the ending node of arc j,
+* j = 1,...,na
+* nxtqueue[i] = node following node i in the fifo queue (0 if node is
+* not in the queue), i = 1,...,n
+* scan[i] = true if node i is scanned, i = 1,...,n
+* mark[i] = true if node i is labeled, i = 1,...,n
+*
+* WORKING PARAMETERS
+*
+* save[1+na] */
+
+static void ascnt1(struct relax4_csa *csa, int dm, int *delx,
+ int *nlabel, int *feasbl, int *svitch, int nscan, int curnode,
+ int *prevnode)
+{ /* input parameters */
+ int n = csa->n;
+ /* int na = csa->na; */
+ int large = csa->large;
+ int *startn = csa->startn;
+ int *endn = csa->endn;
+ int *fou = csa->fou;
+ int *nxtou = csa->nxtou;
+ int *fin = csa->fin;
+ int *nxtin = csa->nxtin;
+ /* updated parameters */
+# define delx (*delx)
+# define nlabel (*nlabel)
+# define feasbl (*feasbl)
+# define svitch (*svitch)
+# define prevnode (*prevnode)
+ int *rc = csa->rc;
+ int *u = csa->u;
+ int *x = csa->x;
+ int *dfct = csa->dfct;
+ int *label = csa->label;
+ int *prdcsr = csa->prdcsr;
+ int *tfstou = csa->tfstou;
+ int *tnxtou = csa->tnxtou;
+ int *tfstin = csa->tfstin;
+ int *tnxtin = csa->tnxtin;
+ int *nxtqueue = csa->nxtqueue;
+ char *scan = csa->scan;
+ char *mark = csa->mark;
+ int *save = csa->save;
+ /* local variables */
+ int arc, delprc, dlx, i, j, nb, node, node2, nsave, rdcost, t1,
+ t2, t3;
+ /* Store the arcs between the set of scanned nodes and its
+ * complement in save and compute delprc, the stepsize to the next
+ * breakpoint in the dual cost in the direction of decreasing
+ * prices of the scanned nodes.
+ * [The arcs are stored into save by looking at the arcs incident
+ * to either the set of scanned nodes or its complement, depending
+ * on whether nscan > n/2 or not. This improves the efficiency of
+ * storing.] */
+ delprc = large;
+ dlx = 0;
+ nsave = 0;
+ if (nscan <= n / 2)
+ { for (i = 1; i <= nscan; i++)
+ { node = label[i];
+ for (arc = fou[node]; arc > 0; arc = nxtou[arc])
+ { /* arc points from scanned node to an unscanned node. */
+ node2 = endn[arc];
+ if (!scan[node2])
+ { nsave++;
+ save[nsave] = arc;
+ rdcost = rc[arc];
+ if ((rdcost == 0) && (prdcsr[node2] != arc))
+ dlx += x[arc];
+ if ((rdcost < 0) && (rdcost > -delprc))
+ delprc = -rdcost;
+ }
+ }
+ for (arc = fin[node]; arc > 0; arc = nxtin[arc])
+ { /* arc points from unscanned node to scanned node. */
+ node2 = startn[arc];
+ if (!scan[node2])
+ { nsave++;
+ save[nsave] = -arc;
+ rdcost = rc[arc];
+ if ((rdcost == 0) && (prdcsr[node2] != -arc))
+ dlx += u[arc];
+ if ((rdcost > 0) && (rdcost < delprc))
+ delprc = rdcost;
+ }
+ }
+ }
+ }
+ else
+ { for (node = 1; node <= n; node++)
+ { if (scan[node])
+ continue;
+ for (arc = fin[node]; arc > 0; arc = nxtin[arc])
+ { node2 = startn[arc];
+ if (scan[node2])
+ { nsave++;
+ save[nsave] = arc;
+ rdcost = rc[arc];
+ if ((rdcost == 0) && (prdcsr[node] != arc))
+ dlx += x[arc];
+ if ((rdcost < 0) && (rdcost > -delprc))
+ delprc = -rdcost;
+ }
+ }
+ for (arc = fou[node]; arc > 0; arc = nxtou[arc])
+ { node2 = endn[arc];
+ if (scan[node2])
+ { nsave++;
+ save[nsave] = -arc;
+ rdcost = rc[arc];
+ if ((rdcost == 0) && (prdcsr[node] != -arc))
+ dlx += u[arc];
+ if ((rdcost > 0) && (rdcost < delprc))
+ delprc = rdcost;
+ }
+ }
+ }
+ }
+ /* Check if the set of scanned nodes truly corresponds to a dual
+ * ascent direction. [Here delx + dlx is the exact sum of the flow
+ * on arcs from the scanned set to the unscanned set plus the
+ * (capacity - flow) on arcs from the unscanned set to the scanned
+ * set.] If this were not the case, set switch to true and exit
+ * subroutine. */
+ if ((!svitch) && (delx + dlx >= dm))
+ { svitch = true;
+ return;
+ }
+ delx += dlx;
+L4: /* Check that the problem is feasible. */
+ if (delprc == large)
+ { /* We can increase the dual cost without bound, so the primal
+ * problem is infeasible. */
+ feasbl = false;
+ return;
+ }
+ /* Decrease the prices of the scanned nodes, add more nodes to
+ * the labeled set and check if a newly labeled node has negative
+ * deficit. */
+ if (svitch)
+ { for (i = 1; i <= nsave; i++)
+ { arc = save[i];
+ if (arc > 0)
+ { rc[arc] += delprc;
+ if (rc[arc] == 0)
+ { node2 = endn[arc];
+ if (tnxtou[arc] < 0)
+ { tnxtou[arc] = tfstou[startn[arc]];
+ tfstou[startn[arc]] = arc;
+ }
+ if (tnxtin[arc] < 0)
+ { tnxtin[arc] = tfstin[node2];
+ tfstin[node2] = arc;
+ }
+ if (!mark[node2])
+ { prdcsr[node2] = arc;
+ nlabel++;
+ label[nlabel] = node2;
+ mark[node2] = true;
+ }
+ }
+ }
+ else
+ { arc = -arc;
+ rc[arc] -= delprc;
+ if (rc[arc] == 0)
+ { node2 = startn[arc];
+ if (tnxtou[arc] < 0)
+ { tnxtou[arc] = tfstou[node2];
+ tfstou[node2] = arc;
+ }
+ if (tnxtin[arc] < 0)
+ { tnxtin[arc] = tfstin[endn[arc]];
+ tfstin[endn[arc]] = arc;
+ }
+ if (!mark[node2])
+ { prdcsr[node2] = -arc;
+ nlabel++;
+ label[nlabel] = node2;
+ mark[node2] = true;
+ }
+ }
+ }
+ }
+ return;
+ }
+ else
+ { /* Decrease the prices of the scanned nodes by delprc. Adjust
+ * flow to maintain complementary slackness with the prices. */
+ nb = 0;
+ for (i = 1; i <= nsave; i++)
+ { arc = save[i];
+ if (arc > 0)
+ { t1 = rc[arc];
+ if (t1 == 0)
+ { t2 = x[arc];
+ t3 = startn[arc];
+ dfct[t3] -= t2;
+ if (nxtqueue[t3] == 0)
+ { nxtqueue[prevnode] = t3;
+ nxtqueue[t3] = curnode;
+ prevnode = t3;
+ }
+ t3 = endn[arc];
+ dfct[t3] += t2;
+ if (nxtqueue[t3] == 0)
+ { nxtqueue[prevnode] = t3;
+ nxtqueue[t3] = curnode;
+ prevnode = t3;
+ }
+ u[arc] += t2;
+ x[arc] = 0;
+ }
+ rc[arc] = t1 + delprc;
+#if 0 /* by mao; 26/IV-2013 */
+ if (rc[arc] == 0)
+#else
+ if (rc[arc] == 0 && nb < n)
+#endif
+ { delx += x[arc];
+ nb++;
+ prdcsr[nb] = arc;
+ }
+ }
+ else
+ { arc = -arc;
+ t1 = rc[arc];
+ if (t1 == 0)
+ { t2 = u[arc];
+ t3 = startn[arc];
+ dfct[t3] += t2;
+ if (nxtqueue[t3] == 0)
+ { nxtqueue[prevnode] = t3;
+ nxtqueue[t3] = curnode;
+ prevnode = t3;
+ }
+ t3 = endn[arc];
+ dfct[t3] -= t2;
+ if (nxtqueue[t3] == 0)
+ { nxtqueue[prevnode] = t3;
+ nxtqueue[t3] = curnode;
+ prevnode = t3;
+ }
+ x[arc] += t2;
+ u[arc] = 0;
+ }
+ rc[arc] = t1 - delprc;
+#if 0 /* by mao; 26/IV-2013 */
+ if (rc[arc] == 0)
+#else
+ if (rc[arc] == 0 && nb < n)
+#endif
+ { delx += u[arc];
+ nb++;
+ prdcsr[nb] = arc;
+ }
+ }
+ }
+ }
+ if (delx <= dm)
+ { /* The set of scanned nodes still corresponds to a dual
+ * (possibly degenerate) ascent direction. Compute the stepsize
+ * delprc to the next breakpoint in the dual cost. */
+ delprc = large;
+ for (i = 1; i <= nsave; i++)
+ { arc = save[i];
+ if (arc > 0)
+ { rdcost = rc[arc];
+ if ((rdcost < 0) && (rdcost > -delprc))
+ delprc = -rdcost;
+ }
+ else
+ { arc = -arc;
+ rdcost = rc[arc];
+ if ((rdcost > 0) && (rdcost < delprc))
+ delprc = rdcost;
+ }
+ }
+ if ((delprc != large) || (delx < dm))
+ goto L4;
+ }
+ /* Add new balanced arcs to the superset of balanced arcs. */
+ for (i = 1; i <= nb; i++)
+ { arc = prdcsr[i];
+ if (tnxtin[arc] == -1)
+ { j = endn[arc];
+ tnxtin[arc] = tfstin[j];
+ tfstin[j] = arc;
+ }
+ if (tnxtou[arc] == -1)
+ { j = startn[arc];
+ tnxtou[arc] = tfstou[j];
+ tfstou[j] = arc;
+ }
+ }
+ return;
+# undef delx
+# undef nlabel
+# undef feasbl
+# undef svitch
+# undef prevnode
+}
+
+/***********************************************************************
+* NAME
+*
+* ascnt2 - multi-node price adjustment for negative deficit case
+*
+* PURPOSE
+*
+* This routine is analogous to ascnt1 but for the case where the
+* scanned nodes have negative deficit. */
+
+static void ascnt2(struct relax4_csa *csa, int dm, int *delx,
+ int *nlabel, int *feasbl, int *svitch, int nscan, int curnode,
+ int *prevnode)
+{ /* input parameters */
+ int n = csa->n;
+ /* int na = csa->na; */
+ int large = csa->large;
+ int *startn = csa->startn;
+ int *endn = csa->endn;
+ int *fou = csa->fou;
+ int *nxtou = csa->nxtou;
+ int *fin = csa->fin;
+ int *nxtin = csa->nxtin;
+ /* updated parameters */
+# define delx (*delx)
+# define nlabel (*nlabel)
+# define feasbl (*feasbl)
+# define svitch (*svitch)
+# define prevnode (*prevnode)
+ int *rc = csa->rc;
+ int *u = csa->u;
+ int *x = csa->x;
+ int *dfct = csa->dfct;
+ int *label = csa->label;
+ int *prdcsr = csa->prdcsr;
+ int *tfstou = csa->tfstou;
+ int *tnxtou = csa->tnxtou;
+ int *tfstin = csa->tfstin;
+ int *tnxtin = csa->tnxtin;
+ int *nxtqueue = csa->nxtqueue;
+ char *scan = csa->scan;
+ char *mark = csa->mark;
+ int *save = csa->save;
+ /* local variables */
+ int arc, delprc, dlx, i, j, nb, node, node2, nsave, rdcost, t1,
+ t2, t3;
+ /* Store the arcs between the set of scanned nodes and its
+ * complement in save and compute delprc, the stepsize to the next
+ * breakpoint in the dual cost in the direction of increasing
+ * prices of the scanned nodes. */
+ delprc = large;
+ dlx = 0;
+ nsave = 0;
+ if (nscan <= n / 2)
+ { for (i = 1; i <= nscan; i++)
+ { node = label[i];
+ for (arc = fin[node]; arc > 0; arc = nxtin[arc])
+ { node2 = startn[arc];
+ if (!scan[node2])
+ { nsave++;
+ save[nsave] = arc;
+ rdcost = rc[arc];
+ if ((rdcost == 0) && (prdcsr[node2] != arc))
+ dlx += x[arc];
+ if ((rdcost < 0) && (rdcost > -delprc))
+ delprc = -rdcost;
+ }
+ }
+ for (arc = fou[node]; arc > 0; arc = nxtou[arc])
+ { node2 = endn[arc];
+ if (!scan[node2])
+ { nsave++;
+ save[nsave] = -arc;
+ rdcost = rc[arc];
+ if ((rdcost == 0) && (prdcsr[node2] != -arc))
+ dlx += u[arc];
+ if ((rdcost > 0) && (rdcost < delprc))
+ delprc = rdcost;
+ }
+ }
+ }
+ }
+ else
+ { for (node = 1; node <= n; node++)
+ { if (scan[node])
+ continue;
+ for (arc = fou[node]; arc > 0; arc = nxtou[arc])
+ { node2 = endn[arc];
+ if (scan[node2])
+ { nsave++;
+ save[nsave] = arc;
+ rdcost = rc[arc];
+ if ((rdcost == 0) && (prdcsr[node] != arc))
+ dlx += x[arc];
+ if ((rdcost < 0) && (rdcost > -delprc))
+ delprc = -rdcost;
+ }
+ }
+ for (arc = fin[node]; arc > 0; arc = nxtin[arc])
+ { node2 = startn[arc];
+ if (scan[node2])
+ { nsave++;
+ save[nsave] = -arc;
+ rdcost = rc[arc];
+ if ((rdcost == 0) && (prdcsr[node] != -arc))
+ dlx += u[arc];
+ if ((rdcost > 0) && (rdcost < delprc))
+ delprc = rdcost;
+ }
+ }
+ }
+ }
+ if ((!svitch) && (delx + dlx >= -dm))
+ { svitch = true;
+ return;
+ }
+ delx += dlx;
+ /* Check that the problem is feasible. */
+L4: if (delprc == large)
+ { feasbl = false;
+ return;
+ }
+ /* Increase the prices of the scanned nodes, add more nodes to
+ * the labeled set and check if a newly labeled node has positive
+ * deficit. */
+ if (svitch)
+ { for (i = 1; i <= nsave; i++)
+ { arc = save[i];
+ if (arc > 0)
+ { rc[arc] += delprc;
+ if (rc[arc] == 0)
+ { node2 = startn[arc];
+ if (tnxtou[arc] < 0)
+ { tnxtou[arc] = tfstou[node2];
+ tfstou[node2] = arc;
+ }
+ if (tnxtin[arc] < 0)
+ { tnxtin[arc] = tfstin[endn[arc]];
+ tfstin[endn[arc]] = arc;
+ }
+ if (!mark[node2])
+ { prdcsr[node2] = arc;
+ nlabel++;
+ label[nlabel] = node2;
+ mark[node2] = true;
+ }
+ }
+ }
+ else
+ { arc = -arc;
+ rc[arc] -= delprc;
+ if (rc[arc] == 0)
+ { node2 = endn[arc];
+ if (tnxtou[arc] < 0)
+ { tnxtou[arc] = tfstou[startn[arc]];
+ tfstou[startn[arc]] = arc;
+ }
+ if (tnxtin[arc] < 0)
+ { tnxtin[arc] = tfstin[node2];
+ tfstin[node2] = arc;
+ }
+ if (!mark[node2])
+ { prdcsr[node2] = -arc;
+ nlabel++;
+ label[nlabel] = node2;
+ mark[node2] = true;
+ }
+ }
+ }
+ }
+ return;
+ }
+ else
+ { nb = 0;
+ for (i = 1; i <= nsave; i++)
+ { arc = save[i];
+ if (arc > 0)
+ { t1 = rc[arc];
+ if (t1 == 0)
+ { t2 = x[arc];
+ t3 = startn[arc];
+ dfct[t3] -= t2;
+ if (nxtqueue[t3] == 0)
+ { nxtqueue[prevnode] = t3;
+ nxtqueue[t3] = curnode;
+ prevnode = t3;
+ }
+ t3 = endn[arc];
+ dfct[t3] += t2;
+ if (nxtqueue[t3] == 0)
+ { nxtqueue[prevnode] = t3;
+ nxtqueue[t3] = curnode;
+ prevnode = t3;
+ }
+ u[arc] += t2;
+ x[arc] = 0;
+ }
+ rc[arc] = t1 + delprc;
+#if 0 /* by mao; 26/IV-2013 */
+ if (rc[arc] == 0)
+#else
+ if (rc[arc] == 0 && nb < n)
+#endif
+ { delx += x[arc];
+ nb++;
+ prdcsr[nb] = arc;
+ }
+ }
+ else
+ { arc = -arc;
+ t1 = rc[arc];
+ if (t1 == 0)
+ { t2 = u[arc];
+ t3 = startn[arc];
+ dfct[t3] += t2;
+ if (nxtqueue[t3] == 0)
+ { nxtqueue[prevnode] = t3;
+ nxtqueue[t3] = curnode;
+ prevnode = t3;
+ }
+ t3 = endn[arc];
+ dfct[t3] -= t2;
+ if (nxtqueue[t3] == 0)
+ { nxtqueue[prevnode] = t3;
+ nxtqueue[t3] = curnode;
+ prevnode = t3;
+ }
+ x[arc] += t2;
+ u[arc] = 0;
+ }
+ rc[arc] = t1 - delprc;
+#if 0 /* by mao; 26/IV-2013 */
+ if (rc[arc] == 0)
+#else
+ if (rc[arc] == 0 && nb < n)
+#endif
+ { delx += u[arc];
+ nb++;
+ prdcsr[nb] = arc;
+ }
+ }
+ }
+ }
+ if (delx <= -dm)
+ { delprc = large;
+ for (i = 1; i <= nsave; i++)
+ { arc = save[i];
+ if (arc > 0)
+ { rdcost = rc[arc];
+ if ((rdcost < 0) && (rdcost > -delprc))
+ delprc = -rdcost;
+ }
+ else
+ { arc = -arc;
+ rdcost = rc[arc];
+ if ((rdcost > 0) && (rdcost < delprc))
+ delprc = rdcost;
+ }
+ }
+ if ((delprc != large) || (delx < -dm))
+ goto L4;
+ }
+ /* Add new balanced arcs to the superset of balanced arcs. */
+ for (i = 1; i <= nb; i++)
+ { arc = prdcsr[i];
+ if (tnxtin[arc] == -1)
+ { j = endn[arc];
+ tnxtin[arc] = tfstin[j];
+ tfstin[j] = arc;
+ }
+ if (tnxtou[arc] == -1)
+ { j = startn[arc];
+ tnxtou[arc] = tfstou[j];
+ tfstou[j] = arc;
+ }
+ }
+ return;
+# undef delx
+# undef nlabel
+# undef feasbl
+# undef svitch
+# undef prevnode
+}
+
+/***********************************************************************
+* NAME
+*
+* auction - compute good initial flow and prices
+*
+* PURPOSE
+*
+* This subroutine uses a version of the auction algorithm for min
+* cost network flow to compute a good initial flow and prices for the
+* problem.
+*
+* INPUT PARAMETERS
+*
+* n = number of nodes
+* na = number of arcs
+* large = a very large integer to represent infinity (see note 3)
+* startn[i] = starting node for the i-th arc, i = 1,...,na
+* endn[i] = ending node for the i-th arc, i = 1,...,na
+* fou[i] = first arc leaving i-th node, i = 1,...,n
+* nxtou[i] = next arc leaving the starting node of j-th arc,
+* i = 1,...,na
+* fin[i] = first arc entering i-th node, i = 1,...,n
+* nxtin[i] = next arc entering the ending node of j-th arc,
+* i = 1,...,na
+*
+* UPDATED PARAMETERS
+*
+* rc[j] = reduced cost of arc j, j = 1,...,na
+* u[j] = residual capacity of arc j, j = 1,...,na
+* x[j] = flow on arc j, j = 1,...,na
+* dfct[i] = deficit at node i, i = 1,...,n
+*
+* OUTPUT PARAMETERS
+*
+* nsp = number of auction/shortest path iterations
+*
+* WORKING PARAMETERS
+*
+* p[1+n], prdcsr[1+n], save[1+na], fpushf[1+n], nxtpushf[1+na],
+* fpushb[1+n], nxtpushb[1+na], nxtqueue[1+n], extend_arc[1+n],
+* sb_level[1+n], sb_arc[1+n], path_id[1+n]
+*
+* RETURNS
+*
+* 0 = normal return
+* 1 = problem is found to be infeasible */
+
+static int auction(struct relax4_csa *csa)
+{ /* input parameters */
+ int n = csa->n;
+ int na = csa->na;
+ int large = csa->large;
+ int *startn = csa->startn;
+ int *endn = csa->endn;
+ int *fou = csa->fou;
+ int *nxtou = csa->nxtou;
+ int *fin = csa->fin;
+ int *nxtin = csa->nxtin;
+ /* updated parameters */
+# define crash (csa->crash)
+ int *rc = csa->rc;
+ int *u = csa->u;
+ int *x = csa->x;
+ int *dfct = csa->dfct;
+ /* output parameters */
+# define nsp (csa->nsp)
+ /* working parameters */
+ int *p = csa->label;
+ int *prdcsr = csa->prdcsr;
+ int *save = csa->save;
+ int *fpushf = csa->tfstou;
+ int *nxtpushf = csa->tnxtou;
+ int *fpushb = csa->tfstin;
+ int *nxtpushb = csa->tnxtin;
+ int *nxtqueue = csa->nxtqueue;
+ int *extend_arc = csa->extend_arc;
+ int *sb_level = csa->sb_level;
+ int *sb_arc = csa->sb_arc;
+ char *path_id = csa->mark;
+ /* local variables */
+ int arc, bstlevel, end, eps, extarc, factor, flow, i, incr,
+ last, lastqueue, maxcost, mincost, nas, naug, new_level, node,
+ nolist, num_passes, nxtnode, pass, pend, pr_term, prd,
+ prevarc, prevlevel, prevnode, pstart, pterm, rdcost, red_cost,
+ resid, root, secarc, seclevel, start, term, thresh_dfct;
+ /* start initialization using auction */
+ naug = 0;
+ pass = 0;
+ thresh_dfct = 0;
+ /* factor determines by how much epsilon is reduced at each
+ * minimization */
+ factor = 3;
+ /* num_passes determines how many auction scaling phases are
+ * performed */
+ num_passes = 1;
+ /* set arc flows to satisfy cs and calculate maxcost and
+ * mincost */
+ maxcost = -large;
+ mincost = large;
+ for (arc = 1; arc <= na; arc++)
+ { start = startn[arc];
+ end = endn[arc];
+ rdcost = rc[arc];
+ if (maxcost < rdcost)
+ maxcost = rdcost;
+ if (mincost > rdcost)
+ mincost = rdcost;
+ if (rdcost < 0)
+ { dfct[start] += u[arc];
+ dfct[end] -= u[arc];
+ x[arc] = u[arc];
+ u[arc] = 0;
+ }
+ else
+ x[arc] = 0;
+ }
+ /* set initial epsilon */
+ if ((maxcost - mincost) >= 8)
+ eps = (maxcost - mincost) / 8;
+ else
+ eps = 1;
+ /* set initial prices to zero */
+ for (node = 1; node <= n; node++)
+ p[node] = 0;
+ /* Initialization using auction/shortest paths. */
+L100: /* Start of the first scaling phase. */
+ pass++;
+ if ((pass == num_passes) || (eps == 1))
+ crash = 0;
+ nolist = 0;
+ /* construct list of positive surplus nodes and queue of negative
+ * surplus nodes */
+ for (node = 1; node <= n; node++)
+ { prdcsr[node] = 0;
+ path_id[node] = false;
+ extend_arc[node] = 0;
+ sb_level[node] = -large;
+ nxtqueue[node] = node + 1;
+ if (dfct[node] > 0)
+ { nolist++;
+ save[nolist] = node;
+ }
+ }
+ nxtqueue[n] = 1;
+ root = 1;
+ prevnode = lastqueue = n;
+ /* initialization with down iterations for negative surplus
+ * nodes */
+ for (i = 1; i <= nolist; i++)
+ { node = save[i];
+ nsp++;
+ /* build the list of arcs w/ room for pushing flow and find
+ * proper price for down iteration */
+ bstlevel = -large;
+ fpushf[node] = 0;
+ for (arc = fou[node]; arc > 0; arc = nxtou[arc])
+ { if (u[arc] > 0)
+ { if (fpushf[node] == 0)
+ { fpushf[node] = arc;
+ nxtpushf[arc] = 0;
+ last = arc;
+ }
+ else
+ { nxtpushf[last] = arc;
+ nxtpushf[arc] = 0;
+ last = arc;
+ }
+ }
+ if (x[arc] > 0)
+ { new_level = p[endn[arc]] + rc[arc];
+ if (new_level > bstlevel)
+ { bstlevel = new_level;
+ extarc = arc;
+ }
+ }
+ }
+ fpushb[node] = 0;
+ for (arc = fin[node]; arc > 0; arc = nxtin[arc])
+ { if (x[arc] > 0)
+ { if (fpushb[node] == 0)
+ { fpushb[node] = arc;
+ nxtpushb[arc] = 0;
+ last = arc;
+ }
+ else
+ { nxtpushb[last] = arc;
+ nxtpushb[arc] = 0;
+ last = arc;
+ }
+ }
+ if (u[arc] > 0)
+ { new_level = p[startn[arc]] - rc[arc];
+ if (new_level > bstlevel)
+ { bstlevel = new_level;
+ extarc = -arc;
+ }
+ }
+ }
+ extend_arc[node] = extarc;
+ p[node] = bstlevel - eps;
+ }
+L200: /* Start the augmentation cycles of the new scaling phase. */
+ if (dfct[root] >= thresh_dfct)
+ goto L3000;
+ term = root;
+ path_id[root] = true;
+L500: /* Main forward algorithm with root as origin. */
+ /* start of a new forward iteration */
+ pterm = p[term];
+ extarc = extend_arc[term];
+ if (extarc == 0)
+ { /* build the list of arcs w/ room for pushing flow */
+ fpushf[term] = 0;
+ for (arc = fou[term]; arc > 0; arc = nxtou[arc])
+ { if (u[arc] > 0)
+ { if (fpushf[term] == 0)
+ { fpushf[term] = arc;
+ nxtpushf[arc] = 0;
+ last = arc;
+ }
+ else
+ { nxtpushf[last] = arc;
+ nxtpushf[arc] = 0;
+ last = arc;
+ }
+ }
+ }
+ fpushb[term] = 0;
+ for (arc = fin[term]; arc > 0; arc = nxtin[arc])
+ { if (x[arc] > 0)
+ { if (fpushb[term] == 0)
+ { fpushb[term] = arc;
+ nxtpushb[arc] = 0;
+ last = arc;
+ }
+ else
+ { nxtpushb[last] = arc;
+ nxtpushb[arc] = 0;
+ last = arc;
+ }
+ }
+ }
+ goto L600;
+ }
+ /* speculative path extension attempt */
+ /* note: arc > 0 means that arc is oriented from the root to the
+ * destinations
+ * arc < 0 means that arc is oriented from the destinations to the
+ * root
+ * extarc = 0 or prdarc = 0, means the extension arc or the
+ * predecessor arc, respectively, has not been established */
+ if (extarc > 0)
+ { if (u[extarc] == 0)
+ { seclevel = sb_level[term];
+ goto L580;
+ }
+ end = endn[extarc];
+ bstlevel = p[end] + rc[extarc];
+ if (pterm >= bstlevel)
+ { if (path_id[end])
+ goto L1200;
+ term = end;
+ prdcsr[term] = extarc;
+ path_id[term] = true;
+ /* if negative surplus node is found, do an augmentation */
+ if (dfct[term] > 0)
+ goto L2000;
+ /* return for another iteration */
+ goto L500;
+ }
+ }
+ else
+ { extarc = -extarc;
+ if (x[extarc] == 0)
+ { seclevel = sb_level[term];
+ goto L580;
+ }
+ start = startn[extarc];
+ bstlevel = p[start] - rc[extarc];
+ if (pterm >= bstlevel)
+ { if (path_id[start])
+ goto L1200;
+ term = start;
+ prdcsr[term] = -extarc;
+ path_id[term] = true;
+ /* if negative surplus node is found, do an augmentation */
+ if (dfct[term] > 0)
+ goto L2000;
+ /* return for another iteration */
+ goto L500;
+ }
+ }
+L550: /* second best logic test applied to save a full node scan
+ * if old best level continues to be best go for another
+ * contraction */
+ seclevel = sb_level[term];
+ if (bstlevel <= seclevel)
+ goto L800;
+L580: /* if second best can be used do either a contraction or start
+ * over with a speculative extension */
+ if (seclevel > -large)
+ { extarc = sb_arc[term];
+ if (extarc > 0)
+ { if (u[extarc] == 0)
+ goto L600;
+ bstlevel = p[endn[extarc]] + rc[extarc];
+ }
+ else
+ { if (x[-extarc] == 0)
+ goto L600;
+ bstlevel = p[startn[-extarc]] - rc[-extarc];
+ }
+ if (bstlevel == seclevel)
+ { sb_level[term] = -large;
+ extend_arc[term] = extarc;
+ goto L800;
+ }
+ }
+L600: /* extension/contraction attempt was unsuccessful, so scan
+ * terminal node */
+ nsp++;
+ bstlevel = seclevel = large;
+ for (arc = fpushf[term]; arc > 0; arc = nxtpushf[arc])
+ { new_level = p[endn[arc]] + rc[arc];
+ if (new_level < seclevel)
+ { if (new_level < bstlevel)
+ { seclevel = bstlevel;
+ bstlevel = new_level;
+ secarc = extarc;
+ extarc = arc;
+ }
+ else
+ { seclevel = new_level;
+ secarc = arc;
+ }
+ }
+ }
+ for (arc = fpushb[term]; arc > 0; arc = nxtpushb[arc])
+ { new_level = p[startn[arc]] - rc[arc];
+ if (new_level < seclevel)
+ { if (new_level < bstlevel)
+ { seclevel = bstlevel;
+ bstlevel = new_level;
+ secarc = extarc;
+ extarc = -arc;
+ }
+ else
+ { seclevel = new_level;
+ secarc = -arc;
+ }
+ }
+ }
+ sb_level[term] = seclevel;
+ sb_arc[term] = secarc;
+ extend_arc[term] = extarc;
+L800: /* End of node scan. */
+ /* if the terminal node is the root, adjust its price and change
+ * root */
+ if (term == root)
+ { p[term] = bstlevel + eps;
+ if (p[term] >= large)
+ { /* no path to the destination */
+ /* problem is found to be infeasible */
+ return 1;
+ }
+ path_id[root] = false;
+ prevnode = root;
+ root = nxtqueue[root];
+ goto L200;
+ }
+ /* check whether extension or contraction */
+ prd = prdcsr[term];
+ if (prd > 0)
+ { pr_term = startn[prd];
+ prevlevel = p[pr_term] - rc[prd];
+ }
+ else
+ { pr_term = endn[-prd];
+ prevlevel = p[pr_term] + rc[-prd];
+ }
+ if (prevlevel > bstlevel)
+ { /* path extension */
+ if (prevlevel >= bstlevel + eps)
+ p[term] = bstlevel + eps;
+ else
+ p[term] = prevlevel;
+ if (extarc > 0)
+ { end = endn[extarc];
+ if (path_id[end])
+ goto L1200;
+ term = end;
+ }
+ else
+ { start = startn[-extarc];
+ if (path_id[start])
+ goto L1200;
+ term = start;
+ }
+ prdcsr[term] = extarc;
+ path_id[term] = true;
+ /* if negative surplus node is found, do an augmentation */
+ if (dfct[term] > 0)
+ goto L2000;
+ /* return for another iteration */
+ goto L500;
+ }
+ else
+ { /* path contraction */
+ p[term] = bstlevel + eps;
+ path_id[term] = false;
+ term = pr_term;
+ if (pr_term != root)
+ { if (bstlevel <= pterm + eps)
+ goto L2000;
+ }
+ pterm = p[term];
+ extarc = prd;
+ if (prd > 0)
+ bstlevel += eps + rc[prd];
+ else
+ bstlevel += eps - rc[-prd];
+ /* do a second best test and if that fails, do a full node
+ * scan */
+ goto L550;
+ }
+L1200:/* A cycle is about to form; do a retreat sequence. */
+ node = term;
+L1600:if (node != root)
+ { path_id[node] = false;
+ prd = prdcsr[node];
+ if (prd > 0)
+ { pr_term = startn[prd];
+ if (p[pr_term] == p[node] + rc[prd] + eps)
+ { node = pr_term;
+ goto L1600;
+ }
+ }
+ else
+ { pr_term = endn[-prd];
+ if (p[pr_term] == p[node] - rc[-prd] + eps)
+ { node = pr_term;
+ goto L1600;
+ }
+ }
+ /* do a full scan and price rise at pr_term */
+ nsp++;
+ bstlevel = seclevel = large;
+ for (arc = fpushf[pr_term]; arc > 0; arc = nxtpushf[arc])
+ { new_level = p[endn[arc]] + rc[arc];
+ if (new_level < seclevel)
+ { if (new_level < bstlevel)
+ { seclevel = bstlevel;
+ bstlevel = new_level;
+ secarc = extarc;
+ extarc = arc;
+ }
+ else
+ { seclevel = new_level;
+ secarc = arc;
+ }
+ }
+ }
+ for (arc = fpushb[pr_term]; arc > 0; arc = nxtpushb[arc])
+ { new_level = p[startn[arc]] - rc[arc];
+ if (new_level < seclevel)
+ { if (new_level < bstlevel)
+ { seclevel = bstlevel;
+ bstlevel = new_level;
+ secarc = extarc;
+ extarc = -arc;
+ }
+ else
+ { seclevel = new_level;
+ secarc = -arc;
+ }
+ }
+ }
+ sb_level[pr_term] = seclevel;
+ sb_arc[pr_term] = secarc;
+ extend_arc[pr_term] = extarc;
+ p[pr_term] = bstlevel + eps;
+ if (pr_term == root)
+ { prevnode = root;
+ path_id[root] = false;
+ root = nxtqueue[root];
+ goto L200;
+ }
+ path_id[pr_term] = false;
+ prd = prdcsr[pr_term];
+ if (prd > 0)
+ term = startn[prd];
+ else
+ term = endn[-prd];
+ if (term == root)
+ { prevnode = root;
+ path_id[root] = false;
+ root = nxtqueue[root];
+ goto L200;
+ }
+ else
+ goto L2000;
+ }
+L2000:/* End of auction/shortest path routine. */
+ /* do augmentation from root and correct the push lists */
+ incr = -dfct[root];
+ for (node = root;;)
+ { extarc = extend_arc[node];
+ path_id[node] = false;
+ if (extarc > 0)
+ { node = endn[extarc];
+ if (incr > u[extarc])
+ incr = u[extarc];
+ }
+ else
+ { node = startn[-extarc];
+ if (incr > x[-extarc])
+ incr = x[-extarc];
+ }
+ if (node == term)
+ break;
+ }
+ path_id[term] = false;
+ if (dfct[term] > 0)
+ { if (incr > dfct[term])
+ incr = dfct[term];
+ }
+ for (node = root;;)
+ { extarc = extend_arc[node];
+ if (extarc > 0)
+ { end = endn[extarc];
+ /* add arc to the reduced graph */
+ if (x[extarc] == 0)
+ { nxtpushb[extarc] = fpushb[end];
+ fpushb[end] = extarc;
+ new_level = p[node] - rc[extarc];
+ if (sb_level[end] > new_level)
+ { sb_level[end] = new_level;
+ sb_arc[end] = -extarc;
+ }
+ }
+ x[extarc] += incr;
+ u[extarc] -= incr;
+ /* remove arc from the reduced graph */
+ if (u[extarc] == 0)
+ { nas++;
+ arc = fpushf[node];
+ if (arc == extarc)
+ fpushf[node] = nxtpushf[arc];
+ else
+ { prevarc = arc;
+ arc = nxtpushf[arc];
+ while (arc > 0)
+ { if (arc == extarc)
+ { nxtpushf[prevarc] = nxtpushf[arc];
+ break;
+ }
+ prevarc = arc;
+ arc = nxtpushf[arc];
+ }
+ }
+ }
+ node = end;
+ }
+ else
+ { extarc = -extarc;
+ start = startn[extarc];
+ /* add arc to the reduced graph */
+ if (u[extarc] == 0)
+ { nxtpushf[extarc] = fpushf[start];
+ fpushf[start] = extarc;
+ new_level = p[node] + rc[extarc];
+ if (sb_level[start] > new_level)
+ { sb_level[start] = new_level;
+ sb_arc[start] = extarc;
+ }
+ }
+ u[extarc] += incr;
+ x[extarc] -= incr;
+ /* remove arc from the reduced graph */
+ if (x[extarc] == 0)
+ { nas++;
+ arc = fpushb[node];
+ if (arc == extarc)
+ fpushb[node] = nxtpushb[arc];
+ else
+ { prevarc = arc;
+ arc = nxtpushb[arc];
+ while (arc > 0)
+ { if (arc == extarc)
+ { nxtpushb[prevarc] = nxtpushb[arc];
+ break;
+ }
+ prevarc = arc;
+ arc = nxtpushb[arc];
+ }
+ }
+ }
+ node = start;
+ }
+ if (node == term)
+ break;
+ }
+ dfct[term] -= incr;
+ dfct[root] += incr;
+ /* insert term in the queue if it has a large enough surplus */
+ if (dfct[term] < thresh_dfct)
+ { if (nxtqueue[term] == 0)
+ { nxtnode = nxtqueue[root];
+ if ((p[term] >= p[nxtnode]) && (root != nxtnode))
+ { nxtqueue[root] = term;
+ nxtqueue[term] = nxtnode;
+ }
+ else
+ { nxtqueue[prevnode] = term;
+ nxtqueue[term] = root;
+ prevnode = term;
+ }
+ }
+ }
+ /* if root has a large enough surplus, keep it in the queue and
+ * return for another iteration */
+ if (dfct[root] < thresh_dfct)
+ { prevnode = root;
+ root = nxtqueue[root];
+ goto L200;
+ }
+L3000:/* end of augmentation cycle */
+ /* Check for termination of scaling phase. If scaling phase is not
+ * finished, advance the queue and return to take another node. */
+ nxtnode = nxtqueue[root];
+ if (root != nxtnode)
+ { nxtqueue[root] = 0;
+ nxtqueue[prevnode] = nxtnode;
+ root = nxtnode;
+ goto L200;
+ }
+ /* End of subproblem (scaling phase). */
+ /* Reduce epsilon. */
+ eps /= factor;
+ if (eps < 1) eps = 1;
+ thresh_dfct /= factor;
+ if (eps == 1) thresh_dfct = 0;
+ /* if another auction scaling phase remains, reset the flows &
+ * the push lists; else reset arc flows to satisfy cs and compute
+ * reduced costs */
+ if (crash == 1)
+ { for (arc = 1; arc <= na; arc++)
+ { start = startn[arc];
+ end = endn[arc];
+ pstart = p[start];
+ pend = p[end];
+ if (pstart > pend + eps + rc[arc])
+ { resid = u[arc];
+ if (resid > 0)
+ { dfct[start] += resid;
+ dfct[end] -= resid;
+ x[arc] += resid;
+ u[arc] = 0;
+ }
+ }
+ else if (pstart < pend - eps + rc[arc])
+ { flow = x[arc];
+ if (flow > 0)
+ { dfct[start] -= flow;
+ dfct[end] += flow;
+ x[arc] = 0;
+ u[arc] += flow;
+ }
+ }
+ }
+ /* return for another phase */
+ goto L100;
+ }
+ else
+ { crash = 1;
+ for (arc = 1; arc <= na; arc++)
+ { start = startn[arc];
+ end = endn[arc];
+ red_cost = rc[arc] + p[end] - p[start];
+ if (red_cost < 0)
+ { resid = u[arc];
+ if (resid > 0)
+ { dfct[start] += resid;
+ dfct[end] -= resid;
+ x[arc] += resid;
+ u[arc] = 0;
+ }
+ }
+ else if (red_cost > 0)
+ { flow = x[arc];
+ if (flow > 0)
+ { dfct[start] -= flow;
+ dfct[end] += flow;
+ x[arc] = 0;
+ u[arc] += flow;
+ }
+ }
+ rc[arc] = red_cost;
+ }
+ }
+ return 0;
+# undef crash
+# undef nsp
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/relax4.h b/test/monniaux/glpk-4.65/src/misc/relax4.h
new file mode 100644
index 00000000..f48b8508
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/relax4.h
@@ -0,0 +1,102 @@
+/* relax4.h */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#ifndef RELAX4_H
+#define RELAX4_H
+
+struct relax4_csa
+{ /* common storage area */
+ /* input parameters --------------------------------------------*/
+ int n;
+ /* number of nodes */
+ int na;
+ /* number of arcs */
+ int large;
+ /* very large int to represent infinity */
+ int repeat;
+ /* true if initialization is to be skipped (false otherwise) */
+ int crash;
+ /* 0 if default initialization is used
+ * 1 if auction initialization is used */
+ int *startn; /* int startn[1+na]; */
+ /* startn[j] = starting node for arc j, j = 1,...,na */
+ int *endn; /* int endn[1+na] */
+ /* endn[j] = ending node for arc j, j = 1,...,na */
+ int *fou; /* int fou[1+n]; */
+ /* fou[i] = first arc out of node i, i = 1,...,n */
+ int *nxtou; /* int nxtou[1+na]; */
+ /* nxtou[j] = next arc out of the starting node of arc j,
+ * j = 1,...,na */
+ int *fin; /* int fin[1+n]; */
+ /* fin[i] = first arc into node i, i = 1,...,n */
+ int *nxtin; /* int nxtin[1+na]; */
+ /* nxtin[j] = next arc into the ending node of arc j,
+ * j = 1,...,na */
+ /* updated parameters ------------------------------------------*/
+ int *rc; /* int rc[1+na]; */
+ /* rc[j] = reduced cost of arc j, j = 1,...,na */
+ int *u; /* int u[1+na]; */
+ /* u[j] = capacity of arc j on input
+ * and (capacity of arc j) - x(j) on output, j = 1,...,na */
+ int *dfct; /* int dfct[1+n]; */
+ /* dfct[i] = demand at node i on input
+ * and zero on output, i = 1,...,n */
+ /* output parameters -------------------------------------------*/
+ int *x; /* int x[1+na]; */
+ /* x[j] = flow on arc j, j = 1,...,na */
+ int nmultinode;
+ /* number of multinode relaxation iterations in RELAX4 */
+ int iter;
+ /* number of relaxation iterations in RELAX4 */
+ int num_augm;
+ /* number of flow augmentation steps in RELAX4 */
+ int num_ascnt;
+ /* number of multinode ascent steps in RELAX4 */
+ int nsp;
+ /* number of auction/shortest path iterations */
+ /* working parameters ------------------------------------------*/
+ int *label; /* int label, tempin, p[1+n]; */
+ int *prdcsr; /* int prdcsr, tempou, price[1+n]; */
+ int *save; /* int save[1+na]; */
+ int *tfstou; /* int tfstou, fpushf[1+n]; */
+ int *tnxtou; /* int tnxtou, nxtpushf[1+na]; */
+ int *tfstin; /* int tfstin, fpushb[1+n]; */
+ int *tnxtin; /* int tnxtin, nxtpushb[1+na]; */
+ int *nxtqueue; /* int nxtqueue[1+n]; */
+ char *scan; /* bool scan[1+n]; */
+ char *mark; /* bool mark, path_id[1+n]; */
+ /* working parameters used by routine auction only -------------*/
+ int *extend_arc; /* int extend_arc[1+n]; */
+ int *sb_level; /* int sb_level[1+n]; */
+ int *sb_arc; /* int sb_arc[1+n]; */
+};
+
+#define relax4 _glp_relax4
+int relax4(struct relax4_csa *csa);
+
+#define relax4_inidat _glp_relax4_inidat
+void relax4_inidat(struct relax4_csa *csa);
+
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/rng.c b/test/monniaux/glpk-4.65/src/misc/rng.c
new file mode 100644
index 00000000..e0acb53a
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/rng.c
@@ -0,0 +1,227 @@
+/* rng.c (pseudo-random number generator) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* This code is a modified version of the module GB_FLIP, a portable
+* pseudo-random number generator. The original version of GB_FLIP is
+* a part of The Stanford GraphBase developed by Donald E. Knuth (see
+* http://www-cs-staff.stanford.edu/~knuth/sgb.html).
+*
+* Note that all changes concern only external names, so this modified
+* version produces exactly the same results as the original version.
+*
+* Changes were made by Andrew Makhorin <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include "env.h"
+#include "rng.h"
+
+#if 0
+int A[56] = { -1 };
+#else
+#define A (rand->A)
+#endif
+/* pseudo-random values */
+
+#if 0
+int *fptr = A;
+#else
+#define fptr (rand->fptr)
+#endif
+/* the next A value to be exported */
+
+#define mod_diff(x, y) (((x) - (y)) & 0x7FFFFFFF)
+/* difference modulo 2^31 */
+
+static int flip_cycle(RNG *rand)
+{ /* this is an auxiliary routine to do 55 more steps of the basic
+ * recurrence, at high speed, and to reset fptr */
+ int *ii, *jj;
+ for (ii = &A[1], jj = &A[32]; jj <= &A[55]; ii++, jj++)
+ *ii = mod_diff(*ii, *jj);
+ for (jj = &A[1]; ii <= &A[55]; ii++, jj++)
+ *ii = mod_diff(*ii, *jj);
+ fptr = &A[54];
+ return A[55];
+}
+
+/***********************************************************************
+* NAME
+*
+* rng_create_rand - create pseudo-random number generator
+*
+* SYNOPSIS
+*
+* #include "rng.h"
+* RNG *rng_create_rand(void);
+*
+* DESCRIPTION
+*
+* The routine rng_create_rand creates and initializes a pseudo-random
+* number generator.
+*
+* RETURNS
+*
+* The routine returns a pointer to the generator created. */
+
+RNG *rng_create_rand(void)
+{ RNG *rand;
+ int i;
+ rand = talloc(1, RNG);
+ A[0] = -1;
+ for (i = 1; i <= 55; i++) A[i] = 0;
+ fptr = A;
+ rng_init_rand(rand, 1);
+ return rand;
+}
+
+/***********************************************************************
+* NAME
+*
+* rng_init_rand - initialize pseudo-random number generator
+*
+* SYNOPSIS
+*
+* #include "rng.h"
+* void rng_init_rand(RNG *rand, int seed);
+*
+* DESCRIPTION
+*
+* The routine rng_init_rand initializes the pseudo-random number
+* generator. The parameter seed may be any integer number. Note that
+* on creating the generator this routine is called with the parameter
+* seed equal to 1. */
+
+void rng_init_rand(RNG *rand, int seed)
+{ int i;
+ int prev = seed, next = 1;
+ seed = prev = mod_diff(prev, 0);
+ A[55] = prev;
+ for (i = 21; i; i = (i + 21) % 55)
+ { A[i] = next;
+ next = mod_diff(prev, next);
+ if (seed & 1)
+ seed = 0x40000000 + (seed >> 1);
+ else
+ seed >>= 1;
+ next = mod_diff(next, seed);
+ prev = A[i];
+ }
+ flip_cycle(rand);
+ flip_cycle(rand);
+ flip_cycle(rand);
+ flip_cycle(rand);
+ flip_cycle(rand);
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* rng_next_rand - obtain pseudo-random integer in the range [0, 2^31-1]
+*
+* SYNOPSIS
+*
+* #include "rng.h"
+* int rng_next_rand(RNG *rand);
+*
+* RETURNS
+*
+* The routine rng_next_rand returns a next pseudo-random integer which
+* is uniformly distributed between 0 and 2^31-1, inclusive. The period
+* length of the generated numbers is 2^85 - 2^30. The low order bits of
+* the generated numbers are just as random as the high-order bits. */
+
+int rng_next_rand(RNG *rand)
+{ return
+ *fptr >= 0 ? *fptr-- : flip_cycle(rand);
+}
+
+/***********************************************************************
+* NAME
+*
+* rng_unif_rand - obtain pseudo-random integer in the range [0, m-1]
+*
+* SYNOPSIS
+*
+* #include "rng.h"
+* int rng_unif_rand(RNG *rand, int m);
+*
+* RETURNS
+*
+* The routine rng_unif_rand returns a next pseudo-random integer which
+* is uniformly distributed between 0 and m-1, inclusive, where m is any
+* positive integer less than 2^31. */
+
+#define two_to_the_31 ((unsigned int)0x80000000)
+
+int rng_unif_rand(RNG *rand, int m)
+{ unsigned int t = two_to_the_31 - (two_to_the_31 % m);
+ int r;
+ xassert(m > 0);
+ do { r = rng_next_rand(rand); } while (t <= (unsigned int)r);
+ return r % m;
+}
+
+/***********************************************************************
+* NAME
+*
+* rng_delete_rand - delete pseudo-random number generator
+*
+* SYNOPSIS
+*
+* #include "rng.h"
+* void rng_delete_rand(RNG *rand);
+*
+* DESCRIPTION
+*
+* The routine rng_delete_rand frees all the memory allocated to the
+* specified pseudo-random number generator. */
+
+void rng_delete_rand(RNG *rand)
+{ tfree(rand);
+ return;
+}
+
+/**********************************************************************/
+
+#ifdef GLP_TEST
+/* To be sure that this modified version produces the same results as
+ * the original version, run this validation program. */
+
+int main(void)
+{ RNG *rand;
+ int j;
+ rand = rng_create_rand();
+ rng_init_rand(rand, -314159);
+ if (rng_next_rand(rand) != 119318998)
+ { fprintf(stderr, "Failure on the first try!\n");
+ return -1;
+ }
+ for (j = 1; j <= 133; j++) rng_next_rand(rand);
+ if (rng_unif_rand(rand, 0x55555555) != 748103812)
+ { fprintf(stderr, "Failure on the second try!\n");
+ return -2;
+ }
+ fprintf(stderr, "OK, the random-number generator routines seem to"
+ " work!\n");
+ rng_delete_rand(rand);
+ return 0;
+}
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/rng.h b/test/monniaux/glpk-4.65/src/misc/rng.h
new file mode 100644
index 00000000..49725e05
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/rng.h
@@ -0,0 +1,67 @@
+/* rng.h (pseudo-random number generator) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2003-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#ifndef RNG_H
+#define RNG_H
+
+typedef struct RNG RNG;
+
+struct RNG
+{ /* Knuth's portable pseudo-random number generator */
+ int A[56];
+ /* pseudo-random values */
+ int *fptr;
+ /* the next A value to be exported */
+};
+
+#define rng_create_rand _glp_rng_create_rand
+RNG *rng_create_rand(void);
+/* create pseudo-random number generator */
+
+#define rng_init_rand _glp_rng_init_rand
+void rng_init_rand(RNG *rand, int seed);
+/* initialize pseudo-random number generator */
+
+#define rng_next_rand _glp_rng_next_rand
+int rng_next_rand(RNG *rand);
+/* obtain pseudo-random integer in the range [0, 2^31-1] */
+
+#define rng_unif_rand _glp_rng_unif_rand
+int rng_unif_rand(RNG *rand, int m);
+/* obtain pseudo-random integer in the range [0, m-1] */
+
+#define rng_delete_rand _glp_rng_delete_rand
+void rng_delete_rand(RNG *rand);
+/* delete pseudo-random number generator */
+
+#define rng_unif_01 _glp_rng_unif_01
+double rng_unif_01(RNG *rand);
+/* obtain pseudo-random number in the range [0, 1] */
+
+#define rng_uniform _glp_rng_uniform
+double rng_uniform(RNG *rand, double a, double b);
+/* obtain pseudo-random number in the range [a, b] */
+
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/rng1.c b/test/monniaux/glpk-4.65/src/misc/rng1.c
new file mode 100644
index 00000000..b89f676f
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/rng1.c
@@ -0,0 +1,73 @@
+/* rng1.c (pseudo-random number generator) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2003-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include "env.h"
+#include "rng.h"
+
+/***********************************************************************
+* NAME
+*
+* rng_unif_01 - obtain pseudo-random number in the range [0, 1]
+*
+* SYNOPSIS
+*
+* #include "rng.h"
+* double rng_unif_01(RNG *rand);
+*
+* RETURNS
+*
+* The routine rng_unif_01 returns a next pseudo-random number which is
+* uniformly distributed in the range [0, 1]. */
+
+double rng_unif_01(RNG *rand)
+{ double x;
+ x = (double)rng_next_rand(rand) / 2147483647.0;
+ xassert(0.0 <= x && x <= 1.0);
+ return x;
+}
+
+/***********************************************************************
+* NAME
+*
+* rng_uniform - obtain pseudo-random number in the range [a, b]
+*
+* SYNOPSIS
+*
+* #include "rng.h"
+* double rng_uniform(RNG *rand, double a, double b);
+*
+* RETURNS
+*
+* The routine rng_uniform returns a next pseudo-random number which is
+* uniformly distributed in the range [a, b]. */
+
+double rng_uniform(RNG *rand, double a, double b)
+{ double x;
+ xassert(a < b);
+ x = rng_unif_01(rand);
+ x = a * (1.0 - x) + b * x;
+ xassert(a <= x && x <= b);
+ return x;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/round2n.c b/test/monniaux/glpk-4.65/src/misc/round2n.c
new file mode 100644
index 00000000..8a94c616
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/round2n.c
@@ -0,0 +1,64 @@
+/* round2n.c (round floating-point number to nearest power of two) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include "env.h"
+#include "misc.h"
+
+/***********************************************************************
+* NAME
+*
+* round2n - round floating-point number to nearest power of two
+*
+* SYNOPSIS
+*
+* #include "misc.h"
+* double round2n(double x);
+*
+* RETURNS
+*
+* Given a positive floating-point value x the routine round2n returns
+* 2^n such that |x - 2^n| is minimal.
+*
+* EXAMPLES
+*
+* round2n(10.1) = 2^3 = 8
+* round2n(15.3) = 2^4 = 16
+* round2n(0.01) = 2^(-7) = 0.0078125
+*
+* BACKGROUND
+*
+* Let x = f * 2^e, where 0.5 <= f < 1 is a normalized fractional part,
+* e is an integer exponent. Then, obviously, 0.5 * 2^e <= x < 2^e, so
+* if x - 0.5 * 2^e <= 2^e - x, we choose 0.5 * 2^e = 2^(e-1), and 2^e
+* otherwise. The latter condition can be written as 2 * x <= 1.5 * 2^e
+* or 2 * f * 2^e <= 1.5 * 2^e or, finally, f <= 0.75. */
+
+double round2n(double x)
+{ int e;
+ double f;
+ xassert(x > 0.0);
+ f = frexp(x, &e);
+ return ldexp(1.0, f <= 0.75 ? e-1 : e);
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/str2int.c b/test/monniaux/glpk-4.65/src/misc/str2int.c
new file mode 100644
index 00000000..cbd6e953
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/str2int.c
@@ -0,0 +1,92 @@
+/* str2int.c (convert string to int) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include "misc.h"
+#include "stdc.h"
+
+/***********************************************************************
+* NAME
+*
+* str2int - convert character string to value of int type
+*
+* SYNOPSIS
+*
+* #include "misc.h"
+* int str2int(const char *str, int *val);
+*
+* DESCRIPTION
+*
+* The routine str2int converts the character string str to a value of
+* integer type and stores the value into location, which the parameter
+* val points to (in the case of error content of this location is not
+* changed).
+*
+* RETURNS
+*
+* The routine returns one of the following error codes:
+*
+* 0 - no error;
+* 1 - value out of range;
+* 2 - character string is syntactically incorrect. */
+
+int str2int(const char *str, int *val_)
+{ int d, k, s, val = 0;
+ /* scan optional sign */
+ if (str[0] == '+')
+ s = +1, k = 1;
+ else if (str[0] == '-')
+ s = -1, k = 1;
+ else
+ s = +1, k = 0;
+ /* check for the first digit */
+ if (!isdigit((unsigned char)str[k]))
+ return 2;
+ /* scan digits */
+ while (isdigit((unsigned char)str[k]))
+ { d = str[k++] - '0';
+ if (s > 0)
+ { if (val > INT_MAX / 10)
+ return 1;
+ val *= 10;
+ if (val > INT_MAX - d)
+ return 1;
+ val += d;
+ }
+ else /* s < 0 */
+ { if (val < INT_MIN / 10)
+ return 1;
+ val *= 10;
+ if (val < INT_MIN + d)
+ return 1;
+ val -= d;
+ }
+ }
+ /* check for terminator */
+ if (str[k] != '\0')
+ return 2;
+ /* conversion has been done */
+ *val_ = val;
+ return 0;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/str2num.c b/test/monniaux/glpk-4.65/src/misc/str2num.c
new file mode 100644
index 00000000..26c2f68f
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/str2num.c
@@ -0,0 +1,110 @@
+/* str2num.c (convert string to double) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include "misc.h"
+#include "stdc.h"
+
+/***********************************************************************
+* NAME
+*
+* str2num - convert character string to value of double type
+*
+* SYNOPSIS
+*
+* #include "misc.h"
+* int str2num(const char *str, double *val);
+*
+* DESCRIPTION
+*
+* The routine str2num converts the character string str to a value of
+* double type and stores the value into location, which the parameter
+* val points to (in the case of error content of this location is not
+* changed).
+*
+* RETURNS
+*
+* The routine returns one of the following error codes:
+*
+* 0 - no error;
+* 1 - value out of range;
+* 2 - character string is syntactically incorrect. */
+
+int str2num(const char *str, double *val_)
+{ int k;
+ double val;
+ /* scan optional sign */
+ k = (str[0] == '+' || str[0] == '-' ? 1 : 0);
+ /* check for decimal point */
+ if (str[k] == '.')
+ { k++;
+ /* a digit should follow it */
+ if (!isdigit((unsigned char)str[k]))
+ return 2;
+ k++;
+ goto frac;
+ }
+ /* integer part should start with a digit */
+ if (!isdigit((unsigned char)str[k]))
+ return 2;
+ /* scan integer part */
+ while (isdigit((unsigned char)str[k]))
+ k++;
+ /* check for decimal point */
+ if (str[k] == '.') k++;
+frac: /* scan optional fraction part */
+ while (isdigit((unsigned char)str[k]))
+ k++;
+ /* check for decimal exponent */
+ if (str[k] == 'E' || str[k] == 'e')
+ { k++;
+ /* scan optional sign */
+ if (str[k] == '+' || str[k] == '-')
+ k++;
+ /* a digit should follow E, E+ or E- */
+ if (!isdigit((unsigned char)str[k]))
+ return 2;
+ }
+ /* scan optional exponent part */
+ while (isdigit((unsigned char)str[k]))
+ k++;
+ /* check for terminator */
+ if (str[k] != '\0')
+ return 2;
+ /* perform conversion */
+ { char *endptr;
+ val = strtod(str, &endptr);
+ if (*endptr != '\0')
+ return 2;
+ }
+ /* check for overflow */
+ if (!(-DBL_MAX <= val && val <= +DBL_MAX))
+ return 1;
+ /* check for underflow */
+ if (-DBL_MIN < val && val < +DBL_MIN)
+ val = 0.0;
+ /* conversion has been done */
+ *val_ = val;
+ return 0;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/strspx.c b/test/monniaux/glpk-4.65/src/misc/strspx.c
new file mode 100644
index 00000000..fe8a2a10
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/strspx.c
@@ -0,0 +1,60 @@
+/* strspx.c (remove all spaces from string) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include "misc.h"
+
+/***********************************************************************
+* NAME
+*
+* strspx - remove all spaces from character string
+*
+* SYNOPSIS
+*
+* #include "misc.h"
+* char *strspx(char *str);
+*
+* DESCRIPTION
+*
+* The routine strspx removes all spaces from the character string str.
+*
+* RETURNS
+*
+* The routine returns a pointer to the character string.
+*
+* EXAMPLES
+*
+* strspx(" Errare humanum est ") => "Errarehumanumest"
+*
+* strspx(" ") => "" */
+
+char *strspx(char *str)
+{ char *s, *t;
+ for (s = t = str; *s; s++)
+ { if (*s != ' ')
+ *t++ = *s;
+ }
+ *t = '\0';
+ return str;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/strtrim.c b/test/monniaux/glpk-4.65/src/misc/strtrim.c
new file mode 100644
index 00000000..9992c4b0
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/strtrim.c
@@ -0,0 +1,62 @@
+/* strtrim.c (remove trailing spaces from string) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include "misc.h"
+#include "stdc.h"
+
+/***********************************************************************
+* NAME
+*
+* strtrim - remove trailing spaces from character string
+*
+* SYNOPSIS
+*
+* #include "misc.h"
+* char *strtrim(char *str);
+*
+* DESCRIPTION
+*
+* The routine strtrim removes trailing spaces from the character
+* string str.
+*
+* RETURNS
+*
+* The routine returns a pointer to the character string.
+*
+* EXAMPLES
+*
+* strtrim("Errare humanum est ") => "Errare humanum est"
+*
+* strtrim(" ") => "" */
+
+char *strtrim(char *str)
+{ char *t;
+ for (t = strrchr(str, '\0') - 1; t >= str; t--)
+ { if (*t != ' ')
+ break;
+ *t = '\0';
+ }
+ return str;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/triang.c b/test/monniaux/glpk-4.65/src/misc/triang.c
new file mode 100644
index 00000000..99ba4d60
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/triang.c
@@ -0,0 +1,311 @@
+/* triang.c (find maximal triangular part of rectangular matrix) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include "env.h"
+#include "triang.h"
+
+/***********************************************************************
+* triang - find maximal triangular part of rectangular matrix
+*
+* Given a mxn sparse matrix A this routine finds permutation matrices
+* P and Q such that matrix A' = P * A * Q has the following structure:
+*
+* 1 s n
+* 1 * . . . . . x x x x x
+* * * . . . . x x x x x
+* * * * . . . x x x x x
+* * * * * . . x x x x x
+* * * * * * . x x x x x
+* s * * * * * * x x x x x
+* x x x x x x x x x x x
+* x x x x x x x x x x x
+* m x x x x x x x x x x x
+*
+* where '*' are elements of the triangular part, '.' are structural
+* zeros, 'x' are other elements.
+*
+* The formal routine mat specifies the original matrix A in both row-
+* and column-wise format. If the routine mat is called with k = +i,
+* 1 <= i <= m, it should store column indices and values of non-zero
+* elements of i-th row of A in locations ind[1], ..., ind[len] and
+* val[1], ..., val[len], resp., where len is the returned number of
+* non-zeros in the row, 0 <= len <= n. Similarly, if the routine mat
+* is called with k = -j, 1 <= j <= n, it should store row indices and
+* values of non-zero elements of j-th column of A and return len, the
+* number of non-zeros in the column, 0 <= len <= m. Should note that
+* duplicate indices are not allowed.
+*
+* The parameter info is a transit pointer passed to the routine mat.
+*
+* The parameter tol is a tolerance. The routine triang guarantees that
+* each diagonal element in the triangular part of matrix A' is not
+* less in magnitude than tol * max, where max is the maximal magnitude
+* of elements in corresponding column.
+*
+* On exit the routine triang stores information on the triangular part
+* found in the arrays rn and cn. Elements rn[1], ..., rn[s] specify
+* row numbers and elements cn[1], ..., cn[s] specify column numbers
+* of the original matrix A, which correspond to rows/columns 1, ..., s
+* of matrix A', where s is the size of the triangular part returned by
+* the routine, 0 <= s <= min(m, n). The order of rows and columns that
+* are not included in the triangular part remains unspecified.
+*
+* ALGORITHM
+*
+* The routine triang uses a simple greedy heuristic.
+*
+* At some step the matrix A' = P * A * Q has the following structure:
+*
+* 1 n
+* 1 * . . . . . . . x x x
+* * * . . . . . . x x x
+* * * * . . . . . x x x
+* * * * * . . . . x x x
+* x x x x # # # # x x x
+* x x x x # # # # x x x
+* x x x x # # # # x x x
+* x x x x # # # # x x x
+* m x x x x # # # # x x x
+*
+* where '#' are elements of active submatrix. Initially P = Q = I, so
+* the active submatrix is the original matrix A = A'.
+*
+* If some row has exactly one non-zero in the active submatrix (row
+* singleton), the routine includes this row and corresponding column
+* in the triangular part, and removes the column from the active
+* submatrix. Otherwise, the routine simply removes a column having
+* maximal number of non-zeros from the active submatrix in the hope
+* that new row singleton(s) will appear.
+*
+* COMPLEXITY
+*
+* The time complexity of the routine triang is O(nnz), where nnz is
+* number of non-zeros in the original matrix A. */
+
+int triang(int m, int n, int (*mat)(void *info, int k, int ind[],
+ double val[]), void *info, double tol, int rn[], int cn[])
+{ int head, i, j, jj, k, kk, ks, len, len2, next_j, ns, size;
+ int *cind, *rind, *cnt, *ptr, *list, *prev, *next;
+ double *cval, *rval, *big;
+ char *flag;
+ /* allocate working arrays */
+ cind = talloc(1+m, int);
+ cval = talloc(1+m, double);
+ rind = talloc(1+n, int);
+ rval = talloc(1+n, double);
+ cnt = ptr = talloc(1+m, int);
+ list = talloc(1+n, int);
+ prev = talloc(1+n, int);
+ next = talloc(1+n, int);
+ big = talloc(1+n, double);
+ flag = talloc(1+n, char);
+ /*--------------------------------------------------------------*/
+ /* build linked lists of columns having equal lengths */
+ /*--------------------------------------------------------------*/
+ /* ptr[len], 0 <= len <= m, is number of first column of length
+ * len;
+ * next[j], 1 <= j <= n, is number of next column having the same
+ * length as column j;
+ * big[j], 1 <= j <= n, is maximal magnitude of elements in j-th
+ * column */
+ for (len = 0; len <= m; len++)
+ ptr[len] = 0;
+ for (j = 1; j <= n; j++)
+ { /* get j-th column */
+ len = mat(info, -j, cind, cval);
+ xassert(0 <= len && len <= m);
+ /* add this column to beginning of list ptr[len] */
+ next[j] = ptr[len];
+ ptr[len] = j;
+ /* determine maximal magnitude of elements in this column */
+ big[j] = 0.0;
+ for (k = 1; k <= len; k++)
+ { if (big[j] < fabs(cval[k]))
+ big[j] = fabs(cval[k]);
+ }
+ }
+ /*--------------------------------------------------------------*/
+ /* build doubly linked list of columns ordered by decreasing */
+ /* column lengths */
+ /*--------------------------------------------------------------*/
+ /* head is number of first column in the list;
+ * prev[j], 1 <= j <= n, is number of column that precedes j-th
+ * column in the list;
+ * next[j], 1 <= j <= n, is number of column that follows j-th
+ * column in the list */
+ head = 0;
+ for (len = 0; len <= m; len++)
+ { /* walk thru list of columns of length len */
+ for (j = ptr[len]; j != 0; j = next_j)
+ { next_j = next[j];
+ /* add j-th column to beginning of the column list */
+ prev[j] = 0;
+ next[j] = head;
+ if (head != 0)
+ prev[head] = j;
+ head = j;
+ }
+ }
+ /*--------------------------------------------------------------*/
+ /* build initial singleton list */
+ /*--------------------------------------------------------------*/
+ /* there are used two list of columns:
+ * 1) doubly linked list of active columns, in which all columns
+ * are ordered by decreasing column lengths;
+ * 2) singleton list; an active column is included in this list
+ * if it has at least one row singleton in active submatrix */
+ /* flag[j], 1 <= j <= n, is a flag of j-th column:
+ * 0 j-th column is inactive;
+ * 1 j-th column is active;
+ * 2 j-th column is active and has row singleton(s) */
+ /* initially all columns are active */
+ for (j = 1; j <= n; j++)
+ flag[j] = 1;
+ /* initialize row counts and build initial singleton list */
+ /* cnt[i], 1 <= i <= m, is number of non-zeros, which i-th row
+ * has in active submatrix;
+ * ns is size of singleton list;
+ * list[1], ..., list[ns] are numbers of active columns included
+ * in the singleton list */
+ ns = 0;
+ for (i = 1; i <= m; i++)
+ { /* get i-th row */
+ len = cnt[i] = mat(info, +i, rind, rval);
+ xassert(0 <= len && len <= n);
+ if (len == 1)
+ { /* a[i,j] is row singleton */
+ j = rind[1];
+ xassert(1 <= j && j <= n);
+ if (flag[j] != 2)
+ { /* include j-th column in singleton list */
+ flag[j] = 2;
+ list[++ns] = j;
+ }
+ }
+ }
+ /*--------------------------------------------------------------*/
+ /* main loop */
+ /*--------------------------------------------------------------*/
+ size = 0; /* size of triangular part */
+ /* loop until active column list is non-empty, i.e. until the
+ * active submatrix has at least one column */
+ while (head != 0)
+ { if (ns == 0)
+ { /* singleton list is empty */
+ /* remove from the active submatrix a column of maximal
+ * length in the hope that some row singletons appear */
+ j = head;
+ len = mat(info, -j, cind, cval);
+ xassert(0 <= len && len <= m);
+ goto drop;
+ }
+ /* take column j from the singleton list */
+ j = list[ns--];
+ xassert(flag[j] == 2);
+ /* j-th column has at least one row singleton in the active
+ * submatrix; choose one having maximal magnitude */
+ len = mat(info, -j, cind, cval);
+ xassert(0 <= len && len <= m);
+ kk = 0;
+ for (k = 1; k <= len; k++)
+ { i = cind[k];
+ xassert(1 <= i && i <= m);
+ if (cnt[i] == 1)
+ { /* a[i,j] is row singleton */
+ if (kk == 0 || fabs(cval[kk]) < fabs(cval[k]))
+ kk = k;
+ }
+ }
+ xassert(kk > 0);
+ /* check magnitude of the row singleton chosen */
+ if (fabs(cval[kk]) < tol * big[j])
+ { /* all row singletons are too small in magnitude; drop j-th
+ * column */
+ goto drop;
+ }
+ /* row singleton a[i,j] is ok; add i-th row and j-th column to
+ * the triangular part */
+ size++;
+ rn[size] = cind[kk];
+ cn[size] = j;
+drop: /* remove j-th column from the active submatrix */
+ xassert(flag[j]);
+ flag[j] = 0;
+ if (prev[j] == 0)
+ head = next[j];
+ else
+ next[prev[j]] = next[j];
+ if (next[j] == 0)
+ ;
+ else
+ prev[next[j]] = prev[j];
+ /* decrease row counts */
+ for (k = 1; k <= len; k++)
+ { i = cind[k];
+ xassert(1 <= i && i <= m);
+ xassert(cnt[i] > 0);
+ cnt[i]--;
+ if (cnt[i] == 1)
+ { /* new singleton appeared in i-th row; determine number
+ * of corresponding column (it is the only active column
+ * in this row) */
+ len2 = mat(info, +i, rind, rval);
+ xassert(0 <= len2 && len2 <= n);
+ ks = 0;
+ for (kk = 1; kk <= len2; kk++)
+ { jj = rind[kk];
+ xassert(1 <= jj && jj <= n);
+ if (flag[jj])
+ { xassert(ks == 0);
+ ks = kk;
+ }
+ }
+ xassert(ks > 0);
+ /* a[i,jj] is new row singleton */
+ jj = rind[ks];
+ if (flag[jj] != 2)
+ { /* include jj-th column in the singleton list */
+ flag[jj] = 2;
+ list[++ns] = jj;
+ }
+ }
+ }
+ }
+ /* now all row counts should be zero */
+ for (i = 1; i <= m; i++)
+ xassert(cnt[i] == 0);
+ /* deallocate working arrays */
+ tfree(cind);
+ tfree(cval);
+ tfree(rind);
+ tfree(rval);
+ tfree(ptr);
+ tfree(list);
+ tfree(prev);
+ tfree(next);
+ tfree(big);
+ tfree(flag);
+ return size;
+}
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/triang.h b/test/monniaux/glpk-4.65/src/misc/triang.h
new file mode 100644
index 00000000..1e50d44d
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/triang.h
@@ -0,0 +1,34 @@
+/* triang.h (find maximal triangular part of rectangular matrix) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#ifndef TRIANG_H
+#define TRIANG_H
+
+#define triang _glp_triang
+int triang(int m, int n, int (*mat)(void *info, int k, int ind[],
+ double val[]), void *info, double tol, int rn[], int cn[]);
+/* find maximal triangular part of rectangular matrix */
+
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/wclique.c b/test/monniaux/glpk-4.65/src/misc/wclique.c
new file mode 100644
index 00000000..5daa69cf
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/wclique.c
@@ -0,0 +1,242 @@
+/* wclique.c (maximum weight clique, Ostergard's algorithm) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Two subroutines sub() and wclique() below are intended to find a
+* maximum weight clique in a given undirected graph. These subroutines
+* are slightly modified version of the program WCLIQUE developed by
+* Patric Ostergard <http://www.tcs.hut.fi/~pat/wclique.html> and based
+* on ideas from the article "P. R. J. Ostergard, A new algorithm for
+* the maximum-weight clique problem, submitted for publication", which
+* in turn is a generalization of the algorithm for unweighted graphs
+* presented in "P. R. J. Ostergard, A fast algorithm for the maximum
+* clique problem, submitted for publication".
+*
+* USED WITH PERMISSION OF THE AUTHOR OF THE ORIGINAL CODE.
+*
+* Changes were made by Andrew Makhorin <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include "env.h"
+#include "wclique.h"
+
+/***********************************************************************
+* NAME
+*
+* wclique - find maximum weight clique with Ostergard's algorithm
+*
+* SYNOPSIS
+*
+* #include "wclique.h"
+* int wclique(int n, const int w[], const unsigned char a[],
+* int ind[]);
+*
+* DESCRIPTION
+*
+* The routine wclique finds a maximum weight clique in an undirected
+* graph with Ostergard's algorithm.
+*
+* INPUT PARAMETERS
+*
+* n is the number of vertices, n > 0.
+*
+* w[i], i = 1,...,n, is a weight of vertex i.
+*
+* a[*] is the strict (without main diagonal) lower triangle of the
+* graph adjacency matrix in packed format.
+*
+* OUTPUT PARAMETER
+*
+* ind[k], k = 1,...,size, is the number of a vertex included in the
+* clique found, 1 <= ind[k] <= n, where size is the number of vertices
+* in the clique returned on exit.
+*
+* RETURNS
+*
+* The routine returns the clique size, i.e. the number of vertices in
+* the clique. */
+
+struct csa
+{ /* common storage area */
+ int n;
+ /* number of vertices */
+ const int *wt; /* int wt[0:n-1]; */
+ /* weights */
+ const unsigned char *a;
+ /* adjacency matrix (packed lower triangle without main diag.) */
+ int record;
+ /* weight of best clique */
+ int rec_level;
+ /* number of vertices in best clique */
+ int *rec; /* int rec[0:n-1]; */
+ /* best clique so far */
+ int *clique; /* int clique[0:n-1]; */
+ /* table for pruning */
+ int *set; /* int set[0:n-1]; */
+ /* current clique */
+};
+
+#define n (csa->n)
+#define wt (csa->wt)
+#define a (csa->a)
+#define record (csa->record)
+#define rec_level (csa->rec_level)
+#define rec (csa->rec)
+#define clique (csa->clique)
+#define set (csa->set)
+
+#if 0
+static int is_edge(struct csa *csa, int i, int j)
+{ /* if there is arc (i,j), the routine returns true; otherwise
+ * false; 0 <= i, j < n */
+ int k;
+ xassert(0 <= i && i < n);
+ xassert(0 <= j && j < n);
+ if (i == j) return 0;
+ if (i < j) k = i, i = j, j = k;
+ k = (i * (i - 1)) / 2 + j;
+ return a[k / CHAR_BIT] &
+ (unsigned char)(1 << ((CHAR_BIT - 1) - k % CHAR_BIT));
+}
+#else
+#define is_edge(csa, i, j) ((i) == (j) ? 0 : \
+ (i) > (j) ? is_edge1(i, j) : is_edge1(j, i))
+#define is_edge1(i, j) is_edge2(((i) * ((i) - 1)) / 2 + (j))
+#define is_edge2(k) (a[(k) / CHAR_BIT] & \
+ (unsigned char)(1 << ((CHAR_BIT - 1) - (k) % CHAR_BIT)))
+#endif
+
+static void sub(struct csa *csa, int ct, int table[], int level,
+ int weight, int l_weight)
+{ int i, j, k, curr_weight, left_weight, *p1, *p2, *newtable;
+ newtable = xcalloc(n, sizeof(int));
+ if (ct <= 0)
+ { /* 0 or 1 elements left; include these */
+ if (ct == 0)
+ { set[level++] = table[0];
+ weight += l_weight;
+ }
+ if (weight > record)
+ { record = weight;
+ rec_level = level;
+ for (i = 0; i < level; i++) rec[i] = set[i];
+ }
+ goto done;
+ }
+ for (i = ct; i >= 0; i--)
+ { if ((level == 0) && (i < ct)) goto done;
+ k = table[i];
+ if ((level > 0) && (clique[k] <= (record - weight)))
+ goto done; /* prune */
+ set[level] = k;
+ curr_weight = weight + wt[k];
+ l_weight -= wt[k];
+ if (l_weight <= (record - curr_weight))
+ goto done; /* prune */
+ p1 = newtable;
+ p2 = table;
+ left_weight = 0;
+ while (p2 < table + i)
+ { j = *p2++;
+ if (is_edge(csa, j, k))
+ { *p1++ = j;
+ left_weight += wt[j];
+ }
+ }
+ if (left_weight <= (record - curr_weight)) continue;
+ sub(csa, p1 - newtable - 1, newtable, level + 1, curr_weight,
+ left_weight);
+ }
+done: xfree(newtable);
+ return;
+}
+
+int wclique(int n_, const int w[], const unsigned char a_[], int ind[])
+{ struct csa csa_, *csa = &csa_;
+ int i, j, p, max_wt, max_nwt, wth, *used, *nwt, *pos;
+ double timer;
+ n = n_;
+ xassert(n > 0);
+ wt = &w[1];
+ a = a_;
+ record = 0;
+ rec_level = 0;
+ rec = &ind[1];
+ clique = xcalloc(n, sizeof(int));
+ set = xcalloc(n, sizeof(int));
+ used = xcalloc(n, sizeof(int));
+ nwt = xcalloc(n, sizeof(int));
+ pos = xcalloc(n, sizeof(int));
+ /* start timer */
+ timer = xtime();
+ /* order vertices */
+ for (i = 0; i < n; i++)
+ { nwt[i] = 0;
+ for (j = 0; j < n; j++)
+ if (is_edge(csa, i, j)) nwt[i] += wt[j];
+ }
+ for (i = 0; i < n; i++)
+ used[i] = 0;
+ for (i = n-1; i >= 0; i--)
+ { max_wt = -1;
+ max_nwt = -1;
+ for (j = 0; j < n; j++)
+ { if ((!used[j]) && ((wt[j] > max_wt) || (wt[j] == max_wt
+ && nwt[j] > max_nwt)))
+ { max_wt = wt[j];
+ max_nwt = nwt[j];
+ p = j;
+ }
+ }
+ pos[i] = p;
+ used[p] = 1;
+ for (j = 0; j < n; j++)
+ if ((!used[j]) && (j != p) && (is_edge(csa, p, j)))
+ nwt[j] -= wt[p];
+ }
+ /* main routine */
+ wth = 0;
+ for (i = 0; i < n; i++)
+ { wth += wt[pos[i]];
+ sub(csa, i, pos, 0, 0, wth);
+ clique[pos[i]] = record;
+ if (xdifftime(xtime(), timer) >= 5.0 - 0.001)
+ { /* print current record and reset timer */
+ xprintf("level = %d (%d); best = %d\n", i+1, n, record);
+ timer = xtime();
+ }
+ }
+ xfree(clique);
+ xfree(set);
+ xfree(used);
+ xfree(nwt);
+ xfree(pos);
+ /* return the solution found */
+ for (i = 1; i <= rec_level; i++) ind[i]++;
+ return rec_level;
+}
+
+#undef n
+#undef wt
+#undef a
+#undef record
+#undef rec_level
+#undef rec
+#undef clique
+#undef set
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/wclique.h b/test/monniaux/glpk-4.65/src/misc/wclique.h
new file mode 100644
index 00000000..d52dc805
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/wclique.h
@@ -0,0 +1,33 @@
+/* wclique.h (maximum weight clique, Ostergard's algorithm) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2009-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#ifndef WCLIQUE_H
+#define WCLIQUE_H
+
+#define wclique _glp_wclique
+int wclique(int n, const int w[], const unsigned char a[], int ind[]);
+/* find maximum weight clique with Ostergard's algorithm */
+
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/wclique1.c b/test/monniaux/glpk-4.65/src/misc/wclique1.c
new file mode 100644
index 00000000..a3d89542
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/wclique1.c
@@ -0,0 +1,317 @@
+/* wclique1.c (maximum weight clique, greedy heuristic) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2012-2018 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#include "env.h"
+#include "wclique1.h"
+
+/***********************************************************************
+* NAME
+*
+* wclique1 - find maximum weight clique with greedy heuristic
+*
+* SYNOPSIS
+*
+* #include "wclique1.h"
+* int wclique1(int n, const double w[],
+* int (*func)(void *info, int i, int ind[]), void *info, int c[]);
+*
+* DESCRIPTION
+*
+* The routine wclique1 implements a sequential greedy heuristic to
+* find maximum weight clique in a given (undirected) graph G = (V, E).
+*
+* The parameter n specifies the number of vertices |V| in the graph,
+* n >= 0.
+*
+* The array w specifies vertex weights in locations w[i], i = 1,...,n.
+* All weights must be non-negative.
+*
+* The formal routine func specifies the graph. For a given vertex i,
+* 1 <= i <= n, it stores indices of all vertices adjacent to vertex i
+* in locations ind[1], ..., ind[deg], where deg is the degree of
+* vertex i, 0 <= deg < n, returned on exit. Note that self-loops and
+* multiple edges are not allowed.
+*
+* The parameter info is a cookie passed to the routine func.
+*
+* On exit the routine wclique1 stores vertex indices included in
+* the clique found to locations c[1], ..., c[size], where size is the
+* clique size returned by the routine, 0 <= size <= n.
+*
+* RETURNS
+*
+* The routine wclique1 returns the size of the clique found. */
+
+struct vertex { int i; double cw; };
+
+static int CDECL fcmp(const void *xx, const void *yy)
+{ const struct vertex *x = xx, *y = yy;
+ if (x->cw > y->cw) return -1;
+ if (x->cw < y->cw) return +1;
+ return 0;
+}
+
+int wclique1(int n, const double w[],
+ int (*func)(void *info, int i, int ind[]), void *info, int c[])
+{ struct vertex *v_list;
+ int deg, c_size, d_size, i, j, k, kk, l, *ind, *c_list, *d_list,
+ size = 0;
+ double c_wght, d_wght, *sw, best = 0.0;
+ char *d_flag, *skip;
+ /* perform sanity checks */
+ xassert(n >= 0);
+ for (i = 1; i <= n; i++)
+ xassert(w[i] >= 0.0);
+ /* if the graph is empty, nothing to do */
+ if (n == 0) goto done;
+ /* allocate working arrays */
+ ind = xcalloc(1+n, sizeof(int));
+ v_list = xcalloc(1+n, sizeof(struct vertex));
+ c_list = xcalloc(1+n, sizeof(int));
+ d_list = xcalloc(1+n, sizeof(int));
+ d_flag = xcalloc(1+n, sizeof(char));
+ skip = xcalloc(1+n, sizeof(char));
+ sw = xcalloc(1+n, sizeof(double));
+ /* build the vertex list */
+ for (i = 1; i <= n; i++)
+ { v_list[i].i = i;
+ /* compute the cumulative weight of each vertex i, which is
+ * cw[i] = w[i] + sum{j : (i,j) in E} w[j] */
+ v_list[i].cw = w[i];
+ deg = func(info, i, ind);
+ xassert(0 <= deg && deg < n);
+ for (k = 1; k <= deg; k++)
+ { j = ind[k];
+ xassert(1 <= j && j <= n && j != i);
+ v_list[i].cw += w[j];
+ }
+ }
+ /* sort the vertex list to access vertices in descending order of
+ * cumulative weights */
+ qsort(&v_list[1], n, sizeof(struct vertex), fcmp);
+ /* initially all vertices are unmarked */
+ memset(&skip[1], 0, sizeof(char) * n);
+ /* clear flags of all vertices */
+ memset(&d_flag[1], 0, sizeof(char) * n);
+ /* look through all vertices of the graph */
+ for (l = 1; l <= n; l++)
+ { /* take vertex i */
+ i = v_list[l].i;
+ /* if this vertex was already included in one of previosuly
+ * constructed cliques, skip it */
+ if (skip[i]) continue;
+ /* use vertex i as the initial clique vertex */
+ c_size = 1; /* size of current clique */
+ c_list[1] = i; /* list of vertices in current clique */
+ c_wght = w[i]; /* weight of current clique */
+ /* determine the candidate set D = { j : (i,j) in E } */
+ d_size = func(info, i, d_list);
+ xassert(0 <= d_size && d_size < n);
+ d_wght = 0.0; /* weight of set D */
+ for (k = 1; k <= d_size; k++)
+ { j = d_list[k];
+ xassert(1 <= j && j <= n && j != i);
+ xassert(!d_flag[j]);
+ d_flag[j] = 1;
+ d_wght += w[j];
+ }
+ /* check an upper bound to the final clique weight */
+ if (c_wght + d_wght < best + 1e-5 * (1.0 + fabs(best)))
+ { /* skip constructing the current clique */
+ goto next;
+ }
+ /* compute the summary weight of each vertex i in D, which is
+ * sw[i] = w[i] + sum{j in D and (i,j) in E} w[j] */
+ for (k = 1; k <= d_size; k++)
+ { i = d_list[k];
+ sw[i] = w[i];
+ /* consider vertices adjacent to vertex i */
+ deg = func(info, i, ind);
+ xassert(0 <= deg && deg < n);
+ for (kk = 1; kk <= deg; kk++)
+ { j = ind[kk];
+ xassert(1 <= j && j <= n && j != i);
+ if (d_flag[j]) sw[i] += w[j];
+ }
+ }
+ /* grow the current clique by adding vertices from D */
+ while (d_size > 0)
+ { /* check an upper bound to the final clique weight */
+ if (c_wght + d_wght < best + 1e-5 * (1.0 + fabs(best)))
+ { /* skip constructing the current clique */
+ goto next;
+ }
+ /* choose vertex i in D having maximal summary weight */
+ i = d_list[1];
+ for (k = 2; k <= d_size; k++)
+ { j = d_list[k];
+ if (sw[i] < sw[j]) i = j;
+ }
+ /* include vertex i in the current clique */
+ c_size++;
+ c_list[c_size] = i;
+ c_wght += w[i];
+ /* remove all vertices not adjacent to vertex i, including
+ * vertex i itself, from the candidate set D */
+ deg = func(info, i, ind);
+ xassert(0 <= deg && deg < n);
+ for (k = 1; k <= deg; k++)
+ { j = ind[k];
+ xassert(1 <= j && j <= n && j != i);
+ /* vertex j is adjacent to vertex i */
+ if (d_flag[j])
+ { xassert(d_flag[j] == 1);
+ /* mark vertex j to keep it in D */
+ d_flag[j] = 2;
+ }
+ }
+ kk = d_size, d_size = 0;
+ for (k = 1; k <= kk; k++)
+ { j = d_list[k];
+ if (d_flag[j] == 1)
+ { /* remove vertex j from D */
+ d_flag[j] = 0;
+ d_wght -= w[j];
+ }
+ else if (d_flag[j] == 2)
+ { /* keep vertex j in D */
+ d_list[++d_size] = j;
+ d_flag[j] = 1;
+ }
+ else
+ xassert(d_flag != d_flag);
+ }
+ }
+ /* the current clique has been completely constructed */
+ if (best < c_wght)
+ { best = c_wght;
+ size = c_size;
+ xassert(1 <= size && size <= n);
+ memcpy(&c[1], &c_list[1], size * sizeof(int));
+ }
+next: /* mark the current clique vertices in order not to use them
+ * as initial vertices anymore */
+ for (k = 1; k <= c_size; k++)
+ skip[c_list[k]] = 1;
+ /* set D can be non-empty, so clean up vertex flags */
+ for (k = 1; k <= d_size; k++)
+ d_flag[d_list[k]] = 0;
+ }
+ /* free working arrays */
+ xfree(ind);
+ xfree(v_list);
+ xfree(c_list);
+ xfree(d_list);
+ xfree(d_flag);
+ xfree(skip);
+ xfree(sw);
+done: /* return to the calling program */
+ return size;
+}
+
+/**********************************************************************/
+
+#ifdef GLP_TEST
+#include "glpk.h"
+#include "rng.h"
+
+typedef struct { double w; } v_data;
+
+#define weight(v) (((v_data *)((v)->data))->w)
+
+glp_graph *G;
+
+char *flag;
+
+int func(void *info, int i, int ind[])
+{ glp_arc *e;
+ int j, k, deg = 0;
+ xassert(info == NULL);
+ xassert(1 <= i && i <= G->nv);
+ /* look through incoming arcs */
+ for (e = G->v[i]->in; e != NULL; e = e->h_next)
+ { j = e->tail->i; /* j->i */
+ if (j != i && !flag[j]) ind[++deg] = j, flag[j] = 1;
+ }
+ /* look through outgoing arcs */
+ for (e = G->v[i]->out; e != NULL; e = e->t_next)
+ { j = e->head->i; /* i->j */
+ if (j != i && !flag[j]) ind[++deg] = j, flag[j] = 1;
+ }
+ /* clear the flag array */
+ xassert(deg < G->nv);
+ for (k = 1; k <= deg; k++) flag[ind[k]] = 0;
+ return deg;
+}
+
+int main(int argc, char *argv[])
+{ RNG *rand;
+ int i, k, kk, size, *c, *ind, deg;
+ double *w, sum, t;
+ /* read graph in DIMACS format */
+ G = glp_create_graph(sizeof(v_data), 0);
+ xassert(argc == 2);
+ xassert(glp_read_ccdata(G, offsetof(v_data, w), argv[1]) == 0);
+ /* print the number of connected components */
+ xprintf("nc = %d\n", glp_weak_comp(G, -1));
+ /* assign random weights unformly distributed in [1,100] */
+ w = xcalloc(1+G->nv, sizeof(double));
+ rand = rng_create_rand();
+ for (i = 1; i <= G->nv; i++)
+#if 0
+ w[i] = weight(G->v[i]) = 1.0;
+#else
+ w[i] = weight(G->v[i]) = rng_unif_rand(rand, 100) + 1;
+#endif
+ /* write graph in DIMACS format */
+ xassert(glp_write_ccdata(G, offsetof(v_data, w), "graph") == 0);
+ /* find maximum weight clique */
+ c = xcalloc(1+G->nv, sizeof(int));
+ flag = xcalloc(1+G->nv, sizeof(char));
+ memset(&flag[1], 0, G->nv);
+ t = xtime();
+ size = wclique1(G->nv, w, func, NULL, c);
+ xprintf("Time used: %.1f s\n", xdifftime(xtime(), t));
+ /* check the clique found */
+ ind = xcalloc(1+G->nv, sizeof(int));
+ for (k = 1; k <= size; k++)
+ { i = c[k];
+ deg = func(NULL, i, ind);
+ for (kk = 1; kk <= size; kk++)
+ flag[c[kk]] = 1;
+ flag[i] = 0;
+ for (kk = 1; kk <= deg; kk++)
+ flag[ind[kk]] = 0;
+ for (kk = 1; kk <= size; kk++)
+ xassert(flag[c[kk]] == 0);
+ }
+ /* compute the clique weight */
+ sum = 0.0;
+ for (i = 1; i <= size; i++)
+ sum += w[c[i]];
+ xprintf("size = %d; sum = %g\n", size, sum);
+ return 0;
+}
+#endif
+
+/* eof */
diff --git a/test/monniaux/glpk-4.65/src/misc/wclique1.h b/test/monniaux/glpk-4.65/src/misc/wclique1.h
new file mode 100644
index 00000000..588f3257
--- /dev/null
+++ b/test/monniaux/glpk-4.65/src/misc/wclique1.h
@@ -0,0 +1,34 @@
+/* wclique1.h (maximum weight clique, greedy heuristic) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+*
+* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied
+* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights
+* reserved. E-mail: <mao@gnu.org>.
+*
+* GLPK is free software: you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* GLPK is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+* License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+#ifndef WCLIQUE1_H
+#define WCLIQUE1_H
+
+#define wclique1 _glp_wclique1
+int wclique1(int n, const double w[],
+ int (*func)(void *info, int i, int ind[]), void *info, int c[]);
+/* find maximum weight clique with greedy heuristic */
+
+#endif
+
+/* eof */