remove lpsolve
							parent
							
								
									44477e12f2
								
							
						
					
					
						commit
						b39d14872a
					
				|  | @ -1,169 +0,0 @@ | |||
| CC= gcc | ||||
| 
 | ||||
| MINGW_EXTRA = c:/cygwin/mingw | ||||
| MINGW_INCDIR = $(MINGW_EXTRA)/include | ||||
| MINGW_LIBDIR = $(MINGW_EXTRA)/lib | ||||
| 
 | ||||
| AS = as | ||||
| DLLTOOL = dlltool | ||||
| DLLWRAP = dllwrap | ||||
| DLLWRAP_FLAGS = --dlltool-name=$(DLLTOOL) --as=$(AS) --driver-name=$(CC) \
 | ||||
| 		--target=i386-mingw32  | ||||
| 
 | ||||
| DLL_LDFLAGS = -L$(MINGW_LIBDIR) -mno-cygwin -mwindows | ||||
| DLL_LDLIBS = liblpk.a | ||||
| 
 | ||||
| #
 | ||||
| # Beginning of supplied stuff
 | ||||
| #
 | ||||
| 
 | ||||
| #should be OK in most situations:
 | ||||
| #CFLAGS= -O
 | ||||
| 
 | ||||
| # HP/UX 9.0X optimized code
 | ||||
| #CFLAGS= +O3 +Oaggressive +Olibcalls -Aa -D_POSIX_SOURCE -DCHECK +FP VZOUiD
 | ||||
| # HP/UX 9.0X debugging
 | ||||
| #CFLAGS= -g -Aa -D_POSIX_SOURCE -DCHECK +FP VZOUiD
 | ||||
| 
 | ||||
| # nice for gcc
 | ||||
| CFLAGS= -O3 -Wall -pedantic -ansi -mrtd | ||||
| #CFLAGS= -g -Wall -pedantic -ansi
 | ||||
| INCLUDE=-Ibfp -Ibfp/bfp_etaPFI -I. -Icolamd -Ishared | ||||
| CFLAGS= -O3 -Wall -pedantic -ansi -mrtd -mno-cygwin -I$(MINGW_INCDIR)\
 | ||||
| -DINTEGERTIME -DPARSER_LP -DYY_INTERACTIVE -DWIN32 $(INCLUDE) \ | ||||
| -DBUILDING_FOR_R -DWIN32 -g | ||||
| 
 | ||||
| # Option -DCHECK checks for numerical problems during rounding of numbers.
 | ||||
| # It will slow things down a bit.
 | ||||
| # You can add a -DREAL=<float type> to the CFLAGS, to change the default float
 | ||||
| # type used in lp_solve (double) to float or 'long double'. However, type float
 | ||||
| # might be fast on your computer, but it is not accurate enough to solve even
 | ||||
| # moderately sized problems without running into numerical problems.
 | ||||
| # The use of long doubles does increase the numerical stability of lp_solve,
 | ||||
| # if your compiler actually implements them with more bits than a double. But
 | ||||
| # it slows down things quite a bit.
 | ||||
| 
 | ||||
| # Choose your favorite or available version of lex and yacc
 | ||||
| 
 | ||||
| #YACC= yacc
 | ||||
| #especially for linux:
 | ||||
| YACC= bison -y | ||||
| 
 | ||||
| #LEX= lex
 | ||||
| #especially for linux:
 | ||||
| LEX= flex -l | ||||
| 
 | ||||
| #LEXLIB= -ll
 | ||||
| #especially for linux:
 | ||||
| LEXLIB= -lfl | ||||
| 
 | ||||
| #ANSI math lib
 | ||||
| #MATHLIB= -lM
 | ||||
| #non-ANSI math lib, should also work
 | ||||
| MATHLIB= -lm | ||||
| 
 | ||||
| LPKSRC.c= $(wildcard *.c) lp_MDO.c \
 | ||||
| colamd/colamd.c shared/commonlib.c shared/myblas.c | ||||
| 
 | ||||
| LEXFILE.l= lp_rlp.l | ||||
| YACCFILE.y= lp_rlp.y | ||||
| 
 | ||||
| LPKLIB=liblpk.a | ||||
| 
 | ||||
| LEXFILE.c= $(LEXFILE.l:.l=.c) | ||||
| YACCFILE.c= $(YACCFILE.y:.y=.c) | ||||
| YACCFILE.o= $(YACCFILE.y:.y=.o) | ||||
| CSOURCES=$(LEXFILE.c) $(YACCFILE.c) $(wildcard *.c) | ||||
| # commonlib.c fortify.c lp_Hash.c \
 | ||||
| # lp_LUMOD.c lp_MPS.c lp_SOS.c lp_crash.c lp_lib.c lp_matrix.c lp_mipbb.c \
 | ||||
| # lp_presolve.c lp_price.c lp_pricePSE.c lp_report.c lp_rlp.c lp_scale.c \
 | ||||
| # lp_simplex.c lp_solveDLL.c lp_utils.c lp_wlp.c lpslink.c myblas.c \
 | ||||
| # yacc_read.c
 | ||||
| COBJ=$(CSOURCES:.c=.o) | ||||
| LPKSRC= $(LPKSRC.c) $(YACCFILE.c) | ||||
| LPKOBJ= $(LPKSRC:.c=.o) | ||||
| HEADERS=*.h | ||||
| 
 | ||||
| all:	lpslink.dll | ||||
| 
 | ||||
| q8.exe:	q8.o | ||||
| 	$(CC) -o q8.exe $(CFLAGS) \
 | ||||
| --allow-multiple-definition \ | ||||
| q8.o colamd/colamd.o shared/commonlib.o \ | ||||
| fortify.o ini.o \ | ||||
| lp_Hash.o lp_LUSOL.o lp_MDO.o lp_MPS.o lp_SOS.o lp_crash.o lp_lib.o \ | ||||
| lp_matrix.o lp_mipbb.o lp_params.o lp_presolve.o lp_price.o lp_pricePSE.o \ | ||||
| lp_report.o lp_rlp.o lp_scale.o lp_simplex.o lp_utils.o lp_wlp.o lpslink.o \ | ||||
| lusol.o mmio.o shared/myblas.o yacc_read.o \ | ||||
| $(MATHLIB) $(LPKLIB) \ | ||||
| -Wl,--allow-multiple-definition | ||||
| 
 | ||||
| 
 | ||||
| $(COBJ): $(HEADERS) | ||||
| 
 | ||||
| purify: lp_solve.o $(LPKLIB) | ||||
| 	purify $(CC) -o $(TARGET) $(CFLAGS) lp_solve.o $(LPKLIB) $(LEXLIB) $(MATHLIB) | ||||
| 
 | ||||
| quantify: lp_solve.o $(LPKLIB) | ||||
| 	quantify $(CC) -o $(TARGET) $(CFLAGS) lp_solve.o $(LPKLIB) $(LEXLIB) $(MATHLIB) | ||||
| 
 | ||||
| $(LPKLIB): $(LPKOBJ) | ||||
| 	ar rv $@ $(LPKOBJ) | ||||
| 	ranlib $(LPKLIB) | ||||
| 
 | ||||
| $(YACCFILE.o): $(LEXFILE.c) | ||||
| 
 | ||||
| $(LEXFILE.c): $(LEXFILE.l) | ||||
| 	$(LEX) $(LEXFILE.l) | ||||
| 	mv lex.yy.c $(LEXFILE.c) | ||||
| 
 | ||||
| $(YACCFILE.c): $(YACCFILE.y) | ||||
| 	$(YACC) $(YACCFILE.y) | ||||
| 	mv y.tab.c $(YACCFILE.c) | ||||
| 
 | ||||
| # liblpk.def: lpslink.o
 | ||||
| # 	dlltool -z liblpk.def -e exports.o -l liblpk.lib lpslink.o
 | ||||
| lpslink.dll: lpslink.o liblpk.def liblpk.a | ||||
| 	$(DLLWRAP) $(DLLWRAP_FLAGS) -o $@ --def liblpk.def \
 | ||||
| lpslink.o $(DLL_LDFLAGS) $(DLL_LDLIBS)  | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| test: | ||||
| 	-for i in $(TESTFILES1); do\
 | ||||
| 		./$(TARGET) -s -S3 -time < $$i > xxx.tmp;\
 | ||||
| 		if diff xxx.tmp lp_examples/`basename $$i .lp`.out > /dev/null; then\
 | ||||
| 			echo "$$i gives the correct result";\
 | ||||
| 		else\
 | ||||
| 			echo "*** $$i gives different result, please check ***";\
 | ||||
| 		fi;\
 | ||||
| 	done;\
 | ||||
| 	for i in $(TESTFILES2); do\
 | ||||
| 		./$(TARGET) -mps -s -S3 -time < $$i > xxx.tmp;\
 | ||||
| 		if diff xxx.tmp lp_examples/`basename $$i .mps`.out > /dev/null; then\
 | ||||
| 			echo "$$i gives the correct result";\
 | ||||
| 		else\
 | ||||
| 			echo "*** $$i gives different result, please check ***";\
 | ||||
| 		fi;\
 | ||||
| 	done;\
 | ||||
|         rm xxx.tmp | ||||
| 
 | ||||
| mktest: | ||||
| 	-for i in $(TESTFILES1); do\
 | ||||
| 		./$(TARGET) -s -S3 -time < $$i > lp_examples/`basename $$i .lp`.out;\
 | ||||
| 	done;\
 | ||||
| 	for i in $(TESTFILES2); do\
 | ||||
| 		./$(TARGET) -mps -s -S3 -time < $$i > lp_examples/`basename $$i .mps`.out;\
 | ||||
| 	done;\
 | ||||
| 
 | ||||
| $(TARGET).man: $(TARGET).1 | ||||
| 	nroff -man $(TARGET).1 > $(TARGET).man | ||||
| 
 | ||||
| MANIFEST: clean | ||||
| 	ls -lR > MANIFEST; ls -lR > MANIFEST | ||||
| 
 | ||||
| clean: | ||||
| 	rm -f *.a *.o TAGS $(LEXFILE.c) $(YACCFILE.c) demo $(TARGET) lp2mps mps2lp .pure .softdebughist datafile | ||||
| 
 | ||||
| TAGS: | ||||
| 	etags *.[chyl] | ||||
|  | @ -1,83 +0,0 @@ | |||
| #
 | ||||
| # Makefile for building lp_solve using GNU Make
 | ||||
| # Usage:
 | ||||
| #   make -f Makefile.Linux [all | bin | lib | clean]
 | ||||
| #
 | ||||
| # $Revision: 1.1 $
 | ||||
| #
 | ||||
| 
 | ||||
| AR = ar | ||||
| ARFLAGS = rv | ||||
| CC = gcc | ||||
| LEX = flex | ||||
| YACC = bison | ||||
| 
 | ||||
| INCLUDE = -I. -Ibfp -Ibfp/bfp_LUSOL -Ibfp/bfp_LUSOL/LUSOL -Icolamd -Ishared | ||||
| 
 | ||||
| # Uncomment any of the following two depending on your profile
 | ||||
| #DEBUG = -g -pg
 | ||||
| DEBUG = -O2 | ||||
| 
 | ||||
| DEFINE = -DYY_NEVER_INTERACTIVE -DPARSER_LP -DINVERSE_ACTIVE=INVERSE_LUSOL -DRoleIsExternalInvEngine | ||||
| 
 | ||||
| # Uncomment any of the following two depending on how easily compiler messages scare you
 | ||||
| #CFLAGS= $(INCLUDE) $(DEBUG) $(DEFINE) -fpic -Wall -pedantic -trigraphs
 | ||||
| CFLAGS= $(INCLUDE) $(DEBUG) $(DEFINE) -fpic | ||||
| 
 | ||||
| LFLAGS = -L -l | ||||
| YFLAGS = --no-lines -y | ||||
| 
 | ||||
| LDFLAGS = -lm -ldl | ||||
| 
 | ||||
| LUSOLSRC = bfp/bfp_LUSOL/lp_LUSOL.c bfp/bfp_LUSOL/LUSOL/lusol.c | ||||
| LUSOLOBJS = bfp/bfp_LUSOL/lp_LUSOL.o bfp/bfp_LUSOL/LUSOL/lusol.o | ||||
| 
 | ||||
| OBJECTS = $(LUSOLOBJS) lp_MDO.o shared/commonlib.o colamd/colamd.o \
 | ||||
| shared/mmio.o shared/myblas.o ini.o fortify.o lp_rlp.o lp_crash.o  \ | ||||
| lp_Hash.o lp_lib.o lp_wlp.o lp_matrix.o lp_mipbb.o lp_MPS.o	   \ | ||||
| lp_params.o lp_presolve.o lp_price.o lp_pricePSE.o lp_report.o	   \ | ||||
| lp_scale.o lp_simplex.o lp_SOS.o lp_utils.o yacc_read.o | ||||
| 
 | ||||
| SRC = $(LUSOLSRC) lp_MDO.c shared/commonlib.c colamd/colamd.c	   \
 | ||||
| shared/mmio.c shared/myblas.c ini.c fortify.c lp_rlp.c lp_crash.c  \ | ||||
| lp_Hash.c lp_lib.c lp_wlp.c lp_matrix.c lp_mipbb.c lp_MPS.c	   \ | ||||
| lp_params.c lp_presolve.c lp_price.c lp_pricePSE.c lp_report.c	   \ | ||||
| lp_scale.c lp_simplex.c lp_SOS.c lp_utils.c yacc_read.c | ||||
| 
 | ||||
| LIBRARIES = liblpsolve55.a liblpsolve55.so | ||||
| BINARIES = lp_solve demo | ||||
| ALL =  $(BINARIES) $(DEMOS) $(LIBRARIES) | ||||
| .PHONY=clean lp_solve | ||||
| 
 | ||||
| all: $(ALL) | ||||
| lib: $(LIBRARIES) | ||||
| bin: $(BINARIES) | ||||
| objects: $(OBJECTS) | ||||
| 
 | ||||
| lp_rlp.o: lp_rlp.l lp_rlp.y | ||||
| 	$(LEX) $(LFLAGS) lp_rlp.l | ||||
| 	sed -e "s/yy/lp_yy/g" lex.yy.c >lp_rlp.h | ||||
| 	rm -f lex.yy.c | ||||
| 
 | ||||
| 	$(YACC) $(YFLAGS) lp_rlp.y | ||||
| 	sed -e "s/yy/lp_yy/g" y.tab.c >lp_rlp.c | ||||
| 	rm -f y.tab.c | ||||
| 
 | ||||
| 	$(CC) $(CFLAGS) $(DEBUG) $(DEFINE) $(INCLUDE) -c $*.c | ||||
| 
 | ||||
| lp_solve: lp_solve/lp_solve.c $(OBJECTS) | ||||
| 	$(CC) $(CFLAGS) $(DEBUG) $(DEFINE) $(INCLUDE) $< $(OBJECTS) -o lp_solve/lp_solve $(LDFLAGS) | ||||
| 
 | ||||
| demo: demo/demo.c $(OBJECTS) | ||||
| 	$(CC) $(CFLAGS) $(DEBUG) $(DEFINE) $(INCLUDE) $< $(OBJECTS) -o demo/demo $(LDFLAGS) | ||||
| 
 | ||||
| liblpsolve55.a: $(OBJECTS) | ||||
| 	$(AR) $(ARFLAGS) lpsolve55/$@ `echo $(SRC)|sed 's/[.]c/.o/g'` | ||||
| 	ranlib lpsolve55/$@ | ||||
| 
 | ||||
| liblpsolve55.so: $(OBJECTS) | ||||
| 	$(CC) -fpic -shared -Wl,-Bsymbolic -Wl,-soname,$@ -o lpsolve55/$@ `echo $(SRC)|sed 's/[.]c/.o/g'` $(LDFLAGS) | ||||
| 
 | ||||
| clean: | ||||
| 	rm -f $(OBJECTS)  *.so *.a lp_solve/lp_solve demo/demo lpsolve55/*.so lpsolve55/*.a | ||||
| 
 | ||||
|  | @ -1,131 +0,0 @@ | |||
| PACKAGE_NAME=@PACKAGE_NAME@ | ||||
| PACKAGE_STRING=@PACKAGE_NAME@_@PACKAGE_VERSION@ | ||||
| CCSHARED=@CCSHARED@ | ||||
| prefix = @prefix@ | ||||
| includedir = @includedir@/lpsolve | ||||
| libdir = @libdir@ | ||||
| CFLAGS=@CFLAGS@ | ||||
| INCLUDES=-I. -I./shared -I./bfp -I./bfp/bfp_LUSOL -I./bfp/bfp_LUSOL/LUSOL -I./colamd | ||||
| DEFINES=-DYY_NEVER_INTERACTIVE -DPARSER_LP -DINVERSE_ACTIVE=INVERSE_LUSOL -DRoleIsExternalInvEngine @DEF@ | ||||
| LIBS=-lc -lm -ldl | ||||
| INSTALL_DATA = ${INSTALL} -m 644 | ||||
| INSTALL_PROGRAM = ${INSTALL} | ||||
| INSTALL_SCRIPT = ${INSTALL} | ||||
| INSTALL = @INSTALL@ | ||||
| mkdir_p = mkdir -p | ||||
| HEADERS = \
 | ||||
| 	declare.h \
 | ||||
| 	fortify.h \
 | ||||
| 	ini.h	\
 | ||||
| 	lp_crash.h \
 | ||||
| 	lp_explicit.h \
 | ||||
| 	lp_fortify.h \
 | ||||
| 	lp_Hash.h \
 | ||||
| 	lpkit.h \
 | ||||
| 	lp_lib.h \
 | ||||
| 	lp_matrix.h \
 | ||||
| 	lp_MDO.h \
 | ||||
| 	lp_mipbb.h \
 | ||||
| 	lp_MPS.h \
 | ||||
| 	lp_presolve.h \
 | ||||
| 	lp_price.h \
 | ||||
| 	lp_pricePSE.h \
 | ||||
| 	lp_report.h \
 | ||||
| 	lp_rlp.h \
 | ||||
| 	lp_scale.h \
 | ||||
| 	lp_simplex.h \
 | ||||
| 	lp_solveDLL.h \
 | ||||
| 	lpsolve.h \
 | ||||
| 	lp_SOS.h \
 | ||||
| 	lp_types.h \
 | ||||
| 	lp_utils.h \
 | ||||
| 	lp_wlp.h \
 | ||||
| 	ufortify.h \
 | ||||
| 	yacc_read.h | ||||
| 
 | ||||
| SOURCES = lp_MDO.c \
 | ||||
| 	shared/commonlib.c \
 | ||||
| 	shared/mmio.c \
 | ||||
| 	shared/myblas.c \
 | ||||
| 	ini.c \
 | ||||
| 	fortify.c \
 | ||||
| 	colamd/colamd.c \
 | ||||
| 	lp_rlp.c \
 | ||||
| 	lp_crash.c \
 | ||||
| 	bfp/bfp_LUSOL/lp_LUSOL.c \
 | ||||
| 	bfp/bfp_LUSOL/LUSOL/lusol.c \
 | ||||
| 	lp_Hash.c \
 | ||||
| 	lp_lib.c \
 | ||||
| 	lp_wlp.c \
 | ||||
| 	lp_matrix.c \
 | ||||
| 	lp_mipbb.c \
 | ||||
| 	lp_MPS.c \
 | ||||
| 	lp_params.c \
 | ||||
| 	lp_presolve.c \
 | ||||
| 	lp_price.c \
 | ||||
| 	lp_pricePSE.c \
 | ||||
| 	lp_report.c \
 | ||||
| 	lp_scale.c \
 | ||||
| 	lp_simplex.c \
 | ||||
| 	lp_SOS.c \
 | ||||
| 	lp_utils.c \
 | ||||
|         yacc_read.c | ||||
| 
 | ||||
| all: liblpsolve55.a @SHARED_LIB@ | ||||
| 
 | ||||
| # OBJECTS = $(patsubst %.c,%.o,$(SOURCES))
 | ||||
| #.c.o:
 | ||||
| #	$(CC) -s -c $(INCLUDES) $(CFLAGS) $(DEFINES) $(SOURCES)
 | ||||
| 
 | ||||
| liblpsolve55.a: $(SOURCES) | ||||
| 	$(CC) -s -c $(INCLUDES) $(CFLAGS) $(DEFINES) $(SOURCES) | ||||
| 	ar rv $@ `echo $(SOURCES)|sed s/[.]c/.o/g|sed 's/[^ ]*\///g'` | ||||
| 	ranlib $@ | ||||
| 
 | ||||
| liblpsolve55@SO@: $(SOURCES) | ||||
| 	$(CC) $(CCSHARED) -s -c $(INCLUDES) $(CFLAGS) $(DEFINES) $(SOURCES) | ||||
| 	$(CC) -shared -Wl,-Bsymbolic -Wl,-soname,$@ -o $@ `echo $(SOURCES)|sed s/[.]c/.o/g|sed 's/[^ ]*\///g'` $(LIBS) | ||||
| 
 | ||||
| install: install-HEADERS install-LIBRARIES | ||||
| 
 | ||||
| install-HEADERS: $(HEADERS) | ||||
| 	test -d $(includedir) || $(mkdir_p) $(includedir) | ||||
| 	@list='$(HEADERS)'; for p in $$list; do \
 | ||||
| 	  echo " $(INSTALL) $$p $(includedir)/$$f"; \
 | ||||
| 	  $(INSTALL) $$p $(includedir)/$$f; \
 | ||||
| 	done | ||||
| 
 | ||||
| install-LIBRARIES: liblpsolve55.a @SHARED_LIB@ | ||||
| 	test -d $(libdir) || $(mkdir_p) $(libdir) | ||||
| 	@list='liblpsolve55.a @SHARED_LIB@'; for p in $$list; do \
 | ||||
| 	  if test -f $$p; then \
 | ||||
| 	    echo " $(INSTALL) $$p $(libdir)/$$f"; \
 | ||||
| 	    $(INSTALL) $$p $(libdir)/$$f; \
 | ||||
| 	  else :; fi; \
 | ||||
| 	done | ||||
| 
 | ||||
| uninstall-LIBRARIES: | ||||
| 	@set -x; list='liblpsolve55.a @SHARED_LIB@'; for p in $$list; do \
 | ||||
| 	  echo " rm -f $(libdir)/$$f"; \
 | ||||
| 	  rm -f "$(libdir)/$$f"; \
 | ||||
| 	done | ||||
| 
 | ||||
| uninstall: uninstall-HEADERS uninstall-LIBRARIES | ||||
| 
 | ||||
| uninstall-HEADERS: | ||||
| 	@set -x; @list=$(HEADERS); for p in $$list; do \
 | ||||
| 	  echo " rm -f $(includedir)/$$f"; \
 | ||||
| 	  rm -f "$(includedir)/$$f"; \
 | ||||
| 	done | ||||
| 
 | ||||
| dist:  | ||||
| 	mkdir $(PACKAGE_STRING) | ||||
| 	tar -cpf- -T MANIFEST | (cd  $(PACKAGE_STRING) && tar -xpf- ) | ||||
| 	tar -czpf $(PACKAGE_STRING).tar.bz2 ./$(PACKAGE_STRING) | ||||
| 	-rm -fr $(PACKAGE_STRING) | ||||
| 
 | ||||
| CLEANFILES = *.o *.so *.a | ||||
| clean: | ||||
| 	-rm -f $(CLEANFILES) | ||||
| 
 | ||||
| .PHONY: install install-HEADERS install-LIBRARIES uninstall uninstall-HEADERS uninstall-LIBRARIES all | ||||
|  | @ -1,89 +0,0 @@ | |||
| #
 | ||||
| # Makefile for building lp_solve using GNU Make
 | ||||
| # Usage:
 | ||||
| #   gmake -f Makefile.msc [all | bin | lib | clean]
 | ||||
| #
 | ||||
| # $Revision: 1.1 $
 | ||||
| #
 | ||||
| 
 | ||||
| AR = ar | ||||
| ARFLAGS = rv | ||||
| CC = cl | ||||
| LEX = flex | ||||
| YACC = bison | ||||
| 
 | ||||
| INC = -I. -Ibfp -Ibfp/bfp_LUSOL -Ibfp/bfp_LUSOL/LUSOL -Icolamd -Ishared | ||||
| 
 | ||||
| # Uncomment any of the following two depending on your profile
 | ||||
| #DEBUG = -g -pg
 | ||||
| DEBUG = /ML /O1 /Zp8 /Gd /W2 /DWIN32 /D_WINDOWS | ||||
| 
 | ||||
| DEFINE = -DNoParanoia -DWIN32 -DYY_NEVER_INTERACTIVE -DPARSER_LP -DINVERSE_ACTIVE=INVERSE_LUSOL -DRoleIsExternalInvEngine | ||||
| 
 | ||||
| # Uncomment any of the following two depending on how easily compiler messages scare you
 | ||||
| CFLAGS= $(INC) $(DEBUG) $(DEFINE) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE | ||||
| 
 | ||||
| LFLAGS = -L -l | ||||
| YFLAGS = --no-lines -y | ||||
| 
 | ||||
| LDFLAGS = | ||||
| 
 | ||||
| LUSOLSRC = bfp/bfp_LUSOL/lp_LUSOL.c bfp/bfp_LUSOL/LUSOL/lusol.c | ||||
| LUSOLOBJS = bfp/bfp_LUSOL/lp_LUSOL.obj bfp/bfp_LUSOL/LUSOL/lusol.obj | ||||
| 
 | ||||
| OBJECTS = $(LUSOLOBJS) lp_MDO.obj shared/commonlib.obj colamd/colamd.obj \
 | ||||
| shared/mmio.obj shared/myblas.obj ini.obj fortify.obj lp_rlp.obj lp_crash.obj  \ | ||||
| lp_Hash.obj lp_lib.obj lp_wlp.obj lp_matrix.obj lp_mipbb.obj lp_MPS.obj	       \ | ||||
| lp_params.obj lp_presolve.obj lp_price.obj lp_pricePSE.obj lp_report.obj     \ | ||||
| lp_scale.obj lp_simplex.obj lp_SOS.obj lp_utils.obj yacc_read.obj | ||||
| 
 | ||||
| SRC = $(LUSOLSRC) lp_MDO.c shared/commonlib.c colamd/colamd.c	   \
 | ||||
| shared/mmio.c shared/myblas.c ini.c fortify.c lp_rlp.c lp_crash.c  \ | ||||
| lp_Hash.c lp_lib.c lp_wlp.c lp_matrix.c lp_mipbb.c lp_MPS.c	   \ | ||||
| lp_params.c lp_presolve.c lp_price.c lp_pricePSE.c lp_report.c	   \ | ||||
| lp_scale.c lp_simplex.c lp_SOS.c lp_utils.c yacc_read.c | ||||
| 
 | ||||
| #LIBRARIES = liblpsolve55.lib liblpsolve55d.lib lpsolve55.dll
 | ||||
| LIBRARIES = | ||||
| #BINARIES = lp_solve.exe demo.exe
 | ||||
| BINARIES = lp_solve.exe | ||||
| ALL =  $(BINARIES) $(DEMOS) $(LIBRARIES) | ||||
| .PHONY=clean lp_solve | ||||
| 
 | ||||
| all: $(ALL) | ||||
| lib: $(LIBRARIES) | ||||
| bin: $(BINARIES) | ||||
| objects: $(OBJECTS) | ||||
| 
 | ||||
| $(OBJECTS): $(SRC) | ||||
| 	$(CC) -c $(CFLAGS) $(SRC) | ||||
| 
 | ||||
| lp_rlp.c: lp_rlp.l lp_rlp.y | ||||
| 	$(LEX) $(LFLAGS) lp_rlp.l | ||||
| 	sed -e "s/yy/lp_yy/g" lex.yy.c >lp_rlp.h | ||||
| 	rm -f lex.yy.c | ||||
| 
 | ||||
| 	$(YACC) $(YFLAGS) lp_rlp.y | ||||
| 	sed -e "s/yy/lp_yy/g" y.tab.c >lp_rlp.c | ||||
| 	rm -f y.tab.c | ||||
| 
 | ||||
| 	$(CC) $(CFLAGS) $(DEBUG) $(DEFINE) $(INC) -c $*.c | ||||
| 
 | ||||
| lp_solve.exe: lp_solve/lp_solve.c $(OBJECTS) | ||||
| 	$(CC) $(CFLAGS) $(DEBUG) $(DEFINE) $(INC) $< $(OBJECTS) -Felp_solve/lp_solve $(LDFLAGS) | ||||
| 
 | ||||
| demo.exe: demo/demo.c $(OBJECTS) | ||||
| 	$(CC) $(CFLAGS) $(DEBUG) $(DEFINE) $(INC) $< $(OBJECTS) -Fedemo/demo $(LDFLAGS) | ||||
| 
 | ||||
| lpsolve.res: lpsolve.rc | ||||
| 	$(RC) lpsolve.rc | ||||
| 
 | ||||
| liblpsolve55.lib: $(OBJECTS) | ||||
| 	$(LIB) *.obj /OUT:lpsolve55/$@ | ||||
| 
 | ||||
| lpsolve55.dll: $(OBJECTS) | ||||
| 	$(CC) -fpic -shared -Wl,-Bsymbolic -Wl,-soname,$@ -o lpsolve55/$@ `echo $(SRC)|sed 's/[.]c/.obj/g'` $(LDFLAGS) | ||||
| 
 | ||||
| clean: | ||||
| 	rm -f $(OBJECTS)  *.lib *.dll lp_solve/lp_solve.exe demo/demo.exe lpsolve55/*.dll lpsolve55/*.lib | ||||
| 
 | ||||
|  | @ -1,344 +0,0 @@ | |||
| Introduction | ||||
| ------------ | ||||
| What is lp_solve and what is it not? | ||||
| The simple answer is, lp_solve is a Mixed Integer Linear Programming (MILP) solver. | ||||
| 
 | ||||
| It is a free (see LGPL for the GNU lesser general public license) linear (integer) programming solver | ||||
| based on the revised simplex method and the Branch-and-bound method for the integers. | ||||
| It contains full source, examples and manuals. | ||||
| lp_solve solves pure linear, (mixed) integer/binary, semi-continuous and | ||||
| special ordered sets (SOS) models. | ||||
| 
 | ||||
| See the reference guide for more information. | ||||
| 
 | ||||
| 
 | ||||
| lp_solve 5.5 | ||||
| ------------ | ||||
| 
 | ||||
| Why a jump from version numbers 5.1 to 5.5 ? | ||||
| This is done to indicate that this is more than just another update. | ||||
| The solver engine was revised and optimised in such a way that performance has improved considerably. | ||||
| Numerical stability is also better resulting in more models that can be solved. | ||||
| The LUSOL bfp is now also the default. In the past, the etaPFI bfp package was the default, | ||||
| but for larger models this leads faster to numerical instabilities and performance problems. | ||||
| 
 | ||||
| Overall, the v5.5 code is faster and more robust than v5.1. | ||||
| This robustness is for example proven by the fact that many more models can now be solved even without scaling. | ||||
| 
 | ||||
| The API hasn't changed very much. | ||||
| There are a couple of new routines and one routine has an extra argument. | ||||
| Some constants got new values. | ||||
| 
 | ||||
|     * Fundamental internal change to the solver engine resulting in better performance and numerical stability. | ||||
|       Both the LP solver and the B&B solvers are enhanced. | ||||
|     * Optimised MILP branch truncation, with reduced cost fixing. | ||||
|     * LUSOL bfp is now the default. | ||||
|     * Presolve is improved in functionality and performance. | ||||
|     * Better handling of degeneracy, with more options. | ||||
|     * Store and read options from a file make it easier to set options. | ||||
|     * Partial pricing for the primal simplex now works. | ||||
|     * Full support for xli_ZIMPL v2.0.3. | ||||
|     * The objective function is no longer stored as part of the constraint matrix. | ||||
|     * Dual-long step code is in place, but not fully activated yet. | ||||
|     * General code cleanup. | ||||
|     * Added OBJSENSE and OBJNAME headers in the free MPS format (See MPS file format). | ||||
|     * The MathProg xli driver has now the ability to generate a model. | ||||
|     * New API routines | ||||
| 
 | ||||
| Start by taking a look at 'Changes compared to version 4', 'Changes from version 5.1 to version 5.5' | ||||
| and 'lp_solve usage' | ||||
| This gives a good starting point. | ||||
| 
 | ||||
| 
 | ||||
| BFP's | ||||
| ----- | ||||
| 
 | ||||
| BFP stands for Basis Factorization Package, which is a unique lp_solve feature.  Considerable | ||||
| effort has been put in this new feature and we have big expectations for this. BFP is a generic | ||||
| interface model and users can develop their own implementations based on the provided templates. | ||||
| We are very interested in providing as many different BFPs as possible to the community. | ||||
| 
 | ||||
| lp_solve 5.5 has the LUSOL BFP built in as default engine.  In addition two other | ||||
| BFPs are included for both Windows and Linux: bfp_etaPFI.dll, bfp_GLPK.dll for Windows and | ||||
| libbfp_etaPFI.so, libbfp_GLPK.so for Linux.  The bfp_etaPFI includes | ||||
| advanced column ordering using the COLAMD library, as well as better pivot management for | ||||
| stability.  For complex models, however, the LU factorization approach is much better, and | ||||
| lp_solve now includes LUSOL as one of the most stable engines available anywhere.  LUSOL was | ||||
| originally developed by Prof. Saunders at Stanford, and it has now been ported to C | ||||
| and enhanced by Kjell. | ||||
| 
 | ||||
| If you compile BFPs yourself, make sure that under Windows, you use __stdcall convention and | ||||
| use 8 byte alignments.  This is needed for the BFPs to work correctly with the general | ||||
| distribution of lp_solve and also to make sharing BFPs as uncomplicated as possible. | ||||
| 
 | ||||
| See the reference guide for more information. | ||||
| 
 | ||||
| 
 | ||||
| XLI's | ||||
| ----- | ||||
| 
 | ||||
| XLI stands for eXternal Language Interface, also a unique lp_solve feature. XLI's are stand-alone | ||||
| libraries used as add-on to lp_solve to make it possible to read and write lp models in a format | ||||
| not natively supported by lp_solve. Examples are CPLEX lp format, LINDO lp format, MathProg format, | ||||
| XML format... | ||||
| 
 | ||||
| See the reference guide for more information. | ||||
| 
 | ||||
| 
 | ||||
| lpsolve API | ||||
| ----------- | ||||
| 
 | ||||
| Don't forget that the API has changed compared to previous versions of lpsolve and that you just | ||||
| can't use the version 5 lpsolve library with your version 4 or older code.  That is also the | ||||
| reason why the library is now called lpsolve55.dll/lpsolve55.a.  lpsolve55.dll or lpsolve55.a are | ||||
| only needed when you call the lpsolve library via the API interface from your program. | ||||
| The lp_solve program is still a stand-alone executable program. | ||||
| 
 | ||||
| There are examples interfaces for different language like C, VB, C#, VB.NET, Java, | ||||
| Delphi, and there is now also even a COM object to access the lpsolve library.  This means that | ||||
| the door is wide-open for using lp_solve in many different situations.  Thus everything that is | ||||
| available in version 4 is now also available in version 5 and already much more! | ||||
| 
 | ||||
| See the reference guide for more information. | ||||
| 
 | ||||
| 
 | ||||
| Conversion between lp modeling formats | ||||
| -------------------------------------- | ||||
| 
 | ||||
| Note that lp2mps and mps2lp don't exist anymore. However this functionality is now implemented | ||||
| in lp_solve: | ||||
| 
 | ||||
| lp2mps can be simulated as following: | ||||
| lp_solve -parse_only -lp infile -wmps outfile | ||||
| 
 | ||||
| mps2lp can be simulated as following: | ||||
| lp_solve -parse_only -mps infile -wlp outfile | ||||
| 
 | ||||
| 
 | ||||
| via the -rxli option, a model can be read via an XLI library and via the -wxli option, a model | ||||
| can be written via an XLI library. | ||||
| 
 | ||||
| 
 | ||||
| How to build the executables yourself. | ||||
| --------------------------------------- | ||||
| 
 | ||||
| At this time, there are no Makefiles yet. However for the time being, there are batch files/scripts | ||||
| to build. For the Microsoft compiler under Windows, use cvc6.bat, for the gnu compiler under Windows, | ||||
| use cgcc.bat and for Unix/Linux, use the ccc shell script (sh ccc). | ||||
| 
 | ||||
| See the reference guide for more information. | ||||
| 
 | ||||
| 
 | ||||
| IDE | ||||
| --- | ||||
| 
 | ||||
| Under Windows, there is now also a very user friendly lpsolve IDE. Check out LPSolveIDE | ||||
| 
 | ||||
| See the reference guide for more information. | ||||
| 
 | ||||
| 
 | ||||
| Documentation (reference guide) | ||||
| ------------------------------- | ||||
| 
 | ||||
| See lp_solve55.chm for a Windows HTML help documentation file. | ||||
| The html files are also in lp_solve_5.5_doc.tar.gz. Start with index.htm | ||||
| Also see http://lpsolve.sourceforge.net/ for a on-line documentation | ||||
| 
 | ||||
| 
 | ||||
| Change history: | ||||
| --------------- | ||||
| 
 | ||||
| 17/05/05 version 5.5.0.0 | ||||
| - Beta release of version 5.5 | ||||
| 
 | ||||
| ??/??/05 version 5.5.0.1 | ||||
| - ? | ||||
| 
 | ||||
| 26/06/05 version 5.5.0.2 | ||||
| - ? | ||||
| 
 | ||||
| 29/06/05 version 5.5.0.3 | ||||
| - ? | ||||
| 
 | ||||
| 16/08/05 version 5.5.0.4 | ||||
| - There are no API changes | ||||
| - The LUSOL message routine could generate a crash under some cicumstances. Fixed | ||||
| - A crash could occur when building the model in add_row_mode. Fixed. | ||||
| - write_params didn't write the PRESOLVE and PRESOLVELOOPS correctly. Fixed. | ||||
| - write_params didn't write constants with value 0. Fixed. | ||||
| - The library did not compile under msdev 2002 (VC 7.0 _MSC_VER 1300). Fixed. | ||||
| - There were some problems with printing long long variables which could generate a crash. Fixed. | ||||
| - An overflow error could occur because memory was sometimes overwritten. Fixed. | ||||
| - Presolve routines are revised. They are again improved and made faster. | ||||
|   Also some problems with it are fixed (possible crashes). | ||||
| - Solver revised. Again made faster and more stable. | ||||
| - get_row/get_column returned FALSE if the row/column is empty. Fixed. | ||||
| - get_rowex/get_columnex now returns -1 if and error is detected. This instead of 0. | ||||
|   This to know the distinction between an empty row/column and an error. | ||||
| - set_bounds had a possible problem when min and max are equal. Fixed. | ||||
| - A crash/damage error could occur when rows/columns are added after a solve. Fixed. | ||||
| - The my_chsign macro in lp_types.h gave warnings with some compilers. Fixed. | ||||
| - The lp_solve program now returns 255 if an unexpected error occurs. Before this was 1 | ||||
|   But this interferes with the lpsolve library return codes. | ||||
| - With the lp_solve program, debug and print modes were not written correctly in a | ||||
|   specified parameter file. Fixed. | ||||
| - With the lp_solve program, presolveloops was not set correctly. Fixed. | ||||
| 
 | ||||
| 17/09/05 version 5.5.0.5 | ||||
| - In some cases, SOS restrictions were not optimized till optimality. Fixed. | ||||
| - Presolve sometimes generated 'Column -xxx out of range during presolve' with a possible crash. | ||||
| - Presolve sometimes removed integer and/or semi-cont variables that should not be deleted. Fixed. | ||||
| - B&B sometimes didn't find the most optimal solution. Fixed. | ||||
| - Internal constant COMP_EQUAL renamed to COMP_PREFERNONE because this could interfere with a define | ||||
|   in the standard header files. | ||||
| - The lp parser had problems with variables starting with INF and there is a + or - sign just before it. | ||||
|   Fixed. | ||||
| - Added options -presolvem, -presolvefd, -presolvebnd, -presolved, -presolveslk | ||||
| - Updated documentation. put_bb_branchfunc, put_bb_nodefunc, set_epslevel, dualize_lp, set_basisvar | ||||
| 
 | ||||
| 16/11/05 version 5.5.0.6 | ||||
| - set_add_rowmode should not be called after a solve. There is now a test in this routine when this is | ||||
|   done and it then returns FALSE. | ||||
| - When an empty string ("") as filename is provided to set_outputfile, then output is completely | ||||
|   ignored. | ||||
| - In some cases, SOS models did not solve to their most optimal solution. | ||||
| - There was as problem with get_sensitivity_objex. Calling it (sometimes only after multiple times) | ||||
|   resulted in protection errors/core dumps. | ||||
| - When a model has no constraints, it did not solve most of the times. | ||||
| - column_in_lp didn't work anymore. | ||||
| - Large upper bounds could make the model unstable. A change was made to fix this. | ||||
| - set_improve could let crash the model. | ||||
| - lp_params.c used the non-ANSI function unlink(). Changed to ANSI function remove(). | ||||
| - Presolve is again revised considerably. | ||||
| - SOS handling is improved when there are a lot of SOS constraints. | ||||
| - Limited constraint-to-SOS1 presolve to constraints with at least 4 variables. | ||||
| - Limited bound tightening presolve loops. | ||||
| 
 | ||||
| 12/02/06 version 5.5.0.7 | ||||
| - When SOS restrictions are added after a previous solve, a crash could occur. | ||||
| - Optimized renaming a variable when the new name is equal to the old name. | ||||
| - A possible crash could occur when presolve was enabled | ||||
| - The constant ANTIDEGEN_DEFAULT is changed. ANTIDEGEN_INFEASIBLE is removed from it. | ||||
|   This constant should not be used unless you have some very tight and hard to solve | ||||
|   models where the optimal solution numerically straddles infeasibility. | ||||
| - There was a possible problem with set_row(ex). It sometimes wrongfully changed the row. | ||||
| - When integer variables were scaled, it could happen that because of rounding errors, | ||||
|   a loop was created. | ||||
| - Sometimes integer models kept on looping in the B&B algorithm. | ||||
| - A memory overrun could occur when an initial basis is set. This when variable names | ||||
|   are in Rnnn format and constraint names in Cnnn format. | ||||
| - Some fixes are made in presolve. | ||||
| - On 64-bit systems, compiler warnings were given and some code worked wrong resulting in | ||||
|   wrong results. | ||||
| - lp_solve.c didn't compile with some compilers because if a very deep nested if statement. | ||||
| - The distributed files now have the version number include in the filename. | ||||
|   For example lp_solve_5.5.0.7_exe.zip | ||||
|   This for a possible move to SourceForge in the (near?) future. | ||||
| - When illegal bounds are specified in the MPS format (lower bound larger than upper bound) | ||||
|   then a warning was given but the illegal bound was just ignored and the model was solved. | ||||
|   This resulted in a solution that did not comply to the original model. Now the message is | ||||
|   seen as an error and solving is aborted. | ||||
| 
 | ||||
| 
 | ||||
| 06/09/06 version 5.5.0.8 | ||||
| - When presolve is active and columns are removed and there are SOS constraints, then presolve | ||||
|   had an error which could result in hanging while solve or maybe wrong solutions. | ||||
| - set_row(ex) set wrong values when used after a previous solve and scaling is active. | ||||
| - disabled PRESOLVE_REDUCEMIP since it is very rare that this is effective, and also that it adds | ||||
|   code complications and delayed presolve effects that are not captured properly. | ||||
| - made routine guess_basis available for all languages (now exported by the dll). | ||||
|   The routine is now also documented. | ||||
| - some bug corrections in guess_basis. | ||||
| - Corrected a problem with add_column(ex) when add_rowmode is enabled. | ||||
| - write_lp now wraps long lines over multiple lines to make it more readable. | ||||
| - A compilation warning/error sometimes occured on is_fixedvar in lp_lusol.c with some compilers. | ||||
| - Added options -wxlisol and -wxlisolopt to lp_solve program to write a solution file for those | ||||
|   XLIs that support it. | ||||
| - Updated CPLEX XLI to support constants in objective. | ||||
| - Added documentation on infeasible models, guess_basis, DIMACS models, CPLEX format, Zimpl, GNU Mathprog. | ||||
|   Corrected/updated documentation on get_col_name, get_row_name, get_nameindex, write_xli, | ||||
|   External Language Interfaces. | ||||
| - The mps reader was improved for the rarely cases where the same elements are provided multiple | ||||
|   times. These are now added. | ||||
| - Revised the java unittest example because it gave some errors that it shouldn't give. | ||||
| 
 | ||||
| 07/10/06 version 5.5.0.9 | ||||
| - set_row(ex) could sometimes set wrong values in the model. | ||||
| - Sometimes models with semi-cont variables which are also integer and scaling is active, a solution | ||||
|   was returned that is not most optimal or it returns infeasible. | ||||
| - write_mps didn't write semi-cont variables with an infinite upper bound. | ||||
| - When presolve can solve the model on its own and objective direction is maximize then a wrong sign | ||||
|   was shown in the reported price on screen. | ||||
| - write_lp writes constraint and bounds in the same way if a constraint is not named. If a constraint | ||||
|   only has one variable then it looks like a bound. This can give problems because when a constraint | ||||
|   is interpreted as bound and it is negative then the problem definition changes. | ||||
|   Therefore a constraint which is not named and having only one variable in it is getting a name to | ||||
|   make sure it is interpreted as a constraint. | ||||
| - The lp_solve program didn't interprete the PRESOLVED solve return code very well. Fixed. | ||||
| - bfp_GLPK and xli_MathProg are now compiled against GLPK 4.11 | ||||
| - When an integer model is aborted before the most optimal solution is found (timeout or | ||||
|   break at first, ...) solve returned OPTIMAL (0) instead of SUBOPTIMAL (1). This is now corrected. | ||||
| 
 | ||||
| 14/01/07 version 5.5.0.10 | ||||
| - If a model has integer variables, but the model is already integer optimal in the simplex fase, | ||||
|   then it was reported as suboptimal feasible. | ||||
| - get_objective, get_variables, get_ptr_variables, get_constraints, get_ptr_constraints, get_primal_solution | ||||
|   reported 'not a valid basis' when presolve is active and the model is entirely solved by presolve. | ||||
| - presolve on a model with SOS variables sometimes went wrong. | ||||
| - presolve on a model with SOS variables where infeasibility is detected crashed. | ||||
| - read_bas could fail when not all constraints had names or had names like default variable names. | ||||
| - A crash could occur with set_row(ex) in rowmode. | ||||
| - The lp format has been extended with a free section to define free variables. | ||||
| - bfp_GLPK and xli_MathProg are now compiled against GLPK 4.13 | ||||
| - fixed bug in the pseudocost logic that can blow up subsequent pseudocost values in that | ||||
|   branch and make them almost random. | ||||
| - In some rare cases a memory overrun could occur when constraints are added after a previous solve. | ||||
| - Made the copy_lp routine work. Note that information about the optimisation of the original model | ||||
|   is not copied (at this time). Only the model is. | ||||
| - Fixed a bug in the hashing routines that had only influence in some rare cases in the | ||||
|   MATLAB, O-Matrix, Scilab, Octave, Python drivers. | ||||
| - coldual sometimes worked on a uninitialised variable value with unpredictable results. | ||||
| 
 | ||||
| 27/12/07 version 5.5.0.11 | ||||
| - Fixed a problem in presolve. Sometimes an array-index-out-of-bounds error occured. | ||||
| - Added a makefile for Linux. | ||||
| - When adding constraints, in some rare cases a memory overrun could occur resulting in a crash. | ||||
| - add_constraintex with count=0 and row=colno=NULL gave a protection error. | ||||
|   several XLIs didn't work anymore because of this. | ||||
| - set_constr_type sometimes set wrong signs for the coefficient matrix when add_rowmode is on. | ||||
| - presolve did an unnecessary extra loop. Also a test is added to stop presolve when very few | ||||
|   changes are done. | ||||
| - for very large models, a request of much more memory than is reasonable could occur. Fixed. | ||||
| - Modified LINDO XLI to read keywords also not at column 1 and to accept an empty objective function. | ||||
|   Previously this wat not possible. | ||||
| - In some rare cases, numbers very close to their integer values (for example 11276.999999999998) | ||||
|   were truncated to their ceiling value (for example 11276) instead of rounded | ||||
|   (for example 11277). | ||||
| - Solved a problem with presolve with an all-int constraint. | ||||
| - Solved a problem with presolve coldominate | ||||
| - Added stronger checking of the MPS format. | ||||
|   Fields that must be blank are now also tested accordingly so that if data is there that it is | ||||
|   not ignored as before. | ||||
| - FREE MPS format was not read ok if row/column name were all numbers | ||||
|   or a FR, MI, PL, BV bound was defined. Fixed. | ||||
| - The lp-format now also supports a bin(ary) section to define binary variables. | ||||
| - When an integer model is aborted before the most optimal solution is found | ||||
|   via break at first or break at value, solve returned OPTIMAL (0) instead of SUBOPTIMAL (1). | ||||
|   This is now corrected. Problem occured in version 5.5.0.10 | ||||
| - Fixed a problem with del_constraint. Constraints names were not shifted and reported variable result was incorrect. | ||||
| - read_XLI failed with MathProg if datamodel was provided with "" when there is no datamodel. | ||||
|   NULL was expected in the past. "" is now also accepted. | ||||
| - Added an XLI to read Xpress lp files. | ||||
| - Added routines MPS_writefileex, write_lpex. | ||||
| - Added options -o0, -o1 to lp_solve command driven program to specify if objective is in basis or not. | ||||
| - Added new information in the reference guide: | ||||
|    - Linear programming basics | ||||
|    - Presolve | ||||
|    - Xpress lp files | ||||
| 
 | ||||
| We are thrilled to hear from you and your experiences with this new version. The good and the bad. | ||||
| Also we would be pleased to hear about your experiences with the different BFPs on your models. | ||||
| 
 | ||||
| Please send reactions to: | ||||
| Peter Notebaert: lpsolve@peno.be | ||||
| Kjell Eikland: kjell.eikland@broadpark.no | ||||
|  | @ -1,6 +0,0 @@ | |||
|          1         1 -0.12264700E+04 | ||||
|          1         2  0.82867600E+01 | ||||
|          2         3  0.62150700E+01 | ||||
|          2         1  0.19468000E+03 | ||||
|          3         2 -0.23990100E+04 | ||||
|          3         3 -0.32849100E+04 | ||||
|  | @ -1,89 +0,0 @@ | |||
|             Notes for Contribution of LUSOL to COIN-OR | ||||
|                             May 2004 | ||||
| 
 | ||||
| Introduction | ||||
| ============ | ||||
| 
 | ||||
| LUSOL maintains sparse LU factors of a square or rectangular sparse matrix.  It includes a Basis Factorization Package (BFP) suitable for implementing simplex and reduced-gradient methods for optimization.  It is a set of  routines written in ANSI C (adapted from the original Fortran 77 version). | ||||
| 
 | ||||
| LUSOL includes the following features: | ||||
| 
 | ||||
| -  A Markowitz-based sparse LU factorization for square, | ||||
|    rectangular and possibly singular matrices. | ||||
| 
 | ||||
| -  Three options for balancing sparsity and stability: | ||||
|    Threshold Partial/Rook/Complete Pivoting (TPP, TRP, TCP). | ||||
| 
 | ||||
| -  Rank-revealing properties.  TRP and TCP are intended for detecting singularities. | ||||
| 
 | ||||
| -  Dynamic storage allocation (C version only). | ||||
| 
 | ||||
| -  Stable column replacement as in the method of Bartels and Golub. | ||||
| 
 | ||||
| -  Other stable updates: add, replace, or delete row or column | ||||
|    (currently F77 version only). | ||||
| 
 | ||||
| -  Implementation into an easy-to-use BFP API (C version only). | ||||
| 
 | ||||
| 
 | ||||
| Implementation | ||||
| ============== | ||||
| 
 | ||||
| The Factor routine is similar to the classical Markowitz routines MA28 and LA05 in the Harwell Subroutine Library. The source matrix nonzeros are stored column-wise with the largest entry at the top of each column.  Internally, the structure is also accessible row-wise.  All entries in a particular column or row are held in contiguous storage.  Fill is accommodated by moving a column or row to the beginning of free storage. Occasional compressions recover storage.  This scheme is effective for column-oriented TPP.  When the remaining matrix reaches a specified density, the factors are completed using dense processing. | ||||
| 
 | ||||
| TRP uses an additional vector of storage to maintain the largest element in each remaining row. | ||||
| 
 | ||||
| TCP uses a heap structure to hold the largest element in each column.  The largest element in the remaining matrix is then available at the top of the heap. | ||||
| 
 | ||||
| The final L is stored column-wise (and never changed).  The final U is stored row-wise as a triangular or trapezoidal sparse matrix. | ||||
| 
 | ||||
| Column replacements are implemented using a forward sweep of 2-by-2 stabilized elimination matrices.  L is updated in product form.  U is updated explicitly. | ||||
| 
 | ||||
| The other updates use either forward or backward sweeps. They tend to generate more nonzeros than column replacement. | ||||
| 
 | ||||
| Both the F77 and C versions contain extensive comments, method and implementational information as part of the code. | ||||
| 
 | ||||
| The C version contains a record-based wrapper for the data.  Function calls have been simplified by including references to this structure.  New maintenance routines enable dynamic instance creation and destruction, and  simplifies access to the most frequently used functions.  The LUSOL C library is multi-instance and fully re-entrant.  All control and output parameters have been given long descriptive names for usability.  | ||||
| 
 | ||||
| 
 | ||||
| Benefits | ||||
| ======== | ||||
| 
 | ||||
| Rank-revealing properties and rectangular factors (and updates) have not previously been available in sparse LU software.  With sensible parameter settings and reasonably scaled data, all routines are numerically stable.  The updates may be called hundreds of times, and the decision to refactorize can be based on sparsity considerations alone. | ||||
| 
 | ||||
| In the Factor routine, rook pivoting (TRP) gives reliable rank determination without catastrophic degradation in sparsity or speed.  Complete pivoting (TCP) is included for moderate-sized matrices and for checking pathological cases (but the factors tend to be substantially more dense). | ||||
| 
 | ||||
| To conserve storage, one may request only the row and column pivot orders.  The factors are discarded as they are computed.  This is useful for basis repair, or for selecting a basis from a rectangular matrix. | ||||
| 
 | ||||
| 
 | ||||
| Known Inefficiencies | ||||
| ==================== | ||||
| 
 | ||||
| LUSOL is usually efficient on sparse matrices with dimensions up to about 100,000 (but not millions). | ||||
| 
 | ||||
| In the Factor routine, row and column lists must be updated each time a row and column is eliminated.  Deleting the pivot row and column is inefficient if the original matrix contains unusually dense rows or columns.  For TPP, dense columns could be kept aside and incorporated at the end via updates (but dense rows remain a difficulty).  For TRP and TCP, all rows and columns must be present to achieve the required numerical properties. | ||||
| 
 | ||||
| For TRP, the current bottleneck is updating the vector containing the largest element in each row.  One solution would be to include the matrix nonzeros in the row structure (but this carries its own cost). | ||||
| 
 | ||||
| For TCP, the heap structure is already efficient, but the dense factors (and the extended searching for acceptable pivots) are unavoidable expenses. | ||||
| 
 | ||||
| The triangular Solve routines do not take full of advantage of sparse right-hand sides.  Gilbert and Peierls have shown how to solve Lx = (sparse b) efficiently if L is stored column-wise.  Their approach could therefore be implemented in LUSOL for solves with L and U(transpose).  Solves with L(transpose) and U would need a second copy of L and U.  | ||||
| 
 | ||||
| 
 | ||||
| Original Reference | ||||
| ================== | ||||
| 
 | ||||
| P. E. Gill, W. Murray, M. A. Saunders and M. H. Wright, Maintaining LU factors of a general sparse matrix, Linear Algebra and its Applications 88/89, 239-270 (1987). | ||||
| 
 | ||||
| 
 | ||||
| Maintainers | ||||
| =========== | ||||
| 
 | ||||
| F77 version: Michael Saunders (saunders@stanford.edu). | ||||
| C version: Kjell Eikland (kjell.eikland@broadpark.no). | ||||
| 
 | ||||
| 
 | ||||
| Contributors | ||||
| ============ | ||||
| 
 | ||||
| Philip Gill, Walter Murray, Margaret Wright, Michael O'Sullivan. | ||||
|  | @ -1,504 +0,0 @@ | |||
| 		  GNU LESSER GENERAL PUBLIC LICENSE | ||||
| 		       Version 2.1, February 1999 | ||||
| 
 | ||||
|  Copyright (C) 1991, 1999 Free Software Foundation, Inc. | ||||
|      59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  Everyone is permitted to copy and distribute verbatim copies | ||||
|  of this license document, but changing it is not allowed. | ||||
| 
 | ||||
| [This is the first released version of the Lesser GPL.  It also counts | ||||
|  as the successor of the GNU Library Public License, version 2, hence | ||||
|  the version number 2.1.] | ||||
| 
 | ||||
| 			    Preamble | ||||
| 
 | ||||
|   The licenses for most software are designed to take away your | ||||
| freedom to share and change it.  By contrast, the GNU General Public | ||||
| Licenses are intended to guarantee your freedom to share and change | ||||
| free software--to make sure the software is free for all its users. | ||||
| 
 | ||||
|   This license, the Lesser General Public License, applies to some | ||||
| specially designated software packages--typically libraries--of the | ||||
| Free Software Foundation and other authors who decide to use it.  You | ||||
| can use it too, but we suggest you first think carefully about whether | ||||
| this license or the ordinary General Public License is the better | ||||
| strategy to use in any particular case, based on the explanations below. | ||||
| 
 | ||||
|   When we speak of free software, we are referring to freedom of use, | ||||
| 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 this service if you wish); that you receive source code or can get | ||||
| it if you want it; that you can change the software and use pieces of | ||||
| it in new free programs; and that you are informed that you can do | ||||
| these things. | ||||
| 
 | ||||
|   To protect your rights, we need to make restrictions that forbid | ||||
| distributors to deny you these rights or to ask you to surrender these | ||||
| rights.  These restrictions translate to certain responsibilities for | ||||
| you if you distribute copies of the library or if you modify it. | ||||
| 
 | ||||
|   For example, if you distribute copies of the library, whether gratis | ||||
| or for a fee, you must give the recipients all the rights that we gave | ||||
| you.  You must make sure that they, too, receive or can get the source | ||||
| code.  If you link other code with the library, you must provide | ||||
| complete object files to the recipients, so that they can relink them | ||||
| with the library after making changes to the library and recompiling | ||||
| it.  And you must show them these terms so they know their rights. | ||||
| 
 | ||||
|   We protect your rights with a two-step method: (1) we copyright the | ||||
| library, and (2) we offer you this license, which gives you legal | ||||
| permission to copy, distribute and/or modify the library. | ||||
| 
 | ||||
|   To protect each distributor, we want to make it very clear that | ||||
| there is no warranty for the free library.  Also, if the library is | ||||
| modified by someone else and passed on, the recipients should know | ||||
| that what they have is not the original version, so that the original | ||||
| author's reputation will not be affected by problems that might be | ||||
| introduced by others. | ||||
|  | ||||
|   Finally, software patents pose a constant threat to the existence of | ||||
| any free program.  We wish to make sure that a company cannot | ||||
| effectively restrict the users of a free program by obtaining a | ||||
| restrictive license from a patent holder.  Therefore, we insist that | ||||
| any patent license obtained for a version of the library must be | ||||
| consistent with the full freedom of use specified in this license. | ||||
| 
 | ||||
|   Most GNU software, including some libraries, is covered by the | ||||
| ordinary GNU General Public License.  This license, the GNU Lesser | ||||
| General Public License, applies to certain designated libraries, and | ||||
| is quite different from the ordinary General Public License.  We use | ||||
| this license for certain libraries in order to permit linking those | ||||
| libraries into non-free programs. | ||||
| 
 | ||||
|   When a program is linked with a library, whether statically or using | ||||
| a shared library, the combination of the two is legally speaking a | ||||
| combined work, a derivative of the original library.  The ordinary | ||||
| General Public License therefore permits such linking only if the | ||||
| entire combination fits its criteria of freedom.  The Lesser General | ||||
| Public License permits more lax criteria for linking other code with | ||||
| the library. | ||||
| 
 | ||||
|   We call this license the "Lesser" General Public License because it | ||||
| does Less to protect the user's freedom than the ordinary General | ||||
| Public License.  It also provides other free software developers Less | ||||
| of an advantage over competing non-free programs.  These disadvantages | ||||
| are the reason we use the ordinary General Public License for many | ||||
| libraries.  However, the Lesser license provides advantages in certain | ||||
| special circumstances. | ||||
| 
 | ||||
|   For example, on rare occasions, there may be a special need to | ||||
| encourage the widest possible use of a certain library, so that it becomes | ||||
| a de-facto standard.  To achieve this, non-free programs must be | ||||
| allowed to use the library.  A more frequent case is that a free | ||||
| library does the same job as widely used non-free libraries.  In this | ||||
| case, there is little to gain by limiting the free library to free | ||||
| software only, so we use the Lesser General Public License. | ||||
| 
 | ||||
|   In other cases, permission to use a particular library in non-free | ||||
| programs enables a greater number of people to use a large body of | ||||
| free software.  For example, permission to use the GNU C Library in | ||||
| non-free programs enables many more people to use the whole GNU | ||||
| operating system, as well as its variant, the GNU/Linux operating | ||||
| system. | ||||
| 
 | ||||
|   Although the Lesser General Public License is Less protective of the | ||||
| users' freedom, it does ensure that the user of a program that is | ||||
| linked with the Library has the freedom and the wherewithal to run | ||||
| that program using a modified version of the Library. | ||||
| 
 | ||||
|   The precise terms and conditions for copying, distribution and | ||||
| modification follow.  Pay close attention to the difference between a | ||||
| "work based on the library" and a "work that uses the library".  The | ||||
| former contains code derived from the library, whereas the latter must | ||||
| be combined with the library in order to run. | ||||
|  | ||||
| 		  GNU LESSER GENERAL PUBLIC LICENSE | ||||
|    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | ||||
| 
 | ||||
|   0. This License Agreement applies to any software library or other | ||||
| program which contains a notice placed by the copyright holder or | ||||
| other authorized party saying it may be distributed under the terms of | ||||
| this Lesser General Public License (also called "this License"). | ||||
| Each licensee is addressed as "you". | ||||
| 
 | ||||
|   A "library" means a collection of software functions and/or data | ||||
| prepared so as to be conveniently linked with application programs | ||||
| (which use some of those functions and data) to form executables. | ||||
| 
 | ||||
|   The "Library", below, refers to any such software library or work | ||||
| which has been distributed under these terms.  A "work based on the | ||||
| Library" means either the Library or any derivative work under | ||||
| copyright law: that is to say, a work containing the Library or a | ||||
| portion of it, either verbatim or with modifications and/or translated | ||||
| straightforwardly into another language.  (Hereinafter, translation is | ||||
| included without limitation in the term "modification".) | ||||
| 
 | ||||
|   "Source code" for a work means the preferred form of the work for | ||||
| making modifications to it.  For a library, complete source code means | ||||
| all the source code for all modules it contains, plus any associated | ||||
| interface definition files, plus the scripts used to control compilation | ||||
| and installation of the library. | ||||
| 
 | ||||
|   Activities other than copying, distribution and modification are not | ||||
| covered by this License; they are outside its scope.  The act of | ||||
| running a program using the Library is not restricted, and output from | ||||
| such a program is covered only if its contents constitute a work based | ||||
| on the Library (independent of the use of the Library in a tool for | ||||
| writing it).  Whether that is true depends on what the Library does | ||||
| and what the program that uses the Library does. | ||||
|    | ||||
|   1. You may copy and distribute verbatim copies of the Library's | ||||
| complete source code as you receive it, in any medium, provided that | ||||
| you conspicuously and appropriately publish on each copy an | ||||
| appropriate copyright notice and disclaimer of warranty; keep intact | ||||
| all the notices that refer to this License and to the absence of any | ||||
| warranty; and distribute a copy of this License along with the | ||||
| Library. | ||||
| 
 | ||||
|   You may charge a fee for the physical act of transferring a copy, | ||||
| and you may at your option offer warranty protection in exchange for a | ||||
| fee. | ||||
|  | ||||
|   2. You may modify your copy or copies of the Library or any portion | ||||
| of it, thus forming a work based on the Library, and copy and | ||||
| distribute such modifications or work under the terms of Section 1 | ||||
| above, provided that you also meet all of these conditions: | ||||
| 
 | ||||
|     a) The modified work must itself be a software library. | ||||
| 
 | ||||
|     b) You must cause the files modified to carry prominent notices | ||||
|     stating that you changed the files and the date of any change. | ||||
| 
 | ||||
|     c) You must cause the whole of the work to be licensed at no | ||||
|     charge to all third parties under the terms of this License. | ||||
| 
 | ||||
|     d) If a facility in the modified Library refers to a function or a | ||||
|     table of data to be supplied by an application program that uses | ||||
|     the facility, other than as an argument passed when the facility | ||||
|     is invoked, then you must make a good faith effort to ensure that, | ||||
|     in the event an application does not supply such function or | ||||
|     table, the facility still operates, and performs whatever part of | ||||
|     its purpose remains meaningful. | ||||
| 
 | ||||
|     (For example, a function in a library to compute square roots has | ||||
|     a purpose that is entirely well-defined independent of the | ||||
|     application.  Therefore, Subsection 2d requires that any | ||||
|     application-supplied function or table used by this function must | ||||
|     be optional: if the application does not supply it, the square | ||||
|     root function must still compute square roots.) | ||||
| 
 | ||||
| These requirements apply to the modified work as a whole.  If | ||||
| identifiable sections of that work are not derived from the Library, | ||||
| and can be reasonably considered independent and separate works in | ||||
| themselves, then this License, and its terms, do not apply to those | ||||
| sections when you distribute them as separate works.  But when you | ||||
| distribute the same sections as part of a whole which is a work based | ||||
| on the Library, the distribution of the whole must be on the terms of | ||||
| this License, whose permissions for other licensees extend to the | ||||
| entire whole, and thus to each and every part regardless of who wrote | ||||
| it. | ||||
| 
 | ||||
| Thus, it is not the intent of this section to claim rights or contest | ||||
| your rights to work written entirely by you; rather, the intent is to | ||||
| exercise the right to control the distribution of derivative or | ||||
| collective works based on the Library. | ||||
| 
 | ||||
| In addition, mere aggregation of another work not based on the Library | ||||
| with the Library (or with a work based on the Library) on a volume of | ||||
| a storage or distribution medium does not bring the other work under | ||||
| the scope of this License. | ||||
| 
 | ||||
|   3. You may opt to apply the terms of the ordinary GNU General Public | ||||
| License instead of this License to a given copy of the Library.  To do | ||||
| this, you must alter all the notices that refer to this License, so | ||||
| that they refer to the ordinary GNU General Public License, version 2, | ||||
| instead of to this License.  (If a newer version than version 2 of the | ||||
| ordinary GNU General Public License has appeared, then you can specify | ||||
| that version instead if you wish.)  Do not make any other change in | ||||
| these notices. | ||||
|  | ||||
|   Once this change is made in a given copy, it is irreversible for | ||||
| that copy, so the ordinary GNU General Public License applies to all | ||||
| subsequent copies and derivative works made from that copy. | ||||
| 
 | ||||
|   This option is useful when you wish to copy part of the code of | ||||
| the Library into a program that is not a library. | ||||
| 
 | ||||
|   4. You may copy and distribute the Library (or a portion or | ||||
| derivative of it, under Section 2) in object code or executable form | ||||
| under the terms of Sections 1 and 2 above provided that you accompany | ||||
| it with the complete corresponding machine-readable source code, which | ||||
| must be distributed under the terms of Sections 1 and 2 above on a | ||||
| medium customarily used for software interchange. | ||||
| 
 | ||||
|   If distribution of object code is made by offering access to copy | ||||
| from a designated place, then offering equivalent access to copy the | ||||
| source code from the same place satisfies the requirement to | ||||
| distribute the source code, even though third parties are not | ||||
| compelled to copy the source along with the object code. | ||||
| 
 | ||||
|   5. A program that contains no derivative of any portion of the | ||||
| Library, but is designed to work with the Library by being compiled or | ||||
| linked with it, is called a "work that uses the Library".  Such a | ||||
| work, in isolation, is not a derivative work of the Library, and | ||||
| therefore falls outside the scope of this License. | ||||
| 
 | ||||
|   However, linking a "work that uses the Library" with the Library | ||||
| creates an executable that is a derivative of the Library (because it | ||||
| contains portions of the Library), rather than a "work that uses the | ||||
| library".  The executable is therefore covered by this License. | ||||
| Section 6 states terms for distribution of such executables. | ||||
| 
 | ||||
|   When a "work that uses the Library" uses material from a header file | ||||
| that is part of the Library, the object code for the work may be a | ||||
| derivative work of the Library even though the source code is not. | ||||
| Whether this is true is especially significant if the work can be | ||||
| linked without the Library, or if the work is itself a library.  The | ||||
| threshold for this to be true is not precisely defined by law. | ||||
| 
 | ||||
|   If such an object file uses only numerical parameters, data | ||||
| structure layouts and accessors, and small macros and small inline | ||||
| functions (ten lines or less in length), then the use of the object | ||||
| file is unrestricted, regardless of whether it is legally a derivative | ||||
| work.  (Executables containing this object code plus portions of the | ||||
| Library will still fall under Section 6.) | ||||
| 
 | ||||
|   Otherwise, if the work is a derivative of the Library, you may | ||||
| distribute the object code for the work under the terms of Section 6. | ||||
| Any executables containing that work also fall under Section 6, | ||||
| whether or not they are linked directly with the Library itself. | ||||
|  | ||||
|   6. As an exception to the Sections above, you may also combine or | ||||
| link a "work that uses the Library" with the Library to produce a | ||||
| work containing portions of the Library, and distribute that work | ||||
| under terms of your choice, provided that the terms permit | ||||
| modification of the work for the customer's own use and reverse | ||||
| engineering for debugging such modifications. | ||||
| 
 | ||||
|   You must give prominent notice with each copy of the work that the | ||||
| Library is used in it and that the Library and its use are covered by | ||||
| this License.  You must supply a copy of this License.  If the work | ||||
| during execution displays copyright notices, you must include the | ||||
| copyright notice for the Library among them, as well as a reference | ||||
| directing the user to the copy of this License.  Also, you must do one | ||||
| of these things: | ||||
| 
 | ||||
|     a) Accompany the work with the complete corresponding | ||||
|     machine-readable source code for the Library including whatever | ||||
|     changes were used in the work (which must be distributed under | ||||
|     Sections 1 and 2 above); and, if the work is an executable linked | ||||
|     with the Library, with the complete machine-readable "work that | ||||
|     uses the Library", as object code and/or source code, so that the | ||||
|     user can modify the Library and then relink to produce a modified | ||||
|     executable containing the modified Library.  (It is understood | ||||
|     that the user who changes the contents of definitions files in the | ||||
|     Library will not necessarily be able to recompile the application | ||||
|     to use the modified definitions.) | ||||
| 
 | ||||
|     b) Use a suitable shared library mechanism for linking with the | ||||
|     Library.  A suitable mechanism is one that (1) uses at run time a | ||||
|     copy of the library already present on the user's computer system, | ||||
|     rather than copying library functions into the executable, and (2) | ||||
|     will operate properly with a modified version of the library, if | ||||
|     the user installs one, as long as the modified version is | ||||
|     interface-compatible with the version that the work was made with. | ||||
| 
 | ||||
|     c) Accompany the work with a written offer, valid for at | ||||
|     least three years, to give the same user the materials | ||||
|     specified in Subsection 6a, above, for a charge no more | ||||
|     than the cost of performing this distribution. | ||||
| 
 | ||||
|     d) If distribution of the work is made by offering access to copy | ||||
|     from a designated place, offer equivalent access to copy the above | ||||
|     specified materials from the same place. | ||||
| 
 | ||||
|     e) Verify that the user has already received a copy of these | ||||
|     materials or that you have already sent this user a copy. | ||||
| 
 | ||||
|   For an executable, the required form of the "work that uses the | ||||
| Library" must include any data and utility programs needed for | ||||
| reproducing the executable from it.  However, as a special exception, | ||||
| the materials to be distributed need not include anything that is | ||||
| normally distributed (in either source or binary form) with the major | ||||
| components (compiler, kernel, and so on) of the operating system on | ||||
| which the executable runs, unless that component itself accompanies | ||||
| the executable. | ||||
| 
 | ||||
|   It may happen that this requirement contradicts the license | ||||
| restrictions of other proprietary libraries that do not normally | ||||
| accompany the operating system.  Such a contradiction means you cannot | ||||
| use both them and the Library together in an executable that you | ||||
| distribute. | ||||
|  | ||||
|   7. You may place library facilities that are a work based on the | ||||
| Library side-by-side in a single library together with other library | ||||
| facilities not covered by this License, and distribute such a combined | ||||
| library, provided that the separate distribution of the work based on | ||||
| the Library and of the other library facilities is otherwise | ||||
| permitted, and provided that you do these two things: | ||||
| 
 | ||||
|     a) Accompany the combined library with a copy of the same work | ||||
|     based on the Library, uncombined with any other library | ||||
|     facilities.  This must be distributed under the terms of the | ||||
|     Sections above. | ||||
| 
 | ||||
|     b) Give prominent notice with the combined library of the fact | ||||
|     that part of it is a work based on the Library, and explaining | ||||
|     where to find the accompanying uncombined form of the same work. | ||||
| 
 | ||||
|   8. You may not copy, modify, sublicense, link with, or distribute | ||||
| the Library except as expressly provided under this License.  Any | ||||
| attempt otherwise to copy, modify, sublicense, link with, or | ||||
| distribute the Library is void, and will automatically terminate your | ||||
| rights under this License.  However, parties who have received copies, | ||||
| or rights, from you under this License will not have their licenses | ||||
| terminated so long as such parties remain in full compliance. | ||||
| 
 | ||||
|   9. You are not required to accept this License, since you have not | ||||
| signed it.  However, nothing else grants you permission to modify or | ||||
| distribute the Library or its derivative works.  These actions are | ||||
| prohibited by law if you do not accept this License.  Therefore, by | ||||
| modifying or distributing the Library (or any work based on the | ||||
| Library), you indicate your acceptance of this License to do so, and | ||||
| all its terms and conditions for copying, distributing or modifying | ||||
| the Library or works based on it. | ||||
| 
 | ||||
|   10. Each time you redistribute the Library (or any work based on the | ||||
| Library), the recipient automatically receives a license from the | ||||
| original licensor to copy, distribute, link with or modify the Library | ||||
| subject to these terms and conditions.  You may not impose any further | ||||
| restrictions on the recipients' exercise of the rights granted herein. | ||||
| You are not responsible for enforcing compliance by third parties with | ||||
| this License. | ||||
|  | ||||
|   11. If, as a consequence of a court judgment or allegation of patent | ||||
| infringement or for any other reason (not limited to patent issues), | ||||
| 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 | ||||
| distribute so as to satisfy simultaneously your obligations under this | ||||
| License and any other pertinent obligations, then as a consequence you | ||||
| may not distribute the Library at all.  For example, if a patent | ||||
| license would not permit royalty-free redistribution of the Library by | ||||
| all those who receive copies directly or indirectly through you, then | ||||
| the only way you could satisfy both it and this License would be to | ||||
| refrain entirely from distribution of the Library. | ||||
| 
 | ||||
| If any portion of this section is held invalid or unenforceable under any | ||||
| particular circumstance, the balance of the section is intended to apply, | ||||
| and the section as a whole is intended to apply in other circumstances. | ||||
| 
 | ||||
| It is not the purpose of this section to induce you to infringe any | ||||
| patents or other property right claims or to contest validity of any | ||||
| such claims; this section has the sole purpose of protecting the | ||||
| integrity of the free software distribution system which is | ||||
| implemented by public license practices.  Many people have made | ||||
| generous contributions to the wide range of software distributed | ||||
| through that system in reliance on consistent application of that | ||||
| system; it is up to the author/donor to decide if he or she is willing | ||||
| to distribute software through any other system and a licensee cannot | ||||
| impose that choice. | ||||
| 
 | ||||
| This section is intended to make thoroughly clear what is believed to | ||||
| be a consequence of the rest of this License. | ||||
| 
 | ||||
|   12. If the distribution and/or use of the Library is restricted in | ||||
| certain countries either by patents or by copyrighted interfaces, the | ||||
| original copyright holder who places the Library under this License may add | ||||
| an explicit geographical distribution limitation excluding those countries, | ||||
| so that distribution is permitted only in or among countries not thus | ||||
| excluded.  In such case, this License incorporates the limitation as if | ||||
| written in the body of this License. | ||||
| 
 | ||||
|   13. The Free Software Foundation may publish revised and/or new | ||||
| versions of the Lesser 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 Library | ||||
| specifies a version number of this License which applies to it and | ||||
| "any later version", you have the option of following the terms and | ||||
| conditions either of that version or of any later version published by | ||||
| the Free Software Foundation.  If the Library does not specify a | ||||
| license version number, you may choose any version ever published by | ||||
| the Free Software Foundation. | ||||
|  | ||||
|   14. If you wish to incorporate parts of the Library into other free | ||||
| programs whose distribution conditions are incompatible with these, | ||||
| write to the author to ask for permission.  For software which is | ||||
| copyrighted by the Free Software Foundation, write to the Free | ||||
| Software Foundation; we sometimes make exceptions for this.  Our | ||||
| decision will be guided by the two goals of preserving the free status | ||||
| of all derivatives of our free software and of promoting the sharing | ||||
| and reuse of software generally. | ||||
| 
 | ||||
| 			    NO WARRANTY | ||||
| 
 | ||||
|   15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO | ||||
| WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. | ||||
| EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR | ||||
| OTHER PARTIES PROVIDE THE LIBRARY "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 | ||||
| LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME | ||||
| THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. | ||||
| 
 | ||||
|   16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN | ||||
| WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY | ||||
| AND/OR REDISTRIBUTE THE LIBRARY 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 | ||||
| LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF | ||||
| SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH | ||||
| DAMAGES. | ||||
| 
 | ||||
| 		     END OF TERMS AND CONDITIONS | ||||
|  | ||||
|            How to Apply These Terms to Your New Libraries | ||||
| 
 | ||||
|   If you develop a new library, and you want it to be of the greatest | ||||
| possible use to the public, we recommend making it free software that | ||||
| everyone can redistribute and change.  You can do so by permitting | ||||
| redistribution under these terms (or, alternatively, under the terms of the | ||||
| ordinary General Public License). | ||||
| 
 | ||||
|   To apply these terms, attach the following notices to the library.  It is | ||||
| safest to attach them to the start of each source file to most effectively | ||||
| convey 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 library's name and a brief idea of what it does.> | ||||
|     Copyright (C) <year>  <name of author> | ||||
| 
 | ||||
|     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 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
| 
 | ||||
| Also add information on how to contact you by electronic and paper mail. | ||||
| 
 | ||||
| You should also get your employer (if you work as a programmer) or your | ||||
| school, if any, to sign a "copyright disclaimer" for the library, if | ||||
| necessary.  Here is a sample; alter the names: | ||||
| 
 | ||||
|   Yoyodyne, Inc., hereby disclaims all copyright interest in the | ||||
|   library `Frob' (a library for tweaking knobs) written by James Random Hacker. | ||||
| 
 | ||||
|   <signature of Ty Coon>, 1 April 1990 | ||||
|   Ty Coon, President of Vice | ||||
| 
 | ||||
| That's all there is to it! | ||||
| 
 | ||||
| 
 | ||||
|  | @ -1,89 +0,0 @@ | |||
|             Notes for Contribution of LUSOL to COIN-OR | ||||
|                             May 2004 | ||||
| 
 | ||||
| Introduction | ||||
| ============ | ||||
| 
 | ||||
| LUSOL maintains sparse LU factors of a square or rectangular sparse matrix.  It includes a Basis Factorization Package (BFP) suitable for implementing simplex and reduced-gradient methods for optimization.  It is a set of  routines written in ANSI C (adapted from the original Fortran 77 version). | ||||
| 
 | ||||
| LUSOL includes the following features: | ||||
| 
 | ||||
| -  A Markowitz-based sparse LU factorization for square, | ||||
|    rectangular and possibly singular matrices. | ||||
| 
 | ||||
| -  Three options for balancing sparsity and stability: | ||||
|    Threshold Partial/Rook/Complete Pivoting (TPP, TRP, TCP). | ||||
| 
 | ||||
| -  Rank-revealing properties.  TRP and TCP are intended for detecting singularities. | ||||
| 
 | ||||
| -  Dynamic storage allocation (C version only). | ||||
| 
 | ||||
| -  Stable column replacement as in the method of Bartels and Golub. | ||||
| 
 | ||||
| -  Other stable updates: add, replace, or delete row or column | ||||
|    (currently F77 version only). | ||||
| 
 | ||||
| -  Implementation into an easy-to-use BFP API (C version only). | ||||
| 
 | ||||
| 
 | ||||
| Implementation | ||||
| ============== | ||||
| 
 | ||||
| The Factor routine is similar to the classical Markowitz routines MA28 and LA05 in the Harwell Subroutine Library. The source matrix nonzeros are stored column-wise with the largest entry at the top of each column.  Internally, the structure is also accessible row-wise.  All entries in a particular column or row are held in contiguous storage.  Fill is accommodated by moving a column or row to the beginning of free storage. Occasional compressions recover storage.  This scheme is effective for column-oriented TPP.  When the remaining matrix reaches a specified density, the factors are completed using dense processing. | ||||
| 
 | ||||
| TRP uses an additional vector of storage to maintain the largest element in each remaining row. | ||||
| 
 | ||||
| TCP uses a heap structure to hold the largest element in each column.  The largest element in the remaining matrix is then available at the top of the heap. | ||||
| 
 | ||||
| The final L is stored column-wise (and never changed).  The final U is stored row-wise as a triangular or trapezoidal sparse matrix. | ||||
| 
 | ||||
| Column replacements are implemented using a forward sweep of 2-by-2 stabilized elimination matrices.  L is updated in product form.  U is updated explicitly. | ||||
| 
 | ||||
| The other updates use either forward or backward sweeps. They tend to generate more nonzeros than column replacement. | ||||
| 
 | ||||
| Both the F77 and C versions contain extensive comments, method and implementational information as part of the code. | ||||
| 
 | ||||
| The C version contains a record-based wrapper for the data.  Function calls have been simplified by including references to this structure.  New maintenance routines enable dynamic instance creation and destruction, and  simplifies access to the most frequently used functions.  The LUSOL C library is multi-instance and fully re-entrant.  All control and output parameters have been given long descriptive names for usability.  | ||||
| 
 | ||||
| 
 | ||||
| Benefits | ||||
| ======== | ||||
| 
 | ||||
| Rank-revealing properties and rectangular factors (and updates) have not previously been available in sparse LU software.  With sensible parameter settings and reasonably scaled data, all routines are numerically stable.  The updates may be called hundreds of times, and the decision to refactorize can be based on sparsity considerations alone. | ||||
| 
 | ||||
| In the Factor routine, rook pivoting (TRP) gives reliable rank determination without catastrophic degradation in sparsity or speed.  Complete pivoting (TCP) is included for moderate-sized matrices and for checking pathological cases (but the factors tend to be substantially more dense). | ||||
| 
 | ||||
| To conserve storage, one may request only the row and column pivot orders.  The factors are discarded as they are computed.  This is useful for basis repair, or for selecting a basis from a rectangular matrix. | ||||
| 
 | ||||
| 
 | ||||
| Known Inefficiencies | ||||
| ==================== | ||||
| 
 | ||||
| LUSOL is usually efficient on sparse matrices with dimensions up to about 100,000 (but not millions). | ||||
| 
 | ||||
| In the Factor routine, row and column lists must be updated each time a row and column is eliminated.  Deleting the pivot row and column is inefficient if the original matrix contains unusually dense rows or columns.  For TPP, dense columns could be kept aside and incorporated at the end via updates (but dense rows remain a difficulty).  For TRP and TCP, all rows and columns must be present to achieve the required numerical properties. | ||||
| 
 | ||||
| For TRP, the current bottleneck is updating the vector containing the largest element in each row.  One solution would be to include the matrix nonzeros in the row structure (but this carries its own cost). | ||||
| 
 | ||||
| For TCP, the heap structure is already efficient, but the dense factors (and the extended searching for acceptable pivots) are unavoidable expenses. | ||||
| 
 | ||||
| The triangular Solve routines do not take full of advantage of sparse right-hand sides.  Gilbert and Peierls have shown how to solve Lx = (sparse b) efficiently if L is stored column-wise.  Their approach could therefore be implemented in LUSOL for solves with L and U(transpose).  Solves with L(transpose) and U would need a second copy of L and U.  | ||||
| 
 | ||||
| 
 | ||||
| Original Reference | ||||
| ================== | ||||
| 
 | ||||
| P. E. Gill, W. Murray, M. A. Saunders and M. H. Wright, Maintaining LU factors of a general sparse matrix, Linear Algebra and its Applications 88/89, 239-270 (1987). | ||||
| 
 | ||||
| 
 | ||||
| Maintainers | ||||
| =========== | ||||
| 
 | ||||
| F77 version: Michael Saunders (saunders@stanford.edu). | ||||
| C version: Kjell Eikland (kjell.eikland@broadpark.no). | ||||
| 
 | ||||
| 
 | ||||
| Contributors | ||||
| ============ | ||||
| 
 | ||||
| Philip Gill, Walter Murray, Margaret Wright, Michael O'Sullivan. | ||||
|  | @ -1,35 +0,0 @@ | |||
| README.TXT for LUSOL - Advanced LU solver with enhanced numerical stability options | ||||
| ----------------------------------------------------------------------------------- | ||||
| 
 | ||||
| LUSOL - pronounced "L-U-SOL" - was developed by Prof. Michael Saunders at the  | ||||
| Stanford (University) Optimization Laboratory over a period of 2 decades of  | ||||
| progressive improvements.  It is a particularly capable matrix factorization system | ||||
| and includes sparsity-preserving column updates and equation solving.  It is | ||||
| therefore particularly well suited to be part of a system to solve tough mathematical  | ||||
| programming problems.  Further details can be found in the file "LUSOL-overview.txt." | ||||
| 
 | ||||
| A big step has been made in converting the original Fortran code into a much more | ||||
| easily accessible and modularized system based on ANSI C as part of the release of | ||||
| lp_solve v5.  LUSOL is fully implemented as a "Basis Factorization Package", BFP in  | ||||
| lp_solve and is the BFP of choice for large and complex models, if not all.  As part | ||||
| of the conversion to C, processor optimized BLAS functionality has been enabled, and | ||||
| future enhancements to LUSOL may make increasing use of this, ensuring top performance.  | ||||
| 
 | ||||
| For the lp_solve release of LUSOL, a stand-alone equation solving system has also been | ||||
| developed.  A pre-compiled Windows command-line executable version is included in the | ||||
| standard distribution of LUSOL. In addition, the program options illustrate several  | ||||
| advanced uses of LUSOL.  The equation solving utility features reading of standard  | ||||
| matrix files in the Harwell-Boeing, MatrixMarket and text formats.  Sample matrix  | ||||
| models are provided for Harwell-Boeing (.RUA) and MatrixMarket (.mtx).   | ||||
| 
 | ||||
| The LUSOL code is released under the GNU Lesser General Public Licence.  Confer the  | ||||
| file "Licence_LGPL.txt" for the full terms of this licence.  These terms make lp_solve | ||||
| and LUSOL available and distributable on equal licencing terms.  It is expected that | ||||
| LUSOL will have an official repository in the near future, but the LUSOL archive at | ||||
| the Yahoo lp_solve group will be an official copy and the formal repository until | ||||
| further notice. | ||||
| 
 | ||||
| 
 | ||||
| Kjell Eikland | ||||
| 14 July 2004 | ||||
| Oslo, Norway | ||||
|  | @ -1,36 +0,0 @@ | |||
| Traditional column-based L0 | ||||
| --------------------------- | ||||
| V[  3] = V[  3] + L[1,3]*V[  1] | ||||
| 0.9375 = -1.26316 + -0.789474*-2.7875 | ||||
| V[  2] = V[  2] + L[1,2]*V[  1] | ||||
| -0.846875 =  -0.15 +   0.25*-2.7875 | ||||
| V[  2] = V[  2] + L[3,2]*V[  3] | ||||
| -0.925 = -0.846875 + -0.0833333*0.9375 | ||||
| V[  4] = V[  4] + L[3,4]*V[  3] | ||||
| -0.3125 =      0 + -0.333333*0.9375 | ||||
| 
 | ||||
| Solution vector | ||||
|             -2.7875             -0.925             0.9375            -0.3125 | ||||
| 
 | ||||
| 
 | ||||
| New row-based L0 | ||||
| ---------------- | ||||
| V[  4] = V[  4] + L[3,4]*V[  3] | ||||
| 0.421053 =      0 + -0.333333*-1.26316 | ||||
| V[  2] = V[  2] + L[3,2]*V[  3] | ||||
| -0.0447368 =  -0.15 + -0.0833333*-1.26316 | ||||
| V[  2] = V[  2] + L[1,2]*V[  1] | ||||
| -0.741612 = -0.0447368 +   0.25*-2.7875 | ||||
| V[  3] = V[  3] + L[1,3]*V[  1] | ||||
| 0.9375 = -1.26316 + -0.789474*-2.7875 | ||||
| 
 | ||||
| Solution vector | ||||
|             -2.7875          -0.741612             0.9375           0.421053 | ||||
| 
 | ||||
| 
 | ||||
| L0 generated | ||||
| ---------------- | ||||
|          0         0         0         0 | ||||
|          0         0         0         0 | ||||
|          0      0.25 -0.789474         0 | ||||
|          0-0.0833333         0 -0.333333 | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -1,3 +0,0 @@ | |||
|        -0.187248E+05 | ||||
|         0.112479E+05 | ||||
|         0.132356E+05 | ||||
|  | @ -1,847 +0,0 @@ | |||
| 
 | ||||
| #include <sys/types.h> | ||||
| 
 | ||||
| #if defined INTEGERTIME || defined CLOCKTIME || defined PosixTime | ||||
| # include <time.h> | ||||
| #elif defined EnhTime | ||||
| # include <windows.h> | ||||
| #else | ||||
| # include <sys/timeb.h> | ||||
| #endif | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #ifdef WIN32 | ||||
| # include <io.h>       /* Used in file search functions */ | ||||
| #endif | ||||
| #include <ctype.h> | ||||
| #include <string.h> | ||||
| #include <math.h> | ||||
| #include "commonlib.h" | ||||
| 
 | ||||
| #ifdef FORTIFY | ||||
| # include "lp_fortify.h" | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /* Math operator equivalence function */ | ||||
| int intpow(int base, int exponent) | ||||
| { | ||||
|   int result = 1; | ||||
|   while(exponent > 0) { | ||||
|     result *= base; | ||||
|     exponent--; | ||||
|   } | ||||
|   while(exponent < 0) { | ||||
|     result /= base; | ||||
|     exponent++; | ||||
|   } | ||||
|   return( result ); | ||||
| } | ||||
| int mod(int n, int d) | ||||
| { | ||||
|   return(n % d); | ||||
| } | ||||
| 
 | ||||
| /* Some string functions */ | ||||
| void strtoup(char *s) | ||||
| { | ||||
|   if(s != NULL) | ||||
|   while (*s) { | ||||
|     *s = toupper(*s); | ||||
|     s++; | ||||
|   } | ||||
| } | ||||
| void strtolo(char *s) | ||||
| { | ||||
|   if(s != NULL) | ||||
|   while (*s) { | ||||
|     *s = tolower(*s); | ||||
|     s++; | ||||
|   } | ||||
| } | ||||
| void strcpyup(char *t, char *s) | ||||
| { | ||||
|   if((s != NULL) && (t != NULL)) { | ||||
|     while (*s) { | ||||
|       *t = toupper(*s); | ||||
|       t++; | ||||
|       s++; | ||||
|     } | ||||
|     *t = '\0'; | ||||
|   } | ||||
| } | ||||
| void strcpylo(char *t, char *s) | ||||
| { | ||||
|   if((s != NULL) && (t != NULL)) { | ||||
|     while (*s) { | ||||
|       *t = tolower(*s); | ||||
|       t++; | ||||
|       s++; | ||||
|     } | ||||
|     *t = '\0'; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /* Unix library naming utility function */ | ||||
| MYBOOL so_stdname(char *stdname, char *descname, int buflen) | ||||
| { | ||||
|   char *ptr; | ||||
| 
 | ||||
|   if((descname == NULL) || (stdname == NULL) || (((int) strlen(descname)) >= buflen - 6)) | ||||
|     return( FALSE ); | ||||
| 
 | ||||
|   strcpy(stdname, descname); | ||||
|   if((ptr = strrchr(descname, '/')) == NULL) | ||||
|     ptr = descname; | ||||
|   else | ||||
|     ptr++; | ||||
|   stdname[(int) (ptr - descname)] = 0; | ||||
|   if(strncmp(ptr, "lib", 3)) | ||||
|     strcat(stdname, "lib"); | ||||
|   strcat(stdname, ptr); | ||||
|   if(strcmp(stdname + strlen(stdname) - 3, ".so")) | ||||
|     strcat(stdname, ".so"); | ||||
|   return( TRUE ); | ||||
| } | ||||
| 
 | ||||
| /* Return the greatest common divisor of a and b, or -1 if it is
 | ||||
|    not defined. Return through the pointer arguments the integers | ||||
|    such that gcd(a,b) = c*a + b*d. */ | ||||
| int gcd(LLONG a, LLONG b, int *c, int *d) | ||||
| { | ||||
|   LLONG q,r,t; | ||||
|   int   cret,dret,C,D,rval, sgn_a = 1,sgn_b = 1, swap = 0; | ||||
| 
 | ||||
|   if((a == 0) || (b == 0)) | ||||
|     return( -1 ); | ||||
| 
 | ||||
|   /* Use local multiplier instances, if necessary */ | ||||
|   if(c == NULL) | ||||
|     c = &cret; | ||||
|   if(d == NULL) | ||||
|     d = &dret; | ||||
| 
 | ||||
|   /* Normalize so that 0 < a <= b */ | ||||
|   if(a < 0){ | ||||
|     a = -a; | ||||
|     sgn_a = -1; | ||||
|   } | ||||
|   if(b < 0){ | ||||
|     b = -b; | ||||
|     sgn_b = -1; | ||||
|   } | ||||
|   if(b < a){ | ||||
|     t = b; | ||||
|     b = a; | ||||
|     a = t; | ||||
|     swap = 1; | ||||
|   } | ||||
| 
 | ||||
|   /* Now a <= b and both >= 1. */ | ||||
|   q = b/a; | ||||
|   r = b - a*q; | ||||
|   if(r == 0) { | ||||
|     if(swap){ | ||||
|       *d = 1; | ||||
|       *c = 0; | ||||
|     } | ||||
|     else { | ||||
|       *c = 1; | ||||
|       *d = 0; | ||||
|     } | ||||
|     *c = sgn_a*(*c); | ||||
|     *d = sgn_b*(*d); | ||||
|     return( (int) a ); | ||||
|   } | ||||
| 
 | ||||
|   rval = gcd(a,r,&C,&D); | ||||
|   if(swap){ | ||||
|     *d = (int) (C-D*q); | ||||
|     *c = D; | ||||
|   } | ||||
|   else { | ||||
|     *d = D; | ||||
|     *c = (int) (C-D*q); | ||||
|   } | ||||
|   *c = sgn_a*(*c); | ||||
|   *d = sgn_b*(*d); | ||||
|   return( rval ); | ||||
| } | ||||
| 
 | ||||
| /* Array search functions */ | ||||
| int findIndex(int target, int *attributes, int count, int offset) | ||||
| { | ||||
|   int focusPos, beginPos, endPos; | ||||
|   int focusAttrib, beginAttrib, endAttrib; | ||||
| 
 | ||||
|  /* Set starting and ending index offsets */ | ||||
|   beginPos = offset; | ||||
|   endPos = beginPos + count - 1; | ||||
|   if(endPos < beginPos) | ||||
|     return(-1); | ||||
| 
 | ||||
|  /* Do binary search logic based on a sorted (decending) attribute vector */ | ||||
|   focusPos = (beginPos + endPos) / 2; | ||||
|   beginAttrib = attributes[beginPos]; | ||||
|   focusAttrib = attributes[focusPos]; | ||||
|   endAttrib   = attributes[endPos]; | ||||
| 
 | ||||
|   while(endPos - beginPos > LINEARSEARCH) { | ||||
|     if(beginAttrib == target) { | ||||
|       focusAttrib = beginAttrib; | ||||
|       endPos = beginPos; | ||||
|     } | ||||
|     else if(endAttrib == target) { | ||||
|       focusAttrib = endAttrib; | ||||
|       beginPos = endPos; | ||||
|     } | ||||
|     else if(focusAttrib < target) { | ||||
|       beginPos = focusPos + 1; | ||||
|       beginAttrib = attributes[beginPos]; | ||||
|       focusPos = (beginPos + endPos) / 2; | ||||
|       focusAttrib = attributes[focusPos]; | ||||
|     } | ||||
|     else if(focusAttrib > target) { | ||||
|       endPos = focusPos - 1; | ||||
|       endAttrib = attributes[endPos]; | ||||
|       focusPos = (beginPos + endPos) / 2; | ||||
|       focusAttrib = attributes[focusPos]; | ||||
|     } | ||||
|     else { | ||||
|       beginPos = focusPos; | ||||
|       endPos = focusPos; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|  /* Do linear (unsorted) search logic */ | ||||
|   if(endPos - beginPos <= LINEARSEARCH) { | ||||
| 
 | ||||
|     /* CPU intensive loop; provide alternative evaluation models */ | ||||
| #if defined DOFASTMATH | ||||
|     /* Do fast pointer arithmetic */ | ||||
|     int *attptr = attributes + beginPos; | ||||
|     while((beginPos < endPos) && ((*attptr) < target)) { | ||||
|       beginPos++; | ||||
|       attptr++; | ||||
|     } | ||||
|     focusAttrib = (*attptr); | ||||
| #else | ||||
|     /* Do traditional indexed access */ | ||||
|     focusAttrib = attributes[beginPos]; | ||||
|     while((beginPos < endPos) && (focusAttrib < target)) { | ||||
|       beginPos++; | ||||
|       focusAttrib = attributes[beginPos]; | ||||
|     } | ||||
| #endif | ||||
|   } | ||||
| 
 | ||||
|  /* Return the index if a match was found, or signal failure with a -1        */ | ||||
|   if(focusAttrib == target)             /* Found; return retrieval index      */ | ||||
|     return(beginPos); | ||||
|   else if(focusAttrib > target)         /* Not found; last item               */ | ||||
|     return(-beginPos); | ||||
|   else if(beginPos > offset+count-1) | ||||
|     return(-(endPos+1));                /* Not found; end of list             */ | ||||
|   else | ||||
|     return(-(beginPos+1));              /* Not found; intermediate point      */ | ||||
| 
 | ||||
| } | ||||
| int findIndexEx(void *target, void *attributes, int count, int offset, int recsize, findCompare_func findCompare, MYBOOL ascending) | ||||
| { | ||||
|   int  focusPos, beginPos, endPos, compare, order; | ||||
|   void *focusAttrib, *beginAttrib, *endAttrib; | ||||
| 
 | ||||
|  /* Set starting and ending index offsets */ | ||||
|   beginPos = offset; | ||||
|   endPos = beginPos + count - 1; | ||||
|   if(endPos < beginPos) | ||||
|     return(-1); | ||||
|   order = (ascending ? -1 : 1); | ||||
| 
 | ||||
|  /* Do binary search logic based on a sorted attribute vector */ | ||||
|   focusPos = (beginPos + endPos) / 2; | ||||
|   beginAttrib = CMP_ATTRIBUTES(beginPos); | ||||
|   focusAttrib = CMP_ATTRIBUTES(focusPos); | ||||
|   endAttrib   = CMP_ATTRIBUTES(endPos); | ||||
| 
 | ||||
|   compare = 0; | ||||
|   while(endPos - beginPos > LINEARSEARCH) { | ||||
|     if(findCompare(target, beginAttrib) == 0) { | ||||
|       focusAttrib = beginAttrib; | ||||
|       endPos = beginPos; | ||||
|     } | ||||
|     else if(findCompare(target, endAttrib) == 0) { | ||||
|       focusAttrib = endAttrib; | ||||
|       beginPos = endPos; | ||||
|     } | ||||
|     else { | ||||
|       compare = findCompare(target, focusAttrib)*order; | ||||
|       if(compare < 0) { | ||||
|         beginPos = focusPos + 1; | ||||
|         beginAttrib = CMP_ATTRIBUTES(beginPos); | ||||
|         focusPos = (beginPos + endPos) / 2; | ||||
|         focusAttrib = CMP_ATTRIBUTES(focusPos); | ||||
|       } | ||||
|       else if(compare > 0) { | ||||
|         endPos = focusPos - 1; | ||||
|         endAttrib = CMP_ATTRIBUTES(endPos); | ||||
|         focusPos = (beginPos + endPos) / 2; | ||||
|         focusAttrib = CMP_ATTRIBUTES(focusPos); | ||||
|       } | ||||
|       else { | ||||
|         beginPos = focusPos; | ||||
|         endPos = focusPos; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|  /* Do linear (unsorted) search logic */ | ||||
|   if(endPos - beginPos <= LINEARSEARCH) { | ||||
| 
 | ||||
|     /* Do traditional indexed access */ | ||||
|     focusAttrib = CMP_ATTRIBUTES(beginPos); | ||||
|     if(beginPos == endPos) | ||||
|       compare = findCompare(target, focusAttrib)*order; | ||||
|     else | ||||
|     while((beginPos < endPos) && | ||||
|           ((compare = findCompare(target, focusAttrib)*order) < 0)) { | ||||
|       beginPos++; | ||||
|       focusAttrib = CMP_ATTRIBUTES(beginPos); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|  /* Return the index if a match was found, or signal failure with a -1        */ | ||||
|   if(compare == 0)                      /* Found; return retrieval index      */ | ||||
|     return(beginPos); | ||||
|   else if(compare > 0)                  /* Not found; last item               */ | ||||
|     return(-beginPos); | ||||
|   else if(beginPos > offset+count-1) | ||||
|     return(-(endPos+1));                /* Not found; end of list             */ | ||||
|   else | ||||
|     return(-(beginPos+1));              /* Not found; intermediate point      */ | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| /* Simple sorting and searching comparison "operators" */ | ||||
| int CMP_CALLMODEL compareCHAR(const void *current, const void *candidate) | ||||
| { | ||||
|   return( CMP_COMPARE( *(char *) current, *(char *) candidate ) ); | ||||
| } | ||||
| int CMP_CALLMODEL compareINT(const void *current, const void *candidate) | ||||
| { | ||||
|   return( CMP_COMPARE( *(int *) current, *(int *) candidate ) ); | ||||
| } | ||||
| int CMP_CALLMODEL compareREAL(const void *current, const void *candidate) | ||||
| { | ||||
|   return( CMP_COMPARE( *(REAL *) current, *(REAL *) candidate ) ); | ||||
| } | ||||
| 
 | ||||
| /* Heap sort function (procedurally based on the Numerical Recipes version,
 | ||||
|    but expanded and generalized to hande any object with the use of | ||||
|    qsort-style comparison operator).  An expanded version is also implemented, | ||||
|    where interchanges are reflected in a caller-initialized integer "tags" list. */ | ||||
| void hpsort(void *attributes, int count, int offset, int recsize, MYBOOL descending, findCompare_func findCompare) | ||||
| { | ||||
|   register int  i, j, k, ir, order; | ||||
|   register char *hold, *base; | ||||
|   char          *save; | ||||
| 
 | ||||
|   if(count < 2) | ||||
|     return; | ||||
|   offset -= 1; | ||||
|   attributes = CMP_ATTRIBUTES(offset); | ||||
|   base = CMP_ATTRIBUTES(1); | ||||
|   save = (char *) malloc(recsize); | ||||
|   if(descending) | ||||
|     order = -1; | ||||
|   else | ||||
|     order = 1; | ||||
| 
 | ||||
|   k = (count >> 1) + 1; | ||||
|   ir = count; | ||||
| 
 | ||||
|   for(;;) { | ||||
|     if(k > 1) { | ||||
|       MEMCOPY(save, CMP_ATTRIBUTES(--k), recsize); | ||||
|     } | ||||
|     else { | ||||
|       hold = CMP_ATTRIBUTES(ir); | ||||
|       MEMCOPY(save, hold, recsize); | ||||
|       MEMCOPY(hold, base, recsize); | ||||
|       if(--ir == 1) { | ||||
|         MEMCOPY(base, save, recsize); | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     i = k; | ||||
|     j = k << 1; | ||||
|     while(j <= ir) { | ||||
|       hold = CMP_ATTRIBUTES(j); | ||||
|       if( (j < ir) && (findCompare(hold, CMP_ATTRIBUTES(j+1))*order < 0) ) { | ||||
|         hold += recsize; | ||||
|         j++; | ||||
|       } | ||||
|       if(findCompare(save, hold)*order < 0) { | ||||
|         MEMCOPY(CMP_ATTRIBUTES(i), hold, recsize); | ||||
|         i = j; | ||||
|         j <<= 1; | ||||
| 	    } | ||||
|       else | ||||
|         break; | ||||
|     } | ||||
|     MEMCOPY(CMP_ATTRIBUTES(i), save, recsize); | ||||
|   } | ||||
| 
 | ||||
|   FREE(save); | ||||
| } | ||||
| void hpsortex(void *attributes, int count, int offset, int recsize, MYBOOL descending, findCompare_func findCompare, int *tags) | ||||
| { | ||||
|   if(count < 2) | ||||
|     return; | ||||
|   if(tags == NULL) { | ||||
|     hpsort(attributes, count, offset, recsize, descending, findCompare); | ||||
|     return; | ||||
|   } | ||||
|   else { | ||||
|     register int  i, j, k, ir, order; | ||||
|     register char *hold, *base; | ||||
|     char          *save; | ||||
|     int           savetag; | ||||
| 
 | ||||
|     offset -= 1; | ||||
|     attributes = CMP_ATTRIBUTES(offset); | ||||
|     tags += offset; | ||||
|     base = CMP_ATTRIBUTES(1); | ||||
|     save = (char *) malloc(recsize); | ||||
|     if(descending) | ||||
|       order = -1; | ||||
|     else | ||||
|       order = 1; | ||||
| 
 | ||||
|     k = (count >> 1) + 1; | ||||
|     ir = count; | ||||
| 
 | ||||
|     for(;;) { | ||||
|       if(k > 1) { | ||||
|         MEMCOPY(save, CMP_ATTRIBUTES(--k), recsize); | ||||
|         savetag = tags[k]; | ||||
|       } | ||||
|       else { | ||||
|         hold = CMP_ATTRIBUTES(ir); | ||||
|         MEMCOPY(save, hold, recsize); | ||||
|         MEMCOPY(hold, base, recsize); | ||||
|         savetag = tags[ir]; | ||||
|         tags[ir] = tags[1]; | ||||
|         if(--ir == 1) { | ||||
|           MEMCOPY(base, save, recsize); | ||||
|           tags[1] = savetag; | ||||
|           break; | ||||
|         } | ||||
|       } | ||||
| 
 | ||||
|       i = k; | ||||
|       j = k << 1; | ||||
|       while(j <= ir) { | ||||
|         hold = CMP_ATTRIBUTES(j); | ||||
|         if( (j < ir) && (findCompare(hold, CMP_ATTRIBUTES(j+1))*order < 0) ) { | ||||
|           hold += recsize; | ||||
|           j++; | ||||
|         } | ||||
|         if(findCompare(save, hold)*order < 0) { | ||||
|           MEMCOPY(CMP_ATTRIBUTES(i), hold, recsize); | ||||
|           tags[i] = tags[j]; | ||||
|           i = j; | ||||
|           j <<= 1; | ||||
|   	    } | ||||
|         else | ||||
|           break; | ||||
|       } | ||||
|       MEMCOPY(CMP_ATTRIBUTES(i), save, recsize); | ||||
|       tags[i] = savetag; | ||||
|     } | ||||
| 
 | ||||
|     FREE(save); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* This is a "specialized generic" version of C.A.R Hoare's Quick Sort algorithm.
 | ||||
|    It will handle arrays that are already sorted, and arrays with duplicate keys. | ||||
|    The implementation here requires the user to pass a comparison operator and | ||||
|    assumes that the array passed has the QSORTrec format, which i.a. includes | ||||
|    the ability for to do linked list sorting. If the passed comparison operator | ||||
|    is NULL, the comparison is assumed to be for integers. */ | ||||
| #define QS_IS_switch 4    /* Threshold for switching to insertion sort */ | ||||
| 
 | ||||
| void QS_swap(UNIONTYPE QSORTrec a[], int i, int j) | ||||
| { | ||||
|   UNIONTYPE QSORTrec T = a[i]; | ||||
|   a[i] = a[j]; | ||||
|   a[j] = T; | ||||
| } | ||||
| int QS_addfirst(UNIONTYPE QSORTrec a[], void *mydata) | ||||
| { | ||||
|   a[0].pvoid2.ptr = mydata; | ||||
|   return( 0 ); | ||||
| } | ||||
| int QS_append(UNIONTYPE QSORTrec a[], int ipos, void *mydata) | ||||
| { | ||||
|   if(ipos <= 0) | ||||
|     ipos = QS_addfirst(a, mydata); | ||||
|   else | ||||
|     a[ipos].pvoid2.ptr = mydata; | ||||
|   return( ipos ); | ||||
| } | ||||
| void QS_replace(UNIONTYPE QSORTrec a[], int ipos, void *mydata) | ||||
| { | ||||
|   a[ipos].pvoid2.ptr = mydata; | ||||
| } | ||||
| void QS_insert(UNIONTYPE QSORTrec a[], int ipos, void *mydata, int epos) | ||||
| { | ||||
|   for(; epos > ipos; epos--) | ||||
|     a[epos] = a[epos-1]; | ||||
|   a[ipos].pvoid2.ptr = mydata; | ||||
| } | ||||
| void QS_delete(UNIONTYPE QSORTrec a[], int ipos, int epos) | ||||
| { | ||||
|   for(; epos > ipos; epos--) | ||||
|     a[epos] = a[epos-1]; | ||||
| } | ||||
| int QS_sort(UNIONTYPE QSORTrec a[], int l, int r, findCompare_func findCompare) | ||||
| { | ||||
|   register int i, j, nmove = 0; | ||||
|   UNIONTYPE QSORTrec v; | ||||
| 
 | ||||
|   /* Perform the a fast QuickSort */ | ||||
|   if((r-l) > QS_IS_switch) { | ||||
|     i = (r+l)/2; | ||||
| 
 | ||||
|     /* Tri-Median Method */ | ||||
|     if(findCompare((char *) &a[l], (char *) &a[i]) > 0) | ||||
|       { nmove++; QS_swap(a,l,i); } | ||||
|     if(findCompare((char *) &a[l], (char *) &a[r]) > 0) | ||||
|       { nmove++; QS_swap(a,l,r); } | ||||
|     if(findCompare((char *) &a[i], (char *) &a[r]) > 0) | ||||
|       { nmove++; QS_swap(a,i,r); } | ||||
| 
 | ||||
|     j = r-1; | ||||
|     QS_swap(a,i,j); | ||||
|     i = l; | ||||
|     v = a[j]; | ||||
|     for(;;) { | ||||
|       while(findCompare((char *) &a[++i], (char *) &v) < 0); | ||||
|       while(findCompare((char *) &a[--j], (char *) &v) > 0); | ||||
|       if(j < i) break; | ||||
|       nmove++; QS_swap (a,i,j); | ||||
|     } | ||||
|     nmove++; QS_swap(a,i,r-1); | ||||
|     nmove += QS_sort(a,l,j,findCompare); | ||||
|     nmove += QS_sort(a,i+1,r,findCompare); | ||||
|   } | ||||
|   return( nmove ); | ||||
| } | ||||
| int QS_finish(UNIONTYPE QSORTrec a[], int lo0, int hi0, findCompare_func findCompare) | ||||
| { | ||||
|   int      i, j, nmove = 0; | ||||
|   UNIONTYPE QSORTrec v; | ||||
| 
 | ||||
|   /* This is actually InsertionSort, which is faster for local sorts */ | ||||
|   for(i = lo0+1; i <= hi0; i++) { | ||||
| 
 | ||||
|     /* Save bottom-most item */ | ||||
|     v = a[i]; | ||||
| 
 | ||||
|     /* Shift down! */ | ||||
|     j = i; | ||||
|     while ((j > lo0) && (findCompare((char *) &a[j-1], (char *) &v) > 0)) { | ||||
|       a[j] = a[j-1]; | ||||
|       j--; | ||||
|       nmove++; | ||||
|     } | ||||
| 
 | ||||
|     /* Store bottom-most item at the top */ | ||||
|     a[j] = v; | ||||
|   } | ||||
|   return( nmove ); | ||||
| } | ||||
| MYBOOL QS_execute(UNIONTYPE QSORTrec a[], int count, findCompare_func findCompare, int *nswaps) | ||||
| { | ||||
|   int iswaps = 0; | ||||
| 
 | ||||
|   /* Check and initialize */ | ||||
|   if(count <= 1) | ||||
|     goto Finish; | ||||
|   count--; | ||||
| 
 | ||||
|   /* Perform sort */ | ||||
|   iswaps = QS_sort(a, 0, count, findCompare); | ||||
| #if QS_IS_switch > 0 | ||||
|   iswaps += QS_finish(a, 0, count, findCompare); | ||||
| #endif | ||||
| 
 | ||||
| Finish: | ||||
|   if(nswaps != NULL) | ||||
|     *nswaps = iswaps; | ||||
|   return( TRUE ); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /* Simple specialized bubble/insertion sort functions */ | ||||
| int sortByREAL(int *item, REAL *weight, int size, int offset, MYBOOL unique) | ||||
| { | ||||
|   int i, ii, saveI; | ||||
|   REAL saveW; | ||||
| 
 | ||||
|   for(i = 1; i < size; i++) { | ||||
|     ii = i+offset-1; | ||||
|     while ((ii >= offset) && (weight[ii] >= weight[ii+1])) { | ||||
|       if(weight[ii] == weight[ii+1]) { | ||||
|         if(unique) | ||||
|           return(item[ii]); | ||||
|       } | ||||
|       else { | ||||
|         saveI = item[ii]; | ||||
|         saveW = weight[ii]; | ||||
|         item[ii] = item[ii+1]; | ||||
|         weight[ii] = weight[ii+1]; | ||||
|         item[ii+1] = saveI; | ||||
|         weight[ii+1] = saveW; | ||||
|       } | ||||
|       ii--; | ||||
|     } | ||||
|   } | ||||
|   return(0); | ||||
| } | ||||
| int sortByINT(int *item, int *weight, int size, int offset, MYBOOL unique) | ||||
| { | ||||
|   int i, ii, saveI; | ||||
|   int saveW; | ||||
| 
 | ||||
|   for(i = 1; i < size; i++) { | ||||
|     ii = i+offset-1; | ||||
|     while ((ii >= offset) && (weight[ii] >= weight[ii+1])) { | ||||
|       if(weight[ii] == weight[ii+1]) { | ||||
|         if(unique) | ||||
|           return(item[ii]); | ||||
|       } | ||||
|       else { | ||||
|         saveI = item[ii]; | ||||
|         saveW = weight[ii]; | ||||
|         item[ii] = item[ii+1]; | ||||
|         weight[ii] = weight[ii+1]; | ||||
|         item[ii+1] = saveI; | ||||
|         weight[ii+1] = saveW; | ||||
|       } | ||||
|       ii--; | ||||
|     } | ||||
|   } | ||||
|   return(0); | ||||
| } | ||||
| REAL sortREALByINT(REAL *item, int *weight, int size, int offset, MYBOOL unique) | ||||
| { | ||||
|   int  i, ii, saveW; | ||||
|   REAL saveI; | ||||
| 
 | ||||
|   for(i = 1; i < size; i++) { | ||||
|     ii = i+offset-1; | ||||
|     while ((ii >= offset) && (weight[ii] >= weight[ii+1])) { | ||||
|       if(weight[ii] == weight[ii+1]) { | ||||
|         if(unique) | ||||
|           return(item[ii]); | ||||
|       } | ||||
|       else { | ||||
|         saveI = item[ii]; | ||||
|         saveW = weight[ii]; | ||||
|         item[ii] = item[ii+1]; | ||||
|         weight[ii] = weight[ii+1]; | ||||
|         item[ii+1] = saveI; | ||||
|         weight[ii+1] = saveW; | ||||
|       } | ||||
|       ii--; | ||||
|     } | ||||
|   } | ||||
|   return(0); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* Time and message functions */ | ||||
| double timeNow(void) | ||||
| { | ||||
| #ifdef INTEGERTIME | ||||
|   return((double)time(NULL)); | ||||
| #elif defined CLOCKTIME | ||||
|   return((double)clock()/CLOCKS_PER_SEC /* CLK_TCK */); | ||||
| #elif defined PosixTime | ||||
|   struct timespec t; | ||||
| # if 0 | ||||
|   clock_gettime(CLOCK_REALTIME, &t); | ||||
|   return( (double) t.tv_sec + (double) t.tv_nsec/1.0e9 ); | ||||
| # else | ||||
|   static double   timeBase; | ||||
| 
 | ||||
|   clock_gettime(CLOCK_MONOTONIC, &t); | ||||
|   if(timeBase == 0) | ||||
|     timeBase = clockNow() - ((double) t.tv_sec + (double) t.tv_nsec/1.0e9); | ||||
|   return( timeBase + (double) t.tv_sec + (double) t.tv_nsec/1.0e9 ); | ||||
| # endif | ||||
| #elif defined EnhTime | ||||
|   static LARGE_INTEGER freq; | ||||
|   static double        timeBase; | ||||
|   LARGE_INTEGER        now; | ||||
| 
 | ||||
|   QueryPerformanceCounter(&now); | ||||
|   if(timeBase == 0) { | ||||
|     QueryPerformanceFrequency(&freq); | ||||
|     timeBase = clockNow() - (double) now.QuadPart/(double) freq.QuadPart; | ||||
|   } | ||||
|   return( timeBase + (double) now.QuadPart/(double) freq.QuadPart ); | ||||
| #else | ||||
|   struct timeb buf; | ||||
| 
 | ||||
|   ftime(&buf); | ||||
|   return((double)buf.time+((double) buf.millitm)/1000.0); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* Miscellaneous reporting functions */ | ||||
| 
 | ||||
| /* List a vector of INT values for the given index range */ | ||||
| void blockWriteINT(FILE *output, char *label, int *myvector, int first, int last) | ||||
| { | ||||
|   int i, k = 0; | ||||
| 
 | ||||
|   fprintf(output, label); | ||||
|   fprintf(output, "\n"); | ||||
|   for(i = first; i <= last; i++) { | ||||
|     fprintf(output, " %5d", myvector[i]); | ||||
|     k++; | ||||
|     if(k % 12 == 0) { | ||||
|       fprintf(output, "\n"); | ||||
|       k = 0; | ||||
|     } | ||||
|   } | ||||
|   if(k % 12 != 0) | ||||
|     fprintf(output, "\n"); | ||||
| } | ||||
| 
 | ||||
| /* List a vector of MYBOOL values for the given index range */ | ||||
| void blockWriteBOOL(FILE *output, char *label, MYBOOL *myvector, int first, int last, MYBOOL asRaw) | ||||
| { | ||||
|   int i, k = 0; | ||||
| 
 | ||||
|   fprintf(output, label); | ||||
|   fprintf(output, "\n"); | ||||
|   for(i = first; i <= last; i++) { | ||||
|     if(asRaw) | ||||
|       fprintf(output, " %1d", myvector[i]); | ||||
|     else | ||||
|       fprintf(output, " %5s", my_boolstr(myvector[i])); | ||||
|     k++; | ||||
|     if(k % 36 == 0) { | ||||
|       fprintf(output, "\n"); | ||||
|       k = 0; | ||||
|     } | ||||
|   } | ||||
|   if(k % 36 != 0) | ||||
|     fprintf(output, "\n"); | ||||
| } | ||||
| 
 | ||||
| /* List a vector of REAL values for the given index range */ | ||||
| void blockWriteREAL(FILE *output, char *label, REAL *myvector, int first, int last) | ||||
| { | ||||
|   int i, k = 0; | ||||
| 
 | ||||
|   fprintf(output, label); | ||||
|   fprintf(output, "\n"); | ||||
|   for(i = first; i <= last; i++) { | ||||
|     fprintf(output, " %18g", myvector[i]); | ||||
|     k++; | ||||
|     if(k % 4 == 0) { | ||||
|       fprintf(output, "\n"); | ||||
|       k = 0; | ||||
|     } | ||||
|   } | ||||
|   if(k % 4 != 0) | ||||
|     fprintf(output, "\n"); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* CONSOLE vector and matrix printing routines */ | ||||
| void printvec( int n, REAL *x, int modulo ) | ||||
| { | ||||
|   int i; | ||||
| 
 | ||||
|   if (modulo <= 0) modulo = 5; | ||||
|   for (i = 1; i<=n; i++) { | ||||
|     if(mod(i, modulo) == 1) | ||||
|       printf("\n%2d:%12g", i, x[i]); | ||||
|     else | ||||
|       printf(" %2d:%12g", i, x[i]); | ||||
|   } | ||||
|   if(i % modulo != 0) printf("\n"); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void printmatUT( int size, int n, REAL *U, int modulo) | ||||
| { | ||||
|    int i, ll; | ||||
|    ll = 0; | ||||
|    for(i = 1; i<=n; i++) { | ||||
|      printvec(n-i+1, &U[ll], modulo); | ||||
|      ll += size-i+1; | ||||
|    } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void printmatSQ( int size, int n, REAL *X, int modulo) | ||||
| { | ||||
|    int i, ll; | ||||
|    ll = 0; | ||||
|    for(i = 1; i<=n; i++) { | ||||
|      printvec(n, &X[ll], modulo); | ||||
|      ll += size; | ||||
|    } | ||||
| } | ||||
| 
 | ||||
| /* Miscellaneous file functions */ | ||||
| #if defined _MSC_VER | ||||
| /* Check MS versions before 7 */ | ||||
| #if _MSC_VER < 1300 | ||||
| # define intptr_t long | ||||
| #endif | ||||
| 
 | ||||
| int fileCount( char *filemask ) | ||||
| { | ||||
|   struct   _finddata_t c_file; | ||||
|   intptr_t hFile; | ||||
|   int      count = 0; | ||||
| 
 | ||||
|   /* Find first .c file in current directory */ | ||||
|   if( (hFile = _findfirst( filemask, &c_file )) == -1L ) | ||||
|     ; | ||||
|   /* Iterate over all matching names */ | ||||
|   else { | ||||
|      while( _findnext( hFile, &c_file ) == 0 ) | ||||
|        count++; | ||||
|     _findclose( hFile ); | ||||
|   } | ||||
|   return( count ); | ||||
| } | ||||
| MYBOOL fileSearchPath( char *envvar, char *searchfile, char *foundpath ) | ||||
| { | ||||
|    char pathbuffer[_MAX_PATH]; | ||||
| 
 | ||||
|    _searchenv( searchfile, envvar, pathbuffer ); | ||||
|    if(pathbuffer[0] == '\0') | ||||
|      return( FALSE ); | ||||
|    else { | ||||
|      if(foundpath != NULL) | ||||
|        strcpy(foundpath, pathbuffer); | ||||
|      return( TRUE ); | ||||
|    } | ||||
| } | ||||
| #endif | ||||
|  | @ -1,324 +0,0 @@ | |||
| #ifndef HEADER_commonlib | ||||
| #define HEADER_commonlib | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| static char SpaceChars[3] = {" " "\7"}; | ||||
| static char NumChars[14]  = {"0123456789-+."}; | ||||
| 
 | ||||
| #define BIGNUMBER      1.0e+30 | ||||
| #define TINYNUMBER     1.0e-04 | ||||
| #define MACHINEPREC   2.22e-16 | ||||
| #define MATHPREC       1.0e-16 | ||||
| #define ERRLIMIT       1.0e-06 | ||||
| 
 | ||||
| #ifndef LINEARSEARCH | ||||
|   #define LINEARSEARCH 5 | ||||
| #endif | ||||
| 
 | ||||
| #if 0 | ||||
|   #define INTEGERTIME | ||||
| #endif | ||||
| 
 | ||||
| /* ************************************************************************ */ | ||||
| /* Define loadable library function headers                                 */ | ||||
| /* ************************************************************************ */ | ||||
| #if (defined WIN32) || (defined WIN64) | ||||
|   #define my_LoadLibrary(name)              LoadLibrary(name) | ||||
|   #define my_GetProcAddress(handle, name)   GetProcAddress(handle, name) | ||||
|   #define my_FreeLibrary(handle)            FreeLibrary(handle); \ | ||||
|                                             handle = NULL | ||||
| #else | ||||
|   #define my_LoadLibrary(name)              dlopen(name, RTLD_LAZY) | ||||
|   #define my_GetProcAddress(handle, name)   dlsym(handle, name) | ||||
|   #define my_FreeLibrary(handle)            dlclose(handle); \ | ||||
|                                             handle = NULL | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /* ************************************************************************ */ | ||||
| /* Define sizes of standard number types                                    */ | ||||
| /* ************************************************************************ */ | ||||
| #ifndef LLONG | ||||
|   #if defined __BORLANDC__ | ||||
|     #define LLONG __int64 | ||||
|   #elif !defined _MSC_VER || _MSC_VER >= 1310 | ||||
|     #define LLONG long long | ||||
|   #else | ||||
|     #define LLONG __int64 | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| #ifndef MYBOOL | ||||
|   #if 0 | ||||
|     #define MYBOOL unsigned int | ||||
|   #else | ||||
|     #define MYBOOL unsigned char | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| #ifndef REAL | ||||
|   #define REAL     double | ||||
| #endif | ||||
| #ifndef BLAS_prec | ||||
|   #define BLAS_prec "d" /* The BLAS precision prefix must correspond to the REAL type */ | ||||
| #endif | ||||
| 
 | ||||
| #ifndef REALXP | ||||
|   #if 1 | ||||
|     #define REALXP long double  /* Set local accumulation variable as long double */ | ||||
|   #else | ||||
|     #define REALXP REAL          /* Set local accumulation as default precision */ | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| #ifndef my_boolstr | ||||
|   #define my_boolstr(x)          (!(x) ? "FALSE" : "TRUE") | ||||
| #endif | ||||
| 
 | ||||
| #ifndef NULL | ||||
|   #define NULL 	       0 | ||||
| #endif | ||||
| 
 | ||||
| #ifndef FALSE | ||||
|   #define FALSE        0 | ||||
|   #define TRUE         1 | ||||
| #endif | ||||
| 
 | ||||
| #ifndef DEF_STRBUFSIZE | ||||
|   #define DEF_STRBUFSIZE   512 | ||||
| #endif | ||||
| #ifndef MAXINT32 | ||||
|   #define MAXINT32  2147483647 | ||||
| #endif | ||||
| #ifndef MAXUINT32 | ||||
|   #define MAXUINT32 4294967295 | ||||
| #endif | ||||
| 
 | ||||
| #ifndef MAXINT64 | ||||
|   #if defined _LONGLONG || defined __LONG_LONG_MAX__ || defined LLONG_MAX | ||||
|     #define MAXINT64   9223372036854775807ll | ||||
|   #else | ||||
|     #define MAXINT64   9223372036854775807l | ||||
|   #endif | ||||
| #endif | ||||
| #ifndef MAXUINT64 | ||||
|   #if defined _LONGLONG || defined __LONG_LONG_MAX__ || defined LLONG_MAX | ||||
|     #define MAXUINT64 18446744073709551616ll | ||||
|   #else | ||||
|     #define MAXUINT64 18446744073709551616l | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| #ifndef DOFASTMATH | ||||
|   #define DOFASTMATH | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| #ifndef CALLOC | ||||
| #define CALLOC(ptr, nr)\ | ||||
|   if(!((void *) ptr = calloc((size_t)(nr), sizeof(*ptr))) && nr) {\ | ||||
|     printf("calloc of %d bytes failed on line %d of file %s\n",\ | ||||
|            (size_t) nr * sizeof(*ptr), __LINE__, __FILE__);\ | ||||
|   } | ||||
| #endif | ||||
| 
 | ||||
| #ifndef MALLOC | ||||
| #define MALLOC(ptr, nr)\ | ||||
|   if(!((void *) ptr = malloc((size_t)((size_t) (nr) * sizeof(*ptr)))) && nr) {\ | ||||
|     printf("malloc of %d bytes failed on line %d of file %s\n",\ | ||||
|            (size_t) nr * sizeof(*ptr), __LINE__, __FILE__);\ | ||||
|   } | ||||
| #endif | ||||
| 
 | ||||
| #ifndef REALLOC | ||||
| #define REALLOC(ptr, nr)\ | ||||
|   if(!((void *) ptr = realloc(ptr, (size_t)((size_t) (nr) * sizeof(*ptr)))) && nr) {\ | ||||
|     printf("realloc of %d bytes failed on line %d of file %s\n",\ | ||||
|            (size_t) nr * sizeof(*ptr), __LINE__, __FILE__);\ | ||||
|   } | ||||
| #endif | ||||
| 
 | ||||
| #ifndef FREE | ||||
| #define FREE(ptr)\ | ||||
|   if((void *) ptr != NULL) {\ | ||||
|     free(ptr);\ | ||||
|     ptr = NULL; \ | ||||
|   } | ||||
| #endif | ||||
| 
 | ||||
| #ifndef MEMCOPY | ||||
| #define MEMCOPY(nptr, optr, nr)\ | ||||
|   memcpy((nptr), (optr), (size_t)((size_t)(nr) * sizeof(*(optr)))) | ||||
| #endif | ||||
| 
 | ||||
| #ifndef MEMMOVE | ||||
| #define MEMMOVE(nptr, optr, nr)\ | ||||
|   memmove((nptr), (optr), (size_t)((size_t)(nr) * sizeof(*(optr)))) | ||||
| #endif | ||||
| 
 | ||||
| #ifndef MEMALLOCCOPY | ||||
| #define MEMALLOCCOPY(nptr, optr, nr)\ | ||||
|   {MALLOC(nptr, (size_t)(nr));\ | ||||
|    MEMCOPY(nptr, optr, (size_t)(nr));} | ||||
| #endif | ||||
| 
 | ||||
| #ifndef STRALLOCCOPY | ||||
| #define STRALLOCCOPY(nstr, ostr)\ | ||||
|   {nstr = (char *) malloc((size_t) (strlen(ostr) + 1));\ | ||||
|    strcpy(nstr, ostr);} | ||||
| #endif | ||||
| 
 | ||||
| #ifndef MEMCLEAR | ||||
| /*#define useMMX*/ | ||||
| #ifdef useMMX | ||||
|   #define MEMCLEAR(ptr, nr)\ | ||||
|     mem_set((ptr), '\0', (size_t)((size_t)(nr) * sizeof(*(ptr)))) | ||||
| #else | ||||
|   #define MEMCLEAR(ptr, nr)\ | ||||
|     memset((ptr), '\0', (size_t)((size_t)(nr) * sizeof(*(ptr)))) | ||||
| #endif | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| #define MIN(x, y)         ((x) < (y) ? (x) : (y)) | ||||
| #define MAX(x, y)         ((x) > (y) ? (x) : (y)) | ||||
| #define SETMIN(x, y)      if((x) > (y)) x = y | ||||
| #define SETMAX(x, y)      if((x) < (y)) x = y | ||||
| #define LIMIT(lo, x, hi)  ((x < (lo) ? lo : ((x) > hi ? hi : x))) | ||||
| #define BETWEEN(x, a, b)  (MYBOOL) (((x)-(a)) * ((x)-(b)) <= 0) | ||||
| #define IF(t, x, y)       ((t) ? (x) : (y)) | ||||
| #define SIGN(x)           ((x) < 0 ? -1 : 1) | ||||
| 
 | ||||
| #define DELTA_SIZE(newSize, oldSize) ((int) ((newSize) * MIN(1.33, pow(1.5, fabs((double)newSize)/((oldSize+newSize)+1))))) | ||||
| 
 | ||||
| #ifndef CMP_CALLMODEL | ||||
| #if (defined WIN32) || (defined WIN64) | ||||
|   #define CMP_CALLMODEL _cdecl | ||||
| #else | ||||
|   #define CMP_CALLMODEL | ||||
| #endif | ||||
| #endif | ||||
| 
 | ||||
| typedef int (CMP_CALLMODEL findCompare_func)(const void *current, const void *candidate); | ||||
| #define CMP_COMPARE(current, candidate) ( current < candidate ? -1 : (current > candidate ? 1 : 0) ) | ||||
| #define CMP_ATTRIBUTES(item)            (((char *) attributes)+(item)*recsize) | ||||
| 
 | ||||
| 
 | ||||
| #ifndef UNIONTYPE | ||||
|   #ifdef __cplusplus | ||||
|     #define UNIONTYPE | ||||
|   #else | ||||
|     #define UNIONTYPE union | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| /* This defines a 16 byte sort record (in both 32 and 64 bit OS-es) */ | ||||
| typedef struct _QSORTrec1 | ||||
| { | ||||
|   void     *ptr; | ||||
|   void     *ptr2; | ||||
| } QSORTrec1; | ||||
| typedef struct _QSORTrec2 | ||||
| { | ||||
|   void     *ptr; | ||||
|   double   realval; | ||||
| } QSORTrec2; | ||||
| typedef struct _QSORTrec3 | ||||
| { | ||||
|   void     *ptr; | ||||
|   int      intval; | ||||
|   int      intpar1; | ||||
| } QSORTrec3; | ||||
| typedef struct _QSORTrec4 | ||||
| { | ||||
|   REAL     realval; | ||||
|   int      intval; | ||||
|   int      intpar1; | ||||
| } QSORTrec4; | ||||
| typedef struct _QSORTrec5 | ||||
| { | ||||
|   double   realval; | ||||
|   long int longval; | ||||
| } QSORTrec5; | ||||
| typedef struct _QSORTrec6 | ||||
| { | ||||
|   double   realval; | ||||
|   double   realpar1; | ||||
| } QSORTrec6; | ||||
| typedef struct _QSORTrec7 | ||||
| { | ||||
|   int      intval; | ||||
|   int      intpar1; | ||||
|   int      intpar2; | ||||
|   int      intpar3; | ||||
| } QSORTrec7; | ||||
| union QSORTrec | ||||
| { | ||||
|   QSORTrec1 pvoid2; | ||||
|   QSORTrec2 pvoidreal; | ||||
|   QSORTrec3 pvoidint2; | ||||
|   QSORTrec4 realint2; | ||||
|   QSORTrec5 reallong; | ||||
|   QSORTrec6 real2; | ||||
|   QSORTrec7 int4; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
|   extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| int intpow(int base, int exponent); | ||||
| int mod(int n, int d); | ||||
| 
 | ||||
| void strtoup(char *s); | ||||
| void strtolo(char *s); | ||||
| void strcpyup(char *t, char *s); | ||||
| void strcpylo(char *t, char *s); | ||||
| 
 | ||||
| MYBOOL so_stdname(char *stdname, char *descname, int buflen); | ||||
| int gcd(LLONG a, LLONG b, int *c, int *d); | ||||
| 
 | ||||
| int findIndex(int target, int *attributes, int count, int offset); | ||||
| int findIndexEx(void *target, void *attributes, int count, int offset, int recsize, findCompare_func findCompare, MYBOOL ascending); | ||||
| 
 | ||||
| int CMP_CALLMODEL compareCHAR(const void *current, const void *candidate); | ||||
| int CMP_CALLMODEL compareINT(const void *current, const void *candidate); | ||||
| int CMP_CALLMODEL compareREAL(const void *current, const void *candidate); | ||||
| void hpsort(void *attributes, int count, int offset, int recsize, MYBOOL descending, findCompare_func findCompare); | ||||
| void hpsortex(void *attributes, int count, int offset, int recsize, MYBOOL descending, findCompare_func findCompare, int *tags); | ||||
| 
 | ||||
| void QS_swap(UNIONTYPE QSORTrec a[], int i, int j); | ||||
| int QS_addfirst(UNIONTYPE QSORTrec a[], void *mydata); | ||||
| int QS_append(UNIONTYPE QSORTrec a[], int ipos, void *mydata); | ||||
| void QS_replace(UNIONTYPE QSORTrec a[], int ipos, void *mydata); | ||||
| void QS_insert(UNIONTYPE QSORTrec a[], int ipos, void *mydata, int epos); | ||||
| void QS_delete(UNIONTYPE QSORTrec a[], int ipos, int epos); | ||||
| MYBOOL QS_execute(UNIONTYPE QSORTrec a[], int count, findCompare_func findCompare, int *nswaps); | ||||
| 
 | ||||
| int sortByREAL(int *item, REAL *weight, int size, int offset, MYBOOL unique); | ||||
| int sortByINT(int *item, int *weight, int size, int offset, MYBOOL unique); | ||||
| REAL sortREALByINT(REAL *item, int *weight, int size, int offset, MYBOOL unique); | ||||
| 
 | ||||
| double timeNow(void); | ||||
| 
 | ||||
| void blockWriteBOOL(FILE *output, char *label, MYBOOL *myvector, int first, int last, MYBOOL asRaw); | ||||
| void blockWriteINT(FILE *output, char *label, int *myvector, int first, int last); | ||||
| void blockWriteREAL(FILE *output, char *label, REAL *myvector, int first, int last); | ||||
| 
 | ||||
| void printvec( int n, REAL *x, int modulo ); | ||||
| void printmatSQ( int size, int n, REAL *X, int modulo ); | ||||
| void printmatUT( int size, int n, REAL *U, int modulo ); | ||||
| 
 | ||||
| #if defined _MSC_VER | ||||
| int fileCount( char *filemask ); | ||||
| MYBOOL fileSearchPath( char *envvar, char *searchfile, char *foundpath ); | ||||
| #endif | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
|   } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* HEADER_commonlib */ | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -1,67 +0,0 @@ | |||
| #ifndef IOHB_H | ||||
| #define IOHB_H | ||||
| 
 | ||||
| #include<stdio.h> | ||||
| #include<stdlib.h> | ||||
| #include<sys/types.h> | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| int readHB_info(const char* filename, int* M, int* N, int* nz, char** Type, | ||||
|                                                       int* Nrhs); | ||||
| 
 | ||||
| int readHB_header(FILE* in_file, char* Title, char* Key, char* Type, | ||||
|                     int* Nrow, int* Ncol, int* Nnzero, int* Nrhs, int* Nrhsix, | ||||
|                     char* Ptrfmt, char* Indfmt, char* Valfmt, char* Rhsfmt, | ||||
|                     int* Ptrcrd, int* Indcrd, int* Valcrd, int* Rhscrd, | ||||
|                     char *Rhstype); | ||||
| 
 | ||||
| int readHB_mat_double(const char* filename, int colptr[], int rowind[], | ||||
|                                                                  double val[]); | ||||
| 
 | ||||
| int readHB_newmat_double(const char* filename, int* M, int* N, int* nonzeros, | ||||
|                          int** colptr, int** rowind, double** val); | ||||
| 
 | ||||
| int readHB_aux_double(const char* filename, const char AuxType, double b[]); | ||||
| 
 | ||||
| int readHB_newaux_double(const char* filename, const char AuxType, double** b); | ||||
| 
 | ||||
| int writeHB_mat_double(const char* filename, int M, int N, | ||||
|                         int nz, const int colptr[], const int rowind[], | ||||
|                         const double val[], int Nrhs, const double rhs[], | ||||
|                         const double guess[], const double exact[], | ||||
|                         const char* Title, const char* Key, const char* Type, | ||||
|                         char* Ptrfmt, char* Indfmt, char* Valfmt, char* Rhsfmt, | ||||
|                         const char* Rhstype); | ||||
| 
 | ||||
| int readHB_mat_char(const char* filename, int colptr[], int rowind[], | ||||
|                                            char val[], char* Valfmt); | ||||
| 
 | ||||
| int readHB_newmat_char(const char* filename, int* M, int* N, int* nonzeros, int** colptr, | ||||
|                           int** rowind, char** val, char** Valfmt); | ||||
| 
 | ||||
| int readHB_aux_char(const char* filename, const char AuxType, char b[]); | ||||
| 
 | ||||
| int readHB_newaux_char(const char* filename, const char AuxType, char** b, char** Rhsfmt); | ||||
| 
 | ||||
| int writeHB_mat_char(const char* filename, int M, int N, | ||||
|                         int nz, const int colptr[], const int rowind[], | ||||
|                         const char val[], int Nrhs, const char rhs[], | ||||
|                         const char guess[], const char exact[], | ||||
|                         const char* Title, const char* Key, const char* Type, | ||||
|                         char* Ptrfmt, char* Indfmt, char* Valfmt, char* Rhsfmt, | ||||
|                         const char* Rhstype); | ||||
| 
 | ||||
| int ParseIfmt(char* fmt, int* perline, int* width); | ||||
| 
 | ||||
| int ParseRfmt(char* fmt, int* perline, int* width, int* prec, int* flag); | ||||
| 
 | ||||
| void IOHBTerminate(char* message); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif | ||||
|  | @ -1,796 +0,0 @@ | |||
| 
 | ||||
| /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 | ||||
|    LUSOL routines from the Stanford Optimization Laboratory | ||||
|    The parts included are: | ||||
|     lusol1      Factor a given matrix A from scratch (lu1fac). | ||||
|     lusol2      Heap-management routines for lu1fac. | ||||
|     lusol6      Solve with the current LU factors. | ||||
|     lusol7      Utilities for all update routines. | ||||
|     lusol8      Replace a column (Bartels-Golub update). | ||||
|    ------------------------------------------------------------------ | ||||
|    26 Apr 2002: TCP implemented using heap data structure. | ||||
|    01 May 2002: lu1DCP implemented. | ||||
|    07 May 2002: lu1mxc must put 0.0 at top of empty columns. | ||||
|    09 May 2002: lu1mCP implements Markowitz with cols searched | ||||
|                 in heap order. | ||||
|                 Often faster (searching 20 or 40 cols) but more dense. | ||||
|    11 Jun 2002: TRP implemented. | ||||
|                 lu1mRP implements Markowitz with Threshold Rook | ||||
|                 Pivoting. | ||||
|                 lu1mxc maintains max col elements  (was lu1max.) | ||||
|                 lu1mxr maintains max row elements. | ||||
|    12 Jun 2002: lu1mCP seems too slow on big problems (e.g. memplus). | ||||
|                 Disabled it for the moment.  (Use lu1mar + TCP.) | ||||
|    14 Dec 2002: TSP implemented. | ||||
|                 lu1mSP implements Markowitz with TSP. | ||||
|    07 Mar 2003: character*1, character*2 changed to f90 form. | ||||
|                 Comments changed from * in column to ! in column 1. | ||||
|                 Comments kept within column 72 to avoid compiler | ||||
|                 warning. | ||||
|    06 Mar 2004: Translation to C by Kjell Eikland with the addition | ||||
|                 of data wrappers, parametric constants, various | ||||
|                 helper routines, and dynamic memory reallocation. | ||||
|    26 May 2004: Added LUSOL_IP_UPDATELIMIT parameter and provided | ||||
|                 for dynamic memory expansion based on possible | ||||
|                 forward requirements. | ||||
|    08 Jul 2004: Revised logic in lu6chk based on new code from | ||||
|                 Michael Saunders. | ||||
|    01 Dec 2005: Add support for CMEX interface (disable by undef MATLAB) | ||||
|                 Also include various bug fixes (disable by undef YZHANG) | ||||
|                 Yin Zhang <yzhang@cs.utexas.edu> | ||||
|    01 Jan 2006: Added storage of singular indeces, not only the last. | ||||
|    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <stdarg.h> | ||||
| #include <string.h> | ||||
| #include <float.h> | ||||
| #include <math.h> | ||||
| #include "lusol.h" | ||||
| #include "myblas.h" | ||||
| #ifdef MATLAB | ||||
|   #include "mex.h" | ||||
| #endif | ||||
| 
 | ||||
| /* LUSOL Object creation and destruction */ | ||||
| 
 | ||||
| void *clean_realloc(void *oldptr, int width, int newsize, int oldsize) | ||||
| { | ||||
|   newsize *= width; | ||||
|   oldsize *= width; | ||||
|   oldptr = LUSOL_REALLOC(oldptr, newsize); | ||||
|   if(newsize > oldsize) | ||||
| /*    MEMCLEAR(oldptr+oldsize, newsize-oldsize); */ | ||||
|     memset((char *)oldptr+oldsize, '\0', newsize-oldsize); | ||||
|   return(oldptr); | ||||
| } | ||||
| 
 | ||||
| MYBOOL LUSOL_realloc_a(LUSOLrec *LUSOL, int newsize) | ||||
| { | ||||
|   int oldsize; | ||||
| 
 | ||||
|   if(newsize < 0) | ||||
|     newsize = LUSOL->lena + MAX(abs(newsize), LUSOL_MINDELTA_a); | ||||
| 
 | ||||
|   oldsize = LUSOL->lena; | ||||
|   LUSOL->lena = newsize; | ||||
|   if(newsize > 0) | ||||
|     newsize++; | ||||
|   if(oldsize > 0) | ||||
|     oldsize++; | ||||
| 
 | ||||
|   LUSOL->a    = (REAL *) clean_realloc(LUSOL->a,    sizeof(*(LUSOL->a)), | ||||
|                                                     newsize, oldsize); | ||||
|   LUSOL->indc = (int *)  clean_realloc(LUSOL->indc, sizeof(*(LUSOL->indc)), | ||||
|                                                     newsize, oldsize); | ||||
|   LUSOL->indr = (int *)  clean_realloc(LUSOL->indr, sizeof(*(LUSOL->indr)), | ||||
|                                                     newsize, oldsize); | ||||
|   if((newsize == 0) || | ||||
|      ((LUSOL->a != NULL) && (LUSOL->indc != NULL) && (LUSOL->indr != NULL))) | ||||
|     return( TRUE ); | ||||
|   else | ||||
|     return( FALSE ); | ||||
| } | ||||
| 
 | ||||
| MYBOOL LUSOL_expand_a(LUSOLrec *LUSOL, int *delta_lena, int *right_shift) | ||||
| { | ||||
| #ifdef StaticMemAlloc | ||||
|   return( FALSE ); | ||||
| #else | ||||
|   int LENA, NFREE, LFREE; | ||||
| 
 | ||||
|   /* Add expansion factor to avoid having to resize too often/too much;
 | ||||
|      (exponential formula suggested by Michael A. Saunders) */ | ||||
|   LENA = LUSOL->lena; | ||||
|   *delta_lena = DELTA_SIZE(*delta_lena, LENA); | ||||
| 
 | ||||
|   /* Expand it! */ | ||||
|   if((*delta_lena <= 0) || !LUSOL_realloc_a(LUSOL, LENA+(*delta_lena))) | ||||
|     return( FALSE ); | ||||
| 
 | ||||
|   /* Make sure we return the actual memory increase of a */ | ||||
|   *delta_lena = LUSOL->lena-LENA; | ||||
| 
 | ||||
|   /* Shift the used memory area to the right */ | ||||
|   LFREE = *right_shift; | ||||
|   NFREE = LFREE+*delta_lena; | ||||
|   LENA  -= LFREE-1; | ||||
|   MEMMOVE(LUSOL->a+NFREE,    LUSOL->a+LFREE,    LENA); | ||||
|   MEMMOVE(LUSOL->indr+NFREE, LUSOL->indr+LFREE, LENA); | ||||
|   MEMMOVE(LUSOL->indc+NFREE, LUSOL->indc+LFREE, LENA); | ||||
| 
 | ||||
|   /* Also return the new starting position for the used memory area of a */ | ||||
|   *right_shift  = NFREE; | ||||
| 
 | ||||
|   LUSOL->expanded_a++; | ||||
|   return( TRUE ); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| MYBOOL LUSOL_realloc_r(LUSOLrec *LUSOL, int newsize) | ||||
| { | ||||
|   int oldsize; | ||||
| 
 | ||||
|   if(newsize < 0) | ||||
|     newsize = LUSOL->maxm + MAX(abs(newsize), LUSOL_MINDELTA_rc); | ||||
| 
 | ||||
|   oldsize = LUSOL->maxm; | ||||
|   LUSOL->maxm = newsize; | ||||
|   if(newsize > 0) | ||||
|     newsize++; | ||||
|   if(oldsize > 0) | ||||
|     oldsize++; | ||||
| 
 | ||||
|   LUSOL->lenr  = (int *) clean_realloc(LUSOL->lenr,  sizeof(*(LUSOL->lenr)), | ||||
|                                                      newsize, oldsize); | ||||
|   LUSOL->ip    = (int *) clean_realloc(LUSOL->ip,    sizeof(*(LUSOL->ip)), | ||||
|                                                      newsize, oldsize); | ||||
|   LUSOL->iqloc = (int *) clean_realloc(LUSOL->iqloc, sizeof(*(LUSOL->iqloc)), | ||||
|                                                      newsize, oldsize); | ||||
|   LUSOL->ipinv = (int *) clean_realloc(LUSOL->ipinv, sizeof(*(LUSOL->ipinv)), | ||||
|                                                      newsize, oldsize); | ||||
|   LUSOL->locr  = (int *) clean_realloc(LUSOL->locr,  sizeof(*(LUSOL->locr)), | ||||
|                                                      newsize, oldsize); | ||||
| 
 | ||||
|   if((newsize == 0) || | ||||
|      ((LUSOL->lenr != NULL) && | ||||
|       (LUSOL->ip != NULL) && (LUSOL->iqloc != NULL) && | ||||
|       (LUSOL->ipinv != NULL) && (LUSOL->locr != NULL))) { | ||||
| 
 | ||||
| #ifndef ClassicHamaxR | ||||
| #ifdef AlwaysSeparateHamaxR | ||||
|     if(LUSOL->luparm[LUSOL_IP_PIVOTTYPE] == LUSOL_PIVMOD_TRP) | ||||
| #endif | ||||
|     { | ||||
|       LUSOL->amaxr = (REAL *) clean_realloc(LUSOL->amaxr, sizeof(*(LUSOL->amaxr)), | ||||
|                                                           newsize, oldsize); | ||||
|       if((newsize > 0) && (LUSOL->amaxr == NULL)) | ||||
|         return( FALSE ); | ||||
|     } | ||||
| #endif | ||||
|     return( TRUE ); | ||||
|   } | ||||
|   else | ||||
|     return( FALSE ); | ||||
| } | ||||
| 
 | ||||
| MYBOOL LUSOL_realloc_c(LUSOLrec *LUSOL, int newsize) | ||||
| { | ||||
|   int oldsize; | ||||
| 
 | ||||
|   if(newsize < 0) | ||||
|     newsize = LUSOL->maxn + MAX(abs(newsize), LUSOL_MINDELTA_rc); | ||||
| 
 | ||||
|   oldsize = LUSOL->maxn; | ||||
|   LUSOL->maxn = newsize; | ||||
|   if(newsize > 0) | ||||
|     newsize++; | ||||
|   if(oldsize > 0) | ||||
|     oldsize++; | ||||
| 
 | ||||
|   LUSOL->lenc  = (int *)  clean_realloc(LUSOL->lenc,  sizeof(*(LUSOL->lenc)), | ||||
|                                                       newsize, oldsize); | ||||
|   LUSOL->iq    = (int *)  clean_realloc(LUSOL->iq,    sizeof(*(LUSOL->iq)), | ||||
|                                                       newsize, oldsize); | ||||
|   LUSOL->iploc = (int *)  clean_realloc(LUSOL->iploc, sizeof(*(LUSOL->iploc)), | ||||
|                                                       newsize, oldsize); | ||||
|   LUSOL->iqinv = (int *)  clean_realloc(LUSOL->iqinv, sizeof(*(LUSOL->iqinv)), | ||||
|                                                       newsize, oldsize); | ||||
|   LUSOL->locc  = (int *)  clean_realloc(LUSOL->locc,  sizeof(*(LUSOL->locc)), | ||||
|                                                       newsize, oldsize); | ||||
|   LUSOL->w     = (REAL *) clean_realloc(LUSOL->w,     sizeof(*(LUSOL->w)), | ||||
|                                                       newsize, oldsize); | ||||
| #ifdef LUSOLSafeFastUpdate | ||||
|   LUSOL->vLU6L = (REAL *) clean_realloc(LUSOL->vLU6L, sizeof(*(LUSOL->vLU6L)), | ||||
|                                                       newsize, oldsize); | ||||
| #else | ||||
|   LUSOL->vLU6L = LUSOL->w; | ||||
| #endif | ||||
| 
 | ||||
|   if((newsize == 0) || | ||||
|      ((LUSOL->w != NULL) && (LUSOL->lenc != NULL) && | ||||
|       (LUSOL->iq != NULL) && (LUSOL->iploc != NULL) && | ||||
|       (LUSOL->iqinv != NULL) && (LUSOL->locc != NULL))) { | ||||
| 
 | ||||
| #ifndef ClassicHamaxR | ||||
|     if(LUSOL->luparm[LUSOL_IP_PIVOTTYPE] == LUSOL_PIVMOD_TCP) { | ||||
|       LUSOL->Ha = (REAL *) clean_realloc(LUSOL->Ha,   sizeof(*(LUSOL->Ha)), | ||||
|                                                       newsize, oldsize); | ||||
|       LUSOL->Hj = (int *)  clean_realloc(LUSOL->Hj,   sizeof(*(LUSOL->Hj)), | ||||
|                                                       newsize, oldsize); | ||||
|       LUSOL->Hk = (int *)  clean_realloc(LUSOL->Hk,   sizeof(*(LUSOL->Hk)), | ||||
|                                                       newsize, oldsize); | ||||
|       if((newsize > 0) && | ||||
|          ((LUSOL->Ha == NULL) || (LUSOL->Hj == NULL) || (LUSOL->Hk == NULL))) | ||||
|         return( FALSE ); | ||||
|     } | ||||
| #endif | ||||
| #ifndef ClassicdiagU | ||||
|     if(LUSOL->luparm[LUSOL_IP_KEEPLU] == FALSE) { | ||||
|       LUSOL->diagU = (REAL *) clean_realloc(LUSOL->diagU, sizeof(*(LUSOL->diagU)), | ||||
|                                                           newsize, oldsize); | ||||
|       if((newsize > 0) && (LUSOL->diagU == NULL)) | ||||
|         return( FALSE ); | ||||
|     } | ||||
| #endif | ||||
| 
 | ||||
|     return( TRUE ); | ||||
|   } | ||||
|   else | ||||
|     return( FALSE ); | ||||
| } | ||||
| 
 | ||||
| LUSOLrec *LUSOL_create(FILE *outstream, int msgfil, int pivotmodel, int updatelimit) | ||||
| { | ||||
|   LUSOLrec *newLU; | ||||
| 
 | ||||
|   newLU = (LUSOLrec *) LUSOL_CALLOC(1, sizeof(*newLU)); | ||||
|   if(newLU == NULL) | ||||
|     return( newLU ); | ||||
| 
 | ||||
|   newLU->luparm[LUSOL_IP_SCALAR_NZA]       = LUSOL_MULT_nz_a; | ||||
|   newLU->outstream = outstream; | ||||
|   newLU->luparm[LUSOL_IP_PRINTUNIT]        = msgfil; | ||||
|   newLU->luparm[LUSOL_IP_PRINTLEVEL]       = LUSOL_MSG_SINGULARITY; | ||||
| 
 | ||||
|   LUSOL_setpivotmodel(newLU, pivotmodel, LUSOL_PIVTOL_DEFAULT); | ||||
| 
 | ||||
|   newLU->parmlu[LUSOL_RP_GAMMA]            = LUSOL_DEFAULT_GAMMA; | ||||
| 
 | ||||
|   newLU->parmlu[LUSOL_RP_ZEROTOLERANCE]    = 3.0e-13; | ||||
| 
 | ||||
|   newLU->parmlu[LUSOL_RP_SMALLDIAG_U]      = /*3.7e-11;*/ | ||||
|   newLU->parmlu[LUSOL_RP_EPSDIAG_U]        = 3.7e-11; | ||||
| 
 | ||||
|   newLU->parmlu[LUSOL_RP_COMPSPACE_U]      = 3.0e+0; | ||||
| 
 | ||||
|   newLU->luparm[LUSOL_IP_MARKOWITZ_MAXCOL] = 5; | ||||
|   newLU->parmlu[LUSOL_RP_MARKOWITZ_CONLY]  = 0.3e+0; | ||||
|   newLU->parmlu[LUSOL_RP_MARKOWITZ_DENSE]  = 0.5e+0; | ||||
| 
 | ||||
|   newLU->parmlu[LUSOL_RP_SMARTRATIO]       = LUSOL_DEFAULT_SMARTRATIO; | ||||
| #ifdef ForceRowBasedL0 | ||||
|   newLU->luparm[LUSOL_IP_ACCELERATION]     = LUSOL_BASEORDER; | ||||
| #endif | ||||
|   newLU->luparm[LUSOL_IP_KEEPLU]           = TRUE; | ||||
|   newLU->luparm[LUSOL_IP_UPDATELIMIT]      = updatelimit; | ||||
| 
 | ||||
|   init_BLAS(); | ||||
| 
 | ||||
|   return( newLU ); | ||||
| } | ||||
| 
 | ||||
| MYBOOL LUSOL_sizeto(LUSOLrec *LUSOL, int init_r, int init_c, int init_a) | ||||
| { | ||||
|   if(init_c == 0) | ||||
|     LUSOL_FREE(LUSOL->isingular); | ||||
|   if(LUSOL_realloc_a(LUSOL, init_a) && | ||||
|      LUSOL_realloc_r(LUSOL, init_r) && | ||||
|      LUSOL_realloc_c(LUSOL, init_c)) | ||||
|     return( TRUE ); | ||||
|   else | ||||
|     return( FALSE ); | ||||
| } | ||||
| 
 | ||||
| char *LUSOL_pivotLabel(LUSOLrec *LUSOL) | ||||
| { | ||||
|   static /*const*/ char *pivotText[LUSOL_PIVMOD_MAX+1] = | ||||
|   {"TPP", "TRP", "TCP", "TSP"}; | ||||
|   return(pivotText[LUSOL->luparm[LUSOL_IP_PIVOTTYPE]]); | ||||
| } | ||||
| 
 | ||||
| void LUSOL_setpivotmodel(LUSOLrec *LUSOL, int pivotmodel, int initlevel) | ||||
| { | ||||
|   REAL newFM, newUM; | ||||
| 
 | ||||
|   /* Set pivotmodel if specified */ | ||||
|   if(pivotmodel > LUSOL_PIVMOD_NOCHANGE) { | ||||
|     if((pivotmodel <= LUSOL_PIVMOD_DEFAULT) || (pivotmodel > LUSOL_PIVMOD_MAX)) | ||||
|       pivotmodel = LUSOL_PIVMOD_TPP; | ||||
|     LUSOL->luparm[LUSOL_IP_PIVOTTYPE]        = pivotmodel; | ||||
|   } | ||||
| 
 | ||||
|   /* Check if we need bother about changing tolerances */ | ||||
|   if((initlevel <= LUSOL_PIVTOL_NOCHANGE) || (initlevel > LUSOL_PIVTOL_MAX)) | ||||
|     return; | ||||
| 
 | ||||
|   /* Set default pivot tolerances
 | ||||
|      (note that UPDATEMAX should always be <= FACTORMAX) */ | ||||
|   if(initlevel == LUSOL_PIVTOL_BAGGY) {        /* Extra-loose pivot thresholds */ | ||||
|     newFM = 500.0; | ||||
|     newUM = newFM / 20; | ||||
|   } | ||||
|   else if(initlevel == LUSOL_PIVTOL_LOOSE) {  /* Moderately tight pivot tolerances */ | ||||
|     newFM = 100.0; | ||||
|     newUM = newFM / 10; | ||||
|   } | ||||
|   else if(initlevel == LUSOL_PIVTOL_NORMAL) { /* Standard pivot tolerances */ | ||||
|     newFM = 28.0; | ||||
|     newUM = newFM / 4; | ||||
|   } | ||||
|   else if(initlevel == LUSOL_PIVTOL_SLIM) {   /* Better accuracy pivot tolerances */ | ||||
|     newFM = 10.0; | ||||
|     newUM = newFM / 2; | ||||
|   } | ||||
|   else if(initlevel == LUSOL_PIVTOL_TIGHT) {  /* Enhanced accuracy pivot tolerances */ | ||||
|     newFM = 5.0; | ||||
|     newUM = newFM / 2; | ||||
|   } | ||||
|   else if(initlevel == LUSOL_PIVTOL_SUPER) {  /* Very tight pivot tolerances for extra accuracy */ | ||||
|     newFM = 2.5; | ||||
|     newUM = 1.99; | ||||
|   } | ||||
|   else {                                      /* Extremely tight pivot tolerances for extra accuracy */ | ||||
|     newFM = 1.99; | ||||
|     newUM = newFM / 1.49; | ||||
|   } | ||||
| 
 | ||||
|   /* Set the tolerances */ | ||||
|   LUSOL->parmlu[LUSOL_RP_FACTORMAX_Lij] = newFM; | ||||
|   LUSOL->parmlu[LUSOL_RP_UPDATEMAX_Lij] = newUM; | ||||
| } | ||||
| 
 | ||||
| MYBOOL LUSOL_tightenpivot(LUSOLrec *LUSOL) | ||||
| { | ||||
|   REAL newvalue; | ||||
| 
 | ||||
|   /* Give up tightening if we are already less than limit and we cannot change strategy */ | ||||
|   if(MIN(LUSOL->parmlu[LUSOL_RP_FACTORMAX_Lij], | ||||
|          LUSOL->parmlu[LUSOL_RP_UPDATEMAX_Lij]) < 1.1) { | ||||
|     if(LUSOL->luparm[LUSOL_IP_PIVOTTYPE] >= LUSOL_PIVMOD_TRP) | ||||
|       return( FALSE ); | ||||
|     LUSOL_setpivotmodel(LUSOL, LUSOL->luparm[LUSOL_IP_PIVOTTYPE]+1, LUSOL_PIVTOL_DEFAULT+1); | ||||
|     return( 2 ); | ||||
|   } | ||||
| 
 | ||||
|   /* Otherwise tighten according to defined schedule */ | ||||
| #if 0   /* This is Michael Saunder's proposed tightening procedure */
 | ||||
|   newvalue = sqrt(LUSOL->parmlu[LUSOL_RP_FACTORMAX_Lij]); | ||||
|   LUSOL->parmlu[LUSOL_RP_FACTORMAX_Lij] = newvalue; | ||||
|   SETMIN(LUSOL->parmlu[LUSOL_RP_UPDATEMAX_Lij], newvalue); | ||||
| #elif 0 /* This is Kjell Eikland's schedule #1 */ | ||||
|   newvalue = sqrt(LUSOL->parmlu[LUSOL_RP_FACTORMAX_Lij]); | ||||
|   LUSOL->parmlu[LUSOL_RP_FACTORMAX_Lij] = newvalue; | ||||
|   LUSOL->parmlu[LUSOL_RP_UPDATEMAX_Lij] = 1.0 + (newvalue - 1.0) / 2; | ||||
| #else   /* This was Kjell Eikland's schedule #2 */ | ||||
|   LUSOL->parmlu[LUSOL_RP_FACTORMAX_Lij] = 1.0 + LUSOL->parmlu[LUSOL_RP_FACTORMAX_Lij]/3.0; | ||||
|   LUSOL->parmlu[LUSOL_RP_UPDATEMAX_Lij] = 1.0 + LUSOL->parmlu[LUSOL_RP_UPDATEMAX_Lij]/3.0; | ||||
| #endif | ||||
|   return( TRUE ); | ||||
| } | ||||
| 
 | ||||
| MYBOOL LUSOL_addSingularity(LUSOLrec *LUSOL, int singcol, int *inform) | ||||
| { | ||||
|   int NSING = LUSOL->luparm[LUSOL_IP_SINGULARITIES], | ||||
|       ASING = LUSOL->luparm[LUSOL_IP_SINGULARLISTSIZE]; | ||||
| 
 | ||||
|   /* Check if we need to allocated list memory to store multiple singularities */ | ||||
|   if((NSING > 0) && (NSING >= ASING)) { | ||||
| 
 | ||||
|     /* Increase list in "reasonable" steps */ | ||||
|     ASING += (int) (10.0 * (log10((REAL) LUSOL->m)+1.0)); | ||||
|     LUSOL->isingular = (int *) LUSOL_REALLOC(LUSOL->isingular, sizeof(*LUSOL->isingular)*(ASING+1)); | ||||
|     if(LUSOL->isingular == NULL) { | ||||
|       LUSOL->luparm[LUSOL_IP_SINGULARLISTSIZE] = 0; | ||||
|       *inform = LUSOL_INFORM_NOMEMLEFT; | ||||
|       return( FALSE ); | ||||
|     } | ||||
|     LUSOL->luparm[LUSOL_IP_SINGULARLISTSIZE] = ASING; | ||||
| 
 | ||||
|     /* Transfer the first singularity if the list was just created */ | ||||
|     if(NSING == 1) | ||||
|       LUSOL->isingular[NSING] = LUSOL->luparm[LUSOL_IP_SINGULARINDEX]; | ||||
|   } | ||||
| 
 | ||||
|   /* Update singularity count and store its index */ | ||||
|   NSING++; | ||||
|   if(NSING > 1) { | ||||
|     LUSOL->isingular[0] = NSING; | ||||
|     LUSOL->isingular[NSING] = singcol; | ||||
|   } | ||||
|   LUSOL->luparm[LUSOL_IP_SINGULARITIES] = NSING; | ||||
| 
 | ||||
|   /* Mimic old logic by keeping the last singularity stored */ | ||||
|   LUSOL->luparm[LUSOL_IP_SINGULARINDEX] = singcol; | ||||
| 
 | ||||
|   return( TRUE ); | ||||
| } | ||||
| 
 | ||||
| int LUSOL_getSingularity(LUSOLrec *LUSOL, int singitem) | ||||
| { | ||||
|   if((singitem > LUSOL->luparm[LUSOL_IP_SINGULARITIES]) || (singitem < 0)) | ||||
|     singitem = -1; | ||||
|   else if(singitem == 0) | ||||
|     singitem = LUSOL->luparm[LUSOL_IP_SINGULARITIES]; | ||||
|   else if(singitem > 1) | ||||
|     singitem = LUSOL->isingular[singitem]; | ||||
|   else | ||||
|     singitem = LUSOL->luparm[LUSOL_IP_SINGULARINDEX]; | ||||
|   return( singitem ); | ||||
| } | ||||
| 
 | ||||
| int LUSOL_findSingularityPosition(LUSOLrec *LUSOL, int singcol) | ||||
| /* The purpose of this routine is to find the slack row/column in
 | ||||
|    user-index that was singular in the last unsuccessful column | ||||
|    update; zero is returned if the search was unsuccessful. | ||||
|    By adding a slack at this position this particular singularity | ||||
|    should disappear. | ||||
|    (Source: Michael A. Saunders; private communication to KE) */ | ||||
| { | ||||
| #if 0 /* Michael Saunders version */
 | ||||
|   int j; | ||||
|   for(j = LUSOL->m; j > 0; j--) | ||||
|     if(LUSOL->iq[j] == singcol) | ||||
|       break; | ||||
|   singcol = j; | ||||
| #else /* Kjell Eikland version (note that iqinv could be invalid in early versions of LUSOL) */ | ||||
|   singcol = LUSOL->iqinv[singcol]; | ||||
| #endif | ||||
|   return( LUSOL->ip[singcol] ); | ||||
| } | ||||
| 
 | ||||
| char *LUSOL_informstr(LUSOLrec *LUSOL, int inform) | ||||
| { | ||||
|   static char *informText[LUSOL_INFORM_MAX-LUSOL_INFORM_MIN+1] = | ||||
|   {"LUSOL_RANKLOSS: Lost rank", | ||||
|    "LUSOL_LUSUCCESS: Success", | ||||
|    "LUSOL_LUSINGULAR: Singular A", | ||||
|    "LUSOL_LUUNSTABLE: Unstable factorization", | ||||
|    "LUSOL_ADIMERR: Row or column count exceeded", | ||||
|    "LUSOL_ADUPLICATE: Duplicate A matrix entry found", | ||||
|    "(Undefined message)", | ||||
|    "(Undefined message)", | ||||
|    "LUSOL_ANEEDMEM: Insufficient memory for factorization", | ||||
|    "LUSOL_FATALERR: Fatal internal error", | ||||
|    "LUSOL_NOPIVOT: Found no suitable pivot", | ||||
|    "LUSOL_NOMEMLEFT: Could not obtain more memory"}; | ||||
|   if((inform < LUSOL_INFORM_MIN) || (inform > LUSOL_INFORM_MAX)) | ||||
|     inform = LUSOL->luparm[LUSOL_IP_INFORM]; | ||||
|   return(informText[inform-LUSOL_INFORM_MIN]); | ||||
| } | ||||
| 
 | ||||
| void LUSOL_clear(LUSOLrec *LUSOL, MYBOOL nzonly) | ||||
| { | ||||
|   int len; | ||||
| 
 | ||||
|   LUSOL->nelem = 0; | ||||
|   if(!nzonly) { | ||||
| 
 | ||||
|    /* lena arrays */ | ||||
|     len = LUSOL->lena + LUSOL_ARRAYOFFSET; | ||||
|     MEMCLEAR(LUSOL->a,    len); | ||||
|     MEMCLEAR(LUSOL->indc, len); | ||||
|     MEMCLEAR(LUSOL->indr, len); | ||||
| 
 | ||||
|    /* maxm arrays */ | ||||
|     len = LUSOL->maxm + LUSOL_ARRAYOFFSET; | ||||
|     MEMCLEAR(LUSOL->lenr,  len); | ||||
|     MEMCLEAR(LUSOL->ip,    len); | ||||
|     MEMCLEAR(LUSOL->iqloc, len); | ||||
|     MEMCLEAR(LUSOL->ipinv, len); | ||||
|     MEMCLEAR(LUSOL->locr,  len); | ||||
| 
 | ||||
| #ifndef ClassicHamaxR | ||||
|     if((LUSOL->amaxr != NULL) | ||||
| #ifdef AlwaysSeparateHamaxR | ||||
|        && (LUSOL->luparm[LUSOL_IP_PIVOTTYPE] == LUSOL_PIVMOD_TRP) | ||||
| #endif | ||||
|       ) | ||||
|       MEMCLEAR(LUSOL->amaxr, len); | ||||
| #endif | ||||
| 
 | ||||
|    /* maxn arrays */ | ||||
|     len = LUSOL->maxn + LUSOL_ARRAYOFFSET; | ||||
|     MEMCLEAR(LUSOL->lenc,  len); | ||||
|     MEMCLEAR(LUSOL->iq,    len); | ||||
|     MEMCLEAR(LUSOL->iploc, len); | ||||
|     MEMCLEAR(LUSOL->iqinv, len); | ||||
|     MEMCLEAR(LUSOL->locc,  len); | ||||
|     MEMCLEAR(LUSOL->w,     len); | ||||
| 
 | ||||
|     if(LUSOL->luparm[LUSOL_IP_PIVOTTYPE] == LUSOL_PIVMOD_TCP) { | ||||
|       MEMCLEAR(LUSOL->Ha,  len); | ||||
|       MEMCLEAR(LUSOL->Hj,  len); | ||||
|       MEMCLEAR(LUSOL->Hk,  len); | ||||
|     } | ||||
| #ifndef ClassicdiagU | ||||
|     if(LUSOL->luparm[LUSOL_IP_KEEPLU] == FALSE) { | ||||
|       MEMCLEAR(LUSOL->diagU, len); | ||||
|     } | ||||
| #endif | ||||
| 
 | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| MYBOOL LUSOL_assign(LUSOLrec *LUSOL, int iA[], int jA[], REAL Aij[], int nzcount, MYBOOL istriplet) | ||||
| { | ||||
|   int k, m, n, ij, kol; | ||||
| 
 | ||||
|   /* Adjust the size of the a structure */ | ||||
|   if(nzcount > (LUSOL->lena/LUSOL->luparm[LUSOL_IP_SCALAR_NZA]) && | ||||
|      !LUSOL_realloc_a(LUSOL, nzcount*LUSOL->luparm[LUSOL_IP_SCALAR_NZA])) | ||||
|     return( FALSE ); | ||||
| 
 | ||||
|   m = 0; | ||||
|   n = 0; | ||||
|   kol = 1; | ||||
|   for(k = 1; k <= nzcount; k++) { | ||||
|     /* First the row indicator */ | ||||
|     ij = iA[k]; | ||||
|     if(ij > m) { | ||||
|       m = ij; | ||||
|       if(m > LUSOL->maxm && | ||||
|          !LUSOL_realloc_r(LUSOL, -(m / LUSOL_MINDELTA_FACTOR + 1))) | ||||
|         return( FALSE ); | ||||
|     } | ||||
|     LUSOL->indc[k] = ij; | ||||
| 
 | ||||
|     /* Then the column indicator;
 | ||||
|        Handle both triplet and column count formats */ | ||||
|     if(istriplet) | ||||
|       ij = jA[k]; | ||||
|     else { | ||||
|       if(k >= jA[kol]) | ||||
|         kol++; | ||||
|       ij = kol; | ||||
|     } | ||||
|     if(ij > n) { | ||||
|       n = ij; | ||||
|       if(n > LUSOL->maxn && | ||||
|          !LUSOL_realloc_c(LUSOL, -(n / LUSOL_MINDELTA_FACTOR + 1))) | ||||
|         return( FALSE ); | ||||
|     } | ||||
|     LUSOL->indr[k] = ij; | ||||
| 
 | ||||
|     /* Lastly the matrix value itself */ | ||||
|     LUSOL->a[k] = Aij[k]; | ||||
|   } | ||||
|   LUSOL->m = m; | ||||
|   LUSOL->n = n; | ||||
|   LUSOL->nelem = nzcount; | ||||
|   return( TRUE ); | ||||
| } | ||||
| 
 | ||||
| int LUSOL_loadColumn(LUSOLrec *LUSOL, int iA[], int jA, REAL Aij[], int nzcount, int offset1) | ||||
| { | ||||
|   int i, ii, nz, k; | ||||
| 
 | ||||
|   nz = LUSOL->nelem; | ||||
|   i = nz + nzcount; | ||||
|   if(i > (LUSOL->lena/LUSOL->luparm[LUSOL_IP_SCALAR_NZA]) && | ||||
|      !LUSOL_realloc_a(LUSOL, i*LUSOL->luparm[LUSOL_IP_SCALAR_NZA])) | ||||
|   return( -1 ); | ||||
| 
 | ||||
|   k = 0; | ||||
|   for(ii = 1; ii <= nzcount; ii++) { | ||||
|     i = ii + offset1; | ||||
|     if(Aij[i] == 0) | ||||
|       continue; | ||||
|     if(iA[i] <= 0 || iA[i] > LUSOL->m || | ||||
|        jA <= 0 || jA > LUSOL->n) { | ||||
|       LUSOL_report(LUSOL, 0, "Variable index outside of set bounds (r:%d/%d, c:%d/%d)\n", | ||||
|                              iA[i], LUSOL->m, jA, LUSOL->n); | ||||
|       continue; | ||||
|     } | ||||
|     k++; | ||||
|     nz++; | ||||
|     LUSOL->a[nz]    = Aij[i]; | ||||
|     LUSOL->indc[nz] = iA[i]; | ||||
|     LUSOL->indr[nz] = jA; | ||||
|   } | ||||
|   LUSOL->nelem = nz; | ||||
|   return( k ); | ||||
| } | ||||
| 
 | ||||
| void LUSOL_free(LUSOLrec *LUSOL) | ||||
| { | ||||
|   LUSOL_realloc_a(LUSOL, 0); | ||||
|   LUSOL_realloc_r(LUSOL, 0); | ||||
|   LUSOL_realloc_c(LUSOL, 0); | ||||
|   if(LUSOL->L0 != NULL) | ||||
|     LUSOL_matfree(&(LUSOL->L0)); | ||||
|   if(LUSOL->U != NULL) | ||||
|     LUSOL_matfree(&(LUSOL->U)); | ||||
|   if(!is_nativeBLAS()) | ||||
|     unload_BLAS(); | ||||
|   LUSOL_FREE(LUSOL); | ||||
| } | ||||
| 
 | ||||
| void LUSOL_report(LUSOLrec *LUSOL, int msglevel, char *format, ...) | ||||
| { | ||||
|   va_list ap; | ||||
| 
 | ||||
|   va_start(ap, format); | ||||
|   if(LUSOL == NULL) { | ||||
|     vfprintf(stderr, format, ap); | ||||
|   } | ||||
|   else if(msglevel >= 0  /*LUSOL->luparm[2]*/) { | ||||
|     if(LUSOL->writelog != NULL) { | ||||
|       char buff[255]; | ||||
| 
 | ||||
|       vsprintf(buff, format, ap); | ||||
|       LUSOL->writelog(LUSOL, LUSOL->loghandle, buff); | ||||
|     } | ||||
|     if(LUSOL->outstream != NULL) { | ||||
|       vfprintf(LUSOL->outstream, format, ap); | ||||
|       fflush(LUSOL->outstream); | ||||
|     } | ||||
|   } | ||||
|   va_end(ap); | ||||
| } | ||||
| 
 | ||||
| void LUSOL_timer(LUSOLrec *LUSOL, int timerid, char *text) | ||||
| { | ||||
|   LUSOL_report(LUSOL, -1, "TimerID %d at %s - %s\n", | ||||
|                           timerid, "", text); | ||||
| } | ||||
| 
 | ||||
| int LUSOL_factorize(LUSOLrec *LUSOL) | ||||
| { | ||||
|   int inform; | ||||
| 
 | ||||
|   LU1FAC( LUSOL, &inform ); | ||||
|   return( inform ); | ||||
| } | ||||
| 
 | ||||
| int LUSOL_ftran(LUSOLrec *LUSOL, REAL b[], int NZidx[], MYBOOL prepareupdate) | ||||
| { | ||||
|   int  inform; | ||||
|   REAL *vector; | ||||
| 
 | ||||
|   if(prepareupdate) | ||||
|     vector = LUSOL->vLU6L; | ||||
|   else | ||||
|     vector = LUSOL->w; | ||||
| 
 | ||||
|   /* Copy RHS vector, but make adjustment for offset since this
 | ||||
|      can create a memory error when the calling program uses | ||||
|      a 0-base vector offset back to comply with LUSOL. */ | ||||
|   MEMCOPY(vector+1, b+1, LUSOL->n); | ||||
|   vector[0] = 0; | ||||
| 
 | ||||
|   LU6SOL(LUSOL, LUSOL_SOLVE_Aw_v, vector, b, NZidx, &inform); | ||||
|   LUSOL->luparm[LUSOL_IP_FTRANCOUNT]++; | ||||
| 
 | ||||
|   return(inform); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int LUSOL_btran(LUSOLrec *LUSOL, REAL b[], int NZidx[]) | ||||
| { | ||||
|   int inform; | ||||
| 
 | ||||
|   /* Copy RHS vector, but make adjustment for offset since this
 | ||||
|      can create a memory error when the calling program uses | ||||
|      a 0-base vector offset back to comply with LUSOL. */ | ||||
|   MEMCOPY(LUSOL->w+1, b+1, LUSOL->m); | ||||
|   LUSOL->w[0] = 0; | ||||
| 
 | ||||
|   LU6SOL(LUSOL, LUSOL_SOLVE_Atv_w, b, LUSOL->w, NZidx, &inform); | ||||
|   LUSOL->luparm[LUSOL_IP_BTRANCOUNT]++; | ||||
| 
 | ||||
|   return(inform); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int LUSOL_replaceColumn(LUSOLrec *LUSOL, int jcol, REAL v[]) | ||||
| { | ||||
|   int  inform; | ||||
|   REAL DIAG, VNORM; | ||||
| 
 | ||||
|   LU8RPC(LUSOL, LUSOL_UPDATE_OLDNONEMPTY, LUSOL_UPDATE_NEWNONEMPTY, | ||||
|                 jcol, v, NULL, | ||||
|                 &inform, &DIAG, &VNORM); | ||||
| 
 | ||||
|   LUSOL->replaced_c++; | ||||
|   return( inform ); | ||||
| } | ||||
| 
 | ||||
| REAL LUSOL_vecdensity(LUSOLrec *LUSOL, REAL V[]) | ||||
| { | ||||
|   int I, N = 0; | ||||
| 
 | ||||
|   for(I = 1; I <= LUSOL->m; I++) | ||||
|     if(fabs(V[I]) > 0) | ||||
|       N++; | ||||
|   return( (REAL) N / (REAL) LUSOL->m ); | ||||
| } | ||||
| 
 | ||||
| char relationChar(REAL left, REAL right) | ||||
| { | ||||
|   if(left > right) | ||||
|     return('>'); | ||||
|   else if(left == right) | ||||
|     return('='); | ||||
|   else | ||||
|     return('<'); | ||||
| } | ||||
| 
 | ||||
| /* Retrieve the core modules ordered by order of dependency */ | ||||
| 
 | ||||
| #include "lusol2.c"      /* Heap management */ | ||||
| #include "lusol6a.c"     /* Singularity checking and equation solving */ | ||||
| #include "lusol1.c"      /* Factorization and core components */ | ||||
| #include "lusol7a.c"     /* Utility routines for updates */ | ||||
| #include "lusol8a.c"     /* Column update */ | ||||
| 
 | ||||
| 
 | ||||
| void LUSOL_dump(FILE *output, LUSOLrec *LUSOL) | ||||
| { | ||||
|   MYBOOL userfile = (MYBOOL) (output != NULL); | ||||
| 
 | ||||
|   if(!userfile) | ||||
|     output = fopen("LUSOL.dbg", "w"); | ||||
| 
 | ||||
|   blockWriteREAL(output, "a", LUSOL->a, 1, LUSOL->lena); | ||||
|   blockWriteINT(output, "indc", LUSOL->indc, 1, LUSOL->lena); | ||||
|   blockWriteINT(output, "indr", LUSOL->indr, 1, LUSOL->lena); | ||||
| 
 | ||||
|   blockWriteINT(output, "ip", LUSOL->ip, 1, LUSOL->m); | ||||
|   blockWriteINT(output, "iq", LUSOL->iq, 1, LUSOL->n); | ||||
|   blockWriteINT(output, "lenc", LUSOL->lenc, 1, LUSOL->n); | ||||
|   blockWriteINT(output, "lenr", LUSOL->lenr, 1, LUSOL->m); | ||||
| 
 | ||||
|   blockWriteINT(output, "locc", LUSOL->locc, 1, LUSOL->n); | ||||
|   blockWriteINT(output, "locr", LUSOL->locr, 1, LUSOL->m); | ||||
|   blockWriteINT(output, "iploc", LUSOL->iploc, 1, LUSOL->n); | ||||
|   blockWriteINT(output, "iqloc", LUSOL->iqloc, 1, LUSOL->m); | ||||
| 
 | ||||
|   blockWriteINT(output, "ipinv", LUSOL->ipinv, 1, LUSOL->m); | ||||
|   blockWriteINT(output, "iqinv", LUSOL->iqinv, 1, LUSOL->n); | ||||
| 
 | ||||
|   if(!userfile) | ||||
|     fclose(output); | ||||
| } | ||||
| 
 | ||||
| LUSOLmat *LUSOL_matcreate(int dim, int nz) | ||||
| { | ||||
|   LUSOLmat *newm; | ||||
| 
 | ||||
|   newm = (LUSOLmat *) LUSOL_CALLOC(1, sizeof(*newm)); | ||||
|   if(newm != NULL) { | ||||
|     newm->a    = (REAL *) LUSOL_MALLOC((nz+1)*sizeof(REAL)); | ||||
|     newm->lenx = (int *)  LUSOL_MALLOC((dim+1)*sizeof(int)); | ||||
|     newm->indx = (int *)  LUSOL_MALLOC((dim+1)*sizeof(int)); | ||||
|     newm->indr = (int *)  LUSOL_MALLOC((nz+1)*sizeof(int)); | ||||
|     newm->indc = (int *)  LUSOL_MALLOC((nz+1)*sizeof(int)); | ||||
|     if((newm->a == NULL) || | ||||
|        (newm->lenx == NULL) || (newm->indx == NULL) || | ||||
|        (newm->indr == NULL) || (newm->indc == NULL)) | ||||
|       LUSOL_matfree(&newm); | ||||
|   } | ||||
|   return(newm); | ||||
| } | ||||
| void LUSOL_matfree(LUSOLmat **mat) | ||||
| { | ||||
|   if((mat == NULL) || (*mat == NULL)) | ||||
|     return; | ||||
|   LUSOL_FREE((*mat)->a); | ||||
|   LUSOL_FREE((*mat)->indc); | ||||
|   LUSOL_FREE((*mat)->indr); | ||||
|   LUSOL_FREE((*mat)->lenx); | ||||
|   LUSOL_FREE((*mat)->indx); | ||||
|   LUSOL_FREE(*mat); | ||||
| } | ||||
| 
 | ||||
|  | @ -1,357 +0,0 @@ | |||
| #ifndef HEADER_LUSOL | ||||
| #define HEADER_LUSOL | ||||
| 
 | ||||
| /* Include necessary libraries                                               */ | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| #include <stdio.h> | ||||
| #include "commonlib.h" | ||||
| 
 | ||||
| /* Version information                                                       */ | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| #define LUSOL_VERMAJOR   2 | ||||
| #define LUSOL_VERMINOR   2 | ||||
| #define LUSOL_RELEASE    2 | ||||
| #define LUSOL_BUILD      0 | ||||
| 
 | ||||
| /* Dynamic memory management macros                                          */ | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| #ifdef MATLAB | ||||
|   #define LUSOL_MALLOC(bytesize)        mxMalloc(bytesize) | ||||
|   #define LUSOL_CALLOC(count, recsize)  mxCalloc(count, recsize) | ||||
|   #define LUSOL_REALLOC(ptr, bytesize)  mxRealloc((void *) ptr, bytesize) | ||||
|   #define LUSOL_FREE(ptr)               {mxFree(ptr); ptr=NULL;} | ||||
| #else | ||||
|   #define LUSOL_MALLOC(bytesize)        malloc(bytesize) | ||||
|   #define LUSOL_CALLOC(count, recsize)  calloc(count, recsize) | ||||
|   #define LUSOL_REALLOC(ptr, bytesize)  realloc((void *) ptr, bytesize) | ||||
|   #define LUSOL_FREE(ptr)               {free(ptr); ptr=NULL;} | ||||
| #endif | ||||
| 
 | ||||
| /* Performance compiler options                                              */ | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| #if 1 | ||||
|   #define ForceInitialization      /* Satisfy compilers, check during debugging! */ | ||||
|   #define LUSOLFastDenseIndex           /* Increment the linearized dense address */ | ||||
|   #define LUSOLFastClear           /* Use intrinsic functions for memory zeroing */ | ||||
|   #define LUSOLFastMove              /* Use intrinsic functions for memory moves */ | ||||
|   #define LUSOLFastCopy               /* Use intrinsic functions for memory copy */ | ||||
|   #define LUSOLFastSolve           /* Use pointer operations in equation solving */ | ||||
|   #define LUSOLSafeFastUpdate      /* Use separate array for LU6L result storage */ | ||||
| /*#define UseOld_LU6CHK_20040510 */ | ||||
| /*#define AlwaysSeparateHamaxR */       /* Enabled when the pivot model is fixed */ | ||||
|   #if 0 | ||||
|     #define ForceRowBasedL0                  /* Create a row-sorted version of L0 */ | ||||
|   #endif | ||||
| /*  #define SetSmallToZero*/ | ||||
| /*  #define DoTraceL0 */ | ||||
| #endif | ||||
| /*#define UseTimer */ | ||||
| 
 | ||||
| 
 | ||||
| /* Legacy compatibility and testing options (Fortran-LUSOL)                  */ | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| #if 0 | ||||
|   #define LegacyTesting | ||||
|   #define StaticMemAlloc           /* Preallocated vs. dynamic memory allocation */ | ||||
|   #define ClassicdiagU                                  /* Store diagU at end of a */ | ||||
|   #define ClassicHamaxR                    /* Store H+AmaxR at end of a/indc/indr */ | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /* General constants and data type definitions                               */ | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| #define LUSOL_ARRAYOFFSET            1 | ||||
| #ifndef ZERO | ||||
|   #define ZERO                       0 | ||||
| #endif | ||||
| #ifndef ONE | ||||
|   #define ONE                        1 | ||||
| #endif | ||||
| #ifndef FALSE | ||||
|   #define FALSE                      0 | ||||
| #endif | ||||
| #ifndef TRUE | ||||
|   #define TRUE                       1 | ||||
| #endif | ||||
| #ifndef NULL | ||||
|   #define NULL                       0 | ||||
| #endif | ||||
| #ifndef REAL | ||||
|   #define REAL double | ||||
| #endif | ||||
| #ifndef REALXP | ||||
|   #define REALXP long double | ||||
| #endif | ||||
| #ifndef MYBOOL | ||||
|   #define MYBOOL unsigned char | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /* User-settable default parameter values                                    */ | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| #define LUSOL_DEFAULT_GAMMA        2.0 | ||||
| #define LUSOL_SMALLNUM         1.0e-20  /* IAEE doubles have precision 2.22e-16 */ | ||||
| #define LUSOL_BIGNUM           1.0e+20 | ||||
| #define LUSOL_MINDELTA_FACTOR        4 | ||||
| #define LUSOL_MINDELTA_a         10000 | ||||
| #if 1 | ||||
|   #define LUSOL_MULT_nz_a            2  /* Suggested by Yin Zhang */ | ||||
| #else | ||||
|   #define LUSOL_MULT_nz_a            5  /* Could consider 6 or 7 */ | ||||
| #endif | ||||
| #define LUSOL_MINDELTA_rc         1000 | ||||
| #define LUSOL_DEFAULT_SMARTRATIO 0.667 | ||||
| 
 | ||||
| /* Fixed system parameters (changeable only by developers)                   */ | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| 
 | ||||
| /* parmlu INPUT parameters: */ | ||||
| #define LUSOL_RP_SMARTRATIO          0 | ||||
| #define LUSOL_RP_FACTORMAX_Lij       1 | ||||
| #define LUSOL_RP_UPDATEMAX_Lij       2 | ||||
| #define LUSOL_RP_ZEROTOLERANCE       3 | ||||
| #define LUSOL_RP_SMALLDIAG_U         4 | ||||
| #define LUSOL_RP_EPSDIAG_U           5 | ||||
| #define LUSOL_RP_COMPSPACE_U         6 | ||||
| #define LUSOL_RP_MARKOWITZ_CONLY     7 | ||||
| #define LUSOL_RP_MARKOWITZ_DENSE     8 | ||||
| #define LUSOL_RP_GAMMA               9 | ||||
| 
 | ||||
| /* parmlu OUPUT parameters: */ | ||||
| #define LUSOL_RP_MAXELEM_A          10 | ||||
| #define LUSOL_RP_MAXMULT_L          11 | ||||
| #define LUSOL_RP_MAXELEM_U          12 | ||||
| #define LUSOL_RP_MAXELEM_DIAGU      13 | ||||
| #define LUSOL_RP_MINELEM_DIAGU      14 | ||||
| #define LUSOL_RP_MAXELEM_TCP        15 | ||||
| #define LUSOL_RP_GROWTHRATE         16 | ||||
| #define LUSOL_RP_USERDATA_1         17 | ||||
| #define LUSOL_RP_USERDATA_2         18 | ||||
| #define LUSOL_RP_USERDATA_3         19 | ||||
| #define LUSOL_RP_RESIDUAL_U         20 | ||||
| #define LUSOL_RP_LASTITEM            LUSOL_RP_RESIDUAL_U | ||||
| 
 | ||||
| /* luparm INPUT parameters: */ | ||||
| #define LUSOL_IP_USERDATA_0          0 | ||||
| #define LUSOL_IP_PRINTUNIT           1 | ||||
| #define LUSOL_IP_PRINTLEVEL          2 | ||||
| #define LUSOL_IP_MARKOWITZ_MAXCOL    3 | ||||
| #define LUSOL_IP_SCALAR_NZA          4 | ||||
| #define LUSOL_IP_UPDATELIMIT         5 | ||||
| #define LUSOL_IP_PIVOTTYPE           6 | ||||
| #define LUSOL_IP_ACCELERATION        7 | ||||
| #define LUSOL_IP_KEEPLU              8 | ||||
| #define LUSOL_IP_SINGULARLISTSIZE    9 | ||||
| 
 | ||||
| /* luparm OUTPUT parameters: */ | ||||
| #define LUSOL_IP_INFORM             10 | ||||
| #define LUSOL_IP_SINGULARITIES      11 | ||||
| #define LUSOL_IP_SINGULARINDEX      12 | ||||
| #define LUSOL_IP_MINIMUMLENA        13 | ||||
| #define LUSOL_IP_MAXLEN             14 | ||||
| #define LUSOL_IP_UPDATECOUNT        15 | ||||
| #define LUSOL_IP_RANK_U             16 | ||||
| #define LUSOL_IP_COLCOUNT_DENSE1    17 | ||||
| #define LUSOL_IP_COLCOUNT_DENSE2    18 | ||||
| #define LUSOL_IP_COLINDEX_DUMIN     19 | ||||
| #define LUSOL_IP_COLCOUNT_L0        20 | ||||
| #define LUSOL_IP_NONZEROS_L0        21 | ||||
| #define LUSOL_IP_NONZEROS_U0        22 | ||||
| #define LUSOL_IP_NONZEROS_L         23 | ||||
| #define LUSOL_IP_NONZEROS_U         24 | ||||
| #define LUSOL_IP_NONZEROS_ROW       25 | ||||
| #define LUSOL_IP_COMPRESSIONS_LU    26 | ||||
| #define LUSOL_IP_MARKOWITZ_MERIT    27 | ||||
| #define LUSOL_IP_TRIANGROWS_U       28 | ||||
| #define LUSOL_IP_TRIANGROWS_L       29 | ||||
| #define LUSOL_IP_FTRANCOUNT         30 | ||||
| #define LUSOL_IP_BTRANCOUNT         31 | ||||
| #define LUSOL_IP_ROWCOUNT_L0        32 | ||||
| #define LUSOL_IP_LASTITEM            LUSOL_IP_ROWCOUNT_L0 | ||||
| 
 | ||||
| 
 | ||||
| /* Macros for matrix-based access for dense part of A and timer mapping      */ | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| #define DAPOS(row, col)   (row + (col-1)*LDA) | ||||
| #define timer(text, id)   LUSOL_timer(LUSOL, id, text) | ||||
| 
 | ||||
| 
 | ||||
| /* Parameter/option defines                                                  */ | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| #define LUSOL_MSG_NONE              -1 | ||||
| #define LUSOL_MSG_SINGULARITY        0 | ||||
| #define LUSOL_MSG_STATISTICS        10 | ||||
| #define LUSOL_MSG_PIVOT             50 | ||||
| 
 | ||||
| #define LUSOL_BASEORDER              0 | ||||
| #define LUSOL_OTHERORDER             1 | ||||
| #define LUSOL_AUTOORDER              2 | ||||
| #define LUSOL_ACCELERATE_L0          4 | ||||
| #define LUSOL_ACCELERATE_U           8 | ||||
| 
 | ||||
| #define LUSOL_PIVMOD_NOCHANGE       -2  /* Don't change active pivoting model */ | ||||
| #define LUSOL_PIVMOD_DEFAULT        -1  /* Set pivoting model to default */ | ||||
| #define LUSOL_PIVMOD_TPP             0  /* Threshold Partial   pivoting (normal) */ | ||||
| #define LUSOL_PIVMOD_TRP             1  /* Threshold Rook      pivoting */ | ||||
| #define LUSOL_PIVMOD_TCP             2  /* Threshold Complete  pivoting */ | ||||
| #define LUSOL_PIVMOD_TSP             3  /* Threshold Symmetric pivoting */ | ||||
| #define LUSOL_PIVMOD_MAX             LUSOL_PIVMOD_TSP | ||||
| 
 | ||||
| #define LUSOL_PIVTOL_NOCHANGE        0 | ||||
| #define LUSOL_PIVTOL_BAGGY           1 | ||||
| #define LUSOL_PIVTOL_LOOSE           2 | ||||
| #define LUSOL_PIVTOL_NORMAL          3 | ||||
| #define LUSOL_PIVTOL_SLIM            4 | ||||
| #define LUSOL_PIVTOL_TIGHT           5 | ||||
| #define LUSOL_PIVTOL_SUPER           6 | ||||
| #define LUSOL_PIVTOL_CORSET          7 | ||||
| #define LUSOL_PIVTOL_DEFAULT         LUSOL_PIVTOL_SLIM | ||||
| #define LUSOL_PIVTOL_MAX             LUSOL_PIVTOL_CORSET | ||||
| 
 | ||||
| #define LUSOL_UPDATE_OLDEMPTY        0  /* No/empty current column. */ | ||||
| #define LUSOL_UPDATE_OLDNONEMPTY     1  /* Current column need not have been empty. */ | ||||
| #define LUSOL_UPDATE_NEWEMPTY        0  /* New column is taken to be zero. */ | ||||
| #define LUSOL_UPDATE_NEWNONEMPTY     1  /* v(*) contains the new column; | ||||
|                                            on exit,  v(*)  satisfies  L*v = a(new). */ | ||||
| #define LUSOL_UPDATE_USEPREPARED     2  /* v(*)  must satisfy  L*v = a(new). */ | ||||
| 
 | ||||
| #define LUSOL_SOLVE_Lv_v             1  /* v  solves   L v = v(input). w  is not touched. */ | ||||
| #define LUSOL_SOLVE_Ltv_v            2  /* v  solves   L'v = v(input). w  is not touched. */ | ||||
| #define LUSOL_SOLVE_Uw_v             3  /* w  solves   U w = v.        v  is not altered. */ | ||||
| #define LUSOL_SOLVE_Utv_w            4  /* v  solves   U'v = w.        w  is destroyed. */ | ||||
| #define LUSOL_SOLVE_Aw_v             5  /* w  solves   A w = v.        v  is altered as in 1. */ | ||||
| #define LUSOL_FTRAN   LUSOL_SOLVE_Aw_v | ||||
| #define LUSOL_SOLVE_Atv_w            6  /* v  solves   A'v = w.        w  is destroyed. */ | ||||
| #define LUSOL_BTRAN  LUSOL_SOLVE_Atv_w | ||||
| 
 | ||||
| /* If mode = 3,4,5,6, v and w must not be the same arrays.
 | ||||
|    If lu1fac has just been used to factorize a symmetric matrix A | ||||
|    (which must be definite or quasi-definite), the factors A = L U | ||||
|    may be regarded as A = LDL', where D = diag(U).  In such cases, | ||||
|    the following (faster) solve codes may be used:                  */ | ||||
| #define LUSOL_SOLVE_Av_v             7  /* v  solves   A v = L D L'v = v(input). w  is not touched. */ | ||||
| #define LUSOL_SOLVE_LDLtv_v          8  /* v  solves       L |D| L'v = v(input). w  is not touched. */ | ||||
| 
 | ||||
| #define LUSOL_INFORM_RANKLOSS       -1 | ||||
| #define LUSOL_INFORM_LUSUCCESS       0 | ||||
| #define LUSOL_INFORM_LUSINGULAR      1 | ||||
| #define LUSOL_INFORM_LUUNSTABLE      2 | ||||
| #define LUSOL_INFORM_ADIMERR         3 | ||||
| #define LUSOL_INFORM_ADUPLICATE      4 | ||||
| #define LUSOL_INFORM_ANEEDMEM        7  /* Set lena >= luparm[LUSOL_IP_MINIMUMLENA] */ | ||||
| #define LUSOL_INFORM_FATALERR        8 | ||||
| #define LUSOL_INFORM_NOPIVOT         9  /* No diagonal pivot found with TSP or TDP. */ | ||||
| #define LUSOL_INFORM_NOMEMLEFT      10 | ||||
| 
 | ||||
| #define LUSOL_INFORM_MIN             LUSOL_INFORM_RANKLOSS | ||||
| #define LUSOL_INFORM_MAX             LUSOL_INFORM_NOMEMLEFT | ||||
| 
 | ||||
| #define LUSOL_INFORM_GETLAST        10  /* Code for LUSOL_informstr. */ | ||||
| #define LUSOL_INFORM_SERIOUS         LUSOL_INFORM_LUUNSTABLE | ||||
| 
 | ||||
| 
 | ||||
| /* Prototypes for call-back functions                                        */ | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| typedef void LUSOLlogfunc(void *lp, void *userhandle, char *buf); | ||||
| 
 | ||||
| 
 | ||||
| /* Sparse matrix data */ | ||||
| typedef struct _LUSOLmat { | ||||
|   REAL *a; | ||||
|   int  *lenx, *indr, *indc, *indx; | ||||
| } LUSOLmat; | ||||
| 
 | ||||
| 
 | ||||
| /* The main LUSOL data record */ | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| typedef struct _LUSOLrec { | ||||
| 
 | ||||
|   /* General data */ | ||||
|   FILE         *outstream;           /* Output stream, initialized to STDOUT */ | ||||
|   LUSOLlogfunc *writelog; | ||||
|     void       *loghandle; | ||||
|   LUSOLlogfunc *debuginfo; | ||||
| 
 | ||||
|   /* Parameter storage arrays */ | ||||
|   int    luparm[LUSOL_IP_LASTITEM + 1]; | ||||
|   REAL   parmlu[LUSOL_RP_LASTITEM + 1]; | ||||
| 
 | ||||
|   /* Arrays of length lena+1 */ | ||||
|   int    lena, nelem; | ||||
|   int    *indc, *indr; | ||||
|   REAL   *a; | ||||
| 
 | ||||
|   /* Arrays of length maxm+1 (row storage) */ | ||||
|   int    maxm, m; | ||||
|   int    *lenr, *ip, *iqloc, *ipinv, *locr; | ||||
| 
 | ||||
|   /* Arrays of length maxn+1 (column storage) */ | ||||
|   int    maxn, n; | ||||
|   int    *lenc, *iq, *iploc, *iqinv, *locc; | ||||
|   REAL   *w, *vLU6L; | ||||
| 
 | ||||
|   /* List of singular columns, with dynamic size allocation */ | ||||
|   int    *isingular; | ||||
| 
 | ||||
|   /* Extra arrays of length n for TCP and keepLU == FALSE */ | ||||
|   REAL   *Ha, *diagU; | ||||
|   int    *Hj, *Hk; | ||||
| 
 | ||||
|   /* Extra arrays of length m for TRP*/ | ||||
|   REAL   *amaxr; | ||||
| 
 | ||||
|   /* Extra array for L0 and U stored by row/column for faster btran/ftran */ | ||||
|   LUSOLmat *L0; | ||||
|   LUSOLmat *U; | ||||
| 
 | ||||
|   /* Miscellaneous data */ | ||||
|   int    expanded_a; | ||||
|   int    replaced_c; | ||||
|   int    replaced_r; | ||||
| 
 | ||||
| } LUSOLrec; | ||||
| 
 | ||||
| 
 | ||||
| LUSOLrec *LUSOL_create(FILE *outstream, int msgfil, int pivotmodel, int updatelimit); | ||||
| MYBOOL LUSOL_sizeto(LUSOLrec *LUSOL, int init_r, int init_c, int init_a); | ||||
| MYBOOL LUSOL_assign(LUSOLrec *LUSOL, int iA[], int jA[], REAL Aij[], | ||||
|                                      int nzcount, MYBOOL istriplet); | ||||
| void LUSOL_clear(LUSOLrec *LUSOL, MYBOOL nzonly); | ||||
| void LUSOL_free(LUSOLrec *LUSOL); | ||||
| 
 | ||||
| LUSOLmat *LUSOL_matcreate(int dim, int nz); | ||||
| void LUSOL_matfree(LUSOLmat **mat); | ||||
| 
 | ||||
| int LUSOL_loadColumn(LUSOLrec *LUSOL, int iA[], int jA, REAL Aij[], int nzcount, int offset1); | ||||
| void LUSOL_setpivotmodel(LUSOLrec *LUSOL, int pivotmodel, int initlevel); | ||||
| int LUSOL_factorize(LUSOLrec *LUSOL); | ||||
| int LUSOL_replaceColumn(LUSOLrec *LUSOL, int jcol, REAL v[]); | ||||
| 
 | ||||
| MYBOOL LUSOL_tightenpivot(LUSOLrec *LUSOL); | ||||
| MYBOOL LUSOL_addSingularity(LUSOLrec *LUSOL, int singcol, int *inform); | ||||
| int LUSOL_getSingularity(LUSOLrec *LUSOL, int singitem); | ||||
| int LUSOL_findSingularityPosition(LUSOLrec *LUSOL, int singcol); | ||||
| 
 | ||||
| char *LUSOL_pivotLabel(LUSOLrec *LUSOL); | ||||
| char *LUSOL_informstr(LUSOLrec *LUSOL, int inform); | ||||
| REAL LUSOL_vecdensity(LUSOLrec *LUSOL, REAL V[]); | ||||
| void LUSOL_report(LUSOLrec *LUSOL, int msglevel, char *format, ...); | ||||
| void LUSOL_timer(LUSOLrec *LUSOL, int timerid, char *text); | ||||
| 
 | ||||
| int LUSOL_ftran(LUSOLrec *LUSOL, REAL b[], int NZidx[], MYBOOL prepareupdate); | ||||
| int LUSOL_btran(LUSOLrec *LUSOL, REAL b[], int NZidx[]); | ||||
| 
 | ||||
| void LU1FAC(LUSOLrec *LUSOL, int *INFORM); | ||||
| MYBOOL LU1L0(LUSOLrec *LUSOL, LUSOLmat **mat, int *inform); | ||||
| void LU6SOL(LUSOLrec *LUSOL, int MODE, REAL V[], REAL W[], int NZidx[], int *INFORM); | ||||
| void LU8RPC(LUSOLrec *LUSOL, int MODE1, int MODE2, | ||||
|             int JREP, REAL V[], REAL W[], | ||||
|             int *INFORM, REAL *DIAG, REAL *VNORM); | ||||
| 
 | ||||
| void LUSOL_dump(FILE *output, LUSOLrec *LUSOL); | ||||
| 
 | ||||
| 
 | ||||
| void print_L0(LUSOLrec *LUSOL); | ||||
| 
 | ||||
| 
 | ||||
| #endif /* HEADER_LUSOL */ | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -1,204 +0,0 @@ | |||
| 
 | ||||
| /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 | ||||
|    File  lusol2 LUSOL heap management routines | ||||
|    Hbuild   Hchange  Hdelete  Hdown    Hinsert  Hup | ||||
|    Heap-management routines for LUSOL's lu1fac. | ||||
|    May be useful for other applications. | ||||
|    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | ||||
|    For LUSOL, the heap structure involves three arrays of length N. | ||||
|    N        is the current number of entries in the heap. | ||||
|    Ha(1:N)  contains the values that the heap is partially sorting. | ||||
|             For LUSOL they are double precision values -- the largest | ||||
|             element in each remaining column of the updated matrix. | ||||
|             The biggest entry is in Ha(1), the top of the heap. | ||||
|    Hj(1:N)  contains column numbers j. | ||||
|             Ha(k) is the biggest entry in column j = Hj(k). | ||||
|    Hk(1:N)  contains indices within the heap.  It is the | ||||
|             inverse of Hj(1:N), so  k = Hk(j)  <=>  j = Hj(k). | ||||
|             Column j is entry k in the heap. | ||||
|    hops     is the number of heap operations, | ||||
|             i.e., the number of times an entry is moved | ||||
|             (the number of "hops" up or down the heap). | ||||
|    Together, Hj and Hk let us find values inside the heap | ||||
|    whenever we want to change one of the values in Ha. | ||||
|    For other applications, Ha may need to be some other data type, | ||||
|    like the keys that sort routines operate on. | ||||
|    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | ||||
|    11 Feb 2002: MATLAB  version derived from "Algorithms" by | ||||
|                 R. Sedgewick | ||||
|    03 Mar 2002: F77     version derived from MATLAB version. | ||||
|    07 May 2002: Safeguard input parameters k, N, Nk. | ||||
|                 We don't want them to be output! | ||||
|    07 May 2002: Current version of lusol2.f. | ||||
|    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ | ||||
| 
 | ||||
| /* ==================================================================
 | ||||
|    Hdown  updates heap by moving down tree from node k. | ||||
|    ------------------------------------------------------------------ | ||||
|    01 May 2002: Need Nk for length of Hk. | ||||
|    05 May 2002: Change input paramter k to kk to stop k being output. | ||||
|    05 May 2002: Current version of Hdown. | ||||
|    ================================================================== */ | ||||
| void HDOWN(REAL HA[], int HJ[], int HK[], int N, int K, int *HOPS) | ||||
| { | ||||
|   int  J, JJ, JV, N2; | ||||
|   REAL V; | ||||
| 
 | ||||
|   *HOPS = 0; | ||||
|   V = HA[K]; | ||||
|   JV = HJ[K]; | ||||
|  N2 = N/2; | ||||
| /*      while 1
 | ||||
|         break */ | ||||
| x100: | ||||
|   if(K>N2) | ||||
|     goto x200; | ||||
|   (*HOPS)++; | ||||
|   J = K+K; | ||||
|   if(J<N) { | ||||
|     if(HA[J]<HA[J+1]) | ||||
|       J++; | ||||
|   } | ||||
| /*      break */ | ||||
|   if(V>=HA[J]) | ||||
|     goto x200; | ||||
|   HA[K] = HA[J]; | ||||
|   JJ = HJ[J]; | ||||
|   HJ[K] = JJ; | ||||
|   HK[JJ] = K; | ||||
|   K = J; | ||||
|   goto x100; | ||||
| /*      end while */ | ||||
| x200: | ||||
|   HA[K] = V; | ||||
|   HJ[K] = JV; | ||||
|   HK[JV] = K; | ||||
| } | ||||
| 
 | ||||
| /* ==================================================================
 | ||||
|    Hup updates heap by moving up tree from node k. | ||||
|    ------------------------------------------------------------------ | ||||
|    01 May 2002: Need Nk for length of Hk. | ||||
|    05 May 2002: Change input paramter k to kk to stop k being output. | ||||
|    05 May 2002: Current version of Hup. | ||||
|    ================================================================== */ | ||||
| void HUP(REAL HA[], int HJ[], int HK[], int K, int *HOPS) | ||||
| { | ||||
|   int  J, JV, K2; | ||||
|   REAL V; | ||||
| 
 | ||||
|   *HOPS = 0; | ||||
|   V = HA[K]; | ||||
|  JV = HJ[K]; | ||||
| /*      while 1
 | ||||
|         break */ | ||||
| x100: | ||||
|   if(K<2) | ||||
|     goto x200; | ||||
|   K2 = K/2; | ||||
| /*      break */ | ||||
|   if(V<HA[K2]) | ||||
|     goto x200; | ||||
|   (*HOPS)++; | ||||
|   HA[K] = HA[K2]; | ||||
|   J = HJ[K2]; | ||||
|   HJ[K] = J; | ||||
|   HK[J] = K; | ||||
|   K = K2; | ||||
|   goto x100; | ||||
| /*      end while */ | ||||
| x200: | ||||
|   HA[K] = V; | ||||
|   HJ[K] = JV; | ||||
|   HK[JV] = K; | ||||
| } | ||||
| 
 | ||||
| /* ==================================================================
 | ||||
|    Hinsert inserts (v,jv) into heap of length N-1 | ||||
|    to make heap of length N. | ||||
|    ------------------------------------------------------------------ | ||||
|    03 Apr 2002: First version of Hinsert. | ||||
|    01 May 2002: Require N to be final length, not old length. | ||||
|                 Need Nk for length of Hk. | ||||
|    07 May 2002: Protect input parameters N, Nk. | ||||
|    07 May 2002: Current version of Hinsert. | ||||
|    ================================================================== */ | ||||
| void HINSERT(REAL HA[], int HJ[], int HK[], int N, | ||||
|              REAL V, int JV, int *HOPS) | ||||
| { | ||||
|   HA[N] = V; | ||||
|   HJ[N] = JV; | ||||
|   HK[JV] = N; | ||||
|   HUP(HA,HJ,HK,N,HOPS); | ||||
| } | ||||
| 
 | ||||
| /* ==================================================================
 | ||||
|    Hchange changes Ha(k) to v in heap of length N. | ||||
|    ------------------------------------------------------------------ | ||||
|    01 May 2002: Need Nk for length of Hk. | ||||
|    07 May 2002: Protect input parameters N, Nk, k. | ||||
|    07 May 2002: Current version of Hchange. | ||||
|    ================================================================== */ | ||||
| void HCHANGE(REAL HA[], int HJ[], int HK[], int N, int K, | ||||
|              REAL V, int JV, int *HOPS) | ||||
| { | ||||
|   REAL V1; | ||||
| 
 | ||||
|   V1 = HA[K]; | ||||
|   HA[K] = V; | ||||
|   HJ[K] = JV; | ||||
|   HK[JV] = K; | ||||
|   if(V1<V) | ||||
|     HUP  (HA,HJ,HK,  K,HOPS); | ||||
|   else | ||||
|     HDOWN(HA,HJ,HK,N,K,HOPS); | ||||
| } | ||||
| 
 | ||||
| /* ==================================================================
 | ||||
|    Hdelete deletes Ha(k) from heap of length N. | ||||
|    ------------------------------------------------------------------ | ||||
|    03 Apr 2002: Current version of Hdelete. | ||||
|    01 May 2002: Need Nk for length of Hk. | ||||
|    07 May 2002: Protect input parameters N, Nk, k. | ||||
|    07 May 2002: Current version of Hdelete. | ||||
|    ================================================================== */ | ||||
| void HDELETE(REAL HA[], int HJ[], int HK[], int *N, int K, int *HOPS) | ||||
| { | ||||
| 
 | ||||
|   int  JV, NX; | ||||
|   REAL V; | ||||
| 
 | ||||
|   NX = *N; | ||||
|   V = HA[NX]; | ||||
|   JV = HJ[NX]; | ||||
|   (*N)--; | ||||
|   *HOPS = 0; | ||||
|   if(K<NX) | ||||
|     HCHANGE(HA,HJ,HK,NX,K,V,JV,HOPS); | ||||
| } | ||||
| 
 | ||||
| /* ==================================================================
 | ||||
|    Hbuild initializes the heap by inserting each element of Ha. | ||||
|    Input:  Ha, Hj. | ||||
|    Output: Ha, Hj, Hk, hops. | ||||
|    ------------------------------------------------------------------ | ||||
|    01 May 2002: Use k for new length of heap, not k-1 for old length. | ||||
|    05 May 2002: Use kk in call to stop loop variable k being altered. | ||||
|                 (Actually Hinsert no longer alters that parameter.) | ||||
|    07 May 2002: ftnchek wants us to protect Nk, Ha(k), Hj(k) too. | ||||
|    07 May 2002: Current version of Hbuild. | ||||
|    ================================================================== */ | ||||
| void HBUILD(REAL HA[], int HJ[], int HK[], int N, int *HOPS) | ||||
| { | ||||
|   int  H, JV, K, KK; | ||||
|   REAL V; | ||||
| 
 | ||||
|   *HOPS = 0; | ||||
|   for(K = 1; K <= N; K++) { | ||||
|     KK = K; | ||||
|     V = HA[K]; | ||||
|     JV = HJ[K]; | ||||
|     HINSERT(HA,HJ,HK,KK,V,JV,&H); | ||||
|     (*HOPS) += H; | ||||
|   } | ||||
| } | ||||
|  | @ -1,867 +0,0 @@ | |||
| 
 | ||||
| /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 | ||||
|    File  lusol6a | ||||
|       lu6sol   lu6L     lu6Lt     lu6U     Lu6Ut   lu6LD   lu6chk | ||||
|    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | ||||
|    26 Apr 2002: lu6 routines put into a separate file. | ||||
|    15 Dec 2002: lu6sol modularized via lu6L, lu6Lt, lu6U, lu6Ut. | ||||
|                 lu6LD implemented to allow solves with LDL' or L|D|L'. | ||||
|    15 Dec 2002: Current version of lusol6a.f. | ||||
|    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ | ||||
| 
 | ||||
| /* ==================================================================
 | ||||
|    lu6chk  looks at the LU factorization  A = L*U. | ||||
|    If mode = 1, lu6chk is being called by lu1fac. | ||||
|    (Other modes not yet implemented.) | ||||
|    ------------------------------------------------------------------ | ||||
|    The important input parameters are | ||||
| 
 | ||||
|                   lprint = luparm(2) | ||||
|                   keepLU = luparm(8) | ||||
|                   Utol1  = parmlu(4) | ||||
|                   Utol2  = parmlu(5) | ||||
| 
 | ||||
|    and the significant output parameters are | ||||
| 
 | ||||
|                   inform = luparm(10) | ||||
|                   nsing  = luparm(11) | ||||
|                   jsing  = luparm(12) | ||||
|                   jumin  = luparm(19) | ||||
|                   Lmax   = parmlu(11) | ||||
|                   Umax   = parmlu(12) | ||||
|                   DUmax  = parmlu(13) | ||||
|                   DUmin  = parmlu(14) | ||||
|                   and      w(*). | ||||
| 
 | ||||
|    Lmax  and Umax  return the largest elements in L and U. | ||||
|    DUmax and DUmin return the largest and smallest diagonals of U | ||||
|                    (excluding diagonals that are exactly zero). | ||||
|    In general, w(j) is set to the maximum absolute element in | ||||
|    the j-th column of U.  However, if the corresponding diagonal | ||||
|    of U is small in absolute terms or relative to w(j) | ||||
|    (as judged by the parameters Utol1, Utol2 respectively), | ||||
|    then w(j) is changed to - w(j). | ||||
|    Thus, if w(j) is not positive, the j-th column of A | ||||
|    appears to be dependent on the other columns of A. | ||||
|    The number of such columns, and the position of the last one, | ||||
|    are returned as nsing and jsing. | ||||
|    Note that nrank is assumed to be set already, and is not altered. | ||||
|    Typically, nsing will satisfy      nrank + nsing = n,  but if | ||||
|    Utol1 and Utol2 are rather large,  nsing > n - nrank   may occur. | ||||
|    If keepLU = 0, | ||||
|    Lmax  and Umax  are already set by lu1fac. | ||||
|    The diagonals of U are in the top of A. | ||||
|    Only Utol1 is used in the singularity test to set w(*). | ||||
|    inform = 0  if  A  appears to have full column rank  (nsing = 0). | ||||
|    inform = 1  otherwise  (nsing .gt. 0). | ||||
|    ------------------------------------------------------------------ | ||||
|    00 Jul 1987: Early version. | ||||
|    09 May 1988: f77 version. | ||||
|    11 Mar 2001: Allow for keepLU = 0. | ||||
|    17 Nov 2001: Briefer output for singular factors. | ||||
|    05 May 2002: Comma needed in format 1100 (via Kenneth Holmstrom). | ||||
|    06 May 2002: With keepLU = 0, diags of U are in natural order. | ||||
|                 They were not being extracted correctly. | ||||
|    23 Apr 2004: TRP can judge singularity better by comparing | ||||
|                 all diagonals to DUmax. | ||||
|    27 Jun 2004: (PEG) Allow write only if nout .gt. 0. | ||||
|    ================================================================== */ | ||||
| #ifdef UseOld_LU6CHK_20040510 | ||||
| void LU6CHK(LUSOLrec *LUSOL, int MODE, int LENA2, int *INFORM) | ||||
| { | ||||
|   MYBOOL KEEPLU; | ||||
|   int    I, J, JUMIN, K, L, L1, L2, LENL, LPRINT, NDEFIC, NRANK; | ||||
|   REAL   AIJ, DIAG, DUMAX, DUMIN, LMAX, UMAX, UTOL1, UTOL2; | ||||
| 
 | ||||
|   LPRINT = LUSOL->luparm[LUSOL_IP_PRINTLEVEL]; | ||||
|   KEEPLU = (MYBOOL) (LUSOL->luparm[LUSOL_IP_KEEPLU]!=0); | ||||
|   NRANK = LUSOL->luparm[LUSOL_IP_RANK_U]; | ||||
|   LENL  = LUSOL->luparm[LUSOL_IP_NONZEROS_L]; | ||||
|   UTOL1 = LUSOL->parmlu[LUSOL_RP_SMALLDIAG_U]; | ||||
|   UTOL2 = LUSOL->parmlu[LUSOL_RP_EPSDIAG_U]; | ||||
|   *INFORM = LUSOL_INFORM_LUSUCCESS; | ||||
|   LMAX  = ZERO; | ||||
|   UMAX  = ZERO; | ||||
|   LUSOL->luparm[LUSOL_IP_SINGULARITIES]  = 0; | ||||
|   LUSOL->luparm[LUSOL_IP_SINGULARINDEX]  = 0; | ||||
|   JUMIN = 0; | ||||
|   DUMAX = ZERO; | ||||
|   DUMIN = LUSOL_BIGNUM; | ||||
| 
 | ||||
| #ifdef LUSOLFastClear | ||||
|   MEMCLEAR(LUSOL->w+1, LUSOL->n); | ||||
| #else | ||||
|   for(I = 1; I <= LUSOL->n; I++) | ||||
|     LUSOL->w[I] = ZERO; | ||||
| #endif | ||||
| 
 | ||||
|   if(KEEPLU) { | ||||
| /*     --------------------------------------------------------------
 | ||||
|         Find  Lmax. | ||||
|        -------------------------------------------------------------- */ | ||||
|     for(L = (LENA2+1)-LENL; L <= LENA2; L++) { | ||||
|       SETMAX(LMAX,fabs(LUSOL->a[L])); | ||||
|     } | ||||
| /*     --------------------------------------------------------------
 | ||||
|         Find Umax and set w(j) = maximum element in j-th column of U. | ||||
|        -------------------------------------------------------------- */ | ||||
|     for(K = 1; K <= NRANK; K++) { | ||||
|       I = LUSOL->ip[K]; | ||||
|       L1 = LUSOL->locr[I]; | ||||
|       L2 = (L1+LUSOL->lenr[I])-1; | ||||
|       for(L = L1; L <= L2; L++) { | ||||
|         J = LUSOL->indr[L]; | ||||
|         AIJ = fabs(LUSOL->a[L]); | ||||
|         SETMAX(LUSOL->w[J],AIJ); | ||||
|         SETMAX(UMAX,AIJ); | ||||
|       } | ||||
|     } | ||||
| /*     --------------------------------------------------------------
 | ||||
|         Negate w(j) if the corresponding diagonal of U is | ||||
|         too small in absolute terms or relative to the other elements | ||||
|         in the same column of  U. | ||||
|         Also find DUmax and DUmin, the extreme diagonals of U. | ||||
|        -------------------------------------------------------------- */ | ||||
|     for(K = 1; K <= LUSOL->n; K++) { | ||||
|       J = LUSOL->iq[K]; | ||||
|       if(K>NRANK) | ||||
|         DIAG = ZERO; | ||||
|       else { | ||||
|         I = LUSOL->ip[K]; | ||||
|         L1 = LUSOL->locr[I]; | ||||
|         DIAG = fabs(LUSOL->a[L1]); | ||||
|         SETMAX(DUMAX,DIAG); | ||||
|         if(DUMIN>DIAG) { | ||||
|           DUMIN = DIAG; | ||||
|           JUMIN = J; | ||||
|         } | ||||
|       } | ||||
|       if((DIAG<=UTOL1) || (DIAG<=UTOL2*LUSOL->w[J])) { | ||||
|         LUSOL_addSingularity(LUSOL, J, INFORM); | ||||
|         LUSOL->w[J] = -LUSOL->w[J]; | ||||
|       } | ||||
|     } | ||||
|     LUSOL->parmlu[LUSOL_RP_MAXMULT_L] = LMAX; | ||||
|     LUSOL->parmlu[LUSOL_RP_MAXELEM_U] = UMAX; | ||||
|   } | ||||
|    else { | ||||
| /*     --------------------------------------------------------------
 | ||||
|         keepLU = 0. | ||||
|         Only diag(U) is stored.  Set w(*) accordingly. | ||||
|        -------------------------------------------------------------- */ | ||||
|     for(K = 1; K <= LUSOL->n; K++) { | ||||
|       J = LUSOL->iq[K]; | ||||
|       if(K>NRANK) | ||||
|         DIAG = ZERO; | ||||
|       else { | ||||
| /* !             diag   = abs( diagU(k) ) ! 06 May 2002: Diags are in natural order */ | ||||
|         DIAG = fabs(LUSOL->diagU[J]); | ||||
|         LUSOL->w[J] = DIAG; | ||||
|         SETMAX(DUMAX,DIAG); | ||||
|         if(DUMIN>DIAG) { | ||||
|           DUMIN = DIAG; | ||||
|           JUMIN = J; | ||||
|         } | ||||
|       } | ||||
|       if(DIAG<=UTOL1) { | ||||
|         LUSOL_addSingularity(LUSOL, J, INFORM); | ||||
|         LUSOL->w[J] = -LUSOL->w[J]; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| /*     -----------------------------------------------------------------
 | ||||
|         Set output parameters. | ||||
|        ----------------------------------------------------------------- */ | ||||
|   if(JUMIN==0) | ||||
|     DUMIN = ZERO; | ||||
|   LUSOL->luparm[LUSOL_IP_COLINDEX_DUMIN] = JUMIN; | ||||
|   LUSOL->parmlu[LUSOL_RP_MAXELEM_DIAGU]  = DUMAX; | ||||
|   LUSOL->parmlu[LUSOL_RP_MINELEM_DIAGU]  = DUMIN; | ||||
| /*      The matrix has been judged singular. */ | ||||
|   if(LUSOL->luparm[LUSOL_IP_SINGULARITIES]>0) { | ||||
|     *INFORM = LUSOL_INFORM_LUSINGULAR; | ||||
|     NDEFIC = LUSOL->n-NRANK; | ||||
|     if(LPRINT>=LUSOL_MSG_SINGULARITY) { | ||||
|       LUSOL_report(LUSOL, 0, "Singular(m%cn)  rank:%9d  n-rank:%8d  nsing:%9d\n", | ||||
|                              relationChar(LUSOL->m, LUSOL->n),NRANK,NDEFIC, | ||||
|                              LUSOL->luparm[LUSOL_IP_SINGULARITIES]); | ||||
|     } | ||||
|   } | ||||
| /*      Exit. */ | ||||
|   LUSOL->luparm[LUSOL_IP_INFORM] = *INFORM; | ||||
| } | ||||
| #else | ||||
| void LU6CHK(LUSOLrec *LUSOL, int MODE, int LENA2, int *INFORM) | ||||
| { | ||||
|   MYBOOL KEEPLU, TRP; | ||||
|   int    I, J, JUMIN, K, L, L1, L2, LENL, LDIAGU, LPRINT, NDEFIC, NRANK; | ||||
|   REAL   AIJ, DIAG, DUMAX, DUMIN, LMAX, UMAX, UTOL1, UTOL2; | ||||
| 
 | ||||
|   LPRINT = LUSOL->luparm[LUSOL_IP_PRINTLEVEL]; | ||||
|   KEEPLU = (MYBOOL) (LUSOL->luparm[LUSOL_IP_KEEPLU] != 0); | ||||
|   TRP    = (MYBOOL) (LUSOL->luparm[LUSOL_IP_PIVOTTYPE] == LUSOL_PIVMOD_TRP); | ||||
|   NRANK  = LUSOL->luparm[LUSOL_IP_RANK_U]; | ||||
|   LENL   = LUSOL->luparm[LUSOL_IP_NONZEROS_L]; | ||||
|   UTOL1  = LUSOL->parmlu[LUSOL_RP_SMALLDIAG_U]; | ||||
|   UTOL2  = LUSOL->parmlu[LUSOL_RP_EPSDIAG_U]; | ||||
|   *INFORM = LUSOL_INFORM_LUSUCCESS; | ||||
|   LMAX   = ZERO; | ||||
|   UMAX   = ZERO; | ||||
|   LUSOL->luparm[LUSOL_IP_SINGULARITIES] = 0; | ||||
|   LUSOL->luparm[LUSOL_IP_SINGULARINDEX] = 0; | ||||
|   JUMIN  = 0; | ||||
|   DUMAX  = ZERO; | ||||
|   DUMIN  = LUSOL_BIGNUM; | ||||
| 
 | ||||
| #ifdef LUSOLFastClear | ||||
|   MEMCLEAR(LUSOL->w+1, LUSOL->n); | ||||
| #else | ||||
|   for(I = 1; I <= LUSOL->n; I++) | ||||
|     LUSOL->w[I] = ZERO; | ||||
| #endif | ||||
| 
 | ||||
|   if(KEEPLU) { | ||||
| /*     --------------------------------------------------------------
 | ||||
|         Find  Lmax. | ||||
|        -------------------------------------------------------------- */ | ||||
|     for(L = (LENA2+1)-LENL; L <= LENA2; L++) { | ||||
|       SETMAX(LMAX,fabs(LUSOL->a[L])); | ||||
|      } | ||||
| /*     --------------------------------------------------------------
 | ||||
|         Find Umax and set w(j) = maximum element in j-th column of U. | ||||
|        -------------------------------------------------------------- */ | ||||
|     for(K = 1; K <= NRANK; K++) { | ||||
|       I = LUSOL->ip[K]; | ||||
|       L1 = LUSOL->locr[I]; | ||||
|       L2 = (L1+LUSOL->lenr[I])-1; | ||||
|       for(L = L1; L <= L2; L++) { | ||||
|         J = LUSOL->indr[L]; | ||||
|         AIJ = fabs(LUSOL->a[L]); | ||||
|         SETMAX(LUSOL->w[J],AIJ); | ||||
|         SETMAX(UMAX,AIJ); | ||||
|       } | ||||
|     } | ||||
|     LUSOL->parmlu[LUSOL_RP_MAXMULT_L] = LMAX; | ||||
|     LUSOL->parmlu[LUSOL_RP_MAXELEM_U] = UMAX; | ||||
| /*     --------------------------------------------------------------
 | ||||
|        Find DUmax and DUmin, the extreme diagonals of U. | ||||
|        -------------------------------------------------------------- */ | ||||
|     for(K = 1; K <= NRANK; K++) { | ||||
|       J     = LUSOL->iq[K]; | ||||
|       I     = LUSOL->ip[K]; | ||||
|       L1    = LUSOL->locr[I]; | ||||
|       DIAG  = fabs(LUSOL->a[L1]); | ||||
|       SETMAX( DUMAX, DIAG ); | ||||
|       if(DUMIN > DIAG) { | ||||
|         DUMIN  = DIAG; | ||||
|         JUMIN  = J; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   else { | ||||
| /*     --------------------------------------------------------------
 | ||||
|        keepLU = 0. | ||||
|        Only diag(U) is stored.  Set w(*) accordingly. | ||||
|        Find DUmax and DUmin, the extreme diagonals of U. | ||||
|        -------------------------------------------------------------- */ | ||||
|     LDIAGU = LENA2 - LUSOL->n; | ||||
|     for(K = 1; K <= NRANK; K++) { | ||||
|       J           = LUSOL->iq[K]; | ||||
|       DIAG        = fabs( LUSOL->a[LDIAGU + J] ); /* are in natural order */ | ||||
|       LUSOL->w[J] = DIAG; | ||||
|       SETMAX( DUMAX, DIAG ); | ||||
|       if(DUMIN > DIAG) { | ||||
|         DUMIN = DIAG; | ||||
|         JUMIN = J; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| /*     --------------------------------------------------------------
 | ||||
|        Negate w(j) if the corresponding diagonal of U is | ||||
|        too small in absolute terms or relative to the other elements | ||||
|        in the same column of  U. | ||||
| 
 | ||||
|        23 Apr 2004: TRP ensures that diags are NOT small relative to | ||||
|                     other elements in their own column. | ||||
|                     Much better, we can compare all diags to DUmax. | ||||
|       -------------------------------------------------------------- */ | ||||
|   if((MODE == 1) && TRP) { | ||||
|     SETMAX( UTOL1, UTOL2*DUMAX ); | ||||
|   } | ||||
| 
 | ||||
|   if(KEEPLU) { | ||||
|     for(K = 1; K <= LUSOL->n; K++) { | ||||
|       J = LUSOL->iq[K]; | ||||
|       if(K>NRANK) | ||||
|         DIAG = ZERO; | ||||
|       else { | ||||
|         I = LUSOL->ip[K]; | ||||
|         L1 = LUSOL->locr[I]; | ||||
|         DIAG = fabs(LUSOL->a[L1]); | ||||
|       } | ||||
|       if((DIAG<=UTOL1) || (DIAG<=UTOL2*LUSOL->w[J])) { | ||||
|         LUSOL_addSingularity(LUSOL, J, INFORM); | ||||
|         LUSOL->w[J] = -LUSOL->w[J]; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   else { /* keepLU = FALSE */ | ||||
|     for(K = 1; K <= LUSOL->n; K++) { | ||||
|       J = LUSOL->iq[K]; | ||||
|       DIAG = LUSOL->w[J]; | ||||
|       if(DIAG<=UTOL1) { | ||||
|         LUSOL_addSingularity(LUSOL, J, INFORM); | ||||
|         LUSOL->w[J] = -LUSOL->w[J]; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| /*     -----------------------------------------------------------------
 | ||||
|         Set output parameters. | ||||
|        ----------------------------------------------------------------- */ | ||||
|   if(JUMIN==0) | ||||
|     DUMIN = ZERO; | ||||
|   LUSOL->luparm[LUSOL_IP_COLINDEX_DUMIN] = JUMIN; | ||||
|   LUSOL->parmlu[LUSOL_RP_MAXELEM_DIAGU]  = DUMAX; | ||||
|   LUSOL->parmlu[LUSOL_RP_MINELEM_DIAGU]  = DUMIN; | ||||
| /*      The matrix has been judged singular. */ | ||||
|   if(LUSOL->luparm[LUSOL_IP_SINGULARITIES]>0) { | ||||
|     *INFORM = LUSOL_INFORM_LUSINGULAR; | ||||
|     NDEFIC = LUSOL->n-NRANK; | ||||
|     if((LUSOL->outstream!=NULL) && (LPRINT>=LUSOL_MSG_SINGULARITY)) { | ||||
|       LUSOL_report(LUSOL, 0, "Singular(m%cn)  rank:%9d  n-rank:%8d  nsing:%9d\n", | ||||
|                              relationChar(LUSOL->m, LUSOL->n),NRANK,NDEFIC, | ||||
|                              LUSOL->luparm[LUSOL_IP_SINGULARITIES]); | ||||
|     } | ||||
|   } | ||||
| /*      Exit. */ | ||||
|   LUSOL->luparm[LUSOL_IP_INFORM] = *INFORM; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /* ------------------------------------------------------------------
 | ||||
|    Include routines for row-based L0. | ||||
|    20 Apr 2005 Current version - KE. | ||||
|    ------------------------------------------------------------------ */ | ||||
| #include "lusol6l0.c" | ||||
| 
 | ||||
| 
 | ||||
| /* ------------------------------------------------------------------
 | ||||
|    lu6L   solves   L v = v(input). | ||||
|    ------------------------------------------------------------------ | ||||
|    15 Dec 2002: First version derived from lu6sol. | ||||
|    15 Dec 2002: Current version. | ||||
|    ------------------------------------------------------------------ */ | ||||
| void LU6L(LUSOLrec *LUSOL, int *INFORM, REAL V[], int NZidx[]) | ||||
| { | ||||
|   int  JPIV, K, L, L1, LEN, LENL, LENL0, NUML, NUML0; | ||||
|   REAL SMALL; | ||||
|   register REAL VPIV; | ||||
| #ifdef LUSOLFastSolve | ||||
|   REAL *aptr; | ||||
|   int  *iptr, *jptr; | ||||
| #else | ||||
|   int  I, J; | ||||
| #endif | ||||
| 
 | ||||
|   NUML0 = LUSOL->luparm[LUSOL_IP_COLCOUNT_L0]; | ||||
|   LENL0 = LUSOL->luparm[LUSOL_IP_NONZEROS_L0]; | ||||
|   LENL  = LUSOL->luparm[LUSOL_IP_NONZEROS_L]; | ||||
|   SMALL = LUSOL->parmlu[LUSOL_RP_ZEROTOLERANCE]; | ||||
|   *INFORM = LUSOL_INFORM_LUSUCCESS; | ||||
|   L1 = LUSOL->lena+1; | ||||
|   for(K = 1; K <= NUML0; K++) { | ||||
|     LEN = LUSOL->lenc[K]; | ||||
|     L = L1; | ||||
|     L1 -= LEN; | ||||
|     JPIV = LUSOL->indr[L1]; | ||||
|     VPIV = V[JPIV]; | ||||
|     if(fabs(VPIV)>SMALL) { | ||||
| /*     ***** This loop could be coded specially. */ | ||||
| #ifdef LUSOLFastSolve | ||||
|       L--; | ||||
|       for(aptr = LUSOL->a+L, iptr = LUSOL->indc+L; | ||||
|           LEN > 0; LEN--, aptr--, iptr--) | ||||
|         V[*iptr] += (*aptr) * VPIV; | ||||
| #else | ||||
|       for(; LEN > 0; LEN--) { | ||||
|         L--; | ||||
|         I = LUSOL->indc[L]; | ||||
|         V[I] += LUSOL->a[L]*VPIV; | ||||
|       } | ||||
| #endif | ||||
|     } | ||||
| #ifdef SetSmallToZero | ||||
|     else | ||||
|       V[JPIV] = 0; | ||||
| #endif | ||||
|   } | ||||
|   L = (LUSOL->lena-LENL0)+1; | ||||
|   NUML = LENL-LENL0; | ||||
| /*     ***** This loop could be coded specially. */ | ||||
| #ifdef LUSOLFastSolve | ||||
|   L--; | ||||
|   for(aptr = LUSOL->a+L, jptr = LUSOL->indr+L, iptr = LUSOL->indc+L; | ||||
|       NUML > 0; NUML--, aptr--, jptr--, iptr--) { | ||||
|     if(fabs(V[*jptr])>SMALL) | ||||
|       V[*iptr] += (*aptr) * V[*jptr]; | ||||
| #ifdef SetSmallToZero | ||||
|     else | ||||
|       V[*jptr] = 0; | ||||
| #endif | ||||
|   } | ||||
| #else | ||||
|   for(; NUML > 0; NUML--) { | ||||
|     L--; | ||||
|     J = LUSOL->indr[L]; | ||||
|     if(fabs(V[J])>SMALL) { | ||||
|       I = LUSOL->indc[L]; | ||||
|       V[I] += LUSOL->a[L]*V[J]; | ||||
|     } | ||||
| #ifdef SetSmallToZero | ||||
|     else | ||||
|       V[J] = 0; | ||||
| #endif | ||||
|   } | ||||
| #endif | ||||
| /*      Exit. */ | ||||
|   LUSOL->luparm[LUSOL_IP_INFORM] = *INFORM; | ||||
| } | ||||
| 
 | ||||
| /* ==================================================================
 | ||||
|    lu6LD  assumes lu1fac has computed factors A = LU of a | ||||
|    symmetric definite or quasi-definite matrix A, | ||||
|    using Threshold Symmetric Pivoting (TSP),   luparm(6) = 3, | ||||
|    or    Threshold Diagonal  Pivoting (TDP),   luparm(6) = 4. | ||||
|    It also assumes that no updates have been performed. | ||||
|    In such cases,  U = D L', where D = diag(U). | ||||
|    lu6LDL returns v as follows: | ||||
| 
 | ||||
|    mode | ||||
|     1    v  solves   L D v = v(input). | ||||
|     2    v  solves   L|D|v = v(input). | ||||
|    ------------------------------------------------------------------ | ||||
|    15 Dec 2002: First version of lu6LD. | ||||
|    15 Dec 2002: Current version. | ||||
|    ================================================================== */ | ||||
| void LU6LD(LUSOLrec *LUSOL, int *INFORM, int MODE, REAL V[], int NZidx[]) | ||||
| { | ||||
|   int  IPIV, K, L, L1, LEN, NUML0; | ||||
|   REAL DIAG, SMALL; | ||||
|   register REAL VPIV; | ||||
| #ifdef LUSOLFastSolve | ||||
|   REAL *aptr; | ||||
|   int  *jptr; | ||||
| #else | ||||
|   int  J; | ||||
| #endif | ||||
| 
 | ||||
| /*      Solve L D v(new) = v  or  L|D|v(new) = v, depending on mode.
 | ||||
|         The code for L is the same as in lu6L, | ||||
|         but when a nonzero entry of v arises, we divide by | ||||
|         the corresponding entry of D or |D|. */ | ||||
|   NUML0 = LUSOL->luparm[LUSOL_IP_COLCOUNT_L0]; | ||||
|   SMALL = LUSOL->parmlu[LUSOL_RP_ZEROTOLERANCE]; | ||||
|   *INFORM = LUSOL_INFORM_LUSUCCESS; | ||||
|   L1 = LUSOL->lena+1; | ||||
|   for(K = 1; K <= NUML0; K++) { | ||||
|     LEN = LUSOL->lenc[K]; | ||||
|     L = L1; | ||||
|     L1 -= LEN; | ||||
|     IPIV = LUSOL->indr[L1]; | ||||
|     VPIV = V[IPIV]; | ||||
|     if(fabs(VPIV)>SMALL) { | ||||
| /*     ***** This loop could be coded specially. */ | ||||
| #ifdef LUSOLFastSolve | ||||
|       L--; | ||||
|       for(aptr = LUSOL->a+L, jptr = LUSOL->indc+L; | ||||
|           LEN > 0; LEN--, aptr--, jptr--) | ||||
|         V[*jptr] += (*aptr)*VPIV; | ||||
| #else | ||||
|       for(; LEN > 0; LEN--) { | ||||
|         L--; | ||||
|         J = LUSOL->indc[L]; | ||||
|         V[J] += LUSOL->a[L]*VPIV; | ||||
|       } | ||||
| #endif | ||||
| /*      Find diag = U(ipiv,ipiv) and divide by diag or |diag|. */ | ||||
|       L = LUSOL->locr[IPIV]; | ||||
|       DIAG = LUSOL->a[L]; | ||||
|       if(MODE==2) | ||||
|         DIAG = fabs(DIAG); | ||||
|       V[IPIV] = VPIV/DIAG; | ||||
|     } | ||||
| #ifdef SetSmallToZero | ||||
|     else | ||||
|       V[IPIV] = 0; | ||||
| #endif | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* ==================================================================
 | ||||
|    lu6Lt  solves   L'v = v(input). | ||||
|    ------------------------------------------------------------------ | ||||
|    15 Dec 2002: First version derived from lu6sol. | ||||
|    15 Dec 2002: Current version. | ||||
|    ================================================================== */ | ||||
| void LU6LT(LUSOLrec *LUSOL, int *INFORM, REAL V[], int NZidx[]) | ||||
| { | ||||
| #ifdef DoTraceL0 | ||||
|   REAL    TEMP; | ||||
| #endif | ||||
|   int     K, L, L1, L2, LEN, LENL, LENL0, NUML0; | ||||
|   REAL    SMALL; | ||||
|   register REALXP SUM; | ||||
|   register REAL HOLD; | ||||
| #if (defined LUSOLFastSolve) && !(defined DoTraceL0) | ||||
|   REAL    *aptr; | ||||
|   int     *iptr, *jptr; | ||||
| #else | ||||
|   int     I, J; | ||||
| #endif | ||||
| 
 | ||||
|   NUML0 = LUSOL->luparm[LUSOL_IP_COLCOUNT_L0]; | ||||
|   LENL0 = LUSOL->luparm[LUSOL_IP_NONZEROS_L0]; | ||||
|   LENL  = LUSOL->luparm[LUSOL_IP_NONZEROS_L]; | ||||
|   SMALL = LUSOL->parmlu[LUSOL_RP_ZEROTOLERANCE]; | ||||
|   *INFORM = LUSOL_INFORM_LUSUCCESS; | ||||
|   L1 = (LUSOL->lena-LENL)+1; | ||||
|   L2 = LUSOL->lena-LENL0; | ||||
| 
 | ||||
| /*     ***** This loop could be coded specially. */ | ||||
| #if (defined LUSOLFastSolve) && !(defined DoTraceL0) | ||||
|   for(L = L1, aptr = LUSOL->a+L1, iptr = LUSOL->indr+L1, jptr = LUSOL->indc+L1; | ||||
|       L <= L2; L++, aptr++, iptr++, jptr++) { | ||||
|     HOLD = V[*jptr]; | ||||
|     if(fabs(HOLD)>SMALL) | ||||
|       V[*iptr] += (*aptr)*HOLD; | ||||
| #ifdef SetSmallToZero | ||||
|     else | ||||
|       V[*jptr] = 0; | ||||
| #endif | ||||
|   } | ||||
| #else | ||||
|   for(L = L1; L <= L2; L++) { | ||||
|     J = LUSOL->indc[L]; | ||||
|     HOLD = V[J]; | ||||
|     if(fabs(HOLD)>SMALL) { | ||||
|       I = LUSOL->indr[L]; | ||||
|       V[I] += LUSOL->a[L]*HOLD; | ||||
|     } | ||||
| #ifdef SetSmallToZero | ||||
|     else | ||||
|       V[J] = 0; | ||||
| #endif | ||||
|   } | ||||
| #endif | ||||
| 
 | ||||
|   /* Do row-based L0 version, if available */ | ||||
|   if((LUSOL->L0 != NULL) || | ||||
|      ((LUSOL->luparm[LUSOL_IP_BTRANCOUNT] == 0) && LU1L0(LUSOL, &(LUSOL->L0), INFORM))) { | ||||
|     LU6L0T_v(LUSOL, LUSOL->L0, V, NZidx, INFORM); | ||||
|   } | ||||
| 
 | ||||
|   /* Alternatively, do the standard column-based L0 version */ | ||||
|   else  { | ||||
|     /* Perform loop over columns */ | ||||
|     for(K = NUML0; K >= 1; K--) { | ||||
|       SUM = ZERO; | ||||
|       LEN = LUSOL->lenc[K]; | ||||
|       L1 = L2+1; | ||||
|       L2 += LEN; | ||||
| /*     ***** This loop could be coded specially. */ | ||||
| #if (defined LUSOLFastSolve) && !(defined DoTraceL0) | ||||
|       for(L = L1, aptr = LUSOL->a+L1, jptr = LUSOL->indc+L1; | ||||
|           L <= L2; L++, aptr++, jptr++) | ||||
|         SUM += (*aptr) * V[*jptr]; | ||||
| #else | ||||
|       for(L = L1; L <= L2; L++) { | ||||
|         J = LUSOL->indc[L]; | ||||
| #ifndef DoTraceL0 | ||||
|         SUM += LUSOL->a[L]*V[J]; | ||||
| #else | ||||
|         TEMP = V[LUSOL->indr[L1]] + SUM; | ||||
|         SUM += LUSOL->a[L]*V[J]; | ||||
|         printf("V[%3d] = V[%3d] + L[%d,%d]*V[%3d]\n", LUSOL->indr[L1], LUSOL->indr[L1], J,LUSOL->indr[L1], J); | ||||
|         printf("%6g = %6g + %6g*%6g\n", V[LUSOL->indr[L1]] + SUM, TEMP, LUSOL->a[L], V[J]); | ||||
| #endif | ||||
|       } | ||||
| #endif | ||||
|       V[LUSOL->indr[L1]] += (REAL) SUM; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| /*      Exit. */ | ||||
|   LUSOL->luparm[LUSOL_IP_INFORM] = *INFORM; | ||||
| } | ||||
| 
 | ||||
| void print_L0(LUSOLrec *LUSOL) | ||||
| { | ||||
|   int  I, J, K, L, L1, L2, LEN, LENL0, NUML0; | ||||
|   REAL *denseL0 = (REAL*) calloc(LUSOL->m+1, (LUSOL->n+1)*sizeof(*denseL0)); | ||||
| 
 | ||||
|   NUML0 = LUSOL->luparm[LUSOL_IP_COLCOUNT_L0]; | ||||
|   LENL0 = LUSOL->luparm[LUSOL_IP_NONZEROS_L0]; | ||||
| 
 | ||||
|   L2 = LUSOL->lena-LENL0; | ||||
|   for(K = NUML0; K >= 1; K--) { | ||||
|     LEN = LUSOL->lenc[K]; | ||||
|     L1 = L2+1; | ||||
|     L2 += LEN; | ||||
|     for(L = L1; L <= L2; L++) { | ||||
|       I = LUSOL->indc[L]; | ||||
|       I = LUSOL->ipinv[I]; /* Undo row mapping */ | ||||
|       J = LUSOL->indr[L]; | ||||
|       denseL0[(LUSOL->n+1)*(J-1) + I] = LUSOL->a[L]; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   for(I = 1; I <= LUSOL->n; I++) { | ||||
|     for(J = 1; J <= LUSOL->m; J++) | ||||
|       fprintf(stdout, "%10g", denseL0[(LUSOL->n+1)*(J-1) + I]); | ||||
|     fprintf(stdout, "\n"); | ||||
|   } | ||||
|   LUSOL_FREE(denseL0); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* ------------------------------------------------------------------
 | ||||
|    Include routines for column-based U. | ||||
|    5 Feb 2006 Current version - KE. | ||||
|    ------------------------------------------------------------------ */ | ||||
| #include "lusol6u.c" | ||||
| 
 | ||||
| 
 | ||||
| /* ==================================================================
 | ||||
|    lu6U   solves   U w = v.          v  is not altered. | ||||
|    ------------------------------------------------------------------ | ||||
|    15 Dec 2002: First version derived from lu6sol. | ||||
|    15 Dec 2002: Current version. | ||||
|    ================================================================== */ | ||||
| void LU6U(LUSOLrec *LUSOL, int *INFORM, REAL V[], REAL W[], int NZidx[]) | ||||
| { | ||||
|   /* Do column-based U version, if available */ | ||||
|   if((LUSOL->U != NULL) || | ||||
|      ((LUSOL->luparm[LUSOL_IP_FTRANCOUNT] == 0) && LU1U0(LUSOL, &(LUSOL->U), INFORM))) { | ||||
|     LU6U0_v(LUSOL, LUSOL->U, V, W, NZidx, INFORM); | ||||
|   } | ||||
|   /* Alternatively, do the standard column-based L0 version */ | ||||
|   else { | ||||
|     int  I, J, K, KLAST, L, L1, L2, L3, NRANK, NRANK1; | ||||
|     REAL SMALL; | ||||
|     register REALXP T; | ||||
| #ifdef LUSOLFastSolve | ||||
|     REAL *aptr; | ||||
|     int  *jptr; | ||||
| #endif | ||||
|     NRANK = LUSOL->luparm[LUSOL_IP_RANK_U]; | ||||
|     SMALL = LUSOL->parmlu[LUSOL_RP_ZEROTOLERANCE]; | ||||
|     *INFORM = LUSOL_INFORM_LUSUCCESS; | ||||
|     NRANK1 = NRANK+1; | ||||
| /*      Find the first nonzero in v(1:nrank), counting backwards. */ | ||||
|     for(KLAST = NRANK; KLAST >= 1; KLAST--) { | ||||
|       I = LUSOL->ip[KLAST]; | ||||
|       if(fabs(V[I])>SMALL) | ||||
|         break; | ||||
|     } | ||||
|     L = LUSOL->n; | ||||
| #ifdef LUSOLFastSolve | ||||
|     for(K = KLAST+1, jptr = LUSOL->iq+K; K <= L; K++, jptr++) | ||||
|       W[*jptr] = ZERO; | ||||
| #else | ||||
|     for(K = KLAST+1; K <= L; K++) { | ||||
|       J = LUSOL->iq[K]; | ||||
|       W[J] = ZERO; | ||||
|     } | ||||
| #endif | ||||
| /*      Do the back-substitution, using rows 1:klast of U. */ | ||||
|     for(K = KLAST; K >= 1; K--) { | ||||
|       I = LUSOL->ip[K]; | ||||
|       T = V[I]; | ||||
|       L1 = LUSOL->locr[I]; | ||||
|       L2 = L1+1; | ||||
|       L3 = (L1+LUSOL->lenr[I])-1; | ||||
| /*     ***** This loop could be coded specially. */ | ||||
| #ifdef LUSOLFastSolve | ||||
|       for(L = L2, aptr = LUSOL->a+L2, jptr = LUSOL->indr+L2; | ||||
|           L <= L3; L++, aptr++, jptr++) | ||||
|         T -= (*aptr) * W[*jptr]; | ||||
| #else | ||||
|       for(L = L2; L <= L3; L++) { | ||||
|         J = LUSOL->indr[L]; | ||||
|         T -= LUSOL->a[L]*W[J]; | ||||
|       } | ||||
| #endif | ||||
|       J = LUSOL->iq[K]; | ||||
|       if(fabs((REAL) T)<=SMALL) | ||||
|         T = ZERO; | ||||
|       else | ||||
|         T /= LUSOL->a[L1]; | ||||
|       W[J] = (REAL) T; | ||||
|     } | ||||
| /*      Compute residual for overdetermined systems. */ | ||||
|     T = ZERO; | ||||
|     for(K = NRANK1; K <= LUSOL->m; K++) { | ||||
|       I = LUSOL->ip[K]; | ||||
|       T += fabs(V[I]); | ||||
|     } | ||||
| /*      Exit. */ | ||||
|     if(T>ZERO) | ||||
|       *INFORM = LUSOL_INFORM_LUSINGULAR; | ||||
|     LUSOL->luparm[LUSOL_IP_INFORM]     = *INFORM; | ||||
|     LUSOL->parmlu[LUSOL_RP_RESIDUAL_U] = (REAL) T; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /* ==================================================================
 | ||||
|    lu6Ut  solves   U'v = w.          w  is destroyed. | ||||
|    ------------------------------------------------------------------ | ||||
|    15 Dec 2002: First version derived from lu6sol. | ||||
|    15 Dec 2002: Current version. | ||||
|    ================================================================== */ | ||||
| void LU6UT(LUSOLrec *LUSOL, int *INFORM, REAL V[], REAL W[], int NZidx[]) | ||||
| { | ||||
|   int  I, J, K, L, L1, L2, NRANK, NRANK1, | ||||
|        *ip = LUSOL->ip + 1, *iq = LUSOL->iq + 1; | ||||
|   REAL SMALL; | ||||
|   register REAL T; | ||||
| #ifdef LUSOLFastSolve | ||||
|   REAL *aptr; | ||||
|   int  *jptr; | ||||
| #endif | ||||
| 
 | ||||
|   NRANK = LUSOL->luparm[LUSOL_IP_RANK_U]; | ||||
|   SMALL = LUSOL->parmlu[LUSOL_RP_ZEROTOLERANCE]; | ||||
|   *INFORM = LUSOL_INFORM_LUSUCCESS; | ||||
|   NRANK1 = NRANK+1; | ||||
|   L = LUSOL->m; | ||||
| #ifdef LUSOLFastSolve | ||||
|   for(K = NRANK1, jptr = LUSOL->ip+K; K <= L; K++, jptr++) | ||||
|     V[*jptr] = ZERO; | ||||
| #else | ||||
|   for(K = NRANK1; K <= L; K++) { | ||||
|     I = LUSOL->ip[K]; | ||||
|     V[I] = ZERO; | ||||
|   } | ||||
| #endif | ||||
| /*      Do the forward-substitution, skipping columns of U(transpose)
 | ||||
|         when the associated element of w(*) is negligible. */ | ||||
| #if 0 | ||||
|   for(K = 1; K <= NRANK; K++) { | ||||
|     I = LUSOL->ip[K]; | ||||
|     J = LUSOL->iq[K]; | ||||
| #else | ||||
|   for(K = 1; K <= NRANK; K++, ip++, iq++) { | ||||
|     I = *ip; | ||||
|     J = *iq; | ||||
| #endif | ||||
|     T = W[J]; | ||||
|     if(fabs(T)<=SMALL) { | ||||
|       V[I] = ZERO; | ||||
|       continue; | ||||
|     } | ||||
|     L1 = LUSOL->locr[I]; | ||||
|     T /= LUSOL->a[L1]; | ||||
|     V[I] = T; | ||||
|     L2 = (L1+LUSOL->lenr[I])-1; | ||||
|     L1++; | ||||
| /*     ***** This loop could be coded specially. */ | ||||
| #ifdef LUSOLFastSolve | ||||
|     for(L = L1, aptr = LUSOL->a+L1, jptr = LUSOL->indr+L1; | ||||
|         L <= L2; L++, aptr++, jptr++) | ||||
|       W[*jptr] -= T * (*aptr); | ||||
| #else | ||||
|     for(L = L1; L <= L2; L++) { | ||||
|       J = LUSOL->indr[L]; | ||||
|       W[J] -= T*LUSOL->a[L]; | ||||
|     } | ||||
| #endif | ||||
|   } | ||||
| /*      Compute residual for overdetermined systems. */ | ||||
|   T = ZERO; | ||||
|   for(K = NRANK1; K <= LUSOL->n; K++) { | ||||
|     J = LUSOL->iq[K]; | ||||
|     T += fabs(W[J]); | ||||
|   } | ||||
| /*      Exit. */ | ||||
|   if(T>ZERO) | ||||
|     *INFORM = LUSOL_INFORM_LUSINGULAR; | ||||
|   LUSOL->luparm[LUSOL_IP_INFORM]     = *INFORM; | ||||
|   LUSOL->parmlu[LUSOL_RP_RESIDUAL_U] = T; | ||||
| } | ||||
| 
 | ||||
| /* ==================================================================
 | ||||
|    lu6sol  uses the factorization  A = L U  as follows: | ||||
|    ------------------------------------------------------------------ | ||||
|    mode | ||||
|     1    v  solves   L v = v(input).   w  is not touched. | ||||
|     2    v  solves   L'v = v(input).   w  is not touched. | ||||
|     3    w  solves   U w = v.          v  is not altered. | ||||
|     4    v  solves   U'v = w.          w  is destroyed. | ||||
|     5    w  solves   A w = v.          v  is altered as in 1. | ||||
|     6    v  solves   A'v = w.          w  is destroyed. | ||||
| 
 | ||||
|    If mode = 3,4,5,6, v and w must not be the same arrays. | ||||
|    If lu1fac has just been used to factorize a symmetric matrix A | ||||
|    (which must be definite or quasi-definite), the factors A = L U | ||||
|    may be regarded as A = LDL', where D = diag(U).  In such cases, | ||||
| 
 | ||||
|    mode | ||||
|     7    v  solves   A v = L D L'v = v(input).   w  is not touched. | ||||
|     8    v  solves       L |D| L'v = v(input).   w  is not touched. | ||||
| 
 | ||||
|    ip(*), iq(*)      hold row and column numbers in pivotal order. | ||||
|    lenc(k)           is the length of the k-th column of initial L. | ||||
|    lenr(i)           is the length of the i-th row of U. | ||||
|    locc(*)           is not used. | ||||
|    locr(i)           is the start  of the i-th row of U. | ||||
| 
 | ||||
|    U is assumed to be in upper-trapezoidal form (nrank by n). | ||||
|    The first entry for each row is the diagonal element | ||||
|    (according to the permutations  ip, iq).  It is stored at | ||||
|    location locr(i) in a(*), indr(*). | ||||
| 
 | ||||
|    On exit, inform = 0 except as follows. | ||||
|      if(mode = 3,4,5,6 and if U (and hence A) is singular,) | ||||
|      inform = 1 if there is a nonzero residual in solving the system | ||||
|      involving U.  parmlu(20) returns the norm of the residual. | ||||
|    ------------------------------------------------------------------ | ||||
|      July 1987: Early version. | ||||
|    09 May 1988: f77 version. | ||||
|    27 Apr 2000: Abolished the dreaded "computed go to". | ||||
|                 But hard to change other "go to"s to "if then else". | ||||
|    15 Dec 2002: lu6L, lu6Lt, lu6U, lu6Ut added to modularize lu6sol. | ||||
|    ================================================================== */ | ||||
| void LU6SOL(LUSOLrec *LUSOL, int MODE, REAL V[], REAL W[], int NZidx[], int *INFORM) | ||||
| { | ||||
|   if(MODE==LUSOL_SOLVE_Lv_v) {          /* Solve  L v(new) = v. */ | ||||
|     LU6L(LUSOL, INFORM,V, NZidx); | ||||
|   } | ||||
|   else if(MODE==LUSOL_SOLVE_Ltv_v) {    /* Solve  L'v(new) = v. */ | ||||
|     LU6LT(LUSOL, INFORM,V, NZidx); | ||||
|   } | ||||
|   else if(MODE==LUSOL_SOLVE_Uw_v) {     /* Solve  U w = v. */ | ||||
|     LU6U(LUSOL, INFORM,V,W, NZidx); | ||||
|   } | ||||
|   else if(MODE==LUSOL_SOLVE_Utv_w) {    /* Solve  U'v = w. */ | ||||
|     LU6UT(LUSOL, INFORM,V,W, NZidx); | ||||
|   } | ||||
|   else if(MODE==LUSOL_SOLVE_Aw_v) {     /* Solve  A w      = v (i.e. FTRAN) */ | ||||
|     LU6L(LUSOL, INFORM,V, NZidx);        /* via     L v(new) = v */ | ||||
|     LU6U(LUSOL, INFORM,V,W, NULL);       /* ... and U w = v(new). */ | ||||
|   } | ||||
|   else if(MODE==LUSOL_SOLVE_Atv_w) {    /* Solve  A'v = w (i.e. BTRAN) */ | ||||
|     LU6UT(LUSOL, INFORM,V,W, NZidx);     /* via      U'v = w */ | ||||
|     LU6LT(LUSOL, INFORM,V, NULL);        /* ... and  L'v(new) = v. */ | ||||
|   } | ||||
|   else if(MODE==LUSOL_SOLVE_Av_v) {     /* Solve  LDv(bar) = v */ | ||||
|     LU6LD(LUSOL, INFORM,1,V, NZidx);     /* and    L'v(new) = v(bar). */ | ||||
|     LU6LT(LUSOL, INFORM,V, NULL); | ||||
|   } | ||||
|   else if(MODE==LUSOL_SOLVE_LDLtv_v) {  /* Solve  L|D|v(bar) = v */ | ||||
|     LU6LD(LUSOL, INFORM,2,V, NZidx);     /* and    L'v(new) = v(bar). */ | ||||
|     LU6LT(LUSOL, INFORM,V, NULL); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
|  | @ -1,163 +0,0 @@ | |||
| 
 | ||||
| /* Create a row-based version of L0.
 | ||||
|    This makes it possible to solve L0'x=h (btran) faster for sparse h, | ||||
|    since we only run down the columns of L0' (rows of LO) for which | ||||
|    the corresponding entry in h is non-zero. */ | ||||
| MYBOOL LU1L0(LUSOLrec *LUSOL, LUSOLmat **mat, int *inform) | ||||
| { | ||||
|   MYBOOL status = FALSE; | ||||
|   int    K, L, LL, L1, L2, LENL0, NUML0, I; | ||||
|   int    *lsumr; | ||||
| 
 | ||||
|   /* Assume success */ | ||||
|   *inform = LUSOL_INFORM_LUSUCCESS; | ||||
| 
 | ||||
|   /* Check if there is anything worth doing */ | ||||
|   if(mat == NULL) | ||||
|     return( status ); | ||||
|   if(*mat != NULL) | ||||
|     LUSOL_matfree(mat); | ||||
|   NUML0 = LUSOL->luparm[LUSOL_IP_COLCOUNT_L0]; | ||||
|   LENL0 = LUSOL->luparm[LUSOL_IP_NONZEROS_L0]; | ||||
|   if((NUML0 == 0) || (LENL0 == 0) || | ||||
|      (LUSOL->luparm[LUSOL_IP_ACCELERATION] == LUSOL_BASEORDER) || | ||||
|      ((LUSOL->luparm[LUSOL_IP_ACCELERATION] & LUSOL_ACCELERATE_L0) == 0)) | ||||
|     return( status ); | ||||
| 
 | ||||
|   /* Allocate temporary array */ | ||||
|   lsumr = (int *) LUSOL_CALLOC((LUSOL->m+1), sizeof(*lsumr)); | ||||
|   if(lsumr == NULL) { | ||||
|     *inform = LUSOL_INFORM_NOMEMLEFT; | ||||
|     return( status ); | ||||
|   } | ||||
| 
 | ||||
|   /* Compute non-zero counts by permuted row index (order is unimportant) */ | ||||
|   K = 0; | ||||
|   L2 = LUSOL->lena; | ||||
|   L1 = L2-LENL0+1; | ||||
|   for(L = L1; L <= L2; L++) { | ||||
|     I = LUSOL->indc[L]; | ||||
|     lsumr[I]++; | ||||
|     if(lsumr[I] == 1) | ||||
|       K++; | ||||
|   } | ||||
|   LUSOL->luparm[LUSOL_IP_ROWCOUNT_L0] = K; | ||||
| 
 | ||||
|   /* Check if we should apply "smarts" before proceeding to the row matrix creation */ | ||||
|   if((LUSOL->luparm[LUSOL_IP_ACCELERATION] & LUSOL_AUTOORDER) && | ||||
|      ((REAL) LUSOL->luparm[LUSOL_IP_ROWCOUNT_L0] / | ||||
| #if 0 | ||||
|              LUSOL->luparm[LUSOL_IP_COLCOUNT_L0] | ||||
| #else | ||||
|              LUSOL->m | ||||
| #endif | ||||
|       > LUSOL->parmlu[LUSOL_RP_SMARTRATIO])) | ||||
|     goto Finish; | ||||
| 
 | ||||
|   /* We are Ok to create the new matrix object */ | ||||
|   *mat = LUSOL_matcreate(LUSOL->m, LENL0); | ||||
|   if(*mat == NULL) { | ||||
|     *inform = LUSOL_INFORM_NOMEMLEFT; | ||||
|     goto Finish; | ||||
|   } | ||||
| 
 | ||||
|   /* Cumulate row counts to get vector offsets; first row is leftmost
 | ||||
|      (stick with Fortran array offset for consistency) */ | ||||
|   (*mat)->lenx[0] = 1; | ||||
|   for(K = 1; K <= LUSOL->m; K++) { | ||||
|     (*mat)->lenx[K] = (*mat)->lenx[K-1] + lsumr[K]; | ||||
|     lsumr[K] = (*mat)->lenx[K-1]; | ||||
|   } | ||||
| 
 | ||||
|   /* Map the matrix into row order by permuted index;
 | ||||
|      Note: The first permuted row is located leftmost in the array. | ||||
|            The column order is irrelevant, since the indeces will | ||||
|            refer to constant / resolved values of V[] during solve. */ | ||||
|   L2 = LUSOL->lena; | ||||
|   L1 = L2-LENL0+1; | ||||
|   for(L = L1; L <= L2; L++) { | ||||
|     I = LUSOL->indc[L]; | ||||
|     LL = lsumr[I]++; | ||||
|     (*mat)->a[LL] = LUSOL->a[L]; | ||||
|     (*mat)->indr[LL] = LUSOL->indr[L]; | ||||
|     (*mat)->indc[LL] = I; | ||||
|   } | ||||
| 
 | ||||
|   /* Pack row starting positions, and set mapper from original index to packed */ | ||||
|   I = 0; | ||||
|   for(L = 1; L <= LUSOL->m; L++) { | ||||
|     K = LUSOL->ip[L]; | ||||
|     if((*mat)->lenx[K] > (*mat)->lenx[K-1]) { | ||||
|       I++; | ||||
|       (*mat)->indx[I] = K; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /* Confirm that everything went well */ | ||||
|   status = TRUE; | ||||
| 
 | ||||
|   /* Clean up */ | ||||
| Finish: | ||||
|   FREE(lsumr); | ||||
|   return( status ); | ||||
| } | ||||
| 
 | ||||
| /* Solve L0' v = v based on row-based version of L0, constructed by LU1L0 */ | ||||
| void LU6L0T_v(LUSOLrec *LUSOL, LUSOLmat *mat, REAL V[], int NZidx[], int *INFORM) | ||||
| { | ||||
| #ifdef DoTraceL0 | ||||
|   REAL TEMP; | ||||
| #endif | ||||
|   int  LEN, K, KK, L, L1, NUML0; | ||||
|   REAL SMALL; | ||||
|   register REAL VPIV; | ||||
| #if (defined LUSOLFastSolve) && !(defined DoTraceL0) | ||||
|   REAL *aptr; | ||||
|   int  *jptr; | ||||
| #else | ||||
|   int  J; | ||||
| #endif | ||||
| 
 | ||||
|   NUML0 = LUSOL->luparm[LUSOL_IP_ROWCOUNT_L0]; | ||||
|   SMALL = LUSOL->parmlu[LUSOL_RP_ZEROTOLERANCE]; | ||||
| 
 | ||||
|   /* Loop over the nz columns of L0' - from the end, going forward. */ | ||||
|   for(K = NUML0; K > 0; K--) { | ||||
|     KK = mat->indx[K]; | ||||
|     L  = mat->lenx[KK]; | ||||
|     L1 = mat->lenx[KK-1]; | ||||
|     LEN = L - L1; | ||||
|     if(LEN == 0) | ||||
|       continue; | ||||
|     /* Get value of the corresponding active entry of V[] */ | ||||
|     VPIV = V[KK]; | ||||
|     /* Only process the column of L0' if the value of V[] is non-zero */ | ||||
|     if(fabs(VPIV)>SMALL) { | ||||
| /*     ***** This loop could be coded specially. */ | ||||
| #if (defined LUSOLFastSolve) && !(defined DoTraceL0) | ||||
|       L--; | ||||
|       for(aptr = mat->a+L, jptr = mat->indr+L; | ||||
|           LEN > 0; LEN--, aptr--, jptr--) | ||||
|         V[*jptr] += VPIV * (*aptr); | ||||
| #else | ||||
|       for(; LEN > 0; LEN--) { | ||||
|         L--; | ||||
|         J = mat->indr[L]; | ||||
| #ifndef DoTraceL0 | ||||
|         V[J] += VPIV * mat->a[L]; | ||||
| #else | ||||
|         TEMP = V[J]; | ||||
|         V[J] += VPIV * mat->a[L]; | ||||
|         printf("V[%3d] = V[%3d] + L[%d,%d]*V[%3d]\n", J, J, KK,J, KK); | ||||
|         printf("%6g = %6g + %6g*%6g\n", V[J], TEMP, mat->a[L], VPIV); | ||||
| #endif | ||||
|       } | ||||
| #endif | ||||
|     } | ||||
| #ifdef SetSmallToZero | ||||
|     else | ||||
|       V[KK] = 0; | ||||
| #endif | ||||
|   } | ||||
| 
 | ||||
| } | ||||
|  | @ -1,176 +0,0 @@ | |||
| 
 | ||||
| /* Create a column-based version of U.
 | ||||
|    This makes it possible to solve Ux=h (ftran) faster for sparse h, | ||||
|    since we only run down the rows of U (columns of U') for which | ||||
|    the corresponding entry in h is non-zero. */ | ||||
| MYBOOL LU1U0(LUSOLrec *LUSOL, LUSOLmat **mat, int *inform) | ||||
| { | ||||
|   MYBOOL status = FALSE; | ||||
|   int    K, L, LL, LENU, NUMU, J; | ||||
|   int    *lsumc; | ||||
| 
 | ||||
|   /* Assume success */ | ||||
|   *inform = LUSOL_INFORM_LUSUCCESS; | ||||
| 
 | ||||
|   /* Check if there is anything worth doing */ | ||||
|   if(mat == NULL) | ||||
|     return( status ); | ||||
|   if(*mat != NULL) | ||||
|     LUSOL_matfree(mat); | ||||
|   NUMU = LUSOL->luparm[LUSOL_IP_RANK_U]; | ||||
|   LENU = LUSOL->luparm[LUSOL_IP_NONZEROS_U]; | ||||
|   if((NUMU == 0) || (LENU == 0) || | ||||
|      (LUSOL->luparm[LUSOL_IP_ACCELERATION] == LUSOL_BASEORDER) || | ||||
|      ((LUSOL->luparm[LUSOL_IP_ACCELERATION] & LUSOL_ACCELERATE_U) == 0)) | ||||
|     return( status ); | ||||
| 
 | ||||
|   /* Allocate temporary array */ | ||||
|   lsumc = (int *) LUSOL_CALLOC((LUSOL->n+1), sizeof(*lsumc)); | ||||
|   if(lsumc == NULL) { | ||||
|     *inform = LUSOL_INFORM_NOMEMLEFT; | ||||
|     return( status ); | ||||
|   } | ||||
| 
 | ||||
|   /* Compute non-zero counts by permuted column index (order is unimportant) */ | ||||
|   for(L = 1; L <= LENU; L++) { | ||||
|     J = LUSOL->indr[L]; | ||||
|     lsumc[J]++; | ||||
|   } | ||||
| 
 | ||||
|   /* Check if we should apply "smarts" before proceeding to the column matrix creation */ | ||||
|   if((LUSOL->luparm[LUSOL_IP_ACCELERATION] & LUSOL_AUTOORDER) && | ||||
|      ((REAL) sqrt((REAL) NUMU/LENU) > LUSOL->parmlu[LUSOL_RP_SMARTRATIO])) | ||||
|     goto Finish; | ||||
| 
 | ||||
|   /* We are Ok to create the new matrix object */ | ||||
|   *mat = LUSOL_matcreate(LUSOL->n, LENU); | ||||
|   if(*mat == NULL) { | ||||
|     *inform = LUSOL_INFORM_NOMEMLEFT; | ||||
|     goto Finish; | ||||
|   } | ||||
| 
 | ||||
|   /* Cumulate row counts to get vector offsets; first column is leftmost
 | ||||
|      (stick with Fortran array offset for consistency) */ | ||||
|   (*mat)->lenx[0] = 1; | ||||
|   for(K = 1; K <= LUSOL->n; K++) { | ||||
|     (*mat)->lenx[K] = (*mat)->lenx[K-1] + lsumc[K]; | ||||
|     lsumc[K] = (*mat)->lenx[K-1]; | ||||
|   } | ||||
| 
 | ||||
|   /* Map the matrix into column order by permuted index;
 | ||||
|      Note: The first permuted column is located leftmost in the array. | ||||
|            The row order is irrelevant, since the indeces will | ||||
|            refer to constant / resolved values of V[] during solve. */ | ||||
|   for(L = 1; L <= LENU; L++) { | ||||
|     J = LUSOL->indr[L]; | ||||
|     LL = lsumc[J]++; | ||||
|     (*mat)->a[LL] = LUSOL->a[L]; | ||||
|     (*mat)->indr[LL] = J; | ||||
|     (*mat)->indc[LL] = LUSOL->indc[L]; | ||||
|   } | ||||
| 
 | ||||
|   /* Pack column starting positions, and set mapper from original index to packed */ | ||||
|   J = 0; | ||||
|   for(L = 1; L <= LUSOL->n; L++) { | ||||
|     K = LUSOL->iq[L]; | ||||
| #if 1  /* Deactivate to produce a full-rank version (implicit unit diagonals) */ | ||||
|     if((*mat)->lenx[K] > (*mat)->lenx[K-1]) | ||||
| #endif | ||||
|     { | ||||
|       J++; | ||||
|      (*mat)->indx[J] = K; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /* Confirm that everything went well */ | ||||
|   status = TRUE; | ||||
| 
 | ||||
|   /* Clean up */ | ||||
| Finish: | ||||
|   FREE(lsumc); | ||||
|   return( status ); | ||||
| } | ||||
| 
 | ||||
| /* Solve U w = v based on column-based version of U, constructed by LU1U0 */ | ||||
| void LU6U0_v(LUSOLrec *LUSOL, LUSOLmat *mat, REAL V[], REAL W[], int NZidx[], int *INFORM) | ||||
| { | ||||
| #ifdef DoTraceU0 | ||||
|   REAL TEMP; | ||||
| #endif | ||||
|   int  LEN, I, K, L, L1, NRANK, NRANK1, KLAST; | ||||
|   REAL SMALL; | ||||
|   register REAL T; | ||||
| #if (defined xxLUSOLFastSolve) && !(defined DoTraceU0) | ||||
|   REAL *aptr; | ||||
|   int  *jptr; | ||||
| #else | ||||
|   int  J; | ||||
| #endif | ||||
| 
 | ||||
|   NRANK = LUSOL->luparm[LUSOL_IP_RANK_U]; | ||||
|   SMALL = LUSOL->parmlu[LUSOL_RP_ZEROTOLERANCE]; | ||||
|   *INFORM = LUSOL_INFORM_LUSUCCESS; | ||||
|   NRANK1 = NRANK+1; | ||||
| /*      Find the first nonzero in v(1:nrank), counting backwards. */ | ||||
|   for(KLAST = NRANK; KLAST >= 1; KLAST--) { | ||||
|     I = LUSOL->ip[KLAST]; | ||||
|     if(fabs(V[I])>SMALL) | ||||
|       break; | ||||
|   } | ||||
|   L = LUSOL->n; | ||||
| #ifdef xxLUSOLFastSolve | ||||
|   for(K = KLAST+1, jptr = LUSOL->iq+K; K <= L; K++, jptr++) | ||||
|     W[*jptr] = ZERO; | ||||
| #else | ||||
|   for(K = KLAST+1; K <= L; K++) { | ||||
|     J = LUSOL->iq[K]; | ||||
|     W[J] = ZERO; | ||||
|   } | ||||
| #endif | ||||
|   /* Loop over the nz columns of U - from the right, going left. */ | ||||
|   for(K = NRANK; K > 0; K--) { | ||||
|     I = mat->indx[K]; | ||||
|     L = mat->lenx[I]; | ||||
|     L1 = mat->lenx[I-1]; | ||||
|     LEN = L - L1; | ||||
|     T = V[I]; | ||||
|     if(fabs(T)<=SMALL) { | ||||
|       W[K] = ZERO; | ||||
|       continue; | ||||
|     } | ||||
|     T /= mat->a[L1];  /* Should it be L or L1 ? */ | ||||
|     W[K] = T; | ||||
|     LEN--; | ||||
| /*     ***** This loop could be coded specially. */ | ||||
| #ifdef xxLUSOLFastSolve | ||||
|     L--; | ||||
|     for(aptr = mat->a+L, jptr = mat->indc+L; | ||||
|         LEN > 0; LEN--, aptr--, jptr--) | ||||
|       V[*jptr] -= T * (*aptr); | ||||
| #else | ||||
|     for(; LEN > 0; LEN--) { | ||||
|       L--; | ||||
|       J = mat->indc[L]; | ||||
| #ifndef DoTraceL0 | ||||
|       V[J] -= T * mat->a[L]; | ||||
| #else | ||||
|       TEMP = V[J]; | ||||
|       V[J] += T * mat->a[L]; | ||||
|       printf("V[%3d] = V[%3d] + L[%d,%d]*V[%3d]\n", J, J, I,J, I); | ||||
|       printf("%6g = %6g + %6g*%6g\n", V[J], TEMP, mat->a[L], T); | ||||
| #endif | ||||
|     } | ||||
| #endif | ||||
|   } | ||||
| /*      Compute residual for overdetermined systems. */ | ||||
|   T = ZERO; | ||||
|   for(K = NRANK1; K <= LUSOL->m; K++) { | ||||
|     I = LUSOL->ip[K]; | ||||
|     T += fabs(V[I]); | ||||
|   } | ||||
| /*      Exit. */ | ||||
|   if(T>ZERO) | ||||
|     *INFORM = LUSOL_INFORM_LUSINGULAR; | ||||
|   LUSOL->luparm[LUSOL_IP_INFORM]     = *INFORM; | ||||
|   LUSOL->parmlu[LUSOL_RP_RESIDUAL_U] = (REAL) T; | ||||
| } | ||||
|  | @ -1,704 +0,0 @@ | |||
| 
 | ||||
| /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 | ||||
|    File  lusol7a | ||||
|       lu7add   lu7cyc   lu7elm   lu7for   lu7rnk   lu7zap | ||||
|       Utilities for LUSOL's update routines. | ||||
|       lu7for is the most important -- the forward sweep. | ||||
|   01 May 2002: Derived from LUSOL's original lu7a.f file. | ||||
|   01 May 2002: Current version of lusol7a.f. | ||||
|    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ | ||||
| 
 | ||||
| /* ==================================================================
 | ||||
|    lu7add  inserts the first nrank elements of the vector v(*) | ||||
|    as column  jadd  of  U.  We assume that  U  does not yet have any | ||||
|    entries in this column. | ||||
|    Elements no larger than  parmlu(3)  are treated as zero. | ||||
|    klast  will be set so that the last row to be affected | ||||
|    (in pivotal order) is row  ip(klast). | ||||
|    ------------------------------------------------------------------ | ||||
|    09 May 1988: First f77 version. | ||||
|    ================================================================== */ | ||||
| void LU7ADD(LUSOLrec *LUSOL, int JADD, REAL V[], int LENL, int *LENU, | ||||
|   int *LROW, int NRANK, int *INFORM, int *KLAST, REAL *VNORM) | ||||
| { | ||||
|   REAL SMALL; | ||||
|   int  K, I, LENI, MINFRE, NFREE, LR1, LR2, L; | ||||
| #ifndef LUSOLFastMove | ||||
|   int J; | ||||
| #endif | ||||
| 
 | ||||
|   SMALL = LUSOL->parmlu[LUSOL_RP_ZEROTOLERANCE]; | ||||
|   *VNORM = ZERO; | ||||
|   *KLAST = 0; | ||||
|   for(K = 1; K <= NRANK; K++) { | ||||
|     I = LUSOL->ip[K]; | ||||
|     if(fabs(V[I])<=SMALL) | ||||
|       continue; | ||||
|     *KLAST = K; | ||||
|     (*VNORM) += fabs(V[I]); | ||||
|     LENI = LUSOL->lenr[I]; | ||||
| /*         Compress row file if necessary. */ | ||||
|     MINFRE = LENI+1; | ||||
|     NFREE = LUSOL->lena - LENL - *LROW; | ||||
|     if(NFREE<MINFRE) { | ||||
|       LU1REC(LUSOL, LUSOL->m, TRUE,LROW,LUSOL->indr,LUSOL->lenr,LUSOL->locr); | ||||
|       NFREE = LUSOL->lena - LENL - *LROW; | ||||
|       if(NFREE<MINFRE) | ||||
|         goto x970; | ||||
|     } | ||||
| /*         Move row  i  to the end of the row file,
 | ||||
|            unless it is already there. | ||||
|            No need to move if there is a gap already. */ | ||||
|     if(LENI==0) | ||||
|       LUSOL->locr[I] = (*LROW) + 1; | ||||
|     LR1 = LUSOL->locr[I]; | ||||
|     LR2 = (LR1+LENI)-1; | ||||
|     if(LR2==*LROW) | ||||
|       goto x150; | ||||
|     if(LUSOL->indr[LR2+1]==0) | ||||
|       goto x180; | ||||
|     LUSOL->locr[I] = (*LROW) + 1; | ||||
| #ifdef LUSOLFastMove | ||||
|     L = LR2-LR1+1; | ||||
|     if(L > 0) { | ||||
|       LR2 = (*LROW)+1; | ||||
|       MEMMOVE(LUSOL->a+LR2,    LUSOL->a+LR1, L); | ||||
|       MEMMOVE(LUSOL->indr+LR2, LUSOL->indr+LR1, L); | ||||
|       MEMCLEAR(LUSOL->indr+LR1, L); | ||||
|       *LROW += L; | ||||
|     } | ||||
| #else | ||||
|     for(L = LR1; L <= LR2; L++) { | ||||
|       (*LROW)++; | ||||
|       LUSOL->a[*LROW] = LUSOL->a[L]; | ||||
|       J = LUSOL->indr[L]; | ||||
|       LUSOL->indr[L] = 0; | ||||
|       LUSOL->indr[*LROW] = J; | ||||
|     } | ||||
| #endif | ||||
| x150: | ||||
|     LR2 = *LROW; | ||||
|     (*LROW)++; | ||||
| /*         Add the element of  v. */ | ||||
| x180: | ||||
|     LR2++; | ||||
|     LUSOL->a[LR2] = V[I]; | ||||
|     LUSOL->indr[LR2] = JADD; | ||||
|     LUSOL->lenr[I] = LENI+1; | ||||
|     (*LENU)++; | ||||
|   } | ||||
| /*      Normal exit. */ | ||||
|   *INFORM = LUSOL_INFORM_LUSUCCESS; | ||||
|   goto x990; | ||||
| /*      Not enough storage. */ | ||||
| x970: | ||||
|   *INFORM = LUSOL_INFORM_ANEEDMEM; | ||||
| x990: | ||||
| ; | ||||
| } | ||||
| 
 | ||||
| /* ==================================================================
 | ||||
|    lu7cyc performs a cyclic permutation on the row or column ordering | ||||
|    stored in ip, moving entry kfirst down to klast. | ||||
|    If kfirst .ge. klast, lu7cyc should not be called. | ||||
|    Sometimes klast = 0 and nothing should happen. | ||||
|    ------------------------------------------------------------------ | ||||
|    09 May 1988: First f77 version. | ||||
|    ================================================================== */ | ||||
| void LU7CYC(LUSOLrec *LUSOL, int KFIRST, int KLAST, int IX[]) | ||||
| { | ||||
|   if(KFIRST<KLAST) { | ||||
|     int IFIRST, K; | ||||
| #ifdef LUSOLFastMove | ||||
| #if 1 | ||||
|     IFIRST = IX[KFIRST]; | ||||
|     K = KLAST-KFIRST; | ||||
|     MEMMOVE(IX+KFIRST, IX+KFIRST+1, K); | ||||
|     IX[KLAST] = IFIRST; | ||||
| #else | ||||
|     int *IXK, *IXK1; | ||||
|     IXK = IX+KFIRST; | ||||
|     IFIRST = *IXK; | ||||
|     for(K = KFIRST, IXK1 = IXK+1; K <= KLAST-1; K++, IXK++, IXK1++) { | ||||
|       *IXK = *IXK1; | ||||
|     } | ||||
|     *IXK = IFIRST; | ||||
| #endif | ||||
| #else | ||||
|     IFIRST = IX[KFIRST]; | ||||
|     for(K = KFIRST; K <= KLAST-1; K++) { | ||||
|       IX[K] = IX[K+1]; | ||||
|     } | ||||
|     IX[KLAST] = IFIRST; | ||||
| #endif | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /* ==================================================================
 | ||||
|    lu7elm  eliminates the subdiagonal elements of a vector  v(*), | ||||
|    where  L*v = y  for some vector y. | ||||
|    If  jelm > 0,  y  has just become column  jelm  of the matrix  A. | ||||
|    lu7elm  should not be called unless  m  is greater than  nrank. | ||||
|    inform = 0 if y contained no subdiagonal nonzeros to eliminate. | ||||
|    inform = 1 if y contained at least one nontrivial subdiagonal. | ||||
|    inform = 7 if there is insufficient storage. | ||||
|    ------------------------------------------------------------------ | ||||
|    09 May 1988: First f77 version. | ||||
|                 No longer calls lu7for at end.  lu8rpc, lu8mod do so. | ||||
|    ================================================================== */ | ||||
| void LU7ELM(LUSOLrec *LUSOL, int JELM, REAL V[], int *LENL, | ||||
|             int *LROW, int NRANK, int *INFORM, REAL *DIAG) | ||||
| { | ||||
|   REAL VI, VMAX, SMALL; | ||||
|   int  NRANK1, MINFRE, NFREE, KMAX, L, K, I, LMAX, IMAX, L1, L2; | ||||
| 
 | ||||
| #ifdef ForceInitialization | ||||
|   LMAX = 0; | ||||
| #endif | ||||
| 
 | ||||
|   SMALL = LUSOL->parmlu[LUSOL_RP_ZEROTOLERANCE]; | ||||
|   NRANK1 = NRANK+1; | ||||
|   *DIAG = ZERO; | ||||
| /*      Compress row file if necessary. */ | ||||
|   MINFRE = LUSOL->m-NRANK; | ||||
|   NFREE = LUSOL->lena-(*LENL)-(*LROW); | ||||
|   if(NFREE>=MINFRE) | ||||
|     goto x100; | ||||
|   LU1REC(LUSOL, LUSOL->m,TRUE,LROW,LUSOL->indr,LUSOL->lenr,LUSOL->locr); | ||||
|   NFREE = LUSOL->lena-(*LENL)-(*LROW); | ||||
|   if(NFREE<MINFRE) | ||||
|     goto x970; | ||||
|      | ||||
| /*      Pack the subdiagonals of  v  into  L,  and find the largest. */ | ||||
| x100: | ||||
|   VMAX = ZERO; | ||||
|   KMAX = 0; | ||||
|   L = (LUSOL->lena-(*LENL))+1; | ||||
|   for(K = NRANK1; K <= LUSOL->m; K++) { | ||||
|     I = LUSOL->ip[K]; | ||||
|     VI = fabs(V[I]); | ||||
|     if(VI<=SMALL) | ||||
|       continue; | ||||
|     L--; | ||||
|     LUSOL->a[L] = V[I]; | ||||
|     LUSOL->indc[L] = I; | ||||
|     if(VMAX>=VI) | ||||
|       continue; | ||||
|     VMAX = VI; | ||||
|     KMAX = K; | ||||
|     LMAX = L; | ||||
|   } | ||||
|   if(KMAX==0) | ||||
|     goto x900; | ||||
| /*      ------------------------------------------------------------------
 | ||||
|         Remove  vmax  by overwriting it with the last packed  v(i). | ||||
|         Then set the multipliers in  L  for the other elements. | ||||
|         ------------------------------------------------------------------ */ | ||||
|   IMAX = LUSOL->ip[KMAX]; | ||||
|   VMAX = LUSOL->a[LMAX]; | ||||
|   LUSOL->a[LMAX] = LUSOL->a[L]; | ||||
|   LUSOL->indc[LMAX] = LUSOL->indc[L]; | ||||
|   L1 = L+1; | ||||
|   L2 = LUSOL->lena-(*LENL); | ||||
|   *LENL = ((*LENL)+L2)-L; | ||||
|   for(L = L1; L <= L2; L++) { | ||||
|     LUSOL->a[L] /= -VMAX; | ||||
|     LUSOL->indr[L] = IMAX; | ||||
|   } | ||||
| /*      Move the row containing vmax to pivotal position nrank + 1. */ | ||||
|   LUSOL->ip[KMAX] = LUSOL->ip[NRANK1]; | ||||
|   LUSOL->ip[NRANK1] = IMAX; | ||||
|   *DIAG = VMAX; | ||||
| /*      ------------------------------------------------------------------
 | ||||
|         If jelm is positive, insert  vmax  into a new row of  U. | ||||
|         This is now the only subdiagonal element. | ||||
|         ------------------------------------------------------------------ */ | ||||
|   if(JELM>0) { | ||||
|     (*LROW)++; | ||||
|     LUSOL->locr[IMAX] = *LROW; | ||||
|     LUSOL->lenr[IMAX] = 1; | ||||
|     LUSOL->a[*LROW] = VMAX; | ||||
|     LUSOL->indr[*LROW] = JELM; | ||||
|   } | ||||
|   *INFORM = LUSOL_INFORM_LUSINGULAR; | ||||
|   goto x990; | ||||
| /*      No elements to eliminate. */ | ||||
| x900: | ||||
|   *INFORM = LUSOL_INFORM_LUSUCCESS; | ||||
|   goto x990; | ||||
| /*      Not enough storage. */ | ||||
| x970: | ||||
|   *INFORM = LUSOL_INFORM_ANEEDMEM; | ||||
| x990: | ||||
| ; | ||||
| } | ||||
| 
 | ||||
| /* ==================================================================
 | ||||
|    lu7for  (forward sweep) updates the LU factorization  A = L*U | ||||
|    when row  iw = ip(klast)  of  U  is eliminated by a forward | ||||
|    sweep of stabilized row operations, leaving  ip * U * iq  upper | ||||
|    triangular. | ||||
|    The row permutation  ip  is updated to preserve stability and/or | ||||
|    sparsity.  The column permutation  iq  is not altered. | ||||
|    kfirst  is such that row  ip(kfirst)  is the first row involved | ||||
|    in eliminating row  iw.  (Hence,  kfirst  marks the first nonzero | ||||
|    in row  iw  in pivotal order.)  If  kfirst  is unknown it may be | ||||
|    input as  1. | ||||
|    klast   is such that row  ip(klast)  is the row being eliminated. | ||||
|    klast   is not altered. | ||||
|    lu7for  should be called only if  kfirst .le. klast. | ||||
|    If  kfirst = klast,  there are no nonzeros to eliminate, but the | ||||
|    diagonal element of row  ip(klast)  may need to be moved to the | ||||
|    front of the row. | ||||
|    ------------------------------------------------------------------ | ||||
|    On entry,  locc(*)  must be zero. | ||||
| 
 | ||||
|    On exit: | ||||
|    inform = 0  if row iw has a nonzero diagonal (could be small). | ||||
|    inform = 1  if row iw has no diagonal. | ||||
|    inform = 7  if there is not enough storage to finish the update. | ||||
| 
 | ||||
|    On a successful exit (inform le 1),  locc(*)  will again be zero. | ||||
|    ------------------------------------------------------------------ | ||||
|       Jan 1985: Final f66 version. | ||||
|    09 May 1988: First f77 version. | ||||
|    ================================================================== */ | ||||
| void LU7FOR(LUSOLrec *LUSOL, int KFIRST, int KLAST, int *LENL, int *LENU, | ||||
|                      int *LROW, int *INFORM, REAL *DIAG) | ||||
| { | ||||
|   MYBOOL SWAPPD; | ||||
|   int    KBEGIN, IW, LENW, LW1, LW2, JFIRST, MINFRE, NFREE, L, J, KSTART, KSTOP, K, | ||||
|          LFIRST, IV, LENV, LV1, JLAST, LV2, LV3, LV, JV, LW, LDIAG, LIMIT; | ||||
|   REAL   AMULT, LTOL, USPACE, SMALL, VJ, WJ; | ||||
| 
 | ||||
|   LTOL   = LUSOL->parmlu[LUSOL_RP_UPDATEMAX_Lij]; | ||||
|   SMALL  = LUSOL->parmlu[LUSOL_RP_ZEROTOLERANCE]; | ||||
|   USPACE = LUSOL->parmlu[LUSOL_RP_COMPSPACE_U]; | ||||
|   KBEGIN = KFIRST; | ||||
|   SWAPPD = FALSE; | ||||
| 
 | ||||
| /*      We come back here from below if a row interchange is performed. */ | ||||
| x100: | ||||
|   IW = LUSOL->ip[KLAST]; | ||||
|   LENW = LUSOL->lenr[IW]; | ||||
|   if(LENW==0) | ||||
|     goto x910; | ||||
|   LW1 = LUSOL->locr[IW]; | ||||
|   LW2 = (LW1+LENW)-1; | ||||
|   JFIRST = LUSOL->iq[KBEGIN]; | ||||
|   if(KBEGIN>=KLAST) | ||||
|     goto x700; | ||||
| /*      Make sure there is room at the end of the row file
 | ||||
|         in case row  iw  is moved there and fills in completely. */ | ||||
|   MINFRE = LUSOL->n+1; | ||||
|   NFREE = LUSOL->lena-(*LENL)-(*LROW); | ||||
|   if(NFREE<MINFRE) { | ||||
|     LU1REC(LUSOL, LUSOL->m,TRUE,LROW,LUSOL->indr,LUSOL->lenr,LUSOL->locr); | ||||
|     LW1 = LUSOL->locr[IW]; | ||||
|     LW2 = (LW1+LENW)-1; | ||||
|     NFREE = LUSOL->lena-(*LENL)-(*LROW); | ||||
|     if(NFREE<MINFRE) | ||||
|       goto x970; | ||||
| 
 | ||||
|   } | ||||
| /*      Set markers on row  iw. */ | ||||
|   for(L = LW1; L <= LW2; L++) { | ||||
|     J = LUSOL->indr[L]; | ||||
|     LUSOL->locc[J] = L; | ||||
|   } | ||||
| /*      ==================================================================
 | ||||
|         Main elimination loop. | ||||
|         ================================================================== */ | ||||
|   KSTART = KBEGIN; | ||||
|   KSTOP = MIN(KLAST,LUSOL->n); | ||||
|   for(K = KSTART; K <= KSTOP; K++) { | ||||
|     JFIRST = LUSOL->iq[K]; | ||||
|     LFIRST = LUSOL->locc[JFIRST]; | ||||
|     if(LFIRST==0) | ||||
|       goto x490; | ||||
| /*         Row  iw  has its first element in column  jfirst. */ | ||||
|     WJ = LUSOL->a[LFIRST]; | ||||
|     if(K==KLAST) | ||||
|       goto x490; | ||||
| /*         ---------------------------------------------------------------
 | ||||
|            We are about to use the first element of row  iv | ||||
|                   to eliminate the first element of row  iw. | ||||
|            However, we may wish to interchange the rows instead, | ||||
|            to preserve stability and/or sparsity. | ||||
|            --------------------------------------------------------------- */ | ||||
|     IV = LUSOL->ip[K]; | ||||
|     LENV = LUSOL->lenr[IV]; | ||||
|     LV1 = LUSOL->locr[IV]; | ||||
|     VJ = ZERO; | ||||
|     if(LENV==0) | ||||
|       goto x150; | ||||
|     if(LUSOL->indr[LV1]!=JFIRST) | ||||
|       goto x150; | ||||
|     VJ = LUSOL->a[LV1]; | ||||
|     if(SWAPPD) | ||||
|       goto x200; | ||||
|     if(LTOL*fabs(WJ)<fabs(VJ)) | ||||
|       goto x200; | ||||
|     if(LTOL*fabs(VJ)<fabs(WJ)) | ||||
|       goto x150; | ||||
|     if(LENV<=LENW) | ||||
|       goto x200; | ||||
| /*         ---------------------------------------------------------------
 | ||||
|            Interchange rows  iv  and  iw. | ||||
|            --------------------------------------------------------------- */ | ||||
| x150: | ||||
|     LUSOL->ip[KLAST] = IV; | ||||
|     LUSOL->ip[K] = IW; | ||||
|     KBEGIN = K; | ||||
|     SWAPPD = TRUE; | ||||
|     goto x600; | ||||
| /*         ---------------------------------------------------------------
 | ||||
|            Delete the eliminated element from row  iw | ||||
|            by overwriting it with the last element. | ||||
|            --------------------------------------------------------------- */ | ||||
| x200: | ||||
|     LUSOL->a[LFIRST] = LUSOL->a[LW2]; | ||||
|     JLAST = LUSOL->indr[LW2]; | ||||
|     LUSOL->indr[LFIRST] = JLAST; | ||||
|     LUSOL->indr[LW2] = 0; | ||||
|     LUSOL->locc[JLAST] = LFIRST; | ||||
|     LUSOL->locc[JFIRST] = 0; | ||||
|     LENW--; | ||||
|     (*LENU)--; | ||||
|     if(*LROW==LW2) | ||||
|       (*LROW)--; | ||||
|     LW2 = LW2-1; | ||||
| /*         ---------------------------------------------------------------
 | ||||
|            Form the multiplier and store it in the  L  file. | ||||
|            --------------------------------------------------------------- */ | ||||
|     if(fabs(WJ)<=SMALL) | ||||
|       goto x490; | ||||
|     AMULT = -WJ/VJ; | ||||
|     L = LUSOL->lena-(*LENL); | ||||
|     LUSOL->a[L] = AMULT; | ||||
|     LUSOL->indr[L] = IV; | ||||
|     LUSOL->indc[L] = IW; | ||||
|     (*LENL)++; | ||||
| /*         ---------------------------------------------------------------
 | ||||
|            Add the appropriate multiple of row  iv  to row  iw. | ||||
|            We use two different inner loops.  The first one is for the | ||||
|            case where row  iw  is not at the end of storage. | ||||
|            --------------------------------------------------------------- */ | ||||
|     if(LENV==1) | ||||
|       goto x490; | ||||
|     LV2 = LV1+1; | ||||
|     LV3 = (LV1+LENV)-1; | ||||
|     if(LW2==*LROW) | ||||
|       goto x400; | ||||
| /*         ...............................................................
 | ||||
|            This inner loop will be interrupted only if | ||||
|            fill-in occurs enough to bump into the next row. | ||||
|            ............................................................... */ | ||||
|     for(LV = LV2; LV <= LV3; LV++) { | ||||
|       JV = LUSOL->indr[LV]; | ||||
|       LW = LUSOL->locc[JV]; | ||||
|       if(LW>0) { | ||||
| /*               No fill-in. */ | ||||
|         LUSOL->a[LW] += AMULT*LUSOL->a[LV]; | ||||
|         if(fabs(LUSOL->a[LW])<=SMALL) { | ||||
| /*                  Delete small computed element. */ | ||||
|           LUSOL->a[LW] = LUSOL->a[LW2]; | ||||
|           J = LUSOL->indr[LW2]; | ||||
|           LUSOL->indr[LW] = J; | ||||
|           LUSOL->indr[LW2] = 0; | ||||
|           LUSOL->locc[J] = LW; | ||||
|           LUSOL->locc[JV] = 0; | ||||
|           (*LENU)--; | ||||
|           LENW--; | ||||
|           LW2--; | ||||
|         } | ||||
|       } | ||||
|       else { | ||||
| /*               Row  iw  doesn't have an element in column  jv  yet
 | ||||
|                  so there is a fill-in. */ | ||||
|         if(LUSOL->indr[LW2+1]!=0) | ||||
|           goto x360; | ||||
|         (*LENU)++; | ||||
|         LENW++; | ||||
|         LW2++; | ||||
|         LUSOL->a[LW2] = AMULT*LUSOL->a[LV]; | ||||
|         LUSOL->indr[LW2] = JV; | ||||
|         LUSOL->locc[JV] = LW2; | ||||
|       } | ||||
|     } | ||||
|     goto x490; | ||||
| /*         Fill-in interrupted the previous loop.
 | ||||
|            Move row  iw  to the end of the row file. */ | ||||
| x360: | ||||
|     LV2 = LV; | ||||
|     LUSOL->locr[IW] = (*LROW)+1; | ||||
| 
 | ||||
| #ifdef LUSOLFastMove | ||||
|     L = LW2-LW1+1; | ||||
|     if(L > 0) { | ||||
|       int loci, *locp; | ||||
|       for(loci = LW1, locp = LUSOL->indr+LW1; | ||||
|           loci <= LW2; loci++, locp++) { | ||||
|         (*LROW)++; | ||||
|         LUSOL->locc[*locp] = *LROW; | ||||
|       } | ||||
|       LW2 = (*LROW)-L+1; | ||||
|       MEMMOVE(LUSOL->a+LW2,    LUSOL->a+LW1, L); | ||||
|       MEMMOVE(LUSOL->indr+LW2, LUSOL->indr+LW1, L); | ||||
|       MEMCLEAR(LUSOL->indr+LW1, L); | ||||
|     } | ||||
| #else | ||||
|     for(L = LW1; L <= LW2; L++) { | ||||
|       (*LROW)++; | ||||
|       LUSOL->a[*LROW] = LUSOL->a[L]; | ||||
|       J = LUSOL->indr[L]; | ||||
|       LUSOL->indr[L] = 0; | ||||
|       LUSOL->indr[*LROW] = J; | ||||
|       LUSOL->locc[J] = *LROW; | ||||
|     } | ||||
| #endif | ||||
|     LW1 = LUSOL->locr[IW]; | ||||
|     LW2 = *LROW; | ||||
| /*         ...............................................................
 | ||||
|            Inner loop with row  iw  at the end of storage. | ||||
|            ............................................................... */ | ||||
| x400: | ||||
|     for(LV = LV2; LV <= LV3; LV++) { | ||||
|       JV = LUSOL->indr[LV]; | ||||
|       LW = LUSOL->locc[JV]; | ||||
|       if(LW>0) { | ||||
| /*               No fill-in. */ | ||||
|         LUSOL->a[LW] += AMULT*LUSOL->a[LV]; | ||||
|         if(fabs(LUSOL->a[LW])<=SMALL) { | ||||
| /*                  Delete small computed element. */ | ||||
|           LUSOL->a[LW] = LUSOL->a[LW2]; | ||||
|           J = LUSOL->indr[LW2]; | ||||
|           LUSOL->indr[LW] = J; | ||||
|           LUSOL->indr[LW2] = 0; | ||||
|           LUSOL->locc[J] = LW; | ||||
|           LUSOL->locc[JV] = 0; | ||||
|           (*LENU)--; | ||||
|           LENW--; | ||||
|           LW2--; | ||||
|         } | ||||
|       } | ||||
|       else { | ||||
| /*               Row  iw  doesn't have an element in column  jv  yet
 | ||||
|                  so there is a fill-in. */ | ||||
|         (*LENU)++; | ||||
|         LENW++; | ||||
|         LW2++; | ||||
|         LUSOL->a[LW2] = AMULT*LUSOL->a[LV]; | ||||
|         LUSOL->indr[LW2] = JV; | ||||
|         LUSOL->locc[JV] = LW2; | ||||
|       } | ||||
|     } | ||||
|     *LROW = LW2; | ||||
| /*         The  k-th  element of row  iw  has been processed.
 | ||||
|            Reset  swappd  before looking at the next element. */ | ||||
| x490: | ||||
|     SWAPPD = FALSE; | ||||
|   } | ||||
| /*      ==================================================================
 | ||||
|         End of main elimination loop. | ||||
|         ================================================================== | ||||
| 
 | ||||
|         Cancel markers on row  iw. */ | ||||
| x600: | ||||
|   LUSOL->lenr[IW] = LENW; | ||||
|   if(LENW==0) | ||||
|     goto x910; | ||||
|   for(L = LW1; L <= LW2; L++) { | ||||
|     J = LUSOL->indr[L]; | ||||
|     LUSOL->locc[J] = 0; | ||||
|   } | ||||
| /*      Move the diagonal element to the front of row  iw.
 | ||||
|         At this stage,  lenw gt 0  and  klast le n. */ | ||||
| x700: | ||||
|   for(L = LW1; L <= LW2; L++) { | ||||
|     LDIAG = L; | ||||
|     if(LUSOL->indr[L]==JFIRST) | ||||
|       goto x730; | ||||
|   } | ||||
|   goto x910; | ||||
| 
 | ||||
| x730: | ||||
|   *DIAG = LUSOL->a[LDIAG]; | ||||
|   LUSOL->a[LDIAG] = LUSOL->a[LW1]; | ||||
|   LUSOL->a[LW1] = *DIAG; | ||||
|   LUSOL->indr[LDIAG] = LUSOL->indr[LW1]; | ||||
|   LUSOL->indr[LW1] = JFIRST; | ||||
| /*      If an interchange is needed, repeat from the beginning with the
 | ||||
|         new row  iw,  knowing that the opposite interchange cannot occur. */ | ||||
|   if(SWAPPD) | ||||
|     goto x100; | ||||
|   *INFORM = LUSOL_INFORM_LUSUCCESS; | ||||
|   goto x950; | ||||
| /*      Singular. */ | ||||
| x910: | ||||
|   *DIAG = ZERO; | ||||
|   *INFORM = LUSOL_INFORM_LUSINGULAR; | ||||
| /*      Force a compression if the file for  U  is much longer than the
 | ||||
|         no. of nonzeros in  U  (i.e. if  lrow  is much bigger than  lenU). | ||||
|         This should prevent memory fragmentation when there is far more | ||||
|         memory than necessary  (i.e. when  lena  is huge). */ | ||||
| x950: | ||||
|   LIMIT = (int) (USPACE*(*LENU))+LUSOL->m+LUSOL->n+1000; | ||||
|   if(*LROW>LIMIT) | ||||
|     LU1REC(LUSOL, LUSOL->m,TRUE,LROW,LUSOL->indr,LUSOL->lenr,LUSOL->locr); | ||||
|   goto x990; | ||||
| /*      Not enough storage. */ | ||||
| x970: | ||||
|   *INFORM = LUSOL_INFORM_ANEEDMEM; | ||||
| /*      Exit. */ | ||||
| x990: | ||||
| ; | ||||
| } | ||||
| 
 | ||||
| /* ==================================================================
 | ||||
|    lu7rnk (check rank) assumes U is currently nrank by n | ||||
|    and determines if row nrank contains an acceptable pivot. | ||||
|    If not, the row is deleted and nrank is decreased by 1. | ||||
|    jsing is an input parameter (not altered).  If jsing is positive, | ||||
|    column jsing has already been judged dependent.  A substitute | ||||
|    (if any) must be some other column. | ||||
|    ------------------------------------------------------------------ | ||||
|    -- Jul 1987: First version. | ||||
|    09 May 1988: First f77 version. | ||||
|    ================================================================== */ | ||||
| void LU7RNK(LUSOLrec *LUSOL, int JSING, int *LENU, | ||||
|             int *LROW, int *NRANK, int *INFORM, REAL *DIAG) | ||||
| { | ||||
|   REAL UTOL1, UMAX; | ||||
|   int  IW, LENW, L1, L2, LMAX, L, JMAX, KMAX; | ||||
| 
 | ||||
| #ifdef ForceInitialization | ||||
|   L1 = 0; | ||||
|   L2 = 0; | ||||
| #endif | ||||
| 
 | ||||
|   UTOL1 = LUSOL->parmlu[LUSOL_RP_SMALLDIAG_U]; | ||||
|   *DIAG = ZERO; | ||||
| /*      Find Umax, the largest element in row nrank. */ | ||||
|   IW = LUSOL->ip[*NRANK]; | ||||
|   LENW = LUSOL->lenr[IW]; | ||||
|   if(LENW==0) | ||||
|     goto x400; | ||||
|   L1 = LUSOL->locr[IW]; | ||||
|   L2 = (L1+LENW)-1; | ||||
|   UMAX = ZERO; | ||||
|   LMAX = L1; | ||||
|   for(L = L1; L <= L2; L++) { | ||||
|     if(UMAX<fabs(LUSOL->a[L])) { | ||||
|       UMAX = fabs(LUSOL->a[L]); | ||||
|       LMAX = L; | ||||
|     } | ||||
|   } | ||||
| /*      Find which column that guy is in (in pivotal order).
 | ||||
|         Interchange him with column nrank, then move him to be | ||||
|         the new diagonal at the front of row nrank. */ | ||||
|   *DIAG = LUSOL->a[LMAX]; | ||||
|   JMAX = LUSOL->indr[LMAX]; | ||||
|   for(KMAX = *NRANK; KMAX <= LUSOL->n; KMAX++) { | ||||
|     if(LUSOL->iq[KMAX]==JMAX) | ||||
|       break; | ||||
|   } | ||||
|   LUSOL->iq[KMAX] = LUSOL->iq[*NRANK]; | ||||
|   LUSOL->iq[*NRANK] = JMAX; | ||||
|   LUSOL->a[LMAX] = LUSOL->a[L1]; | ||||
|   LUSOL->a[L1] = *DIAG; | ||||
|   LUSOL->indr[LMAX] = LUSOL->indr[L1]; | ||||
|   LUSOL->indr[L1] = JMAX; | ||||
| /*      See if the new diagonal is big enough. */ | ||||
|   if(UMAX<=UTOL1) | ||||
|     goto x400; | ||||
|   if(JMAX==JSING) | ||||
|     goto x400; | ||||
| /*      ------------------------------------------------------------------
 | ||||
|         The rank stays the same. | ||||
|         ------------------------------------------------------------------ */ | ||||
|   *INFORM = LUSOL_INFORM_LUSUCCESS; | ||||
|   return; | ||||
| /*      ------------------------------------------------------------------
 | ||||
|         The rank decreases by one. | ||||
|         ------------------------------------------------------------------ */ | ||||
| x400: | ||||
|   *INFORM = LUSOL_INFORM_RANKLOSS; | ||||
|   (*NRANK)--; | ||||
|   if(LENW>0) { | ||||
| /*         Delete row nrank from U. */ | ||||
|     LENU = LENU-LENW; | ||||
|     LUSOL->lenr[IW] = 0; | ||||
|     for(L = L1; L <= L2; L++) { | ||||
|       LUSOL->indr[L] = 0; | ||||
|     } | ||||
|     if(L2==*LROW) { | ||||
| /*            This row was at the end of the data structure.
 | ||||
|               We have to reset lrow. | ||||
|               Preceding rows might already have been deleted, so we | ||||
|               have to be prepared to go all the way back to 1. */ | ||||
|       for(L = 1; L <= L2; L++) { | ||||
|         if(LUSOL->indr[*LROW]>0) | ||||
|           goto x900; | ||||
|         (*LROW)--; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| x900: | ||||
| ; | ||||
| } | ||||
| 
 | ||||
| /* ==================================================================
 | ||||
|    lu7zap  eliminates all nonzeros in column  jzap  of  U. | ||||
|    It also sets  kzap  to the position of  jzap  in pivotal order. | ||||
|    Thus, on exit we have  iq(kzap) = jzap. | ||||
|    ------------------------------------------------------------------ | ||||
|    -- Jul 1987: nrank added. | ||||
|    10 May 1988: First f77 version. | ||||
|    ================================================================== */ | ||||
| void LU7ZAP(LUSOLrec *LUSOL, int JZAP, int *KZAP, int *LENU, int *LROW, | ||||
|             int NRANK) | ||||
| { | ||||
|   int K, I, LENI, LR1, LR2, L; | ||||
| 
 | ||||
|   for(K = 1; K <= NRANK; K++) { | ||||
|     I = LUSOL->ip[K]; | ||||
|     LENI = LUSOL->lenr[I]; | ||||
|     if(LENI==0) | ||||
|       goto x90; | ||||
|     LR1 = LUSOL->locr[I]; | ||||
|     LR2 = (LR1+LENI)-1; | ||||
|     for(L = LR1; L <= LR2; L++) { | ||||
|       if(LUSOL->indr[L]==JZAP) | ||||
|         goto x60; | ||||
|     } | ||||
|     goto x90; | ||||
| /*         Delete the old element. */ | ||||
| x60: | ||||
|     LUSOL->a[L] = LUSOL->a[LR2]; | ||||
|     LUSOL->indr[L] = LUSOL->indr[LR2]; | ||||
|     LUSOL->indr[LR2] = 0; | ||||
|     LUSOL->lenr[I] = LENI-1; | ||||
|     (*LENU)--; | ||||
| /*         Stop if we know there are no more rows containing  jzap. */ | ||||
| x90: | ||||
|     *KZAP = K; | ||||
|     if(LUSOL->iq[K]==JZAP) | ||||
|       goto x800; | ||||
|   } | ||||
| /*      nrank must be smaller than n because we haven't found kzap yet. */ | ||||
|   L = LUSOL->n; | ||||
|   for(K = NRANK+1; K <= L; K++) { | ||||
|     *KZAP = K; | ||||
|     if(LUSOL->iq[K]==JZAP) | ||||
|       break; | ||||
|   } | ||||
| /*      See if we zapped the last element in the file. */ | ||||
| x800: | ||||
|   if(*LROW>0) { | ||||
|     if(LUSOL->indr[*LROW]==0) | ||||
|       (*LROW)--; | ||||
|   } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
|  | @ -1,279 +0,0 @@ | |||
| 
 | ||||
| /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 | ||||
|    File  lusol8a | ||||
|       lu8rpc | ||||
|       Sparse LU update: Replace Column | ||||
|       LUSOL's sparse implementation of the Bartels-Golub update. | ||||
| 
 | ||||
|    01 May 2002: Derived from LUSOL's original lu8a.f file. | ||||
|    01 May 2002: Current version of lusol8a.f. | ||||
|    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ | ||||
| 
 | ||||
| /* ==================================================================
 | ||||
|    lu8rpc  updates the LU factorization  A = L*U  when column  jrep | ||||
|    is replaced by some vector  a(new). | ||||
|    lu8rpc  is an implementation of the Bartels-Golub update, | ||||
|    designed for the case where A is rectangular and/or singular. | ||||
|    L is a product of stabilized eliminations (m x m, nonsingular). | ||||
|    P U Q is upper trapezoidal (m x n, rank nrank). | ||||
| 
 | ||||
|    If  mode1 = 0,  the old column is taken to be zero | ||||
|                    (so it does not have to be removed from  U). | ||||
|    If  mode1 = 1,  the old column need not have been zero. | ||||
|    If  mode2 = 0,  the new column is taken to be zero. | ||||
|                    v(*)  is not used or altered. | ||||
|    If  mode2 = 1,  v(*)  must contain the new column  a(new). | ||||
|                    On exit,  v(*)  will satisfy  L*v = a(new). | ||||
|    If  mode2 = 2,  v(*)  must satisfy  L*v = a(new). | ||||
| 
 | ||||
|    The array  w(*)  is not used or altered. | ||||
|    On entry, all elements of  locc  are assumed to be zero. | ||||
|    On a successful exit (inform != 7), this will again be true. | ||||
|    On exit: | ||||
| 
 | ||||
|    inform = -1  if the rank of U decreased by 1. | ||||
|    inform =  0  if the rank of U stayed the same. | ||||
|    inform =  1  if the rank of U increased by 1. | ||||
|    inform =  2  if the update seemed to be unstable | ||||
|                 (diag much bigger than vnorm). | ||||
|    inform =  7  if the update was not completed (lack of storage). | ||||
|    inform =  8  if jrep is not between 1 and n. | ||||
|    ------------------------------------------------------------------ | ||||
|    -- Jan 1985: Original F66 version. | ||||
|    -- Jul 1987: Modified to maintain U in trapezoidal form. | ||||
|    10 May 1988: First f77 version. | ||||
|    16 Oct 2000: Added test for instability (inform = 2). | ||||
|    ================================================================== */ | ||||
| void LU8RPC(LUSOLrec *LUSOL, int MODE1, int MODE2, | ||||
|             int JREP, REAL V[], REAL W[], | ||||
|             int *INFORM, REAL *DIAG, REAL *VNORM) | ||||
| { | ||||
|   MYBOOL SINGLR; | ||||
|   int    LPRINT, NRANK, LENL, LENU, LROW, NRANK0, KREP, KLAST, IW, L1, J1, JSING; | ||||
|   REAL   UTOL1, UTOL2; | ||||
| 
 | ||||
|   LPRINT = LUSOL->luparm[LUSOL_IP_PRINTLEVEL]; | ||||
|   NRANK  = LUSOL->luparm[LUSOL_IP_RANK_U]; | ||||
|   LENL   = LUSOL->luparm[LUSOL_IP_NONZEROS_L]; | ||||
|   LENU   = LUSOL->luparm[LUSOL_IP_NONZEROS_U]; | ||||
|   LROW   = LUSOL->luparm[LUSOL_IP_NONZEROS_ROW]; | ||||
|   UTOL1  = LUSOL->parmlu[LUSOL_RP_SMALLDIAG_U]; | ||||
|   UTOL2  = LUSOL->parmlu[LUSOL_RP_EPSDIAG_U]; | ||||
|   NRANK0 = NRANK; | ||||
|   *DIAG  = ZERO; | ||||
|   *VNORM = ZERO; | ||||
|   if(JREP<1) | ||||
|     goto x980; | ||||
|   if(JREP>LUSOL->n) | ||||
|     goto x980; | ||||
| 
 | ||||
| /*      ------------------------------------------------------------------
 | ||||
|         If mode1 = 0, there are no elements to be removed from  U | ||||
|         but we still have to set  krep  (using a backward loop). | ||||
|         Otherwise, use lu7zap to remove column  jrep  from  U | ||||
|         and set  krep  at the same time. | ||||
|         ------------------------------------------------------------------ */ | ||||
|   if(MODE1==LUSOL_UPDATE_OLDEMPTY) { | ||||
|     KREP = LUSOL->n+1; | ||||
| x10: | ||||
|     KREP--; | ||||
|     if(LUSOL->iq[KREP]!=JREP) | ||||
|       goto x10; | ||||
|   } | ||||
|   else | ||||
|     LU7ZAP(LUSOL, JREP,&KREP,&LENU,&LROW,NRANK); | ||||
| 
 | ||||
| /*      ------------------------------------------------------------------
 | ||||
|         Insert a new column of u and find klast. | ||||
|         ------------------------------------------------------------------ */ | ||||
|   if(MODE2==LUSOL_UPDATE_NEWEMPTY) { | ||||
|     KLAST = 0; | ||||
|   } | ||||
|   else { | ||||
|     if(MODE2==LUSOL_UPDATE_NEWNONEMPTY) { | ||||
| /*            Transform v = a(new) to satisfy  L*v = a(new). */ | ||||
|       LU6SOL(LUSOL, LUSOL_SOLVE_Lv_v, V,W, NULL, INFORM); | ||||
|     } | ||||
|     else if(V==NULL) | ||||
| /* Otherwise, the V vector is taken to satisfy this already, or stored earlier. */ | ||||
|       V=LUSOL->vLU6L; | ||||
|        | ||||
| 
 | ||||
| /*         Insert into  U  any nonzeros in the top of  v.
 | ||||
|            row  ip(klast)  will contain the last nonzero in pivotal order. | ||||
|            Note that  klast  will be in the range  ( 0, nrank ). */ | ||||
|     LU7ADD(LUSOL, JREP,V,LENL,&LENU,&LROW,NRANK,INFORM,&KLAST,VNORM); | ||||
|     if(*INFORM==LUSOL_INFORM_ANEEDMEM) | ||||
|       goto x970; | ||||
|   } | ||||
| /*      ------------------------------------------------------------------
 | ||||
|         In general, the new column causes U to look like this: | ||||
|                     krep        n                 krep  n | ||||
|                    ....a.........          ..........a... | ||||
|                     .  a        .           .        a  . | ||||
|                      . a        .            .       a  . | ||||
|                       .a        .             .      a  . | ||||
|            P U Q =     a        .    or        .     a  . | ||||
|                        b.       .               .    a  . | ||||
|                        b .      .                .   a  . | ||||
|                        b  .     .                 .  a  . | ||||
|                        b   ......                  ..a...  nrank | ||||
|                        c                             c | ||||
|                        c                             c | ||||
|                        c                             c     m | ||||
|         klast points to the last nonzero "a" or "b". | ||||
|         klast = 0 means all "a" and "b" entries are zero. | ||||
|         ------------------------------------------------------------------ */ | ||||
|   if(MODE2==LUSOL_UPDATE_NEWEMPTY) { | ||||
|     if(KREP>NRANK) | ||||
|       goto x900; | ||||
|   } | ||||
|   else if(NRANK<LUSOL->m) { | ||||
| /*         Eliminate any "c"s (in either case).
 | ||||
|            Row nrank + 1 may end up containing one nonzero. */ | ||||
|     LU7ELM(LUSOL, JREP,V,&LENL,&LROW,NRANK,INFORM,DIAG); | ||||
|     if(*INFORM==LUSOL_INFORM_ANEEDMEM) | ||||
|       goto x970; | ||||
|     if(*INFORM==LUSOL_INFORM_LUSINGULAR) { | ||||
| /*            The nonzero is apparently significant.
 | ||||
|               Increase nrank by 1 and make klast point to the bottom. */ | ||||
|       NRANK++; | ||||
|       KLAST = NRANK; | ||||
|     } | ||||
|   } | ||||
|   if(NRANK<LUSOL->n) { | ||||
| /*         The column rank is low.
 | ||||
|            In the first case, we want the new column to end up in | ||||
|            position nrank, so the trapezoidal columns will have a chance | ||||
|            later on (in lu7rnk) to pivot in that position. | ||||
|            Otherwise the new column is not part of the triangle.  We | ||||
|            swap it into position nrank so we can judge it for singularity. | ||||
|            lu7rnk might choose some other trapezoidal column later. */ | ||||
|     if(KREP<NRANK) | ||||
|       KLAST = NRANK; | ||||
|     else { | ||||
|       LUSOL->iq[KREP] = LUSOL->iq[NRANK]; | ||||
|       LUSOL->iq[NRANK] = JREP; | ||||
|       KREP = NRANK; | ||||
|     } | ||||
|   } | ||||
| /*      ------------------------------------------------------------------
 | ||||
|         If krep .lt. klast, there are some "b"s to eliminate: | ||||
|                      krep | ||||
|                    ....a......... | ||||
|                     .  a        . | ||||
|                      . a        . | ||||
|                       .a        . | ||||
|            P U Q =     a        .  krep | ||||
|                        b.       . | ||||
|                        b .      . | ||||
|                        b  .     . | ||||
|                        b   ......  nrank | ||||
|         If krep .eq. klast, there are no "b"s, but the last "a" still | ||||
|         has to be moved to the front of row krep (by lu7for). | ||||
|         ------------------------------------------------------------------ */ | ||||
|   if(KREP<=KLAST) { | ||||
| /*         Perform a cyclic permutation on the current pivotal order,
 | ||||
|            and eliminate the resulting row spike.  krep becomes klast. | ||||
|            The final diagonal (if any) will be correctly positioned at | ||||
|            the front of the new krep-th row.  nrank stays the same. */ | ||||
|     LU7CYC(LUSOL, KREP,KLAST,LUSOL->ip); | ||||
|     LU7CYC(LUSOL, KREP,KLAST,LUSOL->iq); | ||||
|     LU7FOR(LUSOL, KREP,KLAST,&LENL,&LENU,&LROW,INFORM,DIAG); | ||||
|     if(*INFORM==LUSOL_INFORM_ANEEDMEM) | ||||
|       goto x970; | ||||
|     KREP = KLAST; | ||||
| /*         Test for instability (diag much bigger than vnorm). */ | ||||
|     SINGLR = (MYBOOL) ((*VNORM)<UTOL2*fabs(*DIAG)); | ||||
|     if(SINGLR) | ||||
|       goto x920; | ||||
|   } | ||||
| /*      ------------------------------------------------------------------
 | ||||
|         Test for singularity in column krep (where krep<=nrank). | ||||
|         ------------------------------------------------------------------ */ | ||||
|   *DIAG = ZERO; | ||||
|   IW = LUSOL->ip[KREP]; | ||||
|   SINGLR = (MYBOOL) (LUSOL->lenr[IW]==0); | ||||
|   if(!SINGLR) { | ||||
|     L1 = LUSOL->locr[IW]; | ||||
|     J1 = LUSOL->indr[L1]; | ||||
|     SINGLR = (MYBOOL) (J1!=JREP); | ||||
|     if(!SINGLR) { | ||||
|       *DIAG = LUSOL->a[L1]; | ||||
|       SINGLR = (MYBOOL) (fabs(*DIAG)<=UTOL1 || fabs(*DIAG)<=UTOL2*(*VNORM)); | ||||
|     } | ||||
|   } | ||||
|   if(SINGLR && (KREP<NRANK)) { | ||||
| /*         Perform cyclic permutations to move column jrep to the end.
 | ||||
|            Move the corresponding row to position nrank | ||||
|            then eliminate the resulting row spike. */ | ||||
|     LU7CYC(LUSOL, KREP,NRANK,LUSOL->ip); | ||||
|     LU7CYC(LUSOL, KREP,LUSOL->n,LUSOL->iq); | ||||
|     LU7FOR(LUSOL, KREP,NRANK,&LENL,&LENU,&LROW,INFORM,DIAG); | ||||
|     if(*INFORM==LUSOL_INFORM_ANEEDMEM) | ||||
|       goto x970; | ||||
|   } | ||||
| /*      Find the best column to be in position nrank.
 | ||||
|         If singlr, it can't be the new column, jrep. | ||||
|         If nothing satisfactory exists, nrank will be decreased. */ | ||||
|   if(SINGLR || (NRANK<LUSOL->n)) { | ||||
|     JSING = 0; | ||||
|     if(SINGLR) | ||||
|       JSING = JREP; | ||||
|     LU7RNK(LUSOL, JSING,&LENU,&LROW,&NRANK,INFORM,DIAG); | ||||
|   } | ||||
| 
 | ||||
| /*      ------------------------------------------------------------------
 | ||||
|         Update indeces of optional row-based version of L0. | ||||
|         ------------------------------------------------------------------ */ | ||||
| #if 0 | ||||
|   if(LUSOL->L0 != NULL) | ||||
|     LU1L0UPD(LUSOL, INFORM); | ||||
| #endif | ||||
| 
 | ||||
| /*      ------------------------------------------------------------------
 | ||||
|         Set inform for exit. | ||||
|         ------------------------------------------------------------------ */ | ||||
| x900: | ||||
|   if(NRANK==NRANK0) | ||||
|     *INFORM = LUSOL_INFORM_LUSUCCESS; | ||||
|   else if(NRANK<NRANK0) { | ||||
|     *INFORM = LUSOL_INFORM_RANKLOSS; | ||||
|     if(NRANK0==LUSOL->n) { | ||||
|       if(LPRINT>=LUSOL_MSG_SINGULARITY) | ||||
|         LUSOL_report(LUSOL, 0, "lu8rpc  warning...\nSingularity after replacing column.    jrep=%8d    diag=%g\n", | ||||
|                             JREP,DIAG); | ||||
|     } | ||||
|   } | ||||
|   else | ||||
|     *INFORM = LUSOL_INFORM_LUSINGULAR; | ||||
|   goto x990; | ||||
| /*      Instability. */ | ||||
| x920: | ||||
|   *INFORM = LUSOL_INFORM_LUUNSTABLE; | ||||
|   if(LPRINT>=LUSOL_MSG_SINGULARITY) | ||||
|     LUSOL_report(LUSOL, 0, "lu8rpc  warning...\nInstability after replacing column.    jrep=%8d    diag=%g\n", | ||||
|                         JREP,DIAG); | ||||
|   goto x990; | ||||
| /*      Not enough storage. */ | ||||
| x970: | ||||
|   *INFORM = LUSOL_INFORM_ANEEDMEM; | ||||
|   if(LPRINT>=LUSOL_MSG_SINGULARITY) | ||||
|     LUSOL_report(LUSOL, 0, "lu8rpc  error...\nInsufficient memory.    lena=%8d\n", | ||||
|                         LUSOL->lena); | ||||
|   goto x990; | ||||
| /*      jrep  is out of range. */ | ||||
| x980: | ||||
|   *INFORM = LUSOL_INFORM_FATALERR; | ||||
|   if(LPRINT>=LUSOL_MSG_SINGULARITY) | ||||
|     LUSOL_report(LUSOL, 0, "lu8rpc  error...\njrep  is out of range.    m=%8d    n=%8d    jrep=%8d\n", | ||||
|                         LUSOL->m,LUSOL->n,JREP); | ||||
| /*      Exit. */ | ||||
| x990: | ||||
|   LUSOL->luparm[LUSOL_IP_UPDATECOUNT]++; | ||||
|   LUSOL->luparm[LUSOL_IP_RANK_U]       = NRANK; | ||||
|   LUSOL->luparm[LUSOL_IP_NONZEROS_L]   = LENL; | ||||
|   LUSOL->luparm[LUSOL_IP_NONZEROS_U]   = LENU; | ||||
|   LUSOL->luparm[LUSOL_IP_NONZEROS_ROW] = LROW; | ||||
|   LUSOL->luparm[LUSOL_IP_INFORM]       = *INFORM; | ||||
| } | ||||
|  | @ -1,298 +0,0 @@ | |||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include "mmio.h" | ||||
| #include "hbio.h" | ||||
| #include "lusolio.h" | ||||
| 
 | ||||
| /* Utility routines to read matrix files in the Coordinate Text File format*/ | ||||
| 
 | ||||
| MYBOOL ctf_read_A(char *filename, int maxm, int maxn, int maxnz, | ||||
|                   int *m, int *n, int *nnzero, int *iA, int *jA, REAL *Aij) | ||||
| { | ||||
|   FILE *iofile; | ||||
|   int  eof; | ||||
|   char buffer[100]; | ||||
|   int  k, i, j; | ||||
|   REAL Ak; | ||||
|   MYBOOL filldata; | ||||
| 
 | ||||
|   *nnzero = 0; | ||||
|   *m      = 0; | ||||
|   *n      = 0; | ||||
| 
 | ||||
|   iofile = fopen(filename, "r" ); | ||||
|   if(iofile == NULL) { | ||||
|     printf("A file %s does not exist\n", filename); | ||||
|     return( FALSE ); | ||||
|   } | ||||
| 
 | ||||
|   filldata = (MYBOOL) !((iA == NULL) && (jA == NULL) && (Aij == NULL)); | ||||
|   eof = TRUE; | ||||
|   for (k = 1; k <= maxnz; k++) { | ||||
|     eof = feof(iofile); | ||||
|     if(eof) | ||||
|       break; | ||||
|     eof = fscanf(iofile, "%d %d %s", &i, &j, buffer); | ||||
|     if(eof == 0 || eof == EOF || i <= 0 || j <= 0 || strlen(buffer) == 0) | ||||
|       break; | ||||
|     Ak = atof(buffer); | ||||
|     (*nnzero)++; | ||||
|     if (filldata) { | ||||
|       iA[k]  = i; | ||||
|       jA[k]  = j; | ||||
|       Aij[k] = Ak; | ||||
|     } | ||||
|     if (i > *m) *m = i; | ||||
|     if (j > *n) *n = j; | ||||
|   } | ||||
|   fclose( iofile ); | ||||
|   if(!eof) { | ||||
|     printf("Too much data in A file.  Increase maxnz\n"); | ||||
|     printf("Current maxnz = %d\n", maxnz); | ||||
|     return( FALSE ); | ||||
|   } | ||||
|   printf("A  read successfully\n"); | ||||
|   printf("m      = %d   n      = %d   nnzero = %d\n", | ||||
|           *m, *n, *nnzero); | ||||
|   if (*m > maxm  ||  *n > maxn) { | ||||
|     printf("However, matrix dimensions exceed maxm or maxn\n"); | ||||
|     return( FALSE ); | ||||
|   } | ||||
|   return( TRUE ); | ||||
| } | ||||
| 
 | ||||
| MYBOOL ctf_size_A(char *filename, int *m, int *n, int *nnzero) | ||||
| { | ||||
|   int maxint = 200000000; | ||||
| 
 | ||||
|   return( ctf_read_A(filename, maxint, maxint, maxint, | ||||
|                      m, n, nnzero, NULL, NULL, NULL) ); | ||||
| } | ||||
| 
 | ||||
| MYBOOL ctf_read_b(char *filename, int m, REAL *b) | ||||
| { | ||||
|   FILE *iofile; | ||||
|   int  eof; | ||||
|   char buffer[100]; | ||||
|   int  i; | ||||
| 
 | ||||
|   iofile = fopen(filename, "r"); | ||||
|   if(iofile == NULL) { | ||||
|     printf("b file %s does not exist\n", filename); | ||||
|     return( FALSE ); | ||||
|   } | ||||
| 
 | ||||
|   for (i = 1; i <= m; i++) { | ||||
|     if(feof(iofile)) | ||||
|       goto x350; | ||||
|     eof = fscanf(iofile, "%s", buffer); | ||||
|     if(eof == 0 || eof == EOF) | ||||
|       goto x350; | ||||
|     b[i] = atof(buffer); | ||||
|   } | ||||
| 
 | ||||
|   fclose( iofile ); | ||||
|   printf("b  read successfully\n"); | ||||
|   return( TRUE ); | ||||
| 
 | ||||
| x350: | ||||
|   fclose( iofile ); | ||||
|   printf("Not enough data in b file.\n"); | ||||
|   return( FALSE ); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* Utility routines to read matrix files in the MatrixMarket format*/ | ||||
| #define mmf_recsize 255 | ||||
| MYBOOL mmf_read_A(char *filename, int maxM, int maxN, int maxnz, | ||||
|                   int *M, int *N, int *nz, int *iA, int *jA, REAL *Aij) | ||||
| { | ||||
|   MM_typecode matcode; | ||||
|   FILE   *f; | ||||
|   int    i, k, ret_code, ival, jval; | ||||
|   REAL   Aval; | ||||
|   MYBOOL status = FALSE, ispat, filldata; | ||||
|   char   buf[mmf_recsize]; | ||||
| 
 | ||||
|   f = fopen(filename, "r"); | ||||
|   if(f == NULL)  | ||||
|     return( status ); | ||||
| 
 | ||||
|   if(mm_read_banner(f, &matcode) != 0) { | ||||
|     printf("Could not process Matrix Market banner.\n"); | ||||
|     goto x900; | ||||
|   } | ||||
| 
 | ||||
|   /*  Screen matrix types since LUSOL only supports a 
 | ||||
|       subset of the Matrix Market data types. */ | ||||
|   if(mm_is_complex(matcode) || mm_is_pattern(matcode)) { | ||||
|     printf("Sorry, this application does not support "); | ||||
|     printf("Market Market type: [%s]\n", mm_typecode_to_str(matcode)); | ||||
|     goto x900; | ||||
|   } | ||||
| 
 | ||||
|   /* Verify that we have sufficient array storage */ | ||||
|   filldata = (MYBOOL) !((iA == NULL) && (jA == NULL) && (Aij == NULL)); | ||||
|   if(filldata && maxN > 1 && jA == NULL) { | ||||
|     printf("Market Market insufficient array storage specified\n"); | ||||
|     goto x900; | ||||
|   } | ||||
| 
 | ||||
|   /* Find out size of sparse matrix .... */ | ||||
|   ret_code = mm_read_mtx_crd_size(f, M, N, nz); | ||||
|   if(ret_code != 0 || !filldata || (*M > maxM) || (*N > maxN) || (*nz > maxnz)) { | ||||
|     status = !filldata; | ||||
|     goto x900; | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   /* NOTE: when reading in doubles, ANSI C requires the use of the "l"  */ | ||||
|   /* specifier as in "%lg", "%lf", "%le", otherwise errors will occur   */ | ||||
|   /*  (ANSI C X3.159-1989, Sec. 4.9.6.2, p. 136 lines 13-15)            */ | ||||
| 
 | ||||
|   /* Read dense matrix in column order */ | ||||
|   ispat = (MYBOOL) mm_is_pattern(matcode); | ||||
|   k = 1; | ||||
|   if(mm_is_dense(matcode)) { | ||||
|     maxN = MIN(maxN, *N); | ||||
|     for (jval = 1; jval <= maxN; jval++) { | ||||
|       for (i = 1; i <= *M; i++) { | ||||
|         if(fgets(buf, mmf_recsize-1, f) == NULL) | ||||
|           break; | ||||
|         if(sscanf(buf, "%lg\n", &Aval) == 0) | ||||
|           break; | ||||
|         if(Aval != 0) { | ||||
|           if(iA != NULL) | ||||
|             iA[k] = i; | ||||
|           if(jA != NULL) | ||||
|             jA[k] = jval; | ||||
| 
 | ||||
|           /* Make sure we handle dense vector reading properly */ | ||||
|           if(iA == NULL && jA == NULL) | ||||
|             Aij[i] = Aval; | ||||
|           else | ||||
|             Aij[k] = Aval; | ||||
|           k++; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   /* Read sparse matrix by coordinate */ | ||||
|   else { | ||||
|     for (i = 1; i <= *nz; i++) { | ||||
|       if(fgets(buf, mmf_recsize-1, f) == NULL) | ||||
|         break; | ||||
|       if(buf[0] == '%') | ||||
|         continue; | ||||
|       if(ispat) { | ||||
|         if(sscanf(buf, "%d %d\n", &ival, &jval) == 0) | ||||
|           continue; | ||||
|         Aij[k] = 1.0; | ||||
|       } | ||||
|       else | ||||
|         if(sscanf(buf, "%d %d %lg\n", &ival, &jval, &Aval) == 0) | ||||
|           continue; | ||||
| 
 | ||||
|       /* Check if it is a nonzero and we are within column dimension */ | ||||
|       if(Aval != 0 && jval <= maxN) { | ||||
|         Aij[k] = Aval; | ||||
|         if(iA != NULL) | ||||
|           iA[k] = ival; | ||||
|         if(jA != NULL) | ||||
|           jA[k] = jval; | ||||
|         k++; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   *nz = k - 1; | ||||
| 
 | ||||
|   /* Handle case where only the lower triangular parts are given */ | ||||
|   if(!mm_is_general(matcode)) { | ||||
|     if((M != N) || (maxN != maxM) || (2*(*nz) > maxnz)) { | ||||
|       printf("Market Market cannot fill in symmetry data\n"); | ||||
|       goto x900; | ||||
|     } | ||||
|     ispat = mm_is_skew(matcode); | ||||
|     for(i = 1; i <= *nz; i++) { | ||||
|       iA[k] = jA[i]; | ||||
|       jA[k] = iA[i]; | ||||
|       if(ispat) | ||||
|         Aij[k] = -Aij[i]; | ||||
|       else | ||||
|         Aij[k] = Aij[i]; | ||||
|       k++; | ||||
|     } | ||||
|     *nz = k - 1; | ||||
|   } | ||||
|   status = TRUE; | ||||
| 
 | ||||
|   /* Finish up */ | ||||
| x900: | ||||
|   fclose( f ); | ||||
|   return( status ); | ||||
| } | ||||
| 
 | ||||
| MYBOOL mmf_size_A(char *filename, int *M, int *N, int *nz) | ||||
| { | ||||
|   int maxint = 200000000; | ||||
| 
 | ||||
|   return( mmf_read_A(filename, maxint, maxint, maxint, | ||||
|                      M, N, nz, NULL, NULL, NULL) ); | ||||
| } | ||||
| 
 | ||||
| MYBOOL mmf_read_b(char *filename, int m, REAL *b) | ||||
| { | ||||
|   int im, jn, nnzero; | ||||
| 
 | ||||
|   return( mmf_read_A(filename, m, 1, m, | ||||
|                      &im, &jn, &nnzero, NULL, NULL, b)); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* Utility routines to read matrix files in Harwell-Boeing format*/ | ||||
| 
 | ||||
| MYBOOL hbf_read_A(char *filename, int maxM, int maxN, int maxnz, | ||||
|                   int *M, int *N, int *nz, int *iA, int *jA, REAL *Aij) | ||||
| { | ||||
|   MYBOOL success; | ||||
| 
 | ||||
|   success = hbf_size_A(filename, M, N, nz); | ||||
|   if(!success) | ||||
|     return( success ); | ||||
| 
 | ||||
|   Aij[1] = 0; | ||||
|   success = (MYBOOL) readHB_mat_double(filename, jA, iA-1, Aij-1); | ||||
| 
 | ||||
|   /* Test if we have a pattern matrix and fill it with all zeros */ | ||||
|   if(Aij[1] == 0) { | ||||
|     int i; | ||||
|     for(i = 1; i <= *nz; i++) | ||||
|       Aij[i] = 1; | ||||
|   } | ||||
| 
 | ||||
|   /* Expand the column nz counts to triplet format */ | ||||
|   if(success) { | ||||
|     int i, j, ii, k; | ||||
|     k = *nz; | ||||
|     for(j = *N; j > 0; j--) { | ||||
|       ii = jA[j]; | ||||
|       for(i = jA[j-1]; i < ii; i++, k--) | ||||
|         jA[k] = j; | ||||
|     } | ||||
|   } | ||||
|   return( success ); | ||||
| } | ||||
| 
 | ||||
| MYBOOL hbf_size_A(char *filename, int *M, int *N, int *nz) | ||||
| { | ||||
|   int  Nrhs; | ||||
|   char *Type; | ||||
| 
 | ||||
|   return( (MYBOOL) readHB_info(filename, M, N, nz, &Type, &Nrhs) ); | ||||
| } | ||||
| 
 | ||||
| MYBOOL hbf_read_b(char *filename, int m, REAL *b) | ||||
| { | ||||
|   return( (MYBOOL) readHB_aux_double(filename, 'F', b) ); /* Same format as matrix */ | ||||
| } | ||||
|  | @ -1,24 +0,0 @@ | |||
| #ifndef HEADER_lusolio | ||||
| #define HEADER_lusolio | ||||
| 
 | ||||
| /* Include necessary libraries                                               */ | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| #include "lusol.h" | ||||
| 
 | ||||
| MYBOOL ctf_read_A(char *filename, int maxm, int maxn, int maxnz, | ||||
|                   int *m, int *n, int *nnzero, int *iA, int *jA, REAL *Aij); | ||||
| MYBOOL ctf_size_A(char *filename, int *m, int *n, int *nnzero); | ||||
| MYBOOL ctf_read_b(char *filename, int m, REAL *b); | ||||
| 
 | ||||
| MYBOOL mmf_read_A(char *filename, int maxM, int maxN, int maxnz, | ||||
|                   int *M, int *N, int *nz, int *iA, int *jA, REAL *Aij); | ||||
| MYBOOL mmf_size_A(char *filename, int *M, int *N, int *nz); | ||||
| MYBOOL mmf_read_b(char *filename, int m, REAL *b); | ||||
| 
 | ||||
| MYBOOL hbf_read_A(char *filename, int maxM, int maxN, int maxnz, | ||||
|                   int *M, int *N, int *nz, int *iA, int *jA, REAL *Aij); | ||||
| MYBOOL hbf_size_A(char *filename, int *M, int *N, int *nz); | ||||
| MYBOOL hbf_read_b(char *filename, int m, REAL *b); | ||||
| 
 | ||||
| 
 | ||||
| #endif /* HEADER_lusolio */ | ||||
|  | @ -1,493 +0,0 @@ | |||
| 
 | ||||
| /*     This program solves a sparse linear system Ax = b using LUSOL. */ | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <math.h> | ||||
| #include <string.h> | ||||
| #include <time.h> | ||||
| #include "commonlib.h" | ||||
| #include "myblas.h" | ||||
| #include "lusol.h" | ||||
| #include "lusolio.h" | ||||
| #include "lusolmain.h" | ||||
| 
 | ||||
| #if (defined WIN32) || (defined WIN64) | ||||
| void _strupr_(char *s) | ||||
| { | ||||
|   _strupr(s); | ||||
| } | ||||
| #else | ||||
| /* Yin Zhang noted that _strupr() is not available on many Unix platforms */ | ||||
| void _strupr_(char *s) | ||||
| { | ||||
|   int  i; | ||||
|   char c; | ||||
|   for (i = 0; i < strlen(s); i++) { | ||||
|     c = s[i]; | ||||
|     if (c <= 'z' && c >= 'a') { | ||||
|       s[i] = c - 'a' + 'A'; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| MYBOOL getFileName(char *filename, char *test) | ||||
| { | ||||
|   MYBOOL status; | ||||
|   status = (MYBOOL) (('-' != test[0]) && (strlen(test) > 1)); | ||||
|   if(status) | ||||
|     strcpy(filename, test); | ||||
|   return(status); | ||||
| } | ||||
| MYBOOL isNum(char val) | ||||
| { | ||||
|   int ord; | ||||
|   ord = (int) val - 48; | ||||
|   return( (MYBOOL) ((ord >= 0) && (ord <= 9)) ); | ||||
| } | ||||
| 
 | ||||
| void main( int argc, char *argv[], char *envp[] ) | ||||
| { | ||||
| /* Output device */ | ||||
|   FILE *outunit = stdout; | ||||
| 
 | ||||
| /* Overall dimensions allocated */ | ||||
|   int    maxm = MAXROWS, maxn = MAXCOLS, maxnz = MAXNZ, | ||||
|          replace = 0, randcol = 0; | ||||
|   MYBOOL ftran = TRUE; | ||||
| 
 | ||||
| /* Storage for A, b */ | ||||
|   REAL   *Aij = NULL, *b = NULL, *xexact = NULL; | ||||
|   int    *iA = NULL, *jA = NULL; | ||||
| 
 | ||||
| /* Storage for LUSOL */ | ||||
|   LUSOLrec *LUSOL = NULL; | ||||
| 
 | ||||
| /* Define local storage variables */ | ||||
|   int  i     , inform, j     , k     , i1   , | ||||
|        m     , useropt, lenb, lenx, | ||||
|        n     , nelem , nnzero; | ||||
|   REAL Amax  , test  , | ||||
|        bnorm , rnorm , xnorm, | ||||
|        *rhs = NULL, *r = NULL, *x = NULL; | ||||
|   char fileext[50], filename[255], blasname[255]; | ||||
|   MYBOOL printsolution = FALSE, success = FALSE; | ||||
| 
 | ||||
| /* Check if we have input parameters */ | ||||
|   useropt = argc; | ||||
|   if(useropt < 2) { | ||||
|     printf("LUSOL v%d.%d.%d.%d - Linear equation solver - Development edition.\n", | ||||
|            LUSOL_VERMAJOR, LUSOL_VERMINOR, LUSOL_RELEASE, LUSOL_BUILD); | ||||
|     printf("Usage:   lusol [-p <type>] [-t <tolerance>] [-m <memscalar>]\n"); | ||||
|     printf("               [-s] <MatrixFile> [<RhsFile>]\n"); | ||||
|     printf("Options: -p <type>        <0..3>    Selects pivot type.\n"); | ||||
|     printf("         -t <tolerance>   <1..100>  Selects diagonal tolerance.\n"); | ||||
|     printf("         -m <memscalar>   <%d..100> Memory allocation scalar.\n", LUSOL_MULT_nz_a); | ||||
|     printf("         -b               Solves using btran (rather than ftran).\n"); | ||||
|     printf("         -r <times>       Randomly replace a column and resolve.\n"); | ||||
|     printf("         -s               Show the computed solution.\n"); | ||||
|     printf("         -blas <lib>      Activates external optimized BLAS library.\n"); | ||||
|     printf("Formats: Conventional RCV .TXT, MatrixMarket .MTX, or Harwell-Boeing .RUA\n"); | ||||
|     printf("Author:  Michael A. Saunders (original Fortran version)\n"); | ||||
|     printf("         Kjell Eikland       (modified C version)\n"); | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
| /* Create the LUSOL object and set user options */ | ||||
|   LUSOL = LUSOL_create(outunit, 0, LUSOL_PIVMOD_TPP, 0); | ||||
| #if 1 | ||||
|   LUSOL->luparm[LUSOL_IP_ACCELERATION] = LUSOL_OTHERORDER | LUSOL_ACCELERATE_L0; | ||||
| #elif 0 | ||||
|   LUSOL->luparm[LUSOL_IP_ACCELERATION] = LUSOL_AUTOORDER | LUSOL_ACCELERATE_L0; | ||||
| #endif | ||||
|   LUSOL->luparm[LUSOL_IP_SCALAR_NZA] = 10; | ||||
|   i = 1; | ||||
|   n = 0; | ||||
|   filename[0] = '\0'; | ||||
|   blasname[0] = '\0'; | ||||
|   while((n == 0) && (i < argc)) { | ||||
|     if(strcmp("-p", argv[i]) == 0) { | ||||
|       i1 = i+1; | ||||
|       if((i1 < argc) && isNum(argv[i1][0])) { | ||||
|         i = i1; | ||||
|         m = atoi(argv[i]); | ||||
|         if(m < 0 || m > LUSOL_PIVMOD_MAX) | ||||
|           continue; | ||||
|         LUSOL->luparm[LUSOL_IP_PIVOTTYPE] = m; | ||||
|       } | ||||
|     } | ||||
|     else if(strcmp("-t", argv[i]) == 0) { | ||||
|       i1 = i+1; | ||||
|       if((i1 < argc) && isNum(argv[i1][0])) { | ||||
|         i = i1; | ||||
|         Amax = atof(argv[i]); | ||||
|         if(Amax < 1 || Amax > 100) | ||||
|           continue; | ||||
|         LUSOL->parmlu[LUSOL_RP_FACTORMAX_Lij] = Amax; | ||||
|       } | ||||
|     } | ||||
|     else if(strcmp("-m", argv[i]) == 0) { | ||||
|       i1 = i+1; | ||||
|       if((i1 < argc) && isNum(argv[i1][0])) { | ||||
|         i = i1; | ||||
|         m = atoi(argv[i]); | ||||
|         if(m < LUSOL_MULT_nz_a || m > 100) | ||||
|           continue; | ||||
|         LUSOL->luparm[LUSOL_IP_SCALAR_NZA] = atoi(argv[i]); | ||||
|       } | ||||
|     } | ||||
|     else if(strcmp("-s", argv[i]) == 0) | ||||
|       printsolution = TRUE; | ||||
|     else if(strcmp("-b", argv[i]) == 0) | ||||
|       ftran = FALSE; | ||||
|     else if(strcmp("-r", argv[i]) == 0) { | ||||
|       i1 = i+1; | ||||
|       if((i1 < argc) && isNum(argv[i1][0])) { | ||||
|         i = i1; | ||||
|         m = atoi(argv[i]); | ||||
|         if(m < 0 || m > 10) | ||||
|           continue; | ||||
|       } | ||||
|       else | ||||
|         m = 1; | ||||
|       srand((unsigned) time( NULL )); | ||||
|       replace = 2*m; | ||||
|     } | ||||
|     else if(strcmp("-blas", argv[i]) == 0) { | ||||
|       i1 = i+1; | ||||
|       if((i1 < argc) && getFileName(blasname, argv[i1])) { | ||||
|         if(!load_BLAS(blasname)) | ||||
|           fprintf(outunit, "Could not load external BLAS library '%s'\n", blasname); | ||||
|         i = i1; | ||||
|       } | ||||
|       else | ||||
|         fprintf(outunit, "Ignoring incomplete parameter %d '%s'\n", i, argv[i]); | ||||
|     } | ||||
|     else { | ||||
|       if(getFileName(filename, argv[i])) { | ||||
|         useropt = i; | ||||
|         break; | ||||
|       } | ||||
|       else | ||||
|         fprintf(outunit, "Ignoring unknown parameter %d '%s'\n", i, argv[i]); | ||||
|     } | ||||
|     i++; | ||||
|   } | ||||
| 
 | ||||
| /* Obtain file extension and see if we must estimate matrix data size */ | ||||
|   strcpy(fileext, strchr(argv[useropt], '.')); | ||||
|   /* Yin Zhang noted that _strupr() is not available on many Unix platforms. */ | ||||
|   _strupr_(fileext); | ||||
| /*  _strupr(fileext);*/ | ||||
| 
 | ||||
|   /* Read conventional text file format */ | ||||
|   if(strcmp(fileext, ".TXT") == 0) { | ||||
|     if(!ctf_size_A(filename, &maxm, &maxn, &maxnz)) | ||||
|       goto x900; | ||||
|   } | ||||
|   /* Read MatrixMarket file format */ | ||||
|   else if(strcmp(fileext, ".MTX") == 0) { | ||||
|     if(!mmf_size_A(filename, &maxm, &maxn, &maxnz)) | ||||
|       goto x900; | ||||
|   } | ||||
|   /* Read Harwell-Boeing file format */ | ||||
|   else if(strcmp(fileext, ".RUA") == 0) { | ||||
|     if(!hbf_size_A(filename, &maxm, &maxn, &maxnz)) | ||||
|       goto x900; | ||||
|   } | ||||
|   else { | ||||
|     fprintf(outunit, "Unrecognized matrix file extension %s\n", fileext); | ||||
|     goto x900; | ||||
|   } | ||||
| 
 | ||||
| /* Create the arrays */ | ||||
| 
 | ||||
|   Aij = (REAL *) LUSOL_CALLOC(maxnz + BLAS_BASE, sizeof(REAL)); | ||||
|   iA = (int *)   LUSOL_CALLOC(maxnz + BLAS_BASE, sizeof(int)); | ||||
|   jA = (int *)   LUSOL_CALLOC(maxnz + BLAS_BASE, sizeof(int)); | ||||
|   if(ftran) | ||||
|     lenb = maxm; | ||||
|   else | ||||
|     lenb = maxn; | ||||
|   b   = (REAL *) LUSOL_CALLOC(lenb+BLAS_BASE, sizeof(REAL)); | ||||
|   rhs = (REAL *) LUSOL_CALLOC(lenb+BLAS_BASE, sizeof(REAL)); | ||||
| 
 | ||||
|   if(ftran) | ||||
|     lenx = maxn; | ||||
|   else | ||||
|     lenx = maxm; | ||||
|   xexact = (REAL *) LUSOL_CALLOC(lenx+BLAS_BASE, sizeof(REAL)); | ||||
|   r = (REAL *) LUSOL_CALLOC(lenx+BLAS_BASE, sizeof(REAL)); | ||||
|   x = (REAL *) LUSOL_CALLOC(lenx+BLAS_BASE, sizeof(REAL)); | ||||
| 
 | ||||
| /* -----------------------------------------------------------------
 | ||||
|    Read data files. | ||||
|    ----------------------------------------------------------------- */ | ||||
|   fprintf(stdout, "\n========================================\n"); | ||||
|   fprintf(stdout,   "LUSOL v%d.%d.%d.%d - Linear equation solver", | ||||
|                     LUSOL_VERMAJOR, LUSOL_VERMINOR, LUSOL_RELEASE, LUSOL_BUILD); | ||||
|   fprintf(stdout, "\n========================================\n"); | ||||
| 
 | ||||
| /* -----------------------------------------------------------------
 | ||||
|    Read data for A | ||||
|    ----------------------------------------------------------------- */ | ||||
|   /* Read conventional text file format */ | ||||
|   if(strcmp(fileext, ".TXT") == 0) { | ||||
|     if(!ctf_read_A(argv[useropt], maxm, maxn, maxnz, | ||||
|                    &m, &n, &nnzero, iA, jA, Aij)) | ||||
|       goto x900; | ||||
|   } | ||||
|   /* Read MatrixMarket file format */ | ||||
|   else if(strcmp(fileext, ".MTX") == 0) { | ||||
|     if(!mmf_read_A(argv[useropt], maxm, maxn, maxnz, | ||||
|                    &m, &n, &nnzero, iA, jA, Aij)) | ||||
|       goto x900; | ||||
|   } | ||||
|   /* Read Harwell-Boeing file format */ | ||||
|   else if(strcmp(fileext, ".RUA") == 0) { | ||||
|     if(!hbf_read_A(argv[useropt], maxm, maxn, maxnz, | ||||
|                    &m, &n, &nnzero, iA, jA, Aij)) | ||||
|       goto x900; | ||||
|   } | ||||
|   else { | ||||
|     fprintf(outunit, "Error: Unrecognized matrix file extension %s\n", fileext); | ||||
|     goto x900; | ||||
|   } | ||||
| 
 | ||||
| /* -----------------------------------------------------------------
 | ||||
|    Read data for b | ||||
|    ----------------------------------------------------------------- */ | ||||
|   /* Handle Harwell-Boeing case where the file contains a RHS */ | ||||
|   i = strcmp(fileext, ".RUA"); | ||||
| 
 | ||||
|   if((useropt == argc-1) && (i != 0)) { | ||||
|     srand(timeNow()); | ||||
|     i1 = m; | ||||
|     while(i1 > 0) { | ||||
|       test = rand(); | ||||
|       i = RAND_MAX; | ||||
|       i = (int) ((test/i)*(m-1)); | ||||
| /*      b[i+1] = 1.0; */ | ||||
|       b[i+1] = i - 5; | ||||
|       i1--; | ||||
|     } | ||||
|     if(printsolution) | ||||
|       blockWriteREAL(outunit, "\nGenerated RHS vector", b, 1, lenb); | ||||
|   } | ||||
|   else { | ||||
|     if(i != 0) | ||||
|       useropt++; | ||||
|     strcpy(fileext, strchr(argv[useropt], '.')); | ||||
|     _strupr_(fileext); | ||||
| 
 | ||||
|     /* Read conventional text file format */ | ||||
|     if(strcmp(fileext, ".TXT") == 0) { | ||||
|       if(!ctf_read_b(argv[useropt], lenb, b)) | ||||
|         goto x900; | ||||
|     } | ||||
|     /* Read MatrixMarket file format */ | ||||
|     else if(strcmp(fileext, ".MTX") == 0) { | ||||
|       if(!mmf_read_b(argv[useropt], lenb, b)) | ||||
|         goto x900; | ||||
|     } | ||||
|   /* Read Harwell-Boeing file format */ | ||||
|     else if(strcmp(fileext, ".RUA") == 0) { | ||||
|       if(!hbf_read_b(argv[useropt], lenb, b)) | ||||
|         goto x900; | ||||
|     } | ||||
|     else { | ||||
|       fprintf(outunit, "Error: Unrecognized vector file extension %s\n", fileext); | ||||
|       goto x900; | ||||
|     } | ||||
|   } | ||||
|   success = TRUE; | ||||
| 
 | ||||
| /* -----------------------------------------------------------------
 | ||||
|    Show data on input | ||||
|    ----------------------------------------------------------------- */ | ||||
|   fprintf(outunit, "\nData read from:\n%s\n", filename); | ||||
|   test = (double) nnzero / ((double) m * (double) n); | ||||
|   test *= 100.0; | ||||
|   fprintf(outunit, "Rows = %d   Columns = %d   Non-zeros = %d  Density =%8.4f%%\n", | ||||
|                    m, n, nnzero, test); | ||||
| 
 | ||||
| /* -----------------------------------------------------------------
 | ||||
|    Load A into (a, indc, indr). | ||||
|    ----------------------------------------------------------------- */ | ||||
| #if 0 /* BUG !!! */
 | ||||
|   if(n != m) | ||||
|     LUSOL->luparm[LUSOL_IP_KEEPLU] = FALSE; | ||||
| #endif | ||||
| #ifdef LegacyTesting | ||||
|   LUSOL->luparm[LUSOL_IP_SCALAR_NZA] = LUSOL_MULT_nz_a; | ||||
|   LUSOL_sizeto(LUSOL, MAXROWS, MAXCOLS, MAXNZ*LUSOL_MULT_nz_a); | ||||
| #endif | ||||
| 
 | ||||
|   if(!LUSOL_assign(LUSOL, iA, jA, Aij, nnzero, TRUE)) { | ||||
|     fprintf(outunit, "Error: LUSOL failed due to insufficient memory.\n"); | ||||
|     goto x900; | ||||
|   } | ||||
| 
 | ||||
| /* ------------------------------------------------------------------
 | ||||
|    Factor  A = L U. | ||||
|    ------------------------------------------------------------------ */ | ||||
|   nelem = nnzero; | ||||
|   inform = LUSOL_factorize( LUSOL); | ||||
|   if(inform > LUSOL_INFORM_SERIOUS) { | ||||
|     fprintf(outunit, "Error:\n%s\n", LUSOL_informstr(LUSOL, inform)); | ||||
|     goto x900; | ||||
|   } | ||||
|   if(n != m) | ||||
|     goto x800; | ||||
| 
 | ||||
|   /* Get the largest element in A; we use it below as an estimate
 | ||||
|      of ||A||_inf, even though it isn't a proper norm. */ | ||||
|   Amax = LUSOL->parmlu[LUSOL_RP_MAXELEM_A]; | ||||
| 
 | ||||
| /* ------------------------------------------------------------------
 | ||||
|    SOLVE  A x = b  or  x'A = b'. | ||||
|    Save b first because lu6sol() overwrites the rhs. | ||||
|    ------------------------------------------------------------------ */ | ||||
|   MEMCOPY(x, b, lenb+BLAS_BASE); | ||||
| 
 | ||||
| Resolve: | ||||
|   if(ftran) | ||||
|     inform = LUSOL_ftran(LUSOL, x, NULL, FALSE); | ||||
|   else | ||||
|     inform = LUSOL_btran(LUSOL, x, NULL); | ||||
|   if(inform > LUSOL_INFORM_SERIOUS) { | ||||
|     fprintf(outunit, "Error:\n%s\n", LUSOL_informstr(LUSOL, inform)); | ||||
|     goto x900; | ||||
|   } | ||||
|   if(printsolution) | ||||
|     blockWriteREAL(outunit, "\nSolution vector", x, 1, lenb); | ||||
| 
 | ||||
| /* ------------------------------------------------------------------
 | ||||
|    Set r = b - Ax. | ||||
|    Find norm of r and x. | ||||
|    ------------------------------------------------------------------ */ | ||||
|   MEMCOPY(r, b, lenb+BLAS_BASE); | ||||
|   for(k = 1; k <= nnzero; k++) { | ||||
|     i    = iA[k];  /* Row number    */ | ||||
|     j    = jA[k];  /* Column number */ | ||||
|     if(ftran) | ||||
|       r[i] -= Aij[k]*x[j]; | ||||
|     else | ||||
|       r[j] -= Aij[k]*x[i]; | ||||
|   } | ||||
| /*  blockWriteREAL(outunit, "\nResidual vector", r, 1, lenb);*/ | ||||
|   bnorm  = dnormi( lenb, b ); | ||||
|   rnorm  = dnormi( lenb, r ); | ||||
|   xnorm  = dnormi( lenx, x ); | ||||
| 
 | ||||
| /* ------------------------------------------------------------------
 | ||||
|    Report the findings. | ||||
|    ------------------------------------------------------------------ */ | ||||
|   if(randcol > 0) | ||||
|     fprintf(outunit, "\n\nColumn %d was %s\n", | ||||
|                       randcol, | ||||
|                       (mod(replace,2) == 1 ? "replaced with random data" : "restored")); | ||||
| 
 | ||||
| x800: | ||||
|   fprintf(outunit, "\nLU size statistics (%d reallocations):\n", | ||||
|                    LUSOL->expanded_a); | ||||
|   test = LUSOL->luparm[LUSOL_IP_NONZEROS_U0]+LUSOL->luparm[LUSOL_IP_NONZEROS_L0]; | ||||
|   fprintf(outunit, "L0-size = %d   U0-size = %d   LU-nonzeros = %d   Fill-in = %.1fx\n", | ||||
|                    LUSOL->luparm[LUSOL_IP_NONZEROS_L0], | ||||
|                    LUSOL->luparm[LUSOL_IP_NONZEROS_U0], | ||||
|                    (int) test, test/nnzero); | ||||
|   if(n != m) { | ||||
|     fprintf(outunit, "%s with a factor tol. of %g identified %d singularities.\n", | ||||
|                      LUSOL_pivotLabel(LUSOL), LUSOL->parmlu[LUSOL_RP_FACTORMAX_Lij], | ||||
|                      LUSOL->luparm[LUSOL_IP_SINGULARITIES]); | ||||
|     goto x900; | ||||
|   } | ||||
| 
 | ||||
|   test   = rnorm / (Amax*xnorm); | ||||
|   fprintf(outunit, "\nAccuracy statistics:\n"); | ||||
|   fprintf(outunit, "%s with a factor tol. of %g gave a rel.error of %g and %d singularities.\n", | ||||
|                    LUSOL_pivotLabel(LUSOL), LUSOL->parmlu[LUSOL_RP_FACTORMAX_Lij], test, | ||||
|                    LUSOL->luparm[LUSOL_IP_SINGULARITIES]); | ||||
|   fprintf(outunit, "Amax = %g   bnorm = %g   rnorm = %g   xnorm = %g\n", | ||||
|                    Amax, bnorm, rnorm, xnorm); | ||||
| 
 | ||||
|   fprintf(outunit, "\n"); | ||||
| 
 | ||||
|   if (test <= 1.0e-8) | ||||
|     fprintf(outunit, "The equations were solved with very high accuracy.\n"); | ||||
|   else if (test <= 1.0e-6) | ||||
|     fprintf(outunit, "The equations were solved with reasonably good accuracy.\n"); | ||||
|   else { | ||||
|     if (test <= 1.0e-4) | ||||
|       fprintf(outunit, "Questionable accuracy; the LU factors may not be good enough.\n"); | ||||
|     else | ||||
|       fprintf(outunit, "Poor accuracy; the LU factorization probably failed.\n"); | ||||
|     if(LUSOL->luparm[LUSOL_IP_PIVOTTYPE] == LUSOL_PIVMOD_TRP) | ||||
|       fprintf(outunit, "Try a smaller factor tolerance (current is %g).\n", | ||||
|                        LUSOL->parmlu[LUSOL_RP_FACTORMAX_Lij]); | ||||
|     else | ||||
|       fprintf(outunit, "Try a smaller factor tolerance and/or TRP pivoting.\n"); | ||||
|   } | ||||
| 
 | ||||
|  /* Check if we should replace a column and resolve */ | ||||
|   if(replace > 0) { | ||||
|     replace--; | ||||
|     MEMCLEAR(x, lenb+BLAS_BASE); | ||||
|     if(mod(replace, 2) == 1) { | ||||
|       /* Randomly find a column and replace the column values with random data */ | ||||
|       rnorm   = rand(); | ||||
|       randcol = (int) (n * rnorm / (RAND_MAX+1.0)) + 1; | ||||
|       for(i = 1; i < m; i++) | ||||
|         x[i] = Amax * rand() / RAND_MAX; | ||||
|     } | ||||
|     else { | ||||
|       /* Put the previously replaced column back and resolve */ | ||||
|       for (k = 1; k <= nnzero; k++) { | ||||
|         i    = iA[k]; | ||||
|         j    = jA[k]; | ||||
|         if(j == randcol) | ||||
|           x[i] = Aij[k]; | ||||
|       } | ||||
|     } | ||||
|     inform = LUSOL_replaceColumn(LUSOL, randcol, x); | ||||
|     MEMCOPY(b, x, lenb+BLAS_BASE); | ||||
|     if(inform != LUSOL_INFORM_LUSUCCESS) | ||||
|       fprintf(outunit, "Error:\n%s\n", LUSOL_informstr(LUSOL, inform)); | ||||
|     else | ||||
|       goto Resolve; | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
| /* Free memory */ | ||||
| x900: | ||||
|   if(!success) | ||||
|     fprintf(outunit, "Insufficient memory or data file not found.\n"); | ||||
| 
 | ||||
|   LUSOL_FREE(Aij); | ||||
|   LUSOL_FREE(b); | ||||
|   LUSOL_FREE(xexact); | ||||
|   LUSOL_FREE(iA); | ||||
|   LUSOL_FREE(jA); | ||||
| 
 | ||||
|   LUSOL_FREE(rhs); | ||||
|   LUSOL_FREE(r); | ||||
|   LUSOL_FREE(x); | ||||
| 
 | ||||
| #if 0 | ||||
|   LUSOL_dump(NULL, LUSOL); | ||||
|  -blas "atlas_AXP_512_360.dll" -b -p 1 "STP3D_A.MTX" | ||||
|  "C:\Shared Files\Visual Studio Projects\LU\MatrixMarket\sherman5.mtx" "C:\Shared Files\Visual Studio Projects\LU\MatrixMarket\sherman5_rhs1.mtx" | ||||
|  A6805.txt b6805.txt | ||||
|  A10009.txt b10009.txt | ||||
|  fidap005.mtx fidap005_rhs1.mtx | ||||
|  fidapm05.mtx fidapm05_rhs1.mtx | ||||
|  -b -p 1 "basis.mtx" | ||||
|  -b -p 1 "LU-test3.mtx" | ||||
| #endif | ||||
| 
 | ||||
|   LUSOL_free(LUSOL); | ||||
| 
 | ||||
| /*     End of main program for Test of LUSOL */ | ||||
| } | ||||
| 
 | ||||
|  | @ -1,26 +0,0 @@ | |||
| 
 | ||||
| #ifdef StaticMemAlloc | ||||
| 
 | ||||
| #if 0 | ||||
|   #define MAXNZ        300000 | ||||
|   #define MAXROWS       15000 | ||||
| #elif 0 | ||||
|   #define MAXNZ         60000 | ||||
|   #define MAXROWS       12500 | ||||
| #elif 1 | ||||
|   #define MAXNZ         40000 | ||||
|   #define MAXROWS        3500 | ||||
| #else | ||||
|   #define MAXNZ          1000 | ||||
|   #define MAXROWS          50 | ||||
| #endif | ||||
| 
 | ||||
| #else | ||||
| 
 | ||||
|   #define MAXNZ          1000 | ||||
|   #define MAXROWS          50 | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #define MAXCOLS     MAXROWS | ||||
| #define MAXLU      (LUSOL_MULT_nz_a*MAXNZ) | ||||
|  | @ -1,495 +0,0 @@ | |||
| /* 
 | ||||
| *   Matrix Market I/O library for ANSI C | ||||
| * | ||||
| *   See http://math.nist.gov/MatrixMarket for details.
 | ||||
| * | ||||
| *   (Version 1.01, 5/2003) | ||||
| */ | ||||
| 
 | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <ctype.h> | ||||
| 
 | ||||
| #include "mmio.h" | ||||
| 
 | ||||
| int mm_read_unsymmetric_sparse(const char *fname, int *M_, int *N_, int *nz_, | ||||
|                 double **val_, int **I_, int **J_) | ||||
| { | ||||
|     FILE *f; | ||||
|     MM_typecode matcode; | ||||
|     int M, N, nz; | ||||
|     int i; | ||||
|     double *val; | ||||
|     int *I, *J; | ||||
|   | ||||
|     if ((f = fopen(fname, "r")) == NULL) | ||||
|             return -1; | ||||
|   | ||||
|   | ||||
|     if (mm_read_banner(f, &matcode) != 0) | ||||
|     { | ||||
|         printf("mm_read_unsymetric: Could not process Matrix Market banner "); | ||||
|         printf(" in file [%s]\n", fname); | ||||
|         return -1; | ||||
|     } | ||||
|   | ||||
|   | ||||
|   | ||||
|     if ( !(mm_is_real(matcode) && mm_is_matrix(matcode) && | ||||
|             mm_is_sparse(matcode))) | ||||
|     { | ||||
|         fprintf(stderr, "Sorry, this application does not support "); | ||||
|         fprintf(stderr, "Market Market type: [%s]\n", | ||||
|                 mm_typecode_to_str(matcode)); | ||||
|         return -1; | ||||
|     } | ||||
|   | ||||
|     /* find out size of sparse matrix: M, N, nz .... */ | ||||
|   | ||||
|     if (mm_read_mtx_crd_size(f, &M, &N, &nz) !=0) | ||||
|     { | ||||
|         fprintf(stderr, "read_unsymmetric_sparse(): could not parse matrix size.\n"); | ||||
|         return -1; | ||||
|     } | ||||
|   | ||||
|     *M_ = M; | ||||
|     *N_ = N; | ||||
|     *nz_ = nz; | ||||
|   | ||||
|     /* reseve memory for matrices */ | ||||
|   | ||||
|     I = (int *) malloc(nz * sizeof(int)); | ||||
|     J = (int *) malloc(nz * sizeof(int)); | ||||
|     val = (double *) malloc(nz * sizeof(double)); | ||||
|   | ||||
|     *val_ = val; | ||||
|     *I_ = I; | ||||
|     *J_ = J; | ||||
|   | ||||
|     /* NOTE: when reading in doubles, ANSI C requires the use of the "l"  */ | ||||
|     /*   specifier as in "%lg", "%lf", "%le", otherwise errors will occur */ | ||||
|     /*  (ANSI C X3.159-1989, Sec. 4.9.6.2, p. 136 lines 13-15)            */ | ||||
|   | ||||
|     for (i=0; i<nz; i++) | ||||
|     { | ||||
|         fscanf(f, "%d %d %lg\n", &I[i], &J[i], &val[i]); | ||||
|         I[i]--;  /* adjust from 1-based to 0-based */ | ||||
|         J[i]--; | ||||
|     } | ||||
|     fclose(f); | ||||
|   | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| int mm_is_valid(MM_typecode matcode) | ||||
| { | ||||
|     if (!mm_is_matrix(matcode)) return 0; | ||||
|     if (mm_is_dense(matcode) && mm_is_pattern(matcode)) return 0; | ||||
|     if (mm_is_real(matcode) && mm_is_hermitian(matcode)) return 0; | ||||
|     if (mm_is_pattern(matcode) && (mm_is_hermitian(matcode) ||  | ||||
|                 mm_is_skew(matcode))) return 0; | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| int mm_read_banner(FILE *f, MM_typecode *matcode) | ||||
| { | ||||
|     char line[MM_MAX_LINE_LENGTH]; | ||||
|     char banner[MM_MAX_TOKEN_LENGTH]; | ||||
|     char mtx[MM_MAX_TOKEN_LENGTH];  | ||||
|     char crd[MM_MAX_TOKEN_LENGTH]; | ||||
|     char data_type[MM_MAX_TOKEN_LENGTH]; | ||||
|     char storage_scheme[MM_MAX_TOKEN_LENGTH]; | ||||
|     char *p; | ||||
| 
 | ||||
| 
 | ||||
|     mm_clear_typecode(matcode);   | ||||
| 
 | ||||
|     if (fgets(line, MM_MAX_LINE_LENGTH, f) == NULL)  | ||||
|         return MM_PREMATURE_EOF; | ||||
| 
 | ||||
|     if (sscanf(line, "%s %s %s %s %s", banner, mtx, crd, data_type,  | ||||
|         storage_scheme) != 5) | ||||
|         return MM_PREMATURE_EOF; | ||||
| 
 | ||||
| 	/* convert to lower case */ | ||||
|     for (p=mtx; *p!='\0'; *p= (char) tolower(*p),p++);   | ||||
|     for (p=crd; *p!='\0'; *p= (char) tolower(*p),p++);   | ||||
|     for (p=data_type; *p!='\0'; *p= (char) tolower(*p),p++); | ||||
|     for (p=storage_scheme; *p!='\0'; *p= (char) tolower(*p),p++); | ||||
| 
 | ||||
|     /* check for banner */ | ||||
|     if (strncmp(banner, MatrixMarketBanner, strlen(MatrixMarketBanner)) != 0) | ||||
|         return MM_NO_HEADER; | ||||
| 
 | ||||
|     /* first field should be "mtx" */ | ||||
|     if (strcmp(mtx, MM_MTX_STR) != 0) | ||||
|         return  MM_UNSUPPORTED_TYPE; | ||||
|     mm_set_matrix(matcode); | ||||
| 
 | ||||
| 
 | ||||
|     /* second field describes whether this is a sparse matrix (in coordinate
 | ||||
|             storgae) or a dense array */ | ||||
| 
 | ||||
| 
 | ||||
|     if (strcmp(crd, MM_SPARSE_STR) == 0) | ||||
|         mm_set_sparse(matcode); | ||||
|     else | ||||
|     if (strcmp(crd, MM_DENSE_STR) == 0) | ||||
|             mm_set_dense(matcode); | ||||
|     else | ||||
|         return MM_UNSUPPORTED_TYPE; | ||||
|      | ||||
| 
 | ||||
|     /* third field */ | ||||
| 
 | ||||
|     if (strcmp(data_type, MM_REAL_STR) == 0) | ||||
|         mm_set_real(matcode); | ||||
|     else | ||||
|     if (strcmp(data_type, MM_COMPLEX_STR) == 0) | ||||
|         mm_set_complex(matcode); | ||||
|     else | ||||
|     if (strcmp(data_type, MM_PATTERN_STR) == 0) | ||||
|         mm_set_pattern(matcode); | ||||
|     else | ||||
|     if (strcmp(data_type, MM_INT_STR) == 0) | ||||
|         mm_set_integer(matcode); | ||||
|     else | ||||
|         return MM_UNSUPPORTED_TYPE; | ||||
|      | ||||
| 
 | ||||
|     /* fourth field */ | ||||
| 
 | ||||
|     if (strcmp(storage_scheme, MM_GENERAL_STR) == 0) | ||||
|         mm_set_general(matcode); | ||||
|     else | ||||
|     if (strcmp(storage_scheme, MM_SYMM_STR) == 0) | ||||
|         mm_set_symmetric(matcode); | ||||
|     else | ||||
|     if (strcmp(storage_scheme, MM_HERM_STR) == 0) | ||||
|         mm_set_hermitian(matcode); | ||||
|     else | ||||
|     if (strcmp(storage_scheme, MM_SKEW_STR) == 0) | ||||
|         mm_set_skew(matcode); | ||||
|     else | ||||
|         return MM_UNSUPPORTED_TYPE; | ||||
|          | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| int mm_write_mtx_crd_size(FILE *f, int M, int N, int nz) | ||||
| { | ||||
|     if (fprintf(f, "%d %d %d\n", M, N, nz) < 0) | ||||
|         return MM_COULD_NOT_WRITE_FILE; | ||||
|     else  | ||||
|         return 0; | ||||
| } | ||||
| 
 | ||||
| int mm_read_mtx_crd_size(FILE *f, int *M, int *N, int *nz ) | ||||
| { | ||||
|     char line[MM_MAX_LINE_LENGTH]; | ||||
|     int num_items_read; | ||||
| 
 | ||||
|     /* set return null parameter values, in case we exit with errors */ | ||||
|     *M = *N = *nz = 0; | ||||
| 
 | ||||
|     /* now continue scanning until you reach the end-of-comments */ | ||||
|     do { | ||||
|       if (fgets(line,MM_MAX_LINE_LENGTH,f) == NULL)  | ||||
|           return MM_PREMATURE_EOF; | ||||
|     } while (line[0] == '%'); | ||||
| 
 | ||||
|     /* line[] is either blank, har M,N or M,N,nz */ | ||||
|     if (sscanf(line, "%d %d %d", M, N, nz) >= 2) | ||||
|       return 0; | ||||
|          | ||||
|     else | ||||
|     do {  | ||||
|         num_items_read = fscanf(f, "%d %d %d", M, N, nz);  | ||||
|         if (num_items_read == EOF) return MM_PREMATURE_EOF; | ||||
|     } while (num_items_read < 2); | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int mm_read_mtx_array_size(FILE *f, int *M, int *N) | ||||
| { | ||||
|     char line[MM_MAX_LINE_LENGTH]; | ||||
|     int num_items_read; | ||||
|     /* set return null parameter values, in case we exit with errors */ | ||||
|     *M = *N = 0; | ||||
| 	 | ||||
|     /* now continue scanning until you reach the end-of-comments */ | ||||
|     do  | ||||
|     { | ||||
|         if (fgets(line,MM_MAX_LINE_LENGTH,f) == NULL)  | ||||
|             return MM_PREMATURE_EOF; | ||||
|     }while (line[0] == '%'); | ||||
| 
 | ||||
|     /* line[] is either blank or has M,N, nz */ | ||||
|     if (sscanf(line, "%d %d", M, N) == 2) | ||||
|         return 0; | ||||
|          | ||||
|     else /* we have a blank line */ | ||||
|     do | ||||
|     {  | ||||
|         num_items_read = fscanf(f, "%d %d", M, N);  | ||||
|         if (num_items_read == EOF) return MM_PREMATURE_EOF; | ||||
|     } | ||||
|     while (num_items_read != 2); | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| int mm_write_mtx_array_size(FILE *f, int M, int N) | ||||
| { | ||||
|     if (fprintf(f, "%d %d\n", M, N) < 0) | ||||
|         return MM_COULD_NOT_WRITE_FILE; | ||||
|     else  | ||||
|         return 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /*-------------------------------------------------------------------------*/ | ||||
| 
 | ||||
| /******************************************************************/ | ||||
| /* use when I[], J[], and val[]J, and val[] are already allocated */ | ||||
| /******************************************************************/ | ||||
| 
 | ||||
| int mm_read_mtx_crd_data(FILE *f, int M, int N, int nz, int I[], int J[], | ||||
|         double val[], MM_typecode matcode) | ||||
| { | ||||
|     int i; | ||||
|     if (mm_is_complex(matcode)) | ||||
|     { | ||||
|         for (i=0; i<nz; i++) | ||||
|             if (fscanf(f, "%d %d %lg %lg", &I[i], &J[i], &val[2*i], &val[2*i+1]) | ||||
|                 != 4) return MM_PREMATURE_EOF; | ||||
|     } | ||||
|     else if (mm_is_real(matcode)) | ||||
|     { | ||||
|         for (i=0; i<nz; i++) | ||||
|         { | ||||
|             if (fscanf(f, "%d %d %lg\n", &I[i], &J[i], &val[i]) | ||||
|                 != 3) return MM_PREMATURE_EOF; | ||||
| 
 | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     else if (mm_is_pattern(matcode)) | ||||
|     { | ||||
|         for (i=0; i<nz; i++) | ||||
|             if (fscanf(f, "%d %d", &I[i], &J[i]) | ||||
|                 != 2) return MM_PREMATURE_EOF; | ||||
|     } | ||||
|     else | ||||
|         return MM_UNSUPPORTED_TYPE; | ||||
| 
 | ||||
|     return 0; | ||||
|          | ||||
| } | ||||
| 
 | ||||
| int mm_read_mtx_crd_entry(FILE *f, int *I, int *J, | ||||
|         double *real, double *imag, MM_typecode matcode) | ||||
| { | ||||
|     if (mm_is_complex(matcode)) | ||||
|     { | ||||
|             if (fscanf(f, "%d %d %lg %lg", I, J, real, imag) | ||||
|                 != 4) return MM_PREMATURE_EOF; | ||||
|     } | ||||
|     else if (mm_is_real(matcode)) | ||||
|     { | ||||
|             if (fscanf(f, "%d %d %lg\n", I, J, real) | ||||
|                 != 3) return MM_PREMATURE_EOF; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     else if (mm_is_pattern(matcode)) | ||||
|     { | ||||
|             if (fscanf(f, "%d %d", I, J) != 2) return MM_PREMATURE_EOF; | ||||
|     } | ||||
|     else | ||||
|         return MM_UNSUPPORTED_TYPE; | ||||
| 
 | ||||
|     return 0; | ||||
|          | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /************************************************************************
 | ||||
|     mm_read_mtx_crd()  fills M, N, nz, array of values, and return | ||||
|                         type code, e.g. 'MCRS' | ||||
| 
 | ||||
|                         if matrix is complex, values[] is of size 2*nz, | ||||
|                             (nz pairs of real/imaginary values) | ||||
| ************************************************************************/ | ||||
| 
 | ||||
| int mm_read_mtx_crd(char *fname, int *M, int *N, int *nz, int **I, int **J,  | ||||
|         double **val, MM_typecode *matcode) | ||||
| { | ||||
|     int ret_code; | ||||
|     FILE *f; | ||||
| 
 | ||||
|     if (strcmp(fname, "stdin") == 0) f=stdin; | ||||
|     else | ||||
|     if ((f = fopen(fname, "r")) == NULL) | ||||
|         return MM_COULD_NOT_READ_FILE; | ||||
| 
 | ||||
| 
 | ||||
|     if ((ret_code = mm_read_banner(f, matcode)) != 0) | ||||
|         return ret_code; | ||||
| 
 | ||||
|     if (!(mm_is_valid(*matcode) && mm_is_sparse(*matcode) &&  | ||||
|             mm_is_matrix(*matcode))) | ||||
|         return MM_UNSUPPORTED_TYPE; | ||||
| 
 | ||||
|     if ((ret_code = mm_read_mtx_crd_size(f, M, N, nz)) != 0) | ||||
|         return ret_code; | ||||
| 
 | ||||
| 
 | ||||
|     *I = (int *)  malloc(*nz * sizeof(int)); | ||||
|     *J = (int *)  malloc(*nz * sizeof(int)); | ||||
|     *val = NULL; | ||||
| 
 | ||||
|     if (mm_is_complex(*matcode)) | ||||
|     { | ||||
|         *val = (double *) malloc(*nz * 2 * sizeof(double)); | ||||
|         ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val,  | ||||
|                 *matcode); | ||||
|         if (ret_code != 0) return ret_code; | ||||
|     } | ||||
|     else if (mm_is_real(*matcode)) | ||||
|     { | ||||
|         *val = (double *) malloc(*nz * sizeof(double)); | ||||
|         ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val,  | ||||
|                 *matcode); | ||||
|         if (ret_code != 0) return ret_code; | ||||
|     } | ||||
| 
 | ||||
|     else if (mm_is_pattern(*matcode)) | ||||
|     { | ||||
|         ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val,  | ||||
|                 *matcode); | ||||
|         if (ret_code != 0) return ret_code; | ||||
|     } | ||||
| 
 | ||||
|     if (f != stdin) fclose(f); | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| int mm_write_banner(FILE *f, MM_typecode matcode) | ||||
| { | ||||
|     char *str = mm_typecode_to_str(matcode); | ||||
|     int ret_code; | ||||
| 
 | ||||
|     ret_code = fprintf(f, "%s %s\n", MatrixMarketBanner, str); | ||||
| /*    free(str);  This is a bug from the official distribution - KE fixed */ | ||||
|     if (ret_code < 0 ) | ||||
|         return MM_COULD_NOT_WRITE_FILE; | ||||
|     else | ||||
|         return 0; | ||||
| } | ||||
| 
 | ||||
| int mm_write_mtx_crd(char fname[], int M, int N, int nz, int I[], int J[], | ||||
|         double val[], MM_typecode matcode) | ||||
| { | ||||
|     FILE *f; | ||||
|     int i; | ||||
| 
 | ||||
|     if (strcmp(fname, "stdout") == 0)  | ||||
|         f = stdout; | ||||
|     else | ||||
|     if ((f = fopen(fname, "w")) == NULL) | ||||
|         return MM_COULD_NOT_WRITE_FILE; | ||||
|      | ||||
|     /* print banner followed by typecode */ | ||||
|     fprintf(f, "%s ", MatrixMarketBanner); | ||||
|     fprintf(f, "%s\n", mm_typecode_to_str(matcode)); | ||||
| 
 | ||||
|     /* print matrix sizes and nonzeros */ | ||||
|     fprintf(f, "%d %d %d\n", M, N, nz); | ||||
| 
 | ||||
|     /* print values */ | ||||
|     if (mm_is_pattern(matcode)) | ||||
|         for (i=0; i<nz; i++) | ||||
|             fprintf(f, "%d %d\n", I[i], J[i]); | ||||
|     else | ||||
|     if (mm_is_real(matcode)) | ||||
|         for (i=0; i<nz; i++) | ||||
|             fprintf(f, "%d %d %20.16g\n", I[i], J[i], val[i]); | ||||
|     else | ||||
|     if (mm_is_complex(matcode)) | ||||
|         for (i=0; i<nz; i++) | ||||
|             fprintf(f, "%d %d %20.16g %20.16g\n", I[i], J[i], val[2*i],  | ||||
|                         val[2*i+1]); | ||||
|     else | ||||
|     { | ||||
|         if (f != stdout) fclose(f); | ||||
|         return MM_UNSUPPORTED_TYPE; | ||||
|     } | ||||
| 
 | ||||
|     if (f !=stdout) fclose(f); | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
|      | ||||
| 
 | ||||
| char  *mm_typecode_to_str(MM_typecode matcode) | ||||
| { | ||||
|     static char buffer[MM_MAX_LINE_LENGTH]; | ||||
|     char *types[4]; | ||||
| 
 | ||||
|     /* check for MTX type */ | ||||
|     if (mm_is_matrix(matcode))  | ||||
|         types[0] = MM_MTX_STR; | ||||
|     else | ||||
|         return NULL; | ||||
| 
 | ||||
|     /* check for CRD or ARR matrix */ | ||||
|     if (mm_is_sparse(matcode)) | ||||
|         types[1] = MM_SPARSE_STR; | ||||
|     else | ||||
|     if (mm_is_dense(matcode)) | ||||
|         types[1] = MM_DENSE_STR; | ||||
|     else | ||||
|         return NULL; | ||||
| 
 | ||||
|     /* check for element data type */ | ||||
|     if (mm_is_real(matcode)) | ||||
|         types[2] = MM_REAL_STR; | ||||
|     else | ||||
|     if (mm_is_complex(matcode)) | ||||
|         types[2] = MM_COMPLEX_STR; | ||||
|     else | ||||
|     if (mm_is_pattern(matcode)) | ||||
|         types[2] = MM_PATTERN_STR; | ||||
|     else | ||||
|     if (mm_is_integer(matcode)) | ||||
|         types[2] = MM_INT_STR; | ||||
|     else | ||||
|         return NULL; | ||||
| 
 | ||||
| 
 | ||||
|     /* check for symmetry type */ | ||||
|     if (mm_is_general(matcode)) | ||||
|         types[3] = MM_GENERAL_STR; | ||||
|     else | ||||
|     if (mm_is_symmetric(matcode)) | ||||
|         types[3] = MM_SYMM_STR; | ||||
|     else  | ||||
|     if (mm_is_hermitian(matcode)) | ||||
|         types[3] = MM_HERM_STR; | ||||
|     else  | ||||
|     if (mm_is_skew(matcode)) | ||||
|         types[3] = MM_SKEW_STR; | ||||
|     else | ||||
|         return NULL; | ||||
| 
 | ||||
|     sprintf(buffer,"%s %s %s %s", types[0], types[1], types[2], types[3]); | ||||
|     return & buffer[0]; | ||||
| 
 | ||||
| } | ||||
|  | @ -1,133 +0,0 @@ | |||
| /*
 | ||||
| *   Matrix Market I/O library for ANSI C | ||||
| * | ||||
| *   See http://math.nist.gov/MatrixMarket for details.
 | ||||
| * | ||||
| * | ||||
| */ | ||||
| 
 | ||||
| #ifndef MM_IO_H | ||||
| #define MM_IO_H | ||||
| 
 | ||||
| #define MM_MAX_LINE_LENGTH 1025 | ||||
| #define MatrixMarketBanner "%%MatrixMarket" | ||||
| #define MM_MAX_TOKEN_LENGTH 64 | ||||
| 
 | ||||
| typedef char MM_typecode[4]; | ||||
| 
 | ||||
| char *mm_typecode_to_str(MM_typecode matcode); | ||||
| 
 | ||||
| int mm_read_banner(FILE *f, MM_typecode *matcode); | ||||
| int mm_read_mtx_crd_size(FILE *f, int *M, int *N, int *nz); | ||||
| int mm_read_mtx_array_size(FILE *f, int *M, int *N); | ||||
| 
 | ||||
| int mm_write_banner(FILE *f, MM_typecode matcode); | ||||
| int mm_write_mtx_crd_size(FILE *f, int M, int N, int nz); | ||||
| int mm_write_mtx_array_size(FILE *f, int M, int N); | ||||
| 
 | ||||
| 
 | ||||
| /********************* MM_typecode query fucntions ***************************/ | ||||
| 
 | ||||
| #define mm_is_matrix(typecode)  ((typecode)[0]=='M') | ||||
| 
 | ||||
| #define mm_is_sparse(typecode)  ((typecode)[1]=='C') | ||||
| #define mm_is_coordinate(typecode)((typecode)[1]=='C') | ||||
| #define mm_is_dense(typecode) ((typecode)[1]=='A') | ||||
| #define mm_is_array(typecode) ((typecode)[1]=='A') | ||||
| 
 | ||||
| #define mm_is_complex(typecode) ((typecode)[2]=='C') | ||||
| #define mm_is_real(typecode)    ((typecode)[2]=='R') | ||||
| #define mm_is_pattern(typecode) ((typecode)[2]=='P') | ||||
| #define mm_is_integer(typecode) ((typecode)[2]=='I') | ||||
| 
 | ||||
| #define mm_is_symmetric(typecode)((typecode)[3]=='S') | ||||
| #define mm_is_general(typecode) ((typecode)[3]=='G') | ||||
| #define mm_is_skew(typecode)  ((typecode)[3]=='K') | ||||
| #define mm_is_hermitian(typecode)((typecode)[3]=='H') | ||||
| 
 | ||||
| int mm_is_valid(MM_typecode matcode);   /* too complex for a macro */ | ||||
| 
 | ||||
| 
 | ||||
| /********************* MM_typecode modify fucntions ***************************/ | ||||
| 
 | ||||
| #define mm_set_matrix(typecode) ((*typecode)[0]='M') | ||||
| #define mm_set_coordinate(typecode) ((*typecode)[1]='C') | ||||
| #define mm_set_array(typecode)  ((*typecode)[1]='A') | ||||
| #define mm_set_dense(typecode)  mm_set_array(typecode) | ||||
| #define mm_set_sparse(typecode) mm_set_coordinate(typecode) | ||||
| 
 | ||||
| #define mm_set_complex(typecode)((*typecode)[2]='C') | ||||
| #define mm_set_real(typecode) ((*typecode)[2]='R') | ||||
| #define mm_set_pattern(typecode)((*typecode)[2]='P') | ||||
| #define mm_set_integer(typecode)((*typecode)[2]='I') | ||||
| 
 | ||||
| 
 | ||||
| #define mm_set_symmetric(typecode)((*typecode)[3]='S') | ||||
| #define mm_set_general(typecode)((*typecode)[3]='G') | ||||
| #define mm_set_skew(typecode) ((*typecode)[3]='K') | ||||
| #define mm_set_hermitian(typecode)((*typecode)[3]='H') | ||||
| 
 | ||||
| #define mm_clear_typecode(typecode) ((*typecode)[0]=(*typecode)[1]= \ | ||||
|                   (*typecode)[2]=' ',(*typecode)[3]='G') | ||||
| 
 | ||||
| #define mm_initialize_typecode(typecode) mm_clear_typecode(typecode) | ||||
| 
 | ||||
| 
 | ||||
| /********************* Matrix Market error codes ***************************/ | ||||
| 
 | ||||
| 
 | ||||
| #define MM_COULD_NOT_READ_FILE  11 | ||||
| #define MM_PREMATURE_EOF        12 | ||||
| #define MM_NOT_MTX              13 | ||||
| #define MM_NO_HEADER            14 | ||||
| #define MM_UNSUPPORTED_TYPE     15 | ||||
| #define MM_LINE_TOO_LONG        16 | ||||
| #define MM_COULD_NOT_WRITE_FILE 17 | ||||
| 
 | ||||
| 
 | ||||
| /******************** Matrix Market internal definitions ********************
 | ||||
| 
 | ||||
|    MM_matrix_typecode: 4-character sequence | ||||
| 
 | ||||
|             ojbect    sparse/     data        storage | ||||
|                   dense       type        scheme | ||||
| 
 | ||||
|    string position:  [0]        [1]     [2]         [3] | ||||
| 
 | ||||
|    Matrix typecode:  M(atrix)  C(oord)    R(eal)    G(eneral) | ||||
|                     A(array)  C(omplex)   H(ermitian) | ||||
|                       P(attern)   S(ymmetric) | ||||
|                         I(nteger) K(kew) | ||||
| 
 | ||||
|  ***********************************************************************/ | ||||
| 
 | ||||
| #define MM_MTX_STR    "matrix" | ||||
| #define MM_ARRAY_STR  "array" | ||||
| #define MM_DENSE_STR  "array" | ||||
| #define MM_COORDINATE_STR "coordinate" | ||||
| #define MM_SPARSE_STR "coordinate" | ||||
| #define MM_COMPLEX_STR  "complex" | ||||
| #define MM_REAL_STR   "real" | ||||
| #define MM_INT_STR    "integer" | ||||
| #define MM_GENERAL_STR  "general" | ||||
| #define MM_SYMM_STR   "symmetric" | ||||
| #define MM_HERM_STR   "hermitian" | ||||
| #define MM_SKEW_STR   "skew-symmetric" | ||||
| #define MM_PATTERN_STR  "pattern" | ||||
| 
 | ||||
| 
 | ||||
| /*  high level routines */ | ||||
| 
 | ||||
| int mm_write_mtx_crd(char fname[], int M, int N, int nz, int I[], int J[], | ||||
|      double val[], MM_typecode matcode); | ||||
| int mm_read_mtx_crd_data(FILE *f, int M, int N, int nz, int I[], int J[], | ||||
|     double val[], MM_typecode matcode); | ||||
| int mm_read_mtx_crd_entry(FILE *f, int *I, int *J, double *real, double *img, | ||||
|       MM_typecode matcode); | ||||
| 
 | ||||
| int mm_read_unsymmetric_sparse(const char *fname, int *M_, int *N_, int *nz_, | ||||
|                 double **val_, int **I_, int **J_); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| #endif | ||||
|  | @ -1,849 +0,0 @@ | |||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| /*#include <memory.h>*/ | ||||
| #include <string.h> | ||||
| #include <math.h> | ||||
| #include "myblas.h" | ||||
| 
 | ||||
| #ifdef FORTIFY | ||||
| # include "lp_fortify.h" | ||||
| #endif | ||||
| 
 | ||||
| /* ************************************************************************ */ | ||||
| /* Initialize BLAS interfacing routines                                     */ | ||||
| /* ************************************************************************ */ | ||||
| MYBOOL mustinitBLAS = TRUE; | ||||
| #if (defined WIN32) || (defined WIN64) | ||||
|   HINSTANCE hBLAS = NULL; | ||||
| #else | ||||
|   void     *hBLAS = NULL; | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /* ************************************************************************ */ | ||||
| /* Function pointers for external BLAS library (C base 0)                   */ | ||||
| /* ************************************************************************ */ | ||||
| BLAS_dscal_func  *BLAS_dscal; | ||||
| BLAS_dcopy_func  *BLAS_dcopy; | ||||
| BLAS_daxpy_func  *BLAS_daxpy; | ||||
| BLAS_dswap_func  *BLAS_dswap; | ||||
| BLAS_ddot_func   *BLAS_ddot; | ||||
| BLAS_idamax_func *BLAS_idamax; | ||||
| BLAS_idamin_func *BLAS_idamin; | ||||
| BLAS_dload_func  *BLAS_dload; | ||||
| BLAS_dnormi_func *BLAS_dnormi; | ||||
| 
 | ||||
| 
 | ||||
| /* ************************************************************************ */ | ||||
| /* Define the BLAS interfacing routines                                     */ | ||||
| /* ************************************************************************ */ | ||||
| 
 | ||||
| void init_BLAS(void) | ||||
| { | ||||
|   if(mustinitBLAS) { | ||||
|     load_BLAS(NULL); | ||||
|     mustinitBLAS = FALSE; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| MYBOOL is_nativeBLAS(void) | ||||
| { | ||||
| #ifdef LoadableBlasLib | ||||
|   return( (MYBOOL) (hBLAS == NULL) ); | ||||
| #else | ||||
|   return( TRUE ); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| MYBOOL load_BLAS(char *libname) | ||||
| { | ||||
|   MYBOOL result = TRUE; | ||||
| 
 | ||||
| #ifdef LoadableBlasLib | ||||
|   if(hBLAS != NULL) { | ||||
|     my_FreeLibrary(hBLAS); | ||||
|   } | ||||
| #endif | ||||
| 
 | ||||
|   if(libname == NULL) { | ||||
|     if(!mustinitBLAS && is_nativeBLAS()) | ||||
|       return( FALSE ); | ||||
|     BLAS_dscal = my_dscal; | ||||
|     BLAS_dcopy = my_dcopy; | ||||
|     BLAS_daxpy = my_daxpy; | ||||
|     BLAS_dswap = my_dswap; | ||||
|     BLAS_ddot  = my_ddot; | ||||
|     BLAS_idamax = my_idamax; | ||||
|     BLAS_idamin = my_idamin; | ||||
|     BLAS_dload = my_dload; | ||||
|     BLAS_dnormi = my_dnormi; | ||||
|     if(mustinitBLAS) | ||||
|       mustinitBLAS = FALSE; | ||||
|   } | ||||
|   else { | ||||
| #ifdef LoadableBlasLib | ||||
|   #if (defined WIN32) || (defined WIN64) | ||||
|     char *blasname = libname; | ||||
|   #else | ||||
|    /* First standardize UNIX .SO library name format. */ | ||||
|     char blasname[260]; | ||||
|     if(!so_stdname(blasname, libname, 260)) | ||||
|       return( FALSE ); | ||||
|   #endif | ||||
|    /* Get a handle to the Windows DLL module. */ | ||||
|     hBLAS = my_LoadLibrary(blasname); | ||||
| 
 | ||||
|    /* If the handle is valid, try to get the function addresses. */ | ||||
|     result = (MYBOOL) (hBLAS != NULL); | ||||
|     if(result) { | ||||
|       BLAS_dscal  = (BLAS_dscal_func *)  my_GetProcAddress(hBLAS, BLAS_prec "scal"); | ||||
|       BLAS_dcopy  = (BLAS_dcopy_func *)  my_GetProcAddress(hBLAS, BLAS_prec "copy"); | ||||
|       BLAS_daxpy  = (BLAS_daxpy_func *)  my_GetProcAddress(hBLAS, BLAS_prec "axpy"); | ||||
|       BLAS_dswap  = (BLAS_dswap_func *)  my_GetProcAddress(hBLAS, BLAS_prec "swap"); | ||||
|       BLAS_ddot   = (BLAS_ddot_func *)   my_GetProcAddress(hBLAS, BLAS_prec "dot"); | ||||
|       BLAS_idamax = (BLAS_idamax_func *) my_GetProcAddress(hBLAS, "i" BLAS_prec "amax"); | ||||
|       BLAS_idamin = (BLAS_idamin_func *) my_GetProcAddress(hBLAS, "i" BLAS_prec "amin"); | ||||
| #if 0      
 | ||||
|       BLAS_dload  = (BLAS_dload_func *)  my_GetProcAddress(hBLAS, BLAS_prec "load"); | ||||
|       BLAS_dnormi = (BLAS_dnormi_func *) my_GetProcAddress(hBLAS, BLAS_prec "normi"); | ||||
| #endif       | ||||
|     } | ||||
| #endif | ||||
|     /* Do validation */ | ||||
|     if(!result || | ||||
|        ((BLAS_dscal  == NULL) || | ||||
|         (BLAS_dcopy  == NULL) || | ||||
|         (BLAS_daxpy  == NULL) || | ||||
|         (BLAS_dswap  == NULL) || | ||||
|         (BLAS_ddot   == NULL) || | ||||
|         (BLAS_idamax == NULL) || | ||||
|         (BLAS_idamin == NULL) || | ||||
|         (BLAS_dload  == NULL) || | ||||
|         (BLAS_dnormi == NULL)) | ||||
|       ) { | ||||
|       load_BLAS(NULL); | ||||
|       result = FALSE; | ||||
|     } | ||||
|   } | ||||
|   return( result ); | ||||
| } | ||||
| MYBOOL unload_BLAS(void) | ||||
| { | ||||
|   return( load_BLAS(NULL) ); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* ************************************************************************ */ | ||||
| /* Now define the unoptimized local BLAS functions                          */ | ||||
| /* ************************************************************************ */ | ||||
| void daxpy( int n, REAL da, REAL *dx, int incx, REAL *dy, int incy) | ||||
| { | ||||
|   dx++; | ||||
|   dy++; | ||||
|   BLAS_daxpy( &n, &da, dx, &incx, dy, &incy); | ||||
| } | ||||
| void BLAS_CALLMODEL my_daxpy( int *_n, REAL *_da, REAL *dx, int *_incx, REAL *dy, int *_incy) | ||||
| { | ||||
| 
 | ||||
| /* constant times a vector plus a vector.
 | ||||
|    uses unrolled loops for increments equal to one. | ||||
|    jack dongarra, linpack, 3/11/78. | ||||
|    modified 12/3/93, array[1] declarations changed to array[*] */ | ||||
| 
 | ||||
|   int      i, ix, iy;  | ||||
| #ifndef DOFASTMATH | ||||
|   int      m, mp1; | ||||
| #endif | ||||
|   register REAL rda; | ||||
|   REAL     da = *_da; | ||||
|   int      n = *_n, incx = *_incx, incy = *_incy; | ||||
| 
 | ||||
|   if (n <= 0) return; | ||||
|   if (da == 0.0) return; | ||||
| 
 | ||||
|   dx--; | ||||
|   dy--; | ||||
|   ix = 1; | ||||
|   iy = 1; | ||||
|   if (incx < 0) | ||||
|      ix = (-n+1)*incx + 1; | ||||
|   if (incy < 0) | ||||
|      iy = (-n+1)*incy + 1; | ||||
|   rda = da; | ||||
| 
 | ||||
| /* CPU intensive loop; option to do pointer arithmetic */ | ||||
| #if defined DOFASTMATH | ||||
|   { | ||||
|     REAL *xptr, *yptr; | ||||
|     for (i = 1, xptr = dx + ix, yptr = dy + iy; | ||||
|          i <= n; i++, xptr += incx, yptr += incy) | ||||
|       (*yptr) += rda*(*xptr); | ||||
|   } | ||||
| #else | ||||
| 
 | ||||
|   if (incx==1 && incy==1) goto x20; | ||||
| 
 | ||||
| /* code for unequal increments or equal increments not equal to 1 */ | ||||
|   for (i = 1; i<=n; i++) { | ||||
|      dy[iy]+= rda*dx[ix]; | ||||
|      ix+= incx; | ||||
|      iy+= incy; | ||||
|   } | ||||
|   return; | ||||
| 
 | ||||
| /*  code for both increments equal to 1 */ | ||||
| 
 | ||||
| /*  clean-up loop */ | ||||
| x20: | ||||
|   m = n % 4; | ||||
|   if (m == 0) goto x40; | ||||
|   for (i = 1; i<=m; i++) | ||||
|      dy[i]+= rda*dx[i]; | ||||
|   if(n < 4) return; | ||||
| x40: | ||||
|   mp1 = m + 1; | ||||
|   for (i = mp1; i<=n; i=i+4) { | ||||
|     dy[i]+= rda*dx[i]; | ||||
|     dy[i + 1]+= rda*dx[i + 1]; | ||||
|     dy[i + 2]+= rda*dx[i + 2]; | ||||
|     dy[i + 3]+= rda*dx[i + 3]; | ||||
|   } | ||||
| #endif   | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* ************************************************************************ */ | ||||
| void dcopy( int n, REAL *dx, int incx, REAL *dy, int incy) | ||||
| { | ||||
|   dx++; | ||||
|   dy++; | ||||
|   BLAS_dcopy( &n, dx, &incx, dy, &incy); | ||||
| } | ||||
| 
 | ||||
| void BLAS_CALLMODEL my_dcopy (int *_n, REAL *dx, int *_incx, REAL *dy, int *_incy) | ||||
| { | ||||
| 
 | ||||
| /* copies a vector, x, to a vector, y.
 | ||||
|    uses unrolled loops for increments equal to one. | ||||
|    jack dongarra, linpack, 3/11/78. | ||||
|    modified 12/3/93, array[1] declarations changed to array[*] */ | ||||
| 
 | ||||
|   int      i, ix, iy; | ||||
| #ifndef DOFASTMATH | ||||
|   int      m, mp1; | ||||
| #endif | ||||
|   int      n = *_n, incx = *_incx, incy = *_incy; | ||||
| 
 | ||||
|   if(n<=0)  | ||||
|     return; | ||||
| 
 | ||||
|   dx--; | ||||
|   dy--; | ||||
|   ix = 1; | ||||
|   iy = 1; | ||||
|   if(incx<0) | ||||
|     ix = (-n+1)*incx + 1; | ||||
|   if(incy<0) | ||||
|     iy = (-n+1)*incy + 1; | ||||
| 
 | ||||
| 
 | ||||
| /* CPU intensive loop; option to do pointer arithmetic */ | ||||
| #if defined DOFASTMATH | ||||
|   { | ||||
|     REAL *xptr, *yptr; | ||||
|     for (i = 1, xptr = dx + ix, yptr = dy + iy; | ||||
|          i <= n; i++, xptr += incx, yptr += incy) | ||||
|       (*yptr) = (*xptr); | ||||
|   } | ||||
| #else | ||||
| 
 | ||||
|   if(incx==1 && incy==1)  | ||||
|     goto x20; | ||||
| 
 | ||||
| /* code for unequal increments or equal increments not equal to 1 */ | ||||
| 
 | ||||
|   for(i = 1; i<=n; i++) { | ||||
|     dy[iy] = dx[ix]; | ||||
|     ix+= incx; | ||||
|     iy+= incy; | ||||
|   } | ||||
|   return; | ||||
| 
 | ||||
| /* code for both increments equal to 1 */ | ||||
| 
 | ||||
| /* version with fast machine copy logic (requires memory.h or string.h) */ | ||||
| x20: | ||||
|   m = n % 7; | ||||
|   if (m == 0) goto x40; | ||||
|   for (i = 1; i<=m; i++) | ||||
|      dy[i] = dx[i]; | ||||
|   if (n < 7) return; | ||||
| 
 | ||||
| x40: | ||||
|   mp1 = m + 1; | ||||
|   for (i = mp1; i<=n; i=i+7) { | ||||
|      dy[i] = dx[i]; | ||||
|      dy[i + 1] = dx[i + 1]; | ||||
|      dy[i + 2] = dx[i + 2]; | ||||
|      dy[i + 3] = dx[i + 3]; | ||||
|      dy[i + 4] = dx[i + 4]; | ||||
|      dy[i + 5] = dx[i + 5]; | ||||
|      dy[i + 6] = dx[i + 6]; | ||||
|   } | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* ************************************************************************ */ | ||||
| 
 | ||||
| void dscal (int n, REAL da, REAL *dx, int incx) | ||||
| { | ||||
|   dx++; | ||||
|   BLAS_dscal (&n, &da, dx, &incx); | ||||
| } | ||||
| 
 | ||||
| void BLAS_CALLMODEL my_dscal (int *_n, REAL *_da, REAL *dx, int *_incx) | ||||
| { | ||||
| 
 | ||||
| /* Multiply a vector by a constant.
 | ||||
| 
 | ||||
|      --Input-- | ||||
|         N  number of elements in input vector(s) | ||||
|        DA  double precision scale factor | ||||
|        DX  double precision vector with N elements | ||||
|      INCX  storage spacing between elements of DX | ||||
| 
 | ||||
|      --Output-- | ||||
|        DX  double precision result (unchanged if N.LE.0) | ||||
| 
 | ||||
|      Replace double precision DX by double precision DA*DX. | ||||
|      For I = 0 to N-1, replace DX(IX+I*INCX) with  DA * DX(IX+I*INCX), | ||||
|      where IX = 1 if INCX .GE. 0, else IX = 1+(1-N)*INCX. */ | ||||
| 
 | ||||
|   int      i; | ||||
| #ifndef DOFASTMATH | ||||
|   int      m, mp1, ix; | ||||
| #endif | ||||
|   register REAL rda; | ||||
|   REAL      da = *_da; | ||||
|   int      n = *_n, incx = *_incx; | ||||
| 
 | ||||
|   if (n <= 0) | ||||
|     return; | ||||
|   rda = da;   | ||||
|    | ||||
|   dx--; | ||||
| 
 | ||||
| /* Optionally do fast pointer arithmetic */ | ||||
| #if defined DOFASTMATH | ||||
|   { | ||||
|     REAL *xptr; | ||||
|     for (i = 1, xptr = dx + 1; i <= n; i++, xptr += incx) | ||||
|       (*xptr) *= rda; | ||||
|   } | ||||
| #else | ||||
| 
 | ||||
|   if (incx == 1) | ||||
|     goto x20; | ||||
| 
 | ||||
| /* Code for increment not equal to 1 */ | ||||
|   ix = 1; | ||||
|   if (incx < 0) | ||||
|     ix = (-n+1)*incx + 1; | ||||
|   for(i = 1; i <= n; i++, ix += incx) | ||||
|     dx[ix] *= rda; | ||||
|   return; | ||||
| 
 | ||||
| /* Code for increment equal to 1. */ | ||||
| /* Clean-up loop so remaining vector length is a multiple of 5. */ | ||||
| x20: | ||||
|   m = n % 5; | ||||
|   if (m == 0) goto x40; | ||||
|   for( i = 1; i <= m; i++) | ||||
|     dx[i] *= rda; | ||||
|   if (n < 5) | ||||
|     return; | ||||
| x40: | ||||
|   mp1 = m + 1; | ||||
|   for(i = mp1; i <= n; i += 5) { | ||||
|     dx[i]   *= rda; | ||||
|     dx[i+1] *= rda; | ||||
|     dx[i+2] *= rda; | ||||
|     dx[i+3] *= rda; | ||||
|     dx[i+4] *= rda; | ||||
|   } | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* ************************************************************************ */ | ||||
| 
 | ||||
| REAL ddot(int n, REAL *dx, int incx, REAL *dy, int incy) | ||||
| { | ||||
|   dx++; | ||||
|   dy++; | ||||
|   return( BLAS_ddot (&n, dx, &incx, dy, &incy) ); | ||||
| } | ||||
| 
 | ||||
| REAL BLAS_CALLMODEL my_ddot(int *_n, REAL *dx, int *_incx, REAL *dy, int *_incy) | ||||
| { | ||||
| 
 | ||||
| /* forms the dot product of two vectors.
 | ||||
|    uses unrolled loops for increments equal to one. | ||||
|    jack dongarra, linpack, 3/11/78. | ||||
|    modified 12/3/93, array[1] declarations changed to array[*] */ | ||||
| 
 | ||||
|   register REAL dtemp; | ||||
|   int      i, ix, iy; | ||||
| #ifndef DOFASTMATH | ||||
|   int      m, mp1; | ||||
| #endif | ||||
|   int      n = *_n, incx = *_incx, incy = *_incy; | ||||
| 
 | ||||
|   dtemp = 0.0; | ||||
|   if (n<=0) | ||||
|     return( (REAL) dtemp); | ||||
| 
 | ||||
|   dx--; | ||||
|   dy--; | ||||
|   ix = 1; | ||||
|   iy = 1; | ||||
|   if (incx<0) | ||||
|      ix = (-n+1)*incx + 1; | ||||
|   if (incy<0) | ||||
|      iy = (-n+1)*incy + 1; | ||||
| 
 | ||||
| /* CPU intensive loop; option to do pointer arithmetic */ | ||||
| 
 | ||||
| #if defined DOFASTMATH | ||||
|   { | ||||
|     REAL *xptr, *yptr; | ||||
|     for (i = 1, xptr = dx + ix, yptr = dy + iy; | ||||
|          i <= n; i++, xptr += incx, yptr += incy) | ||||
|       dtemp+= (*yptr)*(*xptr); | ||||
|   } | ||||
| #else | ||||
| 
 | ||||
|   if (incx==1 && incy==1) goto x20; | ||||
| 
 | ||||
| /* code for unequal increments or equal increments not equal to 1 */ | ||||
| 
 | ||||
|   for (i = 1; i<=n; i++) { | ||||
|      dtemp+= dx[ix]*dy[iy]; | ||||
|      ix+= incx; | ||||
|      iy+= incy; | ||||
|   } | ||||
|   return(dtemp); | ||||
| 
 | ||||
| /* code for both increments equal to 1 */ | ||||
| 
 | ||||
| /* clean-up loop */ | ||||
| 
 | ||||
| x20: | ||||
|   m = n % 5; | ||||
|   if (m == 0) goto x40; | ||||
|   for (i = 1; i<=m; i++) | ||||
|      dtemp+= dx[i]*dy[i]; | ||||
|   if (n < 5) goto x60; | ||||
| 
 | ||||
| x40: | ||||
|   mp1 = m + 1; | ||||
|   for (i = mp1; i<=n; i=i+5) | ||||
|      dtemp+= dx[i]*dy[i] + dx[i + 1]*dy[i + 1] + | ||||
|              dx[i + 2]*dy[i + 2] + dx[i + 3]*dy[i + 3] + dx[i + 4]*dy[i + 4]; | ||||
| 
 | ||||
| x60: | ||||
| #endif | ||||
|   return(dtemp); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* ************************************************************************ */ | ||||
| 
 | ||||
| void dswap( int n, REAL *dx, int incx, REAL *dy, int incy ) | ||||
| { | ||||
|   dx++; | ||||
|   dy++; | ||||
|   BLAS_dswap( &n, dx, &incx, dy, &incy ); | ||||
| } | ||||
| 
 | ||||
| void BLAS_CALLMODEL my_dswap( int *_n, REAL *dx, int *_incx, REAL *dy, int *_incy ) | ||||
| { | ||||
|   int   i, ix, iy; | ||||
| #ifndef DOFASTMATH | ||||
|   int   m, mp1, ns; | ||||
|   REAL  dtemp2, dtemp3; | ||||
| #endif | ||||
|   register REAL  dtemp1; | ||||
|   int   n = *_n, incx = *_incx, incy = *_incy; | ||||
| 
 | ||||
|   if (n <= 0) return; | ||||
| 
 | ||||
|   dx--; | ||||
|   dy--; | ||||
|   ix = 1; | ||||
|   iy = 1; | ||||
|   if (incx < 0) | ||||
|     ix = (-n+1)*incx + 1; | ||||
|   if (incy < 0) | ||||
|     iy = (-n+1)*incy + 1; | ||||
| 
 | ||||
| /* CPU intensive loop; option to do pointer arithmetic */ | ||||
| #if defined DOFASTMATH | ||||
|   { | ||||
|     REAL *xptr, *yptr; | ||||
|     for (i = 1, xptr = dx + ix, yptr = dy + iy; | ||||
|          i <= n; i++, xptr += incx, yptr += incy) { | ||||
|       dtemp1 = (*xptr); | ||||
|      (*xptr) = (*yptr); | ||||
|      (*yptr) = dtemp1; | ||||
|     } | ||||
|   } | ||||
| #else | ||||
| 
 | ||||
|   if (incx == incy) { | ||||
|     if (incx <= 0) goto x5; | ||||
|     if (incx == 1) goto x20; | ||||
|     goto x60; | ||||
|   } | ||||
| 
 | ||||
| /* code for unequal or nonpositive increments. */ | ||||
| x5: | ||||
|   for (i = 1; i<=n; i++) { | ||||
|      dtemp1 = dx[ix]; | ||||
|      dx[ix] = dy[iy]; | ||||
|      dy[iy] = dtemp1; | ||||
|      ix+= incx; | ||||
|      iy+= incy; | ||||
|   } | ||||
|   return; | ||||
| 
 | ||||
| /* code for both increments equal to 1.
 | ||||
|    clean-up loop so remaining vector length is a multiple of 3. */ | ||||
| x20: | ||||
|   m = n % 3; | ||||
|   if (m == 0) goto x40; | ||||
|   for (i = 1; i<=m; i++) { | ||||
|      dtemp1 = dx[i]; | ||||
|      dx[i] = dy[i]; | ||||
|      dy[i] = dtemp1; | ||||
|   } | ||||
|   if (n < 3) return; | ||||
| 
 | ||||
| x40: | ||||
|   mp1 = m + 1; | ||||
|   for (i = mp1; i<=n; i=i+3) { | ||||
|      dtemp1 = dx[i]; | ||||
|      dtemp2 = dx[i+1]; | ||||
|      dtemp3 = dx[i+2]; | ||||
|      dx[i] = dy[i]; | ||||
|      dx[i+1] = dy[i+1]; | ||||
|      dx[i+2] = dy[i+2]; | ||||
|      dy[i] = dtemp1; | ||||
|      dy[i+1] = dtemp2; | ||||
|      dy[i+2] = dtemp3; | ||||
|   } | ||||
|   return; | ||||
| 
 | ||||
| /* code for equal, positive, non-unit increments. */ | ||||
| x60: | ||||
|   ns = n*incx; | ||||
|   for (i = 1; i<=ns; i=i+incx) { | ||||
|      dtemp1 = dx[i]; | ||||
|      dx[i] = dy[i]; | ||||
|      dy[i] = dtemp1; | ||||
|   } | ||||
| #endif | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* ************************************************************************ */ | ||||
| 
 | ||||
| void dload(int n, REAL da, REAL *dx, int incx) | ||||
| { | ||||
|   dx++; | ||||
|   BLAS_dload (&n, &da, dx, &incx); | ||||
| } | ||||
| 
 | ||||
| void BLAS_CALLMODEL my_dload (int *_n, REAL *_da, REAL *dx, int *_incx) | ||||
| { | ||||
| /* copies a scalar, a, to a vector, x.
 | ||||
|    uses unrolled loops when incx equals one. | ||||
| 
 | ||||
|    To change the precision of this program, run the change | ||||
|    program on dload.f | ||||
|    Alternatively, to make a single precision version append a | ||||
|    comment character to the start of all lines between sequential | ||||
|       precision > double | ||||
|    and | ||||
|       end precision > double | ||||
|    comments and delete the comment character at the start of all | ||||
|    lines between sequential | ||||
|       precision > single | ||||
|    and | ||||
|       end precision > single | ||||
|    comments.  To make a double precision version interchange | ||||
|     the append and delete operations in these instructions. */ | ||||
| 
 | ||||
|   int    i, ix, m, mp1; | ||||
|   REAL   da = *_da; | ||||
|   int    n = *_n, incx = *_incx; | ||||
| 
 | ||||
|   if (n<=0) return; | ||||
|   dx--; | ||||
|   if (incx==1) goto x20; | ||||
| 
 | ||||
| /* code for incx not equal to 1 */ | ||||
| 
 | ||||
|   ix = 1; | ||||
|   if (incx<0) | ||||
|      ix = (-n+1)*incx + 1; | ||||
|   for (i = 1; i<=n; i++) { | ||||
|      dx[ix] = da; | ||||
|      ix+= incx; | ||||
|   } | ||||
|   return; | ||||
| 
 | ||||
| /* code for incx equal to 1 and clean-up loop */ | ||||
| 
 | ||||
| x20: | ||||
|   m = n % 7; | ||||
|   if (m == 0) goto x40; | ||||
|   for (i = 1; i<=m; i++) | ||||
|      dx[i] = da; | ||||
|   if (n < 7) return; | ||||
| 
 | ||||
| x40: | ||||
|   mp1 = m + 1; | ||||
|   for (i = mp1; i<=n; i=i+7) { | ||||
|      dx[i] = da; | ||||
|      dx[i + 1] = da; | ||||
|      dx[i + 2] = da; | ||||
|      dx[i + 3] = da; | ||||
|      dx[i + 4] = da; | ||||
|      dx[i + 5] = da; | ||||
|      dx[i + 6] = da; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /* ************************************************************************ */ | ||||
| int idamax( int n, REAL *x, int is ) | ||||
| { | ||||
|   x++; | ||||
|   return ( BLAS_idamax( &n, x, &is ) ); | ||||
| } | ||||
| 
 | ||||
| int idamin( int n, REAL *x, int is ) | ||||
| { | ||||
|   x++; | ||||
|   return ( BLAS_idamin( &n, x, &is ) ); | ||||
| } | ||||
| 
 | ||||
| int BLAS_CALLMODEL my_idamax( int *_n, REAL *x, int *_is ) | ||||
| { | ||||
|   register REAL xmax, xtest; | ||||
|   int    i, imax = 0; | ||||
| #if !defined DOFASTMATH | ||||
|   int    ii; | ||||
| #endif | ||||
|   int    n = *_n, is = *_is; | ||||
| 
 | ||||
|   if((n < 1) || (is <= 0)) | ||||
|     return(imax); | ||||
|   imax = 1; | ||||
|   if(n == 1) | ||||
|     return(imax); | ||||
| 
 | ||||
| #if defined DOFASTMATH | ||||
|   xmax = fabs(*x); | ||||
|   for (i = 2, x += is; i <= n; i++, x += is) { | ||||
|     xtest = fabs(*x); | ||||
|     if(xtest > xmax) { | ||||
|       xmax = xtest; | ||||
|       imax = i; | ||||
|     } | ||||
|   } | ||||
| #else | ||||
|   x--; | ||||
|   ii = 1; | ||||
|   xmax = fabs(x[ii]); | ||||
|   for(i = 2, ii+ = is; i <= n; i++, ii+ = is) { | ||||
|     xtest = fabs(x[ii]); | ||||
|     if(xtest > xmax) { | ||||
|       xmax = xtest; | ||||
|       imax = i; | ||||
|     } | ||||
|   } | ||||
| #endif   | ||||
|   return(imax); | ||||
| } | ||||
| 
 | ||||
| int BLAS_CALLMODEL my_idamin( int *_n, REAL *x, int *_is ) | ||||
| { | ||||
|   register REAL xmin, xtest; | ||||
|   int    i, imin = 0; | ||||
| #if !defined DOFASTMATH | ||||
|   int    ii; | ||||
| #endif | ||||
|   int    n = *_n, is = *_is; | ||||
| 
 | ||||
|   if((n < 1) || (is <= 0)) | ||||
|     return(imin); | ||||
|   imin = 1; | ||||
|   if(n == 1) | ||||
|     return(imin); | ||||
| 
 | ||||
| #if defined DOFASTMATH | ||||
|   xmin = fabs(*x); | ||||
|   for (i = 2, x += is; i <= n; i++, x += is) { | ||||
|     xtest = fabs(*x); | ||||
|     if(xtest < xmin) { | ||||
|       xmin = xtest; | ||||
|       imin = i; | ||||
|     } | ||||
|   } | ||||
| #else | ||||
|   x--; | ||||
|   ii = 1; | ||||
|   xmin = fabs(x[ii]); | ||||
|   for(i = 2, ii+ = is; i <= n; i++, ii+ = is) { | ||||
|     xtest = fabs(x[ii]); | ||||
|     if(xtest < xmin) { | ||||
|       xmin = xtest; | ||||
|       imin = i; | ||||
|     } | ||||
|   } | ||||
| #endif   | ||||
|   return(imin); | ||||
| } | ||||
| 
 | ||||
| /* ************************************************************************ */ | ||||
| REAL dnormi( int n, REAL *x ) | ||||
| { | ||||
|   x++; | ||||
|   return( BLAS_dnormi( &n, x ) ); | ||||
| } | ||||
| 
 | ||||
| REAL BLAS_CALLMODEL my_dnormi( int *_n, REAL *x ) | ||||
| { | ||||
| /* ===============================================================
 | ||||
|    dnormi  returns the infinity-norm of the vector x. | ||||
|    =============================================================== */ | ||||
|    int      j; | ||||
|    register REAL hold, absval; | ||||
|    int      n = *_n; | ||||
| 
 | ||||
|    x--; | ||||
|    hold = 0.0; | ||||
| /*   for(j = 1; j <= n; j++) */ | ||||
|    for(j = n; j > 0; j--) { | ||||
|      absval = fabs(x[j]); | ||||
|      hold = MAX( hold, absval ); | ||||
|    } | ||||
| 
 | ||||
|    return( hold ); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* ************************************************************************ */ | ||||
| /* Subvector and submatrix access routines (Fortran compatibility)          */ | ||||
| /* ************************************************************************ */ | ||||
| 
 | ||||
| #ifndef UseMacroVector | ||||
| int  subvec( int item) | ||||
| { | ||||
|   return( item-1 ); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| int submat( int nrowb, int row, int col) | ||||
| { | ||||
|   return( nrowb*(col-1) + subvec(row) ); | ||||
| } | ||||
| 
 | ||||
| int posmat( int nrowb, int row, int col) | ||||
| { | ||||
|   return( submat(nrowb, row, col)+BLAS_BASE ); | ||||
| } | ||||
| 
 | ||||
| /* ************************************************************************ */ | ||||
| /* Randomization functions                                                  */ | ||||
| /* ************************************************************************ */ | ||||
| 
 | ||||
| void randomseed(int seeds[]) | ||||
| /* Simply create some default seed values */ | ||||
| { | ||||
|   seeds[1] = 123456; | ||||
|   seeds[2] = 234567; | ||||
|   seeds[3] = 345678; | ||||
| } | ||||
| 
 | ||||
| void randomdens( int n, REAL *x, REAL r1, REAL r2, REAL densty, int *seeds ) | ||||
| { | ||||
| /* ------------------------------------------------------------------
 | ||||
|    random  generates a vector x[*] of random numbers | ||||
|    in the range (r1, r2) with (approximate) specified density. | ||||
|    seeds[*] must be initialized before the first call. | ||||
|    ------------------------------------------------------------------ */ | ||||
| 
 | ||||
|   int   i; | ||||
|   REAL  *y; | ||||
| 
 | ||||
|   y = (REAL *) malloc(sizeof(*y) * (n+1)); | ||||
|   ddrand( n, x, 1, seeds ); | ||||
|   ddrand( n, y, 1, seeds ); | ||||
| 
 | ||||
|   for (i = 1; i<=n; i++) { | ||||
|      if (y[i] < densty) | ||||
|         x[i] = r1  +  (r2 - r1) * x[i]; | ||||
|      else | ||||
|         x[i] = 0.0; | ||||
|   } | ||||
|   free(y); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ | ||||
| 
 | ||||
| void ddrand( int n, REAL *x, int incx, int *seeds ) | ||||
| { | ||||
| 
 | ||||
| /* ------------------------------------------------------------------
 | ||||
|    ddrand fills a vector x with uniformly distributed random numbers | ||||
|    in the interval (0, 1) using a method due to  Wichman and Hill. | ||||
| 
 | ||||
|    seeds[1..3] should be set to integer values | ||||
|    between 1 and 30000 before the first entry. | ||||
| 
 | ||||
|    Integer arithmetic up to 30323 is required. | ||||
| 
 | ||||
|    Blatantly copied from Wichman and Hill 19-January-1987. | ||||
|    14-Feb-94. Original version. | ||||
|    30 Jun 1999. seeds stored in an array. | ||||
|    30 Jun 1999. This version of ddrand. | ||||
|    ------------------------------------------------------------------ */ | ||||
| 
 | ||||
|   int    ix, xix; | ||||
| 
 | ||||
|   if (n < 1) return; | ||||
| 
 | ||||
|   for (ix = 1; ix<=1+(n-1)*incx; ix=ix+incx) { | ||||
|      seeds[1]     = 171*(seeds[1] % 177) -  2*(seeds[1]/177); | ||||
|      seeds[2]     = 172*(seeds[2] % 176) - 35*(seeds[2]/176); | ||||
|      seeds[3]     = 170*(seeds[3] % 178) - 63*(seeds[3]/178); | ||||
| 
 | ||||
|      if (seeds[1] < 0) seeds[1] = seeds[1] + 30269; | ||||
|      if (seeds[2] < 0) seeds[2] = seeds[2] + 30307; | ||||
|      if (seeds[3] < 0) seeds[3] = seeds[3] + 30323; | ||||
| 
 | ||||
| 	 x[ix]  = ((REAL) seeds[1])/30269.0 + | ||||
|               ((REAL) seeds[2])/30307.0 + | ||||
|               ((REAL) seeds[3])/30323.0; | ||||
|      xix    = (int) x[ix]; | ||||
| 	 x[ix]  = fabs(x[ix] - xix); | ||||
|    } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
|  | @ -1,130 +0,0 @@ | |||
| #ifndef HEADER_myblas | ||||
| #define HEADER_myblas | ||||
| 
 | ||||
| /* ************************************************************************ */ | ||||
| /* BLAS function interface with local and external loadable versions        */ | ||||
| /* Author:  Kjell Eikland                                                   */ | ||||
| /* Version: Initial version spring 2004                                     */ | ||||
| /* Licence: LGPL                                                            */ | ||||
| /* ************************************************************************ */ | ||||
| /* Changes: 19 September 2004   Moved function pointer variable             */ | ||||
| /*                              declarations from myblas.h to myblas.c      */ | ||||
| /*                              to avoid linker problems with the Mac.      */ | ||||
| /*          20 April 2005       Modified all double types to REAL to self-  */ | ||||
| /*                              adjust to global settings.  Note that BLAS  */ | ||||
| /*                              as of now does not have double double.      */ | ||||
| /*          15 December 2005    Added idamin()                              */ | ||||
| /* ************************************************************************ */ | ||||
| 
 | ||||
| #define BLAS_BASE         1 | ||||
| #define UseMacroVector | ||||
| #define LoadableBlasLib | ||||
| 
 | ||||
| 
 | ||||
| /* ************************************************************************ */ | ||||
| /* Include necessary libraries                                              */ | ||||
| /* ************************************************************************ */ | ||||
| #include "commonlib.h" | ||||
| #ifdef LoadableBlasLib | ||||
|   #if (defined WIN32) || (defined WIN64) | ||||
|     #include <windows.h> | ||||
|   #else | ||||
|     #include <dlfcn.h> | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /* ************************************************************************ */ | ||||
| /* BLAS functions                                                           */ | ||||
| /* ************************************************************************ */ | ||||
| 
 | ||||
| #ifndef BLAS_CALLMODEL | ||||
|   #if (defined WIN32) || (defined WIN64) | ||||
|     #define BLAS_CALLMODEL _cdecl | ||||
|   #else | ||||
|     #define BLAS_CALLMODEL | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| typedef void   (BLAS_CALLMODEL BLAS_dscal_func) (int *n, REAL *da, REAL *dx, int *incx); | ||||
| typedef void   (BLAS_CALLMODEL BLAS_dcopy_func) (int *n, REAL *dx, int *incx,  REAL *dy, int *incy); | ||||
| typedef void   (BLAS_CALLMODEL BLAS_daxpy_func) (int *n, REAL *da, REAL *dx, int *incx,  REAL *dy, int *incy); | ||||
| typedef void   (BLAS_CALLMODEL BLAS_dswap_func) (int *n, REAL *dx, int *incx,  REAL *dy, int *incy); | ||||
| typedef double (BLAS_CALLMODEL BLAS_ddot_func)  (int *n, REAL *dx, int *incx,  REAL *dy, int *incy); | ||||
| typedef int    (BLAS_CALLMODEL BLAS_idamax_func)(int *n, REAL *x,  int *is); | ||||
| typedef int    (BLAS_CALLMODEL BLAS_idamin_func)(int *n, REAL *x,  int *is); | ||||
| typedef void   (BLAS_CALLMODEL BLAS_dload_func) (int *n, REAL *da, REAL *dx, int *incx); | ||||
| typedef double (BLAS_CALLMODEL BLAS_dnormi_func)(int *n, REAL *x); | ||||
| 
 | ||||
| #ifndef __WINAPI | ||||
|   #if (defined WIN32) || (defined WIN64) | ||||
|     #define __WINAPI WINAPI | ||||
|   #else | ||||
|     #define __WINAPI | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| void init_BLAS(void); | ||||
| MYBOOL is_nativeBLAS(void); | ||||
| MYBOOL load_BLAS(char *libname); | ||||
| MYBOOL unload_BLAS(void); | ||||
| 
 | ||||
| /* ************************************************************************ */ | ||||
| /* User-callable BLAS definitions (C base 1)                                */ | ||||
| /* ************************************************************************ */ | ||||
| void dscal ( int n, REAL da,  REAL *dx, int incx ); | ||||
| void dcopy ( int n, REAL *dx, int incx, REAL *dy, int incy ); | ||||
| void daxpy ( int n, REAL da,  REAL *dx, int incx,   REAL *dy, int incy ); | ||||
| void dswap ( int n, REAL *dx, int incx, REAL *dy, int incy ); | ||||
| REAL ddot  ( int n, REAL *dx, int incx, REAL *dy, int incy ); | ||||
| int  idamax( int n, REAL *x,  int is ); | ||||
| int  idamin( int n, REAL *x,  int is ); | ||||
| void dload ( int n, REAL da,  REAL *dx, int incx ); | ||||
| REAL dnormi( int n, REAL *x ); | ||||
| 
 | ||||
| 
 | ||||
| /* ************************************************************************ */ | ||||
| /* Locally implemented BLAS functions (C base 0)                            */ | ||||
| /* ************************************************************************ */ | ||||
| void BLAS_CALLMODEL my_dscal ( int *n, REAL *da, REAL *dx,  int *incx ); | ||||
| void BLAS_CALLMODEL my_dcopy ( int *n, REAL *dx, int *incx, REAL *dy, int *incy ); | ||||
| void BLAS_CALLMODEL my_daxpy ( int *n, REAL *da, REAL *dx,  int *incx,  REAL *dy, int *incy ); | ||||
| void BLAS_CALLMODEL my_dswap ( int *n, REAL *dx, int *incx, REAL *dy, int *incy ); | ||||
| REAL BLAS_CALLMODEL my_ddot  ( int *n, REAL *dx, int *incx,  REAL *dy, int *incy ); | ||||
| int  BLAS_CALLMODEL my_idamax( int *n, REAL *x,  int *is ); | ||||
| int  BLAS_CALLMODEL my_idamin( int *n, REAL *x,  int *is ); | ||||
| void BLAS_CALLMODEL my_dload ( int *n, REAL *da, REAL *dx, int *incx ); | ||||
| REAL BLAS_CALLMODEL my_dnormi( int *n, REAL *x ); | ||||
| 
 | ||||
| 
 | ||||
| /* ************************************************************************ */ | ||||
| /* Subvector and submatrix access routines (Fortran compatibility)          */ | ||||
| /* ************************************************************************ */ | ||||
| #ifdef UseMacroVector | ||||
|   #define subvec(item) (item - 1) | ||||
| #else | ||||
|   int subvec( int item ); | ||||
| #endif | ||||
| 
 | ||||
| int submat( int nrowb, int row, int col ); | ||||
| int posmat( int nrowb, int row, int col ); | ||||
| 
 | ||||
| 
 | ||||
| /* ************************************************************************ */ | ||||
| /* Randomization functions                                                  */ | ||||
| /* ************************************************************************ */ | ||||
| void randomseed(int *seeds); | ||||
| void randomdens( int n, REAL *x, REAL r1, REAL r2, REAL densty, int *seeds); | ||||
| void ddrand( int n, REAL *x, int incx, int *seeds ); | ||||
| 
 | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -1,952 +0,0 @@ | |||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <math.h> | ||||
| #include "commonlib.h" | ||||
| #include "myblas.h" | ||||
| #include "sparselib.h" | ||||
| 
 | ||||
| 
 | ||||
| sparseMatrix *createMatrix(int dimLimit, int lenLimit, int initVectors) | ||||
| { | ||||
|   int          initsize; | ||||
|   sparseMatrix *matrix; | ||||
| 
 | ||||
|   if(initVectors < 0) | ||||
|     initVectors = 0; | ||||
|   if(initVectors == 0) | ||||
|     initsize = MIN(INITIALSIZE, dimLimit); | ||||
|   else | ||||
|     initsize = MAX(INITIALSIZE, initVectors); | ||||
| 
 | ||||
|   CALLOC(matrix, 1); | ||||
|   matrix->limit = dimLimit; | ||||
|   matrix->limitVector = lenLimit; | ||||
|   resizeMatrix(matrix, initsize); | ||||
|   while(initVectors > 0) { | ||||
|     initVectors--; | ||||
|     appendMatrix(matrix, createVector(lenLimit, 2)); | ||||
|   } | ||||
|   return(matrix); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void resizeMatrix(sparseMatrix *matrix, int newSize) | ||||
| { | ||||
|   int oldSize; | ||||
| 
 | ||||
|   if(matrix == NULL) | ||||
|     oldSize = 0; | ||||
|   else | ||||
|     oldSize = matrix->size; | ||||
|   while(oldSize>newSize) { | ||||
| 	  oldSize--; | ||||
| 	  freeVector(matrix->list[oldSize]); | ||||
|     return; | ||||
|   } | ||||
|   REALLOC(matrix->list, newSize); | ||||
|   while(oldSize<newSize) { | ||||
| 	  matrix->list[oldSize] = NULL; | ||||
| 	  oldSize++; | ||||
|   } | ||||
|   if(newSize>0) | ||||
|     matrix->size = newSize; | ||||
| } | ||||
| 
 | ||||
| int appendMatrix(sparseMatrix *matrix, sparseVector *newVector) | ||||
| { | ||||
|    if(matrix->count == matrix->size) | ||||
|      resizeMatrix(matrix, matrix->size + 10); | ||||
|    matrix->list[matrix->count] = newVector; | ||||
|    matrix->count++; | ||||
|    putDiagonalIndex(newVector, matrix->count); | ||||
|    return(matrix->count); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int NZcountMatrix(sparseMatrix *matrix) | ||||
| { | ||||
|   int i, nz; | ||||
| 
 | ||||
|   nz = 0; | ||||
|   for(i = 0; i < matrix->count; i++) | ||||
|     nz += matrix->list[i]->count; | ||||
| 
 | ||||
|   return( nz ); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void freeMatrix(sparseMatrix *matrix) | ||||
| { | ||||
|   resizeMatrix(matrix, 0); | ||||
|   FREE(matrix); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void printMatrix(int n, sparseMatrix *matrix, int modulo, MYBOOL showEmpty) | ||||
| { | ||||
|    int i; | ||||
|    for(i = 1; i<=matrix->count; i++)  | ||||
|      if(matrix->list[i-1] != NULL) {  | ||||
|        if(showEmpty || matrix->list[i-1]->count>0) | ||||
|          printVector(n, matrix->list[i-1], modulo); | ||||
|    } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| sparseVector *createVector(int dimLimit, int initSize) | ||||
| { | ||||
|   sparseVector *newitem; | ||||
|   CALLOC(newitem, 1); | ||||
|   newitem->limit = dimLimit; | ||||
|   initSize = resizeVector(newitem, initSize); | ||||
|   return(newitem); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| sparseVector *cloneVector(sparseVector *sparse) | ||||
| { | ||||
|   sparseVector *hold; | ||||
|   hold = createVector(sparse->limit, sparse->count); | ||||
|   hold->count = sparse->count; | ||||
|   MEMCOPY(&hold->value[0], &sparse->value[0], (sparse->count+1)); | ||||
|   MEMCOPY(&hold->index[0], &sparse->index[0], (sparse->count+1)); | ||||
|   return(hold); | ||||
| } | ||||
| 
 | ||||
| int redimensionVector(sparseVector *sparse, int newDim) | ||||
| { | ||||
|   int olddim, i; | ||||
| 
 | ||||
|   olddim = sparse->limit; | ||||
|   sparse->limit = newDim; | ||||
|   if(lastIndex(sparse)>newDim) { | ||||
|     i = sparse->count; | ||||
|     while(i>0 && sparse->index[i]>newDim) i--; | ||||
|     sparse->count = i; | ||||
|     resizeVector(sparse, sparse->count); | ||||
|   } | ||||
|   return(olddim); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int resizeVector(sparseVector *sparse, int newSize) | ||||
| { | ||||
|   int oldsize; | ||||
| 
 | ||||
|   oldsize = sparse->size; | ||||
|   REALLOC(sparse->value, (newSize+1)); | ||||
|   REALLOC(sparse->index, (newSize+1)); | ||||
|   sparse->size = newSize; | ||||
|   return(oldsize); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void moveVector(sparseVector *sparse, int destPos, int sourcePos, int itemCount) | ||||
| { | ||||
|   int i; | ||||
|    | ||||
|   if(itemCount <= 0 || sourcePos == destPos) | ||||
|     return; | ||||
| 
 | ||||
| #if defined DOFASTMATH | ||||
|   if(TRUE) { | ||||
|     MEMMOVE(&sparse->value[destPos], &sparse->value[sourcePos], itemCount); | ||||
|     MEMMOVE(&sparse->index[destPos], &sparse->index[sourcePos], itemCount); | ||||
|   } | ||||
|   else { | ||||
|     int    *idxPtr1, *idxPtr2; | ||||
|     double *valPtr1, *valPtr2; | ||||
| 
 | ||||
|     for(i = 1, idxPtr1 = sparse->index+destPos, idxPtr2 = sparse->index+sourcePos, | ||||
|                valPtr1 = sparse->value+destPos, valPtr2 = sparse->value+sourcePos;  | ||||
|         i<=itemCount; i++, idxPtr1++, idxPtr2++, valPtr1++, valPtr2++) { | ||||
|       *idxPtr1 = *idxPtr2; | ||||
|       *valPtr1 = *valPtr2; | ||||
|     } | ||||
|   } | ||||
| #else | ||||
|   for(i = 1; i<=itemCount; i++) { | ||||
|     sparse->value[destPos] = sparse->value[sourcePos]; | ||||
|     sparse->index[destPos] = sparse->index[sourcePos]; | ||||
|     destPos++; | ||||
|     sourcePos++; | ||||
|   } | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void rotateVector(sparseVector *sparse, int startPos, int chainSize, int stepDelta) | ||||
| { | ||||
| /*  int idxHold; */ | ||||
| /*  double valHold; */ | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void swapVector(sparseVector *sparse1, sparseVector *sparse2) | ||||
| { | ||||
|   int n, m, *idx; | ||||
|   REAL *val; | ||||
| 
 | ||||
|   n = sparse1->count; | ||||
|   sparse1->count = sparse2->count; | ||||
|   sparse2->count = n; | ||||
| 
 | ||||
|   n = sparse1->size; | ||||
|   sparse1->size = sparse2->size; | ||||
|   sparse2->size = n; | ||||
| 
 | ||||
|   n = sparse1->limit; | ||||
|   sparse1->limit = sparse2->limit; | ||||
|   sparse2->limit = n; | ||||
| 
 | ||||
|   idx = sparse1->index; | ||||
|   sparse1->index = sparse2->index; | ||||
|   sparse2->index = idx; | ||||
| 
 | ||||
|   val = sparse1->value; | ||||
|   sparse1->value = sparse2->value; | ||||
|   sparse2->value = val; | ||||
| 
 | ||||
|   n = getDiagonalIndex(sparse1); | ||||
|   m = getDiagonalIndex(sparse2); | ||||
|   putDiagonalIndex(sparse1, m); | ||||
|   putDiagonalIndex(sparse2, n); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void freeVector(sparseVector *sparse) | ||||
| { | ||||
| 	if(sparse != NULL) { | ||||
|     FREE(sparse->value); | ||||
|     FREE(sparse->index); | ||||
|     FREE(sparse); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| MYBOOL verifyVector(sparseVector *sparse) | ||||
| { | ||||
|   int i, n, k1, k2, kd;  | ||||
|   int  err = 0; | ||||
|   double vd; | ||||
| 
 | ||||
|   n = sparse->count; | ||||
|   kd = sparse->index[0]; | ||||
|   vd = sparse->value[0]; | ||||
|   if(n <= 1) | ||||
|     return(TRUE); | ||||
|   k1 = 0; | ||||
|   k2 = sparse->index[1]; | ||||
|   if(k2 == kd && sparse->value[1] != vd)  | ||||
|     err = 2; | ||||
| 
 | ||||
|   for(i = 2; i <= n && err == 0; i++) { | ||||
|     k1 = k2; | ||||
|     k2 = sparse->index[i]; | ||||
|     if(k1 >= k2) err = 1; | ||||
|     if(k2 == kd && sparse->value[i] != vd) err = 2; | ||||
|   } | ||||
|   if(err == 0) | ||||
|     return(TRUE); | ||||
|   else if(err == 1) | ||||
|     printf("Invalid sparse vector index order"); | ||||
|   else if(err == 2) | ||||
|     printf("Invalid sparse vector diagonal value"); | ||||
|   return(FALSE); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int firstIndex(sparseVector *sparse) | ||||
| { | ||||
|   return(sparse->index[1]); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int lastIndex(sparseVector *sparse) | ||||
| { | ||||
|   return(sparse->index[sparse->count]); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int getDiagonalIndex(sparseVector *sparse) | ||||
| { | ||||
|   return(sparse->index[0]); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int putDiagonalIndex(sparseVector *sparse, int index) | ||||
| { | ||||
|   int oldindex; | ||||
|   oldindex = sparse->index[0]; | ||||
|   if(index > 0) { | ||||
|     sparse->index[0] = 0; /* Must temporarily set to zero to force vector search in getItem */ | ||||
|     sparse->value[0] = getItem(sparse, index); | ||||
|   } | ||||
|   else | ||||
|     sparse->value[0] = 0; | ||||
|   sparse->index[0] = index; | ||||
|   return(oldindex); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| MYBOOL putDiagonal(sparseVector *sparse, REAL value) | ||||
| { | ||||
|   if(sparse->index[0]>0) { | ||||
|     putItem(sparse, sparse->index[0], value);  | ||||
|     return(TRUE); | ||||
|   } | ||||
|   else | ||||
|     return(FALSE); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| REAL getDiagonal(sparseVector *sparse) | ||||
| { | ||||
|    return(sparse->value[0]); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| REAL getItem(sparseVector *sparse, int targetIndex) | ||||
| { | ||||
|   /* First check if we want the diagonal element */  | ||||
|   if(targetIndex == sparse->index[0]) | ||||
|     return(sparse->value[0]); | ||||
| 
 | ||||
|   /* If not, search for the variable's position in the index list */ | ||||
|   targetIndex = findIndex(targetIndex, sparse->index, sparse->count, BLAS_BASE); | ||||
|   if(targetIndex < 0) | ||||
|     return(0); | ||||
|   else | ||||
|     return(sparse->value[targetIndex]); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| REAL addtoItem(sparseVector *sparse, int targetIndex, REAL value) | ||||
| { | ||||
|   int idx; | ||||
| 
 | ||||
|   if(targetIndex > 0)  | ||||
|     idx = findIndex(targetIndex, sparse->index, sparse->count, BLAS_BASE); | ||||
|   else { | ||||
|     idx = -targetIndex; | ||||
|     if(idx > sparse->count) | ||||
|       /* Index error; ignore item */ | ||||
|       return(0.0); | ||||
|   } | ||||
| 
 | ||||
|   if(idx <=0 ) | ||||
|     value = putItem(sparse, targetIndex, value); | ||||
|   else { | ||||
|     value += sparse->value[idx]; | ||||
|     putItem(sparse, -idx, value); | ||||
|   } | ||||
|   return(value); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| REAL putItem(sparseVector *sparse, int targetIndex, REAL value) | ||||
| { | ||||
|   REAL last = 0.0; | ||||
|   int  posIndex; | ||||
| 
 | ||||
|   if(targetIndex < 0) { | ||||
|     posIndex = -targetIndex; | ||||
|     if(posIndex > sparse->count) | ||||
|       return(last); | ||||
|     targetIndex = sparse->index[posIndex]; | ||||
|   } | ||||
|   else | ||||
|     posIndex = findIndex(targetIndex, sparse->index, sparse->count, BLAS_BASE); | ||||
| 
 | ||||
|   if(fabs(value) < MACHINEPREC) | ||||
|     value = 0; | ||||
| 
 | ||||
|   if(targetIndex == sparse->index[0])  | ||||
|     sparse->value[0] = value; | ||||
| 
 | ||||
|   if(posIndex < 0) { | ||||
|     if(value != 0) { | ||||
|       if(sparse->count == sparse->size) | ||||
|         resizeVector(sparse, sparse->size + RESIZEDELTA); | ||||
|       posIndex = -posIndex; | ||||
|       sparse->count++; | ||||
|       if(posIndex < sparse->count)  | ||||
|         moveVector(sparse, posIndex+1, posIndex, sparse->count-posIndex); | ||||
|       sparse->value[posIndex] = value; | ||||
|       sparse->index[posIndex] = targetIndex; | ||||
|     } | ||||
|   } | ||||
|   else { | ||||
|     if(value == 0) { | ||||
|       last = sparse->value[posIndex]; | ||||
|       if(sparse->count > posIndex)  | ||||
|         moveVector(sparse, posIndex, posIndex+1, sparse->count-posIndex); | ||||
|       sparse->count--; | ||||
|     } | ||||
|     else { | ||||
|       sparse->value[posIndex] = value; | ||||
|       sparse->index[posIndex] = targetIndex; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| #ifdef DEBUG_SPARSELIB | ||||
|   verifyVector(sparse); | ||||
| #endif | ||||
| 
 | ||||
|   return(last); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void swapItems(sparseVector *sparse, int firstIndex, int secondIndex) | ||||
| { | ||||
|   int i,j,ki,kj; | ||||
|   REAL hold; | ||||
| 
 | ||||
|   if(firstIndex == secondIndex) | ||||
|     return; | ||||
|   if(firstIndex > secondIndex) { | ||||
|     i = firstIndex; | ||||
|     firstIndex = secondIndex; | ||||
|     secondIndex = i; | ||||
|   } | ||||
| 
 | ||||
|   if(FALSE) { | ||||
|     i = 1; | ||||
|     ki = 0; | ||||
|     while(i <= sparse->count && (ki = sparse->index[i])<firstIndex) i++; | ||||
|     j = i; | ||||
|     kj = 0; | ||||
|     while(j <= sparse->count && (kj = sparse->index[j])<secondIndex) j++; | ||||
|   } | ||||
|   else { | ||||
|     i = findIndex(firstIndex, sparse->index, sparse->count, BLAS_BASE); | ||||
|     if(i < 0) | ||||
|       i = -i; | ||||
|     j = findIndex(secondIndex, sparse->index, sparse->count, BLAS_BASE); | ||||
|     if(j < 0) | ||||
|       j = -j; | ||||
|   } | ||||
| 
 | ||||
|   if(i > sparse->count) | ||||
|     ki = 0; | ||||
|   else | ||||
|     ki = sparse->index[i]; | ||||
|   if(j > sparse->count) | ||||
|     kj = 0; | ||||
|   else | ||||
|     kj = sparse->index[j]; | ||||
| 
 | ||||
|   if(ki == firstIndex && kj == secondIndex) {   /* Found both -> swap in place */ | ||||
|     hold = sparse->value[i]; | ||||
|     sparse->value[i] = sparse->value[j]; | ||||
|     sparse->value[j] = hold; | ||||
| 
 | ||||
|     if(sparse->index[0] == firstIndex) | ||||
|       sparse->value[0] = sparse->value[i]; | ||||
|     else if(sparse->index[0] == secondIndex) | ||||
|       sparse->value[0] = sparse->value[j]; | ||||
|   } | ||||
|   else if(ki == firstIndex) {                   /* Found first, but not the second -> shift left */ | ||||
|     j--; | ||||
|     if(i < j) { | ||||
|       hold = sparse->value[i]; | ||||
|       moveVector(sparse, i, i+1, j-i); | ||||
|       sparse->value[j] = hold; | ||||
|     } | ||||
|     sparse->index[j] = secondIndex; | ||||
| 
 | ||||
|     if(sparse->index[0] == firstIndex) | ||||
|       sparse->value[0] = 0; | ||||
|     else if(sparse->index[0] == secondIndex) | ||||
|       sparse->value[0] = sparse->value[j]; | ||||
| 
 | ||||
|   } | ||||
|   else if(kj == secondIndex) {                  /* Found second, but not the first -> shift right */ | ||||
|     if(i < j) { | ||||
|       hold = sparse->value[j]; | ||||
|       moveVector(sparse, i+1, i, j-i); | ||||
|       sparse->value[i] = hold; | ||||
|     } | ||||
|     sparse->index[i] = firstIndex; | ||||
| 
 | ||||
|     if(sparse->index[0] == firstIndex) | ||||
|       sparse->value[0] = sparse->value[i]; | ||||
|     else if(sparse->index[0] == secondIndex) | ||||
|       sparse->value[0] = 0; | ||||
|   } | ||||
| 
 | ||||
| #ifdef DEBUG_SPARSELIB | ||||
|   verifyVector(sparse); | ||||
| #endif | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void clearVector(sparseVector *sparse, int indexStart, int indexEnd) | ||||
| { | ||||
|   int i; | ||||
| 
 | ||||
|   i = sparse->count; | ||||
|   if(i==0) return; | ||||
| 
 | ||||
|   if(indexStart<=0) | ||||
|     indexStart=sparse->index[1]; | ||||
|   if(indexEnd<=0) | ||||
|     indexEnd=sparse->index[i]; | ||||
| 
 | ||||
|   if(indexStart>indexEnd) return; | ||||
| 
 | ||||
|   if(sparse->index[0]>=indexStart && sparse->index[0]<=indexEnd) { | ||||
|     sparse->value[0] = 0; | ||||
|   } | ||||
|   if(indexStart<=sparse->index[1] && indexEnd>=sparse->index[i])  | ||||
|     sparse->count = 0; | ||||
|   else { | ||||
|     while(i>0 && sparse->index[i]>indexEnd) i--; | ||||
|     indexEnd = i; | ||||
|     while(i>0 && sparse->index[i]>=indexStart) i--; | ||||
|     indexStart = i+1; | ||||
|     if(indexEnd>=indexStart) { | ||||
|       i = sparse->count-indexEnd; | ||||
|       moveVector(sparse, indexStart, indexEnd+1, i); | ||||
|       sparse->count -= indexEnd-indexStart+1; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| #ifdef DEBUG_SPARSELIB | ||||
|   verifyVector(sparse); | ||||
| #endif | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int getVector(sparseVector *sparse, REAL *dense, int indexStart, int indexEnd, MYBOOL doClear) | ||||
| { | ||||
|   int i,k; | ||||
| 
 | ||||
|   i = 1; | ||||
|   while(i<=sparse->count && sparse->index[i]<indexStart) i++; | ||||
| 
 | ||||
|   while(i<=sparse->count && (k=sparse->index[i])<=indexEnd) { | ||||
|     while(indexStart<k) { | ||||
|       dense[indexStart] = 0; | ||||
|       indexStart++; | ||||
|     } | ||||
|     dense[indexStart] = sparse->value[i]; | ||||
|     indexStart++; | ||||
|     i++; | ||||
|   } | ||||
| 
 | ||||
|   while(indexStart<=indexEnd) { | ||||
|     dense[indexStart] = 0; | ||||
|     indexStart++; | ||||
|   } | ||||
| 
 | ||||
|   k = sparse->count; | ||||
|   if(doClear) { | ||||
|     sparse->count = 0; | ||||
|     sparse->value[0] = 0; | ||||
|   } | ||||
|   return(k); | ||||
| } | ||||
| 
 | ||||
| void putVector(sparseVector *sparse, REAL *dense, int indexStart, int indexEnd) | ||||
| { | ||||
|   int i,n; | ||||
| 
 | ||||
|   n = sparse->count; | ||||
|   if(indexStart<=0) | ||||
|     indexStart=sparse->index[1]; | ||||
|   if(indexEnd<=0) | ||||
|     indexEnd=sparse->index[n]; | ||||
| 
 | ||||
|   if(n==0 || sparse->index[n]<indexStart) { | ||||
|     i = sparse->index[0]; | ||||
|     if(i>=indexStart && i<=indexEnd) | ||||
|       sparse->value[0] = 0; | ||||
|     for(i = indexStart; i<=indexEnd; i++) { | ||||
|       if(dense[i] == 0) continue; | ||||
|       if(sparse->size == sparse->count) | ||||
|         resizeVector(sparse, sparse->size + RESIZEDELTA); | ||||
|       sparse->count++; | ||||
|       sparse->value[sparse->count] = dense[i]; | ||||
|       sparse->index[sparse->count] = i; | ||||
|       if(i == sparse->index[0])  | ||||
|         sparse->value[0] = dense[i]; | ||||
|     } | ||||
|   } | ||||
|   else { | ||||
|     while(indexStart <= indexEnd) { | ||||
|       putItem(sparse, indexStart, dense[indexStart]); | ||||
|       indexStart++; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| #ifdef DEBUG_SPARSELIB | ||||
|   verifyVector(sparse); | ||||
| #endif | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void fillVector(sparseVector *sparse, int count, REAL value) | ||||
| { | ||||
|   int i; | ||||
| 
 | ||||
|   if(sparse->count > 0)  | ||||
|     clearVector(sparse, 0, 0); | ||||
|   for(i = 1; i<=count; i++) | ||||
|     putItem(sparse, i, value); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| REAL dotVector(sparseVector *sparse, REAL *dense, int indexStart, int indexEnd) | ||||
| { | ||||
|   int  i, n; | ||||
|   long REAL sum; | ||||
|    | ||||
|   n = sparse->count; | ||||
|   sum = 0; | ||||
| 
 | ||||
|   if(n > 0) { | ||||
|     if(indexStart<=0) | ||||
|       indexStart=sparse->index[1]; | ||||
|     if(indexEnd<=0) | ||||
|       indexEnd=sparse->index[n]; | ||||
| 
 | ||||
|     if(indexStart > 1) { | ||||
|       i = findIndex(indexStart, sparse->index, sparse->count, BLAS_BASE); | ||||
|       if(i < 0) { | ||||
|         i = -i; | ||||
|         if(i > n)  | ||||
|           return(sum); | ||||
|       } | ||||
|     } | ||||
|     else | ||||
|       i = 1; | ||||
| 
 | ||||
|     /* CPU intensive loop; provide alternative evaluation models */ | ||||
| #if defined DOFASTMATH | ||||
|     { | ||||
|       /* Do fast pointer arithmetic */ | ||||
|       int  *indexptr; | ||||
|       REAL *valueptr; | ||||
| /*      for(i = 1, indexptr = sparse->index + 1;
 | ||||
|           i <= n && (*indexptr) < indexStart; i++, indexptr++); */ | ||||
|       indexptr = sparse->index + i; | ||||
|       for(valueptr = sparse->value + i; | ||||
|           i <= n && (*indexptr) <= indexEnd;  i++, indexptr++, valueptr++)  | ||||
|         sum += (*valueptr) * dense[(*indexptr)]; | ||||
|     } | ||||
| #else | ||||
|     { | ||||
|       /* Do traditional indexed access */ | ||||
|       int k; | ||||
| /*      i = 1; */ | ||||
| /*      while(i<=n && sparse->index[i]<indexStart) i++; */ | ||||
|       while(i<=n && (k = sparse->index[i])<=indexEnd) { | ||||
|         sum += sparse->value[i] * dense[k]; | ||||
|         i++; | ||||
|       } | ||||
|     } | ||||
| #endif     | ||||
|   } | ||||
| 
 | ||||
|   return(sum); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void daxpyVector1(sparseVector *sparse, REAL scalar, REAL *dense, int indexStart, int indexEnd) | ||||
| { | ||||
|   int i, n; | ||||
| 
 | ||||
|   if(scalar == 0) return; | ||||
| 
 | ||||
|   n = sparse->count; | ||||
|   if(indexStart<=0) | ||||
|     indexStart=sparse->index[1]; | ||||
|   if(indexEnd<=0) | ||||
|     indexEnd=sparse->index[n]; | ||||
| 
 | ||||
|   /* CPU intensive loop; provide alternative evaluation models */ | ||||
| #if defined DOFASTMATH | ||||
|   { | ||||
|     /* Do fast pointer arithmetic */ | ||||
|     int    *indexptr; | ||||
|     REAL *valueptr; | ||||
|     for(i = 1, indexptr = sparse->index + 1; | ||||
|         i <= n && (*indexptr) < indexStart; i++, indexptr++); | ||||
|     for(valueptr = sparse->value + i; | ||||
|         i <= n && (*indexptr) <= indexEnd;  i++, indexptr++, valueptr++)  | ||||
|       dense[(*indexptr)] += (*valueptr) * scalar; | ||||
|   } | ||||
| #else | ||||
|   { | ||||
|     /* Do traditional indexed access */ | ||||
|     int k; | ||||
|     for(i = 1; i<= n; i++) { | ||||
|       k = sparse->index[i]; | ||||
|       if(k<indexStart) continue; | ||||
|       if(k>indexEnd) break; | ||||
|       dense[k] += sparse->value[i] * scalar; | ||||
|     } | ||||
|   } | ||||
| #endif   | ||||
| } | ||||
| void daxpyVector2(REAL *dense, REAL scalar, sparseVector *sparse, int indexStart, int indexEnd) | ||||
| { | ||||
|   sparseVector *hold; | ||||
| 
 | ||||
|   hold = createVector(sparse->limit, sparse->count); | ||||
|   putDiagonalIndex(hold, getDiagonalIndex(sparse)); | ||||
|   putVector(hold, dense, indexStart, indexEnd); | ||||
|   daxpyVector3(hold, scalar, sparse, indexStart, indexEnd); | ||||
|   freeVector(hold); | ||||
| } | ||||
| void daxpyVector3(sparseVector *sparse1, REAL scalar, sparseVector *sparse2, int indexStart, int indexEnd) | ||||
| { | ||||
|   int i1, i2, k, p1, p2, c1, c2; | ||||
|   sparseVector *hold; | ||||
| 
 | ||||
|   if(sparse1->count == 0) return; | ||||
| 
 | ||||
|  /* Spool to start positions */ | ||||
|   i1 = 1; | ||||
|   c1 = sparse1->count; | ||||
|   while(i1 <= c1 && sparse1->index[i1] < indexStart) i1++; | ||||
|   if(i1 <= c1) | ||||
|     p1 = sparse1->index[i1]; | ||||
|   else | ||||
|     p1 = indexEnd+1; | ||||
| 
 | ||||
|   i2 = 1; | ||||
|   c2 = sparse2->count; | ||||
|   while(i2 <= c2 && sparse2->index[i2] < indexStart) i2++; | ||||
|   if(i2 <= c2) | ||||
|     p2 = sparse2->index[i2]; | ||||
|   else | ||||
|     p2 = indexEnd+1; | ||||
| 
 | ||||
|  /* Create a temporary vector */ | ||||
|   k = c1+c2; | ||||
|   if(k > 0) { | ||||
|     hold = createVector(MAX(sparse1->limit, sparse2->limit), k); | ||||
|     putDiagonalIndex(hold, getDiagonalIndex(sparse2)); | ||||
|   } | ||||
|   else | ||||
|     hold = sparse2; | ||||
| 
 | ||||
|  /* Loop over all items in both vectors */ | ||||
|   while((i1 <= c1 && p1 <= indexEnd) ||  | ||||
|         (i2 <= c2 && p2 <= indexEnd)) { | ||||
| 
 | ||||
|     k = 0; | ||||
| 
 | ||||
|    /* Add/spool exclusive right-vector items */ | ||||
|     while(i2 <= c2 && p2 < p1) { | ||||
|       if(hold != sparse2) | ||||
|         putItem(hold, p2, sparse2->value[i2]); | ||||
|       i2++; | ||||
|       if(i2 <= c2) | ||||
|         p2 = sparse2->index[i2]; | ||||
|       else | ||||
|         p2 = indexEnd+1; | ||||
|       k++; | ||||
|     } | ||||
|    /* Add equal-indexed items */ | ||||
|     while(i1 <= c1 && i2 <= c2 && p1 == p2) { | ||||
| /*      if(hold != sparse2) */ | ||||
|         putItem(hold, p1, scalar*sparse1->value[i1]+sparse2->value[i2]); | ||||
| /*      else
 | ||||
|           addtoItem(sparse2, -i2, scalar*sparse1->value[i1]); */ | ||||
|       i1++; | ||||
|       if(i1 <= c1) | ||||
|         p1 = sparse1->index[i1]; | ||||
|       else | ||||
|         p1 = indexEnd+1; | ||||
|       i2++; | ||||
|       if(i2 <= c2) | ||||
|         p2 = sparse2->index[i2]; | ||||
|       else | ||||
|         p2 = indexEnd+1; | ||||
|       k++; | ||||
|     } | ||||
|    /* Add exclusive left-vector items */ | ||||
|     while(i1 <= c1 && p1 < p2) { | ||||
|       putItem(hold, p1, scalar*sparse1->value[i1]); | ||||
| /*      if(hold == sparse2) c2++; */ | ||||
|       i1++; | ||||
|       if(i1 <= c1) | ||||
|         p1 = sparse1->index[i1]; | ||||
|       else | ||||
|         p1 = indexEnd+1; | ||||
|       k++; | ||||
|     } | ||||
| 
 | ||||
|     if(k == 0) break; | ||||
|   } | ||||
| 
 | ||||
| /*  if(hold != sparse2) */ | ||||
|   { | ||||
|     swapVector(hold, sparse2); | ||||
|     freeVector(hold); | ||||
|   } | ||||
| 
 | ||||
| #ifdef DEBUG_SPARSELIB | ||||
|   verifyVector(sparse2); | ||||
| #endif | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void dswapVector1(sparseVector *sparse, REAL *dense, int indexStart, int indexEnd) | ||||
| { | ||||
|   int i, d, n; | ||||
|   REAL *x; | ||||
| 
 | ||||
|   if(indexStart <= 0) | ||||
|     indexStart = 1; | ||||
|   n = lastIndex(sparse); | ||||
|   if(indexEnd <= 0)  | ||||
|     indexEnd = n; | ||||
|   CALLOC(x, (MAX(indexEnd,n)+1)); | ||||
| 
 | ||||
|   getVector(sparse, x, indexStart, n, FALSE); | ||||
|   d = getDiagonalIndex(sparse); | ||||
|   clearVector(sparse, indexStart, n); | ||||
|   for(i = indexStart; i<=indexEnd; i++) { | ||||
|     if(dense[i] != 0) | ||||
|       putItem(sparse, i, dense[i]); | ||||
|   } | ||||
|   for(i = indexEnd+1; i<=n; i++) { | ||||
|     if(x[i] != 0) | ||||
|       putItem(sparse, i, x[i]); | ||||
|   } | ||||
|   MEMCOPY(&dense[indexStart], &x[indexStart], (indexEnd-indexStart+1)); | ||||
| 
 | ||||
| #ifdef DEBUG_SPARSELIB | ||||
|   verifyVector(sparse); | ||||
| #endif | ||||
|    | ||||
|   FREE(x); | ||||
| } | ||||
| void dswapVector2(REAL *dense, sparseVector *sparse, int indexStart, int indexEnd) | ||||
| { | ||||
|   dswapVector1(sparse, dense, indexStart, indexEnd); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void dswapVector3(sparseVector *sparse1, sparseVector *sparse2, int indexStart, int indexEnd) | ||||
| { | ||||
| 
 | ||||
|   REAL *dense1, *dense2; | ||||
| 
 | ||||
|   if(indexStart<=0) | ||||
|     indexStart = 1; | ||||
|   if(indexEnd<=0) | ||||
|     indexEnd = MAX(lastIndex(sparse1), lastIndex(sparse2)); | ||||
| 
 | ||||
|   if(indexStart <= firstIndex(sparse1) && indexStart <= firstIndex(sparse2) &&  | ||||
|      indexEnd >= lastIndex(sparse1) && indexEnd >= lastIndex(sparse2)) { | ||||
|     swapVector(sparse1, sparse2); | ||||
|   } | ||||
|   else { | ||||
| 
 | ||||
|     CALLOC(dense1, (indexEnd+1)); | ||||
|     CALLOC(dense2, (indexEnd+1)); | ||||
|     getVector(sparse1, dense1, indexStart, indexEnd, TRUE); | ||||
|     getVector(sparse2, dense2, indexStart, indexEnd, TRUE); | ||||
|     clearVector(sparse1, indexStart, indexEnd); | ||||
|     clearVector(sparse2, indexStart, indexEnd); | ||||
|     putVector(sparse1, dense2, indexStart, indexEnd); | ||||
|     putVector(sparse2, dense1, indexStart, indexEnd); | ||||
|     FREE(dense1); | ||||
|     FREE(dense2); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int idamaxVector(sparseVector *sparse, int is, REAL *maxValue) | ||||
| { | ||||
|   int    i, n, imax; | ||||
|   REAL xmax; | ||||
| 
 | ||||
|   n = sparse->count; | ||||
|   imax = 1; | ||||
|   if(n == 0) | ||||
|     xmax = 0; | ||||
|   else { | ||||
|     xmax = fabs(sparse->value[imax]); | ||||
| 
 | ||||
|     /* CPU intensive loop; provide alternative evaluation models */ | ||||
| #if defined DOFASTMATH | ||||
|     { | ||||
|       /* Do fast pointer arithmetic */ | ||||
|       int  *indexptr; | ||||
|       REAL *valueptr; | ||||
|       for(i = 1, indexptr = sparse->index + 1; | ||||
|           i <= n && (*indexptr) <= is; i++, indexptr++); | ||||
|       for(valueptr = sparse->value + i; | ||||
|           i <= n; i++, indexptr++, valueptr++) { | ||||
| 	      if((*valueptr)>xmax) { | ||||
| 		      xmax = (*valueptr); | ||||
| 		      imax = (*indexptr); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
| #else | ||||
|     { | ||||
|       REAL xtest; | ||||
|       /* Do traditional indexed access */ | ||||
|       i = 1; | ||||
|       while(i <= n && sparse->index[i] <= is) i++; | ||||
|       for(; i<=n; i++) { | ||||
|         xtest = fabs(sparse->value[i]); | ||||
| 	      if(xtest>xmax) { | ||||
| 		      xmax = xtest; | ||||
| 		      imax = sparse->index[i]; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
| #endif     | ||||
|   } | ||||
|   if(maxValue != NULL) | ||||
|     (*maxValue) = sparse->index[imax]; | ||||
|   return(imax); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void printVector(int n, sparseVector *sparse, int modulo ) | ||||
| { | ||||
|   int i,j,k; | ||||
| 
 | ||||
|   if(sparse == NULL) return; | ||||
| 
 | ||||
|   if (modulo <= 0) modulo = 5; | ||||
|   for (i = 1, j = 1; j<=n; i++, j++) { | ||||
|     if(i<=sparse->count) | ||||
|       k = sparse->index[i]; | ||||
|     else | ||||
|       k = n+1; | ||||
|     while (j < k) { | ||||
|       if(mod(j, modulo) == 1)  | ||||
|         printf("\n%2d:%12g", j, 0.0); | ||||
|       else | ||||
|         printf(" %2d:%12g", j, 0.0); | ||||
|       j++; | ||||
|     } | ||||
|     if(k<=n) { | ||||
|       if(mod(j, modulo) == 1)  | ||||
|         printf("\n%2d:%12g", k, sparse->value[i]); | ||||
|       else | ||||
|         printf(" %2d:%12g", k, sparse->value[i]); | ||||
|     } | ||||
|   } | ||||
|   if(mod(j, modulo) != 0) printf("\n"); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -1,84 +0,0 @@ | |||
| 
 | ||||
| #include "commonlib.h" | ||||
| 
 | ||||
| /*#define DEBUG_SPARSELIB*/ | ||||
| 
 | ||||
| #define INITIALSIZE 10 | ||||
| #define RESIZEDELTA  4 | ||||
| 
 | ||||
| #ifndef SPARSELIB | ||||
| 
 | ||||
| #define SPARSELIB | ||||
| 
 | ||||
| typedef struct _sparseVector { | ||||
|   int    limit; | ||||
|   int    size; | ||||
|   int    count; | ||||
|   int    *index; | ||||
|   REAL *value; | ||||
| } sparseVector; | ||||
| 
 | ||||
| typedef struct _sparseMatrix { | ||||
|   int    limit; | ||||
|   int    size; | ||||
|   int    count; | ||||
|   int    limitVector; | ||||
|   sparseVector **list; | ||||
| } sparseMatrix; | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
|   extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| sparseMatrix *createMatrix(int dimLimit, int lenLimit, int initVectors); | ||||
| void resizeMatrix(sparseMatrix *matrix, int newSize); | ||||
| int appendMatrix(sparseMatrix *matrix, sparseVector *newVector); | ||||
| int NZcountMatrix(sparseMatrix *matrix); | ||||
| void freeMatrix(sparseMatrix *matrix); | ||||
| void printMatrix(int n, sparseMatrix *matrix, int modulo, MYBOOL showEmpty); | ||||
| 
 | ||||
| sparseVector *createVector(int dimLimit, int initSize); | ||||
| sparseVector *cloneVector(sparseVector *sparse); | ||||
| int  redimensionVector(sparseVector *sparse, int newDim); | ||||
| int  resizeVector(sparseVector *sparse, int newSize); | ||||
| void moveVector(sparseVector *sparse, int destPos, int sourcePos, int itemCount); | ||||
| void rotateVector(sparseVector *sparse, int startPos, int chainSize, int stepDelta); | ||||
| void swapVector(sparseVector *sparse1, sparseVector *sparse2); | ||||
| void freeVector(sparseVector *sparse); | ||||
| void printVector(int n, sparseVector *sparse, int modulo); | ||||
| MYBOOL verifyVector(sparseVector *sparse); | ||||
| 
 | ||||
| int firstIndex(sparseVector *sparse); | ||||
| int lastIndex(sparseVector *sparse); | ||||
| int getDiagonalIndex(sparseVector *sparse); | ||||
| int putDiagonalIndex(sparseVector *sparse, int index); | ||||
| MYBOOL putDiagonal(sparseVector *sparse, REAL value); | ||||
| REAL getDiagonal(sparseVector *sparse); | ||||
| REAL getItem(sparseVector *sparse, int targetIndex); | ||||
| REAL putItem(sparseVector *sparse, int targetIndex, REAL value); | ||||
| REAL addtoItem(sparseVector *sparse, int targetIndex, REAL value); | ||||
| void swapItems(sparseVector *sparse, int firstIndex, int secondIndex); | ||||
| void clearVector(sparseVector *sparse, int indexStart, int indexEnd); | ||||
| int getVector(sparseVector *sparse, REAL *dense, int indexStart, int indexEnd, MYBOOL doClear); | ||||
| void putVector(sparseVector *sparse, REAL *dense, int indexStart, int indexEnd); | ||||
| void fillVector(sparseVector *sparse, int count, REAL value); | ||||
| 
 | ||||
| REAL dotVector(sparseVector *sparse, REAL *dense, int indexStart, int indexEnd); | ||||
| 
 | ||||
| void daxpyVector1(sparseVector *sparse, REAL scalar, REAL *dense, int indexStart, int indexEnd); | ||||
| void daxpyVector2(REAL *dense, REAL scalar, sparseVector *sparse, int indexStart, int indexEnd); | ||||
| void daxpyVector3(sparseVector *sparse1, REAL scalar, sparseVector *sparse2, int indexStart, int indexEnd); | ||||
| 
 | ||||
| void dswapVector1(sparseVector *sparse, REAL *dense, int indexStart, int indexEnd); | ||||
| void dswapVector2(REAL *dense, sparseVector *sparse, int indexStart, int indexEnd); | ||||
| void dswapVector3(sparseVector *sparse1, sparseVector *sparse2, int indexStart, int indexEnd); | ||||
| 
 | ||||
| int idamaxVector(sparseVector *sparse, int is, REAL *maxValue); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
|   } | ||||
| #endif | ||||
| 
 | ||||
|  | @ -1,27 +0,0 @@ | |||
| 
 | ||||
| #include "bfp_LUSOL.h" | ||||
| #include "lp_lib.h" | ||||
| #include "lp_LUSOL.h" | ||||
| 
 | ||||
| BOOL APIENTRY DllMain( HANDLE hModule,  | ||||
|                        DWORD  ul_reason_for_call,  | ||||
|                        LPVOID lpReserved | ||||
| 					 ) | ||||
| { | ||||
| 	switch (ul_reason_for_call) | ||||
| 	{ | ||||
| 	case DLL_PROCESS_ATTACH: | ||||
| 	case DLL_THREAD_ATTACH: | ||||
| 	case DLL_THREAD_DETACH: | ||||
| 	case DLL_PROCESS_DETACH: | ||||
| 		break; | ||||
| 	} | ||||
|     return TRUE; | ||||
| } | ||||
| 
 | ||||
| #if defined FORTIFY | ||||
| int EndOfPgr(int i) | ||||
| { | ||||
|     exit(i); | ||||
| } | ||||
| #endif | ||||
|  | @ -1,15 +0,0 @@ | |||
| // stdafx.h : include file for standard system include files,
 | ||||
| // or project specific include files that are used frequently, but
 | ||||
| // are changed infrequently
 | ||||
| //
 | ||||
| 
 | ||||
| //#pragma once
 | ||||
| 
 | ||||
| //RoleIsExternalInvEngine;INVERSE_ACTIVE=INVERSE_LUSOL
 | ||||
| 
 | ||||
| #define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
 | ||||
| // Windows Header Files:
 | ||||
| #include <windows.h> | ||||
| 
 | ||||
| // TODO: reference additional headers your program requires here
 | ||||
| 
 | ||||
|  | @ -1,735 +0,0 @@ | |||
| 
 | ||||
| /*  Modularized simplex basis factorization module - w/interface for lp_solve v5.0+
 | ||||
|    ---------------------------------------------------------------------------------- | ||||
|     Author:        Kjell Eikland | ||||
|     Contact:       kjell.eikland@broadpark.no | ||||
|     License terms: LGPL. | ||||
| 
 | ||||
|     Requires:      lusol.h, lp_lib.h, myblas.h | ||||
| 
 | ||||
|     Release notes: | ||||
|     v2.0.0  1 March 2004        First implementation of the LUSOL v2.0 C translation. | ||||
|     v2.0.1  1 April 2004        Added singularity recovery and fast/reuse update logic. | ||||
|     v2.0.2  23 May 2004         Moved mustrefact() function into the BFP structure. | ||||
|     v2.0.3  5 September 2004    Reworked pivot threshold tightening logic and default | ||||
|                                 values. | ||||
|     v2.1.0  18 June 2005        Made changes to allow for "pure" factorization; | ||||
|                                 i.e. without the objective function included. | ||||
| 
 | ||||
|    ---------------------------------------------------------------------------------- */ | ||||
| 
 | ||||
| /* Generic include libraries */ | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include "lp_lib.h" | ||||
| 
 | ||||
| /* Include libraries for this factorization system */ | ||||
| #include "myblas.h" | ||||
| #include "commonlib.h" | ||||
| #include "lp_LUSOL.h" | ||||
| #include "lusol.h" | ||||
| 
 | ||||
| #ifdef FORTIFY | ||||
| # include "lp_fortify.h" | ||||
| #endif | ||||
| 
 | ||||
| /* Include routines common to factorization engine implementations */ | ||||
| #include "lp_BFP1.c" | ||||
| #include "lp_BFP2.c" | ||||
| 
 | ||||
| 
 | ||||
| /* MUST MODIFY */ | ||||
| char * BFP_CALLMODEL bfp_name(void) | ||||
| { | ||||
|   return( "LUSOL v2.2.1.0" ); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* MUST MODIFY */ | ||||
| MYBOOL BFP_CALLMODEL bfp_resize(lprec *lp, int newsize) | ||||
| { | ||||
|   INVrec *lu; | ||||
| 
 | ||||
|   lu = lp->invB; | ||||
| 
 | ||||
|   /* Increment dimensionality since we put the objective row at the top */ | ||||
|   newsize = newsize + bfp_rowoffset(lp); | ||||
|   lu->dimalloc = newsize; | ||||
| 
 | ||||
|   /* Allocate index tracker arrays, LU matrices and various work vectors */ | ||||
|   if(!allocREAL(lp, &(lu->value), newsize+MATINDEXBASE, AUTOMATIC)) | ||||
|     return( FALSE ); | ||||
| 
 | ||||
|   /* Data specific to the factorization engine */ | ||||
|   if(lu->LUSOL != NULL) { | ||||
|     if(newsize > 0) | ||||
|       LUSOL_sizeto(lu->LUSOL, newsize, newsize, 0); | ||||
|     else { | ||||
|       LUSOL_free(lu->LUSOL); | ||||
|       lu->LUSOL = NULL; | ||||
|     } | ||||
|   } | ||||
|   else if(newsize > 0) { | ||||
|     int  asize; | ||||
|     REAL bsize; | ||||
| 
 | ||||
|     lu->LUSOL = LUSOL_create(NULL, 0, LUSOL_PIVMOD_TPP, bfp_pivotmax(lp)*0); | ||||
| 
 | ||||
| #if 1 | ||||
|     lu->LUSOL->luparm[LUSOL_IP_ACCELERATION]  = LUSOL_AUTOORDER; | ||||
|     lu->LUSOL->parmlu[LUSOL_RP_SMARTRATIO]    = 0.50; | ||||
| #endif | ||||
| #if 0 | ||||
|     lu->timed_refact = DEF_TIMEDREFACT; | ||||
| #else | ||||
|     lu->timed_refact = FALSE; | ||||
| #endif | ||||
| 
 | ||||
|     /* The following adjustments seem necessary to make the really tough NETLIB
 | ||||
|        models perform reliably and still performant (e.g. cycle.mps) */ | ||||
| #if 0 | ||||
|     lu->LUSOL->parmlu[LUSOL_RP_SMALLDIAG_U]   = | ||||
|     lu->LUSOL->parmlu[LUSOL_RP_EPSDIAG_U]     = lp->epsprimal; | ||||
| #endif | ||||
| #if 0 | ||||
|     lu->LUSOL->parmlu[LUSOL_RP_ZEROTOLERANCE] = lp->epsvalue; | ||||
| #endif | ||||
| 
 | ||||
| #if 1 | ||||
|     LUSOL_setpivotmodel(lu->LUSOL, LUSOL_PIVMOD_NOCHANGE, LUSOL_PIVTOL_SLIM); | ||||
| #else | ||||
|     LUSOL_setpivotmodel(lu->LUSOL, LUSOL_PIVMOD_NOCHANGE, LUSOL_PIVTOL_TIGHT); | ||||
| #endif | ||||
| 
 | ||||
| #ifdef LUSOL_UseBLAS | ||||
| /*    if(fileSearchPath("PATH", "myBLAS.DLL", NULL) && load_BLAS("myBLAS")) */ | ||||
|     if(is_nativeBLAS() && load_BLAS(libnameBLAS)) | ||||
|       lp->report(lp, NORMAL, "Optimized BLAS was successfully loaded for bfp_LUSOL.\n"); | ||||
| #endif | ||||
| 
 | ||||
|     /* Try to minimize memory allocation if we have a large number of unit columns */ | ||||
|     bsize = (REAL) lp->get_nonzeros(lp); | ||||
|     if(newsize > lp->columns) | ||||
|       bsize += newsize; | ||||
|     else | ||||
|       bsize = bsize/lp->columns*newsize; | ||||
|     /* Add a "reasonable" delta to allow for B and associated factorizations
 | ||||
|        that are denser than average; this makes reallocations less frequent. | ||||
|        Values between 1.2 and 1.5 appear to be reasonable. */ | ||||
|     asize = (int) (bsize*MAX_DELTAFILLIN*1.3333); | ||||
|     if(!LUSOL_sizeto(lu->LUSOL, newsize, newsize, asize)) | ||||
|       return( FALSE ); | ||||
|   } | ||||
|   lu->dimcount = newsize; | ||||
|   return( TRUE ); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* MUST MODIFY */ | ||||
| void BFP_CALLMODEL bfp_free(lprec *lp) | ||||
| { | ||||
|   INVrec *lu; | ||||
| 
 | ||||
|   lu = lp->invB; | ||||
|   if(lu == NULL) | ||||
|     return; | ||||
| 
 | ||||
|   /* General arrays */ | ||||
|   FREE(lu->opts); | ||||
|   FREE(lu->value); | ||||
| 
 | ||||
|   /* Data specific to the factorization engine */ | ||||
|   LUSOL_free(lu->LUSOL); | ||||
| 
 | ||||
|   FREE(lu); | ||||
|   lp->invB = NULL; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* MUST MODIFY */ | ||||
| int BFP_CALLMODEL bfp_nonzeros(lprec *lp, MYBOOL maximum) | ||||
| { | ||||
|   INVrec *lu; | ||||
| 
 | ||||
|   lu = lp->invB; | ||||
|   if(maximum == TRUE) | ||||
|     return(lu->max_LUsize); | ||||
|   else if(maximum == AUTOMATIC) | ||||
|     return(lu->max_Bsize); | ||||
|   else | ||||
|     return(lu->LUSOL->luparm[LUSOL_IP_NONZEROS_L0]+lu->LUSOL->luparm[LUSOL_IP_NONZEROS_U0]); | ||||
| /*    return(lu->LUSOL->luparm[LUSOL_IP_NONZEROS_ROW]); */ | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* MUST MODIFY (or ignore) */ | ||||
| int BFP_CALLMODEL bfp_memallocated(lprec *lp) | ||||
| { | ||||
|   int      mem; | ||||
|   LUSOLrec *LUSOL = lp->invB->LUSOL; | ||||
| 
 | ||||
|   mem = sizeof(REAL) * (LUSOL->lena+LUSOL->maxm+LUSOL_RP_LASTITEM); | ||||
|   mem += sizeof(int) * (2*LUSOL->lena+5*LUSOL->maxm+5*LUSOL->maxn+LUSOL_IP_LASTITEM); | ||||
|   if(LUSOL->luparm[LUSOL_IP_PIVOTTYPE] == LUSOL_PIVMOD_TCP) | ||||
|     mem += sizeof(REAL) * LUSOL->maxn + 2*sizeof(REAL)*LUSOL->maxn; | ||||
|   else if(LUSOL->luparm[LUSOL_IP_PIVOTTYPE] == LUSOL_PIVMOD_TRP) | ||||
|     mem += sizeof(REAL) * LUSOL->maxn; | ||||
|   if(!LUSOL->luparm[LUSOL_IP_KEEPLU]) | ||||
|     mem += sizeof(REAL) * LUSOL->maxn; | ||||
|   return( mem ); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* MUST MODIFY */ | ||||
| int BFP_CALLMODEL bfp_preparefactorization(lprec *lp) | ||||
| { | ||||
|   INVrec *lu = lp->invB; | ||||
| 
 | ||||
|   /* Finish any outstanding business */ | ||||
|   if(lu->is_dirty == AUTOMATIC) | ||||
|     lp->bfp_finishfactorization(lp); | ||||
| 
 | ||||
|   /* Clear or resize the existing LU matrices - specific for the factorization engine */ | ||||
|   LUSOL_clear(lu->LUSOL, TRUE); | ||||
|   if(lu->dimcount != lp->rows + bfp_rowoffset(lp)) | ||||
|     lp->bfp_resize(lp, lp->rows); | ||||
| 
 | ||||
|   /* Reset additional indicators */ | ||||
|   lp->bfp_updaterefactstats(lp); | ||||
|   lu->col_pos = 0; | ||||
| 
 | ||||
|   return(0); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* LOCAL HELPER ROUTINE - Replace a basis column with corresponding slack */ | ||||
| int bfp_LUSOLsetcolumn(lprec *lp, int posnr, int colnr) | ||||
| { | ||||
|   int nz, inform; | ||||
| 
 | ||||
|   nz = lp->get_lpcolumn(lp, colnr, lp->invB->LUSOL->w + bfp_rowoffset(lp), NULL, NULL); | ||||
|   inform = LUSOL_replaceColumn(lp->invB->LUSOL, posnr, lp->invB->LUSOL->w); | ||||
|   return( inform ); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* LOCAL HELPER ROUTINE - force the basis to be the identity matrix */ | ||||
| int bfp_LUSOLidentity(lprec *lp, int *rownum) | ||||
| { | ||||
|   int    i, nz; | ||||
|   INVrec *invB = lp->invB; | ||||
| 
 | ||||
|   /* Reset the factorization engine */ | ||||
|   LUSOL_clear(invB->LUSOL, TRUE); | ||||
| 
 | ||||
|   /* Add the basis columns */ | ||||
|   lp->invB->set_Bidentity = TRUE; | ||||
|   for(i = 1; i <= invB->dimcount; i++) { | ||||
|     nz = lp->get_basiscolumn(lp, i, rownum, invB->value); | ||||
|     LUSOL_loadColumn(invB->LUSOL, rownum, i, invB->value, nz, 0); | ||||
|   } | ||||
|   lp->invB->set_Bidentity = FALSE; | ||||
| 
 | ||||
|   /* Factorize */ | ||||
|   i = LUSOL_factorize(invB->LUSOL); | ||||
| 
 | ||||
|   return( i ); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* LOCAL HELPER ROUTINE */ | ||||
| int bfp_LUSOLfactorize(lprec *lp, MYBOOL *usedpos, int *rownum, int *singular) | ||||
| { | ||||
|   int    i, j, nz, deltarows = bfp_rowoffset(lp); | ||||
|   INVrec *invB = lp->invB; | ||||
| 
 | ||||
|   /* Handle normal, presumed nonsingular case */ | ||||
|   if(singular == NULL) { | ||||
| 
 | ||||
|   /* Optionally do a symbolic minimum degree ordering;
 | ||||
|      not that slack variables should not be processed */ | ||||
| /*#define UsePreprocessMDO*/ | ||||
| #ifdef UsePreprocessMDO | ||||
|     int *mdo; | ||||
|     mdo = lp->bfp_createMDO(lp, usedpos, lp->rows, TRUE); | ||||
|     if(mdo != NULL) { | ||||
|       for(i = 1; i <= lp->rows; i++) | ||||
|         lp->set_basisvar(lp, i, mdo[i]); | ||||
|       FREE(mdo); | ||||
|     } | ||||
| #endif | ||||
| 
 | ||||
|     /* Reset the factorization engine */ | ||||
|     LUSOL_clear(invB->LUSOL, TRUE); | ||||
| 
 | ||||
|     /* Add the basis columns in the original order */ | ||||
|     for(i = 1; i <= invB->dimcount; i++) { | ||||
|       nz = lp->get_basiscolumn(lp, i, rownum, invB->value); | ||||
|       LUSOL_loadColumn(invB->LUSOL, rownum, i, invB->value, nz, 0); | ||||
|       if((i > deltarows) && (lp->var_basic[i-deltarows] > lp->rows)) | ||||
|         lp->invB->user_colcount++; | ||||
|     } | ||||
| 
 | ||||
|     /* Factorize */ | ||||
|     i = LUSOL_factorize(invB->LUSOL); | ||||
|   } | ||||
| 
 | ||||
|   /* Handle case where a column may be singular */ | ||||
|   else { | ||||
|     LLrec *map; | ||||
| 
 | ||||
|     /* Reset the factorization engine */ | ||||
|     i = bfp_LUSOLidentity(lp, rownum); | ||||
| 
 | ||||
|     /* Build map of available columns */ | ||||
|     nz = createLink(lp->rows, &map, NULL); | ||||
|     for(i = 1; i <= lp->rows; i++) { | ||||
|       if(lp->var_basic[i] <= lp->rows) | ||||
|         removeLink(map, i); | ||||
|     } | ||||
| 
 | ||||
|     /* Rebuild the basis, column by column, while skipping slack columns */ | ||||
|     j = firstActiveLink(map); | ||||
|     for(i = 1; i <= lp->rows; i++) { | ||||
|       if(lp->var_basic[i] <= lp->rows) | ||||
|         continue; | ||||
|       nz = bfp_LUSOLsetcolumn(lp, j+deltarows, lp->var_basic[i]); | ||||
|       if(nz == LUSOL_INFORM_LUSUCCESS) | ||||
|         lp->invB->user_colcount++; | ||||
|       else { | ||||
|         nz = bfp_LUSOLsetcolumn(lp, j+deltarows, i); | ||||
|         lp->set_basisvar(lp, i, i); | ||||
|       } | ||||
|       j = nextActiveLink(map, j); | ||||
|     } | ||||
| 
 | ||||
|     /* Sort the basis list */ | ||||
|     MEMCOPY(rownum, lp->var_basic, lp->rows+1); | ||||
|     sortByINT(lp->var_basic, rownum, lp->rows, 1, TRUE); | ||||
| 
 | ||||
|   } | ||||
| 
 | ||||
|   return( i ); | ||||
| } | ||||
| /* LOCAL HELPER ROUTINE */ | ||||
| void bfp_LUSOLtighten(lprec *lp) | ||||
| { | ||||
|   int infolevel = DETAILED; | ||||
| 
 | ||||
|   switch(LUSOL_tightenpivot(lp->invB->LUSOL)) { | ||||
|     case FALSE: lp->report(lp, infolevel, "bfp_factorize: Very hard numerics, but cannot tighten LUSOL thresholds further.\n"); | ||||
|                  break; | ||||
|     case TRUE:  lp->report(lp, infolevel, "bfp_factorize: Frequent refact pivot count %d at iter %.0f; tightened thresholds.\n", | ||||
|                                            lp->invB->num_pivots, (REAL) lp->get_total_iter(lp)); | ||||
|                  break; | ||||
|     default:    lp->report(lp, infolevel, "bfp_factorize: LUSOL switched to %s pivoting model to enhance stability.\n", | ||||
|                                            LUSOL_pivotLabel(lp->invB->LUSOL)); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| #define is_fixedvar is_fixedvar_ /* resolves a compiler warning/error conflict with lp_lib.h */ | ||||
| 
 | ||||
| static MYBOOL is_fixedvar(lprec *lp, int variable) | ||||
| { | ||||
|   if((lp->bb_bounds != NULL && lp->bb_bounds->UBzerobased) || (variable <= lp->rows)) | ||||
|     return( (MYBOOL) (lp->upbo[variable] < lp->epsprimal) ); | ||||
|   else | ||||
|     return( (MYBOOL) (lp->upbo[variable]-lp->lowbo[variable] < lp->epsprimal) ); | ||||
| } /* is_fixedvar */ | ||||
| 
 | ||||
| /* MUST MODIFY */ | ||||
| int BFP_CALLMODEL bfp_factorize(lprec *lp, int uservars, int Bsize, MYBOOL *usedpos, MYBOOL final) | ||||
| { | ||||
|   int      kcol, inform, | ||||
|            *rownum = NULL, | ||||
|            singularities = 0, | ||||
|            dimsize = lp->invB->dimcount; | ||||
|   LUSOLrec *LUSOL = lp->invB->LUSOL; | ||||
| 
 | ||||
|  /* Set dimensions and create work array */ | ||||
|   SETMAX(lp->invB->max_Bsize, Bsize+(1+lp->rows-uservars)); | ||||
|   kcol = lp->invB->dimcount; | ||||
|   LUSOL->m = kcol; | ||||
|   LUSOL->n = kcol; | ||||
|   allocINT(lp, &rownum, kcol+1, FALSE); | ||||
| 
 | ||||
|  /* Check if the refactorization frequency is low;
 | ||||
|     tighten pivot thresholds if appropriate */ | ||||
|   inform = lp->bfp_pivotcount(lp); | ||||
|   if(!final &&                        /* No solution update-based refactorization */ | ||||
|      !lp->invB->force_refact &&       /* No sparsity-based refactorization */ | ||||
|      !lp->is_action(lp->spx_action, | ||||
|           ACTION_TIMEDREINVERT) &&    /* No optimal time-based refactorization */ | ||||
|      (inform > 5) && (inform < 0.25*lp->bfp_pivotmax(lp))) | ||||
|     bfp_LUSOLtighten(lp); | ||||
| 
 | ||||
| 
 | ||||
|  /* Reload B and factorize */ | ||||
|   inform = bfp_LUSOLfactorize(lp, usedpos, rownum, NULL); | ||||
| 
 | ||||
|  /* Do some checks */ | ||||
| #ifdef Paranoia | ||||
|   if(uservars != lp->invB->user_colcount) { | ||||
|     lp->report(lp, SEVERE, "bfp_factorize: User variable count reconciliation failed\n"); | ||||
|     return( singularities ); | ||||
|   } | ||||
| #endif | ||||
| 
 | ||||
|   /* Check result and do further remedial action if necessary */ | ||||
|   if(inform != LUSOL_INFORM_LUSUCCESS) { | ||||
|     int  singularcols, | ||||
|          replacedcols = 0; | ||||
|     REAL hold; | ||||
| 
 | ||||
|     /* Make sure we do not tighten factorization pivot criteria too often, and simply
 | ||||
|        accept the substitution of slack columns into the basis */ | ||||
|     if((lp->invB->num_singular+1) % TIGHTENAFTER == 0) | ||||
|       bfp_LUSOLtighten(lp); | ||||
| 
 | ||||
|     /* Try to restore a non-singular basis by substituting singular columns with slacks */ | ||||
|     while((inform == LUSOL_INFORM_LUSINGULAR) && (replacedcols < dimsize)) { | ||||
|       int    iLeave, jLeave, iEnter; | ||||
|       MYBOOL isfixed; | ||||
| 
 | ||||
|       singularities++; | ||||
|       singularcols = LUSOL->luparm[LUSOL_IP_SINGULARITIES]; | ||||
|       hold = (REAL) lp->get_total_iter(lp); | ||||
|       lp->report(lp, NORMAL, "bfp_factorize: Resolving %d singularit%s at refact %d, iter %.0f\n", | ||||
|                              singularcols, my_plural_y(singularcols), lp->invB->num_refact, hold); | ||||
| 
 | ||||
|       /* Find the failing / singular column(s) and make slack substitutions */ | ||||
|       for(kcol = 1; kcol <= singularcols; kcol++) { | ||||
| 
 | ||||
|         /* Determine leaving and entering columns. */ | ||||
|         iLeave = LUSOL_getSingularity(LUSOL, kcol);        /* This is the singular column as natural index */ | ||||
|         iEnter = iLeave;                                   /* This is the target replacement slack         */ | ||||
| #if 1 | ||||
|         iEnter = LUSOL->iqinv[iEnter]; | ||||
|         iEnter = LUSOL->ip[iEnter]; | ||||
| #endif | ||||
|         iLeave-= bfp_rowextra(lp);                         /* This is the original B column/basis index    */ | ||||
|         jLeave = lp->var_basic[iLeave];                    /* This is the IA column index in lp_solve      */ | ||||
| 
 | ||||
|         /* Express the slack index in original lp_solve [1..rows] reference and check validity */ | ||||
|  /*       if(B4 != NULL) iEnter = B4->B4_row[iEnter]; v6 FUNCTIONALITY */ | ||||
|         iEnter -=  bfp_rowextra(lp); | ||||
|         if(lp->is_basic[iEnter]) { | ||||
|           lp->report(lp, DETAILED, "bfp_factorize: Replacement slack %d is already basic!\n", iEnter); | ||||
| 
 | ||||
|           /* See if we can find a good alternative slack variable to enter */ | ||||
|           iEnter = 0; | ||||
|           for(inform = 1; inform <= lp->rows; inform++) | ||||
|             if(!lp->is_basic[inform]) { | ||||
|               if((iEnter == 0) || (lp->upbo[inform] > lp->upbo[iEnter])) { | ||||
|                 iEnter = inform; | ||||
|                 if(my_infinite(lp, lp->upbo[iEnter])) | ||||
|                   break; | ||||
|               } | ||||
|             } | ||||
|           if(iEnter == 0) { | ||||
|             lp->report(lp, SEVERE, "bfp_factorize: Could not find replacement slack variable!\n"); | ||||
|             break; | ||||
|           } | ||||
|         } | ||||
| 
 | ||||
|         /* We should update bound states for both the entering and leaving variables.
 | ||||
|            Note that this may cause (primal or dual) infeasibility, but I assume that | ||||
|            lp_solve traps this and takes necessary corrective action. */ | ||||
|         isfixed = is_fixedvar(lp, iEnter); | ||||
|         if(isfixed) | ||||
|           lp->fixedvars++; | ||||
|         hold = lp->upbo[jLeave]; | ||||
|         lp->is_lower[jLeave] = isfixed || (fabs(hold)>=lp->infinite) || (lp->rhs[iLeave] < hold); | ||||
|         lp->is_lower[iEnter] = TRUE; | ||||
| 
 | ||||
|         /* Do the basis replacement */ | ||||
|         lp->set_basisvar(lp, iLeave, iEnter); | ||||
| 
 | ||||
|       } | ||||
| 
 | ||||
|       /* Refactorize with slack substitutions */ | ||||
|       inform = bfp_LUSOLfactorize(lp, NULL, rownum, NULL); | ||||
|       replacedcols += singularcols; | ||||
|     } | ||||
| 
 | ||||
|     /* Check if we had a fundamental problem */ | ||||
|     if(singularities >= dimsize) { | ||||
|       lp->report(lp, IMPORTANT, "bfp_factorize: LUSOL was unable to recover from a singular basis\n"); | ||||
|       lp->spx_status = NUMFAILURE; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /* Clean up before returning */ | ||||
|   FREE(rownum); | ||||
| 
 | ||||
|   /* Update statistics */ | ||||
|   /* SETMAX(lp->invB->max_Bsize, (*Bsize)); */ | ||||
|   lp->invB->num_singular += singularities;    /* The total number of singular updates */ | ||||
| 
 | ||||
|   return( singularities ); | ||||
| } | ||||
| 
 | ||||
| /* MUST MODIFY */ | ||||
| MYBOOL BFP_CALLMODEL bfp_finishupdate(lprec *lp, MYBOOL changesign) | ||||
| /* Was addetacol() in versions of lp_solve before 4.0.1.8 - KE */ | ||||
| { | ||||
|   int      i, k, kcol, deltarows = bfp_rowoffset(lp); | ||||
|   REAL     DIAG, VNORM; | ||||
|   INVrec   *lu = lp->invB; | ||||
|   LUSOLrec *LUSOL = lu->LUSOL; | ||||
| 
 | ||||
|   if(!lu->is_dirty) | ||||
|     return( FALSE ); | ||||
|   if(lu->is_dirty != AUTOMATIC) | ||||
|     lu->is_dirty = FALSE; | ||||
| 
 | ||||
|   /* Perform the update */ | ||||
|   k = lu->col_pos+deltarows; | ||||
|   lu->num_pivots++; | ||||
|   if(lu->col_leave > lu->dimcount-deltarows) | ||||
|     lu->user_colcount--; | ||||
|   if(lu->col_enter > lu->dimcount-deltarows) | ||||
|     lu->user_colcount++; | ||||
|   kcol = lu->col_pos; | ||||
|   lu->col_pos = 0; | ||||
| 
 | ||||
|   /* Do standard update */ | ||||
| #ifdef LUSOLSafeFastUpdate      /* NB! Defined in lusol.h */ | ||||
|   if(TRUE || !changesign) { | ||||
|     if(changesign) { | ||||
|       REAL *temp = LUSOL->vLU6L; | ||||
|       for(i = 1, temp++; i <= lp->rows+deltarows; i++, temp++) | ||||
|         if(*temp != 0) | ||||
|           *temp = -(*temp); | ||||
|     } | ||||
|     /* Execute the update using data prepared earlier */ | ||||
|     LU8RPC(LUSOL, LUSOL_UPDATE_OLDNONEMPTY, LUSOL_UPDATE_USEPREPARED, | ||||
|            k, NULL, NULL, &i, &DIAG, &VNORM); | ||||
|   } | ||||
|   else | ||||
| #endif | ||||
|   { | ||||
|     /* Retrieve the data for the entering column (base 0) */ | ||||
|     i = lp->get_lpcolumn(lp, lu->col_enter, lu->value+deltarows, NULL, NULL); | ||||
|     lu->value[0] = 0; | ||||
|     /* Execute the update */ | ||||
|     LU8RPC(LUSOL, LUSOL_UPDATE_OLDNONEMPTY, LUSOL_UPDATE_NEWNONEMPTY, | ||||
|            k, lu->value, NULL, &i, &DIAG, &VNORM); | ||||
|   } | ||||
| 
 | ||||
|   if(i == LUSOL_INFORM_LUSUCCESS) { | ||||
| 
 | ||||
|     /* Check if we should refactorize based on accumulation of fill-in */ | ||||
|     DIAG  = LUSOL->luparm[LUSOL_IP_NONZEROS_L]+LUSOL->luparm[LUSOL_IP_NONZEROS_U]; | ||||
|     VNORM = LUSOL->luparm[LUSOL_IP_NONZEROS_L0]+LUSOL->luparm[LUSOL_IP_NONZEROS_U0]; | ||||
| #if 0 | ||||
|     /* This is Michael Saunder's fixed parameter */ | ||||
|     VNORM *= MAX_DELTAFILLIN; | ||||
| #else | ||||
|     /* This is Kjell Eikland's dynamic error accumulation measure */ | ||||
|     VNORM *= pow(MAX_DELTAFILLIN, pow((0.5*LUSOL->nelem/VNORM), 0.25)); | ||||
| #endif | ||||
|     lu->force_refact = (MYBOOL) ((DIAG > VNORM) && (lu->num_pivots > 20)); | ||||
| 
 | ||||
| #if 0 | ||||
|     /* Additional KE logic to reduce maximum pivot count based on the density of B */ | ||||
|     if(!lu->force_refact) { | ||||
|       VNORM = lp->rows+1; | ||||
|       VNORM = 1.0 - pow((REAL) LUSOL->nelem/VNORM/VNORM, 0.2); | ||||
|       lu->force_refact = (MYBOOL) (lu->num_pivots > VNORM*lp->bfp_pivotmax(lp)); | ||||
|     } | ||||
| #endif | ||||
|   } | ||||
| 
 | ||||
|   /* Handle errors */ | ||||
|   else { | ||||
| /*    int infolevel = NORMAL; */ | ||||
|     int infolevel = DETAILED; | ||||
|     lp->report(lp, infolevel, "bfp_finishupdate: Failed at iter %.0f, pivot %d;\n%s\n", | ||||
|                    (REAL) (lp->total_iter+lp->current_iter), lu->num_pivots, LUSOL_informstr(LUSOL, i)); | ||||
|     if(i == LUSOL_INFORM_ANEEDMEM) {       /* To compress used memory and realloc, if necessary */ | ||||
|       lp->invert(lp, INITSOL_USEZERO, FALSE); | ||||
|       if(i != LUSOL_INFORM_LUSUCCESS) | ||||
|         lp->report(lp, NORMAL, "bfp_finishupdate: Insufficient memory at iter %.0f;\n%s\n", | ||||
|                        (REAL) (lp->total_iter+lp->current_iter), LUSOL_informstr(LUSOL, i)); | ||||
|     } | ||||
|     else if(i == LUSOL_INFORM_RANKLOSS) {  /* To fix rank loss and clear cumulative errors */ | ||||
| #if 0 | ||||
|       /* This is test code to do pivot in slack BEFORE refactorization (pessimistic approach);
 | ||||
|         assumes that LUSOL returns correct information about the source of the singularity */ | ||||
|       kcol = LUSOL->luparm[LUSOL_IP_SINGULARINDEX]; | ||||
| #ifdef MAPSINGULARCOLUMN | ||||
|       kcol = LUSOL_findColumnPosition(LUSOL, kcol); | ||||
| #endif | ||||
|       lp->set_basisvar(lp, kcol-deltarows, kcol-deltarows); | ||||
| #endif | ||||
|       lp->invert(lp, INITSOL_USEZERO, FALSE); | ||||
|       i = LUSOL->luparm[LUSOL_IP_INFORM]; | ||||
|       if(i != LUSOL_INFORM_LUSUCCESS) | ||||
|         lp->report(lp, NORMAL, "bfp_finishupdate: Recovery attempt unsuccessful at iter %.0f;\n%s\n", | ||||
|                        (REAL) (lp->total_iter+lp->current_iter), LUSOL_informstr(LUSOL, i)); | ||||
|       else | ||||
|         lp->report(lp, infolevel, "bfp_finishupdate: Correction or recovery was successful.\n"); | ||||
|     } | ||||
|   } | ||||
|   return( (MYBOOL) (i == LUSOL_INFORM_LUSUCCESS) ); | ||||
| 
 | ||||
| } /* bfp_finishupdate */ | ||||
| 
 | ||||
| 
 | ||||
| /* MUST MODIFY */ | ||||
| void BFP_CALLMODEL bfp_ftran_normal(lprec *lp, REAL *pcol, int *nzidx) | ||||
| { | ||||
|   int    i; | ||||
|   INVrec *lu; | ||||
| 
 | ||||
|   lu = lp->invB; | ||||
| 
 | ||||
|   /* Do the LUSOL ftran */ | ||||
|   i = LUSOL_ftran(lu->LUSOL, pcol-bfp_rowoffset(lp), nzidx, FALSE); | ||||
|   if(i != LUSOL_INFORM_LUSUCCESS) { | ||||
|     lu->status = BFP_STATUS_ERROR; | ||||
|     lp->report(lp, NORMAL, "bfp_ftran_normal: Failed at iter %.0f, pivot %d;\n%s\n", | ||||
|                    (REAL) (lp->total_iter+lp->current_iter), lu->num_pivots, LUSOL_informstr(lu->LUSOL, i)); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* MAY MODIFY */ | ||||
| void BFP_CALLMODEL bfp_ftran_prepare(lprec *lp, REAL *pcol, int *nzidx) | ||||
| { | ||||
|   int    i; | ||||
|   INVrec *lu; | ||||
| 
 | ||||
|   lu = lp->invB; | ||||
| 
 | ||||
|   /* Do the LUSOL ftran */ | ||||
|   i = LUSOL_ftran(lu->LUSOL, pcol-bfp_rowoffset(lp), nzidx, TRUE); | ||||
|   if(i != LUSOL_INFORM_LUSUCCESS) { | ||||
|     lu->status = BFP_STATUS_ERROR; | ||||
|     lp->report(lp, NORMAL, "bfp_ftran_prepare: Failed at iter %.0f, pivot %d;\n%s\n", | ||||
|                    (REAL) (lp->total_iter+lp->current_iter), lu->num_pivots, LUSOL_informstr(lu->LUSOL, i)); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* MUST MODIFY */ | ||||
| void BFP_CALLMODEL bfp_btran_normal(lprec *lp, REAL *prow, int *nzidx) | ||||
| { | ||||
|   int    i; | ||||
|   INVrec *lu; | ||||
| 
 | ||||
|   lu = lp->invB; | ||||
| 
 | ||||
|   /* Do the LUSOL btran */ | ||||
|   i = LUSOL_btran(lu->LUSOL, prow-bfp_rowoffset(lp), nzidx); | ||||
|   if(i != LUSOL_INFORM_LUSUCCESS) { | ||||
|     lu->status = BFP_STATUS_ERROR; | ||||
|     lp->report(lp, NORMAL, "bfp_btran_normal: Failed at iter %.0f, pivot %d;\n%s\n", | ||||
|                    (REAL) (lp->total_iter+lp->current_iter), lu->num_pivots, LUSOL_informstr(lu->LUSOL, i)); | ||||
|   } | ||||
| 
 | ||||
|   /* Check performance data */ | ||||
| #if 0 | ||||
|   if(lu->num_pivots == 1) { | ||||
|     if(lu->LUSOL->luparm[LUSOL_IP_ACCELERATION] > 0) | ||||
|       lp->report(lp, NORMAL, "RowL0 R:%10.7f  C:%10.7f  NZ:%10.7f\n", | ||||
|                              (REAL) lu->LUSOL->luparm[LUSOL_IP_ROWCOUNT_L0] / lu->LUSOL->m, | ||||
|                              (REAL) lu->LUSOL->luparm[LUSOL_IP_COLCOUNT_L0] / lu->LUSOL->m, | ||||
|                              (REAL) lu->LUSOL->luparm[LUSOL_IP_NONZEROS_L0] / pow((REAL) lu->LUSOL->m, 2)); | ||||
|     else | ||||
|       lp->report(lp, NORMAL, "ColL0 C:%10.7f  NZ:%10.7f\n", | ||||
|                              (REAL) lu->LUSOL->luparm[LUSOL_IP_COLCOUNT_L0] / lu->LUSOL->m, | ||||
|                              (REAL) lu->LUSOL->luparm[LUSOL_IP_NONZEROS_L0] / pow((REAL) lu->LUSOL->m, 2)); | ||||
|   } | ||||
| #endif | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| /* MUST MODIFY - Routine to find maximum rank of equality constraints */ | ||||
| int BFP_CALLMODEL bfp_findredundant(lprec *lp, int items, getcolumnex_func cb, int *maprow, int *mapcol) | ||||
| { | ||||
|   int       i, j, nz = 0, m = 0, n = 0, *nzrows = NULL; | ||||
|   REAL      *nzvalues = NULL, *arraymax = NULL; | ||||
|   LUSOLrec  *LUSOL; | ||||
| 
 | ||||
|   /* Are we capable of finding redundancy with this BFP? */ | ||||
|   if((maprow == NULL) && (mapcol == NULL)) | ||||
|     return( n ); | ||||
| 
 | ||||
|   /* If so, initialize memory structures */ | ||||
|   if(!allocINT(lp, &nzrows, items, FALSE) || | ||||
|      !allocREAL(lp, &nzvalues, items, FALSE)) | ||||
|     return( n ); | ||||
| 
 | ||||
|   /* Compute the number of non-empty columns */ | ||||
|   m = 0; | ||||
|   for(j = 1; j <= mapcol[0]; j++) { | ||||
|     n = cb(lp, mapcol[j], NULL, NULL, maprow); | ||||
|     if(n > 0) { | ||||
|       m++; | ||||
|       mapcol[m] = mapcol[j]; | ||||
|       nz += n; | ||||
|     } | ||||
|   } | ||||
|   mapcol[0] = m; | ||||
| 
 | ||||
|   /* Instantiate a LUSOL object */ | ||||
|   LUSOL = LUSOL_create(NULL, 0, LUSOL_PIVMOD_TRP, 0); | ||||
|   if((LUSOL == NULL) || !LUSOL_sizeto(LUSOL, items, m, nz*LUSOL_MULT_nz_a)) | ||||
|     goto Finish; | ||||
| 
 | ||||
|   /* Modify relevant LUSOL parameters */ | ||||
|   LUSOL->m = items; | ||||
|   LUSOL->n = m; | ||||
| #if 0 | ||||
|   LUSOL->luparm[LUSOL_IP_KEEPLU]        = FALSE; | ||||
|   LUSOL->luparm[LUSOL_IP_PIVOTTYPE]     = LUSOL_PIVMOD_TRP; | ||||
|   LUSOL->parmlu[LUSOL_RP_FACTORMAX_Lij] = 2.0; | ||||
| #endif | ||||
| 
 | ||||
|   /* Load the columns into LUSOL */ | ||||
|   for(j = 1; j <= m; j++) { | ||||
|     n = cb(lp, mapcol[j], nzvalues, nzrows, maprow); | ||||
|     i = LUSOL_loadColumn(LUSOL, nzrows, j, nzvalues, n, -1); | ||||
|     if(n != i) { | ||||
|       lp->report(lp, IMPORTANT, "bfp_findredundant: Error %d while loading column %d with %d nz\n", | ||||
|                                 i, j, n); | ||||
|       n = 0; | ||||
|       goto Finish; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /* Scale rows to prevent numerical problems */ | ||||
|   if((lp->scalemode != SCALE_NONE) && allocREAL(lp, &arraymax, items+1, TRUE)) { | ||||
|     for(i = 1; i <= nz; i++) { | ||||
|       SETMAX(arraymax[LUSOL->indc[i]], fabs(LUSOL->a[i])); | ||||
|     } | ||||
|     for(i = 1; i <= nz; i++) | ||||
|       LUSOL->a[i] /= arraymax[LUSOL->indc[i]]; | ||||
|     FREE(arraymax); | ||||
|   } | ||||
| 
 | ||||
|   /* Factorize for maximum rank */ | ||||
|   n = 0; | ||||
|   i = LUSOL_factorize(LUSOL); | ||||
|   /*  lp->report(lp, NORMAL, "bfp_findredundant: r=%d c=%d - %s\n", items, m, LUSOL_informstr(LUSOL, i));*/ | ||||
|   if((i == LUSOL_INFORM_LUSUCCESS) || (i != LUSOL_INFORM_LUSINGULAR)) | ||||
|     goto Finish; | ||||
| 
 | ||||
|   /* We have a singular matrix, obtain the indeces of the singular rows */ | ||||
|   for(i = LUSOL->luparm[LUSOL_IP_RANK_U] + 1; i <= items; i++) { | ||||
|     n++; | ||||
|     maprow[n] = LUSOL->ip[i]; | ||||
|   } | ||||
|   maprow[0] = n; | ||||
| 
 | ||||
|   /* Clean up */ | ||||
| Finish: | ||||
|   LUSOL_free(LUSOL); | ||||
|   FREE(nzrows); | ||||
|   FREE(nzvalues); | ||||
| 
 | ||||
|   return( n ); | ||||
| } | ||||
|  | @ -1,63 +0,0 @@ | |||
| #ifndef HEADER_lp_LUSOL | ||||
| #define HEADER_lp_LUSOL | ||||
| 
 | ||||
| /* Include libraries for this inverse system */ | ||||
| #include "lp_types.h" | ||||
| #include "lusol.h" | ||||
| 
 | ||||
| /* LUSOL defines */ | ||||
| #ifdef WIN32 | ||||
| # define LUSOL_UseBLAS | ||||
| #endif | ||||
| /*#define MAPSINGULARCOLUMN*/ | ||||
| #define MATINDEXBASE LUSOL_ARRAYOFFSET /* Inversion engine index start for arrays */ | ||||
| #define LU_START_SIZE           10000  /* Start size of LU; realloc'ed if needed */ | ||||
| #define DEF_MAXPIVOT              250  /* Maximum number of pivots before refactorization */ | ||||
| #define MAX_DELTAFILLIN           2.0  /* Do refactorizations based on sparsity considerations */ | ||||
| #define TIGHTENAFTER               10  /* Tighten LU pivot criteria only after this number of singularities */ | ||||
| 
 | ||||
| /* typedef */ struct _INVrec | ||||
| { | ||||
|   int       status;                 /* Last operation status code */ | ||||
|   int       dimcount;               /* The actual number of LU rows/columns */ | ||||
|   int       dimalloc;               /* The allocated LU rows/columns size */ | ||||
|   int       user_colcount;          /* The number of user LU columns */ | ||||
|   LUSOLrec  *LUSOL; | ||||
|   int       col_enter;              /* The full index of the entering column */ | ||||
|   int       col_leave;              /* The full index of the leaving column */ | ||||
|   int       col_pos;                /* The B column to be changed at the next update using data in value[.]*/ | ||||
|   REAL      *value; | ||||
|   REAL      *pcol;                  /* Reference to the elimination vector */ | ||||
|   REAL      theta_enter;            /* Value of the entering column theta */ | ||||
| 
 | ||||
|   int       max_Bsize;              /* The largest B matrix of user variables */ | ||||
|   int       max_colcount;           /* The maximum number of user columns in LU */ | ||||
|   int       max_LUsize;             /* The largest NZ-count of LU-files generated */ | ||||
|   int       num_refact;             /* Number of times the basis was refactored */ | ||||
|   int       num_timed_refact; | ||||
|   int       num_dense_refact; | ||||
|   double    time_refactstart;       /* Time since start of last refactorization-pivots cyle */ | ||||
|   double    time_refactnext;        /* Time estimated to next refactorization */ | ||||
|   int       num_pivots;             /* Number of pivots since last refactorization */ | ||||
|   int       num_singular;           /* The total number of singular updates */ | ||||
|   char      *opts; | ||||
|   MYBOOL    is_dirty;               /* Specifies if a column is incompletely processed */ | ||||
|   MYBOOL    force_refact;           /* Force refactorization at the next opportunity */ | ||||
|   MYBOOL    timed_refact;           /* Set if timer-driven refactorization should be active */ | ||||
|   MYBOOL    set_Bidentity;          /* Force B to be the identity matrix at the next refactorization */ | ||||
| } /* INVrec */; | ||||
| 
 | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| /* namespace LUSOL */ | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| /* Put function headers here */ | ||||
| #include "lp_BFP.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
|  } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* HEADER_lp_LUSOL */ | ||||
|  | @ -1,82 +0,0 @@ | |||
| 
 | ||||
| /* ---------------------------------------------------------------------------------- */ | ||||
| /* lp_solve v5+ headers for basis inversion / factorization libraries                 */ | ||||
| /* ---------------------------------------------------------------------------------- */ | ||||
| #define BFP_STATUS_RANKLOSS     -1 | ||||
| #define BFP_STATUS_SUCCESS       0 | ||||
| #define BFP_STATUS_SINGULAR      1 | ||||
| #define BFP_STATUS_UNSTABLE      2 | ||||
| #define BFP_STATUS_NOPIVOT       3 | ||||
| #define BFP_STATUS_DIMERROR      4 | ||||
| #define BFP_STATUS_DUPLICATE     5 | ||||
| #define BFP_STATUS_NOMEMORY      6 | ||||
| #define BFP_STATUS_ERROR         7             /* Unspecified, command-related error */ | ||||
| #define BFP_STATUS_FATAL         8 | ||||
| 
 | ||||
| #define BFP_STAT_ERROR          -1 | ||||
| #define BFP_STAT_REFACT_TOTAL    0 | ||||
| #define BFP_STAT_REFACT_TIMED    1 | ||||
| #define BFP_STAT_REFACT_DENSE    2 | ||||
| 
 | ||||
| #ifndef BFP_CALLMODEL | ||||
|   #ifdef WIN32 | ||||
|     #define BFP_CALLMODEL __stdcall   /* "Standard" call model */ | ||||
|   #else | ||||
|     #define BFP_CALLMODEL | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| #ifdef RoleIsExternalInvEngine | ||||
|   #define __BFP_EXPORT_TYPE __EXPORT_TYPE | ||||
| #else | ||||
|   #define __BFP_EXPORT_TYPE | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /* Routines with UNIQUE implementations for each inversion engine                     */ | ||||
| /* ---------------------------------------------------------------------------------- */ | ||||
| char   __BFP_EXPORT_TYPE *(BFP_CALLMODEL bfp_name)(void); | ||||
| void   __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_free)(lprec *lp); | ||||
| MYBOOL __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_resize)(lprec *lp, int newsize); | ||||
| int    __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_nonzeros)(lprec *lp, MYBOOL maximum); | ||||
| int    __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_memallocated)(lprec *lp); | ||||
| int    __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_preparefactorization)(lprec *lp); | ||||
| int    __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_factorize)(lprec *lp, int uservars, int Bsize, MYBOOL *usedpos, MYBOOL final); | ||||
| MYBOOL __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_finishupdate)(lprec *lp, MYBOOL changesign); | ||||
| void   __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_ftran_normal)(lprec *lp, REAL *pcol, int *nzidx); | ||||
| void   __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_ftran_prepare)(lprec *lp, REAL *pcol, int *nzidx); | ||||
| void   __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_btran_normal)(lprec *lp, REAL *prow, int *nzidx); | ||||
| int    __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_status)(lprec *lp); | ||||
| int    __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_findredundant)(lprec *lp, int items, getcolumnex_func cb, int *maprow, int*mapcol); | ||||
| 
 | ||||
| 
 | ||||
| /* Routines SHARED for all inverse implementations; located in lp_BFP1.c              */ | ||||
| /* ---------------------------------------------------------------------------------- */ | ||||
| MYBOOL __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_compatible)(lprec *lp, int bfpversion, int lpversion, int sizeofvar); | ||||
| int    __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_indexbase)(lprec *lp); | ||||
| int    __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_rowoffset)(lprec *lp); | ||||
| int    __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_pivotmax)(lprec *lp); | ||||
| REAL   __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_efficiency)(lprec *lp); | ||||
| REAL   __BFP_EXPORT_TYPE *(BFP_CALLMODEL bfp_pivotvector)(lprec *lp); | ||||
| int    __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_pivotcount)(lprec *lp); | ||||
| MYBOOL __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_mustrefactorize)(lprec *lp); | ||||
| int    __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_refactcount)(lprec *lp, int kind); | ||||
| MYBOOL __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_isSetI)(lprec *lp); | ||||
| int    *bfp_createMDO(lprec *lp, MYBOOL *usedpos, int count, MYBOOL doMDO); | ||||
| void   BFP_CALLMODEL bfp_updaterefactstats(lprec *lp); | ||||
| int    BFP_CALLMODEL bfp_rowextra(lprec *lp); | ||||
| 
 | ||||
| /* Routines with OPTIONAL SHARED code; template routines suitable for canned          */ | ||||
| /* inverse engines are located in lp_BFP2.c                                           */ | ||||
| /* ---------------------------------------------------------------------------------- */ | ||||
| MYBOOL __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_init)(lprec *lp, int size, int deltasize, char *options); | ||||
| MYBOOL __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_restart)(lprec *lp); | ||||
| MYBOOL __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_implicitslack)(lprec *lp); | ||||
| MYBOOL __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_pivotalloc)(lprec *lp, int newsize); | ||||
| int    __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_colcount)(lprec *lp); | ||||
| MYBOOL __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_canresetbasis)(lprec *lp); | ||||
| void   __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_finishfactorization)(lprec *lp); | ||||
| LREAL  __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_prepareupdate)(lprec *lp, int row_nr, int col_nr, REAL *pcol); | ||||
| REAL   __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_pivotRHS)(lprec *lp, LREAL theta, REAL *pcol); | ||||
| void   __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_btran_double)(lprec *lp, REAL *prow, int *pnzidx, REAL *drow, int *dnzidx); | ||||
| 
 | ||||
|  | @ -1,206 +0,0 @@ | |||
| 
 | ||||
| /* Routines located in lp_BFP1.cpp; common for all factorization engines              */ | ||||
| /* Cfr. lp_BFP.h for definitions                                                      */ | ||||
| /* ---------------------------------------------------------------------------------- */ | ||||
| /* Changes:                                                                           */ | ||||
| /* 29 May 2004       Corrected calculation of bfp_efficiency(), which required        */ | ||||
| /*                   modifying the max_Bsize to include slack variables. KE.          */ | ||||
| /* 16 June 2004      Make the symbolic minimum degree ordering routine available      */ | ||||
| /*                   to BFPs as a routine internal to the library. KE                 */ | ||||
| /* 1  July 2004      Change due to change in MDO naming.                              */ | ||||
| /* ---------------------------------------------------------------------------------- */ | ||||
| 
 | ||||
| 
 | ||||
| /* MUST MODIFY */ | ||||
| MYBOOL BFP_CALLMODEL bfp_compatible(lprec *lp, int bfpversion, int lpversion, int sizeofvar) | ||||
| { | ||||
|   MYBOOL status = FALSE; | ||||
| 
 | ||||
|   if((lp != NULL) && (bfpversion == BFPVERSION) && (sizeof(REAL) == sizeofvar)) { | ||||
| #if 0 | ||||
|     if(lpversion == MAJORVERSION)  /* Forces BFP renewal at lp_solve major version changes */ | ||||
| #endif | ||||
|       status = TRUE; | ||||
|   } | ||||
|   return( status ); | ||||
| } | ||||
| 
 | ||||
| /* DON'T MODIFY */ | ||||
| int BFP_CALLMODEL bfp_status(lprec *lp) | ||||
| { | ||||
|   return(lp->invB->status); | ||||
| } | ||||
| 
 | ||||
| /* DON'T MODIFY */ | ||||
| int BFP_CALLMODEL bfp_indexbase(lprec *lp) | ||||
| { | ||||
|   return( MATINDEXBASE ); | ||||
| } | ||||
| 
 | ||||
| /* DON'T MODIFY */ | ||||
| int BFP_CALLMODEL bfp_rowoffset(lprec *lp) | ||||
| { | ||||
|   if(lp->obj_in_basis) | ||||
|     return( 1 ); | ||||
|   else | ||||
|     return( 0 ); | ||||
| } | ||||
| 
 | ||||
| /* DON'T MODIFY */ | ||||
| int BFP_CALLMODEL bfp_pivotmax(lprec *lp) | ||||
| { | ||||
|   if(lp->max_pivots > 0) | ||||
|     return( lp->max_pivots ); | ||||
|   else | ||||
|     return( DEF_MAXPIVOT ); | ||||
| } | ||||
| 
 | ||||
| /* DON'T MODIFY */ | ||||
| REAL * BFP_CALLMODEL bfp_pivotvector(lprec *lp) | ||||
| { | ||||
|   return( lp->invB->pcol ); | ||||
| } | ||||
| 
 | ||||
| /* DON'T MODIFY */ | ||||
| REAL BFP_CALLMODEL bfp_efficiency(lprec *lp) | ||||
| { | ||||
|   REAL hold; | ||||
| 
 | ||||
|   hold = lp->bfp_nonzeros(lp, AUTOMATIC); | ||||
|   if(hold == 0) | ||||
|     hold = 1 + lp->rows; | ||||
|   hold = lp->bfp_nonzeros(lp, TRUE)/hold; | ||||
| 
 | ||||
|   return(hold); | ||||
| } | ||||
| 
 | ||||
| /* DON'T MODIFY */ | ||||
| int BFP_CALLMODEL bfp_pivotcount(lprec *lp) | ||||
| { | ||||
|   return(lp->invB->num_pivots); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* DON'T MODIFY */ | ||||
| int BFP_CALLMODEL bfp_refactcount(lprec *lp, int kind) | ||||
| { | ||||
|   if(kind == BFP_STAT_REFACT_TOTAL) | ||||
|     return(lp->invB->num_refact); | ||||
|   else if(kind == BFP_STAT_REFACT_TIMED) | ||||
|     return(lp->invB->num_timed_refact); | ||||
|   else if(kind == BFP_STAT_REFACT_DENSE) | ||||
|     return(lp->invB->num_dense_refact); | ||||
|   else | ||||
|     return( BFP_STAT_ERROR ); | ||||
| } | ||||
| 
 | ||||
| /* DON'T MODIFY */ | ||||
| MYBOOL BFP_CALLMODEL bfp_mustrefactorize(lprec *lp) | ||||
| { | ||||
|   MYBOOL test = lp->is_action(lp->spx_action, ACTION_REINVERT | ACTION_TIMEDREINVERT); | ||||
|   if(!test) { | ||||
|     REAL   f; | ||||
|     INVrec *lu = lp->invB; | ||||
| 
 | ||||
|     if(lu->num_pivots > 0) | ||||
|       f = (timeNow()-lu->time_refactstart) / (REAL) lu->num_pivots; | ||||
|     else | ||||
|       f = 0; | ||||
| 
 | ||||
|     /* Always refactorize if we are above the set pivot limit */ | ||||
|     if(lu->force_refact || | ||||
|        (lu->num_pivots >= lp->bfp_pivotmax(lp))) | ||||
|       lp->set_action(&lp->spx_action, ACTION_REINVERT); | ||||
| 
 | ||||
|     /* Check if we should do an optimal time-based refactorization */ | ||||
|     else if(lu->timed_refact && (lu->num_pivots > 1) && | ||||
|             (f > MIN_TIMEPIVOT) && (f > lu->time_refactnext)) { | ||||
|       /* If we have excessive time usage in automatic mode then
 | ||||
|          treat as untimed case and update optimal time metric, ... */ | ||||
|       if((lu->timed_refact == AUTOMATIC) && | ||||
|          (lu->num_pivots < 0.4*lp->bfp_pivotmax(lp))) | ||||
|         lu->time_refactnext = f; | ||||
|       /* ... otherwise set flag for the optimal time-based refactorization */ | ||||
|       else | ||||
|         lp->set_action(&lp->spx_action, ACTION_TIMEDREINVERT); | ||||
|     } | ||||
| 
 | ||||
|     /* Otherwise simply update the optimal time metric */ | ||||
|     else | ||||
|       lu->time_refactnext = f; | ||||
| #if 0 | ||||
|     if(lu->num_pivots % 10 == 0) | ||||
|       lp->report(lp, NORMAL, "bfp pivot %d - start %f - timestat %f", | ||||
|                              lu->num_pivots, lu->time_refactstart, f); | ||||
| #endif | ||||
|   } | ||||
| 
 | ||||
|   test = lp->is_action(lp->spx_action, ACTION_REINVERT | ACTION_TIMEDREINVERT); | ||||
|   return(test); | ||||
| } | ||||
| 
 | ||||
| /* DON'T MODIFY */ | ||||
| MYBOOL BFP_CALLMODEL bfp_isSetI(lprec *lp) | ||||
| { | ||||
|   return( (MYBOOL) lp->invB->set_Bidentity ); | ||||
| } | ||||
| 
 | ||||
| /* DON'T MODIFY */ | ||||
| int *bfp_createMDO(lprec *lp, MYBOOL *usedpos, int count, MYBOOL doMDO) | ||||
| { | ||||
|   int *mdo, i, j, kk; | ||||
| 
 | ||||
|   mdo = (int *) malloc((count + 1)*sizeof(*mdo)); | ||||
| /*  allocINT(lp, &mdo, count + 1, FALSE); */ | ||||
| 
 | ||||
|  /* Fill the mdo[] array with remaining full-pivot basic user variables */ | ||||
|   kk = 0; | ||||
|   for(j = 1; j <= lp->columns; j++) { | ||||
|     i = lp->rows + j; | ||||
|     if(usedpos[i] == TRUE) { | ||||
|       kk++; | ||||
|       mdo[kk] = i; | ||||
|     } | ||||
|   } | ||||
|   mdo[0] = kk; | ||||
|   if(kk == 0) | ||||
|     goto Process; | ||||
| 
 | ||||
|  /* Calculate the approximate minimum degree column ordering */ | ||||
|   if(doMDO) { | ||||
|     i = lp->getMDO(lp, usedpos, mdo, NULL, FALSE); | ||||
|     if(i != 0) { | ||||
|       lp->report(lp, CRITICAL, "bfp_createMDO: Internal error %d in minimum degree ordering routine", i); | ||||
|       FREE(mdo); | ||||
|     } | ||||
|   } | ||||
| Process: | ||||
|   return( mdo ); | ||||
| } | ||||
| void BFP_CALLMODEL bfp_updaterefactstats(lprec *lp) | ||||
| { | ||||
|   INVrec *lu = lp->invB; | ||||
| 
 | ||||
|   /* Signal that we are refactorizing */ | ||||
|   lu->is_dirty = AUTOMATIC; | ||||
| 
 | ||||
|   /* Set time of start of current refactorization cycle */ | ||||
|   lu->time_refactstart = timeNow(); | ||||
|   lu->time_refactnext  = 0; | ||||
|   lu->user_colcount = 0; | ||||
| 
 | ||||
|   /* Do the numbers */ | ||||
|   if(lu->force_refact) | ||||
|     lu->num_dense_refact++; | ||||
|   else if(lu->timed_refact && lp->is_action(lp->spx_action, ACTION_TIMEDREINVERT)) | ||||
|     lu->num_timed_refact++; | ||||
|   lu->num_refact++; | ||||
| } | ||||
| 
 | ||||
| int BFP_CALLMODEL bfp_rowextra(lprec *lp) | ||||
| { | ||||
|   if(lp->is_obj_in_basis(lp)) | ||||
|     return( 1 ); | ||||
|   else | ||||
|     return( 0 ); | ||||
| } | ||||
|  | @ -1,177 +0,0 @@ | |||
| 
 | ||||
| 
 | ||||
| /* Routines located in lp_BFP2.cpp; optional shared for canned implementations        */ | ||||
| /* Cfr. lp_BFP.h for definitions                                                      */ | ||||
| /* ---------------------------------------------------------------------------------- */ | ||||
| 
 | ||||
| 
 | ||||
| /* DON'T MODIFY */ | ||||
| MYBOOL BFP_CALLMODEL bfp_init(lprec *lp, int size, int delta, char *options) | ||||
| { | ||||
|   INVrec *lu; | ||||
| 
 | ||||
|   lp->invB = (INVrec *) calloc(1, sizeof(*(lp->invB))); | ||||
|   lu = lp->invB; | ||||
|   if((lu == NULL) ||  | ||||
|      !lp->bfp_resize(lp, size) || | ||||
|      !lp->bfp_restart(lp)) | ||||
|     return( FALSE ); | ||||
| 
 | ||||
|   /* Store any passed options */ | ||||
|   if(options != NULL) { | ||||
|     size_t len = strlen(options); | ||||
|     lu->opts = (char *) malloc(len + 1); | ||||
|     strcpy(lu->opts, options); | ||||
|   } | ||||
| 
 | ||||
|   /* Prepare for factorization and undo values reset by bfp_preparefactorization */ | ||||
|   lp->bfp_preparefactorization(lp); | ||||
|   lu->num_refact = 0; | ||||
| 
 | ||||
|   return( TRUE ); | ||||
| } | ||||
| 
 | ||||
| /* DON'T MODIFY */ | ||||
| MYBOOL BFP_CALLMODEL bfp_restart(lprec *lp) | ||||
| { | ||||
|   INVrec *lu; | ||||
| 
 | ||||
|   lu = lp->invB; | ||||
|   if(lu == NULL) | ||||
|     return( FALSE ); | ||||
| 
 | ||||
|   lu->status = BFP_STATUS_SUCCESS; | ||||
|   lu->max_Bsize = 0;          /* The largest NZ-count of the B matrix            */ | ||||
|   lu->max_colcount = 0;       /* The maximum number of user columns in B         */ | ||||
|   lu->max_LUsize = 0;         /* The largest NZ-count of LU-files generated      */ | ||||
|   lu->num_refact = 0;         /* The number of times the basis has been factored */ | ||||
|   lu->num_timed_refact = 0; | ||||
|   lu->num_dense_refact = 0; | ||||
|   lu->num_pivots = 0;         /* The number of pivots since last factorization   */ | ||||
|   lu->pcol = NULL; | ||||
|   lu->set_Bidentity = FALSE; | ||||
| 
 | ||||
|   return( TRUE ); | ||||
| } | ||||
| 
 | ||||
| /* DON'T MODIFY */ | ||||
| MYBOOL BFP_CALLMODEL bfp_implicitslack(lprec *lp) | ||||
| { | ||||
|   return( FALSE ); | ||||
| } | ||||
| 
 | ||||
| /* DON'T MODIFY */ | ||||
| int BFP_CALLMODEL bfp_colcount(lprec *lp) | ||||
| { | ||||
|   return(lp->invB->user_colcount); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* DON'T MODIFY */ | ||||
| MYBOOL BFP_CALLMODEL bfp_canresetbasis(lprec *lp) | ||||
| { | ||||
|   return( FALSE ); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* DON'T MODIFY */ | ||||
| MYBOOL BFP_CALLMODEL bfp_pivotalloc(lprec *lp, int newsize) | ||||
| { | ||||
|   /* Does nothing in the default implementation */ | ||||
|   return( TRUE ); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* DON'T MODIFY */ | ||||
| void BFP_CALLMODEL bfp_finishfactorization(lprec *lp) | ||||
| { | ||||
|   INVrec *lu; | ||||
| 
 | ||||
|   lu = lp->invB; | ||||
| 
 | ||||
|   SETMAX(lu->max_colcount, lp->bfp_colcount(lp)); | ||||
|   SETMAX(lu->max_LUsize, lp->bfp_nonzeros(lp, FALSE)); | ||||
| 
 | ||||
|   /* Signal that we done factorizing/reinverting */ | ||||
|   lu->is_dirty = FALSE; | ||||
|   lp->clear_action(&lp->spx_action, ACTION_REINVERT | ACTION_TIMEDREINVERT); | ||||
|   lu->force_refact = FALSE; | ||||
| 
 | ||||
|   /* Store information about the current inverse */ | ||||
|   lu->num_pivots = 0; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* DON'T MODIFY */ | ||||
| LREAL BFP_CALLMODEL bfp_prepareupdate(lprec *lp, int row_nr, int col_nr, REAL *pcol) | ||||
| /* Was condensecol() in versions of lp_solve before 4.0.1.8 - KE */ | ||||
| { | ||||
|   LREAL  pivValue; | ||||
|   INVrec *lu; | ||||
| 
 | ||||
|   lu = lp->invB; | ||||
| 
 | ||||
|   /* Store the incoming pivot value for RHS update purposes */ | ||||
|   lu->col_enter = col_nr;  /* The index of the new data column */ | ||||
|   lu->col_pos   = row_nr;  /* The basis column to be replaced */ | ||||
|   lu->col_leave = lp->var_basic[row_nr]; | ||||
|   if(pcol == NULL) | ||||
|     pivValue = 0; | ||||
|   else | ||||
|     pivValue = pcol[row_nr]; | ||||
|   lu->theta_enter = pivValue; | ||||
| 
 | ||||
|   /* Save reference to the elimination vector */ | ||||
|   lu->pcol = pcol; | ||||
| 
 | ||||
|   /* Set completion status; but hold if we are reinverting */ | ||||
|   if(lu->is_dirty != AUTOMATIC) | ||||
|     lu->is_dirty = TRUE; | ||||
| 
 | ||||
|   return( pivValue ); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* DON'T MODIFY */ | ||||
| REAL BFP_CALLMODEL bfp_pivotRHS(lprec *lp, LREAL theta, REAL *pcol) | ||||
| /* This function is used to adjust the RHS in bound swap operations as
 | ||||
|    well as handling the updating of the RHS for normal basis changes. | ||||
|    Was rhsmincol(), ie. "rhs minus column" in versions of lp_solve before 4.0.1.8 - KE */ | ||||
| { | ||||
|   INVrec    *lu; | ||||
| 
 | ||||
|   lu = lp->invB; | ||||
| 
 | ||||
|   if(pcol == NULL) | ||||
|     pcol = lu->pcol; | ||||
| 
 | ||||
|   if(theta != 0) { | ||||
|     register int    i, n = lp->rows; | ||||
|     register LREAL  roundzero = lp->epsvalue; | ||||
|     register LREAL  *rhs = lp->rhs, rhsmax = 0; | ||||
| 
 | ||||
|     for(i = 0; i <= n; i++, rhs++, pcol++) { | ||||
|       (*rhs) -= theta * (*pcol); | ||||
|       my_roundzero(*rhs, roundzero); | ||||
|       SETMAX(rhsmax, fabs(*rhs)); | ||||
|     } | ||||
|     lp->rhsmax = rhsmax; | ||||
|   } | ||||
| 
 | ||||
|   if(pcol == lu->pcol) | ||||
|     return( lu->theta_enter ); | ||||
|   else | ||||
|     return( 0.0 ); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* DON'T MODIFY */ | ||||
| void BFP_CALLMODEL bfp_btran_double(lprec *lp, REAL *prow, int *pnzidx, REAL *drow, int *dnzidx) | ||||
| { | ||||
|   if(prow != NULL) | ||||
|     lp->bfp_btran_normal(lp, prow, pnzidx); | ||||
|   if(drow != NULL) | ||||
|     lp->bfp_btran_normal(lp, drow, dnzidx); | ||||
| } | ||||
| 
 | ||||
|  | @ -1,27 +0,0 @@ | |||
| # Look for lpsolve | ||||
| # | ||||
| # Set | ||||
| #  lpsolve_FOUND = TRUE | ||||
| #  lpsolve_INCLUDE_DIRS = /usr/local/include | ||||
| #  lpsolve_LIBRARY = /usr/local/lib/liblpsolve.so | ||||
| #  lpsolve_LIBRARY_DIRS = /usr/local/lib | ||||
| 
 | ||||
| set(lpsolve_BUILD_PATH "${CMAKE_SOURCE_DIR}/gtsam/3rdparty/lp_solve_5.5/lpsolve55") | ||||
| find_library (lpsolve_LIBRARY liblpsolve55.a PATHS ${lpsolve_BUILD_PATH}) | ||||
| 
 | ||||
| if (lpsolve_LIBRARY) | ||||
|   get_filename_component (lpsolve_LIBRARY_DIRS "${lpsolve_LIBRARY}" PATH) | ||||
|   get_filename_component (_ROOT_DIR "${lpsolve_LIBRARY_DIRS}" PATH) | ||||
|   set (lpsolve_FOUND TRUE) | ||||
|   set (lpsolve_INCLUDE_DIRS "${_ROOT_DIR}") | ||||
|   unset (_ROOT_DIR) | ||||
|   if (NOT EXISTS "${lpsolve_INCLUDE_DIRS}/lp_lib.h") | ||||
|     unset (lpsolve_INCLUDE_DIRS) | ||||
|     unset (lpsolve_LIBRARY) | ||||
|     unset (lpsolve_LIBRARY_DIRS) | ||||
|   endif () | ||||
| endif () | ||||
| 
 | ||||
| include (FindPackageHandleStandardArgs) | ||||
| find_package_handle_standard_args (lpsolve DEFAULT_MSG lpsolve_LIBRARY_DIRS lpsolve_LIBRARY lpsolve_INCLUDE_DIRS) | ||||
| mark_as_advanced (lpsolve_LIBRARY_DIRS lpsolve_LIBRARY lpsolve_INCLUDE_DIRS) | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -1,286 +0,0 @@ | |||
| /* ========================================================================== */ | ||||
| /* === colamd/symamd prototypes and definitions ============================= */ | ||||
| /* ========================================================================== */ | ||||
| 
 | ||||
| /*
 | ||||
|     You must include this file (colamd.h) in any routine that uses colamd, | ||||
|     symamd, or the related macros and definitions. | ||||
| 
 | ||||
|     Authors: | ||||
| 
 | ||||
| 	The authors of the code itself are Stefan I. Larimore and Timothy A. | ||||
| 	Davis (davis@cise.ufl.edu), University of Florida.  The algorithm was | ||||
| 	developed in collaboration with John Gilbert, Xerox PARC, and Esmond | ||||
| 	Ng, Oak Ridge National Laboratory. | ||||
| 
 | ||||
|     Date: | ||||
| 
 | ||||
| 	May 4, 2001.  Version 2.1. | ||||
| 
 | ||||
|     Acknowledgements: | ||||
| 
 | ||||
| 	This work was supported by the National Science Foundation, under | ||||
| 	grants DMS-9504974 and DMS-9803599. | ||||
| 
 | ||||
|     Notice: | ||||
| 
 | ||||
| 	Copyright (c) 1998-2001 by the University of Florida. | ||||
| 	All Rights Reserved. | ||||
| 
 | ||||
| 	THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY | ||||
| 	EXPRESSED OR IMPLIED.  ANY USE IS AT YOUR OWN RISK. | ||||
| 
 | ||||
| 	Permission is hereby granted to use or copy this program for any | ||||
| 	purpose, provided the above notices are retained on all copies. | ||||
| 	User documentation of any code that uses this code must cite the | ||||
| 	Authors, the Copyright, and "Used by permission."  If this code is | ||||
| 	accessible from within Matlab, then typing "help colamd" and "help | ||||
| 	symamd" must cite the Authors.  Permission to modify the code and to | ||||
| 	distribute modified code is granted, provided the above notices are | ||||
| 	retained, and a notice that the code was modified is included with the | ||||
| 	above copyright notice.  You must also retain the Availability | ||||
| 	information below, of the original version. | ||||
| 
 | ||||
| 	This software is provided free of charge. | ||||
| 
 | ||||
|     Availability: | ||||
| 
 | ||||
| 	The colamd/symamd library is available at | ||||
| 
 | ||||
| 	    http://www.cise.ufl.edu/research/sparse/colamd
 | ||||
| 
 | ||||
| 	This is the http://www.cise.ufl.edu/research/sparse/colamd/colamd.h
 | ||||
| 	file.  It is required by the colamd.c, colamdmex.c, and symamdmex.c | ||||
| 	files, and by any C code that calls the routines whose prototypes are | ||||
| 	listed below, or that uses the colamd/symamd definitions listed below. | ||||
| 
 | ||||
| */ | ||||
| 
 | ||||
| #ifndef COLAMD_H | ||||
| #define COLAMD_H | ||||
| 
 | ||||
| /* ========================================================================== */ | ||||
| /* === Include files ======================================================== */ | ||||
| /* ========================================================================== */ | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| /* ========================================================================== */ | ||||
| /* === Knob and statistics definitions ====================================== */ | ||||
| /* ========================================================================== */ | ||||
| 
 | ||||
| /* size of the knobs [ ] array.  Only knobs [0..1] are currently used. */ | ||||
| #define COLAMD_KNOBS 20 | ||||
| 
 | ||||
| /* number of output statistics.  Only stats [0..6] are currently used. */ | ||||
| #define COLAMD_STATS 20 | ||||
| 
 | ||||
| /* knobs [0] and stats [0]: dense row knob and output statistic. */ | ||||
| #define COLAMD_DENSE_ROW 0 | ||||
| 
 | ||||
| /* knobs [1] and stats [1]: dense column knob and output statistic. */ | ||||
| #define COLAMD_DENSE_COL 1 | ||||
| 
 | ||||
| /* stats [2]: memory defragmentation count output statistic */ | ||||
| #define COLAMD_DEFRAG_COUNT 2 | ||||
| 
 | ||||
| /* stats [3]: colamd status:  zero OK, > 0 warning or notice, < 0 error */ | ||||
| #define COLAMD_STATUS 3 | ||||
| 
 | ||||
| /* stats [4..6]: error info, or info on jumbled columns */ | ||||
| #define COLAMD_INFO1 4 | ||||
| #define COLAMD_INFO2 5 | ||||
| #define COLAMD_INFO3 6 | ||||
| 
 | ||||
| /* error codes returned in stats [3]: */ | ||||
| #define COLAMD_OK				(0) | ||||
| #define COLAMD_OK_BUT_JUMBLED			(1) | ||||
| #define COLAMD_ERROR_A_not_present		(-1) | ||||
| #define COLAMD_ERROR_p_not_present		(-2) | ||||
| #define COLAMD_ERROR_nrow_negative		(-3) | ||||
| #define COLAMD_ERROR_ncol_negative		(-4) | ||||
| #define COLAMD_ERROR_nnz_negative		(-5) | ||||
| #define COLAMD_ERROR_p0_nonzero			(-6) | ||||
| #define COLAMD_ERROR_A_too_small		(-7) | ||||
| #define COLAMD_ERROR_col_length_negative	(-8) | ||||
| #define COLAMD_ERROR_row_index_out_of_bounds	(-9) | ||||
| #define COLAMD_ERROR_out_of_memory		(-10) | ||||
| #define COLAMD_ERROR_internal_error		(-999) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /* ========================================================================== */ | ||||
| /* === Row and Column structures ============================================ */ | ||||
| /* ========================================================================== */ | ||||
| 
 | ||||
| /* User code that makes use of the colamd/symamd routines need not directly */ | ||||
| /* reference these structures.  They are used only for the COLAMD_RECOMMENDED */ | ||||
| /* macro. */ | ||||
| 
 | ||||
| typedef struct Colamd_Col_struct | ||||
| { | ||||
|     int start ;		/* index for A of first row in this column, or DEAD */ | ||||
| 			/* if column is dead */ | ||||
|     int length ;	/* number of rows in this column */ | ||||
|     union | ||||
|     { | ||||
| 	int thickness ;	/* number of original columns represented by this */ | ||||
| 			/* col, if the column is alive */ | ||||
| 	int parent ;	/* parent in parent tree super-column structure, if */ | ||||
| 			/* the column is dead */ | ||||
|     } shared1 ; | ||||
|     union | ||||
|     { | ||||
| 	int score ;	/* the score used to maintain heap, if col is alive */ | ||||
| 	int order ;	/* pivot ordering of this column, if col is dead */ | ||||
|     } shared2 ; | ||||
|     union | ||||
|     { | ||||
| 	int headhash ;	/* head of a hash bucket, if col is at the head of */ | ||||
| 			/* a degree list */ | ||||
| 	int hash ;	/* hash value, if col is not in a degree list */ | ||||
| 	int prev ;	/* previous column in degree list, if col is in a */ | ||||
| 			/* degree list (but not at the head of a degree list) */ | ||||
|     } shared3 ; | ||||
|     union | ||||
|     { | ||||
| 	int degree_next ;	/* next column, if col is in a degree list */ | ||||
| 	int hash_next ;		/* next column, if col is in a hash list */ | ||||
|     } shared4 ; | ||||
| 
 | ||||
| } Colamd_Col ; | ||||
| 
 | ||||
| typedef struct Colamd_Row_struct | ||||
| { | ||||
|     int start ;		/* index for A of first col in this row */ | ||||
|     int length ;	/* number of principal columns in this row */ | ||||
|     union | ||||
|     { | ||||
| 	int degree ;	/* number of principal & non-principal columns in row */ | ||||
| 	int p ;		/* used as a row pointer in init_rows_cols () */ | ||||
|     } shared1 ; | ||||
|     union | ||||
|     { | ||||
| 	int mark ;	/* for computing set differences and marking dead rows*/ | ||||
| 	int first_column ;/* first column in row (used in garbage collection) */ | ||||
|     } shared2 ; | ||||
| 
 | ||||
| } Colamd_Row ; | ||||
| 
 | ||||
| /* ========================================================================== */ | ||||
| /* === Colamd recommended memory size ======================================= */ | ||||
| /* ========================================================================== */ | ||||
| 
 | ||||
| /*
 | ||||
|     The recommended length Alen of the array A passed to colamd is given by | ||||
|     the COLAMD_RECOMMENDED (nnz, n_row, n_col) macro.  It returns -1 if any | ||||
|     argument is negative.  2*nnz space is required for the row and column | ||||
|     indices of the matrix. COLAMD_C (n_col) + COLAMD_R (n_row) space is | ||||
|     required for the Col and Row arrays, respectively, which are internal to | ||||
|     colamd.  An additional n_col space is the minimal amount of "elbow room", | ||||
|     and nnz/5 more space is recommended for run time efficiency. | ||||
| 
 | ||||
|     This macro is not needed when using symamd. | ||||
| */ | ||||
| 
 | ||||
| #define COLAMD_C(n_col) (((n_col) + 1) * sizeof (Colamd_Col) / sizeof (int)) | ||||
| #define COLAMD_R(n_row) (((n_row) + 1) * sizeof (Colamd_Row) / sizeof (int)) | ||||
| 
 | ||||
| #define COLAMD_RECOMMENDED(nnz, n_row, n_col)                                 \ | ||||
| (                                                                             \ | ||||
| ((nnz) < 0 || (n_row) < 0 || (n_col) < 0)                                     \ | ||||
| ?                                                                             \ | ||||
|     (-1)                                                                      \ | ||||
| :                                                                             \ | ||||
|     (2 * (nnz) + COLAMD_C (n_col) + COLAMD_R (n_row) + (n_col) + ((nnz) / 5)) \ | ||||
| ) | ||||
| 
 | ||||
| /* ========================================================================== */ | ||||
| /* === Prototypes of user-callable routines ================================= */ | ||||
| /* ========================================================================== */ | ||||
| 
 | ||||
| /*
 | ||||
| #ifdef __cplusplus | ||||
|   #define __EXTERN_C extern "C" | ||||
| #else | ||||
|   #define __EXTERN_C | ||||
| #endif | ||||
| */ | ||||
| 
 | ||||
| #ifndef __BORLANDC__ | ||||
| 
 | ||||
|   #ifdef __cplusplus | ||||
|     #define __EXTERN_C extern "C" | ||||
|   #else | ||||
|     #define __EXTERN_C | ||||
|   #endif | ||||
| 
 | ||||
| #else  /* Otherwise set up for the Borland compiler */ | ||||
| 
 | ||||
|   #define __EXTERN_C extern "C" | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| __EXTERN_C { | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| int colamd_recommended		/* returns recommended value of Alen, */ | ||||
| 				/* or (-1) if input arguments are erroneous */ | ||||
| ( | ||||
|     int nnz,			/* nonzeros in A */ | ||||
|     int n_row,		/* number of rows in A */ | ||||
|     int n_col			/* number of columns in A */ | ||||
| ) ; | ||||
| 
 | ||||
| void colamd_set_defaults	/* sets default parameters */ | ||||
| (				/* knobs argument is modified on output */ | ||||
|     double knobs [COLAMD_KNOBS]	/* parameter settings for colamd */ | ||||
| ) ; | ||||
| 
 | ||||
| int colamd			/* returns (1) if successful, (0) otherwise*/ | ||||
| (				/* A and p arguments are modified on output */ | ||||
|     int n_row,		/* number of rows in A */ | ||||
|     int n_col,		/* number of columns in A */ | ||||
|     int Alen,			/* size of the array A */ | ||||
|     int A [],			/* row indices of A, of size Alen */ | ||||
|     int p [],			/* column pointers of A, of size n_col+1 */ | ||||
|     double knobs [COLAMD_KNOBS],/* parameter settings for colamd */ | ||||
|     int stats [COLAMD_STATS]	/* colamd output statistics and error codes */ | ||||
| ) ; | ||||
| 
 | ||||
| int symamd				/* return (1) if OK, (0) otherwise */ | ||||
| ( | ||||
|     int n,				/* number of rows and columns of A */ | ||||
|     int A [],			/* row indices of A */ | ||||
|     int p [],			/* column pointers of A */ | ||||
|     int perm [],	/* output permutation, size n_col+1 */ | ||||
|     double knobs [COLAMD_KNOBS],	/* parameters (uses defaults if NULL) */ | ||||
|     int stats [COLAMD_STATS],		/* output statistics and error codes */ | ||||
|     void * (*allocate) (size_t, size_t), | ||||
|     					/* pointer to calloc (ANSI C) or */ | ||||
| 					/* mxCalloc (for Matlab mexFunction) */ | ||||
|     void (*release) (void *) | ||||
|     					/* pointer to free (ANSI C) or */ | ||||
|     					/* mxFree (for Matlab mexFunction) */ | ||||
| ) ; | ||||
| 
 | ||||
| void colamd_report | ||||
| ( | ||||
|     int stats [COLAMD_STATS] | ||||
| ) ; | ||||
| 
 | ||||
| void symamd_report | ||||
| ( | ||||
|     int stats [COLAMD_STATS] | ||||
| ) ; | ||||
| 
 | ||||
| #endif /* COLAMD_H */ | ||||
| 
 | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
|  | @ -1,144 +0,0 @@ | |||
| This file contains any messages produced by compilers while | ||||
| running configure, to aid debugging if configure makes a mistake. | ||||
| 
 | ||||
| It was created by lpsolve configure 5.5.0.11, which was | ||||
| generated by GNU Autoconf 2.59.  Invocation command line was | ||||
| 
 | ||||
|   $ ./configure --prefix /Users/thduynguyen/install | ||||
| 
 | ||||
| ## --------- ## | ||||
| ## Platform. ## | ||||
| ## --------- ## | ||||
| 
 | ||||
| hostname = lawn-143-215-58-168.lawn.gatech.edu | ||||
| uname -m = x86_64 | ||||
| uname -r = 12.5.0 | ||||
| uname -s = Darwin | ||||
| uname -v = Darwin Kernel Version 12.5.0: Sun Sep 29 13:33:47 PDT 2013; root:xnu-2050.48.12~1/RELEASE_X86_64 | ||||
| 
 | ||||
| /usr/bin/uname -p = i386 | ||||
| /bin/uname -X     = unknown | ||||
| 
 | ||||
| /bin/arch              = unknown | ||||
| /usr/bin/arch -k       = unknown | ||||
| /usr/convex/getsysinfo = unknown | ||||
| hostinfo               = Mach kernel version: | ||||
| 	 Darwin Kernel Version 12.5.0: Sun Sep 29 13:33:47 PDT 2013; root:xnu-2050.48.12~1/RELEASE_X86_64 | ||||
| Kernel configured for up to 4 processors. | ||||
| 2 processors are physically available. | ||||
| 4 processors are logically available. | ||||
| Processor type: i486 (Intel 80486) | ||||
| Processors active: 0 1 2 3 | ||||
| Primary memory available: 8.00 gigabytes | ||||
| Default processor set: 167 tasks, 1145 threads, 4 processors | ||||
| Load average: 1.33, Mach factor: 2.66 | ||||
| /bin/machine           = unknown | ||||
| /usr/bin/oslevel       = unknown | ||||
| /bin/universe          = unknown | ||||
| 
 | ||||
| PATH: /Users/thduynguyen/Library/Enthought/Canopy_64bit/User/bin | ||||
| PATH: /Library/Frameworks/Python.framework/Versions/2.7/bin | ||||
| PATH: /opt/local/bin | ||||
| PATH: /opt/local/sbin | ||||
| PATH: /usr/bin | ||||
| PATH: /bin | ||||
| PATH: /usr/sbin | ||||
| PATH: /sbin | ||||
| PATH: /usr/local/bin | ||||
| PATH: /opt/X11/bin | ||||
| 
 | ||||
| 
 | ||||
| ## ----------- ## | ||||
| ## Core tests. ## | ||||
| ## ----------- ## | ||||
| 
 | ||||
| configure:1279: error: cannot find install-sh or install.sh in . ./.. ./../.. | ||||
| 
 | ||||
| ## ---------------- ## | ||||
| ## Cache variables. ## | ||||
| ## ---------------- ## | ||||
| 
 | ||||
| ac_cv_env_CC_set= | ||||
| ac_cv_env_CC_value= | ||||
| ac_cv_env_CFLAGS_set= | ||||
| ac_cv_env_CFLAGS_value= | ||||
| ac_cv_env_CPPFLAGS_set= | ||||
| ac_cv_env_CPPFLAGS_value= | ||||
| ac_cv_env_LDFLAGS_set= | ||||
| ac_cv_env_LDFLAGS_value= | ||||
| ac_cv_env_build_alias_set= | ||||
| ac_cv_env_build_alias_value= | ||||
| ac_cv_env_host_alias_set= | ||||
| ac_cv_env_host_alias_value= | ||||
| ac_cv_env_target_alias_set= | ||||
| ac_cv_env_target_alias_value= | ||||
| 
 | ||||
| ## ----------------- ## | ||||
| ## Output variables. ## | ||||
| ## ----------------- ## | ||||
| 
 | ||||
| CC='' | ||||
| CCSHARED='' | ||||
| CFLAGS='' | ||||
| CPPFLAGS='' | ||||
| DEF='' | ||||
| DEFS='' | ||||
| ECHO_C='ECHO_N='' | ||||
| ECHO_T='' | ||||
| EXEEXT='' | ||||
| INSTALL_DATA='' | ||||
| INSTALL_PROGRAM='' | ||||
| INSTALL_SCRIPT='' | ||||
| LDFLAGS='' | ||||
| LIBOBJS='' | ||||
| LIBS='' | ||||
| LTLIBOBJS='' | ||||
| OBJEXT='' | ||||
| PACKAGE_BUGREPORT='' | ||||
| PACKAGE_NAME='lpsolve' | ||||
| PACKAGE_STRING='lpsolve 5.5.0.11' | ||||
| PACKAGE_TARNAME='lpsolve' | ||||
| PACKAGE_VERSION='5.5.0.11' | ||||
| PATH_SEPARATOR=':' | ||||
| SHARED_LIB='' | ||||
| SHELL='/bin/sh' | ||||
| SO='' | ||||
| ac_ct_CC='' | ||||
| bindir='${exec_prefix}/bin' | ||||
| build='' | ||||
| build_alias='' | ||||
| build_cpu='' | ||||
| build_os='' | ||||
| build_vendor='' | ||||
| datadir='${prefix}/share' | ||||
| exec_prefix='NONE' | ||||
| host='' | ||||
| host_alias='' | ||||
| host_cpu='' | ||||
| host_os='' | ||||
| host_vendor='' | ||||
| includedir='${prefix}/include' | ||||
| infodir='${prefix}/info' | ||||
| libdir='${exec_prefix}/lib' | ||||
| libexecdir='${exec_prefix}/libexec' | ||||
| localstatedir='${prefix}/var' | ||||
| mandir='${prefix}/man' | ||||
| oldincludedir='/usr/include' | ||||
| prefix='/Users/thduynguyen/install' | ||||
| program_transform_name='s,x,x,' | ||||
| sbindir='${exec_prefix}/sbin' | ||||
| sharedstatedir='${prefix}/com' | ||||
| sysconfdir='${prefix}/etc' | ||||
| target_alias='' | ||||
| 
 | ||||
| ## ----------- ## | ||||
| ## confdefs.h. ## | ||||
| ## ----------- ## | ||||
| 
 | ||||
| #define PACKAGE_BUGREPORT "" | ||||
| #define PACKAGE_NAME "lpsolve" | ||||
| #define PACKAGE_STRING "lpsolve 5.5.0.11" | ||||
| #define PACKAGE_TARNAME "lpsolve" | ||||
| #define PACKAGE_VERSION "5.5.0.11" | ||||
| 
 | ||||
| configure: exit 1 | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -1,57 +0,0 @@ | |||
| AC_PREREQ(2.52) | ||||
| AC_INIT([lpsolve],5.5.0.11,[], []) | ||||
| AC_CONFIG_SRCDIR(lp_simplex.c) | ||||
| AC_CANONICAL_HOST | ||||
| 
 | ||||
| SHARED_LIB=liblpsolve55.so | ||||
| SO=.so | ||||
| case $host_os in | ||||
|   hp*|HP*) | ||||
|     DEF=-ldld | ||||
|     case `uname -m` in | ||||
|       ia64) SO=.so;; | ||||
|       *)    SO=.sl;; | ||||
|     esac | ||||
|     if test "$GCC" = yes; | ||||
|       then CCSHARED="-fPIC"; | ||||
|       else CCSHARED="+z"; | ||||
|     fi;; | ||||
|   CYGWIN*) | ||||
|     SO=.dll;; | ||||
|   linux) | ||||
|     CCSHARED="-fPIC";; | ||||
|   apple-darwin) | ||||
|     DEF=-ldl -idirafter /usr/include/sys -DINTEGERTIME -Wno-long-double | ||||
|     ;; | ||||
|   OpenUNIX*|UnixWare*) | ||||
|     DEF='-dy -DNOLONGLONG' | ||||
|     if test "$GCC" = "yes" | ||||
|       then CCSHARED="-fPIC" | ||||
|       else CCSHARED="-K PIC" | ||||
|     fi;; | ||||
|   SCO_SV*) | ||||
|     DEF='-dy -DNOLONGLONG' | ||||
|     if test "$GCC" = "yes" | ||||
|       then CCSHARED="-fPIC" | ||||
|       else CCSHARED="-Kpic -belf" | ||||
|     fi;; | ||||
|  *) | ||||
| esac | ||||
| 
 | ||||
| AC_SUBST(SO) | ||||
| AC_SUBST(CCSHARED) | ||||
| AC_SUBST(DEF) | ||||
| AC_SUBST(SHARED_LIB) | ||||
| 
 | ||||
| AC_PROG_CC | ||||
| if test "x$GCC" != "xyes" | ||||
| then | ||||
|   echo "*** non GNU CC compiler detected." | ||||
|   echo "*** This package has not been tested very well with non GNU compilers" | ||||
| fi | ||||
| 
 | ||||
| AC_PROG_INSTALL | ||||
| AC_CONFIG_FILES([ \ | ||||
| 	Makefile \ | ||||
| ]) | ||||
| AC_OUTPUT | ||||
|  | @ -1,22 +0,0 @@ | |||
| #ifndef __DECLARE_H__ | ||||
| #define __DECLARE_H__ | ||||
| 
 | ||||
| #if !defined ANSI_PROTOTYPES | ||||
| # if defined MSDOS || defined __BORLANDC__ || defined __HIGHC__ || defined SCO_UNIX || defined AViiON | ||||
| #  define ANSI_PROTOTYPES 1 | ||||
| # endif | ||||
| #endif | ||||
| 
 | ||||
| #if ANSI_PROTOTYPES!=0 | ||||
| # define __OF(args)  args | ||||
| #else | ||||
| # define __OF(args)  () | ||||
| #endif | ||||
| 
 | ||||
| #if defined __HIGHC__ | ||||
| # define VARARG    ... | ||||
| #else | ||||
| # define VARARG | ||||
| #endif | ||||
| 
 | ||||
| #endif | ||||
|  | @ -1,10 +0,0 @@ | |||
| @echo off | ||||
| 
 | ||||
| REM This batch file compiles the demo program with the Borland C++ 5.5 compiler for Windows | ||||
| 
 | ||||
| set src=../shared/commonlib.c ../shared/mmio.c ../shared/myblas.c ../ini.c ../lp_rlp.c ../lp_crash.c ../bfp/bfp_LUSOL/lp_LUSOL.c ../bfp/bfp_LUSOL/LUSOL/lusol.c ../lp_Hash.c ../lp_lib.c ../lp_wlp.c ../lp_matrix.c ../lp_mipbb.c ../lp_MPS.c ../lp_params.c ../lp_presolve.c ../lp_price.c ../lp_pricePSE.c ../lp_report.c ../lp_scale.c ../lp_simplex.c ../lp_SOS.c ../lp_utils.c ../yacc_read.c ../lp_MDO.c ../colamd/colamd.c | ||||
| set c=bcc32 -w-8004 -w-8057 | ||||
| 
 | ||||
| %c% -I.. -I../bfp -I../bfp/bfp_LUSOL -I../bfp/bfp_LUSOL/LUSOL -I../colamd -I../shared /O0 -a8 -DWIN32 -DYY_NEVER_INTERACTIVE=1 -DPARSER_LP -DINVERSE_ACTIVE=INVERSE_LUSOL -DRoleIsExternalInvEngine demo.c -edemo.exe %src% | ||||
| 
 | ||||
| if exist *.obj del *.obj | ||||
|  | @ -1,15 +0,0 @@ | |||
| src='../lp_MDO.c ../shared/commonlib.c ../colamd/colamd.c ../shared/mmio.c ../shared/myblas.c ../ini.c ../lp_rlp.c ../lp_crash.c ../bfp/bfp_LUSOL/lp_LUSOL.c ../bfp/bfp_LUSOL/LUSOL/lusol.c ../lp_Hash.c ../lp_lib.c ../lp_wlp.c ../lp_matrix.c ../lp_mipbb.c ../lp_MPS.c ../lp_params.c ../lp_presolve.c ../lp_price.c ../lp_pricePSE.c ../lp_report.c ../lp_scale.c ../lp_simplex.c ../lp_SOS.c ../lp_utils.c ../yacc_read.c' | ||||
| c=cc | ||||
| 
 | ||||
| math=-lm | ||||
| 
 | ||||
| def= | ||||
| if [ "$PLATFORM" = "SCO_UNIX" ] | ||||
| then def='-dy -K PIC -DNOLONGLONG' | ||||
|      dl=-lc | ||||
| else dl=-ldl | ||||
| fi | ||||
| 
 | ||||
| opts='-O3' | ||||
| 
 | ||||
| $c -I.. -I../bfp -I../bfp/bfp_LUSOL -I../bfp/bfp_LUSOL/LUSOL -I../colamd -I../shared $opts $def -DYY_NEVER_INTERACTIVE -DPARSER_LP -DINVERSE_ACTIVE=INVERSE_LUSOL -DRoleIsExternalInvEngine demo.c $src -o demo $math $dl | ||||
|  | @ -1,14 +0,0 @@ | |||
| src='../bfp/lp_MDO.c ../commonlib.c ../myblas.c ../colamd/colamd.c ../ini.c ../fortify.c ../lp_rlp.c ../lp_crash.c ../bfp/bfp_etaPFI/lp_etaPFI.c ../lp_Hash.c ../lp_lib.c ../lp_wlp.c ../lp_matrix.c ../lp_mipbb.c ../lp_MPS.c ../lp_params.c ../lp_presolve.c ../lp_price.c ../lp_pricePSE.c ../lp_report.c ../lp_scale.c ../lp_simplex.c demo.c ../lp_SOS.c ../lp_utils.c ../yacc_read.c' | ||||
| c=cc | ||||
| 
 | ||||
| math=-lm | ||||
| 
 | ||||
| def= | ||||
| if [ "$PLATFORM" = "SCO_UNIX" ] | ||||
| then def='-DLoadInverseLib=0 -DLoadLanguageLib=0 -D__HYPER=long' | ||||
| else dl=-ldl | ||||
| fi | ||||
| 
 | ||||
| opts='-idirafter /usr/include/sys -O3 -DINTEGERTIME -Wno-long-double' | ||||
| 
 | ||||
| $c -I.. -I../bfp -I../bfp/bfp_etaPFI -I../colamd $opts $def -DYY_NEVER_INTERACTIVE -DPARSER_LP $src -o demo $math $dl | ||||
|  | @ -1,15 +0,0 @@ | |||
| @echo off | ||||
| 
 | ||||
| REM This batch file compiles the demo program with the gnu gcc compiler under DOS/Windows | ||||
| 
 | ||||
| REM There are two ways to do that: use the lpsolve code directly or use that static library. | ||||
| 
 | ||||
| rem link lpsolve code with application | ||||
| set src=../lp_MDO.c ../shared/commonlib.c ../colamd/colamd.c ../shared/mmio.c ../shared/myblas.c ../ini.c ../lp_rlp.c ../lp_crash.c ../bfp/bfp_LUSOL/lp_LUSOL.c ../bfp/bfp_LUSOL/LUSOL/lusol.c ../lp_Hash.c ../lp_lib.c ../lp_wlp.c ../lp_matrix.c ../lp_mipbb.c ../lp_MPS.c ../lp_params.c ../lp_presolve.c ../lp_price.c ../lp_pricePSE.c ../lp_report.c ../lp_scale.c ../lp_simplex.c ../lp_SOS.c ../lp_utils.c ../yacc_read.c | ||||
| 
 | ||||
| rem statically link lpsolve library | ||||
| rem set src=../lpsolve55/liblpsolve55.a | ||||
| 
 | ||||
| set c=gcc | ||||
| 
 | ||||
| %c%  -DINLINE=static -I.. -I../bfp -I../bfp/bfp_LUSOL -I../bfp/bfp_LUSOL/LUSOL -I../colamd -I../shared -O3 -DBFP_CALLMODEL=__stdcall -DYY_NEVER_INTERACTIVE -DPARSER_LP -DINVERSE_ACTIVE=INVERSE_LUSOL -DRoleIsExternalInvEngine demo.c %src% -o demo.exe | ||||
|  | @ -1,10 +0,0 @@ | |||
| @echo off | ||||
| 
 | ||||
| REM This batch file compiles the demo program with the Microsoft Visual C/C++ compiler under Windows | ||||
| 
 | ||||
| set src=../shared/commonlib.c ../shared/mmio.c ../shared/myblas.c ../ini.c ../lp_rlp.c ../lp_crash.c ../bfp/bfp_LUSOL/lp_LUSOL.c ../bfp/bfp_LUSOL/LUSOL/lusol.c ../lp_Hash.c ../lp_lib.c ../lp_wlp.c ../lp_matrix.c ../lp_mipbb.c ../lp_MPS.c ../lp_params.c ../lp_presolve.c ../lp_price.c ../lp_pricePSE.c ../lp_report.c ../lp_scale.c ../lp_simplex.c ../lp_SOS.c ../lp_utils.c ../yacc_read.c ../lp_MDO.c ../colamd/colamd.c | ||||
| set c=cl | ||||
| 
 | ||||
| %c% -I.. -I../bfp -I../bfp/bfp_LUSOL -I../bfp/bfp_LUSOL/LUSOL -I../colamd -I../shared /O1 /Zp8 /Gd -DWIN32 -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -DYY_NEVER_INTERACTIVE -DPARSER_LP -DINVERSE_ACTIVE=INVERSE_LUSOL -DRoleIsExternalInvEngine demo.c %src% -o demo.exe | ||||
| 
 | ||||
| if exist *.obj del *.obj | ||||
|  | @ -1,10 +0,0 @@ | |||
| @echo off | ||||
| 
 | ||||
| REM This batch file compiles the demo program with the Microsoft Visual C/C++ compiler under Windows | ||||
| 
 | ||||
| set src=../shared/commonlib.c ../shared/mmio.c ../shared/myblas.c ../ini.c ../lp_rlp.c ../lp_crash.c ../bfp/bfp_LUSOL/lp_LUSOL.c ../bfp/bfp_LUSOL/LUSOL/lusol.c ../lp_Hash.c ../lp_lib.c ../lp_wlp.c ../lp_matrix.c ../lp_mipbb.c ../lp_MPS.c ../lp_params.c ../lp_presolve.c ../lp_price.c ../lp_pricePSE.c ../lp_report.c ../lp_scale.c ../lp_simplex.c ../lp_SOS.c ../lp_utils.c ../yacc_read.c ../lp_MDO.c ../colamd/colamd.c | ||||
| set c=cl | ||||
| 
 | ||||
| %c% -I.. -I../bfp -I../bfp/bfp_LUSOL -I../bfp/bfp_LUSOL/LUSOL -I../colamd -I../shared /O1 /Zp8 /Gd -DWIN32 -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -DYY_NEVER_INTERACTIVE -DPARSER_LP -DINVERSE_ACTIVE=INVERSE_LUSOL -DRoleIsExternalInvEngine -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE demo.c %src% /Fedemo.exe | ||||
| 
 | ||||
| if exist *.obj del *.obj | ||||
|  | @ -1,265 +0,0 @@ | |||
| /*
 | ||||
|  This program is originally made by by Jeroen J. Dirks (jeroend@tor.numetrix.com) | ||||
|  Adapted by Peter Notebaert (lpsolve@peno.be) | ||||
| */ | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| #include "lp_lib.h" | ||||
| 
 | ||||
| #if defined FORTIFY | ||||
| #include "lp_fortify.h" | ||||
| 
 | ||||
| int EndOfPgr(int i) | ||||
| { | ||||
|     exit(i); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| void press_ret(void) | ||||
| { | ||||
| #if !defined NORETURN | ||||
|   printf("[return]"); | ||||
|   getchar(); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| int main(void) | ||||
| { | ||||
| # if defined ERROR | ||||
| #  undef ERROR | ||||
| # endif | ||||
| # define ERROR() { fprintf(stderr, "Error\n"); exit(1); } | ||||
|   lprec *lp; | ||||
|   int majorversion, minorversion, release, build; | ||||
| 
 | ||||
| #if defined FORTIFY | ||||
|   Fortify_EnterScope(); | ||||
| #endif | ||||
| 
 | ||||
|   lp_solve_version(&majorversion, &minorversion, &release, &build); | ||||
|   printf("lp_solve %d.%d.%d.%d demo\n\n", majorversion, minorversion, release, build); | ||||
|   printf("This demo will show most of the features of lp_solve %d.%d.%d.%d\n", majorversion, minorversion, release, build); | ||||
|   press_ret(); | ||||
|   printf("\nWe start by creating a new problem with 4 variables and 0 constraints\n"); | ||||
|   printf("We use: lp=make_lp(0,4);\n"); | ||||
|   if ((lp=make_lp(0,4)) == NULL) | ||||
|     ERROR(); | ||||
|   press_ret(); | ||||
| 
 | ||||
|   printf("We can show the current problem with print_lp(lp)\n"); | ||||
|   print_lp(lp); | ||||
|   press_ret(); | ||||
|   printf("Now we add some constraints\n"); | ||||
|   printf("str_add_constraint(lp, \"3 2 2 1\" ,LE,4)\n"); | ||||
|   printf("This is the string version of add_constraint. For the normal version\n"); | ||||
|   printf("of add_constraint see the help file\n"); | ||||
|   if (!str_add_constraint(lp, "3 2 2 1", LE, 4)) | ||||
|     ERROR(); | ||||
|   print_lp(lp); | ||||
|   press_ret(); | ||||
|   printf("str_add_constraint(lp, \"0 4 3 1\" ,GE,3)\n"); | ||||
|   if (!str_add_constraint(lp, "0 4 3 1", GE, 3)) | ||||
|     ERROR(); | ||||
|   print_lp(lp); | ||||
|   press_ret(); | ||||
|   printf("Set the objective function\n"); | ||||
|   printf("str_set_obj_fn(lp, \"2 3 -2 3\")\n"); | ||||
|   if (!str_set_obj_fn(lp, "2 3 -2 3")) | ||||
|     ERROR(); | ||||
|   print_lp(lp); | ||||
|   press_ret(); | ||||
|   printf("Now solve the problem with printf(solve(lp));\n"); | ||||
|   printf("%d",solve(lp)); | ||||
|   press_ret(); | ||||
|   printf("The value is 0, this means we found an optimal solution\n"); | ||||
|   printf("We can display this solution with print_objective(lp) and print_solution(lp)\n"); | ||||
|   print_objective(lp); | ||||
|   print_solution(lp, 1); | ||||
|   print_constraints(lp, 1); | ||||
| 
 | ||||
|   press_ret(); | ||||
|   printf("The dual variables of the solution are printed with\n"); | ||||
|   printf("print_duals(lp);\n"); | ||||
|   print_duals(lp); | ||||
|   press_ret(); | ||||
|   printf("We can change a single element in the matrix with\n"); | ||||
|   printf("set_mat(lp,2,1,0.5)\n"); | ||||
|   if (!set_mat(lp,2,1,0.5)) | ||||
|     ERROR(); | ||||
|   print_lp(lp); | ||||
|   press_ret(); | ||||
|   printf("If we want to maximize the objective function use set_maxim(lp);\n"); | ||||
|   set_maxim(lp); | ||||
|   print_lp(lp); | ||||
|   press_ret(); | ||||
|   printf("after solving this gives us:\n"); | ||||
|   solve(lp); | ||||
|   print_objective(lp); | ||||
|   print_solution(lp, 1); | ||||
|   print_constraints(lp, 1); | ||||
|   print_duals(lp); | ||||
|   press_ret(); | ||||
|   printf("Change the value of a rhs element with set_rh(lp,1,7.45)\n"); | ||||
|   set_rh(lp,1,7.45); | ||||
|   print_lp(lp); | ||||
|   solve(lp); | ||||
|   print_objective(lp); | ||||
|   print_solution(lp, 1); | ||||
|   print_constraints(lp, 1); | ||||
|   press_ret(); | ||||
|   printf("We change %s to the integer type with\n", get_col_name(lp, 4)); | ||||
|   printf("set_int(lp, 4, TRUE)\n"); | ||||
|   set_int(lp, 4, TRUE); | ||||
|   print_lp(lp); | ||||
|   printf("We set branch & bound debugging on with set_debug(lp, TRUE)\n"); | ||||
|   set_debug(lp, TRUE); | ||||
|   printf("and solve...\n"); | ||||
|   press_ret(); | ||||
|   solve(lp); | ||||
|   print_objective(lp); | ||||
|   print_solution(lp, 1); | ||||
|   print_constraints(lp, 1); | ||||
|   press_ret(); | ||||
|   printf("We can set bounds on the variables with\n"); | ||||
|   printf("set_lowbo(lp,2,2); & set_upbo(lp,4,5.3)\n"); | ||||
|   set_lowbo(lp,2,2); | ||||
|   set_upbo(lp,4,5.3); | ||||
|   print_lp(lp); | ||||
|   press_ret(); | ||||
|   solve(lp); | ||||
|   print_objective(lp); | ||||
|   print_solution(lp, 1); | ||||
|   print_constraints(lp, 1); | ||||
|   press_ret(); | ||||
|   printf("Now remove a constraint with del_constraint(lp, 1)\n"); | ||||
|   del_constraint(lp,1); | ||||
|   print_lp(lp); | ||||
|   printf("Add an equality constraint\n"); | ||||
|   if (!str_add_constraint(lp, "1 2 1 4", EQ, 8)) | ||||
|     ERROR(); | ||||
|   print_lp(lp); | ||||
|   press_ret(); | ||||
|   printf("A column can be added with:\n"); | ||||
|   printf("str_add_column(lp,\"3 2 2\");\n"); | ||||
|   if (!str_add_column(lp,"3 2 2")) | ||||
|     ERROR(); | ||||
|   print_lp(lp); | ||||
|   press_ret(); | ||||
|   printf("A column can be removed with:\n"); | ||||
|   printf("del_column(lp,3);\n"); | ||||
|   del_column(lp,3); | ||||
|   print_lp(lp); | ||||
|   press_ret(); | ||||
|   printf("We can use automatic scaling with:\n"); | ||||
|   printf("set_scaling(lp, SCALE_MEAN);\n"); | ||||
|   set_scaling(lp, SCALE_MEAN); | ||||
|   print_lp(lp); | ||||
|   press_ret(); | ||||
|   printf("The function get_mat(lprec *lp, int row, int column) returns a single\n"); | ||||
|   printf("matrix element\n"); | ||||
|   printf("%s get_mat(lp,2,3), get_mat(lp,1,1); gives\n","printf(\"%f %f\\n\","); | ||||
|   printf("%f %f\n", (double)get_mat(lp,2,3), (double)get_mat(lp,1,1)); | ||||
|   printf("Notice that get_mat returns the value of the original unscaled problem\n"); | ||||
|   press_ret(); | ||||
|   printf("If there are any integer type variables, then only the rows are scaled\n"); | ||||
|   printf("set_int(lp,3,FALSE);\n"); | ||||
|   printf("set_scaling(lp, SCALE_MEAN);\n"); | ||||
|   set_scaling(lp, SCALE_MEAN); | ||||
|   set_int(lp,3,FALSE); | ||||
|   print_lp(lp); | ||||
|   press_ret(); | ||||
|   solve(lp); | ||||
|   printf("print_objective, print_solution gives the solution to the original problem\n"); | ||||
|   print_objective(lp); | ||||
|   print_solution(lp, 1); | ||||
|   print_constraints(lp, 1); | ||||
|   press_ret(); | ||||
|   printf("Scaling is turned off with unscale(lp);\n"); | ||||
|   unscale(lp); | ||||
|   print_lp(lp); | ||||
|   press_ret(); | ||||
|   printf("Now turn B&B debugging off and simplex tracing on with\n"); | ||||
|   printf("set_debug(lp, FALSE), set_trace(lp, TRUE) and solve(lp)\n"); | ||||
|   set_debug(lp, FALSE); | ||||
|   set_trace(lp, TRUE); | ||||
|   press_ret(); | ||||
|   solve(lp); | ||||
|   printf("Where possible, lp_solve will start at the last found basis\n"); | ||||
|   printf("We can reset the problem to the initial basis with\n"); | ||||
|   printf("default_basis(lp). Now solve it again...\n"); | ||||
|   press_ret(); | ||||
|   default_basis(lp); | ||||
|   solve(lp); | ||||
| 
 | ||||
|   printf("It is possible to give variables and constraints names\n"); | ||||
|   printf("set_row_name(lp,1,\"speed\"); & set_col_name(lp,2,\"money\")\n"); | ||||
|   if (!set_row_name(lp,1,"speed")) | ||||
|     ERROR(); | ||||
|   if (!set_col_name(lp,2,"money")) | ||||
|     ERROR(); | ||||
|   print_lp(lp); | ||||
|   printf("As you can see, all column and rows are assigned default names\n"); | ||||
|   printf("If a column or constraint is deleted, the names shift place also:\n"); | ||||
|   press_ret(); | ||||
|   printf("del_column(lp,1);\n"); | ||||
|   del_column(lp,1); | ||||
|   print_lp(lp); | ||||
|   press_ret(); | ||||
| 
 | ||||
|   delete_lp(lp); | ||||
| 
 | ||||
| #if FALSE | ||||
|   printf("A lp structure can be created and read from a .lp file\n"); | ||||
|   printf("lp = read_lp(\"lp_examples/demo_lag.lp\", TRUE);\n"); | ||||
|   printf("The verbose option is used\n"); | ||||
|   if ((lp = read_LP("lp_examples/demo_lag.lp", TRUE, "test")) == NULL) | ||||
|     ERROR(); | ||||
|   press_ret(); | ||||
|   printf("lp is now:\n"); | ||||
|   print_lp(lp); | ||||
| 
 | ||||
|   press_ret(); | ||||
|   printf("solution:\n"); | ||||
|   set_debug(lp, TRUE); | ||||
|   solve(lp); | ||||
|   set_debug(lp, FALSE); | ||||
|   print_objective(lp); | ||||
|   print_solution(lp, 1); | ||||
|   print_constraints(lp, 1); | ||||
|   press_ret(); | ||||
|   printf("You can see that branch & bound was used in this problem\n"); | ||||
| 
 | ||||
|   printf("Now remove the last constraint and use lagrangian relaxation\n"); | ||||
|   printf("del_constraint(lp,6);\n"); | ||||
|   printf("str_add_lag_con(lp, \"1 1 1 0 0 0\", LE, 2);\n"); | ||||
|   del_constraint(lp,6); | ||||
|   if (!str_add_lag_con(lp, "1 1 1 0 0 0", LE, 2)) | ||||
|     ERROR(); | ||||
|   print_lp(lp); | ||||
| 
 | ||||
|   printf("Lagrangian relaxation is used in some heuristics. It is now possible\n"); | ||||
|   printf("to get a feasible integer solution without usage of branch & bound.\n"); | ||||
|   printf("Use lag_solve(lp, 0, 30); 0 is the initial bound, 30 the maximum\n"); | ||||
|   printf("number of iterations, the last variable turns the verbose mode on.\n"); | ||||
|   press_ret(); | ||||
|   set_lag_trace(lp, TRUE); | ||||
|   printf("%d\n",lag_solve(lp, 0, 30)); | ||||
|   printf("The returncode of lag_solve is 6 or FEAS_FOUND. this means that a feasible\n"); | ||||
|   printf("solution has been found. For a list of other possible return values\n"); | ||||
|   printf("see the help file. Print this solution with print_objective, print_solution\n"); | ||||
|   print_objective(lp); | ||||
|   print_solution(lp, 1); | ||||
|   print_constraints(lp, 1); | ||||
| 
 | ||||
|   delete_lp(lp); | ||||
| 
 | ||||
|   press_ret(); | ||||
| #endif | ||||
| 
 | ||||
| #if defined FORTIFY | ||||
|   Fortify_LeaveScope(); | ||||
| #endif | ||||
| 
 | ||||
|   return(0); | ||||
| } | ||||
|  | @ -1,19 +0,0 @@ | |||
| Microsoft Visual Studio Solution File, Format Version 9.00 | ||||
| # Visual Studio 2005 | ||||
| Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo", "demo.vcproj", "{CED6B89F-02F2-4DB1-8610-4F12A6D02F54}" | ||||
| EndProject | ||||
| Global | ||||
| 	GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||
| 		Debug|Win32 = Debug|Win32 | ||||
| 		Release|Win32 = Release|Win32 | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||||
| 		{CED6B89F-02F2-4DB1-8610-4F12A6D02F54}.Debug|Win32.ActiveCfg = Debug|Win32 | ||||
| 		{CED6B89F-02F2-4DB1-8610-4F12A6D02F54}.Debug|Win32.Build.0 = Debug|Win32 | ||||
| 		{CED6B89F-02F2-4DB1-8610-4F12A6D02F54}.Release|Win32.ActiveCfg = Release|Win32 | ||||
| 		{CED6B89F-02F2-4DB1-8610-4F12A6D02F54}.Release|Win32.Build.0 = Release|Win32 | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(SolutionProperties) = preSolution | ||||
| 		HideSolutionNode = FALSE | ||||
| 	EndGlobalSection | ||||
| EndGlobal | ||||
|  | @ -1,311 +0,0 @@ | |||
| <?xml version="1.0" encoding="Windows-1252"?> | ||||
| <VisualStudioProject | ||||
| 	ProjectType="Visual C++" | ||||
| 	Version="8.00" | ||||
| 	Name="demo" | ||||
| 	ProjectGUID="{CED6B89F-02F2-4DB1-8610-4F12A6D02F54}" | ||||
| 	> | ||||
| 	<Platforms> | ||||
| 		<Platform | ||||
| 			Name="Win32" | ||||
| 		/> | ||||
| 	</Platforms> | ||||
| 	<ToolFiles> | ||||
| 	</ToolFiles> | ||||
| 	<Configurations> | ||||
| 		<Configuration | ||||
| 			Name="Release|Win32" | ||||
| 			OutputDirectory=".\Release" | ||||
| 			IntermediateDirectory=".\Release" | ||||
| 			ConfigurationType="1" | ||||
| 			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" | ||||
| 			UseOfMFC="0" | ||||
| 			ATLMinimizesCRunTimeLibraryUsage="false" | ||||
| 			CharacterSet="2" | ||||
| 			> | ||||
| 			<Tool | ||||
| 				Name="VCPreBuildEventTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCCustomBuildTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCXMLDataGeneratorTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCWebServiceProxyGeneratorTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCMIDLTool" | ||||
| 				TypeLibraryName=".\Release/demo.tlb" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCCLCompilerTool" | ||||
| 				InlineFunctionExpansion="1" | ||||
| 				AdditionalIncludeDirectories="..;..\bfp;..\bfp\bfp_etaPFI;..\colamd;..\shared" | ||||
| 				PreprocessorDefinitions="NDEBUG,WIN32,_CONSOLE,MSDOS,CHECK_SOLUTION,PARSER_LP,_CRT_SECURE_NO_DEPRECATE,_CRT_NONSTDC_NO_DEPRECATE,_SCL_SECURE_NO_DEPRECATE" | ||||
| 				StringPooling="true" | ||||
| 				RuntimeLibrary="0" | ||||
| 				StructMemberAlignment="4" | ||||
| 				EnableFunctionLevelLinking="true" | ||||
| 				UsePrecompiledHeader="0" | ||||
| 				PrecompiledHeaderFile=".\Release/demo.pch" | ||||
| 				AssemblerListingLocation=".\Release/" | ||||
| 				ObjectFile=".\Release/" | ||||
| 				ProgramDataBaseFileName=".\Release/" | ||||
| 				WarningLevel="3" | ||||
| 				SuppressStartupBanner="true" | ||||
| 				CompileAs="1" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCManagedResourceCompilerTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCResourceCompilerTool" | ||||
| 				PreprocessorDefinitions="NDEBUG" | ||||
| 				Culture="2067" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCPreLinkEventTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCLinkerTool" | ||||
| 				AdditionalOptions="/MACHINE:I386" | ||||
| 				AdditionalDependencies="odbc32.lib odbccp32.lib" | ||||
| 				OutputFile=".\Release/demo.exe" | ||||
| 				LinkIncremental="1" | ||||
| 				SuppressStartupBanner="true" | ||||
| 				ProgramDatabaseFile=".\Release/demo.pdb" | ||||
| 				SubSystem="1" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCALinkTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCManifestTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCXDCMakeTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCBscMakeTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCFxCopTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCAppVerifierTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCWebDeploymentTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCPostBuildEventTool" | ||||
| 			/> | ||||
| 		</Configuration> | ||||
| 		<Configuration | ||||
| 			Name="Debug|Win32" | ||||
| 			OutputDirectory=".\Debug" | ||||
| 			IntermediateDirectory=".\Debug" | ||||
| 			ConfigurationType="1" | ||||
| 			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" | ||||
| 			UseOfMFC="0" | ||||
| 			ATLMinimizesCRunTimeLibraryUsage="false" | ||||
| 			CharacterSet="2" | ||||
| 			> | ||||
| 			<Tool | ||||
| 				Name="VCPreBuildEventTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCCustomBuildTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCXMLDataGeneratorTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCWebServiceProxyGeneratorTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCMIDLTool" | ||||
| 				TypeLibraryName=".\Debug/demo.tlb" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCCLCompilerTool" | ||||
| 				Optimization="0" | ||||
| 				AdditionalIncludeDirectories="..;..\bfp;..\bfp\bfp_etaPFI;..\colamd;..\shared" | ||||
| 				PreprocessorDefinitions="_DEBUG,WIN32,_CONSOLE,MSDOS,CHECK_SOLUTION,FORTIFY,PARSER_LP,NORETURN,_CRT_SECURE_NO_DEPRECATE,_CRT_NONSTDC_NO_DEPRECATE,_SCL_SECURE_NO_DEPRECATE" | ||||
| 				RuntimeLibrary="1" | ||||
| 				StructMemberAlignment="4" | ||||
| 				UsePrecompiledHeader="0" | ||||
| 				PrecompiledHeaderFile=".\Debug/demo.pch" | ||||
| 				AssemblerListingLocation=".\Debug/" | ||||
| 				ObjectFile=".\Debug/" | ||||
| 				ProgramDataBaseFileName=".\Debug/" | ||||
| 				WarningLevel="3" | ||||
| 				SuppressStartupBanner="true" | ||||
| 				DebugInformationFormat="4" | ||||
| 				CompileAs="1" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCManagedResourceCompilerTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCResourceCompilerTool" | ||||
| 				PreprocessorDefinitions="_DEBUG" | ||||
| 				Culture="2067" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCPreLinkEventTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCLinkerTool" | ||||
| 				AdditionalOptions="/MACHINE:I386" | ||||
| 				AdditionalDependencies="odbc32.lib odbccp32.lib" | ||||
| 				OutputFile=".\Debug/demo.exe" | ||||
| 				LinkIncremental="2" | ||||
| 				SuppressStartupBanner="true" | ||||
| 				GenerateDebugInformation="true" | ||||
| 				ProgramDatabaseFile=".\Debug/demo.pdb" | ||||
| 				SubSystem="1" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCALinkTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCManifestTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCXDCMakeTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCBscMakeTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCFxCopTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCAppVerifierTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCWebDeploymentTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCPostBuildEventTool" | ||||
| 			/> | ||||
| 		</Configuration> | ||||
| 	</Configurations> | ||||
| 	<References> | ||||
| 	</References> | ||||
| 	<Files> | ||||
| 		<File | ||||
| 			RelativePath="..\colamd\colamd.c" | ||||
| 			> | ||||
| 		</File> | ||||
| 		<File | ||||
| 			RelativePath="..\shared\commonlib.c" | ||||
| 			> | ||||
| 		</File> | ||||
| 		<File | ||||
| 			RelativePath="demo.c" | ||||
| 			> | ||||
| 		</File> | ||||
| 		<File | ||||
| 			RelativePath="..\fortify.c" | ||||
| 			> | ||||
| 		</File> | ||||
| 		<File | ||||
| 			RelativePath="..\ini.c" | ||||
| 			> | ||||
| 		</File> | ||||
| 		<File | ||||
| 			RelativePath="..\lp_crash.c" | ||||
| 			> | ||||
| 		</File> | ||||
| 		<File | ||||
| 			RelativePath="..\bfp\bfp_etaPFI\lp_etaPFI.c" | ||||
| 			> | ||||
| 		</File> | ||||
| 		<File | ||||
| 			RelativePath="..\lp_Hash.c" | ||||
| 			> | ||||
| 		</File> | ||||
| 		<File | ||||
| 			RelativePath="..\lp_lib.c" | ||||
| 			> | ||||
| 		</File> | ||||
| 		<File | ||||
| 			RelativePath="..\lp_matrix.c" | ||||
| 			> | ||||
| 		</File> | ||||
| 		<File | ||||
| 			RelativePath="..\lp_MDO.c" | ||||
| 			> | ||||
| 		</File> | ||||
| 		<File | ||||
| 			RelativePath="..\lp_mipbb.c" | ||||
| 			> | ||||
| 		</File> | ||||
| 		<File | ||||
| 			RelativePath="..\lp_MPS.c" | ||||
| 			> | ||||
| 		</File> | ||||
| 		<File | ||||
| 			RelativePath="..\lp_params.c" | ||||
| 			> | ||||
| 		</File> | ||||
| 		<File | ||||
| 			RelativePath="..\lp_presolve.c" | ||||
| 			> | ||||
| 		</File> | ||||
| 		<File | ||||
| 			RelativePath="..\lp_price.c" | ||||
| 			> | ||||
| 		</File> | ||||
| 		<File | ||||
| 			RelativePath="..\lp_pricePSE.c" | ||||
| 			> | ||||
| 		</File> | ||||
| 		<File | ||||
| 			RelativePath="..\lp_report.c" | ||||
| 			> | ||||
| 		</File> | ||||
| 		<File | ||||
| 			RelativePath="..\lp_rlp.c" | ||||
| 			> | ||||
| 		</File> | ||||
| 		<File | ||||
| 			RelativePath="..\lp_scale.c" | ||||
| 			> | ||||
| 		</File> | ||||
| 		<File | ||||
| 			RelativePath="..\lp_simplex.c" | ||||
| 			> | ||||
| 		</File> | ||||
| 		<File | ||||
| 			RelativePath="..\lp_SOS.c" | ||||
| 			> | ||||
| 		</File> | ||||
| 		<File | ||||
| 			RelativePath="..\lp_utils.c" | ||||
| 			> | ||||
| 		</File> | ||||
| 		<File | ||||
| 			RelativePath="..\lp_wlp.c" | ||||
| 			> | ||||
| 		</File> | ||||
| 		<File | ||||
| 			RelativePath="..\shared\mmio.c" | ||||
| 			> | ||||
| 		</File> | ||||
| 		<File | ||||
| 			RelativePath="..\shared\myblas.c" | ||||
| 			> | ||||
| 		</File> | ||||
| 		<File | ||||
| 			RelativePath="..\yacc_read.c" | ||||
| 			> | ||||
| 		</File> | ||||
| 	</Files> | ||||
| 	<Globals> | ||||
| 	</Globals> | ||||
| </VisualStudioProject> | ||||
|  | @ -1,19 +0,0 @@ | |||
| Microsoft Visual Studio Solution File, Format Version 9.00 | ||||
| # Visual Studio 2005 | ||||
| Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo", "demolib.vcproj", "{CED6B89F-02F2-4DB1-8610-4F12A6D02F54}" | ||||
| EndProject | ||||
| Global | ||||
| 	GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||
| 		Debug|Win32 = Debug|Win32 | ||||
| 		Release|Win32 = Release|Win32 | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||||
| 		{CED6B89F-02F2-4DB1-8610-4F12A6D02F54}.Debug|Win32.ActiveCfg = Debug|Win32 | ||||
| 		{CED6B89F-02F2-4DB1-8610-4F12A6D02F54}.Debug|Win32.Build.0 = Debug|Win32 | ||||
| 		{CED6B89F-02F2-4DB1-8610-4F12A6D02F54}.Release|Win32.ActiveCfg = Release|Win32 | ||||
| 		{CED6B89F-02F2-4DB1-8610-4F12A6D02F54}.Release|Win32.Build.0 = Release|Win32 | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(SolutionProperties) = preSolution | ||||
| 		HideSolutionNode = FALSE | ||||
| 	EndGlobalSection | ||||
| EndGlobal | ||||
|  | @ -1,214 +0,0 @@ | |||
| <?xml version="1.0" encoding="Windows-1252"?> | ||||
| <VisualStudioProject | ||||
| 	ProjectType="Visual C++" | ||||
| 	Version="8.00" | ||||
| 	Name="demo" | ||||
| 	ProjectGUID="{CED6B89F-02F2-4DB1-8610-4F12A6D02F54}" | ||||
| 	RootNamespace="demo" | ||||
| 	> | ||||
| 	<Platforms> | ||||
| 		<Platform | ||||
| 			Name="Win32" | ||||
| 		/> | ||||
| 	</Platforms> | ||||
| 	<ToolFiles> | ||||
| 	</ToolFiles> | ||||
| 	<Configurations> | ||||
| 		<Configuration | ||||
| 			Name="Release|Win32" | ||||
| 			OutputDirectory=".\Release" | ||||
| 			IntermediateDirectory=".\Release" | ||||
| 			ConfigurationType="1" | ||||
| 			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" | ||||
| 			UseOfMFC="0" | ||||
| 			ATLMinimizesCRunTimeLibraryUsage="false" | ||||
| 			CharacterSet="2" | ||||
| 			> | ||||
| 			<Tool | ||||
| 				Name="VCPreBuildEventTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCCustomBuildTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCXMLDataGeneratorTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCWebServiceProxyGeneratorTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCMIDLTool" | ||||
| 				TypeLibraryName=".\Release/demo.tlb" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCCLCompilerTool" | ||||
| 				InlineFunctionExpansion="1" | ||||
| 				AdditionalIncludeDirectories="..;..\colamd" | ||||
| 				PreprocessorDefinitions="NDEBUG,WIN32,_CONSOLE,MSDOS,CHECK_SOLUTION,PARSER_LP,_CRT_SECURE_NO_DEPRECATE,_CRT_NONSTDC_NO_DEPRECATE,_SCL_SECURE_NO_DEPRECATE" | ||||
| 				StringPooling="true" | ||||
| 				RuntimeLibrary="0" | ||||
| 				StructMemberAlignment="4" | ||||
| 				EnableFunctionLevelLinking="true" | ||||
| 				UsePrecompiledHeader="0" | ||||
| 				PrecompiledHeaderFile=".\Release/demo.pch" | ||||
| 				AssemblerListingLocation=".\Release/" | ||||
| 				ObjectFile=".\Release/" | ||||
| 				ProgramDataBaseFileName=".\Release/" | ||||
| 				WarningLevel="3" | ||||
| 				SuppressStartupBanner="true" | ||||
| 				CompileAs="1" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCManagedResourceCompilerTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCResourceCompilerTool" | ||||
| 				PreprocessorDefinitions="NDEBUG" | ||||
| 				Culture="2067" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCPreLinkEventTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCLinkerTool" | ||||
| 				AdditionalOptions="/MACHINE:I386" | ||||
| 				AdditionalDependencies="odbc32.lib odbccp32.lib liblpsolve55.lib" | ||||
| 				OutputFile=".\Release/demo.exe" | ||||
| 				LinkIncremental="1" | ||||
| 				SuppressStartupBanner="true" | ||||
| 				AdditionalLibraryDirectories="..\lpsolve55" | ||||
| 				ProgramDatabaseFile=".\Release/demo.pdb" | ||||
| 				SubSystem="1" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCALinkTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCManifestTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCXDCMakeTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCBscMakeTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCFxCopTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCAppVerifierTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCWebDeploymentTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCPostBuildEventTool" | ||||
| 			/> | ||||
| 		</Configuration> | ||||
| 		<Configuration | ||||
| 			Name="Debug|Win32" | ||||
| 			OutputDirectory=".\Debug" | ||||
| 			IntermediateDirectory=".\Debug" | ||||
| 			ConfigurationType="1" | ||||
| 			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" | ||||
| 			UseOfMFC="0" | ||||
| 			ATLMinimizesCRunTimeLibraryUsage="false" | ||||
| 			CharacterSet="2" | ||||
| 			> | ||||
| 			<Tool | ||||
| 				Name="VCPreBuildEventTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCCustomBuildTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCXMLDataGeneratorTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCWebServiceProxyGeneratorTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCMIDLTool" | ||||
| 				TypeLibraryName=".\Debug/demo.tlb" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCCLCompilerTool" | ||||
| 				Optimization="0" | ||||
| 				AdditionalIncludeDirectories=".." | ||||
| 				PreprocessorDefinitions="_DEBUG,WIN32,_CONSOLE,NOFORTIFY" | ||||
| 				RuntimeLibrary="1" | ||||
| 				StructMemberAlignment="4" | ||||
| 				UsePrecompiledHeader="0" | ||||
| 				PrecompiledHeaderFile=".\Debug/demo.pch" | ||||
| 				AssemblerListingLocation=".\Debug/" | ||||
| 				ObjectFile=".\Debug/" | ||||
| 				ProgramDataBaseFileName=".\Debug/" | ||||
| 				WarningLevel="3" | ||||
| 				SuppressStartupBanner="true" | ||||
| 				DebugInformationFormat="4" | ||||
| 				CompileAs="1" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCManagedResourceCompilerTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCResourceCompilerTool" | ||||
| 				PreprocessorDefinitions="_DEBUG" | ||||
| 				Culture="2067" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCPreLinkEventTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCLinkerTool" | ||||
| 				AdditionalOptions="/MACHINE:I386" | ||||
| 				AdditionalDependencies="odbc32.lib odbccp32.lib liblpsolve5d.lib" | ||||
| 				OutputFile=".\Debug/demo.exe" | ||||
| 				LinkIncremental="2" | ||||
| 				SuppressStartupBanner="true" | ||||
| 				AdditionalLibraryDirectories="..\lpsolve55" | ||||
| 				GenerateDebugInformation="true" | ||||
| 				ProgramDatabaseFile=".\Debug/demo.pdb" | ||||
| 				SubSystem="1" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCALinkTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCManifestTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCXDCMakeTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCBscMakeTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCFxCopTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCAppVerifierTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCWebDeploymentTool" | ||||
| 			/> | ||||
| 			<Tool | ||||
| 				Name="VCPostBuildEventTool" | ||||
| 			/> | ||||
| 		</Configuration> | ||||
| 	</Configurations> | ||||
| 	<References> | ||||
| 	</References> | ||||
| 	<Files> | ||||
| 		<File | ||||
| 			RelativePath="demo.c" | ||||
| 			> | ||||
| 		</File> | ||||
| 		<File | ||||
| 			RelativePath="..\fortify.c" | ||||
| 			> | ||||
| 		</File> | ||||
| 	</Files> | ||||
| 	<Globals> | ||||
| 	</Globals> | ||||
| </VisualStudioProject> | ||||
|  | @ -1,6 +0,0 @@ | |||
| This directory contains the files to build a demo program | ||||
| 
 | ||||
| To build the program under Windows with the Visual C/C++ compiler, use cvc6.bat (also works for VS.NET) | ||||
| To build the program under DOS/Windows with the gcc compiler, use cgcc.bat | ||||
| To build the program under Linux/Unix, use sh ccc | ||||
| To build the program under Mac OS X 10.3.5, use sh ccc.osx | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -1,293 +0,0 @@ | |||
| #ifndef __FORTIFY_H__ | ||||
| #define __FORTIFY_H__ | ||||
| /*
 | ||||
|  * FILE: | ||||
|  *   fortify.h | ||||
|  * | ||||
|  * DESCRIPTION: | ||||
|  *     Header file for fortify.c - A fortified shell for malloc, realloc, | ||||
|  *   calloc, strdup, getcwd, tempnam & free | ||||
|  * | ||||
|  * WRITTEN: | ||||
|  *   spb 29/4/94 | ||||
|  * | ||||
|  * VERSION: | ||||
|  *   1.0 29/4/94 | ||||
|  */ | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| #include "declare.h" | ||||
| 
 | ||||
| #if defined HP9000 || defined AViiON || defined ALPHA || defined SIGNED_UNKNOWN | ||||
| # define signed | ||||
| #endif | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| #ifdef FORTIFY | ||||
| 
 | ||||
| typedef void (*OutputFuncPtr) __OF((char *)); | ||||
| 
 | ||||
| extern char *_Fortify_file; | ||||
| extern int _Fortify_line; | ||||
| 
 | ||||
| #define Fortify_FILE(file) _Fortify_file=file | ||||
| #define Fortify_LINE(line) _Fortify_line=line | ||||
| 
 | ||||
| #define _Fortify_FILE (_Fortify_file==(char *) 0 ? __FILE__ : _Fortify_file) | ||||
| #define _Fortify_LINE (_Fortify_line==0 ? __LINE__ : _Fortify_line) | ||||
| 
 | ||||
| void  _Fortify_Init __OF((char *file, unsigned long line)); | ||||
| void *_Fortify_malloc __OF((size_t size, char *file, unsigned long line)); | ||||
| void *_Fortify_realloc __OF((void *ptr, size_t new_size, char *file, unsigned long line)); | ||||
| void *_Fortify_calloc __OF((size_t nitems, size_t size, char *file, unsigned long line)); | ||||
| char *_Fortify_strdup __OF((char *str, char *file, unsigned long line)); | ||||
| void *_Fortify_memcpy __OF((void *to, void *from, size_t size, char *file, unsigned long line)); | ||||
| void *_Fortify_memmove __OF((void *to, void *from, size_t size, char *file, unsigned long line)); | ||||
| void *_Fortify_memccpy __OF((void *to, void *from, int c, size_t size, char *file, unsigned long line)); | ||||
| void *_Fortify_memset __OF((void *buffer, int c, size_t size, char *file, unsigned long line)); | ||||
| void *_Fortify_memchr __OF((void *buffer, int c, size_t size, char *file, unsigned long line)); | ||||
| int   _Fortify_memcmp __OF((void *buffer1, void *buffer2, size_t size, char *file, unsigned long line)); | ||||
| int   _Fortify_memicmp __OF((void *buffer1, void *buffer2, size_t size, char *file, unsigned long line)); | ||||
| char *_Fortify_strchr __OF((char *buffer, int c, char *file, unsigned long line)); | ||||
| char *_Fortify_strrchr __OF((char *buffer, int c, char *file, unsigned long line)); | ||||
| char *_Fortify_strlwr __OF((char *buffer, char *file, unsigned long line)); | ||||
| char *_Fortify_strupr __OF((char *buffer, char *file, unsigned long line)); | ||||
| char *_Fortify_strrev __OF((char *buffer, char *file, unsigned long line)); | ||||
| char *_Fortify_strset __OF((char *buffer, int c, char *file, unsigned long line)); | ||||
| char *_Fortify_strnset __OF((char *buffer, int c, size_t size, char *file, unsigned long line)); | ||||
| char *_Fortify_strstr __OF((char *to, char *from, char *file, unsigned long line)); | ||||
| char *_Fortify_strcpy __OF((char *to, char *from, char *file, unsigned long line)); | ||||
| char *_Fortify_strncpy __OF((char *to, char *from, size_t size, char *file, unsigned long line)); | ||||
| int   _Fortify_strcmp __OF((char *buffer1, char *buffer2, char *file, unsigned long line)); | ||||
| double _Fortify_strtod __OF((char *buffer1, char **buffer2, char *file, unsigned long line)); | ||||
| long _Fortify_strtol __OF((char *buffer1, char **buffer2, int n, char *file, unsigned long line)); | ||||
| int _Fortify_atoi __OF((char *buffer1, char *file, unsigned long line)); | ||||
| long _Fortify_atol __OF((char *buffer1, char *file, unsigned long line)); | ||||
| double _Fortify_atof __OF((char *buffer1, char *file, unsigned long line)); | ||||
| unsigned long _Fortify_strtoul __OF((char *buffer1, char **buffer2, int n, char *file, unsigned long line)); | ||||
| size_t _Fortify_strcspn __OF((char *buffer1, char *buffer2, char *file, unsigned long line)); | ||||
| int   _Fortify_strcoll __OF((char *buffer1, char *buffer2, char *file, unsigned long line)); | ||||
| int   _Fortify_strcmpi __OF((char *buffer1, char *buffer2, char *file, unsigned long line)); | ||||
| int   _Fortify_strncmp __OF((char *buffer1, char *buffer2, size_t size, char *file, unsigned long line)); | ||||
| int   _Fortify_strnicmp __OF((char *buffer1, char *buffer2, size_t size, char *file, unsigned long line)); | ||||
| char *_Fortify_strcat __OF((char *buffer1, char *buffer2, char *file, unsigned long line)); | ||||
| char *_Fortify_strpbrk __OF((char *buffer1, char *buffer2, char *file, unsigned long line)); | ||||
| size_t _Fortify_strlen __OF((char *buffer, char *file, unsigned long line)); | ||||
| char *_Fortify_getcwd __OF((char *buf, int size, char *file, unsigned long line)); | ||||
| char *_Fortify_tempnam __OF((char *dir, char *pfx, char *file, unsigned long line)); | ||||
| void  _Fortify_free __OF((void *uptr, char *file, unsigned long line)); | ||||
| 
 | ||||
| int   _Fortify_OutputAllMemory __OF((char *file, unsigned long line)); | ||||
| int   _Fortify_CheckAllMemory __OF((char *file, unsigned long line)); | ||||
| int   _Fortify_CheckPointer __OF((void *uptr, char *file, unsigned long line)); | ||||
| int   _Fortify_Disable __OF((char *file, unsigned long line, int how)); | ||||
| int   _Fortify_SetMallocFailRate __OF((int Percent)); | ||||
| int   _Fortify_EnterScope __OF((char *file, unsigned long line)); | ||||
| int   _Fortify_LeaveScope __OF((char *file, unsigned long line)); | ||||
| int   _Fortify_DumpAllMemory __OF((int scope, char *file, unsigned long line)); | ||||
| 
 | ||||
| typedef void (*Fortify_OutputFuncPtr) __OF((/* const */ char *)); | ||||
| Fortify_OutputFuncPtr _Fortify_SetOutputFunc __OF((Fortify_OutputFuncPtr Output)); | ||||
| 
 | ||||
| #endif /* FORTIFY */ | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #ifndef __FORTIFY_C__ /* Only define the macros if we're NOT in fortify.c */ | ||||
| 
 | ||||
| #ifdef FORTIFY /* Add file and line information to the fortify calls */ | ||||
| 
 | ||||
| #if defined malloc | ||||
| # undef malloc | ||||
| #endif | ||||
| #if defined realloc | ||||
| # undef realloc | ||||
| #endif | ||||
| #if defined calloc | ||||
| # undef calloc | ||||
| #endif | ||||
| #if defined strdup | ||||
| # undef strdup | ||||
| #endif | ||||
| #if defined memcpy | ||||
| # undef memcpy | ||||
| #endif | ||||
| #if defined memmove | ||||
| # undef memmove | ||||
| #endif | ||||
| #if defined memccpy | ||||
| # undef memccpy | ||||
| #endif | ||||
| #if defined memset | ||||
| # undef memset | ||||
| #endif | ||||
| #if defined memchr | ||||
| # undef memchr | ||||
| #endif | ||||
| #if defined memcmp | ||||
| # undef memcmp | ||||
| #endif | ||||
| #if defined memicmp | ||||
| # undef memicmp | ||||
| #endif | ||||
| #if defined strcoll | ||||
| # undef strcoll | ||||
| #endif | ||||
| #if defined strcspn | ||||
| # undef strcspn | ||||
| #endif | ||||
| #if defined strcmp | ||||
| # undef strcmp | ||||
| #endif | ||||
| #if defined strcmpi | ||||
| # undef strcmpi | ||||
| #endif | ||||
| #if defined stricmp | ||||
| # undef stricmp | ||||
| #endif | ||||
| #if defined strncmp | ||||
| # undef strncmp | ||||
| #endif | ||||
| #if defined strnicmp | ||||
| # undef strnicmp | ||||
| #endif | ||||
| #if defined strlwr | ||||
| # undef strlwr | ||||
| #endif | ||||
| #if defined strupr | ||||
| # undef strupr | ||||
| #endif | ||||
| #if defined strrev | ||||
| # undef strrev | ||||
| #endif | ||||
| #if defined strchr | ||||
| # undef strchr | ||||
| #endif | ||||
| #if defined strrchr | ||||
| # undef strrchr | ||||
| #endif | ||||
| #if defined strcat | ||||
| # undef strcat | ||||
| #endif | ||||
| #if defined strpbrk | ||||
| # undef strpbrk | ||||
| #endif | ||||
| #if defined strcpy | ||||
| # undef strcpy | ||||
| #endif | ||||
| #if defined atoi | ||||
| # undef atoi | ||||
| #endif | ||||
| #if defined atol | ||||
| # undef atol | ||||
| #endif | ||||
| #if defined atof | ||||
| # undef atof | ||||
| #endif | ||||
| #if defined strtol | ||||
| # undef strtol | ||||
| #endif | ||||
| #if defined strtoul | ||||
| # undef strtoul | ||||
| #endif | ||||
| #if defined strtod | ||||
| # undef strtod | ||||
| #endif | ||||
| #if defined strstr | ||||
| # undef strstr | ||||
| #endif | ||||
| #if defined strncpy | ||||
| # undef strncpy | ||||
| #endif | ||||
| #if defined strset | ||||
| # undef strset | ||||
| #endif | ||||
| #if defined strnset | ||||
| # undef strnset | ||||
| #endif | ||||
| #if defined strlen | ||||
| # undef strlen | ||||
| #endif | ||||
| #if defined getcwd | ||||
| # undef getcwd | ||||
| #endif | ||||
| #if defined tempnam | ||||
| # undef tempnam | ||||
| #endif | ||||
| #if defined free | ||||
| # undef free | ||||
| #endif | ||||
| 
 | ||||
| #define malloc(size)                  _Fortify_malloc(size, _Fortify_FILE, _Fortify_LINE) | ||||
| #define realloc(ptr,new_size)         _Fortify_realloc(ptr, new_size, _Fortify_FILE, _Fortify_LINE) | ||||
| #define calloc(num,size)              _Fortify_calloc(num, size, _Fortify_FILE, _Fortify_LINE) | ||||
| #define strdup(str)                   _Fortify_strdup(str, _Fortify_FILE, _Fortify_LINE) | ||||
| #define memcpy(to,from,size)          _Fortify_memcpy((void *)(to),(void *)(from),size, _Fortify_FILE, _Fortify_LINE) | ||||
| #define memmove(to,from,size)         _Fortify_memmove((void *)(to),(void *)(from),size, _Fortify_FILE, _Fortify_LINE) | ||||
| #define memccpy(to,from,c,size)       _Fortify_memccpy((void *)(to),(void *)(from),c,size, _Fortify_FILE, _Fortify_LINE) | ||||
| #define memset(buffer,c,size)         _Fortify_memset(buffer,c,size, _Fortify_FILE, _Fortify_LINE) | ||||
| #define memchr(buffer,c,size)         _Fortify_memchr(buffer,c,size, _Fortify_FILE, _Fortify_LINE) | ||||
| #define memcmp(buffer1,buffer2,size)  _Fortify_memcmp((void *)buffer1,(void *)buffer2,size, _Fortify_FILE, _Fortify_LINE) | ||||
| #define memicmp(buffer1,buffer2,size) _Fortify_memicmp((void *)buffer1,(void *)buffer2,size, _Fortify_FILE, _Fortify_LINE) | ||||
| #define strlwr(buffer)                _Fortify_strlwr(buffer, _Fortify_FILE, _Fortify_LINE) | ||||
| #define strupr(buffer)                _Fortify_strupr(buffer, _Fortify_FILE, _Fortify_LINE) | ||||
| #define strrev(buffer)                _Fortify_strrev(buffer, _Fortify_FILE, _Fortify_LINE) | ||||
| #define strchr(buffer,c)              _Fortify_strchr(buffer,c, _Fortify_FILE, _Fortify_LINE) | ||||
| #define strrchr(buffer,c)             _Fortify_strrchr(buffer,c, _Fortify_FILE, _Fortify_LINE) | ||||
| #define strset(buffer,c)              _Fortify_strset(buffer,c, _Fortify_FILE, _Fortify_LINE) | ||||
| #define strnset(buffer,c)             _Fortify_strnset(buffer,c, _Fortify_FILE, _Fortify_LINE) | ||||
| #define strstr(buffer1,buffer2)       _Fortify_strstr(buffer1,buffer2, _Fortify_FILE, _Fortify_LINE) | ||||
| #define atoi(buffer)                  _Fortify_atoi(buffer, _Fortify_FILE, _Fortify_LINE) | ||||
| #define atol(buffer)                  _Fortify_atol(buffer, _Fortify_FILE, _Fortify_LINE) | ||||
| #define atof(buffer)                  _Fortify_atof(buffer, _Fortify_FILE, _Fortify_LINE) | ||||
| #define strtol(buffer1,buffer2,n)     _Fortify_strtol(buffer1,buffer2,n, _Fortify_FILE, _Fortify_LINE) | ||||
| #define strtoul(buffer1,buffer2,n)    _Fortify_strtoul(buffer1,buffer2,n, _Fortify_FILE, _Fortify_LINE) | ||||
| #define strtod(buffer1,buffer2)       _Fortify_strtod(buffer1,buffer2, _Fortify_FILE, _Fortify_LINE) | ||||
| #define strcpy(to,from)               _Fortify_strcpy((char *)(to),(char *)(from), _Fortify_FILE, _Fortify_LINE) | ||||
| #define strncpy(to,from,size)         _Fortify_strncpy((char *)(to),(char *)(from),size, _Fortify_FILE, _Fortify_LINE) | ||||
| #define strcoll(buffer1,buffer2)      _Fortify_strcoll((char *)(buffer1),(char *)(buffer2), _Fortify_FILE, _Fortify_LINE) | ||||
| #define strcspn(buffer1,buffer2)      _Fortify_strcspn((char*)(buffer1),(char *)(buffer2), _Fortify_FILE, _Fortify_LINE) | ||||
| #define strcmp(buffer1,buffer2)       _Fortify_strcmp((char *)(buffer1),(char *)(buffer2), _Fortify_FILE, _Fortify_LINE) | ||||
| #define strcmpi(buffer1,buffer2)      _Fortify_strcmpi((char *)(buffer1),(char *)(buffer2), _Fortify_FILE, _Fortify_LINE) | ||||
| #define stricmp(buffer1,buffer2)      _Fortify_strcmpi((char *)(buffer1),(char *)(buffer2), _Fortify_FILE, _Fortify_LINE) | ||||
| #define strncmp(buffer1,buffer2,size) _Fortify_strncmp((char *)(buffer1),(char *)(buffer2),size, _Fortify_FILE, _Fortify_LINE) | ||||
| #define strnicmp(buffer1,buffer2,size) _Fortify_strnicmp((char *)(buffer1),(char *)(buffer2),size, _Fortify_FILE, _Fortify_LINE) | ||||
| #define strcat(buffer1,buffer2)       _Fortify_strcat((char *)(buffer1),(char *)(buffer2), _Fortify_FILE, _Fortify_LINE) | ||||
| #define strpbrk(buffer1,buffer2)      _Fortify_strpbrk((char *)(buffer1),(char *)(buffer2), _Fortify_FILE, _Fortify_LINE) | ||||
| #define strlen(buffer)                _Fortify_strlen((char*)(buffer), _Fortify_FILE, _Fortify_LINE) | ||||
| #define getcwd(buf,size)              _Fortify_getcwd(buf, size, _Fortify_FILE, _Fortify_LINE) | ||||
| #define tempnam(dir,pfx)              _Fortify_tempnam(dir, pfx, _Fortify_FILE, _Fortify_LINE) | ||||
| #define free(ptr)                     _Fortify_free(ptr, _Fortify_FILE, _Fortify_LINE) | ||||
| 
 | ||||
| #define Fortify_Init()                _Fortify_Init(_Fortify_FILE, _Fortify_LINE) | ||||
| #define Fortify_OutputAllMemory()     _Fortify_OutputAllMemory(_Fortify_FILE, _Fortify_LINE) | ||||
| #define Fortify_CheckAllMemory()      _Fortify_CheckAllMemory(_Fortify_FILE, _Fortify_LINE) | ||||
| #define Fortify_CheckPointer(ptr)     _Fortify_CheckPointer(ptr, _Fortify_FILE, _Fortify_LINE) | ||||
| #define Fortify_Disable(how)          _Fortify_Disable(_Fortify_FILE, _Fortify_LINE,how) | ||||
| #define Fortify_EnterScope()          _Fortify_EnterScope(_Fortify_FILE, _Fortify_LINE) | ||||
| #define Fortify_LeaveScope()          _Fortify_LeaveScope(_Fortify_FILE, _Fortify_LINE) | ||||
| #define Fortify_DumpAllMemory(s)      _Fortify_DumpAllMemory(s,_Fortify_FILE, _Fortify_LINE) | ||||
| 
 | ||||
| #else /* FORTIFY Define the special fortify functions away to nothing */ | ||||
| 
 | ||||
| #define Fortify_FILE(file) | ||||
| #define Fortify_LINE(line) | ||||
| #define Fortify_Init() | ||||
| #define Fortify_OutputAllMemory()     0 | ||||
| #define Fortify_CheckAllMemory()      0 | ||||
| #define Fortify_CheckPointer(ptr)     1 | ||||
| #define Fortify_Disable(how)          1 | ||||
| #define Fortify_SetOutputFunc()       0 | ||||
| #define Fortify_SetMallocFailRate(p)  0 | ||||
| #define Fortify_EnterScope()          0 | ||||
| #define Fortify_LeaveScope()          0 | ||||
| #define Fortify_DumpAllMemory(s)      0 | ||||
| 
 | ||||
| #endif /*   FORTIFY     */ | ||||
| #endif /* __FORTIFY_C__ */ | ||||
| #endif /* __FORTIFY_H__ */ | ||||
|  | @ -1,76 +0,0 @@ | |||
| #include <stdio.h> | ||||
| #include <ctype.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| #include "lp_lib.h" | ||||
| 
 | ||||
| #include "ini.h" | ||||
| 
 | ||||
| FILE *ini_create(char *filename) | ||||
| { | ||||
|   FILE *fp; | ||||
| 
 | ||||
|   fp = fopen(filename, "w"); | ||||
| 
 | ||||
|   return(fp); | ||||
| } | ||||
| 
 | ||||
| FILE *ini_open(char *filename) | ||||
| { | ||||
|   FILE *fp; | ||||
| 
 | ||||
|   fp = fopen(filename, "r"); | ||||
| 
 | ||||
|   return(fp); | ||||
| } | ||||
| 
 | ||||
| void ini_writecomment(FILE *fp, char *comment) | ||||
| { | ||||
|   fprintf(fp, "; %s\n", comment); | ||||
| } | ||||
| 
 | ||||
| void ini_writeheader(FILE *fp, char *header, int addnewline) | ||||
| { | ||||
|   if((addnewline) && (ftell(fp) > 0)) | ||||
|     fputs("\n", fp); | ||||
|   fprintf(fp, "[%s]\n", header); | ||||
| } | ||||
| 
 | ||||
| void ini_writedata(FILE *fp, char *name, char *data) | ||||
| { | ||||
|   if(name != NULL) | ||||
|     fprintf(fp, "%s=%s\n", name, data); | ||||
|   else | ||||
|     fprintf(fp, "%s\n", data); | ||||
| } | ||||
| 
 | ||||
| int ini_readdata(FILE *fp, char *data, int szdata, int withcomment) | ||||
| { | ||||
|   int l; | ||||
|   char *ptr; | ||||
| 
 | ||||
|   if(fgets(data, szdata, fp) == NULL) | ||||
|     return(0); | ||||
| 
 | ||||
|   if(!withcomment) { | ||||
|     ptr = strchr(data, ';'); | ||||
|     if(ptr != NULL) | ||||
|       *ptr = 0; | ||||
|   } | ||||
| 
 | ||||
|   l = strlen(data); | ||||
|   while((l > 0) && (isspace(data[l - 1]))) | ||||
|     l--; | ||||
|   data[l] = 0; | ||||
|   if((l >= 2) && (data[0] == '[') && (data[l - 1] == ']')) { | ||||
|     memcpy(data, data + 1, l - 2); | ||||
|     data[l - 2] = 0; | ||||
|     return(1); | ||||
|   } | ||||
|   return(2); | ||||
| } | ||||
| 
 | ||||
| void ini_close(FILE *fp) | ||||
| { | ||||
|   fclose(fp); | ||||
| } | ||||
|  | @ -1,17 +0,0 @@ | |||
| #include <stdio.h> | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| __EXTERN_C { | ||||
| #endif | ||||
| 
 | ||||
| extern FILE *ini_create(char *filename); | ||||
| extern FILE *ini_open(char *filename); | ||||
| extern void ini_writecomment(FILE *fp, char *comment); | ||||
| extern void ini_writeheader(FILE *fp, char *header, int addnewline); | ||||
| extern void ini_writedata(FILE *fp, char *name, char *data); | ||||
| extern int ini_readdata(FILE *fp, char *data, int szdata, int withcomment); | ||||
| extern void ini_close(FILE *fp); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | @ -1,238 +0,0 @@ | |||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include "lp_lib.h" | ||||
| #include "lp_utils.h" | ||||
| #include "lp_report.h" | ||||
| #include "lp_Hash.h" | ||||
| 
 | ||||
| #ifdef FORTIFY | ||||
| # include "lp_fortify.h" | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| #define HASH_START_SIZE  5000  /* Hash table size for row and column name storage */ | ||||
| #define NUMHASHPRIMES      45 | ||||
| 
 | ||||
| STATIC hashtable *create_hash_table(int size, int base) | ||||
| { | ||||
|   int i; | ||||
|   int HashPrimes[ ] = { | ||||
|              29,     229,     883,    1671,    2791,    4801,    8629,   10007, | ||||
|           15289,   25303,   34843,   65269,   99709,  129403,  147673,  166669, | ||||
|          201403,  222163,  242729,  261431,  303491,  320237,  402761,  501131, | ||||
|          602309,  701507,  800999,  900551, 1000619, 1100837, 1200359, 1300021, | ||||
|         1400017, 1500007, 1750009, 2000003, 2500009, 3000017, 4000037, 5000011, | ||||
|         6000011, 7000003, 8000009, 9000011, 9999991}; | ||||
|   hashtable *ht; | ||||
| 
 | ||||
|   /* Find a good size for the hash table */ | ||||
|   if(size < HASH_START_SIZE) | ||||
|     size = HASH_START_SIZE; | ||||
|   for(i = 0; i < NUMHASHPRIMES-1; i++) | ||||
|     if(HashPrimes[i] > size) | ||||
|       break; | ||||
|   size = HashPrimes[i]; | ||||
| 
 | ||||
|   /* Then allocate and initialize memory */ | ||||
|   ht = (hashtable *) calloc(1 , sizeof(*ht)); | ||||
|   ht->table = (hashelem **) calloc(size, sizeof(*(ht->table))); | ||||
|   ht->size = size; | ||||
|   ht->base = base; | ||||
|   ht->count = base-1; | ||||
| 
 | ||||
|   return(ht); | ||||
| } | ||||
| 
 | ||||
| STATIC void free_hash_item(hashelem **hp) | ||||
| { | ||||
|   free((*hp)->name); | ||||
|   free(*hp); | ||||
|   *hp = NULL; | ||||
| } | ||||
| 
 | ||||
| STATIC void free_hash_table(hashtable *ht) | ||||
| { | ||||
|   hashelem *hp, *thp; | ||||
| 
 | ||||
|   hp = ht->first; | ||||
|   while(hp != NULL) { | ||||
|     thp = hp; | ||||
|     hp = hp->nextelem; | ||||
|     free_hash_item(&thp); | ||||
|   } | ||||
|   free(ht->table); | ||||
|   free(ht); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* make a good hash function for any int size */ | ||||
| /* inspired by Aho, Sethi and Ullman, Compilers ..., p436 */ | ||||
| #define HASH_1 sizeof(unsigned int) | ||||
| #define HASH_2 (sizeof(unsigned int) * 6) | ||||
| #define HASH_3 (((unsigned int)0xF0) << ((sizeof(unsigned int) - 1) * CHAR_BIT)) | ||||
| 
 | ||||
| STATIC int hashval(const char *string, int size) | ||||
| { | ||||
|   unsigned int result = 0, tmp; | ||||
| 
 | ||||
|   for(; *string; string++) { | ||||
|     result = (result << HASH_1) + *string; | ||||
|     if((tmp = result & HASH_3) != 0) { | ||||
|       /* if any of the most significant bits is on */ | ||||
|       result ^= tmp >> HASH_2; /* xor them in in a less significant part */ | ||||
|       result ^= tmp; /* and reset the most significant bits to 0 */ | ||||
|     } | ||||
|   } | ||||
|   return(result % size); | ||||
| } /* hashval */ | ||||
| 
 | ||||
| 
 | ||||
| STATIC hashelem *findhash(const char *name, hashtable *ht) | ||||
| { | ||||
|   hashelem *h_tab_p; | ||||
|   for(h_tab_p = ht->table[hashval(name, ht->size)]; | ||||
|       h_tab_p != NULL; | ||||
|       h_tab_p = h_tab_p->next) | ||||
|     if(strcmp(name, h_tab_p->name) == 0) /* got it! */ | ||||
|       break; | ||||
|   return(h_tab_p); | ||||
| } /* findhash */ | ||||
| 
 | ||||
| 
 | ||||
| STATIC hashelem *puthash(const char *name, int index, hashelem **list, hashtable *ht) | ||||
| { | ||||
|   hashelem *hp = NULL; | ||||
|   int      hashindex; | ||||
| 
 | ||||
|   if(list != NULL) { | ||||
|     hp = list[index]; | ||||
|     if(hp != NULL) | ||||
|       list[index] = NULL; | ||||
|   } | ||||
| 
 | ||||
|   if((hp = findhash(name, ht)) == NULL) { | ||||
| 
 | ||||
|     hashindex = hashval(name, ht->size); | ||||
|     hp = (hashelem *) calloc(1, sizeof(*hp)); | ||||
|     allocCHAR(NULL, &hp->name, (int) (strlen(name) + 1), FALSE); | ||||
|     strcpy(hp->name, name); | ||||
|     hp->index = index; | ||||
|     ht->count++; | ||||
|     if(list != NULL) | ||||
|       list[index] = hp; | ||||
| 
 | ||||
|     hp->next = ht->table[hashindex]; | ||||
|     ht->table[hashindex] = hp; | ||||
|     if(ht->first == NULL) | ||||
|       ht->first = hp; | ||||
|     if(ht->last != NULL) | ||||
|       ht->last->nextelem = hp; | ||||
|     ht->last = hp; | ||||
| 
 | ||||
|   } | ||||
|   return(hp); | ||||
| } | ||||
| 
 | ||||
| STATIC void drophash(const char *name, hashelem **list, hashtable *ht) { | ||||
|   hashelem *hp, *hp1, *hp2; | ||||
|   int      hashindex; | ||||
| 
 | ||||
|   if((hp = findhash(name, ht)) != NULL) { | ||||
|     hashindex = hashval(name, ht->size); | ||||
|     if((hp1 = ht->table[hashindex]) != NULL) { | ||||
|       hp2 = NULL; | ||||
|       while((hp1 != NULL) && (hp1 != hp)) { | ||||
|         hp2 = hp1; | ||||
|         hp1 = hp1->next; | ||||
|       } | ||||
|       if(hp1 == hp) { | ||||
|         if(hp2 != NULL) | ||||
|           hp2->next = hp->next; | ||||
|         else | ||||
|           ht->table[hashindex] = hp->next; | ||||
|       } | ||||
| 
 | ||||
|       hp1 = ht->first; | ||||
|       hp2 = NULL; | ||||
|       while((hp1 != NULL) && (hp1 != hp)) { | ||||
|         hp2 = hp1; | ||||
|         hp1 = hp1->nextelem; | ||||
|       } | ||||
|       if(hp1 == hp) { | ||||
|         if(hp2 != NULL) | ||||
|           hp2->nextelem = hp->nextelem; | ||||
|         else { | ||||
|           ht->first = hp->nextelem; | ||||
|           if (ht->first == NULL) | ||||
|             ht->last = NULL; | ||||
|         } | ||||
|       } | ||||
|       if(list != NULL) | ||||
|         list[hp->index] = NULL; | ||||
|       free_hash_item(&hp); | ||||
|       ht->count--; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| STATIC hashtable *copy_hash_table(hashtable *ht, hashelem **list, int newsize) | ||||
| { | ||||
|   hashtable *copy; | ||||
|   hashelem  *elem, *new_elem; | ||||
| 
 | ||||
|   if(newsize < ht->size) | ||||
|     newsize = ht->size; | ||||
| 
 | ||||
|   copy = create_hash_table(newsize, ht->base); | ||||
|   if (copy != NULL) { | ||||
|     elem = ht->first; | ||||
|     while (elem != NULL) { | ||||
|       if((new_elem = puthash(elem->name, elem->index, list, copy)) == NULL) { | ||||
|         free_hash_table(copy); | ||||
|         return(NULL); | ||||
|       } | ||||
|       elem = elem ->nextelem; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   return(copy); | ||||
| } | ||||
| 
 | ||||
| STATIC int find_row(lprec *lp, char *name, MYBOOL Unconstrained_rows_found) | ||||
| { | ||||
|   hashelem *hp; | ||||
| 
 | ||||
|   if (lp->rowname_hashtab != NULL) | ||||
|       hp = findhash(name, lp->rowname_hashtab); | ||||
|   else | ||||
|       hp = NULL; | ||||
| 
 | ||||
|   if (hp == NULL) { | ||||
|     if(Unconstrained_rows_found) { /* just ignore them in this case */ | ||||
|          return(-1); | ||||
|     } | ||||
|     else { | ||||
|       return(-1); | ||||
|     } | ||||
|   } | ||||
|   return(hp->index); | ||||
| } | ||||
| 
 | ||||
| STATIC int find_var(lprec *lp, char *name, MYBOOL verbose) | ||||
| { | ||||
|   hashelem *hp; | ||||
| 
 | ||||
|   if (lp->colname_hashtab != NULL) | ||||
|       hp = findhash(name, lp->colname_hashtab); | ||||
|   else | ||||
|       hp = NULL; | ||||
| 
 | ||||
|   if (hp == NULL) { | ||||
|     if(verbose) | ||||
|       report(lp, SEVERE, "find_var: Unknown variable name '%s'\n", name); | ||||
|     return(-1); | ||||
|   } | ||||
|   return(hp->index); | ||||
| } | ||||
| 
 | ||||
|  | @ -1,43 +0,0 @@ | |||
| #ifndef HEADER_lp_hash | ||||
| #define HEADER_lp_hash | ||||
| 
 | ||||
| /* For row and column name hash tables */ | ||||
| 
 | ||||
| typedef struct _hashelem | ||||
| { | ||||
|   char             *name; | ||||
|   int               index; | ||||
|   struct _hashelem *next; | ||||
|   struct _hashelem *nextelem; | ||||
| } hashelem; | ||||
| 
 | ||||
| typedef struct _hashtable | ||||
| { | ||||
|   hashelem         **table; | ||||
|   int              size; | ||||
|   int              base; | ||||
|   int              count; | ||||
|   struct _hashelem *first; | ||||
|   struct _hashelem *last; | ||||
| } hashtable; | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| STATIC hashtable *create_hash_table(int size, int base); | ||||
| STATIC void      free_hash_table(hashtable *ht); | ||||
| STATIC hashelem  *findhash(const char *name, hashtable *ht); | ||||
| STATIC hashelem  *puthash(const char *name, int index, hashelem **list, hashtable *ht); | ||||
| STATIC void      drophash(const char *name, hashelem **list, hashtable *ht); | ||||
| STATIC void      free_hash_item(hashelem **hp); | ||||
| STATIC hashtable *copy_hash_table(hashtable *ht, hashelem **list, int newsize); | ||||
| STATIC int find_var(lprec *lp, char *name, MYBOOL verbose); | ||||
| STATIC int find_row(lprec *lp, char *name, MYBOOL Unconstrained_rows_found); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
|  } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* HEADER_lp_hash */ | ||||
| 
 | ||||
|  | @ -1,241 +0,0 @@ | |||
| /*
 | ||||
|     Minimum matrix inverse fill-in modules - interface for lp_solve v5.0+ | ||||
|    ---------------------------------------------------------------------------------- | ||||
|     Author:        Kjell Eikland  | ||||
|     Contact:       kjell.eikland@broadpark.no  | ||||
|     License terms: LGPL. | ||||
|      | ||||
|     Requires:      string.h, colamd.h, lp_lib.h | ||||
| 
 | ||||
|     Release notes: | ||||
|     v1.0    1 September 2003    Preprocessing routines for minimum fill-in column  | ||||
|                                 ordering for inverse factorization using the open  | ||||
|                                 source COLAMD library.  Suitable for the dense parts | ||||
|                                 of both the product form and LU factorization inverse  | ||||
|                                 methods. | ||||
|     v1.1    1 July 2004         Renamed from lp_colamdMDO to lp_MDO.                                 | ||||
| 
 | ||||
|    ----------------------------------------------------------------------------------  | ||||
| */ | ||||
| 
 | ||||
| #include <string.h> | ||||
| #include "commonlib.h" | ||||
| #include "lp_lib.h" | ||||
| #include "colamd.h" | ||||
| #include "lp_MDO.h" | ||||
| 
 | ||||
| #ifdef FORTIFY | ||||
| # include "lp_fortify.h" | ||||
| #endif | ||||
| 
 | ||||
| STATIC MYBOOL includeMDO(MYBOOL *usedpos, int item) | ||||
| { | ||||
| /*  Legend:   TRUE            => A basic slack variable already in the basis
 | ||||
|               FALSE           => A column free for being pivoted in | ||||
|               AUTOMATIC+TRUE  => A row-singleton user column pivoted into the basis | ||||
|               AUTOMATIC+FALSE => A column-singleton user column pivoted into the basis */ | ||||
| 
 | ||||
|   /* Handle case where we are processing all columns */ | ||||
|   if(usedpos == NULL) | ||||
|     return( TRUE ); | ||||
|      | ||||
|   else { | ||||
|   /* Otherwise do the selective case */ | ||||
|     MYBOOL test = usedpos[item]; | ||||
| #if 1 | ||||
|     return( test != TRUE ); | ||||
| #else | ||||
|     test = test & TRUE; | ||||
|     return( test == FALSE ); | ||||
| #endif | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| STATIC int prepareMDO(lprec *lp, MYBOOL *usedpos, int *colorder, int *data, int *rowmap) | ||||
| /* This routine prepares data structures for colamd().  It is called twice, the first
 | ||||
|    time to count applicable non-zero elements by column, and the second time to fill in  | ||||
|    the row indexes of the non-zero values from the first call.  Note that the colamd()  | ||||
|    row index base is 0 (which suits lp_solve fine). */ | ||||
| { | ||||
|   int     i, ii, j, k, kk; | ||||
|   int     nrows = lp->rows+1, ncols = colorder[0]; | ||||
|   int     offset = 0, Bnz = 0, Tnz; | ||||
|   MYBOOL  dotally = (MYBOOL) (rowmap == NULL); | ||||
|   MATrec  *mat = lp->matA; | ||||
|   REAL    hold; | ||||
|   REAL    *value; | ||||
|   int     *rownr; | ||||
| 
 | ||||
|   if(dotally) | ||||
|     data[0] = 0; | ||||
| 
 | ||||
|   Tnz = nrows - ncols; | ||||
|   for(j = 1; j <= ncols; j++) { | ||||
|     kk = colorder[j]; | ||||
| 
 | ||||
|     /* Process slacks */ | ||||
|     if(kk <= lp->rows) { | ||||
|       if(includeMDO(usedpos, kk)) { | ||||
|         if(!dotally) | ||||
|           data[Bnz] = rowmap[kk]+offset; | ||||
|         Bnz++; | ||||
|       } | ||||
|       Tnz++; | ||||
|     } | ||||
|     /* Process user columns */ | ||||
|     else { | ||||
|       k = kk - lp->rows; | ||||
|       i = mat->col_end[k-1]; | ||||
|       ii= mat->col_end[k]; | ||||
|       Tnz += ii-i; | ||||
| #ifdef Paranoia | ||||
|       if(i >= ii) | ||||
|         lp->report(lp, SEVERE, "prepareMDO: Encountered empty basic column %d\n", k); | ||||
| #endif | ||||
| 
 | ||||
|       /* Detect if we need to do phase 1 adjustments of zero-valued OF variable */ | ||||
|       rownr = &COL_MAT_ROWNR(i); | ||||
|       value = &COL_MAT_VALUE(i); | ||||
|       hold = 0; | ||||
|       if((*rownr > 0) && includeMDO(usedpos, 0) && modifyOF1(lp, kk, &hold, 1.0)) { | ||||
|         if(!dotally) | ||||
|           data[Bnz] = offset; | ||||
|         Bnz++; | ||||
|       } | ||||
|       /* Loop over all NZ-variables */ | ||||
|       for(; i < ii;  | ||||
|           i++, value += matValueStep, rownr += matRowColStep) { | ||||
|         if(!includeMDO(usedpos, *rownr)) | ||||
|           continue; | ||||
|         /* See if we need to change phase 1 OF value */ | ||||
|         if(*rownr == 0) { | ||||
|           hold = *value; | ||||
|           if(!modifyOF1(lp, kk, &hold, 1.0))  | ||||
|             continue; | ||||
|         } | ||||
|         /* Tally uneliminated constraint row values */ | ||||
|         if(!dotally) | ||||
|           data[Bnz] = rowmap[*rownr]+offset; | ||||
|         Bnz++; | ||||
|       } | ||||
|     } | ||||
|     if(dotally) | ||||
|       data[j] = Bnz; | ||||
|   } | ||||
|   return( Tnz ); | ||||
| } | ||||
| 
 | ||||
| STATIC MYBOOL verifyMDO(lprec *lp, int *col_end, int *row_nr, int rowmax, int colmax) | ||||
| { | ||||
|   int i, j, n, err = 0; | ||||
| 
 | ||||
|   for(i = 1; i <= colmax; i++) { | ||||
|     n = 0; | ||||
|     for(j = col_end[i-1]; (j < col_end[i]) && (err == 0); j++, n++) { | ||||
|       if(row_nr[j] < 0 || row_nr[j] > rowmax) | ||||
|         err = 1; | ||||
|       if(n > 0 && row_nr[j] <= row_nr[j-1]) | ||||
|         err = 2; | ||||
|       n++; | ||||
|     } | ||||
|   } | ||||
|   if(err != 0) | ||||
|     lp->report(lp, SEVERE, "verifyMDO: Invalid MDO input structure generated (error %d)\n", err); | ||||
|   return( (MYBOOL) (err == 0) ); | ||||
| } | ||||
| 
 | ||||
| void *mdo_calloc(size_t size, size_t count) | ||||
| { | ||||
|   return ( calloc(size, count) ); | ||||
| } | ||||
| void mdo_free(void *mem) | ||||
| { | ||||
|   free( mem ); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int __WINAPI getMDO(lprec *lp, MYBOOL *usedpos, int *colorder, int *size, MYBOOL symmetric) | ||||
| { | ||||
|   int    error = FALSE; | ||||
|   int    nrows = lp->rows+1, ncols = colorder[0]; | ||||
|   int    i, j, kk, n; | ||||
|   int    *col_end, *row_map = NULL; | ||||
|   int    Bnz, Blen, *Brows = NULL; | ||||
|   int    stats[COLAMD_STATS]; | ||||
|   double knobs[COLAMD_KNOBS]; | ||||
| 
 | ||||
|  /* Tally the non-zero counts of the unused columns/rows of the 
 | ||||
|     basis matrix and store corresponding "net" starting positions */ | ||||
|   allocINT(lp, &col_end, ncols+1, FALSE); | ||||
|   n = prepareMDO(lp, usedpos, colorder, col_end, NULL); | ||||
|   Bnz = col_end[ncols]; | ||||
| 
 | ||||
|  /* Check that we have unused basic columns, otherwise skip analysis */   | ||||
|   if(ncols == 0 || Bnz == 0)  | ||||
|     goto Transfer; | ||||
| 
 | ||||
|  /* Get net number of rows and fill mapper */ | ||||
|   allocINT(lp, &row_map, nrows, FALSE); | ||||
|   nrows = 0; | ||||
|   for(i = 0; i <= lp->rows; i++) { | ||||
|     row_map[i] = i-nrows; | ||||
|    /* Increment eliminated row counter if necessary */ | ||||
|     if(!includeMDO(usedpos, i))  | ||||
|       nrows++; | ||||
|   } | ||||
|   nrows = lp->rows+1 - nrows; | ||||
| 
 | ||||
|  /* Store row indeces of non-zero values in the basic columns */ | ||||
|   Blen = colamd_recommended(Bnz, nrows, ncols); | ||||
|   allocINT(lp, &Brows, Blen, FALSE); | ||||
|   prepareMDO(lp, usedpos, colorder, Brows, row_map); | ||||
| #ifdef Paranoia | ||||
|   verifyMDO(lp, col_end, Brows, nrows, ncols); | ||||
| #endif | ||||
| 
 | ||||
|  /* Compute the MDO */ | ||||
| #if 1 | ||||
|   colamd_set_defaults(knobs); | ||||
|   knobs [COLAMD_DENSE_ROW] = 0.2+0.2 ;    /* default changed for UMFPACK */ | ||||
|   knobs [COLAMD_DENSE_COL] = knobs [COLAMD_DENSE_ROW];     | ||||
|   if(symmetric && (nrows == ncols)) { | ||||
|     MEMCOPY(colorder, Brows, ncols + 1); | ||||
|     error = !symamd(nrows, colorder, col_end, Brows, knobs, stats, mdo_calloc, mdo_free); | ||||
|   } | ||||
|   else | ||||
|     error = !colamd(nrows, ncols, Blen, Brows, col_end, knobs, stats); | ||||
| #else | ||||
|   if(symmetric && (nrows == ncols)) { | ||||
|     MEMCOPY(colorder, Brows, ncols + 1); | ||||
|     error = !symamd(nrows, colorder, col_end, Brows, knobs, stats, mdo_calloc, mdo_free); | ||||
|   } | ||||
|   else | ||||
|     error = !colamd(nrows, ncols, Blen, Brows, col_end, (double *) NULL, stats); | ||||
| #endif | ||||
| 
 | ||||
|  /* Transfer the estimated optimal ordering, adjusting for index offsets */ | ||||
| Transfer: | ||||
|   if(error)  | ||||
|     error = stats[COLAMD_STATUS]; | ||||
|   else { | ||||
|     MEMCOPY(Brows, colorder, ncols + 1); | ||||
|     for(j = 0; j < ncols; j++) { | ||||
|       kk = col_end[j]; | ||||
|       n = Brows[kk+1]; | ||||
|       colorder[j+1] = n; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /* Free temporary vectors */ | ||||
|   FREE(col_end); | ||||
|   if(row_map != NULL) | ||||
|     FREE(row_map); | ||||
|   if(Brows != NULL) | ||||
|     FREE(Brows); | ||||
| 
 | ||||
|   if(size != NULL) | ||||
|     *size = ncols; | ||||
|   return( error ); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -1,18 +0,0 @@ | |||
| #ifndef HEADER_MDO | ||||
| #define HEADER_MDO | ||||
| 
 | ||||
| #include "lp_types.h" | ||||
| 
 | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| int __WINAPI getMDO(lprec *lp, MYBOOL *usedpos, int *colorder, int *size, MYBOOL symmetric); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
|  } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* HEADER_MDO */ | ||||
| 
 | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -1,33 +0,0 @@ | |||
| #ifndef HEADER_lp_MPS | ||||
| #define HEADER_lp_MPS | ||||
| 
 | ||||
| #include "lp_types.h" | ||||
| 
 | ||||
| /* For MPS file reading and writing */ | ||||
| #define ROWNAMEMASK          "R%d" | ||||
| #define ROWNAMEMASK2         "r%d" | ||||
| #define COLNAMEMASK          "C%d" | ||||
| #define COLNAMEMASK2         "c%d" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| /* Read an MPS file */ | ||||
| MYBOOL MPS_readfile(lprec **newlp, char *filename, int typeMPS, int verbose); | ||||
| MYBOOL __WINAPI MPS_readhandle(lprec **newlp, FILE *filehandle, int typeMPS, int verbose); | ||||
| 
 | ||||
| /* Write a MPS file to output */ | ||||
| MYBOOL MPS_writefile(lprec *lp, int typeMPS, char *filename); | ||||
| MYBOOL MPS_writehandle(lprec *lp, int typeMPS, FILE *output); | ||||
| 
 | ||||
| /* Read and write BAS files */ | ||||
| MYBOOL MPS_readBAS(lprec *lp, int typeMPS, char *filename, char *info); | ||||
| MYBOOL MPS_writeBAS(lprec *lp, int typeMPS, char *filename); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
|  } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* HEADER_lp_MPS */ | ||||
| 
 | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -1,108 +0,0 @@ | |||
| #ifndef HEADER_lp_SOS | ||||
| #define HEADER_lp_SOS | ||||
| 
 | ||||
| /* Specially Ordered Sets (SOS) prototypes and settings                      */ | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| 
 | ||||
| #include "lp_types.h" | ||||
| #include "lp_utils.h" | ||||
| #include "lp_matrix.h" | ||||
| 
 | ||||
| 
 | ||||
| /* SOS constraint defines                                                    */ | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| #define SOS1                     1 | ||||
| #define SOS2                     2 | ||||
| #define SOS3                    -1 | ||||
| #define SOSn                      MAXINT32 | ||||
| #define SOS_START_SIZE          10  /* Start size of SOS_list array; realloced if needed */ | ||||
| 
 | ||||
| /* Define SOS_is_feasible() return values                                    */ | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| #define SOS3_INCOMPLETE         -2 | ||||
| #define SOS_INCOMPLETE          -1 | ||||
| #define SOS_COMPLETE             0 | ||||
| #define SOS_INFEASIBLE           1 | ||||
| #define SOS_INTERNALERROR        2 | ||||
| 
 | ||||
| 
 | ||||
| typedef struct _SOSgroup SOSgroup; | ||||
| 
 | ||||
| typedef struct _SOSrec | ||||
| { | ||||
|   SOSgroup  *parent; | ||||
|   int       tagorder; | ||||
|   char      *name; | ||||
|   int       type; | ||||
|   MYBOOL    isGUB; | ||||
|   int       size; | ||||
|   int       priority; | ||||
|   int       *members; | ||||
|   REAL      *weights; | ||||
|   int       *membersSorted; | ||||
|   int       *membersMapped; | ||||
| } SOSrec; | ||||
| 
 | ||||
| /* typedef */ struct _SOSgroup | ||||
| { | ||||
|   lprec     *lp;                /* Pointer to owner */ | ||||
|   SOSrec    **sos_list;         /* Array of pointers to SOS lists */ | ||||
|   int       sos_alloc;          /* Size allocated to specially ordered sets (SOS1, SOS2...) */ | ||||
|   int       sos_count;          /* Number of specially ordered sets (SOS1, SOS2...) */ | ||||
|   int       maxorder;           /* The highest-order SOS in the group */ | ||||
|   int       sos1_count;         /* Number of the lowest order SOS in the group */ | ||||
|   int       *membership;        /* Array of variable-sorted indeces to SOSes that the variable is member of */ | ||||
|   int       *memberpos;         /* Starting positions of the each column's membership list */ | ||||
| } /* SOSgroup */; | ||||
| 
 | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| /* SOS storage structure */ | ||||
| STATIC SOSgroup *create_SOSgroup(lprec *lp); | ||||
| STATIC void resize_SOSgroup(SOSgroup *group); | ||||
| STATIC int append_SOSgroup(SOSgroup *group, SOSrec *SOS); | ||||
| STATIC int clean_SOSgroup(SOSgroup *group, MYBOOL forceupdatemap); | ||||
| STATIC void free_SOSgroup(SOSgroup **group); | ||||
| 
 | ||||
| STATIC SOSrec *create_SOSrec(SOSgroup *group, char *name, int type, int priority, int size, int *variables, REAL *weights); | ||||
| STATIC MYBOOL delete_SOSrec(SOSgroup *group, int sosindex); | ||||
| STATIC int append_SOSrec(SOSrec *SOS, int size, int *variables, REAL *weights); | ||||
| STATIC void free_SOSrec(SOSrec *SOS); | ||||
| 
 | ||||
| /* SOS utilities */ | ||||
| STATIC int make_SOSchain(lprec *lp, MYBOOL forceresort); | ||||
| STATIC int SOS_member_updatemap(SOSgroup *group); | ||||
| STATIC MYBOOL SOS_member_sortlist(SOSgroup *group, int sosindex); | ||||
| STATIC MYBOOL SOS_shift_col(SOSgroup *group, int sosindex, int column, int delta, LLrec *usedmap, MYBOOL forceresort); | ||||
| int SOS_member_delete(SOSgroup *group, int sosindex, int member); | ||||
| int SOS_get_type(SOSgroup *group, int sosindex); | ||||
| int SOS_infeasible(SOSgroup *group, int sosindex); | ||||
| int SOS_member_index(SOSgroup *group, int sosindex, int member); | ||||
| int SOS_member_count(SOSgroup *group, int sosindex); | ||||
| int SOS_memberships(SOSgroup *group, int column); | ||||
| int *SOS_get_candidates(SOSgroup *group, int sosindex, int column, MYBOOL excludetarget, REAL *upbound, REAL *lobound); | ||||
| int SOS_is_member(SOSgroup *group, int sosindex, int column); | ||||
| MYBOOL SOS_is_member_of_type(SOSgroup *group, int column, int sostype); | ||||
| MYBOOL SOS_set_GUB(SOSgroup *group, int sosindex, MYBOOL state); | ||||
| MYBOOL SOS_is_GUB(SOSgroup *group, int sosindex); | ||||
| MYBOOL SOS_is_marked(SOSgroup *group, int sosindex, int column); | ||||
| MYBOOL SOS_is_active(SOSgroup *group, int sosindex, int column); | ||||
| MYBOOL SOS_is_full(SOSgroup *group, int sosindex, int column, MYBOOL activeonly); | ||||
| MYBOOL SOS_can_activate(SOSgroup *group, int sosindex, int column); | ||||
| MYBOOL SOS_set_marked(SOSgroup *group, int sosindex, int column, MYBOOL asactive); | ||||
| MYBOOL SOS_unmark(SOSgroup *group, int sosindex, int column); | ||||
| int SOS_fix_unmarked(SOSgroup *group, int sosindex, int variable, REAL *bound, REAL value, | ||||
|                      MYBOOL isupper, int *diffcount, DeltaVrec *changelog); | ||||
| int SOS_fix_list(SOSgroup *group, int sosindex, int variable, REAL *bound,  | ||||
|                   int *varlist, MYBOOL isleft, DeltaVrec *changelog); | ||||
| int SOS_is_satisfied(SOSgroup *group, int sosindex, REAL *solution); | ||||
| MYBOOL SOS_is_feasible(SOSgroup *group, int sosindex, REAL *solution); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
|  } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* HEADER_lp_SOS */ | ||||
|  | @ -1,727 +0,0 @@ | |||
| 
 | ||||
| /*
 | ||||
|    ---------------------------------------------------------------------------------- | ||||
|    Crash management routines in lp_solve v5.0+ | ||||
|    ---------------------------------------------------------------------------------- | ||||
|     Author:        Kjell Eikland | ||||
|     Contact:       kjell.eikland@broadpark.no | ||||
|     License terms: LGPL. | ||||
| 
 | ||||
|     Requires:      lp_lib.h, lp_utils.h, lp_matrix.h | ||||
| 
 | ||||
|     Release notes: | ||||
|     v1.0.0  1 April   2004      First version. | ||||
|     v1.1.0  20 July 2004        Reworked with flexible matrix storage model. | ||||
| 
 | ||||
|    ---------------------------------------------------------------------------------- | ||||
| */ | ||||
| 
 | ||||
| #include <string.h> | ||||
| 
 | ||||
| #include "commonlib.h" | ||||
| #include "lp_lib.h" | ||||
| #include "lp_scale.h" | ||||
| #include "lp_utils.h" | ||||
| #include "lp_report.h" | ||||
| #include "lp_matrix.h" | ||||
| #include "lp_crash.h" | ||||
| 
 | ||||
| #ifdef FORTIFY | ||||
| # include "lp_fortify.h" | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| MYBOOL crash_basis(lprec *lp) | ||||
| { | ||||
|   int     i; | ||||
|   MATrec  *mat = lp->matA; | ||||
|   MYBOOL  ok = TRUE; | ||||
| 
 | ||||
|   /* Initialize basis indicators */ | ||||
|   if(lp->basis_valid) | ||||
|     lp->var_basic[0] = FALSE; | ||||
|   else | ||||
|     default_basis(lp); | ||||
| 
 | ||||
|   /* Set initial partial pricing blocks */ | ||||
|   if(lp->rowblocks != NULL) | ||||
|     lp->rowblocks->blocknow = 1; | ||||
|   if(lp->colblocks != NULL) | ||||
|     lp->colblocks->blocknow = ((lp->crashmode == CRASH_NONE) || (lp->colblocks->blockcount == 1) ? 1 : 2); | ||||
| 
 | ||||
|   /* Construct a basis that is in some measure the "most feasible" */ | ||||
|   if((lp->crashmode == CRASH_MOSTFEASIBLE) && mat_validate(mat)) { | ||||
|     /* The logic here follows Maros */ | ||||
|     LLrec   *rowLL = NULL, *colLL = NULL; | ||||
|     int     ii, rx, cx, ix, nz; | ||||
|     REAL    wx, tx, *rowMAX = NULL, *colMAX = NULL; | ||||
|     int     *rowNZ = NULL, *colNZ = NULL, *rowWT = NULL, *colWT = NULL; | ||||
|     REAL    *value; | ||||
|     int     *rownr, *colnr; | ||||
| 
 | ||||
|     report(lp, NORMAL, "crash_basis: 'Most feasible' basis crashing selected\n"); | ||||
| 
 | ||||
|     /* Tally row and column non-zero counts */ | ||||
|     ok = allocINT(lp,  &rowNZ, lp->rows+1,     TRUE) && | ||||
|          allocINT(lp,  &colNZ, lp->columns+1,  TRUE) && | ||||
|          allocREAL(lp, &rowMAX, lp->rows+1,    FALSE) && | ||||
|          allocREAL(lp, &colMAX, lp->columns+1, FALSE); | ||||
|     if(!ok) | ||||
|       goto Finish; | ||||
| 
 | ||||
|     nz = mat_nonzeros(mat); | ||||
|     rownr = &COL_MAT_ROWNR(0); | ||||
|     colnr = &COL_MAT_COLNR(0); | ||||
|     value = &COL_MAT_VALUE(0); | ||||
|     for(i = 0; i < nz; | ||||
|         i++, rownr += matRowColStep, colnr += matRowColStep, value += matValueStep) { | ||||
|       rx = *rownr; | ||||
|       cx = *colnr; | ||||
|       wx = fabs(*value); | ||||
|       rowNZ[rx]++; | ||||
|       colNZ[cx]++; | ||||
|       if(i == 0) { | ||||
|         rowMAX[rx] = wx; | ||||
|         colMAX[cx] = wx; | ||||
|         colMAX[0]  = wx; | ||||
|       } | ||||
|       else { | ||||
|         SETMAX(rowMAX[rx], wx); | ||||
|         SETMAX(colMAX[cx], wx); | ||||
|         SETMAX(colMAX[0],  wx); | ||||
|       } | ||||
|     } | ||||
|     /* Reduce counts for small magnitude to preserve stability */ | ||||
|     rownr = &COL_MAT_ROWNR(0); | ||||
|     colnr = &COL_MAT_COLNR(0); | ||||
|     value = &COL_MAT_VALUE(0); | ||||
|     for(i = 0; i < nz; | ||||
|         i++, rownr += matRowColStep, colnr += matRowColStep, value += matValueStep) { | ||||
|       rx = *rownr; | ||||
|       cx = *colnr; | ||||
|       wx = fabs(*value); | ||||
| #ifdef CRASH_SIMPLESCALE | ||||
|       if(wx < CRASH_THRESHOLD * colMAX[0]) { | ||||
|         rowNZ[rx]--; | ||||
|         colNZ[cx]--; | ||||
|       } | ||||
| #else | ||||
|       if(wx < CRASH_THRESHOLD * rowMAX[rx]) | ||||
|         rowNZ[rx]--; | ||||
|       if(wx < CRASH_THRESHOLD * colMAX[cx]) | ||||
|         colNZ[cx]--; | ||||
| #endif | ||||
|     } | ||||
| 
 | ||||
|     /* Set up priority tables */ | ||||
|     ok = allocINT(lp, &rowWT, lp->rows+1, TRUE); | ||||
|     createLink(lp->rows,    &rowLL, NULL); | ||||
|     ok &= (rowLL != NULL); | ||||
|     if(!ok) | ||||
|       goto Finish; | ||||
|     for(i = 1; i <= lp->rows; i++) { | ||||
|       if(get_constr_type(lp, i)==EQ) | ||||
|         ii = 3; | ||||
|       else if(lp->upbo[i] < lp->infinite) | ||||
|         ii = 2; | ||||
|       else if(fabs(lp->rhs[i]) < lp->infinite) | ||||
|         ii = 1; | ||||
|       else | ||||
|         ii = 0; | ||||
|       rowWT[i] = ii; | ||||
|       if(ii > 0) | ||||
|         appendLink(rowLL, i); | ||||
|     } | ||||
|     ok = allocINT(lp, &colWT, lp->columns+1, TRUE); | ||||
|     createLink(lp->columns, &colLL, NULL); | ||||
|     ok &= (colLL != NULL); | ||||
|     if(!ok) | ||||
|       goto Finish; | ||||
|     for(i = 1; i <= lp->columns; i++) { | ||||
|       ix = lp->rows+i; | ||||
|       if(is_unbounded(lp, i)) | ||||
|         ii = 3; | ||||
|       else if(lp->upbo[ix] >= lp->infinite) | ||||
|         ii = 2; | ||||
|       else if(fabs(lp->upbo[ix]-lp->lowbo[ix]) > lp->epsmachine) | ||||
|         ii = 1; | ||||
|       else | ||||
|         ii = 0; | ||||
|       colWT[i] = ii; | ||||
|       if(ii > 0) | ||||
|         appendLink(colLL, i); | ||||
|     } | ||||
| 
 | ||||
|     /* Loop over all basis variables */ | ||||
|     for(i = 1; i <= lp->rows; i++) { | ||||
| 
 | ||||
|       /* Select row */ | ||||
|       rx = 0; | ||||
|       wx = -lp->infinite; | ||||
|       for(ii = firstActiveLink(rowLL); ii > 0; ii = nextActiveLink(rowLL, ii)) { | ||||
|         tx = rowWT[ii] - CRASH_SPACER*rowNZ[ii]; | ||||
|         if(tx > wx) { | ||||
|           rx = ii; | ||||
|           wx = tx; | ||||
|         } | ||||
|       } | ||||
|       if(rx == 0) | ||||
|         break; | ||||
|       removeLink(rowLL, rx); | ||||
| 
 | ||||
|       /* Select column */ | ||||
|       cx = 0; | ||||
|       wx = -lp->infinite; | ||||
|       for(ii = mat->row_end[rx-1]; ii < mat->row_end[rx]; ii++) { | ||||
| 
 | ||||
|         /* Update NZ column counts for row selected above */ | ||||
|         tx = fabs(ROW_MAT_VALUE(ii)); | ||||
|         ix = ROW_MAT_COLNR(ii); | ||||
| #ifdef CRASH_SIMPLESCALE | ||||
|         if(tx >= CRASH_THRESHOLD * colMAX[0]) | ||||
| #else | ||||
|         if(tx >= CRASH_THRESHOLD * colMAX[ix]) | ||||
| #endif | ||||
|           colNZ[ix]--; | ||||
|         if(!isActiveLink(colLL, ix) || (tx < CRASH_THRESHOLD * rowMAX[rx])) | ||||
|           continue; | ||||
| 
 | ||||
|         /* Now do the test for best pivot */ | ||||
|         tx = my_sign(lp->orig_obj[ix]) - my_sign(ROW_MAT_VALUE(ii)); | ||||
|         tx = colWT[ix] + CRASH_WEIGHT*tx - CRASH_SPACER*colNZ[ix]; | ||||
|         if(tx > wx) { | ||||
|           cx = ix; | ||||
|           wx = tx; | ||||
|         } | ||||
|       } | ||||
|       if(cx == 0) | ||||
|         break; | ||||
|       removeLink(colLL, cx); | ||||
| 
 | ||||
|       /* Update row NZ counts */ | ||||
|       ii = mat->col_end[cx-1]; | ||||
|       rownr = &COL_MAT_ROWNR(ii); | ||||
|       value = &COL_MAT_VALUE(ii); | ||||
|       for(; ii < mat->col_end[cx]; | ||||
|           ii++, rownr += matRowColStep, value += matValueStep) { | ||||
|         wx = fabs(*value); | ||||
|         ix = *rownr; | ||||
| #ifdef CRASH_SIMPLESCALE | ||||
|         if(wx >= CRASH_THRESHOLD * colMAX[0]) | ||||
| #else | ||||
|         if(wx >= CRASH_THRESHOLD * rowMAX[ix]) | ||||
| #endif | ||||
|           rowNZ[ix]--; | ||||
|       } | ||||
| 
 | ||||
|       /* Set new basis variable */ | ||||
|       set_basisvar(lp, rx, lp->rows+cx); | ||||
|     } | ||||
| 
 | ||||
|     /* Clean up */ | ||||
| Finish: | ||||
|     FREE(rowNZ); | ||||
|     FREE(colNZ); | ||||
|     FREE(rowMAX); | ||||
|     FREE(colMAX); | ||||
|     FREE(rowWT); | ||||
|     FREE(colWT); | ||||
|     freeLink(&rowLL); | ||||
|     freeLink(&colLL); | ||||
|   } | ||||
| 
 | ||||
|   /* Construct a basis that is in some measure the "least degenerate" */ | ||||
|   else if((lp->crashmode == CRASH_LEASTDEGENERATE) && mat_validate(mat)) { | ||||
|     /* The logic here follows Maros */ | ||||
|     LLrec   *rowLL = NULL, *colLL = NULL; | ||||
|     int     ii, rx, cx, ix, nz, *merit = NULL; | ||||
|     REAL    *value, wx, hold, *rhs = NULL, *eta = NULL; | ||||
|     int     *rownr, *colnr; | ||||
| 
 | ||||
|     report(lp, NORMAL, "crash_basis: 'Least degenerate' basis crashing selected\n"); | ||||
| 
 | ||||
|     /* Create temporary arrays */ | ||||
|     ok = allocINT(lp,  &merit, lp->columns + 1, FALSE) && | ||||
|          allocREAL(lp, &eta, lp->rows + 1, FALSE) && | ||||
|          allocREAL(lp, &rhs, lp->rows + 1, FALSE); | ||||
|     createLink(lp->columns, &colLL, NULL); | ||||
|     createLink(lp->rows, &rowLL, NULL); | ||||
|     ok &= (colLL != NULL) && (rowLL != NULL); | ||||
|     if(!ok) | ||||
|       goto FinishLD; | ||||
|     MEMCOPY(rhs, lp->orig_rhs, lp->rows + 1); | ||||
|     for(i = 1; i <= lp->columns; i++) | ||||
|       appendLink(colLL, i); | ||||
|     for(i = 1; i <= lp->rows; i++) | ||||
|       appendLink(rowLL, i); | ||||
| 
 | ||||
|     /* Loop until we have found enough new bases */ | ||||
|     while(colLL->count > 0) { | ||||
| 
 | ||||
|       /* Tally non-zeros matching in RHS and each active column */ | ||||
|       nz = mat_nonzeros(mat); | ||||
|       rownr = &COL_MAT_ROWNR(0); | ||||
|       colnr = &COL_MAT_COLNR(0); | ||||
|       ii = 0; | ||||
|       MEMCLEAR(merit, lp->columns + 1); | ||||
|       for(i = 0; i < nz; | ||||
|           i++, rownr += matRowColStep, colnr += matRowColStep) { | ||||
|         rx = *rownr; | ||||
|         cx = *colnr; | ||||
|         if(isActiveLink(colLL, cx) && (rhs[rx] != 0)) { | ||||
|           merit[cx]++; | ||||
|           ii++; | ||||
|         } | ||||
|       } | ||||
|       if(ii == 0) | ||||
|         break; | ||||
| 
 | ||||
|       /* Find maximal match; break ties with column length */ | ||||
|       i = firstActiveLink(colLL); | ||||
|       cx = i; | ||||
|       for(i = nextActiveLink(colLL, i); i != 0; i = nextActiveLink(colLL, i)) { | ||||
|         if(merit[i] >= merit[cx]) { | ||||
|           if((merit[i] > merit[cx]) || (mat_collength(mat, i) > mat_collength(mat, cx))) | ||||
|             cx = i; | ||||
|         } | ||||
|       } | ||||
| 
 | ||||
|       /* Determine the best pivot row */ | ||||
|       i = mat->col_end[cx-1]; | ||||
|       nz = mat->col_end[cx]; | ||||
|       rownr = &COL_MAT_ROWNR(i); | ||||
|       value = &COL_MAT_VALUE(i); | ||||
|       rx = 0; | ||||
|       wx = 0; | ||||
|       MEMCLEAR(eta, lp->rows + 1); | ||||
|       for(; i < nz; | ||||
|           i++, rownr += matRowColStep, value += matValueStep) { | ||||
|         ix = *rownr; | ||||
|         hold = *value; | ||||
|         eta[ix] = rhs[ix] / hold; | ||||
|         hold = fabs(hold); | ||||
|         if(isActiveLink(rowLL, ix) && (hold > wx)) { | ||||
|           wx = hold; | ||||
|           rx = ix; | ||||
|         } | ||||
|       } | ||||
| 
 | ||||
|       /* Set new basis variable */ | ||||
|       if(rx > 0) { | ||||
| 
 | ||||
|         /* We have to update the rhs vector for the implied transformation
 | ||||
|           in order to be able to find the new RHS non-zero pattern */ | ||||
|         for(i = 1; i <= lp->rows; i++) | ||||
|            rhs[i] -= wx * eta[i]; | ||||
|         rhs[rx] = wx; | ||||
| 
 | ||||
|         /* Do the exchange */ | ||||
|         set_basisvar(lp, rx, lp->rows+cx); | ||||
|         removeLink(rowLL, rx); | ||||
|       } | ||||
|       removeLink(colLL, cx); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     /* Clean up */ | ||||
| FinishLD: | ||||
|     FREE(merit); | ||||
|     FREE(rhs); | ||||
|     freeLink(&rowLL); | ||||
|     freeLink(&colLL); | ||||
| 
 | ||||
|   } | ||||
|   return( ok ); | ||||
| } | ||||
| 
 | ||||
| #if 0 | ||||
| MYBOOL __WINAPI guess_basis(lprec *lp, REAL *guessvector, int *basisvector) | ||||
| { | ||||
|   MYBOOL status = FALSE; | ||||
|   REAL   *values = NULL, *violation = NULL, | ||||
|          *value, error, upB, loB, sortorder = 1.0; | ||||
|   int    i, n, *rownr, *colnr; | ||||
|   MATrec *mat = lp->matA; | ||||
| 
 | ||||
|   if(!mat_validate(lp->matA)) | ||||
|     return( status ); | ||||
| 
 | ||||
|   /* Create helper arrays */ | ||||
|   if(!allocREAL(lp, &values, lp->sum+1, TRUE) || | ||||
|      !allocREAL(lp, &violation, lp->sum+1, TRUE)) | ||||
|     goto Finish; | ||||
| 
 | ||||
|   /* Compute values of slack variables for given guess vector */ | ||||
|   i = 0; | ||||
|   n = get_nonzeros(lp); | ||||
|   rownr = &COL_MAT_ROWNR(i); | ||||
|   colnr = &COL_MAT_COLNR(i); | ||||
|   value = &COL_MAT_VALUE(i); | ||||
|   for(; i < n; i++, rownr += matRowColStep, colnr += matRowColStep, value += matValueStep) | ||||
|     values[*rownr] += unscaled_mat(lp, my_chsign(is_chsign(lp, *rownr), *value), *rownr, *colnr) * | ||||
|                       guessvector[*colnr]; | ||||
|   MEMMOVE(values+lp->rows+1, guessvector+1, lp->columns); | ||||
| 
 | ||||
|   /* Initialize constraint bound violation measures */ | ||||
|   for(i = 1; i <= lp->rows; i++) { | ||||
|     upB = get_rh_upper(lp, i); | ||||
|     loB = get_rh_lower(lp, i); | ||||
|     error = values[i] - upB; | ||||
|     if(error > lp->epsprimal) | ||||
|       violation[i] = sortorder*error; | ||||
|     else { | ||||
|       error = loB - values[i]; | ||||
|       if(error > lp->epsprimal) | ||||
|         violation[i] = sortorder*error; | ||||
|       else if(is_infinite(lp, loB) && is_infinite(lp, upB)) | ||||
|         ; | ||||
|       else if(is_infinite(lp, upB)) | ||||
|         violation[i] = sortorder*(loB - values[i]); | ||||
|       else if(is_infinite(lp, loB)) | ||||
|         violation[i] = sortorder*(values[i] - upB); | ||||
|       else | ||||
|         violation[i] = - sortorder*MAX(upB - values[i], values[i] - loB); | ||||
|     } | ||||
|     basisvector[i] = i; | ||||
|   } | ||||
| 
 | ||||
|   /* Initialize user variable bound violation measures */ | ||||
|   for(i = 1; i <= lp->columns; i++) { | ||||
|     n = lp->rows+i; | ||||
|     upB = get_upbo(lp, i); | ||||
|     loB = get_lowbo(lp, i); | ||||
|     error = guessvector[i] - upB; | ||||
|     if(error > lp->epsprimal) | ||||
|       violation[n] = sortorder*error; | ||||
|     else { | ||||
|       error = loB - values[n]; | ||||
|       if(error > lp->epsprimal) | ||||
|         violation[n] = sortorder*error; | ||||
|       else if(is_infinite(lp, loB) && is_infinite(lp, upB)) | ||||
|         ; | ||||
|       else if(is_infinite(lp, upB)) | ||||
|         violation[n] = sortorder*(loB - values[n]); | ||||
|       else if(is_infinite(lp, loB)) | ||||
|         violation[n] = sortorder*(values[n] - upB); | ||||
|       else | ||||
|         violation[n] = - sortorder*MAX(upB - values[n], values[n] - loB); | ||||
|     } | ||||
|     basisvector[n] = n; | ||||
|   } | ||||
| 
 | ||||
|   /* Sort decending by violation; this means that variables with
 | ||||
|      the largest violations will be designated as basic */ | ||||
|   sortByREAL(basisvector, violation, lp->sum, 1, FALSE); | ||||
| 
 | ||||
|   /* Adjust the non-basic indeces for the (proximal) bound state */ | ||||
|   error = lp->epsprimal; | ||||
|   for(i = lp->rows+1, rownr = basisvector+i; i <= lp->sum; i++, rownr++) { | ||||
|     if(*rownr <= lp->rows) { | ||||
|       if(values[*rownr] <= get_rh_lower(lp, *rownr)+error) | ||||
|         *rownr = -(*rownr); | ||||
|     } | ||||
|     else | ||||
|       if(values[i] <= get_lowbo(lp, (*rownr)-lp->rows)+error) | ||||
|         *rownr = -(*rownr); | ||||
|   } | ||||
| 
 | ||||
|   /* Clean up and return status */ | ||||
|   status = (MYBOOL) (violation[1] == 0); | ||||
| Finish: | ||||
|   FREE(values); | ||||
|   FREE(violation); | ||||
| 
 | ||||
| 
 | ||||
|   return( status ); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #if 0 | ||||
| MYBOOL __WINAPI guess_basis(lprec *lp, REAL *guessvector, int *basisvector) | ||||
| { | ||||
|   MYBOOL *isnz, status = FALSE; | ||||
|   REAL   *values = NULL, *violation = NULL, | ||||
|          eps = lp->epsprimal, | ||||
|          *value, error, upB, loB, sortorder = 1.0; | ||||
|   int    i, j, n, *rownr, *colnr, *slkpos, | ||||
|          nrows = lp->rows, ncols = lp->columns; | ||||
|   MATrec *mat = lp->matA; | ||||
| 
 | ||||
|   if(!mat_validate(mat)) | ||||
|     return( status ); | ||||
| 
 | ||||
|   /* Create helper arrays */ | ||||
|   if(!allocREAL(lp, &values, lp->sum+1, TRUE) || | ||||
|      !allocREAL(lp, &violation, lp->sum+1, TRUE)) | ||||
|     goto Finish; | ||||
| 
 | ||||
|   /* Compute values of slack variables for given guess vector */ | ||||
|   i = 0; | ||||
|   n = get_nonzeros(lp); | ||||
|   rownr = &COL_MAT_ROWNR(i); | ||||
|   colnr = &COL_MAT_COLNR(i); | ||||
|   value = &COL_MAT_VALUE(i); | ||||
|   for(; i < n; i++, rownr += matRowColStep, colnr += matRowColStep, value += matValueStep) | ||||
|     values[*rownr] += unscaled_mat(lp, my_chsign(is_chsign(lp, *rownr), *value), *rownr, *colnr) * | ||||
|                       guessvector[*colnr]; | ||||
|   MEMMOVE(values+nrows+1, guessvector+1, ncols); | ||||
| 
 | ||||
|   /* Initialize constraint bound violation measures (expressed as positive values) */ | ||||
|   for(i = 1; i <= nrows; i++) { | ||||
|     upB = get_rh_upper(lp, i); | ||||
|     loB = get_rh_lower(lp, i); | ||||
|     error = values[i] - upB; | ||||
|     if(error > eps) | ||||
|       violation[i] = sortorder*error; | ||||
|     else { | ||||
|       error = loB - values[i]; | ||||
|       if(error > eps) | ||||
|         violation[i] = sortorder*error; | ||||
|       else if(my_infinite(lp, loB) && my_infinite(lp, upB)) | ||||
|         ; | ||||
|       else if(my_infinite(lp, upB)) | ||||
|         violation[i] = sortorder*(loB - values[i]); | ||||
|       else if(my_infinite(lp, loB)) | ||||
|         violation[i] = sortorder*(values[i] - upB); | ||||
|       else | ||||
|         violation[i] = -sortorder*MAX(upB - values[i], values[i] - loB); | ||||
|     } | ||||
|     basisvector[i] = i; | ||||
|   } | ||||
| 
 | ||||
|   /* Initialize user variable bound violation measures (expressed as positive values) */ | ||||
|   for(i = 1; i <= ncols; i++) { | ||||
|     n = nrows+i; | ||||
|     upB = get_upbo(lp, i); | ||||
|     loB = get_lowbo(lp, i); | ||||
|     error = guessvector[i] - upB; | ||||
|     if(error > eps) | ||||
|       violation[n] = sortorder*error; | ||||
|     else { | ||||
|       error = loB - values[n]; | ||||
|       if(error > eps) | ||||
|         violation[n] = sortorder*error; | ||||
|       else if(my_infinite(lp, loB) && my_infinite(lp, upB)) | ||||
|         ; | ||||
|       else if(my_infinite(lp, upB)) | ||||
|         violation[n] = sortorder*(loB - values[n]); | ||||
|       else if(my_infinite(lp, loB)) | ||||
|         violation[n] = sortorder*(values[n] - upB); | ||||
|       else | ||||
|         violation[n] = -sortorder*MAX(upB - values[n], values[n] - loB); | ||||
|     } | ||||
|     basisvector[n] = n; | ||||
|   } | ||||
| 
 | ||||
|   /* Sort decending by violation; this means that variables with
 | ||||
|      the largest violations will be designated as basic */ | ||||
|   sortByREAL(basisvector, violation, lp->sum, 1, FALSE); | ||||
|   error = violation[1]; | ||||
| 
 | ||||
|   /* Adjust the non-basic indeces for the (proximal) bound state */ | ||||
|   for(i = nrows+1, rownr = basisvector+i; i <= lp->sum; i++, rownr++) { | ||||
|     if(*rownr <= nrows) { | ||||
|       if(values[*rownr] <= get_rh_lower(lp, *rownr)+eps) | ||||
|         *rownr = -(*rownr); | ||||
|     } | ||||
|     else | ||||
|       if(values[i] <= get_lowbo(lp, (*rownr)-nrows)+eps) | ||||
|         *rownr = -(*rownr); | ||||
|   } | ||||
| 
 | ||||
| #if 1 | ||||
|   /* Let us check for obvious row singularities and try to fix these;
 | ||||
|      First assemble necessary basis statistics... */ | ||||
|   isnz = (MYBOOL *) values; | ||||
|   MEMCLEAR(isnz, nrows+1); | ||||
|   slkpos = (int *) violation; | ||||
|   MEMCLEAR(slkpos, nrows+1); | ||||
|   for(i = 1; i <= nrows; i++) { | ||||
|     j = abs(basisvector[i]); | ||||
|     if(j <= nrows) { | ||||
|       isnz[j] = TRUE; | ||||
|       slkpos[j] = i; | ||||
|     } | ||||
|     else { | ||||
|       j-= nrows; | ||||
|       j = mat->col_end[j-1]; | ||||
|       isnz[COL_MAT_ROWNR(j)] = TRUE; | ||||
|       /*isnz[COL_MAT_ROWNR(j+1)] = TRUE;*/ | ||||
|     } | ||||
|   } | ||||
|   for(; i <= lp->sum; i++) { | ||||
|     j = abs(basisvector[i]); | ||||
|     if(j <= nrows) | ||||
|       slkpos[j] = i; | ||||
|   } | ||||
| 
 | ||||
|   /* ...then set the corresponding slacks basic for row rank deficient positions */ | ||||
|   for(j = 1; j <= nrows; j++) { | ||||
| #ifdef Paranoia | ||||
|     if(slkpos[j] == 0) | ||||
|       report(lp, SEVERE, "guess_basis: Internal error"); | ||||
| #endif | ||||
|     if(!isnz[j]) { | ||||
|       isnz[j] = TRUE; | ||||
|       i = slkpos[j]; | ||||
|       swapINT(&basisvector[i], &basisvector[j]); | ||||
|       basisvector[j] = abs(basisvector[j]); | ||||
|     } | ||||
|   } | ||||
| #endif | ||||
| 
 | ||||
|   /* Clean up and return status */ | ||||
|   status = (MYBOOL) (error <= eps); | ||||
| Finish: | ||||
|   FREE(values); | ||||
|   FREE(violation); | ||||
| 
 | ||||
|   return( status ); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| MYBOOL __WINAPI guess_basis(lprec *lp, REAL *guessvector, int *basisvector) | ||||
| { | ||||
|   MYBOOL *isnz, status = FALSE; | ||||
|   REAL   *values = NULL, *violation = NULL, | ||||
|          eps = lp->epsprimal, | ||||
|          *value, error, upB, loB, sortorder = 1.0; | ||||
|   int    i, j, jj, n, *rownr, *colnr, *slkpos, | ||||
|          nrows = lp->rows, ncols = lp->columns; | ||||
|   MATrec *mat = lp->matA; | ||||
| 
 | ||||
|   if(!mat_validate(mat)) | ||||
|     return( status ); | ||||
| 
 | ||||
|   /* Create helper arrays */ | ||||
|   if(!allocREAL(lp, &values, lp->sum+1, TRUE) || | ||||
|      !allocREAL(lp, &violation, lp->sum+1, TRUE)) | ||||
|     goto Finish; | ||||
| 
 | ||||
|   /* Compute values of slack variables for given guess vector */ | ||||
|   i = 0; | ||||
|   n = get_nonzeros(lp); | ||||
|   rownr = &COL_MAT_ROWNR(i); | ||||
|   colnr = &COL_MAT_COLNR(i); | ||||
|   value = &COL_MAT_VALUE(i); | ||||
|   for(; i < n; i++, rownr += matRowColStep, colnr += matRowColStep, value += matValueStep) | ||||
|     values[*rownr] += unscaled_mat(lp, my_chsign(is_chsign(lp, *rownr), *value), *rownr, *colnr) * | ||||
|                       guessvector[*colnr]; | ||||
|   MEMMOVE(values+nrows+1, guessvector+1, ncols); | ||||
| 
 | ||||
|   /* Initialize constraint bound violation measures (expressed as positive values) */ | ||||
|   for(i = 1; i <= nrows; i++) { | ||||
|     upB = get_rh_upper(lp, i); | ||||
|     loB = get_rh_lower(lp, i); | ||||
|     error = values[i] - upB; | ||||
|     if(error > -eps) | ||||
|       violation[i] = sortorder*MAX(0,error); | ||||
|     else { | ||||
|       error = loB - values[i]; | ||||
|       if(error > -eps) | ||||
|         violation[i] = sortorder*MAX(0,error); | ||||
|       else if(my_infinite(lp, loB) && my_infinite(lp, upB)) | ||||
|         ; | ||||
|       else if(my_infinite(lp, upB)) | ||||
|         violation[i] = sortorder*(loB - values[i]); | ||||
|       else if(my_infinite(lp, loB)) | ||||
|         violation[i] = sortorder*(values[i] - upB); | ||||
|       else | ||||
|         violation[i] = -sortorder*MAX(upB - values[i], values[i] - loB); | ||||
|     } | ||||
|     basisvector[i] = i; | ||||
|   } | ||||
| 
 | ||||
|   /* Initialize user variable bound violation measures (expressed as positive values) */ | ||||
|   for(i = 1; i <= ncols; i++) { | ||||
|     n = nrows+i; | ||||
|     upB = get_upbo(lp, i); | ||||
|     loB = get_lowbo(lp, i); | ||||
|     error = guessvector[i] - upB; | ||||
|     if(error > -eps) | ||||
|       violation[n] = sortorder*MAX(0,error); | ||||
|     else { | ||||
|       error = loB - values[n]; | ||||
|       if(error > -eps) | ||||
|         violation[n] = sortorder*MAX(0,error); | ||||
|       else if(my_infinite(lp, loB) && my_infinite(lp, upB)) | ||||
|         ; | ||||
|       else if(my_infinite(lp, upB)) | ||||
|         violation[n] = sortorder*(loB - values[n]); | ||||
|       else if(my_infinite(lp, loB)) | ||||
|         violation[n] = sortorder*(values[n] - upB); | ||||
|       else | ||||
|         violation[n] = -sortorder*MAX(upB - values[n], values[n] - loB); | ||||
|     } | ||||
|     basisvector[n] = n; | ||||
|   } | ||||
| 
 | ||||
|   /* Sort decending by violation; this means that variables with
 | ||||
|      the largest violations will be designated as basic */ | ||||
|   sortByREAL(basisvector, violation, lp->sum, 1, FALSE); | ||||
|   error = violation[1]; | ||||
| 
 | ||||
|   /* Adjust the non-basic indeces for the (proximal) bound state */ | ||||
|   for(i = nrows+1, rownr = basisvector+i; i <= lp->sum; i++, rownr++) { | ||||
|     if(*rownr <= nrows) { | ||||
|       values[*rownr] -= lp->orig_rhs[*rownr]; | ||||
|       if(values[*rownr] <= eps) | ||||
|         *rownr = -(*rownr); | ||||
|     } | ||||
|     else | ||||
|       if(values[i] <= get_lowbo(lp, (*rownr)-nrows)+eps) | ||||
|         *rownr = -(*rownr); | ||||
|   } | ||||
| 
 | ||||
|   /* Let us check for obvious row singularities and try to fix these;
 | ||||
|      First assemble necessary basis statistics... */ | ||||
|   isnz = (MYBOOL *) values; | ||||
|   MEMCLEAR(isnz, nrows+1); | ||||
|   slkpos = (int *) violation; | ||||
|   MEMCLEAR(slkpos, nrows+1); | ||||
|   for(i = 1; i <= nrows; i++) { | ||||
|     j = abs(basisvector[i]); | ||||
|     if(j <= nrows) { | ||||
|       isnz[j] = TRUE; | ||||
|       slkpos[j] = i; | ||||
|     } | ||||
|     else { | ||||
|       j-= nrows; | ||||
|       jj = mat->col_end[j-1]; | ||||
|       isnz[COL_MAT_ROWNR(jj)] = TRUE; | ||||
| /*      if(++jj < mat->col_end[j])
 | ||||
|         isnz[COL_MAT_ROWNR(jj)] = TRUE; */ | ||||
|     } | ||||
|   } | ||||
|   for(; i <= lp->sum; i++) { | ||||
|     j = abs(basisvector[i]); | ||||
|     if(j <= nrows) | ||||
|       slkpos[j] = i; | ||||
|   } | ||||
| 
 | ||||
|   /* ...then set the corresponding slacks basic for row rank deficient positions */ | ||||
|   for(j = 1; j <= nrows; j++) { | ||||
| #ifdef Paranoia | ||||
|     if(slkpos[j] == 0) | ||||
|       report(lp, SEVERE, "guess_basis: Internal error"); | ||||
| #endif | ||||
|     if(!isnz[j]) { | ||||
|       isnz[j] = TRUE; | ||||
|       i = slkpos[j]; | ||||
|       swapINT(&basisvector[i], &basisvector[j]); | ||||
|       basisvector[j] = abs(basisvector[j]); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /* Lastly normalize all basic variables to be coded as lower-bounded */ | ||||
|   for(i = 1; i <= nrows; i++) | ||||
|     basisvector[i] = -abs(basisvector[i]); | ||||
| 
 | ||||
|   /* Clean up and return status */ | ||||
|   status = (MYBOOL) (error <= eps); | ||||
| Finish: | ||||
|   FREE(values); | ||||
|   FREE(violation); | ||||
| 
 | ||||
|   return( status ); | ||||
| } | ||||
|  | @ -1,27 +0,0 @@ | |||
| 
 | ||||
| #ifndef HEADER_lp_crash | ||||
| #define HEADER_lp_crash | ||||
| 
 | ||||
| 
 | ||||
| #include "lp_types.h" | ||||
| 
 | ||||
| #define CRASH_SIMPLESCALE       /* Specify if we should use a simple absolute scaling threshold */ | ||||
| 
 | ||||
| #define CRASH_THRESHOLD  0.167 | ||||
| #define CRASH_SPACER        10 | ||||
| #define CRASH_WEIGHT     0.500 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| __EXTERN_C { | ||||
| #endif | ||||
| 
 | ||||
| STATIC MYBOOL crash_basis(lprec *lp); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* HEADER_lp_crash */ | ||||
| 
 | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -1,5 +0,0 @@ | |||
| #ifdef FORTIFY | ||||
| 
 | ||||
| #include "fortify.h" | ||||
| 
 | ||||
| #endif | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -1,257 +0,0 @@ | |||
| #ifndef HEADER_lp_matrix | ||||
| #define HEADER_lp_matrix | ||||
| 
 | ||||
| #include "lp_types.h" | ||||
| #include "lp_utils.h" | ||||
| 
 | ||||
| 
 | ||||
| /* Sparse matrix element (ordered columnwise) */ | ||||
| typedef struct _MATitem | ||||
| { | ||||
|   int  rownr; | ||||
|   int  colnr; | ||||
|   REAL value; | ||||
| } MATitem; | ||||
| 
 | ||||
| /* Constants for matrix product rounding options */ | ||||
| #define MAT_ROUNDNONE             0 | ||||
| #define MAT_ROUNDABS              1 | ||||
| #define MAT_ROUNDREL              2 | ||||
| #define MAT_ROUNDABSREL          (MAT_ROUNDABS + MAT_ROUNDREL) | ||||
| #define MAT_ROUNDRC               4 | ||||
| #define MAT_ROUNDRCMIN            1.0 /* lp->epspivot */ | ||||
| #if 1 | ||||
|  #define MAT_ROUNDDEFAULT         MAT_ROUNDREL  /* Typically increases performance */ | ||||
| #else | ||||
|  #define MAT_ROUNDDEFAULT         MAT_ROUNDABS  /* Probably gives more precision */ | ||||
| #endif | ||||
| 
 | ||||
| /* Compiler option development features */ | ||||
| /*#define DebugInv*/               /* Report array values at factorization/inversion */ | ||||
| #define NoLoopUnroll              /* Do not do loop unrolling */ | ||||
| #define DirectArrayOF             /* Reference lp->obj[] array instead of function call */ | ||||
| 
 | ||||
| 
 | ||||
| /* Matrix column access macros to be able to easily change storage model */ | ||||
| #define CAM_Record                0 | ||||
| #define CAM_Vector                1 | ||||
| #if 0 | ||||
|  #define MatrixColAccess           CAM_Record | ||||
| #else | ||||
|  #define MatrixColAccess           CAM_Vector | ||||
| #endif | ||||
| 
 | ||||
| #if MatrixColAccess==CAM_Record | ||||
| #define SET_MAT_ijA(item,i,j,A)   mat->col_mat[item].rownr = i; \ | ||||
|                                   mat->col_mat[item].colnr = j; \ | ||||
|                                   mat->col_mat[item].value = A | ||||
| #define COL_MAT_COLNR(item)       (mat->col_mat[item].colnr) | ||||
| #define COL_MAT_ROWNR(item)       (mat->col_mat[item].rownr) | ||||
| #define COL_MAT_VALUE(item)       (mat->col_mat[item].value) | ||||
| #define COL_MAT_COPY(left,right)  mat->col_mat[left] = mat->col_mat[right] | ||||
| #define COL_MAT_MOVE(to,from,rec) MEMMOVE(&(mat->col_mat[to]),&(mat->col_mat[from]),rec) | ||||
| #define COL_MAT2_COLNR(item)      (mat2->col_mat[item].colnr) | ||||
| #define COL_MAT2_ROWNR(item)      (mat2->col_mat[item].rownr) | ||||
| #define COL_MAT2_VALUE(item)      (mat2->col_mat[item].value) | ||||
| #define matRowColStep             (sizeof(MATitem)/sizeof(int)) | ||||
| #define matValueStep              (sizeof(MATitem)/sizeof(REAL)) | ||||
| 
 | ||||
| #else /* if MatrixColAccess==CAM_Vector */ | ||||
| #define SET_MAT_ijA(item,i,j,A)   mat->col_mat_rownr[item] = i; \ | ||||
|                                   mat->col_mat_colnr[item] = j; \ | ||||
|                                   mat->col_mat_value[item] = A | ||||
| #define COL_MAT_COLNR(item)       (mat->col_mat_colnr[item]) | ||||
| #define COL_MAT_ROWNR(item)       (mat->col_mat_rownr[item]) | ||||
| #define COL_MAT_VALUE(item)       (mat->col_mat_value[item]) | ||||
| #define COL_MAT_COPY(left,right)  COL_MAT_COLNR(left) = COL_MAT_COLNR(right); \ | ||||
|                                   COL_MAT_ROWNR(left) = COL_MAT_ROWNR(right); \ | ||||
|                                   COL_MAT_VALUE(left) = COL_MAT_VALUE(right) | ||||
| #define COL_MAT_MOVE(to,from,rec) MEMMOVE(&COL_MAT_COLNR(to),&COL_MAT_COLNR(from),rec); \ | ||||
|                                   MEMMOVE(&COL_MAT_ROWNR(to),&COL_MAT_ROWNR(from),rec); \ | ||||
|                                   MEMMOVE(&COL_MAT_VALUE(to),&COL_MAT_VALUE(from),rec) | ||||
| #define COL_MAT2_COLNR(item)      (mat2->col_mat_colnr[item]) | ||||
| #define COL_MAT2_ROWNR(item)      (mat2->col_mat_rownr[item]) | ||||
| #define COL_MAT2_VALUE(item)      (mat2->col_mat_value[item]) | ||||
| #define matRowColStep             1 | ||||
| #define matValueStep              1 | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /* Matrix row access macros to be able to easily change storage model */ | ||||
| #define RAM_Index                 0 | ||||
| #define RAM_FullCopy              1 | ||||
| #define MatrixRowAccess           RAM_Index | ||||
| 
 | ||||
| #if MatrixRowAccess==RAM_Index | ||||
| #define ROW_MAT_COLNR(item)       COL_MAT_COLNR(mat->row_mat[item]) | ||||
| #define ROW_MAT_ROWNR(item)       COL_MAT_ROWNR(mat->row_mat[item]) | ||||
| #define ROW_MAT_VALUE(item)       COL_MAT_VALUE(mat->row_mat[item]) | ||||
| 
 | ||||
| #elif MatrixColAccess==CAM_Record | ||||
| #define ROW_MAT_COLNR(item)       (mat->row_mat[item].colnr) | ||||
| #define ROW_MAT_ROWNR(item)       (mat->row_mat[item].rownr) | ||||
| #define ROW_MAT_VALUE(item)       (mat->row_mat[item].value) | ||||
| 
 | ||||
| #else /* if MatrixColAccess==CAM_Vector */ | ||||
| #define ROW_MAT_COLNR(item)       (mat->row_mat_colnr[item]) | ||||
| #define ROW_MAT_ROWNR(item)       (mat->row_mat_rownr[item]) | ||||
| #define ROW_MAT_VALUE(item)       (mat->row_mat_value[item]) | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| typedef struct _MATrec | ||||
| { | ||||
|   /* Owner reference */ | ||||
|   lprec     *lp; | ||||
| 
 | ||||
|   /* Active dimensions */ | ||||
|   int       rows; | ||||
|   int       columns; | ||||
| 
 | ||||
|   /* Allocated memory */ | ||||
|   int       rows_alloc; | ||||
|   int       columns_alloc; | ||||
|   int       mat_alloc;          /* The allocated size for matrix sized structures */ | ||||
| 
 | ||||
|   /* Sparse problem matrix storage */ | ||||
| #if MatrixColAccess==CAM_Record   | ||||
|   MATitem   *col_mat;           /* mat_alloc : The sparse data storage */ | ||||
| #else /*MatrixColAccess==CAM_Vector*/ | ||||
|   int       *col_mat_colnr; | ||||
|   int       *col_mat_rownr; | ||||
|   REAL      *col_mat_value; | ||||
| #endif   | ||||
|   int       *col_end;           /* columns_alloc+1 : col_end[i] is the index of the
 | ||||
|                                    first element after column i; column[i] is stored | ||||
|                                    in elements col_end[i-1] to col_end[i]-1 */ | ||||
|   int       *col_tag;           /* user-definable tag associated with each column */ | ||||
| 
 | ||||
| #if MatrixRowAccess==RAM_Index | ||||
|   int       *row_mat;           /* mat_alloc : From index 0, row_mat contains the
 | ||||
|                                    row-ordered index of the elements of col_mat */ | ||||
| #elif MatrixColAccess==CAM_Record | ||||
|   MATitem   *row_mat;           /* mat_alloc : From index 0, row_mat contains the
 | ||||
|                                    row-ordered copy of the elements in col_mat */ | ||||
| #else /*if MatrixColAccess==CAM_Vector*/ | ||||
|   int       *row_mat_colnr; | ||||
|   int       *row_mat_rownr; | ||||
|   REAL      *row_mat_value; | ||||
| #endif | ||||
|   int       *row_end;           /* rows_alloc+1 : row_end[i] is the index of the
 | ||||
|                                    first element in row_mat after row i */ | ||||
|   int       *row_tag;           /* user-definable tag associated with each row */ | ||||
| 
 | ||||
|   REAL      *colmax;            /* Array of maximum values of each column */ | ||||
|   REAL      *rowmax;            /* Array of maximum values of each row */ | ||||
| 
 | ||||
|   REAL      epsvalue;           /* Zero element rejection threshold */ | ||||
|   REAL      infnorm;            /* The largest absolute value in the matrix */ | ||||
|   REAL      dynrange; | ||||
|   MYBOOL    row_end_valid;      /* TRUE if row_end & row_mat are valid */ | ||||
|   MYBOOL    is_roworder;        /* TRUE if the current (temporary) matrix order is row-wise */ | ||||
| 
 | ||||
| } MATrec; | ||||
| 
 | ||||
| typedef struct _DeltaVrec | ||||
| { | ||||
|   lprec     *lp; | ||||
|   int       activelevel; | ||||
|   MATrec    *tracker; | ||||
| } DeltaVrec; | ||||
| 
 | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| __EXTERN_C { | ||||
| #endif | ||||
| 
 | ||||
| /* Sparse matrix routines */ | ||||
| STATIC MATrec *mat_create(lprec *lp, int rows, int columns, REAL epsvalue); | ||||
| STATIC MYBOOL mat_memopt(MATrec *mat, int rowextra, int colextra, int nzextra); | ||||
| STATIC void mat_free(MATrec **matrix); | ||||
| STATIC MYBOOL inc_matrow_space(MATrec *mat, int deltarows); | ||||
| STATIC int mat_mapreplace(MATrec *mat, LLrec *rowmap, LLrec *colmap, MATrec *insmat); | ||||
| STATIC int mat_matinsert(MATrec *mat, MATrec *insmat); | ||||
| STATIC int mat_zerocompact(MATrec *mat); | ||||
| STATIC int mat_rowcompact(MATrec *mat, MYBOOL dozeros); | ||||
| STATIC int mat_colcompact(MATrec *mat, int prev_rows, int prev_cols); | ||||
| STATIC MYBOOL inc_matcol_space(MATrec *mat, int deltacols); | ||||
| STATIC MYBOOL inc_mat_space(MATrec *mat, int mindelta); | ||||
| STATIC int mat_shiftrows(MATrec *mat, int *bbase, int delta, LLrec *varmap); | ||||
| STATIC int mat_shiftcols(MATrec *mat, int *bbase, int delta, LLrec *varmap); | ||||
| STATIC MATrec *mat_extractmat(MATrec *mat, LLrec *rowmap, LLrec *colmap, MYBOOL negated); | ||||
| STATIC int mat_appendrow(MATrec *mat, int count, REAL *row, int *colno, REAL mult, MYBOOL checkrowmode); | ||||
| STATIC int mat_appendcol(MATrec *mat, int count, REAL *column, int *rowno, REAL mult, MYBOOL checkrowmode); | ||||
| MYBOOL mat_get_data(lprec *lp, int matindex, MYBOOL isrow, int **rownr, int **colnr, REAL **value); | ||||
| MYBOOL mat_set_rowmap(MATrec *mat, int row_mat_index, int rownr, int colnr, int col_mat_index); | ||||
| STATIC MYBOOL mat_indexrange(MATrec *mat, int index, MYBOOL isrow, int *startpos, int *endpos); | ||||
| STATIC MYBOOL mat_validate(MATrec *mat); | ||||
| STATIC MYBOOL mat_equalRows(MATrec *mat, int baserow, int comprow); | ||||
| STATIC int mat_findelm(MATrec *mat, int row, int column); | ||||
| STATIC int mat_findins(MATrec *mat, int row, int column, int *insertpos, MYBOOL validate); | ||||
| STATIC void mat_multcol(MATrec *mat, int col_nr, REAL mult, MYBOOL DoObj); | ||||
| STATIC REAL mat_getitem(MATrec *mat, int row, int column); | ||||
| STATIC MYBOOL mat_setitem(MATrec *mat, int row, int column, REAL value); | ||||
| STATIC MYBOOL mat_additem(MATrec *mat, int row, int column, REAL delta); | ||||
| STATIC MYBOOL mat_setvalue(MATrec *mat, int Row, int Column, REAL Value, MYBOOL doscale); | ||||
| STATIC int mat_nonzeros(MATrec *mat); | ||||
| STATIC int mat_collength(MATrec *mat, int colnr); | ||||
| STATIC int mat_rowlength(MATrec *mat, int rownr); | ||||
| STATIC void mat_multrow(MATrec *mat, int row_nr, REAL mult); | ||||
| STATIC void mat_multadd(MATrec *mat, REAL *lhsvector, int varnr, REAL mult); | ||||
| STATIC MYBOOL mat_setrow(MATrec *mat, int rowno, int count, REAL *row, int *colno, MYBOOL doscale, MYBOOL checkrowmode); | ||||
| STATIC MYBOOL mat_setcol(MATrec *mat, int colno, int count, REAL *column, int *rowno, MYBOOL doscale, MYBOOL checkrowmode); | ||||
| STATIC MYBOOL mat_mergemat(MATrec *target, MATrec *source, MYBOOL usecolmap); | ||||
| STATIC int mat_checkcounts(MATrec *mat, int *rownum, int *colnum, MYBOOL freeonexit); | ||||
| STATIC int mat_expandcolumn(MATrec *mat, int colnr, REAL *column, int *nzlist, MYBOOL signedA); | ||||
| STATIC MYBOOL mat_computemax(MATrec *mat); | ||||
| STATIC MYBOOL mat_transpose(MATrec *mat); | ||||
| 
 | ||||
| /* Refactorization and recomputation routine */ | ||||
| MYBOOL __WINAPI invert(lprec *lp, MYBOOL shiftbounds, MYBOOL final); | ||||
| 
 | ||||
| /* Vector compression and expansion routines */ | ||||
| STATIC MYBOOL vec_compress(REAL *densevector, int startpos, int endpos, REAL epsilon, REAL *nzvector, int *nzindex); | ||||
| STATIC MYBOOL vec_expand(REAL *nzvector, int *nzindex, REAL *densevector, int startpos, int endpos); | ||||
| 
 | ||||
| /* Sparse matrix products */ | ||||
| STATIC MYBOOL get_colIndexA(lprec *lp, int varset, int *colindex, MYBOOL append); | ||||
| STATIC int prod_Ax(lprec *lp, int *coltarget, REAL *input, int *nzinput, REAL roundzero, REAL ofscalar, REAL *output, int *nzoutput, int roundmode); | ||||
| STATIC int prod_xA(lprec *lp, int *coltarget, REAL *input, int *nzinput, REAL roundzero, REAL ofscalar, REAL *output, int *nzoutput, int roundmode); | ||||
| STATIC MYBOOL prod_xA2(lprec *lp, int *coltarget, REAL *prow, REAL proundzero, int *pnzprow, | ||||
|                                                   REAL *drow, REAL droundzero, int *dnzdrow, REAL ofscalar, int roundmode); | ||||
| 
 | ||||
| /* Equation solution */ | ||||
| STATIC MYBOOL fimprove(lprec *lp, REAL *pcol, int *nzidx, REAL roundzero); | ||||
| STATIC void ftran(lprec *lp, REAL *rhsvector, int *nzidx, REAL roundzero); | ||||
| STATIC MYBOOL bimprove(lprec *lp, REAL *rhsvector, int *nzidx, REAL roundzero); | ||||
| STATIC void btran(lprec *lp, REAL *rhsvector, int *nzidx, REAL roundzero); | ||||
| 
 | ||||
| /* Combined equation solution and matrix product for simplex operations */ | ||||
| STATIC MYBOOL fsolve(lprec *lp, int varin, REAL *pcol, int *nzidx, REAL roundzero, REAL ofscalar, MYBOOL prepareupdate); | ||||
| STATIC MYBOOL bsolve(lprec *lp, int row_nr, REAL *rhsvector, int *nzidx, REAL roundzero, REAL ofscalar); | ||||
| STATIC void bsolve_xA2(lprec *lp, int* coltarget,  | ||||
|                                   int row_nr1, REAL *vector1, REAL roundzero1, int *nzvector1, | ||||
|                                   int row_nr2, REAL *vector2, REAL roundzero2, int *nzvector2, int roundmode); | ||||
| 
 | ||||
| /* Change-tracking routines (primarily for B&B and presolve) */ | ||||
| STATIC DeltaVrec *createUndoLadder(lprec *lp, int levelitems, int maxlevels); | ||||
| STATIC int incrementUndoLadder(DeltaVrec *DV); | ||||
| STATIC MYBOOL modifyUndoLadder(DeltaVrec *DV, int itemno, REAL target[], REAL newvalue); | ||||
| STATIC int countsUndoLadder(DeltaVrec *DV); | ||||
| STATIC int restoreUndoLadder(DeltaVrec *DV, REAL target[]); | ||||
| STATIC int decrementUndoLadder(DeltaVrec *DV); | ||||
| STATIC MYBOOL freeUndoLadder(DeltaVrec **DV); | ||||
| 
 | ||||
| /* Specialized presolve undo functions */ | ||||
| STATIC MYBOOL appendUndoPresolve(lprec *lp, MYBOOL isprimal, REAL beta, int colnrDep); | ||||
| STATIC MYBOOL addUndoPresolve(lprec *lp, MYBOOL isprimal, int colnrElim, REAL alpha, REAL beta, int colnrDep); | ||||
| 
 | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* HEADER_lp_matrix */ | ||||
| 
 | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -1,64 +0,0 @@ | |||
| #ifndef HEADER_lp_mipbb | ||||
| #define HEADER_lp_mipbb | ||||
| 
 | ||||
| #include "lp_types.h" | ||||
| #include "lp_utils.h" | ||||
| 
 | ||||
| 
 | ||||
| /* Bounds storage for B&B routines */ | ||||
| typedef struct _BBrec | ||||
| { | ||||
|   struct    _BBrec *parent; | ||||
|   struct    _BBrec *child; | ||||
|   lprec     *lp; | ||||
|   int       varno; | ||||
|   int       vartype; | ||||
|   int       lastvarcus;            /* Count of non-int variables of the previous branch */ | ||||
|   int       lastrcf; | ||||
|   int       nodesleft; | ||||
|   int       nodessolved; | ||||
|   int       nodestatus; | ||||
|   REAL      noderesult; | ||||
|   REAL      lastsolution;          /* Optimal solution of the previous branch */ | ||||
|   REAL      sc_bound; | ||||
|   REAL      *upbo,   *lowbo; | ||||
|   REAL      UPbound, LObound; | ||||
|   int       UBtrack, LBtrack;      /* Signals that incoming bounds were changed */ | ||||
|   MYBOOL    contentmode;           /* Flag indicating if we "own" the bound vectors */ | ||||
|   MYBOOL    sc_canset; | ||||
|   MYBOOL    isSOS; | ||||
|   MYBOOL    isGUB; | ||||
|   int       *varmanaged;           /* Extended list of variables managed by this B&B level */ | ||||
|   MYBOOL    isfloor;               /* State variable indicating the active B&B bound */ | ||||
|   MYBOOL    UBzerobased;           /* State variable indicating if bounds have been rebased */ | ||||
| } BBrec; | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| STATIC BBrec *create_BB(lprec *lp, BBrec *parentBB, MYBOOL dofullcopy); | ||||
| STATIC BBrec *push_BB(lprec *lp, BBrec *parentBB, int varno, int vartype, int varcus); | ||||
| STATIC MYBOOL initbranches_BB(BBrec *BB); | ||||
| STATIC MYBOOL fillbranches_BB(BBrec *BB); | ||||
| STATIC MYBOOL nextbranch_BB(BBrec *BB); | ||||
| STATIC MYBOOL strongbranch_BB(lprec *lp, BBrec *BB, int varno, int vartype, int varcus); | ||||
| STATIC MYBOOL initcuts_BB(lprec *lp); | ||||
| STATIC int updatecuts_BB(lprec *lp); | ||||
| STATIC MYBOOL freecuts_BB(lprec *lp); | ||||
| STATIC BBrec *findself_BB(BBrec *BB); | ||||
| STATIC int solve_LP(lprec *lp, BBrec *BB); | ||||
| STATIC int rcfbound_BB(BBrec *BB, int varno, MYBOOL isINT, REAL *newbound, MYBOOL *isfeasible); | ||||
| STATIC MYBOOL findnode_BB(BBrec *BB, int *varno, int *vartype, int *varcus); | ||||
| STATIC int solve_BB(BBrec *BB); | ||||
| STATIC MYBOOL free_BB(BBrec **BB); | ||||
| STATIC BBrec *pop_BB(BBrec *BB); | ||||
| 
 | ||||
| STATIC int run_BB(lprec *lp); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
|  } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* HEADER_lp_mipbb */ | ||||
| 
 | ||||
|  | @ -1,691 +0,0 @@ | |||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <ctype.h> | ||||
| #include <errno.h> | ||||
| 
 | ||||
| #include "commonlib.h" | ||||
| #include "lp_lib.h" | ||||
| #include "lp_report.h" | ||||
| #include "ini.h" | ||||
| 
 | ||||
| typedef int (__WINAPI int_get_function)(lprec *lp); | ||||
| typedef long (__WINAPI long_get_function)(lprec *lp); | ||||
| typedef MYBOOL (__WINAPI MYBOOL_get_function)(lprec *lp); | ||||
| typedef REAL (__WINAPI REAL_get_function)(lprec *lp); | ||||
| typedef void (__WINAPI int_set_function)(lprec *lp, int value); | ||||
| typedef void (__WINAPI long_set_function)(lprec *lp, long value); | ||||
| typedef void (__WINAPI MYBOOL_set_function)(lprec *lp, MYBOOL value); | ||||
| typedef void (__WINAPI REAL_set_function)(lprec *lp, REAL value); | ||||
| 
 | ||||
| #define intfunction    1 | ||||
| #define longfunction   2 | ||||
| #define MYBOOLfunction 3 | ||||
| #define REALfunction   4 | ||||
| 
 | ||||
| #define setvalues(values, basemask) values, sizeof(values) / sizeof(*values), basemask | ||||
| #define setNULLvalues NULL, 0, 0 | ||||
| #define setvalue(value) value, #value | ||||
| #define setintfunction(get_function, set_function) get_function, set_function, intfunction | ||||
| #define setlongfunction(get_function, set_function) (int_get_function *) get_function, (int_set_function *) set_function, longfunction | ||||
| #define setMYBOOLfunction(get_function, set_function) (int_get_function *) get_function, (int_set_function *) set_function, MYBOOLfunction | ||||
| #define setREALfunction(get_function, set_function) (int_get_function *) get_function, (int_set_function *) set_function, REALfunction | ||||
| 
 | ||||
| #define WRITE_COMMENTED 0 | ||||
| #define WRITE_ACTIVE    1 | ||||
| 
 | ||||
| struct _values { | ||||
|   int value; | ||||
|   char *svalue; | ||||
| }; | ||||
| 
 | ||||
| struct _functions { | ||||
|   char *par;                                    /* name of parameter in ini file */ | ||||
|   union { | ||||
|     int_get_function *int_get_function;         /* set via setintfunction */ | ||||
|     long_get_function *long_get_function;       /* set via setlongfunction */ | ||||
|     MYBOOL_get_function *MYBOOL_get_function;   /* set via setMYBOOLfunction */ | ||||
|     REAL_get_function *REAL_get_function;       /* set via setREALfunction */ | ||||
|   } get_function; | ||||
|   union { | ||||
|     int_set_function *int_set_function;         /* set via setintfunction */ | ||||
|     long_set_function *long_set_function;       /* set via setlongfunction */ | ||||
|     MYBOOL_set_function *MYBOOL_set_function;   /* set via setMYBOOLfunction */ | ||||
|     REAL_set_function *REAL_set_function;       /* set via setREALfunction */ | ||||
|   } set_function; | ||||
|   int type;                                     /* set via set*function */ | ||||
|   struct _values *values;                       /* set via setvalues to a structure of _values */ | ||||
|   int elements;                                 /*  or via setNULLvalues if the value is shown as is */ | ||||
|   unsigned int basemask; | ||||
|   int mask;                                     /* WRITE_ACTIVE or WRITE_COMMENTED */ | ||||
| }; | ||||
| 
 | ||||
| static struct _values anti_degen[] = | ||||
| { | ||||
|   { setvalue(ANTIDEGEN_NONE) }, | ||||
|   { setvalue(ANTIDEGEN_FIXEDVARS) }, | ||||
|   { setvalue(ANTIDEGEN_COLUMNCHECK) }, | ||||
|   { setvalue(ANTIDEGEN_STALLING) }, | ||||
|   { setvalue(ANTIDEGEN_NUMFAILURE) }, | ||||
|   { setvalue(ANTIDEGEN_LOSTFEAS) }, | ||||
|   { setvalue(ANTIDEGEN_INFEASIBLE) }, | ||||
|   { setvalue(ANTIDEGEN_DYNAMIC) }, | ||||
|   { setvalue(ANTIDEGEN_DURINGBB) }, | ||||
|   { setvalue(ANTIDEGEN_RHSPERTURB) }, | ||||
|   { setvalue(ANTIDEGEN_BOUNDFLIP) }, | ||||
| }; | ||||
| 
 | ||||
| static struct _values basiscrash[] = | ||||
| { | ||||
|   { setvalue(CRASH_NONE) }, | ||||
|   /* { setvalue(CRASH_NONBASICBOUNDS) }, */ /* not yet implemented */ | ||||
|   { setvalue(CRASH_MOSTFEASIBLE) }, | ||||
|   { setvalue(CRASH_LEASTDEGENERATE) }, | ||||
| }; | ||||
| 
 | ||||
| static struct _values bb_floorfirst[] = | ||||
| { | ||||
|   { setvalue(BRANCH_CEILING) }, | ||||
|   { setvalue(BRANCH_FLOOR) }, | ||||
|   { setvalue(BRANCH_AUTOMATIC) }, | ||||
| }; | ||||
| 
 | ||||
| static struct _values bb_rule[] = | ||||
| { | ||||
|   { setvalue(NODE_FIRSTSELECT) }, | ||||
|   { setvalue(NODE_GAPSELECT) }, | ||||
|   { setvalue(NODE_RANGESELECT) }, | ||||
|   { setvalue(NODE_FRACTIONSELECT) }, | ||||
|   { setvalue(NODE_PSEUDOCOSTSELECT) }, | ||||
|   { setvalue(NODE_PSEUDONONINTSELECT) }, | ||||
|   { setvalue(NODE_PSEUDORATIOSELECT) }, | ||||
|   { setvalue(NODE_USERSELECT) }, | ||||
|   { setvalue(NODE_WEIGHTREVERSEMODE) }, | ||||
|   { setvalue(NODE_BRANCHREVERSEMODE) }, | ||||
|   { setvalue(NODE_GREEDYMODE) }, | ||||
|   { setvalue(NODE_PSEUDOCOSTMODE) }, | ||||
|   { setvalue(NODE_DEPTHFIRSTMODE) }, | ||||
|   { setvalue(NODE_RANDOMIZEMODE) }, | ||||
|   { setvalue(NODE_GUBMODE) }, | ||||
|   { setvalue(NODE_DYNAMICMODE) }, | ||||
|   { setvalue(NODE_RESTARTMODE) }, | ||||
|   { setvalue(NODE_BREADTHFIRSTMODE) }, | ||||
|   { setvalue(NODE_AUTOORDER) }, | ||||
|   { setvalue(NODE_RCOSTFIXING) }, | ||||
|   { setvalue(NODE_STRONGINIT) }, | ||||
| }; | ||||
| 
 | ||||
| static struct _values improve[] = | ||||
| { | ||||
|   { setvalue(IMPROVE_NONE) }, | ||||
|   { setvalue(IMPROVE_SOLUTION) }, | ||||
|   { setvalue(IMPROVE_DUALFEAS) }, | ||||
|   { setvalue(IMPROVE_THETAGAP) }, | ||||
|   { setvalue(IMPROVE_BBSIMPLEX) }, | ||||
| }; | ||||
| 
 | ||||
| static REAL __WINAPI get_mip_gap_abs(lprec *lp) | ||||
| { | ||||
|   return(get_mip_gap(lp, TRUE)); | ||||
| } | ||||
| 
 | ||||
| static REAL __WINAPI get_mip_gap_rel(lprec *lp) | ||||
| { | ||||
|   return(get_mip_gap(lp, FALSE)); | ||||
| } | ||||
| 
 | ||||
| static void __WINAPI set_mip_gap_abs(lprec *lp, REAL mip_gap) | ||||
| { | ||||
|   set_mip_gap(lp, TRUE, mip_gap); | ||||
| } | ||||
| 
 | ||||
| static void __WINAPI set_mip_gap_rel(lprec *lp, REAL mip_gap) | ||||
| { | ||||
|   set_mip_gap(lp, FALSE, mip_gap); | ||||
| } | ||||
| 
 | ||||
| static struct _values pivoting[] = | ||||
| { | ||||
|   { setvalue(PRICER_FIRSTINDEX) }, | ||||
|   { setvalue(PRICER_DANTZIG) }, | ||||
|   { setvalue(PRICER_DEVEX) }, | ||||
|   { setvalue(PRICER_STEEPESTEDGE) }, | ||||
|   { setvalue(PRICE_PRIMALFALLBACK) }, | ||||
|   { setvalue(PRICE_MULTIPLE) }, | ||||
|   { setvalue(PRICE_PARTIAL) }, | ||||
|   { setvalue(PRICE_ADAPTIVE) }, | ||||
|   { setvalue(PRICE_RANDOMIZE) }, | ||||
|   { setvalue(PRICE_AUTOPARTIAL) }, | ||||
|   { setvalue(PRICE_LOOPLEFT) }, | ||||
|   { setvalue(PRICE_LOOPALTERNATE) }, | ||||
|   { setvalue(PRICE_HARRISTWOPASS) }, | ||||
|   { setvalue(PRICE_TRUENORMINIT) }, | ||||
| }; | ||||
| 
 | ||||
| static struct _values presolving[] = | ||||
| { | ||||
|   { setvalue(PRESOLVE_NONE) }, | ||||
|   { setvalue(PRESOLVE_ROWS) }, | ||||
|   { setvalue(PRESOLVE_COLS) }, | ||||
|   { setvalue(PRESOLVE_LINDEP) }, | ||||
|   { setvalue(PRESOLVE_AGGREGATE) }, | ||||
|   { setvalue(PRESOLVE_SPARSER) }, | ||||
|   { setvalue(PRESOLVE_SOS) }, | ||||
|   { setvalue(PRESOLVE_REDUCEMIP) }, | ||||
|   { setvalue(PRESOLVE_KNAPSACK) }, | ||||
|   { setvalue(PRESOLVE_ELIMEQ2) }, | ||||
|   { setvalue(PRESOLVE_IMPLIEDFREE) }, | ||||
|   { setvalue(PRESOLVE_REDUCEGCD) }, | ||||
|   { setvalue(PRESOLVE_PROBEFIX) }, | ||||
|   { setvalue(PRESOLVE_PROBEREDUCE) }, | ||||
|   { setvalue(PRESOLVE_ROWDOMINATE) }, | ||||
|   { setvalue(PRESOLVE_COLDOMINATE) }, | ||||
|   { setvalue(PRESOLVE_MERGEROWS) }, | ||||
|   { setvalue(PRESOLVE_IMPLIEDSLK) }, | ||||
|   { setvalue(PRESOLVE_COLFIXDUAL) }, | ||||
|   { setvalue(PRESOLVE_BOUNDS) }, | ||||
|   { setvalue(PRESOLVE_DUALS) }, | ||||
|   { setvalue(PRESOLVE_SENSDUALS) }, | ||||
| }; | ||||
| 
 | ||||
| static char *STRLWR(char *str) | ||||
| { | ||||
|   char *ptr; | ||||
| 
 | ||||
|   for(ptr = str; *ptr; ptr++) | ||||
|     *ptr = (char) tolower((unsigned char) *ptr); | ||||
| 
 | ||||
|   return(str); | ||||
| } | ||||
| 
 | ||||
| static char *STRUPR(char *str) | ||||
| { | ||||
|   char *ptr; | ||||
| 
 | ||||
|   for(ptr = str; *ptr; ptr++) | ||||
|     *ptr = (char) toupper((unsigned char) *ptr); | ||||
| 
 | ||||
|   return(str); | ||||
| } | ||||
| 
 | ||||
| static void __WINAPI set_presolve1(lprec *lp, int do_presolve) | ||||
| { | ||||
|   set_presolve(lp, do_presolve, get_presolveloops(lp)); | ||||
| } | ||||
| 
 | ||||
| static void __WINAPI set_presolve2(lprec *lp, int maxloops) | ||||
| { | ||||
|   set_presolve(lp, get_presolve(lp), maxloops); | ||||
| } | ||||
| 
 | ||||
| static struct _values print_sol[] = | ||||
| { | ||||
|   { FALSE, "0" }, | ||||
|   { TRUE,  "1" }, | ||||
|   { setvalue(AUTOMATIC) }, | ||||
| }; | ||||
| 
 | ||||
| static struct _values scaling[] = | ||||
| { | ||||
|   { setvalue(SCALE_NONE) }, | ||||
|   { setvalue(SCALE_EXTREME) }, | ||||
|   { setvalue(SCALE_RANGE) }, | ||||
|   { setvalue(SCALE_MEAN) }, | ||||
|   { setvalue(SCALE_GEOMETRIC) }, | ||||
|   { setvalue(SCALE_CURTISREID) }, | ||||
|   { setvalue(SCALE_QUADRATIC) }, | ||||
|   { setvalue(SCALE_LOGARITHMIC) }, | ||||
|   { setvalue(SCALE_USERWEIGHT) }, | ||||
|   { setvalue(SCALE_POWER2) }, | ||||
|   { setvalue(SCALE_EQUILIBRATE) }, | ||||
|   { setvalue(SCALE_INTEGERS) }, | ||||
|   { setvalue(SCALE_DYNUPDATE) }, | ||||
|   { setvalue(SCALE_ROWSONLY) }, | ||||
|   { setvalue(SCALE_COLSONLY) }, | ||||
| }; | ||||
| 
 | ||||
| static struct _values simplextype[] = | ||||
| { | ||||
|   { setvalue(SIMPLEX_PRIMAL_PRIMAL) }, | ||||
|   { setvalue(SIMPLEX_DUAL_PRIMAL) }, | ||||
|   { setvalue(SIMPLEX_PRIMAL_DUAL) }, | ||||
|   { setvalue(SIMPLEX_DUAL_DUAL) }, | ||||
| }; | ||||
| 
 | ||||
| static struct _values verbose[] = | ||||
| { | ||||
|   { setvalue(NEUTRAL) }, | ||||
|   { setvalue(CRITICAL) }, | ||||
|   { setvalue(SEVERE) }, | ||||
|   { setvalue(IMPORTANT) }, | ||||
|   { setvalue(NORMAL) }, | ||||
|   { setvalue(DETAILED) }, | ||||
|   { setvalue(FULL) }, | ||||
| }; | ||||
| 
 | ||||
| static struct _functions functions[] = | ||||
| { | ||||
|   /* solve options */ | ||||
|   { "ANTI_DEGEN", setintfunction(get_anti_degen, set_anti_degen), setvalues(anti_degen, ~0), WRITE_ACTIVE }, | ||||
|   { "BASISCRASH", setintfunction(get_basiscrash, set_basiscrash), setvalues(basiscrash, ~0), WRITE_ACTIVE }, | ||||
|   { "IMPROVE", setintfunction(get_improve, set_improve), setvalues(improve, ~0), WRITE_ACTIVE }, | ||||
|   { "MAXPIVOT", setintfunction(get_maxpivot, set_maxpivot), setNULLvalues, WRITE_ACTIVE }, | ||||
|   { "NEGRANGE", setREALfunction(get_negrange, set_negrange), setNULLvalues, WRITE_ACTIVE }, | ||||
|   { "PIVOTING", setintfunction(get_pivoting, set_pivoting), setvalues(pivoting, PRICER_LASTOPTION), WRITE_ACTIVE }, | ||||
|   { "PRESOLVE", setintfunction(get_presolve, set_presolve1), setvalues(presolving, ~0), WRITE_ACTIVE }, | ||||
|   { "PRESOLVELOOPS", setintfunction(get_presolveloops, set_presolve2), setNULLvalues, WRITE_ACTIVE }, | ||||
|   { "SCALELIMIT", setREALfunction(get_scalelimit, set_scalelimit), setNULLvalues, WRITE_ACTIVE }, | ||||
|   { "SCALING", setintfunction(get_scaling, set_scaling), setvalues(scaling, SCALE_CURTISREID), WRITE_ACTIVE }, | ||||
|   { "SIMPLEXTYPE", setintfunction(get_simplextype, set_simplextype), setvalues(simplextype, ~0), WRITE_ACTIVE }, | ||||
|   { "OBJ_IN_BASIS", setMYBOOLfunction(is_obj_in_basis, set_obj_in_basis), setNULLvalues, WRITE_COMMENTED }, | ||||
| 
 | ||||
|   /* B&B options */ | ||||
|   { "BB_DEPTHLIMIT", setintfunction(get_bb_depthlimit, set_bb_depthlimit), setNULLvalues, WRITE_ACTIVE }, | ||||
|   { "BB_FLOORFIRST", setintfunction(get_bb_floorfirst, set_bb_floorfirst), setvalues(bb_floorfirst, ~0), WRITE_ACTIVE }, | ||||
|   { "BB_RULE", setintfunction(get_bb_rule, set_bb_rule), setvalues(bb_rule, NODE_STRATEGYMASK), WRITE_ACTIVE }, | ||||
|   { "BREAK_AT_FIRST", setMYBOOLfunction(is_break_at_first, set_break_at_first), setNULLvalues, WRITE_COMMENTED }, | ||||
|   { "BREAK_AT_VALUE", setREALfunction(get_break_at_value, set_break_at_value), setNULLvalues, WRITE_COMMENTED }, | ||||
|   { "MIP_GAP_ABS", setREALfunction(get_mip_gap_abs, set_mip_gap_abs), setNULLvalues, WRITE_ACTIVE }, | ||||
|   { "MIP_GAP_REL", setREALfunction(get_mip_gap_rel, set_mip_gap_rel), setNULLvalues, WRITE_ACTIVE }, | ||||
|   { "EPSINT", setREALfunction(get_epsint, set_epsint), setNULLvalues, WRITE_ACTIVE }, | ||||
| 
 | ||||
|   /* tolerances, values */ | ||||
|   { "EPSB", setREALfunction(get_epsb, set_epsb), setNULLvalues, WRITE_ACTIVE }, | ||||
|   { "EPSD", setREALfunction(get_epsd, set_epsd), setNULLvalues, WRITE_ACTIVE }, | ||||
|   { "EPSEL", setREALfunction(get_epsel, set_epsel), setNULLvalues, WRITE_ACTIVE }, | ||||
|   { "EPSPERTURB", setREALfunction(get_epsperturb, set_epsperturb), setNULLvalues, WRITE_ACTIVE }, | ||||
|   { "EPSPIVOT", setREALfunction(get_epspivot, set_epspivot), setNULLvalues, WRITE_ACTIVE }, | ||||
|   { "INFINITE", setREALfunction(get_infinite, set_infinite), setNULLvalues, WRITE_ACTIVE }, | ||||
| 
 | ||||
|   /* read-only options */ | ||||
|   { "DEBUG", setMYBOOLfunction(is_debug, set_debug), setNULLvalues, WRITE_COMMENTED }, | ||||
|   { "OBJ_BOUND", setREALfunction(get_obj_bound, set_obj_bound), setNULLvalues, WRITE_COMMENTED }, | ||||
|   { "PRINT_SOL", setintfunction(get_print_sol, set_print_sol), setvalues(print_sol, ~0), WRITE_COMMENTED }, | ||||
|   { "TIMEOUT", setlongfunction(get_timeout, set_timeout), setNULLvalues, WRITE_COMMENTED }, | ||||
|   { "TRACE", setMYBOOLfunction(is_trace, set_trace), setNULLvalues, WRITE_COMMENTED }, | ||||
|   { "VERBOSE", setintfunction(get_verbose, set_verbose), setvalues(verbose, ~0), WRITE_COMMENTED }, | ||||
| }; | ||||
| 
 | ||||
| static void write_params1(lprec *lp, FILE *fp, char *header, int newline) | ||||
| { | ||||
|   int ret = 0, ret2, i, j, k, value, value2, elements, majorversion, minorversion, release, build; | ||||
|   unsigned int basemask; | ||||
|   REAL a = 0; | ||||
|   char buf[4096], par[20]; | ||||
| 
 | ||||
|   ini_writeheader(fp, header, newline); | ||||
|   lp_solve_version(&majorversion, &minorversion, &release, &build); | ||||
|   sprintf(buf, "lp_solve version %d.%d settings\n", majorversion, minorversion); | ||||
|   ini_writecomment(fp, buf); | ||||
|   for(i = 0; i < sizeof(functions) / sizeof(*functions); i++) { | ||||
|     switch(functions[i].type) { | ||||
|     case intfunction: | ||||
|       if(functions[i].get_function.int_get_function == NULL) | ||||
|         continue; | ||||
|       ret = functions[i].get_function.int_get_function(lp); | ||||
|       break; | ||||
|     case longfunction: | ||||
|       if(functions[i].get_function.long_get_function == NULL) | ||||
|         continue; | ||||
|       ret = functions[i].get_function.long_get_function(lp); | ||||
|       break; | ||||
|     case MYBOOLfunction: | ||||
|       if(functions[i].get_function.MYBOOL_get_function == NULL) | ||||
|         continue; | ||||
|       ret = (int) functions[i].get_function.MYBOOL_get_function(lp); | ||||
|       break; | ||||
|     case REALfunction: | ||||
|       if(functions[i].get_function.REAL_get_function == NULL) | ||||
|         continue; | ||||
|       a = functions[i].get_function.REAL_get_function(lp); | ||||
|       break; | ||||
|     } | ||||
|     buf[0] = 0; | ||||
|     if(functions[i].values == NULL) { | ||||
|       switch(functions[i].type) { | ||||
|       case intfunction: | ||||
|       case longfunction: | ||||
|       case MYBOOLfunction: | ||||
|         sprintf(buf, "%d", ret); | ||||
|         break; | ||||
|       case REALfunction: | ||||
|         sprintf(buf, "%g", a); | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
|     else { | ||||
|       elements = functions[i].elements; | ||||
|       basemask = functions[i].basemask; | ||||
|       for(j = 0; j < elements; j++) { | ||||
|         value = functions[i].values[j].value; | ||||
| 	ret2 = ret; | ||||
| 	if(((unsigned int) value) < basemask) | ||||
| 	  ret2 &= basemask; | ||||
|         if(value == 0) { | ||||
|           if(ret2 == 0) { | ||||
|             if(*buf) | ||||
|               strcat(buf, " + "); | ||||
|             strcat(buf, functions[i].values[j].svalue); | ||||
|           } | ||||
|         } | ||||
|         else if((ret2 & value) == value) { | ||||
|           for(k = 0; k < elements; k++) { | ||||
|             value2 = functions[i].values[k].value; | ||||
|             if((k != j) && (value2 > value) && ((value2 & value) == value) && ((ret2 & value2) == value2)) | ||||
|               break; | ||||
|           } | ||||
|           if(k == elements) { | ||||
|             if(*buf) | ||||
|               strcat(buf, " + "); | ||||
|             strcat(buf, functions[i].values[j].svalue); | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     if(functions[i].mask & WRITE_ACTIVE) | ||||
|       par[0] = 0; | ||||
|     else | ||||
|       strcpy(par, ";"); | ||||
|     strcat(par, functions[i].par); | ||||
|     ini_writedata(fp, STRLWR(par), buf); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| static void readoptions(char *options, char **header) | ||||
| { | ||||
|   char *ptr1, *ptr2; | ||||
| 
 | ||||
|   if(options != NULL) { | ||||
|     ptr1 = options; | ||||
|     while(*ptr1) { | ||||
|       ptr2 = strchr(ptr1, '-'); | ||||
|       if(ptr2 == NULL) | ||||
|         break; | ||||
|       ptr2++; | ||||
|       if(tolower((unsigned char) *ptr2) == 'h') { | ||||
|         for(++ptr2; (*ptr2) && (isspace(*ptr2)); ptr2++); | ||||
|         for(ptr1 = ptr2; (*ptr1) && (!isspace(*ptr1)); ptr1++); | ||||
|         *header = (char *) calloc(1 + (int) (ptr1 - ptr2), 1); | ||||
|         memcpy(*header, ptr2, (int) (ptr1 - ptr2)); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   if(*header == NULL) | ||||
|     *header = strdup("Default"); | ||||
| } | ||||
| 
 | ||||
| MYBOOL __WINAPI write_params(lprec *lp, char *filename, char *options) | ||||
| { | ||||
|   int k, ret, params_written; | ||||
|   FILE *fp, *fp0; | ||||
|   int state = 0, looping, newline; | ||||
|   char buf[4096], *filename0, *ptr1, *ptr2, *header = NULL; | ||||
| 
 | ||||
|   readoptions(options, &header); | ||||
| 
 | ||||
|   k = strlen(filename); | ||||
|   filename0 = (char *) malloc(k + 1 + 1); | ||||
|   strcpy(filename0, filename); | ||||
|   ptr1 = strrchr(filename0, '.'); | ||||
|   ptr2 = strrchr(filename0, '\\'); | ||||
|   if((ptr1 == NULL) || ((ptr2 != NULL) && (ptr1 < ptr2))) | ||||
|     ptr1 = filename0 + k; | ||||
|   memmove(ptr1 + 1, ptr1, k + 1 - (int) (ptr1 - filename0)); | ||||
|   ptr1[0] = '_'; | ||||
|   if(rename(filename, filename0)) { | ||||
|     switch(errno) { | ||||
|     case ENOENT: /* File or path specified by oldname not found */ | ||||
|       FREE(filename0); | ||||
|       filename0 = NULL; | ||||
|       break; | ||||
|     case EACCES: /* File or directory specified by newname already exists or could not be created (invalid path); or oldname is a directory and newname specifies a different path. */ | ||||
|       FREE(filename0); | ||||
|       FREE(header); | ||||
|       return(FALSE); | ||||
|       break; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   if((fp = ini_create(filename)) == NULL) | ||||
|     ret = FALSE; | ||||
|   else { | ||||
|     params_written = FALSE; | ||||
|     newline = TRUE; | ||||
|     if(filename0 != NULL) { | ||||
|       fp0 = ini_open(filename0); | ||||
|       if(fp0 == NULL) { | ||||
|         rename(filename0, filename); | ||||
|         FREE(filename0); | ||||
|         FREE(header); | ||||
|         return(FALSE); | ||||
|       } | ||||
|       looping = TRUE; | ||||
|       while(looping) { | ||||
|         switch(ini_readdata(fp0, buf, sizeof(buf), TRUE)) { | ||||
|         case 0: /* End of file */ | ||||
|           looping = FALSE; | ||||
|           break; | ||||
|         case 1: /* header */ | ||||
|           ptr1 = strdup(buf); | ||||
|           STRUPR(buf); | ||||
|           ptr2 = strdup(header); | ||||
|           STRUPR(ptr2); | ||||
|           if(strcmp(buf, ptr2) == 0) { | ||||
|             write_params1(lp, fp, ptr1, newline); | ||||
|             params_written = TRUE; | ||||
|             newline = TRUE; | ||||
|             state = 1; | ||||
|           } | ||||
|           else { | ||||
|             state = 0; | ||||
|             ini_writeheader(fp, ptr1, newline); | ||||
|             newline = TRUE; | ||||
|           } | ||||
|           FREE(ptr2); | ||||
|           FREE(ptr1); | ||||
|           break; | ||||
|         case 2: /* data */ | ||||
|           if(state == 0) { | ||||
|             ini_writedata(fp, NULL, buf); | ||||
|             newline = (*buf != 0); | ||||
|           } | ||||
|           break; | ||||
|         } | ||||
|       } | ||||
|       ini_close(fp0); | ||||
|     } | ||||
| 
 | ||||
|     if(!params_written) | ||||
|       write_params1(lp, fp, header, newline); | ||||
| 
 | ||||
|     ini_close(fp); | ||||
|     ret = TRUE; | ||||
|   } | ||||
| 
 | ||||
|   if(filename0 != NULL) { | ||||
|     remove(filename0); | ||||
|     FREE(filename0); | ||||
|   } | ||||
| 
 | ||||
|   FREE(header); | ||||
| 
 | ||||
|   return( (MYBOOL) ret ); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| MYBOOL __WINAPI read_params(lprec *lp, char *filename, char *options) | ||||
| { | ||||
|   int ret, looping, line; | ||||
|   FILE *fp; | ||||
|   hashtable *hashfunctions, *hashparameters; | ||||
|   hashelem *hp; | ||||
|   int i, j, elements, n, intvalue, state = 0; | ||||
|   REAL REALvalue; | ||||
|   char buf[4096], *header = NULL, *ptr, *ptr1, *ptr2; | ||||
| 
 | ||||
|   if((fp = ini_open(filename)) == NULL) | ||||
|     ret = FALSE; | ||||
|   else { | ||||
|     /* create hashtable of all callable commands to find them quickly */ | ||||
|     hashfunctions = create_hash_table(sizeof(functions) / sizeof(*functions), 0); | ||||
|     for (n = 0, i = 0; i < (int) (sizeof(functions)/sizeof(*functions)); i++) { | ||||
|       puthash(functions[i].par, i, NULL, hashfunctions); | ||||
|       if(functions[i].values != NULL) | ||||
|         n += functions[i].elements; | ||||
|     } | ||||
|     /* create hashtable of all arguments to find them quickly */ | ||||
|     hashparameters = create_hash_table(n, 0); | ||||
|     for (n = 0, i = 0; i < (int) (sizeof(functions)/sizeof(*functions)); i++) { | ||||
|       if(functions[i].values != NULL) { | ||||
|         elements = functions[i].elements; | ||||
|         for(j = 0; j < elements; j++) | ||||
|           if((strcmp(functions[i].values[j].svalue, "0") != 0) && | ||||
|              (strcmp(functions[i].values[j].svalue, "1") != 0)) | ||||
|             puthash(functions[i].values[j].svalue, j, NULL, hashparameters); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     readoptions(options, &header); | ||||
| 
 | ||||
|     STRUPR(header); | ||||
|     ret = looping = TRUE; | ||||
|     line = 0; | ||||
|     while((ret) && (looping)) { | ||||
|       line++; | ||||
|       switch(ini_readdata(fp, buf, sizeof(buf), FALSE)) { | ||||
|         case 0: /* End of file */ | ||||
|           looping = FALSE; | ||||
|           break; | ||||
|         case 1: /* header */ | ||||
|           switch(state) { | ||||
|             case 0: | ||||
|               STRUPR(buf); | ||||
|               if(strcmp(buf, header) == 0) | ||||
|                 state = 1; | ||||
|               break; | ||||
|             case 1: | ||||
|               looping = FALSE; | ||||
|               break; | ||||
|           } | ||||
|           break; | ||||
|         case 2: /* data */ | ||||
|           if(state == 1) { | ||||
|             for(ptr = buf; (*ptr) && (isspace(*ptr)); ptr++); | ||||
|           } | ||||
|           else | ||||
|             ptr = NULL; | ||||
|           if((ptr != NULL) && (*ptr)) { | ||||
|             STRUPR(buf); | ||||
|             ptr = strchr(buf, '='); | ||||
|             if(ptr == NULL) { | ||||
|               report(lp, IMPORTANT, "read_params: No equal sign on line %d\n", line); | ||||
|               ret = FALSE; | ||||
|             } | ||||
|             else { | ||||
|               *ptr = 0; | ||||
|               for(ptr1 = buf; isspace(*ptr1); ptr1++); | ||||
|               for(ptr2 = ptr - 1; (ptr2 >= ptr1) && (isspace(*ptr2)); ptr2--); | ||||
|               if(ptr2 <= ptr1) { | ||||
|                 report(lp, IMPORTANT, "read_params: No parameter name before equal sign on line %d\n", line); | ||||
|                 ret = FALSE; | ||||
|               } | ||||
|               else { | ||||
|                 ptr2[1] = 0; | ||||
|                 hp = findhash(ptr1, hashfunctions); | ||||
|                 if(hp == NULL) { | ||||
|                   report(lp, IMPORTANT, "read_params: Unknown parameter name (%s) before equal sign on line %d\n", ptr1, line); | ||||
|                   ret = FALSE; | ||||
|                 } | ||||
|                 else { | ||||
|                   i = hp->index; | ||||
|                   ptr1 = ++ptr; | ||||
|                   intvalue = 0; | ||||
|                   REALvalue = 0; | ||||
|                   if(functions[i].values == NULL) { | ||||
|                     switch(functions[i].type) { | ||||
|                       case intfunction: | ||||
|                       case longfunction: | ||||
|                       case MYBOOLfunction: | ||||
|                         intvalue = strtol(ptr1, &ptr2, 10); | ||||
|                         while((*ptr2) && (isspace(*ptr2))) | ||||
|                           ptr2++; | ||||
|                         if(*ptr2) { | ||||
|                           report(lp, IMPORTANT, "read_params: Invalid integer value on line %d\n", line); | ||||
|                           ret = FALSE; | ||||
|                         } | ||||
|                         break; | ||||
|                       case REALfunction: | ||||
|                         REALvalue = strtod(ptr1, &ptr2); | ||||
|                         while((*ptr2) && (isspace(*ptr2))) | ||||
|                           ptr2++; | ||||
|                         if(*ptr2) { | ||||
|                           report(lp, IMPORTANT, "read_params: Invalid real value on line %d\n", line); | ||||
|                           ret = FALSE; | ||||
|                         } | ||||
|                         break; | ||||
|                     } | ||||
|                   } | ||||
|                   else { | ||||
|                     while(ret) { | ||||
|                       ptr = strchr(ptr1, '+'); | ||||
|                       if(ptr == NULL) | ||||
|                         ptr = ptr1 + strlen(ptr1); | ||||
|                       for(; isspace(*ptr1); ptr1++); | ||||
|                       for(ptr2 = ptr - 1; (ptr2 >= ptr1) && (isspace(*ptr2)); ptr2--); | ||||
|                       if(ptr2 <= ptr1) | ||||
|                         break; | ||||
|                       else { | ||||
|                         ptr2[1] = 0; | ||||
|                         hp = findhash(ptr1, hashparameters); | ||||
|                         if (hp == NULL) { | ||||
|                           report(lp, IMPORTANT, "read_params: Invalid parameter name (%s) on line %d\n", ptr1, line); | ||||
|                           ret = FALSE; | ||||
|                         } | ||||
|                         else { | ||||
|                           j = hp->index; | ||||
|                           if((j >= functions[i].elements) || | ||||
|                              (strcmp(functions[i].values[j].svalue, ptr1))) { | ||||
|                             report(lp, IMPORTANT, "read_params: Inappropriate parameter name (%s) on line %d\n", ptr1, line); | ||||
|                             ret = FALSE; | ||||
|                           } | ||||
|                           else { | ||||
|                             intvalue += functions[i].values[j].value; | ||||
|                           } | ||||
|                         } | ||||
|                         ptr1 = ptr + 1; | ||||
|                       } | ||||
|                     } | ||||
|                   } | ||||
|                   if(ret) { | ||||
|                     switch(functions[i].type) { | ||||
|                       case intfunction: | ||||
|                         functions[i].set_function.int_set_function(lp, intvalue); | ||||
|                         break; | ||||
|                       case longfunction: | ||||
|                         functions[i].set_function.long_set_function(lp, intvalue); | ||||
|                         break; | ||||
|                       case MYBOOLfunction: | ||||
|                         functions[i].set_function.MYBOOL_set_function(lp, (MYBOOL) intvalue); | ||||
|                         break; | ||||
|                       case REALfunction: | ||||
|                         functions[i].set_function.REAL_set_function(lp, REALvalue); | ||||
|                         break; | ||||
|                     } | ||||
|                   } | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|           break; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     FREE(header); | ||||
|     free_hash_table(hashfunctions); | ||||
|     free_hash_table(hashparameters); | ||||
| 
 | ||||
|     ini_close(fp); | ||||
|   } | ||||
| 
 | ||||
|   return( (MYBOOL) ret ); | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -1,126 +0,0 @@ | |||
| #ifndef HEADER_lp_presolve | ||||
| #define HEADER_lp_presolve | ||||
| 
 | ||||
| #include "lp_types.h" | ||||
| #include "lp_matrix.h" | ||||
| 
 | ||||
| /* -------------------------------------------------------------------------------------------- */ | ||||
| /* Defines for various presolve options                                                         */ | ||||
| /* -------------------------------------------------------------------------------------------- */ | ||||
| 
 | ||||
| #define MAX_PSMERGELOOPS                2                 /* Max loops to merge compatible constraints */ | ||||
| #define MAX_PSLINDEPLOOPS               1   /* Max loops to detect linearly dependendent constraints */ | ||||
| #define MAX_PSBOUNDTIGHTENLOOPS         5     /* Maximumn number of loops to allow bound tightenings */ | ||||
| #define MIN_SOS1LENGTH                  4   /* Minimum length of a constraint for conversion to SOS1 */ | ||||
| #if 1 | ||||
|   #define PRESOLVE_EPSVALUE (0.1*lp->epsprimal) | ||||
| #else | ||||
|   #define PRESOLVE_EPSVALUE  lp->epsvalue | ||||
| #endif | ||||
| #define PRESOLVE_EPSPIVOT         1.0e-3        /* Looses robustness at values smaller than ~1.0e-3 */ | ||||
| #define PRESOLVE_BOUNDSLACK           10                     /* Extra error recovery/tolerance margin */ | ||||
| 
 | ||||
| #define DoPresolveRounding              /* Use absolute and directed rounding (disable at own risk) */ | ||||
| /*#define DoPresolveRelativeTest*/ | ||||
| 
 | ||||
| /*#define PresolveForceUpdateMax*/ | ||||
| 
 | ||||
| /*#define DualFeasibilityLogicEQ2*/              /* Add low-order feasibility/accuracy logic to elimEQ2 */ | ||||
| #define DivisorIntegralityLogicEQ2                                   /* Always prefer integer divisors */ | ||||
| #define FindImpliedEqualities                               /* Detect equalities (default is enabled) */ | ||||
| #define Eq2Reldiff | ||||
| 
 | ||||
| /*#define SavePresolveEliminated */        /* Enable to activate storage of eliminated matrix data */ | ||||
| /*#define UseDualPresolve */                    /* Enable to use full dual information for presolve */ | ||||
| 
 | ||||
| 
 | ||||
| typedef struct _psrec | ||||
| { | ||||
|   LLrec *varmap; | ||||
|   int  **next; | ||||
|   int  *empty; | ||||
|   int  *plucount; | ||||
|   int  *negcount; | ||||
|   int  *pluneg; | ||||
|   int  *infcount; | ||||
|   REAL  *plulower; | ||||
|   REAL  *neglower; | ||||
|   REAL  *pluupper; | ||||
|   REAL  *negupper; | ||||
|   int  allocsize; | ||||
| } psrec; | ||||
| 
 | ||||
| typedef struct _presolverec | ||||
| { | ||||
|   psrec *rows; | ||||
|   psrec *cols; | ||||
|   LLrec *EQmap; | ||||
|   LLrec *LTmap; | ||||
|   LLrec *INTmap; | ||||
|   REAL  *pv_upbo; | ||||
|   REAL  *pv_lobo; | ||||
|   REAL  *dv_upbo; | ||||
|   REAL  *dv_lobo; | ||||
|   lprec *lp; | ||||
|   REAL  epsvalue; | ||||
|   REAL  epspivot; | ||||
|   int   innerloops; | ||||
|   int   middleloops; | ||||
|   int   outerloops; | ||||
|   int   nzdeleted; | ||||
|   MYBOOL forceupdate; | ||||
| } presolverec; | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| /* Put function headers here */ | ||||
| 
 | ||||
| STATIC MYBOOL presolve_createUndo(lprec *lp); | ||||
| STATIC MYBOOL presolve_rebuildUndo(lprec *lp, MYBOOL isprimal); | ||||
| STATIC MYBOOL inc_presolve_space(lprec *lp, int delta, MYBOOL isrows); | ||||
| STATIC MYBOOL presolve_setOrig(lprec *lp, int orig_rows, int orig_cols); | ||||
| STATIC MYBOOL presolve_colfix(presolverec *psdata, int colnr, REAL newvalue, MYBOOL remove, int *tally); | ||||
| STATIC MYBOOL presolve_fillUndo(lprec *lp, int orig_rows, int orig_cols, MYBOOL setOrig); | ||||
| STATIC MYBOOL presolve_freeUndo(lprec *lp); | ||||
| 
 | ||||
| STATIC MYBOOL presolve_updatesums(presolverec *psdata); | ||||
| 
 | ||||
| INLINE int presolve_nextrow(presolverec *psdata, int colnr, int *previtem); | ||||
| INLINE int presolve_nextcol(presolverec *psdata, int rownr, int *previtem); | ||||
| 
 | ||||
| STATIC presolverec *presolve_init(lprec *lp); | ||||
| STATIC void presolve_free(presolverec **psdata); | ||||
| STATIC int presolve_shrink(presolverec *psdata, int *nConRemove, int *nVarRemove); | ||||
| STATIC void presolve_rowremove(presolverec *psdata, int rownr, MYBOOL allowcoldelete); | ||||
| STATIC int presolve_colremove(presolverec *psdata, int colnr, MYBOOL allowrowdelete); | ||||
| 
 | ||||
| STATIC MYBOOL presolve_colfixdual(presolverec *psdata, int colnr, REAL *fixValue, int *status); | ||||
| 
 | ||||
| INLINE int presolve_rowlength(presolverec *psdata, int rownr) | ||||
| { | ||||
|   int *items = psdata->rows->next[rownr]; | ||||
| 
 | ||||
|   if(items == NULL) | ||||
|     return( 0 ); | ||||
|   else | ||||
|     return( items[0] ); | ||||
| } | ||||
| INLINE int presolve_collength(presolverec *psdata, int colnr) | ||||
| { | ||||
|   int *items = psdata->cols->next[colnr]; | ||||
|   if(items == NULL) | ||||
|     return( 0 ); | ||||
|   else | ||||
|     return( items[0] ); | ||||
| } | ||||
| 
 | ||||
| STATIC int presolve(lprec *lp); | ||||
| STATIC MYBOOL postsolve(lprec *lp, int status); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
|  } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* HEADER_lp_presolve */ | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -1,99 +0,0 @@ | |||
| #ifndef HEADER_lp_price | ||||
| #define HEADER_lp_price | ||||
| 
 | ||||
| /* Local defines                                                             */ | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| #define UseSortOnBound_Improve | ||||
| /*#define UseSortOnBound_Substitute*/ | ||||
| 
 | ||||
| #if 0 /* Stricter feasibility-preserving tolerance; use w/ *_UseRejectionList */
 | ||||
|   #define UseRelativeFeasibility       /* Use machine-precision and A-scale data */ | ||||
| #endif | ||||
| #if 0          /* Stricter pivot-selection criteria; use w/ *UseRejectionList */
 | ||||
|   #define UseRelativePivot_Primal             /* In rowprim based on A-scale data */ | ||||
|   #define UseRelativePivot_Dual               /* In coldual based on A-scale data */ | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /* Include required library headers                                          */ | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| #include "lp_types.h" | ||||
| 
 | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| /* Comparison and validity routines */ | ||||
| int CMP_CALLMODEL compareImprovementVar(const pricerec *current, const pricerec *candidate); | ||||
| int CMP_CALLMODEL compareSubstitutionVar(const pricerec *current, const pricerec *candidate); | ||||
| int CMP_CALLMODEL compareBoundFlipVar(const pricerec *current, const pricerec *candidate); | ||||
| STATIC int addCandidateVar(pricerec *candidate, multirec *multi, findCompare_func findCompare, MYBOOL allowSortedExpand); | ||||
| STATIC MYBOOL collectMinorVar(pricerec *candidate, multirec *longsteps, MYBOOL isphase2, MYBOOL isbatch); | ||||
| STATIC MYBOOL validImprovementVar(pricerec *candidate); | ||||
| STATIC MYBOOL validSubstitutionVar(pricerec *candidate); | ||||
| 
 | ||||
| /* Row+column selection routines */ | ||||
| STATIC MYBOOL findImprovementVar(pricerec *current, pricerec *candidate, MYBOOL collectMP, int *candidatecount); | ||||
| STATIC MYBOOL findSubstitutionVar(pricerec *current, pricerec *candidate, int *candidatecount); | ||||
| INLINE REAL normalizeEdge(lprec *lp, int item, REAL edge, MYBOOL isdual); | ||||
| STATIC void makePriceLoop(lprec *lp, int *start, int *end, int *delta); | ||||
| 
 | ||||
| /* Computation of reduced costs */ | ||||
| STATIC void update_reducedcosts(lprec *lp, MYBOOL isdual, int leave_nr, int enter_nr, REAL *prow, REAL *drow); | ||||
| STATIC void compute_reducedcosts(lprec *lp, MYBOOL isdual, int row_nr, int *coltarget, MYBOOL dosolve, | ||||
|                                                             REAL *prow, int *nzprow, | ||||
|                                                             REAL *drow, int *nzdrow, | ||||
|                                                             int roundmode); | ||||
| 
 | ||||
| /* Leaving variable selection and entering column pricing loops */ | ||||
| STATIC int find_rowReplacement(lprec *lp, int rownr, REAL *prow, int *nzprow); | ||||
| STATIC int colprim(lprec *lp, REAL *drow, int *nzdrow, | ||||
|                               MYBOOL skipupdate, int partialloop, int *candidatecount, MYBOOL updateinfeas, REAL *xviol); | ||||
| STATIC int rowprim(lprec *lp, int colnr, LREAL *theta, REAL *pcol, int *nzpcol, MYBOOL forceoutEQ, REAL *xviol); | ||||
| STATIC int rowdual(lprec *lp, REAL *rhvec, MYBOOL forceoutEQ, MYBOOL updateinfeas, REAL *xviol); | ||||
| STATIC int coldual(lprec *lp, int row_nr, | ||||
|                               REAL *prow, int *nzprow, REAL *drow, int *nzdrow, | ||||
|                               MYBOOL dualphase1, MYBOOL skipupdate, | ||||
|                               int *candidatecount, REAL *xviol); | ||||
| 
 | ||||
| /* Partial pricing management routines */ | ||||
| STATIC partialrec *partial_createBlocks(lprec *lp, MYBOOL isrow); | ||||
| STATIC int partial_countBlocks(lprec *lp, MYBOOL isrow); | ||||
| STATIC int partial_activeBlocks(lprec *lp, MYBOOL isrow); | ||||
| STATIC void partial_freeBlocks(partialrec **blockdata); | ||||
| 
 | ||||
| /* Partial pricing utility routines */ | ||||
| STATIC int partial_findBlocks(lprec *lp, MYBOOL autodefine, MYBOOL isrow); | ||||
| STATIC int partial_blockStart(lprec *lp, MYBOOL isrow); | ||||
| STATIC int partial_blockEnd(lprec *lp, MYBOOL isrow); | ||||
| STATIC int partial_blockNextPos(lprec *lp, int block, MYBOOL isrow); | ||||
| 
 | ||||
| STATIC MYBOOL partial_blockStep(lprec *lp, MYBOOL isrow); | ||||
| STATIC MYBOOL partial_isVarActive(lprec *lp, int varno, MYBOOL isrow); | ||||
| 
 | ||||
| /* Multiple pricing / dual long step management routines */ | ||||
| STATIC multirec *multi_create(lprec *lp, MYBOOL truncinf); | ||||
| STATIC MYBOOL multi_resize(multirec *multi, int blocksize, int blockdiv, MYBOOL doVlist, MYBOOL doIset); | ||||
| STATIC int multi_restart(multirec *multi); | ||||
| STATIC int multi_size(multirec *multi); | ||||
| STATIC int multi_used(multirec *multi); | ||||
| STATIC MYBOOL multi_truncatingvar(multirec *multi, int varnr); | ||||
| STATIC MYBOOL multi_mustupdate(multirec *multi); | ||||
| STATIC void multi_valueInit(multirec *multi, REAL step_base, REAL obj_base); | ||||
| STATIC REAL *multi_valueList(multirec *multi); | ||||
| STATIC int *multi_indexSet(multirec *multi, MYBOOL regenerate); | ||||
| STATIC int multi_getvar(multirec *multi, int item); | ||||
| STATIC MYBOOL multi_recompute(multirec *multi, int index, MYBOOL isphase2, MYBOOL fullupdate); | ||||
| STATIC MYBOOL multi_removevar(multirec *multi, int varnr); | ||||
| STATIC int multi_enteringvar(multirec *multi, pricerec *current, int priority); | ||||
| STATIC REAL multi_enteringtheta(multirec *multi); | ||||
| STATIC void multi_free(multirec **multi); | ||||
| STATIC int multi_populateSet(multirec *multi, int **list, int excludenr); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
|  } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* HEADER_lp_price */ | ||||
| 
 | ||||
|  | @ -1,536 +0,0 @@ | |||
| 
 | ||||
| #include <string.h> | ||||
| #include "commonlib.h" | ||||
| #include "lp_lib.h" | ||||
| #include "lp_report.h" | ||||
| #include "lp_pricePSE.h" | ||||
| 
 | ||||
| #ifdef FORTIFY | ||||
| # include "lp_fortify.h" | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|     Advanced simplex price scaling modules - w/interface for lp_solve v5.0+ | ||||
|    ---------------------------------------------------------------------------------- | ||||
|     Author:        Kjell Eikland | ||||
|     Contact:       kjell.eikland@broadpark.no | ||||
|     License terms: LGPL. | ||||
| 
 | ||||
|     Requires:      lp_lib.h | ||||
| 
 | ||||
|     Release notes: | ||||
|     v1.0.0  1 September 2003    Implementation of DEVEX and STEEPEST EDGE | ||||
|                                 routines for the primal and dual simplex. | ||||
|     v1.0.1  1 January 2004      Made initial value of weight of ingoing | ||||
|                                 variable for the standard mode of DEVEX | ||||
|                                 consistent with the initialization at restart; | ||||
|                                 original version could at worst contribute | ||||
|                                 to cycling. | ||||
|     v1.0.2  23 March 2004       Added floors to Steepest Edge updates and | ||||
|                                 moved tests for tiny update higher. Previous | ||||
|                                 logic can be simulated by disabling the compiler | ||||
|                                 define ApplySteepestEdgeMinimum. | ||||
|     v1.1.0  1 July 2004         Renamed from lp_pricerPSE to lp_pricePSE in | ||||
|                                 conjuction with the creation of a separate | ||||
|                                 price library. | ||||
|     v1.2.0  1 March 2005        Changed memory allocation routines to use | ||||
|                                 standard lp_solve functions, improve error handling | ||||
|                                 and return boolean status values. | ||||
| 
 | ||||
|    ---------------------------------------------------------------------------------- | ||||
| */ | ||||
| 
 | ||||
| INLINE MYBOOL applyPricer(lprec *lp) | ||||
| { | ||||
|   int rule = get_piv_rule(lp); | ||||
|   return( (MYBOOL) ((rule == PRICER_DEVEX) || (rule == PRICER_STEEPESTEDGE)) ); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| STATIC void simplexPricer(lprec *lp, MYBOOL isdual) | ||||
| { | ||||
|   if(lp->edgeVector != NULL) | ||||
|     lp->edgeVector[0] = (REAL) isdual; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| STATIC void freePricer(lprec *lp) | ||||
| { | ||||
|   FREE(lp->edgeVector); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| STATIC MYBOOL resizePricer(lprec *lp) | ||||
| { | ||||
|   if(!applyPricer(lp)) | ||||
|     return( TRUE ); | ||||
| 
 | ||||
|   /* Reallocate vector for new size */ | ||||
|   if(!allocREAL(lp, &(lp->edgeVector), lp->sum_alloc+1, AUTOMATIC)) | ||||
|     return( FALSE ); | ||||
| 
 | ||||
|   /* Signal that we have not yet initialized the price vector */ | ||||
|   MEMCLEAR(lp->edgeVector, lp->sum_alloc+1); | ||||
|   lp->edgeVector[0] = -1; | ||||
|   return( TRUE ); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| STATIC MYBOOL initPricer(lprec *lp) | ||||
| { | ||||
|   if(!applyPricer(lp)) | ||||
|     return( FALSE ); | ||||
| 
 | ||||
|   /* Free any pre-existing pricer */ | ||||
|   freePricer(lp); | ||||
| 
 | ||||
|   /* Allocate vector to fit current problem size */ | ||||
|   return( resizePricer(lp) ); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| STATIC REAL getPricer(lprec *lp, int item, MYBOOL isdual) | ||||
| { | ||||
|   REAL value = 1.0; | ||||
| 
 | ||||
|   if(!applyPricer(lp)) | ||||
|     return( value ); | ||||
| 
 | ||||
|   value = *lp->edgeVector; | ||||
| 
 | ||||
|   /* Make sure we have a price vector to use */ | ||||
|   if(value < 0) { | ||||
| #ifdef Paranoia | ||||
|     report(lp, SEVERE, "getPricer: Called without having being initialized!\n"); | ||||
| #endif | ||||
|     return( 1.0 ); | ||||
|   } | ||||
|   /* We may be calling the primal from the dual (and vice-versa) for validation
 | ||||
|      of feasibility; ignore calling origin and simply return 1 */ | ||||
|   else if(isdual != value) { | ||||
|     return( 1.0 ); | ||||
|   } | ||||
|   /* Do the normal norm retrieval */ | ||||
|   else { | ||||
| 
 | ||||
|     if(isdual) | ||||
|       item = lp->var_basic[item]; | ||||
| 
 | ||||
|     value = lp->edgeVector[item]; | ||||
| 
 | ||||
|     if(value == 0) { | ||||
|       value = 1.0; | ||||
|       report(lp, SEVERE, "getPricer: Detected a zero-valued price at index %d\n", item); | ||||
|     } | ||||
| #ifdef Paranoia | ||||
|     else if(value < 0) | ||||
|       report(lp, SEVERE, "getPricer: Invalid %s reduced cost norm %g at index %d\n", | ||||
|                           my_if(isdual, "dual", "primal"), value, item); | ||||
| #endif | ||||
| 
 | ||||
|   /* Return the norm */ | ||||
|     return( sqrt(value) ); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| STATIC MYBOOL restartPricer(lprec *lp, MYBOOL isdual) | ||||
| { | ||||
|   REAL   *sEdge = NULL, seNorm, hold; | ||||
|   int    i, j, m; | ||||
|   MYBOOL isDEVEX, ok = applyPricer(lp); | ||||
| 
 | ||||
|   if(!ok) | ||||
|     return( ok ); | ||||
| 
 | ||||
|   /* Store the active/current pricing type */ | ||||
|   if(isdual == AUTOMATIC) | ||||
|     isdual = (MYBOOL) lp->edgeVector[0]; | ||||
|   else | ||||
|     lp->edgeVector[0] = isdual; | ||||
| 
 | ||||
|   m = lp->rows; | ||||
| 
 | ||||
|   /* Determine strategy and check if we have strategy fallback for the primal */ | ||||
|   isDEVEX = is_piv_rule(lp, PRICER_DEVEX); | ||||
|   if(!isDEVEX && !isdual) | ||||
|     isDEVEX = is_piv_mode(lp, PRICE_PRIMALFALLBACK); | ||||
| 
 | ||||
|   /* Check if we only need to do the simple DEVEX initialization */ | ||||
|   if(!is_piv_mode(lp, PRICE_TRUENORMINIT)) { | ||||
|     if(isdual) { | ||||
|       for(i = 1; i <= m; i++) | ||||
|         lp->edgeVector[lp->var_basic[i]] = 1.0; | ||||
|     } | ||||
|     else { | ||||
|       for(i = 1; i <= lp->sum; i++) | ||||
|         if(!lp->is_basic[i]) | ||||
|           lp->edgeVector[i] = 1.0; | ||||
|     } | ||||
|     return( ok ); | ||||
|   } | ||||
| 
 | ||||
|   /* Otherwise do the full Steepest Edge norm initialization */ | ||||
|   ok = allocREAL(lp, &sEdge, m+1, FALSE); | ||||
|   if(!ok) | ||||
|     return( ok ); | ||||
| 
 | ||||
|   if(isdual) { | ||||
| 
 | ||||
|    /* Extract the rows of the basis inverse and compute their squared norms */ | ||||
| 
 | ||||
|     for(i = 1; i <= m; i++) { | ||||
| 
 | ||||
|       bsolve(lp, i, sEdge, NULL, 0, 0.0); | ||||
| 
 | ||||
|       /* Compute the edge norm */ | ||||
|       seNorm = 0; | ||||
|       for(j = 1; j <= m; j++) { | ||||
|         hold = sEdge[j]; | ||||
|         seNorm += hold*hold; | ||||
|       } | ||||
| 
 | ||||
|       j = lp->var_basic[i]; | ||||
|       lp->edgeVector[j] = seNorm; | ||||
|     } | ||||
| 
 | ||||
|   } | ||||
|   else { | ||||
| 
 | ||||
|    /* Solve a=Bb for b over all non-basic variables and compute their squared norms */ | ||||
| 
 | ||||
|     for(i = 1; i <= lp->sum; i++) { | ||||
|       if(lp->is_basic[i]) | ||||
|         continue; | ||||
| 
 | ||||
|       fsolve(lp, i, sEdge, NULL, 0, 0.0, FALSE); | ||||
| 
 | ||||
|       /* Compute the edge norm */ | ||||
|       seNorm = 1; | ||||
|       for(j = 1; j <= m; j++) { | ||||
|         hold = sEdge[j]; | ||||
|         seNorm += hold*hold; | ||||
|       } | ||||
| 
 | ||||
|       lp->edgeVector[i] = seNorm; | ||||
|     } | ||||
| 
 | ||||
|   } | ||||
| 
 | ||||
|   FREE(sEdge); | ||||
| 
 | ||||
|   return( ok ); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| STATIC MYBOOL formWeights(lprec *lp, int colnr, REAL *pcol, REAL **w) | ||||
| /* This computes Bw = a, where B is the basis and a is a column of A */ | ||||
| { | ||||
|   MYBOOL ok = allocREAL(lp, w, lp->rows+1, FALSE); | ||||
| 
 | ||||
|   if(ok) { | ||||
|     if(pcol == NULL) | ||||
|       fsolve(lp, colnr, *w, NULL, 0.0, 0.0, FALSE); | ||||
|     else { | ||||
|       MEMCOPY(*w, pcol, lp->rows+1); | ||||
| /*    *w[0] = 0; */ /* Test */ | ||||
|     } | ||||
|   } | ||||
| /*
 | ||||
|   if(pcol != NULL) { | ||||
|     REAL cEdge, hold; | ||||
|     int  i; | ||||
| 
 | ||||
|     cEdge = 0; | ||||
|     for(i = 1; i <= m; i++) { | ||||
|       hold = *w[i]-pcol[i]; | ||||
|       cEdge += hold*hold; | ||||
|     } | ||||
|     cEdge /= m; | ||||
|     cEdge = sqrt(cEdge); | ||||
|     if(cEdge > lp->epspivot) | ||||
|       report(lp, SEVERE, "updatePricer: MRS error is %g\n", cEdge); | ||||
|   } | ||||
| */ | ||||
|   return(ok); | ||||
| } | ||||
| STATIC void freeWeights(REAL *w) | ||||
| { | ||||
|   FREE(w); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| STATIC MYBOOL updatePricer(lprec *lp, int rownr, int colnr, REAL *pcol, REAL *prow, int *nzprow) | ||||
| { | ||||
|   REAL   *vEdge = NULL, cEdge, hold, *newEdge, *w = NULL; | ||||
|   int    i, m, n, exitcol, errlevel = DETAILED; | ||||
|   MYBOOL forceRefresh = FALSE, isDual, isDEVEX, ok = FALSE; | ||||
| 
 | ||||
|   if(!applyPricer(lp)) | ||||
|     return(ok); | ||||
| 
 | ||||
|   /* Make sure we have something to update */ | ||||
|   hold = lp->edgeVector[0]; | ||||
|   if(hold < 0) | ||||
|     return(ok); | ||||
|   isDual = (MYBOOL) (hold > 0); | ||||
| 
 | ||||
|   /* Do common initializations and computations */ | ||||
|   m = lp->rows; | ||||
|   n = lp->sum; | ||||
|   isDEVEX = is_piv_rule(lp, PRICER_DEVEX); | ||||
|   exitcol = lp->var_basic[rownr]; | ||||
| 
 | ||||
|   /* Solve/copy Bw = a */ | ||||
| #if 0 | ||||
|   ok = formWeights(lp, colnr, NULL, &w);  /* Compute from scratch - Experimental */ | ||||
| #else | ||||
|   ok = formWeights(lp, colnr, pcol, &w);  /* Use previously computed values */ | ||||
| #endif | ||||
|   if(!ok) | ||||
|     return( ok ); | ||||
| 
 | ||||
|   /* Price norms for the dual simplex - the basic columns */ | ||||
|   if(isDual) { | ||||
|     REAL rw; | ||||
|     int  targetcol; | ||||
| 
 | ||||
|     /* Don't need to compute cross-products with DEVEX */ | ||||
|     if(!isDEVEX) { | ||||
|       ok = allocREAL(lp, &vEdge, m+1, FALSE); | ||||
|       if(!ok) | ||||
|         return( ok ); | ||||
| 
 | ||||
|     /* Extract the row of the inverse containing the leaving variable
 | ||||
|        and then form the dot products against the other variables, i.e. "Tau" */ | ||||
| #if 0 /* Extract row explicitly */
 | ||||
|       bsolve(lp, rownr, vEdge, 0, 0.0); | ||||
| #else /* Reuse previously extracted row data */ | ||||
|       MEMCOPY(vEdge, prow, m+1); | ||||
|       vEdge[0] = 0; | ||||
| #endif | ||||
|       lp->bfp_ftran_normal(lp, vEdge, NULL); | ||||
|     } | ||||
| 
 | ||||
|     /* Update the squared steepest edge norms; first store some constants */ | ||||
|     cEdge = lp->edgeVector[exitcol]; | ||||
|     rw = w[rownr]; | ||||
|     if(fabs(rw) < lp->epspivot) { | ||||
|       forceRefresh = TRUE; | ||||
|       goto Finish2; | ||||
|     } | ||||
| 
 | ||||
|    /* Deal with the variable entering the basis to become a new leaving candidate */ | ||||
|     hold = 1 / rw; | ||||
|     lp->edgeVector[colnr] = (hold*hold) * cEdge; | ||||
| 
 | ||||
| #ifdef Paranoia | ||||
|     if(lp->edgeVector[colnr] <= lp->epsmachine) | ||||
|       report(lp, errlevel, "updatePricer: Invalid dual norm %g at entering index %d - iteration %.0f\n", | ||||
|                            lp->edgeVector[colnr], rownr, (double) (lp->total_iter+lp->current_iter)); | ||||
| #endif | ||||
| 
 | ||||
|    /* Then loop over all basic variables, but skip the leaving row */ | ||||
|     for(i = 1; i <= m; i++) { | ||||
|       if(i == rownr) | ||||
|         continue; | ||||
|       targetcol = lp->var_basic[i]; | ||||
|       hold = w[i]; | ||||
|       if(hold == 0) | ||||
|         continue; | ||||
|       hold /= rw; | ||||
|       if(fabs(hold) < lp->epsmachine) | ||||
|         continue; | ||||
| 
 | ||||
|       newEdge = &(lp->edgeVector[targetcol]); | ||||
|       *newEdge += (hold*hold) * cEdge; | ||||
|       if(isDEVEX) { | ||||
|         if((*newEdge) > DEVEX_RESTARTLIMIT) { | ||||
|           forceRefresh = TRUE; | ||||
|           break; | ||||
|         } | ||||
|       } | ||||
|       else { | ||||
|         *newEdge -= 2*hold*vEdge[i]; | ||||
| #ifdef xxApplySteepestEdgeMinimum | ||||
|         SETMAX(*newEdge, hold*hold+1); /* Kludge; use the primal lower bound */ | ||||
| #else | ||||
|         if(*newEdge <= 0) { | ||||
|           report(lp, errlevel, "updatePricer: Invalid dual norm %g at index %d - iteration %.0f\n", | ||||
|                                 *newEdge, i, (double) (lp->total_iter+lp->current_iter)); | ||||
|           forceRefresh = TRUE; | ||||
|           break; | ||||
|         } | ||||
| #endif | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|   } | ||||
|   /* Price norms for the primal simplex - the non-basic columns */ | ||||
|   else { | ||||
| 
 | ||||
|     REAL *vTemp = NULL, *vAlpha = NULL, cAlpha; | ||||
|     int  *coltarget; | ||||
| 
 | ||||
|     ok = allocREAL(lp, &vTemp, m+1, TRUE) && | ||||
|          allocREAL(lp, &vAlpha, n+1, TRUE); | ||||
|     if(!ok) | ||||
|       return( ok ); | ||||
| 
 | ||||
|     /* Check if we have strategy fallback for the primal */ | ||||
|     if(!isDEVEX) | ||||
|       isDEVEX = is_piv_mode(lp, PRICE_PRIMALFALLBACK); | ||||
| 
 | ||||
|     /* Initialize column target array */ | ||||
|     coltarget = (int *) mempool_obtainVector(lp->workarrays, lp->sum+1, sizeof(*coltarget)); | ||||
|     ok = get_colIndexA(lp, SCAN_SLACKVARS+SCAN_USERVARS+USE_NONBASICVARS, coltarget, FALSE); | ||||
|     if(!ok) { | ||||
|       mempool_releaseVector(lp->workarrays, (char *) coltarget, FALSE); | ||||
|       return( ok ); | ||||
|     } | ||||
| 
 | ||||
|     /* Don't need to compute cross-products with DEVEX */ | ||||
|     if(!isDEVEX) { | ||||
|       ok = allocREAL(lp, &vEdge, n+1, TRUE); | ||||
|       if(!ok) | ||||
|         return( ok ); | ||||
| 
 | ||||
|       /* Compute v and then N'v */ | ||||
|       MEMCOPY(vTemp, w, m+1); | ||||
|       bsolve(lp, -1, vTemp, NULL, lp->epsmachine*DOUBLEROUND, 0.0); | ||||
|       vTemp[0] = 0; | ||||
|       prod_xA(lp, coltarget, vTemp, NULL, lp->epsmachine, 0.0, | ||||
|                              vEdge, NULL, MAT_ROUNDDEFAULT); | ||||
|     } | ||||
| 
 | ||||
|     /* Compute Sigma and then Alpha */ | ||||
|     bsolve(lp, rownr, vTemp, NULL, 0*DOUBLEROUND, 0.0); | ||||
|     vTemp[0] = 0; | ||||
|     prod_xA(lp, coltarget, vTemp, NULL, lp->epsmachine, 0.0, | ||||
|                            vAlpha, NULL, MAT_ROUNDDEFAULT); | ||||
|     mempool_releaseVector(lp->workarrays, (char *) coltarget, FALSE); | ||||
| 
 | ||||
|     /* Update the squared steepest edge norms; first store some constants */ | ||||
|     cEdge = lp->edgeVector[colnr]; | ||||
|     cAlpha = vAlpha[colnr]; | ||||
|     if(fabs(cAlpha) < lp->epspivot) { | ||||
|       forceRefresh = TRUE; | ||||
|       goto Finish1; | ||||
|     } | ||||
| 
 | ||||
|     /* Deal with the variable leaving the basis to become a new entry candidate */ | ||||
|     hold = 1 / cAlpha; | ||||
|     lp->edgeVector[exitcol] = (hold*hold) * cEdge; | ||||
| 
 | ||||
| #ifdef Paranoia | ||||
|     if(lp->edgeVector[exitcol] <= lp->epsmachine) | ||||
|       report(lp, errlevel, "updatePricer: Invalid primal norm %g at leaving index %d - iteration %.0f\n", | ||||
|                           lp->edgeVector[exitcol], exitcol, (double) (lp->total_iter+lp->current_iter)); | ||||
| #endif | ||||
| 
 | ||||
|     /* Then loop over all non-basic variables, but skip the entering column */ | ||||
|     for(i = 1; i <= lp->sum; i++) { | ||||
|       if(lp->is_basic[i] || (i == colnr)) | ||||
|         continue; | ||||
|       hold = vAlpha[i]; | ||||
|       if(hold == 0) | ||||
|         continue; | ||||
|       hold /= cAlpha; | ||||
|       if(fabs(hold) < lp->epsmachine) | ||||
|         continue; | ||||
| 
 | ||||
|       newEdge = &(lp->edgeVector[i]); | ||||
|       *newEdge += (hold*hold) * cEdge; | ||||
|       if(isDEVEX) { | ||||
|         if((*newEdge) > DEVEX_RESTARTLIMIT) { | ||||
|           forceRefresh = TRUE; | ||||
|           break; | ||||
|         } | ||||
|       } | ||||
|       else { | ||||
|         *newEdge -= 2*hold*vEdge[i]; | ||||
| #ifdef ApplySteepestEdgeMinimum | ||||
|         SETMAX(*newEdge, hold*hold+1); | ||||
| #else | ||||
|         if(*newEdge < 0) { | ||||
|           report(lp, errlevel, "updatePricer: Invalid primal norm %g at index %d - iteration %.0f\n", | ||||
|                                *newEdge, i, (double) (lp->total_iter+lp->current_iter)); | ||||
|           if(lp->spx_trace) | ||||
|             report(lp, errlevel, "Error detail: (RelAlpha=%g, vEdge=%g, cEdge=%g)\n", hold, vEdge[i], cEdge); | ||||
|           forceRefresh = TRUE; | ||||
|           break; | ||||
|         } | ||||
| #endif | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
| Finish1: | ||||
|     FREE(vAlpha); | ||||
|     FREE(vTemp); | ||||
| 
 | ||||
|   } | ||||
| 
 | ||||
| Finish2: | ||||
|   FREE(vEdge); | ||||
|   freeWeights(w); | ||||
| 
 | ||||
|   if(forceRefresh) | ||||
|     ok = restartPricer(lp, AUTOMATIC); | ||||
|   else | ||||
|     ok = TRUE; | ||||
| 
 | ||||
|   return( ok ); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| STATIC MYBOOL verifyPricer(lprec *lp) | ||||
| { | ||||
|   REAL value; | ||||
|   int  i, n; | ||||
|   MYBOOL ok = applyPricer(lp); | ||||
| 
 | ||||
|   if(!ok) | ||||
|     return( ok ); | ||||
|   ok = FALSE; | ||||
| 
 | ||||
|   /* Verify */ | ||||
|   if(lp->edgeVector == NULL) | ||||
|     return( ok ); | ||||
|   value = *lp->edgeVector; | ||||
|   if(value < 0) | ||||
|     return( ok ); | ||||
| 
 | ||||
|   /* Check the primal */ | ||||
|   n = 1; | ||||
|   if(value == 0) { | ||||
| 
 | ||||
|     for(n = lp->sum; n > 0; n--) { | ||||
|       if(lp->is_basic[n]) | ||||
|         continue; | ||||
|       value = lp->edgeVector[n]; | ||||
|       if(value <= 0) | ||||
|         break; | ||||
|     } | ||||
|   } | ||||
|   /* Check the dual */ | ||||
|   else { | ||||
|     for(i = lp->rows; i > 0; i--) { | ||||
|       n = lp->var_basic[i]; | ||||
|       value = lp->edgeVector[n]; | ||||
|       if(value <= 0) | ||||
|         break; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   ok = (MYBOOL) (n == 0); | ||||
| #ifdef Paranoia | ||||
|   if(!ok) | ||||
|     report(lp, SEVERE, "verifyPricer: Invalid norm %g at index %d\n", | ||||
|                        value, n); | ||||
| #endif | ||||
|   return( ok ); | ||||
| } | ||||
| 
 | ||||
|  | @ -1,28 +0,0 @@ | |||
| #ifndef HEADER_lp_pricePSE | ||||
| #define HEADER_lp_pricePSE | ||||
| 
 | ||||
| #include "lp_types.h" | ||||
| 
 | ||||
| #define ApplySteepestEdgeMinimum | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| /* Price norm management routines */ | ||||
| STATIC MYBOOL initPricer(lprec *lp); | ||||
| INLINE MYBOOL applyPricer(lprec *lp); | ||||
| STATIC void simplexPricer(lprec *lp, MYBOOL isdual); | ||||
| STATIC void freePricer(lprec *lp); | ||||
| STATIC MYBOOL resizePricer(lprec *lp); | ||||
| STATIC REAL getPricer(lprec *lp, int item, MYBOOL isdual); | ||||
| STATIC MYBOOL restartPricer(lprec *lp, MYBOOL isdual); | ||||
| STATIC MYBOOL updatePricer(lprec *lp, int rownr, int colnr, REAL *pcol, REAL *prow, int *nzprow); | ||||
| STATIC MYBOOL verifyPricer(lprec *lp); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
|  } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* HEADER_lp_pricePSE */ | ||||
| 
 | ||||
|  | @ -1,789 +0,0 @@ | |||
| 
 | ||||
| /*
 | ||||
|     Mixed integer programming optimization drivers for lp_solve v5.0+ | ||||
|    ---------------------------------------------------------------------------------- | ||||
|     Author:        Michel Berkelaar (to lp_solve v3.2), | ||||
|                    Kjell Eikland | ||||
|     Contact: | ||||
|     License terms: LGPL. | ||||
| 
 | ||||
|     Requires:      stdarg.h, lp_lib.h | ||||
| 
 | ||||
|     Release notes: | ||||
|     v5.0.0 3   1 January 2004      New unit isolating reporting routines. | ||||
|     v5.2.0.0   1 December 2005     Addition of Matrix Market writing function. | ||||
| 
 | ||||
|    ---------------------------------------------------------------------------------- | ||||
| */ | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <stdarg.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| #include "lp_lib.h" | ||||
| #include "lp_scale.h" | ||||
| #include "commonlib.h" | ||||
| #include "lp_report.h" | ||||
| 
 | ||||
| #include "mmio.h" | ||||
| 
 | ||||
| #ifdef FORTIFY | ||||
| # include "lp_fortify.h" | ||||
| #endif | ||||
| 
 | ||||
| /* Define buffer-size controled function mapping */ | ||||
| # if defined _MSC_VER | ||||
| #  define vsnprintf _vsnprintf | ||||
| # endif | ||||
| 
 | ||||
| /* Various reporting functions for lp_solve                                  */ | ||||
| /* ------------------------------------------------------------------------- */ | ||||
| 
 | ||||
| /* First define general utilties for reporting and output */ | ||||
| char * __VACALL explain(lprec *lp, char *format, ...) | ||||
| { | ||||
|   char buff[DEF_STRBUFSIZE+1]; | ||||
|   va_list ap; | ||||
| 
 | ||||
|   va_start(ap, format); | ||||
|     vsnprintf(buff, DEF_STRBUFSIZE, format, ap); | ||||
|     allocCHAR(lp, &(lp->ex_status), (int) strlen(buff), AUTOMATIC); | ||||
|     strcpy(lp->ex_status, buff); | ||||
|   va_end(ap); | ||||
|   return( lp->ex_status ); | ||||
| } | ||||
| void __VACALL report(lprec *lp, int level, char *format, ...) | ||||
| { | ||||
|   static char buff[DEF_STRBUFSIZE+1]; | ||||
|   static va_list ap; | ||||
| 
 | ||||
|   if(lp == NULL) { | ||||
|     va_start(ap, format); | ||||
|       vfprintf(stderr, format, ap); | ||||
|     va_end(ap); | ||||
|   } | ||||
|   else if(level <= lp->verbose) { | ||||
|     va_start(ap, format); | ||||
|     if(lp->writelog != NULL) { | ||||
|       vsnprintf(buff, DEF_STRBUFSIZE, format, ap); | ||||
|       lp->writelog(lp, lp->loghandle, buff); | ||||
|     } | ||||
|     if(lp->outstream != NULL) { | ||||
|       vfprintf(lp->outstream, format, ap); | ||||
|       if(lp->outstream != stdout) | ||||
|         fflush(lp->outstream); | ||||
|     } | ||||
|     va_end(ap); | ||||
|   } | ||||
| #ifdef xParanoia | ||||
|   if(level == CRITICAL) | ||||
|     raise(SIGSEGV); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| STATIC void print_indent(lprec *lp) | ||||
| { | ||||
|   int i; | ||||
| 
 | ||||
|   report(lp, NEUTRAL, "%2d", lp->bb_level); | ||||
|   if(lp->bb_level < 50) /* useless otherwise */ | ||||
|     for(i = lp->bb_level; i > 0; i--) | ||||
|       report(lp, NEUTRAL, "--"); | ||||
|   else | ||||
|     report(lp, NEUTRAL, " *** too deep ***"); | ||||
|   report(lp, NEUTRAL, "> "); | ||||
| } /* print_indent */ | ||||
| 
 | ||||
| STATIC void debug_print(lprec *lp, char *format, ...) | ||||
| { | ||||
|   va_list ap; | ||||
| 
 | ||||
|   if(lp->bb_trace) { | ||||
|     print_indent(lp); | ||||
|     va_start(ap, format); | ||||
|     if (lp == NULL) | ||||
|     { | ||||
|       vfprintf(stderr, format, ap); | ||||
|       fputc('\n', stderr); | ||||
|     } | ||||
|     else if(lp->debuginfo != NULL) | ||||
|     { | ||||
|       char buff[DEF_STRBUFSIZE+1]; | ||||
|       vsnprintf(buff, DEF_STRBUFSIZE, format, ap); | ||||
|       lp->debuginfo(lp, lp->loghandle, buff); | ||||
|     } | ||||
|     va_end(ap); | ||||
|   } | ||||
| } /* debug_print */ | ||||
| 
 | ||||
| STATIC void debug_print_solution(lprec *lp) | ||||
| { | ||||
|   int i; | ||||
| 
 | ||||
|   if(lp->bb_trace) | ||||
|     for (i = lp->rows + 1; i <= lp->sum; i++) { | ||||
|       print_indent(lp); | ||||
|       report(lp, NEUTRAL, "%s " RESULTVALUEMASK "\n", | ||||
|                  get_col_name(lp, i - lp->rows), | ||||
|                 (double)lp->solution[i]); | ||||
|     } | ||||
| } /* debug_print_solution */ | ||||
| 
 | ||||
| STATIC void debug_print_bounds(lprec *lp, REAL *upbo, REAL *lowbo) | ||||
| { | ||||
|   int i; | ||||
| 
 | ||||
|   if(lp->bb_trace) | ||||
|     for(i = lp->rows + 1; i <= lp->sum; i++) { | ||||
|       if(lowbo[i] == upbo[i]) { | ||||
|         print_indent(lp); | ||||
|         report(lp, NEUTRAL, "%s = " RESULTVALUEMASK "\n", get_col_name(lp, i - lp->rows), | ||||
|                              (double)lowbo[i]); | ||||
|       } | ||||
|       else { | ||||
|         if(lowbo[i] != 0) { | ||||
|           print_indent(lp); | ||||
|           report(lp, NEUTRAL, "%s > " RESULTVALUEMASK "\n", get_col_name(lp, i - lp->rows), | ||||
|                                (double)lowbo[i]); | ||||
|         } | ||||
|         if(upbo[i] != lp->infinite) { | ||||
|           print_indent(lp); | ||||
|           report(lp, NEUTRAL, "%s < " RESULTVALUEMASK "\n", get_col_name(lp, i - lp->rows), | ||||
|                                (double)upbo[i]); | ||||
|     } | ||||
|       } | ||||
|     } | ||||
| } /* debug_print_bounds */ | ||||
| 
 | ||||
| /* List a vector of LREAL values for the given index range */ | ||||
| void blockWriteLREAL(FILE *output, char *label, LREAL *vector, int first, int last) | ||||
| { | ||||
|   int i, k = 0; | ||||
| 
 | ||||
|   fprintf(output, label); | ||||
|   fprintf(output, "\n"); | ||||
|   for(i = first; i <= last; i++) { | ||||
|     fprintf(output, " %18g", vector[i]); | ||||
|     k++; | ||||
|     if(my_mod(k, 4) == 0) { | ||||
|       fprintf(output, "\n"); | ||||
|       k = 0; | ||||
|     } | ||||
|   } | ||||
|   if(my_mod(k, 4) != 0) | ||||
|     fprintf(output, "\n"); | ||||
| } | ||||
| 
 | ||||
| /* List the current user data matrix columns over the selected row range */ | ||||
| void blockWriteAMAT(FILE *output, const char *label, lprec* lp, int first, int last) | ||||
| { | ||||
|   int    i, j, k = 0; | ||||
|   int    nzb, nze, jb; | ||||
|   double hold; | ||||
|   MATrec *mat = lp->matA; | ||||
| 
 | ||||
|   if(!mat_validate(mat)) | ||||
|     return; | ||||
|   if(first < 0) | ||||
|     first = 0; | ||||
|   if(last < 0) | ||||
|     last = lp->rows; | ||||
| 
 | ||||
|   fprintf(output, label); | ||||
|   fprintf(output, "\n"); | ||||
| 
 | ||||
|   if(first == 0) { | ||||
|     for(j = 1; j <= lp->columns; j++) { | ||||
|       hold = get_mat(lp, 0, j); | ||||
|       fprintf(output, " %18g", hold); | ||||
|       k++; | ||||
|       if(my_mod(k, 4) == 0) { | ||||
|         fprintf(output, "\n"); | ||||
|         k = 0; | ||||
|       } | ||||
|     } | ||||
|     if(my_mod(k, 4) != 0) { | ||||
|       fprintf(output, "\n"); | ||||
|       k = 0; | ||||
|     } | ||||
|     first++; | ||||
|   } | ||||
|   nze = mat->row_end[first-1]; | ||||
|   for(i = first; i <= last; i++) { | ||||
|     nzb = nze; | ||||
|     nze = mat->row_end[i]; | ||||
|     if(nzb >= nze) | ||||
|       jb = lp->columns+1; | ||||
|     else | ||||
|       jb = ROW_MAT_COLNR(nzb); | ||||
|     for(j = 1; j <= lp->columns; j++) { | ||||
|       if(j < jb) | ||||
|         hold = 0; | ||||
|       else { | ||||
|         hold = get_mat(lp, i, j); | ||||
|         nzb++; | ||||
|         if(nzb < nze) | ||||
|           jb = ROW_MAT_COLNR(nzb); | ||||
|         else | ||||
|           jb = lp->columns+1; | ||||
|       } | ||||
|       fprintf(output, " %18g", hold); | ||||
|       k++; | ||||
|       if(my_mod(k, 4) == 0) { | ||||
|         fprintf(output, "\n"); | ||||
|         k = 0; | ||||
|       } | ||||
|     } | ||||
|     if(my_mod(k, 4) != 0) { | ||||
|       fprintf(output, "\n"); | ||||
|       k = 0; | ||||
|     } | ||||
|   } | ||||
|   if(my_mod(k, 4) != 0) | ||||
|     fprintf(output, "\n"); | ||||
| } | ||||
| 
 | ||||
| /* List the current basis matrix columns over the selected row range */ | ||||
| void blockWriteBMAT(FILE *output, const char *label, lprec* lp, int first, int last) | ||||
| { | ||||
|   int    i, j, jb, k = 0; | ||||
|   double hold; | ||||
| 
 | ||||
|   if(first < 0) | ||||
|     first = 0; | ||||
|   if(last < 0) | ||||
|     last = lp->rows; | ||||
| 
 | ||||
|   fprintf(output, label); | ||||
|   fprintf(output, "\n"); | ||||
| 
 | ||||
|   for(i = first; i <= last; i++) { | ||||
|     for(j = 1; j <= lp->rows; j++) { | ||||
|       jb = lp->var_basic[j]; | ||||
|       if(jb <= lp->rows) { | ||||
|         if(jb == i) | ||||
|           hold = 1; | ||||
|         else | ||||
|           hold = 0; | ||||
|       } | ||||
|       else | ||||
|         hold = get_mat(lp, i, j); | ||||
|       if(i == 0) | ||||
|         modifyOF1(lp, jb, &hold, 1); | ||||
|       hold = unscaled_mat(lp, hold, i, jb); | ||||
|       fprintf(output, " %18g", hold); | ||||
|       k++; | ||||
|       if(my_mod(k, 4) == 0) { | ||||
|         fprintf(output, "\n"); | ||||
|         k = 0; | ||||
|       } | ||||
|     } | ||||
|     if(my_mod(k, 4) != 0) { | ||||
|       fprintf(output, "\n"); | ||||
|       k = 0; | ||||
|     } | ||||
|   } | ||||
|   if(my_mod(k, 4) != 0) | ||||
|     fprintf(output, "\n"); | ||||
| } | ||||
| 
 | ||||
| /* Do a generic readable data dump of key lp_solve model variables;
 | ||||
|    principally for run difference and debugging purposes */ | ||||
| MYBOOL REPORT_debugdump(lprec *lp, char *filename, MYBOOL livedata) | ||||
| { | ||||
|   FILE   *output = stdout; | ||||
|   MYBOOL ok; | ||||
| 
 | ||||
|   ok = (MYBOOL) ((filename == NULL) || ((output = fopen(filename,"w")) != NULL)); | ||||
|   if(!ok) | ||||
|     return(ok); | ||||
|   if((filename == NULL) && (lp->outstream != NULL)) | ||||
|     output = lp->outstream; | ||||
| 
 | ||||
|   fprintf(output, "\nGENERAL INFORMATION\n-------------------\n\n"); | ||||
|   fprintf(output, "Model size:     %d rows (%d equalities, %d Lagrangean), %d columns (%d integers, %d SC, %d SOS, %d GUB)\n", | ||||
|                   lp->rows, lp->equalities, get_Lrows(lp), lp->columns, | ||||
|       lp->int_vars, lp->sc_vars, SOS_count(lp), GUB_count(lp)); | ||||
|   fprintf(output, "Data size:      %d model non-zeros, %d invB non-zeros (engine is %s)\n", | ||||
|                   get_nonzeros(lp), my_if(lp->invB == NULL, 0, lp->bfp_nonzeros(lp, FALSE)), lp->bfp_name()); | ||||
|   fprintf(output, "Internal sizes: %d rows allocated, %d columns allocated, %d columns used, %d eta length\n", | ||||
|                   lp->rows_alloc, lp->columns_alloc, lp->columns, my_if(lp->invB == NULL, 0, lp->bfp_colcount(lp))); | ||||
|   fprintf(output, "Memory use:     %d sparse matrix, %d eta\n", | ||||
|                   lp->matA->mat_alloc, my_if(lp->invB == NULL, 0, lp->bfp_memallocated(lp))); | ||||
|   fprintf(output, "Parameters:     Maximize=%d, Names used=%d, Scalingmode=%d, Presolve=%d, SimplexPivot=%d\n", | ||||
|                   is_maxim(lp), lp->names_used, lp->scalemode, lp->do_presolve, lp->piv_strategy); | ||||
|   fprintf(output, "Precision:      EpsValue=%g, EpsPrimal=%g, EpsDual=%g, EpsPivot=%g, EpsPerturb=%g\n", | ||||
|                   lp->epsvalue, lp->epsprimal, lp->epsdual, lp->epspivot, lp->epsperturb); | ||||
|   fprintf(output, "Stability:      AntiDegen=%d, Improvement=%d, Split variables at=%g\n", | ||||
|                   lp->improve, lp->anti_degen, lp->negrange); | ||||
|   fprintf(output, "B&B settings:   BB pivot rule=%d, BB branching=%s, BB strategy=%d, Integer precision=%g, MIP gaps=%g,%g\n", | ||||
|                   lp->bb_rule, my_boolstr(lp->bb_varbranch), lp->bb_floorfirst, lp->epsint, lp->mip_absgap, lp->mip_relgap); | ||||
| 
 | ||||
|   fprintf(output, "\nCORE DATA\n---------\n\n"); | ||||
|   blockWriteINT(output,  "Column starts", lp->matA->col_end, 0, lp->columns); | ||||
|   blockWriteINT(output,  "row_type", lp->row_type, 0, lp->rows); | ||||
|   blockWriteREAL(output, "orig_rhs", lp->orig_rhs, 0, lp->rows); | ||||
|   blockWriteREAL(output, "orig_lowbo", lp->orig_lowbo, 0, lp->sum); | ||||
|   blockWriteREAL(output, "orig_upbo", lp->orig_upbo, 0, lp->sum); | ||||
|   blockWriteINT(output,  "row_type", lp->row_type, 0, lp->rows); | ||||
|   blockWriteBOOL(output, "var_type", lp->var_type, 0, lp->columns, TRUE); | ||||
|   blockWriteAMAT(output, "A", lp, 0, lp->rows); | ||||
| 
 | ||||
|   if(livedata) { | ||||
|     fprintf(output, "\nPROCESS DATA\n------------\n\n"); | ||||
|     blockWriteREAL(output,  "Active rhs", lp->rhs, 0, lp->rows); | ||||
|     blockWriteINT(output,  "Basic variables", lp->var_basic, 0, lp->rows); | ||||
|     blockWriteBOOL(output, "is_basic", lp->is_basic, 0, lp->sum, TRUE); | ||||
|     blockWriteREAL(output, "lowbo", lp->lowbo, 0, lp->sum); | ||||
|     blockWriteREAL(output, "upbo", lp->upbo, 0, lp->sum); | ||||
|     if(lp->scalars != NULL) | ||||
|       blockWriteREAL(output, "scalars", lp->scalars, 0, lp->sum); | ||||
|   } | ||||
| 
 | ||||
|   if(filename != NULL) | ||||
|     fclose(output); | ||||
|   return(ok); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* High level reports for model results */ | ||||
| 
 | ||||
| void REPORT_objective(lprec *lp) | ||||
| { | ||||
|   if(lp->outstream == NULL) | ||||
|     return; | ||||
|   fprintf(lp->outstream, "\nValue of objective function: %g\n", | ||||
|     (double)lp->best_solution[0]); | ||||
|   fflush(lp->outstream); | ||||
| } | ||||
| 
 | ||||
| void REPORT_solution(lprec *lp, int columns) | ||||
| { | ||||
|   int i, j, n; | ||||
|   REAL value; | ||||
|   presolveundorec *psundo = lp->presolve_undo; | ||||
|   MYBOOL NZonly = (MYBOOL) ((lp->print_sol & AUTOMATIC) > 0); | ||||
| 
 | ||||
|   if(lp->outstream == NULL) | ||||
|     return; | ||||
| 
 | ||||
|   fprintf(lp->outstream, "\nActual values of the variables:\n"); | ||||
|   if(columns <= 0) | ||||
|     columns = 2; | ||||
|   n = 0; | ||||
|   for(i = 1; i <= psundo->orig_columns; i++) { | ||||
|     j = psundo->orig_rows + i; | ||||
|     value = get_var_primalresult(lp, j); | ||||
|     if(NZonly && (fabs(value) < lp->epsprimal)) | ||||
|       continue; | ||||
|     n = (n+1) % columns; | ||||
|     fprintf(lp->outstream, "%-20s %12g", get_origcol_name(lp, i), (double) value); | ||||
|     if(n == 0) | ||||
|       fprintf(lp->outstream, "\n"); | ||||
|     else | ||||
|       fprintf(lp->outstream, "       "); | ||||
|   } | ||||
| 
 | ||||
|   fflush(lp->outstream); | ||||
| } /* REPORT_solution */ | ||||
| 
 | ||||
| void REPORT_constraints(lprec *lp, int columns) | ||||
| { | ||||
|   int i, n; | ||||
|   REAL value; | ||||
|   MYBOOL NZonly = (MYBOOL) ((lp->print_sol & AUTOMATIC) > 0); | ||||
| 
 | ||||
|   if(lp->outstream == NULL) | ||||
|     return; | ||||
| 
 | ||||
|   if(columns <= 0) | ||||
|     columns = 2; | ||||
| 
 | ||||
|   fprintf(lp->outstream, "\nActual values of the constraints:\n"); | ||||
|   n = 0; | ||||
|   for(i = 1; i <= lp->rows; i++) { | ||||
|     value = (double)lp->best_solution[i]; | ||||
|     if(NZonly && (fabs(value) < lp->epsprimal)) | ||||
|       continue; | ||||
|     n = (n+1) % columns; | ||||
|     fprintf(lp->outstream, "%-20s %12g", get_row_name(lp, i), value); | ||||
|     if(n == 0) | ||||
|       fprintf(lp->outstream, "\n"); | ||||
|     else | ||||
|       fprintf(lp->outstream, "       "); | ||||
|   } | ||||
| 
 | ||||
|   fflush(lp->outstream); | ||||
| } | ||||
| 
 | ||||
| void REPORT_duals(lprec *lp) | ||||
| { | ||||
|   int i; | ||||
|   REAL *duals, *dualsfrom, *dualstill, *objfrom, *objtill, *objfromvalue; | ||||
|   MYBOOL ret; | ||||
| 
 | ||||
|   if(lp->outstream == NULL) | ||||
|     return; | ||||
| 
 | ||||
|   ret = get_ptr_sensitivity_objex(lp, &objfrom, &objtill, &objfromvalue, NULL); | ||||
|   if(ret) { | ||||
|     fprintf(lp->outstream, "\nObjective function limits:\n"); | ||||
|     fprintf(lp->outstream, "                                 From            Till       FromValue\n"); | ||||
|     for(i = 1; i <= lp->columns; i++) | ||||
|       if(!is_splitvar(lp, i)) | ||||
|         fprintf(lp->outstream, "%-20s  %15.7g %15.7g %15.7g\n", get_col_name(lp, i), | ||||
|          (double)objfrom[i - 1], (double)objtill[i - 1], (double)objfromvalue[i - 1]); | ||||
|   } | ||||
| 
 | ||||
|   ret = get_ptr_sensitivity_rhs(lp, &duals, &dualsfrom, &dualstill); | ||||
|   if(ret) { | ||||
|     fprintf(lp->outstream, "\nDual values with from - till limits:\n"); | ||||
|     fprintf(lp->outstream, "                           Dual value            From            Till\n"); | ||||
|     for(i = 1; i <= lp->sum; i++) | ||||
|       fprintf(lp->outstream, "%-20s  %15.7g %15.7g %15.7g\n", | ||||
|               (i <= lp->rows) ? get_row_name(lp, i) : get_col_name(lp, i - lp->rows), | ||||
|               (double)duals[i - 1], (double)dualsfrom[i - 1], (double)dualstill[i - 1]); | ||||
|     fflush(lp->outstream); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /* Printing of sensitivity analysis reports */ | ||||
| void REPORT_extended(lprec *lp) | ||||
| { | ||||
|   int  i, j; | ||||
|   REAL hold; | ||||
|   REAL *duals, *dualsfrom, *dualstill, *objfrom, *objtill; | ||||
|   MYBOOL ret; | ||||
| 
 | ||||
|   ret = get_ptr_sensitivity_obj(lp, &objfrom, &objtill); | ||||
|   report(lp, NORMAL, " \n"); | ||||
|   report(lp, NORMAL, "Primal objective:\n"); | ||||
|   report(lp, NORMAL, " \n"); | ||||
|   report(lp, NORMAL, "  Column name                      Value   Objective         Min         Max\n"); | ||||
|   report(lp, NORMAL, "  --------------------------------------------------------------------------\n"); | ||||
|   for(j = 1; j <= lp->columns; j++) { | ||||
|     hold = get_mat(lp,0,j); | ||||
|     report(lp, NORMAL, "  %-25s " MPSVALUEMASK MPSVALUEMASK MPSVALUEMASK MPSVALUEMASK "\n", | ||||
|            get_col_name(lp,j), | ||||
|            my_precision(hold,lp->epsprimal), | ||||
|            my_precision(hold*lp->best_solution[lp->rows+j],lp->epsprimal), | ||||
|            my_precision((ret) ? objfrom[j - 1] : 0.0,lp->epsprimal), | ||||
|            my_precision((ret) ? objtill[j - 1] : 0.0,lp->epsprimal)); | ||||
|   } | ||||
|   report(lp, NORMAL, " \n"); | ||||
| 
 | ||||
|   ret = get_ptr_sensitivity_rhs(lp, &duals, &dualsfrom, &dualstill); | ||||
|   report(lp, NORMAL, "Primal variables:\n"); | ||||
|   report(lp, NORMAL, " \n"); | ||||
|   report(lp, NORMAL, "  Column name                      Value       Slack         Min         Max\n"); | ||||
|   report(lp, NORMAL, "  --------------------------------------------------------------------------\n"); | ||||
|   for(j = 1; j <= lp->columns; j++) | ||||
|     report(lp, NORMAL, "  %-25s " MPSVALUEMASK MPSVALUEMASK MPSVALUEMASK MPSVALUEMASK "\n", | ||||
|            get_col_name(lp,j), | ||||
|            my_precision(lp->best_solution[lp->rows+j],lp->epsprimal), | ||||
|            my_precision(my_inflimit(lp, (ret) ? duals[lp->rows+j-1] : 0.0),lp->epsprimal), | ||||
|            my_precision((ret) ? dualsfrom[lp->rows+j-1] : 0.0,lp->epsprimal), | ||||
|            my_precision((ret) ? dualstill[lp->rows+j-1] : 0.0,lp->epsprimal)); | ||||
| 
 | ||||
|   report(lp, NORMAL, " \n"); | ||||
|   report(lp, NORMAL, "Dual variables:\n"); | ||||
|   report(lp, NORMAL, " \n"); | ||||
|   report(lp, NORMAL, "  Row name                         Value       Slack         Min         Max\n"); | ||||
|   report(lp, NORMAL, "  --------------------------------------------------------------------------\n"); | ||||
|   for(i = 1; i <= lp->rows; i++) | ||||
|     report(lp, NORMAL, "  %-25s " MPSVALUEMASK MPSVALUEMASK MPSVALUEMASK MPSVALUEMASK "\n", | ||||
|            get_row_name(lp,i), | ||||
|            my_precision((ret) ? duals[i - 1] : 0.0, lp->epsprimal), | ||||
|            my_precision(lp->best_solution[i], lp->epsprimal), | ||||
|            my_precision((ret) ? dualsfrom[i - 1] : 0.0,lp->epsprimal), | ||||
|            my_precision((ret) ? dualstill[i - 1] : 0.0,lp->epsprimal)); | ||||
| 
 | ||||
|   report(lp, NORMAL, " \n"); | ||||
| } | ||||
| 
 | ||||
| /* A more readable lp-format report of the model; antiquated and not updated */ | ||||
| void REPORT_lp(lprec *lp) | ||||
| { | ||||
|   int  i, j; | ||||
| 
 | ||||
|   if(lp->outstream == NULL) | ||||
|     return; | ||||
| 
 | ||||
|   if(lp->matA->is_roworder) { | ||||
|     report(lp, IMPORTANT, "REPORT_lp: Cannot print lp while in row entry mode.\n"); | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   fprintf(lp->outstream, "Model name: %s\n", get_lp_name(lp)); | ||||
|   fprintf(lp->outstream, "          "); | ||||
| 
 | ||||
|   for(j = 1; j <= lp->columns; j++) | ||||
|     fprintf(lp->outstream, "%8s ", get_col_name(lp,j)); | ||||
| 
 | ||||
|   fprintf(lp->outstream, "\n%simize  ", (is_maxim(lp) ? "Max" : "Min")); | ||||
|   for(j = 1; j <= lp->columns; j++) | ||||
|       fprintf(lp->outstream, "%8g ", get_mat(lp, 0, j)); | ||||
|   fprintf(lp->outstream, "\n"); | ||||
| 
 | ||||
|   for(i = 1; i <= lp->rows; i++) { | ||||
|     fprintf(lp->outstream, "%-9s ", get_row_name(lp, i)); | ||||
|     for(j = 1; j <= lp->columns; j++) | ||||
|       fprintf(lp->outstream, "%8g ", get_mat(lp, i, j)); | ||||
|     if(is_constr_type(lp, i, GE)) | ||||
|       fprintf(lp->outstream, ">= "); | ||||
|     else if(is_constr_type(lp, i, LE)) | ||||
|       fprintf(lp->outstream, "<= "); | ||||
|     else | ||||
|       fprintf(lp->outstream, " = "); | ||||
|     fprintf(lp->outstream, "%8g", get_rh(lp, i)); | ||||
| 
 | ||||
|     if(is_constr_type(lp, i, GE)) { | ||||
|       if(get_rh_upper(lp, i) < lp->infinite) | ||||
|         fprintf(lp->outstream, "  %s = %8g", "upbo", get_rh_upper(lp, i)); | ||||
|     } | ||||
|     else if(is_constr_type(lp, i, LE)) { | ||||
|       if(get_rh_lower(lp, i) > -lp->infinite) | ||||
|         fprintf(lp->outstream, "  %s = %8g", "lowbo", get_rh_lower(lp, i)); | ||||
|     } | ||||
|     fprintf(lp->outstream, "\n"); | ||||
|   } | ||||
| 
 | ||||
|   fprintf(lp->outstream, "Type      "); | ||||
|   for(i = 1; i <= lp->columns; i++) { | ||||
|     if(is_int(lp,i)) | ||||
|       fprintf(lp->outstream, "     Int "); | ||||
|     else | ||||
|       fprintf(lp->outstream, "    Real "); | ||||
|   } | ||||
| 
 | ||||
|   fprintf(lp->outstream, "\nupbo      "); | ||||
|   for(i = 1; i <= lp->columns; i++) | ||||
|     if(get_upbo(lp, i) >= lp->infinite) | ||||
|       fprintf(lp->outstream, "     Inf "); | ||||
|     else | ||||
|       fprintf(lp->outstream, "%8g ", get_upbo(lp, i)); | ||||
|   fprintf(lp->outstream, "\nlowbo     "); | ||||
|   for(i = 1; i <= lp->columns; i++) | ||||
|     if(get_lowbo(lp, i) <= -lp->infinite) | ||||
|       fprintf(lp->outstream, "    -Inf "); | ||||
|     else | ||||
|       fprintf(lp->outstream, "%8g ", get_lowbo(lp, i)); | ||||
|   fprintf(lp->outstream, "\n"); | ||||
| 
 | ||||
|   fflush(lp->outstream); | ||||
| } | ||||
| 
 | ||||
| /* Report the scaling factors used; extremely rarely used */ | ||||
| void REPORT_scales(lprec *lp) | ||||
| { | ||||
|   int i, colMax; | ||||
| 
 | ||||
|   colMax = lp->columns; | ||||
| 
 | ||||
|   if(lp->outstream == NULL) | ||||
|     return; | ||||
| 
 | ||||
|   if(lp->scaling_used) { | ||||
|     fprintf(lp->outstream, "\nScale factors:\n"); | ||||
|     for(i = 0; i <= lp->rows + colMax; i++) | ||||
|       fprintf(lp->outstream, "%-20s scaled at %g\n", | ||||
|               (i <= lp->rows) ? get_row_name(lp, i) : get_col_name(lp, i - lp->rows), | ||||
|         (double)lp->scalars[i]); | ||||
|   } | ||||
|   fflush(lp->outstream); | ||||
| } | ||||
| 
 | ||||
| /* Report the traditional tableau corresponding to the current basis */ | ||||
| MYBOOL REPORT_tableau(lprec *lp) | ||||
| { | ||||
|   int  j, row_nr, *coltarget; | ||||
|   REAL *prow = NULL; | ||||
|   FILE *stream = lp->outstream; | ||||
| 
 | ||||
|   if(lp->outstream == NULL) | ||||
|     return(FALSE); | ||||
| 
 | ||||
|   if(!lp->model_is_valid || !has_BFP(lp) || | ||||
|      (get_total_iter(lp) == 0) || (lp->spx_status == NOTRUN)) { | ||||
|     lp->spx_status = NOTRUN; | ||||
|     return(FALSE); | ||||
|   } | ||||
|   if(!allocREAL(lp, &prow,lp->sum + 1, TRUE)) { | ||||
|     lp->spx_status = NOMEMORY; | ||||
|     return(FALSE); | ||||
|   } | ||||
| 
 | ||||
|   fprintf(stream, "\n"); | ||||
|   fprintf(stream, "Tableau at iter %.0f:\n", (double) get_total_iter(lp)); | ||||
| 
 | ||||
|   for(j = 1; j <= lp->sum; j++) | ||||
|     if (!lp->is_basic[j]) | ||||
|       fprintf(stream, "%15d", (j <= lp->rows ? | ||||
|                                (j + lp->columns) * ((lp->orig_upbo[j] == 0) || | ||||
|                                                     (is_chsign(lp, j)) ? 1 : -1) : j - lp->rows) * | ||||
|                               (lp->is_lower[j] ? 1 : -1)); | ||||
|   fprintf(stream, "\n"); | ||||
| 
 | ||||
|   coltarget = (int *) mempool_obtainVector(lp->workarrays, lp->columns+1, sizeof(*coltarget)); | ||||
|   if(!get_colIndexA(lp, SCAN_USERVARS+USE_NONBASICVARS, coltarget, FALSE)) { | ||||
|     mempool_releaseVector(lp->workarrays, (char *) coltarget, FALSE); | ||||
|     return(FALSE); | ||||
|   } | ||||
|   for(row_nr = 1; (row_nr <= lp->rows + 1); row_nr++) { | ||||
|     if (row_nr <= lp->rows) | ||||
|       fprintf(stream, "%3d", (lp->var_basic[row_nr] <= lp->rows ? | ||||
|                               (lp->var_basic[row_nr] + lp->columns) * ((lp->orig_upbo[lp->var_basic [row_nr]] == 0) || | ||||
|                                                                        (is_chsign(lp, lp->var_basic[row_nr])) ? 1 : -1) : lp->var_basic[row_nr] - lp->rows) * | ||||
|                              (lp->is_lower[lp->var_basic [row_nr]] ? 1 : -1)); | ||||
|     else | ||||
|       fprintf(stream, "   "); | ||||
|     bsolve(lp, row_nr <= lp->rows ? row_nr : 0, prow, NULL, lp->epsmachine*DOUBLEROUND, 1.0); | ||||
|     prod_xA(lp, coltarget, prow, NULL, lp->epsmachine, 1.0, | ||||
|                                        prow, NULL, MAT_ROUNDDEFAULT); | ||||
| 
 | ||||
|     for(j = 1; j <= lp->rows + lp->columns; j++) | ||||
|       if (!lp->is_basic[j]) | ||||
|         fprintf(stream, "%15.7f", prow[j] * (lp->is_lower[j] ? 1 : -1) * | ||||
|                                             (row_nr <= lp->rows ? 1 : -1)); | ||||
|     fprintf(stream, "%15.7f", lp->rhs[row_nr <= lp->rows ? row_nr : 0] * | ||||
|                               (double) ((row_nr <= lp->rows) || (is_maxim(lp)) ? 1 : -1)); | ||||
|     fprintf(stream, "\n"); | ||||
|   } | ||||
|   fflush(stream); | ||||
| 
 | ||||
|   mempool_releaseVector(lp->workarrays, (char *) coltarget, FALSE); | ||||
|   FREE(prow); | ||||
|   return(TRUE); | ||||
| } | ||||
| 
 | ||||
| void REPORT_constraintinfo(lprec *lp, char *datainfo) | ||||
| { | ||||
|   int i, tally[ROWCLASS_MAX+1]; | ||||
| 
 | ||||
|   MEMCLEAR(tally, ROWCLASS_MAX+1); | ||||
|   for(i = 1; i <= lp->rows; i++) | ||||
|     tally[get_constr_class(lp, i)]++; | ||||
| 
 | ||||
|   if(datainfo != NULL) | ||||
|     report(lp, NORMAL, "%s\n", datainfo); | ||||
| 
 | ||||
|   for(i = 0; i <= ROWCLASS_MAX; i++) | ||||
|     if(tally[i] > 0) | ||||
|       report(lp, NORMAL, "%-15s %4d\n", get_str_constr_class(lp, i), tally[i]); | ||||
| } | ||||
| 
 | ||||
| void REPORT_modelinfo(lprec *lp, MYBOOL doName, char *datainfo) | ||||
| { | ||||
|   if(doName) { | ||||
|     report(lp, NORMAL, "\nModel name:  '%s' - run #%-5d\n", | ||||
|                        get_lp_name(lp), lp->solvecount); | ||||
|     report(lp, NORMAL, "Objective:   %simize(%s)\n", | ||||
|                        my_if(is_maxim(lp), "Max", "Min"), get_row_name(lp, 0)); | ||||
|     report(lp, NORMAL, " \n"); | ||||
|   } | ||||
|   if(datainfo != NULL) | ||||
|     report(lp, NORMAL, "%s\n", datainfo); | ||||
| 
 | ||||
|   report(lp, NORMAL, "Model size:  %7d constraints, %7d variables, %12d non-zeros.\n", | ||||
|          lp->rows, lp->columns, get_nonzeros(lp)); | ||||
|   if(GUB_count(lp)+SOS_count(lp) > 0) | ||||
|   report(lp, NORMAL, "Var-types:   %7d integer,     %7d semi-cont.,     %7d SOS.\n", | ||||
|          lp->int_vars, lp->sc_vars, lp->sos_vars); | ||||
|   report(lp, NORMAL, "Sets:                             %7d GUB,            %7d SOS.\n", | ||||
|                          GUB_count(lp), SOS_count(lp)); | ||||
| } | ||||
| 
 | ||||
| /* Save a matrix column subset to a MatrixMarket formatted file,
 | ||||
|    say to export the basis matrix for further numerical analysis. | ||||
|    If colndx is NULL, then the full constraint matrix is assumed. */ | ||||
| MYBOOL REPORT_mat_mmsave(lprec *lp, char *filename, int *colndx, MYBOOL includeOF, char *infotext) | ||||
| { | ||||
|   int         n, m, nz, i, j, k, kk; | ||||
|   MATrec      *mat = lp->matA; | ||||
|   MM_typecode matcode; | ||||
|   FILE        *output = stdout; | ||||
|   MYBOOL      ok; | ||||
|   REAL        *acol = NULL; | ||||
|   int         *nzlist = NULL; | ||||
| 
 | ||||
|   /* Open file */ | ||||
|   ok = (MYBOOL) ((filename == NULL) || ((output = fopen(filename,"w")) != NULL)); | ||||
|   if(!ok) | ||||
|     return(ok); | ||||
|   if((filename == NULL) && (lp->outstream != NULL)) | ||||
|     output = lp->outstream; | ||||
| 
 | ||||
|   /* Compute column and non-zero counts */ | ||||
|   if(colndx == lp->var_basic) { | ||||
|     if(!lp->basis_valid) | ||||
|       return( FALSE ); | ||||
|     m = lp->rows; | ||||
|   } | ||||
|   else if(colndx != NULL) | ||||
|     m = colndx[0]; | ||||
|   else | ||||
|     m = lp->columns; | ||||
|   n = lp->rows; | ||||
|   nz = 0; | ||||
| 
 | ||||
|   for(j = 1; j <= m; j++) { | ||||
|     k = (colndx == NULL ? n + j : colndx[j]); | ||||
|     if(k > n) { | ||||
|       k -= lp->rows; | ||||
|       nz += mat_collength(mat, k); | ||||
|       if(includeOF && is_OF_nz(lp, k)) | ||||
|         nz++; | ||||
|     } | ||||
|     else | ||||
|       nz++; | ||||
|   } | ||||
|   kk = 0; | ||||
|   if(includeOF) { | ||||
|     n++;   /* Row count */ | ||||
|     kk++;  /* Row index offset */ | ||||
|   } | ||||
| 
 | ||||
|   /* Initialize */ | ||||
|   mm_initialize_typecode(&matcode); | ||||
|   mm_set_matrix(&matcode); | ||||
|   mm_set_coordinate(&matcode); | ||||
|   mm_set_real(&matcode); | ||||
| 
 | ||||
|   mm_write_banner(output, matcode); | ||||
|   mm_write_mtx_crd_size(output, n+kk, m, nz+(colndx == lp->var_basic ? 1 : 0)); | ||||
| 
 | ||||
|   /* Allocate working arrays for sparse column storage */ | ||||
|   allocREAL(lp, &acol, n+2, FALSE); | ||||
|   allocINT(lp, &nzlist, n+2, FALSE); | ||||
| 
 | ||||
|   /* Write the matrix non-zero values column-by-column.
 | ||||
|      NOTE: matrixMarket files use 1-based indeces, | ||||
|      i.e. first row of a vector has index 1, not 0. */ | ||||
|   if(infotext != NULL) { | ||||
|     fprintf(output, "%%\n"); | ||||
|     fprintf(output, "%% %s\n", infotext); | ||||
|     fprintf(output, "%%\n"); | ||||
|   } | ||||
|   if(includeOF && (colndx == lp->var_basic)) | ||||
|     fprintf(output, "%d %d %g\n", 1, 1, 1.0); | ||||
|   for(j = 1; j <= m; j++) { | ||||
|     k = (colndx == NULL ? lp->rows + j : colndx[j]); | ||||
|     if(k == 0) | ||||
|       continue; | ||||
|     nz = obtain_column(lp, k, acol, nzlist, NULL); | ||||
|     for(i = 1; i <= nz; i++) { | ||||
|       if(!includeOF && (nzlist[i] == 0)) | ||||
|         continue; | ||||
|       fprintf(output, "%d %d %g\n", nzlist[i]+kk, j+kk, acol[i]); | ||||
|     } | ||||
|   } | ||||
|   fprintf(output, "%% End of MatrixMarket file\n"); | ||||
| 
 | ||||
|   /* Finish */ | ||||
|   FREE(acol); | ||||
|   FREE(nzlist); | ||||
|   fclose(output); | ||||
| 
 | ||||
|   return(ok); | ||||
| } | ||||
| 
 | ||||
|  | @ -1,42 +0,0 @@ | |||
| #ifndef HEADER_lp_report | ||||
| #define HEADER_lp_report | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| /* General information functions */ | ||||
| char * __VACALL explain(lprec *lp, char *format, ...); | ||||
| void __VACALL report(lprec *lp, int level, char *format, ...); | ||||
| 
 | ||||
| /* Prototypes for debugging and general data dumps */ | ||||
| void debug_print(lprec *lp, char *format, ...); | ||||
| void debug_print_solution(lprec *lp); | ||||
| void debug_print_bounds(lprec *lp, REAL *upbo, REAL *lowbo); | ||||
| void blockWriteLREAL(FILE *output, char *label, LREAL *vector, int first, int last); | ||||
| void blockWriteAMAT(FILE *output, const char *label, lprec* lp, int first, int last); | ||||
| void blockWriteBMAT(FILE *output, const char *label, lprec* lp, int first, int last); | ||||
| 
 | ||||
| 
 | ||||
| /* Model reporting headers */ | ||||
| void REPORT_objective(lprec *lp); | ||||
| void REPORT_solution(lprec *lp, int columns); | ||||
| void REPORT_constraints(lprec *lp, int columns); | ||||
| void REPORT_duals(lprec *lp); | ||||
| void REPORT_extended(lprec *lp); | ||||
| 
 | ||||
| /* Other rarely used, but sometimes extremely useful reports */ | ||||
| void REPORT_constraintinfo(lprec *lp, char *datainfo); | ||||
| void REPORT_modelinfo(lprec *lp, MYBOOL doName, char *datainfo); | ||||
| void REPORT_lp(lprec *lp); | ||||
| MYBOOL REPORT_tableau(lprec *lp); | ||||
| void REPORT_scales(lprec *lp); | ||||
| MYBOOL REPORT_debugdump(lprec *lp, char *filename, MYBOOL livedata); | ||||
| MYBOOL REPORT_mat_mmsave(lprec *lp, char *filename, int *colndx, MYBOOL includeOF, char *infotext); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
|  } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* HEADER_lp_report */ | ||||
| 
 | ||||
|  | @ -1,7 +0,0 @@ | |||
| flex -L -l lp_rlp.l | ||||
| sed -e "s/yy/lp_yy/g" lex.yy.c >lp_rlp.h | ||||
| del lex.yy.c | ||||
| 
 | ||||
| bison --no-lines -y lp_rlp.y | ||||
| sed -e "s/yy/lp_yy/g" y.tab.c >lp_rlp.c | ||||
| del y.tab.c | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -1,194 +0,0 @@ | |||
| WS   [ \r\n\t]+ | ||||
| LT   [A-Za-z] | ||||
| KR   [A-Za-z0-9_\[\]\{\}/.&#$%~'@^] | ||||
| DI   [0-9] | ||||
| INNM {DI}+ | ||||
| NM   (({DI}+\.?{DI}*)|(\.{DI}+))([Ee][-+]?{DI}+)? | ||||
| VR   {LT}{KR}*(<{KR}+>)? | ||||
| OPLE [<]?=? | ||||
| OPGE [>]=? | ||||
| EOW  $|[*+-;<=>]|{WS} | ||||
| INF  [ \r\n\t]*[-+][Ii][Nn][Ff]([Ii][Nn][Ii][Tt]([Ee]|[Yy]))?/{EOW} | ||||
| S_OP [-+ \t\n\r]+ | ||||
| MIN  [mM][iI][nN]([iI][mM][iI][zZsS][eE])?[ \t]*: | ||||
| MAX  [mM][aA][xX]([iI][mM][iI][zZsS][eE])?[ \t]*: | ||||
| INT  ^[ \t]*[Ii][Nn][Tt]([Ee][Gg][Ee][Rr])? | ||||
| BIN  ^[ \t]*[Bb][Ii][Nn]([Aa][Rr][Yy])? | ||||
| SEC  ^[ \t]*([Ss][Ee][Cc])|([Ss][Ee][Mm][Ii]-[Cc][Oo][Nn][Tt][Ii][Nn][Uu][Oo][Uu][Ss])|([Ss][Ee][Mm][Ii])|([Ss][Ee][Mm][Ii][Ss]) | ||||
| SOS  ^[ \t]*([Ss][Oo][Ss][12]*)|([Ss][Ee][Tt][Ss]) | ||||
| FREE ^[ \t]*[Ff][Rr][Ee][Ee] | ||||
| LBL  {VR}: | ||||
| SOSD {LBL}: | ||||
| 
 | ||||
| %start COMMENT | ||||
| %start LINECOMMENT | ||||
| 
 | ||||
| %% | ||||
| <INITIAL>"/*" { | ||||
|   BEGIN COMMENT; | ||||
| } /* begin skip comment */ | ||||
| 
 | ||||
| <COMMENT>"*/" { | ||||
|   BEGIN INITIAL; | ||||
| } /* end skip comment */ | ||||
| 
 | ||||
| <COMMENT>. { | ||||
| } | ||||
| 
 | ||||
| <COMMENT>\n { | ||||
| } | ||||
| 
 | ||||
| <COMMENT>\r { | ||||
| } | ||||
| 
 | ||||
| <INITIAL>"//" { | ||||
|   BEGIN LINECOMMENT; | ||||
| } /* begin skip LINECOMMENT */ | ||||
| 
 | ||||
| <LINECOMMENT>\n { | ||||
|   BEGIN INITIAL; | ||||
| } /* end skip LINECOMMENT */ | ||||
| 
 | ||||
| <LINECOMMENT>\r { | ||||
|   BEGIN INITIAL; | ||||
| } /* end skip LINECOMMENT */ | ||||
| 
 | ||||
| <LINECOMMENT>. { | ||||
| } | ||||
| 
 | ||||
| <INITIAL>{WS} { | ||||
| } | ||||
| 
 | ||||
| <INITIAL>"," { | ||||
|   return(COMMA); | ||||
| } | ||||
| 
 | ||||
| <INITIAL>{MIN} { | ||||
|   return(MINIMISE); | ||||
| } | ||||
| 
 | ||||
| <INITIAL>{MAX} { | ||||
|   return(MAXIMISE); | ||||
| } | ||||
| 
 | ||||
| <INITIAL>{INNM} { | ||||
|   f = atof((char *)yytext); | ||||
|   return(INTCONS); | ||||
| } /* f contains the last float */ | ||||
| 
 | ||||
| <INITIAL>{NM} { | ||||
|   f = atof((char *)yytext); | ||||
|   return(CONS); | ||||
| } /* f contains the last float */ | ||||
| 
 | ||||
| <INITIAL>{INF} { | ||||
|   char *ptr; | ||||
| 
 | ||||
|   f = DEF_INFINITE; | ||||
|   Sign = 0; | ||||
|   ptr = (char *)yytext; | ||||
|   while (isspace(*ptr)) ptr++; | ||||
|   if(*ptr == '-') | ||||
|     Sign = 1; | ||||
|   return(INF); | ||||
| } /* f contains the last float */ | ||||
| 
 | ||||
| <INITIAL>{S_OP} { | ||||
|   Sign = 0; | ||||
|   for(x = 0; x < yyleng; x++) | ||||
|     if(yytext[x] == '-' || yytext[x] == '+') | ||||
|       Sign = (Sign == (yytext[x] == '+')); | ||||
|   return (SIGN); | ||||
|   /* Sign is TRUE if the sign-string | ||||
|      represents a '-'. Otherwise Sign | ||||
|      is FALSE */ | ||||
| } | ||||
| 
 | ||||
| <INITIAL>{INT} { | ||||
|   if((!Within_int_decl) && (!Within_sec_decl) && (!Within_sos_decl) && (!Within_free_decl)) { | ||||
|     Within_int_decl = 1; | ||||
|     Within_sos_decl1 = FALSE; | ||||
|   } | ||||
|   return(SEC_INT); | ||||
| } | ||||
| 
 | ||||
| <INITIAL>{BIN} { | ||||
|   if((!Within_int_decl) && (!Within_sec_decl) && (!Within_sos_decl) && (!Within_free_decl)) { | ||||
|     Within_int_decl = 2; | ||||
|     Within_sos_decl1 = FALSE; | ||||
|   } | ||||
|   return(SEC_BIN); | ||||
| } | ||||
| 
 | ||||
| <INITIAL>{SEC} { | ||||
|   if((!Within_int_decl) && (!Within_sec_decl) && (!Within_sos_decl) && (!Within_free_decl)) { | ||||
|     Within_sec_decl = TRUE; | ||||
|     Within_sos_decl1 = FALSE; | ||||
|   } | ||||
|   return(SEC_SEC); | ||||
| } | ||||
| 
 | ||||
| <INITIAL>{SOS} { | ||||
|   if(!Within_sos_decl) | ||||
|     SOStype0 = (short)atoi(((char *)yytext) + 3); | ||||
|   if((!Within_int_decl) && (!Within_sec_decl) && (!Within_sos_decl) && (!Within_free_decl)) | ||||
|     Within_sos_decl = TRUE; | ||||
|   return(SEC_SOS); | ||||
| } | ||||
| 
 | ||||
| <INITIAL>{SOSD} { | ||||
|   FREE(Last_var); | ||||
|   Last_var = strdup((char *)yytext); | ||||
|   Last_var[strlen(Last_var) - 2] = 0; | ||||
|   return(SOSDESCR); | ||||
| } | ||||
| 
 | ||||
| <INITIAL>{FREE} { | ||||
|   if((!Within_int_decl) && (!Within_sec_decl) && (!Within_sos_decl) && (!Within_free_decl)) { | ||||
|     Within_free_decl = TRUE; | ||||
|     Within_sos_decl1 = FALSE; | ||||
|   } | ||||
|   return(SEC_FREE); | ||||
| } | ||||
| 
 | ||||
| <INITIAL>{LBL} { | ||||
|   FREE(Last_var); | ||||
|   Last_var = strdup((char *)yytext); | ||||
|   Last_var[strlen(Last_var) - 1] = 0; | ||||
|   return(VARIABLECOLON); | ||||
| } | ||||
| 
 | ||||
| <INITIAL>{VR} { | ||||
|   FREE(Last_var); | ||||
|   Last_var = strdup((char *)yytext); | ||||
|   return(VAR); | ||||
| } | ||||
| 
 | ||||
| <INITIAL>":" { | ||||
|   return (COLON); | ||||
| } | ||||
| 
 | ||||
| <INITIAL>"*" { | ||||
|   return(AR_M_OP); | ||||
| } | ||||
| 
 | ||||
| <INITIAL>{OPLE} { | ||||
|   return(RE_OPLE); | ||||
| } | ||||
| 
 | ||||
| <INITIAL>{OPGE} { | ||||
|   return(RE_OPGE); | ||||
| } | ||||
| 
 | ||||
| <INITIAL>";" { | ||||
|   Within_int_decl = Within_sec_decl = Within_sos_decl = Within_free_decl = FALSE; | ||||
|   check_int_sec_sos_free_decl(Within_int_decl, Within_sec_decl, Within_sos_decl, Within_free_decl); | ||||
|   return(END_C); | ||||
| } | ||||
| 
 | ||||
| <INITIAL>. { | ||||
|   report(NULL, CRITICAL, "LEX ERROR : %s lineno %d\n", yytext, yylineno); | ||||
|   return(UNDEFINED); | ||||
| } | ||||
| 
 | ||||
| %% | ||||
|  | @ -1,723 +0,0 @@ | |||
| /* ========================================================================= */ | ||||
| /* NAME  : lp_rlp.y                                                          */ | ||||
| /* ========================================================================= */ | ||||
| 
 | ||||
| 
 | ||||
| %token VAR CONS INTCONS VARIABLECOLON INF SEC_INT SEC_BIN SEC_SEC SEC_SOS SOSDESCR SEC_FREE SIGN AR_M_OP RE_OPLE RE_OPGE END_C COMMA COLON MINIMISE MAXIMISE UNDEFINED | ||||
| 
 | ||||
| 
 | ||||
| %{ | ||||
| #include <string.h> | ||||
| #include <ctype.h> | ||||
| 
 | ||||
| #include "lpkit.h" | ||||
| #include "yacc_read.h" | ||||
| 
 | ||||
| #ifdef FORTIFY | ||||
| # include "lp_fortify.h" | ||||
| #endif | ||||
| 
 | ||||
| static int HadVar0, HadVar1, HadVar2, HasAR_M_OP, do_add_row, Had_lineair_sum0, HadSign; | ||||
| static char *Last_var = NULL, *Last_var0 = NULL; | ||||
| static REAL f, f0, f1; | ||||
| static int x; | ||||
| static int state, state0; | ||||
| static int Sign; | ||||
| static int isign, isign0;      /* internal_sign variable to make sure nothing goes wrong */ | ||||
|                 /* with lookahead */ | ||||
| static int make_neg;   /* is true after the relational operator is seen in order */ | ||||
|                 /* to remember if lin_term stands before or after re_op */ | ||||
| static int Within_int_decl = FALSE; /* TRUE when we are within an int declaration */ | ||||
| static int Within_bin_decl = FALSE; /* TRUE when we are within an bin declaration */ | ||||
| static int Within_sec_decl = FALSE; /* TRUE when we are within a sec declaration */ | ||||
| static int Within_sos_decl = FALSE; /* TRUE when we are within a sos declaration */ | ||||
| static int Within_sos_decl1; | ||||
| static int Within_free_decl = FALSE; /* TRUE when we are within a free declaration */ | ||||
| static short SOStype0; /* SOS type */ | ||||
| static short SOStype; /* SOS type */ | ||||
| static int SOSNr; | ||||
| static int SOSweight = 0; /* SOS weight */ | ||||
| 
 | ||||
| static int HadConstraint; | ||||
| static int HadVar; | ||||
| static int Had_lineair_sum; | ||||
| 
 | ||||
| extern FILE *yyin; | ||||
| 
 | ||||
| #define YY_FATAL_ERROR lex_fatal_error | ||||
| 
 | ||||
| /* let's please C++ users */ | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| static int wrap(void) | ||||
| { | ||||
|   return(1); | ||||
| } | ||||
| 
 | ||||
| static int __WINAPI lp_input_yyin(void *fpin, char *buf, int max_size) | ||||
| { | ||||
|   int result; | ||||
| 
 | ||||
|   if ( (result = fread( (char*)buf, sizeof(char), max_size, (FILE *) fpin)) < 0) | ||||
|     YY_FATAL_ERROR( "read() in flex scanner failed"); | ||||
| 
 | ||||
|   return(result); | ||||
| } | ||||
| 
 | ||||
| static read_modeldata_func *lp_input; | ||||
| 
 | ||||
| #undef YY_INPUT | ||||
| #define YY_INPUT(buf,result,max_size) result = lp_input((void *) yyin, buf, max_size); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| }; | ||||
| #endif | ||||
| 
 | ||||
| #define yywrap wrap | ||||
| #define yyerror read_error | ||||
| 
 | ||||
| #include "lp_rlp.h" | ||||
| 
 | ||||
| %} | ||||
| 
 | ||||
| %start inputfile | ||||
| %% | ||||
| 
 | ||||
| EMPTY: /* EMPTY */ | ||||
|                 ; | ||||
| 
 | ||||
| inputfile       : | ||||
| { | ||||
|   isign = 0; | ||||
|   make_neg = 0; | ||||
|   Sign = 0; | ||||
|   HadConstraint = FALSE; | ||||
|   HadVar = HadVar0 = FALSE; | ||||
| } | ||||
|                   objective_function | ||||
|                   constraints | ||||
|                   int_bin_sec_sos_free_declarations | ||||
|                 ; | ||||
| 
 | ||||
| /* start objective_function */ | ||||
| 
 | ||||
| /* | ||||
| 
 | ||||
|  objective_function: MAXIMISE real_of | MINIMISE real_of | real_of; | ||||
|  real_of:            lineair_sum END_C; | ||||
|  lineair_sum:        EMPTY | x_lineair_sum; | ||||
| 
 | ||||
| */ | ||||
| 
 | ||||
| objective_function:   MAXIMISE real_of | ||||
| { | ||||
|   set_obj_dir(TRUE); | ||||
| } | ||||
|                     | MINIMISE real_of | ||||
| { | ||||
|   set_obj_dir(FALSE); | ||||
| } | ||||
|                     | real_of | ||||
|                 ; | ||||
| 
 | ||||
| real_of:            lineair_sum | ||||
|                     END_C | ||||
| { | ||||
|   add_row(); | ||||
|   HadConstraint = FALSE; | ||||
|   HadVar = HadVar0 = FALSE; | ||||
|   isign = 0; | ||||
|   make_neg = 0; | ||||
| } | ||||
|                 ; | ||||
| 
 | ||||
| lineair_sum:          EMPTY | ||||
|                     | x_lineair_sum | ||||
|                 ; | ||||
| 
 | ||||
| /* end objective_function */ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /* start constraints */ | ||||
| 
 | ||||
| /* | ||||
| 
 | ||||
|  constraints:        EMPTY | x_constraints; | ||||
|  x_constraints:      constraint | x_constraints constraint; | ||||
|  constraint:         real_constraint | VARIABLECOLON real_constraint; | ||||
|  real_constraint:    x_lineair_sum2 RE_OP x_lineair_sum3 optionalrange END_C; | ||||
|  optionalrange:      EMPTY | RE_OP cons_term RHS_STORE; | ||||
|  RE_OP:              RE_OPLE | RE_OPGE; | ||||
|  cons_term:          x_SIGN REALCONS | INF; | ||||
|  x_lineair_sum2:     EMPTY | x_lineair_sum3; | ||||
|  x_lineair_sum3:     x_lineair_sum | INF RHS_STORE; | ||||
|  x_lineair_sum:      x_lineair_sum1; | ||||
|  x_lineair_sum1:     x_lineair_term | x_lineair_sum1 x_lineair_term; | ||||
|  x_lineair_term:     x_SIGN x_lineair_term1; | ||||
|  x_lineair_term1:    REALCONS | optional_AR_M_OP VAR; | ||||
|  x_SIGN:             EMPTY | SIGN; | ||||
|  REALCONS:           INTCONS | CONS; | ||||
|  optional_AR_M_OP:   EMPTY | AR_M_OP; | ||||
| 
 | ||||
| */ | ||||
| 
 | ||||
| constraints:      EMPTY | ||||
|                 | x_constraints | ||||
|                 ; | ||||
| 
 | ||||
| x_constraints   : constraint | ||||
|                 | x_constraints | ||||
|                   constraint | ||||
|                 ; | ||||
| 
 | ||||
| constraint      : real_constraint | ||||
|                 | VARIABLECOLON | ||||
| { | ||||
|   if(!add_constraint_name(Last_var)) | ||||
|     YYABORT; | ||||
|   HadConstraint = TRUE; | ||||
| } | ||||
|                   real_constraint | ||||
|                 ; | ||||
| 
 | ||||
| real_constraint : x_lineair_sum2 | ||||
| { | ||||
|   HadVar1 = HadVar0; | ||||
|   HadVar0 = FALSE; | ||||
| } | ||||
|                   RE_OP | ||||
| { | ||||
|   if(!store_re_op((char *) yytext, HadConstraint, HadVar, Had_lineair_sum)) | ||||
|     YYABORT; | ||||
|   make_neg = 1; | ||||
|   f1 = 0; | ||||
| } | ||||
|                   x_lineair_sum3 | ||||
| { | ||||
|   Had_lineair_sum0 = Had_lineair_sum; | ||||
|   Had_lineair_sum = TRUE; | ||||
|   HadVar2 = HadVar0; | ||||
|   HadVar0 = FALSE; | ||||
|   do_add_row = FALSE; | ||||
|   if(HadConstraint && !HadVar ) { | ||||
|     /* it is a range */ | ||||
|     /* already handled */ | ||||
|   } | ||||
|   else if(!HadConstraint && HadVar) { | ||||
|     /* it is a bound */ | ||||
| 
 | ||||
|     if(!store_bounds(TRUE)) | ||||
|       YYABORT; | ||||
|   } | ||||
|   else { | ||||
|     /* it is a row restriction */ | ||||
|     if(HadConstraint && HadVar) | ||||
|       store_re_op("", HadConstraint, HadVar, Had_lineair_sum); /* makes sure that data stored in temporary buffers is treated correctly */ | ||||
|     do_add_row = TRUE; | ||||
|   } | ||||
| } | ||||
|                   optionalrange | ||||
|                   END_C | ||||
| { | ||||
|   if((!HadVar) && (!HadConstraint)) { | ||||
|     yyerror("parse error"); | ||||
|     YYABORT; | ||||
|   } | ||||
|   if(do_add_row) | ||||
|     add_row(); | ||||
|   HadConstraint = FALSE; | ||||
|   HadVar = HadVar0 = FALSE; | ||||
|   isign = 0; | ||||
|   make_neg = 0; | ||||
|   null_tmp_store(TRUE); | ||||
| } | ||||
|                 ; | ||||
| 
 | ||||
| optionalrange:    EMPTY | ||||
| { | ||||
|   if((!HadVar1) && (Had_lineair_sum0)) | ||||
|     if(!negate_constraint()) | ||||
|       YYABORT; | ||||
| } | ||||
|                 | RE_OP | ||||
| { | ||||
|   make_neg = 0; | ||||
|   isign = 0; | ||||
|   if(HadConstraint) | ||||
|     HadVar = Had_lineair_sum = FALSE; | ||||
|   HadVar0 = FALSE; | ||||
|   if(!store_re_op((char *) ((*yytext == '<') ? ">" : (*yytext == '>') ? "<" : yytext), HadConstraint, HadVar, Had_lineair_sum)) | ||||
|     YYABORT; | ||||
| } | ||||
|                   cons_term | ||||
| { | ||||
|   f -= f1; | ||||
| } | ||||
|                   RHS_STORE | ||||
| { | ||||
|   if((HadVar1) || (!HadVar2) || (HadVar0)) { | ||||
|     yyerror("parse error"); | ||||
|     YYABORT; | ||||
|   } | ||||
| 
 | ||||
|   if(HadConstraint && !HadVar ) { | ||||
|     /* it is a range */ | ||||
|     /* already handled */ | ||||
|     if(!negate_constraint()) | ||||
|       YYABORT; | ||||
|   } | ||||
|   else if(!HadConstraint && HadVar) { | ||||
|     /* it is a bound */ | ||||
| 
 | ||||
|     if(!store_bounds(TRUE)) | ||||
|       YYABORT; | ||||
|   } | ||||
| } | ||||
|                 ; | ||||
| 
 | ||||
| x_lineair_sum2:   EMPTY | ||||
| { | ||||
|   /* to allow a range */ | ||||
|   /* constraint: < max */ | ||||
|   if(!HadConstraint) { | ||||
|     yyerror("parse error"); | ||||
|     YYABORT; | ||||
|   } | ||||
|   Had_lineair_sum = FALSE; | ||||
| } | ||||
|                 | x_lineair_sum3 | ||||
| { | ||||
|   Had_lineair_sum = TRUE; | ||||
| } | ||||
|                 ; | ||||
| 
 | ||||
| x_lineair_sum3  :  x_lineair_sum | ||||
|                 | INF | ||||
| { | ||||
|   isign = Sign; | ||||
| } | ||||
|                   RHS_STORE | ||||
|                 ; | ||||
| 
 | ||||
| x_lineair_sum: | ||||
| { | ||||
|   state = state0 = 0; | ||||
| } | ||||
|                 x_lineair_sum1 | ||||
| { | ||||
|   if (state == 1) { | ||||
|     /* RHS_STORE */ | ||||
|     if (    (isign0 || !make_neg) | ||||
|         && !(isign0 && !make_neg)) /* but not both! */ | ||||
|       f0 = -f0; | ||||
|     if(make_neg) | ||||
|       f1 += f0; | ||||
|     if(!rhs_store(f0, HadConstraint, HadVar, Had_lineair_sum)) | ||||
|       YYABORT; | ||||
|   } | ||||
| } | ||||
|                 ; | ||||
| 
 | ||||
| x_lineair_sum1  : x_lineair_term | ||||
|                 | x_lineair_sum1 | ||||
|                   x_lineair_term | ||||
|                 ; | ||||
| 
 | ||||
| x_lineair_term  : x_SIGN | ||||
|                   x_lineair_term1 | ||||
| { | ||||
|   if ((HadSign || state == 1) && (state0 == 1)) { | ||||
|     /* RHS_STORE */ | ||||
|     if (    (isign0 || !make_neg) | ||||
|         && !(isign0 && !make_neg)) /* but not both! */ | ||||
|       f0 = -f0; | ||||
|     if(make_neg) | ||||
|       f1 += f0; | ||||
|     if(!rhs_store(f0, HadConstraint, HadVar, Had_lineair_sum)) | ||||
|       YYABORT; | ||||
|   } | ||||
|   if (state == 1) { | ||||
|     f0 = f; | ||||
|     isign0 = isign; | ||||
|   } | ||||
|   if (state == 2) { | ||||
|     if((HadSign) || (state0 != 1)) { | ||||
|      isign0 = isign; | ||||
|      f0 = 1.0; | ||||
|     } | ||||
|     if (    (isign0 || make_neg) | ||||
|         && !(isign0 && make_neg)) /* but not both! */ | ||||
|       f0 = -f0; | ||||
|     if(!var_store(Last_var, f0, HadConstraint, HadVar, Had_lineair_sum)) { | ||||
|       yyerror("var_store failed"); | ||||
|       YYABORT; | ||||
|     } | ||||
|     HadConstraint |= HadVar; | ||||
|     HadVar = HadVar0 = TRUE; | ||||
|   } | ||||
|   state0 = state; | ||||
| } | ||||
|                 ; | ||||
| 
 | ||||
| x_lineair_term1 : REALCONS | ||||
| { | ||||
|   state = 1; | ||||
| } | ||||
|                 | optional_AR_M_OP | ||||
| { | ||||
|   if ((HasAR_M_OP) && (state != 1)) { | ||||
|     yyerror("parse error"); | ||||
|     YYABORT; | ||||
|   } | ||||
| } | ||||
|                   VAR | ||||
| { | ||||
|   state = 2; | ||||
| } | ||||
|                 ; | ||||
| 
 | ||||
| RE_OP: RE_OPLE | RE_OPGE | ||||
|                 ; | ||||
| 
 | ||||
| cons_term:        x_SIGN | ||||
|                   REALCONS | ||||
|                 | INF | ||||
| { | ||||
|   isign = Sign; | ||||
| } | ||||
|                 ; | ||||
| 
 | ||||
| /* end constraints */ | ||||
| 
 | ||||
| 
 | ||||
| /* start common for objective & constraints */ | ||||
| 
 | ||||
| REALCONS: INTCONS | CONS | ||||
|                 ; | ||||
| 
 | ||||
| x_SIGN:           EMPTY | ||||
| { | ||||
|   isign = 0; | ||||
|   HadSign = FALSE; | ||||
| } | ||||
|                 | SIGN | ||||
| { | ||||
|   isign = Sign; | ||||
|   HadSign = TRUE; | ||||
| } | ||||
|                 ; | ||||
| 
 | ||||
| optional_AR_M_OP: EMPTY | ||||
| { | ||||
|   HasAR_M_OP = FALSE; | ||||
| } | ||||
|                 | AR_M_OP | ||||
| { | ||||
|   HasAR_M_OP = TRUE; | ||||
| } | ||||
|                 ; | ||||
| 
 | ||||
| RHS_STORE:        EMPTY | ||||
| { | ||||
|   if (    (isign || !make_neg) | ||||
|       && !(isign && !make_neg)) /* but not both! */ | ||||
|     f = -f; | ||||
|   if(!rhs_store(f, HadConstraint, HadVar, Had_lineair_sum)) | ||||
|     YYABORT; | ||||
|   isign = 0; | ||||
| } | ||||
|                 ; | ||||
| 
 | ||||
| /* end common for objective & constraints */ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /* start int_bin_sec_sos_free_declarations */ | ||||
| 
 | ||||
| int_bin_sec_sos_free_declarations: | ||||
|                   EMPTY | ||||
|                 | real_int_bin_sec_sos_free_decls | ||||
|                 ; | ||||
| 
 | ||||
| real_int_bin_sec_sos_free_decls: int_bin_sec_sos_free_declaration | ||||
|                 | real_int_bin_sec_sos_free_decls int_bin_sec_sos_free_declaration | ||||
|                 ; | ||||
| 
 | ||||
| SEC_INT_BIN_SEC_SOS_FREE: SEC_INT | SEC_BIN | SEC_SEC | SEC_SOS | SEC_FREE | ||||
|                 ; | ||||
| 
 | ||||
| int_bin_sec_sos_free_declaration: | ||||
|                   SEC_INT_BIN_SEC_SOS_FREE | ||||
| { | ||||
|   Within_sos_decl1 = Within_sos_decl; | ||||
| } | ||||
|                   x_int_bin_sec_sos_free_declaration | ||||
|                 ; | ||||
| 
 | ||||
| xx_int_bin_sec_sos_free_declaration: | ||||
| { | ||||
|   if((!Within_int_decl) && (!Within_sec_decl) && (!Within_sos_decl1) && (!Within_free_decl)) { | ||||
|     yyerror("parse error"); | ||||
|     YYABORT; | ||||
|   } | ||||
|   SOStype = SOStype0; | ||||
|   check_int_sec_sos_free_decl(Within_int_decl, Within_sec_decl, Within_sos_decl1 = (Within_sos_decl1 ? 1 : 0), Within_free_decl); | ||||
| } | ||||
|                   optionalsos | ||||
|                   vars | ||||
|                   optionalsostype | ||||
|                   END_C | ||||
| { | ||||
|   if((Within_sos_decl1) && (SOStype == 0)) | ||||
|   { | ||||
|     yyerror("Unsupported SOS type (0)"); | ||||
|     YYABORT; | ||||
|   } | ||||
| } | ||||
|                 ; | ||||
| 
 | ||||
| x_int_bin_sec_sos_free_declaration: | ||||
|                   xx_int_bin_sec_sos_free_declaration | ||||
|                 | x_int_bin_sec_sos_free_declaration xx_int_bin_sec_sos_free_declaration | ||||
|                 ; | ||||
| 
 | ||||
| optionalsos:      EMPTY | ||||
|                 | SOSDESCR | ||||
| { | ||||
|   FREE(Last_var0); | ||||
|   Last_var0 = strdup(Last_var); | ||||
| } | ||||
|                   sosdescr | ||||
|                 ; | ||||
| 
 | ||||
| optionalsostype:  EMPTY | ||||
| { | ||||
|   if(Within_sos_decl1) { | ||||
|     set_sos_type(SOStype); | ||||
|     set_sos_weight((double) SOSweight, 1); | ||||
|   } | ||||
| } | ||||
|                 | RE_OPLE | ||||
|                   INTCONS | ||||
| { | ||||
|   if((Within_sos_decl1) && (!SOStype)) | ||||
|   { | ||||
|     set_sos_type(SOStype = (short) (f + .1)); | ||||
|   } | ||||
|   else | ||||
|   { | ||||
|     yyerror("SOS type not expected"); | ||||
|     YYABORT; | ||||
|   } | ||||
| } | ||||
|                 optionalSOSweight | ||||
|                 ; | ||||
| 
 | ||||
| optionalSOSweight:EMPTY | ||||
| { | ||||
|   set_sos_weight((double) SOSweight, 1); | ||||
| } | ||||
|                 | COLON | ||||
|                   INTCONS | ||||
| { | ||||
|   set_sos_weight(f, 1); | ||||
| } | ||||
|                 ; | ||||
| 
 | ||||
| vars:             EMPTY | ||||
|                 | x_vars | ||||
|                 ; | ||||
| 
 | ||||
| x_vars          : onevarwithoptionalweight | ||||
|                 | x_vars | ||||
|                   optionalcomma | ||||
|                   onevarwithoptionalweight | ||||
|                 ; | ||||
| 
 | ||||
| optionalcomma:    EMPTY | ||||
|                 | COMMA | ||||
|                 ; | ||||
| 
 | ||||
| variable:         EMPTY | ||||
| { | ||||
|   if(Within_sos_decl1 == 1) | ||||
|   { | ||||
|     char buf[16]; | ||||
| 
 | ||||
|     SOSweight++; | ||||
|     sprintf(buf, "SOS%d", SOSweight); | ||||
|     storevarandweight(buf); | ||||
| 
 | ||||
|     check_int_sec_sos_free_decl(Within_int_decl, Within_sec_decl, 2, Within_free_decl); | ||||
|     Within_sos_decl1 = 2; | ||||
|     SOSNr = 0; | ||||
|   } | ||||
| 
 | ||||
|   storevarandweight(Last_var); | ||||
| 
 | ||||
|   if(Within_sos_decl1 == 2) | ||||
|   { | ||||
|     SOSNr++; | ||||
|     set_sos_weight((double) SOSNr, 2); | ||||
|   } | ||||
| } | ||||
|                 ; | ||||
| 
 | ||||
| variablecolon: | ||||
| { | ||||
|   if(!Within_sos_decl1) { | ||||
|     yyerror("parse error"); | ||||
|     YYABORT; | ||||
|   } | ||||
|   if(Within_sos_decl1 == 1) { | ||||
|     FREE(Last_var0); | ||||
|     Last_var0 = strdup(Last_var); | ||||
|   } | ||||
|   if(Within_sos_decl1 == 2) | ||||
|   { | ||||
|     storevarandweight(Last_var); | ||||
|     SOSNr++; | ||||
|     set_sos_weight((double) SOSNr, 2); | ||||
|   } | ||||
| } | ||||
|                 ; | ||||
| 
 | ||||
| sosweight:        EMPTY | ||||
| { | ||||
|   if(Within_sos_decl1 == 1) | ||||
|   { | ||||
|     char buf[16]; | ||||
| 
 | ||||
|     SOSweight++; | ||||
|     sprintf(buf, "SOS%d", SOSweight); | ||||
|     storevarandweight(buf); | ||||
| 
 | ||||
|     check_int_sec_sos_free_decl(Within_int_decl, Within_sec_decl, 2, Within_free_decl); | ||||
|     Within_sos_decl1 = 2; | ||||
|     SOSNr = 0; | ||||
| 
 | ||||
|     storevarandweight(Last_var0); | ||||
|     SOSNr++; | ||||
|   } | ||||
| 
 | ||||
|   set_sos_weight(f, 2); | ||||
| } | ||||
|                 ; | ||||
| 
 | ||||
| sosdescr:         EMPTY | ||||
| { /* SOS name */ | ||||
|   if(Within_sos_decl1 == 1) | ||||
|   { | ||||
|     storevarandweight(Last_var0); | ||||
|     set_sos_type(SOStype); | ||||
|     check_int_sec_sos_free_decl(Within_int_decl, Within_sec_decl, 2, Within_free_decl); | ||||
|     Within_sos_decl1 = 2; | ||||
|     SOSNr = 0; | ||||
|     SOSweight++; | ||||
|   } | ||||
| } | ||||
|                 ; | ||||
| 
 | ||||
| onevarwithoptionalweight: | ||||
|                   VAR | ||||
|                   variable | ||||
|                 | VARIABLECOLON | ||||
|                   variablecolon | ||||
|                   INTCONSorVARIABLE | ||||
|                 ; | ||||
| 
 | ||||
| INTCONSorVARIABLE:REALCONS /* INTCONS */ | ||||
|                   sosweight | ||||
|                 | sosdescr | ||||
|                   x_onevarwithoptionalweight | ||||
|                 ; | ||||
| 
 | ||||
| x_onevarwithoptionalweight: | ||||
|                   VAR | ||||
|                   variable | ||||
|                 | VARIABLECOLON | ||||
|                   variablecolon | ||||
|                   REALCONS /* INTCONS */ | ||||
|                   sosweight | ||||
|                 ; | ||||
| 
 | ||||
| /* end int_bin_sec_sos_free_declarations */ | ||||
| 
 | ||||
| %% | ||||
| 
 | ||||
| static void yy_delete_allocated_memory(void) | ||||
| { | ||||
|   /* free memory allocated by flex. Otherwise some memory is not freed. | ||||
|      This is a bit tricky. There is not much documentation about this, but a lot of | ||||
|      reports of memory that keeps allocated */ | ||||
| 
 | ||||
|   /* If you get errors on this function call, just comment it. This will only result | ||||
|      in some memory that is not being freed. */ | ||||
| 
 | ||||
| # if defined YY_CURRENT_BUFFER | ||||
|     /* flex defines the macro YY_CURRENT_BUFFER, so you should only get here if lp_rlp.h is | ||||
|        generated by flex */ | ||||
|     /* lex doesn't define this macro and thus should not come here, but lex doesn't has | ||||
|        this memory leak also ...*/ | ||||
| 
 | ||||
|     yy_delete_buffer(YY_CURRENT_BUFFER); /* comment this line if you have problems with it */ | ||||
|     yy_init = 1; /* make sure that the next time memory is allocated again */ | ||||
|     yy_start = 0; | ||||
| # endif | ||||
| 
 | ||||
|   FREE(Last_var); | ||||
|   FREE(Last_var0); | ||||
| } | ||||
| 
 | ||||
| static int parse(void) | ||||
| { | ||||
|   return(yyparse()); | ||||
| } | ||||
| 
 | ||||
| lprec *read_lp1(lprec *lp, void *userhandle, read_modeldata_func read_modeldata, int verbose, char *lp_name) | ||||
| { | ||||
|   yyin = (FILE *) userhandle; | ||||
|   yyout = NULL; | ||||
|   yylineno = 1; | ||||
|   lp_input = read_modeldata; | ||||
|   return(yacc_read(lp, verbose, lp_name, &yylineno, parse, yy_delete_allocated_memory)); | ||||
| } | ||||
| 
 | ||||
| lprec * __WINAPI read_lp(FILE *filename, int verbose, char *lp_name) | ||||
| { | ||||
|   return(read_lp1(NULL, filename, lp_input_yyin, verbose, lp_name)); | ||||
| } | ||||
| 
 | ||||
| lprec * __WINAPI read_lpex(void *userhandle, read_modeldata_func read_modeldata, int verbose, char *lp_name) | ||||
| { | ||||
|   return(read_lp1(NULL, userhandle, read_modeldata, verbose, lp_name)); | ||||
| } | ||||
| 
 | ||||
| lprec *read_LP1(lprec *lp, char *filename, int verbose, char *lp_name) | ||||
| { | ||||
|   FILE *fpin; | ||||
| 
 | ||||
|   if((fpin = fopen(filename, "r")) != NULL) { | ||||
|     lp = read_lp1(lp, fpin, lp_input_yyin, verbose, lp_name); | ||||
|     fclose(fpin); | ||||
|   } | ||||
|   else | ||||
|     lp = NULL; | ||||
|   return(lp); | ||||
| } | ||||
| 
 | ||||
| lprec * __WINAPI read_LP(char *filename, int verbose, char *lp_name) | ||||
| { | ||||
|   return(read_LP1(NULL, filename, verbose, lp_name)); | ||||
| } | ||||
| 
 | ||||
| MYBOOL __WINAPI LP_readhandle(lprec **lp, FILE *filename, int verbose, char *lp_name) | ||||
| { | ||||
|   if(lp != NULL) | ||||
|     *lp = read_lp1(*lp, filename, lp_input_yyin, verbose, lp_name); | ||||
| 
 | ||||
|   return((lp != NULL) && (*lp != NULL)); | ||||
| } | ||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue