summaryrefslogtreecommitdiff
path: root/glpk-5.0/src/misc
diff options
context:
space:
mode:
Diffstat (limited to 'glpk-5.0/src/misc')
-rw-r--r--glpk-5.0/src/misc/avl.c403
-rw-r--r--glpk-5.0/src/misc/avl.h71
-rw-r--r--glpk-5.0/src/misc/bignum.c284
-rw-r--r--glpk-5.0/src/misc/bignum.h35
-rw-r--r--glpk-5.0/src/misc/dimacs.c145
-rw-r--r--glpk-5.0/src/misc/dimacs.h79
-rw-r--r--glpk-5.0/src/misc/dmp.c241
-rw-r--r--glpk-5.0/src/misc/dmp.h61
-rw-r--r--glpk-5.0/src/misc/ffalg.c219
-rw-r--r--glpk-5.0/src/misc/ffalg.h32
-rw-r--r--glpk-5.0/src/misc/fp2rat.c162
-rw-r--r--glpk-5.0/src/misc/fvs.c135
-rw-r--r--glpk-5.0/src/misc/fvs.h74
-rw-r--r--glpk-5.0/src/misc/gcd.c100
-rw-r--r--glpk-5.0/src/misc/hbm.c530
-rw-r--r--glpk-5.0/src/misc/hbm.h124
-rw-r--r--glpk-5.0/src/misc/jd.c150
-rw-r--r--glpk-5.0/src/misc/jd.h30
-rw-r--r--glpk-5.0/src/misc/keller.c233
-rw-r--r--glpk-5.0/src/misc/keller.h32
-rw-r--r--glpk-5.0/src/misc/ks.c464
-rw-r--r--glpk-5.0/src/misc/ks.h42
-rw-r--r--glpk-5.0/src/misc/mc13d.c314
-rw-r--r--glpk-5.0/src/misc/mc13d.h32
-rw-r--r--glpk-5.0/src/misc/mc21a.c301
-rw-r--r--glpk-5.0/src/misc/mc21a.h32
-rw-r--r--glpk-5.0/src/misc/misc.h59
-rw-r--r--glpk-5.0/src/misc/mt1.c1110
-rw-r--r--glpk-5.0/src/misc/mt1.f277
-rw-r--r--glpk-5.0/src/misc/mt1.h32
-rw-r--r--glpk-5.0/src/misc/mygmp.c1160
-rw-r--r--glpk-5.0/src/misc/mygmp.h252
-rw-r--r--glpk-5.0/src/misc/okalg.c380
-rw-r--r--glpk-5.0/src/misc/okalg.h33
-rw-r--r--glpk-5.0/src/misc/qmd.c99
-rw-r--r--glpk-5.0/src/misc/qmd.h56
-rw-r--r--glpk-5.0/src/misc/relax4.c23
-rw-r--r--glpk-5.0/src/misc/relax4.h100
-rw-r--r--glpk-5.0/src/misc/rgr.c167
-rw-r--r--glpk-5.0/src/misc/rgr.h31
-rw-r--r--glpk-5.0/src/misc/rng.c227
-rw-r--r--glpk-5.0/src/misc/rng.h65
-rw-r--r--glpk-5.0/src/misc/rng1.c71
-rw-r--r--glpk-5.0/src/misc/round2n.c62
-rw-r--r--glpk-5.0/src/misc/spm.c844
-rw-r--r--glpk-5.0/src/misc/spm.h162
-rw-r--r--glpk-5.0/src/misc/str2int.c90
-rw-r--r--glpk-5.0/src/misc/str2num.c108
-rw-r--r--glpk-5.0/src/misc/strspx.c58
-rw-r--r--glpk-5.0/src/misc/strtrim.c60
-rw-r--r--glpk-5.0/src/misc/triang.c309
-rw-r--r--glpk-5.0/src/misc/triang.h32
-rw-r--r--glpk-5.0/src/misc/wclique.c242
-rw-r--r--glpk-5.0/src/misc/wclique.h31
-rw-r--r--glpk-5.0/src/misc/wclique1.c315
-rw-r--r--glpk-5.0/src/misc/wclique1.h32
56 files changed, 10812 insertions, 0 deletions
diff --git a/glpk-5.0/src/misc/avl.c b/glpk-5.0/src/misc/avl.c
new file mode 100644
index 0000000..05ce7fb
--- /dev/null
+++ b/glpk-5.0/src/misc/avl.c
@@ -0,0 +1,403 @@
+/* avl.c (binary search tree) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2000-2013 Free Software Foundation, Inc.
+* Written 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 "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/glpk-5.0/src/misc/avl.h b/glpk-5.0/src/misc/avl.h
new file mode 100644
index 0000000..7f45963
--- /dev/null
+++ b/glpk-5.0/src/misc/avl.h
@@ -0,0 +1,71 @@
+/* avl.h (binary search tree) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2000-2013 Free Software Foundation, Inc.
+* Written 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/>.
+***********************************************************************/
+
+#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/glpk-5.0/src/misc/bignum.c b/glpk-5.0/src/misc/bignum.c
new file mode 100644
index 0000000..1d29a82
--- /dev/null
+++ b/glpk-5.0/src/misc/bignum.c
@@ -0,0 +1,284 @@
+/* bignum.c (bignum arithmetic) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2006-2013 Free Software Foundation, Inc.
+* Written 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 "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/glpk-5.0/src/misc/bignum.h b/glpk-5.0/src/misc/bignum.h
new file mode 100644
index 0000000..2e19e3a
--- /dev/null
+++ b/glpk-5.0/src/misc/bignum.h
@@ -0,0 +1,35 @@
+/* bignum.h (bignum arithmetic) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2006-2013 Free Software Foundation, Inc.
+* Written 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/>.
+***********************************************************************/
+
+#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/glpk-5.0/src/misc/dimacs.c b/glpk-5.0/src/misc/dimacs.c
new file mode 100644
index 0000000..66dfbb9
--- /dev/null
+++ b/glpk-5.0/src/misc/dimacs.c
@@ -0,0 +1,145 @@
+/* dimacs.c (reading data in DIMACS format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2009-2015 Free Software Foundation, Inc.
+* Written 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 "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/glpk-5.0/src/misc/dimacs.h b/glpk-5.0/src/misc/dimacs.h
new file mode 100644
index 0000000..2c86b28
--- /dev/null
+++ b/glpk-5.0/src/misc/dimacs.h
@@ -0,0 +1,79 @@
+/* dimacs.h (reading data in DIMACS format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2009-2015 Free Software Foundation, Inc.
+* Written 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/>.
+***********************************************************************/
+
+#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/glpk-5.0/src/misc/dmp.c b/glpk-5.0/src/misc/dmp.c
new file mode 100644
index 0000000..bfaf642
--- /dev/null
+++ b/glpk-5.0/src/misc/dmp.c
@@ -0,0 +1,241 @@
+/* dmp.c (dynamic memory pool) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2000-2013 Free Software Foundation, Inc.
+* Written 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 "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/glpk-5.0/src/misc/dmp.h b/glpk-5.0/src/misc/dmp.h
new file mode 100644
index 0000000..cde0991
--- /dev/null
+++ b/glpk-5.0/src/misc/dmp.h
@@ -0,0 +1,61 @@
+/* dmp.h (dynamic memory pool) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2000-2013 Free Software Foundation, Inc.
+* Written 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/>.
+***********************************************************************/
+
+#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/glpk-5.0/src/misc/ffalg.c b/glpk-5.0/src/misc/ffalg.c
new file mode 100644
index 0000000..bf3ed0c
--- /dev/null
+++ b/glpk-5.0/src/misc/ffalg.c
@@ -0,0 +1,219 @@
+/* ffalg.c (Ford-Fulkerson algorithm) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2009-2013 Free Software Foundation, Inc.
+* Written 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 "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/glpk-5.0/src/misc/ffalg.h b/glpk-5.0/src/misc/ffalg.h
new file mode 100644
index 0000000..32d5cfd
--- /dev/null
+++ b/glpk-5.0/src/misc/ffalg.h
@@ -0,0 +1,32 @@
+/* ffalg.h (Ford-Fulkerson algorithm) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2009-2013 Free Software Foundation, Inc.
+* Written 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/>.
+***********************************************************************/
+
+#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/glpk-5.0/src/misc/fp2rat.c b/glpk-5.0/src/misc/fp2rat.c
new file mode 100644
index 0000000..eae7660
--- /dev/null
+++ b/glpk-5.0/src/misc/fp2rat.c
@@ -0,0 +1,162 @@
+/* fp2rat.c (convert floating-point number to rational number) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2000-2013 Free Software Foundation, Inc.
+* Written 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 "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/glpk-5.0/src/misc/fvs.c b/glpk-5.0/src/misc/fvs.c
new file mode 100644
index 0000000..1b5f04b
--- /dev/null
+++ b/glpk-5.0/src/misc/fvs.c
@@ -0,0 +1,135 @@
+/* fvs.c (sparse vector in FVS format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2016 Free Software Foundation, Inc.
+* Written 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 "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/glpk-5.0/src/misc/fvs.h b/glpk-5.0/src/misc/fvs.h
new file mode 100644
index 0000000..5b59c68
--- /dev/null
+++ b/glpk-5.0/src/misc/fvs.h
@@ -0,0 +1,74 @@
+/* fvs.h (sparse vector in FVS format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2016 Free Software Foundation, Inc.
+* Written 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/>.
+***********************************************************************/
+
+#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/glpk-5.0/src/misc/gcd.c b/glpk-5.0/src/misc/gcd.c
new file mode 100644
index 0000000..78a4e51
--- /dev/null
+++ b/glpk-5.0/src/misc/gcd.c
@@ -0,0 +1,100 @@
+/* gcd.c (greatest common divisor) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2000 Free Software Foundation, Inc.
+* Written 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 "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/glpk-5.0/src/misc/hbm.c b/glpk-5.0/src/misc/hbm.c
new file mode 100644
index 0000000..aa0594d
--- /dev/null
+++ b/glpk-5.0/src/misc/hbm.c
@@ -0,0 +1,530 @@
+/* hbm.c (Harwell-Boeing sparse matrix format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2004-2018 Free Software Foundation, Inc.
+* Written 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 "hbm.h"
+#include "misc.h"
+
+/***********************************************************************
+* NAME
+*
+* hbm_read_mat - read sparse matrix in Harwell-Boeing format
+*
+* SYNOPSIS
+*
+* #include "glphbm.h"
+* HBM *hbm_read_mat(const char *fname);
+*
+* DESCRIPTION
+*
+* The routine hbm_read_mat reads a sparse matrix in the Harwell-Boeing
+* format from a text file whose name is the character string fname.
+*
+* Detailed description of the Harwell-Boeing format recognised by this
+* routine is given in the following report:
+*
+* I.S.Duff, R.G.Grimes, J.G.Lewis. User's Guide for the Harwell-Boeing
+* Sparse Matrix Collection (Release I), TR/PA/92/86, October 1992.
+*
+* RETURNS
+*
+* If no error occured, the routine hbm_read_mat returns a pointer to
+* a data structure containing the matrix. In case of error the routine
+* prints an appropriate error message and returns NULL. */
+
+struct dsa
+{ /* working area used by routine hbm_read_mat */
+ const char *fname;
+ /* name of input text file */
+ FILE *fp;
+ /* stream assigned to input text file */
+ int seqn;
+ /* card sequential number */
+ char card[80+1];
+ /* card image buffer */
+ int fmt_p;
+ /* scale factor */
+ int fmt_k;
+ /* iterator */
+ int fmt_f;
+ /* format code */
+ int fmt_w;
+ /* field width */
+ int fmt_d;
+ /* number of decimal places after point */
+};
+
+/***********************************************************************
+* read_card - read next data card
+*
+* This routine reads the next 80-column card from the input text file
+* and stores its image into the character string card. If the card was
+* read successfully, the routine returns zero, otherwise non-zero. */
+
+#if 1 /* 11/III-2012 */
+static int read_card(struct dsa *dsa)
+{ int c, len = 0;
+ char buf[255+1];
+ dsa->seqn++;
+ for (;;)
+ { c = fgetc(dsa->fp);
+ if (c == EOF)
+ { if (ferror(dsa->fp))
+ xprintf("%s:%d: read error\n",
+ dsa->fname, dsa->seqn);
+ else
+ xprintf("%s:%d: unexpected end-of-file\n",
+ dsa->fname, dsa->seqn);
+ return 1;
+ }
+ else if (c == '\r')
+ /* nop */;
+ else if (c == '\n')
+ break;
+ else if (iscntrl(c))
+ { xprintf("%s:%d: invalid control character\n",
+ dsa->fname, dsa->seqn, c);
+ return 1;
+ }
+ else
+ { if (len == sizeof(buf)-1)
+ goto err;
+ buf[len++] = (char)c;
+ }
+ }
+ /* remove trailing spaces */
+ while (len > 80 && buf[len-1] == ' ')
+ len--;
+ buf[len] = '\0';
+ /* line should not be longer than 80 chars */
+ if (len > 80)
+err: { xerror("%s:%d: card image too long\n",
+ dsa->fname, dsa->seqn);
+ return 1;
+ }
+ /* padd by spaces to 80-column card image */
+ strcpy(dsa->card, buf);
+ memset(&dsa->card[len], ' ', 80 - len);
+ dsa->card[80] = '\0';
+ return 0;
+}
+#endif
+
+/***********************************************************************
+* scan_int - scan integer value from the current card
+*
+* This routine scans an integer value from the current card, where fld
+* is the name of the field, pos is the position of the field, width is
+* the width of the field, val points to a location to which the scanned
+* value should be stored. If the value was scanned successfully, the
+* routine returns zero, otherwise non-zero. */
+
+static int scan_int(struct dsa *dsa, char *fld, int pos, int width,
+ int *val)
+{ char str[80+1];
+ xassert(1 <= width && width <= 80);
+ memcpy(str, dsa->card + pos, width), str[width] = '\0';
+ if (str2int(strspx(str), val))
+ { xprintf("%s:%d: field '%s' contains invalid value '%s'\n",
+ dsa->fname, dsa->seqn, fld, str);
+ return 1;
+ }
+ return 0;
+}
+
+/***********************************************************************
+* parse_fmt - parse Fortran format specification
+*
+* This routine parses the Fortran format specification represented as
+* character string which fmt points to and stores format elements into
+* appropriate static locations. Should note that not all valid Fortran
+* format specifications may be recognised. If the format specification
+* was recognised, the routine returns zero, otherwise non-zero. */
+
+static int parse_fmt(struct dsa *dsa, char *fmt)
+{ int k, s, val;
+ char str[80+1];
+ /* first character should be left parenthesis */
+ if (fmt[0] != '(')
+fail: { xprintf("hbm_read_mat: format '%s' not recognised\n", fmt);
+ return 1;
+ }
+ k = 1;
+ /* optional scale factor */
+ dsa->fmt_p = 0;
+ if (isdigit((unsigned char)fmt[k]))
+ { s = 0;
+ while (isdigit((unsigned char)fmt[k]))
+ { if (s == 80) goto fail;
+ str[s++] = fmt[k++];
+ }
+ str[s] = '\0';
+ if (str2int(str, &val)) goto fail;
+ if (toupper((unsigned char)fmt[k]) != 'P') goto iter;
+ dsa->fmt_p = val, k++;
+ if (!(0 <= dsa->fmt_p && dsa->fmt_p <= 255)) goto fail;
+ /* optional comma may follow scale factor */
+ if (fmt[k] == ',') k++;
+ }
+ /* optional iterator */
+ dsa->fmt_k = 1;
+ if (isdigit((unsigned char)fmt[k]))
+ { s = 0;
+ while (isdigit((unsigned char)fmt[k]))
+ { if (s == 80) goto fail;
+ str[s++] = fmt[k++];
+ }
+ str[s] = '\0';
+ if (str2int(str, &val)) goto fail;
+iter: dsa->fmt_k = val;
+ if (!(1 <= dsa->fmt_k && dsa->fmt_k <= 255)) goto fail;
+ }
+ /* format code */
+ dsa->fmt_f = toupper((unsigned char)fmt[k++]);
+ if (!(dsa->fmt_f == 'D' || dsa->fmt_f == 'E' ||
+ dsa->fmt_f == 'F' || dsa->fmt_f == 'G' ||
+ dsa->fmt_f == 'I')) goto fail;
+ /* field width */
+ if (!isdigit((unsigned char)fmt[k])) goto fail;
+ s = 0;
+ while (isdigit((unsigned char)fmt[k]))
+ { if (s == 80) goto fail;
+ str[s++] = fmt[k++];
+ }
+ str[s] = '\0';
+ if (str2int(str, &dsa->fmt_w)) goto fail;
+ if (!(1 <= dsa->fmt_w && dsa->fmt_w <= 255)) goto fail;
+ /* optional number of decimal places after point */
+ dsa->fmt_d = 0;
+ if (fmt[k] == '.')
+ { k++;
+ if (!isdigit((unsigned char)fmt[k])) goto fail;
+ s = 0;
+ while (isdigit((unsigned char)fmt[k]))
+ { if (s == 80) goto fail;
+ str[s++] = fmt[k++];
+ }
+ str[s] = '\0';
+ if (str2int(str, &dsa->fmt_d)) goto fail;
+ if (!(0 <= dsa->fmt_d && dsa->fmt_d <= 255)) goto fail;
+ }
+ /* last character should be right parenthesis */
+ if (!(fmt[k] == ')' && fmt[k+1] == '\0')) goto fail;
+ return 0;
+}
+
+/***********************************************************************
+* read_int_array - read array of integer type
+*
+* This routine reads an integer array from the input text file, where
+* name is array name, fmt is Fortran format specification that controls
+* reading, n is number of array elements, val is array of integer type.
+* If the array was read successful, the routine returns zero, otherwise
+* non-zero. */
+
+static int read_int_array(struct dsa *dsa, char *name, char *fmt,
+ int n, int val[])
+{ int k, pos;
+ char str[80+1];
+ if (parse_fmt(dsa, fmt)) return 1;
+ if (!(dsa->fmt_f == 'I' && dsa->fmt_w <= 80 &&
+ dsa->fmt_k * dsa->fmt_w <= 80))
+ { xprintf(
+ "%s:%d: can't read array '%s' - invalid format '%s'\n",
+ dsa->fname, dsa->seqn, name, fmt);
+ return 1;
+ }
+ for (k = 1, pos = INT_MAX; k <= n; k++, pos++)
+ { if (pos >= dsa->fmt_k)
+ { if (read_card(dsa)) return 1;
+ pos = 0;
+ }
+ memcpy(str, dsa->card + dsa->fmt_w * pos, dsa->fmt_w);
+ str[dsa->fmt_w] = '\0';
+ strspx(str);
+ if (str2int(str, &val[k]))
+ { xprintf(
+ "%s:%d: can't read array '%s' - invalid value '%s'\n",
+ dsa->fname, dsa->seqn, name, str);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/***********************************************************************
+* read_real_array - read array of real type
+*
+* This routine reads a real array from the input text file, where name
+* is array name, fmt is Fortran format specification that controls
+* reading, n is number of array elements, val is array of real type.
+* If the array was read successful, the routine returns zero, otherwise
+* non-zero. */
+
+static int read_real_array(struct dsa *dsa, char *name, char *fmt,
+ int n, double val[])
+{ int k, pos;
+ char str[80+1], *ptr;
+ if (parse_fmt(dsa, fmt)) return 1;
+ if (!(dsa->fmt_f != 'I' && dsa->fmt_w <= 80 &&
+ dsa->fmt_k * dsa->fmt_w <= 80))
+ { xprintf(
+ "%s:%d: can't read array '%s' - invalid format '%s'\n",
+ dsa->fname, dsa->seqn, name, fmt);
+ return 1;
+ }
+ for (k = 1, pos = INT_MAX; k <= n; k++, pos++)
+ { if (pos >= dsa->fmt_k)
+ { if (read_card(dsa)) return 1;
+ pos = 0;
+ }
+ memcpy(str, dsa->card + dsa->fmt_w * pos, dsa->fmt_w);
+ str[dsa->fmt_w] = '\0';
+ strspx(str);
+ if (strchr(str, '.') == NULL && strcmp(str, "0"))
+ { xprintf("%s(%d): can't read array '%s' - value '%s' has no "
+ "decimal point\n", dsa->fname, dsa->seqn, name, str);
+ return 1;
+ }
+ /* sometimes lower case letters appear */
+ for (ptr = str; *ptr; ptr++)
+ *ptr = (char)toupper((unsigned char)*ptr);
+ ptr = strchr(str, 'D');
+ if (ptr != NULL) *ptr = 'E';
+ /* value may appear with decimal exponent but without letters
+ E or D (for example, -123.456-012), so missing letter should
+ be inserted */
+ ptr = strchr(str+1, '+');
+ if (ptr == NULL) ptr = strchr(str+1, '-');
+ if (ptr != NULL && *(ptr-1) != 'E')
+ { xassert(strlen(str) < 80);
+ memmove(ptr+1, ptr, strlen(ptr)+1);
+ *ptr = 'E';
+ }
+ if (str2num(str, &val[k]))
+ { xprintf(
+ "%s:%d: can't read array '%s' - invalid value '%s'\n",
+ dsa->fname, dsa->seqn, name, str);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+HBM *hbm_read_mat(const char *fname)
+{ struct dsa _dsa, *dsa = &_dsa;
+ HBM *hbm = NULL;
+ dsa->fname = fname;
+ xprintf("hbm_read_mat: reading matrix from '%s'...\n",
+ dsa->fname);
+ dsa->fp = fopen(dsa->fname, "r");
+ if (dsa->fp == NULL)
+ { xprintf("hbm_read_mat: unable to open '%s' - %s\n",
+#if 0 /* 29/I-2017 */
+ dsa->fname, strerror(errno));
+#else
+ dsa->fname, xstrerr(errno));
+#endif
+ goto fail;
+ }
+ dsa->seqn = 0;
+ hbm = xmalloc(sizeof(HBM));
+ memset(hbm, 0, sizeof(HBM));
+ /* read the first heading card */
+ if (read_card(dsa)) goto fail;
+ memcpy(hbm->title, dsa->card, 72), hbm->title[72] = '\0';
+ strtrim(hbm->title);
+ xprintf("%s\n", hbm->title);
+ memcpy(hbm->key, dsa->card+72, 8), hbm->key[8] = '\0';
+ strspx(hbm->key);
+ xprintf("key = %s\n", hbm->key);
+ /* read the second heading card */
+ if (read_card(dsa)) goto fail;
+ if (scan_int(dsa, "totcrd", 0, 14, &hbm->totcrd)) goto fail;
+ if (scan_int(dsa, "ptrcrd", 14, 14, &hbm->ptrcrd)) goto fail;
+ if (scan_int(dsa, "indcrd", 28, 14, &hbm->indcrd)) goto fail;
+ if (scan_int(dsa, "valcrd", 42, 14, &hbm->valcrd)) goto fail;
+ if (scan_int(dsa, "rhscrd", 56, 14, &hbm->rhscrd)) goto fail;
+ xprintf("totcrd = %d; ptrcrd = %d; indcrd = %d; valcrd = %d; rhsc"
+ "rd = %d\n", hbm->totcrd, hbm->ptrcrd, hbm->indcrd,
+ hbm->valcrd, hbm->rhscrd);
+ /* read the third heading card */
+ if (read_card(dsa)) goto fail;
+ memcpy(hbm->mxtype, dsa->card, 3), hbm->mxtype[3] = '\0';
+ if (strchr("RCP", hbm->mxtype[0]) == NULL ||
+ strchr("SUHZR", hbm->mxtype[1]) == NULL ||
+ strchr("AE", hbm->mxtype[2]) == NULL)
+ { xprintf("%s:%d: matrix type '%s' not recognised\n",
+ dsa->fname, dsa->seqn, hbm->mxtype);
+ goto fail;
+ }
+ if (scan_int(dsa, "nrow", 14, 14, &hbm->nrow)) goto fail;
+ if (scan_int(dsa, "ncol", 28, 14, &hbm->ncol)) goto fail;
+ if (scan_int(dsa, "nnzero", 42, 14, &hbm->nnzero)) goto fail;
+ if (scan_int(dsa, "neltvl", 56, 14, &hbm->neltvl)) goto fail;
+ xprintf("mxtype = %s; nrow = %d; ncol = %d; nnzero = %d; neltvl ="
+ " %d\n", hbm->mxtype, hbm->nrow, hbm->ncol, hbm->nnzero,
+ hbm->neltvl);
+ /* read the fourth heading card */
+ if (read_card(dsa)) goto fail;
+ memcpy(hbm->ptrfmt, dsa->card, 16), hbm->ptrfmt[16] = '\0';
+ strspx(hbm->ptrfmt);
+ memcpy(hbm->indfmt, dsa->card+16, 16), hbm->indfmt[16] = '\0';
+ strspx(hbm->indfmt);
+ memcpy(hbm->valfmt, dsa->card+32, 20), hbm->valfmt[20] = '\0';
+ strspx(hbm->valfmt);
+ memcpy(hbm->rhsfmt, dsa->card+52, 20), hbm->rhsfmt[20] = '\0';
+ strspx(hbm->rhsfmt);
+ xprintf("ptrfmt = %s; indfmt = %s; valfmt = %s; rhsfmt = %s\n",
+ hbm->ptrfmt, hbm->indfmt, hbm->valfmt, hbm->rhsfmt);
+ /* read the fifth heading card (optional) */
+ if (hbm->rhscrd <= 0)
+ { strcpy(hbm->rhstyp, "???");
+ hbm->nrhs = 0;
+ hbm->nrhsix = 0;
+ }
+ else
+ { if (read_card(dsa)) goto fail;
+ memcpy(hbm->rhstyp, dsa->card, 3), hbm->rhstyp[3] = '\0';
+ if (scan_int(dsa, "nrhs", 14, 14, &hbm->nrhs)) goto fail;
+ if (scan_int(dsa, "nrhsix", 28, 14, &hbm->nrhsix)) goto fail;
+ xprintf("rhstyp = '%s'; nrhs = %d; nrhsix = %d\n",
+ hbm->rhstyp, hbm->nrhs, hbm->nrhsix);
+ }
+ /* read matrix structure */
+ hbm->colptr = xcalloc(1+hbm->ncol+1, sizeof(int));
+ if (read_int_array(dsa, "colptr", hbm->ptrfmt, hbm->ncol+1,
+ hbm->colptr)) goto fail;
+ hbm->rowind = xcalloc(1+hbm->nnzero, sizeof(int));
+ if (read_int_array(dsa, "rowind", hbm->indfmt, hbm->nnzero,
+ hbm->rowind)) goto fail;
+ /* read matrix values */
+ if (hbm->valcrd <= 0) goto done;
+ if (hbm->mxtype[2] == 'A')
+ { /* assembled matrix */
+ hbm->values = xcalloc(1+hbm->nnzero, sizeof(double));
+ if (read_real_array(dsa, "values", hbm->valfmt, hbm->nnzero,
+ hbm->values)) goto fail;
+ }
+ else
+ { /* elemental (unassembled) matrix */
+ hbm->values = xcalloc(1+hbm->neltvl, sizeof(double));
+ if (read_real_array(dsa, "values", hbm->valfmt, hbm->neltvl,
+ hbm->values)) goto fail;
+ }
+ /* read right-hand sides */
+ if (hbm->nrhs <= 0) goto done;
+ if (hbm->rhstyp[0] == 'F')
+ { /* dense format */
+ hbm->nrhsvl = hbm->nrow * hbm->nrhs;
+ hbm->rhsval = xcalloc(1+hbm->nrhsvl, sizeof(double));
+ if (read_real_array(dsa, "rhsval", hbm->rhsfmt, hbm->nrhsvl,
+ hbm->rhsval)) goto fail;
+ }
+ else if (hbm->rhstyp[0] == 'M' && hbm->mxtype[2] == 'A')
+ { /* sparse format */
+ /* read pointers */
+ hbm->rhsptr = xcalloc(1+hbm->nrhs+1, sizeof(int));
+ if (read_int_array(dsa, "rhsptr", hbm->ptrfmt, hbm->nrhs+1,
+ hbm->rhsptr)) goto fail;
+ /* read sparsity pattern */
+ hbm->rhsind = xcalloc(1+hbm->nrhsix, sizeof(int));
+ if (read_int_array(dsa, "rhsind", hbm->indfmt, hbm->nrhsix,
+ hbm->rhsind)) goto fail;
+ /* read values */
+ hbm->rhsval = xcalloc(1+hbm->nrhsix, sizeof(double));
+ if (read_real_array(dsa, "rhsval", hbm->rhsfmt, hbm->nrhsix,
+ hbm->rhsval)) goto fail;
+ }
+ else if (hbm->rhstyp[0] == 'M' && hbm->mxtype[2] == 'E')
+ { /* elemental format */
+ hbm->rhsval = xcalloc(1+hbm->nrhsvl, sizeof(double));
+ if (read_real_array(dsa, "rhsval", hbm->rhsfmt, hbm->nrhsvl,
+ hbm->rhsval)) goto fail;
+ }
+ else
+ { xprintf("%s:%d: right-hand side type '%c' not recognised\n",
+ dsa->fname, dsa->seqn, hbm->rhstyp[0]);
+ goto fail;
+ }
+ /* read starting guesses */
+ if (hbm->rhstyp[1] == 'G')
+ { hbm->nguess = hbm->nrow * hbm->nrhs;
+ hbm->sguess = xcalloc(1+hbm->nguess, sizeof(double));
+ if (read_real_array(dsa, "sguess", hbm->rhsfmt, hbm->nguess,
+ hbm->sguess)) goto fail;
+ }
+ /* read solution vectors */
+ if (hbm->rhstyp[2] == 'X')
+ { hbm->nexact = hbm->nrow * hbm->nrhs;
+ hbm->xexact = xcalloc(1+hbm->nexact, sizeof(double));
+ if (read_real_array(dsa, "xexact", hbm->rhsfmt, hbm->nexact,
+ hbm->xexact)) goto fail;
+ }
+done: /* reading has been completed */
+ xprintf("hbm_read_mat: %d cards were read\n", dsa->seqn);
+ fclose(dsa->fp);
+ return hbm;
+fail: /* something wrong in Danish kingdom */
+ if (hbm != NULL)
+ { if (hbm->colptr != NULL) xfree(hbm->colptr);
+ if (hbm->rowind != NULL) xfree(hbm->rowind);
+ if (hbm->rhsptr != NULL) xfree(hbm->rhsptr);
+ if (hbm->rhsind != NULL) xfree(hbm->rhsind);
+ if (hbm->values != NULL) xfree(hbm->values);
+ if (hbm->rhsval != NULL) xfree(hbm->rhsval);
+ if (hbm->sguess != NULL) xfree(hbm->sguess);
+ if (hbm->xexact != NULL) xfree(hbm->xexact);
+ xfree(hbm);
+ }
+ if (dsa->fp != NULL) fclose(dsa->fp);
+ return NULL;
+}
+
+/***********************************************************************
+* NAME
+*
+* hbm_free_mat - free sparse matrix in Harwell-Boeing format
+*
+* SYNOPSIS
+*
+* #include "glphbm.h"
+* void hbm_free_mat(HBM *hbm);
+*
+* DESCRIPTION
+*
+* The hbm_free_mat routine frees all the memory allocated to the data
+* structure containing a sparse matrix in the Harwell-Boeing format. */
+
+void hbm_free_mat(HBM *hbm)
+{ if (hbm->colptr != NULL) xfree(hbm->colptr);
+ if (hbm->rowind != NULL) xfree(hbm->rowind);
+ if (hbm->rhsptr != NULL) xfree(hbm->rhsptr);
+ if (hbm->rhsind != NULL) xfree(hbm->rhsind);
+ if (hbm->values != NULL) xfree(hbm->values);
+ if (hbm->rhsval != NULL) xfree(hbm->rhsval);
+ if (hbm->sguess != NULL) xfree(hbm->sguess);
+ if (hbm->xexact != NULL) xfree(hbm->xexact);
+ xfree(hbm);
+ return;
+}
+
+/* eof */
diff --git a/glpk-5.0/src/misc/hbm.h b/glpk-5.0/src/misc/hbm.h
new file mode 100644
index 0000000..cd6d55f
--- /dev/null
+++ b/glpk-5.0/src/misc/hbm.h
@@ -0,0 +1,124 @@
+/* hbm.h (Harwell-Boeing sparse matrix format) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2004-2018 Free Software Foundation, Inc.
+* Written 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/>.
+***********************************************************************/
+
+#ifndef HBM_H
+#define HBM_H
+
+typedef struct HBM HBM;
+
+struct HBM
+{ /* sparse matrix in Harwell-Boeing format; for details see the
+ report: I.S.Duff, R.G.Grimes, J.G.Lewis. User's Guide for the
+ Harwell-Boeing Sparse Matrix Collection (Release I), 1992 */
+ char title[72+1];
+ /* matrix title (informative) */
+ char key[8+1];
+ /* matrix key (informative) */
+ char mxtype[3+1];
+ /* matrix type:
+ R.. real matrix
+ C.. complex matrix
+ P.. pattern only (no numerical values supplied)
+ .S. symmetric (lower triangle + main diagonal)
+ .U. unsymmetric
+ .H. hermitian (lower triangle + main diagonal)
+ .Z. skew symmetric (lower triangle only)
+ .R. rectangular
+ ..A assembled
+ ..E elemental (unassembled) */
+ char rhstyp[3+1];
+ /* optional types:
+ F.. right-hand sides in dense format
+ M.. right-hand sides in same format as matrix
+ .G. starting vector(s) (guess) is supplied
+ ..X exact solution vector(s) is supplied */
+ char ptrfmt[16+1];
+ /* format for pointers */
+ char indfmt[16+1];
+ /* format for row (or variable) indices */
+ char valfmt[20+1];
+ /* format for numerical values of coefficient matrix */
+ char rhsfmt[20+1];
+ /* format for numerical values of right-hand sides */
+ int totcrd;
+ /* total number of cards excluding header */
+ int ptrcrd;
+ /* number of cards for ponters */
+ int indcrd;
+ /* number of cards for row (or variable) indices */
+ int valcrd;
+ /* number of cards for numerical values */
+ int rhscrd;
+ /* number of lines for right-hand sides;
+ including starting guesses and solution vectors if present;
+ zero indicates no right-hand side data is present */
+ int nrow;
+ /* number of rows (or variables) */
+ int ncol;
+ /* number of columns (or elements) */
+ int nnzero;
+ /* number of row (or variable) indices;
+ equal to number of entries for assembled matrix */
+ int neltvl;
+ /* number of elemental matrix entries;
+ zero in case of assembled matrix */
+ int nrhs;
+ /* number of right-hand sides */
+ int nrhsix;
+ /* number of row indices;
+ ignored in case of unassembled matrix */
+ int nrhsvl;
+ /* total number of entries in all right-hand sides */
+ int nguess;
+ /* total number of entries in all starting guesses */
+ int nexact;
+ /* total number of entries in all solution vectors */
+ int *colptr; /* alias: eltptr */
+ /* column pointers (in case of assembled matrix);
+ elemental matrix pointers (in case of unassembled matrix) */
+ int *rowind; /* alias: varind */
+ /* row indices (in case of assembled matrix);
+ variable indices (in case of unassembled matrix) */
+ int *rhsptr;
+ /* right-hand side pointers */
+ int *rhsind;
+ /* right-hand side indices */
+ double *values;
+ /* matrix values */
+ double *rhsval;
+ /* right-hand side values */
+ double *sguess;
+ /* starting guess values */
+ double *xexact;
+ /* solution vector values */
+};
+
+#define hbm_read_mat _glp_hbm_read_mat
+HBM *hbm_read_mat(const char *fname);
+/* read sparse matrix in Harwell-Boeing format */
+
+#define hbm_free_mat _glp_hbm_free_mat
+void hbm_free_mat(HBM *hbm);
+/* free sparse matrix in Harwell-Boeing format */
+
+#endif
+
+/* eof */
diff --git a/glpk-5.0/src/misc/jd.c b/glpk-5.0/src/misc/jd.c
new file mode 100644
index 0000000..b637387
--- /dev/null
+++ b/glpk-5.0/src/misc/jd.c
@@ -0,0 +1,150 @@
+/* jd.c (conversions between calendar date and Julian day number) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2000 Free Software Foundation, Inc.
+* Written 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 <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/glpk-5.0/src/misc/jd.h b/glpk-5.0/src/misc/jd.h
new file mode 100644
index 0000000..f59b063
--- /dev/null
+++ b/glpk-5.0/src/misc/jd.h
@@ -0,0 +1,30 @@
+/* jd.h (conversions between calendar date and Julian day number) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2000 Free Software Foundation, Inc.
+* Written 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/>.
+***********************************************************************/
+
+#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/glpk-5.0/src/misc/keller.c b/glpk-5.0/src/misc/keller.c
new file mode 100644
index 0000000..bb4576b
--- /dev/null
+++ b/glpk-5.0/src/misc/keller.c
@@ -0,0 +1,233 @@
+/* keller.c (cover edges by cliques, Kellerman's heuristic) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2009-2013 Free Software Foundation, Inc.
+* Written 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 "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/glpk-5.0/src/misc/keller.h b/glpk-5.0/src/misc/keller.h
new file mode 100644
index 0000000..2768f35
--- /dev/null
+++ b/glpk-5.0/src/misc/keller.h
@@ -0,0 +1,32 @@
+/* keller.h (cover edges by cliques, Kellerman's heuristic) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2009-2013 Free Software Foundation, Inc.
+* Written 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/>.
+***********************************************************************/
+
+#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/glpk-5.0/src/misc/ks.c b/glpk-5.0/src/misc/ks.c
new file mode 100644
index 0000000..894c91a
--- /dev/null
+++ b/glpk-5.0/src/misc/ks.c
@@ -0,0 +1,464 @@
+/* ks.c (0-1 knapsack problem) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2017-2018 Free Software Foundation, Inc.
+* Written 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 "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/glpk-5.0/src/misc/ks.h b/glpk-5.0/src/misc/ks.h
new file mode 100644
index 0000000..37368d2
--- /dev/null
+++ b/glpk-5.0/src/misc/ks.h
@@ -0,0 +1,42 @@
+/* ks.h (0-1 knapsack problem) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2017-2018 Free Software Foundation, Inc.
+* Written 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/>.
+***********************************************************************/
+
+#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/glpk-5.0/src/misc/mc13d.c b/glpk-5.0/src/misc/mc13d.c
new file mode 100644
index 0000000..d8bab39
--- /dev/null
+++ b/glpk-5.0/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/glpk-5.0/src/misc/mc13d.h b/glpk-5.0/src/misc/mc13d.h
new file mode 100644
index 0000000..ceb9df4
--- /dev/null
+++ b/glpk-5.0/src/misc/mc13d.h
@@ -0,0 +1,32 @@
+/* mc13d.h */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2009-2013 Free Software Foundation, Inc.
+* Written 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/>.
+***********************************************************************/
+
+#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/glpk-5.0/src/misc/mc21a.c b/glpk-5.0/src/misc/mc21a.c
new file mode 100644
index 0000000..700d0f4
--- /dev/null
+++ b/glpk-5.0/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/glpk-5.0/src/misc/mc21a.h b/glpk-5.0/src/misc/mc21a.h
new file mode 100644
index 0000000..882bf3a
--- /dev/null
+++ b/glpk-5.0/src/misc/mc21a.h
@@ -0,0 +1,32 @@
+/* mc21a.h (permutations for zero-free diagonal) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2009-2013 Free Software Foundation, Inc.
+* Written 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/>.
+***********************************************************************/
+
+#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/glpk-5.0/src/misc/misc.h b/glpk-5.0/src/misc/misc.h
new file mode 100644
index 0000000..dd16a24
--- /dev/null
+++ b/glpk-5.0/src/misc/misc.h
@@ -0,0 +1,59 @@
+/* misc.h (miscellaneous routines) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2000-2013 Free Software Foundation, Inc.
+* Written 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/>.
+***********************************************************************/
+
+#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/glpk-5.0/src/misc/mt1.c b/glpk-5.0/src/misc/mt1.c
new file mode 100644
index 0000000..63a0f80
--- /dev/null
+++ b/glpk-5.0/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/glpk-5.0/src/misc/mt1.f b/glpk-5.0/src/misc/mt1.f
new file mode 100644
index 0000000..82cc4a1
--- /dev/null
+++ b/glpk-5.0/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/glpk-5.0/src/misc/mt1.h b/glpk-5.0/src/misc/mt1.h
new file mode 100644
index 0000000..37bc44c
--- /dev/null
+++ b/glpk-5.0/src/misc/mt1.h
@@ -0,0 +1,32 @@
+/* mt1.h (0-1 knapsack problem; Martello & Toth algorithm) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2017-2018 Free Software Foundation, Inc.
+* Written 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/>.
+***********************************************************************/
+
+#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/glpk-5.0/src/misc/mygmp.c b/glpk-5.0/src/misc/mygmp.c
new file mode 100644
index 0000000..87ef681
--- /dev/null
+++ b/glpk-5.0/src/misc/mygmp.c
@@ -0,0 +1,1160 @@
+/* mygmp.c (integer and rational arithmetic) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2008-2015 Free Software Foundation, Inc.
+* Written 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 "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/glpk-5.0/src/misc/mygmp.h b/glpk-5.0/src/misc/mygmp.h
new file mode 100644
index 0000000..a0a87ec
--- /dev/null
+++ b/glpk-5.0/src/misc/mygmp.h
@@ -0,0 +1,252 @@
+/* mygmp.h (integer and rational arithmetic) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2008-2015 Free Software Foundation, Inc.
+* Written 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/>.
+***********************************************************************/
+
+#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/glpk-5.0/src/misc/okalg.c b/glpk-5.0/src/misc/okalg.c
new file mode 100644
index 0000000..788f5b3
--- /dev/null
+++ b/glpk-5.0/src/misc/okalg.c
@@ -0,0 +1,380 @@
+/* okalg.c (out-of-kilter algorithm) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2009-2013 Free Software Foundation, Inc.
+* Written 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 "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/glpk-5.0/src/misc/okalg.h b/glpk-5.0/src/misc/okalg.h
new file mode 100644
index 0000000..95fdcf5
--- /dev/null
+++ b/glpk-5.0/src/misc/okalg.h
@@ -0,0 +1,33 @@
+/* okalg.h (out-of-kilter algorithm) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2009-2013 Free Software Foundation, Inc.
+* Written 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/>.
+***********************************************************************/
+
+#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/glpk-5.0/src/misc/qmd.c b/glpk-5.0/src/misc/qmd.c
new file mode 100644
index 0000000..e5cbd5c
--- /dev/null
+++ b/glpk-5.0/src/misc/qmd.c
@@ -0,0 +1,99 @@
+/* qmd.c */
+
+#include "env.h"
+#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)
+{ static const char func[] = "genqmd";
+ xassert(neqns == neqns);
+ xassert(xadj == xadj);
+ xassert(adjncy == adjncy);
+ xassert(perm == perm);
+ xassert(invp == invp);
+ xassert(deg == deg);
+ xassert(marker == marker);
+ xassert(rchset == rchset);
+ xassert(nbrhd == nbrhd);
+ xassert(qsize == qsize);
+ xassert(qlink == qlink);
+ xassert(nofsub == nofsub);
+ xerror("%s: sorry, this routine is temporarily disabled due to li"
+ "censing problems\n", func);
+ abort();
+}
+
+void qmdrch(int *root, int xadj[], int adjncy[], int deg[],
+ int marker[], int *rchsze, int rchset[], int *nhdsze,
+ int nbrhd[])
+{ static const char func[] = "qmdrch";
+ xassert(root == root);
+ xassert(xadj == xadj);
+ xassert(adjncy == adjncy);
+ xassert(deg == deg);
+ xassert(marker == marker);
+ xassert(rchsze == rchsze);
+ xassert(rchset == rchset);
+ xassert(nhdsze == nhdsze);
+ xassert(nbrhd == nbrhd);
+ xerror("%s: sorry, this routine is temporarily disabled due to li"
+ "censing problems\n", func);
+ abort();
+}
+
+void qmdqt(int *root, int xadj[], int adjncy[], int marker[],
+ int *rchsze, int rchset[], int nbrhd[])
+{ static const char func[] = "qmdqt";
+ xassert(root == root);
+ xassert(xadj == xadj);
+ xassert(adjncy == adjncy);
+ xassert(marker == marker);
+ xassert(rchsze == rchsze);
+ xassert(rchset == rchset);
+ xassert(nbrhd == nbrhd);
+ xerror("%s: sorry, this routine is temporarily disabled due to li"
+ "censing problems\n", func);
+ abort();
+}
+
+void qmdupd(int xadj[], int adjncy[], int *nlist, int list[],
+ int deg[], int qsize[], int qlink[], int marker[], int rchset[],
+ int nbrhd[])
+{ static const char func[] = "qmdupd";
+ xassert(xadj == xadj);
+ xassert(adjncy == adjncy);
+ xassert(nlist == nlist);
+ xassert(list == list);
+ xassert(deg == deg);
+ xassert(qsize == qsize);
+ xassert(qlink == qlink);
+ xassert(marker == marker);
+ xassert(rchset == rchset);
+ xassert(nbrhd == nbrhd);
+ xerror("%s: sorry, this routine is temporarily disabled due to li"
+ "censing problems\n", func);
+ abort();
+}
+
+void qmdmrg(int xadj[], int adjncy[], int deg[], int qsize[],
+ int qlink[], int marker[], int *deg0, int *nhdsze, int nbrhd[],
+ int rchset[], int ovrlp[])
+{ static const char func[] = "qmdmrg";
+ xassert(xadj == xadj);
+ xassert(adjncy == adjncy);
+ xassert(deg == deg);
+ xassert(qsize == qsize);
+ xassert(qlink == qlink);
+ xassert(marker == marker);
+ xassert(deg0 == deg0);
+ xassert(nhdsze == nhdsze);
+ xassert(nbrhd == nbrhd);
+ xassert(rchset == rchset);
+ xassert(ovrlp == ovrlp);
+ xerror("%s: sorry, this routine is temporarily disabled due to li"
+ "censing problems\n", func);
+ abort();
+}
+
+/* eof */
diff --git a/glpk-5.0/src/misc/qmd.h b/glpk-5.0/src/misc/qmd.h
new file mode 100644
index 0000000..6c6f1d2
--- /dev/null
+++ b/glpk-5.0/src/misc/qmd.h
@@ -0,0 +1,56 @@
+/* qmd.h (quotient minimum degree algorithm) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2001 Free Software Foundation, Inc.
+* Written 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/>.
+***********************************************************************/
+
+#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/glpk-5.0/src/misc/relax4.c b/glpk-5.0/src/misc/relax4.c
new file mode 100644
index 0000000..807cf9c
--- /dev/null
+++ b/glpk-5.0/src/misc/relax4.c
@@ -0,0 +1,23 @@
+/* relax4.c */
+
+#include "env.h"
+#include "relax4.h"
+
+int relax4(struct relax4_csa *csa)
+{ static const char func[] = "relax4";
+ xassert(csa == csa);
+ xerror("%s: sorry, this routine is temporarily disabled due to li"
+ "censing problems\n", func);
+ abort();
+ return -1;
+}
+
+void relax4_inidat(struct relax4_csa *csa)
+{ static const char func[] = "relax4_inidat";
+ xassert(csa == csa);
+ xerror("%s: sorry, this routine is temporarily disabled due to li"
+ "censing problems\n", func);
+ abort();
+}
+
+/* eof */
diff --git a/glpk-5.0/src/misc/relax4.h b/glpk-5.0/src/misc/relax4.h
new file mode 100644
index 0000000..abcef0e
--- /dev/null
+++ b/glpk-5.0/src/misc/relax4.h
@@ -0,0 +1,100 @@
+/* relax4.h */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2012-2013 Free Software Foundation, Inc.
+* Written 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/>.
+***********************************************************************/
+
+#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/glpk-5.0/src/misc/rgr.c b/glpk-5.0/src/misc/rgr.c
new file mode 100644
index 0000000..f2dc371
--- /dev/null
+++ b/glpk-5.0/src/misc/rgr.c
@@ -0,0 +1,167 @@
+/* rgr.c (raster graphics) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2004-2018 Free Software Foundation, Inc.
+* Written 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 "rgr.h"
+
+/***********************************************************************
+* NAME
+*
+* rgr_write_bmp16 - write 16-color raster image in BMP file format
+*
+* SYNOPSIS
+*
+* #include "rgr.h"
+* int rgr_write_bmp16(const char *fname, int m, int n, const char
+* map[]);
+*
+* DESCRIPTION
+*
+* The routine rgr_write_bmp16 writes 16-color raster image in
+* uncompressed BMP file format (Windows bitmap) to a binary file whose
+* name is specified by the character string fname.
+*
+* The parameters m and n specify, respectively, the number of rows and
+* the numbers of columns (i.e. height and width) of the raster image.
+*
+* The character array map has m*n elements. Elements map[0, ..., n-1]
+* correspond to the first (top) scanline, elements map[n, ..., 2*n-1]
+* correspond to the second scanline, etc.
+*
+* Each element of the array map specifies a color of the corresponding
+* pixel as 8-bit binary number XXXXIRGB, where four high-order bits (X)
+* are ignored, I is high intensity bit, R is red color bit, G is green
+* color bit, and B is blue color bit. Thus, all 16 possible colors are
+* coded as following hexadecimal numbers:
+*
+* 0x00 = black 0x08 = dark gray
+* 0x01 = blue 0x09 = bright blue
+* 0x02 = green 0x0A = bright green
+* 0x03 = cyan 0x0B = bright cyan
+* 0x04 = red 0x0C = bright red
+* 0x05 = magenta 0x0D = bright magenta
+* 0x06 = brown 0x0E = yellow
+* 0x07 = light gray 0x0F = white
+*
+* RETURNS
+*
+* If no error occured, the routine returns zero; otherwise, it prints
+* an appropriate error message and returns non-zero. */
+
+static void put_byte(FILE *fp, int c)
+{ fputc(c, fp);
+ return;
+}
+
+static void put_word(FILE *fp, int w)
+{ /* big endian */
+ put_byte(fp, w);
+ put_byte(fp, w >> 8);
+ return;
+}
+
+static void put_dword(FILE *fp, int d)
+{ /* big endian */
+ put_word(fp, d);
+ put_word(fp, d >> 16);
+ return;
+}
+
+int rgr_write_bmp16(const char *fname, int m, int n, const char map[])
+{ FILE *fp;
+ int offset, bmsize, i, j, b, ret = 0;
+ if (!(1 <= m && m <= 32767))
+ xerror("rgr_write_bmp16: m = %d; invalid height\n", m);
+ if (!(1 <= n && n <= 32767))
+ xerror("rgr_write_bmp16: n = %d; invalid width\n", n);
+ fp = fopen(fname, "wb");
+ if (fp == NULL)
+ { xprintf("rgr_write_bmp16: unable to create '%s' - %s\n",
+#if 0 /* 29/I-2017 */
+ fname, strerror(errno));
+#else
+ fname, xstrerr(errno));
+#endif
+ ret = 1;
+ goto fini;
+ }
+ offset = 14 + 40 + 16 * 4;
+ bmsize = (4 * n + 31) / 32;
+ /* struct BMPFILEHEADER (14 bytes) */
+ /* UINT bfType */ put_byte(fp, 'B'), put_byte(fp, 'M');
+ /* DWORD bfSize */ put_dword(fp, offset + bmsize * 4);
+ /* UINT bfReserved1 */ put_word(fp, 0);
+ /* UNIT bfReserved2 */ put_word(fp, 0);
+ /* DWORD bfOffBits */ put_dword(fp, offset);
+ /* struct BMPINFOHEADER (40 bytes) */
+ /* DWORD biSize */ put_dword(fp, 40);
+ /* LONG biWidth */ put_dword(fp, n);
+ /* LONG biHeight */ put_dword(fp, m);
+ /* WORD biPlanes */ put_word(fp, 1);
+ /* WORD biBitCount */ put_word(fp, 4);
+ /* DWORD biCompression */ put_dword(fp, 0 /* BI_RGB */);
+ /* DWORD biSizeImage */ put_dword(fp, 0);
+ /* LONG biXPelsPerMeter */ put_dword(fp, 2953 /* 75 dpi */);
+ /* LONG biYPelsPerMeter */ put_dword(fp, 2953 /* 75 dpi */);
+ /* DWORD biClrUsed */ put_dword(fp, 0);
+ /* DWORD biClrImportant */ put_dword(fp, 0);
+ /* struct RGBQUAD (16 * 4 = 64 bytes) */
+ /* CGA-compatible colors: */
+ /* 0x00 = black */ put_dword(fp, 0x000000);
+ /* 0x01 = blue */ put_dword(fp, 0x000080);
+ /* 0x02 = green */ put_dword(fp, 0x008000);
+ /* 0x03 = cyan */ put_dword(fp, 0x008080);
+ /* 0x04 = red */ put_dword(fp, 0x800000);
+ /* 0x05 = magenta */ put_dword(fp, 0x800080);
+ /* 0x06 = brown */ put_dword(fp, 0x808000);
+ /* 0x07 = light gray */ put_dword(fp, 0xC0C0C0);
+ /* 0x08 = dark gray */ put_dword(fp, 0x808080);
+ /* 0x09 = bright blue */ put_dword(fp, 0x0000FF);
+ /* 0x0A = bright green */ put_dword(fp, 0x00FF00);
+ /* 0x0B = bright cyan */ put_dword(fp, 0x00FFFF);
+ /* 0x0C = bright red */ put_dword(fp, 0xFF0000);
+ /* 0x0D = bright magenta */ put_dword(fp, 0xFF00FF);
+ /* 0x0E = yellow */ put_dword(fp, 0xFFFF00);
+ /* 0x0F = white */ put_dword(fp, 0xFFFFFF);
+ /* pixel data bits */
+ b = 0;
+ for (i = m - 1; i >= 0; i--)
+ { for (j = 0; j < ((n + 7) / 8) * 8; j++)
+ { b <<= 4;
+ b |= (j < n ? map[i * n + j] & 15 : 0);
+ if (j & 1) put_byte(fp, b);
+ }
+ }
+ fflush(fp);
+ if (ferror(fp))
+ { xprintf("rgr_write_bmp16: write error on '%s' - %s\n",
+#if 0 /* 29/I-2017 */
+ fname, strerror(errno));
+#else
+ fname, xstrerr(errno));
+#endif
+ ret = 1;
+ }
+fini: if (fp != NULL) fclose(fp);
+ return ret;
+}
+
+/* eof */
diff --git a/glpk-5.0/src/misc/rgr.h b/glpk-5.0/src/misc/rgr.h
new file mode 100644
index 0000000..027cb7a
--- /dev/null
+++ b/glpk-5.0/src/misc/rgr.h
@@ -0,0 +1,31 @@
+/* rgr.h (raster graphics) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2004-2018 Free Software Foundation, Inc.
+* Written 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/>.
+***********************************************************************/
+
+#ifndef RGR_H
+#define RGR_H
+
+#define rgr_write_bmp16 _glp_rgr_write_bmp16
+int rgr_write_bmp16(const char *fname, int m, int n, const char map[]);
+/* write 16-color raster image in BMP file format */
+
+#endif
+
+/* eof */
diff --git a/glpk-5.0/src/misc/rng.c b/glpk-5.0/src/misc/rng.c
new file mode 100644
index 0000000..e0acb53
--- /dev/null
+++ b/glpk-5.0/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/glpk-5.0/src/misc/rng.h b/glpk-5.0/src/misc/rng.h
new file mode 100644
index 0000000..09e1e5c
--- /dev/null
+++ b/glpk-5.0/src/misc/rng.h
@@ -0,0 +1,65 @@
+/* rng.h (pseudo-random number generator) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2003 Free Software Foundation, Inc.
+* Written 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/>.
+***********************************************************************/
+
+#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/glpk-5.0/src/misc/rng1.c b/glpk-5.0/src/misc/rng1.c
new file mode 100644
index 0000000..4184682
--- /dev/null
+++ b/glpk-5.0/src/misc/rng1.c
@@ -0,0 +1,71 @@
+/* rng1.c (pseudo-random number generator) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2003 Free Software Foundation, Inc.
+* Written 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"
+
+/***********************************************************************
+* 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/glpk-5.0/src/misc/round2n.c b/glpk-5.0/src/misc/round2n.c
new file mode 100644
index 0000000..1caa000
--- /dev/null
+++ b/glpk-5.0/src/misc/round2n.c
@@ -0,0 +1,62 @@
+/* round2n.c (round floating-point number to nearest power of two) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2000 Free Software Foundation, Inc.
+* Written 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 "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/glpk-5.0/src/misc/spm.c b/glpk-5.0/src/misc/spm.c
new file mode 100644
index 0000000..7c1bd96
--- /dev/null
+++ b/glpk-5.0/src/misc/spm.c
@@ -0,0 +1,844 @@
+/* glpspm.c (general sparse matrices) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2004-2018 Free Software Foundation, Inc.
+* Written 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 "hbm.h"
+#include "rgr.h"
+#include "spm.h"
+
+/***********************************************************************
+* NAME
+*
+* spm_create_mat - create general sparse matrix
+*
+* SYNOPSIS
+*
+* #include "glpspm.h"
+* SPM *spm_create_mat(int m, int n);
+*
+* DESCRIPTION
+*
+* The routine spm_create_mat creates a general sparse matrix having
+* m rows and n columns. Being created the matrix is zero (empty), i.e.
+* has no elements.
+*
+* RETURNS
+*
+* The routine returns a pointer to the matrix created. */
+
+SPM *spm_create_mat(int m, int n)
+{ SPM *A;
+ xassert(0 <= m && m < INT_MAX);
+ xassert(0 <= n && n < INT_MAX);
+ A = xmalloc(sizeof(SPM));
+ A->m = m;
+ A->n = n;
+ if (m == 0 || n == 0)
+ { A->pool = NULL;
+ A->row = NULL;
+ A->col = NULL;
+ }
+ else
+ { int i, j;
+ A->pool = dmp_create_pool();
+ A->row = xcalloc(1+m, sizeof(SPME *));
+ for (i = 1; i <= m; i++) A->row[i] = NULL;
+ A->col = xcalloc(1+n, sizeof(SPME *));
+ for (j = 1; j <= n; j++) A->col[j] = NULL;
+ }
+ return A;
+}
+
+/***********************************************************************
+* NAME
+*
+* spm_new_elem - add new element to sparse matrix
+*
+* SYNOPSIS
+*
+* #include "glpspm.h"
+* SPME *spm_new_elem(SPM *A, int i, int j, double val);
+*
+* DESCRIPTION
+*
+* The routine spm_new_elem adds a new element to the specified sparse
+* matrix. Parameters i, j, and val specify the row number, the column
+* number, and a numerical value of the element, respectively.
+*
+* RETURNS
+*
+* The routine returns a pointer to the new element added. */
+
+SPME *spm_new_elem(SPM *A, int i, int j, double val)
+{ SPME *e;
+ xassert(1 <= i && i <= A->m);
+ xassert(1 <= j && j <= A->n);
+ e = dmp_get_atom(A->pool, sizeof(SPME));
+ e->i = i;
+ e->j = j;
+ e->val = val;
+ e->r_prev = NULL;
+ e->r_next = A->row[i];
+ if (e->r_next != NULL) e->r_next->r_prev = e;
+ e->c_prev = NULL;
+ e->c_next = A->col[j];
+ if (e->c_next != NULL) e->c_next->c_prev = e;
+ A->row[i] = A->col[j] = e;
+ return e;
+}
+
+/***********************************************************************
+* NAME
+*
+* spm_delete_mat - delete general sparse matrix
+*
+* SYNOPSIS
+*
+* #include "glpspm.h"
+* void spm_delete_mat(SPM *A);
+*
+* DESCRIPTION
+*
+* The routine deletes the specified general sparse matrix freeing all
+* the memory allocated to this object. */
+
+void spm_delete_mat(SPM *A)
+{ /* delete sparse matrix */
+ if (A->pool != NULL) dmp_delete_pool(A->pool);
+ if (A->row != NULL) xfree(A->row);
+ if (A->col != NULL) xfree(A->col);
+ xfree(A);
+ return;
+}
+
+/***********************************************************************
+* NAME
+*
+* spm_test_mat_e - create test sparse matrix of E(n,c) class
+*
+* SYNOPSIS
+*
+* #include "glpspm.h"
+* SPM *spm_test_mat_e(int n, int c);
+*
+* DESCRIPTION
+*
+* The routine spm_test_mat_e creates a test sparse matrix of E(n,c)
+* class as described in the book: Ole 0sterby, Zahari Zlatev. Direct
+* Methods for Sparse Matrices. Springer-Verlag, 1983.
+*
+* Matrix of E(n,c) class is a symmetric positive definite matrix of
+* the order n. It has the number 4 on its main diagonal and the number
+* -1 on its four co-diagonals, two of which are neighbour to the main
+* diagonal and two others are shifted from the main diagonal on the
+* distance c.
+*
+* It is necessary that n >= 3 and 2 <= c <= n-1.
+*
+* RETURNS
+*
+* The routine returns a pointer to the matrix created. */
+
+SPM *spm_test_mat_e(int n, int c)
+{ SPM *A;
+ int i;
+ xassert(n >= 3 && 2 <= c && c <= n-1);
+ A = spm_create_mat(n, n);
+ for (i = 1; i <= n; i++)
+ spm_new_elem(A, i, i, 4.0);
+ for (i = 1; i <= n-1; i++)
+ { spm_new_elem(A, i, i+1, -1.0);
+ spm_new_elem(A, i+1, i, -1.0);
+ }
+ for (i = 1; i <= n-c; i++)
+ { spm_new_elem(A, i, i+c, -1.0);
+ spm_new_elem(A, i+c, i, -1.0);
+ }
+ return A;
+}
+
+/***********************************************************************
+* NAME
+*
+* spm_test_mat_d - create test sparse matrix of D(n,c) class
+*
+* SYNOPSIS
+*
+* #include "glpspm.h"
+* SPM *spm_test_mat_d(int n, int c);
+*
+* DESCRIPTION
+*
+* The routine spm_test_mat_d creates a test sparse matrix of D(n,c)
+* class as described in the book: Ole 0sterby, Zahari Zlatev. Direct
+* Methods for Sparse Matrices. Springer-Verlag, 1983.
+*
+* Matrix of D(n,c) class is a non-singular matrix of the order n. It
+* has unity main diagonal, three co-diagonals above the main diagonal
+* on the distance c, which are cyclically continued below the main
+* diagonal, and a triangle block of the size 10x10 in the upper right
+* corner.
+*
+* It is necessary that n >= 14 and 1 <= c <= n-13.
+*
+* RETURNS
+*
+* The routine returns a pointer to the matrix created. */
+
+SPM *spm_test_mat_d(int n, int c)
+{ SPM *A;
+ int i, j;
+ xassert(n >= 14 && 1 <= c && c <= n-13);
+ A = spm_create_mat(n, n);
+ for (i = 1; i <= n; i++)
+ spm_new_elem(A, i, i, 1.0);
+ for (i = 1; i <= n-c; i++)
+ spm_new_elem(A, i, i+c, (double)(i+1));
+ for (i = n-c+1; i <= n; i++)
+ spm_new_elem(A, i, i-n+c, (double)(i+1));
+ for (i = 1; i <= n-c-1; i++)
+ spm_new_elem(A, i, i+c+1, (double)(-i));
+ for (i = n-c; i <= n; i++)
+ spm_new_elem(A, i, i-n+c+1, (double)(-i));
+ for (i = 1; i <= n-c-2; i++)
+ spm_new_elem(A, i, i+c+2, 16.0);
+ for (i = n-c-1; i <= n; i++)
+ spm_new_elem(A, i, i-n+c+2, 16.0);
+ for (j = 1; j <= 10; j++)
+ for (i = 1; i <= 11-j; i++)
+ spm_new_elem(A, i, n-11+i+j, 100.0 * (double)j);
+ return A;
+}
+
+/***********************************************************************
+* NAME
+*
+* spm_show_mat - write sparse matrix pattern in BMP file format
+*
+* SYNOPSIS
+*
+* #include "glpspm.h"
+* int spm_show_mat(const SPM *A, const char *fname);
+*
+* DESCRIPTION
+*
+* The routine spm_show_mat writes pattern of the specified sparse
+* matrix in uncompressed BMP file format (Windows bitmap) to a binary
+* file whose name is specified by the character string fname.
+*
+* Each pixel corresponds to one matrix element. The pixel colors have
+* the following meaning:
+*
+* Black structurally zero element
+* White positive element
+* Cyan negative element
+* Green zero element
+* Red duplicate element
+*
+* RETURNS
+*
+* If no error occured, the routine returns zero. Otherwise, it prints
+* an appropriate error message and returns non-zero. */
+
+int spm_show_mat(const SPM *A, const char *fname)
+{ int m = A->m;
+ int n = A->n;
+ int i, j, k, ret;
+ char *map;
+ xprintf("spm_show_mat: writing matrix pattern to '%s'...\n",
+ fname);
+ xassert(1 <= m && m <= 32767);
+ xassert(1 <= n && n <= 32767);
+ map = xmalloc(m * n);
+ memset(map, 0x08, m * n);
+ for (i = 1; i <= m; i++)
+ { SPME *e;
+ for (e = A->row[i]; e != NULL; e = e->r_next)
+ { j = e->j;
+ xassert(1 <= j && j <= n);
+ k = n * (i - 1) + (j - 1);
+ if (map[k] != 0x08)
+ map[k] = 0x0C;
+ else if (e->val > 0.0)
+ map[k] = 0x0F;
+ else if (e->val < 0.0)
+ map[k] = 0x0B;
+ else
+ map[k] = 0x0A;
+ }
+ }
+ ret = rgr_write_bmp16(fname, m, n, map);
+ xfree(map);
+ return ret;
+}
+
+/***********************************************************************
+* NAME
+*
+* spm_read_hbm - read sparse matrix in Harwell-Boeing format
+*
+* SYNOPSIS
+*
+* #include "glpspm.h"
+* SPM *spm_read_hbm(const char *fname);
+*
+* DESCRIPTION
+*
+* The routine spm_read_hbm reads a sparse matrix in the Harwell-Boeing
+* format from a text file whose name is the character string fname.
+*
+* Detailed description of the Harwell-Boeing format recognised by this
+* routine can be found in the following report:
+*
+* I.S.Duff, R.G.Grimes, J.G.Lewis. User's Guide for the Harwell-Boeing
+* Sparse Matrix Collection (Release I), TR/PA/92/86, October 1992.
+*
+* NOTE
+*
+* The routine spm_read_hbm reads the matrix "as is", due to which zero
+* and/or duplicate elements can appear in the matrix.
+*
+* RETURNS
+*
+* If no error occured, the routine returns a pointer to the matrix
+* created. Otherwise, the routine prints an appropriate error message
+* and returns NULL. */
+
+SPM *spm_read_hbm(const char *fname)
+{ SPM *A = NULL;
+ HBM *hbm;
+ int nrow, ncol, nnzero, i, j, beg, end, ptr, *colptr, *rowind;
+ double val, *values;
+ char *mxtype;
+ hbm = hbm_read_mat(fname);
+ if (hbm == NULL)
+ { xprintf("spm_read_hbm: unable to read matrix\n");
+ goto fini;
+ }
+ mxtype = hbm->mxtype;
+ nrow = hbm->nrow;
+ ncol = hbm->ncol;
+ nnzero = hbm->nnzero;
+ colptr = hbm->colptr;
+ rowind = hbm->rowind;
+ values = hbm->values;
+ if (!(strcmp(mxtype, "RSA") == 0 || strcmp(mxtype, "PSA") == 0 ||
+ strcmp(mxtype, "RUA") == 0 || strcmp(mxtype, "PUA") == 0 ||
+ strcmp(mxtype, "RRA") == 0 || strcmp(mxtype, "PRA") == 0))
+ { xprintf("spm_read_hbm: matrix type '%s' not supported\n",
+ mxtype);
+ goto fini;
+ }
+ A = spm_create_mat(nrow, ncol);
+ if (mxtype[1] == 'S' || mxtype[1] == 'U')
+ xassert(nrow == ncol);
+ for (j = 1; j <= ncol; j++)
+ { beg = colptr[j];
+ end = colptr[j+1];
+ xassert(1 <= beg && beg <= end && end <= nnzero + 1);
+ for (ptr = beg; ptr < end; ptr++)
+ { i = rowind[ptr];
+ xassert(1 <= i && i <= nrow);
+ if (mxtype[0] == 'R')
+ val = values[ptr];
+ else
+ val = 1.0;
+ spm_new_elem(A, i, j, val);
+ if (mxtype[1] == 'S' && i != j)
+ spm_new_elem(A, j, i, val);
+ }
+ }
+fini: if (hbm != NULL) hbm_free_mat(hbm);
+ return A;
+}
+
+/***********************************************************************
+* NAME
+*
+* spm_count_nnz - determine number of non-zeros in sparse matrix
+*
+* SYNOPSIS
+*
+* #include "glpspm.h"
+* int spm_count_nnz(const SPM *A);
+*
+* RETURNS
+*
+* The routine spm_count_nnz returns the number of structural non-zero
+* elements in the specified sparse matrix. */
+
+int spm_count_nnz(const SPM *A)
+{ SPME *e;
+ int i, nnz = 0;
+ for (i = 1; i <= A->m; i++)
+ for (e = A->row[i]; e != NULL; e = e->r_next) nnz++;
+ return nnz;
+}
+
+/***********************************************************************
+* NAME
+*
+* spm_drop_zeros - remove zero elements from sparse matrix
+*
+* SYNOPSIS
+*
+* #include "glpspm.h"
+* int spm_drop_zeros(SPM *A, double eps);
+*
+* DESCRIPTION
+*
+* The routine spm_drop_zeros removes all elements from the specified
+* sparse matrix, whose absolute value is less than eps.
+*
+* If the parameter eps is 0, only zero elements are removed from the
+* matrix.
+*
+* RETURNS
+*
+* The routine returns the number of elements removed. */
+
+int spm_drop_zeros(SPM *A, double eps)
+{ SPME *e, *next;
+ int i, count = 0;
+ for (i = 1; i <= A->m; i++)
+ { for (e = A->row[i]; e != NULL; e = next)
+ { next = e->r_next;
+ if (e->val == 0.0 || fabs(e->val) < eps)
+ { /* remove element from the row list */
+ if (e->r_prev == NULL)
+ A->row[e->i] = e->r_next;
+ else
+ e->r_prev->r_next = e->r_next;
+ if (e->r_next == NULL)
+ ;
+ else
+ e->r_next->r_prev = e->r_prev;
+ /* remove element from the column list */
+ if (e->c_prev == NULL)
+ A->col[e->j] = e->c_next;
+ else
+ e->c_prev->c_next = e->c_next;
+ if (e->c_next == NULL)
+ ;
+ else
+ e->c_next->c_prev = e->c_prev;
+ /* return element to the memory pool */
+ dmp_free_atom(A->pool, e, sizeof(SPME));
+ count++;
+ }
+ }
+ }
+ return count;
+}
+
+/***********************************************************************
+* NAME
+*
+* spm_read_mat - read sparse matrix from text file
+*
+* SYNOPSIS
+*
+* #include "glpspm.h"
+* SPM *spm_read_mat(const char *fname);
+*
+* DESCRIPTION
+*
+* The routine reads a sparse matrix from a text file whose name is
+* specified by the parameter fname.
+*
+* For the file format see description of the routine spm_write_mat.
+*
+* RETURNS
+*
+* On success the routine returns a pointer to the matrix created,
+* otherwise NULL. */
+
+#if 1
+SPM *spm_read_mat(const char *fname)
+{ xassert(fname != fname);
+ return NULL;
+}
+#else
+SPM *spm_read_mat(const char *fname)
+{ SPM *A = NULL;
+ PDS *pds;
+ jmp_buf jump;
+ int i, j, k, m, n, nnz, fail = 0;
+ double val;
+ xprintf("spm_read_mat: reading matrix from '%s'...\n", fname);
+ pds = pds_open_file(fname);
+ if (pds == NULL)
+ { xprintf("spm_read_mat: unable to open '%s' - %s\n", fname,
+ strerror(errno));
+ fail = 1;
+ goto done;
+ }
+ if (setjmp(jump))
+ { fail = 1;
+ goto done;
+ }
+ pds_set_jump(pds, jump);
+ /* number of rows, number of columns, number of non-zeros */
+ m = pds_scan_int(pds);
+ if (m < 0)
+ pds_error(pds, "invalid number of rows\n");
+ n = pds_scan_int(pds);
+ if (n < 0)
+ pds_error(pds, "invalid number of columns\n");
+ nnz = pds_scan_int(pds);
+ if (nnz < 0)
+ pds_error(pds, "invalid number of non-zeros\n");
+ /* create matrix */
+ xprintf("spm_read_mat: %d rows, %d columns, %d non-zeros\n",
+ m, n, nnz);
+ A = spm_create_mat(m, n);
+ /* read matrix elements */
+ for (k = 1; k <= nnz; k++)
+ { /* row index, column index, element value */
+ i = pds_scan_int(pds);
+ if (!(1 <= i && i <= m))
+ pds_error(pds, "row index out of range\n");
+ j = pds_scan_int(pds);
+ if (!(1 <= j && j <= n))
+ pds_error(pds, "column index out of range\n");
+ val = pds_scan_num(pds);
+ /* add new element to the matrix */
+ spm_new_elem(A, i, j, val);
+ }
+ xprintf("spm_read_mat: %d lines were read\n", pds->count);
+done: if (pds != NULL) pds_close_file(pds);
+ if (fail && A != NULL) spm_delete_mat(A), A = NULL;
+ return A;
+}
+#endif
+
+/***********************************************************************
+* NAME
+*
+* spm_write_mat - write sparse matrix to text file
+*
+* SYNOPSIS
+*
+* #include "glpspm.h"
+* int spm_write_mat(const SPM *A, const char *fname);
+*
+* DESCRIPTION
+*
+* The routine spm_write_mat writes the specified sparse matrix to a
+* text file whose name is specified by the parameter fname. This file
+* can be read back with the routine spm_read_mat.
+*
+* RETURNS
+*
+* On success the routine returns zero, otherwise non-zero.
+*
+* FILE FORMAT
+*
+* The file created by the routine spm_write_mat is a plain text file,
+* which contains the following information:
+*
+* m n nnz
+* row[1] col[1] val[1]
+* row[2] col[2] val[2]
+* . . .
+* row[nnz] col[nnz] val[nnz]
+*
+* where:
+* m is the number of rows;
+* n is the number of columns;
+* nnz is the number of non-zeros;
+* row[k], k = 1,...,nnz, are row indices;
+* col[k], k = 1,...,nnz, are column indices;
+* val[k], k = 1,...,nnz, are element values. */
+
+#if 1
+int spm_write_mat(const SPM *A, const char *fname)
+{ xassert(A != A);
+ xassert(fname != fname);
+ return 0;
+}
+#else
+int spm_write_mat(const SPM *A, const char *fname)
+{ FILE *fp;
+ int i, nnz, ret = 0;
+ xprintf("spm_write_mat: writing matrix to '%s'...\n", fname);
+ fp = fopen(fname, "w");
+ if (fp == NULL)
+ { xprintf("spm_write_mat: unable to create '%s' - %s\n", fname,
+ strerror(errno));
+ ret = 1;
+ goto done;
+ }
+ /* number of rows, number of columns, number of non-zeros */
+ nnz = spm_count_nnz(A);
+ fprintf(fp, "%d %d %d\n", A->m, A->n, nnz);
+ /* walk through rows of the matrix */
+ for (i = 1; i <= A->m; i++)
+ { SPME *e;
+ /* walk through elements of i-th row */
+ for (e = A->row[i]; e != NULL; e = e->r_next)
+ { /* row index, column index, element value */
+ fprintf(fp, "%d %d %.*g\n", e->i, e->j, DBL_DIG, e->val);
+ }
+ }
+ fflush(fp);
+ if (ferror(fp))
+ { xprintf("spm_write_mat: writing error on '%s' - %s\n", fname,
+ strerror(errno));
+ ret = 1;
+ goto done;
+ }
+ xprintf("spm_write_mat: %d lines were written\n", 1 + nnz);
+done: if (fp != NULL) fclose(fp);
+ return ret;
+}
+#endif
+
+/***********************************************************************
+* NAME
+*
+* spm_transpose - transpose sparse matrix
+*
+* SYNOPSIS
+*
+* #include "glpspm.h"
+* SPM *spm_transpose(const SPM *A);
+*
+* RETURNS
+*
+* The routine computes and returns sparse matrix B, which is a matrix
+* transposed to sparse matrix A. */
+
+SPM *spm_transpose(const SPM *A)
+{ SPM *B;
+ int i;
+ B = spm_create_mat(A->n, A->m);
+ for (i = 1; i <= A->m; i++)
+ { SPME *e;
+ for (e = A->row[i]; e != NULL; e = e->r_next)
+ spm_new_elem(B, e->j, i, e->val);
+ }
+ return B;
+}
+
+SPM *spm_add_sym(const SPM *A, const SPM *B)
+{ /* add two sparse matrices (symbolic phase) */
+ SPM *C;
+ int i, j, *flag;
+ xassert(A->m == B->m);
+ xassert(A->n == B->n);
+ /* create resultant matrix */
+ C = spm_create_mat(A->m, A->n);
+ /* allocate and clear the flag array */
+ flag = xcalloc(1+C->n, sizeof(int));
+ for (j = 1; j <= C->n; j++)
+ flag[j] = 0;
+ /* compute pattern of C = A + B */
+ for (i = 1; i <= C->m; i++)
+ { SPME *e;
+ /* at the beginning i-th row of C is empty */
+ /* (i-th row of C) := (i-th row of C) union (i-th row of A) */
+ for (e = A->row[i]; e != NULL; e = e->r_next)
+ { /* (note that i-th row of A may have duplicate elements) */
+ j = e->j;
+ if (!flag[j])
+ { spm_new_elem(C, i, j, 0.0);
+ flag[j] = 1;
+ }
+ }
+ /* (i-th row of C) := (i-th row of C) union (i-th row of B) */
+ for (e = B->row[i]; e != NULL; e = e->r_next)
+ { /* (note that i-th row of B may have duplicate elements) */
+ j = e->j;
+ if (!flag[j])
+ { spm_new_elem(C, i, j, 0.0);
+ flag[j] = 1;
+ }
+ }
+ /* reset the flag array */
+ for (e = C->row[i]; e != NULL; e = e->r_next)
+ flag[e->j] = 0;
+ }
+ /* check and deallocate the flag array */
+ for (j = 1; j <= C->n; j++)
+ xassert(!flag[j]);
+ xfree(flag);
+ return C;
+}
+
+void spm_add_num(SPM *C, double alfa, const SPM *A, double beta,
+ const SPM *B)
+{ /* add two sparse matrices (numeric phase) */
+ int i, j;
+ double *work;
+ /* allocate and clear the working array */
+ work = xcalloc(1+C->n, sizeof(double));
+ for (j = 1; j <= C->n; j++)
+ work[j] = 0.0;
+ /* compute matrix C = alfa * A + beta * B */
+ for (i = 1; i <= C->n; i++)
+ { SPME *e;
+ /* work := alfa * (i-th row of A) + beta * (i-th row of B) */
+ /* (note that A and/or B may have duplicate elements) */
+ for (e = A->row[i]; e != NULL; e = e->r_next)
+ work[e->j] += alfa * e->val;
+ for (e = B->row[i]; e != NULL; e = e->r_next)
+ work[e->j] += beta * e->val;
+ /* (i-th row of C) := work, work := 0 */
+ for (e = C->row[i]; e != NULL; e = e->r_next)
+ { j = e->j;
+ e->val = work[j];
+ work[j] = 0.0;
+ }
+ }
+ /* check and deallocate the working array */
+ for (j = 1; j <= C->n; j++)
+ xassert(work[j] == 0.0);
+ xfree(work);
+ return;
+}
+
+SPM *spm_add_mat(double alfa, const SPM *A, double beta, const SPM *B)
+{ /* add two sparse matrices (driver routine) */
+ SPM *C;
+ C = spm_add_sym(A, B);
+ spm_add_num(C, alfa, A, beta, B);
+ return C;
+}
+
+SPM *spm_mul_sym(const SPM *A, const SPM *B)
+{ /* multiply two sparse matrices (symbolic phase) */
+ int i, j, k, *flag;
+ SPM *C;
+ xassert(A->n == B->m);
+ /* create resultant matrix */
+ C = spm_create_mat(A->m, B->n);
+ /* allocate and clear the flag array */
+ flag = xcalloc(1+C->n, sizeof(int));
+ for (j = 1; j <= C->n; j++)
+ flag[j] = 0;
+ /* compute pattern of C = A * B */
+ for (i = 1; i <= C->m; i++)
+ { SPME *e, *ee;
+ /* compute pattern of i-th row of C */
+ for (e = A->row[i]; e != NULL; e = e->r_next)
+ { k = e->j;
+ for (ee = B->row[k]; ee != NULL; ee = ee->r_next)
+ { j = ee->j;
+ /* if a[i,k] != 0 and b[k,j] != 0 then c[i,j] != 0 */
+ if (!flag[j])
+ { /* c[i,j] does not exist, so create it */
+ spm_new_elem(C, i, j, 0.0);
+ flag[j] = 1;
+ }
+ }
+ }
+ /* reset the flag array */
+ for (e = C->row[i]; e != NULL; e = e->r_next)
+ flag[e->j] = 0;
+ }
+ /* check and deallocate the flag array */
+ for (j = 1; j <= C->n; j++)
+ xassert(!flag[j]);
+ xfree(flag);
+ return C;
+}
+
+void spm_mul_num(SPM *C, const SPM *A, const SPM *B)
+{ /* multiply two sparse matrices (numeric phase) */
+ int i, j;
+ double *work;
+ /* allocate and clear the working array */
+ work = xcalloc(1+A->n, sizeof(double));
+ for (j = 1; j <= A->n; j++)
+ work[j] = 0.0;
+ /* compute matrix C = A * B */
+ for (i = 1; i <= C->m; i++)
+ { SPME *e, *ee;
+ double temp;
+ /* work := (i-th row of A) */
+ /* (note that A may have duplicate elements) */
+ for (e = A->row[i]; e != NULL; e = e->r_next)
+ work[e->j] += e->val;
+ /* compute i-th row of C */
+ for (e = C->row[i]; e != NULL; e = e->r_next)
+ { j = e->j;
+ /* c[i,j] := work * (j-th column of B) */
+ temp = 0.0;
+ for (ee = B->col[j]; ee != NULL; ee = ee->c_next)
+ temp += work[ee->i] * ee->val;
+ e->val = temp;
+ }
+ /* reset the working array */
+ for (e = A->row[i]; e != NULL; e = e->r_next)
+ work[e->j] = 0.0;
+ }
+ /* check and deallocate the working array */
+ for (j = 1; j <= A->n; j++)
+ xassert(work[j] == 0.0);
+ xfree(work);
+ return;
+}
+
+SPM *spm_mul_mat(const SPM *A, const SPM *B)
+{ /* multiply two sparse matrices (driver routine) */
+ SPM *C;
+ C = spm_mul_sym(A, B);
+ spm_mul_num(C, A, B);
+ return C;
+}
+
+PER *spm_create_per(int n)
+{ /* create permutation matrix */
+ PER *P;
+ int k;
+ xassert(n >= 0);
+ P = xmalloc(sizeof(PER));
+ P->n = n;
+ P->row = xcalloc(1+n, sizeof(int));
+ P->col = xcalloc(1+n, sizeof(int));
+ /* initially it is identity matrix */
+ for (k = 1; k <= n; k++)
+ P->row[k] = P->col[k] = k;
+ return P;
+}
+
+void spm_check_per(PER *P)
+{ /* check permutation matrix for correctness */
+ int i, j;
+ xassert(P->n >= 0);
+ for (i = 1; i <= P->n; i++)
+ { j = P->row[i];
+ xassert(1 <= j && j <= P->n);
+ xassert(P->col[j] == i);
+ }
+ return;
+}
+
+void spm_delete_per(PER *P)
+{ /* delete permutation matrix */
+ xfree(P->row);
+ xfree(P->col);
+ xfree(P);
+ return;
+}
+
+/* eof */
diff --git a/glpk-5.0/src/misc/spm.h b/glpk-5.0/src/misc/spm.h
new file mode 100644
index 0000000..a3a22c5
--- /dev/null
+++ b/glpk-5.0/src/misc/spm.h
@@ -0,0 +1,162 @@
+/* spm.h (general sparse matrices) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2004-2018 Free Software Foundation, Inc.
+* Written 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/>.
+***********************************************************************/
+
+#ifndef SPM_H
+#define SPM_H
+
+#include "dmp.h"
+
+typedef struct SPM SPM;
+typedef struct SPME SPME;
+
+struct SPM
+{ /* general sparse matrix */
+ int m;
+ /* number of rows, m >= 0 */
+ int n;
+ /* number of columns, n >= 0 */
+ DMP *pool;
+ /* memory pool to store matrix elements */
+ SPME **row; /* SPME *row[1+m]; */
+ /* row[i], 1 <= i <= m, is a pointer to i-th row list */
+ SPME **col; /* SPME *col[1+n]; */
+ /* col[j], 1 <= j <= n, is a pointer to j-th column list */
+};
+
+struct SPME
+{ /* sparse matrix element */
+ int i;
+ /* row number */
+ int j;
+ /* column number */
+ double val;
+ /* element value */
+ SPME *r_prev;
+ /* pointer to previous element in the same row */
+ SPME *r_next;
+ /* pointer to next element in the same row */
+ SPME *c_prev;
+ /* pointer to previous element in the same column */
+ SPME *c_next;
+ /* pointer to next element in the same column */
+};
+
+typedef struct PER PER;
+
+struct PER
+{ /* permutation matrix */
+ int n;
+ /* matrix order, n >= 0 */
+ int *row; /* int row[1+n]; */
+ /* row[i] = j means p[i,j] = 1 */
+ int *col; /* int col[1+n]; */
+ /* col[j] = i means p[i,j] = 1 */
+};
+
+#define spm_create_mat _glp_spm_create_mat
+SPM *spm_create_mat(int m, int n);
+/* create general sparse matrix */
+
+#define spm_new_elem _glp_spm_new_elem
+SPME *spm_new_elem(SPM *A, int i, int j, double val);
+/* add new element to sparse matrix */
+
+#define spm_delete_mat _glp_spm_delete_mat
+void spm_delete_mat(SPM *A);
+/* delete general sparse matrix */
+
+#define spm_test_mat_e _glp_spm_test_mat_e
+SPM *spm_test_mat_e(int n, int c);
+/* create test sparse matrix of E(n,c) class */
+
+#define spm_test_mat_d _glp_spm_test_mat_d
+SPM *spm_test_mat_d(int n, int c);
+/* create test sparse matrix of D(n,c) class */
+
+#define spm_show_mat _glp_spm_show_mat
+int spm_show_mat(const SPM *A, const char *fname);
+/* write sparse matrix pattern in BMP file format */
+
+#define spm_read_hbm _glp_spm_read_hbm
+SPM *spm_read_hbm(const char *fname);
+/* read sparse matrix in Harwell-Boeing format */
+
+#define spm_count_nnz _glp_spm_count_nnz
+int spm_count_nnz(const SPM *A);
+/* determine number of non-zeros in sparse matrix */
+
+#define spm_drop_zeros _glp_spm_drop_zeros
+int spm_drop_zeros(SPM *A, double eps);
+/* remove zero elements from sparse matrix */
+
+#define spm_read_mat _glp_spm_read_mat
+SPM *spm_read_mat(const char *fname);
+/* read sparse matrix from text file */
+
+#define spm_write_mat _glp_spm_write_mat
+int spm_write_mat(const SPM *A, const char *fname);
+/* write sparse matrix to text file */
+
+#define spm_transpose _glp_spm_transpose
+SPM *spm_transpose(const SPM *A);
+/* transpose sparse matrix */
+
+#define spm_add_sym _glp_spm_add_sym
+SPM *spm_add_sym(const SPM *A, const SPM *B);
+/* add two sparse matrices (symbolic phase) */
+
+#define spm_add_num _glp_spm_add_num
+void spm_add_num(SPM *C, double alfa, const SPM *A, double beta,
+ const SPM *B);
+/* add two sparse matrices (numeric phase) */
+
+#define spm_add_mat _glp_spm_add_mat
+SPM *spm_add_mat(double alfa, const SPM *A, double beta,
+ const SPM *B);
+/* add two sparse matrices (driver routine) */
+
+#define spm_mul_sym _glp_spm_mul_sym
+SPM *spm_mul_sym(const SPM *A, const SPM *B);
+/* multiply two sparse matrices (symbolic phase) */
+
+#define spm_mul_num _glp_spm_mul_num
+void spm_mul_num(SPM *C, const SPM *A, const SPM *B);
+/* multiply two sparse matrices (numeric phase) */
+
+#define spm_mul_mat _glp_spm_mul_mat
+SPM *spm_mul_mat(const SPM *A, const SPM *B);
+/* multiply two sparse matrices (driver routine) */
+
+#define spm_create_per _glp_spm_create_per
+PER *spm_create_per(int n);
+/* create permutation matrix */
+
+#define spm_check_per _glp_spm_check_per
+void spm_check_per(PER *P);
+/* check permutation matrix for correctness */
+
+#define spm_delete_per _glp_spm_delete_per
+void spm_delete_per(PER *P);
+/* delete permutation matrix */
+
+#endif
+
+/* eof */
diff --git a/glpk-5.0/src/misc/str2int.c b/glpk-5.0/src/misc/str2int.c
new file mode 100644
index 0000000..20325d5
--- /dev/null
+++ b/glpk-5.0/src/misc/str2int.c
@@ -0,0 +1,90 @@
+/* str2int.c (convert string to int) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2000 Free Software Foundation, Inc.
+* Written 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 "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/glpk-5.0/src/misc/str2num.c b/glpk-5.0/src/misc/str2num.c
new file mode 100644
index 0000000..3543667
--- /dev/null
+++ b/glpk-5.0/src/misc/str2num.c
@@ -0,0 +1,108 @@
+/* str2num.c (convert string to double) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2000 Free Software Foundation, Inc.
+* Written 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 "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/glpk-5.0/src/misc/strspx.c b/glpk-5.0/src/misc/strspx.c
new file mode 100644
index 0000000..6be016b
--- /dev/null
+++ b/glpk-5.0/src/misc/strspx.c
@@ -0,0 +1,58 @@
+/* strspx.c (remove all spaces from string) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2000 Free Software Foundation, Inc.
+* Written 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 "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/glpk-5.0/src/misc/strtrim.c b/glpk-5.0/src/misc/strtrim.c
new file mode 100644
index 0000000..d3528cb
--- /dev/null
+++ b/glpk-5.0/src/misc/strtrim.c
@@ -0,0 +1,60 @@
+/* strtrim.c (remove trailing spaces from string) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2000 Free Software Foundation, Inc.
+* Written 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 "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/glpk-5.0/src/misc/triang.c b/glpk-5.0/src/misc/triang.c
new file mode 100644
index 0000000..e70eaa9
--- /dev/null
+++ b/glpk-5.0/src/misc/triang.c
@@ -0,0 +1,309 @@
+/* triang.c (find maximal triangular part of rectangular matrix) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2012-2013 Free Software Foundation, Inc.
+* Written 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 "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/glpk-5.0/src/misc/triang.h b/glpk-5.0/src/misc/triang.h
new file mode 100644
index 0000000..47c33b1
--- /dev/null
+++ b/glpk-5.0/src/misc/triang.h
@@ -0,0 +1,32 @@
+/* triang.h (find maximal triangular part of rectangular matrix) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2012-2013 Free Software Foundation, Inc.
+* Written 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/>.
+***********************************************************************/
+
+#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/glpk-5.0/src/misc/wclique.c b/glpk-5.0/src/misc/wclique.c
new file mode 100644
index 0000000..5daa69c
--- /dev/null
+++ b/glpk-5.0/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/glpk-5.0/src/misc/wclique.h b/glpk-5.0/src/misc/wclique.h
new file mode 100644
index 0000000..7ee4468
--- /dev/null
+++ b/glpk-5.0/src/misc/wclique.h
@@ -0,0 +1,31 @@
+/* wclique.h (maximum weight clique, Ostergard's algorithm) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2009 Free Software Foundation, Inc.
+* Written 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/>.
+***********************************************************************/
+
+#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/glpk-5.0/src/misc/wclique1.c b/glpk-5.0/src/misc/wclique1.c
new file mode 100644
index 0000000..c0cb082
--- /dev/null
+++ b/glpk-5.0/src/misc/wclique1.c
@@ -0,0 +1,315 @@
+/* wclique1.c (maximum weight clique, greedy heuristic) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2012-2018 Free Software Foundation, Inc.
+* Written 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 "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/glpk-5.0/src/misc/wclique1.h b/glpk-5.0/src/misc/wclique1.h
new file mode 100644
index 0000000..52596b1
--- /dev/null
+++ b/glpk-5.0/src/misc/wclique1.h
@@ -0,0 +1,32 @@
+/* wclique1.h (maximum weight clique, greedy heuristic) */
+
+/***********************************************************************
+* This code is part of GLPK (GNU Linear Programming Kit).
+* Copyright (C) 2012-2013 Free Software Foundation, Inc.
+* Written 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/>.
+***********************************************************************/
+
+#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 */