[med-svn] [qsopt-ex] 01/03: Imported Upstream version 2.5.10.3+ds

Afif Elghraoui afif-guest at moszumanska.debian.org
Thu Jan 21 09:19:33 UTC 2016


This is an automated email from the git hooks/post-receive script.

afif-guest pushed a commit to branch master
in repository qsopt-ex.

commit 4fcec2f79fa924d61b0c860b837d74fe13505883
Author: Afif Elghraoui <afif at ghraoui.name>
Date:   Fri Oct 9 01:57:14 2015 -0700

    Imported Upstream version 2.5.10.3+ds
---
 .gitignore                  |   56 +
 .travis.yml                 |   11 +
 Doxyfile                    | 1201 ++++++++++
 License.txt                 |  674 ++++++
 Makefile.am                 |  240 ++
 NEWS.md                     |   40 +
 README.md                   |   91 +
 bootstrap                   |    6 +
 configure.ac                |  123 +
 esolver/esolver.c           |  391 +++
 m4/README                   |    3 +
 qsopt_ex/QSopt_ex.h         |  114 +
 qsopt_ex/QSopt_ex_version.c |   33 +
 qsopt_ex/QSopt_ex_version.h |   26 +
 qsopt_ex/allocrus.c         |  284 +++
 qsopt_ex/allocrus.h         |  241 ++
 qsopt_ex/basicdefs.h        |  386 +++
 qsopt_ex/basis.c            | 1554 ++++++++++++
 qsopt_ex/basis.h            |   99 +
 qsopt_ex/bgetopt.c          |  132 +
 qsopt_ex/bgetopt.h          |   43 +
 qsopt_ex/binary.c           | 1756 ++++++++++++++
 qsopt_ex/binary.h           |   36 +
 qsopt_ex/dheaps_i.c         |  347 +++
 qsopt_ex/dheaps_i.h         |   72 +
 qsopt_ex/dstruct.c          |  499 ++++
 qsopt_ex/dstruct.h          |  134 ++
 qsopt_ex/editor.c           |  789 ++++++
 qsopt_ex/editor.h           |   35 +
 qsopt_ex/eg_elist.h         |  229 ++
 qsopt_ex/eg_exact.h         |   41 +
 qsopt_ex/eg_exutil.c        |  485 ++++
 qsopt_ex/eg_exutil.h        |  317 +++
 qsopt_ex/eg_io.c            |  695 ++++++
 qsopt_ex/eg_io.h            |  338 +++
 qsopt_ex/eg_lpnum.c         |  905 +++++++
 qsopt_ex/eg_lpnum.dbl.h     |  488 ++++
 qsopt_ex/eg_lpnum.h         |  706 ++++++
 qsopt_ex/eg_lpnum.mpf.h     |  628 +++++
 qsopt_ex/eg_lpnum.mpq.h     |  596 +++++
 qsopt_ex/eg_macros.c        |  148 ++
 qsopt_ex/eg_macros.h        |  270 +++
 qsopt_ex/eg_mem.h           |  194 ++
 qsopt_ex/eg_memslab.c       |  327 +++
 qsopt_ex/eg_memslab.h       |  418 ++++
 qsopt_ex/eg_nummacros.h     |   81 +
 qsopt_ex/eg_numutil.c       |  106 +
 qsopt_ex/eg_numutil.h       |   97 +
 qsopt_ex/eg_timer.h         |  143 ++
 qsopt_ex/exact.c            | 1824 ++++++++++++++
 qsopt_ex/exact.h            |  361 +++
 qsopt_ex/except.c           |   54 +
 qsopt_ex/except.h           |  170 ++
 qsopt_ex/factor.c           | 5602 +++++++++++++++++++++++++++++++++++++++++++
 qsopt_ex/factor.h           |  206 ++
 qsopt_ex/fct.c              | 2501 +++++++++++++++++++
 qsopt_ex/fct.h              |  250 ++
 qsopt_ex/format.c           |  231 ++
 qsopt_ex/format.h           |  137 ++
 qsopt_ex/lib.c              | 4348 +++++++++++++++++++++++++++++++++
 qsopt_ex/lib.h              |  150 ++
 qsopt_ex/logging-private.h  |  261 ++
 qsopt_ex/logging.c          |   82 +
 qsopt_ex/logging.h          |   26 +
 qsopt_ex/lp.c               | 1280 ++++++++++
 qsopt_ex/lp.h               |   74 +
 qsopt_ex/lpdata.c           |  744 ++++++
 qsopt_ex/lpdata.h           |  303 +++
 qsopt_ex/lpdefs.h           |  330 +++
 qsopt_ex/mps.c              | 1350 +++++++++++
 qsopt_ex/mps.h              |   53 +
 qsopt_ex/names.c            |  102 +
 qsopt_ex/names.h            |   35 +
 qsopt_ex/presolve.c         | 2634 ++++++++++++++++++++
 qsopt_ex/presolve.h         |   41 +
 qsopt_ex/price.c            | 1640 +++++++++++++
 qsopt_ex/price.h            |  222 ++
 qsopt_ex/priority.c         |  259 ++
 qsopt_ex/priority.h         |   75 +
 qsopt_ex/qs_config.h        |   70 +
 qsopt_ex/qsopt.c            | 3933 ++++++++++++++++++++++++++++++
 qsopt_ex/qsopt.h            |  358 +++
 qsopt_ex/qstruct.h          |   49 +
 qsopt_ex/ratio.c            | 1297 ++++++++++
 qsopt_ex/ratio.h            |   73 +
 qsopt_ex/rawlp.c            | 1765 ++++++++++++++
 qsopt_ex/rawlp.h            |  259 ++
 qsopt_ex/read_lp.c          |  837 +++++++
 qsopt_ex/read_lp.h          |  148 ++
 qsopt_ex/read_mps.c         |  522 ++++
 qsopt_ex/read_mps.h         |   97 +
 qsopt_ex/reader.c           |  283 +++
 qsopt_ex/reader.h           |   33 +
 qsopt_ex/readline.c         |   62 +
 qsopt_ex/readline.h         |   64 +
 qsopt_ex/reporter.c         |   94 +
 qsopt_ex/reporter.h         |   59 +
 qsopt_ex/simplex.c          | 3026 +++++++++++++++++++++++
 qsopt_ex/simplex.h          |   89 +
 qsopt_ex/sortrus.c          |  289 +++
 qsopt_ex/sortrus.h          |   44 +
 qsopt_ex/sortrus_common.c   |  426 ++++
 qsopt_ex/sortrus_common.h   |   63 +
 qsopt_ex/stddefs.h          |   34 +
 qsopt_ex/symtab.c           |  969 ++++++++
 qsopt_ex/symtab.h           |  141 ++
 qsopt_ex/trace.h            |   41 +
 qsopt_ex/urandom.c          |  169 ++
 qsopt_ex/urandom.h          |   59 +
 qsopt_ex/util.c             |  283 +++
 qsopt_ex/util.h             |  152 ++
 qsopt_ex/write_lp.c         |  262 ++
 qsopt_ex/write_lp.h         |   73 +
 qsopt_ex/zeit.c             |  292 +++
 qsopt_ex/zeit.h             |   65 +
 tap-driver.sh               |  651 +++++
 tests/eg_lpnum_ex.c         |  297 +++
 tests/eg_sloan.c            |  243 ++
 tests/eg_sloan.h            |    9 +
 tests/ftest.c               |  303 +++
 tests/ftest.h               |   21 +
 tests/solver.c              |  356 +++
 tests/solver.h              |   33 +
 tests/test_qs.c             |  243 ++
 124 files changed, 60609 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0c5a244
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,56 @@
+# Object files
+*.o
+*.ko
+*.obj
+*.elf
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Libraries
+*.lib
+*.a
+*.la
+*.lo
+
+# Shared objects (inc. Windows DLLs)
+*.dll
+*.so
+*.so.*
+*.dylib
+
+# Executables
+*.exe
+*.out
+*.app
+*.i*86
+*.x86_64
+*.hex
+
+# http://www.gnu.org/software/automake
+
+.deps
+.dirstamp
+Makefile
+Makefile.in
+
+/test-driver
+
+# http://www.gnu.org/software/autoconf
+
+/autom4te.cache
+/aclocal.m4
+/compile
+/configure
+/depcomp
+/install-sh
+/ltmain.sh
+/m4/*.m4
+/missing
+/stamp-h1
+/config.guess
+/config.h*
+/config.log
+/config.status
+/config.sub
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..0349c6d
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,11 @@
+language: c
+compiler:
+  - gcc
+  - clang
+before_install:
+  - sed -i -e 's|AC_PREREQ(2.69)|AC_PREREQ(2.68)|' configure.ac
+  - sudo apt-get update -qq
+install:
+  - sudo apt-get install -qq libgmp-dev libgmp10
+script: >
+  ./bootstrap && ./configure && make -j2 distcheck
diff --git a/Doxyfile b/Doxyfile
new file mode 100644
index 0000000..6c9ddee
--- /dev/null
+++ b/Doxyfile
@@ -0,0 +1,1201 @@
+# Doxyfile 1.4.3
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = QSopt_ex
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER         = 050502
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = doc
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 
+# 4096 sub-directories (in 2 levels) under the output directory of each output 
+# format and will distribute the generated files over these directories. 
+# Enabling this option can be useful when feeding doxygen a huge amount of 
+# source files, where putting all generated files in the same directory would 
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
+# documentation generated by doxygen is written. Doxygen will use this 
+# information to generate all constant output in the proper language. 
+# The default language is English, other supported languages are: 
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, 
+# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, 
+# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, 
+# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, 
+# Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc). 
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
+# the brief description of a member or function before the detailed description. 
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator 
+# that is used to form the text in various listings. Each string 
+# in this list, if found as the leading text of the brief description, will be 
+# stripped from the text and the result after processing the whole list, is 
+# used as the annotated text. Otherwise, the brief description is used as-is. 
+# If left blank, the following values are used ("$name" is automatically 
+# replaced with the name of the entity): "The $name class" "The $name widget" 
+# "The $name file" "is" "provides" "specifies" "contains" 
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       = 
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
+# Doxygen will generate a detailed section even if there is only a brief 
+# description.
+
+ALWAYS_DETAILED_SEC    = YES
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 
+# inherited members of a class in the documentation of that class as if those 
+# members were ordinary class members. Constructors, destructors and assignment 
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
+# path before files name in the file list and in the header files. If set 
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
+# can be used to strip a user-defined part of the path. Stripping is 
+# only done if one of the specified strings matches the left-hand part of 
+# the path. The tag can be used to show relative paths in the file list. 
+# If left blank the directory from which doxygen is run is used as the 
+# path to strip.
+
+STRIP_FROM_PATH        = 
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
+# the path mentioned in the documentation of a class, which tells 
+# the reader which header file to include in order to use a class. 
+# If left blank only the name of the header file containing the class 
+# definition is used. Otherwise one should specify the include paths that 
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    = 
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
+# (but less readable) file names. This can be useful is your file systems 
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
+# will interpret the first line (until the first dot) of a JavaDoc-style 
+# comment as the brief description. If set to NO, the JavaDoc 
+# comments will behave just like the Qt-style comments (thus requiring an 
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF      = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
+# comments) as a brief description. This used to be the default behaviour. 
+# The new default is to treat a multi-line C++ comment block as a detailed 
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member 
+# documentation.
+
+DETAILS_AT_TOP         = YES
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
+# tag is set to YES, then doxygen will reuse the documentation of the first 
+# member in the group (if any) for the other members of the group. By default 
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce 
+# a new page for each member. If set to NO, the documentation of a member will 
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 2
+
+# This tag can be used to specify a number of aliases that acts 
+# as commands in the documentation. An alias has the form "name=value". 
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
+# put the command \sideeffect (or @sideeffect) in the documentation, which 
+# will result in a user-defined paragraph with heading "Side Effects:". 
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                = 
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
+# sources only. Doxygen will then generate output that is more tailored for C. 
+# For instance, some of the names that are used will be different. The list 
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources 
+# only. Doxygen will then generate output that is more tailored for Java. 
+# For instance, namespaces will be presented as packages, qualified scopes 
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
+# the same type (for instance a group of public functions) to be put as a 
+# subgroup of that type (e.g. under the Public Functions section). Set it to 
+# NO to prevent subgrouping. Alternatively, this can be done per class using 
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
+# documentation are documented, even if no documentation was available. 
+# Private class members and static file members will be hidden unless 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = YES
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation.
+
+EXTRACT_STATIC         = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
+# defined locally in source files will be included in the documentation. 
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local 
+# methods, which are defined in the implementation section but not in 
+# the interface are included in the documentation. 
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) these members will be included in the 
+# various overviews, but no documentation section is generated. 
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
+# undocumented classes that are normally visible in the class hierarchy. 
+# If set to NO (the default) these classes will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
+# friend (class|struct|union) declarations. 
+# If set to NO (the default) these declarations will be included in the 
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
+# documentation blocks found inside the body of a function. 
+# If set to NO (the default) these blocks will be appended to the 
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = YES
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
+# file names in lower-case letters. If set to YES upper-case letters are also 
+# allowed. This is useful if you have classes or files whose names only differ 
+# in case and if your file system supports case sensitive file names. Windows 
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put a list of the files that are included by a file in the documentation 
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
+# will sort the (detailed) documentation of file and class members 
+# alphabetically by member name. If set to NO the members will appear in 
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
+# brief documentation of file, namespace and class members alphabetically 
+# by member name. If set to NO (the default) the members will appear in 
+# declaration order.
+
+SORT_BRIEF_DOCS        = YES
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
+# sorted by fully-qualified names, including namespaces. If set to 
+# NO (the default), the class list will be sorted only by class name, 
+# not including the namespace part. 
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the 
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = YES
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or 
+# disable (NO) the todo list. This list is created by putting \todo 
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or 
+# disable (NO) the test list. This list is created by putting \test 
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting 
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or define consists of for it to appear in 
+# the documentation. If the initializer consists of more lines than specified 
+# here it will be hidden. Use a value of 0 to hide initializers completely. 
+# The appearance of the initializer of individual variables and defines in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 300
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# If the sources in your project are distributed over multiple directories 
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 
+# in the documentation.
+
+SHOW_DIRECTORIES       = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that 
+# doxygen should invoke to get the current version for each file (typically from the 
+# version control system). Doxygen will invoke the program by executing (via 
+# popen()) the command <command> <input-file>, where <command> is the value of 
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file 
+# provided by doxygen. Whatever the progam writes to standard output 
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
+# potential errors in the documentation, such as not documenting some 
+# parameters in a documented function, or documenting parameters that 
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for 
+# functions that are documented, but have no documentation for their parameters 
+# or return value. If set to NO (the default) doxygen will only warn about 
+# wrong or incomplete parameter documentation, but not about the absence of 
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that 
+# doxygen can produce. The string should contain the $file, $line, and $text 
+# tags, which will be replaced by the file and line number from which the 
+# warning originated and the warning text. Optionally the format may contain 
+# $version, which will be replaced by the version of the file (if it could 
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning 
+# and error messages should be written. If left blank the output is written 
+# to stderr.
+
+WARN_LOGFILE           = doxygen.log
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT                  = 
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank the following patterns are tested: 
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx 
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
+
+FILE_PATTERNS          = *.c \
+                         *.h
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should 
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                = EGlib 
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or 
+# directories that are symbolic links (a Unix filesystem feature) are excluded 
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories.
+
+EXCLUDE_PATTERNS       = 
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH           = . EGlib
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+EXAMPLE_PATTERNS       = 
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are included in the documentation (see 
+# the \image command).
+
+IMAGE_PATH             = 
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should 
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
+# ignored.
+
+INPUT_FILTER           = 
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 
+# basis.  Doxygen will compare the file name with each pattern and apply the 
+# filter if there is a match.  The filters are a list of the form: 
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER 
+# is applied to all files.
+
+FILTER_PATTERNS        = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources. 
+# Note: To get rid of all source code in the generated output, make sure also 
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = NO
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default) 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default) 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code 
+# will point to the HTML generated by the htags(1) tool instead of doxygen 
+# built-in source browser. The htags tool is part of GNU's global source 
+# tagging system (see http://www.gnu.org/software/global/global.html). You 
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
+# will generate a verbatim copy of the header file for each class for 
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
+# of all compounds will be generated. Enable this if the project 
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all 
+# classes will be put under the same header in the alphabetical index. 
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header.
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER            = 
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
+# style sheet that is used by each HTML page. It can be used to 
+# fine-tune the look of the HTML output. If the tag is left blank doxygen 
+# will generate a default style sheet. Note that doxygen will try to copy 
+# the style sheet file to the HTML output directory, so don't put your own 
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        = 
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
+# files or namespaces will be aligned in HTML using tables. If set to 
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) 
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output directory.
+
+CHM_FILE               = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = YES
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = YES
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
+# top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20]) 
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that 
+# is generated for HTML Help). For this to work a browser that supports 
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW      = YES
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
+# used to set the initial width (in pixels) of the frame in which the tree 
+# is shown.
+
+TREEVIEW_WIDTH         = 150
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output.
+
+GENERATE_LATEX         = yes
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_LATEX          = YES
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = letter
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         = pst-all amsmath amssymb algorithmic
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
+# include the index chapters (such as File Index, Compound Index, etc.) 
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimized for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using WORD or other 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assignments. You only have to provide 
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = /home/daespino/man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .9
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD                = 
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
+# dump the program listings (including syntax highlighting 
+# and cross-referencing information) to the XML output. Note that 
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
+# generate a Perl module file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
+# nicely formatted so it can be parsed by a human reader.  This is useful 
+# if you want to understand what is going on.  On the other hand, if this 
+# tag is set to NO the size of the Perl module output will be much smaller 
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file 
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
+# This is useful so different doxyrules.make files included by the same 
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor.
+
+INCLUDE_PATH           = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of 
+# gcc). The argument of the tag is a list of macros of the form: name 
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed. To prevent a macro definition from being 
+# undefined via #undef or recursively expanded use the := operator 
+# instead of the = operator.
+
+PREDEFINED             = 
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
+# this tag can be used to specify a list of macro names that should be expanded. 
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all function-like macros that are alone 
+# on a line, have an all uppercase name, and do not end with a semicolon. Such 
+# function macros are typically used for boiler-plate code, and will confuse 
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = NO
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. 
+# Optionally an initial location of the external documentation 
+# can be added for each tagfile. The format of a tag file without 
+# this location is as follows: 
+#   TAGFILES = file1 file2 ... 
+# Adding location for the tag files is done as follows: 
+#   TAGFILES = file1=loc1 "file2 = loc2" ... 
+# where "loc1" and "loc2" can be relative or absolute paths or 
+# URLs. If a location is present for each tag, the installdox tool 
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen 
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               = EGlib/EGlib_Doxygen_Tags=http://www.dii.uchile.cl/~daespino/EGlib_doc
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       = ESolver_Doxygen_Tags
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed.
+
+ALLEXTERNALS           = YES
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 
+# or super classes. Setting the tag to NO turns the diagrams off. Note that 
+# this option is superseded by the HAVE_DOT option below. This is only a 
+# fallback. It is recommended to install and use dot, since it yields more 
+# powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = YES
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
+# collaboration diagrams in a style similar to the OMG's Unified Modeling 
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will 
+# generate a call dependency graph for every global function or class method. 
+# Note that enabling this option will significantly increase the time of a run. 
+# So in most cases it will be better to enable call graphs for selected 
+# functions only using the \callgraph command.
+
+CALL_GRAPH             = YES
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES 
+# then doxygen will show the dependencies a directory has on other directories 
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = gif
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               = 
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS           = 
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
+# graphs generated by dot. A depth value of 3 means that only nodes reachable 
+# from the root by following a path via at most 3 edges will be shown. Nodes 
+# that lay further from the root node will be omitted. Note that setting this 
+# option to 1 or 2 may greatly reduce the computation time needed for large 
+# code bases. Also note that a graph may be further truncated if the graph's 
+# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH 
+# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default), 
+# the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent 
+# background. This is disabled by default, which results in a white background. 
+# Warning: Depending on the platform used, enabling this option may lead to 
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to 
+# read).
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output 
+# files in one run (i.e. multiple -o and -T options on the command line). This 
+# makes dot run faster, but since only newer versions of dot (>1.8.10) 
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermediate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine   
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE           = NO
diff --git a/License.txt b/License.txt
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/License.txt
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program 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.
+
+    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..58fdab7
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,240 @@
+
+ACLOCAL_AMFLAGS = -I m4
+
+# These source files are used as is for the library
+MAIN_SOURCE_FILES = \
+	qsopt_ex/allocrus.c \
+	qsopt_ex/bgetopt.c \
+	qsopt_ex/eg_io.c \
+	qsopt_ex/eg_lpnum.c \
+	qsopt_ex/except.c \
+	qsopt_ex/urandom.c \
+	qsopt_ex/zeit.c \
+	qsopt_ex/names.c \
+	qsopt_ex/symtab.c \
+	qsopt_ex/util.c \
+	qsopt_ex/logging.c \
+	qsopt_ex/exact.c \
+	qsopt_ex/reporter.c \
+	qsopt_ex/eg_exutil.c \
+	qsopt_ex/eg_macros.c \
+	qsopt_ex/eg_memslab.c \
+	qsopt_ex/sortrus_common.c \
+	qsopt_ex/QSopt_ex_version.c
+
+# Header files
+PUBLIC_HEADER_FILES = \
+	qsopt_ex/bgetopt.h \
+	qsopt_ex/eg_io.h \
+	qsopt_ex/eg_lpnum.h \
+	qsopt_ex/urandom.h \
+	qsopt_ex/zeit.h \
+	qsopt_ex/names.h \
+	qsopt_ex/symtab.h \
+	qsopt_ex/exact.h \
+	qsopt_ex/reporter.h \
+	qsopt_ex/eg_exutil.h \
+	qsopt_ex/eg_macros.h \
+	qsopt_ex/eg_memslab.h \
+	qsopt_ex/eg_mem.h \
+	qsopt_ex/eg_elist.h \
+	qsopt_ex/eg_nummacros.h \
+	qsopt_ex/eg_lpnum.dbl.h \
+	qsopt_ex/eg_lpnum.mpq.h \
+	qsopt_ex/eg_lpnum.mpf.h \
+	qsopt_ex/eg_timer.h \
+	qsopt_ex/basicdefs.h \
+	qsopt_ex/stddefs.h \
+	qsopt_ex/sortrus_common.h \
+	qsopt_ex/QSopt_ex_version.h \
+	qsopt_ex/QSopt_ex.h \
+	qsopt_ex/logging.h
+
+PRIVATE_HEADER_FILES = \
+	qsopt_ex/allocrus.h \
+	qsopt_ex/except.h \
+	qsopt_ex/logging-private.h \
+	qsopt_ex/logging.h \
+	qsopt_ex/qs_config.h \
+	qsopt_ex/trace.h \
+	qsopt_ex/util.h
+
+# These source files have to be instantiated using the
+# type template mechanism
+TEMPLATE_SOURCE_FILES = \
+	qsopt_ex/rawlp.c \
+	qsopt_ex/mps.c \
+	qsopt_ex/read_mps.c \
+	qsopt_ex/lp.c \
+	qsopt_ex/write_lp.c \
+	qsopt_ex/read_lp.c \
+	qsopt_ex/readline.c \
+	qsopt_ex/lpdata.c \
+	qsopt_ex/presolve.c \
+	qsopt_ex/factor.c \
+	qsopt_ex/basis.c \
+	qsopt_ex/price.c \
+	qsopt_ex/dstruct.c \
+	qsopt_ex/simplex.c \
+	qsopt_ex/fct.c \
+	qsopt_ex/ratio.c \
+	qsopt_ex/lib.c \
+	qsopt_ex/binary.c \
+	qsopt_ex/qsopt.c \
+	qsopt_ex/sortrus.c \
+	qsopt_ex/dheaps_i.c \
+	qsopt_ex/priority.c \
+	qsopt_ex/editor.c \
+	qsopt_ex/format.c \
+	qsopt_ex/eg_numutil.c
+
+TEMPLATE_PUBLIC_HEADER_FILES = \
+	qsopt_ex/write_lp.h \
+	qsopt_ex/read_lp.h \
+	qsopt_ex/read_mps.h \
+	qsopt_ex/readline.h \
+	qsopt_ex/lpdata.h \
+	qsopt_ex/presolve.h \
+	qsopt_ex/factor.h \
+	qsopt_ex/basis.h \
+	qsopt_ex/price.h \
+	qsopt_ex/dstruct.h \
+	qsopt_ex/simplex.h \
+	qsopt_ex/fct.h \
+	qsopt_ex/ratio.h \
+	qsopt_ex/lib.h \
+	qsopt_ex/binary.h \
+	qsopt_ex/qsopt.h \
+	qsopt_ex/sortrus.h \
+	qsopt_ex/dheaps_i.h \
+	qsopt_ex/priority.h \
+	qsopt_ex/editor.h \
+	qsopt_ex/format.h \
+	qsopt_ex/lpdefs.h \
+	qsopt_ex/qstruct.h \
+	qsopt_ex/eg_numutil.h
+
+TEMPLATE_PRIVATE_HEADER_FILES = \
+	qsopt_ex/rawlp.h \
+	qsopt_ex/mps.h \
+	qsopt_ex/lp.h
+
+# Define specific template sources
+TEMPLATE_SOURCES_DBL = $(TEMPLATE_SOURCE_FILES:.c=_dbl.c)
+TEMPLATE_PUBLIC_HEADERS_DBL = \
+	$(TEMPLATE_PUBLIC_HEADER_FILES:.h=_dbl.h)
+TEMPLATE_HEADERS_DBL = \
+	$(TEMPLATE_PUBLIC_HEADERS_DBL) \
+	$(TEMPLATE_PRIVATE_HEADER_FILES:.h=_dbl.h)
+
+$(TEMPLATE_SOURCES_DBL): %_dbl.c: %.c Makefile
+	$(AM_V_GEN)$(MKDIR_P) $(@D) && ( \
+		echo "/* WARNING! This file was autogenerated from template */" && \
+		$(SED) -e 's|EGLPNUM_TYPENAME|dbl|g' -e 's|EGLPNUM_TYPE|double|g' $< ) > $@
+$(TEMPLATE_HEADERS_DBL): %_dbl.h: %.h Makefile
+	$(AM_V_GEN)$(MKDIR_P) $(@D) && ( \
+		echo "/* WARNING! This file was autogenerated from template */" && \
+		$(SED) -e 's|EGLPNUM_TYPENAME|dbl|g' -e 's|EGLPNUM_TYPE|double|g' $< ) > $@
+
+TEMPLATE_SOURCES_MPQ = $(TEMPLATE_SOURCE_FILES:.c=_mpq.c)
+TEMPLATE_PUBLIC_HEADERS_MPQ = \
+	$(TEMPLATE_PUBLIC_HEADER_FILES:.h=_mpq.h)
+TEMPLATE_HEADERS_MPQ = \
+	$(TEMPLATE_PUBLIC_HEADERS_MPQ) \
+	$(TEMPLATE_PRIVATE_HEADER_FILES:.h=_mpq.h)
+
+$(TEMPLATE_SOURCES_MPQ): %_mpq.c: %.c Makefile
+	$(AM_V_GEN)$(MKDIR_P) $(@D) && ( \
+		echo "/* WARNING! This file was autogenerated from template */" && \
+		$(SED) -e 's|EGLPNUM_TYPENAME|mpq|g' -e 's|EGLPNUM_TYPE|mpq_t|g' $< ) > $@
+$(TEMPLATE_HEADERS_MPQ): %_mpq.h: %.h Makefile
+	$(AM_V_GEN)$(MKDIR_P) $(@D) && ( \
+		echo "/* WARNING! This file was autogenerated from template */" && \
+		$(SED) -e 's|EGLPNUM_TYPENAME|mpq|g' -e 's|EGLPNUM_TYPE|mpq_t|g' $< ) > $@
+
+TEMPLATE_SOURCES_MPF = $(TEMPLATE_SOURCE_FILES:.c=_mpf.c)
+TEMPLATE_PUBLIC_HEADERS_MPF = \
+	$(TEMPLATE_PUBLIC_HEADER_FILES:.h=_mpf.h)
+TEMPLATE_HEADERS_MPF = \
+	$(TEMPLATE_PUBLIC_HEADERS_MPF) \
+	$(TEMPLATE_PRIVATE_HEADER_FILES:.h=_mpf.h)
+
+$(TEMPLATE_SOURCES_MPF): %_mpf.c: %.c Makefile
+	$(AM_V_GEN)$(MKDIR_P) $(@D) && ( \
+		echo "/* WARNING! This file was autogenerated from template */" && \
+		$(SED) -e 's|EGLPNUM_TYPENAME|mpf|g' -e 's|EGLPNUM_TYPE|mpf_t|g' $< ) > $@
+$(TEMPLATE_HEADERS_MPF): %_mpf.h: %.h Makefile
+	$(AM_V_GEN)$(MKDIR_P) $(@D) && ( \
+		echo "/* WARNING! This file was autogenerated from template */" && \
+		$(SED) -e 's|EGLPNUM_TYPENAME|mpf|g' -e 's|EGLPNUM_TYPE|mpf_t|g' $< ) > $@
+
+# Define complete set of template files
+TEMPLATE_FILES = \
+	$(TEMPLATE_SOURCES_DBL) $(TEMPLATE_HEADERS_DBL) \
+	$(TEMPLATE_SOURCES_MPQ) $(TEMPLATE_HEADERS_MPQ) \
+	$(TEMPLATE_SOURCES_MPF) $(TEMPLATE_HEADERS_MPF)
+
+# Tell automake that these are generated files
+BUILT_SOURCES = $(TEMPLATE_FILES)
+
+
+AM_CFLAGS = -I$(top_srcdir)/qsopt_ex -I$(top_builddir)/qsopt_ex
+
+# Library files
+lib_LTLIBRARIES = libqsopt_ex.la
+libqsopt_ex_la_SOURCES = \
+	$(MAIN_SOURCE_FILES) $(PUBLIC_HEADER_FILES) \
+	$(PRIVATE_HEADER_FILES)
+nodist_libqsopt_ex_la_SOURCES = \
+	$(TEMPLATE_FILES)
+libqsopt_ex_la_CFLAGS = \
+	$(AM_CFLAGS) $(GMP_CFLAGS)
+libqsopt_ex_la_LDFLAGS = \
+	-no-undefined \
+	-version-info $(LT_VERSION_INFO) \
+	$(AM_LDFLAGS)
+libqsopt_ex_la_LIBADD = $(GMP_LIBS)
+
+# Library header files
+headerdir = $(includedir)/qsopt_ex
+header_DATA = \
+	$(PUBLIC_HEADER_FILES) \
+	$(TEMPLATE_PUBLIC_HEADERS_DBL) \
+	$(TEMPLATE_PUBLIC_HEADERS_MPQ) \
+	$(TEMPLATE_PUBLIC_HEADERS_MPF)
+
+
+# Program files
+bin_PROGRAMS = esolver/esolver
+noinst_PROGRAMS = tests/test_qs tests/eg_sloan
+
+tests_test_qs_SOURCES = tests/test_qs.c
+tests_test_qs_CFLAGS = $(AM_CFLAGS) $(GMP_CFLAGS)
+tests_test_qs_LDADD = $(GMP_LIBS) libqsopt_ex.la
+
+tests_eg_sloan_SOURCES = tests/eg_sloan.c tests/eg_sloan.h
+tests_eg_sloan_CFLAGS = $(AM_CFLAGS) $(GMP_CFLAGS)
+tests_eg_sloan_LDADD = $(GMP_LIBS) libqsopt_ex.la
+
+esolver_esolver_SOURCES = esolver/esolver.c
+esolver_esolver_CFLAGS = $(AM_CFLAGS) $(GMP_CFLAGS)
+esolver_esolver_LDADD = $(GMP_LIBS) libqsopt_ex.la
+
+
+# Tests
+LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
+	$(top_srcdir)/tap-driver.sh
+TESTS = tests/test_qs
+
+
+# Additional files to be distributed. Always run `make distcheck`
+# to be sure all necessary files are distributed!
+EXTRA_DIST = \
+	README.md NEWS.md Doxyfile License.txt \
+	$(TEMPLATE_SOURCE_FILES) \
+	$(TEMPLATE_PUBLIC_HEADER_FILES) \
+	$(TEMPLATE_PRIVATE_HEADER_FILES)
+
+# Clean files
+CLEANFILES = \
+	$(TEMPLATE_FILES)
diff --git a/NEWS.md b/NEWS.md
new file mode 100644
index 0000000..c610a70
--- /dev/null
+++ b/NEWS.md
@@ -0,0 +1,40 @@
+
+2.5.10.3
+--------
+- All output to stdout/stderr now goes through an internal logging function.
+	The log messages can optionally be redirected to a user supplied function
+	(by default they are written to stderr).
+- Some headers that are internal to the library are no longer installed.
+- Restored possibility of compressing the output files (Denis Rosset).
+- Remove unused support for dmalloc.
+- Convert demo_qs into test_qs TAP test suite.
+
+2.5.10.2
+--------
+* (The patch `_p` version notation used in 2.5.10_p1 is not widely supported so
+  this release simply uses the dot notation.)
+* Removes Python module (moved to separate repository at
+  https://github.com/jonls/python-qsoptex).
+* Move library source files into `qsopt_ex` so the header files can be accessed
+  in the same way as when installed (`<qsopt_ex/XX.h>`).
+* Explicitly include the typename of template types when using a macro,
+  variable or function that is template generated. This removes the
+  build dependencies on Exuberant Ctags and GNU sed, as well as speeding up
+  the template generation significantly.
+* Remove util.c/util.h from template generation since the majority of symbols
+  are not template type specific.
+
+2.5.10_p1
+---------
+* Based on original version v2.5.10 published by Daniel Espinoza et al.
+* Changed to autotools-based build system.
+* Removed external dependency on EGlib.
+* Build library using libtool for portability.
+* Add Cython-based Python module to interface with libqsopt_ex.
+* Fix sprintf calls with missing format string.
+* Add missing header declarations, includes.
+* Clean up headers to make external use easier.
+* Remove some unused functions/macros that caused compiler warnings/errors.
+* Workaround: Writing solution to gz-file was broken; temporarily disabled gzip output.
+* Add README file with build instructions and code examples.
+* Add Travis CI build script.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..6b98b21
--- /dev/null
+++ b/README.md
@@ -0,0 +1,91 @@
+
+QSopt Exact
+===========
+
+[![Build Status](https://travis-ci.org/jonls/qsopt-ex.svg?branch=master)](https://travis-ci.org/jonls/qsopt-ex)
+
+Exact linear programming solver. This is a fork of QSopt_ex, originally
+released by Daniel Espinoza _et al._
+[version 2.5.10](http://www.math.uwaterloo.ca/~bico/qsopt/ex/) under the
+GPL 3 (or later). The authors of QSopt_ex also granted a free license to
+use the software for research purposes but this license does not extend
+to the changes introduced by this project.
+
+The goal of this fork is to update the software, and in particular the
+build system, to be more friendly. In addition the external
+dependencies have been reduced by removing the dependency on EGlib,
+GNU awk and Exuberant Ctags.
+
+Dependencies
+------------
+
+- C compiler: Tested with GCC and Clang.
+- Libtool: To build QSopt_ex as a library.
+- [GNU MP](https://gmplib.org/): Tested with 6.0.0. The original authors
+  stated that QSopt_ex was tested with the 4.x.x and with 5.0.x version
+  series. The authors also noted that GNU MP should be compiled using option
+  `--enable-alloca=malloc-reentrant` but this does not seem to be required
+  anymore.
+- libz: To read/write gz-compresed files.
+- libbz2 To read/write bz2-compresed files.
+
+Installing
+----------
+
+If you have just cloned the source code with Git, run the `bootstrap`
+script to automatically set up the build system.
+
+``` shell
+$ ./bootstrap
+```
+
+This script calls `autoreconf` and `libtoolize` with the proper
+arguments. This will also regenerate the `configure` script. It is
+recommended to build out of source directory. This is simply done
+by running `configure` from an empty directory.
+
+``` shell
+$ mkdir build && cd build
+$ ../configure
+```
+
+Use `./configure --help` to see available options. Now the test
+programs and library can be compiled using `make`. It is possible
+to do a parallel build using the `-jX` switch where `X` is the number
+of parallel processes.
+
+``` shell
+$ make -j4
+```
+
+To install the libraries and executables run
+
+``` shell
+$ make install
+```
+
+This will install into the prefix specified when `configure` was run.
+
+Running the solver
+------------------
+
+The exact solver is available though the `esolver` executable. It can be
+invoked to solve an LP or MPS format problem.
+
+``` shell
+$ ./esolver cycle.mps
+```
+
+See `./esolver -h` for more information on command line options.
+
+Using it as a library
+---------------------
+To see an example of how to use this software as a C library, see the test
+[tests/test_qs.c](tests/test_qs.c) or the program
+[esolver/esolver.c](esolver/esolver.c).
+
+Python module
+-------------
+
+The Python module has moved to a separate repository at
+[jonls/python-qsoptex](https://github.com/jonls/python-qsoptex).
diff --git a/bootstrap b/bootstrap
new file mode 100755
index 0000000..8724a10
--- /dev/null
+++ b/bootstrap
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+# change to root directory
+cd $(dirname "$0")
+
+autoreconf --force --install --verbose
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..e99e21d
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,123 @@
+#                                               -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.69)
+AC_INIT([QSopt_ex], [2.5.10.3], [https://github.com/jonls/qsopt-ex/issues])
+AC_CONFIG_SRCDIR([qsopt_ex/QSopt_ex.h])
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_MACRO_DIR([m4])
+AC_REQUIRE_AUX_FILE([tap-driver.sh])
+AM_INIT_AUTOMAKE([foreign subdir-objects dist-xz])
+
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+AC_USE_SYSTEM_EXTENSIONS
+
+### Versioning
+# This is the internal library version information used by libtool.
+# IT DOES NOT FOLLOW THE NORMAL RELEASE VERSIONING!
+# Instead follow these rules from the libtool documentation:
+# 1. Update the version information only immediately before a public release of your software.
+# 2. If the library source code has changed at all since the last update, then increment revision.
+#    ("c:r:a" becomes "c:r+1:a")
+# 3. If any interfaces have been added, removed, or changed since the last update, increment current,
+#    and set revision to 0. ("c+1:0:a")
+# 4. If any interfaces have been added since the last public release, then increment age.
+# 5. If any interfaces have been removed since the last public release, then set age to 0.
+
+m4_define([lt_current],[3])
+m4_define([lt_revision],[0])
+m4_define([lt_age],[1])
+m4_define([lt_version_info],[lt_current:lt_revision:lt_age])
+AC_SUBST([LT_VERSION_INFO], [lt_version_info])
+
+### Checks for programs.
+AC_PROG_CC
+AC_PROG_SED
+AC_PROG_LIBTOOL
+
+
+### Check for debug mode
+AC_ARG_ENABLE([debug],
+	[AS_HELP_STRING([--enable-debug], [enable debug mode @<:@default=yes@:>@])],
+	[enable_debug=$enable])
+AS_IF([test "x$enable_debug" != xno], [
+	AC_SUBST([ENABLE_DEBUG],[1])
+	AC_DEFINE([DEBUG], [1], [Enable debug mode])
+], [
+  AC_SUBST([ENABLE_DEBUG],[0])
+	AC_DEFINE([DEBUG], [0], [Disable debug mode])
+])
+
+### Check for verbosity level
+AC_ARG_ENABLE([verbose-level],
+	[AS_HELP_STRING([--enable-verbose-level], [fix verbose-level for compile-time routines @<:@default=100@:>@])],
+	[],[enable_verbose_level=100])
+AC_DEFINE_UNQUOTED([VERBOSE_LEVEL],[$enable_verbose_level],[Compilation-time verbose level])
+
+### Check for libgmp
+AC_ARG_VAR([GMP_CFLAGS], [C compiler flags for GMP, overriding automatic detection])
+AC_ARG_VAR([GMP_LIBS], [linker flags for GMP, overriding automatic detection])
+AS_IF([test -z "$GMP_CFLAGS" -a -z "$GMP_LIBS"], [
+	AC_CHECK_LIB([gmp], [__gmpz_init], [
+		GMP_CFLAGS=""
+		GMP_LIBS="-lgmp"
+	], [AC_MSG_ERROR([GNU MP not found, see https://gmplib.org/])])
+])
+
+### Check for libz
+AC_CHECK_LIB([z], [gzopen], [], AC_MSG_NOTICE([compiling without libz]))
+
+### Check for libbz2
+AC_CHECK_LIB([bz2], [BZ2_bzopen], [], AC_MSG_NOTICE([compiling without libbz2]))
+
+### Check for math library
+AC_SEARCH_LIBS([pow], [m], [], [
+	AC_MSG_ERROR([unable to find library with math functions (pow)])])
+
+### Check for pthread library
+AC_CHECK_LIB([pthread], [pthread_mutex_lock])
+
+### Checks for header files.
+AC_HEADER_STDC
+AC_HEADER_TIME
+AC_CHECK_HEADERS([errno.h float.h getopt.h inttypes.h limits.h math.h setjmp.h signal.h stdarg.h stdint.h stdio.h string.h sys/param.h sys/resource.h sys/time.h sys/times.h sys/utsname.h unistd.h])
+
+### Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_C_TYPEOF
+AC_TYPE_INT16_T
+AC_TYPE_INT32_T
+AC_TYPE_INT64_T
+AC_TYPE_INT8_T
+AC_TYPE_SIGNAL
+AC_TYPE_SIZE_T
+AC_TYPE_SSIZE_T
+AC_TYPE_UINT16_T
+AC_TYPE_UINT32_T
+AC_TYPE_UINT64_T
+AC_TYPE_UINT8_T
+
+### Checks for library functions.
+AC_FUNC_MALLOC
+AC_FUNC_MEMCMP
+AC_FUNC_REALLOC
+AC_FUNC_STRTOD
+AC_FUNC_VPRINTF
+AC_CHECK_FUNCS([floor memset pow sqrt strdup strerror uname posix_memalign sleep getrusage times clock sigaction signal])
+
+### Print output files
+AC_CONFIG_FILES([
+	Makefile
+])
+AC_OUTPUT
+
+
+echo "
+ $PACKAGE_NAME $VERSION
+
+    prefix:		${prefix}
+    compiler:		${CC}
+    cflags:		${CFLAGS}
+    ldflags:		${LDFLAGS}
+"
diff --git a/esolver/esolver.c b/esolver/esolver.c
new file mode 100644
index 0000000..6694518
--- /dev/null
+++ b/esolver/esolver.c
@@ -0,0 +1,391 @@
+/* ========================================================================= */
+/* ESolver "Exact Mixed Integer Linear Solver" provides some basic structures 
+ * and algorithms commons in solving MIP's
+ *
+ * Copyright (C) 2008 David Applegate, Bill Cook, Sanjeeb Dash, Daniel Espinoza.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library 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 Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
+ * */
+/* ========================================================================= */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <signal.h>
+#include <limits.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include "QSopt_ex.h"
+
+#include "except.h"
+#include "logging-private.h"
+#include "qs_config.h"
+
+/* ========================================================================= */
+/** @name static parameters for the main program */
+/*@{*/
+static char *fname = 0;
+static int lpfile = 0;
+static int usescaling = 1;
+static int showversion = 0;
+static int simplexalgo = PRIMAL_SIMPLEX;
+static int pstrategy = QS_PRICE_PSTEEP;
+static int dstrategy = QS_PRICE_DSTEEP;
+static unsigned precision = 128;
+static int printsol = 0;
+static char *solname = 0;
+static char *readbasis = 0;
+static char *writebasis = 0;
+/** @brief maximum running time */
+static double max_rtime = INT_MAX;
+/** @brief maximum memory usage */
+static unsigned long memlimit = UINT_MAX;
+/*@}*/
+/* ========================================================================= */
+/** @brief Display options to the screen */
+static void usage (char *s)
+{
+	fprintf (stderr, "Usage: %s [- below -] prob_file\n", s);
+	fprintf (stderr, "   -b f  write basis to file f\n");
+	fprintf (stderr, "   -B f  read initial basis from file f\n");
+#if 0
+	fprintf (stderr, "   -I    solve the MIP using BestBound\n");
+	fprintf (stderr, "   -E    edit problem after solving initial version\n");
+#endif
+	fprintf (stderr, "   -L    input file is in lp format (default: mps)\n");
+	fprintf (stderr, "   -O    write the final solution to the given file\n");
+	fprintf (stderr, "         append .gz/.bz2 to the .sol extension to compress the file\n");
+	fprintf (stderr, "   -p #  run primal simplex with pricing rule #\n");
+	fprintf (stderr,
+					 "         (%d-Dantzig, %d-Devex, %d-Steep (default), %d-Partial\n",
+					 QS_PRICE_PDANTZIG, QS_PRICE_PDEVEX, QS_PRICE_PSTEEP,
+					 QS_PRICE_PMULTPARTIAL);
+	fprintf (stderr,
+					 "   -P #  number of bits to use for the float representation (default: 128)\n");
+	fprintf (stderr, "   -d #  run dual simplex with pricing rule #\n");
+	fprintf (stderr, "         (%d-Dantzig, %d-Steep, %d-Partial, %d-Devex)\n",
+					 QS_PRICE_DDANTZIG, QS_PRICE_DSTEEP, QS_PRICE_DMULTPARTIAL,
+					 QS_PRICE_DDEVEX);
+	fprintf (stderr, "   -S    do NOT scale the initial LP\n");
+	fprintf (stderr, "   -v    print QSopt version number\n");
+	fprintf (stderr, "   -R n  maximum running time allowed, default %lf\n",
+						max_rtime);
+	fprintf (stderr, "   -m n  maximum memory usage allowed, default %lu\n", 
+						memlimit);
+}
+
+/* ========================================================================= */
+/** @brief decide if a given file is mps or lp (only by extension) */
+static void get_ftype (char const *const name,
+											 int *ftype)
+{
+	char buff[4096],*argv[128];
+	int argc;
+	*ftype = 0; /* by default, file is MPS */
+	snprintf(buff,4096,"%s",name);
+	EGioNParse(buff,128,"."," ",&argc,argv);
+	argc-=1;
+	if(argc)
+	{
+		if(strncmp(argv[argc],"gz",3)==0) argc-=1;
+		else if(strncmp(argv[argc],"GZ",3)==0) argc-=1;
+		else if(strncmp(argv[argc],"bz2",4)==0) argc-=1;
+		else if(strncmp(argv[argc],"BZ2",4)==0) argc-=1;
+	}
+	if(argc)
+	{
+		if(strncmp(argv[argc],"lp",3)==0) *ftype=1;
+		else if(strncmp(argv[argc],"LP",3)==0) *ftype=1;
+	}
+}
+/* ========================================================================= */
+/** @brief signal handler for time-limit reached */
+static void sighandler(int s)
+{
+	switch(s)
+	{
+		case SIGXCPU:
+			fprintf(stderr,"TIME_LIMIT_REACHED (ending now)\n");
+			exit(EXIT_FAILURE);
+		default:
+			fprintf(stderr,"Unknown signal %d (ending now)\n",s);
+			exit(EXIT_FAILURE);
+	}
+}
+/* ========================================================================= */
+/** @brief function to handle resource usage limits */
+static int mem_limits(void)
+{
+	int rval = 0;
+	struct rlimit mlim;
+	rval = getrlimit(RLIMIT_CPU,&mlim);
+	CHECKRVAL(rval);
+	fprintf(stderr, "Cur rtime limit %ld, trying to set to %lg\n", mlim.rlim_cur, max_rtime);
+	if(max_rtime > mlim.rlim_max) max_rtime = (double)mlim.rlim_max;
+	mlim.rlim_cur = (rlim_t)max_rtime;
+	rval = setrlimit(RLIMIT_CPU,&mlim);
+	TESTERRNOIF(rval);
+	fprintf(stderr, "New rtime limit %ld (%.3lg)\n", mlim.rlim_cur, max_rtime);
+	rval = getrlimit(RLIMIT_DATA,&mlim);
+	TESTERRNOIF(rval);
+	fprintf(stderr, "Cur data limit %ld,%ld (soft,hard)\n", mlim.rlim_cur, 
+					mlim.rlim_max);
+	mlim.rlim_cur = memlimit;				
+	rval = setrlimit(RLIMIT_DATA,&mlim);				
+	TESTERRNOIF(rval);
+	rval = getrlimit(RLIMIT_DATA,&mlim);
+	TESTERRNOIF(rval);
+	fprintf(stderr, "New data limit %ld,%ld (soft,hard)\n", mlim.rlim_cur, 
+					mlim.rlim_max);
+	rval = getrlimit(RLIMIT_AS,&mlim);
+	TESTERRNOIF(rval);
+	fprintf(stderr, "Cur address space limit %ld,%ld (soft,hard)\n", 
+					mlim.rlim_cur, mlim.rlim_max);
+	mlim.rlim_cur = memlimit;	
+	rval = setrlimit(RLIMIT_AS,&mlim);				
+	TESTERRNOIF(rval);
+	rval = getrlimit(RLIMIT_AS,&mlim);
+	TESTERRNOIF(rval);
+	fprintf(stderr, "New address space limit %ld,%ld (soft,hard)\n", 
+					mlim.rlim_cur, mlim.rlim_max);
+	mlim.rlim_cur = 0;
+	rval = setrlimit(RLIMIT_CORE,&mlim);				
+	TESTERRNOIF(rval);
+	rval = getrlimit(RLIMIT_CORE,&mlim);
+	TESTERRNOIF(rval);
+	fprintf(stderr, "New core dump space limit %ld,%ld (soft,hard)\n", 
+					mlim.rlim_cur, mlim.rlim_max);
+	/* set signal handler for SIGXCPU */
+	signal(SIGXCPU,sighandler);
+	return rval;
+}
+/* ========================================================================= */
+/** @brief parssing options for the program */
+static int parseargs (int ac,
+											char **av)
+{
+	int c;
+	int boptind = 1;
+	char *boptarg = 0;
+
+	while ((c =
+					ILLutil_bix_getopt (ac, av, "b:B:d:EILm:O:p:P:R:Sv", &boptind,
+															&boptarg)) != EOF)
+		switch (c)
+		{
+		case 'm':
+			memlimit = strtoul(boptarg,0,10);
+			break;
+		case 'R':
+			max_rtime = strtod(boptarg,0);
+			break;
+		case 'b':
+			writebasis = boptarg;
+			break;
+		case 'B':
+			readbasis = boptarg;
+			break;
+		case 'P':
+			precision = atoi (boptarg);
+			break;
+		case 'd':
+			simplexalgo = DUAL_SIMPLEX;
+			dstrategy = atoi (boptarg);
+			break;
+		case 'L':
+			lpfile = 1;
+			break;
+		case 'O':
+			printsol = 1;
+			solname = strdup(boptarg);
+			break;
+		case 'p':
+			simplexalgo = PRIMAL_SIMPLEX;
+			pstrategy = atoi (boptarg);
+			break;
+		case 'S':
+			usescaling = 0;
+			break;
+		case 'v':
+			showversion = 1;
+			break;
+		case '?':
+		default:
+			usage (av[0]);
+			return 1;
+		}
+	if ((boptind == ac) && (showversion))
+	{
+		char *buf = 0;
+		buf = mpq_QSversion ();
+		printf ("%s\n", buf);
+		mpq_QSfree ((void *) buf);
+		exit(0);
+	}
+	if (boptind != (ac - 1))
+	{
+		usage (av[0]);
+		return 1;
+	}
+
+	fname = av[boptind++];
+	fprintf (stderr, "Reading problem from %s\n", fname);
+	mem_limits();
+	return 0;
+}
+
+/* ========================================================================= */
+/** @brief the main thing! */
+/* ========================================================================= */
+int main (int ac,
+					char **av)
+{
+	int rval = 0,
+	  status = 0;
+	mpq_QSdata *p_mpq = 0;
+	QSbasis *basis = 0;
+	ILLutil_timer timer_solve;
+	ILLutil_timer timer_read;
+	int ftype = 0;								/* 0 mps, 1 lp */
+	mpq_t *y_mpq = 0,
+	 *x_mpq = 0;
+	QSopt_ex_version();
+	QSexactStart();
+	/* parse arguments and initialize EGlpNum related things */
+	rval = parseargs (ac, av);
+	QSexact_set_precision (precision);
+	if (rval)
+		goto CLEANUP;
+	if (writebasis)
+	{
+		basis = EGsMalloc (QSbasis, 1);
+		memset (basis, 0, sizeof (QSbasis));
+	}
+
+	/* just for the bell's and wistle */
+	if (showversion)
+	{
+		char *buf = 0;
+		buf = mpq_QSversion ();
+		if (buf == 0)
+		{
+			ILL_CLEANUP;
+		}
+		else
+		{
+			printf ("%s\n", buf);
+			mpq_QSfree ((void *) buf);
+		}
+	}
+
+	/* get the file type */
+	if (lpfile)
+		ftype = 1;
+	else
+		get_ftype (fname, &ftype);
+
+	/* read the mpq problem */
+	ILLutil_init_timer (&timer_read, "SOLVER_READ_MPQ");
+	ILLutil_start_timer (&timer_read);
+	if (ftype == 1)
+	{
+		p_mpq = mpq_QSread_prob ((const char *) fname, "LP");
+		if (p_mpq == 0)
+		{
+			fprintf (stderr, "Could not read lp file.\n");
+			rval = 1;
+			ILL_CLEANUP_IF (rval);
+		}
+	}
+	else
+	{
+		p_mpq = mpq_QSread_prob ((const char *) fname, "MPS");
+		if (p_mpq == 0)
+		{
+			fprintf (stderr, "Could not read mps file.\n");
+			rval = 1;
+			ILL_CLEANUP_IF (rval);
+		}
+	}
+
+	/* and get the basis if needed */
+	if (readbasis)
+	{
+		rval = mpq_QSread_and_load_basis (p_mpq, (const char *) readbasis);
+		ILL_CLEANUP_IF (rval);
+		if (basis)
+			mpq_QSfree_basis (basis);
+		basis = mpq_QSget_basis (p_mpq);
+	}
+	ILLutil_stop_timer (&timer_read, 1);
+	/* set the readed flags */
+	rval = mpq_QSset_param (p_mpq, QS_PARAM_SIMPLEX_DISPLAY, 1)
+		|| mpq_QSset_param (p_mpq, QS_PARAM_PRIMAL_PRICING, pstrategy)
+		|| mpq_QSset_param (p_mpq, QS_PARAM_DUAL_PRICING, dstrategy)
+		|| mpq_QSset_param (p_mpq, QS_PARAM_SIMPLEX_SCALING, usescaling);
+	ILL_CLEANUP_IF (rval);
+	if (printsol)
+	{
+		x_mpq = mpq_EGlpNumAllocArray (p_mpq->qslp->ncols);
+		y_mpq = mpq_EGlpNumAllocArray (p_mpq->qslp->nrows);
+	}
+	ILLutil_init_timer (&timer_solve, "SOLVER");
+	ILLutil_start_timer (&timer_solve);
+	rval = QSexact_solver (p_mpq, x_mpq, y_mpq, basis, simplexalgo, &status);
+	ILL_CLEANUP_IF (rval);
+	ILLutil_stop_timer (&timer_solve, 1);
+	if (printsol)
+	{
+		char out_f_name[1024];
+		EGioFile_t *out_f;
+		sprintf (out_f_name, "%s", solname);
+		out_f = EGioOpen (out_f_name, "w");
+		switch (status)
+		{
+		case QS_LP_OPTIMAL:
+			EGioPrintf (out_f, "status = OPTIMAL\n");
+			rval = QSexact_print_sol (p_mpq, out_f);
+			CHECKRVALG(rval,CLEANUP);
+			break;
+		case QS_LP_INFEASIBLE:
+			EGioPrintf (out_f, "status = INFEASIBLE\n");
+			break;
+		case QS_LP_UNBOUNDED:
+			EGioPrintf (out_f, "status = UNBOUNDED\n");
+			break;
+		default:
+			EGioPrintf (out_f, "status = UNDEFINED\n");
+			break;
+		}
+		EGioClose (out_f);
+	}
+	/* ending */
+CLEANUP:
+	EGfree(solname);
+	mpq_EGlpNumFreeArray (x_mpq);
+	mpq_EGlpNumFreeArray (y_mpq);
+	/* free the last allocated basis, and if we wanted to save it, do so */
+	if (basis)
+	{
+		if (writebasis)
+			rval = mpq_QSwrite_basis (p_mpq, 0, writebasis);
+	}
+	mpq_QSfree_basis (basis);
+	mpq_QSfree_prob (p_mpq);
+	QSexactClear();
+	return rval;									/* main return */
+}
diff --git a/m4/README b/m4/README
new file mode 100644
index 0000000..120657b
--- /dev/null
+++ b/m4/README
@@ -0,0 +1,3 @@
+This README is here so that git will keep the m4 directory.
+The m4 directory must be here to work around a bug in autotools
+where autoreconf fails if it is not present.
diff --git a/qsopt_ex/QSopt_ex.h b/qsopt_ex/QSopt_ex.h
new file mode 100644
index 0000000..9bea725
--- /dev/null
+++ b/qsopt_ex/QSopt_ex.h
@@ -0,0 +1,114 @@
+/* QSopt_ex.h -- QSopt_ex main header file
+ * This file is part of QSopt_ex.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library 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 Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Copyright (c) 2014-2015  Jon Lund Steffensen <jonlst at gmail.com>
+ */
+
+#ifndef QSOPT_EX_H
+#define QSOPT_EX_H
+
+#include "eg_elist.h"
+#include "eg_io.h"
+#include "eg_lpnum.h"
+#include "eg_macros.h"
+#include "eg_mem.h"
+#include "eg_memslab.h"
+
+#include "eg_lpnum.dbl.h"
+#include "eg_lpnum.mpf.h"
+#include "eg_lpnum.mpq.h"
+
+#include "basicdefs.h"
+#include "urandom.h"
+#include "symtab.h"
+#include "reporter.h"
+#include "bgetopt.h"
+#include "zeit.h"
+#include "logging.h"
+
+#include "QSopt_ex_version.h"
+
+/* Double template headers */
+#include "qstruct_dbl.h"
+#include "editor_dbl.h"
+#include "dstruct_dbl.h"
+#include "factor_dbl.h"
+#include "lpdefs_dbl.h"
+#include "readline_dbl.h"
+#include "lpdata_dbl.h"
+#include "basis_dbl.h"
+#include "dheaps_i_dbl.h"
+#include "qsopt_dbl.h"
+#include "format_dbl.h"
+#include "price_dbl.h"
+#include "priority_dbl.h"
+#include "ratio_dbl.h"
+#include "read_lp_dbl.h"
+#include "read_mps_dbl.h"
+#include "simplex_dbl.h"
+#include "write_lp_dbl.h"
+#include "lib_dbl.h"
+#include "eg_numutil_dbl.h"
+
+/* MPQ template headers */
+#include "qstruct_mpq.h"
+#include "editor_mpq.h"
+#include "dstruct_mpq.h"
+#include "factor_mpq.h"
+#include "lpdefs_mpq.h"
+#include "readline_mpq.h"
+#include "lpdata_mpq.h"
+#include "basis_mpq.h"
+#include "dheaps_i_mpq.h"
+#include "qsopt_mpq.h"
+#include "format_mpq.h"
+#include "price_mpq.h"
+#include "priority_mpq.h"
+#include "ratio_mpq.h"
+#include "read_lp_mpq.h"
+#include "read_mps_mpq.h"
+#include "simplex_mpq.h"
+#include "write_lp_mpq.h"
+#include "lib_mpq.h"
+#include "eg_numutil_mpq.h"
+
+/* MPF template headers */
+#include "qstruct_mpf.h"
+#include "editor_mpf.h"
+#include "dstruct_mpf.h"
+#include "factor_mpf.h"
+#include "lpdefs_mpf.h"
+#include "readline_mpf.h"
+#include "lpdata_mpf.h"
+#include "basis_mpf.h"
+#include "dheaps_i_mpf.h"
+#include "qsopt_mpf.h"
+#include "format_mpf.h"
+#include "price_mpf.h"
+#include "priority_mpf.h"
+#include "ratio_mpf.h"
+#include "read_lp_mpf.h"
+#include "read_mps_mpf.h"
+#include "simplex_mpf.h"
+#include "write_lp_mpf.h"
+#include "lib_mpf.h"
+#include "eg_numutil_mpf.h"
+
+#include "exact.h"
+#include "eg_exutil.h"
+
+#endif /* !QSOPT_EX_H */
diff --git a/qsopt_ex/QSopt_ex_version.c b/qsopt_ex/QSopt_ex_version.c
new file mode 100644
index 0000000..a07bffa
--- /dev/null
+++ b/qsopt_ex/QSopt_ex_version.c
@@ -0,0 +1,33 @@
+/* QSopt_ex_version.c -- QSopt_ex version information
+ * This file is part of QSopt_ex.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library 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 Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Copyright (c) 2014-2015  Jon Lund Steffensen <jonlst at gmail.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "logging-private.h"
+
+void
+QSopt_ex_version(void)
+{
+	QSlog("Using %s %s", PACKAGE_NAME, PACKAGE_VERSION);
+}
diff --git a/qsopt_ex/QSopt_ex_version.h b/qsopt_ex/QSopt_ex_version.h
new file mode 100644
index 0000000..12d221a
--- /dev/null
+++ b/qsopt_ex/QSopt_ex_version.h
@@ -0,0 +1,26 @@
+/* QSopt_ex_version.h -- QSopt_ex version information header
+ * This file is part of QSopt_ex.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library 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 Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Copyright (c) 2014  Jon Lund Steffensen <jonlst at gmail.com> 
+ */
+
+#ifndef QSOPT_EX_VERSION_H
+#define QSOPT_EX_VERSION_H
+
+void QSopt_ex_version(void);
+
+#endif /* !QSOPT_EX_VERSION_H */
diff --git a/qsopt_ex/allocrus.c b/qsopt_ex/allocrus.c
new file mode 100644
index 0000000..17b071a
--- /dev/null
+++ b/qsopt_ex/allocrus.c
@@ -0,0 +1,284 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCSINFO $Id: allocrus.c,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of CONCORDE                                           */
+/*                                                                          */
+/*  (c) Copyright 1995--1999 by David Applegate, Robert Bixby,              */
+/*  Vasek Chvatal, and William Cook                                         */
+/*                                                                          */
+/*  Permission is granted for academic research use.  For other uses,       */
+/*  contact the authors for licensing options.                              */
+/*                                                                          */
+/*  Use at your own risk.  We make no guarantees about the                  */
+/*  correctness or usefulness of this code.                                 */
+/*                                                                          */
+/****************************************************************************/
+
+/****************************************************************************/
+/*                                                                          */
+/*                   MEMORY ALLOCATION MACROS                               */
+/*                                                                          */
+/*                           TSP CODE                                       */
+/*                                                                          */
+/*                                                                          */
+/*  Written by:  Applegate, Bixby, Chvatal, and Cook                        */
+/*  Date: February 2, 1995 (cofeb16)                                        */
+/*                                                                          */
+/*                                                                          */
+/*    EXPORTED FUNCTIONS:                                                   */
+/*                                                                          */
+/*  void *ILLutil_allocrus (size_t size)                                    */
+/*    RETURNS a pointer to an allocated block of "size" memory.             */
+/*                                                                          */
+/*  void ILLutil_freerus (void *ptr)                                        */
+/*    FREES ptr.                                                            */
+/*                                                                          */
+/*  void *ILLutil_reallocrus (void *ptr, size_t size)                       */
+/*    REALLOCS ptr to size bytes.                                           */
+/*                                                                          */
+/*  int ILLutil_reallocrus_scale (void **pptr, int *pnnum, int count,       */
+/*      double scale, size_t size)                                          */
+/*    void **pptr (a reference to the pointer to the allocated space)       */
+/*    int *pnnum (a reference to the number of objects in the               */
+/*                allocated space)                                          */
+/*    int count (a minimum value for the new nnum)                          */
+/*    double scale (a scale factor to apply to nnum)                        */
+/*    int size (the size of objects to be realloced)                        */
+/*    RETURNS 0 if *pptr was successfully changed to point to at            */
+/*            least max(*pnnum*scale, *pnnum+1000, count) objects.          */
+/*            *pnnum is changed to the new object count.                    */
+/*            Otherwise, prints an error message, leaves *pptr and          */
+/*            *pnnum alone, and returns nonzero.                            */
+/*                                                                          */
+/*  int ILLutil_reallocrus_count (void **pptr, int count,                   */
+/*      size_t size)                                                        */
+/*    void **pptr (a reference to the pointer to the allocated space)       */
+/*    int count (number of objects to be realloced)                         */
+/*    int size (the size of the objects to be realloced)                    */
+/*    RETURNS 0 is successful, and 1 if the realloc failed.                 */
+/*                                                                          */
+/*  ILLbigchunkptr *ILLutil_bigchunkalloc (void)                            */
+/*         RETURNS a ILLbigchunkptr with the "this_one" field loaded with a */
+/*                 a pointer to a bigchunk of memory.                       */
+/*    NOTES:                                                                */
+/*       The idea is to use bigchunks (the size of a bigchunk is defined    */
+/*       by ILL_BIGCHUNK in util.h) to supply local routines with memory    */
+/*       for ptrs, so the memory can be shared with other                   */
+/*       local routines.                                                    */
+/*                                                                          */
+/*  ILLutil_bigchunkfree (ILLbigchunkptr *bp)                               */
+/*    ACTION: Frees a ILLbigchunkptr.                                       */
+/*                                                                          */
+/*  void ILLptrworld_init (ILLptrworld *world)                              */
+/*     initialize a ILLptrworld with 1 reference                            */
+/*                                                                          */
+/*  void ILLptrworld_add (ILLptrworld *world)                               */
+/*     add a reference to a ILLptrworld                                     */
+/*                                                                          */
+/*  void ILLptrworld_delete (ILLptrworld *world)                            */
+/*     delete a reference to a ptrworld, and free if no more references     */
+/*                                                                          */
+/****************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "logging-private.h"
+
+#include "except.h"
+#include "util.h"
+
+int ILLTRACE_MALLOC = 0;
+
+typedef struct ILLbigchunk
+{
+	char space[ILL_BIGCHUNK];
+	ILLbigchunkptr ptr;
+}
+ILLbigchunk;
+
+void *ILLutil_allocrus (
+	size_t size)
+{
+	void *mem = (void *) NULL;
+
+	if (size == 0)
+	{
+		//QSlog("Warning: 0 bytes allocated");
+	}
+
+	mem = (void *) malloc (size);
+	if (mem == (void *) NULL)
+	{
+		QSlog("Out of memory. Asked for %d bytes", (int) size);
+	}
+	return mem;
+}
+
+void ILLutil_freerus (
+	void *p)
+{
+	if (!p)
+	{
+		//QSlog("Warning: null pointer freed");
+		return;
+	}
+
+	free (p);
+}
+
+void *ILLutil_reallocrus (
+	void *ptr,
+	size_t size)
+{
+	void *newptr;
+
+	if (!ptr)
+	{
+		return ILLutil_allocrus (size);
+	}
+	else
+	{
+		newptr = (void *) realloc (ptr, size);
+		if (!newptr)
+		{
+			QSlog("Out of memory.  Tried to grow to %d bytes", (int) size);
+		}
+		return newptr;
+	}
+}
+
+int ILLutil_reallocrus_scale (
+	void **pptr,
+	int *pnnum,
+	int count,
+	double scale,
+	size_t size)
+{
+	int rval = 0;
+	int newsize = (int) (((double) *pnnum) * scale);
+	void *p;
+
+	if (newsize < *pnnum + 1000)
+		newsize = *pnnum + 1000;
+	if (newsize < count)
+		newsize = count;
+	p = ILLutil_reallocrus (*pptr, newsize * size);
+	if (!p)
+	{
+		rval = ILL_GENERAL_ERROR;
+		ILL_REPRT ("ILLutil_reallocrus_scale failed\n");
+		ILL_CLEANUP;
+	}
+	else
+	{
+		*pptr = p;
+		*pnnum = newsize;
+	}
+CLEANUP:
+	return rval;
+}
+
+int ILLutil_reallocrus_count (
+	void **pptr,
+	int count,
+	size_t size)
+{
+	int rval = 0;
+	void *p = ILLutil_reallocrus (*pptr, count * size);
+
+	if (!p)
+	{
+		rval = ILL_GENERAL_ERROR;
+		ILL_REPRT ("ILLutil_reallocrus_count failed\n");
+		ILL_CLEANUP;
+	}
+	else
+	{
+		*pptr = p;
+	}
+CLEANUP:
+	return rval;
+}
+
+
+ILLbigchunkptr *ILLutil_bigchunkalloc (
+	void)
+{
+	ILLbigchunk *p;
+
+	ILL_NEW_no_rval (p, ILLbigchunk);
+
+	p->ptr.this_chunk = p;
+	p->ptr.this_one = (void *) p->space;
+CLEANUP:
+	if (p == (ILLbigchunk *) NULL)
+	{
+		return (ILLbigchunkptr *) NULL;
+	}
+	return &(p->ptr);
+}
+
+void ILLutil_bigchunkfree (
+	ILLbigchunkptr * bp)
+{
+	/* This copy is necessary since ILL_FREE zeros its first argument */
+	ILLbigchunk *p = bp->this_chunk;
+
+	ILL_IFFREE (p, ILLbigchunk);
+}
+
+void ILLptrworld_init (
+	ILLptrworld * world)
+{
+	world->refcount = 1;
+	world->freelist = (void *) NULL;
+	world->chunklist = (ILLbigchunkptr *) NULL;
+}
+
+void ILLptrworld_add (
+	ILLptrworld * world)
+{
+	world->refcount++;
+}
+
+void ILLptrworld_delete (
+	ILLptrworld * world)
+{
+	world->refcount--;
+	if (world->refcount <= 0)
+	{
+		ILLbigchunkptr *bp, *bpnext;
+
+		for (bp = world->chunklist; bp; bp = bpnext)
+		{
+			bpnext = bp->next;
+			ILLutil_bigchunkfree (bp);
+		}
+		world->chunklist = (ILLbigchunkptr *) NULL;
+		world->freelist = (void *) NULL;
+		world->refcount = 0;
+	}
+}
diff --git a/qsopt_ex/allocrus.h b/qsopt_ex/allocrus.h
new file mode 100644
index 0000000..dbe3e07
--- /dev/null
+++ b/qsopt_ex/allocrus.h
@@ -0,0 +1,241 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+#ifndef __ALLOCRUS_H__
+#define __ALLOCRUS_H__
+/****************************************************************************/
+/*                                                                          */
+/*                             allocrus.c                                   */
+/*                                                                          */
+/****************************************************************************/
+
+/****************************************************************************/
+/*                                                                          */
+/*                   MEMORY ALLOCATION MACROS                               */
+/*                                                                          */
+/*                           TSP CODE                                       */
+/*                                                                          */
+/*                                                                          */
+/*  Written by:  Applegate, Bixby, Chvatal, and Cook                        */
+/*  Date: February 24, 1995 (cofeb24)                                       */
+/*  see allocrus.c                                                          */
+/*                                                                          */
+/****************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "logging-private.h"
+
+extern int ILLTRACE_MALLOC;
+
+#define ILL_UTIL_SAFE_MALLOC(nnum,type,varname)                             \
+    (((ILLTRACE_MALLOC) ? QSlog("%s.%d: %s: ILL_UTIL_SAFE_MALLOC: %s = %d * %s\n", __FILE__, __LINE__, __DEV_FUNCTION__, #varname, nnum, #type) : 0), \
+     (type *) ILLutil_allocrus (((size_t) (nnum)) * sizeof (type)))
+
+#define ILL_IFFREE(object,type) {                                           \
+    if ((object)) {                                                        \
+       ILLutil_freerus ((void *) (object));                                 \
+       object = (type *) NULL;                                             \
+    }}
+
+#define ILL_PTRWORLD_ALLOC_ROUTINE(type, ptr_alloc_r, ptr_bulkalloc_r)        \
+                                                                             \
+static int ptr_bulkalloc_r (ILLptrworld *world, int nalloc)                   \
+{                                                                            \
+    ILLbigchunkptr *bp;                                                       \
+    int i;                                                                   \
+    int count = ILL_BIGCHUNK / sizeof ( type );                               \
+    type *p;                                                                 \
+                                                                             \
+    while (nalloc > 0) {                                                     \
+        bp = ILLutil_bigchunkalloc ();                                        \
+        if (bp == (ILLbigchunkptr *) NULL) {                                  \
+            QSlog("ptr alloc failed\n");                          \
+            return 1;                                                        \
+        }                                                                    \
+        bp->next = world->chunklist ;                                        \
+        world->chunklist = bp;                                               \
+                                                                             \
+        p = ( type * ) bp->this_one;                                         \
+        for (i=count-2; i>=0; i--) {                                         \
+            p[i].next = &p[i+1];                                             \
+        }                                                                    \
+        p[count - 1].next = (type *) world->freelist;                        \
+        world->freelist = (void *) p;                                        \
+        nalloc -= count;                                                     \
+    }                                                                        \
+    return 0;                                                                \
+}                                                                            \
+                                                                             \
+static type *ptr_alloc_r (ILLptrworld *world)                                 \
+{                                                                            \
+    type *p;                                                                 \
+                                                                             \
+    if (world->freelist == (void *) NULL) {                                  \
+        if (ptr_bulkalloc_r (world, 1)) {                                    \
+            QSlog("ptr alloc failed\n");                          \
+            return ( type * ) NULL;                                          \
+        }                                                                    \
+    }                                                                        \
+    p = (type *) world->freelist ;                                           \
+    world->freelist = (void *) p->next;                                      \
+                                                                             \
+    return p;                                                                \
+}
+
+#define ILL_PTRWORLD_FREE_ROUTINE(type, ptr_free_r)                           \
+                                                                             \
+static void ptr_free_r (ILLptrworld *world, type *p)                          \
+{                                                                            \
+    p->next = (type *) world->freelist ;                                     \
+    world->freelist = (void *) p;                                            \
+}
+
+#define ILL_PTRWORLD_LISTADD_ROUTINE(type, entrytype, ptr_listadd_r, ptr_alloc_r) \
+                                                                             \
+static int ptr_listadd_r (type **list, entrytype x, ILLptrworld *world)       \
+{                                                                            \
+    if (list != (type **) NULL) {                                            \
+        type *p = ptr_alloc_r (world);                                       \
+                                                                             \
+        if (p == (type *) NULL) {                                            \
+            QSlog("ptr list add failed\n");                       \
+            return 1;                                                        \
+        }                                                                    \
+        p->this = x;                                                         \
+        p->next = *list;                                                     \
+        *list = p;                                                           \
+    }                                                                        \
+    return 0;                                                                \
+}
+
+#define ILL_PTRWORLD_LISTFREE_ROUTINE(type, ptr_listfree_r, ptr_free_r)       \
+                                                                             \
+static void ptr_listfree_r (ILLptrworld *world, type *p)                      \
+{                                                                            \
+    type *next;                                                              \
+                                                                             \
+    while (p != (type *) NULL) {                                             \
+        next = p->next;                                                      \
+        ptr_free_r (world, p);                                               \
+        p = next;                                                            \
+    }                                                                        \
+}
+
+#define ILL_PTRWORLD_LEAKS_ROUTINE(type, ptr_leaks_r, field, fieldtype)       \
+                                                                             \
+static int ptr_leaks_r (ILLptrworld *world, int *total, int *onlist)          \
+{                                                                            \
+    int count = ILL_BIGCHUNK / sizeof ( type );                               \
+    int duplicates = 0;                                                      \
+    type * p;                                                                \
+    ILLbigchunkptr *bp;                                                       \
+                                                                             \
+    *total = 0;                                                              \
+    *onlist = 0;                                                             \
+                                                                             \
+    for (bp = world->chunklist ; bp; bp = bp->next)                          \
+        (*total) += count;                                                   \
+                                                                             \
+    for (p = (type *) world->freelist ; p; p = p->next) {                    \
+        (*onlist)++;                                                         \
+        p-> field = ( fieldtype ) 0;                                         \
+    }                                                                        \
+    for (p = (type *) world->freelist ; p; p = p->next) {                    \
+        if ((unsigned long) p-> field == (unsigned long) (size_t) 1)                           \
+            duplicates++;                                                    \
+        else                                                                 \
+            p-> field = ( fieldtype ) (size_t) 1;                            \
+    }                                                                        \
+    if (duplicates) {                                                        \
+        QSlog("WARNING: %d duplicates on ptr free list \n",       \
+							duplicates);																							\
+    }                                                                        \
+    return *total - *onlist;                                                 \
+}
+
+#define ILL_PTRWORLD_ROUTINES(type, ptr_alloc_r, ptr_bulkalloc_r, ptr_free_r) \
+ILL_PTRWORLD_ALLOC_ROUTINE (type, ptr_alloc_r, ptr_bulkalloc_r)               \
+ILL_PTRWORLD_FREE_ROUTINE (type, ptr_free_r)
+
+#define ILL_PTRWORLD_LIST_ROUTINES(type, entrytype, ptr_alloc_r, ptr_bulkalloc_r, ptr_free_r, ptr_listadd_r, ptr_listfree_r) \
+ILL_PTRWORLD_ROUTINES (type, ptr_alloc_r, ptr_bulkalloc_r, ptr_free_r)        \
+ILL_PTRWORLD_LISTADD_ROUTINE (type, entrytype, ptr_listadd_r, ptr_alloc_r)    \
+ILL_PTRWORLD_LISTFREE_ROUTINE (type, ptr_listfree_r, ptr_free_r)
+
+#define ILL_BIGCHUNK ((int) ((1<<16) - sizeof (ILLbigchunkptr) - 16))
+
+struct ILLbigchunk;
+
+typedef struct ILLbigchunkptr
+{
+	void *this_one;
+	struct ILLbigchunk *this_chunk;
+	struct ILLbigchunkptr *next;
+}
+ILLbigchunkptr;
+
+
+typedef struct ILLptrworld
+{
+	int refcount;
+	void *freelist;
+	ILLbigchunkptr *chunklist;
+}
+ILLptrworld;
+
+
+
+void *ILLutil_allocrus (
+	size_t size),
+ *ILLutil_reallocrus (
+	void *ptr,
+	size_t size),
+  ILLutil_freerus (
+	void *p),
+  ILLutil_bigchunkfree (
+	ILLbigchunkptr * bp),
+  ILLptrworld_init (
+	ILLptrworld * world),
+  ILLptrworld_add (
+	ILLptrworld * world),
+  ILLptrworld_delete (
+	ILLptrworld * world);
+
+int ILLutil_reallocrus_scale (
+	void **pptr,
+	int *pnnum,
+	int count,
+	double scale,
+	size_t size),
+  ILLutil_reallocrus_count (
+	void **pptr,
+	int count,
+	size_t size);
+
+ILLbigchunkptr *ILLutil_bigchunkalloc (
+	void);
+
+
+
+#endif
diff --git a/qsopt_ex/basicdefs.h b/qsopt_ex/basicdefs.h
new file mode 100644
index 0000000..1b8c01f
--- /dev/null
+++ b/qsopt_ex/basicdefs.h
@@ -0,0 +1,386 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+#ifndef __BASICDEFS__
+#define __BASICDEFS__
+
+/* storage type */
+#define DENSE          0
+#define SPARSE         1
+
+/* type of vector */
+#define ROW_SOLVE      1
+#define COLUMN_SOLVE   2
+
+/* direction of change in non-basic var */
+#define VINCREASE      1
+#define VDECREASE      2
+
+/* status of variables */
+#define STAT_BASIC     1
+#define STAT_UPPER     2
+#define STAT_LOWER     3
+#define STAT_ZERO      4
+
+#define BOUND_LOWER    1
+#define BOUND_UPPER    2
+
+/* type of variables */
+#define VARTIFICIAL    1
+#define VFIXED         2
+#define VFREE          4
+#define VUPPER         8
+#define VLOWER         16
+#define VBOUNDED       32
+
+/* class of variables */
+#define CLASS_STRUCT   0
+#define CLASS_LOGICAL  1
+
+/* algo */
+#define PRIMAL_SIMPLEX 1
+#define DUAL_SIMPLEX   2
+#define PRIMAL_OR_DUAL 3
+
+/* phase */
+#define PRIMAL_PHASEI  1
+#define PRIMAL_PHASEII 2
+#define DUAL_PHASEI    3
+#define DUAL_PHASEII   4
+
+/* number of phases */
+#define PHASEI         1
+#define PHASEII        2
+
+/* type of pricing (all vars or some) */
+#define COMPLETE_PRICING   1
+#define PARTIAL_PRICING    2
+#define MULTI_PART_PRICING 3
+
+/* default pricing */
+
+#define QS_DEFAULT_PRICE_PI  QS_PRICE_PSTEEP
+#define QS_DEFAULT_PRICE_PII QS_PRICE_PSTEEP
+#define QS_DEFAULT_PRICE_DI  QS_PRICE_DSTEEP
+#define QS_DEFAULT_PRICE_DII QS_PRICE_DSTEEP
+
+/* lp sol status */
+#define ILL_LP_SOLVED            1
+#define ILL_LP_UNSOLVED          2
+#define ILL_MAX_ITER             3
+#define ILL_MAX_TIME             4
+#define ILL_BND_REACHED          5
+#define ILL_PPHASEI_ERROR        6
+#define ILL_PPHASEII_ERROR       7
+#define ILL_DPHASEI_ERROR        8
+#define ILL_DPHASEII_ERROR       9
+#define ILL_LP_ABORTED          10
+
+/* basis status */
+#define OPTIMAL                  1
+#define NONOPTIMAL               2
+#define PRIMAL_FEASIBLE          3
+#define PRIMAL_INFEASIBLE        4
+#define PRIMAL_UNBOUNDED         5
+#define DUAL_FEASIBLE            7
+#define DUAL_INFEASIBLE          8
+#define DUAL_UNBOUNDED           9
+
+/* type of ratio test */
+#define RATIOTEST_NORMAL 1
+#define RATIOTEST_HARRIS 2
+
+/* control parameters */
+#define PARAM_PRATIOTESTS        10
+#define PARAM_DRATIOTESTS        20
+#define PARAM_PRIMAL_REFACTORGAP 50
+#define PARAM_PRIMAL_RESOLVEGAP  25
+#define PARAM_DUAL_REFACTORGAP   100
+#define PARAM_DUAL_RESOLVEGAP    25
+#define PARAM_MAX_NOSOLVE        500
+#define PARAM_MAX_NOPROG         300
+#define PARAM_NOPROG_FACTOR      15
+
+/* numerical parameters */
+#define PARAM_BSHIFT             10
+#define PARAM_CSHIFT             10
+
+/* general constants */
+#define PARAM_HEAP_UTRIGGER      10
+#define PARAM_HEAP_RATIO         4.0
+
+/* errors */
+#define E_GENERAL_ERROR          1
+#define E_INV_LINSOLVE_OPTION    2
+#define E_NO_MEMORY              3
+#define E_INVALID_OPTION         4
+#define E_NULL_ARGUMENT          5
+#define E_SIMPLEX_ERROR          6
+#define E_BASIS_SINGULAR         7
+
+#ifndef __QS_BASIS__
+#define __QS_BASIS__
+typedef struct qsbasis
+{
+	int nstruct;
+	int nrows;
+	char *cstat;
+	char *rstat;
+}
+QSbasis;
+#endif
+
+typedef struct itcnt_t
+{
+	int pI_iter;
+	int pII_iter;
+	int dI_iter;
+	int dII_iter;
+	int tot_iter;
+} itcnt_t;
+
+#ifndef QS_DEFINITIONS
+#define QS_DEFINITIONS
+#define QS_MIN       (1)
+#define QS_MAX       (-1)
+
+/****************************************************************************/
+/*                                                                          */
+/*                 PARAMETERS THAT CAN BE SET BY setparam                   */
+/*                                                                          */
+/****************************************************************************/
+
+
+#define QS_PARAM_PRIMAL_PRICING    0
+#define QS_PARAM_DUAL_PRICING      2
+#define QS_PARAM_SIMPLEX_DISPLAY   4
+#define QS_PARAM_SIMPLEX_MAX_ITERATIONS 5
+#define QS_PARAM_SIMPLEX_MAX_TIME  6
+#define QS_PARAM_SIMPLEX_SCALING   7
+#define QS_PARAM_OBJULIM           8
+#define QS_PARAM_OBJLLIM           9
+
+
+/****************************************************************************/
+/*                                                                          */
+/*                     VALUES FOR PRICING PARAMETERS                        */
+/*                                                                          */
+/****************************************************************************/
+
+#define QS_PRICE_PDANTZIG 1
+#define QS_PRICE_PDEVEX 2
+#define QS_PRICE_PSTEEP 3
+#define QS_PRICE_PMULTPARTIAL 4
+
+#define QS_PRICE_DDANTZIG 6
+#define QS_PRICE_DSTEEP 7
+#define QS_PRICE_DMULTPARTIAL 8
+#define QS_PRICE_DDEVEX 9
+
+
+/****************************************************************************/
+/*                                                                          */
+/*                         VALUES FOR BASIS STATUS                          */
+/*                                                                          */
+/****************************************************************************/
+
+
+#define QS_COL_BSTAT_LOWER     '0'
+#define QS_COL_BSTAT_BASIC     '1'
+#define QS_COL_BSTAT_UPPER     '2'
+#define QS_COL_BSTAT_FREE      '3'
+
+#define QS_ROW_BSTAT_LOWER     '0'
+#define QS_ROW_BSTAT_BASIC     '1'
+#define QS_ROW_BSTAT_UPPER     '2'
+
+
+/****************************************************************************/
+/*                                                                          */
+/*         Return Status for dbl_QSopt_primal, dbl_QSopt_dual, dbl_QSget_status         */
+/*                                                                          */
+/****************************************************************************/
+
+#define QS_LP_OPTIMAL           1
+#define QS_LP_INFEASIBLE        2
+#define QS_LP_UNBOUNDED         3
+#define QS_LP_ITER_LIMIT        4
+#define QS_LP_TIME_LIMIT        5
+#define QS_LP_UNSOLVED          6
+#define QS_LP_ABORTED		7
+#define QS_LP_NUMERR            8
+#define QS_LP_OBJ_LIMIT         9
+#define QS_LP_MODIFIED        100
+#define QS_LP_CHANGE_PREC			1024
+#endif
+
+
+
+/** @brief If set to one, them we allow to re-start the simplex algorithm due to
+ * numerical issues */
+#define DO_NUMER 0
+/** @brief If set to one, then we allow to re-start simplex due to singular
+ * basis */
+#define DO_SINGULAR 0
+
+/** @brief Factor for wich we change tolerances each time we have to resume
+ * simplex */
+#define SIMPLEX_FACTOR 5U
+#define DENSE_PI 0
+#define DENSE_PIIPI 0
+#define DENSE_NORM 0
+#define SIMPLEX_DEBUG 0
+
+
+/* possible values of nextstep */
+#define SIMPLEX_CONTINUE   1
+#define SIMPLEX_TERMINATE  2
+#define SIMPLEX_RESUME     3
+
+/* reason for resuming simplex */
+#define SIMPLEX_RESUME_SING     1
+#define SIMPLEX_RESUME_UNSHIFT  2
+#define SIMPLEX_RESUME_NUMER    3
+
+/* values for newphase */
+#define SIMPLEX_PHASE_RECOMP  1
+#define SIMPLEX_PHASE_NEW     2
+
+#define SIMPLEX_PIVOTINROW 1
+#define SIMPLEX_PIVOTINCOL 2
+#define SIMPLEX_MAX_RESTART 4
+#define SIMPLEX_MAX_PIVOT_FAIL 300
+
+
+#define FALSE 0
+#define TRUE  1
+#define QS_FACTOR_MAX_K        1
+#define QS_FACTOR_P            2
+#define QS_FACTOR_ETAMAX       3
+#define QS_FACTOR_FZERO_TOL    4
+#define QS_FACTOR_SZERO_TOL    5
+#define QS_FACTOR_PARTIAL_TOL  6
+#define QS_FACTOR_UR_SPACE_MUL 7
+#define QS_FACTOR_UC_SPACE_MUL 8
+#define QS_FACTOR_LC_SPACE_MUL 9
+#define QS_FACTOR_LR_SPACE_MUL 10
+#define QS_FACTOR_ER_SPACE_MUL 11
+#define QS_FACTOR_GROW_MUL     12
+#define QS_FACTOR_MAXMULT      13
+#define QS_FACTOR_MINMULT      14
+#define QS_FACTOR_UPDMAXMULT   15
+#define QS_FACTOR_DENSE_FRACT  16
+#define QS_FACTOR_DENSE_MIN    17
+#define E_CHECK_FAILED 6
+#define E_NO_PIVOT 7
+#define E_FACTOR_BLOWUP 8
+#define E_UPDATE_NOSPACE 9
+#define E_UPDATE_SINGULAR_ROW 10
+#define E_UPDATE_SINGULAR_COL 11
+#define E_SING_NO_DATA 12
+#define E_SINGULAR_INTERNAL 13
+#define SPARSE_FACTOR 0.05
+#define CNT_YNZ           1			/* nz in entering columns */
+#define CNT_ZNZ           2			/* nz in ith row of B^{-1}, ie z_i */
+#define CNT_ZANZ          3			/* nz in ith row of B^{-1}, ie z_i */
+#define CNT_PINZ          4			/* nz in phase II pi (solve) */
+#define CNT_P1PINZ        5			/* nz in phase I pi (solve) */
+#define CNT_UPNZ          6			/* nz in ftran_updates */
+#define CNT_PPHASE1ITER   7			/* primal phase I iterations */
+#define CNT_PPHASE2ITER   8
+#define CNT_DPHASE1ITER   9			/* dual phase I iterations */
+#define CNT_DPHASE2ITER   10
+#define CNT_PIPIV         11
+#define CNT_PIIPIV        12
+#define CNT_DIPIV         13
+#define CNT_DIIPIV        14
+#define CNT_YRAVG         15
+#define CNT_ZARAVG        16
+
+#define ROW_PIVOT         0
+#define COL_PIVOT         1
+
+#define ILL_LP_OPTIMAL           1
+#define ILL_LP_NONOPTIMAL        2
+#define ILL_LP_PRIMAL_FEASIBLE   3
+#define ILL_LP_PRIMAL_INFEASIBLE 4
+#define ILL_LP_PRIMAL_UNBOUNDED  5
+#define ILL_LP_DUAL_FEASIBLE     6
+#define ILL_LP_DUAL_INFEASIBLE   7
+#define ILL_LP_DUAL_UNBOUNDED    8
+
+typedef enum
+{ ILL_MPS_NAME, ILL_MPS_OBJSENSE, ILL_MPS_OBJNAME,
+	ILL_MPS_ROWS, ILL_MPS_COLS, ILL_MPS_RHS, ILL_MPS_RANGES,
+	ILL_MPS_BOUNDS, ILL_MPS_REFROW, ILL_MPS_ENDATA,
+	ILL_MPS_NONE
+}
+ILLmps_section;
+
+#define ILL_MPS_N_SECTIONS ILL_MPS_NONE
+
+/*define as > 0 if heap is to be used */
+#define USEHEAP 1
+
+/*result of pricing */
+#define PRICE_OPTIMAL 1
+#define PRICE_NONOPTIMAL  2
+
+/*type of pricing */
+#define ROW_PRICING 1
+#define COL_PRICING 2
+
+
+/****************************************************************************
+ * error collection
+ */
+#define QS_DATA_ERROR			0
+#define QS_DATA_WARN			1
+#define QS_MPS_FORMAT_ERROR		2
+#define QS_MPS_FORMAT_WARN		3
+#define QS_LP_FORMAT_ERROR		4
+#define QS_LP_FORMAT_WARN		5
+#define QS_INPUT_NERROR        8
+
+/* defs for phase I ratio test */
+#define BBOUND    1
+#define BATOLOWER 2
+#define BATOUPPER 3
+#define BBTOLOWER 4
+#define BBTOUPPER 5
+#define BSKIP     6
+
+/* result of ratio test */
+#define RATIO_UNBOUNDED 1
+#define RATIO_NOBCHANGE 2
+#define RATIO_BCHANGE   3
+#define RATIO_FAILED    4
+#define RATIO_NEGATIVE  5
+
+/* warning level */
+#define QSE_WLVL 10000
+
+
+
+
+
+
+#endif
diff --git a/qsopt_ex/basis.c b/qsopt_ex/basis.c
new file mode 100644
index 0000000..576c920
--- /dev/null
+++ b/qsopt_ex/basis.c
@@ -0,0 +1,1554 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: basis.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+static int TRACE = 0;
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "eg_lpnum.h"
+#include "eg_io.h"
+#include "except.h"
+#include "util.h"
+
+#include "sortrus_EGLPNUM_TYPENAME.h"
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+#include "qstruct_EGLPNUM_TYPENAME.h"
+#include "qsopt_EGLPNUM_TYPENAME.h"
+#include "basis_EGLPNUM_TYPENAME.h"
+#include "fct_EGLPNUM_TYPENAME.h"
+#include "lp_EGLPNUM_TYPENAME.h"
+#include "lib_EGLPNUM_TYPENAME.h"
+
+//#define DJZERO_TOLER EGLPNUM_TYPENAME_PFEAS_TOLER
+#define BASIS_STATS 0
+//#define BASIS_DEBUG 10
+#define BASIS_DEBUG 0
+
+void EGLPNUM_TYPENAME_ILLbasis_init_vardata (
+	EGLPNUM_TYPENAME_var_data * vd)
+{
+	memset (vd, 0, sizeof (EGLPNUM_TYPENAME_var_data));
+	EGLPNUM_TYPENAME_EGlpNumInitVar (vd->cmax);
+}
+
+void EGLPNUM_TYPENAME_ILLbasis_clear_vardata (
+	EGLPNUM_TYPENAME_var_data * vd)
+{
+	EGLPNUM_TYPENAME_EGlpNumClearVar (vd->cmax);
+	memset (vd, 0, sizeof (EGLPNUM_TYPENAME_var_data));
+}
+
+static void get_var_info (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_var_data * v);
+
+static int init_slack_basis (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int *vstat,
+	int *irow,
+	int *rrow,
+	int *unitcol,
+	int *icol,
+	int *rcol),
+  get_initial_basis1 (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int *vstat),
+  get_initial_basis2 (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int *vstat),
+  set_basis_indices (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int *vstat),
+  choose_basis (
+	int algorithm,
+	EGLPNUM_TYPE pinf1,
+	EGLPNUM_TYPE dinf1,
+	EGLPNUM_TYPE pinf2,
+	EGLPNUM_TYPE dinf2);
+
+void EGLPNUM_TYPENAME_ILLbasis_init_basisinfo (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	lp->baz = 0;
+	lp->nbaz = 0;
+	lp->vstat = 0;
+	lp->vindex = 0;
+	lp->f = 0;
+}
+
+void EGLPNUM_TYPENAME_ILLbasis_free_basisinfo (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	ILL_IFFREE (lp->baz, int);
+	ILL_IFFREE (lp->nbaz, int);
+	ILL_IFFREE (lp->vstat, int);
+	ILL_IFFREE (lp->vindex, int);
+
+	if (lp->f)
+	{
+		EGLPNUM_TYPENAME_ILLfactor_free_factor_work (lp->f);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (lp->f->fzero_tol);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (lp->f->szero_tol);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (lp->f->partial_tol);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (lp->f->maxelem_orig);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (lp->f->maxelem_factor);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (lp->f->maxelem_cur);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (lp->f->partial_cur);
+		ILL_IFFREE (lp->f, EGLPNUM_TYPENAME_factor_work);
+	}
+}
+
+int EGLPNUM_TYPENAME_ILLbasis_build_basisinfo (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	int rval = 0;
+
+	ILL_SAFE_MALLOC (lp->baz, lp->O->nrows, int);
+	ILL_SAFE_MALLOC (lp->nbaz, lp->O->ncols, int);
+	ILL_SAFE_MALLOC (lp->vstat, lp->O->ncols, int);
+	ILL_SAFE_MALLOC (lp->vindex, lp->O->ncols, int);
+
+	lp->fbasisid = -1;
+
+CLEANUP:
+	if (rval)
+		EGLPNUM_TYPENAME_ILLbasis_free_basisinfo (lp);
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLbasis_load (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_ILLlp_basis * B)
+{
+	int rval = 0;
+	char *cstat = B->cstat;
+	char *rstat = B->rstat;
+	int *structmap = lp->O->structmap;
+	int *rowmap = lp->O->rowmap;
+	char *sense = lp->O->sense;
+	int i, j, ncols = lp->O->ncols, nrows = lp->O->nrows, nstruct = lp->O->nstruct;
+	int basic = 0, nonbasic = 0;
+
+	EGLPNUM_TYPENAME_ILLbasis_free_basisinfo (lp);
+	EGLPNUM_TYPENAME_ILLbasis_init_basisinfo (lp);
+	rval = EGLPNUM_TYPENAME_ILLbasis_build_basisinfo (lp);
+	CHECKRVALG (rval, CLEANUP);
+
+	for (i = 0; i < nstruct; i++)
+	{
+		j = structmap[i];
+		if (cstat[i] == QS_COL_BSTAT_BASIC)
+		{
+			lp->vstat[j] = STAT_BASIC;
+			lp->baz[basic] = j;
+			lp->vindex[j] = basic;
+			basic++;
+		}
+		else
+		{
+			lp->nbaz[nonbasic] = j;
+			lp->vindex[j] = nonbasic;
+			nonbasic++;
+			switch (cstat[i])
+			{
+			case QS_COL_BSTAT_LOWER:
+				lp->vstat[j] = STAT_LOWER;
+				break;
+			case QS_COL_BSTAT_UPPER:
+				lp->vstat[j] = STAT_UPPER;
+				break;
+			case QS_COL_BSTAT_FREE:
+				lp->vstat[j] = STAT_ZERO;
+				break;
+			default:
+				QSlog("unknown col basis stat 1: %c", cstat[i]);
+				rval = 1;
+				goto CLEANUP;
+			}
+		}
+	}
+
+	for (i = 0; i < nrows; i++)
+	{
+		j = rowmap[i];
+		if (sense[i] == 'R')
+		{
+			if (rstat[i] == QS_ROW_BSTAT_BASIC)
+			{
+				lp->vstat[j] = STAT_BASIC;
+				lp->baz[basic] = j;
+				lp->vindex[j] = basic;
+				basic++;
+			}
+			else
+			{
+				lp->nbaz[nonbasic] = j;
+				lp->vindex[j] = nonbasic;
+				nonbasic++;
+				switch (rstat[i])
+				{
+				case QS_ROW_BSTAT_LOWER:
+					lp->vstat[j] = STAT_LOWER;
+					break;
+				case QS_ROW_BSTAT_UPPER:
+					lp->vstat[j] = STAT_UPPER;
+					break;
+				default:
+					QSlog("unknown range basis stat 2");
+					rval = 1;
+					goto CLEANUP;
+				}
+			}
+		}
+		else
+		{
+			switch (rstat[i])
+			{
+			case QS_ROW_BSTAT_BASIC:
+				lp->vstat[j] = STAT_BASIC;
+				lp->baz[basic] = j;
+				lp->vindex[j] = basic;
+				basic++;
+				break;
+			case QS_ROW_BSTAT_LOWER:
+				lp->vstat[j] = STAT_LOWER;
+				lp->nbaz[nonbasic] = j;
+				lp->vindex[j] = nonbasic;
+				nonbasic++;
+				break;
+			default:
+				QSlog("unknown row basis stat 3");
+				rval = 1;
+				goto CLEANUP;
+			}
+		}
+	}
+
+	if (basic + nonbasic != ncols)
+	{
+		QSlog("error in counts in ILLopt_load_basis");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	if (lp->fbasisid != 0)
+		lp->basisid = 0;
+	else
+		lp->basisid = 1;
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLbasis_tableau_row (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int row,
+	EGLPNUM_TYPE * brow,
+	EGLPNUM_TYPE * trow,
+	EGLPNUM_TYPE * rhs,
+	int strict)
+{
+	int rval = 0;
+	int i;
+	int singular = 0;
+	int indx;
+	EGLPNUM_TYPE coef;
+	EGLPNUM_TYPE sum;
+	EGLPNUM_TYPENAME_svector z, zA;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (coef);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (sum);
+	EGLPNUM_TYPENAME_EGlpNumZero (sum);
+
+	EGLPNUM_TYPENAME_ILLsvector_init (&z);
+	EGLPNUM_TYPENAME_ILLsvector_init (&zA);
+
+	if (lp->basisid == -1)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLbasis_tableau_row: no basis");
+		rval = E_GENERAL_ERROR;
+		ILL_CLEANUP;
+	}
+	if (lp->fbasisid != lp->basisid)
+	{															/* Needs to be changed */
+		rval = EGLPNUM_TYPENAME_ILLbasis_factor (lp, &singular);
+		CHECKRVALG (rval, CLEANUP);
+		if (singular)
+		{
+			MESSAGE (__QS_SB_VERB, "Singular Basis found!");
+			rval = E_BASIS_SINGULAR;
+			ILL_CLEANUP;
+		}
+	}
+	if (brow == NULL)
+	{
+		QSlog("No array for basis inverse row");
+		rval = E_GENERAL_ERROR;
+		ILL_CLEANUP;
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&z, lp->nrows);
+	CHECKRVALG (rval, CLEANUP);
+	EGLPNUM_TYPENAME_ILLfct_compute_zz (lp, &z, row);
+
+	for (i = 0; i < lp->O->nrows; i++)
+		EGLPNUM_TYPENAME_EGlpNumZero (brow[i]);
+	for (i = 0; i < z.nzcnt; i++)
+	{
+		indx = z.indx[i];
+		EGLPNUM_TYPENAME_EGlpNumCopy (coef, z.coef[i]);
+		EGLPNUM_TYPENAME_EGlpNumCopy (brow[indx], coef);
+		EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, coef, lp->bz[indx]);
+	}
+
+	if (rhs != NULL)
+		EGLPNUM_TYPENAME_EGlpNumCopy (*rhs, sum);
+	if (trow != NULL)
+	{
+		if (!strict)
+		{
+			rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&zA, lp->ncols);
+			if (rval)
+				ILL_CLEANUP;
+			ILL_IFTRACE ("%s:\n", __func__);
+			rval = EGLPNUM_TYPENAME_ILLfct_compute_zA (lp, &z, &zA);
+			CHECKRVALG (rval, CLEANUP);
+
+			for (i = 0; i < lp->ncols; i++)
+				EGLPNUM_TYPENAME_EGlpNumZero (trow[i]);
+			for (i = 0; i < zA.nzcnt; i++)
+				EGLPNUM_TYPENAME_EGlpNumCopy (trow[lp->nbaz[zA.indx[i]]], zA.coef[i]);
+			EGLPNUM_TYPENAME_EGlpNumOne (trow[lp->baz[row]]);
+		}
+		else
+		{
+			EGLPNUM_TYPENAME_ILLfct_compute_vA (lp, &z, trow);
+		}
+	}
+
+#if BASIS_DEBUG > 0
+	if (rhs != NULL && trow != NULL)
+	{
+		EGLPNUM_TYPE *tr = NULL;
+
+		EGLPNUM_TYPENAME_EGlpNumZero (sum);
+		if (strict)
+			tr = trow;
+		else
+		{
+			tr = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->ncols);
+			EGLPNUM_TYPENAME_ILLfct_compute_vA (lp, &z, tr);
+		}
+		for (i = 0; i < lp->nrows; i++)
+			if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (tr[lp->baz[i]]))
+				EGLPNUM_TYPENAME_EGlpNumAddTo (sum, tr[lp->baz[i]]);
+			else
+				EGLPNUM_TYPENAME_EGlpNumSubTo (sum, tr[lp->baz[i]]);
+		EGLPNUM_TYPENAME_EGlpNumCopy (coef, EGLPNUM_TYPENAME_oneLpNum);
+		EGLPNUM_TYPENAME_EGlpNumSubTo (coef, sum);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (coef))
+			EGLPNUM_TYPENAME_EGlpNumSign (coef);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_PIVZ_TOLER, coef))
+			QSlog("tableau: bas computed = %.12f", EGLPNUM_TYPENAME_EGlpNumToLf (sum));
+		if (!strict)
+			EGLPNUM_TYPENAME_EGlpNumFreeArray (tr);
+#if BASIS_DEBUG > 1
+		EGLPNUM_TYPENAME_EGlpNumZero (sum);
+		for (i = 0; i < lp->ncols; i++)
+		{
+			if (lp->vstat[i] == STAT_BASIC)
+				EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, lp->xbz[lp->vindex[i]], trow[i]);
+			else if (lp->vstat[i] == STAT_UPPER)
+				EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, lp->uz[i], trow[i]);
+			else if (lp->vstat[i] == STAT_LOWER)
+				EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, lp->lz[i], trow[i]);
+		}
+		EGLPNUM_TYPENAME_EGlpNumSet (coef, 1e-10);
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeq (sum, *rhs, coef))
+			QSlog("tableau rhs = %.9f, computed = %.9f",
+									EGLPNUM_TYPENAME_EGlpNumToLf (*rhs), EGLPNUM_TYPENAME_EGlpNumToLf (sum));
+#endif
+	}
+#endif
+
+CLEANUP:
+	EGLPNUM_TYPENAME_ILLsvector_free (&z);
+	EGLPNUM_TYPENAME_ILLsvector_free (&zA);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (coef);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (sum);
+	return rval;
+}
+
+static void get_var_info (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_var_data * v)
+{
+	int i = 0;
+
+	v->nartif = 0;
+	v->nslacks = 0;
+	v->nfree = 0;
+	v->nbndone = 0;
+	v->nbounded = 0;
+	v->nfixed = 0;
+	EGLPNUM_TYPENAME_EGlpNumCopy (v->cmax, EGLPNUM_TYPENAME_NINFTY);
+
+	for (i = 0; i < lp->ncols; i++)
+	{
+		switch (lp->vtype[i])
+		{
+		case VARTIFICIAL:
+			v->nartif++;
+			break;
+		case VFREE:
+			v->nfree++;
+			break;
+		case VLOWER:
+		case VUPPER:
+			if (lp->vclass[i] == CLASS_LOGICAL)
+				v->nslacks++;
+			else
+				v->nbndone++;
+			break;
+
+		case VFIXED:
+			v->nfixed++;
+		case VBOUNDED:
+			if (lp->vclass[i] == CLASS_LOGICAL)
+				v->nslacks++;
+			else
+				v->nbounded++;
+			break;
+		}
+		EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (v->cmax, lp->cz[i]);
+	}
+
+#if BASIS_STATS > 0
+	QSlog("cols = %d, acols = %d, total  = %d, nrows = %d, nlog = %d",
+							lp->ncols, lp->ncols - lp->nrows,
+							v->nartif + v->nfree + v->nslacks + v->nbndone + v->nbounded,
+							lp->nrows, v->nartif + v->nslacks);
+#endif
+}
+
+static int init_slack_basis (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int *vstat,
+	int *irow,
+	int *rrow,
+	int *unitcol,
+	int *icol,
+	int *rcol)
+{
+	int j, r, vt;
+	int nslacks = 0;
+
+	for (j = 0; j < lp->ncols; j++)
+	{
+		r = lp->matind[lp->matbeg[j]];
+		vt = lp->vtype[j];
+
+		if ((vt == VUPPER || vt == VLOWER || vt == VBOUNDED || vt == VFIXED) &&
+				lp->vclass[j] == CLASS_LOGICAL)
+		{
+
+			vstat[j] = STAT_BASIC;
+			irow[r] = 1;
+			rrow[r] = 1;
+			unitcol[r] = j;
+			if (icol != NULL)
+			{
+				icol[j] = 1;
+				rcol[j] = 1;
+			}
+			nslacks++;
+		}
+		else if (vt == VARTIFICIAL)
+		{
+			unitcol[r] = j;
+			vstat[j] = STAT_UPPER;
+		}
+		else if (vt == VFREE)
+			vstat[j] = STAT_ZERO;
+		else if (vt == VFIXED || vt == VUPPER)
+			vstat[j] = STAT_UPPER;
+		else if (vt == VLOWER)
+			vstat[j] = STAT_LOWER;
+		else if (vt == VBOUNDED)
+		{
+			if (fabs (EGLPNUM_TYPENAME_EGlpNumToLf (lp->lz[j])) < fabs (EGLPNUM_TYPENAME_EGlpNumToLf (lp->uz[j])))
+				vstat[j] = STAT_LOWER;
+			else
+				vstat[j] = STAT_UPPER;
+		}
+	}
+	return nslacks;
+}
+
+static int primal_col_select (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int *vstat,
+	int *irow,
+	int *rrow,
+	int *unitcol,
+	EGLPNUM_TYPE * v,
+	int *perm,
+	int *porder,
+	int nbelem,
+	int pcols)
+{
+	int i, j, k, tr, r = 0;
+	int mcnt, mbeg;
+	int *matbeg = lp->matbeg;
+	int *matcnt = lp->matcnt;
+	int *matind = lp->matind;
+	EGLPNUM_TYPE *matval = lp->matval;
+	EGLPNUM_TYPE alpha, val, maxelem;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (alpha);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (val);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (maxelem);
+
+	for (k = 0; k < pcols; k++)
+	{
+		j = porder[perm[k]];
+		mcnt = matcnt[j];
+		mbeg = matbeg[j];
+
+		EGLPNUM_TYPENAME_EGlpNumCopy (alpha, EGLPNUM_TYPENAME_NINFTY);
+		EGLPNUM_TYPENAME_EGlpNumCopy (maxelem, EGLPNUM_TYPENAME_NINFTY);
+
+		for (i = 0; i < mcnt; i++)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopyAbs (val, matval[mbeg + i]);
+			if (EGLPNUM_TYPENAME_EGlpNumIsLess (maxelem, val))
+				EGLPNUM_TYPENAME_EGlpNumCopy (maxelem, val);
+			if (rrow[matind[mbeg + i]] == 0 && EGLPNUM_TYPENAME_EGlpNumIsLess (alpha, val))
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (alpha, val);
+				r = matind[mbeg + i];
+			}
+		}
+		EGLPNUM_TYPENAME_EGlpNumCopy (val, maxelem);
+		EGLPNUM_TYPENAME_EGlpNumMultTo (val, EGLPNUM_TYPENAME_PARAM_IBASIS_RPIVOT);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (val, alpha))
+		{
+			vstat[j] = STAT_BASIC;
+			nbelem++;
+			irow[r] = 1;
+			EGLPNUM_TYPENAME_EGlpNumCopy (v[r], alpha);
+			for (i = 0; i < mcnt; i++)
+				if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (matval[mbeg + i]))
+					rrow[matind[mbeg + i]]++;
+		}
+		else
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (alpha, EGLPNUM_TYPENAME_NINFTY);
+			for (i = 0; i < mcnt; i++)
+			{
+				tr = matind[mbeg + i];
+				EGLPNUM_TYPENAME_EGlpNumCopyAbs (val, matval[mbeg + i]);
+				EGLPNUM_TYPENAME_EGlpNumDivTo (val, EGLPNUM_TYPENAME_PARAM_IBASIS_RTRIANG);
+				if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (v[tr], EGLPNUM_TYPENAME_INFTY) && EGLPNUM_TYPENAME_EGlpNumIsLess (v[tr], val))
+				{
+					EGLPNUM_TYPENAME_EGlpNumZero (alpha);
+					break;
+				}
+				EGLPNUM_TYPENAME_EGlpNumCopyAbs (val, matval[mbeg + i]);
+				if (irow[tr] == 0 && EGLPNUM_TYPENAME_EGlpNumIsLess (alpha, val))
+				{
+					EGLPNUM_TYPENAME_EGlpNumCopy (alpha, val);
+					r = tr;
+				}
+			}
+			if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (alpha) && EGLPNUM_TYPENAME_EGlpNumIsNeqq (alpha, EGLPNUM_TYPENAME_NINFTY))
+			{
+				vstat[j] = STAT_BASIC;
+				nbelem++;
+				irow[r] = 1;
+				EGLPNUM_TYPENAME_EGlpNumCopy (v[r], alpha);
+				for (i = 0; i < mcnt; i++)
+					if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (matval[mbeg + i]))
+						rrow[matind[mbeg + i]]++;
+			}
+		}
+	}
+#if BASIS_STATS > 0
+	QSlog("nartifs = %d", lp->nrows - nbelem);
+#endif
+
+	if (nbelem < lp->nrows)
+	{
+		for (i = 0; i < lp->nrows; i++)
+		{
+			if (irow[i] == 0)
+			{
+				if (unitcol[i] != -1)
+				{
+					vstat[unitcol[i]] = STAT_BASIC;
+					nbelem++;
+				}
+				else
+				{
+					QSlog("Error: Not enough artificials");
+					return -1;
+				}
+			}
+		}
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (alpha);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (val);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (maxelem);
+	return nbelem;
+}
+
+/* This is an implementation of the initial basis procedure
+   in: "Implementing the simplex method: the initial basis", by
+   Bob Bixby.
+   Goals: choose initial variables to go into basis which satisfy:
+   1) vars are slacks, 2) vars have freedom to move
+   3) initial submatrix is nonsingular, 4) low objective function
+   contribution.
+*/
+static int get_initial_basis1 (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int *vstat)
+{
+	int rval = 0;
+	int i, j, tot1 = 0, tot2 = 0;
+	int nbelem = 0, nslacks = 0;
+	int tfree = 0, tbndone = 0;
+	int tbounded = 0;
+	int *irow = NULL, *rrow = NULL;
+	int *perm = NULL, *porder = NULL;
+	int *unitcol = NULL;
+	EGLPNUM_TYPE cmax;
+	EGLPNUM_TYPE *v = NULL;
+	EGLPNUM_TYPE *qpenalty = NULL;
+	EGLPNUM_TYPENAME_var_data vd;
+
+	EGLPNUM_TYPENAME_ILLbasis_init_vardata (&vd);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (cmax);
+
+	get_var_info (lp, &vd);
+	if (!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (vd.cmax))
+		EGLPNUM_TYPENAME_EGlpNumOne (cmax);
+	else
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (cmax, vd.cmax);
+		EGLPNUM_TYPENAME_EGlpNumMultUiTo (cmax, 1000);
+	}
+
+	ILL_SAFE_MALLOC (irow, lp->nrows, int);
+	ILL_SAFE_MALLOC (rrow, lp->nrows, int);
+
+	v = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+	ILL_SAFE_MALLOC (unitcol, lp->nrows, int);
+
+	for (i = 0; i < lp->nrows; i++)
+	{
+		unitcol[i] = -1;
+		EGLPNUM_TYPENAME_EGlpNumCopy (v[i], EGLPNUM_TYPENAME_INFTY);
+		irow[i] = 0;
+		rrow[i] = 0;
+	}
+
+	nslacks = init_slack_basis (lp, vstat, irow, rrow, unitcol, NULL, NULL);
+	if (nslacks != vd.nslacks)
+	{
+		QSlog("complain: incorrect basis info(slacks)");
+		rval = E_SIMPLEX_ERROR;
+		ILL_CLEANUP;
+	}
+	if (nslacks == lp->nrows)
+		ILL_CLEANUP;
+	nbelem = nslacks;
+	if (nbelem < lp->nrows)
+	{
+		for (i = 0; i < lp->nrows; i++)
+		{
+			if (irow[i] == 0)
+			{
+				if (unitcol[i] != -1)
+				{
+					vstat[unitcol[i]] = STAT_BASIC;
+					nbelem++;
+				}
+				else
+				{
+					QSlog("Error: Not enough artificials");
+					return -1;
+				}
+			}
+		}
+	}
+	ILL_CLEANUP;
+
+	tot1 = vd.nfree + vd.nbndone;
+	tot2 = vd.nfree + vd.nbndone + vd.nbounded;
+	ILL_SAFE_MALLOC (perm, tot2, int);
+	ILL_SAFE_MALLOC (porder, tot2, int);
+
+	qpenalty = EGLPNUM_TYPENAME_EGlpNumAllocArray (tot2);
+
+	for (j = 0; j < lp->ncols; j++)
+	{
+		if (vstat[j] == STAT_BASIC)
+			continue;
+
+		switch (lp->vtype[j])
+		{
+		case VFREE:
+			porder[tfree] = j;
+			perm[tfree] = tfree;
+			EGLPNUM_TYPENAME_EGlpNumCopyFrac (qpenalty[tfree], lp->cz[j], cmax);
+			tfree++;
+			break;
+
+		case VLOWER:
+		case VUPPER:
+			porder[vd.nfree + tbndone] = j;
+			perm[vd.nfree + tbndone] = tbndone;
+			EGLPNUM_TYPENAME_EGlpNumCopyFrac (qpenalty[vd.nfree + tbndone], lp->cz[j], cmax);
+			if (lp->vtype[j] == VLOWER)
+				EGLPNUM_TYPENAME_EGlpNumAddTo (qpenalty[vd.nfree + tbndone], lp->lz[j]);
+			else
+				EGLPNUM_TYPENAME_EGlpNumSubTo (qpenalty[vd.nfree + tbndone], lp->uz[j]);
+			tbndone++;
+			break;
+
+		case VFIXED:
+		case VBOUNDED:
+			porder[tot1 + tbounded] = j;
+			perm[tot1 + tbounded] = tbounded;
+			EGLPNUM_TYPENAME_EGlpNumCopyFrac (qpenalty[tot1 + tbndone], lp->cz[j], cmax);
+			EGLPNUM_TYPENAME_EGlpNumAddTo (qpenalty[tot1 + tbndone], lp->lz[j]);
+			EGLPNUM_TYPENAME_EGlpNumSubTo (qpenalty[tot1 + tbndone], lp->uz[j]);
+			tbounded++;
+			break;
+		}
+	}
+	if (tfree != vd.nfree || tbndone != vd.nbndone || tbounded != vd.nbounded)
+	{
+		QSlog("complain: incorrect basis info");
+		rval = E_SIMPLEX_ERROR;
+		ILL_CLEANUP;
+	}
+
+	EGLPNUM_TYPENAME_ILLutil_EGlpNum_perm_quicksort (perm, qpenalty, vd.nfree);
+	EGLPNUM_TYPENAME_ILLutil_EGlpNum_perm_quicksort (perm + vd.nfree, qpenalty + vd.nfree,
+																	vd.nbndone);
+	EGLPNUM_TYPENAME_ILLutil_EGlpNum_perm_quicksort (perm + tot1, qpenalty + tot1, vd.nbounded);
+
+	for (i = 0; i < vd.nbndone; i++)
+		perm[vd.nfree + i] += vd.nfree;
+	for (i = 0; i < vd.nbounded; i++)
+		perm[tot1 + i] += tot1;
+
+	nbelem =
+		primal_col_select (lp, vstat, irow, rrow, unitcol, v, perm, porder, nbelem,
+											 tot2);
+	if (nbelem != lp->nrows)
+	{
+		QSlog("complain: incorrect final basis size");
+		rval = E_SIMPLEX_ERROR;
+		ILL_CLEANUP;
+	}
+
+CLEANUP:
+	EGLPNUM_TYPENAME_EGlpNumClearVar (cmax);
+	if (rval)
+		EGLPNUM_TYPENAME_ILLbasis_free_basisinfo (lp);
+	ILL_IFFREE (irow, int);
+	ILL_IFFREE (rrow, int);
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (v);
+	ILL_IFFREE (perm, int);
+	ILL_IFFREE (porder, int);
+	ILL_IFFREE (unitcol, int);
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (qpenalty);
+	EGLPNUM_TYPENAME_ILLbasis_clear_vardata (&vd);
+	EG_RETURN (rval);
+}
+
+static int get_initial_basis2 (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int *vstat)
+{
+	int rval = 0;
+	int i, j, k, tot1, tot2;
+	int rbeg, rcnt, mcnt;
+	int nbelem = 0, nslacks = 0;
+	int tfree = 0, tbndone = 0;
+	int tbounded = 0;
+	int *irow = NULL, *rrow = NULL;
+	int *perm = NULL, *porder = NULL;
+	int *unitcol = NULL;
+	EGLPNUM_TYPE *v = NULL;
+	EGLPNUM_TYPE *qpenalty = NULL;
+	int col = 0, s_i = 0, selc = 0;
+	int *icol = NULL, *rcol = NULL;
+	int *plen = NULL;
+	EGLPNUM_TYPE *dj = NULL;
+	EGLPNUM_TYPENAME_var_data vd;
+	EGLPNUM_TYPE seldj;
+	EGLPNUM_TYPE selv;
+	EGLPNUM_TYPE c_dj;
+	EGLPNUM_TYPE cmax;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (seldj);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (selv);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (c_dj);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (cmax);
+	EGLPNUM_TYPENAME_EGlpNumZero (c_dj);
+	EGLPNUM_TYPENAME_EGlpNumZero (selv);
+	EGLPNUM_TYPENAME_EGlpNumZero (seldj);
+	EGLPNUM_TYPENAME_ILLbasis_init_vardata (&vd);
+
+	get_var_info (lp, &vd);
+
+	ILL_SAFE_MALLOC (irow, lp->nrows, int);
+	ILL_SAFE_MALLOC (rrow, lp->nrows, int);
+
+	v = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+	ILL_SAFE_MALLOC (unitcol, lp->nrows, int);
+	ILL_SAFE_MALLOC (icol, lp->ncols, int);
+	ILL_SAFE_MALLOC (rcol, lp->ncols, int);
+
+	dj = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->ncols);
+
+	for (i = 0; i < lp->nrows; i++)
+	{
+		unitcol[i] = -1;
+		EGLPNUM_TYPENAME_EGlpNumCopy (v[i], EGLPNUM_TYPENAME_INFTY);
+		irow[i] = 0;
+		rrow[i] = 0;
+	}
+	/* assign all d_j */
+	for (i = 0; i < lp->ncols; i++)
+	{
+		icol[i] = 0;
+		rcol[i] = 0;
+		EGLPNUM_TYPENAME_EGlpNumCopy (dj[i], lp->cz[i]);
+	}
+
+	nslacks = init_slack_basis (lp, vstat, irow, rrow, unitcol, icol, rcol);
+	if (nslacks != vd.nslacks)
+	{
+		QSlog("complain: incorrect basis info");
+		rval = E_SIMPLEX_ERROR;
+		ILL_CLEANUP;
+	}
+	if (nslacks == lp->nrows)
+		ILL_CLEANUP;
+	nbelem = nslacks;
+
+	/* allocate maximum required space for perm etc. */
+	ILL_SAFE_MALLOC (perm, lp->ncols, int);
+	ILL_SAFE_MALLOC (porder, lp->ncols, int);
+	ILL_SAFE_MALLOC (plen, lp->nrows, int);
+
+	qpenalty = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->ncols);
+
+	/* find all unit rows and record lengths */
+	for (i = 0; i < lp->nrows; i++)
+	{
+		if (irow[i] != 1)
+		{
+			rbeg = lp->rowbeg[i];
+			rcnt = lp->rowcnt[i];
+			for (j = 0; j < rcnt; j++)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopyAbs (cmax, lp->rowval[rbeg + j]);
+				if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (cmax, EGLPNUM_TYPENAME_oneLpNum))
+					break;
+			}
+			if (j == rcnt)
+			{
+				perm[s_i] = s_i;
+				porder[s_i] = i;
+				plen[s_i] = rcnt;
+				s_i++;
+			}
+		}
+	}
+
+	/*sort all unit rows */
+	ILLutil_int_perm_quicksort (perm, plen, s_i);
+
+	/* now go through the unit rows */
+	for (k = 0; k < s_i; k++)
+	{
+		i = porder[perm[k]];
+		rbeg = lp->rowbeg[i];
+		rcnt = lp->rowcnt[i];
+		selc = -1;
+		EGLPNUM_TYPENAME_EGlpNumCopy (seldj, EGLPNUM_TYPENAME_INFTY);
+		EGLPNUM_TYPENAME_EGlpNumZero (selv);
+
+		/* for every row s_i, compute min {d_j : d_j <0 , j is u or l or fr} */
+		for (j = 0; j < rcnt; j++)
+		{
+			col = lp->rowind[rbeg + j];
+			if (rcol[col] == 1)
+				break;
+			if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (dj[col]))
+			{
+				if (EGLPNUM_TYPENAME_EGlpNumIsLess (dj[col], seldj))
+				{
+					selc = col;
+					EGLPNUM_TYPENAME_EGlpNumCopy (seldj, dj[col]);
+					EGLPNUM_TYPENAME_EGlpNumCopy (selv, lp->rowval[rbeg + j]);
+				}
+			}
+		}
+		/* select pivot element and update all d_j's */
+		if (selc != -1)
+		{
+			nbelem++;
+			irow[i] = 1;
+			rrow[i] = 1;
+			icol[selc] = 1;
+			EGLPNUM_TYPENAME_EGlpNumCopyFrac (c_dj, dj[selc], selv);
+			vstat[selc] = STAT_BASIC;
+			for (j = 0; j < rcnt; j++)
+			{
+				col = lp->rowind[rbeg + j];
+				EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (dj[col], lp->rowval[rbeg + j], c_dj);
+				rcol[col] = 1;
+			}
+		}
+	}
+#if BASIS_STATS > 0
+	QSlog("unit rows = %d", s_i);
+	QSlog("nslacks %d, unit rows selected = %d", nslacks, nbelem - nslacks);
+#endif
+	/* now go through remaining cols with dj = 0 */
+	tot1 = vd.nfree + vd.nbndone;
+
+	if (!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (vd.cmax))
+		EGLPNUM_TYPENAME_EGlpNumOne (cmax);
+	else
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (cmax, vd.cmax);
+		EGLPNUM_TYPENAME_EGlpNumMultUiTo (cmax, 1000);
+	}
+	for (j = 0; j < lp->ncols; j++)
+	{
+		if (vstat[j] == STAT_BASIC)
+			continue;
+		if (icol[j] == 1 || EGLPNUM_TYPENAME_EGlpNumIsNeqZero (dj[j], EGLPNUM_TYPENAME_BD_TOLER))
+			continue;
+		mcnt = lp->matcnt[j];
+
+		EGLPNUM_TYPENAME_EGlpNumSet (c_dj, (double) mcnt);
+		switch (lp->vtype[j])
+		{
+		case VFREE:
+			porder[tfree] = j;
+			perm[tfree] = tfree;
+			EGLPNUM_TYPENAME_EGlpNumCopyFrac (qpenalty[tfree], lp->cz[j], cmax);
+			EGLPNUM_TYPENAME_EGlpNumAddTo (qpenalty[tfree], c_dj);
+			tfree++;
+			break;
+
+		case VLOWER:
+		case VUPPER:
+			porder[vd.nfree + tbndone] = j;
+			perm[vd.nfree + tbndone] = tbndone;
+			EGLPNUM_TYPENAME_EGlpNumCopyFrac (qpenalty[vd.nfree + tbndone], lp->cz[j], cmax);
+			EGLPNUM_TYPENAME_EGlpNumAddTo (qpenalty[vd.nfree + tbndone], c_dj);
+			if (lp->vtype[j] == VLOWER)
+				EGLPNUM_TYPENAME_EGlpNumAddTo (qpenalty[vd.nfree + tbndone], lp->lz[j]);
+			else
+				EGLPNUM_TYPENAME_EGlpNumSubTo (qpenalty[vd.nfree + tbndone], lp->uz[j]);
+			tbndone++;
+			break;
+
+		case VFIXED:
+		case VBOUNDED:
+			porder[tot1 + tbounded] = j;
+			perm[tot1 + tbounded] = tbounded;
+			EGLPNUM_TYPENAME_EGlpNumCopyFrac (qpenalty[tot1 + tbounded], lp->cz[j], cmax);
+			EGLPNUM_TYPENAME_EGlpNumAddTo (qpenalty[tot1 + tbounded], lp->lz[j]);
+			EGLPNUM_TYPENAME_EGlpNumSubTo (qpenalty[tot1 + tbounded], lp->uz[j]);
+			EGLPNUM_TYPENAME_EGlpNumAddTo (qpenalty[tot1 + tbounded], c_dj);
+			tbounded++;
+			break;
+		}
+	}
+#if BASIS_STATS > 0
+	QSlog("bfree %d, bone %d, bbnd %d", tfree, tbndone, tbounded);
+#endif
+
+	EGLPNUM_TYPENAME_ILLutil_EGlpNum_perm_quicksort (perm, qpenalty, tfree);
+	EGLPNUM_TYPENAME_ILLutil_EGlpNum_perm_quicksort (perm + vd.nfree, qpenalty + vd.nfree,
+																	tbndone);
+	EGLPNUM_TYPENAME_ILLutil_EGlpNum_perm_quicksort (perm + tot1, qpenalty + tot1, tbounded);
+
+	tot2 = tfree + tbndone;
+	for (i = 0; i < tbndone; i++)
+	{
+		perm[tfree + i] = perm[vd.nfree + i] + tfree;
+		porder[tfree + i] = porder[vd.nfree + i];
+	}
+	for (i = 0; i < tbounded; i++)
+	{
+		perm[tot2 + i] = perm[tot1 + i] + tot2;
+		porder[tot2 + i] = porder[tot1 + i];
+	}
+	tot2 += tbounded;
+
+	nbelem =
+		primal_col_select (lp, vstat, irow, rrow, unitcol, v, perm, porder, nbelem,
+											 tot2);
+	if (nbelem != lp->nrows)
+	{
+		QSlog("complain: incorrect final basis size");
+		rval = E_SIMPLEX_ERROR;
+		ILL_CLEANUP;
+	}
+
+CLEANUP:
+	if (rval)
+		EGLPNUM_TYPENAME_ILLbasis_free_basisinfo (lp);
+
+	ILL_IFFREE (irow, int);
+	ILL_IFFREE (rrow, int);
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (v);
+	ILL_IFFREE (unitcol, int);
+	ILL_IFFREE (icol, int);
+	ILL_IFFREE (rcol, int);
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (dj);
+	ILL_IFFREE (perm, int);
+	ILL_IFFREE (porder, int);
+	ILL_IFFREE (plen, int);
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (qpenalty);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (seldj);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (selv);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (c_dj);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (cmax);
+	EGLPNUM_TYPENAME_ILLbasis_clear_vardata (&vd);
+	EG_RETURN (rval);
+}
+
+static int set_basis_indices (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int *vstat)
+{
+	int i, b = 0, nb = 0;
+	int vs;
+
+	for (i = 0; i < lp->ncols; i++)
+	{
+		vs = vstat[i];
+		lp->vstat[i] = vs;
+
+		if (vs == STAT_BASIC)
+		{
+			lp->baz[b] = i;
+			lp->vindex[i] = b;
+			b++;
+		}
+		else if (vs == STAT_UPPER || vs == STAT_LOWER || vs == STAT_ZERO)
+		{
+			lp->nbaz[nb] = i;
+			lp->vindex[i] = nb;
+			nb++;
+		}
+		else
+		{
+			QSlog("Error in basis creation");
+			return E_SIMPLEX_ERROR;
+		}
+	}
+	if (b != lp->nrows)
+	{
+		QSlog("Error 2 in basis creation");
+		return E_SIMPLEX_ERROR;
+	}
+	else if (nb != lp->nnbasic)
+	{
+		QSlog("Error 3 in basis creation");
+		return E_SIMPLEX_ERROR;
+	}
+	return 0;
+}
+
+int EGLPNUM_TYPENAME_ILLbasis_get_initial (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int algorithm)
+{
+	int rval = 0;
+	int *vstat = NULL;
+
+	EGLPNUM_TYPENAME_ILLbasis_free_basisinfo (lp);
+	EGLPNUM_TYPENAME_ILLbasis_init_basisinfo (lp);
+	rval = EGLPNUM_TYPENAME_ILLbasis_build_basisinfo (lp);
+	CHECKRVALG (rval, CLEANUP);
+
+	ILL_SAFE_MALLOC (vstat, lp->ncols, int);
+
+	if (algorithm == PRIMAL_SIMPLEX)
+		rval = get_initial_basis1 (lp, vstat);
+	else
+		rval = get_initial_basis2 (lp, vstat);
+
+	if (rval == E_SIMPLEX_ERROR)
+	{
+#ifdef HAVE_LIBZ
+		EGioFile_t *f = EGioOpen ("bad.lp.gz", "w");
+#else
+#ifdef HAVE_LIBBZ2
+		EGioFile_t *f = EGioOpen ("bad.lp.bz2", "w");
+#else
+		EGioFile_t *f = EGioOpen ("bad.lp", "w");
+#endif
+#endif
+		int tval = EGLPNUM_TYPENAME_ILLwrite_lp_file (lp->O, f, NULL);
+		if (tval)
+		{
+			QSlog("Error writing bad lp");
+		}
+		if (f != NULL)
+			EGioClose (f);
+	}
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = set_basis_indices (lp, vstat);
+	CHECKRVALG (rval, CLEANUP);
+	lp->basisid = 0;
+
+CLEANUP:
+	ILL_IFFREE (vstat, int);
+
+	EG_RETURN (rval);
+}
+
+static int choose_basis (
+	int algorithm,
+	EGLPNUM_TYPE pinf1,
+	EGLPNUM_TYPE dinf1,
+	EGLPNUM_TYPE pinf2,
+	EGLPNUM_TYPE dinf2)
+{
+/* We changed the constant definitions outside here, the actual numbers are
+ * asigned in lpdata.c. the values are as follows:
+ * EGLPNUM_TYPENAME_CB_EPS = 0.001;
+ * EGLPNUM_TYPENAME_CB_PRI_RLIMIT = 0.25;
+ * EGLPNUM_TYPENAME_CB_INF_RATIO = 10.0; 
+ * */
+	int choice = 1;
+	EGLPNUM_TYPE rp, rd;
+
+	if (algorithm == PRIMAL_SIMPLEX)
+	{
+		EGLPNUM_TYPENAME_EGlpNumInitVar (rp);
+		EGLPNUM_TYPENAME_EGlpNumInitVar (rd);
+		EGLPNUM_TYPENAME_EGlpNumCopyDiff (rp, pinf1, pinf2);
+		EGLPNUM_TYPENAME_EGlpNumCopyDiff (rd, dinf1, dinf2);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLeq (rp, EGLPNUM_TYPENAME_CB_EPS) && EGLPNUM_TYPENAME_EGlpNumIsLeq (rd, EGLPNUM_TYPENAME_CB_EPS))
+			choice = 1;
+		else
+		{
+			EGLPNUM_TYPENAME_EGlpNumSign (rp);
+			EGLPNUM_TYPENAME_EGlpNumSign (rd);
+			if (EGLPNUM_TYPENAME_EGlpNumIsLeq (rp, EGLPNUM_TYPENAME_CB_EPS) && EGLPNUM_TYPENAME_EGlpNumIsLeq (rd, EGLPNUM_TYPENAME_CB_EPS))
+				choice = 2;
+			else if (EGLPNUM_TYPENAME_EGlpNumIsLess (pinf1, pinf2) && EGLPNUM_TYPENAME_EGlpNumIsLess (dinf2, dinf1))
+			{
+				choice = 1;
+				EGLPNUM_TYPENAME_EGlpNumCopyFrac (rp, pinf1, pinf2);
+				EGLPNUM_TYPENAME_EGlpNumCopyFrac (rd, dinf2, dinf1);
+				EGLPNUM_TYPENAME_EGlpNumMultTo (rd, EGLPNUM_TYPENAME_CB_INF_RATIO);
+				if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_CB_PRI_RLIMIT, rp) && (EGLPNUM_TYPENAME_EGlpNumIsLess (rd, rp)))
+					choice = 2;
+			}
+			else if (EGLPNUM_TYPENAME_EGlpNumIsLess (pinf2, pinf1) && EGLPNUM_TYPENAME_EGlpNumIsLess (dinf1, dinf2))
+			{
+				choice = 2;
+				EGLPNUM_TYPENAME_EGlpNumCopyFrac (rp, pinf2, pinf1);
+				EGLPNUM_TYPENAME_EGlpNumCopyFrac (rd, dinf1, dinf2);
+				EGLPNUM_TYPENAME_EGlpNumMultTo (rd, EGLPNUM_TYPENAME_CB_INF_RATIO);
+				if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_CB_PRI_RLIMIT, rp) && EGLPNUM_TYPENAME_EGlpNumIsLess (rd, rp))
+					choice = 1;
+			}
+			else
+				choice = 1;
+		}
+		EGLPNUM_TYPENAME_EGlpNumClearVar (rp);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (rd);
+	}
+	ILL_IFTRACE ("%s:%d\n", __func__, choice);
+	return choice;
+}
+
+int EGLPNUM_TYPENAME_ILLbasis_get_cinitial (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int algorithm)
+{
+	int rval = 0;
+	int *vstat1 = NULL;
+	int *vstat2 = NULL;
+	int singular;
+	int choice = 0;
+
+#if BASIS_STATS > 0
+	int i, nz1 = 0, nz2 = 0;
+#endif
+	EGLPNUM_TYPE pinf1, pinf2, dinf1, dinf2;
+	EGLPNUM_TYPENAME_feas_info fi;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (pinf1);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (pinf2);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (dinf1);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (dinf2);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (fi.totinfeas);
+
+	EGLPNUM_TYPENAME_ILLbasis_free_basisinfo (lp);
+	EGLPNUM_TYPENAME_ILLbasis_init_basisinfo (lp);
+	rval = EGLPNUM_TYPENAME_ILLbasis_build_basisinfo (lp);
+	CHECKRVALG (rval, CLEANUP);
+
+	ILL_SAFE_MALLOC (vstat1, lp->ncols, int);
+	ILL_SAFE_MALLOC (vstat2, lp->ncols, int);
+
+	if (algorithm != PRIMAL_SIMPLEX)
+	{
+		rval = get_initial_basis2 (lp, vstat2);
+		CHECKRVALG (rval, CLEANUP);
+		rval = set_basis_indices (lp, vstat2);
+		lp->basisid = 0;
+		ILL_CLEANUP;
+	}
+
+	rval = get_initial_basis1 (lp, vstat1);
+	CHECKRVALG (rval, CLEANUP);
+	rval = get_initial_basis2 (lp, vstat2);
+	CHECKRVALG (rval, CLEANUP);
+	lp->basisid = 0;
+
+	/* handle first basis */
+	rval = set_basis_indices (lp, vstat1);
+	CHECKRVALG (rval, CLEANUP);
+#if BASIS_STATS > 0
+	for (i = 0; i < lp->nrows; i++)
+		nz1 += lp->matcnt[lp->baz[i]];
+#endif
+	rval = EGLPNUM_TYPENAME_ILLbasis_factor (lp, &singular);
+	if (singular)
+		MESSAGE (__QS_SB_VERB, "Singular Basis found!");
+	CHECKRVALG (rval, CLEANUP);
+
+	EGLPNUM_TYPENAME_ILLfct_compute_piz (lp);
+	EGLPNUM_TYPENAME_ILLfct_compute_dz (lp);
+	EGLPNUM_TYPENAME_ILLfct_dual_adjust (lp, EGLPNUM_TYPENAME_zeroLpNum);
+	EGLPNUM_TYPENAME_ILLfct_compute_xbz (lp);
+
+	EGLPNUM_TYPENAME_ILLfct_check_pfeasible (lp, &fi, lp->tol->pfeas_tol);
+	EGLPNUM_TYPENAME_ILLfct_check_dfeasible (lp, &fi, lp->tol->dfeas_tol);
+	EGLPNUM_TYPENAME_EGlpNumCopy (pinf1, lp->pinfeas);
+	EGLPNUM_TYPENAME_EGlpNumCopy (dinf1, lp->dinfeas);
+	/*
+	 * EGLPNUM_TYPENAME_ILLfct_compute_pobj (lp);  obj1p = lp->objval;
+	 * EGLPNUM_TYPENAME_ILLfct_compute_dobj (lp);  obj1d = lp->objval;
+	 */
+
+	/* handle second basis */
+	rval = set_basis_indices (lp, vstat2);
+	CHECKRVALG (rval, CLEANUP);
+#if BASIS_STATS > 0
+	for (i = 0; i < lp->nrows; i++)
+		nz2 += lp->matcnt[lp->baz[i]];
+#endif
+	rval = EGLPNUM_TYPENAME_ILLbasis_factor (lp, &singular);
+	if (singular)
+		MESSAGE (__QS_SB_VERB, "Singular Basis found!");
+	CHECKRVALG (rval, CLEANUP);
+
+	EGLPNUM_TYPENAME_ILLfct_compute_piz (lp);
+	EGLPNUM_TYPENAME_ILLfct_compute_dz (lp);
+	EGLPNUM_TYPENAME_ILLfct_dual_adjust (lp, EGLPNUM_TYPENAME_zeroLpNum);
+	EGLPNUM_TYPENAME_ILLfct_compute_xbz (lp);
+
+	EGLPNUM_TYPENAME_ILLfct_check_pfeasible (lp, &fi, lp->tol->pfeas_tol);
+	EGLPNUM_TYPENAME_ILLfct_check_dfeasible (lp, &fi, lp->tol->dfeas_tol);
+	EGLPNUM_TYPENAME_EGlpNumCopy (pinf2, lp->pinfeas);
+	EGLPNUM_TYPENAME_EGlpNumCopy (dinf2, lp->dinfeas);
+
+#if BASIS_STATS > 0
+	QSlog("b1: nz %d pinf %.2f dinf %.2f", nz1, EGLPNUM_TYPENAME_EGlpNumToLf (pinf1),
+							EGLPNUM_TYPENAME_EGlpNumToLf (dinf1));
+	QSlog("b2: nz %d pinf %.2f dinf %.2f", nz2, EGLPNUM_TYPENAME_EGlpNumToLf (pinf2),
+					EGLPNUM_TYPENAME_EGlpNumToLf (dinf2));
+#endif
+	choice = choose_basis (algorithm, pinf1, dinf1, pinf2, dinf2);
+	if (choice == 1)
+	{
+		lp->fbasisid = -1;
+		rval = set_basis_indices (lp, vstat1);
+		CHECKRVALG (rval, CLEANUP);
+	}
+
+CLEANUP:
+	if (rval == E_SIMPLEX_ERROR)
+	{
+#ifdef HAVE_LIBZ
+		EGioFile_t *fil = EGioOpen ("bad.lp.gz", "w");
+#else
+#ifdef HAVE_LIBBZ2
+		EGioFile_t *fil = EGioOpen ("bad.lp.bz2", "w");
+#else
+		EGioFile_t *fil = EGioOpen ("bad.lp", "w");
+#endif
+#endif
+		int tval = EGLPNUM_TYPENAME_ILLwrite_lp_file (lp->O, fil, NULL);
+
+		if (tval)
+		{
+			QSlog("Error writing bad lp");
+		}
+		if (fil != NULL)
+			EGioClose (fil);
+	}
+	ILL_IFFREE (vstat1, int);
+	ILL_IFFREE (vstat2, int);
+
+	EGLPNUM_TYPENAME_EGlpNumClearVar (pinf1);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (pinf2);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (dinf1);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (dinf2);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (fi.totinfeas);
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLbasis_factor (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int *singular)
+{
+	int rval = 0;
+	int i;
+	int eindex;
+	int lindex;
+	int ltype;
+	int lvstat;
+	int nsing = 0;
+	int *singr = 0;
+	int *singc = 0;
+
+	*singular = 0;
+	do
+	{
+		if (lp->f)
+		{
+			EGLPNUM_TYPENAME_ILLfactor_free_factor_work (lp->f);
+		}
+		else
+		{
+			ILL_SAFE_MALLOC (lp->f, 1, EGLPNUM_TYPENAME_factor_work);
+			EGLPNUM_TYPENAME_EGlpNumInitVar (lp->f->fzero_tol);
+			EGLPNUM_TYPENAME_EGlpNumInitVar (lp->f->szero_tol);
+			EGLPNUM_TYPENAME_EGlpNumInitVar (lp->f->partial_tol);
+			EGLPNUM_TYPENAME_EGlpNumInitVar (lp->f->maxelem_orig);
+			EGLPNUM_TYPENAME_EGlpNumInitVar (lp->f->maxelem_factor);
+			EGLPNUM_TYPENAME_EGlpNumInitVar (lp->f->maxelem_cur);
+			EGLPNUM_TYPENAME_EGlpNumInitVar (lp->f->partial_cur);
+			EGLPNUM_TYPENAME_ILLfactor_init_factor_work (lp->f);
+		}
+		rval = EGLPNUM_TYPENAME_ILLfactor_create_factor_work (lp->f, lp->O->nrows);
+		CHECKRVALG (rval, CLEANUP);
+
+		rval = EGLPNUM_TYPENAME_ILLfactor (lp->f, lp->baz, lp->matbeg, lp->matcnt,
+											lp->matind, lp->matval, &nsing, &singr, &singc);
+		CHECKRVALG (rval, CLEANUP);
+
+		if (nsing != 0)
+		{
+			*singular = 1;
+			MESSAGE (__QS_SB_VERB, "Found singular basis!");
+			for (i = 0; i < nsing; i++)
+			{
+				eindex = lp->vindex[lp->O->rowmap[singr[i]]];
+				lindex = singc[i];
+				ltype = lp->vtype[lp->baz[lindex]];
+
+				if (ltype == VBOUNDED || ltype == VLOWER || ltype == VARTIFICIAL)
+					lvstat = STAT_LOWER;
+				else if (ltype == VUPPER)
+					lvstat = STAT_UPPER;
+				else
+					lvstat = STAT_ZERO;
+
+				EGLPNUM_TYPENAME_ILLfct_update_basis_info (lp, eindex, lindex, lvstat);
+				lp->basisid++;
+			}
+			ILL_IFFREE (singr, int);
+			ILL_IFFREE (singc, int);
+		}
+
+	} while (nsing != 0);
+
+	lp->fbasisid = lp->basisid;
+
+CLEANUP:
+	ILL_IFFREE (singr, int);
+	ILL_IFFREE (singc, int);
+
+	if (rval)
+		QSlog("Error: unknown in %s", __func__);
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLbasis_refactor (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	int sing = 0;
+	int rval = 0;
+
+	rval = EGLPNUM_TYPENAME_ILLbasis_factor (lp, &sing);
+	if (sing)
+	{
+		MESSAGE (__QS_SB_VERB, "Singular Basis found!");
+		rval = QS_LP_CHANGE_PREC;
+		return rval;
+	}
+	EG_RETURN (rval);
+}
+
+void EGLPNUM_TYPENAME_ILLbasis_column_solve (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * rhs,
+	EGLPNUM_TYPENAME_svector * soln)
+{
+	EGLPNUM_TYPENAME_ILLfactor_ftran (lp->f, rhs, soln);
+}
+
+void EGLPNUM_TYPENAME_ILLbasis_column_solve_update (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * rhs,
+	EGLPNUM_TYPENAME_svector * upd,
+	EGLPNUM_TYPENAME_svector * soln)
+{
+	EGLPNUM_TYPENAME_ILLfactor_ftran_update (lp->f, rhs, upd, soln);
+}
+
+void EGLPNUM_TYPENAME_ILLbasis_row_solve (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * rhs,
+	EGLPNUM_TYPENAME_svector * soln)
+{
+	EGLPNUM_TYPENAME_ILLfactor_btran (lp->f, rhs, soln);
+}
+
+int EGLPNUM_TYPENAME_ILLbasis_update (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * y,
+	int lindex,
+	int *refactor,
+	int *singular)
+{
+#if 0														/* To always refactor, change 0 to 1 */
+	*refactor = 1;
+	return EGLPNUM_TYPENAME_ILLbasis_factor (lp, singular);
+#else
+
+	int rval = 0;
+
+	*refactor = 0;
+	rval = EGLPNUM_TYPENAME_ILLfactor_update (lp->f, y, lindex, refactor);
+	if (rval == E_FACTOR_BLOWUP || rval == E_UPDATE_SINGULAR_ROW
+			|| rval == E_UPDATE_SINGULAR_COL)
+	{
+/* Bico - comment out for dist
+       QSlog("Warning: numerically bad basis in EGLPNUM_TYPENAME_ILLfactor_update");
+*/
+		*refactor = 1;
+		rval = 0;
+	}
+	if (rval == E_UPDATE_NOSPACE)
+	{
+		*refactor = 1;
+		rval = 0;
+	}
+
+	if (*refactor)
+	{
+		rval = EGLPNUM_TYPENAME_ILLbasis_factor (lp, singular);
+		if (*singular)
+			MESSAGE (__QS_SB_VERB, "Singular Basis found!");
+	}
+	if (rval)
+	{
+		EGioFile_t *eout = 0;
+		int tval;
+
+		QSlog("write bad lp to factor.lp");
+#ifdef HAVE_LIBZ
+		eout = EGioOpen ("factor.lp.gz", "w");
+#else
+#ifdef HAVE_LIBBZ2
+		eout = EGioOpen ("factor.lp.bz2", "w");
+#else
+		eout = EGioOpen ("factor.lp", "w");
+#endif
+#endif
+		if (!eout)
+		{
+			QSlog("could not open file to write bad factor lp");
+		}
+		else
+		{
+			tval = EGLPNUM_TYPENAME_ILLwrite_lp_file (lp->O, eout, NULL);
+			if (tval)
+			{
+				QSlog("error while writing bad factor lp");
+			}
+			EGioClose (eout);
+		}
+
+		QSlog("write bad basis to factor.bas");
+		tval = EGLPNUM_TYPENAME_ILLlib_writebasis (lp, 0, "factor.bas");
+		if (tval)
+		{
+			QSlog("error while writing factor basis");
+		}
+	}
+
+	EG_RETURN (rval);
+#endif
+}
diff --git a/qsopt_ex/basis.h b/qsopt_ex/basis.h
new file mode 100644
index 0000000..9d073be
--- /dev/null
+++ b/qsopt_ex/basis.h
@@ -0,0 +1,99 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCSINFO $Id: basis_EGLPNUM_TYPENAME.h,v 1.3 2003/11/05 16:57:39 meven Exp $ */
+#ifndef EGLPNUM_TYPENAME___BASIS_H
+#define EGLPNUM_TYPENAME___BASIS_H
+
+#include "dstruct_EGLPNUM_TYPENAME.h"
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+#include "lpdata_EGLPNUM_TYPENAME.h"
+
+
+typedef struct EGLPNUM_TYPENAME_var_data
+{
+	int nartif;
+	int nslacks;
+	int nfree;
+	int nbndone;
+	int nbounded;
+	int nfixed;
+	EGLPNUM_TYPE cmax;
+}
+EGLPNUM_TYPENAME_var_data;
+
+void EGLPNUM_TYPENAME_ILLbasis_init_vardata (
+	EGLPNUM_TYPENAME_var_data * vd);
+void EGLPNUM_TYPENAME_ILLbasis_clear_vardata (
+	EGLPNUM_TYPENAME_var_data * vd);
+
+int EGLPNUM_TYPENAME_ILLbasis_build_basisinfo (
+	EGLPNUM_TYPENAME_lpinfo * lp),
+  EGLPNUM_TYPENAME_ILLbasis_get_initial (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int algorithm),
+  EGLPNUM_TYPENAME_ILLbasis_get_cinitial (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int algorithm),
+  EGLPNUM_TYPENAME_ILLbasis_load (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_ILLlp_basis * B),
+  EGLPNUM_TYPENAME_ILLbasis_tableau_row (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int row,
+	EGLPNUM_TYPE * brow,
+	EGLPNUM_TYPE * trow,
+	EGLPNUM_TYPE * rhs,
+	int strict),
+  EGLPNUM_TYPENAME_ILLbasis_factor (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int *singular),
+  EGLPNUM_TYPENAME_ILLbasis_refactor (
+	EGLPNUM_TYPENAME_lpinfo * lp),
+  EGLPNUM_TYPENAME_ILLbasis_update (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * y,
+	int lindex,
+	int *refactor,
+	int *singular);
+
+void EGLPNUM_TYPENAME_ILLbasis_column_solve (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * rhs,
+	EGLPNUM_TYPENAME_svector * soln),
+  EGLPNUM_TYPENAME_ILLbasis_column_solve_update (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * rhs,
+	EGLPNUM_TYPENAME_svector * upd,
+	EGLPNUM_TYPENAME_svector * soln),
+  EGLPNUM_TYPENAME_ILLbasis_row_solve (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * rhs,
+	EGLPNUM_TYPENAME_svector * soln),
+  EGLPNUM_TYPENAME_ILLbasis_free_basisinfo (
+	EGLPNUM_TYPENAME_lpinfo * lp),
+  EGLPNUM_TYPENAME_ILLbasis_free_fbasisinfo (
+	EGLPNUM_TYPENAME_lpinfo * lp),
+  EGLPNUM_TYPENAME_ILLbasis_init_basisinfo (
+	EGLPNUM_TYPENAME_lpinfo * lp);
+
+#endif /* EGLPNUM_TYPENAME___BASIS_H */
diff --git a/qsopt_ex/bgetopt.c b/qsopt_ex/bgetopt.c
new file mode 100644
index 0000000..3ba4564
--- /dev/null
+++ b/qsopt_ex/bgetopt.c
@@ -0,0 +1,132 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCSINFO $Id: bgetopt.c,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of CONCORDE                                           */
+/*                                                                          */
+/*  (c) Copyright 1995--1999 by David Applegate, Robert Bixby,              */
+/*  Vasek Chvatal, and William Cook                                         */
+/*                                                                          */
+/*  Permission is granted for academic research use.  For other uses,       */
+/*  contact the authors for licensing options.                              */
+/*                                                                          */
+/*  Use at your own risk.  We make no guarantees about the                  */
+/*  correctness or usefulness of this code.                                 */
+/*                                                                          */
+/****************************************************************************/
+
+/****************************************************************************/
+/*                                                                          */
+/*                        PORTABLE GETOPT                                   */
+/*                                                                          */
+/*                           TSP CODE                                       */
+/*                                                                          */
+/*                                                                          */
+/*  Written by:  Applegate, Bixby, Chvatal, and Cook                        */
+/*  Date: 1993 (?) (fmfeb02)                                                */
+/*  Modified: 15 February 1995 (bico)  - added warning                      */
+/*                                                                          */
+/*    EXPORTED FUNCTIONS:                                                   */
+/*                                                                          */
+/*  int ILLutil_bix_getopt (int argc, char **argv, const char *def,          */
+/*      int *p_optind, char **p_optarg)                                     */
+/*     parse an argument list                                               */
+/*                                                                          */
+/****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "logging-private.h"
+
+#include "util.h"
+
+
+int ILLutil_bix_getopt (
+	int ac,
+	char **av,
+	const char *def,
+	int *p_optind,
+	char **p_optarg)
+{
+	int c;
+	char *sp = av[*p_optind];
+	char bwarn[2];
+
+	if (*p_optind < 1 || *p_optind >= ac)
+	{
+		*p_optind = ac;
+		return (EOF);
+	}
+	if ((int) *sp != (int) '-')
+		return (EOF);
+	if ((int) *(sp + 1) == (int) '-')
+	{
+		(*p_optind)++;
+		return (EOF);
+	}
+	(av[*p_optind])++;
+	sp++;
+	while ((int) *sp != (int) *def && (int) *def != (int) '\0')
+		def++;
+	if ((int) *def == (int) '\0')
+	{
+		*p_optind = ac;
+		bwarn[0] = *sp;							/* Bico: February 8, 1995 */
+		bwarn[1] = '\0';
+		QSlog("Illegal option: -%s", bwarn);
+		return ILL_BIX_GETOPT_UNKNOWN;
+	}
+	if ((int) *(def + 1) != (int) ':')
+	{
+		c = *sp;
+		if ((int) *(sp + 1) != (int) '\0')
+			*sp = '-';
+		else
+			(*p_optind)++;
+		return (c);
+	}
+	else
+	{
+		if ((int) *(sp + 1) != (int) '\0')
+		{
+			*p_optarg = sp + 1;
+			c = *sp;
+			(*p_optind)++;
+			return (c);
+		}
+		else if (*p_optind >= ac - 1)
+		{
+			*p_optind = ac;
+			return (EOF);
+		}
+		else
+		{
+			*p_optarg = av[*p_optind + 1];
+			c = *sp;
+			*p_optind += 2;
+			return (c);
+		}
+	}
+}
diff --git a/qsopt_ex/bgetopt.h b/qsopt_ex/bgetopt.h
new file mode 100644
index 0000000..6ec0cf0
--- /dev/null
+++ b/qsopt_ex/bgetopt.h
@@ -0,0 +1,43 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+#ifndef __BGETOPT_H__
+#define __BGETOPT_H__
+
+/****************************************************************************/
+/*                                                                          */
+/*                             bgetopt.c                                    */
+/*                                                                          */
+/****************************************************************************/
+int ILLutil_bix_getopt (
+	int argc,
+	char **argv,
+	const char *def,
+	int *p_optind,
+	char **p_optarg);
+
+
+#define ILL_BIX_GETOPT_UNKNOWN -3038
+
+
+
+#endif
diff --git a/qsopt_ex/binary.c b/qsopt_ex/binary.c
new file mode 100644
index 0000000..56363bb
--- /dev/null
+++ b/qsopt_ex/binary.c
@@ -0,0 +1,1756 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: binary.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+static int TRACE = 0;
+
+/****************************************************************************/
+/*                                                                          */
+/*                     Simple MIP Code to test LP Solver                    */
+/*                                                                          */
+/*  EXPORTED FUNCTIONS                                                      */
+/*                                                                          */
+/*    int EGLPNUM_TYPENAME_ILLmip_bfs (EGLPNUM_TYPENAME_lpinfo *lp, double *val, double *x)                   */
+/*                                                                          */
+/*  NOTES                                                                   */
+/*                                                                          */
+/*                                                                          */
+/****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "allocrus.h"
+#include "eg_lpnum.h"
+#include "eg_io.h"
+#include "except.h"
+#include "zeit.h"
+
+#include "priority_EGLPNUM_TYPENAME.h"
+#include "sortrus_EGLPNUM_TYPENAME.h"
+#include "lpdata_EGLPNUM_TYPENAME.h"
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+#include "simplex_EGLPNUM_TYPENAME.h"
+#include "binary_EGLPNUM_TYPENAME.h"
+#include "price_EGLPNUM_TYPENAME.h"
+#include "lib_EGLPNUM_TYPENAME.h"
+#include "qstruct_EGLPNUM_TYPENAME.h"
+#include "qsopt_EGLPNUM_TYPENAME.h"
+
+/*#define  ILL_INTTOL (0.000001)*/
+#define ILL_INTTOL EGLPNUM_TYPENAME_PFEAS_TOLER
+
+#define  STRONG_PIVOTS     (50)
+#define  STRONG_CANDIDATES (10)
+
+#define ILL_BRANCH_STRONG_WEIGHT (10)
+#define ILL_BRANCH_STRONG_VAL(v0,v1)                                 \
+    (((v0) < (v1) ? (ILL_BRANCH_STRONG_WEIGHT * (v0) + (v1))         \
+                  : (ILL_BRANCH_STRONG_WEIGHT * (v1) + (v0)))        \
+                    / (ILL_BRANCH_STRONG_WEIGHT + 1.0))
+
+#define ILL_BRANCH_PENALTY_WEIGHT (2)
+#define ILL_BRANCH_PENALTY_VAL(v0,v1,f)                              \
+    (((v0)*(f) < (v1)*(1.0-(f)) ?                                    \
+        (ILL_BRANCH_PENALTY_WEIGHT * (v0)*(f) + (v1)*(1.0-(f)))    \
+      : (ILL_BRANCH_PENALTY_WEIGHT * (v1)*(1.0-(f)) + (v0)*(f)))    \
+                    / (ILL_BRANCH_PENALTY_WEIGHT + 1.0))
+
+
+
+#define FIRSTBRANCH  1
+#define MIDDLEBRANCH 2
+#define STRONGBRANCH 3
+#define PENALTYBRANCH 4
+
+
+typedef struct bbnode
+{
+	struct bbnode *next;
+	struct bbnode *prev;
+	int id;
+	int depth;
+	int handle;
+	EGLPNUM_TYPE bound;
+	char *cstat;
+	char *rstat;
+	EGLPNUM_TYPE *rownorms;
+	int rownorms_size;
+	int bound_cnt;
+	int *bound_indx;
+	char *lu;
+	EGLPNUM_TYPE *bounds;
+	int bounds_size;
+}
+bbnode;
+
+typedef struct mipinfo
+{
+	int branching_rule;
+	int watch;
+	int depth;
+	int totalnodes;
+	int activenodes;
+	int totalpivots;
+	int lastpivots;
+	int objsense;
+	EGLPNUM_TYPE objectivebound;
+	EGLPNUM_TYPE value;
+	EGLPNUM_TYPE *downpen;
+	EGLPNUM_TYPE *uppen;
+	EGLPNUM_TYPE *x;
+	EGLPNUM_TYPE *bestx;
+	EGLPNUM_TYPE *orig_lower;
+	EGLPNUM_TYPE *orig_upper;
+	EGLPNUM_TYPE *lower;
+	EGLPNUM_TYPE *upper;
+	int nstruct;									/* size of all EGLPNUM_TYPE arrays */
+	EGLPNUM_TYPENAME_lpinfo *lp;
+	EGLPNUM_TYPENAME_price_info *pinf;
+	bbnode head_bbnode;
+	EGLPNUM_TYPENAME_ILLpriority *que;
+	ILLptrworld ptrworld;
+}
+mipinfo;
+
+
+ILL_PTRWORLD_ROUTINES (bbnode, bbnodealloc, bbnode_bulkalloc, bbnodefree)
+ILL_PTRWORLD_LISTFREE_ROUTINE (bbnode, bbnode_listfree, bbnodefree)
+ILL_PTRWORLD_LEAKS_ROUTINE (bbnode, bbnode_check_leaks, depth, int)
+static void cleanup_mip ( mipinfo * minf), 
+		choose_initial_price ( EGLPNUM_TYPENAME_price_info * pinf), 
+		best_bbnode ( mipinfo * minf, bbnode ** best),
+		put_bbnode ( mipinfo * minf, bbnode * b),
+		remove_bbnode ( bbnode * b),
+		find_first_branch ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPE * x, int *bvar),
+		find_middle_branch ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPE * x, int *bvar),
+		check_integral ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPE * x, int *yesno),
+		copy_x ( int nstruct, EGLPNUM_TYPE * from_x, EGLPNUM_TYPE * to_x),
+		init_mipinfo ( mipinfo * minf),
+		free_mipinfo ( mipinfo * minf),
+		init_bbnode ( bbnode * b),
+		free_bbnode ( bbnode * b);
+
+static int startup_mip ( mipinfo * minf, EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_price_info * pinf,
+			EGLPNUM_TYPE * lpval, itcnt_t*itcnt),
+		run_bfs ( mipinfo * minf, itcnt_t*itcnt),
+		process_bfs_bbnode ( mipinfo * minf, bbnode * b, itcnt_t*itcnt),
+		child_work ( mipinfo * minf, bbnode * active, int bvar, int bdir,
+			EGLPNUM_TYPE * cval, int *cp, itcnt_t*itcnt),
+		fix_variables ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPE * bestval, bbnode * b,
+			EGLPNUM_TYPE * wupper, EGLPNUM_TYPE * wlower, int *hit),
+		find_branch ( mipinfo * minf, EGLPNUM_TYPE * x, EGLPNUM_TYPE * lpval,
+			int *bvar, itcnt_t*itcnt),
+		find_penalty_branch ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_price_info * pinf, EGLPNUM_TYPE * x,
+			EGLPNUM_TYPE * downpen, EGLPNUM_TYPE * uppen, EGLPNUM_TYPE * lpval, int *bvar,
+			itcnt_t*itcnt),
+		find_strong_branch ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_price_info * pinf, EGLPNUM_TYPE * x,
+			int *bvar, itcnt_t*itcnt),
+		plunge ( mipinfo * minf, itcnt_t*itcnt),
+		plunge_work ( mipinfo * minf, int depth, itcnt_t*itcnt),
+		round_variables ( mipinfo * minf, int *count, EGLPNUM_TYPE * tol);
+
+static void choose_initial_price ( EGLPNUM_TYPENAME_price_info * pinf)
+{
+	pinf->pI_price = QS_PRICE_PSTEEP;
+	pinf->pII_price = QS_PRICE_PSTEEP;
+	pinf->dI_price = QS_PRICE_DSTEEP;
+	pinf->dII_price = QS_PRICE_DSTEEP;
+}
+
+int EGLPNUM_TYPENAME_ILLmip_bfs (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPE * val,
+	EGLPNUM_TYPE * x,
+	itcnt_t*itcnt)
+{
+	int tval, rval = 0;
+	EGLPNUM_TYPENAME_price_info pinf;
+	mipinfo minf;
+	bbnode *b;
+	EGLPNUM_TYPE lpval;
+	double szeit = ILLutil_zeit ();
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (lpval);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (pinf.htrigger);
+
+	EGLPNUM_TYPENAME_ILLprice_init_pricing_info (&pinf);
+	init_mipinfo (&minf);
+
+	if (!lp)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLmip_bfs called without an LP");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	rval = startup_mip (&minf, lp, &pinf, &lpval, itcnt);
+	ILL_CLEANUP_IF (rval);
+
+	ILL_SAFE_MALLOC (minf.que, 1, EGLPNUM_TYPENAME_ILLpriority);
+	rval = EGLPNUM_TYPENAME_ILLutil_priority_init (minf.que, lp->O->nstruct + 1);
+	ILL_CLEANUP_IF (rval);
+
+	b = bbnodealloc (&minf.ptrworld);
+	init_bbnode (b);
+	b->depth = 0;
+	b->id = minf.totalnodes++;
+	EGLPNUM_TYPENAME_EGlpNumCopy (b->bound, lpval);
+	ILL_SAFE_MALLOC (b->cstat, lp->O->nstruct, char);
+	ILL_SAFE_MALLOC (b->rstat, lp->nrows, char);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_getbasis (lp, b->cstat, b->rstat);
+	ILL_CLEANUP_IF (rval);
+
+	if (pinf.dII_price == QS_PRICE_DSTEEP)
+	{
+		b->rownorms = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+		tval = EGLPNUM_TYPENAME_ILLlib_getrownorms (lp, &pinf, b->rownorms);
+		if (tval)
+		{
+			QSlog("Row norms not available");
+			EGLPNUM_TYPENAME_EGlpNumFreeArray (b->rownorms);
+		}
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLutil_priority_insert (minf.que, (void *) b, &lpval, &(b->handle));
+	ILL_CLEANUP_IF (rval);
+
+	b->prev = &(minf.head_bbnode);
+	b->next = 0;
+	minf.head_bbnode.next = b;
+	minf.activenodes++;
+
+	minf.branching_rule = PENALTYBRANCH;
+
+	rval = run_bfs (&minf, itcnt);
+	ILL_CLEANUP_IF (rval);
+
+	QSlog("Total Number of Nodes: %d", minf.totalnodes);
+	QSlog("Total Number of Pivots: %d", minf.totalpivots);
+	QSlog("BFS MIP Runing Time: %.2f seconds", ILLutil_zeit () - szeit);
+
+	EGLPNUM_TYPENAME_EGlpNumCopy (*val, minf.value);
+	if (minf.objsense == EGLPNUM_TYPENAME_ILL_MAX)
+		EGLPNUM_TYPENAME_EGlpNumSign (*val);
+
+	if (x && EGLPNUM_TYPENAME_EGlpNumIsNeqq (minf.value, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+	{
+		copy_x (lp->O->nstruct, minf.bestx, x);
+	}
+
+CLEANUP:
+
+	if (minf.que)
+	{
+		EGLPNUM_TYPENAME_ILLutil_priority_free (minf.que);
+		ILL_IFFREE (minf.que, EGLPNUM_TYPENAME_ILLpriority);
+	}
+	cleanup_mip (&minf);
+	free_mipinfo (&minf);
+	EGLPNUM_TYPENAME_ILLprice_free_pricing_info (&pinf);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (lpval);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (pinf.htrigger);
+	ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLmip_bfs");
+}
+
+static int startup_mip (
+	mipinfo * minf,
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * pinf,
+	EGLPNUM_TYPE * lpval,
+	itcnt_t*itcnt)
+{
+	int rval = 0;
+	int i, col, status, intcount = 0;
+	EGLPNUM_TYPE val;
+	EGLPNUM_TYPENAME_ILLlpdata *qlp;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (val);
+
+	choose_initial_price (pinf);
+
+	qlp = lp->O;
+
+	rval = EGLPNUM_TYPENAME_ILLlib_optimize (lp, 0, pinf, DUAL_SIMPLEX, &status, 0, itcnt);
+	ILL_CLEANUP_IF (rval);
+
+	minf->totalpivots += EGLPNUM_TYPENAME_ILLlib_iter (lp);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_objval (lp, 0, &val);
+	ILL_CLEANUP_IF (rval);
+
+	QSlog("LP Value: %.6f", EGLPNUM_TYPENAME_EGlpNumToLf (val));
+	if (lpval)
+		EGLPNUM_TYPENAME_EGlpNumCopy (*lpval, val);
+
+	if (qlp->intmarker)
+	{
+		for (i = 0; i < qlp->nstruct; i++)
+		{
+			if (qlp->intmarker[i])
+			{
+				col = qlp->structmap[i];
+				intcount++;
+				if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (qlp->lower[col], EGLPNUM_TYPENAME_ILL_MINDOUBLE)
+						|| EGLPNUM_TYPENAME_EGlpNumIsEqqual (qlp->upper[col], EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+				{
+					QSlog("Instance has unbounded integer variable");
+					rval = 1;
+					goto CLEANUP;
+				}
+			}
+		}
+	}
+
+	if (intcount == 0)
+	{
+		QSlog("No integer variables");
+		rval = 1;
+		goto CLEANUP;
+	}
+	else
+	{
+		QSlog("%d integer variables", intcount);
+	}
+
+	if (qlp->sinfo)
+	{															/* Free the presolve LP and work with orginal */
+		EGLPNUM_TYPENAME_ILLlp_sinfo_free (qlp->sinfo);
+		ILL_IFFREE (qlp->sinfo, EGLPNUM_TYPENAME_ILLlp_sinfo);
+	}
+
+
+	minf->lp = lp;
+	minf->pinf = pinf;
+	minf->objsense = qlp->objsense;
+	if (qlp->objsense == EGLPNUM_TYPENAME_ILL_MAX)
+	{															/* MIP codes work with min */
+		for (i = 0; i < lp->ncols; i++)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopyNeg (qlp->obj[i], qlp->obj[i]);
+		}
+		qlp->objsense = EGLPNUM_TYPENAME_ILL_MIN;
+	}
+
+	minf->x = EGLPNUM_TYPENAME_EGlpNumAllocArray (qlp->nstruct);
+	minf->bestx = EGLPNUM_TYPENAME_EGlpNumAllocArray (qlp->nstruct);
+	minf->lower = EGLPNUM_TYPENAME_EGlpNumAllocArray (qlp->nstruct);
+	minf->upper = EGLPNUM_TYPENAME_EGlpNumAllocArray (qlp->nstruct);
+	minf->orig_lower = EGLPNUM_TYPENAME_EGlpNumAllocArray (qlp->nstruct);
+	minf->orig_upper = EGLPNUM_TYPENAME_EGlpNumAllocArray (qlp->nstruct);
+	minf->downpen = EGLPNUM_TYPENAME_EGlpNumAllocArray (qlp->nstruct);
+	minf->uppen = EGLPNUM_TYPENAME_EGlpNumAllocArray (qlp->nstruct);
+	minf->nstruct = qlp->nstruct;
+
+	rval = EGLPNUM_TYPENAME_ILLlib_get_x (lp, 0, minf->x);
+	ILL_CLEANUP_IF (rval);
+
+	for (i = 0; i < qlp->nstruct; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (minf->lower[i], qlp->lower[i]);
+		EGLPNUM_TYPENAME_EGlpNumCopy (minf->upper[i], qlp->upper[i]);
+		EGLPNUM_TYPENAME_EGlpNumCopy (minf->orig_lower[i], qlp->lower[i]);
+		EGLPNUM_TYPENAME_EGlpNumCopy (minf->orig_upper[i], qlp->upper[i]);
+		EGLPNUM_TYPENAME_EGlpNumOne (minf->downpen[i]);
+		EGLPNUM_TYPENAME_EGlpNumOne (minf->uppen[i]);
+		EGLPNUM_TYPENAME_EGlpNumSign (minf->downpen[i]);
+		EGLPNUM_TYPENAME_EGlpNumSign (minf->uppen[i]);
+	}
+
+
+CLEANUP:
+
+	EGLPNUM_TYPENAME_EGlpNumClearVar (val);
+	ILL_RETURN (rval, "startup_mip");
+}
+
+static void cleanup_mip (
+	mipinfo * minf)
+{
+	int i;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp;
+
+	if (minf && minf->lp)
+	{
+		qslp = minf->lp->O;
+		if (minf->objsense == EGLPNUM_TYPENAME_ILL_MAX)
+		{
+			for (i = 0; i < minf->lp->ncols; i++)
+			{
+				EGLPNUM_TYPENAME_EGlpNumSign (qslp->obj[i]);
+			}
+			qslp->objsense = EGLPNUM_TYPENAME_ILL_MIN;
+		}
+	}
+}
+
+static int run_bfs (
+	mipinfo * minf,
+	itcnt_t*itcnt)
+{
+	int rval = 0;
+	bbnode *b;
+
+	while (minf->head_bbnode.next)
+	{
+		best_bbnode (minf, &b);
+		rval = process_bfs_bbnode (minf, b, itcnt);
+		ILL_CLEANUP_IF (rval);
+		remove_bbnode (b);
+		free_bbnode (b);
+		bbnodefree (&minf->ptrworld, b);
+		minf->activenodes--;
+	}
+
+CLEANUP:
+
+	ILL_RETURN (rval, "run_bfs");
+}
+
+static int process_bfs_bbnode (
+	mipinfo * minf,
+	bbnode * active,
+	itcnt_t*itcnt)
+{
+	EGLPNUM_TYPENAME_lpinfo *lp = minf->lp;
+	EGLPNUM_TYPENAME_ILLlp_basis B;
+	int status, bvar = 0;
+	int i, j, hit, dnp = 0, upp = 0;
+	int nstruct = lp->O->nstruct;
+	EGLPNUM_TYPE t, lpval, dnval, upval;
+	EGLPNUM_TYPE *wupper = 0;
+	EGLPNUM_TYPE *wlower = 0;
+	int rval = 0;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (t);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (lpval);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (dnval);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (upval);
+
+	EGLPNUM_TYPENAME_ILLlp_basis_init (&B);
+
+	if (minf->watch > 1)
+	{
+		QSlog("Node %4d: %.3f", active->id, EGLPNUM_TYPENAME_EGlpNumToLf (active->bound));
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (minf->value, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+			QSlog(" %.3f", EGLPNUM_TYPENAME_EGlpNumToLf (minf->value));
+		else
+			QSlog("  None");
+		QSlog(", Active %d ", minf->activenodes);
+	}
+	else if (minf->watch == 1)
+	{
+		if (minf->lastpivots > 1000)
+		{
+			minf->lastpivots = 0;
+			QSlog("Pivots %d, Active Nodes %d, Bound %.3f, Soln ",
+									minf->totalpivots, minf->activenodes,
+									EGLPNUM_TYPENAME_EGlpNumToLf (active->bound));
+			if (!EGLPNUM_TYPENAME_EGlpNumIsLess (minf->value, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+				QSlog("%.3f", EGLPNUM_TYPENAME_EGlpNumToLf (minf->value));
+			else
+				QSlog("None");
+		}
+	}
+
+	if (EGLPNUM_TYPENAME_EGlpNumIsLeq (minf->objectivebound, active->bound))
+	{
+		if (minf->watch > 1)
+		{
+			QSlog("  Node can be purged");
+		}
+		goto CLEANUP;
+	}
+
+	/*  Set the LP bounds for the node. */
+
+	wlower = EGLPNUM_TYPENAME_EGlpNumAllocArray (nstruct);
+	wupper = EGLPNUM_TYPENAME_EGlpNumAllocArray (nstruct);
+
+	for (i = 0; i < nstruct; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (wlower[i], minf->orig_lower[i]);
+		EGLPNUM_TYPENAME_EGlpNumCopy (wupper[i], minf->orig_upper[i]);
+	}
+	for (i = 0; i < active->bound_cnt; i++)
+	{
+		j = active->bound_indx[i];
+		if (active->lu[i] == 'L')
+			EGLPNUM_TYPENAME_EGlpNumCopy (wlower[j], active->bounds[i]);
+		else
+			EGLPNUM_TYPENAME_EGlpNumCopy (wupper[j], active->bounds[i]);
+	}
+
+	if (active->bound_cnt > 0)
+	{
+		rval = EGLPNUM_TYPENAME_ILLlib_chgbnds (lp, active->bound_cnt, active->bound_indx,
+													 active->lu, active->bounds);
+		ILL_CLEANUP_IF (rval);
+	}
+
+	/*  Solve the LP. */
+
+	rval = EGLPNUM_TYPENAME_ILLlib_loadbasis (&B, nstruct, lp->nrows, active->cstat,
+													 active->rstat);
+	ILL_CLEANUP_IF (rval);
+	if (active->rownorms)
+	{
+		B.rownorms = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+		for (i = 0; i < lp->nrows; i++)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (B.rownorms[i], active->rownorms[i]);
+		}
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLlib_optimize (lp, &B, minf->pinf, DUAL_SIMPLEX, &status, 0, itcnt);
+	ILL_CLEANUP_IF (rval);
+
+	minf->totalpivots += EGLPNUM_TYPENAME_ILLlib_iter (lp);
+	minf->lastpivots += EGLPNUM_TYPENAME_ILLlib_iter (lp);
+
+	if (status == QS_LP_UNSOLVED)
+	{
+		QSlog("Simplex did not solve the LP");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	if (status == QS_LP_INFEASIBLE)
+	{
+		QSlog("  Infeasible LP, should have been purged earlier");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	if (active->depth < 0)
+	{
+		for (i = 0; i < nstruct; i++)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (minf->lower[i], wlower[i]);
+			EGLPNUM_TYPENAME_EGlpNumCopy (minf->upper[i], wupper[i]);
+		}
+		rval = plunge (minf, itcnt);
+		ILL_CLEANUP_IF (rval);
+	}
+
+	/*  Fix variables. */
+
+	if (EGLPNUM_TYPENAME_EGlpNumIsLess (minf->value, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+	{
+		rval = fix_variables (lp, &(minf->value), active, wupper, wlower, &hit);
+		ILL_CLEANUP_IF (rval);
+
+		if (hit)
+		{
+			rval = EGLPNUM_TYPENAME_ILLlib_optimize (lp, &B, minf->pinf, DUAL_SIMPLEX, &status, 0, itcnt);
+			ILL_CLEANUP_IF (rval);
+
+			minf->totalpivots += EGLPNUM_TYPENAME_ILLlib_iter (lp);
+			minf->lastpivots += EGLPNUM_TYPENAME_ILLlib_iter (lp);
+
+			if (status == QS_LP_UNSOLVED)
+			{
+				QSlog("Simplex did not solve the LP");
+				rval = 1;
+				ILL_CLEANUP;
+			}
+
+			if (status == QS_LP_INFEASIBLE)
+			{
+				QSlog("  Infeasible LP after fixing");
+				rval = 1;
+				ILL_CLEANUP;
+			}
+		}
+	}
+
+
+	/*  Branch. */
+
+	rval = EGLPNUM_TYPENAME_ILLlib_get_x (lp, 0, minf->x);
+	ILL_CLEANUP_IF (rval);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_objval (lp, 0, &lpval);
+	ILL_CLEANUP_IF (rval);
+
+	rval = find_branch (minf, minf->x, &lpval, &bvar, itcnt);
+	ILL_CLEANUP_IF (rval);
+
+	if (bvar == -1)
+	{
+		QSlog("Found integral solution: %f", EGLPNUM_TYPENAME_EGlpNumToLf (lpval));
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (lpval, minf->value))
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (minf->value, lpval);
+			EGLPNUM_TYPENAME_EGlpNumCopy (minf->objectivebound, lpval);
+			EGLPNUM_TYPENAME_EGlpNumSubTo (minf->objectivebound, ILL_INTTOL);
+			copy_x (nstruct, minf->x, minf->bestx);
+		}
+	}
+	else
+	{
+		/* Create down child */
+
+		rval = child_work (minf, active, bvar, 'D', &dnval, &dnp, itcnt);
+		ILL_CLEANUP_IF (rval);
+
+		/* Restore parent basis */
+
+		rval = EGLPNUM_TYPENAME_ILLlib_loadbasis (&B, nstruct, lp->nrows, active->cstat,
+														 active->rstat);
+		ILL_CLEANUP_IF (rval);
+		if (active->rownorms)
+		{
+			B.rownorms = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+			for (i = 0; i < lp->nrows; i++)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (B.rownorms[i], active->rownorms[i]);
+			}
+		}
+
+		/* Create up child */
+
+		rval = child_work (minf, active, bvar, 'U', &upval, &upp, itcnt);
+		ILL_CLEANUP_IF (rval);
+
+		if (minf->watch > 1)
+		{
+			if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (dnval, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+			{
+				QSlog("DN->XXX");
+			}
+			else
+			{
+				QSlog("DN->%.3f%c", EGLPNUM_TYPENAME_EGlpNumToLf (dnval), dnp ? 'X' : ' ');
+			}
+			if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (upval, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+			{
+				QSlog("UP->XXX");
+			}
+			else
+			{
+				QSlog("UP->%.3f%c", EGLPNUM_TYPENAME_EGlpNumToLf (upval), upp ? 'X' : ' ');
+			}
+		}
+	}
+
+	/* Set the LP bounds back to original values */
+
+	for (i = 0; i < active->bound_cnt; i++)
+	{
+		if (active->lu[i] == 'L')
+			EGLPNUM_TYPENAME_EGlpNumCopy (t, minf->orig_lower[active->bound_indx[i]]);
+		else
+			EGLPNUM_TYPENAME_EGlpNumCopy (t, minf->orig_upper[active->bound_indx[i]]);
+
+		rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, active->bound_indx[i], active->lu[i], t);
+		ILL_CLEANUP_IF (rval);
+	}
+
+CLEANUP:
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (wlower);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (wupper);
+	EGLPNUM_TYPENAME_ILLlp_basis_free (&B);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (t);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (lpval);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (dnval);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (upval);
+	ILL_RETURN (rval, "process_bfs_bbnode");
+}
+
+static int child_work (
+	mipinfo * minf,
+	bbnode * active,
+	int bvar,
+	int bdir,
+	EGLPNUM_TYPE * cval,
+	int *cp,
+	itcnt_t*itcnt)
+{
+	int tval, rval = 0;
+	int i, status, intsol;
+	EGLPNUM_TYPE t, oldt, lpval;
+	EGLPNUM_TYPE *xi = &(minf->x[bvar]);
+	EGLPNUM_TYPENAME_lpinfo *lp = minf->lp;
+	bbnode *b;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (t);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (lpval);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (oldt);
+
+	*cp = 0;
+
+	if (bdir == 'D')
+	{
+		rval = EGLPNUM_TYPENAME_ILLlib_getbnd (lp, bvar, 'U', &oldt);
+		ILL_CLEANUP_IF (rval);
+		EGLPNUM_TYPENAME_EGlpNumFloor (t, *xi);
+		rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, bvar, 'U', t);
+		ILL_CLEANUP_IF (rval);
+	}
+	else
+	{
+		rval = EGLPNUM_TYPENAME_ILLlib_getbnd (lp, bvar, 'L', &oldt);
+		ILL_CLEANUP_IF (rval);
+		EGLPNUM_TYPENAME_EGlpNumCeil (t, *xi);
+		rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, bvar, 'L', t);
+		ILL_CLEANUP_IF (rval);
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLlib_optimize (lp, 0, minf->pinf, DUAL_SIMPLEX, &status, 0, itcnt);
+	ILL_CLEANUP_IF (rval);
+
+	minf->totalpivots += EGLPNUM_TYPENAME_ILLlib_iter (lp);
+	minf->lastpivots += EGLPNUM_TYPENAME_ILLlib_iter (lp);
+
+	if (status == QS_LP_UNSOLVED)
+	{
+		QSlog("Simplex did not solve Child LP");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	if (status == QS_LP_INFEASIBLE)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (*cval, EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+		*cp = 1;
+	}
+	else
+	{
+		rval = EGLPNUM_TYPENAME_ILLlib_objval (lp, 0, &lpval);
+		ILL_CLEANUP_IF (rval);
+		EGLPNUM_TYPENAME_EGlpNumCopy (*cval, lpval);
+
+		/* What about the x vector?  Bico - 020531 */
+
+		check_integral (lp, minf->x, &intsol);
+		if (intsol)
+		{
+			if (EGLPNUM_TYPENAME_EGlpNumIsLess (lpval, minf->value))
+			{
+				QSlog("Found integral solution: %f", EGLPNUM_TYPENAME_EGlpNumToLf (lpval));
+				EGLPNUM_TYPENAME_EGlpNumCopy (minf->value, lpval);
+				EGLPNUM_TYPENAME_EGlpNumCopy (minf->objectivebound, lpval);
+				EGLPNUM_TYPENAME_EGlpNumSubTo (minf->objectivebound, ILL_INTTOL);
+				copy_x (lp->O->nstruct, minf->x, minf->bestx);
+			}
+		}
+
+		if (EGLPNUM_TYPENAME_EGlpNumIsLeq (minf->objectivebound, lpval))
+		{
+			*cp = 1;
+		}
+		else
+		{
+			b = bbnodealloc (&minf->ptrworld);
+			init_bbnode (b);
+			b->depth = active->depth + 1;
+			b->id = minf->totalnodes;
+			EGLPNUM_TYPENAME_EGlpNumCopy (b->bound, lpval);
+			ILL_SAFE_MALLOC (b->cstat, lp->O->nstruct, char);
+			ILL_SAFE_MALLOC (b->rstat, lp->nrows, char);
+
+			rval = EGLPNUM_TYPENAME_ILLlib_getbasis (lp, b->cstat, b->rstat);
+			ILL_CLEANUP_IF (rval);
+			if (minf->pinf->dII_price == QS_PRICE_DSTEEP)
+			{
+				b->rownorms = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+				tval = EGLPNUM_TYPENAME_ILLlib_getrownorms (lp, minf->pinf, b->rownorms);
+				if (tval)
+				{
+					QSlog("Row norms not available");
+					QSlog("A");
+					exit (1);
+					EGLPNUM_TYPENAME_EGlpNumFreeArray (b->rownorms);
+				}
+			}
+			ILL_SAFE_MALLOC (b->bound_indx, active->bound_cnt + 1, int);
+			ILL_SAFE_MALLOC (b->lu, active->bound_cnt + 1, char);
+
+			b->bounds = EGLPNUM_TYPENAME_EGlpNumAllocArray (active->bound_cnt + 1);
+			for (i = 0; i < active->bound_cnt; i++)
+			{
+				b->bound_indx[i] = active->bound_indx[i];
+				b->lu[i] = active->lu[i];
+				EGLPNUM_TYPENAME_EGlpNumCopy (b->bounds[i], active->bounds[i]);
+			}
+			b->bound_indx[active->bound_cnt] = bvar;
+			if (bdir == 'D')
+				b->lu[active->bound_cnt] = 'U';
+			else
+				b->lu[active->bound_cnt] = 'L';
+			EGLPNUM_TYPENAME_EGlpNumCopy (b->bounds[active->bound_cnt], t);
+			b->bound_cnt = active->bound_cnt + 1;
+
+			rval = EGLPNUM_TYPENAME_ILLutil_priority_insert (minf->que, (void *) b, &lpval,
+																			&(b->handle));
+			ILL_CLEANUP_IF (rval);
+
+			put_bbnode (minf, b);
+			minf->activenodes++;
+		}
+	}
+	minf->totalnodes++;
+
+	if (bdir == 'D')
+	{
+		rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, bvar, 'U', oldt);
+		ILL_CLEANUP_IF (rval);
+	}
+	else
+	{
+		rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, bvar, 'L', oldt);
+		ILL_CLEANUP_IF (rval);
+	}
+
+CLEANUP:
+
+	EGLPNUM_TYPENAME_EGlpNumClearVar (t);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (lpval);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (oldt);
+	return rval;
+}
+
+static int fix_variables (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPE * bestval,
+	bbnode * b,
+	EGLPNUM_TYPE * wupper,
+	EGLPNUM_TYPE * wlower,
+	int *hit)
+{
+	int rval = 0;
+	int i, nnew = 0;
+	int nstruct = lp->O->nstruct;
+	EGLPNUM_TYPE delta, lpval;
+	int *new_indx = 0;
+	char *new_lu = 0;
+	EGLPNUM_TYPE *new_bounds = 0;
+	EGLPNUM_TYPE *dj = 0;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (delta);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (lpval);
+
+	*hit = 0;
+
+	if (EGLPNUM_TYPENAME_EGlpNumIsLess (*bestval, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+	{
+		rval = EGLPNUM_TYPENAME_ILLlib_objval (lp, 0, &lpval);
+		ILL_CLEANUP_IF (rval);
+		//delta = bestval - lpval + ILL_INTTOL;
+		EGLPNUM_TYPENAME_EGlpNumCopy (delta, *bestval);
+		EGLPNUM_TYPENAME_EGlpNumSubTo (delta, lpval);
+		EGLPNUM_TYPENAME_EGlpNumAddTo (delta, ILL_INTTOL);
+
+		ILL_SAFE_MALLOC (new_indx, nstruct, int);
+		ILL_SAFE_MALLOC (new_lu, nstruct, char);
+
+		dj = EGLPNUM_TYPENAME_EGlpNumAllocArray (nstruct);
+		new_bounds = EGLPNUM_TYPENAME_EGlpNumAllocArray (nstruct);
+
+		rval = EGLPNUM_TYPENAME_ILLlib_solution (lp, 0, 0, 0, 0, 0, dj);
+		ILL_CLEANUP_IF (rval);
+
+		for (i = 0; i < nstruct; i++)
+		{
+			if (lp->O->intmarker[i])
+			{
+				if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (wlower[i], wupper[i]))
+				{
+					if (EGLPNUM_TYPENAME_EGlpNumIsLess (delta, dj[i]))
+					{
+						EGLPNUM_TYPENAME_EGlpNumSubTo (wupper[i], EGLPNUM_TYPENAME_oneLpNum);
+						rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, i, 'U', wupper[i]);
+						ILL_CLEANUP_IF (rval);
+						new_indx[nnew] = i;
+						new_lu[nnew] = 'U';
+						EGLPNUM_TYPENAME_EGlpNumCopy (new_bounds[nnew], wupper[i]);
+						nnew++;
+					}
+					/*if (-dj[i] > delta) */
+					EGLPNUM_TYPENAME_EGlpNumSign (delta);
+					if (EGLPNUM_TYPENAME_EGlpNumIsLess (delta, dj[i]))
+					{
+						EGLPNUM_TYPENAME_EGlpNumAddTo (wlower[i], EGLPNUM_TYPENAME_oneLpNum);
+						rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, i, 'L', wlower[i]);
+						ILL_CLEANUP_IF (rval);
+						new_indx[nnew] = i;
+						new_lu[nnew] = 'L';
+						EGLPNUM_TYPENAME_EGlpNumCopy (new_bounds[nnew], wlower[i]);
+						nnew++;
+					}
+					EGLPNUM_TYPENAME_EGlpNumSign (delta);
+				}
+			}
+		}
+
+		if (nnew)
+		{
+			b->bound_indx =
+				EGrealloc (b->bound_indx, sizeof (int) * (b->bound_cnt + nnew));
+			//rval = ILLutil_reallocrus_count ((void **) &(b->bound_indx),
+			//                                 b->bound_cnt + nnew, sizeof (int));
+			//ILL_CLEANUP_IF (rval);
+			b->lu = EGrealloc (b->lu, sizeof (char) * (b->bound_cnt + nnew));
+			//rval = ILLutil_reallocrus_count ((void **) &(b->lu),
+			//                                 b->bound_cnt + nnew, sizeof (char));
+			//ILL_CLEANUP_IF (rval);
+			EGLPNUM_TYPENAME_EGlpNumReallocArray (&(b->bounds), b->bound_cnt + nnew);
+			for (i = 0; i < nnew; i++)
+			{
+				b->bound_indx[b->bound_cnt + i] = new_indx[i];
+				b->lu[b->bound_cnt + i] = new_lu[i];
+				EGLPNUM_TYPENAME_EGlpNumCopy (b->bounds[b->bound_cnt + i], new_bounds[i]);
+			}
+			b->bound_cnt += nnew;
+		}
+	}
+
+	*hit = nnew;
+
+CLEANUP:
+
+	ILL_IFFREE (new_indx, int);
+	ILL_IFFREE (new_lu, char);
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (dj);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (new_bounds);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (delta);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (lpval);
+	return rval;
+}
+
+static void best_bbnode (
+	mipinfo * minf,
+	bbnode ** best)
+{
+#if 0
+	bbnode *b;
+	double bestval = EGLPNUM_TYPENAME_ILL_MAXDOUBLE;
+
+	for (b = minf->head_bbnode.next; b; b = b->next)
+	{
+		if (b->bound < bestval)
+		{
+			*best = b;
+			bestval = b->bound;
+		}
+	}
+#endif
+
+	EGLPNUM_TYPE val;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (val);
+	EGLPNUM_TYPENAME_ILLutil_priority_deletemin (minf->que, &val, (void **) best);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (val);
+}
+
+static void put_bbnode (
+	mipinfo * minf,
+	bbnode * b)
+{
+	b->next = minf->head_bbnode.next;
+	b->prev = &(minf->head_bbnode);
+	if (b->next)
+		b->next->prev = b;
+	minf->head_bbnode.next = b;
+}
+
+static void remove_bbnode (
+	bbnode * b)
+{
+	b->prev->next = b->next;
+	if (b->next)
+		b->next->prev = b->prev;
+}
+
+static int find_branch (
+	mipinfo * minf,
+	EGLPNUM_TYPE * x,
+	EGLPNUM_TYPE * lpval,
+	int *bvar,
+	itcnt_t*itcnt)
+{
+	EGLPNUM_TYPENAME_lpinfo *lp = minf->lp;
+	int rval = 0;
+
+	switch (minf->branching_rule)
+	{
+	case PENALTYBRANCH:
+		rval = find_penalty_branch (lp, minf->pinf, x, minf->downpen,
+																minf->uppen, lpval, bvar, itcnt);
+		ILL_CLEANUP_IF (rval);
+		break;
+	case FIRSTBRANCH:
+		find_first_branch (lp, x, bvar);
+		break;
+	case MIDDLEBRANCH:
+		find_middle_branch (lp, x, bvar);
+		break;
+	case STRONGBRANCH:
+		rval = find_strong_branch (lp, minf->pinf, x, bvar, itcnt);
+		ILL_CLEANUP_IF (rval);
+		break;
+	default:
+		QSlog("Unknown branching rule.");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+CLEANUP:
+
+	ILL_RETURN (rval, "find_branch");
+}
+
+static void find_first_branch (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPE * x,
+	int *bvar)
+{
+	int i, ibest = -1;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp = lp->O;
+	EGLPNUM_TYPE t;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (t);
+
+	for (i = 0; i < qslp->nstruct; i++)
+	{
+		if (qslp->intmarker[i])
+		{
+			/*t = EGLPNUM_TYPENAME_ILLutil_our_frac (x[i]); */
+			EGLPNUM_TYPENAME_EGlpNumFloor (t, x[i]);
+			EGLPNUM_TYPENAME_EGlpNumSubTo (t, x[i]);
+			EGLPNUM_TYPENAME_EGlpNumSign (t);
+			if ((EGLPNUM_TYPENAME_EGlpNumIsNeqZero (t, ILL_INTTOL)) &&
+					(EGLPNUM_TYPENAME_EGlpNumIsNeq (t, EGLPNUM_TYPENAME_oneLpNum, ILL_INTTOL)))
+			{
+				ibest = i;
+				break;
+			}
+		}
+	}
+	*bvar = ibest;
+	EGLPNUM_TYPENAME_EGlpNumClearVar (t);
+}
+
+static void find_middle_branch (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPE * x,
+	int *bvar)
+{
+	int i, ibest = -1;
+	EGLPNUM_TYPE t, tbest;
+	EGLPNUM_TYPENAME_ILLlpdata *qlp = lp->O;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (t);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (tbest);
+	EGLPNUM_TYPENAME_EGlpNumSet (tbest, 0.5);
+
+	for (i = 0; i < qlp->nstruct; i++)
+	{
+		if (qlp->intmarker[i])
+		{
+			/*t = EGLPNUM_TYPENAME_ILLutil_our_frac (x[i]) - 0.5;
+			 * if (t < 0.0)
+			 * t = -t; */
+			EGLPNUM_TYPENAME_EGlpNumFloor (t, x[i]);
+			EGLPNUM_TYPENAME_EGlpNumMultUiTo (t, 2);
+			EGLPNUM_TYPENAME_EGlpNumSubTo (t, EGLPNUM_TYPENAME_oneLpNum);
+			EGLPNUM_TYPENAME_EGlpNumDivUiTo (t, 2);
+			if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (t))
+				EGLPNUM_TYPENAME_EGlpNumSign (t);
+			/*if (t < tbest) */
+			if (EGLPNUM_TYPENAME_EGlpNumIsLess (t, tbest))
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (tbest, t);
+				ibest = i;
+			}
+		}
+	}
+
+	/*if (tbest < (0.5 - ILL_INTTOL)) */
+	EGLPNUM_TYPENAME_EGlpNumAddTo (tbest, ILL_INTTOL);
+	if (EGLPNUM_TYPENAME_EGlpNumIsLessDbl (tbest, 0.5))
+	{
+		*bvar = ibest;
+	}
+	else
+	{
+		*bvar = -1;
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (t);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (tbest);
+}
+
+static int find_penalty_branch (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * pinf,
+	EGLPNUM_TYPE * x,
+	EGLPNUM_TYPE * downpen,
+	EGLPNUM_TYPE * uppen,
+	EGLPNUM_TYPE * lpval,
+	int *bvar,
+	itcnt_t*itcnt)
+{
+	int rval = 0;
+	int i, k, ibest = -1, ncand = 0, nneed = 0;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp = lp->O;
+	int *candidatelist = 0;
+	int *needlist = 0;
+	EGLPNUM_TYPE *fval = 0;
+	EGLPNUM_TYPE *xlist = 0;
+	EGLPNUM_TYPE *newdown = 0;
+	EGLPNUM_TYPE *newup = 0;
+	EGLPNUM_TYPE a, t, tbest;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (a);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (t);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (tbest);
+	EGLPNUM_TYPENAME_EGlpNumCopy (tbest, EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+
+	ILL_SAFE_MALLOC (candidatelist, qslp->nstruct, int);
+	ILL_SAFE_MALLOC (needlist, qslp->nstruct, int);
+
+	fval = EGLPNUM_TYPENAME_EGlpNumAllocArray (qslp->nstruct);
+	xlist = EGLPNUM_TYPENAME_EGlpNumAllocArray (qslp->nstruct);
+	for (i = 0; i < qslp->nstruct; i++)
+	{
+		if (qslp->intmarker[i])
+		{
+			/*fval[i] = x[i] - floor(x[i]); */
+			EGLPNUM_TYPENAME_EGlpNumFloor (fval[i], x[i]);
+			EGLPNUM_TYPENAME_EGlpNumSubTo (fval[i], x[i]);
+			EGLPNUM_TYPENAME_EGlpNumSign (fval[i]);
+			if ((EGLPNUM_TYPENAME_EGlpNumIsNeqZero (fval[i], ILL_INTTOL)) &&
+					(EGLPNUM_TYPENAME_EGlpNumIsNeq (fval[i], EGLPNUM_TYPENAME_oneLpNum, ILL_INTTOL)))
+			{
+				candidatelist[ncand++] = i;
+				/*if (downpen[i] == -1.0) */
+				EGLPNUM_TYPENAME_EGlpNumSign (downpen[i]);
+				if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (downpen[i], EGLPNUM_TYPENAME_oneLpNum))
+				{
+					EGLPNUM_TYPENAME_EGlpNumCopy (xlist[nneed], x[i]);
+					needlist[nneed++] = i;
+				}
+				EGLPNUM_TYPENAME_EGlpNumSign (downpen[i]);
+			}
+		}
+	}
+
+	if (nneed > 0)
+	{
+		newdown = EGLPNUM_TYPENAME_EGlpNumAllocArray (nneed);
+		newup = EGLPNUM_TYPENAME_EGlpNumAllocArray (nneed);
+		rval = EGLPNUM_TYPENAME_ILLlib_strongbranch (lp, pinf, needlist, nneed,
+																0, newdown, newup,
+																5 * STRONG_PIVOTS, EGLPNUM_TYPENAME_ILL_MAXDOUBLE, itcnt);
+		ILL_CLEANUP_IF (rval);
+
+		for (i = 0; i < nneed; i++)
+		{
+			k = needlist[i];
+			/*uppen[k] = (newup[i] - lpval) / (1.0 - fval[k]); */
+			EGLPNUM_TYPENAME_EGlpNumCopyDiff (uppen[k], newup[i], *lpval);
+			EGLPNUM_TYPENAME_EGlpNumCopyDiff (downpen[k], EGLPNUM_TYPENAME_oneLpNum, fval[k]);
+			EGLPNUM_TYPENAME_EGlpNumDivTo (uppen[k], downpen[k]);
+			/*downpen[k] = (newdown[i] - lpval) / fval[k]; */
+			EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (downpen[k], newdown[i], *lpval, fval[k]);
+
+		}
+	}
+
+	for (i = 0; i < ncand; i++)
+	{
+		k = candidatelist[i];
+		/*t = ILL_BRANCH_PENALTY_VAL (downpen[k], uppen[k], fval[k]); */
+		EGLPNUM_TYPENAME_EGlpNumCopy (t, downpen[k]);
+		EGLPNUM_TYPENAME_EGlpNumMultTo (t, fval[k]);
+		EGLPNUM_TYPENAME_EGlpNumCopyDiff (a, EGLPNUM_TYPENAME_oneLpNum, fval[k]);
+		EGLPNUM_TYPENAME_EGlpNumMultTo (a, uppen[k]);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (t, a))
+		{
+			EGLPNUM_TYPENAME_EGlpNumMultUiTo (t, ILL_BRANCH_PENALTY_WEIGHT);
+			EGLPNUM_TYPENAME_EGlpNumAddTo (t, a);
+		}
+		else
+		{
+			EGLPNUM_TYPENAME_EGlpNumMultUiTo (a, ILL_BRANCH_PENALTY_WEIGHT);
+			EGLPNUM_TYPENAME_EGlpNumAddTo (t, a);
+		}
+		EGLPNUM_TYPENAME_EGlpNumDivUiTo (t, ILL_BRANCH_PENALTY_WEIGHT + 1);
+
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (tbest, t))
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (tbest, t);
+			ibest = k;
+		}
+	}
+
+	*bvar = ibest;
+
+CLEANUP:
+
+	EGLPNUM_TYPENAME_EGlpNumClearVar (a);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (t);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (tbest);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (newdown);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (newup);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (fval);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (xlist);
+	ILL_IFFREE (candidatelist, int);
+	ILL_IFFREE (needlist, int);
+
+	return rval;
+}
+
+static int find_strong_branch (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * pinf,
+	EGLPNUM_TYPE * x,
+	int *bvar,
+	itcnt_t*itcnt)
+{
+	int rval = 0;
+	int i, ibest = -1, ncand = 0;
+	int maxtrys = STRONG_CANDIDATES;
+	EGLPNUM_TYPE t, tbest;
+	EGLPNUM_TYPENAME_ILLlpdata *qlp = lp->O;
+	int *candidatelist = 0;
+	int *newlist = 0;
+	int *perm = 0;
+	EGLPNUM_TYPE *tval = 0;
+	EGLPNUM_TYPE *xlist = 0;
+	EGLPNUM_TYPE *downpen = 0;
+	EGLPNUM_TYPE *uppen = 0;
+	ILLrandstate rstate;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (t);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (tbest);
+	EGLPNUM_TYPENAME_EGlpNumCopy (tbest, EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+
+	ILLutil_sprand (999, &rstate);
+	ILL_SAFE_MALLOC (candidatelist, qlp->nstruct, int);
+
+	tval = EGLPNUM_TYPENAME_EGlpNumAllocArray (qlp->nstruct);
+
+	for (i = 0; i < qlp->nstruct; i++)
+	{
+		if (qlp->intmarker[i])
+		{
+			/*t = EGLPNUM_TYPENAME_ILLutil_our_frac (x[i]) - 0.5;
+			 * if (t < 0.0)
+			 * t = -t; */
+			EGLPNUM_TYPENAME_EGlpNumFloor (t, x[i]);
+			EGLPNUM_TYPENAME_EGlpNumSubTo (t, x[i]);
+			EGLPNUM_TYPENAME_EGlpNumSign (t);
+			EGLPNUM_TYPENAME_EGlpNumMultUiTo (t, 2);
+			EGLPNUM_TYPENAME_EGlpNumSubTo (t, EGLPNUM_TYPENAME_oneLpNum);
+			if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (t))
+				EGLPNUM_TYPENAME_EGlpNumSign (t);
+			/*if (t < (0.5 - ILL_INTTOL)) */
+			if (EGLPNUM_TYPENAME_EGlpNumIsNeq (t, EGLPNUM_TYPENAME_oneLpNum, ILL_INTTOL))
+			{
+				candidatelist[ncand] = i;
+				EGLPNUM_TYPENAME_EGlpNumDivUiTo (t, 2);
+				EGLPNUM_TYPENAME_EGlpNumCopy (tval[ncand++], t);
+			}
+		}
+	}
+
+	if (ncand > 0)
+	{
+		if (ncand > maxtrys)
+		{
+			ILL_SAFE_MALLOC (perm, ncand, int);
+
+			for (i = 0; i < ncand; i++)
+			{
+				perm[i] = i;
+			}
+			EGLPNUM_TYPENAME_ILLutil_EGlpNum_rselect (perm, 0, ncand - 1, maxtrys, tval, &rstate);
+
+			ILL_SAFE_MALLOC (newlist, maxtrys, int);
+
+			for (i = 0; i < maxtrys; i++)
+			{
+				newlist[i] = candidatelist[perm[i]];
+			}
+			ILL_IFFREE (candidatelist, int);
+
+			candidatelist = newlist;
+			newlist = 0;
+			ncand = maxtrys;
+		}
+
+		downpen = EGLPNUM_TYPENAME_EGlpNumAllocArray (ncand);
+		uppen = EGLPNUM_TYPENAME_EGlpNumAllocArray (ncand);
+		xlist = EGLPNUM_TYPENAME_EGlpNumAllocArray (ncand);
+
+		for (i = 0; i < ncand; i++)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (xlist[i], x[candidatelist[i]]);
+		}
+
+		rval = EGLPNUM_TYPENAME_ILLlib_strongbranch (lp, pinf, candidatelist, ncand,
+																0, downpen, uppen, STRONG_PIVOTS,
+																EGLPNUM_TYPENAME_ILL_MAXDOUBLE, itcnt);
+		ILL_CLEANUP_IF (rval);
+
+		for (i = 0; i < ncand; i++)
+		{
+			/*t = ILL_BRANCH_STRONG_VAL (downpen[i], uppen[i]); */
+			if (EGLPNUM_TYPENAME_EGlpNumIsLess (downpen[i], uppen[i]))
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (t, downpen[i]);
+				EGLPNUM_TYPENAME_EGlpNumMultUiTo (t, ILL_BRANCH_STRONG_WEIGHT);
+				EGLPNUM_TYPENAME_EGlpNumAddTo (t, uppen[i]);
+			}
+			else
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (t, uppen[i]);
+				EGLPNUM_TYPENAME_EGlpNumMultUiTo (t, ILL_BRANCH_STRONG_WEIGHT);
+				EGLPNUM_TYPENAME_EGlpNumAddTo (t, downpen[i]);
+			}
+			EGLPNUM_TYPENAME_EGlpNumDivUiTo (t, ILL_BRANCH_STRONG_WEIGHT + 1);
+			if (EGLPNUM_TYPENAME_EGlpNumIsLess (tbest, t))
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (tbest, t);
+				ibest = candidatelist[i];
+			}
+		}
+	}
+
+	*bvar = ibest;
+
+
+CLEANUP:
+
+	EGLPNUM_TYPENAME_EGlpNumClearVar (t);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (tbest);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (tval);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (xlist);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (uppen);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (downpen);
+	ILL_IFFREE (candidatelist, int);
+	ILL_IFFREE (newlist, int);
+	ILL_IFFREE (perm, int);
+
+	ILL_RETURN (rval, "find_strong_branch");
+}
+
+static void check_integral (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPE * x,
+	int *yesno)
+{
+	int i;
+	EGLPNUM_TYPE t;
+	EGLPNUM_TYPENAME_ILLlpdata *qlp = lp->O;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (t);
+
+	for (i = 0; i < qlp->nstruct; i++)
+	{
+		if (qlp->intmarker[i])
+		{
+			/*t = EGLPNUM_TYPENAME_ILLutil_our_frac (x[i]); */
+			EGLPNUM_TYPENAME_EGlpNumFloor (t, x[i]);
+			EGLPNUM_TYPENAME_EGlpNumSubTo (t, x[i]);
+			EGLPNUM_TYPENAME_EGlpNumSign (t);
+			/*if (t > ILL_INTTOL && t < 1.0 - ILL_INTTOL) */
+			if ((EGLPNUM_TYPENAME_EGlpNumIsNeqZero (t, ILL_INTTOL)) &&
+					(EGLPNUM_TYPENAME_EGlpNumIsNeq (t, EGLPNUM_TYPENAME_oneLpNum, ILL_INTTOL)))
+			{
+				*yesno = 0;
+				EGLPNUM_TYPENAME_EGlpNumClearVar (t);
+				return;
+			}
+		}
+	}
+
+	*yesno = 1;
+	EGLPNUM_TYPENAME_EGlpNumClearVar (t);
+}
+
+static int plunge (
+	mipinfo * minf,
+	itcnt_t*itcnt)
+{
+	int rval = 0;
+	int i, status;
+	EGLPNUM_TYPENAME_lpinfo *lp = minf->lp;
+	EGLPNUM_TYPENAME_ILLlpdata *qlp = minf->lp->O;
+	EGLPNUM_TYPE *oldlower = 0;
+	EGLPNUM_TYPE *oldupper = 0;
+
+	if (minf->watch)
+	{
+		QSlog("Plunging ...");
+	}
+
+	oldlower = EGLPNUM_TYPENAME_EGlpNumAllocArray (qlp->nstruct);
+	oldupper = EGLPNUM_TYPENAME_EGlpNumAllocArray (qlp->nstruct);
+
+	for (i = 0; i < qlp->nstruct; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (oldlower[i], minf->lower[i]);
+		EGLPNUM_TYPENAME_EGlpNumCopy (oldupper[i], minf->upper[i]);
+	}
+
+	rval = plunge_work (minf, 0, itcnt);
+	ILL_CLEANUP_IF (rval);
+
+	for (i = 0; i < qlp->nstruct; i++)
+	{
+		rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, i, 'L', oldlower[i]);
+		ILL_CLEANUP_IF (rval);
+		rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, i, 'U', oldupper[i]);
+		ILL_CLEANUP_IF (rval);
+		EGLPNUM_TYPENAME_EGlpNumCopy (minf->lower[i], oldlower[i]);
+		EGLPNUM_TYPENAME_EGlpNumCopy (minf->upper[i], oldupper[i]);
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLlib_optimize (lp, 0, minf->pinf, DUAL_SIMPLEX, &status, 0, itcnt);
+	ILL_CLEANUP_IF (rval);
+
+
+CLEANUP:
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (oldlower);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (oldupper);
+
+	ILL_RETURN (rval, "plunge");
+}
+
+static int plunge_work (
+	mipinfo * minf,
+	int depth,
+	itcnt_t*itcnt)
+{
+	int rval = 0;
+	int bvar, status, count;
+	EGLPNUM_TYPE lpval, val0, val1, int_tol;
+	EGLPNUM_TYPENAME_lpinfo *lp = minf->lp;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (lpval);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (val0);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (val1);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (int_tol);
+	EGLPNUM_TYPENAME_EGlpNumSet (int_tol, 0.001);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_get_x (lp, 0, minf->x);
+	ILL_CLEANUP_IF (rval);
+
+	rval = round_variables (minf, &count, &int_tol /* 0.001 */ );
+	ILL_CLEANUP_IF (rval);
+	if (count)
+	{
+		rval = EGLPNUM_TYPENAME_ILLlib_optimize (lp, 0, minf->pinf, DUAL_SIMPLEX, &status, 0, itcnt);
+		ILL_CLEANUP_IF (rval);
+		if (status != QS_LP_OPTIMAL)
+		{
+			goto CLEANUP;
+		}
+		rval = EGLPNUM_TYPENAME_ILLlib_get_x (lp, 0, minf->x);
+		ILL_CLEANUP_IF (rval);
+	}
+
+	find_middle_branch (lp, minf->x, &bvar);
+	if (bvar == -1)
+	{
+		rval = EGLPNUM_TYPENAME_ILLlib_objval (lp, 0, &lpval);
+		ILL_CLEANUP_IF (rval);
+
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (lpval, minf->value))
+		{
+			QSlog("Plunge Integral Solution: %.6f (Depth: %d)",
+									EGLPNUM_TYPENAME_EGlpNumToLf (lpval), depth);
+
+			EGLPNUM_TYPENAME_EGlpNumCopy (minf->value, lpval);
+			EGLPNUM_TYPENAME_EGlpNumCopyDiff (minf->objectivebound, lpval, ILL_INTTOL);
+			copy_x (lp->O->nstruct, minf->x, minf->bestx);
+		}
+		goto CLEANUP;
+	}
+
+	EGLPNUM_TYPENAME_EGlpNumOne (minf->lower[bvar]);
+	rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, bvar, 'L', EGLPNUM_TYPENAME_oneLpNum);
+	ILL_CLEANUP_IF (rval);
+	rval = EGLPNUM_TYPENAME_ILLlib_optimize (lp, 0, minf->pinf, DUAL_SIMPLEX, &status, 0, itcnt);
+	ILL_CLEANUP_IF (rval);
+
+	if (status == QS_LP_UNSOLVED)
+	{
+		QSlog("Simplex did not solve the plunge LP");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+	else if (status == QS_LP_INFEASIBLE)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (val1, EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+	}
+	else if (status == QS_LP_OPTIMAL)
+	{
+		rval = EGLPNUM_TYPENAME_ILLlib_objval (lp, 0, &val1);
+		ILL_CLEANUP_IF (rval);
+	}
+	else
+	{
+		ILL_CLEANUP;
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, bvar, 'L', EGLPNUM_TYPENAME_zeroLpNum);
+	ILL_CLEANUP_IF (rval);
+	EGLPNUM_TYPENAME_EGlpNumZero (minf->lower[bvar]);
+
+	EGLPNUM_TYPENAME_EGlpNumZero (minf->upper[bvar]);
+	rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, bvar, 'U', EGLPNUM_TYPENAME_zeroLpNum);
+	ILL_CLEANUP_IF (rval);
+	rval = EGLPNUM_TYPENAME_ILLlib_optimize (lp, 0, minf->pinf, DUAL_SIMPLEX, &status, 0, itcnt);
+	ILL_CLEANUP_IF (rval);
+
+	if (status == QS_LP_UNSOLVED)
+	{
+		QSlog("Simplex did not solve the plunge LP");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+	else if (status == QS_LP_INFEASIBLE)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (val0, EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+	}
+	else if (status == QS_LP_OPTIMAL)
+	{
+		rval = EGLPNUM_TYPENAME_ILLlib_objval (lp, 0, &val0);
+		ILL_CLEANUP_IF (rval);
+	}
+	else
+	{
+		ILL_CLEANUP;
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, bvar, 'U', EGLPNUM_TYPENAME_oneLpNum);
+	ILL_CLEANUP_IF (rval);
+	EGLPNUM_TYPENAME_EGlpNumCopy (minf->upper[bvar], EGLPNUM_TYPENAME_oneLpNum);
+
+	if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (val0, EGLPNUM_TYPENAME_ILL_MAXDOUBLE) &&
+			EGLPNUM_TYPENAME_EGlpNumIsEqqual (val1, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+	{
+		ILL_CLEANUP;
+	}
+
+	if (EGLPNUM_TYPENAME_EGlpNumIsLess (val0, val1))
+	{
+		EGLPNUM_TYPENAME_EGlpNumZero (minf->upper[bvar]);
+		rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, bvar, 'U', EGLPNUM_TYPENAME_zeroLpNum);
+		ILL_CLEANUP_IF (rval);
+		rval = EGLPNUM_TYPENAME_ILLlib_optimize (lp, 0, minf->pinf, DUAL_SIMPLEX, &status, 0, itcnt);
+		ILL_CLEANUP_IF (rval);
+		rval = plunge_work (minf, depth + 1, itcnt);
+		ILL_CLEANUP_IF (rval);
+		rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, bvar, 'U', EGLPNUM_TYPENAME_oneLpNum);
+		ILL_CLEANUP_IF (rval);
+		EGLPNUM_TYPENAME_EGlpNumOne (minf->upper[bvar]);
+	}
+	else
+	{
+		EGLPNUM_TYPENAME_EGlpNumOne (minf->lower[bvar]);
+		rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, bvar, 'L', EGLPNUM_TYPENAME_oneLpNum);
+		ILL_CLEANUP_IF (rval);
+		rval = EGLPNUM_TYPENAME_ILLlib_optimize (lp, 0, minf->pinf, DUAL_SIMPLEX, &status, 0, itcnt);
+		ILL_CLEANUP_IF (rval);
+		rval = plunge_work (minf, depth + 1, itcnt);
+		ILL_CLEANUP_IF (rval);
+		rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, bvar, 'L', EGLPNUM_TYPENAME_zeroLpNum);
+		ILL_CLEANUP_IF (rval);
+		EGLPNUM_TYPENAME_EGlpNumZero (minf->lower[bvar]);
+	}
+
+CLEANUP:
+
+	EGLPNUM_TYPENAME_EGlpNumClearVar (lpval);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (val0);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (val1);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (int_tol);
+	ILL_RETURN (rval, "plunge_work");
+}
+
+static int round_variables (
+	mipinfo * minf,
+	int *count,
+	EGLPNUM_TYPE * tol)
+{
+	int rval = 0;
+	int i, hit = 0;
+	EGLPNUM_TYPENAME_lpinfo *lp = minf->lp;
+	EGLPNUM_TYPENAME_ILLlpdata *qlp = lp->O;
+
+	*count = 0;
+
+	for (i = 0; i < qlp->nstruct; i++)
+	{
+		if (qlp->intmarker[i])
+		{
+			if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (minf->lower[i], minf->upper[i]))
+			{
+				if (EGLPNUM_TYPENAME_EGlpNumIsLess (minf->x[i], *tol))
+				{
+					EGLPNUM_TYPENAME_EGlpNumZero (minf->upper[i]);
+					rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, i, 'U', EGLPNUM_TYPENAME_zeroLpNum);
+					ILL_CLEANUP_IF (rval);
+					hit++;
+				}
+				else if (EGLPNUM_TYPENAME_EGlpNumIsEqual (minf->x[i], EGLPNUM_TYPENAME_oneLpNum, *tol))
+				{
+					EGLPNUM_TYPENAME_EGlpNumOne (minf->lower[i]);
+					rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, i, 'L', EGLPNUM_TYPENAME_oneLpNum);
+					ILL_CLEANUP_IF (rval);
+					hit++;
+				}
+			}
+		}
+	}
+	*count = hit;
+
+CLEANUP:
+
+	ILL_RETURN (rval, "round_variables");
+}
+
+static void copy_x (
+	int nstruct,
+	EGLPNUM_TYPE * from_x,
+	EGLPNUM_TYPE * to_x)
+{
+	int j;
+
+	for (j = 0; j < nstruct; j++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (to_x[j], from_x[j]);
+	}
+}
+
+static void init_mipinfo (
+	mipinfo * minf)
+{
+	if (minf)
+	{
+		minf->depth = 0;
+		minf->totalnodes = 0;
+		minf->activenodes = 0;
+		minf->totalpivots = 0;
+		minf->lastpivots = 0;
+		minf->downpen = 0;
+		minf->uppen = 0;
+		minf->x = 0;
+		minf->bestx = 0;
+		minf->lower = 0;
+		minf->upper = 0;
+		minf->lp = 0;
+		minf->pinf = 0;
+		minf->head_bbnode.prev = 0;
+		minf->head_bbnode.next = 0;
+		minf->que = 0;
+		minf->branching_rule = /* MIDDLEBRANCH */ STRONGBRANCH;
+		minf->watch = 1;
+		EGLPNUM_TYPENAME_EGlpNumInitVar (minf->objectivebound);
+		EGLPNUM_TYPENAME_EGlpNumInitVar (minf->value);
+		EGLPNUM_TYPENAME_EGlpNumCopy (minf->objectivebound, EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+		EGLPNUM_TYPENAME_EGlpNumCopy (minf->value, EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+		ILLptrworld_init (&minf->ptrworld);
+	}
+}
+
+static void free_mipinfo (
+	mipinfo * minf)
+{
+	int total, onlist;
+
+	if (minf)
+	{
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (minf->downpen);
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (minf->uppen);
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (minf->x);
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (minf->bestx);
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (minf->lower);
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (minf->upper);
+		bbnode_listfree (&minf->ptrworld, minf->head_bbnode.next);
+		if (bbnode_check_leaks (&minf->ptrworld, &total, &onlist))
+		{
+			QSlog("WARNING: %d outstanding bbnodes", total - onlist);
+		}
+		ILLptrworld_delete (&minf->ptrworld);
+		EGLPNUM_TYPENAME_EGlpNumClearVar ((minf->objectivebound));
+		EGLPNUM_TYPENAME_EGlpNumClearVar ((minf->value));
+		memset (minf, 0, sizeof (mipinfo));
+		//init_mipinfo (minf);
+	}
+}
+
+static void init_bbnode (
+	bbnode * b)
+{
+	if (b)
+	{
+		b->next = 0;
+		b->prev = 0;
+		b->id = 0;
+		b->depth = 0;
+		b->handle = 0;
+		b->cstat = 0;
+		b->rstat = 0;
+		b->rownorms = 0;
+		b->bound_cnt = 0;
+		b->bound_indx = 0;
+		b->lu = 0;
+		b->bounds = 0;
+		EGLPNUM_TYPENAME_EGlpNumInitVar ((b->bound));
+		EGLPNUM_TYPENAME_EGlpNumCopy (b->bound, EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+	}
+}
+
+static void free_bbnode (
+	bbnode * b)
+{
+	if (b)
+	{
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (b->rownorms);
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (b->bounds);
+		ILL_IFFREE (b->cstat, char);
+		ILL_IFFREE (b->rstat, char);
+		ILL_IFFREE (b->bound_indx, int);
+		ILL_IFFREE (b->lu, char);
+
+		EGLPNUM_TYPENAME_EGlpNumClearVar ((b->bound));
+		memset (b, 0, sizeof (bbnode));
+	}
+}
diff --git a/qsopt_ex/binary.h b/qsopt_ex/binary.h
new file mode 100644
index 0000000..b859e33
--- /dev/null
+++ b/qsopt_ex/binary.h
@@ -0,0 +1,36 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCSINFO $Id: binary_EGLPNUM_TYPENAME.h,v 1.3 2003/11/05 16:57:39 meven Exp $ */
+/****************************************************************************/
+/*                                                                          */
+/*                             binary.c                                     */
+/*                                                                          */
+/****************************************************************************/
+
+struct itcnt_t;
+
+int EGLPNUM_TYPENAME_ILLmip_bfs (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPE * val,
+	EGLPNUM_TYPE * x,
+	struct itcnt_t*itcnt);
diff --git a/qsopt_ex/dheaps_i.c b/qsopt_ex/dheaps_i.c
new file mode 100644
index 0000000..fcc944d
--- /dev/null
+++ b/qsopt_ex/dheaps_i.c
@@ -0,0 +1,347 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCSINFO $Id: dheaps_i.c,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of CONCORDE                                           */
+/*                                                                          */
+/*  (c) Copyright 1995--1999 by David Applegate, Robert Bixby,              */
+/*  Vasek Chvatal, and William Cook                                         */
+/*                                                                          */
+/*  Permission is granted for academic research use.  For other uses,       */
+/*  contact the authors for licensing options.                              */
+/*                                                                          */
+/*  Use at your own risk.  We make no guarantees about the                  */
+/*  correctness or usefulness of this code.                                 */
+/*                                                                          */
+/****************************************************************************/
+
+/****************************************************************************/
+/*                                                                          */
+/*                           DHEAP ROUTINES                                 */
+/*                                                                          */
+/*                                                                          */
+/*                              TSP CODE                                    */
+/*  Written by:  Applegate, Bixby, Chvatal, and Cook                        */
+/*  Date: February 9, 1995                                                  */
+/*        March 11, 2002 - Cook (Modifed for QS)                            */
+/*  Reference: R.E. Tarjan, Data Structures and Network Algorithms          */
+/*                                                                          */
+/*    EXPORTED FUNCTIONS:                                                   */
+/*                                                                          */
+/*  int EGLPNUM_TYPENAME_ILLutil_dheap_init (EGLPNUM_TYPENAME_ILLdheap *h, int k)                             */
+/*        -h should point to a EGLPNUM_TYPENAME_ILLdheap struct.                             */
+/*        -k the max number of elements in the dheap.                       */
+/*                                                                          */
+/*  void EGLPNUM_TYPENAME_ILLutil_dheap_free (EGLPNUM_TYPENAME_ILLdheap *h)                                   */
+/*    -frees the spaces allocated by EGLPNUM_TYPENAME_ILLutil_dheap_init                     */
+/*                                                                          */
+/*  int EGLPNUM_TYPENAME_ILLutil_dheap_resize (EGLPNUM_TYPENAME_ILLdheap *h, int newsize)                     */
+/*    -REALLOCs h so it can contain newsize elements.                       */
+/*    -returns -1 if it can't resize the EGLPNUM_TYPENAME_heap.                              */
+/*                                                                          */
+/*  void EGLPNUM_TYPENAME_ILLutil_dheap_findmin (EGLPNUM_TYPENAME_ILLdheap *h, int *i)                        */
+/*    -sets i to the index of the element with min value h->key[i]          */
+/*    -sets i to -1 if no elements in EGLPNUM_TYPENAME_heap.                                 */
+/*                                                                          */
+/*  int EGLPNUM_TYPENAME_ILLutil_dheap_insert (EGLPNUM_TYPENAME_ILLdheap *h, int i)                           */
+/*    -inserts the element with index i (so its key should be loaded        */
+/*     beforehand in h->key[i]).                                            */
+/*                                                                          */
+/*  void EGLPNUM_TYPENAME_ILLutil_dheap_delete (EGLPNUM_TYPENAME_ILLdheap *h, int i)                          */
+/*    -deletes the element with index i.                                    */
+/*                                                                          */
+/*  void EGLPNUM_TYPENAME_ILLutil_dheap_deletemin (EGLPNUM_TYPENAME_ILLdheap *h, int *i)                      */
+/*    -sets i to the min element in the EGLPNUM_TYPENAME_heap, and deletes the min element   */
+/*    -sets i to -1 if no elements in EGLPNUM_TYPENAME_heap.                                 */
+/*                                                                          */
+/*  void EGLPNUM_TYPENAME_ILLutil_dheap_changekey (EGLPNUM_TYPENAME_ILLdheap *h, int i, EGLPNUM_TYPE* newkey)        */
+/*    -changes the key of the element with index i to newkey.               */
+/*                                                                          */
+/****************************************************************************/
+
+/****************************************************************************/
+/*                                                                          */
+/*  NOTES:                                                                  */
+/*      A k-element EGLPNUM_TYPENAME_heap will malloc 16k bytes of memory. If memory is      */
+/*  tight, using integer keys (instead of doubles), brings it down to       */
+/*  12k bytes, and if arbitrary deletions are not required, with a little   */
+/*  rewriting, the h->loc field can be eliminated, bring the space down     */
+/*  to 8k bytes.                                                            */
+/*      These routines work with indices into the h->key array, so in       */
+/*  some cases, you will need to maintain a separate names array to know    */
+/*  what element belongs to index i. For an example, see the k_nearest      */
+/*  code in kdnear.c.                                                       */
+/*                                                                          */
+/****************************************************************************/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "dheaps_i_EGLPNUM_TYPENAME.h"
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "eg_lpnum.h"
+
+#include "allocrus.h"
+#include "except.h"
+#include "trace.h"
+
+static int TRACE = 0;
+
+#define HEAP_D 3
+#define HEAP_UP(x) (((x)-1)/HEAP_D)
+#define HEAP_DOWN(x) (((x)*HEAP_D)+1)
+
+
+static void dheap_siftup (
+	EGLPNUM_TYPENAME_ILLdheap * h,
+	int i,
+	int x),
+  dheap_siftdown (
+	EGLPNUM_TYPENAME_ILLdheap * h,
+	int i,
+	int x);
+
+static int dheap_minchild (
+	int x,
+	EGLPNUM_TYPENAME_ILLdheap * h);
+
+
+int EGLPNUM_TYPENAME_ILLutil_dheap_init (
+	EGLPNUM_TYPENAME_ILLdheap * h,
+	int k)
+{
+	int rval = 0;
+
+	h->entry = (int *) NULL;
+	h->loc = (int *) NULL;
+	h->key = 0;
+
+
+	ILL_SAFE_MALLOC (h->entry, k, int);
+	ILL_SAFE_MALLOC (h->loc, k, int);
+
+	h->key = EGLPNUM_TYPENAME_EGlpNumAllocArray (k);
+	h->size = 0;
+	h->total_space = k;
+
+CLEANUP:
+
+	if (rval)
+	{
+		EGLPNUM_TYPENAME_ILLutil_dheap_free (h);
+	}
+
+	ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLutil_dheap_init");
+}
+
+void EGLPNUM_TYPENAME_ILLutil_dheap_free (
+	EGLPNUM_TYPENAME_ILLdheap * h)
+{
+	ILL_IFFREE (h->entry, int);
+	ILL_IFFREE (h->loc, int);
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (h->key);
+}
+
+int EGLPNUM_TYPENAME_ILLutil_dheap_resize (
+	EGLPNUM_TYPENAME_ILLdheap * h,
+	int newsize)
+{
+	int rval = 0;
+
+	if (newsize < h->size || newsize < h->total_space)
+	{
+		ILL_CLEANUP;
+	}
+
+	h->key = EGrealloc (h->key, sizeof (double) * newsize);
+	//rval = ILLutil_reallocrus_count ((void **) &(h->key), newsize,
+	//                                 sizeof (double));
+	//ILL_CLEANUP_IF (rval);
+	h->entry = EGrealloc (h->entry, sizeof (int) * newsize);
+	//rval = ILLutil_reallocrus_count ((void **) &(h->entry), newsize,
+	//                                 sizeof (int));
+	//ILL_CLEANUP_IF (rval);
+	h->loc = EGrealloc (h->loc, sizeof (int) * newsize);
+	//rval = ILLutil_reallocrus_count ((void **) &(h->loc), newsize, sizeof (int));
+	//ILL_CLEANUP_IF (rval);
+	h->total_space = newsize;
+
+CLEANUP:
+
+	ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLutil_dheap_resize");
+}
+
+void EGLPNUM_TYPENAME_ILLutil_dheap_findmin (
+	EGLPNUM_TYPENAME_ILLdheap * h,
+	int *i)
+{
+	if (h->size == 0)
+		*i = -1;
+	else
+		*i = h->entry[0];
+}
+
+int EGLPNUM_TYPENAME_ILLutil_dheap_insert (
+	EGLPNUM_TYPENAME_ILLdheap * h,
+	int i)
+{
+	if (h->size >= h->total_space)
+	{
+		QSlog("Error - EGLPNUM_TYPENAME_heap already full");
+		return 1;
+	}
+	h->size++;
+	dheap_siftup (h, i, h->size - 1);
+
+	return 0;
+}
+
+void EGLPNUM_TYPENAME_ILLutil_dheap_delete (
+	EGLPNUM_TYPENAME_ILLdheap * h,
+	int i)
+{
+	int j;
+
+	h->size--;
+	j = h->entry[h->size];
+	h->entry[h->size] = -1;
+
+	if (j != i)
+	{
+		if (EGLPNUM_TYPENAME_EGlpNumIsLeq (h->key[j], h->key[i]))
+		{
+			dheap_siftup (h, j, h->loc[i]);
+		}
+		else
+		{
+			dheap_siftdown (h, j, h->loc[i]);
+		}
+	}
+}
+
+void EGLPNUM_TYPENAME_ILLutil_dheap_deletemin (
+	EGLPNUM_TYPENAME_ILLdheap * h,
+	int *i)
+{
+	int j;
+
+	if (h->size == 0)
+		*i = -1;
+	else
+	{
+		j = h->entry[0];
+		EGLPNUM_TYPENAME_ILLutil_dheap_delete (h, j);
+		*i = j;
+	}
+}
+
+void EGLPNUM_TYPENAME_ILLutil_dheap_changekey (
+	EGLPNUM_TYPENAME_ILLdheap * h,
+	int i,
+	EGLPNUM_TYPE * newkey)
+{
+	if (EGLPNUM_TYPENAME_EGlpNumIsLess (*newkey, h->key[i]))
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (h->key[i], *newkey);
+		dheap_siftup (h, i, h->loc[i]);
+	}
+	else if (EGLPNUM_TYPENAME_EGlpNumIsLess (h->key[i], *newkey))
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (h->key[i], *newkey);
+		dheap_siftdown (h, i, h->loc[i]);
+	}
+}
+
+static void dheap_siftup (
+	EGLPNUM_TYPENAME_ILLdheap * h,
+	int i,
+	int x)
+{
+	int p;
+
+	p = HEAP_UP (x);
+	while (x && EGLPNUM_TYPENAME_EGlpNumIsLess (h->key[i], h->key[h->entry[p]]))
+	{
+		h->entry[x] = h->entry[p];
+		h->loc[h->entry[p]] = x;
+		x = p;
+		p = HEAP_UP (p);
+	}
+	h->entry[x] = i;
+	h->loc[i] = x;
+}
+
+static void dheap_siftdown (
+	EGLPNUM_TYPENAME_ILLdheap * h,
+	int i,
+	int x)
+{
+	int c;
+
+	c = dheap_minchild (x, h);
+
+	while (c >= 0 && EGLPNUM_TYPENAME_EGlpNumIsLess (h->key[h->entry[c]], h->key[i]))
+	{
+		h->entry[x] = h->entry[c];
+		h->loc[h->entry[c]] = x;
+		x = c;
+		c = dheap_minchild (c, h);
+	}
+	h->entry[x] = i;
+	h->loc[i] = x;
+}
+
+static int dheap_minchild (
+	int x,
+	EGLPNUM_TYPENAME_ILLdheap * h)
+{
+	int c = HEAP_DOWN (x);
+	int cend;
+	EGLPNUM_TYPE minval;
+	int minloc;
+
+	if (c >= h->size)
+		return -1;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (minval);
+	EGLPNUM_TYPENAME_EGlpNumCopy (minval, h->key[h->entry[c]]);
+	minloc = c;
+	cend = c + HEAP_D;
+	if (h->size < cend)
+		cend = h->size;
+	for (c++; c < cend; c++)
+	{
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (h->key[h->entry[c]], minval))
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (minval, h->key[h->entry[c]]);
+			minloc = c;
+		}
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (minval);
+	return minloc;
+}
diff --git a/qsopt_ex/dheaps_i.h b/qsopt_ex/dheaps_i.h
new file mode 100644
index 0000000..e4ecfcd
--- /dev/null
+++ b/qsopt_ex/dheaps_i.h
@@ -0,0 +1,72 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+#ifndef EGLPNUM_TYPENAME___DHEAPS_I_H__
+#define EGLPNUM_TYPENAME___DHEAPS_I_H__
+
+#include "eg_lpnum.h"
+
+/****************************************************************************/
+/*                                                                          */
+/*                             dheaps_i.c                                   */
+/*                                                                          */
+/****************************************************************************/
+
+typedef struct EGLPNUM_TYPENAME_ILLdheap
+{
+	EGLPNUM_TYPE *key;
+	int *entry;
+	int *loc;
+	int total_space;
+	int size;
+}
+EGLPNUM_TYPENAME_ILLdheap;
+
+void EGLPNUM_TYPENAME_ILLutil_dheap_free (
+	EGLPNUM_TYPENAME_ILLdheap * h),
+  EGLPNUM_TYPENAME_ILLutil_dheap_delete (
+	EGLPNUM_TYPENAME_ILLdheap * h,
+	int i),
+  EGLPNUM_TYPENAME_ILLutil_dheap_changekey (
+	EGLPNUM_TYPENAME_ILLdheap * h,
+	int i,
+	EGLPNUM_TYPE * newkey),
+  EGLPNUM_TYPENAME_ILLutil_dheap_findmin (
+	EGLPNUM_TYPENAME_ILLdheap * h,
+	int *i),
+  EGLPNUM_TYPENAME_ILLutil_dheap_deletemin (
+	EGLPNUM_TYPENAME_ILLdheap * h,
+	int *i);
+
+int EGLPNUM_TYPENAME_ILLutil_dheap_init (
+	EGLPNUM_TYPENAME_ILLdheap * h,
+	int k),
+  EGLPNUM_TYPENAME_ILLutil_dheap_resize (
+	EGLPNUM_TYPENAME_ILLdheap * h,
+	int newsize),
+  EGLPNUM_TYPENAME_ILLutil_dheap_insert (
+	EGLPNUM_TYPENAME_ILLdheap * h,
+	int i);
+
+
+
+#endif
diff --git a/qsopt_ex/dstruct.c b/qsopt_ex/dstruct.c
new file mode 100644
index 0000000..5c25162
--- /dev/null
+++ b/qsopt_ex/dstruct.c
@@ -0,0 +1,499 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: dstruct.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+static int TRACE = 0;
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "logging-private.h"
+
+#include "allocrus.h"
+#include "eg_lpnum.h"
+#include "eg_io.h"
+#include "except.h"
+
+#include "dstruct_EGLPNUM_TYPENAME.h"
+#include "qsopt_EGLPNUM_TYPENAME.h"
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+
+/****************************************************************************/
+/*                                                                          */
+/*                            EGLPNUM_TYPENAME_svector                                       */
+/*                                                                          */
+/*  Written by:  Applegate, Cook, Dash                                      */
+/*  Date:                                                                   */
+/*                                                                          */
+/*    EXPORTED FUNCTIONS:                                                   */
+/*                                                                          */
+/****************************************************************************/
+
+void EGLPNUM_TYPENAME_ILLsvector_init (
+	EGLPNUM_TYPENAME_svector * s)
+{
+	s->nzcnt = 0;
+	s->indx = 0;
+	s->coef = 0;
+}
+
+void EGLPNUM_TYPENAME_ILLsvector_free (
+	EGLPNUM_TYPENAME_svector * s)
+{
+	ILL_IFFREE (s->indx, int);
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (s->coef);
+	s->nzcnt = 0;
+}
+
+int EGLPNUM_TYPENAME_ILLsvector_alloc (
+	EGLPNUM_TYPENAME_svector * s,
+	int nzcnt)
+{
+	int rval = 0;
+
+	s->nzcnt = nzcnt;
+	if (nzcnt == 0)
+	{
+		s->indx = 0;
+		s->coef = 0;
+	}
+	else
+	{
+		ILL_SAFE_MALLOC (s->indx, nzcnt, int);
+
+		s->coef = EGLPNUM_TYPENAME_EGlpNumAllocArray (nzcnt);
+	}
+	return 0;
+CLEANUP:
+	ILL_IFFREE (s->indx, int);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (s->coef);
+	ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLsvector_alloc");
+}
+
+int EGLPNUM_TYPENAME_ILLsvector_copy (
+	const EGLPNUM_TYPENAME_svector * s_in,
+	EGLPNUM_TYPENAME_svector * s_out)
+{
+	int i;
+	int nzcnt = s_in->nzcnt;
+	int rval = 0;
+
+	rval = EGLPNUM_TYPENAME_ILLsvector_alloc (s_out, nzcnt);
+	ILL_CLEANUP_IF (rval);
+	for (i = 0; i < nzcnt; i++)
+	{
+		s_out->indx[i] = s_in->indx[i];
+		EGLPNUM_TYPENAME_EGlpNumCopy (s_out->coef[i], s_in->coef[i]);
+	}
+
+CLEANUP:
+	ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLsvector_copy");
+}
+
+/****************************************************************************/
+/*                                                                          */
+/*                            EGLPNUM_TYPENAME_heap                                          */
+/*                                                                          */
+/*  Written by:  Applegate, Cook, Dash                                      */
+/*  Date:                                                                   */
+/*                                                                          */
+/*    EXPORTED FUNCTIONS:                                                   */
+/*                                                                          */
+/****************************************************************************/
+
+#define DEBUG_HEAP 0
+
+#define HEAP_D 3
+#define HEAP_UP(x) (((x)-1)/HEAP_D)
+#define HEAP_DOWN(x) (((x)*HEAP_D)+1)
+
+static int siftup (
+	EGLPNUM_TYPENAME_heap * h,
+	int hloc,
+	int ix),
+  siftdown (
+	EGLPNUM_TYPENAME_heap * h,
+	int hloc,
+	int ix),
+  maxchild (
+	EGLPNUM_TYPENAME_heap * h,
+	int hloc);
+
+static int siftup (
+	EGLPNUM_TYPENAME_heap * h,
+	int hloc,
+	int ix)
+{
+	int i = hloc;
+	int p = HEAP_UP (i);
+	EGLPNUM_TYPE val;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (val);
+	EGLPNUM_TYPENAME_EGlpNumCopy (val, h->key[ix]);
+
+	while (i > 0 && EGLPNUM_TYPENAME_EGlpNumIsLess (h->key[h->entry[p]], val))
+	{
+		h->entry[i] = h->entry[p];
+		h->loc[h->entry[i]] = i;
+		i = p;
+		p = HEAP_UP (p);
+	}
+	h->entry[i] = ix;
+	h->loc[ix] = i;
+	ILL_IFTRACE2 ("%s:%la:%d:%d:%d\n", __func__, EGLPNUM_TYPENAME_EGlpNumToLf (val), hloc, ix, i);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (val);
+	return i;
+}
+
+static int siftdown (
+	EGLPNUM_TYPENAME_heap * h,
+	int hloc,
+	int ix)
+{
+	int i = hloc;
+	int c = maxchild (h, i);
+	EGLPNUM_TYPE val;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (val);
+	EGLPNUM_TYPENAME_EGlpNumCopy (val, h->key[ix]);
+	ILL_IFTRACE2 ("%s:%d:%d:%d:%la", __func__, hloc, ix, c, EGLPNUM_TYPENAME_EGlpNumToLf (val));
+
+	while (c != -1 && EGLPNUM_TYPENAME_EGlpNumIsLess (val, h->key[h->entry[c]]))
+	{
+		h->entry[i] = h->entry[c];
+		h->loc[h->entry[i]] = i;
+		i = c;
+		c = maxchild (h, c);
+	}
+	h->entry[i] = ix;
+	h->loc[ix] = i;
+	EGLPNUM_TYPENAME_EGlpNumClearVar (val);
+	ILL_IFTRACE2 ("%s:%d:%d\n", __func__, ix, i);
+	return i;
+}
+
+//extern EGLPNUM_TYPE EGLPNUM_TYPENAME_ILL_MINDOUBLE;
+static int maxchild (
+	EGLPNUM_TYPENAME_heap * h,
+	int hloc)
+{
+	int i;
+	int mc = -1;
+	int hmin = HEAP_D * hloc + 1;
+	int hmax = HEAP_D * hloc + HEAP_D;
+	EGLPNUM_TYPE val;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (val);
+	EGLPNUM_TYPENAME_EGlpNumCopy (val, EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+	ILL_IFTRACE2 (" %s:%d", __func__, hloc);
+
+	for (i = hmin; i <= hmax && i < h->size; i++)
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (val, h->key[h->entry[i]]))
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (val, h->key[h->entry[i]]);
+			mc = i;
+			ILL_IFTRACE2 (":%d:%la", mc, EGLPNUM_TYPENAME_EGlpNumToLf (val));
+		}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (val);
+	ILL_IFTRACE2 ("\n");
+	return mc;
+}
+
+#if DEBUG_HEAP > 0
+
+static void printheap (
+	EGLPNUM_TYPENAME_heap * h)
+{
+	int i;
+
+	QSlog("entry (%d): ", h->size);
+	for (i = 0; i < h->size; i++)
+		QSlog("%d ", h->entry[i]);
+	QSlog(" loc: ");
+	for (i = 0; i < h->maxsize; i++)
+		QSlog("%d ", h->loc[i]);
+	QSlog("\n key: ");
+	for (i = 0; i < h->maxsize; i++)
+		QSlog("%la ", EGLPNUM_TYPENAME_EGlpNumToLf (h->key[i]));
+	QSlog("\n key(sorted): ");
+	for (i = 0; i < h->size; i++)
+		QSlog("%la ", EGLPNUM_TYPENAME_EGlpNumToLf (h->key[h->entry[i]]));
+}
+
+static void heapcheck (
+	EGLPNUM_TYPENAME_heap * h)
+{
+	int i, tcnt = 0;
+
+	for (i = 0; i < h->maxsize; i++)
+	{
+		if (h->loc[i] < -1)
+			QSlog("error in EGLPNUM_TYPENAME_heap\n");
+		else if (h->loc[i] > -1)
+			tcnt++;
+	}
+	if (tcnt != h->size)
+		QSlog("error 3 in EGLPNUM_TYPENAME_heap\n");
+
+	for (i = 0; i < h->size; i++)
+	{
+		if (h->loc[h->entry[i]] != i)
+			QSlog("error 1 in EGLPNUM_TYPENAME_heap\n");
+		if (!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (h->key[h->entry[i]]))
+			QSlog("error 2 in EGLPNUM_TYPENAME_heap\n");
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (h->key[h->entry[HEAP_UP (i)]], h->key[h->entry[i]]))
+			QSlog("error 4 in EGLPNUM_TYPENAME_heap\n");
+	}
+}
+
+#endif
+
+void EGLPNUM_TYPENAME_ILLheap_insert (
+	EGLPNUM_TYPENAME_heap * const h,
+	int const ix)
+{
+	int i = h->size;
+
+	ILL_IFTRACE ("%s:%d:%la\n", __func__, ix, EGLPNUM_TYPENAME_EGlpNumToLf (h->key[ix]));
+
+	i = siftup (h, i, ix);
+	h->size++;
+
+#if DEBUG_HEAP > 0
+	heapcheck (h);
+#endif
+#if DEBUG_HEAP > 1
+	printheap (h);
+#endif
+}
+
+void EGLPNUM_TYPENAME_ILLheap_modify (
+	EGLPNUM_TYPENAME_heap * const h,
+	int const ix)
+{
+	int i = h->loc[ix];
+	int pi = i;
+
+	ILL_IFTRACE ("%s:%d\n", __func__, ix);
+
+	if (h->loc[ix] == -1)
+		return;
+	i = siftup (h, i, ix);
+	if (pi == i)
+		i = siftdown (h, i, ix);
+
+#if DEBUG_HEAP > 0
+	heapcheck (h);
+#endif
+#if DEBUG_HEAP > 1
+	printheap (h);
+#endif
+}
+
+void EGLPNUM_TYPENAME_ILLheap_delete (
+	EGLPNUM_TYPENAME_heap * const h,
+	int const ix)
+{
+	int i = h->loc[ix];
+	int pi = i;
+	int nix = h->entry[h->size - 1];
+
+	ILL_IFTRACE ("%s:%d:%d:%d\n", __func__, ix, nix, pi);
+
+	h->loc[ix] = -1;
+	h->size--;
+	if (nix == ix)
+	{
+#if DEBUG_HEAP > 0
+		heapcheck (h);
+#endif
+#if DEBUG_HEAP > 1
+		printheap (h);
+#endif
+		return;
+	}
+
+	h->entry[i] = nix;
+	h->loc[nix] = i;
+
+	i = siftup (h, i, nix);
+	ILL_IFTRACE ("%s:%d:%d:%d:%d\n", __func__, ix, nix, pi, i);
+	if (pi == i)
+		siftdown (h, i, nix);
+
+#if DEBUG_HEAP > 0
+	heapcheck (h);
+#endif
+#if DEBUG_HEAP > 1
+	printheap (h);
+#endif
+}
+
+int EGLPNUM_TYPENAME_ILLheap_findmin (
+	EGLPNUM_TYPENAME_heap * const h)
+{
+	if (h->hexist == 0 || h->size <= 0)
+		return -1;
+	return h->entry[0];
+}
+
+void EGLPNUM_TYPENAME_ILLheap_init (
+	EGLPNUM_TYPENAME_heap * const h)
+{
+	h->entry = NULL;
+	h->loc = NULL;
+	h->key = NULL;
+	h->hexist = 0;
+}
+
+int EGLPNUM_TYPENAME_ILLheap_build (
+	EGLPNUM_TYPENAME_heap * const h,
+	int const nelems,
+	EGLPNUM_TYPE * key)
+{
+	int rval = 0;
+	int i, n = 0;
+
+	ILL_IFTRACE ("%s:%d\n", __func__, nelems);
+
+	h->hexist = 1;
+	h->size = 0;
+	h->maxsize = nelems;
+	h->key = key;
+	ILL_SAFE_MALLOC (h->entry, nelems, int);
+	ILL_SAFE_MALLOC (h->loc, nelems, int);
+
+	for (i = 0; i < nelems; i++)
+	{
+		if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (key[i]))
+		{
+			h->entry[n] = i;
+			h->loc[i] = n;
+			n++;
+		}
+		else
+			h->loc[i] = -1;
+	}
+	h->size = n;
+	for (i = n - 1; i >= 0; i--)
+	{
+		ILL_IFTRACE2 ("insert %la\n", EGLPNUM_TYPENAME_EGlpNumToLf (h->key[h->entry[i]]));
+		siftdown (h, i, h->entry[i]);
+	}
+
+#if DEBUG_HEAP > 0
+	heapcheck (h);
+#endif
+#if DEBUG_HEAP > 1
+	printheap (h);
+#endif
+
+CLEANUP:
+	if (rval)
+		EGLPNUM_TYPENAME_ILLheap_free (h);
+	ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLheap_init");
+}
+
+void EGLPNUM_TYPENAME_ILLheap_free (
+	EGLPNUM_TYPENAME_heap * const h)
+{
+	if (h->hexist)
+	{
+		ILL_IFFREE (h->entry, int);
+		ILL_IFFREE (h->loc, int);
+
+		h->hexist = 0;
+		h->maxsize = 0;
+		h->size = 0;
+	}
+}
+
+
+/****************************************************************************/
+/*                                                                          */
+/*                          matrix                                          */
+/*                                                                          */
+/*  Written by:  Applegate, Cook, Dash                                      */
+/*  Date:                                                                   */
+/*                                                                          */
+/*    EXPORTED FUNCTIONS:                                                   */
+/*                                                                          */
+/****************************************************************************/
+
+void EGLPNUM_TYPENAME_ILLmatrix_init (
+	EGLPNUM_TYPENAME_ILLmatrix * A)
+{
+	if (A)
+	{
+		A->matval = 0;
+		A->matcnt = 0;
+		A->matbeg = 0;
+		A->matind = 0;
+		A->matcols = 0;
+		A->matcolsize = 0;
+		A->matrows = 0;
+		A->matsize = 0;
+		A->matfree = 0;
+	}
+}
+
+void EGLPNUM_TYPENAME_ILLmatrix_free (
+	EGLPNUM_TYPENAME_ILLmatrix * A)
+{
+	if (A)
+	{
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (A->matval);
+		ILL_IFFREE (A->matcnt, int);
+		ILL_IFFREE (A->matbeg, int);
+		ILL_IFFREE (A->matind, int);
+
+		EGLPNUM_TYPENAME_ILLmatrix_init (A);
+	}
+}
+
+void EGLPNUM_TYPENAME_ILLmatrix_prt (
+	EGioFile_t * fd,
+	EGLPNUM_TYPENAME_ILLmatrix * A)
+{
+	int j, k;
+
+	if (A == NULL)
+	{
+		EGioPrintf (fd, "Matrix %p: empty\n", (void *) A);
+	}
+	else
+	{
+		EGioPrintf (fd, "Matrix %p: nrows = %d ncols = %d\n",
+						 (void *) A, A->matrows, A->matcols);
+		for (j = 0; j < A->matcols; j++)
+		{
+			EGioPrintf (fd, "col %d: ", j);
+			for (k = A->matbeg[j]; k < A->matbeg[j] + A->matcnt[j]; k++)
+			{
+				EGioPrintf (fd, "row %d=%.3f ", A->matind[k], EGLPNUM_TYPENAME_EGlpNumToLf (A->matval[k]));
+			}
+			EGioPrintf (fd, "\n");
+		}
+	}
+}
diff --git a/qsopt_ex/dstruct.h b/qsopt_ex/dstruct.h
new file mode 100644
index 0000000..d741bb7
--- /dev/null
+++ b/qsopt_ex/dstruct.h
@@ -0,0 +1,134 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCSINFO $Id: dstruct_EGLPNUM_TYPENAME.h,v 1.3 2003/11/05 16:57:39 meven Exp $ */
+/****************************************************************************/
+/*                                                                          */
+/*                           EGLPNUM_TYPENAME_svector.h                                      */
+/*                                                                          */
+/****************************************************************************/
+
+#ifndef EGLPNUM_TYPENAME___SVECTOR_H
+#define EGLPNUM_TYPENAME___SVECTOR_H
+
+#include "eg_io.h"
+
+typedef struct EGLPNUM_TYPENAME_svector
+{
+	int nzcnt;
+	int *indx;
+	int size;
+	EGLPNUM_TYPE *coef;
+}
+EGLPNUM_TYPENAME_svector;
+
+void EGLPNUM_TYPENAME_ILLsvector_init (
+	EGLPNUM_TYPENAME_svector * s),
+  EGLPNUM_TYPENAME_ILLsvector_free (
+	EGLPNUM_TYPENAME_svector * s);
+
+int EGLPNUM_TYPENAME_ILLsvector_alloc (
+	EGLPNUM_TYPENAME_svector * s,
+	int nzcnt),
+  EGLPNUM_TYPENAME_ILLsvector_copy (
+	const EGLPNUM_TYPENAME_svector * s_in,
+	EGLPNUM_TYPENAME_svector * s_out);
+
+#endif /* EGLPNUM_TYPENAME___SVECTOR_H */
+
+/****************************************************************************/
+/*                                                                          */
+/*                           EGLPNUM_TYPENAME_heap.h                                         */
+/*                                                                          */
+/****************************************************************************/
+
+#ifndef EGLPNUM_TYPENAME___HEAP_H
+#define EGLPNUM_TYPENAME___HEAP_H
+
+typedef struct
+{
+	int *entry;
+	int *loc;
+	EGLPNUM_TYPE *key;
+	int hexist;
+	int maxsize;
+	int size;
+}
+EGLPNUM_TYPENAME_heap;
+
+void EGLPNUM_TYPENAME_ILLheap_insert (
+	EGLPNUM_TYPENAME_heap * const h,
+	int const ix),
+  EGLPNUM_TYPENAME_ILLheap_modify (
+	EGLPNUM_TYPENAME_heap * const h,
+	int const ix),
+  EGLPNUM_TYPENAME_ILLheap_delete (
+	EGLPNUM_TYPENAME_heap * const h,
+	int const ix),
+  EGLPNUM_TYPENAME_ILLheap_init (
+	EGLPNUM_TYPENAME_heap * const h),
+  EGLPNUM_TYPENAME_ILLheap_free (
+	EGLPNUM_TYPENAME_heap * const h);
+
+int EGLPNUM_TYPENAME_ILLheap_findmin (
+	EGLPNUM_TYPENAME_heap * const h),
+  EGLPNUM_TYPENAME_ILLheap_build (
+	EGLPNUM_TYPENAME_heap * const h,
+	int const nelems,
+	EGLPNUM_TYPE * key);
+
+#endif /* EGLPNUM_TYPENAME___HEAP_H */
+
+/****************************************************************************/
+/*                                                                          */
+/*                         matrix.h                                         */
+/*                                                                          */
+/****************************************************************************/
+
+#ifndef EGLPNUM_TYPENAME___MATRIX_H
+#define EGLPNUM_TYPENAME___MATRIX_H
+
+typedef struct EGLPNUM_TYPENAME_ILLmatrix
+{
+	EGLPNUM_TYPE *matval;						/* The coefficients.                       */
+	int *matcnt;									/* Number of coefs in each col.            */
+	int *matind;									/* The row indices of the coefs.           */
+	int *matbeg;									/* The start of each col.                  */
+	int matcols;									/* Number of columns.                      */
+	int matrows;
+	int matcolsize;								/* Length of matbeg and matcnt.            */
+	int matsize;									/* Length of matind and matval.            */
+	int matfree;									/* Free space at end of matind.            */
+	/* Note: free elements marked by -1 in     */
+	/* matind; we keep at least 1 free at end. */
+}
+EGLPNUM_TYPENAME_ILLmatrix;
+
+void EGLPNUM_TYPENAME_ILLmatrix_init (
+	EGLPNUM_TYPENAME_ILLmatrix * A);
+void EGLPNUM_TYPENAME_ILLmatrix_free (
+	EGLPNUM_TYPENAME_ILLmatrix * A);
+void EGLPNUM_TYPENAME_ILLmatrix_prt (
+	EGioFile_t * fd,
+	EGLPNUM_TYPENAME_ILLmatrix * A);
+
+#endif /* EGLPNUM_TYPENAME___MATRIX_H */
diff --git a/qsopt_ex/editor.c b/qsopt_ex/editor.c
new file mode 100644
index 0000000..47d7b48
--- /dev/null
+++ b/qsopt_ex/editor.c
@@ -0,0 +1,789 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: editor.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "eg_lpnum.h"
+#include "eg_io.h"
+#include "except.h"
+#include "util.h"
+
+#include "qsopt_EGLPNUM_TYPENAME.h"
+#include "lpdata_EGLPNUM_TYPENAME.h"
+#include "qstruct_EGLPNUM_TYPENAME.h"
+#include "qsopt_EGLPNUM_TYPENAME.h"
+#include "editor_EGLPNUM_TYPENAME.h"
+#include "readline_EGLPNUM_TYPENAME.h"
+#include "rawlp_EGLPNUM_TYPENAME.h"
+#include "stddefs.h"						/* for MAX */
+#include "read_lp_EGLPNUM_TYPENAME.h"
+#include "lp_EGLPNUM_TYPENAME.h"
+#include "lib_EGLPNUM_TYPENAME.h"
+
+static int TRACE = 0;
+
+#define ILL_BREAK_BODY_IF(rval) if (rval != 0) goto CLEANUP
+#define ILL_BREAK_BODY goto CLEANUP
+
+static int transpose ( EGLPNUM_TYPENAME_rawlpdata * lp);
+static int pull_info_from_p ( EGLPNUM_TYPENAME_QSdata * p, EGLPNUM_TYPENAME_rawlpdata * lp);
+static void add_row ( EGLPNUM_TYPENAME_QSdata * p, EGLPNUM_TYPENAME_rawlpdata * lp, EGLPNUM_TYPENAME_ILLread_lp_state * state);
+
+/* static int new_row(EGLPNUM_TYPENAME_QSdata *p, EGLPNUM_TYPENAME_rawlpdata *lp, EGLPNUM_TYPENAME_ILLread_lp_state *state); */
+static void del_row ( EGLPNUM_TYPENAME_QSdata * p, EGLPNUM_TYPENAME_rawlpdata * lp, EGLPNUM_TYPENAME_ILLread_lp_state * state);
+
+static void add_col ( EGLPNUM_TYPENAME_QSdata * p, EGLPNUM_TYPENAME_rawlpdata * lp, EGLPNUM_TYPENAME_ILLread_lp_state * state);
+static void del_col ( EGLPNUM_TYPENAME_QSdata * p, EGLPNUM_TYPENAME_rawlpdata * lp, EGLPNUM_TYPENAME_ILLread_lp_state * state);
+
+#define NONE -1
+#define QS_EXIT 0
+#define ROW 1
+#define COL 2
+#define PLP 3
+#define PRTX 4
+#define SOLVE 5
+#define PMPS 6
+#define HELP 7
+#define DEL 8
+#define NEW 9
+#define ADD 10
+#define PRIMAL 11
+#define DUAL 12
+#define NCOMMAND 13
+static const char *commands[NCOMMAND + 1];
+static char hasSubCmd[NCOMMAND + 1];
+
+void EGLPNUM_TYPENAME_ILLeditor_init (
+	void)
+{
+	commands[QS_EXIT] = "QS_EXIT";
+	commands[ROW] = "ROW";
+	commands[COL] = "COL";
+	commands[PLP] = "LP";
+	commands[PMPS] = "MPS";
+	commands[SOLVE] = "SOLVE";
+	commands[PRTX] = "PRT";
+	commands[HELP] = "HELP";
+	commands[ADD] = "ADD";
+	commands[DEL] = "DEL";
+	commands[NEW] = "NEW";
+	commands[PRIMAL] = "PRIMAL";
+	commands[DUAL] = "DUAL";
+	commands[NCOMMAND] = NULL;
+
+	hasSubCmd[QS_EXIT] = 0;
+	hasSubCmd[ROW] = 1;
+	hasSubCmd[COL] = 1;
+	hasSubCmd[PLP] = 0;
+	hasSubCmd[PMPS] = 0;
+	hasSubCmd[SOLVE] = 1;
+	hasSubCmd[PRTX] = 0;
+	hasSubCmd[HELP] = 0;
+	hasSubCmd[ADD] = 1;
+	hasSubCmd[DEL] = 1;
+	hasSubCmd[NEW] = 1;
+	hasSubCmd[PRIMAL] = 1;
+	hasSubCmd[DUAL] = 1;
+	hasSubCmd[NCOMMAND] = 0;
+}
+
+static void ILLeditor_help_cmd (
+	int cmd,
+	int subcmd);
+
+static void ILLeditor_help (
+	void)
+{
+	ILLeditor_help_cmd (ROW, ADD);
+	/* ILLeditor_help_cmd(ROW, NEW);  */
+	ILLeditor_help_cmd (ROW, DEL);
+	ILLeditor_help_cmd (COL, ADD);
+	ILLeditor_help_cmd (COL, DEL);
+	ILLeditor_help_cmd (SOLVE, NONE);
+	ILLeditor_help_cmd (PRTX, NONE);
+	ILLeditor_help_cmd (PLP, NONE);
+	ILLeditor_help_cmd (PMPS, NONE);
+	ILLeditor_help_cmd (QS_EXIT, NONE);
+	ILLeditor_help_cmd (HELP, NONE);
+}
+
+static void ILLeditor_help_cmd (
+	int cmd,
+	int subcmd)
+{
+	if (cmd == ROW && subcmd == ADD)
+		QSlog("%s ADD:\t%s.",
+								commands[ROW], "add a row; enter in LP format");
+	if (cmd == COL && subcmd == ADD)
+		QSlog("%s ADD:\t%s.",
+								commands[COL], "add a col; enter in LP format");
+	/* if (cmd == ROW && subcmd == NEW) 
+	 * QSlog("%s NEW:\t%s.", 
+	 * commands[ROW], "new row; enter rowname: sense rhs");  
+	 */
+	if (cmd == ROW && subcmd == DEL)
+		QSlog("%s DEL:\t%s.",
+								commands[ROW], "delete a row; give rowname");
+	if (cmd == COL && subcmd == DEL)
+		QSlog("%s DEL:\t%s.",
+								commands[COL], "delete a col; give colname");
+	if (cmd == SOLVE)
+		QSlog("%s:\t%s.", commands[SOLVE], "solve problem");
+	if (cmd == PRTX)
+		QSlog("%s:\t%s.",
+								commands[PRTX], "print variable values for optimal solution");
+	if (cmd == PLP)
+		QSlog("%s [file]:\t%s.",
+								commands[PLP], "print problem in LP format to file or stdout");
+	if (cmd == PMPS)
+		QSlog("%s [file]:\t%s.",
+								commands[PMPS], "print problem in MPS format to file or stdout");
+	if (cmd == QS_EXIT)
+		QSlog("%s:\t%s.", commands[QS_EXIT], "QS_EXIT");
+	if (cmd == HELP)
+		QSlog("%s:\t%s.", commands[HELP], "print this help");
+}
+
+static void getCmd (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	int *cmd,
+	int *subcmd)
+{
+	const char *cmd_str, *subcmd_str;
+	int tmp;
+
+	*cmd = ILLutil_index (commands, state->field);
+	*subcmd = -1;
+	if (hasSubCmd[*cmd] && (EGLPNUM_TYPENAME_ILLread_lp_state_next_field_on_line (state) == 0))
+	{
+		*subcmd = ILLutil_index (commands, state->field);
+		if ((*subcmd == ROW) || (*subcmd == COL) || (*subcmd == SOLVE))
+		{
+			ILL_SWAP (*subcmd, *cmd, tmp);
+		}
+	}
+	cmd_str = (*cmd >= 0) ? commands[*cmd] : "???";
+	subcmd_str = (*subcmd >= 0) ? commands[*subcmd] : "???";
+	ILL_IFTRACE ("cmd = %s, subcmd = %s\n", cmd_str, subcmd_str);
+}
+
+void EGLPNUM_TYPENAME_ILLeditor (
+	EGLPNUM_TYPENAME_QSdata * p)
+{
+	EGLPNUM_TYPENAME_rawlpdata raw, *lp = &raw;
+	int cmd, subcmd, tval, rval = 0;
+	EGLPNUM_TYPENAME_ILLread_lp_state lpstate, *state = &lpstate;
+	EGLPNUM_TYPENAME_qsline_reader *reader;
+
+	ILL_IFTRACE ("EGLPNUM_TYPENAME_ILLeditor\n");
+
+	reader = EGLPNUM_TYPENAME_ILLline_reader_new ((EGLPNUM_TYPENAME_qsread_line_fct) fgets, stdin);
+	rval = EGLPNUM_TYPENAME_ILLread_lp_state_init (state, reader, "STDIN", 1);
+	rval = rval || pull_info_from_p (p, lp);
+	ILL_BREAK_BODY_IF (rval);
+
+	while (EGLPNUM_TYPENAME_ILLread_lp_state_next_field (state) == 0)
+	{
+		getCmd (state, &cmd, &subcmd);
+		switch (cmd)
+		{
+		case QS_EXIT:
+			ILL_BREAK_BODY;
+
+		case ROW:
+			{
+				switch (subcmd)
+				{
+				case ADD:
+					add_row (p, lp, state);
+					break;
+					/* case NEW: rval = new_row(p, lp, state); break; */
+				case DEL:
+					del_row (p, lp, state);
+					break;
+				default:
+					ILLeditor_help ();
+					break;
+				}
+				break;
+			}
+		case COL:
+			{
+				switch (subcmd)
+				{
+				case ADD:
+					add_col (p, lp, state);
+					break;
+				case DEL:
+					del_col (p, lp, state);
+					break;
+				default:
+					ILLeditor_help ();
+					break;
+				}
+				break;
+			}
+
+		case SOLVE:
+			{
+				if (subcmd == PRIMAL)
+				{
+					(void) EGLPNUM_TYPENAME_ILLeditor_solve (p, PRIMAL_SIMPLEX);
+				}
+				else if (subcmd == DUAL)
+				{
+					(void) EGLPNUM_TYPENAME_ILLeditor_solve (p, DUAL_SIMPLEX);
+				}
+				else
+				{
+					ILLeditor_help ();
+				}
+				break;
+			}
+
+		case PRTX:
+			{
+				EGioFile_t*lout = EGioOpenFILE(stdout);
+				if ((rval = EGLPNUM_TYPENAME_ILLlib_print_x (lout, p->lp, 0, 0, 1)))
+				{
+					QSlog("The problem may not be feasible.");
+				}
+				EGioClose(lout);
+				break;
+			}
+
+		case PLP:
+		case PMPS:
+			{
+				if (EGLPNUM_TYPENAME_ILLread_lp_state_next_field_on_line (state) == 0)
+				{
+					if (cmd == PMPS)
+					{
+						tval = EGLPNUM_TYPENAME_QSwrite_prob (p, state->field, "MPS");
+					}
+					else
+					{
+						tval = EGLPNUM_TYPENAME_QSwrite_prob (p, state->field, "LP");
+					}
+					if (tval)
+					{
+						QSlog("Could not write problem to \"%s\".",
+												state->field);
+					}
+					else
+					{
+						QSlog("Saved to \"%s\".", state->field);
+					}
+				}
+				else
+				{
+					if (cmd == PMPS)
+					{
+						(void) EGLPNUM_TYPENAME_QSwrite_prob_file (p, stdout, "MPS");
+					}
+					else
+					{
+						(void) EGLPNUM_TYPENAME_QSwrite_prob_file (p, stdout, "LP");
+					}
+				}
+				break;
+			}
+
+		case NONE:
+			QSlog("Unknown command: %s", state->field);
+		default:
+			ILLeditor_help ();
+			break;
+		}
+		EGLPNUM_TYPENAME_ILLread_lp_state_next_line (state);
+	}
+CLEANUP:
+	EGLPNUM_TYPENAME_ILLline_reader_free (reader);
+	EGLPNUM_TYPENAME_ILLfree_rawlpdata (lp);
+}
+
+int EGLPNUM_TYPENAME_ILLeditor_solve (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int salgo)
+{
+	int rval = 0;
+	int status = 0;
+	EGLPNUM_TYPE val;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (val);
+
+	if (salgo == PRIMAL_SIMPLEX)
+	{
+		rval = EGLPNUM_TYPENAME_QSopt_primal (p, &status);
+	}
+	else
+	{
+		rval = EGLPNUM_TYPENAME_QSopt_dual (p, &status);
+	}
+	ILL_BREAK_BODY_IF (rval);
+	rval = EGLPNUM_TYPENAME_QSget_objval (p, &val);
+	if (p->simplex_display)
+		if (rval == 0)
+		{
+			QSlog("LP Value: %.6f, status %d", EGLPNUM_TYPENAME_EGlpNumToLf (val),
+									status);
+		}
+CLEANUP:
+	EGLPNUM_TYPENAME_EGlpNumClearVar (val);
+	ILL_RESULT (rval, "EGLPNUM_TYPENAME_ILLeditor_solve");
+}
+
+
+static int pull_info_from_p (
+	EGLPNUM_TYPENAME_QSdata * p,
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	int i, rval = 0;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp = p->lp->O;
+	int nrows, ncols;
+
+	EGLPNUM_TYPENAME_ILLinit_rawlpdata (lp, NULL);
+	rval = ILLsymboltab_create (&lp->rowtab, 100) ||
+		ILLsymboltab_create (&lp->coltab, 100);
+	ILL_BREAK_BODY_IF (rval);
+
+	nrows = qslp->nrows;
+	ncols = qslp->nstruct;
+	/* add rows to lp */
+	EGLPNUM_TYPENAME_ILLraw_add_row (lp, qslp->objname, 'N', EGLPNUM_TYPENAME_zeroLpNum);
+	for (i = 0; i < nrows; i++)
+	{
+		ILL_FAILfalse (qslp->rownames[i] != NULL, "should have no NULL names");
+		EGLPNUM_TYPENAME_ILLraw_add_row (lp, qslp->rownames[i], qslp->sense[i], qslp->rhs[i]);
+	}
+
+	/* add cols to coltab and lp */
+	for (i = 0; i < ncols; i++)
+	{
+		ILL_FAILfalse (qslp->colnames[i] != NULL, "should have no NULL names");
+		EGLPNUM_TYPENAME_ILLraw_add_col (lp, qslp->colnames[i],
+										(qslp->intmarker) ? qslp->intmarker[i] : 0);
+	}
+CLEANUP:
+	ILL_RETURN (rval, "pull_info_from_p");
+}
+
+static int transpose (
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	int rval = 0;
+	int tmp;
+	ILLsymboltab tmptab;
+
+	tmp = QSMAX (lp->nrows, lp->ncols);
+	if (tmp >= lp->sensesize)
+	{
+		lp->sensesize *= 1.3;
+		lp->sensesize += 1000;
+		if (lp->sensesize < tmp + 1)
+			lp->sensesize = tmp + 1;
+		lp->rowsense = EGrealloc (lp->rowsense, sizeof (char) * lp->sensesize);
+		//rval = ILLutil_reallocrus_scale ((void **) &lp->rowsense,
+		//                                 &lp->sensesize, tmp + 1,
+		//                                 1.3, sizeof (char));
+		//ILL_CLEANUP_IF (rval);
+	}
+	if (tmp >= lp->rhssize)
+	{
+		lp->rhssize *= 1.3;
+		lp->rhssize += 1000;
+		if (lp->rhssize < tmp + 1)
+			lp->rhssize = tmp + 1;
+		EGLPNUM_TYPENAME_EGlpNumReallocArray (&(lp->rhs), lp->rhssize);
+		//lp->rhs = EGrealloc(lp->rhs, sizeof(double)*lp->rhssize);
+		//rval = ILLutil_reallocrus_scale ((void **) &lp->rhs,
+		//                                 &lp->sensesize, tmp + 1,
+		//                                 1.3, sizeof (double));
+		//ILL_CLEANUP_IF (rval);
+	}
+	ILL_SWAP (lp->nrows, lp->ncols, tmp);
+	ILL_SWAP (lp->rowtab, lp->coltab, tmptab);
+	ILL_RETURN (rval, "transpose");
+}
+
+static char *get_row_col_name (
+	EGLPNUM_TYPENAME_QSdata * p,
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	int doRow)
+{
+	int rval = 0;
+	int ind;
+	char *rname, *thename = NULL;
+	char buf[ILL_namebufsize];
+	ILLsymboltab *tab = (doRow) ? &lp->rowtab : &lp->coltab;
+	int id = (doRow) ? lp->nrows : lp->ncols;
+
+	id--;													/* in EGLPNUM_TYPENAME_rawlpdata obj counts as a row */
+
+	rval = EGLPNUM_TYPENAME_ILLread_constraint_name (state, &rname);
+	ILL_BREAK_BODY_IF (rval);
+
+	if (rname == NULL)
+	{
+		EGLPNUM_TYPENAME_ILLlib_findName (p->qslp, doRow /* forRow */ , rname, id, buf);
+		ILL_UTIL_STR (thename, buf);
+	}
+	else
+	{
+		ILL_UTIL_STR (thename, rname);
+	}
+	if (ILLsymboltab_lookup (tab, thename, &ind) == 0)
+	{
+		rval = EGLPNUM_TYPENAME_ILLlp_error (state, "\"%s\" already exists.", thename);
+	}
+CLEANUP:
+	if (rval != 0)
+	{
+		ILL_IFFREE (thename, char);
+	}
+	return thename;
+}
+
+static int fill_matrix (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	EGLPNUM_TYPENAME_ILLmatrix * m,
+	EGLPNUM_TYPE * obj,
+	int n)
+{
+	int i, cnt, rval = 0;
+	EGLPNUM_TYPENAME_colptr *cp;
+	EGLPNUM_TYPE val;
+	int newCol = (obj != NULL);
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (val);
+
+	/* rely on fact that objective has rowindex 0 */
+
+	m->matrows = lp->nrows;
+	m->matcols = 1;
+	m->matval = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->ncols);
+	ILL_SAFE_MALLOC (m->matind, lp->ncols, int);
+	ILL_SAFE_MALLOC (m->matbeg, 1, int);
+	ILL_SAFE_MALLOC (m->matcnt, 1, int);
+
+	m->matsize = lp->ncols;
+	m->matbeg[0] = 0;
+	m->matcnt[0] = 0;
+	for (i = 0; i < lp->ncols; i++)
+	{
+		cnt = 0;
+		EGLPNUM_TYPENAME_EGlpNumZero (val);
+		for (cp = lp->cols[i]; cp != NULL; cp = cp->next)
+		{
+			ILL_FAILfalse (cp->this_val == n, "n should be the only row around");
+			if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (cp->coef))
+			{
+				EGLPNUM_TYPENAME_EGlpNumAddTo (val, cp->coef);
+				cnt++;
+			}
+		}
+		if (cnt > 1)
+		{
+			EGLPNUM_TYPENAME_ILLlp_warn (state, "Multiple coefficients for \"%s\".",
+									EGLPNUM_TYPENAME_ILLraw_colname (lp, i));
+		}
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (val))
+		{
+			if ((i - newCol) >= 0)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (m->matval[m->matcnt[0]], val);
+				m->matind[m->matcnt[0]] = i - newCol;
+				m->matcnt[0]++;
+			}
+			else
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (obj[0], val);
+			}
+		}
+	}
+	if (m->matcnt[0] == 0)
+	{
+		rval = EGLPNUM_TYPENAME_ILLlp_error (state, "There are no non zero coefficients.");
+	}
+CLEANUP:
+	EGLPNUM_TYPENAME_EGlpNumClearVar (val);
+	ILL_RESULT (rval, "fill_matrix");
+}
+
+static void add_row (
+	EGLPNUM_TYPENAME_QSdata * p,
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+	int rval = 0;
+	int n;
+	char *name;
+	EGLPNUM_TYPENAME_ILLmatrix m;
+	char sense[1];
+
+	EGLPNUM_TYPENAME_ILLmatrix_init (&m);
+	n = lp->nrows;
+	name = get_row_col_name (p, lp, state, 1 /*doRow */ );
+
+	if (name == NULL)
+	{
+		rval = 1;
+	}
+	else
+	{
+		rval = EGLPNUM_TYPENAME_ILLread_one_constraint (state, name, lp, 0);
+
+		/* adds row name to lp->rowtab the checks constraint expression  */
+		if (rval != 0)
+		{
+			/* failed because of error in expression => 
+			 * must remove name from symbol table */
+			QSlog("Incorrect expression.");
+		}
+		else
+		{
+			ILL_FAILfalse (lp->nrows == (n + 1), "Should have one row");
+			ILL_IFTRACE ("ADDING row %s.\n", name);
+
+			sense[0] = lp->rowsense[n];
+
+			rval = fill_matrix (lp, state, &m, NULL, n);
+			ILL_BREAK_BODY_IF (rval);
+
+			EGLPNUM_TYPENAME_QSadd_rows (p, 1, m.matcnt, m.matbeg, m.matind, m.matval,
+									&(lp->rhs[n]), sense, (const char **) &name);
+		}
+	}
+CLEANUP:
+	EGLPNUM_TYPENAME_ILLmatrix_free (&m);
+	if (name != NULL)
+	{
+		if (rval != 0)
+			ILLsymboltab_delete (&lp->rowtab, name);
+		ILL_IFFREE (name, char);
+	}
+	if (rval != 0)
+	{
+		lp->nrows = n;
+	}
+	EGLPNUM_TYPENAME_ILLraw_clear_matrix (lp);
+}
+
+static void add_col (
+	EGLPNUM_TYPENAME_QSdata * p,
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+	int rval = 0;
+	int n;
+	char *name[1];
+	int transposed = 1;
+	EGLPNUM_TYPENAME_ILLmatrix matrix, *m = &matrix;
+	EGLPNUM_TYPE obj[1], lower[1], upper[2];
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (*obj);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (*lower);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (upper[0]);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (upper[1]);
+
+	n = lp->ncols;
+	EGLPNUM_TYPENAME_ILLmatrix_init (m);
+	name[0] = get_row_col_name (p, lp, state, 0 /*doRow */ );
+	rval = (name[0] == NULL);
+	ILL_BREAK_BODY_IF (rval);
+
+	transposed = !transpose (lp);
+	rval = EGLPNUM_TYPENAME_ILLread_one_constraint (state, name[0], lp, 0);
+
+	/* adds row name to lp->rowtab the checks constraint expression  */
+	if (rval != 0)
+	{
+		/* failed because of error in expression => 
+		 * must remove name from symbol table */
+		QSlog("Incorrect expression.");
+	}
+	else
+	{
+		ILL_FAILfalse (lp->nrows == (n + 1), "Should have one row");
+
+		rval = fill_matrix (lp, state, m, obj, n);
+		ILL_BREAK_BODY_IF (rval);
+
+		QSlog("lower ");
+		rval = EGLPNUM_TYPENAME_ILLread_lp_state_next_line (state) ||
+			EGLPNUM_TYPENAME_ILLread_lp_state_value (state, &(lower[0]));
+		ILL_BREAK_BODY_IF (rval);
+
+		QSlog("upper ");
+		rval = EGLPNUM_TYPENAME_ILLread_lp_state_next_line (state) ||
+			EGLPNUM_TYPENAME_ILLread_lp_state_value (state, &(upper[0]));
+		ILL_BREAK_BODY_IF (rval);
+
+		ILL_IFTRACE ("ADDING col %s.\n", name[0]);
+
+		EGLPNUM_TYPENAME_QSadd_cols (p, 1, m->matcnt, m->matbeg, m->matind, m->matval,
+								obj, lower, upper, (const char **) name);
+
+	}
+CLEANUP:
+	EGLPNUM_TYPENAME_ILLmatrix_free (m);
+	if (name[0] != NULL)
+	{
+		if (rval != 0)
+			ILLsymboltab_delete (&lp->rowtab, name[0]);
+		ILL_IFFREE (name[0], char);
+	}
+	if (rval != 0)
+	{
+		lp->nrows = n;
+	}
+	EGLPNUM_TYPENAME_ILLraw_clear_matrix (lp);
+	if (transposed)
+		transpose (lp);
+	ILL_IFFREE (name[0], char);
+
+	EGLPNUM_TYPENAME_EGlpNumClearVar (*obj);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (*lower);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (upper[0]);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (upper[1]);
+}
+
+#if 0
+#ifndef JAVA_PORT
+static void new_row (
+	EGLPNUM_TYPENAME_QSdata * p,
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+	int rval = 0;
+	char *rowname = NULL, *rname = NULL;
+	char sense;
+	double d;
+	int ind, hit;
+
+	rval = EGLPNUM_TYPENAME_ILLread_constraint_name (state, &rname);
+	if (rname == NULL)
+	{
+		rval = 1;
+		ILLeditor_help_cmd (ROW, NEW);
+	}
+	ILL_BREAK_BODY_IF (rval);
+
+	ILLsymboltab_lookup (&lp->rowtab, rname, &ind);
+	if (ind != ILL_SYM_NOINDEX)
+	{
+		rval = EGLPNUM_TYPENAME_ILLlp_error (state, "\"%s\" is already defined.\n", rname);
+		ILL_BREAK_BODY_IF (rval);
+	}
+	ILL_UTIL_STR (rowname, rname);
+
+	rval = EGLPNUM_TYPENAME_ILLread_lp_state_sense (state);
+	sense = state->sense_val;
+	ILL_BREAK_BODY_IF (rval);
+
+	rval = EGLPNUM_TYPENAME_ILLread_lp_state_value (state, &d);
+	ILL_BREAK_BODY_IF (rval);
+
+	rval = EGLPNUM_TYPENAME_QSnew_row (p, d, sense, rowname);
+	if (rval != 0)
+	{
+		QSlog("could not add row");
+	}
+	else
+	{
+		ILLsymboltab_register (&lp->rowtab, rname, &ind, &hit);
+	}
+CLEANUP:
+	ILL_IFFREE (rowname, char);
+}
+#endif
+#endif
+
+static int del_row_or_col (
+	EGLPNUM_TYPENAME_QSdata * p,
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	int isRow)
+{
+	int i[1], rval = 0;
+	char **names = (isRow) ? p->qslp->rownames : p->qslp->colnames;
+	int nnames = (isRow) ? p->qslp->nrows : p->qslp->nstruct;
+	ILLsymboltab *tab = (isRow) ? &lp->rowtab : &lp->coltab;
+
+	rval = EGLPNUM_TYPENAME_ILLread_lp_state_next_field_on_line (state);
+	ILL_BREAK_BODY_IF (rval);
+
+	i[0] = ILLutil_array_index (names, nnames, state->field);
+	if (i[0] >= 0)
+	{
+		rval = (isRow) ? EGLPNUM_TYPENAME_QSdelete_rows (p, 1, i) : EGLPNUM_TYPENAME_QSdelete_cols (p, 1, i);
+		if (rval == 0)
+		{
+			ILLsymboltab_delete (tab, state->field);
+		}
+	}
+	else
+	{
+		rval = EGLPNUM_TYPENAME_ILLlp_error (state, "\"%s\" is not defined.\n", state->field);
+	}
+
+CLEANUP:
+	ILL_RESULT (rval, "del_row_or_col");
+}
+
+static void del_row (
+	EGLPNUM_TYPENAME_QSdata * p,
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+	int rval = del_row_or_col (p, lp, state, 1);
+
+	if (rval == 0)
+	{
+		lp->nrows--;
+	}
+}
+
+static void del_col (
+	EGLPNUM_TYPENAME_QSdata * p,
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+	int rval = del_row_or_col (p, lp, state, 0);
+
+	if (rval == 0)
+	{
+		lp->ncols--;
+	}
+}
diff --git a/qsopt_ex/editor.h b/qsopt_ex/editor.h
new file mode 100644
index 0000000..227846a
--- /dev/null
+++ b/qsopt_ex/editor.h
@@ -0,0 +1,35 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCSINFO $Id: editor_EGLPNUM_TYPENAME.h,v 1.2 2003/11/05 16:57:39 meven Exp $ */
+#ifndef EGLPNUM_TYPENAME_EDITOR_H
+#define EGLPNUM_TYPENAME_EDITOR_H
+
+extern void EGLPNUM_TYPENAME_ILLeditor_init (
+	void);
+extern void EGLPNUM_TYPENAME_ILLeditor (
+	EGLPNUM_TYPENAME_QSdata * p);
+extern int EGLPNUM_TYPENAME_ILLeditor_solve (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int salgo);
+
+#endif
diff --git a/qsopt_ex/eg_elist.h b/qsopt_ex/eg_elist.h
new file mode 100644
index 0000000..ef584d7
--- /dev/null
+++ b/qsopt_ex/eg_elist.h
@@ -0,0 +1,229 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library 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 Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
+ * */
+/* ========================================================================= */
+/** @defgroup EGeList EGeList
+ *
+ * Here we define the basic interface for a circular linked list where the list
+ * is embeded in some other structure. The ideas come from the Linux Kernel
+ * implementation of lists. This implementation is based on the philosophy of 
+ * embeded structures.
+ *
+ * 
+ * @version 0.0.1
+ * @par History:
+ * - 2005-08-19
+ * 						- Add debugging control
+ * - 2005-05-23
+ * 						- First Implementation.
+ *
+ * @note In general, the functions described bellow don't perform consistency
+ * checks. It is asumed that the user does know what is he doing.
+ *
+ * @note If you want to have some debugging control try changing the debug level
+ * at compile time, and lowering the debug level asociated to the list function
+ * as defined in eg_configure.h.
+ *
+ * */
+/** @file 
+ * @ingroup EGeList */
+/** @addtogroup EGeList */
+/** @{ */
+/** @example eg_elist.ex.c 
+ * This is a working (althought useless) example on @ref EGeList.
+ * */
+/* ========================================================================= */
+#ifndef __EG_ELIST_H__
+#define __EG_ELIST_H__
+
+#include "eg_macros.h"
+
+/* ========================================================================= */
+/** @brief debug level for lists */
+#define __EL_DEBUG_ 100
+/* ========================================================================= */
+/** @brief Null-initialized embeded list */
+#define EGeListNull ((EGeList_t){0,0})
+
+/* ========================================================================= */
+/** 
+ * @brief List Node Structure.
+ * @par Description:
+ * This structure is to store a general node of the list. It is composed by
+ * two members, that point to the next and previous structures in the list.  */
+typedef struct EGeList_t
+{
+	struct EGeList_t *next;/**< Pointer to the next structure in the list */
+	struct EGeList_t *prev;/**< Pointer to the previous structure in the list */
+}
+EGeList_t;
+
+/* ========================================================================= */
+/** @brief Initialize a given structure to point to itself (in circular
+ * fashion).
+ * @param __lpt pointer to the list to initialize. 
+ * @return the pointer to the list. */
+#define EGeListInit(__lpt) ({\
+	EGeList_t*const __EGeL_init =(__lpt);\
+	__EGeL_init->next = __EGeL_init->prev = __EGeL_init;})
+
+/* ========================================================================= */
+/** @brief Insert a __newpt __entry between two known consecutive entries.
+ * @par Description:
+ * This is only for internal list manipulation, where we know the prev/next
+ * entries already.
+ * @param __newpt pointer to the list node to insert.
+ * @param __prevpt pointer to the node to preceed the __newpt node.
+ * @param __nextpt pointer to the node to follow the __newpt node. 
+ * @return the address of __newpt.
+ * */
+#define __EGeListAdd(__newpt,__prevpt,__nextpt) ({\
+	EGeList_t*const __EGeL_add_new = (__newpt);\
+	EGeList_t*const __EGeL_add_prev = (__prevpt);\
+	EGeList_t*const __EGeL_add_next = (__nextpt);\
+	__EGeL_add_next->prev = __EGeL_add_new;\
+	__EGeL_add_prev->next = __EGeL_add_new;\
+	__EGeL_add_new->next = __EGeL_add_next;\
+	__EGeL_add_new->prev = __EGeL_add_prev;\
+	__EGeL_add_new;})
+
+/* ========================================================================= */
+/** @brief Insert a __newpt __entry after the given pointer.
+ * @param __newpt pointer to the __newpt list node to insert.
+ * @param __head pointer from where the __newpt __entry will follow.
+ * @return the pointer to the __newpt __entry in the list. 
+ * */
+#define EGeListAddAfter(__newpt,__head) __EGeListAdd(__newpt,__head,(__head)->next)
+
+/* ========================================================================= */
+/** @brief Insert a __newpt __entry before the given pointer.
+ * @param __newpt pointer to the __newpt list node to insert.
+ * @param __tailpt pointer that will follow the __newpt __entry in the list.
+ * @return the pointer to the __newpt __entry in the list. 
+ * */
+#define EGeListAddBefore(__newpt,__tailpt) __EGeListAdd(__newpt,(__tailpt)->prev,__tailpt)
+
+/* ========================================================================= */
+/** @brief Given two nodes, link them as if they would follow one another in the
+ * list (used to delete points from a list).
+ * @param __prevpt pointer to the guy to be in first in the list.
+ * @param __nextpt pointer to the guy to follow in the list.
+ * @par Description:
+ * This function is intended to be used only internally, where we know what is
+ * what, if you use it is because you also know what is going on.
+ * */
+#define __EGeListLink(__prevpt,__nextpt) ({\
+	EGeList_t* __EGeL_lnk_prev = (__prevpt);\
+	EGeList_t* __EGeL_lnk_next = (__nextpt);\
+	__EGeL_lnk_prev->next = __EGeL_lnk_next;\
+	__EGeL_lnk_next->prev = __EGeL_lnk_prev;\
+	0;})
+
+/* ========================================================================= */
+/** @brief Given a node, eliminate it from the list it bellongs. but don't
+ * change the internal data in the eliminated list (be carefull, if you will 
+ * use it afterwards, then you MUST initialize it). If debugging is enabled,
+ * then whenever you delete, the connector is reseted to 0xffffffff. What you
+ * can count on is that the connector won't be NULL after deleting it from the
+ * list, but it's values may be lost if we are debugging.
+ * @param __entry __entry to eliminate from the list.
+ * @return pointer to the deleted __entry from the list.*/
+#define EGeListDel(__entry) ({\
+	EGeList_t *const __EGeL_del_entr = (__entry);\
+	__EGeListLink(__EGeL_del_entr->prev,__EGeL_del_entr->next);\
+	if(__EL_DEBUG_ <= DEBUG) \
+		(*__EGeL_del_entr) = (EGeList_t){(EGeList_t*)0xffffffffU,\
+																		 (EGeList_t*)0xffffffffU};\
+	__EGeL_del_entr;})
+
+/* ========================================================================= */
+/** @brief Replace one __entry with another in a list.
+ * @param __oldpt __entry to be replaced, note that the pointers stored in next/prev
+ * won't be changed, this may possible lead to errors if the __entry is used
+ * afterwards without initialization.
+ * @param __newpt __newpt __entry in the list.
+ * @return pointer to the old replaced member.
+ * */
+#define EGeListReplace(__oldpt,__newpt) ({\
+	EGeList_t* __EGeL_rep_old = (__oldpt);\
+	EGeList_t* __EGeL_rep_new = (__newpt);\
+	__EGeL_rep_new->next = __EGeL_rep_old->next;\
+	__EGeL_rep_new->prev = __EGeL_rep_old->prev;\
+	__EGeL_rep_new->next->prev = __EGeL_rep_new;\
+	__EGeL_rep_new->prev->next = __EGeL_rep_new;\
+	__EGeL_rep_old;})
+
+/* ========================================================================= */
+/** @brief Move an element from one list to another (deleting it from the
+ * original one).
+ * @param __entry element to be removed from it's current list to a position 
+ * after the given __head.
+ * @param __head element to be before the moved element.
+ * */
+#define EGeListMoveAfter(__entry,__head) ({\
+	__EGeListLink((__entry)->prev,(__entry)->next);\
+	EGeListAddAfter(__entry,__head);})
+
+/* ========================================================================= */
+/** @brief Move an element from one list to another (deleting it from the
+ * original one).
+ * @param __entry element to be removed from it's current list to a position
+ * before the given __tailpt.
+ * @param __tailpt element to be after the moved element.
+ * */
+#define EGeListMoveBefore(__entry,__tailpt) ({\
+	__EGeListLink((__entry)->prev,(__entry)->next);\
+	EGeListAddBefore(__entry,__tailpt);})
+
+/* ========================================================================= */
+/** @brief test whether a list is empty (i.e. he is its own next pointer) */
+#define EGeListIsEmpty(__head) ({\
+	EGeList_t* __EGeL_emp_head = (__head);\
+	(__EGeL_emp_head == __EGeL_emp_head->next);})
+
+/* ========================================================================= */
+/** @brief move all elements in one list to the given location in a second list.
+ * Note that this function assumes that the list is represented by a pointer to
+ * an EGeList_t structure that act as a marker but that don't bellong to the
+ * list, and thus is not included in the joinded list.
+ * @param __list marker to the list to be joined with the second. Note that the
+ * fields in list won't be reinitialized, so be carefull with that, because the
+ * fields are pointing to inconsistent data as it is, if you want to reutilize
+ * the list you must call #EGeListInit before.
+ * @param __head position from where the list will be spliced in.
+ * @note Note that the original list is left in an undefined status, so before
+ * use it, it should be re-initialized.
+ * */
+#define __EGeListSplice(__list,__head) ({\
+	EGeList_t* __EGeL_spl_list = (__list);\
+	EGeList_t* __EGeL_spl_first = __EGeL_spl_list->next;\
+	EGeList_t* __EGeL_spl_last = __EGeL_spl_list->prev;\
+	EGeList_t* __EGeL_spl_head = (__head);\
+	EGeList_t* __EGeL_spl_at = __EGeL_spl_head->next;\
+	__EGeL_spl_first->prev = __EGeL_spl_head;\
+	__EGeL_spl_head->next = __EGeL_spl_first;\
+	__EGeL_spl_last->next = __EGeL_spl_at;\
+	__EGeL_spl_at->prev = __EGeL_spl_last;\
+	0;})
+#define EGeListSplice(__list,__head) ({if(!EGeListIsEmpty(__list)) __EGeListSplice(__list,__head);})
+
+/* ========================================================================= */
+/** @}*/
+/* end of eg_elist.h */
+#endif
diff --git a/qsopt_ex/eg_exact.h b/qsopt_ex/eg_exact.h
new file mode 100644
index 0000000..a8d436d
--- /dev/null
+++ b/qsopt_ex/eg_exact.h
@@ -0,0 +1,41 @@
+/* QSopt-Exact "An exact LP solver"
+ *
+ * Copyright (C) 2006 Daniel Espinoza.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library 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 Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
+ * */
+/* ========================================================================= */
+/** @mainpage QSopt-Exact Home Page
+ *
+ * @section Introduction
+ 
+<P>This is a joint project of <A HREF=http://www.dii.uchile.cl/~daespino TARGET=_top>Daniel Espinoza</A>, <A HREF=http://www.isye.gatech.edu/~wcook TARGET=_top>William Cook</A>, <A HREF=http://www.research.ibm.com/people/s/sanjeebd TARGET=_top>Sanjeeb Dash</A> and <A HREF=http://public.research.att.com/viewPage.cfm?PageID=424 TARGET=_top>David Applegate</A>.
+Also, <A HREF=http://www.zib.de/wolter/ TARGET=_top>Kati Wolter</A> has contributed with bug-fixes, bug-reports and special functionality for SCIP exact.</P>
+
+<P>The objective of this software is to provide a solver for Linear Programming (and Integer Programming to a lesser degree)  that  returns true (rational) optimal solutions.</P>
+
+<P>It relies heavilly on the <A HREF=http://www.swox.com/gmp TARGET=_top>GNUMP library</A>, that provides a multiprecision library for both floating point and also rational arithmetic.
+Note that if you use a dynamicly linked version of QSopt-Exact, then the GMP library should have been compiled with the option --enable-alloca=malloc-reentrant, this is needed to avoid memory corruption. 
+The basis for the LP solver was taken from <A HREF=http://www.isye.gatech.edu/~wcook/qsopt TARGET=_top>QSopt</A>, which is an LP solver based on floating point arithmetic and available for free for research purposes.
+A brief description of the implementation and the obtained results can be obtained <A HREF=http://www.dii.uchile.cl/~daespino/files/exact_simplex.pdf >here (pdf)</A>, and a longer description (which is part of my Ph.D. thesis) can be found <A HREF=http://www.dii.uchile.cl/~daespino/files/espinoza_daniel_g_200605_phd.pdf >here</A>
+Much of the functionality used in QSopt-Exact comes from <A HREF=http://www.dii.uchile.cl/~daespino/EGlib_doc/main.html TARGET=_self>EGlib</A>. 
+</P>
+
+<P>You can see the <A HREF=http://www.dii.uchile.cl/~daespino/QSoptExact_doc/modules.html TARGET=_self>documentation</A> or download the <A HREF=http://www.dii.uchile.cl/~daespino/SOurce/QSoptExact.tar.bz2 TARGET=_top>program source</A>.</P>
+<P>We also have made available binaries for <A HREF=http://www.dii.uchile.cl/~daespino/SOurce/QSoptExact-32.tar.bz2 TARGET=_top>linux 32 bit</A> and for <A HREF=http://www.dii.uchile.cl/~daespino/SOurce/QSoptExact-64.tar.bz2 TARGET=_top>linux 64 bit</A>
+ 
+<P>Finally, many thanks to all people that have contributed with bug-reports, comments, and help.</P>
+
+ * */
diff --git a/qsopt_ex/eg_exutil.c b/qsopt_ex/eg_exutil.c
new file mode 100644
index 0000000..5491b0d
--- /dev/null
+++ b/qsopt_ex/eg_exutil.c
@@ -0,0 +1,485 @@
+/* ========================================================================= */
+/* ESolver "Exact Mixed Integer Linear Solver" provides some basic structures 
+ * and algorithms commons in solving MIP's
+ *
+ * Copyright (C) 2005 Daniel Espinoza.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library 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 Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
+ * */
+/* ========================================================================= */
+/** @file 
+ * @ingroup Esolver */
+/** @addtogroup Esolver */
+/** @{ */
+#include "eg_exutil.h"
+
+#include "logging-private.h"
+
+/* ========================================================================= */
+/** @name EXutilStatics
+ * Variables asociated with the #EXutilApproximate function, we use them
+ * as static to save some time in intialization */
+/*@{*/
+/** @brief Array of integers used in the continued fraction method */
+static mpz_t Z[7];
+/**@brief rational remainder used in the continued fraction method */
+static mpq_t cvl;
+/* ========================================================================= */
+/** @brief Initialize the static variables at start-up */
+void EXutilDoInit (void)
+{
+	unsigned __EXui;
+	EGlpNumStart();
+	mpq_init (cvl);
+	for (__EXui = 7; __EXui--;)
+		mpz_init (Z[__EXui]);
+}
+
+/* ========================================================================= */
+/** @brief Clear all memory related to the static variables */
+void EXutilDoClear (void)
+{
+	unsigned __EXui;
+	mpq_clear (cvl);
+	for (__EXui = 7; __EXui--;)
+		mpz_clear (Z[__EXui]);
+	EGlpNumClear();
+
+}
+
+/*@}*/
+
+/* ========================================================================= */
+int EXutilIntegralize (const unsigned n,
+											 mpq_t * const  a,
+											 mpq_t b,
+											 mpq_t maxabs)
+{
+	mpz_t lcm,
+	  gcd;
+	register unsigned int i;
+	mpz_init (lcm);
+	mpz_init (gcd);
+	mpz_set (lcm, mpq_denref (b));
+	mpz_set (gcd, mpq_numref (b));
+	if (mpz_cmp_ui (gcd, 0UL) == 0)
+		mpz_set_ui (gcd, 1UL);
+	/* compute the greatest common divisor ammong the numerator of a_i and b,
+	 * and the least common multiple ammong the denominators of a_i and b */
+	for (i = n; i--;)
+	{
+		mpz_lcm (lcm, lcm, mpq_denref (a[i]));
+		mpz_gcd (gcd, gcd, mpq_numref (a[i]));
+	}
+	/* divide everything by lcm/gcd */
+	mpz_mul (mpq_numref (b), mpq_numref (b), lcm);
+	mpz_mul (mpq_denref (b), mpq_denref (b), gcd);
+	mpq_canonicalize (b);
+	mpz_abs (mpq_numref (maxabs), mpq_numref (b));
+	for (i = n; i--;)
+	{
+		mpz_mul (mpq_denref (a[i]), mpq_denref (a[i]), gcd);
+		mpz_mul (mpq_numref (a[i]), mpq_numref (a[i]), lcm);
+		mpq_canonicalize (a[i]);
+		if (mpz_cmpabs (mpq_numref (maxabs), mpq_numref (a[i])) < 0)
+			mpz_abs (mpq_numref (maxabs), mpq_numref (a[i]));
+	}
+	/* ending */
+	mpz_set_ui (mpq_denref (maxabs), 1UL);
+	mpz_clear (gcd);
+	mpz_clear (lcm);
+	return 0;
+}
+
+/* ========================================================================= */
+int EXutilSimplify (const unsigned n,
+										mpq_t * const  a,
+										mpq_t b)
+{
+	register unsigned i;
+	mpq_t maxabs;
+	mpq_init (maxabs);
+	EXutilIntegralize (n, a, b, maxabs);
+	/* normalize the cut so that |(a,b)|_inf == 1 */
+	if (mpz_cmp_ui (mpq_numref (maxabs), 0UL))
+	{
+		mpq_div (b, b, maxabs);
+		for (i = n; i--;)
+			mpq_div (a[i], a[i], maxabs);
+	}
+	/* ending */
+	mpq_clear (maxabs);
+	return 0;
+}
+
+/* ========================================================================= */
+void mpq_GomoryCoeff (mpq_t rop,
+											mpq_t coef,
+											unsigned const is_int,
+											int const bound,
+											unsigned const cut_mlt,
+											mpq_t b_frac)
+{
+	mpq_t fj;
+	mpq_init (fj);
+	mpq_set_ui (rop, 0UL,1UL);
+	/* if the variable is integer */
+	if (is_int)
+	{
+		if (mpq_IsInteger (coef))
+		{
+			mpq_set (rop, coef);
+			mpq_EGlpNumMultUiTo (rop, cut_mlt);
+			mpq_EGlpNumMultTo (rop, b_frac);
+		}
+		/* if the variable is integer, but the coefficient id fractional */
+		else
+		{
+			mpq_set (fj, coef);
+			mpq_EGlpNumMultUiTo (fj, cut_mlt);
+			mpq_FracPart (fj, fj);
+			/* if the variable is complemented to its lower bound */
+			if (bound == 'L')
+			{
+				if (mpq_cmp (fj, b_frac) <= 0)
+				{
+					mpq_set (rop, coef);
+					mpq_EGlpNumMultUiTo (rop, cut_mlt);
+					mpq_EGlpNumFloor (rop, rop);
+					mpq_EGlpNumMultTo (rop, b_frac);
+					mpq_EGlpNumAddTo (rop, fj);
+				}
+				else
+				{
+					mpq_set (rop, coef);
+					mpq_EGlpNumMultUiTo (rop, cut_mlt);
+					mpq_EGlpNumCeil (rop, rop);
+					mpq_EGlpNumMultTo (rop, b_frac);
+				}
+			}
+			/* if the variable is complemented to its upper bound */
+			else
+			{
+				mpq_EGlpNumSubTo (fj, mpq_oneLpNum);
+				mpq_neg (fj, fj);
+				if (mpq_cmp (fj, b_frac) <= 0)
+				{
+					mpq_set (rop, coef);
+					mpq_EGlpNumMultUiTo (rop, cut_mlt);
+					mpq_EGlpNumCeil (rop, rop);
+					mpq_EGlpNumMultTo (rop, b_frac);
+					mpq_EGlpNumSubTo (rop, fj);
+				}
+				else
+				{
+					mpq_set (rop, coef);
+					mpq_EGlpNumMultUiTo (rop, cut_mlt);
+					mpq_EGlpNumFloor (rop, rop);
+					mpq_EGlpNumMultTo (rop, b_frac);
+				}
+			}
+		}
+	}
+	/* if the variable is continuous */
+	else
+	{
+		/* if the variable is complemented to its lower bound */
+		if (bound == 'L')
+		{
+			if (mpq_cmp_ui (coef, 0UL,1UL) > 0)
+			{
+				mpq_set (rop, coef);
+				mpq_EGlpNumMultUiTo (rop, cut_mlt);
+			}
+		}
+		/* if the variable is complemented to its upper bound */
+		else
+		{
+			if (mpq_cmp_ui (coef, 0UL,1UL) < 0)
+			{
+				mpq_set (rop, coef);
+				mpq_EGlpNumMultUiTo (rop, cut_mlt);
+			}
+		}
+	}
+	/* done */
+	mpq_clear (fj);
+}
+
+/* ========================================================================= */
+int EXutilExpandLogicals (mpq_QSdata * const act_lp,
+													mpq_t *  const vector,
+													mpq_t b,
+													mpq_ILLlp_rows * const lprows)
+{
+	const int n_rows = act_lp->qslp->nrows;
+	const int n_struct = act_lp->qslp->nstruct;
+	int const *const rowmap = act_lp->qslp->rowmap;
+	mpq_t * const rhs = act_lp->qslp->rhs;
+	mpq_ILLmatrix *const A = &(act_lp->qslp->A);
+	int rowbeg;
+	int rowcnt;
+	int *rowind;
+	mpq_t * rowval;
+	register int i,
+	  k;
+	for (i = n_rows; i--;)
+	{
+		/* convert the vector */
+		if (mpz_cmp_ui (mpq_numref (vector[i + n_struct]), 0UL))
+		{
+			rowbeg = lprows->rowbeg[i];
+			rowcnt = lprows->rowcnt[i];
+			rowind = lprows->rowind + rowbeg;
+			rowval = lprows->rowval + rowbeg;
+			/* we use slack again as the multiplier that we need to add the
+			 * row to the current vector so as to make dissapear the slack */
+			mpq_neg (cvl, vector[i + n_struct]);
+			mpq_div (cvl, cvl, A->matval[A->matbeg[rowmap[i]]]);
+			MESSAGE (EX_UTIL_VERBOSE + 100, "Replacing constraint %s with multiple"
+							 " %lf from integer part", act_lp->qslp->rownames[i],
+							 mpq_get_d (cvl));
+			mpq_EGlpNumAddInnProdTo (b, rhs[i], cvl);
+			for (k = rowcnt; k--;)
+				mpq_EGlpNumAddInnProdTo (vector[rowind[k]], cvl, rowval[k]);
+			mpq_set_ui (vector[i + n_struct], 0UL, 1UL);
+		}
+	}
+	return 0;
+}
+
+/* ========================================================================= */
+void EXutilApproximate (mpq_t var,
+												mpq_t ori,
+												unsigned const max_den)
+{
+	/* local variables */
+	unsigned lsng = mpz_cmp_ui (mpq_numref (ori), 0UL) < 0 ? 1U : 0U;
+	int i;
+	mpq_t __lpnum__;
+	mpq_init(__lpnum__);
+	/* check if the given number is zero, if so, set to zero var and return */
+	if (mpz_cmp_ui (mpq_numref (ori), 0UL) == 0)
+	{
+		return;
+	}
+	/* if not, then we have some work to do */
+	/* now we initialize the internal numbers */
+	mpq_abs (cvl, ori);
+	for (i = 7; i--;)
+		mpz_set_ui (Z[i], 0UL);
+	mpz_set_ui (Z[0], 1UL);
+	mpz_set_ui (Z[4], 1UL);
+	mpz_fdiv_q (Z[1], mpq_numref (cvl), mpq_denref (cvl));
+	mpq_set_z (__lpnum__, Z[1]);
+	mpq_sub (cvl, cvl, __lpnum__);
+	/* now we loop until the next t's is more than mpf_eps */
+	/* the formula is 
+	 * p_i = t_i*p_{i-1} + p_{i-2}, and 
+	 * q_i = t_i*q_{i-1} + q_{i-2} 
+	 * note that |x-p_i/q_i|<1/q_i^2
+	 * for us t_i = Z[6], and the current number is either [0,1,2] in the Z
+	 * array, we use those popsitions ciclicly, and use the four position as a
+	 * temporary number, Z+4 is used to store q's, at the beginning i = 1. */
+	while (1)
+	{
+		if (mpq_cmp_ui (cvl, 1UL, (unsigned long)max_den) < 0 || (mpz_cmp_ui (Z[4], (unsigned long)max_den) > 0))
+		{
+			mpz_set (mpq_denref (var), Z[4]);
+			mpz_set (mpq_numref (var), Z[1]);
+			break;
+		}
+		/* first run */
+		mpq_inv (cvl, cvl);
+		mpz_fdiv_q (Z[6], mpq_numref (cvl), mpq_denref (cvl));
+		mpq_set_z (__lpnum__, Z[6]);
+		mpq_sub (cvl, cvl, __lpnum__);
+		mpz_set (Z[2], Z[0]);
+		mpz_addmul (Z[2], Z[1], Z[6]);
+		mpz_set (Z[5], Z[3]);
+		mpz_addmul (Z[5], Z[4], Z[6]);
+		if (mpq_cmp_ui (cvl, 1UL, (unsigned long)max_den) < 0 || (mpz_cmp_ui (Z[5], (unsigned long)max_den) > 0))
+		{
+			mpz_set (mpq_denref (var), Z[5]);
+			mpz_set (mpq_numref (var), Z[2]);
+			break;
+		}
+		/* second run */
+		mpq_inv (cvl, cvl);
+		mpz_fdiv_q (Z[6], mpq_numref (cvl), mpq_denref (cvl));
+		mpq_set_z (__lpnum__, Z[6]);
+		mpq_sub (cvl, cvl, __lpnum__);
+		mpz_set (Z[0], Z[1]);
+		mpz_addmul (Z[0], Z[2], Z[6]);
+		mpz_set (Z[3], Z[4]);
+		mpz_addmul (Z[3], Z[5], Z[6]);
+		if (mpq_cmp_ui (cvl, 1UL, (unsigned long)max_den) < 0 || (mpz_cmp_ui (Z[3], (unsigned long)max_den) > 0))
+		{
+			mpz_set (mpq_denref (var), Z[3]);
+			mpz_set (mpq_numref (var), Z[0]);
+			break;
+		}
+		/* third run */
+		mpq_inv (cvl, cvl);
+		mpz_fdiv_q (Z[6], mpq_numref (cvl), mpq_denref (cvl));
+		mpq_set_z (__lpnum__, Z[6]);
+		mpq_sub (cvl, cvl, __lpnum__);
+		mpz_set (Z[1], Z[2]);
+		mpz_addmul (Z[1], Z[0], Z[6]);
+		mpz_set (Z[4], Z[5]);
+		mpz_addmul (Z[4], Z[3], Z[6]);
+	}
+	/* ending */
+	mpq_canonicalize (var);
+	if (lsng)
+		mpq_neg (var, var);
+	/* clean-up */
+	mpq_clear(__lpnum__);
+	return;
+}
+
+/* ========================================================================= */
+void EXutilOverEstimate (mpq_t var,
+												 mpq_t ori,
+												 unsigned const max_den)
+{
+	EXutilApproximate (var, ori, max_den);
+	/* check if var is < ori, if so, we must add one to the numerator */
+	if (mpq_cmp (ori, var) > 0)
+	{
+		mpq_set_ui (cvl, 1UL, (unsigned long)(max_den * max_den));
+		mpq_add (var, var, cvl);
+		EXIT (mpq_cmp (ori, var) > 0, "Imposible!");
+	}
+	return;
+}
+
+/* ========================================================================= */
+void EXutilNicefy (mpq_QSdata * const act_prob,
+									 const unsigned char *const var_stat,
+									 const unsigned max_den,
+									 mpq_t *  a,
+									 mpq_t b,
+									 int const sense)
+{
+	const unsigned square = max_den * max_den;
+	const int nstruct = act_prob->qslp->nstruct;
+	const int *const  structmap = act_prob->qslp->structmap;
+	mpq_t *const  lower = act_prob->qslp->lower;
+	mpq_t *const  upper = act_prob->qslp->upper;
+	mpq_t num1,
+	  num2;
+	register int i;
+	int colid = 0;
+	int sign = 0;
+	unsigned cur_stat = 0;
+	mpq_init (num1);
+	mpq_init (num2);
+	if (sense != 'L' && sense != 'G')
+		return;
+	/* we internally assume that the inequality is of the form ax >= b */
+	if (sense == 'L')
+	{
+		mpq_neg (b, b);
+		for (i = nstruct; i--;)
+			mpq_neg (a[i], a[i]);
+	}
+	/* now we first approximate each coefficient */
+	for (i = nstruct; i--;)
+	{
+		colid = structmap[i];
+		cur_stat = var_stat[colid];
+		/* if the variables is not bounded, we can't nicefy the coefficient */
+		if ((cur_stat & (EX_STATUS_UB | EX_STATUS_LB)) == 0)
+			continue;
+		/* if the numerator is less than square, there is nothing to do */
+		if (mpz_cmp_ui (mpq_denref (a[i]), (unsigned long)square) <= 0)
+			continue;
+		EXutilApproximate (num1, a[i], max_den);
+		mpq_sub (num2, num1, a[i]);
+		sign = mpz_cmp_ui (mpq_numref (num2), 0UL);
+		/* depending on the side that the approximation land we see what we have to
+		 * do, first case, num1 > a[i] */
+	REDO:
+		if (sign > 0)
+		{
+			/* if the variable is bounded bellow, we just update the RHS and set the
+			 * coefficient */
+			if (cur_stat & EX_STATUS_LB)
+			{
+				EXIT ((mpq_EGlpNumIsEqqual (lower[colid], mpq_ILL_MINDOUBLE)),
+							"Imposible");
+				mpq_EGlpNumAddInnProdTo (b, num2, lower[colid]);
+				mpq_set (a[i], num1);
+			}
+			/* otherwise, we can't approximate by above, but we have to approximate
+			 * by bellow */
+			else
+			{
+				mpq_set_ui (num2, 1UL, (unsigned long)square);
+				mpq_sub (num1, num1, num2);
+				mpq_sub (num2, num1, a[i]);
+				sign = mpz_cmp_ui (mpq_numref (num2), 0UL);
+				goto REDO;
+			}
+		}
+		/* otherwise, we have that num1 < a[i] */
+		else if (sign < 0)
+		{
+			/* if the variable is bounded by above, we just update the RHS and set
+			 * the coefficient */
+			if (cur_stat & EX_STATUS_UB)
+			{
+				EXIT ((mpq_EGlpNumIsEqqual (upper[colid], mpq_ILL_MAXDOUBLE)),
+							"Imposible");
+				mpq_EGlpNumAddInnProdTo (b, num2, upper[colid]);
+				mpq_set (a[i], num1);
+			}
+			/* otherwise, we can't approximate by bellow, but we have to approximate
+			 * by above. */
+			else
+			{
+				mpq_set_ui (num2, 1UL, (unsigned long)square);
+				mpq_add (num1, num1, num2);
+				mpq_sub (num2, num1, a[i]);
+				sign = mpz_cmp_ui (mpq_numref (num2), 0UL);
+				goto REDO;
+			}
+		}
+	}
+	/* now we round the RHS, we do this by adding the constraint 0 >= -1 */
+	EXutilApproximate (num1, b, max_den);
+	if (mpq_cmp (num1, b) > 0)
+	{
+		mpq_set_ui (num2, 1UL, (unsigned long)square);
+		mpq_sub (num1, num1, num2);
+	}
+	mpq_set (b, num1);
+	/* before ending, we return the constraint to its normal form */
+	if (sense == 'L')
+	{
+		mpq_neg (b, b);
+		for (i = nstruct; i--;)
+			mpq_neg (a[i], a[i]);
+	}
+	/* ending */
+	mpq_clear (num2);
+	mpq_clear (num1);
+	return;
+}
+
+/* ========================================================================= */
+/** @} */
+/* end eg_exutil.c */
diff --git a/qsopt_ex/eg_exutil.h b/qsopt_ex/eg_exutil.h
new file mode 100644
index 0000000..7855184
--- /dev/null
+++ b/qsopt_ex/eg_exutil.h
@@ -0,0 +1,317 @@
+/* ========================================================================= */
+/* ESolver "Exact Mixed Integer Linear Solver" provides some basic structures 
+ * and algorithms commons in solving MIP's
+ *
+ * Copyright (C) 2005 Daniel Espinoza.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library 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 Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
+ * */
+/* ========================================================================= */
+#ifndef __EG_EX_UTIL__
+#define __EG_EX_UTIL__
+
+#include <stdlib.h>
+
+#include "eg_lpnum.h"
+#include "eg_io.h"
+
+#include "qstruct_mpq.h"
+#include "lpdata_mpq.h"
+
+/** @file 
+ * @ingroup Esolver */
+/** @addtogroup Esolver */
+/** @{ */
+/* ========================================================================= */
+/** @brief status for variables that are logicals */
+#define EX_STATUS_LGC 1U
+
+/* ========================================================================= */
+/** @brief status for variables that are structural */
+#define EX_STATUS_STR 2U
+
+/* ========================================================================= */
+/** @brief status for variables that are integer */
+#define EX_STATUS_INT 4U
+
+/* ========================================================================= */
+/** @brief status for variables that bounded from below */
+#define EX_STATUS_LB 8U
+
+/* ========================================================================= */
+/** @brief status for variables that bounded from above */
+#define EX_STATUS_UB 16U
+
+/* ========================================================================= */
+/** @brief status for integer variable fixed at its upper bound. This status is
+ * not defined while calling cut callbacks. */
+#define EX_STATUS_FIX_UB 32U
+
+/* ========================================================================= */
+/** @brief status for integer variable fixed at its lower bound. This status is
+ * not defined while calling cut callbacks. */
+#define EX_STATUS_FIX_LB 64U
+
+/* ========================================================================= */
+/** @brief status for integer variable among our set of selected integer
+ * variables. This status is not defined while calling cut callbacks. */
+#define EX_STATUS_BESTFRAC 128U
+
+/* ========================================================================= */
+/** @brief given a cut ax <=> b, write it in integer form ,i.e. set all a,b to
+ * integer in such a way that a_i and b are all relativelly prime. 
+ * @param n size of the a vector.
+ * @param a RHS of the inequality
+ * @param b LHS of the inequality.
+ * @param maxabs return the maximum absolute value among all resulting a_i,b.
+ * @return zero on success, non-zero otherwise.
+ * */
+int EXutilIntegralize (const unsigned n,
+											 mpq_t * const  a,
+											 mpq_t b,
+											 mpq_t maxabs);
+
+/* ========================================================================= */
+/** @brief verbosity level */
+#define EX_UTIL_VERBOSE 100
+
+/* ========================================================================= */
+/** @brief given two vectors (a,b) and (v,w), compute its inner product and
+ * store it into rop.
+ * @param dim dimmension of the a and v part of the vector.
+ * @param a first part of the first vector.
+ * @param b second part of the first vector.
+ * @param v first part of the second vector.
+ * @param w second part of the second vector.
+ * @param rop where we store the result.
+ * @note we may take a == v and/or b == w.
+ * */
+#define EXutilInnProd(dim,a,b,v,w,rop) do{\
+	register unsigned __EXuti = (dim);\
+	mpq_mul(rop,b,w);\
+	while(__EXuti--) mpq_EGlpNumAddInnProdTo(rop,(a)[__EXuti],(v)[__EXuti]);\
+	} while(0);
+
+/* ========================================================================= */
+/** @brief Compute the number of non-zeros in a given vector. 
+ * @param dim size of the a vector.
+ * @param a vector where we are operating.
+ * @param rop where to return the number of non-zeros (it should be an integer
+ * variable, not a pointer to such a variable) */
+#define EXutilNzSz(dim,a,rop) do{\
+	register unsigned __EXuti = (dim);\
+	rop = 0;\
+	while(__EXuti--) if(mpz_cmp_ui(mpq_numref((a)[__EXuti]),0UL)) rop++;}while(0)
+
+/* ========================================================================= */
+/** @brief Compute the L_1 norm of a given vector. 
+ * @param dim size of the a vector.
+ * @param a vector where we are operating.
+ * @param rop where to retirn the L1 norm value */
+#define EXutilL1Norm(dim,a,rop) do{\
+	mpq_t*const  __EXuta = (a);\
+	mpq_t __qtmp__;\
+	register unsigned __EXuti = (dim);\
+	mpq_init(__qtmp__);\
+	mpq_set_ui(rop,0UL,1UL);\
+	while(__EXuti--){\
+		mpq_abs(__qtmp__,__EXuta[__EXuti]);\
+		mpq_add(rop,rop,__qtmp__);}mpq_clear(__qtmp__);}while(0)
+
+/* ========================================================================= */
+/** @brief given a cut ax <=> b, write it in normalized form ,i.e. set all a,b 
+ * to integer in such a way that a_i and b are all relativelly prime, and
+ * divide them all over the
+ * maximum such (a_i,b) (so that the infinity norm of (a,b) is one. 
+ * @param n size of the a vector.
+ * @param a RHS of the inequality
+ * @param b LHS of the inequality.
+ * @return zero on success, non-zero otherwise.
+ * */
+int EXutilSimplify (const unsigned n,
+										mpq_t * const  a,
+										mpq_t b);
+
+/* ========================================================================= */
+/** @brief asign to the first number the fractional part of the second, i.e.
+ * 	\f$ rop = op1 - \lfloor op1 \rfloor \f$.
+ * 	@param rop where to retunr our result.
+ * 	@param op1 number for wich we want to compute its fractional part */
+#define mpq_FracPart(rop, op1) do{\
+	mpz_fdiv_r (mpq_numref (rop), mpq_numref (op1), mpq_denref (op1));\
+	mpz_set (mpq_denref (rop), mpq_denref (op1));\
+	mpq_canonicalize((rop));\
+} while(0)
+
+/* ========================================================================= */
+/** @brief test if the given number is integer.
+ * @param op number to test.
+ * @return one if the nummber is integer, zero- otherwise. */
+#define mpq_IsInteger(op) ({\
+	(mpz_cmp(mpq_denref(op),mpz_oneLpNum)==0);})
+
+/* ========================================================================= */
+/** @brief round to \f$-\infty\f$ the given number to the closest fraction 
+ * of the form \f$a/2^{exp}\f$ from bellow.
+ * @param op number to round.
+ * @param exp exponent to use in the fraction */
+#define mpq_FroundExp(op,exp) do{\
+			mpz_t __ztmp__;\
+			mpz_init(__ztmp__);\
+			mpz_mul_2exp(__ztmp__,mpq_numref((op)),(exp));\
+			mpz_fdiv_q(mpq_numref((op)),__ztmp__,mpq_denref((op)));\
+			mpz_mul_2exp(mpq_denref((op)),mpz_oneLpNum,(exp));\
+			mpq_canonicalize((op));mpz_clear(__ztmp__);}while(0)
+
+/* ========================================================================= */
+/** @brief round to \f$+\infty\f$ the given number to the closest fraction 
+ * of the form \f$a/2^{exp}\f$ from above.
+ * @param op number to round.
+ * @param exp exponent to use in the fraction */
+#define mpq_CroundExp(op,exp) do{\
+			mpz_t __ztmp__;\
+			mpz_init(__ztmp__);\
+			mpz_mul_2exp(__ztmp__,mpq_numref((op)),(exp));\
+			mpz_cdiv_q(mpq_numref((op)),__ztmp__,mpq_denref((op)));\
+			mpz_mul_2exp(mpq_denref((op)),mpz_oneLpNum,(exp));\
+			mpq_canonicalize((op));mpz_clear(__ztmp__);}while(0)
+
+/* ========================================================================= */
+/** @brief round to \f$0\f$ the given number to the closest fraction 
+ * of the form \f$a/2^{exp}\f$ towards zero.
+ * @param op number to round.
+ * @param exp exponent to use in the fraction */
+#define mpq_TroundExp(op,exp) do{\
+			mpz_t __ztmp__;\
+			mpz_init(__ztmp__);\
+			mpz_mul_2exp(__ztmp__,mpq_numref((op)),(exp));\
+			mpz_tdiv_q(mpq_numref((op)),__ztmp__,mpq_denref((op)));\
+			mpz_mul_2exp(mpq_denref((op)),mpz_oneLpNum,(exp));\
+			mpq_canonicalize((op));mpz_clear(__ztmp__);}while(0)
+
+/* ========================================================================= */
+/** @brief compute the gomory coefficient of the variable given the original
+ * coefficient, the multiplier, and all relevant information.
+ * @param rop Where we return the gomory coefficient. (it should be different
+ * location than the original coefficient).
+ * @param coef original coefficient in the equality that we are using to
+ * derive the gomory cut.
+ * @param is_int this is either zero (indicating that the variable asociated
+ * with this coefficient is continuous) or one (indicating that the variable
+ * asociated with this coeffcient is integer).
+ * @param bound indicate if this variable was complemented to its lower bound
+ * (then L) or to its upper bound (then U), any other value will generate an
+ * error.
+ * @param cut_mlt multiplier to use to the coefficient (and thus the effective
+ * coefficient would be coef*cut_mlt).
+ * @param b_frac fractional part of the RHS in the equation (after
+ * complementing variables). */
+void mpq_GomoryCoeff (mpq_t rop,
+											mpq_t coef,
+											unsigned const is_int,
+											int const bound,
+											unsigned const cut_mlt,
+											mpq_t b_frac);
+
+/* ========================================================================= */
+/** @brief Given a vector in QSopt external form, and a row description of the
+ * related LP, re-write the vector using only real variables, we do that by
+ * substracting the equation defining the logical variable multiplied by the
+ * coefficient of the logical variable in the vector to the vector.
+ * @param act_lp lp where we are working.
+ * @param vector vector of length at least nrows + nstruct where we want to
+ * replace all logical coefficients.
+ * @param lprows row description of the given LP.
+ * @param rhs if we look at vector,rhs as an inequality, then we eliminate the
+ * slack coefficient form the inequality as a whole.
+ * @return zero on success, non-zero otherwise.
+ * */
+int EXutilExpandLogicals (mpq_QSdata * const act_lp,
+													mpq_t *  const vector,
+													mpq_t rhs,
+													mpq_ILLlp_rows * const lprows);
+
+/* ========================================================================= */
+/** @brief Approximate <A HREF=http://mathworld.wolfram.com/ContinuedFraction.html TARGET=_top>using continued fractions method</A> a given rational 
+ * \f$\frac{a}{b} \f$ with another rational \f$\frac{a'}{b'}\f$ that satisfy 
+ * that \f$ b' < max_den^2 \f$ and also 
+ * \f$|\frac{a}{b} - \frac{a'}{b'}|\leq\frac1{max_den^2}\f$.
+ * @param ori original coefficient that we want to represent as a/b with b <=
+ * max_den^2. 
+ * @param dest we return here the resulting number. 
+ * @param max_den maximum allowed denominator in the new representation. */
+void EXutilApproximate (mpq_t dest,
+												mpq_t ori,
+												unsigned const max_den);
+
+/* ========================================================================= */
+/** @brief Overestimate the given coefficient by another rational that is
+ * representble with denominators not bigger than max_den^2.
+ * @param ori original coefficient that we want to represent as a/b with b <=
+ * max_den^2. 
+ * @param dest we return here the resulting number, note that we always
+ * insure that the returned value is bigger than the original value. 
+ * @param max_den maximum allowed denominator in the new representation. */
+void EXutilOverEstimate (mpq_t dest,
+												 mpq_t ori,
+												 unsigned const max_den);
+
+/* ========================================================================= */
+/** @brief Given an inequality, we try to re-write so that no denominator is
+ * bigger than the square of the given number, and ensuring validity. for 
+ * coefficients that can't be `nacified' we leave them intact. the process 
+ * imply adding multiples of the bounds on variables, and at the end, nicify 
+ * the rhs of the inequality.
+ * @param max_den the square of this value is the maximum denominator allowed.
+ * @param a hand side of the inequality.
+ * @param sense sense of the inequality, it should be either 'L' or 'G'.
+ * @param b right hand side of the inequality.
+ * @param act_prob LP from where we draw the bounds on the variables.
+ * @param var_stat status (as defined in #EXmipinfo_t::var_stat) for all
+ * variables in the LP, in the internal QSopt ordering. 
+ * @note The length of the a vector is at least nstruct, and we assume that
+ * entry a[k] corresnpond to the coefficient associated with the k-th
+ * structural variable inside. */
+void EXutilNicefy (mpq_QSdata * const act_prob,
+									 const unsigned char *const var_stat,
+									 const unsigned max_den,
+									 mpq_t *  a,
+									 mpq_t b,
+									 int const sense);
+
+/* ========================================================================= */
+/** @brief given a variable in internal number, return a pointer to its name.
+ * @param iid internal ordering number.
+ * @param QSlp pointer to the mpq_QSdata structure containing the LP.
+ * @param QSinv_map pointer to an array containing the inverse map from internal
+ * numbering to external numbering as in #EXmipinfo_t::inv_map.
+ * @return pointer to its name.
+ * @note If the variable is a slack variable, it return the name of the
+ * inequality. */ 
+#define EXutilIidToStr(iid,QSlp,QSinv_map) ({\
+	mpq_QSdata*const __EXlp = (QSlp);\
+	const int __EXeid = (QSinv_map)[(iid)];\
+	(__EXeid >= __EXlp->qslp->nstruct) ? __EXlp->qslp->rownames[__EXeid - __EXlp->qslp->nstruct] : __EXlp->qslp->colnames[__EXeid];})
+
+/* ========================================================================= */
+/** @brief Initialize the static variables at start-up */
+extern void EXutilDoInit (void);
+/* ========================================================================= */
+/** @brief Clear all memory related to the static variables */
+extern void EXutilDoClear (void);
+/* ========================================================================= */
+/** @} */
+/* end eg_exutil.h */
+#endif
diff --git a/qsopt_ex/eg_io.c b/qsopt_ex/eg_io.c
new file mode 100644
index 0000000..8dc53cd
--- /dev/null
+++ b/qsopt_ex/eg_io.c
@@ -0,0 +1,695 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library 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 Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * */
+/** @file
+ * @ingroup EGio */
+/** @addtogroup EGio */
+/** @{ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef HAVE_LIBBZ2
+# include <bzlib.h>
+#endif
+
+#ifdef HAVE_LIBZ
+# include <zlib.h>
+#endif
+
+#include "logging-private.h"
+
+#include "eg_io.h"
+
+/* file-types: */
+#define EGIO_PLAIN 0
+#define EGIO_ZLIB  1
+#define EGIO_BZLIB 2
+
+/* ========================================================================= */
+/** @brief Given a string 'input' this function uses EGioParse to separate
+ * up to N words in it, we assume that argc is an array of pointers to strings
+ * of size N, and note that the input array will be changed. */
+void EGioNParse (char *input,
+								 int max_argc,
+								 const char *delim,
+								 const char *comment,
+								 int *argc,
+								 char **argv)
+{
+	const size_t clen = strlen(comment);
+	const size_t dlen = strlen(delim);
+	char __EGiobuff[256] = 
+		"20000000000000000000000000000000" /* 000-031 */
+		"11111111111111111111111111111111" /* 032-063 */
+		"11111111111111111111111111111111" /* 064-095 */
+		"11111111111111111111111111111110" /* 096-127 */
+		"00000000000000000000000000000000" /* 128-159 */
+		"00000000000000000000000000000000" /* 160-191 */
+		"00000000000000000000000000000000" /* 192-223 */
+		"00000000000000000000000000000000";/* 224-255 */
+	int i, EGiostat = 0, cc;
+	char *cur;
+	/* set convertion table */
+	for( i = clen ; i-- ; )
+	{
+		cc = comment[i];
+		if(cc>31 && cc<127) __EGiobuff[cc] = '2';
+	}
+	for( i = dlen ; i-- ; )
+	{
+		cc = delim[i];
+		if(cc>31 && cc<127) __EGiobuff[cc] = '0';
+	}
+	/* now parse */
+	*argc = EGiostat = 0;
+	cur = input;
+	while(cur && (*argc) < max_argc)
+	{
+		cc = __EGiobuff[(int)(*cur)];
+		switch(cc)
+		{
+			case '1':
+				if(!EGiostat) argv[(*argc)++] = cur;
+				EGiostat = 1;
+				cur++;
+				break;
+			case '0':
+				EGiostat = 0;
+				*(cur++) = '\0';
+				break;
+			case '2':
+				*cur = '\0';
+				cur = 0;
+				break;
+			default:
+				EXIT(1,"Imposible, cc=%c, cur = %c, pos %zd",cc, *cur, cur-input);
+		}
+	}
+	/* cleanup */
+	for( i = clen ; i-- ; )
+	{
+		cc = comment[i];
+		if(cc>31 && cc<127) __EGiobuff[cc] = '1';
+	}
+	for( i = dlen ; i-- ; )
+	{
+		cc = delim[i];
+		if(cc>31 && cc<127) __EGiobuff[cc] = '1';
+	}
+	return;
+}
+
+/* given two *pointers 'next' and 'current' and a constant set  
+ * of strings (parse delimiters), it store in 'next the next 
+ * meaningfull string, and in current the rest of the secuence, 
+ * the idea is to iterate over 'next' while it is not true; 
+ * you have to store the original pointer to the string stream 
+ * elsewere; also, we assume that the original stream is 
+ * terminated with '\0'; also, it will discaard any sub-string 
+ * that start with #, that is inteded for discard comments.
+ * NOTE: this function WILL change the original string!!!!!
+ * There is no guarantee on how it will be changed. */
+void EGioParse (char **next,
+								char **current,
+								const char *delim,
+								const char *comment)
+{
+	/* local variables */
+	const size_t clen = strlen(comment);
+	const size_t dlen = strlen(delim);
+	char __EGiobuff[256] = 
+		"20000000000000000000000000000000" /* 000-031 */
+		"11111111111111111111111111111111" /* 032-063 */
+		"11111111111111111111111111111111" /* 064-095 */
+		"11111111111111111111111111111110" /* 096-127 */
+		"00000000000000000000000000000000" /* 128-159 */
+		"00000000000000000000000000000000" /* 160-191 */
+		"00000000000000000000000000000000" /* 192-223 */
+		"00000000000000000000000000000000";/* 224-255 */
+	int i, EGiostat = 0, cc;
+	char *cur;
+	/* set convertion table */
+	for( i = clen ; i-- ; )
+	{
+		cc = comment[i];
+		if(cc>31 && cc<127) __EGiobuff[cc] = '2';
+	}
+	for( i = dlen ; i-- ; )
+	{
+		cc = delim[i];
+		if(cc>31 && cc<127) __EGiobuff[cc] = '0';
+	}
+	/* parse */
+	*next = 0;
+	cur = *current;
+	while(cur)
+	{
+		cc = __EGiobuff[(int)(*cur)];
+		switch(cc)
+		{
+			case '1':
+				if(!EGiostat) *next = cur;
+				EGiostat = 1;
+				cur++;
+				break;
+			case '0':
+				*(cur++) = '\0';
+				if(EGiostat)
+				{
+					*current = cur;
+					cur = 0;
+				}
+				EGiostat = 0;
+				break;
+			case '2':
+				*cur = '\0';
+				*current = cur = 0;
+				break;
+			default:
+				EXIT(1,"Imposible, cc=%c, cur = %c, pos %zd",cc, *cur, cur-*current);
+		}
+	}
+	/* cleanup */
+	for( i = clen ; i-- ; )
+	{
+		cc = comment[i];
+		if(cc>31 && cc<127) __EGiobuff[cc] = '1';
+	}
+	for( i = dlen ; i-- ; )
+	{
+		cc = delim[i];
+		if(cc>31 && cc<127) __EGiobuff[cc] = '1';
+	}
+	return;
+}
+
+/* this discard all lines starting with comments and stores the next 
+ * leading line in current and the next token in next, we assume that next 
+ * does not contain data, and that current store the remainings of the
+ * current line */
+void EGioDisCom (char **next,
+								 char **current,
+								 const char *delim,
+								 const char *comment,
+								 char *store,
+								 unsigned int storeSize,
+								 FILE * in)
+{
+	/* local variables */
+	int status = 1;
+
+	/* if no current line we read it from the file */
+	if (!(*current))
+	{
+		status = (store == fgets (store, (int) storeSize, in));
+		*current = store;
+	}
+	/* we process the current line, and while the line does
+	 * not have a token we look the next line */
+	EGioParse (next, current, delim, comment);
+	while (!(*next) && status)
+	{
+		status = (store == fgets (store, (int) storeSize, in));
+		*current = store;
+		EGioParse (next, current, delim, comment);
+	}
+	/* ending */
+	return;
+}
+
+/* ========================================================================= */
+void EGdisplayString (void *str,
+											FILE * file)
+{
+	fprintf (file, "%s", (char *) str);
+}
+
+/* ========================================================================= */
+int EGioReadLine(char*const str,size_t const max_len, FILE*file)
+{
+	char *rc = fgets(str,max_len,file);
+	int rval = !rc;
+	FTESTG(rval, CLEANUP,"Nothing to be read");
+	CLEANUP:
+	return rval;
+	/*
+	int c=0;
+	size_t len = max_len ;
+	while(((c=getc(file))!=EOF) && (c!='\n') && --len)
+	{
+		str[max_len-1-len] = (char)c;
+	}
+	str[max_len-len] = '\0';
+	FTEST((max_len - len)==0 && c!= '\n',"Nothing to be read"); 
+	return 0;
+	*/
+}
+/* ========================================================================= */
+int EGioReadNamedDblPlusParam(const int argc,
+															char**argv,
+															const char*const name,
+															double*const param,
+															int*const has_param,
+															int*const rval)
+{
+	const size_t len = strlen(name)+5;
+	int fail=0;
+	*rval = 0;
+	if(argc<1) return 0;
+	if(strncmp(argv[0],name,len)==0)
+		{
+			FTESTG((fail=(argc!=2)),CLEANUP,"%s has not 2 tokens",name);
+			FTESTG((fail=(*has_param)),CLEANUP,"%s keyword repeated",name);
+			*param = strtod(argv[1],0);
+			FTESTG((fail=((*param)<0)),CLEANUP,"%s should be positive,"
+						"is %lf",name,*param);
+			*has_param = 1;
+			return 1;
+		}
+	else
+		return 0;
+	CLEANUP:
+	*rval=1;
+	return fail;
+}
+/* ========================================================================= */
+int EGioReadNamedIntPlusParam(const int argc,
+															char**argv,
+															const char*const name,
+															int*const param,
+															int*const has_param,
+															int*const rval)
+{
+	const size_t len = strlen(name)+5;
+	int fail=0;
+	*rval = 0;
+	if(argc<1) return 0;
+	if(strncmp(argv[0],name,len)==0)
+		{
+			FTESTG((fail=(argc!=2)),CLEANUP,"%s has not 2 tokens",name);
+			FTESTG((fail=(*has_param)),CLEANUP,"%s keyword repeated",name);
+			*param = atoi(argv[1]);
+			FTESTG((fail=((*param)<1)),CLEANUP,"%s should be positive,"
+						"is %d",name,*param);
+			*has_param = 1;
+			return 1;
+		}
+	else
+		return 0;
+	CLEANUP:
+	*rval=1;
+	return fail;
+}
+/* ========================================================================= */
+int EGioReadNamedIntNNParam(const int argc,
+														char**argv,
+														const char*const name,
+														int*const param,
+														int*const has_param,
+														int*const rval)
+{
+	const size_t len = strlen(name)+5;
+	int fail=0;
+	*rval = 0;
+	if(argc<1) return 0;
+	if(strncmp(argv[0],name,len)==0)
+		{
+			FTESTG((fail=(argc!=2)),CLEANUP,"%s has not 2 tokens",name);
+			FTESTG((fail=(*has_param)),CLEANUP,"%s keyword repeated",name);
+			*param = atoi(argv[1]);
+			FTESTG((fail=((*param)<0)),CLEANUP,"%s should be positive,"
+						"is %d",name,*param);
+			*has_param = 1;
+			return 1;
+		}
+	else
+		return 0;
+	CLEANUP:
+	*rval=1;
+	return fail;
+}
+/* ========================================================================= */
+int EGioReadNamedStringParam(const int argc,
+															char**argv,
+															const char*const name,
+															char**const param,
+															int*const has_param,
+															int*const rval)
+{
+	const size_t len = strlen(name)+5;
+	int fail=0;
+	*rval = 0;
+	if(argc<1) return 0;
+	if(strncmp(argv[0],name,len)==0)
+		{
+			FTESTG((fail=(argc!=2)),CLEANUP,"%s has not 2 tokens",name);
+			FTESTG((fail=(*has_param)),CLEANUP,"%s keyword repeated",name);
+			if(param) *param = strdup(argv[1]);
+			*has_param = 1;
+			return 1;
+		}
+	else
+		return 0;
+	CLEANUP:
+	*rval=1;
+	return fail;
+}
+/* ========================================================================= */
+int EGioReadNamedParam( const int argc,
+												char**argv,
+												const char*const name,
+												int*const has_param,
+												int*const rval)
+{
+	const size_t len = strlen(name)+5;
+	int fail=0;
+	*rval = 0;
+	if(argc<1) return 0;
+	if(strncmp(argv[0],name,len)==0)
+		{
+			FTESTG((fail=(argc!=1)),CLEANUP,"%s has not 1 token",name);
+			FTESTG((fail=(*has_param)),CLEANUP,"%s keyword repeated",name);
+			*has_param = 1;
+			return 1;
+		}
+	else
+		return 0;
+	CLEANUP:
+	*rval=1;
+	return fail;
+}
+/* ========================================================================= */
+
+int EGioReadIntParam( const int argc,
+											char**argv,
+											int*const param,
+											int*const rval)
+{
+	*rval = 0;
+	if(argc<1) return 0;
+	FTESTG((argc!=1),CLEANUP,"line has not 1 token");
+	*param = atoi(argv[0]);
+	return 0;
+	CLEANUP:
+	*rval=1;
+	return 1;
+}
+/* ========================================================================= */
+#define EGio_BUFSIZE 4096
+/* ========================================================================= */
+struct EGioFile_st {int type; void*file;};
+/* ========================================================================= */
+int EGioWrite(EGioFile_t*file,const char*const string)
+{
+	char buf[EGio_BUFSIZE];
+	int len;
+	buf[EGio_BUFSIZE-1] = 0;
+	snprintf(buf,EGio_BUFSIZE,"%s",string);
+	len = strlen(buf);
+	if(len<=0 || len >= EGio_BUFSIZE || buf[EGio_BUFSIZE-1]!=0) return 0;
+	switch(file->type)
+	{
+		case EGIO_PLAIN:
+			return fwrite(buf, (size_t)1, (size_t)len, (FILE*)(file->file));
+		case EGIO_ZLIB:
+#ifdef HAVE_LIBZ
+			return gzwrite((gzFile)(file->file),buf,(unsigned)len);
+#else
+			QSlog("no zlib support");
+			return 0;
+#endif
+		case EGIO_BZLIB:
+#ifdef HAVE_LIBBZ2
+			return BZ2_bzwrite((BZFILE*)(file->file),buf,len);
+#else
+			QSlog("no bzip2 support");
+			return 0;
+#endif
+		default:
+			QSlog("UNKNOWN FILE TYPE %d", file->type);
+			return 0;
+	}
+}
+/* ========================================================================= */
+int EGioPrintf(EGioFile_t*file,const char* format, ...)
+{
+	char buf[EGio_BUFSIZE];
+	va_list va;
+	buf[EGio_BUFSIZE-1]=0;
+	va_start(va,format);
+	vsnprintf(buf,EGio_BUFSIZE,format,va);
+	va_end(va);
+	return EGioWrite(file,buf);
+}
+/* ========================================================================= */
+EGioFile_t* EGioOpenFILE(FILE*ifile)
+{
+	EGioFile_t* file= (EGioFile_t*)malloc(sizeof(EGioFile_t));
+	if(!file) goto CLEANUP;
+	file->type = EGIO_PLAIN;
+	file->file = ifile;
+	if(!file->file)
+	{
+		free(file);
+		file = 0;
+	}
+	CLEANUP:
+	return file;
+}
+/* ========================================================================= */
+EGioFile_t* EGioOpen(const char *path, const char *mode)
+{
+	char lmode[8];
+	int len = strlen(path);
+	EGioFile_t* file= (EGioFile_t*)malloc(sizeof(EGioFile_t));
+	if(!file) goto CLEANUP;
+	if(len>3 && path[len-3] == '.' && path[len-2] == 'g' && path[len-1] == 'z')
+	{
+		file->type = EGIO_ZLIB;
+		if(index(mode,'b')) snprintf(lmode,7,"%s",mode);
+		else snprintf(lmode,7,"%s9b",mode);
+	}
+	else if(len>4 && path[len-4] == '.' && path[len-3] == 'b' && path[len-2] == 'z' && path[len-1] == '2')
+	{
+		file->type = EGIO_BZLIB;
+		if(index(mode,'b')) snprintf(lmode,7,"%s",mode);
+		else snprintf(lmode,7,"%sb",mode);
+	}
+	else 
+	{
+		file->type = EGIO_PLAIN;
+		snprintf(lmode,7,"%s",mode);
+	}
+	switch(file->type)
+	{
+		case EGIO_PLAIN:
+			file->file = fopen(path,lmode);
+			break;
+		case EGIO_ZLIB:
+#ifdef HAVE_LIBZ
+			file->file = gzopen(path,lmode);
+#else
+			QSlog("no zlib support");
+			file->file = 0;
+#endif
+			break;
+		case EGIO_BZLIB:
+#ifdef HAVE_LIBBZ2
+			file->file = BZ2_bzopen(path,lmode);
+#else
+			QSlog("no bzip2 support");
+			file->file = 0;
+#endif
+			break;
+		default:
+			QSlog("UNKNOWN FILE TYPE %d",file->type);
+			file->file = 0;
+			break;
+	}
+	if(!file->file)
+	{
+		const int __EGserrno = errno;
+		free(file);
+		errno = __EGserrno;
+		return NULL;
+	}
+	CLEANUP:
+	return file;
+}
+/* ========================================================================= */
+int EGioClose(EGioFile_t*file)
+{
+	int rval = 0;
+	if(!file) return 0;
+	switch(file->type)
+	{
+		case EGIO_PLAIN:
+			if( (((FILE*)(file->file)) != stdin) &&
+					(((FILE*)(file->file)) != stdout) &&
+					(((FILE*)(file->file)) != stderr))
+				rval = fclose((FILE*)(file->file));
+			break;
+		case EGIO_ZLIB:
+#ifdef HAVE_LIBZ
+			rval = gzclose((gzFile)(file->file));
+#else
+			QSlog("no zlib support");
+			rval = EOF;
+#endif
+			break;
+		case EGIO_BZLIB:
+#ifdef HAVE_LIBBZ2
+			BZ2_bzerror((BZFILE*)(file->file),&rval);
+			BZ2_bzclose((BZFILE*)(file->file));
+#else
+			QSlog("no bzip2 support");
+			rval =  EOF;
+#endif
+			break;
+		default:
+			QSlog("UNKNOWN FILE TYPE %d", file->type);
+			rval = EOF;
+			break;
+	}
+	free(file);
+	return rval;
+}
+/* ========================================================================= */
+int EGioFlush(EGioFile_t*file)
+{
+	switch(file->type)
+	{
+		case EGIO_PLAIN:
+			return fflush((FILE*)(file->file));
+		case EGIO_ZLIB:
+#ifdef HAVE_LIBZ
+			/*return gzflush((gzFile)(file->file),Z_FINISH);*/
+			return 0;
+#else
+			QSlog("no zlib support");
+			return EOF;
+#endif
+		case EGIO_BZLIB:
+#ifdef HAVE_LIBBZ2
+			return 0;
+#else
+			QSlog("no bzip2 support");
+			return EOF;
+#endif
+		default:
+			QSlog("UNKNOWN FILE TYPE %d", file->type);
+			return EOF;
+	}
+}
+/* ========================================================================= */
+char* EGioGets(char*buf, int len, EGioFile_t*file)
+{
+	char*b = buf;
+	switch(file->type)
+	{
+		case EGIO_PLAIN:
+			return fgets(buf,len,(FILE*)(file->file));
+		case EGIO_ZLIB:
+#ifdef HAVE_LIBZ
+			return gzgets((gzFile)(file->file),buf,len);
+#else
+			QSlog("no zlib support");
+			return NULL;
+#endif
+		case EGIO_BZLIB:
+#ifdef HAVE_LIBBZ2
+			if(buf == 0 || len <=0 ) return NULL;
+			while( --len > 0 && BZ2_bzread(((BZFILE*)(file->file)), buf, 1) == 1 && *buf++ != '\n') ;
+			*buf = '\0';
+			return b == buf && len >0 ? NULL : b ;
+#else
+			QSlog("no bzip2 support");
+			return NULL;
+#endif
+		default:
+			QSlog("UNKNOWN FILE TYPE %d", file->type);
+			return NULL;
+	}
+}
+/* ========================================================================= */
+int EGioEof(const EGioFile_t*const file)
+{
+	int err;
+	switch(file->type)
+	{
+		case EGIO_PLAIN:
+			return feof((FILE*)(file->file));
+		case EGIO_ZLIB:
+#ifdef HAVE_LIBZ
+			return gzeof((gzFile)(file->file));
+#else
+			QSlog("no zlib support");
+			return 1;
+#endif
+		case EGIO_BZLIB:
+#ifdef HAVE_LIBBZ2
+			BZ2_bzerror(((BZFILE*)(file->file)),&err);
+			return err == BZ_STREAM_END;
+#else
+			QSlog("no bzip2 support");
+			return 1;
+#endif
+		default:
+			QSlog("UNKNOWN FILE TYPE %d", file->type);
+			return 1;
+	}
+}
+/* ========================================================================= */
+int EGioError(const EGioFile_t*const file)
+{
+	int errnum;
+	switch(file->type)
+	{
+		case EGIO_PLAIN:
+			return ferror((FILE*)(file->file));
+		case EGIO_ZLIB:
+#ifdef HAVE_LIBZ
+			gzerror((gzFile)(file->file),&errnum);
+			return errnum;
+#else
+			QSlog("no zlib support");
+			return 1;
+#endif
+		case EGIO_BZLIB:
+#ifdef HAVE_LIBBZ2
+			BZ2_bzerror(((BZFILE*)(file->file)),&errnum);
+			return errnum;
+#else
+			QSlog("no bzip2 support");
+			return 1;
+#endif
+		default:
+			QSlog("UNKNOWN FILE TYPE %d", file->type);
+			return 1;
+	}
+}/* ========================================================================= */
+/** @} */
diff --git a/qsopt_ex/eg_io.h b/qsopt_ex/eg_io.h
new file mode 100644
index 0000000..8680606
--- /dev/null
+++ b/qsopt_ex/eg_io.h
@@ -0,0 +1,338 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library 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 Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * */
+
+/* ========================================================================= */
+/** @defgroup EGio EGio
+ * input/output utilities
+ *
+ * Version 0.0.2 2003-05-09 (Marcos)
+ *
+ * Added the function EGioNParse to get a more argc, argv feel.
+ * Also: Changed EGioParse so that it ignores multiple sequential delimiters.
+ * 
+ * Version 0.0.1 2003-04-11
+ * - 2004-08-17
+ * 					-	Add EGdisplayString function.
+ * - 2006-08-16
+ * 					- Add EGioReadLine function.
+ * - 2007-12-06
+ * 					- Add EGioReadxxxParam functions
+ * - 2009-10-19
+ * 					- Add bzlib/zlib/plain text interface
+ * */
+/** @file
+ * @ingroup EGio */
+/** @addtogroup EGio */
+/** @{
+ * @example eg_ebtree.ex.c
+ * This is an example of writing to a zlib-compresed file
+ *
+ * @example eg_min_cut.ex.c
+ * This is an example of reading files, either plain, bz2 or gz
+ * */
+/* ========================================================================= */
+
+#ifndef __EG_IO_H__
+#define __EG_IO_H__
+
+#include "eg_macros.h"
+
+/* ========================================================================= */
+/** @brief safe open function, it test that we can open the given file with the
+ * given mode, if an error occurs, display it on screen and exit, otherwise,
+ * return the open file stream.
+ * @param __file file name to open (is a const char*)
+ * @param __mode mode to use to open the file (is a const char*)
+ * @return FILE* stream */
+#define EGsfopen(__file,__mode) ({\
+	const char*__EGsfile = (__file);\
+	const char*__EGsmode = (__mode);\
+	FILE*__EGsFILE = fopen(__EGsfile,__EGsmode);\
+	if(!__EGsFILE)\
+	{\
+		const int __EGserrno = errno;\
+		fprintf(stderr,"fopen() failed with error code %d, error\n%s",__EGserrno,strerror(__EGserrno));\
+		MESSAGE(0,"Could not open %s with mode %s", __EGsfile, __EGsmode);\
+		exit(__EGserrno);\
+	}\
+	__EGsFILE;})
+
+/* ========================================================================= */
+/**@brief type of functions for display, receives a void* to the structure to print,
+ * and a *FILE where to output */
+typedef void (*EGdisplay_f) (void *, FILE *);
+#define EGnullDisplay ((EGdisplay_f)0)
+
+/* ========================================================================= */
+/** @brief type of functions for display, receives a void* to the structure to print, a
+ * *FILE where to output, and a set of offsets for datas, the length of that
+ * array must be know by the user. */
+typedef void (*EGdisplayOS_f) (void *,
+															 FILE *,
+															 size_t *);
+
+/* ========================================================================= */
+/** @brief Given a string 'input' this function uses EGioParse to separate
+ * up to N words in it, we assume that argc is an array of pointers to strings
+ * of size N, and note that the input array will be changed. */
+void EGioNParse (char *input,
+								 int max_argc,
+								 const char *delim,
+								 const char *comment,
+								 int *argc,
+								 char **argv);
+
+/* ========================================================================= */
+/** @brief given two *pointers 'next' and 'current' and a constant set 
+ * of strings (parse delimiters), it store in 'next the next 
+ * meaningfull string, and in current the rest of the secuence, 
+ * the idea is to iterate over 'next' while it is not true; 
+ * you have to store the original pointer to the string stream 
+ * elsewere; also, we assume that the original stream is 
+ * terminated with '\0'; also, it will discaard any sub-string 
+ * that start with #, that is inteded for discard comments */
+void EGioParse (char **next,
+								char **current,
+								const char *delim,
+								const char *coment);
+
+/* ========================================================================= */
+/** @brief read a line from an input stream.
+ * @param str where to store the line.
+ * @param max_len maximum allowed length.
+ * @param file stream from where we read the input
+ * @return zero on success, non-zero otherwise, errors are cast when we can not
+ * read from the given file.
+ * */
+int EGioReadLine(char*const str,size_t const max_len, FILE*file);
+
+/* ========================================================================= */
+/** @brief read a named string parameter, this function checks that we have two
+ * parameters, and check if we had previously readed the parameter, if an error
+ * occurs, report it in the given rval 
+ * @param argc number of tokens in the current line
+ * @param argv array of strings of tokens
+ * @param name named of the parameter
+ * @param param where to save the parameter (if null, don't save it)
+ * @param has_param if we had the parameter before, should be one, if not,
+ * should be zero, if successfull, then it will be set to one.
+ * @param rval return value if an error while reading occurs.
+ * @return one if we found the parameter in the line, or if we had an error
+ * while reading the named parameter, zero otherwise. */
+int EGioReadNamedStringParam( const int argc,
+															char**argv,
+															const char*const name,
+															char**const param,
+															int*const has_param,
+															int*const rval);
+/* ========================================================================= */
+/** @brief read a named, non-negative, integer parameter, this function checks that we have two
+ * parameters, and check if we had previously readed the parameter, if an error
+ * occurs, report it in the given rval 
+ * @param argc number of tokens in the current line
+ * @param argv array of strings of tokens
+ * @param name named of the parameter
+ * @param param where to save the parameter (if null, don't save it)
+ * @param has_param if we had the parameter before, should be one, if not,
+ * should be zero, if successfull, then it will be set to one.
+ * @param rval return value if an error while reading occurs.
+ * @return one if we found the parameter in the line, or if we had an error
+ * while reading the named parameter, zero otherwise. */
+int EGioReadNamedIntNNParam(const int argc,
+															char**argv,
+															const char*const name,
+															int*const param,
+															int*const has_param,
+															int*const rval);
+/* ========================================================================= */
+/** @brief read a named, strictly positive, integer parameter, this function checks that we have two
+ * parameters, and check if we had previously readed the parameter, if an error
+ * occurs, report it in the given rval 
+ * @param argc number of tokens in the current line
+ * @param argv array of strings of tokens
+ * @param name named of the parameter
+ * @param param where to save the parameter (if null, don't save it)
+ * @param has_param if we had the parameter before, should be one, if not,
+ * should be zero, if successfull, then it will be set to one.
+ * @param rval return value if an error while reading occurs.
+ * @return one if we found the parameter in the line, or if we had an error
+ * while reading the named parameter, zero otherwise. */
+int EGioReadNamedIntPlusParam(const int argc,
+															char**argv,
+															const char*const name,
+															int*const param,
+															int*const has_param,
+															int*const rval);
+/* ========================================================================= */
+/** @brief read a named positive double parameter, this function checks that we have two
+ * parameters, and check if we had previously readed the parameter, if an error
+ * occurs, report it in the given rval 
+ * @param argc number of tokens in the current line
+ * @param argv array of strings of tokens
+ * @param name named of the parameter
+ * @param param where to save the parameter (if null, don't save it)
+ * @param has_param if we had the parameter before, should be one, if not,
+ * should be zero, if successfull, then it will be set to one.
+ * @param rval return value if an error while reading occurs.
+ * @return one if we found the parameter in the line, or if we had an error
+ * while reading the named parameter, zero otherwise. */
+int EGioReadNamedDblPlusParam(const int argc,
+															char**argv,
+															const char*const name,
+															double*const param,
+															int*const has_param,
+															int*const rval);
+/* ========================================================================= */
+/** @brief read a named parameter, this function checks that we have one
+ * parameter, and check if we had previously readed the parameter, if an error
+ * occurs, report it in the given rval 
+ * @param argc number of tokens in the current line
+ * @param argv array of strings of tokens
+ * @param name named of the parameter
+ * @param has_param if we had the parameter before, should be one, if not,
+ * should be zero, if successfull, then it will be set to one.
+ * @param rval return value if an error while reading occurs.
+ * @return one if we found the parameter in the line, or if we had an error
+ * while reading the named parameter, zero otherwise. */
+int EGioReadNamedParam( const int argc,
+												char**argv,
+												const char*const name,
+												int*const has_param,
+												int*const rval);
+/* ========================================================================= */
+/** @brief read an integer parameter, this function checks that we have one
+ * parameter, if an error
+ * occurs, report it in the given rval 
+ * @param argc number of tokens in the current line
+ * @param argv array of strings of tokens
+ * @param param named of the parameter
+ * should be zero, if successfull, then it will be set to one.
+ * @param rval return value if an error while reading occurs.
+ * @return one if we found the parameter in the line, or if we had an error
+ * while reading the named parameter, zero otherwise. */
+int EGioReadIntParam( const int argc,
+											char**argv,
+											int*const param,
+											int*const rval);
+
+/* ========================================================================= */
+/** @name Zlib, BZlib compability interface:
+ * This functions pretend to provide a common interface to work with plain or
+ * compresed files. Up to now, we implement zlib and plain text handling, as
+ * well as basic input/output handling. */
+/* @{ */
+/* ========================================================================= */
+/* ========================================================================= */
+struct EGioFile_st;
+typedef struct EGioFile_st EGioFile_t;
+/* ========================================================================= */
+/* comon functions */
+/* ========================================================================= */
+/** @brief Converts, formats, and writes the args to the file under control 
+ * of the format string, as in fprintf.
+ * @return the number of bytes actually written (0 in case of error).
+ * @note The number of bytes written is limited to 4095 (inherited from
+ * gzprintf). The caller should assure that this limit is not exceeded.
+ * If it is exceeded, then EGioprintf() will return return an error (0) with 
+ * nothing written. In this case, there may also be a buffer overflow with
+ * unpredictable consequences, which is possible only if zlib was compiled
+ * with the insecure functions sprintf() or vsprintf() because the secure
+ * snprintf() or vsnprintf() functions were not available. For more details,
+ * see zlib's manual. */
+int EGioPrintf(EGioFile_t*file,const char *format, ...);
+int EGioWrite(EGioFile_t*file,const char* buf);
+/* ========================================================================= */
+/** @brief open a file for read or write as in fopen. if the file name ends
+ * with gz, it will (try to) use gzFile mode, if not, it will use regular FILE
+ * modes 
+ * @return on success, pointer to an EGioFile_t structure, if can not open
+ * file, it will print system error on screen and exit execution. */
+EGioFile_t* EGioOpen(const char *path, const char *mode);
+/* ========================================================================= */
+/** @brief open a C stdandard file FILE as an EGioFile_t, it can be used to
+ * open stderr, stdout, stdin, it will use plain access to the file. At
+ * closing, it will not close the three standard stdout, stderr, stdin, but
+ * other files will be closed.
+ * @param file pointer to a std-c FILE structure
+ * @return pointer to a EGioFile_t structure, linked to the given file.
+ * @note we assume that file points to an already opened file.
+ * */
+EGioFile_t* EGioOpenFILE(FILE*file);
+/* ========================================================================= */
+/** @brief close file, flush all pending information, free all internally
+ * allocated information.
+ * @return zero on success; non-zero otherwise
+ * */
+int EGioClose(EGioFile_t*file);
+/* ========================================================================= */
+/** @brief flush all un-writed information into the file.
+ * @return zero on success, non-zero otherwise. */
+int EGioFlush(EGioFile_t*file);
+/* ========================================================================= */
+/** @brief reads bytes from file until len-1 characters are read, or a newline
+ * character is read and transferred to buf, or an end-of-file condition is
+ * encountered. The string is then terminated with a null character.
+ * @return buf on success, 0 otherwise. 
+ * */
+char* EGioGets(char*buf, int len, EGioFile_t*file);
+/* ========================================================================= */
+/** @brief Test if the given file stream pointer point to the end of file.
+ * @return non-zero if stream pointer points to end of file, 0 otherwise.
+ * */
+int EGioEof(const EGioFile_t*const file);
+/* ========================================================================= */
+/** @brief Test if the given file stream has an internal error flag
+ * @return zero if no error detected, otherwise, return the apropiate error
+ * code */
+int EGioError(const EGioFile_t*const file);
+/* ========================================================================= */
+/* end interface for zlib-compresed files */
+/* @} */
+/* ========================================================================= */
+/** @name Deprecated Functions
+ * All functions here are marked as deprecated, and may be discontinued in
+ * sub-sequent releases */
+/* @{ */
+/* ========================================================================= */
+/** @brief this discard all lines starting with comments and stores the next 
+ * leading line in current and the next token in next, we assume that next 
+ * does not contain data, and that current store the remainings of the
+ * current line */
+void EGioDisCom (char **next,
+								 char **current,
+								 const char *delim,
+								 const char *coment,
+								 char *store,
+								 unsigned int storeSize,
+								 FILE * in);
+/* ========================================================================= */
+/** @brief display function for strings
+ * @param str pointer to a null terminated string of chars.
+ * @param file pointer to a stream where we write the string.
+ * @par Description:
+ * This function just print the string on the file, it won't add a '\n' at the
+ * end. */
+void EGdisplayString (void *str,
+											FILE * file);
+
+/* @} */
+/* ========================================================================= */
+/** @} */
+#endif
diff --git a/qsopt_ex/eg_lpnum.c b/qsopt_ex/eg_lpnum.c
new file mode 100644
index 0000000..bd957cd
--- /dev/null
+++ b/qsopt_ex/eg_lpnum.c
@@ -0,0 +1,905 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library 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 Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
+ * */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <stdint.h>
+
+#include <gmp.h>
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "eg_memslab.h"
+#include "eg_nummacros.h"
+
+/** @file
+ * @ingroup EGlpNum */
+/** @addtogroup EGlpNum */
+/** @{ */
+/* ========================================================================= */
+/** @brief This constant define the acuracy required while
+ * converting doubles to rationals, a good number is 1e-5. More exactly, we 
+ * stop the continued fraction method whenever the next e_i-[e_i] computed is
+ * less than EGLPNUM_MINEPS. Note that this value can't be smaller than
+ * 1/ULONG_MAX, otherwise we will have problems in the confertion step. */
+#ifndef EGLPNUM_MINEPS
+#define EGLPNUM_MINEPS 0x1ep-20
+#else
+#if EGLPNUM_MINEPS < 3e-10
+#undef EGLPNUM_MINEPS
+#define EGLPNUM_MINEPS 3e-10
+#endif
+#endif
+
+
+/* ========================================================================= */
+/** @brief if non-zero, use slab-pool allocator for GMP, otherwise, use malloc/
+ * realloc / free, */
+#ifndef EG_LPNUM_MEMSLAB
+#define EG_LPNUM_MEMSLAB 1
+#endif
+/* ========================================================================= */
+/** @brief type-dependant constants and helper numbers @{ */
+mpz_t __zeroLpNum_mpz__;
+mpz_t __oneLpNum_mpz__;
+mpz_t __MaxLpNum_mpz__;
+mpz_t __MinLpNum_mpz__;
+mpq_t __zeroLpNum_mpq__;
+mpq_t __oneLpNum_mpq__;
+mpq_t __MaxLpNum_mpq__;
+mpq_t __MinLpNum_mpq__;
+mpf_t __zeroLpNum_mpf__;
+mpf_t __MaxLpNum_mpf__;
+mpf_t __MinLpNum_mpf__;
+mpf_t __oneLpNum_mpf__;
+mpf_t mpf_eps;
+unsigned long int EGLPNUM_PRECISION = 128;
+
+/** @} */
+
+/* ========================================================================= */
+static int __EGlpNum_setup=0;
+/* ========================================================================= */
+/** @name data to handle memory allocations within gmp */
+/** @{*/
+#define __GMP_MEM_VERBOSE 100
+#define __GMP_MEM_STATS__ 0
+#define __GMP_MEM_MAX__ 256
+static const uint8_t _EGgmpPlTable[257] = \
+	{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,	/* pool for 0-16 bytes */
+		1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,	/* pool for 17-32 bytes */
+		2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,	/* pool for 33-64 bytes */
+		2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+		3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,	/* pool for 65-128 bytes */
+		3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+		3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+		3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+		4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,	/* pool for 129-255 bytes */
+		4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+		4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+		4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+		4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+		4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+		4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+		4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4};
+static const size_t _EGgmpPlSz[5] = {16,32,64,128,256};
+#define __GMP_MEM_NPOOL__ 5
+EGmemSlabPool_t EGgmpPl[__GMP_MEM_NPOOL__];
+#if __GMP_MEM_STATS__
+static size_t __alloc_sz[__GMP_MEM_NPOOL__] = {0,0,0,0,0};
+static size_t __rlloc_sz[__GMP_MEM_NPOOL__] = {0,0,0,0,0};
+static size_t __totmem = 0;
+static size_t __maxmem = 0;
+static size_t __nallocs = 0;
+static size_t __nrllocs = 0;
+static size_t __nalarge = 0;
+static size_t __nrlarge = 0;
+static size_t __laaverage=0;
+static size_t __lraverage=0;
+#endif
+/** @}*/
+/* ========================================================================= */
+#if __GMP_MEM_STATS__
+#define _TACC(__m) do{\
+	__totmem += __m;\
+	if(__totmem > __maxmem) __maxmem = __totmem;}while(0)
+#else
+#define _TACC(__m)
+#endif
+/* ========================================================================= */
+#if __GMP_MEM_STATS__
+#define _AACC(__a) do{\
+	__nallocs++;\
+	if((__a) <= __GMP_MEM_MAX__)\
+		__alloc_sz[_EGgmpPlTable[__a]]++;\
+	else{\
+		__nalarge++;\
+		__laaverage += (__a);}}while(0)
+#else
+#define _AACC(__a)
+#endif
+/* ========================================================================= */
+/** @brief dummy malloc function for gmp, at this stage is used for 
+ * creating an account of the allocation */
+static void* __EGgmp_malloc(size_t sz)
+{
+	void*ptr = 0;
+	_TACC(sz);
+	_AACC(sz);
+	if(sz <= __GMP_MEM_MAX__)
+	{
+		ptr = EGmemSlabPoolAlloc(EGgmpPl+_EGgmpPlTable[sz]);
+		MESSAGE(__GMP_MEM_VERBOSE,"alloc %p [%zd]",ptr, sz);
+		return ptr;
+		/*memset(ptr,0,sz);*/
+	}
+	else
+	{
+		ptr = malloc(sz);
+		if(!ptr) EXIT(1,"No more memory");
+		MESSAGE(__GMP_MEM_VERBOSE,"alloc %p [%zd]",ptr, sz);
+		return ptr;
+	}
+	/*QSlog("allocating %p [%zd]",ptr,sz);*/
+	/*return ptr;*/
+}
+/* ========================================================================= */
+#if __GMP_MEM_STATS__
+#define _RACC(__a) do{\
+	__nrllocs++;\
+	if(__a<__GMP_MEM_MAX__)\
+		__rlloc_sz[_EGgmpPlTable[__a]]++;\
+	else{\
+		__nrlarge++;\
+		__lraverage += (__a);}}while(0)
+#else
+#define _RACC(__a)
+#endif
+/* ========================================================================= */
+/** @brief dummy realloc for gmp */
+static void* __EGgmp_realloc(void*ptr,size_t osz,size_t nsz)
+{
+	const size_t a1 = nsz > __GMP_MEM_MAX__ ? __GMP_MEM_NPOOL__ : _EGgmpPlTable[nsz];
+	const size_t a2 = osz > __GMP_MEM_MAX__ ? __GMP_MEM_NPOOL__ : _EGgmpPlTable[osz];
+	const size_t msz = nsz > osz ? osz : nsz;
+	void*rptr=0;
+	#if __GMP_MEM_STATS__
+	_RACC(nsz);
+	__totmem -= osz;
+	_TACC(nsz);
+	#endif
+	if(a1 < __GMP_MEM_NPOOL__)
+	{
+		if(a2 == a1)
+		{
+			rptr = ptr;
+			MESSAGE(__GMP_MEM_VERBOSE,"realloc %p [%zd] to %p [%zd]",ptr, osz, rptr, nsz);
+			return rptr;
+		}
+		else
+		{
+			rptr = EGmemSlabPoolAlloc(EGgmpPl+a1);
+			memcpy(rptr,ptr,msz);
+			if(a2 < __GMP_MEM_NPOOL__)
+			{
+				MESSAGE(__GMP_MEM_VERBOSE,"realloc %p [%zd] to %p [%zd]",ptr, osz, rptr, nsz);
+				EGmemSlabPoolFree(ptr);
+				return rptr;
+			}
+			else
+			{
+				MESSAGE(__GMP_MEM_VERBOSE,"realloc %p [%zd] to %p [%zd]",ptr, osz, rptr, nsz);
+				EGfree(ptr);
+				return rptr;
+			}
+		}
+	}
+	else if(a2 < __GMP_MEM_NPOOL__)
+	{
+		rptr = EGmalloc(nsz);
+		memcpy(rptr,ptr,msz);
+		MESSAGE(__GMP_MEM_VERBOSE,"realloc %p [%zd] to %p [%zd]",ptr, osz, rptr, nsz);
+		EGmemSlabPoolFree(ptr);
+		return rptr;
+	}
+	else
+	{
+		rptr = EGrealloc(ptr,nsz);
+		MESSAGE(__GMP_MEM_VERBOSE,"realloc %p [%zd] to %p [%zd]",ptr, osz, rptr, nsz);
+		return rptr;
+	}
+	/*QSlog("Re-allocating %p [%zd] to %p [%zd]",ptr,osz,rptr,nsz);*/
+	/*return rptr;*/
+}
+/* ========================================================================= */
+/** @brief dummy free for gmp */
+static void __EGgmp_free(void*ptr,size_t sz)
+{
+	const size_t a = sz > __GMP_MEM_MAX__ ? __GMP_MEM_NPOOL__ : _EGgmpPlTable[sz];
+	#if __GMP_MEM_STATS__
+	__totmem -= sz;
+	#endif
+	MESSAGE(__GMP_MEM_VERBOSE,"freeing %p",ptr);
+	if(a<__GMP_MEM_NPOOL__)
+	{
+		EGmemSlabPoolFree(ptr);
+		return;
+	}
+	else
+	{
+		EGfree(ptr);
+		return;
+	}
+}
+
+/* ========================================================================= */
+/*void EGlpNumStart(void) __attribute__ ((constructor));*/
+void EGlpNumStart(void)
+{
+	int rval=0;
+	register int i;
+	if(__EGlpNum_setup) return;
+	if(EG_LPNUM_MEMSLAB)
+	{
+		for( i = __GMP_MEM_NPOOL__ ; i-- ; )
+		{
+			EGmemSlabPoolInit(EGgmpPl+i,_EGgmpPlSz[i],0,0);
+			rval = EGmemSlabPoolSetParam(EGgmpPl+i,EG_MSLBP_FREEFREE,0);
+			EXIT(rval,"Unknown error");
+		}
+		mp_set_memory_functions(__EGgmp_malloc, __EGgmp_realloc, __EGgmp_free);
+	}
+
+	mpf_set_default_prec (EGLPNUM_PRECISION);
+	mpz_init (__zeroLpNum_mpz__);
+	mpz_init (__oneLpNum_mpz__);
+	mpz_init (__MaxLpNum_mpz__);
+	mpz_init (__MinLpNum_mpz__);
+	mpz_set_ui (__zeroLpNum_mpz__, (unsigned long int)0);
+	mpz_set_ui (__oneLpNum_mpz__, (unsigned long int)1);
+	mpq_init (__MaxLpNum_mpq__);
+	mpq_init (__MinLpNum_mpq__);
+	mpf_init (__MaxLpNum_mpf__);
+	mpf_init (__MinLpNum_mpf__);
+	mpf_init (__zeroLpNum_mpf__);
+	mpf_init (__oneLpNum_mpf__);
+	mpf_set_ui(__MaxLpNum_mpf__,1UL);
+	mpf_set_si(__MinLpNum_mpf__,-1L);
+	mpf_mul_2exp(__MaxLpNum_mpf__,__MaxLpNum_mpf__,4096);
+	/*mpf_mul_2exp(__MaxLpNum_mpf__,__MaxLpNum_mpf__,ULONG_MAX);*/
+	mpf_mul_2exp(__MinLpNum_mpf__,__MinLpNum_mpf__,4096);
+	/*mpf_mul_2exp(__MinLpNum_mpf__,__MinLpNum_mpf__,ULONG_MAX);*/
+	mpq_set_f(__MaxLpNum_mpq__,__MaxLpNum_mpf__);
+	mpq_set_f(__MinLpNum_mpq__,__MinLpNum_mpf__);
+	mpz_set_f(__MaxLpNum_mpz__,__MaxLpNum_mpf__);
+	mpz_set_f(__MinLpNum_mpz__,__MinLpNum_mpf__);
+	mpf_set_ui (__oneLpNum_mpf__, (unsigned long int)1);
+	mpf_set_ui (__zeroLpNum_mpf__, (unsigned long int)0);
+	mpf_init_set_ui (mpf_eps, (unsigned long int)1);
+	mpf_div_2exp (mpf_eps, mpf_eps,  (unsigned long int)(EGLPNUM_PRECISION - 1));
+	mpq_init (__zeroLpNum_mpq__);
+	mpq_init (__oneLpNum_mpq__);
+	mpq_set_ui (__oneLpNum_mpq__, (unsigned long int)1, (unsigned long int)1);
+	mpq_set_ui (__zeroLpNum_mpq__, (unsigned long int)0, (unsigned long int)1);
+	__EGlpNum_setup=1;
+}
+
+/* ========================================================================= */
+void EGlpNumSetPrecision (const unsigned prec)
+{
+	EGLPNUM_PRECISION = prec;
+	mpf_set_default_prec (EGLPNUM_PRECISION);
+	mpf_clear (mpf_eps);
+	mpf_init_set_ui (mpf_eps, (unsigned long int)1);
+	mpf_div_2exp (mpf_eps, mpf_eps,  (unsigned long int)(EGLPNUM_PRECISION - 1));
+}
+
+/* ========================================================================= */
+/*void EGlpNumExit(void) __attribute__ ((destructor));*/
+void EGlpNumClear(void)
+{
+	#if __GMP_MEM_STATS__
+	const char mc[5][3] = {"b ","Kb","Mb","Gb","Tb"};
+	#endif
+	int i;
+	if(!__EGlpNum_setup) return;
+	mpf_clear (__zeroLpNum_mpf__);
+	mpf_clear (__oneLpNum_mpf__);
+	mpf_clear (__MaxLpNum_mpf__);
+	mpf_clear (__MinLpNum_mpf__);
+	mpf_clear (mpf_eps);
+	mpq_clear (__zeroLpNum_mpq__);
+	mpq_clear (__oneLpNum_mpq__);
+	mpq_clear (__MinLpNum_mpq__);
+	mpq_clear (__MaxLpNum_mpq__);
+	mpz_clear (__zeroLpNum_mpz__);
+	mpz_clear (__oneLpNum_mpz__);
+	mpz_clear (__MaxLpNum_mpz__);
+	mpz_clear (__MinLpNum_mpz__);
+	if(EG_LPNUM_MEMSLAB)
+	{
+		mp_set_memory_functions(0, 0, 0);
+		for(i = __GMP_MEM_NPOOL__ ; i-- ; )
+		{
+			EGmemSlabPoolClear(EGgmpPl+i);
+		}
+		#if __GMP_MEM_STATS__
+		QSlog("GMP alloc statistics:");
+		for( i = 0 ; i < __GMP_MEM_NPOOL__ ; i++)
+		{
+			if(__maxmem > 1024*1024) __maxmem= (__maxmem+1023)/1024;
+			else break;
+		}
+		QSlog("\tmaximum memory allocated      : %8.3lf %s",
+								((double)__maxmem)/1024, mc[i+1]);
+		QSlog("\tmalloc calls                  : %11zd",__nallocs);
+		QSlog("\trealloc calls                 : %11zd",__nrllocs);
+		QSlog("\tsmall size allocs-reallocs:");
+		for( i = 0 ; i < __GMP_MEM_NPOOL__ ; i++)
+		{
+			if(__alloc_sz[i] || __rlloc_sz[i])
+				QSlog("\t%4d %11zd (%5.2lf%%) %11zd (%5.2lf%%)", 
+										_EGgmpPlSz[i], __alloc_sz[i], 
+										100.0*((double)__alloc_sz[i])/(__nallocs+__nrllocs),
+										__rlloc_sz[i], 
+										100.0*((double)__rlloc_sz[i])/(__nrllocs+__nallocs));
+		}
+		if(__nalarge)
+			QSlog("\tlarge size allocs (cals/avg)  : %11zd %11zd",
+									__nalarge,__laaverage/__nalarge);
+		if(__nrlarge)
+			QSlog("\tlarge size reallocs (cals/avg): %11zd %11zd",
+									__nrlarge,__lraverage/__nalarge);
+		#endif
+		QSlog("Disabling EG-GMP mempool");
+	}
+	__EGlpNum_setup=0;
+}
+
+/* ========================================================================= */
+void mpq_EGlpNumSet_mpf (mpq_t var,
+												 mpf_t flt)
+{
+	/* local variables */
+	unsigned long int __lsgn = mpf_cmp_ui (flt, (unsigned long int)0) < 0 ? (unsigned long int)1 : (unsigned long int)0;
+	mpz_t __utmp,
+	  __z[7],
+	  max_den;
+	long int __lexp = 0;
+	int i;
+	unsigned long int uexp;
+	mpf_t __cvl,__lpnum__;
+	mpf_init(__lpnum__);
+	/* check if the given number is zero, if so, set to zero var and return */
+	if (mpf_cmp_ui (flt, (unsigned long int)0) == 0)
+	{
+		mpq_set_ui (var, (unsigned long int)0, (unsigned long int)1);
+		return;
+	}
+	/* if not, then we have some work to do */
+	/* now we initialize the internal numbers */
+	mpf_init (__cvl);
+	mpf_abs (__cvl, flt);
+	mpz_init_set_ui (__utmp, (unsigned long int)0);
+	for (i = 7; i--;)
+		mpz_init_set_ui (__z[i], (unsigned long int)0);
+	mpz_set_ui (__z[0], (unsigned long int)1);
+	mpz_set_ui (__z[4], (unsigned long int)1);
+	/* max_den is the maximum denominator that we want to see, this number should
+	 * be sligtly larger than the square root of 2^EGLPNUM_PRECISION */
+	mpz_init_set_ui (max_den, (unsigned long int)1);
+	mpz_mul_2exp (max_den, max_den, EGLPNUM_PRECISION >> 1);
+	/* first we compute the exponent stored in the limbs */
+	/* now we compute the 2^n part needed to set this number between 0.5 and 1 */
+	mpf_get_d_2exp(&__lexp,__cvl);
+	if (__lexp < 0)
+	{
+		uexp = (unsigned long int)(-__lexp);
+		mpf_mul_2exp (__cvl, __cvl, (unsigned long int) uexp);
+	}
+	else
+	{
+		uexp = (unsigned long int)(__lexp);
+		mpf_div_2exp (__cvl, __cvl, (unsigned long int) uexp);
+	}
+	/* now we loop until the next t's is more than mpf_eps */
+	/* the formula is 
+	 * p_i = t_i*p_{i-1} + p_{i-2}, and 
+	 * q_i = t_i*q_{i-1} + q_{i-2} 
+	 * note that |x-p_i/q_i|<1/q_i^2
+	 * for us t_i = __utmp, and the current number is either [0,1,2] in the __z
+	 * array, we use those popsitions ciclicly, and use the four position as a
+	 * temporary number, __z+4 is used to store q's, at the beginning i = 1. */
+	while (1)
+	{
+		if (mpf_cmp (__cvl, mpf_eps) < 0 || (mpz_cmp (__z[4], max_den) > 0))
+		{
+			mpz_set (mpq_denref (var), __z[4]);
+			mpz_set (mpq_numref (var), __z[1]);
+			break;
+		}
+		/* first run */
+		mpf_ui_div (__cvl, (unsigned long int)1, __cvl);
+		mpz_set_f (__utmp, __cvl);
+		mpf_set_z (__lpnum__, __utmp);
+		mpf_sub (__cvl, __cvl, __lpnum__);
+		mpz_set (__z[6], __utmp);
+		mpz_set (__z[2], __z[0]);
+		mpz_addmul (__z[2], __z[1], __z[6]);
+		mpz_set (__z[5], __z[3]);
+		mpz_addmul (__z[5], __z[4], __z[6]);
+		if (mpf_cmp (__cvl, mpf_eps) < 0 || (mpz_cmp (__z[5], max_den) > 0))
+		{
+			mpz_set (mpq_denref (var), __z[5]);
+			mpz_set (mpq_numref (var), __z[2]);
+			break;
+		}
+		/* second run */
+		mpf_ui_div (__cvl, (unsigned long int)1, __cvl);
+		mpz_set_f (__utmp, __cvl);
+		mpf_set_z (__lpnum__, __utmp);
+		mpf_sub (__cvl, __cvl, __lpnum__);
+		mpz_set (__z[6], __utmp);
+		mpz_set (__z[0], __z[1]);
+		mpz_addmul (__z[0], __z[2], __z[6]);
+		mpz_set (__z[3], __z[4]);
+		mpz_addmul (__z[3], __z[5], __z[6]);
+		if (mpf_cmp (__cvl, mpf_eps) < 0 || (mpz_cmp (__z[3], max_den) > 0))
+		{
+			mpz_set (mpq_denref (var), __z[3]);
+			mpz_set (mpq_numref (var), __z[0]);
+			break;
+		}
+		/* third run */
+		mpf_ui_div (__cvl, (unsigned long int)1, __cvl);
+		mpz_set_f (__utmp, __cvl);
+		mpf_set_z (__lpnum__, __utmp);
+		mpf_sub (__cvl, __cvl, __lpnum__);
+		mpz_set (__z[6], __utmp);
+		mpz_set (__z[1], __z[2]);
+		mpz_addmul (__z[1], __z[0], __z[6]);
+		mpz_set (__z[4], __z[5]);
+		mpz_addmul (__z[4], __z[3], __z[6]);
+	}
+
+	/* ending */
+	mpq_canonicalize (var);
+	if (__lsgn)
+		mpq_neg (var, var);
+	if (__lexp > 0)
+		mpq_mul_2exp (var, var, (unsigned long int) __lexp);
+	if (__lexp < 0)
+		mpq_div_2exp (var, var, (unsigned long int) (-__lexp));
+	for (i = 7; i--;)
+		mpz_clear (__z[i]);
+	mpf_clear (__cvl);
+	mpz_clear (max_den);
+	mpz_clear (__utmp);
+	mpf_clear(__lpnum__);
+	return;
+}
+/* ========================================================================= */
+/** @brief verbosity of continued fraction conversion method */
+#ifndef MPQ_VERBOSE_CNT_FRAC
+#define MPQ_VERBOSE_CNT_FRAC 1000
+#endif
+/* ========================================================================= */
+void mpq_EGlpNumSet (mpq_t var,
+										 double const dbl)
+{
+	/* local variables */
+	double __dbl = dbl;
+	unsigned __lsgn = __dbl > 0.0 ? 0U: 1U;
+	unsigned long __utmp = 0;
+	int __lexp = 0;
+	double __cvl = __dbl = fabs (__dbl);
+	/* we use the first three numbers for p, and the last three numbers for q */
+	/* first check that the dbl is not zero */
+	if (__dbl < 1e-151)
+	{
+		mpq_set_ui (var, (unsigned long int)0, (unsigned long int)1);
+		__lsgn = 0;
+	}
+	else if (__dbl > 1e151)
+		mpq_set_d (var, __dbl);
+	else
+	{
+		/* now we initialize the integer numbers */
+		mpz_t __z[7];
+		for (__utmp = 7; __utmp--;)
+			mpz_init (__z[__utmp]);
+		mpz_set_ui (__z[0], (unsigned long int)1);
+		mpz_set_ui (__z[4], (unsigned long int)1);
+		/* now we compute the 2^n part needed to set this number between 0 and 1 */
+#define __HI_EXP(x,e,v,lv) {if( x >=v ){ e = e + lv; x /= v;}}
+		if (__cvl > 1)
+		{
+			__HI_EXP (__cvl, __lexp,
+								115792089237316195423570985008687907853269984665640564039457584007913129639936.0,
+								256);
+			__HI_EXP (__cvl, __lexp, 340282366920938463463374607431768211456.0, 128);
+			__HI_EXP (__cvl, __lexp, 18446744073709551616.0, 64);
+			__HI_EXP (__cvl, __lexp, 4294967296.0, 32);
+			__HI_EXP (__cvl, __lexp, 65536.0, 16);
+			__HI_EXP (__cvl, __lexp, 256.0, 8);
+			__HI_EXP (__cvl, __lexp, 16.0, 4);
+			__HI_EXP (__cvl, __lexp, 4.0, 2);
+			__HI_EXP (__cvl, __lexp, 2.0, 1);
+#undef __HI_EXP
+		}
+		else if (__cvl < 0.5)
+		{
+#define __LO_EXP(x,e,v,lv) {if( x < 1/v ) { e = e - lv; x *= v;}}
+			__LO_EXP (__cvl, __lexp,
+								115792089237316195423570985008687907853269984665640564039457584007913129639936.0,
+								256);
+			__LO_EXP (__cvl, __lexp, 340282366920938463463374607431768211456.0, 128);
+			__LO_EXP (__cvl, __lexp, 18446744073709551616.0, 64);
+			__LO_EXP (__cvl, __lexp, 4294967296.0, 32);
+			__LO_EXP (__cvl, __lexp, 65536.0, 16);
+			__LO_EXP (__cvl, __lexp, 256.0, 8);
+			__LO_EXP (__cvl, __lexp, 16.0, 4);
+			__LO_EXP (__cvl, __lexp, 4.0, 2);
+			__LO_EXP (__cvl, __lexp, 2.0, 1);
+#undef __LO_EXP
+		}
+		/* now we loop until the next t's is more than EGLPNUM_MINEPS */
+		/* the formula is 
+		 * p_i = t_i*p_{i-1} + p_{i-2}, and 
+		 * q_i = t_i*q_{i-1} + q_{i-2} 
+		 * note that |x-p_i/q_i|<1/q_i^2
+		 * for us t_i = __utmp, and the current number is either [0,1,2] in the __z
+		 * array, we use those popsitions ciclicly, and use the four position as a
+		 * temporary number, __z+4 is used to store q's, at the beginning i = 1. */
+		while (1)
+		{
+			if (__cvl < EGLPNUM_MINEPS || (mpz_cmp_ui (__z[4], (unsigned long int)0xfffffff) > 0))
+			{
+				mpz_set (mpq_denref (var), __z[4]);
+				mpz_set (mpq_numref (var), __z[1]);
+				break;
+			}
+			MESSAGE(MPQ_VERBOSE_CNT_FRAC,"cur approximate %ld/%ld, error %10.7lg", 
+							mpz_get_si(__z[1]), mpz_get_si(__z[4]), __cvl);
+			/* first run */
+			__cvl = 1 / __cvl;
+			__dbl = floor(__cvl);
+			__utmp = (unsigned long)__dbl;
+			__cvl -= __dbl;
+			mpz_set_ui (__z[6], __utmp);
+			mpz_set (__z[2], __z[0]);
+			mpz_addmul (__z[2], __z[1], __z[6]);
+			mpz_set (__z[5], __z[3]);
+			mpz_addmul (__z[5], __z[4], __z[6]);
+			if (__cvl < EGLPNUM_MINEPS || (mpz_cmp_ui (__z[5], (unsigned long int)0xfffffff) > 0))
+			{
+				mpz_set (mpq_denref (var), __z[5]);
+				mpz_set (mpq_numref (var), __z[2]);
+				break;
+			}
+			MESSAGE(MPQ_VERBOSE_CNT_FRAC,"cur approximate %ld/%ld, error %10.7lg", 
+							mpz_get_si(__z[2]), mpz_get_si(__z[5]), __cvl);
+			/* second run */
+			__cvl = 1 / __cvl;
+			__dbl = floor(__cvl);
+			__utmp = (unsigned long)(__dbl);
+			__cvl -= __dbl;
+			mpz_set_ui (__z[6], __utmp);
+			mpz_set (__z[0], __z[1]);
+			mpz_addmul (__z[0], __z[2], __z[6]);
+			mpz_set (__z[3], __z[4]);
+			mpz_addmul (__z[3], __z[5], __z[6]);
+			if (__cvl < EGLPNUM_MINEPS || (mpz_cmp_ui (__z[3], (unsigned long int)0xfffffff) > 0))
+			{
+				mpz_set (mpq_denref (var), __z[3]);
+				mpz_set (mpq_numref (var), __z[0]);
+				break;
+			}
+			MESSAGE(MPQ_VERBOSE_CNT_FRAC,"cur approximate %ld/%ld, error %10.7lg", 
+							mpz_get_si(__z[0]), mpz_get_si(__z[3]), __cvl);
+			/* third run */
+			__cvl = 1 / __cvl;
+			__dbl = floor(__cvl);
+			__utmp = (unsigned long)(__dbl);
+			__cvl -= __dbl;
+			mpz_set_ui (__z[6], __utmp);
+			mpz_set (__z[1], __z[2]);
+			mpz_addmul (__z[1], __z[0], __z[6]);
+			mpz_set (__z[4], __z[5]);
+			mpz_addmul (__z[4], __z[3], __z[6]);
+		}
+		for (__utmp = 7; __utmp--;)
+			mpz_clear (__z[__utmp]);
+	}
+	/* ending */
+	mpq_canonicalize (var);
+	if (__lsgn)
+		mpq_neg (var, var);
+	if (__lexp > 0)
+		mpq_mul_2exp (var, var, (unsigned long int) __lexp);
+	if (__lexp < 0)
+		mpq_div_2exp (var, var, (unsigned long int) (-__lexp));
+	return;
+}
+
+/* ========================================================================= */
+int mpz_EGlpNumReadStr (mpz_t var,
+												char const *str)
+{
+	/* local variables */
+	char unsigned a_sgn = 1;
+	char unsigned sgn = 0;
+	char c = 0;
+	int n_char = 0;
+	/* now we read the string */
+	c = str[n_char];
+	mpz_set_ui (var, (unsigned long int)0);
+	while ((('0' <= c) && (c <= '9')) ||	/* allow to read digits */
+				 (a_sgn && (c == '+' || c == '-')) /* allow sign for exponent */ )
+	{
+		switch (c)
+		{
+		case '0':
+		case '1':
+		case '2':
+		case '3':
+		case '4':
+		case '5':
+		case '6':
+		case '7':
+		case '8':
+		case '9':
+			mpz_mul_ui (var, var, (unsigned long int)10);
+			mpz_add_ui (var, var,  (unsigned long int)(c - '0'));
+			a_sgn = 0;
+			break;
+		case '-':
+			sgn = 1;
+		case '+':
+			a_sgn = 0;
+			break;
+		}
+		/* advance the reading character */
+		c = str[++n_char];
+	}
+	if (sgn)
+		mpz_neg (var, var);
+	return n_char;
+}
+
+/* ========================================================================= */
+int mpq_EGlpNumReadStrXc (mpq_t var,
+													char const *str)
+{
+	/* local variables */
+	char unsigned a_dot = 1,
+	  a_exp = 0,
+	  a_exp_sgn = 0,
+	  a_sgn = 1,
+	  a_div = 1;
+	char c = 0;
+	int l_exp = 0,
+	  sgn = 0,
+	  exp_sgn = 0;
+	int n_char = 0,
+	  n_dig = 0,
+	  cn = 0;
+	mpq_t den[2];
+	mpq_init (den[0]);
+	mpq_init (den[1]);
+	mpq_set_ui (den[1], (unsigned long int)1, (unsigned long int)1);
+	mpq_set_ui (den[0], (unsigned long int)0, (unsigned long int)1);
+
+	/* now we read the string */
+	c = str[n_char];
+	while ((('0' <= c) && (c <= '9')) ||	/* allow to read digits */
+				 (a_dot && (c == '.')) ||	/* allow to read a dot point */
+				 (a_exp && (c == 'e' || c == 'E')) ||	/* allow an exponent marker */
+				 (a_sgn && (c == '+' || c == '-')) ||	/* allow a number sign */
+				 (a_div && c == '/') ||	/* allow the division sign */
+				 (a_exp_sgn && (c == '+' || c == '-')) /* allow sign for exponent */ )
+	{
+		switch (c)
+		{
+		case '0':
+		case '1':
+		case '2':
+		case '3':
+		case '4':
+		case '5':
+		case '6':
+		case '7':
+		case '8':
+		case '9':
+			/* if we haven't read the exponent then the digits bellongs to the mantisa
+			 * */
+			if (a_exp || n_dig == 0)
+			{
+				if (!a_dot)
+					mpz_mul_ui (mpq_denref (den[cn]), mpq_denref (den[cn]), (unsigned long int)10);
+				mpz_mul_ui (mpq_numref (den[cn]), mpq_numref (den[cn]), (unsigned long int)10);
+				mpz_add_ui (mpq_numref (den[cn]), mpq_numref (den[cn]),
+										 (unsigned long int)(c - '0'));
+				n_dig++;
+				a_exp = 1;
+			}
+			/* otherwise, if we have read the exponent, the digits should go to the
+			 * exponent */
+			else
+			{
+				l_exp = 10 * l_exp + c - '0';
+				a_exp_sgn = 0;
+			}
+			a_sgn = 0;
+			break;
+		case '.':
+			a_sgn = 0;
+			a_dot = 0;
+			a_sgn = 0;
+			break;
+		case '-':
+			if (a_sgn)
+				sgn = 1;
+			else
+				exp_sgn = 1;
+		case '+':
+			if (a_sgn)
+				a_sgn = 0;
+			if (a_exp_sgn)
+				a_exp_sgn = 0;
+			break;
+		case 'e':
+		case 'E':
+			a_sgn = 0;
+			a_exp = 0;
+			a_exp_sgn = 1;
+			break;
+		case '/':
+			if (exp_sgn)
+				l_exp = -l_exp;
+			if (l_exp > 0)
+				while (l_exp--)
+					mpz_mul_ui (mpq_numref (den[0]), mpq_numref (den[0]), (unsigned long int)10);
+			else if (l_exp < 0)
+			{
+				l_exp = -l_exp;
+				while (l_exp--)
+					mpz_mul_ui (mpq_denref (den[0]), mpq_denref (den[0]), (unsigned long int)10);
+			}
+			if (sgn)
+				mpz_neg (mpq_numref (den[0]), mpq_numref (den[0]));
+			mpq_canonicalize (den[0]);
+			mpq_set_ui (den[1], (unsigned long int)0, (unsigned long int)1);
+			sgn = 0;
+			exp_sgn = 0;
+			l_exp = 0;
+			a_div = 0;
+			n_dig = 0;
+			a_dot = 1;
+			a_exp = 0;
+			a_exp_sgn = 0;
+			a_sgn = 1;
+			cn = 1;
+			break;
+		}
+		/* advance the reading character */
+		c = str[++n_char];
+	}
+	if (n_char)
+	{
+		/* now expand the exponent of the denominator */
+		if (exp_sgn)
+			l_exp = -l_exp;
+		if (l_exp > 0)
+			while (l_exp--)
+				mpz_mul_ui (mpq_numref (den[cn]), mpq_numref (den[cn]), (unsigned long int)10);
+		else if (l_exp < 0)
+		{
+			l_exp = -l_exp;
+			while (l_exp--)
+				mpz_mul_ui (mpq_denref (den[cn]), mpq_denref (den[cn]), (unsigned long int)10);
+		}
+		/* check the sign of the whole number */
+		if (sgn)
+			mpz_neg (mpq_numref (den[cn]), mpq_numref (den[cn]));
+		/* ending */
+		mpq_canonicalize (den[0]);
+		mpq_canonicalize (den[1]);
+		mpq_div (var, den[0], den[1]);
+	}
+	mpq_clear (den[0]);
+	mpq_clear (den[1]);
+	return n_char;
+}
+
+/* ========================================================================= */
+void uint32_EGutilPermSort (const size_t sz,
+										 int *const perm,
+										 const uint32_t * const elem)
+{
+	size_t i,
+	  j;
+	int temp;
+	uint32_t t;
+	if (sz <= 1)
+		return;
+
+	EGswap (perm[0], perm[(sz - 1) / 2], temp);
+	i = 0;
+	j = sz;
+	(t= elem[perm[0]]);
+	for (;;)
+	{
+		do
+			i++;
+		while (i < sz && (elem[perm[i]]< t));
+		do
+			j--;
+		while (j && (t< elem[perm[j]]));
+		if (j < i)
+			break;
+		EGswap (perm[i], perm[j], temp);
+	}
+	EGswap (perm[0], perm[j], temp);
+	uint32_EGutilPermSort (j, perm, elem);
+	uint32_EGutilPermSort (sz - i, perm + i, elem);
+}
+
+/* ========================================================================= */
+void uint32_EGutilPermSort2 (const size_t sz,
+										 int *const perm,
+										 const uint32_t * const elem)
+{
+	size_t i,
+	  j;
+	int temp;
+	uint32_t t;
+	if (sz <= 1)
+		return;
+
+	EGswap (perm[0], perm[(sz - 1) / 2], temp);
+	i = 0;
+	j = sz;
+	(t= elem[perm[0]]);
+	for (;;)
+	{
+		do
+			i++;
+		while (i < sz && (t< elem[perm[i]]));
+		do
+			j--;
+		while ((elem[perm[j]]< t));
+		if (j < i)
+			break;
+		EGswap (perm[i], perm[j], temp);
+	}
+	EGswap (perm[0], perm[j], temp);
+	uint32_EGutilPermSort2 (j, perm, elem);
+	uint32_EGutilPermSort2 (sz - i, perm + i, elem);
+}
+
+/* ========================================================================= */
+/** @} */
diff --git a/qsopt_ex/eg_lpnum.dbl.h b/qsopt_ex/eg_lpnum.dbl.h
new file mode 100644
index 0000000..48e8faa
--- /dev/null
+++ b/qsopt_ex/eg_lpnum.dbl.h
@@ -0,0 +1,488 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library 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 Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
+ * */
+#ifndef __EG_LPNUM_DBL__
+#define __EG_LPNUM_DBL__
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+
+#include "eg_lpnum.h"
+
+/** @file
+ * @ingroup EGlpNum */
+/** @addtogroup EGlpNum */
+/** @{ */
+/* ========================================================================= */
+/** extern definitions of constaants for different set-ups */
+#define dbl_zeroLpNum 0.0
+#define dbl_oneLpNum  1.0
+#define dbl_epsLpNum  DBL_EPSILON
+#define dbl_MaxLpNum	DBL_MAX
+#define dbl_MinLpNum	DBL_MIN
+
+/* ========================================================================= */
+/** @brief Read from a string a number and store it in the given double, 
+ * @return the number of chars readed from the input string */
+#define dbl_EGlpNumReadStr(a,str) ({\
+	int __i =0;\
+	sscanf(str,"%lf%n",&(a),&__i);\
+	__i;})
+
+/* ========================================================================= */
+/** @brief given a double, write it to a string (to be allocated internally), 
+ * and return it. */
+#define dbl_EGlpNumGetStr(a) ({\
+	char *__str=0;\
+	int __i=snprintf(__str,(size_t)0,"%.7lg",a);\
+	__str = EGsMalloc(char,__i+1);\
+	snprintf(__str,(size_t)(__i+1),"%.7lg",a);\
+	__str;})
+
+/* ========================================================================= */
+/** @brief given an array of type double, free it, if the pointer is NULL
+ * nothing happen. */
+#define dbl_EGlpNumFreeArray(ea) __EGlpNumFreeArray(ea)
+
+/* ========================================================================= */
+/** @brief Reallocate and initialize (if needed) 'size' elements of type 
+ * EGlpNum_t and return it, if no more memory, exit(1) */
+#define dbl_EGlpNumReallocArray(lptr, lsize) ({\
+	size_t __csz = (lsize), *__usp = 0;\
+	size_t __psz = __EGlpNumArraySize(*lptr);\
+	double** __ptr__ = (lptr);\
+	if (!__psz) *__ptr__ = dbl_EGlpNumAllocArray (__csz); \
+	else if (__psz < __csz) {\
+		__usp = (size_t*)(*__ptr__);\
+		__usp--;\
+		__usp = EGrealloc(__usp, sizeof(double)*__csz+sizeof(size_t));\
+		__usp[0] = __csz;\
+		*__ptr__ = (double*)(__usp+1);\
+		memset((*__ptr__)+__psz,0,sizeof(double)*(__csz-__psz));\
+	}\
+	*__ptr__;})
+
+/* ========================================================================= */
+/** @brief Allocate and initialize (if needed) 'size' elements of type double
+ * and return it, if no more memory, exit(1) */
+#define dbl_EGlpNumAllocArray(size) __EGlpNumAllocArray(double,size)
+
+/* ========================================================================= */
+/** @brief set the given number pointer, set its value to the given double.
+ * @param var double where we will store the double value.
+ * @param dbl double value to be stored in 'var'.
+ * @par Description:
+ * This function is intended to set initial values to variables; note that the
+ * double is a number and not a pointer to that value, be carefull with this
+ * detail. Also, due to implementation details this function can't deal with
+ * numbers above 1e158 or smaller than 1e-158. Note also that if the number is
+ * writen in the form \f$x=\bar{x}\cdot 2^e\f$ with \f$0.5<|\bar{x}|<1\f$, 
+ * then \f$\left|x-\frac{p}{q}\right|<2^{e-64}\f$.
+ * */
+#define dbl_EGlpNumSet(var, dbl) ((var) = (dbl))
+
+/* ========================================================================= */
+/** @brief Stores in the first number the ceil value of the second number, i.e.
+ * EGlpNumCeil(a,b) <==> a= ceil(b) */
+#define dbl_EGlpNumCeil(a, b) ((a) = ceil(b))
+
+/* ========================================================================= */
+/** @brief Stores in the first number the floor value of the second number, i.e.
+ * EGlpNumFloor(a,b) <==> a= floor(b) */
+#define dbl_EGlpNumFloor(a, b) ((a) = floor(b))
+
+/* ========================================================================= */
+/** @brief store the (multiplicative) inverse of a number to itself, i.e.
+ * implement a = 1/a.
+ * @param a the number to be inverted. */
+#define dbl_EGlpNumInv(a) ((a) = 1.0/(a))
+
+/* ========================================================================= */
+/** @brief Compare if two numbers are equal within a maximum error.
+ * @param a EGlpNum_t first number to compare.
+ * @param b EGlpNum_t second number to compare.
+ * @return int one in success, zero oterwise.
+ * @par Description:
+ * Given two numbers 'a','b' return 1 if a == b, otherwise it return 0
+ * */
+#define dbl_EGlpNumIsEqqual(a,b) ((a) == (b))
+
+/* ========================================================================= */
+/** @brief Compare if two numbers are equal within a maximum error.
+ * @param a EGlpNum_t first number to compare.
+ * @param b EGlpNum_t second number to compare.
+ * @param error EGlpNum_t maximum difference allowed between both
+ * numbers.
+ * @return int one in success, zero oterwise.
+ * @par Description:
+ * Given two numbers 'a','b' and a tolerance 'error',
+ * return 1 if |a-b|<= error, otherwise it return 0.
+ * */
+#define dbl_EGlpNumIsEqual(a,b,error) (fabs((a)-(b)) <= (error))
+#define dbl_EGlpNumIsNeq(a,b,error) (((a)-(b) > (error)) || ((b)-(a) > (error)))
+#define dbl_EGlpNumIsNeqq(a,b)  ((a) != (b))
+#define dbl_EGlpNumIsNeqZero(a,error) (((a) > (error)) || (-(a) > (error)))
+#define dbl_EGlpNumIsNeqqZero(a)     	((a) != 0.0)
+
+/* ========================================================================= */
+/** @brief test if the first number is greater than zero
+ * @param a EGlpNum_t number to test.
+ * @return int one if success, zero otherwise.
+ * */
+#define dbl_EGlpNumIsGreatZero(a) (a > 0.0)
+
+/* ========================================================================= */
+/** @brief test if the first number is less than zero
+ * @param a EGlpNum_t number to test.
+ * @return int one if success, zero otherwise.
+ * */
+#define dbl_EGlpNumIsLessZero(a) (a < 0.0)
+
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a EGlpNum_t the first number.
+ * @param b EGlpNum_t the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a < b, zero
+ * otherwise.
+ * */
+#define dbl_EGlpNumIsLess(a,b) (a < b)
+
+/* ========================================================================= */
+/** @brief test if the sum of the first two numbers is less thatn the third
+ * number.
+ * @param a EGlpNum_t the first number.
+ * @param b EGlpNum_t the second number
+ * @param c EGlpNum_t the third number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given a,b, and c, return nonzero if (a + b < c), zero toherwise.
+ * */
+#define dbl_EGlpNumIsSumLess(a, b, c) ((a) + (b) < (c))
+
+/* ========================================================================= */
+/** @brief test if the diference of the first two numbers is less thatn the 
+ * third number.
+ * @param a EGlpNum_t the first number.
+ * @param b EGlpNum_t the second number
+ * @param c EGlpNum_t the third number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given a,b, and c, return nonzero if (a - b < c), zero toherwise.
+ * */
+#define dbl_EGlpNumIsDiffLess(a, b, c) ((a) - (b) < (c))
+
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a EGlpNum_t the first number.
+ * @param b double the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a < b, zero
+ * otherwise.
+ * */
+#define dbl_EGlpNumIsLessDbl(a,b) ((a) < (b))
+
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a EGlpNum_t the first number.
+ * @param b double the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a > b, zero
+ * otherwise.
+ * */
+#define dbl_EGlpNumIsGreaDbl(a,b) ((a) > (b))
+
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a EGlpNum_t the first number.
+ * @param b EGlpNum_t the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a <= b, zero
+ * otherwise.
+ * */
+#define dbl_EGlpNumIsLeq(a,b) ((a) <= (b))
+
+/* ========================================================================= */
+/** @brief copy the value of the second number to the first.
+ * @param a EGlpNum_t source number (it won't change value).
+ * @param b EGlpNum_t source number (it won't change value).
+ * @param den EGlpNum_t denominator of the difference (it won't change value).
+ * @param dest EGlpNum_t where to store the value .
+ * @par Description:
+ * Set dest = (a - b) / den */
+#define dbl_EGlpNumCopyDiffRatio(dest,a, b, den) ((dest) = ((a) - (b)) / (den))
+
+/* ========================================================================= */
+/** @brief copy the value of the second number to the first.
+ * @param a EGlpNum_t source number (it won't change value).
+ * @param b EGlpNum_t source number (it won't change value).
+ * @param dest EGlpNum_t where to store the value stored in 'orig'.
+ * @par Description:
+ * Set dest = a - b */
+#define dbl_EGlpNumCopyDiff(dest,a,b) ((dest) = (a) - (b))
+
+/* ========================================================================= */
+/** @brief copy the value of the sum of the second and third parameter
+ * @param a EGlpNum_t source number (it won't change value).
+ * @param b EGlpNum_t source number (it won't change value).
+ * @param dest EGlpNum_t where to store the sum.
+ * @par Description:
+ * Set dest = a + b */
+#define dbl_EGlpNumCopySum(dest,a,b) ((dest) = (a) + (b))
+
+/* ========================================================================= */
+/** @brief copy the value of the second number to the first.
+ * @param orig EGlpNum_t source number (it won't change value).
+ * @param dest EGlpNum_t where to store the value stored in 'orig'.
+ * @par Description:
+ * Given two numbers copy the values in 'orig', into 'dest'.
+ * */
+#define dbl_EGlpNumCopy(dest,orig) ((dest) = (orig))
+
+/* ========================================================================= */
+/** @brief change the fist number to the maximum between itself and the 
+ * absolute value of the second.
+ * @param orig EGlpNum_t source number (it won't change value).
+ * @param dest EGlpNum_t where to store the value stored in 'orig'.
+ * @par Description:
+ * implement dest = max(dest,abs(orig))
+ * */
+#define dbl_EGlpNumSetToMaxAbs(dest, orig) if((dest) < fabs(orig)) \
+																							(dest) = fabs(orig)
+#define dbl_EGlpNumSetToMinAbs(dest, orig) if((dest) > fabs(orig)) \
+																							(dest) = fabs(orig)
+
+/* ========================================================================= */
+/** @brief copy the square of the second argument, divided by the third 
+ * argument into the first argument.
+ * @param dest EGlpNum_t where to store the result
+ * @param orig EGlpNum_t second parameter
+ * @param den EGlpNum_t third parameter
+ * @par Description:
+ * compute dest = (orig*orig)/den
+ * */
+#define dbl_EGlpNumCopySqrOver(dest, orig, den) ((dest) = (orig)*(orig)/(den))
+
+/* ========================================================================= */
+/** @brief copy the value of the absolute value of the second parameter to the 
+ * first parameter.
+ * @param orig EGlpNum_t source number (it won't change value).
+ * @param dest EGlpNum_t where to store the absolute value stored
+ * in 'orig'.
+ * @par Description:
+ * Given a number 'orig', copy its absolute value to 'dest'. i.e.
+ * dest = |orig|
+ * */
+#define dbl_EGlpNumCopyAbs(dest,orig) ((dest) = fabs(orig))
+
+/* ========================================================================= */
+/** @brief copy minus the value of the second parameter to the 
+ * first parameter.
+ * @param orig EGlpNum_t the source number (it won't change value).
+ * @param dest EGlpNum_t where to store minus the value stored
+ * in 'orig'.
+ * @par Description:
+ * Given a number 'orig', copy minus the value to 'dest'. i.e.
+ * dest = -orig
+ * */
+#define dbl_EGlpNumCopyNeg(dest,orig) ((dest) = -(orig))
+
+/* ========================================================================= */
+/** @brief Set des = op1/op2.
+ * @param dest EGlpNum_t where we will store the result.
+ * @param op1 EGlpNum_t numerator of the fraction (possibly non an integer)
+ * @param op2 EGlpNum_t denominator of the fraction (possibly non an integer)
+ * @par Description:
+ *  Set des = op1/op2
+ * */
+#define dbl_EGlpNumCopyFrac(dest,op1,op2) ((dest) = (op1)/(op2))
+
+/* ========================================================================= */
+/** @brief copy the first 'size' values in the second array to the first array.
+ * @param orig EGlpNum_t* pointer to the array from where we will copy the
+ * values (it won't change value).
+ * @param dest EGlpNum_t* pointer to where to store the first 'size' values 
+ * stored in 'orig'.
+ * @param size unsigned int specifying how many values of 'orig' will be copied
+ * onto 'dest'
+ * @par Description:
+ * This function is provided to (possible) make fast copies of arrays of
+ * numbers, the arrays should be of length at least 'size', and the resulting
+ * copy is absolutely independent froom the original, any change in one vale of
+ * one array won't change values on the other array.
+ * */
+#define dbl_EGlpNumCopyArray(dest,orig,size) memcpy(dest,orig,sizeof(double)*(size))
+
+/* ========================================================================= */
+/** @brief Sub to a given number the product of two numbers.
+ * @param a EGlpNum_t the number that we are going to Sub to.
+ * @param b EGlpNum_t value to be multiplyed.
+ * @param c EGlpNum_t value to be multiplyed.
+ * @par Description:
+ * This function implements a = a - b*c, and clearly don't change the value
+ * stored in 'b' nor in 'c'.
+ * */
+#define dbl_EGlpNumSubInnProdTo(a, b, c) ((a) -= (b)*(c))
+
+/* ========================================================================= */
+/** @brief Add to a given number the product of two numbers.
+ * @param a EGlpNum_t the number that we are going to add to.
+ * @param b EGlpNum_t value to be multiplyed.
+ * @param c EGlpNum_t value to be multiplyed.
+ * @par Description:
+ * This function implements a = a + b*c, and clearly don't change the value
+ * stored in 'b' nor in 'c'.
+ * */
+#define dbl_EGlpNumAddInnProdTo(a, b, c) ((a) += (b)*(c))
+
+/* ========================================================================= */
+/** @brief Substract to a given number the value of the second number.
+ * @param a EGlpNum_t the number that we are going to substract to.
+ * @param b unsigned int value to be substracted to 'a'.
+ * @par Description:
+ * This function implements a = a - b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define dbl_EGlpNumSubUiTo(a,b) ((a) -= (b))
+
+/* ========================================================================= */
+/** @brief Add to a given number the value of the second number.
+ * @param a EGlpNum_t the number that we are going to add to.
+ * @param b unsigned int value to be added to 'a'.
+ * @par Description:
+ * This function implements a = a + b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define dbl_EGlpNumAddUiTo(a,b) ((a) += (b))
+
+/* ========================================================================= */
+/** @brief Add to a given number the value of the second number.
+ * @param a EGlpNum_t the number that we are going to add to.
+ * @param b EGlpNum_t value to be added to 'a'.
+ * @par Description:
+ * This function implements a = a + b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define dbl_EGlpNumAddTo(a,b) ((a) += (b))
+
+/* ========================================================================= */
+/** @brief Substract to a given number the value of the second number.
+ * @param a EGlpNum_t the number that we are going to substract
+ * from.
+ * @param b EGlpNum_t value to be substracted to 'a'.
+ * @par Description:
+ * This function implements a = a - b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define dbl_EGlpNumSubTo(a,b) ((a) -= (b))
+
+/* ========================================================================= */
+/** @brief Multiply a given number by the value of the second number.
+ * @param a EGlpNum_t the number that we are going to multiply by
+ * the second number and store the result.
+ * @param b EGlpNum_t value to be multyply to 'a'.
+ * @par Description:
+ * This function implements a = a * b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define dbl_EGlpNumMultTo(a,b) ((a) *= (b))
+
+/* ========================================================================= */
+/** @brief Divide a given number by the value of the second number.
+ * @param a EGlpNum_t the number that we are going to divide by
+ * the second number and store the result.
+ * @param b EGlpNum_t value to be divide to 'a'.
+ * @par Description:
+ * This function implements a = a / b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define dbl_EGlpNumDivTo(a,b) ((a) /= (b))
+
+/* ========================================================================= */
+/** @brief Divide a given number by the value of the second number.
+ * @param a EGlpNum_t the number that we are going to divide by
+ * the second number and store the result.
+ * @param b unsigned int value to be divided to 'a'.
+ * @par Description:
+ * This function implements a = a / b, and don't change the value
+ * stored in 'b'.
+ * */
+#define dbl_EGlpNumDivUiTo(a,b) ((a) /= (b))
+
+/* ========================================================================= */
+/** @brief Multiply a given number by the value of the second number.
+ * @param a EGlpNum_t the number that we are going to multiply by
+ * the second number and store the result.
+ * @param b unsigned int value to be multyply to 'a'.
+ * @par Description:
+ * This function implements a = a * b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define dbl_EGlpNumMultUiTo(a,b) ((a) *= (b))
+
+/* ========================================================================= */
+/** @brief Reset the value of the pointed number to zero.
+ * @param a EGlpNum_t the value to be set to zero.
+ * @par Descrpition:
+ * Reset a to zero, i.e. implements a = 0;
+ * */
+#define dbl_EGlpNumZero(a) ((a) = 0.0)
+
+/* ========================================================================= */
+/** @brief Reset the value of the pointed number to one.
+ * @param a EGlpNum_t value to be set to one.
+ * @par Descrpition:
+ * Reset a to zero, i.e. implements a = 1;
+ * */
+#define dbl_EGlpNumOne(a) ((a) = 1.0)
+
+/* ========================================================================= */
+/** @brief Change the sign of the number.
+ * @param a EGlpNum_t number we will change sign.
+ * @par Descrpition:
+ * Change the sign of the given number, i.e. implements a = -a
+ * */
+#define dbl_EGlpNumSign(a) ((a) = -(a))
+
+/* ========================================================================= */
+/** @brief return the closest double value of the given pointer number.
+ * @param a EGlpNum_t number that we will be transformed to double.
+ * @return double the closest double representation of the given number.
+ * par Description:
+ * return the double number closest in value to the value stored in a.
+ * */
+#define dbl_EGlpNumToLf(a) ((double)a)
+
+/* ========================================================================= */
+/** @brief initialize the internal memory of a given variable */
+#define dbl_EGlpNumInitVar(a) dbl_EGlpNumZero(a)
+
+/* ========================================================================= */
+/** @brief free the internal memory of a given variable */
+#define dbl_EGlpNumClearVar(a)
+
+/* ========================================================================= */
+/** @} */
+#endif
diff --git a/qsopt_ex/eg_lpnum.h b/qsopt_ex/eg_lpnum.h
new file mode 100644
index 0000000..3a90fbd
--- /dev/null
+++ b/qsopt_ex/eg_lpnum.h
@@ -0,0 +1,706 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library 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 Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
+ * */
+#ifndef __EG_LPNUM_H__
+#define __EG_LPNUM_H__
+/* ========================================================================= */
+/** @defgroup EGlpNum EGlpNum
+ *
+ * Here we define a common interface to handle numbers in general, the idea is
+ * to be able to work with infinite precicion numbers, plain doubles, floats,
+ * integers, or fixed point numbers, without actually making different codes
+ * for each of those types, rather we preffer to fix that at compyle time.
+ *
+ * @par History:
+ * Revision 1.1.0
+ * 	- 2013-04-18
+ * 						- Add uint32_EGutilPermSort and uint32_EGutilPermSort2
+ * 	- 2010-09-02
+ * 						- Add support for int32 templates, streamline the template
+ * 						implementation too
+ * 						- Add MaxLpNum and MinLpNum keywords
+ *  We start doing the migration to gmp and 'natural' types, this means that we
+ *  drop support for EGrat, this allow us to drop the requirement to use
+ *  pointers, and instead we can just call the functions with the original
+ *  parameters, still we have to be VERY carefull regarding changing
+ *  local/external copies.
+ *  - 2007-10-08
+ *  					- Move EGswap, EGabs, EGmin and Egmax to eg_numutil.h
+ *  - 2005-10-31
+ *  					- Add EGswap to swap elements of any predefined type.
+ *  - 2005-08-31
+ *  					- Add EGmin and EGmax for built in types (i.e. for types where
+ *  					the < comparison works as we want).
+ *  - 2005-08-16
+ *  					- Streamline mpq_EGlpNumGetStr
+ *  					- Minor Fixes for zeroLpNum
+ *  - 2005-07-29
+ *  					- Add EGabs definition.
+ *  - 2005-07-24
+ *  					- Split eg_lpnum.h into different headers for each type of
+ *  						suported numbers.
+ *  					- Deprecate EGlpNumCOmpUFrac
+ *  - 2005-05-26
+ *  					- Add epsLpNum
+ *  - 2005-05-17
+ *  					- Add mpq_EGlpNumReadStrXc(mpq_t,__EGPstr__)
+ *  - 2005-05-16
+ *  					- Add mpq_EGlpNumSet_mpf(mpq,mpf)
+ *  - 2005-05-12
+ *  					- Add mpf_EGlpNumEpow(num,power)
+ *  					- Add function to change precision of the numbers on the fly.
+ *  					- Add EGlpNumReadStr to set a number from a given input string.
+ *  					- Add EGlpNumGetStr to get (hopefully) the exact representation 
+ *  						of the given input as string.
+ *  - 2005-05-03
+ *  					- Change the structure of the header so it provides an interface
+ *  					in which a program can use all types of numbers at the same time,
+ *  					this implies that we must define a start-up and clean-up function
+ *  					that would initialize all constants for all numbers, and change
+ *  					the naming scheme accordingly to support this.
+ *  					- Deprecate EGlpNumInitArray
+ *  					- Deprecate EGlpNumFreeIntArray
+ *  					- Change all static-inline definitions to Statement Exprs style.
+ *  - 2005-04-25
+ *  					- Add EGlpNumIsSumLess(__EGPa__,__EGPb__,__EGPc__)
+ *  					- Add EGlpNumIsDiffLess(__EGPa__,__EGPb__,__EGPc__)
+ *  - 2005-04-13
+ *  					- Add EGlpNumCopyDiffRatio(__EGPa__,__EGPb__,__EGPc__,d)
+ *  					- Add EGlpNumIsEqqual(__EGPa__,__EGPb__)
+ *  					- Add EGlpNumIsEqual(__EGPa__,__EGPb__,__EGPerr__)
+ *  					- Add EGlpNumCopy(__EGPa__,__EGPb__)
+ *  					- Add EGlpNumIsLess(__EGPa__,__EGPb__)
+ *  					- Add EGlpNumToLf(__EGPa__)
+ *  					- Add EGlpNumCopyDiff(__EGPa__,__EGPb__,__EGPc__)
+ *  					- Add EGlpNumCopyAbs(__EGPa__,__EGPb__)
+ *  					- Add EGlpNumSubTo(__EGPa__,__EGPb__)
+ *  					- Add EGlpNumAddTo(__EGPa__,__EGPb__)
+ *  					- Add EGlpNumDivTo(__EGPa__,__EGPb__)
+ *  					- Add EGlpNumMultTo(__EGPa__,__EGPb__)
+ *  					- Add EGlpNumZero(__EGPa__)
+ *  					- Add EGlpNumOne(__EGPa__)
+ *  					- Add EGlpNumAddInnProdTo(__EGPa__,__EGPb__,__EGPc__)
+ *  					- Add EGlpNumSubInnProdTo(__EGPa__,__EGPb__,__EGPc__)
+ *  					- Add EGlpNumSign(__EGPa__)
+ *  					- Add EGlpNumCopyNeg(__EGPa__,__EGPb__)
+ *  					- Add EGlpNumDivUiTo(__EGPa__,__EGPb__)
+ *  					- Add EGlpNumMultUiTo(__EGPa__,__EGPb__)
+ *  					- Add EGlpNumIsLeq(__EGPa__,__EGPb__)
+ *  					- Add EGlpNumCopySqrOver(__EGPa__,__EGPb__,__EGPc__)
+ *  					- Add EGlpNumSet(__EGPa__,__EGPb__)
+ *  					- Add EGlpNumCopyFrac(__EGPa__,__EGPb__,__EGPc__)
+ *  					- Add EGlpNumAddUiTo(__EGPa__,__EGPb__)
+ *  					- Add EGlpNumSubUiTo(__EGPa__,__EGPb__)
+ *  					- Add EGlpNumCopySum(__EGPa__,__EGPb__,__EGPc__)
+ *  					- Add EGlpNumInv(__EGPa__)
+ *  					- Add EGlpNumFloor(__EGPa__)
+ *  					- Add EGlpNumCeil(__EGPa__)
+ *  					- Add EGlpNumIsLessDbl(__EGPa__,__EGPb__)
+ *  					- Add EGlpNumIsGreaDbl(__EGPa__,__EGPb__)
+ *  					- Add EGlpNumSetToMaxAbs(__EGPa__,__EGPb__)
+ *  					- Add EGlpNumAllocArray(__EGPszb__)
+ *  					- Add EGlpNumFreeArray(__EGPa__)
+ *  					- Add EGlpNumReallocArray(__EGPa__,__EGPszb__)
+ *  					- Add EGlpNumInitVar(__EGPa__)
+ *  					- Add EGlpNumClearVar(__EGPa__)
+ *  					- Add EGlpNumIsNeqq(__EGPa__,__EGPb__)
+ *  					- Add EGlpNumIsNeq(__EGPa__,__EGPb__,__EGPc__)
+ *  					- Add EGlpNumIsNeqqZero(__EGPa__)
+ *  					- Add EGlpNumIsNeqZero(__EGPa__,__EGPb__)
+ *  					- Add EGlpNumSetToMinAbs(__EGPa__,__EGPb__)
+ * Revision 0.0.1
+ * - 2004-07-15
+ * 						- Add support for GNU_MP_F types
+ * - 2004-07-14
+ * 						- Add support for GNU_MP_Q types
+ * - 2004-07-12
+ * 						- Add support for EG-rationals
+ * - 2004-06-21
+ * 						- First Implementation/Definition
+ * */
+
+/** @file
+ * @ingroup EGlpNum */
+/** @addtogroup EGlpNum */
+/** @{ */
+/* ========================================================================= */
+
+#include <stdlib.h>
+#include <stdint.h>
+
+#include <gmp.h>
+
+/* ========================================================================= */
+/** @name Number Types Definitions:
+ * Define (as its name suggest) an internal identifier for the given 
+ * type. this definitions are provided to select different types of data at 
+ * compile  time, thus allowing us to provide limited template support. */
+/* @{ */
+/** C double type. */
+#define DBL_TYPE 0
+/** C float type. */
+#define FLT_TYPE 1
+/** C int type. */
+#define INT_TYPE 2
+/** EGlib #EGfp10_t type, this is an implementation of fixed precision
+ * arithmetic with 10 bits for fractional representation. */
+#define FP10_TYPE 3
+/** EGlib #EGfp20_t type, this is an implementation of fixed precision
+ * arithmetic with 20 bits for fractional representation. */
+#define FP20_TYPE 4
+/** EGlib #EGfp28_t type, this is an implementation of fixed precision
+ * arithmetic with 28 bits for fractional representation. */
+#define FP28_TYPE 5
+/** EGlib #EGfp25_t type, this is an implementation of fixed precision
+ * arithmetic with 25 bits for fractional representation. */
+#define FP25_TYPE 6
+/** GNU_MP library mpz_t type */
+#define GNU_MP_Z 8
+/** GNU_MP library mpq_t type */
+#define GNU_MP_Q 9
+/** GNU_MP library mpf_t type */
+#define GNU_MP_F 10
+/** C long double type */
+#define LDBL_TYPE 11
+/** C long long int type */
+#define LLINT_TYPE 12
+/** SoftFloat 128-bit floating point numbner */
+#define FLOAT128_TYPE 13
+/** int32_t integers */
+#define INT32_TYPE 14
+/* @} */
+/* ========================================================================= */
+
+/* We have no mpz specific header so we include these here */
+extern const mpz_t __zeroLpNum_mpz__;
+extern const mpz_t __oneLpNum_mpz__;
+extern const mpz_t __MaxLpNum_mpz__;
+extern const mpz_t __MinLpNum_mpz__;
+#define mpz_zeroLpNum __zeroLpNum_mpz__
+#define mpz_oneLpNum  __oneLpNum_mpz__
+#define mpz_epsLpNum  __zeroLpNum_mpz__
+#define mpz_MaxLpNum  __MaxLpNum_mpz__
+#define mpz_MinLpNum  __MinLpNum_mpz__
+
+#include "eg_lpnum.dbl.h"
+#include "eg_lpnum.mpq.h"
+#include "eg_lpnum.mpf.h"
+#include "eg_macros.h"
+#include "eg_mem.h"
+#include "eg_nummacros.h"
+/* ========================================================================= */
+/** @brief Debugging verbosity messages deped on the value of DEBUG (defined in
+ * eg_configure.h) and on the value of EGLPNUM_DEBUGL macro defined here.
+* */
+#define EGLPNUM_DEBUGL 100
+
+/* ========================================================================= */
+/** @brief Set the default number of __BITS__ used in the precision of the
+ * float point numbers (mpf_t), a normal double use up to 56-64 bits., the 
+ * default precision is set to 128 */
+extern unsigned long int EGLPNUM_PRECISION;
+
+/* ========================================================================= */
+/** @brief Change the default precision for mpf_t numbers. */
+void EGlpNumSetPrecision (const unsigned prec);
+
+/* ========================================================================= */
+/** @brief Allocate an array of a given type and store (sizeof(size_t) bytes 
+ * before the actual array) the size of the allocated array. 
+ * @param __type the type of the array to be returned.
+ * @param __size the length of the array to be returned, note that it can be
+ * zero, in wich case no memory allocation is made and NULL is returned. */
+#define __EGlpNumAllocArray(__type,__size) ({\
+	size_t __sz = (__size);\
+	size_t *__utmp = __sz ? (size_t*) EGmalloc (sizeof(__type) * __sz + sizeof(size_t)) : 0;\
+	if(__sz) __utmp[0] = __sz;\
+	(__type*)(__sz ? (__utmp+1):0);})
+
+/* ========================================================================= */
+/** @brief Given an array allocated with __EGlpNumAllocArray, return the size of
+ * the given array, if the array is null, return zero. 
+ * @param __array the array from where we need the size. */
+/* ========================================================================= */
+#define __EGlpNumArraySize(__array) ({\
+	size_t *__utmp = (size_t*)(__array);\
+	if(__utmp) __utmp--;\
+	__utmp ? __utmp[0]:0;})
+
+/* ========================================================================= */
+/** @brief, given an array allocated by __EGlpNumAllocArray, free the allocated
+ * memory.
+ * @param __array the array to be freed, it can be null. The given array will
+ * always pooint to NULL when this function is done.
+ * */
+/* ========================================================================= */
+#define __EGlpNumFreeArray(__array) ({\
+	size_t *__utmp = (size_t*)(__array);\
+	if(__utmp) free (__utmp-1);\
+	(__array) = 0;})
+
+/* ========================================================================= */
+/** @brief indicate if the global data needed for EGlpNum has been initialized,
+ * if zero, initialization routine should be called. This is provided to allow
+ * syncronization between libraries */
+extern int __EGlpNum_setup;
+/* ========================================================================= */
+/** @brief initialization routine for global data. This function is called as a
+ * constructor, but calling it twice won't cause any problems, it is provided
+ * to ensure that all EGlpnum globals are initialized at the beggining 
+ * and in case they where not (__EGlpNMum_setup==0), then call the initializator */
+extern void EGlpNumStart(void);
+/* ========================================================================= */
+/** @brief This function must be called at the end of the program to free all
+ * internal data used in the EGlpNum_t structures, once this function is called
+ * any operation on EGlpNum_t types may fail.
+ * */
+extern void EGlpNumClear(void);
+/* ========================================================================= */
+/** @brief provided for backwards compatibility */
+#define EGlpNumExit EGlpNumClear
+/** @}*/
+/* ========================================================================= */
+/** @name Common EGlpNum Interface functions:
+ * Here we define the basic functions needed to declare when implementing a
+ * number template. */
+/** @{ */
+#ifdef UNUSED_INTERFACE
+/* ========================================================================= */
+/** extern definitions of constants for different set-ups */
+#define zeroLpNum 
+#define oneLpNum 
+#define epsLpNum
+#define MaxLpNum 
+#define MinLpNum
+/* ========================================================================= */
+/** @brief Read from a string a number and store it in the given number, 
+ * @return the number of chars readed from the input string */
+#define EGlpNumReadStr(__EGPa__,__EGPstr__) 
+/* ========================================================================= */
+/** @brief given a int, write it to a string (to be allocated internally), 
+ * and return it. */
+#define EGlpNumGetStr(__EGPa__) 
+/* ========================================================================= */
+/** @brief given an array of type int, free it, if the pointer is NULL
+ * nothing happen. */
+#define EGlpNumFreeArray(__EGParr__)
+/* ========================================================================= */
+/** @brief Reallocate and initialize (if needed) 'size' elements of type 
+ * EGlpNum_t and return it, if no more memory, exit(1) */
+#define EGlpNumReallocArray(__EGPptr__,__EGPsza__) 
+/* ========================================================================= */
+/** @brief Allocate and initialize (if needed) 'size' elements of type int
+ * and return it, if no more memory, exit(1) */
+#define EGlpNumAllocArray(__EGPszb__)
+/* ========================================================================= */
+/** @brief set the given number, set its value to the given double.
+ * @param var where we will store the int value.
+ * @param dbl_var value to be stored in 'var'.
+ * @par Description:
+ * This function is intended to set initial values to variables; note that the
+ * int is a number and not a pointer to that value, be carefull with this
+ * detail. */
+#define EGlpNumSet(__EGPnum__,__EGPdnum__)
+/* ========================================================================= */
+/** @brief Stores in the first number the ceil value of the second number, i.e.
+ * EGlpNumCeil(__EGPa__,__EGPb__) <==> a= ceil(__EGPb__) */
+#define EGlpNumCeil(__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief Stores in the first number the floor value of the second number, i.e.
+ * EGlpNumFloor(__EGPa__,__EGPb__) <==> a= floor(__EGPb__) */
+#define EGlpNumFloor(__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief store the (multiplicative) inverse of a number to itself, i.e.
+ * implement a = 1/a.
+ * @param a the number to be inverted. */
+#define EGlpNumInv(__EGPa__)
+/* ========================================================================= */
+/** @brief Compare if two numbers are equal within a maximum error.
+ * @param a EGlpNum_t first number to compare.
+ * @param b EGlpNum_t second number to compare.
+ * @return int one in success, zero oterwise.
+ * @par Description:
+ * Given two numbers 'a','b' return 1 if a == b, otherwise it return 0
+ * */
+#define EGlpNumIsEqqual(__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief Compare if two numbers are equal within a maximum error.
+ * @param a EGlpNum_t first number to compare.
+ * @param b EGlpNum_t second number to compare.
+ * @param error EGlpNum_t maximum difference allowed between both
+ * numbers.
+ * @return int one in success, zero oterwise.
+ * @par Description:
+ * Given two numbers 'a','b' and a tolerance 'error',
+ * return 1 if |a-b| <= error, otherwise it return 0.
+ * */
+#define EGlpNumIsEqual(__EGPa__,__EGPb__,__EGPerr__)
+/* return 1 if |a-b| > error */
+#define EGlpNumIsNeq(__EGPa__,__EGPb__,__EGPerr__)
+/* return 1 if a == b */
+#define EGlpNumIsNeqq(__EGPa__,__EGPb__)
+/* return 1 if |a| <= error */
+#define EGlpNumIsNeqZero(__EGPa__,__EGPerr__)
+/* return 1 if a!= 0 */
+#define EGlpNumIsNeqqZero(__EGPa__)
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a EGlpNum_t the first number.
+ * @param b EGlpNum_t the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a < b, zero
+ * otherwise.
+ * */
+#define EGlpNumIsLess(__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief test if a numer is greater than zero
+ * @param a number to test
+ * @return int one if success, zero otherwise.
+ * */
+#define EGlpNumIsGreatZero(__EGPa__)
+
+/* ========================================================================= */
+/** @brief test if a numer is less than zero
+ * @param a number to test
+ * @return int one if success, zero otherwise.
+ * */
+#define EGlpNumIsLessZero(__EGPa__)
+/* ========================================================================= */
+/** @brief test if the sum of the first two numbers is less thatn the third
+ * number.
+ * @param a EGlpNum_t the first number.
+ * @param b EGlpNum_t the second number
+ * @param c EGlpNum_t the third number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given a,__EGPb__, and c, return nonzero if (a + b < c), zero toherwise.
+ * */
+#define EGlpNumIsSumLess(__EGPa__,__EGPb__,__EGPc__)
+/* ========================================================================= */
+/** @brief test if the diference of the first two numbers is less thatn the 
+ * third number.
+ * @param a EGlpNum_t the first number.
+ * @param b EGlpNum_t the second number
+ * @param c EGlpNum_t the third number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given a,__EGPb__, and c, return nonzero if (a - b < c), zero toherwise.
+ * */
+#define EGlpNumIsDiffLess(__EGPa__,__EGPb__,__EGPc__)
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a EGlpNum_t the first number.
+ * @param b int the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a < b, zero
+ * otherwise.
+ * */
+#define EGlpNumIsLessDbl(__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a EGlpNum_t the first number.
+ * @param b int the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a > b, zero
+ * otherwise.
+ * */
+#define EGlpNumIsGreaDbl(__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a EGlpNum_t the first number.
+ * @param b EGlpNum_t the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a <= b, zero
+ * otherwise.
+ * */
+#define EGlpNumIsLeq(__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief copy the value of the second number to the first.
+ * @param a EGlpNum_t source number (it won't change value).
+ * @param b EGlpNum_t source number (it won't change value).
+ * @param __EGden__ EGlpNum_t denominator of the difference (it won't change value).
+ * @param __EGdest__ EGlpNum_t where to store the value .
+ * @par Description:
+ * Set __EGdest__ = (a - b) / __EGden__ */
+#define EGlpNumCopyDiffRatio(__EGdest__,__EGPa__,__EGPb__,__EGden__)
+/* ========================================================================= */
+/** @brief copy the value of the second number to the first.
+ * @param a EGlpNum_t source number (it won't change value).
+ * @param b EGlpNum_t source number (it won't change value).
+ * @param __EGdest__ EGlpNum_t where to store the value stored in '__EGorig__'.
+ * @par Description:
+ * Set __EGdest__ = a - b */
+#define EGlpNumCopyDiff(__EGdest__,__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief copy the value of the sum of the second and third parameter
+ * @param a EGlpNum_t source number (it won't change value).
+ * @param b EGlpNum_t source number (it won't change value).
+ * @param __EGdest__ EGlpNum_t where to store the sum.
+ * @par Description:
+ * Set __EGdest__ = a + b */
+#define EGlpNumCopySum(__EGdest__,__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief copy the value of the second number to the first.
+ * @param __EGorig__ EGlpNum_t source number (it won't change value).
+ * @param __EGdest__ EGlpNum_t where to store the value stored in '__EGorig__'.
+ * @par Description:
+ * Given two numbers copy the values in '__EGorig__', into '__EGdest__'.
+ * */
+#define EGlpNumCopy(__EGdest__,__EGorig__)
+/* ========================================================================= */
+/** @brief change the fist number to the maximum between itself and the 
+ * absolute value of the second.
+ * @param __EGorig__ EGlpNum_t source number (it won't change value).
+ * @param __EGdest__ EGlpNum_t where to store the value stored in '__EGorig__'.
+ * @par Description:
+ * implement __EGdest__ = max(__EGdest__,abs(__EGorig__))
+ * */
+#define EGlpNumSetToMaxAbs(__EGdest__,__EGorig__) 
+#define EGlpNumSetToMinAbs(__EGdest__,__EGorig__)
+/* ========================================================================= */
+/** @brief copy the square of the second argument, divided by the third 
+ * argument into the first argument.
+ * @param __EGdest__ EGlpNum_t where to store the result
+ * @param __EGorig__ EGlpNum_t second parameter
+ * @param __EGden__ EGlpNum_t third parameter
+ * @par Description:
+ * compute __EGdest__ = (__EGorig__*__EGorig__)/__EGden__
+ * */
+#define EGlpNumCopySqrOver(__EGdest__,__EGorig__,__EGden__)
+/* ========================================================================= */
+/** @brief copy the value of the absolute value of the second parameter to the 
+ * first parameter.
+ * @param __EGorig__ EGlpNum_t source number (it won't change value).
+ * @param __EGdest__ EGlpNum_t where to store the absolute value stored
+ * in '__EGorig__'.
+ * @par Description:
+ * Given a number '__EGorig__', copy its absolute value to '__EGdest__'. i.e.
+ * __EGdest__ = |__EGorig__|
+ * */
+#define EGlpNumCopyAbs(__EGdest__,__EGorig__)
+/* ========================================================================= */
+/** @brief copy minus the value of the second parameter to the 
+ * first parameter.
+ * @param __EGorig__ EGlpNum_t the source number (it won't change value).
+ * @param __EGdest__ EGlpNum_t where to store minus the value stored
+ * in '__EGorig__'.
+ * @par Description:
+ * Given a number '__EGorig__', copy minus the value to '__EGdest__'. i.e.
+ * __EGdest__ = -__EGorig__
+ * */
+#define EGlpNumCopyNeg(__EGdest__,__EGorig__)
+/* ========================================================================= */
+/** @brief Set des = __EGPa__/__EGPb__.
+ * @param __EGdest__ EGlpNum_t where we will store the result.
+ * @param __EGPa__ EGlpNum_t numerator of the fraction (possibly non an integer)
+ * @param __EGPb__ EGlpNum_t denominator of the fraction (possibly non an integer)
+ * @par Description:
+ *  Set __EGdest__ = __EGPa__/__EGPb__
+ * */
+#define EGlpNumCopyFrac(__EGdest__,__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief copy the first 'size' values in the second array to the first array.
+ * @param __EGorig__ EGlpNum_t* pointer to the array from where we will copy the
+ * values (it won't change value).
+ * @param __EGdest__ EGlpNum_t* pointer to where to store the first 'size' values 
+ * stored in '__EGorig__'.
+ * @param size unsigned int specifying how many values of '__EGorig__' will be copied
+ * onto '__EGdest__'
+ * @par Description:
+ * This function is provided to (possible) make fast copies of arrays of
+ * numbers, the arrays should be of length at least 'size', and the resulting
+ * copy is absolutely independent froom the original, any change in one vale of
+ * one array won't change values on the other array.
+ * */
+#define EGlpNumCopyArray(__EGdest__,__EGorig__,__EGPszb__)
+/* ========================================================================= */
+/** @brief Sub to a given number the product of two numbers.
+ * @param a EGlpNum_t the number that we are going to Sub to.
+ * @param b EGlpNum_t value to be multiplyed.
+ * @param c EGlpNum_t value to be multiplyed.
+ * @par Description:
+ * This function implements a = a - b*c, and clearly don't change the value
+ * stored in 'b' nor in 'c'.
+ * */
+#define EGlpNumSubInnProdTo(__EGPa__,__EGPb__,__EGPc__) 
+/* ========================================================================= */
+/** @brief Add to a given number the product of two numbers.
+ * @param a EGlpNum_t the number that we are going to add to.
+ * @param b EGlpNum_t value to be multiplyed.
+ * @param c EGlpNum_t value to be multiplyed.
+ * @par Description:
+ * This function implements a = a + b*c, and clearly don't change the value
+ * stored in 'b' nor in 'c'.
+ * */
+#define EGlpNumAddInnProdTo(__EGPa__,__EGPb__,__EGPc__)
+/* ========================================================================= */
+/** @brief Substract to a given number the value of the second number.
+ * @param a EGlpNum_t the number that we are going to substract to.
+ * @param b unsigned int value to be substracted to 'a'.
+ * @par Description:
+ * This function implements a = a - b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define EGlpNumSubUiTo(__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief Add to a given number the value of the second number.
+ * @param a EGlpNum_t the number that we are going to add to.
+ * @param b unsigned int value to be added to 'a'.
+ * @par Description:
+ * This function implements a = a + b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define EGlpNumAddUiTo(__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief Add to a given number the value of the second number.
+ * @param a EGlpNum_t the number that we are going to add to.
+ * @param b EGlpNum_t value to be added to 'a'.
+ * @par Description:
+ * This function implements a = a + b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define EGlpNumAddTo(__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief Substract to a given number the value of the second number.
+ * @param a EGlpNum_t the number that we are going to substract
+ * from.
+ * @param b EGlpNum_t value to be substracted to 'a'.
+ * @par Description:
+ * This function implements a = a - b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define EGlpNumSubTo(__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief Multiply a given number by the value of the second number.
+ * @param a EGlpNum_t the number that we are going to multiply by
+ * the second number and store the result.
+ * @param b EGlpNum_t value to be multyply to 'a'.
+ * @par Description:
+ * This function implements a = a * b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define EGlpNumMultTo(__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief Divide a given number by the value of the second number.
+ * @param a EGlpNum_t the number that we are going to divide by
+ * the second number and store the result.
+ * @param b EGlpNum_t value to be divide to 'a'.
+ * @par Description:
+ * This function implements a = a / b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define EGlpNumDivTo(__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief Divide a given number by the value of the second number.
+ * @param a EGlpNum_t the number that we are going to divide by
+ * the second number and store the result.
+ * @param b unsigned int value to be divided to 'a'.
+ * @par Description:
+ * This function implements a = a / b, and don't change the value
+ * stored in 'b'.
+ * */
+#define EGlpNumDivUiTo(__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief Multiply a given number by the value of the second number.
+ * @param a EGlpNum_t the number that we are going to multiply by
+ * the second number and store the result.
+ * @param b unsigned int value to be multyply to 'a'.
+ * @par Description:
+ * This function implements a = a * b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define EGlpNumMultUiTo(__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief Reset the value of the pointed number to zero.
+ * @param a EGlpNum_t the value to be set to zero.
+ * @par Descrpition:
+ * Reset a to zero, i.e. implements a = 0;
+ * */
+#define EGlpNumZero(__EGPa__)
+/* ========================================================================= */
+/** @brief Reset the value of the pointed number to one.
+ * @param a EGlpNum_t value to be set to one.
+ * @par Descrpition:
+ * Reset a to zero, i.e. implements a = 1;
+ * */
+#define EGlpNumOne(__EGPa__)
+/* ========================================================================= */
+/** @brief Change the sign of the number.
+ * @param a EGlpNum_t number we will change sign.
+ * @par Descrpition:
+ * Change the sign of the given number, i.e. implements a = -a
+ * */
+#define EGlpNumSign(__EGPa__)
+/* ========================================================================= */
+/** @brief return the closest double value of the given pointer number.
+ * @param a EGlpNum_t number that we will be transformed to int.
+ * @return int the closest int representation of the given number.
+ * par Description:
+ * return the int number closest in value to the value stored in a.
+ * */
+#define EGlpNumToLf(__EGPa__)
+/* ========================================================================= */
+/** @brief initialize the internal memory of a given variable and set its
+ * initial value to zero */
+#define EGlpNumInitVar(__EGPa__)
+
+/* ========================================================================= */
+/** @brief free the internal memory of a given variable */
+#define EGlpNumClearVar(__EGPa__)
+#endif
+ /** @} */
+/* ========================================================================= */
+/** @brief Sort (in increasing order) a sub-set of entries in an array using 
+ * quicksort, by permutating the order of the elements in the subset rather 
+ * than in the whole original array.
+ * @param sz length of the permutation array.
+ * @param perm array of indices of elements that we want to sort.
+ * @param elem array (of length at least max(perm[k]:k=0,...,sz-1)) containing
+ * the elements to be sorted.
+ * @note The array of elements is not changed by this function.
+ * @note This code is based in concorde's implementation of
+ * permutation-quick-sort.
+ * */
+void uint32_EGutilPermSort (const size_t sz,
+										 int *const perm,
+										 const uint32_t * const elem);
+
+/* ========================================================================= */
+/** @brief Sort (in decreasing order) a sub-set of entries in an array using 
+ * quicksort, by permutating the order of the elements in the subset rather 
+ * than in the whole original array.
+ * @param sz length of the permutation array.
+ * @param perm array of indices of elements that we want to sort.
+ * @param elem array (of length at least max(perm[k]:k=0,...,sz-1)) containing
+ * the elements to be sorted.
+ * @note The array of elements is not changed by this function.
+ * @note This code is based in concorde's implementation of
+ * permutation-quick-sort.
+ * */
+void uint32_EGutilPermSort2 (const size_t sz,
+										 int*const perm,
+										 const uint32_t*const elem);
+
+
+/* ========================================================================= */
+#endif
diff --git a/qsopt_ex/eg_lpnum.mpf.h b/qsopt_ex/eg_lpnum.mpf.h
new file mode 100644
index 0000000..640afde
--- /dev/null
+++ b/qsopt_ex/eg_lpnum.mpf.h
@@ -0,0 +1,628 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library 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 Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * */
+#ifndef __EG_LPNUM_MPF__
+#define __EG_LPNUM_MPF__
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <gmp.h>
+
+#include "eg_lpnum.h"
+
+/** @file
+ * @ingroup EGlpNum */
+/** @addtogroup EGlpNum */
+/** @{ */
+/* ========================================================================= */
+/** @brief This is the smallest difference (with the current precision) that can
+ * be distinguished betwen 1.0 and it's clossest representable number, in some
+ * sense it is the absolute minimum epsilon for comparisons */
+extern mpf_t mpf_eps;
+
+/* ========================================================================= */
+/** extern definitions of constaants for different set-ups */
+extern const mpf_t __zeroLpNum_mpf__;
+extern const mpf_t __oneLpNum_mpf__;
+extern const mpf_t __MaxLpNum_mpf__;
+extern const mpf_t __MinLpNum_mpf__;
+#define mpf_zeroLpNum __zeroLpNum_mpf__
+#define mpf_oneLpNum  __oneLpNum_mpf__
+#define mpf_epsLpNum  mpf_eps
+#define mpf_MaxLpNum  __MaxLpNum_mpf__
+#define mpf_MinLpNum  __MinLpNum_mpf__
+
+/* ========================================================================= */
+/** @brief Given a double exp, compute \f$ e^{exp} \f$ and store it in the given
+ * mpf_t number.
+ * @param exp double exponent to be used.
+ * @param num mpf_t number where to store the result.
+ * */
+#define mpf_EGlpNumEpow(num,exp) ({\
+	unsigned int __i = 0;\
+	int __lsgn = (exp)<0 ? 1:0;\
+	mpf_t __ntmp,__res,__lexp,__err;\
+	mpf_init_set_d(__lexp,exp);\
+	if(__lsgn) mpf_neg(__lexp,__lexp);\
+	mpf_init_set_ui(__ntmp,(unsigned long int)1);\
+	mpf_init_set_ui(__res,(unsigned long int)1);\
+	mpf_init(__err);\
+	mpf_div(__err,__ntmp,__res);\
+	while(mpf_cmp(__err,mpf_eps)>0)\
+	{\
+		mpf_mul(__ntmp,__ntmp,__lexp);\
+		mpf_div_ui(__ntmp,__ntmp,(unsigned long int)(++__i));\
+		mpf_add(__res,__res,__ntmp);\
+		mpf_div(__err,__ntmp,__res);\
+	}\
+	if(__lsgn) mpf_ui_div(num,(unsigned long int)1,__res);\
+	else mpf_set(num,__res);\
+	mpf_clear(__ntmp);\
+	mpf_clear(__res);\
+	mpf_clear(__err);\
+	mpf_clear(__lexp);})
+
+/* ========================================================================= */
+/** @brief Read from a string a number and store it in the given mpf_t, 
+ * @return the number of chars readed from the input string */
+#define mpf_EGlpNumReadStr(a,str) ({\
+	int __i =0;\
+	char __lpstr__[4096];\
+	mp_exp_t __lexp;\
+	mpf_set_str(a,str,10);\
+	mpf_get_str(__lpstr__,&__lexp,10,(size_t)0,a);\
+	__i = strlen(__lpstr__);\
+	__i;})
+
+/* ========================================================================= */
+/** @brief given a mpf_t, write it to a string (to be allocated internally),
+ * and return it. */
+#define mpf_EGlpNumGetStr(a) ({\
+	char *__out= 0;\
+	mp_exp_t __lexp = 0;\
+	size_t __pos = 0,__lo = (mpf_cmp_ui(a,(unsigned long)0) < 0) ? 1:0;\
+	char __lpstr__[4096];\
+	mpf_get_str(__lpstr__,&__lexp,10,(size_t)25,a);\
+	__pos = strlen(__lpstr__) + ((size_t)(__lo + 2));\
+	__out = EGsMalloc(char,__pos+((size_t)15));\
+	if(__lo) sprintf(__out,"-0.");\
+	else sprintf(__out,"0.");\
+	sprintf(__out+__lo+2,"%s",__lpstr__+__lo);\
+	if(__pos == 2) __out[1] = '\0';\
+	else if(__lexp != 0)\
+	{\
+		__out[__pos-__lo] = 'e';\
+		snprintf(__out+__pos+1-__lo,(size_t)(12-__lo),"%d",(int)__lexp);\
+	}\
+	__out;})
+
+/* ========================================================================= */
+/** @brief given an array of type mpf_t, free it, if the pointer is NULL
+ * nothing happen. */
+#define mpf_EGlpNumFreeArray(ea) ({\
+	size_t __sz = __EGlpNumArraySize(ea);\
+	mpf_t* __ptr__ = (ea);\
+	while(__sz--) mpf_clear(__ptr__[__sz]);\
+	__EGlpNumFreeArray(ea);})
+
+
+/* ========================================================================= */
+/** @brief Reallocate and initialize (if needed) 'size' elements of type 
+ * mpf_t and return it, if no more memory, exit(1) */
+#define mpf_EGlpNumReallocArray(lptr, lsize) ({ \
+	mpf_t** __ptr__ = (lptr); \
+	size_t __sz__ = (lsize); \
+	size_t *__ntmp__ = (size_t *) *__ptr__; \
+	size_t __psz__; \
+	/* if no memory allocated before we just call the regular allocator */ \
+	if (!*__ptr__) *__ptr__ = mpf_EGlpNumAllocArray (__sz__); \
+	else \
+	{ \
+		/* first check that the previous size is not larger than the current */ \
+		__ntmp__--; \
+		__psz__ = __ntmp__[0]; \
+		if (__psz__ < __sz__) \
+		{ \
+			/* now we have to do the reallocation */ \
+			*__ptr__ = (mpf_t *) __ntmp__; \
+			*__ptr__ = EGrealloc(*__ptr__, sizeof(mpf_t) * __sz__ +sizeof(size_t));\
+			__ntmp__ = (size_t *) *__ptr__; \
+			__ntmp__[0] = __sz__; \
+			__ntmp__++; \
+			*__ptr__ = (mpf_t *) __ntmp__; \
+			for (; __psz__ < __sz__; __psz__++) mpf_init ((*__ptr__)[__psz__]); \
+		} \
+	} \
+})
+
+/* ========================================================================= */
+/** @brief Allocate and initialize (if needed) 'size' elements of type mpf_t
+ * and return it, if no more memory, exit(1) */
+#define mpf_EGlpNumAllocArray(size) ({\
+	size_t __i__ = (size);\
+	mpf_t *__res = __EGlpNumAllocArray(mpf_t,__i__);\
+	while(__i__--) mpf_init(__res[__i__]);\
+	__res;})
+
+/* ========================================================================= */
+/** @brief set the given number pointer, set its value to the given double.
+ * @param var mpf_t where we will store the double value.
+ * @param dbl double value to be stored in 'var'.
+ * @par Description:
+ * This function is intended to set initial values to variables; note that the
+ * double is a number and not a pointer to that value, be carefull with this
+ * detail. Also, due to implementation details this function can't deal with
+ * numbers above 1e158 or smaller than 1e-158. Note also that if the number is
+ * writen in the form \f$x=\bar{x}\cdot 2^e\f$ with \f$0.5<|\bar{x}|<1\f$, 
+ * then \f$\left|x-\frac{p}{q}\right|<2^{e-64}\f$.
+ * */
+#define mpf_EGlpNumSet(var, dbl) mpf_set_d(var,(double)(dbl))
+
+/* ========================================================================= */
+/** @brief Stores in the first number the ceil value of the second number, i.e.
+ * EGlpNumCeil(a,b) <==> a= ceil(b) */
+#define mpf_EGlpNumCeil(a, b) mpf_ceil(a,b)
+
+/* ========================================================================= */
+/** @brief Stores in the first number the floor value of the second number, i.e.
+ * EGlpNumFloor(a,b) <==> a= floor(b) */
+#define mpf_EGlpNumFloor(a, b) mpf_floor(a,b)
+
+/* ========================================================================= */
+/** @brief store the (multiplicative) inverse of a number to itself, i.e.
+ * implement a = 1/a.
+ * @param a the number to be inverted. */
+#define mpf_EGlpNumInv(a) mpf_ui_div(a,(unsigned long int)1,a)
+
+/* ========================================================================= */
+/** @brief Compare if two numbers are equal within a maximum __error.
+ * @param a mpf_t first number to compare.
+ * @param b mpf_t second number to compare.
+ * @return int one in success, zero oterwise.
+ * @par Description:
+ * Given two numbers 'a','b' return 1 if a == b, otherwise it return 0
+ * */
+#define mpf_EGlpNumIsEqqual(a,b) (mpf_cmp(a,b) == 0)
+
+/* ========================================================================= */
+/** @brief Compare if two numbers are equal within a maximum __error.
+ * @param a mpf_t first number to compare.
+ * @param b mpf_t second number to compare.
+ * @param __error mpf_t maximum difference allowed between both
+ * numbers.
+ * @return int one in success, zero oterwise.
+ * @par Description:
+ * Given two numbers 'a','b' and a tolerance '__error',
+ * return 1 if |a-b|<= __error, otherwise it return 0.
+ * */
+#define mpf_EGlpNumIsEqual(a,b,__error) ({\
+	mpf_t __lpnum__;int __res__=0;mpf_init(__lpnum__);\
+	mpf_sub (__lpnum__, a, b);\
+	mpf_abs (__lpnum__, __lpnum__);\
+	__res__=(mpf_cmp (__lpnum__, __error) <= 0);\
+	mpf_clear(__lpnum__);\
+	__res__;\
+})
+
+#define mpf_EGlpNumIsNeq(a,b,__error) ({\
+	mpf_t __lpnum__;int __res__=0;mpf_init(__lpnum__);\
+	mpf_sub (__lpnum__, a, b);\
+	mpf_abs (__lpnum__, __lpnum__);\
+	__res__=(mpf_cmp (__lpnum__, __error) > 0);\
+	mpf_clear(__lpnum__);\
+	__res__;\
+})
+
+#define mpf_EGlpNumIsNeqZero(a,__error) ({\
+	mpf_t __lpnum__;int __res__=0;mpf_init(__lpnum__);\
+	mpf_abs (__lpnum__, a);\
+	__res__=(mpf_cmp (__lpnum__, __error) > 0);\
+	mpf_clear(__lpnum__);\
+	__res__;\
+})
+
+#define mpf_EGlpNumIsNeqqZero(a)     	(mpf_sgn(a))
+#define mpf_EGlpNumIsNeqq(a,b)        (mpf_cmp(a,b)!=0)
+
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a mpf_t the first number.
+ * @param b mpf_t the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a < b, zero
+ * otherwise.
+ * */
+#define mpf_EGlpNumIsLess(a,b) (mpf_cmp(a,b) < 0)
+
+/* ========================================================================= */
+/** @brief test if a given number is greater than zero
+ * @param a number to test
+ * @return int one if success, zero otherwise.
+ * */
+#define mpf_EGlpNumIsGreatZero(a) (mpf_sgn(a) > 0)
+
+/* ========================================================================= */
+/** @brief test if a given number is less than zero
+ * @param a number to test
+ * @return int one if success, zero otherwise.
+ * */
+#define mpf_EGlpNumIsLessZero(a) (mpf_sgn(a) < 0)
+
+/* ========================================================================= */
+/** @brief test if the sum of the first two numbers is less thatn the third
+ * number.
+ * @param a mpf_t the first number.
+ * @param b mpf_t the second number
+ * @param c mpf_t the third number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given a,b, and c, return nonzero if (a + b < c), zero toherwise.
+ * */
+#define mpf_EGlpNumIsSumLess(a, b, c) ({\
+	mpf_t __lpnum__;int __res__=0;mpf_init(__lpnum__);\
+	mpf_add (__lpnum__, a, b);\
+	__res__=(mpf_cmp (__lpnum__, c) < 0);\
+	mpf_clear(__lpnum__);\
+	__res__;\
+})
+
+/* ========================================================================= */
+/** @brief test if the diference of the first two numbers is less thatn the 
+ * third number.
+ * @param a mpf_t the first number.
+ * @param b mpf_t the second number
+ * @param c mpf_t the third number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given a,b, and c, return nonzero if (a - b < c), zero toherwise.
+ * */
+#define mpf_EGlpNumIsDiffLess(a, b, c) ({\
+	mpf_t __lpnum__;int __res__=0;mpf_init(__lpnum__);\
+	mpf_sub (__lpnum__, a, b);\
+	__res__=(mpf_cmp (__lpnum__, c) < 0);\
+	mpf_clear(__lpnum__);\
+	__res__;\
+})
+
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a mpf_t the first number.
+ * @param b double the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a < b, zero
+ * otherwise.
+ * */
+#define mpf_EGlpNumIsLessDbl(a,b) (mpf_cmp_d(a,((double)(b))) < 0)
+
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a mpf_t the first number.
+ * @param b double the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a > b, zero
+ * otherwise.
+ * */
+#define mpf_EGlpNumIsGreaDbl(a,b) (mpf_cmp_d(a,((double)(b))) > 0)
+
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a mpf_t the first number.
+ * @param b mpf_t the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a <= b, zero
+ * otherwise.
+ * */
+#define mpf_EGlpNumIsLeq(a,b) (mpf_cmp(a,b) <= 0)
+
+/* ========================================================================= */
+/** @brief copy the value of the second number to the first.
+ * @param a mpf_t source number (it won't change value).
+ * @param b mpf_t source number (it won't change value).
+ * @param c mpf_t denominator of the difference (it won't change value).
+ * @param d mpf_t where to store the value .
+ * @par Description:
+ * Set @f$a = \frac{b - c}{d} @f$ */
+#define mpf_EGlpNumCopyDiffRatio(a, b, c, d) ({\
+	mpf_sub (a, b, c);\
+	mpf_div (a, a, d);\
+})
+
+/* ========================================================================= */
+/** @brief copy the value of the second number to the first.
+ * @param a mpf_t source number (it won't change value).
+ * @param b mpf_t source number (it won't change value).
+ * @param dest mpf_t where to store the value stored in 'orig'.
+ * @par Description:
+ * Set dest = a - b */
+#define mpf_EGlpNumCopyDiff(dest,a,b) mpf_sub(dest,a,b)
+
+/* ========================================================================= */
+/** @brief copy the value of the sum of the second and third parameter
+ * @param a mpf_t source number (it won't change value).
+ * @param b mpf_t source number (it won't change value).
+ * @param dest mpf_t where to store the sum.
+ * @par Description:
+ * Set dest = a + b */
+#define mpf_EGlpNumCopySum(dest,a,b) mpf_add(dest,a,b)
+
+/* ========================================================================= */
+/** @brief copy the value of the second number to the first.
+ * @param orig mpf_t source number (it won't change value).
+ * @param dest mpf_t where to store the value stored in 'orig'.
+ * @par Description:
+ * Given two numbers copy the values in 'orig', into 'dest'.
+ * */
+#define mpf_EGlpNumCopy(dest,orig) mpf_set(dest,orig)
+
+/* ========================================================================= */
+/** @brief change the fist number to the maximum between itself and the 
+ * absolute value of the second.
+ * @param orig mpf_t source number (it won't change value).
+ * @param dest mpf_t where to store the value stored in 'orig'.
+ * @par Description:
+ * implement dest = max(dest,abs(orig))
+ * */
+#define mpf_EGlpNumSetToMaxAbs(dest, orig) ({\
+	mpf_t __lpnum__;mpf_init(__lpnum__);\
+	mpf_abs (__lpnum__, orig);\
+	if (mpf_cmp (dest, __lpnum__) < 0) mpf_set (dest, __lpnum__);\
+	mpf_clear(__lpnum__);})
+
+#define mpf_EGlpNumSetToMinAbs(dest, orig) ({\
+	mpf_t __lpnum__;mpf_init(__lpnum__);\
+	mpf_abs (__lpnum__, orig);\
+	if (mpf_cmp (dest, __lpnum__) > 0) mpf_set (dest, __lpnum__);\
+	mpf_clear(__lpnum__);})
+
+/* ========================================================================= */
+/** @brief copy the square of the second argument, divided by the third 
+ * argument into the first argument.
+ * @param dest mpf_t where to store the result
+ * @param orig mpf_t second parameter
+ * @param den mpf_t third parameter
+ * @par Description:
+ * compute dest = (orig*orig)/den
+ * */
+#define mpf_EGlpNumCopySqrOver(dest, orig, den) ({\
+	mpf_mul (dest, orig, orig);\
+	mpf_div (dest, dest, den);\
+})
+
+/* ========================================================================= */
+/** @brief copy the value of the absolute value of the second parameter to the 
+ * first parameter.
+ * @param orig mpf_t source number (it won't change value).
+ * @param dest mpf_t where to store the absolute value stored
+ * in 'orig'.
+ * @par Description:
+ * Given a number 'orig', copy its absolute value to 'dest'. i.e.
+ * dest = |orig|
+ * */
+#define mpf_EGlpNumCopyAbs(dest,orig) mpf_abs(dest,orig)
+
+/* ========================================================================= */
+/** @brief copy minus the value of the second parameter to the 
+ * first parameter.
+ * @param orig mpf_t the source number (it won't change value).
+ * @param dest mpf_t where to store minus the value stored
+ * in 'orig'.
+ * @par Description:
+ * Given a number 'orig', copy minus the value to 'dest'. i.e.
+ * dest = -orig
+ * */
+#define mpf_EGlpNumCopyNeg(dest,orig) mpf_neg(dest,orig)
+
+/* ========================================================================= */
+/** @brief Set des = op1/op2.
+ * @param dest mpf_t where we will store the result.
+ * @param op1 mpf_t numerator of the fraction (possibly non an integer)
+ * @param op2 mpf_t denominator of the fraction (possibly non an integer)
+ * @par Description:
+ *  Set des = op1/op2
+ * */
+#define mpf_EGlpNumCopyFrac(dest,op1,op2) mpf_div(dest,op1,op2)
+
+/* ========================================================================= */
+/** @brief copy the first 'size' values in the second array to the first array.
+ * @param orig mpf_t* pointer to the array from where we will copy the
+ * values (it won't change value).
+ * @param dest mpf_t* pointer to where to store the first 'size' values 
+ * stored in 'orig'.
+ * @param size unsigned int specifying how many values of 'orig' will be copied
+ * onto 'dest'
+ * @par Description:
+ * This function is provided to (possible) make fast copies of arrays of
+ * numbers, the arrays should be of length at least 'size', and the resulting
+ * copy is absolutely independent froom the original, any change in one vale of
+ * one array won't change values on the other array.
+ * */
+#define mpf_EGlpNumCopyArray(dest,orig,size) {\
+	register unsigned int __i__ = (size);\
+	for(;__i__--;)\
+	{\
+		mpf_set(dest[__i__],orig[__i__]);\
+	}\
+}
+
+/* ========================================================================= */
+/** @brief Sub to a given number the product of two numbers.
+ * @param a mpf_t the number that we are going to Sub to.
+ * @param b mpf_t value to be multiplyed.
+ * @param c mpf_t value to be multiplyed.
+ * @par Description:
+ * This function implements a = a - b*c, and clearly don't change the value
+ * stored in 'b' nor in 'c'.
+ * */
+#define mpf_EGlpNumSubInnProdTo(a, b, c) ({\
+	mpf_t __lpnum__;mpf_init(__lpnum__);\
+	mpf_mul (__lpnum__, b, c);\
+	mpf_sub (a, a, __lpnum__);\
+	mpf_clear(__lpnum__);\
+})
+
+/* ========================================================================= */
+/** @brief Add to a given number the product of two numbers.
+ * @param a mpf_t the number that we are going to add to.
+ * @param b mpf_t value to be multiplyed.
+ * @param c mpf_t value to be multiplyed.
+ * @par Description:
+ * This function implements a = a + b*c, and clearly don't change the value
+ * stored in 'b' nor in 'c'.
+ * */
+#define mpf_EGlpNumAddInnProdTo(a, b, c) ({\
+	mpf_t __lpnum__;mpf_init(__lpnum__);\
+	mpf_mul (__lpnum__, b, c);\
+	mpf_add (a, a, __lpnum__);\
+	mpf_clear(__lpnum__);\
+})
+
+/* ========================================================================= */
+/** @brief Substract to a given number the value of the second number.
+ * @param a mpf_t the number that we are going to substract to.
+ * @param b unsigned int value to be substracted to 'a'.
+ * @par Description:
+ * This function implements a = a - b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define mpf_EGlpNumSubUiTo(a,b) mpf_sub_ui(a,a,((unsigned long)(b)))
+
+/* ========================================================================= */
+/** @brief Add to a given number the value of the second number.
+ * @param a mpf_t the number that we are going to add to.
+ * @param b unsigned int value to be added to 'a'.
+ * @par Description:
+ * This function implements a = a + b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define mpf_EGlpNumAddUiTo(a,b) mpf_add_ui(a,a,((unsigned long)(b)))
+
+/* ========================================================================= */
+/** @brief Add to a given number the value of the second number.
+ * @param a mpf_t the number that we are going to add to.
+ * @param b mpf_t value to be added to 'a'.
+ * @par Description:
+ * This function implements a = a + b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define mpf_EGlpNumAddTo(a,b) mpf_add(a,a,b)
+
+/* ========================================================================= */
+/** @brief Substract to a given number the value of the second number.
+ * @param a mpf_t the number that we are going to substract
+ * from.
+ * @param b mpf_t value to be substracted to 'a'.
+ * @par Description:
+ * This function implements a = a - b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define mpf_EGlpNumSubTo(a,b) mpf_sub(a,a,b)
+
+/* ========================================================================= */
+/** @brief Multiply a given number by the value of the second number.
+ * @param a mpf_t the number that we are going to multiply by
+ * the second number and store the result.
+ * @param b mpf_t value to be multyply to 'a'.
+ * @par Description:
+ * This function implements a = a * b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define mpf_EGlpNumMultTo(a,b) mpf_mul(a,a,b)
+
+/* ========================================================================= */
+/** @brief Divide a given number by the value of the second number.
+ * @param a mpf_t the number that we are going to divide by
+ * the second number and store the result.
+ * @param b mpf_t value to be divide to 'a'.
+ * @par Description:
+ * This function implements a = a / b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define mpf_EGlpNumDivTo(a,b) mpf_div(a,a,b)
+
+/* ========================================================================= */
+/** @brief Divide a given number by the value of the second number.
+ * @param a mpf_t the number that we are going to divide by
+ * the second number and store the result.
+ * @param b unsigned int value to be divided to 'a'.
+ * @par Description:
+ * This function implements a = a / b, and don't change the value
+ * stored in 'b'.
+ * */
+#define mpf_EGlpNumDivUiTo(a,b) mpf_div_ui(a,a,((unsigned long)(b)))
+
+/* ========================================================================= */
+/** @brief Multiply a given number by the value of the second number.
+ * @param a mpf_t the number that we are going to multiply by
+ * the second number and store the result.
+ * @param b unsigned int value to be multyply to 'a'.
+ * @par Description:
+ * This function implements a = a * b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define mpf_EGlpNumMultUiTo(a,b) mpf_mul_ui(a,a,((unsigned long)(b)))
+
+/* ========================================================================= */
+/** @brief Reset the value of the pointed number to zero.
+ * @param a mpf_t the value to be set to zero.
+ * @par Descrpition:
+ * Reset a to zero, i.e. implements a = 0;
+ * */
+#define mpf_EGlpNumZero(a) mpf_set_ui(a,(unsigned long)0)
+
+/* ========================================================================= */
+/** @brief Reset the value of the pointed number to one.
+ * @param a mpf_t value to be set to one.
+ * @par Descrpition:
+ * Reset a to zero, i.e. implements a = 1;
+ * */
+#define mpf_EGlpNumOne(a) mpf_set_ui(a,(unsigned long)1)
+
+/* ========================================================================= */
+/** @brief Change the sign of the number.
+ * @param a mpf_t number we will change sign.
+ * @par Descrpition:
+ * Change the sign of the given number, i.e. implements a = -a
+ * */
+#define mpf_EGlpNumSign(a) mpf_neg(a,a)
+
+/* ========================================================================= */
+/** @brief return the closest double value of the given pointer number.
+ * @param a mpf_t number that we will be transformed to double.
+ * @return double the closest double representation of the given number.
+ * par Description:
+ * return the double number closest in value to the value stored in a.
+ * */
+#define mpf_EGlpNumToLf(a) mpf_get_d(a)
+
+/* ========================================================================= */
+/** @brief initialize the internal memory of a given variable */
+#define mpf_EGlpNumInitVar(a) mpf_init(a)
+
+/* ========================================================================= */
+/** @brief free the internal memory of a given variable */
+#define mpf_EGlpNumClearVar(a) mpf_clear(a)
+
+/* ========================================================================= */
+/** @} */
+#endif
diff --git a/qsopt_ex/eg_lpnum.mpq.h b/qsopt_ex/eg_lpnum.mpq.h
new file mode 100644
index 0000000..e04c83b
--- /dev/null
+++ b/qsopt_ex/eg_lpnum.mpq.h
@@ -0,0 +1,596 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library 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 Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
+ * */
+#ifndef __EG_LPNUM_MPQ__
+#define __EG_LPNUM_MPQ__
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <gmp.h>
+
+#include "eg_lpnum.h"
+
+/** @file
+ * @brief Interface for rational implementation of the EGlpNum_t type.
+ * @par History
+ * - 2006-02-01
+ * 					- Add verbosity flag for continued fraction conversions.
+ * @ingroup EGlpNum */
+/** @addtogroup EGlpNum */
+/** @{ */
+/* ========================================================================= */
+/** extern definitions of constaants for different set-ups */
+extern const mpq_t __zeroLpNum_mpq__;
+extern const mpq_t __oneLpNum_mpq__;
+extern const mpq_t __MaxLpNum_mpq__;
+extern const mpq_t __MinLpNum_mpq__;
+#define mpq_zeroLpNum __zeroLpNum_mpq__
+#define mpq_oneLpNum  __oneLpNum_mpq__
+#define mpq_epsLpNum  __zeroLpNum_mpq__
+#define mpq_MaxLpNum  __MaxLpNum_mpq__
+#define mpq_MinLpNum  __MinLpNum_mpq__
+
+/* ========================================================================= */
+/** @brief This function read a number in float form and store it in an mpq_t
+ * variable, returning how many chars read to create the number, the twist is
+ * that it does an 'exact' transformation, in the sense that 0.33333333 will be
+ * stored as 33333333/100000000.
+ * @param str input string.
+ * @param var variable where we will store the number as rational.
+ * @return number of reade chars.
+ * @par Descriptiom:
+ * If the input string doesn't contain a number, 'var' will be set to zero, and
+ * the number of readed chars will be zero, we assume that there are no leading
+ * empty spaces, (nor tabs), no eschape characters, and trailing zeros are
+ * considered as readed, but no the following spaces. 
+ * @note
+ * This function will only read number in decimal base, in a future release we
+ * may include a more general reader. */
+int mpq_EGlpNumReadStrXc (mpq_t var,
+													char const *str);
+
+/* ========================================================================= */
+/** @brief Read from a string a number and store it in the given mpq_t, return
+ * the number of chars readed from the input string */
+#define mpq_EGlpNumReadStr(a,str) mpq_EGlpNumReadStrXc(a,str)
+
+/* ========================================================================= */
+/** @brief given a mpq_t, write it to a string (to be allocated internally), 
+ * and return it. */
+#define mpq_EGlpNumGetStr(a) ({\
+	const size_t __sz = mpz_sizeinbase(mpq_numref(a),10) + mpz_sizeinbase(mpq_denref(a),10) + 3;\
+	char *__str=EGsMalloc(char,__sz);\
+	mpq_get_str(__str,10,a);})
+
+/* ========================================================================= */
+/** @brief given an array of type mpq_t, free it, if the pointer is NULL
+ * nothing happen. */
+#define mpq_EGlpNumFreeArray(ea) ({\
+	size_t __sz = __EGlpNumArraySize(ea);\
+	mpq_t* __ptr__ = (ea);\
+	while(__sz--) mpq_clear(__ptr__[__sz]);\
+	__EGlpNumFreeArray(ea);})
+
+
+/* ========================================================================= */
+/** @brief Reallocate and initialize (if needed) 'size' elements of type 
+ * mpq_t and return it, if no more memory, exit(1) */
+#define mpq_EGlpNumReallocArray(lptr, lsize) ({\
+	mpq_t **__ptr__ = (lptr);\
+	size_t *__ntmp__ = (size_t *) *__ptr__, __sz__ = (lsize);\
+	size_t __psz__;\
+	/* if no memory allocated before we just call the regular allocator */\
+	if (!*__ptr__)\
+		*__ptr__ = mpq_EGlpNumAllocArray (__sz__);\
+	else\
+	{\
+		/* first check that the previous size is not larger than the current */\
+		__ntmp__--;\
+		__psz__ = __ntmp__[0];\
+		if (__psz__ < __sz__)\
+		{\
+			/* now we have to do the reallocation */\
+			*__ptr__ = (mpq_t *) __ntmp__;\
+			*__ptr__ = EGrealloc(*__ptr__,sizeof(mpq_t) * __sz__ + sizeof(size_t));\
+			__ntmp__ = (size_t *) *__ptr__;\
+			__ntmp__[0] = __sz__;\
+			__ntmp__++;\
+			*__ptr__ = (mpq_t *) __ntmp__;\
+			for (; __psz__ < __sz__; __psz__++) mpq_init ((*__ptr__)[__psz__]);\
+		}\
+	}\
+})
+
+/* ========================================================================= */
+/** @brief Allocate and initialize (if needed) 'size' elements of type mpq_t
+ * and return it, if no more memory, exit(1) */
+#define mpq_EGlpNumAllocArray(size) ({\
+	size_t __i__ = (size);\
+	mpq_t *__res = __EGlpNumAllocArray(mpq_t,__i__);\
+	while(__i__--) mpq_init(__res[__i__]);\
+	__res;})
+
+/* ========================================================================= */
+/** @brief set the given rational number , to the value to the value of the 
+ * given mpf_t, this conversion is done using the continuous fraction method.
+ * @param var mpq_t where we will store the value.
+ * @param flt mpf_t value to be stored in 'var'.
+ * @par Description:
+ * This function is intended to set initial values to variables. Note also 
+ * that if the number is
+ * writen in the form \f$x=\bar{x}\cdot 2^e\f$ with \f$0.5<|\bar{x}|<1\f$, 
+ * then \f$\left|x-\frac{p}{q}\right|<2^{e-EGLPNUM_PRECISION}\f$.
+ * */
+void mpq_EGlpNumSet_mpf (mpq_t var,
+												 mpf_t flt);
+
+/* ========================================================================= */
+/** @brief set the given number pointer, set its value to the given double.
+ * @param var mpq_t where we will store the double value.
+ * @param dbl double value to be stored in 'var'.
+ * @par Description:
+ * This function is intended to set initial values to variables; note that the
+ * double is a number and not a pointer to that value, be carefull with this
+ * detail. Also, due to implementation details this function can't deal with
+ * numbers above 1e158 or smaller than 1e-158. Note also that if the number is
+ * writen in the form \f$x=\bar{x}\cdot 2^e\f$ with \f$0.5<|\bar{x}|<1\f$, 
+ * then \f$\left|x-\frac{p}{q}\right|<2^{e-64}\f$.
+ * */
+void mpq_EGlpNumSet (mpq_t var,
+										 const double dbl);
+
+/* ========================================================================= */
+/** @brief Stores in the first number the ceil value of the second number, i.e.
+ * EGlpNumCeil(a,b) <==> a= ceil(b) */
+#define mpq_EGlpNumCeil(a, b) ({\
+	mpz_cdiv_q (mpq_numref (a), mpq_numref (b), mpq_denref (b));\
+	mpz_set_ui (mpq_denref (a), (unsigned long int)1);\
+})
+
+/* ========================================================================= */
+/** @brief Stores in the first number the floor value of the second number, i.e.
+ * EGlpNumFloor(a,b) <==> a= floor(b) */
+#define mpq_EGlpNumFloor(a, b) ({\
+	mpz_fdiv_q (mpq_numref (a), mpq_numref (b), mpq_denref (b));\
+	mpz_set_ui (mpq_denref (a), (unsigned long int)1);\
+})
+
+/* ========================================================================= */
+/** @brief store the (multiplicative) inverse of a number to itself, i.e.
+ * implement a = 1/a.
+ * @param a the number to be inverted. */
+#define mpq_EGlpNumInv(a) mpq_inv(a,a)
+
+/* ========================================================================= */
+/** @brief Compare if two numbers are equal within a maximum error.
+ * @param a mpq_t first number to compare.
+ * @param b mpq_t second number to compare.
+ * @return int one in success, zero oterwise.
+ * @par Description:
+ * Given two numbers 'a','b' return 1 if a == b, otherwise it return 0
+ * */
+#define mpq_EGlpNumIsEqqual(a,b) (mpq_equal(a,b))
+
+/* ========================================================================= */
+/** @brief Compare if two numbers are equal within a maximum error.
+ * @param a mpq_t first number to compare.
+ * @param b mpq_t second number to compare.
+ * @param error mpq_t maximum difference allowed between both
+ * numbers.
+ * @return int one in success, zero oterwise.
+ * @par Description:
+ * Given two numbers 'a','b' and a tolerance 'error',
+ * return 1 if |a-b|<= error, otherwise it return 0.
+ * */
+#define mpq_EGlpNumIsEqual(a,b,error) (mpq_equal(a,b))
+#define mpq_EGlpNumIsNeq(a,b,error)   (!(mpq_equal(a,b)))
+#define mpq_EGlpNumIsNeqq(a,b)        (!(mpq_equal(a,b)))
+#define mpq_EGlpNumIsNeqZero(a,error) (mpq_sgn(a))
+#define mpq_EGlpNumIsNeqqZero(a)      (mpq_sgn(a))
+
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a mpq_t the first number.
+ * @param b mpq_t the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a < b, zero
+ * otherwise.
+ * */
+#define mpq_EGlpNumIsLess(a,b) (mpq_cmp(a,b) < 0)
+
+/* ========================================================================= */
+/** @brief test if a number is greater than zero
+ * @param a number to test
+ * @return int one if success, zero otherwise.
+ * */
+#define mpq_EGlpNumIsGreatZero(a) (mpq_sgn(a) > 0)
+
+/* ========================================================================= */
+/** @brief test if a number is less than zero
+ * @param a number to test
+ * @return int one if success, zero otherwise.
+ * */
+#define mpq_EGlpNumIsLessZero(a) (mpq_sgn(a) < 0)
+
+/* ========================================================================= */
+/** @brief test if the sum of the first two numbers is less thatn the third
+ * number.
+ * @param a mpq_t the first number.
+ * @param b mpq_t the second number
+ * @param c mpq_t the third number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given a,b, and c, return nonzero if (a + b < c), zero toherwise.
+ * */
+#define mpq_EGlpNumIsSumLess(a, b, c) ({\
+	mpq_t __lpnum__;int __res__=0;mpq_init(__lpnum__);\
+	mpq_add(__lpnum__,a,b);\
+	__res__=(mpq_cmp (__lpnum__, c) < 0);\
+	mpq_clear(__lpnum__);\
+	__res__;\
+})
+
+/* ========================================================================= */
+/** @brief test if the diference of the first two numbers is less thatn the 
+ * third number.
+ * @param a mpq_t the first number.
+ * @param b mpq_t the second number
+ * @param c mpq_t the third number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given a,b, and c, return nonzero if (a - b < c), zero toherwise.
+ * */
+#define mpq_EGlpNumIsDiffLess(a, b, c) ({\
+	mpq_t __lpnum__;int __res__=0;mpq_init(__lpnum__);\
+	mpq_sub (__lpnum__, a, b);\
+	__res__=(mpq_cmp (__lpnum__, c) < 0);\
+	mpq_clear(__lpnum__);\
+	__res__;\
+})
+
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a mpq_t the first number.
+ * @param b double the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a < b, zero
+ * otherwise.
+ * */
+#define mpq_EGlpNumIsLessDbl(a,b) (mpq_get_d(a) < b)
+
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a mpq_t the first number.
+ * @param b double the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a > b, zero
+ * otherwise.
+ * */
+#define mpq_EGlpNumIsGreaDbl(a,b) (mpq_get_d(a) > b)
+
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a mpq_t the first number.
+ * @param b mpq_t the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a <= b, zero
+ * otherwise.
+ * */
+#define mpq_EGlpNumIsLeq(a,b) (mpq_cmp(a,b) <= 0)
+
+/* ========================================================================= */
+/** @brief copy the value of the second number to the first.
+ * @param a mpq_t source number (it won't change value).
+ * @param b mpq_t source number (it won't change value).
+ * @param c mpq_t denominator of the difference (it won't change value).
+ * @param d mpq_t where to store the value .
+ * @par Description:
+ * Set @f$a = \frac{b - c}{d} @f$ */
+#define mpq_EGlpNumCopyDiffRatio(a, b, c, d) ({\
+	mpq_sub (a, b, c);\
+	mpq_div (a, a, d);\
+})
+
+/* ========================================================================= */
+/** @brief copy the value of the second number to the first.
+ * @param a mpq_t source number (it won't change value).
+ * @param b mpq_t source number (it won't change value).
+ * @param dest mpq_t where to store the value stored in 'orig'.
+ * @par Description:
+ * Set dest = a - b */
+#define mpq_EGlpNumCopyDiff(dest,a,b) mpq_sub(dest,a,b)
+
+/* ========================================================================= */
+/** @brief copy the value of the sum of the second and third parameter
+ * @param a mpq_t source number (it won't change value).
+ * @param b mpq_t source number (it won't change value).
+ * @param dest mpq_t where to store the sum.
+ * @par Description:
+ * Set dest = a + b */
+#define mpq_EGlpNumCopySum(dest,a,b) mpq_add(dest,a,b)
+
+/* ========================================================================= */
+/** @brief copy the value of the second number to the first.
+ * @param orig mpq_t source number (it won't change value).
+ * @param dest mpq_t where to store the value stored in 'orig'.
+ * @par Description:
+ * Given two numbers copy the values in 'orig', into 'dest'.
+ * */
+#define mpq_EGlpNumCopy(dest,orig) mpq_set(dest,orig)
+
+/* ========================================================================= */
+/** @brief change the fist number to the maximum between itself and the 
+ * absolute value of the second.
+ * @param orig mpq_t source number (it won't change value).
+ * @param dest mpq_t where to store the value stored in 'orig'.
+ * @par Description:
+ * implement dest = max(dest,abs(orig))
+ * */
+#define mpq_EGlpNumSetToMaxAbs(dest, orig) ({\
+	mpq_t __lpnum__;mpq_init(__lpnum__);\
+	mpq_abs (__lpnum__, orig);\
+	if (mpq_cmp (dest, __lpnum__) < 0)\
+		mpq_set (dest, __lpnum__);\
+	mpq_clear(__lpnum__);\
+})
+
+#define mpq_EGlpNumSetToMinAbs(dest, orig) ({\
+	mpq_t __lpnum__;mpq_init(__lpnum__);\
+	mpq_abs (__lpnum__, orig);\
+	if (mpq_cmp (dest, __lpnum__) > 0)\
+		mpq_set (dest, __lpnum__);\
+	mpq_clear(__lpnum__);\
+})
+
+/* ========================================================================= */
+/** @brief copy the square of the second argument, divided by the third 
+ * argument into the first argument.
+ * @param dest mpq_t where to store the result
+ * @param orig mpq_t second parameter
+ * @param den mpq_t third parameter
+ * @par Description:
+ * compute dest = (orig*orig)/den
+ * */
+#define mpq_EGlpNumCopySqrOver(dest, orig, den) ({\
+	mpq_mul (dest, orig, orig);\
+	mpq_div (dest, dest, den);\
+})
+
+/* ========================================================================= */
+/** @brief copy the value of the absolute value of the second parameter to the 
+ * first parameter.
+ * @param orig mpq_t source number (it won't change value).
+ * @param dest mpq_t where to store the absolute value stored
+ * in 'orig'.
+ * @par Description:
+ * Given a number 'orig', copy its absolute value to 'dest'. i.e.
+ * dest = |orig|
+ * */
+#define mpq_EGlpNumCopyAbs(dest,orig) mpq_abs(dest,orig)
+
+/* ========================================================================= */
+/** @brief copy minus the value of the second parameter to the 
+ * first parameter.
+ * @param orig mpq_t the source number (it won't change value).
+ * @param dest mpq_t where to store minus the value stored
+ * in 'orig'.
+ * @par Description:
+ * Given a number 'orig', copy minus the value to 'dest'. i.e.
+ * dest = -orig
+ * */
+#define mpq_EGlpNumCopyNeg(dest,orig) mpq_neg(dest,orig)
+
+/* ========================================================================= */
+/** @brief Set des = op1/op2.
+ * @param dest mpq_t where we will store the result.
+ * @param op1 mpq_t numerator of the fraction (possibly non an integer)
+ * @param op2 mpq_t denominator of the fraction (possibly non an integer)
+ * @par Description:
+ *  Set des = op1/op2
+ * */
+#define mpq_EGlpNumCopyFrac(dest,op1,op2) mpq_div(dest,op1,op2)
+
+/* ========================================================================= */
+/** @brief copy the first 'size' values in the second array to the first array.
+ * @param orig mpq_t* pointer to the array from where we will copy the
+ * values (it won't change value).
+ * @param dest mpq_t* pointer to where to store the first 'size' values 
+ * stored in 'orig'.
+ * @param size unsigned int specifying how many values of 'orig' will be copied
+ * onto 'dest'
+ * @par Description:
+ * This function is provided to (possible) make fast copies of arrays of
+ * numbers, the arrays should be of length at least 'size', and the resulting
+ * copy is absolutely independent froom the original, any change in one vale of
+ * one array won't change values on the other array.
+ * */
+#define mpq_EGlpNumCopyArray(dest,orig,size) {\
+	register unsigned int __i__ = size;\
+	for(;__i__--;)\
+	{\
+		mpq_set(dest[__i__],orig[__i__]);\
+	}\
+}
+
+/* ========================================================================= */
+/** @brief Sub to a given number the product of two numbers.
+ * @param a mpq_t the number that we are going to Sub to.
+ * @param b mpq_t value to be multiplyed.
+ * @param c mpq_t value to be multiplyed.
+ * @par Description:
+ * This function implements a = a - b*c, and clearly don't change the value
+ * stored in 'b' nor in 'c'.
+ * */
+#define mpq_EGlpNumSubInnProdTo(a, b, c) ({\
+	mpq_t __lpnum__;mpq_init(__lpnum__);\
+	mpq_mul (__lpnum__, b, c);\
+	mpq_sub (a, a, __lpnum__);\
+	mpq_clear(__lpnum__);\
+})
+
+/* ========================================================================= */
+/** @brief Add to a given number the product of two numbers.
+ * @param a mpq_t the number that we are going to add to.
+ * @param b mpq_t value to be multiplyed.
+ * @param c mpq_t value to be multiplyed.
+ * @par Description:
+ * This function implements a = a + b*c, and clearly don't change the value
+ * stored in 'b' nor in 'c'.
+ * */
+#define mpq_EGlpNumAddInnProdTo(a, b, c) ({\
+	mpq_t __lpnum__;mpq_init(__lpnum__);\
+	mpq_mul (__lpnum__, b, c);\
+	mpq_add (a, a, __lpnum__);\
+	mpq_clear(__lpnum__);\
+})
+
+/* ========================================================================= */
+/** @brief Substract to a given number the value of the second number.
+ * @param a mpq_t the number that we are going to substract to.
+ * @param b unsigned int value to be substracted to 'a'.
+ * @par Description:
+ * This function implements a = a - b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define mpq_EGlpNumSubUiTo(a,b) mpz_submul_ui(mpq_numref(a),mpq_denref(a),(unsigned long int)b)
+
+/* ========================================================================= */
+/** @brief Add to a given number the value of the second number.
+ * @param a mpq_t the number that we are going to add to.
+ * @param b unsigned int value to be added to 'a'.
+ * @par Description:
+ * This function implements a = a + b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define mpq_EGlpNumAddUiTo(a,b) mpz_addmul_ui(mpq_numref(a),mpq_denref(a),(unsigned long int)b)
+
+/* ========================================================================= */
+/** @brief Add to a given number the value of the second number.
+ * @param a mpq_t the number that we are going to add to.
+ * @param b mpq_t value to be added to 'a'.
+ * @par Description:
+ * This function implements a = a + b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define mpq_EGlpNumAddTo(a,b) mpq_add(a,a,b)
+
+/* ========================================================================= */
+/** @brief Substract to a given number the value of the second number.
+ * @param a mpq_t the number that we are going to substract
+ * from.
+ * @param b mpq_t value to be substracted to 'a'.
+ * @par Description:
+ * This function implements a = a - b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define mpq_EGlpNumSubTo(a,b) mpq_sub(a,a,b)
+
+/* ========================================================================= */
+/** @brief Multiply a given number by the value of the second number.
+ * @param a mpq_t the number that we are going to multiply by
+ * the second number and store the result.
+ * @param b mpq_t value to be multyply to 'a'.
+ * @par Description:
+ * This function implements a = a * b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define mpq_EGlpNumMultTo(a,b) mpq_mul(a,a,b)
+
+/* ========================================================================= */
+/** @brief Divide a given number by the value of the second number.
+ * @param a mpq_t the number that we are going to divide by
+ * the second number and store the result.
+ * @param b mpq_t value to be divide to 'a'.
+ * @par Description:
+ * This function implements a = a / b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define mpq_EGlpNumDivTo(a,b) mpq_div(a,a,b)
+
+/* ========================================================================= */
+/** @brief Divide a given number by the value of the second number.
+ * @param a mpq_t the number that we are going to divide by
+ * the second number and store the result.
+ * @param b unsigned int value to be divided to 'a'.
+ * @par Description:
+ * This function implements a = a / b, and don't change the value
+ * stored in 'b'.
+ * */
+#define mpq_EGlpNumDivUiTo(a,b) do{mpz_mul_ui(mpq_denref(a),mpq_denref(a),(unsigned long)b);mpq_canonicalize(a);}while(0)
+
+/* ========================================================================= */
+/** @brief Multiply a given number by the value of the second number.
+ * @param a mpq_t the number that we are going to multiply by
+ * the second number and store the result.
+ * @param b unsigned int value to be multyply to 'a'.
+ * @par Description:
+ * This function implements a = a * b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define mpq_EGlpNumMultUiTo(a,b) do{mpz_mul_ui(mpq_numref(a),mpq_numref(a),(unsigned long int)b);mpq_canonicalize(a);}while(0)
+
+/* ========================================================================= */
+/** @brief Reset the value of the pointed number to zero.
+ * @param a mpq_t the value to be set to zero.
+ * @par Descrpition:
+ * Reset a to zero, i.e. implements a = 0;
+ * */
+#define mpq_EGlpNumZero(a) mpq_set_ui(a,(unsigned long)0,(unsigned long)1)
+
+/* ========================================================================= */
+/** @brief Reset the value of the pointed number to one.
+ * @param a mpq_t value to be set to one.
+ * @par Descrpition:
+ * Reset a to zero, i.e. implements a = 1;
+ * */
+#define mpq_EGlpNumOne(a) mpq_set_ui(a,(unsigned long)1,(unsigned long)1)
+
+/* ========================================================================= */
+/** @brief Change the sign of the number.
+ * @param a mpq_t number we will change sign.
+ * @par Descrpition:
+ * Change the sign of the given number, i.e. implements a = -a
+ * */
+#define mpq_EGlpNumSign(a) mpq_neg(a,a)
+
+/* ========================================================================= */
+/** @brief return the closest double value of the given pointer number.
+ * @param a mpq_t number that we will be transformed to double.
+ * @return double the closest double representation of the given number.
+ * par Description:
+ * return the double number closest in value to the value stored in a.
+ * */
+#define mpq_EGlpNumToLf(a) mpq_get_d(a)
+
+/* ========================================================================= */
+/** @brief initialize the internal memory of a given variable */
+#define mpq_EGlpNumInitVar(a) mpq_init(a)
+
+/* ========================================================================= */
+/** @brief free the internal memory of a given variable */
+#define mpq_EGlpNumClearVar(a) mpq_clear(a)
+
+/* ========================================================================= */
+/** @} */
+#endif
diff --git a/qsopt_ex/eg_macros.c b/qsopt_ex/eg_macros.c
new file mode 100644
index 0000000..42140ef
--- /dev/null
+++ b/qsopt_ex/eg_macros.c
@@ -0,0 +1,148 @@
+/* ========================================================================= */
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library 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 Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
+ * */
+/* ========================================================================= */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/utsname.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "eg_macros.h"
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+/** @file
+ * @brief implementation of some macros.
+ *
+ * @version 0.9.2 
+ * @par History:
+ * 	-2006-09-28
+ * 						- First implementation
+ *	-2007-12-06
+ *						- Add versioning information in header
+ * @ingroup EGmacros */
+/** @addtogroup EGmacros */
+/** @{ */
+/* ========================================================================= */
+void EGlib_info(void)
+{
+	int rval;
+	struct utsname uts;
+	rval = uname(&uts);
+	if(rval)
+	{
+		QSlog("Can't get host info");
+	}
+	else
+	{
+		QSlog("Host: %s, %s %s %s", uts.nodename, uts.sysname, uts.release, uts.machine);
+		QSlog("Current process id: %d", (int)getpid());
+	}
+}
+/** @} */
+/* ========================================================================= */
+jmp_buf __EGljmp;
+/* ========================================================================= */
+void EGsighandler(int s)
+{
+	switch(s)
+	{
+		case SIGXCPU:
+			/* time is over */ 
+			QSlog("TIME_LIMIT_REACHED (ending now)");
+			longjmp(__EGljmp,s);
+			break;
+		case SIGINT:
+		case SIGTERM:
+		case SIGTSTP:
+			/* time is over */ 
+			QSlog("USER_INTERRUPT (ending now)");
+			longjmp(__EGljmp,s);
+			break;
+		case SIGSEGV:
+			/* Memory is over or segmentation fault */
+			QSlog("MEMORY_LIMIT_REACHED (ending now)");
+			longjmp(__EGljmp,s);
+			break;
+		case SIGABRT:
+			/* something is sending an abort code.... stop execution, report the
+			 * signal, do destruction and report and end */
+			QSlog("SIGABRT received (ending now)");
+			longjmp(__EGljmp,s);
+			break;
+		default:
+			QSlog("Unkown signal %d", s);
+			QSlog("Ending with status %d", s);
+			exit(s);
+	}
+}
+/* ========================================================================= */
+void __EGsigSetSignal(void)
+{
+	signal(SIGXCPU,EGsighandler);
+	signal(SIGINT,EGsighandler);
+	signal(SIGSEGV,EGsighandler);
+	signal(SIGABRT,EGsighandler);
+}
+/* ========================================================================= */
+void EGsetLimits(double max_rtime, unsigned long memlimit)
+{
+	struct rlimit mlim;
+	WARNIF(getrlimit(RLIMIT_CPU,&mlim));
+	MESSAGE(0, "Cur rtime limit %ld, trying to set to %lg", mlim.rlim_cur, max_rtime);
+	if(max_rtime > mlim.rlim_max) max_rtime = (double)mlim.rlim_max;
+	mlim.rlim_cur = (rlim_t)max_rtime;
+	WARNIF(setrlimit(RLIMIT_CPU,&mlim));
+	MESSAGE(0, "New rtime limit %ld (%.3lg)", mlim.rlim_cur, max_rtime);
+	WARNIF(getrlimit(RLIMIT_DATA,&mlim));
+	MESSAGE(0, "Cur data limit %ld,%ld (soft,hard)", mlim.rlim_cur, 
+					mlim.rlim_max);
+	mlim.rlim_cur = memlimit;				
+	WARNIF( setrlimit(RLIMIT_DATA,&mlim));
+	WARNIF( getrlimit(RLIMIT_DATA,&mlim));
+	MESSAGE(0, "New data limit %ld,%ld (soft,hard)", mlim.rlim_cur, 
+					mlim.rlim_max);
+	WARNIF( getrlimit(RLIMIT_AS,&mlim));
+	MESSAGE(0, "Cur address space limit %ld,%ld (soft,hard)", 
+					mlim.rlim_cur, mlim.rlim_max);
+	mlim.rlim_cur = memlimit;	
+	WARNIF( setrlimit(RLIMIT_AS,&mlim));				
+	WARNIF( getrlimit(RLIMIT_AS,&mlim));
+	MESSAGE(0, "New address space limit %ld,%ld (soft,hard)", 
+					mlim.rlim_cur, mlim.rlim_max);
+	mlim.rlim_cur = 0;
+	WARNIF( setrlimit(RLIMIT_CORE,&mlim));				
+	WARNIF( getrlimit(RLIMIT_CORE,&mlim));
+	MESSAGE(0, "New core dump space limit %ld,%ld (soft,hard)", 
+					mlim.rlim_cur, mlim.rlim_max);
+	return;
+}
+/* ========================================================================= */
+/* end of eg_macros.c */
diff --git a/qsopt_ex/eg_macros.h b/qsopt_ex/eg_macros.h
new file mode 100644
index 0000000..1866041
--- /dev/null
+++ b/qsopt_ex/eg_macros.h
@@ -0,0 +1,270 @@
+/* ========================================================================= */
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library 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 Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
+ * */
+/* ========================================================================= */
+/** @defgroup EGmacros General Macros
+ * global macros and types for EGlib
+ *
+ * @version 0.9.2 
+ * @par History:
+ * - 2013-04-30
+ * 						- Add EGaGetCElem EGaGetElem EGaGetPos to get array-based pointers and
+ * 						positions
+ * - 2012-10-12
+ * 						- Add TESTGD that jumps automatically to CLEANUP
+ * - 2011-12-06
+ * 						- Add generic signal handler and necesary macros
+ * - 2011-05-16
+ * 						- Add WARNIF(xxx) to warn (on screen) non-zero return values
+ * - 2010-08-31
+ * 						- Add EGcallD(xxx) short hand to EGcall(rval,CLEANUP,xxx)
+ * - 2010-04-30
+ * 						- Add IFMESSAGE messaging macro
+ * - 2010-02-20
+ * 						- Add EGcall macro to resume tracing calls.
+ * - 2009-07-21
+ * 						- Change macro-variables to __name convention to avoid name
+ * 						clashes
+ * - 2008-08-29
+ * 						- Add EG_RETURN
+ * - 2008-07-24
+ * 						- Add TESTGL
+ * - 2007-12-07
+ * 						- Add FTESTG and FTEST, that always test the parameters
+ * 							regardless of the debug level
+ * - 2007-01-19
+ * 						- Delete EGosGetOffset
+ * - 2006-09-28
+ * 						- Add function that display basic process information, including
+ * 						version and date of compilation of EGlib
+ * - 2005-12-19
+ * 						- Add float128 support ussing SoftFloat.
+ * - 2005-10-28
+ * 						- Add some status definitions for algorithms.
+ * - 2005-06-14
+ * 						- Add strdup definition, just for cleanliness when compiling
+ * - 2005-05-23
+ * 						- Add EGcontainerOf
+ * - 2005-05-03
+ * 						- Add typeof definition;
+ * - 2004-07-14
+ * 						- Add GNU_MP_Z GNU_MP_F and GNU_MP_Q to the type definitions.
+ * - 2004-07-12
+ * 						- Add EGRAT_TYPE to the type definitions.
+ * - 2004-03-17
+ * 						- Add TESTG that if recives something that is nonzero print an
+ * 							user message and the go to the given location.
+ * - 2004-02-05
+ * 						- Add CHECKRVALG that checks a return value, display a mesage,
+ * 							and then perform a goto.
+ * - 2003-12-01
+ * 						- Add definition of a 'copy' function and its MP version.
+ * - 2003-11-20
+ * 						- Add PTRTEST that check if a pointer points to the first 64Kb of
+ * 							memory internal memory. Althought such situation may happend 
+ * 							(if we work in kernel-related stuff), it is usually an error 
+ * 							when we try to access such a memory.
+ * - 2003-09-08
+ * 						- Add ADVTESTL
+ * - 2003-07-10
+ * 						- Add MESSAGEF, ADVCHECKRVAL
+ * - 2003-07-02
+ * 						- Add EGosGetData, EGosSetData, EGosGetOffset
+ * - 2003-06-16
+ * 						- Add EXITL macro
+ * - 2003-06-06 
+ * 						- Add TESTL macro to test conditions but only when the debug
+ * 							level is at least some value
+ * - 2003-05-22 
+ * 						- Add EXITRVAL
+ * - 2003-05-15 
+ * 						- Add CHECKRVAL MESSAGE and WARNING macros.
+ * - 2003-05-08 
+ * 						- Add support for variadic macros for EXIT and TEST
+ * 						- Define EGRAND_MAX for SUN and LINUX acordingly, this is becouse 
+ * 							for some reason the value of RAND_MAX in SUN is not as 
+ * 							specified in stdlib.h but rather 1 << 31 - 1. Still I am not 
+ * 							sure about the maximum value of rand() on sun... will fix that 
+ * 							later on to.
+ * 						- Add a mesage macro, it only print if the debug level is as high
+ * 							as required by the first field. Again the definition is
+ * 							variadric and if the debug level is 0 we reduce the macro to 
+ * 							the empty instruction.
+ *
+ * */
+/**  @{ */
+/** @file 
+ * */
+/* ========================================================================= */
+
+#ifndef __EG_MACROS_H__
+#define __EG_MACROS_H__
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <setjmp.h>
+#include <errno.h>
+
+/* ========================================================================= */
+/** @brief return the offset of a member inside a structure.
+ * @param type the type of the containing structure.
+ * @param member the name of the member that we are interested in compute the
+ * offset.
+ * @return the number of bytes between the member and the beginning of the
+ * structure. */
+#define EGoffsetOf(__type,__member) ((size_t) &((__type *)0)->__member)
+
+/* ========================================================================= */
+/** @brief given a pointer to a member of a structure, return the pointer to
+ * the head of the structure. (idea taken from Linux Kernel).
+ * @param __ptr pointer to the member of the containing structure.
+ * @param __type name type of the containing structure.
+ * @param __member name of the given member in the containing structure.
+ * @return pointer to the containing structure.
+ * */
+#define EGcontainerOf(__ptr,__type,__member) ({\
+	typeof(((__type *)0)->__member) *const __EGcOf_ptr = (__ptr);\
+	(__type *)( (char*)__EGcOf_ptr - ((size_t) &((__type *)0)->__member));})
+
+/* ========================================================================= */
+/** @brief retrieve the data of type '__TYPE' in the structure '__DATA' that is 
+ * located in the offset '__OFFS'. */
+#define EGosGetData(__DATA,__OFFS,__TYPE) (*((__TYPE*)(((char*)__DATA)+__OFFS)))
+
+/* ========================================================================= */
+/** @brief set the data of type '__TYPE' in the structure '__DATA' that is 
+ * located in the offset '__OFFS' to the value 'val'. */
+#define EGosSetData(__DATA,__OFFS,__TYPE,val) (EGosGetData(__DATA,__OFFS,__TYPE)=val)
+
+/* ========================================================================= */
+/** @brief Defione copy functions, these functions
+ * return copy of objects but with independent storage space, there are two
+ * versions, one that require a memory pool from where to look for memory, and
+ * another where we don't care about that.... the place from where the memory
+ * was asked for depend on the function, se the function definition for 
+ * details.
+ * Note that if the is no more memory available the function should call
+ * exit(EXIT_FAILURE).
+ * This is only intended as a readibility help */
+typedef void *(*EGcopy_f) (void *p);
+
+/* ========================================================================= */
+/** @brief Define a null copy function */
+#define nullCopy ((EGcopy_f)0)
+
+/* ========================================================================= */
+/** @name Algorithms Return Status
+ * Here we define some general status for algorithms, the exact meaning should
+ * be sought in the actual algorithm definition, but the definitions here
+ * provide a first overview of their meaning. */
+/*  @{  */
+/** @brief the algorithm finish successfully. */
+#define EG_ALGSTAT_SUCCESS 0
+/** @brief the algorithm could only partially finish */
+#define EG_ALGSTAT_PARTIAL 1
+/** @brief the algorithm stop because of some numerical problem */
+#define EG_ALGSTAT_NUMERROR 2
+/** @brief the algorithm stop because of some unforeseen error */
+#define EG_ALGSTAT_ERROR 3
+/* @} */
+
+/* ========================================================================= */
+/** @name Mathematical Constants 
+ * Here we define some mathematical constants needed in some parts of the code
+ * that are of general use */
+/* @{ */
+/** @brief definition of \f$\pi\f$ as a constant, suitable for quad-IEEE
+ * operations. */
+#define EG_M_PI 3.1415926535897932384626433832795029L
+/* @} */
+
+/* ========================================================================= */
+/** @brief Call macro. The idea is to replace the following call:
+ * rval = myfunction(mypar);
+ * CHECKRVALG(rval,mygoto);
+ * with the call
+ * EGcall(rval,mygoto,myfunction(mypar));
+ * this should help simplify calls and clean-up the code
+ * @note each parameter is evaluated once, thus ensuring correct evaluation of
+ * parameters, even if they are an expresion. */
+#define EGcall(__rval__,__cleanup__,__myfunc__) do{const int __EGrval__=__myfunc__;(__rval__)=__EGrval__;TESTG(__EGrval__,__cleanup__,"Function " #__myfunc__ " failed with code %d ",__EGrval__);}while(0)
+/* ========================================================================= */
+/** @brief call macro with default arguments, it assumes that rval is an
+ * integer variable to be used to store return value, and CLEANUP is a valid
+ * label for an exit point in the code */
+#define EGcallD(__myfunc2__) EGcall(rval,CLEANUP,__myfunc2__)
+/* ========================================================================= */
+/** @brief Display information about the library and the running process */
+void EGlib_info(void);
+/* ========================================================================= */
+/** @brief print versioning info of the library */
+void EGlib_version(void);
+/* ========================================================================= */
+/** @brief needed global jump-control variable */
+extern jmp_buf __EGljmp;
+/* ========================================================================= */
+/** @brief a generic signal handler, it can handle SIGXCPU, SIGINT and SIGSEGV
+ * signals by displaying a proper indication to stderr; note that a call to
+ * #EGsigSetjmp should be performed at the very beggining of the main function
+ * for this to be robust.
+ * When receiving a SIGXCPU, SIGINT signal, the function report the signal and jump-back
+ * to the setjmp position.
+ * When receiving a SIGINT signal, the function report the signal and jump-back
+ * @param s the signal number received
+ * */
+void EGsighandler(int s);
+/* ========================================================================= */
+/** @brief use #EGsighandler for SIGXCPU, SIGINT and SIGSEGV as signal handler.
+ * */
+void __EGsigSetSignal(void);
+/* ========================================================================= */
+/** @brief set the jump point, and the sginal handler.
+ * it must receive a label where to jump, and where
+ * to save the returning status, typically this will be the clean-up section 
+ * of the main function and the status variable in the mian program.
+ * @param __status__ the returning status of the call, zero when set, non-zero
+ * when comming back from a long-jump.
+ * @param __LABEL__ where to jump when returning from a long-jump. */
+#define EGsigSet(__status__,__LABEL__) do{MESSAGE(0,"setjmp here");if((__status__=setjmp(__EGljmp))){IFMESSAGE(1,"Back from signal handler, status %d",__status__); goto __LABEL__;}__EGsigSetSignal();}while(0)
+/* ========================================================================= */
+/** @brief set memory and run-time limits (soft and hard); if the current
+ * limits are bellow the porposed limits, it will warn on screen, but will not
+ * fail. Note that this function will set RLMIT_CORE to zero.
+ * @param max_rtime maximum running time.
+ * @param mem_limit maximum memory allowed for the process, this include
+ * RLIMIT_AS and RLIMIT_DATA.
+ * */
+void EGsetLimits(double max_rtime, unsigned long memlimit);
+/* ========================================================================= */
+/** @brief given a constant array-base, an element size, and a position, 
+ * return the pointer to the appropiate element */
+#define EGaGetCElem(__EGabase__,__EGasz__,__EGaelem__) ((const char*)(((const char*)(__EGabase__))+((const size_t)(__EGasz__))*((const size_t)(__EGaelem__))))
+/* ========================================================================= */
+/** @brief given an array-base, an element size, and a position, return the
+ * pointer to the appropiate element */
+#define EGaGetElem(__EGabase__,__EGasz__,__EGaelem__) ((char*)(((char*)(__EGabase__))+((const size_t)(__EGasz__))*((const size_t)(__EGaelem__))))
+/* ========================================================================= */
+/** @brief given an array base, an element size, and a pointer, return the
+ * position of the element on the array */
+#define EGaGetPos(__EGabase__,__EGasz__,__EGaptr__) ((((char*)(__EGaptr__))-((char*)(__EGabase__)))/((const size_t)(__EGasz__)))
+/* ========================================================================= */
+/**  @}  */
+/* end of eg_macros.h */
+#endif
diff --git a/qsopt_ex/eg_mem.h b/qsopt_ex/eg_mem.h
new file mode 100644
index 0000000..42c4896
--- /dev/null
+++ b/qsopt_ex/eg_mem.h
@@ -0,0 +1,194 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library 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 Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
+ * */
+/* ========================================================================= */
+/** @defgroup EGmem EGmem
+ *
+ * Here we define some usefull macros to deal with memory issues, for example,
+ * assert that we always return memory when posible, and if no memory is found,
+ * then we just exit to the system (because if there is trully no memory....
+ * there is no much else to do... unless we start using shrinkable memory
+ * pools, like for example @ref EGmemSlab , but that is still a long way off,
+ * it will also perform (if debugging enabled) some allocation / freeing
+ * checkings and so on.
+ *
+ * @version 0.0.1
+ * @par History:
+ * -2005-09-05
+ * 					- Add EGrealloc, wich is a wrapper of realloc but that assures us
+ * 					to have memory, if there is no  memory, we exit. The idea of these
+ * 					functions is that in the future they would interact with the
+ * 					memory pools to use any memory still in the pools.
+ * -2005-08-20
+ * 					- Move memory align definitions here, and set the aligment of
+ * 						memory to 8 bytes (i.e. 64 bits). This is to simplify compilation
+ * 						in diferent architectures like Sun, opteron 64 and intel 32.
+ * -2005-08-01
+ * 					- Fix calloc call to the right type (size_t), and some printing
+ * 						issues while compiling on 64-bit architectures.
+ * -2005-07-30
+ * 					- First Implementation
+ * */
+/** @file
+ * @ingroup EGmem */
+/** @addtogroup EGmem */
+/** @{ */
+#ifndef __EG_MEM_H__
+#define __EG_MEM_H__
+
+#include "eg_macros.h"
+
+/* ========================================================================= */
+/** @brief size of a normal word in this machine (a word is just big enough to
+ * store a pointer) */
+#define EG_MEM_WORD_SIZE (sizeof(void*))
+/* ========================================================================= */
+/** @brief memory aligment used by EG alloc functions. */
+#define EG_MEM_ALIGNMENT 8U
+
+/* ========================================================================= */
+/** @brief \f$log_2(EG_MEM_ALIGNMENT)\f$. */
+#define EG_MEM_ALIGNMENT_SHIFT 3U
+
+/* ========================================================================= */
+/** @brief Given a pointer, return it's aligned value. */
+#define EG_MEM_ALIGN(__ptr) \
+	((((size_t)__ptr)+EG_MEM_ALIGNMENT-1)&(~(EG_MEM_ALIGNMENT-1)))
+
+/* ========================================================================= */
+/** @brief type of the free functions that recive only one parameter */
+typedef void (*EGfree_f) (void *);
+
+/* ========================================================================= */
+/** @brief this is the the data free that does nothing, use it when you don't 
+ * want/need to free the internal list data becouse you will do it 
+ * elsewere */
+#define nullFree ((EGfree_f)0)
+
+/* ========================================================================= */
+/** @brief custom allocation functions prototype: This class of functions
+ * receive some user-provided data (udata), and given a size (psz), return a pointer of the given size */
+typedef void*(*EGualloc_f)(void*udata,size_t psz);
+
+/* ========================================================================= */
+/** @brief custom free functions prototype: This class of functions receive
+ * some user-provided data (udata), and a pointer (ptr), and should free (or
+ * manage de-alocation) of the provided pointer. */
+typedef void (*EGufree_f)(void*udata,void*ptr);
+
+/* ========================================================================= */
+/** @brief type for constructor functions. Given a pointer to an element of
+ * some type, do the internal initialization necesary so that we can work with
+ * the lement, such initialization may include allocating some internal memory
+ * needed by the structure (not done by the user). This functions must never
+ * fail. if some unexpected error does happen inside, then the function should
+ * not return. (a call to exit(1) would do the trick). */
+typedef void (*EGconstructor_f) (void *);
+
+/* ========================================================================= */
+/** @brief Null constructor function (do nothing) */
+#define nullConstructor ((EGconstructor_f)0)
+
+/* ========================================================================= */
+/** @brief type for destructor functions. Given a pointer to an element of some
+ * type, free all internal memory related to the element allocated during the
+ * construction phase. (but not the pointer itself). This function must always
+ * succed, if an error happen, the function should never return. (a call to
+ * exit(1) would do the trick). */
+typedef void (*EGdestructor_f) (void *);
+
+/* ========================================================================= */
+/** @brief Null destructor function (do nothing) */
+#define nullDestructor ((EGdestructor_f)0)
+
+/* ========================================================================= */
+/** @brief this function replace malloc, check if the memory is not zero, if 
+ * it is, it exit from the program, and display who called it and how much 
+ * memory it tryed to alloc.
+ * @param __A number of bytes to allocate.
+ * @return a void* pointer to the newly allocated memory, note that if the 
+ * function returns at all, it will return with the amount of memory required, 
+ * so no NULL checking is ever necesary after an EGmalloc call. 
+ * */
+#define EGmalloc(__A) ({\
+	size_t const _EGmp_sz_ = (size_t)(__A);\
+	void * _EGmp_res_ = 0;\
+	/*WARNINGL(0,!_EGmp_sz_,"Allocating 0 bytes");*/\
+	if(_EGmp_sz_)\
+	{\
+		_EGmp_res_ = calloc((size_t)1,_EGmp_sz_);\
+		EXIT(!_EGmp_res_,"Not enough memory while allocating %zd bytes",_EGmp_sz_);\
+	}\
+	_EGmp_res_;})
+
+/* ========================================================================= */
+/** @brief This function allocate 'count' elements of type 'type' and return 
+ * a pointer of type 'type*'. If the memory is not available the program will 
+ * exit indicating where it was trying to get memory and how much, it will also
+ * check some common errors like allocating zero bytes.
+ * @param __type type of the element required.
+ * @param __count number of contiguous elements of the given type required.
+ * @return pointer to the beggining of the allocated array of the apropiate
+ * type (so no casting is needed). Note that if this function returns at all,
+ * then the memory has been allocated and thus no NULL checking return is
+ * necesary. */
+#define EGsMalloc(__type,__count) (__type*)EGmalloc(sizeof(__type)*((size_t)(__count)))
+
+/* ========================================================================= */
+/** @brief Realloc a given pointer to the new size, and check that we find
+ * enough memory to return. If we don't, we exit the execution.
+ * @param __ptr pointer to reallocate.
+ * @param __sz new number of bytes to reallocate.
+ * @return pointer to the new block of memory */
+#define EGrealloc(__ptr,__sz) ({\
+	const size_t ____sz = (size_t)(__sz);\
+	(__ptr) = realloc((__ptr),____sz);\
+	EXIT(!(__ptr)&&(____sz),"not enough memory while reallocating %zd",____sz);\
+	(__ptr);})
+
+/* ========================================================================= */
+/** @brief this is used to enable malloc/free tracking and extra debugging */
+#ifndef __EG_MEM_FREE_CHECK__
+#define __EG_MEM_FREE_CHECK__  (1 && DEBUG)
+#endif
+
+/* ========================================================================= */
+/** @brief This function replace free, the idea of this is to HOPEFULLY later 
+ * develop a memory leack checker that tell us who and where asked for memory 
+ * and didn't free it, in hte meantime they do nothing.
+ * @param __A pointer to the piece of memory to be freed, if debuging is enabled,
+ * the function will test for freing NULL pointers, for suspicios address
+ * freing and so on. note that the given pointer will point to NULL after this
+ * call, thus reducing the posibility of freeing multiple times the same piece
+ * of memory, or of allocating it after freeing it. */
+#if __EG_MEM_FREE_CHECK__
+#define EGfree(__A) ({\
+		EXIT(((__A) && !(((size_t)(__A))>>19)),"Trying to free pointer "#__A\
+				" with value %zd\nThis is probably an error",(size_t)(__A));\
+		if(__A) free(__A);\
+		else WARNING(1,"Trying to free "#__A", a NULL pointer");\
+		(__A) = 0;})
+#else
+#define EGfree(__A) ({free(__A);(__A)=0;})
+#endif
+
+/* ========================================================================= */
+/* end of eg_mem.h */
+/** @} */
+#endif
diff --git a/qsopt_ex/eg_memslab.c b/qsopt_ex/eg_memslab.c
new file mode 100644
index 0000000..4a1857f
--- /dev/null
+++ b/qsopt_ex/eg_memslab.c
@@ -0,0 +1,327 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2008 Daniel Espinoza.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library 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 Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
+ * */
+/* ========================================================================= */
+/** @file
+ * @ingroup EGmemSlab */
+/** @addtogroup EGmemSlab */
+/** @{ */
+/* ========================================================================= */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <inttypes.h> /* For printf format support */
+
+#include "eg_memslab.h"
+
+#include "logging-private.h"
+
+/* ========================================================================= */
+int EGmemSlabPoolSetParam(EGmemSlabPool_t*const pool,
+													const int param,
+													const int val)
+{
+	int rval = 0;
+	switch(param)
+	{
+		case EG_MSLBP_FREEFREE:
+			__EGmspLock(pool);
+			if(val) pool->freefree = 1;
+			else pool->freefree = 0;
+			__EGmspUnlock(pool);
+			break;
+		default:
+			rval = 1;
+			MESSAGE(0,"Unknown parameter %d",param);
+			break;
+	}
+	EG_RETURN(rval);
+}
+/* ========================================================================= */
+void EGmemSlabDisplay(const EGmemSlab_t*const slab)
+{
+	const size_t n_elem = slab->control.pool ? slab->control.pool->n_elem : (size_t)0;
+	const size_t n_elem2 = (n_elem/8)*8;
+	register size_t i;
+	QSlog("Slab %p:", (const void*const)slab);
+	QSlog("\t->base     : %8p", (void*)(slab->control.base));
+	QSlog("\t->elem_sz  : %8zd", slab->control.elem_sz);
+	QSlog("\t->n_elem   : %8zd", slab->control.n_elem);
+	QSlog("\t->slab_cn  : [%8p,%8p]", 
+							(void*)(slab->control.slab_cn.prev), 
+							(void*)(slab->control.slab_cn.next));
+	QSlog("\t->pool     : %8p", (void*)(slab->control.pool));
+	QSlog("\t->next     : %8zd", slab->control.next);
+	QSlog("\t->next_list:");
+	for( i = 0 ; i < n_elem2 ; i+= 8)
+	{
+		QSlog("\t[%3zu]=%3u [%3zu]=%3u [%3zu]=%3u [%3zu]=%3u "
+								"[%3zu]=%3u [%3zu]=%3u [%3zu]=%3u [%3zu]=%3u",
+								i, ((unsigned)(slab->next_list[i])),
+								i+1, ((unsigned)(slab->next_list[i+1])),
+								i+2, ((unsigned)(slab->next_list[i+2])), 
+								i+3, ((unsigned)(slab->next_list[i+3])),
+								i+4, ((unsigned)(slab->next_list[i+4])),
+								i+5, ((unsigned)(slab->next_list[i+5])),
+								i+6, ((unsigned)(slab->next_list[i+6])),
+								i+7, ((unsigned)(slab->next_list[i+7])));
+	}
+	QSlog("\t");
+	for( ; i < n_elem ; i++)
+	{
+		QSlog("[%3zu]=%3u ",i, ((unsigned)(slab->next_list[i])));
+	}
+}
+/* ========================================================================= */
+void __EGmemSlabInit( EGmemSlab_t*const slab,
+										EGmemSlabPool_t*const Pool)
+{
+	const EGconstructor_f _EGconstr = Pool->constr;
+	const size_t elem_sz = Pool->elem_sz;
+	const size_t n_elem = Pool->n_elem;
+	register size_t i;
+	char*base = (char*)(EG_MEM_ALIGN(sizeof(EGmsbControl_t)+Pool->n_elem) +
+											(char*)(slab) + (Pool->c_color));
+	slab->control.base = base;
+	slab->control.elem_sz = elem_sz;
+	slab->control.n_elem = 0;
+	EGeListAddAfter(&(slab->control.slab_cn),&(Pool->empty));
+	slab->control.pool = Pool;
+	slab->control.next = 0;
+	/* now we initialize all elements and list of next elements */
+	for( i = 0 ; i < n_elem; i++)
+	{
+		slab->next_list[i] = (uint8_t)(i+1);
+		if(_EGconstr)
+		{
+			_EGconstr(base);
+			base += elem_sz;
+		}
+	}
+	slab->next_list[n_elem-1] = EG_SLAB_ENDMARK;
+	/* if we are profiling, update here */
+	#if EG_SLAB_PROFILE <= DEBUG
+	slab->control.pool->n_allocs++;
+	slab->control.pool->n_slabs++;
+	if(slab->control.pool->max_slabs < slab->control.pool->n_slabs)
+		slab->control.pool->max_slabs = slab->control.pool->n_slabs;
+	#endif
+	/* change current color in main pool */
+	Pool->c_color += (uint8_t)(EG_MEM_ALIGNMENT);
+	if(Pool->c_color > Pool->max_color) Pool->c_color = 0;
+	if(EG_SLAB_VERBOSE <= DEBUG)
+	{
+		QSlog("Initializing slab as:");
+		EGmemSlabDisplay(slab);
+	}
+}
+/* ========================================================================= */
+void EGmemSlabClear( EGmemSlab_t*slab)
+{
+	const EGdestructor_f _EGdest = slab->control.pool->dest;
+	const size_t elem_sz = slab->control.elem_sz;
+	const size_t n_elem = slab->control.pool->n_elem;
+	char*base = slab->control.base;
+	register size_t i = n_elem;
+	if(EG_SLAB_VERBOSE <= DEBUG)
+	{
+		QSlog("slab before clearing:");
+		EGmemSlabDisplay(slab);
+	}
+	WARNINGL( EG_SLAB_DEBUG, slab->control.n_elem, 
+						"Clearing slab at %p with %zd elements of size %zd",
+						(void*)slab, slab->control.n_elem, elem_sz);
+	/* clear each element */
+	if(_EGdest)
+	{
+		while(i--)
+		{
+			_EGdest(base);
+			base += elem_sz;
+		}
+	}
+	/* remove the slab from it's containing list */
+	EGeListDel(&(slab->control.slab_cn));
+	/* if we are profiling, update here */
+	#if EG_SLAB_PROFILE <= DEBUG
+	slab->control.pool->n_slabs--;
+	#endif
+	/* if we are debugging, poison all data */
+	if(EG_SLAB_DEBUG <= DEBUG)
+	{
+		slab->control.base = (char*)EG_SLAB_POISON;
+		slab->control.slab_cn = (EGeList_t){(void*)EG_SLAB_POISON,(void*)EG_SLAB_POISON};
+		slab->control.next = EG_SLAB_ENDMARK;
+		for( i = n_elem ; i-- ; ) slab->next_list[i] = EG_SLAB_ENDMARK;
+	}
+	/* and display if needed */
+	if(EG_SLAB_VERBOSE <= DEBUG)
+	{
+		QSlog("slab after clearing:");
+		EGmemSlabDisplay(slab);
+	}
+	if(EG_SLAB_DEBUG <= DEBUG)
+		slab->control.pool = (EGmemSlabPool_t*)EG_SLAB_POISON;
+}
+/* ========================================================================= */
+/** @brief Initialize the profiling data of a slab pool */
+#if EG_SLAB_PROFILE <= DEBUG
+#define EGmemSlabPoolInitProfile(_EGmPl, __sz, __file, __func, __line) ({\
+	_EGmPl->file = __file;\
+	_EGmPl->func = __func;\
+	_EGmPl->line = __line;\
+	_EGmPl->real_sz = __sz;\
+	_EGmPl->n_slabs = _EGmPl->n_tot = _EGmPl->max_tot = _EGmPl->max_slabs = \
+	_EGmPl->ncals = _EGmPl->n_allocs = 0;})
+#else
+#define EGmemSlabPoolInitProfile(_EGmPl, __sz, __file, __func, __line)
+#endif
+
+/* ========================================================================= */
+void __EGmemSlabPoolInit( EGmemSlabPool_t*const pool,
+													const size_t sz,
+													EGconstructor_f constr_fn,
+													EGdestructor_f dest_fn,
+													const char*const file,
+													const char*const func,
+													const int line)
+{
+	const size_t elem_sz = sz < EG_SLAB_LLIMIT ? EG_SLAB_LLIMIT: EG_MEM_ALIGN(sz);
+	const size_t n_elem = (EG_SLAB_SIZE - EG_MEM_ALIGN(sizeof(EGmsbControl_t)))/
+												(elem_sz +1);
+	/* check that the real element size is within bounds */
+	if(elem_sz > EG_SLAB_ULIMIT)
+	{
+		QSlog("ERROR: Trying to initializate slab pool with element size"
+								" %zd > %zd (hard upper limit)", elem_sz, EG_SLAB_ULIMIT);
+		exit(EXIT_FAILURE);
+	}
+	/* initialize the structure */
+	#if HAVE_EG_THREAD
+	pthread_mutex_init(&(pool->mt),0);
+	#endif
+	__EGmspLock(pool);
+	EGeListInit(&(pool->half));
+	EGeListInit(&(pool->empty));
+	EGeListInit(&(pool->full));
+	pool->constr = constr_fn;
+	pool->dest = dest_fn;
+	pool->elem_sz = (uint16_t)(elem_sz);
+	pool->n_elem = (uint8_t)(n_elem);
+	pool->c_color = 0;
+	pool->max_color = ((uint8_t)(EG_SLAB_SIZE - EG_MEM_ALIGN(sizeof(EGmsbControl_t)+ n_elem) - 
+											(elem_sz*n_elem)));
+	pool->freefree = 1;
+	EGmemSlabPoolInitProfile(pool,sz, file, func, line);
+	/* verbose output */
+	if(EG_SLAB_VERBOSE <= DEBUG )
+		EGmemSlabPoolDisplay(pool);
+	__EGmspUnlock(pool);
+}
+/* ========================================================================= */
+void EGmemSlabPoolClear(EGmemSlabPool_t*const Pool)
+{
+	void* _EGptr;
+	__EGmspLock(Pool);
+	while(!EGeListIsEmpty(&(Pool->half)))
+	{
+		_EGptr = EGmemSlabGetSlab(Pool->half.next);
+		EGmemSlabClear(_EGptr);
+		free(_EGptr);
+	}
+	while(!EGeListIsEmpty(&(Pool->empty)))
+	{
+		_EGptr = EGmemSlabGetSlab(Pool->empty.next);
+		EGmemSlabClear(_EGptr);
+		free(_EGptr);
+	}
+	while(!EGeListIsEmpty(&(Pool->full)))
+	{
+		_EGptr = EGmemSlabGetSlab(Pool->full.next);
+		EGmemSlabClear(_EGptr);
+		free((void*)EG_SLAB_PAGE(_EGptr));
+	}
+	/* verbose output */
+	if(EG_SLAB_VERBOSE <= DEBUG || EG_SLAB_PROFILE <= DEBUG)
+	{
+		QSlog("After clearing slab pool:");
+		EGmemSlabPoolDisplay(Pool);
+	}
+	__EGmspUnlock(Pool);
+}
+/* ========================================================================= */
+void EGmemSlabPoolShrink(EGmemSlabPool_t*const Pool)
+{
+	void* _EGptr;
+	__EGmspLock(Pool);
+	while(!EGeListIsEmpty(&(Pool->empty)))
+	{
+		_EGptr = EGmemSlabGetSlab(Pool->empty.next);
+		EGmemSlabClear(_EGptr);
+		free((void*)EG_SLAB_PAGE(_EGptr));
+	}
+	__EGmspUnlock(Pool);
+}
+/* ========================================================================= */
+void EGmemSlabPoolDisplay(const EGmemSlabPool_t*const pool)
+{
+	QSlog("Pool %p:", (const void*const)pool);
+	QSlog("\t->half      : [%8p,%8p]",
+							(void*)(pool->half.prev), 
+							(void*)(pool->half.next));
+	QSlog("\t->empty     : [%8p,%8p]",
+							(void*)(pool->empty.prev), 
+							(void*)(pool->empty.next));
+	QSlog("\t->full      : [%8p,%8p]",
+							(void*)(pool->full.prev), 
+							(void*)(pool->full.next));
+	QSlog("\t->constr    : %8p", (void*)(pool->constr));
+	QSlog("\t->dest      : %8p", (void*)(pool->dest));
+	QSlog("\t->elem_sz   : %8"PRIu16, pool->elem_sz);
+	QSlog("\t->n_elem    : %8"PRIu8, pool->n_elem);
+	QSlog("\t->c_color   : %8"PRIu8, pool->c_color);
+	QSlog("\t->max_color : %8"PRIu8, pool->max_color);
+	QSlog("\t->freefree  : %8"PRIu8, pool->freefree);
+	#if EG_SLAB_PROFILE <= DEBUG
+	if(pool->ncals)
+	{
+		QSlog("\t->file      : %s", pool->file);
+		QSlog("\t->func      : %s", pool->func);
+		QSlog("\t->line      : %8d", pool->line);
+		QSlog("\t->real_sz   : %8"PRIu64, pool->real_sz);
+		QSlog("\t->n_slabs   : %8"PRIu64, pool->n_slabs);
+		QSlog("\t->n_tot     : %8"PRIu64, pool->n_tot);
+		QSlog("\t->max_tot   : %8"PRIu64, pool->max_tot);
+		QSlog("\t->max_slabs : %8"PRIu64, pool->max_slabs);
+		QSlog("\t->ncals     : %8"PRIu64, pool->ncals);
+		QSlog("\t->n_allocs  : %8"PRIu64, pool->n_allocs);
+		QSlog("\tEficiency   :");
+		QSlog("\t\talloc ratio  : %8lg (%"PRIu64"/%"PRIu64")", 
+								((double)pool->ncals)/pool->n_allocs, pool->ncals, pool->n_allocs);
+		QSlog("\t\tmemory waste : %8.3lf %%",
+								100*(1-((double)pool->max_tot*pool->real_sz)/
+										 ((double)pool->max_slabs*EG_SLAB_SIZE)));
+	}
+	#endif
+}
+/* ========================================================================= */
diff --git a/qsopt_ex/eg_memslab.h b/qsopt_ex/eg_memslab.h
new file mode 100644
index 0000000..5c2d05b
--- /dev/null
+++ b/qsopt_ex/eg_memslab.h
@@ -0,0 +1,418 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005,2006,2007,2008,2009,2010,2011 Daniel Espinoza.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library 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 Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
+ * */
+/* ========================================================================= */
+/** @defgroup EGmemSlab EGmemSlab
+ *
+ * This is a basic interface for slab pool managment. The idea comes from Slabs
+ * as defined in both Linux and Solaris (see "The Slab Allocator: An
+ * Object-Caching Kernel Memory Allocator", by Jeff Bonwick, Sun Microsystems),
+ * the basic idea is
+ * to provide pool for a specific type of object, and to store them in an
+ * initialized state, so that initialization and destruction only is done while
+ * growing/freeing the memory slabs, thus this approach should provide greater
+ * advantages for complitated to initialize structures. and in theory
+ * (althought not yet implemented) this structure can be managed so as to
+ * provide a shrinkable memory managment on the fly.
+ *
+ * In this implementation we only allow small caches (i.e. objects must be
+ * smaller than EG_SLAB_ULIMIT and internally we don't allocate objects smaller
+ * than EG_SLAB_LLIMIT), 
+ * within a unique memory page. We could allow in the future for more flexible
+ * slabs. This implementation also uses colored slabs (see the paper for
+ * further details).
+ *
+ * Here we can see a schematic drawing of the slab allocator structure and
+ * functions:
+ *
+ * @version 0.9.0
+ * @par History:
+ * - 2011-03-01
+ * 						- Make EGms_t thread-safe, i.e. a single memory pool can serve
+ * 							several threads. This makes the default memory manager for GMP
+ * 							thread safe as well
+ * - 2010-12-27
+ * 						- Add short-hand names for functions
+ * - 2008-10-06
+ * 						- Second implementation
+ * - 2005-07-30
+ * 						- First Implpementation.
+ * */
+/** @file
+ * @ingroup EGmemSlab */
+/** @addtogroup EGmemSlab */
+/**  @{  */
+/** @example eg_memslab.ex.c */
+/* ========================================================================= */
+#ifndef __EG_MEM_SLAB_H__
+#define __EG_MEM_SLAB_H__
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include "eg_mem.h"
+#include "eg_elist.h"
+
+/* ========================================================================= */
+/** @name EGmemSlab Parameters
+ * @brief parameters for controling slab pool allocation */
+/* @{ */
+/** @brief control the handle of empty slabs, if set to non-zero, free unused
+ * slabs as they become unused, if set to zero, keep all unused slabs until
+ * #EGmemSlabPoolShrink is called */
+#define EG_MSLBP_FREEFREE 1
+/* @} */
+/* ========================================================================= */
+/* declare the slab pool structure */
+struct EGmemSlabPool_t;
+
+/* ========================================================================= */
+/** @brief maximum size of the objects that can be allocated via slab. */
+#define EG_SLAB_ULIMIT ((size_t)1023)
+#define EG_SLAB_LLIMIT ((size_t)16)
+
+/* ========================================================================= */
+/** @brief size of the memory slabs (in bytes ) */
+#define EG_SLAB_SIZE ((size_t)0x1000)
+
+/* ========================================================================= */
+/** @brief mask to detect the position of a piece of memory within a slab */
+#define EG_SLAB_MASK (~(EG_SLAB_SIZE-1))
+
+/* ========================================================================= */
+/** @brief address used to check consistency if enabled */
+#define EG_SLAB_POISON ((size_t)0xdeadbeef)
+
+/* ========================================================================= */
+/** @brief if set to one, enable profiling for the slab allocator */
+#define EG_SLAB_PROFILE 1000
+
+/* ========================================================================= */
+/** @brief local verbose level for the slab allocator, the lower the level, the
+ * more information will be printed on screen. */
+#define EG_SLAB_VERBOSE 1000
+
+/* ========================================================================= */
+/** @brief local debug level for the slab allocator, the lower the level, the
+ * more testing will be done. */
+#define EG_SLAB_DEBUG 1000
+
+/* ========================================================================= */
+/** @brief end of list marker, note that this can not be more than 255 */
+#define EG_SLAB_ENDMARK ((uint8_t)255U)
+
+#ifndef EG_SLAB_REDUCE_TO_MALLOC
+/* ========================================================================= */
+/** @brief if set to one, reduce the slab pool allocator to a simple malloc
+ * call */
+#define EG_SLAB_REDUCE_TO_MALLOC 0
+#endif
+
+
+/* ========================================================================= */
+/** @brief Given a pointer, return a pointer to the beginning of the containing
+ * page. */
+#define EG_SLAB_PAGE(__ptr) (((size_t)__ptr)&EG_SLAB_MASK)
+
+/* ========================================================================= */
+/** @brief structure that holds the information relevant to each slab
+ * */
+typedef struct
+{
+	char*base;								/**< @brief Where the data-payload start */
+	size_t elem_sz;						/**< @brief byte-size of each element */
+	size_t n_elem;						/**< @brief number of used elements */
+	EGeList_t slab_cn;				/**< @brief Connector into the list of slabs*/
+	struct EGmemSlabPool_t *pool;	/**< Pointer to the slab pool structure */
+	size_t next;							/**< @brief next free element */
+} EGmsbControl_t;
+typedef struct
+{
+	EGmsbControl_t control;	/**< @brief comon base structure for slabs */
+	uint8_t next_list[];		/**< @brief list of free elements, the next 
+																element is next_list[0], whenever we reach a
+																value of 255, it is the end of the free-list.
+																*/
+} EGmemSlab_t;
+
+/* ========================================================================= */
+/** @brief structure used to store a slab memory pool */
+typedef struct EGmemSlabPool_t
+{
+	EGeList_t half;					/**< Head of the list for half-full slabs */
+	EGeList_t empty;				/**< Head of the list for non used slabs */
+	EGeList_t full;					/**< Head of the list for fully used slabs*/
+	EGconstructor_f constr;	/**< Constructor for the local elements */
+	EGdestructor_f dest;		/**< Destructor for the local elements */
+	uint16_t elem_sz;				/**< Size of the elements in the slab, including 
+															 extra space for pointer to next. */
+	uint8_t n_elem;					/**< Total number of elements in each slab */
+	uint8_t c_color;				/**< Last used color while creating slabs. */
+	uint8_t max_color;			/**< Maximum valid value for colors in this pool */
+	uint8_t freefree:1;			/**< if non-zero, free non-used slabs */
+	uint8_t pad1:7;					/**< padding */
+	uint16_t pad2;					/**< padding */
+	char const *file;				/**< File where the structure was initialized */
+	char const *func;				/**< Function where the structure was initialized */
+	int line;								/**< Line where the structure was initialized */
+	uint64_t real_sz;				/**< Actual size of the elements asked by the user */
+	uint64_t n_slabs;				/**< Number of slabs */
+	uint64_t n_tot;					/**< Total number of elements in use by the user */
+	uint64_t max_tot;				/**< Maximum number of elements allocated */
+	uint64_t max_slabs;			/**< Maximum number of slabs used */
+	uint64_t ncals;					/**< number to alloc calls */
+	uint64_t n_allocs;			/**< number slab alloc calls */
+	#if HAVE_EG_THREAD
+	pthread_mutex_t mt;			/**< mutex for memory slab manager */
+	#endif
+}
+EGmemSlabPool_t;
+
+/* ========================================================================= */
+/** @brief slab lock/unlock macros */
+#if HAVE_EG_THREAD
+#define __EGmspLock(__slab) pthread_mutex_lock(&(__slab->mt))
+#define __EGmspUnlock(__slab) pthread_mutex_unlock(&(__slab->mt))
+#else
+#define __EGmspLock(__slab)
+#define __EGmspUnlock(__slab)
+#endif
+/* ========================================================================= */
+/** @brief display given slab structure 
+ * @param slab what to display
+ * */
+void EGmemSlabDisplay(const EGmemSlab_t*const slab);
+
+/* ========================================================================= */
+/** @brief display given pool structure
+ * @param pool what to display
+ * */
+void EGmemSlabPoolDisplay(const EGmemSlabPool_t*const pool);
+
+/* ========================================================================= */
+/** @brief given a piece of memory that should be within a slab, return the
+ * pointer to the related slab structure, remember that the slab structure is
+ * at the beggining of the page. */
+#define EGmemSlabGetSlab(__ptr) \
+		((EGmemSlab_t*)(EG_SLAB_PAGE(__ptr)))
+
+/* ========================================================================= */
+/** @brief initialize a slab structure. This include calling the constructor
+ * for all elements in the slab. Note that this function asumes that all memory
+ * has been previously set to NULL. It will also place this slab in the list 
+ * of empty slabs in the given pool.
+ * @param slab pointer within the memory range of the slab to be initialized.
+ * @param __Pool Slab __Pool where this slab will bellong from. The slab pool
+ * should be initialized (i.e. should have a constructor and destructor, and an
+ * element size set.
+ * */
+void __EGmemSlabInit( EGmemSlab_t*const slab,
+										EGmemSlabPool_t*const __Pool);
+/* ========================================================================= */
+/** @brief given an initialized slab, clear all internally allocated memory,
+ * and leave the slab ready to be freed by 'free', this include calling the
+ * destructor for all elements in the slab.
+ * @param slab pointer to an area of the slab memory to be clear.
+ * @note If debugging is enabled, then all fields will be poisoned so that
+ * subsequent use of this structure will fail (but for the free call). Also, if
+ * debugging is enabled, we will check that the slab has no element in use.
+ * */
+void EGmemSlabClear( EGmemSlab_t*const slab);
+
+/* ========================================================================= */
+/** @brief Given a non-full slab, extract a pointer to the next unused element
+ * in the slab, and update all internal data. and if it becomes full, then move
+ * it to the full list within the pool. Also, if debugging, poison the pointer
+ * to the enext element in the returned element. If the slab is not full, and
+ * the number of active elements is one, then move the slab to the half-full
+ * slab list in the pool.
+ * @param slab pointer within a slab memory.
+ * @return pointer to a void* of initialized memory by the given contructor in
+ * the slab pool.
+ * */
+#define EGmemSlabPopElement(slab) ({\
+	EGmemSlab_t*const _EGmSlb = EGmemSlabGetSlab(slab);\
+	EGmemSlabPool_t*const _EGPlRf = _EGmSlb->control.pool;\
+	const size_t _EGmSlb_esz = _EGmSlb->control.elem_sz;\
+	const size_t _EGmSlb_ne = _EGmSlb->control.next;\
+	const size_t _EGmSlb_nn = _EGmSlb->next_list[_EGmSlb_ne];\
+	void*const _EGelem = (void*)(_EGmSlb_ne*_EGmSlb_esz + _EGmSlb->control.base);\
+	/* now update the slab */\
+	_EGmSlb->control.n_elem++;\
+	_EGmSlb->control.next = _EGmSlb_nn;\
+	EXITL(EG_SLAB_DEBUG,_EGmSlb_ne == EG_SLAB_ENDMARK, "Allocating from full slab");\
+	/* if the slab is full, move it to full list */\
+	if(_EGmSlb_nn == EG_SLAB_ENDMARK){\
+		EGeListMoveAfter(&(_EGmSlb->control.slab_cn),&(_EGPlRf->full));}\
+	/* if the slab is first-time used, move to half list */\
+	else if(_EGmSlb->control.n_elem == 1U){\
+		EGeListMoveAfter(&(_EGmSlb->control.slab_cn),&(_EGPlRf->half));}\
+	/* return the element */\
+	_EGelem;})
+
+/* ========================================================================= */
+/** @brief Given an used object within a slab, give it back to the slab for
+ * future use.
+ * @param __ptr pointer to the element to be given back to its containing slab.
+ * */
+#define EGmemSlabPushElement(__ptr) do{\
+	char*const _EGmsbPtr = (char*)(__ptr);\
+	EGmemSlab_t*const _EGmSlb = EGmemSlabGetSlab(_EGmsbPtr);\
+	EGmemSlabPool_t*const _EGPlRf = _EGmSlb->control.pool;\
+	__EGmspLock(_EGPlRf);{\
+	const size_t _EGmSlb_esz = _EGmSlb->control.elem_sz;\
+	const size_t _EGmSlb_ne = _EGmSlb->control.next;\
+	const size_t _EGmSlb_nn = ((_EGmsbPtr) - _EGmSlb->control.base)/_EGmSlb_esz;\
+	/* if debugging, check for poison in the pointer to the next element in the \
+	 * given element */\
+	EXITL(EG_SLAB_DEBUG, !_EGmSlb->control.n_elem, "freeing from an empty slab");\
+	/* now actually put the element into the slab */\
+	_EGmSlb->control.n_elem--;\
+	_EGmSlb->control.next = _EGmSlb_nn;\
+	_EGmSlb->next_list[_EGmSlb_nn] = _EGmSlb_ne;\
+	__EGmsbUPD2(_EGPlRf);\
+	/* if the slab is now not being used, update accordingly */\
+	if(_EGmSlb_ne == EG_SLAB_ENDMARK){\
+		EGeListMoveAfter(&(_EGmSlb->control.slab_cn),&(_EGPlRf->half));}\
+	else if(!_EGmSlb->control.n_elem){\
+		if(_EGPlRf->freefree){\
+			EGmemSlabClear(_EGmSlb);\
+			free((void*)_EGmSlb);}\
+		else{\
+			EGeListMoveAfter(&(_EGmSlb->control.slab_cn),&(_EGPlRf->empty));}}}\
+	__EGmspUnlock(_EGPlRf);\
+	}while(0)
+
+/* ========================================================================= */
+/** @brief initialize a slab pool as an empty pool for elements of the given
+ * size, and with te given constructor and destructors. 
+ * @param constr_fn constructor fnctioin for the elements to be stored in the
+ * pool.
+ * @param dest_fn destructor function for the elements to be stored in the
+ * pool.
+ * @param pool pointer to the slab pool to initialize.
+ * @param sz (real) size (in bytes) of the elements to be hold. in the pool.
+ * This means that sz is the result of sizeof(TYPE), where TYPE is the
+ * structure to be pooled. */
+#define EGmemSlabPoolInit(pool, sz, constr_fn, dest_fn) \
+				__EGmemSlabPoolInit(pool, sz, constr_fn, dest_fn, \
+														__FILE__, __func__, __LINE__)
+void __EGmemSlabPoolInit( EGmemSlabPool_t*const pool,
+													const size_t sz,
+													EGconstructor_f constr_fn,
+													EGdestructor_f dest_fn,
+													const char*const file,
+													const char*const func,
+													const int line);
+/* ========================================================================= */
+/** @brief clear a slab pool and all internal sub-structures and data, no
+ * further calls to this structure are posible after this (but for freeing the
+ * memory containing this data, or to re-initialize it).
+ * @param __Pool slab pool to be cleared.
+ * */
+void EGmemSlabPoolClear(EGmemSlabPool_t*const __Pool);
+/* ========================================================================= */
+/** @brief add one to the given pointer, if profiling is enabled, otherwise, do
+ * nothing */
+#if EG_SLAB_PROFILE <= DEBUG
+#define __EGmsbUPD1(__pool) do{\
+	__pool->ncals++;\
+	__pool->n_tot++;\
+	if(__pool->max_tot < __pool->n_tot) __pool->max_tot = __pool->n_tot;}while(0)
+#define __EGmsbUPD2(__pool) __pool->n_tot--
+#else
+#define __EGmsbUPD1(__pool)
+#define __EGmsbUPD2(__pool)
+#endif
+
+/* ========================================================================= */
+/** @brief Given a slab pool, return an element from the pool. 
+ * @param __Pool slab pool from where we will get the memory. 
+ * @return pointer to an initialize element. */
+#if EG_SLAB_REDUCE_TO_MALLOC
+#define EGmemSlabPoolAlloc(__Pool) ({\
+	EGmemSlabPool_t*const _EGmPl = (__Pool);\
+	void*_EGmb = EGmalloc(_EGmPl->elem_sz+sizeof(void*));\
+	void**_EGpt = (void**)_EGmb;\
+	__EGmsbUPD1(_EGmPl);\
+	(*_EGpt) = _EGmPl;\
+	_EGmb=((void*)(_EGpt+1));\
+	if(_EGmPl->constr) _EGmPl->constr(_EGmb);\
+	_EGmb;})
+#else
+#define EGmemSlabPoolAlloc(__Pool) ({\
+	EGmemSlabPool_t*const _EGmPl = (__Pool);\
+	void* _EGSmbRf = 0;\
+	void* _EGrptr = 0;\
+	int __EGmPlerr=0;\
+	__EGmspLock(_EGmPl);\
+	__EGmsbUPD1(_EGmPl);\
+	if(!EGeListIsEmpty(&(_EGmPl->half))){ _EGSmbRf = _EGmPl->half.next;}\
+	else if(!EGeListIsEmpty(&(_EGmPl->empty))){ _EGSmbRf = _EGmPl->empty.next;}\
+	else{\
+		if((__EGmPlerr=posix_memalign(&_EGSmbRf,EG_SLAB_SIZE,EG_SLAB_SIZE))){\
+			EXIT(1,"posix_memalign falied with code %d, error %s",__EGmPlerr,\
+					strerror(__EGmPlerr));}\
+		__EGmemSlabInit(_EGSmbRf,_EGmPl);}\
+	_EGrptr = EGmemSlabPopElement(_EGSmbRf);\
+	MESSAGE(EG_SLAB_VERBOSE,"Returning %p",_EGrptr);\
+	__EGmspUnlock(_EGmPl);\
+	_EGrptr;})
+#endif
+
+/* ========================================================================= */
+/** @brief Given a pointer to an element allocated through a slab pool, give it
+ * back to the pool.
+ * @param __ptr pointer to be returned to the pool.
+ * */
+#if EG_SLAB_REDUCE_TO_MALLOC
+#define EGmemSlabPoolFree(__ptr) ({\
+	void**_EGptr = ((void**)(__ptr))-1;\
+	EGmemSlabPool_t*const _EGmPl = (EGmemSlabPool_t*)(*_EGptr);\
+	__EGmsbUPD2(_EGmPl);\
+	if(_EGmPl->dest) _EGmPl->dest(((void*)(_EGptr+1)));\
+	EGfree(_EGptr);})
+#else
+#define EGmemSlabPoolFree(__ptr) EGmemSlabPushElement(__ptr)
+#endif
+
+/* ========================================================================= */
+/** @brief Given a slab pool, free all unused slabs 
+ * @param pool slab pool to be shrinked. */
+void EGmemSlabPoolShrink(EGmemSlabPool_t*const pool);
+
+/* ========================================================================= */
+/** @brief set parameters for a slab pool */
+int EGmemSlabPoolSetParam(EGmemSlabPool_t*const pool,
+													const int param,
+													const int val);
+/* ========================================================================= */
+/** @brief short names for common functions */
+#define EGmsAlloc  EGmemSlabPoolAlloc
+#define EGmsFree   EGmemSlabPoolFree
+#define EGmsInit   EGmemSlabPoolInit
+#define EGmsClear  EGmemSlabPoolClear
+#define EGms_t     EGmemSlabPool_t
+#define EGmsShrink EGmemSlabPoolShrink
+/* ========================================================================= */
+/* end of eg_memslab.h */
+/**  @}  */
+#endif
diff --git a/qsopt_ex/eg_nummacros.h b/qsopt_ex/eg_nummacros.h
new file mode 100644
index 0000000..2c74d03
--- /dev/null
+++ b/qsopt_ex/eg_nummacros.h
@@ -0,0 +1,81 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library 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 Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
+ * */
+#ifndef __EG_NUMMACROS_H__
+#define __EG_NUMMACROS_H__
+
+#include "eg_macros.h"
+
+/* ========================================================================= */
+/** @defgroup EGlpNumMacros General Number Utilities
+ * Here we put some utilities common for number.
+ * 
+ * @par History:
+ * Revision 0.0.2
+ *  - 2007-10-08
+ *  					- Move EGabs, EGswap, EGmin and EGmax to this file
+ * */
+/** @{*/
+/** @file
+ * @brief This file provide the user interface and function definitions 
+ * for general number utilities.
+ * */
+
+/* ========================================================================= */
+/** @brief Given tree numbers N1, N2 and Ntmp, swap values of N1 and N2 using
+ * Ntmp as a temporal number. The variables should be of some primitive type of
+ * C for this macro to work.
+ * @param N1 first number.
+ * @param N2 second number.
+ * @param Ntmp temporal variable.
+ * */
+#define EGswap(N1,N2,Ntmp) do{\
+	Ntmp = N1;\
+	N1 = N2;\
+	N2 = Ntmp;} while(0)
+
+/* ========================================================================= */
+/** @brief given two variables (of the same type, and of some predefined type)
+ * return the maximum value among the two of them. */
+#define EGmax(a,b) ({\
+	const typeof(a) __EGma = (a);\
+	const typeof(b) __EGmb = (b);\
+	(__EGma > __EGmb ? __EGma : __EGmb);})
+
+/* ========================================================================= */
+/** @brief given two variables (of the same type, and of some predefined type)
+ * return the minimum value among the two of them. */
+#define EGmin(a,b) ({\
+	const typeof(a) __EGma = (a);\
+	const typeof(b) __EGmb = (b);\
+	(__EGma < __EGmb ? __EGma : __EGmb);})
+
+/* ========================================================================= */
+/** @brief a general macro to return the absolute value of the given variable
+ * @param var variable whose absolute value we want to compute.
+ * @return value of the absolute value of the given variable, note that this
+ * macro will only work in built-in types, and will use the default comparison
+ * for those internal types. */
+#define EGabs(var) ({\
+		const typeof(var) __EGav = (var);\
+		(__EGav < 0) ? -__EGav : __EGav;})
+
+/* ========================================================================= */
+/** @}*/
+#endif
diff --git a/qsopt_ex/eg_numutil.c b/qsopt_ex/eg_numutil.c
new file mode 100644
index 0000000..7a0ef95
--- /dev/null
+++ b/qsopt_ex/eg_numutil.c
@@ -0,0 +1,106 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library 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 Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
+ * */
+#include "eg_numutil_EGLPNUM_TYPENAME.h"
+/** @file
+ * @ingroup EGlpNumUtil */
+/** @addtogroup EGlpNumUtil */
+/** @{ */
+/* ========================================================================= */
+void EGLPNUM_TYPENAME_EGutilPermSort (const size_t sz,
+										 int *const perm,
+										 const EGLPNUM_TYPE * const elem)
+{
+	size_t i,
+	  j;
+	int temp;
+	EGLPNUM_TYPE t;
+	if (sz <= 1)
+		return;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (t);
+	EGswap (perm[0], perm[(sz - 1) / 2], temp);
+	i = 0;
+	j = sz;
+	EGLPNUM_TYPENAME_EGlpNumCopy (t, elem[perm[0]]);
+	for (;;)
+	{
+		do
+			i++;
+		while (i < sz && EGLPNUM_TYPENAME_EGlpNumIsLess (elem[perm[i]], t));
+		do
+			j--;
+		while (j && EGLPNUM_TYPENAME_EGlpNumIsLess (t, elem[perm[j]]));
+		if (j < i)
+			break;
+		EGswap (perm[i], perm[j], temp);
+	}
+	EGswap (perm[0], perm[j], temp);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (t);
+	EGLPNUM_TYPENAME_EGutilPermSort (j, perm, elem);
+	EGLPNUM_TYPENAME_EGutilPermSort (sz - i, perm + i, elem);
+}
+
+/* ========================================================================= */
+void EGLPNUM_TYPENAME_EGutilPermSort2 (const size_t sz,
+										 int *const perm,
+										 const EGLPNUM_TYPE * const elem)
+{
+	size_t i,
+	  j;
+	int temp;
+	EGLPNUM_TYPE t;
+	if (sz <= 1)
+		return;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (t);
+	EGswap (perm[0], perm[(sz - 1) / 2], temp);
+	i = 0;
+	j = sz;
+	EGLPNUM_TYPENAME_EGlpNumCopy (t, elem[perm[0]]);
+	for (;;)
+	{
+		do
+			i++;
+		while (i < sz && EGLPNUM_TYPENAME_EGlpNumIsLess (t, elem[perm[i]]));
+		do
+			j--;
+		while (EGLPNUM_TYPENAME_EGlpNumIsLess (elem[perm[j]], t));
+		if (j < i)
+			break;
+		EGswap (perm[i], perm[j], temp);
+	}
+	EGswap (perm[0], perm[j], temp);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (t);
+	EGLPNUM_TYPENAME_EGutilPermSort2 (j, perm, elem);
+	EGLPNUM_TYPENAME_EGutilPermSort2 (sz - i, perm + i, elem);
+}
+
+/* ========================================================================= */
+void EGLPNUM_TYPENAME___EGlpNumInnProd(EGLPNUM_TYPE*rop,
+											EGLPNUM_TYPE*const __EGa1,
+											EGLPNUM_TYPE*const __EGa2, 
+											const size_t length )
+{
+	size_t __EGdim = length;
+	EGLPNUM_TYPENAME_EGlpNumZero((*rop));
+	while(__EGdim--) EGLPNUM_TYPENAME_EGlpNumAddInnProdTo((*rop),__EGa1[__EGdim],__EGa2[__EGdim]);
+}
+/* ========================================================================= */
+/** @} */
diff --git a/qsopt_ex/eg_numutil.h b/qsopt_ex/eg_numutil.h
new file mode 100644
index 0000000..f35b663
--- /dev/null
+++ b/qsopt_ex/eg_numutil.h
@@ -0,0 +1,97 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library 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 Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
+ * */
+#ifndef EGLPNUM_TYPENAME___EG_NUMUTIL_H__
+#define EGLPNUM_TYPENAME___EG_NUMUTIL_H__
+
+#include "eg_macros.h"
+#include "eg_nummacros.h"
+#include "eg_lpnum.h"
+
+/* ========================================================================= */
+/** @defgroup EGlpNumUtil General Number Utilities
+ * Here we put some utilities common for different number types but thaat we
+ * want to implement as templates, like permutation sorting, inner product of
+ * vectors, and so-on..
+ * 
+ * @par History:
+ * Revision 0.0.2
+ *  - 2007-10-08
+ *  					- Separate template file and independet file into eg_nummacros.h
+ *  					- Move EGabs, EGswap, EGmin and EGmax to this file
+ *  - 2005-10-31
+ *  					- First implementation.
+ * */
+/** @{*/
+/** @file
+ * @brief This file provide the user interface and function definitions for
+ * general number utilities.
+ * */
+
+/* Swap two EGLPNUM_TYPE variables using the third as a temporary. */
+#define EGLPNUM_TYPENAME_EGLPNUM_SWAP(a,b,t) ((EGLPNUM_TYPENAME_EGlpNumCopy(t,a)),(EGLPNUM_TYPENAME_EGlpNumCopy(a,b)),(EGLPNUM_TYPENAME_EGlpNumCopy(b,t)))
+
+/* ========================================================================= */
+/** @brief compute the inner product of two arrays.
+ * @param arr1 first array.
+ * @param arr2 second array.
+ * @param length number of entries to consider in both arrays, from zero to
+ * length - 1.
+ * @param rop where to store the result.
+ * */
+#define EGLPNUM_TYPENAME_EGlpNumInnProd(__rop,__arr1,__arr2,__length) EGLPNUM_TYPENAME___EGlpNumInnProd((&(__rop)),__arr1,__arr2,__length)
+/* ========================================================================= */
+/** @brief internal version, this is done to avoid using stdc99 and rely on
+ * more basic stdc89 */
+void EGLPNUM_TYPENAME___EGlpNumInnProd(EGLPNUM_TYPE*rop,EGLPNUM_TYPE*const arr1,EGLPNUM_TYPE*const arr2, const size_t length);
+/* ========================================================================= */
+/** @brief Sort (in increasing order) a sub-set of entries in an array using 
+ * quicksort, by permutating the order of the elements in the subset rather 
+ * than in the whole original array.
+ * @param sz length of the permutation array.
+ * @param perm array of indices of elements that we want to sort.
+ * @param elem array (of length at least max(perm[k]:k=0,...,sz-1)) containing
+ * the elements to be sorted.
+ * @note The array of elements is not changed by this function.
+ * @note This code is based in concorde's implementation of
+ * permutation-quick-sort.
+ * */
+void EGLPNUM_TYPENAME_EGutilPermSort (const size_t sz,
+										 int *const perm,
+										 const EGLPNUM_TYPE * const elem);
+
+/* ========================================================================= */
+/** @brief Sort (in decreasing order) a sub-set of entries in an array using 
+ * quicksort, by permutating the order of the elements in the subset rather 
+ * than in the whole original array.
+ * @param sz length of the permutation array.
+ * @param perm array of indices of elements that we want to sort.
+ * @param elem array (of length at least max(perm[k]:k=0,...,sz-1)) containing
+ * the elements to be sorted.
+ * @note The array of elements is not changed by this function.
+ * @note This code is based in concorde's implementation of
+ * permutation-quick-sort.
+ * */
+void EGLPNUM_TYPENAME_EGutilPermSort2 (const size_t sz,
+										 int*const perm,
+										 const EGLPNUM_TYPE*const elem);
+
+/* ========================================================================= */
+/** @}*/
+#endif
diff --git a/qsopt_ex/eg_timer.h b/qsopt_ex/eg_timer.h
new file mode 100644
index 0000000..1e1b56f
--- /dev/null
+++ b/qsopt_ex/eg_timer.h
@@ -0,0 +1,143 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library 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 Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
+ * */
+/* ========================================================================= */
+/** @defgroup EGtimer EGtimer 
+ *
+ * Here we implement types and functions for __timer functions
+ *
+ * @version 1.0.1 
+ * @par History:
+ * - 2013-04-18
+ * 						- Add EGtimerZero static initializer
+ * - 2006-01-25
+ * 						- Fix compilation errors on sun, change includes accordingly and
+ * 						code
+ * - 2005-05-31
+ * 						- Eliminate the definition of #EGwallClockTimer_t and replace it by
+ * 						a macro definition that replace it by #EGtimer_t.
+ * - 2004-01-20
+ * 						- Add a 'wall clock' __timer (Renan-Marcos) type and functions
+ * - 2003-05-08
+ * 						- First Implementation
+ * @note Up to now, this code will only work on linux machines, and maybe on
+ * unix/posix systems.
+ * */
+/** @file 
+ * @ingroup EGtimer */
+/** @addtogroup EGtimer */
+/** @{ */
+/* ========================================================================= */
+
+#ifndef __EG_TIMER_H__
+#define __EG_TIMER_H__
+
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include "eg_macros.h"
+
+/* ========================================================================= */
+/** @brief Get system time.
+ *
+ * This function is for internal purposes only and should not be called from the
+ * user space, it ask the (user) time from the system. 
+ * @return the time (in seconds) stored as a double. */
+#ifdef HAVE_GETRUSAGE
+#define __EGzeit() ({\
+	struct rusage __EGzeit_ru;\
+	int __EGzeit_st = getrusage(RUSAGE_SELF,&__EGzeit_ru);\
+	EXIT(__EGzeit_st,"getrusage failed with code error %d (%s)", errno, \
+	strerror(errno));\
+	(((double)__EGzeit_ru.ru_utime.tv_sec) + \
+	((double)__EGzeit_ru.ru_utime.tv_usec)/1000000);})
+#else
+#ifdef HAVE_TIMES
+#ifdef CLK_TCK
+#define MACHINE_FREQ CLK_TCK
+#else
+#define MACHINE_FREQ HZ
+#endif
+#define __EGzeit() ({\
+	struct tms __EGzeit_now;\
+	times(&__EGzeit_now);\
+	((double) __EGzeit_now.tms_utime)/((double) MACHINE_FREQ);})
+#else
+#error Your system does not have (or the configure script could not find)\
+ getrusage nor times functions, and thus we are unable to provide \
+ timing functions. Without them this library will not compile in this system
+#endif
+#endif
+
+/* ========================================================================= */
+/** @brief this structure holds a __timer structure */
+typedef struct
+{
+	double time;	/**< hold the accumulated time */
+	double stime;	/**< hols the last time when we start counting, this is only 
+										 for internal purposes, the user should only use the 
+										 field 'time' */
+}
+EGtimer_t;
+/* ========================================================================= */
+/** @brief static initializer */
+#define EGtimerZero {.time=0,.stime=0}
+/* ========================================================================= */
+/** @brief This is done for backward compability, we used to define
+ * EGwallClockTimer_t just as the normal __timer, so in reality we don't need
+ * another type, but keep the name so that older code depending on this still
+ * compiles. */
+#define EGwallClockTimer_t EGtimer_t
+
+/* ========================================================================= */
+/** @brief Set a new starting time for the __timer.
+ * @param __timer pointer to a EGtimer_t structure.
+ * @return starting time (in seconds), and the type is a double. */
+#define EGtimerStart(__timer) ({(__timer)->stime = __EGzeit();})
+
+/* ========================================================================= */
+/** @brief Stop a 'running' __timer and accumulate the run time.
+ * @return the time elapsed since the last 'start' call (in seconds). */
+#define EGtimerStop(__timer) ({(__timer)->time += __EGzeit() - (__timer)->stime;})
+
+/* ========================================================================= */
+/** @brief this function reset the accumulated time to zero */
+#define EGtimerReset(__timer) ({(__timer)->time = 0;})
+
+/* ========================================================================= */
+/** @brief Set the starting time the current (wall) time.
+ * @return the current wall time. */
+#define EGwallClockTimerStart(__timer) ({(__timer)->stime = time(0);})
+
+/* ========================================================================= */
+/** @brief Stop a 'running' __timer and accumulate the (wall) runing time.
+ * @return the wall time elapsed since the last initialization. */
+#define EGwallClockTimerStop(__timer) ({\
+	(__timer)->time += difftime(time(0),(__timer)->stime);})
+
+/* ========================================================================= */
+/** @brief Reset the accumulated time to zero */
+#define EGwallClockTimerReset(__timer) EGtimerReset(__timer)
+
+/* ========================================================================= */
+/** @}
+ * end of eg_timer.h */
+#endif
diff --git a/qsopt_ex/exact.c b/qsopt_ex/exact.c
new file mode 100644
index 0000000..4fbdd0a
--- /dev/null
+++ b/qsopt_ex/exact.c
@@ -0,0 +1,1824 @@
+/* ========================================================================= */
+/* ESolver "Exact Mixed Integer Linear Solver" provides some basic structures
+ * and algorithms commons in solving MIP's
+ *
+ * Copyright (C) 2005 Daniel Espinoza.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library 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 Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * */
+/* ========================================================================= */
+/** @file
+ * @ingroup Esolver */
+/** @addtogroup Esolver */
+/** @{ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "exact.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "logging-private.h"
+
+#include "util.h"
+#include "eg_timer.h"
+#include "eg_exutil.h"
+#include "except.h"
+
+#include "basis_mpq.h"
+#include "editor_dbl.h"
+#include "editor_mpf.h"
+#include "fct_mpq.h"
+#include "lpdata_mpq.h"
+#include "simplex_mpq.h"
+
+/* ========================================================================= */
+int QSexact_print_sol (mpq_QSdata * p,
+											 EGioFile_t * out_f)
+{
+	int rval = 0,
+	  status;
+	const int ncols = mpq_QSget_colcount (p);
+	const int nrows = mpq_QSget_rowcount (p);
+	mpq_t *x = mpq_EGlpNumAllocArray (ncols);
+	mpq_t *rc = mpq_EGlpNumAllocArray (ncols);
+	mpq_t *slack = mpq_EGlpNumAllocArray (nrows);
+	mpq_t *pi = mpq_EGlpNumAllocArray (nrows);
+	mpq_t value;
+	register int i;
+	char *str1 = 0;
+	mpq_init (value);
+	EGcallD(mpq_QSget_status (p, &status));
+	if(mpq_QSget_x_array (p, x)) mpq_EGlpNumFreeArray (x);
+	if(mpq_QSget_slack_array (p, slack)) mpq_EGlpNumFreeArray (slack);
+	if(mpq_QSget_pi_array (p, pi)) mpq_EGlpNumFreeArray (pi);
+	if(mpq_QSget_rc_array (p, rc)) mpq_EGlpNumFreeArray (rc);
+
+	switch (status)
+	{
+	case QS_LP_OPTIMAL:
+		EGcallD(mpq_QSget_objval (p, &value));
+		str1 = mpq_EGlpNumGetStr (value);
+		EGioPrintf (out_f, "status OPTIMAL\n\tValue = %s\n", str1);
+		free (str1);
+		str1 = 0;
+		break;
+	case QS_LP_INFEASIBLE:
+		EGioPrintf (out_f, "status INFEASIBLE\n");
+		break;
+	case QS_LP_UNBOUNDED:
+		EGioPrintf (out_f, "status UNBOUNDED\n");
+		break;
+	case QS_LP_ITER_LIMIT:
+	case QS_LP_TIME_LIMIT:
+	case QS_LP_UNSOLVED:
+	case QS_LP_ABORTED:
+	case QS_LP_MODIFIED:
+		EGioPrintf (out_f, "status NOT_SOLVED\n");
+		break;
+	}
+	if (x)
+	{
+		EGioPrintf (out_f, "VARS:\n");
+		for (i = 0; i < ncols; i++)
+			if (!mpq_equal (x[i], __zeroLpNum_mpq__))
+			{
+				str1 = mpq_EGlpNumGetStr (x[i]);
+				EGioPrintf (out_f, "%s = %s\n", p->qslp->colnames[i], str1);
+				free (str1);
+			}
+	}
+	if (rc)
+	{
+		EGioPrintf (out_f, "REDUCED COST:\n");
+		for (i = 0; i < ncols; i++)
+			if (!mpq_equal (rc[i], __zeroLpNum_mpq__))
+			{
+				str1 = mpq_EGlpNumGetStr (rc[i]);
+				EGioPrintf (out_f, "%s = %s\n", p->qslp->colnames[i], str1);
+				free (str1);
+			}
+	}
+	if (pi)
+	{
+		EGioPrintf (out_f, "PI:\n");
+		for (i = 0; i < nrows; i++)
+			if (!mpq_equal (pi[i], __zeroLpNum_mpq__))
+			{
+				str1 = mpq_EGlpNumGetStr (pi[i]);
+				EGioPrintf (out_f, "%s = %s\n", p->qslp->rownames[i], str1);
+				free (str1);
+			}
+	}
+	if (slack)
+	{
+		EGioPrintf (out_f, "SLACK:\n");
+		for (i = 0; i < nrows; i++)
+			if (!mpq_equal (slack[i], __zeroLpNum_mpq__))
+			{
+				str1 = mpq_EGlpNumGetStr (slack[i]);
+				EGioPrintf (out_f, "%s = %s\n", p->qslp->rownames[i], str1);
+				free (str1);
+			}
+	}
+
+	/* ending */
+CLEANUP:
+	if (x)
+		mpq_EGlpNumFreeArray (x);
+	if (pi)
+		mpq_EGlpNumFreeArray (pi);
+	if (rc)
+		mpq_EGlpNumFreeArray (rc);
+	if (slack)
+		mpq_EGlpNumFreeArray (slack);
+	mpq_clear (value);
+	return rval;
+}
+
+/* ========================================================================= */
+dbl_QSdata *QScopy_prob_mpq_dbl (mpq_QSdata * p,
+																 const char *newname)
+{
+	const int ncol = mpq_QSget_colcount(p);
+	const int nrow = mpq_QSget_rowcount(p);
+	char*sense=0;
+	int*rowcnt=0;
+	int*rowbeg=0;
+	int*rowind=0;
+	int objsense;
+	mpq_t*mpq_lb=0;
+	mpq_t*mpq_ub=0;
+	mpq_t*mpq_obj=0;
+	mpq_t*mpq_range=0;
+	mpq_t*mpq_rhs=0;
+	mpq_t*mpq_rowval=0;
+	double*dbl_lb=0;
+	double*dbl_ub=0;
+	double*dbl_obj=0;
+	double*dbl_range=0;
+	double*dbl_rhs=0;
+	double*dbl_rowval=0;
+	dbl_QSdata *p2 = 0;
+	int rval = 0;
+	register int i;
+	mpq_t mpq_val;
+	double dbl_val;
+	mpq_init(mpq_val);
+	/* get all information */
+	EGcallD(mpq_QSget_objsense(p,&objsense));
+	mpq_lb = mpq_EGlpNumAllocArray(ncol);
+	mpq_ub = mpq_EGlpNumAllocArray(ncol);
+	EGcallD(mpq_QSget_bounds(p,mpq_lb,mpq_ub));
+	dbl_lb = QScopy_array_mpq_dbl(mpq_lb);
+	dbl_ub = QScopy_array_mpq_dbl(mpq_ub);
+	mpq_EGlpNumFreeArray(mpq_ub);
+	mpq_obj = mpq_lb;
+	mpq_lb = 0;
+	EGcallD(mpq_QSget_obj(p, mpq_obj));
+	dbl_obj = QScopy_array_mpq_dbl(mpq_obj);
+	mpq_EGlpNumFreeArray(mpq_obj);
+	EGcallD(mpq_QSget_ranged_rows(p, &rowcnt, &rowbeg, &rowind, &mpq_rowval,
+																&mpq_rhs, &sense, &mpq_range, 0));
+	dbl_rowval = QScopy_array_mpq_dbl(mpq_rowval);
+	mpq_EGlpNumFreeArray(mpq_rowval);
+	dbl_range = QScopy_array_mpq_dbl(mpq_range);
+	mpq_EGlpNumFreeArray(mpq_range);
+	dbl_rhs = QScopy_array_mpq_dbl(mpq_rhs);
+	mpq_EGlpNumFreeArray(mpq_rhs);
+	/* create copy */
+	p2 = dbl_QScreate_prob (newname, objsense);
+	if (!p2) goto CLEANUP;
+	for( i = 0 ; i < ncol; i++)
+	{
+		EGcallD(dbl_QSnew_col(p2, dbl_obj[i], dbl_lb[i], dbl_ub[i], 0));
+	}
+	dbl_EGlpNumFreeArray(dbl_lb);
+	dbl_EGlpNumFreeArray(dbl_ub);
+	dbl_EGlpNumFreeArray(dbl_obj);
+	EGcallD(dbl_QSadd_ranged_rows(p2, nrow, rowcnt, rowbeg, rowind, 
+																dbl_rowval, dbl_rhs, sense, dbl_range, 0));
+	/* set parameters */
+	EGcallD(mpq_QSget_param(p, QS_PARAM_PRIMAL_PRICING, &objsense));
+	EGcallD(dbl_QSset_param(p2, QS_PARAM_PRIMAL_PRICING, objsense));
+	EGcallD(mpq_QSget_param(p, QS_PARAM_DUAL_PRICING, &objsense));
+	EGcallD(dbl_QSset_param(p2, QS_PARAM_DUAL_PRICING, objsense));
+	EGcallD(mpq_QSget_param(p, QS_PARAM_SIMPLEX_DISPLAY, &objsense));
+	EGcallD(dbl_QSset_param(p2, QS_PARAM_SIMPLEX_DISPLAY, objsense));
+	EGcallD(mpq_QSget_param(p, QS_PARAM_SIMPLEX_MAX_ITERATIONS, &objsense));
+	EGcallD(dbl_QSset_param(p2, QS_PARAM_SIMPLEX_MAX_ITERATIONS, objsense));
+	EGcallD(mpq_QSget_param(p, QS_PARAM_SIMPLEX_SCALING, &objsense));
+	EGcallD(dbl_QSset_param(p2, QS_PARAM_SIMPLEX_SCALING, objsense));
+	EGcallD(mpq_QSget_param_EGlpNum(p, QS_PARAM_SIMPLEX_MAX_TIME, &mpq_val));
+	dbl_val = mpq_get_d(mpq_val);
+	EGcallD(dbl_QSset_param_EGlpNum(p2, QS_PARAM_SIMPLEX_MAX_TIME, dbl_val));
+	EGcallD(mpq_QSget_param_EGlpNum(p, QS_PARAM_OBJULIM, &mpq_val));
+	dbl_val = mpq_get_d(mpq_val);
+	EGcallD(dbl_QSset_param_EGlpNum(p2, QS_PARAM_OBJULIM, dbl_val));
+	EGcallD(mpq_QSget_param_EGlpNum(p, QS_PARAM_OBJLLIM, &mpq_val));
+	dbl_val = mpq_get_d(mpq_val);
+	EGcallD(dbl_QSset_param_EGlpNum(p2, QS_PARAM_OBJLLIM, dbl_val));
+	/* ending */
+	CLEANUP:
+	mpq_clear(mpq_val);
+	dbl_EGlpNumFreeArray(dbl_rowval);
+	dbl_EGlpNumFreeArray(dbl_range);
+	dbl_EGlpNumFreeArray(dbl_rhs);
+	dbl_EGlpNumFreeArray(dbl_lb);
+	dbl_EGlpNumFreeArray(dbl_ub);
+	dbl_EGlpNumFreeArray(dbl_obj);
+	mpq_EGlpNumFreeArray(mpq_rowval);
+	mpq_EGlpNumFreeArray(mpq_range);
+	mpq_EGlpNumFreeArray(mpq_rhs);
+	mpq_EGlpNumFreeArray(mpq_lb);
+	mpq_EGlpNumFreeArray(mpq_ub);
+	mpq_EGlpNumFreeArray(mpq_obj);
+	EGfree(rowcnt);
+	EGfree(rowbeg);
+	EGfree(rowind);
+	EGfree(sense);
+	if (rval)
+	{
+		dbl_QSfree_prob (p2);
+		p2 = 0;
+	}
+#if QSEXACT_SAVE_INT
+	else
+	{
+		dbl_QSwrite_prob (p2, "prob.dbl.lp", "LP");
+	}
+#endif
+	return p2;
+}
+
+/* ========================================================================= */
+mpf_QSdata *QScopy_prob_mpq_mpf (mpq_QSdata * p,
+																 const char *newname)
+{
+	const int ncol = mpq_QSget_colcount(p);
+	const int nrow = mpq_QSget_rowcount(p);
+	char*sense=0;
+	int*rowcnt=0;
+	int*rowbeg=0;
+	int*rowind=0;
+	int objsense;
+	mpq_t*mpq_lb=0;
+	mpq_t*mpq_ub=0;
+	mpq_t*mpq_obj=0;
+	mpq_t*mpq_range=0;
+	mpq_t*mpq_rhs=0;
+	mpq_t*mpq_rowval=0;
+	mpf_t*mpf_lb=0;
+	mpf_t*mpf_ub=0;
+	mpf_t*mpf_obj=0;
+	mpf_t*mpf_range=0;
+	mpf_t*mpf_rhs=0;
+	mpf_t*mpf_rowval=0;
+	mpf_QSdata *p2 = 0;
+	int rval = 0;
+	mpq_t mpq_val;
+	mpf_t mpf_val;
+	register int i;
+	mpq_init(mpq_val);
+	mpf_init(mpf_val);
+	/* get all information */
+	EGcallD(mpq_QSget_objsense(p,&objsense));
+	mpq_lb = mpq_EGlpNumAllocArray(ncol);
+	mpq_ub = mpq_EGlpNumAllocArray(ncol);
+	EGcallD(mpq_QSget_bounds(p,mpq_lb,mpq_ub));
+	mpf_lb = QScopy_array_mpq_mpf(mpq_lb);
+	mpf_ub = QScopy_array_mpq_mpf(mpq_ub);
+	mpq_EGlpNumFreeArray(mpq_ub);
+	mpq_obj = mpq_lb;
+	mpq_lb = 0;
+	EGcallD(mpq_QSget_obj(p, mpq_obj));
+	mpf_obj = QScopy_array_mpq_mpf(mpq_obj);
+	mpq_EGlpNumFreeArray(mpq_obj);
+	EGcallD(mpq_QSget_ranged_rows(p, &rowcnt, &rowbeg, &rowind, &mpq_rowval, &mpq_rhs, &sense, &mpq_range, 0));
+	mpf_rowval = QScopy_array_mpq_mpf(mpq_rowval);
+	mpq_EGlpNumFreeArray(mpq_rowval);
+	mpf_range = QScopy_array_mpq_mpf(mpq_range);
+	mpq_EGlpNumFreeArray(mpq_range);
+	mpf_rhs = QScopy_array_mpq_mpf(mpq_rhs);
+	mpq_EGlpNumFreeArray(mpq_rhs);
+	/* create copy */
+	p2 = mpf_QScreate_prob (newname, objsense);
+	if (!p2) goto CLEANUP;
+	for( i = 0 ; i < ncol; i++)
+	{
+		EGcallD(mpf_QSnew_col(p2, mpf_obj[i], mpf_lb[i], mpf_ub[i], 0));
+	}
+	mpf_EGlpNumFreeArray(mpf_lb);
+	mpf_EGlpNumFreeArray(mpf_ub);
+	mpf_EGlpNumFreeArray(mpf_obj);
+	EGcallD(mpf_QSadd_ranged_rows(p2, nrow, rowcnt, rowbeg, rowind, (const mpf_t*)mpf_rowval,(const mpf_t*) mpf_rhs, sense,(const mpf_t*) mpf_range, 0));
+	/* set parameters */
+	EGcallD(mpq_QSget_param(p, QS_PARAM_PRIMAL_PRICING, &objsense));
+	EGcallD(mpf_QSset_param(p2, QS_PARAM_PRIMAL_PRICING, objsense));
+	EGcallD(mpq_QSget_param(p, QS_PARAM_DUAL_PRICING, &objsense));
+	EGcallD(mpf_QSset_param(p2, QS_PARAM_DUAL_PRICING, objsense));
+	EGcallD(mpq_QSget_param(p, QS_PARAM_SIMPLEX_DISPLAY, &objsense));
+	EGcallD(mpf_QSset_param(p2, QS_PARAM_SIMPLEX_DISPLAY, objsense));
+	EGcallD(mpq_QSget_param(p, QS_PARAM_SIMPLEX_MAX_ITERATIONS, &objsense));
+	EGcallD(mpf_QSset_param(p2, QS_PARAM_SIMPLEX_MAX_ITERATIONS, objsense));
+	EGcallD(mpq_QSget_param(p, QS_PARAM_SIMPLEX_SCALING, &objsense));
+	EGcallD(mpf_QSset_param(p2, QS_PARAM_SIMPLEX_SCALING, objsense));
+	EGcallD(mpq_QSget_param_EGlpNum(p, QS_PARAM_SIMPLEX_MAX_TIME, &mpq_val));
+	mpf_set_q(mpf_val,mpq_val);
+	EGcallD(mpf_QSset_param_EGlpNum(p2, QS_PARAM_SIMPLEX_MAX_TIME, mpf_val));
+	EGcallD(mpq_QSget_param_EGlpNum(p, QS_PARAM_OBJULIM, &mpq_val));
+	mpf_set_q(mpf_val,mpq_val);
+	EGcallD(mpf_QSset_param_EGlpNum(p2, QS_PARAM_OBJULIM, mpf_val));
+	EGcallD(mpq_QSget_param_EGlpNum(p, QS_PARAM_OBJLLIM, &mpq_val));
+	mpf_set_q(mpf_val,mpq_val);
+	EGcallD(mpf_QSset_param_EGlpNum(p2, QS_PARAM_OBJLLIM, mpf_val));
+	/* ending */
+	CLEANUP:
+	mpq_clear(mpq_val);
+	mpf_clear(mpf_val);
+	mpf_EGlpNumFreeArray(mpf_rowval);
+	mpf_EGlpNumFreeArray(mpf_range);
+	mpf_EGlpNumFreeArray(mpf_rhs);
+	mpf_EGlpNumFreeArray(mpf_lb);
+	mpf_EGlpNumFreeArray(mpf_ub);
+	mpf_EGlpNumFreeArray(mpf_obj);
+	mpq_EGlpNumFreeArray(mpq_rowval);
+	mpq_EGlpNumFreeArray(mpq_range);
+	mpq_EGlpNumFreeArray(mpq_rhs);
+	mpq_EGlpNumFreeArray(mpq_lb);
+	mpq_EGlpNumFreeArray(mpq_ub);
+	mpq_EGlpNumFreeArray(mpq_obj);
+	EGfree(rowcnt);
+	EGfree(rowbeg);
+	EGfree(rowind);
+	EGfree(sense);
+	if (rval)
+	{
+		mpf_QSfree_prob (p2);
+		p2 = 0;
+	}
+#if QSEXACT_SAVE_INT
+	else
+	{
+		mpf_QSwrite_prob (p2, "prob.mpf.lp", "LP");
+	}
+#endif
+	return p2;
+}
+
+#if QSEXACT_SAVE_OPTIMAL
+/* ========================================================================= */
+/** @brief used to enumerate the generated optimal tests */
+static int QSEXACT_SAVE_OPTIMAL_IND = 0;
+#endif
+
+/* ========================================================================= */
+int QSexact_optimal_test (mpq_QSdata * p,
+													mpq_t * p_sol,
+													mpq_t * d_sol,
+													QSbasis * basis)
+{
+	/* local variables */
+	register int i,
+	  j;
+	mpq_ILLlpdata *qslp = p->lp->O;
+	int *iarr1 = 0,
+	 *rowmap = qslp->rowmap,
+	 *structmap = qslp->structmap,
+	  col;
+	mpq_t *arr1 = 0,
+	 *arr2 = 0,
+	 *arr3 = 0,
+	 *arr4 = 0,
+	 *rhs_copy = 0;
+	mpq_t *dz = 0;
+	int objsense = (qslp->objsense == QS_MIN) ? 1 : -1;
+	int const msg_lvl = __QS_SB_VERB <= DEBUG ? 0 : 100000 * (1 - p->simplex_display);
+	int rval = 1;									/* store whether or not the solution is optimal, we start 
+																 * assuming it is. */
+	mpq_t num1,
+	  num2,
+	  num3,
+	  p_obj,
+	  d_obj;
+	mpq_init (num1);
+	mpq_init (num2);
+	mpq_init (num3);
+	mpq_init (p_obj);
+	mpq_init (d_obj);
+	mpq_set_ui (p_obj, 0UL, 1UL);
+	mpq_set_ui (d_obj, 0UL, 1UL);
+
+	/* now check if the given basis is the optimal basis */
+	arr3 = qslp->lower;
+	arr4 = qslp->upper;
+	if (mpq_QSload_basis (p, basis))
+	{
+		rval = 0;
+		MESSAGE (msg_lvl, "QSload_basis failed");
+		goto CLEANUP;
+	}
+	for (i = basis->nstruct; i--;)
+	{
+		/* check that the upper and lower bound define a non-empty space */
+		if (mpq_cmp (arr3[structmap[i]], arr4[structmap[i]]) > 0)
+		{
+			rval = 0;
+			if(!msg_lvl)
+			{
+				MESSAGE(0, "variable %s has empty feasible range [%lg,%lg]",
+								 qslp->colnames[i], mpq_EGlpNumToLf(arr3[structmap[i]]), 
+								 mpq_EGlpNumToLf(arr4[structmap[i]]));
+			}
+			goto CLEANUP;
+		}
+		/* set the variable to its apropiate values, depending its status */
+		switch (basis->cstat[i])
+		{
+		case QS_COL_BSTAT_FREE:
+		case QS_COL_BSTAT_BASIC:
+			if (mpq_cmp (p_sol[i], arr4[structmap[i]]) > 0)
+				mpq_set (p_sol[i], arr4[structmap[i]]);
+			else if (mpq_cmp (p_sol[i], arr3[structmap[i]]) < 0)
+				mpq_set (p_sol[i], arr3[structmap[i]]);
+			break;
+		case QS_COL_BSTAT_UPPER:
+			mpq_set (p_sol[i], arr4[structmap[i]]);
+			break;
+		case QS_COL_BSTAT_LOWER:
+			mpq_set (p_sol[i], arr3[structmap[i]]);
+			break;
+		default:
+			rval = 0;
+			MESSAGE (msg_lvl, "Unknown Variable basic status %d, for variable "
+							 "(%s,%d)", basis->cstat[i], qslp->colnames[i], i);
+			goto CLEANUP;
+			break;
+		}
+	}
+	for (i = basis->nrows; i--;)
+	{
+		/* check that the upper and lower bound define a non-empty space */
+		if (mpq_cmp (arr3[rowmap[i]], arr4[rowmap[i]]) > 0)
+		{
+			rval = 0;
+			if(!msg_lvl)
+			{
+				MESSAGE(0, "constraint %s logical has empty feasible range "
+								 "[%lg,%lg]", qslp->rownames[i], 
+								 mpq_EGlpNumToLf(arr3[rowmap[i]]), 
+								 mpq_EGlpNumToLf(arr4[rowmap[i]]));
+			}
+			goto CLEANUP;
+		}
+		/* set the variable to its apropiate values, depending its status */
+		switch (basis->rstat[i])
+		{
+		case QS_ROW_BSTAT_BASIC:
+			if (mpq_cmp (p_sol[i + basis->nstruct], arr4[rowmap[i]]) > 0)
+				mpq_set (p_sol[i + basis->nstruct], arr4[rowmap[i]]);
+			else if (mpq_cmp (p_sol[i + basis->nstruct], arr3[rowmap[i]]) < 0)
+				mpq_set (p_sol[i + basis->nstruct], arr3[rowmap[i]]);
+			break;
+		case QS_ROW_BSTAT_UPPER:
+			mpq_set (p_sol[i + basis->nstruct], arr4[rowmap[i]]);
+			break;
+		case QS_ROW_BSTAT_LOWER:
+			mpq_set (p_sol[i + basis->nstruct], arr3[rowmap[i]]);
+			break;
+		default:
+			rval = 0;
+			MESSAGE (msg_lvl, "Unknown Variable basic status %d, for constraint "
+							 "(%s,%d)", basis->cstat[i], qslp->rownames[i], i);
+			goto CLEANUP;
+			break;
+		}
+	}
+
+	/* compute the actual RHS */
+	rhs_copy = mpq_EGlpNumAllocArray (qslp->nrows);
+	for (i = qslp->nstruct; i--;)
+	{
+		if (!mpq_equal (p_sol[i], mpq_zeroLpNum))
+		{
+			arr1 = qslp->A.matval + qslp->A.matbeg[structmap[i]];
+			iarr1 = qslp->A.matind + qslp->A.matbeg[structmap[i]];
+			for (j = qslp->A.matcnt[structmap[i]]; j--;)
+			{
+				mpq_mul (num1, arr1[j], p_sol[i]);
+				mpq_add (rhs_copy[iarr1[j]], rhs_copy[iarr1[j]], num1);
+			}
+		}
+	}
+
+	/* now check if both rhs and copy_rhs are equal */
+	arr4 = qslp->upper;
+	arr1 = qslp->rhs;
+	arr2 = qslp->lower;
+	for (i = qslp->nrows; i--;)
+	{
+		mpq_mul (num1, arr1[i], d_sol[i]);
+		mpq_add (d_obj, d_obj, num1);
+		mpq_sub (num2, arr1[i], rhs_copy[i]);
+		EXIT (qslp->A.matcnt[rowmap[i]] != 1, "Imposible!");
+		if (basis->rstat[i] == QS_ROW_BSTAT_BASIC)
+			mpq_div (p_sol[qslp->nstruct + i], num2,
+							 qslp->A.matval[qslp->A.matbeg[rowmap[i]]]);
+		else
+		{
+			mpq_mul (num1, p_sol[qslp->nstruct + i],
+							 qslp->A.matval[qslp->A.matbeg[rowmap[i]]]);
+			if (!mpq_equal (num1, num2))
+			{
+				rval = 0;
+				if(!msg_lvl)
+				{
+					MESSAGE(0, "solution is infeasible for constraint %s, violation"
+								 " %lg", qslp->rownames[i],
+								 mpq_get_d (num1) - mpq_get_d (num2));
+				}
+				goto CLEANUP;
+			}
+		}
+		mpq_set (num2, p_sol[qslp->nstruct + i]);
+		/* now we check the bounds on the logical variables */
+		if (mpq_cmp (num2, arr2[rowmap[i]]) < 0)
+		{
+			rval = 0;
+			if(!msg_lvl)
+			{
+				MESSAGE(0, "constraint %s artificial (%lg) bellow lower"
+								 " bound (%lg), actual LHS (%lg), actual RHS (%lg)",
+								 qslp->rownames[i], mpq_get_d (num2), 
+								 mpq_get_d (arr2[rowmap[i]]), mpq_get_d (rhs_copy[i]), 
+								 mpq_get_d (arr1[i]));
+			}
+			goto CLEANUP;
+		}
+		else if (mpq_cmp (num2, arr4[rowmap[i]]) > 0)
+		{
+			rval = 0;
+			if(!msg_lvl)
+			{
+				MESSAGE(0, "constraint %s artificial (%lg) bellow lower bound"
+								 " (%lg)", qslp->rownames[i], mpq_get_d (num2),
+								 mpq_get_d (arr4[rowmap[i]]));
+			}
+			goto CLEANUP;
+		}
+	}
+
+	/* compute the upper and lower bound dual variables, note that dl is the dual
+	 * of the lower bounds, and du the dual of the upper bound, dl >= 0 and du <=
+	 * 0 and A^t y + Idl + Idu = c, and the dual objective value is 
+	 * max y*b + l*dl + u*du, we colapse both vector dl and du into dz, note that
+	 * if we are maximizing, then dl <= 0 and du >=0 */
+	dz = mpq_EGlpNumAllocArray (qslp->ncols);
+	arr2 = qslp->obj;
+	arr3 = qslp->lower;
+	arr4 = qslp->upper;
+	for (i = qslp->nstruct; i--;)
+	{
+		col = structmap[i];
+		mpq_mul (num1, arr2[col], p_sol[i]);
+		mpq_add (p_obj, p_obj, num1);
+		arr1 = qslp->A.matval + qslp->A.matbeg[col];
+		iarr1 = qslp->A.matind + qslp->A.matbeg[col];
+		mpq_set (num1, arr2[col]);
+		for (j = qslp->A.matcnt[col]; j--;)
+		{
+			mpq_mul (num2, arr1[j], d_sol[iarr1[j]]);
+			mpq_sub (num1, num1, num2);
+		}
+		mpq_set (dz[col], num1);
+		/* objective update */
+		if (objsense * mpq_cmp_ui (dz[col], 0UL, 1UL) > 0)
+		{
+			mpq_mul (num3, dz[col], arr3[col]);
+			mpq_add (d_obj, d_obj, num3);
+		}
+		else
+		{
+			mpq_mul (num3, dz[col], arr4[col]);
+			mpq_add (d_obj, d_obj, num3);
+		}
+		/* now we check that only when the logical is tight then the dual
+		 * variable may be non-zero, also check for primal feasibility with respect
+		 * to lower/upper bounds. */
+		mpq_set_ui (num2, 0UL, 1UL);
+		if (objsense * mpq_cmp_ui (dz[col], 0UL, 1UL) > 0)
+		{
+			mpq_sub (num1, p_sol[i], arr3[col]);
+			mpq_mul (num2, num1, dz[col]);
+		}
+		if (mpq_cmp_ui (num2, 0UL, 1UL) != 0)
+		{
+			rval = 0;
+			if(!msg_lvl)
+			{
+				MESSAGE(0, "lower bound (%s,%d) slack (%lg) and dual variable (%lg)"
+								 " don't satisfy complementary slacknes %s",
+								 qslp->colnames[i], i, mpq_get_d(num1), mpq_get_d(dz[col]),
+								 "(real)");
+			}
+			goto CLEANUP;
+		}
+		mpq_set_ui (num2, 0UL, 1UL);
+		if (objsense * mpq_cmp_ui (dz[col], 0UL, 1UL) < 0)
+		{
+			mpq_sub (num1, p_sol[i], arr4[col]);
+			mpq_mul (num2, num1, dz[col]);
+		}
+		if (mpq_cmp_ui (num2, 0UL, 1UL) != 0)
+		{
+			rval = 0;
+			if(!msg_lvl)
+			{
+				MESSAGE(0, "upper bound (%lg) variable (%lg) and dual variable"
+									" (%lg) don't satisfy complementary slacknes for variable"
+									" (%s,%d) %s", mpq_get_d(arr4[col]), mpq_get_d(p_sol[i]),
+									mpq_get_d(dz[col]), qslp->colnames[i], i, "(real)");
+			}
+			goto CLEANUP;
+		}
+	}
+	/* complenetary slackness checked, now update the same for the logical
+	 * variables */
+	for (i = qslp->nrows; i--;)
+	{
+		col = rowmap[i];
+		mpq_mul (num1, arr2[col], p_sol[i + qslp->nstruct]);
+		WARNING (mpq_cmp (arr2[col], mpq_zeroLpNum), "logical variable %s with "
+						 "non-zero objective function %lf", qslp->rownames[i],
+						 mpq_get_d (arr2[col]));
+		mpq_add (p_obj, p_obj, num1);
+		arr1 = qslp->A.matval + qslp->A.matbeg[col];
+		iarr1 = qslp->A.matind + qslp->A.matbeg[col];
+		mpq_set (num1, arr2[col]);
+		for (j = qslp->A.matcnt[col]; j--;)
+		{
+			mpq_mul (num2, arr1[j], d_sol[iarr1[j]]);
+			mpq_sub (num1, num1, num2);
+		}
+		mpq_set (dz[col], num1);
+		/* objective update */
+		if (objsense * mpq_cmp_ui (dz[col], 0UL, 1UL) > 0)
+		{
+			mpq_mul (num3, dz[col], arr3[col]);
+			mpq_add (d_obj, d_obj, num3);
+		}
+		else
+		{
+			mpq_mul (num3, dz[col], arr4[col]);
+			mpq_add (d_obj, d_obj, num3);
+		}
+		/* now we check that only when the primal variable is tight then the dual
+		 * variable may be non-zero, also check for primal feasibility with respect
+		 * to lower/upper bounds. */
+		mpq_set_ui (num2, 0UL, 1UL);
+		if (objsense * mpq_cmp_ui (dz[col], 0UL, 1UL) > 0)
+		{
+			mpq_sub (num1, p_sol[i + qslp->nstruct], arr3[col]);
+			mpq_mul (num2, num1, dz[col]);
+		}
+		if (mpq_cmp_ui (num2, 0UL, 1UL) != 0)
+		{
+			rval = 0;
+			if(!msg_lvl)
+			{
+				MESSAGE(0, "lower bound (%s,%d) slack (%lg) and dual variable (%lg)"
+								 " don't satisfy complementary slacknes %s", 
+								 qslp->colnames[col], i, mpq_get_d(num1), mpq_get_d(dz[col]), 
+								 "(real)");
+			}
+			goto CLEANUP;
+		}
+		mpq_set_ui (num2, 0UL, 1UL);
+		if (objsense * mpq_cmp_ui (dz[col], 0UL, 1UL) < 0)
+		{
+			mpq_sub (num1, p_sol[i + qslp->nstruct], arr4[col]);
+			mpq_mul (num2, num1, dz[col]);
+		}
+		if (mpq_cmp_ui (num2, 0UL, 1UL) != 0)
+		{
+			rval = 0;
+			if(!msg_lvl)
+			{
+				MESSAGE(0, "upper bound (%lg) variable (%lg) and dual variable"
+								" (%lg) don't satisfy complementary slacknes for variable "
+								"(%s,%d) %s", mpq_get_d(arr4[col]), 
+								mpq_get_d(p_sol[i+qslp->nstruct]), mpq_get_d(dz[col]), qslp->colnames[col], i,
+								"(real)");
+			}
+			goto CLEANUP;
+		}
+	}
+
+	/* now check the objective values */
+	if (mpq_cmp (p_obj, d_obj) != 0)
+	{
+		rval = 0;
+		if(!msg_lvl)
+		{
+			MESSAGE(0, "primal and dual objective value differ %lg %lg",
+							 mpq_get_d(p_obj), mpq_get_d(d_obj));
+		}
+		goto CLEANUP;
+	}
+	/* now we report optimality */
+	if(!msg_lvl)
+	{
+		MESSAGE(0, "Problem solved to optimality, LP value %lg", mpq_get_d(p_obj));
+	}
+	/* now we load into cache the solution */
+	if (!p->cache)
+	{
+		p->cache = EGsMalloc (mpq_ILLlp_cache, 1);
+		mpq_EGlpNumInitVar (p->cache->val);
+		mpq_ILLlp_cache_init (p->cache);
+	}
+	if (qslp->nrows != p->cache->nrows || qslp->nstruct != p->cache->nstruct)
+	{
+		mpq_ILLlp_cache_free (p->cache);
+		EGcallD(mpq_ILLlp_cache_alloc (p->cache, qslp->nstruct, qslp->nrows));
+	}
+	p->cache->status = QS_LP_OPTIMAL;
+	p->qstatus = QS_LP_OPTIMAL;
+	p->lp->basisstat.optimal = 1;
+	mpq_set (p->cache->val, p_obj);
+	for (i = qslp->nstruct; i--;)
+	{
+		mpq_set (p->cache->x[i], p_sol[i]);
+		mpq_set (p->cache->rc[i], dz[structmap[i]]);
+	}
+	for (i = qslp->nrows; i--;)
+	{
+		mpq_set (p->cache->slack[i], p_sol[i + qslp->nstruct]);
+		mpq_set (p->cache->pi[i], d_sol[i]);
+	}
+
+	/* save the problem and solution if enablred */
+#if QSEXACT_SAVE_OPTIMAL
+	{
+		char stmp[1024];
+		EGioFile_t *out_f = 0;
+		snprintf (stmp, 1023, "%s-opt%03d.lp", p->name ? p->name : "UNNAMED",
+							QSEXACT_SAVE_OPTIMAL_IND);
+		if (mpq_QSwrite_prob (p, stmp, "LP"))
+		{
+			rval = 0;
+			MESSAGE (0, "Couldn't write output problem %s", stmp);
+			goto CLEANUP;
+		}
+		snprintf (stmp, 1023, "%s-opt%03d.sol.gz", p->name ? p->name : "UNNAMED",
+							QSEXACT_SAVE_OPTIMAL_IND);
+		if (!(out_f = EGioOpen (stmp, "w+")))
+		{
+			rval = 0;
+			MESSAGE (0, "Couldn't open solution file %s", stmp);
+			goto CLEANUP;
+		}
+		if (QSexact_print_sol (p, out_f))
+		{
+			rval = 0;
+			MESSAGE (0, "Couldn't write output solution %s", stmp);
+			goto CLEANUP;
+		}
+		EGioClose (out_f);
+		QSEXACT_SAVE_OPTIMAL_IND++;
+	}
+#endif
+	rval = 1;
+
+	/* ending */
+CLEANUP:
+	mpq_EGlpNumFreeArray (dz);
+	mpq_EGlpNumFreeArray (rhs_copy);
+	mpq_clear (num1);
+	mpq_clear (num2);
+	mpq_clear (num3);
+	mpq_clear (p_obj);
+	mpq_clear (d_obj);
+	return rval;
+}
+
+/* ========================================================================= */
+int QSexact_infeasible_test (mpq_QSdata * p,
+														 mpq_t * d_sol)
+{
+	/* local variables */
+	register int i,
+	  j;
+	int *iarr1;
+	mpq_ILLlpdata *qslp = p->lp->O;
+	mpq_t *arr1,
+	 *arr2,
+	 *arr3,
+	 *arr4;
+	mpq_t *dl = 0,
+	 *du = 0;
+	int const msg_lvl = __QS_SB_VERB <= DEBUG ? 0 : 100000 * (1 - p->simplex_display);
+	int rval = 1;									/* store whether or not the solution is optimal, we start 
+																 * assuming it is. */
+	mpq_t num1,
+	  num2,
+	  num3,
+	  d_obj;
+	mpq_init (num1);
+	mpq_init (num2);
+	mpq_init (num3);
+	mpq_init (d_obj);
+	mpq_set_ui (d_obj, 0UL, 1UL);
+
+	/* compute the dual objective value */
+	arr2 = qslp->rhs;
+	for (i = qslp->nrows; i--;)
+	{
+		mpq_mul (num1, arr2[i], d_sol[i]);
+		mpq_add (d_obj, d_obj, num1);
+	}
+
+	/* compute the upper and lower bound dual variables, note that dl is the dual
+	 * of the lower bounds, and du the dual of the upper bound, dl <= 0 and du >=
+	 * 0 and A^t y + Idl + Idu = c, and the dual objective value is 
+	 * max y*b + l*dl + u*du */
+	du = mpq_EGlpNumAllocArray (qslp->ncols);
+	dl = mpq_EGlpNumAllocArray (qslp->ncols);
+	arr3 = qslp->lower;
+	arr4 = qslp->upper;
+	for (i = qslp->ncols; i--;)
+	{
+		arr1 = qslp->A.matval + qslp->A.matbeg[i];
+		iarr1 = qslp->A.matind + qslp->A.matbeg[i];
+		mpq_set_ui (num1, 0UL, 1UL);
+		mpq_set_ui (du[i], 0UL, 1UL);
+		mpq_set_ui (dl[i], 0UL, 1UL);
+		for (j = qslp->A.matcnt[i]; j--;)
+		{
+			mpq_mul (num2, arr1[j], d_sol[iarr1[j]]);
+			mpq_sub (num1, num1, num2);
+		}
+		if (mpq_cmp_ui (num1, 0UL, 1UL) < 0)
+			mpq_set (du[i], num1);
+		else
+			mpq_set (dl[i], num1);
+		if (mpq_equal (arr4[i], mpq_ILL_MAXDOUBLE) &&
+				mpq_cmp_ui (du[i], 0UL, 1UL) != 0)
+		{
+			rval = 0;
+			if(!msg_lvl)
+			{
+				MESSAGE(0, "upper bound of variable is INFTY, and it's dual is "
+								 "non-zero %lg", mpq_get_d(du[i]));
+			}
+			goto CLEANUP;
+		}
+		if (mpq_equal (arr3[i], mpq_ILL_MINDOUBLE) &&
+				mpq_cmp_ui (dl[i], 0UL, 1UL) != 0)
+		{
+			rval = 0;
+			if(!msg_lvl)
+			{
+				MESSAGE(0, "lower bound of variable is -INFTY, and it's dual is "
+								 "non-zero %lg", mpq_get_d(dl[i]));
+			}
+			goto CLEANUP;
+		}
+		mpq_mul (num3, dl[i], arr3[i]);
+		mpq_add (d_obj, d_obj, num3);
+		mpq_mul (num3, du[i], arr4[i]);
+		mpq_add (d_obj, d_obj, num3);
+	}
+	/* now check the objective values */
+	if (mpq_cmp_ui (d_obj, 0UL, 1UL) <= 0)
+	{
+		rval = 0;
+		if(!msg_lvl)
+		{
+			MESSAGE(0, "dual ray is feasible, but objective is non "
+							"positive %lg", mpq_get_d(d_obj));
+		}
+		goto CLEANUP;
+	}
+	p->qstatus = QS_LP_INFEASIBLE;
+
+	/* ending */
+CLEANUP:
+	mpq_EGlpNumFreeArray (dl);
+	mpq_EGlpNumFreeArray (du);
+	mpq_clear (num1);
+	mpq_clear (num2);
+	mpq_clear (num3);
+	mpq_clear (d_obj);
+	return rval;
+}
+
+/* ========================================================================= */
+/** @brief Used as separator while printing output to the screen (controled by
+ * enabling simplex_display in the mpq_QSdata */
+/* ========================================================================= */
+static const char __sp[81] =
+	"================================================================================";
+
+/* ========================================================================= */
+/** @brief print into screen (if enable) a message indicating that we have
+ * successfully prove infeasibility, and save (if y is non
+ * NULL ) the dual ray solution provided in y_mpq.
+ * @param p_mpq the problem data.
+ * @param y where to store the optimal dual solution (if not null).
+ * @param y_mpq  the optimal dual solution.
+ * */
+/* ========================================================================= */
+static void infeasible_output (mpq_QSdata * p_mpq,
+															 mpq_t * const y,
+															 mpq_t * y_mpq)
+{
+	if (p_mpq->simplex_display)
+	{
+		QSlog("Problem Is Infeasible");
+	}
+	if (y)
+	{
+		unsigned sz = __EGlpNumArraySize (y_mpq);
+		while (sz--)
+			mpq_set (y[sz], y_mpq[sz]);
+	}
+}
+
+/* ========================================================================= */
+/** @brief print into screen (if enable) a message indicating that we have
+ * successfully solved the problem at optimality, and save (if x and y are non
+ * NULL respectivelly) the optimal primal/dual solution provided in x_mpq and
+ * y_mpq. 
+ * @param p_mpq the problem data.
+ * @param x where to store the optimal primal solution (if not null).
+ * @param y where to store the optimal dual solution (if not null).
+ * @param x_mpq  the optimal primal solution.
+ * @param y_mpq  the optimal dual solution.
+ * */
+/* ========================================================================= */
+static void optimal_output (mpq_QSdata * p_mpq,
+														mpq_t * const x,
+														mpq_t * const y,
+														mpq_t * x_mpq,
+														mpq_t * y_mpq)
+{
+	if (p_mpq->simplex_display)
+	{
+		QSlog("Problem Solved Exactly");
+	}
+	if (y)
+	{
+		unsigned sz = __EGlpNumArraySize (y_mpq);
+		while (sz--)
+			mpq_set (y[sz], y_mpq[sz]);
+	}
+	if (x)
+	{
+		unsigned sz = __EGlpNumArraySize (x_mpq);
+		while (sz--)
+			mpq_set (x[sz], x_mpq[sz]);
+	}
+}
+
+/* ========================================================================= */
+/** @brief get the status for a given basis in rational arithmetic, it should
+ * also leave everything set to get primal/dual solutions when needed.
+ * */
+static int QSexact_basis_status (mpq_QSdata * p_mpq,
+																 int *status,
+																 QSbasis * const basis,
+																 const int msg_lvl,
+																 int *const simplexalgo)
+{
+	int rval = 0,
+	singular;
+	mpq_feas_info fi;
+	EGtimer_t local_timer;
+	mpq_EGlpNumInitVar (fi.totinfeas);
+	EGtimerReset (&local_timer);
+	EGtimerStart (&local_timer);
+	EGcallD(mpq_QSload_basis (p_mpq, basis));
+	if (p_mpq->cache) 
+	{
+		mpq_ILLlp_cache_free (p_mpq->cache);
+		mpq_clear (p_mpq->cache->val);
+		ILL_IFFREE (p_mpq->cache, mpq_ILLlp_cache); 
+	}
+	p_mpq->qstatus = QS_LP_MODIFIED;
+	if(p_mpq->qslp->sinfo) 
+	{
+		mpq_ILLlp_sinfo_free(p_mpq->qslp->sinfo);
+		ILL_IFFREE(p_mpq->qslp->sinfo, mpq_ILLlp_sinfo); 
+	}
+	if(p_mpq->qslp->rA)
+	{
+		mpq_ILLlp_rows_clear (p_mpq->qslp->rA);
+		ILL_IFFREE (p_mpq->qslp->rA, mpq_ILLlp_rows);
+	}
+	mpq_free_internal_lpinfo (p_mpq->lp);
+	mpq_init_internal_lpinfo (p_mpq->lp);
+	EGcallD(mpq_build_internal_lpinfo (p_mpq->lp));
+	mpq_ILLfct_set_variable_type (p_mpq->lp);
+	EGcallD(mpq_ILLbasis_load (p_mpq->lp, p_mpq->basis));
+	EGcallD(mpq_ILLbasis_factor (p_mpq->lp, &singular));
+	memset (&(p_mpq->lp->basisstat), 0, sizeof (mpq_lp_status_info));
+	mpq_ILLfct_compute_piz (p_mpq->lp);
+	mpq_ILLfct_compute_dz (p_mpq->lp);
+	mpq_ILLfct_compute_xbz (p_mpq->lp);
+	mpq_ILLfct_check_pfeasible (p_mpq->lp, &fi, mpq_zeroLpNum);
+	mpq_ILLfct_check_dfeasible (p_mpq->lp, &fi, mpq_zeroLpNum);
+	mpq_ILLfct_set_status_values (p_mpq->lp, fi.pstatus, fi.dstatus, PHASEII,
+			PHASEII);
+	if (p_mpq->lp->basisstat.optimal)
+	{
+		*status = QS_LP_OPTIMAL;
+		EGcallD(mpq_QSgrab_cache (p_mpq, QS_LP_OPTIMAL));
+	}
+	else if (p_mpq->lp->basisstat.primal_infeasible
+			|| p_mpq->lp->basisstat.dual_unbounded)
+	{
+		if (*status == QS_LP_INFEASIBLE)
+			*simplexalgo = PRIMAL_SIMPLEX;
+		*status = QS_LP_INFEASIBLE;
+		p_mpq->lp->final_phase = PRIMAL_PHASEI;
+		p_mpq->lp->pIpiz = mpq_EGlpNumAllocArray (p_mpq->lp->nrows);
+		mpq_ILLfct_compute_phaseI_piz (p_mpq->lp);
+	}
+	else if (p_mpq->lp->basisstat.primal_unbounded)
+		*status = QS_LP_UNBOUNDED;
+	else
+		*status = QS_LP_UNSOLVED;
+	EGtimerStop (&local_timer);
+	if(!msg_lvl)
+	{
+		MESSAGE(0, "Performing Rational Basic Solve on %s, %s, check"
+				" done in %lg seconds, PS %s %lg, DS %s %lg", p_mpq->name, 
+				(*status == QS_LP_OPTIMAL) ? "RAT_optimal" : 
+				((*status == QS_LP_INFEASIBLE) ?  "RAT_infeasible" : 
+				 ((*status == QS_LP_UNBOUNDED) ?  "RAT_unbounded" : "RAT_unsolved")),
+				local_timer.time, p_mpq->lp->basisstat.primal_feasible ? 
+				"F":(p_mpq->lp->basisstat.primal_infeasible ? "I" : "U"), 
+				p_mpq->lp->basisstat.primal_feasible ?
+				mpq_get_d(p_mpq->lp->objval) : 
+				(p_mpq->lp->basisstat.primal_infeasible ?
+				 mpq_get_d(p_mpq->lp->pinfeas) : mpq_get_d(p_mpq->lp->objbound)), 
+				p_mpq->lp->basisstat.dual_feasible ? 
+				"F":(p_mpq->lp->basisstat.dual_infeasible ? "I" : "U"), 
+				p_mpq->lp->basisstat.dual_feasible ? mpq_get_d(p_mpq->lp->dobjval) 
+				:(p_mpq->lp->basisstat.dual_infeasible ? 
+					mpq_get_d(p_mpq->lp->dinfeas) : mpq_get_d(p_mpq->lp->objbound)) );
+	}
+CLEANUP:
+	mpq_EGlpNumClearVar (fi.totinfeas);
+	return rval;
+}
+
+/* ========================================================================= */
+/** @brief test whether given basis is primal and dual feasible in rational arithmetic. 
+ * @param p_mpq   the problem data.
+ * @param basis   basis to be tested.
+ * @param result  where to store whether given basis is primal and dual feasible.
+ * @param msg_lvl message level.
+ */
+int QSexact_basis_optimalstatus(
+   mpq_QSdata * p_mpq,
+   QSbasis* basis,
+   char* result,
+   const int msg_lvl
+   )
+{
+   int rval = 0,
+      singular;
+   mpq_feas_info fi;
+   EGtimer_t local_timer;
+
+   /* test primal and dual feasibility of basic solution */
+   mpq_EGlpNumInitVar (fi.totinfeas);
+
+   EGtimerReset (&local_timer);
+   EGtimerStart (&local_timer);
+
+   EGcallD(mpq_QSload_basis (p_mpq, basis));
+
+   if (p_mpq->cache) 
+   {
+      mpq_ILLlp_cache_free (p_mpq->cache);
+      mpq_clear (p_mpq->cache->val);
+      ILL_IFFREE (p_mpq->cache, mpq_ILLlp_cache); 
+   }
+   p_mpq->qstatus = QS_LP_MODIFIED;
+
+   if(p_mpq->qslp->sinfo) 
+   {
+      mpq_ILLlp_sinfo_free(p_mpq->qslp->sinfo);
+      ILL_IFFREE(p_mpq->qslp->sinfo, mpq_ILLlp_sinfo); 
+   }
+   if(p_mpq->qslp->rA)
+   {
+      mpq_ILLlp_rows_clear (p_mpq->qslp->rA);
+      ILL_IFFREE (p_mpq->qslp->rA, mpq_ILLlp_rows);
+   }
+
+   mpq_free_internal_lpinfo (p_mpq->lp);
+   mpq_init_internal_lpinfo (p_mpq->lp);
+   EGcallD(mpq_build_internal_lpinfo (p_mpq->lp));
+
+   mpq_ILLfct_set_variable_type (p_mpq->lp);
+
+   EGcallD(mpq_ILLbasis_load (p_mpq->lp, p_mpq->basis));
+   EGcallD(mpq_ILLbasis_factor (p_mpq->lp, &singular));
+
+   memset (&(p_mpq->lp->basisstat), 0, sizeof (mpq_lp_status_info));
+   mpq_ILLfct_compute_piz (p_mpq->lp); 
+   mpq_ILLfct_compute_dz (p_mpq->lp);
+   mpq_ILLfct_compute_xbz (p_mpq->lp);
+   mpq_ILLfct_check_pfeasible (p_mpq->lp, &fi, mpq_zeroLpNum);
+   mpq_ILLfct_check_dfeasible (p_mpq->lp, &fi, mpq_zeroLpNum);
+   mpq_ILLfct_set_status_values (p_mpq->lp, fi.pstatus, fi.dstatus, PHASEII, PHASEII);
+   
+   if( p_mpq->lp->basisstat.optimal )
+   {
+      *result = 1;
+   }
+   else
+   {
+      *result = 0;
+   }
+
+   EGtimerStop (&local_timer);
+
+   if( !msg_lvl )
+   {
+      MESSAGE(0, "Performing rational solution check for accuratelp on %s, sucess=%s", 
+         p_mpq->name, 
+         *result ? "YES" : "NO");
+   }
+   
+ CLEANUP:
+   mpq_EGlpNumClearVar (fi.totinfeas);
+   return rval;
+}
+
+/* ========================================================================= */
+/** @brief test whether given basis is dual feasible in rational arithmetic. 
+ * @param p_mpq   the problem data.
+ * @param basis   basis to be tested.
+ * @param result  where to store whether given basis is dual feasible.
+ * @param dobjval where to store dual solution value in case of dual feasibility (if not NULL).
+ * @param msg_lvl message level.
+ */
+int QSexact_basis_dualstatus(
+   mpq_QSdata * p_mpq,
+   QSbasis* basis,
+   char* result,
+   mpq_t* dobjval,
+   const int msg_lvl
+   )
+{
+	int rval = 0,
+	singular;
+	mpq_feas_info fi;
+	EGtimer_t local_timer;
+
+	mpq_EGlpNumInitVar (fi.totinfeas);
+	EGtimerReset (&local_timer);
+	EGtimerStart (&local_timer);
+	EGcallD(mpq_QSload_basis (p_mpq, basis));
+	if (p_mpq->cache) 
+	{
+		mpq_ILLlp_cache_free (p_mpq->cache);
+		mpq_clear (p_mpq->cache->val);
+		ILL_IFFREE (p_mpq->cache, mpq_ILLlp_cache); 
+	}
+	p_mpq->qstatus = QS_LP_MODIFIED;
+
+	if(p_mpq->qslp->sinfo) 
+	{
+		mpq_ILLlp_sinfo_free(p_mpq->qslp->sinfo);
+		ILL_IFFREE(p_mpq->qslp->sinfo, mpq_ILLlp_sinfo); 
+	}
+
+	if(p_mpq->qslp->rA)
+	{
+		mpq_ILLlp_rows_clear (p_mpq->qslp->rA);
+		ILL_IFFREE (p_mpq->qslp->rA, mpq_ILLlp_rows);
+	}
+
+	mpq_free_internal_lpinfo (p_mpq->lp);
+	mpq_init_internal_lpinfo (p_mpq->lp);
+	EGcallD(mpq_build_internal_lpinfo (p_mpq->lp));
+	mpq_ILLfct_set_variable_type (p_mpq->lp);
+	EGcallD(mpq_ILLbasis_load (p_mpq->lp, p_mpq->basis));
+	EGcallD(mpq_ILLbasis_factor (p_mpq->lp, &singular));
+
+	memset (&(p_mpq->lp->basisstat), 0, sizeof (mpq_lp_status_info));
+	mpq_ILLfct_compute_piz (p_mpq->lp); 
+	mpq_ILLfct_compute_dz (p_mpq->lp);
+	mpq_ILLfct_compute_dobj(p_mpq->lp); 
+	mpq_ILLfct_check_dfeasible (p_mpq->lp, &fi, mpq_zeroLpNum);
+	mpq_ILLfct_set_status_values (p_mpq->lp, fi.pstatus, fi.dstatus, PHASEII, PHASEII);
+
+	if( p_mpq->lp->basisstat.dual_feasible )
+	{
+		*result = 1;
+		if( dobjval )
+		{
+			mpq_EGlpNumCopy(*dobjval, p_mpq->lp->dobjval);
+		}
+	}
+	else if( p_mpq->lp->basisstat.dual_infeasible )
+	{
+		*result = 0;
+	}
+	else 
+	{
+		TESTG((rval=!(p_mpq->lp->basisstat.dual_unbounded)), CLEANUP, "Internal BUG, problem should be dual unbounded but is not");
+		*result = 1;
+		if( dobjval )
+		{
+			mpq_EGlpNumCopy(*dobjval, p_mpq->lp->objbound);
+		}
+	}
+
+	EGtimerStop (&local_timer);
+
+	if(!msg_lvl)
+	{
+		MESSAGE(0, "Performing Rational Basic Test on %s, check done in %lg seconds, DS %s %lg", 
+				p_mpq->name, local_timer.time, 
+				p_mpq->lp->basisstat.dual_feasible ? "F": (p_mpq->lp->basisstat.dual_infeasible ? "I" : "U"), 
+				p_mpq->lp->basisstat.dual_feasible ? mpq_get_d(p_mpq->lp->dobjval) : (p_mpq->lp->basisstat.dual_infeasible ? mpq_get_d(p_mpq->lp->dinfeas) : mpq_get_d(p_mpq->lp->objbound)) );
+	}
+
+CLEANUP:
+	mpq_EGlpNumClearVar (fi.totinfeas);
+	return rval;
+}
+
+/* ========================================================================= */
+/** @brief test whether given basis is dual feasible in rational arithmetic. 
+ * if wanted it will first directly test the corresponding approximate dual and primal solution 
+ * (corrected via dual variables for bounds and primal variables for slacks if possible) for optimality
+ * before performing the dual feasibility test on the more expensive exact basic solution. 
+ * @param p_mpq   the problem data.
+ * @param basis   basis to be tested.
+ * @param useprestep whether to directly test approximate primal and dual solution first.
+ * @param dbl_p_sol  approximate primal solution to use in prestep 
+ *                   (NULL in order to compute it by dual simplex in double precision with given starting basis).
+ * @param dbl_d_sol  approximate dual solution to use in prestep 
+ *                   (NULL in order to compute it by dual simplex in double precision with given starting basis).
+ * @param result  where to store whether given basis is dual feasible.
+ * @param dobjval where to store dual solution value in case of dual feasibility (if not NULL).
+ * @param msg_lvl message level.
+ */
+int QSexact_verify (
+   mpq_QSdata * p_mpq,
+   QSbasis* basis,
+   int useprestep,
+   double* dbl_p_sol,
+   double* dbl_d_sol,
+   char* result,
+   mpq_t* dobjval,
+   const int msg_lvl
+)
+{
+   int rval = 0;
+
+   //assert(basis);
+   //assert(basis->nstruct);
+
+   *result = 0;
+            
+   if( useprestep )
+   {
+      mpq_t *x_mpq = 0;
+      mpq_t *y_mpq = 0;
+      int status = 0;
+
+      if( dbl_p_sol == NULL || dbl_d_sol == NULL  )
+      {
+         dbl_QSdata *p_dbl = 0;
+         double *x_dbl = 0;
+         double *y_dbl = 0;
+
+         /* create double problem, warmstart with given basis and solve it using double precision 
+          * this is only done to get approximate primal and dual solution corresponding to the given basis 
+          */
+         p_dbl = QScopy_prob_mpq_dbl(p_mpq, "dbl_problem");
+   
+         dbl_QSload_basis(p_dbl, basis);
+         rval = dbl_ILLeditor_solve(p_dbl, DUAL_SIMPLEX);
+         CHECKRVALG(rval, CLEANUP);
+      
+         rval = dbl_QSget_status(p_dbl, &status);
+         CHECKRVALG(rval, CLEANUP);
+      
+         if( status == QS_LP_OPTIMAL )
+         {
+            /* get continued fraction approximation of approximate solution */
+            x_dbl = dbl_EGlpNumAllocArray(p_dbl->qslp->ncols);
+            y_dbl = dbl_EGlpNumAllocArray(p_dbl->qslp->nrows);
+
+            rval = dbl_QSget_x_array(p_dbl, x_dbl);
+            CHECKRVALG(rval, CLEANUP);
+            rval = dbl_QSget_pi_array(p_dbl, y_dbl);
+            CHECKRVALG(rval, CLEANUP);
+            x_mpq = QScopy_array_dbl_mpq(x_dbl);
+            y_mpq = QScopy_array_dbl_mpq(y_dbl);
+            
+            /* test optimality of constructed solution */
+            basis = dbl_QSget_basis(p_dbl);
+            rval = QSexact_optimal_test(p_mpq, x_mpq, y_mpq, basis);
+            if( rval )
+            {
+               *result = 1;
+               if( dobjval )
+               {
+                  rval = mpq_QSget_objval(p_mpq, dobjval);
+                  if( rval )
+                     *result = 0;
+               }         
+            }
+            if( !msg_lvl )
+            {
+               MESSAGE(0, "Performing approximated solution check on %s, sucess=%s dobjval=%lg", 
+                  p_mpq->name, 
+                  *result ? "YES" : "NO",
+                  *result ? mpq_get_d(*dobjval) : mpq_get_d(*dobjval));
+            }
+         }
+      CLEANUP:
+         dbl_EGlpNumFreeArray(x_dbl);
+         dbl_EGlpNumFreeArray(y_dbl);
+         mpq_EGlpNumFreeArray(x_mpq);
+         mpq_EGlpNumFreeArray(y_mpq);
+         dbl_QSfree_prob(p_dbl);
+         rval = 0;
+      }
+      else
+      {
+         dbl_QSdata *p_dbl = 0;
+         int i;
+
+         /* for some reason, this help to avoid fails in QSexact_basis_dualstatus() after 
+          * the test here fails, i.e., if we would not perform the test here, than QSexact_basis_dualstatus() would normally not fail
+          * something happens with the basis... if we do not set up the dbl-prob (?) ????????????????????????
+          */
+         p_dbl = QScopy_prob_mpq_dbl(p_mpq, "dbl_problem");
+         dbl_QSload_basis(p_dbl, basis);
+
+         x_mpq = mpq_EGlpNumAllocArray(p_mpq->qslp->ncols);
+         y_mpq = mpq_EGlpNumAllocArray(p_mpq->qslp->nrows);
+
+         /* get continued fraction approximation of approximate solution */
+         for( i = 0; i < p_mpq->qslp->ncols; ++i )
+            mpq_EGlpNumSet(x_mpq[i], dbl_p_sol[i]);
+
+         for( i = 0; i < p_mpq->qslp->nrows; ++i )
+            mpq_EGlpNumSet(y_mpq[i], dbl_d_sol[i]);
+            
+         /* test optimality of constructed solution */
+         basis = dbl_QSget_basis(p_dbl);
+         rval = QSexact_optimal_test(p_mpq, x_mpq, y_mpq, basis);
+         if( rval )
+         {
+            *result = 1;
+            if( dobjval )
+            {
+               rval = mpq_QSget_objval(p_mpq, dobjval);
+               if( rval )
+                  *result = 0;
+            }         
+         }
+         if( !msg_lvl )
+         {
+            MESSAGE(0, "Performing approximated solution check on %s, sucess=%s dobjval=%lg", 
+               p_mpq->name, 
+               *result ? "YES" : "NO",
+               *result ? mpq_get_d(*dobjval) : mpq_get_d(*dobjval));
+         }
+         mpq_EGlpNumFreeArray(x_mpq);
+         mpq_EGlpNumFreeArray(y_mpq);
+         dbl_QSfree_prob(p_dbl);
+         rval = 0;
+      }
+   }
+
+   if( !(*result) )
+   {
+      rval = QSexact_basis_dualstatus(p_mpq, basis, result, dobjval, msg_lvl);
+      if( !msg_lvl )
+      {
+         MESSAGE(0, "Performing rational solution check on %s, sucess=%s dobjval=%lg", 
+            p_mpq->name, 
+            *result ? "YES" : "NO",
+            *result ? mpq_get_d(*dobjval) : mpq_get_d(*dobjval));
+      }
+   }
+
+   return rval;
+}
+
+/* ========================================================================= */
+int QSexact_solver (mpq_QSdata * p_mpq,
+										mpq_t * const x,
+										mpq_t * const y,
+										QSbasis * const ebasis,
+										int simplexalgo,
+										int *status)
+{
+	/* local variables */
+	int last_status = 0, last_iter = 0;
+	QSbasis *basis = 0;
+	unsigned precision = EGLPNUM_PRECISION;
+	int rval = 0,
+	  it = QS_EXACT_MAX_ITER;
+	dbl_QSdata *p_dbl = 0;
+	mpf_QSdata *p_mpf = 0;
+	double *x_dbl = 0,
+	 *y_dbl = 0;
+	mpq_t *x_mpq = 0,
+	 *y_mpq = 0;
+	mpf_t *x_mpf = 0,
+	 *y_mpf = 0;
+	int const msg_lvl = __QS_SB_VERB <= DEBUG ? 0: (1 - p_mpq->simplex_display) * 10000;
+	*status = 0;
+	/* save the problem if we are really debugging */
+	if(DEBUG >= __QS_SB_VERB)
+	{
+		EGcallD(mpq_QSwrite_prob(p_mpq, "qsxprob.lp","LP"));
+	}
+	/* try first with doubles */
+	if (p_mpq->simplex_display || DEBUG >= __QS_SB_VERB)
+	{
+		QSlog("Trying double precision");
+	}
+	p_dbl = QScopy_prob_mpq_dbl (p_mpq, "dbl_problem");
+	if(__QS_SB_VERB <= DEBUG) p_dbl->simplex_display = 1;
+	if (ebasis && ebasis->nstruct)
+		dbl_QSload_basis (p_dbl, ebasis);
+	if (dbl_ILLeditor_solve (p_dbl, simplexalgo))
+	{
+		MESSAGE(p_mpq->simplex_display ? 0: __QS_SB_VERB, 
+						"double approximation failed, code %d, "
+						"continuing in extended precision", rval);
+		goto MPF_PRECISION;
+	}
+	EGcallD(dbl_QSget_status (p_dbl, status));
+	if ((*status == QS_LP_INFEASIBLE) &&
+			(p_dbl->lp->final_phase != PRIMAL_PHASEI) &&
+			(p_dbl->lp->final_phase != DUAL_PHASEII))
+		dbl_QSopt_primal (p_dbl, status);
+	EGcallD(dbl_QSget_status (p_dbl, status));
+	last_status = *status;
+	EGcallD(dbl_QSget_itcnt(p_dbl, 0, 0, 0, 0, &last_iter));
+	/* deal with the problem depending on what status we got from our optimizer */
+	switch (*status)
+	{
+	case QS_LP_OPTIMAL:
+		x_dbl = dbl_EGlpNumAllocArray (p_dbl->qslp->ncols);
+		y_dbl = dbl_EGlpNumAllocArray (p_dbl->qslp->nrows);
+		EGcallD(dbl_QSget_x_array (p_dbl, x_dbl));
+		EGcallD(dbl_QSget_pi_array (p_dbl, y_dbl));
+		x_mpq = QScopy_array_dbl_mpq (x_dbl);
+		y_mpq = QScopy_array_dbl_mpq (y_dbl);
+		dbl_EGlpNumFreeArray (x_dbl);
+		dbl_EGlpNumFreeArray (y_dbl);
+		basis = dbl_QSget_basis (p_dbl);
+		if (QSexact_optimal_test (p_mpq, x_mpq, y_mpq, basis))
+		{
+			optimal_output (p_mpq, x, y, x_mpq, y_mpq);
+			goto CLEANUP;
+		}
+		else
+		{
+			EGcallD(QSexact_basis_status (p_mpq, status, basis, msg_lvl, &simplexalgo));
+			if (*status == QS_LP_OPTIMAL)
+			{
+				if(!msg_lvl)
+				{
+					MESSAGE(0,"Retesting solution");
+				}
+				EGcallD(mpq_QSget_x_array (p_mpq, x_mpq));
+				EGcallD(mpq_QSget_pi_array (p_mpq, y_mpq));
+				if (QSexact_optimal_test (p_mpq, x_mpq, y_mpq, basis))
+				{
+					optimal_output (p_mpq, x, y, x_mpq, y_mpq);
+					goto CLEANUP;
+				}
+				else
+				{
+					last_status = *status = QS_LP_UNSOLVED;
+				}
+			}
+			else
+			{
+				if(!msg_lvl)
+				{
+					MESSAGE(0,"Status is not optimal, but %d", *status);
+				}
+			}
+		}
+		mpq_EGlpNumFreeArray (x_mpq);
+		mpq_EGlpNumFreeArray (y_mpq);
+		break;
+	case QS_LP_INFEASIBLE:
+		y_dbl = dbl_EGlpNumAllocArray (p_dbl->qslp->nrows);
+		if (dbl_QSget_infeas_array (p_dbl, y_dbl))
+		{
+			MESSAGE(p_mpq->simplex_display ? 0 : __QS_SB_VERB, "double approximation"
+							" failed, code %d, continuing in extended precision\n", rval);
+			goto MPF_PRECISION;
+		}
+		y_mpq = QScopy_array_dbl_mpq (y_dbl);
+		dbl_EGlpNumFreeArray (y_dbl);
+		if (QSexact_infeasible_test (p_mpq, y_mpq))
+		{
+			infeasible_output (p_mpq, y, y_mpq);
+			goto CLEANUP;
+		}
+		else
+		{
+			MESSAGE (msg_lvl, "Retesting solution in exact arithmetic");
+			basis = dbl_QSget_basis (p_dbl);
+			EGcallD(QSexact_basis_status (p_mpq, status, basis, msg_lvl, &simplexalgo));
+			#if 0
+			mpq_QSset_param (p_mpq, QS_PARAM_SIMPLEX_MAX_ITERATIONS, 1);
+			mpq_QSload_basis (p_mpq, basis);
+			mpq_QSfree_basis (basis);
+			EGcallD(mpq_ILLeditor_solve (p_mpq, simplexalgo));
+			EGcallD(mpq_QSget_status (p_mpq, status));
+			#endif
+			if (*status == QS_LP_INFEASIBLE)
+			{
+				mpq_EGlpNumFreeArray (y_mpq);
+				y_mpq = mpq_EGlpNumAllocArray (p_mpq->qslp->nrows);
+				EGcallD(mpq_QSget_infeas_array (p_mpq, y_mpq));
+				if (QSexact_infeasible_test (p_mpq, y_mpq))
+				{
+					infeasible_output (p_mpq, y, y_mpq);
+					goto CLEANUP;
+				}
+				else
+				{
+					last_status = *status = QS_LP_UNSOLVED;
+				}
+			}
+		}
+		mpq_EGlpNumFreeArray (y_mpq);
+		break;
+	case QS_LP_UNBOUNDED:
+		MESSAGE(p_mpq->simplex_display ? 0 : __QS_SB_VERB, "%s\n\tUnbounded "
+						"Problem found, not implemented to deal with this\n%s\n",__sp,__sp);
+		break;
+	case QS_LP_OBJ_LIMIT:
+		rval=1;
+		IFMESSAGE(p_mpq->simplex_display,"Objective limit reached (in floating point) ending now");
+		goto CLEANUP;
+		break;
+	default:
+		IFMESSAGE(p_mpq->simplex_display,"Re-trying inextended precision");
+		break;
+	}
+	/* if we reach this point, then we have to keep going, we use the previous
+	 * basis ONLY if the previous precision think that it has the optimal
+	 * solution, otherwise we start from scratch. */
+	precision = 128;
+	MPF_PRECISION:
+	dbl_QSfree_prob (p_dbl);
+	p_dbl = 0;
+	/* try with multiple precision floating points */
+	for (; it--; precision = (unsigned) (precision * 1.5))
+	{
+		QSexact_set_precision (precision);
+		if (p_mpq->simplex_display || DEBUG >= __QS_SB_VERB)
+		{
+			QSlog("Trying mpf with %u bits", precision);
+		}
+		p_mpf = QScopy_prob_mpq_mpf (p_mpq, "mpf_problem");
+		if(DEBUG >= __QS_SB_VERB)
+		{
+			EGcallD(mpf_QSwrite_prob(p_mpf, "qsxprob.mpf.lp","LP"));
+		}
+		if(__QS_SB_VERB <= DEBUG) p_mpf->simplex_display = 1;
+		simplexalgo = PRIMAL_SIMPLEX;
+		if(!last_iter) last_status = QS_LP_UNSOLVED;
+		if(last_status == QS_LP_OPTIMAL || last_status == QS_LP_INFEASIBLE)
+		{
+			if (p_mpq->simplex_display || DEBUG >= __QS_SB_VERB)
+			{
+				QSlog("Re-using previous basis");
+			}
+			if (basis)
+			{
+				EGcallD(mpf_QSload_basis (p_mpf, basis));
+				mpf_QSfree_basis (basis);
+				simplexalgo = DUAL_SIMPLEX;
+				basis = 0;
+			}
+			else if (ebasis && ebasis->nstruct)
+			{
+				mpf_QSload_basis (p_mpf, ebasis);
+				simplexalgo = DUAL_SIMPLEX;
+			}
+		}
+		else
+		{
+			if(p_mpf->basis)
+			{
+				mpf_ILLlp_basis_free(p_mpf->basis);
+				p_mpf->lp->basisid = -1;
+				p_mpf->factorok = 0;
+			}
+			if (p_mpq->simplex_display || DEBUG >= __QS_SB_VERB)
+			{
+				QSlog("Not-using previous basis");
+			}
+		}
+		if (mpf_ILLeditor_solve (p_mpf, simplexalgo))
+		{
+			if (p_mpq->simplex_display || DEBUG >= __QS_SB_VERB)
+			{
+				QSlog("mpf_%u precision falied, error code %d, continuing with "
+										"next precision", precision, rval);
+			 }
+			goto NEXT_PRECISION;
+		}
+		EGcallD(mpf_QSget_status (p_mpf, status));
+		if ((*status == QS_LP_INFEASIBLE) &&
+				(p_mpf->lp->final_phase != PRIMAL_PHASEI) &&
+				(p_mpf->lp->final_phase != DUAL_PHASEII))
+			mpf_QSopt_primal (p_mpf, status);
+		EGcallD(mpf_QSget_status (p_mpf, status));
+		last_status = *status;
+		EGcallD(mpf_QSget_itcnt(p_mpf, 0, 0, 0, 0, &last_iter));
+		/* deal with the problem depending on status we got from our optimizer */
+		switch (*status)
+		{
+		case QS_LP_OPTIMAL:
+			basis = mpf_QSget_basis (p_mpf);
+			x_mpf = mpf_EGlpNumAllocArray (p_mpf->qslp->ncols);
+			y_mpf = mpf_EGlpNumAllocArray (p_mpf->qslp->nrows);
+			EGcallD(mpf_QSget_x_array (p_mpf, x_mpf));
+			EGcallD(mpf_QSget_pi_array (p_mpf, y_mpf));
+			x_mpq = QScopy_array_mpf_mpq (x_mpf);
+			y_mpq = QScopy_array_mpf_mpq (y_mpf);
+			mpf_EGlpNumFreeArray (x_mpf);
+			mpf_EGlpNumFreeArray (y_mpf);
+			if (QSexact_optimal_test (p_mpq, x_mpq, y_mpq, basis))
+			{
+				optimal_output (p_mpq, x, y, x_mpq, y_mpq);
+				goto CLEANUP;
+			}
+			else
+			{
+				EGcallD(QSexact_basis_status (p_mpq, status, basis, msg_lvl, &simplexalgo));
+				if (*status == QS_LP_OPTIMAL)
+				{
+					MESSAGE (msg_lvl, "Retesting solution");
+					EGcallD(mpq_QSget_x_array (p_mpq, x_mpq));
+					EGcallD(mpq_QSget_pi_array (p_mpq, y_mpq));
+					if (QSexact_optimal_test (p_mpq, x_mpq, y_mpq, basis))
+					{
+						optimal_output (p_mpq, x, y, x_mpq, y_mpq);
+						goto CLEANUP;
+					}
+					else
+					{
+						last_status = *status = QS_LP_UNSOLVED;
+					}
+				}
+				else
+					MESSAGE (msg_lvl, "Status is not optimal, but %d", *status);
+			}
+			mpq_EGlpNumFreeArray (x_mpq);
+			mpq_EGlpNumFreeArray (y_mpq);
+			break;
+		case QS_LP_INFEASIBLE:
+			y_mpf = mpf_EGlpNumAllocArray (p_mpf->qslp->nrows);
+			EGcallD(mpf_QSget_infeas_array (p_mpf, y_mpf));
+			y_mpq = QScopy_array_mpf_mpq (y_mpf);
+			mpf_EGlpNumFreeArray (y_mpf);
+			if (QSexact_infeasible_test (p_mpq, y_mpq))
+			{
+				infeasible_output (p_mpq, y, y_mpq);
+				goto CLEANUP;
+			}
+			else
+			{
+				MESSAGE (msg_lvl, "Retesting solution in exact arithmetic");
+				basis = mpf_QSget_basis (p_mpf);
+				EGcallD(QSexact_basis_status (p_mpq, status, basis, msg_lvl, &simplexalgo));
+#if 0
+				mpq_QSset_param (p_mpq, QS_PARAM_SIMPLEX_MAX_ITERATIONS, 1);
+				mpq_QSload_basis (p_mpq, basis);
+				mpq_QSfree_basis (basis);
+				EGcallD(mpq_ILLeditor_solve (p_mpq, simplexalgo));
+				EGcallD(mpq_QSget_status (p_mpq, status));
+#endif
+				if (*status == QS_LP_INFEASIBLE)
+				{
+					mpq_EGlpNumFreeArray (y_mpq);
+					y_mpq = mpq_EGlpNumAllocArray (p_mpq->qslp->nrows);
+					EGcallD(mpq_QSget_infeas_array (p_mpq, y_mpq));
+					if (QSexact_infeasible_test (p_mpq, y_mpq))
+					{
+						infeasible_output (p_mpq, y, y_mpq);
+						goto CLEANUP;
+					}
+					else
+					{
+						last_status = *status = QS_LP_UNSOLVED;
+					}
+				}
+			}
+			mpq_EGlpNumFreeArray (y_mpq);
+			break;
+			break;
+		case QS_LP_OBJ_LIMIT:
+			rval=1;
+			IFMESSAGE(p_mpq->simplex_display,"Objective limit reached (in floating point) ending now");
+			goto CLEANUP;
+			break;
+		case QS_LP_UNBOUNDED:
+		default:
+			MESSAGE(__QS_SB_VERB,"Re-trying inextended precision");
+			break;
+		}
+	NEXT_PRECISION:
+		mpf_QSfree_prob (p_mpf);
+		p_mpf = 0;
+	}
+	/* ending */
+CLEANUP:
+	dbl_EGlpNumFreeArray (x_dbl);
+	dbl_EGlpNumFreeArray (y_dbl);
+	mpq_EGlpNumFreeArray (x_mpq);
+	mpq_EGlpNumFreeArray (y_mpq);
+	mpf_EGlpNumFreeArray (x_mpf);
+	mpf_EGlpNumFreeArray (y_mpf);
+	if (ebasis && basis)
+	{
+		ILL_IFFREE (ebasis->cstat, char);
+		ILL_IFFREE (ebasis->rstat, char);
+		ebasis->nstruct = basis->nstruct;
+		ebasis->nrows = basis->nrows;
+		ebasis->cstat = basis->cstat;
+		ebasis->rstat = basis->rstat;
+		basis->cstat = basis->rstat = 0;
+	}
+	mpq_QSfree_basis (basis);
+	dbl_QSfree_prob (p_dbl);
+	mpf_QSfree_prob (p_mpf);
+	return rval;
+}
+
+/* ========================================================================= */
+int __QSexact_setup = 0;
+/* ========================================================================= */
+void QSexactStart(void)
+{
+	/* if we have been initialized before, do nothing */
+	if(__QSexact_setup) return;
+	/* we should call EGlpNumStart() */
+	EGlpNumStart();
+	/* now we call all setups */
+	EXutilDoInit();
+	dbl_ILLstart();
+	mpf_ILLstart();
+	mpq_ILLstart();
+	/* ending */
+	__QSexact_setup = 1;
+}
+/* ========================================================================= */
+void QSexactClear(void)
+{
+	if(!__QSexact_setup) return;
+	/* now we call all ends */
+	dbl_ILLend();
+	mpf_ILLend();
+	mpq_ILLend();
+	EXutilDoClear();
+	/* ending */
+	EGlpNumClear();
+	__QSexact_setup = 0;
+}
+/* ========================================================================= */
+/** @} */
+/* end of exact.c */
+
diff --git a/qsopt_ex/exact.h b/qsopt_ex/exact.h
new file mode 100644
index 0000000..b47f72b
--- /dev/null
+++ b/qsopt_ex/exact.h
@@ -0,0 +1,361 @@
+/* ========================================================================= */
+/* ESolver "Exact Mixed Integer Linear Solver" provides some basic structures
+ * and algorithms commons in solving MIP's
+ *
+ * Copyright (C) 2005 Daniel Espinoza.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library 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 Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * */
+/* ========================================================================= */
+#ifndef __EXACT_H__
+#define __EXACT_H__
+
+#include <gmp.h>
+
+#include "basicdefs.h"
+#include "eg_io.h"
+#include "eg_lpnum.h"
+#include "eg_lpnum.dbl.h"
+#include "eg_lpnum.mpq.h"
+#include "eg_lpnum.mpf.h"
+#include "lpdata_dbl.h"
+#include "lpdata_mpq.h"
+#include "lpdata_mpf.h"
+#include "qsopt_mpf.h" /* mpf_QSset_precision */
+#include "qstruct_dbl.h"
+#include "qstruct_mpq.h"
+#include "qstruct_mpf.h"
+
+/* ========================================================================= */
+/** @defgroup Esolver Esolver
+ * Here we define an interface to solve LP's (#QSexact_solver) and MIP's 
+ * exactly. 
+ * @par History:
+ * Revision 0.1
+ * - 2005-11-14
+ * 						- Fix handling of infeasibility testing, the problem is that
+ * 						sometimes, the QSget_infeas_array only work after calling primal
+ * 						simplex, so, if we are doing dual, ans finish with infeasibility
+ * 						status, the call will fail, the fix is to call primal simples on
+ * 						those cases before calling the infeasibility proof.
+ * - 2005-10-05
+ * 						- If one of the floating point approximations fail, keep going
+ * 						to the next floating point approximation. A floating point
+ * 						approximation may fail because the basis is singular within the
+ * 						used precision.
+ * - 2005-09-29
+ * 						- If the plain double approximation return unbounded we re-try
+ * 						in extended precision, but when the extended precision LP solver
+ * 						return with QS_LP_UNBOUNDED status, we just give-up and return
+ * 						QS_LP_UNBOUNDED status.
+ * - 2005-08-17
+ * 						- Improve reliability of optimality test.
+ * - 2005-07-07
+ * 						- Load optimal soplution into the cache.
+ * 						- Change the behavior of QSopt, when he wants to re-start simplex,
+ * 							we instead increase the precision of the numbers, this behavior
+ * 							is managed by DO_NUMER and DO_SINGULAR.
+ * - 2005-05-31
+ * 						- If the status of the ending call is not optimal, we don't load
+ * 						the previous basis, this is because in some examples doing so lead
+ * 						to bad behavior of the overall code.
+ * - 2005-05-11
+ * 						- First definition and implementation
+ *
+ * */
+/** @file
+ * @ingroup Esolver */
+/** @addtogroup Esolver */
+/** @{ */
+/* ========================================================================= */
+
+/* ========================================================================= */
+/** @brief If enabled, save the last problem proved to be optimal, and its
+ * solution. */
+#define QSEXACT_SAVE_OPTIMAL 0
+
+/* ========================================================================= */
+/** @brief If enabled, save the intermediate problems created by the functions
+ * #QScopy_prob_mpq_dbl and #QScopy_prob_mpq_mpf */
+#define QSEXACT_SAVE_INT 0
+
+/* ========================================================================= */
+/** @brief Copy an exact problem (mpq_QSdata) to a regular double version of the
+ * problem (dbl_QSdata) */
+dbl_QSdata *QScopy_prob_mpq_dbl (mpq_QSdata * p,
+																 const char *newname);
+
+/* ========================================================================= */
+/** @brief Copy an exact problem (mpq_QSdata) to a regular double version of the
+ * problem (dbl_QSdata) */
+mpf_QSdata *QScopy_prob_mpq_mpf (mpq_QSdata * p,
+																 const char *newname);
+
+/* ========================================================================= */
+/** @brief Test if a given primal/dual solution is feasible and has the same
+ * objective value.
+ * @param p original problem.
+ * @param p_sol primal solution candidate.
+ * @param d_sol dual solution candidate.
+ * @param basis Basis for wich the current primal/dual vector is a solution.
+ * @return one if the given primal/dual solution is optimal, zero otherwise. 
+ * @par Description:
+ * The input problem has the form \f[ \begin{array}{l}\min cx\\
+  s.t. \begin{array}{lcl}Ax&=&b\end{array}\\
+  l\leq x\leq u\end{array} \f]
+ * where some of the bounds can be \f$\infty\f$ or \f$-\infty\f$. Note that from
+ * this the dual problem is allways feasible (we treat \f$\infty\f$ as a
+ * suitable large number) because it looks like 
+ * \f[ \begin{array}{l}\max by + d_uu-d_ll\\
+  s.t. \begin{array}{lcl}A^ty-Id_l+Id_u & =& c \end{array}\\
+  d_u,d_l\geq0\end{array} \f] thus we just need to check primal 
+ * feasibility and complementary slackness (just to be sure we also check that
+ * both dual and primal objective values coincide.
+ *
+ * If the optimality test is true (i.e. the basis and the given solution, wich
+ * might have been modified inside the function) then this function store the
+ * optimal solution into the cache of the problem.
+ *
+ * @note We assume that p_sol and d_sol have the right size for the problem. and
+ * moreover, we assume that the problem already has the logical variables added
+ * in (to transform it into standard form), this allow us to fix somewhat the
+ * primal vector solution to try to get an optimality certificate.
+ * */
+int QSexact_optimal_test (mpq_QSdata * p,
+													mpq_t * p_sol,
+													mpq_t * d_sol,
+													QSbasis * basis);
+
+/* ========================================================================= */
+/** @brief Print into a file the optimal solution.
+ * @param p original problem.
+ * @param out_f file where to write the solution.
+ * @return zero on success, non-zero otherwise.
+ * */
+int QSexact_print_sol (mpq_QSdata * p,
+											 EGioFile_t * out_f);
+
+/* ========================================================================= */
+/** @brief Check if the given dual vector is a proof of infeasibility for the
+ * given exact problem. 
+ * @param p pointer to the problem data structure.
+ * @param d_sol array of length at least nrows with the suposed proof of
+ * infeasibility.
+ * @return zero if the given dual vector is indeed a proof of infeasibility for
+ * the problem, non zero otherwise.
+ * @par Description:
+ * Note that for infeasibility, we just need to proof that the problem 
+ \f[ \begin{array}{ll} \min & 0\\ s.t. & Ax = b\\ & l\leq x\leq b\\ 
+ \end{array} \f]
+ * is infeasible, but it's dual is
+ \f[ \begin{array}{ll} \max & by - ud_u + ld_l\\ s.t. & A^ty +Id_l - Id_u = 0\\ 
+ & d_u,d_l\geq0\\ \end{array} \f]
+ * wich is always feasible (provided \f$y\geq0\f$ (set \f$ (y,d_u,d_l)=0\f$), 
+ * and thus we just need to check whether the objective value is \f$\neq 0\f$ 
+ * and we have a proof of infeasibility for the primal. That's what this 
+ * function perform as a test.
+ * */
+int QSexact_infeasible_test (mpq_QSdata * p,
+														 mpq_t * d_sol);
+
+/* ========================================================================= */
+/** @brief create a copy of a mpq_t array into a double array.
+ * @param array mpq_t array from where we will create the values. */
+#define QScopy_array_mpq_dbl(array) ({ \
+	mpq_t*__larray = (array);\
+	register unsigned __lsz = __EGlpNumArraySize(__larray);\
+	double*__lres = dbl_EGlpNumAllocArray(__lsz);\
+	while(__lsz--)\
+	{\
+		if(mpq_equal(__larray[__lsz],mpq_ILL_MAXDOUBLE))\
+			__lres[__lsz] = dbl_ILL_MAXDOUBLE;\
+		else if(mpq_equal(__larray[__lsz],mpq_ILL_MINDOUBLE))\
+			__lres[__lsz] = dbl_ILL_MINDOUBLE;\
+		else __lres[__lsz] = mpq_get_d(__larray[__lsz]);\
+	}\
+	__lres;})
+
+/* ========================================================================= */
+/** @brief create a copy of a mpq_t array into a mpf_t array.
+ * @param array mpq_t array from where we will create the values. */
+#define QScopy_array_mpq_mpf(array) ({ \
+	mpq_t*__larray = (array);\
+	register unsigned __lsz = __EGlpNumArraySize(__larray);\
+	mpf_t*__lres = mpf_EGlpNumAllocArray(__lsz);\
+	while(__lsz--)\
+	{\
+		if(mpq_equal(__larray[__lsz],mpq_ILL_MAXDOUBLE))\
+			mpf_set(__lres[__lsz], mpf_ILL_MAXDOUBLE);\
+		else if(mpq_equal(__larray[__lsz],mpq_ILL_MINDOUBLE))\
+			mpf_set(__lres[__lsz], mpf_ILL_MINDOUBLE);\
+		else mpf_set_q(__lres[__lsz],__larray[__lsz]);\
+	}\
+	__lres;})
+
+/* ========================================================================= */
+/** @brief create a copy of a double array into mpq_t array.
+ * @param array original array of double values (note that this array must have
+ * been allocated with dbl_EGlpNumAllocArray for this function to work). */
+#define QScopy_array_dbl_mpq(array) ({ \
+	double*__larray = (array);\
+	register unsigned __lsz = __EGlpNumArraySize(__larray);\
+	mpq_t*__lres = mpq_EGlpNumAllocArray(__lsz);\
+	while(__lsz--)\
+	{\
+		if(__larray[__lsz] == dbl_ILL_MAXDOUBLE)\
+			mpq_set(__lres[__lsz],mpq_ILL_MAXDOUBLE);\
+		else if(__larray[__lsz] == dbl_ILL_MINDOUBLE)\
+			mpq_set(__lres[__lsz],mpq_ILL_MINDOUBLE);\
+		else mpq_EGlpNumSet(__lres[__lsz],__larray[__lsz]);\
+	}\
+	__lres;})
+
+/* ========================================================================= */
+/** @brief create a copy of a mpf_t array into mpq_t array.
+ * @param array original array of double values (note that this array must have
+ * been allocated with __EGlpNumAllocArray for this function to work). */
+#define QScopy_array_mpf_mpq(array) ({ \
+	mpf_t*__larray = (array);\
+	register unsigned __lsz = __EGlpNumArraySize(__larray);\
+	mpq_t*__lres = mpq_EGlpNumAllocArray(__lsz);\
+	while(__lsz--)\
+	{\
+		if(mpf_cmp(__larray[__lsz],mpf_ILL_MAXDOUBLE)==0)\
+			mpq_set(__lres[__lsz],mpq_ILL_MAXDOUBLE);\
+		else if(mpf_cmp(__larray[__lsz],mpf_ILL_MINDOUBLE)==0)\
+			mpq_set(__lres[__lsz],mpq_ILL_MINDOUBLE);\
+		mpq_set_f(__lres[__lsz],__larray[__lsz]);\
+	}\
+	__lres;})
+
+/* ========================================================================= */
+/** @brief Write a given row from the LP into the given stream, in exact
+ * arithmetic */
+void QSexact_write_row (EGioFile_t * out_f,
+												mpq_ILLlpdata * lp,
+												int row);
+
+/* ========================================================================= */
+/** @brief Set the number of bits to use with mpf_t type numbers and change all
+ * internal constants as needed. */
+#define QSexact_set_precision(precision) mpf_QSset_precision(precision)
+
+#ifndef QS_EXACT_MAX_ITER
+/* ========================================================================= */
+/** @brief This constant define the maximum number of try's for the exact solver
+ * with mpf_t numbers while incrementing the precision */
+#define QS_EXACT_MAX_ITER 12
+#endif
+
+/* ========================================================================= */
+/** @brief test whether given basis is primal and dual feasible in rational arithmetic. 
+ * @param p_mpq   the problem data.
+ * @param basis   basis to be tested.
+ * @param result  where to store whether given basis is primal and dual feasible.
+ * @param msg_lvl message level.
+ */
+int QSexact_basis_optimalstatus(
+   mpq_QSdata * p_mpq,
+   QSbasis* basis,
+   char* result,
+   const int msg_lvl
+   );
+
+/* ========================================================================= */
+/** @brief test whether given basis is dual feasible in rational arithmetic. 
+ * @param p_mpq   the problem data.
+ * @param basis   basis to be tested.
+ * @param result  where to store whether given basis is dual feasible.
+ * @param dobjval where to store dual solution value in case of dual feasibility (if not NULL).
+ * @param msg_lvl message level.
+ */
+int QSexact_basis_dualstatus(
+   mpq_QSdata * p_mpq,
+   QSbasis* basis,
+   char* result,
+   mpq_t* dobjval,
+   const int msg_lvl
+   );
+
+/* ========================================================================= */
+/** @brief test whether given basis is dual feasible in rational arithmetic. 
+ * if wanted it will first directly test the corresponding approximate dual and primal solution 
+ * (corrected via dual variables for bounds and primal variables for slacks if possible) for optimality
+ * before performing the dual feasibility test on the more expensive exact basic solution. 
+ * @param p_mpq   the problem data.
+ * @param basis   basis to be tested.
+ * @param useprestep whether to directly test approximate primal and dual solution first.
+ * @param dbl_p_sol  approximate primal solution to use in prestep 
+ *                   (NULL in order to compute it by dual simplex in double precision with given starting basis).
+ * @param dbl_d_sol  approximate dual solution to use in prestep 
+ *                   (NULL in order to compute it by dual simplex in double precision with given starting basis).
+ * @param result  where to store whether given basis is dual feasible.
+ * @param dobjval where to store dual solution value in case of dual feasibility (if not NULL).
+ * @param msg_lvl message level.
+ */
+int QSexact_verify (
+   mpq_QSdata * p_mpq,
+   QSbasis* basis,
+   int useprestep,
+   double* dbl_p_sol,
+   double* dbl_d_sol,
+   char* result,
+   mpq_t* dobjval,
+   const int msg_lvl
+   );
+
+/* ========================================================================= */
+/** @brief Given an mpq_QSdata problem, solve it exactly.
+ * @param x if not null, we store here the primal solution to the 
+ * problem (if it exist).
+ * @param y if not null, we store here the dual solution to the
+ * problem, 
+ * @param p_mpq problem to solve exactly.
+ * @param status pointer to the integer where we will return the status
+ * of the problem, either optimal, infeasible, or unbounded (we could also 
+ * return time out).
+ * @param simplexalgo whether to use primal or dual simplex while solving
+ * to optimality the problem.
+ * @param basis if not null, use the given basis to start the
+ * iteration of simplex, and store here the optimal basis (if found).
+ * @return zero on success, non-zero otherwise. */
+int QSexact_solver (mpq_QSdata * p_mpq,
+										mpq_t * const x,
+										mpq_t * const y,
+										QSbasis * const basis,
+										int simplexalgo,
+										int *status);
+
+/* ========================================================================= */
+/** @brief Initializator for global data, this is needed mainly for defining
+ * constants in extended floating point precision and for rational precision.
+ * This call should be done BEFORE any mpq_xxx mpf_xxx QSxx EGxx call */
+extern void QSexactStart(void);
+/* ========================================================================= */
+/** @brief This function must be called at the end of the program to free all
+ * internal data used in the QSexact structures, once this function is called
+ * any operation on EGxxx mpq_xxx mpf_xx QSxx may fail.
+ * */
+extern void QSexactClear(void);
+/* ========================================================================= */
+/** @brief indicate if the global data needed for QSexact has been initialized,
+ * if zero, initialization routine should be called. This is provided to allow
+ * syncronization between libraries */
+extern int __QSexact_setup;
+/** @} */
+/* ========================================================================= */
+/* end of exact.h */
+#endif
+
diff --git a/qsopt_ex/except.c b/qsopt_ex/except.c
new file mode 100644
index 0000000..9f33732
--- /dev/null
+++ b/qsopt_ex/except.c
@@ -0,0 +1,54 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCSINFO $Id: exception.c,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+#include <stdio.h>
+#include <string.h>
+
+#include "except.h"
+
+#include "logging-private.h"
+
+
+void ILL_report (
+	const char *msg,
+	const char *fct,
+	const char *file,
+	unsigned int line,
+	int with_src_info)
+{
+	if (msg != NULL)
+	{
+		QSlog("FAILURE: %s", msg);
+		if (with_src_info == 1)
+		{
+			if (fct != NULL)
+			{
+				QSlog("\tin function %s", fct);
+			}
+			QSlog("\tin file %s line %d", file, line);
+		}
+	}
+}
+
+/* by default we turn off verbose messages of singular basis */
+int __QS_SB_VERB = 1000;
diff --git a/qsopt_ex/except.h b/qsopt_ex/except.h
new file mode 100644
index 0000000..138371c
--- /dev/null
+++ b/qsopt_ex/except.h
@@ -0,0 +1,170 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCSINFO $Id: except.h,v 1.3 2003/11/05 17:02:10 meven Exp $ */
+#ifndef ILL_except
+#define ILL_except
+
+#include "allocrus.h"
+#include "trace.h"
+
+/* Version 2.4 and later of GCC define a magical variable `__PRETTY_FUNCTION__'
+   which contains the name of the function currently being defined.
+#  define __DEV_FUNCTION__     __PRETTY_FUNCTION__
+   This is broken in G++ before version 2.6.
+   C9x has a similar variable called __func__, but prefer the GCC one since
+   it demangles C++ function names.  */
+# ifdef __GNUC__
+#  if __GNUC__ > 2 || (__GNUC__ == 2 \
+                       && __GNUC_MINOR__ >= (defined __cplusplus ? 6 : 4))
+#   define __DEV_FUNCTION__    __PRETTY_FUNCTION__
+#  else
+#   define __DEV_FUNCTION__    ((__const char *) 0)
+#  endif
+# else
+#  if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
+#   define __DEV_FUNCTION__    __func__
+#  else
+#   define __DEV_FUNCTION__    ((const char *) 0)
+#  endif
+# endif
+
+
+/* put debugger breakpoint here */
+extern void ILL_report (
+	const char *msg,
+	const char *fct,
+	const char *file,
+	unsigned int line,
+	int with_source_info);
+
+/* printed message looks as follows
+ *
+ * with_source_info == 0:   <msg> + "\n"
+ *
+ * with_source_info == 1:   if (fct != NULL) 
+ *                              <msg> + " in function <fct>\n";
+ *                          else 
+ *                              <msg> + " in file <file> line <line>\n"; 
+ */
+
+#define ILL_GENERAL_ERROR -1
+#define ILL_NO_MEMORY 2
+#define ILL_NULL_PTR  3
+
+#define ILL_REPORT(msg,with) \
+    ILL_report(msg, __DEV_FUNCTION__, __FILE__, __LINE__, with)
+#ifdef NDEBUG
+#define ILL_REPRT(msg) \
+    ILL_report(msg, __DEV_FUNCTION__, __FILE__, __LINE__, 0)
+#else
+#define ILL_REPRT(msg) \
+    ILL_report(msg, __DEV_FUNCTION__, __FILE__, __LINE__, 1)
+#endif
+
+#define ILL_RESULT(expr, msg) \
+{								\
+	if (TRACE > 0) { ILL_RETURN(expr, msg); } \
+    return expr; \
+}
+
+#define ILL_RETURN_PTR(ptr, msg) \
+    { void *ILL_RETURN_p = ptr; \
+      if (ILL_RETURN_p == NULL) {  \
+        if (TRACE > 0) ILL_REPRT(msg); \
+      } \
+      return ILL_RETURN_p;  \
+    }
+
+#ifdef NDEBUG
+#define ILL_RETURN(expr, msg)           \
+{										\
+	if (expr != 0) {					\
+			if (TRACE > 0) ILL_REPRT(msg); \
+    }									\
+    return expr;						\
+}
+
+#else
+#define ILL_RETURN(expr, msg)           \
+	{									\
+		if (expr != 0) {                \
+			ILL_REPRT(msg);             \
+		}                               \
+		ILL_IFTRACE("%s: returning %d\n", __DEV_FUNCTION__, expr); \
+		return expr;					\
+	}
+#endif
+
+#define ILL_CHECKnull(expr, msg) \
+    { if ((expr) == NULL)  {  \
+         ILL_REPRT(msg); \
+         rval = ILL_NULL_PTR; \
+         goto CLEANUP;  \
+      } }
+
+#define ILL_FAILtrue(expr, msg) \
+    { if (expr)  {  \
+         ILL_REPRT(msg); \
+         rval = ILL_GENERAL_ERROR; \
+         goto CLEANUP;  \
+      } }
+
+#define ILL_FAILtrue_no_rval(expr, msg) \
+    { if (expr)  {  \
+         ILL_REPRT(msg); \
+         goto CLEANUP;  \
+      } }
+
+
+#define ILL_FAILfalse(expr, msg)  ILL_FAILtrue(!(expr), msg)
+#define ILL_FAILfalse_no_rval(expr, msg)  ILL_FAILtrue_no_rval(!(expr), msg)
+
+#define ILL_ERROR(rval, msg)      {									\
+									fprintf(stderr, "%s\n", msg);	\
+									rval = 1; goto CLEANUP;			\
+								  }
+#define ILL_CLEANUP_IF(rval)      { if ((rval) != 0) { goto CLEANUP; } }
+#define ILL_CLEANUP               goto CLEANUP
+
+#define ILL_SAFE_MALLOC(lhs, n, type) \
+    { lhs = ILL_UTIL_SAFE_MALLOC(n, type, lhs); \
+      if (lhs == NULL)  {  \
+         ILL_REPRT("Out of memory"); \
+         rval = ILL_NO_MEMORY; \
+         goto CLEANUP;  \
+      }}
+
+#define ILL_SAFE_MALLOC_no_rval(lhs, n, type) \
+    { lhs = ILL_UTIL_SAFE_MALLOC(n, type, lhs); \
+      if (lhs == NULL)  {  \
+         ILL_REPRT("Out of memory"); \
+         goto CLEANUP;  \
+      }}
+
+
+#define ILL_NEW(ptr, type) ILL_SAFE_MALLOC(ptr, 1, type)
+#define ILL_NEW_no_rval(ptr, type) ILL_SAFE_MALLOC_no_rval(ptr, 1, type)
+
+/* we define debugging verbosity for singular basis */
+extern int __QS_SB_VERB;
+#endif
diff --git a/qsopt_ex/factor.c b/qsopt_ex/factor.c
new file mode 100644
index 0000000..98f1473
--- /dev/null
+++ b/qsopt_ex/factor.c
@@ -0,0 +1,5602 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: factor.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+//static int TRACE = 0;
+
+/* implement a = max(a,abs(b)) and execute the extra code if the update is
+ * needed */
+#define EGlpNumSetToMaxAbsAndDo(a,b,c) \
+	if(EGLPNUM_TYPENAME_EGlpNumIsGreatZero(b))\
+	{\
+		if(EGLPNUM_TYPENAME_EGlpNumIsLess(a,b)){\
+			EGLPNUM_TYPENAME_EGlpNumCopy(a,b);\
+			c;\
+			}\
+	}\
+	else\
+	{\
+		EGLPNUM_TYPENAME_EGlpNumSign(a);\
+		if(EGLPNUM_TYPENAME_EGlpNumIsLess(b,a)){\
+			EGLPNUM_TYPENAME_EGlpNumCopy(a,b);\
+			c;\
+			}\
+		EGLPNUM_TYPENAME_EGlpNumSign(a);\
+	}
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "logging-private.h"
+
+#include "allocrus.h"
+#include "eg_lpnum.h"
+#include "eg_numutil_EGLPNUM_TYPENAME.h"
+#include "eg_io.h"
+#include "except.h"
+#include "util.h"
+
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+#include "factor_EGLPNUM_TYPENAME.h"
+
+
+#undef  RECORD
+#undef  DEBUG_FACTOR
+#undef  SOLVE_DEBUG
+
+#undef  FACTOR_DEBUG
+#undef  UPDATE_DEBUG
+
+#undef TRACK_FACTOR
+#undef NOTICE_BLOWUP
+
+#undef  FACTOR_STATS
+#undef  UPDATE_STATS
+#undef  GROWTH_STATS
+
+#undef  UPDATE_STUDY
+
+#undef  SORT_RESULTS
+
+#ifdef UPDATE_STUDY
+int nupdate = 0;
+long int colspiketot = 0.0;
+long int rowspiketot = 0.0;
+long int permshifttot = 0.0;
+long int leftetatot = 0.0;
+#endif
+
+void EGLPNUM_TYPENAME_ILLfactor_init_factor_work (
+	EGLPNUM_TYPENAME_factor_work * f)
+{
+	f->max_k = 1000;							/* must be less than 46340 (2^15.5) */
+	EGLPNUM_TYPENAME_EGlpNumCopy (f->fzero_tol, EGLPNUM_TYPENAME_SZERO_TOLER);	/* 2^-50 */
+	EGLPNUM_TYPENAME_EGlpNumCopy (f->szero_tol, EGLPNUM_TYPENAME_SZERO_TOLER);	/* 2^-50 */
+	EGLPNUM_TYPENAME_EGlpNumCopy (f->partial_tol, EGLPNUM_TYPENAME_OBJBND_TOLER);	/* 2^-7 */
+	f->ur_space_mul = 2.0;
+	f->uc_space_mul = 1.1;
+	f->lc_space_mul = 1.1;
+	f->er_space_mul = 1000.0;
+	f->grow_mul = 1.5;
+	f->p = 4;
+	f->etamax = 100;
+	f->minmult = 1e3;
+	f->maxmult = 1e5;
+	f->updmaxmult = 1e7;
+	f->dense_fract = 0.25;
+	f->dense_min = 25;
+	EGLPNUM_TYPENAME_EGlpNumCopy (f->partial_cur, f->partial_tol);
+	f->work_coef = 0;
+	f->work_indx = 0;
+	f->uc_inf = 0;
+	f->ur_inf = 0;
+	f->lc_inf = 0;
+	f->lr_inf = 0;
+	f->er_inf = 0;
+	f->ucindx = 0;
+	f->ucrind = 0;
+	f->uccoef = 0;
+	f->urindx = 0;
+	f->urcind = 0;
+	f->urcoef = 0;
+	f->lcindx = 0;
+	f->lccoef = 0;
+	f->lrindx = 0;
+	f->lrcoef = 0;
+	f->erindx = 0;
+	f->ercoef = 0;
+	f->rperm = 0;
+	f->rrank = 0;
+	f->cperm = 0;
+	f->crank = 0;
+	f->dmat = 0;
+	EGLPNUM_TYPENAME_ILLsvector_init (&f->xtmp);
+}
+
+void EGLPNUM_TYPENAME_ILLfactor_free_factor_work (
+	EGLPNUM_TYPENAME_factor_work * f)
+{
+#ifdef UPDATE_STUDY
+	if (nupdate)
+	{
+		MESSAGE(0, "UPDATE STUDY: avg %d upd: %.2f col, %.2f row, %.2f lefteta, "
+						"%.2f perm", nupdate, ((double) colspiketot) / nupdate, 
+						((double) rowspiketot) / nupdate, ((double) leftetatot) / nupdate,
+						((double) permshifttot) / nupdate);
+	}
+#endif
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (f->work_coef);
+	ILL_IFFREE (f->work_indx, int);
+
+	ILL_IFFREE (f->uc_inf, EGLPNUM_TYPENAME_uc_info);
+	if (f->dim + f->max_k > 0 && f->ur_inf)
+	{
+		unsigned int i = f->dim + f->max_k + 1;
+
+		while (i--)
+			EGLPNUM_TYPENAME_EGlpNumClearVar (f->ur_inf[i].max);
+	}
+	ILL_IFFREE (f->ur_inf, EGLPNUM_TYPENAME_ur_info);
+	ILL_IFFREE (f->lc_inf, EGLPNUM_TYPENAME_lc_info);
+	ILL_IFFREE (f->lr_inf, EGLPNUM_TYPENAME_lr_info);
+	ILL_IFFREE (f->er_inf, EGLPNUM_TYPENAME_er_info);
+	ILL_IFFREE (f->ucindx, int);
+	ILL_IFFREE (f->ucrind, int);
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (f->uccoef);
+	ILL_IFFREE (f->urindx, int);
+	ILL_IFFREE (f->urcind, int);
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (f->urcoef);
+	ILL_IFFREE (f->lcindx, int);
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (f->lccoef);
+	ILL_IFFREE (f->lrindx, int);
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (f->lrcoef);
+	ILL_IFFREE (f->erindx, int);
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (f->ercoef);
+	ILL_IFFREE (f->rperm, int);
+	ILL_IFFREE (f->rrank, int);
+	ILL_IFFREE (f->cperm, int);
+	ILL_IFFREE (f->crank, int);
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (f->dmat);
+	EGLPNUM_TYPENAME_ILLsvector_free (&f->xtmp);
+}
+
+int EGLPNUM_TYPENAME_ILLfactor_set_factor_iparam (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int param,
+	int val)
+{
+	switch (param)
+	{
+	case QS_FACTOR_MAX_K:
+		f->max_k = val;
+		break;
+	case QS_FACTOR_P:
+		f->p = val;
+		break;
+	case QS_FACTOR_ETAMAX:
+		f->etamax = val;
+		break;
+	case QS_FACTOR_DENSE_MIN:
+		f->dense_min = val;
+		break;
+	default:
+		QSlog("Invalid param %d in EGLPNUM_TYPENAME_ILLfactor_set_factor_iparam",
+								param);
+		return 1;
+	}
+	return 0;
+}
+
+int EGLPNUM_TYPENAME_ILLfactor_set_factor_dparam (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int param,
+	EGLPNUM_TYPE val)
+{
+	switch (param)
+	{
+	case QS_FACTOR_FZERO_TOL:
+		EGLPNUM_TYPENAME_EGlpNumCopy (f->fzero_tol, val);
+		break;
+	case QS_FACTOR_SZERO_TOL:
+		EGLPNUM_TYPENAME_EGlpNumCopy (f->szero_tol, val);
+		break;
+	case QS_FACTOR_UR_SPACE_MUL:
+		f->ur_space_mul = EGLPNUM_TYPENAME_EGlpNumToLf (val);
+		break;
+	case QS_FACTOR_UC_SPACE_MUL:
+		f->uc_space_mul = EGLPNUM_TYPENAME_EGlpNumToLf (val);
+		break;
+	case QS_FACTOR_LC_SPACE_MUL:
+		f->lc_space_mul = EGLPNUM_TYPENAME_EGlpNumToLf (val);
+		break;
+	case QS_FACTOR_LR_SPACE_MUL:
+		f->lr_space_mul = EGLPNUM_TYPENAME_EGlpNumToLf (val);
+		break;
+	case QS_FACTOR_ER_SPACE_MUL:
+		f->er_space_mul = EGLPNUM_TYPENAME_EGlpNumToLf (val);
+		break;
+	case QS_FACTOR_GROW_MUL:
+		f->grow_mul = EGLPNUM_TYPENAME_EGlpNumToLf (val);
+		break;
+	case QS_FACTOR_MAXMULT:
+		f->maxmult = EGLPNUM_TYPENAME_EGlpNumToLf (val);
+		break;
+	case QS_FACTOR_UPDMAXMULT:
+		f->updmaxmult = EGLPNUM_TYPENAME_EGlpNumToLf (val);
+		break;
+	case QS_FACTOR_DENSE_FRACT:
+		f->dense_fract = EGLPNUM_TYPENAME_EGlpNumToLf (val);
+		break;
+	case QS_FACTOR_PARTIAL_TOL:
+		EGLPNUM_TYPENAME_EGlpNumCopy (f->partial_tol, val);
+		EGLPNUM_TYPENAME_EGlpNumCopy (f->partial_cur, val);
+		break;
+	default:
+		QSlog("Invalid param %d in EGLPNUM_TYPENAME_ILLfactor_set_factor_dparam",
+								param);
+		return 1;
+	}
+	return 0;
+}
+
+int EGLPNUM_TYPENAME_ILLfactor_create_factor_work (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int dim)
+{
+	int i;
+	int rval;
+
+	f->dim = dim;
+	f->etacnt = 0;
+	f->work_coef = EGLPNUM_TYPENAME_EGlpNumAllocArray (dim);
+	ILL_SAFE_MALLOC (f->work_indx, dim, int);
+
+	ILL_SAFE_MALLOC (f->uc_inf, dim + (f->max_k + 1), EGLPNUM_TYPENAME_uc_info);
+	ILL_SAFE_MALLOC (f->ur_inf, dim + (f->max_k + 1), EGLPNUM_TYPENAME_ur_info);
+	ILL_SAFE_MALLOC (f->lc_inf, dim, EGLPNUM_TYPENAME_lc_info);
+	ILL_SAFE_MALLOC (f->lr_inf, dim, EGLPNUM_TYPENAME_lr_info);
+	ILL_SAFE_MALLOC (f->rperm, dim, int);
+	ILL_SAFE_MALLOC (f->rrank, dim, int);
+	ILL_SAFE_MALLOC (f->cperm, dim, int);
+	ILL_SAFE_MALLOC (f->crank, dim, int);
+
+	for (i = dim + f->max_k + 1; i--;)
+		EGLPNUM_TYPENAME_EGlpNumInitVar (f->ur_inf[i].max);
+
+	for (i = 0; i < dim; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumZero (f->work_coef[i]);
+		f->work_indx[i] = 0;
+		f->uc_inf[i].nzcnt = 0;
+		f->ur_inf[i].nzcnt = 0;
+		f->lc_inf[i].nzcnt = 0;
+		f->lr_inf[i].nzcnt = 0;
+		f->rperm[i] = i;
+		f->rrank[i] = i;
+		f->cperm[i] = i;
+		f->crank[i] = i;
+	}
+	for (i = 0; i <= f->max_k; i++)
+	{
+		f->uc_inf[dim + i].nzcnt = i;
+		f->uc_inf[dim + i].next = dim + i;
+		f->uc_inf[dim + i].prev = dim + i;
+		f->ur_inf[dim + i].nzcnt = i;
+		f->ur_inf[dim + i].next = dim + i;
+		f->ur_inf[dim + i].prev = dim + i;
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&f->xtmp, dim);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = 0;
+
+CLEANUP:
+	if (rval)
+	{
+		EGLPNUM_TYPENAME_ILLfactor_free_factor_work (f);
+	}
+	EG_RETURN (rval);
+}
+#ifdef FACTOR_DEBUG
+static void dump_matrix (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int remaining)
+{
+	int dim = f->dim;
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+	EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+	EGLPNUM_TYPENAME_lc_info *lc_inf = f->lc_inf;
+	EGLPNUM_TYPENAME_lr_info *lr_inf = f->lr_inf;
+	EGLPNUM_TYPENAME_er_info *er_inf = f->er_inf;
+	int nzcnt;
+	int beg;
+
+	int i;
+	int j;
+
+	for (i = 0; i < dim; i++)
+	{
+		if (!remaining || ur_inf[i].next >= 0)
+		{
+			QSlog("Row %d %d (max %.3f):", i, f->rrank[i],
+									EGLPNUM_TYPENAME_EGlpNumToLf (ur_inf[i].max));
+			nzcnt = ur_inf[i].nzcnt;
+			beg = ur_inf[i].rbeg;
+			for (j = 0; j < nzcnt; j++)
+			{
+				if (j == ur_inf[i].pivcnt)
+				{
+					QSlog(" |");
+				}
+				QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (f->urcoef[beg + j]),
+										f->urindx[beg + j]);
+				if (f->urcind)
+					QSlog("@%d", f->urcind[beg + j]);
+			}
+		}
+	}
+	if (f->dmat)
+	{
+		int start = 0;
+
+		if (remaining)
+			start = f->stage - f->dense_base;
+		QSlog("Dcols at %d %d - %d    :", f->stage - f->dense_base,
+								f->dense_base + start, f->nstages);
+		for (j = start; j < f->dcols; j++)
+		{
+			QSlog(" %5d", f->cperm[j + f->dense_base]);
+		}
+
+		for (i = start; i < f->drows; i++)
+		{
+			QSlog("DRow %d %d (max %.3f):", i,
+									f->rperm[i + f->dense_base],
+									EGLPNUM_TYPENAME_EGlpNumToLf (ur_inf[f->rperm[i + f->dense_base]].max));
+			for (j = start; j < f->dcols; j++)
+			{
+				if (j == f->drows)
+				{
+					QSlog(" |");
+				}
+				QSlog(" %.3f", EGLPNUM_TYPENAME_EGlpNumToLf (f->dmat[i * f->dcols + j]));
+			}
+		}
+	}
+
+	if (!remaining)
+	{
+		for (i = 0; i < f->stage; i++)
+		{
+			QSlog("L col %d:", lc_inf[i].c);
+			nzcnt = lc_inf[i].nzcnt;
+			beg = lc_inf[i].cbeg;
+			for (j = 0; j < nzcnt; j++)
+			{
+				QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (f->lccoef[beg + j]),
+										f->lcindx[beg + j]);
+			}
+		}
+		for (i = f->nstages; i < f->dim; i++)
+		{
+			QSlog("L col %d:", lc_inf[i].c);
+			nzcnt = lc_inf[i].nzcnt;
+			beg = lc_inf[i].cbeg;
+			for (j = 0; j < nzcnt; j++)
+			{
+				QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (f->lccoef[beg + j]),
+										f->lcindx[beg + j]);
+			}
+		}
+		for (i = 0; i < f->dim; i++)
+		{
+			if (!lr_inf[i].nzcnt)
+				continue;
+			QSlog("L row %d:", lr_inf[i].r);
+			nzcnt = lr_inf[i].nzcnt;
+			beg = lr_inf[i].rbeg;
+			for (j = 0; j < nzcnt; j++)
+			{
+				QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (f->lrcoef[beg + j]),
+										f->lrindx[beg + j]);
+			}
+		}
+	}
+
+	if (!remaining)
+	{
+		for (i = 0; i < f->etacnt; i++)
+		{
+			QSlog("Eta row %d:", f->er_inf[i].r);
+			nzcnt = er_inf[i].nzcnt;
+			beg = er_inf[i].rbeg;
+			for (j = 0; j < nzcnt; j++)
+			{
+				QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (f->ercoef[beg + j]),
+										f->erindx[beg + j]);
+			}
+		}
+	}
+
+	for (i = 0; i < dim; i++)
+	{
+		if (!remaining || uc_inf[i].next >= 0)
+		{
+			QSlog("Col %d %d:", i, f->crank[i]);
+			nzcnt = uc_inf[i].nzcnt;
+			beg = uc_inf[i].cbeg;
+			for (j = 0; j < nzcnt; j++)
+			{
+				if (f->uccoef != 0)
+				{
+					QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (f->uccoef[beg + j]),
+											f->ucindx[beg + j]);
+					if (f->ucrind)
+						QSlog("@%d", f->ucrind[beg + j]);
+				}
+				else
+				{
+					QSlog(" %d", f->ucindx[beg + j]);
+				}
+			}
+		}
+	}
+
+	if (!remaining)
+	{
+		QSlog("rperm:");
+		for (i = 0; i < dim; i++)
+		{
+			if (i == f->nstages)
+				QSlog("|");
+			if (i == f->stage)
+				QSlog("|");
+			QSlog(" %d", f->rperm[i]);
+		}
+
+		QSlog("cperm:");
+		for (i = 0; i < dim; i++)
+		{
+			if (i == f->nstages)
+				QSlog("|");
+			if (i == f->stage)
+				QSlog("|");
+			QSlog(" %d", f->cperm[i]);
+		}
+	}
+
+	QSlog("Rows by nzcnt:");
+	for (i = 0; i <= f->max_k; i++)
+	{
+		if (ur_inf[dim + i].next != dim + i)
+		{
+			QSlog("%d:", i);
+			for (j = ur_inf[dim + i].next; j != dim + i; j = ur_inf[j].next)
+			{
+				QSlog(" %d", j);
+			}
+		}
+	}
+
+	QSlog("Cols by nzcnt:\n");
+	for (i = 0; i <= f->max_k; i++)
+	{
+		if (uc_inf[dim + i].next != dim + i)
+		{
+			QSlog("%d:", i);
+			for (j = uc_inf[dim + i].next; j != dim + i; j = uc_inf[j].next)
+			{
+				QSlog(" %d", j);
+			}
+		}
+	}
+}
+#endif
+
+#ifdef SORT_RESULTS
+static void sort_vector2 (
+	int nzcnt,
+	int *indx,
+	EGLPNUM_TYPE * coef)
+{
+	int i;
+	int j;
+	int itmp;
+	EGLPNUM_TYPE ctmp;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (ctmp);
+
+	for (i = 1; i < nzcnt; i++)
+	{
+		itmp = indx[i];
+		EGLPNUM_TYPENAME_EGlpNumCopy (ctmp, coef[i]);
+		for (j = i; j >= 1 && indx[j - 1] > itmp; j--)
+		{
+			indx[j] = indx[j - 1];
+			EGLPNUM_TYPENAME_EGlpNumCopy (coef[j], coef[j - 1]);
+		}
+		indx[j] = itmp;
+		EGLPNUM_TYPENAME_EGlpNumCopy (coef[j], ctmp);
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (ctmp);
+}
+
+static void sort_vector (
+	EGLPNUM_TYPENAME_svector * x)
+{
+	sort_vector2 (x->nzcnt, x->indx, x->coef);
+}
+#endif
+
+#ifdef DEBUG_FACTOR
+static int check_matrix (
+	EGLPNUM_TYPENAME_factor_work * f)
+{
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+	EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+	int rbeg;
+	int nzcnt;
+	int cbeg;
+	int c;
+	int r;
+	int j;
+	int nerr = 0;
+
+	for (r = 0; r < f->dim; r++)
+	{
+		nzcnt = ur_inf[r].nzcnt;
+		rbeg = ur_inf[r].rbeg;
+		for (j = 0; j < nzcnt; j++)
+		{
+			c = f->urindx[rbeg + j];
+			cbeg = uc_inf[c].cbeg;
+			if (f->ucindx[cbeg + f->urcind[rbeg + j]] != r)
+			{
+				MESSAGE(0,"index mismatch, row %d column %d", r, c);
+				nerr++;
+			}
+			if (fabs(EGLPNUM_TYPENAME_EGlpNumToLf(f->uccoef[cbeg + f->urcind[rbeg + j]]) - EGLPNUM_TYPENAME_EGlpNumToLf(f->urcoef[rbeg + j]))>1000*EGLPNUM_TYPENAME_EGlpNumToLf(EGLPNUM_TYPENAME_epsLpNum))
+			{
+				MESSAGE(0,"coef mismatch, row %d column %d", r, c);
+				nerr++;
+			}
+		}
+	}
+	if (f->urindx[f->ur_space] != 0)
+	{
+		MESSAGE(0,"last urindx entry %d != 0", f->urindx[f->ur_space]);
+		nerr++;
+	}
+
+	for (c = 0; c < f->dim; c++)
+	{
+		nzcnt = uc_inf[c].nzcnt;
+		cbeg = uc_inf[c].cbeg;
+		for (j = 0; j < nzcnt; j++)
+		{
+			r = f->ucindx[cbeg + j];
+			rbeg = ur_inf[r].rbeg;
+			if (f->urindx[rbeg + f->ucrind[cbeg + j]] != c)
+			{
+				MESSAGE(0,"index mismatch, column %d row %d", c, r);
+				nerr++;
+			}
+			if (f->urcoef[rbeg + f->ucrind[cbeg + j]] != f->uccoef[cbeg + j])
+			{
+				MESSAGE(0,"coef mismatch, column %d row %d", c, r);
+				nerr++;
+			}
+		}
+	}
+	if (f->ucindx[f->uc_space] != 0)
+	{
+		MESSAGE(0,"last ucindx entry %d != 0", f->ucindx[f->uc_space]);
+		nerr++;
+	}
+	if (nerr)
+	{
+		dump_matrix (f, 0);
+		return E_CHECK_FAILED;
+	}
+	return 0;
+}
+#endif
+
+#ifdef FACTOR_STATS
+static void dump_factor_stats (
+	EGLPNUM_TYPENAME_factor_work * f)
+{
+	int dim = f->dim;
+	int ecnt = f->etacnt;
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+	EGLPNUM_TYPENAME_lc_info *lc_inf = f->lc_inf;
+	EGLPNUM_TYPENAME_er_info *er_inf = f->er_inf;
+	EGLPNUM_TYPE *urcoef = f->urcoef;
+	EGLPNUM_TYPE *lccoef = f->lccoef;
+	EGLPNUM_TYPE *ercoef = f->ercoef;
+	int lnzcnt = 0;
+	int unzcnt = 0;
+	int enzcnt = 0;
+	int nzcnt;
+	int beg;
+	EGLPNUM_TYPE umax;
+	EGLPNUM_TYPE lmax;
+	EGLPNUM_TYPE emax;
+	int i;
+	int j;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (umax);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (lmax);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (emax);
+	EGLPNUM_TYPENAME_EGlpNumZero (umax);
+	for (i = 0; i < dim; i++)
+	{
+		nzcnt = ur_inf[i].nzcnt;
+		beg = ur_inf[i].rbeg;
+		unzcnt += nzcnt;
+		for (j = 0; j < nzcnt; j++)
+		{
+			EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (umax, urcoef[beg + j]);
+		}
+	}
+	EGLPNUM_TYPENAME_EGlpNumZero (lmax);
+	for (i = 0; i < dim; i++)
+	{
+		nzcnt = lc_inf[i].nzcnt;
+		beg = lc_inf[i].cbeg;
+		lnzcnt += nzcnt;
+		for (j = 0; j < nzcnt; j++)
+		{
+			EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (lmax, lccoef[beg + j]);
+		}
+	}
+	EGLPNUM_TYPENAME_EGlpNumZero (emax);
+	for (i = 0; i < ecnt; i++)
+	{
+		nzcnt = er_inf[i].nzcnt;
+		beg = er_inf[i].rbeg;
+		enzcnt += nzcnt;
+		for (j = 0; j < nzcnt; j++)
+		{
+			EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (emax, ercoef[beg + j]);
+		}
+	}
+	MESSAGE(0, "factor U %d nzs %.3e max L %d nzs %.3e max E %d nzs %.3e max",
+					unzcnt, EGLPNUM_TYPENAME_EGlpNumToLf (umax), lnzcnt, EGLPNUM_TYPENAME_EGlpNumToLf (lmax), enzcnt,
+					EGLPNUM_TYPENAME_EGlpNumToLf (emax));
+	EGLPNUM_TYPENAME_EGlpNumClearVar (umax);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (lmax);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (emax);
+}
+#endif
+
+static void clear_work (
+	EGLPNUM_TYPENAME_factor_work * f)
+{
+	int i;
+	int dim = f->dim;
+	EGLPNUM_TYPE *work_coef = f->work_coef;
+
+	for (i = 0; i < dim; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumZero (work_coef[i]);
+	}
+}
+
+static void load_row (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int r)
+{
+	EGLPNUM_TYPE *prow_urcoef = f->urcoef + f->ur_inf[r].rbeg;
+	int *prow_urindx = f->urindx + f->ur_inf[r].rbeg;
+	int prow_nzcnt = f->ur_inf[r].nzcnt;
+	EGLPNUM_TYPE *work_coef = f->work_coef;
+	int *work_indx = f->work_indx;
+	int i;
+	int j;
+
+	for (i = 0; i < prow_nzcnt; i++)
+	{
+		j = prow_urindx[i];
+		EGLPNUM_TYPENAME_EGlpNumCopy (work_coef[j], prow_urcoef[i]);
+		work_indx[j] = 1;
+	}
+}
+
+static void clear_row (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int r)
+{
+	int *prow_urindx = f->urindx + f->ur_inf[r].rbeg;
+	int prow_nzcnt = f->ur_inf[r].nzcnt;
+	EGLPNUM_TYPE *work_coef = f->work_coef;
+	int *work_indx = f->work_indx;
+	int i;
+	int j;
+
+	for (i = 0; i < prow_nzcnt; i++)
+	{
+		j = prow_urindx[i];
+		EGLPNUM_TYPENAME_EGlpNumZero (work_coef[j]);
+		work_indx[j] = 0;
+	}
+}
+
+static int make_ur_space (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int space)
+{
+	EGLPNUM_TYPE *new_urcoef = 0;
+	int *new_urindx = 0;
+	int *new_urcind = 0;
+	EGLPNUM_TYPE *urcoef = f->urcoef;
+	int *urindx = f->urindx;
+	int *urcind = f->urcind;
+	int minspace;
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+	int dim = f->dim;
+	int new_nzcnt = 0, old_nzcnt;
+	int rbeg;
+	int nzcnt;
+	int i;
+	int j;
+	int rval;
+
+	minspace = f->ur_space;
+	nzcnt = space;
+	for (i = 0; i < dim; i++)
+		nzcnt += ur_inf[i].nzcnt;
+	old_nzcnt = nzcnt;
+	while (nzcnt * 2 >= minspace)
+	{
+		minspace = 1 + minspace * f->grow_mul;
+	}
+
+#ifdef GROWTH_STATS
+	QSlog("make_ur_space growing from %d to %d...", f->ur_space, minspace);
+#endif
+	new_urcoef = EGLPNUM_TYPENAME_EGlpNumAllocArray (minspace);
+	ILL_SAFE_MALLOC (new_urindx, minspace + 1, int);
+
+	if (urcind)
+	{
+		ILL_SAFE_MALLOC (new_urcind, minspace, int);
+	}
+
+	if (urcind)
+	{
+		for (j = 0; j < dim; j++)
+		{
+			rbeg = ur_inf[j].rbeg;
+			nzcnt = ur_inf[j].nzcnt;
+			ur_inf[j].rbeg = new_nzcnt;
+			for (i = 0; i < nzcnt; i++)
+			{
+				new_urindx[new_nzcnt] = urindx[rbeg + i];
+				EGLPNUM_TYPENAME_EGlpNumCopy (new_urcoef[new_nzcnt], urcoef[rbeg + i]);
+				new_urcind[new_nzcnt] = urcind[rbeg + i];
+				new_nzcnt++;
+			}
+		}
+	}
+	else
+	{
+		for (j = 0; j < dim; j++)
+		{
+			rbeg = ur_inf[j].rbeg;
+			nzcnt = ur_inf[j].nzcnt;
+			ur_inf[j].rbeg = new_nzcnt;
+			for (i = 0; i < nzcnt; i++)
+			{
+				new_urindx[new_nzcnt] = urindx[rbeg + i];
+				EGLPNUM_TYPENAME_EGlpNumCopy (new_urcoef[new_nzcnt], urcoef[rbeg + i]);
+				new_nzcnt++;
+			}
+		}
+	}
+
+	for (i = new_nzcnt; i < minspace; i++)
+	{
+		new_urindx[i] = -1;
+	}
+	new_urindx[minspace] = 0;
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (f->urcoef);
+	f->urcoef = new_urcoef;
+	new_urcoef = 0;
+
+	ILL_IFFREE (f->urindx, int);
+
+	f->urindx = new_urindx;
+	new_urindx = 0;
+
+	ILL_IFFREE (f->urcind, int);
+
+	f->urcind = new_urcind;
+	new_urcind = 0;
+
+	f->ur_freebeg = new_nzcnt;
+	f->ur_space = minspace;
+
+#ifdef GROWTH_STATS
+	MESSAGE (0,"%d/%d nonzeros", new_nzcnt, old_nzcnt);
+	dump_factor_stats (f);
+#endif
+
+	rval = 0;
+
+CLEANUP:
+	ILL_IFFREE (new_urcoef, EGLPNUM_TYPE);
+	ILL_IFFREE (new_urindx, int);
+	ILL_IFFREE (new_urcind, int);
+
+	EG_RETURN (rval);
+}
+
+static int make_uc_space (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int space)
+{
+	EGLPNUM_TYPE *new_uccoef = 0;
+	int *new_ucindx = 0;
+	int *new_ucrind = 0;
+	int uc_freebeg = f->uc_freebeg;
+	EGLPNUM_TYPE *uccoef = f->uccoef;
+	int *ucindx = f->ucindx;
+	int *ucrind = f->ucrind;
+	int minspace = uc_freebeg + space;
+	EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+	int dim = f->dim;
+	int new_nzcnt = 0;
+	int cbeg;
+	int nzcnt;
+	int i;
+	int j;
+	int rval;
+
+	minspace = f->uc_space;
+	nzcnt = space;
+	for( i = 0 ; i < dim ; i++) nzcnt += uc_inf[i].nzcnt;
+	while(nzcnt*2 >= minspace)
+	{
+		minspace = 10 + (f->grow_mul * minspace);
+	}
+
+#ifdef GROWTH_STATS
+	MESSAGE (0,"make_uc_space growing from %d to %d...", f->uc_space, minspace);
+#endif
+
+	ILL_SAFE_MALLOC (new_ucindx, minspace + 1, int);
+
+	if (ucrind)
+	{
+		new_uccoef = EGLPNUM_TYPENAME_EGlpNumAllocArray (minspace);
+		ILL_SAFE_MALLOC (new_ucrind, minspace, int);
+	}
+
+	if (ucrind)
+	{
+		for (j = 0; j < dim; j++)
+		{
+			cbeg = uc_inf[j].cbeg;
+			nzcnt = uc_inf[j].nzcnt;
+			uc_inf[j].cbeg = new_nzcnt;
+			for (i = 0; i < nzcnt; i++)
+			{
+				new_ucindx[new_nzcnt] = ucindx[cbeg + i];
+				EGLPNUM_TYPENAME_EGlpNumCopy (new_uccoef[new_nzcnt], uccoef[cbeg + i]);
+				new_ucrind[new_nzcnt] = ucrind[cbeg + i];
+				new_nzcnt++;
+			}
+		}
+	}
+	else
+	{
+		for (j = 0; j < dim; j++)
+		{
+			cbeg = uc_inf[j].cbeg;
+			nzcnt = uc_inf[j].nzcnt;
+			uc_inf[j].cbeg = new_nzcnt;
+			for (i = 0; i < nzcnt; i++)
+			{
+				new_ucindx[new_nzcnt] = ucindx[cbeg + i];
+				new_nzcnt++;
+			}
+		}
+	}
+
+	for (i = new_nzcnt; i < minspace; i++)
+	{
+		new_ucindx[i] = -1;
+	}
+	new_ucindx[minspace] = 0;
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (f->uccoef);
+	f->uccoef = new_uccoef;
+	new_uccoef = 0;
+
+	ILL_IFFREE (f->ucindx, int);
+
+	f->ucindx = new_ucindx;
+	new_ucindx = 0;
+
+	ILL_IFFREE (f->ucrind, int);
+
+	f->ucrind = new_ucrind;
+	new_ucrind = 0;
+
+	f->uc_freebeg = new_nzcnt;
+	f->uc_space = minspace;
+
+#ifdef GROWTH_STATS
+	MESSAGE (0,"%d nonzeros", new_nzcnt);
+	dump_factor_stats (f);
+#endif
+
+	rval = 0;
+
+CLEANUP:
+	ILL_IFFREE (new_uccoef, EGLPNUM_TYPE);
+	ILL_IFFREE (new_ucindx, int);
+	ILL_IFFREE (new_ucrind, int);
+
+	EG_RETURN (rval);
+}
+
+static int make_lc_space (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int space)
+{
+	EGLPNUM_TYPE *new_lccoef = 0;
+	int *new_lcindx = 0;
+	int lc_freebeg = f->lc_freebeg;
+	EGLPNUM_TYPE *lccoef = f->lccoef;
+	int *lcindx = f->lcindx;
+	int minspace = lc_freebeg + space;
+	int i;
+	int rval;
+
+	if (f->lc_space * f->grow_mul > minspace)
+	{
+		minspace = f->lc_space * f->grow_mul;
+	}
+
+#ifdef GROWTH_STATS
+	MESSAGE (0,"make_lc_space growing from %d to %d...", f->lc_space, minspace);
+#endif
+
+	new_lccoef = EGLPNUM_TYPENAME_EGlpNumAllocArray (minspace);
+	ILL_SAFE_MALLOC (new_lcindx, minspace, int);
+
+	for (i = 0; i < lc_freebeg; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (new_lccoef[i], lccoef[i]);
+		new_lcindx[i] = lcindx[i];
+	}
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (lccoef);
+	f->lccoef = new_lccoef;
+	new_lccoef = 0;
+
+	ILL_IFFREE (lcindx, int);
+
+	f->lcindx = new_lcindx;
+	new_lcindx = 0;
+
+	f->lc_space = minspace;
+
+#ifdef GROWTH_STATS
+	dump_factor_stats (f);
+#endif
+
+	rval = 0;
+
+CLEANUP:
+	ILL_IFFREE (new_lccoef, EGLPNUM_TYPE);
+	ILL_IFFREE (new_lcindx, int);
+
+	EG_RETURN (rval);
+}
+
+static void set_col_nz (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int c)
+{
+	EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+	int nzcnt = uc_inf[c].nzcnt;
+	int max_k = f->max_k;
+	int dim = f->dim;
+
+	if (uc_inf[c].next >= 0)
+	{
+		uc_inf[uc_inf[c].next].prev = uc_inf[c].prev;
+		uc_inf[uc_inf[c].prev].next = uc_inf[c].next;
+
+		if (nzcnt >= max_k)
+			nzcnt = max_k;
+		uc_inf[c].next = uc_inf[dim + nzcnt].next;
+		uc_inf[c].prev = dim + nzcnt;
+		uc_inf[dim + nzcnt].next = c;
+		uc_inf[uc_inf[c].next].prev = c;
+	}
+}
+
+static void set_row_nz (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int r)
+{
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+	int nzcnt = ur_inf[r].pivcnt;
+	int max_k = f->max_k;
+	int dim = f->dim;
+
+	if (ur_inf[r].next >= 0)
+	{
+		ur_inf[ur_inf[r].next].prev = ur_inf[r].prev;
+		ur_inf[ur_inf[r].prev].next = ur_inf[r].next;
+
+		if (nzcnt >= max_k)
+			nzcnt = max_k;
+		ur_inf[r].next = ur_inf[dim + nzcnt].next;
+		ur_inf[r].prev = dim + nzcnt;
+		ur_inf[dim + nzcnt].next = r;
+		ur_inf[ur_inf[r].next].prev = r;
+	}
+}
+
+static void remove_col_nz (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int r,
+	int c)
+{
+	EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+	int *ucindx = f->ucindx + uc_inf[c].cbeg;
+	int nzcnt = uc_inf[c].nzcnt;
+	int i;
+
+	for (i = 0; i < nzcnt; i++)
+	{
+		if (ucindx[i] == r)
+		{
+			--nzcnt;
+			ucindx[i] = ucindx[nzcnt];
+			ucindx[nzcnt] = -1;
+			break;
+		}
+	}
+	uc_inf[c].nzcnt = nzcnt;
+
+	set_col_nz (f, c);
+}
+
+static void remove_row_nz (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int r,
+	int c)
+{
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+	int *urindx = f->urindx + ur_inf[r].rbeg;
+	EGLPNUM_TYPE *urcoef = f->urcoef + ur_inf[r].rbeg;
+	int pivcnt = ur_inf[r].pivcnt;
+	EGLPNUM_TYPE max;
+	int tind;
+	EGLPNUM_TYPE tcoef;
+	int i;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (tcoef);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (max);
+	EGLPNUM_TYPENAME_EGlpNumZero (max);
+
+	for (i = 0; i < pivcnt; i++)
+	{
+		if (urindx[i] == c)
+		{
+			--pivcnt;
+			ILL_SWAP (urindx[i], urindx[pivcnt], tind);
+			EGLPNUM_TYPENAME_EGLPNUM_SWAP (urcoef[i], urcoef[pivcnt], tcoef);
+			--i;
+		}
+		else
+		{
+			EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (max, urcoef[i]);
+		}
+	}
+	ur_inf[r].pivcnt = pivcnt;
+	EGLPNUM_TYPENAME_EGlpNumCopy (ur_inf[r].max, max);
+	set_row_nz (f, r);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (max);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (tcoef);
+}
+
+static int add_col_nz (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int r,
+	int c)
+{
+	EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+	int cbeg = uc_inf[c].cbeg;
+	int nzcnt = uc_inf[c].nzcnt;
+	int uc_freebeg = f->uc_freebeg;
+	int *ucindx = f->ucindx;
+	int i;
+	int rval = 0;
+
+	if (uc_inf[c].next == -1)
+	{
+		return 0;
+	}
+
+	if (ucindx[cbeg + nzcnt] == -1)
+	{
+		ucindx[cbeg + nzcnt] = r;
+		uc_inf[c].nzcnt++;
+		if (nzcnt + cbeg == uc_freebeg)
+		{
+			f->uc_freebeg = uc_freebeg + 1;
+		}
+	}
+	else
+	{
+		if (uc_freebeg + nzcnt + 1 >= f->uc_space)
+		{
+			rval = make_uc_space (f, nzcnt + 1);
+			CHECKRVALG (rval, CLEANUP);
+			uc_freebeg = f->uc_freebeg;
+			cbeg = uc_inf[c].cbeg;
+			ucindx = f->ucindx;
+		}
+		for (i = 0; i < nzcnt; i++)
+		{
+			ucindx[uc_freebeg + i] = ucindx[cbeg + i];
+			ucindx[cbeg + i] = -1;
+		}
+		ucindx[uc_freebeg + nzcnt] = r;
+		uc_inf[c].cbeg = uc_freebeg;
+		uc_inf[c].nzcnt++;
+		f->uc_freebeg = uc_freebeg + nzcnt + 1;
+	}
+
+	set_col_nz (f, c);
+CLEANUP:
+	EG_RETURN (rval);
+}
+
+static void disable_col (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int c)
+{
+	EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+
+	if (uc_inf[c].next >= 0)
+	{
+		uc_inf[uc_inf[c].next].prev = uc_inf[c].prev;
+		uc_inf[uc_inf[c].prev].next = uc_inf[c].next;
+
+		uc_inf[c].next = -2;
+		uc_inf[c].prev = -2;
+	}
+}
+
+static void remove_col (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int c)
+{
+	EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+	int cbeg = uc_inf[c].cbeg;
+	int nzcnt = uc_inf[c].nzcnt;
+	int *ucindx = f->ucindx;
+	int i;
+
+	for (i = 0; i < nzcnt; i++)
+	{
+		ucindx[cbeg + i] = -1;
+	}
+	uc_inf[c].cbeg = 0;
+	uc_inf[c].nzcnt = 0;
+
+	if (uc_inf[c].next >= 0)
+	{
+		uc_inf[uc_inf[c].next].prev = uc_inf[c].prev;
+		uc_inf[uc_inf[c].prev].next = uc_inf[c].next;
+
+		uc_inf[c].next = -1;
+		uc_inf[c].prev = -1;
+	}
+}
+
+static void remove_row (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int r)
+{
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+
+	if (ur_inf[r].next >= 0)
+	{
+		ur_inf[ur_inf[r].next].prev = ur_inf[r].prev;
+		ur_inf[ur_inf[r].prev].next = ur_inf[r].next;
+
+		ur_inf[r].next = -1;
+		ur_inf[r].prev = -1;
+	}
+}
+
+static void find_coef (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int r,
+	int c,
+	EGLPNUM_TYPE * coef)
+{
+	EGLPNUM_TYPE *prow_urcoef = f->urcoef + f->ur_inf[r].rbeg;
+	int *prow_urindx = f->urindx + f->ur_inf[r].rbeg;
+	int i;
+	int prow_nzcnt = f->ur_inf[r].nzcnt;
+
+	EGLPNUM_TYPENAME_EGlpNumZero (*coef);
+	for (i = 0; i < prow_nzcnt; i++)
+	{
+		if (prow_urindx[i] == c)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (*coef, prow_urcoef[i]);
+			return;
+		}
+	}
+	QSlog("Coefficient not found");
+	return;
+}
+
+static int elim_row (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int elim_r,
+	int r,
+	int c,
+	EGLPNUM_TYPE * p_pivot_coef)
+{
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+	EGLPNUM_TYPE *work_coef = f->work_coef;
+	int *work_indx = f->work_indx;
+	EGLPNUM_TYPE *urcoef = f->urcoef;
+	int *urindx = f->urindx;
+	int prow_beg = ur_inf[r].rbeg;
+	int prow_nzcnt = ur_inf[r].nzcnt;
+	int prow_pivcnt = ur_inf[r].pivcnt;
+	int fill = ur_inf[elim_r].nzcnt;
+	int cancel = 0;
+	EGLPNUM_TYPE max;
+	int erow_beg;
+	int erow_nzcnt;
+	int erow_pivcnt;
+	EGLPNUM_TYPE x;
+	int i;
+	int j;
+	int rval = 0;
+	EGLPNUM_TYPE elim_coef;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (max);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (x);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (elim_coef);
+	EGLPNUM_TYPENAME_EGlpNumZero (max);
+	find_coef (f, r, c, &elim_coef);
+	EGLPNUM_TYPENAME_EGlpNumDivTo (elim_coef, work_coef[c]);
+	EGLPNUM_TYPENAME_EGlpNumCopy (*p_pivot_coef, elim_coef);
+
+	for (i = 0; i < prow_nzcnt; i++)
+	{
+		j = urindx[prow_beg + i];
+		if (work_indx[j] == 1)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (x, urcoef[prow_beg + i]);
+			EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (x, elim_coef, work_coef[j]);
+			if ((!(EGLPNUM_TYPENAME_EGlpNumIsNeqZero (x, f->fzero_tol))) || j == c)
+			{
+				cancel++;
+				if (j != c)
+				{
+					remove_col_nz (f, r, j);
+				}
+				if (i < prow_pivcnt)
+				{
+					prow_pivcnt--;
+					prow_nzcnt--;
+					urindx[prow_beg + i] = urindx[prow_beg + prow_pivcnt];
+					EGLPNUM_TYPENAME_EGlpNumCopy (urcoef[prow_beg + i], urcoef[prow_beg + prow_pivcnt]);
+					if (prow_pivcnt != prow_nzcnt)
+					{
+						urindx[prow_beg + prow_pivcnt] = urindx[prow_beg + prow_nzcnt];
+						EGLPNUM_TYPENAME_EGlpNumCopy (urcoef[prow_beg + prow_pivcnt],
+												 urcoef[prow_beg + prow_nzcnt]);
+					}
+				}
+				else
+				{
+					prow_nzcnt--;
+					urindx[prow_beg + i] = urindx[prow_beg + prow_nzcnt];
+					EGLPNUM_TYPENAME_EGlpNumCopy (urcoef[prow_beg + i], urcoef[prow_beg + prow_nzcnt]);
+				}
+				urindx[prow_beg + prow_nzcnt] = -1;
+				i--;
+			}
+			else
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (urcoef[prow_beg + i], x);
+				if (i < prow_pivcnt)
+				{
+					EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (max, x);
+				}
+			}
+			work_indx[j] = 0;
+			fill--;
+		}
+		else
+		{
+			if (i < prow_pivcnt)
+			{
+				EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (max, urcoef[prow_beg + i]);
+			}
+		}
+	}
+
+	if (fill > 0)
+	{
+		ur_inf[r].nzcnt = prow_nzcnt;
+		ur_inf[r].pivcnt = prow_pivcnt;
+		if (fill > cancel)
+		{
+			int ur_freebeg = f->ur_freebeg;
+
+			if (ur_freebeg + prow_nzcnt + fill >= f->ur_space)
+			{
+				rval = make_ur_space (f, prow_nzcnt + fill);
+				CHECKRVALG (rval, CLEANUP);
+				urcoef = f->urcoef;
+				urindx = f->urindx;
+				ur_freebeg = f->ur_freebeg;
+				prow_beg = f->ur_inf[r].rbeg;
+			}
+			for (i = 0; i < prow_nzcnt; i++)
+			{
+				urindx[ur_freebeg + i] = urindx[prow_beg + i];
+				EGLPNUM_TYPENAME_EGlpNumCopy (urcoef[ur_freebeg + i], urcoef[prow_beg + i]);
+				urindx[prow_beg + i] = -1;
+			}
+			ur_inf[r].rbeg = ur_freebeg;
+			f->ur_freebeg = ur_freebeg + prow_nzcnt + fill;
+			prow_beg = ur_freebeg;
+		}
+
+		erow_beg = ur_inf[elim_r].rbeg;
+		erow_nzcnt = ur_inf[elim_r].nzcnt;
+		erow_pivcnt = ur_inf[elim_r].pivcnt;
+
+		for (i = 0; i < erow_pivcnt; i++)
+		{
+			j = urindx[erow_beg + i];
+			if (work_indx[j] == 1)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopyNeg (x, elim_coef);
+				EGLPNUM_TYPENAME_EGlpNumMultTo (x, urcoef[erow_beg + i]);
+				if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (x, f->fzero_tol))
+				{
+					rval = add_col_nz (f, r, j);
+					CHECKRVALG (rval, CLEANUP);
+					if (prow_pivcnt != prow_nzcnt)
+					{
+						urindx[prow_beg + prow_nzcnt] = urindx[prow_beg + prow_pivcnt];
+						EGLPNUM_TYPENAME_EGlpNumCopy (urcoef[prow_beg + prow_nzcnt],
+												 urcoef[prow_beg + prow_pivcnt]);
+					}
+					urindx[prow_beg + prow_pivcnt] = j;
+					EGLPNUM_TYPENAME_EGlpNumCopy (urcoef[prow_beg + prow_pivcnt], x);
+					EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (max, x);
+					prow_pivcnt++;
+					prow_nzcnt++;
+				}
+			}
+			else
+			{
+				work_indx[j] = 1;
+			}
+		}
+		for (i = erow_pivcnt; i < erow_nzcnt; i++)
+		{
+			j = urindx[erow_beg + i];
+			if (work_indx[j] == 1)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopyNeg (x, elim_coef);
+				EGLPNUM_TYPENAME_EGlpNumMultTo (x, urcoef[erow_beg + i]);
+				if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (x, f->fzero_tol))
+				{
+					rval = add_col_nz (f, r, j);
+					CHECKRVALG (rval, CLEANUP);
+					urindx[prow_beg + prow_nzcnt] = j;
+					EGLPNUM_TYPENAME_EGlpNumCopy (urcoef[prow_beg + prow_nzcnt], x);
+					prow_nzcnt++;
+				}
+			}
+			else
+			{
+				work_indx[j] = 1;
+			}
+		}
+	}
+	else
+	{
+		erow_nzcnt = ur_inf[elim_r].nzcnt;
+		erow_beg = ur_inf[elim_r].rbeg;
+		for (i = 0; i < erow_nzcnt; i++)
+		{
+			j = urindx[erow_beg + i];
+			work_indx[j] = 1;
+		}
+	}
+
+	ur_inf[r].nzcnt = prow_nzcnt;
+	ur_inf[r].pivcnt = prow_pivcnt;
+	EGLPNUM_TYPENAME_EGlpNumCopy (ur_inf[r].max, max);
+
+	set_row_nz (f, r);
+CLEANUP:
+	EGLPNUM_TYPENAME_EGlpNumClearVar (elim_coef);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (x);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (max);
+	EG_RETURN (rval);
+}
+
+#define SETPERM(f,s,r,c) {                    \
+        f->rperm[f->rrank[r]] = f->rperm[s];  \
+        f->rrank[f->rperm[s]] = f->rrank[r];  \
+        f->rperm[s] = r;                      \
+        f->rrank[r] = s;                      \
+                                              \
+        f->cperm[f->crank[c]] = f->cperm[s];  \
+        f->crank[f->cperm[s]] = f->crank[c];  \
+        f->cperm[s] = c;                      \
+        f->crank[c] = s;                      \
+}
+
+static int elim (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int r,
+	int c)
+{
+	EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+	EGLPNUM_TYPENAME_lc_info *lc_inf = f->lc_inf;
+	int *urindx;
+	int *ucindx;
+	int *lcindx;
+	EGLPNUM_TYPE *urcoef;
+	EGLPNUM_TYPE *lccoef;
+	EGLPNUM_TYPE pivot_coef;
+	int nzcnt;
+	int lc_freebeg;
+	int s = f->stage;
+	int i;
+	int j;
+	int rval = 0;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (pivot_coef);
+
+	if (uc_inf[c].nzcnt == 1)
+	{
+		/* col singleton */
+		SETPERM (f, s, r, c);
+
+		lc_inf[s].cbeg = -1;
+		lc_inf[s].c = r;
+		lc_inf[s].nzcnt = 0;
+		f->stage++;
+
+		urindx = f->urindx + ur_inf[r].rbeg;
+		urcoef = f->urcoef + ur_inf[r].rbeg;
+		nzcnt = ur_inf[r].nzcnt;
+		for (i = 0; i < nzcnt; i++)
+		{
+			j = urindx[i];
+			remove_col_nz (f, r, j);
+			if (j == c)
+			{
+				urindx[i] = urindx[0];
+				urindx[0] = c;
+				EGLPNUM_TYPENAME_EGLPNUM_SWAP (urcoef[0], urcoef[i], pivot_coef);
+			}
+		}
+		remove_row (f, r);
+		remove_col (f, c);
+	}
+	else if (ur_inf[r].nzcnt == 1)
+	{
+		/* row singleton */
+		--(f->nstages);
+		SETPERM (f, f->nstages, r, c);
+
+		lc_inf[f->nstages].cbeg = -1;
+		lc_inf[f->nstages].c = r;
+		lc_inf[f->nstages].nzcnt = 0;
+
+		ucindx = f->ucindx + uc_inf[c].cbeg;
+		nzcnt = uc_inf[c].nzcnt;
+		for (i = 0; i < nzcnt; i++)
+		{
+			j = ucindx[i];
+			remove_row_nz (f, j, c);
+		}
+		remove_row (f, r);
+		remove_col (f, c);
+	}
+	else
+	{
+		SETPERM (f, s, r, c);
+		f->stage++;
+
+		nzcnt = uc_inf[c].nzcnt;
+		if (f->lc_freebeg + nzcnt >= f->lc_space)
+		{
+			rval = make_lc_space (f, nzcnt);
+			CHECKRVALG (rval, CLEANUP);
+		}
+		lc_freebeg = f->lc_freebeg;
+		lc_inf[s].cbeg = lc_freebeg;
+		lc_inf[s].c = r;
+		lcindx = f->lcindx;
+		lccoef = f->lccoef;
+		load_row (f, r);
+		ucindx = f->ucindx + uc_inf[c].cbeg;
+		for (i = 0; i < nzcnt; i++)
+		{
+			j = f->ucindx[uc_inf[c].cbeg + i];
+			if (j != r)
+			{
+				rval = elim_row (f, r, j, c, &pivot_coef);
+				CHECKRVALG (rval, CLEANUP);
+				lcindx[lc_freebeg] = j;
+				EGLPNUM_TYPENAME_EGlpNumCopy (lccoef[lc_freebeg], pivot_coef);
+				lc_freebeg++;
+#ifdef TRACK_FACTOR
+				EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (f->maxelem_factor, pivot_coef);
+				if (EGLPNUM_TYPENAME_EGlpNumIsLess (f->maxelem_factor, ur_inf[r].max))
+					EGLPNUM_TYPENAME_EGlpNumCopy (f->maxelem_factor, ur_inf[r].max);
+#endif /* TRACK_FACTOR */
+			}
+		}
+		lc_inf[s].nzcnt = lc_freebeg - lc_inf[s].cbeg;
+		f->lc_freebeg = lc_freebeg;
+
+		clear_row (f, r);
+
+		urindx = f->urindx + ur_inf[r].rbeg;
+		urcoef = f->urcoef + ur_inf[r].rbeg;
+		nzcnt = ur_inf[r].nzcnt;
+		for (i = 0; i < nzcnt; i++)
+		{
+			j = urindx[i];
+			remove_col_nz (f, r, j);
+			if (j == c)
+			{
+				urindx[i] = urindx[0];
+				urindx[0] = c;
+				EGLPNUM_TYPENAME_EGLPNUM_SWAP (urcoef[0], urcoef[i], pivot_coef);
+			}
+		}
+		remove_row (f, r);
+		remove_col (f, c);
+	}
+CLEANUP:
+	EGLPNUM_TYPENAME_EGlpNumClearVar (pivot_coef);
+	EG_RETURN (rval);
+}
+
+static void find_pivot_column (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int c,
+	int *p_r)
+{
+	EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+	int *ucindx = f->ucindx;
+	int nzcnt = uc_inf[c].nzcnt;
+	int cbeg = uc_inf[c].cbeg;
+	EGLPNUM_TYPE num_tmp[2];
+	int bestnz = -1;
+	int i;
+	int r;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (num_tmp[0]);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (num_tmp[1]);
+
+	*p_r = -1;
+	for (i = 0; i < nzcnt; i++)
+	{
+		r = ucindx[cbeg + i];
+		if((bestnz == -1 || ur_inf[r].pivcnt < bestnz))
+		{
+			find_coef (f, r, c, num_tmp);
+			if(EGLPNUM_TYPENAME_EGlpNumIsLessZero(num_tmp[0]))
+				EGLPNUM_TYPENAME_EGlpNumSign (num_tmp[0]);
+			EGLPNUM_TYPENAME_EGlpNumCopy (num_tmp[1], f->partial_cur);
+			EGLPNUM_TYPENAME_EGlpNumMultTo (num_tmp[1], ur_inf[r].max);
+			if(EGLPNUM_TYPENAME_EGlpNumIsLeq (num_tmp[1], num_tmp[0]))
+			{
+				bestnz = ur_inf[r].pivcnt;
+				*p_r = r;
+			}
+		}
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (num_tmp[0]);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (num_tmp[1]);
+}
+
+static void find_pivot_row (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int r,
+	int *p_c)
+{
+	EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+	int *urindx = f->urindx;
+	EGLPNUM_TYPE *urcoef = f->urcoef;
+	int pivcnt = ur_inf[r].pivcnt;
+	int rbeg = ur_inf[r].rbeg;
+	EGLPNUM_TYPE thresh[2];
+	int bestnz = -1;
+	int i;
+	int c;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (thresh[0]);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (thresh[1]);
+	EGLPNUM_TYPENAME_EGlpNumCopy (thresh[0], f->partial_cur);
+	EGLPNUM_TYPENAME_EGlpNumMultTo (thresh[0], ur_inf[r].max);
+	*p_c = -1;
+	for (i = 0; i < pivcnt; i++)
+	{
+		c = urindx[rbeg + i];
+		if ((bestnz == -1 || uc_inf[c].nzcnt < bestnz))
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopyAbs (thresh[1], urcoef[rbeg + i]);
+			if(EGLPNUM_TYPENAME_EGlpNumIsLeq (thresh[0], thresh[1]))
+			{
+				bestnz = uc_inf[c].nzcnt;
+				*p_c = c;
+			}
+		}
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (thresh[0]);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (thresh[1]);
+}
+
+static int find_pivot (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int *p_r,
+	int *p_c)
+{
+	EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+	int dim = f->dim;
+	int max_k = f->max_k;
+	int p = f->p;
+	int c;
+	int r;
+	int mm = 0;
+	int n = 0;
+	int m;
+	int k = 2;
+
+	if (uc_inf[dim + 1].next != dim + 1)
+	{
+		c = uc_inf[dim + 1].next;
+		r = f->ucindx[uc_inf[c].cbeg];
+		*p_c = c;
+		*p_r = r;
+		return 0;
+	}
+	else if (ur_inf[dim + 1].next != dim + 1)
+	{
+		r = ur_inf[dim + 1].next;
+		c = f->urindx[ur_inf[r].rbeg];
+		*p_c = c;
+		*p_r = r;
+		return 0;
+	}
+	*p_r = -1;
+	*p_c = -1;
+	for (; k <= max_k && (mm == 0 || mm > (k - 1) * (k - 1)); k++)
+	{
+		if (uc_inf[dim + k].next != dim + k)
+		{
+			for (c = uc_inf[dim + k].next; c != dim + k; c = uc_inf[c].next)
+			{
+				find_pivot_column (f, c, &r);
+				if (r >= 0)
+				{
+					m = (uc_inf[c].nzcnt - 1) * (ur_inf[r].pivcnt - 1);
+					if (mm == 0 || m < mm)
+					{
+						mm = m;
+						*p_c = c;
+						*p_r = r;
+						if (mm <= (k - 1) * (k - 1))
+						{
+							return 0;
+						}
+					}
+				}
+				else
+				{
+					c = uc_inf[c].prev;
+					disable_col (f, uc_inf[c].next);
+				}
+				n++;
+				if (n >= p && mm != 0)
+				{
+					return 0;
+				}
+			}
+		}
+
+		if (ur_inf[dim + k].next != dim + k)
+		{
+			for (r = ur_inf[dim + k].next; r != dim + k; r = ur_inf[r].next)
+			{
+				find_pivot_row (f, r, &c);
+				if (c >= 0)
+				{
+					m = (uc_inf[c].nzcnt - 1) * (ur_inf[r].pivcnt - 1);
+					if (mm == 0 || m < mm)
+					{
+						mm = m;
+						*p_c = c;
+						*p_r = r;
+						if (mm <= k * (k - 1))
+						{
+							return 0;
+						}
+					}
+				}
+				n++;
+				if (n >= p && mm != 0)
+				{
+					return 0;
+				}
+			}
+		}
+	}
+	if (mm != 0)
+	{
+		return 0;
+	}
+	else
+	{
+		//QSlog("No acceptable pivot found");
+		return E_NO_PIVOT;
+	}
+}
+
+static int create_factor_space (
+	EGLPNUM_TYPENAME_factor_work * f)
+{
+	EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+	int dim = f->dim;
+	int nzcnt;
+	int i;
+	int rval;
+
+	nzcnt = 0;
+	for (i = 0; i < dim; i++)
+	{
+		nzcnt += ur_inf[i].nzcnt;
+	}
+
+	if (f->ucindx == 0)
+	{
+		f->uc_space = nzcnt * f->uc_space_mul;
+		ILL_SAFE_MALLOC (f->ucindx, f->uc_space + 1, int);
+	}
+
+	if (f->urindx == 0 || f->urcoef == 0)
+	{
+		ILL_IFFREE (f->urindx, int);
+
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (f->urcoef);
+		f->ur_space = nzcnt * f->ur_space_mul;
+		ILL_SAFE_MALLOC (f->urindx, f->ur_space + 1, int);
+
+		f->urcoef = EGLPNUM_TYPENAME_EGlpNumAllocArray (f->ur_space);
+	}
+
+	if (f->lcindx == 0 || f->lccoef == 0)
+	{
+		ILL_IFFREE (f->lcindx, int);
+
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (f->lccoef);
+		f->lc_space = nzcnt * f->lc_space_mul;
+		ILL_SAFE_MALLOC (f->lcindx, f->lc_space, int);
+
+		f->lccoef = EGLPNUM_TYPENAME_EGlpNumAllocArray (f->lc_space);
+	}
+
+	nzcnt = 0;
+	for (i = 0; i < dim; i++)
+	{
+		ur_inf[i].rbeg = nzcnt;
+		nzcnt += ur_inf[i].nzcnt;
+		ur_inf[i].nzcnt = ur_inf[i].rbeg;
+	}
+	f->ur_freebeg = nzcnt;
+
+	nzcnt = 0;
+	for (i = 0; i < dim; i++)
+	{
+		uc_inf[i].cbeg = nzcnt;
+		nzcnt += uc_inf[i].nzcnt;
+		uc_inf[i].nzcnt = uc_inf[i].cbeg;
+	}
+	f->uc_freebeg = nzcnt;
+
+	f->lc_freebeg = 0;
+
+	rval = 0;
+CLEANUP:
+	EG_RETURN (rval);
+}
+
+static int init_matrix (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int *basis,
+	int *cbeg,
+	int *clen,
+	int *in_ucindx,
+	EGLPNUM_TYPE * in_uccoef)
+{
+	EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+	int dim = f->dim;
+	int max_k = f->max_k;
+	int *ucindx;
+	int *urindx;
+	EGLPNUM_TYPE *urcoef;
+	int nzcnt;
+	int beg;
+	int i;
+	int j;
+	int r;
+	int rval = 0;
+	EGLPNUM_TYPE v;
+	EGLPNUM_TYPE max;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (max);
+
+	for (i = 0; i < dim; i++)
+	{
+		ur_inf[i].nzcnt = 0;
+	}
+	for (i = 0; i < dim; i++)
+	{
+		nzcnt = clen[basis[i]];
+		beg = cbeg[basis[i]];
+		uc_inf[i].nzcnt = nzcnt;
+		for (j = 0; j < nzcnt; j++)
+		{
+			r = in_ucindx[beg + j];
+			ur_inf[r].nzcnt++;
+		}
+	}
+
+	rval = create_factor_space (f);
+	CHECKRVALG (rval, CLEANUP);
+
+	urindx = f->urindx;
+	ucindx = f->ucindx;
+	urcoef = f->urcoef;
+
+	for (i = 0; i < dim; i++)
+	{
+		nzcnt = clen[basis[i]];
+		beg = cbeg[basis[i]];
+		for (j = 0; j < nzcnt; j++)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (v, in_uccoef[beg + j]);
+			if (!(EGLPNUM_TYPENAME_EGlpNumIsNeqZero (v, f->fzero_tol)))
+				continue;
+			r = in_ucindx[beg + j];
+			ucindx[uc_inf[i].nzcnt++] = r;
+			urindx[ur_inf[r].nzcnt] = i;
+			EGLPNUM_TYPENAME_EGlpNumCopy (urcoef[ur_inf[r].nzcnt], v);
+			ur_inf[r].nzcnt++;
+		}
+	}
+
+	for (i = 0; i < dim; i++)
+	{
+		uc_inf[i].nzcnt -= uc_inf[i].cbeg;
+		ur_inf[i].nzcnt -= ur_inf[i].rbeg;
+	}
+
+	j = f->uc_space;
+	for (i = f->uc_freebeg; i < j; i++)
+	{
+		ucindx[i] = -1;
+	}
+	ucindx[j] = 0;
+
+	j = f->ur_space;
+	for (i = f->ur_freebeg; i < j; i++)
+	{
+		urindx[i] = -1;
+	}
+	urindx[j] = 0;
+
+	for (i = 0; i < dim; i++)
+	{
+		nzcnt = ur_inf[i].nzcnt;
+		ur_inf[i].pivcnt = nzcnt;
+		beg = ur_inf[i].rbeg;
+		EGLPNUM_TYPENAME_EGlpNumZero (max);
+		for (j = 0; j < nzcnt; j++)
+		{
+			EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (max, urcoef[beg + j]);
+		}
+		EGLPNUM_TYPENAME_EGlpNumCopy (ur_inf[i].max, max);
+	}
+
+	for (i = 0; i <= max_k; i++)
+	{
+		ur_inf[dim + i].next = dim + i;
+		ur_inf[dim + i].prev = dim + i;
+		uc_inf[dim + i].next = dim + i;
+		uc_inf[dim + i].prev = dim + i;
+	}
+
+	for (i = 0; i < dim; i++)
+	{
+		nzcnt = uc_inf[i].nzcnt;
+		if (nzcnt >= max_k)
+			nzcnt = max_k;
+		uc_inf[i].next = uc_inf[dim + nzcnt].next;
+		uc_inf[i].prev = dim + nzcnt;
+		uc_inf[dim + nzcnt].next = i;
+		uc_inf[uc_inf[i].next].prev = i;
+
+		nzcnt = ur_inf[i].pivcnt;
+		if (nzcnt >= max_k)
+			nzcnt = max_k;
+		ur_inf[i].next = ur_inf[dim + nzcnt].next;
+		ur_inf[i].prev = dim + nzcnt;
+		ur_inf[dim + nzcnt].next = i;
+		ur_inf[ur_inf[i].next].prev = i;
+	}
+
+#ifdef TRACK_FACTOR
+	EGLPNUM_TYPENAME_EGlpNumZero (max);
+	nzcnt = 0;
+	for (i = 0; i < dim; i++)
+	{
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (max, ur_inf[i].max))
+			EGLPNUM_TYPENAME_EGlpNumCopy (max, ur_inf[i].max);
+		nzcnt += ur_inf[i].nzcnt;
+	}
+
+	EGLPNUM_TYPENAME_EGlpNumCopy (f->maxelem_orig, max);
+	f->nzcnt_orig = nzcnt;
+	EGLPNUM_TYPENAME_EGlpNumCopy (f->maxelem_factor, f->maxelem_orig);
+	f->nzcnt_factor = f->nzcnt_orig;
+#endif /* TRACK_FACTOR */
+
+	/* sentinal for column space */
+	ucindx[f->uc_space] = 0;
+
+	clear_work (f);
+
+CLEANUP:
+	EGLPNUM_TYPENAME_EGlpNumClearVar (max);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+	EG_RETURN (rval);
+}
+
+static int build_iteration_u_data (
+	EGLPNUM_TYPENAME_factor_work * f)
+{
+	int dim = f->dim;
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+	EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+	EGLPNUM_TYPE *uccoef = 0;
+	int *ucindx = 0;
+	int *urindx = f->urindx;
+	EGLPNUM_TYPE *urcoef = f->urcoef;
+	int *ucrind = 0;
+	int *urcind = 0;
+	int nzcnt;
+	int beg;
+	int cbeg;
+	int cnzcnt;
+	int uc_space = f->uc_space;
+	int er_space;
+	int i;
+	int j;
+	int k;
+	int rval;
+
+	nzcnt = 0;
+	for (i = 0; i < dim; i++)
+	{
+		nzcnt += ur_inf[i].nzcnt;
+	}
+
+#ifdef TRACK_FACTOR
+	f->nzcnt_factor = nzcnt;
+#endif /* TRACK_FACTOR */
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (f->uccoef);
+	uccoef = EGLPNUM_TYPENAME_EGlpNumAllocArray (nzcnt);
+	f->uccoef = uccoef;
+
+	ILL_IFFREE (f->ucrind, int);
+	ILL_SAFE_MALLOC (ucrind, nzcnt, int);
+
+	f->ucrind = ucrind;
+
+	ILL_IFFREE (f->urcind, int);
+	ILL_SAFE_MALLOC (urcind, f->ur_space, int);
+
+	f->urcind = urcind;
+
+	if (uc_space < nzcnt)
+	{
+		ILL_IFFREE (f->ucindx, int);
+		ILL_SAFE_MALLOC (f->ucindx, nzcnt + 1, int);
+	}
+	f->uc_space = nzcnt;
+	uc_space = nzcnt;
+	ucindx = f->ucindx;
+
+	for (i = 0; i < dim; i++)
+	{
+		uc_inf[i].nzcnt = 0;
+	}
+
+	for (i = 0; i < dim; i++)
+	{
+		nzcnt = ur_inf[i].nzcnt;
+		beg = ur_inf[i].rbeg;
+		for (j = 0; j < nzcnt; j++)
+		{
+			uc_inf[urindx[beg + j]].nzcnt++;
+		}
+		ur_inf[i].delay = 0;
+	}
+
+	nzcnt = 0;
+	for (i = 0; i < dim; i++)
+	{
+		uc_inf[i].cbeg = nzcnt;
+		nzcnt += uc_inf[i].nzcnt;
+		uc_inf[i].nzcnt = 0;
+		uc_inf[i].delay = 0;
+	}
+
+	f->uc_freebeg = nzcnt;
+	for (i = nzcnt; i < uc_space; i++)
+	{
+		ucindx[i] = -1;
+	}
+	ucindx[uc_space] = 0;
+
+	for (i = 0; i < dim; i++)
+	{
+		nzcnt = ur_inf[i].nzcnt;
+		beg = ur_inf[i].rbeg;
+		k = urindx[beg];
+		cbeg = uc_inf[k].cbeg;
+		cnzcnt = uc_inf[k].nzcnt;
+		if (cnzcnt != 0)
+		{
+			ucindx[cbeg + cnzcnt] = ucindx[cbeg];
+			EGLPNUM_TYPENAME_EGlpNumCopy (uccoef[cbeg + cnzcnt], uccoef[cbeg]);
+			ucrind[cbeg + cnzcnt] = ucrind[cbeg];
+			urcind[ur_inf[ucindx[cbeg]].rbeg + ucrind[cbeg]] = cnzcnt;
+		}
+		ucindx[cbeg] = i;
+		EGLPNUM_TYPENAME_EGlpNumCopy (uccoef[cbeg], urcoef[beg]);
+		ucrind[cbeg] = 0;
+		urcind[beg] = 0;
+		uc_inf[k].nzcnt = cnzcnt + 1;
+		for (j = 1; j < nzcnt; j++)
+		{
+			k = urindx[beg + j];
+			cbeg = uc_inf[k].cbeg;
+			cnzcnt = uc_inf[k].nzcnt;
+			ucindx[cbeg + cnzcnt] = i;
+			EGLPNUM_TYPENAME_EGlpNumCopy (uccoef[cbeg + cnzcnt], urcoef[beg + j]);
+			ucrind[cbeg + cnzcnt] = j;
+			urcind[beg + j] = cnzcnt;
+			uc_inf[k].nzcnt++;
+		}
+	}
+
+	for (i = 0; i < dim; i++)
+	{
+		f->rrank[f->rperm[i]] = i;
+	}
+
+	nzcnt = f->ur_space;
+
+	for (i = f->ur_freebeg; i < nzcnt; i++)
+	{
+		urindx[i] = -1;
+	}
+	urindx[nzcnt] = 0;
+
+	clear_work (f);
+
+	er_space = f->er_space_mul * f->etamax;
+	ILL_SAFE_MALLOC (f->er_inf, f->etamax, EGLPNUM_TYPENAME_er_info);
+	ILL_SAFE_MALLOC (f->erindx, er_space, int);
+
+	f->ercoef = EGLPNUM_TYPENAME_EGlpNumAllocArray (er_space);
+	f->etacnt = 0;
+	f->er_freebeg = 0;
+	f->er_space = er_space;
+
+	rval = 0;
+
+CLEANUP:
+	EG_RETURN (rval);
+}
+
+static int build_iteration_l_data (
+	EGLPNUM_TYPENAME_factor_work * f)
+{
+	int dim = f->dim;
+	EGLPNUM_TYPENAME_lc_info *lc_inf = f->lc_inf;
+	EGLPNUM_TYPENAME_lr_info *lr_inf = f->lr_inf;
+	EGLPNUM_TYPE *lrcoef = 0;
+	int *lrindx = 0;
+	EGLPNUM_TYPE *lccoef = f->lccoef;
+	int *lcindx = f->lcindx;
+	int nzcnt;
+	int beg;
+	int rnzcnt;
+	int rbeg;
+	int i;
+	int j;
+	int k;
+	int c;
+	int rval;
+
+	nzcnt = 0;
+	for (i = 0; i < dim; i++)
+	{
+		nzcnt += lc_inf[i].nzcnt;
+		lr_inf[i].nzcnt = 0;
+		lr_inf[i].delay = 0;
+		lc_inf[lc_inf[i].c].crank = i;
+	}
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (f->lrcoef);
+	if (nzcnt)
+	{
+		lrcoef = EGLPNUM_TYPENAME_EGlpNumAllocArray (nzcnt);
+		f->lrcoef = lrcoef;
+	}
+
+	ILL_IFFREE (f->lrindx, int);
+	ILL_SAFE_MALLOC (lrindx, nzcnt + 1, int);
+
+	f->lrindx = lrindx;
+
+	for (i = 0; i < dim; i++)
+	{
+		nzcnt = lc_inf[i].nzcnt;
+		beg = lc_inf[i].cbeg;
+		lc_inf[i].delay = 0;
+		for (j = 0; j < nzcnt; j++)
+		{
+			lr_inf[lc_inf[lcindx[beg + j]].crank].nzcnt++;
+		}
+	}
+
+	nzcnt = 0;
+	for (i = 0; i < dim; i++)
+	{
+		lr_inf[i].rbeg = nzcnt;
+		nzcnt += lr_inf[i].nzcnt;
+		lr_inf[i].nzcnt = 0;
+		lr_inf[i].r = lc_inf[i].c;
+		lr_inf[lr_inf[i].r].rrank = i;
+	}
+
+	for (i = 0; i < dim; i++)
+	{
+		nzcnt = lc_inf[i].nzcnt;
+		beg = lc_inf[i].cbeg;
+		c = lc_inf[i].c;
+		for (j = 0; j < nzcnt; j++)
+		{
+			k = lc_inf[lcindx[beg + j]].crank;
+			rbeg = lr_inf[k].rbeg;
+			rnzcnt = lr_inf[k].nzcnt;
+			lrindx[rbeg + rnzcnt] = c;
+			EGLPNUM_TYPENAME_EGlpNumCopy (lrcoef[rbeg + rnzcnt], lccoef[beg + j]);
+			lr_inf[k].nzcnt++;
+		}
+	}
+
+#ifdef TRACK_FACTOR
+	nzcnt = f->nzcnt_factor;
+	for (i = 0; i < dim; i++)
+	{
+		nzcnt += lc_inf[i].nzcnt;
+	}
+	f->nzcnt_factor = nzcnt;
+
+	EGLPNUM_TYPENAME_EGlpNumCopy (f->maxelem_cur, f->maxelem_factor);
+	f->nzcnt_cur = f->nzcnt_factor;
+
+/*
+    dump_factor_stats (f);
+    QSlog("orig max  %e nzcnt %d", f->maxelem_orig, f->nzcnt_orig);
+    QSlog("f maxelem %e nzcnt %d", f->maxelem_cur, f->nzcnt_cur);
+*/
+#endif /* TRACK_FACTOR */
+
+	rval = 0;
+
+CLEANUP:
+	EG_RETURN (rval);
+}
+
+static int handle_singularity (
+	EGLPNUM_TYPENAME_factor_work * f)
+{
+	int rval = 0;
+	int nsing;
+	int *singr = 0;
+	int *singc = 0;
+	int i;
+
+	if (f->p_nsing == 0 || f->p_singr == 0 || f->p_singc == 0)
+	{
+		QSlog("singular basis, but no place for singularity data");
+		return E_SING_NO_DATA;
+	}
+
+	nsing = f->nstages - f->stage;
+	ILL_SAFE_MALLOC (singr, nsing, int);
+	ILL_SAFE_MALLOC (singc, nsing, int);
+
+	for (i = f->stage; i < f->nstages; i++)
+	{
+		singr[i - f->stage] = f->rperm[i];
+		singc[i - f->stage] = f->cperm[i];
+	}
+	*f->p_nsing = nsing;
+	*f->p_singr = singr;
+	*f->p_singc = singc;
+	singr = 0;
+	singc = 0;
+
+CLEANUP:
+	ILL_IFFREE (singr, int);
+	ILL_IFFREE (singc, int);
+
+	EG_RETURN (rval);
+}
+
+static int dense_build_matrix (
+	EGLPNUM_TYPENAME_factor_work * f)
+{
+	EGLPNUM_TYPE *dmat = 0;
+	int stage = f->stage;
+	int drows = f->nstages - stage;
+	int dcols = f->dim - stage;
+	int dsize = drows * dcols;
+	int *crank = f->crank;
+	EGLPNUM_TYPE *urcoef = f->urcoef;
+	int *urindx = f->urindx;
+	int nzcnt;
+	int beg;
+	int i;
+	int r;
+	int j;
+	int rval = 0;
+
+	dmat = EGLPNUM_TYPENAME_EGlpNumAllocArray (dsize);
+
+	for (i = 0; i < dsize; i++)
+		EGLPNUM_TYPENAME_EGlpNumZero (dmat[i]);
+
+	for (i = 0; i < drows; i++)
+	{
+		r = f->rperm[i + stage];
+		nzcnt = f->ur_inf[r].nzcnt;
+		beg = f->ur_inf[r].rbeg;
+		for (j = 0; j < nzcnt; j++)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (dmat[i * dcols - stage + crank[urindx[beg + j]]],
+									 urcoef[beg + j]);
+		}
+	}
+
+	f->drows = drows;
+	f->dcols = dcols;
+	f->dense_base = f->stage;
+	f->dmat = dmat;
+	dmat = 0;
+
+//CLEANUP:
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (dmat);
+	EG_RETURN (rval);
+}
+
+static int dense_find_pivot (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int *p_r,
+	int *p_c)
+{
+	int dcols = f->dcols;
+	int drows = f->drows;
+	EGLPNUM_TYPE *dmat = f->dmat;
+	int dense_base = f->dense_base;
+	int s = f->stage - dense_base;
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+	int *rperm = f->rperm;
+	EGLPNUM_TYPE maxval;
+	int max_r;
+	int max_c;
+	int i;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (maxval);
+	EGLPNUM_TYPENAME_EGlpNumZero (maxval);
+	max_r = -1;
+	for (i = s; i < drows; i++)
+	{
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (maxval, ur_inf[rperm[dense_base + i]].max))
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (maxval, ur_inf[rperm[dense_base + i]].max);
+			max_r = i;
+		}
+	}
+	if (max_r == -1)
+	{
+		return E_NO_PIVOT;
+	}
+
+	EGLPNUM_TYPENAME_EGlpNumZero (maxval);
+	max_c = -1;
+	for (i = s; i < drows; i++)
+	{
+		EGlpNumSetToMaxAbsAndDo (maxval, dmat[max_r * dcols + i], max_c = i);
+	}
+	if (max_c == -1)
+	{
+		return E_NO_PIVOT;
+	}
+	*p_r = max_r;
+	*p_c = max_c;
+
+	EGLPNUM_TYPENAME_EGlpNumClearVar (maxval);
+	return 0;
+}
+
+static void dense_swap (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int r,
+	int c)
+{
+	int dcols = f->dcols;
+	int drows = f->drows;
+	EGLPNUM_TYPE *dmat = f->dmat;
+	int dense_base = f->dense_base;
+	int s = f->stage - dense_base;
+	int i;
+	EGLPNUM_TYPE v;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+	if (r != s)
+	{
+		ILL_SWAP (f->rperm[dense_base + s], f->rperm[dense_base + r], i);
+		f->rrank[f->rperm[dense_base + s]] = dense_base + s;
+		f->rrank[f->rperm[dense_base + r]] = dense_base + r;
+		for (i = 0; i < dcols; i++)
+		{
+			EGLPNUM_TYPENAME_EGLPNUM_SWAP (dmat[s * dcols + i], dmat[r * dcols + i], v);
+		}
+	}
+	if (c != s)
+	{
+		ILL_SWAP (f->cperm[dense_base + s], f->cperm[dense_base + c], i);
+		f->crank[f->cperm[dense_base + s]] = dense_base + s;
+		f->crank[f->cperm[dense_base + c]] = dense_base + c;
+		for (i = 0; i < drows; i++)
+		{
+			EGLPNUM_TYPENAME_EGLPNUM_SWAP (dmat[i * dcols + s], dmat[i * dcols + c], v);
+		}
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+
+static void dense_elim (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int r,
+	int c)
+{
+	int dcols = f->dcols;
+	int drows = f->drows;
+	EGLPNUM_TYPE *dmat = f->dmat;
+	int dense_base = f->dense_base;
+	int s = f->stage - dense_base;
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+	int *rperm = f->rperm;
+	int i;
+	int j;
+	EGLPNUM_TYPE pivval;
+	EGLPNUM_TYPE max;
+	EGLPNUM_TYPE v;
+	EGLPNUM_TYPE w;
+
+#ifdef TRACK_FACTOR
+	EGLPNUM_TYPE maxelem_factor;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (maxelem_factor);
+	EGLPNUM_TYPENAME_EGlpNumCopy (maxelem_factor, f->maxelem_factor);
+#endif
+	EGLPNUM_TYPENAME_EGlpNumInitVar (pivval);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (max);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (w);
+
+	dense_swap (f, r, c);
+	f->stage++;
+	EGLPNUM_TYPENAME_EGlpNumCopyFrac (pivval, EGLPNUM_TYPENAME_oneLpNum, dmat[s * dcols + s]);
+	for (i = s + 1; i < drows; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (v, dmat[i * dcols + s]);
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (v))
+		{
+			EGLPNUM_TYPENAME_EGlpNumMultTo (v, pivval);
+			if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (v, f->fzero_tol))
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (dmat[i * dcols + s], v);
+#ifdef TRACK_FACTOR
+				EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (maxelem_factor, v);
+#endif
+				EGLPNUM_TYPENAME_EGlpNumZero (max);
+				for (j = s + 1; j < drows; j++)
+				{
+					EGLPNUM_TYPENAME_EGlpNumCopy (w, dmat[i * dcols + j]);
+					EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (w, v, dmat[s * dcols + j]);
+					EGLPNUM_TYPENAME_EGlpNumCopy (dmat[i * dcols + j], w);
+					EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (max, w);
+				}
+				for (j = drows; j < dcols; j++)
+				{
+					EGLPNUM_TYPENAME_EGlpNumCopy (w, dmat[i * dcols + j]);
+					EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (w, v, dmat[s * dcols + j]);
+					EGLPNUM_TYPENAME_EGlpNumCopy (dmat[i * dcols + j], w);
+				}
+				EGLPNUM_TYPENAME_EGlpNumCopy (ur_inf[rperm[dense_base + i]].max, max);
+#ifdef TRACK_FACTOR
+				if (EGLPNUM_TYPENAME_EGlpNumIsLess (maxelem_factor, max))
+					EGLPNUM_TYPENAME_EGlpNumCopy (maxelem_factor, max);
+#endif
+			}
+			else
+			{
+				EGLPNUM_TYPENAME_EGlpNumZero (dmat[i * dcols + s]);
+			}
+		}
+	}
+#ifdef TRACK_FACTOR
+	EGLPNUM_TYPENAME_EGlpNumCopy (f->maxelem_factor, maxelem_factor);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (maxelem_factor);
+#endif
+	EGLPNUM_TYPENAME_EGlpNumClearVar (pivval);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (max);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (w);
+}
+
+static int dense_replace_row (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int i)
+{
+	int dcols = f->dcols;
+	int dense_base = f->dense_base;
+	EGLPNUM_TYPE *dmat = f->dmat + i * dcols;
+	EGLPNUM_TYPE *urcoef;
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+	int *cperm = f->cperm;
+	int r = f->rperm[dense_base + i];
+	int *urindx;
+	int nzcnt;
+	int beg;
+	int j;
+	int rval = 0;
+
+	nzcnt = 0;
+	for (j = i; j < dcols; j++)
+	{
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (dmat[j], f->fzero_tol))
+		{
+			nzcnt++;
+		}
+	}
+	if (nzcnt > ur_inf[r].nzcnt)
+	{
+		if (ur_inf[r].rbeg + ur_inf[r].nzcnt == f->ur_freebeg)
+		{
+			f->ur_freebeg = ur_inf[r].rbeg;
+		}
+		ur_inf[r].nzcnt = 0;
+		if (f->ur_freebeg + nzcnt > f->ur_space)
+		{
+			rval = make_ur_space (f, nzcnt);
+			CHECKRVALG (rval, CLEANUP);
+		}
+		ur_inf[r].rbeg = f->ur_freebeg;
+		f->ur_freebeg += nzcnt;
+	}
+	beg = ur_inf[r].rbeg;
+	urcoef = f->urcoef;
+	urindx = f->urindx;
+	for (j = i; j < dcols; j++)
+	{
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (dmat[j], f->fzero_tol))
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (urcoef[beg], dmat[j]);
+			urindx[beg] = cperm[dense_base + j];
+			beg++;
+		}
+	}
+	ur_inf[r].nzcnt = beg - ur_inf[r].rbeg;
+CLEANUP:
+	EG_RETURN (rval);
+}
+
+static int dense_create_col (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int i)
+{
+	int dcols = f->dcols;
+	int drows = f->drows;
+	int dense_base = f->dense_base;
+	EGLPNUM_TYPE *dmat = f->dmat;
+	EGLPNUM_TYPE *lccoef;
+	EGLPNUM_TYPENAME_lc_info *lc_inf = f->lc_inf;
+	int *rperm = f->rperm;
+	int *lcindx;
+	int nzcnt;
+	int beg;
+	int j;
+	int rval = 0;
+
+	nzcnt = 0;
+	for (j = i + 1; j < drows; j++)
+	{
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (dmat[j * dcols + i], f->fzero_tol))
+		{
+			nzcnt++;
+		}
+	}
+
+	if (f->lc_freebeg + nzcnt >= f->lc_space)
+	{
+		rval = make_lc_space (f, nzcnt);
+		CHECKRVALG (rval, CLEANUP);
+	}
+	beg = f->lc_freebeg;
+	lc_inf[dense_base + i].cbeg = beg;
+	lc_inf[dense_base + i].c = rperm[dense_base + i];
+	lcindx = f->lcindx;
+	lccoef = f->lccoef;
+
+	for (j = i + 1; j < drows; j++)
+	{
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (dmat[j * dcols + i], f->fzero_tol))
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (lccoef[beg], dmat[j * dcols + i]);
+			lcindx[beg] = rperm[dense_base + j];
+			beg++;
+		}
+	}
+	lc_inf[dense_base + i].nzcnt = beg - lc_inf[dense_base + i].cbeg;
+	f->lc_freebeg = beg;
+CLEANUP:
+	EG_RETURN (rval);
+}
+
+static int dense_replace (
+	EGLPNUM_TYPENAME_factor_work * f)
+{
+	int drows = f->drows;
+	int rval = 0;
+	int i;
+
+	for (i = 0; i < drows; i++)
+	{
+		rval = dense_replace_row (f, i);
+		CHECKRVALG (rval, CLEANUP);
+		rval = dense_create_col (f, i);
+		CHECKRVALG (rval, CLEANUP);
+	}
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (f->dmat);
+	f->drows = 0;
+	f->dcols = 0;
+CLEANUP:
+	EG_RETURN (rval);
+}
+
+static int dense_factor (
+	EGLPNUM_TYPENAME_factor_work * f)
+{
+	int r;
+	int c;
+	int rval = 0;
+
+#ifdef TRACK_FACTOR
+#ifdef NOTICE_BLOWUP
+	double tmpsize;
+#endif
+#endif
+
+/*
+    QSlog("dense kernel, %d rows, %d  cols...", f->nstages - f->stage,
+		            f->dim - f->stage);
+*/
+
+	rval = dense_build_matrix (f);
+	CHECKRVALG (rval, CLEANUP);
+
+#ifdef FACTOR_DEBUG
+#if (FACTOR_DEBUG+0>1)
+	MESSAGE (0,"before Dense EGLPNUM_TYPENAME_ILLfactor");
+	dump_matrix (f, 1);
+#endif
+#endif
+
+	while (f->stage < f->nstages)
+	{
+		r = f->stage - f->dense_base;
+		rval = dense_find_pivot (f, &r, &c);
+		if (rval == E_NO_PIVOT)
+		{
+			rval = handle_singularity (f);
+			CHECKRVALG (rval, CLEANUP);
+			return E_SINGULAR_INTERNAL;
+		}
+		else
+		{
+			CHECKRVALG (rval, CLEANUP);
+		}
+#ifdef FACTOR_DEBUG
+#if (FACTOR_DEBUG+0>2)
+		MESSAGE (0,"dense pivot elem: %d %d", r, c);
+#endif
+#endif /* FACTOR_DEBUG */
+		dense_elim (f, r, c);
+
+#ifdef TRACK_FACTOR
+#ifdef NOTICE_BLOWUP
+		tmpsize = f->maxmult * EGLPNUM_TYPENAME_EGlpNumToLf (f->maxelem_orig);
+		if (tmpsize < EGLPNUM_TYPENAME_EGlpNumToLf (f->maxelem_factor) &&
+				EGLPNUM_TYPENAME_EGlpNumIsLess (f->partial_cur, EGLPNUM_TYPENAME_oneLpNum))
+		{
+			return E_FACTOR_BLOWUP;
+		}
+#endif /* NOTICE_BLOWUP */
+#endif /* TRACK_FACTOR */
+
+#ifdef FACTOR_DEBUG
+#if (FACTOR_DEBUG+0>1)
+		MESSAGE (0,"After dense pivot stage %d (%d) of %d (%d)",
+						f->stage - f->dense_base, f->stage,
+						f->nstages - f->dense_base, f->nstages);
+#endif
+#if (FACTOR_DEBUG+0>2)
+		dump_matrix (f, 1);
+#endif
+#endif /* FACTOR_DEBUG */
+	}
+
+#ifdef FACTOR_DEBUG
+	MESSAGE (0,"After dense EGLPNUM_TYPENAME_ILLfactor:\n");
+	dump_matrix (f, 0);
+#endif /* FACTOR_DEBUG */
+
+	rval = dense_replace (f);
+	CHECKRVALG (rval, CLEANUP);
+
+#ifdef FACTOR_DEBUG
+	MESSAGE (0,"After replacement:\n");
+	dump_matrix (f, 0);
+#endif /* FACTOR_DEBUG */
+
+CLEANUP:
+	EG_RETURN (rval);
+}
+
+#ifdef RECORD
+EGioFile_t *fsave = 0;
+int fsavecnt = 0;
+#endif /* RECORD */
+
+static int ILLfactor_try (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int *basis,
+	int *cbeg,
+	int *clen,
+	int *cindx,
+	EGLPNUM_TYPE * ccoef)
+{
+	int rval = 0;
+	int r;
+	int c;
+
+#ifdef TRACK_FACTOR
+#ifdef NOTICE_BLOWUP
+	EGLPNUM_TYPE tmpsize;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (tmpsize);
+#endif
+#endif
+
+#ifdef RECORD
+	{
+		int ncol = 0;
+		int nzcnt = 0;
+		int dim = f->dim;
+		int i;
+		int j;
+		char fnambuf[40];
+
+		for (i = 0; i < dim; i++)
+		{
+			if (basis[i] > ncol)
+				ncol = basis[i];
+		}
+		ncol++;
+		for (i = 0; i < ncol; i++)
+		{
+			nzcnt += clen[i];
+		}
+		if (fsave)
+			EGioClose (fsave);
+#if HAVE_LIBZ
+		sprintf (fnambuf, "prob.mat.%d.gz", fsavecnt);
+#elif HAVE_LIBBZ2
+		sprintf (fnambuf, "prob.mat.%d.bz2", fsavecnt);
+#else
+		sprintf (fnambuf, "prob.mat.%d", fsavecnt);
+#endif
+		fsavecnt++;
+		fsave = EGioOpen (fnambuf, "w");
+		EGioPrintf (fsave, "%d %d %d\n", f->dim, ncol, nzcnt);
+		for (i = 0; i < dim; i++)
+		{
+			EGioPrintf (fsave, "%d ", basis[i]);
+		}
+		EGioPrintf (fsave, "\n");
+		for (i = 0; i < ncol; i++)
+		{
+			EGioPrintf (fsave, "%d", clen[i]);
+			for (j = 0; j < clen[i]; j++)
+			{
+				EGioPrintf (fsave, " %d %.16lg", cindx[cbeg[i] + j],
+								 EGLPNUM_TYPENAME_EGlpNumToLf (ccoef[cbeg[i] + j]));
+			}
+			EGioPrintf (fsave, "\n");
+		}
+		EGioPrintf (fsave, "\n");
+		EGioFlush (fsave);
+	}
+#endif /* RECORD */
+
+	rval = init_matrix (f, basis, cbeg, clen, cindx, ccoef);
+	CHECKRVALG (rval, CLEANUP);
+
+	f->stage = 0;
+	f->nstages = f->dim;
+
+#ifdef FACTOR_DEBUG
+	MESSAGE (0,"Initial matrix:");
+#if (FACTOR_DEBUG+0>1)
+	dump_matrix (f, 0);
+#endif
+#endif /* FACTOR_DEBUG */
+#ifdef FACTOR_STATS
+	QSlog("Initial matrix: ");
+	dump_factor_stats (f);
+#endif /* FACTOR_STATS */
+
+	while (f->stage < f->nstages)
+	{
+		rval = find_pivot (f, &r, &c);
+		if (rval == E_NO_PIVOT)
+		{
+			rval = handle_singularity (f);
+			CHECKRVALG (rval, CLEANUP);
+			return 0;
+		}
+		else
+		{
+			CHECKRVALG (rval, CLEANUP);
+		}
+		if (f->ur_inf[r].pivcnt > f->dense_fract * (f->nstages - f->stage) &&
+				f->uc_inf[c].nzcnt > f->dense_fract * (f->nstages - f->stage) &&
+				f->nstages - f->stage > f->dense_min)
+		{
+			rval = dense_factor (f);
+			if (rval == E_SINGULAR_INTERNAL)
+				return 0;
+			if (rval)
+				return rval;
+			break;
+		}
+#ifdef FACTOR_DEBUG
+		MESSAGE (0,"pivot elem: %d %d", r, c);
+#endif /* FACTOR_DEBUG */
+		rval = elim (f, r, c);
+		CHECKRVALG (rval, CLEANUP);
+
+#ifdef TRACK_FACTOR
+#ifdef NOTICE_BLOWUP
+		EGLPNUM_TYPENAME_EGlpNumSet (tmpsize, f->maxmult);
+		EGLPNUM_TYPENAME_EGlpNumMultTo (tmpsize, f->maxelem_orig);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (tmpsize, f->maxelem_factor) &&
+				EGLPNUM_TYPENAME_EGlpNumIsLess (f->partial_cur, EGLPNUM_TYPENAME_oneLpNum))
+		{
+			return E_FACTOR_BLOWUP;
+		}
+#endif /* NOTICE_BLOWUP */
+#endif /* TRACK_FACTOR */
+
+#ifdef FACTOR_DEBUG
+#if (FACTOR_DEBUG+0>3)
+		MESSAGE (0,"After pivot stage %d of %d", f->stage, f->nstages);
+		dump_matrix (f, 0);
+#endif
+#endif /* FACTOR_DEBUG */
+	}
+
+	rval = build_iteration_u_data (f);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = build_iteration_l_data (f);
+	CHECKRVALG (rval, CLEANUP);
+
+#ifdef TRACK_FACTOR
+#ifdef NOTICE_BLOWUP
+	EGLPNUM_TYPENAME_EGlpNumSet (tmpsize, f->minmult);
+	EGLPNUM_TYPENAME_EGlpNumMultTo (tmpsize, f->maxelem_orig);
+	if (EGLPNUM_TYPENAME_EGlpNumIsLess (f->maxelem_factor, tmpsize) &&
+			EGLPNUM_TYPENAME_EGlpNumIsLess (f->partial_tol, f->partial_cur))
+	{
+		if (EGLPNUM_TYPENAME_EGlpNumIsGreaDbl (f->partial_cur, 0.5))
+		{
+			EGLPNUM_TYPENAME_EGlpNumSet (f->partial_cur, 0.5);
+		}
+		else if (EGLPNUM_TYPENAME_EGlpNumIsGreaDbl (f->partial_cur, 0.25))
+		{
+			EGLPNUM_TYPENAME_EGlpNumSet (f->partial_cur, 0.25);
+		}
+		else if (EGLPNUM_TYPENAME_EGlpNumIsGreaDbl (f->partial_cur, 0.1))
+		{
+			EGLPNUM_TYPENAME_EGlpNumSet (f->partial_cur, 0.1);
+		}
+		else
+		{
+			EGLPNUM_TYPENAME_EGlpNumDivUiTo (f->partial_cur, 10);
+		}
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (f->partial_cur, f->partial_tol))
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (f->partial_cur, f->partial_tol);
+		}
+/*  Bico - comment out for dist 
+        QSlog("factor good, lowering partial tolerance to %.2f",
+                    f->partial_cur);
+*/
+	}
+#endif /* NOTICE_BLOWUP */
+#endif /* TRACK_FACTOR */
+
+#ifdef FACTOR_DEBUG
+	MESSAGE(0,"Factored matrix:");
+#if (FACTOR_DEBUG+0>1)
+	dump_matrix (f, 0);
+#endif
+#endif /* FACTOR_DEBUG */
+
+#ifdef FACTOR_STATS
+	QSlog("Factored matrix: ");
+	dump_factor_stats (f);
+#endif /* FACTOR_STATS */
+CLEANUP:
+#ifdef TRACK_FACTOR
+#ifdef NOTICE_BLOWUP
+	EGLPNUM_TYPENAME_EGlpNumClearVar (tmpsize);
+#endif
+#endif
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLfactor (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int *basis,
+	int *cbeg,
+	int *clen,
+	int *cindx,
+	EGLPNUM_TYPE * ccoef,
+	int *p_nsing,
+	int **p_singr,
+	int **p_singc)
+{
+	int rval;
+
+	f->p_nsing = p_nsing;
+	f->p_singr = p_singr;
+	f->p_singc = p_singc;
+	*p_nsing = 0;
+
+AGAIN:
+	rval = ILLfactor_try (f, basis, cbeg, clen, cindx, ccoef);
+	if (rval == E_FACTOR_BLOWUP)
+	{
+		if (EGLPNUM_TYPENAME_EGlpNumIsLessDbl (f->partial_cur, 0.1))
+		{
+			EGLPNUM_TYPENAME_EGlpNumMultUiTo (f->partial_cur, 10);
+		}
+		else if (EGLPNUM_TYPENAME_EGlpNumIsLessDbl (f->partial_cur, 0.25))
+		{
+			EGLPNUM_TYPENAME_EGlpNumSet (f->partial_cur, 0.25);
+		}
+		else if (EGLPNUM_TYPENAME_EGlpNumIsLessDbl (f->partial_cur, 0.5))
+		{
+			EGLPNUM_TYPENAME_EGlpNumSet (f->partial_cur, 0.5);
+		}
+		else if (EGLPNUM_TYPENAME_EGlpNumIsLess (f->partial_cur, EGLPNUM_TYPENAME_oneLpNum))
+		{
+			EGLPNUM_TYPENAME_EGlpNumOne (f->partial_cur);
+		}
+		else
+		{
+			EG_RETURN (rval);
+		}
+/* Bico - comment out for dist
+        QSlog("factor blowup, changing partial tolerance to %.2f",
+                    f->partial_cur);
+*/
+		goto AGAIN;
+	}
+	EG_RETURN (rval);
+}
+
+static void ILLfactor_ftranl (
+	EGLPNUM_TYPENAME_factor_work * f,
+	EGLPNUM_TYPE * a)
+{
+	int *lcindx = f->lcindx;
+	EGLPNUM_TYPENAME_lc_info *lc_inf = f->lc_inf;
+	EGLPNUM_TYPE *lccoef = f->lccoef;
+	int dim = f->dim;
+	int beg;
+	int nzcnt;
+	int i;
+	int j;
+	EGLPNUM_TYPE v;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+	for (i = 0; i < dim; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (v, a[lc_inf[i].c]);
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (v))
+		{
+			nzcnt = lc_inf[i].nzcnt;
+			beg = lc_inf[i].cbeg;
+			for (j = 0; j < nzcnt; j++)
+			{
+				EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (a[lcindx[beg + j]], v, lccoef[beg + j]);
+			}
+		}
+#ifdef SOLVE_DEBUG
+#if (SOLVE_DEBUG+0 > 1)
+		QSlog("EGLPNUM_TYPENAME_ILLfactor_ftran a after l %d:", i);
+		for (j = 0; j < f->dim; j++)
+		{
+			QSlog(" %.3f", EGLPNUM_TYPENAME_EGlpNumToLf (a[j]));
+		}
+		MESSAGE(0," ");
+#endif
+#endif /* SOLVE_DEBUG */
+	}
+#ifdef SOLVE_DEBUG
+#if (SOLVE_DEBUG+0 <= 1)
+	QSlog("EGLPNUM_TYPENAME_ILLfactor_ftran a after l:");
+	for (j = 0; j < f->dim; j++)
+	{
+		QSlog(" %.3f", EGLPNUM_TYPENAME_EGlpNumToLf (a[j]));
+	}
+#endif
+#endif /* SOLVE_DEBUG */
+	EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+
+#if 0
+static void ftranl3_delay (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int c)
+{
+	EGLPNUM_TYPENAME_lc_info *lc_inf = f->lc_inf;
+	int nzcnt;
+	int *indx;
+	int i;
+
+	c = lc_inf[c].crank;
+	nzcnt = lc_inf[c].nzcnt;
+	indx = f->lcindx + lc_inf[c].cbeg;
+	for (i = 0; i < nzcnt; i++)
+	{
+		c = indx[i];
+		if (lc_inf[c].delay++ == 0)
+		{
+			ftranl3_delay (f, c);
+		}
+	}
+}
+#endif
+
+static void ftranl3_delay2 (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int c)
+{
+	EGLPNUM_TYPENAME_lc_info *lc_inf = f->lc_inf;
+	int nzcnt;
+	int *indx;
+	int i;
+	int last;
+
+	do
+	{
+		c = lc_inf[c].crank;
+		nzcnt = lc_inf[c].nzcnt;
+		indx = f->lcindx + lc_inf[c].cbeg;
+		last = -1;
+		for (i = 0; i < nzcnt; i++)
+		{
+			c = indx[i];
+			if (lc_inf[c].delay++ == 0)
+			{
+				if (last >= 0)
+				{
+					ftranl3_delay2 (f, last);
+				}
+				last = c;
+			}
+		}
+		c = last;
+	} while (c >= 0);
+}
+
+#if 0
+static void ftranl3_process (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int c,
+	EGLPNUM_TYPENAME_svector * x)
+{
+	EGLPNUM_TYPENAME_lc_info *lc_inf = f->lc_inf;
+	EGLPNUM_TYPE *work = f->work_coef;
+	int nzcnt;
+	int *indx;
+	int i;
+	EGLPNUM_TYPE *coef;
+	EGLPNUM_TYPE v;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+	EGLPNUM_TYPENAME_EGlpNumCopy (v, work[c]);
+	EGLPNUM_TYPENAME_EGlpNumZero (work[c]);
+	if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (v))
+	{
+		x->indx[x->nzcnt] = c;
+		EGLPNUM_TYPENAME_EGlpNumCopy (x->coef[x->nzcnt], v);
+		x->nzcnt++;
+	}
+	c = lc_inf[c].crank;
+	nzcnt = lc_inf[c].nzcnt;
+	indx = f->lcindx + lc_inf[c].cbeg;
+	coef = f->lccoef + lc_inf[c].cbeg;
+	for (i = 0; i < nzcnt; i++)
+	{
+		c = indx[i];
+		EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (work[c], v, coef[i]);
+		if (--lc_inf[c].delay == 0)
+		{
+			ftranl3_process (f, c, x);
+		}
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+#endif
+
+static void ftranl3_process2 (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int c,
+	EGLPNUM_TYPENAME_svector * x)
+{
+	EGLPNUM_TYPENAME_lc_info *lc_inf = f->lc_inf;
+	EGLPNUM_TYPE *work = f->work_coef;
+	int nzcnt;
+	int *indx;
+	EGLPNUM_TYPE *coef;
+	int i;
+	int last;
+	EGLPNUM_TYPE v;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+	do
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (v, work[c]);
+		EGLPNUM_TYPENAME_EGlpNumZero (work[c]);
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (v))
+		{
+			x->indx[x->nzcnt] = c;
+			EGLPNUM_TYPENAME_EGlpNumCopy (x->coef[x->nzcnt], v);
+			x->nzcnt++;
+		}
+		c = lc_inf[c].crank;
+		nzcnt = lc_inf[c].nzcnt;
+		indx = f->lcindx + lc_inf[c].cbeg;
+		coef = f->lccoef + lc_inf[c].cbeg;
+		last = -1;
+		for (i = 0; i < nzcnt; i++)
+		{
+			c = indx[i];
+			EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (work[c], v, coef[i]);
+			if (--lc_inf[c].delay == 0)
+			{
+				if (last >= 0)
+				{
+					ftranl3_process2 (f, last, x);
+				}
+				last = c;
+			}
+		}
+		c = last;
+	} while (c >= 0);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+
+static void ILLfactor_ftranl3 (
+	EGLPNUM_TYPENAME_factor_work * f,
+	EGLPNUM_TYPENAME_svector * a,
+	EGLPNUM_TYPENAME_svector * x)
+{
+	EGLPNUM_TYPE *work = f->work_coef;
+	int anzcnt = a->nzcnt;
+	int *aindx = a->indx;
+	EGLPNUM_TYPE *acoef = a->coef;
+	EGLPNUM_TYPENAME_lc_info *lc_inf = f->lc_inf;
+	int i;
+
+	for (i = 0; i < anzcnt; i++)
+	{
+		if (lc_inf[aindx[i]].delay++ == 0)
+		{
+			ftranl3_delay2 (f, aindx[i]);
+		}
+		EGLPNUM_TYPENAME_EGlpNumCopy (work[aindx[i]], acoef[i]);
+	}
+	x->nzcnt = 0;
+	for (i = 0; i < anzcnt; i++)
+	{
+		if (--lc_inf[aindx[i]].delay == 0)
+		{
+			ftranl3_process2 (f, aindx[i], x);
+		}
+	}
+#ifdef SOLVE_DEBUG
+	QSlog("EGLPNUM_TYPENAME_ILLfactor_ftran x after l3:");
+	for (i = 0; i < x->nzcnt; i++)
+	{
+		QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (x->coef[i]), x->indx[i]);
+	}
+#endif /* SOLVE_DEBUG */
+}
+
+static void ILLfactor_ftrane (
+	EGLPNUM_TYPENAME_factor_work * f,
+	EGLPNUM_TYPE * a)
+{
+	int *erindx = f->erindx;
+	EGLPNUM_TYPE *ercoef = f->ercoef;
+	EGLPNUM_TYPENAME_er_info *er_inf = f->er_inf;
+	int etacnt = f->etacnt;
+	int beg;
+	int nzcnt;
+	int i;
+	int j;
+	EGLPNUM_TYPE v;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+	for (i = 0; i < etacnt; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (v, a[er_inf[i].r]);
+		nzcnt = er_inf[i].nzcnt;
+		beg = er_inf[i].rbeg;
+		for (j = 0; j < nzcnt; j++)
+		{
+			EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (v, ercoef[beg + j], a[erindx[beg + j]]);
+		}
+		EGLPNUM_TYPENAME_EGlpNumCopy (a[er_inf[i].r], v);
+#ifdef SOLVE_DEBUG
+#if (SOLVE_DEBUG+0 > 1)
+		QSlog("EGLPNUM_TYPENAME_ILLfactor_ftran a after eta %d:", i);
+		for (j = 0; j < f->dim; j++)
+		{
+			QSlog(" %.3f", EGLPNUM_TYPENAME_EGlpNumToLf (a[j]));
+		}
+#endif
+#endif /* SOLVE_DEBUG */
+	}
+#ifdef SOLVE_DEBUG
+#if (SOLVE_DEBUG+0 <= 1)
+	QSlog("EGLPNUM_TYPENAME_ILLfactor_ftran a after eta:");
+	for (j = 0; j < f->dim; j++)
+	{
+		QSlog(" %.3f", EGLPNUM_TYPENAME_EGlpNumToLf (a[j]));
+	}
+#endif
+#endif /* SOLVE_DEBUG */
+	EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+
+static void ILLfactor_ftrane2 (
+	EGLPNUM_TYPENAME_factor_work * f,
+	EGLPNUM_TYPENAME_svector * a)
+{
+	int *erindx = f->erindx;
+	EGLPNUM_TYPE *ercoef = f->ercoef;
+	EGLPNUM_TYPENAME_er_info *er_inf = f->er_inf;
+	int etacnt = f->etacnt;
+	int beg;
+	int nzcnt;
+	int anzcnt = a->nzcnt;
+	int *aindx = a->indx;
+	EGLPNUM_TYPE *acoef = a->coef;
+	EGLPNUM_TYPE *work_coef = f->work_coef;
+	int *work_indx = f->work_indx;
+	int i;
+	int j;
+	int r;
+	EGLPNUM_TYPE v;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+	for (i = 0; i < anzcnt; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
+		work_indx[aindx[i]] = i + 1;
+	}
+	for (i = 0; i < etacnt; i++)
+	{
+		r = er_inf[i].r;
+		EGLPNUM_TYPENAME_EGlpNumCopy (v, work_coef[r]);
+		nzcnt = er_inf[i].nzcnt;
+		beg = er_inf[i].rbeg;
+		for (j = 0; j < nzcnt; j++)
+		{
+			EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (v, ercoef[beg + j], work_coef[erindx[beg + j]]);
+		}
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (v))
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (work_coef[r], v);
+			if (work_indx[r] == 0)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (acoef[anzcnt], v);
+				aindx[anzcnt] = r;
+				work_indx[r] = anzcnt + 1;
+				anzcnt++;
+			}
+			else
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (acoef[work_indx[r] - 1], v);
+			}
+		}
+		else
+		{
+			EGLPNUM_TYPENAME_EGlpNumZero (work_coef[r]);
+			if (work_indx[r])
+			{
+				EGLPNUM_TYPENAME_EGlpNumZero (acoef[work_indx[r] - 1]);
+			}
+		}
+#ifdef SOLVE_DEBUG
+#if (SOLVE_DEBUG+0 > 1)
+		QSlog("EGLPNUM_TYPENAME_ILLfactor_ftran a after eta2 %d:", i);
+		for (j = 0; j < anzcnt; j++)
+		{
+			QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (acoef[j]), aindx[j]);
+		}
+#endif
+#endif /* SOLVE_DEBUG */
+	}
+	i = 0;
+	while (i < anzcnt)
+	{
+		EGLPNUM_TYPENAME_EGlpNumZero (work_coef[aindx[i]]);
+		work_indx[aindx[i]] = 0;
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (acoef[i], f->fzero_tol))
+		{
+			/*if (acoef[i] > fzero_tol || acoef[i] < -fzero_tol) */
+			i++;
+		}
+		else
+		{
+			--anzcnt;
+			EGLPNUM_TYPENAME_EGlpNumCopy (acoef[i], acoef[anzcnt]);
+			aindx[i] = aindx[anzcnt];
+		}
+	}
+	a->nzcnt = anzcnt;
+
+#ifdef SOLVE_DEBUG
+#if (SOLVE_DEBUG+0 <= 1)
+	QSlog("EGLPNUM_TYPENAME_ILLfactor_ftran a after eta2:");
+	for (j = 0; j < anzcnt; j++)
+	{
+		QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (acoef[j]), aindx[j]);
+	}
+#endif
+#endif /* SOLVE_DEBUG */
+	EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+
+static void ILLfactor_ftranu (
+	EGLPNUM_TYPENAME_factor_work * f,
+	EGLPNUM_TYPE * a,
+	EGLPNUM_TYPENAME_svector * x)
+{
+	int *ucindx = f->ucindx;
+	EGLPNUM_TYPE *uccoef = f->uccoef;
+	EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+	int *cperm = f->cperm;
+	int *rperm = f->rperm;
+	int dim = f->dim;
+	int xnzcnt = 0;
+	int *xindx = x->indx;
+	EGLPNUM_TYPE *xcoef = x->coef;
+	int nzcnt;
+	int beg;
+	int i;
+	int j;
+	EGLPNUM_TYPE v;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+	for (i = dim - 1; i >= 0; i--)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (v, a[rperm[i]]);
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (v))	/*((v = a[rperm[i]]) != 0.0) */
+		{
+			j = cperm[i];
+			beg = uc_inf[j].cbeg;
+			EGLPNUM_TYPENAME_EGlpNumDivTo (v, uccoef[beg]);
+			if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (v, f->szero_tol))
+			{
+				/*if (v > szero_tol || v < -szero_tol) */
+				xindx[xnzcnt] = j;
+				EGLPNUM_TYPENAME_EGlpNumCopy (xcoef[xnzcnt], v);
+				xnzcnt++;
+			}
+			nzcnt = uc_inf[j].nzcnt;
+			for (j = 1; j < nzcnt; j++)
+			{
+				EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (a[ucindx[beg + j]], v, uccoef[beg + j]);
+			}
+			EGLPNUM_TYPENAME_EGlpNumZero (a[rperm[i]]);
+		}
+	}
+	x->nzcnt = xnzcnt;
+#ifdef SOLVE_DEBUG
+	QSlog("EGLPNUM_TYPENAME_ILLfactor_ftran x after u:");
+	for (j = 0; j < x->nzcnt; j++)
+	{
+		QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (x->coef[j]), x->indx[j]);
+	}
+#endif /* SOLVE_DEBUG */
+	EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+
+
+#if 0
+static void ftranu3_delay (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int c)
+{
+	EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+	int nzcnt;
+	int *indx;
+	int i;
+
+	c = f->cperm[f->rrank[c]];
+	nzcnt = uc_inf[c].nzcnt;
+	indx = f->ucindx + uc_inf[c].cbeg;
+	for (i = 1; i < nzcnt; i++)
+	{
+		c = indx[i];
+		if (uc_inf[c].delay++ == 0)
+		{
+			ftranu3_delay (f, c);
+		}
+	}
+}
+#endif
+
+static void ftranu3_delay2 (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int c)
+{
+	EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+	int nzcnt;
+	int *indx;
+	int i;
+	int last;
+
+	do
+	{
+		c = f->cperm[f->rrank[c]];
+		nzcnt = uc_inf[c].nzcnt;
+		indx = f->ucindx + uc_inf[c].cbeg;
+		last = -1;
+		for (i = 1; i < nzcnt; i++)
+		{
+			c = indx[i];
+			if (uc_inf[c].delay++ == 0)
+			{
+				if (last >= 0)
+				{
+					ftranu3_delay2 (f, last);
+				}
+				last = c;
+			}
+		}
+		c = last;
+	} while (c >= 0);
+}
+
+#if 0
+static void ftranu3_process (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int c,
+	EGLPNUM_TYPENAME_svector * x)
+{
+	EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+	EGLPNUM_TYPE *work = f->work_coef;
+	int nzcnt;
+	int *indx;
+	EGLPNUM_TYPE *coef;
+	int i;
+	EGLPNUM_TYPE v;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+	EGLPNUM_TYPENAME_EGlpNumCopy (v, work[c]);
+	EGLPNUM_TYPENAME_EGlpNumZero (work[c]);
+	c = f->cperm[f->rrank[c]];
+	nzcnt = uc_inf[c].nzcnt;
+	indx = f->ucindx + uc_inf[c].cbeg;
+	coef = f->uccoef + uc_inf[c].cbeg;
+	EGLPNUM_TYPENAME_EGlpNumDivTo (v, coef[0]);
+	if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (v, f->szero_tol))
+		/*if (v > szero_tol || v < -szero_tol) */
+	{
+		x->indx[x->nzcnt] = c;
+		EGLPNUM_TYPENAME_EGlpNumCopy (x->coef[x->nzcnt], v);
+		x->nzcnt++;
+	}
+	for (i = 1; i < nzcnt; i++)
+	{
+		c = indx[i];
+		EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (work[c], v, coef[i]);
+		if (--uc_inf[c].delay == 0)
+		{
+			ftranu3_process (f, c, x);
+		}
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+#endif
+
+static void ftranu3_process2 (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int c,
+	EGLPNUM_TYPENAME_svector * x)
+{
+	EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+	EGLPNUM_TYPE *work = f->work_coef;
+	int nzcnt;
+	int *indx;
+	EGLPNUM_TYPE *coef;
+	int i;
+	int last;
+	EGLPNUM_TYPE v;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+	do
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (v, work[c]);
+		EGLPNUM_TYPENAME_EGlpNumZero (work[c]);
+		c = f->cperm[f->rrank[c]];
+		nzcnt = uc_inf[c].nzcnt;
+		indx = f->ucindx + uc_inf[c].cbeg;
+		coef = f->uccoef + uc_inf[c].cbeg;
+		EGLPNUM_TYPENAME_EGlpNumDivTo (v, coef[0]);
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (v, f->szero_tol))
+			/*if (v > szero_tol || v < -szero_tol) */
+		{
+			x->indx[x->nzcnt] = c;
+			EGLPNUM_TYPENAME_EGlpNumCopy (x->coef[x->nzcnt], v);
+			x->nzcnt++;
+		}
+		last = -1;
+		for (i = 1; i < nzcnt; i++)
+		{
+			c = indx[i];
+			EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (work[c], v, coef[i]);
+			if (--uc_inf[c].delay == 0)
+			{
+				if (last >= 0)
+				{
+					ftranu3_process2 (f, last, x);
+				}
+				last = c;
+			}
+		}
+		c = last;
+	} while (c >= 0);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+
+static void ILLfactor_ftranu3 (
+	EGLPNUM_TYPENAME_factor_work * f,
+	EGLPNUM_TYPENAME_svector * a,
+	EGLPNUM_TYPENAME_svector * x)
+{
+	EGLPNUM_TYPE *work = f->work_coef;
+	int anzcnt = a->nzcnt;
+	int *aindx = a->indx;
+	EGLPNUM_TYPE *acoef = a->coef;
+	EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+	int i;
+
+	for (i = 0; i < anzcnt; i++)
+	{
+		if (uc_inf[aindx[i]].delay++ == 0)
+		{
+			ftranu3_delay2 (f, aindx[i]);
+		}
+		EGLPNUM_TYPENAME_EGlpNumCopy (work[aindx[i]], acoef[i]);
+	}
+	x->nzcnt = 0;
+	for (i = 0; i < anzcnt; i++)
+	{
+		if (--uc_inf[aindx[i]].delay == 0)
+		{
+			ftranu3_process2 (f, aindx[i], x);
+		}
+	}
+#ifdef SOLVE_DEBUG
+	QSlog("EGLPNUM_TYPENAME_ILLfactor_ftran x after u3:");
+	for (i = 0; i < x->nzcnt; i++)
+	{
+		QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (x->coef[i]), x->indx[i]);
+	}
+#endif /* SOLVE_DEBUG */
+}
+
+/* EGLPNUM_TYPENAME_ILLfactor_ftran solves Bx=a for x */
+void EGLPNUM_TYPENAME_ILLfactor_ftran (
+	EGLPNUM_TYPENAME_factor_work * f,
+	EGLPNUM_TYPENAME_svector * a,
+	EGLPNUM_TYPENAME_svector * x)
+{
+	int i;
+	int nzcnt;
+	int sparse;
+	int *aindx;
+	EGLPNUM_TYPE *acoef;
+	EGLPNUM_TYPE *work_coef = f->work_coef;
+
+#ifdef RECORD
+	{
+		EGioPrintf (fsave, "f %d", a->nzcnt);
+		for (i = 0; i < a->nzcnt; i++)
+		{
+			EGioPrintf (fsave, " %d %.16e", a->indx[i], EGLPNUM_TYPENAME_EGlpNumToLf (a->coef[i]));
+		}
+		EGioPrintf (fsave, "\n");
+		EGioFlush (fsave);
+	}
+#endif /* RECORD */
+#ifdef DEBUG_FACTOR
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLfactor_ftran a:");
+		for (i = 0; i < a->nzcnt; i++)
+		{
+			QSlog(" %d %la", a->indx[i], EGLPNUM_TYPENAME_EGlpNumToLf (a->coef[i]));
+		}
+	}
+#endif /* DEBUG_FACTOR */
+
+	if (a->nzcnt >= SPARSE_FACTOR * f->dim)
+	{
+		nzcnt = a->nzcnt;
+		aindx = a->indx;
+		acoef = a->coef;
+		for (i = 0; i < nzcnt; i++)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
+		}
+		sparse = 0;
+	}
+	else
+	{
+		sparse = 1;
+	}
+
+	if (sparse)
+	{
+		ILLfactor_ftranl3 (f, a, &f->xtmp);
+		if (f->xtmp.nzcnt >= SPARSE_FACTOR * f->dim)
+		{
+			nzcnt = f->xtmp.nzcnt;
+			aindx = f->xtmp.indx;
+			acoef = f->xtmp.coef;
+
+			for (i = 0; i < nzcnt; i++)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
+			}
+			sparse = 0;
+		}
+	}
+	else
+	{
+		ILLfactor_ftranl (f, work_coef);
+	}
+
+	if (sparse)
+	{
+		ILLfactor_ftrane2 (f, &f->xtmp);
+		if (f->xtmp.nzcnt >= SPARSE_FACTOR * f->dim)
+		{
+			nzcnt = f->xtmp.nzcnt;
+			aindx = f->xtmp.indx;
+			acoef = f->xtmp.coef;
+
+			for (i = 0; i < nzcnt; i++)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
+			}
+			sparse = 0;
+		}
+	}
+	else
+	{
+		ILLfactor_ftrane (f, work_coef);
+	}
+
+	if (sparse)
+	{
+		ILLfactor_ftranu3 (f, &f->xtmp, x);
+	}
+	else
+	{
+		ILLfactor_ftranu (f, work_coef, x);
+	}
+
+#ifdef SORT_RESULTS
+	sort_vector (x);
+#endif
+
+#ifdef DEBUG_FACTOR
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLfactor_ftran x:");
+		for (i = 0; i < x->nzcnt; i++)
+		{
+			QSlog(" %d %la", x->indx[i], EGLPNUM_TYPENAME_EGlpNumToLf (x->coef[i]));
+		}
+	}
+#endif /* DEBUG_FACTOR */
+	return;
+}
+
+/* EGLPNUM_TYPENAME_ILLfactor_ftran_update solves Bx=a for x, and also returns upd, where Ux=upd */
+void EGLPNUM_TYPENAME_ILLfactor_ftran_update (
+	EGLPNUM_TYPENAME_factor_work * f,
+	EGLPNUM_TYPENAME_svector * a,
+	EGLPNUM_TYPENAME_svector * upd,
+	EGLPNUM_TYPENAME_svector * x)
+{
+	int i;
+	int nzcnt;
+	int dim;
+	int sparse;
+	int *aindx;
+	EGLPNUM_TYPE *acoef;
+	EGLPNUM_TYPE *work_coef = f->work_coef;
+
+#ifdef RECORD
+	{
+		EGioPrintf (fsave, "F %d", a->nzcnt);
+		for (i = 0; i < a->nzcnt; i++)
+		{
+			EGioPrintf (fsave, " %d %.16e", a->indx[i], EGLPNUM_TYPENAME_EGlpNumToLf (a->coef[i]));
+		}
+		EGioPrintf (fsave, "\n");
+		EGioFlush (fsave);
+	}
+#endif /* RECORD */
+#ifdef DEBUG_FACTOR
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLfactor_ftran_update a:");
+		for (i = 0; i < a->nzcnt; i++)
+		{
+			QSlog(" %d %.3f", a->indx[i], EGLPNUM_TYPENAME_EGlpNumToLf (a->coef[i]));
+		}
+	}
+#endif /* DEBUG_FACTOR */
+
+	if (a->nzcnt >= SPARSE_FACTOR * f->dim)
+	{
+		aindx = a->indx;
+		acoef = a->coef;
+		nzcnt = a->nzcnt;
+
+		for (i = 0; i < nzcnt; i++)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
+		}
+		sparse = 0;
+	}
+	else
+	{
+		sparse = 1;
+	}
+
+	if (sparse)
+	{
+		ILLfactor_ftranl3 (f, a, upd);
+		if (upd->nzcnt >= SPARSE_FACTOR * f->dim)
+		{
+			nzcnt = upd->nzcnt;
+			aindx = upd->indx;
+			acoef = upd->coef;
+
+			for (i = 0; i < nzcnt; i++)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
+			}
+			sparse = 0;
+		}
+	}
+	else
+	{
+		ILLfactor_ftranl (f, work_coef);
+	}
+
+	if (sparse)
+	{
+		ILLfactor_ftrane2 (f, upd);
+		if (upd->nzcnt >= SPARSE_FACTOR * f->dim)
+		{
+			nzcnt = upd->nzcnt;
+			aindx = upd->indx;
+			acoef = upd->coef;
+
+			for (i = 0; i < nzcnt; i++)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
+			}
+			sparse = 0;
+		}
+	}
+	else
+	{
+		ILLfactor_ftrane (f, work_coef);
+		nzcnt = 0;
+		dim = f->dim;
+		aindx = upd->indx;
+		acoef = upd->coef;
+		for (i = 0; i < dim; i++)
+		{
+			if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (work_coef[i]))
+			{
+				if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (work_coef[i], f->szero_tol))
+					/*if(work_coef[i] > szero_tol || work_coef[i] < -szero_tol) */
+				{
+					aindx[nzcnt] = i;
+					EGLPNUM_TYPENAME_EGlpNumCopy (acoef[nzcnt], work_coef[i]);
+					nzcnt++;
+				}
+			}
+		}
+		upd->nzcnt = nzcnt;
+	}
+
+	if (sparse)
+	{
+		ILLfactor_ftranu3 (f, upd, x);
+	}
+	else
+	{
+		ILLfactor_ftranu (f, work_coef, x);
+	}
+
+#ifdef SORT_RESULTS
+	sort_vector (upd);
+	sort_vector (x);
+#endif
+
+#ifdef DEBUG_FACTOR
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLfactor_ftran update x:");
+		for (i = 0; i < x->nzcnt; i++)
+		{
+			QSlog(" %d %.3f", x->indx[i], EGLPNUM_TYPENAME_EGlpNumToLf (x->coef[i]));
+		}
+	}
+#endif /* DEBUG_FACTOR */
+}
+
+
+static void ILLfactor_btranl2 (
+	EGLPNUM_TYPENAME_factor_work * f,
+	EGLPNUM_TYPE * x)
+{
+	int *lrindx = f->lrindx;
+	EGLPNUM_TYPE *lrcoef = f->lrcoef;
+	EGLPNUM_TYPENAME_lr_info *lr_inf = f->lr_inf;
+	int dim = f->dim;
+	int nzcnt;
+	int beg;
+	int i;
+	int j;
+	EGLPNUM_TYPE v;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+	for (i = dim - 1; i >= 0; i--)
+	{
+#ifdef SOLVE_DEBUG
+#if (SOLVE_DEBUG+0 > 1)
+		QSlog("EGLPNUM_TYPENAME_ILLfactor_btran x before l2 %d:", i);
+		for (j = 0; j < f->dim; j++)
+		{
+			QSlog(" %.3f", EGLPNUM_TYPENAME_EGlpNumToLf (x[j]));
+		}
+#endif
+#endif /* SOLVE_DEBUG */
+		EGLPNUM_TYPENAME_EGlpNumCopy (v, x[lr_inf[i].r]);
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (v))
+		{
+			nzcnt = lr_inf[i].nzcnt;
+			beg = lr_inf[i].rbeg;
+			for (j = 0; j < nzcnt; j++)
+			{
+				EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (x[lrindx[beg + j]], v, lrcoef[beg + j]);
+			}
+		}
+	}
+#ifdef SOLVE_DEBUG
+#if (SOLVE_DEBUG+0 <= 1)
+	QSlog("EGLPNUM_TYPENAME_ILLfactor_btran x after l2:");
+	for (j = 0; j < f->dim; j++)
+	{
+		QSlog(" %.3f", EGLPNUM_TYPENAME_EGlpNumToLf (x[j]));
+	}
+#endif
+#endif /* SOLVE_DEBUG */
+	EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+
+#if 0
+static void btranl3_delay (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int r)
+{
+	EGLPNUM_TYPENAME_lr_info *lr_inf = f->lr_inf;
+	int nzcnt;
+	int *indx;
+	int i;
+
+	r = lr_inf[r].rrank;
+	nzcnt = lr_inf[r].nzcnt;
+	indx = f->lrindx + lr_inf[r].rbeg;
+	for (i = 0; i < nzcnt; i++)
+	{
+		r = indx[i];
+		if (lr_inf[r].delay++ == 0)
+		{
+			btranl3_delay (f, r);
+		}
+	}
+}
+#endif
+
+static void btranl3_delay2 (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int r)
+{
+	EGLPNUM_TYPENAME_lr_info *lr_inf = f->lr_inf;
+	int nzcnt;
+	int *indx;
+	int i;
+	int last;
+
+	do
+	{
+		r = lr_inf[r].rrank;
+		nzcnt = lr_inf[r].nzcnt;
+		indx = f->lrindx + lr_inf[r].rbeg;
+		last = -1;
+		for (i = 0; i < nzcnt; i++)
+		{
+			r = indx[i];
+			if (lr_inf[r].delay++ == 0)
+			{
+				if (last >= 0)
+				{
+					btranl3_delay2 (f, last);
+				}
+				last = r;
+			}
+		}
+		r = last;
+	} while (r >= 0);
+}
+
+#if 0
+static void btranl3_process (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int r,
+	EGLPNUM_TYPENAME_svector * x)
+{
+	EGLPNUM_TYPENAME_lr_info *lr_inf = f->lr_inf;
+	EGLPNUM_TYPE *work = f->work_coef;
+	int nzcnt;
+	int *indx;
+	EGLPNUM_TYPE *coef;
+	int i;
+	EGLPNUM_TYPE v;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+	EGLPNUM_TYPENAME_EGlpNumCopy (v, work[r]);
+	EGLPNUM_TYPENAME_EGlpNumZero (work[r]);
+	if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (v, f->szero_tol))
+		/*if (v > szero_tol || v < -szero_tol) */
+	{
+		x->indx[x->nzcnt] = r;
+		EGLPNUM_TYPENAME_EGlpNumCopy (x->coef[x->nzcnt], v);
+		x->nzcnt++;
+	}
+	r = lr_inf[r].rrank;
+	nzcnt = lr_inf[r].nzcnt;
+	indx = f->lrindx + lr_inf[r].rbeg;
+	coef = f->lrcoef + lr_inf[r].rbeg;
+	for (i = 0; i < nzcnt; i++)
+	{
+		r = indx[i];
+		EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (work[r], v, coef[i]);
+		if (--lr_inf[r].delay == 0)
+		{
+			btranl3_process (f, r, x);
+		}
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+#endif
+
+static void btranl3_process2 (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int r,
+	EGLPNUM_TYPENAME_svector * x)
+{
+	EGLPNUM_TYPENAME_lr_info *lr_inf = f->lr_inf;
+	EGLPNUM_TYPE *work = f->work_coef;
+	int nzcnt;
+	int *indx;
+	EGLPNUM_TYPE *coef;
+	int i;
+	int last;
+	EGLPNUM_TYPE v;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+	do
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (v, work[r]);
+		EGLPNUM_TYPENAME_EGlpNumZero (work[r]);
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (v, f->szero_tol))
+			/*if (v > szero_tol || v < -szero_tol) */
+		{
+			x->indx[x->nzcnt] = r;
+			EGLPNUM_TYPENAME_EGlpNumCopy (x->coef[x->nzcnt], v);
+			x->nzcnt++;
+		}
+		r = lr_inf[r].rrank;
+		nzcnt = lr_inf[r].nzcnt;
+		indx = f->lrindx + lr_inf[r].rbeg;
+		coef = f->lrcoef + lr_inf[r].rbeg;
+		last = -1;
+		for (i = 0; i < nzcnt; i++)
+		{
+			r = indx[i];
+			EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (work[r], v, coef[i]);
+			if (--lr_inf[r].delay == 0)
+			{
+				if (last >= 0)
+				{
+					btranl3_process2 (f, last, x);
+				}
+				last = r;
+			}
+		}
+		r = last;
+	} while (r >= 0);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+
+static void ILLfactor_btranl3 (
+	EGLPNUM_TYPENAME_factor_work * f,
+	EGLPNUM_TYPENAME_svector * a,
+	EGLPNUM_TYPENAME_svector * x)
+{
+	EGLPNUM_TYPE *work = f->work_coef;
+	int anzcnt = a->nzcnt;
+	int *aindx = a->indx;
+	EGLPNUM_TYPE *acoef = a->coef;
+	EGLPNUM_TYPENAME_lr_info *lr_inf = f->lr_inf;
+	int i;
+
+	for (i = 0; i < anzcnt; i++)
+	{
+		if (lr_inf[aindx[i]].delay++ == 0)
+		{
+			btranl3_delay2 (f, aindx[i]);
+		}
+		EGLPNUM_TYPENAME_EGlpNumCopy (work[aindx[i]], acoef[i]);
+	}
+	x->nzcnt = 0;
+	for (i = 0; i < anzcnt; i++)
+	{
+		if (--lr_inf[aindx[i]].delay == 0)
+		{
+			btranl3_process2 (f, aindx[i], x);
+		}
+	}
+#ifdef SOLVE_DEBUG
+	QSlog("EGLPNUM_TYPENAME_ILLfactor_btran x after l3:");
+	for (i = 0; i < x->nzcnt; i++)
+	{
+		QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (x->coef[i]), x->indx[i]);
+	}
+#endif /* SOLVE_DEBUG */
+}
+
+static void ILLfactor_btrane (
+	EGLPNUM_TYPENAME_factor_work * f,
+	EGLPNUM_TYPE * x)
+{
+	int *erindx = f->erindx;
+	EGLPNUM_TYPE *ercoef = f->ercoef;
+	EGLPNUM_TYPENAME_er_info *er_inf = f->er_inf;
+	int etacnt = f->etacnt;
+	int beg;
+	int nzcnt;
+	int i;
+	int j;
+	EGLPNUM_TYPE v;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+	for (i = etacnt - 1; i >= 0; i--)
+	{
+#ifdef SOLVE_DEBUG
+#if (SOLVE_DEBUG+0 > 1)
+		QSlog("EGLPNUM_TYPENAME_ILLfactor_btran x before eta %d:", i);
+		for (j = 0; j < f->dim; j++)
+		{
+			QSlog(" %.3f", EGLPNUM_TYPENAME_EGlpNumToLf (x[j]));
+		}
+#endif
+#endif /* SOLVE_DEBUG */
+		EGLPNUM_TYPENAME_EGlpNumCopy (v, x[er_inf[i].r]);
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (v))
+		{
+			nzcnt = er_inf[i].nzcnt;
+			beg = er_inf[i].rbeg;
+			for (j = 0; j < nzcnt; j++)
+			{
+				EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (x[erindx[beg + j]], v, ercoef[beg + j]);
+			}
+		}
+	}
+#ifdef SOLVE_DEBUG
+#if (SOLVE_DEBUG+0 <= 1)
+	QSlog("EGLPNUM_TYPENAME_ILLfactor_btran x after eta:");
+	for (j = 0; j < f->dim; j++)
+	{
+		QSlog(" %.3f", EGLPNUM_TYPENAME_EGlpNumToLf (x[j]));
+	}
+#endif
+#endif /* SOLVE_DEBUG */
+	EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+
+static void ILLfactor_btrane2 (
+	EGLPNUM_TYPENAME_factor_work * f,
+	EGLPNUM_TYPENAME_svector * x)
+{
+	int *erindx = f->erindx;
+	EGLPNUM_TYPE *ercoef = f->ercoef;
+	EGLPNUM_TYPENAME_er_info *er_inf = f->er_inf;
+	int etacnt = f->etacnt;
+	int beg;
+	int nzcnt;
+	int xnzcnt = x->nzcnt;
+	int *xindx = x->indx;
+	EGLPNUM_TYPE *xcoef = x->coef;
+	EGLPNUM_TYPE *work_coef = f->work_coef;
+	int *work_indx = f->work_indx;
+	int i;
+	int j;
+	EGLPNUM_TYPE v;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+	for (i = 0; i < xnzcnt; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (work_coef[xindx[i]], xcoef[i]);
+		work_indx[xindx[i]] = i + 1;
+	}
+	for (i = etacnt - 1; i >= 0; i--)
+	{
+#ifdef SOLVE_DEBUG
+#if (SOLVE_DEBUG+0 > 1)
+		QSlog("EGLPNUM_TYPENAME_ILLfactor_btran x before eta2 %d:", i);
+		for (j = 0; j < xnzcnt; j++)
+		{
+			QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (work_coef[xindx[j]]), xindx[j]);
+		}
+#endif
+#endif /* SOLVE_DEBUG */
+		EGLPNUM_TYPENAME_EGlpNumCopy (v, work_coef[er_inf[i].r]);
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (v))
+		{
+			nzcnt = er_inf[i].nzcnt;
+			beg = er_inf[i].rbeg;
+			for (j = 0; j < nzcnt; j++)
+			{
+				if (work_indx[erindx[beg + j]] == 0)
+				{
+					work_indx[erindx[beg + j]] = xnzcnt;
+					xindx[xnzcnt++] = erindx[beg + j];
+				}
+				EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (work_coef[erindx[beg + j]], v, ercoef[beg + j]);
+			}
+		}
+	}
+
+	j = 0;
+	while (j < xnzcnt)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (xcoef[j], work_coef[xindx[j]]);
+		EGLPNUM_TYPENAME_EGlpNumZero (work_coef[xindx[j]]);
+		work_indx[xindx[j]] = 0;
+		if (!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (xcoef[j]))
+		{
+			--xnzcnt;
+			xindx[j] = xindx[xnzcnt];
+		}
+		else
+		{
+			j++;
+		}
+	}
+	x->nzcnt = xnzcnt;
+
+#ifdef SOLVE_DEBUG
+#if (SOLVE_DEBUG+0 <= 1)
+	QSlog("EGLPNUM_TYPENAME_ILLfactor_btran x after eta2:");
+	for (j = 0; j < xnzcnt; j++)
+	{
+		QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (xcoef[j]), xindx[j]);
+	}
+#endif
+#endif /* SOLVE_DEBUG */
+	EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+
+static void ILLfactor_btranu (
+	EGLPNUM_TYPENAME_factor_work * f,
+	EGLPNUM_TYPE * a,
+	EGLPNUM_TYPENAME_svector * x)
+{
+	int *urindx = f->urindx;
+	EGLPNUM_TYPE *urcoef = f->urcoef;
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+	int *rperm = f->rperm;
+	int *cperm = f->cperm;
+	int dim = f->dim;
+	int xnzcnt = 0;
+	int *xindx = x->indx;
+	EGLPNUM_TYPE *xcoef = x->coef;
+	int nzcnt;
+	int beg;
+	int i;
+	int j;
+	EGLPNUM_TYPE v;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+	for (i = 0; i < dim; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (v, a[cperm[i]]);
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (v))
+		{
+			j = rperm[i];
+			beg = ur_inf[j].rbeg;
+			EGLPNUM_TYPENAME_EGlpNumDivTo (v, urcoef[beg]);
+			if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (v, f->szero_tol))	/*
+																							 * if (v > szero_tol || v < -szero_tol) */
+			{
+				xindx[xnzcnt] = j;
+				EGLPNUM_TYPENAME_EGlpNumCopy (xcoef[xnzcnt], v);
+				xnzcnt++;
+			}
+			nzcnt = ur_inf[j].nzcnt;
+			for (j = 1; j < nzcnt; j++)
+			{
+				EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (a[urindx[beg + j]], v, urcoef[beg + j]);
+			}
+			EGLPNUM_TYPENAME_EGlpNumZero (a[cperm[i]]);
+		}
+	}
+	x->nzcnt = xnzcnt;
+#ifdef SOLVE_DEBUG
+	QSlog("EGLPNUM_TYPENAME_ILLfactor_btran x after u:");
+	for (i = 0; i < x->nzcnt; i++)
+	{
+		QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (x->coef[i]), x->indx[i]);
+	}
+#endif /* SOLVE_DEBUG */
+	EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+
+
+#if 0
+static void btranu3_delay (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int r)
+{
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+	int nzcnt;
+	int *indx;
+	int i;
+
+	r = f->rperm[f->crank[r]];
+	nzcnt = ur_inf[r].nzcnt;
+	indx = f->urindx + ur_inf[r].rbeg;
+	for (i = 1; i < nzcnt; i++)
+	{
+		r = indx[i];
+		if (ur_inf[r].delay++ == 0)
+		{
+			btranu3_delay (f, r);
+		}
+	}
+}
+#endif
+
+static void btranu3_delay2 (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int r)
+{
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+	int nzcnt;
+	int *indx;
+	int i;
+	int last;
+
+	do
+	{
+		r = f->rperm[f->crank[r]];
+		nzcnt = ur_inf[r].nzcnt;
+		indx = f->urindx + ur_inf[r].rbeg;
+		last = -1;
+		for (i = 1; i < nzcnt; i++)
+		{
+			r = indx[i];
+			if (ur_inf[r].delay++ == 0)
+			{
+				if (last >= 0)
+				{
+					btranu3_delay2 (f, last);
+				}
+				last = r;
+			}
+		}
+		r = last;
+	} while (r >= 0);
+}
+
+#if 0
+static void btranu3_process (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int r,
+	EGLPNUM_TYPENAME_svector * x)
+{
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+	EGLPNUM_TYPE *work = f->work_coef;
+	int nzcnt;
+	int *indx;
+	EGLPNUM_TYPE *coef;
+	int i;
+	EGLPNUM_TYPE v;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+	EGLPNUM_TYPENAME_EGlpNumCopy (v, work[r]);
+	EGLPNUM_TYPENAME_EGlpNumZero (work[r]);
+	r = f->rperm[f->crank[r]];
+	nzcnt = ur_inf[r].nzcnt;
+	indx = f->urindx + ur_inf[r].rbeg;
+	coef = f->urcoef + ur_inf[r].rbeg;
+	EGLPNUM_TYPENAME_EGlpNumDivTo (v, coef[0]);
+	if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (v))
+	{
+		x->indx[x->nzcnt] = r;
+		EGLPNUM_TYPENAME_EGlpNumCopy (x->coef[x->nzcnt], v);
+		x->nzcnt++;
+	}
+	for (i = 1; i < nzcnt; i++)
+	{
+		r = indx[i];
+		EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (work[r], v, coef[i]);
+		if (--ur_inf[r].delay == 0)
+		{
+			btranu3_process (f, r, x);
+		}
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+#endif
+
+static void btranu3_process2 (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int r,
+	EGLPNUM_TYPENAME_svector * x)
+{
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+	EGLPNUM_TYPE *work = f->work_coef;
+	int nzcnt;
+	int *indx;
+	EGLPNUM_TYPE *coef;
+	int i;
+	int last;
+	EGLPNUM_TYPE v;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+	do
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (v, work[r]);
+		EGLPNUM_TYPENAME_EGlpNumZero (work[r]);
+		r = f->rperm[f->crank[r]];
+		nzcnt = ur_inf[r].nzcnt;
+		indx = f->urindx + ur_inf[r].rbeg;
+		coef = f->urcoef + ur_inf[r].rbeg;
+		EGLPNUM_TYPENAME_EGlpNumDivTo (v, coef[0]);
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (v))
+		{
+			x->indx[x->nzcnt] = r;
+			EGLPNUM_TYPENAME_EGlpNumCopy (x->coef[x->nzcnt], v);
+			x->nzcnt++;
+		}
+		last = -1;
+		for (i = 1; i < nzcnt; i++)
+		{
+			r = indx[i];
+			EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (work[r], v, coef[i]);
+			if (--ur_inf[r].delay == 0)
+			{
+				if (last >= 0)
+				{
+					btranu3_process2 (f, last, x);
+				}
+				last = r;
+			}
+		}
+		r = last;
+	} while (r >= 0);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+
+static void ILLfactor_btranu3 (
+	EGLPNUM_TYPENAME_factor_work * f,
+	EGLPNUM_TYPENAME_svector * a,
+	EGLPNUM_TYPENAME_svector * x)
+{
+	EGLPNUM_TYPE *work = f->work_coef;
+	int anzcnt = a->nzcnt;
+	int *aindx = a->indx;
+	EGLPNUM_TYPE *acoef = a->coef;
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+	int i;
+
+	for (i = 0; i < anzcnt; i++)
+	{
+		if (ur_inf[aindx[i]].delay++ == 0)
+		{
+			btranu3_delay2 (f, aindx[i]);
+		}
+		EGLPNUM_TYPENAME_EGlpNumCopy (work[aindx[i]], acoef[i]);
+	}
+	x->nzcnt = 0;
+	for (i = 0; i < anzcnt; i++)
+	{
+		if (--ur_inf[aindx[i]].delay == 0)
+		{
+			btranu3_process2 (f, aindx[i], x);
+		}
+	}
+#ifdef SOLVE_DEBUG
+	QSlog("EGLPNUM_TYPENAME_ILLfactor_btran x after u3:");
+	for (i = 0; i < x->nzcnt; i++)
+	{
+		QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (x->coef[i]), x->indx[i]);
+	}
+#endif /* SOLVE_DEBUG */
+}
+
+/* EGLPNUM_TYPENAME_ILLfactor_btran solves x^tB=a^t (or, B^t x = a) for x */
+void EGLPNUM_TYPENAME_ILLfactor_btran (
+	EGLPNUM_TYPENAME_factor_work * f,
+	EGLPNUM_TYPENAME_svector * a,
+	EGLPNUM_TYPENAME_svector * x)
+{
+	int i;
+	int nzcnt;
+	int sparse;
+	int *aindx = a->indx;
+	EGLPNUM_TYPE *acoef = a->coef;
+	EGLPNUM_TYPE *work_coef = f->work_coef;
+	int dim = f->dim;
+
+#ifdef RECORD
+	{
+		EGioPrintf (fsave, "b %d", a->nzcnt);
+		for (i = 0; i < a->nzcnt; i++)
+		{
+			EGioPrintf (fsave, " %d %.16e", a->indx[i], EGLPNUM_TYPENAME_EGlpNumToLf (a->coef[i]));
+		}
+		EGioPrintf (fsave, "\n");
+		EGioFlush (fsave);
+	}
+#endif /* RECORD */
+#ifdef DEBUG_FACTOR
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLfactor_btran a:");
+		for (i = 0; i < a->nzcnt; i++)
+		{
+			QSlog(" %d %.3f", a->indx[i], EGLPNUM_TYPENAME_EGlpNumToLf (a->coef[i]));
+		}
+	}
+#endif /* DEBUG_FACTOR */
+
+	if (a->nzcnt >= SPARSE_FACTOR * f->dim)
+	{
+		aindx = a->indx;
+		acoef = a->coef;
+		work_coef = f->work_coef;
+		nzcnt = a->nzcnt;
+		for (i = 0; i < nzcnt; i++)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
+		}
+		sparse = 0;
+	}
+	else
+	{
+		sparse = 1;
+	}
+
+	if (sparse)
+	{
+		ILLfactor_btranu3 (f, a, &f->xtmp);
+	}
+	else
+	{
+		ILLfactor_btranu (f, work_coef, &f->xtmp);
+	}
+
+	if (f->xtmp.nzcnt >= SPARSE_FACTOR * f->dim)
+	{
+		aindx = f->xtmp.indx;
+		acoef = f->xtmp.coef;
+		work_coef = f->work_coef;
+		nzcnt = f->xtmp.nzcnt;
+		for (i = 0; i < nzcnt; i++)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
+		}
+		sparse = 0;
+	}
+	else
+	{
+		sparse = 1;
+	}
+
+	if (sparse)
+	{
+		ILLfactor_btrane2 (f, &f->xtmp);
+		if (f->xtmp.nzcnt >= SPARSE_FACTOR * f->dim)
+		{
+			aindx = f->xtmp.indx;
+			acoef = f->xtmp.coef;
+			work_coef = f->work_coef;
+			nzcnt = f->xtmp.nzcnt;
+			for (i = 0; i < nzcnt; i++)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
+			}
+			sparse = 0;
+		}
+	}
+	else
+	{
+		ILLfactor_btrane (f, work_coef);
+	}
+
+	if (sparse)
+	{
+		ILLfactor_btranl3 (f, &f->xtmp, x);
+	}
+	else
+	{
+		ILLfactor_btranl2 (f, work_coef);
+		dim = f->dim;
+		nzcnt = 0;
+		aindx = x->indx;
+		acoef = x->coef;
+		for (i = 0; i < dim; i++)
+		{
+			if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (work_coef[i]))
+			{
+				if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (work_coef[i], f->szero_tol))
+					/*if (work_coef[i] > szero_tol || work_coef[i] < -szero_tol) */
+				{
+					aindx[nzcnt] = i;
+					EGLPNUM_TYPENAME_EGlpNumCopy (acoef[nzcnt], work_coef[i]);
+					nzcnt++;
+				}
+				EGLPNUM_TYPENAME_EGlpNumZero (work_coef[i]);
+			}
+		}
+		x->nzcnt = nzcnt;
+	}
+
+#ifdef SORT_RESULTS
+	sort_vector (x);
+#endif
+
+#ifdef DEBUG_FACTOR
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLfactor_btran x:");
+		for (i = 0; i < x->nzcnt; i++)
+		{
+			QSlog(" %d %.3f", x->indx[i], EGLPNUM_TYPENAME_EGlpNumToLf (x->coef[i]));
+		}
+	}
+#endif /* DEBUG_FACTOR */
+	return;
+}
+
+static int expand_col (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int col)
+{
+	EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf + col;
+	int uc_freebeg = f->uc_freebeg;
+	int nzcnt = uc_inf->nzcnt;
+	int cbeg;
+	EGLPNUM_TYPE *uccoef;
+	int *ucindx;
+	int *ucrind;
+	int i;
+	int rval = 0;
+
+	if (uc_freebeg + nzcnt + 1 >= f->uc_space)
+	{
+		rval = make_uc_space (f, nzcnt + 1);
+		CHECKRVALG (rval, CLEANUP);
+		uc_freebeg = f->uc_freebeg;
+	}
+	cbeg = uc_inf->cbeg;
+	uccoef = f->uccoef;
+	ucindx = f->ucindx;
+	ucrind = f->ucrind;
+
+	for (i = 0; i < nzcnt; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (uccoef[uc_freebeg + i], uccoef[cbeg + i]);
+		ucindx[uc_freebeg + i] = ucindx[cbeg + i];
+		ucrind[uc_freebeg + i] = ucrind[cbeg + i];
+		ucindx[cbeg + i] = -1;
+	}
+
+	uc_inf->cbeg = uc_freebeg;
+	f->uc_freebeg = uc_freebeg + nzcnt;
+CLEANUP:
+	EG_RETURN (rval);
+}
+
+static int expand_row (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int row)
+{
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf + row;
+	int ur_freebeg = f->ur_freebeg;
+	int nzcnt = ur_inf->nzcnt;
+	int rbeg;
+	EGLPNUM_TYPE *urcoef;
+	int *urindx;
+	int *urcind;
+	int i;
+	int rval = 0;
+
+	if (ur_freebeg + nzcnt + 1 >= f->ur_space)
+	{
+		rval = make_ur_space (f, nzcnt + 1);
+		CHECKRVALG (rval, CLEANUP);
+		ur_freebeg = f->ur_freebeg;
+	}
+	rbeg = ur_inf->rbeg;
+	urcoef = f->urcoef;
+	urindx = f->urindx;
+	urcind = f->urcind;
+
+	for (i = 0; i < nzcnt; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (urcoef[ur_freebeg + i], urcoef[rbeg + i]);
+		urindx[ur_freebeg + i] = urindx[rbeg + i];
+		urcind[ur_freebeg + i] = urcind[rbeg + i];
+		urindx[rbeg + i] = -1;
+	}
+
+	ur_inf->rbeg = ur_freebeg;
+	f->ur_freebeg = ur_freebeg + nzcnt;
+CLEANUP:
+	EG_RETURN (rval);
+}
+
+static int add_nonzero (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int row,
+	int col,
+	EGLPNUM_TYPE val)
+{
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf + row;
+	EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf + col;
+	int cnzcnt = uc_inf->nzcnt;
+	int rnzcnt = ur_inf->nzcnt;
+	int cloc = uc_inf->cbeg + cnzcnt;
+	int rloc = ur_inf->rbeg + rnzcnt;
+	int rval = 0;
+
+	if (f->ucindx[cloc] != -1)
+	{
+		rval = expand_col (f, col);
+		CHECKRVALG (rval, CLEANUP);
+		cloc = uc_inf->cbeg + cnzcnt;
+	}
+	TESTG ((rval = (rloc < 0 || rloc > f->ur_space)), CLEANUP,
+				 "rloc %d outside boundaries [0:%d]", rloc, f->ur_space);
+	if (f->urindx[rloc] != -1)
+	{
+		rval = expand_row (f, row);
+		CHECKRVALG (rval, CLEANUP);
+		rloc = ur_inf->rbeg + rnzcnt;
+	}
+	f->ucindx[cloc] = row;
+	EGLPNUM_TYPENAME_EGlpNumCopy (f->uccoef[cloc], val);
+	f->ucrind[cloc] = rnzcnt;
+	f->urindx[rloc] = col;
+	EGLPNUM_TYPENAME_EGlpNumCopy (f->urcoef[rloc], val);
+	f->urcind[rloc] = cnzcnt;
+
+	if (cloc == f->uc_freebeg)
+		f->uc_freebeg++;
+	if (rloc == f->ur_freebeg)
+		f->ur_freebeg++;
+
+	uc_inf->nzcnt = cnzcnt + 1;
+	ur_inf->nzcnt = rnzcnt + 1;
+CLEANUP:
+	EG_RETURN (rval);
+}
+
+static int delete_nonzero_row (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int row,
+	int ind)
+{
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+	EGLPNUM_TYPE *urcoef = f->urcoef;
+	int *urindx = f->urindx;
+	int *urcind = f->urcind;
+	int *ucrind = f->ucrind;
+	int rbeg = ur_inf[row].rbeg;
+	int nzcnt = ur_inf[row].nzcnt - 1;
+	int cbeg, rval = 0;
+	#ifdef DEBUG_FACTOR
+	TESTG((rval=(nzcnt<0)),CLEANUP,"Deleting empty row %d ind %d!",row, ind);
+	#endif
+
+	if (ind != nzcnt)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (urcoef[rbeg + ind], urcoef[rbeg + nzcnt]);
+		urindx[rbeg + ind] = urindx[rbeg + nzcnt];
+		urcind[rbeg + ind] = urcind[rbeg + nzcnt];
+		cbeg = f->uc_inf[urindx[rbeg + nzcnt]].cbeg;
+		ucrind[cbeg + urcind[rbeg + nzcnt]] = ind;
+		urindx[rbeg + nzcnt] = -1;
+	}
+	ur_inf[row].nzcnt = nzcnt;
+	#ifdef DEBUG_FACTOR
+	CLEANUP:
+	#endif
+	return rval;
+}
+
+static void delete_nonzero_col (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int col,
+	int ind)
+{
+	EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+	EGLPNUM_TYPE *uccoef = f->uccoef;
+	int *ucindx = f->ucindx;
+	int *ucrind = f->ucrind;
+	int *urcind = f->urcind;
+	int cbeg = uc_inf[col].cbeg;
+	int nzcnt = uc_inf[col].nzcnt - 1;
+	int rbeg;
+
+	if (ind != nzcnt)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (uccoef[cbeg + ind], uccoef[cbeg + nzcnt]);
+		ucindx[cbeg + ind] = ucindx[cbeg + nzcnt];
+		ucrind[cbeg + ind] = ucrind[cbeg + nzcnt];
+		rbeg = f->ur_inf[ucindx[cbeg + nzcnt]].rbeg;
+		urcind[rbeg + ucrind[cbeg + nzcnt]] = ind;
+		ucindx[cbeg + nzcnt] = -1;
+	}
+	uc_inf[col].nzcnt = nzcnt;
+}
+
+static int delete_column (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int col)
+{
+	EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+	int beg = uc_inf[col].cbeg;
+	int nzcnt = uc_inf[col].nzcnt;
+	int *ucindx = f->ucindx + beg;
+	int *ucrind = f->ucrind + beg;
+	int i, rval = 0;
+	#ifdef DEBUG_FACTOR
+	rval = check_matrix(f);
+	TESTG(rval,CLEANUP,"Corrupted Matrix");
+	#endif
+
+	for (i = 0; i < nzcnt; i++)
+	{
+		rval = delete_nonzero_row (f, ucindx[i], ucrind[i]);
+		CHECKRVALG(rval,CLEANUP);
+		ucindx[i] = -1;
+	}
+	uc_inf[col].nzcnt = 0;
+
+#ifdef TRACK_FACTOR
+	f->nzcnt_cur -= nzcnt;
+#endif
+
+	#ifdef DEBUG_FACTOR
+	rval = check_matrix(f);
+	TESTG(rval,CLEANUP,"Corrupted Matrix");
+	#endif /* DEBUG_FACTOR */
+	CLEANUP:
+	EG_RETURN(rval);
+}
+
+static int delete_row (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int row,
+	EGLPNUM_TYPENAME_svector * x)
+{
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+	int beg = ur_inf[row].rbeg;
+	int nzcnt = ur_inf[row].nzcnt;
+	int *urindx = f->urindx + beg;
+	EGLPNUM_TYPE *urcoef = f->urcoef + beg;
+	int *urcind = f->urcind + beg;
+	int i,rval=0;
+
+	#ifdef DEBUG_FACTOR
+	rval = check_matrix(f);
+	TESTG(rval,CLEANUP,"Corrupted Matrix");
+	#endif /* DEBUG_FACTOR */
+
+	for (i = 0; i < nzcnt; i++)
+	{
+		x->indx[i] = urindx[i];
+		EGLPNUM_TYPENAME_EGlpNumCopy (x->coef[i], urcoef[i]);
+		delete_nonzero_col (f, urindx[i], urcind[i]);
+		urindx[i] = -1;
+	}
+	x->nzcnt = nzcnt;
+	ur_inf[row].nzcnt = 0;
+
+#ifdef TRACK_FACTOR
+	f->nzcnt_cur -= nzcnt;
+#endif
+
+	#ifdef DEBUG_FACTOR
+	rval = check_matrix(f);
+	TESTG(rval,CLEANUP,"Corrupted Matrix");
+	CLEANUP:
+	#endif /* DEBUG_FACTOR */
+	return rval;
+}
+
+static int create_column (
+	EGLPNUM_TYPENAME_factor_work * f,
+	EGLPNUM_TYPENAME_svector * a,
+	int col,
+	int *p_last_rank)
+{
+	int *rrank = f->rrank;
+	int nzcnt = a->nzcnt;
+	int *aindx = a->indx;
+	EGLPNUM_TYPE *acoef = a->coef;
+	int i;
+	int j;
+	int rval = 0;
+	int last_rank = -1;
+
+#ifdef TRACK_FACTOR
+	EGLPNUM_TYPE max;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (max);
+	EGLPNUM_TYPENAME_EGlpNumCopy (max, f->maxelem_cur);
+#endif /* TRACK_FACTOR */
+
+	last_rank = 0;
+
+	for (i = 0; i < nzcnt; i++)
+	{
+		rval = add_nonzero (f, aindx[i], col, acoef[i]);
+		CHECKRVALG (rval, CLEANUP);
+#ifdef TRACK_FACTOR
+		EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (max, acoef[i]);
+#endif /* TRACK_FACTOR */
+		j = rrank[aindx[i]];
+		if (j > last_rank)
+			last_rank = j;
+	}
+	*p_last_rank = last_rank;
+
+#ifdef TRACK_FACTOR
+	f->nzcnt_cur += nzcnt;
+	EGLPNUM_TYPENAME_EGlpNumCopy (f->maxelem_cur, max);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (max);
+#endif /* TRACK_FACTOR */
+
+	#ifdef DEBUG_FACTOR
+	rval = check_matrix(f);
+	TESTG(rval,CLEANUP,"Corrupted Matrix");
+	#endif /* DEBUG_FACTOR */
+
+	CLEANUP:
+	EG_RETURN (rval);
+}
+
+#ifdef UPDATE_STUDY
+static int column_rank (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int col)
+{
+	int *cperm = f->cperm;
+	int dim = f->dim;
+	int i;
+
+	for (i = 0; i < dim; i++)
+	{
+		if (cperm[i] == col)
+		{
+			return i;
+		}
+	}
+	return 0;
+}
+#endif
+
+static void shift_permutations (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int rank_p,
+	int rank_r)
+{
+	int *cperm = f->cperm;
+	int *crank = f->crank;
+	int *rperm = f->rperm;
+	int *rrank = f->rrank;
+	int col_p = cperm[rank_p];
+	int row_p = rperm[rank_p];
+	int i;
+
+	for (i = rank_p; i < rank_r; i++)
+	{
+		cperm[i] = cperm[i + 1];
+		crank[cperm[i]] = i;
+		rperm[i] = rperm[i + 1];
+		rrank[rperm[i]] = i;
+	}
+	cperm[rank_r] = col_p;
+	crank[col_p] = rank_r;
+	rperm[rank_r] = row_p;
+	rrank[row_p] = rank_r;
+}
+
+static int eliminate_row (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int rank_p,
+	int rank_r)
+{
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+	int *rperm = f->rperm;
+	int *cperm = f->cperm;
+	int *urindx = f->urindx;
+	EGLPNUM_TYPE *urcoef = f->urcoef;
+	int *erindx = f->erindx;
+	EGLPNUM_TYPE *ercoef = f->ercoef;
+	EGLPNUM_TYPE *work_coef = f->work_coef;
+	int er_freebeg = f->er_freebeg;
+	int er_space = f->er_space;
+	int beg;
+	int nzcnt;
+	int i;
+	int j;
+	int c;
+	int r;
+	EGLPNUM_TYPE pivot_mul;
+
+#ifdef TRACK_FACTOR
+	EGLPNUM_TYPE max;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (max);
+	EGLPNUM_TYPENAME_EGlpNumCopy (max, f->maxelem_cur);
+#endif /* TRACK_FACTOR */
+	EGLPNUM_TYPENAME_EGlpNumInitVar (pivot_mul);
+
+	for (i = rank_p; i < rank_r; i++)
+	{
+		c = cperm[i];
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (work_coef[c], f->fzero_tol))	/*
+																												 * if (work_coef[c] > fzero_tol || work_coef[c] < -fzero_tol) */
+		{
+			r = rperm[i];
+			beg = ur_inf[r].rbeg;
+			nzcnt = ur_inf[r].nzcnt;
+			EGLPNUM_TYPENAME_EGlpNumCopyFrac (pivot_mul, work_coef[c], urcoef[beg]);
+			EGLPNUM_TYPENAME_EGlpNumZero (work_coef[c]);
+			for (j = 1; j < nzcnt; j++)
+			{
+				EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (work_coef[urindx[beg + j]], pivot_mul, urcoef[beg + j]);	/* 0.85 */
+			}
+			if (er_freebeg >= er_space)
+			{
+				/* QSlog("no space in eliminate_row"); */
+#ifdef TRACK_FACTOR
+				EGLPNUM_TYPENAME_EGlpNumClearVar (max);
+#endif
+				EGLPNUM_TYPENAME_EGlpNumClearVar (pivot_mul);
+				return E_UPDATE_NOSPACE;
+			}
+			erindx[er_freebeg] = r;
+			EGLPNUM_TYPENAME_EGlpNumCopy (ercoef[er_freebeg], pivot_mul);
+#ifdef TRACK_FACTOR
+			EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (max, pivot_mul);
+#endif /* TRACK_FACTOR */
+			er_freebeg++;
+		}
+		else
+		{
+			EGLPNUM_TYPENAME_EGlpNumZero (work_coef[c]);
+		}
+	}
+	f->er_freebeg = er_freebeg;
+#ifdef TRACK_FACTOR
+	EGLPNUM_TYPENAME_EGlpNumCopy (f->maxelem_cur, max);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (max);
+#endif /* TRACK_FACTOR */
+	EGLPNUM_TYPENAME_EGlpNumClearVar (pivot_mul);
+	return 0;
+}
+
+static int create_row (
+	EGLPNUM_TYPENAME_factor_work * f,
+	EGLPNUM_TYPE * a,
+	int row,
+	int minrank)
+{
+	int *cperm = f->cperm;
+	int dim = f->dim;
+	int i;
+	int j;
+	int rval = 0;
+
+#ifdef TRACK_FACTOR
+	EGLPNUM_TYPE max;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (max);
+	EGLPNUM_TYPENAME_EGlpNumCopy (max, f->maxelem_cur);
+#endif /* TRACK_FACTOR */
+
+	for (i = minrank; i < dim; i++)
+	{
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (a[cperm[i]]))
+		{
+			j = cperm[i];
+			if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (a[j], f->fzero_tol))	/*
+																									 * if (a[j] > fzero_tol || a[j] < -fzero_tol) */
+			{
+				rval = add_nonzero (f, row, j, a[j]);
+				CHECKRVALG (rval, CLEANUP);
+#ifdef TRACK_FACTOR
+				EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (max, a[j]);
+#endif /* TRACK_FACTOR */
+			}
+			EGLPNUM_TYPENAME_EGlpNumZero (a[j]);
+		}
+	}
+
+#ifdef TRACK_FACTOR
+	f->nzcnt_cur += f->ur_inf[row].nzcnt;
+	EGLPNUM_TYPENAME_EGlpNumCopy (f->maxelem_cur, max);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (max);
+#endif /* TRACK_FACTOR */
+
+	#ifdef DEBUG_FACTOR
+	rval = check_matrix(f);
+	TESTG(rval,CLEANUP,"Corrupted Matrix");
+	#endif /* DEBUG_FACTOR */
+	CLEANUP:
+	EG_RETURN (rval);
+}
+
+static void serow_delay (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int r,
+	int rank_r)
+{
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+	int *crank = f->crank;
+	int nzcnt;
+	int *indx;
+	int i;
+	int last;
+
+	do
+	{
+		r = f->rperm[crank[r]];
+		nzcnt = ur_inf[r].nzcnt;
+		indx = f->urindx + ur_inf[r].rbeg;
+		last = -1;
+		for (i = 1; i < nzcnt; i++)
+		{
+			r = indx[i];
+			if (ur_inf[r].delay++ == 0 && crank[r] < rank_r)
+			{
+				if (last >= 0)
+				{
+					serow_delay (f, last, rank_r);
+				}
+				last = r;
+			}
+		}
+		r = last;
+	} while (r >= 0);
+}
+
+static int serow_process (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int r,
+	EGLPNUM_TYPENAME_svector * newr,
+	int rank_r)
+{
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+	EGLPNUM_TYPE *work = f->work_coef;
+	int nzcnt;
+	int *indx;
+	EGLPNUM_TYPE *coef;
+	int i;
+	EGLPNUM_TYPE v;
+	int last;
+	int rval;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+	do
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (v, work[r]);
+		EGLPNUM_TYPENAME_EGlpNumZero (work[r]);
+		if (f->crank[r] >= rank_r)
+		{
+			if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (v, f->fzero_tol))	/*
+																							 * if (v > fzero_tol || v < -fzero_tol) */
+			{
+				/* stash this nonzero in the resulting row */
+#ifdef TRACK_FACTOR
+				EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (f->maxelem_cur, v);
+#endif /* TRACK_FACTOR */
+				newr->indx[newr->nzcnt] = r;
+				EGLPNUM_TYPENAME_EGlpNumCopy (newr->coef[newr->nzcnt], v);
+				newr->nzcnt++;
+				EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+				return 0;
+			}
+			else
+			{
+				EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+				return 0;
+			}
+		}
+		r = f->rperm[f->crank[r]];
+		nzcnt = ur_inf[r].nzcnt;
+		indx = f->urindx + ur_inf[r].rbeg;
+		coef = f->urcoef + ur_inf[r].rbeg;
+		EGLPNUM_TYPENAME_EGlpNumDivTo (v, coef[0]);
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (v, f->fzero_tol))	/*
+																						 * if (v > fzero_tol || v < -fzero_tol) */
+		{
+			/* stash v in eta */
+			if (f->er_freebeg >= f->er_space)
+			{
+				/* QSlog("no space in eliminate_row"); */
+				EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+				return E_UPDATE_NOSPACE;
+			}
+			f->erindx[f->er_freebeg] = r;
+			EGLPNUM_TYPENAME_EGlpNumCopy (f->ercoef[f->er_freebeg], v);
+#ifdef TRACK_FACTOR
+			EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (f->maxelem_cur, v);
+#endif /* TRACK_FACTOR */
+			f->er_freebeg++;
+		}
+		last = -1;
+		for (i = 1; i < nzcnt; i++)
+		{
+			r = indx[i];
+			EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (work[r], v, coef[i]);
+			if (--ur_inf[r].delay == 0)
+			{
+				if (last >= 0)
+				{
+					rval = serow_process (f, last, newr, rank_r);
+					if (rval)
+					{
+						EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+						return rval;
+					}
+				}
+				last = r;
+			}
+		}
+		r = last;
+	} while (r >= 0);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+	return 0;
+}
+
+static int sparse_eliminate_row (
+	EGLPNUM_TYPENAME_factor_work * f,
+	EGLPNUM_TYPENAME_svector * x,
+	int row_p,
+	int rank_r)
+{
+	EGLPNUM_TYPE *work = f->work_coef;
+	int xnzcnt = x->nzcnt;
+	int *xindx = x->indx;
+	EGLPNUM_TYPE *xcoef = x->coef;
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+	int *crank = f->crank;
+	int i;
+	int j;
+	int rval = 0;
+	EGLPNUM_TYPENAME_svector newr;
+
+	newr.indx = 0;
+	newr.coef = 0;
+
+	for (i = 0; i < xnzcnt; i++)
+	{
+		j = xindx[i];
+		if (ur_inf[j].delay++ == 0 && crank[j] < rank_r)
+		{
+			serow_delay (f, j, rank_r);
+		}
+		EGLPNUM_TYPENAME_EGlpNumCopy (work[j], xcoef[i]);
+	}
+
+	newr.nzcnt = 0;
+	ILL_SAFE_MALLOC (newr.indx, f->dim, int);
+
+	newr.coef = EGLPNUM_TYPENAME_EGlpNumAllocArray (f->dim);
+
+	for (i = 0; i < xnzcnt; i++)
+	{
+		j = xindx[i];
+		if (--ur_inf[j].delay == 0)
+		{
+			rval = serow_process (f, j, &newr, rank_r);
+			CHECKRVALG (rval, CLEANUP);
+		}
+	}
+
+	for (i = 0; i < newr.nzcnt; i++)
+	{
+		rval = add_nonzero (f, row_p, newr.indx[i], newr.coef[i]);
+		CHECKRVALG (rval, CLEANUP);
+	}
+
+#ifdef TRACK_FACTOR
+	f->nzcnt_cur += newr.nzcnt;
+#endif /* TRACK_FACTOR */
+
+CLEANUP:
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (newr.coef);
+	ILL_IFFREE (newr.indx, int);
+
+	/* Bico 031210 - chg from ILL_RETURN */
+	EG_RETURN (rval);
+}
+
+static int move_pivot_row (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int r,
+	int c)
+{
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf + r;
+	EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+	int beg = ur_inf->rbeg;
+	int nzcnt = ur_inf->nzcnt;
+	int *urindx = f->urindx;
+	int *urcind = f->urcind;
+	int *ucrind = f->ucrind;
+	EGLPNUM_TYPE *urcoef = f->urcoef;
+	EGLPNUM_TYPE dt;
+	int it;
+	int i;
+
+	if (urindx[beg] == c)
+		return 0;
+	EGLPNUM_TYPENAME_EGlpNumInitVar (dt);
+
+	for (i = 1; i < nzcnt; i++)
+	{
+		if (urindx[beg + i] == c)
+		{
+			EGLPNUM_TYPENAME_EGLPNUM_SWAP (urcoef[beg], urcoef[beg + i], dt);
+			ILL_SWAP (urcind[beg], urcind[beg + i], it);
+			urindx[beg + i] = urindx[beg];
+			urindx[beg] = c;
+			ucrind[uc_inf[c].cbeg + urcind[beg]] = 0;
+			ucrind[uc_inf[urindx[beg + i]].cbeg + urcind[beg + i]] = i;
+			EGLPNUM_TYPENAME_EGlpNumClearVar (dt);
+			return 0;
+		}
+	}
+	MESSAGE (__QS_SB_VERB, "pivot row nonzero not found");
+	EGLPNUM_TYPENAME_EGlpNumClearVar (dt);
+	return E_UPDATE_SINGULAR_ROW;
+}
+
+static int move_pivot_col (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int c,
+	int r)
+{
+	EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf + c;
+	EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+	int beg = uc_inf->cbeg;
+	int nzcnt = uc_inf->nzcnt;
+	int *ucindx = f->ucindx;
+	int *ucrind = f->ucrind;
+	int *urcind = f->urcind;
+	EGLPNUM_TYPE *uccoef = f->uccoef;
+	EGLPNUM_TYPE dt;
+	int i, it;
+
+	if (ucindx[beg] == r)
+		return 0;
+	EGLPNUM_TYPENAME_EGlpNumInitVar (dt);
+
+	for (i = 1; i < nzcnt; i++)
+	{
+		if (ucindx[beg + i] == r)
+		{
+			EGLPNUM_TYPENAME_EGLPNUM_SWAP (uccoef[beg], uccoef[beg + i], dt);
+			ILL_SWAP (ucrind[beg], ucrind[beg + i], it);
+			ucindx[beg + i] = ucindx[beg];
+			ucindx[beg] = r;
+			urcind[ur_inf[r].rbeg + ucrind[beg]] = 0;
+			urcind[ur_inf[ucindx[beg + i]].rbeg + ucrind[beg + i]] = i;
+			EGLPNUM_TYPENAME_EGlpNumClearVar (dt);
+			return 0;
+		}
+	}
+	MESSAGE(__QS_SB_VERB, "pivot col nonzero not found");
+	EGLPNUM_TYPENAME_EGlpNumClearVar (dt);
+	return E_UPDATE_SINGULAR_COL;
+}
+
+static int move_pivot (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int rank_r)
+{
+	int r = f->rperm[rank_r];
+	int c = f->cperm[rank_r];
+	int rval = 0;
+
+	rval = move_pivot_row (f, r, c);
+	CHECKRVALG (rval, CLEANUP);
+
+	#ifdef DEBUG_FACTOR
+	rval = check_matrix(f);
+	TESTG(rval,CLEANUP,"Corrupted Matrix");
+	#endif /* DEBUG_FACTOR */
+
+	rval = move_pivot_col (f, c, r);
+	if(rval != E_UPDATE_SINGULAR_COL) CHECKRVALG (rval, CLEANUP);
+	else goto CLEANUP;
+
+	#ifdef DEBUG_FACTOR
+	rval = check_matrix(f);
+	TESTG(rval,CLEANUP,"Corrupted Matrix");
+	#endif /* DEBUG_FACTOR */
+
+	CLEANUP:
+	if(rval != E_UPDATE_SINGULAR_COL) EG_RETURN (rval);							/* Bico 031209 - chg from RETURN */
+	return rval;
+}
+
+int EGLPNUM_TYPENAME_ILLfactor_update (
+	EGLPNUM_TYPENAME_factor_work * f,
+	EGLPNUM_TYPENAME_svector * a,
+	int col_p,
+	int *p_refact)
+{
+	int row_p;
+	int rank_r = 0;
+	int rank_p = 0;
+	int rval = 0;
+	int nzcnt;
+	int *aindx;
+	EGLPNUM_TYPE *acoef;
+	EGLPNUM_TYPE *work_coef = f->work_coef;
+
+#ifdef TRACK_FACTOR
+#ifdef NOTICE_BLOWUP
+	EGLPNUM_TYPE tmpsize;
+#endif
+#endif
+	int i;
+
+#ifdef RECORD
+	{
+		EGioPrintf (fsave, "u %d %d", col_p, a->nzcnt);
+		for (i = 0; i < a->nzcnt; i++)
+		{
+			EGioPrintf (fsave, " %d %.16e", a->indx[i], EGLPNUM_TYPENAME_EGlpNumToLf (a->coef[i]));
+		}
+		EGioPrintf (fsave, "\n");
+		EGioFlush (fsave);
+	}
+#endif /* RECORD */
+
+#ifdef DEBUG_FACTOR
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLfactor_update col %d:", col_p);
+		for (i = 0; i < a->nzcnt; i++)
+		{
+			QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (a->coef[i]), a->indx[i]);
+		}
+	}
+#endif /* DEBUG_FACTOR */
+
+	#ifdef DEBUG_FACTOR
+	rval = check_matrix(f);
+	TESTG(rval,CLEANUP,"Corrupted Matrix");
+	#endif /* DEBUG_FACTOR */
+
+	if (f->etacnt >= f->etamax)
+	{
+		*p_refact = 1;
+		return 0;
+	}
+
+#ifdef UPDATE_STUDY
+	nupdate++;
+#endif
+
+	row_p = f->ucindx[f->uc_inf[col_p].cbeg];
+
+	rval = delete_column (f, col_p);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = create_column (f, a, col_p, &rank_r);
+	/* if (rval) QSlog("create_column failed"); */
+	CHECKRVALG (rval, CLEANUP);
+
+	rank_p = f->crank[col_p];
+#ifdef UPDATE_STUDY
+	if (rank_p != f->rrank[row_p] || rank_p != column_rank (f, col_p))
+	{
+		QSlog("rank_p %d rrank[row_p] %d column_rank(f,col_p) %d",
+								rank_p, f->rrank[row_p], column_rank (f, col_p));
+	}
+	if (rank_r > rank_p)
+	{
+		permshifttot += rank_r - rank_p;
+	}
+	for (i = 0; i < a->nzcnt; i++)
+	{
+		if (f->rrank[a->indx[i]] > rank_p)
+			colspiketot++;
+	}
+	for (i = 0; i < f->ur_inf[row_p].nzcnt; i++)
+	{
+		if (f->crank[f->urindx[f->ur_inf[row_p].rbeg + i]] <= rank_r &&
+				f->crank[f->urindx[f->ur_inf[row_p].rbeg + i]] != rank_p)
+		{
+			rowspiketot++;
+		}
+	}
+#endif
+
+	shift_permutations (f, rank_p, rank_r);
+
+	rval = delete_row (f, row_p, &f->xtmp);
+	CHECKRVALG(rval,CLEANUP);
+
+	f->er_inf[f->etacnt].rbeg = f->er_freebeg;
+	f->er_inf[f->etacnt].r = row_p;
+
+	if (f->xtmp.nzcnt >= SPARSE_FACTOR * f->dim)
+	{
+		nzcnt = f->xtmp.nzcnt;
+		aindx = f->xtmp.indx;
+		acoef = f->xtmp.coef;
+
+		for (i = 0; i < nzcnt; i++)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
+		}
+
+		rval = eliminate_row (f, rank_p, rank_r);
+		/* if (rval) QSlog("eliminate_row failed"); */
+		CHECKRVALG (rval, CLEANUP);
+
+		rval = create_row (f, f->work_coef, row_p, rank_r);
+		/* if (rval) QSlog("create_row failed"); */
+		CHECKRVALG (rval, CLEANUP);
+	}
+	else
+	{
+		rval = sparse_eliminate_row (f, &f->xtmp, row_p, rank_r);
+		/* if (rval) QSlog("sparse_eliminate_row failed"); */
+		CHECKRVALG (rval, CLEANUP);
+	}
+
+	if (f->er_freebeg - f->er_inf[f->etacnt].rbeg > 0)
+	{
+		f->er_inf[f->etacnt].nzcnt = f->er_freebeg - f->er_inf[f->etacnt].rbeg;
+#ifdef TRACK_FACTOR
+		f->nzcnt_cur += f->er_inf[f->etacnt].nzcnt;
+#endif /* TRACK_FACTOR */
+#ifdef UPDATE_STUDY
+		leftetatot += f->er_inf[f->etacnt].nzcnt;
+#endif
+
+#ifdef SORT_RESULTS
+		sort_vector2 (f->er_inf[f->etacnt].nzcnt,
+									f->erindx + f->er_inf[f->etacnt].rbeg,
+									f->ercoef + f->er_inf[f->etacnt].rbeg);
+#endif
+
+		f->etacnt++;
+	}
+
+	rval = move_pivot (f, rank_r);
+	/* if (rval) QSlog("move_pivot failed"); */
+	if(rval != E_UPDATE_SINGULAR_COL) CHECKRVALG (rval, CLEANUP);
+	else goto CLEANUP;
+
+#ifdef UPDATE_DEBUG
+	QSlog("Updated factorization:");
+#if (UPDATE_DEBUG+0>1)
+	dump_matrix (f, 0);
+#endif
+#endif /* UPDATE_DEBUG */
+
+#ifdef TRACK_FACTOR
+#ifdef NOTICE_BLOWUP
+	EGLPNUM_TYPENAME_EGlpNumInitVar (tmpsize);
+	EGLPNUM_TYPENAME_EGlpNumSet (tmpsize, f->updmaxmult);
+	EGLPNUM_TYPENAME_EGlpNumMultTo (tmpsize, f->maxelem_orig);
+	if (EGLPNUM_TYPENAME_EGlpNumIsLess (tmpsize, f->maxelem_cur))
+	{
+/* Bico - comment out for dist 
+        QSlog("factor_update blowup max cur %e max orig %e",
+                    f->maxelem_cur, f->maxelem_orig);
+*/
+		EGLPNUM_TYPENAME_EGlpNumClearVar (tmpsize);
+		return E_FACTOR_BLOWUP;
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (tmpsize);
+#endif /* NOTICE_BLOWUP */
+#endif
+#ifdef UPDATE_STATS
+	dump_factor_stats (f);
+#endif
+CLEANUP:
+	if(rval != E_UPDATE_SINGULAR_COL) EG_RETURN (rval);							/* Bico 031209 - chg from RETURN */
+	return rval;
+}
diff --git a/qsopt_ex/factor.h b/qsopt_ex/factor.h
new file mode 100644
index 0000000..2f2f247
--- /dev/null
+++ b/qsopt_ex/factor.h
@@ -0,0 +1,206 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCSINFO $Id: factor_EGLPNUM_TYPENAME.h,v 1.3 2003/11/05 16:57:39 meven Exp $ */
+#ifndef EGLPNUM_TYPENAME___QS_FACTOR_H_
+#define EGLPNUM_TYPENAME___QS_FACTOR_H_
+
+#include "basicdefs.h"
+#include "dstruct_EGLPNUM_TYPENAME.h"
+
+typedef char EGLPNUM_TYPENAME_QSbool;
+
+typedef struct EGLPNUM_TYPENAME_uc_info
+{
+	int cbeg;
+	int nzcnt;
+	int next;
+	int prev;
+	int delay;
+}
+EGLPNUM_TYPENAME_uc_info;
+
+typedef struct EGLPNUM_TYPENAME_ur_info
+{
+	EGLPNUM_TYPE max;
+	int rbeg;
+	int nzcnt;
+	int pivcnt;
+	int next;
+	int prev;
+	int delay;
+}
+EGLPNUM_TYPENAME_ur_info;
+
+typedef struct EGLPNUM_TYPENAME_lc_info
+{
+	int cbeg;
+	int nzcnt;
+	int c;
+	int crank;
+	int delay;
+}
+EGLPNUM_TYPENAME_lc_info;
+
+typedef struct EGLPNUM_TYPENAME_lr_info
+{
+	int rbeg;
+	int nzcnt;
+	int r;
+	int rrank;
+	int delay;
+}
+EGLPNUM_TYPENAME_lr_info;
+
+typedef struct EGLPNUM_TYPENAME_er_info
+{
+	int rbeg;
+	int nzcnt;
+	int r;
+}
+EGLPNUM_TYPENAME_er_info;
+
+typedef struct EGLPNUM_TYPENAME_factor_work
+{
+	int max_k;
+	EGLPNUM_TYPE fzero_tol;
+	EGLPNUM_TYPE szero_tol;
+	EGLPNUM_TYPE partial_tol;
+	double ur_space_mul;
+	double uc_space_mul;
+	double lc_space_mul;
+	double lr_space_mul;
+	double er_space_mul;
+	double grow_mul;
+	int p;
+	int etamax;
+	double minmult;
+	double maxmult;
+	double updmaxmult;
+	double dense_fract;
+	int dense_min;
+
+	EGLPNUM_TYPE maxelem_orig;
+	int nzcnt_orig;
+	EGLPNUM_TYPE maxelem_factor;
+	int nzcnt_factor;
+	EGLPNUM_TYPE maxelem_cur;
+	int nzcnt_cur;
+
+	EGLPNUM_TYPE partial_cur;
+
+	int dim;
+	int stage;
+	int nstages;
+	int etacnt;
+	EGLPNUM_TYPE *work_coef;
+	int *work_indx;
+	EGLPNUM_TYPENAME_uc_info *uc_inf;
+	EGLPNUM_TYPENAME_ur_info *ur_inf;
+	EGLPNUM_TYPENAME_lc_info *lc_inf;
+	EGLPNUM_TYPENAME_lr_info *lr_inf;
+	EGLPNUM_TYPENAME_er_info *er_inf;
+	int *ucindx;									/* row index for column data */
+	int *ucrind;									/* index of column in row data */
+	EGLPNUM_TYPE *uccoef;						/* coefficient for column data */
+	int *urindx;									/* col index for row data */
+	int *urcind;									/* index of row in column data */
+	EGLPNUM_TYPE *urcoef;						/* coefficient for row data */
+	int *lcindx;									/* row index for L data */
+	EGLPNUM_TYPE *lccoef;						/* coefficient for L row data */
+	int *lrindx;									/* col index for L data */
+	EGLPNUM_TYPE *lrcoef;						/* coefficient for L col data */
+	int *erindx;									/* col index for eta data */
+	EGLPNUM_TYPE *ercoef;						/* coefficient for eta data */
+	int *rperm;
+	int *rrank;
+	int *cperm;
+	int *crank;
+	EGLPNUM_TYPENAME_svector xtmp;
+	int ur_freebeg;
+	int ur_space;
+	int uc_freebeg;
+	int uc_space;
+	int lc_freebeg;
+	int lc_space;
+	int lr_freebeg;
+	int lr_space;
+	int er_freebeg;
+	int er_space;
+
+	int *p_nsing;
+	int **p_singr;
+	int **p_singc;
+
+	EGLPNUM_TYPE *dmat;
+	int drows;
+	int dcols;
+	int dense_base;
+}
+EGLPNUM_TYPENAME_factor_work;
+
+void EGLPNUM_TYPENAME_ILLfactor_init_factor_work (
+	EGLPNUM_TYPENAME_factor_work * f),
+  EGLPNUM_TYPENAME_ILLfactor_free_factor_work (
+	EGLPNUM_TYPENAME_factor_work * f),
+  EGLPNUM_TYPENAME_ILLfactor_ftran (
+	EGLPNUM_TYPENAME_factor_work * f,
+	EGLPNUM_TYPENAME_svector * a,
+	EGLPNUM_TYPENAME_svector * x),
+  EGLPNUM_TYPENAME_ILLfactor_ftran_update (
+	EGLPNUM_TYPENAME_factor_work * f,
+	EGLPNUM_TYPENAME_svector * a,
+	EGLPNUM_TYPENAME_svector * upd,
+	EGLPNUM_TYPENAME_svector * x),
+  EGLPNUM_TYPENAME_ILLfactor_btran (
+	EGLPNUM_TYPENAME_factor_work * f,
+	EGLPNUM_TYPENAME_svector * a,
+	EGLPNUM_TYPENAME_svector * x);
+
+int EGLPNUM_TYPENAME_ILLfactor_create_factor_work (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int dim),
+  EGLPNUM_TYPENAME_ILLfactor_set_factor_iparam (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int param,
+	int val),
+  EGLPNUM_TYPENAME_ILLfactor_set_factor_dparam (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int param,
+	EGLPNUM_TYPE val),
+  EGLPNUM_TYPENAME_ILLfactor (
+	EGLPNUM_TYPENAME_factor_work * f,
+	int *basis,
+	int *cbeg,
+	int *clen,
+	int *cindx,
+	EGLPNUM_TYPE * ccoef,
+	int *p_nsing,
+	int **p_singr,
+	int **p_singc),
+  EGLPNUM_TYPENAME_ILLfactor_update (
+	EGLPNUM_TYPENAME_factor_work * f,
+	EGLPNUM_TYPENAME_svector * a,
+	int col,
+	int *p_refact);
+
+#endif /* EGLPNUM_TYPENAME___QS_FACTOR_H_ */
diff --git a/qsopt_ex/fct.c b/qsopt_ex/fct.c
new file mode 100644
index 0000000..4a88afe
--- /dev/null
+++ b/qsopt_ex/fct.c
@@ -0,0 +1,2501 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: fct.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+static int TRACE = 0;
+
+//#define FCT_DEBUG 10
+#define FCT_DEBUG 0
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "allocrus.h"
+#include "eg_lpnum.h"
+#include "eg_io.h"
+#include "except.h"
+#include "trace.h"
+#include "util.h"
+
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+#include "stddefs.h"
+#include "basis_EGLPNUM_TYPENAME.h"
+#include "fct_EGLPNUM_TYPENAME.h"
+#include "price_EGLPNUM_TYPENAME.h"
+#include "ratio_EGLPNUM_TYPENAME.h"
+#include "dstruct_EGLPNUM_TYPENAME.h"
+
+
+EGLPNUM_TYPENAME_bndinfo *EGLPNUM_TYPENAME_ILLfct_new_bndinfo (
+	void)
+{
+	EGLPNUM_TYPENAME_bndinfo *nbnd = (EGLPNUM_TYPENAME_bndinfo *) malloc (sizeof (EGLPNUM_TYPENAME_bndinfo));
+
+	if (!nbnd)
+	{
+		QSlog("not enough memory, in %s", __func__);
+		exit (1);
+	}
+	EGLPNUM_TYPENAME_EGlpNumInitVar ((nbnd->pbound));
+	EGLPNUM_TYPENAME_EGlpNumInitVar ((nbnd->cbound));
+	return nbnd;
+}
+
+void EGLPNUM_TYPENAME_ILLfct_free_bndinfo (
+	EGLPNUM_TYPENAME_bndinfo * binfo)
+{
+	EGLPNUM_TYPENAME_EGlpNumClearVar ((binfo->pbound));
+	EGLPNUM_TYPENAME_EGlpNumClearVar ((binfo->cbound));
+	ILL_IFFREE (binfo, EGLPNUM_TYPENAME_bndinfo);
+	return;
+}
+
+static int compute_zA1 (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * z,
+	EGLPNUM_TYPENAME_svector * zA,
+	EGLPNUM_TYPE ztoler),
+/*
+  compute_zA2 (EGLPNUM_TYPENAME_lpinfo * lp,
+							 EGLPNUM_TYPENAME_svector * z,
+							 EGLPNUM_TYPENAME_svector * zA,
+							 const EGLPNUM_TYPE* ztoler), */
+  compute_zA3 (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * z,
+	EGLPNUM_TYPENAME_svector * zA,
+	EGLPNUM_TYPE ztoler),
+  expand_var_bounds (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPE ftol,
+	int *chgb),
+  expand_var_coefs (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPE ftol,
+	int *chgc);
+
+static void update_piv_values (
+	EGLPNUM_TYPENAME_count_struct * c,
+	int phase,
+	const EGLPNUM_TYPE piv),
+/*  copy_vectors (EGLPNUM_TYPENAME_svector * a,
+								EGLPNUM_TYPENAME_svector * b),*/
+  add_vectors (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * a,
+	EGLPNUM_TYPENAME_svector * b,
+	EGLPNUM_TYPENAME_svector * c,
+	const EGLPNUM_TYPE t);
+
+static double my_rand (
+	int bound,
+	ILLrandstate * r);
+
+
+void EGLPNUM_TYPENAME_ILLfct_load_workvector (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * s)
+{
+	int i;
+
+	for (i = 0; i < s->nzcnt; i++)
+	{
+		lp->work.indx[i] = s->indx[i];
+		EGLPNUM_TYPENAME_EGlpNumCopy (lp->work.coef[s->indx[i]], s->coef[i]);
+	}
+	lp->work.nzcnt = s->nzcnt;
+}
+
+void EGLPNUM_TYPENAME_ILLfct_zero_workvector (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	int i;
+
+	for (i = 0; i < lp->work.nzcnt; i++)
+		EGLPNUM_TYPENAME_EGlpNumZero (lp->work.coef[lp->work.indx[i]]);
+	lp->work.nzcnt = 0;
+}
+
+void EGLPNUM_TYPENAME_ILLfct_set_variable_type (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	int j;
+
+	for (j = 0; j < lp->ncols; j++)
+	{
+
+		if (lp->matcnt[j] == 1 && lp->O->rowmap[lp->matind[lp->matbeg[j]]] == j)
+			lp->vclass[j] = CLASS_LOGICAL;
+		else
+			lp->vclass[j] = CLASS_STRUCT;
+		switch ((EGLPNUM_TYPENAME_EGlpNumIsEqqual (lp->uz[j], EGLPNUM_TYPENAME_INFTY) ? 1U : 0U) |
+						(EGLPNUM_TYPENAME_EGlpNumIsEqqual (lp->lz[j], EGLPNUM_TYPENAME_NINFTY) ? 2U : 0U))
+		{
+		case 0:
+			if (EGLPNUM_TYPENAME_EGlpNumIsLess (lp->lz[j], lp->uz[j]))
+				lp->vtype[j] = VBOUNDED;
+			else if (!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (lp->lz[j]) &&
+							 (lp->vclass[j] == CLASS_LOGICAL))
+				lp->vtype[j] = VARTIFICIAL;
+			else
+				lp->vtype[j] = VFIXED;
+			break;
+		case 3:
+			lp->vtype[j] = VFREE;
+			break;
+		case 1:
+			lp->vtype[j] = VLOWER;
+			break;
+		case 2:
+			lp->vtype[j] = VUPPER;
+			break;
+		}
+	}
+}
+
+/* compute various vectors */
+
+void EGLPNUM_TYPENAME_ILLfct_compute_pobj (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	int i, j;
+	int col;
+	EGLPNUM_TYPE sum;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (sum);
+	EGLPNUM_TYPENAME_EGlpNumZero (sum);
+
+	for (i = 0; i < lp->nrows; i++)
+		EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, lp->cz[lp->baz[i]], lp->xbz[i]);
+
+	for (j = 0; j < lp->nnbasic; j++)
+	{
+		col = lp->nbaz[j];
+		if (lp->vstat[col] == STAT_UPPER)
+			EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, lp->cz[col], lp->uz[col]);
+		else if (lp->vstat[col] == STAT_LOWER)
+			EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, lp->cz[col], lp->lz[col]);
+	}
+	EGLPNUM_TYPENAME_EGlpNumCopy (lp->pobjval, sum);
+	EGLPNUM_TYPENAME_EGlpNumCopy (lp->objval, sum);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (sum);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_compute_dobj (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	int i, j;
+	int col;
+	EGLPNUM_TYPE sum;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (sum);
+	EGLPNUM_TYPENAME_EGlpNumZero (sum);
+
+	for (i = 0; i < lp->nrows; i++)
+		EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, lp->piz[i], lp->bz[i]);
+
+	for (j = 0; j < lp->nnbasic; j++)
+	{
+		col = lp->nbaz[j];
+		if (lp->vstat[col] == STAT_UPPER)
+			EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, lp->dz[j], lp->uz[col]);
+		else if (lp->vstat[col] == STAT_LOWER)
+			EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, lp->dz[j], lp->lz[col]);
+	}
+	EGLPNUM_TYPENAME_EGlpNumCopy (lp->dobjval, sum);
+	EGLPNUM_TYPENAME_EGlpNumCopy (lp->objval, sum);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (sum);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_compute_xbz (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	int i, j, r;
+	int col, mcnt, mbeg;
+	EGLPNUM_TYPENAME_svector *srhs = &(lp->srhs);
+	EGLPNUM_TYPENAME_svector *ssoln = &(lp->ssoln);
+	EGLPNUM_TYPE xval;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (xval);
+
+	for (i = 0; i < lp->nrows; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumZero (lp->xbz[i]);
+		EGLPNUM_TYPENAME_EGlpNumCopy (srhs->coef[i], lp->bz[i]);
+	}
+	for (j = 0; j < lp->nnbasic; j++)
+	{
+		col = lp->nbaz[j];
+		EGLPNUM_TYPENAME_EGlpNumZero (xval);
+		if (lp->vstat[col] == STAT_UPPER && EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (lp->uz[col]))
+			EGLPNUM_TYPENAME_EGlpNumCopy (xval, lp->uz[col]);
+		else if (lp->vstat[col] == STAT_LOWER && EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (lp->lz[col]))
+			EGLPNUM_TYPENAME_EGlpNumCopy (xval, lp->lz[col]);
+
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (xval))
+		{
+			mcnt = lp->matcnt[col];
+			mbeg = lp->matbeg[col];
+			for (i = 0; i < mcnt; i++)
+				EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (srhs->coef[lp->matind[mbeg + i]], xval,
+														 lp->matval[mbeg + i]);
+		}
+	}
+	for (i = 0, r = 0; i < lp->nrows; i++)
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (srhs->coef[i]))
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (srhs->coef[r], srhs->coef[i]);
+			srhs->indx[r] = i;
+			r++;
+		}
+	srhs->nzcnt = r;
+
+	EGLPNUM_TYPENAME_ILLbasis_column_solve (lp, srhs, ssoln);
+	for (i = 0; i < ssoln->nzcnt; i++)
+		EGLPNUM_TYPENAME_EGlpNumCopy (lp->xbz[ssoln->indx[i]], ssoln->coef[i]);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (xval);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_compute_piz (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	int i, r;
+	EGLPNUM_TYPENAME_svector *srhs = &(lp->srhs);
+	EGLPNUM_TYPENAME_svector *ssoln = &(lp->ssoln);
+
+	for (i = 0, r = 0; i < lp->nrows; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumZero (lp->piz[i]);
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (lp->cz[lp->baz[i]]))
+		{
+			srhs->indx[r] = i;
+			EGLPNUM_TYPENAME_EGlpNumCopy (srhs->coef[r], lp->cz[lp->baz[i]]);
+			r++;
+		}
+	}
+	srhs->nzcnt = r;
+
+	EGLPNUM_TYPENAME_ILLbasis_row_solve (lp, srhs, ssoln);
+	for (i = 0; i < ssoln->nzcnt; i++)
+		EGLPNUM_TYPENAME_EGlpNumCopy (lp->piz[ssoln->indx[i]], ssoln->coef[i]);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_compute_dz (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	int i, j;
+	int col;
+	int mcnt, mbeg;
+	EGLPNUM_TYPE sum;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (sum);
+
+	for (j = 0; j < lp->nnbasic; j++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumZero (sum);
+		col = lp->nbaz[j];
+		mcnt = lp->matcnt[col];
+		mbeg = lp->matbeg[col];
+		for (i = 0; i < mcnt; i++)
+			EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, lp->piz[lp->matind[mbeg + i]],
+													 lp->matval[mbeg + i]);
+		EGLPNUM_TYPENAME_EGlpNumCopyDiff (lp->dz[j], lp->cz[col], sum);
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (sum);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_compute_phaseI_xbz (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	int i, j, r;
+	int col, mcnt, mbeg;
+	EGLPNUM_TYPENAME_svector *srhs = &(lp->srhs);
+	EGLPNUM_TYPENAME_svector *ssoln = &(lp->ssoln);
+
+	for (i = 0; i < lp->nrows; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumZero (lp->xbz[i]);
+		EGLPNUM_TYPENAME_EGlpNumZero (srhs->coef[i]);
+	}
+	for (j = 0; j < lp->nnbasic; j++)
+	{
+		col = lp->nbaz[j];
+
+		if (lp->dfeas[j])
+		{
+			mcnt = lp->matcnt[col];
+			mbeg = lp->matbeg[col];
+			if (lp->dfeas[j] == -1)
+				for (i = 0; i < mcnt; i++)
+					EGLPNUM_TYPENAME_EGlpNumSubTo (srhs->coef[lp->matind[mbeg + i]], lp->matval[mbeg + i]);
+			else
+				for (i = 0; i < mcnt; i++)
+					EGLPNUM_TYPENAME_EGlpNumAddTo (srhs->coef[lp->matind[mbeg + i]], lp->matval[mbeg + i]);
+		}
+	}
+	for (i = 0, r = 0; i < lp->nrows; i++)
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (srhs->coef[i]))
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (srhs->coef[r], srhs->coef[i]);
+			srhs->indx[r] = i;
+			r++;
+		}
+	srhs->nzcnt = r;
+
+	EGLPNUM_TYPENAME_ILLbasis_column_solve (lp, srhs, ssoln);
+	for (i = 0; i < ssoln->nzcnt; i++)
+		EGLPNUM_TYPENAME_EGlpNumCopy (lp->xbz[ssoln->indx[i]], ssoln->coef[i]);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_compute_phaseI_piz (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	int i, r;
+	EGLPNUM_TYPENAME_svector *srhs = &(lp->srhs);
+	EGLPNUM_TYPENAME_svector *ssoln = &(lp->ssoln);
+
+	for (i = 0, r = 0; i < lp->nrows; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumZero (lp->pIpiz[i]);
+		if (lp->bfeas[i] != 0)
+		{
+			srhs->indx[r] = i;
+			EGLPNUM_TYPENAME_EGlpNumSet (srhs->coef[r], (double) lp->bfeas[i]);
+			r++;
+		}
+	}
+	srhs->nzcnt = r;
+
+	EGLPNUM_TYPENAME_ILLbasis_row_solve (lp, srhs, ssoln);
+	for (i = 0; i < ssoln->nzcnt; i++)
+		EGLPNUM_TYPENAME_EGlpNumCopy (lp->pIpiz[ssoln->indx[i]], ssoln->coef[i]);
+	EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_P1PINZ, ssoln->nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_compute_phaseI_dz (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	int i, j;
+	int col;
+	int mcnt, mbeg;
+	EGLPNUM_TYPE sum;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (sum);
+	ILL_IFTRACE ("%s\n", __func__);
+
+	for (j = 0; j < lp->nnbasic; j++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumZero (sum);
+		col = lp->nbaz[j];
+		mcnt = lp->matcnt[col];
+		mbeg = lp->matbeg[col];
+		for (i = 0; i < mcnt; i++)
+			EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, lp->pIpiz[lp->matind[mbeg + i]],
+													 lp->matval[mbeg + i]);
+		EGLPNUM_TYPENAME_EGlpNumCopyNeg (lp->pIdz[j], sum);
+		ILL_IFTRACE ("%d:%d:%lf:%la\n", j, col, EGLPNUM_TYPENAME_EGlpNumToLf (sum),
+								 EGLPNUM_TYPENAME_EGlpNumToLf (sum));
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (sum);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_compute_yz (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * yz,
+	EGLPNUM_TYPENAME_svector * updz,
+	int col)
+{
+	EGLPNUM_TYPENAME_svector a;
+
+	a.nzcnt = lp->matcnt[col];
+	a.indx = &(lp->matind[lp->matbeg[col]]);
+	a.coef = &(lp->matval[lp->matbeg[col]]);
+
+	EGLPNUM_TYPENAME_ILLfactor_set_factor_dparam (lp->f, QS_FACTOR_SZERO_TOL, EGLPNUM_TYPENAME_PIVZ_TOLER);
+	if (updz)
+		EGLPNUM_TYPENAME_ILLbasis_column_solve_update (lp, &a, updz, yz);
+	else
+		EGLPNUM_TYPENAME_ILLbasis_column_solve (lp, &a, yz);
+	EGLPNUM_TYPENAME_ILLfactor_set_factor_dparam (lp->f, QS_FACTOR_SZERO_TOL, EGLPNUM_TYPENAME_SZERO_TOLER);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_compute_zz (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * zz,
+	int row)
+{
+	EGLPNUM_TYPENAME_ILLfct_compute_binvrow (lp, zz, row, EGLPNUM_TYPENAME_PIVZ_TOLER);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_compute_binvrow (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * zz,
+	int row,
+	EGLPNUM_TYPE ztoler)
+{
+	EGLPNUM_TYPENAME_svector a;
+	EGLPNUM_TYPE e;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (e);
+	EGLPNUM_TYPENAME_EGlpNumOne (e);
+
+	a.nzcnt = 1;
+	a.coef = &e;
+	a.indx = &row;
+
+	if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (ztoler))
+		EGLPNUM_TYPENAME_ILLfactor_set_factor_dparam (lp->f, QS_FACTOR_SZERO_TOL, ztoler);
+	EGLPNUM_TYPENAME_ILLbasis_row_solve (lp, &a, zz);
+	if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (ztoler))
+		EGLPNUM_TYPENAME_ILLfactor_set_factor_dparam (lp->f, QS_FACTOR_SZERO_TOL, EGLPNUM_TYPENAME_SZERO_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (e);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_compute_psteep_upv (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * swz)
+{
+	EGLPNUM_TYPENAME_ILLbasis_row_solve (lp, &(lp->yjz), swz);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_compute_dsteep_upv (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * swz)
+{
+	EGLPNUM_TYPENAME_ILLbasis_column_solve (lp, &(lp->zz), swz);
+}
+
+static int compute_zA1 (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * z,
+	EGLPNUM_TYPENAME_svector * zA,
+	EGLPNUM_TYPE ztoler)
+{
+	int rval = 0;
+	int i, j, nz = 0;
+	int col, mcnt, mbeg;
+	EGLPNUM_TYPE sum;
+	EGLPNUM_TYPE *v = 0;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (sum);
+	v = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+
+	for (i = 0; i < lp->nrows; i++)
+		EGLPNUM_TYPENAME_EGlpNumZero (v[i]);
+	for (i = 0; i < z->nzcnt; i++)
+		EGLPNUM_TYPENAME_EGlpNumCopy (v[z->indx[i]], z->coef[i]);
+
+	for (j = 0; j < lp->nnbasic; j++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumZero (sum);
+		col = lp->nbaz[j];
+		mcnt = lp->matcnt[col];
+		mbeg = lp->matbeg[col];
+		for (i = 0; i < mcnt; i++)
+			EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, v[lp->matind[mbeg + i]], lp->matval[mbeg + i]);
+
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (sum, ztoler))
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (zA->coef[nz], sum);
+			zA->indx[nz] = j;
+			nz++;
+		}
+	}
+	zA->nzcnt = nz;
+
+	EGLPNUM_TYPENAME_EGlpNumClearVar (sum);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (v);
+	EG_RETURN (rval);
+}
+
+
+static int compute_zA3 (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * z,
+	EGLPNUM_TYPENAME_svector * zA,
+	EGLPNUM_TYPE ztoler)
+{
+	int rval = 0;
+	int i, j, k, ix;
+	int nz = 0;
+	int row, col;
+	int rcnt, rbeg;
+	EGLPNUM_TYPE val;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (val);
+	k = 0;
+	for (i = 0; i < z->nzcnt; i++)
+	{
+		row = z->indx[i];
+		EGLPNUM_TYPENAME_EGlpNumCopy (val, z->coef[i]);
+		rcnt = lp->rowcnt[row];
+		rbeg = lp->rowbeg[row];
+		for (j = 0; j < rcnt; j++)
+		{
+			col = lp->rowind[rbeg + j];
+			if (lp->vstat[col] != STAT_BASIC)
+			{
+				ix = lp->vindex[col];
+				if (lp->iwork[ix] == 0)
+				{
+					lp->iwork[ix] = 1;
+					lp->work.indx[k++] = ix;
+				}
+				EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (lp->work.coef[ix], val, lp->rowval[rbeg + j]);
+			}
+		}
+	}
+	for (j = 0; j < k; j++)
+	{
+		ix = lp->work.indx[j];
+		EGLPNUM_TYPENAME_EGlpNumCopy (val, lp->work.coef[ix]);
+		EGLPNUM_TYPENAME_EGlpNumZero (lp->work.coef[ix]);
+		lp->iwork[ix] = 0;
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (val, ztoler))
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (zA->coef[nz], val);
+			zA->indx[nz] = ix;
+			nz++;
+		}
+	}
+	zA->nzcnt = nz;
+	EGLPNUM_TYPENAME_EGlpNumClearVar (val);
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLfct_compute_zA (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * z,
+	EGLPNUM_TYPENAME_svector * zA)
+{
+	if (z->nzcnt < lp->nrows / 2)
+		return compute_zA3 (lp, z, zA, EGLPNUM_TYPENAME_PIVZ_TOLER);
+	else
+		return compute_zA1 (lp, z, zA, EGLPNUM_TYPENAME_PIVZ_TOLER);
+}
+
+/* compute v^T A */
+void EGLPNUM_TYPENAME_ILLfct_compute_vA (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * v,
+	EGLPNUM_TYPE * vA)
+{
+	int i, j;
+	int row, col;
+	int rcnt, rbeg;
+	EGLPNUM_TYPE val;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (val);
+
+	for (j = 0; j < lp->ncols; j++)
+		EGLPNUM_TYPENAME_EGlpNumZero (vA[j]);
+
+	for (i = 0; i < v->nzcnt; i++)
+	{
+		row = v->indx[i];
+		EGLPNUM_TYPENAME_EGlpNumCopy (val, v->coef[i]);
+		rcnt = lp->rowcnt[row];
+		rbeg = lp->rowbeg[row];
+		for (j = 0; j < rcnt; j++)
+		{
+			col = lp->rowind[rbeg + j];
+			EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (vA[col], val, lp->rowval[rbeg + j]);
+		}
+	}
+
+	for (j = 0; j < lp->ncols; j++)
+		if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (vA[j], EGLPNUM_TYPENAME_SZERO_TOLER))
+			EGLPNUM_TYPENAME_EGlpNumZero (vA[j]);
+
+	EGLPNUM_TYPENAME_EGlpNumClearVar (val);
+	return;
+}
+
+/* update information */
+
+/*
+1) lvstat - new status of leaving var.
+*/
+void EGLPNUM_TYPENAME_ILLfct_update_basis_info (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int eindex,
+	int lindex,
+	int lvstat)
+{
+	int evar;
+	int lvar;
+
+	evar = lp->nbaz[eindex];
+
+	if (lindex >= 0)
+	{															/* variable leaves basis */
+		lvar = lp->baz[lindex];
+		lp->vstat[evar] = STAT_BASIC;
+		lp->vstat[lvar] = lvstat;
+		lp->vindex[evar] = lindex;
+		lp->vindex[lvar] = eindex;
+		lp->baz[lindex] = evar;
+		lp->nbaz[eindex] = lvar;
+		(lp->basisid)++;
+	}
+	else
+	{
+		lp->vstat[evar] = (lp->vstat[evar] == STAT_LOWER) ? STAT_UPPER : STAT_LOWER;
+	}
+}
+
+void EGLPNUM_TYPENAME_ILLfct_update_xz (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPE tz,
+	int eindex,
+	int lindex)
+{
+	int i, evar, estat;
+
+	ILL_IFTRACE ("%s:%la:%d:%d:%d\n", __func__, EGLPNUM_TYPENAME_EGlpNumToLf (tz), eindex,
+							 lindex, lp->yjz.nzcnt);
+
+	if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (tz))
+		for (i = 0; i < lp->yjz.nzcnt; i++)
+			EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (lp->xbz[lp->yjz.indx[i]], tz, lp->yjz.coef[i]);
+
+	if (lindex >= 0)
+	{															/* variable leaves basis */
+		evar = lp->nbaz[eindex];
+		estat = lp->vstat[evar];
+		if (estat == STAT_LOWER)
+			EGLPNUM_TYPENAME_EGlpNumCopySum (lp->xbz[lindex], lp->lz[evar], tz);
+		else if (estat == STAT_UPPER)
+			EGLPNUM_TYPENAME_EGlpNumCopySum (lp->xbz[lindex], lp->uz[evar], tz);
+		else if (estat == STAT_ZERO)
+			EGLPNUM_TYPENAME_EGlpNumCopy (lp->xbz[lindex], tz);
+	}
+}
+
+void EGLPNUM_TYPENAME_ILLfct_update_piz (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPE alpha)
+{
+	int i;
+
+	for (i = 0; i < lp->zz.nzcnt; i++)
+		EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (lp->piz[lp->zz.indx[i]], alpha, lp->zz.coef[i]);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_update_pIpiz (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * z,
+	const EGLPNUM_TYPE alpha)
+{
+	int i;
+
+	if (!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (alpha))
+		return;
+	if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (alpha, EGLPNUM_TYPENAME_oneLpNum))
+	{
+		for (i = 0; i < z->nzcnt; i++)
+			EGLPNUM_TYPENAME_EGlpNumAddTo (lp->pIpiz[z->indx[i]], z->coef[i]);
+	}
+	else
+	{
+		for (i = 0; i < z->nzcnt; i++)
+			EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (lp->pIpiz[z->indx[i]], alpha, z->coef[i]);
+	}
+}
+
+void EGLPNUM_TYPENAME_ILLfct_update_dz (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int eindex,
+	EGLPNUM_TYPE alpha)
+{
+	int i;
+
+	for (i = 0; i < lp->zA.nzcnt; i++)
+		EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (lp->dz[lp->zA.indx[i]], alpha, lp->zA.coef[i]);
+	EGLPNUM_TYPENAME_EGlpNumCopyNeg (lp->dz[eindex], alpha);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_update_pIdz (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * zA,
+	int eindex,
+	const EGLPNUM_TYPE alpha)
+{
+	int i;
+
+	if (!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (alpha))
+		return;
+
+	if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (alpha, EGLPNUM_TYPENAME_oneLpNum))
+	{
+		for (i = 0; i < zA->nzcnt; i++)
+			EGLPNUM_TYPENAME_EGlpNumSubTo (lp->pIdz[zA->indx[i]], zA->coef[i]);
+	}
+	else
+	{
+		for (i = 0; i < zA->nzcnt; i++)
+			EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (lp->pIdz[zA->indx[i]], alpha, zA->coef[i]);
+	}
+	if (eindex > -1)
+		EGLPNUM_TYPENAME_EGlpNumCopyNeg (lp->pIdz[eindex], alpha);
+}
+
+/* bound and coef shift routines */
+
+/* scale bound in my_rand to get more random digits, unless bound is large */
+static double my_rand (
+	int bound,
+	ILLrandstate * r)
+{
+	int k = bound, scale = 1;
+	double v = 0.0;
+
+	if (bound < 100000)
+	{
+		k = 20000 * bound;
+		scale = 20000;
+	}
+	v = 1 + (ILLutil_lprand (r) % (k));
+	return v / (double) scale;
+}
+
+static int expand_var_bounds (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPE ftol,
+	int *chgb)
+{
+	int rval = 0;
+	int i, col, nchg = 0;
+	EGLPNUM_TYPE newb, cftol;
+	EGLPNUM_TYPE *x, *l, *u;
+	ILLrandstate r;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (newb);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (cftol);
+	EGLPNUM_TYPENAME_EGlpNumCopyAbs (cftol, ftol);
+	EGLPNUM_TYPENAME_EGlpNumDivUiTo (cftol, 10);
+
+	ILLutil_sprand (1, &r);
+
+	for (i = 0; i < lp->nrows; i++)
+	{
+		col = lp->baz[i];
+		if (lp->vtype[col] == VARTIFICIAL || lp->vtype[col] == VFREE)
+			continue;
+		x = &(lp->xbz[i]);
+		l = &(lp->lz[col]);
+		u = &(lp->uz[col]);
+		/* we use newb as temporal variable outside the if's scope */
+		EGLPNUM_TYPENAME_EGlpNumCopyDiff (newb, *x, ftol);
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*l, EGLPNUM_TYPENAME_NINFTY) && EGLPNUM_TYPENAME_EGlpNumIsLess (newb, *l))
+		{
+			EGLPNUM_TYPENAME_EGlpNumSet (newb, -1.0 * (my_rand (50, &(lp->rstate)) + 1.0));
+			EGLPNUM_TYPENAME_EGlpNumMultTo (newb, cftol);
+			if (EGLPNUM_TYPENAME_EGlpNumIsLess (*x, *l))
+				EGLPNUM_TYPENAME_EGlpNumAddTo (newb, *x);
+			else
+				EGLPNUM_TYPENAME_EGlpNumAddTo (newb, *l);
+			rval = EGLPNUM_TYPENAME_ILLfct_bound_shift (lp, col, BOUND_LOWER, newb);
+			CHECKRVALG (rval, CLEANUP);
+			nchg++;
+		}
+		EGLPNUM_TYPENAME_EGlpNumCopySum (newb, *x, ftol);
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*u, EGLPNUM_TYPENAME_INFTY) && EGLPNUM_TYPENAME_EGlpNumIsLess (*u, newb))
+		{
+			EGLPNUM_TYPENAME_EGlpNumSet (newb, my_rand (50, &(lp->rstate)) + 1.0);
+			EGLPNUM_TYPENAME_EGlpNumMultTo (newb, cftol);
+			if (EGLPNUM_TYPENAME_EGlpNumIsLess (*x, *u))
+				EGLPNUM_TYPENAME_EGlpNumAddTo (newb, *u);
+			else
+				EGLPNUM_TYPENAME_EGlpNumAddTo (newb, *x);
+			rval = EGLPNUM_TYPENAME_ILLfct_bound_shift (lp, col, BOUND_UPPER, newb);
+			CHECKRVALG (rval, CLEANUP);
+			nchg++;
+		}
+	}
+	*chgb = nchg;
+
+CLEANUP:
+	EGLPNUM_TYPENAME_EGlpNumClearVar (newb);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (cftol);
+	EG_RETURN (rval);
+}
+
+static int expand_phaseI_bounds (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int *chgb)
+{
+	int rval = 0;
+	int i, col, nchg = 0;
+	EGLPNUM_TYPE newb, cftol;
+	EGLPNUM_TYPE *u, *l, *x;
+	ILLrandstate r;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (newb);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (cftol);
+	EGLPNUM_TYPENAME_EGlpNumCopyAbs (cftol, lp->tol->ip_tol);
+	EGLPNUM_TYPENAME_EGlpNumDivUiTo (cftol, 10);
+	ILLutil_sprand (1, &r);
+
+	for (i = 0; i < lp->nrows; i++)
+	{
+		col = lp->baz[i];
+		if (lp->vtype[col] == VARTIFICIAL || lp->vtype[col] == VFREE)
+			continue;
+		x = &(lp->xbz[i]);
+		l = &(lp->lz[col]);
+		u = &(lp->uz[col]);
+
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*l, EGLPNUM_TYPENAME_NINFTY) && EGLPNUM_TYPENAME_EGlpNumIsEqual (*x, *l, cftol))
+		{
+			EGLPNUM_TYPENAME_EGlpNumSet (newb, my_rand (50, &(lp->rstate)) + 1.0);
+			EGLPNUM_TYPENAME_EGlpNumMultTo (newb, cftol);
+			EGLPNUM_TYPENAME_EGlpNumSign (newb);
+			EGLPNUM_TYPENAME_EGlpNumAddTo (newb, *l);
+			rval = EGLPNUM_TYPENAME_ILLfct_bound_shift (lp, col, BOUND_LOWER, newb);
+			CHECKRVALG (rval, CLEANUP);
+			nchg++;
+		}
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*u, EGLPNUM_TYPENAME_INFTY) && EGLPNUM_TYPENAME_EGlpNumIsEqual (*x, *u, cftol))
+		{
+			EGLPNUM_TYPENAME_EGlpNumSet (newb, my_rand (50, &(lp->rstate)) + 1.0);
+			EGLPNUM_TYPENAME_EGlpNumMultTo (newb, cftol);
+			EGLPNUM_TYPENAME_EGlpNumAddTo (newb, *u);
+			rval = EGLPNUM_TYPENAME_ILLfct_bound_shift (lp, col, BOUND_UPPER, newb);
+			CHECKRVALG (rval, CLEANUP);
+			nchg++;
+		}
+	}
+	*chgb = nchg;
+
+CLEANUP:
+	EGLPNUM_TYPENAME_EGlpNumClearVar (newb);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (cftol);
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLfct_adjust_viol_bounds (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	int rval = 0;
+	int chgb = 0;
+	EGLPNUM_TYPE tol;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (tol);
+	EGLPNUM_TYPENAME_EGlpNumCopyNeg (tol, lp->tol->pfeas_tol);
+	rval = expand_var_bounds (lp, tol, &chgb);
+#if FCT_DEBUG > 0
+	if (rval == 0)
+		QSlog("adjusting %d bounds", chgb);
+#endif
+	EGLPNUM_TYPENAME_EGlpNumClearVar (tol);
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLfct_perturb_bounds (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	int rval = 0;
+	int chgb = 0;
+
+	rval = expand_var_bounds (lp, lp->tol->ip_tol, &chgb);
+#if FCT_DEBUG > 0
+	if (rval == 0)
+		QSlog("perturbing %d bounds", chgb);
+#endif
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLfct_perturb_phaseI_bounds (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	int rval = 0;
+	int chgb = 0;
+
+	rval = expand_phaseI_bounds (lp, &chgb);
+#if FCT_DEBUG > 0
+	if (rval == 0)
+		QSlog("perturbing %d phase I bounds", chgb);
+#endif
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLfct_bound_shift (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int col,
+	int bndtype,
+	EGLPNUM_TYPE newbnd)
+{
+	int rval = 0;
+	EGLPNUM_TYPENAME_bndinfo *nbnd = 0;
+
+	ILL_IFTRACE ("\n%s:%d:%d:%la", __func__, col, bndtype, EGLPNUM_TYPENAME_EGlpNumToLf (newbnd));
+	nbnd = EGLPNUM_TYPENAME_ILLfct_new_bndinfo ();
+
+	nbnd->varnum = col;
+	nbnd->btype = bndtype;
+	if (bndtype == BOUND_LOWER)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (nbnd->pbound, lp->lz[col]);
+		EGLPNUM_TYPENAME_EGlpNumCopy (nbnd->cbound, newbnd);
+		EGLPNUM_TYPENAME_EGlpNumCopy (lp->lz[col], newbnd);
+	}
+	else
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (nbnd->pbound, lp->uz[col]);
+		EGLPNUM_TYPENAME_EGlpNumCopy (nbnd->cbound, newbnd);
+		EGLPNUM_TYPENAME_EGlpNumCopy (lp->uz[col], newbnd);
+	}
+	ILL_IFTRACE (":%la", EGLPNUM_TYPENAME_EGlpNumToLf (nbnd->pbound));
+	if (lp->vtype[col] == VFIXED || lp->vtype[col] == VARTIFICIAL)
+	{
+		/* QSlog("changing f/a bound"); */
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (lp->lz[col], lp->uz[col]))
+			lp->vtype[col] = VBOUNDED;
+	}
+
+	nbnd->next = lp->bchanges;
+	lp->bchanges = nbnd;
+	lp->nbchange++;
+
+//CLEANUP:
+	if (rval)
+		EGLPNUM_TYPENAME_ILLfct_free_bndinfo (nbnd);
+	ILL_IFTRACE ("\n");
+	EG_RETURN (rval);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_unroll_bound_change (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	int col;
+	int changex = 0;
+	EGLPNUM_TYPENAME_bndinfo *bptr = lp->bchanges;
+	EGLPNUM_TYPENAME_bndinfo *nptr = 0;
+
+	ILL_IFTRACE ("%s:", __func__);
+
+	while (lp->nbchange != 0)
+	{
+		col = bptr->varnum;
+		ILL_IFTRACE (":%d", col);
+
+		if (bptr->btype == BOUND_UPPER)
+			EGLPNUM_TYPENAME_EGlpNumCopy (lp->uz[col], bptr->pbound);
+		else
+			EGLPNUM_TYPENAME_EGlpNumCopy (lp->lz[col], bptr->pbound);
+
+		if (lp->vtype[col] == VBOUNDED)
+		{
+			if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (lp->lz[col], lp->uz[col]))
+				lp->vtype[col] = (!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (lp->lz[col])) ?
+					VARTIFICIAL : VFIXED;
+		}
+
+		if (lp->vstat[col] != STAT_BASIC)
+		{
+			if ((bptr->btype == BOUND_UPPER && lp->vstat[col] == STAT_UPPER) ||
+					(bptr->btype == BOUND_LOWER && lp->vstat[col] == STAT_LOWER))
+				changex++;
+		}
+		nptr = bptr->next;
+		EGLPNUM_TYPENAME_EGlpNumClearVar ((bptr->cbound));
+		EGLPNUM_TYPENAME_EGlpNumClearVar ((bptr->pbound));
+		ILL_IFFREE (bptr, EGLPNUM_TYPENAME_bndinfo);
+		bptr = nptr;
+		lp->nbchange--;
+	}
+	lp->bchanges = bptr;
+	ILL_IFTRACE ("\n");
+	if (changex)
+		EGLPNUM_TYPENAME_ILLfct_compute_xbz (lp);
+}
+
+static int expand_var_coefs (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPE ftol,
+	int *chgc)
+{
+	int rval = 0;
+	int i, col, vs, vt;
+	int nchg = 0;
+	EGLPNUM_TYPE newc, cftol, mftol[1];
+	EGLPNUM_TYPE *c, *dj;
+	ILLrandstate r;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (newc);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (cftol);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (mftol[0]);
+	EGLPNUM_TYPENAME_EGlpNumCopyAbs (cftol, ftol);
+	EGLPNUM_TYPENAME_EGlpNumDivUiTo (cftol, 10);
+	EGLPNUM_TYPENAME_EGlpNumCopyNeg (mftol[0], ftol);
+	ILLutil_sprand (1, &r);
+
+	for (i = 0; i < lp->nnbasic; i++)
+	{
+		dj = &(lp->dz[i]);
+		col = lp->nbaz[i];
+		c = &(lp->cz[col]);
+		vs = lp->vstat[col];
+		vt = lp->vtype[col];
+
+		if (vt == VARTIFICIAL || vt == VFIXED)
+			continue;
+		switch (vs)
+		{
+		case STAT_ZERO:
+			EGLPNUM_TYPENAME_EGlpNumCopyDiff (newc, *c, *dj);
+			rval = EGLPNUM_TYPENAME_ILLfct_coef_shift (lp, col, newc);
+			CHECKRVALG (rval, CLEANUP);
+			nchg++;
+			break;
+		case STAT_LOWER:
+			if (EGLPNUM_TYPENAME_EGlpNumIsLess (*dj, ftol))
+			{
+				EGLPNUM_TYPENAME_EGlpNumSet (newc, my_rand (50, &(lp->rstate)) + 1.0);
+				EGLPNUM_TYPENAME_EGlpNumMultTo (newc, cftol);
+				EGLPNUM_TYPENAME_EGlpNumAddTo (newc, *c);
+				if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (*dj))
+					EGLPNUM_TYPENAME_EGlpNumSubTo (newc, *dj);
+				rval = EGLPNUM_TYPENAME_ILLfct_coef_shift (lp, col, newc);
+				CHECKRVALG (rval, CLEANUP);
+				nchg++;
+			}
+			break;
+		case STAT_UPPER:
+			if (EGLPNUM_TYPENAME_EGlpNumIsLess (mftol[0], *dj))
+			{
+				EGLPNUM_TYPENAME_EGlpNumSet (newc, my_rand (50, &(lp->rstate)) + 1.0);
+				EGLPNUM_TYPENAME_EGlpNumMultTo (newc, cftol);
+				EGLPNUM_TYPENAME_EGlpNumSign (newc);
+				EGLPNUM_TYPENAME_EGlpNumAddTo (newc, *c);
+				if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (*dj))
+					EGLPNUM_TYPENAME_EGlpNumSubTo (newc, *dj);
+				rval = EGLPNUM_TYPENAME_ILLfct_coef_shift (lp, col, newc);
+				CHECKRVALG (rval, CLEANUP);
+				nchg++;
+			}
+			break;
+		default:
+			break;
+		}
+	}
+	*chgc = nchg;
+
+CLEANUP:
+	EGLPNUM_TYPENAME_EGlpNumClearVar (mftol[0]);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (newc);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (cftol);
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLfct_adjust_viol_coefs (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	int rval = 0;
+	int chgc = 0;
+	EGLPNUM_TYPE tol;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (tol);
+	EGLPNUM_TYPENAME_EGlpNumCopyNeg (tol, lp->tol->dfeas_tol);
+
+	rval = expand_var_coefs (lp, tol, &chgc);
+#if FCT_DEBUG > 0
+	if (rval == 0)
+		QSlog("perturbing %d coefs", chgc);
+#endif
+	EGLPNUM_TYPENAME_EGlpNumClearVar (tol);
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLfct_perturb_coefs (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	int rval = 0;
+	int chgc = 0;
+
+	rval = expand_var_coefs (lp, lp->tol->id_tol, &chgc);
+#if FCT_DEBUG > 0
+	if (rval == 0)
+		QSlog("perturbing %d coefs", chgc);
+#endif
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLfct_coef_shift (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int col,
+	EGLPNUM_TYPE newcoef)
+{
+	int rval = 0;
+	EGLPNUM_TYPENAME_coefinfo *ncoef = 0;
+
+	ILL_SAFE_MALLOC (ncoef, 1, EGLPNUM_TYPENAME_coefinfo);
+	EGLPNUM_TYPENAME_EGlpNumInitVar ((ncoef->pcoef));
+	EGLPNUM_TYPENAME_EGlpNumInitVar ((ncoef->ccoef));
+
+	ncoef->varnum = col;
+	EGLPNUM_TYPENAME_EGlpNumCopy (ncoef->pcoef, lp->cz[col]);
+	EGLPNUM_TYPENAME_EGlpNumCopy (ncoef->ccoef, newcoef);
+	EGLPNUM_TYPENAME_EGlpNumCopy (lp->cz[col], newcoef);
+	ncoef->next = lp->cchanges;
+	lp->cchanges = ncoef;
+	EGLPNUM_TYPENAME_EGlpNumAddTo (lp->dz[lp->vindex[col]], ncoef->ccoef);
+	EGLPNUM_TYPENAME_EGlpNumSubTo (lp->dz[lp->vindex[col]], ncoef->pcoef);
+	lp->ncchange++;
+
+CLEANUP:
+	if (rval)
+	{
+		EGLPNUM_TYPENAME_EGlpNumClearVar ((ncoef->pcoef));
+		EGLPNUM_TYPENAME_EGlpNumClearVar ((ncoef->ccoef));
+		ILL_IFFREE (ncoef, EGLPNUM_TYPENAME_coefinfo);
+	}
+	EG_RETURN (rval);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_unroll_coef_change (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	int bascoef = 0;
+	EGLPNUM_TYPENAME_coefinfo *cptr = (EGLPNUM_TYPENAME_coefinfo *) lp->cchanges;
+	EGLPNUM_TYPENAME_coefinfo *nptr = 0;
+
+	while (lp->ncchange != 0)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (lp->cz[cptr->varnum], cptr->pcoef);
+		if (lp->vstat[cptr->varnum] != STAT_BASIC)
+		{
+			EGLPNUM_TYPENAME_EGlpNumAddTo (lp->dz[lp->vindex[cptr->varnum]], cptr->pcoef);
+			EGLPNUM_TYPENAME_EGlpNumSubTo (lp->dz[lp->vindex[cptr->varnum]], cptr->ccoef);
+		}
+		else
+			bascoef++;
+
+		nptr = cptr->next;
+		EGLPNUM_TYPENAME_EGlpNumClearVar ((cptr->pcoef));
+		EGLPNUM_TYPENAME_EGlpNumClearVar ((cptr->ccoef));
+		ILL_IFFREE (cptr, EGLPNUM_TYPENAME_coefinfo);
+		cptr = nptr;
+		lp->ncchange--;
+	}
+	lp->cchanges = cptr;
+	if (bascoef)
+	{
+		EGLPNUM_TYPENAME_ILLfct_compute_piz (lp);
+		EGLPNUM_TYPENAME_ILLfct_compute_dz (lp);
+	}
+}
+
+/* feasibility routines */
+void EGLPNUM_TYPENAME_ILLfct_check_pfeasible (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_feas_info * fs,
+	const EGLPNUM_TYPE ftol)
+{
+	int i, col;
+	EGLPNUM_TYPE infeas, err1, err2;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (infeas);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (err1);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (err2);
+	EGLPNUM_TYPENAME_EGlpNumZero (infeas);
+	fs->pstatus = PRIMAL_FEASIBLE;
+	EGLPNUM_TYPENAME_EGlpNumZero (fs->totinfeas);
+	ILL_IFTRACE ("%s:tol %la\n", __func__, EGLPNUM_TYPENAME_EGlpNumToLf (ftol));
+
+	for (i = 0; i < lp->nrows; i++)
+	{
+		col = lp->baz[i];
+		EGLPNUM_TYPENAME_EGlpNumCopyDiff (err1, lp->xbz[i], lp->uz[col]);
+		EGLPNUM_TYPENAME_EGlpNumCopyDiff (err2, lp->lz[col], lp->xbz[i]);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (ftol, err1)
+				&& EGLPNUM_TYPENAME_EGlpNumIsNeq (lp->uz[col], EGLPNUM_TYPENAME_INFTY, EGLPNUM_TYPENAME_oneLpNum))
+		{
+			EGLPNUM_TYPENAME_EGlpNumAddTo (infeas, err1);
+			WARNINGL (QSE_WLVL, EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_INFTY, err1),
+							 "This is imposible lu = %15lg xbz = %15lg" " EGLPNUM_TYPENAME_INFTY = %15lg",
+							 EGLPNUM_TYPENAME_EGlpNumToLf (lp->uz[col]), EGLPNUM_TYPENAME_EGlpNumToLf (lp->xbz[i]),
+							 EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_INFTY));
+			lp->bfeas[i] = 1;
+		}
+		else if (EGLPNUM_TYPENAME_EGlpNumIsLess (ftol, err2)
+						 && EGLPNUM_TYPENAME_EGlpNumIsNeq (lp->lz[col], EGLPNUM_TYPENAME_NINFTY, EGLPNUM_TYPENAME_oneLpNum))
+		{
+			EGLPNUM_TYPENAME_EGlpNumAddTo (infeas, err2);
+			WARNINGL (QSE_WLVL, EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_INFTY, err2),
+							 "This is imposible lz = %15lg xbz = %15lg" " EGLPNUM_TYPENAME_NINFTY = %15lg",
+							 EGLPNUM_TYPENAME_EGlpNumToLf (lp->lz[col]), EGLPNUM_TYPENAME_EGlpNumToLf (lp->xbz[i]),
+							 EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_NINFTY));
+			lp->bfeas[i] = -1;
+		}
+		else
+			lp->bfeas[i] = 0;
+	}
+	if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (infeas))
+	{
+		fs->pstatus = PRIMAL_INFEASIBLE;
+		EGLPNUM_TYPENAME_EGlpNumCopy (fs->totinfeas, infeas);
+		ILL_IFTRACE ("%s:inf %la\n", __func__, EGLPNUM_TYPENAME_EGlpNumToLf (infeas));
+		if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (fs->totinfeas))
+		{
+			QSlog("Negative infeasibility, Imposible! %lf %la",
+									EGLPNUM_TYPENAME_EGlpNumToLf (infeas), EGLPNUM_TYPENAME_EGlpNumToLf (infeas));
+		}
+	}
+	EGLPNUM_TYPENAME_EGlpNumCopy (lp->pinfeas, infeas);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (infeas);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (err1);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (err2);
+}
+
+/* feasibility routines */
+void EGLPNUM_TYPENAME_ILLfct_check_pIpfeasible (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_feas_info * fs,
+	EGLPNUM_TYPE ftol)
+{
+	int i, col;
+	int ninf = 0;
+
+	fs->pstatus = PRIMAL_FEASIBLE;
+	EGLPNUM_TYPENAME_EGlpNumZero (fs->totinfeas);
+
+	for (i = 0; i < lp->nrows; i++)
+	{
+		if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (lp->xbz[i], ftol))
+			continue;
+		col = lp->baz[i];
+		if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero(lp->xbz[i]) &&
+				EGLPNUM_TYPENAME_EGlpNumIsNeqq (lp->uz[col], EGLPNUM_TYPENAME_INFTY))
+		{
+			ninf++;
+		}
+		else if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (lp->xbz[i]) &&
+						 EGLPNUM_TYPENAME_EGlpNumIsNeqq (lp->lz[col], EGLPNUM_TYPENAME_NINFTY))
+		{
+			ninf++;
+		}
+	}
+	if (ninf != 0)
+		fs->pstatus = PRIMAL_INFEASIBLE;
+}
+
+void EGLPNUM_TYPENAME_ILLfct_check_dfeasible (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_feas_info * fs,
+	const EGLPNUM_TYPE ftol)
+{
+	int j, col;
+	EGLPNUM_TYPE infeas;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (infeas);
+	EGLPNUM_TYPENAME_EGlpNumZero (infeas);
+	fs->dstatus = DUAL_FEASIBLE;
+	EGLPNUM_TYPENAME_EGlpNumZero (fs->totinfeas);
+
+	for (j = 0; j < lp->nnbasic; j++)
+	{
+		lp->dfeas[j] = 0;
+		if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (lp->dz[j], ftol))
+			continue;
+		col = lp->nbaz[j];
+
+		if (lp->vtype[col] == VARTIFICIAL || lp->vtype[col] == VFIXED)
+			continue;
+
+		if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (lp->dz[j]) &&
+				(lp->vstat[col] == STAT_LOWER || lp->vstat[col] == STAT_ZERO))
+		{
+			EGLPNUM_TYPENAME_EGlpNumSubTo (infeas, lp->dz[j]);
+			lp->dfeas[j] = -1;
+		}
+		else if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (lp->dz[j]) &&
+						 (lp->vstat[col] == STAT_UPPER || lp->vstat[col] == STAT_ZERO))
+		{
+			EGLPNUM_TYPENAME_EGlpNumAddTo (infeas, lp->dz[j]);
+			lp->dfeas[j] = 1;
+		}
+	}
+
+	if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (infeas))
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (fs->totinfeas, infeas);
+		fs->dstatus = DUAL_INFEASIBLE;
+		ILL_IFTRACE ("%s:inf %la\n", __func__, EGLPNUM_TYPENAME_EGlpNumToLf (infeas));
+		if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (fs->totinfeas))
+		{
+			QSlog("Negative infeasibility, Imposible! %lf %la",
+									EGLPNUM_TYPENAME_EGlpNumToLf (infeas), EGLPNUM_TYPENAME_EGlpNumToLf (infeas));
+		}
+	}
+	EGLPNUM_TYPENAME_EGlpNumCopy (lp->dinfeas, infeas);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (infeas);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_check_pIdfeasible (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_feas_info * fs,
+	EGLPNUM_TYPE ftol)
+{
+	int j, col;
+	int ninf = 0;
+	EGLPNUM_TYPE *dz = lp->pIdz;
+
+	fs->dstatus = DUAL_FEASIBLE;
+
+	for (j = 0; j < lp->nnbasic; j++)
+	{
+		if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (dz[j], ftol))
+			continue;
+		col = lp->nbaz[j];
+		if (lp->vtype[col] == VARTIFICIAL || lp->vtype[col] == VFIXED)
+			continue;
+
+		if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (dz[j]) &&
+				(lp->vstat[col] == STAT_LOWER || lp->vstat[col] == STAT_ZERO))
+			ninf++;
+		else if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (dz[j]) &&
+						 (lp->vstat[col] == STAT_UPPER || lp->vstat[col] == STAT_ZERO))
+			ninf++;
+	}
+
+	if (ninf != 0)
+		fs->dstatus = DUAL_INFEASIBLE;
+}
+
+void EGLPNUM_TYPENAME_ILLfct_dual_adjust (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	const EGLPNUM_TYPE ftol)
+{
+	int j, col;
+
+	for (j = 0; j < lp->nnbasic; j++)
+	{
+		if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (lp->dz[j], ftol))
+			continue;
+		col = lp->nbaz[j];
+		if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (lp->dz[j]) &&
+				EGLPNUM_TYPENAME_EGlpNumIsNeqq (lp->uz[col], EGLPNUM_TYPENAME_INFTY))
+			lp->vstat[col] = STAT_UPPER;
+		else if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (lp->dz[j]) &&
+						 EGLPNUM_TYPENAME_EGlpNumIsNeqq (lp->lz[col], EGLPNUM_TYPENAME_NINFTY))
+			lp->vstat[col] = STAT_LOWER;
+	}
+}
+
+void EGLPNUM_TYPENAME_ILLfct_dphaseI_simple_update (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPE ftol)
+{
+	int j, col;
+
+	for (j = 0; j < lp->nnbasic; j++)
+	{
+		if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (lp->dz[j], ftol))
+			continue;
+		col = lp->nbaz[j];
+		if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (lp->dz[j] ) && lp->vtype[col] == VBOUNDED)
+			lp->vstat[col] = STAT_UPPER;
+		else if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (lp->dz[j]) && lp->vtype[col] == VBOUNDED)
+			lp->vstat[col] = STAT_LOWER;
+	}
+}
+
+/* set status values */
+void EGLPNUM_TYPENAME_ILLfct_set_status_values (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int pstatus,
+	int dstatus,
+	int ptype,
+	int dtype)
+{
+	if (dstatus == DUAL_FEASIBLE && dtype == PHASEII)
+	{
+		if (!lp->ncchange)
+		{
+			lp->probstat.dual_feasible = 1;
+			lp->basisstat.dual_feasible = 1;
+			lp->basisstat.dual_infeasible = 0;
+		}
+	}
+	if (dstatus == DUAL_INFEASIBLE && dtype == PHASEII)
+	{
+		if (!lp->ncchange)
+		{
+			lp->basisstat.dual_feasible = 0;
+			lp->basisstat.dual_infeasible = 1;
+		}
+		if (pstatus == PRIMAL_FEASIBLE && ptype == PHASEI)
+			if (!lp->ncchange)
+				lp->probstat.dual_infeasible = 1;
+	}
+	if (pstatus == PRIMAL_FEASIBLE && ptype == PHASEII)
+	{
+		if (!lp->nbchange)
+		{
+			lp->probstat.primal_feasible = 1;
+			lp->basisstat.primal_feasible = 1;
+			lp->basisstat.primal_infeasible = 0;
+		}
+	}
+	if (pstatus == PRIMAL_INFEASIBLE && ptype == PHASEII)
+	{
+		lp->basisstat.primal_feasible = 0;
+		lp->basisstat.primal_infeasible = 1;
+
+		if (dstatus == DUAL_FEASIBLE && dtype == PHASEI)
+			lp->probstat.primal_infeasible = 1;
+	}
+	if (pstatus == PRIMAL_UNBOUNDED)
+	{
+		if (!lp->nbchange)
+		{
+			lp->probstat.primal_unbounded = 1;
+			lp->basisstat.primal_unbounded = 1;
+			lp->probstat.dual_infeasible = 1;
+			lp->basisstat.dual_infeasible = 1;
+			lp->basisstat.dual_feasible = 0;
+		}
+	}
+	if (dstatus == DUAL_UNBOUNDED)
+	{
+		if (!lp->ncchange)
+		{
+			lp->probstat.dual_unbounded = 1;
+			lp->basisstat.dual_unbounded = 1;
+			lp->probstat.primal_infeasible = 1;
+			lp->basisstat.primal_infeasible = 1;
+			lp->basisstat.primal_feasible = 0;
+		}
+	}
+	if (lp->probstat.primal_feasible && lp->probstat.dual_feasible)
+		lp->probstat.optimal = 1;
+
+	if (lp->basisstat.primal_feasible && lp->basisstat.dual_feasible)
+		lp->basisstat.optimal = 1;
+	else
+		lp->basisstat.optimal = 0;
+}
+
+void EGLPNUM_TYPENAME_ILLfct_init_counts (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	int i;
+	EGLPNUM_TYPENAME_count_struct *c = lp->cnts;
+
+#define C_VALUE(a) (1.0+(double)(a)/(PARAM_HEAP_RATIO*ILLutil_our_log2(a)))
+	EGLPNUM_TYPENAME_EGlpNumSet (c->y_ravg, C_VALUE (lp->nrows));
+	EGLPNUM_TYPENAME_EGlpNumSet (c->za_ravg, C_VALUE (lp->nnbasic));
+	ILL_IFTRACE ("%s:%la\n", __func__, EGLPNUM_TYPENAME_EGlpNumToLf (c->za_ravg));
+#undef C_VALUE
+	c->ynz_cnt = 0;
+	c->num_y = 0;
+	c->znz_cnt = 0;
+	c->num_z = 0;
+	c->zanz_cnt = 0;
+	c->num_za = 0;
+	c->pnorm_cnt = 0;
+	c->dnorm_cnt = 0;
+	c->pinz_cnt = 0;
+	c->num_pi = 0;
+	c->pi1nz_cnt = 0;
+	c->num_pi1 = 0;
+	c->upnz_cnt = 0;
+	c->num_up = 0;
+	c->pupv_cnt = 0;
+	c->dupv_cnt = 0;
+	c->pI_iter = 0;
+	c->pII_iter = 0;
+	c->dI_iter = 0;
+	c->dII_iter = 0;
+	c->tot_iter = 0;
+	for (i = 0; i < 10; i++)
+	{
+		c->pivpI[i] = 0;
+		c->pivpII[i] = 0;
+		c->pivdI[i] = 0;
+		c->pivdII[i] = 0;
+	}
+}
+
+static void update_piv_values (
+	EGLPNUM_TYPENAME_count_struct * c,
+	int phase,
+	const EGLPNUM_TYPE piv2)
+{
+	int i = 0;
+	EGLPNUM_TYPE v, piv;
+
+	if (!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero(piv2))
+		return;
+	EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (piv);
+	EGLPNUM_TYPENAME_EGlpNumCopyAbs (piv, piv2);
+	EGLPNUM_TYPENAME_EGlpNumOne (v);
+	while (EGLPNUM_TYPENAME_EGlpNumIsLess (piv, v) && i < 9)
+	{
+		EGLPNUM_TYPENAME_EGlpNumDivUiTo (v, 10);
+		i++;
+	}
+	switch (phase)
+	{
+	case PRIMAL_PHASEI:
+		c->pivpI[i]++;
+		break;
+	case PRIMAL_PHASEII:
+		c->pivpII[i]++;
+		break;
+	case DUAL_PHASEI:
+		c->pivdI[i]++;
+		break;
+	case DUAL_PHASEII:
+		c->pivdII[i]++;
+		break;
+	default:
+		break;
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (piv);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_update_counts (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int f,
+	int upi,
+	const EGLPNUM_TYPE upd)
+{
+	EGLPNUM_TYPENAME_count_struct *c = lp->cnts;
+
+	switch (f)
+	{
+	case CNT_PPHASE1ITER:
+		c->pI_iter++;
+		c->tot_iter++;
+		break;
+	case CNT_PPHASE2ITER:
+		c->pII_iter++;
+		c->tot_iter++;
+		break;
+	case CNT_DPHASE1ITER:
+		c->dI_iter++;
+		c->tot_iter++;
+		break;
+	case CNT_DPHASE2ITER:
+		c->dII_iter++;
+		c->tot_iter++;
+		break;
+	case CNT_YNZ:
+		c->ynz_cnt += upi;
+		c->num_y++;
+		break;
+	case CNT_ZANZ:
+		c->zanz_cnt += upi;
+		c->num_za++;
+		break;
+	case CNT_PINZ:
+		c->pinz_cnt += upi;
+		c->num_pi++;
+		break;
+	case CNT_P1PINZ:
+		c->pi1nz_cnt += upi;
+		c->num_pi1++;
+		break;
+	case CNT_UPNZ:
+		c->upnz_cnt += upi;
+		c->num_up++;
+		break;
+	case CNT_PIPIV:
+		update_piv_values (c, PRIMAL_PHASEI, upd);
+		break;
+	case CNT_PIIPIV:
+		update_piv_values (c, PRIMAL_PHASEII, upd);
+		break;
+	case CNT_DIPIV:
+		update_piv_values (c, DUAL_PHASEI, upd);
+		break;
+	case CNT_DIIPIV:
+		update_piv_values (c, DUAL_PHASEII, upd);
+		break;
+	case CNT_YRAVG:
+		EGLPNUM_TYPENAME_EGlpNumMultUiTo (c->y_ravg, c->tot_iter);
+		EGLPNUM_TYPENAME_EGlpNumAddUiTo (c->y_ravg, upi);
+		EGLPNUM_TYPENAME_EGlpNumDivUiTo (c->y_ravg, c->tot_iter + 1);
+		break;
+	case CNT_ZARAVG:
+		ILL_IFTRACE ("%s:%d:%d:%d:%la:%la", __func__, f, c->tot_iter, upi,
+								 EGLPNUM_TYPENAME_EGlpNumToLf (upd), EGLPNUM_TYPENAME_EGlpNumToLf (c->za_ravg));
+		EGLPNUM_TYPENAME_EGlpNumMultUiTo (c->za_ravg, c->tot_iter);
+		EGLPNUM_TYPENAME_EGlpNumAddUiTo (c->za_ravg, upi);
+		EGLPNUM_TYPENAME_EGlpNumDivUiTo (c->za_ravg, c->tot_iter + 1);
+		ILL_IFTRACE (":%la\n", EGLPNUM_TYPENAME_EGlpNumToLf (c->za_ravg));
+		break;
+	}
+}
+
+void EGLPNUM_TYPENAME_ILLfct_print_counts (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	int i, niter;
+	EGLPNUM_TYPENAME_count_struct *c = lp->cnts;
+
+	c->tot_iter = c->pI_iter + c->pII_iter + c->dI_iter + c->dII_iter;
+	niter = (c->tot_iter == 0) ? 1 : c->tot_iter;
+	QSlog("Counts for problem %s", lp->O->probname);
+	if (c->num_y != 0)
+		QSlog("avg ynz = %.2f", (double) c->ynz_cnt / c->num_y);
+	if (c->num_z != 0)
+		QSlog("avg znz = %.2f", (double) c->znz_cnt / c->num_z);
+	if (c->num_za != 0)
+		QSlog("avg zanz = %.2f", (double) c->zanz_cnt / c->num_za);
+	QSlog("avg pnorm = %.2f", (double) c->pnorm_cnt / lp->nnbasic);
+	QSlog("avg dnorm = %.2f", (double) c->dnorm_cnt / lp->nrows);
+	if (c->num_pi != 0)
+		QSlog("avg pinz = %.2f", (double) c->pinz_cnt / c->num_pi);
+	if (c->num_pi1 != 0)
+		QSlog("avg piInz = %.2f", (double) c->pi1nz_cnt / c->num_pi1);
+	if (c->num_up != 0)
+		QSlog("avg upnz = %.2f", (double) c->upnz_cnt / c->num_up);
+
+	for (i = 0; i < 10; i++)
+		QSlog("piv 1.0e-%d : %d %d %d %d",
+								i, c->pivpI[i], c->pivpII[i], c->pivdI[i], c->pivdII[i]);
+}
+
+
+/* c <- a + t*b */
+static void add_vectors (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * a,
+	EGLPNUM_TYPENAME_svector * b,
+	EGLPNUM_TYPENAME_svector * c,
+	const EGLPNUM_TYPE t)
+{
+	int i, r, l;
+	EGLPNUM_TYPENAME_svector *w = &(lp->work);
+
+	for (i = 0; i < b->nzcnt; i++)
+	{
+		r = b->indx[i];
+		w->indx[i] = r;
+		EGLPNUM_TYPENAME_EGlpNumCopy (w->coef[r], t);
+		EGLPNUM_TYPENAME_EGlpNumMultTo (w->coef[r], b->coef[i]);
+		lp->iwork[r] = 1;
+	}
+	l = b->nzcnt;
+
+	for (i = 0; i < a->nzcnt; i++)
+	{
+		r = a->indx[i];
+		if (lp->iwork[r] == 0)
+			w->indx[l++] = r;
+		EGLPNUM_TYPENAME_EGlpNumAddTo (w->coef[r], a->coef[i]);
+	}
+	for (i = 0; i < l; i++)
+	{
+		r = w->indx[i];
+		c->indx[i] = r;
+		EGLPNUM_TYPENAME_EGlpNumCopy (c->coef[i], w->coef[r]);
+		EGLPNUM_TYPENAME_EGlpNumZero (w->coef[r]);
+		lp->iwork[r] = 0;
+	}
+	w->nzcnt = 0;
+	c->nzcnt = l;
+}
+
+void EGLPNUM_TYPENAME_ILLfct_update_pfeas (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int lindex,
+	EGLPNUM_TYPENAME_svector * srhs)
+{
+	int i, k, r;
+	int col, nz = 0;
+	int cbnd, f;
+	int *perm = lp->upd.perm;
+	int *ix = lp->upd.ix;
+	int tctr = lp->upd.tctr;
+	EGLPNUM_TYPE *t = lp->upd.t;
+	EGLPNUM_TYPE tz, *dty, ntmp;
+	EGLPNUM_TYPE *l, *x, *u, *pftol = &(lp->tol->ip_tol);
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (tz);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (ntmp);
+	dty = &(lp->upd.dty);
+	EGLPNUM_TYPENAME_EGlpNumZero (*dty);
+	EGLPNUM_TYPENAME_EGlpNumCopyAbs (tz, lp->upd.tz);
+	EGLPNUM_TYPENAME_EGlpNumDivUiTo (tz, 100);
+	EGLPNUM_TYPENAME_EGlpNumAddTo (tz, lp->upd.tz);
+	ILL_IFTRACE ("%s:%d", __func__, tctr);
+	for (i = 0; i < tctr && EGLPNUM_TYPENAME_EGlpNumIsLeq (t[perm[i]], tz); i++)
+	{
+		cbnd = ix[perm[i]] % 10;
+		ILL_IFTRACE (":%d", cbnd);
+		if (cbnd == BBOUND)
+			continue;
+		k = ix[perm[i]] / 10;
+		r = lp->yjz.indx[k];
+		ILL_IFTRACE (":%d:%d:%d", k, r, lp->iwork[r]);
+
+		if (lp->iwork[r] != 1)
+		{
+			lp->iwork[r] = 1;
+			x = &(lp->xbz[r]);
+			col = lp->baz[r];
+			l = &(lp->lz[col]);
+			u = &(lp->uz[col]);
+
+			if (r != lindex)
+			{
+				f = 0;
+				EGLPNUM_TYPENAME_EGlpNumCopyDiff (ntmp, *l, *x);
+				if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*l, EGLPNUM_TYPENAME_NINFTY) && EGLPNUM_TYPENAME_EGlpNumIsLess (*pftol, ntmp))
+					f = -1;
+				else
+				{
+					EGLPNUM_TYPENAME_EGlpNumCopyDiff (ntmp, *x, *u);
+					if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*u, EGLPNUM_TYPENAME_INFTY) && EGLPNUM_TYPENAME_EGlpNumIsLess (*pftol, ntmp))
+						f = 1;
+				}
+
+				ILL_IFTRACE (":%d:%d", f, lp->bfeas[r]);
+				if (f != lp->bfeas[r])
+				{
+					srhs->indx[nz] = r;
+					EGLPNUM_TYPENAME_EGlpNumSet (srhs->coef[nz], (double) (f - lp->bfeas[r]));
+					EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (*dty, srhs->coef[nz], lp->yjz.coef[k]);
+					nz++;
+					lp->bfeas[r] = f;
+				}
+			}
+			else
+			{
+				lp->bfeas[r] = 0;
+			}
+		}
+	}
+	while (--i >= 0)
+	{
+		cbnd = ix[perm[i]] % 10;
+		if (cbnd == BBOUND)
+			continue;
+		k = ix[perm[i]] / 10;
+		r = lp->yjz.indx[k];
+		lp->iwork[r] = 0;
+	}
+	srhs->nzcnt = nz;
+	ILL_IFTRACE (":%d\n", nz);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (tz);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_compute_ppIzz (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * srhs,
+	EGLPNUM_TYPENAME_svector * ssoln)
+{
+	if (srhs->nzcnt != 0)
+	{
+		ILL_IFTRACE ("%s:\n", __func__);
+		EGLPNUM_TYPENAME_ILLbasis_row_solve (lp, srhs, ssoln);
+	}
+}
+
+void EGLPNUM_TYPENAME_ILLfct_update_ppI_prices (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * pinf,
+	EGLPNUM_TYPENAME_svector * srhs,
+	EGLPNUM_TYPENAME_svector * ssoln,
+	int eindex,
+	int lindex,
+	const EGLPNUM_TYPE alpha)
+{
+	EGLPNUM_TYPE ntmp;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (ntmp);
+	EGLPNUM_TYPENAME_EGlpNumCopy (ntmp, alpha);
+	ILL_IFTRACE ("%s:\n", __func__);
+	if (lindex == -1)
+	{
+		if (srhs->nzcnt != 0)
+		{
+			EGLPNUM_TYPENAME_ILLfct_update_pIpiz (lp, ssoln, EGLPNUM_TYPENAME_oneLpNum);
+			if (pinf->p_strategy == COMPLETE_PRICING)
+			{
+				EGLPNUM_TYPENAME_ILLfct_compute_zA (lp, ssoln, &(lp->zA));
+				EGLPNUM_TYPENAME_ILLfct_update_pIdz (lp, &(lp->zA), -1, EGLPNUM_TYPENAME_oneLpNum);
+			}
+		}
+		else
+		{
+			if (pinf->p_strategy == COMPLETE_PRICING)
+				EGLPNUM_TYPENAME_ILLprice_compute_dual_inf (lp, pinf, &eindex, 1, PRIMAL_PHASEI);
+			else
+				EGLPNUM_TYPENAME_ILLprice_update_mpartial_price (lp, pinf, PRIMAL_PHASEI, COL_PRICING);
+			EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+			return;
+		}
+	}
+	else
+	{
+		if (srhs->nzcnt == 0)
+		{
+			EGLPNUM_TYPENAME_ILLfct_update_pIpiz (lp, &(lp->zz), ntmp);
+			if (pinf->p_strategy == COMPLETE_PRICING)
+				EGLPNUM_TYPENAME_ILLfct_update_pIdz (lp, &(lp->zA), eindex, ntmp);
+		}
+		else
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopyFrac (ntmp, lp->upd.dty, lp->upd.piv);
+			EGLPNUM_TYPENAME_EGlpNumSubTo (ntmp, alpha);
+			EGLPNUM_TYPENAME_EGlpNumSign (ntmp);
+			add_vectors (lp, ssoln, &(lp->zz), &(lp->zz), ntmp);
+			EGLPNUM_TYPENAME_ILLfct_update_pIpiz (lp, &(lp->zz), EGLPNUM_TYPENAME_oneLpNum);
+			if (pinf->p_strategy == COMPLETE_PRICING)
+			{
+				EGLPNUM_TYPENAME_ILLfct_compute_zA (lp, &(lp->zz), &(lp->zA));
+				EGLPNUM_TYPENAME_ILLfct_update_pIdz (lp, &(lp->zA), eindex, EGLPNUM_TYPENAME_oneLpNum);
+			}
+		}
+		EGLPNUM_TYPENAME_EGlpNumSet (lp->pIdz[eindex], (double) (lp->upd.fs));
+		EGLPNUM_TYPENAME_EGlpNumAddTo (lp->pIdz[eindex], ntmp);
+		EGLPNUM_TYPENAME_EGlpNumSign (lp->pIdz[eindex]);
+	}
+	if (pinf->p_strategy == COMPLETE_PRICING)
+	{
+		EGLPNUM_TYPENAME_ILLprice_compute_dual_inf (lp, pinf, lp->zA.indx, lp->zA.nzcnt,
+															 PRIMAL_PHASEI);
+		if (eindex > -1)
+			EGLPNUM_TYPENAME_ILLprice_compute_dual_inf (lp, pinf, &eindex, 1, PRIMAL_PHASEI);
+		EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_ZARAVG, lp->zA.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+	}
+	else
+		EGLPNUM_TYPENAME_ILLprice_update_mpartial_price (lp, pinf, PRIMAL_PHASEI, COL_PRICING);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+	return;
+}
+
+void EGLPNUM_TYPENAME_ILLfct_update_dfeas (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int eindex,
+	EGLPNUM_TYPENAME_svector * srhs)
+{
+	int i, j, k, c;
+	int cbnd, col, nz = 0;
+	int vs, vt, f;
+	int delta;
+	int *perm = lp->upd.perm;
+	int *ix = lp->upd.ix;
+	int tctr = lp->upd.tctr;
+	int mcnt, mbeg;
+	EGLPNUM_TYPE *t = lp->upd.t;
+	EGLPNUM_TYPE *w = lp->work.coef;
+	EGLPNUM_TYPE tz;
+	EGLPNUM_TYPE *dty = &(lp->upd.dty);
+	EGLPNUM_TYPE *dftol = &(lp->tol->id_tol);
+	EGLPNUM_TYPE dj;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (dj);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (tz);
+	EGLPNUM_TYPENAME_EGlpNumZero (*dty);
+	EGLPNUM_TYPENAME_EGlpNumCopy (tz, lp->upd.tz);
+	EGLPNUM_TYPENAME_EGlpNumMultUiTo (tz, 101);
+	EGLPNUM_TYPENAME_EGlpNumDivUiTo (tz, 100);
+
+	for (j = 0; j < tctr && EGLPNUM_TYPENAME_EGlpNumIsLeq (t[perm[j]], tz); j++)
+	{
+		k = ix[perm[j]] / 10;
+		c = lp->zA.indx[k];
+
+		if (lp->iwork[c] != 1)
+		{
+			lp->iwork[c] = 1;
+			cbnd = ix[perm[j]] % 10;
+			col = lp->nbaz[c];
+			EGLPNUM_TYPENAME_EGlpNumCopy (dj, lp->dz[c]);
+			vs = lp->vstat[col];
+			vt = lp->vtype[col];
+
+			if (cbnd == BSKIP)
+			{
+				if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (dj, *dftol));
+				else if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (dj) && vs == STAT_LOWER)
+					lp->vstat[col] = STAT_UPPER;
+				else if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (dj) && vs == STAT_UPPER)
+					lp->vstat[col] = STAT_LOWER;
+			}
+			else if (c != eindex)
+			{
+				if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (dj, *dftol))
+					f = 0;
+				else if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (dj) &&
+								 (vs == STAT_LOWER || vs == STAT_ZERO))
+					f = -1;
+				else if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (dj) &&
+								 (vs == STAT_UPPER || vs == STAT_ZERO))
+					f = 1;
+				else
+					f = 0;
+
+				if (f != lp->dfeas[c])
+				{
+					delta = f - lp->dfeas[c];
+					mcnt = lp->matcnt[col];
+					mbeg = lp->matbeg[col];
+					EGLPNUM_TYPENAME_EGlpNumSet (dj, (double) (delta));
+					for (i = 0; i < mcnt; i++)
+						EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (w[lp->matind[mbeg + i]], dj,
+																 lp->matval[mbeg + i]);
+					EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (*dty, dj, lp->zA.coef[k]);
+					nz = 1;
+					lp->dfeas[c] = f;
+				}
+			}
+			else
+			{
+				lp->dfeas[c] = 0;
+			}
+		}
+	}
+	while (--j >= 0)
+	{
+		k = ix[perm[j]] / 10;
+		c = lp->zA.indx[k];
+		lp->iwork[c] = 0;
+	}
+
+	if (nz)
+	{
+		for (i = 0, nz = 0; i < lp->nrows; i++)
+			if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (w[i]))
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (srhs->coef[nz], w[i]);
+				srhs->indx[nz] = i;
+				nz++;
+				EGLPNUM_TYPENAME_EGlpNumZero (w[i]);
+			}
+	}
+
+	srhs->nzcnt = nz;
+	EGLPNUM_TYPENAME_EGlpNumClearVar (dj);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (tz);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_compute_dpIy (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * srhs,
+	EGLPNUM_TYPENAME_svector * ssoln)
+{
+	if (srhs->nzcnt != 0)
+	{
+		EGLPNUM_TYPENAME_ILLbasis_column_solve (lp, srhs, ssoln);
+	}
+}
+
+void EGLPNUM_TYPENAME_ILLfct_update_dpI_prices (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * pinf,
+	EGLPNUM_TYPENAME_svector * srhs,
+	EGLPNUM_TYPENAME_svector * ssoln,
+	int lindex,
+	EGLPNUM_TYPE alpha)
+{
+	int i;
+	EGLPNUM_TYPE ntmp;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (ntmp);
+	EGLPNUM_TYPENAME_EGlpNumZero (ntmp);
+
+	if (srhs->nzcnt == 0)
+	{
+		EGLPNUM_TYPENAME_ILLfct_update_xz (lp, alpha, -1, -1);
+	}
+	else
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopyFrac (ntmp, lp->upd.dty, lp->upd.piv);
+		EGLPNUM_TYPENAME_EGlpNumAddTo (ntmp, alpha);
+		EGLPNUM_TYPENAME_EGlpNumSign (ntmp);
+		add_vectors (lp, ssoln, &(lp->yjz), &(lp->yjz), ntmp);
+		EGLPNUM_TYPENAME_EGlpNumSign (ntmp);
+		for (i = 0; i < lp->yjz.nzcnt; i++)
+			EGLPNUM_TYPENAME_EGlpNumAddTo (lp->xbz[lp->yjz.indx[i]], lp->yjz.coef[i]);
+	}
+	EGLPNUM_TYPENAME_EGlpNumSet (lp->xbz[lindex], ((double) (-lp->upd.fs)));
+	EGLPNUM_TYPENAME_EGlpNumAddTo (lp->xbz[lindex], ntmp);
+
+	if (pinf->d_strategy == COMPLETE_PRICING)
+	{
+		EGLPNUM_TYPENAME_ILLprice_compute_primal_inf (lp, pinf, lp->yjz.indx, lp->yjz.nzcnt,
+																 DUAL_PHASEI);
+		EGLPNUM_TYPENAME_ILLprice_compute_primal_inf (lp, pinf, &lindex, 1, DUAL_PHASEI);
+		EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_YRAVG, lp->yjz.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+	}
+	else
+		EGLPNUM_TYPENAME_ILLprice_update_mpartial_price (lp, pinf, DUAL_PHASEI, ROW_PRICING);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_update_dIIfeas (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int eindex,
+	EGLPNUM_TYPENAME_svector * srhs)
+{
+	int j, k;
+	int col, indx, vs;
+	int *perm = lp->upd.perm;
+	int *ix = lp->upd.ix;
+	int tctr = lp->upd.tctr;
+	EGLPNUM_TYPE *zAj, *l, *u;
+	EGLPNUM_TYPE *dty = &(lp->upd.dty);
+	EGLPNUM_TYPE *t_max = &(lp->upd.tz);
+	EGLPNUM_TYPE *t = lp->upd.t;
+	EGLPNUM_TYPE delta;
+	EGLPNUM_TYPENAME_svector a;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (delta);
+	EGLPNUM_TYPENAME_EGlpNumZero (delta);
+	EGLPNUM_TYPENAME_EGlpNumZero (*dty);
+
+	srhs->nzcnt = 0;
+	for (j = 0; j < tctr && EGLPNUM_TYPENAME_EGlpNumIsLeq (t[perm[j]], *t_max); j++)
+	{
+		k = ix[perm[j]];
+		indx = lp->zA.indx[k];
+
+		if (indx != eindex)
+		{
+			zAj = &(lp->zA.coef[k]);
+			col = lp->nbaz[indx];
+			l = &(lp->lz[col]);
+			u = &(lp->uz[col]);
+			vs = lp->vstat[col];
+			if (vs == STAT_UPPER)
+				EGLPNUM_TYPENAME_EGlpNumCopyDiff (delta, *l, *u);
+			else
+				EGLPNUM_TYPENAME_EGlpNumCopyDiff (delta, *u, *l);
+			EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (*dty, delta, *zAj);
+			lp->vstat[col] = (vs == STAT_UPPER) ? STAT_LOWER : STAT_UPPER;
+
+			a.nzcnt = lp->matcnt[col];
+			a.indx = &(lp->matind[lp->matbeg[col]]);
+			a.coef = &(lp->matval[lp->matbeg[col]]);
+			add_vectors (lp, srhs, &a, srhs, delta);
+		}
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (delta);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_compute_dpIIy (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * srhs,
+	EGLPNUM_TYPENAME_svector * ssoln)
+{
+	if (srhs->nzcnt != 0)
+	{
+		EGLPNUM_TYPENAME_ILLbasis_column_solve (lp, srhs, ssoln);
+	}
+}
+
+void EGLPNUM_TYPENAME_ILLfct_update_dpII_prices (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * pinf,
+	EGLPNUM_TYPENAME_svector * srhs,
+	EGLPNUM_TYPENAME_svector * ssoln,
+	/*int eindex,*/
+	int lindex,
+	EGLPNUM_TYPE eval,
+	EGLPNUM_TYPE alpha)
+{
+	int i;
+	EGLPNUM_TYPENAME_svector *u;
+
+	if (srhs->nzcnt == 0)
+	{
+		EGLPNUM_TYPENAME_ILLfct_update_xz (lp, alpha, -1, -1);
+		u = &(lp->yjz);
+	}
+	else
+	{
+		if (ssoln->nzcnt != 0)
+			for (i = 0; i < ssoln->nzcnt; i++)
+				EGLPNUM_TYPENAME_EGlpNumSubTo (lp->xbz[ssoln->indx[i]], ssoln->coef[i]);
+		EGLPNUM_TYPENAME_ILLfct_update_xz (lp, alpha, -1, -1);
+		add_vectors (lp, ssoln, &(lp->yjz), ssoln, EGLPNUM_TYPENAME_oneLpNum);
+		u = ssoln;
+	}
+	EGLPNUM_TYPENAME_EGlpNumCopySum (lp->xbz[lindex], eval, alpha);
+
+	if (pinf->d_strategy == COMPLETE_PRICING)
+	{
+		EGLPNUM_TYPENAME_ILLprice_compute_primal_inf (lp, pinf, u->indx, u->nzcnt, DUAL_PHASEII);
+		EGLPNUM_TYPENAME_ILLprice_compute_primal_inf (lp, pinf, &lindex, 1, DUAL_PHASEII);
+		EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_YRAVG, u->nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+	}
+	else
+		EGLPNUM_TYPENAME_ILLprice_update_mpartial_price (lp, pinf, DUAL_PHASEII, ROW_PRICING);
+}
+
+int EGLPNUM_TYPENAME_ILLfct_test_pivot (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int indx,
+	int indxtype,
+	EGLPNUM_TYPE piv_val)
+{
+	int i;
+	EGLPNUM_TYPE pval, ntmp;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (pval);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (ntmp);
+	EGLPNUM_TYPENAME_EGlpNumZero (pval);
+
+	if (indxtype == ROW_PIVOT)
+	{
+		for (i = 0; i < lp->yjz.nzcnt; i++)
+			if (lp->yjz.indx[i] == indx)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (pval, lp->yjz.coef[i]);
+				break;
+			}
+	}
+	else
+	{
+		for (i = 0; i < lp->zA.nzcnt; i++)
+			if (lp->zA.indx[i] == indx)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (pval, lp->zA.coef[i]);
+				break;
+			}
+	}
+	EGLPNUM_TYPENAME_EGlpNumCopyDiff (ntmp, pval, piv_val);
+	EGLPNUM_TYPENAME_EGlpNumDivTo (ntmp, piv_val);
+	if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (ntmp))
+		EGLPNUM_TYPENAME_EGlpNumSign (ntmp);
+	if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_ALTPIV_TOLER, ntmp))
+	{
+#if FCT_DEBUG > 1
+		if (indxtype == ROW_PIVOT)
+			QSlog("y_i = %.8f, z_j = %.8f %la %la", EGLPNUM_TYPENAME_EGlpNumToLf (pval),
+									EGLPNUM_TYPENAME_EGlpNumToLf (piv_val), EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_ALTPIV_TOLER),
+									EGLPNUM_TYPENAME_EGlpNumToLf (ntmp));
+		else
+			QSlog("z_j = %.8f, y_i = %.8f", EGLPNUM_TYPENAME_EGlpNumToLf (pval),
+									EGLPNUM_TYPENAME_EGlpNumToLf (piv_val));
+#endif
+		EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (pval);
+		return 1;
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (pval);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+	return 0;
+}
+
+#if FCT_DEBUG > 0
+
+void EGLPNUM_TYPENAME_fct_test_workvector (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	int i, err = 0;
+
+	for (i = 0; i < lp->ncols; i++)
+	{
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (lp->work.coef[i]))
+		{
+			err++;
+			EGLPNUM_TYPENAME_EGlpNumZero (lp->work.coef[i]);
+		}
+		if (lp->iwork[i] != 0)
+		{
+			err++;
+			lp->iwork[i] = 0;
+		}
+	}
+	if (err)
+		QSlog("bad work vector, err=%d", err);
+}
+
+void EGLPNUM_TYPENAME_fct_test_pfeasible (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	int i, col;
+	int err = 0;
+	EGLPNUM_TYPE *ftol = &(lp->tol->pfeas_tol);
+
+	for (i = 0; i < lp->nrows; i++)
+	{
+		col = lp->baz[i];
+
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (lp->uz[col], EGLPNUM_TYPENAME_INFTY)
+				&& EGLPNUM_TYPENAME_EGlpNumIsSumLess (*ftol, lp->uz[col], lp->xbz[i]))
+		{
+			if (lp->bfeas[i] != 1)
+			{
+				err++;
+				lp->bfeas[i] = 1;
+			}
+		}
+		else if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (lp->lz[col], EGLPNUM_TYPENAME_NINFTY)
+						 && EGLPNUM_TYPENAME_EGlpNumIsSumLess (lp->xbz[i], *ftol, lp->lz[col]))
+		{
+			if (lp->bfeas[i] != -1)
+			{
+				err++;
+				lp->bfeas[i] = -1;
+			}
+		}
+		/* else if (lp->bfeas[i] != 0) {err++; lp->bfeas[i] = 0;} */
+	}
+	if (err != 0)
+		QSlog("test_pfeas err =%d", err);
+}
+
+void EGLPNUM_TYPENAME_fct_test_dfeasible (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	int j, col;
+	int err = 0;
+	EGLPNUM_TYPE *ftol = &(lp->tol->dfeas_tol);
+	EGLPNUM_TYPE mftol[1];
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (mftol[0]);
+	EGLPNUM_TYPENAME_EGlpNumCopyNeg (mftol[0], *ftol);
+
+	for (j = 0; j < lp->nnbasic; j++)
+	{
+		col = lp->nbaz[j];
+
+		if (lp->vtype[col] == VARTIFICIAL || lp->vtype[col] == VFIXED)
+			continue;
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (lp->dz[j], mftol[0]) &&
+				(lp->vstat[col] == STAT_LOWER || lp->vstat[col] == STAT_ZERO))
+		{
+			if (lp->dfeas[j] != -1)
+			{
+				err++;
+				lp->dfeas[j] = -1;
+			}
+		}
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (*ftol, lp->dz[j]) &&
+				(lp->vstat[col] == STAT_UPPER || lp->vstat[col] == STAT_ZERO))
+		{
+			if (lp->dfeas[j] != 1)
+			{
+				err++;
+				lp->dfeas[j] = 1;
+			}
+		}
+		/* else if (lp->dfeas[j] != 0) {err++; lp->dfeas[j] = 0;} */
+	}
+	if (err != 0)
+		QSlog("test_dfeas err =%d", err);
+}
+
+void EGLPNUM_TYPENAME_fct_test_pI_x (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * p)
+{
+	int i;
+	int ern = 0;
+	EGLPNUM_TYPE *x;
+	EGLPNUM_TYPE err, diff;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (err);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (diff);
+	EGLPNUM_TYPENAME_EGlpNumZero (err);
+	x = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+
+	for (i = 0; i < lp->nrows; i++)
+		EGLPNUM_TYPENAME_EGlpNumCopy (x[i], lp->xbz[i]);
+	EGLPNUM_TYPENAME_ILLfct_compute_phaseI_xbz (lp);
+	for (i = 0; i < lp->nrows; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopyDiff (diff, x[i], lp->xbz[i]);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (diff))
+			EGLPNUM_TYPENAME_EGlpNumSign (diff);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_PFEAS_TOLER, diff))
+		{
+			EGLPNUM_TYPENAME_EGlpNumAddTo (err, diff);
+			ern++;
+			QSlog("bad i = %d", i);
+		}
+	}
+	if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (err))
+		QSlog("dI x err = %.7f, ern = %d", EGLPNUM_TYPENAME_EGlpNumToLf (err), ern);
+	EGLPNUM_TYPENAME_ILLprice_compute_primal_inf (lp, p, NULL, 0, DUAL_PHASEI);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (x);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (diff);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (err);
+}
+
+void EGLPNUM_TYPENAME_fct_test_pII_x (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * p)
+{
+	int i;
+	int ern = 0;
+	EGLPNUM_TYPE *x;
+	EGLPNUM_TYPE err, diff;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (err);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (diff);
+	EGLPNUM_TYPENAME_EGlpNumZero (err);
+	x = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+
+	for (i = 0; i < lp->nrows; i++)
+		EGLPNUM_TYPENAME_EGlpNumCopy (x[i], lp->xbz[i]);
+	EGLPNUM_TYPENAME_ILLfct_compute_xbz (lp);
+	for (i = 0; i < lp->nrows; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopyDiff (diff, x[i], lp->xbz[i]);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (diff ))
+			EGLPNUM_TYPENAME_EGlpNumSign (diff);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_PFEAS_TOLER, diff))
+		{
+			EGLPNUM_TYPENAME_EGlpNumAddTo (err, diff);
+			ern++;
+			QSlog("bad i = %d", i);
+		}
+	}
+	if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (err))
+		QSlog("dII x err = %.7f, ern = %d", EGLPNUM_TYPENAME_EGlpNumToLf (err), ern);
+	EGLPNUM_TYPENAME_ILLprice_compute_primal_inf (lp, p, NULL, 0, DUAL_PHASEII);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (x);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (diff);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (err);
+}
+
+void EGLPNUM_TYPENAME_fct_test_pI_pi_dz (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * p)
+{
+	int i;
+	int ern = 0;
+	EGLPNUM_TYPE *pidz;
+	EGLPNUM_TYPE err, diff;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (err);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (diff);
+	pidz = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->ncols);
+	EGLPNUM_TYPENAME_EGlpNumZero (err);
+
+	for (i = 0; i < lp->nrows; i++)
+		EGLPNUM_TYPENAME_EGlpNumCopy (pidz[i], lp->pIpiz[i]);
+	EGLPNUM_TYPENAME_ILLfct_compute_phaseI_piz (lp);
+	for (i = 0; i < lp->nrows; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopyDiff (diff, pidz[i], lp->pIpiz[i]);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (diff))
+			EGLPNUM_TYPENAME_EGlpNumSign (diff);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_DFEAS_TOLER, diff))
+		{
+			EGLPNUM_TYPENAME_EGlpNumAddTo (err, diff);
+			ern++;
+		}
+	}
+	if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (err))
+		QSlog("pI pi err = %.7f, ern = %d", EGLPNUM_TYPENAME_EGlpNumToLf (err), ern);
+
+	EGLPNUM_TYPENAME_EGlpNumZero (err);
+	ern = 0;
+	for (i = 0; i < lp->nnbasic; i++)
+		EGLPNUM_TYPENAME_EGlpNumCopy (pidz[i], lp->pIdz[i]);
+	EGLPNUM_TYPENAME_ILLfct_compute_phaseI_dz (lp);
+	for (i = 0; i < lp->nnbasic; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopyDiff (diff, pidz[i], lp->pIdz[i]);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (diff))
+			EGLPNUM_TYPENAME_EGlpNumSign (diff);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_DFEAS_TOLER, diff))
+		{
+			EGLPNUM_TYPENAME_EGlpNumAddTo (err, diff);
+			ern++;
+		}
+	}
+	if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (err))
+		QSlog("pI dz err = %.7f, ern = %d", EGLPNUM_TYPENAME_EGlpNumToLf (err), ern);
+	EGLPNUM_TYPENAME_ILLprice_compute_dual_inf (lp, p, NULL, 0, PRIMAL_PHASEI);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (err);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (diff);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (pidz);
+}
+
+void EGLPNUM_TYPENAME_fct_test_pII_pi_dz (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * p)
+{
+	int i;
+	int ern = 0;
+	EGLPNUM_TYPE *pidz;
+	EGLPNUM_TYPE err, diff;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (err);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (diff);
+	EGLPNUM_TYPENAME_EGlpNumZero (err);
+	pidz = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->ncols);
+
+	for (i = 0; i < lp->nrows; i++)
+		EGLPNUM_TYPENAME_EGlpNumCopy (pidz[i], lp->piz[i]);
+	EGLPNUM_TYPENAME_ILLfct_compute_piz (lp);
+	for (i = 0; i < lp->nrows; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopyDiff (diff, pidz[i], lp->piz[i]);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (diff))
+			EGLPNUM_TYPENAME_EGlpNumSign (diff);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_DFEAS_TOLER, diff))
+		{
+			EGLPNUM_TYPENAME_EGlpNumAddTo (err, diff);
+			ern++;
+		}
+	}
+	if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (err))
+		QSlog("pII pi err = %.7f, ern = %d", EGLPNUM_TYPENAME_EGlpNumToLf (err), ern);
+
+	EGLPNUM_TYPENAME_EGlpNumZero (err);
+	ern = 0;
+	for (i = 0; i < lp->nnbasic; i++)
+		EGLPNUM_TYPENAME_EGlpNumCopy (pidz[i], lp->dz[i]);
+	EGLPNUM_TYPENAME_ILLfct_compute_dz (lp);
+	for (i = 0; i < lp->nnbasic; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopyDiff (diff, pidz[i], lp->dz[i]);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (diff))
+			EGLPNUM_TYPENAME_EGlpNumSign (diff);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_DFEAS_TOLER, diff))
+		{
+			EGLPNUM_TYPENAME_EGlpNumAddTo (err, diff);
+			ern++;
+		}
+	}
+	if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (err))
+		QSlog("pII dz err = %.7f, ern = %d", EGLPNUM_TYPENAME_EGlpNumToLf (err), ern);
+	/*
+	 * EGLPNUM_TYPENAME_ILLprice_compute_dual_inf (lp, p, NULL, 0, PRIMAL_PHASEII);
+	 */
+	EGLPNUM_TYPENAME_EGlpNumClearVar (err);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (diff);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (pidz);
+}
+
+#endif
diff --git a/qsopt_ex/fct.h b/qsopt_ex/fct.h
new file mode 100644
index 0000000..acee452
--- /dev/null
+++ b/qsopt_ex/fct.h
@@ -0,0 +1,250 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCSINFO $Id: fct_EGLPNUM_TYPENAME.h,v 1.3 2003/11/05 16:57:39 meven Exp $ */
+#ifndef EGLPNUM_TYPENAME___FUNCTIONS_H
+#define EGLPNUM_TYPENAME___FUNCTIONS_H
+
+#include "basicdefs.h"
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+
+
+int EGLPNUM_TYPENAME_ILLfct_compute_zA (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * z,
+	EGLPNUM_TYPENAME_svector * zA),
+  EGLPNUM_TYPENAME_ILLfct_compute_wz (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPE * wz),
+  EGLPNUM_TYPENAME_ILLfct_adjust_viol_bounds (
+	EGLPNUM_TYPENAME_lpinfo * lp),
+  EGLPNUM_TYPENAME_ILLfct_perturb_bounds (
+	EGLPNUM_TYPENAME_lpinfo * lp),
+  EGLPNUM_TYPENAME_ILLfct_perturb_phaseI_bounds (
+	EGLPNUM_TYPENAME_lpinfo * lp),
+  EGLPNUM_TYPENAME_ILLfct_bound_shift (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int col,
+	int bndtype,
+	EGLPNUM_TYPE newbnd),
+  EGLPNUM_TYPENAME_ILLfct_adjust_viol_coefs (
+	EGLPNUM_TYPENAME_lpinfo * lp),
+  EGLPNUM_TYPENAME_ILLfct_perturb_coefs (
+	EGLPNUM_TYPENAME_lpinfo * lp),
+  EGLPNUM_TYPENAME_ILLfct_coef_shift (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int col,
+	EGLPNUM_TYPE newcoef),
+  EGLPNUM_TYPENAME_ILLfct_test_pivot (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int indx,
+	int indxtype,
+	EGLPNUM_TYPE piv_val);
+
+void EGLPNUM_TYPENAME_ILLfct_load_workvector (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * s),
+  EGLPNUM_TYPENAME_ILLfct_zero_workvector (
+	EGLPNUM_TYPENAME_lpinfo * lp),
+  EGLPNUM_TYPENAME_ILLfct_set_variable_type (
+	EGLPNUM_TYPENAME_lpinfo * lp),
+  EGLPNUM_TYPENAME_ILLfct_compute_pobj (
+	EGLPNUM_TYPENAME_lpinfo * lp),
+  EGLPNUM_TYPENAME_ILLfct_compute_dobj (
+	EGLPNUM_TYPENAME_lpinfo * lp),
+  EGLPNUM_TYPENAME_ILLfct_compute_xbz (
+	EGLPNUM_TYPENAME_lpinfo * lp),
+  EGLPNUM_TYPENAME_ILLfct_compute_piz (
+	EGLPNUM_TYPENAME_lpinfo * lp),
+  EGLPNUM_TYPENAME_ILLfct_compute_phaseI_xbz (
+	EGLPNUM_TYPENAME_lpinfo * lp),
+  EGLPNUM_TYPENAME_ILLfct_compute_phaseI_piz (
+	EGLPNUM_TYPENAME_lpinfo * lp),
+  EGLPNUM_TYPENAME_ILLfct_compute_dz (
+	EGLPNUM_TYPENAME_lpinfo * lp),
+  EGLPNUM_TYPENAME_ILLfct_compute_phaseI_dz (
+	EGLPNUM_TYPENAME_lpinfo * lp),
+  EGLPNUM_TYPENAME_ILLfct_compute_yz (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * yz,
+	EGLPNUM_TYPENAME_svector * updz,
+	int ecol),
+  EGLPNUM_TYPENAME_ILLfct_compute_zz (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * zz,
+	int lindex),
+  EGLPNUM_TYPENAME_ILLfct_compute_binvrow (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * zz,
+	int row,
+	EGLPNUM_TYPE ztoler),
+  EGLPNUM_TYPENAME_ILLfct_compute_vA (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * v,
+	EGLPNUM_TYPE * vA),
+  EGLPNUM_TYPENAME_ILLfct_compute_psteep_upv (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * swz),
+  EGLPNUM_TYPENAME_ILLfct_compute_dsteep_upv (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * swz),
+  EGLPNUM_TYPENAME_ILLfct_update_basis_info (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int eindex,
+	int lindex,
+	int lvstat),
+  EGLPNUM_TYPENAME_ILLfct_update_xz (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPE tz,
+	int eindex,
+	int lindex),
+  EGLPNUM_TYPENAME_ILLfct_update_piz (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPE alpha),
+  EGLPNUM_TYPENAME_ILLfct_update_pIpiz (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * z,
+	const EGLPNUM_TYPE alpha),
+  EGLPNUM_TYPENAME_ILLfct_update_dz (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int eindex,
+	EGLPNUM_TYPE alpha),
+  EGLPNUM_TYPENAME_ILLfct_update_pIdz (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * zA,
+	int eindex,
+	const EGLPNUM_TYPE alpha),
+  EGLPNUM_TYPENAME_ILLfct_unroll_bound_change (
+	EGLPNUM_TYPENAME_lpinfo * lp),
+  EGLPNUM_TYPENAME_ILLfct_unroll_coef_change (
+	EGLPNUM_TYPENAME_lpinfo * lp),
+  EGLPNUM_TYPENAME_ILLfct_check_pfeasible (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_feas_info * fs,
+	const EGLPNUM_TYPE ftol),
+  EGLPNUM_TYPENAME_ILLfct_check_pIpfeasible (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_feas_info * fs,
+	EGLPNUM_TYPE ftol),
+  EGLPNUM_TYPENAME_ILLfct_check_dfeasible (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_feas_info * fs,
+	const EGLPNUM_TYPE ftol),
+  EGLPNUM_TYPENAME_ILLfct_dual_adjust (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	const EGLPNUM_TYPE ftol),
+  EGLPNUM_TYPENAME_ILLfct_dphaseI_simple_update (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPE ftol),
+  EGLPNUM_TYPENAME_ILLfct_set_status_values (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int pstatus,
+	int dstatus,
+	int ptype,
+	int dtype),
+  EGLPNUM_TYPENAME_ILLfct_init_counts (
+	EGLPNUM_TYPENAME_lpinfo * lp),
+  EGLPNUM_TYPENAME_ILLfct_update_counts (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int f,
+	int upi,
+	const EGLPNUM_TYPE upd),
+  EGLPNUM_TYPENAME_ILLfct_print_counts (
+	EGLPNUM_TYPENAME_lpinfo * lp),
+  EGLPNUM_TYPENAME_ILLfct_check_pIdfeasible (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_feas_info * fs,
+	EGLPNUM_TYPE ftol),
+  EGLPNUM_TYPENAME_ILLfct_update_pfeas (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int lindex,
+	EGLPNUM_TYPENAME_svector * srhs),
+  EGLPNUM_TYPENAME_ILLfct_compute_ppIzz (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * srhs,
+	EGLPNUM_TYPENAME_svector * ssoln),
+  EGLPNUM_TYPENAME_ILLfct_update_ppI_prices (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * pinf,
+	EGLPNUM_TYPENAME_svector * srhs,
+	EGLPNUM_TYPENAME_svector * ssoln,
+	int eindex,
+	int lindex,
+	const EGLPNUM_TYPE alpha),
+  EGLPNUM_TYPENAME_ILLfct_update_dfeas (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int eindex,
+	EGLPNUM_TYPENAME_svector * srhs),
+  EGLPNUM_TYPENAME_ILLfct_compute_dpIy (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * srhs,
+	EGLPNUM_TYPENAME_svector * ssoln),
+  EGLPNUM_TYPENAME_ILLfct_update_dpI_prices (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * pinf,
+	EGLPNUM_TYPENAME_svector * srhs,
+	EGLPNUM_TYPENAME_svector * ssoln,
+	int lindex,
+	EGLPNUM_TYPE alpha),
+  EGLPNUM_TYPENAME_ILLfct_update_dIIfeas (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int eindex,
+	EGLPNUM_TYPENAME_svector * srhs),
+  EGLPNUM_TYPENAME_ILLfct_compute_dpIIy (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_svector * srhs,
+	EGLPNUM_TYPENAME_svector * ssoln),
+  EGLPNUM_TYPENAME_ILLfct_update_dpII_prices (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * pinf,
+	EGLPNUM_TYPENAME_svector * srhs,
+	EGLPNUM_TYPENAME_svector * ssoln,
+	/*int eindex,*/
+	int lindex,
+	EGLPNUM_TYPE eval,
+	EGLPNUM_TYPE alpha);
+
+void EGLPNUM_TYPENAME_fct_test_workvector (
+	EGLPNUM_TYPENAME_lpinfo * lp),
+  EGLPNUM_TYPENAME_fct_test_pfeasible (
+	EGLPNUM_TYPENAME_lpinfo * lp),
+  EGLPNUM_TYPENAME_fct_test_dfeasible (
+	EGLPNUM_TYPENAME_lpinfo * lp),
+  EGLPNUM_TYPENAME_fct_test_pI_x (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * p),
+  EGLPNUM_TYPENAME_fct_test_pII_x (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * p),
+  EGLPNUM_TYPENAME_fct_test_pI_pi_dz (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * p),
+  EGLPNUM_TYPENAME_fct_test_pII_pi_dz (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * p);
+
+EGLPNUM_TYPENAME_bndinfo *EGLPNUM_TYPENAME_ILLfct_new_bndinfo (
+	void);
+void EGLPNUM_TYPENAME_ILLfct_free_bndinfo (
+	EGLPNUM_TYPENAME_bndinfo * binfo);
+
+#endif /* EGLPNUM_TYPENAME___FUNCTIONS_H */
diff --git a/qsopt_ex/format.c b/qsopt_ex/format.c
new file mode 100644
index 0000000..76f7615
--- /dev/null
+++ b/qsopt_ex/format.c
@@ -0,0 +1,231 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: format_error.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "qs_config.h"
+
+#include "eg_io.h"
+#include "except.h"
+
+#include "format_EGLPNUM_TYPENAME.h"
+#include "qsopt_EGLPNUM_TYPENAME.h"
+
+
+int EGLPNUM_TYPENAME_ILLformat_error_create (
+	EGLPNUM_TYPENAME_qsformat_error * error,
+	int mode,
+	const char *desc,
+	int lineNum,
+	const char *theLine,
+	int atPos)
+{
+	int len;
+	int rval = 0;
+
+	error->theLine = NULL;
+	error->desc = NULL;
+	error->next = NULL;
+
+	ILL_FAILtrue (desc == NULL, "non empty error desc please");
+	ILL_FAILtrue (mode >= QS_INPUT_NERROR
+								|| mode < 0, "0<= mode <=QS_INPUT_NERROR");
+	error->type = mode;
+	len = strlen (desc);
+	ILL_SAFE_MALLOC (error->desc, len + 1, char);
+
+	strcpy (error->desc, desc);
+	error->lineNumber = lineNum;
+	if (theLine != NULL)
+	{
+		len = strlen (theLine);
+		ILL_SAFE_MALLOC (error->theLine, len + 2, char);
+
+		strcpy (error->theLine, theLine);
+		if (error->theLine[len - 1] != '\n')
+		{
+			error->theLine[len] = '\n';
+			error->theLine[len + 1] = '\0';
+		}
+	}
+	error->at = atPos;
+CLEANUP:
+	if (rval)
+	{
+		EGLPNUM_TYPENAME_ILLformat_error_delete (error);
+	}
+	return rval;
+}
+
+void EGLPNUM_TYPENAME_ILLformat_error_delete (
+	EGLPNUM_TYPENAME_qsformat_error * error)
+{
+	ILL_IFFREE (error->desc, char);
+	ILL_IFFREE (error->theLine, char);
+}
+
+void EGLPNUM_TYPENAME_ILLformat_error_print (
+	EGioFile_t * out,
+	EGLPNUM_TYPENAME_qsformat_error * error)
+{
+	int at = error->at;
+	int tp = error->type;
+	const char *type = "Error";
+	const char *line = NULL;
+	int i;
+
+	type = EGLPNUM_TYPENAME_QSformat_error_type_string (tp);
+
+	EGioPrintf (out, "%s  line %d pos %d\n",
+					 type, EGLPNUM_TYPENAME_QSerror_get_line_number (error), at);
+	line = EGLPNUM_TYPENAME_QSerror_get_line (error);
+	if (line != NULL)
+	{
+		EGioPrintf (out, "LINE %s", line);
+		if (at >= 0)
+		{
+			EGioPrintf (out, ".....");
+			for (i = 0; i <= (at - 1); i++)
+			{
+				if (line[i] == '\t')
+				{
+					EGioPrintf(out, "\t");
+				}
+				else
+				{
+					EGioPrintf(out, ".");
+				}
+			}
+			EGioPrintf (out, "^\n");
+		}
+	}
+	else
+	{
+		EGioPrintf (out, "NO LINE\n");
+	}
+	EGioPrintf (out, "MSG: %s\n", EGLPNUM_TYPENAME_QSerror_get_desc (error));
+}
+
+
+EGLPNUM_TYPENAME_qserror_collector *EGLPNUM_TYPENAME_ILLerror_collector_new (
+	EGLPNUM_TYPENAME_qsadd_error_fct fct,
+	void *dest)
+{
+	int rval = 0;
+	EGLPNUM_TYPENAME_qserror_collector *c = NULL;
+
+	ILL_SAFE_MALLOC (c, 1, EGLPNUM_TYPENAME_qserror_collector);
+	c->add_error = fct;
+	c->dest = dest;
+
+CLEANUP:
+	if (rval)
+	{
+		ILL_IFFREE (c, EGLPNUM_TYPENAME_qserror_collector);
+	}
+	return c;
+}
+
+EGLPNUM_TYPENAME_qserror_collector *EGLPNUM_TYPENAME_ILLerror_memory_collector_new (
+	EGLPNUM_TYPENAME_qserror_memory * dest)
+{
+	return EGLPNUM_TYPENAME_ILLerror_collector_new (EGLPNUM_TYPENAME_ILLadd_error_to_memory, dest);
+}
+
+void EGLPNUM_TYPENAME_ILLerror_collector_free (
+	EGLPNUM_TYPENAME_qserror_collector * c)
+{
+	ILL_IFFREE (c, EGLPNUM_TYPENAME_qserror_collector);
+}
+
+EGLPNUM_TYPENAME_qserror_memory *EGLPNUM_TYPENAME_ILLerror_memory_create (
+	int takeErrorLines)
+{
+	int rval = 0, i;
+	EGLPNUM_TYPENAME_qserror_memory *mem = NULL;
+
+	ILL_SAFE_MALLOC (mem, 1, EGLPNUM_TYPENAME_qserror_memory);
+	for (i = 0; i < QS_INPUT_NERROR; i++)
+	{
+		mem->has_error[i] = 0;
+	}
+	mem->error_list = NULL;
+	mem->nerror = 0;
+	mem->hasErrorLines = takeErrorLines;
+CLEANUP:
+	return mem;
+}
+
+void EGLPNUM_TYPENAME_ILLerror_memory_free (
+	EGLPNUM_TYPENAME_qserror_memory * mem)
+{
+	EGLPNUM_TYPENAME_qsformat_error *ths, *nxt;
+
+	if (mem != NULL)
+	{
+		ths = mem->error_list;
+		while (ths != NULL)
+		{
+			nxt = ths->next;
+			ILL_IFFREE (ths, EGLPNUM_TYPENAME_qsformat_error);
+			ths = nxt;
+		}
+		ILL_IFFREE (mem, EGLPNUM_TYPENAME_qserror_memory);
+	}
+}
+
+int EGLPNUM_TYPENAME_ILLadd_error_to_memory (
+	void *dest,
+	const EGLPNUM_TYPENAME_qsformat_error * error)
+{
+	int rval = 0;
+	EGLPNUM_TYPENAME_qserror_memory *mem = (EGLPNUM_TYPENAME_qserror_memory *) dest;
+	EGLPNUM_TYPENAME_qsformat_error *e = 0;
+
+	ILL_CHECKnull (mem, "must give non NULL EGLPNUM_TYPENAME_qserror_memory");
+
+	ILL_SAFE_MALLOC (e, 1, EGLPNUM_TYPENAME_qsformat_error);
+	rval = EGLPNUM_TYPENAME_ILLformat_error_create (e, error->type, error->desc,
+																 error->lineNumber,
+																 (mem->hasErrorLines) ? error->theLine : NULL,
+																 error->at);
+	ILL_CLEANUP_IF (rval);
+	e->next = mem->error_list;
+	mem->error_list = e;
+	mem->nerror++;
+	mem->has_error[error->type]++;
+
+CLEANUP:
+	if (rval)
+	{
+		EGLPNUM_TYPENAME_ILLformat_error_delete (e);
+		ILL_IFFREE (e, EGLPNUM_TYPENAME_qsformat_error);
+	}
+	return rval;
+}
diff --git a/qsopt_ex/format.h b/qsopt_ex/format.h
new file mode 100644
index 0000000..44ef43d
--- /dev/null
+++ b/qsopt_ex/format.h
@@ -0,0 +1,137 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCSINFO $Id: format_EGLPNUM_TYPENAME.h,v 1.3 2003/11/05 16:59:48 meven Exp $ */
+#ifndef EGLPNUM_TYPENAME_QS_FORMAT_ERROR_H
+#define EGLPNUM_TYPENAME_QS_FORMAT_ERROR_H
+
+#include <stdio.h>
+
+#include "qsopt_EGLPNUM_TYPENAME.h"
+#include "eg_io.h"
+
+/****************************************************************************/
+/*
+   The LP/MPS readers, writers, 
+       EGLPNUM_TYPENAME_ILLrawlpdata_to_lpdata, and 
+   use EGLPNUM_TYPENAME_ILLformat_error to report problems with their input iff
+       the line reader used in reading the problem  or 
+       the  EGLPNUM_TYPENAME_qserror_collector pointer passed to EGLPNUM_TYPENAME_ILLwrite_lp_file
+   is not NULL.
+
+   The QSgui code uses this feature to collect EGLPNUM_TYPENAME_qsformat_error instances 
+   which it uses after reading is done to insert error messages into the 
+   input window. 
+*/
+/****************************************************************************/
+
+/* 
+for error type USE: 
+          QS_DATA_ERROR			
+          QS_DATA_WARN			
+          QS_MPS_FORMAT_ERROR		
+          QS_MPS_FORMAT_WARN		
+          QS_LP_FORMAT_ERROR		
+          QS_LP_FORMAT_WARN		
+          QS_LP_OBJ_WARN			
+          QS_GENERIC_ERROR		
+*/
+
+typedef struct EGLPNUM_TYPENAME_qsformat_error
+{
+	char *desc;
+	char *theLine;
+	struct EGLPNUM_TYPENAME_qsformat_error *next;
+	int type;
+	int lineNumber;								/* 1 based line counting */
+	int at;
+}
+EGLPNUM_TYPENAME_qsformat_error;
+
+extern int EGLPNUM_TYPENAME_ILLformat_error_create (
+	EGLPNUM_TYPENAME_qsformat_error * error,
+	int mode,
+	const char *desc,
+	int lineNum,
+	const char *theLine,
+	int atPos);
+extern void EGLPNUM_TYPENAME_ILLformat_error_delete (
+	EGLPNUM_TYPENAME_qsformat_error * error);
+
+extern void EGLPNUM_TYPENAME_ILLformat_error_print (
+	EGioFile_t * out,
+	EGLPNUM_TYPENAME_qsformat_error * e);
+
+
+
+/*****************************************************************************
+ * collecting error messages 
+ * either with defining own qsad_error_fct and corresponding data structure 
+ * or by using predefined EGLPNUM_TYPENAME_ILLadd_error_to_memory fct with EGLPNUM_TYPENAME_qserror_memory
+ */
+
+typedef int (
+	*EGLPNUM_TYPENAME_qsadd_error_fct) (
+	void *dest,
+	const EGLPNUM_TYPENAME_qsformat_error * error);
+
+typedef struct EGLPNUM_TYPENAME_qserror_collector
+{
+	EGLPNUM_TYPENAME_qsadd_error_fct add_error;
+	void *dest;
+}
+EGLPNUM_TYPENAME_qserror_collector;
+
+typedef struct EGLPNUM_TYPENAME_qserror_memory
+{
+	unsigned int nerror;
+	EGLPNUM_TYPENAME_qsformat_error *error_list;
+	char has_error[QS_INPUT_NERROR];
+	char hasErrorLines;
+}
+EGLPNUM_TYPENAME_qserror_memory;
+
+
+extern EGLPNUM_TYPENAME_qserror_collector *EGLPNUM_TYPENAME_ILLerror_collector_new (
+	EGLPNUM_TYPENAME_qsadd_error_fct fct,
+	void *dest);
+
+EGLPNUM_TYPENAME_qserror_collector *EGLPNUM_TYPENAME_ILLerror_memory_collector_new (
+	EGLPNUM_TYPENAME_qserror_memory * dest);
+
+extern void EGLPNUM_TYPENAME_ILLerror_collector_free (
+	EGLPNUM_TYPENAME_qserror_collector * c);
+
+#define EGLPNUM_TYPENAME_ILLformat_error(collector, error)  \
+	((collector)->add_error((collector)->dest, error))
+
+
+extern int EGLPNUM_TYPENAME_ILLadd_error_to_memory (
+	void *dest,
+	const EGLPNUM_TYPENAME_qsformat_error * error);
+
+extern EGLPNUM_TYPENAME_qserror_memory *EGLPNUM_TYPENAME_ILLerror_memory_create (
+	int takeErrorLines);
+extern void EGLPNUM_TYPENAME_ILLerror_memory_free (
+	EGLPNUM_TYPENAME_qserror_memory * mem);
+
+#endif
diff --git a/qsopt_ex/lib.c b/qsopt_ex/lib.c
new file mode 100644
index 0000000..fdd7fa7
--- /dev/null
+++ b/qsopt_ex/lib.c
@@ -0,0 +1,4348 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: lib.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+//static int TRACE = 0;
+
+/****************************************************************************/
+/*                                                                          */
+/*               Interface Routines to Core LP Solver                       */
+/*                                                                          */
+/*  EXPORTED FUNCTIONS                                                      */
+/*                                                                          */
+/*    int EGLPNUM_TYPENAME_ILLlib_optimize (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_basis *B, EGLPNUM_TYPENAME_price_info *pinf,    */
+/*            int algo, int *status, int simplex_display)                   */
+/*    int EGLPNUM_TYPENAME_ILLlib_cache_solution (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_cache *C)                */
+/*    int EGLPNUM_TYPENAME_ILLlib_solution (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_cache *C, double *val,         */
+/*            double *x, double *pi, double *slack, double *rc)             */
+/*    int EGLPNUM_TYPENAME_ILLlib_get_x (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_cache *C, double *x)              */
+/*    int EGLPNUM_TYPENAME_ILLlib_get_slack (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_cache *C, double *slack)      */
+/*    int EGLPNUM_TYPENAME_ILLlib_objval (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_cache *C, double *val)           */
+/*    int EGLPNUM_TYPENAME_ILLlib_newrow (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_basis *B, double rhs,            */
+/*            char sense, double range, const char *name)                   */
+/*        -range can specify a rangeval for the row (if sense is not 'R',   */
+/*         then range is ignored); it should be 0 if no range is needed;    */
+/*         if sense is 'R' but no rangeval array exists for the LP, the     */
+/*         array will be allocated and initialized.                         */
+/*    int EGLPNUM_TYPENAME_ILLlib_newrows (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_basis *B, int num, double *rhs, */
+/*            char *sense, double *range, const char **names)               */
+/*        -range is an array specifying the rangevals for the rows; range   */
+/*         should be NULL if no rangevals are needed.                       */
+/*    int EGLPNUM_TYPENAME_ILLlib_addrow (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_basis *B, int cnt, int *ind,     */
+/*            double *val, double rhs, char sense, double range,            */
+/*            const char *name)                                             */
+/*    int EGLPNUM_TYPENAME_ILLlib_addrows (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_basis *B, int num,              */
+/*            int *rmatcnt, int *rmatbeg, int *rmatind, double *rmatval,    */
+/*            double *rhs, char *sense, double *range, const char **names,  */
+/*            int *factorok)                                                */
+/*    int EGLPNUM_TYPENAME_ILLlib_delrows (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_basis *B,                       */
+/*            int num, int *dellist, int *basis_ok)                         */
+/*    int EGLPNUM_TYPENAME_ILLlib_newcol (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_basis *B,                        */
+/*            double obj, double lower, double upper, const char *name,     */
+/*            int factorok)                                                 */
+/*    int EGLPNUM_TYPENAME_ILLlib_newcols (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_basis *B,                       */
+/*            int num, double *obj, double *lower, double *upper,           */
+/*            const char **names, int factorok)                             */
+/*    int EGLPNUM_TYPENAME_ILLlib_addcol (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_basis *B,                        */
+/*            int cnt, int *ind, double *val, double obj, double lower,     */
+/*            double upper, const char *name, int factorok)                 */
+/*    int EGLPNUM_TYPENAME_ILLlib_addcols (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_basis *B,                       */
+/*            int num, int *cmatcnt, int *cmatbeg, int *cmatind,            */
+/*            double *cmatval, double *obj, double *lower, double *upper,   */
+/*            const char **names, int factorok)                             */
+/*    int EGLPNUM_TYPENAME_ILLlib_delcols (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_basis *B, int num, int *dellist */
+/*            int *basis_ok)                                                */
+/*    int EGLPNUM_TYPENAME_ILLlib_chgcoef (EGLPNUM_TYPENAME_lpinfo *lp, int rowindex, int colindex,           */
+/*            double coef)                                                  */
+/*    int EGLPNUM_TYPENAME_ILLlib_chgsense (EGLPNUM_TYPENAME_lpinfo *lp, int num, int *rowlist, char *sense)  */
+/*    int EGLPNUM_TYPENAME_ILLlib_getrows (EGLPNUM_TYPENAME_lpinfo *lp, int num, int *rowlist, int **rowcnt,  */
+/*            int **rowbeg, int **rowind, double **rowval, double **rhs,    */
+/*            char **sense, char ***names)                                  */
+/*    int EGLPNUM_TYPENAME_ILLlib_getcols (EGLPNUM_TYPENAME_lpinfo *lp, int num, int *collist, int **colcnt,  */
+/*            int **colbeg, int **colind, double **colval, double **obj,    */
+/*            double **lower, double **upper, char ***names)                */
+/*    int EGLPNUM_TYPENAME_ILLlib_getobj (EGLPNUM_TYPENAME_lpinfo *lp, double *obj)                           */
+/*    int EGLPNUM_TYPENAME_ILLlib_chgobj (EGLPNUM_TYPENAME_lpinfo *lp, int indx, double coef)                 */
+/*    int EGLPNUM_TYPENAME_ILLlib_getrhs (EGLPNUM_TYPENAME_lpinfo *lp, double *rhs)                           */
+/*    int EGLPNUM_TYPENAME_ILLlib_chgrhs (EGLPNUM_TYPENAME_lpinfo *lp, int indx, double coef)                 */
+/*    int EGLPNUM_TYPENAME_ILLlib_getintflags (EGLPNUM_TYPENAME_lpinfo *lp, int *intflags)                    */
+/*    int EGLPNUM_TYPENAME_ILLlib_rownames (EGLPNUM_TYPENAME_lpinfo *lp, char **rownames)                     */
+/*    int EGLPNUM_TYPENAME_ILLlib_colnames (EGLPNUM_TYPENAME_lpinfo *lp, char **colnames)                     */
+/*    int EGLPNUM_TYPENAME_ILLlib_colindex (EGLPNUM_TYPENAME_lpinfo *lp, char *name, int *colindex)           */
+/*    int EGLPNUM_TYPENAME_ILLlib_rowindex (EGLPNUM_TYPENAME_lpinfo *lp, char *name, int *rowindex)           */
+/*    int EGLPNUM_TYPENAME_ILLlib_chgbnd  (EGLPNUM_TYPENAME_lpinfo *lp, int indx, char lu, double bnd)        */
+/*    int EGLPNUM_TYPENAME_ILLlib_chgbnds (EGLPNUM_TYPENAME_lpinfo *lp, int cnt, int *indx, char *lu,         */
+/*            double *bnd)                                                  */
+/*    int EGLPNUM_TYPENAME_ILLlib_getbnd (EGLPNUM_TYPENAME_lpinfo *lp, int indx, char lu, double *bnd)        */
+/*    int EGLPNUM_TYPENAME_ILLlib_getbnds (EGLPNUM_TYPENAME_lpinfo *lp, double *lower, double *upper)         */
+/*    int EGLPNUM_TYPENAME_ILLlib_strongbranch (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_price_info *pinf,                */
+/*      int *candidatelist, int ncand, double *xlist, double *downpen,      */
+/*      double *uppen, int iterations, double objbound)                     */
+/*    int EGLPNUM_TYPENAME_ILLlib_getbasis (EGLPNUM_TYPENAME_lpinfo *lp, char *cstat, char *rstat)            */
+/*    int EGLPNUM_TYPENAME_ILLlib_loadbasis (EGLPNUM_TYPENAME_ILLlp_basis *B, int nstruct, int nrows,         */
+/*      char *cstat, char *rstat)                                           */
+/*    int EGLPNUM_TYPENAME_ILLlib_readbasis (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_basis *B, char *fname)        */
+/*    int EGLPNUM_TYPENAME_ILLlib_writebasis (EGLPNUM_TYPENAME_lpinfo *lp, const char *fname)                 */
+/*    int EGLPNUM_TYPENAME_ILLlib_getrownorms (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_price_info *pinf,                 */
+/*            double *rownorms)                                             */
+/*    int EGLPNUM_TYPENAME_ILLlib_loadrownorms (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_price_info *pinf,                */
+/*            double *rownorms)                                             */
+/*    int EGLPNUM_TYPENAME_ILLlib_recompute_rownorms (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_price_info *pinf)          */
+/*    int EGLPNUM_TYPENAME_ILLlib_print_x (EGioFile_t *fd, EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_cache *C, double *x,  */
+/*            int nonZerosOnly)                                             */
+/*    int EGLPNUM_TYPENAME_ILLlib_print_x (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_cache *C)                       */
+/*    int EGLPNUM_TYPENAME_ILLlib_iter (EGLPNUM_TYPENAME_lpinfo *lp)                                          */
+/*                                                                          */
+/*  NOTES                                                                   */
+/*                                                                          */
+/*                                                                          */
+/****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "eg_lpnum.h"
+#include "eg_io.h"
+#include "except.h"
+#include "util.h"
+
+#include "lpdata_EGLPNUM_TYPENAME.h"
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+#include "simplex_EGLPNUM_TYPENAME.h"
+#include "price_EGLPNUM_TYPENAME.h"
+#include "basis_EGLPNUM_TYPENAME.h"
+#include "lib_EGLPNUM_TYPENAME.h"
+#include "qstruct_EGLPNUM_TYPENAME.h"
+#include "qsopt_EGLPNUM_TYPENAME.h"
+#include "lp_EGLPNUM_TYPENAME.h"
+#include "mps_EGLPNUM_TYPENAME.h"
+
+
+static void check_pinf (
+	EGLPNUM_TYPENAME_price_info * pinf,
+	int *it_exists);
+
+static int matrix_addrow (
+	EGLPNUM_TYPENAME_ILLmatrix * A,
+	int rowcnt,
+	int *rowind,
+	const EGLPNUM_TYPE * rowval),
+  matrix_addrow_end (
+	EGLPNUM_TYPENAME_ILLmatrix * A,
+	int row,
+	int rowcnt,
+	int *rowind,
+	const EGLPNUM_TYPE * rowval),
+  matrix_addcoef (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_ILLmatrix * A,
+	int row,
+	int col,
+	EGLPNUM_TYPE val),
+  matrix_addcol (
+	EGLPNUM_TYPENAME_ILLmatrix * A,
+	int colcnt,
+	int *colind,
+	EGLPNUM_TYPE * colval),
+  delcols_work (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	char *colmark),
+  reset_colindex (
+	EGLPNUM_TYPENAME_lpinfo * lp),
+  reset_rowindex (
+	EGLPNUM_TYPENAME_lpinfo * lp);
+
+int EGLPNUM_TYPENAME_ILLlib_optimize (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_ILLlp_basis * B,
+	EGLPNUM_TYPENAME_price_info * pinf,
+	int algo,
+	int *status,
+	int simplex_display,
+	itcnt_t*itcnt)
+{
+	int rval = 0;
+	int sol_status;
+
+	if (status)
+		*status = QS_LP_UNSOLVED;
+
+	/* EGLPNUM_TYPENAME_ILLprice_free_pricing_info (pinf); *//* Should be removed later */
+
+	rval = EGLPNUM_TYPENAME_ILLsimplex (lp, algo, B, pinf, &sol_status, simplex_display, itcnt);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (status)
+		*status = sol_status;
+
+CLEANUP:
+
+	if (rval == E_SIMPLEX_ERROR)
+	{
+		EGioFile_t *eout = 0;
+		int tval;
+
+		QSlog("write bad lp to error.lp");
+#ifdef HAVE_LIBZ
+		eout = EGioOpen ("error.lp.gz", "w");
+#else
+#ifdef HAVE_LIBBZ2
+		eout = EGioOpen ("error.lp.bz2", "w");
+#else
+		eout = EGioOpen ("error.lp", "w");
+#endif
+#endif
+		if (!eout)
+		{
+			QSlog("could not open file to write bad lp");
+		}
+		else
+		{
+			tval = EGLPNUM_TYPENAME_ILLwrite_lp (lp->O, NULL);
+			if (tval)
+			{
+				QSlog("error while writing bad lp");
+			}
+			EGioClose (eout);
+		}
+
+		QSlog("write bad basis to error.bas");
+		tval = EGLPNUM_TYPENAME_ILLlib_writebasis (lp, 0, "error.bas");
+		if (tval)
+		{
+			QSlog("error while writing bad basis");
+		}
+	}
+	if (rval == QS_LP_CHANGE_PREC)
+	{
+		MESSAGE (__QS_SB_VERB, "Changing precision");
+		return rval;
+	}
+	MESSAGE (rval ? 0 : 1000, "Error code %d", rval);
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_cache_solution (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_ILLlp_cache * C)
+{
+	int rval = 0;
+
+	if (C)
+	{
+		if (C->nstruct != lp->O->nstruct || C->nrows != lp->O->nrows)
+		{
+			QSlog("lp_cache does not match size of lp");
+			rval = 1;
+			ILL_CLEANUP;
+		}
+		rval = EGLPNUM_TYPENAME_ILLlib_solution (lp, 0, &(C->val), C->x, C->pi, C->slack, C->rc);
+		CHECKRVALG (rval, CLEANUP);
+	}
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_solution (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_ILLlp_cache * C,
+	EGLPNUM_TYPE * val,
+	EGLPNUM_TYPE * x,
+	EGLPNUM_TYPE * pi,
+	EGLPNUM_TYPE * slack,
+	EGLPNUM_TYPE * rc)
+{
+	int i, rval = 0;
+	EGLPNUM_TYPE *tempx = 0;
+	EGLPNUM_TYPE *temprc = 0;
+	int ncols = lp->O->ncols;
+	int nrows = lp->O->nrows;
+	int nstruct = lp->O->nstruct;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp = lp->O;
+
+	if (C)
+	{
+		if (C->nrows != nrows || C->nstruct != nstruct)
+		{
+			QSlog("cache mismatch in EGLPNUM_TYPENAME_ILLlib_solution");
+			rval = 0;
+			ILL_CLEANUP;
+		}
+		if (val)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (*val, C->val);
+		}
+		if (x)
+		{
+			for (i = 0; i < nstruct; i++)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (x[i], C->x[i]);
+			}
+		}
+		if (pi)
+		{
+			for (i = 0; i < nrows; i++)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (pi[i], C->pi[i]);
+			}
+		}
+		if (slack)
+		{
+			for (i = 0; i < nrows; i++)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (slack[i], C->slack[i]);
+			}
+		}
+		if (rc)
+		{
+			for (i = 0; i < nstruct; i++)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (rc[i], C->rc[i]);
+			}
+		}
+	}
+	else
+	{
+		if (x || slack)
+			tempx = EGLPNUM_TYPENAME_EGlpNumAllocArray (ncols);
+
+		if (rc)
+			temprc = EGLPNUM_TYPENAME_EGlpNumAllocArray (ncols);
+
+		rval = EGLPNUM_TYPENAME_ILLsimplex_solution (lp, tempx, pi, temprc, val);
+		CHECKRVALG (rval, CLEANUP);
+
+		if (x)
+		{
+			for (i = 0; i < nstruct; i++)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (x[i], tempx[qslp->structmap[i]]);
+			}
+		}
+		if (slack)
+		{
+			for (i = 0; i < nrows; i++)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (slack[i], tempx[qslp->rowmap[i]]);
+			}
+		}
+
+		if (rc)
+		{
+			for (i = 0; i < nstruct; i++)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (rc[i], temprc[qslp->structmap[i]]);
+			}
+		}
+
+
+		if (lp->O->objsense == EGLPNUM_TYPENAME_ILL_MAX)
+		{														/* Reverse signs for max prob */
+			if (val)
+			{
+				EGLPNUM_TYPENAME_EGlpNumSign (*val);
+			}
+			if (pi)
+			{
+				for (i = 0; i < nrows; i++)
+				{
+					EGLPNUM_TYPENAME_EGlpNumSign (pi[i]);
+				}
+			}
+			if (rc)
+			{
+				for (i = 0; i < nstruct; i++)
+				{
+					EGLPNUM_TYPENAME_EGlpNumSign (rc[i]);
+				}
+			}
+		}
+	}
+
+CLEANUP:
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (tempx);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (temprc);
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_get_x (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_ILLlp_cache * C,
+	EGLPNUM_TYPE * x)
+{
+	int rval = 0;
+
+	rval = EGLPNUM_TYPENAME_ILLlib_solution (lp, C, 0, x, 0, 0, 0);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_get_slack (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_ILLlp_cache * C,
+	EGLPNUM_TYPE * slack)
+{
+	int rval = 0;
+
+	rval = EGLPNUM_TYPENAME_ILLlib_solution (lp, C, 0, 0, 0, slack, 0);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+
+int EGLPNUM_TYPENAME_ILLlib_objval (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_ILLlp_cache * C,
+	EGLPNUM_TYPE * val)
+{
+	int rval = 0;
+
+	if (lp->basisstat.optimal)
+	{
+		rval = EGLPNUM_TYPENAME_ILLlib_solution (lp, C, val, 0, 0, 0, 0);
+		CHECKRVALG (rval, CLEANUP);
+	}
+	else
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (*val, lp->dobjval);	/* Ask Sanjeeb */
+	}
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_tableau (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int row,
+	EGLPNUM_TYPE * binv,
+	EGLPNUM_TYPE * tabrow)
+{
+	int rval = 0;
+	int i;
+	int ncols = lp->O->ncols;
+	int nrows = lp->O->nrows;
+	int nstruct = lp->O->nstruct;
+	EGLPNUM_TYPE *brow = 0;
+	EGLPNUM_TYPE *trow = 0;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp = lp->O;
+
+	if (row < 0 || row >= qslp->nrows)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_tableau called with bad row: %d", row);
+		rval = 1;
+		ILL_CLEANUP;
+	}
+	brow = EGLPNUM_TYPENAME_EGlpNumAllocArray (nrows);
+
+	if (tabrow)
+		trow = EGLPNUM_TYPENAME_EGlpNumAllocArray (ncols);
+
+	rval = EGLPNUM_TYPENAME_ILLbasis_tableau_row (lp, row, brow, trow, 0, 0);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (binv)
+	{
+		for (i = 0; i < nrows; i++)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (binv[i], brow[i]);
+		}
+	}
+
+	if (tabrow)
+	{
+		for (i = 0; i < nstruct; i++)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (tabrow[i], trow[qslp->structmap[i]]);
+		}
+		for (i = 0; i < nrows; i++)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (tabrow[nstruct + i], trow[qslp->rowmap[i]]);
+		}
+	}
+
+CLEANUP:
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (brow);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (trow);
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_basis_order (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int *header)
+{
+	int rval = 0;
+	int i, j;
+	int ncols = lp->O->ncols;
+	int nrows = lp->O->nrows;
+	int nstruct = lp->O->nstruct;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp = lp->O;
+	int *invmap = 0;
+
+	ILL_SAFE_MALLOC (invmap, ncols, int);
+
+	for (j = 0; j < nstruct; j++)
+	{
+		invmap[qslp->structmap[j]] = j;
+	}
+	for (i = 0; i < nrows; i++)
+	{
+		invmap[qslp->rowmap[i]] = nstruct + i;
+	}
+
+	for (i = 0; i < nrows; i++)
+	{
+		header[i] = invmap[lp->baz[i]];
+	}
+
+CLEANUP:
+
+	ILL_IFFREE (invmap, int);
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_chgbnd (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int indx,
+	int lu,
+	const EGLPNUM_TYPE bnd)
+{
+	int rval = 0;
+	int col;
+
+	if (!lp)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_chgbnd called without an lp");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	if (indx < 0 || indx > lp->O->nstruct)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_chgbnd called with bad indx: %d", indx);
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	if (lp->O->sinfo)
+	{															/* Presolve LP is no longer valid, free the data */
+		EGLPNUM_TYPENAME_ILLlp_sinfo_free (lp->O->sinfo);
+		ILL_IFFREE (lp->O->sinfo, EGLPNUM_TYPENAME_ILLlp_sinfo);
+	}
+
+	col = lp->O->structmap[indx];
+
+	switch (lu)
+	{
+	case 'L':
+		EGLPNUM_TYPENAME_EGlpNumCopy (lp->O->lower[col], bnd);
+		break;
+	case 'U':
+		EGLPNUM_TYPENAME_EGlpNumCopy (lp->O->upper[col], bnd);
+		break;
+	case 'B':
+		EGLPNUM_TYPENAME_EGlpNumCopy (lp->O->lower[col], bnd);
+		EGLPNUM_TYPENAME_EGlpNumCopy (lp->O->upper[col], bnd);
+		break;
+	default:
+		QSlog("EGLPNUM_TYPENAME_ILLlib_chgbnd called with lu: %c", lu);
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_chgbnds (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int cnt,
+	int *indx,
+	char *lu,
+	const EGLPNUM_TYPE * bnd)
+{
+	int rval = 0;
+	int i;
+
+	for (i = 0; i < cnt; i++)
+	{
+		rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, indx[i], lu[i], bnd[i]);
+		if (rval)
+			ILL_CLEANUP;
+	}
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_getbnd (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int indx,
+	int lu,
+	EGLPNUM_TYPE * bnd)
+{
+	int rval = 0;
+	int col;
+
+	if (!lp)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_getbnd called without an lp");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	if (indx < 0 || indx > lp->O->nstruct)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_getbnd called with bad indx: %d", indx);
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	col = lp->O->structmap[indx];
+
+	switch (lu)
+	{
+	case 'L':
+		EGLPNUM_TYPENAME_EGlpNumCopy (*bnd, lp->O->lower[col]);
+		break;
+	case 'U':
+		EGLPNUM_TYPENAME_EGlpNumCopy (*bnd, lp->O->upper[col]);
+		break;
+	default:
+		QSlog("EGLPNUM_TYPENAME_ILLlib_getbnd called with lu: %c", lu);
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_getbnds_list ( 
+	EGLPNUM_TYPENAME_lpinfo *lp,
+	int num,
+	int*collist, 
+	EGLPNUM_TYPE *lower,
+	EGLPNUM_TYPE *upper)
+{
+    int rval = 0;
+    EGLPNUM_TYPENAME_ILLlpdata *qslp;
+    int nstruct;
+    int j, col;
+
+    if (!lp) {
+        QSlog("EGLPNUM_TYPENAME_ILLlib_getbnds_list called without an lp");
+        rval = 1; ILL_CLEANUP;
+    }
+
+    qslp = lp->O;
+    nstruct = qslp->nstruct;
+		for (j = 0; j < num ; j++) {
+		if(collist[j]<0|| collist[j] >= nstruct)
+			{
+				QSlog("EGLPNUM_TYPENAME_ILLlib_getbnds_list collist[%d] = %d out "
+										"of range", j, collist[j]);
+			}
+			col = qslp->structmap[collist[j]];
+			if (lower)
+				EGLPNUM_TYPENAME_EGlpNumCopy(lower[j], qslp->lower[col]);
+			if (upper)
+				EGLPNUM_TYPENAME_EGlpNumCopy(upper[j], qslp->upper[col]);
+		}
+
+CLEANUP:
+
+	EG_RETURN(rval);		
+}
+
+
+int EGLPNUM_TYPENAME_ILLlib_getbnds (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPE * lower,
+	EGLPNUM_TYPE * upper)
+{
+	int rval = 0;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp;
+	int nstruct;
+	int j, col;
+
+	if (!lp)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_getbnd called without an lp");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	qslp = lp->O;
+	nstruct = qslp->nstruct;
+
+	for (j = 0; j < nstruct; j++)
+	{
+		col = qslp->structmap[j];
+		if (lower)
+			EGLPNUM_TYPENAME_EGlpNumCopy (lower[j], qslp->lower[col]);
+		if (upper)
+			EGLPNUM_TYPENAME_EGlpNumCopy (upper[j], qslp->upper[col]);
+	}
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_strongbranch (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * pinf,
+	int *candidatelist,
+	int ncand,
+	EGLPNUM_TYPE * xlist,
+	EGLPNUM_TYPE * downpen,
+	EGLPNUM_TYPE * uppen,
+	int iterations,
+	EGLPNUM_TYPE objbound,
+	itcnt_t*itcnt)
+{
+	int rval = 0;
+	int i, k, status, have_norms;
+	int olditer = lp->maxiter;
+	int nstruct = lp->O->nstruct;
+	int nrows = lp->O->nrows;
+	EGLPNUM_TYPE *myx = 0;
+	EGLPNUM_TYPE xi, t, oldbnd;
+	EGLPNUM_TYPENAME_price_info lpinf;
+	EGLPNUM_TYPENAME_ILLlp_basis B, origB;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (lpinf.htrigger);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (xi);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (t);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (oldbnd);
+	EGLPNUM_TYPENAME_EGlpNumZero (oldbnd);
+	EGLPNUM_TYPENAME_ILLlp_basis_init (&B);
+	EGLPNUM_TYPENAME_ILLlp_basis_init (&origB);
+	EGLPNUM_TYPENAME_ILLprice_init_pricing_info (&lpinf);
+	lpinf.dI_price = QS_PRICE_DSTEEP;
+	lpinf.dII_price = QS_PRICE_DSTEEP;
+
+	if (xlist == 0)
+	{
+		myx = EGLPNUM_TYPENAME_EGlpNumAllocArray (nstruct);
+		rval = EGLPNUM_TYPENAME_ILLlib_get_x (lp, 0, myx);
+		CHECKRVALG (rval, CLEANUP);
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLlp_basis_alloc (&origB, nstruct, nrows);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_getbasis (lp, origB.cstat, origB.rstat);
+	CHECKRVALG (rval, CLEANUP);
+
+	check_pinf (pinf, &have_norms);
+	if (have_norms == 0)
+	{
+		origB.rownorms = EGLPNUM_TYPENAME_EGlpNumAllocArray (nrows);
+		rval = EGLPNUM_TYPENAME_ILLlib_getrownorms (lp, pinf, origB.rownorms);
+		CHECKRVALG (rval, CLEANUP);
+	}
+	else
+	{
+		lp->basisid = -1;
+		rval = EGLPNUM_TYPENAME_ILLlib_optimize (lp, 0, &lpinf, DUAL_SIMPLEX, &status, 0, itcnt);
+		CHECKRVALG (rval, CLEANUP);
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLlp_basis_alloc (&B, nstruct, nrows);	/* Note: B and orgiB may */
+	/* differ.               */
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_getbasis (lp, B.cstat, B.rstat);
+	CHECKRVALG (rval, CLEANUP);
+	B.rownorms = EGLPNUM_TYPENAME_EGlpNumAllocArray (nrows);
+
+	if (have_norms == 0)
+	{
+		rval = EGLPNUM_TYPENAME_ILLlib_getrownorms (lp, pinf, B.rownorms);
+		CHECKRVALG (rval, CLEANUP);
+	}
+	else
+	{
+		rval = EGLPNUM_TYPENAME_ILLlib_getrownorms (lp, &lpinf, B.rownorms);
+		CHECKRVALG (rval, CLEANUP);
+	}
+
+	lp->maxiter = iterations;
+
+	for (i = 0; i < ncand; i++)
+	{
+		k = candidatelist[i];
+		rval = EGLPNUM_TYPENAME_ILLlib_getbnd (lp, k, 'U', &oldbnd);
+		CHECKRVALG (rval, CLEANUP);
+		if (xlist)
+			EGLPNUM_TYPENAME_EGlpNumCopy (xi, xlist[i]);
+		else
+			EGLPNUM_TYPENAME_EGlpNumCopy (xi, myx[k]);
+		EGLPNUM_TYPENAME_EGlpNumFloor (t, xi);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLessDbl (t, 0.1) && EGLPNUM_TYPENAME_EGlpNumIsGreaDbl (t, -0.1))
+			EGLPNUM_TYPENAME_EGlpNumZero (t);
+
+		rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, k, 'U', t);
+		CHECKRVALG (rval, CLEANUP);
+
+		rval = EGLPNUM_TYPENAME_ILLlib_optimize (lp, &B, &lpinf, DUAL_SIMPLEX, &status, 0, itcnt);
+		CHECKRVALG (rval, CLEANUP);
+
+		EGLPNUM_TYPENAME_EGlpNumCopy (downpen[i], lp->dobjval);
+		rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, k, 'U', oldbnd);
+		CHECKRVALG (rval, CLEANUP);
+
+		rval = EGLPNUM_TYPENAME_ILLlib_getbnd (lp, k, 'L', &oldbnd);
+		CHECKRVALG (rval, CLEANUP);
+		EGLPNUM_TYPENAME_EGlpNumCeil (t, xi);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLessDbl (t, 1.1) && EGLPNUM_TYPENAME_EGlpNumIsGreaDbl (t, 0.9))
+			EGLPNUM_TYPENAME_EGlpNumOne (t);
+		rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, k, 'L', t);
+		CHECKRVALG (rval, CLEANUP);
+
+		rval = EGLPNUM_TYPENAME_ILLlib_optimize (lp, &B, &lpinf, DUAL_SIMPLEX, &status, 0, itcnt);
+		CHECKRVALG (rval, CLEANUP);
+
+		EGLPNUM_TYPENAME_EGlpNumCopy (uppen[i], lp->dobjval);
+		rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, k, 'L', oldbnd);
+		CHECKRVALG (rval, CLEANUP);
+	}
+
+	if (lp->O->objsense == EGLPNUM_TYPENAME_ILL_MAX)
+	{
+
+	}
+	else
+	{
+		for (i = 0; i < ncand; i++)
+		{
+			if (EGLPNUM_TYPENAME_EGlpNumIsLess (objbound, downpen[i]))
+				EGLPNUM_TYPENAME_EGlpNumCopy (downpen[i], objbound);
+			if (EGLPNUM_TYPENAME_EGlpNumIsLess (objbound, uppen[i]))
+				EGLPNUM_TYPENAME_EGlpNumCopy (uppen[i], objbound);
+		}
+	}
+
+	/* Restore the old optimal solution */
+
+	lp->maxiter = olditer;
+	rval = EGLPNUM_TYPENAME_ILLlib_optimize (lp, &origB, pinf, DUAL_SIMPLEX, &status, 0, itcnt);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EGLPNUM_TYPENAME_EGlpNumClearVar (xi);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (t);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (oldbnd);
+	lp->maxiter = olditer;
+	EGLPNUM_TYPENAME_ILLprice_free_pricing_info (&lpinf);
+	EGLPNUM_TYPENAME_ILLlp_basis_free (&B);
+	EGLPNUM_TYPENAME_ILLlp_basis_free (&origB);
+	if (xlist == 0)
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (myx);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (lpinf.htrigger);
+	EG_RETURN (rval);
+}
+
+#define EXTRA_ROWS (100)
+#define EXTRA_COLS (100)
+#define EXTRA_MAT  (1000)
+
+int EGLPNUM_TYPENAME_ILLlib_newrow (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_ILLlp_basis * B,
+	const EGLPNUM_TYPE rhs,
+	int sense,
+	const EGLPNUM_TYPE range,
+	const char *name)
+{
+	int rval = 0;
+
+	rval = EGLPNUM_TYPENAME_ILLlib_addrow (lp, B, 0, 0, 0, rhs, sense, range, name);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_newrows (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_ILLlp_basis * B,
+	int num,
+	const EGLPNUM_TYPE * rhs,
+	char *sense,
+	const EGLPNUM_TYPE * range,
+	const char **names)
+{
+	int rval = 0;
+	int *rmatcnt = 0;
+	int *rmatbeg = 0;
+	int i;
+
+	if (!num)
+		ILL_CLEANUP;
+
+	ILL_SAFE_MALLOC (rmatcnt, num, int);
+
+	ILL_SAFE_MALLOC (rmatbeg, num, int);
+
+	for (i = 0; i < num; i++)
+	{
+		rmatcnt[i] = 0;
+		rmatbeg[i] = 0;
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLlib_addrows (lp, B, num, rmatcnt, rmatbeg, 0, 0, rhs, sense,
+												 range, names, 0);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	ILL_IFFREE (rmatcnt, int);
+	ILL_IFFREE (rmatbeg, int);
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_addrows (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_ILLlp_basis * B,
+	int num,
+	int *rmatcnt,
+	int *rmatbeg,
+	int *rmatind,
+	const EGLPNUM_TYPE * rmatval,
+	const EGLPNUM_TYPE * rhs,
+	char *sense,
+	const EGLPNUM_TYPE * range,
+	const char **names,
+	int *factorok)
+{
+	int rval = 0;
+	int i, j, total, bsing;
+	int *imap = 0;
+	int *bbeg = 0;
+	int *bcnt = 0;
+	int *bindi = 0;
+	int *rindi = 0;
+	int *jstat = 0;
+	EGLPNUM_TYPE *bval = 0;
+	EGLPNUM_TYPE rng;
+	int badfactor = 0;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (rng);
+
+	if (B == 0 || B->rownorms == 0)
+	{
+		if (factorok)
+			*factorok = 0;
+	}
+
+	if (B)
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (B->colnorms);
+
+	if (B && B->rownorms && factorok && *factorok == 1)
+	{
+		int *structmap = lp->O->structmap;
+
+		lp->matbeg = lp->O->A.matbeg;
+		lp->matcnt = lp->O->A.matcnt;
+		lp->matind = lp->O->A.matind;
+		lp->matval = lp->O->A.matval;
+
+		lp->nrows = lp->O->nrows;
+		lp->ncols = lp->O->ncols;
+		if (B->rownorms_size < lp->O->nrows + num)
+			EGLPNUM_TYPENAME_EGlpNumReallocArray (&(B->rownorms), lp->O->nrows + num);
+
+		ILL_SAFE_MALLOC (bcnt, num, int);
+		ILL_SAFE_MALLOC (bbeg, num, int);
+		ILL_SAFE_MALLOC (imap, lp->O->nstruct, int);
+
+		ILL_SAFE_MALLOC (jstat, lp->ncols, int);
+
+		for (i = 0; i < lp->ncols; i++)
+		{
+			jstat[i] = -1;
+		}
+		for (i = 0; i < lp->O->nstruct; i++)
+		{
+			jstat[structmap[i]] = i;
+		}
+
+		for (i = 0; i < lp->O->nstruct; i++)
+		{
+			imap[i] = -1;
+		}
+		for (i = 0; i < lp->O->nrows; i++)
+		{
+			if (jstat[lp->baz[i]] != -1)
+			{
+				imap[jstat[lp->baz[i]]] = i;
+			}
+		}
+
+		for (i = 0, total = 0; i < num; i++)
+		{
+			bcnt[i] = 0;
+			bbeg[i] = total;
+			for (j = 0; j < rmatcnt[i]; j++)
+			{
+				if (imap[rmatind[rmatbeg[i] + j]] != -1)
+				{
+					bcnt[i]++;
+					total++;
+				}
+			}
+		}
+		if (total)
+		{
+			ILL_SAFE_MALLOC (bindi, total, int);
+
+			bval = EGLPNUM_TYPENAME_EGlpNumAllocArray (total);
+		}
+		for (i = 0, total = 0; i < num; i++)
+		{
+			for (j = 0; j < rmatcnt[i]; j++)
+			{
+				if (imap[rmatind[rmatbeg[i] + j]] != -1)
+				{
+					EGLPNUM_TYPENAME_EGlpNumCopy (bval[total], rmatval[rmatbeg[i] + j]);
+					bindi[total] = imap[rmatind[rmatbeg[i] + j]];
+					total++;
+				}
+			}
+		}
+
+		rval = EGLPNUM_TYPENAME_ILLprice_get_new_rownorms (lp, num, B->rownorms + lp->O->nrows,
+																			bcnt, bbeg, bindi, bval);
+		CHECKRVALG (rval, CLEANUP);
+
+		ILL_IFFREE (bcnt, int);
+		ILL_IFFREE (bbeg, int);
+		ILL_IFFREE (bindi, int);
+
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (bval);
+		ILL_IFFREE (imap, int);
+
+		badfactor = 1;
+	}
+
+	for (i = 0; i < num; i++)
+	{
+		if (range)
+			EGLPNUM_TYPENAME_EGlpNumCopy (rng, range[i]);
+		else
+			EGLPNUM_TYPENAME_EGlpNumZero (rng);
+		if (names)
+		{
+			rval = EGLPNUM_TYPENAME_ILLlib_addrow (lp, B, rmatcnt[i], rmatind + rmatbeg[i],
+														rmatval + rmatbeg[i], rhs[i], sense[i], rng,
+														names[i]);
+		}
+		else
+		{
+			rval = EGLPNUM_TYPENAME_ILLlib_addrow (lp, B, rmatcnt[i], rmatind + rmatbeg[i],
+														rmatval + rmatbeg[i], rhs[i], sense[i], rng, 0);
+		}
+		CHECKRVALG (rval, CLEANUP);
+	}
+
+
+	if (B && B->rownorms && (factorok && *factorok == 0))
+	{
+		lp->matbeg = lp->O->A.matbeg;
+		lp->matcnt = lp->O->A.matcnt;
+		lp->matind = lp->O->A.matind;
+		lp->matval = lp->O->A.matval;
+		lp->nrows = lp->O->nrows;
+		lp->ncols = lp->O->ncols;
+		lp->bz = lp->O->rhs;
+		lp->nnbasic = lp->ncols - lp->nrows;
+
+		rval = EGLPNUM_TYPENAME_ILLbasis_load (lp, B);
+		CHECKRVALG (rval, CLEANUP);
+
+		if (lp->f)
+			EGLPNUM_TYPENAME_ILLfactor_free_factor_work (lp->f);
+
+		rval = EGLPNUM_TYPENAME_ILLbasis_factor (lp, &bsing);
+		CHECKRVALG (rval, CLEANUP);
+		if (bsing)
+			MESSAGE (__QS_SB_VERB, "Singular Basis found!");
+		*factorok = 1;
+
+		if (B->rownorms_size < lp->O->nrows)
+			EGLPNUM_TYPENAME_EGlpNumReallocArray (&(B->rownorms), lp->O->nrows);
+
+		ILL_SAFE_MALLOC (rindi, lp->O->nrows /* num */ , int);
+
+		for (i = 0; i < num; i++)
+		{
+			rindi[i] = lp->O->nrows - num + i;
+		}
+
+		rval = EGLPNUM_TYPENAME_ILLprice_get_dsteep_norms (lp, num, rindi,
+																			B->rownorms + lp->O->nrows - num);
+		CHECKRVALG (rval, CLEANUP);
+	}
+
+	if (factorok != 0 && badfactor == 1)
+	{
+		*factorok = 0;
+	}
+
+
+CLEANUP:
+
+	ILL_IFFREE (bcnt, int);
+	ILL_IFFREE (bbeg, int);
+	ILL_IFFREE (bindi, int);
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (bval);
+	ILL_IFFREE (imap, int);
+	ILL_IFFREE (jstat, int);
+	ILL_IFFREE (rindi, int);
+
+	EGLPNUM_TYPENAME_EGlpNumClearVar (rng);
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_addrow (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_ILLlp_basis * B,
+	int cnt,
+	int *ind,
+	const EGLPNUM_TYPE * val,
+	const EGLPNUM_TYPE rhs,
+	int sense,
+	const EGLPNUM_TYPE range,
+	const char *name)
+{
+	int rval = 0;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp;
+	EGLPNUM_TYPENAME_ILLmatrix *A;
+	int i, nrows, ncols;
+	char buf[ILL_namebufsize];
+	int tind[1];
+	EGLPNUM_TYPE tval[1];
+	int *tempind = 0;
+	int pind, hit;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (tval[0]);
+
+	if (!lp)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_addrow called without an lp");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	qslp = lp->O;
+	A = &qslp->A;
+
+	if (qslp->rA)
+	{															/* After an addrow call, needs to be updated */
+		EGLPNUM_TYPENAME_ILLlp_rows_clear (qslp->rA);
+		ILL_IFFREE (qslp->rA, EGLPNUM_TYPENAME_ILLlp_rows);
+	}
+
+	if (qslp->sinfo)
+	{															/* Presolve LP is no longer valid, free the data */
+		EGLPNUM_TYPENAME_ILLlp_sinfo_free (qslp->sinfo);
+		ILL_IFFREE (qslp->sinfo, EGLPNUM_TYPENAME_ILLlp_sinfo);
+	}
+
+	nrows = qslp->nrows;
+	ncols = qslp->ncols;
+
+	/* If the row has a range, create the rangeval array if needed  */
+
+	if (sense == 'R' && !(qslp->rangeval) && qslp->rowsize > 0)
+	{
+		qslp->rangeval = EGLPNUM_TYPENAME_EGlpNumAllocArray (qslp->rowsize);
+		for (i = 0; i < qslp->nrows; i++)
+		{
+			EGLPNUM_TYPENAME_EGlpNumZero (qslp->rangeval[i]);
+		}
+	}
+
+	/* Add the row to the row structures */
+
+	if (qslp->rowsize < nrows + 1)
+	{
+		EGLPNUM_TYPENAME_EGlpNumReallocArray (&(qslp->rhs), qslp->rowsize + EXTRA_ROWS);
+		qslp->sense = EGrealloc (qslp->sense,
+														 sizeof (char) * (qslp->rowsize + EXTRA_ROWS));
+		//rval = ILLutil_reallocrus_count ((void **) &(qslp->sense),
+		//                                 qslp->rowsize + EXTRA_ROWS, sizeof (char));
+		//CHECKRVALG(rval,CLEANUP);
+
+		qslp->rowmap = EGrealloc (qslp->rowmap,
+															sizeof (int) * (qslp->rowsize + EXTRA_ROWS));
+		//rval = ILLutil_reallocrus_count ((void **) &(qslp->rowmap),
+		//                                 qslp->rowsize + EXTRA_ROWS, sizeof (int));
+		//CHECKRVALG(rval,CLEANUP);
+
+		if (qslp->rangeval || sense == 'R')
+			EGLPNUM_TYPENAME_EGlpNumReallocArray (&(qslp->rangeval), qslp->rowsize + EXTRA_ROWS);
+
+		qslp->rownames = EGrealloc (qslp->rownames,
+																sizeof (char *) * (qslp->rowsize + EXTRA_ROWS));
+		//rval = ILLutil_reallocrus_count ((void **) &(qslp->rownames),
+		//                                 qslp->rowsize + EXTRA_ROWS,
+		//                                 sizeof (char *));
+		//CHECKRVALG(rval,CLEANUP);
+		qslp->rowsize += EXTRA_ROWS;
+	}
+
+	EGLPNUM_TYPENAME_EGlpNumCopy (qslp->rhs[nrows], rhs);
+	qslp->sense[nrows] = sense;
+	qslp->rowmap[nrows] = ncols;	/* this will be the new logical */
+	if (qslp->rangeval)
+	{
+		if (sense == 'R')
+			EGLPNUM_TYPENAME_EGlpNumCopy (qslp->rangeval[nrows], range);
+		else
+			EGLPNUM_TYPENAME_EGlpNumZero (qslp->rangeval[nrows]);
+	}
+	ILL_FAILtrue (qslp->rownames == NULL, "must always be non NULL");
+	EGLPNUM_TYPENAME_ILLlib_findName (qslp, 1 /*row */ , name, nrows, buf);
+	ILL_UTIL_STR (qslp->rownames[nrows], buf);
+	ILLsymboltab_register (&qslp->rowtab, buf, qslp->nrows, &pind, &hit);
+	ILL_FAILfalse (hit == 0, "must be new");
+
+
+	/* Add the logical variable to the column structures */
+
+	if (qslp->colsize < ncols + 1)
+	{
+		EGLPNUM_TYPENAME_EGlpNumReallocArray (&(qslp->lower), qslp->colsize + EXTRA_COLS);
+		EGLPNUM_TYPENAME_EGlpNumReallocArray (&(qslp->upper), qslp->colsize + EXTRA_COLS);
+		EGLPNUM_TYPENAME_EGlpNumReallocArray (&(qslp->obj), qslp->colsize + EXTRA_COLS);
+		qslp->colsize += EXTRA_COLS;
+	}
+
+	EGLPNUM_TYPENAME_EGlpNumZero (qslp->obj[ncols]);
+	EGLPNUM_TYPENAME_EGlpNumZero (qslp->lower[ncols]);
+	if (sense == 'E')
+	{
+		EGLPNUM_TYPENAME_EGlpNumZero (qslp->upper[ncols]);	/* Artificial */
+	}
+	else if (sense == 'R')
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (qslp->upper[ncols], range);	/* Range      */
+	}
+	else
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (qslp->upper[ncols], EGLPNUM_TYPENAME_ILL_MAXDOUBLE);	/* Slack      */
+	}
+
+	/* Add new row and new logical col to matrix */
+
+	/* Need to map the structural indices to their proper place */
+
+	if (cnt)
+	{
+		ILL_SAFE_MALLOC (tempind, cnt, int);
+
+		for (i = 0; i < cnt; i++)
+		{
+			tempind[i] = qslp->structmap[ind[i]];
+		}
+	}
+
+	rval = matrix_addrow (A, cnt, tempind, val);
+	CHECKRVALG (rval, CLEANUP);
+
+	tind[0] = nrows;
+	EGLPNUM_TYPENAME_EGlpNumOne (*tval);
+	if (sense == 'G' || sense == 'R')
+		EGLPNUM_TYPENAME_EGlpNumSign (*tval);
+
+	rval = matrix_addcol (A, 1, tind, tval);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (B != 0)
+	{
+		B->rstat = EGrealloc (B->rstat, sizeof (char) * (nrows + 1));
+		//rval = ILLutil_reallocrus_count ((void **) &(B->rstat), nrows + 1,
+		//                                 sizeof (char));
+		//CHECKRVALG(rval,CLEANUP);
+		B->rstat[nrows] = QS_ROW_BSTAT_BASIC;
+	}
+
+#if 0
+	lp->basisid = -1;							/* To get optimizer to reload the basis */
+#endif
+
+	qslp->ncols++;
+	qslp->nrows++;
+	qslp->nzcount += (cnt + 1);
+
+	if (B != 0)
+	{
+		B->nrows++;
+	}
+
+CLEANUP:
+	ILL_IFFREE (tempind, int);
+
+	EGLPNUM_TYPENAME_EGlpNumClearVar (tval[0]);
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_delrows (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_ILLlp_basis * B,
+	EGLPNUM_TYPENAME_ILLlp_cache * C,
+	int num,
+	int *dellist,
+	int *basis_ok,
+	int *cache_ok)
+{
+	int rval = 0;
+	int i, j, k, nrows, ncols, nstruct, spot, dk, bok = 0, cok = 0;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp;
+	EGLPNUM_TYPENAME_ILLmatrix *A;
+	char *rowmark = 0;
+	char *colmark = 0;
+	int *newrowindex = 0;
+	int *newcolindex = 0;
+	int *ind, *beg, *cnt;
+	EGLPNUM_TYPE *val;
+
+	if (!lp)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_delrows called without an lp");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	if (num <= 0)
+	{
+		if (basis_ok)
+			*basis_ok = 1;
+		if (cache_ok)
+			*cache_ok = 1;
+		ILL_CLEANUP;
+	}
+
+	if (basis_ok)
+		*basis_ok = 0;
+	if (cache_ok)
+		*cache_ok = 0;
+
+	qslp = lp->O;
+	A = &qslp->A;
+
+	if (qslp->rA)
+	{															/* After a delrow call, needs to be updated */
+		EGLPNUM_TYPENAME_ILLlp_rows_clear (qslp->rA);
+		ILL_IFFREE (qslp->rA, EGLPNUM_TYPENAME_ILLlp_rows);
+	}
+
+	nrows = A->matrows;
+	ncols = A->matcols;
+	ind = A->matind;
+	beg = A->matbeg;
+	cnt = A->matcnt;
+	val = A->matval;
+	nstruct = qslp->nstruct;
+
+	ILL_SAFE_MALLOC (rowmark, nrows, char);
+
+	for (i = 0; i < nrows; i++)
+	{
+		rowmark[i] = 0;
+	}
+	for (i = 0; i < num; i++)
+	{
+		rowmark[dellist[i]] = 1;
+	}
+
+
+	/* Try to update the basis */
+
+	if (B)
+	{
+		bok = 1;
+		cok = 1;
+		for (i = 0; i < num; i++)
+		{
+			j = dellist[i];
+			if (B->rstat[j] == QS_ROW_BSTAT_LOWER ||
+					B->rstat[j] == QS_ROW_BSTAT_UPPER)
+			{
+				bok = 0;
+				break;
+			}
+			if (C && EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_DFEAS_TOLER, C->pi[j]))
+			{
+/*
+                QSlog("XXXX: Postive pi (%f) at basic row", C->pi[j]);
+*/
+				cok = 0;
+			}
+		}
+		if (bok == 1)
+		{
+			EGLPNUM_TYPENAME_EGlpNumFreeArray (B->colnorms);
+			if (B->rownorms)
+			{
+				for (i = 0, k = 0; i < nstruct; i++)
+				{
+					if (B->cstat[i] == QS_COL_BSTAT_BASIC)
+						k++;
+				}
+				for (i = 0, j = k; i < nrows; i++)
+				{
+					if (B->rstat[i] == QS_ROW_BSTAT_BASIC)
+					{
+						if (rowmark[i] == 0)
+						{
+							EGLPNUM_TYPENAME_EGlpNumCopy (B->rownorms[k++], B->rownorms[j]);
+						}
+						j++;
+					}
+				}
+				if (k != nrows - num)
+				{
+					QSlog("error in  EGLPNUM_TYPENAME_ILLlib_delrows");
+					rval = 1;
+					ILL_CLEANUP;
+				}
+			}
+
+			for (i = 0, j = 0; i < nrows; i++)
+			{
+				if (rowmark[i] == 0)
+				{
+					B->rstat[j++] = B->rstat[i];
+				}
+			}
+			B->nrows = j;
+
+			if (C && cok == 1)
+			{
+				for (i = 0, j = 0; i < nrows; i++)
+				{
+					if (rowmark[i] == 0)
+					{
+						EGLPNUM_TYPENAME_EGlpNumCopy (C->pi[j], C->pi[i]);
+						EGLPNUM_TYPENAME_EGlpNumCopy (C->slack[j++], C->slack[i]);
+					}
+				}
+				C->nrows = j;
+				if (cache_ok)
+					*cache_ok = 1;
+			}
+			if (basis_ok)
+				*basis_ok = 1;
+		}
+	}
+
+	ILL_SAFE_MALLOC (newrowindex, nrows, int);
+
+
+	/* Delete the marked rows */
+
+	ILL_FAILtrue (qslp->rownames == NULL, "must always be non NULL");
+	for (i = 0, j = 0; i < nrows; i++)
+	{
+		if (rowmark[i] == 0)
+		{
+			if (i != j)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (qslp->rhs[j], qslp->rhs[i]);
+				qslp->sense[j] = qslp->sense[i];
+				if (qslp->rangeval)
+					EGLPNUM_TYPENAME_EGlpNumCopy (qslp->rangeval[j], qslp->rangeval[i]);
+				if (qslp->rownames)
+					qslp->rownames[j] = qslp->rownames[i];
+			}
+			newrowindex[i] = j++;
+		}
+		else
+		{
+			if (qslp->rownames)
+			{
+				rval = ILLsymboltab_delete (&qslp->rowtab, qslp->rownames[i]);
+				CHECKRVALG (rval, CLEANUP);
+				ILL_IFFREE (qslp->rownames[i], char);
+			}
+		}
+	}
+
+
+	/* Delete the logicals */
+
+	ILL_SAFE_MALLOC (colmark, ncols, char);
+
+	for (i = 0; i < ncols; i++)
+	{
+		colmark[i] = 0;
+	}
+	for (i = 0; i < num; i++)
+	{
+		colmark[qslp->rowmap[dellist[i]]] = 1;
+	}
+
+	rval = delcols_work (lp, colmark);
+	CHECKRVALG (rval, CLEANUP);
+
+	A->matcols -= num;
+	qslp->ncols -= num;
+
+
+	/* Pack the rowmap  */
+
+	for (i = 0, j = 0; i < nrows; i++)
+	{
+		if (rowmark[i] == 0)
+		{
+			qslp->rowmap[j++] = qslp->rowmap[i];
+		}
+	}
+
+	/* Remove the entries to deleted rows, and update the indices */
+
+	for (i = 0; i < ncols - num; i++)
+	{
+		dk = 0;
+		spot = beg[i];
+		for (j = 0; j < cnt[i]; j++)
+		{
+			if (rowmark[ind[beg[i] + j]] == 1)
+			{
+				dk++;
+			}
+			else
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (val[spot], val[beg[i] + j]);
+				ind[spot] = newrowindex[ind[beg[i] + j]];
+				spot++;
+			}
+		}
+		for (; spot < beg[i] + cnt[i]; spot++)
+		{
+			ind[spot] = -1;
+		}
+
+		cnt[i] -= dk;
+		if (cnt[i] == 0)
+		{
+			ind[beg[i]] = 1;					/* we always mark the empty cols */
+		}
+	}
+
+	A->matrows -= num;
+	qslp->nrows -= num;
+
+#if 0
+	lp->basisid = -1;							/* To get optimizer to reload the basis */
+#endif
+
+	/* if the base is OK, we MUST load the status variables again */
+	if(bok)
+	{
+		rval = EGLPNUM_TYPENAME_ILLbasis_load( lp, B);
+		CHECKRVALG (rval, CLEANUP);
+	}
+CLEANUP:
+
+	ILL_IFFREE (rowmark, char);
+	ILL_IFFREE (colmark, char);
+	ILL_IFFREE (newcolindex, int);
+	ILL_IFFREE (newrowindex, int);
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_delcols (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_ILLlp_basis * B,
+	int num,
+	int *dellist,
+	int *basis_ok)
+{
+	int rval = 0;
+	int i, j, bok = 0, ncols;
+	char *colmark = 0;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp;
+
+	if (!lp)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_delcols called without an lp");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	if (basis_ok)
+		*basis_ok = 0;
+
+	if (num <= 0)
+	{
+		*basis_ok = 1;
+		ILL_CLEANUP;
+	}
+
+	qslp = lp->O;
+	ncols = qslp->A.matcols;
+
+	if (qslp->rA)
+	{															/* After a delcol call, needs to be updated */
+		EGLPNUM_TYPENAME_ILLlp_rows_clear (qslp->rA);
+		ILL_IFFREE (qslp->rA, EGLPNUM_TYPENAME_ILLlp_rows);
+	}
+
+	ILL_SAFE_MALLOC (colmark, ncols, char);
+
+	for (i = 0; i < ncols; i++)
+	{
+		colmark[i] = 0;
+	}
+	for (i = 0; i < num; i++)
+	{
+		colmark[qslp->structmap[dellist[i]]] = 1;
+	}
+
+	if (B)
+	{
+		B->nstruct -= num;
+		bok = 1;
+		for (i = 0; i < num; i++)
+		{
+			j = dellist[i];
+			if (B->cstat[j] == QS_COL_BSTAT_BASIC)
+			{
+				bok = 0;
+				//QSlog("BONG");
+				break;
+			}
+		}
+		if (bok == 1)
+		{
+			EGLPNUM_TYPENAME_EGlpNumFreeArray (B->colnorms);
+			for (i = 0, j = 0; i < qslp->nstruct; i++)
+			{
+				if (colmark[qslp->structmap[i]] == 0)
+				{
+					B->cstat[j++] = B->cstat[i];
+				}
+			}
+			if (basis_ok)
+				*basis_ok = 1;
+		}
+	}
+
+	rval = delcols_work (lp, colmark);
+	CHECKRVALG (rval, CLEANUP);
+
+
+	qslp->A.matcols -= num;
+	qslp->ncols -= num;
+	qslp->nstruct -= num;
+
+	/* if the base is OK, we MUST load the status variables again */
+	if(bok)
+	{
+		rval = EGLPNUM_TYPENAME_ILLbasis_load( lp, B);
+		CHECKRVALG (rval, CLEANUP);
+	}
+#if 0
+	lp->basisid = -1;							/* To get optimizer to reload the basis */
+#endif
+
+CLEANUP:
+
+	ILL_IFFREE (colmark, char);
+
+	EG_RETURN (rval);
+}
+
+static int matrix_getcoef (
+	EGLPNUM_TYPENAME_ILLmatrix *A, 
+	int row,
+	int col,
+	EGLPNUM_TYPE*val)
+{
+	int i;
+	int rval = 0;
+	if (row >= A->matrows || row < 0)
+	{
+		QSlog("illegal row index in matrix_getcoef");
+		rval= 1;
+		ILL_CLEANUP;
+	}
+
+	if (col >= A->matcols || col < 0)
+	{
+		QSlog("illegal col index in matrix_getcoef");
+		rval= 1;
+		ILL_CLEANUP;
+	}
+
+	/* by default value is zero */
+	EGLPNUM_TYPENAME_EGlpNumZero(*val);
+	for (i = A->matbeg[col]; i < A->matbeg[col] + A->matcnt[col]; i++)
+	{
+		if (A->matind[i] == row)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy(*val, A->matval[i]);
+			ILL_CLEANUP;
+		}
+	}
+
+CLEANUP:
+
+	EG_RETURN(rval);
+}
+
+static int delcols_work (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	char *colmark)
+{
+	int rval = 0;
+	int i, j, k, nrows, ncols;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp;
+	EGLPNUM_TYPENAME_ILLmatrix *A;
+	int *newcolindex = 0;
+	int *ind, *beg, *cnt;
+
+	/* Allows logicals to be deleted, to handle call from delcols. */
+
+	qslp = lp->O;
+	A = &qslp->A;
+	nrows = A->matrows;
+	ncols = A->matcols;
+	ind = A->matind;
+	beg = A->matbeg;
+	cnt = A->matcnt;
+
+	ILL_SAFE_MALLOC (newcolindex, ncols, int);
+
+	/* Delete the columns */
+
+	for (i = 0, j = 0; i < ncols; i++)
+	{
+		if (colmark[i] == 0)
+		{
+			if (i != j)
+			{
+				beg[j] = beg[i];
+				cnt[j] = cnt[i];
+				EGLPNUM_TYPENAME_EGlpNumCopy (qslp->obj[j], qslp->obj[i]);
+				EGLPNUM_TYPENAME_EGlpNumCopy (qslp->lower[j], qslp->lower[i]);
+				EGLPNUM_TYPENAME_EGlpNumCopy (qslp->upper[j], qslp->upper[i]);
+			}
+			newcolindex[i] = j++;
+		}
+		else
+		{
+			for (k = 0; k < cnt[i]; k++)
+			{
+				ind[beg[i] + k] = -1;
+			}
+			newcolindex[i] = -1;
+		}
+	}
+
+	/* Update the struct arrays */
+
+	for (i = 0, j = 0; i < qslp->nstruct; i++)
+	{
+		k = qslp->structmap[i];
+		if (colmark[k] == 0)
+		{
+			qslp->structmap[j] = newcolindex[k];
+			qslp->colnames[j] = qslp->colnames[i];
+			if (qslp->intmarker)
+				qslp->intmarker[j] = qslp->intmarker[i];
+			j++;
+		}
+		else
+		{
+			rval = ILLsymboltab_delete (&qslp->coltab, qslp->colnames[i]);
+			CHECKRVALG (rval, CLEANUP);
+			ILL_IFFREE (qslp->colnames[i], char);
+		}
+	}
+
+	/* Update the rowmap: note if logicals deleted, map will be -1 */
+
+	for (i = 0; i < nrows; i++)
+	{
+		qslp->rowmap[i] = newcolindex[qslp->rowmap[i]];
+	}
+
+CLEANUP:
+
+	ILL_IFFREE (newcolindex, int);
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_getcoef (
+	EGLPNUM_TYPENAME_lpinfo *lp,
+	int rowindex,
+	int colindex,
+	EGLPNUM_TYPE* coef)
+{ 
+	int rval = 0;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp;
+	EGLPNUM_TYPENAME_ILLmatrix *A;
+	int nrows, nstruct, j;
+	if (!lp)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_chgcoef called without an lp");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	qslp = lp->O;
+	A = &qslp->A;
+	nrows = qslp->nrows;
+	nstruct = qslp->nstruct;
+
+	if (rowindex < 0 || rowindex >= nrows || colindex < 0 || colindex >= nstruct)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_getcoef called with out-of-range index");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+	
+	j = qslp->structmap[colindex];
+	rval = matrix_getcoef (A, rowindex, j, coef);
+	CHECKRVALG(rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_chgcoef (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int rowindex,
+	int colindex,
+	EGLPNUM_TYPE coef)
+{
+	int rval = 0;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp;
+	EGLPNUM_TYPENAME_ILLmatrix *A;
+	int nrows, nstruct, j;
+
+	if (!lp)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_chgcoef called without an lp");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	qslp = lp->O;
+	A = &qslp->A;
+
+	nrows = qslp->nrows;
+	nstruct = qslp->nstruct;
+
+	if (rowindex < 0 || rowindex >= nrows || colindex < 0 || colindex >= nstruct)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_chgcoef called with out-of-range index");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	if (qslp->rA)
+	{															/* After a chgcoef call, needs to be updated */
+		EGLPNUM_TYPENAME_ILLlp_rows_clear (qslp->rA);
+		ILL_IFFREE (qslp->rA, EGLPNUM_TYPENAME_ILLlp_rows);
+	}
+
+	if (qslp->sinfo)
+	{															/* Presolve LP is no longer valid, free the data */
+		EGLPNUM_TYPENAME_ILLlp_sinfo_free (qslp->sinfo);
+		ILL_IFFREE (qslp->sinfo, EGLPNUM_TYPENAME_ILLlp_sinfo);
+	}
+
+	j = qslp->structmap[colindex];
+
+	rval = matrix_addcoef (lp, A, rowindex, j, coef);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_chgsense (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int num,
+	int *rowlist,
+	char *sense)
+{
+	int rval = 0;
+	int i, j, k;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp = lp->O;
+	EGLPNUM_TYPENAME_ILLmatrix *A = &(lp->O->A);
+
+	for (i = 0; i < num; i++)
+	{
+		j = qslp->rowmap[rowlist[i]];
+		if (A->matcnt[j] != 1)
+		{
+			QSlog("logical variable is not a singleton");
+			rval = 1;
+			ILL_CLEANUP;
+		}
+		k = A->matbeg[j];
+		switch (sense[i])
+		{
+		case 'R':									/* Range constraint, we will set its upper bound
+																 once we call EGLPNUM_TYPENAME_QSchange_range, by default it 
+																 will be zero, i.e. an equation. */
+			qslp->sense[rowlist[i]] = 'R';
+			EGLPNUM_TYPENAME_EGlpNumZero(qslp->lower[j]);
+			EGLPNUM_TYPENAME_EGlpNumZero(qslp->upper[j]);
+			EGLPNUM_TYPENAME_EGlpNumOne(A->matval[k]);
+			break;
+		case 'E':									/* Artificial */
+			qslp->sense[rowlist[i]] = 'E';
+			EGLPNUM_TYPENAME_EGlpNumZero (qslp->lower[j]);
+			EGLPNUM_TYPENAME_EGlpNumZero (qslp->upper[j]);
+			EGLPNUM_TYPENAME_EGlpNumOne (A->matval[k]);
+			break;
+		case 'G':									/* Surplus   */
+			qslp->sense[rowlist[i]] = 'G';
+			EGLPNUM_TYPENAME_EGlpNumZero (qslp->lower[j]);
+			EGLPNUM_TYPENAME_EGlpNumCopy (qslp->upper[j], EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+			EGLPNUM_TYPENAME_EGlpNumOne (A->matval[k]);
+			EGLPNUM_TYPENAME_EGlpNumSign (A->matval[k]);
+			break;
+		case 'L':									/* Slack     */
+			qslp->sense[rowlist[i]] = 'L';
+			EGLPNUM_TYPENAME_EGlpNumZero (qslp->lower[j]);
+			EGLPNUM_TYPENAME_EGlpNumCopy (qslp->upper[j], EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+			EGLPNUM_TYPENAME_EGlpNumOne (A->matval[k]);
+			break;
+		default:
+			QSlog("illegal sense %c in EGLPNUM_TYPENAME_ILLlib_chgsense", sense[i]);
+			rval = 1;
+			ILL_CLEANUP;
+		}
+	}
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_getsenses (
+	EGLPNUM_TYPENAME_lpinfo *lp,
+	char *senses)
+{
+	EGLPNUM_TYPENAME_ILLlpdata *qslp;
+	int nrows, i;
+	int rval = 0;
+
+	if (!lp) {
+		QSlog("ILLlib_getsense called without an LP");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	qslp = lp->O;
+	nrows = qslp->nrows;
+
+	for (i = 0; i < nrows; i++)
+	{
+		senses[i] = qslp->sense[i];
+	} 
+
+CLEANUP:
+
+    EG_RETURN(rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_newcol (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_ILLlp_basis * B,
+	const EGLPNUM_TYPE obj,
+	const EGLPNUM_TYPE lower,
+	const EGLPNUM_TYPE upper,
+	const char *name,
+	int factorok)
+{
+	int rval = 0;
+
+	rval = EGLPNUM_TYPENAME_ILLlib_addcol (lp, B, 0, 0, 0, obj, lower, upper, name, factorok);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_newcols (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_ILLlp_basis * B,
+	int num,
+	EGLPNUM_TYPE * obj,
+	EGLPNUM_TYPE * lower,
+	EGLPNUM_TYPE * upper,
+	const char **names,
+	int factorok)
+{
+	int rval = 0;
+	int *cmatcnt = 0;
+	int *cmatbeg = 0;
+	int i;
+
+	ILL_SAFE_MALLOC (cmatcnt, num, int);
+
+	ILL_SAFE_MALLOC (cmatbeg, num, int);
+
+	for (i = 0; i < num; i++)
+	{
+		cmatcnt[i] = 0;
+		cmatbeg[i] = 0;
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLlib_addcols (lp, B, num, cmatcnt, cmatbeg, 0,
+												 0, obj, lower, upper, names, factorok);
+	CHECKRVALG (rval, CLEANUP);
+
+
+CLEANUP:
+
+	ILL_IFFREE (cmatcnt, int);
+	ILL_IFFREE (cmatbeg, int);
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_addcols (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_ILLlp_basis * B,
+	int num,
+	int *cmatcnt,
+	int *cmatbeg,
+	int *cmatind,
+	EGLPNUM_TYPE * cmatval,
+	EGLPNUM_TYPE * obj,
+	EGLPNUM_TYPE * lower,
+	EGLPNUM_TYPE * upper,
+	const char **names,
+	int factorok)
+{
+	int rval = 0;
+	int i;
+
+	for (i = 0; i < num; i++)
+	{
+		if (names)
+		{
+			rval = EGLPNUM_TYPENAME_ILLlib_addcol (lp, B, cmatcnt[i], cmatind + cmatbeg[i],
+														cmatval + cmatbeg[i], obj[i], lower[i],
+														upper[i], names[i], factorok);
+		}
+		else
+		{
+			rval = EGLPNUM_TYPENAME_ILLlib_addcol (lp, B, cmatcnt[i], cmatind + cmatbeg[i],
+														cmatval + cmatbeg[i], obj[i], lower[i],
+														upper[i], 0, factorok);
+		}
+		CHECKRVALG (rval, CLEANUP);
+	}
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_addcol (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_ILLlp_basis * B,
+	int cnt,
+	int *ind,
+	EGLPNUM_TYPE * val,
+	const EGLPNUM_TYPE obj,
+	const EGLPNUM_TYPE lower,
+	const EGLPNUM_TYPE upper,
+	const char *name,
+	int factorok)
+{
+	int rval = 0;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp;
+	EGLPNUM_TYPENAME_ILLmatrix *A;
+	int ncols;
+	char buf[ILL_namebufsize];
+	int pind, hit;
+	EGLPNUM_TYPE l, u;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (l);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (u);
+
+	if (!lp)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_addcol called without an lp");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	qslp = lp->O;
+	A = &qslp->A;
+	ncols = qslp->ncols;
+
+	if (qslp->rA)
+	{															/* After an addcol call, needs to be updated */
+		EGLPNUM_TYPENAME_ILLlp_rows_clear (qslp->rA);
+		ILL_IFFREE (qslp->rA, EGLPNUM_TYPENAME_ILLlp_rows);
+	}
+
+	if (qslp->sinfo)
+	{															/* Presolve LP is no longer valid, free the data */
+		EGLPNUM_TYPENAME_ILLlp_sinfo_free (qslp->sinfo);
+		ILL_IFFREE (qslp->sinfo, EGLPNUM_TYPENAME_ILLlp_sinfo);
+	}
+
+
+	/* Add the new variable to the column structures */
+
+	if (qslp->colsize < ncols + 1)
+	{
+		EGLPNUM_TYPENAME_EGlpNumReallocArray (&(qslp->lower), qslp->colsize + EXTRA_COLS);
+		EGLPNUM_TYPENAME_EGlpNumReallocArray (&(qslp->upper), qslp->colsize + EXTRA_COLS);
+		EGLPNUM_TYPENAME_EGlpNumReallocArray (&(qslp->obj), qslp->colsize + EXTRA_COLS);
+		qslp->colsize += EXTRA_COLS;
+	}
+
+	EGLPNUM_TYPENAME_EGlpNumCopy (qslp->obj[ncols], obj);
+	EGLPNUM_TYPENAME_EGlpNumCopy (qslp->lower[ncols], lower);
+	EGLPNUM_TYPENAME_EGlpNumCopy (qslp->upper[ncols], upper);
+
+	/*  Add the variable to the structural arrays */
+
+	if (qslp->structsize < qslp->nstruct + 1)
+	{
+		qslp->structmap = EGrealloc (qslp->structmap,
+																 sizeof (int) * (qslp->structsize +
+																								 EXTRA_COLS));
+		//rval = ILLutil_reallocrus_count ((void **) &(qslp->structmap),
+		//                                 qslp->structsize + EXTRA_COLS,
+		//                                 sizeof (int));
+		//CHECKRVALG(rval,CLEANUP);
+
+		qslp->colnames = EGrealloc (qslp->colnames,
+																sizeof (char *) * (qslp->structsize +
+																									 EXTRA_COLS));
+		//rval = ILLutil_reallocrus_count ((void **) &(qslp->colnames),
+		//                                 qslp->structsize + EXTRA_COLS,
+		//                                 sizeof (char *));
+		//CHECKRVALG(rval,CLEANUP);
+
+		if (qslp->intmarker)
+		{
+			qslp->intmarker = EGrealloc (qslp->intmarker,
+																	 sizeof (char) * (qslp->structsize +
+																										EXTRA_COLS));
+			//rval = ILLutil_reallocrus_count ((void **) &(qslp->intmarker),
+			//                                 qslp->structsize + EXTRA_COLS,
+			//                                 sizeof (char));
+			//CHECKRVALG(rval,CLEANUP);
+		}
+		qslp->structsize += EXTRA_COLS;
+	}
+
+	qslp->structmap[qslp->nstruct] = ncols;
+	if (qslp->intmarker)
+	{
+		/* NOTE: If we want to add integer variables, this is the place. */
+		qslp->intmarker[qslp->nstruct] = (char) 0;
+	}
+
+	ILL_FAILtrue (qslp->colnames == NULL, "must always be non NULL");
+	EGLPNUM_TYPENAME_ILLlib_findName (qslp, 0 /*isRow */ , name, qslp->nstruct, buf);
+	ILLsymboltab_register (&qslp->coltab, buf, qslp->nstruct, &pind, &hit);
+	ILL_FAILfalse ((pind == qslp->nstruct) && (hit == 0), "must be new");
+	ILL_UTIL_STR (qslp->colnames[qslp->nstruct], buf);
+
+
+	/*  Add col to the matrix */
+
+	rval = matrix_addcol (A, cnt, ind, val);
+	CHECKRVALG (rval, CLEANUP);
+
+
+	if (B)
+	{
+		B->cstat = EGrealloc (B->cstat, sizeof (char) * (qslp->nstruct + 1));
+		//rval = ILLutil_reallocrus_count ((void **) &(B->cstat),
+		//                                 qslp->nstruct + 1, sizeof (char));
+		//CHECKRVALG(rval,CLEANUP);
+		if (EGLPNUM_TYPENAME_EGlpNumIsEqual (lower, EGLPNUM_TYPENAME_ILL_MINDOUBLE, EGLPNUM_TYPENAME_oneLpNum) &&
+				EGLPNUM_TYPENAME_EGlpNumIsEqual (upper, EGLPNUM_TYPENAME_ILL_MAXDOUBLE, EGLPNUM_TYPENAME_oneLpNum))
+		{
+			B->cstat[qslp->nstruct] = QS_COL_BSTAT_FREE;
+		}
+		else if (EGLPNUM_TYPENAME_EGlpNumIsEqual (upper, EGLPNUM_TYPENAME_ILL_MAXDOUBLE, EGLPNUM_TYPENAME_oneLpNum))
+		{
+			B->cstat[qslp->nstruct] = QS_COL_BSTAT_LOWER;
+		}
+		//else if (lower == EGLPNUM_TYPENAME_ILL_MAXDOUBLE)
+		else if (EGLPNUM_TYPENAME_EGlpNumIsEqual (lower, EGLPNUM_TYPENAME_ILL_MAXDOUBLE, EGLPNUM_TYPENAME_oneLpNum))
+		{
+			B->cstat[qslp->nstruct] = QS_COL_BSTAT_UPPER;
+		}
+		else
+		{
+			/*l = fabs (lower);
+			 * u = fabs (upper); */
+			EGLPNUM_TYPENAME_EGlpNumCopyAbs (l, lower);
+			EGLPNUM_TYPENAME_EGlpNumCopyAbs (u, upper);
+			if (EGLPNUM_TYPENAME_EGlpNumIsLess (l, u))
+			{
+				B->cstat[qslp->nstruct] = QS_COL_BSTAT_LOWER;
+			}
+			else
+			{
+				B->cstat[qslp->nstruct] = QS_COL_BSTAT_UPPER;
+			}
+		}
+
+		/* UPDATE THE PINF PRIMAL NORMS */
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (B->colnorms);
+	}
+
+	if (factorok == 0)
+	{
+#if 0
+		lp->basisid = -1;						/* To get optimizer to reload the basis */
+#endif
+	}
+	else
+	{
+		if (!lp->nbaz || !lp->vindex || !lp->vstat)
+		{
+			QSlog("ERROR: factorok set without a current basis");
+			rval = 1;
+			ILL_CLEANUP;
+		}
+
+		lp->nbaz = EGrealloc (lp->nbaz, sizeof (int) * (qslp->nstruct + 1));
+		//rval = ILLutil_reallocrus_count ((void **) &(lp->nbaz),
+		//                                 qslp->nstruct + 1, sizeof (int));
+		//CHECKRVALG(rval,CLEANUP);
+
+		lp->vindex = EGrealloc (lp->vindex, sizeof (int) * (qslp->ncols + 1));
+		//rval = ILLutil_reallocrus_count ((void **) &(lp->vindex),
+		//                                 qslp->ncols + 1, sizeof (int));
+		//CHECKRVALG(rval,CLEANUP);
+
+		lp->vstat = EGrealloc (lp->vstat, sizeof (int) * (qslp->ncols + 1));
+		//rval = ILLutil_reallocrus_count ((void **) &(lp->vstat),
+		//                                 qslp->ncols + 1, sizeof (int));
+
+
+		lp->nbaz[qslp->nstruct] = qslp->ncols;
+		lp->vindex[qslp->ncols] = qslp->nstruct;
+
+		if (EGLPNUM_TYPENAME_EGlpNumIsEqual (lower, EGLPNUM_TYPENAME_ILL_MINDOUBLE, EGLPNUM_TYPENAME_oneLpNum) &&
+				EGLPNUM_TYPENAME_EGlpNumIsEqual (upper, EGLPNUM_TYPENAME_ILL_MAXDOUBLE, EGLPNUM_TYPENAME_oneLpNum))
+		{
+			lp->vstat[qslp->ncols] = STAT_ZERO;
+		}
+		else if (EGLPNUM_TYPENAME_EGlpNumIsEqual (upper, EGLPNUM_TYPENAME_ILL_MAXDOUBLE, EGLPNUM_TYPENAME_oneLpNum))
+		{
+			lp->vstat[qslp->ncols] = STAT_LOWER;
+		}
+		//else if (lower == EGLPNUM_TYPENAME_ILL_MAXDOUBLE)
+		else if (EGLPNUM_TYPENAME_EGlpNumIsEqual (lower, EGLPNUM_TYPENAME_ILL_MAXDOUBLE, EGLPNUM_TYPENAME_oneLpNum))
+		{
+			lp->vstat[qslp->ncols] = STAT_UPPER;
+		}
+		else
+		{
+			/*l = fabs (lower);
+			 * u = fabs (upper); */
+			EGLPNUM_TYPENAME_EGlpNumCopyAbs (l, lower);
+			EGLPNUM_TYPENAME_EGlpNumCopyAbs (u, upper);
+			if (EGLPNUM_TYPENAME_EGlpNumIsLess (l, u))
+			{
+				lp->vstat[qslp->ncols] = STAT_LOWER;
+			}
+			else
+			{
+				lp->vstat[qslp->ncols] = STAT_UPPER;
+			}
+		}
+	}
+
+
+	qslp->ncols++;
+	qslp->nstruct++;
+	(qslp->nzcount) += cnt;
+
+	if (B)
+	{
+		B->nstruct++;
+	}
+
+CLEANUP:
+	EGLPNUM_TYPENAME_EGlpNumClearVar (l);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (u);
+	EG_RETURN (rval);
+}
+
+static int matrix_addrow (
+	EGLPNUM_TYPENAME_ILLmatrix * A,
+	int rowcnt,
+	int *rowind,
+	const EGLPNUM_TYPE * rowval)
+{
+	int rval = 0;
+	int i, j, k, ind, memo, stop, delta = 0;
+
+	/* matsize will be the length of the array.                   */
+	/* matfree will keep track of the free space at end of array. */
+
+	for (i = 0; i < rowcnt; i++)
+	{
+		if (rowind[i] >= A->matcols || rowind[i] < 0)
+		{
+			QSlog("illegal col index in matrix_addrow");
+			rval = 1;
+			ILL_CLEANUP;
+		}
+	}
+
+	for (i = 0; i < rowcnt; i++)
+	{
+		j = rowind[i];
+		if (A->matcnt[j] > 0 &&
+				(A->matbeg[j] + A->matcnt[j] + 1 > A->matsize ||
+				 A->matind[A->matbeg[j] + A->matcnt[j]] != -1))
+		{
+			delta += (A->matcnt[j] + 2);	/* 1 for the new coef and 1 for */
+			/* an extra space               */
+		}
+	}
+
+	if (delta < A->matfree)
+	{
+		for (i = 0; i < rowcnt; i++)
+		{
+			j = rowind[i];
+			if (A->matcnt[j] == 0)
+			{
+				A->matind[A->matbeg[j]] = A->matrows;
+				EGLPNUM_TYPENAME_EGlpNumCopy (A->matval[A->matbeg[j]], rowval[i]);
+				A->matcnt[j] = 1;
+			}
+			else if (A->matind[A->matbeg[j] + A->matcnt[j]] == -1)
+			{
+				/* Since A->matfree is positive, we know that we are not */
+				/* sitting at the end of the array.                      */
+				A->matind[A->matbeg[j] + A->matcnt[j]] = A->matrows;
+				EGLPNUM_TYPENAME_EGlpNumCopy (A->matval[A->matbeg[j] + A->matcnt[j]], rowval[i]);
+				if ((A->matbeg[j] + A->matcnt[j]) == (A->matsize - A->matfree))
+				{
+					A->matfree--;					/* at end of used space */
+				}
+				(A->matcnt[j])++;
+			}
+			else
+			{
+				ind = A->matsize - A->matfree + 1;	/* leave space for -1 */
+				memo = ind;
+				stop = A->matbeg[j] + A->matcnt[j];
+				for (k = A->matbeg[j]; k < stop; k++)
+				{
+					if (ind >= A->matsize)
+					{
+						QSlog("WHAT: %d, %d", A->matsize, ind);
+						exit (1);
+					}
+					A->matind[ind] = A->matind[k];
+					EGLPNUM_TYPENAME_EGlpNumCopy (A->matval[ind], A->matval[k]);
+					A->matind[k] = -1;
+					ind++;
+				}
+				A->matind[ind] = A->matrows;
+				EGLPNUM_TYPENAME_EGlpNumCopy (A->matval[ind], rowval[i]);
+				A->matbeg[j] = memo;
+				(A->matcnt[j])++;
+				(A->matfree) -= (A->matcnt[j] + 1);
+			}
+		}
+	}
+	else
+	{
+		rval = matrix_addrow_end (A, A->matrows, rowcnt, rowind, rowval);
+		CHECKRVALG (rval, CLEANUP);
+	}
+	A->matrows++;
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+static int matrix_addrow_end (
+	EGLPNUM_TYPENAME_ILLmatrix * A,
+	int row,
+	int rowcnt,
+	int *rowind,
+	const EGLPNUM_TYPE * rowval)
+{
+	int rval = 0;
+	int i, j, k, start, stop, total;
+	int *newbeg = 0;
+	int *newind = 0;
+	EGLPNUM_TYPE *newval = 0;
+	int ncols = A->matcols;
+
+	if (A->matcolsize > 0)
+	{
+		ILL_SAFE_MALLOC (newbeg, A->matcolsize, int);
+	}
+	ILL_SAFE_MALLOC (newind, A->matsize + rowcnt + EXTRA_MAT, int);
+
+	newval = EGLPNUM_TYPENAME_EGlpNumAllocArray (A->matsize + rowcnt + EXTRA_MAT);
+
+	A->matsize += (rowcnt + EXTRA_MAT);
+
+	for (i = 0; i < rowcnt; i++)
+	{
+		A->matcnt[rowind[i]]++;
+	}
+	for (total = 0, j = 0; j < ncols; j++)
+	{
+		newbeg[j] = total;
+		if (A->matcnt[j] > 0)
+			total += A->matcnt[j];
+		else
+			total += 1;
+	}
+	for (i = 0; i < rowcnt; i++)
+	{
+		A->matcnt[rowind[i]]--;
+	}
+	for (j = total; j < A->matsize; j++)
+	{
+		newind[j] = -1;
+	}
+	A->matfree = A->matsize - total;
+
+	for (j = 0; j < ncols; j++)
+	{
+		if (A->matcnt[j] > 0)
+		{
+			stop = A->matbeg[j] + A->matcnt[j];
+			start = newbeg[j];
+			for (k = A->matbeg[j]; k < stop; k++)
+			{
+				newind[start] = A->matind[k];
+				EGLPNUM_TYPENAME_EGlpNumCopy (newval[start], A->matval[k]);
+				start++;
+			}
+		}
+		else
+		{
+			newind[newbeg[j]] = 1;
+		}
+	}
+	for (i = 0; i < rowcnt; i++)
+	{
+		j = rowind[i];
+		newind[newbeg[j] + A->matcnt[j]] = row;
+		EGLPNUM_TYPENAME_EGlpNumCopy (newval[newbeg[j] + A->matcnt[j]], rowval[i]);
+		(A->matcnt[j])++;
+	}
+
+	ILL_IFFREE (A->matbeg, int);
+	ILL_IFFREE (A->matind, int);
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (A->matval);
+
+	A->matbeg = newbeg;
+	A->matind = newind;
+	A->matval = newval;
+
+CLEANUP:
+
+	if (rval)
+	{
+		ILL_IFFREE (newbeg, int);
+		ILL_IFFREE (newind, int);
+
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (newval);
+	}
+
+	EG_RETURN (rval);
+}
+
+static int matrix_addcoef (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_ILLmatrix * A,
+	int row,
+	int col,
+	EGLPNUM_TYPE val)
+{
+	int i, k, delta, ind, stop, memo;
+	int tind[1];
+	EGLPNUM_TYPE tval[1];
+	int rval = 0;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (tval[0]);
+	EGLPNUM_TYPENAME_EGlpNumCopy (tval[0], val);
+
+	if (row >= A->matrows || row < 0)
+	{
+		QSlog("illegal row index in matrix_addcoef");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	if (col >= A->matcols || col < 0)
+	{
+		QSlog("illegal col index in matrix_addcoef");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	for (i = A->matbeg[col]; i < A->matbeg[col] + A->matcnt[col]; i++)
+	{
+		if (A->matind[i] == row)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (A->matval[i], val);
+			ILL_CLEANUP;
+		}
+	}
+
+	/* The coef is new, we need to add it to A */
+
+	lp->O->nzcount++;
+	delta = A->matcnt[col] + 2;
+
+	if (A->matcnt[col] == 0)
+	{
+		/* First entry, always a free space */
+		A->matind[A->matbeg[col]] = row;
+		EGLPNUM_TYPENAME_EGlpNumCopy (A->matval[A->matbeg[col]], val);
+		A->matcnt[col] = 1;
+	}
+	else if (A->matbeg[col] + A->matcnt[col] < A->matsize &&
+					 A->matind[A->matbeg[col] + A->matcnt[col]] == -1)
+	{
+		/* Free space in the column */
+		A->matind[A->matbeg[col] + A->matcnt[col]] = row;
+		EGLPNUM_TYPENAME_EGlpNumCopy (A->matval[A->matbeg[col] + A->matcnt[col]], val);
+		if ((A->matbeg[col] + A->matcnt[col]) == (A->matsize - A->matfree))
+		{
+			A->matfree--;
+		}
+		(A->matcnt[col])++;
+	}
+	else if (A->matfree > delta)
+	{
+		/* Enough space to move column to end of array */
+		ind = A->matsize - A->matfree + 1;
+		memo = ind;
+		stop = A->matbeg[col] + A->matcnt[col];
+		for (k = A->matbeg[col]; k < stop; k++)
+		{
+			A->matind[ind] = A->matind[k];
+			EGLPNUM_TYPENAME_EGlpNumCopy (A->matval[ind], A->matval[k]);
+			A->matind[k] = -1;
+			ind++;
+		}
+		A->matind[ind] = row;
+		EGLPNUM_TYPENAME_EGlpNumCopy (A->matval[ind], val);
+
+		A->matbeg[col] = memo;
+		(A->matcnt[col])++;
+		(A->matfree) -= (A->matcnt[col] + 1);
+	}
+	else
+	{
+		/* Need to malloc space to move column to end of array */
+
+		tind[0] = col;
+
+		rval = matrix_addrow_end (A, row, 1, tind, tval);
+		CHECKRVALG (rval, CLEANUP);
+	}
+
+CLEANUP:
+
+	EGLPNUM_TYPENAME_EGlpNumClearVar (tval[0]);
+	EG_RETURN (rval);
+}
+
+static int matrix_addcol (
+	EGLPNUM_TYPENAME_ILLmatrix * A,
+	int colcnt,
+	int *colind,
+	EGLPNUM_TYPE * colval)
+{
+	int rval = 0;
+	int i, ind;
+
+	for (i = 0; i < colcnt; i++)
+	{
+		if (colind[i] >= A->matrows || colind[i] < 0)
+		{
+			QSlog("illegal row index in matrix_addcol");
+			rval = 1;
+			ILL_CLEANUP;
+		}
+	}
+
+	if (A->matcolsize < A->matcols + 1)
+	{
+		A->matbeg =
+			EGrealloc (A->matbeg, sizeof (int) * (A->matcolsize + EXTRA_COLS));
+		//rval = ILLutil_reallocrus_count ((void **) &(A->matbeg),
+		//                                 A->matcolsize + EXTRA_COLS, sizeof (int));
+		//CHECKRVALG(rval,CLEANUP);
+
+		A->matcnt =
+			EGrealloc (A->matcnt, sizeof (int) * (A->matcolsize + EXTRA_COLS));
+		//rval = ILLutil_reallocrus_count ((void **) &(A->matcnt),
+		//                                 A->matcolsize + EXTRA_COLS, sizeof (int));
+		//CHECKRVALG(rval,CLEANUP);
+
+		(A->matcolsize) += EXTRA_COLS;
+	}
+
+	if (A->matfree < colcnt + 1)
+	{
+		A->matind = EGrealloc (A->matind,
+													 sizeof (int) * (A->matsize + colcnt + EXTRA_MAT +
+																					 1));
+		//rval = ILLutil_reallocrus_count ((void **) &(A->matind),
+		//                                 A->matsize + colcnt + EXTRA_MAT + 1,
+		//                                 sizeof (int));
+		//CHECKRVALG(rval,CLEANUP);
+		EGLPNUM_TYPENAME_EGlpNumReallocArray (&(A->matval), A->matsize + colcnt + EXTRA_MAT + 1);
+
+		for (i = 0; i < colcnt + EXTRA_MAT + 1; i++)
+		{
+			A->matind[A->matsize + i] = -1;
+		}
+		A->matsize += (colcnt + EXTRA_MAT + 1);
+		A->matfree += (colcnt + EXTRA_MAT + 1);
+	}
+
+	ind = A->matsize - A->matfree;
+	A->matbeg[A->matcols] = ind;
+	A->matcnt[A->matcols] = colcnt;
+	if (colcnt == 0)
+	{
+		A->matind[ind] = 1;					/* Dummy value to stop columns from stealing */
+		/* this space in addrows.                    */
+		A->matfree -= 1;
+	}
+	else
+	{
+		for (i = 0; i < colcnt; i++)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (A->matval[ind], colval[i]);
+			A->matind[ind] = colind[i];
+			ind++;
+		}
+		A->matfree -= colcnt;
+	}
+	A->matcols++;
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_getrows (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int num,
+	int *rowlist,
+	int **rowcnt,
+	int **rowbeg,
+	int **rowind,
+	EGLPNUM_TYPE ** rowval,
+	EGLPNUM_TYPE ** rhs,
+	char **sense,
+	EGLPNUM_TYPE ** range,
+	char ***names)
+{
+	int rval = 0;
+	int *allbeg = 0;
+	int *allcnt = 0;
+	int *allind = 0;
+	EGLPNUM_TYPE *allval = 0;
+	int i, row, k, start, stop, len, tcnt, cnt = 0;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp;
+	EGLPNUM_TYPENAME_ILLlp_rows lprows;
+
+	if (rowcnt) *rowcnt = 0;
+	if (rowbeg) *rowbeg = 0;
+	if (rowind) *rowind = 0;
+	if (rowval) *rowval = 0;
+	if (rhs) *rhs = 0;
+	if (range) *range = 0;
+	if (sense) *sense = 0;
+	if (names) *names = 0;
+
+	if (!lp)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_getrows called without an LP");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	if (!num)
+		ILL_CLEANUP;
+
+	qslp = lp->O;
+
+	rval = EGLPNUM_TYPENAME_ILLlp_rows_init (&lprows, qslp, 0);
+	CHECKRVALG (rval, CLEANUP);
+	allbeg = lprows.rowbeg;
+	allcnt = lprows.rowcnt;
+	allind = lprows.rowind;
+	allval = lprows.rowval;
+
+	for (i = 0; i < num; i++)
+	{
+		cnt += allcnt[rowlist[i]];
+	}
+
+	if (rowcnt)
+	{
+		ILL_SAFE_MALLOC (*rowcnt, num, int);
+
+		for (i = 0; i < num; i++)
+		{
+			(*rowcnt)[i] = allcnt[rowlist[i]];
+		}
+	}
+
+	if (rowbeg)
+	{
+		ILL_SAFE_MALLOC (*rowbeg, num, int);
+
+		tcnt = 0;
+		for (i = 0; i < num; i++)
+		{
+			(*rowbeg)[i] = tcnt;
+			tcnt += allcnt[rowlist[i]];
+		}
+	}
+
+	if (cnt && rowind)
+	{
+		ILL_SAFE_MALLOC (*rowind, cnt, int);
+
+		tcnt = 0;
+		for (i = 0; i < num; i++)
+		{
+			row = rowlist[i];
+			start = allbeg[row];
+			stop = start + allcnt[row];
+			for (k = start; k < stop; k++)
+			{
+				(*rowind)[tcnt++] = allind[k];
+			}
+		}
+	}
+
+	if (cnt && rowval)
+	{
+		*rowval = EGLPNUM_TYPENAME_EGlpNumAllocArray (cnt);
+		tcnt = 0;
+		for (i = 0; i < num; i++)
+		{
+			row = rowlist[i];
+			start = allbeg[row];
+			stop = start + allcnt[row];
+			for (k = start; k < stop; k++)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy ((*rowval)[tcnt++], allval[k]);
+			}
+		}
+	}
+
+	if (rhs)
+	{
+		*rhs = EGLPNUM_TYPENAME_EGlpNumAllocArray (num);
+		for (i = 0; i < num; i++)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy ((*rhs)[i], qslp->rhs[rowlist[i]]);
+		}
+	}
+
+	if (range)
+	{
+		*range = EGLPNUM_TYPENAME_EGlpNumAllocArray(num);
+		if(qslp->rangeval)
+		{
+			for(i = 0; i < num ; i++)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy((*range)[i], qslp->rangeval[rowlist[i]]);
+			}
+		}
+		else
+		{
+			for(i = 0; i < num ; i++)
+			{
+				EGLPNUM_TYPENAME_EGlpNumZero((*range)[i]);
+			}
+		}
+	}
+
+	if (sense)
+	{
+		ILL_SAFE_MALLOC (*sense, num, char);
+
+		for (i = 0; i < num; i++)
+		{
+			(*sense)[i] = qslp->sense[rowlist[i]];
+		}
+	}
+
+	if (names)
+	{
+		if (qslp->rownames == 0)
+		{
+			QSlog("LP does not have row names");
+			rval = 1;
+			ILL_CLEANUP;
+		}
+		ILL_SAFE_MALLOC (*names, num, char *);
+
+		for (i = 0; i < num; i++)
+		{
+			(*names)[i] = 0;
+		}
+		for (i = 0; i < num; i++)
+		{
+			len = strlen (qslp->rownames[rowlist[i]]) + 1;
+			ILL_SAFE_MALLOC ((*names)[i], len, char);
+
+			strcpy ((*names)[i], qslp->rownames[rowlist[i]]);
+		}
+	}
+
+CLEANUP:
+
+	ILL_IFFREE (allbeg, int);
+	ILL_IFFREE (allcnt, int);
+	ILL_IFFREE (allind, int);
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (allval);
+
+	if (rval)
+	{
+		if (rowcnt)
+			ILL_IFFREE (*rowcnt, int);
+
+		if (rowbeg)
+			ILL_IFFREE (*rowbeg, int);
+
+		if (rowind)
+			ILL_IFFREE (*rowind, int);
+
+		if (rowval)
+			EGLPNUM_TYPENAME_EGlpNumFreeArray (*rowval);
+		if (rhs)
+			EGLPNUM_TYPENAME_EGlpNumFreeArray (*rhs);
+		if (sense)
+			ILL_IFFREE (*sense, char);
+
+		if (names && (*names))
+		{
+			for (i = 0; i < num; i++)
+			{
+				ILL_IFFREE ((*names)[i], char);
+			}
+			ILL_IFFREE (*names, char *);
+		}
+	}
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_getcols (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int num,
+	int *collist,
+	int **colcnt,
+	int **colbeg,
+	int **colind,
+	EGLPNUM_TYPE ** colval,
+	EGLPNUM_TYPE ** obj,
+	EGLPNUM_TYPE ** lower,
+	EGLPNUM_TYPE ** upper,
+	char ***names)
+{
+	int rval = 0;
+	int i, col, k, start, stop, len, tcnt, cnt = 0;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp;
+	EGLPNUM_TYPENAME_ILLmatrix *A;
+	int *tlist = 0;
+
+	if (colcnt)
+		*colcnt = 0;
+	if (colbeg)
+		*colbeg = 0;
+	if (colind)
+		*colind = 0;
+	if (colval)
+		*colval = 0;
+	if (lower)
+		*lower = 0;
+	if (upper)
+		*upper = 0;
+	if (obj)
+		*obj = 0;
+	if (names)
+		*names = 0;
+
+	if (!lp)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_getcols called without an LP");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	if (!num)
+		ILL_CLEANUP;
+
+	qslp = lp->O;
+	A = &(qslp->A);
+
+	ILL_SAFE_MALLOC (tlist, num, int);
+
+	for (i = 0; i < num; i++)
+	{
+		tlist[i] = qslp->structmap[collist[i]];
+	}
+
+	for (i = 0; i < num; i++)
+	{
+		cnt += A->matcnt[tlist[i]];
+	}
+
+	if (colcnt)
+	{
+		ILL_SAFE_MALLOC (*colcnt, num, int);
+
+		for (i = 0; i < num; i++)
+		{
+			(*colcnt)[i] = A->matcnt[tlist[i]];
+		}
+	}
+
+	if (colbeg)
+	{
+		ILL_SAFE_MALLOC (*colbeg, num, int);
+
+		tcnt = 0;
+		for (i = 0; i < num; i++)
+		{
+			(*colbeg)[i] = tcnt;
+			tcnt += A->matcnt[tlist[i]];
+		}
+	}
+
+	if (cnt && colind)
+	{
+		ILL_SAFE_MALLOC (*colind, cnt, int);
+
+		tcnt = 0;
+		for (i = 0; i < num; i++)
+		{
+			col = tlist[i];
+			start = A->matbeg[col];
+			stop = start + A->matcnt[col];
+			for (k = start; k < stop; k++)
+			{
+				(*colind)[tcnt++] = A->matind[k];
+			}
+		}
+	}
+
+	if (cnt && colval)
+	{
+		*colval = EGLPNUM_TYPENAME_EGlpNumAllocArray (cnt);
+		tcnt = 0;
+		for (i = 0; i < num; i++)
+		{
+			col = tlist[i];
+			start = A->matbeg[col];
+			stop = start + A->matcnt[col];
+			for (k = start; k < stop; k++)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy ((*colval)[tcnt++], A->matval[k]);
+			}
+		}
+	}
+
+	if (obj)
+	{
+		*obj = EGLPNUM_TYPENAME_EGlpNumAllocArray (num);
+		for (i = 0; i < num; i++)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy ((*obj)[i], qslp->obj[tlist[i]]);
+		}
+	}
+
+	if (lower)
+	{
+		*lower = EGLPNUM_TYPENAME_EGlpNumAllocArray (num);
+		for (i = 0; i < num; i++)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy ((*lower)[i], qslp->lower[tlist[i]]);
+		}
+	}
+
+	if (upper)
+	{
+		*upper = EGLPNUM_TYPENAME_EGlpNumAllocArray (num);
+		for (i = 0; i < num; i++)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy ((*upper)[i], qslp->upper[tlist[i]]);
+		}
+	}
+
+	if (names)
+	{
+		if (qslp->colnames == 0)
+		{
+			QSlog("LP does not have col names");
+			rval = 1;
+			ILL_CLEANUP;
+		}
+		ILL_SAFE_MALLOC (*names, num, char *);
+
+		for (i = 0; i < num; i++)
+		{
+			(*names)[i] = 0;
+		}
+		for (i = 0; i < num; i++)
+		{
+			len = strlen (qslp->colnames[collist[i]]) + 1;
+			ILL_SAFE_MALLOC ((*names)[i], len, char);
+
+			strcpy ((*names)[i], qslp->colnames[collist[i]]);
+		}
+	}
+
+CLEANUP:
+
+	if (rval)
+	{
+		if (colcnt)
+			ILL_IFFREE (*colcnt, int);
+
+		if (colbeg)
+			ILL_IFFREE (*colbeg, int);
+
+		if (colind)
+			ILL_IFFREE (*colind, int);
+
+		if (colval)
+			EGLPNUM_TYPENAME_EGlpNumFreeArray (*colval);
+		if (obj)
+			EGLPNUM_TYPENAME_EGlpNumFreeArray (*obj);
+		if (lower)
+			EGLPNUM_TYPENAME_EGlpNumFreeArray (*lower);
+		if (upper)
+			EGLPNUM_TYPENAME_EGlpNumFreeArray (*upper);
+		if (names && (*names))
+		{
+			for (i = 0; i < num; i++)
+			{
+				ILL_IFFREE ((*names)[i], char);
+			}
+			ILL_IFFREE (*names, char *);
+		}
+	}
+	ILL_IFFREE (tlist, int);
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_getobj_list (
+	EGLPNUM_TYPENAME_lpinfo *lp,
+	int num,
+	int* collist,
+	EGLPNUM_TYPE* obj)
+{
+	const int*const structmap = lp->O->structmap;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp;
+	int nstruct, j, col;
+	int rval = 0;
+	
+	if (!lp)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_getobj_list called without an LP");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+	
+	qslp = lp->O;
+	nstruct = qslp->nstruct;
+	
+	for (j = 0; j < num; j++)
+	{
+		col = collist[j];
+		if(col<0 || col >= nstruct)
+		{
+			QSlog("EGLPNUM_TYPENAME_ILLlib_getobj_list collist[%d] = %d outside"
+									" valid range", j, col);
+			rval = 1;
+			ILL_CLEANUP;
+		}
+		EGLPNUM_TYPENAME_EGlpNumCopy(obj[j],qslp->obj[structmap[col]]);
+	}  
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+
+int EGLPNUM_TYPENAME_ILLlib_getobj (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPE * obj)
+{
+	const int*const structmap = lp->O->structmap;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp;
+	int nstruct, j;
+	int rval = 0;
+
+	if (!lp)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_getobj called without an LP");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	qslp = lp->O;
+	nstruct = qslp->nstruct;
+
+	for (j = 0; j < nstruct; j++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (obj[j], qslp->obj[structmap[j]]);
+	}
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_chgobj (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int indx,
+	EGLPNUM_TYPE coef)
+{
+	int rval = 0;
+	int col;
+
+	if (!lp)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_chgobj called without an lp");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	if (indx < 0 || indx >= lp->O->nstruct)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_chgrhs called with bad indx: %d", indx);
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	if (lp->O->sinfo)
+	{															/* Presolve LP is no longer valid, free the data */
+		EGLPNUM_TYPENAME_ILLlp_sinfo_free (lp->O->sinfo);
+		ILL_IFFREE (lp->O->sinfo, EGLPNUM_TYPENAME_ILLlp_sinfo);
+	}
+
+	col = lp->O->structmap[indx];
+	EGLPNUM_TYPENAME_EGlpNumCopy (lp->O->obj[col], coef);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_getrhs (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPE * rhs)
+{
+	EGLPNUM_TYPENAME_ILLlpdata *qslp;
+	int nrows, i;
+	int rval = 0;
+
+	if (!lp)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_getrhs called without an LP");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	qslp = lp->O;
+	nrows = qslp->nrows;
+
+	for (i = 0; i < nrows; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (rhs[i], qslp->rhs[i]);
+	}
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_chgrange (
+	EGLPNUM_TYPENAME_lpinfo *lp,
+	int indx,
+	EGLPNUM_TYPE coef)
+{
+	register int i;
+	int rval = 0;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp;
+	
+	if (!lp)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_chgrhs called without an lp");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+	
+	if (indx < 0 || indx >= lp->O->nrows)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_chgrhs called with bad indx: %d", indx);
+		rval = 1;
+		ILL_CLEANUP;
+	}
+	
+	if (lp->O->sinfo)
+	{/* Presolve LP is no longer valid, free the data */
+		EGLPNUM_TYPENAME_ILLlp_sinfo_free (lp->O->sinfo);
+		ILL_IFFREE (lp->O->sinfo, EGLPNUM_TYPENAME_ILLlp_sinfo);
+	}
+	
+	qslp = lp->O;
+	if(qslp->rangeval == 0)
+	{
+		qslp->rangeval = EGLPNUM_TYPENAME_EGlpNumAllocArray(qslp->rowsize);
+		for( i = qslp->nrows ; i-- ; )
+		{
+			EGLPNUM_TYPENAME_EGlpNumZero(qslp->rangeval[i]);
+		}
+	}
+	
+	if(qslp->sense[indx] != 'R')
+	{
+		QSlog("setting range for non-range constraint");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+	
+	EGLPNUM_TYPENAME_EGlpNumCopy(qslp->rangeval[indx], coef);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+
+int EGLPNUM_TYPENAME_ILLlib_chgrhs (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int indx,
+	EGLPNUM_TYPE coef)
+{
+	int rval = 0;
+
+	if (!lp)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_chgrhs called without an lp");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	if (indx < 0 || indx >= lp->O->nrows)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_chgrhs called with bad indx: %d", indx);
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	if (lp->O->sinfo)
+	{															/* Presolve LP is no longer valid, free the data */
+		EGLPNUM_TYPENAME_ILLlp_sinfo_free (lp->O->sinfo);
+		ILL_IFFREE (lp->O->sinfo, EGLPNUM_TYPENAME_ILLlp_sinfo);
+	}
+
+	EGLPNUM_TYPENAME_EGlpNumCopy (lp->O->rhs[indx], coef);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_rownames (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	char **rownames)
+{
+	EGLPNUM_TYPENAME_ILLlpdata *qslp;
+	int nrows, len, i, rcount = 0;
+	int rval = 0;
+
+	if (!lp)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_rownames called without an LP");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+	if (!rownames)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_rownames called with NULL rownames");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	qslp = lp->O;
+	nrows = qslp->nrows;
+
+	if (qslp->rownames == 0)
+	{
+		QSlog("LP does not have rownames assigned");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	for (i = 0; i < nrows; i++)
+	{
+		len = strlen (qslp->rownames[i]) + 1;
+		ILL_SAFE_MALLOC (rownames[i], len, char);
+
+		strcpy (rownames[i], qslp->rownames[i]);
+		rcount++;
+	}
+
+CLEANUP:
+
+	if (rval)
+	{
+		for (i = 0; i < rcount; i++)
+		{
+			ILL_IFFREE (rownames[i], char);
+		}
+	}
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_getintflags (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int *intflags)
+{
+	int j, nstruct, rval = 0;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp;
+
+	if (!lp)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_getintflags called without an LP");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	qslp = lp->O;
+	nstruct = qslp->nstruct;
+
+	if (qslp->intmarker == 0)
+	{
+		for (j = 0; j < nstruct; j++)
+		{
+			intflags[j] = 0;
+		}
+	}
+	else
+	{
+		for (j = 0; j < nstruct; j++)
+		{
+			if (qslp->intmarker[j])
+			{
+				intflags[j] = 1;
+			}
+			else
+			{
+				intflags[j] = 0;
+			}
+		}
+	}
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_colnames (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	char **colnames)
+{
+	EGLPNUM_TYPENAME_ILLlpdata *qslp;
+	int nstruct, len, i, ccount = 0;
+	int rval = 0;
+
+	if (!lp)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_colnames called without an LP");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+	if (!colnames)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_colnames called with NULL colnames");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	qslp = lp->O;
+	nstruct = qslp->nstruct;
+
+	if (qslp->colnames == 0)
+	{
+		QSlog("LP does not have colnames assigned");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	for (i = 0; i < nstruct; i++)
+	{
+		len = strlen (qslp->colnames[i]) + 1;
+		ILL_SAFE_MALLOC (colnames[i], len, char);
+
+		strcpy (colnames[i], qslp->colnames[i]);
+		ccount++;
+	}
+
+
+CLEANUP:
+
+	if (rval)
+	{
+		for (i = 0; i < ccount; i++)
+		{
+			ILL_IFFREE (colnames[i], char);
+		}
+	}
+
+	EG_RETURN (rval);
+}
+
+static int reset_colindex (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	int rval = 0;
+	int test;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp = lp->O;
+
+	test = ILLsymboltab_index_ok (&qslp->coltab);
+	if (!test)
+	{
+		rval = ILLsymboltab_index_reset (&qslp->coltab, qslp->nstruct,
+																		 qslp->colnames);
+		CHECKRVALG (rval, CLEANUP);
+	}
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+static int reset_rowindex (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	int rval = 0;
+	int test;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp = lp->O;
+
+	test = ILLsymboltab_index_ok (&qslp->rowtab);
+	if (!test)
+	{
+		rval = ILLsymboltab_index_reset (&qslp->rowtab, qslp->nrows,
+																		 qslp->rownames);
+		CHECKRVALG (rval, CLEANUP);
+	}
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_colindex (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	const char *name,
+	int *colindex)
+{
+	int rval = 0;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp;
+
+	*colindex = -1;
+
+	if (!lp)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_colindex called without an LP");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	qslp = lp->O;
+
+	rval = reset_colindex (lp);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = ILLsymboltab_getindex (&qslp->coltab, name, colindex);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_rowindex (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	const char *name,
+	int *rowindex)
+{
+	int rval = 0;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp;
+
+	*rowindex = -1;
+
+	if (!lp)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_rowindex called without an LP");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	qslp = lp->O;
+
+	rval = reset_rowindex (lp);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = ILLsymboltab_getindex (&qslp->rowtab, name, rowindex);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_getbasis (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	char *cstat,
+	char *rstat)
+{
+	int rval = 0;
+	int i, j, nrows;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp;
+
+	if (!lp)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_getbasis called without an LP");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	if (lp->basisid == -1)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_getbasis called with modifed LP");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	nrows = lp->O->nrows;
+	qslp = lp->O;
+
+	for (i = 0; i < qslp->nstruct; i++)
+	{
+		j = qslp->structmap[i];
+		switch (lp->vstat[j])
+		{
+		case STAT_BASIC:
+			cstat[i] = QS_COL_BSTAT_BASIC;
+			break;
+		case STAT_LOWER:
+			cstat[i] = QS_COL_BSTAT_LOWER;
+			break;
+		case STAT_UPPER:
+			cstat[i] = QS_COL_BSTAT_UPPER;
+			break;
+		case STAT_ZERO:
+			cstat[i] = QS_COL_BSTAT_FREE;
+			break;
+		default:
+			QSlog("unknown vstat in EGLPNUM_TYPENAME_ILLlib_getbasis: %d", lp->vstat[j]);
+			rval = 1;
+			ILL_CLEANUP;
+		}
+	}
+
+	for (i = 0; i < nrows; i++)
+	{
+		j = qslp->rowmap[i];
+		if (qslp->rangeval && EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (qslp->rangeval[i]))
+		{
+			switch (lp->vstat[j])
+			{
+			case STAT_BASIC:
+				rstat[i] = QS_ROW_BSTAT_BASIC;
+				break;
+			case STAT_LOWER:
+				rstat[i] = QS_ROW_BSTAT_LOWER;
+				break;
+			case STAT_UPPER:
+				rstat[i] = QS_ROW_BSTAT_UPPER;
+				break;
+			default:
+				QSlog("unknown vstat in EGLPNUM_TYPENAME_ILLlib_getbasis 2");
+				rval = 1;
+				ILL_CLEANUP;
+			}
+		}
+		else
+		{
+			switch (lp->vstat[j])
+			{
+			case STAT_BASIC:
+				rstat[i] = QS_ROW_BSTAT_BASIC;
+				break;
+			case STAT_UPPER:
+			case STAT_LOWER:
+				rstat[i] = QS_ROW_BSTAT_LOWER;
+				break;
+			default:
+				QSlog("unknown vstat in EGLPNUM_TYPENAME_ILLlib_getbasis 3: %d, %d",
+										i, lp->vstat[j]);
+				rval = 1;
+				ILL_CLEANUP;
+			}
+		}
+	}
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_loadbasis (
+	EGLPNUM_TYPENAME_ILLlp_basis * B,
+	int nstruct,
+	int nrows,
+	char *cstat,
+	char *rstat)
+{
+	int i;
+	int rval = 0;
+
+	EGLPNUM_TYPENAME_ILLlp_basis_init (B);
+
+	if (!cstat || !rstat)
+	{
+		rval = 1;
+		CHECKRVALG (rval, CLEANUP);
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLlp_basis_alloc (B, nstruct, nrows);
+	CHECKRVALG (rval, CLEANUP);
+
+	for (i = 0; i < nstruct; i++)
+	{
+		B->cstat[i] = cstat[i];
+	}
+	for (i = 0; i < nrows; i++)
+	{
+		B->rstat[i] = rstat[i];
+	}
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+#define READ_BASIS_XL 0
+#define READ_BASIS_XU 1
+#define READ_BASIS_LL 2
+#define READ_BASIS_UL 3
+
+int EGLPNUM_TYPENAME_ILLlib_readbasis (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_ILLlp_basis * B,
+	const char *fname)
+{
+	int rval = 0;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp = lp->O;
+	int nstruct = qslp->nstruct;
+	int nrows = qslp->nrows;
+	int i, j, end = 0, sec, havename = 0;
+	int rowtype, row, col;
+	char *bname = 0;
+	EGioFile_t *file_in = 0;
+	EGLPNUM_TYPENAME_ILLread_mps_state state;
+	EGLPNUM_TYPENAME_qsline_reader *in = NULL;
+
+	EGLPNUM_TYPENAME_ILLlp_basis_init (B);
+
+	ILL_SAFE_MALLOC (B->cstat, qslp->nstruct, char);
+	ILL_SAFE_MALLOC (B->rstat, qslp->nrows, char);
+
+	B->nstruct = nstruct;
+	B->nrows = nrows;
+
+	for (j = 0; j < nstruct; j++)
+	{
+		B->cstat[j] = QS_COL_BSTAT_LOWER;
+	}
+	for (i = 0; i < nrows; i++)
+	{
+		B->rstat[i] = QS_ROW_BSTAT_BASIC;
+	}
+
+	file_in = EGioOpen (fname, "r");
+	if (file_in == 0)
+	{
+		QSlog("unable to open %s for reading", fname);
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	in = EGLPNUM_TYPENAME_ILLline_reader_new ((EGLPNUM_TYPENAME_qsread_line_fct) EGioGets, file_in);
+	rval = EGLPNUM_TYPENAME_ILLmps_state_init (&state, in, fname);
+	CHECKRVALG (rval, CLEANUP);
+
+	while (EGLPNUM_TYPENAME_ILLmps_next_line (&state) == 0)
+	{
+		if (EGLPNUM_TYPENAME_ILLmps_empty_key (&state))
+		{
+
+			/* Get the XL XU LL UL line */
+
+			if (!havename)
+			{
+				rval = EGLPNUM_TYPENAME_ILLmps_error (&state, "BASIS data before NAME\n");
+				ILL_CLEANUP;
+			}
+
+			if (!strcmp (state.field, "XL"))
+			{
+				rowtype = READ_BASIS_XL;
+			}
+			else if (!strcmp (state.field, "XU"))
+			{
+				rowtype = READ_BASIS_XU;
+			}
+			else if (!strcmp (state.field, "LL"))
+			{
+				rowtype = READ_BASIS_LL;
+			}
+			else if (!strcmp (state.field, "UL"))
+			{
+				rowtype = READ_BASIS_UL;
+			}
+			else
+			{
+				rval = EGLPNUM_TYPENAME_ILLmps_error (&state, "BASIS \"%s\" is invalid\n", state.field);
+				ILL_CLEANUP;
+			}
+
+			if (EGLPNUM_TYPENAME_ILLmps_next_field (&state) == 0)
+			{
+
+				rval = EGLPNUM_TYPENAME_ILLlib_colindex (lp, (const char *) state.field, &col);
+				CHECKRVALG (rval, CLEANUP);
+				if (col == -1)
+				{
+					rval = EGLPNUM_TYPENAME_ILLmps_error (&state, "BASIS col not in LP\n");
+					ILL_CLEANUP;
+				}
+
+				if (rowtype == READ_BASIS_XL || rowtype == READ_BASIS_XU)
+				{
+					if (EGLPNUM_TYPENAME_ILLmps_next_field (&state) == 0)
+					{
+						rval = EGLPNUM_TYPENAME_ILLlib_rowindex (lp, (const char *) state.field, &row);
+						CHECKRVALG (rval, CLEANUP);
+						if (row == -1)
+						{
+							rval = EGLPNUM_TYPENAME_ILLmps_error (&state, "BASIS row not in LP\n");
+							ILL_CLEANUP;
+						}
+						if (rowtype == READ_BASIS_XL)
+						{
+							B->cstat[col] = QS_COL_BSTAT_BASIC;
+							B->rstat[row] = QS_ROW_BSTAT_LOWER;
+
+						}
+						else
+						{
+							B->cstat[col] = QS_COL_BSTAT_BASIC;
+							B->rstat[row] = QS_ROW_BSTAT_UPPER;
+						}
+					}
+					else
+					{
+						rval = EGLPNUM_TYPENAME_ILLmps_error (&state, "BASIS line needs row and column\n");
+						ILL_CLEANUP;
+					}
+				}
+				else
+				{
+					if (rowtype == READ_BASIS_LL)
+					{
+						B->cstat[col] = QS_COL_BSTAT_LOWER;
+					}
+					else
+					{
+						B->cstat[col] = QS_COL_BSTAT_UPPER;
+					}
+				}
+			}
+			else
+			{
+				rval = EGLPNUM_TYPENAME_ILLmps_error (&state, "BASIS line has no row/column\n");
+				ILL_CLEANUP;
+			}
+		}
+		else
+		{
+			/* found a section indicator in col 1 */
+			if (!strcmp (state.key, EGLPNUM_TYPENAME_ILLmps_section_name[ILL_MPS_ENDATA]))
+			{
+				end = 1;
+				break;									/* done reading */
+			}
+
+			sec = ILLutil_index (EGLPNUM_TYPENAME_ILLmps_section_name, state.key);
+			if (sec < 0 || sec != ILL_MPS_NAME)
+			{
+				rval = EGLPNUM_TYPENAME_ILLmps_error (&state, "BASIS \"%s\" is not a key\n", state.key);
+				ILL_CLEANUP;
+			}
+
+			if (havename)
+			{
+				rval = EGLPNUM_TYPENAME_ILLmps_error (&state, "BASIS two name sections\n");
+				ILL_CLEANUP;
+			}
+
+			havename = 1;
+
+			if (EGLPNUM_TYPENAME_ILLmps_empty_field (&state))
+			{
+				EGLPNUM_TYPENAME_ILLmps_warn (&state, "BASIS blank NAME.");
+			}
+			else
+			{
+				ILL_UTIL_STR (bname, state.field);
+				QSlog("Basis Name: %s", bname);
+				if (strcmp (bname, qslp->probname))
+				{
+					EGLPNUM_TYPENAME_ILLmps_warn (&state, "BASIS name does not match LP.");
+				}
+			}
+		}
+	}
+
+	if (!end)
+	{
+		EGLPNUM_TYPENAME_ILLmps_warn (&state, "Missing ENDATA in basis file.");
+	}
+	if (!EGLPNUM_TYPENAME_ILLmps_next_line (&state))
+	{
+		EGLPNUM_TYPENAME_ILLmps_warn (&state, "Ignoring text after ENDATA.");
+	}
+
+	if (!havename)
+	{
+		rval = EGLPNUM_TYPENAME_ILLmps_error (&state, "BASIS no name section\n");
+		ILL_CLEANUP;
+	}
+
+	/* Correct the free variables */
+
+	for (j = 0; j < nstruct; j++)
+	{
+		col = lp->O->structmap[j];
+		if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (qslp->lower[col], EGLPNUM_TYPENAME_ILL_MINDOUBLE) &&
+				EGLPNUM_TYPENAME_EGlpNumIsEqqual (qslp->upper[col], EGLPNUM_TYPENAME_ILL_MAXDOUBLE) &&
+				B->cstat[j] == QS_COL_BSTAT_LOWER)
+		{
+			B->cstat[j] = QS_COL_BSTAT_FREE;
+		}
+	}
+
+CLEANUP:
+
+	if (file_in)
+		EGioClose (file_in);
+	EGLPNUM_TYPENAME_ILLline_reader_free (in);
+
+	if (rval)
+	{
+		EGLPNUM_TYPENAME_ILLlp_basis_free (B);
+	}
+	ILL_IFFREE (bname, char);
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_writebasis (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_ILLlp_basis * B,
+	const char *fname)
+{
+	int rval = 0;
+	EGioFile_t *out = 0;
+	char *cstat = 0;
+	char *rstat = 0;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp;
+	int i, j, nstruct, nrows;
+
+	/* NOTE: non-basic free variables are encoded as non-basic at lower */
+
+	if (!lp)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_writebasis called without an LP");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+	if (!B && lp->basisid == -1)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlib_writebasis called with unsolved LP");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	qslp = lp->O;
+	nstruct = qslp->nstruct;
+	nrows = qslp->nrows;
+
+	out = EGioOpen (fname, "w");
+	if (out == 0)
+	{
+		QSlog("unable to open %s for writing", fname);
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	if (B)
+	{
+		cstat = B->cstat;
+		rstat = B->rstat;
+	}
+	else
+	{
+		ILL_SAFE_MALLOC (cstat, nstruct, char);
+		ILL_SAFE_MALLOC (rstat, nrows, char);
+
+		rval = EGLPNUM_TYPENAME_ILLlib_getbasis (lp, cstat, rstat);
+		CHECKRVALG (rval, CLEANUP);
+	}
+
+	EGioPrintf (out, "NAME    %s\n", qslp->probname);
+
+	/* Pick out the non-basic rows and find a matching basic column */
+
+	i = 0;
+	j = 0;
+	do
+	{
+		while (i < nrows && rstat[i] == QS_ROW_BSTAT_BASIC)
+		{
+			i++;
+		}
+		if (i < nrows)
+		{
+			while (j < nstruct && cstat[j] != QS_COL_BSTAT_BASIC)
+			{
+				j++;
+			}
+			if (j == nstruct)
+			{
+				/* No basic column to match the non-basic row */
+				QSlog("No basic column to match non-basic row %d", i);
+				rval = 1;
+				goto CLEANUP;
+			}
+
+			if (rstat[i] == QS_ROW_BSTAT_LOWER)
+			{
+				EGioPrintf (out, " XL %s %s\n", qslp->colnames[j], qslp->rownames[i]);
+			}
+			else
+			{
+				EGioPrintf (out, " XU %s %s\n", qslp->colnames[j], qslp->rownames[i]);
+			}
+			i++;
+			j++;
+		}
+	} while (i < nrows);
+
+	/* Now go through and output the non-basic cols at upper bound */
+
+	for (j = 0; j < nstruct; j++)
+	{
+		if (cstat[j] == QS_COL_BSTAT_UPPER)
+		{
+			EGioPrintf (out, " UL %s\n", qslp->colnames[j]);
+		}
+	}
+
+	EGioPrintf (out, "ENDATA\n");
+
+CLEANUP:
+
+	if (out)
+		EGioClose (out);
+	if (!B)
+	{
+		ILL_IFFREE (cstat, char);
+		ILL_IFFREE (rstat, char);
+	}
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_getrownorms (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * pinf,
+	EGLPNUM_TYPE * rownorms)
+{
+	int rval = 0;
+	int i, j, basic = 0;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp = lp->O;
+	int nstruct = lp->O->nstruct;
+	int nrows = lp->O->nrows;
+
+	check_pinf (pinf, &rval);
+	if (rval)
+	{
+/*
+        QSlog("dual steepest edge norms not available");
+*/
+		ILL_CLEANUP;
+	}
+
+	for (i = 0; i < nstruct; i++)
+	{
+		j = qslp->structmap[i];
+		if (lp->vstat[j] == STAT_BASIC)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (rownorms[basic++], pinf->dsinfo.norms[lp->vindex[j]]);
+		}
+	}
+	for (i = 0; i < nrows; i++)
+	{
+		j = qslp->rowmap[i];
+		if (lp->vstat[j] == STAT_BASIC)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (rownorms[basic++], pinf->dsinfo.norms[lp->vindex[j]]);
+		}
+	}
+
+	if (basic != nrows)
+	{
+		QSlog("error in EGLPNUM_TYPENAME_ILLlib_getrownorms");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+CLEANUP:
+
+/*
+    EG_RETURN(rval);
+*/
+	return rval;									/* Don't want error message */
+}
+
+int EGLPNUM_TYPENAME_ILLlib_loadrownorms (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * pinf,
+	EGLPNUM_TYPE * rownorms)
+{
+	int rval = 0;
+
+	rval = EGLPNUM_TYPENAME_ILLprice_load_rownorms (lp, rownorms, pinf);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_recompute_rownorms (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * pinf)
+{
+	int rval = 0;
+
+	rval = EGLPNUM_TYPENAME_ILLprice_build_pricing_info (lp, pinf, DUAL_PHASEII);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_iter (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	int iter = 0;
+
+	if (lp && lp->cnts)
+	{
+		iter = lp->cnts->pI_iter + lp->cnts->pII_iter +
+			lp->cnts->dI_iter + lp->cnts->dII_iter;
+	}
+
+	return iter;
+}
+
+//#define PRINT_TOL 0.000001
+#define PRINT_TOL EGLPNUM_TYPENAME_PFEAS_TOLER
+
+int EGLPNUM_TYPENAME_ILLlib_print_x (
+	EGioFile_t * fd,
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_ILLlp_cache * C,
+	EGLPNUM_TYPE * x,
+	int nonZerosOnly)
+{
+	int rval = 0;
+	int j;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp = lp->O;
+	EGLPNUM_TYPE *dx, *myx = 0;
+	char *strtmp;
+
+	/* If x is not specified, grab the LP solution */
+
+	if (!x)
+	{
+		myx = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->ncols);
+		rval = EGLPNUM_TYPENAME_ILLlib_get_x (lp, C, myx);
+		CHECKRVALG (rval, CLEANUP);
+		dx = myx;
+	}
+	else
+	{
+		dx = x;
+	}
+
+	EGioPrintf (fd, "Solution Values\n");
+	for (j = 0; j < qslp->nstruct; j++)
+	{
+		/*if (!nonZerosOnly || dx[j] > PRINT_TOL || dx[j] < -PRINT_TOL) */
+		if (!nonZerosOnly || EGLPNUM_TYPENAME_EGlpNumIsNeqZero (dx[j], PRINT_TOL))
+		{
+			strtmp = EGLPNUM_TYPENAME_EGlpNumGetStr (dx[j]);
+			ILL_FAILfalse (qslp->colnames[j] != NULL, "no NULL names PLEASE!");
+			EGioPrintf (fd, "%s = %s\n", qslp->colnames[j], strtmp);
+			EGioFlush (fd);
+			EGfree (strtmp);
+		}
+	}
+
+CLEANUP:
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (myx);
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_findName (
+	EGLPNUM_TYPENAME_ILLlpdata * qslp,
+	int forRow,
+	const char *name,
+	int id,
+	char buf[ILL_namebufsize])
+{
+	ILLsymboltab *tab;
+	const char *mode;
+	const char *p1, *p2;
+	int sind, rval = 0;
+
+	id++;
+	tab = (forRow) ? &qslp->rowtab : &qslp->coltab;
+	if (tab->tablesize == 0)
+		ILLsymboltab_create (tab, 100);
+	p1 = (forRow) ? "c" : "x";
+	p2 = (forRow) ? "c_" : "x_";
+	mode = (forRow) ? "row" : "column";
+	if (name == 0)
+	{
+		ILLsymboltab_unique_name (tab, id, p1, buf);
+		/*
+		 * QSlog("Generating %s name \"%s\".", mode, buf);
+		 */
+	}
+	else
+	{
+		strcpy (buf, name);
+	}
+	if (!ILLsymboltab_lookup (tab, buf, &sind))
+	{
+		rval = ILLsymboltab_uname (&qslp->rowtab, buf, p1, p2);
+		if (name != NULL)
+		{
+			QSlog("Changing %s name \"%s\" to \"%s\".", mode, name, buf);
+		}
+		CHECKRVALG (rval, CLEANUP);
+	}
+CLEANUP:
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLwrite_lp_file (
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	EGioFile_t * out,
+	EGLPNUM_TYPENAME_qserror_collector * c)
+{
+	int rval = 0;
+	qsstring_reporter rep;
+
+	ILLstring_reporter_copy (&rep, &lp->reporter);
+	ILLstring_reporter_init (&lp->reporter, (qsreport_string_fct) EGioWrite, out);
+	rval = EGLPNUM_TYPENAME_ILLwrite_lp (lp, c);
+	ILLstring_reporter_copy (&lp->reporter, &rep);
+	return rval;
+}
+
+static void check_pinf (
+	EGLPNUM_TYPENAME_price_info * pinf,
+	int *it_exists)
+{
+	if (!pinf || pinf->dI_price != QS_PRICE_DSTEEP ||
+			pinf->dII_price != QS_PRICE_DSTEEP || pinf->dsinfo.norms == 0)
+	{
+		*it_exists = 1;
+	}
+	else
+	{
+		*it_exists = 0;
+	}
+}
+
+#if 0
+static int test_matrix (
+	EGLPNUM_TYPENAME_ILLmatrix * A)
+{
+	int rval = 0;
+	int i, j, k;
+	int ncols = A->matcols;
+	int nrows = A->matrows;
+	int matsize = A->matsize;
+	int *mbeg = A->matbeg;
+	int *mcnt = A->matcnt;
+	int *mind = A->matind;
+	int *tempi = 0;
+
+
+	if (matsize == 0)
+		ILL_CLEANUP;
+
+	ILL_SAFE_MALLOC (tempi, matsize, int);
+
+	for (i = 0; i < matsize; i++)
+		tempi[i] = 0;
+
+	for (i = 0; i < ncols; i++)
+	{
+		for (j = 0; j < mcnt[i]; j++)
+		{
+			k = mind[mbeg[i] + j];
+			if (k < 0 || k >= nrows)
+			{
+				QSlog("ERROR IN MATRIX: %d", k);
+				QSlog("ncols = %d, bad col = %d", ncols, i);
+				QSlog("bad cnt = %d, bad index = %d", mcnt[i], mbeg[i] + j);
+				QSlog("matcolsize = %d, matsize = %d", A->matcolsize, A->matsize);
+				rval = 1;
+				ILL_CLEANUP;
+			}
+			if (tempi[mbeg[i] + j] != 0)
+			{
+				QSlog("ERROR: over written matrix");
+				QSlog("ncols = %d, bad col = %d", ncols, i);
+				QSlog("nrows = %d", nrows);
+				QSlog("bad cnt = %d, bad index = %d", mcnt[i], mbeg[i] + j);
+				rval = 1;
+				ILL_CLEANUP;
+			}
+			else
+			{
+				tempi[mbeg[i] + j] = 1;
+			}
+		}
+	}
+
+	for (i = A->matsize - A->matfree; i < A->matsize; i++)
+	{
+		if (tempi[i] != 0)
+		{
+			QSlog("ERROR: free space is being used");
+			rval = 1;
+			ILL_CLEANUP;
+		}
+	}
+
+CLEANUP:
+
+	ILL_IFFREE (tempi, int);
+
+	EG_RETURN (rval);
+}
+#endif
diff --git a/qsopt_ex/lib.h b/qsopt_ex/lib.h
new file mode 100644
index 0000000..8ee8982
--- /dev/null
+++ b/qsopt_ex/lib.h
@@ -0,0 +1,150 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCSINFO $Id: lib_EGLPNUM_TYPENAME.h,v 1.4 2003/11/05 17:00:26 meven Exp $ */
+#ifndef EGLPNUM_TYPENAME_ILL_LIB_H
+#define EGLPNUM_TYPENAME_ILL_LIB_H
+
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+#include "lpdata_EGLPNUM_TYPENAME.h"
+#include "price_EGLPNUM_TYPENAME.h"
+#include "basicdefs.h"
+
+/****************************************************************************/
+/*                                                                          */
+/*                   Return Status for EGLPNUM_TYPENAME_ILLlib_optimize                      */
+/*                                                                          */
+/****************************************************************************/
+
+/****************************************************************************/
+/*                                                                          */
+/*                               lib.c                                      */
+/*                                                                          */
+/****************************************************************************/
+
+struct itcnt_t;
+
+int EGLPNUM_TYPENAME_ILLlib_optimize ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_basis * B, EGLPNUM_TYPENAME_price_info * pinf, int algo,
+			int *status, int simplex_display, struct itcnt_t*itcnt),
+		EGLPNUM_TYPENAME_ILLlib_cache_solution ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_cache * C), 
+		EGLPNUM_TYPENAME_ILLlib_solution ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_cache * C, EGLPNUM_TYPE * val, 
+			EGLPNUM_TYPE * x, EGLPNUM_TYPE * pi, EGLPNUM_TYPE * slack, EGLPNUM_TYPE * rc),
+		EGLPNUM_TYPENAME_ILLlib_get_x ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_cache * C, EGLPNUM_TYPE * x),
+		EGLPNUM_TYPENAME_ILLlib_get_slack ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_cache * C, EGLPNUM_TYPE * slack),
+		EGLPNUM_TYPENAME_ILLlib_objval ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_cache * C, EGLPNUM_TYPE * val),
+		EGLPNUM_TYPENAME_ILLlib_tableau ( EGLPNUM_TYPENAME_lpinfo * lp, int row, EGLPNUM_TYPE * binv, EGLPNUM_TYPE * tabrow),
+		EGLPNUM_TYPENAME_ILLlib_basis_order ( EGLPNUM_TYPENAME_lpinfo * lp, int *header),
+		EGLPNUM_TYPENAME_ILLlib_newrow ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_basis * B,const EGLPNUM_TYPE rhs, int sense,
+			const EGLPNUM_TYPE range, const char *name),
+		EGLPNUM_TYPENAME_ILLlib_newrows ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_basis * B, int num,const EGLPNUM_TYPE * rhs,
+			char *sense, const EGLPNUM_TYPE * range, const char **names),
+		EGLPNUM_TYPENAME_ILLlib_addrow ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_basis * B, int cnt, int *ind,
+			const EGLPNUM_TYPE * val, const EGLPNUM_TYPE rhs, int sense,const EGLPNUM_TYPE range,
+			const char *rowname),
+		EGLPNUM_TYPENAME_ILLlib_addrows ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_basis * B, int num, int *rmatcnt, 
+			int *rmatbeg, int *rmatind,const EGLPNUM_TYPE * rmatval,const EGLPNUM_TYPE * rhs, 
+			char *sense, const EGLPNUM_TYPE * range, const char **names, int *nofactor),
+		EGLPNUM_TYPENAME_ILLlib_delrows ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_basis * B, EGLPNUM_TYPENAME_ILLlp_cache * C, int num, 
+			int *dellist, int *basis_ok, int *cache_ok), 
+		EGLPNUM_TYPENAME_ILLlib_newcol ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_basis * B,const EGLPNUM_TYPE obj, 
+			const EGLPNUM_TYPE lower,const EGLPNUM_TYPE upper, const char *name, int factorok), 
+		EGLPNUM_TYPENAME_ILLlib_newcols ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_basis * B, int num, EGLPNUM_TYPE * obj,
+			EGLPNUM_TYPE * lower, EGLPNUM_TYPE * upper, const char **names, int factorok),
+		EGLPNUM_TYPENAME_ILLlib_addcol ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_basis * B, int cnt, int *ind,
+			EGLPNUM_TYPE * val,const EGLPNUM_TYPE obj,const EGLPNUM_TYPE lower,const EGLPNUM_TYPE upper, 
+			const char *name, int factorok),
+		EGLPNUM_TYPENAME_ILLlib_addcols ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_basis * B, int num, int *cmatcnt,
+			int *cmatbeg, int *cmatind, EGLPNUM_TYPE * cmatval, EGLPNUM_TYPE * obj,
+			EGLPNUM_TYPE * lower, EGLPNUM_TYPE * upper, const char **names, int factorok),
+		EGLPNUM_TYPENAME_ILLlib_delcols ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_basis * B, int num, int *dellist,
+			int *basis_ok),
+		EGLPNUM_TYPENAME_ILLlib_chgcoef ( EGLPNUM_TYPENAME_lpinfo * lp, int rowindex, int colindex, EGLPNUM_TYPE coef), 
+		EGLPNUM_TYPENAME_ILLlib_getcoef (EGLPNUM_TYPENAME_lpinfo *lp, int rowindex, int colindex, EGLPNUM_TYPE* coef),
+		EGLPNUM_TYPENAME_ILLlib_chgrange (EGLPNUM_TYPENAME_lpinfo *lp, int indx, EGLPNUM_TYPE coef),
+		EGLPNUM_TYPENAME_ILLlib_chgsense ( EGLPNUM_TYPENAME_lpinfo * lp, int num, int *rowlist, char *sense),
+    EGLPNUM_TYPENAME_ILLlib_getsenses (EGLPNUM_TYPENAME_lpinfo *lp, char *senses),
+		EGLPNUM_TYPENAME_ILLlib_getrows ( EGLPNUM_TYPENAME_lpinfo * lp, int num, int *rowlist, int **rowcnt,
+			int **rowbeg, int **rowind, EGLPNUM_TYPE ** rowval, EGLPNUM_TYPE ** rhs,
+			char **sense, EGLPNUM_TYPE ** range, char ***names),
+		EGLPNUM_TYPENAME_ILLlib_getcols ( EGLPNUM_TYPENAME_lpinfo * lp, int num, int *collist, int **colcnt,
+			int **colbeg, int **colind, EGLPNUM_TYPE ** colval, EGLPNUM_TYPE ** obj,
+			EGLPNUM_TYPE ** lower, EGLPNUM_TYPE ** upper, char ***names),
+		EGLPNUM_TYPENAME_ILLlib_getobj ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPE * obj),
+		EGLPNUM_TYPENAME_ILLlib_getobj_list (EGLPNUM_TYPENAME_lpinfo *lp, int num, int* collist, EGLPNUM_TYPE* obj),
+		EGLPNUM_TYPENAME_ILLlib_chgobj ( EGLPNUM_TYPENAME_lpinfo * lp, int indx, EGLPNUM_TYPE coef),
+		EGLPNUM_TYPENAME_ILLlib_getrhs ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPE * rhs),
+		EGLPNUM_TYPENAME_ILLlib_chgrhs ( EGLPNUM_TYPENAME_lpinfo * lp, int indx, EGLPNUM_TYPE coef),
+		EGLPNUM_TYPENAME_ILLlib_getintflags ( EGLPNUM_TYPENAME_lpinfo * lp, int *intflags),
+		EGLPNUM_TYPENAME_ILLlib_rownames ( EGLPNUM_TYPENAME_lpinfo * lp, char **rownames),
+		EGLPNUM_TYPENAME_ILLlib_colnames ( EGLPNUM_TYPENAME_lpinfo * lp, char **colnames),
+		EGLPNUM_TYPENAME_ILLlib_colindex ( EGLPNUM_TYPENAME_lpinfo * lp, const char *name, int *colindex),
+		EGLPNUM_TYPENAME_ILLlib_rowindex ( EGLPNUM_TYPENAME_lpinfo * lp, const char *name, int *rowindex),
+		EGLPNUM_TYPENAME_ILLlib_chgbnd ( EGLPNUM_TYPENAME_lpinfo * lp, int indx, int lu,const EGLPNUM_TYPE bnd),
+		EGLPNUM_TYPENAME_ILLlib_chgbnds ( EGLPNUM_TYPENAME_lpinfo * lp, int cnt, int *indx, char *lu, const EGLPNUM_TYPE * bnd),
+		EGLPNUM_TYPENAME_ILLlib_getbnd ( EGLPNUM_TYPENAME_lpinfo * lp, int indx, int lu, EGLPNUM_TYPE * bnd),
+		EGLPNUM_TYPENAME_ILLlib_getbnds ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPE * lower, EGLPNUM_TYPE * upper),
+		EGLPNUM_TYPENAME_ILLlib_getbnds_list ( EGLPNUM_TYPENAME_lpinfo *lp, int num, int*collist, EGLPNUM_TYPE *lower,
+			EGLPNUM_TYPE *upper),
+		EGLPNUM_TYPENAME_ILLlib_strongbranch ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_price_info * pinf, int *candidatelist,
+			int ncand, EGLPNUM_TYPE * xlist, EGLPNUM_TYPE * downpen, EGLPNUM_TYPE * uppen,
+			int iterations, EGLPNUM_TYPE objbound, struct itcnt_t*itcnt),
+		EGLPNUM_TYPENAME_ILLlib_getbasis ( EGLPNUM_TYPENAME_lpinfo * lp, char *cstat, char *rstat),
+		EGLPNUM_TYPENAME_ILLlib_loadbasis ( EGLPNUM_TYPENAME_ILLlp_basis * B, int nstruct, int nrows, char *cstat,
+			char *rstat),
+		EGLPNUM_TYPENAME_ILLlib_readbasis ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_basis * B, const char *fname),
+		EGLPNUM_TYPENAME_ILLlib_writebasis ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_basis * B, const char *fname),
+		EGLPNUM_TYPENAME_ILLlib_getrownorms ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_price_info * pinf, EGLPNUM_TYPE * rownorms),
+		EGLPNUM_TYPENAME_ILLlib_loadrownorms ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_price_info * pinf, EGLPNUM_TYPE * rownorms),
+		EGLPNUM_TYPENAME_ILLlib_recompute_rownorms ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_price_info * pinf),
+		EGLPNUM_TYPENAME_ILLlib_iter ( EGLPNUM_TYPENAME_lpinfo * lp),
+		EGLPNUM_TYPENAME_ILLlib_print_x ( EGioFile_t * fd, EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_cache * C, EGLPNUM_TYPE * x,
+			int nonZerosOnly),
+		EGLPNUM_TYPENAME_ILLwrite_lp_file ( EGLPNUM_TYPENAME_ILLlpdata * lp, EGioFile_t * eout, EGLPNUM_TYPENAME_qserror_collector * c);
+
+
+extern int EGLPNUM_TYPENAME_ILLlib_findName (
+	EGLPNUM_TYPENAME_ILLlpdata * qslp,
+	int forRow,
+	const char *name,
+	int id,
+	char buf[ILL_namebufsize]);
+
+/****************************************************************************/
+/*                                                                          */
+/*                           presolve.c                                     */
+/*                                                                          */
+/****************************************************************************/
+
+int EGLPNUM_TYPENAME_ILLpresolve_add_logicals (
+	EGLPNUM_TYPENAME_ILLlpdata * lp);
+
+
+/****************************************************************************/
+/*                                                                          */
+/*                            binary.c                                      */
+/*                                                                          */
+/****************************************************************************/
+
+int EGLPNUM_TYPENAME_ILLmip_binary_dfs (
+	EGLPNUM_TYPENAME_lpinfo * lp);
+
+#endif /* EGLPNUM_TYPENAME_ILL_LIB_H */
diff --git a/qsopt_ex/logging-private.h b/qsopt_ex/logging-private.h
new file mode 100644
index 0000000..9cf9c0e
--- /dev/null
+++ b/qsopt_ex/logging-private.h
@@ -0,0 +1,261 @@
+/* logging - Private functions for logging/error reporting
+ *
+ * Copyright (C) 2015  Jon Lund Steffensen <jonlst at gmail.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+ * */
+
+#ifndef QS_LOGGING_PRIVATE_H__
+#define QS_LOGGING_PRIVATE_H__
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+
+void QSlogv(const char *format, va_list args)
+	__attribute__ ((format(__printf__, 1, 0)));
+void QSlog(const char *format, ...)
+	__attribute__ ((format(__printf__, 1, 0)));
+
+
+/** @name Code Location Utility:
+ * this are utility macros to print information about where we are.
+ * @note For some reason __func__ don't work correctly for sun's cc in inline
+ * functions, so we don't use in SUN architecture */
+/*  @{  */
+#define __EG_PRINTLOCF__  QSlog(", in %s (%s:%d)",__func__,__FILE__,__LINE__)
+#define __EG_PRINTLOC__      __EG_PRINTLOCF__
+#define __EG_PRINTLOC2F__ QSlog("in %s (%s:%d)",__func__,__FILE__,__LINE__)
+#define __EG_PRINTLOC2__     __EG_PRINTLOC2F__
+/*  @}  */
+
+/** @brief if the given display level is over the given treshold, display the
+ * given message and location information */
+#define IFMESSAGE(__display,...) do{\
+	if((__display)>0){\
+		QSlog(__VA_ARGS__);										\
+		__EG_PRINTLOC__;}}while(0)
+
+/** @brief if return value is non-zero warn on screen */
+#define WARNIF(__L__) do{\
+	const int __Wval__= (__L__);\
+	if(__Wval__){QSlog("WARNING: In %s (%s:%d) "#__L__" = %d",__func__,__FILE__,__LINE__,__Wval__);}}while(0)
+#if DEBUG>=1
+
+/** @brief This macro is to print error messages and to return with value one
+ * from the current function, it also print the file and line where this
+ * happend, but the condition is looked only if the debug level is at least __L
+ * */
+#define EXITL(__L,__A,...) ({\
+	if(__L<=DEBUG){\
+	if(__A){\
+		QSlog(__VA_ARGS__);										\
+		__EG_PRINTLOC__;\
+		_exit(1);}}})
+
+/** @brief This macro is to print error messages and to return with value one
+ * from the current function, it also print the file and line where this
+ * happend, but the condition is looked only if the debug level is at least __L
+ * */
+#define TESTL(__L,__A,...) ({\
+	if(__L<=DEBUG){\
+	if(__A){\
+		QSlog(__VA_ARGS__);										\
+		__EG_PRINTLOC__;\
+		return 1;}}})
+
+/** @brief this macro check if the value of a pointer is not bellow the first
+ * 64Kb, if so it return the given value */
+#define PTRTEST(__PTR,__RVAL) {\
+	if(__PTR) ADVTESTL(0,((size_t)(__PTR)) < (1U<<16),__RVAL, \
+								 "%s=%p is not a valid pointer",\
+									#__PTR, (void*)(__PTR));}
+
+/** @brief This macro is to print error messages and jump to the given point
+ * in the code, it also print the file and line where this happend */
+#define TESTGL(__L,__A,__B,...) ({\
+	if((__L)<=DEBUG && (__A)){\
+		QSlog("ERROR: " __VA_ARGS__);					\
+		__EG_PRINTLOC__;\
+		goto __B;}})
+
+/** @brief return value macro, if the value is non-zero, write to standard
+ * error the returning code and where this happen */
+#define EG_RETURN(__A) {\
+	const int __RVAL__ = (__A);\
+	if(__RVAL__){\
+		QSlog("rval %d",__RVAL__);						\
+		__EG_PRINTLOC__;}\
+	return __RVAL__;}
+
+/** @brief This macro is to print error messages and jump to the given point
+ * in the code, it also print the file and line where this happend */
+#define TESTG(__A,__B,...) ({\
+	if(__A){\
+		QSlog("ERROR: " __VA_ARGS__);					\
+		__EG_PRINTLOC__;\
+		goto __B;}})
+
+/** @brief This macro is to print error messages and jump to the CLEANUP label
+ * in the current function, it also print the file and line where this happend */
+#define TESTGD(__A,...) ({\
+	if(__A){\
+		QSlog("ERROR: " __VA_ARGS__);					\
+		__EG_PRINTLOC__;\
+		goto CLEANUP;}})
+
+/** @brief This macro is to print error messages and to return with value one
+ * from the current function, it also print the file and line where this
+ * happend */
+#define TEST(__A,...) ({\
+	if(__A){\
+		QSlog(__VA_ARGS__);										\
+		__EG_PRINTLOC__;\
+		return 1;}})
+
+/** @brief This macro print messages to the screen when the debug level is as
+ * big as the first parameter, if the debug level is zero we eliminate the
+ * code and reduce it to the empty instruction. */
+#define MESSAGEF(__A,...) ({\
+	if(__A <= DEBUG ){\
+		QSlog(__VA_ARGS__);										\
+		__EG_PRINTLOCF__(__F);}})
+
+/** @brief This macro print messages to the screen when the debug level is as
+ * big as the first parameter, if the debug level is zero we eliminate the
+ * code and reduce it to the empty instruction. */
+#define MESSAGE(__A,...) ({\
+	if(__A <= DEBUG ){\
+		QSlog(__VA_ARGS__);										\
+		__EG_PRINTLOC__;}})
+
+/** @brief This macro print messages to the screen when the verbose level is as
+ * big as the first parameter, if the verbose level is zero we eliminate the
+ * code and reduce it to the empty instruction. */
+#if VERBOSE_LEVEL >= 1
+#define OUTPUT(__A,...) ({\
+	if(__A <= VERBOSE_LEVEL ){\
+		QSlog(__VA_ARGS__);}})
+#else
+#define OUTPUT(__A,...) ;
+#endif
+
+/** @brief This macro print messages to the screen when the condition __A is
+ * true .if the debug level is one we don't print any warning message. if
+ * the debug level is zero we eliminate the code and reduce it to the empty
+ * instruction. */
+#define WARNINGL(__L,__A,...) ({\
+	if((__A)&&(DEBUG>=__L)){\
+		QSlog("WARNING: " __VA_ARGS__);\
+		__EG_PRINTLOC__;}})
+
+#else
+#define TESTL(__L,__A,...) ;
+#define EXITL(__L,__A,...) ;
+#define TEST(__A,...) ;
+#define TESTG(__A,__B,...) ;
+#define TESTGL(__A,__B,...) ;
+#define MESSAGE(__A,...) ;
+#define MESSAGEF(__A,__F,...) ;
+#define WARNINGL(__L,__A,...) ;
+#define EG_RETURN(__A) do{return (__A);}while(0)
+#define PTRTEST(__PTR,__RVAL) ;
+#endif
+
+/** @brief This macro is to print error messages and to return with value one
+ * from the current function, it also print the file and line where this
+ * happend */
+#define FTEST(__A,...) ({\
+	if(__A){\
+		QSlog(__VA_ARGS__);										\
+		__EG_PRINTLOC__;\
+		return 1;}})
+
+/** @brief This macro is to print error messages and to return with value one
+ * from the current function, it also print the file and line where this
+ * happend */
+#define FTESTG(__A,__B,...) ({\
+	if(__A){\
+		QSlog("ERROR: " __VA_ARGS__);					\
+		__EG_PRINTLOC__;\
+		goto __B;}})
+
+/** @brief This macro print messages to the screen when the condition __A is
+ * true. */
+#define WARNING(__A,...) ({									\
+	if(__A){																	\
+		QSlog("WARNING: " __VA_ARGS__);		\
+		__EG_PRINTLOC__;}})
+
+/** @brief this macro test if a value is non zero, if it is it print where is
+ * it and exit EXIT_FAILURE. The idea is to use it to check return values of functions,
+ * and the calling function can't return a status, and then we are forced to
+ * exit. */
+#define EXITRVAL(__A) ({\
+	if(__A){\
+		__EG_PRINTLOC2__;\
+		exit(EXIT_FAILURE);}})
+
+/** @brief This macro is to print error messages and exit the program with
+ * code one from the current function, it also print the file and line where
+ * this happend */
+#define EXIT(__A,...) ({										\
+	if(__A){																	\
+		QSlog("EXIT: " __VA_ARGS__);			\
+		__EG_PRINTLOC__;\
+		exit(EXIT_FAILURE);}})
+
+/** @brief this macro test if a value is non zero, if it is it print where is
+ * it and return __B. The idea is to use it to check return values of functions
+ * */
+#define ADVCHECKRVAL(__A,__B) ({\
+	if(__A){\
+		__EG_PRINTLOC2__;\
+		return __B;}})
+
+/** @brief This macro test a condition '__A' when the debug level used at
+ * compile time is at least '__L'. If the condition is true, it print the
+ * message and return the '__RVAL' value. */
+#define ADVTESTL(__L,__A,__RVAL,...) ({\
+	if((DEBUG>=__L)&&(__A)){\
+		QSlog(__VA_ARGS__);										\
+		__EG_PRINTLOC__;\
+		return __RVAL;}})
+
+/** @brief this macro test if a value is non zero, if it is it print where is
+ * it and return 1. The idea is to use it to check return values of functions
+ * */
+#define CHECKRVAL(__A) ({\
+	if(__A){\
+		__EG_PRINTLOC2__;\
+		return __A;}})
+
+/** @brief, if a non-zero value is given as an argument, check the errno stored
+ * in the system, print the related message, and return the non-zero given
+ * parameter, otherwise, do nothing.
+ * @param __value if non-zero check systems errors, and return this value
+ * */
+#define TESTERRNOIF(__value) do{\
+	if(__value){\
+		const int __EGserrno = errno;\
+		QSlog("failed with errno %d, %s",__EGserrno, strerror(__EGserrno)); \
+		__EG_PRINTLOC2__;\
+		return __value;}}while(0)
+
+/** @brief this function, if the input is non zero, print a message of
+ * function, file and line and then goto the second parameter */
+#define CHECKRVALG(__A,__B) do{if(__A){__EG_PRINTLOC2__;goto __B;}}while(0)
+
+#endif /* ! QS_LOGGING_PRIVATE_H__ */
diff --git a/qsopt_ex/logging.c b/qsopt_ex/logging.c
new file mode 100644
index 0000000..9abe1a4
--- /dev/null
+++ b/qsopt_ex/logging.c
@@ -0,0 +1,82 @@
+/* logging - Functions for logging/error reporting
+ *
+ * Copyright (C) 2015  Jon Lund Steffensen <jonlst at gmail.com>
+ *
+ * This program 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.
+ *
+ * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+ * */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "logging.h"
+#include "logging-private.h"
+
+
+static QSlog_func global_log_func = NULL;
+static void *global_log_data = NULL;
+
+
+void QSlog_set_handler(QSlog_func log_func, void *data)
+{
+	global_log_func = log_func;
+	global_log_data = data;
+}
+
+void QSlogv(const char *format, va_list args)
+{
+	va_list args2;
+	va_copy(args2, args);
+
+	int n = vsnprintf(NULL, 0, format, args2);
+	if (n < 0) {
+		perror("vsnprintf");
+		abort();
+	}
+
+	va_end(args2);
+
+	char *buffer = malloc(n+1);
+	if (buffer == NULL) {
+		perror("malloc");
+		abort();
+	}
+
+	n = vsnprintf(buffer, n+1, format, args);
+	if (n < 0) {
+		perror("vsnprintf");
+		free(buffer);
+		abort();
+	}
+
+	if (global_log_func != NULL) {
+		global_log_func(buffer, global_log_data);
+	} else {
+		fprintf(stderr, "%s\n", buffer);
+	}
+
+	free(buffer);
+}
+
+void QSlog(const char *format, ...)
+{
+	va_list args;
+	va_start(args, format);
+	QSlogv(format, args);
+	va_end(args);
+}
diff --git a/qsopt_ex/logging.h b/qsopt_ex/logging.h
new file mode 100644
index 0000000..bd79629
--- /dev/null
+++ b/qsopt_ex/logging.h
@@ -0,0 +1,26 @@
+/* logging - Functions for logging/error reporting
+ *
+ * Copyright (C) 2015  Jon Lund Steffensen <jonlst at gmail.com>
+ * 
+ * This program 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.
+ *
+ * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+ * */
+
+#ifndef QS_LOGGING_H__
+#define QS_LOGGING_H__
+
+typedef void (*QSlog_func)(const char *message, void *data);
+
+void QSlog_set_handler(QSlog_func log_func, void *data);
+
+#endif /* ! QS_LOGGING_H__ */
diff --git a/qsopt_ex/lp.c b/qsopt_ex/lp.c
new file mode 100644
index 0000000..73c6fc3
--- /dev/null
+++ b/qsopt_ex/lp.c
@@ -0,0 +1,1280 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: lp.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+
+/****************************************************************************/
+/*                                                                          */
+/*               Routines for Reading and Writing LP Files                  */
+/*                                                                          */
+/*  EXPORTED FUNCTIONS                                                      */
+/*                                                                          */
+/*        int EGLPNUM_TYPENAME_ILLwrite_lp (EGioFile_t *out, EGLPNUM_TYPENAME_ILLlpdata *lp)                  */
+/*        int EGLPNUM_TYPENAME_ILLread_lp (EGLPNUM_TYPENAME_qsline_reader f, const char *fname, EGLPNUM_TYPENAME_rawlpdata *lp)*/
+/*        int EGLPNUM_TYPENAME_ILLis_lp_name_char (char c, int pos)                          */
+/*        int EGLPNUM_TYPENAME_ILLread_constraint_expr(EGLPNUM_TYPENAME_ILLread_lp_state *state,              */
+/*          EGLPNUM_TYPENAME_rawlpdata *lp, int rowind, int allowNew)                        */
+/*        int EGLPNUM_TYPENAME_ILLread_constraint_name (EGLPNUM_TYPENAME_ILLread_lp_state *state,             */
+/*          char **rowname)                                                 */
+/*        int EGLPNUM_TYPENAME_ILLread_one_constraint (EGLPNUM_TYPENAME_ILLread_lp_state *state,              */
+/*          const char *rowname, EGLPNUM_TYPENAME_rawlpdata *lp, int allowNewCols)           */
+/*                                                                          */
+/****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "eg_lpnum.h"
+#include "eg_io.h"
+#include "except.h"
+#include "names.h"
+#include "util.h"
+
+/* from the cplex manual: 
+ 
+    not exceed 16 characters, all of which must be alphanumeric
+    (a-z, A-Z, 0-9) or one of these symbols: ! " # $ % & ( ) / ,
+    . ; ? @ _ ` ' { } | ~. Longer names will be truncated to 16
+    characters. A variable name can not begin with a number or a
+    period. 
+
+    The letter E or e, alone or followed by other valid symbols,
+    or followed by another E or e, should be avoided as this
+    notation is reserved for exponential entries. Thus, variables
+    can not be named e9, E-24, E8cats, or other names that could
+    be interpreted as an exponent. Even variable names such as
+    eels or example can cause a read error, depending on their
+    placement in an input line. 
+
+    Also, the following characters are not valid in variable
+    names (in order to allow for quadratic objective
+    information): ^, *, [ and ]. 
+*/
+/* OUR DEFINTION:
+ * -) variables consist of a-z A-Z 0-9 !"#$%(),;.?@_`'{}|~ 
+ *    don't start with a digit or '.'
+ * return  0 for variable 
+ * return -1 for keyword 
+ * return  1 otherwise 
+ */
+
+
+int EGLPNUM_TYPENAME_ILLis_lp_name_char (
+	int c,
+	int pos)
+{
+	return ((('a' <= c) && (c <= 'z')) ||
+					(('A' <= c) && (c <= 'Z')) ||
+					((pos > 0) && ('0' <= c) && (c <= '9')) ||
+					((pos > 0) && (c == '.')) ||
+					(strchr ("!\"#$%&()/,;?@_`'{}|~", c) != NULL));
+}
+
+
+/* 
+ * -) anything after '\' is comment 
+ * -) Problem is optional and comes first
+ * -) Minimize, Maximize, ... comes after Problem
+ * -) variables consist of a-z A-Z 0-9!"#$%(),;.?@_`'{}|~ 
+ */
+
+/*  NOTES                                                                   */
+/*   
+ *    don't start with a digit or '.'
+ */
+
+static const int LINE_LEN = 256;
+
+#include "lp_EGLPNUM_TYPENAME.h"
+#include "rawlp_EGLPNUM_TYPENAME.h"
+#include "read_lp_EGLPNUM_TYPENAME.h"
+#include "write_lp_EGLPNUM_TYPENAME.h"
+
+//extern EGLPNUM_TYPE EGLPNUM_TYPENAME_SZERO_TOLER;
+static int TRACE = 0;
+
+static int read_problem_name (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp);
+static int read_minmax (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp);
+static int read_objective (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp);
+static int read_objective (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp);
+static int read_constraints (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	int allowNewCols);
+static int read_colname (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	ILLsymboltab * coltab,
+	int mustHave);
+static int read_integer (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp);
+static int read_bounds (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp);
+static int add_var (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	EGLPNUM_TYPE coef,
+	int row,
+	int allowNew);
+
+/*------------------------------------------------------------------------ 
+ * EGLPNUM_TYPENAME_ILLwrite_lp and support routines
+ */
+static int fix_names (
+	EGLPNUM_TYPENAME_qserror_collector * collector,
+	char **names,
+	int nnames,
+	const char *extra,
+	int prefix,
+	char ***newnames);
+static void write_objective (
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	const char *objname,
+	char **colnames);
+static int write_row (
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	EGLPNUM_TYPENAME_ILLlp_rows * lprows,
+	int i,
+	char **rownames,
+	char **colnames,
+	int *colInRow,
+	EGLPNUM_TYPE * colCoef);
+static int write_bounds (
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	char **colnames);
+static void write_intvars (
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	char **colnames);
+
+int EGLPNUM_TYPENAME_ILLwrite_lp (
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	EGLPNUM_TYPENAME_qserror_collector * collector)
+{
+	int rval = 0;
+	int i;
+	EGLPNUM_TYPENAME_ILLlp_rows lp_rows, *lprows = NULL;
+	char **colnames = (char **) NULL;
+	char **rownames = (char **) NULL;
+	EGLPNUM_TYPE *colCoef = NULL;
+	int *colInRow = NULL;
+	const char *objname;
+
+	ILL_FAILfalse (lp, "called without data\n");
+	if (lp->nstruct == 0 || lp->nrows == 0)
+	{
+		EG_RETURN (rval);
+	}
+	ILL_FAILfalse (lp->colnames != NULL, "lp->colnames != NULL");
+	ILL_FAILfalse (lp->rownames != NULL, "lp->rownames != NULL");
+	ILL_FAILfalse (lp->nstruct == lp->coltab.tablesize,
+								 "lp coltab has nstruct entries");
+	if (lp->objname == (char *) NULL)
+	{
+		ILL_FAILfalse (lp->nrows == lp->rowtab.tablesize,
+									 "lp rowtab should have nrows entries");
+	}
+	else
+	{
+		ILL_FAILfalse (lp->nrows + 1 == lp->rowtab.tablesize,
+									 "lp rowtab should have nrows+1 entries");
+		ILL_FAILfalse (ILLsymboltab_contains (&lp->rowtab, lp->objname),
+									 "rowtab must contain objname");
+	}
+
+	rval = fix_names (collector, lp->colnames, lp->nstruct, NULL, 'x', &colnames);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = fix_names (collector, lp->rownames, lp->nrows,
+										(lp->objname) ? lp->objname : "obj", 'c', &rownames);
+	CHECKRVALG (rval, CLEANUP);
+	objname = rownames[lp->nrows];
+
+	ILL_FAILtrue (objname == NULL, "OOps, that should never happen");
+	CHECKRVALG (rval, CLEANUP);
+
+	if (lp->sos.matcols > 0)
+	{
+		rval +=
+			EGLPNUM_TYPENAME_ILLdata_error (collector, "Can't express SOS information in LP format.");
+	}
+
+	write_objective (lp, objname, colnames);
+
+	/* Note, EGLPNUM_TYPENAME_ILLlp_rows_init returns cols ordered by structmap, so we may use 
+	 * colnames[i] when pulling i from the matrix data.  */
+
+	lprows = &lp_rows;
+	if (EGLPNUM_TYPENAME_ILLlp_rows_init (lprows, lp, 0) != 0)
+	{
+		rval += 1;
+		ILL_FAILtrue (rval, "EGLPNUM_TYPENAME_ILLlp_rows_init failed\n");
+	}
+
+	colCoef = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nstruct);
+	ILL_SAFE_MALLOC (colInRow, lp->nstruct, int);
+
+	for (i = 0; i < lp->nstruct; i++)
+	{
+		colInRow[i] = -1;
+	}
+
+	EGLPNUM_TYPENAME_ILLprint_report (lp, "Subject To\n");
+	for (i = 0; i < lp->nrows; i++)
+	{
+		if (lprows->rowcnt[i] == 0)
+		{
+			/*
+			 * EGLPNUM_TYPENAME_ILLdata_warn (collector, "Not printing  empty row \"%s\".", rownames[i]);
+			 */
+			continue;
+		}
+		rval += write_row (lp, lprows, i, rownames, colnames, colInRow, colCoef);
+	}
+
+	rval += write_bounds (lp, colnames);
+
+	if (lp->intmarker != NULL)
+	{
+		write_intvars (lp, colnames);
+	}
+
+	EGLPNUM_TYPENAME_ILLprint_report (lp, "End\n");
+CLEANUP:
+	if (lprows != NULL)
+	{
+		EGLPNUM_TYPENAME_ILLlp_rows_clear (lprows);
+	}
+	ILLfree_names (colnames, lp->nstruct);
+	ILLfree_names (rownames, lp->nrows + 1);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (colCoef);
+	ILL_IFFREE (colInRow, int);
+
+	EG_RETURN (rval);
+}
+
+static void write_objective (
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	const char *objname,
+	char **colnames)
+{
+	int ri, i, k, var;
+	EGLPNUM_TYPENAME_ILLwrite_lp_state ln, *line = &ln;
+
+	if (lp->probname != NULL)
+	{
+		EGLPNUM_TYPENAME_ILLprint_report (lp, "Problem\n %s\n", lp->probname);
+	}
+	if (lp->objsense == EGLPNUM_TYPENAME_ILL_MIN)
+	{
+		EGLPNUM_TYPENAME_ILLprint_report (lp, "Minimize\n");
+	}
+	else
+	{
+		EGLPNUM_TYPENAME_ILLprint_report (lp, "Maximize\n");
+	}
+	EGLPNUM_TYPENAME_ILLwrite_lp_state_init (line, NULL);
+	EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " ");
+	EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, objname);
+	EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, ": ");
+	EGLPNUM_TYPENAME_ILLwrite_lp_state_save_start (line);
+
+	for (ri = 0, var = 0; ri < lp->nstruct; ri++)
+	{
+		i = lp->structmap[ri];
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (lp->obj[i]))
+		{
+			EGLPNUM_TYPENAME_ILLwrite_lp_state_append_coef (line, lp->obj[i], var);
+			EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " ");
+			EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, colnames[ri]);
+			var++;
+
+			/* we put a least 4 terms on a line 
+			 * and then we stop after LINE_LEN or more characters 
+			 */
+			if ((line->total >= LINE_LEN) && (var >= 4))
+			{
+				/* see whether there is another term 
+				 * if so append a '+' and print line */
+				k = ri + 1;
+				while (k < lp->nstruct)
+				{
+					if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (lp->obj[lp->structmap[k]]))
+					{
+						break;
+					}
+					else
+					{
+						if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (lp->obj[lp->structmap[k]]))
+						{
+							EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " +");
+							break;
+						}
+					}
+					k++;
+				}
+				var = 0;								/* next line does not need to prefix coef with '+' */
+				EGLPNUM_TYPENAME_ILLprint_report (lp, "%s\n", line->buf);
+				EGLPNUM_TYPENAME_ILLwrite_lp_state_start (line);
+			}
+		}
+	}
+	if (var > 0)
+	{
+		EGLPNUM_TYPENAME_ILLprint_report (lp, "%s\n", line->buf);
+	}
+}
+
+static void write_the_expr (
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	EGLPNUM_TYPENAME_ILLwrite_lp_state * line,
+	char *rowname,
+	EGLPNUM_TYPENAME_ILLlp_rows * lprows,
+	int row,
+	char **colnames,
+	int *colInRow,
+	EGLPNUM_TYPE * colCoef,
+	int ncols)
+{
+	int var, firstVar, k, i;
+	EGLPNUM_TYPE *coef;
+
+	EGLPNUM_TYPENAME_ILLwrite_lp_state_init (line, NULL);
+	if (rowname != NULL)
+	{
+		EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " ");
+		EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, rowname);
+		EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, ": ");
+	}
+	else
+	{
+		EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, "   ");
+	}
+	EGLPNUM_TYPENAME_ILLwrite_lp_state_save_start (line);
+
+	for (k = lprows->rowbeg[row];
+			 k < lprows->rowbeg[row] + lprows->rowcnt[row]; k++)
+	{
+		i = lprows->rowind[k];
+		colInRow[i] = row;
+		EGLPNUM_TYPENAME_EGlpNumCopy (colCoef[i], lprows->rowval[k]);
+	}
+	var = 0;
+	firstVar = 1;
+	for (i = 0; i < ncols; i++)
+	{
+		if (colInRow[i] == row)
+		{
+			if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (colCoef[i]))
+			{
+				coef = &(colCoef[i]);
+				if (line->total >= LINE_LEN)
+				{
+					EGLPNUM_TYPENAME_ILLprint_report (lp, "%s\n", line->buf);
+					EGLPNUM_TYPENAME_ILLwrite_lp_state_start (line);
+					if ((!firstVar) && !EGLPNUM_TYPENAME_EGlpNumIsLessZero (*coef))
+					{
+						EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " +");
+					}
+					var = 0;
+				}
+
+				EGLPNUM_TYPENAME_ILLwrite_lp_state_append_coef (line, *coef, var);
+				EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " ");
+				EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, colnames[i]);
+				var++;
+				firstVar = 0;
+			}
+		}
+	}
+}
+
+static int write_row (
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	EGLPNUM_TYPENAME_ILLlp_rows * lprows,
+	int i,
+	char **rownames,
+	char **colnames,
+	int *colInRow,
+	EGLPNUM_TYPE * colCoef)
+{
+	EGLPNUM_TYPENAME_ILLwrite_lp_state ln, *line = &ln;
+	int rval = 0;
+	EGLPNUM_TYPE ntmp;
+
+	write_the_expr (lp, line, rownames[i], lprows, i, colnames,
+									colInRow, colCoef, lp->nstruct);
+
+	switch (lp->sense[i])
+	{
+	case 'G':
+		EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " >= ");
+		EGLPNUM_TYPENAME_ILLwrite_lp_state_append_number (line, lp->rhs[i]);
+		break;
+	case 'L':
+		EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " <= ");
+		EGLPNUM_TYPENAME_ILLwrite_lp_state_append_number (line, lp->rhs[i]);
+		break;
+	case 'E':
+		EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " = ");
+		EGLPNUM_TYPENAME_ILLwrite_lp_state_append_number (line, lp->rhs[i]);
+		break;
+	case 'R':
+		ILL_FAILtrue (!lp->rangeval, "RANGE constraints without values\n");
+		EGLPNUM_TYPENAME_EGlpNumInitVar (ntmp);
+		EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " >= ");
+		EGLPNUM_TYPENAME_ILLwrite_lp_state_append_number (line, lp->rhs[i]);
+
+		EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " \t\\ RANGE (");
+		EGLPNUM_TYPENAME_ILLwrite_lp_state_append_number (line, lp->rhs[i]);
+		EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, ", ");
+		EGLPNUM_TYPENAME_EGlpNumCopySum (ntmp, lp->rhs[i], lp->rangeval[i]);
+		EGLPNUM_TYPENAME_ILLwrite_lp_state_append_number (line, ntmp);
+		EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, ")");
+		EGLPNUM_TYPENAME_ILLprint_report (lp, "%s\n", line->buf);
+
+		write_the_expr (lp, line, NULL, lprows, i,
+										colnames, colInRow, colCoef, lp->nstruct);
+		EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " <= ");
+		EGLPNUM_TYPENAME_ILLwrite_lp_state_append_number (line, ntmp);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+		break;
+	default:
+		ILL_FAILtrue (1, "Unknown row sense\n");
+	}
+
+	EGLPNUM_TYPENAME_ILLprint_report (lp, "%s\n", line->buf);
+CLEANUP:
+	EG_RETURN (rval);
+}
+
+static int write_bounds (
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	char **colnames)
+{
+	int ri, i, rval = 0;
+	int prtLower, prtUpper;
+	EGLPNUM_TYPENAME_ILLwrite_lp_state l, *line = &l;
+
+	ILL_FAILtrue (lp->lower == NULL || lp->upper == NULL,
+								"Should not call write_bounds when lower or upper are NULL");
+	ri = EGLPNUM_TYPENAME_ILLraw_first_nondefault_bound (lp);
+	if (ri != lp->nstruct)
+	{
+		EGLPNUM_TYPENAME_ILLprint_report (lp, "Bounds\n");
+		EGLPNUM_TYPENAME_ILLwrite_lp_state_init (line, " ");
+		EGLPNUM_TYPENAME_ILLwrite_lp_state_save_start (line);
+
+		for (; ri < lp->nstruct; ri++)
+		{
+			EGLPNUM_TYPENAME_ILLwrite_lp_state_start (line);
+			i = lp->structmap[ri];
+			if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (lp->lower[i], lp->upper[i]))
+			{
+				EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " ");
+				EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, colnames[ri]);
+				EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " = ");
+				EGLPNUM_TYPENAME_ILLwrite_lp_state_append_number (line, lp->upper[i]);
+				EGLPNUM_TYPENAME_ILLprint_report (lp, "%s\n", line->buf);
+				continue;
+			}
+			if ((EGLPNUM_TYPENAME_EGlpNumIsEqqual (lp->lower[i], EGLPNUM_TYPENAME_ILL_MINDOUBLE)) &&
+					(EGLPNUM_TYPENAME_EGlpNumIsEqqual (lp->upper[i], EGLPNUM_TYPENAME_ILL_MAXDOUBLE)))
+			{
+				EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, colnames[ri]);
+				EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " free");
+				EGLPNUM_TYPENAME_ILLprint_report (lp, "%s\n", line->buf);
+				continue;
+			}
+			prtLower = !EGLPNUM_TYPENAME_ILLraw_default_lower (lp, i);
+			prtUpper = !EGLPNUM_TYPENAME_ILLraw_default_upper (lp, i, ri);
+			if (prtLower || prtUpper)
+			{
+				if (prtLower)
+				{
+					EGLPNUM_TYPENAME_ILLwrite_lp_state_append_number (line, lp->lower[i]);
+					EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " <= ");
+				}
+				if (prtLower || prtUpper)
+				{
+					EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, colnames[ri]);
+				}
+				if (prtUpper)
+				{
+					EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " <= ");
+					EGLPNUM_TYPENAME_ILLwrite_lp_state_append_number (line, lp->upper[i]);
+				}
+				EGLPNUM_TYPENAME_ILLprint_report (lp, "%s\n", line->buf);
+			}
+		}
+	}
+CLEANUP:
+	EG_RETURN (rval);
+}
+
+static void write_intvars (
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	char **colnames)
+{
+	EGLPNUM_TYPENAME_ILLwrite_lp_state ln, *line = &ln;
+	int var, j;
+
+	EGLPNUM_TYPENAME_ILLprint_report (lp, "Integer\n");
+	EGLPNUM_TYPENAME_ILLwrite_lp_state_init (line, " ");
+	EGLPNUM_TYPENAME_ILLwrite_lp_state_save_start (line);
+
+	for (j = 0, var = 0; j < lp->nstruct; j++)
+	{
+		if (lp->intmarker[j])
+		{
+			if (var > 0)
+			{
+				EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " ");
+			}
+			EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, colnames[j]);
+			var++;
+			if (line->total >= LINE_LEN)
+			{
+				EGLPNUM_TYPENAME_ILLprint_report (lp, "%s\n", line->buf);
+				EGLPNUM_TYPENAME_ILLwrite_lp_state_init (line, " ");
+				var = 0;
+			}
+		}
+	}
+	if (var > 0)
+	{
+		EGLPNUM_TYPENAME_ILLprint_report (lp, "%s\n", line->buf);
+	}
+}
+
+/* ------------------------------------------------------------ */
+/* fix up names that are numbers, i.e. prefix with x X x_ or X_ */
+
+/* 
+ * redefine names that start with [0-9]; i.e. give a prefix of 
+ *         "x" | "X" | "x_" | "X_"  
+ *         or if all these are already taken prefix with "X"<number>
+ *         make sure names contain solely the characters: 
+ *            [a-zA-Z0-9] and ! " # $ % & ( ) / , . ; ? @ _ ` ' { } | ~
+ *         rename names with 'bad' chars to <x X x_ X_><number>
+ */
+static int fix_names (
+	EGLPNUM_TYPENAME_qserror_collector * collector,
+	char **names,
+	int nnames,
+	const char *extra,
+	int pref,
+	char ***newnames)
+{
+	ILLsymboltab symt, *symtab = NULL;
+	int rval = 0, i, j, n, ind, hit;
+	char **n_names = NULL;
+	const char *old_name;
+	char buf[ILL_namebufsize];
+	char p1[2], p2[3];
+
+	p1[0] = pref;
+	p1[1] = '\0';
+	p2[0] = pref;
+	p2[1] = '_';
+	p2[2] = '\0';
+
+	ILL_SAFE_MALLOC (n_names, nnames + 1, char *);
+
+	for (i = 0; i < nnames; i++)
+	{
+		n_names[i] = (char *) NULL;
+	}
+
+	for (i = 0; i <= nnames; i++)
+	{
+		if (i == nnames)
+		{
+			if (extra == NULL)
+				break;
+			old_name = extra;
+		}
+		else
+			old_name = names[i];
+
+		n = strlen (old_name);
+		strcpy (buf, old_name);
+		if (!EGLPNUM_TYPENAME_ILLis_lp_name_char (buf[0], 1))
+		{
+			sprintf (buf, "%d", i);
+		}
+		else
+		{
+			for (j = 1; j < n; j++)
+			{
+				if (!EGLPNUM_TYPENAME_ILLis_lp_name_char (buf[j], j))
+				{
+					sprintf (buf, "%d", i);
+					break;
+				}
+			}
+		}
+
+		if (!EGLPNUM_TYPENAME_ILLis_lp_name_char (buf[0], 0))
+		{
+			if (symtab == NULL)
+			{
+				symtab = &symt;
+				ILLsymboltab_init (symtab);
+				ILLsymboltab_create (symtab, nnames + 1);
+				for (j = 0; j < nnames; j++)
+				{
+					ILLsymboltab_register (symtab, names[j], -1, &ind, &hit);
+					ILL_FAILfalse (ind == j, "ind == j");
+				}
+				if (extra != NULL)
+					ILLsymboltab_register (symtab, extra, -1, &ind, &hit);
+			}
+			rval = ILLsymboltab_uname (symtab, buf, p1, p2);
+			CHECKRVALG (rval, CLEANUP);
+			rval = ILLsymboltab_rename (symtab, i, buf);
+			CHECKRVALG (rval, CLEANUP);
+
+			ILL_UTIL_STR (n_names[i], buf);
+			EGLPNUM_TYPENAME_ILLdata_warn (collector,
+										"\"%s\" is not a valid name in LP format; %s\"%s\".",
+										old_name, "renaiming to ", buf);
+		}
+		else
+		{
+			ILL_UTIL_STR (n_names[i], old_name);
+		}
+	}
+
+CLEANUP:
+	if (symtab != NULL)
+	{
+		ILLsymboltab_free (symtab);
+	}
+	*newnames = n_names;
+	EG_RETURN (rval);
+}
+
+/* 
+ * end ILLlpdata_lpwrite 
+ * ---------------------------------------------------------------------- */
+
+int EGLPNUM_TYPENAME_ILLread_lp (
+	EGLPNUM_TYPENAME_qsline_reader * file,
+	const char *fname,
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+/* file format: 
+ *     optional problem name (this is in addition to the bix format) 
+ *     min or max 
+ *     objective fct 
+ *     constraints (mandatory !) 
+ *     optional bounds 
+ *     optional integer (also new) 
+ *
+ * as opposed to the official bix-format: 
+ *     no blanks in variable names 
+ *     there may be several bound defs on the same line; 
+ *     bound definitions may cross line boundaries
+ *     constraints that have no name get generated names:
+ *             if constraint i has not name we take the first name from the 
+ *             following list that is not in use:
+ *                  c<i>,  C<i>, or c<i>_0, c<i>_1, c<i>_2, ...
+ */
+	int rval = 0;
+	EGLPNUM_TYPENAME_ILLread_lp_state lpstate, *state = &lpstate;
+
+	const char *bnds[3], *integer[3], *end[2];
+
+	bnds[0] = "BOUNDS";
+	bnds[1] = "BOUND";
+	bnds[2] = NULL;
+	integer[0] = "INTEGER";
+	integer[1] = "INT";
+	integer[2] = NULL;
+	end[0] = "END";
+	end[1] = NULL;
+
+	rval = EGLPNUM_TYPENAME_ILLread_lp_state_init (state, file, fname, 0);
+	CHECKRVALG (rval, CLEANUP);
+
+	EGLPNUM_TYPENAME_ILLinit_rawlpdata (lp, file->error_collector);
+	rval = ILLsymboltab_create (&lp->rowtab, 100) ||
+		ILLsymboltab_create (&lp->coltab, 100);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (EGLPNUM_TYPENAME_ILLread_lp_state_next_field (state))
+	{
+		rval = EGLPNUM_TYPENAME_ILLlp_error (state, "Empty file.\n");
+	}
+	if (rval == 0)
+		rval = read_problem_name (state, lp);
+	if (rval == 0)
+		rval = read_minmax (state, lp);
+	if (rval == 0)
+		rval = read_objective (state, lp);
+	if (rval == 0)
+		rval = read_constraints (state, lp, 1);
+	if ((rval == 0) && (lp->ncols == 0 || lp->nrows == 0))
+	{
+		rval = EGLPNUM_TYPENAME_ILLlp_error (state,
+												"Problem must contain at least one %s.\n",
+												"non empty constraint");
+	}
+	CHECKRVALG (rval, CLEANUP);
+
+	if (EGLPNUM_TYPENAME_ILLread_lp_state_keyword (state, bnds) == 0)
+	{
+		rval = read_bounds (state, lp);
+	}
+	CHECKRVALG (rval, CLEANUP);
+
+	if (EGLPNUM_TYPENAME_ILLread_lp_state_keyword (state, integer) == 0)
+	{
+		rval = read_integer (state, lp);
+	}
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_ILLread_lp_state_keyword (state, end);
+	if (rval != 0)
+	{
+		if (state->eof)
+		{
+			rval = EGLPNUM_TYPENAME_ILLlp_error (state, "Missing \"End\" at end of file.\n");
+		}
+		else
+		{
+			rval = EGLPNUM_TYPENAME_ILLlp_error (state, "\"%s\" unknown keyword\n", state->field);
+		}
+	}
+	if (rval == 0)
+	{
+		rval = EGLPNUM_TYPENAME_ILLraw_fill_in_rownames (lp) || EGLPNUM_TYPENAME_ILLraw_fill_in_bounds (lp);
+	}
+
+CLEANUP:
+	EGLPNUM_TYPENAME_EGlpNumClearVar (lpstate.bound_val);
+	EG_RETURN (rval);
+}
+
+static int read_problem_name (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	int rval = 0;
+
+	if (!state->fieldOnFirstCol)
+	{
+		rval = EGLPNUM_TYPENAME_ILLlp_error (state,
+												"Keyword \"%s\" not at beginning of line.\n",
+												state->field);
+	}
+	if (!ILLutil_strcasecmp (state->field, "PROBLEM") ||
+			!ILLutil_strcasecmp (state->field, "PROB"))
+	{
+		if (EGLPNUM_TYPENAME_ILLread_lp_state_next_field (state) != 0)
+		{
+			rval = EGLPNUM_TYPENAME_ILLlp_error (state, "No Problem name field.\n");
+		}
+		else
+		{
+			ILL_IFFREE (lp->name, char);
+
+			ILL_UTIL_STR (lp->name, state->field);
+			ILL_IFTRACE ("ProblemName: %s\n", state->field);
+			(void) EGLPNUM_TYPENAME_ILLread_lp_state_next_field (state);
+		}
+	}
+CLEANUP:
+	EG_RETURN (rval);
+}
+
+static int read_minmax (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	int rval = 0;
+
+	if (!state->fieldOnFirstCol)
+	{
+		rval = EGLPNUM_TYPENAME_ILLlp_error (state,
+												"Keyword \"%s\" not at beginning of line.\n",
+												state->field);
+	}
+	if (!ILLutil_strcasecmp (state->field, "MAX") ||
+			!ILLutil_strcasecmp (state->field, "MAXIMUM") ||
+			!ILLutil_strcasecmp (state->field, "MAXIMIZE"))
+	{
+		lp->objsense = EGLPNUM_TYPENAME_ILL_MAX;
+	}
+	else
+	{
+		if (!ILLutil_strcasecmp (state->field, "MIN") ||
+				!ILLutil_strcasecmp (state->field, "MINIMUM") ||
+				!ILLutil_strcasecmp (state->field, "MINIMIZE"))
+		{
+			lp->objsense = EGLPNUM_TYPENAME_ILL_MIN;
+		}
+		else
+		{
+			EGLPNUM_TYPENAME_ILLread_lp_state_prev_field (state);
+			rval = EGLPNUM_TYPENAME_ILLlp_error (state, "Expecting \"%s\" or \"%s\" keyword.\n",
+													"Minimize", "Maximize");
+		}
+	}
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLread_constraint_expr (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	int rowind,
+	int allowNew)
+{
+	int rval = 0;
+	char firstTerm, haveCoef;
+	const char *name;
+	EGLPNUM_TYPE sign, coef;
+	EGLPNUM_TYPE ntmp;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (ntmp);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (sign);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (coef);
+
+	firstTerm = 1;
+	while (1)
+	{
+		if (EGLPNUM_TYPENAME_ILLread_lp_state_sign (state, &sign) != 0)
+		{
+			if (!firstTerm)
+			{
+				break;									/* we've ssen at least one term, 
+																 * this is the constraint's end */
+			}
+		}
+		haveCoef = EGLPNUM_TYPENAME_ILLread_lp_state_possible_coef (state, &coef, EGLPNUM_TYPENAME_oneLpNum);
+		if (EGLPNUM_TYPENAME_ILLread_lp_state_next_var (state) == 0)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (ntmp, coef);
+			EGLPNUM_TYPENAME_EGlpNumMultTo (ntmp, sign);
+			rval = add_var (lp, state, ntmp, rowind, allowNew);
+			CHECKRVALG (rval, CLEANUP);
+		}
+		else
+		{
+			if (haveCoef == 0)
+			{
+				return EGLPNUM_TYPENAME_ILLlp_error (state, "Coefficient without variable.\n");
+			}
+			else
+			{
+				break;
+			}
+		}
+		firstTerm = 0;
+	}
+CLEANUP:
+	if ((rval == 0) && firstTerm)
+	{
+		name = EGLPNUM_TYPENAME_ILLraw_rowname (lp, rowind);
+		if (name != NULL)
+		{
+			EGLPNUM_TYPENAME_ILLlp_warn (state,
+									"No terms in constraint expression for \"%s\".\n", name);
+		}
+		else
+		{
+			EGLPNUM_TYPENAME_ILLlp_warn (state, "No terms in constraint expression.\n");
+		}
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (sign);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (coef);
+	EG_RETURN (rval);
+}
+
+static int read_objective (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	int rval = 0;
+	char objname[ILL_namebufsize];
+	char *name;
+
+	ILL_FAILfalse (lp->nrows == 0, "objective should be first row");
+	EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (state, 1);
+	if (EGLPNUM_TYPENAME_ILLread_lp_state_has_colon (state))
+	{
+		if (EGLPNUM_TYPENAME_ILLread_lp_state_next_var (state) != 0)
+		{
+			rval = EGLPNUM_TYPENAME_ILLlp_error (state, "Bad objective function name.\n");
+		}
+		name = state->field;
+		if (rval == 0)
+		{
+			if (EGLPNUM_TYPENAME_ILLread_lp_state_colon (state) != 0)
+			{
+				rval = EGLPNUM_TYPENAME_ILLlp_error (state, "':' must follow constraint row name.\n");
+			}
+		}
+	}
+	else
+	{
+		name = NULL;
+	}
+
+	if (rval == 0)
+	{
+		ILL_FAILfalse (lp->rowtab.tablesize == 0,
+									 "objective row is first in symbol tab");
+		if (name == NULL)
+		{
+			strcpy (objname, "obj");
+			EGLPNUM_TYPENAME_ILLlp_warn (state, "Empty obj name; using \"%s\".\n", objname);
+		}
+		else
+		{
+			strcpy (objname, name);
+		}
+		rval = EGLPNUM_TYPENAME_ILLraw_add_row (lp, objname, 'N', EGLPNUM_TYPENAME_zeroLpNum);
+		lp->objindex = lp->nrows - 1;
+		CHECKRVALG (rval, CLEANUP);
+		rval = EGLPNUM_TYPENAME_ILLread_constraint_expr (state, lp, lp->objindex, 1);
+	}
+CLEANUP:
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLread_constraint_name (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	char **rowname)
+{
+	int rval = 0;
+
+	*rowname = NULL;
+
+	/* if there is a ':' on the line: look for constraint row name */
+	if (EGLPNUM_TYPENAME_ILLread_lp_state_has_colon (state))
+	{
+		if (EGLPNUM_TYPENAME_ILLread_lp_state_next_var (state) != 0)
+		{
+			rval = EGLPNUM_TYPENAME_ILLlp_error (state, "Bad constraint row name.\n");
+		}
+		else
+		{
+			*rowname = state->field;
+			if (EGLPNUM_TYPENAME_ILLread_lp_state_colon (state) != 0)
+			{
+				rval = EGLPNUM_TYPENAME_ILLlp_error (state, "':' must follow constraint row name.\n");
+			}
+		}
+	}
+	return rval;
+}
+
+int EGLPNUM_TYPENAME_ILLread_one_constraint (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	const char *rowname,
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	int allowNewCols)
+{
+	int rval = 0;
+	int rowind;
+	char sense;
+	EGLPNUM_TYPE d;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (d);
+
+	if ((rowname != NULL) &&
+			(ILLsymboltab_lookup (&lp->rowtab, rowname, &rowind) == 0))
+	{
+		rval = EGLPNUM_TYPENAME_ILLlp_error (state, "Repeated row name \"%s\".\n", rowname);
+		CHECKRVALG (rval, CLEANUP);
+	}
+	rowind = lp->nrows;
+	rval = rval || EGLPNUM_TYPENAME_ILLraw_add_row (lp, rowname, 'N', EGLPNUM_TYPENAME_zeroLpNum);
+
+	rval = rval || EGLPNUM_TYPENAME_ILLread_constraint_expr (state, lp, rowind, allowNewCols);
+	rval = rval || EGLPNUM_TYPENAME_ILLread_lp_state_sense (state);
+	sense = state->sense_val;
+	if (rval == 0)
+	{
+		rval = EGLPNUM_TYPENAME_ILLread_lp_state_value (state, &d);
+		if (rval)
+		{
+			(void) EGLPNUM_TYPENAME_ILLlp_error (state, "No right hand side value in constraint.\n");
+		}
+	}
+	if (rval == 0)
+	{
+		lp->rowsense[rowind] = sense;
+		EGLPNUM_TYPENAME_EGlpNumCopy (lp->rhs[rowind], d);
+		ILL_IFTRACE ("SENSE \"%s\": %c %f\n",
+								 EGLPNUM_TYPENAME_ILLraw_rowname (lp, rowind), sense, EGLPNUM_TYPENAME_EGlpNumToLf (d));
+	}
+CLEANUP:
+	EGLPNUM_TYPENAME_EGlpNumClearVar (d);
+	EG_RETURN (rval);
+}
+
+static int read_constraints (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	int allowNewCols)
+{
+	int rval = 0;
+	char *rowname = NULL;
+
+	if (EGLPNUM_TYPENAME_ILLcheck_subject_to (state) != 0)
+	{
+		return EGLPNUM_TYPENAME_ILLlp_error (state, "Constraint section expected.\n");
+	}
+	while (rval == 0)
+	{
+		rval = EGLPNUM_TYPENAME_ILLread_constraint_name (state, &rowname);
+		if (rval == 0)
+		{
+			rval = EGLPNUM_TYPENAME_ILLread_one_constraint (state, rowname, lp, allowNewCols);
+		}
+		if (rval == 0)
+		{
+			if (EGLPNUM_TYPENAME_ILLread_lp_state_next_constraint (state) != 0)
+			{
+				break;
+			}
+		}
+	}
+	EGLPNUM_TYPENAME_ILLread_lp_state_next_field (state);
+	EG_RETURN (rval);
+}
+
+/* 
+ * return -2 iff next is not a variable and not a keyword
+ * return -1 iff next is a keyword and !mustHave 
+ * return 1  iff unknown column name or mustHave and keyword 
+ * return 0  for success
+ */
+static int read_colname (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	ILLsymboltab * coltab,
+	int mustHave)
+{
+	int rval = 0;
+	int colind = ILL_SYM_NOINDEX;
+
+	rval = EGLPNUM_TYPENAME_ILLread_lp_state_next_var (state);
+	if (mustHave && (rval != 0))
+	{
+		return EGLPNUM_TYPENAME_ILLlp_error (state, "Expecting a column name.\n");
+	}
+	if (rval != 0)
+	{
+		return (rval == -1) ? rval : -2;
+	}
+	if (ILLsymboltab_lookup (coltab, state->field, &colind))
+	{
+		EGLPNUM_TYPENAME_ILLread_lp_state_prev_field (state);
+		return EGLPNUM_TYPENAME_ILLlp_error (state, "\"%s\" is not a column name.\n", state->field);
+	}
+	state->column_index = colind;
+	return 0;
+}
+
+static int read_integer (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	int rval = 0;
+	ILLsymboltab *coltab = &lp->coltab;
+
+	ILL_FAILfalse (lp->intmarker, "Programming error");
+
+	while ((rval = read_colname (state, coltab, 0)) == 0)
+	{
+		ILL_FAILtrue (state->column_index == ILL_SYM_NOINDEX, "Programming error");
+		lp->intmarker[state->column_index] = 1;
+	}
+CLEANUP:
+	if (rval == -1)
+	{															/* last try for a colname gave us a keyword */
+		rval = 0;
+	}
+	else
+	{
+		rval = EGLPNUM_TYPENAME_ILLlp_error (state, "Expecting a column name.");
+	}
+	EGLPNUM_TYPENAME_ILLread_lp_state_next_field (state);
+	EG_RETURN (rval);
+}
+
+static int read_bounds (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	int rval = 0;
+	int colind, haveBound;
+	char sense;
+	const char *msg;
+	ILLsymboltab *coltab;
+
+	EGLPNUM_TYPENAME_ILLraw_init_bounds (lp);
+	coltab = &lp->coltab;
+
+	while (1)
+	{
+		colind = -1;
+		haveBound = 0;
+		if (EGLPNUM_TYPENAME_ILLread_lp_state_possible_bound_value (state))
+		{
+			/* this must be for a lower bound */
+			EGLPNUM_TYPENAME_ILLtest_lp_state_bound_sense (state);
+			if (state->sense_val != 'L')
+			{
+				rval = EGLPNUM_TYPENAME_ILLlp_error (state, "Expecting \"<=\".\n");
+				break;
+			}
+			rval = read_colname (state, coltab, 1);
+			if (rval != 0)
+			{
+				break;
+			}
+			colind = state->column_index;
+			/* add lower bound value */
+			msg = EGLPNUM_TYPENAME_ILLraw_set_lowerBound (lp, colind, state->bound_val);
+			EGLPNUM_TYPENAME_ILLlp_warn (state, msg);
+			haveBound = 1;
+		}
+		if (colind == -1)
+		{
+			rval = read_colname (state, coltab, 0);
+			colind = state->column_index;
+			if (rval != 0)
+			{
+				if (rval == -1)
+				{
+					rval = 0;							/* found a keyword and that's OK */
+				}
+				else if (rval == -2)
+				{
+					rval = EGLPNUM_TYPENAME_ILLlp_error (state, "Expecting a column name.\n");
+				}
+				break;
+			}
+		}
+		ILL_FAILtrue (colind == -1, "must have a valid colname");
+		EGLPNUM_TYPENAME_ILLtest_lp_state_bound_sense (state);
+		if (state->sense_val != ' ')
+		{
+			sense = state->sense_val;
+			if ((sense != 'L') && (sense != 'E'))
+			{
+				rval = EGLPNUM_TYPENAME_ILLlp_error (state, "Expecting \"<=\" or \"=\".\n");
+				break;
+			}
+			if (EGLPNUM_TYPENAME_ILLread_lp_state_possible_bound_value (state))
+			{
+				if (sense == 'E')
+				{
+					msg = EGLPNUM_TYPENAME_ILLraw_set_fixedBound (lp, colind, state->bound_val);
+				}
+				else
+				{
+					msg = EGLPNUM_TYPENAME_ILLraw_set_upperBound (lp, colind, state->bound_val);
+				}
+				EGLPNUM_TYPENAME_ILLlp_warn (state, msg);
+				haveBound = 1;
+			}
+			else
+			{
+				rval = EGLPNUM_TYPENAME_ILLlp_error (state, "Expecting bound value.\n");
+				break;
+			}
+		}
+		else
+		{
+			if (EGLPNUM_TYPENAME_ILLtest_lp_state_next_is (state, "FREE"))
+			{
+				msg = EGLPNUM_TYPENAME_ILLraw_set_unbound (lp, colind);
+				EGLPNUM_TYPENAME_ILLlp_warn (state, msg);
+				haveBound = 1;
+			}
+			else
+			{
+				if (!haveBound)
+				{
+					rval = EGLPNUM_TYPENAME_ILLlp_error (state, "Not a bound expression.\n");
+					break;
+				}
+			}
+		}
+		ILL_IFTRACE ("BOUNDS: %f <= %s <= %f\n", EGLPNUM_TYPENAME_EGlpNumToLf (lp->lower[colind]),
+								 EGLPNUM_TYPENAME_ILLraw_colname (lp, colind), EGLPNUM_TYPENAME_EGlpNumToLf (lp->upper[colind]));
+	}
+	EGLPNUM_TYPENAME_ILLread_lp_state_next_field (state);
+CLEANUP:
+	EG_RETURN (rval);
+}
+
+static int add_var (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	EGLPNUM_TYPE coef,
+	int row,
+	int allowNew)
+{
+	char *var = state->field;
+	int rval = 0;
+	int colind;
+
+	if (ILLsymboltab_lookup (&lp->coltab, var, &colind) != 0)
+	{
+		if (!allowNew)
+		{
+			rval = EGLPNUM_TYPENAME_ILLlp_error (state, "Unknown col name \"%s\".\n", var);
+		}
+		CHECKRVALG (rval, CLEANUP);
+		rval = EGLPNUM_TYPENAME_ILLraw_add_col (lp, var, 0 /* not an integer var */ );
+		colind = lp->ncols - 1;
+		CHECKRVALG (rval, CLEANUP);
+	}
+	ILL_IFTRACE ("add_var: \"%s\" coef=%f row=%s\n",
+							 var, EGLPNUM_TYPENAME_EGlpNumToLf (coef), EGLPNUM_TYPENAME_ILLraw_rowname (lp, row));
+	rval = EGLPNUM_TYPENAME_ILLraw_add_col_coef (lp, colind, row, coef);
+CLEANUP:
+	EG_RETURN (rval);
+}
diff --git a/qsopt_ex/lp.h b/qsopt_ex/lp.h
new file mode 100644
index 0000000..9e40b91
--- /dev/null
+++ b/qsopt_ex/lp.h
@@ -0,0 +1,74 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCSINFO $Id: lp_EGLPNUM_TYPENAME.h,v 1.2 2003/11/05 16:57:39 meven Exp $ */
+#ifndef EGLPNUM_TYPENAME_LP_H
+#define EGLPNUM_TYPENAME_LP_H
+
+#include "readline_EGLPNUM_TYPENAME.h"
+
+/****************************************************************************/
+/*                                                                          */
+/*               Routines to support Reading and Writing LP Files           */
+/*                                                                          */
+/****************************************************************************/
+/* 
+ * -) anything after '\' is comment 
+ * -) Problem is optional and comes first
+ * -) Minimize, Maximize, ... comes after Problem
+ * -) variables consist of a-z A-Z 0-9!"#$%(),;.?@_`'{}|~ 
+ *    don't start with a digit or '.'
+ */
+
+#include "lpdata_EGLPNUM_TYPENAME.h"
+#include "rawlp_EGLPNUM_TYPENAME.h"
+#include "read_lp_EGLPNUM_TYPENAME.h"
+#include "write_lp_EGLPNUM_TYPENAME.h"
+
+extern int EGLPNUM_TYPENAME_ILLread_lp (
+	EGLPNUM_TYPENAME_qsline_reader * file,
+	const char *fname,
+	EGLPNUM_TYPENAME_rawlpdata * lp);
+extern int EGLPNUM_TYPENAME_ILLwrite_lp (
+	EGLPNUM_TYPENAME_ILLlpdata * l,
+	EGLPNUM_TYPENAME_qserror_collector * collector);
+
+			/* write using current lp->reporter */
+extern int EGLPNUM_TYPENAME_ILLis_lp_name_char (
+	int c,
+	int pos);
+
+extern int EGLPNUM_TYPENAME_ILLread_constraint_name (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	char **rowname);
+extern int EGLPNUM_TYPENAME_ILLread_one_constraint (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	const char *rowname,
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	int allowNewColsAddRow);
+extern int EGLPNUM_TYPENAME_ILLread_constraint_expr (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	int rowind,
+	int allowNew);
+
+#endif
diff --git a/qsopt_ex/lpdata.c b/qsopt_ex/lpdata.c
new file mode 100644
index 0000000..f0cee50
--- /dev/null
+++ b/qsopt_ex/lpdata.c
@@ -0,0 +1,744 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: lpdata.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+/****************************************************************************/
+/*                                                                          */
+/*               Routines for Manipulating and Writing LPdata               */
+/*                                                                          */
+/*  EXPORTED FUNCTIONS                                                      */
+/*                                                                          */
+/*    int ILLlpdata_buildrows (EGLPNUM_TYPENAME_ILLlpdata *lp, int **rowbeg, int **rowcnt,     */
+/*            int **rowind, double **rowval, int include_logicals)          */
+/*      - include_logicals:  if nonzero, then logical variables will be     */
+/*          included in the row data                                        */
+/*                                                                          */
+/*                                                                          */
+/*    All _init routines initialize fields of allocated structure to        */
+/*    appropiate default values                                             */
+/*    The _free routines free structures contained in pareameter structure  */
+/*    but not the parameter itself.                                         */
+/*    The _alloc routines check whether given parameter is NULL; they either*/
+/*    print an error message or fill structure with default values or the   */
+/*    given paremeter values.                                               */
+/*                                                                          */
+/*    void EGLPNUM_TYPENAME_ILLlpdata_init (EGLPNUM_TYPENAME_ILLlpdata *lp)                                   */
+/*    void EGLPNUM_TYPENAME_ILLlpdata_free (EGLPNUM_TYPENAME_ILLlpdata *lp)                                   */
+/*                                                                          */
+/*    void EGLPNUM_TYPENAME_ILLlp_basis_init (EGLPNUM_TYPENAME_ILLlp_basis *B)                                */
+/*    void EGLPNUM_TYPENAME_ILLlp_basis_free (EGLPNUM_TYPENAME_ILLlp_basis *B)                                */
+/*    int EGLPNUM_TYPENAME_ILLlp_basis_alloc (EGLPNUM_TYPENAME_ILLlp_basis *B, int nstruct, int nrows)        */
+/*                                                                          */
+/*    void EGLPNUM_TYPENAME_ILLlp_cache_init (EGLPNUM_TYPENAME_ILLlp_cache *C)                                */
+/*    void EGLPNUM_TYPENAME_ILLlp_cache_free (EGLPNUM_TYPENAME_ILLlp_cache *C)                                */
+/*    int EGLPNUM_TYPENAME_ILLlp_cache_alloc (EGLPNUM_TYPENAME_ILLlp_cache *C, int nstruct, int nrows)        */
+/*                                                                          */
+/*    void EGLPNUM_TYPENAME_ILLlp_sinfo_init (EGLPNUM_TYPENAME_ILLlp_sinfo *sinfo)                            */
+/*    void EGLPNUM_TYPENAME_ILLlp_sinfo_free (EGLPNUM_TYPENAME_ILLlp_sinfo *sinfo)                            */
+/*                                                                          */
+/*    int EGLPNUM_TYPENAME_ILLlp_rows_init(EGLPNUM_TYPENAME_ILLlp_rows *lprows, EGLPNUM_TYPENAME_ILLlpdata *lp,                */
+/*                                           int include_logicals)          */
+/*                                                                          */
+/****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "allocrus.h"
+#include "eg_lpnum.h"
+#include "eg_io.h"
+#include "except.h"
+
+#include "lpdata_EGLPNUM_TYPENAME.h"
+#include "qstruct_EGLPNUM_TYPENAME.h"
+#include "qsopt_EGLPNUM_TYPENAME.h"
+#include "lp_EGLPNUM_TYPENAME.h"
+#include "mps_EGLPNUM_TYPENAME.h"
+#include "rawlp_EGLPNUM_TYPENAME.h"
+
+//static int TRACE = 0;
+
+EGLPNUM_TYPE EGLPNUM_TYPENAME_PARAM_IBASIS_RPIVOT;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_PARAM_IBASIS_RTRIANG;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_PARAM_MIN_DNORM;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_PFEAS_TOLER;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_BD_TOLER;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_DFEAS_TOLER;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_PIVOT_TOLER;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_SZERO_TOLER;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_PIVZ_TOLER;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_OBJBND_TOLER;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_DBNDPIV_TOLER;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_DBNDPIV_RATIO;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_ALTPIV_TOLER;
+//EGLPNUM_TYPE DJZERO_TOLER;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_PROGRESS_ZERO;				/*   1e-7 */
+EGLPNUM_TYPE EGLPNUM_TYPENAME_PROGRESS_THRESH;			/*   1e-5 */
+EGLPNUM_TYPE EGLPNUM_TYPENAME_CB_EPS;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_CB_INF_RATIO;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_CB_PRI_RLIMIT;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_ILL_MAXDOUBLE;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_ILL_MINDOUBLE;
+
+/* ========================================================================= */
+int EGLPNUM_TYPENAME___QSEX_SETUP = 0;
+/* ========================================================================= */
+void EGLPNUM_TYPENAME_ILLstart ( void)
+{
+	if (EGLPNUM_TYPENAME___QSEX_SETUP)
+		return;
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_PARAM_IBASIS_RPIVOT);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_PARAM_IBASIS_RTRIANG);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_PARAM_MIN_DNORM);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_PFEAS_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_BD_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_DFEAS_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_PIVOT_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_SZERO_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_PIVZ_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_OBJBND_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_DBNDPIV_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_DBNDPIV_RATIO);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_ALTPIV_TOLER);
+	//EGLPNUM_TYPENAME_EGlpNumInitVar (DJZERO_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_PROGRESS_ZERO);	/*            1e-7 */
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_PROGRESS_THRESH);	/*          1e-5 */
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_CB_PRI_RLIMIT);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_CB_INF_RATIO);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_CB_EPS);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+	/* parameters that do depend on the tolerance to zero */
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_PARAM_MIN_DNORM, 4.5036e-9);
+	EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_PARAM_MIN_DNORM, EGLPNUM_TYPENAME_epsLpNum);
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_PFEAS_TOLER, 4.5036e9);
+	EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_PFEAS_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_BD_TOLER, 4.5036e8);
+	EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_BD_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_DFEAS_TOLER, 4.5036e9);
+	EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_DFEAS_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_PIVOT_TOLER, 4.5036e5);
+	EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_PIVOT_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_SZERO_TOLER, 4.5036);
+	EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_SZERO_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_PIVZ_TOLER, 4.5036e3);
+	EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_PIVZ_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_OBJBND_TOLER, 4.5036e13);
+	EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_OBJBND_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_ALTPIV_TOLER, 4.5036e7);
+	EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_ALTPIV_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_PROGRESS_ZERO, 4.5036e8);
+	EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_PROGRESS_ZERO, EGLPNUM_TYPENAME_epsLpNum);
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_PROGRESS_THRESH, 4.5036e10);
+	EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_PROGRESS_THRESH, EGLPNUM_TYPENAME_epsLpNum);
+#if VERBOSE_LEVEL <= DEBUG
+	MESSAGE (VERBOSE_LEVEL, "Setting EGLPNUM_TYPENAME_PARAM_MIN_DNORM to %lg", EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_PARAM_MIN_DNORM));
+	MESSAGE (VERBOSE_LEVEL, "Setting EGLPNUM_TYPENAME_PFEAS_TOLER to %lg", EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_PFEAS_TOLER));
+	MESSAGE (VERBOSE_LEVEL, "Setting EGLPNUM_TYPENAME_BD_TOLER to %lg", EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_BD_TOLER));
+	MESSAGE (VERBOSE_LEVEL, "Setting EGLPNUM_TYPENAME_DFEAS_TOLER to %lg", EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_DFEAS_TOLER));
+	MESSAGE (VERBOSE_LEVEL, "Setting EGLPNUM_TYPENAME_PIVOT_TOLER to %lg", EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_PIVOT_TOLER));
+	MESSAGE (VERBOSE_LEVEL, "Setting EGLPNUM_TYPENAME_SZERO_TOLER to %lg", EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_SZERO_TOLER));
+	MESSAGE (VERBOSE_LEVEL, "Setting EGLPNUM_TYPENAME_PIVZ_TOLER to %lg", EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_PIVZ_TOLER));
+	MESSAGE (VERBOSE_LEVEL, "Setting EGLPNUM_TYPENAME_OBJBND_TOLER to %lg", EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_OBJBND_TOLER));
+	MESSAGE (VERBOSE_LEVEL, "Setting EGLPNUM_TYPENAME_ALTPIV_TOLER to %lg", EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_ALTPIV_TOLER));
+	MESSAGE (VERBOSE_LEVEL, "Setting EGLPNUM_TYPENAME_PROGRESS_ZERO to %lg", EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_PROGRESS_ZERO));
+	MESSAGE (VERBOSE_LEVEL, "Setting EGLPNUM_TYPENAME_PROGRESS_THRESH to %lg", EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_PROGRESS_THRESH));
+#endif
+	/* parameters that do not depend on the tolerance to zero */
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_ILL_MAXDOUBLE, 1e150);
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_ILL_MINDOUBLE, -1e150);
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_PARAM_IBASIS_RPIVOT, 0.98);
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_PARAM_IBASIS_RTRIANG, 0.01);
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_DBNDPIV_TOLER, 1e-3);
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_DBNDPIV_RATIO, 1e-2);
+	//EGLPNUM_TYPENAME_EGlpNumSet (DJZERO_TOLER, 1e-8);
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_CB_EPS, 0.001);
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_CB_INF_RATIO, 10.0);
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_CB_PRI_RLIMIT, 0.25);
+	EGLPNUM_TYPENAME___QSEX_SETUP = 1;
+}
+
+/* ========================================================================= */
+void EGLPNUM_TYPENAME_ILLchange_precision (
+	void)
+{
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_PFEAS_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_BD_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_DFEAS_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_PIVOT_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_SZERO_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_PIVZ_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_OBJBND_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_ALTPIV_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_PARAM_MIN_DNORM);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_PROGRESS_ZERO);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_PROGRESS_THRESH);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_PROGRESS_ZERO);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_PROGRESS_THRESH);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_PFEAS_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_BD_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_DFEAS_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_PIVOT_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_SZERO_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_PIVZ_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_OBJBND_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_ALTPIV_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_PARAM_MIN_DNORM);
+	/* parameters that do depend on the tolerance to zero */
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_PARAM_MIN_DNORM, 4.5036e-9);
+	EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_PARAM_MIN_DNORM, EGLPNUM_TYPENAME_epsLpNum);
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_PFEAS_TOLER, 4.5036e9);
+	EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_PFEAS_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_BD_TOLER, 4.5036e8);
+	EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_BD_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_DFEAS_TOLER, 4.5036e9);
+	EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_DFEAS_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_PIVOT_TOLER, 4.5036e5);
+	EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_PIVOT_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_SZERO_TOLER, 4.5036);
+	EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_SZERO_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_PIVZ_TOLER, 4.5036e3);
+	EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_PIVZ_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_OBJBND_TOLER, 4.5036e13);
+	EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_OBJBND_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_ALTPIV_TOLER, 4.5036e7);
+	EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_ALTPIV_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_PROGRESS_ZERO, 4.5036e8);
+	EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_PROGRESS_ZERO, EGLPNUM_TYPENAME_epsLpNum);
+	EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_PROGRESS_THRESH, 4.5036e10);
+	EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_PROGRESS_THRESH, EGLPNUM_TYPENAME_epsLpNum);
+}
+
+/* ========================================================================= */
+void EGLPNUM_TYPENAME_ILLend ( void)
+{
+	if (!EGLPNUM_TYPENAME___QSEX_SETUP)
+		return;
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_PARAM_IBASIS_RPIVOT);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_PARAM_IBASIS_RTRIANG);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_PARAM_MIN_DNORM);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_PFEAS_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_BD_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_DFEAS_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_PIVOT_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_SZERO_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_PIVZ_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_OBJBND_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_DBNDPIV_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_DBNDPIV_RATIO);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_ALTPIV_TOLER);
+	//EGLPNUM_TYPENAME_EGlpNumClearVar (DJZERO_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_PROGRESS_ZERO);	/*            1e-7 */
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_PROGRESS_THRESH);	/*          1e-5 */
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_CB_EPS);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_CB_INF_RATIO);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_CB_PRI_RLIMIT);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+	EGLPNUM_TYPENAME___QSEX_SETUP = 0;
+}
+
+EGLPNUM_TYPENAME_QSdata *EGLPNUM_TYPENAME_ILLread (
+	EGLPNUM_TYPENAME_qsline_reader * file,
+	const char *fname,
+	int isMps)
+{
+	int rval = 0;
+	EGLPNUM_TYPENAME_QSdata *p = 0;
+	EGLPNUM_TYPENAME_ILLlpdata *lp;
+	EGLPNUM_TYPENAME_rawlpdata rawlp;
+
+	ILL_FAILfalse (file != NULL, NULL);
+	ILL_FAILfalse (fname != NULL, NULL);
+
+	p = EGLPNUM_TYPENAME_QScreate_prob (fname, QS_MIN);
+	ILL_CHECKnull (p, NULL);
+	ILL_IFFREE (p->qslp->probname, char);
+
+	lp = p->qslp;
+
+	EGLPNUM_TYPENAME_ILLinit_rawlpdata (&rawlp, file->error_collector);
+	EGLPNUM_TYPENAME_ILLlpdata_init (lp);
+
+	if (isMps != 0)
+	{
+		rval = EGLPNUM_TYPENAME_ILLread_mps (file, fname, &rawlp);
+	}
+	else
+	{
+		rval = EGLPNUM_TYPENAME_ILLread_lp (file, fname, &rawlp);
+	}
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_ILLrawlpdata_to_lpdata (&rawlp, lp);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+	EGLPNUM_TYPENAME_ILLfree_rawlpdata (&rawlp);
+	if (rval != 0)
+	{
+		EGLPNUM_TYPENAME_QSfree_prob (p);
+		p = 0;
+	}
+	return p;
+}
+
+static int EGLPNUM_TYPENAME_ILLlpdata_log(
+	void *dest, const char *s)
+{
+	if (s != NULL) {
+		QSlog("%s", s);
+	}
+	return 0;
+}
+
+void EGLPNUM_TYPENAME_ILLlpdata_init (
+	EGLPNUM_TYPENAME_ILLlpdata * lp)
+{
+	if (lp)
+	{
+		lp->nrows = 0;
+		lp->ncols = 0;
+		lp->nstruct = 0;
+		lp->nzcount = 0;
+		lp->rowsize = 0;
+		lp->colsize = 0;
+		lp->structsize = 0;
+		lp->objsense = EGLPNUM_TYPENAME_ILL_MIN;
+		lp->sense = 0;
+		lp->obj = 0;
+		lp->rhs = 0;
+		lp->rangeval = 0;
+		lp->lower = 0;
+		lp->upper = 0;
+
+		EGLPNUM_TYPENAME_ILLmatrix_init (&lp->A);
+		EGLPNUM_TYPENAME_ILLmatrix_init (&lp->sos);
+		lp->rA = 0;
+		lp->is_sos_mem = NULL;
+		lp->refrowname = NULL;
+		lp->refind = -1;
+
+		lp->colnames = 0;
+		ILLsymboltab_init (&lp->coltab);
+		lp->rownames = 0;
+		ILLsymboltab_init (&lp->rowtab);
+		lp->objname = 0;
+
+		lp->probname = 0;
+		lp->intmarker = 0;
+		lp->structmap = 0;
+		lp->rowmap = 0;
+		lp->basis = 0;
+		/*lp->presolve   = 0; */
+		lp->sinfo = 0;
+
+		ILLstring_reporter_init(
+			&lp->reporter, EGLPNUM_TYPENAME_ILLlpdata_log, NULL);
+	}
+}
+
+void EGLPNUM_TYPENAME_ILLlpdata_free (
+	EGLPNUM_TYPENAME_ILLlpdata * lp)
+{
+	int i;
+
+	if (lp)
+	{
+		ILL_IFFREE (lp->sense, char);
+
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->obj);
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->rhs);
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->rangeval);
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->lower);
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->upper);
+		EGLPNUM_TYPENAME_ILLmatrix_free (&lp->A);
+		if (lp->rA)
+		{
+			EGLPNUM_TYPENAME_ILLlp_rows_clear (lp->rA);
+			ILL_IFFREE (lp->rA, EGLPNUM_TYPENAME_ILLlp_rows);
+		}
+		ILL_IFFREE (lp->is_sos_mem, int);
+		ILL_IFFREE (lp->refrowname, char);
+
+		EGLPNUM_TYPENAME_ILLmatrix_free (&lp->sos);
+		if (lp->colnames)
+		{
+			for (i = 0; i < lp->nstruct; i++)
+			{
+				ILL_IFFREE (lp->colnames[i], char);
+			}
+			ILL_IFFREE (lp->colnames, char *);
+		}
+		ILLsymboltab_free (&lp->coltab);
+		if (lp->rownames)
+		{
+			for (i = 0; i < lp->nrows; i++)
+			{
+				ILL_IFFREE (lp->rownames[i], char);
+			}
+			ILL_IFFREE (lp->rownames, char *);
+		}
+		ILLsymboltab_free (&lp->rowtab);
+		ILL_IFFREE (lp->objname, char);
+		ILL_IFFREE (lp->probname, char);
+		ILL_IFFREE (lp->intmarker, char);
+		ILL_IFFREE (lp->structmap, int);
+		ILL_IFFREE (lp->rowmap, int);
+
+		if (lp->sinfo)
+		{
+			EGLPNUM_TYPENAME_ILLlp_sinfo_free (lp->sinfo);
+			ILL_IFFREE (lp->sinfo, EGLPNUM_TYPENAME_ILLlp_sinfo);
+		}
+		EGLPNUM_TYPENAME_ILLlpdata_init (lp);
+	}
+}
+
+void EGLPNUM_TYPENAME_ILLlp_basis_init (
+	EGLPNUM_TYPENAME_ILLlp_basis * B)
+{
+	if (B)
+	{
+		B->cstat = 0;
+		B->rstat = 0;
+		B->rownorms = 0;
+		B->colnorms = 0;
+		B->nstruct = 0;
+		B->nrows = 0;
+	}
+}
+
+void EGLPNUM_TYPENAME_ILLlp_basis_free (
+	EGLPNUM_TYPENAME_ILLlp_basis * B)
+{
+	if (B)
+	{
+		ILL_IFFREE (B->cstat, char);
+		ILL_IFFREE (B->rstat, char);
+
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (B->rownorms);
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (B->colnorms);
+		B->nstruct = 0;
+		B->nrows = 0;
+	}
+}
+
+int EGLPNUM_TYPENAME_ILLlp_basis_alloc (
+	EGLPNUM_TYPENAME_ILLlp_basis * B,
+	int nstruct,
+	int nrows)
+{
+	int rval = 0;
+
+	ILL_FAILtrue (B == NULL, "EGLPNUM_TYPENAME_ILLlp_basis_alloc called without a basis");
+
+	B->nstruct = nstruct;
+	B->nrows = nrows;
+
+	if (nstruct > 0)
+	{
+		ILL_SAFE_MALLOC (B->cstat, nstruct, char);
+	}
+
+	if (nrows > 0)
+	{
+		ILL_SAFE_MALLOC (B->rstat, nrows, char);
+	}
+
+CLEANUP:
+
+	if (rval)
+	{
+		EGLPNUM_TYPENAME_ILLlp_basis_free (B);
+	}
+
+	EG_RETURN (rval);
+}
+
+void EGLPNUM_TYPENAME_ILLlp_cache_init (
+	EGLPNUM_TYPENAME_ILLlp_cache * C)
+{
+	if (C)
+	{
+		C->x = 0;
+		C->rc = 0;
+		C->pi = 0;
+		C->slack = 0;
+		C->nstruct = 0;
+		C->nrows = 0;
+		C->status = 0;
+		EGLPNUM_TYPENAME_EGlpNumZero (C->val);
+	}
+}
+
+void EGLPNUM_TYPENAME_ILLlp_cache_free (
+	EGLPNUM_TYPENAME_ILLlp_cache * C)
+{
+	if (C)
+	{
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (C->x);
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (C->rc);
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (C->pi);
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (C->slack);
+		C->nstruct = 0;
+		C->nrows = 0;
+		C->status = 0;
+	}
+}
+
+int EGLPNUM_TYPENAME_ILLlp_cache_alloc (
+	EGLPNUM_TYPENAME_ILLlp_cache * C,
+	int nstruct,
+	int nrows)
+{
+	int rval = 0;
+
+	ILL_FAILtrue (C == NULL, "EGLPNUM_TYPENAME_ILLlp_cache_alloc called without a cache");
+
+	C->nstruct = nstruct;
+	C->nrows = nrows;
+
+	if (nstruct > 0)
+	{
+		C->x = EGLPNUM_TYPENAME_EGlpNumAllocArray (nstruct);
+		C->rc = EGLPNUM_TYPENAME_EGlpNumAllocArray (nstruct);
+	}
+
+	if (nrows > 0)
+	{
+		C->pi = EGLPNUM_TYPENAME_EGlpNumAllocArray (nrows);
+		C->slack = EGLPNUM_TYPENAME_EGlpNumAllocArray (nrows);
+	}
+
+CLEANUP:
+
+	if (rval)
+	{
+		EGLPNUM_TYPENAME_ILLlp_cache_free (C);
+	}
+
+	EG_RETURN (rval);
+}
+
+
+int EGLPNUM_TYPENAME_ILLlp_rows_init (
+	EGLPNUM_TYPENAME_ILLlp_rows * lprows,
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	int include_logicals)
+{
+	int rval = 0;
+	int i, k, st;
+	int *beg, *cnt, *ind;
+	EGLPNUM_TYPE *val;
+	EGLPNUM_TYPENAME_ILLmatrix *A;
+	char *hit = 0;
+	int *inv_structmap = 0;
+
+	/* If logicals are not included, then the columns are ordered as in */
+	/* lp->structmap.  Otherwise, the columns are ordered as in the     */
+	/* matrix structure.                                                */
+
+	if (lprows != NULL)
+	{
+		lprows->rowbeg = 0;
+		lprows->rowcnt = 0;
+		lprows->rowind = 0;
+		lprows->rowval = 0;
+	}
+
+	ILL_FAILfalse ((lp != NULL) && (lprows != NULL),
+								 "called with a NULL pointer");
+
+	A = &lp->A;
+
+	if (lp->nrows > 0)
+	{
+		if (include_logicals == 0)
+		{
+			ILL_FAILtrue (lp->rowmap == NULL, "Programming error.");
+			ILL_SAFE_MALLOC (hit, lp->ncols, char);
+
+			for (i = 0; i < lp->ncols; i++)
+			{
+				hit[i] = 0;
+			}
+			for (i = 0; i < lp->nrows; i++)
+			{
+				hit[lp->rowmap[i]] = 1;
+			}
+
+			ILL_SAFE_MALLOC (inv_structmap, lp->ncols, int);
+
+			for (i = 0; i < lp->nstruct; i++)
+			{
+				inv_structmap[lp->structmap[i]] = i;
+			}
+		}
+
+		ILL_SAFE_MALLOC (lprows->rowbeg, lp->nrows, int);
+		ILL_SAFE_MALLOC (lprows->rowcnt, lp->nrows, int);
+
+		if (((include_logicals != 0) && lp->nzcount > 0) ||
+				((include_logicals == 0) && lp->nzcount > lp->nrows))
+		{
+			if (include_logicals != 0)
+			{
+				ILL_SAFE_MALLOC (lprows->rowind, lp->nzcount, int);
+
+				lprows->rowval = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nzcount);
+			}
+			else
+			{
+				ILL_SAFE_MALLOC (lprows->rowind, lp->nzcount - lp->nrows, int);
+
+				lprows->rowval = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nzcount - lp->nrows);
+			}
+		}
+
+		beg = lprows->rowbeg;
+		cnt = lprows->rowcnt;
+		ind = lprows->rowind;
+		val = lprows->rowval;
+
+		for (i = 0; i < lp->nrows; i++)
+		{
+			cnt[i] = 0;
+		}
+
+		for (i = 0; i < lp->ncols; i++)
+		{
+			if ((include_logicals != 0) || hit[i] == 0)
+			{
+				k = A->matbeg[i];
+				st = k + A->matcnt[i];
+				for (; k < st; k++)
+				{
+					cnt[A->matind[k]]++;
+				}
+			}
+		}
+
+		for (i = 0, k = 0; i < lp->nrows; i++)
+		{
+			beg[i] = k;
+			k += cnt[i];
+		}
+
+		for (i = 0; i < lp->ncols; i++)
+		{
+			if ((include_logicals != 0) || hit[i] == 0)
+			{
+				k = A->matbeg[i];
+				st = k + A->matcnt[i];
+				for (; k < st; k++)
+				{
+					if (include_logicals != 0)
+					{
+						ind[beg[A->matind[k]]] = i;
+					}
+					else
+					{
+						ind[beg[A->matind[k]]] = inv_structmap[i];
+					}
+					EGLPNUM_TYPENAME_EGlpNumCopy (val[beg[A->matind[k]]], A->matval[k]);
+					beg[A->matind[k]]++;
+				}
+			}
+		}
+
+		for (i = 0, k = 0; i < lp->nrows; i++)
+		{
+			beg[i] = k;
+			k += cnt[i];
+		}
+	}
+CLEANUP:
+
+	if (rval)
+	{
+		EGLPNUM_TYPENAME_ILLlp_rows_clear (lprows);
+	}
+	ILL_IFFREE (hit, char);
+	ILL_IFFREE (inv_structmap, int);
+
+	EG_RETURN (rval);
+}
+
+void EGLPNUM_TYPENAME_ILLlp_rows_clear (
+	EGLPNUM_TYPENAME_ILLlp_rows * lprows)
+{
+	if (lprows != NULL)
+	{
+		ILL_IFFREE (lprows->rowbeg, int);
+		ILL_IFFREE (lprows->rowcnt, int);
+		ILL_IFFREE (lprows->rowind, int);
+
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (lprows->rowval);
+	}
+}
+
+static int wr_line (
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	const char *format,
+	va_list argptr)
+{
+	char buffer[ILL_namebufsize];
+	int rval = 0;
+
+	rval = vsprintf (buffer, format, argptr);
+	if (rval > 0)
+	{
+                /* Bico -- OPTERON DEBUGGING 051005  */
+                /* Replaced ILLstring_report by the explicit call to */
+                /* fprintf.                                          */
+                /*rval = fprintf (lp->reporter.dest, buffer);
+                if (rval < 0) rval = 1;
+                else          rval = 0;
+								*/
+		/* daespino -- BACK to ILLstring_report to support compresed files 090909
+		 * */
+		rval = ILLstring_report(buffer, &lp->reporter);
+	}
+	return rval;
+}
+
+int EGLPNUM_TYPENAME_ILLprint_report (
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	const char *format,
+	...)
+{
+	va_list marker;
+	int rval = 0;
+
+	va_start (marker, format);		/* ANSI style */
+	rval = wr_line (lp, format, marker);
+	va_end (marker);							/* Reset variable arguments.      */
+	return rval;
+}
diff --git a/qsopt_ex/lpdata.h b/qsopt_ex/lpdata.h
new file mode 100644
index 0000000..452df5d
--- /dev/null
+++ b/qsopt_ex/lpdata.h
@@ -0,0 +1,303 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCSINFO $Id: lpdata_EGLPNUM_TYPENAME.h,v 1.4 2003/11/05 17:00:56 meven Exp $ */
+#ifndef EGLPNUM_TYPENAME_ILL_LPDATA_H
+#define EGLPNUM_TYPENAME_ILL_LPDATA_H
+
+#include "eg_lpnum.h"
+#include "reporter.h"
+#include "symtab.h"
+
+#include "qstruct_EGLPNUM_TYPENAME.h"
+#include "readline_EGLPNUM_TYPENAME.h"
+#include "format_EGLPNUM_TYPENAME.h"
+#include "dstruct_EGLPNUM_TYPENAME.h"
+
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_ILL_MAXDOUBLE;	/*  1e150 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_ILL_MINDOUBLE;	/* -1e150 */
+
+#define EGLPNUM_TYPENAME_ILL_MAXINT    (2147483647)	/* this is equal to 2^31-1 */
+#define EGLPNUM_TYPENAME_ILL_MIN       (1)				/* Must be same as QS_MIN */
+#define EGLPNUM_TYPENAME_ILL_MAX       (-1)			/* Must be same as QS_MAX */
+
+/*  Setting Alg in Presolve  */
+
+#define EGLPNUM_TYPENAME_ILL_PRE_SCALE           1
+#define EGLPNUM_TYPENAME_ILL_PRE_FIXED           2
+#define EGLPNUM_TYPENAME_ILL_PRE_SINGLE_ROW      4
+#define EGLPNUM_TYPENAME_ILL_PRE_FORCING         8
+#define EGLPNUM_TYPENAME_ILL_PRE_SINGLE_COL     16
+#define EGLPNUM_TYPENAME_ILL_PRE_DUPLICATE_ROW  32
+#define EGLPNUM_TYPENAME_ILL_PRE_DUPLICATE_COL  64
+#define EGLPNUM_TYPENAME_ILL_PRE_EMPTY_COL     128
+#define EGLPNUM_TYPENAME_ILL_PRE_ALL (EGLPNUM_TYPENAME_ILL_PRE_SCALE | EGLPNUM_TYPENAME_ILL_PRE_FIXED | EGLPNUM_TYPENAME_ILL_PRE_SINGLE_ROW           \
+                    EGLPNUM_TYPENAME_ILL_PRE_FORCING | EGLPNUM_TYPENAME_ILL_PRE_SINGLE_COL | EGLPNUM_TYPENAME_ILL_PRE_DUPLICATE_ROW \
+                   EGLPNUM_TYPENAME_ILL_PRE_DUPLICATE_COL | EGLPNUM_TYPENAME_ILL_PRE_EMPTY_COL)
+#define EGLPNUM_TYPENAME_ILL_PRE_SIMPLE (EGLPNUM_TYPENAME_ILL_PRE_FIXED | EGLPNUM_TYPENAME_ILL_PRE_EMPTY_COL)
+
+typedef struct EGLPNUM_TYPENAME_ILLlpdata
+{																/* Complete LP data filled in by mpsread.  */
+	int nrows;
+	int ncols;
+	int nstruct;									/* Not including logicals.                 */
+	int nzcount;
+	int rowsize;									/* Length of row arrays.                   */
+	int colsize;									/* Length of col arrays.                   */
+	int structsize;								/* Length of intmarker, structmap,         */
+	/* colnames                                */
+	int objsense;
+	char *sense;									/* Original sense, not after logicals.     */
+	EGLPNUM_TYPE *obj;
+	EGLPNUM_TYPE *rhs;
+	EGLPNUM_TYPE *rangeval;
+	EGLPNUM_TYPE *lower;
+	EGLPNUM_TYPE *upper;
+	EGLPNUM_TYPENAME_ILLmatrix A;									/* The coef matrix.                        */
+	struct EGLPNUM_TYPENAME_ILLlp_rows *rA;				/* Coef matrix in row form.                */
+
+	char **rownames;
+	ILLsymboltab rowtab;					/* contains rownames in no particular order */
+	char *objname;								/* if colname is not NULL it is entered into 
+																 * the rowtab, see reader fcts in lp.c, mps.c*/
+
+	char **colnames;							/* columns of struct variables */
+	ILLsymboltab coltab;					/* contains colnames in no particular order */
+
+	char *probname;
+	char *intmarker;
+	int *structmap;								/* Indices of structural variables         */
+	int *rowmap;									/* Indices of logical and range variables  */
+	struct EGLPNUM_TYPENAME_ILLlp_basis *basis;
+	struct EGLPNUM_TYPENAME_ILLlp_predata *presolve;
+	struct EGLPNUM_TYPENAME_ILLlp_sinfo *sinfo;
+
+	 /**************************************************************************/
+	/* these fields are currently only set by mps.c reader fcts               */
+	 /**************************************************************************/
+	EGLPNUM_TYPENAME_ILLmatrix sos;								/* columns are the sets, rows are the  
+																 * problem's structural variables
+																 * coefficients are the weights */
+
+	char *sos_type;								/* type of each set */
+	int *is_sos_mem;							/* for each structural variable contains 
+																 *    -1 == not a set member
+																 *     i == member of sos set i 
+																 *          where 0 <= i < sos.matcols */
+	char *refrowname;							/* name of reference row */
+	int refind;										/* index of reference row 
+																 *     -1 if refrow was a free row 
+																 *          and weights are found only in the 
+																 *          sos matrix 
+																 *     index >=0 if refrow is also a lp-row */
+
+	 /**************************************************************************
+    * EGLPNUM_TYPENAME_QSset_reporter initializes reporter 
+    **************************************************************************/
+	qsstring_reporter reporter;		/* used from within ILL fcts 
+																 * to report feedback */
+}
+EGLPNUM_TYPENAME_ILLlpdata;
+
+typedef struct EGLPNUM_TYPENAME_ILLlp_basis
+{
+	int nstruct;
+	int nrows;
+	int rownorms_size;
+	int colnorms_size;
+	char *cstat;
+	char *rstat;
+	EGLPNUM_TYPE *rownorms;
+	EGLPNUM_TYPE *colnorms;
+}
+EGLPNUM_TYPENAME_ILLlp_basis;
+
+typedef struct EGLPNUM_TYPENAME_ILLlp_cache
+{
+	int nstruct;
+	int nrows;
+	int status;
+	EGLPNUM_TYPE val;
+	EGLPNUM_TYPE *x;
+	EGLPNUM_TYPE *pi;
+	EGLPNUM_TYPE *rc;
+	EGLPNUM_TYPE *slack;
+}
+EGLPNUM_TYPENAME_ILLlp_cache;
+
+typedef struct EGLPNUM_TYPENAME_ILLlp_sinfo
+{																/* LP info returned by presolve            */
+	int ncols;
+	int nrows;
+	int nzcount;
+	int rowsize;
+	int colsize;
+	int objsense;
+
+	EGLPNUM_TYPE *obj;
+	EGLPNUM_TYPE *rhs;
+	EGLPNUM_TYPE *lower;
+	EGLPNUM_TYPE *upper;
+
+	EGLPNUM_TYPENAME_ILLmatrix A;
+
+	char **colnames;							/* Just for debugging - not updated */
+}
+EGLPNUM_TYPENAME_ILLlp_sinfo;
+
+typedef struct EGLPNUM_TYPENAME_ILLlp_preline
+{
+	EGLPNUM_TYPE rhs;
+	EGLPNUM_TYPE obj;
+	EGLPNUM_TYPE lower;
+	EGLPNUM_TYPE upper;
+	int count;
+	int *ind;
+	int row_or_col;								/* 0 is row, 1 is col */
+	EGLPNUM_TYPE *val;
+}
+EGLPNUM_TYPENAME_ILLlp_preline;
+
+typedef struct EGLPNUM_TYPENAME_ILLlp_preop
+{
+	int ptype;
+	int rowindex;
+	int colindex;
+	EGLPNUM_TYPENAME_ILLlp_preline line;
+}
+EGLPNUM_TYPENAME_ILLlp_preop;
+
+typedef struct EGLPNUM_TYPENAME_ILLlp_predata
+{																/* Data needed in un-presolve.            */
+	int opcount;
+	int opsize;
+	EGLPNUM_TYPENAME_ILLlp_preop *oplist;
+	int r_nrows;
+	int r_ncols;
+	int *colmap;
+	int *rowmap;
+	EGLPNUM_TYPE *rowscale;
+	EGLPNUM_TYPE *colscale;
+	EGLPNUM_TYPE *colfixval;
+	EGLPNUM_TYPE *rowfixval;
+}
+EGLPNUM_TYPENAME_ILLlp_predata;
+
+typedef struct EGLPNUM_TYPENAME_ILLlp_rows
+{
+	int *rowbeg;
+	int *rowcnt;
+	int *rowind;
+	EGLPNUM_TYPE *rowval;
+}
+EGLPNUM_TYPENAME_ILLlp_rows;
+
+
+/****************************************************************************/
+/*                                                                          */
+/*                             lpdata.c                                     */
+/*                                                                          */
+/****************************************************************************/
+
+struct EGLPNUM_TYPENAME_qsdata *EGLPNUM_TYPENAME_ILLread (
+	EGLPNUM_TYPENAME_qsline_reader * file,
+	const char *fname,
+	int isMps);
+void EGLPNUM_TYPENAME_ILLstart (
+	void);							/**< initialize EGLPNUM_TYPENAME_ILL_MAXDOUBLE and other 
+
+													 constants, this funtion should be callef AFTER 
+													 EGlpNumStart() */
+void EGLPNUM_TYPENAME_ILLend (
+	void);						/**< free any internal data asociated with variable 
+
+												 precision numbers */
+void EGLPNUM_TYPENAME_ILLchange_precision (
+	void);												/**< This function re-compute the internal 
+
+																		 variables precision to the (previously 
+																		 set) EGLPNUM_PRECISION value (done with 
+																		 EGlpNumSetPrecision) */
+void EGLPNUM_TYPENAME_ILLlpdata_init (
+	EGLPNUM_TYPENAME_ILLlpdata * lp);
+void EGLPNUM_TYPENAME_ILLlpdata_free (
+	EGLPNUM_TYPENAME_ILLlpdata * lp);
+void EGLPNUM_TYPENAME_ILLlp_basis_init (
+	EGLPNUM_TYPENAME_ILLlp_basis * B);
+void EGLPNUM_TYPENAME_ILLlp_basis_free (
+	EGLPNUM_TYPENAME_ILLlp_basis * B);
+void EGLPNUM_TYPENAME_ILLlp_cache_init (
+	EGLPNUM_TYPENAME_ILLlp_cache * C);
+void EGLPNUM_TYPENAME_ILLlp_cache_free (
+	EGLPNUM_TYPENAME_ILLlp_cache * C);
+int EGLPNUM_TYPENAME_ILLlp_basis_alloc (
+	EGLPNUM_TYPENAME_ILLlp_basis * B,
+	int ncols,
+	int nrows);
+int EGLPNUM_TYPENAME_ILLlp_cache_alloc (
+	EGLPNUM_TYPENAME_ILLlp_cache * C,
+	int ncols,
+	int nrows);
+
+int EGLPNUM_TYPENAME_ILLlp_rows_init (
+	EGLPNUM_TYPENAME_ILLlp_rows * lp_rows,
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	int include_logicals);
+void EGLPNUM_TYPENAME_ILLlp_rows_clear (
+	EGLPNUM_TYPENAME_ILLlp_rows * lp_rows);
+int EGLPNUM_TYPENAME_ILLprint_report (
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	const char *format,
+	...);
+
+							/* print to lp->reporter */
+
+/****************************************************************************/
+/*                                                                          */
+/*                             presolve.c                                   */
+/*                                                                          */
+/****************************************************************************/
+
+void EGLPNUM_TYPENAME_ILLlp_sinfo_init (
+	EGLPNUM_TYPENAME_ILLlp_sinfo * sinfo),
+  EGLPNUM_TYPENAME_ILLlp_sinfo_free (
+	EGLPNUM_TYPENAME_ILLlp_sinfo * sinfo),
+  EGLPNUM_TYPENAME_ILLlp_predata_init (
+	EGLPNUM_TYPENAME_ILLlp_predata * pre),
+  EGLPNUM_TYPENAME_ILLlp_predata_free (
+	EGLPNUM_TYPENAME_ILLlp_predata * pre);
+
+int EGLPNUM_TYPENAME_ILLlp_add_logicals (
+	EGLPNUM_TYPENAME_ILLlpdata * lp),
+  EGLPNUM_TYPENAME_ILLlp_scale (
+	EGLPNUM_TYPENAME_ILLlpdata * lp),
+  EGLPNUM_TYPENAME_ILLlp_presolve (
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	int pre_types);
+
+/* ========================================================================= */
+/* if non-zero, then internal data has been initialized, and there is some
+ * memory allocated, if zero, no internal memory has been allocated
+ * (or it has been freed) */
+extern int EGLPNUM_TYPENAME___QSEX_SETUP;
+
+#endif /* __ILL_LPDATA_H */
diff --git a/qsopt_ex/lpdefs.h b/qsopt_ex/lpdefs.h
new file mode 100644
index 0000000..decc400
--- /dev/null
+++ b/qsopt_ex/lpdefs.h
@@ -0,0 +1,330 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCSINFO $Id: lpdefs_EGLPNUM_TYPENAME.h,v 1.3 2003/11/05 16:57:39 meven Exp $ */
+#ifndef EGLPNUM_TYPENAME___QS_LPDEFS_H
+#define EGLPNUM_TYPENAME___QS_LPDEFS_H
+
+#include "urandom.h"
+
+#include "qsopt_EGLPNUM_TYPENAME.h"
+#include "lpdata_EGLPNUM_TYPENAME.h"
+#include "factor_EGLPNUM_TYPENAME.h"
+
+/* infinity and negative infinity */
+#define EGLPNUM_TYPENAME_INFTY  EGLPNUM_TYPENAME_ILL_MAXDOUBLE
+#define EGLPNUM_TYPENAME_NINFTY EGLPNUM_TYPENAME_ILL_MINDOUBLE
+
+#include "basicdefs.h"
+/* tolerances, these are initialized in EGLPNUM_TYPENAME_ILLstart, file lpdata.c */
+/* these three constants are defined in lpdata.c */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_PARAM_IBASIS_RPIVOT;	/*       0.98 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_PARAM_IBASIS_RTRIANG;/*       0.01 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_PARAM_MIN_DNORM;			/*      1e-24 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_PFEAS_TOLER;					/*       1e-6 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_BD_TOLER;						/*       1e-7 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_DFEAS_TOLER;					/*       1e-6 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_PIVOT_TOLER;					/*      1e-10 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_SZERO_TOLER;					/*      1e-15 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_PIVZ_TOLER;					/*      1e-12 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_OBJBND_TOLER;				/*       1e-2 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_DBNDPIV_TOLER;				/*       1e-3 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_DBNDPIV_RATIO;				/*       1e-2 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_ALTPIV_TOLER;				/*       1e-8 */
+//extern EGLPNUM_TYPE DJZERO_TOLER;/*             1e-8 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_PROGRESS_ZERO;				/*       1e-7 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_PROGRESS_THRESH;			/*       1e-5 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_CB_EPS;							/*      0.001 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_CB_INF_RATIO;				/*       10.0 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_CB_PRI_RLIMIT;				/*       0.25 */
+
+/* structure for statistics */
+typedef struct
+{
+	int ynz_cnt;									/* nz in entering columns */
+	int num_y;
+	EGLPNUM_TYPE y_ravg;							/* weighted avg. of current & prior y */
+	int znz_cnt;									/* nz in ith row of B^{-1}, ie z_i */
+	int num_z;
+	EGLPNUM_TYPE z_ravg;							/* weighted avg. of current & prior z */
+	int zanz_cnt;									/* nz in z^TA */
+	int num_za;
+	EGLPNUM_TYPE za_ravg;						/* weighted avg. of current & prior za */
+	int pnorm_cnt;								/* nz in columns for primal norms */
+	int dnorm_cnt;								/* nz in rows for dual norms */
+	int pinz_cnt;									/* nz in phase II pi (solve) */
+	int num_pi;										/* # of pi solves */
+	int pi1nz_cnt;								/* nz in phase I pi (solve) */
+	int num_pi1;									/* # of phase I pi solves */
+	int upnz_cnt;									/* nz in ftran update vector */
+	int num_up;										/* # of ftran_updates */
+	int pupv_cnt;									/* nz in primal steep updates */
+	int dupv_cnt;									/* nz in dual steep updates */
+
+	int start_slacks;							/* # slacks in beginning */
+	int final_slacks;							/* # slacks in the end */
+	int start_art;								/* # arts in beginning */
+	int final_art;								/* # arts in the end */
+
+	int pI_iter;									/* primal phase I iterations */
+	int pII_iter;
+	int dI_iter;									/* dual phase I iterations */
+	int dII_iter;
+	int tot_iter;
+
+	int pivpI[10];								/* sizes of pivots */
+	int pivpII[10];
+	int pivdI[10];
+	int pivdII[10];
+}
+EGLPNUM_TYPENAME_count_struct;
+
+/* structure for tolerances */
+typedef struct
+{
+	EGLPNUM_TYPE pfeas_tol;
+	EGLPNUM_TYPE dfeas_tol;
+	EGLPNUM_TYPE pivot_tol;
+	EGLPNUM_TYPE szero_tol;
+	EGLPNUM_TYPE ip_tol;							/* inner primal & dual feas toler */
+	EGLPNUM_TYPE id_tol;
+}
+EGLPNUM_TYPENAME_tol_struct;
+
+/* bound information */
+typedef struct EGLPNUM_TYPENAME_bndinfo
+{
+	EGLPNUM_TYPE pbound;
+	EGLPNUM_TYPE cbound;
+	int btype;
+	int varnum;
+	struct EGLPNUM_TYPENAME_bndinfo *next;
+}
+EGLPNUM_TYPENAME_bndinfo;
+
+/* bound information */
+typedef struct EGLPNUM_TYPENAME_coefinfo
+{
+	EGLPNUM_TYPE pcoef;
+	EGLPNUM_TYPE ccoef;
+	int varnum;
+	struct EGLPNUM_TYPENAME_coefinfo *next;
+}
+EGLPNUM_TYPENAME_coefinfo;
+
+/* feasibility info */
+typedef struct EGLPNUM_TYPENAME_feas_info
+{
+	int pstatus;
+	int dstatus;
+	EGLPNUM_TYPE totinfeas;
+}
+EGLPNUM_TYPENAME_feas_info;
+
+typedef struct EGLPNUM_TYPENAME_lp_status_info
+{
+	char optimal;
+	char primal_feasible;
+	char primal_infeasible;
+	char primal_unbounded;
+	char dual_feasible;
+	char dual_infeasible;
+	char dual_unbounded;
+	char padd;
+}
+EGLPNUM_TYPENAME_lp_status_info;
+
+typedef struct EGLPNUM_TYPENAME_pI_uinfo
+{
+	int tctr;
+	int i;
+	int *perm;
+	int *ix;
+	int fs;
+	EGLPNUM_TYPE piv;
+	EGLPNUM_TYPE *t;
+	EGLPNUM_TYPE dty;
+	EGLPNUM_TYPE c_obj;
+	EGLPNUM_TYPE tz;
+}
+EGLPNUM_TYPENAME_pI_uinfo;
+
+extern void EGLPNUM_TYPENAME_ILLlp_status_info_init (
+	EGLPNUM_TYPENAME_lp_status_info * ls);
+
+/* structure for local lp information
+ * contains lp obj values - status - dimensions - input data -
+ * solution vecs - basis info - update vecs - work vecs - bound changes -
+ * tolerances - time info - statistics 
+ */
+typedef struct EGLPNUM_TYPENAME_lpinfo
+{
+
+	EGLPNUM_TYPE objval;							/* obj info */
+	EGLPNUM_TYPE pobjval;						/* intermediate status info */
+	EGLPNUM_TYPE dobjval;
+	EGLPNUM_TYPE pinfeas;
+	EGLPNUM_TYPE dinfeas;
+	EGLPNUM_TYPE objbound;
+	EGLPNUM_TYPENAME_lp_status_info probstat;			/* final status */
+	EGLPNUM_TYPENAME_lp_status_info basisstat;			/* final status */
+	int nrows;										/* input info follows; given in col format */
+	int ncols;
+	int *matcnt;
+	int *matbeg;
+	int *matind;
+	EGLPNUM_TYPE *matval;
+	int matfree;
+	int matsize;
+	EGLPNUM_TYPE *bz;
+	EGLPNUM_TYPE *lz;
+	EGLPNUM_TYPE *uz;
+	EGLPNUM_TYPE *cz;
+	int localrows;								/* set to 1 if these are created locally */
+	int *rowcnt;									/* row info follows, copy of col info */
+	int *rowbeg;
+	int *rowind;
+	EGLPNUM_TYPE *rowval;
+
+	EGLPNUM_TYPE *xbz;								/* output info x, pi, reduced cost */
+	EGLPNUM_TYPE *piz;
+	EGLPNUM_TYPE *dz;
+	EGLPNUM_TYPE *pIxbz;							/* output info (phase I) x, pi, reduced cost */
+	EGLPNUM_TYPE *pIpiz;
+	EGLPNUM_TYPE *pIdz;
+
+	int final_phase;							/* final phase, inf & unboundedness info */
+	int infub_ix;
+
+	int basisid;									/* basis and variable info follows */
+	int nnbasic;
+	int *baz;
+	int *nbaz;
+	int *vstat;
+	int *vindex;
+	int fbasisid;
+	EGLPNUM_TYPENAME_factor_work *f;
+	int *vtype;										/* internal var info */
+	char *vclass;									/* structural or logical */
+
+	EGLPNUM_TYPENAME_svector zz;										/* local EGLPNUM_TYPENAME_ILLfactor_update vectors z, yj, za */
+	EGLPNUM_TYPENAME_svector yjz;
+	EGLPNUM_TYPENAME_svector zA;
+	EGLPNUM_TYPENAME_svector work;									/* local work vector */
+	EGLPNUM_TYPENAME_svector srhs;									/* local vectors for lin. eq. solves */
+	EGLPNUM_TYPENAME_svector ssoln;
+	int *iwork;										/* local work vector */
+	EGLPNUM_TYPENAME_pI_uinfo upd;									/* phase I update info */
+	int *bfeas;										/* primal and dual infeasibility info */
+	int *dfeas;
+
+	EGLPNUM_TYPENAME_tol_struct *tol;							/* tolerances */
+	EGLPNUM_TYPENAME_count_struct *cnts;						/* counts */
+	int nbchange;									/* # bound shifts */
+	int ncchange;									/* # obj coef shifts */
+	EGLPNUM_TYPENAME_bndinfo *bchanges;						/* list of bound shifts */
+	EGLPNUM_TYPENAME_coefinfo *cchanges;						/* list of coef shifts */
+	int pIratio;									/* ratio tests */
+	int pIIratio;
+	int dIratio;
+	int dIIratio;
+
+	int maxiter;
+	int iterskip;
+	double maxtime;
+	double starttime;
+	struct EGLPNUM_TYPENAME_ILLlpdata *O;
+	ILLrandstate rstate;
+
+}
+EGLPNUM_TYPENAME_lpinfo;
+
+/* pricing structures */
+typedef struct
+{
+	int ninit;
+	EGLPNUM_TYPE *norms;
+	int *refframe;
+}
+EGLPNUM_TYPENAME_p_devex_info;
+
+typedef struct
+{
+	EGLPNUM_TYPE *norms;
+}
+EGLPNUM_TYPENAME_p_steep_info;
+
+typedef struct
+{
+	int k;
+	int cgroup;
+	int ngroups;
+	int *gstart;
+	int *gshift;
+	int *gsize;
+	int bsize;
+	int *bucket;
+	int *perm;
+	EGLPNUM_TYPE *infeas;
+}
+EGLPNUM_TYPENAME_mpart_info;
+
+typedef struct
+{
+	int ninit;
+	EGLPNUM_TYPE *norms;
+	int *refframe;
+}
+EGLPNUM_TYPENAME_d_devex_info;
+
+typedef struct
+{
+	EGLPNUM_TYPE *norms;
+}
+EGLPNUM_TYPENAME_d_steep_info;
+
+/* pricing information */
+typedef struct EGLPNUM_TYPENAME_price_info
+{
+	int p_strategy;
+	int d_strategy;
+	int pI_price;
+	int pII_price;
+	int dI_price;
+	int dII_price;
+	int cur_price;
+	EGLPNUM_TYPE *p_scaleinf;
+	EGLPNUM_TYPE *d_scaleinf;
+	EGLPNUM_TYPENAME_p_devex_info pdinfo;
+	EGLPNUM_TYPENAME_p_steep_info psinfo;
+	EGLPNUM_TYPENAME_mpart_info pmpinfo;
+	EGLPNUM_TYPENAME_d_devex_info ddinfo;
+	EGLPNUM_TYPENAME_d_steep_info dsinfo;
+	EGLPNUM_TYPENAME_mpart_info dmpinfo;
+	EGLPNUM_TYPENAME_heap h;
+	EGLPNUM_TYPE htrigger;
+	int hineff;
+	char init;
+}
+EGLPNUM_TYPENAME_price_info;
+
+#endif /* EGLPNUM_TYPENAME___QS_LPDEFS_H */
diff --git a/qsopt_ex/mps.c b/qsopt_ex/mps.c
new file mode 100644
index 0000000..65afcad
--- /dev/null
+++ b/qsopt_ex/mps.c
@@ -0,0 +1,1350 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: mps.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+
+/****************************************************************************/
+/*                                                                          */
+/*               Routines for Reading and Writing MPS Files                 */
+/*                                                                          */
+/*  EXPORTED FUNCTIONS                                                      */
+/*                                                                          */
+/*    int  ILLlpdata_mpsread (EGLPNUM_TYPENAME_ILLlpdata *lp, const char *filename);         */
+/*    int  ILLlpdata_mpswrite(EGLPNUM_TYPENAME_ILLlpdata *lp, const char *filename);         */
+/*                                                                          */
+/*  NOTES                                                                   */
+/*                                                                          */
+/*    In the MPS reader, integer variables without an explicit bound are    */
+/*    set to binary; real variables without an explict lower bound and      */
+/*    either a nonnegative or free upperbound set to nonnegative.  (These   */
+/*    are standard settings.)                                               */
+/*                                                                          */
+/*    If a RHS is not specified for a row, it is set to 0.                  */
+/*                                                                          */
+/*    The MPS reader allows CPLEX's OBJSENSE extension to specify max or    */
+/*    min and the OBJNAME extension to specify an objective row.            */
+/*                                                                          */
+/****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "eg_lpnum.h"
+#include "eg_io.h"
+
+#include "except.h"
+#include "util.h"
+#include "names.h"
+#include "mps_EGLPNUM_TYPENAME.h"
+#include "rawlp_EGLPNUM_TYPENAME.h"
+#include "lpdata_EGLPNUM_TYPENAME.h"
+//extern EGLPNUM_TYPE EGLPNUM_TYPENAME_SZERO_TOLER;
+
+
+static int TRACE = 0;
+
+const char *EGLPNUM_TYPENAME_ILLmps_section_name[ILL_MPS_N_SECTIONS + 2] = {
+	"NAME", "OBJSENSE", "OBJNAME", "ROWS", "COLUMNS",
+	"RHS", "RANGES", "BOUNDS", "REFROW", "ENDATA",
+	NULL
+};
+
+static const char *mps_bound_name[] = {
+	"LO", "UP", "FX", "FR", "MI", "PL", "BV", "UI", "LI", NULL
+};
+
+/****************************************************************************/
+/* reading 
+ */
+static int read_mps_section (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp);
+
+static int read_mps_name (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp);
+static int read_mps_refrow (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp);
+static int read_mps_objnamesense (
+	ILLmps_section sec,
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp);
+static int read_mps_objname (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state);
+static int read_mps_objsense (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp);
+
+static int read_mps_line_in_section (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp);
+
+
+static int add_row (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp);
+static int add_col (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp);
+static int add_rhs (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp);
+static int add_ranges (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp);
+static int add_bounds (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp);
+
+static int mps_read_marker_line (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp);
+static int is_marker_line (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state);
+static int mps_read_col_line (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp);
+
+static int mps_fill_in (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	const char *obj);
+
+
+static void mps_set_bound (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	int colind,
+	const char *bndtype,
+	EGLPNUM_TYPE bnd);
+
+int EGLPNUM_TYPENAME_ILLread_mps (
+	EGLPNUM_TYPENAME_qsline_reader * file,
+	const char *f,
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	int rval = 0;
+	int end = 0;
+	EGLPNUM_TYPENAME_ILLread_mps_state state;
+
+	ILL_IFTRACE ("\tread_mps\n");
+	if (ILLsymboltab_create (&lp->rowtab, 100) ||
+			ILLsymboltab_create (&lp->coltab, 100))
+	{
+		rval = 1;
+	}
+	else
+	{
+		rval = EGLPNUM_TYPENAME_ILLmps_state_init (&state, file, f);
+	}
+	if (rval != 0)
+	{
+		goto CLEANUP;
+	}
+
+	while (EGLPNUM_TYPENAME_ILLmps_next_line (&state) == 0)
+	{
+		if (EGLPNUM_TYPENAME_ILLmps_empty_key (&state))
+		{
+			if (read_mps_line_in_section (&state, lp) != 0)
+			{
+				rval++;
+			}
+		}
+		else
+		{
+			/* found a section indicator in col 1 */
+			if (!strcmp (state.key, EGLPNUM_TYPENAME_ILLmps_section_name[ILL_MPS_ENDATA]))
+			{
+				end = 1;
+				break;									/* done reading */
+			}
+			if (read_mps_section (&state, lp) != 0)
+			{
+				rval++;
+			}
+		}
+		if (rval == 50)
+		{
+			(void) EGLPNUM_TYPENAME_ILLmps_error (&state, "Too many errors.\n");
+		}
+	}
+
+	if (!end)
+	{
+		EGLPNUM_TYPENAME_ILLmps_warn (&state, "Missing ENDATA.");
+	}
+	if (!EGLPNUM_TYPENAME_ILLmps_next_line (&state))
+	{
+		EGLPNUM_TYPENAME_ILLmps_warn (&state, "Ignoring text after ENDATA.");
+	}
+	if (rval == 0)
+	{
+		rval = mps_fill_in (lp, state.obj);
+	}
+
+CLEANUP:
+	ILL_RESULT (rval, "read_mps");
+}
+
+static int check_section_order (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	int sec)
+{
+	switch (sec)
+	{
+	case ILL_MPS_REFROW:
+		if (state->section[ILL_MPS_ROWS] == 1)
+		{
+			return EGLPNUM_TYPENAME_ILLmps_error (state, "%s section after ROWS section.\n",
+													 EGLPNUM_TYPENAME_ILLmps_section_name[sec]);
+		}
+		break;
+
+	case ILL_MPS_COLS:
+	case ILL_MPS_RHS:
+	case ILL_MPS_RANGES:
+		if (state->section[ILL_MPS_ROWS] == 0)
+		{
+			return EGLPNUM_TYPENAME_ILLmps_error (state, "%s section before ROWS section.\n",
+													 EGLPNUM_TYPENAME_ILLmps_section_name[sec]);
+		};
+		break;
+
+	case ILL_MPS_BOUNDS:
+		if (state->section[ILL_MPS_COLS] == 0)
+		{
+			return EGLPNUM_TYPENAME_ILLmps_error (state, "%s section before COLUMNS section.\n",
+													 EGLPNUM_TYPENAME_ILLmps_section_name[sec]);
+		}
+		break;
+	}
+	return 0;
+}
+
+static int read_mps_section (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	int sec;
+	int rval = 0, r;
+
+	ILL_FAILtrue (EGLPNUM_TYPENAME_ILLmps_empty_key (state), "must have a key on this line");
+
+	sec = ILLutil_index (EGLPNUM_TYPENAME_ILLmps_section_name, state->key);
+	if (sec < 0)
+	{
+		return EGLPNUM_TYPENAME_ILLmps_error (state, "\"%s\" is not a key.\n", state->key);
+	}
+	rval = EGLPNUM_TYPENAME_ILLmps_set_section (state, sec);
+
+	state->active = ILL_MPS_NONE;
+	rval = rval || check_section_order (state, sec);
+	switch (sec)
+	{
+	case ILL_MPS_COLS:
+	case ILL_MPS_ROWS:
+		state->active = sec;
+		break;
+
+	case ILL_MPS_NAME:
+		if (rval == 0)
+		{
+			rval = read_mps_name (state, lp);
+		}
+		break;
+
+	case ILL_MPS_RHS:
+		if (rval == 0)
+		{
+			rval = EGLPNUM_TYPENAME_ILLraw_init_rhs (lp);
+		}
+		state->active = ILL_MPS_RHS;
+		break;
+
+	case ILL_MPS_RANGES:
+		if (rval == 0)
+		{
+			rval = EGLPNUM_TYPENAME_ILLraw_init_ranges (lp);
+		}
+		state->active = ILL_MPS_RANGES;
+		break;
+
+	case ILL_MPS_BOUNDS:
+		if (rval == 0)
+		{
+			rval = EGLPNUM_TYPENAME_ILLraw_init_bounds (lp);
+		}
+		state->active = ILL_MPS_BOUNDS;
+		break;
+
+	case ILL_MPS_OBJNAME:
+	case ILL_MPS_OBJSENSE:
+		r = read_mps_objnamesense (sec, state, lp);
+		rval = r || rval;
+		break;
+
+	case ILL_MPS_REFROW:
+		r = read_mps_refrow (state, lp);
+		rval = r || rval;
+		break;
+
+	default:
+		ILL_REPRT ("should never get here");
+		goto CLEANUP;
+	}
+CLEANUP:
+	ILL_RESULT (rval, "read_mps_section");
+}
+
+static int read_mps_name (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	int rval = 0;
+
+	if (EGLPNUM_TYPENAME_ILLmps_empty_field (state))
+	{
+		EGLPNUM_TYPENAME_ILLmps_warn (state, "Blank NAME.");
+	}
+	else
+	{
+		ILL_UTIL_STR (lp->name, state->field);
+	}
+CLEANUP:
+	ILL_RESULT (rval, "read_mps_name");
+}
+
+static int read_mps_refrow (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	int rval = 0;
+
+	rval = EGLPNUM_TYPENAME_ILLmps_next_line (state);
+	if (state->section[ILL_MPS_REFROW] > 1)
+	{
+		/* this is the second time we see this section; 
+		 * don't complain about errors */
+		return 0;
+	}
+	if (EGLPNUM_TYPENAME_ILLmps_empty_key (state) && !EGLPNUM_TYPENAME_ILLmps_empty_field (state))
+	{
+		ILL_UTIL_STR (lp->refrow, state->field);
+		return 0;
+	}
+	else
+	{
+		return EGLPNUM_TYPENAME_ILLmps_error (state, "Bad row name in REFROW section.\n");
+	}
+CLEANUP:
+	ILL_RETURN (rval, "read_mps_refrow");
+}
+
+static int read_mps_objnamesense (
+	ILLmps_section sec,
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	if (state->section[sec] > 1)
+	{
+		/* this is the second time we see this section; just skip next line */
+		(void) EGLPNUM_TYPENAME_ILLmps_next_line (state);
+		return 0;
+	}
+	if (EGLPNUM_TYPENAME_ILLmps_next_line (state) != 0)
+	{
+		return EGLPNUM_TYPENAME_ILLmps_error (state, "Missing %s line at end of file.\n",
+												 EGLPNUM_TYPENAME_ILLmps_section_name[sec]);
+	}
+	if ((!EGLPNUM_TYPENAME_ILLmps_empty_key (state)) || EGLPNUM_TYPENAME_ILLmps_empty_field (state))
+	{
+		(void) EGLPNUM_TYPENAME_ILLmps_error (state, "Bad %s in %s record.\n",
+												 ((sec == ILL_MPS_OBJNAME) ? "row name"
+													: "objective sense"), EGLPNUM_TYPENAME_ILLmps_section_name[sec]);
+		if (!EGLPNUM_TYPENAME_ILLmps_empty_key (state))
+		{
+			(void) read_mps_section (state, lp);
+		}
+		return 1;
+	}
+	if (sec == ILL_MPS_OBJNAME)
+	{
+		if (read_mps_objname (state))
+		{
+			return 1;
+		}
+	}
+	else
+	{
+		if (read_mps_objsense (state, lp) != 0)
+		{
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static int read_mps_objsense (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	int rval = 0;
+	char *objsense = state->field;
+
+	ILL_FAILfalse (state->section[ILL_MPS_OBJSENSE] == 1, "should never happen");
+	if (!strcmp (objsense, "MAX") ||
+			!strcmp (objsense, "Max") ||
+			!strcmp (objsense, "max") ||
+			!strcmp (objsense, "MAXIMIZE") ||
+			!strcmp (objsense, "Maximize") || !strcmp (objsense, "maximize"))
+	{
+		lp->objsense = EGLPNUM_TYPENAME_ILL_MAX;
+	}
+	else if (!strcmp (objsense, "MIN") ||
+					 !strcmp (objsense, "Min") ||
+					 !strcmp (objsense, "min") ||
+					 !strcmp (objsense, "MINIMIZE") ||
+					 !strcmp (objsense, "Minimize") || !strcmp (objsense, "minimize"))
+	{
+		lp->objsense = EGLPNUM_TYPENAME_ILL_MIN;
+	}
+	else
+	{
+		return EGLPNUM_TYPENAME_ILLmps_error (state, "\"%s\" is no OBJSENSE.\n", objsense);
+	}
+CLEANUP:
+	ILL_RESULT (rval, "read_mps_objsense");
+}
+
+static int read_mps_objname (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state)
+{
+	int rval = 0;
+
+	ILL_FAILfalse (state->section[ILL_MPS_OBJNAME] == 1, "should never happen");
+	ILL_UTIL_STR (state->obj, state->field);
+CLEANUP:
+	ILL_RETURN (rval, "read_mps_objname");
+}
+
+static int read_mps_line_in_section (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	int rval = 0;
+
+	ILL_FAILtrue (!EGLPNUM_TYPENAME_ILLmps_empty_key (state) || EGLPNUM_TYPENAME_ILLmps_empty_field (state),
+								"no key but at least one field on state->line");
+
+	if (state->active == ILL_MPS_NONE)
+	{
+		return EGLPNUM_TYPENAME_ILLmps_error (state, "Line is in no section.\n");
+	}
+	else
+	{
+		if (state->section[state->active] == 1)
+		{
+			switch (state->active)
+			{
+			case ILL_MPS_ROWS:
+				rval = add_row (state, lp);
+				break;
+			case ILL_MPS_COLS:
+				rval = add_col (state, lp);
+				break;
+			case ILL_MPS_RHS:
+				rval = add_rhs (state, lp);
+				break;
+			case ILL_MPS_RANGES:
+				rval = add_ranges (state, lp);
+				break;
+			case ILL_MPS_BOUNDS:
+				rval = add_bounds (state, lp);
+				break;
+			default:
+				ILL_REPRT ("should never get here");
+				ILL_CLEANUP;
+			}
+			if (rval == 0)
+			{
+				/* see whether there are extra fields on line */
+				EGLPNUM_TYPENAME_ILLmps_check_end_of_line (state);
+			}
+		}
+	}
+CLEANUP:
+	ILL_RESULT (rval, "read_mps_line_in_section");
+}
+
+static int add_row (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	int ind, hit, rval = 0;
+	char sense;
+
+	ILL_FAILtrue (!EGLPNUM_TYPENAME_ILLmps_empty_key (state) || EGLPNUM_TYPENAME_ILLmps_empty_field (state),
+								"no key but at least one field on state->line");
+
+	/* field should contain exactly one character */
+	if (state->field[1] == '\0')
+	{
+		sense = state->field[0];
+		if (sense != 'L' && sense != 'G' && sense != 'E' && sense != 'N')
+		{
+			return EGLPNUM_TYPENAME_ILLmps_error (state,
+													 "Unknown rowsense '%c' in ROWS record.\n", sense);
+		}
+		if (EGLPNUM_TYPENAME_ILLmps_next_field (state) == 0)
+		{
+			hit = ILLsymboltab_lookup (&lp->rowtab, state->field, &ind);
+			if (!hit)
+			{
+				rval = EGLPNUM_TYPENAME_ILLmps_error (state,
+														 "Repeated row definition for \"%s\".\n",
+														 state->field);
+			}
+			else
+			{
+				rval = EGLPNUM_TYPENAME_ILLraw_add_row (lp, state->field, sense, EGLPNUM_TYPENAME_zeroLpNum);	/* default rhs is 0.0 */
+			}
+		}
+		else
+		{
+			rval = EGLPNUM_TYPENAME_ILLmps_error (state, "Missing rowname in ROWS record.\n");
+		}
+	}
+	else
+	{
+		rval = EGLPNUM_TYPENAME_ILLmps_error (state, "Unknown rowsense '%s' in ROWS record.\n",
+												 state->field);
+	}
+CLEANUP:
+	ILL_RESULT (rval, "add_row");
+}
+
+static int add_col (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	int rval = 0;
+
+	ILL_FAILtrue (!EGLPNUM_TYPENAME_ILLmps_empty_key (state) || EGLPNUM_TYPENAME_ILLmps_empty_field (state),
+								"no key but at least one field on state->line");
+
+	if (is_marker_line (state))
+	{
+		return mps_read_marker_line (state, lp);
+	}
+	else
+	{
+		return mps_read_col_line (state, lp);
+	}
+CLEANUP:
+	ILL_RETURN (rval, "add_col");
+}
+
+static int mps_read_col_line (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	int hit, colind, rowind, rval = 0, more, ind;
+	EGLPNUM_TYPE ncoef;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (ncoef);
+
+	ILL_FAILtrue (!EGLPNUM_TYPENAME_ILLmps_empty_key (state) || EGLPNUM_TYPENAME_ILLmps_empty_field (state),
+								"no key but at least one field on state->line");
+
+	hit = ILLsymboltab_lookup (&lp->coltab, state->field, &colind);
+	if (hit)
+	{
+		rval = EGLPNUM_TYPENAME_ILLraw_add_col (lp, state->field, state->intvar);
+		ILL_CLEANUP_IF (rval);
+		colind = lp->ncols - 1;
+	}
+	else
+	{
+		if (state->intvar)
+		{
+			/*previously declared variable is in integer section */
+			lp->intmarker[colind] = 1;
+		}
+	}
+#ifndef NDEBUG
+	hit = ILLsymboltab_lookup (&lp->coltab, state->field, &ind);
+	ILL_FAILfalse (colind == ind, "colind should be index of state->field");
+#endif
+	if (state->sosvar == 1)
+	{
+		if (EGLPNUM_TYPENAME_ILLraw_is_mem_other_sos (lp, colind))
+		{
+			rval = EGLPNUM_TYPENAME_ILLmps_error (state,
+													 "\"%s\" is a member of SOS set #%d.\n",
+													 EGLPNUM_TYPENAME_ILLraw_colname (lp, colind),
+													 lp->is_sos_member[colind] + 1);
+		}
+		else
+		{
+			rval = EGLPNUM_TYPENAME_ILLraw_add_sos_member (lp, colind);
+		}
+		ILL_CLEANUP_IF (rval);
+	}
+
+	more = (EGLPNUM_TYPENAME_ILLmps_next_field (state) == 0);
+	if (!more)
+	{
+		return EGLPNUM_TYPENAME_ILLmps_error (state, "Missing fields in COLUMNS record.\n");
+	}
+	for (more = 1; more; more = (EGLPNUM_TYPENAME_ILLmps_next_field (state) == 0))
+	{
+		hit = ILLsymboltab_lookup (&lp->rowtab, state->field, &rowind);
+		if (hit)
+		{
+			return EGLPNUM_TYPENAME_ILLmps_error (state, "\"%s\" is not a row name.\n", state->field);
+		}
+		if (EGLPNUM_TYPENAME_ILLmps_next_coef (state, &ncoef) != 0)
+		{
+			return EGLPNUM_TYPENAME_ILLmps_error (state,
+													 "Missing/Bad coefficient in COLUMNS record.\n");
+		}
+		rval = EGLPNUM_TYPENAME_ILLraw_add_col_coef (lp, colind, rowind, ncoef);
+	}
+CLEANUP:
+	EGLPNUM_TYPENAME_EGlpNumClearVar (ncoef);
+	ILL_RESULT (rval, "mps_read_col_line");
+}
+
+static int is_marker_line (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state)
+{
+	const char *field = state->line;
+
+	while ((field = ILLutil_strchr (field, '\'')))
+	{
+		if (strncmp (field, "'MARKER'", (size_t) 8) == 0)
+		{
+			return 1;
+		}
+		while ((!EGLPNUM_TYPENAME_ILL_ISBLANK (field)) && (*field != '\0'))
+		{
+			field++;
+		}
+	}
+	return 0;
+}
+
+static int mps_read_marker_line (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	int rval = 0;
+	int sos_type = EGLPNUM_TYPENAME_ILL_SOS_TYPE1;
+	int sos_line = 0;
+	int cur_sos_mode = state->sosvar;
+
+	if (strcmp (state->field, "S2") == 0)
+	{
+		sos_type = EGLPNUM_TYPENAME_ILL_SOS_TYPE2;
+		sos_line = 1;
+	}
+	else if (strcmp (state->field, "S1") == 0)
+	{
+		sos_line = 1;
+	}
+	if (sos_line)
+	{
+		rval = EGLPNUM_TYPENAME_ILLmps_next_field (state);
+	}
+	rval = rval || EGLPNUM_TYPENAME_ILLmps_next_field (state);	/* swallow marker-id */
+	if (strcmp (state->field, "'MARKER'"))
+	{
+		return EGLPNUM_TYPENAME_ILLmps_error (state, "Bad 'MARKER' line.\n");
+	}
+	if (EGLPNUM_TYPENAME_ILLmps_next_field (state))
+	{
+		return EGLPNUM_TYPENAME_ILLmps_error (state, "Missing field on 'MARKER' line.\n");
+	}
+	rval = EGLPNUM_TYPENAME_ILLmps_int_sos_mode (state);
+	if (rval == 0)
+	{
+		if (cur_sos_mode != state->sosvar)
+		{
+			if (state->sosvar)
+			{
+				/* beginning of a new set */
+				rval = EGLPNUM_TYPENAME_ILLraw_add_sos (lp, sos_type);
+			}
+		}
+	}
+	ILL_RESULT (rval, "mps_read_marker_line");
+}
+
+static int add_rhs (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	int rowind, more_fields, skip;
+	const char *rhsname;
+	EGLPNUM_TYPE rhs;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (rhs);
+
+	rhsname = EGLPNUM_TYPENAME_ILLmps_possibly_blank_name (state->field, state, &lp->rowtab);
+	if (EGLPNUM_TYPENAME_ILLraw_set_rhs_name (lp, rhsname, &skip))
+	{
+		EGLPNUM_TYPENAME_ILLmps_error (state, "Could not add right hand side.\n");
+	}
+
+	if (skip)
+	{
+		EGLPNUM_TYPENAME_ILLmps_set_end_of_line (state);	/* to avoid warning about extra fields */
+	}
+	else
+	{
+		if (strcmp (rhsname, " "))
+		{
+			/* field is non blank rhs name; advance to row name  */
+			if (EGLPNUM_TYPENAME_ILLmps_next_field (state))
+			{
+				return EGLPNUM_TYPENAME_ILLmps_error (state, "Missing row name in RHS record.\n");
+			}
+		}
+		for (more_fields = 1; more_fields; more_fields = !EGLPNUM_TYPENAME_ILLmps_next_field (state))
+		{
+			if (ILLsymboltab_lookup (&lp->rowtab, state->field, &rowind))
+			{
+				return EGLPNUM_TYPENAME_ILLmps_error (state, "\"%s\" is not a row name.\n",
+														 state->field);
+			}
+			if (EGLPNUM_TYPENAME_ILLmps_next_coef (state, &rhs))
+			{
+				return EGLPNUM_TYPENAME_ILLmps_error (state, "Missing/Bad coefficient in RHS record.\n");
+			}
+			if (lp->rhsind[rowind])
+			{
+				return EGLPNUM_TYPENAME_ILLmps_error (state, "Two rhs values for row \"%s\".\n",
+														 state->field);
+			}
+			else
+			{
+				if (lp->rowsense[rowind] == 'N')
+				{
+					EGLPNUM_TYPENAME_ILLmps_warn (state,
+											 "Ignoring right hand side for N-row \"%s\".",
+											 EGLPNUM_TYPENAME_ILLraw_rowname (lp, rowind));
+				}
+				else
+				{
+					EGLPNUM_TYPENAME_EGlpNumCopy (lp->rhs[rowind], rhs);
+					lp->rhsind[rowind] = 1;
+				}
+			}
+		}
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (rhs);
+	return 0;
+}
+
+static int add_bounds (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	char bndtype[3];
+	const char *bounds_name;
+	int colind, skip, rval = 0;
+	EGLPNUM_TYPE bnd;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (bnd);
+
+	ILL_FAILtrue (!EGLPNUM_TYPENAME_ILLmps_empty_key (state) || EGLPNUM_TYPENAME_ILLmps_empty_field (state),
+								"no key but at least one field on state->line");
+
+	if (ILLutil_index (mps_bound_name, state->field) < 0)
+	{
+		return EGLPNUM_TYPENAME_ILLmps_error (state, "\"%s\" is not a BOUNDS type.\n", state->field);
+	}
+	strcpy (bndtype, state->field);
+
+	if (EGLPNUM_TYPENAME_ILLmps_next_field (state) != 0)
+	{
+		return EGLPNUM_TYPENAME_ILLmps_error (state,
+												 "No bounds/column identifier in BOUNDS record.\n");
+	}
+
+	bounds_name = EGLPNUM_TYPENAME_ILLmps_possibly_blank_name (state->field, state, &lp->coltab);
+	if (bounds_name == NULL)
+	{
+		return 1;
+	}
+	if (EGLPNUM_TYPENAME_ILLraw_set_bounds_name (lp, bounds_name, &skip))
+	{
+		return 1;
+	}
+	if (skip)
+	{
+		EGLPNUM_TYPENAME_ILLmps_set_end_of_line (state);	/* to avoid warning about extra fields */
+	}
+	else
+	{
+		if (strcmp (bounds_name, " "))
+		{
+			/* non empty bounds_name ==> advance to col name field */
+			if (EGLPNUM_TYPENAME_ILLmps_next_field (state))
+			{
+				return EGLPNUM_TYPENAME_ILLmps_error (state, "Missing column field in BOUNDS record.\n");
+			}
+		}
+		if (ILLsymboltab_lookup (&lp->coltab, state->field, &colind))
+		{
+			return EGLPNUM_TYPENAME_ILLmps_error (state, "\"%s\" is not a column name.\n",
+													 state->field);
+		}
+		EGLPNUM_TYPENAME_EGlpNumZero (bnd);
+		if (strcmp (bndtype, "FR") && strcmp (bndtype, "BV") &&
+				strcmp (bndtype, "MI") && strcmp (bndtype, "PL"))
+		{
+			/* neither "FR", "BV", "MI" nor "PL" ==> there should be a bound */
+			if (EGLPNUM_TYPENAME_ILLmps_next_bound (state, &bnd))
+			{
+				return EGLPNUM_TYPENAME_ILLmps_error (state,
+														 "Missing/Bad bound field in BOUNDS record.\n");
+			}
+		}
+		mps_set_bound (lp, state, colind, bndtype, bnd);
+	}
+CLEANUP:
+	EGLPNUM_TYPENAME_EGlpNumClearVar (bnd);
+	ILL_RESULT (rval, "add_bounds");
+}
+
+static void mps_set_bound (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	int colind,
+	const char *bndtype,
+	EGLPNUM_TYPE bnd)
+{
+	const char *msg = NULL;
+
+	if (!strcmp (bndtype, "LO"))
+	{
+		msg = EGLPNUM_TYPENAME_ILLraw_set_lowerBound (lp, colind, bnd);
+	}
+	else if (!strcmp (bndtype, "UP"))
+	{
+		msg = EGLPNUM_TYPENAME_ILLraw_set_upperBound (lp, colind, bnd);
+	}
+	else if (!strcmp (bndtype, "FX"))
+	{
+		msg = EGLPNUM_TYPENAME_ILLraw_set_fixedBound (lp, colind, bnd);
+	}
+	else if (!strcmp (bndtype, "FR"))
+	{
+		msg = EGLPNUM_TYPENAME_ILLraw_set_unbound (lp, colind);
+	}
+	else if (!strcmp (bndtype, "BV"))
+	{
+		msg = EGLPNUM_TYPENAME_ILLraw_set_binaryBound (lp, colind);
+		if (msg == NULL)
+		{
+			lp->intmarker[colind] = 1;
+		}
+	}
+	else if (!strcmp (bndtype, "UI"))
+	{
+		msg = EGLPNUM_TYPENAME_ILLraw_set_upperBound (lp, colind, bnd);
+		if (msg == NULL)
+		{
+			lp->intmarker[colind] = 1;
+		}
+	}
+	else if (!strcmp (bndtype, "LI"))
+	{
+		msg = EGLPNUM_TYPENAME_ILLraw_set_lowerBound (lp, colind, bnd);
+		if (msg == NULL)
+		{
+			lp->intmarker[colind] = 1;
+		}
+	}
+	else if (!strcmp (bndtype, "MI"))
+	{
+		msg = EGLPNUM_TYPENAME_ILLraw_set_lowerBound (lp, colind, EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+	}
+	else if (!strcmp (bndtype, "PL"))
+	{
+		msg = EGLPNUM_TYPENAME_ILLraw_set_upperBound (lp, colind, EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+	}
+	else
+	{
+		ILL_REPRT ("should never get here");
+		ILL_CLEANUP;
+	}
+	EGLPNUM_TYPENAME_ILLmps_warn (state, msg);
+CLEANUP:
+	return;
+}
+
+static int add_ranges (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	const char *rangesname;
+	int skip, more_fields, rowind;
+	EGLPNUM_TYPE ntmp;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (ntmp);
+
+	rangesname = EGLPNUM_TYPENAME_ILLmps_possibly_blank_name (state->field, state, &lp->rowtab);
+	if (EGLPNUM_TYPENAME_ILLraw_set_ranges_name (lp, rangesname, &skip))
+	{
+		return EGLPNUM_TYPENAME_ILLmps_error (state, "Could not add range.\n");
+	}
+	if (skip)
+	{
+		EGLPNUM_TYPENAME_ILLmps_set_end_of_line (state);	/* to avoid warning about extra fields */
+	}
+	else
+	{
+		if (strcmp (rangesname, " "))
+		{
+			/* field is non blank ranges name; advance to row name */
+			if (EGLPNUM_TYPENAME_ILLmps_next_field (state))
+			{
+				return EGLPNUM_TYPENAME_ILLmps_error (state, "Missing row name in RANGES record.");
+			}
+		}
+		for (more_fields = 1; more_fields; more_fields = !EGLPNUM_TYPENAME_ILLmps_next_field (state))
+		{
+			if (ILLsymboltab_lookup (&lp->rowtab, state->field, &rowind))
+			{
+				return EGLPNUM_TYPENAME_ILLmps_error (state, "\"%s\" is not a row name.\n",
+														 state->field);
+			}
+			if (EGLPNUM_TYPENAME_ILLmps_next_coef (state, &ntmp))
+			{
+				return EGLPNUM_TYPENAME_ILLmps_error (state,
+														 "Missing/Bad coefficient in RANGES record.\n");
+			}
+			if (lp->rangesind[rowind])
+			{
+				EGLPNUM_TYPENAME_ILLmps_warn (state, "Ignoring second RANGE value %s \"%s\".",
+										 "for row", EGLPNUM_TYPENAME_ILLraw_rowname (lp, rowind));
+			}
+			else
+			{
+				if (lp->rowsense[rowind] != 'N')
+				{
+					if (EGLPNUM_TYPENAME_ILLraw_add_ranges_coef (lp, rowind, ntmp))
+						return 1;
+				}
+				else
+				{
+					EGLPNUM_TYPENAME_ILLmps_warn (state, "Ignoring RANGE value for N-row \"%s\".",
+											 EGLPNUM_TYPENAME_ILLraw_rowname (lp, rowind));
+				}
+			}
+		}
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+	return 0;
+}
+
+
+static int mps_fill_in (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	const char *obj)
+{
+	int i, hit, rval = 0;
+
+	/* find the objective function -- the first N row if obj is not defined  */
+	if (obj)
+	{
+		hit = ILLsymboltab_lookup (&lp->rowtab, obj, &lp->objindex);
+		if (hit)
+		{
+			return EGLPNUM_TYPENAME_ILLdata_error (lp->error_collector,
+														"Bad objective name \"%s\".\n", obj);
+		}
+		else if (lp->rowsense[lp->objindex] != 'N')
+		{
+			EGLPNUM_TYPENAME_ILLdata_warn (lp->error_collector,
+										"Making objective row \"%s\" a N-row.", obj);
+		}
+		lp->rowsense[lp->objindex] = 'N';
+	}
+	else
+	{
+		for (i = 0; i < lp->nrows; i++)
+		{
+			if (lp->rowsense[i] == 'N')
+			{
+				lp->objindex = i;
+				break;
+			}
+		}
+		if (i == lp->nrows)
+		{
+			return EGLPNUM_TYPENAME_ILLdata_error (lp->error_collector,
+														"No N-row in lp definition.\n");
+		}
+	}
+
+	if (lp->ncols > 0)
+	{
+		rval = EGLPNUM_TYPENAME_ILLraw_fill_in_bounds (lp);
+	}
+
+	/* set weights of sos set members */
+	if (lp->refrow)
+	{
+		/* take the values from refrow */
+		EGLPNUM_TYPE weight;
+		EGLPNUM_TYPENAME_colptr *cp;
+
+		EGLPNUM_TYPENAME_EGlpNumInitVar (weight);
+
+		hit = ILLsymboltab_lookup (&lp->rowtab, lp->refrow, &lp->refrowind);
+		if (hit)
+		{
+			return EGLPNUM_TYPENAME_ILLdata_error (lp->error_collector,
+														"REFROW \"%s\" is not a row name.\n", lp->refrow);
+		}
+		for (i = 0; i < lp->nsos_member; i++)
+		{
+			for (cp = lp->cols[lp->sos_col[i]]; cp != NULL; cp = cp->next)
+			{
+				if (cp->this_val == lp->refrowind)
+					break;
+			}
+			if ((cp != NULL) && EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (cp->coef))
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (weight, cp->coef);
+			}
+			else
+			{
+				EGLPNUM_TYPENAME_ILLdata_warn (lp->error_collector,
+											"\"%s\" has 0.0 coefficient in REFROW \"%s\".",
+											EGLPNUM_TYPENAME_ILLraw_colname (lp, lp->sos_col[i]), lp->refrow);
+				EGLPNUM_TYPENAME_EGlpNumZero (weight);
+			}
+			EGLPNUM_TYPENAME_EGlpNumCopy (lp->sos_weight[i], weight);
+		}
+		EGLPNUM_TYPENAME_EGlpNumClearVar (weight);
+	}
+	else
+	{															/* no refrow */
+		/* set weights to 1, 2, 3, ... in order of definition */
+		int si, w;
+		EGLPNUM_TYPENAME_sosptr *set;
+
+		for (si = 0; si < lp->nsos; si++)
+		{
+			set = lp->sos_set + si;
+			w = 1;
+			for (i = set->first; i < set->first + set->nelem; i++)
+			{
+				EGLPNUM_TYPENAME_EGlpNumSet (lp->sos_weight[i], (double) w);
+				w++;
+			}
+		}
+	}
+	ILL_IFTRACE ("bound %lf <= x1 <= %lf\n", EGLPNUM_TYPENAME_EGlpNumToLf (lp->lower[0]),
+							 EGLPNUM_TYPENAME_EGlpNumToLf (lp->upper[0]));
+	ILL_IFTRACE ("MAXDOUBLE %lf MINDOUBLE %lf\n", EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_ILL_MAXDOUBLE),
+							 EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_ILL_MINDOUBLE));
+	ILL_RESULT (rval, "mps_fill_in");
+}
+
+/****************************************************************************/
+/* writing 
+ */
+
+static int mps_write_col (
+	int i,
+	int iorig,
+	char *colname,
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	char **rownames,
+	int intmode,
+	char *objname);
+
+int EGLPNUM_TYPENAME_ILLwrite_mps (
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	EGLPNUM_TYPENAME_qserror_collector * collector)
+{
+	int rval = 0;
+	int marker = 0;
+	int intmode = 0;
+	int i, ri, set, el, empty, prtLower, prtUpper;
+	char **colnames = (char **) NULL;
+	char **rownames = (char **) NULL;
+	EGLPNUM_TYPENAME_ILLlp_rows lp_rows, *lprows = NULL;
+	char buf[ILL_namebufsize];
+	char *objname = NULL;
+	char *str;
+
+	ILL_CHECKnull (lp, "lp must not be null");
+	ILL_FAILtrue (lp->probname == NULL, "oops should never happen");
+
+	ILL_FAILfalse (lp->colnames != NULL, "colnames != NULL");
+	ILL_FAILfalse (lp->rownames != NULL, "colnames != NULL");
+	colnames = lp->colnames;
+	rownames = lp->rownames;
+
+	objname = lp->objname;
+	if (objname == (char *) NULL)
+	{
+		strcpy (buf, "obj");
+		rval = ILLsymboltab_uname (&lp->rowtab, buf, "", NULL);
+		ILL_CLEANUP_IF (rval);
+		ILL_UTIL_STR (objname, buf);
+	}
+	EGLPNUM_TYPENAME_ILLprint_report (lp, "NAME    %s\n", lp->probname);
+	EGLPNUM_TYPENAME_ILLprint_report (lp, "OBJSENSE\n  %s\n",
+									 (lp->objsense == EGLPNUM_TYPENAME_ILL_MIN) ? "MIN" : "MAX");
+	EGLPNUM_TYPENAME_ILLprint_report (lp, "OBJNAME\n  %s\n", objname);
+	if (lp->refrowname)
+	{
+		EGLPNUM_TYPENAME_ILLprint_report (lp, "REFROW\n");
+		EGLPNUM_TYPENAME_ILLprint_report (lp, " %s\n", lp->refrowname);
+	}
+
+
+	EGLPNUM_TYPENAME_ILLprint_report (lp, "ROWS\n");
+	EGLPNUM_TYPENAME_ILLprint_report (lp, " N  %s\n", objname);
+	if (lp->refrowname && (lp->refind == -1))
+	{
+		EGLPNUM_TYPENAME_ILLprint_report (lp, " N  %s\n", lp->refrowname);
+	}
+
+	lprows = &lp_rows;
+	rval = EGLPNUM_TYPENAME_ILLlp_rows_init (lprows, lp, 0);
+	ILL_CLEANUP_IF (rval);
+	for (i = 0; i < lp->nrows; i++)
+	{
+		if (lprows->rowcnt[i] == 0)
+		{
+			EGLPNUM_TYPENAME_ILLdata_warn (collector,
+										"Deleting empty row \"%s\" from constraints.", rownames[i]);
+			continue;
+		}
+		switch (lp->sense[i])
+		{
+		case 'G':
+			EGLPNUM_TYPENAME_ILLprint_report (lp, " G  ");
+			break;
+		case 'L':
+			EGLPNUM_TYPENAME_ILLprint_report (lp, " L  ");
+			break;
+		case 'E':
+			EGLPNUM_TYPENAME_ILLprint_report (lp, " E  ");
+			break;
+		case 'R':
+			EGLPNUM_TYPENAME_ILLprint_report (lp, " G  ");
+			break;
+		}
+		EGLPNUM_TYPENAME_ILLprint_report (lp, "%s\n", rownames[i]);
+	}
+
+	EGLPNUM_TYPENAME_ILLprint_report (lp, "COLUMNS\n");
+	for (set = 0; set < lp->sos.matcols; set++)
+	{
+		ILL_FAILtrue (lp->sos_type == NULL, "must have non NULL sos_type");
+		ILL_FAILtrue (lp->is_sos_mem == NULL, "must have non NULL is_sos_mem");
+		empty = 1;
+		for (el = lp->sos.matbeg[set];
+				 el < lp->sos.matbeg[set] + lp->sos.matcnt[set]; el++)
+		{
+			if (empty)
+			{
+				EGLPNUM_TYPENAME_ILLprint_report (lp, " %s SOS%dqs    'MARKER'    'SOSORG'\n",
+												 ((lp->sos_type[set] == EGLPNUM_TYPENAME_ILL_SOS_TYPE1)) ? "S1" : "S2",
+												 marker++);
+				empty = 0;
+			}
+			ri = lp->sos.matind[el];
+			i = lp->structmap[ri];
+			intmode = mps_write_col (i, ri, colnames[ri], lp, rownames,
+															 intmode, objname);
+			if (lp->refrowname && (lp->refind == -1))
+			{
+				EGLPNUM_TYPENAME_ILLprint_report (lp, "  %s    %s    %g\n",
+												 colnames[ri], lp->refrowname, lp->sos.matval[el]);
+			}
+		}
+		if (!empty)
+		{
+			EGLPNUM_TYPENAME_ILLprint_report (lp, " SOS%dqs       'MARKER'    'SOSEND'\n", marker++);
+		}
+	}
+	for (ri = 0; ri < lp->nstruct; ri++)
+	{
+		if (lp->is_sos_mem == (int *) NULL || lp->is_sos_mem[ri] == -1)
+		{
+			i = lp->structmap[ri];
+			intmode = mps_write_col (i, ri, colnames[ri], lp, rownames,
+															 intmode, objname);
+		}
+	}
+	if (intmode)
+	{
+		EGLPNUM_TYPENAME_ILLprint_report (lp, " MARK%dqs      'MARKER'    'INTEND'\n", lp->nstruct);
+	}
+
+	EGLPNUM_TYPENAME_ILLprint_report (lp, "RHS\n");
+	for (i = 0; i < lp->nrows; i++)
+	{
+		if ((lprows->rowcnt[i] != 0) && EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (lp->rhs[i]))
+		{
+			str = EGLPNUM_TYPENAME_EGlpNumGetStr(lp->rhs[i]);
+			EGLPNUM_TYPENAME_ILLprint_report (lp, " RHS    %s    %s\n", rownames[i], str);
+			EGfree(str);
+		}
+	}
+
+	if (lp->rangeval)
+	{
+		EGLPNUM_TYPENAME_ILLprint_report (lp, "RANGES\n");
+		for (i = 0; i < lp->nrows; i++)
+		{
+			if ((lprows->rowcnt[i] != 0) && EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (lp->rangeval[i]))
+			{
+				str = EGLPNUM_TYPENAME_EGlpNumGetStr(lp->rangeval[i]);
+				EGLPNUM_TYPENAME_ILLprint_report (lp, " RANGE    %s    %s\n", rownames[i], str);
+				EGfree(str);
+			}
+		}
+	}
+
+	ri = EGLPNUM_TYPENAME_ILLraw_first_nondefault_bound (lp);
+	if (ri != lp->nstruct)
+	{
+		EGLPNUM_TYPENAME_ILLprint_report (lp, "BOUNDS\n");
+		for (; ri < lp->nstruct; ri++)
+		{
+			i = lp->structmap[ri];
+			if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (lp->lower[i], lp->upper[i]))
+			{
+				str = EGLPNUM_TYPENAME_EGlpNumGetStr(lp->lower[i]);
+				EGLPNUM_TYPENAME_ILLprint_report (lp, " FX BOUND    %s    %s\n", colnames[ri], str);
+				EGfree(str);
+				continue;
+			}
+			if ((EGLPNUM_TYPENAME_EGlpNumIsEqqual (lp->lower[i], EGLPNUM_TYPENAME_ILL_MINDOUBLE)) &&
+					(EGLPNUM_TYPENAME_EGlpNumIsEqqual (lp->upper[i], EGLPNUM_TYPENAME_ILL_MAXDOUBLE)))
+			{
+				EGLPNUM_TYPENAME_ILLprint_report (lp, " FR BOUND    %s\n", colnames[ri]);
+				continue;
+			}
+			prtLower = !EGLPNUM_TYPENAME_ILLraw_default_lower (lp, i);
+			prtUpper = !EGLPNUM_TYPENAME_ILLraw_default_upper (lp, i, ri);
+			if (prtLower)
+			{
+				if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (lp->lower[i], EGLPNUM_TYPENAME_ILL_MINDOUBLE))
+				{
+					EGLPNUM_TYPENAME_ILLprint_report (lp, " MI BOUND    %s\n", colnames[ri]);
+				}
+				else
+				{
+					str = EGLPNUM_TYPENAME_EGlpNumGetStr(lp->lower[i]);
+					EGLPNUM_TYPENAME_ILLprint_report (lp, " LO BOUND    %s    %s\n", colnames[ri], str);
+					EGfree(str);
+				}
+			}
+			if (prtUpper)
+			{
+				if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (lp->upper[i], EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+				{
+					EGLPNUM_TYPENAME_ILLprint_report (lp, " PL BOUND    %s\n", colnames[ri]);
+				}
+				else
+				{
+					str = EGLPNUM_TYPENAME_EGlpNumGetStr(lp->upper[i]);
+					EGLPNUM_TYPENAME_ILLprint_report (lp, " UP BOUND    %s    %s\n", colnames[ri], str);
+					EGfree(str);
+				}
+			}
+		}
+	}
+	EGLPNUM_TYPENAME_ILLprint_report (lp, "ENDATA\n");
+
+CLEANUP:
+	EGLPNUM_TYPENAME_ILLlp_rows_clear (lprows);
+	if (!lp->colnames)
+	{
+		ILLfree_names (colnames, lp->ncols);
+	}
+	if (!lp->rownames)
+	{
+		ILLfree_names (rownames, lp->nrows);
+	}
+	if (objname != lp->objname)
+	{
+		ILL_IFFREE (objname, char);
+	}
+	ILL_RESULT (rval, "ILLlpdata_mpswrite");
+}
+
+static int mps_write_col (
+	int i,
+	int iorig,
+	char *colname,
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	char **rownames,
+	int intmode,
+	char *objname)
+{
+	int row, k;
+	char*str;
+	EGLPNUM_TYPENAME_ILLmatrix *A;
+
+	A = &lp->A;
+	if (lp->intmarker && (lp->intmarker[iorig] != intmode))
+	{
+		EGLPNUM_TYPENAME_ILLprint_report (lp, " MARK%dqs      'MARKER'    '%s'\n", iorig,
+										 (lp->intmarker[iorig] ? "INTORG" : "INTEND"));
+		intmode = lp->intmarker[iorig];
+	}
+	if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (lp->obj[i]))
+	{
+		str = EGLPNUM_TYPENAME_EGlpNumGetStr(lp->obj[i]);
+		EGLPNUM_TYPENAME_ILLprint_report (lp, "  %s    %s    %s\n", colname, objname, str);
+		EGfree(str);
+	}
+	for (k = A->matbeg[i]; k < A->matbeg[i] + A->matcnt[i]; k++)
+	{
+		row = A->matind[k];
+		str = EGLPNUM_TYPENAME_EGlpNumGetStr(A->matval[k]);
+		EGLPNUM_TYPENAME_ILLprint_report (lp, "  %s    %s    %s\n", colname, rownames[row], str);
+		EGfree(str);
+	}
+	return intmode;
+}
diff --git a/qsopt_ex/mps.h b/qsopt_ex/mps.h
new file mode 100644
index 0000000..e0094dc
--- /dev/null
+++ b/qsopt_ex/mps.h
@@ -0,0 +1,53 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCSINFO $Id: mps_EGLPNUM_TYPENAME.h,v 1.2 2003/11/05 16:57:39 meven Exp $ */
+#ifndef EGLPNUM_TYPENAME_MPS_H
+#define EGLPNUM_TYPENAME_MPS_H
+
+#include "readline_EGLPNUM_TYPENAME.h"
+#include "format_EGLPNUM_TYPENAME.h"
+
+/****************************************************************************/
+/*                                                                          */
+/*              Routines to support Reading and Writing MPS Files           */
+/*                                                                          */
+/****************************************************************************/
+#include "basicdefs.h"
+extern const char *EGLPNUM_TYPENAME_ILLmps_section_name[ILL_MPS_N_SECTIONS + 2];
+
+#include "lpdata_EGLPNUM_TYPENAME.h"
+#include "rawlp_EGLPNUM_TYPENAME.h"
+#include "read_mps_EGLPNUM_TYPENAME.h"
+
+extern int EGLPNUM_TYPENAME_ILLread_mps (
+	EGLPNUM_TYPENAME_qsline_reader * file,
+	const char *filename,
+	EGLPNUM_TYPENAME_rawlpdata * lp);
+
+extern int EGLPNUM_TYPENAME_ILLwrite_mps (
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	EGLPNUM_TYPENAME_qserror_collector * collector);
+
+				/* use lp->reporter for output */
+
+#endif
diff --git a/qsopt_ex/names.c b/qsopt_ex/names.c
new file mode 100644
index 0000000..fed05df
--- /dev/null
+++ b/qsopt_ex/names.c
@@ -0,0 +1,102 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCSINFO $Id: names.c,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "names.h"
+
+#include "logging-private.h"
+
+#include "util.h"
+#include "except.h"
+#include "symtab.h"
+
+
+void ILLfree_names (
+	char **names,
+	int count)
+{
+	int i;
+
+	if (names)
+	{
+		for (i = 0; i < count; i++)
+		{
+			ILL_IFFREE (names[i], char);
+		}
+		ILL_IFFREE (names, char *);
+	}
+}
+
+int ILLgenerate_names (
+	char prefix,
+	int nnames,
+	char ***names)
+{
+	int rval = 0;
+	int i, len;
+	char *buf = (char *) NULL;
+
+	*names = (char **) NULL;
+	if (nnames == 0)
+		goto CLEANUP;
+
+	ILL_SAFE_MALLOC (buf, ILL_namebufsize, char);
+	ILL_SAFE_MALLOC (*names, nnames, char *);
+
+	for (i = 0; i < nnames; i++)
+	{
+		(*names)[i] = (char *) NULL;
+	}
+
+	for (i = 0; i < nnames; i++)
+	{
+		sprintf (buf, "%c%d", prefix, i);
+		len = strlen (buf) + 1;
+		ILL_SAFE_MALLOC ((*names)[i], len, char);
+
+		strcpy ((*names)[i], buf);
+	}
+
+CLEANUP:
+
+	if (rval)
+	{
+		if (*names)
+		{
+			ILLfree_names (*names, nnames);
+			*names = (char **) NULL;
+		}
+	}
+
+	ILL_IFFREE (buf, char);
+
+	if (rval)
+	{
+		QSlog("ILLsymboltab_generate_names failed");
+	}
+	return rval;
+}
diff --git a/qsopt_ex/names.h b/qsopt_ex/names.h
new file mode 100644
index 0000000..d065f7b
--- /dev/null
+++ b/qsopt_ex/names.h
@@ -0,0 +1,35 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCSINFO $Id: names.h,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+#ifndef ILL_NAMES_H
+#define ILL_NAMES_H
+
+extern void ILLfree_names (
+	char **names,
+	int count);
+extern int ILLgenerate_names (
+	char prefix,
+	int nnames,
+	char ***names);
+
+#endif
diff --git a/qsopt_ex/presolve.c b/qsopt_ex/presolve.c
new file mode 100644
index 0000000..6b9e06e
--- /dev/null
+++ b/qsopt_ex/presolve.c
@@ -0,0 +1,2634 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: presolve.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+static int TRACE = 0;
+
+/****************************************************************************/
+/*                                                                          */
+/*                 Presolve Routine for Simplex Method                      */
+/*                                                                          */
+/*  EXPORTED FUNCTIONS                                                      */
+/*                                                                          */
+/*    int EGLPNUM_TYPENAME_ILLlp_add_logicals (ILLlpata *lp)                                 */
+/*    int EGLPNUM_TYPENAME_ILLlp_presolve (EGLPNUM_TYPENAME_ILLlpdata *lp)                                    */
+/*    int EGLPNUM_TYPENAME_ILLlp_scale (EGLPNUM_TYPENAME_ILLlpdata *lp)                                       */
+/*    void EGLPNUM_TYPENAME_ILLlp_sinfo_init (EGLPNUM_TYPENAME_ILLlp_sinfo *sinfo)                            */
+/*    void EGLPNUM_TYPENAME_ILLlp_sinfo_free (EGLPNUM_TYPENAME_ILLlp_sinfo *sinfo)                            */
+/*    void EGLPNUM_TYPENAME_ILLlp_predata_init (EGLPNUM_TYPENAME_ILLlp_predata *pre)                          */
+/*    void EGLPNUM_TYPENAME_ILLlp_predata_free (EGLPNUM_TYPENAME_ILLlp_predata *pre)                          */
+/*                                                                          */
+/*  NOTES                                                                   */
+/*                                                                          */
+/*    presolve will assume that logicals have been added.                   */
+/*                                                                          */
+/****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "presolve_EGLPNUM_TYPENAME.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "allocrus.h"
+#include "eg_lpnum.h"
+#include "eg_io.h"
+#include "except.h"
+#include "zeit.h"
+
+#include "lpdata_EGLPNUM_TYPENAME.h"
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+//extern EGLPNUM_TYPE EGLPNUM_TYPENAME_SZERO_TOLER;
+
+#define ILL_LP_STATUS_OK (0)
+#define ILL_PRE_FEAS_TOL EGLPNUM_TYPENAME_PFEAS_TOLER	//(1e-6)
+#define ILL_PRE_ZERO_TOL EGLPNUM_TYPENAME_PIVOT_TOLER	//(1e-10)
+
+#define ILL_PRE_DELETE_EMPTY_ROW               (1)
+#define ILL_PRE_DELETE_SINGLETON_ROW           (2)
+#define ILL_PRE_DELETE_FIXED_VARIABLE          (3)
+#define ILL_PRE_DELETE_FORCED_VARIABLE         (4)
+#define ILL_PRE_DELETE_SINGLETON_VARIABLE      (5)
+#define ILL_PRE_DELETE_FREE_SINGLETON_VARIABLE (6)
+#define ILL_PRE_DELETE_EMPTY_COLUMN            (7)
+
+#define ILL_PRE_COL_STRUC                      (0)
+#define ILL_PRE_COL_LOGICAL                    (1)
+
+static int debug = 0;
+
+typedef struct
+{
+	int row;
+	int col;
+	char coltype;
+	char mark;
+	char del;
+	EGLPNUM_TYPE coef;
+}
+edge;
+
+typedef struct node
+{
+	edge **adj;
+	EGLPNUM_TYPE obj;
+	EGLPNUM_TYPE lower;
+	EGLPNUM_TYPE upper;
+	EGLPNUM_TYPE rhs;
+	int deg;
+	char mark;
+	char del;
+	char coltype;
+	char rowsense;
+}
+node;
+
+typedef struct intptr
+{
+	int this_val;
+	struct intptr *next;
+}
+intptr;
+
+typedef struct graph
+{
+	edge *edgelist;
+	struct node *rows;
+	struct node *cols;
+	int ecount;
+	int nrows;
+	int ncols;
+	int nzcount;
+	edge **adjspace;
+	ILLptrworld intptrworld;
+	int objsense;
+}
+graph;
+
+static void set_fixed_variable (
+	graph * G,
+	int j,
+	EGLPNUM_TYPE val),
+  get_implied_rhs_bounds (
+	graph * G,
+	int i,
+	EGLPNUM_TYPE * lb,
+	EGLPNUM_TYPE * ub),
+  get_implied_variable_bounds (
+	graph * G,
+	int j,
+	edge * a_ij,
+	EGLPNUM_TYPE * lb,
+	EGLPNUM_TYPE * ub),
+  dump_line (
+	EGLPNUM_TYPENAME_ILLlp_preline * line),
+  init_graph (
+	graph * G),
+  free_graph (
+	graph * G),
+  dump_graph (
+	graph * G);
+
+static int simple_presolve (
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	EGLPNUM_TYPENAME_ILLlp_predata * pre,
+	EGLPNUM_TYPENAME_ILLlp_sinfo * info,
+	int pre_types,
+	int *status),
+  grab_lp_line (
+	graph * G,
+	int indx,
+	EGLPNUM_TYPENAME_ILLlp_preline * line,
+	int row_or_col),
+  grab_lp_info (
+	graph * G,
+	char **colnames,
+	EGLPNUM_TYPENAME_ILLlp_sinfo * info),
+  fixed_variables (
+	graph * G,
+	EGLPNUM_TYPENAME_ILLlp_predata * pre),
+  empty_columns (
+	graph * G,
+	EGLPNUM_TYPENAME_ILLlp_predata * pre),
+  singleton_rows (
+	graph * G,
+	EGLPNUM_TYPENAME_ILLlp_predata * pre,
+	int *hit),
+  forcing_constraints (
+	graph * G,
+	EGLPNUM_TYPENAME_ILLlp_predata * pre,
+	int *hit),
+  singleton_columns (
+	graph * G,
+	EGLPNUM_TYPENAME_ILLlp_predata * pre,
+	int *hit),
+  duplicate_rows (
+	graph * G,
+	int *hit),
+  duplicate_cols (
+	graph * G,
+	int *hit),
+  gather_dup_lists (
+	int *s,
+	int count,
+	int *duptotal,
+	int **dupcnt,
+	int **dupind),
+  get_next_preop (
+	EGLPNUM_TYPENAME_ILLlp_predata * pre,
+	EGLPNUM_TYPENAME_ILLlp_preop ** op),
+  add_to_list (
+	ILLptrworld * world,
+	intptr ** list,
+	int i),
+  build_graph (
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	graph * G);
+
+
+ILL_PTRWORLD_ROUTINES (intptr, intptralloc, intptr_bulkalloc, intptrfree)
+ILL_PTRWORLD_LISTFREE_ROUTINE (intptr, intptr_listfree, intptrfree)
+ILL_PTRWORLD_LEAKS_ROUTINE (intptr, intptr_check_leaks, this_val, int)
+		 int EGLPNUM_TYPENAME_ILLlp_add_logicals (
+	EGLPNUM_TYPENAME_ILLlpdata * lp)
+{
+	int rval = 0;
+	int ncols, nrows, nzcount, i, aindex;
+	char *sense;
+	EGLPNUM_TYPENAME_ILLmatrix *A;
+
+	if (!lp)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlp_add_logicals called with a NULL pointer");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	QSlog("EGLPNUM_TYPENAME_ILLlp_add_logicals ...");
+
+	A = &lp->A;
+	sense = lp->sense;
+	ncols = lp->ncols;
+	nrows = lp->nrows;
+	nzcount = lp->nzcount;
+
+	if (nrows == 0)
+		goto CLEANUP;
+	EGLPNUM_TYPENAME_EGlpNumReallocArray (&(lp->obj), lp->colsize + nrows);
+	EGLPNUM_TYPENAME_EGlpNumReallocArray (&(lp->upper), lp->colsize + nrows);
+	EGLPNUM_TYPENAME_EGlpNumReallocArray (&(lp->lower), lp->colsize + nrows);
+	lp->colnames =
+		EGrealloc (lp->colnames, sizeof (char *) * (lp->colsize + nrows));
+	//rval = ILLutil_reallocrus_count ((void **) &(lp->colnames),
+	//                                 lp->colsize + nrows, sizeof (char *));
+	//ILL_CLEANUP_IF (rval);
+	memset (lp->colnames + ncols, 0, sizeof (char *) * nrows);
+
+	ILL_SAFE_MALLOC (lp->rowmap, lp->rowsize, int);
+
+
+	A->matcnt = EGrealloc (A->matcnt, sizeof (int) * (A->matcolsize + nrows));
+	//rval = ILLutil_reallocrus_count ((void **) &(A->matcnt),
+	//                                 A->matcolsize + nrows, sizeof (int));
+	//ILL_CLEANUP_IF (rval);
+
+	A->matbeg = EGrealloc (A->matbeg, sizeof (int) * (A->matcolsize + nrows));
+	//rval = ILLutil_reallocrus_count ((void **) &(A->matbeg),
+	//                                 A->matcolsize + nrows, sizeof (int));
+	//ILL_CLEANUP_IF (rval);
+
+	A->matind = EGrealloc (A->matind, sizeof (int) * (A->matsize + nrows));
+	//rval = ILLutil_reallocrus_count ((void **) &(A->matind),
+	//                                 A->matsize + nrows, sizeof (int));
+	//ILL_CLEANUP_IF (rval);
+	EGLPNUM_TYPENAME_EGlpNumReallocArray (&(A->matval), A->matsize + nrows);
+
+	for (i = 0; i < nrows; i++)
+	{
+		A->matind[A->matsize + i] = -1;
+	}
+
+	aindex = A->matsize - A->matfree;
+
+	for (i = 0; i < nrows; i++)
+	{
+		lp->rowmap[i] = ncols;
+		EGLPNUM_TYPENAME_EGlpNumZero (lp->obj[ncols]);
+		A->matcnt[ncols] = 1;
+		A->matbeg[ncols] = aindex;
+		A->matind[aindex] = i;
+		switch (sense[i])
+		{
+		case 'E':									/* Arificial */
+			EGLPNUM_TYPENAME_EGlpNumZero (lp->lower[ncols]);
+			EGLPNUM_TYPENAME_EGlpNumZero (lp->upper[ncols]);
+			EGLPNUM_TYPENAME_EGlpNumOne (A->matval[aindex]);
+			break;
+		case 'G':									/* Surplus   */
+			EGLPNUM_TYPENAME_EGlpNumZero (lp->lower[ncols]);
+			EGLPNUM_TYPENAME_EGlpNumCopy (lp->upper[ncols], EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+			EGLPNUM_TYPENAME_EGlpNumOne (A->matval[aindex]);
+			EGLPNUM_TYPENAME_EGlpNumSign (A->matval[aindex]);
+			break;
+		case 'L':									/* Slack     */
+			EGLPNUM_TYPENAME_EGlpNumZero (lp->lower[ncols]);
+			EGLPNUM_TYPENAME_EGlpNumCopy (lp->upper[ncols], EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+			EGLPNUM_TYPENAME_EGlpNumOne (A->matval[aindex]);
+			break;
+		case 'R':									/* Range     */
+			EGLPNUM_TYPENAME_EGlpNumZero (lp->lower[ncols]);
+			EGLPNUM_TYPENAME_EGlpNumCopy (lp->upper[ncols], lp->rangeval[i]);
+			EGLPNUM_TYPENAME_EGlpNumOne (A->matval[aindex]);
+			EGLPNUM_TYPENAME_EGlpNumSign (A->matval[aindex]);
+			break;
+		default:
+			QSlog("unknown sense %c in EGLPNUM_TYPENAME_ILLlp_add_logicals", sense[i]);
+			rval = 1;
+			goto CLEANUP;
+		}
+		ncols++;
+		nzcount++;
+		aindex++;
+	}
+
+	lp->ncols = ncols;
+	lp->nzcount = nzcount;
+	A->matcols = ncols;
+
+	lp->colsize += nrows;
+	A->matsize += nrows;
+	A->matcolsize += nrows;
+
+	if (lp->rA)
+	{
+		EGLPNUM_TYPENAME_ILLlp_rows_clear (lp->rA);
+	}
+	else
+	{
+		ILL_SAFE_MALLOC (lp->rA, 1, EGLPNUM_TYPENAME_ILLlp_rows);
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLlp_rows_init (lp->rA, lp, 1);
+	ILL_CLEANUP_IF (rval);
+
+CLEANUP:
+
+	ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLlp_add_logicals");
+}
+
+int EGLPNUM_TYPENAME_ILLlp_scale (
+	EGLPNUM_TYPENAME_ILLlpdata * lp)
+{
+	int rval = 0;
+	int i, j, k, col, row, nstruct, start, stop;
+	EGLPNUM_TYPENAME_ILLmatrix *A;
+	EGLPNUM_TYPE rho;
+	EGLPNUM_TYPE *gama = 0;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (rho);
+
+	/* Columns - divide by largest absolute value */
+
+	if (!lp)
+	{
+		ILL_ERROR (rval, "EGLPNUM_TYPENAME_ILLlp_scale called with a NULL pointer");
+	}
+
+	if (lp->nrows == 0 || lp->ncols == 0)
+		goto CLEANUP;
+
+	A = &lp->A;
+	nstruct = lp->nstruct;
+
+	for (j = 0; j < nstruct; j++)
+	{
+		col = lp->structmap[j];
+		EGLPNUM_TYPENAME_EGlpNumZero (rho);
+
+		start = A->matbeg[col];
+		stop = start + A->matcnt[col];
+
+		for (k = start; k < stop; k++)
+		{
+			EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (rho, A->matval[k]);
+		}
+
+		if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (rho))
+		{
+			for (k = start; k < stop; k++)
+			{
+				EGLPNUM_TYPENAME_EGlpNumDivTo (A->matval[k], rho);
+			}
+			EGLPNUM_TYPENAME_EGlpNumDivTo (lp->obj[col], rho);
+			if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (lp->lower[col], EGLPNUM_TYPENAME_ILL_MINDOUBLE))
+				EGLPNUM_TYPENAME_EGlpNumMultTo (lp->lower[col], rho);
+			if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (lp->upper[col], EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+				EGLPNUM_TYPENAME_EGlpNumMultTo (lp->upper[col], rho);
+		}
+	}
+
+	gama = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+	for (i = 0; i < lp->nrows; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumZero (gama[i]);
+	}
+
+	for (j = 0; j < nstruct; j++)
+	{
+		col = lp->structmap[j];
+		start = A->matbeg[col];
+		stop = start + A->matcnt[col];
+
+		for (k = start; k < stop; k++)
+		{
+			row = A->matind[k];
+			EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (gama[row], A->matval[k]);
+		}
+	}
+
+	for (j = 0; j < nstruct; j++)
+	{
+		col = lp->structmap[j];
+		start = A->matbeg[col];
+		stop = start + A->matcnt[col];
+
+		for (k = start; k < stop; k++)
+		{
+			row = A->matind[k];
+			if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (gama[row]))
+			{
+				EGLPNUM_TYPENAME_EGlpNumDivTo (A->matval[k], gama[row]);
+			}
+		}
+	}
+
+	for (i = 0; i < lp->nrows; i++)
+	{
+		if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero ( gama[i]))
+		{
+			EGLPNUM_TYPENAME_EGlpNumDivTo (lp->rhs[i], gama[i]);
+			col = lp->rowmap[i];
+			if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (lp->upper[col], EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+			{
+				EGLPNUM_TYPENAME_EGlpNumDivTo (lp->upper[col], gama[i]);	/* Ranged row */
+			}
+		}
+	}
+
+	if (lp->rA)
+	{															/* Need to clear the row version of data */
+		EGLPNUM_TYPENAME_ILLlp_rows_clear (lp->rA);
+		ILL_IFFREE (lp->rA, EGLPNUM_TYPENAME_ILLlp_rows);
+	}
+
+
+CLEANUP:
+
+	EGLPNUM_TYPENAME_EGlpNumClearVar (rho);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (gama);
+	ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLlp_scale");
+}
+
+int EGLPNUM_TYPENAME_ILLlp_presolve (
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	int pre_types)
+{
+	int rval = 0;
+	int status = ILL_LP_STATUS_OK;
+	EGLPNUM_TYPENAME_ILLlp_predata *pre = 0;
+	EGLPNUM_TYPENAME_ILLlp_sinfo *info = 0;
+
+	if (!lp)
+	{
+		QSlog("EGLPNUM_TYPENAME_ILLlp_presolve called with a NULL pointer");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+
+/*
+    ILLlpdata_writelp (lp, 0);
+*/
+
+	ILL_SAFE_MALLOC (pre, 1, EGLPNUM_TYPENAME_ILLlp_predata);
+	EGLPNUM_TYPENAME_ILLlp_predata_init (pre);
+
+	ILL_SAFE_MALLOC (info, 1, EGLPNUM_TYPENAME_ILLlp_sinfo);
+	EGLPNUM_TYPENAME_ILLlp_sinfo_init (info);
+
+	rval = simple_presolve (lp, pre, info, pre_types, &status);
+	ILL_CLEANUP_IF (rval);
+	if (status != ILL_LP_STATUS_OK)
+	{
+		QSlog("simple_presolve returned with bad status");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+/*
+    rval = EGLPNUM_TYPENAME_ILLlp_sinfo_print (info);
+    ILL_CLEANUP_IF (rval);
+*/
+
+CLEANUP:
+
+	if (rval)
+	{
+		if (pre)
+		{
+			EGLPNUM_TYPENAME_ILLlp_predata_free (pre);
+			ILL_IFFREE (pre, EGLPNUM_TYPENAME_ILLlp_predata);
+		}
+
+		if (info)
+		{
+			EGLPNUM_TYPENAME_ILLlp_sinfo_free (info);
+			ILL_IFFREE (info, EGLPNUM_TYPENAME_ILLlp_sinfo);
+		}
+	}
+	else
+	{
+		lp->presolve = pre;
+		lp->sinfo = info;
+	}
+
+	ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLlp_presolve");
+}
+
+
+#if 0
+int ILLlp_presolve_addrow (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int cnt,
+	int *ind,
+	double *val,
+	double rhs)
+{
+	int rval = 0;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp;
+	EGLPNUM_TYPENAME_ILLlp_sinfo *S;
+	EGLPNUM_TYPENAME_ILLmatrix *A;
+
+	/* This will need to evolve into a function that handles the task */
+	/* of working through the presolve data to determine the new LP   */
+	/* created when a row is added to the original LP.                */
+
+	/* The copies of the obj and bound used in the simplex code are   */
+	/* also updated in this function.                                 */
+
+	if (!lp)
+	{
+		QSlog("ILLlp_presolve_addrow is called without an LP");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	if (lp->presolve != 0)
+	{
+		QSlog("Not yet set up to handle addrows after presolve");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	qslp = lp->O;
+	S = qslp->sinfo;
+	A = S->A;
+
+
+	rval = ILLlib_matrix_addrow (A, cnt, ind, val, rhs);
+	ILL_CLEANUP_IF (rval);
+
+
+CLEANUP:
+
+	ILL_RETURN (rval, "ILLlp_presolve_addrow");
+}
+#endif
+
+
+static int simple_presolve (
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	EGLPNUM_TYPENAME_ILLlp_predata * pre,
+	EGLPNUM_TYPENAME_ILLlp_sinfo * info,
+	int pre_types,
+	int *status)
+{
+	int rval = 0;
+	int i, hit, newhit;
+	graph G;
+
+	if (status)
+		*status = ILL_LP_STATUS_OK;
+	init_graph (&G);
+
+	if (!lp)
+	{
+		QSlog("simple_presolve called with a NULL pointer");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	QSlog("Initial Rows = %d, Cols = %d, Nzcount = %d",
+							lp->nrows, lp->ncols, lp->nzcount);
+
+	rval = build_graph (lp, &G);
+	ILL_CLEANUP_IF (rval);
+	if (debug)
+		dump_graph (&G);
+
+	if (pre_types & EGLPNUM_TYPENAME_ILL_PRE_FIXED)
+	{
+		rval = fixed_variables (&G, pre);
+		ILL_CLEANUP_IF (rval);
+	}
+
+	do
+	{
+		hit = 0;
+		if (pre_types & EGLPNUM_TYPENAME_ILL_PRE_SINGLE_ROW)
+		{
+			rval = singleton_rows (&G, pre, &newhit);
+			ILL_CLEANUP_IF (rval);
+			hit += newhit;
+		}
+
+		if (pre_types & EGLPNUM_TYPENAME_ILL_PRE_FORCING)
+		{
+			rval = forcing_constraints (&G, pre, &newhit);
+			ILL_CLEANUP_IF (rval);
+			hit += newhit;
+		}
+
+		if (pre_types & EGLPNUM_TYPENAME_ILL_PRE_SINGLE_COL)
+		{
+			rval = singleton_columns (&G, pre, &newhit);
+			ILL_CLEANUP_IF (rval);
+			hit += newhit;
+		}
+
+		if (pre_types & EGLPNUM_TYPENAME_ILL_PRE_DUPLICATE_ROW)
+		{
+			rval = duplicate_rows (&G, &newhit);
+			ILL_CLEANUP_IF (rval);
+			hit += newhit;
+		}
+
+		if (pre_types & EGLPNUM_TYPENAME_ILL_PRE_DUPLICATE_COL)
+		{
+			rval = duplicate_cols (&G, &newhit);
+			ILL_CLEANUP_IF (rval);
+			hit += newhit;
+		}
+
+
+/*
+        {
+            int k, cnt = 0;
+            for (i = 0; i < G.ncols; i++) {
+                if (G.cols[i].del == 0) {
+                    for (k = 0; k < G.cols[i].deg; k++)  {
+                        if (G.cols[i].adj[k]->del == 0) {
+                            cnt++;
+                        }
+                    }
+                }
+            }
+            QSlog("Current NZCOUNT = %d", cnt);
+        }
+*/
+	} while (hit);
+
+	if (EGLPNUM_TYPENAME_ILL_PRE_EMPTY_COL)
+	{
+		rval = empty_columns (&G, pre);
+		ILL_CLEANUP_IF (rval);
+	}
+
+	if (debug)
+	{
+		QSlog("Operations");
+		for (i = 0; i < pre->opcount; i++)
+		{
+			switch (pre->oplist[i].ptype)
+			{
+			case ILL_PRE_DELETE_EMPTY_ROW:
+				QSlog("Delete Empty Row: %d", pre->oplist[i].rowindex);
+				break;
+			case ILL_PRE_DELETE_SINGLETON_ROW:
+				QSlog("Delete Singleton Row: %d (col %d)",
+										pre->oplist[i].rowindex, pre->oplist[i].colindex);
+				dump_line (&pre->oplist[i].line);
+				break;
+			case ILL_PRE_DELETE_FIXED_VARIABLE:
+				QSlog("Delete Fixed Variable: %d", pre->oplist[i].colindex);
+				dump_line (&pre->oplist[i].line);
+				break;
+			case ILL_PRE_DELETE_FORCED_VARIABLE:
+				QSlog("Delete Forced Variable: %d", pre->oplist[i].colindex);
+				dump_line (&pre->oplist[i].line);
+				break;
+			case ILL_PRE_DELETE_SINGLETON_VARIABLE:
+				QSlog("Delete Singleton Variable: %d", pre->oplist[i].colindex);
+				dump_line (&pre->oplist[i].line);
+				break;
+			case ILL_PRE_DELETE_FREE_SINGLETON_VARIABLE:
+				QSlog("Delete Free Singleton Variable: %d",
+										pre->oplist[i].colindex);
+				dump_line (&pre->oplist[i].line);
+				break;
+			case ILL_PRE_DELETE_EMPTY_COLUMN:
+				QSlog("Delete Empty Column: %d", pre->oplist[i].colindex);
+				dump_line (&pre->oplist[i].line);
+				break;
+			default:
+				QSlog("unknon presolve operation");
+				rval = 1;
+				goto CLEANUP;
+			}
+		}
+	}
+
+	rval = grab_lp_info (&G, lp->colnames, info);
+	ILL_CLEANUP_IF (rval);
+
+/*
+    QSlog("Final Rows = %d, Cols = %d, Nzcount = %d",
+                info->nrows, info->ncols, info->nzcount);
+*/
+
+
+CLEANUP:
+
+	free_graph (&G);
+	ILL_RETURN (rval, "simple_presolve");
+}
+
+static int grab_lp_line (
+	graph * G,
+	int indx,
+	EGLPNUM_TYPENAME_ILLlp_preline * line,
+	int row_or_col)
+{
+	int rval = 0;
+	int k, cnt;
+	node *n;
+
+	if (row_or_col == 0)
+		n = &G->rows[indx];
+	else
+		n = &G->cols[indx];
+
+	line->count = 0;
+
+	for (k = 0; k < n->deg; k++)
+	{
+		if (n->adj[k]->del == 0)
+		{
+			line->count++;
+		}
+	}
+
+	if (line->count)
+	{
+		ILL_SAFE_MALLOC (line->ind, line->count, int);
+
+		line->val = EGLPNUM_TYPENAME_EGlpNumAllocArray (line->count);
+		if (!line->ind || !line->val)
+		{
+			QSlog("out of memory in grab_lp_line");
+			rval = 1;
+			goto CLEANUP;
+		}
+		for (k = 0, cnt = 0; k < n->deg; k++)
+		{
+			if (n->adj[k]->del == 0)
+			{
+				line->ind[cnt] = n->adj[k]->row;
+				EGLPNUM_TYPENAME_EGlpNumCopy (line->val[cnt], n->adj[k]->coef);
+				cnt++;
+			}
+		}
+	}
+
+	if (row_or_col == 0)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (line->rhs, n->rhs);
+	}
+	else
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (line->obj, n->obj);
+		EGLPNUM_TYPENAME_EGlpNumCopy (line->lower, n->lower);
+		EGLPNUM_TYPENAME_EGlpNumCopy (line->upper, n->upper);
+	}
+
+	line->row_or_col = row_or_col;
+
+CLEANUP:
+
+	ILL_RETURN (rval, "grab_lp_line");
+}
+
+static void dump_line (
+	EGLPNUM_TYPENAME_ILLlp_preline * line)
+{
+	int k;
+
+	if (line->row_or_col == 0)
+	{
+		for (k = 0; k < line->count; k++)
+		{
+			QSlog(" C%d->%g", line->ind[k], EGLPNUM_TYPENAME_EGlpNumToLf (line->val[k]));
+		}
+		QSlog(" RHS->%g", EGLPNUM_TYPENAME_EGlpNumToLf (line->rhs));
+	}
+	else
+	{
+		for (k = 0; k < line->count; k++)
+		{
+			QSlog(" R%d->%g", line->ind[k], EGLPNUM_TYPENAME_EGlpNumToLf (line->val[k]));
+		}
+		QSlog(" Obj->%g  LB->%g  UB->%g", EGLPNUM_TYPENAME_EGlpNumToLf (line->obj),
+						EGLPNUM_TYPENAME_EGlpNumToLf (line->lower), EGLPNUM_TYPENAME_EGlpNumToLf (line->upper));
+	}
+}
+
+static int grab_lp_info (
+	graph * G,
+	char **colnames,
+	EGLPNUM_TYPENAME_ILLlp_sinfo * info)
+{
+	int rval = 0;
+	int ncols = 0, nrows = 0, nzcount = 0;
+	int i, j, k, cnt, len;
+	node *grows = G->rows;
+	node *gcols = G->cols;
+	int *tdeg = 0;
+	int *map = 0;
+	char *buf = 0;
+	EGLPNUM_TYPENAME_ILLmatrix *A = &info->A;
+
+	ILL_SAFE_MALLOC (tdeg, G->ncols, int);
+	ILL_SAFE_MALLOC (map, G->nrows, int);
+
+	if (!tdeg || !map)
+	{
+		QSlog("out of memory in grab_lp_info");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	for (i = 0; i < G->nrows; i++)
+	{
+		if (grows[i].del == 0)
+		{
+			map[i] = nrows;
+			nrows++;
+		}
+	}
+
+	for (j = 0; j < G->ncols; j++)
+	{
+		if (gcols[j].del == 0)
+		{
+			tdeg[ncols] = 0;
+			for (k = 0; k < gcols[j].deg; k++)
+			{
+				if (gcols[j].adj[k]->del == 0)
+				{
+					tdeg[ncols]++;
+					nzcount++;
+				}
+			}
+			ncols++;
+		}
+	}
+
+	info->ncols = ncols;
+	info->nrows = nrows;
+	info->nzcount = nzcount;
+
+	info->rowsize = nrows;
+	info->colsize = ncols;
+
+	info->rhs = EGLPNUM_TYPENAME_EGlpNumAllocArray (nrows);
+	info->obj = EGLPNUM_TYPENAME_EGlpNumAllocArray (ncols);
+	info->upper = EGLPNUM_TYPENAME_EGlpNumAllocArray (ncols);
+	info->lower = EGLPNUM_TYPENAME_EGlpNumAllocArray (ncols);
+	A->matval = EGLPNUM_TYPENAME_EGlpNumAllocArray (info->nzcount + 1);
+	ILL_SAFE_MALLOC (A->matind, info->nzcount + 1, int);
+	ILL_SAFE_MALLOC (A->matcnt, info->colsize, int);
+	ILL_SAFE_MALLOC (A->matbeg, info->colsize, int);
+
+	if (!info->rhs || !info->obj || !info->lower || !info->upper ||
+			!A->matval || !A->matind || !A->matcnt || !A->matbeg)
+	{
+		QSlog("out of memory in grab_lp");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	A->matind[info->nzcount] = -1;
+	A->matsize = info->nzcount + 1;
+	A->matcolsize = info->colsize;
+	A->matfree = 1;
+	A->matcols = ncols;
+	A->matrows = nrows;
+
+
+	nrows = 0;
+	for (i = 0; i < G->nrows; i++)
+	{
+		if (grows[i].del == 0)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (info->rhs[nrows], grows[i].rhs);
+			nrows++;
+		}
+	}
+
+	ncols = 0;
+	cnt = 0;
+	for (j = 0; j < G->ncols; j++)
+	{
+		if (gcols[j].del == 0)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (info->obj[ncols], gcols[j].obj);
+			EGLPNUM_TYPENAME_EGlpNumCopy (info->lower[ncols], gcols[j].lower);
+			EGLPNUM_TYPENAME_EGlpNumCopy (info->upper[ncols], gcols[j].upper);
+			A->matcnt[ncols] = tdeg[ncols];
+			A->matbeg[ncols] = cnt;
+			for (k = 0; k < gcols[j].deg; k++)
+			{
+				if (gcols[j].adj[k]->del == 0)
+				{
+					EGLPNUM_TYPENAME_EGlpNumCopy (A->matval[cnt], gcols[j].adj[k]->coef);
+					A->matind[cnt] = map[gcols[j].adj[k]->row];
+					cnt++;
+				}
+			}
+			ncols++;
+		}
+	}
+
+	if (colnames)
+	{
+		ILL_SAFE_MALLOC (info->colnames, info->colsize, char *);
+
+		if (!info->colnames)
+		{
+			QSlog("out of memory in grab_lp");
+			rval = 1;
+			goto CLEANUP;
+		}
+		for (j = 0; j < info->colsize; j++)
+		{
+			info->colnames[j] = 0;
+		}
+
+		ILL_SAFE_MALLOC (buf, ILL_namebufsize, char);
+
+		if (!buf)
+		{
+			QSlog("out of memory in grab_lp");
+			rval = 1;
+			goto CLEANUP;
+		}
+		ncols = 0;
+		for (j = 0; j < G->ncols; j++)
+		{
+			if (gcols[j].del == 0)
+			{
+				if (gcols[j].coltype == ILL_PRE_COL_STRUC)
+				{
+					len = strlen (colnames[j]) + 1;
+					ILL_SAFE_MALLOC (info->colnames[ncols], len, char);
+
+					if (!info->colnames[ncols])
+					{
+						QSlog("out of memory in grab_lp");
+						rval = 1;
+						goto CLEANUP;
+					}
+					strcpy (info->colnames[ncols], colnames[j]);
+				}
+				else
+				{
+					for (k = 0; k < gcols[j].deg; k++)
+					{
+						if (gcols[j].adj[k]->del == 0)
+						{
+							i = gcols[j].adj[k]->row;
+							break;
+						}
+					}
+					if (k == gcols[j].deg)
+					{
+						QSlog("problem with graph in grab_lp");
+						rval = 1;
+						goto CLEANUP;
+					}
+					sprintf (buf, "s%d", i);
+					len = strlen (buf) + 1;
+					ILL_SAFE_MALLOC (info->colnames[ncols], len, char);
+
+					if (!info->colnames[ncols])
+					{
+						QSlog("out of memory in grab_lp");
+						rval = 1;
+						goto CLEANUP;
+					}
+					strcpy (info->colnames[ncols], buf);
+				}
+				ncols++;
+			}
+		}
+	}
+
+/* ADD STRUCT VARIABLE STUFF */
+
+
+CLEANUP:
+
+	if (rval)
+	{
+		EGLPNUM_TYPENAME_ILLlp_sinfo_free (info);
+	}
+	ILL_IFFREE (tdeg, int);
+	ILL_IFFREE (map, int);
+	ILL_IFFREE (buf, char);
+
+	ILL_RETURN (rval, "grab_lp_info");
+}
+
+static int fixed_variables (
+	graph * G,
+	EGLPNUM_TYPENAME_ILLlp_predata * pre)
+{
+	int rval = 0;
+	int j;
+	int ncols = G->ncols;
+	node *cols = G->cols;
+	EGLPNUM_TYPENAME_ILLlp_preop *op = 0;
+
+	for (j = 0; j < ncols; j++)
+	{
+		if (cols[j].del == 0)
+		{
+			if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (cols[j].lower, cols[j].upper))
+			{
+				rval = get_next_preop (pre, &op);
+				ILL_CLEANUP_IF (rval);
+
+				op->colindex = j;
+				op->rowindex = -1;
+				op->ptype = ILL_PRE_DELETE_FIXED_VARIABLE;
+
+				rval = grab_lp_line (G, op->colindex, &op->line, 1);
+				ILL_CLEANUP_IF (rval);
+				pre->opcount++;
+
+				set_fixed_variable (G, j, cols[j].lower);
+			}
+		}
+	}
+
+CLEANUP:
+
+	ILL_RETURN (rval, "fixed_variables");
+}
+
+static int empty_columns (
+	graph * G,
+	EGLPNUM_TYPENAME_ILLlp_predata * pre)
+{
+	int rval = 0;
+	int j, k;
+	int ncols = G->ncols;
+	node *cols = G->cols;
+	EGLPNUM_TYPENAME_ILLlp_preop *op = 0;
+	EGLPNUM_TYPE objtmp;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (objtmp);
+
+	for (j = 0; j < ncols; j++)
+	{
+		if (cols[j].del == 0)
+		{
+			for (k = 0; k < cols[j].deg; k++)
+			{
+				if (cols[j].adj[k]->del == 0)
+					break;
+			}
+			if (k == cols[j].deg)
+			{
+				rval = get_next_preop (pre, &op);
+				ILL_CLEANUP_IF (rval);
+
+				op->colindex = j;
+				op->rowindex = -1;
+				op->ptype = ILL_PRE_DELETE_EMPTY_COLUMN;
+
+				rval = grab_lp_line (G, op->colindex, &op->line, 1);
+				ILL_CLEANUP_IF (rval);
+				pre->opcount++;
+				EGLPNUM_TYPENAME_EGlpNumCopy (objtmp, cols[j].obj);
+				if (G->objsense < 0)
+					EGLPNUM_TYPENAME_EGlpNumSign (objtmp);
+				if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (objtmp, ILL_PRE_FEAS_TOL))
+				{
+					set_fixed_variable (G, j, cols[j].lower);
+				}
+				else if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (objtmp))
+				{
+					if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (cols[j].lower, EGLPNUM_TYPENAME_ILL_MINDOUBLE))
+					{
+						QSlog("unbounded prob detected in empty_columns");
+						QSlog("col %d, obj %g", j, EGLPNUM_TYPENAME_EGlpNumToLf (cols[j].obj));
+						rval = 1;
+						goto CLEANUP;
+					}
+					else
+					{
+						set_fixed_variable (G, j, cols[j].lower);
+					}
+				}
+				else if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (objtmp))
+				{
+					if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (cols[j].upper, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+					{
+						QSlog("unbounded prob detected in empty_columns");
+						QSlog("col %d, obj %g", j, EGLPNUM_TYPENAME_EGlpNumToLf (cols[j].obj));
+						rval = 1;
+						goto CLEANUP;
+					}
+					else
+					{
+						set_fixed_variable (G, j, cols[j].upper);
+					}
+				}
+				else
+				{
+					set_fixed_variable (G, j, cols[j].lower);
+				}
+			}
+		}
+	}
+
+CLEANUP:
+
+	EGLPNUM_TYPENAME_EGlpNumClearVar (objtmp);
+	ILL_RETURN (rval, "empty_columns");
+}
+
+static int singleton_rows (
+	graph * G,
+	EGLPNUM_TYPENAME_ILLlp_predata * pre,
+	int *hit)
+{
+	int rval = 0;
+	int rowindex, i, k, h;
+	int nrows = G->nrows;
+	node *rows = G->rows;
+	node *cols = G->cols;
+	node *r, *c;
+	edge *pivot, *f;
+	intptr *next, *list = 0;
+	int *tdeg = 0;
+	EGLPNUM_TYPE val;
+	EGLPNUM_TYPENAME_ILLlp_preop *op = 0;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (val);
+
+	*hit = 0;
+	if (G->nrows == 0)
+		goto CLEANUP;
+
+	ILL_SAFE_MALLOC (tdeg, G->nrows, int);
+
+	if (!tdeg)
+	{
+		QSlog("out of memory in singleton_rows");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	for (i = 0; i < nrows; i++)
+	{
+		if (rows[i].del == 0)
+		{
+			tdeg[i] = 0;
+			for (k = 0; k < rows[i].deg; k++)
+			{
+				if (rows[i].adj[k]->del == 0)
+				{
+					tdeg[i]++;
+				}
+			}
+			if (tdeg[i] <= 1)
+			{
+				rval = add_to_list (&G->intptrworld, &list, i);
+				ILL_CLEANUP_IF (rval);
+			}
+		}
+	}
+
+	while (list)
+	{
+		(*hit)++;
+		rowindex = list->this_val;
+		next = list->next;
+		intptrfree (&G->intptrworld, list);
+		list = next;
+
+		rval = get_next_preop (pre, &op);
+		ILL_CLEANUP_IF (rval);
+
+		r = &rows[rowindex];
+
+		if (tdeg[rowindex] == 0)
+		{
+			if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (r->rhs, ILL_PRE_FEAS_TOL))
+			{
+				QSlog("infeasible row detected in singleton_row");
+				QSlog("empty row with rhs = %g", EGLPNUM_TYPENAME_EGlpNumToLf (r->rhs));
+				rval = 1;
+				goto CLEANUP;
+			}
+			op->ptype = ILL_PRE_DELETE_EMPTY_ROW;
+			op->rowindex = rowindex;
+		}
+		else
+		{
+			/*  Find the "pivot" entry and colum */
+
+			for (k = 0; k < r->deg; k++)
+			{
+				if (r->adj[k]->del == 0)
+					break;
+			}
+			if (k == r->deg)
+			{
+				QSlog("lost an edge in singleton_rows");
+				rval = 1;
+				goto CLEANUP;
+			}
+
+			pivot = r->adj[k];
+			c = &cols[pivot->col];
+
+			/*  Store data from operation (incluing the col coefs) */
+
+			op->ptype = ILL_PRE_DELETE_SINGLETON_ROW;
+			op->rowindex = rowindex;
+			op->colindex = c - cols;
+			EGLPNUM_TYPENAME_EGlpNumCopy (op->line.rhs, r->rhs);
+			rval = grab_lp_line (G, op->colindex, &op->line, 1);
+			ILL_CLEANUP_IF (rval);
+
+			/*  Fix the x[c] to its rhs value */
+			/*val = r->rhs / pivot->coef; */
+			EGLPNUM_TYPENAME_EGlpNumCopyFrac (val, r->rhs, pivot->coef);
+			/* if (val < c->lower - ILL_PRE_FEAS_TOL ||
+			 * val > c->upper + ILL_PRE_FEAS_TOL) */
+			if (EGLPNUM_TYPENAME_EGlpNumIsSumLess (val, ILL_PRE_FEAS_TOL, c->lower) ||
+					EGLPNUM_TYPENAME_EGlpNumIsSumLess (c->upper, ILL_PRE_FEAS_TOL, val))
+			{
+				QSlog("infeasible bounds detected in singleton_row %d", rowindex);
+				QSlog("lower->%g  upper->%g  val = %g",
+										EGLPNUM_TYPENAME_EGlpNumToLf (c->lower), EGLPNUM_TYPENAME_EGlpNumToLf (c->upper),
+										EGLPNUM_TYPENAME_EGlpNumToLf (val));
+				rval = 1;
+				goto CLEANUP;
+			}
+			else
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (c->lower, val);
+				EGLPNUM_TYPENAME_EGlpNumCopy (c->upper, val);
+			}
+
+			/*  Delete x[c] from other rows (and adjust their rhs) */
+
+			c->del = 1;
+
+			for (h = 0; h < c->deg; h++)
+			{
+				f = c->adj[h];
+				if (f->del == 0)
+				{
+					/*rows[f->row].rhs -= (f->coef * c->lower); */
+					EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (rows[f->row].rhs, f->coef, c->lower);
+					tdeg[f->row]--;
+					if (tdeg[f->row] == 1)
+					{
+						if (f == pivot)
+						{
+							QSlog("bad pivot element");
+							rval = 1;
+							goto CLEANUP;
+						}
+						rval = add_to_list (&G->intptrworld, &list, f->row);
+						ILL_CLEANUP_IF (rval);
+					}
+					f->del = 1;
+				}
+			}
+		}
+
+		r->del = 1;
+		pre->opcount++;
+	}
+
+CLEANUP:
+
+	ILL_IFFREE (tdeg, int);
+
+	intptr_listfree (&G->intptrworld, list);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (val);
+	ILL_RETURN (rval, "singleton_rows");
+}
+
+static int forcing_constraints (
+	graph * G,
+	EGLPNUM_TYPENAME_ILLlp_predata * pre,
+	int *hit)
+{
+	int rval = 0;
+	int i, j, k, ts;
+	node *rows = G->rows;
+	node *cols = G->cols;
+	edge *e;
+	int nrows = G->nrows;
+	EGLPNUM_TYPE ub, lb;
+	EGLPNUM_TYPENAME_ILLlp_preop *op = 0;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (ub);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (lb);
+
+	*hit = 0;
+
+	for (i = 0; i < nrows; i++)
+	{
+		if (rows[i].del == 0)
+		{
+			get_implied_rhs_bounds (G, i, &lb, &ub);
+			if (EGLPNUM_TYPENAME_EGlpNumIsSumLess (rows[i].rhs, ILL_PRE_FEAS_TOL, lb) ||
+					EGLPNUM_TYPENAME_EGlpNumIsSumLess (ub, ILL_PRE_FEAS_TOL, rows[i].rhs))
+			{
+				QSlog("infeasible row detected in forcing_constraints");
+				QSlog("Row %d:  RHS->%g  LBnd->%g  UBnd->%g",
+										i, EGLPNUM_TYPENAME_EGlpNumToLf (rows[i].rhs),
+										EGLPNUM_TYPENAME_EGlpNumToLf (lb), EGLPNUM_TYPENAME_EGlpNumToLf (ub));
+				rval = 1;
+				goto CLEANUP;
+			}
+			else if (EGLPNUM_TYPENAME_EGlpNumIsDiffLess (rows[i].rhs, ILL_PRE_FEAS_TOL, lb) ||
+							 EGLPNUM_TYPENAME_EGlpNumIsDiffLess (ub, ILL_PRE_FEAS_TOL, rows[i].rhs))
+			{
+				(*hit)++;
+				ts = (EGLPNUM_TYPENAME_EGlpNumIsDiffLess (rows[i].rhs, ILL_PRE_FEAS_TOL, lb) ? 0 : 1);
+				for (k = 0; k < rows[i].deg; k++)
+				{
+					e = rows[i].adj[k];
+					if (e->del == 0)
+					{
+						j = e->col;
+
+						rval = get_next_preop (pre, &op);
+						ILL_CLEANUP_IF (rval);
+
+						op->colindex = j;
+						op->rowindex = i;
+						op->ptype = ILL_PRE_DELETE_FORCED_VARIABLE;
+
+						rval = grab_lp_line (G, j, &op->line, 1);
+						ILL_CLEANUP_IF (rval);
+						pre->opcount++;
+
+						if ((ts == 0 && EGLPNUM_TYPENAME_EGlpNumIsLessZero (e->coef)) ||
+								(ts == 1 && EGLPNUM_TYPENAME_EGlpNumIsGreatZero (e->coef)))
+						{
+							set_fixed_variable (G, j, cols[j].upper);
+						}
+						else
+						{
+							set_fixed_variable (G, j, cols[j].lower);
+						}
+					}
+				}
+			}
+		}
+	}
+
+CLEANUP:
+
+	EGLPNUM_TYPENAME_EGlpNumClearVar (ub);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (lb);
+	ILL_RETURN (rval, "forcing_constraints");
+}
+
+static int singleton_columns (
+	graph * G,
+	EGLPNUM_TYPENAME_ILLlp_predata * pre,
+	int *hit)
+{
+	int rval = 0;
+	int ncols = G->ncols;
+	int j, k, deg, rdeg, single = 0, irow;
+	EGLPNUM_TYPE lb, ub, b, eb;
+	node *cols = G->cols;
+	node *rows = G->rows;
+	edge *b_edge;
+	EGLPNUM_TYPENAME_ILLlp_preop *op = 0;
+	EGLPNUM_TYPE newub, newlb;
+	EGLPNUM_TYPE a, c, l, u;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (lb);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (ub);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (eb);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (b);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (newlb);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (newub);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (a);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (c);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (l);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (u);
+
+	*hit = 0;
+	if (G->ncols == 0)
+		goto CLEANUP;
+
+	for (j = 0; j < ncols; j++)
+	{
+		if (cols[j].del == 0)
+		{
+			deg = 0;
+			for (k = 0; k < cols[j].deg && deg <= 1; k++)
+			{
+				if (cols[j].adj[k]->del == 0)
+				{
+					single = k;
+					deg++;
+				}
+			}
+			if (deg == 1)
+			{
+				irow = cols[j].adj[single]->row;
+				EGLPNUM_TYPENAME_EGlpNumCopy (b, cols[j].adj[single]->coef);
+				b_edge = cols[j].adj[single];
+
+				get_implied_variable_bounds (G, j, b_edge, &lb, &ub);
+
+				/*if (lb >= cols[j].lower && ub <= cols[j].upper) */
+				if (EGLPNUM_TYPENAME_EGlpNumIsLeq (cols[j].lower, lb) &&
+						EGLPNUM_TYPENAME_EGlpNumIsLeq (ub, cols[j].upper))
+				{
+					edge *a_edge;
+
+					/*  The jth variable can be substituted out of problem */
+					/*        x = (c/b) - (a/b)y                           */
+
+
+					rval = get_next_preop (pre, &op);
+					ILL_CLEANUP_IF (rval);
+
+					op->colindex = j;
+					op->rowindex = irow;
+					op->ptype = ILL_PRE_DELETE_FREE_SINGLETON_VARIABLE;
+
+					rval = grab_lp_line (G, irow, &op->line, 0);
+					ILL_CLEANUP_IF (rval);
+					pre->opcount++;
+
+					/*  Adjust the objective function                      */
+					/*     dy ==> (d - (e/b))ay   (e is obj coef of y)     */
+					/*eb = cols[j].obj / b; */
+					EGLPNUM_TYPENAME_EGlpNumCopyFrac (eb, cols[j].obj, b);
+
+					for (k = 0; k < rows[irow].deg; k++)
+					{
+						a_edge = rows[irow].adj[k];
+						if (a_edge->del == 0 && a_edge != b_edge)
+						{
+							/*cols[a_edge->col].obj -= (eb * a_edge->coef); */
+							EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (cols[a_edge->col].obj, eb, a_edge->coef);
+						}
+					}
+
+
+					/*  Delete y from graph */
+
+					cols[j].del = 1;
+
+					/*  Delete equation ay + bx = c */
+
+					rows[irow].del = 1;
+					for (k = 0; k < rows[irow].deg; k++)
+					{
+						rows[irow].adj[k]->del = 1;
+					}
+
+				}
+				else
+				{
+					rdeg = 0;
+					for (k = 0; k < rows[irow].deg && rdeg <= 2; k++)
+					{
+						if (rows[irow].adj[k]->del == 0)
+						{
+							rdeg++;
+						}
+					}
+					if (rdeg == 2)
+					{
+						edge *a_edge = 0;
+						int col2 = 0;
+
+						EGLPNUM_TYPENAME_EGlpNumCopy (newub, EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+						EGLPNUM_TYPENAME_EGlpNumCopy (newlb, EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+						EGLPNUM_TYPENAME_EGlpNumZero (a);
+
+						/*    ay + bx = c                                */
+						/*    l <= x <= u                                */
+						/*      x - is column singleton                  */
+						/*      derive bounds on y and substitute out x  */
+
+						EGLPNUM_TYPENAME_EGlpNumCopy (c, rows[irow].rhs);
+						EGLPNUM_TYPENAME_EGlpNumCopy (l, cols[j].lower);
+						EGLPNUM_TYPENAME_EGlpNumCopy (u, cols[j].upper);
+
+						/* Find the ay term */
+
+						for (k = 0; k < rows[irow].deg; k++)
+						{
+							if (rows[irow].adj[k]->del == 0 && rows[irow].adj[k]->col != j)
+							{
+								a_edge = rows[irow].adj[k];
+								EGLPNUM_TYPENAME_EGlpNumCopy (a, rows[irow].adj[k]->coef);
+								col2 = rows[irow].adj[k]->col;
+								break;
+							}
+						}
+						if (k == rows[irow].deg)
+						{
+							QSlog("graph error in singleton_col");
+							rval = 1;
+							goto CLEANUP;
+						}
+
+						/*  Record the operation             */
+						/*  x is column j,  y is column col2 */
+
+						rval = get_next_preop (pre, &op);
+						ILL_CLEANUP_IF (rval);
+
+						op->colindex = j;
+						op->rowindex = irow;
+						op->ptype = ILL_PRE_DELETE_SINGLETON_VARIABLE;
+
+						rval = grab_lp_line (G, irow, &op->line, 0);
+						ILL_CLEANUP_IF (rval);
+						pre->opcount++;
+
+						/*  Adjust the bounds on y           */
+						/*  Using x = c/b - (a/b)y            */
+						/* we use eb as temporal variable here */
+						/*if (a / b > 0) */
+						EGLPNUM_TYPENAME_EGlpNumCopyFrac (eb, a, b);
+						if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (eb))
+						{
+							/*if (l > -EGLPNUM_TYPENAME_ILL_MAXDOUBLE) */
+							if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_ILL_MINDOUBLE, l))
+							{
+								/*newub = (c / a) - (l * b) / a; */
+								EGLPNUM_TYPENAME_EGlpNumCopy (newub, c);
+								EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (newub, l, b);
+								EGLPNUM_TYPENAME_EGlpNumDivTo (newub, a);
+							}
+							/*if (u < EGLPNUM_TYPENAME_ILL_MAXDOUBLE) */
+							if (EGLPNUM_TYPENAME_EGlpNumIsLess (u, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+							{
+								/*newlb = (c / a) - (u * b) / a; */
+								EGLPNUM_TYPENAME_EGlpNumCopy (newlb, c);
+								EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (newlb, u, b);
+								EGLPNUM_TYPENAME_EGlpNumDivTo (newlb, a);
+							}
+						}
+						else
+						{
+							/*if (l > -EGLPNUM_TYPENAME_ILL_MAXDOUBLE) */
+							if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_ILL_MINDOUBLE, l))
+							{
+								/*newlb = (c / a) - (l * b) / a; */
+								EGLPNUM_TYPENAME_EGlpNumCopy (newlb, c);
+								EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (newlb, l, b);
+								EGLPNUM_TYPENAME_EGlpNumDivTo (newlb, a);
+							}
+							/*if (u < EGLPNUM_TYPENAME_ILL_MAXDOUBLE) */
+							if (EGLPNUM_TYPENAME_EGlpNumIsLess (u, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+							{
+								/*newub = (c / a) - (u * b) / a; */
+								EGLPNUM_TYPENAME_EGlpNumCopy (newub, c);
+								EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (newub, u, b);
+								EGLPNUM_TYPENAME_EGlpNumDivTo (newub, a);
+							}
+						}
+
+						if (EGLPNUM_TYPENAME_EGlpNumIsLess (cols[col2].lower, newlb))
+							EGLPNUM_TYPENAME_EGlpNumCopy (cols[col2].lower, newlb);
+						if (EGLPNUM_TYPENAME_EGlpNumIsLess (newub, cols[col2].upper))
+							EGLPNUM_TYPENAME_EGlpNumCopy (cols[col2].upper, newub);
+						EGLPNUM_TYPENAME_EGlpNumSubTo (cols[col2].obj, eb);
+
+						/*  Delete x (and the bx term) from graph */
+
+						cols[j].del = 1;
+						b_edge->del = 1;
+
+						/*  Delete equation ay + bx = c (and the ax term) */
+
+						rows[irow].del = 1;
+						a_edge->del = 1;
+					}
+				}
+			}
+		}
+	}
+
+
+CLEANUP:
+
+	EGLPNUM_TYPENAME_EGlpNumClearVar (lb);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (ub);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (eb);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (b);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (newlb);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (newub);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (a);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (c);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (l);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (u);
+	ILL_RETURN (rval, "singleton_columns");
+}
+
+static int duplicate_rows (
+	graph * G,
+	int *hit)
+{
+	int rval = 0;
+	node *cols = G->cols;
+	node *rows = G->rows;
+	int ncols = G->ncols;
+	int nrows = G->nrows;
+	int *s = 0;
+	EGLPNUM_TYPE *f = 0;
+	double szeit = ILLutil_zeit ();
+	EGLPNUM_TYPE q;
+	int i, j, k, k2, ri, r0 = 0, n, nu = 0, got, t0, t = 1;
+	node *c;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (q);
+
+
+	/*  Code follows J. Tomlin and J. S. Welch, OR Letters 5 (1986) 7--11 */
+
+	*hit = 0;
+	if (nrows == 0)
+		goto CLEANUP;
+
+	ILL_SAFE_MALLOC (s, nrows, int);
+
+	f = EGLPNUM_TYPENAME_EGlpNumAllocArray (nrows);
+
+	for (i = 0; i < nrows; i++)
+	{
+		if (rows[i].del || rows[i].rowsense != 'E')
+		{
+			s[i] = EGLPNUM_TYPENAME_ILL_MAXINT;				/* EGLPNUM_TYPENAME_ILL_MAXINT means no longer eligible    */
+		}
+		else
+		{
+			s[i] = 0;									/* 0 means eligible, >0 means in a group */
+			nu++;											/* Tracks the number of eligible rows    */
+		}
+	}
+
+	for (j = 0; j < ncols; j++)
+	{
+		c = &cols[j];
+		if (c->del)
+			continue;
+		if (c->coltype != ILL_PRE_COL_STRUC)
+			continue;
+
+		n = 0;
+		t0 = t++;
+
+		for (k = 0; k < c->deg; k++)
+		{
+			if (c->adj[k]->del)
+				continue;
+
+			ri = c->adj[k]->row;
+			if (s[ri] == 0)
+			{
+				s[ri] = t0;
+				EGLPNUM_TYPENAME_EGlpNumCopy (f[ri], c->adj[k]->coef);
+				r0 = ri;
+				n++;
+			}
+			else if (s[ri] < t0)
+			{
+				got = 0;
+				for (k2 = k + 1; k2 < c->deg; k2++)
+				{
+					if (c->adj[k2]->del)
+						continue;
+
+					i = c->adj[k2]->row;
+					if (s[i] == s[ri])
+					{
+						/*q = (c->adj[k]->coef * (f[i])) / (f[ri] * (c->adj[k2]->coef)); */
+						EGLPNUM_TYPENAME_EGlpNumCopy (q, c->adj[k]->coef);
+						EGLPNUM_TYPENAME_EGlpNumMultTo (q, f[i]);
+						EGLPNUM_TYPENAME_EGlpNumDivTo (q, f[ri]);
+						EGLPNUM_TYPENAME_EGlpNumDivTo (q, c->adj[k2]->coef);
+						if (EGLPNUM_TYPENAME_EGlpNumIsEqual (q, EGLPNUM_TYPENAME_oneLpNum, ILL_PRE_ZERO_TOL))
+						{
+							s[ri] = t;
+							s[i] = t;
+							got++;
+						}
+					}
+				}
+				if (got)
+				{
+					t++;
+				}
+				else
+				{
+					s[ri] = EGLPNUM_TYPENAME_ILL_MAXINT;
+					if (--nu == 0)
+						goto DONE;
+				}
+			}
+		}
+
+		if (n == 1)
+		{
+			s[r0] = EGLPNUM_TYPENAME_ILL_MAXINT;
+			if (--nu == 0)
+				goto DONE;
+		}
+	}
+
+DONE:
+
+	{
+		int idup = 0;
+
+		for (i = 0; i < nrows; i++)
+		{
+			if (s[i] > 0 && s[i] < EGLPNUM_TYPENAME_ILL_MAXINT)
+			{
+				QSlog("Row %d: %d", i, s[i]);
+				idup++;
+			}
+		}
+		QSlog("Number of duplicate rows: %d", idup);
+	}
+
+	QSlog("Time in duplicate_rows: %.2f (seconds)", ILLutil_zeit () - szeit);
+
+CLEANUP:
+
+	ILL_IFFREE (s, int);
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (f);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (q);
+	ILL_RETURN (rval, "duplicate_rows");
+}
+
+static int duplicate_cols (
+	graph * G,
+	int *hit)
+{
+	int rval = 0;
+	node *cols = G->cols;
+	node *rows = G->rows;
+	int ncols = G->ncols;
+	int nrows = G->nrows;
+	int *s = 0;
+	EGLPNUM_TYPE *f = 0;
+	double szeit = ILLutil_zeit ();
+	EGLPNUM_TYPE q;
+	int i, j, k, k2, ci, c0 = 0, n, nu = 0, got, t0, t = 1;
+	node *r;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (q);
+
+
+	/*  Code follows J. Tomlin and J. S. Welch, OR Letters 5 (1986) 7--11 */
+
+	*hit = 0;
+	if (ncols == 0)
+		goto CLEANUP;
+
+	ILL_SAFE_MALLOC (s, ncols, int);
+
+	f = EGLPNUM_TYPENAME_EGlpNumAllocArray (ncols);
+
+	for (j = 0; j < ncols; j++)
+	{
+		if (cols[j].del || cols[j].coltype != ILL_PRE_COL_STRUC)
+		{
+			s[j] = EGLPNUM_TYPENAME_ILL_MAXINT;				/* EGLPNUM_TYPENAME_ILL_MAXINT means no longer eligible    */
+		}
+		else
+		{
+			s[j] = 0;									/* 0 means eligible, >0 means in a group */
+			nu++;											/* Tracks the number of eligible rows    */
+		}
+	}
+
+	for (i = 0; i < nrows; i++)
+	{
+		r = &rows[i];
+		if (r->del)
+			continue;
+
+		n = 0;
+		t0 = t++;
+
+		for (k = 0; k < r->deg; k++)
+		{
+			if (r->adj[k]->del)
+				continue;
+
+			ci = r->adj[k]->col;
+			if (s[ci] == 0)
+			{
+				s[ci] = t0;
+				EGLPNUM_TYPENAME_EGlpNumCopy (f[ci], r->adj[k]->coef);
+				c0 = ci;
+				n++;
+			}
+			else if (s[ci] < t0)
+			{
+				got = 0;
+				for (k2 = k + 1; k2 < r->deg; k2++)
+				{
+					if (r->adj[k2]->del)
+						continue;
+
+					j = r->adj[k2]->col;
+					if (s[j] == s[ci])
+					{
+						/*q = (r->adj[k]->coef * (f[j])) / (f[ci] * (r->adj[k2]->coef)); */
+						EGLPNUM_TYPENAME_EGlpNumCopy (q, r->adj[k]->coef);
+						EGLPNUM_TYPENAME_EGlpNumMultTo (q, f[j]);
+						EGLPNUM_TYPENAME_EGlpNumDivTo (q, f[ci]);
+						EGLPNUM_TYPENAME_EGlpNumDivTo (q, r->adj[k2]->coef);
+						if (EGLPNUM_TYPENAME_EGlpNumIsEqual (q, EGLPNUM_TYPENAME_oneLpNum, ILL_PRE_ZERO_TOL))
+						{
+							s[ci] = t;
+							s[j] = t;
+							got++;
+						}
+					}
+				}
+				if (got)
+				{
+					t++;
+				}
+				else
+				{
+					s[ci] = EGLPNUM_TYPENAME_ILL_MAXINT;
+					if (--nu == 0)
+						goto DONE;
+				}
+			}
+		}
+
+		if (n == 1)
+		{
+			s[c0] = EGLPNUM_TYPENAME_ILL_MAXINT;
+			if (--nu == 0)
+				goto DONE;
+		}
+	}
+
+DONE:
+
+	{
+		int dcount;
+		int *dcnt;
+		int *dlist;
+
+		rval = gather_dup_lists (s, ncols, &dcount, &dcnt, &dlist);
+		ILL_CLEANUP_IF (rval);
+	}
+
+	QSlog("Time in duplicate_cols: %.2f (seconds)", ILLutil_zeit () - szeit);
+
+CLEANUP:
+
+	ILL_IFFREE (s, int);
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (f);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (q);
+	ILL_RETURN (rval, "duplicate_cols");
+}
+
+static int gather_dup_lists (
+	/* graph *G, */ int *s,
+	/* double *f, */
+	int count,
+	int *duptotal,
+	int **dupcnt,
+	int **dupind)
+{
+	int rval = 0;
+	int *cnt = 0;
+	int *ind = 0;
+	int *beg = 0;
+	int i, smax = 0, ndup = 0, total = 0;
+
+	*duptotal = 0;
+	*dupcnt = 0;
+	*dupind = 0;
+
+
+	for (i = 0; i < count; i++)
+	{
+		if (s[i] < EGLPNUM_TYPENAME_ILL_MAXINT && s[i] > smax)
+			smax = s[i];
+	}
+	if (smax == 0)
+		goto CLEANUP;
+
+	ILL_SAFE_MALLOC (cnt, smax + 1, int);
+
+	ILL_SAFE_MALLOC (ind, smax + 1, int);
+
+	for (i = 0; i < smax + 1; i++)
+	{
+		cnt[i] = 0;
+	}
+
+	for (i = 0; i < count; i++)
+	{
+		if (s[i] < EGLPNUM_TYPENAME_ILL_MAXINT)
+		{
+			cnt[s[i]]++;
+		}
+	}
+
+	if (cnt[0] > 0)
+		QSlog("%d Empty Lines", cnt[0]);
+
+	QSlog("Duplicate Classes:");
+	for (i = 1; i < smax + 1; i++)
+	{
+		if (cnt[i] > 1)
+		{
+			ndup++;
+			QSlog(" %d", cnt[i]);
+		}
+	}
+	QSlog("  Number %d\n", ndup);
+
+	if (ndup == 0)
+		goto CLEANUP;
+
+	ILL_SAFE_MALLOC (beg, ndup, int);
+
+	for (i = 1, ndup = 0; i < smax + 1; i++)
+	{
+		if (cnt[i] > 1)
+		{
+			beg[ndup] = total;
+			total += cnt[i];
+			ind[i] = ndup;
+			ndup++;
+		}
+	}
+
+	if (total == 0)
+		goto CLEANUP;
+
+	ILL_SAFE_MALLOC (*dupcnt, ndup, int);
+
+	ILL_SAFE_MALLOC (*dupind, total, int);
+
+	for (i = 0; i < ndup; i++)
+	{
+		(*dupcnt)[i] = 0;
+	}
+
+	for (i = 0; i < count; i++)
+	{
+		if (s[i] < EGLPNUM_TYPENAME_ILL_MAXINT && s[i] > 0)
+		{
+			if (cnt[s[i]] > 1)
+			{
+				(*dupind)[beg[ind[s[i]]] + (*dupcnt)[ind[s[i]]]] = i;
+				(*dupcnt)[ind[s[i]]]++;
+			}
+		}
+	}
+
+	for (i = 0; i < ndup; i++)
+	{
+		int j;
+
+		for (j = beg[i]; j < beg[i] + (*dupcnt)[i]; j++)
+		{
+			QSlog(" %d", (*dupind)[j]);
+		}
+		QSlog(" | ");
+	}
+
+	*duptotal = ndup;
+
+CLEANUP:
+
+	ILL_IFFREE (cnt, int);
+	ILL_IFFREE (ind, int);
+	ILL_IFFREE (beg, int);
+
+	ILL_RETURN (rval, "gather_dup_lists");
+}
+
+static void set_fixed_variable (
+	graph * G,
+	int j,
+	EGLPNUM_TYPE val)
+{
+	int k;
+	edge *e;
+
+	G->cols[j].del = 1;
+	for (k = 0; k < G->cols[j].deg; k++)
+	{
+		e = G->cols[j].adj[k];
+		if (e->del == 0)
+		{
+			/*G->rows[e->row].rhs -= (e->coef * val); */
+			EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (G->rows[e->row].rhs, e->coef, val);
+			e->del = 1;
+		}
+	}
+}
+
+static void get_implied_rhs_bounds (
+	graph * G,
+	int i,
+	EGLPNUM_TYPE * lb,
+	EGLPNUM_TYPE * ub)
+{
+	int k;
+	EGLPNUM_TYPE l, u;
+	node *cols = G->cols;
+	node *rows = G->rows;
+	edge *e;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (u);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (l);
+
+	EGLPNUM_TYPENAME_EGlpNumZero (l);
+	for (k = 0; k < rows[i].deg; k++)
+	{
+		e = rows[i].adj[k];
+		if (e->del == 0)
+		{
+			if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (e->coef))
+			{
+				if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (cols[e->col].upper, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+				{
+					EGLPNUM_TYPENAME_EGlpNumCopy (l, EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+					break;
+				}
+				else
+				{
+					/*l += (e->coef * cols[e->col].upper); */
+					EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (l, e->coef, cols[e->col].upper);
+				}
+			}
+			else if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (e->coef))
+			{
+				if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (cols[e->col].lower, EGLPNUM_TYPENAME_ILL_MINDOUBLE))
+				{
+					EGLPNUM_TYPENAME_EGlpNumCopy (l, EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+					break;
+				}
+				else
+				{
+					/*l += (e->coef * cols[e->col].lower); */
+					EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (l, e->coef, cols[e->col].lower);
+				}
+			}
+		}
+	}
+
+	EGLPNUM_TYPENAME_EGlpNumZero (u);
+	for (k = 0; k < rows[i].deg; k++)
+	{
+		e = rows[i].adj[k];
+		if (e->del == 0)
+		{
+			if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (e->coef ))
+			{
+				if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (cols[e->col].lower, EGLPNUM_TYPENAME_ILL_MINDOUBLE))
+				{
+					EGLPNUM_TYPENAME_EGlpNumCopy (u, EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+				}
+				else
+				{
+					/*u += (e->coef * cols[e->col].lower); */
+					EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (u, e->coef, cols[e->col].lower);
+				}
+			}
+			else if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (e->coef))
+			{
+				if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (cols[e->col].upper, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+				{
+					EGLPNUM_TYPENAME_EGlpNumCopy (u, EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+				}
+				else
+				{
+					/*u += (e->coef * cols[e->col].upper); */
+					EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (u, e->coef, cols[e->col].upper);
+				}
+			}
+		}
+	}
+
+	EGLPNUM_TYPENAME_EGlpNumCopy (*lb, l);
+	EGLPNUM_TYPENAME_EGlpNumCopy (*ub, u);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (u);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (l);
+}
+
+static void get_implied_variable_bounds (
+	graph * G,
+	int j,
+	edge * a_ij,
+	EGLPNUM_TYPE * lb,
+	EGLPNUM_TYPE * ub)
+{
+	int i = a_ij->row;
+	EGLPNUM_TYPE l, u;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (u);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (l);
+
+	get_implied_rhs_bounds (G, i, &l, &u);
+	EGLPNUM_TYPENAME_EGlpNumCopy (*lb, EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+	EGLPNUM_TYPENAME_EGlpNumCopy (*ub, EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+
+	if (EGLPNUM_TYPENAME_EGlpNumIsLess (ILL_PRE_FEAS_TOL, a_ij->coef))
+	{
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (u, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+		{
+			/**lb = (G->rows[i].rhs - u) / a_ij->coef + G->cols[j].upper;*/
+			EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (*lb, G->rows[i].rhs, u, a_ij->coef);
+			EGLPNUM_TYPENAME_EGlpNumAddTo (*lb, G->cols[j].upper);
+		}
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_ILL_MINDOUBLE, l))
+		{
+			/**ub = (G->rows[i].rhs - l) / a_ij->coef + G->cols[j].lower;*/
+			EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (*ub, G->rows[i].rhs, l, a_ij->coef);
+			EGLPNUM_TYPENAME_EGlpNumAddTo (*ub, G->cols[j].lower);
+		}
+	}
+	else if (EGLPNUM_TYPENAME_EGlpNumIsLess (a_ij->coef, ILL_PRE_FEAS_TOL))
+	{
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_ILL_MINDOUBLE, l))
+		{
+			/**lb = (G->rows[i].rhs - l) / a_ij->coef + G->cols[j].upper;*/
+			EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (*lb, G->rows[i].rhs, l, a_ij->coef);
+			EGLPNUM_TYPENAME_EGlpNumAddTo (*lb, G->cols[j].upper);
+		}
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (u, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+		{
+			/**ub = (G->rows[i].rhs - u) / a_ij->coef + G->cols[j].lower;*/
+			EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (*ub, G->rows[i].rhs, u, a_ij->coef);
+			EGLPNUM_TYPENAME_EGlpNumAddTo (*ub, G->cols[j].lower);
+		}
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (u);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (l);
+}
+
+static int get_next_preop (
+	EGLPNUM_TYPENAME_ILLlp_predata * pre,
+	EGLPNUM_TYPENAME_ILLlp_preop ** op)
+{
+	int rval = 0;
+
+	if (pre->opcount >= pre->opsize)
+	{
+		pre->opsize *= 1.3;
+		pre->opsize += 1000;
+		if (pre->opsize < pre->opcount + 1)
+			pre->opsize = pre->opcount + 1;
+		pre->oplist = EGrealloc (pre->oplist, sizeof (EGLPNUM_TYPENAME_ILLlp_preop) * pre->opsize);
+		//rval = ILLutil_reallocrus_scale ((void **) &pre->oplist,
+		//                                 &pre->opsize, pre->opcount + 1, 1.3,
+		//                                 sizeof (EGLPNUM_TYPENAME_ILLlp_preop));
+		//ILL_CLEANUP_IF (rval);
+	}
+	*op = &pre->oplist[pre->opcount];
+	EGLPNUM_TYPENAME_ILLlp_preop_init (*op);
+
+//CLEANUP:
+
+	ILL_RETURN (rval, "get_next_preop");
+}
+
+static int add_to_list (
+	ILLptrworld * world,
+	intptr ** list,
+	int i)
+{
+	int rval = 0;
+	intptr *ip;
+
+	ip = intptralloc (world);
+	if (!ip)
+	{
+		rval = 1;
+		goto CLEANUP;
+	}
+	ip->this_val = i;
+	ip->next = *list;
+	*list = ip;
+
+CLEANUP:
+
+	ILL_RETURN (rval, "add_to_list");
+}
+
+static int build_graph (
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	graph * G)
+{
+	int rval = 0;
+	int ncols = lp->ncols;
+	int nrows = lp->nrows;
+	int nzcount = lp->nzcount;
+	int i, j, k, stop, count;
+	edge *edgelist;
+	node *rows, *cols;
+	EGLPNUM_TYPENAME_ILLmatrix *A = &lp->A;
+
+	G->objsense = lp->objsense;
+
+	ILL_SAFE_MALLOC (G->rows, nrows, node);
+	if (!G->rows)
+	{
+		QSlog("out of memory in build_graph");
+		rval = 1;
+		goto CLEANUP;
+	}
+	rows = G->rows;
+
+	for (i = 0; i < nrows; i++)
+	{
+		rows[i].rowsense = lp->sense[i];
+		rows[i].deg = 0;
+	}
+
+	ILL_SAFE_MALLOC (G->cols, ncols, node);
+	ILL_SAFE_MALLOC (G->edgelist, nzcount, edge);
+	for (i = nzcount; i--;)
+		EGLPNUM_TYPENAME_EGlpNumInitVar ((G->edgelist[i].coef));
+	G->nzcount = nzcount;
+	ILL_SAFE_MALLOC (G->adjspace, 2 * nzcount, edge *);
+
+	if (!G->cols || !G->edgelist || !G->adjspace)
+	{
+		QSlog("out of memory in build_graph");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	cols = G->cols;
+	edgelist = G->edgelist;
+
+	for (j = 0; j < ncols; j++)
+	{
+		stop = A->matbeg[j] + A->matcnt[j];
+		for (k = A->matbeg[j]; k < stop; k++)
+		{
+			rows[A->matind[k]].deg++;
+		}
+	}
+
+	for (i = 0, count = 0; i < nrows; i++)
+	{
+		rows[i].adj = G->adjspace + count;
+		count += rows[i].deg;
+		rows[i].deg = 0;
+	}
+
+	for (j = 0; j < ncols; j++)
+	{
+		cols[j].adj = G->adjspace + count;
+		count += A->matcnt[j];
+		cols[j].deg = 0;
+		cols[j].coltype = ILL_PRE_COL_STRUC;
+	}
+	for (i = 0; i < nrows; i++)
+	{
+		cols[lp->rowmap[i]].coltype = ILL_PRE_COL_LOGICAL;
+	}
+
+	for (j = 0, count = 0; j < ncols; j++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (cols[j].obj, lp->obj[j]);
+		EGLPNUM_TYPENAME_EGlpNumCopy (cols[j].lower, lp->lower[j]);
+		EGLPNUM_TYPENAME_EGlpNumCopy (cols[j].upper, lp->upper[j]);
+		stop = A->matbeg[j] + A->matcnt[j];
+		for (k = A->matbeg[j]; k < stop; k++)
+		{
+			i = A->matind[k];
+			rows[i].adj[rows[i].deg++] = &(edgelist[count]);
+			cols[j].adj[cols[j].deg++] = &(edgelist[count]);
+			edgelist[count].row = i;
+			edgelist[count].col = j;
+			EGLPNUM_TYPENAME_EGlpNumCopy (edgelist[count].coef, A->matval[k]);
+			edgelist[count].mark = 0;
+			edgelist[count].del = 0;
+			edgelist[count].coltype = cols[j].coltype;
+			count++;
+		}
+	}
+	if (count != nzcount)
+	{
+		QSlog("counts are off in build_graph");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	G->ecount = count;
+	G->nrows = nrows;
+	G->ncols = ncols;
+
+	for (i = 0; i < G->nrows; i++)
+	{
+		G->rows[i].del = 0;
+		EGLPNUM_TYPENAME_EGlpNumCopy (G->rows[i].rhs, lp->rhs[i]);
+	}
+	for (j = 0; j < G->ncols; j++)
+	{
+		G->cols[j].del = 0;
+	}
+
+CLEANUP:
+
+	ILL_RETURN (rval, "build_graph");
+}
+
+static void dump_graph (
+	graph * G)
+{
+	int i, j, k;
+
+	QSlog("ecount = %d, nrows = %d, ncols = %d",
+							G->ecount, G->nrows, G->ncols);
+
+	for (i = 0; i < G->nrows; i++)
+	{
+		QSlog("Row %d:", i);
+		for (k = 0; k < G->rows[i].deg; k++)
+		{
+			QSlog(" %d", G->rows[i].adj[k]->col);
+			if (G->rows[i].adj[k]->coltype == ILL_PRE_COL_LOGICAL)
+				QSlog("S");
+			QSlog("(%g)", EGLPNUM_TYPENAME_EGlpNumToLf (G->rows[i].adj[k]->coef));
+		}
+		QSlog("  rhs: %g", EGLPNUM_TYPENAME_EGlpNumToLf (G->rows[i].rhs));
+		if (G->rows[i].del) QSlog(" (deleted)");
+	}
+
+	for (j = 0; j < G->ncols; j++)
+	{
+		if (G->cols[j].coltype == ILL_PRE_COL_LOGICAL)
+		{
+			QSlog("Slk %d:", j);
+		}
+		else
+		{
+			QSlog("Col %d:", j);
+		}
+		for (k = 0; k < G->cols[j].deg; k++)
+		{
+			QSlog(" %d", G->cols[j].adj[k]->row);
+		}
+		QSlog("  obj: %g  bnd: (%g, %g)", EGLPNUM_TYPENAME_EGlpNumToLf (G->cols[j].obj),
+								EGLPNUM_TYPENAME_EGlpNumToLf (G->cols[j].lower), EGLPNUM_TYPENAME_EGlpNumToLf (G->cols[j].upper));
+		if (G->cols[j].del) QSlog(" (deleted)");
+	}
+}
+
+static void init_graph (
+	graph * G)
+{
+	if (G)
+	{
+		G->edgelist = 0;
+		G->rows = 0;
+		G->cols = 0;
+		G->ecount = 0;
+		G->nrows = 0;
+		G->ncols = 0;
+		G->adjspace = 0;
+		ILLptrworld_init (&G->intptrworld);
+	}
+}
+
+static void free_graph (
+	graph * G)
+{
+	register int i;
+
+	if (G)
+	{
+		int total, onlist;
+
+		for (i = G->nzcount; i--;)
+			EGLPNUM_TYPENAME_EGlpNumClearVar ((G->edgelist[i].coef));
+		ILL_IFFREE (G->edgelist, edge);
+		ILL_IFFREE (G->rows, node);
+		ILL_IFFREE (G->cols, node);
+		ILL_IFFREE (G->adjspace, edge *);
+		if (intptr_check_leaks (&G->intptrworld, &total, &onlist))
+		{
+			QSlog("WARNING: %d outstanding intptrs", total - onlist);
+		}
+		ILLptrworld_delete (&G->intptrworld);
+		init_graph (G);
+	}
+}
+
+int EGLPNUM_TYPENAME_ILLlp_sinfo_print (
+	EGLPNUM_TYPENAME_ILLlp_sinfo * s)
+{
+	int rval = 0;
+	int i;
+	EGLPNUM_TYPENAME_ILLlpdata lp;
+	char *sense = 0;
+
+	EGLPNUM_TYPENAME_ILLlpdata_init (&lp);
+
+	lp.nrows = s->nrows;
+	lp.ncols = s->ncols;
+	lp.nzcount = s->nzcount;
+	lp.objsense = s->objsense;
+	lp.obj = s->obj;
+	lp.rhs = s->rhs;
+	lp.lower = s->lower;
+	lp.upper = s->upper;
+	lp.A.matval = s->A.matval;
+	lp.A.matcnt = s->A.matcnt;
+	lp.A.matbeg = s->A.matbeg;
+	lp.A.matind = s->A.matind;
+	lp.rownames = 0;
+	lp.colnames = s->colnames;
+	lp.objname = 0;
+	lp.probname = 0;
+	lp.intmarker = 0;
+
+	ILL_SAFE_MALLOC (sense, s->nrows, char);
+
+	if (!sense)
+	{
+		QSlog("out of memory in EGLPNUM_TYPENAME_ILLlp_sinfo_print");
+		rval = 1;
+		goto CLEANUP;
+	}
+	for (i = 0; i < s->nrows; i++)
+	{
+		sense[i] = 'E';
+	}
+	lp.sense = sense;
+
+/*
+    rval = ILLlpdata_writelp (&lp, 0);
+    ILL_CLEANUP_IF (rval);
+*/
+
+CLEANUP:
+
+	ILL_IFFREE (sense, char);
+
+	ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLlp_sinfo_print");
+}
+
+void EGLPNUM_TYPENAME_ILLlp_sinfo_init (
+	EGLPNUM_TYPENAME_ILLlp_sinfo * sinfo)
+{
+	if (sinfo)
+	{
+		sinfo->ncols = 0;
+		sinfo->nrows = 0;
+		sinfo->nzcount = 0;
+		sinfo->rowsize = 0;
+		sinfo->colsize = 0;
+		sinfo->obj = 0;
+		sinfo->rhs = 0;
+		sinfo->lower = 0;
+		sinfo->upper = 0;
+		sinfo->colnames = 0;
+		sinfo->objsense = EGLPNUM_TYPENAME_ILL_MIN;
+		EGLPNUM_TYPENAME_ILLmatrix_init (&sinfo->A);
+	}
+}
+
+void EGLPNUM_TYPENAME_ILLlp_sinfo_free (
+	EGLPNUM_TYPENAME_ILLlp_sinfo * sinfo)
+{
+	if (sinfo)
+	{
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (sinfo->obj);
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (sinfo->lower);
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (sinfo->upper);
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (sinfo->rhs);
+		EGLPNUM_TYPENAME_ILLmatrix_free (&sinfo->A);
+		if (sinfo->colnames)
+		{
+			int i;
+
+			for (i = 0; i < sinfo->ncols; i++)
+			{
+				ILL_IFFREE (sinfo->colnames[i], char);
+			}
+			ILL_IFFREE (sinfo->colnames, char *);
+		}
+		EGLPNUM_TYPENAME_ILLlp_sinfo_init (sinfo);
+	}
+}
+
+void EGLPNUM_TYPENAME_ILLlp_predata_init (
+	EGLPNUM_TYPENAME_ILLlp_predata * pre)
+{
+	if (pre)
+	{
+		pre->opcount = 0;
+		pre->opsize = 0;
+		pre->oplist = 0;
+		pre->r_nrows = 0;
+		pre->r_ncols = 0;
+		pre->colmap = 0;
+		pre->rowmap = 0;
+		pre->colscale = 0;
+		pre->rowscale = 0;
+		pre->colfixval = 0;
+		pre->rowfixval = 0;
+	}
+}
+
+void EGLPNUM_TYPENAME_ILLlp_predata_free (
+	EGLPNUM_TYPENAME_ILLlp_predata * pre)
+{
+	if (pre)
+	{
+		int i;
+
+		for (i = 0; i < pre->opcount; i++)
+		{
+			EGLPNUM_TYPENAME_ILLlp_preop_free (&pre->oplist[i]);
+		}
+		ILL_IFFREE (pre->oplist, EGLPNUM_TYPENAME_ILLlp_preop);
+		ILL_IFFREE (pre->colmap, int);
+		ILL_IFFREE (pre->rowmap, int);
+
+		ILL_IFFREE (pre->colscale, EGLPNUM_TYPE);
+		ILL_IFFREE (pre->rowscale, EGLPNUM_TYPE);
+		ILL_IFFREE (pre->colfixval, EGLPNUM_TYPE);
+		ILL_IFFREE (pre->rowfixval, EGLPNUM_TYPE);
+		EGLPNUM_TYPENAME_ILLlp_predata_init (pre);
+	}
+}
+
+void EGLPNUM_TYPENAME_ILLlp_preop_init (
+	EGLPNUM_TYPENAME_ILLlp_preop * op)
+{
+	if (op)
+	{
+		op->ptype = 0;
+		op->rowindex = -1;
+		op->colindex = -1;
+		EGLPNUM_TYPENAME_ILLlp_preline_init (&op->line);
+	}
+}
+
+void EGLPNUM_TYPENAME_ILLlp_preop_free (
+	EGLPNUM_TYPENAME_ILLlp_preop * op)
+{
+	if (op)
+	{
+		EGLPNUM_TYPENAME_ILLlp_preline_free (&op->line);
+		EGLPNUM_TYPENAME_ILLlp_preop_init (op);
+	}
+}
+
+void EGLPNUM_TYPENAME_ILLlp_preline_init (
+	EGLPNUM_TYPENAME_ILLlp_preline * line)
+{
+	if (line)
+	{
+		EGLPNUM_TYPENAME_EGlpNumInitVar (line->rhs);
+		EGLPNUM_TYPENAME_EGlpNumInitVar (line->obj);
+		EGLPNUM_TYPENAME_EGlpNumInitVar (line->upper);
+		EGLPNUM_TYPENAME_EGlpNumInitVar (line->lower);
+		EGLPNUM_TYPENAME_EGlpNumZero (line->rhs);
+		EGLPNUM_TYPENAME_EGlpNumZero (line->obj);
+		EGLPNUM_TYPENAME_EGlpNumZero (line->upper);
+		EGLPNUM_TYPENAME_EGlpNumZero (line->lower);
+		line->count = 0;
+		line->ind = 0;
+		line->val = 0;
+	}
+}
+
+void EGLPNUM_TYPENAME_ILLlp_preline_free (
+	EGLPNUM_TYPENAME_ILLlp_preline * line)
+{
+	if (line)
+	{
+		EGLPNUM_TYPENAME_EGlpNumClearVar (line->rhs);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (line->obj);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (line->upper);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (line->lower);
+		ILL_IFFREE (line->ind, int);
+
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (line->val);
+		//EGLPNUM_TYPENAME_ILLlp_preline_init (line);
+	}
+}
diff --git a/qsopt_ex/presolve.h b/qsopt_ex/presolve.h
new file mode 100644
index 0000000..172fc8a
--- /dev/null
+++ b/qsopt_ex/presolve.h
@@ -0,0 +1,41 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+#ifndef EGLPNUM_TYPENAME_PRESOLVE_H
+#define EGLPNUM_TYPENAME_PRESOLVE_H
+
+#include "lpdata_EGLPNUM_TYPENAME.h"
+
+void EGLPNUM_TYPENAME_ILLlp_sinfo_init(EGLPNUM_TYPENAME_ILLlp_sinfo * sinfo);
+void EGLPNUM_TYPENAME_ILLlp_sinfo_free(EGLPNUM_TYPENAME_ILLlp_sinfo * sinfo);
+int EGLPNUM_TYPENAME_ILLlp_sinfo_print(EGLPNUM_TYPENAME_ILLlp_sinfo * s);
+
+void EGLPNUM_TYPENAME_ILLlp_predata_init(EGLPNUM_TYPENAME_ILLlp_predata * pre);
+void EGLPNUM_TYPENAME_ILLlp_predata_free(EGLPNUM_TYPENAME_ILLlp_predata * pre);
+
+void EGLPNUM_TYPENAME_ILLlp_preop_init(EGLPNUM_TYPENAME_ILLlp_preop * op);
+void EGLPNUM_TYPENAME_ILLlp_preop_free(EGLPNUM_TYPENAME_ILLlp_preop * op);
+
+void EGLPNUM_TYPENAME_ILLlp_preline_init(EGLPNUM_TYPENAME_ILLlp_preline * line);
+void EGLPNUM_TYPENAME_ILLlp_preline_free(EGLPNUM_TYPENAME_ILLlp_preline * line);
+
+#endif /* ! EGLPNUM_TYPENAME_PRESOLVE_H */
diff --git a/qsopt_ex/price.c b/qsopt_ex/price.c
new file mode 100644
index 0000000..dcc6e9c
--- /dev/null
+++ b/qsopt_ex/price.c
@@ -0,0 +1,1640 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: price.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+//static int TRACE = 0;
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "allocrus.h"
+#include "eg_lpnum.h"
+#include "eg_numutil_EGLPNUM_TYPENAME.h"
+#include "eg_io.h"
+#include "except.h"
+#include "util.h"
+
+#include "stddefs.h"
+#include "qsopt_EGLPNUM_TYPENAME.h"
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+#include "fct_EGLPNUM_TYPENAME.h"
+#include "price_EGLPNUM_TYPENAME.h"
+#include "basis_EGLPNUM_TYPENAME.h"
+#include "dstruct_EGLPNUM_TYPENAME.h"
+
+#define  MULTIP 1
+#define  PRICE_DEBUG 0
+
+
+static void update_d_scaleinf (
+	EGLPNUM_TYPENAME_price_info * const p,
+	EGLPNUM_TYPENAME_heap * const h,
+	int const j,
+	EGLPNUM_TYPE inf,
+	int const prule),
+  update_p_scaleinf (
+	EGLPNUM_TYPENAME_price_info * const p,
+	EGLPNUM_TYPENAME_heap * const h,
+	int const i,
+	EGLPNUM_TYPE inf,
+	int const prule);
+
+static void compute_dualI_inf (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	int const j,
+	EGLPNUM_TYPE * const inf),
+  compute_dualII_inf (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	int const j,
+	EGLPNUM_TYPE * const inf),
+  compute_primalI_inf (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	int const i,
+	EGLPNUM_TYPE * const inf),
+  compute_primalII_inf (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	int const i,
+	EGLPNUM_TYPE * const inf);
+
+void EGLPNUM_TYPENAME_ILLprice_free_heap (
+	EGLPNUM_TYPENAME_price_info * const pinf)
+{
+	EGLPNUM_TYPENAME_ILLheap_free (&(pinf->h));
+}
+
+int EGLPNUM_TYPENAME_ILLprice_build_heap (
+	EGLPNUM_TYPENAME_price_info * const pinf,
+	int const nkeys,
+	EGLPNUM_TYPE * keylist)
+{
+	EGLPNUM_TYPENAME_ILLheap_init (&(pinf->h));
+	EGLPNUM_TYPENAME_EGlpNumSet (pinf->htrigger,
+							1.0 +
+							(double) nkeys / (PARAM_HEAP_RATIO * ILLutil_our_log2 (nkeys)));
+	return EGLPNUM_TYPENAME_ILLheap_build (&(pinf->h), nkeys, keylist);
+}
+
+int EGLPNUM_TYPENAME_ILLprice_test_for_heap (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_price_info * const pinf,
+	int const nkeys,
+	EGLPNUM_TYPE * keylist,
+	int const algo,
+	int const upd)
+{
+	EGLPNUM_TYPENAME_heap *const h = &(pinf->h);
+	int rval = 0;
+	EGLPNUM_TYPE ravg;
+
+	if (upd != 0)
+	{
+		EGLPNUM_TYPENAME_EGlpNumInitVar (ravg);
+		if (algo == PRIMAL_SIMPLEX)
+			EGLPNUM_TYPENAME_EGlpNumCopy (ravg, lp->cnts->za_ravg);
+		else
+			EGLPNUM_TYPENAME_EGlpNumCopy (ravg, lp->cnts->y_ravg);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLeq (ravg, pinf->htrigger))
+			pinf->hineff--;
+		else
+		{
+			EGLPNUM_TYPENAME_EGlpNumDivUiTo (ravg, 2U);
+			if (EGLPNUM_TYPENAME_EGlpNumIsLess (pinf->htrigger, ravg))
+				pinf->hineff++;
+		}
+		EGLPNUM_TYPENAME_EGlpNumClearVar (ravg);
+	}
+	if (h->hexist == 0 && pinf->hineff <= 0)
+	{
+		rval = EGLPNUM_TYPENAME_ILLprice_build_heap (pinf, nkeys, keylist);
+		CHECKRVALG (rval, CLEANUP);
+	}
+	else if (h->hexist != 0 && pinf->hineff >= PARAM_HEAP_UTRIGGER)
+	{
+		EGLPNUM_TYPENAME_ILLprice_free_heap (pinf);
+		/*
+		 * QSlog("freeing EGLPNUM_TYPENAME_heap ..");
+		 * QSlog("iter = %d, ravg = %.2f, trigger = %.2f",
+		 * lp->cnts->tot_iter, ravg, pinf->htrigger);
+		 */
+	}
+
+CLEANUP:
+	if (rval)
+		EGLPNUM_TYPENAME_ILLprice_free_heap (pinf);
+	return rval;
+}
+
+void EGLPNUM_TYPENAME_ILLprice_init_pricing_info (
+	EGLPNUM_TYPENAME_price_info * const pinf)
+{
+	pinf->p_strategy = -1;
+	pinf->d_strategy = -1;
+	pinf->pI_price = -1;
+	pinf->pII_price = -1;
+	pinf->dI_price = -1;
+	pinf->dII_price = -1;
+	pinf->cur_price = -1;
+	pinf->p_scaleinf = 0;
+	pinf->d_scaleinf = 0;
+	pinf->pdinfo.norms = 0;
+	pinf->pdinfo.refframe = 0;
+	pinf->psinfo.norms = 0;
+	pinf->ddinfo.norms = 0;
+	pinf->ddinfo.refframe = 0;
+	pinf->dsinfo.norms = 0;
+	pinf->dmpinfo.gstart = pinf->pmpinfo.gstart = 0;
+	pinf->dmpinfo.gshift = pinf->pmpinfo.gshift = 0;
+	pinf->dmpinfo.gsize = pinf->pmpinfo.gsize = 0;
+	pinf->dmpinfo.bucket = pinf->pmpinfo.bucket = 0;
+	pinf->dmpinfo.perm = pinf->pmpinfo.perm = 0;
+	pinf->dmpinfo.infeas = pinf->pmpinfo.infeas = 0;
+	EGLPNUM_TYPENAME_ILLheap_init (&(pinf->h));
+	EGLPNUM_TYPENAME_EGlpNumZero (pinf->htrigger);
+	pinf->hineff = 0;
+}
+
+void EGLPNUM_TYPENAME_ILLprice_free_pricing_info (
+	EGLPNUM_TYPENAME_price_info * const pinf)
+{
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (pinf->p_scaleinf);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (pinf->d_scaleinf);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (pinf->pdinfo.norms);
+	ILL_IFFREE (pinf->pdinfo.refframe, int);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (pinf->psinfo.norms);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (pinf->ddinfo.norms);
+	ILL_IFFREE (pinf->ddinfo.refframe, int);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (pinf->dsinfo.norms);
+
+	EGLPNUM_TYPENAME_ILLprice_free_mpartial_info (&(pinf->pmpinfo));
+	EGLPNUM_TYPENAME_ILLprice_free_mpartial_info (&(pinf->dmpinfo));
+	EGLPNUM_TYPENAME_ILLprice_free_heap (pinf);
+}
+
+int EGLPNUM_TYPENAME_ILLprice_build_pricing_info (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_price_info * const pinf,
+	int const phase)
+{
+	int rval = 0;
+	int p_price = -1;
+	int d_price = -1;
+
+	switch (phase)
+	{
+	case PRIMAL_PHASEI:
+		p_price = pinf->pI_price;
+		break;
+	case PRIMAL_PHASEII:
+		p_price = pinf->pII_price;
+		break;
+	case DUAL_PHASEI:
+		d_price = pinf->dI_price;
+		break;
+	case DUAL_PHASEII:
+		d_price = pinf->dII_price;
+		break;
+	}
+
+	if (p_price != -1)
+	{
+		pinf->cur_price = p_price;
+
+		if (p_price == QS_PRICE_PDANTZIG || p_price == QS_PRICE_PDEVEX ||
+				p_price == QS_PRICE_PSTEEP)
+		{
+			pinf->p_strategy = COMPLETE_PRICING;
+			EGLPNUM_TYPENAME_EGlpNumFreeArray (pinf->d_scaleinf);
+			pinf->d_scaleinf = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nnbasic);
+		}
+		else if (p_price == QS_PRICE_PMULTPARTIAL)
+			pinf->p_strategy = MULTI_PART_PRICING;
+
+		switch (p_price)
+		{
+		case QS_PRICE_PDEVEX:
+			if (pinf->pdinfo.norms)
+				return rval;
+			rval = EGLPNUM_TYPENAME_ILLprice_build_pdevex_norms (lp, &(pinf->pdinfo), 0);
+			CHECKRVALG(rval,CLEANUP);
+			break;
+		case QS_PRICE_PSTEEP:
+			if (pinf->psinfo.norms)
+				return rval;
+			rval = EGLPNUM_TYPENAME_ILLprice_build_psteep_norms (lp, &(pinf->psinfo));
+			CHECKRVALG(rval,CLEANUP);
+			break;
+		case QS_PRICE_PMULTPARTIAL:
+			rval = EGLPNUM_TYPENAME_ILLprice_build_mpartial_info (lp, pinf, COL_PRICING);
+			CHECKRVALG(rval,CLEANUP);
+			break;
+		}
+	}
+	else if (d_price != -1)
+	{
+		pinf->cur_price = d_price;
+
+		if (d_price == QS_PRICE_DDANTZIG || d_price == QS_PRICE_DSTEEP ||
+				d_price == QS_PRICE_DDEVEX)
+		{
+			pinf->d_strategy = COMPLETE_PRICING;
+			EGLPNUM_TYPENAME_EGlpNumFreeArray (pinf->p_scaleinf);
+			pinf->p_scaleinf = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+		}
+		else if (d_price == QS_PRICE_DMULTPARTIAL)
+			pinf->d_strategy = MULTI_PART_PRICING;
+
+		switch (d_price)
+		{
+		case QS_PRICE_DSTEEP:
+			if (pinf->dsinfo.norms)
+				return rval;
+			rval = EGLPNUM_TYPENAME_ILLprice_build_dsteep_norms (lp, &(pinf->dsinfo));
+			CHECKRVALG(rval,CLEANUP);
+			break;
+		case QS_PRICE_DMULTPARTIAL:
+			rval = EGLPNUM_TYPENAME_ILLprice_build_mpartial_info (lp, pinf, ROW_PRICING);
+			CHECKRVALG(rval,CLEANUP);
+			break;
+		case QS_PRICE_DDEVEX:
+			if (pinf->ddinfo.norms)
+				return rval;
+			rval = EGLPNUM_TYPENAME_ILLprice_build_ddevex_norms (lp, &(pinf->ddinfo), 0);
+			CHECKRVALG(rval,CLEANUP);
+			break;
+		}
+	}
+
+CLEANUP:
+	if (rval)
+		EGLPNUM_TYPENAME_ILLprice_free_pricing_info (pinf);
+	EG_RETURN(rval);
+}
+
+int EGLPNUM_TYPENAME_ILLprice_update_pricing_info (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_price_info * const pinf,
+	int const phase,
+	EGLPNUM_TYPENAME_svector * const wz,
+	int const eindex,
+	int const lindex,
+	EGLPNUM_TYPE y)
+{
+	int rval = 0;
+	int p_price = -1;
+	int d_price = -1;
+
+	switch (phase)
+	{
+	case PRIMAL_PHASEI:
+		p_price = pinf->pI_price;
+		break;
+	case PRIMAL_PHASEII:
+		p_price = pinf->pII_price;
+		break;
+	case DUAL_PHASEI:
+		d_price = pinf->dI_price;
+		break;
+	case DUAL_PHASEII:
+		d_price = pinf->dII_price;
+		break;
+	}
+
+	if (p_price != -1)
+	{
+		if (p_price == QS_PRICE_PDEVEX)
+		{
+			rval = EGLPNUM_TYPENAME_ILLprice_update_pdevex_norms (lp, &(pinf->pdinfo), eindex, y);
+			CHECKRVALG(rval,CLEANUP);
+		}
+		else if (p_price == QS_PRICE_PSTEEP)
+			EGLPNUM_TYPENAME_ILLprice_update_psteep_norms (lp, &(pinf->psinfo), wz, eindex, y);
+	}
+	else if (d_price != -1)
+	{
+		if (d_price == QS_PRICE_DSTEEP)
+			EGLPNUM_TYPENAME_ILLprice_update_dsteep_norms (lp, &(pinf->dsinfo), wz, lindex, y);
+		else if (d_price == QS_PRICE_DDEVEX)
+		{
+			rval = EGLPNUM_TYPENAME_ILLprice_update_ddevex_norms (lp, &(pinf->ddinfo), lindex, y);
+			CHECKRVALG(rval,CLEANUP);
+		}
+	}
+CLEANUP:
+	EG_RETURN(rval);
+}
+
+int EGLPNUM_TYPENAME_ILLprice_get_price (
+	EGLPNUM_TYPENAME_price_info * const p,
+	int const phase)
+{
+	int pri = -1;
+
+	switch (phase)
+	{
+	case PRIMAL_PHASEI:
+		return p->pI_price;
+	case PRIMAL_PHASEII:
+		return p->pII_price;
+	case DUAL_PHASEI:
+		return p->dI_price;
+	case DUAL_PHASEII:
+		return p->dII_price;
+	}
+	return pri;
+}
+
+void EGLPNUM_TYPENAME_ILLprice_free_mpartial_info (
+	EGLPNUM_TYPENAME_mpart_info * p)
+{
+	ILL_IFFREE (p->gstart, int);
+	ILL_IFFREE (p->gshift, int);
+	ILL_IFFREE (p->gsize, int);
+	ILL_IFFREE (p->bucket, int);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (p->infeas);
+	ILL_IFFREE (p->perm, int);
+}
+
+int EGLPNUM_TYPENAME_ILLprice_build_mpartial_info (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_price_info * const pinf,
+	int const pricetype)
+{
+	int i = 0;
+	int rval = 0;
+	int extra = 0;
+	int nelems;
+	EGLPNUM_TYPENAME_mpart_info *p;
+
+	p = (pricetype == COL_PRICING) ? &(pinf->pmpinfo) : &(pinf->dmpinfo);
+	p->k = 50;
+	p->cgroup = 0;
+	nelems = (pricetype == COL_PRICING) ? lp->nnbasic : lp->nrows;
+
+	if (nelems % p->k)
+		extra = nelems - p->k * (nelems / p->k);
+	p->ngroups = nelems / p->k;
+	if (extra != 0)
+		p->ngroups++;
+
+	ILL_SAFE_MALLOC (p->gstart, p->ngroups, int);
+	ILL_SAFE_MALLOC (p->gshift, p->ngroups, int);
+	ILL_SAFE_MALLOC (p->gsize, p->ngroups, int);
+	ILL_SAFE_MALLOC (p->bucket, 2 * p->k, int);
+	p->infeas = EGLPNUM_TYPENAME_EGlpNumAllocArray (2 * p->k);
+	ILL_SAFE_MALLOC (p->perm, 2 * p->k, int);
+
+	p->bsize = 0;
+
+	if (extra != 0)
+	{
+		p->gstart[0] = 0;
+		p->gshift[0] = 1;
+		p->gsize[0] = extra;
+		for (i = 1; i < p->ngroups; i++)
+		{
+			p->gstart[i] = extra + i - 1;
+			p->gshift[i] = p->ngroups - 1;
+			p->gsize[i] = p->k;
+		}
+	}
+	else
+	{
+		for (i = 0; i < p->ngroups; i++)
+		{
+			p->gstart[i] = i;
+			p->gshift[i] = p->ngroups;
+			p->gsize[i] = p->k;
+		}
+	}
+
+CLEANUP:
+	if (rval)
+		EGLPNUM_TYPENAME_ILLprice_free_mpartial_info (p);
+	EG_RETURN(rval);
+}
+
+void EGLPNUM_TYPENAME_ILLprice_init_mpartial_price (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_price_info * const pinf,
+	int const phase,
+	int const pricetype)
+{
+	int i;
+	EGLPNUM_TYPENAME_mpart_info *p;
+
+	p = (pricetype == COL_PRICING) ? &(pinf->pmpinfo) : &(pinf->dmpinfo);
+	p->bsize = 0;
+	i = p->cgroup;
+	do
+	{
+		EGLPNUM_TYPENAME_ILLprice_mpartial_group (lp, p, phase, i, pricetype);
+		i = (i + 1) % p->ngroups;
+	} while (i != p->cgroup && p->bsize <= p->k);
+	p->cgroup = i;
+}
+
+void EGLPNUM_TYPENAME_ILLprice_update_mpartial_price (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_price_info * const pinf,
+	int const phase,
+	int const pricetype)
+{
+	int i = 0;
+	int csize = 0;
+	EGLPNUM_TYPE infeas;
+	EGLPNUM_TYPENAME_mpart_info *p;
+	EGLPNUM_TYPENAME_price_res pr;
+
+	p = (pricetype == COL_PRICING) ? &(pinf->pmpinfo) : &(pinf->dmpinfo);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (pr.dinfeas);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (pr.pinfeas);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (infeas);
+
+#ifdef MULTIP
+	i = 0;
+	while (i < p->bsize)
+	{
+		if (pricetype == COL_PRICING)
+		{
+			EGLPNUM_TYPENAME_ILLprice_column (lp, p->bucket[i], phase, &pr);
+			EGLPNUM_TYPENAME_EGlpNumCopy (infeas, pr.dinfeas);
+		}
+		else
+		{
+			EGLPNUM_TYPENAME_ILLprice_row (lp, p->bucket[i], phase, &pr);
+			EGLPNUM_TYPENAME_EGlpNumCopy (infeas, pr.pinfeas);
+		}
+		if (!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (infeas))
+		{
+			p->bucket[i] = p->bucket[p->bsize - 1];
+			p->bsize--;
+		}
+		else
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (p->infeas[i], infeas);
+			i++;
+		}
+	}
+	if (p->bsize > 0)
+	{
+		for (i = 0; i < p->bsize; i++)
+			p->perm[i] = i;
+		EGLPNUM_TYPENAME_EGutilPermSort ((size_t) (p->bsize), p->perm,
+										(const EGLPNUM_TYPE * const) p->infeas);
+
+		csize = QSMIN (p->bsize, p->k);
+		for (i = csize - 1; i >= 0; i--)
+			lp->iwork[p->bucket[p->perm[i]]] = 1;
+
+		for (i = 0, csize = 0; i < p->bsize; i++)
+			if (lp->iwork[p->bucket[i]] == 1)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (p->infeas[csize], p->infeas[i]);
+				p->bucket[csize] = p->bucket[i];
+				csize++;
+			}
+		p->bsize = csize;
+	}
+#else
+	p->bsize = 0;
+#endif
+
+	i = p->cgroup;
+	do
+	{
+		EGLPNUM_TYPENAME_ILLprice_mpartial_group (lp, p, phase, i, pricetype);
+		i = (i + 1) % p->ngroups;
+	} while (i != p->cgroup && p->bsize <= p->k);
+	p->cgroup = i;
+
+#ifdef MULTIP
+	for (i = 0; i < csize; i++)
+		lp->iwork[p->bucket[i]] = 0;
+#endif
+	EGLPNUM_TYPENAME_EGlpNumClearVar (infeas);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (pr.pinfeas);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (pr.dinfeas);
+}
+
+void EGLPNUM_TYPENAME_ILLprice_delete_onempart_price (
+	/*EGLPNUM_TYPENAME_lpinfo * const lp,*/
+	EGLPNUM_TYPENAME_price_info * const pinf,
+	int const indx,
+	int const pricetype)
+{
+	int i = 0;
+	EGLPNUM_TYPENAME_mpart_info *p;
+
+	p = (pricetype == COL_PRICING) ? &(pinf->pmpinfo) : &(pinf->dmpinfo);
+
+	for (i = 0; i < p->bsize; i++)
+		if (p->bucket[i] == indx)
+		{
+			p->bucket[i] = p->bucket[p->bsize - 1];
+			EGLPNUM_TYPENAME_EGlpNumCopy (p->infeas[i], p->infeas[p->bsize - 1]);
+			p->bsize--;
+			break;
+		}
+}
+
+void EGLPNUM_TYPENAME_ILLprice_mpartial_group (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_mpart_info * const p,
+	int const phase,
+	int const g,
+	int const pricetype)
+{
+	int i, ix;
+	int gstart = p->gstart[g];
+	int gsize = p->gsize[g];
+	int gshift = p->gshift[g];
+	EGLPNUM_TYPE infeas;
+	EGLPNUM_TYPENAME_price_res pr;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (pr.dinfeas);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (pr.pinfeas);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (infeas);
+
+	for (i = 0, ix = gstart; i < gsize; i++, ix += gshift)
+	{
+#ifdef MULTIP
+		if (lp->iwork[ix])
+			continue;
+#endif
+		if (pricetype == COL_PRICING)
+		{
+			EGLPNUM_TYPENAME_ILLprice_column (lp, ix, phase, &pr);
+			EGLPNUM_TYPENAME_EGlpNumCopy (infeas, pr.dinfeas);
+		}
+		else
+		{
+			EGLPNUM_TYPENAME_ILLprice_row (lp, ix, phase, &pr);
+			EGLPNUM_TYPENAME_EGlpNumCopy (infeas, pr.pinfeas);
+		}
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (infeas))
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (p->infeas[p->bsize], infeas);
+			p->bucket[p->bsize] = ix;
+			p->bsize++;
+		}
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (infeas);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (pr.dinfeas);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (pr.pinfeas);
+}
+
+void EGLPNUM_TYPENAME_ILLprice_column (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	int const ix,
+	int const phase,
+	EGLPNUM_TYPENAME_price_res * const pr)
+{
+	int i;
+	int col;
+	int mcnt;
+	int mbeg;
+	EGLPNUM_TYPE sum;
+
+	EGLPNUM_TYPENAME_EGlpNumZero (pr->dinfeas);
+	col = lp->nbaz[ix];
+	if (lp->vtype[col] == VARTIFICIAL || lp->vtype[col] == VFIXED)
+		return;
+	EGLPNUM_TYPENAME_EGlpNumInitVar (sum);
+	EGLPNUM_TYPENAME_EGlpNumZero (sum);
+	mcnt = lp->matcnt[col];
+	mbeg = lp->matbeg[col];
+
+	if (phase == PRIMAL_PHASEII)
+	{
+		for (i = 0; i < mcnt; i++)
+			EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, lp->piz[lp->matind[mbeg + i]], lp->matval[mbeg + i]);
+		EGLPNUM_TYPENAME_EGlpNumCopyDiff (lp->dz[ix], lp->cz[col], sum);
+		compute_dualII_inf (lp, ix, &(pr->dinfeas));
+	}
+	else
+	{
+		for (i = 0; i < mcnt; i++)
+			EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, lp->pIpiz[lp->matind[mbeg + i]], lp->matval[mbeg + i]);
+		EGLPNUM_TYPENAME_EGlpNumCopyNeg (lp->pIdz[ix], sum);
+		compute_dualI_inf (lp, ix, &(pr->dinfeas));
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (sum);
+}
+
+void EGLPNUM_TYPENAME_ILLprice_row (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	int const ix,
+	int const phase,
+	EGLPNUM_TYPENAME_price_res * const pr)
+{
+	if (phase == DUAL_PHASEII)
+		compute_primalII_inf (lp, ix, &(pr->pinfeas));
+	else
+		compute_primalI_inf (lp, ix, &(pr->pinfeas));
+}
+
+int EGLPNUM_TYPENAME_ILLprice_build_pdevex_norms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_p_devex_info * const pdinfo,
+	int const reinit)
+{
+	int j;
+	int rval = 0;
+
+	if (reinit == 0)
+	{
+		pdinfo->ninit = 0;
+		pdinfo->norms = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nnbasic);
+		ILL_SAFE_MALLOC (pdinfo->refframe, lp->ncols, int);
+	}
+
+	if (reinit != 0)
+		pdinfo->ninit++;
+
+	for (j = 0; j < lp->ncols; j++)
+	{
+		if (lp->vstat[j] == STAT_BASIC)
+			pdinfo->refframe[j] = 0;
+		else
+		{
+			EGLPNUM_TYPENAME_EGlpNumOne (pdinfo->norms[lp->vindex[j]]);
+			pdinfo->refframe[j] = 1;
+		}
+	}
+
+CLEANUP:
+	if (rval)
+	{
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (pdinfo->norms);
+		ILL_IFFREE (pdinfo->refframe, int);
+	}
+	EG_RETURN(rval);
+}
+
+int EGLPNUM_TYPENAME_ILLprice_update_pdevex_norms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_p_devex_info * const pdinfo,
+	int const eindex,
+	EGLPNUM_TYPE yl)
+{
+	int i, j;
+	EGLPNUM_TYPE normj;
+	EGLPNUM_TYPE zAj;
+	EGLPNUM_TYPE ntmp, ntmp2;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (normj);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (zAj);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (ntmp);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (ntmp2);
+	EGLPNUM_TYPENAME_EGlpNumZero (normj);
+
+	for (i = 0; i < lp->yjz.nzcnt; i++)
+		if (pdinfo->refframe[lp->baz[lp->yjz.indx[i]]])
+			EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (normj, lp->yjz.coef[i], lp->yjz.coef[i]);
+
+	if (pdinfo->refframe[lp->nbaz[eindex]])
+		EGLPNUM_TYPENAME_EGlpNumAddTo (normj, EGLPNUM_TYPENAME_oneLpNum);
+
+	EGLPNUM_TYPENAME_EGlpNumSet(ntmp,1000.0);
+	EGLPNUM_TYPENAME_EGlpNumSet(ntmp2,0.001);
+	EGLPNUM_TYPENAME_EGlpNumMultTo(ntmp,pdinfo->norms[eindex]);
+	EGLPNUM_TYPENAME_EGlpNumMultTo(ntmp2,pdinfo->norms[eindex]);
+	if (EGLPNUM_TYPENAME_EGlpNumIsLess (normj, ntmp2) || EGLPNUM_TYPENAME_EGlpNumIsLess (ntmp, normj))
+	{
+		EGLPNUM_TYPENAME_EGlpNumClearVar (zAj);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (normj);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp2);
+		return EGLPNUM_TYPENAME_ILLprice_build_pdevex_norms (lp, pdinfo, 1);
+	}
+
+	for (i = 0; i < lp->zA.nzcnt; i++)
+	{
+		j = lp->zA.indx[i];
+		EGLPNUM_TYPENAME_EGlpNumCopyFrac (zAj, lp->zA.coef[i], yl);
+		EGLPNUM_TYPENAME_EGlpNumMultTo (zAj, zAj);
+		EGLPNUM_TYPENAME_EGlpNumMultTo (zAj, normj);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (pdinfo->norms[j], zAj))
+			EGLPNUM_TYPENAME_EGlpNumCopy (pdinfo->norms[j], zAj);
+	}
+	EGLPNUM_TYPENAME_EGlpNumDivTo (normj, yl);
+	EGLPNUM_TYPENAME_EGlpNumDivTo (normj, yl);
+	if (EGLPNUM_TYPENAME_EGlpNumIsLess (normj, EGLPNUM_TYPENAME_oneLpNum))
+		EGLPNUM_TYPENAME_EGlpNumCopy (pdinfo->norms[eindex], EGLPNUM_TYPENAME_oneLpNum);
+	else
+		EGLPNUM_TYPENAME_EGlpNumCopy (pdinfo->norms[eindex], normj);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (zAj);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (normj);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp2);
+	return 0;
+}
+
+int EGLPNUM_TYPENAME_ILLprice_build_psteep_norms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_p_steep_info * const psinfo)
+{
+	int j;
+	int rval = 0;
+	EGLPNUM_TYPENAME_svector yz;
+
+	EGLPNUM_TYPENAME_ILLsvector_init (&yz);
+	rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&yz, lp->nrows);
+	CHECKRVALG(rval,CLEANUP);
+	psinfo->norms = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nnbasic);
+
+	for (j = 0; j < lp->nnbasic; j++)
+	{
+		rval = ILLstring_report (NULL, &lp->O->reporter);
+		CHECKRVALG(rval,CLEANUP);
+		EGLPNUM_TYPENAME_ILLfct_compute_yz (lp, &yz, 0, lp->nbaz[j]);
+		EGLPNUM_TYPENAME_EGlpNumInnProd (psinfo->norms[j], yz.coef, yz.coef, (size_t) yz.nzcnt);
+		EGLPNUM_TYPENAME_EGlpNumAddTo (psinfo->norms[j], EGLPNUM_TYPENAME_oneLpNum);
+	}
+
+CLEANUP:
+	EGLPNUM_TYPENAME_ILLsvector_free (&yz);
+	if (rval)
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (psinfo->norms);
+
+	EG_RETURN(rval);
+}
+
+void EGLPNUM_TYPENAME_ILLprice_update_psteep_norms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_p_steep_info * const psinfo,
+	EGLPNUM_TYPENAME_svector * const wz,
+	int const eindex,
+	EGLPNUM_TYPE yl)
+{
+	int i, j, k;
+	int mcnt, mbeg;
+	EGLPNUM_TYPE normj,ntmp;
+	EGLPNUM_TYPE zAj, wAj;
+	EGLPNUM_TYPE *v = 0;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (normj);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (zAj);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (ntmp);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (wAj);
+	EGLPNUM_TYPENAME_EGlpNumInnProd (normj, lp->yjz.coef, lp->yjz.coef, (size_t) (lp->yjz.nzcnt));
+	EGLPNUM_TYPENAME_EGlpNumAddTo (normj, EGLPNUM_TYPENAME_oneLpNum);
+
+#if 0
+	Bico - remove warnings for dist
+		if (fabs ((normj - psinfo->norms[eindex]) / normj) > 1000.0 /* 0.01 */ )
+		{
+			QSlog("warning: incorrect norm values");
+			QSlog("anorm = %.6f, pnorm = %.6f", normj, psinfo->norms[eindex]);
+		}
+#endif
+
+	EGLPNUM_TYPENAME_ILLfct_load_workvector (lp, wz);
+	v = lp->work.coef;
+
+	for (k = 0; k < lp->zA.nzcnt; k++)
+	{
+		j = lp->zA.indx[k];
+		EGLPNUM_TYPENAME_EGlpNumCopy (zAj, lp->zA.coef[k]);
+		EGLPNUM_TYPENAME_EGlpNumZero (wAj);
+		mcnt = lp->matcnt[lp->nbaz[j]];
+		mbeg = lp->matbeg[lp->nbaz[j]];
+		for (i = 0; i < mcnt; i++)
+			EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (wAj, lp->matval[mbeg + i], v[lp->matind[mbeg + i]]);
+
+		/* compute ntmp = (zAj * ((zAj * normj / yl) - (2.0 * wAj))) / yl; */ 
+		EGLPNUM_TYPENAME_EGlpNumCopy(ntmp,zAj);
+		EGLPNUM_TYPENAME_EGlpNumMultTo(ntmp,normj);
+		EGLPNUM_TYPENAME_EGlpNumDivTo(ntmp,yl);
+		EGLPNUM_TYPENAME_EGlpNumSubTo(ntmp,wAj);
+		EGLPNUM_TYPENAME_EGlpNumSubTo(ntmp,wAj);
+		EGLPNUM_TYPENAME_EGlpNumMultTo(ntmp,zAj);
+		EGLPNUM_TYPENAME_EGlpNumDivTo(ntmp,yl);
+		/* set psinfo->norms[j] += (zAj * ((zAj * normj / yl) - (2.0 * wAj))) / yl; */
+		EGLPNUM_TYPENAME_EGlpNumAddTo(psinfo->norms[j],ntmp);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (psinfo->norms[j], EGLPNUM_TYPENAME_oneLpNum))
+			EGLPNUM_TYPENAME_EGlpNumOne (psinfo->norms[j]);
+	}
+
+	EGLPNUM_TYPENAME_EGlpNumCopyFrac (psinfo->norms[eindex], normj, yl);
+	EGLPNUM_TYPENAME_EGlpNumDivTo (psinfo->norms[eindex], yl);
+	if (EGLPNUM_TYPENAME_EGlpNumIsLess (psinfo->norms[eindex], EGLPNUM_TYPENAME_oneLpNum))
+		EGLPNUM_TYPENAME_EGlpNumOne (psinfo->norms[eindex]);
+
+	EGLPNUM_TYPENAME_ILLfct_zero_workvector (lp);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (wAj);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (zAj);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (normj);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+}
+
+int EGLPNUM_TYPENAME_ILLprice_build_ddevex_norms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_d_devex_info * const ddinfo,
+	int const reinit)
+{
+	int i;
+	int rval = 0;
+
+	if (reinit == 0)
+	{
+		ddinfo->ninit = 0;
+		ddinfo->norms = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+		ILL_SAFE_MALLOC (ddinfo->refframe, lp->ncols, int);
+	}
+	if (reinit != 0)
+		ddinfo->ninit++;
+
+	for (i = 0; i < lp->ncols; i++)
+		ddinfo->refframe[i] = (lp->vstat[i] == STAT_BASIC) ? 1 : 0;
+
+	for (i = 0; i < lp->nrows; i++)
+		EGLPNUM_TYPENAME_EGlpNumOne (ddinfo->norms[i]);
+
+CLEANUP:
+	if (rval)
+	{
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (ddinfo->norms);
+		ILL_IFFREE (ddinfo->refframe, int);
+	}
+	EG_RETURN(rval);
+}
+
+int EGLPNUM_TYPENAME_ILLprice_update_ddevex_norms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_d_devex_info * const ddinfo,
+	int const lindex,
+	EGLPNUM_TYPE yl)
+{
+	int i, r;
+	EGLPNUM_TYPE normi;
+	EGLPNUM_TYPE yr;
+	EGLPNUM_TYPE ntmp,ntmp2;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (ntmp);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (ntmp2);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (normi);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (yr);
+	EGLPNUM_TYPENAME_EGlpNumZero (normi);
+
+	for (i = 0; i < lp->zA.nzcnt; i++)
+		if (ddinfo->refframe[lp->nbaz[lp->zA.indx[i]]])
+			EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (normi, lp->zA.coef[i], lp->zA.coef[i]);
+
+	if (ddinfo->refframe[lp->baz[lindex]])
+		EGLPNUM_TYPENAME_EGlpNumAddTo (normi, EGLPNUM_TYPENAME_oneLpNum);
+
+	EGLPNUM_TYPENAME_EGlpNumSet(ntmp,1000.0);
+	EGLPNUM_TYPENAME_EGlpNumSet(ntmp2,0.001);
+	EGLPNUM_TYPENAME_EGlpNumMultTo(ntmp,ddinfo->norms[lindex]);
+	EGLPNUM_TYPENAME_EGlpNumMultTo(ntmp2,ddinfo->norms[lindex]);
+	if (EGLPNUM_TYPENAME_EGlpNumIsLess(normi, ntmp2) || EGLPNUM_TYPENAME_EGlpNumIsLess(ntmp, normi))
+	{
+		EGLPNUM_TYPENAME_EGlpNumClearVar (normi);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (yr);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp2);
+		return EGLPNUM_TYPENAME_ILLprice_build_ddevex_norms (lp, ddinfo, 1);
+	}
+
+	for (i = 0; i < lp->yjz.nzcnt; i++)
+	{
+		r = lp->yjz.indx[i];
+		EGLPNUM_TYPENAME_EGlpNumCopy(yr, lp->yjz.coef[i]);
+		EGLPNUM_TYPENAME_EGlpNumCopy(ntmp,yr);
+		EGLPNUM_TYPENAME_EGlpNumMultTo(ntmp,yr);
+		EGLPNUM_TYPENAME_EGlpNumMultTo(ntmp,normi);
+		EGLPNUM_TYPENAME_EGlpNumDivTo(ntmp,yl);
+		EGLPNUM_TYPENAME_EGlpNumDivTo(ntmp,yl);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (ddinfo->norms[r], ntmp))
+			EGLPNUM_TYPENAME_EGlpNumCopy (ddinfo->norms[r], ntmp);
+	}
+	EGLPNUM_TYPENAME_EGlpNumCopy (ddinfo->norms[lindex], normi);
+	EGLPNUM_TYPENAME_EGlpNumDivTo(ddinfo->norms[lindex], yl);
+	EGLPNUM_TYPENAME_EGlpNumDivTo(ddinfo->norms[lindex], yl);
+	if (EGLPNUM_TYPENAME_EGlpNumIsLess (ddinfo->norms[lindex], EGLPNUM_TYPENAME_oneLpNum))
+		EGLPNUM_TYPENAME_EGlpNumOne (ddinfo->norms[lindex]);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (normi);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (yr);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp2);
+	return 0;
+}
+
+int EGLPNUM_TYPENAME_ILLprice_build_dsteep_norms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_d_steep_info * const dsinfo)
+{
+	int i;
+	int rval = 0;
+	EGLPNUM_TYPENAME_svector z;
+
+	EGLPNUM_TYPENAME_ILLsvector_init (&z);
+	rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&z, lp->nrows);
+	CHECKRVALG(rval,CLEANUP);
+	dsinfo->norms = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+
+	for (i = 0; i < lp->nrows; i++)
+	{
+		rval = ILLstring_report (NULL, &lp->O->reporter);
+		CHECKRVALG(rval,CLEANUP);
+
+		EGLPNUM_TYPENAME_ILLfct_compute_zz (lp, &z, i);
+
+		EGLPNUM_TYPENAME_EGlpNumInnProd (dsinfo->norms[i], z.coef, z.coef, (size_t) z.nzcnt);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (dsinfo->norms[i], EGLPNUM_TYPENAME_PARAM_MIN_DNORM))
+			EGLPNUM_TYPENAME_EGlpNumCopy (dsinfo->norms[i], EGLPNUM_TYPENAME_PARAM_MIN_DNORM);
+	}
+
+CLEANUP:
+	EGLPNUM_TYPENAME_ILLsvector_free (&z);
+	if (rval)
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (dsinfo->norms);
+
+	EG_RETURN(rval);
+}
+
+int EGLPNUM_TYPENAME_ILLprice_get_dsteep_norms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	int const count,
+	int *const rowind,
+	EGLPNUM_TYPE * const norms)
+{
+	int i;
+	int rval = 0;
+	EGLPNUM_TYPENAME_svector z;
+
+	EGLPNUM_TYPENAME_ILLsvector_init (&z);
+	rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&z, lp->nrows);
+	CHECKRVALG(rval,CLEANUP);
+
+	for (i = 0; i < count; i++)
+	{
+		EGLPNUM_TYPENAME_ILLfct_compute_zz (lp, &z, rowind[i]);
+		EGLPNUM_TYPENAME_EGlpNumInnProd (norms[i], z.coef, z.coef, (size_t) z.nzcnt);
+	}
+
+CLEANUP:
+	EGLPNUM_TYPENAME_ILLsvector_free (&z);
+	EG_RETURN(rval);
+}
+
+void EGLPNUM_TYPENAME_ILLprice_update_dsteep_norms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_d_steep_info * const dsinfo,
+	EGLPNUM_TYPENAME_svector * const wz,
+	int const lindex,
+	EGLPNUM_TYPE yl)
+{
+	int i, k;
+	EGLPNUM_TYPE yij;
+	EGLPNUM_TYPE norml;
+	EGLPNUM_TYPE *v = 0;
+	EGLPNUM_TYPE ntmp;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (ntmp);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (norml);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (yij);
+	EGLPNUM_TYPENAME_EGlpNumInnProd (norml, lp->zz.coef, lp->zz.coef, (size_t) (lp->zz.nzcnt));
+
+#if 0
+	Bico - remove warnings for dist
+		if (fabs ((norml - dsinfo->norms[lindex]) / norml) > 1000.0 /*0.01 */ )
+		{
+			QSlog("warning: incorrect dnorm values");
+			QSlog("anorm = %.6f, pnorm = %.6f", norml, dsinfo->norms[lindex]);
+		}
+#endif
+
+	EGLPNUM_TYPENAME_ILLfct_load_workvector (lp, wz);
+	v = lp->work.coef;
+
+	for (k = 0; k < lp->yjz.nzcnt; k++)
+	{
+		i = lp->yjz.indx[k];
+		EGLPNUM_TYPENAME_EGlpNumCopy (yij, lp->yjz.coef[k]);
+		/* compute in ntmp (yij * ((yij * norml / yl) - (2.0 * v[i]))) / yl; */
+		EGLPNUM_TYPENAME_EGlpNumCopy(ntmp,yij);
+		EGLPNUM_TYPENAME_EGlpNumMultTo(ntmp,norml);
+		EGLPNUM_TYPENAME_EGlpNumDivTo(ntmp,yl);
+		EGLPNUM_TYPENAME_EGlpNumSubTo(ntmp,v[i]);
+		EGLPNUM_TYPENAME_EGlpNumSubTo(ntmp,v[i]);
+		EGLPNUM_TYPENAME_EGlpNumMultTo (ntmp, yij);
+		EGLPNUM_TYPENAME_EGlpNumDivTo (ntmp, yl);
+		/* set dsinfo->norms[i] += (yij * ((yij * norml / yl) - (2.0 * v[i]))) / yl;*/
+		EGLPNUM_TYPENAME_EGlpNumAddTo(dsinfo->norms[i], ntmp);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (dsinfo->norms[i], EGLPNUM_TYPENAME_PARAM_MIN_DNORM))
+			EGLPNUM_TYPENAME_EGlpNumCopy (dsinfo->norms[i], EGLPNUM_TYPENAME_PARAM_MIN_DNORM);
+	}
+	EGLPNUM_TYPENAME_EGlpNumCopyFrac (dsinfo->norms[lindex], norml, yl);
+	EGLPNUM_TYPENAME_EGlpNumDivTo (dsinfo->norms[lindex], yl);
+	if (EGLPNUM_TYPENAME_EGlpNumIsLess (dsinfo->norms[lindex], EGLPNUM_TYPENAME_PARAM_MIN_DNORM))
+		EGLPNUM_TYPENAME_EGlpNumCopy (dsinfo->norms[lindex], EGLPNUM_TYPENAME_PARAM_MIN_DNORM);
+
+	EGLPNUM_TYPENAME_ILLfct_zero_workvector (lp);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (norml);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (yij);
+}
+
+static void update_d_scaleinf (
+	EGLPNUM_TYPENAME_price_info * const p,
+	EGLPNUM_TYPENAME_heap * const h,
+	int const j,
+	EGLPNUM_TYPE inf,
+	int const prule)
+{
+	if (!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (inf))
+	{
+		EGLPNUM_TYPENAME_EGlpNumZero (p->d_scaleinf[j]);
+		if (h->hexist != 0 && h->loc[j] != -1)
+			EGLPNUM_TYPENAME_ILLheap_delete (h, j);
+	}
+	else
+	{
+		if (prule == QS_PRICE_PDANTZIG)
+			EGLPNUM_TYPENAME_EGlpNumCopy (p->d_scaleinf[j], inf);
+		else if (prule == QS_PRICE_PDEVEX)
+			EGLPNUM_TYPENAME_EGlpNumCopySqrOver (p->d_scaleinf[j], inf, p->pdinfo.norms[j]);
+		else if (prule == QS_PRICE_PSTEEP)
+			EGLPNUM_TYPENAME_EGlpNumCopySqrOver (p->d_scaleinf[j], inf, p->psinfo.norms[j]);
+
+		if (h->hexist != 0)
+		{
+			if (h->loc[j] == -1)
+				EGLPNUM_TYPENAME_ILLheap_insert (h, j);
+			else
+				EGLPNUM_TYPENAME_ILLheap_modify (h, j);
+		}
+	}
+}
+
+static void compute_dualI_inf (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	const int j,
+	EGLPNUM_TYPE * const inf)
+{
+	int col = lp->nbaz[j];
+	int vt = lp->vtype[col];
+	int vs = lp->vstat[col];
+	EGLPNUM_TYPE*dj = &(lp->pIdz[j]);
+	EGLPNUM_TYPE*ftol = &(lp->tol->id_tol);
+	EGLPNUM_TYPENAME_EGlpNumZero (*inf);
+	if (vt != VARTIFICIAL && vt != VFIXED)
+	{
+		if( EGLPNUM_TYPENAME_EGlpNumIsSumLess(*dj,*ftol,EGLPNUM_TYPENAME_zeroLpNum) && (vs == STAT_LOWER || vs == STAT_ZERO))
+			EGLPNUM_TYPENAME_EGlpNumCopyNeg(*inf,*dj);
+		else if (EGLPNUM_TYPENAME_EGlpNumIsLess(*ftol, *dj) && (vs == STAT_UPPER || vs == STAT_ZERO))
+			EGLPNUM_TYPENAME_EGlpNumCopy (*inf, *dj);
+	}
+}
+
+static void compute_dualII_inf (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	int const j,
+	EGLPNUM_TYPE * const inf)
+{
+	int col = lp->nbaz[j];
+	int vt = lp->vtype[col];
+	int vs = lp->vstat[col];
+	EGLPNUM_TYPE*dj = &(lp->dz[j]);
+	EGLPNUM_TYPE*ftol = &(lp->tol->dfeas_tol);
+	EGLPNUM_TYPENAME_EGlpNumZero (*inf);
+	if (vt != VARTIFICIAL && vt != VFIXED)
+	{
+		if( EGLPNUM_TYPENAME_EGlpNumIsSumLess(*dj,*ftol,EGLPNUM_TYPENAME_zeroLpNum) && (vs == STAT_LOWER || vs == STAT_ZERO))
+			EGLPNUM_TYPENAME_EGlpNumCopyNeg(*inf,*dj);
+		else if (EGLPNUM_TYPENAME_EGlpNumIsLess(*ftol,*dj) && (vs == STAT_UPPER || vs == STAT_ZERO))
+			EGLPNUM_TYPENAME_EGlpNumCopy (*inf, *dj);
+	}
+}
+
+void EGLPNUM_TYPENAME_ILLprice_compute_dual_inf (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_price_info * const p,
+	int *const ix,
+	int const icnt,
+	int const phase)
+{
+	int i;
+	int price;
+	EGLPNUM_TYPE inf;
+	EGLPNUM_TYPENAME_heap *h = &(p->h);
+
+	price = (phase == PRIMAL_PHASEI) ? p->pI_price : p->pII_price;
+	EGLPNUM_TYPENAME_EGlpNumInitVar (inf);
+	EGLPNUM_TYPENAME_EGlpNumZero (inf);
+
+	if (phase == PRIMAL_PHASEI)
+	{
+		if (ix == NULL)
+			for (i = 0; i < lp->nnbasic; i++)
+			{
+				compute_dualI_inf (lp, i, &(inf));
+				update_d_scaleinf (p, h, i, inf, price);
+			}
+		else
+			for (i = 0; i < icnt; i++)
+			{
+				compute_dualI_inf (lp, ix[i], &(inf));
+				update_d_scaleinf (p, h, ix[i], inf, price);
+			}
+	}
+	else if (phase == PRIMAL_PHASEII)
+	{
+		if (ix == NULL)
+			for (i = 0; i < lp->nnbasic; i++)
+			{
+				compute_dualII_inf (lp, i, &inf);
+				update_d_scaleinf (p, h, i, inf, price);
+			}
+		else
+			for (i = 0; i < icnt; i++)
+			{
+				compute_dualII_inf (lp, ix[i], &inf);
+				update_d_scaleinf (p, h, ix[i], inf, price);
+			}
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (inf);
+}
+
+void EGLPNUM_TYPENAME_ILLprice_primal (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_price_info * const pinf,
+	EGLPNUM_TYPENAME_price_res * const pr,
+	int const phase)
+{
+	int j, vs;
+	EGLPNUM_TYPE d_e, d_max;
+	EGLPNUM_TYPE *ftol = &(lp->tol->dfeas_tol);
+	EGLPNUM_TYPENAME_heap *const h = &(pinf->h);
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (d_e);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (d_max);
+	pr->eindex = -1;
+	EGLPNUM_TYPENAME_EGlpNumZero(d_max);
+
+#if USEHEAP > 0
+	EGLPNUM_TYPENAME_ILLprice_test_for_heap (lp, pinf, lp->nnbasic, pinf->d_scaleinf,
+													PRIMAL_SIMPLEX, 1);
+#endif
+
+	if (pinf->p_strategy == COMPLETE_PRICING)
+	{
+		if (h->hexist)
+		{
+			pr->eindex = EGLPNUM_TYPENAME_ILLheap_findmin (h);
+			if (pr->eindex != -1)
+				EGLPNUM_TYPENAME_ILLheap_delete (h, pr->eindex);
+		}
+		else
+		{
+			for (j = 0; j < lp->nnbasic; j++)
+			{
+				if (EGLPNUM_TYPENAME_EGlpNumIsLess (d_max, pinf->d_scaleinf[j]))
+				{
+					EGLPNUM_TYPENAME_EGlpNumCopy (d_max, pinf->d_scaleinf[j]);
+					pr->eindex = j;
+				}
+			}
+		}
+	}
+	else if (pinf->p_strategy == MULTI_PART_PRICING)
+	{
+		for (j = 0; j < pinf->pmpinfo.bsize; j++)
+		{
+			if (EGLPNUM_TYPENAME_EGlpNumIsLess (d_max, pinf->pmpinfo.infeas[j]))
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (d_max, pinf->pmpinfo.infeas[j]);
+				pr->eindex = pinf->pmpinfo.bucket[j];
+			}
+		}
+	}
+
+	if (pr->eindex < 0)
+		pr->price_stat = PRICE_OPTIMAL;
+	else
+	{
+		if (phase == PRIMAL_PHASEI)
+			EGLPNUM_TYPENAME_EGlpNumCopy (d_e, lp->pIdz[pr->eindex]);
+		else
+			EGLPNUM_TYPENAME_EGlpNumCopy (d_e, lp->dz[pr->eindex]);
+		vs = lp->vstat[lp->nbaz[pr->eindex]];
+
+		pr->price_stat = PRICE_NONOPTIMAL;
+		if (vs == STAT_UPPER || (vs == STAT_ZERO && EGLPNUM_TYPENAME_EGlpNumIsLess (*ftol, d_e)))
+			pr->dir = VDECREASE;
+		else
+			pr->dir = VINCREASE;
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (d_e);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (d_max);
+}
+
+static void update_p_scaleinf (
+	EGLPNUM_TYPENAME_price_info * const p,
+	EGLPNUM_TYPENAME_heap * const h,
+	int const i,
+	EGLPNUM_TYPE inf,
+	int const prule)
+{
+	if (!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (inf))
+	{
+		EGLPNUM_TYPENAME_EGlpNumZero (p->p_scaleinf[i]);
+		if (h->hexist != 0 && h->loc[i] != -1)
+			EGLPNUM_TYPENAME_ILLheap_delete (h, i);
+	}
+	else
+	{
+		if (prule == QS_PRICE_DDANTZIG)
+			EGLPNUM_TYPENAME_EGlpNumCopy (p->p_scaleinf[i], inf);
+		else if (prule == QS_PRICE_DSTEEP)
+			EGLPNUM_TYPENAME_EGlpNumCopySqrOver (p->p_scaleinf[i], inf, p->dsinfo.norms[i]);
+		else if (prule == QS_PRICE_DDEVEX)
+			EGLPNUM_TYPENAME_EGlpNumCopySqrOver (p->p_scaleinf[i], inf, p->ddinfo.norms[i]);
+
+		if (h->hexist != 0)
+		{
+			if (h->loc[i] == -1)
+				EGLPNUM_TYPENAME_ILLheap_insert (h, i);
+			else
+				EGLPNUM_TYPENAME_ILLheap_modify (h, i);
+		}
+	}
+}
+
+static void compute_primalI_inf (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	int const i,
+	EGLPNUM_TYPE * const inf)
+{
+	int const col = lp->baz[i];
+	EGLPNUM_TYPE*x = &(lp->xbz[i]);
+	EGLPNUM_TYPE*l = &(lp->lz[col]);
+	EGLPNUM_TYPE*u = &(lp->uz[col]);
+	EGLPNUM_TYPE*ftol = &(lp->tol->ip_tol);
+	EGLPNUM_TYPENAME_EGlpNumZero (*inf);
+
+	if (EGLPNUM_TYPENAME_EGlpNumIsLess (*ftol, *x) && EGLPNUM_TYPENAME_EGlpNumIsNeqq (*u, EGLPNUM_TYPENAME_INFTY))
+		EGLPNUM_TYPENAME_EGlpNumCopy (*inf, *x);
+	else if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*l, EGLPNUM_TYPENAME_NINFTY) && EGLPNUM_TYPENAME_EGlpNumIsSumLess (*x, *ftol,EGLPNUM_TYPENAME_zeroLpNum))
+		EGLPNUM_TYPENAME_EGlpNumCopy (*inf, *x);
+}
+
+static void compute_primalII_inf (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	int const i,
+	EGLPNUM_TYPE * const inf)
+{
+	int const col = lp->baz[i];
+	EGLPNUM_TYPE*x = &(lp->xbz[i]);
+	EGLPNUM_TYPE*l = &(lp->lz[col]);
+	EGLPNUM_TYPE*u = &(lp->uz[col]);
+	EGLPNUM_TYPE*ftol = &(lp->tol->pfeas_tol);
+	EGLPNUM_TYPENAME_EGlpNumZero (*inf);
+
+	if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*u, EGLPNUM_TYPENAME_INFTY) && EGLPNUM_TYPENAME_EGlpNumIsSumLess (*u, *ftol, *x))
+		EGLPNUM_TYPENAME_EGlpNumCopyDiff (*inf, *x, *u);
+	else if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*l, EGLPNUM_TYPENAME_NINFTY) && EGLPNUM_TYPENAME_EGlpNumIsSumLess (*x, *ftol, *l))
+		EGLPNUM_TYPENAME_EGlpNumCopyDiff (*inf, *l, *x);
+}
+
+void EGLPNUM_TYPENAME_ILLprice_compute_primal_inf (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_price_info * const p,
+	int *const ix,
+	int const icnt,
+	int const phase)
+{
+	int i;
+	int price;
+	EGLPNUM_TYPE inf;
+	EGLPNUM_TYPENAME_heap *h = &(p->h);
+
+	price = (phase == DUAL_PHASEI) ? p->dI_price : p->dII_price;
+	EGLPNUM_TYPENAME_EGlpNumInitVar (inf);
+	EGLPNUM_TYPENAME_EGlpNumZero (inf);
+
+	if (phase == DUAL_PHASEI)
+	{
+		if (ix == NULL)
+			for (i = 0; i < lp->nrows; i++)
+			{
+				compute_primalI_inf (lp, i, &inf);
+				update_p_scaleinf (p, h, i, inf, price);
+			}
+		else
+			for (i = 0; i < icnt; i++)
+			{
+				compute_primalI_inf (lp, ix[i], &inf);
+				update_p_scaleinf (p, h, ix[i], inf, price);
+			}
+	}
+	else if (phase == DUAL_PHASEII)
+	{
+		if (ix == NULL)
+			for (i = 0; i < lp->nrows; i++)
+			{
+				compute_primalII_inf (lp, i, &inf);
+				update_p_scaleinf (p, h, i, inf, price);
+			}
+		else
+			for (i = 0; i < icnt; i++)
+			{
+				compute_primalII_inf (lp, ix[i], &inf);
+				update_p_scaleinf (p, h, ix[i], inf, price);
+			}
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (inf);
+}
+
+void EGLPNUM_TYPENAME_ILLprice_dual (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_price_info * const pinf,
+	int const phase,
+	EGLPNUM_TYPENAME_price_res * const pr)
+{
+	int i;
+	EGLPNUM_TYPE p_max;
+	EGLPNUM_TYPE ubound;
+	EGLPNUM_TYPE*ftol = &(lp->tol->pfeas_tol);
+	EGLPNUM_TYPENAME_heap *const h = &(pinf->h);
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (p_max);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (ubound);
+	pr->lindex = -1;
+	EGLPNUM_TYPENAME_EGlpNumZero(p_max);
+
+#if USEHEAP > 0
+	EGLPNUM_TYPENAME_ILLprice_test_for_heap (lp, pinf, lp->nrows, pinf->p_scaleinf, DUAL_SIMPLEX,
+													1);
+#endif
+
+	if (pinf->d_strategy == COMPLETE_PRICING)
+	{
+		if (h->hexist)
+		{
+			pr->lindex = EGLPNUM_TYPENAME_ILLheap_findmin (h);
+			if (pr->lindex != -1)
+				EGLPNUM_TYPENAME_ILLheap_delete (h, pr->lindex);
+		}
+		else
+		{
+			for (i = 0; i < lp->nrows; i++)
+			{
+				if (EGLPNUM_TYPENAME_EGlpNumIsLess (p_max, pinf->p_scaleinf[i]))
+				{
+					EGLPNUM_TYPENAME_EGlpNumCopy (p_max, pinf->p_scaleinf[i]);
+					pr->lindex = i;
+				}
+			}
+		}
+	}
+	else if (pinf->d_strategy == MULTI_PART_PRICING)
+	{
+		for (i = 0; i < pinf->dmpinfo.bsize; i++)
+		{
+			if (EGLPNUM_TYPENAME_EGlpNumIsLess (p_max, pinf->dmpinfo.infeas[i]))
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (p_max, pinf->dmpinfo.infeas[i]);
+				pr->lindex = pinf->dmpinfo.bucket[i];
+			}
+		}
+	}
+
+	if (pr->lindex < 0)
+		pr->price_stat = PRICE_OPTIMAL;
+	else
+	{
+		pr->price_stat = NONOPTIMAL;
+
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (lp->uz[lp->baz[pr->lindex]], EGLPNUM_TYPENAME_INFTY))
+		{
+			if (phase == DUAL_PHASEI)
+				EGLPNUM_TYPENAME_EGlpNumZero(ubound);
+			else
+				EGLPNUM_TYPENAME_EGlpNumCopy(ubound,lp->uz[lp->baz[pr->lindex]]);
+			if (EGLPNUM_TYPENAME_EGlpNumIsSumLess (*ftol, ubound, lp->xbz[pr->lindex]))
+				pr->lvstat = STAT_UPPER;
+			else
+				pr->lvstat = STAT_LOWER;
+		}
+		else
+			pr->lvstat = STAT_LOWER;
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (p_max);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (ubound);
+}
+
+int EGLPNUM_TYPENAME_ILLprice_get_rownorms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_price_info * const pinf,
+	EGLPNUM_TYPE * const rnorms)
+{
+	int rval = 0;
+	int i;
+
+	if (pinf->dsinfo.norms == NULL)
+	{
+		rval = EGLPNUM_TYPENAME_ILLprice_build_dsteep_norms (lp, &(pinf->dsinfo));
+		CHECKRVALG(rval,CLEANUP);
+	}
+	for (i = 0; i < lp->nrows; i++)
+		EGLPNUM_TYPENAME_EGlpNumCopy (rnorms[i], pinf->dsinfo.norms[i]);
+
+CLEANUP:
+	if (rval)
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (pinf->dsinfo.norms);
+
+	return rval;
+}
+
+int EGLPNUM_TYPENAME_ILLprice_get_colnorms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_price_info * const pinf,
+	EGLPNUM_TYPE * const cnorms)
+{
+	int rval = 0;
+	int i, j;
+
+	if (pinf->psinfo.norms == NULL)
+	{
+		rval = EGLPNUM_TYPENAME_ILLprice_build_psteep_norms (lp, &(pinf->psinfo));
+		CHECKRVALG(rval,CLEANUP);
+	}
+	for (i = 0; i < lp->nrows; i++)
+		EGLPNUM_TYPENAME_EGlpNumZero (cnorms[lp->baz[i]]);
+	for (j = 0; j < lp->nnbasic; j++)
+		EGLPNUM_TYPENAME_EGlpNumCopy (cnorms[lp->nbaz[j]], pinf->psinfo.norms[j]);
+
+CLEANUP:
+	if (rval)
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (pinf->psinfo.norms);
+
+	return rval;
+}
+
+int EGLPNUM_TYPENAME_ILLprice_get_newnorms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	int const nelems,
+	EGLPNUM_TYPE * const norms,
+	int *const matcnt,
+	int *const matbeg,
+	int *const matind,
+	EGLPNUM_TYPE * const matval,
+	int const option)
+{
+	int i, j;
+	int rval = 0;
+	EGLPNUM_TYPENAME_svector a;
+	EGLPNUM_TYPENAME_svector y;
+
+	EGLPNUM_TYPENAME_ILLsvector_init (&y);
+	rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&y, lp->nrows);
+	CHECKRVALG(rval,CLEANUP);
+
+	for (j = 0; j < nelems; j++)
+	{
+		a.nzcnt = matcnt[j];
+		a.indx = &(matind[matbeg[j]]);
+		a.coef = &(matval[matbeg[j]]);
+
+		if (option == COLUMN_SOLVE)
+			EGLPNUM_TYPENAME_ILLbasis_column_solve (lp, &a, &y);
+		else
+			EGLPNUM_TYPENAME_ILLbasis_row_solve (lp, &a, &y);
+
+		EGLPNUM_TYPENAME_EGlpNumOne (norms[j]);
+		for (i = 0; i < y.nzcnt; i++)
+			EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (norms[j], y.coef[i], y.coef[i]);
+	}
+
+CLEANUP:
+	EGLPNUM_TYPENAME_ILLsvector_free (&y);
+	EG_RETURN(rval);
+}
+
+int EGLPNUM_TYPENAME_ILLprice_get_new_rownorms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	int const newrows,
+	EGLPNUM_TYPE * const rnorms,
+	int *const rmatcnt,
+	int *const rmatbeg,
+	int *const rmatind,
+	EGLPNUM_TYPE * const rmatval)
+{
+	return EGLPNUM_TYPENAME_ILLprice_get_newnorms (lp, newrows, rnorms, rmatcnt, rmatbeg, rmatind,
+																rmatval, ROW_SOLVE);
+}
+
+int EGLPNUM_TYPENAME_ILLprice_get_new_colnorms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	int const newrows,
+	EGLPNUM_TYPE * const rnorms,
+	int *const matcnt,
+	int *const matbeg,
+	int *const matind,
+	EGLPNUM_TYPE * const matval)
+{
+	return EGLPNUM_TYPENAME_ILLprice_get_newnorms (lp, newrows, rnorms, matcnt, matbeg, matind,
+																matval, COLUMN_SOLVE);
+}
+
+int EGLPNUM_TYPENAME_ILLprice_load_rownorms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPE * const rnorms,
+	EGLPNUM_TYPENAME_price_info * const pinf)
+{
+	int i;
+	int rval = 0;
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (pinf->dsinfo.norms);
+	pinf->dsinfo.norms = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+
+	for (i = 0; i < lp->nrows; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (pinf->dsinfo.norms[i], rnorms[i]);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (pinf->dsinfo.norms[i], EGLPNUM_TYPENAME_PARAM_MIN_DNORM))
+			EGLPNUM_TYPENAME_EGlpNumCopy (pinf->dsinfo.norms[i], EGLPNUM_TYPENAME_PARAM_MIN_DNORM);
+	}
+
+	EG_RETURN(rval);
+}
+
+int EGLPNUM_TYPENAME_ILLprice_load_colnorms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPE * const cnorms,
+	EGLPNUM_TYPENAME_price_info * const pinf)
+{
+	int j;
+	int rval = 0;
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (pinf->psinfo.norms);
+	pinf->psinfo.norms = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nnbasic);
+
+	for (j = 0; j < lp->nnbasic; j++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (pinf->psinfo.norms[j], cnorms[lp->nbaz[j]]);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (pinf->psinfo.norms[j], EGLPNUM_TYPENAME_oneLpNum))
+			EGLPNUM_TYPENAME_EGlpNumOne (pinf->psinfo.norms[j]);
+	}
+
+	EG_RETURN(rval);
+}
+
+#if PRICE_DEBUG > 0
+void EGLPNUM_TYPENAME_test_dsteep_norms (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * p)
+{
+	int i, errn = 0;
+	EGLPNUM_TYPE *pn = EGLPNUM_TYPENAME_EGlpNumAllocArray(lp->nrows);
+	EGLPNUM_TYPE err, diff;
+	EGLPNUM_TYPENAME_EGlpNumZero (err);
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (err);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (diff);
+
+	EGLPNUM_TYPENAME_ILLprice_get_dsteep_norms (lp, lp->yjz.nzcnt, lp->yjz.indx, pn);
+	for (i = 0; i < lp->yjz.nzcnt; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopyDiff (diff, pn[i], p->dsinfo.norms[lp->yjz.indx[i]]);
+		EGLPNUM_TYPENAME_EGlpNumCopyAbs(diff,diff);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_PFEAS_TOLER, diff))
+		{
+			errn++;
+			EGLPNUM_TYPENAME_EGlpNumAddTo (err, diff);
+			EGLPNUM_TYPENAME_EGlpNumCopy (p->dsinfo.norms[lp->yjz.indx[i]], pn[i]);
+		}
+	}
+	if (errn)
+		QSlog("%d: dnorm errn = %d, err = %.6f", lp->cnts->tot_iter, errn,
+								EGLPNUM_TYPENAME_EGlpNumToLf (err));
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (pn);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (diff);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (err);
+}
+#endif
diff --git a/qsopt_ex/price.h b/qsopt_ex/price.h
new file mode 100644
index 0000000..d477a19
--- /dev/null
+++ b/qsopt_ex/price.h
@@ -0,0 +1,222 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/*  $RCSfile: price_EGLPNUM_TYPENAME.h,v $ $Revision: 1.3 $ $Date: 2003/11/05 16:57:39 $" */
+#ifndef EGLPNUM_TYPENAME___PRICE_H
+#define EGLPNUM_TYPENAME___PRICE_H
+
+#include "dstruct_EGLPNUM_TYPENAME.h"
+#include "basicdefs.h"
+
+typedef struct EGLPNUM_TYPENAME_price_res
+{
+	int eindex;
+	int dir;
+	int lindex;
+	int lvstat;
+	int price_stat;
+	EGLPNUM_TYPE dinfeas;
+	EGLPNUM_TYPE pinfeas;
+}
+EGLPNUM_TYPENAME_price_res;
+
+int EGLPNUM_TYPENAME_ILLprice_test_for_heap (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_price_info * const pinf,
+	int const nkeys,
+	EGLPNUM_TYPE * keylist,
+	int const algo,
+	int const upd),
+  EGLPNUM_TYPENAME_ILLprice_build_heap (
+	EGLPNUM_TYPENAME_price_info * const pinf,
+	int const nkeys,
+	EGLPNUM_TYPE * keylist),
+  EGLPNUM_TYPENAME_ILLprice_build_pricing_info (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_price_info * const pinf,
+	int const phase),
+  EGLPNUM_TYPENAME_ILLprice_update_pricing_info (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_price_info * const pinf,
+	int const phase,
+	EGLPNUM_TYPENAME_svector * const wz,
+	int const eindex,
+	int const lindex,
+	EGLPNUM_TYPE y),
+  EGLPNUM_TYPENAME_ILLprice_get_price (
+	EGLPNUM_TYPENAME_price_info * const p,
+	int const phase),
+  EGLPNUM_TYPENAME_ILLprice_build_mpartial_info (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_price_info * const pinf,
+	int const pricetype),
+  EGLPNUM_TYPENAME_ILLprice_build_pdevex_norms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_p_devex_info * const pdinfo,
+	int const reinit),
+  EGLPNUM_TYPENAME_ILLprice_update_pdevex_norms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_p_devex_info * const pdinfo,
+	int const eindex,
+	EGLPNUM_TYPE yl),
+  EGLPNUM_TYPENAME_ILLprice_build_psteep_norms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_p_steep_info * const psinfo),
+  EGLPNUM_TYPENAME_ILLprice_build_ddevex_norms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_d_devex_info * const ddinfo,
+	int const reinit),
+  EGLPNUM_TYPENAME_ILLprice_update_ddevex_norms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_d_devex_info * const ddinfo,
+	int const eindex,
+	EGLPNUM_TYPE yl),
+  EGLPNUM_TYPENAME_ILLprice_build_dsteep_norms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_d_steep_info * const dsinfo),
+  EGLPNUM_TYPENAME_ILLprice_get_dsteep_norms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	int const count,
+	int *constrowind,
+	EGLPNUM_TYPE * const norms),
+  EGLPNUM_TYPENAME_ILLprice_get_rownorms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_price_info * const pinf,
+	EGLPNUM_TYPE * const rnorms),
+  EGLPNUM_TYPENAME_ILLprice_get_colnorms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_price_info * const pinf,
+	EGLPNUM_TYPE * const cnorms),
+  EGLPNUM_TYPENAME_ILLprice_get_newnorms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	int const nelems,
+	EGLPNUM_TYPE * const norms,
+	int *const matcnt,
+	int *const matbeg,
+	int *const matind,
+	EGLPNUM_TYPE * const matval,
+	int const option),
+  EGLPNUM_TYPENAME_ILLprice_get_new_rownorms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	int const newrows,
+	EGLPNUM_TYPE * const rnorms,
+	int *const rmatcnt,
+	int *const rmatbeg,
+	int *const rmatind,
+	EGLPNUM_TYPE * const rmatval),
+  EGLPNUM_TYPENAME_ILLprice_get_new_colnorms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	int const newrows,
+	EGLPNUM_TYPE * const rnorms,
+	int *const matcnt,
+	int *const matbeg,
+	int *const matind,
+	EGLPNUM_TYPE * const matval),
+  EGLPNUM_TYPENAME_ILLprice_load_rownorms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPE * const rnorms,
+	EGLPNUM_TYPENAME_price_info * const pinf),
+  EGLPNUM_TYPENAME_ILLprice_load_colnorms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPE * const cnorms,
+	EGLPNUM_TYPENAME_price_info * const pinf);
+
+
+void EGLPNUM_TYPENAME_ILLprice_free_heap (
+	EGLPNUM_TYPENAME_price_info * const pinf),
+  EGLPNUM_TYPENAME_ILLprice_init_pricing_info (
+	EGLPNUM_TYPENAME_price_info * const pinf),
+  EGLPNUM_TYPENAME_ILLprice_free_pricing_info (
+	EGLPNUM_TYPENAME_price_info * const pinf),
+  EGLPNUM_TYPENAME_ILLprice_free_mpartial_info (
+	EGLPNUM_TYPENAME_mpart_info * p),
+  EGLPNUM_TYPENAME_ILLprice_init_mpartial_price (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_price_info * const pinf,
+	int const phase,
+	int const pricetype),
+  EGLPNUM_TYPENAME_ILLprice_update_mpartial_price (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_price_info * const pinf,
+	int const phase,
+	int const pricetype),
+  EGLPNUM_TYPENAME_ILLprice_delete_onempart_price (
+	/*EGLPNUM_TYPENAME_lpinfo * const lp,*/
+	EGLPNUM_TYPENAME_price_info * const pinf,
+	int const indx,
+	int const pricetype),
+  EGLPNUM_TYPENAME_ILLprice_mpartial_group (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_mpart_info * const p,
+	int const phase,
+	int const g,
+	int const pricetype),
+  EGLPNUM_TYPENAME_ILLprice_column (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	int const ix,
+	int const phase,
+	EGLPNUM_TYPENAME_price_res * const pr),
+  EGLPNUM_TYPENAME_ILLprice_row (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	int const ix,
+	int const phase,
+	EGLPNUM_TYPENAME_price_res * const pr),
+  EGLPNUM_TYPENAME_ILLprice_update_psteep_norms (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_p_steep_info * psinfo,
+	EGLPNUM_TYPENAME_svector * wz,
+	int eindex,
+	EGLPNUM_TYPE yl),
+  EGLPNUM_TYPENAME_ILLprice_update_dsteep_norms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_d_steep_info * const dsinfo,
+	EGLPNUM_TYPENAME_svector * const wz,
+	int const lindex,
+	EGLPNUM_TYPE yl),
+  EGLPNUM_TYPENAME_ILLprice_compute_dual_inf (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_price_info * const p,
+	int *const ix,
+	int const icnt,
+	int const phase),
+  EGLPNUM_TYPENAME_ILLprice_primal (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_price_info * const pinf,
+	EGLPNUM_TYPENAME_price_res * const pr,
+	int const phase),
+  EGLPNUM_TYPENAME_ILLprice_compute_primal_inf (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_price_info * const p,
+	int *const ix,
+	int const icnt,
+	int const phase),
+  EGLPNUM_TYPENAME_ILLprice_dual (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_price_info * const pinf,
+	int const phase,
+	EGLPNUM_TYPENAME_price_res * const pr);
+
+void EGLPNUM_TYPENAME_test_dsteep_norms (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	EGLPNUM_TYPENAME_price_info * const p);
+
+#endif /* EGLPNUM_TYPENAME___PRICE_H */
diff --git a/qsopt_ex/priority.c b/qsopt_ex/priority.c
new file mode 100644
index 0000000..93b3647
--- /dev/null
+++ b/qsopt_ex/priority.c
@@ -0,0 +1,259 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCSINFO $Id: priority.c,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of CONCORDE                                           */
+/*                                                                          */
+/*  (c) Copyright 1995--1999 by David Applegate, Robert Bixby,              */
+/*  Vasek Chvatal, and William Cook                                         */
+/*                                                                          */
+/*  Permission is granted for academic research use.  For other uses,       */
+/*  contact the authors for licensing options.                              */
+/*                                                                          */
+/*  Use at your own risk.  We make no guarantees about the                  */
+/*  correctness or usefulness of this code.                                 */
+/*                                                                          */
+/****************************************************************************/
+
+/****************************************************************************/
+/*                                                                          */
+/*                      PRIORITY QUEUE ROUTINES                             */
+/*                                                                          */
+/*                                                                          */
+/*                              TSP CODE                                    */
+/*  Written by:  Applegate, Bixby, Chvatal, and Cook                        */
+/*  Date: March 3, 1997                                                     */
+/*        March 13, 2002 - Cook Modified for QS)                            */
+/*  Reference: R.E. Tarjan, Data Structures and Network Algorithms          */
+/*                                                                          */
+/*    EXPORTED FUNCTIONS:                                                   */
+/*                                                                          */
+/*  int EGLPNUM_TYPENAME_ILLutil_priority_init (EGLPNUM_TYPENAME_ILLpriority *pri, int k)                     */
+/*    -h should point to a EGLPNUM_TYPENAME_ILLpriority struct.                              */
+/*    -k an initial allocation for the priority queue.                      */
+/*                                                                          */
+/*  void EGLPNUM_TYPENAME_ILLutil_priority_free (EGLPNUM_TYPENAME_ILLpriority *pri)                           */
+/*    -frees the spaces allocated for the EGLPNUM_TYPENAME_ILLpriority queue.                */
+/*                                                                          */
+/*  void EGLPNUM_TYPENAME_ILLutil_priority_findmin (EGLPNUM_TYPENAME_ILLpriority *pri, double *keyval         */
+/*      void **en)                                                          */
+/*    -en the entry with least key value (NULL if no entries in EGLPNUM_TYPENAME_heap).      */
+/*    -if (keyval != NULL), *keyval will be the minimum key value.          */
+/*                                                                          */
+/*  int EGLPNUM_TYPENAME_ILLutil_priority_insert (EGLPNUM_TYPENAME_ILLpriority *pri, void *data,              */
+/*      double keyval, int *handle)                                         */
+/*    -adds (data, keyval) to h.                                            */
+/*    -handle returns a handle (>= 0) to use when deleting or changing the  */
+/*     entry                                                                */
+/*                                                                          */
+/*  void EGLPNUM_TYPENAME_ILLutil_priority_delete (EGLPNUM_TYPENAME_ILLpriority *pri, int handle)             */
+/*    -deletes an entry from the queue.  handle is the value returned by    */
+/*     EGLPNUM_TYPENAME_ILLutil_priority_insert.                                             */
+/*                                                                          */
+/*  void EGLPNUM_TYPENAME_ILLutil_priority_deletemin (EGLPNUM_TYPENAME_ILLpriority *pri, double *keyval,      */
+/*       void **en)                                                         */
+/*    -like EGLPNUM_TYPENAME_ILLutil_priority_findmin, but also deletes the entry.           */
+/*                                                                          */
+/*  void EGLPNUM_TYPENAME_ILLutil_priority_changekey (EGLPNUM_TYPENAME_ILLpriority *pri, int handle,          */
+/*      double newkey)                                                      */
+/*    -changes the key of an entry in the queue.  handle is the value       */
+/*     returned by EGLPNUM_TYPENAME_ILLutil_priority_insert.                                 */
+/*                                                                          */
+/****************************************************************************/
+
+/****************************************************************************/
+/*                                                                          */
+/*  NOTES:                                                                  */
+/*      These priority queue routines use the EGLPNUM_TYPENAME_ILLdheap routines to maintain */
+/*  the priority queue.                                                     */
+/*                                                                          */
+/****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "eg_lpnum.h"
+
+#include "priority_EGLPNUM_TYPENAME.h"
+#include "allocrus.h"
+#include "except.h"
+
+
+int EGLPNUM_TYPENAME_ILLutil_priority_init (
+	EGLPNUM_TYPENAME_ILLpriority * pri,
+	int k)
+{
+	int i;
+	int list;
+	int rval = 0;
+
+	pri->space = k;
+	ILL_SAFE_MALLOC (pri->pri_info, k, union EGLPNUM_TYPENAME_ILLpri_data);
+
+	rval = EGLPNUM_TYPENAME_ILLutil_dheap_init (&pri->EGLPNUM_TYPENAME_heap, k);
+	ILL_CLEANUP_IF (rval);
+
+	list = -1;
+	for (i = k - 1; i >= 0; i--)
+	{
+		pri->pri_info[i].next = list;
+		list = i;
+	}
+	pri->freelist = list;
+
+CLEANUP:
+
+	if (rval)
+	{
+		ILL_IFFREE (pri->pri_info, union EGLPNUM_TYPENAME_ILLpri_data);
+	}
+	return rval;
+}
+
+void EGLPNUM_TYPENAME_ILLutil_priority_free (
+	EGLPNUM_TYPENAME_ILLpriority * pri)
+{
+	EGLPNUM_TYPENAME_ILLutil_dheap_free (&pri->EGLPNUM_TYPENAME_heap);
+	ILL_IFFREE (pri->pri_info, union EGLPNUM_TYPENAME_ILLpri_data);
+
+	pri->space = 0;
+}
+
+void EGLPNUM_TYPENAME_ILLutil_priority_findmin (
+	EGLPNUM_TYPENAME_ILLpriority * pri,
+	EGLPNUM_TYPE * keyval,
+	void **en)
+{
+	int handle;
+
+	EGLPNUM_TYPENAME_ILLutil_dheap_findmin (&pri->EGLPNUM_TYPENAME_heap, &handle);
+
+	if (handle < 0)
+	{
+		*en = (void *) NULL;
+	}
+	else
+	{
+		if (keyval)
+			EGLPNUM_TYPENAME_EGlpNumCopy (*keyval, pri->EGLPNUM_TYPENAME_heap.key[handle]);
+		*en = pri->pri_info[handle].data;
+	}
+}
+
+int EGLPNUM_TYPENAME_ILLutil_priority_insert (
+	EGLPNUM_TYPENAME_ILLpriority * pri,
+	void *data,
+	EGLPNUM_TYPE * keyval,
+	int *handle)
+{
+	int newsize;
+	int i;
+	int list;
+	int rval = 0;
+
+	if (pri->freelist == -1)
+	{
+		/* Change from 1.3 * pri->space to avoid a warning */
+		newsize = pri->space + (pri->space / 3);
+		if (newsize < pri->space + 1000)
+			newsize = pri->space + 1000;
+		rval = EGLPNUM_TYPENAME_ILLutil_dheap_resize (&pri->EGLPNUM_TYPENAME_heap, newsize);
+		ILL_CLEANUP_IF (rval);
+
+		pri->pri_info =
+			EGrealloc (pri->pri_info, sizeof (union EGLPNUM_TYPENAME_ILLpri_data) * newsize);
+		//rval = ILLutil_reallocrus_count ((void **) &pri->pri_info, newsize,
+		//                                 sizeof (union EGLPNUM_TYPENAME_ILLpri_data));
+		//ILL_CLEANUP_IF (rval);
+
+		list = -1;
+		for (i = newsize - 1; i >= pri->space; i--)
+		{
+			pri->pri_info[i].next = list;
+			list = i;
+		}
+		pri->space = newsize;
+		pri->freelist = list;
+	}
+
+	i = pri->freelist;
+	pri->freelist = pri->pri_info[i].next;
+	pri->pri_info[i].data = data;
+	EGLPNUM_TYPENAME_EGlpNumCopy (pri->EGLPNUM_TYPENAME_heap.key[i], *keyval);
+	rval = EGLPNUM_TYPENAME_ILLutil_dheap_insert (&pri->EGLPNUM_TYPENAME_heap, i);
+	ILL_CLEANUP_IF (rval);
+
+	if (handle)
+		*handle = i;
+
+CLEANUP:
+
+	return rval;
+}
+
+void EGLPNUM_TYPENAME_ILLutil_priority_delete (
+	EGLPNUM_TYPENAME_ILLpriority * pri,
+	int handle)
+{
+	EGLPNUM_TYPENAME_ILLutil_dheap_delete (&pri->EGLPNUM_TYPENAME_heap, handle);
+	pri->pri_info[handle].next = pri->freelist;
+	pri->freelist = handle;
+}
+
+void EGLPNUM_TYPENAME_ILLutil_priority_deletemin (
+	EGLPNUM_TYPENAME_ILLpriority * pri,
+	EGLPNUM_TYPE * keyval,
+	void **en)
+{
+	int handle;
+	void *data;
+
+	EGLPNUM_TYPENAME_ILLutil_dheap_deletemin (&pri->EGLPNUM_TYPENAME_heap, &handle);
+
+	if (handle < 0)
+	{
+		*en = (void *) NULL;
+	}
+	else
+	{
+		if (keyval)
+			EGLPNUM_TYPENAME_EGlpNumCopy (*keyval, pri->EGLPNUM_TYPENAME_heap.key[handle]);
+		data = pri->pri_info[handle].data;
+		pri->pri_info[handle].next = pri->freelist;
+		pri->freelist = handle;
+		*en = data;
+	}
+}
+
+void EGLPNUM_TYPENAME_ILLutil_priority_changekey (
+	EGLPNUM_TYPENAME_ILLpriority * pri,
+	int handle,
+	EGLPNUM_TYPE * newkey)
+{
+	EGLPNUM_TYPENAME_ILLutil_dheap_changekey (&pri->EGLPNUM_TYPENAME_heap, handle, newkey);
+}
diff --git a/qsopt_ex/priority.h b/qsopt_ex/priority.h
new file mode 100644
index 0000000..6bf6d5c
--- /dev/null
+++ b/qsopt_ex/priority.h
@@ -0,0 +1,75 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+#ifndef EGLPNUM_TYPENAME___PRIORITY_H__
+#define EGLPNUM_TYPENAME___PRIORITY_H__
+#include "dheaps_i_EGLPNUM_TYPENAME.h"
+/****************************************************************************/
+/*                                                                          */
+/*                             priority.c                                   */
+/*                                                                          */
+/****************************************************************************/
+
+typedef struct EGLPNUM_TYPENAME_ILLpriority
+{
+	EGLPNUM_TYPENAME_ILLdheap EGLPNUM_TYPENAME_heap;
+	union EGLPNUM_TYPENAME_ILLpri_data
+	{
+		void *data;
+		int next;
+	}
+	 *pri_info;
+	int space;
+	int freelist;
+}
+EGLPNUM_TYPENAME_ILLpriority;
+
+void EGLPNUM_TYPENAME_ILLutil_priority_free (
+	EGLPNUM_TYPENAME_ILLpriority * pri),
+  EGLPNUM_TYPENAME_ILLutil_priority_delete (
+	EGLPNUM_TYPENAME_ILLpriority * pri,
+	int handle),
+  EGLPNUM_TYPENAME_ILLutil_priority_changekey (
+	EGLPNUM_TYPENAME_ILLpriority * pri,
+	int handle,
+	EGLPNUM_TYPE * newkey),
+  EGLPNUM_TYPENAME_ILLutil_priority_findmin (
+	EGLPNUM_TYPENAME_ILLpriority * pri,
+	EGLPNUM_TYPE * keyval,
+	void **en),
+  EGLPNUM_TYPENAME_ILLutil_priority_deletemin (
+	EGLPNUM_TYPENAME_ILLpriority * pri,
+	EGLPNUM_TYPE * keyval,
+	void **en);
+
+int EGLPNUM_TYPENAME_ILLutil_priority_init (
+	EGLPNUM_TYPENAME_ILLpriority * pri,
+	int k),
+  EGLPNUM_TYPENAME_ILLutil_priority_insert (
+	EGLPNUM_TYPENAME_ILLpriority * pri,
+	void *data,
+	EGLPNUM_TYPE * keyval,
+	int *handle);
+
+
+
+#endif
diff --git a/qsopt_ex/qs_config.h b/qsopt_ex/qs_config.h
new file mode 100644
index 0000000..52afce5
--- /dev/null
+++ b/qsopt_ex/qs_config.h
@@ -0,0 +1,70 @@
+/* Taken from EGlib 10-09-26 */
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library 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 Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * */
+/* ========================================================================= */
+/** Main Configuration for the library, as debug levels and so on
+ *
+ * @par History:
+ * - 2010-09-26
+ * 						- Addapted for QSopt_ex
+ * - 2010-08-13
+ * 						- Add suport for autoconf and configure for header and feature
+ * 						selection
+ * - 2006-01-27
+ *					- Handle some problems with stdint.h in SUN
+ * - 2005-08-17
+ * 					- Set memory aligment to 8 bits
+ * - 2003-06-02
+ * 					- First Implementation
+ * @version 1.1.1
+ * */
+/* ========================================================================= */
+#ifndef __QS_CONFIG_H__
+#define __QS_CONFIG_H__
+
+#if ! defined(_XOPEN_SOURCE) || _XOPEN_SOURCE < 600
+# define _XOPEN_SOURCE 600
+#endif
+
+#define EG_NEWLINE "\n"
+
+/* ========================================================================= */
+/** @brief see if we have both pthread library and header file available, if
+ * so, define HAVE_EG_THREAD */
+#if defined HAVE_PTHREAD_H && HAVE_PTHREAD_H && defined HAVE_LIBPTHREAD && HAVE_LIBPTHREAD
+#define HAVE_EG_THREAD 1
+#else
+#define HAVE_EG_THREAD 0
+#endif
+
+/* ========================================================================= */
+/** @brief assert Debug options definitions, by defoult set on */
+#ifndef DEBUG
+#warning you should define DEBUG, assuming it to be 1
+#define DEBUG 1
+#endif
+
+/* ========================================================================= */
+/** @brief assert Verbose options definition, by default set on */
+#ifndef VERBOSE_LEVEL
+#warning you should define VERBOSE_LEVEL, assuming it to be 1
+#define VERBOSE_LEVEL 1
+#endif
+#endif
diff --git a/qsopt_ex/qsopt.c b/qsopt_ex/qsopt.c
new file mode 100644
index 0000000..05c53dd
--- /dev/null
+++ b/qsopt_ex/qsopt.c
@@ -0,0 +1,3933 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: qsopt.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+static int TRACE = 0;
+
+/****************************************************************************/
+/*                                                                          */
+/*                     User-level Functions                                 */
+/*                                                                          */
+/*  EXPORTED FUNCTIONS                                                      */
+/*                                                                          */
+/*    int EGLPNUM_TYPENAME_QSopt_primal (EGLPNUM_TYPENAME_QSdata *p, int *status)                             */
+/*    int EGLPNUM_TYPENAME_QSopt_dual (EGLPNUM_TYPENAME_QSdata *p, int *status)                               */
+/*    EGLPNUM_TYPENAME_QSdata *EGLPNUM_TYPENAME_QScreate_prob (const char *name, int objsense)                */
+/*    EGLPNUM_TYPENAME_QSdata *EGLPNUM_TYPENAME_QSread_prob (const char *filename, const char *filetype)      */
+/*    EGLPNUM_TYPENAME_QSdata *EGLPNUM_TYPENAME_QSload_prob (const char *probname, int ncols, int nrows,      */
+/*        int *cmatcnt, int *cmatbeg, int *cmatind, double *cmatval,        */
+/*        int objsense, double *obj, double *rhs, char *sense,              */
+/*        double *lower, double *upper, const char **colnames,              */
+/*        const char **rownames)                                            */
+/*    EGLPNUM_TYPENAME_QSdata *EGLPNUM_TYPENAME_QScopy_prob (EGLPNUM_TYPENAME_QSdata *p, const char *newname)                  */
+/*    int EGLPNUM_TYPENAME_QSchange_objsense (EGLPNUM_TYPENAME_QSdata *p, int newsense)                       */
+/*    int EGLPNUM_TYPENAME_QSget_objsense (EGLPNUM_TYPENAME_QSdata *p, int *objsense)                         */
+/*    int EGLPNUM_TYPENAME_QSnew_col (EGLPNUM_TYPENAME_QSdata *p, double obj, double lower, double upper,     */
+/*        const char *name)                                                 */
+/*    int EGLPNUM_TYPENAME_QSadd_cols (EGLPNUM_TYPENAME_QSdata *p, int num, int *cmatcnt, int *cmatbeg,       */
+/*        int *cmatind, double *cmatval, double *obj, double *lower,        */
+/*        double *upper, const char **names)                                */
+/*    int EGLPNUM_TYPENAME_QSadd_col (EGLPNUM_TYPENAME_QSdata *p, int cnt, int *cmatind, double *cmatval,     */
+/*        double obj, double lower, double upper, const char *name)         */
+/*    int EGLPNUM_TYPENAME_QSnew_row (EGLPNUM_TYPENAME_QSdata *p, double rhs, const char sense, char *name)   */
+/*    int EGLPNUM_TYPENAME_QSadd_rows (EGLPNUM_TYPENAME_QSdata *p, int num, int *rmatcnt, int *rmatbeg,       */
+/*        int *rmatind, double *rmatval, double *rhs, char *sense,          */
+/*        char **names)                                                     */
+/*    int EGLPNUM_TYPENAME_QSadd_row (EGLPNUM_TYPENAME_QSdata *p, int cnt, int *rmatind, double *rmatval,     */
+/*        double rhs, char sense, const char *name)                         */
+/*    int EGLPNUM_TYPENAME_QSdelete_rows (EGLPNUM_TYPENAME_QSdata *p, int num, int *dellist)                  */
+/*    int EGLPNUM_TYPENAME_QSdelete_row (EGLPNUM_TYPENAME_QSdata *p, int rowindex)                            */
+/*    int EGLPNUM_TYPENAME_QSdelete_setrows (EGLPNUM_TYPENAME_QSdata *p, int *flags)                          */
+/*    int EGLPNUM_TYPENAME_QSdelete_cols (EGLPNUM_TYPENAME_QSdata *p, int num, int *dellist)                  */
+/*    int EGLPNUM_TYPENAME_QSdelete_col (EGLPNUM_TYPENAME_QSdata *p, int colindex)                            */
+/*    int EGLPNUM_TYPENAME_QSdelete_setcols (EGLPNUM_TYPENAME_QSdata *p, int *flags)                          */
+/*    int EGLPNUM_TYPENAME_QSdelete_named_column (EGLPNUM_TYPENAME_QSdata *p, const char *colname)            */
+/*    int EGLPNUM_TYPENAME_QSdelete_named_columns_list (EGLPNUM_TYPENAME_QSdata *p, int num,                  */
+/*        const char **colnames)                                            */
+/*    int EGLPNUM_TYPENAME_QSdelete_named_row (EGLPNUM_TYPENAME_QSdata *p, const char *rowname)               */
+/*    int EGLPNUM_TYPENAME_QSdelete_named_rows_list (EGLPNUM_TYPENAME_QSdata *p, int num,                     */
+/*        const char **rownames)                                            */
+/*    int EGLPNUM_TYPENAME_QSchange_senses (EGLPNUM_TYPENAME_QSdata *p, int num, int *rowlist, char *sense)   */
+/*    int EGLPNUM_TYPENAME_QSchange_sense (EGLPNUM_TYPENAME_QSdata *p, int rowindex, char sense)              */
+/*    int EGLPNUM_TYPENAME_QSchange_coef (EGLPNUM_TYPENAME_QSdata *p, int rowindex, int colindex,             */
+/*        double coef)                                                      */
+/*    int EGLPNUM_TYPENAME_QSchange_objcoef (EGLPNUM_TYPENAME_QSdata *p, int indx, double coef)               */
+/*    int EGLPNUM_TYPENAME_QSchange_rhscoef (EGLPNUM_TYPENAME_QSdata *p, int indx, double coef)               */
+/*    int EGLPNUM_TYPENAME_QSchange_bounds (EGLPNUM_TYPENAME_QSdata *p, int num, int *collist, char *lu,      */
+/*        double *bounds)                                                   */
+/*    int EGLPNUM_TYPENAME_QSchange_bound (EGLPNUM_TYPENAME_QSdata *p, int indx, char lu, double bound)       */
+/*    int EGLPNUM_TYPENAME_QSwrite_basis (EGLPNUM_TYPENAME_QSdata *p, QSbasis *B, const char *filename)       */
+/*    QSbasis *EGLPNUM_TYPENAME_QSget_basis (EGLPNUM_TYPENAME_QSdata *p)                                      */
+/*    QSbasis *EGLPNUM_TYPENAME_QSread_basis (EGLPNUM_TYPENAME_QSdata *p, const char *filename)               */
+/*    int EGLPNUM_TYPENAME_QSload_basis (EGLPNUM_TYPENAME_QSdata *p, QSbasis *B)                              */
+/*    int EGLPNUM_TYPENAME_QSread_and_load_basis (EGLPNUM_TYPENAME_QSdata *p, const char *filename)           */
+/*    int EGLPNUM_TYPENAME_QSload_basis_array (EGLPNUM_TYPENAME_QSdata *p, char *cstat, char *rstat)          */
+/*    int EGLPNUM_TYPENAME_QSload_basis_and_row_norms_array (EGLPNUM_TYPENAME_QSdata *p, char *cstat,         */
+/*      char *rstat, double *rownorms)                                      */
+/*    int EGLPNUM_TYPENAME_QSget_basis_array (EGLPNUM_TYPENAME_QSdata *p, char *cstat, char *rstat)           */
+/*    int EGLPNUM_TYPENAME_QSget_basis_and_row_norms_array (EGLPNUM_TYPENAME_QSdata *p, char *cstat,          */
+/*      char *rstat, double *rownorms)                                      */
+/*    int EGLPNUM_TYPENAME_QSget_binv_row (EGLPNUM_TYPENAME_QSdata *p, int indx, double *binvrow)             */
+/*    int EGLPNUM_TYPENAME_QSget_tableau_row (EGLPNUM_TYPENAME_QSdata *p, int indx, double *tableaurow)       */
+/*    int EGLPNUM_TYPENAME_QSget_basis_order (EGLPNUM_TYPENAME_QSdata *p, int *basorder)                      */
+/*    int EGLPNUM_TYPENAME_QSget_status (EGLPNUM_TYPENAME_QSdata *p, int *status)                             */
+/*    int EGLPNUM_TYPENAME_QSget_solution (EGLPNUM_TYPENAME_QSdata *p, double *value, double *x,              */
+/*        double *pi, double *slack, double *rc),                           */
+/*    int EGLPNUM_TYPENAME_QSget_objval (EGLPNUM_TYPENAME_QSdata *p, double *value)                           */
+/*    int EGLPNUM_TYPENAME_QSget_x_array (EGLPNUM_TYPENAME_QSdata *p, double *x)                              */
+/*    int EGLPNUM_TYPENAME_QSget_rc_array (EGLPNUM_TYPENAME_QSdata *p, double *rc)                            */
+/*    int EGLPNUM_TYPENAME_QSget_pi_array (EGLPNUM_TYPENAME_QSdata *p, double *pi)                            */
+/*    int EGLPNUM_TYPENAME_QSget_slack_array (EGLPNUM_TYPENAME_QSdata *p, double *slack)                      */
+/*    int EGLPNUM_TYPENAME_QSget_infeas_array (EGLPNUM_TYPENAME_QSdata *p, double *pi)                        */
+/*    int EGLPNUM_TYPENAME_QSget_named_x (EGLPNUM_TYPENAME_QSdata *p, const char *colname, double *val)       */
+/*    int EGLPNUM_TYPENAME_QSget_named_rc (EGLPNUM_TYPENAME_QSdata *p, const char *colname, double *val)      */
+/*    int EGLPNUM_TYPENAME_QSget_named_pi (EGLPNUM_TYPENAME_QSdata *p, const char *rowname, double *val)      */
+/*    int EGLPNUM_TYPENAME_QSget_named_slack (EGLPNUM_TYPENAME_QSdata *p, const char *rowname, double *val)   */
+/*    int EGLPNUM_TYPENAME_QSget_colcount (EGLPNUM_TYPENAME_QSdata *p)                                        */
+/*    int EGLPNUM_TYPENAME_QSget_rowcount (EGLPNUM_TYPENAME_QSdata *p)                                        */
+/*    int EGLPNUM_TYPENAME_QSget_nzcount (EGLPNUM_TYPENAME_QSdata *p)                                         */
+/*    int EGLPNUM_TYPENAME_QSget_obj (EGLPNUM_TYPENAME_QSdata *p, double *obj),                               */
+/*    int EGLPNUM_TYPENAME_QSget_rhs (EGLPNUM_TYPENAME_QSdata *p, double *rhs)                                */
+/*    char* EGLPNUM_TYPENAME_QSget_probname (EGLPNUM_TYPENAME_QSdata *p)                                      */
+/*    char* EGLPNUM_TYPENAME_QSget_objname (EGLPNUM_TYPENAME_QSdata *p)                                       */
+/*    int EGLPNUM_TYPENAME_QSget_columns (EGLPNUM_TYPENAME_QSdata *p, int **colcnt, int **colbeg,             */
+/*        int **colind, double **colval, double **obj, double **lower,      */
+/*        double **upper, char ***names)                                    */
+/*    int EGLPNUM_TYPENAME_QSget_columns_list (EGLPNUM_TYPENAME_QSdata *p, int num, int *collist,             */
+/*        int **colcnt, int **colbeg, int **colind, double **colval,        */
+/*        double **obj, double **lower, double **upper, char ***names)      */
+/*    int EGLPNUM_TYPENAME_QSget_rows (EGLPNUM_TYPENAME_QSdata *p, int **rowcnt, int **rowbeg, int **rowind,  */
+/*        double **rowval, double **rhs, char **sense, char ***names)       */
+/*    int EGLPNUM_TYPENAME_QSget_rows_list (EGLPNUM_TYPENAME_QSdata *p, int num, int *rowlist, int **rowcnt,  */
+/*        int **rowbeg, int **rowind, double **rowval, double **rhs,        */
+/*        char **sense, char ***names)                                      */
+/*    int EGLPNUM_TYPENAME_QSget_column_index (EGLPNUM_TYPENAME_QSdata *p, const char *name, int *colindex)   */
+/*    int EGLPNUM_TYPENAME_QSget_row_index (EGLPNUM_TYPENAME_QSdata *p, const char *name, int *rowindex)      */
+/*    int EGLPNUM_TYPENAME_QSget_rownames (EGLPNUM_TYPENAME_QSdata *p, char **rownames)                       */
+/*    int EGLPNUM_TYPENAME_QSget_colnames (EGLPNUM_TYPENAME_QSdata *p, char **colnames)                       */
+/*    int EGLPNUM_TYPENAME_QSget_bound (EGLPNUM_TYPENAME_QSdata *p, int colindex, char lu, double *bound)     */
+/*    int EGLPNUM_TYPENAME_QSget_bounds (EGLPNUM_TYPENAME_QSdata *p, double *lower, double *upper)            */
+/*    int EGLPNUM_TYPENAME_QSget_intcount (EGLPNUM_TYPENAME_QSdata *p, int *count)                            */
+/*    int EGLPNUM_TYPENAME_QSget_intflags (EGLPNUM_TYPENAME_QSdata *p, int *intflags)                         */
+/*    int EGLPNUM_TYPENAME_QScompute_row_norms (EGLPNUM_TYPENAME_QSdata *p)                                   */
+/*    void EGLPNUM_TYPENAME_QSfree_prob (EGLPNUM_TYPENAME_QSdata *p)                                          */
+/*    void EGLPNUM_TYPENAME_QSfree_basis (QSbasis *B)                                        */
+/*    int EGLPNUM_TYPENAME_QSwrite_prob (EGLPNUM_TYPENAME_QSdata *p, const char *filename,                    */
+/*        const char *filetype)                                             */
+/*    int EGLPNUM_TYPENAME_QSwrite_prob_file (EGLPNUM_TYPENAME_QSdata *p, FILE *file, const char *filetype)   */
+/*    int EGLPNUM_TYPENAME_QSset_param (EGLPNUM_TYPENAME_QSdata *p, int whichparam, int newvalue)             */
+/*    int QSset_param_double (EGLPNUM_TYPENAME_QSdata *p, int whichparam, double newvalue)   */
+/*    int EGLPNUM_TYPENAME_QSget_param (EGLPNUM_TYPENAME_QSdata *p, int whichparam, int *value)               */
+/*    int QSget_param_double (EGLPNUM_TYPENAME_QSdata *p, int whichparam, double *value)     */
+/*    int EGLPNUM_TYPENAME_QStest_row_norms (EGLPNUM_TYPENAME_QSdata *p)                                      */
+/*    int EGLPNUM_TYPENAME_QSopt_strongbranch (EGLPNUM_TYPENAME_QSdata *p, int ncand, int *candidatelist,     */
+/*        double *xlist, double *down_vals, double *up_vals,                */
+/*        int iterations, double objbound)                                  */
+/*    int EGLPNUM_TYPENAME_QSopt_pivotin_row (EGLPNUM_TYPENAME_QSdata *p, int rcnt, int *rlist)               */
+/*    int EGLPNUM_TYPENAME_QSopt_pivotin_col (EGLPNUM_TYPENAME_QSdata *p, int ccnt, int *clist)               */
+/*    void EGLPNUM_TYPENAME_QSfree (void *ptr)                                               */
+/*    void EGLPNUM_TYPENAME_QSstart (void)                                                   */
+/*    void EGLPNUM_TYPENAME_QSend (void)                                                     */
+/*    char *EGLPNUM_TYPENAME_QSversion (void))                                               */
+/*                                                                          */
+/*    NEW FUNCTIONS - Add to Docs                                           */
+/*                                                                          */
+/*    char *EGLPNUM_TYPENAME_QSversion (void))                                               */
+/*    int EGLPNUM_TYPENAME_QSget_objsense (EGLPNUM_TYPENAME_QSdata *p, int *objsense)                         */
+/*                                                                          */
+/****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "qsopt_EGLPNUM_TYPENAME.h"
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "eg_lpnum.h"
+#include "eg_io.h"
+#include "except.h"
+#include "util.h"
+
+#include "lpdata_EGLPNUM_TYPENAME.h"
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+#include "simplex_EGLPNUM_TYPENAME.h"
+#include "price_EGLPNUM_TYPENAME.h"
+#include "qstruct_EGLPNUM_TYPENAME.h"
+#include "lib_EGLPNUM_TYPENAME.h"
+#include "mps_EGLPNUM_TYPENAME.h"
+#include "lp_EGLPNUM_TYPENAME.h"
+
+
+void EGLPNUM_TYPENAME_QSset_precision (
+	const unsigned prec)
+{
+	EGlpNumSetPrecision (prec);
+	EGLPNUM_TYPENAME_ILLchange_precision ();
+	/* change the numbers */
+}
+
+static void init_basis (
+	QSbasis * B),
+  free_cache (
+	EGLPNUM_TYPENAME_QSdata * p);
+
+static int opt_work ( EGLPNUM_TYPENAME_QSdata * p, int *status, int primal_or_dual),
+  qsbasis_to_illbasis ( QSbasis * qB, EGLPNUM_TYPENAME_ILLlp_basis * B),
+  illbasis_to_qsbasis ( EGLPNUM_TYPENAME_ILLlp_basis * B, QSbasis * qB),
+  grab_basis ( EGLPNUM_TYPENAME_QSdata * p),
+  check_qsdata_pointer ( EGLPNUM_TYPENAME_QSdata * p);
+
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSopt_primal (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int *status)
+{
+	int rval = 0;
+
+	if (status)
+		*status = QS_LP_UNSOLVED;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	/* If both the basis and the cache exist, then skip the optimization */
+
+	if (!p->basis || !p->cache)
+	{
+		rval = opt_work (p, status, 0);
+		CHECKRVALG (rval, CLEANUP);
+	}
+	else
+	{
+		if (status)
+			*status = p->cache->status;
+	}
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSopt_dual (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int *status)
+{
+	int rval = 0;
+
+	if (status)
+		*status = QS_LP_UNSOLVED;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (!p->basis || !p->cache || !p->factorok)
+	{
+		rval = opt_work (p, status, 1);
+		CHECKRVALG (rval, CLEANUP);
+	}
+	else
+	{
+		if (status)
+			*status = p->cache->status;
+	}
+
+CLEANUP:
+
+	if (rval == QS_LP_CHANGE_PREC)
+	{
+		MESSAGE (__QS_SB_VERB, "Changing precision");
+		return rval;
+	}
+	EG_RETURN (rval);
+}
+
+static int opt_work (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int *status,
+	int primal_or_dual)
+{
+	int rval = 0;
+	int rstatus = QS_LP_UNSOLVED;
+	EGLPNUM_TYPENAME_QSdata *p2 = 0;
+
+	if (p->basis)
+	{
+		if (p->basis->nstruct != p->qslp->nstruct ||
+				p->basis->nrows != p->qslp->nrows)
+		{
+			QSlog("Size of basis does not match LP");
+			rval = 1;
+			goto CLEANUP;
+		}
+	}
+
+	if (!p->basis && p->lp->basisid == -1 && p->simplex_scaling == 1)
+	{
+		/* Try scaling by copying the LP and solving */
+
+		EGLPNUM_TYPENAME_ILLprice_free_pricing_info (p->pricing);	/* Just to be sure  */
+		p->factorok = 0;						/* that p is clean. */
+
+		p2 = EGLPNUM_TYPENAME_QScopy_prob (p, "scaled_lp");
+		if (p2 == 0)
+			goto CLEANUP;
+
+		rval = EGLPNUM_TYPENAME_ILLlp_scale (p2->qslp);
+		CHECKRVALG (rval, CLEANUP);
+
+		if (primal_or_dual == 0)
+		{
+			rval = EGLPNUM_TYPENAME_ILLlib_optimize (p2->lp, p2->basis, p2->pricing,
+															PRIMAL_SIMPLEX, 0, p2->simplex_display, 
+															&(p->itcnt));
+		}
+		else
+		{
+			rval = EGLPNUM_TYPENAME_ILLlib_optimize (p2->lp, p2->basis, p2->pricing,
+															DUAL_SIMPLEX, 0, p2->simplex_display,
+															&(p->itcnt));
+		}
+		CHECKRVALG (rval, CLEANUP);
+
+		rval = grab_basis (p2);
+		CHECKRVALG (rval, CLEANUP);
+
+		if (p->basis)
+		{
+			EGLPNUM_TYPENAME_ILLlp_basis_free (p->basis);
+			ILL_IFFREE (p->basis, EGLPNUM_TYPENAME_ILLlp_basis);
+		}
+		p->basis = p2->basis;
+		p2->basis = 0;
+		EGLPNUM_TYPENAME_QSfree_prob (p2);
+		p2 = 0;
+	}
+
+	if (primal_or_dual == 0)
+	{
+		if (p->factorok == 0)
+		{
+			if (p->basis == 0)
+				p->lp->basisid = -1;
+			rval = EGLPNUM_TYPENAME_ILLlib_optimize (p->lp, p->basis, p->pricing, PRIMAL_SIMPLEX,
+															&rstatus, p->simplex_display, &(p->itcnt));
+		}
+		else
+		{
+			EGLPNUM_TYPENAME_ILLprice_free_pricing_info (p->pricing);
+			if (p->lp->basisid != -1)
+				p->lp->fbasisid = p->lp->basisid;
+			rval = EGLPNUM_TYPENAME_ILLlib_optimize (p->lp, 0, p->pricing,
+															PRIMAL_SIMPLEX, &rstatus, p->simplex_display, 
+															&(p->itcnt));
+		}
+	}
+	else
+	{
+		if (p->factorok == 0)
+		{
+			if (p->basis == 0)
+				p->lp->basisid = -1;
+			rval = EGLPNUM_TYPENAME_ILLlib_optimize (p->lp, p->basis, p->pricing, DUAL_SIMPLEX,
+															&rstatus, p->simplex_display, &(p->itcnt));
+		}
+		else
+		{
+			/* The factorization and rownorms should be up-to-date */
+			if (p->lp->basisid != -1)
+			{
+				p->lp->fbasisid = p->lp->basisid;
+			}
+			else
+			{
+				EGLPNUM_TYPENAME_ILLprice_free_pricing_info (p->pricing);
+			}
+			rval = EGLPNUM_TYPENAME_ILLlib_optimize (p->lp, 0, p->pricing,
+															DUAL_SIMPLEX, &rstatus, p->simplex_display, 
+															&(p->itcnt));
+		}
+	}
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = grab_basis (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (rstatus == QS_LP_OPTIMAL)
+	{
+		rval = EGLPNUM_TYPENAME_QSgrab_cache (p, rstatus);
+		CHECKRVALG (rval, CLEANUP);
+	}
+	else
+	{
+		free_cache (p);
+	}
+
+	p->factorok = 1;
+
+#if 0
+	p->lp->basisid = -1;					/* This will cause the basis to be reloaded at the */
+	/* next optimization - it could be moved into the  */
+	/* add/del routines if we want to cache the        */
+	/* factored basis.                                 */
+	-switched to having qs_simplex load a basis whenever it is passed;
+	the trouble with keeping basisid == -1 is that the QS - level routines
+		will not know if the
+		current lp has been optimized (so, for example,
+																	 getbasis will not work)
+		.
+#endif
+	CLEANUP:p->qstatus = rstatus;
+
+	if (status)
+		*status = rstatus;
+
+	if (p2)
+		EGLPNUM_TYPENAME_QSfree_prob (p2);
+	if (rval == QS_LP_CHANGE_PREC)
+	{
+		MESSAGE (__QS_SB_VERB, "Changing precision");
+		return rval;
+	}
+	MESSAGE (rval ? 0 : 1000, "Error code %d", rval);
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSopt_pivotin_row (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int rcnt,
+	int *rlist)
+{
+	int basismod = 0;
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (p->pricing == 0)
+	{
+		ILL_ERROR (rval, "pricing info not available in EGLPNUM_TYPENAME_QSopt_pivotin_row\n");
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLsimplex_pivotin (p->lp, p->pricing, rcnt, rlist,
+														 SIMPLEX_PIVOTINROW, &basismod);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = grab_basis (p);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSopt_pivotin_col (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int ccnt,
+	int *clist)
+{
+	int basismod = 0;
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (p->pricing == 0)
+	{
+		ILL_ERROR (rval, "pricing info not available in QSopt_pivotin\n");
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLsimplex_pivotin (p->lp, p->pricing, ccnt, clist,
+														 SIMPLEX_PIVOTINCOL, &basismod);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = grab_basis (p);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSopt_strongbranch (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int ncand,
+	int *candidatelist,
+	EGLPNUM_TYPE * xlist,
+	EGLPNUM_TYPE * down_vals,
+	EGLPNUM_TYPE * up_vals,
+	int iterations,
+	EGLPNUM_TYPE objbound)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (p->pricing == 0)
+	{
+		rval = 1;
+		CHECKRVALG (rval, CLEANUP);
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLlib_strongbranch (p->lp, p->pricing, candidatelist, ncand,
+															xlist, down_vals, up_vals, iterations, objbound,
+															&(p->itcnt));
+	CHECKRVALG (rval, CLEANUP);
+
+	p->factorok = 0;
+	free_cache (p);
+	p->qstatus = QS_LP_UNSOLVED;	/* Was set to MODIFIED in free_cache () */
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSdata *EGLPNUM_TYPENAME_QScreate_prob (
+	const char *name,
+	int objsense)
+{
+	int rval = 0;
+	EGLPNUM_TYPENAME_QSdata *p = 0;
+	int len;
+
+	ILL_SAFE_MALLOC (p, 1, EGLPNUM_TYPENAME_QSdata);
+	if (!p)
+	{
+		QSlog("out of memory in EGLPNUM_TYPENAME_QScreate_prob");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	p->qslp = 0;
+	p->lp = 0;
+	p->pricing = 0;
+	p->basis = 0;
+	p->cache = 0;
+	p->qstatus = QS_LP_UNSOLVED;
+	p->factorok = 0;
+
+	p->itcnt.pI_iter = 0;
+	p->itcnt.pII_iter = 0;
+	p->itcnt.dI_iter = 0;
+	p->itcnt.dII_iter = 0;
+	p->itcnt.tot_iter = 0;
+	EGLPNUM_TYPENAME_EGlpNumInitVar(p->uobjlim);
+	EGLPNUM_TYPENAME_EGlpNumInitVar(p->lobjlim);
+	EGLPNUM_TYPENAME_EGlpNumCopy(p->uobjlim, EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+	EGLPNUM_TYPENAME_EGlpNumCopy(p->lobjlim, EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+
+	p->simplex_display = 0;
+	p->simplex_scaling = 1;
+
+	ILL_SAFE_MALLOC (p->qslp, 1, EGLPNUM_TYPENAME_ILLlpdata);
+	if (!p->qslp)
+	{
+		QSlog("out of memory in EGLPNUM_TYPENAME_QScreate_prob");
+		rval = 1;
+		goto CLEANUP;
+	}
+	EGLPNUM_TYPENAME_ILLlpdata_init (p->qslp);
+
+	ILL_SAFE_MALLOC (p->lp, 1, EGLPNUM_TYPENAME_lpinfo);
+	if (!p->lp)
+	{
+		QSlog("out of memory in EGLPNUM_TYPENAME_QScreate_prob");
+		rval = 1;
+		goto CLEANUP;
+	}
+	EGLPNUM_TYPENAME_EGlpNumInitVar (p->lp->objval);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (p->lp->pobjval);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (p->lp->dobjval);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (p->lp->pinfeas);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (p->lp->dinfeas);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (p->lp->objbound);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (p->lp->upd.piv);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (p->lp->upd.dty);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (p->lp->upd.c_obj);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (p->lp->upd.tz);
+	EGLPNUM_TYPENAME_ILLsimplex_init_lpinfo (p->lp);
+	EGLPNUM_TYPENAME_ILLsimplex_load_lpinfo (p->qslp, p->lp);
+
+	ILL_SAFE_MALLOC (p->pricing, 1, EGLPNUM_TYPENAME_price_info);
+	if (!p->pricing)
+	{
+		QSlog("out of memory in EGLPNUM_TYPENAME_QScreate_prob");
+		rval = 1;
+		goto CLEANUP;
+	}
+	EGLPNUM_TYPENAME_EGlpNumInitVar (p->pricing->htrigger);
+	EGLPNUM_TYPENAME_ILLprice_init_pricing_info (p->pricing);
+	p->pricing->pI_price = QS_DEFAULT_PRICE_PI;
+	p->pricing->pII_price = QS_DEFAULT_PRICE_PII;
+	p->pricing->dI_price = QS_DEFAULT_PRICE_DI;
+	p->pricing->dII_price = QS_DEFAULT_PRICE_DII;
+
+	if (name)
+	{
+		len = strlen (name) + 1;
+		ILL_SAFE_MALLOC (p->name, len, char);
+
+		strcpy (p->name, name);
+	}
+	else
+	{
+		ILL_SAFE_MALLOC (p->name, 7, char);
+
+		sprintf (p->name, "noname");
+	}
+
+	len = strlen (p->name) + 1;
+	ILL_SAFE_MALLOC (p->qslp->probname, len, char);
+
+	strcpy (p->qslp->probname, p->name);
+
+	if (objsense == QS_MAX)
+	{
+		p->qslp->objsense = QS_MAX;
+	}
+
+CLEANUP:
+
+	if (rval)
+	{
+		EGLPNUM_TYPENAME_QSfree_prob (p);
+		p = 0;
+	}
+
+	return p;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSdata *EGLPNUM_TYPENAME_QSread_prob (
+	const char *filename,
+	const char *filetype)
+{
+	EGLPNUM_TYPENAME_QSdata *p = 0;
+	EGioFile_t *file = 0;
+	EGLPNUM_TYPENAME_QSline_reader reader;
+
+	if ((file = EGioOpen (filename, "r")) == 0)
+	{
+		perror (filename);
+		QSlog("Unable to open \"%s\" for input.", filename);
+	}
+	if (file == NULL)
+		goto CLEANUP;
+
+	reader = EGLPNUM_TYPENAME_ILLline_reader_new ((EGLPNUM_TYPENAME_qsread_line_fct) EGioGets, file);
+	p = EGLPNUM_TYPENAME_QSget_prob (reader, filename, filetype);
+	EGLPNUM_TYPENAME_QSline_reader_free (reader);	/* Bico - 040723 */
+
+CLEANUP:
+	if (file != NULL)
+	{
+		EGioClose (file);
+	}
+	return p;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSdata *EGLPNUM_TYPENAME_QSload_prob (
+	const char *probname,
+	int ncols,
+	int nrows,
+	int *cmatcnt,
+	int *cmatbeg,
+	int *cmatind,
+	EGLPNUM_TYPE * cmatval,
+	int objsense,
+	EGLPNUM_TYPE * obj,
+	EGLPNUM_TYPE * rhs,
+	char *sense,
+	EGLPNUM_TYPE * lower,
+	EGLPNUM_TYPE * upper,
+	const char **colnames,
+	const char **rownames)
+{
+	int rval = 0;
+	EGLPNUM_TYPENAME_QSdata *p = 0;
+
+	p = EGLPNUM_TYPENAME_QScreate_prob (probname, objsense);
+	if (p == 0)
+		goto CLEANUP;
+
+	rval = EGLPNUM_TYPENAME_ILLlib_newrows (p->lp, 0, nrows, rhs, sense, 0, rownames);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_addcols (p->lp, 0, ncols, cmatcnt, cmatbeg, cmatind,
+												 cmatval, obj, lower, upper, colnames, 0);
+	CHECKRVALG (rval, CLEANUP);
+
+	p->factorok = 0;
+
+CLEANUP:
+
+	if (rval)
+	{
+		EGLPNUM_TYPENAME_QSfree_prob (p);
+		p = 0;
+	}
+
+	return p;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSdata *EGLPNUM_TYPENAME_QScopy_prob (
+	EGLPNUM_TYPENAME_QSdata * p,
+	const char *newname)
+{
+	int rval = 0;
+	int j, col, beg, pindex, hit;
+	EGLPNUM_TYPENAME_QSdata *p2 = 0;
+	char *coln;
+	char buf[ILL_namebufsize];
+
+	/* QSlog("EGLPNUM_TYPENAME_QScopy_prob ..."); */
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	p2 = EGLPNUM_TYPENAME_QScreate_prob (newname, p->qslp->objsense);
+	if (p2 == 0)
+		goto CLEANUP;
+
+	rval = EGLPNUM_TYPENAME_ILLlib_newrows (p2->lp, 0, p->qslp->nrows,
+												 p->qslp->rhs, p->qslp->sense, p->qslp->rangeval,
+												 (const char **) p->qslp->rownames);
+	CHECKRVALG (rval, CLEANUP);
+
+	for (j = 0; j < p->qslp->nstruct; j++)
+	{
+		col = p->qslp->structmap[j];
+		if (p->qslp->colnames)
+			coln = p->qslp->colnames[j];
+		else
+			coln = 0;
+		beg = p->qslp->A.matbeg[col];
+
+		/* Monika: Note that Java will need to handle these arrays */
+		/*         without using the beg offset.  The easiest way  */
+		/*         may be to copy the arrays, as in the getcols()  */
+		/*         code in lib.c.                                  */
+
+		rval = EGLPNUM_TYPENAME_ILLlib_addcol (p2->lp, 0,
+													p->qslp->A.matcnt[col],
+													p->qslp->A.matind + beg, p->qslp->A.matval + beg,
+													p->qslp->obj[col], p->qslp->lower[col],
+													p->qslp->upper[col], coln, 0);
+		CHECKRVALG (rval, CLEANUP);
+	}
+
+	p2->qslp->objsense = p->qslp->objsense;
+
+	p2->factorok = 0;
+	p2->simplex_display = p->simplex_display;
+	p2->simplex_scaling = p->simplex_scaling;
+	EGLPNUM_TYPENAME_EGlpNumClearVar (p2->pricing->htrigger);
+	*(p2->pricing) = *(p->pricing);
+	/* I added this line because copying the EGLPNUM_TYPENAME_heap (as a pointer) doesn't make any
+	 * sense ! */
+	EGLPNUM_TYPENAME_ILLheap_init (&(p2->pricing->h));
+	EGLPNUM_TYPENAME_EGlpNumInitVar (p2->pricing->htrigger);
+	EGLPNUM_TYPENAME_EGlpNumCopy (p2->pricing->htrigger, p->pricing->htrigger);
+
+	if (p->qslp->intmarker != 0)
+	{
+		ILL_SAFE_MALLOC (p2->qslp->intmarker, p->qslp->nstruct, char);
+
+		for (j = 0; j < p->qslp->nstruct; j++)
+		{
+			p2->qslp->intmarker[j] = p->qslp->intmarker[j];
+		}
+	}
+
+	if (p->qslp->objname != 0)
+	{
+		ILL_UTIL_STR (p2->qslp->objname, p->qslp->objname);
+	}
+	else
+	{
+		strcpy (buf, "obj");
+		rval = ILLsymboltab_uname (&p2->qslp->rowtab, buf, "", NULL);
+		CHECKRVALG (rval, CLEANUP);
+		ILL_UTIL_STR (p2->qslp->objname, buf);
+	}
+	rval = ILLsymboltab_register (&p2->qslp->rowtab, p2->qslp->objname,
+																-1, &pindex, &hit);
+	rval = rval || hit;
+	CHECKRVALG (rval, CLEANUP);
+
+	ILLstring_reporter_copy (&p2->qslp->reporter, &p->qslp->reporter);
+
+CLEANUP:
+
+	if (rval)
+	{
+		EGLPNUM_TYPENAME_QSfree_prob (p2);
+		p2 = 0;
+	}
+
+	return p2;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSchange_objsense (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int newsense)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (newsense != QS_MIN && newsense != QS_MAX)
+	{
+		QSlog("Illegal objective sense %d", newsense);
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	if (p->qslp->objsense != newsense)
+	{
+		if(newsense == QS_MAX) EGLPNUM_TYPENAME_ILLsimplex_set_bound(p->lp,(const EGLPNUM_TYPE *)(&(p->lobjlim)), newsense);
+		else EGLPNUM_TYPENAME_ILLsimplex_set_bound(p->lp,(const EGLPNUM_TYPE*)(&(p->uobjlim)), newsense);
+		p->qslp->objsense = newsense;
+		free_cache (p);
+	}
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int
+EGLPNUM_TYPENAME_QSget_itcnt(
+	EGLPNUM_TYPENAME_QSdata* p,
+	int *pI_iter,
+	int *pII_iter,
+	int *dI_iter, 
+	int *dII_iter,
+	int *tot_iter)
+{
+	int rval = 0;
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+	if(pI_iter) *pI_iter = p->itcnt.pI_iter;
+	if(pII_iter) *pII_iter = p->itcnt.pII_iter;
+	if(dI_iter) *dI_iter = p->itcnt.dI_iter;
+	if(dII_iter) *dII_iter = p->itcnt.dII_iter;
+	if(tot_iter) *tot_iter = p->itcnt.tot_iter;
+
+CLEANUP:
+
+ 	EG_RETURN(rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_objsense (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int *objsense)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (objsense)
+		*objsense = p->qslp->objsense;
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSnew_col (
+	EGLPNUM_TYPENAME_QSdata * p,
+	const EGLPNUM_TYPE obj,
+	const EGLPNUM_TYPE lower,
+	const EGLPNUM_TYPE upper,
+	const char *name)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_newcol (p->lp, p->basis, obj, lower, upper, name, p->factorok);
+	CHECKRVALG (rval, CLEANUP);
+
+	free_cache (p);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSadd_cols (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int num,
+	int *cmatcnt,
+	int *cmatbeg,
+	int *cmatind,
+	EGLPNUM_TYPE * cmatval,
+	EGLPNUM_TYPE * obj,
+	EGLPNUM_TYPE * lower,
+	EGLPNUM_TYPE * upper,
+	const char **names)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_addcols (p->lp, p->basis, num, cmatcnt, cmatbeg,
+												 cmatind, cmatval, obj, lower, upper, names,
+												 p->factorok);
+	CHECKRVALG (rval, CLEANUP);
+
+	free_cache (p);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSadd_col (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int cnt,
+	int *cmatind,
+	EGLPNUM_TYPE * cmatval,
+	EGLPNUM_TYPE obj,
+	EGLPNUM_TYPE lower,
+	EGLPNUM_TYPE upper,
+	const char *name)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_addcol (p->lp, p->basis, cnt, cmatind, cmatval,
+												obj, lower, upper, name, p->factorok);
+	CHECKRVALG (rval, CLEANUP);
+
+	free_cache (p);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSnew_row (
+	EGLPNUM_TYPENAME_QSdata * p,
+	const EGLPNUM_TYPE rhs,
+	int sense,
+	const char *name)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_newrow (p->lp, p->basis, rhs, sense, EGLPNUM_TYPENAME_zeroLpNum, name);
+	CHECKRVALG (rval, CLEANUP);
+
+	p->factorok = 0;
+	free_cache (p);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSadd_ranged_rows (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int num,
+	int *rmatcnt,
+	int *rmatbeg,
+	int *rmatind,
+	const EGLPNUM_TYPE * rmatval,
+	const EGLPNUM_TYPE * rhs,
+	char *sense,
+	const EGLPNUM_TYPE * range,
+	const char **names)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_addrows (p->lp, p->basis, num, rmatcnt, rmatbeg,
+												 rmatind, rmatval, rhs, sense, range,
+												 names, &(p->factorok));
+	CHECKRVALG (rval, CLEANUP);
+
+	if (p->factorok == 1 && p->basis->rownorms)
+	{
+		rval = EGLPNUM_TYPENAME_ILLlib_loadrownorms (p->lp, p->pricing, p->basis->rownorms);
+		CHECKRVALG (rval, CLEANUP);
+		/* This really should go inside of EGLPNUM_TYPENAME_ILLlib_addrows, once pinf is  */
+		/* is moved into the lp struct.                                  */
+	}
+
+	free_cache (p);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSadd_ranged_row (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int cnt,
+	int *rmatind,
+	const EGLPNUM_TYPE * rmatval,
+	const EGLPNUM_TYPE * rhs,
+	int sense,
+	const EGLPNUM_TYPE * range,
+	const char *name)
+{
+	int rval = 0;
+	int vmatcnt[1];
+	int vmatbeg[1];
+	char vsense[1];
+	const char *vnames[1];
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	vmatcnt[0] = cnt;
+	vmatbeg[0] = 0;
+	vsense[0] = sense;
+	vnames[0] = name;
+
+	rval = EGLPNUM_TYPENAME_QSadd_ranged_rows (p, 1, vmatcnt, vmatbeg, rmatind, rmatval, rhs,
+														vsense, range, vnames);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSadd_rows (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int num,
+	int *rmatcnt,
+	int *rmatbeg,
+	int *rmatind,
+	const EGLPNUM_TYPE * rmatval,
+	const EGLPNUM_TYPE * rhs,
+	char *sense,
+	const char **names)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_addrows (p->lp, p->basis, num, rmatcnt, rmatbeg,
+												 rmatind, rmatval, rhs, sense, 0, names,
+												 &(p->factorok));
+	CHECKRVALG (rval, CLEANUP);
+
+	if (p->factorok == 1 && p->basis->rownorms)
+	{
+		rval = EGLPNUM_TYPENAME_ILLlib_loadrownorms (p->lp, p->pricing, p->basis->rownorms);
+		CHECKRVALG (rval, CLEANUP);
+		/* This really should go inside of EGLPNUM_TYPENAME_ILLlib_addrows, once pinf is  */
+		/* is moved into the lp struct.                                  */
+	}
+
+	free_cache (p);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSadd_row (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int cnt,
+	int *rmatind,
+	const EGLPNUM_TYPE * rmatval,
+	const EGLPNUM_TYPE * rhs,
+	int sense,
+	const char *name)
+{
+	int rval = 0;
+	int vmatcnt[1];
+	int vmatbeg[1];
+	char vsense[1];
+	const char *vnames[1];
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	vmatcnt[0] = cnt;
+	vmatbeg[0] = 0;
+	vsense[0] = sense;
+	vnames[0] = name;
+
+	rval = EGLPNUM_TYPENAME_QSadd_rows (p, 1, vmatcnt, vmatbeg, rmatind, rmatval, rhs, vsense,
+										 vnames);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSdelete_rows (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int num,
+	int *dellist)
+{
+	int rval = 0;
+	int basis_ok = 0;
+	int cache_ok = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_delrows (p->lp, p->basis, p->cache, num, dellist, &basis_ok,
+												 &cache_ok);
+	CHECKRVALG (rval, CLEANUP);
+
+	/* For now, just remove the basis - wait for pivotin */
+
+	if (p->basis && !basis_ok)
+	{
+		EGLPNUM_TYPENAME_ILLlp_basis_free (p->basis);
+		ILL_IFFREE (p->basis, EGLPNUM_TYPENAME_ILLlp_basis);
+	}
+
+	p->factorok = 0;
+
+	if (!p->basis || !basis_ok || !cache_ok)
+	{
+		/* Note: If we only delete basic rows then cached soln is valid */
+		free_cache (p);
+	}
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSdelete_row (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int rowindex)
+{
+	int rval = 0;
+	int vdellist[1];
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	vdellist[0] = rowindex;
+
+	rval = EGLPNUM_TYPENAME_QSdelete_rows (p, 1, vdellist);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSdelete_setrows (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int *flags)
+{
+	int rval = 0;
+	int j, num = 0;
+	int *dellist = 0;
+	int nrows;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	nrows = p->qslp->nrows;
+
+	for (j = 0; j < nrows; j++)
+	{
+		if (flags[j] == 1)
+			num++;
+	}
+
+	if (num > 0)
+	{
+		ILL_SAFE_MALLOC (dellist, num, int);
+
+		for (j = 0, num = 0; j < nrows; j++)
+		{
+			if (flags[j] == 1)
+			{
+				dellist[num++] = j;
+			}
+		}
+
+		rval = EGLPNUM_TYPENAME_QSdelete_rows (p, num, dellist);
+		CHECKRVALG (rval, CLEANUP);
+	}
+
+CLEANUP:
+
+	ILL_IFFREE (dellist, int);
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSdelete_named_row (
+	EGLPNUM_TYPENAME_QSdata * p,
+	const char *rowname)
+{
+	int rval = 0;
+	int i, vdellist[1];
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_QSget_row_index (p, rowname, &i);
+	CHECKRVALG (rval, CLEANUP);
+
+	vdellist[0] = i;
+
+	rval = EGLPNUM_TYPENAME_QSdelete_rows (p, 1, vdellist);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSdelete_named_rows_list (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int num,
+	const char **rownames)
+{
+	int rval = 0;
+	int i, k;
+	int *vdellist = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (num > 0)
+	{
+		ILL_SAFE_MALLOC (vdellist, num, int);
+
+		for (k = 0; k < num; k++)
+		{
+			rval = EGLPNUM_TYPENAME_QSget_row_index (p, rownames[k], &i);
+			CHECKRVALG (rval, CLEANUP);
+			vdellist[k] = i;
+		}
+
+		rval = EGLPNUM_TYPENAME_QSdelete_rows (p, num, vdellist);
+		CHECKRVALG (rval, CLEANUP);
+	}
+
+CLEANUP:
+
+	ILL_IFFREE (vdellist, int);
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSdelete_cols (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int num,
+	int *dellist)
+{
+	int rval = 0;
+	int basis_ok;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_delcols (p->lp, p->basis, num, dellist, &basis_ok);
+	CHECKRVALG (rval, CLEANUP);
+
+	/* For now, just remove the basis - wait for pivotout */
+
+	if (p->basis && !basis_ok)
+	{
+		EGLPNUM_TYPENAME_ILLlp_basis_free (p->basis);
+		ILL_IFFREE (p->basis, EGLPNUM_TYPENAME_ILLlp_basis);
+	}
+
+	p->factorok = 0;
+	free_cache (p);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSdelete_col (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int colindex)
+{
+	int rval = 0;
+	int vdellist[1];
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	vdellist[0] = colindex;
+
+	rval = EGLPNUM_TYPENAME_QSdelete_cols (p, 1, vdellist);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSdelete_setcols (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int *flags)
+{
+	int rval = 0;
+	int j, num = 0;
+	int *dellist = 0;
+	int ncols;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	ncols = p->qslp->nstruct;
+
+	for (j = 0; j < ncols; j++)
+	{
+		if (flags[j] == 1)
+			num++;
+	}
+
+	if (num > 0)
+	{
+		ILL_SAFE_MALLOC (dellist, num, int);
+
+		for (j = 0, num = 0; j < ncols; j++)
+		{
+			if (flags[j] == 1)
+			{
+				dellist[num++] = j;
+			}
+		}
+
+		rval = EGLPNUM_TYPENAME_QSdelete_cols (p, num, dellist);
+		CHECKRVALG (rval, CLEANUP);
+	}
+
+CLEANUP:
+
+	ILL_IFFREE (dellist, int);
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSdelete_named_column (
+	EGLPNUM_TYPENAME_QSdata * p,
+	const char *colname)
+{
+	int rval = 0;
+	int j, vdellist[1];
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_QSget_column_index (p, colname, &j);
+	CHECKRVALG (rval, CLEANUP);
+
+	vdellist[0] = j;
+
+	rval = EGLPNUM_TYPENAME_QSdelete_cols (p, 1, vdellist);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSdelete_named_columns_list (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int num,
+	const char **colnames)
+{
+	int rval = 0;
+	int i, j;
+	int *vdellist = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (num > 0)
+	{
+		ILL_SAFE_MALLOC (vdellist, num, int);
+
+		for (i = 0; i < num; i++)
+		{
+			rval = EGLPNUM_TYPENAME_QSget_column_index (p, colnames[i], &j);
+			CHECKRVALG (rval, CLEANUP);
+			vdellist[i] = j;
+		}
+
+		rval = EGLPNUM_TYPENAME_QSdelete_cols (p, num, vdellist);
+		CHECKRVALG (rval, CLEANUP);
+	}
+
+CLEANUP:
+
+	ILL_IFFREE (vdellist, int);
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSchange_senses (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int num,
+	int *rowlist,
+	char *sense)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_chgsense (p->lp, num, rowlist, sense);
+	CHECKRVALG (rval, CLEANUP);
+
+	free_cache (p);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSchange_range (
+	EGLPNUM_TYPENAME_QSdata*p,
+	int rowindex,
+	EGLPNUM_TYPE range)
+{
+	int rval = 0; 
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG(rval, CLEANUP);
+	
+	rval = EGLPNUM_TYPENAME_ILLlib_chgrange (p->lp, rowindex, range);
+	CHECKRVALG(rval, CLEANUP);
+	
+	p->factorok = 0; /* Sanjeeb -- 050911  */
+	free_cache (p);
+ 
+CLEANUP:
+
+	EG_RETURN(rval);
+
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSchange_sense (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int rowindex,
+	int sense)
+{
+	int rval = 0;
+	int vrowlist[1];
+	char vsenselist[1];
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	vrowlist[0] = rowindex;
+	vsenselist[0] = sense;
+
+	rval = EGLPNUM_TYPENAME_QSchange_senses (p, 1, vrowlist, vsenselist);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE  int EGLPNUM_TYPENAME_QSget_coef (
+	EGLPNUM_TYPENAME_QSdata *p,
+	int rowindex,
+	int colindex,
+	EGLPNUM_TYPE* coef)
+{
+	int rval = 0;
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+	rval = EGLPNUM_TYPENAME_ILLlib_getcoef (p->lp, rowindex, colindex, coef);
+	CHECKRVALG (rval, CLEANUP);
+	
+CLEANUP:
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSchange_coef (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int rowindex,
+	int colindex,
+	EGLPNUM_TYPE coef)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_chgcoef (p->lp, rowindex, colindex, coef);
+	CHECKRVALG (rval, CLEANUP);
+
+	free_cache (p);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSchange_objcoef (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int indx,
+	EGLPNUM_TYPE coef)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_chgobj (p->lp, indx, coef);
+	CHECKRVALG (rval, CLEANUP);
+
+	free_cache (p);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSchange_rhscoef (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int indx,
+	EGLPNUM_TYPE coef)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_chgrhs (p->lp, indx, coef);
+	CHECKRVALG (rval, CLEANUP);
+
+	free_cache (p);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSchange_bounds (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int num,
+	int *collist,
+	char *lu,
+	const EGLPNUM_TYPE * bounds)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_chgbnds (p->lp, num, collist, lu, bounds);
+	CHECKRVALG (rval, CLEANUP);
+
+	free_cache (p);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSchange_bound (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int indx,
+	int lu,
+	const EGLPNUM_TYPE bound)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (p->lp, indx, lu, bound);
+	CHECKRVALG (rval, CLEANUP);
+
+	free_cache (p);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+#if 0
+		/*
+		 * Bico - I removed this on 02.04.22.  I don't think we need to support
+		 * this type of interface (the loading via arrays can do the job)
+		 */
+EGLPNUM_TYPENAME_QSLIB_INTERFACE QSbasis *QScreate_basis (
+	int nstruct,
+	int nrows)
+{
+	int rval = 0;
+	int i;
+	QSbasis *B = 0;
+
+	ILL_SAFE_MALLOC (B, 1, QSbasis);
+
+	B->nstruct = nstruct;
+	B->nrows = nrows;
+	B->cstat = 0;
+	B->rstat = 0;
+
+	if (nstruct)
+	{
+		ILL_SAFE_MALLOC (B->cstat, nstruct, char);
+	}
+
+	if (nrows)
+	{
+		ILL_SAFE_MALLOC (B->rstat, nrows, char);
+	}
+
+	for (i = 0; i < nstruct; i++)
+		B->cstat[i] = 0;
+	for (i = 0; i < nrows; i++)
+		B->rstat[i] = 0;
+
+CLEANUP:
+
+	if (rval)
+	{
+		EGLPNUM_TYPENAME_QSfree_basis (B);
+		B = 0;
+	}
+
+	return B;
+}
+#endif
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE QSbasis *EGLPNUM_TYPENAME_QSread_basis (
+	EGLPNUM_TYPENAME_QSdata * p,
+	const char *filename)
+{
+	int rval = 0;
+	QSbasis *qB = 0;
+	EGLPNUM_TYPENAME_ILLlp_basis B;
+
+	EGLPNUM_TYPENAME_ILLlp_basis_init (&B);
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	ILL_NEW (qB, QSbasis);
+	init_basis (qB);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_readbasis (p->lp, &B, filename);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = illbasis_to_qsbasis (&B, qB);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	if (rval && qB)
+	{
+		EGLPNUM_TYPENAME_QSfree_basis (qB);
+		qB = 0;
+	}
+	EGLPNUM_TYPENAME_ILLlp_basis_free (&B);
+
+	return qB;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSload_basis (
+	EGLPNUM_TYPENAME_QSdata * p,
+	QSbasis * B)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (B->nstruct != p->qslp->nstruct || B->nrows != p->qslp->nrows)
+	{
+		QSlog("size of basis does not match lp");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	if (p->basis == 0)
+	{
+		ILL_SAFE_MALLOC (p->basis, 1, EGLPNUM_TYPENAME_ILLlp_basis);
+		EGLPNUM_TYPENAME_ILLlp_basis_init (p->basis);
+	}
+	else
+	{
+		EGLPNUM_TYPENAME_ILLlp_basis_free (p->basis);
+	}
+
+	rval = qsbasis_to_illbasis (B, p->basis);
+	CHECKRVALG (rval, CLEANUP);
+
+	p->factorok = 0;
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSread_and_load_basis (
+	EGLPNUM_TYPENAME_QSdata * p,
+	const char *filename)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (p->basis == 0)
+	{
+		ILL_SAFE_MALLOC (p->basis, 1, EGLPNUM_TYPENAME_ILLlp_basis);
+		EGLPNUM_TYPENAME_ILLlp_basis_init (p->basis);
+	}
+	else
+	{
+		EGLPNUM_TYPENAME_ILLlp_basis_free (p->basis);
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLlib_readbasis (p->lp, p->basis, filename);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	return rval;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSload_basis_array (
+	EGLPNUM_TYPENAME_QSdata * p,
+	char *cstat,
+	char *rstat)
+{
+	int rval = 0;
+	int i;
+	EGLPNUM_TYPENAME_ILLlp_basis *B;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	qslp = p->qslp;
+
+	if (qslp->nstruct > 0 && cstat == 0)
+	{
+		QSlog("EGLPNUM_TYPENAME_QSload_basis_array called without cstat");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	if (qslp->nrows > 0 && rstat == 0)
+	{
+		QSlog("EGLPNUM_TYPENAME_QSload_basis_array called without rstat");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	if (p->basis == 0)
+	{
+		ILL_SAFE_MALLOC (p->basis, 1, EGLPNUM_TYPENAME_ILLlp_basis);
+		EGLPNUM_TYPENAME_ILLlp_basis_init (p->basis);
+	}
+	else
+	{
+		EGLPNUM_TYPENAME_ILLlp_basis_free (p->basis);
+	}
+
+	B = p->basis;
+
+	B->nstruct = qslp->nstruct;
+	B->nrows = qslp->nrows;
+	ILL_SAFE_MALLOC (B->cstat, qslp->nstruct, char);
+	ILL_SAFE_MALLOC (B->rstat, qslp->nrows, char);
+
+	for (i = 0; i < qslp->nstruct; i++)
+	{
+		B->cstat[i] = cstat[i];
+	}
+
+	for (i = 0; i < qslp->nrows; i++)
+	{
+		B->rstat[i] = rstat[i];
+	}
+
+	p->factorok = 0;
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSload_basis_and_row_norms_array (
+	EGLPNUM_TYPENAME_QSdata * p,
+	char *cstat,
+	char *rstat,
+	EGLPNUM_TYPE * rownorms)
+{
+	int rval = 0;
+	int i, nrows;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	nrows = p->qslp->nrows;
+
+	rval = EGLPNUM_TYPENAME_QSload_basis_array (p, cstat, rstat);
+	CHECKRVALG (rval, CLEANUP);
+	p->basis->rownorms = EGLPNUM_TYPENAME_EGlpNumAllocArray (nrows);
+
+	for (i = 0; i < nrows; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (p->basis->rownorms[i], rownorms[i]);
+	}
+
+	p->factorok = 0;
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSwrite_basis (
+	EGLPNUM_TYPENAME_QSdata * p,
+	QSbasis * B,
+	const char *filename)
+{
+	int rval = 0;
+	EGLPNUM_TYPENAME_ILLlp_basis iB, *basis = 0;
+
+	EGLPNUM_TYPENAME_ILLlp_basis_init (&iB);
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (B)
+	{
+		rval = qsbasis_to_illbasis (B, &iB);
+		CHECKRVALG (rval, CLEANUP);
+		basis = &iB;
+	}
+	else
+	{
+		if (p->basis == 0)
+		{
+			QSlog("no basis available in EGLPNUM_TYPENAME_QSwrite_basis");
+			rval = 1;
+			goto CLEANUP;
+		}
+		basis = p->basis;
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLlib_writebasis (p->lp, basis, filename);
+	CHECKRVALG (rval, CLEANUP);
+
+
+CLEANUP:
+
+	EGLPNUM_TYPENAME_ILLlp_basis_free (basis);
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE QSbasis *EGLPNUM_TYPENAME_QSget_basis (
+	EGLPNUM_TYPENAME_QSdata * p)
+{
+	int rval = 0;
+	QSbasis *B = 0;
+
+	if (p->basis == 0)
+	{
+		QSlog("no basis available in EGLPNUM_TYPENAME_QSget_basis");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	ILL_SAFE_MALLOC (B, 1, QSbasis);
+	init_basis (B);
+	rval = illbasis_to_qsbasis (p->basis, B);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	if (rval)
+	{
+		EGLPNUM_TYPENAME_QSfree_basis (B);
+		B = 0;
+	}
+
+	return B;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_basis_array (
+	EGLPNUM_TYPENAME_QSdata * p,
+	char *cstat,
+	char *rstat)
+{
+	int rval = 0;
+	int i;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (p->basis == 0)
+	{
+		QSlog("no basis available in EGLPNUM_TYPENAME_QSget_basis_array");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	for (i = 0; i < p->basis->nstruct; i++)
+		cstat[i] = p->basis->cstat[i];
+	for (i = 0; i < p->basis->nrows; i++)
+		rstat[i] = p->basis->rstat[i];
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_basis_and_row_norms_array (
+	EGLPNUM_TYPENAME_QSdata * p,
+	char *cstat,
+	char *rstat,
+	EGLPNUM_TYPE * rownorms)
+{
+	int rval = 0;
+	int i;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (p->basis == 0)
+	{
+		QSlog("no basis available");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	for (i = 0; i < p->basis->nstruct; i++)
+		cstat[i] = p->basis->cstat[i];
+	for (i = 0; i < p->basis->nrows; i++)
+		rstat[i] = p->basis->rstat[i];
+
+	if (p->basis->rownorms == 0)
+	{
+		QSlog("no row norms available");
+		rval = 1;
+		goto CLEANUP;
+	}
+	else
+	{
+		for (i = 0; i < p->basis->nrows; i++)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (rownorms[i], p->basis->rownorms[i]);
+		}
+	}
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+static int illbasis_to_qsbasis (
+	EGLPNUM_TYPENAME_ILLlp_basis * B,
+	QSbasis * qB)
+{
+	int rval = 0;
+	int i;
+
+	qB->nstruct = B->nstruct;
+	qB->nrows = B->nrows;
+	ILL_SAFE_MALLOC (qB->cstat, B->nstruct, char);
+	ILL_SAFE_MALLOC (qB->rstat, B->nrows, char);
+
+	for (i = 0; i < B->nstruct; i++)
+	{
+		qB->cstat[i] = B->cstat[i];
+	}
+
+	for (i = 0; i < B->nrows; i++)
+	{
+		qB->rstat[i] = B->rstat[i];
+	}
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+static int qsbasis_to_illbasis (
+	QSbasis * qB,
+	EGLPNUM_TYPENAME_ILLlp_basis * B)
+{
+	int rval = 0;
+	int i;
+	int nbas = 0;
+
+	B->nstruct = qB->nstruct;
+	B->nrows = qB->nrows;
+	ILL_SAFE_MALLOC (B->cstat, qB->nstruct, char);
+	ILL_SAFE_MALLOC (B->rstat, qB->nrows, char);
+
+	for (i = 0; i < qB->nstruct; i++)
+	{
+		if(qB->cstat[i] == QS_COL_BSTAT_BASIC) nbas++;
+		B->cstat[i] = qB->cstat[i];
+	}
+
+	for (i = 0; i < qB->nrows; i++)
+	{
+		if(qB->rstat[i] == QS_ROW_BSTAT_BASIC) nbas++;
+		B->rstat[i] = qB->rstat[i];
+	}
+
+	if(nbas != qB->nrows)
+	{
+		QSlog("Received basis is not valid, in qsbasis_to_illbasis");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+int grab_basis (
+	EGLPNUM_TYPENAME_QSdata * p)
+{
+	int rval = 0;
+	EGLPNUM_TYPENAME_ILLlp_basis *B = p->basis;
+	int nstruct = p->qslp->nstruct;
+	int nrows = p->qslp->nrows;
+
+	if (!B)
+	{
+		ILL_SAFE_MALLOC (p->basis, 1, EGLPNUM_TYPENAME_ILLlp_basis);
+		EGLPNUM_TYPENAME_ILLlp_basis_init (p->basis);
+		B = p->basis;
+	}
+
+	if (nstruct != B->nstruct)
+	{
+		ILL_IFFREE (B->cstat, char);
+		ILL_SAFE_MALLOC (B->cstat, nstruct, char);
+
+		B->nstruct = nstruct;
+	}
+
+	if (nrows != B->nrows)
+	{
+		ILL_IFFREE (B->rstat, char);
+		ILL_SAFE_MALLOC (B->rstat, nrows, char);
+
+		B->nrows = nrows;
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLlib_getbasis (p->lp, B->cstat, B->rstat);
+	CHECKRVALG (rval, CLEANUP);
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (B->rownorms);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (B->colnorms);
+
+	if (p->pricing->dII_price == QS_PRICE_DSTEEP)
+	{
+		B->rownorms = EGLPNUM_TYPENAME_EGlpNumAllocArray (nrows);
+		rval = EGLPNUM_TYPENAME_ILLlib_getrownorms (p->lp, p->pricing, B->rownorms);
+		if (rval)
+		{
+/*
+            QSlog("no edge norms, continue anyway");
+*/
+			EGLPNUM_TYPENAME_EGlpNumFreeArray (B->rownorms);
+			rval = 0;
+		}
+	}
+
+CLEANUP:
+
+	if (rval)
+	{
+		if (B)
+		{
+			EGLPNUM_TYPENAME_ILLlp_basis_free (B);
+			ILL_IFFREE (p->basis, EGLPNUM_TYPENAME_ILLlp_basis);
+		}
+	}
+
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_QSgrab_cache (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int status)
+{
+	int rval = 0;
+	EGLPNUM_TYPENAME_ILLlp_cache *C = p->cache;
+	int nstruct = p->qslp->nstruct;
+	int nrows = p->qslp->nrows;
+	#if 0
+	/* we may need to fix basic status for fixed variables */
+	register int i;
+	char *const cstat = p->basis->cstat;
+	const int *const structmap = p->lp->O->structmap;
+	const int sense = p->lp->O->objsense;
+	const int *const vtype = p->lp->vtype;
+	int *const vstat = p->lp->vstat;
+	/* end extra variables needed */
+	#endif
+
+	if (C == 0)
+	{
+		ILL_SAFE_MALLOC (p->cache, 1, EGLPNUM_TYPENAME_ILLlp_cache);
+		EGLPNUM_TYPENAME_EGlpNumInitVar (p->cache->val);
+		EGLPNUM_TYPENAME_ILLlp_cache_init (p->cache);
+		C = p->cache;
+	}
+
+	if (nstruct != C->nstruct || nrows != C->nrows)
+	{
+		EGLPNUM_TYPENAME_ILLlp_cache_free (C);
+		rval = EGLPNUM_TYPENAME_ILLlp_cache_alloc (C, nstruct, nrows);
+		CHECKRVALG (rval, CLEANUP);
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLlib_cache_solution (p->lp, C);
+	CHECKRVALG (rval, CLEANUP);
+
+	#if 0
+	/* we fix basis status and vstat */
+	for( i = nstruct ; i-- ; )
+	{
+		if(vtype[structmap[i]] != VFIXED) continue;
+		if(cstat[i] == QS_COL_BSTAT_BASIC) continue;
+		if(( sense > 0 && EGLPNUM_TYPENAME_EGlpNumIsLess(EGLPNUM_TYPENAME_SZERO_TOLER,C->rc[i])) ||
+			 ( sense < 0 && !EGLPNUM_TYPENAME_EGlpNumIsLess(EGLPNUM_TYPENAME_SZERO_TOLER,C->rc[i])))
+		{
+			vstat[structmap[i]] = STAT_LOWER;
+			cstat[i] = QS_COL_BSTAT_LOWER;
+		}
+		else
+		{
+			vstat[structmap[i]] = STAT_UPPER;
+			cstat[i] = QS_COL_BSTAT_UPPER;
+		}
+	}/* end fix */
+	#endif
+	C->status = status;
+
+CLEANUP:
+
+	if (rval)
+	{
+		if (C)
+		{
+			EGLPNUM_TYPENAME_ILLlp_cache_free (C);
+			EGLPNUM_TYPENAME_EGlpNumClearVar (p->cache->val);
+			ILL_IFFREE (p->cache, EGLPNUM_TYPENAME_ILLlp_cache);
+		}
+	}
+
+	EG_RETURN (rval);
+}
+
+void free_cache (
+	EGLPNUM_TYPENAME_QSdata * p)
+{
+	if (p->cache)
+	{
+		EGLPNUM_TYPENAME_ILLlp_cache_free (p->cache);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (p->cache->val);
+		ILL_IFFREE (p->cache, EGLPNUM_TYPENAME_ILLlp_cache);
+	}
+	p->qstatus = QS_LP_MODIFIED;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_binv_row (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int indx,
+	EGLPNUM_TYPE * binvrow)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if(!p->basis)
+	{
+		QSlog("no active basis in store");
+		rval = 1;
+		goto CLEANUP;
+	}
+	if(0>indx || indx >= EGLPNUM_TYPENAME_QSget_rowcount(p))
+	{
+		QSlog("row index %d outside valid bounds [%d:%d]",
+								indx, 0, EGLPNUM_TYPENAME_QSget_rowcount(p)-1);
+		rval = 1;
+		goto CLEANUP;
+	}
+	if (p->cache == 0)
+	{
+		QSlog("LP has not been optimized in EGLPNUM_TYPENAME_QSget_binv_row");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLlib_tableau (p->lp, indx, binvrow, 0);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_tableau_row (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int indx,
+	EGLPNUM_TYPE * tableaurow)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (p->cache == 0)
+	{
+		QSlog("LP has not been optimized in EGLPNUM_TYPENAME_QSget_tableau_row");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLlib_tableau (p->lp, indx, 0, tableaurow);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_basis_order (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int *basorder)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (p->cache == 0)
+	{
+		QSlog("LP has not been optimized in EGLPNUM_TYPENAME_QSget_basis_order");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLlib_basis_order (p->lp, basorder);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QScompute_row_norms (
+	EGLPNUM_TYPENAME_QSdata * p)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (p->pricing->dII_price != QS_PRICE_DSTEEP)
+	{
+		QSlog("not using dual steepest edge");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLlib_recompute_rownorms (p->lp, p->pricing);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = grab_basis (p);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSfree_prob (
+	EGLPNUM_TYPENAME_QSdata * p)
+{
+	if (p)
+	{
+		EGLPNUM_TYPENAME_EGlpNumClearVar(p->uobjlim);
+		EGLPNUM_TYPENAME_EGlpNumClearVar(p->lobjlim);
+		if (p->qslp)
+		{
+			EGLPNUM_TYPENAME_ILLlpdata_free (p->qslp);
+			ILL_IFFREE (p->qslp, EGLPNUM_TYPENAME_ILLlpdata);
+		}
+		if (p->lp)
+		{
+			EGLPNUM_TYPENAME_ILLsimplex_free_lpinfo (p->lp);
+			EGLPNUM_TYPENAME_EGlpNumClearVar (p->lp->objval);
+			EGLPNUM_TYPENAME_EGlpNumClearVar (p->lp->pobjval);
+			EGLPNUM_TYPENAME_EGlpNumClearVar (p->lp->dobjval);
+			EGLPNUM_TYPENAME_EGlpNumClearVar (p->lp->pinfeas);
+			EGLPNUM_TYPENAME_EGlpNumClearVar (p->lp->dinfeas);
+			EGLPNUM_TYPENAME_EGlpNumClearVar (p->lp->objbound);
+			EGLPNUM_TYPENAME_EGlpNumClearVar (p->lp->upd.piv);
+			EGLPNUM_TYPENAME_EGlpNumClearVar (p->lp->upd.dty);
+			EGLPNUM_TYPENAME_EGlpNumClearVar (p->lp->upd.c_obj);
+			EGLPNUM_TYPENAME_EGlpNumClearVar (p->lp->upd.tz);
+			ILL_IFFREE (p->lp, EGLPNUM_TYPENAME_lpinfo);
+		}
+		if (p->basis)
+		{
+			EGLPNUM_TYPENAME_ILLlp_basis_free (p->basis);
+			ILL_IFFREE (p->basis, EGLPNUM_TYPENAME_ILLlp_basis);
+		}
+		if (p->cache)
+		{
+			EGLPNUM_TYPENAME_ILLlp_cache_free (p->cache);
+			EGLPNUM_TYPENAME_EGlpNumClearVar (p->cache->val);
+			ILL_IFFREE (p->cache, EGLPNUM_TYPENAME_ILLlp_cache);
+		}
+		if (p->pricing)
+		{
+			EGLPNUM_TYPENAME_EGlpNumClearVar (p->pricing->htrigger);
+			EGLPNUM_TYPENAME_ILLprice_free_pricing_info (p->pricing);
+			ILL_IFFREE (p->pricing, EGLPNUM_TYPENAME_price_info);
+		}
+		ILL_IFFREE (p->name, char);
+
+		ILL_IFFREE (p, EGLPNUM_TYPENAME_QSdata);
+	}
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSfree_basis (
+	QSbasis * B)
+{
+	if (B)
+	{
+		ILL_IFFREE (B->rstat, char);
+		ILL_IFFREE (B->cstat, char);
+
+		ILL_IFFREE (B, QSbasis);
+	}
+}
+
+static void init_basis (
+	QSbasis * B)
+{
+	if (B)
+	{
+		B->nstruct = 0;
+		B->nrows = 0;
+		B->cstat = 0;
+		B->rstat = 0;
+	}
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_status (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int *status)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (status)
+		*status = p->qstatus;
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_solution (
+	EGLPNUM_TYPENAME_QSdata * p,
+	EGLPNUM_TYPE * value,
+	EGLPNUM_TYPE * x,
+	EGLPNUM_TYPE * pi,
+	EGLPNUM_TYPE * slack,
+	EGLPNUM_TYPE * rc)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (p->cache == 0)
+	{
+		QSlog("no solution available in EGLPNUM_TYPENAME_QSget_solution");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLlib_solution (p->lp, p->cache, value, x, pi, slack, rc);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_objval (
+	EGLPNUM_TYPENAME_QSdata * p,
+	EGLPNUM_TYPE * value)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+/* Want to get objval after limited number of pivots. */
+
+	if (p->qstatus == QS_LP_MODIFIED)
+	{
+		QSlog("QSmsg: LP has been modified since last solve.");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLlib_objval (p->lp, p->cache, value);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_x_array (
+	EGLPNUM_TYPENAME_QSdata * p,
+	EGLPNUM_TYPE * x)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (p->cache == 0)
+	{
+		QSlog("no solution available in EGLPNUM_TYPENAME_QSget_x_array");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLlib_get_x (p->lp, p->cache, x);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_slack_array (
+	EGLPNUM_TYPENAME_QSdata * p,
+	EGLPNUM_TYPE * slack)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (p->cache == 0)
+	{
+		QSlog("no solution available in EGLPNUM_TYPENAME_QSget_slack_array");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLlib_get_slack (p->lp, p->cache, slack);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_rc_array (
+	EGLPNUM_TYPENAME_QSdata * p,
+	EGLPNUM_TYPE * rc)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (p->cache == 0)
+	{
+		QSlog("no solution available in EGLPNUM_TYPENAME_QSget_rc_array");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLlib_solution (p->lp, p->cache, 0, 0, 0, 0, rc);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_pi_array (
+	EGLPNUM_TYPENAME_QSdata * p,
+	EGLPNUM_TYPE * pi)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (p->cache == 0)
+	{
+		QSlog("no solution available in EGLPNUM_TYPENAME_QSget_pi_array");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLlib_solution (p->lp, p->cache, 0, 0, pi, 0, 0);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_infeas_array (
+	EGLPNUM_TYPENAME_QSdata * p,
+	EGLPNUM_TYPE * pi)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (pi == 0)
+	{
+		ILL_ERROR (rval, "QS_get_infeas_array called with NULL pi vector\n");
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLsimplex_infcertificate (p->lp, pi);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_named_x (
+	EGLPNUM_TYPENAME_QSdata * p,
+	const char *colname,
+	EGLPNUM_TYPE * val)
+{
+	int rval = 0;
+	int j;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (p->cache == 0)
+	{
+		QSlog("no solution available in EGLPNUM_TYPENAME_QSget_named_x");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	rval = EGLPNUM_TYPENAME_QSget_column_index (p, colname, &j);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (j != -1)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (*val, p->cache->x[j]);
+	}
+	else
+	{
+		rval = 1;
+	}
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_named_rc (
+	EGLPNUM_TYPENAME_QSdata * p,
+	const char *colname,
+	EGLPNUM_TYPE * val)
+{
+	int rval = 0;
+	int j;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (p->cache == 0)
+	{
+		QSlog("no solution available in EGLPNUM_TYPENAME_QSget_named_rc");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	rval = EGLPNUM_TYPENAME_QSget_column_index (p, colname, &j);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (j != -1)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (*val, p->cache->rc[j]);
+	}
+	else
+	{
+		rval = 1;
+	}
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_named_pi (
+	EGLPNUM_TYPENAME_QSdata * p,
+	const char *rowname,
+	EGLPNUM_TYPE * val)
+{
+	int rval = 0;
+	int i;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (p->cache == 0)
+	{
+		QSlog("no solution available in EGLPNUM_TYPENAME_QSget_named_pi");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	rval = EGLPNUM_TYPENAME_QSget_row_index (p, rowname, &i);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (i != -1)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (*val, p->cache->pi[i]);
+	}
+	else
+	{
+		rval = 1;
+	}
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_named_slack (
+	EGLPNUM_TYPENAME_QSdata * p,
+	const char *rowname,
+	EGLPNUM_TYPE * val)
+{
+	int rval = 0;
+	int i;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (p->cache == 0)
+	{
+		QSlog("no solution available in EGLPNUM_TYPENAME_QSget_named_slack");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	rval = EGLPNUM_TYPENAME_QSget_row_index (p, rowname, &i);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (i != -1)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (*val, p->cache->slack[i]);
+	}
+	else
+	{
+		rval = 1;
+	}
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_colcount (
+	EGLPNUM_TYPENAME_QSdata * p)
+{
+	int cnt;
+
+	if (check_qsdata_pointer (p))
+		cnt = 0;
+	else
+		cnt = p->qslp->nstruct;
+
+	return cnt;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_rowcount (
+	EGLPNUM_TYPENAME_QSdata * p)
+{
+	int cnt;
+
+	if (check_qsdata_pointer (p))
+		cnt = 0;
+	else
+		cnt = p->qslp->nrows;
+
+	return cnt;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_nzcount (
+	EGLPNUM_TYPENAME_QSdata * p)
+{
+	int cnt;
+
+	if (check_qsdata_pointer (p))
+		cnt = 0;
+	else
+		cnt = p->qslp->nzcount - p->qslp->nrows;
+
+	return cnt;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QStest_row_norms (
+	EGLPNUM_TYPENAME_QSdata * p)
+{
+	int yesno;
+
+	if (check_qsdata_pointer (p))
+	{
+		yesno = 0;
+	}
+	else
+	{
+		if (p->basis && p->basis->rownorms)
+		{
+			yesno = 1;
+		}
+		else
+		{
+			yesno = 0;
+		}
+	}
+
+	return yesno;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_obj_list(EGLPNUM_TYPENAME_QSprob p,
+	int num,
+	int*collist,
+	EGLPNUM_TYPE*obj)
+{
+	int rval = 0;
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+	rval = EGLPNUM_TYPENAME_ILLlib_getobj_list (p->lp, num, collist, obj);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_obj (
+	EGLPNUM_TYPENAME_QSdata * p,
+	EGLPNUM_TYPE * obj)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_getobj (p->lp, obj);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_rhs (
+	EGLPNUM_TYPENAME_QSdata * p,
+	EGLPNUM_TYPE * rhs)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_getrhs (p->lp, rhs);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_ranged_rows_list (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int num,
+	int *rowlist,
+	int **rowcnt,
+	int **rowbeg,
+	int **rowind,
+	EGLPNUM_TYPE ** rowval,
+	EGLPNUM_TYPE ** rhs,
+	char **sense,
+	EGLPNUM_TYPE ** range,
+	char ***names)
+{
+	int rval = 0;
+	int i, nrows;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	nrows = EGLPNUM_TYPENAME_QSget_rowcount (p);
+	for (i = 0; i < num; i++)
+	{
+		if (rowlist[i] < 0 || rowlist[i] >= nrows)
+		{
+			QSlog("entry %d in rowlist out of range", i);
+			rval = 1;
+			goto CLEANUP;
+		}
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLlib_getrows (p->lp, num, rowlist, rowcnt, rowbeg, rowind,
+												 rowval, rhs, sense, range, names);
+	CHECKRVALG (rval, CLEANUP);
+
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_ranged_rows (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int **rowcnt,
+	int **rowbeg,
+	int **rowind,
+	EGLPNUM_TYPE ** rowval,
+	EGLPNUM_TYPE ** rhs,
+	char **sense,
+	EGLPNUM_TYPE ** range,
+	char ***names)
+{
+	int rval = 0;
+	int i, nrows;
+	int *rowlist = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	nrows = EGLPNUM_TYPENAME_QSget_rowcount (p);
+	if (nrows > 0)
+	{
+		ILL_SAFE_MALLOC (rowlist, nrows, int);
+
+		for (i = 0; i < nrows; i++)
+		{
+			rowlist[i] = i;
+		}
+		rval = EGLPNUM_TYPENAME_ILLlib_getrows (p->lp, nrows, rowlist, rowcnt, rowbeg, rowind,
+													 rowval, rhs, sense, range, names);
+		CHECKRVALG (rval, CLEANUP);
+	}
+
+CLEANUP:
+
+	ILL_IFFREE (rowlist, int);
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_senses (
+	EGLPNUM_TYPENAME_QSdata *p,
+	char *senses)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_getsenses (p->lp, senses);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_rows_list (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int num,
+	int *rowlist,
+	int **rowcnt,
+	int **rowbeg,
+	int **rowind,
+	EGLPNUM_TYPE ** rowval,
+	EGLPNUM_TYPE ** rhs,
+	char **sense,
+	char ***names)
+{
+	int rval = 0;
+	int i, nrows;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	nrows = EGLPNUM_TYPENAME_QSget_rowcount (p);
+	for (i = 0; i < num; i++)
+	{
+		if (rowlist[i] < 0 || rowlist[i] >= nrows)
+		{
+			QSlog("entry %d in rowlist out of range", i);
+			rval = 1;
+			goto CLEANUP;
+		}
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLlib_getrows (p->lp, num, rowlist, rowcnt, rowbeg, rowind,
+												 rowval, rhs, sense, 0, names);
+	CHECKRVALG (rval, CLEANUP);
+
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_rows (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int **rowcnt,
+	int **rowbeg,
+	int **rowind,
+	EGLPNUM_TYPE ** rowval,
+	EGLPNUM_TYPE ** rhs,
+	char **sense,
+	char ***names)
+{
+	int rval = 0;
+	int i, nrows;
+	int *rowlist = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	nrows = EGLPNUM_TYPENAME_QSget_rowcount (p);
+	if (nrows > 0)
+	{
+		ILL_SAFE_MALLOC (rowlist, nrows, int);
+
+		for (i = 0; i < nrows; i++)
+		{
+			rowlist[i] = i;
+		}
+		rval = EGLPNUM_TYPENAME_ILLlib_getrows (p->lp, nrows, rowlist, rowcnt, rowbeg, rowind,
+													 rowval, rhs, sense, 0, names);
+		CHECKRVALG (rval, CLEANUP);
+	}
+
+CLEANUP:
+
+	ILL_IFFREE (rowlist, int);
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_columns_list (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int num,
+	int *collist,
+	int **colcnt,
+	int **colbeg,
+	int **colind,
+	EGLPNUM_TYPE ** colval,
+	EGLPNUM_TYPE ** obj,
+	EGLPNUM_TYPE ** lower,
+	EGLPNUM_TYPE ** upper,
+	char ***names)
+{
+	int rval = 0;
+	int j, ncols;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	ncols = EGLPNUM_TYPENAME_QSget_colcount (p);
+	for (j = 0; j < num; j++)
+	{
+		if (collist[j] < 0 || collist[j] >= ncols)
+		{
+			QSlog("entry %d in collist out of range", j);
+			rval = 1;
+			goto CLEANUP;
+		}
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLlib_getcols (p->lp, num, collist, colcnt, colbeg, colind,
+												 colval, obj, lower, upper, names);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_columns (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int **colcnt,
+	int **colbeg,
+	int **colind,
+	EGLPNUM_TYPE ** colval,
+	EGLPNUM_TYPE ** obj,
+	EGLPNUM_TYPE ** lower,
+	EGLPNUM_TYPE ** upper,
+	char ***names)
+{
+	int rval = 0;
+	int j, ncols;
+	int *collist = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	ncols = EGLPNUM_TYPENAME_QSget_colcount (p);
+	if (ncols > 0)
+	{
+		ILL_SAFE_MALLOC (collist, ncols, int);
+
+		for (j = 0; j < ncols; j++)
+		{
+			collist[j] = j;
+		}
+		rval = EGLPNUM_TYPENAME_ILLlib_getcols (p->lp, ncols, collist, colcnt, colbeg, colind,
+													 colval, obj, lower, upper, names);
+		CHECKRVALG (rval, CLEANUP);
+	}
+
+CLEANUP:
+
+	ILL_IFFREE (collist, int);
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE char *EGLPNUM_TYPENAME_QSget_probname (
+	EGLPNUM_TYPENAME_QSdata * p)
+{
+	int rval = 0;
+	char *name = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	ILL_UTIL_STR (name, p->name);
+
+CLEANUP:
+	ILL_RETURN_PTR (name, "EGLPNUM_TYPENAME_QSget_probname");
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE char *EGLPNUM_TYPENAME_QSget_objname (
+	EGLPNUM_TYPENAME_QSdata * p)
+{
+	int rval = 0;
+	char *name = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (p->qslp->objname != 0)
+	{
+		ILL_UTIL_STR (name, p->qslp->objname);
+	}
+
+CLEANUP:
+	ILL_RETURN_PTR (name, "EGLPNUM_TYPENAME_QSget_objname");
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_rownames (
+	EGLPNUM_TYPENAME_QSdata * p,
+	char **rownames)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_rownames (p->lp, rownames);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_colnames (
+	EGLPNUM_TYPENAME_QSdata * p,
+	char **colnames)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_colnames (p->lp, colnames);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_bound (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int colindex,
+	int lu,
+	EGLPNUM_TYPE * bound)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_getbnd (p->lp, colindex, lu, bound);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_bounds_list(
+	EGLPNUM_TYPENAME_QSdata* p,
+	int num,
+	int*collist,
+	EGLPNUM_TYPE*lb,
+	EGLPNUM_TYPE*ub)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_getbnds_list (p->lp, num, collist, lb, ub);
+	CHECKRVALG (rval, CLEANUP);
+	
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_bounds (
+	EGLPNUM_TYPENAME_QSdata * p,
+	EGLPNUM_TYPE * lower,
+	EGLPNUM_TYPE * upper)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_getbnds (p->lp, lower, upper);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_intflags (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int *intflags)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (intflags == 0)
+	{
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLlib_getintflags (p->lp, intflags);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_intcount (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int *count)
+{
+	int j, ncols, cnt = 0, rval = 0;
+	int *intflags = 0;
+
+	*count = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	ncols = EGLPNUM_TYPENAME_QSget_colcount (p);
+
+	if (ncols > 0)
+	{
+		ILL_SAFE_MALLOC (intflags, ncols, int);
+
+		rval = EGLPNUM_TYPENAME_ILLlib_getintflags (p->lp, intflags);
+		CHECKRVALG (rval, CLEANUP);
+
+		for (j = 0; j < ncols; j++)
+		{
+			if (intflags[j] > 0)
+				cnt++;
+		}
+	}
+
+CLEANUP:
+
+	*count = cnt;
+	ILL_IFFREE (intflags, int);
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_column_index (
+	EGLPNUM_TYPENAME_QSdata * p,
+	const char *name,
+	int *colindex)
+{
+	int rval = 0;
+
+	*colindex = -1;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_colindex (p->lp, name, colindex);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_row_index (
+	EGLPNUM_TYPENAME_QSdata * p,
+	const char *name,
+	int *rowindex)
+{
+	int rval = 0;
+
+	*rowindex = -1;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	rval = EGLPNUM_TYPENAME_ILLlib_rowindex (p->lp, name, rowindex);
+	CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+static int QSwrite_prob_EGioFile(
+		EGLPNUM_TYPENAME_QSdata*p,
+		EGioFile_t*out,
+		const char*filetype)
+{
+    int rval = 0; 
+    qsstring_reporter rep; 
+
+    ILLstring_reporter_copy(&rep, &p->qslp->reporter); 
+    ILLstring_reporter_init(&p->qslp->reporter, 
+                            (qsreport_string_fct) EGioWrite, out); 
+    rval = EGLPNUM_TYPENAME_QSreport_prob(p, filetype, NULL);
+    ILLstring_reporter_copy(&p->qslp->reporter, &rep); 
+    ILL_RESULT(rval, "QSwrite_prob_EGioFile");
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSwrite_prob (
+	EGLPNUM_TYPENAME_QSdata * p,
+	const char *filename,
+	const char *filetype)
+{
+	EGioFile_t *file = NULL;
+	int rval = 0;
+
+	if (filename == NULL)
+	{
+		file = EGioOpenFILE(stdout);
+	}
+	else
+	{
+		if ((file = EGioOpen (filename, "w")) == 0)
+		{
+			QSlog("Unable to open \"%s\" for output: %s.", filename,
+									strerror(errno));
+		}
+	}
+	ILL_CHECKnull (file, NULL);
+	rval = QSwrite_prob_EGioFile (p, file, filetype);
+	if (file)
+	{
+		EGioClose (file);
+	}
+CLEANUP:
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSwrite_prob_file (
+	EGLPNUM_TYPENAME_QSdata * p,
+	FILE * out,
+	const char *filetype)
+{
+	int rval = 0;
+	EGioFile_t*lout = EGioOpenFILE(out);
+	rval = QSwrite_prob_EGioFile(p,lout,filetype);
+	CHECKRVALG(rval,CLEANUP);
+	CLEANUP:
+	free(lout);
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSfree (
+	void *ptr)
+{
+	ILL_IFFREE (ptr, void);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSset_param (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int whichparam,
+	int newvalue)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	switch (whichparam)
+	{
+	case QS_PARAM_PRIMAL_PRICING:
+		if (newvalue == QS_PRICE_PDANTZIG ||
+				newvalue == QS_PRICE_PDEVEX ||
+				newvalue == QS_PRICE_PSTEEP || newvalue == QS_PRICE_PMULTPARTIAL)
+		{
+			p->pricing->pI_price = newvalue;
+			p->pricing->pII_price = newvalue;
+		}
+		else
+		{
+			QSlog("illegal value for QS_PARAM_PRIMAL_PRICING");
+			rval = 1;
+			goto CLEANUP;
+		}
+		break;
+	case QS_PARAM_DUAL_PRICING:
+		if (newvalue == QS_PRICE_DDANTZIG ||
+				newvalue == QS_PRICE_DSTEEP ||
+				newvalue == QS_PRICE_DMULTPARTIAL || newvalue == QS_PRICE_DDEVEX)
+		{
+			p->pricing->dI_price = newvalue;
+			p->pricing->dII_price = newvalue;
+		}
+		else
+		{
+			QSlog("illegal value for QS_PARAM_DUAL_PRICING");
+			rval = 1;
+			goto CLEANUP;
+		}
+		break;
+	case QS_PARAM_SIMPLEX_DISPLAY:
+		if (newvalue == 0 || (newvalue > 0 && newvalue < 4))
+		{
+			p->simplex_display = newvalue;
+		}
+		else
+		{
+			QSlog("illegal value for QS_PARAM_SIMPLEX_DISPLAY");
+			rval = 1;
+			goto CLEANUP;
+		}
+		break;
+	case QS_PARAM_SIMPLEX_MAX_ITERATIONS:
+		if (newvalue > 0)
+		{
+			p->lp->maxiter = newvalue;
+		}
+		else
+		{
+			QSlog("illegal value for QS_PARAM_SIMPLEX_MAX_ITERATIONS");
+			rval = 1;
+			goto CLEANUP;
+		}
+		break;
+	case QS_PARAM_SIMPLEX_SCALING:
+		if (newvalue == 0 || newvalue == 1)
+		{
+			p->simplex_scaling = newvalue;
+		}
+		else
+		{
+			QSlog("illegal value for QS_PARAM_SIMPLEX_SCALING");
+			rval = 1;
+			goto CLEANUP;
+		}
+		break;
+	default:
+		QSlog("unknown parameter: %d", whichparam);
+		rval = 1;
+		goto CLEANUP;
+	}
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSset_param_EGlpNum (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int whichparam,
+	EGLPNUM_TYPE newvalue)
+{
+	int rval = 0;
+	int sense;
+	EGLPNUM_TYPE lvar;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar(lvar);
+	EGLPNUM_TYPENAME_EGlpNumCopy(lvar,newvalue);
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	switch (whichparam)
+	{
+	case QS_PARAM_SIMPLEX_MAX_TIME:
+		if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (lvar))
+		{
+			p->lp->maxtime = EGLPNUM_TYPENAME_EGlpNumToLf (lvar);
+		}
+		else
+		{
+			QSlog("illegal value for QS_PARAM_SIMPLEX_MAX_TIME");
+			rval = 1;
+			goto CLEANUP;
+		}
+		break;
+	case QS_PARAM_OBJULIM:
+		EGLPNUM_TYPENAME_QSget_objsense(p,&sense);
+		if(EGLPNUM_TYPENAME_EGlpNumIsLeq(EGLPNUM_TYPENAME_ILL_MAXDOUBLE,lvar)) EGLPNUM_TYPENAME_EGlpNumCopy(lvar,EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+		EGLPNUM_TYPENAME_EGlpNumCopy(p->uobjlim,lvar);
+		if(sense == QS_MIN) EGLPNUM_TYPENAME_ILLsimplex_set_bound(p->lp,(const EGLPNUM_TYPE*)(&lvar), sense);
+		break;
+	case QS_PARAM_OBJLLIM:
+		EGLPNUM_TYPENAME_QSget_objsense(p,&sense);
+		if(EGLPNUM_TYPENAME_EGlpNumIsLeq(newvalue,EGLPNUM_TYPENAME_ILL_MINDOUBLE)) EGLPNUM_TYPENAME_EGlpNumCopy(lvar,EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+		EGLPNUM_TYPENAME_EGlpNumCopy(p->lobjlim,lvar);
+		if(sense == QS_MAX) EGLPNUM_TYPENAME_ILLsimplex_set_bound(p->lp,(const EGLPNUM_TYPE*)(&lvar), sense);
+		break;
+	default:
+		QSlog("unknown parameter: %d", whichparam);
+		rval = 1;
+		goto CLEANUP;
+	}
+
+CLEANUP:
+
+	EGLPNUM_TYPENAME_EGlpNumClearVar(lvar);
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_param (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int whichparam,
+	int *value)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (!value)
+	{
+		QSlog("EGLPNUM_TYPENAME_QSget_param call without a value pointer");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	switch (whichparam)
+	{
+	case QS_PARAM_PRIMAL_PRICING:
+		*value = p->pricing->pII_price;
+		break;
+	case QS_PARAM_DUAL_PRICING:
+		*value = p->pricing->dII_price;
+		break;
+	case QS_PARAM_SIMPLEX_DISPLAY:
+		*value = p->simplex_display;
+		break;
+	case QS_PARAM_SIMPLEX_MAX_ITERATIONS:
+		*value = p->lp->maxiter;
+		break;
+	case QS_PARAM_SIMPLEX_SCALING:
+		*value = p->simplex_scaling;
+		break;
+	default:
+		QSlog("unknown parameter: %d", whichparam);
+		rval = 1;
+		goto CLEANUP;
+	}
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_param_EGlpNum (
+	EGLPNUM_TYPENAME_QSdata * p,
+	int whichparam,
+	EGLPNUM_TYPE * value)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (p);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (!value)
+	{
+		QSlog("QSget_param_double call without a value pointer");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	switch (whichparam)
+	{
+	case QS_PARAM_SIMPLEX_MAX_TIME:
+		EGLPNUM_TYPENAME_EGlpNumSet (*value, p->lp->maxtime);
+		break;
+	case QS_PARAM_OBJULIM:
+		EGLPNUM_TYPENAME_EGlpNumCopy(*value,p->uobjlim);
+		break;
+	case QS_PARAM_OBJLLIM:
+		EGLPNUM_TYPENAME_EGlpNumCopy(*value,p->lobjlim);
+		break;
+	default:
+		QSlog("unknown parameter: %d", whichparam);
+		rval = 1;
+		goto CLEANUP;
+	}
+
+CLEANUP:
+
+	EG_RETURN (rval);
+}
+
+static int check_qsdata_pointer (
+	EGLPNUM_TYPENAME_QSdata * p)
+{
+	if (p == NULL)
+	{
+		QSlog("NULL EGLPNUM_TYPENAME_QSprob pointer");
+		return 1;
+	}
+	else
+	{
+		return 0;
+	}
+}
+
+static int formatIsMps (
+	const char *filetype,
+	int *isMps)
+{
+	int rval = 0;
+
+	if (!strcasecmp (filetype, "MPS"))
+	{
+		*isMps = 1;
+	}
+	else if (!strcasecmp (filetype, "LP"))
+	{
+		*isMps = 0;
+	}
+	else
+	{
+		QSlog("Unknown prob-file type: %s", filetype);
+		rval = 1;
+		ILL_CLEANUP;
+	}
+CLEANUP:
+	return rval;
+}
+
+
+/****************************************************************************/
+/* 
+ * undocumentyed functions 
+ */
+
+static void check_pointer (
+	void *p,
+	const char *fct,
+	const char *param)
+{
+	if (p == NULL)
+		QSlog("NULL %s argument to %s", param, fct);
+}
+
+/* EGLPNUM_TYPENAME_QSline_reader: 
+ *    used by mps/lp reader to get input lines 
+ *    by default input is read froma FILE* via fgets 
+ */
+EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSline_reader EGLPNUM_TYPENAME_QSline_reader_new (
+	void *fct,
+	void *data_src)
+{
+	check_pointer (fct, "EGLPNUM_TYPENAME_QSline_reader_new", "fct");
+	check_pointer (data_src, "EGLPNUM_TYPENAME_QSline_reader_new", "data_src");
+	return EGLPNUM_TYPENAME_ILLline_reader_new ((EGLPNUM_TYPENAME_qsread_line_fct) fct, data_src);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSline_reader_set_error_collector (
+	EGLPNUM_TYPENAME_QSline_reader reader,
+	EGLPNUM_TYPENAME_QSerror_collector collector)
+{
+	check_pointer (reader, "EGLPNUM_TYPENAME_QSline_reader_set_error_collector", "reader");
+	check_pointer (collector, "EGLPNUM_TYPENAME_QSline_reader_set_error_collector", "collector");
+	reader->error_collector = collector;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSline_reader_free (
+	EGLPNUM_TYPENAME_QSline_reader reader)
+{
+	EGLPNUM_TYPENAME_ILLline_reader_free (reader);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE char *EGLPNUM_TYPENAME_QSline_reader_get (
+	EGLPNUM_TYPENAME_QSline_reader reader,
+	char *s,
+	int size)
+{
+	check_pointer (reader, "EGLPNUM_TYPENAME_QSline_reader_get", "reader");
+	check_pointer (s, "EGLPNUM_TYPENAME_QSline_reader_get", "s");
+	return EGLPNUM_TYPENAME_ILLline_reader_get (s, size, reader);
+}
+
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSerror_collector EGLPNUM_TYPENAME_QSerror_collector_new (
+	void *fct,
+	void *dest)
+{
+	check_pointer (fct, "EGLPNUM_TYPENAME_QSerror_collector_new", "fct");
+	return EGLPNUM_TYPENAME_ILLerror_collector_new ((EGLPNUM_TYPENAME_qsadd_error_fct) fct, dest);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE
+	EGLPNUM_TYPENAME_QSerror_collector EGLPNUM_TYPENAME_QSerror_memory_collector_new (EGLPNUM_TYPENAME_QSerror_memory mem)
+{
+	check_pointer (mem, "EGLPNUM_TYPENAME_QSerror_memory_collector_new", "mem");
+	return EGLPNUM_TYPENAME_ILLerror_memory_collector_new (mem);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSerror_collector_free (
+	EGLPNUM_TYPENAME_QSerror_collector c)
+{
+	EGLPNUM_TYPENAME_ILLerror_collector_free (c);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSdata *EGLPNUM_TYPENAME_QSget_prob (
+	EGLPNUM_TYPENAME_QSline_reader reader,
+	const char *probname,
+	const char *filetype)
+{
+	int isMps, rval = 0;
+	EGLPNUM_TYPENAME_QSdata *p = 0;
+
+	if ((filetype != NULL) && !strcasecmp (filetype, "MPS"))
+	{
+		isMps = 1;
+	}
+	else if ((filetype != NULL) && !strcasecmp (filetype, "LP"))
+	{
+		isMps = 0;
+	}
+	else
+	{
+		QSlog("Unknown prob-file type: %s",
+								(filetype != NULL) ? filetype : "NULL");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	p = EGLPNUM_TYPENAME_ILLread (reader, probname, isMps);
+	ILL_CHECKnull (p, NULL);
+
+	ILL_FAILfalse (p->qslp != NULL, "If there's a p there must be a p-qslp");
+	ILL_IFFREE (p->name, char);
+
+	ILL_UTIL_STR (p->name, p->qslp->probname);
+	EGLPNUM_TYPENAME_ILLsimplex_load_lpinfo (p->qslp, p->lp);
+
+CLEANUP:
+
+	if (rval != 0)
+	{
+		EGLPNUM_TYPENAME_QSfree_prob (p);
+		p = 0;
+	}
+	return p;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSreport_prob (
+	EGLPNUM_TYPENAME_QSdata * p,
+	const char *filetype,
+	EGLPNUM_TYPENAME_qserror_collector * c)
+{
+	int isMps, rval = 0;
+
+	rval = formatIsMps (filetype, &isMps);
+	CHECKRVALG (rval, CLEANUP);
+	if (isMps)
+	{
+		rval = EGLPNUM_TYPENAME_ILLwrite_mps (p->qslp, c);
+	}
+	else
+	{
+		rval = EGLPNUM_TYPENAME_ILLwrite_lp (p->qslp, c);
+	}
+CLEANUP:
+	EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE char *EGLPNUM_TYPENAME_QSversion (
+	void)
+{
+	char *name = 0;
+	name = EGsMalloc (char, 256);
+
+	snprintf (name, (size_t) 255, "%s (build %s-%s)",PACKAGE_STRING, __DATE__,
+						__TIME__);
+	return name;
+}
+
+/* QSstring_reporter: 
+ *    used by solver code to report feedback 
+ *    by default feedback is sent to logging
+ */
+EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSset_reporter (
+	EGLPNUM_TYPENAME_QSprob prob,
+	int skip,
+	void *fct,
+	void *dest)
+{
+	int rval = 0;
+
+	rval = check_qsdata_pointer (prob);
+	if (rval != 0)
+		return;
+
+	check_pointer (fct, "EGLPNUM_TYPENAME_QSset_reporter", "fct");
+
+	ILL_FAILtrue (prob->lp == NULL, "EGLPNUM_TYPENAME_QSprob internal error: prob->lp == NULL");
+	ILLstring_reporter_init (&prob->qslp->reporter,
+													 (qsreport_string_fct) fct, dest);
+
+	prob->lp->iterskip = skip;
+CLEANUP:
+	return;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE const char *EGLPNUM_TYPENAME_QSformat_error_type_string (
+	int tp)
+{
+	const char *type = "Error";
+
+	if (tp == QS_DATA_ERROR)
+	{
+		type = "Data Error";
+	}
+	if (tp == QS_DATA_WARN)
+	{
+		type = "Data Warning";
+	}
+	if (tp == QS_MPS_FORMAT_ERROR)
+	{
+		type = "MPS Error";
+	}
+	if (tp == QS_MPS_FORMAT_WARN)
+	{
+		type = "MPS Warning";
+	}
+	if (tp == QS_LP_FORMAT_ERROR)
+	{
+		type = "LP Error";
+	}
+	if (tp == QS_LP_FORMAT_WARN)
+	{
+		type = "LP Warning";
+	}
+	return type;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSerror_get_type (
+	EGLPNUM_TYPENAME_QSformat_error error)
+{
+	check_pointer (error, "EGLPNUM_TYPENAME_QSerror_get_type", "error");
+	return error->type;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE const char *EGLPNUM_TYPENAME_QSerror_get_desc (
+	EGLPNUM_TYPENAME_QSformat_error error)
+{
+	check_pointer (error, "EGLPNUM_TYPENAME_QSerror_get_desc", "error");
+	return error->desc;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSerror_get_line_number (
+	EGLPNUM_TYPENAME_QSformat_error error)
+{
+	check_pointer (error, "EGLPNUM_TYPENAME_QSerror_get_line_number", "error");
+	return error->lineNumber;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSerror_get_pos (
+	EGLPNUM_TYPENAME_QSformat_error error)
+{
+	check_pointer (error, "EGLPNUM_TYPENAME_QSerror_get_pos", "error");
+	return error->at;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE const char *EGLPNUM_TYPENAME_QSerror_get_line (
+	EGLPNUM_TYPENAME_QSformat_error error)
+{
+	check_pointer (error, "EGLPNUM_TYPENAME_QSerror_get_line", "error");
+	return error->theLine;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSerror_print (
+	FILE * f,
+	EGLPNUM_TYPENAME_QSformat_error error)
+{
+	check_pointer (f, "EGLPNUM_TYPENAME_QSerror_print", "f");
+	if (error == NULL)
+	{
+		QSlog("0");
+	}
+	else
+	{
+		EGioFile_t*out = EGioOpenFILE(f);
+		EGLPNUM_TYPENAME_ILLformat_error_print (out, error);
+		EGioClose(out);
+	}
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSerror_memory EGLPNUM_TYPENAME_QSerror_memory_create (
+	int takeErrorLines)
+{
+	return EGLPNUM_TYPENAME_ILLerror_memory_create (takeErrorLines);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSerror_memory_free (
+	EGLPNUM_TYPENAME_QSerror_memory mem)
+{
+	if (mem != NULL)
+	{
+		EGLPNUM_TYPENAME_ILLerror_memory_free (mem);
+	}
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSerror_memory_get_nerrors (
+	EGLPNUM_TYPENAME_QSerror_memory mem)
+{
+	check_pointer (mem, "EGLPNUM_TYPENAME_QSerror_memory_get_nerrors", "mem");
+	return mem->nerror;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSerror_memory_get_nof (
+	EGLPNUM_TYPENAME_QSerror_memory mem,
+	int type)
+{
+	check_pointer (mem, "EGLPNUM_TYPENAME_QSerror_memory_get_nerrors", "mem");
+	if (0 <= type && type < QS_INPUT_NERROR)
+	{
+		return mem->has_error[type];
+	}
+	else
+	{
+		ILL_REPRT ("bad error type");
+		return 0;
+	}
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSformat_error EGLPNUM_TYPENAME_QSerror_memory_get_last_error (
+	EGLPNUM_TYPENAME_QSerror_memory mem)
+{
+	check_pointer (mem, "QSerror_memory_get_last_errors", "mem");
+	return mem->error_list;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSformat_error EGLPNUM_TYPENAME_QSerror_memory_get_prev_error (
+	EGLPNUM_TYPENAME_QSformat_error e)
+{
+	check_pointer (e, "QSerror_memory_get_prev_errors", "e");
+	if (e != NULL)
+		e = e->next;
+	return e;
+}
diff --git a/qsopt_ex/qsopt.h b/qsopt_ex/qsopt.h
new file mode 100644
index 0000000..bd4ec7b
--- /dev/null
+++ b/qsopt_ex/qsopt.h
@@ -0,0 +1,358 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/*  $RCSfile: qsopt_EGLPNUM_TYPENAME.h,v $ $Revision: 1.3 $ $Date: 2003/11/05 16:57:39 $" */
+#ifndef EGLPNUM_TYPENAME___QS_QSOPT_H
+#define EGLPNUM_TYPENAME___QS_QSOPT_H
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <gmp.h>
+
+#ifdef WIN32
+
+#ifdef QSLIB_EXPORTS
+#define EGLPNUM_TYPENAME_QSLIB_INTERFACE __declspec(dllexport)
+#else
+#define EGLPNUM_TYPENAME_QSLIB_INTERFACE __declspec(dllimport)
+#endif
+
+#else
+#define EGLPNUM_TYPENAME_QSLIB_INTERFACE extern
+#endif
+
+#ifdef WIN32
+typedef struct EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_qsdata *EGLPNUM_TYPENAME_QSprob;
+typedef struct EGLPNUM_TYPENAME_QSLIB_INTERFACE qsbasis *EGLPNUM_TYPENAME_QSbas;
+#else
+typedef struct EGLPNUM_TYPENAME_qsdata *EGLPNUM_TYPENAME_QSprob;
+typedef struct qsbasis *EGLPNUM_TYPENAME_QSbas;
+#endif
+
+/****************************************************************************/
+/*                                                                          */
+/*                 PARAMETERS TO SPECIFY OBJECTIVE SENSE                    */
+/*                                                                          */
+/****************************************************************************/
+#include "basicdefs.h"
+/*
+#define QS_LP_PRIMAL_FEASIBLE   11
+#define QS_LP_PRIMAL_INFEASIBLE 12
+#define QS_LP_PRIMAL_UNBOUNDED  13
+#define QS_LP_DUAL_FEASIBLE     14
+#define QS_LP_DUAL_INFEASIBLE   15
+#define QS_LP_DUAL_UNBOUNDED    16
+*/
+
+/****************************************************************************/
+/*                                                                          */
+/*                      QSopt Library Functions                             */
+/*                                                                          */
+/****************************************************************************/
+#ifdef  __cplusplus
+extern "C"
+{
+#endif
+
+#ifdef WIN32
+/* 
+ *  in WINDOWS we make 
+ *     EGLPNUM_TYPENAME_solver_main/EGLPNUM_TYPENAME_reader_main part of DLL
+ */
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_solver_main ( int argc, char **argv);
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_reader_main ( int argc, char **argv);
+#endif
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSfree ( void *ptr),
+		EGLPNUM_TYPENAME_QSfree_prob ( EGLPNUM_TYPENAME_QSprob p),
+		EGLPNUM_TYPENAME_QSfree_basis ( EGLPNUM_TYPENAME_QSbas B),
+	  EGLPNUM_TYPENAME_QSset_precision ( const unsigned prec),/**< set the precision for floating 
+																								 point numbers to the given 
+																								 number of bits */
+		EGLPNUM_TYPENAME_QSstart ( void),/**< whe we use non native numbers, we need to make 
+												 some initializations before operating with the
+												 library */
+	  EGLPNUM_TYPENAME_QSend ( void);	/**< just to free any internal static data needed by
+												 the variable precision numbers */
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSopt_primal ( EGLPNUM_TYPENAME_QSprob p, int *status),
+		EGLPNUM_TYPENAME_QSopt_dual ( EGLPNUM_TYPENAME_QSprob p, int *status),
+		EGLPNUM_TYPENAME_QSopt_pivotin_col ( EGLPNUM_TYPENAME_QSprob p, int ccnt, int *clist),
+		EGLPNUM_TYPENAME_QSopt_pivotin_row ( EGLPNUM_TYPENAME_QSprob p, int rcnt, int *rlist),
+		EGLPNUM_TYPENAME_QSopt_strongbranch ( EGLPNUM_TYPENAME_QSprob p, int ncand, int *candidatelist,
+			EGLPNUM_TYPE * xlist, EGLPNUM_TYPE * down_vals, EGLPNUM_TYPE * up_vals,
+			int iterations, EGLPNUM_TYPE objbound),
+		EGLPNUM_TYPENAME_QSchange_objsense ( EGLPNUM_TYPENAME_QSprob p, int newsense),
+		EGLPNUM_TYPENAME_QSget_objsense ( EGLPNUM_TYPENAME_QSprob p, int *newsense),
+		EGLPNUM_TYPENAME_QSnew_col ( EGLPNUM_TYPENAME_QSprob p,const EGLPNUM_TYPE obj,const EGLPNUM_TYPE lower,const EGLPNUM_TYPE upper,
+			const char *name),
+		EGLPNUM_TYPENAME_QSadd_cols ( EGLPNUM_TYPENAME_QSprob p, int num, int *cmatcnt, int *cmatbeg, int *cmatind,
+			EGLPNUM_TYPE * cmatval, EGLPNUM_TYPE * obj, EGLPNUM_TYPE * lower,
+			EGLPNUM_TYPE * upper, const char **names),
+		EGLPNUM_TYPENAME_QSadd_col ( EGLPNUM_TYPENAME_QSprob p, int cnt, int *cmatind, EGLPNUM_TYPE * cmatval,
+			EGLPNUM_TYPE obj, EGLPNUM_TYPE lower, EGLPNUM_TYPE upper, const char *name),
+		EGLPNUM_TYPENAME_QSnew_row ( EGLPNUM_TYPENAME_QSprob p,const EGLPNUM_TYPE rhs, int sense, const char *name),
+		EGLPNUM_TYPENAME_QSadd_ranged_rows ( EGLPNUM_TYPENAME_QSprob p, int num, int *rmatcnt, int *rmatbeg, 
+			int *rmatind,const EGLPNUM_TYPE * rmatval,const EGLPNUM_TYPE * rhs, char *sense,
+			const EGLPNUM_TYPE* range, const char **names),
+		EGLPNUM_TYPENAME_QSadd_ranged_row ( EGLPNUM_TYPENAME_QSprob p, int cnt, int *rmatind,const EGLPNUM_TYPE * rmatval,
+			const EGLPNUM_TYPE * rhs, int sense,const EGLPNUM_TYPE * range, const char *name),
+		EGLPNUM_TYPENAME_QSadd_rows ( EGLPNUM_TYPENAME_QSprob p, int num, int *rmatcnt, int *rmatbeg, int *rmatind,
+			const EGLPNUM_TYPE * rmatval,const EGLPNUM_TYPE * rhs, char *sense, const char **names),
+		EGLPNUM_TYPENAME_QSadd_row ( EGLPNUM_TYPENAME_QSprob p, int cnt, int *rmatind,const EGLPNUM_TYPE * rmatval,
+			const EGLPNUM_TYPE * rhs, int sense, const char *name),
+		EGLPNUM_TYPENAME_QSdelete_rows ( EGLPNUM_TYPENAME_QSprob p, int num, int *dellist),
+		EGLPNUM_TYPENAME_QSdelete_row ( EGLPNUM_TYPENAME_QSprob p, int rowindex),
+		EGLPNUM_TYPENAME_QSdelete_setrows ( EGLPNUM_TYPENAME_QSprob p, int *flags),
+		EGLPNUM_TYPENAME_QSdelete_named_row ( EGLPNUM_TYPENAME_QSprob p, const char *rowname),
+		EGLPNUM_TYPENAME_QSdelete_named_rows_list ( EGLPNUM_TYPENAME_QSprob p, int num, const char **rownames),
+		EGLPNUM_TYPENAME_QSdelete_cols ( EGLPNUM_TYPENAME_QSprob p, int num, int *dellist),
+		EGLPNUM_TYPENAME_QSdelete_col ( EGLPNUM_TYPENAME_QSprob p, int colindex),
+		EGLPNUM_TYPENAME_QSdelete_setcols ( EGLPNUM_TYPENAME_QSprob p, int *flags),
+		EGLPNUM_TYPENAME_QSdelete_named_column ( EGLPNUM_TYPENAME_QSprob p, const char *colname),
+		EGLPNUM_TYPENAME_QSdelete_named_columns_list ( EGLPNUM_TYPENAME_QSprob p, int num, const char **colnames),
+		EGLPNUM_TYPENAME_QSchange_senses ( EGLPNUM_TYPENAME_QSprob p, int num, int *rowlist, char *sense),
+		EGLPNUM_TYPENAME_QSchange_sense ( EGLPNUM_TYPENAME_QSprob p, int rowindex, int sense),
+		EGLPNUM_TYPENAME_QSchange_coef ( EGLPNUM_TYPENAME_QSprob p, int rowindex, int colindex, EGLPNUM_TYPE coef),
+		EGLPNUM_TYPENAME_QSchange_objcoef ( EGLPNUM_TYPENAME_QSprob p, int indx, EGLPNUM_TYPE coef),
+		EGLPNUM_TYPENAME_QSchange_rhscoef ( EGLPNUM_TYPENAME_QSprob p, int indx, EGLPNUM_TYPE coef),
+		EGLPNUM_TYPENAME_QSchange_range(EGLPNUM_TYPENAME_QSprob p, int rowindex, EGLPNUM_TYPE range),
+		EGLPNUM_TYPENAME_QSchange_bounds ( EGLPNUM_TYPENAME_QSprob p, int num, int *collist, char *lu, 
+			const EGLPNUM_TYPE * bounds),
+		EGLPNUM_TYPENAME_QSchange_bound ( EGLPNUM_TYPENAME_QSprob p, int indx, int lu,const EGLPNUM_TYPE bound),
+		EGLPNUM_TYPENAME_QSload_basis ( EGLPNUM_TYPENAME_QSprob p, EGLPNUM_TYPENAME_QSbas B),
+		EGLPNUM_TYPENAME_QSread_and_load_basis ( EGLPNUM_TYPENAME_QSprob p, const char *filename),
+		EGLPNUM_TYPENAME_QSload_basis_array ( EGLPNUM_TYPENAME_QSprob p, char *cstat, char *rstat),
+		EGLPNUM_TYPENAME_QSload_basis_and_row_norms_array ( EGLPNUM_TYPENAME_QSprob p, char *cstat, char *rstat, 
+			EGLPNUM_TYPE * rownorms),
+		EGLPNUM_TYPENAME_QSget_basis_array ( EGLPNUM_TYPENAME_QSprob p, char *cstat, char *rstat),
+		EGLPNUM_TYPENAME_QSget_basis_and_row_norms_array ( EGLPNUM_TYPENAME_QSprob p, char *cstat, char *rstat,
+			EGLPNUM_TYPE * rownorms),
+		EGLPNUM_TYPENAME_QSget_binv_row ( EGLPNUM_TYPENAME_QSprob p, int indx, EGLPNUM_TYPE * binvrow),
+		EGLPNUM_TYPENAME_QSget_tableau_row ( EGLPNUM_TYPENAME_QSprob p, int indx, EGLPNUM_TYPE * tableaurow),
+		EGLPNUM_TYPENAME_QSget_basis_order ( EGLPNUM_TYPENAME_QSprob p, int *basorder), 
+    EGLPNUM_TYPENAME_QSget_coef (EGLPNUM_TYPENAME_QSprob p, int rowindex, int colindex, EGLPNUM_TYPE*coef),
+		EGLPNUM_TYPENAME_QSget_status ( EGLPNUM_TYPENAME_QSprob p, int *status),
+		EGLPNUM_TYPENAME_QSget_solution ( EGLPNUM_TYPENAME_QSprob p, EGLPNUM_TYPE * value, EGLPNUM_TYPE * x,
+			EGLPNUM_TYPE * pi, EGLPNUM_TYPE * slack, EGLPNUM_TYPE * rc),
+		EGLPNUM_TYPENAME_QSget_objval ( EGLPNUM_TYPENAME_QSprob p, EGLPNUM_TYPE * value),
+		EGLPNUM_TYPENAME_QSget_pi_array ( EGLPNUM_TYPENAME_QSprob p, EGLPNUM_TYPE * pi),
+		EGLPNUM_TYPENAME_QSget_rc_array ( EGLPNUM_TYPENAME_QSprob p, EGLPNUM_TYPE * rc),
+		EGLPNUM_TYPENAME_QSget_x_array ( EGLPNUM_TYPENAME_QSprob p, EGLPNUM_TYPE * x),
+		EGLPNUM_TYPENAME_QSget_slack_array ( EGLPNUM_TYPENAME_QSprob p, EGLPNUM_TYPE * slack),
+		EGLPNUM_TYPENAME_QSget_infeas_array ( EGLPNUM_TYPENAME_QSprob p, EGLPNUM_TYPE * pi),
+		EGLPNUM_TYPENAME_QSget_colcount ( EGLPNUM_TYPENAME_QSprob p),
+		EGLPNUM_TYPENAME_QSget_rowcount ( EGLPNUM_TYPENAME_QSprob p),
+		EGLPNUM_TYPENAME_QSget_nzcount ( EGLPNUM_TYPENAME_QSprob p),
+		EGLPNUM_TYPENAME_QSget_obj_list(EGLPNUM_TYPENAME_QSprob p, int num, int*collist, EGLPNUM_TYPE*obj),
+		EGLPNUM_TYPENAME_QSget_obj ( EGLPNUM_TYPENAME_QSprob p, EGLPNUM_TYPE * obj),
+		EGLPNUM_TYPENAME_QSget_rhs ( EGLPNUM_TYPENAME_QSprob p, EGLPNUM_TYPE * rhs),
+		EGLPNUM_TYPENAME_QSget_ranged_rows_list ( EGLPNUM_TYPENAME_QSprob p, int num, int *rowlist, int **rowcnt,
+			int **rowbeg, int **rowind, EGLPNUM_TYPE ** rowval, EGLPNUM_TYPE ** rhs,
+			char **sense, EGLPNUM_TYPE **range, char ***names),
+		EGLPNUM_TYPENAME_QSget_ranged_rows ( EGLPNUM_TYPENAME_QSprob p, int **rowcnt, int **rowbeg, int **rowind,
+			EGLPNUM_TYPE ** rowval, EGLPNUM_TYPE ** rhs, char **sense, 
+			EGLPNUM_TYPE ** range, char ***names),
+		EGLPNUM_TYPENAME_QSget_senses ( EGLPNUM_TYPENAME_QSprob p, char*senses),
+		EGLPNUM_TYPENAME_QSget_rows_list ( EGLPNUM_TYPENAME_QSprob p, int num, int *rowlist, int **rowcnt,
+			int **rowbeg, int **rowind, EGLPNUM_TYPE ** rowval, EGLPNUM_TYPE ** rhs,
+			char **sense, char ***names),
+		EGLPNUM_TYPENAME_QSget_rows ( EGLPNUM_TYPENAME_QSprob p, int **rowcnt, int **rowbeg, int **rowind,
+			EGLPNUM_TYPE ** rowval, EGLPNUM_TYPE ** rhs, char **sense, char ***names),
+	  EGLPNUM_TYPENAME_QSget_columns_list ( EGLPNUM_TYPENAME_QSprob p, int num, int *collist, int **colcnt,
+			int **colbeg, int **colind, EGLPNUM_TYPE ** colval, EGLPNUM_TYPE ** obj,
+			EGLPNUM_TYPE ** lower, EGLPNUM_TYPE ** upper, char ***names),
+		EGLPNUM_TYPENAME_QSget_columns ( EGLPNUM_TYPENAME_QSprob p, int **colcnt, int **colbeg, int **colind,
+			EGLPNUM_TYPE ** colval, EGLPNUM_TYPE ** obj, EGLPNUM_TYPE ** lower,
+			EGLPNUM_TYPE ** upper, char ***names),
+		EGLPNUM_TYPENAME_QSget_rownames ( EGLPNUM_TYPENAME_QSprob p, char **rownames),
+		EGLPNUM_TYPENAME_QSget_colnames ( EGLPNUM_TYPENAME_QSprob p, char **colnames),
+		EGLPNUM_TYPENAME_QSget_bound ( EGLPNUM_TYPENAME_QSprob p, int colindex, int lu, EGLPNUM_TYPE * bound),
+		EGLPNUM_TYPENAME_QSget_bounds ( EGLPNUM_TYPENAME_QSprob p, EGLPNUM_TYPE * lower, EGLPNUM_TYPE * upper),
+		EGLPNUM_TYPENAME_QSget_bounds_list(EGLPNUM_TYPENAME_QSprob p, int num, int*collist, EGLPNUM_TYPE*lb,
+			EGLPNUM_TYPE*ub),
+		EGLPNUM_TYPENAME_QSget_intflags ( EGLPNUM_TYPENAME_QSprob p, int *intflags),
+		EGLPNUM_TYPENAME_QSget_intcount ( EGLPNUM_TYPENAME_QSprob p, int *count),
+		EGLPNUM_TYPENAME_QSget_column_index ( EGLPNUM_TYPENAME_QSprob p, const char *name, int *colindex),
+		EGLPNUM_TYPENAME_QSget_row_index ( EGLPNUM_TYPENAME_QSprob p, const char *name, int *rowindex),
+		EGLPNUM_TYPENAME_QSget_named_x ( EGLPNUM_TYPENAME_QSprob p, const char *colname, EGLPNUM_TYPE * val),
+		EGLPNUM_TYPENAME_QSget_named_rc ( EGLPNUM_TYPENAME_QSprob p, const char *colname, EGLPNUM_TYPE * val),
+		EGLPNUM_TYPENAME_QSget_named_pi ( EGLPNUM_TYPENAME_QSprob p, const char *rowname, EGLPNUM_TYPE * val),
+		EGLPNUM_TYPENAME_QSget_named_slack ( EGLPNUM_TYPENAME_QSprob p, const char *rowname, EGLPNUM_TYPE * val),
+		EGLPNUM_TYPENAME_QScompute_row_norms ( EGLPNUM_TYPENAME_QSprob p),
+		EGLPNUM_TYPENAME_QSwrite_prob ( EGLPNUM_TYPENAME_QSprob p, const char *filename, const char *filetype),
+		EGLPNUM_TYPENAME_QSwrite_prob_file ( EGLPNUM_TYPENAME_QSprob p, FILE * file, const char *filetype),
+		EGLPNUM_TYPENAME_QSwrite_basis ( EGLPNUM_TYPENAME_QSprob p, EGLPNUM_TYPENAME_QSbas B, const char *filename),
+		EGLPNUM_TYPENAME_QStest_row_norms ( EGLPNUM_TYPENAME_QSprob p),
+		EGLPNUM_TYPENAME_QSget_itcnt(EGLPNUM_TYPENAME_QSprob p, int *pI_iter, int *pII_iter, int *dI_iter,
+			int *dII_iter, int *tot_iter),
+		EGLPNUM_TYPENAME_QSset_param ( EGLPNUM_TYPENAME_QSprob p, int whichparam, int newvalue),
+		EGLPNUM_TYPENAME_QSset_param_EGlpNum ( EGLPNUM_TYPENAME_QSprob p, int whichparam, EGLPNUM_TYPE newvalue),
+		EGLPNUM_TYPENAME_QSget_param ( EGLPNUM_TYPENAME_QSprob p, int whichparam, int *value),
+		EGLPNUM_TYPENAME_QSget_param_EGlpNum ( EGLPNUM_TYPENAME_QSprob p, int whichparam, EGLPNUM_TYPE * value); 
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE char *EGLPNUM_TYPENAME_QSget_probname ( EGLPNUM_TYPENAME_QSprob p);
+EGLPNUM_TYPENAME_QSLIB_INTERFACE char *EGLPNUM_TYPENAME_QSget_objname ( EGLPNUM_TYPENAME_QSprob p);
+EGLPNUM_TYPENAME_QSLIB_INTERFACE char *EGLPNUM_TYPENAME_QSversion ( void);
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSprob EGLPNUM_TYPENAME_QScreate_prob ( const char *name, int objsense),
+		EGLPNUM_TYPENAME_QSread_prob ( const char *filename, const char *filetype),
+		EGLPNUM_TYPENAME_QSload_prob ( const char *probname, int ncols, int nrows, int *cmatcnt,
+			int *cmatbeg, int *cmatind, EGLPNUM_TYPE * cmatval, int objsense,
+			EGLPNUM_TYPE * obj, EGLPNUM_TYPE * rhs, char *sense, EGLPNUM_TYPE * lower,
+			EGLPNUM_TYPE * upper, const char **colnames, const char **rownames),
+		EGLPNUM_TYPENAME_QScopy_prob ( EGLPNUM_TYPENAME_QSprob p, const char *newname);
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSbas EGLPNUM_TYPENAME_QSget_basis ( EGLPNUM_TYPENAME_QSprob p),
+		EGLPNUM_TYPENAME_QSread_basis ( EGLPNUM_TYPENAME_QSprob p, const char *filename);
+
+#ifdef  __cplusplus
+}
+#endif
+
+/****************************************************************************
+ *
+ * This is the undocumented part of the QSlib interface 
+ *
+ ****************************************************************************/
+/* 
+ * functions to facilitate line by line reading from other sources than 
+ * files from within MPS/LP parsers  
+ * 
+ * functions to facilitate the collection of error information instead of 
+ * having the parsers print messages to stderr
+ *                              by mps/lp format writers
+ * 
+ * a problem's reporter is used by the solver code to provide important 
+ * feedback/progress information
+ */
+
+#ifdef WIN32
+typedef struct EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_qsline_reader *EGLPNUM_TYPENAME_QSline_reader;
+typedef struct EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_qsformat_error *EGLPNUM_TYPENAME_QSformat_error;
+typedef struct EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_qserror_collector *EGLPNUM_TYPENAME_QSerror_collector;
+typedef struct EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_qserror_memory *EGLPNUM_TYPENAME_QSerror_memory;
+#else
+typedef struct EGLPNUM_TYPENAME_qsline_reader *EGLPNUM_TYPENAME_QSline_reader;
+typedef struct EGLPNUM_TYPENAME_qsformat_error *EGLPNUM_TYPENAME_QSformat_error;
+typedef struct EGLPNUM_TYPENAME_qserror_collector *EGLPNUM_TYPENAME_QSerror_collector;
+typedef struct EGLPNUM_TYPENAME_qserror_memory *EGLPNUM_TYPENAME_QSerror_memory;
+#endif
+
+#ifdef  __cplusplus
+extern "C"
+{
+#endif
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSgrab_cache (EGLPNUM_TYPENAME_QSprob p, int status);
+
+	EGLPNUM_TYPENAME_QSLIB_INTERFACE const char *EGLPNUM_TYPENAME_QSformat_error_type_string (
+	int tp);
+
+	EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSerror_get_type (
+	EGLPNUM_TYPENAME_QSformat_error error);
+	EGLPNUM_TYPENAME_QSLIB_INTERFACE const char *EGLPNUM_TYPENAME_QSerror_get_desc (
+	EGLPNUM_TYPENAME_QSformat_error error);
+	EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSerror_get_line_number (
+	EGLPNUM_TYPENAME_QSformat_error error);
+	EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSerror_get_pos (
+	EGLPNUM_TYPENAME_QSformat_error error);
+	EGLPNUM_TYPENAME_QSLIB_INTERFACE const char *EGLPNUM_TYPENAME_QSerror_get_line (
+	EGLPNUM_TYPENAME_QSformat_error error);
+	EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSerror_print (
+	FILE * f,
+	EGLPNUM_TYPENAME_QSformat_error error);
+
+	EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSerror_collector EGLPNUM_TYPENAME_QSerror_collector_new (
+	void *fct,
+	void *dest);
+	EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSerror_collector EGLPNUM_TYPENAME_QSerror_memory_collector_new (
+	EGLPNUM_TYPENAME_QSerror_memory mem);
+	EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSerror_collector_free (
+	EGLPNUM_TYPENAME_QSerror_collector c);
+
+/****************************************************************************
+ * line reader 
+ */
+	EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSline_reader EGLPNUM_TYPENAME_QSline_reader_new (
+	void *fct,
+	void *data_src);
+	/* reader->read_line_fct defaults to fgets */
+
+	EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSline_reader_free (
+	EGLPNUM_TYPENAME_QSline_reader reader);
+
+	EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSline_reader_set_error_collector (
+	EGLPNUM_TYPENAME_QSline_reader reader,
+	EGLPNUM_TYPENAME_QSerror_collector collector);
+
+	EGLPNUM_TYPENAME_QSLIB_INTERFACE char *EGLPNUM_TYPENAME_QSline_reader_get (
+	EGLPNUM_TYPENAME_QSline_reader reader,
+	char *s,
+	int size);
+
+	EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSprob EGLPNUM_TYPENAME_QSget_prob (
+	EGLPNUM_TYPENAME_QSline_reader reader,
+	const char *probname,
+	const char *filetype);
+	/* the MPS and LP parsers uses the fct from reader 
+	 * to get to next input line */
+
+
+/****************************************************************************
+ * error memory 
+ */
+	EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSerror_memory EGLPNUM_TYPENAME_QSerror_memory_create (
+	int takeErrorLines);
+	EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSerror_memory_free (
+	EGLPNUM_TYPENAME_QSerror_memory mem);
+
+	EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSerror_memory_get_nof (
+	EGLPNUM_TYPENAME_QSerror_memory mem,
+	int error_type);
+	EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSerror_memory_get_nerrors (
+	EGLPNUM_TYPENAME_QSerror_memory mem);
+
+	EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSformat_error EGLPNUM_TYPENAME_QSerror_memory_get_last_error (
+	EGLPNUM_TYPENAME_QSerror_memory mem);
+	EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSformat_error EGLPNUM_TYPENAME_QSerror_memory_get_prev_error (
+	EGLPNUM_TYPENAME_QSformat_error e);
+
+/**************************************************************************** 
+ * reporter for solver feedback 
+ */
+	EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSset_reporter (
+	EGLPNUM_TYPENAME_QSprob prob,
+	int iterskip,
+	void *fct,
+	void *dest);
+
+	EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSreport_prob (
+	EGLPNUM_TYPENAME_QSprob p,
+	const char *filetype,
+	EGLPNUM_TYPENAME_QSerror_collector c);
+
+#ifdef  __cplusplus
+}
+#endif
+#endif													/* EGLPNUM_TYPENAME___QS_QSOPT_H */
diff --git a/qsopt_ex/qstruct.h b/qsopt_ex/qstruct.h
new file mode 100644
index 0000000..21e83b7
--- /dev/null
+++ b/qsopt_ex/qstruct.h
@@ -0,0 +1,49 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/*  $RCSfile: qstruct_EGLPNUM_TYPENAME.h,v $ $Revision: 1.3 $ $Date: 2003/11/05 16:57:39 $" */
+#ifndef EGLPNUM_TYPENAME___QS_QSTRUCT_H
+#define EGLPNUM_TYPENAME___QS_QSTRUCT_H
+
+#include "basicdefs.h"
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+#include "eg_lpnum.h"
+
+typedef struct EGLPNUM_TYPENAME_qsdata
+{
+	struct EGLPNUM_TYPENAME_ILLlpdata *qslp;
+	struct EGLPNUM_TYPENAME_lpinfo *lp;
+	struct EGLPNUM_TYPENAME_price_info *pricing;
+	struct EGLPNUM_TYPENAME_ILLlp_basis *basis;
+	struct EGLPNUM_TYPENAME_ILLlp_cache *cache;
+	char *name;
+	int qstatus;									/* QS_LP_UNSOLVED or an opt status  */
+	int factorok;									/* set to 0 if factorization is old */
+	int simplex_display;					/* 0 off, 1 on */
+	int simplex_scaling;					/* 0 off, 1 on */
+	itcnt_t itcnt;
+	EGLPNUM_TYPE uobjlim;
+	EGLPNUM_TYPE lobjlim;
+}
+EGLPNUM_TYPENAME_QSdata;
+
+#endif /* EGLPNUM_TYPENAME___QS_QSTRUCT_H */
diff --git a/qsopt_ex/ratio.c b/qsopt_ex/ratio.c
new file mode 100644
index 0000000..5463cca
--- /dev/null
+++ b/qsopt_ex/ratio.c
@@ -0,0 +1,1297 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* "$RCSfile: ratio.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+static int TRACE = 0;
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "logging-private.h"
+
+#include "eg_lpnum.h"
+#include "eg_io.h"
+#include "except.h"
+#include "trace.h"
+
+#include "sortrus_EGLPNUM_TYPENAME.h"
+#include "stddefs.h"
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+#include "ratio_EGLPNUM_TYPENAME.h"
+#include "fct_EGLPNUM_TYPENAME.h"
+
+
+void EGLPNUM_TYPENAME_ILLratio_pI_test (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int eindex,
+	int dir,
+	EGLPNUM_TYPENAME_ratio_res * rs)
+{
+	int i = 0, k = 0;
+	int col, ecol;
+	int cbnd, indx = 0;
+	int tctr = 0;
+	int *perm = lp->upd.perm;
+	int *ix = lp->upd.ix;
+	EGLPNUM_TYPE *pivtol = &(lp->tol->pivot_tol);
+	EGLPNUM_TYPE *dftol = &(lp->tol->id_tol);
+
+	 /*HHH*/ EGLPNUM_TYPE * t = lp->upd.t;
+	EGLPNUM_TYPE t_i, delta, y_ij, rcost, nrcost, ntmp;
+	EGLPNUM_TYPE *x, *l, *u;
+
+	 /*HHH*/ EGLPNUM_TYPENAME_EGlpNumInitVar (t_i);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (delta);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (y_ij);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (rcost);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (nrcost);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (ntmp);
+	EGLPNUM_TYPENAME_EGlpNumZero (t_i);
+	EGLPNUM_TYPENAME_EGlpNumZero (y_ij);
+	EGLPNUM_TYPENAME_EGlpNumZero (delta);
+	rs->lindex = -1;
+	EGLPNUM_TYPENAME_EGlpNumZero (rs->tz);
+	EGLPNUM_TYPENAME_EGlpNumZero (rs->pivotval);
+	rs->ratio_stat = RATIO_FAILED;
+	rs->lvstat = -1;
+	ecol = lp->nbaz[eindex];
+	ILL_IFTRACE2 ("%s:%d:%d:%d:%d", __func__, eindex, dir, ecol,
+								(VBOUNDED == lp->vtype[ecol]));
+	if (lp->vtype[ecol] == VBOUNDED)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopyDiff (t[0], lp->uz[ecol], lp->lz[ecol]);
+		ix[0] = BBOUND;
+		ILL_IFTRACE2 (":%d[%d](%la,%la,%la)\n", ix[tctr], tctr,
+									EGLPNUM_TYPENAME_EGlpNumToLf (t[tctr]), EGLPNUM_TYPENAME_EGlpNumToLf (lp->uz[ecol]),
+									EGLPNUM_TYPENAME_EGlpNumToLf (lp->lz[ecol]));
+		tctr++;
+	}
+	ILL_IFTRACE2 (":%d", lp->yjz.nzcnt);
+	for (k = 0; k < lp->yjz.nzcnt; k++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (y_ij, lp->yjz.coef[k]);
+		if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (y_ij, *pivtol))
+			continue;
+
+		i = lp->yjz.indx[k];
+		x = &(lp->xbz[i]);
+		col = lp->baz[i];
+		l = &(lp->lz[col]);
+		u = &(lp->uz[col]);
+
+		if ((dir == VINCREASE && EGLPNUM_TYPENAME_EGlpNumIsGreatZero (y_ij)) ||
+				(dir == VDECREASE && EGLPNUM_TYPENAME_EGlpNumIsLessZero (y_ij)))
+		{
+			if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (y_ij))
+				EGLPNUM_TYPENAME_EGlpNumSign (y_ij);
+			ILL_IFTRACE2 (":%d", lp->bfeas[i]);
+			if (lp->bfeas[i] > 0)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (t[tctr], *x, *u, y_ij);
+				ix[tctr] = 10 * k + BATOUPPER;
+				ILL_IFTRACE2 (":%d[%d](%la)\n", ix[tctr], tctr, EGLPNUM_TYPENAME_EGlpNumToLf (t[tctr]));
+				tctr++;
+				if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*l, EGLPNUM_TYPENAME_NINFTY))
+				{
+					EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (t[tctr], *x, *l, y_ij);
+					ix[tctr] = 10 * k + BATOLOWER;
+					ILL_IFTRACE2 (":%d[%d](%la)\n", ix[tctr], tctr,
+												EGLPNUM_TYPENAME_EGlpNumToLf (t[tctr]));
+					tctr++;
+				}
+			}
+			else if (lp->bfeas[i] == 0)
+			{
+				if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*l, EGLPNUM_TYPENAME_NINFTY))
+				{
+					EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (t[tctr], *x, *l, y_ij);
+					ix[tctr] = 10 * k + BATOLOWER;
+					ILL_IFTRACE2 (":%d[%d](%la)\n", ix[tctr], tctr,
+												EGLPNUM_TYPENAME_EGlpNumToLf (t[tctr]));
+					tctr++;
+				}
+			}
+		}
+		else if ((dir == VINCREASE && EGLPNUM_TYPENAME_EGlpNumIsLessZero (y_ij)) ||
+						 (dir == VDECREASE && EGLPNUM_TYPENAME_EGlpNumIsGreatZero (y_ij)))
+		{
+			if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (y_ij))
+				EGLPNUM_TYPENAME_EGlpNumSign (y_ij);
+			ILL_IFTRACE2 (":%d", lp->bfeas[i]);
+			if (lp->bfeas[i] < 0)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (t[tctr], *l, *x, y_ij);
+				ix[tctr] = 10 * k + BBTOLOWER;
+				ILL_IFTRACE2 (":%d[%d](%la)\n", ix[tctr], tctr, EGLPNUM_TYPENAME_EGlpNumToLf (t[tctr]));
+				tctr++;
+				if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*u, EGLPNUM_TYPENAME_INFTY))
+				{
+					EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (t[tctr], *u, *x, y_ij);
+					ix[tctr] = 10 * k + BBTOUPPER;
+					ILL_IFTRACE2 (":%d[%d](%la)\n", ix[tctr], tctr,
+												EGLPNUM_TYPENAME_EGlpNumToLf (t[tctr]));
+					tctr++;
+				}
+			}
+			else if (lp->bfeas[i] == 0)
+			{
+				if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*u, EGLPNUM_TYPENAME_INFTY))
+				{
+					EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (t[tctr], *u, *x, y_ij);
+					ix[tctr] = 10 * k + BBTOUPPER;
+					ILL_IFTRACE2 (":%d[%d](%la)\n", ix[tctr], tctr,
+												EGLPNUM_TYPENAME_EGlpNumToLf (t[tctr]));
+					tctr++;
+				}
+			}
+		}
+	}
+	if (tctr == 0)
+	{
+		rs->ratio_stat = RATIO_FAILED;
+		ILL_CLEANUP;
+	}
+
+	for (i = 0; i < tctr; i++)
+		perm[i] = i;
+	EGLPNUM_TYPENAME_ILLutil_EGlpNum_perm_quicksort (perm, t, tctr);
+
+	EGLPNUM_TYPENAME_EGlpNumZero (lp->upd.c_obj);
+	EGLPNUM_TYPENAME_EGlpNumCopy (rcost, lp->pIdz[eindex]);
+	ILL_IFTRACE2 ("\n%s:%d:%lf", __func__, tctr, EGLPNUM_TYPENAME_EGlpNumToLf (rcost));
+	for (i = 0; i < tctr; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (t_i, t[perm[i]]);
+		EGLPNUM_TYPENAME_EGlpNumCopy (ntmp, t_i);
+		EGLPNUM_TYPENAME_EGlpNumSubTo (ntmp, delta);
+		EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (lp->upd.c_obj, ntmp, rcost);
+		EGLPNUM_TYPENAME_EGlpNumCopy (delta, t_i);
+		ILL_IFTRACE2 (":%d:%lf", perm[i], EGLPNUM_TYPENAME_EGlpNumToLf (delta));
+		 /*HHH*/ cbnd = ix[perm[i]] % 10;
+		if (cbnd != BBOUND)
+		{
+			k = ix[perm[i]] / 10;
+			EGLPNUM_TYPENAME_EGlpNumCopy (y_ij, lp->yjz.coef[k]);
+			indx = lp->yjz.indx[k];
+			ILL_IFTRACE2 (":%d", indx);
+		}
+
+		switch (cbnd)
+		{
+		case BBOUND:
+			rs->ratio_stat = RATIO_NOBCHANGE;
+			EGLPNUM_TYPENAME_EGlpNumCopy (rs->tz, t_i);
+			if (dir != VINCREASE)
+				EGLPNUM_TYPENAME_EGlpNumSign (rs->tz);
+			ILL_CLEANUP;
+
+		case BATOLOWER:
+		case BATOUPPER:
+			EGLPNUM_TYPENAME_EGlpNumAddTo (rcost, y_ij);
+			break;
+		case BBTOLOWER:
+		case BBTOUPPER:
+			EGLPNUM_TYPENAME_EGlpNumSubTo (rcost, y_ij);
+			break;
+		}
+		EGLPNUM_TYPENAME_EGlpNumCopyNeg (nrcost, rcost);
+		if ((dir == VINCREASE && EGLPNUM_TYPENAME_EGlpNumIsLeq (nrcost, *dftol)) ||
+				(dir == VDECREASE && EGLPNUM_TYPENAME_EGlpNumIsLeq (rcost, *dftol)))
+		{
+			/* change 5 to -1 if t_i > 0 is required below */
+			if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (t_i) && i > 5)
+			{
+				/* QSlog("pIhell %.5f %d", t_i, i); */
+				EGLPNUM_TYPENAME_EGlpNumDivUiTo (t_i, 2);
+				rs->ratio_stat = RATIO_NEGATIVE;
+				EGLPNUM_TYPENAME_EGlpNumZero (rs->tz);
+				ILL_CLEANUP;
+			}
+			rs->lindex = indx;
+			rs->ratio_stat = RATIO_BCHANGE;
+			if (cbnd == BATOLOWER || cbnd == BBTOLOWER)
+				rs->lvstat = STAT_LOWER;
+			else
+				rs->lvstat = STAT_UPPER;
+
+			EGLPNUM_TYPENAME_EGlpNumCopy (rs->pivotval, y_ij);
+			EGLPNUM_TYPENAME_EGlpNumCopy (rs->tz, t_i);
+			if (dir != VINCREASE)
+				EGLPNUM_TYPENAME_EGlpNumSign (rs->tz);
+			ILL_CLEANUP;
+		}
+	}
+
+CLEANUP:
+	EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_PIPIV, 0, rs->pivotval);
+	ILL_IFTRACE2 (":tctr %d:%d\n", tctr, rs->ratio_stat);
+	lp->upd.tctr = tctr;
+	lp->upd.i = i;
+	EGLPNUM_TYPENAME_EGlpNumCopy (lp->upd.tz, t_i);
+	EGLPNUM_TYPENAME_EGlpNumCopy (lp->upd.piv, rs->pivotval);
+	if (dir == VDECREASE)
+		EGLPNUM_TYPENAME_EGlpNumSign (lp->upd.c_obj);
+	if (rs->lindex != -1)
+		lp->upd.fs = lp->bfeas[rs->lindex];
+	EGLPNUM_TYPENAME_EGlpNumClearVar (t_i);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (delta);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (y_ij);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (rcost);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (nrcost);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+}
+
+void EGLPNUM_TYPENAME_ILLratio_pII_test (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int eindex,
+	int dir,
+	EGLPNUM_TYPENAME_ratio_res * rs)
+{
+	int i, k, indx, col, ecol;
+	EGLPNUM_TYPE *x, *l, *u, t_max, ayi_max, yi_max, ay_ij, y_ij, t_i, t_z;
+	EGLPNUM_TYPE *pivtol = &(lp->tol->pivot_tol);
+	EGLPNUM_TYPE *pftol = &(lp->tol->pfeas_tol);
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (y_ij);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (ay_ij);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (t_i);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (t_z);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (t_max);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (yi_max);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (ayi_max);
+	 /*HHH*/ rs->boundch = 0;
+	rs->lindex = -1;
+	EGLPNUM_TYPENAME_EGlpNumZero (rs->tz);
+	rs->ratio_stat = RATIO_FAILED;
+	rs->lvstat = -1;
+	EGLPNUM_TYPENAME_EGlpNumZero (rs->pivotval);
+	EGLPNUM_TYPENAME_EGlpNumZero (rs->lbound);
+	ecol = lp->nbaz[eindex];
+
+	for (k = 0, EGLPNUM_TYPENAME_EGlpNumCopy (t_max, EGLPNUM_TYPENAME_INFTY); k < lp->yjz.nzcnt; k++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (y_ij, lp->yjz.coef[k]);
+		EGLPNUM_TYPENAME_EGlpNumCopyAbs (ay_ij, y_ij);
+		if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (y_ij, *pivtol))
+			continue;
+
+		EGLPNUM_TYPENAME_EGlpNumCopy (t_i, EGLPNUM_TYPENAME_INFTY);
+		i = lp->yjz.indx[k];
+		x = &(lp->xbz[i]);
+		col = lp->baz[i];
+		l = &(lp->lz[col]);
+		u = &(lp->uz[col]);
+
+		if ((dir == VINCREASE && EGLPNUM_TYPENAME_EGlpNumIsGreatZero (y_ij)) ||
+				(dir == VDECREASE && EGLPNUM_TYPENAME_EGlpNumIsLessZero (y_ij)))
+		{
+			if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*l, EGLPNUM_TYPENAME_NINFTY))
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopyDiff (t_i, *x, *l);
+				EGLPNUM_TYPENAME_EGlpNumAddTo (t_i, *pftol);
+				EGLPNUM_TYPENAME_EGlpNumDivTo (t_i, ay_ij);
+			}
+		}
+		else if ((dir == VINCREASE && EGLPNUM_TYPENAME_EGlpNumIsLessZero (y_ij)) ||
+						 (dir == VDECREASE && EGLPNUM_TYPENAME_EGlpNumIsGreatZero (y_ij)))
+		{
+			if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*u, EGLPNUM_TYPENAME_INFTY))
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopySum (t_i, *u, *pftol);
+				EGLPNUM_TYPENAME_EGlpNumSubTo (t_i, *x);
+				EGLPNUM_TYPENAME_EGlpNumDivTo (t_i, ay_ij);
+			}
+		}
+		if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (t_i, EGLPNUM_TYPENAME_INFTY))
+			continue;
+
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (t_i, t_max))
+		{
+			/*HHH tind = i; yval = fabs (y_ij); tval = t_i - pftol/fabs(y_ij); */
+			EGLPNUM_TYPENAME_EGlpNumCopy (t_max, t_i);
+		}
+	}
+	/* we use yi_max as temporal variable here */
+	EGLPNUM_TYPENAME_EGlpNumCopyDiff (yi_max, lp->uz[ecol], lp->lz[ecol]);
+	if (lp->vtype[ecol] == VBOUNDED && EGLPNUM_TYPENAME_EGlpNumIsLeq (yi_max, t_max))
+	{
+
+		EGLPNUM_TYPENAME_EGlpNumCopy (t_max, yi_max);
+		rs->ratio_stat = RATIO_NOBCHANGE;
+		EGLPNUM_TYPENAME_EGlpNumCopy (rs->tz, t_max);
+		if (dir != VINCREASE)
+			EGLPNUM_TYPENAME_EGlpNumSign (rs->tz);
+		ILL_CLEANUP;
+	}
+
+	if (EGLPNUM_TYPENAME_EGlpNumIsLeq (EGLPNUM_TYPENAME_INFTY, t_max))
+	{
+		rs->ratio_stat = RATIO_UNBOUNDED;
+		ILL_CLEANUP;
+	}
+	/*if (EGLPNUM_TYPENAME_EGlpNumIsLess (t_max, EGLPNUM_TYPENAME_zeroLpNum))
+	 * QSlog("pIIhell");
+	 */
+	indx = -1;
+	EGLPNUM_TYPENAME_EGlpNumZero (t_z);
+	EGLPNUM_TYPENAME_EGlpNumZero (yi_max);
+	EGLPNUM_TYPENAME_EGlpNumZero (ayi_max);
+	ILL_IFTRACE2 (":%d", lp->yjz.nzcnt);
+	for (k = 0; k < lp->yjz.nzcnt; k++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (y_ij, lp->yjz.coef[k]);
+		EGLPNUM_TYPENAME_EGlpNumCopyAbs (ay_ij, y_ij);
+		if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (y_ij, *pivtol))
+			continue;
+
+		EGLPNUM_TYPENAME_EGlpNumCopy (t_i, EGLPNUM_TYPENAME_INFTY);
+		i = lp->yjz.indx[k];
+		x = &(lp->xbz[i]);
+		col = lp->baz[i];
+		l = &(lp->lz[col]);
+		u = &(lp->uz[col]);
+
+		if ((dir == VINCREASE && EGLPNUM_TYPENAME_EGlpNumIsGreatZero (y_ij)) ||
+				(dir == VDECREASE && EGLPNUM_TYPENAME_EGlpNumIsLessZero (y_ij)))
+		{
+			if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*l, EGLPNUM_TYPENAME_NINFTY))
+				EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (t_i, *x, *l, ay_ij);
+		}
+		else if ((dir == VINCREASE && EGLPNUM_TYPENAME_EGlpNumIsLessZero (y_ij)) ||
+						 (dir == VDECREASE && EGLPNUM_TYPENAME_EGlpNumIsGreatZero (y_ij)))
+		{
+			if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*u, EGLPNUM_TYPENAME_INFTY))
+				EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (t_i, *u, *x, ay_ij);
+		}
+
+		if (EGLPNUM_TYPENAME_EGlpNumIsLeq (t_i, t_max))
+		{
+			if (EGLPNUM_TYPENAME_EGlpNumIsLess (ayi_max, ay_ij))
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (yi_max, y_ij);
+				EGLPNUM_TYPENAME_EGlpNumCopy (ayi_max, ay_ij);
+				indx = i;
+				EGLPNUM_TYPENAME_EGlpNumCopy (t_z, t_i);
+				ILL_IFTRACE2 (":%d:%lf:%lf:%lf:%lf", indx, EGLPNUM_TYPENAME_EGlpNumToLf (t_i),
+											EGLPNUM_TYPENAME_EGlpNumToLf (t_max), EGLPNUM_TYPENAME_EGlpNumToLf (ayi_max),
+											EGLPNUM_TYPENAME_EGlpNumToLf (ay_ij));
+			}
+		}
+	}
+
+	if (indx < 0)
+	{
+		rs->ratio_stat = RATIO_FAILED;
+	}
+	else
+	{
+		/*
+		 * if (tind != rs->lindex){
+		 * HHHprintf ("tmax %e tval = %e yval = %e tind = %d\n", t_max, tval, yval, tind);
+		 * HHHprintf ("h tval = %e yval = %e tind = %d\n",rs->tz, yi_max, rs->lindex);
+		 * }
+		 */
+		ILL_IFTRACE2 (":%d", indx);
+		rs->lindex = indx;
+		EGLPNUM_TYPENAME_EGlpNumCopy (rs->tz, t_z);
+		EGLPNUM_TYPENAME_EGlpNumCopy (rs->pivotval, yi_max);
+		rs->ratio_stat = RATIO_BCHANGE;
+
+		if (dir == VINCREASE)
+			rs->lvstat =
+				(EGLPNUM_TYPENAME_EGlpNumIsGreatZero (yi_max)) ? STAT_LOWER : STAT_UPPER;
+		else
+			rs->lvstat =
+				(EGLPNUM_TYPENAME_EGlpNumIsGreatZero (yi_max)) ? STAT_UPPER : STAT_LOWER;
+
+		if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (rs->tz))
+		{
+			ILL_IFTRACE2 ("need to change bound, tz=%la\n", EGLPNUM_TYPENAME_EGlpNumToLf (rs->tz));
+			EGLPNUM_TYPENAME_EGlpNumCopyAbs (rs->tz, t_max);
+			EGLPNUM_TYPENAME_EGlpNumDivUiTo (rs->tz, 10);
+			rs->boundch = 1;
+			EGLPNUM_TYPENAME_EGlpNumCopy (rs->lbound, lp->xbz[rs->lindex]);
+			if (rs->lvstat == STAT_LOWER)
+				EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (rs->lbound, rs->tz, ayi_max);
+			else
+				EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (rs->lbound, rs->tz, ayi_max);
+		}
+		if (dir == VDECREASE)
+			EGLPNUM_TYPENAME_EGlpNumSign (rs->tz);
+	}
+CLEANUP:
+	EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_PIIPIV, 0, rs->pivotval);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (y_ij);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (ay_ij);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (t_i);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (t_z);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (t_max);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (yi_max);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (ayi_max);
+}
+
+#define GET_XY_DRATIOTEST \
+      if (lp->vstat[col] == STAT_UPPER){ \
+				EGLPNUM_TYPENAME_EGlpNumCopyNeg(x,lp->dz[j]);\
+        EGLPNUM_TYPENAME_EGlpNumCopy(y, *zAj);\
+      } \
+      else{ \
+         EGLPNUM_TYPENAME_EGlpNumCopy(x, lp->dz[j]); \
+         EGLPNUM_TYPENAME_EGlpNumCopyNeg(y, *zAj);\
+      } \
+      if (lvstat == STAT_UPPER) \
+         EGLPNUM_TYPENAME_EGlpNumSign(y);
+
+
+void EGLPNUM_TYPENAME_ILLratio_dI_test (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int lindex,
+	int lvstat,
+	EGLPNUM_TYPENAME_ratio_res * rs)
+{
+	int j = 0, k;
+	int col;
+	int cbnd, indx;
+	int tctr = 0;
+	int *perm = lp->upd.perm;
+	int *ix = lp->upd.ix;
+	EGLPNUM_TYPE *t = lp->upd.t;
+	EGLPNUM_TYPE *zAj, x, y, t_j, theta, rcost, delta;
+	EGLPNUM_TYPE *pftol = &(lp->tol->ip_tol);
+	EGLPNUM_TYPE *pivtol = &(lp->tol->pivot_tol);
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (x);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (y);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (t_j);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (theta);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (rcost);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (delta);
+	EGLPNUM_TYPENAME_EGlpNumZero (delta);
+	EGLPNUM_TYPENAME_EGlpNumZero (t_j);
+	EGLPNUM_TYPENAME_EGlpNumZero (rs->tz);
+	 /*HHH*/ rs->eindex = -1;
+	rs->ratio_stat = RATIO_FAILED;
+	EGLPNUM_TYPENAME_EGlpNumZero (rs->pivotval);
+
+	for (k = 0; k < lp->zA.nzcnt; k++)
+	{
+		zAj = &(lp->zA.coef[k]);
+		if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (*zAj, *pivtol))
+			continue;
+
+		EGLPNUM_TYPENAME_EGlpNumCopy (t_j, EGLPNUM_TYPENAME_INFTY);
+		j = lp->zA.indx[k];
+		col = lp->nbaz[j];
+
+		if (lp->vtype[col] == VARTIFICIAL || lp->vtype[col] == VFIXED)
+			continue;
+
+		GET_XY_DRATIOTEST;
+
+		if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (y))
+		{
+			if (lp->dfeas[j] != 0 && lp->vstat[col] != STAT_ZERO)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopyFrac (t[tctr], x, y);
+				ix[tctr] = 10 * k + BBTOLOWER;
+				tctr++;
+			}
+			else if (lp->vstat[col] == STAT_ZERO)
+			{
+				if (lp->dfeas[j] < 0)
+				{
+					EGLPNUM_TYPENAME_EGlpNumCopyFrac (t[tctr], x, y);
+					ix[tctr] = 10 * k + BBTOLOWER;
+					tctr++;
+				}
+				if (lp->dfeas[j] <= 0)
+				{
+					EGLPNUM_TYPENAME_EGlpNumCopyFrac (t[tctr], x, y);
+					ix[tctr] = 10 * k + BBTOUPPER;
+					tctr++;
+				}
+			}
+		}
+		else
+		{
+			if (lp->dfeas[j] > 0)
+			{
+				if (lp->vstat[col] == STAT_ZERO)
+				{
+					EGLPNUM_TYPENAME_EGlpNumCopyFrac (t[tctr], x, y);
+					ix[tctr] = 10 * k + BATOUPPER;
+					tctr++;
+					EGLPNUM_TYPENAME_EGlpNumCopyFrac (t[tctr], x, y);
+					ix[tctr] = 10 * k + BATOLOWER;
+					tctr++;
+				}
+			}
+			else if (lp->dfeas[j] == 0)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopyFrac (t[tctr], x, y);
+				if (lp->vtype[col] == VBOUNDED)
+					ix[tctr] = 10 * k + BSKIP;
+				else
+					ix[tctr] = 10 * k + BATOLOWER;
+				tctr++;
+			}
+		}
+	}
+
+	if (tctr == 0)
+	{
+		rs->ratio_stat = RATIO_FAILED;
+		ILL_CLEANUP;
+	}
+
+	for (j = 0; j < tctr; j++)
+		perm[j] = j;
+	EGLPNUM_TYPENAME_ILLutil_EGlpNum_perm_quicksort (perm, t, tctr);
+
+	EGLPNUM_TYPENAME_EGlpNumZero (lp->upd.c_obj);
+	EGLPNUM_TYPENAME_EGlpNumCopy (rcost, lp->xbz[lindex]);
+	if (lvstat == STAT_LOWER)
+		EGLPNUM_TYPENAME_EGlpNumSign (rcost);
+	for (j = 0; j < tctr; j++)
+	{
+		cbnd = ix[perm[j]] % 10;
+		if (cbnd == BSKIP)
+			continue;
+
+		EGLPNUM_TYPENAME_EGlpNumCopy (t_j, t[perm[j]]);
+		EGLPNUM_TYPENAME_EGlpNumCopy (x, t_j);
+		EGLPNUM_TYPENAME_EGlpNumSubTo (x, delta);
+		EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (lp->upd.c_obj, x, rcost);
+		EGLPNUM_TYPENAME_EGlpNumCopy (delta, t_j);
+		k = ix[perm[j]] / 10;
+		zAj = &(lp->zA.coef[k]);
+		indx = lp->zA.indx[k];
+
+		if (lp->vstat[lp->nbaz[indx]] == STAT_LOWER
+				|| lp->vstat[lp->nbaz[indx]] == STAT_ZERO)
+			EGLPNUM_TYPENAME_EGlpNumCopyNeg (theta, *zAj);
+		else
+			EGLPNUM_TYPENAME_EGlpNumCopy (theta, *zAj);
+
+		if (lvstat == STAT_UPPER)
+			EGLPNUM_TYPENAME_EGlpNumSign (theta);
+
+		switch (cbnd)
+		{
+		case BATOLOWER:
+		case BATOUPPER:
+			EGLPNUM_TYPENAME_EGlpNumSubTo (rcost, theta);
+			break;
+		case BBTOLOWER:
+		case BBTOUPPER:
+			EGLPNUM_TYPENAME_EGlpNumAddTo (rcost, theta);
+			break;
+		}
+		if (EGLPNUM_TYPENAME_EGlpNumIsLeq (rcost, *pftol))
+		{
+			/* if (t_j < 0.0) QSlog("dIhell"); */
+			rs->eindex = indx;
+			EGLPNUM_TYPENAME_EGlpNumCopy (rs->tz, t_j);
+			EGLPNUM_TYPENAME_EGlpNumCopy (rs->pivotval, *zAj);
+			rs->ratio_stat = RATIO_BCHANGE;
+			ILL_CLEANUP;
+		}
+	}
+
+CLEANUP:
+	EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_DIPIV, 0, rs->pivotval);
+	ILL_IFTRACE2 ("%s:tctr %d\n", __func__, tctr);
+	lp->upd.tctr = tctr;
+	lp->upd.i = j;
+	EGLPNUM_TYPENAME_EGlpNumCopyAbs (lp->upd.tz, t_j);
+	EGLPNUM_TYPENAME_EGlpNumCopy (lp->upd.piv, rs->pivotval);
+	if (rs->eindex != -1)
+		lp->upd.fs = lp->dfeas[rs->eindex];
+	EGLPNUM_TYPENAME_EGlpNumClearVar (x);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (y);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (t_j);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (theta);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (rcost);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (delta);
+}
+
+void EGLPNUM_TYPENAME_ILLratio_dII_test (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	/*int lindex,*/
+	int lvstat,
+	EGLPNUM_TYPENAME_ratio_res * rs)
+{
+	int j, k, indx;
+	int col, ecol;
+	EGLPNUM_TYPE *zAj, azAj, az_max, x, y, t_j, z_max, t_max, t_z;
+	EGLPNUM_TYPE *dftol = &(lp->tol->dfeas_tol);
+	EGLPNUM_TYPE *pivtol = &(lp->tol->pivot_tol);
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (x);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (y);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (t_j);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (z_max);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (t_max);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (az_max);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (azAj);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (t_z);
+	EGLPNUM_TYPENAME_EGlpNumZero (t_j);
+	rs->coeffch = 0;
+	EGLPNUM_TYPENAME_EGlpNumZero (rs->ecoeff);
+	rs->eindex = -1;
+	rs->ratio_stat = RATIO_FAILED;
+	ILL_IFTRACE2 ("%s:tctr %d\n", __func__, 0);
+	lp->upd.tctr = 0;
+	EGLPNUM_TYPENAME_EGlpNumZero (lp->upd.dty);
+	for (k = 0, EGLPNUM_TYPENAME_EGlpNumCopy (t_max, EGLPNUM_TYPENAME_INFTY); k < lp->zA.nzcnt; k++)
+	{
+		zAj = &(lp->zA.coef[k]);
+		if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (*zAj, *pivtol))
+			continue;
+
+		EGLPNUM_TYPENAME_EGlpNumCopy (t_j, EGLPNUM_TYPENAME_INFTY);
+		j = lp->zA.indx[k];
+		col = lp->nbaz[j];
+
+		if (lp->vtype[col] == VARTIFICIAL || lp->vtype[col] == VFIXED)
+			continue;
+
+		GET_XY_DRATIOTEST;
+
+//#warning adding/substracting tolerances to used value, is it rigght?
+		if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (y))
+		{
+			//t_j = (x + dftol) / y;
+			EGLPNUM_TYPENAME_EGlpNumCopySum (t_j, x, *dftol);
+			EGLPNUM_TYPENAME_EGlpNumDivTo (t_j, y);
+		}
+		else
+		{
+//#warning adding/substracting tolerances to used value, is it rigght?
+			if (lp->vstat[col] == STAT_ZERO)
+				EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (t_j, x, *dftol, y);
+		}
+		//if (t_j == EGLPNUM_TYPENAME_INFTY)
+		if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (t_j, EGLPNUM_TYPENAME_INFTY))
+			continue;
+
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (t_j, t_max))
+			EGLPNUM_TYPENAME_EGlpNumCopy (t_max, t_j);
+	}
+
+	if (EGLPNUM_TYPENAME_EGlpNumIsLeq (EGLPNUM_TYPENAME_INFTY, t_max))
+	{
+		rs->ratio_stat = RATIO_UNBOUNDED;
+		ILL_CLEANUP;
+	}
+	/* if (t_max < 0.0) QSlog("dIIhell"); */
+
+	indx = -1;
+	EGLPNUM_TYPENAME_EGlpNumZero (t_z);
+	EGLPNUM_TYPENAME_EGlpNumZero (z_max);
+	EGLPNUM_TYPENAME_EGlpNumZero (az_max);
+
+	for (k = 0; k < lp->zA.nzcnt; k++)
+	{
+		zAj = &(lp->zA.coef[k]);
+		EGLPNUM_TYPENAME_EGlpNumCopyAbs (azAj, *zAj);
+		if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (*zAj, *pivtol))
+			continue;
+
+		EGLPNUM_TYPENAME_EGlpNumCopy (t_j, EGLPNUM_TYPENAME_INFTY);
+		j = lp->zA.indx[k];
+		col = lp->nbaz[j];
+
+		if (lp->vtype[col] == VARTIFICIAL || lp->vtype[col] == VFIXED)
+			continue;
+
+		GET_XY_DRATIOTEST;
+
+		if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (y) || lp->vstat[col] == STAT_ZERO)
+			EGLPNUM_TYPENAME_EGlpNumCopyFrac (t_j, x, y);
+
+		if (EGLPNUM_TYPENAME_EGlpNumIsLeq (t_j, t_max) && (EGLPNUM_TYPENAME_EGlpNumIsLess (az_max, azAj)))
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (z_max, *zAj);
+			EGLPNUM_TYPENAME_EGlpNumCopy (az_max, azAj);
+			indx = j;
+			EGLPNUM_TYPENAME_EGlpNumCopy (t_z, t_j);
+		}
+	}
+
+
+	if (indx < 0)
+	{
+		rs->ratio_stat = RATIO_FAILED;
+	}
+	else
+	{
+		rs->eindex = indx;
+		EGLPNUM_TYPENAME_EGlpNumCopy (rs->tz, t_z);
+		EGLPNUM_TYPENAME_EGlpNumCopy (rs->pivotval, z_max);
+		rs->ratio_stat = RATIO_BCHANGE;
+
+		if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (rs->tz))
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopyAbs (rs->tz, t_max);
+			EGLPNUM_TYPENAME_EGlpNumDivUiTo (rs->tz, 20);
+			rs->coeffch = 1;
+			ecol = lp->nbaz[indx];
+			EGLPNUM_TYPENAME_EGlpNumCopyDiff (rs->ecoeff, lp->cz[ecol], lp->dz[indx]);
+			switch (lp->vstat[ecol])
+			{
+			case STAT_LOWER:
+				EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (rs->ecoeff, rs->tz, az_max);
+				break;
+			case STAT_UPPER:
+				EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (rs->ecoeff, rs->tz, az_max);
+				break;
+			default:
+				EGLPNUM_TYPENAME_EGlpNumZero (rs->tz);
+				break;
+			}
+		}
+	}
+
+CLEANUP:
+	EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_DIIPIV, 0, rs->pivotval);
+	EGLPNUM_TYPENAME_EGlpNumCopy (lp->upd.piv, rs->pivotval);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (x);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (y);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (t_j);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (z_max);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (t_max);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (t_z);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (az_max);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (azAj);
+}
+
+void EGLPNUM_TYPENAME_ILLratio_longdII_test (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int lindex,
+	int lvstat,
+	EGLPNUM_TYPENAME_ratio_res * rs)
+{
+	int j, k, indx = 0, tctr = 0;
+	int col, ecol;
+	int vs, bnd_exist = 0;
+	int *perm = lp->upd.perm;
+	int *ix = lp->upd.ix;
+	int b_indx = -1;
+	EGLPNUM_TYPE *t = lp->upd.t;
+	EGLPNUM_TYPE *l,
+		*u,
+		*xb,
+		*zAj = 0,
+		x,
+		y,
+		t_j,
+		z_max,
+		t_max, t_z, theta, rcost, delta, zb_val, tb_val, az_max, azb_val, azAj;
+	EGLPNUM_TYPE *pftol = &(lp->tol->pfeas_tol);
+	EGLPNUM_TYPE *dftol = &(lp->tol->dfeas_tol);
+	EGLPNUM_TYPE *pivtol = &(lp->tol->pivot_tol);
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (x);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (azAj);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (y);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (t_j);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (z_max);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (az_max);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (t_max);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (t_z);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (theta);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (rcost);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (delta);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (zb_val);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (azb_val);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (tb_val);
+	EGLPNUM_TYPENAME_EGlpNumZero (t_j);
+	EGLPNUM_TYPENAME_EGlpNumZero (delta);
+	EGLPNUM_TYPENAME_EGlpNumZero (zb_val);
+	EGLPNUM_TYPENAME_EGlpNumZero (azb_val);
+	EGLPNUM_TYPENAME_EGlpNumCopy (tb_val, EGLPNUM_TYPENAME_NINFTY);
+//#warning not sure about THIS line
+	EGLPNUM_TYPENAME_EGlpNumZero (rs->pivotval);
+
+	rs->coeffch = 0;
+	rs->eindex = -1;
+	rs->ratio_stat = RATIO_FAILED;
+
+	ILL_IFTRACE2 ("%s:tctr %d\n", __func__, 0);
+	lp->upd.tctr = 0;
+	lp->upd.i = 0;
+	EGLPNUM_TYPENAME_EGlpNumZero (lp->upd.tz);
+	EGLPNUM_TYPENAME_EGlpNumZero (lp->upd.piv);
+	EGLPNUM_TYPENAME_EGlpNumZero (lp->upd.c_obj);
+	EGLPNUM_TYPENAME_EGlpNumZero (lp->upd.dty);
+
+	xb = &(lp->xbz[lindex]);
+	col = lp->baz[lindex];
+	l = &(lp->lz[col]);
+	u = &(lp->uz[col]);
+	//rcost = (lvstat == STAT_LOWER) ? l - xb : xb - u;
+	if (lvstat == STAT_LOWER)
+		EGLPNUM_TYPENAME_EGlpNumCopyDiff (rcost, *l, *xb);
+	else
+		EGLPNUM_TYPENAME_EGlpNumCopyDiff (rcost, *xb, *u);
+
+	for (k = 0, EGLPNUM_TYPENAME_EGlpNumCopy (t_max, EGLPNUM_TYPENAME_INFTY); k < lp->zA.nzcnt; k++)
+	{
+		zAj = &(lp->zA.coef[k]);
+		if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (*zAj, *pivtol))
+			continue;
+
+		EGLPNUM_TYPENAME_EGlpNumCopy (t_j, EGLPNUM_TYPENAME_INFTY);
+		j = lp->zA.indx[k];
+		col = lp->nbaz[j];
+
+		if (lp->vtype[col] == VARTIFICIAL || lp->vtype[col] == VFIXED)
+			continue;
+		if (lp->vtype[col] == VBOUNDED)
+		{
+			bnd_exist++;
+			continue;
+		}
+
+		GET_XY_DRATIOTEST;
+
+		if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (y))
+		{
+			//t_j = (x + dftol) / y;
+//#warning Using tolerances to add to result, is it right?
+			EGLPNUM_TYPENAME_EGlpNumCopySum (t_j, x, *dftol);
+			EGLPNUM_TYPENAME_EGlpNumDivTo (t_j, y);
+		}
+		else
+		{
+			if (lp->vstat[col] == STAT_ZERO)
+				EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (t_j, x, *dftol, y);
+		}
+		if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (t_j, EGLPNUM_TYPENAME_INFTY))
+			continue;
+
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (t_j, t_max))
+			EGLPNUM_TYPENAME_EGlpNumCopy (t_max, t_j);
+	}
+	if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (t_max))
+	{
+		/*QSlog("dIIhell, %.4f", t_max); */
+		rs->ratio_stat = RATIO_NEGATIVE;
+		ILL_CLEANUP;
+	}
+
+	if (bnd_exist == 0 && EGLPNUM_TYPENAME_EGlpNumIsLeq (EGLPNUM_TYPENAME_INFTY, t_max))
+	{
+		rs->ratio_stat = RATIO_UNBOUNDED;
+		/*
+		 * QSlog("x = %.8f, b = %.2f", lp->xbz[lindex], (lvstat == STAT_LOWER ) ? lp->lz[lp->baz[lindex]] : lp->uz[lp->baz[lindex]]);
+		 */
+		ILL_CLEANUP;
+	}
+
+	if (bnd_exist != 0)
+	{
+		for (k = 0; k < lp->zA.nzcnt; k++)
+		{
+			zAj = &(lp->zA.coef[k]);
+			if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (*zAj, *pivtol))
+				continue;
+
+			EGLPNUM_TYPENAME_EGlpNumCopy (t_j, EGLPNUM_TYPENAME_INFTY);
+			j = lp->zA.indx[k];
+			col = lp->nbaz[j];
+
+			if (lp->vtype[col] != VBOUNDED)
+				continue;
+
+			GET_XY_DRATIOTEST;
+
+			if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (y))
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopyFrac (t_j, x, y);
+				if (EGLPNUM_TYPENAME_EGlpNumIsLeq (t_j, t_max))
+				{
+					EGLPNUM_TYPENAME_EGlpNumCopy (t[tctr], t_j);
+					ix[tctr] = k;
+					tctr++;
+				}
+			}
+		}
+	}
+
+	if (tctr != 0)
+	{
+		for (j = 0; j < tctr; j++)
+			perm[j] = j;
+		EGLPNUM_TYPENAME_ILLutil_EGlpNum_perm_quicksort (perm, t, tctr);
+
+		for (j = 0; j < tctr; j++)
+		{
+
+			EGLPNUM_TYPENAME_EGlpNumCopy (t_j, t[perm[j]]);
+			/* we use x as temporal storage */
+			//lp->upd.c_obj += (t_j - delta) * rcost;
+			EGLPNUM_TYPENAME_EGlpNumCopy (x, t_j);
+			EGLPNUM_TYPENAME_EGlpNumSubTo (x, delta);
+			EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (lp->upd.c_obj, x, rcost);
+			EGLPNUM_TYPENAME_EGlpNumCopy (delta, t_j);
+			 /*HHH*/ k = ix[perm[j]];
+			zAj = &(lp->zA.coef[k]);
+			indx = lp->zA.indx[k];
+			col = lp->nbaz[indx];
+			l = &(lp->lz[col]);
+			u = &(lp->uz[col]);
+			vs = lp->vstat[col];
+			//theta = (vs == STAT_UPPER) ? (l - u) * zAj : (u - l) * zAj;
+			EGLPNUM_TYPENAME_EGlpNumCopyDiff (theta, *l, *u);
+			EGLPNUM_TYPENAME_EGlpNumMultTo (theta, *zAj);
+			if (vs != STAT_UPPER)
+				EGLPNUM_TYPENAME_EGlpNumSign (theta);
+			if (lvstat == STAT_LOWER)
+				EGLPNUM_TYPENAME_EGlpNumAddTo (rcost, theta);
+			else
+				EGLPNUM_TYPENAME_EGlpNumSubTo (rcost, theta);
+
+			if (EGLPNUM_TYPENAME_EGlpNumIsLeq (rcost, *pftol))
+			{
+				rs->eindex = indx;
+				EGLPNUM_TYPENAME_EGlpNumCopy (rs->tz, t_j);
+				EGLPNUM_TYPENAME_EGlpNumCopy (rs->pivotval, *zAj);
+				rs->ratio_stat = RATIO_BCHANGE;
+
+				if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (rs->tz))
+				{
+					EGLPNUM_TYPENAME_EGlpNumZero (rs->tz);
+					rs->coeffch = 1;
+					//rs->ecoeff = lp->cz[col] - lp->dz[indx];
+					EGLPNUM_TYPENAME_EGlpNumCopyDiff (rs->ecoeff, lp->cz[col], lp->dz[indx]);
+					//lp->upd.c_obj += (rs->tz - delta) * rcost; note ts->tz == 0;
+					EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (lp->upd.c_obj, delta, rcost);
+				}
+				ILL_IFTRACE2 ("%s:tctr %d\n", __func__, tctr);
+				lp->upd.tctr = tctr;
+				lp->upd.i = j;
+				EGLPNUM_TYPENAME_EGlpNumCopy (lp->upd.tz, rs->tz);
+				ILL_CLEANUP;
+			}
+		}
+		ILL_IFTRACE2 ("%s:tctr %d\n", __func__, tctr);
+		lp->upd.tctr = tctr;
+		lp->upd.i = tctr;
+		EGLPNUM_TYPENAME_EGlpNumCopy (lp->upd.tz, t_j);
+		EGLPNUM_TYPENAME_EGlpNumCopy (zb_val, *zAj);
+		EGLPNUM_TYPENAME_EGlpNumCopyAbs (azb_val, zb_val);
+		EGLPNUM_TYPENAME_EGlpNumCopy (tb_val, t_j);
+		b_indx = indx;
+	}
+
+	if (bnd_exist != 0 && EGLPNUM_TYPENAME_EGlpNumIsLeq (EGLPNUM_TYPENAME_INFTY, t_max))
+	{
+		rs->ratio_stat = RATIO_UNBOUNDED;
+		/* QSlog("rcost: %.8f", rcost); */
+		ILL_CLEANUP;
+	}
+
+	EGLPNUM_TYPENAME_EGlpNumZero (z_max);
+	EGLPNUM_TYPENAME_EGlpNumZero (az_max);
+	indx = -1;
+	EGLPNUM_TYPENAME_EGlpNumZero (t_z);
+	for (k = 0; k < lp->zA.nzcnt; k++)
+	{
+		zAj = &(lp->zA.coef[k]);
+		EGLPNUM_TYPENAME_EGlpNumCopyAbs (azAj, *zAj);
+		if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (*zAj, *pivtol))
+			continue;
+
+		EGLPNUM_TYPENAME_EGlpNumCopy (t_j, EGLPNUM_TYPENAME_INFTY);
+		j = lp->zA.indx[k];
+		col = lp->nbaz[j];
+
+		if (lp->vtype[col] == VARTIFICIAL || lp->vtype[col] == VFIXED ||
+				lp->vtype[col] == VBOUNDED)
+			continue;
+
+		GET_XY_DRATIOTEST;
+
+		if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (y) || lp->vstat[col] == STAT_ZERO)
+			EGLPNUM_TYPENAME_EGlpNumCopyFrac (t_j, x, y);
+
+		if (EGLPNUM_TYPENAME_EGlpNumIsLeq (t_j, t_max))
+		{
+			if (EGLPNUM_TYPENAME_EGlpNumIsLess (az_max, azAj))
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (z_max, *zAj);
+				EGLPNUM_TYPENAME_EGlpNumCopy (az_max, azAj);
+				indx = j;
+				EGLPNUM_TYPENAME_EGlpNumCopy (t_z, t_j);
+			}
+		}
+	}
+
+	if (indx < 0)
+	{
+		rs->ratio_stat = RATIO_FAILED;
+		ILL_CLEANUP;
+	}
+	if ((tctr == 0) || (EGLPNUM_TYPENAME_EGlpNumIsLessZero (tb_val)) ||
+			(tctr != 0 && EGLPNUM_TYPENAME_EGlpNumIsLeq (tb_val, t_z) &&
+			 EGLPNUM_TYPENAME_EGlpNumIsLeq (azb_val, az_max)))
+	{
+		/* we use x as temporal vvariable */
+		/* lp->upd.c_obj += (t_z - delta) * rcost; */
+		EGLPNUM_TYPENAME_EGlpNumCopyDiff (x, t_z, delta);
+		EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (lp->upd.c_obj, x, rcost);
+		EGLPNUM_TYPENAME_EGlpNumCopy (delta, t_z);
+		rs->eindex = indx;
+		EGLPNUM_TYPENAME_EGlpNumCopy (rs->tz, t_z);
+		EGLPNUM_TYPENAME_EGlpNumCopy (rs->pivotval, z_max);
+		rs->ratio_stat = RATIO_BCHANGE;
+	}
+	/* For now */
+	else if (tctr != 0)
+	{
+		rs->eindex = b_indx;
+		EGLPNUM_TYPENAME_EGlpNumCopy (rs->tz, tb_val);
+		EGLPNUM_TYPENAME_EGlpNumCopy (rs->pivotval, zb_val);
+		rs->ratio_stat = RATIO_BCHANGE;
+		lp->upd.i -= 1;
+	}
+
+	if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (rs->tz))
+	{
+		/* if (tctr != 0) QSlog("despite long step"); */
+		/* rs->tz = fabs (t_max / 20.0); */
+		EGLPNUM_TYPENAME_EGlpNumCopyAbs (rs->tz, t_max);
+		EGLPNUM_TYPENAME_EGlpNumDivUiTo (rs->tz, 20);
+		rs->coeffch = 1;
+
+		ecol = lp->nbaz[indx];
+		if (lp->vstat[ecol] == STAT_LOWER)
+		{
+			/*rs->ecoeff = lp->cz[ecol] - lp->dz[indx] + rs->tz * fabs (z_max); */
+			EGLPNUM_TYPENAME_EGlpNumCopy (rs->ecoeff, az_max);
+			EGLPNUM_TYPENAME_EGlpNumMultTo (rs->ecoeff, rs->tz);
+			EGLPNUM_TYPENAME_EGlpNumAddTo (rs->ecoeff, lp->cz[ecol]);
+			EGLPNUM_TYPENAME_EGlpNumSubTo (rs->ecoeff, lp->dz[indx]);
+		}
+		else if (lp->vstat[ecol] == STAT_UPPER)
+		{
+			/*rs->ecoeff = lp->cz[ecol] - lp->dz[indx] - rs->tz * fabs (z_max); */
+			EGLPNUM_TYPENAME_EGlpNumCopy (rs->ecoeff, az_max);
+			EGLPNUM_TYPENAME_EGlpNumMultTo (rs->ecoeff, rs->tz);
+			EGLPNUM_TYPENAME_EGlpNumSign (rs->ecoeff);
+			EGLPNUM_TYPENAME_EGlpNumAddTo (rs->ecoeff, lp->cz[ecol]);
+			EGLPNUM_TYPENAME_EGlpNumSubTo (rs->ecoeff, lp->dz[indx]);
+		}
+		else
+		{
+			/*rs->ecoeff = lp->cz[ecol] - lp->dz[indx]; */
+			EGLPNUM_TYPENAME_EGlpNumCopyDiff (rs->ecoeff, lp->cz[ecol], lp->dz[indx]);
+			EGLPNUM_TYPENAME_EGlpNumZero (rs->tz);
+		}
+		/* we use x as temporal storage */
+		/*lp->upd.c_obj += (rs->tz - delta) * rcost; */
+		EGLPNUM_TYPENAME_EGlpNumCopy (x, rs->tz);
+		EGLPNUM_TYPENAME_EGlpNumSubTo (x, delta);
+		EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (lp->upd.c_obj, x, rcost);
+	}
+
+CLEANUP:
+	EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_DIIPIV, 0, rs->pivotval);
+	EGLPNUM_TYPENAME_EGlpNumCopy (lp->upd.piv, rs->pivotval);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (x);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (y);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (t_j);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (z_max);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (az_max);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (t_max);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (t_z);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (theta);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (rcost);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (delta);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (zb_val);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (azb_val);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (tb_val);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (azAj);
+}
+
+void EGLPNUM_TYPENAME_ILLratio_pivotin_test (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int *rlist,
+	int rcnt,
+	EGLPNUM_TYPENAME_ratio_res * rs)
+{
+	int i, k, col;
+	EGLPNUM_TYPE *x, *l, *u;
+	EGLPNUM_TYPE ay_ij,
+		at_i, at_l, at_u, ayi_max, y_ij, t_i, t_l, t_u, t_max, yi_max;
+	EGLPNUM_TYPE *pivtol = &(lp->tol->pivot_tol);
+
+	if (rcnt <= 0 || rs == NULL)
+		return;
+	EGLPNUM_TYPENAME_EGlpNumInitVar (ay_ij);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (at_i);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (at_l);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (at_u);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (ayi_max);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (t_max);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (y_ij);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (t_i);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (t_l);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (t_u);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (yi_max);
+	rs->boundch = 0;
+	rs->lindex = -1;
+	EGLPNUM_TYPENAME_EGlpNumZero (rs->tz);
+	rs->ratio_stat = RATIO_FAILED;
+	rs->lvstat = -1;
+	EGLPNUM_TYPENAME_EGlpNumZero (rs->pivotval);
+	EGLPNUM_TYPENAME_EGlpNumZero (rs->lbound);
+
+	for (i = 0; i < rcnt; i++)
+		lp->iwork[rlist[i]] = 1;
+
+	for (k = 0, EGLPNUM_TYPENAME_EGlpNumCopy (t_max, EGLPNUM_TYPENAME_INFTY); k < lp->yjz.nzcnt; k++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (y_ij, lp->yjz.coef[k]);
+		if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (y_ij, *pivtol))
+			continue;
+
+		i = lp->yjz.indx[k];
+		if (lp->iwork[lp->baz[i]] == 1)
+			continue;
+		x = &(lp->xbz[i]);
+		col = lp->baz[i];
+		l = &(lp->lz[col]);
+		u = &(lp->uz[col]);
+		EGLPNUM_TYPENAME_EGlpNumCopy (t_u, EGLPNUM_TYPENAME_INFTY);
+		EGLPNUM_TYPENAME_EGlpNumCopy (at_u, EGLPNUM_TYPENAME_INFTY);
+		EGLPNUM_TYPENAME_EGlpNumCopy (t_l, EGLPNUM_TYPENAME_NINFTY);
+		EGLPNUM_TYPENAME_EGlpNumCopy (at_l, EGLPNUM_TYPENAME_INFTY);
+
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*l, EGLPNUM_TYPENAME_NINFTY))
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (t_l, *x, *l, y_ij);
+			EGLPNUM_TYPENAME_EGlpNumCopyAbs (at_l, t_l);
+			if (EGLPNUM_TYPENAME_EGlpNumIsLess (at_l, t_max))
+				EGLPNUM_TYPENAME_EGlpNumCopy (t_max, at_l);
+		}
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*u, EGLPNUM_TYPENAME_INFTY))
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (t_u, *x, *u, y_ij);
+			EGLPNUM_TYPENAME_EGlpNumCopyAbs (at_u, t_u);
+			if (EGLPNUM_TYPENAME_EGlpNumIsLess (at_u, t_max))
+				EGLPNUM_TYPENAME_EGlpNumCopy (t_max, at_u);
+		}
+	}
+
+	if (EGLPNUM_TYPENAME_EGlpNumIsLeq (EGLPNUM_TYPENAME_INFTY, t_max))
+	{
+		rs->ratio_stat = RATIO_UNBOUNDED;
+		ILL_CLEANUP;
+	}
+
+	EGLPNUM_TYPENAME_EGlpNumZero (yi_max);
+	EGLPNUM_TYPENAME_EGlpNumZero (ayi_max);
+	EGLPNUM_TYPENAME_EGlpNumMultUiTo (t_max, 101);
+	EGLPNUM_TYPENAME_EGlpNumDivUiTo (t_max, 100);
+	for (k = 0; k < lp->yjz.nzcnt; k++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (y_ij, lp->yjz.coef[k]);
+		EGLPNUM_TYPENAME_EGlpNumCopyAbs (ay_ij, y_ij);
+		if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (y_ij, *pivtol))
+			continue;
+
+		i = lp->yjz.indx[k];
+		if (lp->iwork[lp->baz[i]] == 1)
+			continue;
+		x = &(lp->xbz[i]);
+		col = lp->baz[i];
+		l = &(lp->lz[col]);
+		u = &(lp->uz[col]);
+
+		EGLPNUM_TYPENAME_EGlpNumCopy (t_u, EGLPNUM_TYPENAME_INFTY);
+		EGLPNUM_TYPENAME_EGlpNumCopy (at_u, t_u);
+		EGLPNUM_TYPENAME_EGlpNumCopy (t_l, EGLPNUM_TYPENAME_NINFTY);
+		EGLPNUM_TYPENAME_EGlpNumCopy (at_l, t_u);
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*l, EGLPNUM_TYPENAME_NINFTY))
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (t_l, *x, *l, y_ij);
+			EGLPNUM_TYPENAME_EGlpNumCopyAbs (at_l, t_l);
+		}
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*u, EGLPNUM_TYPENAME_INFTY))
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (t_u, *x, *u, y_ij);
+			EGLPNUM_TYPENAME_EGlpNumCopyAbs (at_u, t_u);
+		}
+		//t_i = (fabs (t_l) < fabs (t_u)) ? t_l : t_u;
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (at_l, at_u))
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (t_i, t_l);
+			EGLPNUM_TYPENAME_EGlpNumCopy (at_i, at_l);
+		}
+		else
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (t_i, t_u);
+			EGLPNUM_TYPENAME_EGlpNumCopy (at_i, at_u);
+		}
+		/*if (fabs (t_i) <= t_max + t_max * (1.0e-2)) */
+		if (EGLPNUM_TYPENAME_EGlpNumIsLeq (at_i, t_max))
+		{
+			if (EGLPNUM_TYPENAME_EGlpNumIsLess (ayi_max, ay_ij))
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (yi_max, y_ij);
+				EGLPNUM_TYPENAME_EGlpNumCopy (ayi_max, ay_ij);
+				rs->lindex = i;
+				EGLPNUM_TYPENAME_EGlpNumCopy (rs->tz, t_i);
+				rs->lvstat = (EGLPNUM_TYPENAME_EGlpNumIsLess (at_l, at_u)) ? STAT_LOWER : STAT_UPPER;
+			}
+		}
+	}
+
+	if (rs->lindex < 0)
+	{
+		rs->ratio_stat = RATIO_FAILED;
+	}
+	else
+	{
+		rs->ratio_stat = RATIO_BCHANGE;
+		EGLPNUM_TYPENAME_EGlpNumCopy (rs->pivotval, yi_max);
+	}
+CLEANUP:
+	for (i = 0; i < rcnt; i++)
+		lp->iwork[rlist[i]] = 0;
+	EGLPNUM_TYPENAME_EGlpNumClearVar (t_max);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (ay_ij);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (at_i);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (at_l);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (at_u);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (ayi_max);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (y_ij);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (t_i);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (t_l);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (t_u);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (yi_max);
+	return;
+}
diff --git a/qsopt_ex/ratio.h b/qsopt_ex/ratio.h
new file mode 100644
index 0000000..ff8abfd
--- /dev/null
+++ b/qsopt_ex/ratio.h
@@ -0,0 +1,73 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/*  $RCSfile: ratio_EGLPNUM_TYPENAME.h,v $ $Revision: 1.3 $ $Date: 2003/11/05 16:57:39 $" */
+#ifndef EGLPNUM_TYPENAME___RATIO_H
+#define EGLPNUM_TYPENAME___RATIO_H
+#include "basicdefs.h"
+typedef struct EGLPNUM_TYPENAME_ratio_res
+{
+	EGLPNUM_TYPE tz;
+	int eindex;
+	int lindex;
+	int lvstat;
+	int ratio_stat;
+	int boundch;
+	int coeffch;
+	EGLPNUM_TYPE lbound;
+	EGLPNUM_TYPE ecoeff;
+	EGLPNUM_TYPE pivotval;
+}
+EGLPNUM_TYPENAME_ratio_res;
+
+void EGLPNUM_TYPENAME_ILLratio_pI_test (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	int const eindex,
+	int const dir,
+	EGLPNUM_TYPENAME_ratio_res * const rs),
+  EGLPNUM_TYPENAME_ILLratio_pII_test (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	int const eindex,
+	int const dir,
+	EGLPNUM_TYPENAME_ratio_res * const rs),
+  EGLPNUM_TYPENAME_ILLratio_dI_test (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	int const lindex,
+	int const lvstat,
+	EGLPNUM_TYPENAME_ratio_res * const rs),
+  EGLPNUM_TYPENAME_ILLratio_dII_test (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	/*int const lindex,*/
+	int const lvstat,
+	EGLPNUM_TYPENAME_ratio_res * const rs),
+  EGLPNUM_TYPENAME_ILLratio_longdII_test (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	int const lindex,
+	int const lvstat,
+	EGLPNUM_TYPENAME_ratio_res * const rs),
+  EGLPNUM_TYPENAME_ILLratio_pivotin_test (
+	EGLPNUM_TYPENAME_lpinfo * const lp,
+	int *const rlist,
+	int const rcnt,
+	EGLPNUM_TYPENAME_ratio_res * const rs);
+
+#endif /* EGLPNUM_TYPENAME___RATIO_H */
diff --git a/qsopt_ex/rawlp.c b/qsopt_ex/rawlp.c
new file mode 100644
index 0000000..d0472bc
--- /dev/null
+++ b/qsopt_ex/rawlp.c
@@ -0,0 +1,1765 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: rawlp.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+/****************************************************************************/
+/* DataStructure and routines to deal with raw lp information as read       */
+/* from mps or lp files.                                                    */
+/****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <math.h>
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "eg_lpnum.h"
+#include "eg_io.h"
+
+#include "sortrus_EGLPNUM_TYPENAME.h"
+#include "rawlp_EGLPNUM_TYPENAME.h"
+#include "allocrus.h"
+#include "except.h"
+#include "util.h"
+
+
+static int TRACE = 0;
+
+ILL_PTRWORLD_ROUTINES (EGLPNUM_TYPENAME_colptr, colptralloc, colptr_bulkalloc, colptrfree)
+ILL_PTRWORLD_LISTFREE_ROUTINE (EGLPNUM_TYPENAME_colptr, colptr_listfree, colptrfree)
+ILL_PTRWORLD_LEAKS_ROUTINE (EGLPNUM_TYPENAME_colptr, colptr_check_leaks, this_val, int)
+		 const int EGLPNUM_TYPENAME_ILL_SOS_TYPE1 = 1;
+		 const int EGLPNUM_TYPENAME_ILL_SOS_TYPE2 = 2;
+
+		 static void ILLprt_EGlpNum (
+	FILE * f,
+	EGLPNUM_TYPE * d)
+{
+	if (EGLPNUM_TYPENAME_EGlpNumIsLeq (EGLPNUM_TYPENAME_ILL_MAXDOUBLE, *d))
+	{
+		fprintf (f, "MAX_DOUBLE");
+	}
+	else
+	{
+		if (EGLPNUM_TYPENAME_EGlpNumIsLeq (*d, EGLPNUM_TYPENAME_ILL_MINDOUBLE))
+		{
+			fprintf (f, "-MAX_DOUBLE");
+		}
+		else
+		{
+			fprintf (f, "%f", EGLPNUM_TYPENAME_EGlpNumToLf (*d));
+		}
+	}
+}
+
+static int ILLraw_check_bounds (
+	EGLPNUM_TYPENAME_rawlpdata * lp);
+
+void EGLPNUM_TYPENAME_ILLinit_rawlpdata (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	EGLPNUM_TYPENAME_qserror_collector * collector)
+{
+	if (lp)
+	{
+		lp->name = 0;
+		lp->ncols = 0;
+		lp->nrows = 0;
+		lp->cols = 0;
+		lp->rowsense = 0;
+		lp->rhsname = 0;
+		lp->rhs = 0;
+		lp->rhsind = 0;
+		lp->rangesname = 0;
+		lp->rangesind = 0;
+		lp->ranges = 0;
+		lp->boundsname = 0;
+		lp->lbind = 0;
+		lp->ubind = 0;
+		lp->lower = 0;
+		lp->upper = 0;
+		lp->intmarker = 0;
+		lp->colsize = 0;
+		lp->sensesize = 0;
+		lp->intsize = 0;
+		lp->rhssize = 0;
+		lp->refrow = NULL;
+		lp->is_sos_size = 0;
+		lp->is_sos_member = NULL;
+		lp->nsos_member = 0;
+		lp->sos_weight_size = 0;
+		lp->sos_weight = NULL;
+		lp->sos_col_size = 0;
+		lp->sos_col = NULL;
+		lp->nsos = 0;
+		lp->sos_setsize = 0;
+		lp->sos_set = NULL;
+		ILLsymboltab_init (&lp->coltab);
+		ILLsymboltab_init (&lp->rowtab);
+		lp->objindex = -1;
+		lp->objsense = EGLPNUM_TYPENAME_ILL_MIN;
+		lp->refrowind = -1;					/* undefined */
+		ILLptrworld_init (&lp->ptrworld);
+		lp->error_collector = collector;
+	}
+}
+
+void EGLPNUM_TYPENAME_ILLraw_clear_matrix (
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	int i;
+	EGLPNUM_TYPENAME_colptr *next, *curr;
+
+	if ((lp != NULL) && (lp->cols != NULL))
+	{
+		for (i = 0; i < lp->ncols; i++)
+		{
+			{
+				curr = lp->cols[i];
+				while (curr)
+				{
+					next = curr->next;
+					EGLPNUM_TYPENAME_EGlpNumClearVar ((curr->coef));
+					colptrfree (&(lp->ptrworld), curr);
+					curr = next;
+				}
+			}
+			//colptr_listfree (&lp->ptrworld, lp->cols[i]);
+			lp->cols[i] = NULL;
+		}
+	}
+}
+
+void EGLPNUM_TYPENAME_ILLfree_rawlpdata (
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	int total, onlist;
+	EGLPNUM_TYPENAME_colptr *next, *curr;
+
+	if (lp)
+	{
+		ILL_IFFREE (lp->name, char);
+
+		ILLsymboltab_free (&lp->rowtab);
+		ILLsymboltab_free (&lp->coltab);
+		ILL_IFFREE (lp->rowsense, char);
+
+		EGLPNUM_TYPENAME_ILLraw_clear_matrix (lp);
+		ILL_IFFREE (lp->cols, EGLPNUM_TYPENAME_colptr *);
+		{
+			curr = lp->ranges;
+			while (curr)
+			{
+				next = curr->next;
+				EGLPNUM_TYPENAME_EGlpNumClearVar ((curr->coef));
+				colptrfree (&(lp->ptrworld), curr);
+				curr = next;
+			}
+		}
+		//colptr_listfree (&lp->ptrworld, lp->ranges);
+		if (colptr_check_leaks (&lp->ptrworld, &total, &onlist))
+		{
+			QSlog("WARNING: %d outstanding colptrs", total - onlist);
+		}
+		ILLptrworld_delete (&lp->ptrworld);
+		ILL_IFFREE (lp->rhsname, char);
+
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->rhs);
+		ILL_IFFREE (lp->rhsind, char);
+		ILL_IFFREE (lp->rangesname, char);
+		ILL_IFFREE (lp->rangesind, char);
+		ILL_IFFREE (lp->boundsname, char);
+		ILL_IFFREE (lp->lbind, char);
+		ILL_IFFREE (lp->ubind, char);
+
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->lower);
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->upper);
+		ILL_IFFREE (lp->intmarker, char);
+		ILL_IFFREE (lp->refrow, char);
+		ILL_IFFREE (lp->is_sos_member, int);
+
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->sos_weight);
+		ILL_IFFREE (lp->sos_col, int);
+
+		ILL_IFFREE (lp->sos_set, EGLPNUM_TYPENAME_sosptr);
+		EGLPNUM_TYPENAME_ILLinit_rawlpdata (lp, NULL);
+	}
+}
+
+const char *EGLPNUM_TYPENAME_ILLraw_rowname (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	int i)
+{
+	const char *name = NULL;
+
+	ILL_FAILfalse_no_rval ((i >= 0) && (i < lp->nrows), "index out of range");
+	ILL_FAILfalse_no_rval (lp->nrows == lp->rowtab.tablesize,
+												 "tab and lp must be in synch");
+	name = ILLsymboltab_get (&lp->rowtab, i);
+CLEANUP:
+	return name;
+}
+const char *EGLPNUM_TYPENAME_ILLraw_colname (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	int i)
+{
+	const char *name = NULL;
+
+	ILL_FAILfalse_no_rval ((i >= 0) && (i < lp->ncols), "index out of range");
+	ILL_FAILfalse_no_rval (lp->ncols == lp->coltab.tablesize,
+												 "tab and lp must be in synch");
+	name = ILLsymboltab_get (&lp->coltab, i);
+CLEANUP:
+	return name;
+}
+
+int EGLPNUM_TYPENAME_ILLraw_add_col (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	const char *name,
+	int intmarker)
+{
+	int rval = 0;
+	int pindex, hit;
+
+	rval = ILLsymboltab_register (&lp->coltab, name, -1, &pindex, &hit);
+	rval = rval || hit;
+	ILL_CLEANUP_IF (rval);
+	if (lp->ncols >= lp->colsize)
+	{
+		lp->colsize *= 1.3;
+		lp->colsize += 1000;
+		if (lp->colsize < lp->ncols + 1)
+			lp->colsize = lp->ncols + 1;
+		lp->cols = EGrealloc (lp->cols, lp->colsize * sizeof (EGLPNUM_TYPENAME_colptr *));
+		//rval = rval || ILLutil_reallocrus_scale (&lp->cols,
+		//                                         &lp->colsize, lp->ncols + 1, 1.3,
+		//                                         sizeof (EGLPNUM_TYPENAME_colptr *));
+	}
+	if (lp->ncols >= lp->intsize)
+	{
+		lp->intsize *= 1.3;
+		lp->intsize += 1000;
+		if (lp->intsize < lp->ncols + 1)
+			lp->intsize = lp->ncols + 1;
+		lp->intmarker = EGrealloc (lp->intmarker, lp->intsize * sizeof (char));
+		//rval = rval || ILLutil_reallocrus_scale ((void **) &lp->intmarker,
+		//                                         &lp->intsize, lp->ncols + 1,
+		//                                         1.3, sizeof (char));
+	}
+	if (lp->ncols >= lp->is_sos_size)
+	{
+		lp->is_sos_size *= 1.3;
+		lp->is_sos_size += 1000;
+		if (lp->is_sos_size < lp->ncols + 1)
+			lp->is_sos_size = lp->ncols + 1;
+		lp->is_sos_member = EGrealloc (lp->is_sos_member,
+																	 sizeof (int) * lp->is_sos_size);
+		//rval = rval || ILLutil_reallocrus_scale ((void **) &lp->is_sos_member,
+		//                                         &lp->is_sos_size, lp->ncols + 1,
+		//                                         1.3, sizeof (int));
+	}
+	ILL_CLEANUP_IF (rval);
+	lp->cols[lp->ncols] = 0;
+	lp->is_sos_member[lp->ncols] = -1;
+	lp->intmarker[lp->ncols] = intmarker;
+	lp->ncols++;
+CLEANUP:
+	ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLraw_add_col");
+}
+
+int EGLPNUM_TYPENAME_ILLraw_init_rhs (
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	int i, rval = 0;
+
+	ILL_FAILfalse (lp->rhsind == NULL, "Should be called exactly once");
+	if (lp->nrows > 0)
+	{
+		ILL_SAFE_MALLOC (lp->rhsind, lp->nrows, char);
+
+		for (i = 0; i < lp->nrows; i++)
+		{
+			lp->rhsind[i] = (char) 0;
+		}
+	}
+CLEANUP:
+	ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLraw_init_rhs");
+}
+
+int EGLPNUM_TYPENAME_ILLraw_init_ranges (
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	int i, rval = 0;
+
+	ILL_FAILfalse (lp->rangesind == NULL, "Should be called exactly once");
+	if (lp->nrows > 0)
+	{
+		ILL_SAFE_MALLOC (lp->rangesind, lp->nrows, char);
+
+		for (i = 0; i < lp->nrows; i++)
+		{
+			lp->rangesind[i] = (char) 0;
+		}
+	}
+CLEANUP:
+	ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLraw_init_ranges");
+}
+
+int EGLPNUM_TYPENAME_ILLraw_add_col_coef (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	int colind,
+	int rowind,
+	EGLPNUM_TYPE coef)
+{
+	EGLPNUM_TYPENAME_colptr *cp = EGLPNUM_TYPENAME_ILLcolptralloc (&lp->ptrworld);
+
+	if (!cp)
+	{
+		return 1;
+	}
+	cp->this_val = rowind;
+	EGLPNUM_TYPENAME_EGlpNumCopy (cp->coef, coef);
+	cp->next = lp->cols[colind];
+	lp->cols[colind] = cp;
+	return 0;
+}
+
+
+int EGLPNUM_TYPENAME_ILLraw_add_ranges_coef (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	int rowind,
+	EGLPNUM_TYPE coef)
+{
+	EGLPNUM_TYPENAME_colptr *cp = EGLPNUM_TYPENAME_ILLcolptralloc (&lp->ptrworld);
+
+	if (!cp)
+	{
+		return 1;
+	}
+	cp->this_val = rowind;
+	EGLPNUM_TYPENAME_EGlpNumCopy (cp->coef, coef);
+	cp->next = lp->ranges;
+	lp->ranges = cp;
+	lp->rangesind[rowind] = (char) 1;
+	return 0;
+}
+
+int EGLPNUM_TYPENAME_ILLraw_add_sos (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	int tp)
+{
+	int rval = 0;
+	EGLPNUM_TYPENAME_sosptr *sos, *bef;
+
+	if (lp->nsos >= lp->sos_setsize)
+	{
+		lp->sos_setsize *= 1.3;
+		lp->sos_setsize += 1000;
+		if (lp->sos_setsize < lp->nsos + 1)
+			lp->sos_setsize = lp->nsos + 1;
+		lp->sos_set = EGrealloc (lp->sos_set, sizeof (EGLPNUM_TYPENAME_sosptr *) * lp->sos_setsize);
+		//if (ILLutil_reallocrus_scale ((void **) &lp->sos_set,
+		//                              &lp->sos_setsize, lp->nsos + 1, 1.3,
+		//                              sizeof (EGLPNUM_TYPENAME_sosptr *)))
+		//{
+		//  ILL_CLEANUP_IF (rval);
+		//}
+	}
+	sos = lp->sos_set + lp->nsos;
+	sos->nelem = 0;
+	sos->type = tp;
+	if (lp->nsos == 0)
+	{
+		sos->first = 0;
+	}
+	else
+	{
+		bef = &(lp->sos_set[lp->nsos - 1]);
+		sos->first = bef->first + bef->nelem;
+	}
+	lp->nsos++;
+//CLEANUP:
+	ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLraw_add_sos");
+}
+
+int EGLPNUM_TYPENAME_ILLraw_is_mem_other_sos (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	int colind)
+{
+	return (lp->is_sos_member[colind] >= 0) &&
+		(lp->is_sos_member[colind] != (lp->nsos - 1));
+}
+
+int EGLPNUM_TYPENAME_ILLraw_add_sos_member (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	int colind)
+{
+	int rval = 0;
+
+	ILL_FAILfalse (lp->nsos > 0, "we should have called EGLPNUM_TYPENAME_ILLraw_add_sos earlier");
+	ILL_FAILtrue (EGLPNUM_TYPENAME_ILLraw_is_mem_other_sos (lp, colind),
+								"colind is member of another sos set");
+
+	if (lp->is_sos_member[colind] == -1)
+	{
+		if (lp->nsos_member >= lp->sos_weight_size)
+		{
+			lp->sos_weight_size *= 1.3;
+			lp->sos_weight_size += 1000;
+			if (lp->sos_weight_size < lp->nsos_member + 1)
+				lp->sos_weight_size = lp->nsos_member + 1;
+			lp->sos_weight = EGrealloc (lp->sos_weight,
+																	lp->sos_weight_size * sizeof (double));
+			//if (ILLutil_reallocrus_scale ((void **) &lp->sos_weight,
+			//                              &lp->sos_weight_size,
+			//                              lp->nsos_member + 1, 1.3, sizeof (double)))
+			//{
+			//  ILL_CLEANUP_IF (rval);
+			//}
+		}
+		if (lp->nsos_member >= lp->sos_col_size)
+		{
+			lp->sos_col_size *= 1.3;
+			lp->sos_col_size += 1000;
+			if (lp->sos_col_size < lp->nsos_member + 1)
+				lp->sos_col_size = lp->nsos_member + 1;
+			lp->sos_col = EGrealloc (lp->sos_col, sizeof (int) * lp->sos_col_size);
+			//if (ILLutil_reallocrus_scale ((void **) &lp->sos_col,
+			//                              &lp->sos_col_size,
+			//                              lp->nsos_member + 1, 1.3, sizeof (int)))
+			//{
+			//  ILL_CLEANUP_IF (rval);
+			//}
+		}
+		lp->sos_col[lp->nsos_member] = colind;
+		lp->sos_set[lp->nsos - 1].nelem++;
+		lp->is_sos_member[colind] = lp->nsos - 1;
+		lp->nsos_member++;
+	}
+CLEANUP:
+	ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLraw_add_sos_member");
+}
+
+
+int EGLPNUM_TYPENAME_ILLraw_add_row (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	const char *name,
+	int sense,
+	const EGLPNUM_TYPE rhs)
+{
+	int pindex, hit, rval = 0;
+
+	rval = ILLsymboltab_register (&lp->rowtab, name, -1, &pindex, &hit);
+	rval = rval || hit;
+	ILL_CLEANUP_IF (rval);
+	if (lp->nrows >= lp->sensesize)
+	{
+		lp->sensesize *= 1.3;
+		lp->sensesize += 1000;
+		if (lp->sensesize < lp->nrows + 1)
+			lp->sensesize = lp->nrows + 1;
+		lp->rowsense = EGrealloc (lp->rowsense, sizeof (char) * lp->sensesize);
+		//if (ILLutil_reallocrus_scale ((void **) &lp->rowsense,
+		//                              &lp->sensesize, lp->nrows + 1,
+		//                              1.3, sizeof (char)))
+		//{
+		//  ILL_CLEANUP_IF (rval);
+		//}
+	}
+	if (lp->nrows >= lp->rhssize)
+	{
+		if (lp->rhssize + 1000 < (lp->nrows + 1) * 1.3)
+			lp->rhssize = (lp->nrows + 1) * 1.3;
+		else
+			lp->rhssize += 1000;
+		EGLPNUM_TYPENAME_EGlpNumReallocArray (&(lp->rhs), lp->rhssize);
+	}
+	lp->rowsense[lp->nrows] = sense;
+	EGLPNUM_TYPENAME_EGlpNumCopy (lp->rhs[lp->nrows], rhs);
+	lp->nrows++;
+
+CLEANUP:
+	ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLraw_add_row");
+}
+
+static int ILLcheck_rawlpdata (
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	int i, col, rval = 0;
+	int si, *perm = NULL;
+	const char *c1, *c2;
+	EGLPNUM_TYPENAME_sosptr *set;
+
+	ILL_FAILfalse (lp, "lp must not be NULL");
+
+	/* check    
+	 *          *) that there is at least one variable 
+	 *          *) that the weights in all SOS sets are distinct 
+	 *          *) all sos members are non integer variables     
+	 *          *) sos set members have distint weights 
+	 *          *) objindex is not -1
+	 *          *) INVARIANT: rowname[objindex] != NULL
+	 *          *) INVARIANT: upper/lower arrays are filled in 
+	 *          *) INVARIANT: if col or rownames != NULL then 
+	 *                        all their elements are not NULL
+	 */
+	if (lp->ncols < 1)
+	{
+		return EGLPNUM_TYPENAME_ILLdata_error (lp->error_collector, "There are no variables.");
+	}
+	if (lp->objindex == -1)
+	{
+		return EGLPNUM_TYPENAME_ILLdata_error (lp->error_collector, "There is no objective fct.");
+	}
+	ILL_FAILfalse (EGLPNUM_TYPENAME_ILLraw_rowname (lp, lp->objindex) != NULL,
+								 "must have objective name");
+	if (lp->nsos_member > 1)
+	{
+		ILL_SAFE_MALLOC (perm, lp->nsos_member, int);
+
+		for (si = 0; si < lp->nsos; si++)
+		{
+			set = lp->sos_set + si;
+			for (i = 0; i < set->nelem; i++)
+			{
+				col = lp->sos_col[set->first + i];
+				if (lp->intmarker[col])
+				{
+					rval = EGLPNUM_TYPENAME_ILLdata_error (lp->error_collector,
+																"SOS set member \"%s\" is an %s.\n",
+																EGLPNUM_TYPENAME_ILLraw_colname (lp, col),
+																"integer/binary variable");
+				}
+			}
+			if (set->nelem > 1)
+			{
+				for (i = 0; i < set->nelem; i++)
+				{
+					perm[i] = set->first + i;
+				}
+				EGLPNUM_TYPENAME_ILLutil_EGlpNum_perm_quicksort (perm, lp->sos_weight, set->nelem);
+				for (i = 1; i < set->nelem; i++)
+				{
+					if (EGLPNUM_TYPENAME_EGlpNumIsEqqual
+							(lp->sos_weight[perm[i - 1]], lp->sos_weight[perm[i]]))
+					{
+						c1 = EGLPNUM_TYPENAME_ILLraw_colname (lp, lp->sos_col[perm[i]]);
+						c2 = EGLPNUM_TYPENAME_ILLraw_colname (lp, lp->sos_col[perm[i - 1]]);
+						EGLPNUM_TYPENAME_ILLdata_error (lp->error_collector,
+													 "\"%s\" and \"%s\" both have %s %f.\n", c1, c2,
+													 "SOS weight", lp->sos_weight[perm[i]]);
+						rval = 1;
+					}
+				}
+			}
+		}
+	}
+	for (i = 0; i < lp->ncols; i++)
+	{
+		ILL_CHECKnull (EGLPNUM_TYPENAME_ILLraw_colname (lp, i), "There is a NULL col name");
+	}
+	for (i = 0; i < lp->nrows; i++)
+	{
+		ILL_CHECKnull (EGLPNUM_TYPENAME_ILLraw_rowname (lp, i), "There is a NULL row name");
+	}
+	ILL_FAILtrue ((lp->upper == NULL) | (lp->lower == NULL),
+								"Upper/Lower arrays must be filled in.");
+
+	rval += ILLraw_check_bounds (lp);
+CLEANUP:
+	ILL_IFFREE (perm, int);
+
+	ILL_RESULT (rval, "ILLcheck_rawlpdata");
+}
+
+int EGLPNUM_TYPENAME_ILLraw_init_bounds (
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	int i, rval = 0;
+
+	ILL_FAILfalse (lp->upper == NULL, "Should be called exactly once");
+	ILL_FAILfalse (lp->lower == NULL, "Should be called exactly once");
+	ILL_FAILfalse (lp->lbind == NULL, "Should be called exactly once");
+	ILL_FAILfalse (lp->ubind == NULL, "Should be called exactly once");
+	lp->upper = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->ncols);
+	lp->lower = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->ncols);
+	ILL_SAFE_MALLOC (lp->lbind, lp->ncols, char);
+	ILL_SAFE_MALLOC (lp->ubind, lp->ncols, char);
+
+	for (i = 0; i < lp->ncols; i++)
+	{
+		lp->lbind[i] = (char) 0;
+		lp->ubind[i] = (char) 0;
+		EGLPNUM_TYPENAME_EGlpNumZero (lp->lower[i]);
+	}
+CLEANUP:
+	ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLraw_init_bounds");
+}
+
+const char *EGLPNUM_TYPENAME_ILLraw_set_lowerBound (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	int i,
+	EGLPNUM_TYPE bnd)
+{
+	ILL_FAILtrue_no_rval (i >= lp->ncols, "proper colind");
+	if (lp->lbind[i])
+	{
+		return "Using previous bound definition.";
+	}
+	EGLPNUM_TYPENAME_EGlpNumCopy (lp->lower[i], bnd);
+	lp->lbind[i] = (char) 1;
+CLEANUP:
+	return NULL;
+}
+
+const char *EGLPNUM_TYPENAME_ILLraw_set_upperBound (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	int i,
+	EGLPNUM_TYPE bnd)
+{
+	ILL_FAILtrue_no_rval (i >= lp->ncols, "proper colind");
+	if (lp->ubind[i])
+	{
+		return "Using previous bound definition.";
+	}
+	EGLPNUM_TYPENAME_EGlpNumCopy (lp->upper[i], bnd);
+	lp->ubind[i] = (char) 1;
+	if (!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (lp->lower[i]) &&
+			!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (bnd))
+	{
+		return "0.0 upper bound fixes variable.";
+	}
+CLEANUP:
+	return NULL;
+}
+
+const char *EGLPNUM_TYPENAME_ILLraw_set_fixedBound (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	int i,
+	EGLPNUM_TYPE bnd)
+{
+	ILL_FAILtrue_no_rval (i >= lp->ncols, "proper colind");
+	if (lp->ubind[i] || lp->lbind[i])
+	{
+		return "Using previous bound definition.";
+	}
+	EGLPNUM_TYPENAME_EGlpNumCopy (lp->lower[i], bnd);
+	lp->lbind[i] = (char) 1;
+	EGLPNUM_TYPENAME_EGlpNumCopy (lp->upper[i], bnd);
+	lp->ubind[i] = (char) 1;
+CLEANUP:
+	return NULL;
+}
+
+const char *EGLPNUM_TYPENAME_ILLraw_set_unbound (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	int i)
+{
+	ILL_FAILtrue_no_rval (i >= lp->ncols, "proper colind");
+	if (lp->lbind[i] || lp->ubind[i])
+	{
+		return "Using previous bound definition.";
+	}
+	EGLPNUM_TYPENAME_EGlpNumCopy (lp->lower[i], EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+	EGLPNUM_TYPENAME_EGlpNumCopy (lp->upper[i], EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+	lp->lbind[i] = 1;
+	lp->ubind[i] = 1;
+CLEANUP:
+	return NULL;
+}
+
+const char *EGLPNUM_TYPENAME_ILLraw_set_binaryBound (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	int i)
+{
+	ILL_FAILtrue_no_rval (i >= lp->ncols, "proper colind");
+	if (lp->lbind[i] || lp->ubind[i])
+	{
+		return "Using previous bound definition.";
+	}
+	EGLPNUM_TYPENAME_EGlpNumZero (lp->lower[i]);
+	EGLPNUM_TYPENAME_EGlpNumOne (lp->upper[i]);
+	lp->lbind[i] = 1;
+	lp->ubind[i] = 1;
+CLEANUP:
+	return NULL;
+}
+
+int EGLPNUM_TYPENAME_ILLraw_fill_in_bounds (
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	int rval = 0, i;
+
+	if (lp->lbind == NULL)
+	{
+		EGLPNUM_TYPENAME_ILLraw_init_bounds (lp);
+	}
+	ILL_FAILtrue (lp->upper == NULL, "must all be there now");
+	ILL_FAILtrue (lp->lower == NULL, "must all be there now");
+	ILL_FAILtrue (lp->lbind == NULL, "must all be there now");
+	ILL_FAILtrue (lp->ubind == NULL, "must all be there now");
+	for (i = 0; i < lp->ncols; i++)
+	{
+		if (!lp->lbind[i])
+		{
+			if (lp->ubind[i] && EGLPNUM_TYPENAME_EGlpNumIsLessZero (lp->upper[i]))
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (lp->lower[i], EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+			}
+		}
+		if (!lp->ubind[i])
+		{
+			/* int vars without bounds are binary                        */
+			/* all, also int vars                                        */
+			/*          with explicit lower bound 0.0 are in [0.0,+inf]  */
+			if (((lp->intmarker != NULL) && lp->intmarker[i]) && !lp->lbind[i])
+			{
+				EGLPNUM_TYPENAME_EGlpNumOne (lp->upper[i]);
+			}
+			else
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (lp->upper[i], EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+			}
+		}
+	}
+
+CLEANUP:
+	if (rval)
+	{
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->lower);
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->upper);
+	}
+	ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLraw_fill_in_bounds");
+}
+
+static int ILLraw_check_bounds (
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	int rval = 0, i;
+
+	ILL_FAILtrue (lp->upper == NULL, "must all be there now");
+	ILL_FAILtrue (lp->lower == NULL, "must all be there now");
+	ILL_FAILtrue (lp->lbind == NULL, "must all be there now");
+	ILL_FAILtrue (lp->ubind == NULL, "must all be there now");
+	for (i = 0; i < lp->ncols; i++)
+	{
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (lp->upper[i], lp->lower[i]))
+		{
+			rval += EGLPNUM_TYPENAME_ILLdata_error (lp->error_collector,
+														 "Lower bound is bigger than %s \"%s\".\n",
+														 "upper bound for", EGLPNUM_TYPENAME_ILLraw_colname (lp, i));
+		}
+	}
+	ILL_RESULT (rval, "ILLraw_check_bounds");
+CLEANUP:
+	ILL_RETURN (rval, "ILLraw_check_bounds");
+}
+
+int EGLPNUM_TYPENAME_ILLraw_first_nondefault_bound (
+	EGLPNUM_TYPENAME_ILLlpdata * lp)
+{
+	int ri = lp->nstruct, i;
+
+	ILL_FAILtrue_no_rval (lp->lower == NULL || lp->upper == NULL,
+												"Should not call write_bounds when lower or upper are NULL");
+	for (ri = 0; ri < lp->nstruct; ri++)
+	{
+		i = lp->structmap[ri];
+		if (!EGLPNUM_TYPENAME_ILLraw_default_lower (lp, i) || !EGLPNUM_TYPENAME_ILLraw_default_upper (lp, i, ri))
+			break;
+	}
+CLEANUP:
+	return ri;
+}
+
+int EGLPNUM_TYPENAME_ILLraw_default_lower (
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	int i)
+{
+	ILL_FAILtrue_no_rval (lp->lower == NULL || lp->upper == NULL,
+												"Should not call write_bounds when lower or upper are NULL");
+	ILL_FAILfalse_no_rval (lp->ncols > i, "i is not col index");
+	if (!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (lp->lower[i]) &&
+			!EGLPNUM_TYPENAME_EGlpNumIsLessZero (lp->upper[i]))
+	{
+		return 1;
+	}
+	if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (lp->lower[i], EGLPNUM_TYPENAME_ILL_MINDOUBLE) &&
+			EGLPNUM_TYPENAME_EGlpNumIsLessZero (lp->upper[i]))
+	{
+		return 1;
+	}
+CLEANUP:
+	return 0;
+}
+
+int EGLPNUM_TYPENAME_ILLraw_default_upper (
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	int i, 
+	int ri)
+{
+	int isInt;
+
+	ILL_FAILtrue_no_rval (lp->lower == NULL || lp->upper == NULL,
+												"Should not call write_bounds when lower or upper are NULL");
+	ILL_FAILfalse_no_rval (lp->ncols >= i, "i is not col index");
+	isInt = (lp->intmarker != NULL) && lp->intmarker[ri];
+	if (isInt)
+	{
+		if (!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (lp->lower[i]))
+		{
+			return (EGLPNUM_TYPENAME_EGlpNumIsEqqual (lp->upper[i], EGLPNUM_TYPENAME_oneLpNum));
+		}
+	}
+
+	if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (lp->upper[i], EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+	{
+		return 1;
+	}
+CLEANUP:
+	return 0;
+}
+
+int EGLPNUM_TYPENAME_ILLraw_fill_in_rownames (
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	int i, rval = 0;
+	char uname2[ILL_namebufsize];
+	ILLsymboltab *rowtab;
+	char first = 1;
+
+	rowtab = &lp->rowtab;
+	ILL_FAILtrue (lp->nrows != rowtab->tablesize, "must have same #entries");
+	for (i = 0; (rval == 0) && i < lp->nrows; i++)
+	{
+		if (ILLsymboltab_get (rowtab, i) == NULL)
+		{
+			if (first)
+			{
+				EGLPNUM_TYPENAME_ILLdata_warn (lp->error_collector,
+											"Generating names for unnamed rows.");
+				first = 0;
+			}
+
+			ILLsymboltab_unique_name (rowtab, i, "c", uname2);
+			rval = ILLsymboltab_rename (rowtab, i, uname2);
+			ILL_CLEANUP_IF (rval);
+		}
+	}
+CLEANUP:
+	ILL_RESULT (rval, "EGLPNUM_TYPENAME_ILLraw_fill_in_rownames");
+}
+
+static int whichColsAreUsed (
+	EGLPNUM_TYPENAME_rawlpdata * raw,
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	int *colindex)
+{
+	int rval = 0;
+	int i, objind = raw->objindex;
+	EGLPNUM_TYPENAME_colptr *cp;
+	char *colUsed = NULL;
+
+	/* colUsed[i]  variable raw->colnames[i] is used in obj fct 
+	 * and/or equation(s) */
+	ILL_SAFE_MALLOC (colUsed, raw->ncols, char);
+
+	for (i = 0; i < raw->ncols; i++)
+	{
+		colUsed[i] = 0;
+	}
+	for (i = 0; i < raw->ncols; i++)
+	{
+		for (cp = raw->cols[i]; cp; cp = cp->next)
+		{
+			if ((cp->this_val == objind) || (raw->rowsense[cp->this_val] != 'N'))
+			{
+				colUsed[i] = 1;
+				break;
+			}
+		}
+	}
+
+	/* colindex[i] = -1 for undefined, 0, 1, ... lp->ncol-1 
+	 * lp->ncols <= raw->ncols */
+	for (i = 0; i < raw->ncols; i++)
+	{
+		if (colUsed[i])
+		{
+			colindex[i] = lp->ncols++;
+		}
+		else
+		{
+			colindex[i] = -1;
+			EGLPNUM_TYPENAME_ILLdata_warn (raw->error_collector,
+										"\"%s\" is used in non objective 'N' rows only.",
+										EGLPNUM_TYPENAME_ILLraw_colname (raw, i));
+		}
+	}
+	if (lp->ncols < 1)
+	{
+		rval = EGLPNUM_TYPENAME_ILLdata_error (raw->error_collector, "There are no variables.");
+		ILL_CLEANUP_IF (rval);
+	}
+CLEANUP:
+	ILL_IFFREE (colUsed, char);
+
+	ILL_RESULT (rval, "whichColsAreUsed");
+}
+
+static int whichRowsAreUsed (
+	EGLPNUM_TYPENAME_rawlpdata * raw,
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	int *rowindex)
+{
+	int i, rval = 0;
+
+	/* only use non 'N' rows */
+	for (i = 0; i < raw->nrows; i++)
+	{
+		if (raw->rowsense[i] != 'N')
+		{
+			rowindex[i] = lp->nrows++;
+		}
+		else
+		{
+			rowindex[i] = -1;
+		}
+	}
+	if (lp->nrows == 0)
+	{
+		rval = EGLPNUM_TYPENAME_ILLdata_error (raw->error_collector, "There are no constraints.");
+	}
+	ILL_RESULT (rval, "whichRowsAreUsed");
+}
+
+
+static int transferObjective (
+	EGLPNUM_TYPENAME_rawlpdata * raw,
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	int *colindex)
+{
+	int rval = 0, i, ci, objind = raw->objindex;
+	EGLPNUM_TYPENAME_colptr *cp;
+	int *coefWarn = NULL;
+
+	/* transfer objective fct */
+	lp->obj = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->ncols);
+	ILL_SAFE_MALLOC (coefWarn, lp->ncols, int);
+
+	for (i = 0; i < lp->ncols; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumZero (lp->obj[i]);
+		coefWarn[i] = 0;
+	}
+	for (i = 0; i < raw->ncols; i++)
+	{
+		for (cp = raw->cols[i]; cp; cp = cp->next)
+		{
+			if (cp->this_val == objind)
+			{
+				ci = colindex[i];
+				TESTG ((rval =
+								(ci < 0
+								 || ci >= lp->ncols)), CLEANUP, "ci %d is out of range [0,%d[",
+							 ci, lp->ncols);
+				ILL_FAILfalse (ci != -1,
+											 "all vars in obj fct should be marked as useful");
+				coefWarn[ci]++;
+				if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (cp->coef))
+					EGLPNUM_TYPENAME_EGlpNumAddTo (lp->obj[ci], cp->coef);
+				if (coefWarn[ci] == 2)
+				{
+					EGLPNUM_TYPENAME_ILLdata_warn (raw->error_collector,
+												"Multiple coefficients for \"%s\" in %s.",
+												EGLPNUM_TYPENAME_ILLraw_colname (raw, i), "objective function");
+				}
+			}
+		}
+	}
+CLEANUP:
+	ILL_IFFREE (coefWarn, int);
+
+	ILL_RETURN (rval, "transferObjective");
+}
+
+static int transferColNamesLowerUpperIntMarker (
+	EGLPNUM_TYPENAME_rawlpdata * raw,
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	int *colindex)
+{
+	int i, ci, ind, pre, rval = 0;
+	int hasIntVar;
+	ILL_SAFE_MALLOC (lp->colnames, lp->ncols, char *);
+
+	if (raw->upper)
+		lp->upper = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->ncols);
+	if (raw->lower)
+		lp->lower = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->ncols);
+	ILL_SAFE_MALLOC (lp->intmarker, lp->ncols, char);
+
+	hasIntVar = 0;
+	for (i = 0; i < raw->ncols; i++)
+	{
+		ci = colindex[i];
+		if (ci != -1)
+		{
+			ILL_FAILfalse ((ci >= 0) && (ci < lp->ncols), "colindex problem");
+			ILL_UTIL_STR (lp->colnames[ci], EGLPNUM_TYPENAME_ILLraw_colname (raw, i));
+			rval = ILLsymboltab_register (&lp->coltab,
+																		lp->colnames[ci], -1, &ind, &pre);
+			ILL_FAILfalse ((rval == 0) && (ind == ci) && (pre == 0),
+										 "should have new entry");
+			if (raw->upper)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (lp->upper[ci], raw->upper[i]);
+			}
+			if (raw->lower)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (lp->lower[ci], raw->lower[i]);
+			}
+			lp->intmarker[ci] = raw->intmarker[i];
+			hasIntVar = hasIntVar || lp->intmarker[ci];
+			ILL_IFDOTRACE
+			{
+				if (lp->lower)
+				{
+					ILLprt_EGlpNum (stdout, &(lp->lower[ci]));
+					ILL_IFTRACE (" <= ");
+				}
+				ILL_IFTRACE ("%s", lp->colnames[ci]);
+				if (lp->upper)
+				{
+					ILL_IFTRACE (" <= ");
+					ILLprt_EGlpNum (stdout, &(lp->upper[ci]));
+				}
+				if (lp->intmarker[ci])
+				{
+					ILL_IFTRACE (" INTEGER ");
+				}
+				ILL_IFTRACE ("\n");
+			}
+		}
+	}
+	if (!hasIntVar)
+	{
+		ILL_IFFREE (lp->intmarker, char);
+	}
+CLEANUP:
+	ILL_RETURN (rval, "transferColNamesLowerUpperIntMarker");
+}
+
+static void safeRegister (
+	ILLsymboltab * tab,
+	const char *name,
+	int i)
+{
+	int ind, pre, rval;
+
+	rval = ILLsymboltab_register (tab, name, -1, &ind, &pre);
+	ILL_FAILfalse ((rval == 0) && (ind == i) && (pre == 0),
+								 "Pgming Error: should have new entry");
+CLEANUP:
+	return;
+}
+
+static int transferSenseRhsRowNames (
+	EGLPNUM_TYPENAME_rawlpdata * raw,
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	int *rowindex)
+{
+	int i, ri, rval = 0;
+	int objind = raw->objindex;
+
+	/* transfer sense/rhs/rownames */
+	if (lp->nrows > 0)
+	{
+		ILL_SAFE_MALLOC (lp->sense, lp->nrows, char);
+
+		lp->rhs = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+		ILL_SAFE_MALLOC (lp->rownames, lp->nrows, char *);
+
+		ILL_FAILfalse (EGLPNUM_TYPENAME_ILLraw_rowname (raw, raw->objindex), "NULL objname");
+		safeRegister (&lp->rowtab, EGLPNUM_TYPENAME_ILLraw_rowname (raw, raw->objindex), 0);
+
+		ri = 0;
+		for (i = 0; i < raw->nrows; i++)
+		{
+			ri = rowindex[i];
+			if (i == raw->refrowind)
+			{
+				ILL_UTIL_STR (lp->refrowname, EGLPNUM_TYPENAME_ILLraw_rowname (raw, i));
+				lp->refind = ri;
+			}
+			if (raw->rowsense[i] != 'N')
+			{
+				ILL_FAILfalse (EGLPNUM_TYPENAME_ILLraw_rowname (raw, i) != NULL,
+											 "all rownames should be non NULL");
+				ILL_UTIL_STR (lp->rownames[ri], EGLPNUM_TYPENAME_ILLraw_rowname (raw, i));
+				safeRegister (&lp->rowtab, lp->rownames[ri], ri + 1);
+				lp->sense[ri] = raw->rowsense[i];
+				EGLPNUM_TYPENAME_EGlpNumCopy (lp->rhs[ri], raw->rhs[i]);
+			}
+			else if (i == objind)
+			{
+				ILL_FAILfalse (lp->objname == NULL, "objname == NULL");
+				ILL_UTIL_STR (lp->objname, EGLPNUM_TYPENAME_ILLraw_rowname (raw, i));
+			}
+			else
+			{
+				/* unused 'N' row */
+			}
+		}
+		ILL_FAILfalse ((lp->nrows + 1) == lp->rowtab.tablesize,
+									 "problem with rowtab structure");
+	}
+CLEANUP:
+	ILL_RETURN (rval, "transferSenseRhsRowNames");
+}
+
+static int buildMatrix (
+	EGLPNUM_TYPENAME_rawlpdata * raw,
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	int *rowindex,
+	int *colindex)
+{
+	int i, ri, ci, k, nempty = 0, rval = 0;
+	int *nRowsUsed = 0;
+	int *coefSet = 0;
+	int *coefWarn = 0;
+	EGLPNUM_TYPENAME_ILLmatrix *A = &lp->A;
+	EGLPNUM_TYPENAME_colptr *cp = NULL;
+
+	/* put subjective fcts into matrix */
+	ILL_SAFE_MALLOC (A->matcnt, lp->ncols, int);
+	ILL_SAFE_MALLOC (A->matbeg, lp->ncols, int);
+	ILL_SAFE_MALLOC (nRowsUsed, lp->nrows, int);
+
+	ILL_SAFE_MALLOC (coefWarn, lp->ncols, int);
+
+	for (i = 0; i < lp->ncols; i++)
+	{
+		coefWarn[i] = 0;
+	}
+	for (i = 0; i < lp->nrows; i++)
+	{
+		nRowsUsed[i] = -1;
+	}
+	for (i = 0; i < raw->ncols; i++)
+	{
+		ci = colindex[i];
+		if (ci == -1)
+			continue;
+		k = 0;
+		for (cp = raw->cols[i]; cp; cp = cp->next)
+		{
+			ri = rowindex[cp->this_val];
+			if (ri >= 0)
+			{
+				if (nRowsUsed[ri] != i)
+				{
+					nRowsUsed[ri] = i;
+					k++;
+				}
+				else
+				{
+					if (!coefWarn[ci])
+					{
+						EGLPNUM_TYPENAME_ILLdata_warn (raw->error_collector,
+													"Multiple coefficients for \"%s\" %s.",
+													lp->colnames[i], "in a row");
+						coefWarn[ci] = 1;
+					}
+				}
+			}
+		}
+		A->matcnt[ci] = k;
+		A->matbeg[ci] = lp->nzcount + nempty;	/* mark empty cols */
+		lp->nzcount += k;
+		if (k == 0)
+			nempty++;
+	}
+
+	A->matrows = lp->nrows;
+	A->matcols = lp->ncols;
+	A->matcolsize = lp->ncols;
+	A->matsize = lp->nzcount + nempty + 1;
+	A->matfree = 1;
+	ILL_SAFE_MALLOC (A->matind, A->matsize, int);
+
+	A->matval = EGLPNUM_TYPENAME_EGlpNumAllocArray (A->matsize);
+	ILL_SAFE_MALLOC (coefSet, lp->nrows, int);
+
+	for (k = 0; k < lp->nrows; k++)
+	{
+		coefSet[k] = -1;
+	}
+
+	for (i = 0; i < raw->ncols; i++)
+	{
+		ci = colindex[i];
+		if (ci == -1)
+			continue;									/* unused variable */
+		k = A->matbeg[ci];
+		if (A->matcnt[ci] == 0)
+		{
+			A->matind[k] = 1;					/* Used in addcols and addrows */
+		}
+		else
+		{
+			for (cp = raw->cols[i]; cp; cp = cp->next)
+			{
+				ri = rowindex[cp->this_val];
+				if (ri >= 0)
+				{
+					if (coefSet[ri] == -1)
+					{
+						A->matind[k] = ri;
+						EGLPNUM_TYPENAME_EGlpNumCopy (A->matval[k], cp->coef);
+						coefSet[ri] = k;
+						k++;
+					}
+					else
+					{
+						EGLPNUM_TYPENAME_EGlpNumAddTo (A->matval[coefSet[ri]], cp->coef);
+					}
+				}
+			}
+			if (k != A->matbeg[ci] + A->matcnt[ci])
+			{
+				ILL_ERROR (rval, "problem with matrix");
+			}
+			for (k--; k >= A->matbeg[ci]; k--)
+			{
+				coefSet[A->matind[k]] = -1;
+			}
+		}
+	}
+	A->matind[lp->nzcount + nempty] = -1;
+CLEANUP:
+	ILL_IFFREE (nRowsUsed, int);
+	ILL_IFFREE (coefWarn, int);
+	ILL_IFFREE (coefSet, int);
+
+	ILL_RETURN (rval, "buildMatrix");
+}
+
+static int transferRanges (
+	EGLPNUM_TYPENAME_rawlpdata * raw,
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	int *rowindex)
+{
+	int i, ri, rval = 0;
+	EGLPNUM_TYPENAME_colptr *cp;
+
+		/*****************************************************/
+	/*                                                   */
+	/*  Interpretation of RANGE values in MPS files      */
+	/*                                                   */
+	/*    G    rhs           <= row <= rhs + |range|     */
+	/*    L    rhs - |range| <= row <= rhs               */
+	/*    E +  rhs           <= row <= rhs + range       */
+	/*    E -  rhs + range   <= row <= rhs               */
+	/*                                                   */
+	/*     - where + and - refer to the sign of range    */
+	/*       and the letters refer to sense of the row.  */
+	/*                                                   */
+	/*    We will store ranged rows as                   */
+	/*                                                   */
+	/*       rhs  <= row  <= rhs + range                 */
+	/*                                                   */
+		/*****************************************************/
+
+
+	lp->rangeval = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+	for (i = 0; i < lp->nrows; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumZero (lp->rangeval[i]);
+	}
+	for (cp = raw->ranges; cp; cp = cp->next)
+	{
+		i = cp->this_val;
+		ri = rowindex[cp->this_val];
+		switch (raw->rowsense[i])
+		{
+		case 'N':
+			EGLPNUM_TYPENAME_ILLdata_error (raw->error_collector, "No range for N-row.\n");
+			rval = 1;
+			goto CLEANUP;
+		case 'G':
+			lp->sense[ri] = 'R';
+			EGLPNUM_TYPENAME_EGlpNumCopyAbs (lp->rangeval[ri], cp->coef);
+			break;
+		case 'L':
+			lp->sense[ri] = 'R';
+			EGLPNUM_TYPENAME_EGlpNumCopyAbs (lp->rangeval[ri], cp->coef);
+			EGLPNUM_TYPENAME_EGlpNumSubTo (lp->rhs[ri], lp->rangeval[ri]);
+			break;
+		case 'E':
+			lp->sense[ri] = 'R';
+			if (!EGLPNUM_TYPENAME_EGlpNumIsLessZero (cp->coef))
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopy (lp->rangeval[ri], cp->coef);
+			}
+			else
+			{
+				EGLPNUM_TYPENAME_EGlpNumAddTo (lp->rhs[ri], cp->coef);
+				EGLPNUM_TYPENAME_EGlpNumCopyNeg (lp->rangeval[ri], cp->coef);
+			}
+			break;
+		}
+	}
+CLEANUP:
+	ILL_RETURN (rval, "transferRanges");
+}
+
+static int initStructmap (
+	EGLPNUM_TYPENAME_ILLlpdata * lp)
+{
+	int i, rval = 0;
+
+	/* all vars are structural */
+	ILL_SAFE_MALLOC (lp->structmap, lp->nstruct, int);
+
+	for (i = 0; i < lp->nstruct; i++)
+	{
+		lp->structmap[i] = i;
+	}
+
+CLEANUP:
+	ILL_RETURN (rval, "initStructmap");
+}
+
+static int buildSosInfo (
+	EGLPNUM_TYPENAME_rawlpdata * raw,
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	int *colindex)
+{
+	int i, ci, set, rval = 0;
+	int nSosMem, nSetMem;
+
+	/* build sos info */
+	/* see comment in lpdata_EGLPNUM_TYPENAME.h about EGLPNUM_TYPENAME_ILLlpdata's sos and is_sos_mem 
+	 * fields and section of EGLPNUM_TYPENAME_ILLprint_rawlpdata that prints SOS sets */
+
+	ILL_SAFE_MALLOC (lp->is_sos_mem, lp->ncols, int);
+
+	nSosMem = 0;
+	for (i = 0; i < raw->ncols; i++)
+	{
+		ci = colindex[i];
+		if (ci != -1)
+		{
+			lp->is_sos_mem[ci] = raw->is_sos_member[i];
+			if (raw->is_sos_member[i] != -1)
+				nSosMem++;
+		}
+	}
+	if (nSosMem > 0)
+	{
+		lp->sos.matsize = nSosMem;
+		lp->sos.matcols = raw->nsos;
+		lp->sos.matcolsize = raw->nsos;
+		lp->sos.matrows = lp->ncols;
+		lp->sos.matfree = 0;
+		lp->sos.matval = EGLPNUM_TYPENAME_EGlpNumAllocArray (nSosMem);
+		ILL_SAFE_MALLOC (lp->sos.matind, nSosMem, int);
+		ILL_SAFE_MALLOC (lp->sos.matbeg, raw->nsos, int);
+		ILL_SAFE_MALLOC (lp->sos.matcnt, raw->nsos, int);
+		ILL_SAFE_MALLOC (lp->sos_type, raw->nsos, char);
+
+		nSosMem = 0;
+		for (set = 0; set < raw->nsos; set++)
+		{
+			lp->sos_type[set] = raw->sos_set[set].type;
+			lp->sos.matbeg[set] = nSosMem;
+			nSetMem = 0;
+			for (i = raw->sos_set[set].first;
+					 i < raw->sos_set[set].first + raw->sos_set[set].nelem; i++)
+			{
+				ci = colindex[raw->sos_col[i]];
+				if (ci != -1)
+				{
+					lp->sos.matind[nSosMem + nSetMem] = ci;
+					EGLPNUM_TYPENAME_EGlpNumCopy (lp->sos.matval[nSosMem + nSetMem], raw->sos_weight[i]);
+					nSetMem++;
+				}
+			}
+			lp->sos.matcnt[set] = nSetMem;
+			nSosMem += nSetMem;
+		}
+	}
+CLEANUP:
+	ILL_RETURN (rval, "buildSosInfo");
+}
+
+static int convert_rawlpdata_to_lpdata (
+	EGLPNUM_TYPENAME_rawlpdata * raw,
+	EGLPNUM_TYPENAME_ILLlpdata * lp)
+/* 
+ * only raw's non 'N' rows are converted to matrix entries in lp
+ * columns that are used in non objective 'N' rows only are not 
+ * converted. That is they don't end up in lp's matrix, row/colnames, 
+ * upper/lower bounds or SOS information.
+ */
+{
+	int rval = 0;
+	int *rowindex = 0;
+	int *colindex = 0;
+
+	ILL_FAILfalse ((raw && lp), "rawlpdata_to_lpdata called without input");
+	if (raw->name == NULL)
+	{
+		EGLPNUM_TYPENAME_ILLdata_warn (raw->error_collector, "Setting problem name to \"unnamed\".");
+		ILL_UTIL_STR (raw->name, "unnamed");
+	}
+	rval = ILLcheck_rawlpdata (raw);
+	ILL_CLEANUP_IF (rval);
+
+	ILL_FAILfalse (raw->objindex != -1, "EGLPNUM_TYPENAME_rawlpdata must have objective fct.");
+	EGLPNUM_TYPENAME_ILLlpdata_init (lp);
+
+	ILL_IFFREE (lp->probname, char);
+
+	lp->probname = raw->name;
+	raw->name = 0;
+
+	/* MINIMIZE or MAXIMIZE ? */
+	lp->objsense = raw->objsense;
+	if (lp->objsense != EGLPNUM_TYPENAME_ILL_MIN && lp->objsense != EGLPNUM_TYPENAME_ILL_MAX)
+	{
+		EGLPNUM_TYPENAME_ILLdata_error (raw->error_collector, "Bad objsense.\n");
+		rval = 1;
+		goto CLEANUP;
+	}
+
+	ILL_SAFE_MALLOC (colindex, raw->ncols, int);
+	ILL_SAFE_MALLOC (rowindex, raw->nrows, int);
+
+	rval = whichColsAreUsed (raw, lp, colindex) ||
+		whichRowsAreUsed (raw, lp, rowindex);
+	ILL_CLEANUP_IF (rval);
+	ILL_FAILtrue (lp->ncols == 0 || lp->nrows == 0, "we need rows and cols");
+
+	/* array sizes */
+	lp->rowsize = lp->nrows;
+	lp->colsize = lp->ncols;
+	lp->nstruct = lp->ncols;
+	lp->structsize = lp->ncols;
+	ILLsymboltab_create (&lp->rowtab, lp->nrows);
+	ILLsymboltab_create (&lp->coltab, lp->ncols);
+
+	rval = transferObjective (raw, lp, colindex);
+	rval = rval || transferColNamesLowerUpperIntMarker (raw, lp, colindex);
+	rval = rval || buildMatrix (raw, lp, rowindex, colindex);
+	rval = rval || buildSosInfo (raw, lp, colindex);
+	ILL_CLEANUP_IF (rval);
+	ILL_IFDOTRACE
+	{
+		EGioFile_t*lout = EGioOpenFILE(stdout);
+		EGLPNUM_TYPENAME_ILLmatrix_prt (lout, &lp->A);
+		EGioClose(lout);
+	}
+
+	rval = transferSenseRhsRowNames (raw, lp, rowindex);
+	if ((lp->nrows > 0) && raw->ranges)
+	{
+		rval = rval || transferRanges (raw, lp, rowindex);
+	}
+	ILL_CLEANUP_IF (rval);
+
+	rval = initStructmap (lp);
+	ILL_CLEANUP_IF (rval);
+
+CLEANUP:
+
+	ILL_IFFREE (rowindex, int);
+	ILL_IFFREE (colindex, int);
+
+	EGLPNUM_TYPENAME_ILLfree_rawlpdata (raw);
+
+	ILL_RESULT (rval, "convert_rawlpdata_to_lpdata");
+}
+
+int EGLPNUM_TYPENAME_ILLrawlpdata_to_lpdata (
+	EGLPNUM_TYPENAME_rawlpdata * raw,
+	EGLPNUM_TYPENAME_ILLlpdata * lp)
+{
+	int rval = 0;
+
+	ILL_IFDOTRACE
+	{
+		QSlog("%s", __func__);
+		EGLPNUM_TYPENAME_ILLprint_rawlpdata (raw);
+	}
+	rval = convert_rawlpdata_to_lpdata (raw, lp);
+	if (rval == 0)
+	{
+		rval = EGLPNUM_TYPENAME_ILLlp_add_logicals (lp);
+	}
+	ILL_RESULT (rval, "EGLPNUM_TYPENAME_ILLrawlpdata_to_lpdata");
+}
+
+static int set_field_name (
+	char **field,
+	const char *name,
+	int *skip)
+{
+	int rval = 0;
+
+	/* name is bounds/rhs/rangesname field from EGLPNUM_TYPENAME_rawlpdata */
+	*skip = 0;
+	if (!*field)
+	{
+		ILL_UTIL_STR (*field, name);
+	}
+
+	if (strcmp (*field, name))
+	{
+		/* not first specified RHS/BOUNDS - skip it */
+		*skip = 1;
+	}
+CLEANUP:
+	ILL_RETURN (rval, "set_field_name");
+}
+
+int EGLPNUM_TYPENAME_ILLraw_set_rhs_name (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	const char *name,
+	int *skip)
+{
+	return set_field_name (&lp->rhsname, name, skip);
+}
+
+int EGLPNUM_TYPENAME_ILLraw_set_bounds_name (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	const char *name,
+	int *skip)
+{
+	return set_field_name (&lp->boundsname, name, skip);
+}
+
+int EGLPNUM_TYPENAME_ILLraw_set_ranges_name (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	const char *name,
+	int *skip)
+{
+	return set_field_name (&lp->rangesname, name, skip);
+}
+
+void EGLPNUM_TYPENAME_ILLprint_rawlpdata (
+	EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+	int i, cnt, si, m;
+	char c;
+	EGLPNUM_TYPE d;
+	EGLPNUM_TYPENAME_colptr *cp;
+	EGLPNUM_TYPENAME_sosptr *set;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (d);
+
+	if (lp)
+	{
+		if (lp->name)
+		{
+			printf ("PROBLEM  %s\n", lp->name);
+		}
+		if (lp->rowsense && lp->rhs)
+		{
+			printf ("Subject To\n");
+			for (i = 0; i < lp->nrows; i++)
+			{
+				switch (lp->rowsense[i])
+				{
+				case 'E':
+					c = '=';
+					break;
+				case 'L':
+					c = '<';
+					break;
+				case 'G':
+					c = '>';
+					break;
+				default:
+					c = '?';
+					break;
+				}
+				printf ("%s: %c %f\n", EGLPNUM_TYPENAME_ILLraw_rowname (lp, i), c,
+								EGLPNUM_TYPENAME_EGlpNumToLf (lp->rhs[i]));
+			}
+			printf ("\n");
+		}
+		if (lp->ncols > 0)
+		{
+			printf ("Columns\n");
+			for (i = 0; i < lp->ncols; i++)
+			{
+				for (cp = lp->cols[i]; cp; cp = cp->next)
+				{
+					printf ("%s: ", EGLPNUM_TYPENAME_ILLraw_rowname (lp, cp->this_val));
+					printf ("%c ", (EGLPNUM_TYPENAME_EGlpNumIsLessZero (cp->coef)) ? '-' : '+');
+					EGLPNUM_TYPENAME_EGlpNumCopyAbs (d, cp->coef);
+					if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (d, EGLPNUM_TYPENAME_oneLpNum))
+					{
+						printf (" %f ", EGLPNUM_TYPENAME_EGlpNumToLf (d));
+					}
+					printf ("%s\n", EGLPNUM_TYPENAME_ILLraw_colname (lp, i));
+				}
+				printf ("\n");
+			}
+		}
+		if (lp->rangesname)
+		{
+			printf ("RANGES %s\n", lp->rangesname);
+			for (cp = lp->ranges; cp; cp = cp->next)
+			{
+				printf ("(%s, %f) ", EGLPNUM_TYPENAME_ILLraw_rowname (lp, cp->this_val),
+								EGLPNUM_TYPENAME_EGlpNumToLf (cp->coef));
+			}
+			printf ("\n");
+		}
+		if (lp->boundsname)
+		{
+			printf ("BOUNDS %s\n", lp->boundsname);
+		}
+		else
+		{
+			printf ("BOUNDS \n");
+		}
+		if (lp->lower && lp->upper)
+		{
+			for (i = 0; i < lp->ncols; i++)
+			{
+				ILLprt_EGlpNum (stdout, &(lp->lower[i]));
+				printf (" <= %s <= ", EGLPNUM_TYPENAME_ILLraw_colname (lp, i));
+				ILLprt_EGlpNum (stdout, &(lp->upper[i]));
+				printf ("\n");
+			}
+		}
+		if (lp->intmarker)
+		{
+			printf ("Integer\n");
+			cnt = 0;
+			for (i = 0; i < lp->ncols; i++)
+			{
+				if (lp->intmarker[i])
+				{
+					printf ("%s", EGLPNUM_TYPENAME_ILLraw_colname (lp, i));
+					cnt++;
+					if (cnt == 8)
+					{
+						printf ("\n    ");
+						cnt = 0;
+					}
+				}
+			}
+			printf ("\n");
+		}
+		printf ("SOS-SETS\n");
+		for (si = 0; si < lp->nsos; si++)
+		{
+			set = lp->sos_set + si;
+			printf ("SOS-SET %d: %s; nelem=%d; first=%d;\n",
+							si, ((set->type == EGLPNUM_TYPENAME_ILL_SOS_TYPE1) ? "TYPE1" : "TYPE2"),
+							set->nelem, set->first);
+			printf ("\t");
+			for (m = set->first; m < set->first + set->nelem; m++)
+			{
+				printf (" %s %f; ", EGLPNUM_TYPENAME_ILLraw_colname (lp, lp->sos_col[m]),
+								EGLPNUM_TYPENAME_EGlpNumToLf (lp->sos_weight[m]));
+			}
+			printf ("\n");
+		}
+		printf ("\n");
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (d);
+}
+
+static int ILLmsg (
+	EGLPNUM_TYPENAME_qserror_collector * collector,
+	int isError,
+	const char *format,
+	va_list args)
+{
+	const char *pre;
+	int slen, errtype;
+	EGLPNUM_TYPENAME_qsformat_error error;
+	char error_desc[256];
+
+	vsprintf (error_desc, format, args);
+	slen = strlen (error_desc);
+	if ((slen > 0) && error_desc[slen - 1] != '\n')
+	{
+		error_desc[slen] = '\n';
+		error_desc[slen + 1] = '\0';
+	}
+
+	if (collector != NULL)
+	{
+		errtype = (isError) ? QS_DATA_ERROR : QS_DATA_WARN;
+		EGLPNUM_TYPENAME_ILLformat_error_create (&error, errtype, error_desc, -1, NULL, -1);
+		EGLPNUM_TYPENAME_ILLformat_error (collector, &error);
+		EGLPNUM_TYPENAME_ILLformat_error_delete (&error);
+	}
+	else
+	{
+		pre = (isError) ? "Data Error" : "Data Warning";
+		QSlog("%s: %s", pre, error_desc);
+	}
+	return 1;
+}
+
+int EGLPNUM_TYPENAME_ILLdata_error (
+	EGLPNUM_TYPENAME_qserror_collector * collector,
+	const char *format,
+	...)
+{
+	va_list args;
+
+	va_start (args, format);
+	return ILLmsg (collector, TRUE, format, args);
+}
+
+void EGLPNUM_TYPENAME_ILLdata_warn (
+	EGLPNUM_TYPENAME_qserror_collector * collector,
+	const char *format,
+	...)
+{
+	va_list args;
+
+	va_start (args, format);
+	(void) ILLmsg (collector, FALSE, format, args);
+}
+
+EGLPNUM_TYPENAME_colptr *EGLPNUM_TYPENAME_ILLcolptralloc (
+	ILLptrworld * p)
+{
+	EGLPNUM_TYPENAME_colptr *sol = colptralloc (p);
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar ((sol->coef));
+	return sol;
+}
diff --git a/qsopt_ex/rawlp.h b/qsopt_ex/rawlp.h
new file mode 100644
index 0000000..c701731
--- /dev/null
+++ b/qsopt_ex/rawlp.h
@@ -0,0 +1,259 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/*  RCS_INFO = "$RCSfile: rawlp_EGLPNUM_TYPENAME.h,v $ $Revision: 1.3 $ $Date: 2003/11/05 16:57:39 $"; */
+#ifndef EGLPNUM_TYPENAME___ILL_RAWLP_H_
+#define EGLPNUM_TYPENAME___ILL_RAWLP_H_
+
+/****************************************************************************/
+/* DataStructure and Routines                                               */
+/*          to deal with raw lp information as read from mps or lp files    */
+/*          support scanning of input                                       */
+/*          error reporting                                                 */
+/****************************************************************************/
+
+#include "allocrus.h"
+#include "eg_lpnum.h"
+#include "symtab.h"
+#include "trace.h"
+
+#include "lpdata_EGLPNUM_TYPENAME.h"
+#include "format_EGLPNUM_TYPENAME.h"
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+
+#define EGLPNUM_TYPENAME_ILL_ISBLANK(p) \
+             (((*(p))==' '||(*(p))=='\t'||(*(p))=='\r'||(*(p))=='\f') ? 1 : 0)
+
+/* 
+ * we rely on ILLsymboltab property:
+ *   the ith name added can be retrieved by ILLsymboltab_get(table, i) 
+ *   as long as we never delete names from the symbol table 
+ */
+typedef struct EGLPNUM_TYPENAME_rawlpdata
+{
+	char *name;
+
+	char *rhsname;
+	char *rangesname;
+	char *boundsname;
+
+	int objsense;									/* maximize or minimize */
+	int objindex;									/* index of objective row */
+
+	int nrows;										/* number of rows in problem */
+	ILLsymboltab rowtab;					/* ILLsymboltab_get(rowtab, i) name of ith row */
+
+	int sensesize;								/* size of rowsense */
+	char *rowsense;								/* rowsense[i] snese of row[i] */
+
+	char *rhsind;									/* rhsind[i] == 1 we saw an rhs for row[i] */
+	/* size is nrows */
+	int rhssize;									/* size of rhs array */
+	EGLPNUM_TYPE *rhs;								/* rhs values for rows; size is nrows */
+	char *rangesind;							/* ranges[i] == 1 we saw a range def for row[i] */
+	struct EGLPNUM_TYPENAME_colptr *ranges;				/* list of range values */
+
+	int ncols;										/* number of cols in problem */
+	ILLsymboltab coltab;					/* ILLsymboltab_get(coltab, i) name of ith col */
+	int colsize;									/* size of cols array */
+	struct EGLPNUM_TYPENAME_colptr **cols;
+
+	char *lbind;									/* lbind[i] == 1  we saw a lower bound for col[i] */
+	char *ubind;									/* ubind[i] == 1  we saw a upper bound for col[i] */
+	EGLPNUM_TYPE *lower;							/* lower[i] = lower bound for col[i] */
+	EGLPNUM_TYPE *upper;							/* upper[i] = upper bound for col[i] */
+
+	int intsize;									/* size of intmarker array */
+	char *intmarker;							/* intmarker[i] == 1  col[i] is an int var */
+
+	/* sos information is tranfered into EGLPNUM_TYPENAME_ILLmatrix lpdata->sos */
+	char *refrow;									/* name of reference row */
+	int refrowind;								/* index of refrow or -1  */
+
+	int is_sos_size;							/* size of is_sos_member array */
+	int *is_sos_member;						/* for each col contains either               
+																 *     -1 == no sos memeber 
+																 *     i  == member of set #i */
+
+	int nsos_member;							/* total number of sos set members */
+	int sos_weight_size;					/* size of sos_weight array */
+	EGLPNUM_TYPE *sos_weight;				/* sos set elem i has weight of sos_weight[i] 
+																 * value comes from refrow coeficients */
+	int sos_col_size;							/* size of sos_col array */
+	int *sos_col;									/* sos elem i is column sos_col[i] */
+
+	int nsos;											/* number of sos sets */
+	int sos_setsize;							/* size of sosset array */
+	struct EGLPNUM_TYPENAME_sosptr *sos_set;				/* type, size, first element of sos sets 
+																 * first is index into sos_weight and sos_col 
+																 * arrays */
+	EGLPNUM_TYPENAME_qserror_collector *error_collector;
+	ILLptrworld ptrworld;
+}
+EGLPNUM_TYPENAME_rawlpdata;
+
+typedef struct EGLPNUM_TYPENAME_colptr
+{
+	EGLPNUM_TYPE coef;
+	struct EGLPNUM_TYPENAME_colptr *next;
+	int this_val;											/* row index */
+}
+EGLPNUM_TYPENAME_colptr;
+extern EGLPNUM_TYPENAME_colptr *EGLPNUM_TYPENAME_ILLcolptralloc (
+	ILLptrworld * p);
+
+typedef struct EGLPNUM_TYPENAME_sosptr
+{
+	int nelem;										/* number of set elements */
+	int first;										/* index of first set element in sosmemeber */
+	char type;										/* set type */
+}
+EGLPNUM_TYPENAME_sosptr;
+extern const int EGLPNUM_TYPENAME_ILL_SOS_TYPE1;
+extern const int EGLPNUM_TYPENAME_ILL_SOS_TYPE2;
+
+extern void EGLPNUM_TYPENAME_ILLinit_rawlpdata (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	EGLPNUM_TYPENAME_qserror_collector * collector);
+extern void EGLPNUM_TYPENAME_ILLfree_rawlpdata (
+	EGLPNUM_TYPENAME_rawlpdata * lp);
+extern void EGLPNUM_TYPENAME_ILLraw_clear_matrix (
+	EGLPNUM_TYPENAME_rawlpdata * lp);
+
+extern const char *EGLPNUM_TYPENAME_ILLraw_rowname (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	int i);
+extern const char *EGLPNUM_TYPENAME_ILLraw_colname (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	int i);
+
+extern int EGLPNUM_TYPENAME_ILLraw_add_col (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	const char *name,
+	int intmarker);
+extern int EGLPNUM_TYPENAME_ILLraw_add_row (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	const char *name,
+	int sense,
+	const EGLPNUM_TYPE rhs);
+
+extern int EGLPNUM_TYPENAME_ILLraw_add_col_coef (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	int colind,
+	int rowind,
+	EGLPNUM_TYPE coef);
+
+extern int EGLPNUM_TYPENAME_ILLraw_init_ranges (
+	EGLPNUM_TYPENAME_rawlpdata * lp);
+extern int EGLPNUM_TYPENAME_ILLraw_init_rhs (
+	EGLPNUM_TYPENAME_rawlpdata * lp);
+
+extern int EGLPNUM_TYPENAME_ILLraw_add_ranges_coef (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	int rowind,
+	EGLPNUM_TYPE coef);
+
+
+extern int EGLPNUM_TYPENAME_ILLraw_add_sos (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	int sos_type);
+
+																								/* add empty set with type */
+extern int EGLPNUM_TYPENAME_ILLraw_add_sos_member (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	int colind);
+
+																								/* add col to last set */
+extern int EGLPNUM_TYPENAME_ILLraw_is_mem_other_sos (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	int colind);
+
+extern int EGLPNUM_TYPENAME_ILLraw_set_rhs_name (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	const char *name,
+	int *skip);
+extern int EGLPNUM_TYPENAME_ILLraw_set_bounds_name (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	const char *name,
+	int *skip);
+extern int EGLPNUM_TYPENAME_ILLraw_set_ranges_name (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	const char *name,
+	int *skip);
+extern void EGLPNUM_TYPENAME_ILLprint_rawlpdata (
+	EGLPNUM_TYPENAME_rawlpdata * lp);
+
+extern char *EGLPNUM_TYPENAME_ILLraw_unique_name (
+	ILLsymboltab * tab,
+	char *prefix,
+	int i);
+extern int EGLPNUM_TYPENAME_ILLraw_fill_in_rownames (
+	EGLPNUM_TYPENAME_rawlpdata * lp);
+
+extern int EGLPNUM_TYPENAME_ILLraw_init_bounds (
+	EGLPNUM_TYPENAME_rawlpdata * lp);
+
+extern const char *EGLPNUM_TYPENAME_ILLraw_set_lowerBound (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	int i,
+	EGLPNUM_TYPE bnd);
+extern const char *EGLPNUM_TYPENAME_ILLraw_set_upperBound (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	int i,
+	EGLPNUM_TYPE bnd);
+extern const char *EGLPNUM_TYPENAME_ILLraw_set_fixedBound (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	int i,
+	EGLPNUM_TYPE bnd);
+extern const char *EGLPNUM_TYPENAME_ILLraw_set_binaryBound (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	int i);
+extern const char *EGLPNUM_TYPENAME_ILLraw_set_unbound (
+	EGLPNUM_TYPENAME_rawlpdata * lp,
+	int colind);
+extern int EGLPNUM_TYPENAME_ILLraw_fill_in_bounds (
+	EGLPNUM_TYPENAME_rawlpdata * lp);
+
+extern int EGLPNUM_TYPENAME_ILLraw_first_nondefault_bound (
+	EGLPNUM_TYPENAME_ILLlpdata * lp);
+extern int EGLPNUM_TYPENAME_ILLraw_default_lower (
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	int i);
+extern int EGLPNUM_TYPENAME_ILLraw_default_upper (
+	EGLPNUM_TYPENAME_ILLlpdata * lp,
+	int i,
+	int ri);
+
+extern int EGLPNUM_TYPENAME_ILLrawlpdata_to_lpdata (
+	EGLPNUM_TYPENAME_rawlpdata * raw,
+	EGLPNUM_TYPENAME_ILLlpdata * lp);
+
+extern int EGLPNUM_TYPENAME_ILLdata_error (
+	EGLPNUM_TYPENAME_qserror_collector * collector,
+	const char *format,
+	...);
+extern void EGLPNUM_TYPENAME_ILLdata_warn (
+	EGLPNUM_TYPENAME_qserror_collector * collector,
+	const char *format,
+	...);
+
+#endif
diff --git a/qsopt_ex/read_lp.c b/qsopt_ex/read_lp.c
new file mode 100644
index 0000000..fd25715
--- /dev/null
+++ b/qsopt_ex/read_lp.c
@@ -0,0 +1,837 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: read_lp_state.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+
+/****************************************************************************/
+/*                                                                          */
+/*               Routines to support Reading LP Files                       */
+/*                                                                          */
+/****************************************************************************/
+
+/* 
+ * -) anything after '\' is comment 
+ * -) variables consist of a-z A-Z 0-9!"#$%(),;.?@_`'{}|~ 
+ *    don't start with a digit or '.'
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "eg_lpnum.h"
+#include "eg_io.h"
+#include "except.h"
+
+#include "read_lp_EGLPNUM_TYPENAME.h"
+#include "lp_EGLPNUM_TYPENAME.h"
+#include "rawlp_EGLPNUM_TYPENAME.h"
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+#include "format_EGLPNUM_TYPENAME.h"
+
+
+static int TRACE = 0;
+
+#define END_LINE(p)  (((*p) == '\\' || (*p) == '\n' || (*p) == '\0') ? 1 : 0)
+
+static const char *all_keyword[] = {
+	"MIN", "MINIMUM", "MINIMIZE",
+	"MAX", "MAXIMUM", "MAXIMIZE",
+	"SUBJECT", "ST", "PROBLEM", "PROB",
+	"BOUNDS", "BOUND", "INTEGER", "END", NULL
+};
+static int all_keyword_len[] = {
+	3, 7, 8,
+	3, 7, 8,
+	7, 2, 7, 4,
+	6, 5, 7, 3, -1
+};
+
+int EGLPNUM_TYPENAME_ILLread_lp_state_init (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	EGLPNUM_TYPENAME_qsline_reader * file,
+	const char *fname,
+	int inter)
+{
+	int rval = 0;
+
+	ILL_FAILtrue (file == NULL, "need a file");
+	state->eof = 0;
+	state->file_name = fname;
+	state->interactive = inter;
+	state->file = file;
+	state->line_num = 0;
+	state->p = state->line;
+	state->line[0] = '\0';
+	state->realline[0] = '\0';
+	state->field[0] = '\0';
+	state->fieldOnFirstCol = 0;
+	EGLPNUM_TYPENAME_EGlpNumInitVar (state->bound_val);
+	EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (state, 1);
+CLEANUP:
+	ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLread_lp_state_init");
+}
+
+int EGLPNUM_TYPENAME_ILLread_lp_state_next_line (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+	char *slash;
+
+	if (state->eof)
+	{
+		return 1;
+	}
+	state->line[0] = '\0';
+	if (state->interactive)
+	{
+		fprintf (stdout, "> ");
+		fflush (stdout);
+	}
+	while (EGLPNUM_TYPENAME_ILLline_reader_get (state->realline, ILL_namebufsize - 2, state->file)
+				 != (char *) NULL)
+	{
+		state->p = state->line;
+		state->line_num++;
+		strcpy (state->line, state->realline);
+		slash = strchr (state->line, '\\');
+		if (slash != NULL)
+		{
+			*slash = '\0';
+		}
+		while (EGLPNUM_TYPENAME_ILL_ISBLANK (state->p))
+		{
+			state->p++;
+		}
+		if (!END_LINE (state->p))
+		{
+			ILL_IFTRACE ("NEWLINE %s %d: %s",
+									 state->file_name, state->line_num, state->line);
+			return 0;
+		}
+		if (state->interactive)
+		{
+			fprintf (stdout, "> ");
+			fflush (stdout);
+		}
+	}
+	state->eof = 1;
+	state->line_num++;
+	state->field[0] = '\0';
+	state->line[0] = '\0';
+	strcpy (state->realline, "\n");
+	state->p = state->line;
+	state->fieldOnFirstCol = 0;
+	return 1;
+}
+
+int EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	int wrapLines)
+{
+	while (1)
+	{
+		while (EGLPNUM_TYPENAME_ILL_ISBLANK (state->p))
+		{
+			state->p++;
+		}
+		if (END_LINE (state->p))
+		{
+			if (wrapLines)
+			{
+				if (EGLPNUM_TYPENAME_ILLread_lp_state_next_line (state) != 0)
+				{
+					return 1;
+				}
+			}
+			else
+			{
+				return 0;								/* done */
+			}
+		}
+		else
+		{
+			return 0;									/* foud non blank */
+		}
+	}
+}
+
+static int next_field (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	int acrossLines)
+{
+	(void) EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (state, (char) acrossLines);
+	if (state->eof)
+	{
+		return 1;
+	}
+	state->fieldOnFirstCol = (state->line == state->p);
+	if (sscanf (state->p, "%s", state->field) != EOF)
+	{
+		state->p += strlen (state->field);
+		return 0;
+	}
+	return 1;
+}
+
+int EGLPNUM_TYPENAME_ILLread_lp_state_next_field_on_line (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+	return next_field (state, 0);
+}
+
+int EGLPNUM_TYPENAME_ILLread_lp_state_next_field (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+	return next_field (state, 1);
+}
+
+void EGLPNUM_TYPENAME_ILLread_lp_state_prev_field (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+	if (state->p > state->line)
+	{
+		state->p--;
+	}
+	while (EGLPNUM_TYPENAME_ILL_ISBLANK (state->p) && (state->p > state->line))
+	{
+		state->p--;
+	}
+	while (!EGLPNUM_TYPENAME_ILL_ISBLANK (state->p) && (state->p > state->line))
+	{
+		state->p--;
+	}
+	state->fieldOnFirstCol = (state->line == state->p);
+}
+
+int EGLPNUM_TYPENAME_ILLread_lp_state_next_var (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+	char *p;
+	int var_len, i;
+
+	if (EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (state, 1))
+	{
+		return 1;
+	}
+	state->fieldOnFirstCol = (state->line == state->p);
+	var_len = 0;
+	p = state->p;
+	while (1)
+	{
+		if (EGLPNUM_TYPENAME_ILLis_lp_name_char (*p, var_len))
+		{
+			p++;
+			var_len++;
+		}
+		else
+		{
+			break;
+		}
+	}
+	if (var_len == 0)
+	{
+		return 1;
+	}
+	if (state->fieldOnFirstCol)
+	{
+		/* see whether we founbd a reserved keyword */
+		for (i = 0; all_keyword[i] != NULL; i++)
+		{
+			if ((var_len == all_keyword_len[i]) &&
+					(strncasecmp (all_keyword[i], state->p, (size_t) (all_keyword_len[i]))
+					 == 0))
+			{
+				return -1;							/* yes we did */
+			}
+		}
+	}
+	strncpy (state->field, state->p, (size_t) var_len);
+	state->field[var_len] = '\0';
+	state->p = p;
+	return 0;
+}
+
+int EGLPNUM_TYPENAME_ILLread_lp_state_bad_keyword (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+	if (!state->fieldOnFirstCol)
+	{
+		return EGLPNUM_TYPENAME_ILLlp_error (state,
+												"Keyword \"%s\" not at beginning of line.\n",
+												state->field);
+	}
+	return 0;
+}
+
+int EGLPNUM_TYPENAME_ILLtest_lp_state_keyword (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	const char *kwd[])
+{
+	int i = 0;
+
+	if (!state->eof && state->fieldOnFirstCol)
+	{
+		for (i = 0; kwd[i] != NULL; i++)
+		{
+			if (strcasecmp (state->field, kwd[i]) == 0)
+			{
+				return 0;
+			}
+		}
+	}
+	return 1;
+}
+
+int EGLPNUM_TYPENAME_ILLread_lp_state_keyword (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	const char *kwd[])
+{
+	if (state->eof || EGLPNUM_TYPENAME_ILLread_lp_state_bad_keyword (state))
+	{
+		return 1;
+	}
+	return EGLPNUM_TYPENAME_ILLtest_lp_state_keyword (state, kwd);
+}
+
+
+int EGLPNUM_TYPENAME_ILLread_lp_state_colon (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+	if ((EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (state, 1) == 0) && (*state->p == ':'))
+	{
+		state->p++;
+		return 0;
+	}
+	return 1;
+}
+
+int EGLPNUM_TYPENAME_ILLread_lp_state_has_colon (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+	char *pp;
+
+	EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (state, 0);
+	for (pp = state->p; *pp != '\n'; pp++)
+	{
+		if (*pp == ':')
+		{
+			return 1;
+		}
+	}
+	return 0;
+}
+
+int EGLPNUM_TYPENAME_ILLread_lp_state_next_constraint (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+	int rval;
+	int ln = state->line_num;
+
+	EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (state, 1);
+	if (state->eof)
+	{
+		return 1;
+	}
+	if (ln == state->line_num)
+	{
+		return EGLPNUM_TYPENAME_ILLlp_error (state, "Constraints must start on a new line.\n");
+	}
+	if (EGLPNUM_TYPENAME_ILLread_lp_state_next_field (state) == 0)
+	{
+		rval = EGLPNUM_TYPENAME_ILLtest_lp_state_keyword (state, all_keyword);
+		EGLPNUM_TYPENAME_ILLread_lp_state_prev_field (state);
+		return !rval;
+	}
+	return 0;
+}
+
+/* return 0 if there is a sign */
+int EGLPNUM_TYPENAME_ILLread_lp_state_sign (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	EGLPNUM_TYPE * sign)
+{
+	char found = 0;
+
+	EGLPNUM_TYPENAME_EGlpNumOne (*sign);
+	if (EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (state, 1) == 0)
+	{
+		if ((*state->p == '+') || (*state->p == '-'))
+		{
+			if (*state->p != '+')
+				EGLPNUM_TYPENAME_EGlpNumSign (*sign);
+			state->p++;
+			found = 1;
+		}
+	}
+	return 1 - found;
+}
+
+int EGLPNUM_TYPENAME_ILLtest_lp_state_next_is (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	const char *str)
+{
+	EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (state, 0);
+	if (strncasecmp (state->p, str, strlen (str)) == 0)
+	{
+		state->p += strlen (str);
+		return 1;
+	}
+	return 0;
+}
+
+int EGLPNUM_TYPENAME_ILLread_lp_state_value (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	EGLPNUM_TYPE * coef)
+{
+	int len = 0;
+
+	if (EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (state, 1) != 0)
+	{
+		ILL_RESULT (1, "EGLPNUM_TYPENAME_ILLread_lp_state_value");
+	}
+	else
+	{
+		state->fieldOnFirstCol = (state->line == state->p);
+		len = EGLPNUM_TYPENAME_ILLget_value (state->p, coef);
+		if (len > 0)
+		{
+			state->p += len;
+			ILL_RESULT (0, "EGLPNUM_TYPENAME_ILLread_lp_state_value");
+		}
+		ILL_RESULT (1, "EGLPNUM_TYPENAME_ILLread_lp_state_value");
+	}
+}
+
+int EGLPNUM_TYPENAME_ILLread_lp_state_possible_coef (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	EGLPNUM_TYPE * coef,
+	const EGLPNUM_TYPE defValue)
+{
+	EGLPNUM_TYPENAME_EGlpNumCopy (*coef, defValue);
+	return EGLPNUM_TYPENAME_ILLread_lp_state_value (state, coef);
+}
+
+
+int EGLPNUM_TYPENAME_ILLread_lp_state_possible_bound_value (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+	EGLPNUM_TYPE sign;
+	int len = 0;
+	char *p = NULL;
+	int rval = 0;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (sign);
+	(void) EGLPNUM_TYPENAME_ILLread_lp_state_sign (state, &sign);
+
+	if (!strncasecmp (state->p, "INFINITY", (size_t) 8))
+	{
+		len = 8;
+	}
+	else
+	{
+		if (!strncasecmp (state->p, "INF", (size_t) 3))
+		{
+			len = 3;
+		}
+	}
+	if (len > 0)
+	{
+		state->p += len;
+		p = state->p;
+		EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (state, 0);
+		if (!END_LINE (p) && p == state->p)
+		{
+			/* found no blanks so this INF/INFINITY is the prefix 
+			 * of something else */
+			state->p -= len;
+			goto CLEANUP;
+			return 0;									/* no coef found */
+		}
+		else
+		{
+			if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (sign))
+				EGLPNUM_TYPENAME_EGlpNumCopy (state->bound_val, EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+			else if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (sign))
+				EGLPNUM_TYPENAME_EGlpNumCopy (state->bound_val, EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+			else
+				EGLPNUM_TYPENAME_EGlpNumZero (state->bound_val);
+			rval = 1;
+			goto CLEANUP;
+		}
+	}
+	if (EGLPNUM_TYPENAME_ILLread_lp_state_value (state, &(state->bound_val)) == 0)
+	{
+		EGLPNUM_TYPENAME_EGlpNumMultTo (state->bound_val, sign);
+		rval = 1;
+		goto CLEANUP;
+	}
+CLEANUP:
+	EGLPNUM_TYPENAME_EGlpNumClearVar (sign);
+	return rval;									/* no coef found */
+}
+
+int EGLPNUM_TYPENAME_ILLtest_lp_state_sense (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	int all)
+{
+	char c;
+
+	state->sense_val = ' ';
+	if (EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (state, 1) == 0)
+	{
+		c = *state->p;
+		if (!all)
+		{														/* look for '=' and '<=' */
+			if (c == '=')
+			{
+				state->p++;
+				state->sense_val = 'E';
+			}
+			else
+			{
+				if ((c == '<') && (*(state->p + 1) == '='))
+				{
+					state->p += 2;
+					state->sense_val = 'L';
+				}
+			}
+		}
+		else
+		{
+			c = *state->p;
+			if ((c == '<') || (c == '>'))
+			{
+				state->sense_val = (c == '<') ? 'L' : 'G';
+				state->p++;
+				c = *state->p;
+				if (*state->p == '=')
+				{
+					state->p++;
+				}
+			}
+			else
+			{
+				if (c == '=')
+				{
+					state->p++;
+					c = *state->p;
+					if ((c == '<') || (c == '>'))
+					{
+						state->sense_val = (c == '<') ? 'L' : 'G';
+						state->p++;
+					}
+					else
+					{
+						state->sense_val = 'E';
+					}
+				}
+			}
+		}
+	}
+	return (state->sense_val != ' ');
+}
+
+void EGLPNUM_TYPENAME_ILLtest_lp_state_bound_sense (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+	(void) EGLPNUM_TYPENAME_ILLtest_lp_state_sense (state, 0);
+}
+
+int EGLPNUM_TYPENAME_ILLread_lp_state_sense (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+	if (!EGLPNUM_TYPENAME_ILLtest_lp_state_sense (state, 1))
+	{
+		if (END_LINE (state->p))
+		{
+			return EGLPNUM_TYPENAME_ILLlp_error (state, "Missing row sense at end of line.\n");
+		}
+		else
+		{
+			if (*state->p != '\0')
+			{
+				return EGLPNUM_TYPENAME_ILLlp_error (state, "\"%c\" is not a row sense.\n", *state->p);
+			}
+			else
+			{
+				return EGLPNUM_TYPENAME_ILLlp_error (state, "Missing row sense at end of line.\n");
+			}
+		}
+	}
+	return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+/*  error printing 
+ */
+
+static void ILLread_lp_state_print_at (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+	char *p;
+
+	if (state->eof)
+	{
+		QSlog("end of file");
+	}
+	else
+	{
+		if (*state->p == '\n')
+		{
+			QSlog("end of line");
+		}
+		else
+		{
+			p = state->p;
+			while (EGLPNUM_TYPENAME_ILL_ISBLANK (p))
+			{
+				p++;
+			}
+			QSlog("%c", '"');
+			for (; !EGLPNUM_TYPENAME_ILL_ISBLANK (p) && !END_LINE (p); p++)
+			{
+				QSlog("%c", *p);
+			}
+			QSlog("\"");
+		}
+	}
+}
+
+static void lp_err (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	int isError,
+	const char *format,
+	va_list args)
+{
+	int rval = 0;
+	int errtype, slen, at;
+	EGLPNUM_TYPENAME_qsformat_error error;
+	char error_desc[256];
+
+	ILL_FAILfalse (state != NULL, "state != NULL");
+	ILL_FAILfalse (state->file != NULL, "state->file != NULL");
+	ILL_FAILfalse (format != NULL, "format != NULL");
+	ILL_FAILfalse (format[0] != '\0', "format[0] != '0'");
+
+	EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (state, 0);
+	at = state->p - state->line;
+	vsprintf (error_desc, format, args);
+	slen = strlen (error_desc);
+	if ((slen > 0) && error_desc[slen - 1] != '\n')
+	{
+		error_desc[slen] = '\n';
+		error_desc[slen + 1] = '\0';
+	}
+
+	if (state->file->error_collector != NULL)
+	{
+		errtype = (isError) ? QS_LP_FORMAT_ERROR : QS_LP_FORMAT_WARN;
+		EGLPNUM_TYPENAME_ILLformat_error_create (&error, errtype, error_desc,
+														state->line_num, state->realline, at);
+		EGLPNUM_TYPENAME_ILLformat_error (state->file->error_collector, &error);
+		EGLPNUM_TYPENAME_ILLformat_error_delete (&error);
+	}
+	else
+	{
+		if (!state->interactive)
+		{
+			QSlog("%s %d: %s\t", state->file_name, state->line_num,
+									state->realline);
+			QSlog("%s at ", (isError) ? "LP Error" : "LP Warning");
+			ILLread_lp_state_print_at (state);
+			QSlog(": ");
+		}
+		else
+		{
+			QSlog("%s : ", (isError) ? "LP Error" : "LP Warning");
+		}
+		QSlog("%s", error_desc);
+	}
+CLEANUP:;
+}
+
+int EGLPNUM_TYPENAME_ILLlp_error (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	const char *format,
+	...)
+{
+	va_list args;
+
+	va_start (args, format);
+	lp_err (state, TRUE, format, args);
+	return 1;
+}
+
+void EGLPNUM_TYPENAME_ILLlp_warn (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	const char *format,
+	...)
+{
+	va_list args;
+
+	va_start (args, format);
+	if (format != NULL)
+	{
+		lp_err (state, FALSE, format, args);
+	}
+}
+
+/* shared with read_mps_state.c */
+int EGLPNUM_TYPENAME_ILLget_value (
+	char *line,
+	EGLPNUM_TYPE * coef)
+{
+#ifdef mpq_READ_LP_STATE_H
+	mpq_t res;
+	int rval = 0;
+
+	mpq_init (res);
+	rval = mpq_EGlpNumReadStrXc (res, line);
+	if (rval == 0)
+		mpq_set_ui (*coef, 1UL, 1UL);
+	else
+		mpq_set (*coef, res);
+	mpq_clear (res);
+	return rval;
+	//return mpq_EGlpNumReadStrXc (*coef, line);
+#else
+	char field[ILL_namebufsize];
+	int rval = 0, i;
+	char c, lastC, *p;
+	int allowDot, allowExp, allowSign;
+	double dtmp;
+
+	p = line;
+	c = *p;
+	i = 0;
+	lastC = ' ';
+	allowSign = 1;
+	allowExp = 0;
+	allowDot = 1;
+	while ((('0' <= c) && (c <= '9')) ||
+				 (allowDot && (c == '.')) ||
+				 ((allowExp == 1) && ((c == 'e') || (c == 'E'))) ||
+				 ((allowSign || lastC == 'e' || lastC == 'E') &&
+					((c == '+') || (c == '-'))))
+	{
+		if (c == '.')
+			allowDot = 0;
+		allowSign = 0;
+
+		if ((allowExp == 0) && (c >= '0') && (c <= '9'))
+		{
+			allowExp = 1;
+		}
+		if ((c == 'e') || (c == 'E'))
+		{
+			allowExp++;
+			allowDot = 0;
+		}
+		p++;
+		lastC = c;
+		c = *p;
+		i++;
+	}
+	if ((lastC == '+') || (lastC == '-'))
+	{
+		p--;
+		i--;
+		if (p > line)
+			lastC = *(p - 1);
+		else
+			lastC = ' ';
+	}
+	if ((lastC == 'e') || (lastC == 'E'))
+	{
+		p--;
+		i--;
+	}
+	if (i > 0)
+	{
+		strncpy (field, line, (size_t) i);
+		field[i] = '\0';
+		rval = !sscanf (field, "%lf%n", &dtmp, &i);
+		EGLPNUM_TYPENAME_EGlpNumSet (*coef, dtmp);
+		ILL_IFTRACE ("%la\n", EGLPNUM_TYPENAME_EGlpNumToLf (*coef));
+		if (rval != 0)
+		{
+			ILL_RESULT (0, "EGLPNUM_TYPENAME_ILLget_value");
+		}
+	}
+	//ILL_RESULT (i, "EGLPNUM_TYPENAME_ILLget_value");
+	return i;
+#endif
+}
+
+int EGLPNUM_TYPENAME_ILLcheck_subject_to (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+	int rval;
+	char *p;
+
+	if ((rval = EGLPNUM_TYPENAME_ILLread_lp_state_next_field (state)) == 0)
+	{
+		if (strcasecmp (state->field, "ST") == 0)
+		{
+			rval = EGLPNUM_TYPENAME_ILLread_lp_state_bad_keyword (state);
+		}
+		else
+		{
+			if (strcasecmp (state->field, "SUBJECT") == 0)
+			{
+				p = state->p;
+				while (EGLPNUM_TYPENAME_ILL_ISBLANK (p))
+				{
+					p++;
+				}
+				if (!strncasecmp (p, "TO", (size_t) 2))
+				{
+					rval = EGLPNUM_TYPENAME_ILLread_lp_state_bad_keyword (state);
+					if (rval == 0)
+					{
+						state->p = p + 2;
+					}
+				}
+			}
+			else
+			{
+				rval = 1;
+			}
+		}
+		if (rval != 0)
+		{
+			EGLPNUM_TYPENAME_ILLread_lp_state_prev_field (state);
+		}
+		else
+		{
+			EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (state, 1);
+		}
+	}
+	ILL_RESULT (rval, "check_subject_to");
+}
diff --git a/qsopt_ex/read_lp.h b/qsopt_ex/read_lp.h
new file mode 100644
index 0000000..9750b78
--- /dev/null
+++ b/qsopt_ex/read_lp.h
@@ -0,0 +1,148 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/*  RCS_INFO = "$RCSfile: read_lp_state.h,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:57:39 $"; */
+#ifndef EGLPNUM_TYPENAME_READ_LP_STATE_H
+#define EGLPNUM_TYPENAME_READ_LP_STATE_H
+
+/****************************************************************************/
+/*                                                                          */
+/*               Routines to support Reading LP Files                       */
+/*                                                                          */
+/****************************************************************************/
+
+/* 
+ * -) anything after '\' is comment 
+ * -) variables consist of a-z A-Z 0-9!"#$%(),;.?@_`'{}|~ 
+ *    don't start with a digit or '.'
+ */
+
+#include "eg_lpnum.h"
+#include "symtab.h"
+
+#include "readline_EGLPNUM_TYPENAME.h"
+
+
+typedef struct EGLPNUM_TYPENAME_ILLread_lp_state
+{
+	EGLPNUM_TYPENAME_qsline_reader *file;
+	const char *file_name;
+	char *p;
+	EGLPNUM_TYPE bound_val;
+	int interactive;
+	int line_num;
+	int column_index;
+	char realline[ILL_namebufsize];
+	char line[ILL_namebufsize];
+	char field[ILL_namebufsize + 1];
+	char fieldOnFirstCol;
+	char eof;
+	char sense_val;
+}
+EGLPNUM_TYPENAME_ILLread_lp_state;
+
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_init (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	EGLPNUM_TYPENAME_qsline_reader * file,
+	const char *fname,
+	int interactve);
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_next_line (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state);
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_next_var (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state);
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_keyword (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	const char **kwd);
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_bad_keyword (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state);
+extern int EGLPNUM_TYPENAME_ILLtest_lp_state_keyword (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	const char *kwd[]);
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_next_field (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state);
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_next_field_on_line (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state);
+extern void EGLPNUM_TYPENAME_ILLread_lp_state_prev_field (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state);
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_sign (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	EGLPNUM_TYPE * sign);
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_possible_coef (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	EGLPNUM_TYPE * coef,
+	const EGLPNUM_TYPE defValue);
+
+																				/* returns 1 iff found a number 
+																				 * otherwise 0 */
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_possible_bound_value (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state);
+
+																							 /* returns 1 iff found a number 
+																							  * otherwise 0 */
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_colon (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state);
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_has_colon (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state);
+extern int EGLPNUM_TYPENAME_ILLread_lp_statxe_has_colon (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state);
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_next_constraint (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state);
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_sense (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state);
+extern int EGLPNUM_TYPENAME_ILLtest_lp_state_sense (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	int all);
+extern void EGLPNUM_TYPENAME_ILLtest_lp_state_bound_sense (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state);
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_value (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	EGLPNUM_TYPE * d);
+extern int EGLPNUM_TYPENAME_ILLtest_lp_state_next_is (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	const char *str);
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	int wrapLines);
+
+extern int EGLPNUM_TYPENAME_ILLcheck_subject_to (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state);
+
+/*---------------------------------------------------------------------------*/
+/* errors and warnings 
+ */
+extern int EGLPNUM_TYPENAME_ILLlp_error (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	const char *format,
+	...);
+extern void EGLPNUM_TYPENAME_ILLlp_warn (
+	EGLPNUM_TYPENAME_ILLread_lp_state * state,
+	const char *format,
+	...);
+
+/*---------------------------------------------------------------------------*/
+/* shared with read_mps_state.c 
+ */
+extern int EGLPNUM_TYPENAME_ILLget_value (
+	char *line,
+	EGLPNUM_TYPE * coef);
+
+#endif
diff --git a/qsopt_ex/read_mps.c b/qsopt_ex/read_mps.c
new file mode 100644
index 0000000..92e0158
--- /dev/null
+++ b/qsopt_ex/read_mps.c
@@ -0,0 +1,522 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: read_mps_state.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+
+/****************************************************************************/
+/*                                                                          */
+/*               Routines to Support  Reading MPS Files                     */
+/*                                                                          */
+/****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "eg_lpnum.h"
+#include "eg_io.h"
+#include "except.h"
+
+#include "mps_EGLPNUM_TYPENAME.h"
+#include "rawlp_EGLPNUM_TYPENAME.h"
+#include "read_mps_EGLPNUM_TYPENAME.h"
+#include "read_lp_EGLPNUM_TYPENAME.h"						/* for EGLPNUM_TYPENAME_ILLget_value */
+#include "format_EGLPNUM_TYPENAME.h"
+
+
+static int TRACE = 0;
+
+#define END_LINE(p)  (((*(p)) == '$' || (*(p)) == '\n' || (*(p)) == '\0') ? 1 : 0)
+
+static int mps_skip_comment (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state);
+static char ILLmps_next_field_is_number (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state);
+
+int EGLPNUM_TYPENAME_ILLmps_state_init (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPENAME_qsline_reader * file,
+	const char *fname)
+{
+	int i, rval = 0;
+
+	ILL_FAILtrue (file == 0, "need file");
+	state->p = 0;
+	state->file_name = fname;
+	state->file = file;
+
+	for (i = 0; i < ILL_MPS_N_SECTIONS; i++)
+	{
+		state->section[i] = 0;
+	}
+	state->active = ILL_MPS_NONE;
+	state->intvar = 0;
+	state->sosvar = 0;
+	state->line_num = 0;
+	state->p = 0;
+
+	state->obj = 0;
+	state->line[0] = '\0';
+	state->key[0] = '\0';
+	state->field[0] = '\0';
+
+CLEANUP:
+	ILL_RESULT (rval, "EGLPNUM_TYPENAME_ILLmps_state_init");
+}
+
+int EGLPNUM_TYPENAME_ILLmps_next_line (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state)
+{
+	int rval = 0;
+
+	/* if field 3 or 5 start with $ rest of line is interpreted as comment */
+	state->line[0] = '\0';
+	state->p = 0;
+	while (EGLPNUM_TYPENAME_ILLline_reader_get (state->line, ILL_namebufsize - 2, state->file)
+				 != 0)
+	{
+		state->line_num++;
+		state->key[0] = '\0';
+		state->field[0] = '\0';
+		state->field_num = 1;
+		state->p = state->line;
+		if (!EGLPNUM_TYPENAME_ILL_ISBLANK ((state->line)))
+		{
+			if (state->line[0] == '*' || state->line[0] == '\n')
+			{
+				continue;								/* comment or blank line */
+			}
+			else
+			{
+				if (sscanf (state->p, "%s", state->key) == 1)
+				{
+					state->p += strlen (state->key);
+					while (EGLPNUM_TYPENAME_ILL_ISBLANK (state->p))
+					{
+						state->p++;
+					}
+					if (sscanf (state->p, "%s", state->field) == 1)
+					{
+						state->p += strlen (state->field);
+					}
+					else
+					{
+						ILL_FAILfalse (state->field[0] == '\0', "sscanf problem?");
+					}
+				}
+				else
+				{
+					ILL_FAILfalse (0, "should almost never happen");
+				}
+			}
+		}
+		else
+		{
+			while (EGLPNUM_TYPENAME_ILL_ISBLANK (state->p))
+			{
+				state->p++;
+			}
+			if (sscanf (state->p, "%s", state->field) < 1)
+			{
+				continue;								/* nothing more on line */
+			}
+			else
+			{
+				if (state->field[0] == '\0')
+				{
+					continue;							/* found empty string */
+				}
+				state->p += strlen (state->field);
+			}
+		}
+		return 0;
+	}
+CLEANUP:
+	return 1;											/* end of file */
+}
+
+/* fields 3,5,7,... may start with '$' signifying comment 
+ * ==> if we find a '$' as next non blank and 
+ *     we read 2,4,6,... fields successfully so far
+ *     we have a comment 
+ */
+static int mps_skip_comment (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state)
+{
+	int rval;
+
+	while (EGLPNUM_TYPENAME_ILL_ISBLANK (state->p))
+	{
+		state->p++;
+	}
+	rval = ((*state->p == '$') && (state->field_num >= 2) &&
+					(state->field_num % 2 == 0));
+	return rval;
+}
+
+int EGLPNUM_TYPENAME_ILLmps_next_field (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state)
+{
+	state->field[0] = '\0';
+	if (!mps_skip_comment (state))
+	{
+		if (sscanf (state->p, "%s", state->field) == 1)
+		{
+			state->p += strlen (state->field) + 1;
+			state->field_num++;
+			return 0;
+		}
+	}
+	return 1;											/* no more fields */
+}
+
+static char get_double (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	int peek,
+	EGLPNUM_TYPE * coef)
+{
+	char ok = 0;
+	int len, rval = 0;
+
+	ILL_FAILfalse (state != 0, "must have state");
+	if (mps_skip_comment (state))
+		return 0;
+	len = EGLPNUM_TYPENAME_ILLget_value (state->p, coef);
+	if (len > 0)
+	{
+		if (!peek)
+		{
+			state->p += len;
+			state->field_num++;
+		}
+		ok = 1;
+	}
+CLEANUP:
+	ILL_RESULT (ok, "get_double");
+}
+
+int EGLPNUM_TYPENAME_ILLmps_next_coef (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPE * coef)
+{
+	int len = 0;
+
+	if (!mps_skip_comment (state))
+	{
+		len = get_double (state, 0, coef);
+	}
+	ILL_RESULT (!(len > 0), "EGLPNUM_TYPENAME_ILLmps_next_coef");
+}
+
+int EGLPNUM_TYPENAME_ILLmps_next_bound (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPE * coef)
+{
+	int len = 0, sign = 1;
+	char c, *p;
+
+	if (!mps_skip_comment (state))
+	{
+		c = *state->p;
+		if (c == '-')
+		{
+			sign = -1;
+			len = 1;
+		}
+		else
+		{
+			if (c == '+')
+			{
+				len = 1;
+			}
+		}
+		if (!strncasecmp (state->p + len, "INFINITY", (size_t) 8))
+		{
+			len += 8;
+		}
+		else
+		{
+			if (!strncasecmp (state->p + len, "INF", (size_t) 3))
+			{
+				len += 3;
+			}
+		}
+		if (len > 1)
+		{
+			state->p += len;
+			p = state->p;
+			mps_skip_comment (state);
+			if (!END_LINE (state->p) && p == state->p)
+			{
+				/* found no blanks so this INF/INFINITY is the prefix 
+				 * of something else */
+				state->p -= len;
+				return 1;								/* no coef found */
+			}
+			else
+			{
+				if (sign == 1)
+					EGLPNUM_TYPENAME_EGlpNumCopy (*coef, EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+				else
+					EGLPNUM_TYPENAME_EGlpNumCopy (*coef, EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+				state->field_num++;
+				ILL_RESULT (0, "EGLPNUM_TYPENAME_ILLmps_next_bound");
+			}
+		}
+		if (get_double (state, 0, coef))
+		{
+			ILL_RESULT (0, "EGLPNUM_TYPENAME_ILLmps_next_bound");
+		}
+		else
+		{
+			ILL_RESULT (1, "EGLPNUM_TYPENAME_ILLmps_next_bound");	/* no coef found */
+		}
+	}
+	ILL_RETURN (1, "EGLPNUM_TYPENAME_ILLmps_next_bound");
+}
+
+static char ILLmps_next_field_is_number (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state)
+{
+	EGLPNUM_TYPE d;
+	int len = 0;
+
+	if (!mps_skip_comment (state))
+	{
+		EGLPNUM_TYPENAME_EGlpNumInitVar (d);
+		len = get_double (state, 1, &d);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (d);
+	}
+	return (len > 0);
+}
+
+void EGLPNUM_TYPENAME_ILLmps_check_end_of_line (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state)
+{
+	if (!mps_skip_comment (state))
+	{
+		if (!END_LINE (state->p))
+		{
+			EGLPNUM_TYPENAME_ILLmps_warn (state, "Extra fields on line.");
+		}
+	}
+}
+
+void EGLPNUM_TYPENAME_ILLmps_set_end_of_line (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state)
+{
+	*state->p = '\n';
+}
+
+int EGLPNUM_TYPENAME_ILLmps_set_section (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	const ILLmps_section sec)
+{
+	int rval = 0;
+
+	ILL_FAILfalse (sec != ILL_MPS_NONE, "must be in a proper section");
+	if (state->section[sec])
+	{
+		rval = EGLPNUM_TYPENAME_ILLmps_error (state, "Two %s sections.\n", EGLPNUM_TYPENAME_ILLmps_section_name[sec]);
+	}
+	state->section[sec]++;
+	state->active = sec;
+CLEANUP:
+	ILL_RESULT (rval, "EGLPNUM_TYPENAME_ILLmps_set_section");
+}
+
+int EGLPNUM_TYPENAME_ILLmps_int_sos_mode (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state)
+{
+	if (!strcmp (state->field, "'INTORG'"))
+	{
+		if (state->intvar)
+		{
+			return !EGLPNUM_TYPENAME_ILLmps_error (state, "'INTEND' expected.\n");
+		}
+		else
+		{
+			state->intvar = 1;
+			ILL_RESULT (0, "EGLPNUM_TYPENAME_ILLmps_int_sos_mode");
+		}
+	}
+	if (!strcmp (state->field, "'INTEND'"))
+	{
+		if (state->intvar)
+		{
+			state->intvar = 0;
+			ILL_RESULT (0, "EGLPNUM_TYPENAME_ILLmps_int_sos_mode");
+		}
+		else
+		{
+			return !EGLPNUM_TYPENAME_ILLmps_error (state, "'INTORG' expected.\n");
+		}
+	}
+	if (!strcmp (state->field, "'SOSORG'"))
+	{
+		if (state->sosvar)
+		{
+			return !EGLPNUM_TYPENAME_ILLmps_error (state, "'SOSEND' expected.\n");
+		}
+		else
+		{
+			state->sosvar = 1;
+			ILL_RESULT (0, "EGLPNUM_TYPENAME_ILLmps_int_sos_mode");
+		}
+	}
+	if (!strcmp (state->field, "'SOSEND'"))
+	{
+		if (state->sosvar)
+		{
+			state->sosvar = 0;
+			ILL_RESULT (0, "EGLPNUM_TYPENAME_ILLmps_int_sos_mode");
+		}
+		else
+		{
+			return !EGLPNUM_TYPENAME_ILLmps_error (state, "'SOSORG' expected.\n");
+		}
+	}
+	return EGLPNUM_TYPENAME_ILLmps_error (state, "%s is not a MARKER field.\n", state->field);
+}
+
+const char *EGLPNUM_TYPENAME_ILLmps_possibly_blank_name (
+	const char *field,
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	ILLsymboltab * tab)
+{
+	int ind;
+
+	if (ILLsymboltab_lookup (tab, field, &ind) == 0)
+	{
+		/* Possibly a blank identifier on the line */
+		if (ILLmps_next_field_is_number (state))
+		{
+			/* assume a blank bound ident */
+			return " ";
+		}
+		else
+		{
+			return field;
+		}
+	}
+	else
+	{
+		return field;
+	}
+}
+
+int EGLPNUM_TYPENAME_ILLmps_empty_key (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state)
+{
+	return state->key[0] == '\0';
+}
+
+int EGLPNUM_TYPENAME_ILLmps_empty_field (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state)
+{
+	return state->field[0] == '\0';
+}
+
+static void mps_err (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	int isError,
+	const char *format,
+	va_list args)
+{
+	int rval = 0;
+	const char *type = (isError) ? "MPS Error" : "MPS Warning";
+	int errtype, slen, at;
+	EGLPNUM_TYPENAME_qsformat_error error;
+	char error_desc[256];
+
+	ILL_FAILfalse_no_rval (format != 0, "format != 0");
+	ILL_FAILfalse_no_rval (format[0] != '\0', "format[0] != '0'");
+	ILL_FAILfalse_no_rval (state != 0, "state != 0");
+	ILL_FAILfalse_no_rval (state->file != 0, "state->file != 0");
+
+	if (state->p == 0)
+	{
+		at = -1;
+	}
+	else
+	{
+		ILL_FAILfalse (state->p >= state->line, "state->p >= state->line");
+		at = state->p - state->line;
+	}
+	vsprintf (error_desc, format, args);
+	slen = strlen (error_desc);
+	if ((slen > 0) && error_desc[slen - 1] != '\n')
+	{
+		error_desc[slen] = '\n';
+		error_desc[slen + 1] = '\0';
+	}
+
+	if (state->file->error_collector != 0)
+	{
+		errtype = (isError) ? QS_MPS_FORMAT_ERROR : QS_MPS_FORMAT_WARN;
+		EGLPNUM_TYPENAME_ILLformat_error_create (&error, errtype, error_desc,
+														(int) (state->line_num), state->line, at);
+		EGLPNUM_TYPENAME_ILLformat_error (state->file->error_collector, &error);
+		EGLPNUM_TYPENAME_ILLformat_error_delete (&error);
+	}
+	else
+	{
+		QSlog("%s %d: %s\t", state->file_name, state->line_num,
+								state->line);
+		QSlog("%s: %s", type, error_desc);
+	}
+CLEANUP:
+	;
+}
+
+int EGLPNUM_TYPENAME_ILLmps_error (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	const char *format,
+	...)
+{
+	va_list args;
+
+	va_start (args, format);
+	mps_err (state, TRUE, format, args);
+	/* ILL_RESULT(1, "EGLPNUM_TYPENAME_ILLmps_error"); */
+	return 1;
+}
+
+void EGLPNUM_TYPENAME_ILLmps_warn (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	const char *format,
+	...)
+{
+	va_list args;
+
+	va_start (args, format);
+	if (format != 0)
+	{
+		mps_err (state, FALSE, format, args);
+	}
+}
diff --git a/qsopt_ex/read_mps.h b/qsopt_ex/read_mps.h
new file mode 100644
index 0000000..b0e1196
--- /dev/null
+++ b/qsopt_ex/read_mps.h
@@ -0,0 +1,97 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* $RCSfile: rd_mps.h,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:57:39 $ */
+#ifndef EGLPNUM_TYPENAME_READ_MPS_STATE_H
+#define EGLPNUM_TYPENAME_READ_MPS_STATE_H
+
+#include "symtab.h"
+#include "basicdefs.h"
+
+#include "readline_EGLPNUM_TYPENAME.h"
+
+
+typedef struct EGLPNUM_TYPENAME_ILLread_mps_state_struct
+{
+	int section[ILL_MPS_N_SECTIONS];
+	ILLmps_section active;
+	const char *file_name;
+	EGLPNUM_TYPENAME_qsline_reader *file;
+	unsigned int line_num;
+	unsigned int field_num;				/* number of successfully read fields on line */
+	int intvar;
+	int sosvar;
+	char line[ILL_namebufsize];
+	char key[ILL_namebufsize];
+	char field[ILL_namebufsize];
+	char *obj;
+	char *p;											/* ptr to next 'unread' character */
+}
+EGLPNUM_TYPENAME_ILLread_mps_state;
+
+extern int EGLPNUM_TYPENAME_ILLmps_state_init (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPENAME_qsline_reader * file,
+	const char *fname);
+extern void EGLPNUM_TYPENAME_ILLmps_state_clear (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state);
+extern int EGLPNUM_TYPENAME_ILLmps_set_section (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	const ILLmps_section sec);
+
+extern int EGLPNUM_TYPENAME_ILLmps_next_line (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state);
+extern int EGLPNUM_TYPENAME_ILLmps_next_field (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state);
+extern int EGLPNUM_TYPENAME_ILLmps_next_coef (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPE * coef);
+extern int EGLPNUM_TYPENAME_ILLmps_next_bound (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	EGLPNUM_TYPE * coef);
+extern void EGLPNUM_TYPENAME_ILLmps_check_end_of_line (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state);
+extern void EGLPNUM_TYPENAME_ILLmps_set_end_of_line (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state);
+
+extern int EGLPNUM_TYPENAME_ILLmps_int_sos_mode (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state);
+
+extern const char *EGLPNUM_TYPENAME_ILLmps_possibly_blank_name (
+	const char *field,
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	ILLsymboltab * tab);
+extern int EGLPNUM_TYPENAME_ILLmps_empty_key (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state);
+extern int EGLPNUM_TYPENAME_ILLmps_empty_field (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state);
+
+extern int EGLPNUM_TYPENAME_ILLmps_error (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	const char *format,
+	...);
+extern void EGLPNUM_TYPENAME_ILLmps_warn (
+	EGLPNUM_TYPENAME_ILLread_mps_state * state,
+	const char *format,
+	...);
+
+#endif
diff --git a/qsopt_ex/reader.c b/qsopt_ex/reader.c
new file mode 100644
index 0000000..32db02e
--- /dev/null
+++ b/qsopt_ex/reader.c
@@ -0,0 +1,283 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: reader.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+
+#include "reader.h"
+#include "qstruct.h"
+#include "qsopt.h"
+
+static int TRACE = 0;
+static int TEST_ERROR_COLLECTOR = 0;
+static int TEST_ERROR_MEMORY = 0;
+
+static char *fname = (char *) NULL;
+static char *out_lp = (char *) NULL;
+static char *out_mps = (char *) NULL;
+static int lpfile = 0;
+static int stats = 0;
+
+static void usage (
+	char *s);
+
+static int parseargs (
+	int ac,
+	char **av);
+
+static int add_error (
+	void *dest,
+	QSformat_error error)
+{
+	const char *type = "Error";
+	const char *line;
+	int tp, i, at;
+	FILE *out = (FILE *) dest;
+
+	at = QSerror_get_pos (error);
+	tp = QSerror_get_type (error);
+	type = QSformat_error_type_string (tp);
+
+	fprintf (out, "ADD: ");
+	fprintf (out, "%s  line %d pos %d\n",
+					 type, QSerror_get_line_number (error), at);
+	line = QSerror_get_line (error);
+	if (line != NULL)
+	{
+		fprintf (out, "LINE %s", line);
+		if (at >= 0)
+		{
+			fprintf (out, ".....");
+			for (i = 0; i <= (at - 1); i++)
+			{
+				if (line[i] == '\t')
+				{
+					fputc ('\t', out);
+				}
+				else
+				{
+					fputc ('.', out);
+				}
+			}
+			fprintf (out, "^\n");
+		}
+	}
+	else
+	{
+		fprintf (out, "NO LINE\n");
+	}
+
+	fprintf (out, "MSG: %s\n", QSerror_get_desc (error));
+	return 0;
+}
+
+QSLIB_INTERFACE int reader_main (
+	int ac,
+	char **av)
+{
+	int rval = 0;
+	int rvalmps = 0;
+	int rvallp = 0;
+	QSdata *p = NULL;
+	ILLutil_timer timer_read;
+	ILLutil_timer timer_write;
+	FILE *fin = NULL;
+	QSline_reader reader = NULL;
+	QSerror_collector collector = NULL;
+	QSerror_memory error_mem = NULL;
+	QSformat_error e = NULL;
+
+	if (parseargs (ac, av))
+		goto CLEANUP;
+
+	ILLutil_init_timer (&timer_read, "READER_READ");
+	ILLutil_start_timer (&timer_read);
+	if (TEST_ERROR_COLLECTOR || TEST_ERROR_MEMORY)
+	{
+		fin = fopen (fname, "r");
+		reader = QSline_reader_new ((void *) fgets, fin);
+		if (TEST_ERROR_COLLECTOR)
+		{
+			collector = QSerror_collector_new ((void *) add_error, stderr);
+		}
+		if (TEST_ERROR_MEMORY)
+		{
+			error_mem = QSerror_memory_create (0);
+			ILL_CHECKnull (error_mem, "Could not make error memory");
+			collector = QSerror_memory_collector_new (error_mem);
+		}
+		if (fin == NULL)
+		{
+			fprintf (stderr, "Can't open \"%s\" for reading.\n", fname);
+		}
+		rval = (fin == NULL) || (reader == NULL) || (collector == NULL);
+		ILL_CLEANUP_IF (rval);
+
+		QSline_reader_set_error_collector (reader, collector);
+		p = QSget_prob (reader, fname, (lpfile == 0) ? "MPS" : "LP");
+
+		if (TEST_ERROR_MEMORY)
+		{
+			int n = QSerror_memory_get_nerrors (error_mem);
+
+			fprintf (stderr, "#error %d\n", n);
+			for (e = QSerror_memory_get_last_error (error_mem);
+					 e != NULL; e = QSerror_memory_get_prev_error (e))
+			{
+				QSerror_print (stderr, e);
+			}
+		}
+	}
+	else
+	{
+		if (lpfile == 0)
+		{
+			p = QSread_prob (fname, "MPS");
+		}
+		else
+		{
+			p = QSread_prob (fname, "LP");
+		}
+	}
+	ILL_IFTRACE ("QSread_prob %s\n", fname);
+	ILLutil_stop_timer (&timer_read, 1);
+	rval = (p == NULL);
+	fprintf (stdout,
+					 "read \"%s\" %s.\n", fname, (rval == 0) ? "succeeded" : "failed");
+	ILL_CLEANUP_IF (rval);
+
+	if (stats)
+	{
+		fprintf (stdout, "\n");
+		fprintf (stdout, "The problem \"%s\" has %d rows and %d cols.\n",
+						 QSget_probname (p), QSget_rowcount (p), QSget_colcount (p));
+	}
+	ILLutil_init_timer (&timer_write, "READER_WRITE");
+	ILLutil_start_timer (&timer_write);
+	if (out_mps)
+	{
+		fprintf (stdout, "\n");
+		rvalmps = QSwrite_prob (p, out_mps, "MPS");
+		fprintf (stdout, "write \"%s\" %s.\n", out_mps,
+						 (rvalmps == 0) ? "succeeded" : "failed");
+	}
+	if (out_lp)
+	{
+		fprintf (stdout, "\n");
+		rvallp = QSwrite_prob (p, out_lp, "LP");
+		fprintf (stdout, "write \"%s\" %s.\n", out_lp,
+						 (rvallp == 0) ? "succeeded" : "failed");
+	}
+	ILLutil_stop_timer (&timer_write, 1);
+
+	rval = rvalmps || rvallp;
+	ILL_CLEANUP_IF (rval);
+
+CLEANUP:
+
+	if (p != NULL)
+		QSfree_prob (p);
+	if (fin != NULL)
+		fclose (fin);
+	if (reader != NULL)
+		QSline_reader_free (reader);
+	if (collector != NULL)
+		QSerror_collector_free (collector);
+	if (error_mem != NULL)
+		QSerror_memory_free (error_mem);
+
+	return rval;									/* main return */
+}
+
+static void usage (
+	char *s)
+{
+	fprintf (stderr, "Usage: %s [- below -] prob_file\n", s);
+	fprintf (stderr, "   -L    input file is in lp format (default: mps)\n");
+	fprintf (stderr, "   -s    print information about problem to stdout\n");
+	fprintf (stderr, "   -l f  write lp in LP format to file f\n");
+	fprintf (stderr, "   -m f  write lp in MPS format to file f\n");
+#if 0
+	fprintf (stderr, "   -E    test error_memory\n");
+	fprintf (stderr, "   -e    test error_collector\n");
+#endif
+}
+
+static int parseargs (
+	int ac,
+	char **av)
+{
+	int c;
+	int boptind = 1;
+	char *boptarg = (char *) NULL;
+
+	while ((c =
+					ILLutil_bix_getopt (ac, av, "Ll:m:tseE", &boptind, &boptarg)) != EOF)
+		switch (c)
+		{
+		case 'L':
+			lpfile = 1;
+			break;
+		case 'l':
+			out_lp = boptarg;
+			break;
+		case 'm':
+			out_mps = boptarg;
+			break;
+		case 's':
+			stats = 1;
+			break;
+		case 't':
+			TRACE++;
+			break;
+#if 0
+		case 'E':
+			TEST_ERROR_MEMORY++;
+			break;
+		case 'e':
+			TEST_ERROR_COLLECTOR++;
+			break;
+#endif
+		case '?':
+		default:
+			usage (av[0]);
+			return 1;
+		}
+
+	if (boptind != (ac - 1))
+	{
+		usage (av[0]);
+		return 1;
+	}
+
+	fname = av[boptind++];
+	return 0;
+}
+
+
+#ifndef WIN32
+int main (
+	int ac,
+	char **av)
+{
+	return reader_main (ac, av);
+}
+#endif
diff --git a/qsopt_ex/reader.h b/qsopt_ex/reader.h
new file mode 100644
index 0000000..03bcd82
--- /dev/null
+++ b/qsopt_ex/reader.h
@@ -0,0 +1,33 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/*  RCS_INFO = "$RCSfile: reader.h,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:57:39 $"; */
+#ifndef READER_H
+#define READER_H
+
+#include "qsopt.h"
+
+QSLIB_INTERFACE int reader_main (
+	int argc,
+	char **argv);
+
+#endif
diff --git a/qsopt_ex/readline.c b/qsopt_ex/readline.c
new file mode 100644
index 0000000..d8f35e2
--- /dev/null
+++ b/qsopt_ex/readline.c
@@ -0,0 +1,62 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCS_INFO = "$Id: line_reader.c,v 1.2 2003/11/05 16:49:52 meven Exp $"; */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "allocrus.h"
+#include "eg_io.h"
+#include "except.h"
+#include "readline_EGLPNUM_TYPENAME.h"
+
+
+/* #ifdef _WINDOWS*/
+EGLPNUM_TYPENAME_qsline_reader *EGLPNUM_TYPENAME_ILLline_reader_new (
+	EGLPNUM_TYPENAME_qsread_line_fct fct,
+	void *data_src)
+{
+	EGLPNUM_TYPENAME_qsline_reader *reader;
+	int rval = 0;
+
+	ILL_NEW (reader, EGLPNUM_TYPENAME_qsline_reader);
+	if (reader != NULL)
+	{
+		reader->read_line_fct = fct;
+		reader->data_src = data_src;
+		reader->error_collector = NULL;
+	}
+CLEANUP:
+	return reader;
+}
+
+void EGLPNUM_TYPENAME_ILLline_reader_free (
+	EGLPNUM_TYPENAME_qsline_reader * reader)
+{
+	ILL_IFFREE (reader, EGLPNUM_TYPENAME_qsline_reader);
+}
+
+/* #endif */
diff --git a/qsopt_ex/readline.h b/qsopt_ex/readline.h
new file mode 100644
index 0000000..ac2f14c
--- /dev/null
+++ b/qsopt_ex/readline.h
@@ -0,0 +1,64 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCSINFO $Id: rdline.h,v 1.2 2003/11/05 16:57:39 meven Exp $ */
+#ifndef EGLPNUM_TYPENAME_LINE_READER_FILE_H
+#define EGLPNUM_TYPENAME_LINE_READER_FILE_H
+
+#include "qsopt_EGLPNUM_TYPENAME.h"
+#include "format_EGLPNUM_TYPENAME.h"
+
+/* #ifdef _WINDOWS */
+typedef char *(
+	*EGLPNUM_TYPENAME_qsread_line_fct) (
+	char *s,
+	int size,
+	void *src);
+
+typedef struct EGLPNUM_TYPENAME_qsline_reader
+{
+	EGLPNUM_TYPENAME_qsread_line_fct read_line_fct;
+	void *data_src;
+	struct EGLPNUM_TYPENAME_qserror_collector *error_collector;
+}
+EGLPNUM_TYPENAME_qsline_reader;
+
+EGLPNUM_TYPENAME_qsline_reader *EGLPNUM_TYPENAME_ILLline_reader_new (
+	EGLPNUM_TYPENAME_qsread_line_fct fct,
+	void *data_src);
+void EGLPNUM_TYPENAME_ILLline_reader_free (
+	EGLPNUM_TYPENAME_qsline_reader * reader);
+
+#define EGLPNUM_TYPENAME_ILLline_reader_get(s, size, reader)  \
+	(reader)->read_line_fct(s, size, (reader)->data_src)
+									 /* used by parsers to retrieve next input line */
+/* #else  
+ *
+ * typedef FILE EGLPNUM_TYPENAME_qsline_reader; 
+ *
+ * #define EGLPNUM_TYPENAME_ILLline_reader_new(fct, data) ((FILE*) (data)) 
+ * #define EGLPNUM_TYPENAME_ILLline_reader_free(reader)  
+ * #define EGLPNUM_TYPENAME_ILLline_reader_get(s, size, reader) fgets(s,size,reader) 
+ * #endif 
+ */
+
+#endif
diff --git a/qsopt_ex/reporter.c b/qsopt_ex/reporter.c
new file mode 100644
index 0000000..52e2f62
--- /dev/null
+++ b/qsopt_ex/reporter.c
@@ -0,0 +1,94 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCS_INFO = "$Id: reporter.c,v 1.1 2003/11/05 16:49:52 meven Exp $"; */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "reporter.h"
+#include "except.h"
+
+
+int ILL_fprintf (
+	void *dest,
+	const char *s)
+{
+	if (s != NULL)
+		return fputs(s, (FILE *)dest);
+	return 0;
+}
+
+void ILLstring_reporter_init (
+	qsstring_reporter * reporter,
+	qsreport_string_fct fct,
+	void *dest)
+{
+	int rval = 0;
+
+	ILL_FAILfalse (reporter != NULL, "Must get non NULL reporter");
+	if (reporter != NULL)
+	{
+		reporter->report_fct = fct;
+		reporter->dest = dest;
+	}
+CLEANUP:
+	return;
+}
+
+void ILLstring_reporter_copy (
+	qsstring_reporter * dest,
+	qsstring_reporter * src)
+{
+	*dest = *src;
+}
+
+
+#ifdef REPORTER_MAIN
+static int string_reporter_main (
+	int ac,
+	char **av)
+{
+	int i = 0;
+	qsstring_reporter reporter;
+
+	ILLstring_reporter_init (&reporter, ILL_fprintf, stdout);
+	for (i = 0; i < ac; i++)
+	{
+		(void) ILLstring_report (av[i], &reporter);
+		(void) ILLstring_report ("\n", &reporter);
+	}
+	(void) ILLstring_report (NULL, &reporter);
+
+	return 0;
+}
+
+int main (
+	int ac,
+	char **av)
+{
+	return string_reporter_main (ac, av);
+}
+#endif
diff --git a/qsopt_ex/reporter.h b/qsopt_ex/reporter.h
new file mode 100644
index 0000000..76be2e0
--- /dev/null
+++ b/qsopt_ex/reporter.h
@@ -0,0 +1,59 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* $RCSfile: reporter.h,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:57:39 $ */
+#ifndef REPORTER_FILE
+#define REPORTER_FILE
+
+#include "eg_io.h"
+
+typedef int (
+	*qsreport_string_fct) (
+	void *dest,
+	const char *s);
+
+typedef struct qsstring_reporter
+{
+	qsreport_string_fct report_fct;
+	void *dest;
+}
+qsstring_reporter;
+
+extern int ILL_fprintf (
+	void *dest,
+	const char *s);
+
+void ILLstring_reporter_init (
+	qsstring_reporter * reporter,
+	qsreport_string_fct fct,
+	void *dest);
+
+void ILLstring_reporter_copy (
+	qsstring_reporter * dest,
+	qsstring_reporter * src);
+
+#define ILLstring_report(s, reporter)  \
+	((reporter)->report_fct((reporter)->dest, s) < 0)
+									 /* used from with ILL fct to report progress */
+
+/* REPORTER_FILE */
+#endif
diff --git a/qsopt_ex/simplex.c b/qsopt_ex/simplex.c
new file mode 100644
index 0000000..adfbdaf
--- /dev/null
+++ b/qsopt_ex/simplex.c
@@ -0,0 +1,3026 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: simplex.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+static int TRACE = 0;
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "logging-private.h"
+
+#include "eg_lpnum.h"
+#include "eg_io.h"
+#include "except.h"
+#include "zeit.h"
+#include "util.h"
+
+#define QSOPT_CURRENT_PRECICION
+#include "basicdefs.h"
+#include "lpdata_EGLPNUM_TYPENAME.h"
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+
+#include "stddefs.h"
+#include "fct_EGLPNUM_TYPENAME.h"
+#include "ratio_EGLPNUM_TYPENAME.h"
+#include "price_EGLPNUM_TYPENAME.h"
+#include "basis_EGLPNUM_TYPENAME.h"
+#include "simplex_EGLPNUM_TYPENAME.h"
+#include "dstruct_EGLPNUM_TYPENAME.h"
+#include "qstruct_EGLPNUM_TYPENAME.h"
+#include "qsopt_EGLPNUM_TYPENAME.h"
+#include "lib_EGLPNUM_TYPENAME.h"								/* for EGLPNUM_TYPENAME_ILLlib_writebasis */
+#include "lp_EGLPNUM_TYPENAME.h"									/* for EGLPNUM_TYPENAME_ILLwrite_lp */
+
+
+static void init_lp_status_info (
+	EGLPNUM_TYPENAME_lp_status_info * ls),
+  init_simplex_tols (
+	EGLPNUM_TYPENAME_lpinfo * lp),
+  monitor_iter (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * p,
+	EGLPNUM_TYPENAME_iter_info * it,
+	int cphase),
+  get_current_stat (
+	EGLPNUM_TYPENAME_lp_status_info * p,
+	int algorithm,
+	int *bstat);
+
+static int terminate_simplex (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int phase,
+	EGLPNUM_TYPENAME_iter_info * it),
+  primal_phaseI_step (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * pinf,
+	EGLPNUM_TYPENAME_svector * updz,
+	EGLPNUM_TYPENAME_svector * wz,
+	EGLPNUM_TYPENAME_iter_info * it),
+  primal_phaseII_step (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * pinf,
+	EGLPNUM_TYPENAME_svector * updz,
+	EGLPNUM_TYPENAME_svector * wz,
+	EGLPNUM_TYPENAME_iter_info * it),
+  dual_phaseI_step (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * pinf,
+	EGLPNUM_TYPENAME_svector * updz,
+	EGLPNUM_TYPENAME_svector * wz,
+	EGLPNUM_TYPENAME_iter_info * it),
+  dual_phaseII_step (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * pinf,
+	EGLPNUM_TYPENAME_svector * updz,
+	EGLPNUM_TYPENAME_svector * wz,
+	EGLPNUM_TYPENAME_iter_info * it),
+  report_value (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_iter_info * it,
+	const char *value_name,
+	EGLPNUM_TYPE value);
+
+
+void EGLPNUM_TYPENAME_ILLsimplex_init_lpinfo (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	EGLPNUM_TYPENAME_ILLbasis_init_basisinfo (lp);
+	EGLPNUM_TYPENAME_init_internal_lpinfo (lp);
+}
+
+void EGLPNUM_TYPENAME_ILLsimplex_free_lpinfo (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	if (lp)
+	{
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->lz);
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->uz);
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->cz);
+		EGLPNUM_TYPENAME_ILLbasis_free_basisinfo (lp);
+		EGLPNUM_TYPENAME_free_internal_lpinfo (lp);
+	}
+}
+
+void EGLPNUM_TYPENAME_ILLsimplex_load_lpinfo (
+	EGLPNUM_TYPENAME_ILLlpdata * qslp,
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	lp->basisid = -1;
+	lp->maxiter = 500000;
+	lp->maxtime = 300000;
+	//lp->iterskip = 10;
+	lp->iterskip = 100;
+	EGLPNUM_TYPENAME_EGlpNumCopy (lp->objbound, EGLPNUM_TYPENAME_INFTY);
+	lp->O = qslp;
+}
+
+void EGLPNUM_TYPENAME_ILLsimplex_set_bound (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	const EGLPNUM_TYPE * objbound,
+	int sense)
+{
+	EGLPNUM_TYPENAME_EGlpNumCopy (lp->objbound, *objbound);
+	if (sense == EGLPNUM_TYPENAME_ILL_MAX)
+		EGLPNUM_TYPENAME_EGlpNumSign (lp->objbound);
+}
+
+static void init_lp_status_info (
+	EGLPNUM_TYPENAME_lp_status_info * ls)
+{
+	ls->optimal = 0;
+	ls->primal_feasible = 0;
+	ls->primal_infeasible = 0;
+	ls->primal_unbounded = 0;
+	ls->dual_feasible = 0;
+	ls->dual_infeasible = 0;
+	ls->dual_unbounded = 0;
+}
+
+static void init_simplex_tols (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	EGLPNUM_TYPENAME_EGlpNumCopy (lp->tol->pfeas_tol, EGLPNUM_TYPENAME_PFEAS_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumCopy (lp->tol->dfeas_tol, EGLPNUM_TYPENAME_DFEAS_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumCopy (lp->tol->pivot_tol, EGLPNUM_TYPENAME_PIVOT_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumCopy (lp->tol->szero_tol, EGLPNUM_TYPENAME_SZERO_TOLER);
+	EGLPNUM_TYPENAME_EGlpNumCopy (lp->tol->ip_tol, lp->tol->pfeas_tol);
+	EGLPNUM_TYPENAME_EGlpNumCopy (lp->tol->id_tol, lp->tol->dfeas_tol);
+	if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (lp->tol->ip_tol))
+	{
+#if VERBOSE_LEVEL <= DEBUG
+		MESSAGE (VERBOSE_LEVEL, "ip_tol %lg", EGLPNUM_TYPENAME_EGlpNumToLf (lp->tol->ip_tol));
+		MESSAGE (VERBOSE_LEVEL, "eps %lg", EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_epsLpNum));
+		MESSAGE (VERBOSE_LEVEL, "EGLPNUM_TYPENAME_PFEAS_TOLER %lg", EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_PFEAS_TOLER));
+#endif
+		EGLPNUM_TYPENAME_EGlpNumDivUiTo (lp->tol->ip_tol, 2UL);
+	}
+	if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (lp->tol->id_tol))
+	{
+#if VERBOSE_LEVEL <= DEBUG
+		MESSAGE (VERBOSE_LEVEL, "id_tol %lg", EGLPNUM_TYPENAME_EGlpNumToLf (lp->tol->id_tol));
+#endif
+		EGLPNUM_TYPENAME_EGlpNumDivUiTo (lp->tol->id_tol, 2UL);
+	}
+}
+
+void EGLPNUM_TYPENAME_init_internal_lpinfo (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	int rval = 0;
+
+	lp->nrows = 0;
+	lp->nnbasic = 0;
+	lp->localrows = 0;
+	lp->rowcnt = 0;
+	lp->rowbeg = 0;
+	lp->rowind = 0;
+	lp->rowval = 0;
+	lp->cz = 0;
+	lp->lz = 0;
+	lp->uz = 0;
+	lp->xbz = 0;
+	lp->piz = 0;
+	lp->dz = 0;
+	lp->pIxbz = 0;
+	lp->pIpiz = 0;
+	lp->pIdz = 0;
+	lp->vtype = 0;
+	lp->vclass = 0;
+	lp->iwork = 0;
+	lp->upd.perm = 0;
+	lp->upd.ix = 0;
+	lp->upd.t = 0;
+	lp->bfeas = 0;
+	lp->dfeas = 0;
+	lp->tol = 0;
+	lp->cnts = 0;
+	lp->bchanges = 0;
+	lp->cchanges = 0;
+	EGLPNUM_TYPENAME_ILLsvector_init (&(lp->zz));
+	EGLPNUM_TYPENAME_ILLsvector_init (&(lp->yjz));
+	EGLPNUM_TYPENAME_ILLsvector_init (&(lp->zA));
+	EGLPNUM_TYPENAME_ILLsvector_init (&(lp->work));
+	EGLPNUM_TYPENAME_ILLsvector_init (&(lp->srhs));
+	EGLPNUM_TYPENAME_ILLsvector_init (&(lp->ssoln));
+	ILL_SAFE_MALLOC (lp->tol, 1, EGLPNUM_TYPENAME_tol_struct);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (lp->tol->pfeas_tol);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (lp->tol->dfeas_tol);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (lp->tol->pivot_tol);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (lp->tol->szero_tol);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (lp->tol->ip_tol);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (lp->tol->id_tol);
+	ILL_SAFE_MALLOC (lp->cnts, 1, EGLPNUM_TYPENAME_count_struct);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (lp->cnts->y_ravg);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (lp->cnts->z_ravg);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (lp->cnts->za_ravg);
+CLEANUP:
+	if (rval)
+	{
+		QSlog("no memory, in %s, exit", __func__);
+		exit (1);
+	}
+}
+
+void EGLPNUM_TYPENAME_free_internal_lpinfo (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	EGLPNUM_TYPENAME_bndinfo *binfo = 0;
+	EGLPNUM_TYPENAME_coefinfo *cinfo = 0;
+
+	if (lp->localrows)
+	{
+		ILL_IFFREE (lp->rowcnt, int);
+		ILL_IFFREE (lp->rowbeg, int);
+		ILL_IFFREE (lp->rowind, int);
+
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->rowval);
+		lp->localrows = 0;
+	}
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->lz);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->uz);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->cz);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->xbz);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->piz);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->pIpiz);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->dz);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->pIdz);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->pIxbz);
+
+	ILL_IFFREE (lp->vtype, int);
+	ILL_IFFREE (lp->vclass, char);
+
+	EGLPNUM_TYPENAME_ILLsvector_free (&(lp->zz));
+	EGLPNUM_TYPENAME_ILLsvector_free (&(lp->yjz));
+	EGLPNUM_TYPENAME_ILLsvector_free (&(lp->zA));
+	EGLPNUM_TYPENAME_ILLsvector_free (&(lp->work));
+	EGLPNUM_TYPENAME_ILLsvector_free (&(lp->srhs));
+	EGLPNUM_TYPENAME_ILLsvector_free (&(lp->ssoln));
+	ILL_IFFREE (lp->iwork, int);
+	ILL_IFFREE (lp->upd.perm, int);
+	ILL_IFFREE (lp->upd.ix, int);
+
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->upd.t);
+
+	ILL_IFFREE (lp->bfeas, int);
+	ILL_IFFREE (lp->dfeas, int);
+
+	if (lp->tol)
+	{
+		EGLPNUM_TYPENAME_EGlpNumClearVar (lp->tol->pfeas_tol);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (lp->tol->dfeas_tol);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (lp->tol->pivot_tol);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (lp->tol->szero_tol);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (lp->tol->ip_tol);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (lp->tol->id_tol);
+		ILL_IFFREE (lp->tol, EGLPNUM_TYPENAME_tol_struct);
+	}
+	if (lp->cnts)
+	{
+		EGLPNUM_TYPENAME_EGlpNumClearVar (lp->cnts->y_ravg);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (lp->cnts->z_ravg);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (lp->cnts->za_ravg);
+		ILL_IFFREE (lp->cnts, EGLPNUM_TYPENAME_count_struct);
+	}
+
+	while (lp->bchanges)
+	{
+		binfo = lp->bchanges;
+		EGLPNUM_TYPENAME_EGlpNumClearVar (binfo->pbound);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (binfo->cbound);
+		lp->bchanges = binfo->next;
+		ILL_IFFREE (binfo, EGLPNUM_TYPENAME_bndinfo);
+	}
+
+	while (lp->cchanges)
+	{
+		cinfo = lp->cchanges;
+		EGLPNUM_TYPENAME_EGlpNumClearVar (cinfo->pcoef);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (cinfo->ccoef);
+		lp->cchanges = cinfo->next;
+		ILL_IFFREE (cinfo, EGLPNUM_TYPENAME_coefinfo);
+	}
+}
+
+int EGLPNUM_TYPENAME_build_internal_lpinfo (
+	EGLPNUM_TYPENAME_lpinfo * lp)
+{
+	int rval = 0;
+	int i, n;
+	EGLPNUM_TYPENAME_ILLlpdata *qslp = lp->O;
+	EGLPNUM_TYPENAME_ILLlp_sinfo *S = lp->O->sinfo;
+	EGLPNUM_TYPE *lower, *upper, *obj;
+	EGLPNUM_TYPENAME_ILLlp_rows lprows;
+	EGLPNUM_TYPENAME_ILLmatrix *A;
+
+	init_lp_status_info (&(lp->probstat));
+	init_lp_status_info (&(lp->basisstat));
+
+	if (S != 0)
+	{
+		lp->nrows = S->nrows;
+		lp->ncols = S->ncols;
+		lp->bz = S->rhs;
+		lower = S->lower;
+		upper = S->upper;
+		obj = S->obj;
+		A = &(S->A);
+	}
+	else
+	{
+		lp->nrows = qslp->nrows;
+		lp->ncols = qslp->ncols;
+		lp->bz = qslp->rhs;
+		lower = qslp->lower;
+		upper = qslp->upper;
+		obj = qslp->obj;
+		A = &(qslp->A);
+	}
+
+	lp->matbeg = A->matbeg;
+	lp->matcnt = A->matcnt;
+	lp->matind = A->matind;
+	lp->matval = A->matval;
+
+	lp->nnbasic = lp->ncols - lp->nrows;
+
+	lp->lz = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->ncols);
+	lp->cz = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->ncols);
+	lp->uz = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->ncols);
+	if (!lp->lz || !lp->uz || !lp->cz)
+	{
+		QSlog("EGLPNUM_TYPENAME_build_internal_lpinfo");
+		rval = 1;
+		goto CLEANUP;
+	}
+	for (i = 0; i < lp->ncols; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (lp->lz[i], lower[i]);
+		EGLPNUM_TYPENAME_EGlpNumCopy (lp->uz[i], upper[i]);
+		EGLPNUM_TYPENAME_EGlpNumCopy (lp->cz[i], obj[i]);
+		if (qslp->objsense == EGLPNUM_TYPENAME_ILL_MAX)
+		{
+			EGLPNUM_TYPENAME_EGlpNumSign (lp->cz[i]);
+		}
+	}
+
+	if (!lp->O->rA)
+	{
+		rval = EGLPNUM_TYPENAME_ILLlp_rows_init (&lprows, lp->O, 1);
+		CHECKRVALG (rval, CLEANUP);
+		lp->rowbeg = lprows.rowbeg;
+		lp->rowcnt = lprows.rowcnt;
+		lp->rowind = lprows.rowind;
+		lp->rowval = lprows.rowval;
+		lp->localrows = 1;
+	}
+	else
+	{
+		/* row format exists, just use pointers */
+		lp->rowbeg = lp->O->rA->rowbeg;
+		lp->rowcnt = lp->O->rA->rowcnt;
+		lp->rowind = lp->O->rA->rowind;
+		lp->rowval = lp->O->rA->rowval;
+		lp->localrows = 0;
+	}
+
+	lp->xbz = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+	lp->piz = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+	lp->dz = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nnbasic);
+	lp->final_phase = -1;
+	lp->infub_ix = -1;
+
+	ILL_SAFE_MALLOC (lp->vtype, lp->ncols, int);
+	ILL_SAFE_MALLOC (lp->vclass, lp->ncols, char);
+
+	rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&(lp->zz), lp->nrows);
+	CHECKRVALG (rval, CLEANUP);
+	rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&(lp->yjz), lp->nrows);
+	CHECKRVALG (rval, CLEANUP);
+	rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&(lp->zA), lp->nnbasic);
+	CHECKRVALG (rval, CLEANUP);
+	rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&(lp->work), lp->ncols);
+	CHECKRVALG (rval, CLEANUP);
+	rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&(lp->srhs), lp->nrows);
+	CHECKRVALG (rval, CLEANUP);
+	rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&(lp->ssoln), lp->nrows);
+	CHECKRVALG (rval, CLEANUP);
+	ILL_SAFE_MALLOC (lp->iwork, lp->ncols, int);
+
+	for (i = 0; i < lp->ncols; i++)
+	{
+		lp->work.indx[i] = 0;
+		EGLPNUM_TYPENAME_EGlpNumZero (lp->work.coef[i]);
+		lp->iwork[i] = 0;
+	}
+	n = lp->nrows > lp->ncols ? 2 * (lp->nrows) + 1 : 2 * (lp->ncols) + 1;
+	lp->upd.t = EGLPNUM_TYPENAME_EGlpNumAllocArray (n);
+	ILL_SAFE_MALLOC (lp->upd.perm, n, int);
+	ILL_SAFE_MALLOC (lp->upd.ix, n, int);
+
+
+	ILL_SAFE_MALLOC (lp->bfeas, lp->nrows, int);
+	ILL_SAFE_MALLOC (lp->dfeas, lp->nnbasic, int);
+
+	init_simplex_tols (lp);
+	EGLPNUM_TYPENAME_ILLfct_init_counts (lp);
+
+	lp->nbchange = 0;
+	lp->ncchange = 0;
+
+	lp->pIratio = RATIOTEST_HARRIS;
+	lp->pIIratio = RATIOTEST_HARRIS;
+	lp->dIratio = RATIOTEST_HARRIS;
+	lp->dIIratio = RATIOTEST_HARRIS;
+	lp->starttime = ILLutil_zeit ();
+	ILLutil_sprand (1, &(lp->rstate));
+
+CLEANUP:
+	if (rval)
+		EGLPNUM_TYPENAME_free_internal_lpinfo (lp);
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLsimplex_retest_psolution (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * p,
+	int phase,
+	EGLPNUM_TYPENAME_feas_info * fi)
+{
+	int rval = 0;
+	int fbid = lp->fbasisid;
+	int bid = lp->basisid;
+	EGLPNUM_TYPE *ptol = &(lp->tol->pfeas_tol);
+	EGLPNUM_TYPE *dtol = &(lp->tol->dfeas_tol);
+	EGLPNUM_TYPE *iptol = &(lp->tol->ip_tol);
+	EGLPNUM_TYPE *idtol = &(lp->tol->id_tol);
+
+	fi->pstatus = -1;
+	fi->dstatus = -1;
+	if (fbid < bid - PARAM_PRIMAL_REFACTORGAP)
+	{
+		rval = EGLPNUM_TYPENAME_ILLbasis_refactor (lp);
+		CHECKRVALG (rval, CLEANUP);
+	}
+	if (fbid < bid - PARAM_PRIMAL_RESOLVEGAP)
+		EGLPNUM_TYPENAME_ILLfct_compute_xbz (lp);
+
+	if (phase == PRIMAL_PHASEII)
+	{
+		if (fbid < bid - PARAM_PRIMAL_RESOLVEGAP)
+		{
+			EGLPNUM_TYPENAME_ILLfct_compute_piz (lp);
+			EGLPNUM_TYPENAME_ILLfct_compute_dz (lp);
+			if (p != NULL && p->p_strategy == COMPLETE_PRICING)
+				EGLPNUM_TYPENAME_ILLprice_compute_dual_inf (lp, p, NULL, 0, PRIMAL_PHASEII);
+		}
+		EGLPNUM_TYPENAME_ILLfct_compute_pobj (lp);
+		EGLPNUM_TYPENAME_ILLfct_check_pfeasible (lp, fi, *ptol);
+		EGLPNUM_TYPENAME_ILLfct_check_dfeasible (lp, fi, *dtol);
+	}
+	else if (phase == PRIMAL_PHASEI)
+	{
+		EGLPNUM_TYPENAME_ILLfct_check_pfeasible (lp, fi, *iptol);
+		if (fi->pstatus != PRIMAL_FEASIBLE)
+		{
+			if (lp->pIpiz)
+			{
+				EGLPNUM_TYPENAME_ILLfct_compute_phaseI_piz (lp);
+				EGLPNUM_TYPENAME_ILLfct_compute_phaseI_dz (lp);
+				EGLPNUM_TYPENAME_ILLfct_check_pIdfeasible (lp, fi, *idtol);
+				if (p != NULL && p->p_strategy == COMPLETE_PRICING)
+					EGLPNUM_TYPENAME_ILLprice_compute_dual_inf (lp, p, NULL, 0, PRIMAL_PHASEI);
+			}
+		}
+	}
+CLEANUP:
+	if (rval == QS_LP_CHANGE_PREC)
+	{
+		MESSAGE (__QS_SB_VERB, "Changing precision");
+		return rval;
+	}
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLsimplex_retest_dsolution (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * p,
+	int phase,
+	EGLPNUM_TYPENAME_feas_info * fi)
+{
+	int rval = 0;
+	int fbid = lp->fbasisid;
+	int bid = lp->basisid;
+	EGLPNUM_TYPE *ptol = &(lp->tol->pfeas_tol);
+	EGLPNUM_TYPE *dtol = &(lp->tol->dfeas_tol);
+	EGLPNUM_TYPE *iptol = &(lp->tol->ip_tol);
+	EGLPNUM_TYPE *idtol = &(lp->tol->id_tol);
+
+	//ILL_IFTRACE("\t%s:%s:%d\n",__func__,__FILE__,__LINE__);
+
+	fi->pstatus = -1;
+	fi->dstatus = -1;
+	if (fbid < bid - PARAM_DUAL_REFACTORGAP)
+	{
+		//ILL_IFTRACE("Refactor: %s:%s:%d\n",__func__,__FILE__,__LINE__);
+		rval = EGLPNUM_TYPENAME_ILLbasis_refactor (lp);
+		CHECKRVALG (rval, CLEANUP);
+	}
+	if (fbid < bid - PARAM_DUAL_RESOLVEGAP)
+	{
+		//ILL_IFTRACE("\t%s:%s:%d\n",__func__,__FILE__,__LINE__);
+		EGLPNUM_TYPENAME_ILLfct_compute_piz (lp);
+		EGLPNUM_TYPENAME_ILLfct_compute_dz (lp);
+	}
+
+	if (phase == DUAL_PHASEII)
+	{
+		//ILL_IFTRACE("\t%s:%s:%d\n",__func__,__FILE__,__LINE__);
+		if (fbid < bid - PARAM_DUAL_RESOLVEGAP)
+		{
+			//ILL_IFTRACE("\t%s:%s:%d\n",__func__,__FILE__,__LINE__);
+			EGLPNUM_TYPENAME_ILLfct_compute_xbz (lp);
+			CHECKRVALG (rval, CLEANUP);
+			if (p != NULL)
+			{
+				//ILL_IFTRACE("\t%s:%s:%d\n",__func__,__FILE__,__LINE__);
+				if (p->d_strategy == COMPLETE_PRICING)
+				{
+					//ILL_IFTRACE("\t%s:%s:%d\n",__func__,__FILE__,__LINE__);
+					EGLPNUM_TYPENAME_ILLprice_compute_primal_inf (lp, p, NULL, 0, DUAL_PHASEII);
+				}
+				else
+				{
+					//ILL_IFTRACE("\t%s:%s:%d\n",__func__,__FILE__,__LINE__);
+					EGLPNUM_TYPENAME_ILLprice_update_mpartial_price (lp, p, DUAL_PHASEII, ROW_PRICING);
+				}
+			}
+		}
+		//ILL_IFTRACE("\t%s:%s:%d\n",__func__,__FILE__,__LINE__);
+		EGLPNUM_TYPENAME_ILLfct_compute_dobj (lp);
+		EGLPNUM_TYPENAME_ILLfct_check_dfeasible (lp, fi, *dtol);
+		EGLPNUM_TYPENAME_ILLfct_check_pfeasible (lp, fi, *ptol);
+	}
+	else if (phase == DUAL_PHASEI)
+	{
+		EGLPNUM_TYPENAME_ILLfct_check_dfeasible (lp, fi, *idtol);
+		if (fi->dstatus != DUAL_FEASIBLE)
+		{
+			EGLPNUM_TYPENAME_ILLfct_compute_phaseI_xbz (lp);
+			EGLPNUM_TYPENAME_ILLfct_check_pIpfeasible (lp, fi, *iptol);
+			if (p != NULL)
+			{
+				if (p->d_strategy == COMPLETE_PRICING)
+					EGLPNUM_TYPENAME_ILLprice_compute_primal_inf (lp, p, NULL, 0, DUAL_PHASEI);
+				else
+					EGLPNUM_TYPENAME_ILLprice_update_mpartial_price (lp, p, DUAL_PHASEI, ROW_PRICING);
+			}
+		}
+	}
+CLEANUP:
+	EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLsimplex_solution (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPE * xz,
+	EGLPNUM_TYPE * piz,
+	EGLPNUM_TYPE * dz,
+	EGLPNUM_TYPE * objval)
+{
+	int i, j;
+	int col;
+
+	if (xz != NULL)
+	{
+		if (lp->basisstat.optimal == 0)
+		{
+			EG_RETURN (1);
+		}
+		for (i = 0; i < lp->nrows; i++)
+			EGLPNUM_TYPENAME_EGlpNumCopy (xz[lp->baz[i]], lp->xbz[i]);
+		for (j = 0; j < lp->nnbasic; j++)
+		{
+			col = lp->nbaz[j];
+			if (lp->vstat[col] == STAT_UPPER)
+				EGLPNUM_TYPENAME_EGlpNumCopy (xz[col], lp->uz[col]);
+			else if (lp->vstat[col] == STAT_LOWER)
+				EGLPNUM_TYPENAME_EGlpNumCopy (xz[col], lp->lz[col]);
+			else
+				EGLPNUM_TYPENAME_EGlpNumZero (xz[col]);
+		}
+	}
+	if (piz != NULL)
+	{
+		if (lp->basisstat.optimal == 0)
+		{
+			EG_RETURN (1);
+		}
+		for (i = 0; i < lp->nrows; i++)
+			EGLPNUM_TYPENAME_EGlpNumCopy (piz[i], lp->piz[i]);
+	}
+	if (dz != NULL)
+	{
+		if (lp->basisstat.optimal == 0)
+		{
+			EG_RETURN (1);
+		}
+		for (i = 0; i < lp->nrows; i++)
+			EGLPNUM_TYPENAME_EGlpNumZero (dz[lp->baz[i]]);
+		for (j = 0; j < lp->nnbasic; j++)
+			EGLPNUM_TYPENAME_EGlpNumCopy (dz[lp->nbaz[j]], lp->dz[j]);
+	}
+	if (objval != NULL)
+		EGLPNUM_TYPENAME_EGlpNumCopy (*objval, lp->objval);
+	return 0;
+}
+
+int EGLPNUM_TYPENAME_ILLsimplex_infcertificate (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPE * pi)
+{
+	int i, col, nz;
+	char *sense;
+	EGLPNUM_TYPE *x, *l, *u;
+	EGLPNUM_TYPENAME_lp_status_info *ls;
+
+	if (pi == NULL)
+		return 0;
+
+	ls = &(lp->basisstat);
+	if (ls->primal_infeasible == 0 && ls->dual_unbounded == 0)
+	{
+		EG_RETURN (1);
+	}
+
+	if (lp->final_phase == PRIMAL_PHASEI && lp->pIpiz != NULL)
+	{
+		for (i = 0; i < lp->nrows; i++)
+			EGLPNUM_TYPENAME_EGlpNumCopy (pi[i], lp->pIpiz[i]);
+	}
+	else if (lp->final_phase == DUAL_PHASEII && lp->infub_ix != -1)
+	{
+		col = lp->baz[lp->infub_ix];
+		x = &(lp->xbz[lp->infub_ix]);
+		l = &(lp->lz[col]);
+		u = &(lp->uz[col]);
+
+		for (i = 0; i < lp->nrows; i++)
+			EGLPNUM_TYPENAME_EGlpNumZero (pi[i]);
+
+		if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*l, EGLPNUM_TYPENAME_NINFTY) && EGLPNUM_TYPENAME_EGlpNumIsLess (*x, *l))
+		{
+			for (i = 0, nz = lp->zz.nzcnt; i < nz; i++)
+				EGLPNUM_TYPENAME_EGlpNumCopyNeg (pi[lp->zz.indx[i]], lp->zz.coef[i]);
+		}
+		else
+		{
+			for (i = 0, nz = lp->zz.nzcnt; i < nz; i++)
+				EGLPNUM_TYPENAME_EGlpNumCopy (pi[lp->zz.indx[i]], lp->zz.coef[i]);
+		}
+	}
+	else
+	{
+		QSlog("Invalid call to inf. certificate routine");
+		EG_RETURN (1);
+	}
+
+	sense = lp->O->sense;
+	for (i = 0; i < lp->nrows; i++)
+	{
+		if (sense[i] == 'G' && EGLPNUM_TYPENAME_EGlpNumIsLessZero (pi[i]))
+			EGLPNUM_TYPENAME_EGlpNumZero (pi[i]);
+		if (sense[i] == 'L' && EGLPNUM_TYPENAME_EGlpNumIsGreatZero (pi[i]))
+			EGLPNUM_TYPENAME_EGlpNumZero (pi[i]);
+	}
+	return 0;
+}
+
+#if SIMPLEX_DEBUG > 1
+static void test_cert (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPE * pi)
+{
+	int i, j;
+	int mcnt, mbeg;
+	EGLPNUM_TYPE fsum, sum;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (fsum);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (sum);
+	EGLPNUM_TYPENAME_EGlpNumZero (fsum);
+
+	for (i = 0; i < lp->nrows; i++)
+	{
+		if (lp->O->sense[i] == 'G' && EGLPNUM_TYPENAME_EGlpNumIsLessZero (pi[i]))
+			QSlog("compl");
+		if (lp->O->sense[i] == 'L' && EGLPNUM_TYPENAME_EGlpNumIsGreatZero (pi[i]))
+			QSlog("compll");
+	}
+
+	for (i = 0; i < lp->nrows; i++)
+		EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (fsum, pi[i], lp->bz[i]);
+
+	for (j = 0; j < lp->nnbasic; j++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumZero (sum);
+		mcnt = lp->matcnt[j];
+		mbeg = lp->matbeg[j];
+		for (i = 0; i < mcnt; i++)
+			EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, pi[lp->matind[mbeg + i]], lp->matval[mbeg + i]);
+
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_PFEAS_TOLER, sum) &&
+				(lp->vtype[j] == VLOWER || lp->vtype[j] == VFREE))
+			QSlog("compl2");
+		else
+		{
+			EGLPNUM_TYPENAME_EGlpNumSign (sum);
+			if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_PFEAS_TOLER, sum) &&
+					(lp->vtype[j] == VUPPER || lp->vtype[j] == VFREE))
+				QSlog("compl1");
+			EGLPNUM_TYPENAME_EGlpNumSign (sum);
+		}
+
+		if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (sum)
+				&& (lp->vtype[j] & (VFREE | VUPPER)) == 0)
+			EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (fsum, sum, lp->lz[j]);
+		else if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (sum)
+						 && (lp->vtype[j] & (VFREE | VLOWER)) == 0)
+			EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (fsum, sum, lp->uz[j]);
+	}
+	QSlog("fsum = %.8f", EGLPNUM_TYPENAME_EGlpNumToLf (fsum));
+	EGLPNUM_TYPENAME_EGlpNumClearVar (fsum);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (sum);
+}
+#endif
+
+static void save_paraminfo (
+	EGLPNUM_TYPENAME_price_info * pinf,
+	EGLPNUM_TYPENAME_iter_info * it)
+{
+	EGLPNUM_TYPENAME_param_info *pr = &(it->oldinfo);
+
+	pr->origalgo = it->algorithm;
+	pr->pphaseI = pinf->pI_price;
+	pr->pphaseII = pinf->pII_price;
+	pr->dphaseI = pinf->dI_price;
+	pr->dphaseII = pinf->dII_price;
+	pr->p_strategy = pinf->p_strategy;
+	pr->d_strategy = pinf->d_strategy;
+}
+
+static void restore_paraminfo (
+	EGLPNUM_TYPENAME_iter_info * it,
+	EGLPNUM_TYPENAME_price_info * pinf)
+{
+	EGLPNUM_TYPENAME_param_info *pr = &(it->oldinfo);
+
+	it->algorithm = pr->origalgo;
+	pinf->pI_price = pr->pphaseI;
+	pinf->pII_price = pr->pphaseII;
+	pinf->dI_price = pr->dphaseI;
+	pinf->dII_price = pr->dphaseII;
+	pinf->p_strategy = pr->p_strategy;
+	pinf->d_strategy = pr->d_strategy;
+}
+
+int EGLPNUM_TYPENAME_ILLsimplex (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int algorithm,
+	EGLPNUM_TYPENAME_ILLlp_basis * B,
+	EGLPNUM_TYPENAME_price_info * pinf,
+	int *status,
+	int sdisplay,
+	itcnt_t*itcnt)
+{
+	int phase = -1;
+	int singular = -1;
+	int rval = 0;
+	int new_price = -1;
+	EGLPNUM_TYPENAME_svector wz;
+	EGLPNUM_TYPENAME_svector updz;
+	EGLPNUM_TYPENAME_feas_info fi;
+	EGLPNUM_TYPENAME_iter_info it;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (fi.totinfeas);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (it.prevobj);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (it.objtol);
+
+	it.newphase = -1;
+	it.nextphase = -1;
+	it.nextstep = -1;
+	it.sdisplay = sdisplay;
+	it.n_pivot_fail = 0;
+	it.itercnt = 0;
+	it.n_restart = 0;
+	it.solstatus = ILL_LP_UNSOLVED;
+	it.curtime = 0;
+	it.rounds = 0;
+	EGLPNUM_TYPENAME_EGlpNumCopy (it.prevobj, EGLPNUM_TYPENAME_INFTY);
+	it.nosolve = 0;
+	it.noprog = 0;
+	EGLPNUM_TYPENAME_EGlpNumCopy (it.objtol, EGLPNUM_TYPENAME_OBJBND_TOLER);
+	it.chkobj = PARAM_MAX_NOPROG;
+	it.inner = 0;
+	it.algorithm = algorithm;
+	it.pricetype = -1;
+	it.resumeid = -1;
+	save_paraminfo (pinf, &it);
+
+#if SIMPLEX_DEBUG > 0
+	if (lp->O->nrows > 1000)
+		it.sdisplay = 1;
+#endif
+	if (status)
+		*status = QS_LP_UNSOLVED;
+
+	EGLPNUM_TYPENAME_free_internal_lpinfo (lp);
+	EGLPNUM_TYPENAME_init_internal_lpinfo (lp);
+	rval = EGLPNUM_TYPENAME_build_internal_lpinfo (lp);
+	CHECKRVALG (rval, CLEANUP);
+
+	EGLPNUM_TYPENAME_ILLsvector_init (&wz);
+	rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&wz, lp->nrows);
+	CHECKRVALG (rval, CLEANUP);
+	EGLPNUM_TYPENAME_ILLsvector_init (&updz);
+	rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&updz, lp->nrows);
+	CHECKRVALG (rval, CLEANUP);
+
+	if (it.sdisplay)
+	{
+		char buffer[256];
+		int nonzero = 0;
+		register int i = lp->ncols;
+
+		while (i--)
+			nonzero += lp->matcnt[i];
+		sprintf (buffer, "starting EGLPNUM_TYPENAME_ILLsimplex on %s...", lp->O->probname);
+		/* depending on LP's reporter 
+		 * string is printed to stdout 
+		 * or handed to GUI */
+		rval = rval || ILLstring_report (buffer, &lp->O->reporter);
+		QSlog("Problem has %d rows and %d cols and %d nonzeros", lp->nrows,
+								lp->ncols, nonzero);
+	}
+	EGLPNUM_TYPENAME_ILLfct_set_variable_type (lp);
+
+	if (B != 0)
+	{
+		rval = EGLPNUM_TYPENAME_ILLbasis_load (lp, B);
+		CHECKRVALG (rval, CLEANUP);
+		if (it.algorithm == DUAL_SIMPLEX)
+		{
+			if (B->rownorms)
+			{
+				rval = EGLPNUM_TYPENAME_ILLprice_load_rownorms (lp, B->rownorms, pinf);
+				CHECKRVALG (rval, CLEANUP);
+			}
+			else
+				EGLPNUM_TYPENAME_EGlpNumFreeArray (pinf->dsinfo.norms);
+		}
+		else if (it.algorithm == PRIMAL_SIMPLEX)
+		{
+			if (B->colnorms)
+			{
+				rval = EGLPNUM_TYPENAME_ILLprice_load_colnorms (lp, B->colnorms, pinf);
+				CHECKRVALG (rval, CLEANUP);
+			}
+			else
+				EGLPNUM_TYPENAME_EGlpNumFreeArray (pinf->psinfo.norms);
+		}
+		else if (it.algorithm != PRIMAL_OR_DUAL)
+		{
+			QSlog("Unknown algorithm %d in EGLPNUM_TYPENAME_ILLsimplex", it.algorithm);
+			rval = 1;
+			ILL_CLEANUP;
+		}
+	}
+	else if (lp->basisid == -1)
+	{
+		if (lp->nrows < 200 && lp->ncols < 400)
+			rval = EGLPNUM_TYPENAME_ILLbasis_get_initial (lp, it.algorithm);
+		else
+			rval = EGLPNUM_TYPENAME_ILLbasis_get_cinitial (lp, it.algorithm);
+		CHECKRVALG (rval, CLEANUP);
+		EGLPNUM_TYPENAME_ILLprice_free_pricing_info (pinf);
+	}
+
+	if (lp->fbasisid != lp->basisid)
+	{
+		rval = EGLPNUM_TYPENAME_ILLbasis_factor (lp, &singular);
+		CHECKRVALG (rval, CLEANUP);
+		if (singular)
+		{
+			MESSAGE (__QS_SB_VERB, "Singular basis found!");
+			EGLPNUM_TYPENAME_ILLprice_free_pricing_info (pinf);
+		}
+	}
+
+START:
+#if 0
+	if (it.resumeid == SIMPLEX_RESUME_UNSHIFT)
+		QSlog("Resuming Unshift");
+	else if (it.resumeid == SIMPLEX_RESUME_SING)
+		QSlog("Resuming Singular");
+	else if (it.resumeid == SIMPLEX_RESUME_NUMER)
+		QSlog("Resuming Numer");
+	else if (it.resumeid != -1)
+		QSlog("Resuming for other reason... %d", it.resumeid);
+#endif
+	it.solstatus = ILL_LP_UNSOLVED;
+	init_lp_status_info (&(lp->basisstat));
+
+	EGLPNUM_TYPENAME_ILLfct_compute_piz (lp);
+	EGLPNUM_TYPENAME_ILLfct_compute_dz (lp);
+	if (it.algorithm == DUAL_SIMPLEX)
+	{
+		if (B != NULL || it.resumeid == SIMPLEX_RESUME_UNSHIFT)
+			EGLPNUM_TYPENAME_ILLfct_dual_adjust (lp, lp->tol->dfeas_tol);
+		else
+			EGLPNUM_TYPENAME_ILLfct_dual_adjust (lp, EGLPNUM_TYPENAME_zeroLpNum);
+	}
+	EGLPNUM_TYPENAME_ILLfct_compute_xbz (lp);
+
+	EGLPNUM_TYPENAME_ILLfct_check_pfeasible (lp, &fi, lp->tol->pfeas_tol);
+	EGLPNUM_TYPENAME_ILLfct_check_dfeasible (lp, &fi, lp->tol->dfeas_tol);
+	EGLPNUM_TYPENAME_ILLfct_set_status_values (lp, fi.pstatus, fi.dstatus, PHASEII, PHASEII);
+
+	if (fi.dstatus == DUAL_FEASIBLE && EGLPNUM_TYPENAME_EGlpNumIsNeqq (lp->objbound, EGLPNUM_TYPENAME_INFTY))
+	{
+		EGLPNUM_TYPENAME_ILLfct_compute_dobj (lp);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (lp->objbound, lp->dobjval))
+		{
+			it.solstatus = ILL_BND_REACHED;
+			QSlog("solstatus = ILL_BND_REACHED = 5 %lf %lf",
+									EGLPNUM_TYPENAME_EGlpNumToLf (lp->objbound),
+									EGLPNUM_TYPENAME_EGlpNumToLf (lp->dobjval));
+			goto TERMINATE;
+		}
+	}
+	if (fi.pstatus == PRIMAL_FEASIBLE && fi.dstatus == DUAL_FEASIBLE)
+	{
+		it.solstatus = ILL_LP_SOLVED;
+		EGLPNUM_TYPENAME_ILLfct_compute_pobj (lp);
+		goto TERMINATE;
+	}
+
+	if (it.algorithm == PRIMAL_OR_DUAL)
+	{
+		if (fi.pstatus == PRIMAL_FEASIBLE)
+			it.algorithm = PRIMAL_SIMPLEX;
+		else if (fi.dstatus == DUAL_FEASIBLE)
+			it.algorithm = DUAL_SIMPLEX;
+		else if (EGLPNUM_TYPENAME_EGlpNumToLf (lp->pinfeas) < 10 * EGLPNUM_TYPENAME_EGlpNumToLf (lp->dinfeas))
+			it.algorithm = PRIMAL_SIMPLEX;
+		else
+			it.algorithm = DUAL_SIMPLEX;
+	}
+
+	if (it.algorithm == PRIMAL_SIMPLEX)
+	{
+		if (fi.pstatus == PRIMAL_FEASIBLE)
+			phase = PRIMAL_PHASEII;
+		else
+			phase = PRIMAL_PHASEI;
+	}
+	else if (it.algorithm == DUAL_SIMPLEX)
+	{
+		if (fi.dstatus == DUAL_FEASIBLE)
+			phase = DUAL_PHASEII;
+		else
+			phase = DUAL_PHASEI;
+	}
+
+	rval = EGLPNUM_TYPENAME_ILLprice_build_pricing_info (lp, pinf, phase);
+	CHECKRVALG (rval, CLEANUP);
+
+	it.newphase = SIMPLEX_PHASE_NEW;
+	it.nextstep = SIMPLEX_CONTINUE;
+
+	while (it.nextstep == SIMPLEX_CONTINUE)
+	{
+		//ILL_IFTRACE("\t%s:%s:%d\n",__func__,__FILE__,__LINE__);
+
+		if (phase == PRIMAL_PHASEI)
+		{
+			rval = primal_phaseI_step (lp, pinf, &updz, &wz, &it);
+			CHECKRVALG (rval, CLEANUP);
+		}
+
+		else if (phase == PRIMAL_PHASEII)
+		{
+			rval = primal_phaseII_step (lp, pinf, &updz, &wz, &it);
+			CHECKRVALG (rval, CLEANUP);
+		}
+
+		else if (phase == DUAL_PHASEI)
+		{
+			rval = dual_phaseI_step (lp, pinf, &updz, &wz, &it);
+			CHECKRVALG (rval, CLEANUP);
+		}
+
+		else if (phase == DUAL_PHASEII)
+		{
+			rval = dual_phaseII_step (lp, pinf, &updz, &wz, &it);
+			CHECKRVALG (rval, CLEANUP);
+		}
+		if (it.nextstep == SIMPLEX_RESUME)
+		{
+			//ILL_IFTRACE("\t%s:%s:%d\n",__func__,__FILE__,__LINE__);
+			EGLPNUM_TYPENAME_ILLprice_free_pricing_info (pinf);
+			if (it.resumeid == SIMPLEX_RESUME_UNSHIFT)
+			{
+				if (it.pricetype == QS_PRICE_PDEVEX)
+				{
+					pinf->pI_price = QS_PRICE_PDEVEX;
+					pinf->pII_price = QS_PRICE_PDEVEX;
+				}
+				else if (it.pricetype == QS_PRICE_DDEVEX)
+				{
+					pinf->dI_price = QS_PRICE_DDEVEX;
+					pinf->dII_price = QS_PRICE_DDEVEX;
+				}
+			}
+			else if (it.resumeid == SIMPLEX_RESUME_NUMER)
+			{
+				EGLPNUM_TYPENAME_ILLfct_unroll_bound_change (lp);
+				EGLPNUM_TYPENAME_ILLfct_unroll_coef_change (lp);
+				/* we are disabling re-do under this circunstances ! */
+				rval = EGLPNUM_TYPENAME_ILLbasis_get_initial (lp, it.algorithm);
+				CHECKRVALG (rval, CLEANUP);
+				rval = EGLPNUM_TYPENAME_ILLbasis_factor (lp, &singular);
+				if (singular)
+					MESSAGE (__QS_SB_VERB, "Singular basis found!");
+				CHECKRVALG (rval, CLEANUP);
+			}
+			it.pricetype = -1;
+			if (it.n_restart > SIMPLEX_MAX_RESTART)
+			{
+				it.solstatus = ILL_MAX_ITER;
+				goto LIMIT_TERMINATE;
+			}
+			goto START;
+		}
+		else if (it.nextstep == SIMPLEX_CONTINUE)
+		{
+			//ILL_IFTRACE("\t%s:%s:%d\n",__func__,__FILE__,__LINE__);
+			it.itercnt++;
+
+			if (it.nextphase != phase)
+			{
+				//ILL_IFTRACE("\t%s:%s:%d\n",__func__,__FILE__,__LINE__);
+				it.newphase = SIMPLEX_PHASE_NEW;
+				phase = it.nextphase;
+				new_price = EGLPNUM_TYPENAME_ILLprice_get_price (pinf, phase);
+
+				if (pinf->cur_price != new_price)
+				{
+					//ILL_IFTRACE("\t%s:%s:%d\n",__func__,__FILE__,__LINE__);
+					EGLPNUM_TYPENAME_ILLprice_free_pricing_info (pinf);
+					rval = EGLPNUM_TYPENAME_ILLprice_build_pricing_info (lp, pinf, phase);
+					CHECKRVALG (rval, CLEANUP);
+				}
+			}
+		}
+	}
+
+#if SIMPLEX_DEBUG > 0
+	EGLPNUM_TYPENAME_ILLfct_print_counts (lp);
+#endif
+LIMIT_TERMINATE:
+	rval = terminate_simplex (lp, phase, &it);
+	CHECKRVALG (rval, CLEANUP);
+
+TERMINATE:
+	restore_paraminfo (&it, pinf);
+
+	if (it.sdisplay)
+	{
+		QSlog("completed EGLPNUM_TYPENAME_ILLsimplex");
+		QSlog("%s: ", lp->O->probname);
+	}
+
+	if (status)
+	{
+		if (it.solstatus == ILL_MAX_ITER)
+		{
+			*status = QS_LP_ITER_LIMIT;
+		}
+		else if (it.solstatus == ILL_MAX_TIME)
+		{
+			*status = QS_LP_TIME_LIMIT;
+		}
+		else if (it.solstatus == ILL_LP_ABORTED)
+		{
+			*status = QS_LP_ABORTED;
+		}
+		else if (it.solstatus == ILL_PPHASEI_ERROR ||
+						 it.solstatus == ILL_PPHASEII_ERROR ||
+						 it.solstatus == ILL_DPHASEI_ERROR ||
+						 it.solstatus == ILL_DPHASEII_ERROR)
+		{
+			*status = QS_LP_NUMERR;
+		}
+		else if(it.solstatus == ILL_LP_UNSOLVED)
+		{
+			*status = QS_LP_UNSOLVED;
+		}
+		else if (it.solstatus == ILL_BND_REACHED)
+		{
+			*status = QS_LP_OBJ_LIMIT;
+		}
+		else if (it.solstatus == ILL_LP_SOLVED)
+		{
+			if (lp->basisstat.optimal)
+			{
+				*status = QS_LP_OPTIMAL;
+			}
+			else if (lp->basisstat.primal_infeasible || lp->basisstat.dual_unbounded)
+			{
+				*status = QS_LP_INFEASIBLE;
+				if (it.sdisplay)
+				{
+					if (lp->basisstat.primal_infeasible)
+						QSlog("Primal Infeasible");
+					else
+						QSlog("Dual Unbounded");
+				}
+			}
+			else if (lp->basisstat.primal_unbounded)
+			{
+				*status = QS_LP_UNBOUNDED;
+			}
+		}
+		else
+		{
+			QSlog("unknown solution status in EGLPNUM_TYPENAME_ILLsimplex %d",
+									it.solstatus);
+			rval = 1;
+			CHECKRVALG (rval, CLEANUP);
+		}
+	}
+
+#if SIMPLEX_DEBUG > 1
+	{
+		int rva = 0;
+		EGLPNUM_TYPE *pi = NULL;
+
+		pi = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+		rva = EGLPNUM_TYPENAME_ILLsimplex_infcertificate (lp, pi);
+		QSlog("rva = %d", rva);
+		if (!rva)
+		{
+			test_cert (lp, pi);
+		}
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (pi);
+	}
+#endif
+	 /* update counter */
+	 itcnt->pI_iter += lp->cnts->pI_iter;
+	 itcnt->pII_iter += lp->cnts->pII_iter;
+	 itcnt->dI_iter += lp->cnts->dI_iter;
+	 itcnt->dII_iter += lp->cnts->dII_iter;
+	 itcnt->tot_iter = itcnt->pI_iter + itcnt->pII_iter + itcnt->dI_iter +
+	 										itcnt->dII_iter;
+   /* end update */
+	if (it.sdisplay)
+	{
+		int bstat = 0;
+
+		QSlog("time = %.3f, pI = %d, pII = %d, dI = %d, dII = %d,",
+								ILLutil_zeit () - lp->starttime, lp->cnts->pI_iter,
+								lp->cnts->pII_iter, lp->cnts->dI_iter, lp->cnts->dII_iter);
+		get_current_stat (&(lp->basisstat), it.algorithm, &bstat);
+		switch (bstat)
+		{
+		case OPTIMAL:
+			QSlog("opt = %f", EGLPNUM_TYPENAME_EGlpNumToLf (lp->objval));
+			break;
+		case PRIMAL_INFEASIBLE:
+			QSlog("no primal soln");
+			break;
+		case PRIMAL_UNBOUNDED:
+			QSlog("primal unbounded");
+			break;
+		case PRIMAL_FEASIBLE:
+			QSlog("primal obj = %f", EGLPNUM_TYPENAME_EGlpNumToLf (lp->pobjval));
+			break;
+		case DUAL_INFEASIBLE:
+			QSlog("no dual soln");
+			break;
+		case DUAL_UNBOUNDED:
+			QSlog("dual unbounded");
+			break;
+		case DUAL_FEASIBLE:
+			QSlog("dual obj = %f", EGLPNUM_TYPENAME_EGlpNumToLf (lp->dobjval));
+			break;
+		}
+
+		if (it.sdisplay > 1)
+		{
+			if (it.algorithm == PRIMAL_SIMPLEX && pinf->pI_price == QS_PRICE_PDEVEX)
+				QSlog("Devex norms initialised %d times", pinf->pdinfo.ninit);
+		}
+	}
+
+CLEANUP:
+	EGLPNUM_TYPENAME_ILLsvector_free (&wz);
+	EGLPNUM_TYPENAME_ILLsvector_free (&updz);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (it.prevobj);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (it.objtol);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (fi.totinfeas);
+	if (rval == QS_LP_CHANGE_PREC)
+	{
+		MESSAGE (__QS_SB_VERB, "Changing precision");
+		return rval;
+	}
+	else
+	{
+		MESSAGE (rval ? 0 : 1000, "Error code %d", rval);
+		EG_RETURN (rval);
+	}
+}
+
+static int terminate_simplex (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	int phase,
+	EGLPNUM_TYPENAME_iter_info * it)
+{
+	int rval = 0;
+	int sphase;
+	EGLPNUM_TYPENAME_feas_info fi;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (fi.totinfeas);
+
+	if (it->solstatus != ILL_MAX_TIME && it->solstatus != ILL_MAX_ITER)
+		ILL_CLEANUP;
+
+	if (it->algorithm == PRIMAL_SIMPLEX)
+	{
+		if (lp->nbchange != 0)
+		{
+			if (it->sdisplay > 1)
+			{
+				QSlog("unrolling %d bound shifts", lp->nbchange);
+			}
+			EGLPNUM_TYPENAME_ILLfct_unroll_bound_change (lp);
+		}
+		rval = EGLPNUM_TYPENAME_ILLsimplex_retest_psolution (lp, NULL, phase, &fi);
+		CHECKRVALG (rval, CLEANUP);
+
+		sphase = (phase == PRIMAL_PHASEI) ? PHASEI : PHASEII;
+		EGLPNUM_TYPENAME_ILLfct_set_status_values (lp, fi.pstatus, fi.dstatus, PHASEII, sphase);
+	}
+	else if (it->algorithm == DUAL_SIMPLEX)
+	{
+		if (lp->ncchange != 0)
+		{
+			if (it->sdisplay > 1)
+			{
+				QSlog("unrolling %d coef shifts", lp->ncchange);
+			}
+			EGLPNUM_TYPENAME_ILLfct_unroll_coef_change (lp);
+		}
+		rval = EGLPNUM_TYPENAME_ILLsimplex_retest_dsolution (lp, NULL, phase, &fi);
+		CHECKRVALG (rval, CLEANUP);
+
+		sphase = (phase == DUAL_PHASEI) ? PHASEI : PHASEII;
+		EGLPNUM_TYPENAME_ILLfct_set_status_values (lp, fi.pstatus, fi.dstatus, sphase, PHASEII);
+	}
+
+CLEANUP:
+	EGLPNUM_TYPENAME_EGlpNumClearVar (fi.totinfeas);
+	EG_RETURN (rval);
+}
+
+static int test_progress (
+	EGLPNUM_TYPE objval,
+	EGLPNUM_TYPE prevobj)
+{
+	EGLPNUM_TYPE denom;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (denom);
+	EGLPNUM_TYPENAME_EGlpNumCopyDiff (denom, objval, prevobj);
+	if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (objval, EGLPNUM_TYPENAME_PROGRESS_ZERO))
+		EGLPNUM_TYPENAME_EGlpNumDivTo (denom, objval);
+	if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (denom, EGLPNUM_TYPENAME_PROGRESS_THRESH))
+	{
+		EGLPNUM_TYPENAME_EGlpNumClearVar (denom);
+		return 0;
+	}
+	else
+	{
+		EGLPNUM_TYPENAME_EGlpNumClearVar (denom);
+		return 1;
+	}
+}
+
+static void monitor_iter (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * p,
+	EGLPNUM_TYPENAME_iter_info * it,
+	int phase)
+{
+	EGLPNUM_TYPE print_val;
+	double tottime = ILLutil_zeit () - lp->starttime;
+	int curtime = ILLutil_our_floor (tottime);	/* MONIKA */
+	char print_str[20];
+	EGLPNUM_TYPENAME_feas_info fi;
+	int aborted = 0;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (print_val);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (fi.totinfeas);
+	EGLPNUM_TYPENAME_EGlpNumZero (fi.totinfeas);
+	EGLPNUM_TYPENAME_EGlpNumZero (print_val);
+
+	/* one of the following two time display mechanisms */
+	switch (phase)
+	{
+	case PRIMAL_PHASEI:
+		EGLPNUM_TYPENAME_EGlpNumCopy (print_val, lp->pinfeas);
+		EGLPNUM_TYPENAME_EGlpNumAddTo (fi.totinfeas, lp->pinfeas);
+		strcpy (print_str, "primal infeas");
+		if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (lp->pinfeas) &&
+				(EGLPNUM_TYPENAME_EGlpNumIsNeqZero (lp->pinfeas, EGLPNUM_TYPENAME_oneLpNum)))
+		{
+			/*QSlog("Negative Infeasibility! Imposible %lg %la, iter %d",
+			 * EGLPNUM_TYPENAME_EGlpNumToLf (print_val), EGLPNUM_TYPENAME_EGlpNumToLf (print_val), it->itercnt);
+			 */
+			//exit(1);
+		}
+		break;
+	case PRIMAL_PHASEII:
+		EGLPNUM_TYPENAME_EGlpNumCopy (print_val, lp->pobjval);
+		strcpy (print_str, "primal objval");
+		break;
+	case DUAL_PHASEI:
+		EGLPNUM_TYPENAME_EGlpNumCopy (print_val, lp->dinfeas);
+		EGLPNUM_TYPENAME_EGlpNumAddTo (fi.totinfeas, lp->dinfeas);
+		strcpy (print_str, "dual infeas");
+		break;
+	case DUAL_PHASEII:
+		EGLPNUM_TYPENAME_EGlpNumCopy (print_val, lp->dobjval);
+		strcpy (print_str, "dual objval");
+		break;
+	}
+
+	aborted = report_value (lp, it, print_str, print_val);
+	/*if (it->sdisplay && it->itercnt % lp->iterskip == 0) {
+	 * // QSlog("(%d): %s = %f", it->itercnt, print_str, print_val);
+	 * } */
+	if (curtime != it->curtime)
+	{
+		it->curtime = curtime;
+		/*
+		 * if (it->sdisplay){
+		 * QSlog("time = %d.0, ", curtime);
+		 * QSlog("(%d): %s = %f", it->itercnt, print_str, print_val);
+		 * }
+		 */
+	}
+
+	EGLPNUM_TYPENAME_EGlpNumAddUiTo (fi.totinfeas, 1000);
+	if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (fi.totinfeas))
+	{
+		it->nextstep = SIMPLEX_TERMINATE;
+		it->solstatus = ILL_MAX_ITER;
+		MESSAGE (it->sdisplay ? 0 : __QS_SB_VERB,
+						 "early finish by excess infeasibility");
+		ILL_CLEANUP;
+	}
+
+	if (phase == DUAL_PHASEII && EGLPNUM_TYPENAME_EGlpNumIsNeqq (lp->objbound, EGLPNUM_TYPENAME_INFTY))
+	{
+		/*if (lp->dobjval > lp->objbound + it->objtol) */
+		EGLPNUM_TYPENAME_EGlpNumCopyDiff (print_val, lp->dobjval, lp->objbound);
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (it->objtol, print_val))
+		{
+			EGLPNUM_TYPENAME_ILLfct_unroll_coef_change (lp);
+			EGLPNUM_TYPENAME_ILLfct_check_dfeasible (lp, &fi, lp->tol->dfeas_tol);
+			EGLPNUM_TYPENAME_ILLfct_set_status_values (lp, -1, fi.dstatus, -1, PHASEII);
+
+			if (fi.dstatus == DUAL_FEASIBLE)
+			{
+				EGLPNUM_TYPENAME_ILLfct_compute_dobj (lp);
+				if (EGLPNUM_TYPENAME_EGlpNumIsLess (lp->objbound, lp->dobjval))
+				{
+					it->solstatus = ILL_BND_REACHED;
+					it->nextstep = SIMPLEX_TERMINATE;
+					/*if (it->sdisplay) */
+					{
+						QSlog("bound reached %lf %lf", EGLPNUM_TYPENAME_EGlpNumToLf (lp->objbound),
+										EGLPNUM_TYPENAME_EGlpNumToLf (lp->dobjval));
+					}
+				}
+				else
+					EGLPNUM_TYPENAME_EGlpNumMultUiTo (it->objtol, 10);
+			}
+			else
+			{
+				it->nextphase = DUAL_PHASEI;
+				it->newphase = SIMPLEX_PHASE_NEW;
+				EGLPNUM_TYPENAME_EGlpNumMultUiTo (it->objtol, 5);
+			}
+		}
+	}
+	if (it->itercnt >= lp->maxiter)
+	{
+		it->solstatus = ILL_MAX_ITER;
+		it->nextstep = SIMPLEX_TERMINATE;
+		if (it->sdisplay)
+		{
+			QSlog("iter limit reached");
+		}
+		ILL_CLEANUP;
+	}
+	else if (tottime >= lp->maxtime)
+	{
+		it->solstatus = ILL_MAX_TIME;
+		it->nextstep = SIMPLEX_TERMINATE;
+		if (it->sdisplay)
+		{
+			QSlog("time limit reached");
+		}
+		ILL_CLEANUP;
+	}
+	else if (aborted)
+	{
+		it->solstatus = ILL_LP_ABORTED;
+		it->nextstep = SIMPLEX_TERMINATE;
+		if (it->sdisplay)
+		{
+			QSlog("aborted");
+		}
+		ILL_CLEANUP;
+	}
+	/* why is this commented out? */
+	if(0){
+		if (it->rounds && it->inner){
+			it->inner --;
+			if (it->inner == 0){
+				QSlog("restoring ..");
+				restore_paraminfo (it, p);
+				it->newphase   = SIMPLEX_PHASE_NEW;
+				it->nextstep   = SIMPLEX_RESUME;
+				/*it->resumeid   = SIMPLEX_RESUME_OUTER;*/
+				ILL_CLEANUP;
+			}
+		}
+	}
+	if (phase == DUAL_PHASEII)
+	{
+		if (it->noprog > it->chkobj)
+		{
+			EGLPNUM_TYPENAME_ILLfct_perturb_coefs (lp);
+			it->noprog = 0;
+			EGLPNUM_TYPENAME_EGlpNumCopy (it->prevobj, lp->dobjval);
+		}
+	}
+	else if (phase == PRIMAL_PHASEII)
+	{
+		if (it->noprog > it->chkobj)
+		{
+			EGLPNUM_TYPENAME_ILLfct_perturb_bounds (lp);
+			it->noprog = 0;
+			EGLPNUM_TYPENAME_EGlpNumCopy (it->prevobj, lp->pobjval);
+		}
+	}
+	else if (phase == PRIMAL_PHASEI)
+	{
+		if (it->noprog > it->chkobj)
+		{
+			it->algorithm = DUAL_SIMPLEX;
+			it->nextstep = SIMPLEX_RESUME;
+			it->resumeid = SIMPLEX_RESUME_NUMER;
+			/* this is to force to exit in the case of bad basis */
+			EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->pfeas_tol, SIMPLEX_FACTOR);
+			EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->dfeas_tol, SIMPLEX_FACTOR);
+			it->n_restart++;
+			//QSlog("Resume Numerical %s:%s:%d",__func__,__FILE__,__LINE__);
+		}
+	}
+	else if (phase == DUAL_PHASEI)
+	{
+		if (it->noprog > it->chkobj)
+		{
+			it->algorithm = PRIMAL_SIMPLEX;
+			it->nextstep = SIMPLEX_RESUME;
+			it->resumeid = SIMPLEX_RESUME_NUMER;
+			/* this is to force to exit in the case of bad basis */
+			EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->pfeas_tol, SIMPLEX_FACTOR);
+			EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->dfeas_tol, SIMPLEX_FACTOR);
+			it->n_restart++;
+			//QSlog("Resume Numerical %s:%s:%d",__func__,__FILE__,__LINE__);
+		}
+	}
+CLEANUP:
+	EGLPNUM_TYPENAME_EGlpNumClearVar (fi.totinfeas);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (print_val);
+	return;
+}
+
+static int primal_phaseI_step (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * pinf,
+	EGLPNUM_TYPENAME_svector * updz,
+	EGLPNUM_TYPENAME_svector * wz,
+	EGLPNUM_TYPENAME_iter_info * it)
+{
+	int rval = 0;
+	int singular = 0;
+	int refactor = 0;
+	int cphase = PRIMAL_PHASEI;
+	EGLPNUM_TYPE alpha;
+	EGLPNUM_TYPENAME_feas_info fi;
+	EGLPNUM_TYPENAME_ratio_res rs;
+	EGLPNUM_TYPENAME_price_res pr;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (alpha);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (fi.totinfeas);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (pr.dinfeas);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (pr.pinfeas);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (rs.tz);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (rs.lbound);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (rs.ecoeff);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (rs.pivotval);
+	EGLPNUM_TYPENAME_EGlpNumZero (alpha);
+
+	EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_PPHASE1ITER, 0, EGLPNUM_TYPENAME_zeroLpNum);
+	it->nextstep = SIMPLEX_CONTINUE;
+	it->nextphase = PRIMAL_PHASEI;
+	lp->final_phase = PRIMAL_PHASEI;
+	it->nosolve++;
+
+	if (it->newphase != 0)
+	{
+		EGLPNUM_TYPENAME_ILLfct_check_pfeasible (lp, &fi, lp->tol->ip_tol);
+		if (it->newphase == SIMPLEX_PHASE_NEW)
+		{
+			it->noprog = 0;
+			if (it->sdisplay)
+			{
+				QSlog("starting primal phase I, nosolve %d", it->nosolve);
+			}
+		}
+		it->newphase = 0;
+		it->nosolve = 0;
+		EGLPNUM_TYPENAME_EGlpNumCopy (it->prevobj, lp->pinfeas);
+		lp->pIpiz = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+		lp->pIdz = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nnbasic);
+
+		EGLPNUM_TYPENAME_ILLfct_compute_phaseI_piz (lp);
+		if (pinf->p_strategy == COMPLETE_PRICING)
+		{
+			EGLPNUM_TYPENAME_ILLfct_compute_phaseI_dz (lp);
+#if USEHEAP > 0
+			EGLPNUM_TYPENAME_ILLprice_free_heap (pinf);
+#endif
+			EGLPNUM_TYPENAME_ILLprice_compute_dual_inf (lp, pinf, NULL, 0, PRIMAL_PHASEI);
+#if USEHEAP > 0
+			rval = EGLPNUM_TYPENAME_ILLprice_test_for_heap (lp, pinf, lp->nnbasic, pinf->d_scaleinf,
+																		 PRIMAL_SIMPLEX, 0);
+			CHECKRVALG (rval, CLEANUP);
+#endif
+		}
+		else if (pinf->p_strategy == MULTI_PART_PRICING)
+			EGLPNUM_TYPENAME_ILLprice_init_mpartial_price (lp, pinf, cphase, COL_PRICING);
+	}
+
+	monitor_iter (lp, pinf, it, cphase);
+	if (it->nextstep == SIMPLEX_TERMINATE || it->nextstep == SIMPLEX_RESUME ||
+			it->newphase != 0)
+		ILL_CLEANUP;
+
+	EGLPNUM_TYPENAME_ILLprice_primal (lp, pinf, &pr, cphase);
+	ILL_IFTRACE2 ("%s:after_price\n", __func__);
+
+	if (pr.price_stat == PRICE_OPTIMAL)
+	{
+		if (it->sdisplay > 1)
+		{
+			QSlog("primal phase I seemingly done");
+			QSlog("retesting soln");
+		}
+		rval = EGLPNUM_TYPENAME_ILLsimplex_retest_psolution (lp, pinf, cphase, &fi);
+
+		CHECKRVALG (rval, CLEANUP);
+		EGLPNUM_TYPENAME_ILLfct_set_status_values (lp, fi.pstatus, fi.dstatus, PHASEII, PHASEI);
+
+		if (fi.pstatus == PRIMAL_FEASIBLE)
+		{
+			it->nextphase = PRIMAL_PHASEII;
+		}
+		else if (fi.dstatus == DUAL_FEASIBLE)
+		{
+			it->solstatus = ILL_LP_SOLVED;
+			it->nextstep = SIMPLEX_TERMINATE;
+		}
+		ILL_CLEANUP;
+	}
+
+	EGLPNUM_TYPENAME_ILLfct_compute_yz (lp, &(lp->yjz), updz, lp->nbaz[pr.eindex]);
+	EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_YNZ, lp->yjz.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+	EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_UPNZ, updz->nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+
+	EGLPNUM_TYPENAME_ILLratio_pI_test (lp, pr.eindex, pr.dir, &rs);
+	//ILL_IFTRACE(":%d",rs.lindex);
+
+	if (rs.ratio_stat == RATIO_FAILED)
+	{
+		/*
+		 * rval = E_SIMPLEX_ERROR;
+		 * it->solstatus = ILL_PPHASEI_ERROR;
+		 */
+		//ILL_IFTRACE("ratio_failed\n");
+		it->algorithm = DUAL_SIMPLEX;
+		it->nextstep = SIMPLEX_RESUME;
+		it->resumeid = SIMPLEX_RESUME_NUMER;
+		/* this is to force to exit in the case of bad basis */
+		it->n_restart++;
+		EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->pfeas_tol, SIMPLEX_FACTOR);
+		EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->dfeas_tol, SIMPLEX_FACTOR);
+		//QSlog("Resume Numerical %s:%s:%d",__func__,__FILE__,__LINE__);
+		ILL_CLEANUP;
+	}
+	else if (rs.ratio_stat == RATIO_NEGATIVE)
+	{
+		EGLPNUM_TYPE itol;
+
+		EGLPNUM_TYPENAME_EGlpNumInitVar (itol);
+		//ILL_IFTRACE("ratio_negative\n");
+		EGLPNUM_TYPENAME_EGlpNumCopy (itol, lp->tol->ip_tol);
+		EGLPNUM_TYPENAME_EGlpNumZero (lp->tol->ip_tol);
+		EGLPNUM_TYPENAME_EGlpNumAddTo (lp->pinfeas, lp->upd.c_obj);
+		if (!test_progress (lp->pinfeas, it->prevobj))
+			it->noprog++;
+		else
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (it->prevobj, lp->pinfeas);
+			it->noprog = 0;
+		}
+		EGLPNUM_TYPENAME_ILLfct_update_pfeas (lp, rs.lindex, &(lp->srhs));
+		EGLPNUM_TYPENAME_EGlpNumCopy (lp->tol->ip_tol, itol);
+		EGLPNUM_TYPENAME_ILLfct_compute_ppIzz (lp, &(lp->srhs), &(lp->ssoln));
+		EGLPNUM_TYPENAME_ILLfct_update_ppI_prices (lp, pinf, &(lp->srhs), &(lp->ssoln), pr.eindex,
+															rs.lindex, EGLPNUM_TYPENAME_zeroLpNum);
+		EGLPNUM_TYPENAME_EGlpNumClearVar (itol);
+	}
+	else if (rs.ratio_stat == RATIO_NOBCHANGE)
+	{
+		//ILL_IFTRACE("ratio_nobchange\n");
+		EGLPNUM_TYPENAME_EGlpNumAddTo (lp->pinfeas, lp->upd.c_obj);
+		if (!test_progress (lp->pinfeas, it->prevobj))
+			it->noprog++;
+		else
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (it->prevobj, lp->pinfeas);
+			it->noprog = 0;
+		}
+
+		//ILL_IFTRACE("%s:a\n",__func__);
+		EGLPNUM_TYPENAME_ILLfct_update_xz (lp, rs.tz, pr.eindex, rs.lindex);
+		EGLPNUM_TYPENAME_ILLfct_update_pfeas (lp, rs.lindex, &(lp->srhs));
+		EGLPNUM_TYPENAME_ILLfct_compute_ppIzz (lp, &(lp->srhs), &(lp->ssoln));
+		EGLPNUM_TYPENAME_ILLfct_update_basis_info (lp, pr.eindex, rs.lindex, rs.lvstat);
+#if DENSE_PI > 0
+		EGLPNUM_TYPENAME_fct_test_workvector (lp);
+		EGLPNUM_TYPENAME_fct_test_pfeasible (lp);
+#endif
+		EGLPNUM_TYPENAME_ILLfct_update_ppI_prices (lp, pinf, &(lp->srhs), &(lp->ssoln), pr.eindex,
+															rs.lindex, EGLPNUM_TYPENAME_zeroLpNum);
+	}
+	else if (rs.ratio_stat == RATIO_BCHANGE)
+	{
+		//ILL_IFTRACE("ratio_bchange\n");
+		EGLPNUM_TYPENAME_EGlpNumCopyFrac (alpha, lp->pIdz[pr.eindex], rs.pivotval);
+		EGLPNUM_TYPENAME_EGlpNumAddTo (lp->pinfeas, lp->upd.c_obj);
+
+		if (!test_progress (lp->pinfeas, it->prevobj))
+		{
+			if (lp->vtype[lp->nbaz[pr.eindex]] == VFREE ||
+					lp->vtype[lp->baz[rs.lindex]] == VARTIFICIAL)
+			{
+				if (it->noprog > 0)
+					it->noprog--;
+			}
+			else
+				it->noprog++;
+		}
+		else
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (it->prevobj, lp->pinfeas);
+			it->noprog = 0;
+		}
+
+		EGLPNUM_TYPENAME_ILLfct_compute_zz (lp, &(lp->zz), rs.lindex);
+		EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_ZNZ, lp->zz.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+		if (pinf->p_strategy == COMPLETE_PRICING)
+		{
+			//ILL_IFTRACE("%s:a\n",__func__);
+			EGLPNUM_TYPENAME_ILLfct_compute_zA (lp, &(lp->zz), &(lp->zA));
+			EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_ZANZ, lp->zA.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+
+			if (pinf->pI_price == QS_PRICE_PSTEEP)
+			{
+				EGLPNUM_TYPENAME_ILLfct_compute_psteep_upv (lp, wz);
+			}
+		}
+
+		rval =
+			EGLPNUM_TYPENAME_ILLprice_update_pricing_info (lp, pinf, cphase, wz, pr.eindex, rs.lindex,
+																		rs.pivotval);
+		CHECKRVALG (rval, CLEANUP);
+
+		//ILL_IFTRACE("%s:b:%d\n",__func__,rs.lindex);
+		EGLPNUM_TYPENAME_ILLfct_update_xz (lp, rs.tz, pr.eindex, rs.lindex);
+		EGLPNUM_TYPENAME_ILLfct_update_pfeas (lp, rs.lindex, &(lp->srhs));
+		//ILL_IFTRACE("%s:%d:%d\n",__func__,rs.lindex,lp->srhs.nzcnt);
+		EGLPNUM_TYPENAME_ILLfct_compute_ppIzz (lp, &(lp->srhs), &(lp->ssoln));
+		EGLPNUM_TYPENAME_ILLfct_update_basis_info (lp, pr.eindex, rs.lindex, rs.lvstat);
+#if DENSE_PI > 0
+		EGLPNUM_TYPENAME_fct_test_workvector (lp);
+		EGLPNUM_TYPENAME_fct_test_pfeasible (lp);
+#endif
+		rval = EGLPNUM_TYPENAME_ILLbasis_update (lp, updz, rs.lindex, &refactor, &singular);
+		CHECKRVALG (rval, CLEANUP);
+
+		if (singular)
+		{
+			it->nextstep = SIMPLEX_RESUME;
+			it->resumeid = SIMPLEX_RESUME_SING;
+			/* this is to force to exit in the case of bad basis */
+			it->n_restart++;
+			EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->pfeas_tol, SIMPLEX_FACTOR);
+			EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->dfeas_tol, SIMPLEX_FACTOR);
+			//QSlog("Resume Singular %s:%s:%d",__func__,__FILE__,__LINE__);
+			ILL_CLEANUP;
+		}
+		if (!refactor)
+		{
+			EGLPNUM_TYPENAME_ILLfct_update_ppI_prices (lp, pinf, &(lp->srhs), &(lp->ssoln), pr.eindex,
+																rs.lindex, alpha);
+		}
+		if (refactor != 0 || it->nosolve > PARAM_MAX_NOSOLVE)
+		{
+			EGLPNUM_TYPENAME_ILLfct_compute_xbz (lp);
+			EGLPNUM_TYPENAME_ILLfct_check_pfeasible (lp, &fi, lp->tol->ip_tol);
+			EGLPNUM_TYPENAME_ILLfct_set_status_values (lp, fi.pstatus, -1, PHASEII, -1);
+			if (fi.pstatus == PRIMAL_FEASIBLE)
+				it->nextphase = PRIMAL_PHASEII;
+
+			it->newphase = SIMPLEX_PHASE_RECOMP;
+			ILL_CLEANUP;
+		}
+	}
+
+#if DENSE_PI > 1
+	EGLPNUM_TYPENAME_fct_test_workvector (lp);
+	fct_test_pi_dz (lp, pinf);
+#endif
+
+CLEANUP:
+	if (it->nextphase != PRIMAL_PHASEI || it->nextstep == SIMPLEX_RESUME ||
+			it->newphase != 0 || rval != 0)
+	{
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->pIpiz);
+		EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->pIdz);
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (alpha);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (fi.totinfeas);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (pr.dinfeas);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (pr.pinfeas);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (rs.tz);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (rs.lbound);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (rs.ecoeff);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (rs.pivotval);
+	//EG_RETURN(rval);
+	return rval;
+}
+
+static int primal_phaseII_step (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * pinf,
+	EGLPNUM_TYPENAME_svector * updz,
+	EGLPNUM_TYPENAME_svector * wz,
+	EGLPNUM_TYPENAME_iter_info * it)
+{
+	int boundch;
+	int rval = 0;
+	int bndtype = 0;
+	int singular = 0;
+	int refactor = 0;
+	int ratio_iter = 0;
+	int cphase = PRIMAL_PHASEII;
+	EGLPNUM_TYPE lbound;
+	EGLPNUM_TYPE alpha;
+	EGLPNUM_TYPENAME_feas_info fi;
+	EGLPNUM_TYPENAME_ratio_res rs;
+	EGLPNUM_TYPENAME_price_res pr;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (alpha);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (lbound);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (fi.totinfeas);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (pr.dinfeas);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (pr.pinfeas);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (rs.tz);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (rs.lbound);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (rs.ecoeff);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (rs.pivotval);
+
+	EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_PPHASE2ITER, 0, EGLPNUM_TYPENAME_zeroLpNum);
+	it->nextstep = SIMPLEX_CONTINUE;
+	it->nextphase = PRIMAL_PHASEII;
+	lp->final_phase = PRIMAL_PHASEII;
+	it->nosolve++;
+
+	if (it->newphase != 0)
+	{
+		EGLPNUM_TYPENAME_ILLfct_compute_pobj (lp);
+		if (it->newphase == SIMPLEX_PHASE_NEW)
+		{
+			it->noprog = 0;
+			if (it->sdisplay)
+			{
+				QSlog("starting primal phase II, nosolve %d", it->nosolve);
+			}
+		}
+		it->newphase = 0;
+		it->nosolve = 0;
+		EGLPNUM_TYPENAME_EGlpNumCopy (it->prevobj, lp->pobjval);
+		EGLPNUM_TYPENAME_ILLfct_compute_piz (lp);
+		if (pinf->p_strategy == COMPLETE_PRICING)
+		{
+			EGLPNUM_TYPENAME_ILLfct_compute_dz (lp);
+#if USEHEAP > 0
+			EGLPNUM_TYPENAME_ILLprice_free_heap (pinf);
+#endif
+			EGLPNUM_TYPENAME_ILLprice_compute_dual_inf (lp, pinf, NULL, 0, PRIMAL_PHASEII);
+#if USEHEAP > 0
+			rval = EGLPNUM_TYPENAME_ILLprice_test_for_heap (lp, pinf, lp->nnbasic, pinf->d_scaleinf,
+																		 PRIMAL_SIMPLEX, 0);
+			CHECKRVALG (rval, CLEANUP);
+#endif
+		}
+		else if (pinf->p_strategy == MULTI_PART_PRICING)
+		{
+			EGLPNUM_TYPENAME_ILLprice_init_mpartial_price (lp, pinf, cphase, COL_PRICING);
+		}
+	}
+
+	monitor_iter (lp, pinf, it, cphase);
+	if (it->nextstep == SIMPLEX_TERMINATE || it->nextstep == SIMPLEX_RESUME ||
+			it->newphase != 0)
+		ILL_CLEANUP;
+
+	EGLPNUM_TYPENAME_ILLprice_primal (lp, pinf, &pr, cphase);
+
+	if (pr.price_stat == PRICE_OPTIMAL)
+	{
+		//ILL_IFTRACE("%s:PRICE_OPTIMAL\n",__func__);
+		if (lp->nbchange != 0)
+		{
+			if (it->sdisplay > 1)
+			{
+				QSlog("unrolling %d bound shifts", lp->nbchange);
+			}
+			EGLPNUM_TYPENAME_ILLfct_unroll_bound_change (lp);
+			EGLPNUM_TYPENAME_ILLfct_check_pfeasible (lp, &fi, lp->tol->pfeas_tol);
+			EGLPNUM_TYPENAME_ILLfct_set_status_values (lp, fi.pstatus, -1, PHASEII, -1);
+
+			 /*HHH*/ EGLPNUM_TYPENAME_ILLfct_check_dfeasible (lp, &fi, lp->tol->dfeas_tol);
+			/*HHH* QSlog("primal (opt) infeas %.6f", lp->pinfeas);
+			 *HHH* QSlog("dual (opt) infeas %.6f", lp->dinfeas);*/
+
+			if (fi.pstatus != PRIMAL_FEASIBLE)
+			{
+				it->algorithm = DUAL_SIMPLEX;
+				it->nextstep = SIMPLEX_RESUME;
+				it->resumeid = SIMPLEX_RESUME_UNSHIFT;
+				it->pricetype = QS_PRICE_DDEVEX;
+				/* this is to force to exit in the case of bad basis */
+				//QSlog("Resume Unshift %s:%s:%d",__func__,__FILE__,__LINE__);
+				EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->pfeas_tol, SIMPLEX_FACTOR);
+				EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->dfeas_tol, SIMPLEX_FACTOR);
+				it->n_restart++;
+				ILL_CLEANUP;
+				/*
+				 * it->nextphase = PRIMAL_PHASEI;
+				 * lp->tol->ip_tol /= 5.0;
+				 * lp->tol->id_tol /= 5.0;
+				 * ILL_CLEANUP;
+				 */
+			}
+		}
+
+		if (it->sdisplay > 1)
+		{
+			QSlog("problem seemingly solved");
+			QSlog("seemingly opt = %f",
+									EGLPNUM_TYPENAME_EGlpNumToLf (lp->pobjval));
+			QSlog("retesting soln");
+		}
+		rval = EGLPNUM_TYPENAME_ILLsimplex_retest_psolution (lp, pinf, cphase, &fi);
+		CHECKRVALG (rval, CLEANUP);
+		EGLPNUM_TYPENAME_ILLfct_set_status_values (lp, fi.pstatus, fi.dstatus, PHASEII, PHASEII);
+
+		if (fi.pstatus == PRIMAL_INFEASIBLE)
+		{
+			it->nextphase = PRIMAL_PHASEI;
+			EGLPNUM_TYPENAME_EGlpNumDivUiTo (lp->tol->ip_tol, 5);
+			EGLPNUM_TYPENAME_EGlpNumDivUiTo (lp->tol->id_tol, 5);
+			ILL_IFTRACE ("%s:PINF:%lg\n", __func__, EGLPNUM_TYPENAME_EGlpNumToLf (lp->tol->ip_tol));
+		}
+		else if (fi.dstatus == DUAL_FEASIBLE)
+		{
+			//ILL_IFTRACE("%s:PFEAS_DFEAS\n",__func__);
+			it->solstatus = ILL_LP_SOLVED;
+			EGLPNUM_TYPENAME_EGlpNumCopy (lp->objval, lp->pobjval);
+			it->nextstep = SIMPLEX_TERMINATE;
+		}
+		else
+			ILL_IFTRACE ("%s:DINF:%la:%lf\n", __func__, EGLPNUM_TYPENAME_EGlpNumToLf (lp->dinfeas),
+									 EGLPNUM_TYPENAME_EGlpNumToLf (lp->dinfeas));
+		ILL_CLEANUP;
+	}
+
+	EGLPNUM_TYPENAME_ILLfct_compute_yz (lp, &(lp->yjz), updz, lp->nbaz[pr.eindex]);
+	EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_YNZ, lp->yjz.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+	EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_UPNZ, updz->nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+	ratio_iter = 0;
+	do
+	{
+		EGLPNUM_TYPENAME_ILLratio_pII_test (lp, pr.eindex, pr.dir, &rs);
+		//ILL_IFTRACE("all:%d",rs.lindex);
+		EGLPNUM_TYPENAME_EGlpNumCopy (lbound, rs.lbound);
+		boundch = rs.boundch;
+		ratio_iter++;
+
+		if (boundch)
+		{
+			/*
+			 * if (ratio_iter > PARAM_PRATIOTESTS){
+			 * lbound = lp->xbz[rs.lindex];
+			 * boundch = 0;
+			 * }
+			 */
+			boundch = 0;
+			bndtype = (rs.lvstat == STAT_UPPER) ? BOUND_UPPER : BOUND_LOWER;
+			rval = EGLPNUM_TYPENAME_ILLfct_bound_shift (lp, lp->baz[rs.lindex], bndtype, lbound);
+			CHECKRVALG (rval, CLEANUP);
+		}
+	} while (boundch);
+
+	if (rs.ratio_stat == RATIO_FAILED)
+	{
+		//ILL_IFTRACE(":%d",rs.lindex);
+		/*
+		 * rval = E_SIMPLEX_ERROR;
+		 * it->solstatus = ILL_PPHASEII_ERROR;
+		 */
+		it->algorithm = DUAL_SIMPLEX;
+		it->nextstep = SIMPLEX_RESUME;
+		it->resumeid = SIMPLEX_RESUME_NUMER;
+		/* this is to force to exit in the case of bad basis */
+		it->n_restart++;
+		EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->pfeas_tol, SIMPLEX_FACTOR);
+		EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->dfeas_tol, SIMPLEX_FACTOR);
+		//QSlog("Resume Numerical %s:%s:%d",__func__,__FILE__,__LINE__);
+		ILL_CLEANUP;
+	}
+	else if (rs.ratio_stat == RATIO_UNBOUNDED)
+	{
+		//ILL_IFTRACE(":%d",rs.lindex);
+		if (lp->nbchange != 0)
+		{
+			if (it->sdisplay > 1)
+			{
+				QSlog("unrolling %d bound shifts", lp->nbchange);
+			}
+			EGLPNUM_TYPENAME_ILLfct_unroll_bound_change (lp);
+		}
+		EGLPNUM_TYPENAME_ILLfct_set_status_values (lp, PRIMAL_UNBOUNDED, -1, PHASEII, -1);
+		it->solstatus = ILL_LP_SOLVED;
+		it->nextstep = SIMPLEX_TERMINATE;
+		ILL_CLEANUP;
+	}
+	else if (rs.ratio_stat == RATIO_NOBCHANGE)
+	{
+		//ILL_IFTRACE(":%d",rs.lindex);
+		EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (lp->pobjval, rs.tz, lp->dz[pr.eindex]);
+		EGLPNUM_TYPENAME_EGlpNumCopy (lp->objval, lp->pobjval);
+		if (!test_progress (lp->pobjval, it->prevobj))
+			it->noprog++;
+		else
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (it->prevobj, lp->pobjval);
+			it->noprog = 0;
+		}
+
+		//ILL_IFTRACE("%s:c:%d\n",__func__,rs.lindex);
+		EGLPNUM_TYPENAME_ILLfct_update_xz (lp, rs.tz, pr.eindex, rs.lindex);
+		EGLPNUM_TYPENAME_ILLfct_update_basis_info (lp, pr.eindex, rs.lindex, rs.lvstat);
+		if (pinf->p_strategy == COMPLETE_PRICING)
+			EGLPNUM_TYPENAME_ILLprice_compute_dual_inf (lp, pinf, &pr.eindex, 1, PRIMAL_PHASEII);
+		else if (pinf->p_strategy == MULTI_PART_PRICING)
+			EGLPNUM_TYPENAME_ILLprice_update_mpartial_price (lp, pinf, cphase, COL_PRICING);
+	}
+	else if (rs.ratio_stat == RATIO_BCHANGE)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopyFrac (alpha, lp->dz[pr.eindex], rs.pivotval);
+		EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (lp->pobjval, rs.tz, lp->dz[pr.eindex]);
+		EGLPNUM_TYPENAME_EGlpNumCopy (lp->objval, lp->pobjval);
+
+		if (!test_progress (lp->pobjval, it->prevobj))
+		{
+			//ILL_IFTRACE(":%d",rs.lindex);
+			if (lp->vtype[lp->nbaz[pr.eindex]] == VFREE ||
+					lp->vtype[lp->baz[rs.lindex]] == VARTIFICIAL)
+			{
+				if (it->noprog > 0)
+					it->noprog--;
+			}
+			else
+				it->noprog++;
+		}
+		else
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (it->prevobj, lp->pobjval);
+			it->noprog = 0;
+		}
+
+		//ILL_IFTRACE(":%d",rs.lindex);
+		EGLPNUM_TYPENAME_ILLfct_compute_zz (lp, &(lp->zz), rs.lindex);
+		EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_ZNZ, lp->zz.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+		if (pinf->p_strategy == COMPLETE_PRICING)
+		{
+			//ILL_IFTRACE("%s:b\n",__func__);
+			EGLPNUM_TYPENAME_ILLfct_compute_zA (lp, &(lp->zz), &(lp->zA));
+			EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_ZANZ, lp->zA.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+			if (pinf->pII_price == QS_PRICE_PSTEEP)
+				EGLPNUM_TYPENAME_ILLfct_compute_psteep_upv (lp, wz);
+		}
+		rval =
+			EGLPNUM_TYPENAME_ILLprice_update_pricing_info (lp, pinf, cphase, wz, pr.eindex, rs.lindex,
+																		rs.pivotval);
+		CHECKRVALG (rval, CLEANUP);
+
+		//ILL_IFTRACE("%s:d:%d\n",__func__,rs.lindex);
+		EGLPNUM_TYPENAME_ILLfct_update_xz (lp, rs.tz, pr.eindex, rs.lindex);
+		EGLPNUM_TYPENAME_ILLfct_update_basis_info (lp, pr.eindex, rs.lindex, rs.lvstat);
+		rval = EGLPNUM_TYPENAME_ILLbasis_update (lp, updz, rs.lindex, &refactor, &singular);
+		CHECKRVALG (rval, CLEANUP);
+
+		if (singular)
+		{
+			it->nextstep = SIMPLEX_RESUME;
+			it->resumeid = SIMPLEX_RESUME_SING;
+			/* this is to force to exit in the case of bad basis */
+			it->n_restart++;
+			//QSlog("Resume Singular %s:%s:%d",__func__,__FILE__,__LINE__);
+			EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->pfeas_tol, SIMPLEX_FACTOR);
+			EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->dfeas_tol, SIMPLEX_FACTOR);
+			ILL_CLEANUP;
+		}
+		if (!refactor)
+		{
+			EGLPNUM_TYPENAME_ILLfct_update_piz (lp, alpha);
+
+			if (pinf->p_strategy == COMPLETE_PRICING)
+			{
+				EGLPNUM_TYPENAME_ILLfct_update_dz (lp, pr.eindex, alpha);
+				EGLPNUM_TYPENAME_ILLprice_compute_dual_inf (lp, pinf, lp->zA.indx, lp->zA.nzcnt,
+																	 PRIMAL_PHASEII);
+				EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_ZARAVG, lp->zA.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+			}
+			else if (pinf->p_strategy == MULTI_PART_PRICING)
+			{
+				EGLPNUM_TYPENAME_ILLprice_update_mpartial_price (lp, pinf, cphase, COL_PRICING);
+			}
+		}
+		if (refactor != 0 || it->nosolve > PARAM_MAX_NOSOLVE)
+		{
+			EGLPNUM_TYPENAME_ILLfct_compute_xbz (lp);
+			it->newphase = SIMPLEX_PHASE_RECOMP;
+		}
+	}
+
+CLEANUP:
+	EGLPNUM_TYPENAME_EGlpNumClearVar (alpha);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (lbound);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (fi.totinfeas);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (pr.dinfeas);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (pr.pinfeas);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (rs.tz);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (rs.lbound);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (rs.ecoeff);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (rs.pivotval);
+	//EG_RETURN(rval);
+	return rval;
+}
+
+static int dual_phaseI_step (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * pinf,
+	EGLPNUM_TYPENAME_svector * updz,
+	EGLPNUM_TYPENAME_svector * wz,
+	EGLPNUM_TYPENAME_iter_info * it)
+{
+	int rval = 0;
+	int singular = 0;
+	int refactor = 0;
+	int cphase = DUAL_PHASEI;
+	EGLPNUM_TYPE alpha;
+	EGLPNUM_TYPE alpha1;
+	EGLPNUM_TYPENAME_feas_info fi;
+	EGLPNUM_TYPENAME_ratio_res rs;
+	EGLPNUM_TYPENAME_price_res pr;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (alpha);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (alpha1);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (fi.totinfeas);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (pr.dinfeas);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (pr.pinfeas);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (rs.tz);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (rs.lbound);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (rs.ecoeff);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (rs.pivotval);
+	EGLPNUM_TYPENAME_EGlpNumZero (alpha1);
+
+	EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_DPHASE1ITER, 0, EGLPNUM_TYPENAME_zeroLpNum);
+	it->nextstep = SIMPLEX_CONTINUE;
+	it->nextphase = DUAL_PHASEI;
+	lp->final_phase = DUAL_PHASEI;
+	it->nosolve++;
+
+	if (it->newphase != 0)
+	{
+		EGLPNUM_TYPENAME_ILLfct_check_dfeasible (lp, &fi, lp->tol->id_tol);
+		if (it->newphase == SIMPLEX_PHASE_NEW)
+		{
+			it->noprog = 0;
+			if (it->sdisplay)
+			{
+				QSlog("starting dual phase I, nosolve %d", it->nosolve);
+			}
+		}
+		it->newphase = 0;
+		it->nosolve = 0;
+		EGLPNUM_TYPENAME_EGlpNumCopy (it->prevobj, lp->dinfeas);
+
+		EGLPNUM_TYPENAME_ILLfct_compute_phaseI_xbz (lp);
+		if (pinf->d_strategy == COMPLETE_PRICING)
+		{
+#if USEHEAP > 0
+			EGLPNUM_TYPENAME_ILLprice_free_heap (pinf);
+#endif
+			EGLPNUM_TYPENAME_ILLprice_compute_primal_inf (lp, pinf, NULL, 0, DUAL_PHASEI);
+#if USEHEAP > 0
+			rval = EGLPNUM_TYPENAME_ILLprice_test_for_heap (lp, pinf, lp->nrows, pinf->p_scaleinf,
+																		 DUAL_SIMPLEX, 0);
+			CHECKRVALG (rval, CLEANUP);
+#endif
+		}
+		else if (pinf->d_strategy == MULTI_PART_PRICING)
+		{
+			EGLPNUM_TYPENAME_ILLprice_init_mpartial_price (lp, pinf, cphase, ROW_PRICING);
+		}
+	}
+
+	monitor_iter (lp, pinf, it, cphase);
+	if (it->nextstep == SIMPLEX_TERMINATE || it->nextstep == SIMPLEX_RESUME ||
+			it->newphase != 0)
+		ILL_CLEANUP;
+
+	EGLPNUM_TYPENAME_ILLprice_dual (lp, pinf, cphase, &pr);
+
+	if (pr.price_stat == PRICE_OPTIMAL)
+	{
+		if (it->sdisplay > 1)
+		{
+			QSlog("dual phase I seemingly done");
+			QSlog("retesting soln");
+		}
+
+		rval = EGLPNUM_TYPENAME_ILLsimplex_retest_dsolution (lp, pinf, cphase, &fi);
+		CHECKRVALG (rval, CLEANUP);
+		EGLPNUM_TYPENAME_ILLfct_set_status_values (lp, fi.pstatus, fi.dstatus, PHASEI, PHASEII);
+
+		if (fi.dstatus == DUAL_FEASIBLE)
+		{
+			it->nextphase = DUAL_PHASEII;
+		}
+		else if (fi.pstatus == PRIMAL_FEASIBLE)
+		{
+			it->solstatus = ILL_LP_SOLVED;
+			it->nextstep = SIMPLEX_TERMINATE;
+		}
+		it->newphase = SIMPLEX_PHASE_NEW;
+		ILL_CLEANUP;
+	}
+
+	EGLPNUM_TYPENAME_ILLfct_compute_zz (lp, &(lp->zz), pr.lindex);
+	//ILL_IFTRACE("%s:c\n",__func__);
+	EGLPNUM_TYPENAME_ILLfct_compute_zA (lp, &(lp->zz), &(lp->zA));
+	EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_ZNZ, lp->zz.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+	EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_ZANZ, lp->zA.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+
+	EGLPNUM_TYPENAME_ILLratio_dI_test (lp, pr.lindex, pr.lvstat, &rs);
+
+	if (rs.ratio_stat == RATIO_FAILED)
+	{
+		/*
+		 * rval = E_SIMPLEX_ERROR;
+		 * it->solstatus = ILL_DPHASEI_ERROR;
+		 */
+		it->algorithm = PRIMAL_SIMPLEX;
+		it->nextstep = SIMPLEX_RESUME;
+		it->resumeid = SIMPLEX_RESUME_NUMER;
+		/* this is to force to exit in the case of bad basis */
+		it->n_restart++;
+		EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->pfeas_tol, SIMPLEX_FACTOR);
+		EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->dfeas_tol, SIMPLEX_FACTOR);
+		//QSlog("Resume Numerical %s:%s:%d",__func__,__FILE__,__LINE__);
+		ILL_CLEANUP;
+	}
+	else if (rs.ratio_stat == RATIO_BCHANGE)
+	{
+		EGLPNUM_TYPENAME_ILLfct_compute_yz (lp, &(lp->yjz), updz, lp->nbaz[rs.eindex]);
+		rval = EGLPNUM_TYPENAME_ILLfct_test_pivot (lp, pr.lindex, ROW_PIVOT, rs.pivotval);
+		if (rval)
+		{
+			it->n_pivot_fail++;
+			if (it->n_pivot_fail > SIMPLEX_MAX_PIVOT_FAIL)
+			{
+				it->n_pivot_fail = 0;
+				/* this is to force to exit in the case of bad basis */
+				it->n_restart++;
+				it->algorithm = PRIMAL_SIMPLEX;
+				it->nextstep = SIMPLEX_RESUME;
+				it->resumeid = SIMPLEX_RESUME_NUMER;
+				EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->pfeas_tol, SIMPLEX_FACTOR);
+				EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->dfeas_tol, SIMPLEX_FACTOR);
+				//QSlog("Resume Pivot %s:%s:%d",__func__,__FILE__,__LINE__);
+				rval = 0;
+				ILL_CLEANUP;
+			}
+			rval = EGLPNUM_TYPENAME_ILLbasis_factor (lp, &singular);
+			if (singular)
+				MESSAGE (__QS_SB_VERB, "Singular basis found!");
+			CHECKRVALG (rval, CLEANUP);
+			if (singular == 0)
+				refactor = 1;
+			goto END;
+		}
+		EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_YNZ, lp->yjz.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+		EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_UPNZ, updz->nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+
+		if (pinf->dI_price == QS_PRICE_DSTEEP)
+			EGLPNUM_TYPENAME_ILLfct_compute_dsteep_upv (lp, wz);
+		rval =
+			EGLPNUM_TYPENAME_ILLprice_update_pricing_info (lp, pinf, cphase, wz, rs.eindex, pr.lindex,
+																		rs.pivotval);
+		CHECKRVALG (rval, CLEANUP);
+
+		EGLPNUM_TYPENAME_EGlpNumSubTo (lp->dinfeas, lp->upd.c_obj);
+
+		if (!test_progress (lp->dinfeas, it->prevobj))
+		{
+			if (lp->vtype[lp->baz[pr.lindex]] == VARTIFICIAL ||
+					lp->vtype[lp->nbaz[rs.eindex]] == VFREE)
+			{
+				if (it->noprog > 0)
+					it->noprog--;
+			}
+			else
+				it->noprog++;
+		}
+		else
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (it->prevobj, lp->dinfeas);
+			it->noprog = 0;
+		}
+
+		EGLPNUM_TYPENAME_EGlpNumCopyFrac (alpha, lp->dz[rs.eindex], rs.pivotval);
+		EGLPNUM_TYPENAME_EGlpNumCopyFrac (alpha1, lp->xbz[pr.lindex], rs.pivotval);
+
+		EGLPNUM_TYPENAME_ILLfct_update_piz (lp, alpha);
+		EGLPNUM_TYPENAME_ILLfct_update_dz (lp, rs.eindex, alpha);
+		EGLPNUM_TYPENAME_ILLfct_update_dfeas (lp, rs.eindex, &(lp->srhs));
+		EGLPNUM_TYPENAME_ILLfct_compute_dpIy (lp, &(lp->srhs), &(lp->ssoln));
+		EGLPNUM_TYPENAME_ILLfct_update_basis_info (lp, rs.eindex, pr.lindex, pr.lvstat);
+
+#if DENSE_PI > 0
+		EGLPNUM_TYPENAME_fct_test_workvector (lp);
+		EGLPNUM_TYPENAME_fct_test_dfeasible (lp);
+#endif
+		rval = EGLPNUM_TYPENAME_ILLbasis_update (lp, updz, pr.lindex, &refactor, &singular);
+		CHECKRVALG (rval, CLEANUP);
+
+#if DENSE_NORM > 0
+		EGLPNUM_TYPENAME_test_dsteep_norms (lp, pinf);
+#endif
+
+		EGLPNUM_TYPENAME_ILLfct_update_dpI_prices (lp, pinf, &(lp->srhs), &(lp->ssoln), pr.lindex,
+															alpha1);
+
+	END:
+		if (singular)
+		{
+			it->nextstep = SIMPLEX_RESUME;
+			it->resumeid = SIMPLEX_RESUME_SING;
+			/* this is to force to exit in the case of bad basis */
+			it->n_restart++;
+			//QSlog("Resume Singular %s:%s:%d",__func__,__FILE__,__LINE__);
+			EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->pfeas_tol, SIMPLEX_FACTOR);
+			EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->dfeas_tol, SIMPLEX_FACTOR);
+			ILL_CLEANUP;
+		}
+		if (refactor != 0 || it->nosolve > PARAM_MAX_NOSOLVE)
+		{
+			EGLPNUM_TYPENAME_ILLfct_compute_piz (lp);
+			EGLPNUM_TYPENAME_ILLfct_compute_dz (lp);
+			EGLPNUM_TYPENAME_ILLfct_dual_adjust (lp, EGLPNUM_TYPENAME_zeroLpNum);
+			EGLPNUM_TYPENAME_ILLfct_check_dfeasible (lp, &fi, lp->tol->id_tol);
+			EGLPNUM_TYPENAME_ILLfct_set_status_values (lp, -1, fi.dstatus, -1, PHASEII);
+			if (fi.dstatus == DUAL_FEASIBLE)
+				it->nextphase = DUAL_PHASEII;
+
+			it->newphase = SIMPLEX_PHASE_RECOMP;
+			ILL_CLEANUP;
+		}
+	}
+
+#if DENSE_PI > 1
+	EGLPNUM_TYPENAME_fct_test_workvector (lp);
+	EGLPNUM_TYPENAME_fct_test_pI_x (lp, pinf);
+#endif
+
+CLEANUP:
+	EGLPNUM_TYPENAME_EGlpNumClearVar (alpha);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (alpha1);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (fi.totinfeas);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (pr.dinfeas);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (pr.pinfeas);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (rs.tz);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (rs.lbound);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (rs.ecoeff);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (rs.pivotval);
+	//EG_RETURN(rval);
+	return rval;
+}
+
+static int dual_phaseII_step (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * pinf,
+	EGLPNUM_TYPENAME_svector * updz,
+	EGLPNUM_TYPENAME_svector * wz,
+	EGLPNUM_TYPENAME_iter_info * it)
+{
+	int coeffch;
+	int rval = 0;
+	int singular = 0;
+	int refactor = 0;
+	int ratio_iter = 0;
+	int cphase = DUAL_PHASEII;
+	int lcol, ecol;
+	int estat, newphase;
+	EGLPNUM_TYPE x_bi, v_l, eval;
+	EGLPNUM_TYPE ecoeff;
+	EGLPNUM_TYPE alpha;
+	EGLPNUM_TYPE alpha1;
+	EGLPNUM_TYPENAME_feas_info fi;
+	EGLPNUM_TYPENAME_ratio_res rs;
+	EGLPNUM_TYPENAME_price_res pr;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (x_bi);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (v_l);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (eval);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (ecoeff);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (alpha);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (alpha1);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (fi.totinfeas);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (pr.dinfeas);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (pr.pinfeas);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (rs.tz);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (rs.lbound);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (rs.ecoeff);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (rs.pivotval);
+	EGLPNUM_TYPENAME_EGlpNumZero (rs.ecoeff);
+	EGLPNUM_TYPENAME_EGlpNumZero (alpha1);
+
+	EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_DPHASE2ITER, 0, EGLPNUM_TYPENAME_zeroLpNum);
+	it->nextstep = SIMPLEX_CONTINUE;
+	it->nextphase = DUAL_PHASEII;
+	lp->final_phase = DUAL_PHASEII;
+	newphase = it->newphase;
+	it->nosolve++;
+
+	if (it->newphase != 0)
+	{
+		EGLPNUM_TYPENAME_ILLfct_compute_dobj (lp);
+		if (it->newphase == SIMPLEX_PHASE_NEW)
+		{
+			it->noprog = 0;
+			if (it->sdisplay)
+			{
+				QSlog("starting dual phase II, nosolve %d", it->nosolve);
+			}
+		}
+		it->newphase = 0;
+		it->nosolve = 0;
+		EGLPNUM_TYPENAME_EGlpNumCopy (it->prevobj, lp->dobjval);
+		EGLPNUM_TYPENAME_ILLfct_compute_xbz (lp);
+
+		if (pinf->d_strategy == COMPLETE_PRICING)
+		{
+#if USEHEAP > 0
+			EGLPNUM_TYPENAME_ILLprice_free_heap (pinf);
+#endif
+			EGLPNUM_TYPENAME_ILLprice_compute_primal_inf (lp, pinf, NULL, 0, DUAL_PHASEII);
+#if USEHEAP > 0
+			rval = EGLPNUM_TYPENAME_ILLprice_test_for_heap (lp, pinf, lp->nrows, pinf->p_scaleinf,
+																		 DUAL_SIMPLEX, 0);
+			CHECKRVALG (rval, CLEANUP);
+#endif
+		}
+		else if (pinf->d_strategy == MULTI_PART_PRICING)
+		{
+			EGLPNUM_TYPENAME_ILLprice_init_mpartial_price (lp, pinf, cphase, ROW_PRICING);
+		}
+	}
+
+	monitor_iter (lp, pinf, it, cphase);
+	if (it->nextstep == SIMPLEX_TERMINATE || it->nextstep == SIMPLEX_RESUME ||
+			it->newphase != 0)
+		ILL_CLEANUP;
+
+	EGLPNUM_TYPENAME_ILLprice_dual (lp, pinf, cphase, &pr);
+
+	if (pr.price_stat == PRICE_OPTIMAL)
+	{
+		if (lp->ncchange != 0)
+		{
+			if (it->sdisplay > 1)
+			{
+				QSlog("unrolling %d coef shifts", lp->ncchange);
+			}
+			EGLPNUM_TYPENAME_ILLfct_unroll_coef_change (lp);
+			EGLPNUM_TYPENAME_ILLfct_check_dfeasible (lp, &fi, lp->tol->dfeas_tol);
+			EGLPNUM_TYPENAME_ILLfct_set_status_values (lp, -1, fi.dstatus, -1, PHASEII);
+
+			 /*HHH*/ EGLPNUM_TYPENAME_ILLfct_check_pfeasible (lp, &fi, lp->tol->pfeas_tol);
+			/*HHH* QSlog("dual (opt) infeas %.6f", lp->dinfeas);
+			 *HHH* QSlog("primal (opt) infeas %.6f", lp->pinfeas);*/
+
+			if (fi.dstatus != DUAL_FEASIBLE)
+			{
+				it->algorithm = PRIMAL_SIMPLEX;
+				it->nextstep = SIMPLEX_RESUME;
+				it->resumeid = SIMPLEX_RESUME_UNSHIFT;
+				it->pricetype = QS_PRICE_PDEVEX;
+				/* this is to force to exit in the case of bad basis */
+				it->n_restart++;
+				EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->pfeas_tol, SIMPLEX_FACTOR);
+				EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->dfeas_tol, SIMPLEX_FACTOR);
+				//QSlog("Resume Unshift %s:%s:%d",__func__,__FILE__,__LINE__);
+				ILL_CLEANUP;
+				/*
+				 * it->nextphase = DUAL_PHASEI;
+				 * lp->tol->ip_tol /= 5.0;
+				 * lp->tol->id_tol /= 5.0;
+				 * ILL_CLEANUP;
+				 */
+			}
+		}
+		if (it->sdisplay > 1)
+		{
+			//ILL_IFTRACE("\t%s:%s:%d\n",__func__,__FILE__,__LINE__);
+			QSlog("problem seemingly solved");
+			QSlog("seemingly dual opt = %f", EGLPNUM_TYPENAME_EGlpNumToLf (lp->dobjval));
+			QSlog("retesting soln");
+		}
+
+		rval = EGLPNUM_TYPENAME_ILLsimplex_retest_dsolution (lp, pinf, cphase, &fi);
+		CHECKRVALG (rval, CLEANUP);
+		EGLPNUM_TYPENAME_ILLfct_set_status_values (lp, fi.pstatus, fi.dstatus, PHASEII, PHASEII);
+
+		if (fi.dstatus == DUAL_INFEASIBLE)
+		{
+			ILL_IFTRACE ("DUAL_INFEAS: %s\n", __func__);
+			it->nextphase = DUAL_PHASEI;
+			EGLPNUM_TYPENAME_EGlpNumDivUiTo (lp->tol->ip_tol, 5);
+			EGLPNUM_TYPENAME_EGlpNumDivUiTo (lp->tol->id_tol, 5);
+		}
+		else if (fi.pstatus == PRIMAL_FEASIBLE)
+		{
+			ILL_IFTRACE ("PRIM_FEAS: %s\n", __func__);
+			EGLPNUM_TYPENAME_EGlpNumCopy (lp->objval, lp->dobjval);
+			it->solstatus = ILL_LP_SOLVED;
+			it->nextstep = SIMPLEX_TERMINATE;
+		}
+		else
+			ILL_IFTRACE ("PRIM_INFEAS: %s\n", __func__);
+		ILL_CLEANUP;
+	}
+
+	EGLPNUM_TYPENAME_ILLfct_compute_zz (lp, &(lp->zz), pr.lindex);
+	//ILL_IFTRACE("%s:d\n",__func__);
+	EGLPNUM_TYPENAME_ILLfct_compute_zA (lp, &(lp->zz), &(lp->zA));
+	EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_ZNZ, lp->zz.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+	EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_ZANZ, lp->zA.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+
+	ratio_iter = 0;
+	do
+	{
+		EGLPNUM_TYPENAME_ILLratio_longdII_test (lp, pr.lindex, pr.lvstat, &rs);
+		if (rs.ratio_stat == RATIO_NEGATIVE)
+		{
+			if (it->sdisplay > 1)
+			{
+				QSlog("adjust coefs to remove negative ratio tests");
+			}
+			EGLPNUM_TYPENAME_ILLfct_adjust_viol_coefs (lp);
+			EGLPNUM_TYPENAME_ILLratio_longdII_test (lp, pr.lindex, pr.lvstat, &rs);
+			if (rs.ratio_stat == RATIO_NEGATIVE)
+			{
+				MESSAGE (__QS_SB_VERB, "internal error: bad ratio test");
+				rs.ratio_stat = RATIO_FAILED;
+				break;
+			}
+		}
+
+		coeffch = rs.coeffch;
+		EGLPNUM_TYPENAME_EGlpNumCopy (ecoeff, rs.ecoeff);
+		ratio_iter++;
+
+		if (coeffch)
+		{
+			/*
+			 * if (ratio_iter > PARAM_DRATIOTESTS){
+			 * ecoeff = lp->cz[lp->nbaz[rs.eindex]] - lp->dz[rs.eindex];
+			 * coeffch = 0;
+			 * }
+			 */
+			coeffch = 0;
+			rval = EGLPNUM_TYPENAME_ILLfct_coef_shift (lp, lp->nbaz[rs.eindex], ecoeff);
+			CHECKRVALG (rval, CLEANUP);
+		}
+		if (rs.ratio_stat == RATIO_BCHANGE)
+			if (lp->vstat[lp->nbaz[rs.eindex]] == STAT_ZERO)
+				break;
+
+	} while (coeffch);
+
+	if (rs.ratio_stat == RATIO_FAILED)
+	{
+		/*
+		 * rval = E_SIMPLEX_ERROR;
+		 * it->solstatus = ILL_DPHASEII_ERROR;
+		 */
+		it->algorithm = PRIMAL_SIMPLEX;
+		it->nextstep = SIMPLEX_RESUME;
+		it->resumeid = SIMPLEX_RESUME_NUMER;
+		/* this is to force to exit in the case of bad basis */
+		it->n_restart++;
+		EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->pfeas_tol, SIMPLEX_FACTOR);
+		EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->dfeas_tol, SIMPLEX_FACTOR);
+		//QSlog("Resume Numerical %s:%s:%d",__func__,__FILE__,__LINE__);
+		ILL_CLEANUP;
+	}
+	else if (rs.ratio_stat == RATIO_UNBOUNDED)
+	{
+		lp->infub_ix = pr.lindex;
+		if (lp->ncchange != 0)
+		{
+			if (it->sdisplay > 1)
+			{
+				QSlog("unrolling %d coef shifts", lp->ncchange);
+			}
+			EGLPNUM_TYPENAME_ILLfct_unroll_coef_change (lp);
+		}
+		EGLPNUM_TYPENAME_ILLfct_set_status_values (lp, -1, DUAL_UNBOUNDED, -1, PHASEII);
+		it->solstatus = ILL_LP_SOLVED;
+		it->nextstep = SIMPLEX_TERMINATE;
+	}
+	else if (rs.ratio_stat == RATIO_BCHANGE)
+	{
+		lcol = lp->baz[pr.lindex];
+		ecol = lp->nbaz[rs.eindex];
+
+		EGLPNUM_TYPENAME_ILLfct_compute_yz (lp, &(lp->yjz), updz, ecol);
+		EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_YNZ, lp->yjz.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+		EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_UPNZ, updz->nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+		rval = EGLPNUM_TYPENAME_ILLfct_test_pivot (lp, pr.lindex, ROW_PIVOT, rs.pivotval);
+		if (rval != 0)
+		{
+			it->n_pivot_fail++;
+			if (it->n_pivot_fail > SIMPLEX_MAX_PIVOT_FAIL)
+			{
+				it->n_pivot_fail = 0;
+				/* this is to force to exit in the case of bad basis */
+				it->algorithm = PRIMAL_SIMPLEX;
+				it->nextstep = SIMPLEX_RESUME;
+				it->resumeid = SIMPLEX_RESUME_NUMER;
+				it->n_restart++;
+				EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->pfeas_tol, SIMPLEX_FACTOR);
+				EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->dfeas_tol, SIMPLEX_FACTOR);
+				//QSlog("Resume Pivot %s:%s:%d",__func__,__FILE__,__LINE__);
+				rval = 0;
+				ILL_CLEANUP;
+			}
+			if (newphase == 0)
+			{
+				rval = EGLPNUM_TYPENAME_ILLbasis_factor (lp, &singular);
+				CHECKRVALG (rval, CLEANUP);
+				if (singular)
+					MESSAGE (__QS_SB_VERB, "Singular basis found!");
+#ifdef dbl_QSOPT_CURRENT_PRECICION
+				if (singular)
+				{
+					MESSAGE (__QS_SB_VERB, "Forcing fail!");
+					rval = QS_LP_CHANGE_PREC;
+				}
+#endif
+				if (singular == 0)
+					refactor = 1;
+				goto END;
+			}
+			else
+			{
+				if (it->sdisplay > 1)
+				{
+					QSlog("warning: bad step");
+				}
+			}
+		}
+
+		EGLPNUM_TYPENAME_EGlpNumAddTo (lp->dobjval, lp->upd.c_obj);
+		EGLPNUM_TYPENAME_EGlpNumCopy (lp->objval, lp->dobjval);
+
+		if (!test_progress (lp->dobjval, it->prevobj))
+		{
+			if (lp->vtype[lcol] == VARTIFICIAL || lp->vtype[ecol] == VFREE)
+			{
+				if (it->noprog > 0)
+					it->noprog--;
+			}
+			else
+				it->noprog++;
+		}
+		else
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (it->prevobj, lp->dobjval);
+			it->noprog = 0;
+		}
+
+		if (pinf->dII_price == QS_PRICE_DSTEEP)
+			EGLPNUM_TYPENAME_ILLfct_compute_dsteep_upv (lp, wz);
+		rval =
+			EGLPNUM_TYPENAME_ILLprice_update_pricing_info (lp, pinf, cphase, wz, rs.eindex, pr.lindex,
+																		rs.pivotval);
+		CHECKRVALG (rval, CLEANUP);
+
+		EGLPNUM_TYPENAME_EGlpNumCopy (x_bi, lp->xbz[pr.lindex]);
+		if (pr.lvstat == STAT_LOWER)
+			EGLPNUM_TYPENAME_EGlpNumCopy (v_l, lp->lz[lcol]);
+		else
+			EGLPNUM_TYPENAME_EGlpNumCopy (v_l, lp->uz[lcol]);
+		EGLPNUM_TYPENAME_EGlpNumCopy (alpha, rs.tz);
+		if (pr.lvstat == STAT_LOWER)
+			EGLPNUM_TYPENAME_EGlpNumSign (alpha);
+		estat = lp->vstat[ecol];
+		if (estat == STAT_LOWER)
+			EGLPNUM_TYPENAME_EGlpNumCopy (eval, lp->lz[ecol]);
+		else if (estat == STAT_ZERO)
+			EGLPNUM_TYPENAME_EGlpNumZero (eval);
+		else
+			EGLPNUM_TYPENAME_EGlpNumCopy (eval, lp->uz[ecol]);
+
+		EGLPNUM_TYPENAME_ILLfct_update_piz (lp, alpha);
+		EGLPNUM_TYPENAME_ILLfct_update_dz (lp, rs.eindex, alpha);
+		EGLPNUM_TYPENAME_ILLfct_update_dIIfeas (lp, rs.eindex, &(lp->srhs));
+		EGLPNUM_TYPENAME_ILLfct_compute_dpIIy (lp, &(lp->srhs), &(lp->ssoln));
+		EGLPNUM_TYPENAME_EGlpNumCopyDiff (alpha1, x_bi, v_l);
+		EGLPNUM_TYPENAME_EGlpNumSubTo (alpha1, lp->upd.dty);
+		EGLPNUM_TYPENAME_EGlpNumDivTo (alpha1, rs.pivotval);
+		EGLPNUM_TYPENAME_ILLfct_update_basis_info (lp, rs.eindex, pr.lindex, pr.lvstat);
+		rval = EGLPNUM_TYPENAME_ILLbasis_update (lp, updz, pr.lindex, &refactor, &singular);
+		CHECKRVALG (rval, CLEANUP);
+
+		EGLPNUM_TYPENAME_ILLfct_update_dpII_prices (lp, pinf, &(lp->srhs), &(lp->ssoln), /*rs.eindex,*/
+															 pr.lindex, eval, alpha1);
+
+#if DENSE_NORM > 0
+		EGLPNUM_TYPENAME_test_dsteep_norms (lp, pinf);
+#endif
+
+	END:
+		if (singular)
+		{
+			it->nextstep = SIMPLEX_RESUME;
+			it->resumeid = SIMPLEX_RESUME_SING;
+			/* this is to force to exit in the case of bad basis */
+			it->n_restart++;
+			EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->pfeas_tol, SIMPLEX_FACTOR);
+			EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->dfeas_tol, SIMPLEX_FACTOR);
+			//QSlog("Resume Singular %s:%s:%d",__func__,__FILE__,__LINE__);
+			ILL_CLEANUP;
+		}
+		if (refactor != 0 || it->nosolve > PARAM_MAX_NOSOLVE)
+		{
+			EGLPNUM_TYPENAME_ILLfct_compute_piz (lp);
+			EGLPNUM_TYPENAME_ILLfct_compute_dz (lp);
+			EGLPNUM_TYPENAME_ILLfct_dual_adjust (lp, EGLPNUM_TYPENAME_zeroLpNum);
+			it->newphase = SIMPLEX_PHASE_RECOMP;
+		}
+	}
+
+#if DENSE_PIIPI > 0
+	EGLPNUM_TYPENAME_fct_test_workvector (lp);
+	if (!refactor)
+	{
+		EGLPNUM_TYPENAME_fct_test_pII_x (lp, pinf);
+		EGLPNUM_TYPENAME_fct_test_pII_pi_dz (lp, pinf);
+	}
+#endif
+
+CLEANUP:
+	EGLPNUM_TYPENAME_EGlpNumClearVar (x_bi);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (v_l);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (eval);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (ecoeff);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (alpha);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (alpha1);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (fi.totinfeas);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (pr.dinfeas);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (pr.pinfeas);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (rs.tz);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (rs.lbound);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (rs.ecoeff);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (rs.pivotval);
+	//EG_RETURN(rval);
+	return rval;
+}
+
+static void get_current_stat (
+	EGLPNUM_TYPENAME_lp_status_info * p,
+	int algorithm,
+	int *bstat)
+{
+	if (p->optimal)
+		*bstat = OPTIMAL;
+	else if (algorithm == PRIMAL_SIMPLEX)
+	{
+		if (p->primal_feasible)
+			*bstat = PRIMAL_FEASIBLE;
+		else if (p->primal_infeasible)
+			*bstat = PRIMAL_INFEASIBLE;
+		else if (p->primal_unbounded)
+			*bstat = PRIMAL_UNBOUNDED;
+		else
+			*bstat = NONOPTIMAL;
+	}
+	else if (algorithm == DUAL_SIMPLEX)
+	{
+		if (p->dual_feasible)
+			*bstat = DUAL_FEASIBLE;
+		else if (p->dual_infeasible)
+			*bstat = DUAL_INFEASIBLE;
+		else if (p->dual_unbounded)
+			*bstat = DUAL_UNBOUNDED;
+		else
+			*bstat = NONOPTIMAL;
+	}
+}
+
+int EGLPNUM_TYPENAME_ILLsimplex_pivotin (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_price_info * pinf,
+	int rcnt,
+	int *rlist,
+	int pivot_opt,
+	int *basis_mod)
+{
+	int i, npiv = 0;
+	int eindex;
+	int rval = 0;
+	int singular = 0;
+	int refactor = 0;
+	int *rowmap = lp->O->rowmap;
+	int *clist = NULL;
+	EGLPNUM_TYPENAME_svector wz;
+	EGLPNUM_TYPENAME_svector updz;
+	EGLPNUM_TYPE alpha;
+	EGLPNUM_TYPENAME_ratio_res rs;
+	EGLPNUM_TYPENAME_feas_info fi;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (alpha);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (fi.totinfeas);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (rs.tz);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (rs.lbound);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (rs.ecoeff);
+	EGLPNUM_TYPENAME_EGlpNumInitVar (rs.pivotval);
+	EGLPNUM_TYPENAME_EGlpNumZero (alpha);
+
+	*basis_mod = 0;
+	if (rcnt <= 0)
+	{
+		EG_RETURN (rval);
+	}
+
+	if (pivot_opt == SIMPLEX_PIVOTINROW)
+	{
+		ILL_SAFE_MALLOC (clist, rcnt, int);
+
+		for (i = 0; i < rcnt; i++)
+			clist[i] = rowmap[rlist[i]];
+	}
+	else
+		clist = rlist;
+
+	for (i = 0; i < rcnt; i++)
+	{
+		if (lp->vstat[clist[i]] != STAT_BASIC)
+		{
+			*basis_mod = 1;
+			break;
+		}
+	}
+	if (*basis_mod == 0)
+	{
+		if (pivot_opt == SIMPLEX_PIVOTINROW)
+		{
+			ILL_IFFREE (clist, int);
+		}
+		EG_RETURN (rval);
+	}
+
+	/* QSlog("Forcing vars into basis in EGLPNUM_TYPENAME_ILLsimplex_pivotin"); */
+	EGLPNUM_TYPENAME_ILLsvector_init (&wz);
+	rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&wz, lp->nrows);
+	CHECKRVALG (rval, CLEANUP);
+	EGLPNUM_TYPENAME_ILLsvector_init (&updz);
+	rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&updz, lp->nrows);
+	CHECKRVALG (rval, CLEANUP);
+
+	EGLPNUM_TYPENAME_EGlpNumCopy (lp->pobjval, lp->dobjval);
+	for (i = 0; i < rcnt; i++)
+	{
+		if (lp->vstat[clist[i]] == STAT_BASIC)
+			continue;
+		npiv++;
+
+		eindex = lp->vindex[clist[i]];
+		EGLPNUM_TYPENAME_ILLfct_compute_yz (lp, &(lp->yjz), &updz, lp->nbaz[eindex]);
+		EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_YNZ, lp->yjz.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+		EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_UPNZ, updz.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+
+		EGLPNUM_TYPENAME_ILLratio_pivotin_test (lp, clist, rcnt, &rs);
+
+		if (rs.ratio_stat == RATIO_UNBOUNDED || rs.ratio_stat == RATIO_FAILED)
+		{
+			QSlog("Pivot_in failed");
+			rval = E_SIMPLEX_ERROR;
+			ILL_CLEANUP;
+		}
+		else if (rs.ratio_stat == RATIO_BCHANGE)
+		{
+			if (rs.lvstat == STAT_LOWER)
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopyDiff (alpha, lp->lz[lp->baz[rs.lindex]], lp->xbz[rs.lindex]);
+				EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (lp->dobjval, rs.tz, alpha);
+			}
+			else
+			{
+				EGLPNUM_TYPENAME_EGlpNumCopyDiff (alpha, lp->xbz[rs.lindex], lp->uz[lp->baz[rs.lindex]]);
+				EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (lp->dobjval, rs.tz, alpha);
+			}
+			EGLPNUM_TYPENAME_EGlpNumCopyFrac (alpha, lp->dz[eindex], rs.pivotval);
+			EGLPNUM_TYPENAME_EGlpNumCopy (lp->objval, lp->dobjval);
+
+			EGLPNUM_TYPENAME_ILLfct_compute_zz (lp, &(lp->zz), rs.lindex);
+			//ILL_IFTRACE("%s:e\n",__func__);
+			EGLPNUM_TYPENAME_ILLfct_compute_zA (lp, &(lp->zz), &(lp->zA));
+			EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_ZNZ, lp->zz.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+			EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_ZANZ, lp->zA.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+
+			if (pinf->dsinfo.norms && pinf->dII_price == QS_PRICE_DSTEEP)
+			{
+				EGLPNUM_TYPENAME_ILLfct_compute_dsteep_upv (lp, &wz);
+				rval = EGLPNUM_TYPENAME_ILLprice_update_pricing_info (lp, pinf, DUAL_PHASEII, &wz,
+																						 eindex, rs.lindex, rs.pivotval);
+				CHECKRVALG (rval, CLEANUP);
+			}
+			else if (pinf->psinfo.norms && pinf->pII_price == QS_PRICE_PSTEEP)
+			{
+				EGLPNUM_TYPENAME_ILLfct_compute_psteep_upv (lp, &wz);
+				rval = EGLPNUM_TYPENAME_ILLprice_update_pricing_info (lp, pinf, PRIMAL_PHASEII, &wz,
+																						 eindex, rs.lindex, rs.pivotval);
+				CHECKRVALG (rval, CLEANUP);
+			}
+
+			//ILL_IFTRACE("%s:e\n",__func__);
+			EGLPNUM_TYPENAME_ILLfct_update_xz (lp, rs.tz, eindex, rs.lindex);
+			EGLPNUM_TYPENAME_ILLfct_update_basis_info (lp, eindex, rs.lindex, rs.lvstat);
+			rval = EGLPNUM_TYPENAME_ILLbasis_update (lp, &updz, rs.lindex, &refactor, &singular);
+			CHECKRVALG (rval, CLEANUP);
+
+			if (singular)
+			{
+				QSlog("singular matrix in pivot_in");
+				rval = E_SIMPLEX_ERROR;
+				ILL_CLEANUP;
+			}
+			if (!refactor)
+			{
+				EGLPNUM_TYPENAME_ILLfct_update_piz (lp, alpha);
+				EGLPNUM_TYPENAME_ILLfct_update_dz (lp, eindex, alpha);
+			}
+			else
+			{
+				EGLPNUM_TYPENAME_ILLfct_compute_xbz (lp);
+				EGLPNUM_TYPENAME_ILLfct_compute_piz (lp);
+				EGLPNUM_TYPENAME_ILLfct_compute_dz (lp);
+				EGLPNUM_TYPENAME_ILLfct_compute_dobj (lp);
+			}
+		}
+	}
+	/*
+	 * EGLPNUM_TYPENAME_ILLfct_dphaseI_simple_update (lp, lp->tol->dfeas_tol);
+	 * EGLPNUM_TYPENAME_ILLfct_compute_xbz (lp);
+	 * EGLPNUM_TYPENAME_ILLfct_compute_dobj (lp);
+	 */
+
+	EGLPNUM_TYPENAME_ILLfct_check_pfeasible (lp, &fi, lp->tol->pfeas_tol);
+	EGLPNUM_TYPENAME_ILLfct_check_dfeasible (lp, &fi, lp->tol->dfeas_tol);
+	EGLPNUM_TYPENAME_ILLfct_set_status_values (lp, fi.pstatus, fi.dstatus, PHASEII, PHASEII);
+
+CLEANUP:
+	if (pivot_opt == SIMPLEX_PIVOTINROW)
+		ILL_IFFREE (clist, int);
+
+	EGLPNUM_TYPENAME_ILLsvector_free (&wz);
+	EGLPNUM_TYPENAME_ILLsvector_free (&updz);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (alpha);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (fi.totinfeas);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (rs.tz);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (rs.lbound);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (rs.ecoeff);
+	EGLPNUM_TYPENAME_EGlpNumClearVar (rs.pivotval);
+	EG_RETURN (rval);
+}
+
+static int report_value (
+	EGLPNUM_TYPENAME_lpinfo * lp,
+	EGLPNUM_TYPENAME_iter_info * it,
+	const char *value_name,
+	EGLPNUM_TYPE value)
+{
+	int rval = 0;
+
+	if (it->sdisplay && it->itercnt % lp->iterskip == 0)
+	{
+		char buffer[1024];
+
+		snprintf (buffer, (size_t) 1023, "(%d): %s = %10.7lf", it->itercnt,
+							value_name, EGLPNUM_TYPENAME_EGlpNumToLf (value));
+		rval = ILLstring_report (buffer, &lp->O->reporter);
+	}
+	else
+	{
+		/* make sure ILLstring_report is called at least every 10 iterations */
+		if (it->itercnt % (lp->iterskip / 10))
+		{
+			rval = ILLstring_report (NULL, &lp->O->reporter);
+		}
+	}
+	if (rval != 0)
+	{															/* ILLstring_report was called and failed, which means we should abort */
+		it->solstatus = QS_LP_ABORTED;
+	}
+	return rval;
+}
+
+#undef QSOPT_CURRENT_PRECICION
diff --git a/qsopt_ex/simplex.h b/qsopt_ex/simplex.h
new file mode 100644
index 0000000..2a42bf7
--- /dev/null
+++ b/qsopt_ex/simplex.h
@@ -0,0 +1,89 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* $RCSfile: simplex_EGLPNUM_TYPENAME.h,v $ $Revision: 1.3 $ $Date: 2003/11/05 16:57:39 $ */
+
+#ifndef EGLPNUM_TYPENAME___SIMPLEX_H
+#define EGLPNUM_TYPENAME___SIMPLEX_H
+
+struct itcnt_t;
+
+#include "lpdata_EGLPNUM_TYPENAME.h"
+#include "basicdefs.h"
+
+typedef struct EGLPNUM_TYPENAME_param_info
+{
+	int origalgo;
+	int pphaseI;
+	int pphaseII;
+	int dphaseI;
+	int dphaseII;
+	int p_strategy;
+	int d_strategy;
+}
+EGLPNUM_TYPENAME_param_info;
+
+typedef struct EGLPNUM_TYPENAME_iter_info
+{
+	int newphase;
+	int nextphase;
+	int nextstep;
+	int sdisplay;
+	int itercnt;
+	int solstatus;
+	int curtime;
+	int rounds;
+	int chkobj;
+	int nosolve;
+	int noprog;
+	int inner;
+	int algorithm;
+	int resumeid;
+	int pricetype;
+	int n_restart;
+	int n_pivot_fail;
+	EGLPNUM_TYPE prevobj;
+	EGLPNUM_TYPE objtol;
+	EGLPNUM_TYPENAME_param_info oldinfo;
+}
+EGLPNUM_TYPENAME_iter_info;
+
+void EGLPNUM_TYPENAME_ILLsimplex_init_lpinfo ( EGLPNUM_TYPENAME_lpinfo * lp),
+		EGLPNUM_TYPENAME_ILLsimplex_free_lpinfo ( EGLPNUM_TYPENAME_lpinfo * lp),
+		EGLPNUM_TYPENAME_ILLsimplex_load_lpinfo ( EGLPNUM_TYPENAME_ILLlpdata * qslp, EGLPNUM_TYPENAME_lpinfo * lp),
+		EGLPNUM_TYPENAME_ILLsimplex_set_bound ( EGLPNUM_TYPENAME_lpinfo * lp, const EGLPNUM_TYPE * objbound, int sense);
+void EGLPNUM_TYPENAME_free_internal_lpinfo ( EGLPNUM_TYPENAME_lpinfo * lp);
+void EGLPNUM_TYPENAME_init_internal_lpinfo ( EGLPNUM_TYPENAME_lpinfo * lp);
+int EGLPNUM_TYPENAME_build_internal_lpinfo ( EGLPNUM_TYPENAME_lpinfo * lp);
+int EGLPNUM_TYPENAME_ILLsimplex_retest_psolution ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_price_info * p, int phase,
+			EGLPNUM_TYPENAME_feas_info * fs),
+		EGLPNUM_TYPENAME_ILLsimplex_retest_dsolution ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_price_info * p, int phase,
+			EGLPNUM_TYPENAME_feas_info * fs),
+		EGLPNUM_TYPENAME_ILLsimplex_solution ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPE * xz, EGLPNUM_TYPE * piz,
+			EGLPNUM_TYPE * dz, EGLPNUM_TYPE * objval),
+		EGLPNUM_TYPENAME_ILLsimplex_infcertificate ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPE * pi),
+		EGLPNUM_TYPENAME_ILLsimplex ( EGLPNUM_TYPENAME_lpinfo * lp, int algorithm, EGLPNUM_TYPENAME_ILLlp_basis * B, 
+			EGLPNUM_TYPENAME_price_info * pinf, int *sol_status, int sdisplay, itcnt_t* itcnt),
+		EGLPNUM_TYPENAME_ILLsimplex_pivotin ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_price_info * pinf, int rcnt, 
+			int *rlist, int pivot_opt, int *basis_mod);
+
+#endif /* EGLPNUM_TYPENAME___SIMPLEX_H */
diff --git a/qsopt_ex/sortrus.c b/qsopt_ex/sortrus.c
new file mode 100644
index 0000000..b68e397
--- /dev/null
+++ b/qsopt_ex/sortrus.c
@@ -0,0 +1,289 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCSINFO $Id: sortrus.c,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of CONCORDE                                           */
+/*                                                                          */
+/*  (c) Copyright 1995--1999 by David Applegate, Robert Bixby,              */
+/*  Vasek Chvatal, and William Cook                                         */
+/*                                                                          */
+/*  Permission is granted for academic research use.  For other uses,       */
+/*  contact the authors for licensing options.                              */
+/*                                                                          */
+/*  Use at your own risk.  We make no guarantees about the                  */
+/*  correctness or usefulness of this code.                                 */
+/*                                                                          */
+/****************************************************************************/
+
+/****************************************************************************/
+/*                                                                          */
+/*                         SORTING ROUTINES                                 */
+/*                                                                          */
+/*                             TSP CODE                                     */
+/*                                                                          */
+/*   Written by:  Applegate, Bixby, Chvatal, and Cook                       */
+/*   DATE:  February 24, 1994                                               */
+/*                                                                          */
+/*    EXPORTED FUNCTIONS:                                                   */
+/*                                                                          */
+/*  char *ILLutil_linked_radixsort (char *data, char *datanext,              */
+/*      char *dataval, int valsize)                                         */
+/*    USAGE:                                                                */
+/*      head = (bar *) ILLutil_linked_radixsort ((char *) head,              */
+/*         (char *) &(head->next), (char *) &(head->val), sizeof (int));    */
+/*    Then head is the start of the linked list in increasing order of      */
+/*    val, with next as the field that links the bars.                      */
+/*    WARNING: DOES NOT HANDLE NEGATIVE NUMBERS PROPERLY.                   */
+/*                                                                          */
+/*  void ILLutil_int_array_quicksort (int *len, int n)                       */
+/*    len - the array to be sorted                                          */
+/*    n - the number of elements in len                                     */
+/*    Uses quicksort to put len in increasing order.                        */
+/*                                                                          */
+/*  void ILLutil_int_perm_quicksort (int *perm, int *len, int n)             */
+/*    perm - must be allocated and initialized by the calling routine,      */
+/*           it will be arranged in increasing order of len.                */
+/*    n - the number of elements in perm and len.                           */
+/*                                                                          */
+/*  void ILLutil_double_perm_quicksort (int *perm, double *len, int n)       */
+/*    perm - must be allocated and initialized by the calling routine,      */
+/*           it will be arranged in increasing order of len.                */
+/*    n - the number of elements in perm and len.                           */
+/*                                                                          */
+/*  void ILLutil_rselect (int *arr, int l, int r, int m,                     */
+/*      double *coord, ILLrandstate *rstate)                                 */
+/*    arr - permutation that will be rearranged                             */
+/*    l,r - specify the range of arr that we are interested in              */
+/*    m - is the index into l,r that is the break point for the perm        */
+/*    coord - gives the keys that determine the ordering                    */
+/*                                                                          */
+/****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "eg_lpnum.h"
+
+#include "util.h"
+#include "except.h"
+
+
+#define BITS_PER_PASS (8)
+
+#define NBINS (1<<BITS_PER_PASS)
+
+
+static void select_EGlpNum_split (
+	int *arr,
+	int n,
+	EGLPNUM_TYPE * v,
+	int *start,
+	int *end,
+	EGLPNUM_TYPE * coord),
+  select_EGlpNum_sort (
+	int *arr,
+	int n,
+	EGLPNUM_TYPE * coord),
+  select_EGlpNum_sort_dsample (
+	EGLPNUM_TYPE * samp,
+	int n);
+
+void EGLPNUM_TYPENAME_ILLutil_EGlpNum_perm_quicksort (
+	int *perm,
+	EGLPNUM_TYPE * len,
+	int n)
+{
+	int i, j, temp;
+	EGLPNUM_TYPE t;
+
+	if (n <= 1)
+		return;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (t);
+	ILL_SWAP (perm[0], perm[(n - 1) / 2], temp);
+
+	i = 0;
+	j = n;
+	EGLPNUM_TYPENAME_EGlpNumCopy (t, len[perm[0]]);
+
+	for (;;)
+	{
+		do
+			i++;
+		while (i < n && EGLPNUM_TYPENAME_EGlpNumIsLess (len[perm[i]], t));
+		do
+			j--;
+		while (EGLPNUM_TYPENAME_EGlpNumIsLess (t, len[perm[j]]));
+		if (j < i)
+			break;
+		ILL_SWAP (perm[i], perm[j], temp);
+	}
+	ILL_SWAP (perm[0], perm[j], temp);
+
+	EGLPNUM_TYPENAME_EGlpNumClearVar (t);
+	EGLPNUM_TYPENAME_ILLutil_EGlpNum_perm_quicksort (perm, len, j);
+	EGLPNUM_TYPENAME_ILLutil_EGlpNum_perm_quicksort (perm + i, len, n - i);
+}
+
+/**********  Median - Select Routines **********/
+
+/* NSAMPLES should be odd */
+#define NSAMPLES 3
+#define SORTSIZE 20
+
+
+void EGLPNUM_TYPENAME_ILLutil_EGlpNum_rselect (
+	int *arr,
+	int l,
+	int r,
+	int m,
+	EGLPNUM_TYPE * coord,
+	ILLrandstate * rstate)
+{
+	EGLPNUM_TYPE *samplevals = EGLPNUM_TYPENAME_EGlpNumAllocArray (NSAMPLES);
+	int i;
+	int st, en;
+	int n;
+
+	arr += l;
+	n = r - l + 1;
+	m -= l;
+
+	while (n > SORTSIZE)
+	{
+		for (i = 0; i < NSAMPLES; i++)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (samplevals[i], coord[arr[ILLutil_lprand (rstate) % n]]);
+		}
+		select_EGlpNum_sort_dsample (samplevals, NSAMPLES);
+		select_EGlpNum_split (arr, n, &(samplevals[(NSAMPLES - 1) / 2]),
+													&st, &en, coord);
+		if (st > m)
+		{
+			n = st;
+		}
+		else if (en <= m)
+		{
+			arr += en;
+			n -= en;
+			m -= en;
+		}
+		else
+		{
+			return;
+		}
+	}
+
+	select_EGlpNum_sort (arr, n, coord);
+	EGLPNUM_TYPENAME_EGlpNumFreeArray (samplevals);
+	return;
+}
+
+static void select_EGlpNum_split (
+	int *arr,
+	int n,
+	EGLPNUM_TYPE * v,
+	int *start,
+	int *end,
+	EGLPNUM_TYPE * coord)
+{
+	int i, j, k;
+	int t;
+
+	i = 0;
+	j = k = n;
+
+	while (i < j)
+	{
+		if (EGLPNUM_TYPENAME_EGlpNumIsLess (coord[arr[i]], *v))
+		{
+			i++;
+		}
+		else if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (coord[arr[i]], *v))
+		{
+			j--;
+			ILL_SWAP (arr[i], arr[j], t);
+		}
+		else
+		{
+			j--;
+			k--;
+			t = arr[i];
+			arr[i] = arr[j];
+			arr[j] = arr[k];
+			arr[k] = t;
+		}
+	}
+	*start = j;
+	*end = k;
+	return;
+}
+
+static void select_EGlpNum_sort (
+	int *arr,
+	int n,
+	EGLPNUM_TYPE * coord)
+{
+	int i, j;
+	int t;
+
+	for (i = 1; i < n; i++)
+	{
+		t = arr[i];
+		for (j = i; j > 0 && EGLPNUM_TYPENAME_EGlpNumIsLess (coord[t], coord[arr[j - 1]]); j--)
+		{
+			arr[j] = arr[j - 1];
+		}
+		arr[j] = t;
+	}
+}
+
+static void select_EGlpNum_sort_dsample (
+	EGLPNUM_TYPE * samp,
+	int n)
+{
+	int i, j;
+	EGLPNUM_TYPE t;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (t);
+
+	for (i = 1; i < n; i++)
+	{
+		EGLPNUM_TYPENAME_EGlpNumCopy (t, samp[i]);
+		for (j = i; j > 0 && EGLPNUM_TYPENAME_EGlpNumIsLess (t, samp[j - 1]); j--)
+		{
+			EGLPNUM_TYPENAME_EGlpNumCopy (samp[j], samp[j - 1]);
+		}
+		EGLPNUM_TYPENAME_EGlpNumCopy (samp[j], t);
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (t);
+}
+
+
+
+
diff --git a/qsopt_ex/sortrus.h b/qsopt_ex/sortrus.h
new file mode 100644
index 0000000..a32b822
--- /dev/null
+++ b/qsopt_ex/sortrus.h
@@ -0,0 +1,44 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+#ifndef EGLPNUM_TYPENAME___SORTRUS_H__
+#define EGLPNUM_TYPENAME___SORTRUS_H__
+/****************************************************************************/
+/*                                                                          */
+/*                             sortrus.c                                    */
+/*                                                                          */
+/****************************************************************************/
+
+#include "urandom.h"
+
+void EGLPNUM_TYPENAME_ILLutil_EGlpNum_perm_quicksort (
+	int *perm,
+	EGLPNUM_TYPE * len,
+	int n),
+  EGLPNUM_TYPENAME_ILLutil_EGlpNum_rselect (
+	int *arr,
+	int l,
+	int r,
+	int m,
+	EGLPNUM_TYPE * coord,
+	ILLrandstate * rstate);
+#endif
diff --git a/qsopt_ex/sortrus_common.c b/qsopt_ex/sortrus_common.c
new file mode 100644
index 0000000..21b3793
--- /dev/null
+++ b/qsopt_ex/sortrus_common.c
@@ -0,0 +1,426 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCSINFO $Id: sortrus.c,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of CONCORDE                                           */
+/*                                                                          */
+/*  (c) Copyright 1995--1999 by David Applegate, Robert Bixby,              */
+/*  Vasek Chvatal, and William Cook                                         */
+/*                                                                          */
+/*  Permission is granted for academic research use.  For other uses,       */
+/*  contact the authors for licensing options.                              */
+/*                                                                          */
+/*  Use at your own risk.  We make no guarantees about the                  */
+/*  correctness or usefulness of this code.                                 */
+/*                                                                          */
+/****************************************************************************/
+
+/****************************************************************************/
+/*                                                                          */
+/*                         SORTING ROUTINES                                 */
+/*                                                                          */
+/*                             TSP CODE                                     */
+/*                                                                          */
+/*   Written by:  Applegate, Bixby, Chvatal, and Cook                       */
+/*   DATE:  February 24, 1994                                               */
+/*                                                                          */
+/*    EXPORTED FUNCTIONS:                                                   */
+/*                                                                          */
+/*  char *ILLutil_linked_radixsort (char *data, char *datanext,              */
+/*      char *dataval, int valsize)                                         */
+/*    USAGE:                                                                */
+/*      head = (bar *) ILLutil_linked_radixsort ((char *) head,              */
+/*         (char *) &(head->next), (char *) &(head->val), sizeof (int));    */
+/*    Then head is the start of the linked list in increasing order of      */
+/*    val, with next as the field that links the bars.                      */
+/*    WARNING: DOES NOT HANDLE NEGATIVE NUMBERS PROPERLY.                   */
+/*                                                                          */
+/*  void ILLutil_int_array_quicksort (int *len, int n)                       */
+/*    len - the array to be sorted                                          */
+/*    n - the number of elements in len                                     */
+/*    Uses quicksort to put len in increasing order.                        */
+/*                                                                          */
+/*  void ILLutil_int_perm_quicksort (int *perm, int *len, int n)             */
+/*    perm - must be allocated and initialized by the calling routine,      */
+/*           it will be arranged in increasing order of len.                */
+/*    n - the number of elements in perm and len.                           */
+/*                                                                          */
+/*  void ILLutil_double_perm_quicksort (int *perm, double *len, int n)       */
+/*    perm - must be allocated and initialized by the calling routine,      */
+/*           it will be arranged in increasing order of len.                */
+/*    n - the number of elements in perm and len.                           */
+/*                                                                          */
+/*  void ILLutil_rselect (int *arr, int l, int r, int m,                     */
+/*      double *coord, ILLrandstate *rstate)                                 */
+/*    arr - permutation that will be rearranged                             */
+/*    l,r - specify the range of arr that we are interested in              */
+/*    m - is the index into l,r that is the break point for the perm        */
+/*    coord - gives the keys that determine the ordering                    */
+/*                                                                          */
+/****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "qs_config.h"
+#include "util.h"
+#include "except.h"
+
+
+#define BITS_PER_PASS (8)
+
+#define NBINS (1<<BITS_PER_PASS)
+
+
+static void select_split (
+	int *arr,
+	int n,
+	double v,
+	int *start,
+	int *end,
+	double *coord),
+  select_sort (
+	int *arr,
+	int n,
+	double *coord),
+  select_sort_dsample (
+	double *samp,
+	int n);
+
+
+
+char *ILLutil_linked_radixsort (
+	char *data,
+	char *datanext,
+	char *dataval,
+	int valsize)
+{
+	size_t nextoff = datanext - data;
+	size_t valoff = dataval - data;
+	int i;
+	char *head[NBINS];
+	char **tail[NBINS];
+	char *p;
+	char **last;
+	int j;
+	int v;
+
+
+	for (j = valsize - 1; j >= 0; j--)
+	{
+		for (i = 0; i < NBINS; i++)
+		{
+			head[i] = (char *) NULL;
+			tail[i] = &head[i];
+		}
+		for (p = data; p; p = *(char **) (p + nextoff))
+		{
+			v = (unsigned char) p[valoff + j];
+			*tail[v] = p;
+			tail[v] = (char **) (p + nextoff);
+		}
+		last = &data;
+		for (i = 0; i < NBINS; i++)
+		{
+			if (head[i])
+			{
+				*last = head[i];
+				last = tail[i];
+			}
+		}
+		*last = (char *) NULL;
+	}
+	return data;
+}
+
+void ILLutil_int_array_quicksort (
+	int *len,
+	int n)
+{
+	int i, j, temp, t;
+
+	if (n <= 1)
+		return;
+
+	ILL_SWAP (len[0], len[(n - 1) / 2], temp);
+
+	i = 0;
+	j = n;
+	t = len[0];
+
+	for (;;)
+	{
+		do
+			i++;
+		while (i < n && len[i] < t);
+		do
+			j--;
+		while (len[j] > t);
+		if (j < i)
+			break;
+		ILL_SWAP (len[i], len[j], temp);
+	}
+	ILL_SWAP (len[0], len[j], temp);
+
+	ILLutil_int_array_quicksort (len, j);
+	ILLutil_int_array_quicksort (len + i, n - i);
+}
+
+void ILLutil_int_perm_quicksort (
+	int *perm,
+	int *len,
+	int n)
+{
+	int i, j, temp, t;
+
+	if (n <= 1)
+		return;
+
+	ILL_SWAP (perm[0], perm[(n - 1) / 2], temp);
+
+	i = 0;
+	j = n;
+	t = len[perm[0]];
+
+	for (;;)
+	{
+		do
+			i++;
+		while (i < n && len[perm[i]] < t);
+		do
+			j--;
+		while (len[perm[j]] > t);
+		if (j < i)
+			break;
+		ILL_SWAP (perm[i], perm[j], temp);
+	}
+	ILL_SWAP (perm[0], perm[j], temp);
+
+	ILLutil_int_perm_quicksort (perm, len, j);
+	ILLutil_int_perm_quicksort (perm + i, len, n - i);
+}
+
+
+void ILLutil_double_perm_quicksort (
+	int *perm,
+	double *len,
+	int n)
+{
+	int i, j, temp;
+	double t;
+
+	if (n <= 1)
+		return;
+
+	ILL_SWAP (perm[0], perm[(n - 1) / 2], temp);
+
+	i = 0;
+	j = n;
+	t = len[perm[0]];
+
+	for (;;)
+	{
+		do
+			i++;
+		while (i < n && len[perm[i]] < t);
+		do
+			j--;
+		while (t < len[perm[j]]);
+		if (j < i)
+			break;
+		ILL_SWAP (perm[i], perm[j], temp);
+	}
+	ILL_SWAP (perm[0], perm[j], temp);
+
+	ILLutil_double_perm_quicksort (perm, len, j);
+	ILLutil_double_perm_quicksort (perm + i, len, n - i);
+}
+
+void ILLutil_str_perm_quicksort (
+	int *perm,
+	char **len,
+	int n)
+{
+	int i, j, temp;
+	char *t;
+
+	if (n <= 1)
+		return;
+
+	ILL_SWAP (perm[0], perm[(n - 1) / 2], temp);
+
+	i = 0;
+	j = n;
+	t = len[perm[0]];
+
+	for (;;)
+	{
+		do
+			i++;
+		while (i < n && (strcmp (len[perm[i]], t) < 0));
+		do
+			j--;
+		while (strcmp (len[perm[j]], t) > 0);
+		if (j < i)
+			break;
+		ILL_SWAP (perm[i], perm[j], temp);
+	}
+	ILL_SWAP (perm[0], perm[j], temp);
+
+	ILLutil_str_perm_quicksort (perm, len, j);
+	ILLutil_str_perm_quicksort (perm + i, len, n - i);
+}
+
+
+/**********  Median - Select Routines **********/
+
+/* NSAMPLES should be odd */
+#define NSAMPLES 3
+#define SORTSIZE 20
+
+void ILLutil_rselect (
+	int *arr,
+	int l,
+	int r,
+	int m,
+	double *coord,
+	ILLrandstate * rstate)
+{
+	double samplevals[NSAMPLES];
+	int i;
+	int st, en;
+	int n;
+
+	arr += l;
+	n = r - l + 1;
+	m -= l;
+
+	while (n > SORTSIZE)
+	{
+		for (i = 0; i < NSAMPLES; i++)
+		{
+			samplevals[i] = coord[arr[ILLutil_lprand (rstate) % n]];
+		}
+		select_sort_dsample (samplevals, NSAMPLES);
+		select_split (arr, n, samplevals[(NSAMPLES - 1) / 2], &st, &en, coord);
+		if (st > m)
+		{
+			n = st;
+		}
+		else if (en <= m)
+		{
+			arr += en;
+			n -= en;
+			m -= en;
+		}
+		else
+		{
+			return;
+		}
+	}
+
+	select_sort (arr, n, coord);
+	return;
+}
+
+static void select_split (
+	int *arr,
+	int n,
+	double v,
+	int *start,
+	int *end,
+	double *coord)
+{
+	int i, j, k;
+	int t;
+
+	i = 0;
+	j = k = n;
+
+	while (i < j)
+	{
+		if (coord[arr[i]] < v)
+		{
+			i++;
+		}
+		else if (coord[arr[i]] == v)
+		{
+			j--;
+			ILL_SWAP (arr[i], arr[j], t);
+		}
+		else
+		{
+			j--;
+			k--;
+			t = arr[i];
+			arr[i] = arr[j];
+			arr[j] = arr[k];
+			arr[k] = t;
+		}
+	}
+	*start = j;
+	*end = k;
+	return;
+}
+
+static void select_sort (
+	int *arr,
+	int n,
+	double *coord)
+{
+	int i, j;
+	int t;
+
+	for (i = 1; i < n; i++)
+	{
+		t = arr[i];
+		for (j = i; j > 0 && coord[arr[j - 1]] > coord[t]; j--)
+		{
+			arr[j] = arr[j - 1];
+		}
+		arr[j] = t;
+	}
+}
+
+static void select_sort_dsample (
+	double *samp,
+	int n)
+{
+	int i, j;
+	double t;
+
+	for (i = 1; i < n; i++)
+	{
+		t = samp[i];
+		for (j = i; j > 0 && samp[j - 1] > t; j--)
+		{
+			samp[j] = samp[j - 1];
+		}
+		samp[j] = t;
+	}
+}
diff --git a/qsopt_ex/sortrus_common.h b/qsopt_ex/sortrus_common.h
new file mode 100644
index 0000000..c95943f
--- /dev/null
+++ b/qsopt_ex/sortrus_common.h
@@ -0,0 +1,63 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+#ifndef __SORTRUS_H__
+#define __SORTRUS_H__
+/****************************************************************************/
+/*                                                                          */
+/*                             sortrus.c                                    */
+/*                                                                          */
+/****************************************************************************/
+
+#include "urandom.h"
+
+void ILLutil_int_array_quicksort (
+	int *len,
+	int n),
+  ILLutil_int_perm_quicksort (
+	int *perm,
+	int *len,
+	int n),
+  ILLutil_double_perm_quicksort (
+	int *perm,
+	double *len,
+	int n),
+	ILLutil_str_perm_quicksort (
+	int *perm,
+	char **len,
+	int n),
+  ILLutil_rselect (
+	int *arr,
+	int l,
+	int r,
+	int m,
+	double *coord,
+	ILLrandstate * rstate);
+
+char *ILLutil_linked_radixsort (
+	char *data,
+	char *datanext,
+	char *dataval,
+	int valsize);
+
+
+#endif
diff --git a/qsopt_ex/stddefs.h b/qsopt_ex/stddefs.h
new file mode 100644
index 0000000..0200c55
--- /dev/null
+++ b/qsopt_ex/stddefs.h
@@ -0,0 +1,34 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* $RCSfile: stddefs.h,v $ $Revision: 1.3 $ $Date: 2003/11/05 16:57:39 $ */
+#ifndef ILL_STDDEFS_H
+#define ILL_STDDEFS_H
+
+#define SWAP(x,y,temp) {temp = x; x = y; y = temp;}
+
+#define QSMIN(x,y) ((x) < (y) ? (x) : (y))
+#define QSMAX(x,y) ((x) > (y) ? (x) : (y))
+
+#define ABS(x) ((x) >= 0 ? (x) : -(x))
+
+#endif /* ILL_STDDEFS_H */
diff --git a/qsopt_ex/symtab.c b/qsopt_ex/symtab.c
new file mode 100644
index 0000000..0a0eab9
--- /dev/null
+++ b/qsopt_ex/symtab.c
@@ -0,0 +1,969 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCSINFO $Id: symboltab.c,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "eg_mem.h"
+
+#include "logging-private.h"
+
+#include "util.h"
+#include "trace.h"
+#include "except.h"
+#include "symtab.h"
+
+
+static int TRACE = 0;
+
+static unsigned int stringhash (
+	const char *key,
+	int tsize);
+static int look_it_up (
+	ILLsymboltab * h,
+	const char *s);
+static int grow_symboltab (
+	ILLsymboltab * h);
+static int grow_namelist (
+	ILLsymboltab * h);
+static int add_string (
+	ILLsymboltab * h,
+	const char *s,
+	int *symbol);
+static void delete_from_list (
+	ILLsymboltab * h,
+	int del_ind,
+	int prev_ind,
+	int x);
+
+#ifdef TRY_CODE
+/* debug support */
+static const char *get_str (
+	const ILLsymboltab * h,
+	int indx);
+static void prt_xchain (
+	const ILLsymboltab * h,
+	int x);
+static void prt_chain (
+	const ILLsymboltab * h,
+	char *s);
+#endif
+
+
+void ILLsymboltab_init (
+	ILLsymboltab * h)
+{
+	h->tablesize = 0;
+	h->strsize = 0;
+	h->freedchars = 0;
+	h->hashspace = 0;
+	h->name_space = 0;
+	h->strspace = 0;
+	h->hashtable = (int *) NULL;
+	h->nametable = (ILLsymbolent *) NULL;
+	h->namelist = (char *) NULL;
+}
+
+void ILLsymboltab_free (
+	ILLsymboltab * h)
+{
+	ILL_IFFREE (h->hashtable, int);
+
+	ILL_IFFREE (h->nametable, ILLsymbolent);
+	ILL_IFFREE (h->namelist, char);
+
+	ILLsymboltab_init (h);
+}
+
+int ILLsymboltab_create (
+	ILLsymboltab * h,
+	int init_size)
+{
+	int rval = 0;
+	int i;
+
+	if (init_size <= 0)
+		init_size = 1000;
+
+	ILLsymboltab_free (h);
+
+	h->tablesize = 0;
+	h->strsize = 0;
+	h->freedchars = 0;
+	h->name_space = init_size;
+	h->hashspace = ILLutil_nextprime (((unsigned) h->name_space));
+#ifdef TRY_CODE
+	h->strspace = init_size;
+#else
+	h->strspace = init_size * 5;
+#endif
+	h->index_ok = 0;
+
+	ILL_SAFE_MALLOC (h->hashtable, h->hashspace, int);
+
+	ILL_SAFE_MALLOC (h->nametable, h->name_space, ILLsymbolent);
+	ILL_SAFE_MALLOC (h->namelist, h->strspace, char);
+
+	for (i = 0; i < h->hashspace; i++)
+	{
+		h->hashtable[i] = ILL_SYM_NOINDEX;
+	}
+
+CLEANUP:
+	if (rval)
+	{
+		ILLsymboltab_free (h);
+	}
+	ILL_RETURN (rval, "ILLsymboltab_create");
+}
+
+int ILLsymboltab_copy (
+	ILLsymboltab * src,
+	ILLsymboltab * dst)
+{
+	int rval = 0;
+	int i;
+
+	ILLsymboltab_free (dst);
+
+	*dst = *src;
+	ILL_SAFE_MALLOC (dst->hashtable, dst->hashspace, int);
+
+	ILL_SAFE_MALLOC (dst->nametable, dst->name_space, ILLsymbolent);
+	ILL_SAFE_MALLOC (dst->namelist, dst->strspace, char);
+
+	for (i = 0; i < src->hashspace; i++)
+	{
+		dst->hashtable[i] = src->hashtable[i];
+	}
+	for (i = 0; i < src->tablesize; i++)
+	{
+		dst->nametable[i] = src->nametable[i];
+	}
+	for (i = 0; i < src->strsize; i++)
+	{
+		dst->namelist[i] = src->namelist[i];
+	}
+
+CLEANUP:
+	if (rval)
+	{
+		ILLsymboltab_free (dst);
+	}
+	ILL_RETURN (rval, "ILLsymboltab_copy");
+}
+
+
+const char *ILLsymboltab_get (
+	const ILLsymboltab * h,
+	int i)
+{
+	char *name = NULL;
+
+	ILL_FAILfalse_no_rval ((i >= 0) && (i <= h->tablesize), "Index out of range");
+	if (h->nametable[i].symbol != -1)
+		name = h->namelist + h->nametable[i].symbol;
+CLEANUP:
+	return name;
+}
+
+int ILLsymboltab_index_ok (
+	ILLsymboltab * h)
+{
+	return (h && (h->index_ok == 1));
+}
+
+int ILLsymboltab_index_reset (
+	ILLsymboltab * h,
+	int icount,
+	char **names)
+{
+	int rval = 0;
+	int i, k;
+
+	/* Note may have tablesize 1 larger than icount, due to objname */
+
+	if ((h->tablesize != icount) && (h->tablesize != icount + 1))
+	{
+		QSlog("symbol table (%d) does not match reset list (%d)",
+								h->tablesize, icount);
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	for (i = 0; i < icount; i++)
+	{
+		k = look_it_up (h, (const char *) names[i]);
+		if (k)
+		{
+			QSlog("Symbol %s is not in table", names[i]);
+			rval = 1;
+			ILL_CLEANUP;
+		}
+		k = h->the_index;
+		h->nametable[k].index = i;
+	}
+
+	h->index_ok = 1;
+
+CLEANUP:
+	return rval;
+}
+
+int ILLsymboltab_getindex (
+	ILLsymboltab * h,
+	const char *name,
+	int *hindex)
+{
+	int rval = 0;
+	int k;
+
+	*hindex = -1;
+
+	if (!h || !h->index_ok)
+	{
+		QSlog("symbol table index out of date");
+		rval = 1;
+		ILL_CLEANUP;
+	}
+
+	k = look_it_up (h, name);
+	if (k)
+	{
+		QSlog("Symbol %s is not in table", name);
+		ILL_CLEANUP;
+	}
+	k = h->the_index;
+
+	*hindex = h->nametable[k].index;
+
+CLEANUP:
+
+	ILL_RETURN (rval, "ILLsymboltab_getindex");
+}
+
+int ILLsymboltab_rename (
+	ILLsymboltab * h,
+	int i,
+	const char *new_name)
+{
+	int rval = 0;
+	int symbol = 0;
+
+	ILL_FAILfalse ((i >= 0) && (i <= h->tablesize), "Index out of range");
+	if ((new_name != NULL) && (look_it_up (h, new_name) == 0))
+	{
+		rval = (i != h->the_index);
+		ILL_RETURN (rval, "ILLsymboltab_rename");
+	}
+	if (h->nametable[i].symbol != -1)
+	{
+		(void) look_it_up (h, h->namelist + h->nametable[i].symbol);
+		ILL_FAILfalse (i == h->the_index, "must find it at i");
+		delete_from_list (h, i, h->the_prev_index, h->the_hash);
+	}
+	if (new_name != NULL)
+	{
+		rval = add_string (h, new_name, &symbol);
+		ILL_CLEANUP_IF (rval);
+		h->the_hash = stringhash (new_name, h->hashspace);
+		h->nametable[i].symbol = symbol;
+		h->nametable[i].next = h->hashtable[h->the_hash];
+		h->hashtable[h->the_hash] = i;
+	}
+	else
+	{
+		h->nametable[i].symbol = -1;
+		h->nametable[i].next = ILL_SYM_NOINDEX;
+	}
+CLEANUP:
+	ILL_RETURN (rval, "ILLsymboltab_rename");
+}
+
+int ILLsymboltab_lookup (
+	ILLsymboltab * h,
+	const char *s,
+	int *ind)
+{
+	int rval = look_it_up (h, s);
+
+	*ind = h->the_index;
+	return rval;
+}
+
+int ILLsymboltab_contains (
+	ILLsymboltab * tab,
+	const char *name)
+{
+	return !look_it_up (tab, name);
+}
+
+void ILLsymboltab_size (
+	const ILLsymboltab * h,
+	int *p_size)
+{
+	*p_size = h->tablesize;
+}
+
+int ILLsymboltab_register (
+	ILLsymboltab * h,
+	const char *s,
+	int itemindex,
+	int *the_prev_index,
+	int *existed)
+{
+	ILLsymbolent *nametable = h->nametable;
+	int e, symbol = 0;
+	int rval = 0;
+
+	if (itemindex < 0)
+	{
+		h->index_ok = 0;
+	}
+
+	h->the_prev_index = ILL_SYM_NOINDEX;
+	h->the_index = ILL_SYM_NOINDEX;
+	if (s == NULL)
+	{
+		e = h->tablesize;
+		h->the_index = e;
+		*existed = 0;
+		while (h->tablesize >= h->name_space)
+		{
+			rval = grow_symboltab (h);
+			ILL_CLEANUP_IF (rval);
+		}
+		h->tablesize++;
+		h->nametable[e].symbol = -1;
+		h->nametable[e].index = itemindex;
+		h->nametable[e].next = ILL_SYM_NOINDEX;
+		ILL_IFTRACE ("register: %s NULL entry#=%d\n", (*existed) ? "OLD" : "NEW",
+								 e);
+	}
+	else
+	{
+		*existed = !look_it_up (h, s);
+		if (*existed)
+		{
+			ILL_IFTRACE ("register: OLD %s entry#=%d hash=%d\n",
+									 s, h->the_index, h->the_hash);
+			return 0;
+		}
+
+		rval = add_string (h, s, &symbol);
+		ILL_CLEANUP_IF (rval);
+
+		while (h->tablesize >= h->name_space)
+		{
+			rval = grow_symboltab (h);
+			ILL_CLEANUP_IF (rval);
+			h->the_hash = stringhash (s, h->hashspace);	/*hash changes with bigger table */
+		}
+
+		nametable = h->nametable;
+
+		e = h->tablesize;
+		h->tablesize++;
+		h->the_prev_index = e;
+
+		nametable[e].symbol = symbol;
+		nametable[e].index = itemindex;
+		nametable[e].next = h->hashtable[h->the_hash];
+		h->hashtable[h->the_hash] = e;
+
+		ILL_IFTRACE ("register: %s NULL entry#=%d\n", (*existed) ? "OLD" : "NEW",
+								 e);
+	}
+
+CLEANUP:
+	*the_prev_index = h->the_prev_index;
+	ILL_RETURN (rval, "ILLsymboltab_register");
+}
+
+int ILLsymboltab_delete (
+	ILLsymboltab * h,
+	const char *s)
+{
+	int del_ind, rval = 0;
+	char *last;
+
+	ILL_FAILtrue (s == NULL, "must give non NULL str");
+
+	rval = look_it_up (h, s);
+	del_ind = h->the_index;
+	ILL_CLEANUP_IF (rval);				/* was not in table */
+	ILL_FAILfalse ((del_ind != ILL_SYM_NOINDEX) &&
+								 (h->nametable[del_ind].symbol != -1),
+								 "we should have found this non NULL str");
+	h->index_ok = 0;
+	delete_from_list (h, del_ind, h->the_prev_index, h->the_hash);
+
+	h->tablesize--;
+	if (del_ind != h->tablesize)
+	{
+		if (h->nametable[h->tablesize].symbol != -1)
+		{
+			last = h->namelist + h->nametable[h->tablesize].symbol;
+			rval = look_it_up (h, last);
+			ILL_FAILfalse ((rval == 0) && (h->the_index == h->tablesize),
+										 "Should find last entry");
+			if (h->the_prev_index != ILL_SYM_NOINDEX)
+			{
+				h->nametable[h->the_prev_index].next = del_ind;
+			}
+			else
+			{
+				h->hashtable[h->the_hash] = del_ind;
+			}
+		}
+		h->nametable[del_ind] = h->nametable[h->tablesize];
+	}
+CLEANUP:
+	ILL_RETURN (rval, "ILLsymboltab_delete");
+}
+
+void ILLsymboltab_prt (
+	FILE * fd,
+	ILLsymboltab * h)
+{
+	char *str;
+	int i;
+
+	for (i = 0; i < h->tablesize; i++)
+	{
+		if (h->nametable[i].symbol == -1)
+		{
+			fprintf (fd, "%d: NULL nohash\n", i);
+		}
+		else
+		{
+			str = h->namelist + h->nametable[i].symbol;
+			fprintf (fd, "%d: %s hash=%d\n", i, str, stringhash (str, h->hashspace));
+		}
+	}
+}
+
+static int look_it_up (
+	ILLsymboltab * h,
+	const char *s)
+{
+	ILLsymbolent *nametable = h->nametable;
+	char *namelist = h->namelist;
+	int e;
+
+	if(!h->hashspace) goto CLEANUP;
+	ILL_FAILfalse_no_rval (s, "Should never call with NULL string");
+	h->the_prev_index = ILL_SYM_NOINDEX;
+	h->the_hash = stringhash (s, h->hashspace);
+	for (e = h->hashtable[h->the_hash]; e != ILL_SYM_NOINDEX;
+			 e = nametable[e].next)
+	{
+		if (strcmp (namelist + nametable[e].symbol, s) == 0)
+		{
+			h->the_index = e;
+			ILL_IFTRACE ("look_it_up: OLD %s entry#=%d hash=%d\n", s, e, h->the_hash);
+			return 0;
+		}
+		h->the_prev_index = e;
+	}
+CLEANUP:
+	h->the_index = ILL_SYM_NOINDEX;
+	ILL_IFTRACE ("look_it_up: NEW %s \n", s);
+	return 1;
+}
+
+
+static void delete_from_list (
+	ILLsymboltab * h,
+	int del_ind,
+	int prev_ind,
+	int x)
+{
+	if (prev_ind != ILL_SYM_NOINDEX)
+	{
+		ILL_FAILtrue_no_rval (h->nametable[prev_ind].symbol == -1,
+													"A NULL str with same hash ?");
+		h->nametable[prev_ind].next = h->nametable[del_ind].next;
+	}
+	else
+	{
+		h->hashtable[x] = h->nametable[del_ind].next;
+	}
+	h->freedchars += strlen (h->namelist + h->nametable[del_ind].symbol) + 1;
+CLEANUP:
+	;
+}
+
+
+static int grow_symboltab (
+	ILLsymboltab * h)
+{
+	int newnamespace, newhashspace, *newhash, tablesize;
+	ILLsymbolent *newname;
+	char *namelist = h->namelist;
+	int i;
+	unsigned int x;
+	int rval = 0;
+
+	newnamespace = h->name_space * 2;
+	newhashspace = ILLutil_nextprime (((unsigned) newnamespace));
+	// rval = ILLutil_reallocrus_count ((void **) (&h->nametable), newnamespace,
+	//                                 sizeof (ILLsymbolent));
+	//ILL_CLEANUP_IF (rval);
+	h->nametable = EGrealloc (h->nametable, sizeof (ILLsymbolent) * newnamespace);
+	newname = h->nametable;
+
+	ILL_SAFE_MALLOC (newhash, newhashspace, int);
+	ILL_IFFREE (h->hashtable, int);
+
+	h->hashtable = newhash;
+
+	h->name_space = newnamespace;
+	h->hashspace = newhashspace;
+
+	newhash = h->hashtable;
+	tablesize = h->tablesize;
+
+	for (i = 0; i < newhashspace; i++)
+	{
+		newhash[i] = ILL_SYM_NOINDEX;
+	}
+	for (i = 0; i < tablesize; i++)
+	{
+		if (newname[i].symbol != -1)
+		{
+			x = stringhash (namelist + newname[i].symbol, newhashspace);
+			newname[i].next = newhash[x];
+			newhash[x] = i;
+		}
+	}
+CLEANUP:
+	ILL_RETURN (rval, "grow_symboltab");
+}
+
+static int grow_namelist (
+	ILLsymboltab * h)
+{
+	int newstrspace, i, j, newsymbol, rval = 0;
+	char *newnamelist, *newc;
+
+	if (2 * h->freedchars >= h->strspace)
+	{
+		/* compact string array */
+		ILL_SAFE_MALLOC (newnamelist, h->strspace, char);
+
+		newc = newnamelist;
+		for (i = 0; i < h->tablesize; i++)
+		{
+			if (h->nametable[i].symbol != -1)
+			{
+				newsymbol = newc - newnamelist;
+				for (j = h->nametable[i].symbol; h->namelist[j] != '\0'; j++)
+				{
+					*newc = h->namelist[j];
+					newc++;
+				}
+				*newc = '\0';
+				newc++;
+				h->nametable[i].symbol = newsymbol;
+			}
+		}
+		ILL_IFFREE (h->namelist, char);
+
+		h->namelist = newnamelist;
+		h->strsize = newc - newnamelist;
+		h->freedchars = 0;
+	}
+	else
+	{
+		newstrspace = h->strspace * 2;
+		h->namelist = EGrealloc (h->namelist, sizeof (char) * newstrspace);
+		//rval = ILLutil_reallocrus_count ((void **) &h->namelist, newstrspace,
+		//                                 sizeof (char));
+		//ILL_CLEANUP_IF (rval);
+		h->strspace = newstrspace;
+	}
+CLEANUP:
+	ILL_RETURN (rval, "grow_namelist");
+}
+
+static int add_string (
+	ILLsymboltab * h,
+	const char *s,
+	int *symbol)
+{
+	int l, rval = 0;
+
+	l = strlen (s) + 1;
+	while (h->strsize + l > h->strspace)
+	{
+		rval = grow_namelist (h);
+		ILL_CLEANUP_IF (rval);
+	}
+	strcpy (h->namelist + h->strsize, s);
+	*symbol = h->strsize;
+	h->strsize += l;
+CLEANUP:
+	ILL_RETURN (rval, "add_string");
+}
+
+static unsigned int stringhash (
+	const char *key,
+	int tsize)
+{
+	unsigned int x = 0;
+
+#ifdef TRY_CODE
+	while (*key)
+	{
+		x += *key;
+		key++;
+	}
+#else
+	while (*key)
+	{
+		x = 37 * x + *key;
+		key++;
+	}
+#endif
+	return x % tsize;
+}
+
+/**************************************************************************/
+/* ILLsymboltab_unique_name and its support                                */
+/**************************************************************************/
+static void make_var (
+	char *new_var,
+	const char *prefix,
+	char *name)
+{
+	size_t plen = strlen (prefix);
+	size_t nlen = strlen (name);
+	char *p;
+
+	if (nlen + plen >= ILL_namebufsize)
+	{
+		nlen = ILL_namebufsize - plen - 1;
+	}
+	strcpy (new_var, prefix);
+	p = new_var + plen;
+	strncpy (p, name, nlen + 1);
+}
+
+int ILLsymboltab_uname (
+	ILLsymboltab * symtab,
+	char *name,
+	const char *try_prefix1,
+	const char *try_prefix2)
+{
+	int nvars = symtab->tablesize;
+	int rval = 0;
+	int i, found, numlen;
+	const char *try_prefix[3];
+	char prefix[ILL_namebufsize];
+	char new_pre[ILL_namebufsize];
+	char new[ILL_namebufsize];
+
+	ILL_FAILtrue (try_prefix1 == NULL, "try_prefix must not be NULL");
+	try_prefix[0] = try_prefix1;
+	try_prefix[1] = try_prefix2;
+	try_prefix[2] = NULL;
+	new[0] = '\0';
+	found = 0;
+	for (i = 0; (!found) && try_prefix[i]; i++)
+	{
+		make_var (new, try_prefix[i], name);
+		found = !ILLsymboltab_contains (symtab, new);
+	}
+	if (!found)
+	{
+		i = 0;
+		sprintf (prefix, "%s", try_prefix[0]);
+		numlen = (log10 ((double) (symtab->tablesize - 1) * 10)) + 1;
+		while (!found)
+		{
+			ILL_FAILfalse (i <= nvars, "something wrong in find_unique_name");
+			make_var (new_pre, prefix, name);
+			new_pre[ILL_namebufsize - numlen - 1] = '\0';
+			sprintf (new, "%s_%d", new_pre, i);
+			found = !ILLsymboltab_contains (symtab, new);
+			i++;
+		}
+	}
+
+CLEANUP:
+	strcpy (name, new);
+	return rval;
+}
+
+void ILLsymboltab_unique_name (
+	ILLsymboltab * tab,
+	int i,
+	const char *pref,
+	char uname2[ILL_namebufsize])
+{
+	int notUnique;
+
+	sprintf (uname2, "%d", i);
+	notUnique = ILLsymboltab_uname (tab, uname2, pref, NULL);
+	ILL_FAILtrue_no_rval (notUnique, "Programming error");
+CLEANUP:
+	return;
+}
+
+#ifdef TRY_CODE
+/* debugging */
+static const char *get_str (
+	const ILLsymboltab * h,
+	int indx)
+{
+	if (indx < 0 || indx >= h->tablesize)
+	{
+		return "INDEX OUT OF RANGE";
+	}
+	if (h->nametable[indx].symbol == -1)
+	{
+		return "NULL";
+	}
+	else
+	{
+		return h->namelist + h->nametable[indx].symbol;
+	}
+}
+
+static void prt_xchain (
+	const ILLsymboltab * h,
+	int x)
+{
+	int e;
+	char *str;
+
+	x = x % h->hashspace;
+	QSlog("chain hash %d:", x);
+	for (e = h->hashtable[x]; e != ILL_SYM_NOINDEX; e = h->nametable[e].next)
+	{
+		if (h->nametable[e].symbol >= 0)
+		{
+			str = h->namelist + h->nametable[e].symbol;
+			x = stringhash (str, h->hashspace);
+			QSlog(" %s(h=%d, e=%d)", str, x, e);
+		}
+		else
+		{
+			QSlog(" NULL");
+		}
+	}
+}
+
+static void prt_chain (
+	const ILLsymboltab * h,
+	char *s)
+{
+	int e;
+
+	if (s != NULL)
+	{
+		prt_xchain (h, stringhash (s, h->hashspace));
+	}
+	else
+	{
+		for (e = 0; e < h->hashspace; e++)
+		{
+			if (h->hashtable[e] != ILL_SYM_NOINDEX)
+				prt_xchain (h, e);
+		}
+	}
+}
+#endif
+
+#ifdef TRY_CODE
+int main (
+	int ac,
+	char **av)
+{
+
+	int i, rval, index, pre_exist, nwords;
+	const char *prefix[3];
+	ILLsymboltab t, *tab = &t;
+	char cmd[100], symbol[100], line[256], str[100];
+	const char *s;
+	int ok;
+
+	TRACE = 1;
+	prefix[0] = "C";
+	prefix[1] = "c";
+	prefix[2] = NULL;
+	ILLsymboltab_init (tab);
+	ILLsymboltab_create (tab, 1);
+
+	fprintf (stdout, "> ");
+	fflush (stdout);
+	while (fgets (line, 100, stdin))
+	{
+		ok = 0;
+		symbol[0] = '\0';
+		nwords = sscanf (line, "%s%s%s", cmd, symbol, str);
+		if (nwords >= 1)
+		{
+			fprintf (stdout, ":: %s", line);
+			if ((nwords >= 2) && strcmp (cmd, "REG") == 0)
+			{
+				ok = 1;
+				if (strcmp (symbol, "NULL") == 0)
+				{
+					rval = ILLsymboltab_register (tab, NULL, &index, &pre_exist);
+				}
+				else
+				{
+					rval = ILLsymboltab_register (tab, symbol, &index, &pre_exist);
+				}
+			}
+			if ((nwords >= 2) && strcmp (cmd, "LOOK") == 0)
+			{
+				ok = 1;
+				rval = ILLsymboltab_register (tab, symbol, &index, &pre_exist);
+			}
+			if ((nwords >= 2) && strcmp (cmd, "DEL") == 0)
+			{
+				ok = 1;
+				rval = ILLsymboltab_delete (tab, symbol);
+			}
+			if ((nwords >= 2) && strcmp (cmd, "UNIQUE") == 0)
+			{
+				ok = 1;
+				rval = ILLsymboltab_uname (tab, symbol, "c", "C");
+			}
+			if ((nwords >= 1) && strcmp (cmd, "PRT") == 0)
+			{
+				ok = 1;
+				ILLsymboltab_prt (stdout, tab);
+			}
+			if ((nwords >= 2) && strcmp (cmd, "GET") == 0)
+			{
+				ok = 1;
+				i = atoi (symbol);
+				s = ILLsymboltab_get (tab, i);
+				fprintf (stdout, "%d: %s\n", i, (s != NULL) ? s : "NULL");
+			}
+			if ((nwords >= 3) && strcmp (cmd, "RENAME") == 0)
+			{
+				ok = 1;
+				i = atoi (symbol);
+				if (strcmp (str, "NULL") == 0)
+				{
+					ILLsymboltab_rename (tab, i, NULL);
+				}
+				else
+				{
+					ILLsymboltab_rename (tab, i, str);
+				}
+			}
+			if (strcmp (cmd, "CHAIN") == 0)
+			{
+				ok = 1;
+				if ((nwords == 1) || strcmp (symbol, "NULL") == 0)
+				{
+					prt_chain (tab, NULL);
+					fprintf (stdout,
+									 "last %s(%d) strsize/space: %d/%d freedchars: %d\n",
+									 get_str (tab, tab->tablesize - 1), tab->tablesize - 1,
+									 tab->strsize, tab->strspace, tab->freedchars);
+				}
+				else
+				{
+					prt_chain (tab, symbol);
+				}
+			}
+			if ((nwords >= 1) && strcmp (cmd, "INFO") == 0)
+			{
+				ok = 1;
+				fprintf (stdout,
+								 "last %s(%d) strsize/space: %d/%d freedchars: %d\n",
+								 get_str (tab, tab->tablesize - 1), tab->tablesize - 1,
+								 tab->strsize, tab->strspace, tab->freedchars);
+			}
+			if ((nwords >= 1) && strcmp (cmd, "STR") == 0)
+			{
+				ok = 1;
+				for (i = 0; i < tab->strsize; i++)
+				{
+					if (tab->namelist[i] == '\0')
+						fprintf (stdout, "\\0");
+					else
+						fprintf (stdout, "%c", tab->namelist[i]);
+				}
+				fprintf (stdout, "\n");
+			}
+		}
+		if (ok == 0)
+		{
+			fprintf (stdout, "commands: REG, LOOK, DEL, RENAME, GET, %s\n",
+							 "RENAME, UNIQUE, CHAIN, STR, INFO, PRT");
+		}
+		fprintf (stdout, "> ");
+		fflush (stdout);
+	}
+
+	return 0;
+}
+
+/* sample input for testing symboltab */
+#ifdef NEVER
+REG aabb REG aabb								// its already there 
+  REG abab REG abab							// its already there 
+  REG baba REG baba							// its already there 
+  REG bbaa REG bbaa							// its already there 
+  CHAIN aabb STR								// all with same hash 
+  DEL abab											// remove from middle
+  CHAIN baba DEL aabb						// remove last
+  CHAIN baba DEL bbaa						// remove first
+  CHAIN baba DEL baba						// remove the only element 
+  CHAIN PRT STR REG 123456789012	// compact name list no entries in table
+  STR REG longnametoo INFO REG a REG b DEL 123456789012 DEL longnametoo INFO STR REG more	// compact name list with entries in table
+  STR INFO PRT REG NULL					// add NULL str 
+  PRT DEL b											// remove with NULL being last entry
+  PRT CHAIN DEL a								// remove with NULL somewhere in table
+  PRT DEL more CHAIN						// nothing left in table
+  REG NULL											// add NULL str 
+  REG NULL											// add NULL str 
+  REG NULL											// add NULL str 
+  REG more PRT CHAIN						// only chain is for more
+  RENAME 0 more									// should fail
+  RENAME 0 another							// own hash 
+  RENAME 0 another							// must fail 
+  CHAIN RENAME 1 orem						// existing hash 
+  CHAIN RENAME 2 makestrarraygrowevenlongerwiththisid CHAIN PRT INFO STR DEL makestrarraygrowevenlongerwiththisid STR RENAME 3 somemore	// should trigger grownamelist
+ 
+	PRT
+	REG omemore
+	STR
+	CHAIN
+	INFO
+	UNIQUE a
+	UNIQUE a
+	REG Ca
+	UNIQUE a REG ca UNIQUE a REG Ca_0 REG Ca_1 REG Ca_2 REG Ca_3 REG Ca_4 UNIQUE a
+#endif
+#endif
diff --git a/qsopt_ex/symtab.h b/qsopt_ex/symtab.h
new file mode 100644
index 0000000..3ce795d
--- /dev/null
+++ b/qsopt_ex/symtab.h
@@ -0,0 +1,141 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCSINFO $Id: symtab.h,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+#ifndef ILL_SYMTAB_H
+#define ILL_SYMTAB_H
+
+#include <stdlib.h>
+#include <stdio.h>
+
+/* we allow 256KB of buffer space i.e. 2^17*/
+#define ILL_namebufsize 0x20000U
+
+typedef struct ILLsymbolent
+{
+	int symbol;
+	int index;
+	int next;
+}
+ILLsymbolent;
+
+typedef struct ILLsymboltab
+{
+	int *hashtable;
+	ILLsymbolent *nametable;
+	char *namelist;
+	int tablesize;
+	int strsize;
+	int hashspace;
+	int name_space;
+	int strspace;
+	int freedchars;
+	int the_hash;
+	int the_index;
+	int the_prev_index;
+	int index_ok;
+}
+ILLsymboltab;
+
+/* 
+ * hashtable[stringhash(entry) % hashspace] either NO_INDEX or some hash number
+ * nametable[hash number] = { next:    another index for nametable 
+ *                            symbol:  index into namelist where string resides
+ *                          }
+ * tablesize:  number of entries   (tablesize <= name_space)
+ * name_space:  length of nametable and indexlist
+ * hashspace:  length of hashtable   nextprime(name_space)
+ * strsize:    number of chars used in namelist 
+ * strspace:   length of namelist
+ * indexlist:  LP col/row indices for the table entries
+ * indexlist_ok:  1 if column indices in indexlist are up-to-date, 0 otherwise
+ *
+ * Deletion of entries affects their ordering in symboltab->nametable. 
+ * Strings may move around within symboltab->namelist. 
+ */
+
+
+#define ILL_SYM_NOINDEX (-1)
+extern void ILLsymboltab_init (
+	ILLsymboltab * h),
+  ILLsymboltab_free (
+	ILLsymboltab * h),
+  ILLsymboltab_size (
+	const ILLsymboltab * h,
+	int *p_size),
+  ILLsymboltab_prt (
+	FILE * fd,
+	ILLsymboltab * h);
+
+extern int ILLsymboltab_create (
+	ILLsymboltab * h,
+	int init_size),
+  ILLsymboltab_copy (
+	ILLsymboltab * src,
+	ILLsymboltab * dst),
+  ILLsymboltab_register (
+	ILLsymboltab * h,
+	const char *s,
+	int itemindex,
+	int *p_index,
+	int *p_existed),
+  ILLsymboltab_lookup (
+	ILLsymboltab * h,
+	const char *s,
+	int *p_index),
+  ILLsymboltab_index_ok (
+	ILLsymboltab * h),
+  ILLsymboltab_index_reset (
+	ILLsymboltab * h,
+	int icount,
+	char **names),
+  ILLsymboltab_getindex (
+	ILLsymboltab * h,
+	const char *name,
+	int *hindex),
+  ILLsymboltab_contains (
+	ILLsymboltab * h,
+	const char *s),
+  ILLsymboltab_delete (
+	ILLsymboltab * h,
+	const char *s),
+  ILLsymboltab_uname (
+	ILLsymboltab * h,
+	char name[ILL_namebufsize],
+	const char *try_prefix1,
+	const char *try_prefix2);
+
+extern void ILLsymboltab_unique_name (
+	ILLsymboltab * tab,
+	int i,
+	const char *pref,
+	char uname[ILL_namebufsize]);
+
+extern const char *ILLsymboltab_get (
+	const ILLsymboltab * tab,
+	int i);
+extern int ILLsymboltab_rename (
+	ILLsymboltab * h,
+	int i,
+	const char *new_name);
+
+#endif /* __SYMTAB_H */
diff --git a/qsopt_ex/trace.h b/qsopt_ex/trace.h
new file mode 100644
index 0000000..158fe0b
--- /dev/null
+++ b/qsopt_ex/trace.h
@@ -0,0 +1,41 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCSINFO $Id: trace.h,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+#ifndef ILL_trace_h
+#define ILL_trace_h
+
+#include "logging-private.h"
+
+/* users of these macros must declare a static int TRACE variable */
+#ifndef NDEBUG
+#define ILL_IFTRACE        if (TRACE) QSlog
+#define ILL_IFTRACE2       if (TRACE > 1) QSlog
+#define ILL_IFDOTRACE      if (TRACE)
+#else
+/* the optimizer will take care of this */
+#define ILL_IFTRACE        if (0) QSlog
+#define ILL_IFTRACE        if (0) QSlog
+#define ILL_IFDOTRACE      if (0)
+#endif
+
+#endif
diff --git a/qsopt_ex/urandom.c b/qsopt_ex/urandom.c
new file mode 100644
index 0000000..75062ea
--- /dev/null
+++ b/qsopt_ex/urandom.c
@@ -0,0 +1,169 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCSINFO $Id: urandom.c,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of CONCORDE                                           */
+/*                                                                          */
+/*  (c) Copyright 1995--1999 by David Applegate, Robert Bixby,              */
+/*  Vasek Chvatal, and William Cook                                         */
+/*                                                                          */
+/*  Permission is granted for academic research use.  For other uses,       */
+/*  contact the authors for licensing options.                              */
+/*                                                                          */
+/*  Use at your own risk.  We make no guarantees about the                  */
+/*  correctness or usefulness of this code.                                 */
+/*                                                                          */
+/****************************************************************************/
+
+/****************************************************************************/
+/*                                                                          */
+/*              MACHINE INDEPENDENT RANDOM NUMBER GENERATOR                 */
+/*                                                                          */
+/*                             TSP CODE                                     */
+/*                                                                          */
+/*                                                                          */
+/*  Written by:  DIMACS  (modified for TSP)                                 */
+/*  Date: February 7, 1995  (cofeb16)                                       */
+/*                                                                          */
+/*                                                                          */
+/*    EXPORTED FUNCTIONS:                                                   */
+/*                                                                          */
+/*  void ILLutil_sprand (int seed, ILLrandstate *r)                         */
+/*    - Call once to initialize the generator.                              */
+/*                                                                          */
+/*  int ILLutil_lprand (QSrandstate *r)                                     */
+/*    - Returns an integer in the range 0 to ILL_PRANDMAX - 1.              */
+/*                                                                          */
+/****************************************************************************/
+
+/****************************************************************************/
+/*                                                                          */
+/*    NOTES (from DIMACS):                                                  */
+/*        This file contains a set of c-language functions for generating   */
+/*    uniform integers.   This is a COMPLETELY PORTABLE generator. It will  */
+/*    give IDENTICAL sequences of random numbers for any architecture with  */
+/*    at least 30-bit integers, regardless of the integer representation,   */
+/*    INT_MAX value, or roundoff/truncation method, etc.                    */
+/*        This Truly Remarkable RNG is described more fully in              */
+/*    J. Bentley's column, ``The Software Exploratorium ''. It is based on  */
+/*    one in Knuth, Vol 2, Section 3.2.2 (Algorithm A).                     */
+/*                                                                          */
+/****************************************************************************/
+
+
+#include "util.h"
+
+
+void ILLutil_sprand (
+	int seed,
+	ILLrandstate * r)
+{
+	int i, ii;
+	int last, next;
+	int *arr = r->arr;
+
+	arr[0] = last = seed;
+	next = 1;
+	for (i = 1; i < 55; i++)
+	{
+		ii = (21 * i) % 55;
+		arr[ii] = next;
+		next = last - next;
+		if (next < 0)
+			next += ILL_PRANDMAX;
+		last = arr[ii];
+	}
+	r->a = 0;
+	r->b = 24;
+	for (i = 0; i < 165; i++)
+		last = ILLutil_lprand (r);
+}
+
+
+int ILLutil_lprand (
+	ILLrandstate * r)
+{
+	int t;
+
+	if (r->a-- == 0)
+		r->a = 54;
+	if (r->b-- == 0)
+		r->b = 54;
+
+	t = r->arr[r->a] - r->arr[r->b];
+
+	if (t < 0)
+		t += ILL_PRANDMAX;
+
+	r->arr[r->a] = t;
+
+	return t;
+}
+
+
+#ifdef      TRY_CODE
+
+/*-----------------------------------------------*/
+/* This is a little driver program so you can    */
+/* test the code.                                */
+/* Typing: a.out 0 3 1                           */
+/* should produce                                */
+/*     921674862                                 */
+/*     250065336                                 */
+/*     377506581                                 */
+/*  Typing: a.out 1000000 1 2                    */
+/*  should produce                               */
+/*     57265995                                  */
+/*-----------------------------------------------*/
+
+int main (
+	int ac,
+	char **av)
+{
+	int i;
+	int j;
+	int n;
+	int m;
+	int seed;
+	ILLrandstate rstate;
+
+	if (ac < 4)
+	{
+		fprintf (stderr, "Usage: #discard #print #seed\n");
+		return 0;
+	}
+	m = atoi (av[1]);							/* Number to discard initially */
+	n = atoi (av[2]);							/* Number to print */
+	seed = atoi (av[3]);					/* Seed */
+
+	ILLutil_sprand (seed, &rstate);
+
+	for (i = 0; i < m; i++)
+		j = ILLutil_lprand (&rstate);
+	for (i = 0; i < n; i++)
+		printf ("%ld\n", ILLutil_lprand (&rstate));
+	return 0;
+}
+
+#endif /* TRY_CODE */
diff --git a/qsopt_ex/urandom.h b/qsopt_ex/urandom.h
new file mode 100644
index 0000000..dc298ac
--- /dev/null
+++ b/qsopt_ex/urandom.h
@@ -0,0 +1,59 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+#ifndef __URANDOM_H__
+#define __URANDOM_H__
+/****************************************************************************/
+/*                                                                          */
+/*                             urandom.c                                    */
+/*                                                                          */
+/****************************************************************************/
+
+/* since urandom's generator does everything modulo ILL_PRANDMAX, if two
+ * seeds are congruent mod x and x|ILL_PRANDMAX, then the resulting numbers
+ * will be congruent mod x.  One example was if ILL_PRANDMAX = 1000000000 and
+ * urandom is used to generate a point set from a 1000x1000 grid, seeds
+ * congruent mod 1000 generate the same point set.
+ *
+ * For this reason, we use 1000000007 (a prime)
+ */
+#define ILL_PRANDMAX 1000000007
+
+typedef struct ILLrandstate
+{
+	int a;
+	int b;
+	int arr[55];
+}
+ILLrandstate;
+
+
+void ILLutil_sprand (
+	int seed,
+	ILLrandstate * r);
+
+int ILLutil_lprand (
+	ILLrandstate * r);
+
+
+
+#endif
diff --git a/qsopt_ex/util.c b/qsopt_ex/util.c
new file mode 100644
index 0000000..b9bb67b
--- /dev/null
+++ b/qsopt_ex/util.c
@@ -0,0 +1,283 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCSINFO $Id: util.c,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of CONCORDE                                           */
+/*                                                                          */
+/*  (c) Copyright 1995--1999 by David Applegate, Robert Bixby,              */
+/*  Vasek Chvatal, and William Cook                                         */
+/*                                                                          */
+/*  Permission is granted for academic research use.  For other uses,       */
+/*  contact the authors for licensing options.                              */
+/*                                                                          */
+/*  Use at your own risk.  We make no guarantees about the                  */
+/*  correctness or usefulness of this code.                                 */
+/*                                                                          */
+/****************************************************************************/
+
+/****************************************************************************/
+/*                                                                          */
+/*               MISCELLANEOUS UTILITY ROUTINES                             */
+/*                                                                          */
+/*                           TSP CODE                                       */
+/*                                                                          */
+/*  Written by:  Applegate, Bixby, Chvatal, and Cook                        */
+/*  Date: October 12, 1995                                                  */
+/*  Date: September 28, 1997                                                */
+/*                                                                          */
+/*    EXPORTED FUNCTIONS:                                                   */
+/*                                                                          */
+/*  unsigned int ILLutil_nextprime (unsigned int x)                         */
+/*    FINDS the smallest positive prime >= x                                */
+/*                                                                          */
+/*  int ILLutil_our_gcd (int a, int b)                                      */
+/*    COMPUTES gcd(a,b)                                                     */
+/*    -gcd(a,b) is always >= 0                                              */
+/*    -a and b can be negative, positive, or zero                           */
+/*                                                                          */
+/*  int ILLutil_our_lcm (int a, int b)                                      */
+/*    COMPUTES lcm(a,b)                                                     */
+/*    -lcm(a,b) is always >= 0                                              */
+/*    -a and b can be negative, positive, or zero                           */
+/*                                                                          */
+/*  double ILLutil_our_floor (double x)                                     */
+/*    REURNS the greatest integer no larger than x.                         */
+/*                                                                          */
+/*  double ILLutil_our_ceil (double x)                                      */
+/*    REURNS the least integer no smaller than x.                           */
+/*                                                                          */
+/*  double ILLutil_our_frac (double x)                                      */
+/*    REURNS the fractional part of x.                                      */
+/*                                                                          */
+/*  char *ILLutil_strchr (const char *s, int c)                             */
+/*    RETURNS a pointer to the first occurrence of c in s, or NULL if c     */
+/*    does not occur in s                                                   */
+/*                                                                          */
+/* int ILLutil_strcasecmp(const char *s1, const char *s2)                   */
+/*    RETURNS the string comparison, iqnoring the case of the letters.      */
+/*                                                                          */
+/* int ILLutil_strncasecmp(const char *s1, const char *s2, size_t n)        */
+/*    RETURNS the string comparision, iqnoring case, looks at max n bytes.  */
+/*                                                                          */
+/*  char *ILLutil_str(const char *s)                                        */
+/*    allocates and returns a copy of s                                     */
+/*                                                                          */
+/****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "except.h"
+#include "util.h"
+
+
+static int isprime (
+	unsigned int x);
+
+
+unsigned int ILLutil_nextprime (
+	unsigned int x)
+{
+	if (x < 3)
+		return 3;
+	x |= 1;
+	while (!isprime (x))
+		x += 2;
+	return x;
+}
+
+static int isprime (
+	unsigned int p)
+{
+	unsigned int i;
+
+	if ((p & 1) == 0)
+		return 0;
+	for (i = 3; i * i <= p; i += 2)
+	{
+		if (p % i == 0)
+			return 0;
+	}
+	return 1;
+}
+
+int ILLutil_our_gcd (
+	int a,
+	int b)
+{
+	int c;
+
+	if (a < 0)
+		a = -a;
+	if (b < 0)
+		b = -b;
+	if (a > b)
+		ILL_SWAP (a, b, c);
+
+	while (a)
+	{
+		c = b % a;
+		b = a;
+		a = c;
+	}
+	return b;
+}
+
+int ILLutil_our_lcm (
+	int a,
+	int b)
+{
+	int c;
+
+	if (a < 0)
+		a = -a;
+	if (b < 0)
+		b = -b;
+
+	c = ILLutil_our_gcd (a, b);
+
+	return (a / c) * b;
+}
+
+double ILLutil_our_floor (
+	double x)
+{
+	return floor (x);
+}
+
+double ILLutil_our_ceil (
+	double x)
+{
+	return ceil (x);
+}
+
+double ILLutil_our_frac (
+	double x)
+{
+	return x - floor (x);
+}
+
+double ILLutil_norm_sqr (
+	double *v,
+	int len)
+{
+	int i;
+	double sum = 0.0;
+
+	for (i = 0; i < len; i++)
+		sum += v[i] * v[i];
+	return sum;
+}
+
+int ILLutil_our_log2 (
+	int a)
+{
+	int i = 0, j = 1;
+
+	while (j < a)
+	{
+		j = j << 1;
+		i++;
+	}
+	return i ? i : 1;
+}
+
+const char *ILLutil_strchr (
+	const char *s,
+	int c)
+{
+	while (*s)
+	{
+		if (*s == c)
+			return s;
+		s++;
+	}
+	return (char *) NULL;
+}
+
+int ILLutil_strcasecmp (
+	const char *s1,
+	const char *s2)
+{
+	return strcasecmp (s1, s2);
+}
+
+int ILLutil_strncasecmp (
+	const char *s1,
+	const char *s2,
+	size_t n)
+{
+	return strncasecmp (s1, s2, n);
+}
+
+int ILLutil_index (
+	const char *list[],
+	const char *name)
+{
+	int i;
+
+	for (i = 0; list[i] != NULL; i++)
+	{
+		if (!strcmp (name, list[i]))
+		{
+			return i;
+		}
+	}
+	return -1;
+}
+
+int ILLutil_array_index (
+	char *list[],
+	int n,
+	const char *name)
+{
+	int i;
+
+	for (i = 0; i < n; i++)
+	{
+		if ((list[i] != NULL) && !strcmp (name, list[i]))
+		{
+			return i;
+		}
+	}
+	return -1;
+}
+
+char *ILLutil_str (
+	const char *str)
+{
+	int len;
+	char *cpy = NULL;
+
+	if (str != NULL)
+	{
+		len = strlen (str) + 1;
+		ILL_SAFE_MALLOC_no_rval (cpy, len, char);
+
+		strcpy (cpy, str);
+	}
+CLEANUP:
+	return cpy;
+}
diff --git a/qsopt_ex/util.h b/qsopt_ex/util.h
new file mode 100644
index 0000000..f6021b7
--- /dev/null
+++ b/qsopt_ex/util.h
@@ -0,0 +1,152 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCSINFO $Id: util.h,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+#ifndef ILL_UTIL_H
+#define ILL_UTIL_H
+
+#ifdef _USRDLL
+
+#ifdef QSLIB_EXPORTS
+#define QSLIB_INTERFACE __declspec(dllexport)
+#else
+#define QSLIB_INTERFACE __declspec(dllimport)
+#endif
+
+#else
+
+#define QSLIB_INTERFACE extern
+
+#endif
+
+#ifdef WIN32
+#define strcasecmp(s1, s2) 	stricmp(s1, s2)
+#define strncasecmp(s1, s2, n) 	strnicmp(s1, s2, n)
+#endif
+
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of CONCORDE                                           */
+/*                                                                          */
+/*  (c) Copyright 1995--1999 by David Applegate, Robert Bixby,              */
+/*  Vasek Chvatal, and William Cook                                         */
+/*                                                                          */
+/*  Permission is granted for academic research use.  For other uses,       */
+/*  contact the authors for licensing options.                              */
+/*                                                                          */
+/*  Use at your own risk.  We make no guarantees about the                  */
+/*  correctness or usefulness of this code.                                 */
+/*                                                                          */
+/****************************************************************************/
+
+/****************************************************************************/
+/*                                                                          */
+/*    EXPORTED FUNCTIONS:                                                   */
+/*                                                                          */
+/*  EGLPNUMPT_SWAP                                                          */
+/*  ILL_SWAP(a,b,t)                                                         */
+/*    swaps a and b, using t as temporary space.  a, b, and t should all    */
+/*    be the same type.                                                     */
+/*                                                                          */
+/*  ILL_OURABS(a)                                                           */
+/*    returns the absolute value of a.                                      */
+/*                                                                          */
+/****************************************************************************/
+typedef char ILLbool;
+
+#define FALSE 0
+#define TRUE  1
+
+#define ILL_SWAP(a,b,t) (((t)=(a)),((a)=(b)),((b)=(t)))
+
+#define ILL_OURABS(a) (((a) >= 0) ? (a) : -(a))
+
+#include "sortrus_common.h"
+#include "allocrus.h"
+#include "urandom.h"
+#include "zeit.h"
+/****************************************************************************/
+/*                                                                          */
+/*                             util.c                                       */
+/*                                                                          */
+/****************************************************************************/
+#define ILL_UTIL_STR(new, str) \
+    { new = ILLutil_str(str); \
+      if (str != NULL) { ILL_CHECKnull(new, "out of memeory"); } }
+
+extern char *ILLutil_str (
+	const char *str);
+
+	 /* allocates and returns a copy of s */
+
+extern int ILLutil_array_index (
+	char *list[],
+	int n,
+	const char *name);
+
+	 /* returns index of name in list or -1  */
+
+extern int ILLutil_index (
+	const char *list[],
+	const char *name);
+
+	 /* returns index of name in list or -1  */
+
+extern unsigned int ILLutil_nextprime (
+	unsigned int x);
+
+extern const char *ILLutil_strchr (
+	const char *s,
+	int c);
+
+extern int ILLutil_strcasecmp (
+	const char *s1,
+	const char *s2);
+extern int ILLutil_strncasecmp (
+	const char *s1,
+	const char *s2,
+	size_t n);
+
+
+extern int ILLutil_our_gcd (
+	int a,
+	int b),
+  ILLutil_our_lcm (
+	int a,
+	int b),
+  ILLutil_our_log2 (
+	int a);
+
+double ILLutil_our_floor (
+	double x),
+  ILLutil_our_ceil (
+	double x),
+  ILLutil_our_frac (
+	double x),
+  ILLutil_norm_sqr (
+	double *v,
+	int len);
+
+#include "bgetopt.h"
+/*#include "dheaps_i.h"*/
+/*#include "priority.h"*/
+#endif /* ILL_UTIL_H */
diff --git a/qsopt_ex/write_lp.c b/qsopt_ex/write_lp.c
new file mode 100644
index 0000000..f03c6ce
--- /dev/null
+++ b/qsopt_ex/write_lp.c
@@ -0,0 +1,262 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: wr_lp.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+
+/****************************************************************************/
+/*                                                                          */
+/*               Routines to support writing of LP files                    */
+/*                                                                          */
+/****************************************************************************/
+
+/* 
+ * -) anything after '\' is comment 
+ * -) variables consist of a-z A-Z 0-9!"#$%(),;.?@_`'{}|~ 
+ *    don't start with a digit or '.'
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "logging-private.h"
+
+#include "eg_lpnum.h"
+#include "eg_io.h"
+#include "except.h"
+
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+#include "write_lp_EGLPNUM_TYPENAME.h"
+
+
+void EGLPNUM_TYPENAME_ILLwrite_lp_state_init (
+	EGLPNUM_TYPENAME_ILLwrite_lp_state * line,
+	const char *str)
+{
+	line->total = 0;
+	line->p = line->buf;
+	*line->p = '\0';
+	if (str != NULL)
+	{
+		EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, str);
+	}
+}
+
+void EGLPNUM_TYPENAME_ILLwrite_lp_state_append (
+	EGLPNUM_TYPENAME_ILLwrite_lp_state * line,
+	const char *str)
+{
+	int len, rval = 0;
+
+	ILL_FAILfalse (str, "Must have non NULL string");
+	sprintf (line->p, "%s", str);
+	len = strlen (line->p);
+	line->total += len;
+	line->p += len;
+CLEANUP:
+	return;
+}
+
+void EGLPNUM_TYPENAME_ILLwrite_lp_state_append_coef (
+	EGLPNUM_TYPENAME_ILLwrite_lp_state * line,
+	EGLPNUM_TYPE v,
+	int cnt)
+{
+	EGLPNUM_TYPE ntmp;
+	int len = 0;
+
+	EGLPNUM_TYPENAME_EGlpNumInitVar (ntmp);
+	EGLPNUM_TYPENAME_EGlpNumCopy (ntmp, v);
+	if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (ntmp))
+	{
+		sprintf (line->p, " - ");
+		len = 3;
+		EGLPNUM_TYPENAME_EGlpNumSign (ntmp);
+	}
+	else
+	{
+		if (cnt > 0)
+		{
+			sprintf (line->p, " + ");
+			len = 3;
+		}
+		else
+		{
+			sprintf (line->p, " ");
+			len = 1;
+		}
+	}
+	line->p += len;
+	line->total += len;
+	if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (ntmp, EGLPNUM_TYPENAME_oneLpNum))
+	{
+		EGLPNUM_TYPENAME_ILLwrite_lp_state_append_number (line, ntmp);
+	}
+	EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+}
+
+/* so that diff will not stumble over too many number format differences 
+ * between c and java generated lp files we make here sure that doubles 
+ * which are printed without a ".xxx" part get ".0" from us
+ */
+static void append_number (
+	EGLPNUM_TYPENAME_ILLwrite_lp_state * line,
+	EGLPNUM_TYPE v);
+void EGLPNUM_TYPENAME_ILLwrite_lp_state_append_number (
+	EGLPNUM_TYPENAME_ILLwrite_lp_state * line,
+	EGLPNUM_TYPE v)
+{
+	/* write a blank after 'inf' in case it is used as a coefficient and 
+	 * a variable follows */
+	if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (v, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+	{
+		EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, "inf ");
+	}
+	else
+	{
+		if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (v, EGLPNUM_TYPENAME_ILL_MINDOUBLE))
+		{
+			EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, "-inf ");
+		}
+		else
+			append_number (line, v);
+	}
+}
+
+static void append_number (
+	EGLPNUM_TYPENAME_ILLwrite_lp_state * line,
+	EGLPNUM_TYPE v)
+{
+	int len = 0;
+	char *numstr = EGLPNUM_TYPENAME_EGlpNumGetStr (v);
+
+	sprintf (line->p, "%s%n", numstr, &len);
+	EGfree (numstr);
+	line->p += len;
+	line->total += len;
+}
+
+#if 0
+#define D_SCALE (1e9)
+static void append_number (
+	EGLPNUM_TYPENAME_ILLwrite_lp_state * line,
+	double x)
+{
+	/* Better code for writing rational problems */
+	int i, k;
+	int got = 0;
+	double w, t;
+	int nnum = 0;
+	int nden = 0;
+
+	if (x != 0.0)
+	{
+		if (x < 0.0)
+			w = -x;
+		else
+			w = x;
+
+		for (i = -9, t = 0.000000001; i <= 7; i++, t *= 10.0)
+		{
+			if (w >= t && w <= t * 10)
+			{
+				got = 1;
+				break;
+			}
+		}
+		if (got == 0)
+		{
+			QSlog("Out-of-range number: %f", x);
+			exit (1);
+		}
+	}
+
+	if (x < 0.0)
+	{
+		sprintf (line->p, "-");
+		line->p++;
+		line->total++;
+		x = -x;
+	}
+
+	while (x >= 10.0 * D_SCALE)
+	{
+		x /= 10.0;
+		nnum++;
+	}
+
+	/* (x != (double) (int) x) is a hack to let small integers print nicely */
+
+	while (x < D_SCALE && x != (double) (int) x)
+	{
+		x *= 10.0;
+		nden++;
+	}
+
+	sprintf (line->p, "%.0f%n", x, &k);
+	line->p += k;
+	line->total += k;
+
+	for (i = 0; i < nnum; i++)
+	{
+		sprintf (line->p, "0");
+		line->p++;
+		line->total++;
+	}
+
+	if (nden)
+	{
+		sprintf (line->p, "/1%n", &k);
+		line->p += k;
+		line->total += k;
+		for (i = 0; i < nden; i++)
+		{
+			sprintf (line->p, "0");
+			line->p++;
+			line->total++;
+		}
+	}
+}
+#endif
+
+void EGLPNUM_TYPENAME_ILLwrite_lp_state_save_start (
+	EGLPNUM_TYPENAME_ILLwrite_lp_state * line)
+{
+	line->startlen = line->total;
+}
+
+void EGLPNUM_TYPENAME_ILLwrite_lp_state_start (
+	EGLPNUM_TYPENAME_ILLwrite_lp_state * line)
+{
+	int j;
+
+	for (j = 0; j < line->startlen; j++)
+	{
+		line->buf[j] = ' ';
+	}
+	line->buf[j] = '\0';
+	line->p = line->buf + j;
+	line->total = j;
+}
diff --git a/qsopt_ex/write_lp.h b/qsopt_ex/write_lp.h
new file mode 100644
index 0000000..6df6385
--- /dev/null
+++ b/qsopt_ex/write_lp.h
@@ -0,0 +1,73 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/*  RCS_INFO = "$RCSfile: wr_lp.h,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:57:39 $"; */
+#ifndef EGLPNUM_TYPENAME_WRITE_LP_STATE_H
+#define EGLPNUM_TYPENAME_WRITE_LP_STATE_H
+
+#include "eg_lpnum.h"
+#include "symtab.h"
+
+/****************************************************************************/
+/*                                                                          */
+/*               Routines to support writing of LP files                    */
+/*                                                                          */
+/****************************************************************************/
+
+/* 
+ * -) anything after '\' is comment 
+ * -) variables consist of a-z A-Z 0-9!"#$%(),;.?@_`'{}|~ 
+ *    don't start with a digit or '.'
+ */
+
+typedef struct EGLPNUM_TYPENAME_ILLwrite_lp_state
+{
+	char buf[ILL_namebufsize];
+	char *p;
+	int startlen;
+	int total;
+}
+EGLPNUM_TYPENAME_ILLwrite_lp_state;
+
+extern void EGLPNUM_TYPENAME_ILLwrite_lp_state_init (
+	EGLPNUM_TYPENAME_ILLwrite_lp_state * line,
+	const char *str);
+extern void EGLPNUM_TYPENAME_ILLwrite_lp_state_append (
+	EGLPNUM_TYPENAME_ILLwrite_lp_state * line,
+	const char *str);
+extern void EGLPNUM_TYPENAME_ILLwrite_lp_state_append_coef (
+	EGLPNUM_TYPENAME_ILLwrite_lp_state * line,
+	EGLPNUM_TYPE v,
+	int cnt);
+
+			/* append number sign ('+', '-') iff cnt > 0 or v < 0.0  
+			 * append number iff v != 1.0, v != -1.0  
+			 */
+extern void EGLPNUM_TYPENAME_ILLwrite_lp_state_append_number (
+	EGLPNUM_TYPENAME_ILLwrite_lp_state * line,
+	EGLPNUM_TYPE v);
+extern void EGLPNUM_TYPENAME_ILLwrite_lp_state_save_start (
+	EGLPNUM_TYPENAME_ILLwrite_lp_state * line);
+extern void EGLPNUM_TYPENAME_ILLwrite_lp_state_start (
+	EGLPNUM_TYPENAME_ILLwrite_lp_state * line);
+
+#endif
diff --git a/qsopt_ex/zeit.c b/qsopt_ex/zeit.c
new file mode 100644
index 0000000..bd4b7fc
--- /dev/null
+++ b/qsopt_ex/zeit.c
@@ -0,0 +1,292 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCSINFO $Id: zeit.c,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of CONCORDE                                           */
+/*                                                                          */
+/*  (c) Copyright 1995--1999 by David Applegate, Robert Bixby,              */
+/*  Vasek Chvatal, and William Cook                                         */
+/*                                                                          */
+/*  Permission is granted for academic research use.  For other uses,       */
+/*  contact the authors for licensing options.                              */
+/*                                                                          */
+/*  Use at your own risk.  We make no guarantees about the                  */
+/*  correctness or usefulness of this code.                                 */
+/*                                                                          */
+/****************************************************************************/
+
+/****************************************************************************/
+/*                                                                          */
+/*                        TIMING FUNCTIONS                                  */
+/*                                                                          */
+/*                            TSP CODE                                      */
+/*                                                                          */
+/*                                                                          */
+/*  Written by:  Applegate, Bixby, Chvatal, and Cook                        */
+/*  Date: Summer 1994  (cofeb16)                                            */
+/*        December 1997 (dla)                                               */
+/*                                                                          */
+/*                                                                          */
+/*    EXPORTED FUNCTIONS:                                                   */
+/*                                                                          */
+/*  double ILLutil_zeit (void)                                              */
+/*        - To measure cpu time.                                            */
+/*    To use this, set double t = ILLutil_zeit (), run the function you     */
+/*    want to time, then compute ILLutil_zeit () - t.                       */
+/*                                                                          */
+/*  double ILLutil_real_zeit (void)                                         */
+/*    - To measure wall clock time.                                         */
+/*                                                                          */
+/*    To use this, set double t = ILLutil_real_zeit (), run the function    */
+/*    you want to time, then compute ILLutil_real_zeit () - t.              */
+/*                                                                          */
+/*  void ILLutil_init_timer (ILLutil_timer *t, const char *name)            */
+/*    - Initializes a ILLutil_timer, and gives it a name.                   */
+/*    - The name is silently truncated if it is too long.                   */
+/*                                                                          */
+/*  void ILLutil_start_timer (ILLutil_timer *t)                             */
+/*    - Starts the timer.                                                   */
+/*                                                                          */
+/*  void ILLutil_suspend_timer (ILLutil_timer *t)                           */
+/*    - Suspends the timer.  Similar to ILLutil_stop_timer, but doesn't     */
+/*      count a call, and doesn't output.                                   */
+/*                                                                          */
+/*  void ILLutil_resume_timer (QSutil_timer *t)                             */
+/*    - Resumes the timer after a suspend.                                  */
+/*                                                                          */
+/*  double ILLutil_stop_timer (ILLutil_timer *t, int printit)               */
+/*    - Stops the timer, and returns the time since the last start.         */
+/*    - if printit == 1, outputs the time spent.                            */
+/*    - if printit == 2, outputs the time spent only if nonzero             */
+/*    - if printit == 3,4, like 1,2, except brief, table-form output        */
+/*                                                                          */
+/*  double ILLutil_total_timer (ILLutil_timer *t, int printit)              */
+/*    - Returns the cumulative time for this timer.                         */
+/*    - if printit == 1, outputs the cumulative time.                       */
+/*    - if printit == 2, outputs the cumulative time only if nonzero        */
+/*    - if printit == 3,4, like 1,2, except brief, table-form output        */
+/*                                                                          */
+/****************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include "logging-private.h"
+
+#include "util.h"
+
+#ifdef HAVE_GETRUSAGE
+
+#ifdef HAVE_SYS_RESOURCE_H
+# include <sys/resource.h>
+#endif
+
+#define ZEIT_FCT "getrusage"
+
+double ILLutil_zeit (
+	void)
+{
+	struct rusage ru;
+	double t;
+
+	getrusage (RUSAGE_SELF, &ru);
+
+	t = ((double) ru.ru_utime.tv_sec) +
+		((double) ru.ru_utime.tv_usec) / 1000000.0;
+	return t;
+}
+#else	/* HAVE_GETRUSAGE */
+
+#ifdef HAVE_TIMES
+
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_TIMES_H
+# include <sys/times.h>
+#endif
+
+#ifdef CLK_TCK
+#define MACHINE_FREQ CLK_TCK
+#else
+#define MACHINE_FREQ HZ
+#endif
+
+#define ZEIT_FCT "times"
+
+double ILLutil_zeit (
+	void)
+{
+	struct tms now;
+
+	times (&now);
+	return ((double) now.tms_utime) / ((double) MACHINE_FREQ);
+}
+#else	/* HAVE_TIMES */
+
+#ifdef HAVE_CLOCK
+
+#ifndef CLOCKS_PER_SEC
+#ifdef CLK_TCK
+#define CLOCKS_PER_SEC CLK_TCK
+#else
+#define CLOCKS_PER_SEC 60
+#endif
+#endif
+
+#define ZEIT_FCT "clock"
+
+double ILLutil_zeit (
+	void)
+{
+	return ((double) clock ()) / ((double) CLOCKS_PER_SEC);
+}
+
+#else	/* HAVE_CLOCK */
+
+#define ZEIT_FCT "???"
+
+double ILLutil_zeit (
+	void)
+{
+	return 0.0;
+}
+#endif /* HAVE_CLOCK */
+#endif /* HAVE_TIMES */
+#endif /* HAVE_GETRUSAGE */
+
+double ILLutil_real_zeit (
+	void)
+{
+	return time (0);
+}
+
+void ILLutil_init_timer (
+	ILLutil_timer * t,
+	const char *name)
+{
+	t->szeit = -1.0;
+	t->cum_zeit = 0.0;
+	t->count = 0;
+	if (name == (char *) NULL || name[0] == '\0')
+	{
+		strncpy (t->name, "ANONYMOUS", sizeof (t->name) - 1);
+	}
+	else
+	{
+		strncpy (t->name, name, sizeof (t->name) - 1);
+	}
+	t->name[sizeof (t->name) - 1] = '\0';
+}
+
+void ILLutil_start_timer (
+	ILLutil_timer * t)
+{
+	if (t->szeit != -1.0)
+	{
+		QSlog("Warning: restarting running timer %s", t->name);
+	}
+	t->szeit = ILLutil_zeit ();
+}
+
+void ILLutil_suspend_timer (
+	ILLutil_timer * t)
+{
+	if (t->szeit == -1.0)
+	{
+		QSlog("Warning: suspended non-running timer %s", t->name);
+		return;
+	}
+
+	t->cum_zeit += ILLutil_zeit () - t->szeit;
+	t->szeit = -1.0;
+}
+
+void ILLutil_resume_timer (
+	ILLutil_timer * t)
+{
+	if (t->szeit != -1.0)
+	{
+		QSlog("Warning: resuming running timer %s", t->name);
+		return;
+	}
+	t->szeit = ILLutil_zeit ();
+}
+
+static void ILL_print (
+	ILLutil_timer * t,
+	double z,
+	int printit)
+{
+	if (printit == 1 || (printit == 2 && z > 0.0))
+	{
+		if (t->count > 1)
+		{
+			QSlog("Time for %s: %.2f seconds (%.2f total in %d calls).",
+									t->name, z, t->cum_zeit, t->count);
+		}
+		else
+		{
+			QSlog("Time for %s: %.2f seconds.", t->name, z);
+		}
+	}
+	else if (printit == 3 || (printit == 4 && z > 0.0))
+	{
+		QSlog("T %-34.34s %9.2f %9.2f %d (%s)",
+								t->name, z, t->cum_zeit, t->count, ZEIT_FCT);
+	}
+}
+
+double ILLutil_stop_timer (
+	ILLutil_timer * t,
+	int printit)
+{
+	double z;
+
+	if (t->szeit == -1.0)
+	{
+		QSlog("Warning: stopping non-running timer %s", t->name);
+		return 0.0;
+	}
+	z = ILLutil_zeit () - t->szeit;
+	t->szeit = -1.0;
+	t->cum_zeit += z;
+	t->count++;
+	ILL_print (t, z, printit);
+	return z;
+}
+
+double ILLutil_total_timer (
+	ILLutil_timer * t,
+	int printit)
+{
+	double z = t->cum_zeit;
+
+	if (t->szeit != -1.0)
+		z += ILLutil_zeit () - t->szeit;
+	ILL_print (t, z, printit);
+	return z;
+}
diff --git a/qsopt_ex/zeit.h b/qsopt_ex/zeit.h
new file mode 100644
index 0000000..9793a1d
--- /dev/null
+++ b/qsopt_ex/zeit.h
@@ -0,0 +1,65 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+#ifndef __ZEIT_H__
+#define __ZEIT_H__
+/****************************************************************************/
+/*                                                                          */
+/*                             zeit.c                                       */
+/*                                                                          */
+/****************************************************************************/
+
+typedef struct ILLutil_timer
+{
+	double szeit;
+	double cum_zeit;
+	char name[40];
+	int count;
+}
+ILLutil_timer;
+
+
+double ILLutil_zeit (
+	void),
+  ILLutil_real_zeit (
+	void),
+  ILLutil_stop_timer (
+	ILLutil_timer * t,
+	int printit),
+  ILLutil_total_timer (
+	ILLutil_timer * t,
+	int printit);
+
+
+void ILLutil_init_timer (
+	ILLutil_timer * t,
+	const char *name),
+  ILLutil_start_timer (
+	ILLutil_timer * t),
+  ILLutil_suspend_timer (
+	ILLutil_timer * t),
+  ILLutil_resume_timer (
+	ILLutil_timer * t);
+
+
+
+#endif
diff --git a/tap-driver.sh b/tap-driver.sh
new file mode 100755
index 0000000..4254e2b
--- /dev/null
+++ b/tap-driver.sh
@@ -0,0 +1,651 @@
+#! /bin/sh
+# Copyright (C) 2011-2014 Free Software Foundation, Inc.
+#
+# This program 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 2, or (at your option)
+# any later version.
+#
+# This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake at gnu.org> or send patches to
+# <automake-patches at gnu.org>.
+
+scriptversion=2013-12-23.17; # UTC
+
+# Make unconditional expansion of undefined variables an error.  This
+# helps a lot in preventing typo-related bugs.
+set -u
+
+me=tap-driver.sh
+
+fatal ()
+{
+  echo "$me: fatal: $*" >&2
+  exit 1
+}
+
+usage_error ()
+{
+  echo "$me: $*" >&2
+  print_usage >&2
+  exit 2
+}
+
+print_usage ()
+{
+  cat <<END
+Usage:
+  tap-driver.sh --test-name=NAME --log-file=PATH --trs-file=PATH
+                [--expect-failure={yes|no}] [--color-tests={yes|no}]
+                [--enable-hard-errors={yes|no}] [--ignore-exit]
+                [--diagnostic-string=STRING] [--merge|--no-merge]
+                [--comments|--no-comments] [--] TEST-COMMAND
+The '--test-name', '-log-file' and '--trs-file' options are mandatory.
+END
+}
+
+# TODO: better error handling in option parsing (in particular, ensure
+# TODO: $log_file, $trs_file and $test_name are defined).
+test_name= # Used for reporting.
+log_file=  # Where to save the result and output of the test script.
+trs_file=  # Where to save the metadata of the test run.
+expect_failure=0
+color_tests=0
+merge=0
+ignore_exit=0
+comments=0
+diag_string='#'
+while test $# -gt 0; do
+  case $1 in
+  --help) print_usage; exit $?;;
+  --version) echo "$me $scriptversion"; exit $?;;
+  --test-name) test_name=$2; shift;;
+  --log-file) log_file=$2; shift;;
+  --trs-file) trs_file=$2; shift;;
+  --color-tests) color_tests=$2; shift;;
+  --expect-failure) expect_failure=$2; shift;;
+  --enable-hard-errors) shift;; # No-op.
+  --merge) merge=1;;
+  --no-merge) merge=0;;
+  --ignore-exit) ignore_exit=1;;
+  --comments) comments=1;;
+  --no-comments) comments=0;;
+  --diagnostic-string) diag_string=$2; shift;;
+  --) shift; break;;
+  -*) usage_error "invalid option: '$1'";;
+  esac
+  shift
+done
+
+test $# -gt 0 || usage_error "missing test command"
+
+case $expect_failure in
+  yes) expect_failure=1;;
+    *) expect_failure=0;;
+esac
+
+if test $color_tests = yes; then
+  init_colors='
+    color_map["red"]="" # Red.
+    color_map["grn"]="" # Green.
+    color_map["lgn"]="" # Light green.
+    color_map["blu"]="" # Blue.
+    color_map["mgn"]="" # Magenta.
+    color_map["std"]=""     # No color.
+    color_for_result["ERROR"] = "mgn"
+    color_for_result["PASS"]  = "grn"
+    color_for_result["XPASS"] = "red"
+    color_for_result["FAIL"]  = "red"
+    color_for_result["XFAIL"] = "lgn"
+    color_for_result["SKIP"]  = "blu"'
+else
+  init_colors=''
+fi
+
+# :; is there to work around a bug in bash 3.2 (and earlier) which
+# does not always set '$?' properly on redirection failure.
+# See the Autoconf manual for more details.
+:;{
+  (
+    # Ignore common signals (in this subshell only!), to avoid potential
+    # problems with Korn shells.  Some Korn shells are known to propagate
+    # to themselves signals that have killed a child process they were
+    # waiting for; this is done at least for SIGINT (and usually only for
+    # it, in truth).  Without the `trap' below, such a behaviour could
+    # cause a premature exit in the current subshell, e.g., in case the
+    # test command it runs gets terminated by a SIGINT.  Thus, the awk
+    # script we are piping into would never seen the exit status it
+    # expects on its last input line (which is displayed below by the
+    # last `echo $?' statement), and would thus die reporting an internal
+    # error.
+    # For more information, see the Autoconf manual and the threads:
+    # <http://lists.gnu.org/archive/html/bug-autoconf/2011-09/msg00004.html>
+    # <http://mail.opensolaris.org/pipermail/ksh93-integration-discuss/2009-February/004121.html>
+    trap : 1 3 2 13 15
+    if test $merge -gt 0; then
+      exec 2>&1
+    else
+      exec 2>&3
+    fi
+    "$@"
+    echo $?
+  ) | LC_ALL=C ${AM_TAP_AWK-awk} \
+        -v me="$me" \
+        -v test_script_name="$test_name" \
+        -v log_file="$log_file" \
+        -v trs_file="$trs_file" \
+        -v expect_failure="$expect_failure" \
+        -v merge="$merge" \
+        -v ignore_exit="$ignore_exit" \
+        -v comments="$comments" \
+        -v diag_string="$diag_string" \
+'
+# TODO: the usages of "cat >&3" below could be optimized when using
+#       GNU awk, and/on on systems that supports /dev/fd/.
+
+# Implementation note: in what follows, `result_obj` will be an
+# associative array that (partly) simulates a TAP result object
+# from the `TAP::Parser` perl module.
+
+## ----------- ##
+##  FUNCTIONS  ##
+## ----------- ##
+
+function fatal(msg)
+{
+  print me ": " msg | "cat >&2"
+  exit 1
+}
+
+function abort(where)
+{
+  fatal("internal error " where)
+}
+
+# Convert a boolean to a "yes"/"no" string.
+function yn(bool)
+{
+  return bool ? "yes" : "no";
+}
+
+function add_test_result(result)
+{
+  if (!test_results_index)
+    test_results_index = 0
+  test_results_list[test_results_index] = result
+  test_results_index += 1
+  test_results_seen[result] = 1;
+}
+
+# Whether the test script should be re-run by "make recheck".
+function must_recheck()
+{
+  for (k in test_results_seen)
+    if (k != "XFAIL" && k != "PASS" && k != "SKIP")
+      return 1
+  return 0
+}
+
+# Whether the content of the log file associated to this test should
+# be copied into the "global" test-suite.log.
+function copy_in_global_log()
+{
+  for (k in test_results_seen)
+    if (k != "PASS")
+      return 1
+  return 0
+}
+
+function get_global_test_result()
+{
+    if ("ERROR" in test_results_seen)
+      return "ERROR"
+    if ("FAIL" in test_results_seen || "XPASS" in test_results_seen)
+      return "FAIL"
+    all_skipped = 1
+    for (k in test_results_seen)
+      if (k != "SKIP")
+        all_skipped = 0
+    if (all_skipped)
+      return "SKIP"
+    return "PASS";
+}
+
+function stringify_result_obj(result_obj)
+{
+  if (result_obj["is_unplanned"] || result_obj["number"] != testno)
+    return "ERROR"
+
+  if (plan_seen == LATE_PLAN)
+    return "ERROR"
+
+  if (result_obj["directive"] == "TODO")
+    return result_obj["is_ok"] ? "XPASS" : "XFAIL"
+
+  if (result_obj["directive"] == "SKIP")
+    return result_obj["is_ok"] ? "SKIP" : COOKED_FAIL;
+
+  if (length(result_obj["directive"]))
+      abort("in function stringify_result_obj()")
+
+  return result_obj["is_ok"] ? COOKED_PASS : COOKED_FAIL
+}
+
+function decorate_result(result)
+{
+  color_name = color_for_result[result]
+  if (color_name)
+    return color_map[color_name] "" result "" color_map["std"]
+  # If we are not using colorized output, or if we do not know how
+  # to colorize the given result, we should return it unchanged.
+  return result
+}
+
+function report(result, details)
+{
+  if (result ~ /^(X?(PASS|FAIL)|SKIP|ERROR)/)
+    {
+      msg = ": " test_script_name
+      add_test_result(result)
+    }
+  else if (result == "#")
+    {
+      msg = " " test_script_name ":"
+    }
+  else
+    {
+      abort("in function report()")
+    }
+  if (length(details))
+    msg = msg " " details
+  # Output on console might be colorized.
+  print decorate_result(result) msg
+  # Log the result in the log file too, to help debugging (this is
+  # especially true when said result is a TAP error or "Bail out!").
+  print result msg | "cat >&3";
+}
+
+function testsuite_error(error_message)
+{
+  report("ERROR", "- " error_message)
+}
+
+function handle_tap_result()
+{
+  details = result_obj["number"];
+  if (length(result_obj["description"]))
+    details = details " " result_obj["description"]
+
+  if (plan_seen == LATE_PLAN)
+    {
+      details = details " # AFTER LATE PLAN";
+    }
+  else if (result_obj["is_unplanned"])
+    {
+       details = details " # UNPLANNED";
+    }
+  else if (result_obj["number"] != testno)
+    {
+       details = sprintf("%s # OUT-OF-ORDER (expecting %d)",
+                         details, testno);
+    }
+  else if (result_obj["directive"])
+    {
+      details = details " # " result_obj["directive"];
+      if (length(result_obj["explanation"]))
+        details = details " " result_obj["explanation"]
+    }
+
+  report(stringify_result_obj(result_obj), details)
+}
+
+# `skip_reason` should be empty whenever planned > 0.
+function handle_tap_plan(planned, skip_reason)
+{
+  planned += 0 # Avoid getting confused if, say, `planned` is "00"
+  if (length(skip_reason) && planned > 0)
+    abort("in function handle_tap_plan()")
+  if (plan_seen)
+    {
+      # Error, only one plan per stream is acceptable.
+      testsuite_error("multiple test plans")
+      return;
+    }
+  planned_tests = planned
+  # The TAP plan can come before or after *all* the TAP results; we speak
+  # respectively of an "early" or a "late" plan.  If we see the plan line
+  # after at least one TAP result has been seen, assume we have a late
+  # plan; in this case, any further test result seen after the plan will
+  # be flagged as an error.
+  plan_seen = (testno >= 1 ? LATE_PLAN : EARLY_PLAN)
+  # If testno > 0, we have an error ("too many tests run") that will be
+  # automatically dealt with later, so do not worry about it here.  If
+  # $plan_seen is true, we have an error due to a repeated plan, and that
+  # has already been dealt with above.  Otherwise, we have a valid "plan
+  # with SKIP" specification, and should report it as a particular kind
+  # of SKIP result.
+  if (planned == 0 && testno == 0)
+    {
+      if (length(skip_reason))
+        skip_reason = "- "  skip_reason;
+      report("SKIP", skip_reason);
+    }
+}
+
+function extract_tap_comment(line)
+{
+  if (index(line, diag_string) == 1)
+    {
+      # Strip leading `diag_string` from `line`.
+      line = substr(line, length(diag_string) + 1)
+      # And strip any leading and trailing whitespace left.
+      sub("^[ \t]*", "", line)
+      sub("[ \t]*$", "", line)
+      # Return what is left (if any).
+      return line;
+    }
+  return "";
+}
+
+# When this function is called, we know that line is a TAP result line,
+# so that it matches the (perl) RE "^(not )?ok\b".
+function setup_result_obj(line)
+{
+  # Get the result, and remove it from the line.
+  result_obj["is_ok"] = (substr(line, 1, 2) == "ok" ? 1 : 0)
+  sub("^(not )?ok[ \t]*", "", line)
+
+  # If the result has an explicit number, get it and strip it; otherwise,
+  # automatically assing the next progresive number to it.
+  if (line ~ /^[0-9]+$/ || line ~ /^[0-9]+[^a-zA-Z0-9_]/)
+    {
+      match(line, "^[0-9]+")
+      # The final `+ 0` is to normalize numbers with leading zeros.
+      result_obj["number"] = substr(line, 1, RLENGTH) + 0
+      line = substr(line, RLENGTH + 1)
+    }
+  else
+    {
+      result_obj["number"] = testno
+    }
+
+  if (plan_seen == LATE_PLAN)
+    # No further test results are acceptable after a "late" TAP plan
+    # has been seen.
+    result_obj["is_unplanned"] = 1
+  else if (plan_seen && testno > planned_tests)
+    result_obj["is_unplanned"] = 1
+  else
+    result_obj["is_unplanned"] = 0
+
+  # Strip trailing and leading whitespace.
+  sub("^[ \t]*", "", line)
+  sub("[ \t]*$", "", line)
+
+  # This will have to be corrected if we have a "TODO"/"SKIP" directive.
+  result_obj["description"] = line
+  result_obj["directive"] = ""
+  result_obj["explanation"] = ""
+
+  if (index(line, "#") == 0)
+    return # No possible directive, nothing more to do.
+
+  # Directives are case-insensitive.
+  rx = "[ \t]*#[ \t]*([tT][oO][dD][oO]|[sS][kK][iI][pP])[ \t]*"
+
+  # See whether we have the directive, and if yes, where.
+  pos = match(line, rx "$")
+  if (!pos)
+    pos = match(line, rx "[^a-zA-Z0-9_]")
+
+  # If there was no TAP directive, we have nothing more to do.
+  if (!pos)
+    return
+
+  # Let`s now see if the TAP directive has been escaped.  For example:
+  #  escaped:     ok \# SKIP
+  #  not escaped: ok \\# SKIP
+  #  escaped:     ok \\\\\# SKIP
+  #  not escaped: ok \ # SKIP
+  if (substr(line, pos, 1) == "#")
+    {
+      bslash_count = 0
+      for (i = pos; i > 1 && substr(line, i - 1, 1) == "\\"; i--)
+        bslash_count += 1
+      if (bslash_count % 2)
+        return # Directive was escaped.
+    }
+
+  # Strip the directive and its explanation (if any) from the test
+  # description.
+  result_obj["description"] = substr(line, 1, pos - 1)
+  # Now remove the test description from the line, that has been dealt
+  # with already.
+  line = substr(line, pos)
+  # Strip the directive, and save its value (normalized to upper case).
+  sub("^[ \t]*#[ \t]*", "", line)
+  result_obj["directive"] = toupper(substr(line, 1, 4))
+  line = substr(line, 5)
+  # Now get the explanation for the directive (if any), with leading
+  # and trailing whitespace removed.
+  sub("^[ \t]*", "", line)
+  sub("[ \t]*$", "", line)
+  result_obj["explanation"] = line
+}
+
+function get_test_exit_message(status)
+{
+  if (status == 0)
+    return ""
+  if (status !~ /^[1-9][0-9]*$/)
+    abort("getting exit status")
+  if (status < 127)
+    exit_details = ""
+  else if (status == 127)
+    exit_details = " (command not found?)"
+  else if (status >= 128 && status <= 255)
+    exit_details = sprintf(" (terminated by signal %d?)", status - 128)
+  else if (status > 256 && status <= 384)
+    # We used to report an "abnormal termination" here, but some Korn
+    # shells, when a child process die due to signal number n, can leave
+    # in $? an exit status of 256+n instead of the more standard 128+n.
+    # Apparently, both behaviours are allowed by POSIX (2008), so be
+    # prepared to handle them both.  See also Austing Group report ID
+    # 0000051 <http://www.austingroupbugs.net/view.php?id=51>
+    exit_details = sprintf(" (terminated by signal %d?)", status - 256)
+  else
+    # Never seen in practice.
+    exit_details = " (abnormal termination)"
+  return sprintf("exited with status %d%s", status, exit_details)
+}
+
+function write_test_results()
+{
+  print ":global-test-result: " get_global_test_result() > trs_file
+  print ":recheck: "  yn(must_recheck()) > trs_file
+  print ":copy-in-global-log: " yn(copy_in_global_log()) > trs_file
+  for (i = 0; i < test_results_index; i += 1)
+    print ":test-result: " test_results_list[i] > trs_file
+  close(trs_file);
+}
+
+BEGIN {
+
+## ------- ##
+##  SETUP  ##
+## ------- ##
+
+'"$init_colors"'
+
+# Properly initialized once the TAP plan is seen.
+planned_tests = 0
+
+COOKED_PASS = expect_failure ? "XPASS": "PASS";
+COOKED_FAIL = expect_failure ? "XFAIL": "FAIL";
+
+# Enumeration-like constants to remember which kind of plan (if any)
+# has been seen.  It is important that NO_PLAN evaluates "false" as
+# a boolean.
+NO_PLAN = 0
+EARLY_PLAN = 1
+LATE_PLAN = 2
+
+testno = 0     # Number of test results seen so far.
+bailed_out = 0 # Whether a "Bail out!" directive has been seen.
+
+# Whether the TAP plan has been seen or not, and if yes, which kind
+# it is ("early" is seen before any test result, "late" otherwise).
+plan_seen = NO_PLAN
+
+## --------- ##
+##  PARSING  ##
+## --------- ##
+
+is_first_read = 1
+
+while (1)
+  {
+    # Involutions required so that we are able to read the exit status
+    # from the last input line.
+    st = getline
+    if (st < 0) # I/O error.
+      fatal("I/O error while reading from input stream")
+    else if (st == 0) # End-of-input
+      {
+        if (is_first_read)
+          abort("in input loop: only one input line")
+        break
+      }
+    if (is_first_read)
+      {
+        is_first_read = 0
+        nextline = $0
+        continue
+      }
+    else
+      {
+        curline = nextline
+        nextline = $0
+        $0 = curline
+      }
+    # Copy any input line verbatim into the log file.
+    print | "cat >&3"
+    # Parsing of TAP input should stop after a "Bail out!" directive.
+    if (bailed_out)
+      continue
+
+    # TAP test result.
+    if ($0 ~ /^(not )?ok$/ || $0 ~ /^(not )?ok[^a-zA-Z0-9_]/)
+      {
+        testno += 1
+        setup_result_obj($0)
+        handle_tap_result()
+      }
+    # TAP plan (normal or "SKIP" without explanation).
+    else if ($0 ~ /^1\.\.[0-9]+[ \t]*$/)
+      {
+        # The next two lines will put the number of planned tests in $0.
+        sub("^1\\.\\.", "")
+        sub("[^0-9]*$", "")
+        handle_tap_plan($0, "")
+        continue
+      }
+    # TAP "SKIP" plan, with an explanation.
+    else if ($0 ~ /^1\.\.0+[ \t]*#/)
+      {
+        # The next lines will put the skip explanation in $0, stripping
+        # any leading and trailing whitespace.  This is a little more
+        # tricky in truth, since we want to also strip a potential leading
+        # "SKIP" string from the message.
+        sub("^[^#]*#[ \t]*(SKIP[: \t][ \t]*)?", "")
+        sub("[ \t]*$", "");
+        handle_tap_plan(0, $0)
+      }
+    # "Bail out!" magic.
+    # Older versions of prove and TAP::Harness (e.g., 3.17) did not
+    # recognize a "Bail out!" directive when preceded by leading
+    # whitespace, but more modern versions (e.g., 3.23) do.  So we
+    # emulate the latter, "more modern" behaviour.
+    else if ($0 ~ /^[ \t]*Bail out!/)
+      {
+        bailed_out = 1
+        # Get the bailout message (if any), with leading and trailing
+        # whitespace stripped.  The message remains stored in `$0`.
+        sub("^[ \t]*Bail out![ \t]*", "");
+        sub("[ \t]*$", "");
+        # Format the error message for the
+        bailout_message = "Bail out!"
+        if (length($0))
+          bailout_message = bailout_message " " $0
+        testsuite_error(bailout_message)
+      }
+    # Maybe we have too look for dianogtic comments too.
+    else if (comments != 0)
+      {
+        comment = extract_tap_comment($0);
+        if (length(comment))
+          report("#", comment);
+      }
+  }
+
+## -------- ##
+##  FINISH  ##
+## -------- ##
+
+# A "Bail out!" directive should cause us to ignore any following TAP
+# error, as well as a non-zero exit status from the TAP producer.
+if (!bailed_out)
+  {
+    if (!plan_seen)
+      {
+        testsuite_error("missing test plan")
+      }
+    else if (planned_tests != testno)
+      {
+        bad_amount = testno > planned_tests ? "many" : "few"
+        testsuite_error(sprintf("too %s tests run (expected %d, got %d)",
+                                bad_amount, planned_tests, testno))
+      }
+    if (!ignore_exit)
+      {
+        # Fetch exit status from the last line.
+        exit_message = get_test_exit_message(nextline)
+        if (exit_message)
+          testsuite_error(exit_message)
+      }
+  }
+
+write_test_results()
+
+exit 0
+
+} # End of "BEGIN" block.
+'
+
+# TODO: document that we consume the file descriptor 3 :-(
+} 3>"$log_file"
+
+test $? -eq 0 || fatal "I/O or internal error"
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/tests/eg_lpnum_ex.c b/tests/eg_lpnum_ex.c
new file mode 100644
index 0000000..e7a4653
--- /dev/null
+++ b/tests/eg_lpnum_ex.c
@@ -0,0 +1,297 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ * 
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library 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 Lesser General Public 
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
+ * */
+/** @file
+ * @ingroup EGlpNum
+ * */
+/** @addtogroup EGlpNum */
+/** @{ */
+#include "eg_lpnum.h"
+/* ========================================================================= */
+/** @brief Tester program for EGlpNum_t structure and functions
+ * @return zero on success, non-zero otherwise 
+ * @par Description:
+ * Perform various tests on EGlpNum_t and their functions 
+ * */
+int main (int argc,
+					char **argv)
+{
+	/* local variables */
+	EGlpNum_t ntmp[4];
+	double dtmp[5];
+	char *strnum1,
+	 *strnum2,
+	 *strnum3;
+	int rval=0;
+	#ifdef HAVE_LIBGMP
+	int n_char = 0;
+	mpq_t qnum;
+	#endif
+	EGlpNumStart();
+	/* set signal and limits */
+	EGsigSet(rval,CLEANUP);
+	EGsetLimits(3600.0,4294967295UL);
+	#ifdef HAVE_LIBGMP
+	EGlpNumSetPrecision (128);
+	mpq_init (qnum);
+	#endif
+	EGlpNumInitVar (ntmp[0]);
+	EGlpNumInitVar (ntmp[1]);
+	EGlpNumInitVar (ntmp[2]);
+	EGlpNumInitVar (ntmp[3]);
+	/* the input should have at least two parameters, namelly the number where we
+	 * will work on */
+	if (argc < 3)
+	{
+		fprintf (stderr,
+						 "usage: %s num1 num2\n\tWhere num1 and num2 are numbers in"
+						 " the number format (either a/b or regular doubles)\n", argv[0]);
+		exit (1);
+	}
+
+	/* we ask for two numbers and perform some basic operations and compare
+	 * aganist double arithmetic */
+	#ifdef HAVE_LIBGMP
+	n_char = mpq_EGlpNumReadStrXc (qnum, argv[1]);
+	#endif
+	EGlpNumReadStr (ntmp[0], argv[1]);
+	EGlpNumReadStr (ntmp[1], argv[2]);
+	dtmp[0] = EGlpNumToLf (ntmp[0]);
+	dtmp[1] = EGlpNumToLf (ntmp[1]);
+
+	/* convert numbers */
+	strnum1 = EGlpNumGetStr (ntmp[0]);
+	strnum2 = EGlpNumGetStr (ntmp[1]);
+	fprintf (stderr, "You Input %s (%lg) and %s (%lg)\n", strnum1, dtmp[0],
+					 strnum2, dtmp[1]);
+	#ifdef HAVE_LIBGMP
+	strnum3 = mpq_EGlpNumGetStr (qnum);
+	fprintf (stderr, "Your first number represented as exact rational is %s, "
+					 "readed with %d chars\n", strnum3, n_char);
+	free (strnum3);
+	mpq_EGlpNumSet (qnum, dtmp[0]);
+	strnum3 = mpq_EGlpNumGetStr (qnum);
+	fprintf (stderr, "Your first number represented as continuous fraction "
+					 "is %s, readed with %d chars\n", strnum3, n_char);
+	free (strnum3);
+	#endif
+
+	/* internal constants */
+	strnum3 = EGlpNumGetStr (oneLpNum);
+	fprintf (stderr, "1.0 = %s\n", strnum3);
+	EGfree (strnum3);
+	strnum3 = EGlpNumGetStr (zeroLpNum);
+	fprintf (stderr, "0.0 = %s\n", strnum3);
+	EGfree (strnum3);
+	strnum3 = EGlpNumGetStr (epsLpNum);
+	fprintf (stderr, "eps = %s\n", strnum3);
+	EGfree (strnum3);
+	strnum3 = EGlpNumGetStr (MaxLpNum);
+	fprintf (stderr, "Max = %s\n", strnum3);
+	EGfree (strnum3);
+	strnum3 = EGlpNumGetStr (MinLpNum);
+	fprintf (stderr, "Min = %s\n", strnum3);
+	EGfree (strnum3);
+
+	/* copying functions */
+	EGlpNumCopy (ntmp[2], ntmp[0]);
+	strnum3 = EGlpNumGetStr (ntmp[2]);
+	fprintf (stderr, "%s = %s (%lg)\n", strnum3, strnum1, dtmp[0]);
+	EGfree (strnum3);
+	EGlpNumCopyDiff (ntmp[2], ntmp[0], ntmp[1]);
+	strnum3 = EGlpNumGetStr (ntmp[2]);
+	fprintf (stderr, "%s = %s - %s (%lg)\n", strnum3, strnum1, strnum2,
+					 dtmp[0] - dtmp[1]);
+	EGfree (strnum3);
+	EGlpNumCopyDiffRatio (ntmp[2], ntmp[0], ntmp[1], ntmp[0]);
+	strnum3 = EGlpNumGetStr (ntmp[2]);
+	fprintf (stderr, "%s = (%s  - %s)/%s (%lg)\n", strnum3, strnum1, strnum2,
+					 strnum1, (dtmp[0] - dtmp[1]) / dtmp[0]);
+	EGfree (strnum3);
+	EGlpNumCopySum (ntmp[2], ntmp[0], ntmp[1]);
+	strnum3 = EGlpNumGetStr (ntmp[2]);
+	fprintf (stderr, "%s = %s + %s (%lg)\n", strnum3, strnum1, strnum2,
+					 dtmp[0] + dtmp[1]);
+	EGfree (strnum3);
+	EGlpNumCopySqrOver (ntmp[2], ntmp[1], ntmp[0]);
+	strnum3 = EGlpNumGetStr (ntmp[2]);
+	fprintf (stderr, "%s = %s^2/%s (%lg)\n", strnum3, strnum2, strnum1,
+					 dtmp[1] * dtmp[1] / dtmp[0]);
+	EGfree (strnum3);
+	EGlpNumCopyAbs (ntmp[2], ntmp[0]);
+	strnum3 = EGlpNumGetStr (ntmp[2]);
+	fprintf (stderr, "%s = |%s| (%lg)\n", strnum3, strnum1, fabs (dtmp[0]));
+	EGfree (strnum3);
+	EGlpNumCopyNeg (ntmp[2], ntmp[0]);
+	strnum3 = EGlpNumGetStr (ntmp[2]);
+	fprintf (stderr, "%s = -1*%s (%lg)\n", strnum3, strnum1, -dtmp[0]);
+	EGfree (strnum3);
+	EGlpNumCopyFrac (ntmp[2], ntmp[1], ntmp[0]);
+	strnum3 = EGlpNumGetStr (ntmp[2]);
+	fprintf (stderr, "%s = %s/%s (%lg)\n", strnum3, strnum2, strnum1,
+					 dtmp[1] / dtmp[0]);
+	EGfree (strnum3);
+
+	/* add */
+	EGlpNumCopy (ntmp[2], ntmp[0]);
+	EGlpNumAddTo (ntmp[2], ntmp[1]);
+	strnum3 = EGlpNumGetStr (ntmp[2]);
+	fprintf (stderr, "%s + %s = %s (%lg)\n", strnum1, strnum2, strnum3,
+					 dtmp[0] + dtmp[1]);
+	EGfree (strnum3);
+	EGlpNumCopy (ntmp[2], ntmp[0]);
+	EGlpNumAddUiTo (ntmp[2], 0xffU);
+	strnum3 = EGlpNumGetStr (ntmp[2]);
+	fprintf (stderr, "%s + %u = %s (%lg)\n", strnum1, 0xffU, strnum3,
+					 dtmp[0] + 0xffU);
+	EGfree (strnum3);
+
+	/* substract */
+	EGlpNumCopy (ntmp[2], ntmp[0]);
+	EGlpNumSubTo (ntmp[2], ntmp[1]);
+	strnum3 = EGlpNumGetStr (ntmp[2]);
+	fprintf (stderr, "%s - %s = %s (%lg)\n", strnum1, strnum2, strnum3,
+					 dtmp[0] - dtmp[1]);
+	EGfree (strnum3);
+	EGlpNumCopy (ntmp[2], ntmp[0]);
+	EGlpNumSubUiTo (ntmp[2], 0xffU);
+	strnum3 = EGlpNumGetStr (ntmp[2]);
+	fprintf (stderr, "%s - %u = %s (%lg)\n", strnum1, 0xffU, strnum3,
+					 dtmp[0] - 0xffU);
+	EGfree (strnum3);
+
+	/* multiply */
+	EGlpNumCopy (ntmp[2], ntmp[0]);
+	EGlpNumMultTo (ntmp[2], ntmp[1]);
+	strnum3 = EGlpNumGetStr (ntmp[2]);
+	fprintf (stderr, "%s * %s = %s (%lg)\n", strnum1, strnum2, strnum3,
+					 dtmp[0] * dtmp[1]);
+	EGfree (strnum3);
+
+	/* multiply unsigned */
+	EGlpNumCopy (ntmp[2], ntmp[0]);
+	EGlpNumMultUiTo (ntmp[2], 13);
+	strnum3 = EGlpNumGetStr (ntmp[2]);
+	fprintf (stderr, "%s * 13 = %s (%lg)\n", strnum1, strnum3, dtmp[0] * 13);
+	EGfree (strnum3);
+
+	/* inverse */
+	EGlpNumCopy (ntmp[2], ntmp[0]);
+	EGlpNumInv (ntmp[2]);
+	strnum3 = EGlpNumGetStr (ntmp[2]);
+	fprintf (stderr, "1/%s = %s (%lg)\n", strnum1, strnum3, 1.0 / dtmp[0]);
+	EGfree (strnum3);
+
+	/* floor and ceil */
+	EGlpNumFloor (ntmp[2], ntmp[0]);
+	strnum3 = EGlpNumGetStr (ntmp[2]);
+	fprintf (stderr, "floor(%s) = %s (%lg)\n", strnum1, strnum3, floor (dtmp[0]));
+	EGfree (strnum3);
+	EGlpNumCeil (ntmp[2], ntmp[0]);
+	strnum3 = EGlpNumGetStr (ntmp[2]);
+	fprintf (stderr, "ceil(%s) = %s (%lg)\n", strnum1, strnum3, ceil (dtmp[0]));
+	EGfree (strnum3);
+
+	/* negative and inner products */
+	EGlpNumCopy (ntmp[2], ntmp[0]);
+	EGlpNumSign (ntmp[2]);
+	strnum3 = EGlpNumGetStr (ntmp[2]);
+	fprintf (stderr, "-(%s) = %s (%lg)\n", strnum1, strnum3, -dtmp[0]);
+	EGfree (strnum3);
+	EGlpNumOne (ntmp[2]);
+	EGlpNumAddInnProdTo (ntmp[2], ntmp[0], ntmp[1]);
+	strnum3 = EGlpNumGetStr (ntmp[2]);
+	fprintf (stderr, "1.0 + %s*%s = %s (%lg)\n", strnum1, strnum2, strnum3,
+					 1.0 + dtmp[1] * dtmp[0]);
+	EGfree (strnum3);
+	EGlpNumOne (ntmp[2]);
+	EGlpNumSubInnProdTo (ntmp[2], ntmp[0], ntmp[1]);
+	strnum3 = EGlpNumGetStr (ntmp[2]);
+	fprintf (stderr, "1.0 - %s*%s = %s (%lg)\n", strnum1, strnum2, strnum3,
+					 1.0 - dtmp[1] * dtmp[0]);
+	EGfree (strnum3);
+
+	/* divide */
+	EGlpNumCopy (ntmp[2], ntmp[0]);
+	EGlpNumDivTo (ntmp[2], ntmp[1]);
+	strnum3 = EGlpNumGetStr (ntmp[2]);
+	fprintf (stderr, "%s / %s = %s (%lg)\n", strnum1, strnum2, strnum3,
+					 dtmp[0] / dtmp[1]);
+	EGfree (strnum3);
+	EGlpNumCopy (ntmp[2], ntmp[0]);
+	EGlpNumDivUiTo (ntmp[2], 0xffU);
+	strnum3 = EGlpNumGetStr (ntmp[2]);
+	fprintf (stderr, "%s / %u = %s (%lg)\n", strnum1, 0xffU, strnum3,
+					 dtmp[0] / 0xffU);
+	EGfree (strnum3);
+	EGfree (strnum1);
+	EGfree (strnum2);
+
+#ifdef HAVE_LIBGMP
+	/* test transformation to rationals */
+	{
+		mpq_t n1, n2;
+		mpf_t f1, f2;
+		mpq_init (n1);
+		mpq_init (n2);
+		mpf_init (f1);
+		mpf_init (f2);
+		mpf_EGlpNumSet(f1,EGlpNumToLf(ntmp[0]));
+		mpf_EGlpNumSet(f2,EGlpNumToLf(ntmp[1]));
+		mpq_EGlpNumSet_mpf (n1, f1);
+		mpq_EGlpNumSet_mpf (n2, f2);
+		strnum1 = mpq_EGlpNumGetStr (n1);
+		strnum2 = mpq_EGlpNumGetStr (n2);
+		fprintf (stderr, "Your input in rational was:\n\t(%10.7lf) %s\n\t(%10.7lf)"
+				" %s\n", EGlpNumToLf (ntmp[0]), strnum1, EGlpNumToLf (ntmp[1]),
+				strnum2);
+		EGfree (strnum1);
+		EGfree (strnum2);
+
+		/* test natural exponentiation */
+		mpf_EGlpNumEpow (f1, -38.81624211135693732736499880);
+		mpf_set_ui (f2, (unsigned long)1);
+		mpf_div_2exp (f2, f2, (unsigned long)56);
+		strnum1 = mpf_EGlpNumGetStr (f1);
+		strnum2 = mpf_EGlpNumGetStr (f2);
+		fprintf (stderr, "2^-56 = %s ~ %s\n", strnum1, strnum2);
+		EGfree (strnum1);
+		EGfree (strnum2);
+		mpq_clear (n1);
+		mpq_clear (n2);
+		mpf_clear (f1);
+		mpf_clear (f2);
+	}
+#endif
+
+	/* ending */
+	CLEANUP:
+	EGlpNumClearVar (ntmp[0]);
+	EGlpNumClearVar (ntmp[1]);
+	EGlpNumClearVar (ntmp[2]);
+	EGlpNumClearVar (ntmp[3]);
+	#ifdef HAVE_LIBGMP
+	mpq_clear (qnum);
+	#endif
+	EGlpNumClear();
+	return 0;
+}
+
+/* ========================================================================= */
+/** @} */
diff --git a/tests/eg_sloan.c b/tests/eg_sloan.c
new file mode 100644
index 0000000..38e7833
--- /dev/null
+++ b/tests/eg_sloan.c
@@ -0,0 +1,243 @@
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "QSopt_ex.h"
+/* ========================================================================= */
+/** @name Static Variables
+ * Set of static variables for this program. */
+/*@{*/
+/** @brief range of values for first OA level */
+static unsigned s1 = 3;
+/** @brief range of values for second OA level */
+static unsigned s2 = 3;
+/** @brief number of columns for first OA level */
+static unsigned k1 = 3;
+/** @brief number of columns for second OA level */
+static unsigned k2 = 3;
+/** @brief use (or not) scaling of the resulting LP */
+static int use_scaling = 1;
+/** @brief use dlouble floating point output */
+static int use_double = 0;
+/** @brief file name output. */
+const char *out_file = "output.lp";
+/** @brief Strength level required */
+static unsigned t = 2;
+/** @brief temporal string space */
+char strtmp[1024];
+/*@}*/
+
+/* ========================================================================= */
+/** @brief Display options to the screen */
+static inline void sl_usage (char const *const s)
+{
+	fprintf (stderr,
+					 "This programs compute bounds for mixed-level orthogonal arrays (OA) of different strengths for two levels\n");
+	fprintf (stderr, "Usage: %s [options]\n", s);
+	fprintf (stderr, "    -a n   range of values for the first OA level (>=2)\n");
+	fprintf (stderr,
+					 "    -b n   range of values for the second OA level (>=2)\n");
+	fprintf (stderr,
+					 "    -c n   number of columns for the first OA level (>=2)\n");
+	fprintf (stderr,
+					 "    -e n   number of columns for the second OA level (>=2)\n");
+	fprintf (stderr,
+					 "    -d n   if n > 0, write the LP in double precition arithmetic, otherwise, write it in rational form\n");
+	fprintf (stderr, "    -o f   filename where to write the output LP\n");
+	fprintf (stderr,
+					 "    -s n   if n > 0 scale the resulting LP, otherwise present the unscaled LP\n");
+	fprintf (stderr, "    -t n   required strength of the OA (>=1)\n");
+}
+
+/* ========================================================================= */
+/** @brief Display options to the screen */
+static inline int sl_parseargs (int argc,
+																char **argv)
+{
+	int c;
+	while ((c = getopt (argc, argv, "a:b:c:e:s:d:o:t:")) != EOF)
+	{
+		switch (c)
+		{
+		case 'a':
+			s1 = atoi (optarg);
+			break;
+		case 'b':
+			s2 = atoi (optarg);
+			break;
+		case 'c':
+			k1 = atoi (optarg);
+			break;
+		case 'e':
+			k2 = atoi (optarg);
+			break;
+		case 's':
+			use_scaling = atoi (optarg);
+			break;
+		case 'd':
+			use_double = atoi (optarg);
+			break;
+		case 'o':
+			out_file = optarg;
+			break;
+		case 't':
+			t = atoi (optarg);
+			break;
+		default:
+			sl_usage (argv[0]);
+			return 1;
+		}
+	}
+	if (s1 < 2 || s2 < 2 || k1 < 1 || k2 < 1 || t < 1)
+	{
+		sl_usage (argv[0]);
+		return 1;
+	}
+	fprintf (stderr, "Running %s\nOptions:\n", argv[0]);
+	fprintf (stderr, "\tfirst level columns = %d\n", k1);
+	fprintf (stderr, "\tsecond level columns = %d\n", k2);
+	fprintf (stderr, "\tfirst level range = %d\n", s1);
+	fprintf (stderr, "\tsecond level range = %d\n", s2);
+	fprintf (stderr, "\tt = %d\n", t);
+	fprintf (stderr, "\t%s scaling\n", use_scaling ? "using" : "not using");
+	fprintf (stderr, "\t%s output\n", use_double ? "double" : "rational");
+	fprintf (stderr, "\toutput file : %s\n", out_file);
+	return 0;
+}
+
+/* ========================================================================= */
+/** @brief compute the krawtchouk ppolynomial, defined as
+ * \f[P^s_j(x,m)=\sum\limits_{i=0}^j(-1)^i(s-1)^{j-i}\binom{x}{i}\binom{m-x}{j-i}\f]
+ * @param x the \f$x\f$ parameter of the function.
+ * @param s the \f$s\f$ parameter of the function.
+ * @param j the \f$j\f$ parameter of the function.
+ * @param m the \f$m\f$ parameter of the function.
+ * @param rop where to store the result */
+void Kpoly (unsigned x,
+						unsigned s,
+						unsigned j,
+						unsigned m,
+						mpz_t rop)
+{
+	register unsigned i = j + 1;
+	mpz_t z1,
+	  z2;
+	mpz_init (z1);
+	mpz_init (z2);
+	mpz_set_ui (rop, (unsigned long)0);
+	EXIT (m < x, "m < x! impossible!");
+	EXIT (s < 1, "s < 1! impossible!");
+	while (i--)
+	{
+		mpz_bin_uiui (z1, (unsigned long)x, (unsigned long)i);
+		mpz_set (z2, z1);
+		mpz_bin_uiui (z1, (unsigned long)(m - x), (unsigned long)(j - i));
+		mpz_mul (z2, z2, z1);
+		mpz_ui_pow_ui (z1, (unsigned long)(s - 1), (unsigned long)(j - i));
+		mpz_mul (z2, z2, z1);
+		if (i & 1U)
+			mpz_sub (rop, rop, z2);
+		else
+			mpz_add (rop, rop, z2);
+	}
+	mpz_clear (z1);
+	mpz_clear (z2);
+}
+
+/* ========================================================================= */
+/** @brief main function, here we build the LP, execute the options and exit */
+int main (int argc,
+					char **argv)
+{
+	int rval = 0;
+	mpq_t v1,
+	  v2;
+	mpq_QSdata *p_mpq = 0;
+	dbl_QSdata *p_dbl = 0;
+	register unsigned i,
+	  j,
+	  k,
+	  l;
+	/* parse input */
+	QSopt_ex_version();
+	QSexactStart();
+	rval = sl_parseargs (argc, argv);
+	if (rval)
+		return rval;
+	mpq_init (v1);
+	mpq_init (v2);
+	/* create the problem with the appropriate number of variables and
+	 * constraints */
+	snprintf (strtmp, (size_t)1023, "OA_SL_%d-%d_%d-%d_t-%d", s1, k1, s2, k2, t);
+	p_mpq = mpq_QScreate_prob (strtmp, QS_MIN);
+	for (i = 0; i <= k1; i++)
+		for (j = 0; j <= k2; j++)
+		{
+			snprintf (strtmp, (size_t)1023, "V_%d_%d", i, j);
+			rval =
+				mpq_QSnew_col (p_mpq, mpq_oneLpNum,
+											 (i + j == 0) ? mpq_oneLpNum : mpq_zeroLpNum,
+											 mpq_ILL_MAXDOUBLE, strtmp);
+			CHECKRVALG (rval, CLEANUP);
+			strtmp[0] = 'C';
+			rval = mpq_QSnew_row (p_mpq, mpq_zeroLpNum,
+											 ((i + j >= 1) && (i + j <= t)) ? 'E' : 'G', strtmp);
+			CHECKRVALG (rval, CLEANUP);
+		}
+	/* now set the coefficients */
+	for (i = 0; i <= k1; i++)
+		for (j = 0; j <= k2; j++)
+			for (k = 0; k <= k1; k++)
+				for (l = 0; l <= k2; l++)
+				{
+					Kpoly (k, s1, i, k1, mpq_numref (v2));
+					Kpoly (l, s2, j, k2, mpq_numref (v1));
+					mpq_mul (v1, v1, v2);
+					if (mpz_cmp_ui (mpq_numref (v1), (unsigned long)0))
+					{
+						rval =
+							mpq_QSchange_coef (p_mpq, ((int)(j + i * (k2 + 1))), (int)(l + k * (k2 + 1)), v1);
+						CHECKRVALG (rval, CLEANUP);
+					}
+				}
+	/* now, if we are using scaling, we scale the non-zeros */
+	if (use_scaling)
+	{
+		mpq_set_ui (v1, (unsigned long)1, (unsigned long)1);
+		EXutilSimplify ((unsigned)(p_mpq->qslp->A.matsize), p_mpq->qslp->A.matval, v1);
+		mpq_div (v2, mpq_oneLpNum, v1);
+		fprintf (stderr, "Scale factor %lf\n", mpq_get_d (v2));
+	}
+	/* now we save the LP */
+	if (use_double)
+	{
+		snprintf (strtmp, (size_t)1023, "OA_SL_%d-%d_%d-%d_t-%d", s1, k1, s2, k2, t);
+		p_dbl = QScopy_prob_mpq_dbl (p_mpq, strtmp);
+		rval = dbl_QSwrite_prob (p_dbl, out_file, "LP");
+		CHECKRVALG (rval, CLEANUP);
+	}
+	else
+	{
+		rval = mpq_QSwrite_prob (p_mpq, out_file, "LP");
+		CHECKRVALG (rval, CLEANUP);
+	}
+
+	/* ending */
+CLEANUP:
+	if (p_mpq)
+		mpq_QSfree_prob (p_mpq);
+	if (p_dbl)
+		dbl_QSfree_prob (p_dbl);
+	mpq_clear (v1);
+	mpq_clear (v2);
+	QSexactClear();
+	return rval;
+}
diff --git a/tests/eg_sloan.h b/tests/eg_sloan.h
new file mode 100644
index 0000000..facf073
--- /dev/null
+++ b/tests/eg_sloan.h
@@ -0,0 +1,9 @@
+#ifndef __SLOAN_LP__
+#define __SLOAN_LP__
+#include <stdio.h>
+
+#if OS == LINUX
+#include <getopt.h>
+#endif
+#include "exact.h"
+#endif
diff --git a/tests/ftest.c b/tests/ftest.c
new file mode 100644
index 0000000..73865f5
--- /dev/null
+++ b/tests/ftest.c
@@ -0,0 +1,303 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: ftest.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+
+#include "qs_config.h"
+#include "config.h"
+#include "iqsutil.h"
+#include "lpdefs.h"
+#include "factor.h"
+
+#define NREP 2
+#define MAXITER 10000
+#undef  DENSE_READ
+//static int TRACE = 0;
+
+#if 0
+static int handle_singularity (
+	void *sdata,
+	int c,
+	int r)
+{
+	fprintf (stderr, "singular basis, replace column %d by row %d logical\n",
+					 r, c);
+	return 0;
+}
+#endif
+
+int main (
+	int ac,
+	char **av)
+{
+	factor_work f;
+	int dim = 0;
+	int ncol = 0;
+	int nzcnt = 0;
+	int *basis = (int *) NULL;
+	int *cbeg = (int *) NULL;
+	int *clen = (int *) NULL;
+	int *cind = (int *) NULL;
+	EGlpNum_t *coef = (EGlpNum_t *) NULL;
+	int niter = 0;
+	char str[4096];
+	char*l_argv[1024];
+	int l_argc,l_par;
+	char cmd[MAXITER];
+	int col[MAXITER];
+	svector a[MAXITER];
+	svector x;
+	svector upd;
+	int rval;
+	int i;
+	int j;
+	int rep;
+	int nz;
+	EGioFile_t *fin = 0;
+	char c;
+	int iter;
+	int nsing, *psrow, *pscol;
+	double szeit;
+	double factor_szeit;
+	double ftran_szeit;
+	double btran_szeit;
+	double update_szeit;
+	double factor_zeit = 0.0;
+	double ftran_zeit = 0.0;
+	double btran_zeit = 0.0;
+	double update_zeit = 0.0;
+	double dtmp;
+	QSexactStart();
+	ILLfactor_init_factor_work (&f);
+	for (i = 0; i < MAXITER; i++)
+	{
+		ILLsvector_init (&a[i]);
+	}
+	ILLsvector_init (&x);
+	ILLsvector_init (&upd);
+
+	szeit = ILLutil_zeit ();
+
+	if (ac > 1)
+	{
+		fin = EGioOpen (av[1], "r");
+		if (!fin)
+		{
+			perror (av[1]);
+			fprintf (stderr, "Unable to open %s for input\n", av[1]);
+			return 1;
+		}
+	}
+	else
+	{
+		fin = EGioOpenFILE(stdin);
+	}
+	do{
+		EGioGets(str,4096,fin);
+		EGioNParse(str,1024," ","%#",&i,l_argv);
+	}while(i==0 && !EGioEof(fin));
+	WARNING (i != 3, "Couldn't read dimension, columns and nonzeros, only read"
+					 " %d elements", i);
+	dim = atoi(l_argv[0]);
+	ncol = atoi(l_argv[1]);
+	nzcnt = atoi(l_argv[2]);
+	fprintf (stderr, "Using dimension %d columns %d and nonzero %d\n", dim,
+					 ncol, nzcnt);
+
+	ILL_SAFE_MALLOC (basis, dim, int);
+	ILL_SAFE_MALLOC (cbeg, ncol, int);
+	ILL_SAFE_MALLOC (clen, ncol, int);
+	ILL_SAFE_MALLOC (cind, nzcnt, int);
+
+	coef = EGlpNumAllocArray (nzcnt);
+
+	do{
+		EGioGets(str,4096,fin);
+		EGioNParse(str,1024," ","%#",&i,l_argv);
+	}while(i==0 && !EGioEof(fin));
+	TESTG((rval=(i!=dim)), CLEANUP, "Wrong format!");
+	for (i = 0; i < dim; i++)
+	{
+		basis[i] = atoi(l_argv[i]);
+	}
+
+	nz = 0;
+	for (i = 0; i < ncol; i++)
+	{
+		cbeg[i] = nz;
+		do
+		{
+			EGioGets(str,4096,fin);
+			EGioNParse(str,1024," ","%#",&l_argc,l_argv);
+		}while(l_argc==0 && !EGioEof(fin));
+		TESTG((rval=(l_argc<1)), CLEANUP, "Wrong format!");
+		clen[i] = l_argv[0];
+		TESTG((rval=(l_argc!= 2*clen[i]+1)), CLEANUP, "Wrong format or too long lines!");
+		for (j = 0; j < clen[i]; j++)
+		{
+			cind[nz] = atoi(l_argv[2*i+1]);
+			dtmp = strtod(l_argv[2*i+2],0);
+			EGlpNumSet (coef[nz], dtmp);
+			nz++;
+		}
+	}
+
+	rval = ILLsvector_alloc (&x, dim);
+	ILL_CLEANUP_IF (rval);
+	rval = ILLsvector_alloc (&upd, dim);
+	ILL_CLEANUP_IF (rval);
+
+	while (niter < MAXITER)
+	{
+		do
+		{
+			EGioGets(str,4096,fin);
+			EGioNParse(str,1024," ","%#",&l_argc,l_argv);
+		}while(l_argc==0 && !EGioEof(fin));
+		l_par = 0;
+		if(l_argc==0) break;
+		TESTG((rval=(l_argc<2)), CLEANUP,"Wrong Format");
+		c = l_argv[l_par++][0];
+		cmd[niter] = c;
+
+		switch (c)
+		{
+		case 'u':
+			col[niter] = atoi(l_argv[l_par++]);
+		case 'F':
+		case 'f':
+		case 'b':
+#ifdef DENSE_READ
+			nzcnt = 0;
+			TESTG((rval=(l_argc!=dim+l_par)), CLEANUP, "Wrng format or too long lines!");
+			for (i = 0; i < dim; i++)
+			{
+				dtmp = strtod(l_argv[l_par++],0);
+				if (dtmp != 0.0)
+				{
+					x.indx[nzcnt] = i;
+					EGlpNumSet (x.coef[nzcnt], dtmp);
+					nzcnt++;
+				}
+			}
+#else
+			nzcnt = atoi(l_argv[l_par++]);
+			TESTG((rval=(l_argc!=2*nzcnt+l_par)), CLEANUP, "Wrong format or too log lines!");
+			for (i = 0; i < nzcnt; i++)
+			{
+				x.indx[i] = atoi(l_argv[l_par++]);
+				dtmp = strtod(l_argv[l_par++],0);
+				EGlpNumSet (x.coef[i], dtmp);
+
+			}
+#endif
+			x.nzcnt = nzcnt;
+			rval = ILLsvector_copy (&x, &a[niter]);
+			ILL_CLEANUP_IF (rval);
+			break;
+		}
+		niter++;
+	}
+
+	printf ("Matrix and iterations read in %.2f seconds\n",
+					ILLutil_zeit () - szeit);
+	fflush (stdout);
+
+	szeit = ILLutil_zeit ();
+
+	for (rep = 0; rep < NREP; rep++)
+	{
+
+		factor_szeit = ILLutil_zeit ();
+
+#if 0
+		ILLfactor_init_factor_work (&f);
+#endif
+
+		rval = ILLfactor_create_factor_work (&f, dim);
+		ILL_CLEANUP_IF (rval);
+
+		rval =
+			ILLfactor (&f, basis, cbeg, clen, cind, coef, &nsing, &psrow, &pscol);
+		ILL_CLEANUP_IF (rval);
+
+		factor_zeit += ILLutil_zeit () - factor_szeit;
+
+		for (iter = 0; iter < niter; iter++)
+		{
+			switch (cmd[iter])
+			{
+			case 'f':
+				ftran_szeit = ILLutil_zeit ();
+				ILLfactor_ftran (&f, &a[iter], &x);
+				ftran_zeit += ILLutil_zeit () - ftran_szeit;
+				break;
+			case 'F':
+				ftran_szeit = ILLutil_zeit ();
+				ILLfactor_ftran_update (&f, &a[iter], &upd, &x);
+				ftran_zeit += ILLutil_zeit () - ftran_szeit;
+				break;
+			case 'b':
+				btran_szeit = ILLutil_zeit ();
+				ILLfactor_btran (&f, &a[iter], &x);
+				btran_zeit += ILLutil_zeit () - btran_szeit;
+				break;
+			case 'u':
+				update_szeit = ILLutil_zeit ();
+				ILLfactor_update (&f, &a[iter], col[iter], &nz);
+				update_zeit += ILLutil_zeit () - update_szeit;
+				break;
+			}
+		}
+		ILLfactor_free_factor_work (&f);
+	}
+	printf ("%d reps of %d steps finished in %.2f seconds\n", rep, niter,
+					ILLutil_zeit () - szeit);
+	printf ("factor: %.2f\n", factor_zeit);
+	printf ("ftran:  %.2f\n", ftran_zeit);
+	printf ("btran:  %.2f\n", btran_zeit);
+	printf ("update: %.2f\n", update_zeit);
+	fflush (stdout);
+
+	rval = 0;
+
+CLEANUP:
+	if (fin)
+	{
+		EGioClose (fin);
+	}
+	ILLfactor_free_factor_work (&f);
+	ILL_IFFREE (basis, int);
+	ILL_IFFREE (cbeg, int);
+	ILL_IFFREE (clen, int);
+	ILL_IFFREE (cind, int);
+
+	EGlpNumFreeArray (coef);
+	for (i = 0; i < niter; i++)
+	{
+		ILLsvector_free (&a[i]);
+	}
+	ILLsvector_free (&upd);
+	ILLsvector_free (&x);
+	QSexactClear();
+	return rval;
+}
diff --git a/tests/ftest.h b/tests/ftest.h
new file mode 100644
index 0000000..86a0d9b
--- /dev/null
+++ b/tests/ftest.h
@@ -0,0 +1,21 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
diff --git a/tests/solver.c b/tests/solver.c
new file mode 100644
index 0000000..5d3ed11
--- /dev/null
+++ b/tests/solver.c
@@ -0,0 +1,356 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: solver.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+
+#include "qs_config.h"
+#include "exact.h"
+#include "solver.h"
+#include "iqsutil.h"
+#include "util.h"
+#include "lpdefs.h"							/* for PRIMAL_SIMPLEX */
+#include "qstruct.h"
+#include "qsopt.h"
+#include "binary.h"
+#include "editor.h"
+#include "price.h"
+#include "lib.h"								/* for ILLmip_binary_dfs */
+
+static char *fname = 0;
+static int lpfile = 0;
+static int solvemip = 0;
+static int interactive = 0;
+static int usescaling = 1;
+static int showversion = 0;
+static int simplexalgo = PRIMAL_SIMPLEX;
+static int pstrategy = QS_PRICE_PSTEEP;
+static int dstrategy = QS_PRICE_DSTEEP;
+static unsigned precision = 128;
+static int printsol = 0;
+static char *readbasis = 0;
+static char *writebasis = 0;
+
+static void usage (
+	char *s),
+  get_ftype (
+	char *name,
+	int *ftype);
+
+#ifdef TEST_FEEDBACK
+static int feedback (
+	FILE * dest,
+	const char *str);
+#endif
+static int parseargs (
+	int ac,
+	char **av);
+
+#ifndef WIN32
+QSLIB_INTERFACE int main ( int ac, char **av);
+int main ( int ac, char **av)
+{
+	int rval;
+	QSopt_ex_version();
+	QSexactStart();
+	rval = solver_main (ac, av);
+	QSexactClear();
+	return rval;
+}
+#endif
+
+QSLIB_INTERFACE int solver_main (
+	int ac,
+	char **av)
+{
+	int rval = 0;
+	QSdata *p = 0;
+	ILLutil_timer timer_solve;
+	ILLutil_timer timer_read;
+	int ftype = 0;								/* 0 mps, 1 lp */
+	EGlpNum_t *x = 0;
+	EGlpNum_t val;
+	double szeit;
+
+	rval = parseargs (ac, av);
+	if (rval)
+		ILL_CLEANUP;
+
+	QSset_precision (precision);
+	EGlpNumInitVar (val);
+	if (showversion)
+	{
+		char *buf = 0;
+
+		buf = QSversion ();
+		if (buf == 0)
+		{
+			ILL_CLEANUP;
+		}
+		else
+		{
+			printf ("%s\n", buf);
+			QSfree ((void *) buf);
+		}
+	}
+
+	if (lpfile)
+	{
+		ftype = 1;
+	}
+	else
+	{
+		get_ftype (fname, &ftype);
+	}
+
+	ILLutil_init_timer (&timer_read, "SOLVER_READ");
+	ILLutil_start_timer (&timer_read);
+	if (ftype == 1)
+	{
+		p = QSread_prob ((const char *) fname, "LP");
+		if (p == 0)
+		{
+			fprintf (stderr, "Could not read lp file.\n");
+			rval = 1;
+			ILL_CLEANUP_IF (rval);
+		}
+	}
+	else
+	{
+		p = QSread_prob ((const char *) fname, "MPS");
+		if (p == 0)
+		{
+			fprintf (stderr, "Could not read mps file.\n");
+			rval = 1;
+			ILL_CLEANUP_IF (rval);
+		}
+	}
+
+	if (readbasis)
+	{
+		rval = QSread_and_load_basis (p, (const char *) readbasis);
+		ILL_CLEANUP_IF (rval);
+	}
+	ILLutil_stop_timer (&timer_read, 1);
+	rval = QSset_param (p, QS_PARAM_SIMPLEX_DISPLAY, 1)
+		|| QSset_param (p, QS_PARAM_PRIMAL_PRICING, pstrategy)
+		|| QSset_param (p, QS_PARAM_DUAL_PRICING, dstrategy)
+		|| QSset_param (p, QS_PARAM_SIMPLEX_SCALING, usescaling);
+	ILL_CLEANUP_IF (rval);
+
+	if (interactive)
+	{
+		ILLeditor_init ();
+		ILLeditor (p);
+		goto CLEANUP;
+	}
+
+	szeit = ILLutil_zeit();
+	ILLutil_init_timer (&timer_solve, "SOLVER");
+	ILLutil_start_timer (&timer_solve);
+
+#ifdef TEST_FEEDBACK
+	QSset_reporter (p, (void *) feedback, stdout);
+#endif
+	rval = ILLeditor_solve (p, simplexalgo);
+	ILLutil_stop_timer (&timer_solve, 1);
+	ILL_CLEANUP_IF (rval);
+
+	printf ("ZZ %s %.2f\n", p->lp->O->probname, ILLutil_zeit () - szeit);
+ 	fflush (stdout);
+
+	if (printsol)
+		x = EGlpNumAllocArray (p->lp->O->nstruct);
+
+	if (solvemip)
+	{
+		rval = ILLmip_bfs (p->lp, &val, x, &(p->itcnt));
+		ILL_CLEANUP_IF (rval);
+		printf ("MIP Objective Value: %.6f\n", EGlpNumToLf (val));
+		fflush (stdout);
+		if (printsol && EGlpNumIsNeqq (val, ILL_MAXDOUBLE) &&
+				EGlpNumIsNeqq (val, ILL_MINDOUBLE))
+		{
+			EGioFile_t*out = EGioOpenFILE(stdout);
+			rval = ILLlib_print_x (out, p->lp, 0, x, 1);
+			EGioClose(out);
+			ILL_CLEANUP_IF (rval);
+		}
+	}
+	else
+	{
+		if (writebasis)
+		{
+			rval = QSwrite_basis (p, 0, writebasis);
+			ILL_CLEANUP_IF (rval);
+		}
+		if (printsol)
+		{
+			EGioFile_t*out = EGioOpenFILE(stdout);
+			rval = ILLlib_print_x (out, p->lp, 0, 0, 1);
+			EGioClose(out);
+			ILL_CLEANUP_IF (rval);
+		}
+	}
+
+CLEANUP:
+	EGlpNumFreeArray (x);
+	QSfree_prob (p);
+	EGlpNumClearVar (val);
+	return rval;									/* main return */
+}
+
+static void usage (
+	char *s)
+{
+	char *buf = 0;
+
+	buf = QSversion ();
+	if (buf)
+	{
+		fprintf (stderr, "%s\n", buf);
+		QSfree ((void *) buf);
+	}
+
+	fprintf (stderr, "Usage: %s [- below -] prob_file\n", s);
+	fprintf (stderr, "   -b f  write basis to file f\n");
+	fprintf (stderr, "   -B f  read initial basis from file f\n");
+#if 0
+	fprintf (stderr, "   -I    solve the MIP using BestBound\n");
+	fprintf (stderr, "   -E    edit problem after solving initial version\n");
+#endif
+	fprintf (stderr, "   -L    input file is in lp format (default: mps)\n");
+	fprintf (stderr, "   -O    print the final solution\n");
+	fprintf (stderr, "   -p #  run primal simplex with pricing rule #\n");
+	fprintf (stderr,
+					 "         (%d-Dantzig, %d-Devex, %d-Steep (default), %d-Partial\n",
+					 QS_PRICE_PDANTZIG, QS_PRICE_PDEVEX, QS_PRICE_PSTEEP,
+					 QS_PRICE_PMULTPARTIAL);
+	fprintf (stderr, "   -d #  run dual simplex with pricing rule #\n");
+	fprintf (stderr, "         (%d-Dantzig, %d-Steep, %d-Partial, %d-Devex)\n",
+					 QS_PRICE_DDANTZIG, QS_PRICE_DSTEEP, QS_PRICE_DMULTPARTIAL,
+					 QS_PRICE_DDEVEX);
+	fprintf (stderr, "   -S    do NOT scale the initial LP\n");
+	fprintf (stderr, "   -v    print QSopt version number\n");
+}
+
+static int parseargs (
+	int ac,
+	char **av)
+{
+	int c;
+	int boptind = 1;
+	char *boptarg = 0;
+
+	while ((c =
+					ILLutil_bix_getopt (ac, av, "b:B:d:p:P:IELOSv", &boptind,
+															&boptarg)) != EOF)
+		switch (c)
+		{
+		case 'b':
+			writebasis = boptarg;
+			break;
+		case 'B':
+			readbasis = boptarg;
+			break;
+		case 'P':
+			precision = atoi (boptarg);
+			break;
+		case 'd':
+			simplexalgo = DUAL_SIMPLEX;
+			dstrategy = atoi (boptarg);
+			break;
+#if 0
+		case 'E':
+			interactive = 1;
+			break;
+		case 'I':
+			solvemip = 1;
+			break;
+#endif
+		case 'L':
+			lpfile = 1;
+			break;
+		case 'O':
+			printsol = 1;
+			break;
+		case 'p':
+			simplexalgo = PRIMAL_SIMPLEX;
+			pstrategy = atoi (boptarg);
+			break;
+		case 'S':
+			usescaling = 0;
+			break;
+		case 'v':
+			showversion = 1;
+			break;
+		case '?':
+		default:
+			usage (av[0]);
+			return 1;
+		}
+	if (boptind != (ac - 1))
+	{
+		usage (av[0]);
+		return 1;
+	}
+
+	fname = av[boptind++];
+	fprintf (stderr, "Reading problem from %s\n", fname);
+	return 0;
+}
+
+static void get_ftype (
+	char *name,
+	int *ftype)
+{
+	char *q;
+
+	q = strrchr (name, '.');
+	if (q)
+	{
+		q++;
+		if (!strcmp (q, "lp") || !strcmp (q, "LP"))
+		{
+			*ftype = 1;
+		}
+		else
+		{
+			*ftype = 0;
+		}
+	}
+}
+
+#ifdef TEST_FEEDBACK
+static int feedback (
+	FILE * dest,
+	const char *str)
+{
+	if (str != NULL)
+	{
+		int rc = fprintf ((FILE *) dest, "FEEDBACK: %s", str);
+
+		fflush (dest);
+		return rc;
+	}
+	return 0;
+}
+#endif
diff --git a/tests/solver.h b/tests/solver.h
new file mode 100644
index 0000000..46586e6
--- /dev/null
+++ b/tests/solver.h
@@ -0,0 +1,33 @@
+/****************************************************************************/
+/*                                                                          */
+/*  This file is part of QSopt_ex.                                          */
+/*                                                                          */
+/*  (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,      */
+/*  and Daniel Espinoza                                                     */
+/*                                                                          */
+/*  Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his     */
+/*  copyright in QSopt.                                                     */
+/*                                                                          */
+/*  This code may be used under the terms of the GNU General Public License */
+/*  (Version 2.1 or later) as published by the Free Software Foundation.    */
+/*                                                                          */
+/*  Alternatively, use is granted for research purposes only.               */
+/*                                                                          */
+/*  It is your choice of which of these two licenses you are operating      */
+/*  under.                                                                  */
+/*                                                                          */
+/*  We make no guarantees about the correctness or usefulness of this code. */
+/*                                                                          */
+/****************************************************************************/
+
+/* $RCSfile: solver.h,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:57:39 $ */
+#ifndef SOLVER_H
+#define SOLVER_H
+
+#include "qsopt.h"
+
+QSLIB_INTERFACE int solver_main (
+	int argc,
+	char **argv);
+
+#endif
diff --git a/tests/test_qs.c b/tests/test_qs.c
new file mode 100644
index 0000000..2952424
--- /dev/null
+++ b/tests/test_qs.c
@@ -0,0 +1,243 @@
+/*
+ * This file is part of QSopt_ex.
+ *
+ * (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,
+ * and Daniel Espinoza
+ * (c) Copyright 2015  Jon Lund Steffensen <jonlst at gmail.com>
+ *
+ * Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his
+ * copyright in QSopt.
+ *
+ * This code may be used under the terms of the GNU General Public License
+ * (Version 2.1 or later) as published by the Free Software Foundation.
+ *
+ * Alternatively, use is granted for research purposes only.
+ *
+ * It is your choice of which of these two licenses you are operating
+ * under.
+ *
+ * We make no guarantees about the correctness or usefulness of this code.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <gmp.h>
+
+#include "QSopt_ex.h"
+
+/* Number of tests. Must be kept up-to-date manually */
+#define TEST_COUNT  8
+
+/*                                                      */
+/*  Using QSload_prob to load the following LP problem  */
+/*       Maximize  3.0x + 2.0y + 4.0z                   */
+/*       Subject to                                     */
+/*                 3.0x + 2.0y + 1.0z <= 12.0           */
+/*                 5.0x + 1.0y         = 10.0           */
+/*                 x >= 2.0                             */
+/*                 y free                               */
+/*                 1.0 <= z <= 10.0                     */
+/*                                                      */
+
+static int load_test_problem (mpq_QSprob *p)
+{
+    int i, rval = 0;
+    int cmatcnt[3] = { 2, 2, 1 };
+    int cmatbeg[3] = { 0, 2, 4 };
+    int cmatind[5] = { 0, 1, 0, 1, 0 };
+    char sense[2] = { 'L', 'E' };
+    const char *colnames[3] = { "x", "y", "z" };
+    const char *rownames[2] = { "c1", "c2"};
+    mpq_t cmatval[5];
+    mpq_t obj[3];
+    mpq_t rhs[2];
+    mpq_t lower[3];
+    mpq_t upper[3];
+
+    for (i = 0; i < 5; i++) mpq_init (cmatval[i]);
+    mpq_set_d (cmatval[0], 3.0);
+    mpq_set_d (cmatval[1], 5.0);
+    mpq_set_d (cmatval[2], 2.0);
+    mpq_set_d (cmatval[3], 1.0);
+    mpq_set_d (cmatval[4], 1.0);
+
+    for (i = 0; i < 3; i++) mpq_init (obj[i]);
+    mpq_set_d (obj[0], 3.0);
+    mpq_set_d (obj[1], 2.0);
+    mpq_set_d (obj[2], 4.0);
+
+    for (i = 0; i < 2; i++) mpq_init (rhs[i]);
+    mpq_set_d (rhs[0], 12.0);
+    mpq_set_d (rhs[1], 10.0);
+
+    for (i = 0; i < 3; i++) mpq_init (lower[i]);
+    mpq_set_d (lower[0], 2.0);
+    mpq_set (lower[1], mpq_ILL_MINDOUBLE);
+    mpq_set_d (lower[2], 1.0);
+
+    for (i = 0; i < 3; i++) mpq_init (upper[i]);
+    mpq_set (upper[0], mpq_ILL_MAXDOUBLE);
+    mpq_set (upper[1], mpq_ILL_MAXDOUBLE);
+    mpq_set_d (upper[2], 10.0);
+
+    /*  CPXcopylpwnames  */
+
+    *p = mpq_QSload_prob ("small", 3, 2, cmatcnt, cmatbeg, cmatind, cmatval,
+                      QS_MAX, obj, rhs, sense, lower, upper, colnames,
+                      rownames);
+
+    if (*p == (mpq_QSprob) NULL) {
+        fprintf (stderr, "Unable to load the LP problem\n");
+        rval = 1;  goto CLEANUP;
+    }
+
+CLEANUP:
+
+    for (i = 0; i < 5; i++) mpq_clear (cmatval[i]);
+    for (i = 0; i < 3; i++) mpq_clear (obj[i]);
+    for (i = 0; i < 2; i++) mpq_clear (rhs[i]);
+    for (i = 0; i < 3; i++) mpq_clear (lower[i]);
+    for (i = 0; i < 3; i++) mpq_clear (upper[i]);
+
+    return rval;
+}
+
+int main (int ac, char **av)
+{
+    int rval = 0, status = 0;
+    int i, nrows = 0, ncols = 0;
+    mpq_t value;
+    mpq_t *x = (mpq_t *) NULL;
+    mpq_t *y = (mpq_t *) NULL;
+    mpq_QSprob p = (mpq_QSprob) NULL;
+    char **colnames = (char **) NULL;
+    char **rownames = (char **) NULL;
+
+    QSexactStart();
+
+    mpq_init (value);
+
+    if (ac > 1) {
+        printf ("Usage: %s\n", *av);
+        rval = EXIT_FAILURE; goto CLEANUP;
+    }
+
+    /*  Must call QSexact_set_precision before any other QS function       */
+    /*  Cannot use mpq_ILL_MAXDOUBLE or mpq_ILL_MINDOUBLE before this call */
+
+    QSexact_set_precision (128);   
+
+    /* Print number of tests */
+    printf("1..%u\n", TEST_COUNT);
+
+    /* Test 1 - load test problem */
+    rval = load_test_problem (&p);
+    if (rval) {
+        printf("not ok 1 - Unable to load the LP\n");
+        goto CLEANUP;
+    }
+
+    printf("ok 1 - Loaded test LP problem\n");
+
+    /* Test 2 - get row count */
+    nrows = mpq_QSget_rowcount (p);
+    if (nrows != 2) {
+        printf("not ok 2 - Invalid number of constraints: %d\n", nrows);
+    } else {
+        printf("ok 2 - Got number of constraints\n");
+    }
+
+    /* Test 3 - get col count */
+    ncols = mpq_QSget_colcount (p);
+    if (ncols != 3) {
+        printf("not ok 3 - Invalid number of variables: %d\n", ncols);
+    } else {
+        printf("ok 3 - Got number of variables\n");
+    }
+
+    /*  Test 4 - Solve problem  */
+    rval = QSexact_solver (p, NULL, NULL, NULL, DUAL_SIMPLEX, &status);
+    if (rval) {
+        printf("not ok 4 - Solver failed\n");
+        goto CLEANUP;
+    }
+    if (status != QS_LP_OPTIMAL) {
+        printf("not ok 4 - Did not find an optimal solution.\n");
+        goto CLEANUP;
+    }
+
+    printf("ok 4 - Solution was found\n");
+
+    /* Test 5 - Get objective value  */
+    rval = mpq_QSget_objval (p, &value);
+    if (rval) {
+        printf("not ok 5 - Could not get obj value, error code %d\n", rval);
+    } else {
+        if (mpq_cmp_ui(value, 42, 1) != 0) {
+            printf("not ok 5 - Unexpected obj value: %.6f\n", mpq_get_d(value));
+        } else {
+            printf("ok 5 - The correct objective value was obtained\n");
+        }
+    }
+
+    /* Test 6 - Get variable values */
+    x = (mpq_t *) malloc (ncols * sizeof (mpq_t));
+    for (i = 0; i < ncols; i++) mpq_init (x[i]);
+    rval = mpq_QSget_x_array (p, x);
+    if (rval) {
+        printf("not ok 6 - Could not get x-vector, error code %d\n", rval);
+    } else {
+        colnames = (char **) malloc (ncols * sizeof (char *));
+        mpq_QSget_colnames (p, colnames);
+        printf("ok 6 - Obtained variable values and names\n");
+    }
+
+    /* Test 7 - Get dual values */
+    y = (mpq_t *) malloc (nrows * sizeof (mpq_t));
+    for (i = 0; i < nrows; i++) mpq_init (y[i]);
+    rval = mpq_QSget_pi_array (p, y);
+    if (rval) {
+        printf("not ok 7 - Could not get dual values, error code %d\n", rval);
+    } else {
+        rownames = (char **) malloc (nrows * sizeof (char *));
+        mpq_QSget_rownames (p, rownames);
+        printf("ok 7 - Obtained dual values and contraint names\n");
+    }
+
+    /* Test 8 - Write problem out to /dev/null */
+    rval = mpq_QSwrite_prob (p, "/dev/null", "LP");
+    if (rval) {
+        printf("not ok 8 - Could not write the LP, error code %d\n", rval);
+    } else {
+        printf("ok 8 - LP written to /dev/null\n");
+    }
+
+CLEANUP:
+
+    if (p) mpq_QSfree_prob (p);  /*  CPXfreeprob  */
+
+    mpq_clear (value);
+    if (x) {
+        for (i = 0; i < ncols; i++) mpq_clear (x[i]);
+        free (x);
+    }
+    if (y) {
+        for (i = 0; i < nrows; i++) mpq_clear (y[i]);
+        free (y);
+    }
+    if (rownames) {
+        for (i = 0; i < nrows; i++) if (rownames[i]) free (rownames[i]);
+        free (rownames);
+    }
+    if (colnames) {
+        for (i = 0; i < ncols; i++) if (colnames[i]) free (colnames[i]);
+        free (colnames);
+    }
+
+    QSexactClear();
+    return rval;
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/qsopt-ex.git



More information about the debian-med-commit mailing list